前提条件:源库配置

  • 修改postgresql.conf文件
#逻辑级别日志
wal_level = logical
#设置日志保留个数,设置太少了,日志量太大了日志自动删除后,容易读不到日志
注:postgresql 13.0中,将wal_keep_segments重命名为wal_keep_size
wal_keep_segments = 10
#如果需要远程读日志,需要设置,至少为1,就接受1个读日志线程
max_wal_senders = 10

验证是否成功

select name,setting,category from pg_settings where name in ('wal_level','wal_keep_segments','max_wal_senders');
  • 查询数据库或者zcbus用户加密方式
    show password_encryption;
    select rolname,rolpassword from pg_authid where rolname='zcbus';
  • 如果远程读日志,需要设置读日志的权限,修改pg_hba.conf
host    replication     all             0.0.0.0/32            md5 #加密方式需要和添加的zcbus用户加密方式一致
  • 修改pg_hba.conf执行pg_ctl命令生效
pg_ctl reload -D 指定pg_hba.conf所在目录
示例:pg_ctl reload -D /opt/postgresql/data
  • 验证是否成功
select * from pg_hba_file_rules;

以下过程中,web页面不要点击注册按键,所有配置手工完成!

添加槽位号说明(如发布数据库未配置SLOT_NAME参数,则此步骤添加槽位号跳过)

1、创建槽位号
查看槽位号信息
  select * from pg_replication_slots;
2、创建槽位号信息,槽位名字:zcbus_slot_name
# PG系列创建槽位号
sql命令:
  添加:select pg_create_physical_replication_slot('zcbus_slot_name');
  删除:SELECT pg_drop_replication_slot('zcbus_slot_name');
系统命令:
  添加:pg_receivewal --create-slot --slot=zcbus_slot_name
  删除:pg_receivewal --drop-slot --slot=zcbus_slot_name
# OpenGaussDB创建槽位号
sql命令:
  添加:select pg_create_physical_replication_slot('zcbus_slot_name',false);
  删除:SELECT pg_drop_replication_slot('zcbus_slot_name');

3、配置页面槽位号信息
  切换POSTGRESQL日志操作
  旧版本:select pg_switch_xlog();
  新版本:select pg_switch_wal();
  ZCBUS发布配置增加SLOT_NAME参数,自动匹配指定槽位号进行日志读取。
4、监控日志即可

注:删除日志参考:
正常删除pg日志方式
1、检查可以删除wal的日志文件
83e44cfdd569:~/data$ pg_controldata -D /var/lib/postgresql/data/ |grep "REDO WAL file"
Latest checkpoint's REDO WAL file:    000000010000000100000067
2、删除日志文件操作
pg_archivecleanup /var/lib/postgresql/data/pg_wal/ 000000010000000100000067

配置说明

用postgres系统账号登录pg库,执行如下(数据库命令行执行):

create user zcbus with password  'zcbus';
grant connect on database db01 to zcbus;
create schema zcbus AUTHORIZATION zcbus;

切换到同步库下,创建ddl_event_tbl表与zcbus_func_ddl_command函数

create table zcbus.ddl_event_tbl (  
event text,
tag text, 
objid oid,
object_type text,  
schema_name text,  
object_identity text,
query text,
op_time timestamp default now()
);

检查ddl_event_tbl表是否创建:

select * from information_schema.tables where table_schema='zcbus' and table_type='BASE TABLE' and table_name='ddl_event_tbl';

alter table "zcbus"."ddl_event_tbl" REPLICA IDENTITY FULL;
create or replace function zcbus.zcbus_func_ddl_command() returns event_trigger as $$  
declare  
  v1 text;
  r record;
begin
  select query into v1 from pg_stat_activity where pid=pg_backend_pid();
  -- RAISE NOTICE 'ddl event:%, command:%', tg_event, tg_tag; 
  if TG_EVENT='ddl_command_end' then  
    SELECT * into r FROM pg_event_trigger_ddl_commands();
    if r.classid > 0 then
      insert into zcbus.ddl_event_tbl(event, tag, objid, object_type, schema_name, object_identity, query)  
        values(TG_EVENT, TG_TAG, r.objid, r.object_type, r.schema_name, r.object_identity, v1);
    end if;
  end if;
  if TG_EVENT='sql_drop' then
    if TG_TAG != 'ALTER TABLE' then
      SELECT * into r FROM pg_event_trigger_dropped_objects();
      insert into zcbus.ddl_event_tbl(event, tag, object_type, schema_name, object_identity, query)  
        values(TG_EVENT, TG_TAG, r.object_type, r.schema_name, r.object_identity, v1);
    end if;
  end if;
end;  
$$ language plpgsql strict;

检查function是否创建:

select a.*
FROM pg_catalog.pg_proc a
JOIN pg_catalog.pg_namespace b ON a.pronamespace = b.oid
WHERE a.proname = 'zcbus_func_ddl_command' and b.nspname='zcbus'

CREATE EVENT TRIGGER zcbus_et_ddl_command on ddl_command_end EXECUTE PROCEDURE zcbus.zcbus_func_ddl_command();
CREATE EVENT TRIGGER zcbus_et_ddl_drop on sql_drop EXECUTE PROCEDURE zcbus.zcbus_func_ddl_command();

检查EVENT TRIGGER是否创建:

select * from  pg_event_trigger  where evtname in ('zcbus_et_ddl_drop','zcbus_et_ddl_command')

grant select,trigger on table zcbus.ddl_event_tbl  to zcbus;
grant execute ON FUNCTION zcbus.zcbus_func_ddl_command to zcbus;
alter user zcbus REPLICATION;

**** 切换到db01库下执行

\c db01
grant select on all tables in schema public to zcbus;
grant execute on function pg_hba_file_rules to zcbus;

**** 添加新表,需要postgres账号开启表的补充日志模式(切换到同步库执行),并且要再次执行select权限

ALTER TABLE public.tb02 REPLICA IDENTITY FULL;
grant select on all tables in schema public to zcbus;
grant usage on schema public to zcbus;

**** 添加新表,根据schemaname.tablename,确认postgres账号开启表的补充日志模式状态开启成功:

select relreplident from pg_class c , pg_tables tab where tab.schemaname = 'schemaname' and c.relname='tablename';

查询结果说明:

d = 默认(主键)
n = 无
f = 所有列
i = 索引的indisreplident被设置或者默认
查询结果为f,则此表满足同步条件,上一步postgres账号开启表的补充日志模式成功

**** 回退方式:

drop owned by zcbus cascade;
drop user zcbus;

查看用户的表权限

select * from information_schema.table_privileges where grantee='zcbus';

查看usage权限表

select * from information_schema.usage_privileges where grantee='zcbus';

查看存储过程函数相关权限

select * from information_schema.routine_privileges where grantee='zcbus';

开启表REPLICA IDENTITY参数

开启REPLICA IDENTITY

\c database_name;
ALTER TABLE schema_name.table_name REPLICA IDENTITY FULL;

生成修改表sql语句参考

SELECT 'ALTER TABLE '||nspname||'.'||relname||' REPLICA IDENTITY FULL;' FROM pg_class c,pg_namespace n where relnamespace = n.oid and c.relkind in ('r','p') and nspname='public';

注:表所属用户或者超级用户才有开启REPLICA IDENTITY权限,否则报错:must be owner of table

查询REPLICA IDENTITY状态

SELECT c.relreplident FROM pg_class c,pg_namespace n where relnamespace = n.oid and c.relkind in ('r','p') and nspname='schema_name' and relname='table_name'

状态说明:

  • d = DEFAULT - 更新和删除将包含primary key列的现前值
  • n = NOTHING - 更新和删除将不包含任何先前值
  • f = FULL - 更新和删除将包含所有列的先前值
  • i = INDEX index name -?更新和删除事件将包含名为index name的索引定义中包含的列的先前值。

查看分区表是否打开全列附加日志:

SELECT
   parent.relname AS partitioned_table_name,
   parent.relkind AS partitioned_table_type,
   parent.relpartbound AS partition_bound,
   child.relname,
   child.relkind,
   child.relreplident,
   'ALTER TABLE ' || nspname || '.' || child.relname || ' REPLICA IDENTITY FULL' rif
FROM
 pg_class parent
LEFT JOIN pg_inherits ON pg_inherits.inhparent = parent.oid
LEFT JOIN pg_class child ON pg_inherits.inhrelid = child.oid
LEFT JOIN pg_namespace pns ON child.relnamespace = pns.oid
WHERE
 parent.relkind = 'p'
AND parent.relname = 'energy_meter_info'

注:

#连接opengaussdb报“Invalid or unsupported by client SCRAM mechanisms”处理方法
使用show password_encryption_type可以查看密码的加密方式。当password_encryption_type=1是表示采用sha256方式对密码加密,兼容postgres客户端的MD5用户认证方式。password_encryption_type=2表示采用sha256方式对密码加密,此时不兼容postgres开源驱动和开源客户端。使用postgres开源生态工具连接会出现报错,连接GaussDB(DWS)出现如下报错:
The authentication type 10 is not supported.
Invalid or unsupported by client SCRAM mechanisms。
解决方法:
gs_guc reload -Z coordinator -Z datanode -N all -I all -c “password_encryption_type=1”
这个动作需要对方许可才行

文档更新时间: 2024-06-12 01:54   作者:操李红