postgresql Two-phase commit

对于XA的支持,pg目前没明确提出来,只是实现了两阶段提交,

 

XID这个名词已被占用,所以提出了GID a global transaction identifier

 

create table a(a int);

 

begin;

 

insert a values(1);

 

prepare transaction 'aaa';

 

commit prepared 'aaa';

 

rollback prepared 'aaa';

 

目前支持这样的语法,'aaa' 就是GID,具体见下

http://www.postgresql.org/docs/current/static/sql-prepare-transaction.html

 

 

/* The lifecycle of a global transaction is: * * 1. After checking that the requested GID is not in use, set up an * entry in the TwoPhaseState->prepXacts array with the correct XID and GID, * with locking_xid = my own XID and valid = false. * * 2. After successfully completing prepare, set valid = true and enter the * contained PGPROC into the global ProcArray. * * 3. To begin COMMIT PREPARED or ROLLBACK PREPARED, check that the entry * is valid and its locking_xid is no longer active, then store my current * XID into locking_xid. This prevents concurrent attempts to commit or * rollback the same prepared xact. * * 4. On completion of COMMIT PREPARED or ROLLBACK PREPARED, remove the entry * from the ProcArray and the TwoPhaseState->prepXacts array and return it to * the freelist. */

 

下面是全局事务的定义,就是比局部事务上多了几个变量,是专门的一个列表,和普通事务的不一样

 

#define GIDSIZE 200 typedef struct GlobalTransactionData { PGPROC proc; /* dummy proc */ BackendId dummyBackendId; /* similar to backend id for backends */ TimestampTz prepared_at; /* time of preparation */ XLogRecPtr prepare_lsn; /* XLOG offset of prepare record */ Oid owner; /* ID of user that executed the xact */ TransactionId locking_xid; /* top-level XID of backend working on xact */ bool valid; /* TRUE if fully prepared */ char gid[GIDSIZE]; /* The GID assigned to the prepared xact 存GID字符串*/ } GlobalTransactionData; //共享内存中的,正在运行的,全局事务列表 typedef struct TwoPhaseStateData { /* Head of linked list of free GlobalTransactionData structs */ GlobalTransaction freeGXacts; /* Number of valid prepXacts entries. */ int numPrepXacts; /* * There are max_prepared_xacts items in this array, but C wants a * fixed-size array. */ GlobalTransaction prepXacts[1]; /* VARIABLE LENGTH ARRAY */ } TwoPhaseStateData; /* VARIABLE LENGTH STRUCT */

 

 

 

 

 

在 prepare transaction 的时候,在数据库的目录的 pg_twophase 文件夹生成state file,文件名为事务的XID, 

 

 

/* * 2PC state file format: * * 1. TwoPhaseFileHeader * 2. TransactionId[] (subtransactions) * 3. RelFileNode[] (files to be deleted at commit) * 4. RelFileNode[] (files to be deleted at abort) * 5. SharedInvalidationMessage[] (inval messages to be sent at commit) * 6. TwoPhaseRecordOnDisk * 7. ... 还记录了下面三种资源 for all locks currently held Save the transactional stats state Save multixact state * 8. TwoPhaseRecordOnDisk (end sentinel, rmid == TWOPHASE_RM_END_ID) * 9. CRC32 * * Each segment except the final CRC32 is MAXALIGN'd. */ typedef struct TwoPhaseFileHeader { uint32 magic; /* format identifier */ uint32 total_len; /* actual file length */ TransactionId xid; /* original transaction XID */ Oid database; /* OID of database it was in */ TimestampTz prepared_at; /* time of preparation */ Oid owner; /* user running the transaction */ int32 nsubxacts; /* number of following subxact XIDs */ int32 ncommitrels; /* number of delete-on-commit rels */ int32 nabortrels; /* number of delete-on-abort rels */ int32 ninvalmsgs; /* number of cache invalidation messages */ bool initfileinval; /* does relcache init file need invalidation? */ char gid[GIDSIZE]; /* GID for transaction */ } TwoPhaseFileHeader; /* * Header for each record in a state file * * NOTE: len counts only the rmgr data, not the TwoPhaseRecordOnDisk header. * The rmgr data will be stored starting on a MAXALIGN boundary. */ typedef struct TwoPhaseRecordOnDisk { uint32 len; /* length of rmgr data */ TwoPhaseRmgrId rmid; /* resource manager for this record */ uint16 info; /* flag bits for use by rmgr */ } TwoPhaseRecordOnDisk;

 

 

 

 

prepare transaction

 

要生成state file的主要原因是,在这一过程中,已完成了资源的释放,把不能释放的记录下来,以便commit时候释放

 

commit prepared

 

把state file读出来解析,接着释放资源,之后就是记录日志,并把state file删除

 

当在prepare transaction成功,之后系统挂掉,这时state file已创建成功,保留在硬盘上,当系统重启后,会根据日志和state file重构XA事物,在系统启动完成后,可以接着 commit prepared 或 rollback prepared 这个事物。

  

你可能感兴趣的:(manager,struct,File,database,PostgreSQL,locking)