暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

PostgreSQL 14 preview - Add option to enable two_phase commits via pg_create_logical_replication_slot

digoal 2021-01-03
626

作者

digoal

日期

2021-03-04

标签

PostgreSQL , pg_create_logical_replication_slot


背景

《PostgreSQL 14 preview - logical decoding 增加2pc 两阶段事务,xa事务 支持》

PG 14 新增一个pg_create_logical_replication_slot选项, 在创建slot时, 支持是否解析2pc.

https://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=19890a064ebf53dedcefed0d8339ed3d449b06e6

```
Add option to enable two_phase commits via pg_create_logical_replication_slot.

Commit 0aa8a01d04 extends the output plugin API to allow decoding of
prepared xacts and allowed the user to enable/disable the two-phase option
via pg_logical_slot_get_changes(). This can lead to a problem such that
the first time when it gets changes via pg_logical_slot_get_changes()
without two_phase option enabled it will not get the prepared even though
prepare is after consistent snapshot. Now next time during getting changes,
if the two_phase option is enabled it can skip prepare because by that
time start decoding point has been moved. So the user will only get commit
prepared.

Allow to enable/disable this option at the create slot time and default
will be false. It will break the existing slots which is fine in a major
release.

Author: Ajin Cherian
Reviewed-by: Amit Kapila and Vignesh C
Discussion: https://postgr.es/m/d0f60d60-133d-bf8d-bd70-47784d8fabf3@enterprisedb.com
```

背景:

``` Amit, Ajin, hackers,

testing logical decoding for two-phase transactions, I stumbled over what I first thought is a bug. But comments seems to indicate this is intended behavior. Could you please clarify or elaborate on the design decision? Or indicate this indeed is a bug?

What puzzled me is that if a decoder is restarted in between the PREPARE and the COMMIT PREPARED, it repeats the entire transaction, despite it being already sent and potentially prepared on the receiving side.

In terms of pg_logical_slot_get_changes (and roughly from the prepare.sql test), this looks as follows:

                     data

BEGIN table public.test_prepared1: INSERT: id[integer]:1 PREPARE TRANSACTION 'test_prepared#1' (3 rows)

This is the first delivery of the transaction. After a restart, it will get all of the changes again, though:

                     data

BEGIN table public.test_prepared1: INSERT: id[integer]:1 PREPARE TRANSACTION 'test_prepared#1' COMMIT PREPARED 'test_prepared#1' (4 rows)

I did not expect this, as any receiver that wants to have decoded 2PC is likely supporting some kind of two-phase commits itself. And would therefore prepare the transaction upon its first reception. Potentially receiving it a second time would require complicated filtering on every prepared transaction.

Furthermore, this clearly and unnecessarily holds back the restart LSN. Meaning even just a single prepared transaction can block advancing the restart LSN. In most cases, these are short lived. But on the other hand, there may be an arbitrary amount of other transactions in between a PREPARE and the corresponding COMMIT PREPARED in the WAL. Not being able to advance over a prepared transaction seems like a bad thing in such a case.

I fail to see where this repetition would ever be useful. Is there any reason for the current implementation that I'm missing or can this be corrected? Thanks for elaborating.

Regards

Markus

```

PostgreSQL 许愿链接

您的愿望将传达给PG kernel hacker、数据库厂商等, 帮助提高数据库产品质量和功能, 说不定下一个PG版本就有您提出的功能点. 针对非常好的提议,奖励限量版PG文化衫、纪念品、贴纸、PG热门书籍等,奖品丰富,快来许愿。开不开森.

9.9元购买3个月阿里云RDS PostgreSQL实例

PostgreSQL 解决方案集合

德哥 / digoal's github - 公益是一辈子的事.

digoal's wechat

文章转载自digoal,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论