当RDS PostgreSQL容灾搭建的可行性评估报告状态为失败时,您可以单击评估任务列表中对应任务的操作列的查看报告,查看详细内容。本文介绍RDS PostgreSQL容灾搭建可行性评估报告的内容详情、常见报错以及解决方案。
检查项
容灾搭建可行性评估报告包含以下内容。
源实例:需要进行容灾的实例。
目标实例:灾备实例,即RDS PostgreSQL。
检查项 | 说明 | 报错时解决方案 |
Check rds empty | 检查目标实例是否是空库,防止数据覆盖。 | |
Check source connectivity |
| |
Check major version | 检查源实例和目标实例的大版本是否一致。 | |
Check glibc version | 检查源实例和目标实例的glibc版本是否兼容。 说明 该检查项不通过时, 触发warning级别的报错。 | |
Check disk size | 检查目标实例磁盘空间是否充足。 当前要求源实例数据量不超过目标实例磁盘容量的80%。 | |
Check wal keep size | 检查源实例 源实例
| |
Check spec param | 检查目标实例的规格参数 | |
Check rds user | 检查源实例是否存在名为 说明 若源实例为阿里云RDS PostgreSQL实例,则无需进行检查。 | |
Check extensions | 检查插件兼容性。检查源实例:
| |
Check logical replication slot | 检查逻辑复制槽。 说明 该检查项不通过时, 触发warning级别的报错。 | |
Check local cross db access | 检查本地跨库访问。检查源实例是否使用了 说明 该检查项不通过时, 触发warning级别的报错。 | |
Check Postgres system catalogs | 检查PostgreSQL的系统catalogs:
| |
Check reserved role permission | 检查预留角色权限。 |
解决方案
Check rds empty(检查目标实例是否是空库)
检查内容
检查目标实例是否存在非空的数据库,防止目标实例原有数据被覆盖。
常见报错
error:xxx not empty, check if any table exists
说明
目标实例中存在包含数据的数据库。
解决方案
清空目标实例中包含数据的数据库,或直接删除包含数据的数据库,但要保留数据库template0、template1和postgres。
Check source connectivity(检查网络连通性和同步账号权限)
检查内容1
检查源实例IP是否可以连通。
常见报错
error:xxx.xxx.xxx.xxx is unapproachable
说明
目标实例网络环境下,源实例的IP或域名无法连通。
解决方案
配置网络环境,查看网络配置是否存在未完成的代办事项。
检查内容2
检查源实例端口是否可以连通。
常见报错
error:5432 is unapproachable
说明
目标实例网络环境下,源实例的端口无法连通。
解决方案
修改源实例的配置文件postgresql.conf,设置
listen_address = '*'
,并重启源实例。设置源实例防火墙,开放指定端口。
检查内容3
检查源实例PostgreSQL数据库服务是否可以连接。
常见报错
error:cannot connect to source database by replicatoraccount:replicatorPassword
说明
同步账号的密码不正确。同步账号指的是源实例和目标实例之间数据同步使用的账号。
源实例配置文件pg_hba.conf配置错误。
解决方案
确认是否可以使用同步账号连接到源实例。无法连接时,尝试更新密码。假设同步账号是replicatoraccount,示例如下:
ALTER ROLE replicatoraccount WITH PASSWORD 'replicatorPassword';
修改源实例的pg_hba.conf配置文件,添加放开同步账号的条目。假设同步账号是replicatoraccount,示例如下:
host all replicatoraccount <目标实例VPC网段> md5
检查内容4
检查同步账号是否具有REPLICATION权限,以完成数据同步等操作。
常见报错
error:replicatoraccount has no replication privilege
说明
同步账号没有REPLICATION权限。
源实例配置文件pg_hba.conf配置不正确。
解决方案
为同步账号添加REPLICATION权限。假设同步账号是replicatoraccount,示例如下:
ALTER ROLE replicatoraccount REPLICATION;
修改源实例的pg_hba.conf配置文件,添加条目允许同步账号发起replication连接。假设同步账号是replicatoraccount,示例如下:
host replication replicatoraccount <目标实例VPC网段> md5
检查内容5
检查同步账号是否具有CREATEROLE权限。
常见报错
error:replicatoraccount has no createrole privilege
说明
同步账号没有CREATEROLE权限。
解决方案
为同步账号添加CREATEROLE权限。假设同步账号是replicatoraccount,示例如下:
ALTER ROLE replicatoraccount CREATEROLE;
检查内容6
检查同步账号是否具备pg_monitor权限,以便查询pg_stat_replication和pg_stat_wal_receive等系统视图,从而获取数据同步状态。
常见报错
error: replicatoraccount should be a member of pg_monitor to monitor replication status
说明
同步账号没有pg_monitor权限。
解决方案
将同步账号添加到pg_monitor。假设同步账号是replicatoraccount,示例如下:
GRANT pg_monitor TO replicatoraccount
Check major version(检查大版本是否一致)
检查内容
检查源实例和目标实例的大版本是否一致。
常见报错
version mismatch, source version:15, current version:16
说明
源实例和目标实例的大版本不一致。
解决方案
使用与源实例大版本一致的RDS PostgreSQL实例作为目标实例。
Check glibc version(检查glibc版本兼容性)
检查内容
检查源实例和目标实例的glib 版本是否兼容。
常见报错
warning:source glibc version is not compatible with rds pg
说明
源实例所依赖的glibc版本与RDS PostgreSQL实例所依赖的glibc版本存在不兼容问题。glibc 2.28版本对UTF-8部分字符的排序规则进行了变更,在版本不兼容的情况下,数据的排序规则可能不同,因而存在排序结果不符合预期的风险。
解决方案
检查表排序。
BEGIN; CREATE TEMP TABLE testcollation (id VARCHAR(20) COLLATE "en_US.utf8") ON COMMIT DROP; INSERT INTO testcollation VALUES ('-1'), ('1'); SELECT id = '1' FROM testcollation ORDER BY id LIMIT 1; ROLLBACK;
返回结果:
true:结束,无风险。
false:进行下一步检查。
检查库Collation。
SELECT datname,datcollate FROM pg_database where datcollate NOT IN ('C', 'POSIX');
返回结果:
返回为空:结束,无风险。
返回非空:进行下一步检查。
在所有库下检查Collation不是
C
或者POSIX
的索引。WITH result AS ( WITH defcoll AS ( SELECT datcollate AS coll FROM pg_database WHERE datname = current_database() ) SELECT indrelid::regclass::text relname, indexrelid::regclass::text indexname, CASE WHEN c.collname = 'default' THEN defcoll.coll ELSE c.collname END AS collation FROM (SELECT indexrelid, indrelid, indcollation[i] coll FROM pg_index, generate_subscripts(indcollation, 1) g(i)) s JOIN pg_collation c ON coll=c.oid CROSS JOIN defcoll WHERE collprovider IN ('d', 'c') AND collname NOT IN ('C', 'POSIX') ) SELECT result.relname, result.indexname, result.collation FROM result WHERE result.collation NOT IN ('C', 'POSIX');
返回结果:
返回为空:结束,无风险。
返回非空:存在风险。
Check disk size(检查磁盘空间是否充足)
检查内容
检查目标实例磁盘空间是否充足.
常见报错
error:source_db_size > disk_size * 0.8
说明
源实例数据量已超过目标实例磁盘空间的80%,导致磁盘空间不足。
解决方案
使用以下命令估算源实例的数据量大小,单位为MB。.
SELECT sum(pg_database_size(datname))/1024/1024 AS size FROM pg_database;
计算目标实例需要多大的磁盘空间,进行扩容。详情请参见变更配置。
Check wal keep size(检查源实例wal_keep_size大小)
检查内容
检查源实例的wal_keep_size是否足够大,以避免目标实例所需的WAL日志被删除。
常见报错
wal_keep_size xxMB is too small. Try to set wal_keep_segments or wal_keep_size large enough ensure pg_basebackup success
说明
源实例内核参数wal_keep_size或wal_keep_segments设置过小,需要调整。
解决方案
如源实例大版本大于或等于13,则增大内核参数wal_keep_size的取值。
如源实例大版本小于13,增大内核参数wal_keep_segments的取值。
Check spec param(检查规格参数)
检查内容
检查目标实例的规格参数max_connections、max_prepared_transactions
等取值是否大于源实例。
常见报错
error:max_connections too large, value=xxx; max_prepared_transactions too large, value=xxx
说明
为了在源实例与目标实例之间建立主备复制关系,要求源实例的max_connections、max_prepared_transactions
等规格参数不得超过目标实例的相应值。
解决方案
减少源实例内核参数max_connections、max_prepared_transactions
的取值,并重启源实例。
Check rds user(检查源实例是否存在目标实例所需系统账号)
检查内容
检查源实例是否存在账号alicloud_rds_admin、aurora、replicator,这些账号会作为目标实例的系统账号。
常见报错
error:xxx will be reused in rds
说明
源实例存在的 alicloud_rds_admin、aurora、replicator等会作为目标实例的系统账号的账号。
解决方案
在源实例中删除报错提到的账号。
Check extensions(检查插件兼容性)
检查内容1
检查源实例是否存在目标实例不支持的插件。
常见报错
error:Check source supported extensions xxx not supported
说明
源实例存在目标实例不支持的插件。
解决方案
源实例删除不支持的插件。
检查内容2
检查源实例是否存在版本比目标实例支持的版本更高的插件。
常见报错
error:Check source extensions with higher version xxx
说明
源实例存在版本高于目标实例支持的插件。
解决方案
源实例安装插件的低版本,与目标实例支持的版本的一致。或直接删除不支持的插件。
检查内容3
检查源实例是否存在版本比目标实例支持的版本低的插件。
常见报错
warning:Check source extensions with lower version xxx
说明
源实例存在版本低于的目标实例支持的插件。
解决方案
无需处理,搭建容灾关系过程中将会自动升级插件版本。
Check logical replication slot(检查逻辑复制槽)
检查内容
检查源实例是否存在逻辑复制槽。
常见报错
warning:The logical replication slots: xxx will be lost on target instance
说明
源实例中存在的逻辑复制槽将不会同步至目标实例,因此在目标实例被提升为主库后,逻辑复制的下游将无法找到相应的逻辑复制槽进行消费。
解决方案
用户需明确理解,逻辑复制槽不会同步至目标实例的这一事实,以及由此可能引发的风险。
Check local cross db access(检查本地跨库访问)
检查内容
检查源实例是否使用了postgres_fdw或dblink等插件进行本地跨库访问。
常见报错
warning:Foreign servers for local cross-database access exist
说明
如果源实例存在本地跨库访问的行为,由于目标实例PostgreSQL服务在本地固定监听于5432端口,这与源实例服务在本地监听的端口可能不一致。端口的变化将导致目标实例在提升为主库后,原有的本地跨库访问失效。
解决方案
无需解决,但用户需明确源实例和目标实例服务的本地监听端口可能存在不一致的情况。如果存在本地跨库访问,用户在提升目标实例后需重新配置用于本地跨库访问端口。
Check Postgres system catalogs(检查PostgreSQL的系统catalogs)
检查内容1
检查源实例是否存在目标实例不支持的语言(pg_language)。
常见报错
error: disallowed language exist in databases [xxx, xxx], the languages allowed are [c, internal, sql, plpgsql, pltcl, plperl].
说明
RDS PostgreSQL仅支持C、internal、SQL、PL/pgSQL、PL/Tcl和PL/Perl等语言。源实例中存在的不支持的语言,无法在目标实例上使用。
解决办法
在源实例中删除不支持的语言。
检查内容2
检查源实例是否存在大对象(Large Object)。
常见报错
error: large object exist in databases [xxx, xxx].
说明
由于RDS PostgreSQL不支持大对象,因此源实例中存在的大对象无法在目标实例上使用。
解决办法
在源实例中删除已存在的大对象。
检查内容3
检查源实例是否已通过
ALTER DEFAULT PRIVILEGES ... GRANT ...
命令设置了默认权限。即检查源实例中是否存在系统表pg_catalog.pg_default_acl不为空的数据库。常见报错
error: default acl settings exist in databases [xxx, xxx].
说明
如果源实例在某个数据库下执行过
ALTER DEFAULT PRIVILEGES ... GRANT ...
语句,则该数据库下的系统表pg_catalog.pg_default_acl将非空。解决办法
需要先在源实例相应的数据库中,执行
ALTER DEFAULT PRIVILEGES ... REVOKE ...
语句,以确保所有数据库下的系统表pg_default_acl为空。在完成容灾搭建后,再重新执行ALTER DEFAULT PRIVILEGES ... GRANT ...
语句,以恢复原先的默认权限设置。检查内容4
检查源实例系统表pg_parameter_acl和pg_db_role_setting是否不为空。
常见报错
warning: Invalid system tables: [pg_parameter_acl, pg_db_role_setting], these system tables should be empty.
说明
系统表pg_parameter_acl记录用户对内核参数的访问权限,RDS PostgreSQL不支持用户对这些权限进行修改。系统表pg_db_role_setting记录了不同用户在各个数据库中的默认权限设置。
解决办法
在源实例中执行以下语句,清空系统表pg_parameter_acl和pg_db_role_setting:
DELETE FROM pg_parameter_acl; DELETE FROM pg_db_role_setting;
在完成容灾搭建后,需要在目标实例中重新配置不同用户在各个数据库下的默认权限。
Check reserved role permission(检查预留角色权限)
检查内容
检查源实例是否向某些账号授予了目标实例不允许的预留角色权限。
常见报错
error: some disallowed reserved roles [pg_write_server_files] are granted to user. you should revoke these roles from their members
说明
RDS PostgreSQL不支持账户拥有pg_write_server_files等预留角色的权限。如果源实例曾执行过GRANT pg_write_server_files TO "user";
等授权语句,则需要执行REVOKE
语句以收回这些权限。
解决办法
在源实例中,执行REVOKE
语句回收相应的权限,如REVOKE pg_write_server_files FROM "user";
。