postgresql/lightdb CommandCounterIncrement()函数的作用
CommandCounterIncrement的作用是使当前事务中前面语句的修改对本语句可见,相当于oracle中的当前读概念(current read,只不过oracle区分,pg不区分)。事务中每执行一个语句后,对后续语句都会直接可见。如下:
zjh@postgres=# START TRANSACTION ISOLATION LEVEL REPEATABLE READ; START TRANSACTION zjh@postgres=*# select * from t; id | v ----+---- 1 | v1 (1 row) zjh@postgres=*# insert into t values(2,'v2'); INSERT 0 1 zjh@postgres=*# select * from t; id | v ----+---- 1 | v1 2 | v2 (2 rows) zjh@postgres=*# rollback; ROLLBACK
该函数的作用和cid没有关系,cid是标记当前行是被事务中的第几个语句修改。存储在元组头src/include/access/htup_details.h中,如下:
typedef struct HeapTupleFields { TransactionId t_xmin; /* inserting xact ID */ TransactionId t_xmax; /* deleting or locking xact ID */ union { CommandId t_cid; /* inserting or deleting command ID, or both */ TransactionId t_xvac; /* old-style VACUUM FULL xact ID */ } t_field3; } HeapTupleFields;
可通过pageinspect查询每行记录的元组头,如下:
zjh@postgres=# SELECT * FROM heap_page_items(get_raw_page('pg_class', 0)); lp | lp_off | lp_flags | lp_len | t_xmin | t_xmax | t_field3 | t_ctid | t_infomask2 | t_infomask | t_hoff | t_bits | t_oid | t_data ----+--------+----------+--------+--------+--------+----------+--------+-------------+------------+--------+------------------------------------------+-------+-------------------------------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------------------------------------------------------------------- 1 | 47 | 2 | 0 | | | | | | | | | | 2 | 7584 | 1 | 172 | 488 | 488 | 0 | (0,5) | 16417 | 1313 | 32 | 1111111111111111111111111111110000000000 | | \x004000007461626c655f666f725f7 66163756d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009808000002400000000000000a0000000200000000400000000000000000000000000000000000000000 00000000707202000000000000000001640000000000e801000001000000 3 | 7408 | 1 | 172 | 488 | 493 | 6 | (0,13) | 33 | 1281 | 32 | 1111111111111111111111111111110000000000 | | \x0340000070675f746f6173745f313 633383400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006300000004400000000000000a0000000200000003400000000000000000000000000000000000000000 000001007074030000000000000000016e0000000000e801000001000000 4 | 7232 | 1 | 172 | 488 | 493 | 6 | (0,15) | 33 | 1281 | 32 | 1111111111111111111111111111110000000000 | | \x0540000070675f746f6173745f313 63338345f696e64657800000000000000000000000000000000000000000000000000000000000000000000000000000000000000006300000000000000000000000a0000009301000005400000000000000100000000000000000000000000 000000007069020000000000000000016e00000000000000000000000000 5 | 7056 | 1 | 172 | 488 | 493 | 6 | (0,11) | 32801 | 9473 | 32 | 1111111111111111111111111111110000000000 | | \x004000007461626c655f666f725f7 66163756d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009808000002400000000000000a0000000200000000400000000000000b0000000000fa440b0000000340 00000000707202000000000000000001640000000000e801000001000000
zjh@postgres=# SELECT * FROM heap_page_items(get_raw_page('t', 0)); lp | lp_off | lp_flags | lp_len | t_xmin | t_xmax | t_field3 | t_ctid | t_infomask2 | t_infomask | t_hoff | t_bits | t_oid | t_data ----+--------+----------+--------+--------+--------+----------+--------+-------------+------------+--------+--------+-------+------------------ 1 | 8160 | 1 | 31 | 548 | 0 | 0 | (0,1) | 2 | 2306 | 24 | | | \x01000000077631 2 | 8128 | 1 | 31 | 549 | 0 | 0 | (0,2) | 2 | 2562 | 24 | | | \x02000000077632 3 | 8096 | 1 | 31 | 550 | 0 | 0 | (0,3) | 2 | 2562 | 24 | | | \x02000000077632 (3 rows)
如果内核相关部分没有调用CommandCounterIncrement()函数,就会发生当前事务之前的修改对随后的查询不可见的情况,这是不符合sql标准要求的。
所以,在PG内部,在每个SQL语句执行后会自动调用中间层事务命令CommitTransactionCommand(),其中自动调用CommandCounterIncrement(),对于业务元祖是无需人工调用的。但是如果是内核表(catalog),考虑到后续需要加锁、检查依赖关系等,会人工调用CommitTransactionCommand()。
https://postgrespro.com/list/id/11330.1006296063@sss.pgh.pa.us
注:需要进一步确认,如果某个语句实际的增删改查是0行,那么command id是否会增加?如果是package兼容,那么里面的元素执行了是否应该增加?见
lightdb源码中的CreatePackage(ParseState *pstate, LtCreatePackageStmt *stmt)。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!