【PostgreSQL-15逻辑复制发布/订阅的两阶段提交功能测试】

数据库版本:

一、启动两阶段提交

1发布方

  • 创建表和发布。
postgres=# CREATE TABLE test (col1 INT, col2 TEXT, PRIMARY KEY(col1));
CREATE TABLE
postgres=# CREATE PUBLICATION pub FOR TABLE test;

2订阅方

  • 创建同一个表,并创建一个启用 two_phase 模式的订阅。
  • 检查subtwophasestate列以验证它是否启用了two_phase(如果值为e,则开启了)。
     postgres=#  CREATE TABLE test (col1 INT, col2 TEXT, PRIMARY KEY(col1));
     CREATE TABLE
     postgres=# CREATE SUBSCRIPTION sub CONNECTION 'dbname=postgres host=172.20.10.6 port=6000 user=ysla  password=1qaz!QAZ' PUBLICATION pub WITH (two_phase = on);	
     NOTICE:  created replication slot "sub" on publisher
     CREATE SUBSCRIPTION
     
     postgres=# SELECT subtwophasestate FROM pg_subscription;
     subtwophasestate
     ------------------
     e
     (1 row)

相应日志为

发布节点

订阅节点

3发布方

  • 开始交易。
  • 插入一些数据。
  • 准备事务并检查 GID。
    postgres=# BEGIN;
    BEGIN
    postgres=*# INSERT INTO test VALUES (7,'aa');
    INSERT 0 1
    postgres=*# PREPARE TRANSACTION 't1';
    PREPARE TRANSACTION

操作的时候由于疏忽,没启动prepare transaction ,这点需要注意,要启动要启动prepare transaction,需要到postgresql.conf配置文件中,将参数max_prepare_transactions设置为非零的值,然后重启数据库服务即可 。

参数修改后,正确的如下

4订阅方

  • 检查订户端并查看生成的准备好的事务 GID 也在那里复制。
postgres=# SELECT * FROM pg_prepared_xacts;

此时我们检查订阅节点的pg_twophase目录,该目录包含预备事务的状态文件
 

对于这个二进制文件,我们可以用hexdump查看内容,例如:

5发布方

  • 提交准备好的事务。
  • 观察准备好的事务 GID 现在已经消失(它已提交)。
  • 选择插入的数据。
    postgres=# COMMIT PREPARED 't1';
    COMMIT PREPARED
    postgres=# SELECT * FROM pg_prepared_xacts;
    transaction | gid | prepared | owner | database
    ------------+-----+----------+-------+----------
    (0 rows)
    postgres=# SELECT * FROM test;
     a | b 
    ---+----
     7 | aa
    (1 row)

6订阅方

  • 订阅方生成的 GID 也消失了(已提交)。
  • 选择显示已复制发布的数据。
      postgres=# SELECT * FROM pg_prepared_xacts;
      transaction | gid | prepared | owner | database
      ------------+-----+----------+-------+----------
      (0 rows)
      postgres=# SELECT * from test;
       a | b 
      ---+----
       7 | aa
      (1 row)


订阅节点的pg_twophase目录里的对应事务状态的文件已经不存在了

二、不启动两阶段提交

1发布方

  • 创建表和发布。
      postgres=# CREATE TABLE test2 (col1 INT, col2 TEXT, PRIMARY KEY(col1));
      CREATE TABLE
      postgres=# CREATE PUBLICATION pub FOR TABLE test2;

2订阅方

  • 创建同一个表,并创建一个启用 two_phase 模式的订阅。
  • 检查subtwophasestate列以验证它是否启用了two_phase(如果值为e,则开启了)。
      postgres=#  CREATE TABLE test2 (col1 INT, col2 TEXT, PRIMARY KEY(col1));
      CREATE TABLE
      postgres=# CREATE SUBSCRIPTION sub2 CONNECTION 'dbname=postgres host=172.20.10.6 port=6000 user=ysla  password=1qaz!QAZ' PUBLICATION pub2 WITH (two_phase = off);
      NOTICE:  created replication slot "sub2" on publisher
      CREATE SUBSCRIPTION
      
      postgres=# SELECT subname,subtwophasestate  FROM pg_subscription;
       subname | subtwophasestate 
      ---------+------------------
       sub     | e
       sub2    | d
      (2 rows)

3发布方

  • 开始交易。
  • 插入一些数据。
  • 准备事务并检查 GID。
    postgres=# BEGIN;
    BEGIN
    postgres=*# INSERT INTO test2 VALUES (22,'aa');
    INSERT 0 1
    postgres=*# PREPARE TRANSACTION 't2';
    PREPARE TRANSACTION
    postgres=# SELECT * FROM pg_prepared_xacts;
     transaction | gid |           prepared            |  owner   | database 
    -------------+-----+-------------------------------+----------+----------
             749 | t2  | 2022-04-24 19:12:27.372256+08 | postgres | postgres
    (1 row)

4订阅方

  • 检查订户端并查看生成的准备好的事务 GID 也在那里复制。
       postgres=#  SELECT * FROM pg_prepared_xacts;
       transaction |       gid        |           prepared            |  owner   | database 
      -------------+------------------+-------------------------------+----------+----------
              1951 | pg_gid_24607_749 | 2022-04-24 19:12:27.602742+08 | postgres | postgres
      (1 row)
      
      postgres=# select * from test2;
       col1 | col2 
      ------+------
      (0 rows)

此时在订阅节点的pg_twophase目录下,也传输过来了对应的状态文件

5发布方

  • 提交准备好的事务。
  • 观察准备好的事务 GID 现在已经消失(它已提交)。
  • 选择插入的数据。

6订阅方

  • 订阅方生成的 GID消失(提交失败)。
  • 不显示已复制发布的数据。

总结

根据测试结果来看:
1、逻辑复制开启two_phase,主库COMMIT PREPARE之后,订阅节点才会把事务提交,看到结果,但是在PREPARE TRANSACTION阶段,已经把准备好的事务发送到订阅节点了。

2.逻辑复制不开启two_phase,在PREPARE TRANSACTION阶段,会把两阶段提交的状态文件传输到订阅节点,但就算发布节点COMMIT PREPARE了,因为没使用two_phase,发布节点提交成功,而订阅节点提交失败。

因此,如果在逻辑复制不使用two_phase的时候,就只能通过正常的BEGIN;COMMIT;的方式把事务发送给订阅节点 。

欢迎交流。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小怪兽ysl

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值