Postgres-XL分布式事务实现三
Postgres-XL分布式事务介绍一:Postgres-XL分布式事务实现一
Postgres-XL分布式事务介绍二:Postgres-XL分布式事务实现二
3.4 分布式事务二阶段提交(2PC)的阶段
实际上前面的3.1节、3.2节、3.3节从功能上来说属于阶段,不过我更倾向于称之为子事务的预处理阶段,从协议层面上来说,2PC的阶段是全局事务管理器要求所有的子事务进入预交阶段,进行投票查询。若子事务准备好了并愿意提交,则如果子事务是一个只读事务,就返回“只读”票并先行提交,否则投“提交”票。若子事务不能提交,就投“失败”票,然后先行失败。该阶段也称之为子事务的预提交阶段。
该阶段的时序图如下图所示,为了便于直观,没有画出pg1中dn1_bycn1和D_dn1之间的数据交互,他们之间的数据交互类似于pg2和pg3:具体步骤为:
步骤一、 pg1的cn1pgxl进程同时分别向dn1_bycn1、dn2_bycn1、dn3_bycn1发送“PREPARE TRANSACTION”命令,让他们为当前事务做两阶段提交的准备,发送命令如下,其中事务ID(XID)为’1254604:coord1:F:3:0:-560021589:352366662:-700122826’
PREPARE TRANSACTION '_$XC$1254604:coord1:F:3:0:-560021589:352366662:-700122826'
注意:下图绿色框中的“Ack=545”,在下面的步骤五中依然会用到该连接,用于发回响应数据。
步骤二、dn1_bycn1、dn2_bycn1、dn3_bycn1收到“PREPARE TRANSACTION”命令后,立即向与其相连接的D_dn1、D_dn2、D_dn3发送“COMMIT TRANSACTION”命令,让其尝试进行事务提交操作
步骤三、pg1上三个事务处理子进程D_dn1、D_dn2、D_dn3在接到“COMMIT TRANSACTION”命令后,会进行提交操作,使得3.3节步骤四开启的事务正常结束,此时其处于空闲状况(I)。
步骤四、dn1_bycn1、dn2_bycn1、dn3_bycn1收到D_dn1、D_dn2、D_dn3发送回的事务正常结束响应后,会接着发送“RESET ALL”和“RSET”命令,重置环境,命令如下,在D_dn1、D_dn2、D_dn3都重置成功后会立刻发回响应数据给对应的数据协调进程。
RESET ALL; RESET SESSION AUTHORIZATION; RESET transaction_isolation;
步骤五、数据协调进程dn1_bycn1、dn2_bycn1、dn3_bycn1收到下层数据处理子进程放送回的重置成功响应后,会向pg1的cn1_pgxl进程发送“PREPARE TRANSACTION”命令(该节步骤一发送的)操作成功的响应;
注意:下图绿色框中的“Seq=545”,即前面步骤一中的连接,用于发回响应数据。步骤六、pg1的cn1_pgxl进程收到成功响应后,会分别向dn1_bycn1、dn2_bycn1、dn3_bycn1发送“RESET ALL”和“RSET”命令,用于重置环境,命令如下,在dn1_bycn1、dn2_bycn1、dn3_bycn1重置成功都后会立刻发回响应数据给cn1_pgxl进程。
RESET ALL; RESET SESSION AUTHORIZATION; RESET transaction_isolation;
步骤七、cn1_pgxl收到三个数据协调进程的成功响应后,会向pg2的dn2_bycn1发送“SET”命令,用于重新设置global_session和parentPGXCPid,dn2_bycn1设置成功后会返回成功的响应;
SET global_session TO coord1_61366; SET parentPGXCPid TO 61366;
步骤八、cn1_pgxl收到pg2的dn2_bycn1返回设置成功的响应后,会依次和pg1的dn1_bycn1和pg3的dn3_bycn1进行同样的步骤七操作,只有全部操作成功后,才标准2PC的阶段成功,转为进入第二阶段。
3.5 分布式事务二阶段提交(2PC)的第二阶段
在第二阶段,全局事务管理器分析接收到的子事务消息,若超时或收到一个“失败”票,则决定失败整个分布事务,并向所有投“提交”票的子事务发失败命令,否则向它们发提交命令:“COMMIT PREPARED” ;
因为前面的3.1节到3.4节所示操作,将事务的前期操作都已经全部完成,包括待插入数据的生成等,所以第二阶段的提交操作是一个耗时极短的微小操作。
整个2PC阶段的时序图如下图所示,为了便于直观,没有画出pg1中dn1_bycn1和D_dn1之间的数据交互,他们之间的数据交互类似于pg2和pg3:具体过程如下:
步骤一、pg1的cn1pgxl同时向dn1_bycn1、dn2_bycn1、dn3_bycn1发送“COMMIT PREPARED”命令,用于提交一个早先为两阶段提交准备好的事务,命令如下,其中事务ID(XID)为’1254604:coord1:F:3:0:-560021589:352366662:-700122826’,XID和3.4节步骤一中所用到XID必须是同一个:
COMMIT PREPARED ‘_1254604:coord1:F:3:0:-560021589:352366662:-700122826’
步骤二、dn1_bycn1、dn2_bycn1、dn3_bycn1执行“COMMIT PREPARED”命令成功后,即INSERT操作成功后,都会给pg1的cn1_pgxl发送操作成功的响应数据
步骤三、cn1_pgxl收到dn1_bycn1、dn2_bycn1、dn3_bycn1发送回的操作成功的响应数据后,会后向他们发送“RESET ALL”和“RSET”命令,用于重置环境,命令如下,在dn1_bycn1、dn2_bycn1、dn3_bycn1重置成功都后会立刻发回响应数据给cn1_pgxl进程。
RESET ALL; RESET SESSION AUTHORIZATION; RESET transaction_isolation;至此,整个分布式事务两阶段提交就已经全部完成,依次查询dn1、dn2、dn3上的表test_hash中插入的数据如下:
来源 https://mp.weixin.qq.com/s/z6fqwvNVzDESkqM4ig4KCQ
相关文章