client
undo_log
In AT mode, you need to add an undo in the database participating in the global transaction_ Log table. The table creation statement is as follows:
SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for undo_log -- ---------------------------- DROP TABLE IF EXISTS `undo_log`; CREATE TABLE `undo_log` ( `branch_id` bigint(20) NOT NULL COMMENT 'Branch transaction ID', `xid` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'Global transaction ID', `context` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'context', `rollback_info` longblob NOT NULL COMMENT 'rollback information ', `log_status` int(11) NOT NULL COMMENT 'Status, 0 normal, 1 global completed', `log_created` datetime(6) NOT NULL COMMENT 'Creation time', `log_modified` datetime(6) NOT NULL COMMENT 'Modification time', UNIQUE INDEX `ux_undo_log`(`xid`, `branch_id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = 'AT transaction mode undo table' ROW_FORMAT = Compact; SET FOREIGN_KEY_CHECKS = 1;
In the first phase of a global transaction, when a branch transaction obtains the global lock and commits the transaction, it will release the local lock and connection resources and_ Insert a piece of data into the log table.
For example, when updating, such a piece of data will be inserted:
The details of each field are as follows:
Field name | explain |
---|---|
branch_id | Branch transaction ID, for example: 99302990136558270 |
xid | Global transaction ID, for example: 192.168.58.1:8091:99302990136558268 (Seata server address + ID) |
context | Rollback information serialization and compression format, serializer = fastjson & compressortype = none, indicating that fastjson serialization is used without compression |
rollback_info | rollback information |
log_status | Log status, 0 normal, 1 global completed |
log_created | Creation time |
log_modified | Modification time |
The most important one is rollback_info, for example, when updating a piece of data, set money = 97 will query the status of the data before and after modification.
In rollback_ In info, the data was 98:
Before modification, the data is 97:
In the second stage, if the global transaction is successful, it will receive the branch submission request of TC, put the request into the queue of an asynchronous task, and immediately return the successful submission result to TC. The branch submission request in the asynchronous task phase will delete the corresponding UNDO LOG records asynchronously and in batch.
In the second stage, if the global transaction fails, you will receive a branch rollback request from the TC, start a local transaction, and perform the following operations.
- Find the corresponding UNDO LOG record through XID and Branch ID.
- Data verification: compare the back mirror in UNDO LOG with the current data. If it is different, it indicates that the data has been modified by actions other than the current global transaction. This situation needs to be handled according to the configuration policy. The detailed description is introduced in another document.
- Generate and execute rollback statements according to the relevant information of the front image and business SQL in UNDO LOG.
- Commit local transaction. And report the execution result of local transaction (i.e. the result of branch transaction rollback) to TC.
Server
Transaction session storage mode
On the server side, transaction session information needs to be stored. The following methods are supported:
- File local file (HA is not supported),
- db database (HA supported)
- Redis (HA supported)
The local file mode is the most efficient, but it does not support clustering, and when there is a problem, it is impossible to format and view the current data, so it is recommended to use the database or cache mode.
When using database schema, you need to create the following three tables:
- global_table: global transaction
- branch_table: Branch transaction
- lock_table: global lock
global_table
global_table records the information of global transactions. The statement of creating a table is as follows:
SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for global_table -- ---------------------------- DROP TABLE IF EXISTS `global_table`; CREATE TABLE `global_table` ( `xid` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'Global transaction ID', `transaction_id` bigint(20) NULL DEFAULT NULL COMMENT 'affair ID', `status` tinyint(4) NOT NULL COMMENT 'state', `application_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'application ID', `transaction_service_group` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'Transaction group name', `transaction_name` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'Method of executing transaction', `timeout` int(11) NULL DEFAULT NULL COMMENT 'Timeout', `begin_time` bigint(20) NULL DEFAULT NULL COMMENT 'start time', `application_data` varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'Application data', `gmt_create` datetime(0) NULL DEFAULT NULL COMMENT 'Creation time', `gmt_modified` datetime(0) NULL DEFAULT NULL COMMENT 'Modification time', PRIMARY KEY (`xid`) USING BTREE, INDEX `idx_gmt_modified_status`(`gmt_modified`, `status`) USING BTREE, INDEX `idx_transaction_id`(`transaction_id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact; SET FOREIGN_KEY_CHECKS = 1;
For example, the current application demo001 initiates a global transaction, and the following information will be stored in this table:
branch_table
branch_table records the information of branch transactions. The statement for creating a table is as follows:
SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for branch_table -- ---------------------------- DROP TABLE IF EXISTS `branch_table`; CREATE TABLE `branch_table` ( `branch_id` bigint(20) NOT NULL COMMENT 'Branch transaction ID', `xid` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'Global transaction ID', `transaction_id` bigint(20) NULL DEFAULT NULL COMMENT 'Global transaction ID,No TC address', `resource_group_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'Resource grouping ID', `resource_id` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'resources ID', `branch_type` varchar(8) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'Transaction mode, AT,XA etc.', `status` tinyint(4) NULL DEFAULT NULL COMMENT 'state', `client_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'client ID', `application_data` varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'Application data', `gmt_create` datetime(6) NULL DEFAULT NULL COMMENT 'Creation time', `gmt_modified` datetime(6) NULL DEFAULT NULL COMMENT 'Modification time', PRIMARY KEY (`branch_id`) USING BTREE, INDEX `idx_xid`(`xid`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact; -- ---------------------------- -- Records of branch_table -- ---------------------------- SET FOREIGN_KEY_CHECKS = 1;
When a service calls another service for a global transaction, you can see that the relevant information of the current two service branch transactions is inserted into the table, among which the important ones are ID, transaction mode, client address, database connection address, etc.
INSERT INTO `branch_table` VALUES (99302990136565280, '192.168.58.1:8091:99302990136565278', 99302990136565278, NULL, 'jdbc:mysql://127.0.0.1:3306/db_account', 'AT', 0, 'demo001:192.168.58.1:2116', NULL, '2022-01-25 16:56:58.092953', '2022-01-25 16:56:58.092953'); INSERT INTO `branch_table` VALUES (99302990136565283, '192.168.58.1:8091:99302990136565278', 99302990136565278, NULL, 'jdbc:mysql://127.0.0.1:3306/db_order', 'AT', 0, 'demo002:192.168.58.1:2617', NULL, '2022-01-25 16:56:58.551257', '2022-01-25 16:56:58.551257');
lock_table
lock_table records lock related information. The table creation statement is as follows:
SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for lock_table -- ---------------------------- DROP TABLE IF EXISTS `lock_table`; CREATE TABLE `lock_table` ( `row_key` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'Row key', `xid` varchar(96) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'Global transaction ID', `transaction_id` bigint(20) NULL DEFAULT NULL COMMENT 'Global transaction ID,No TC address', `branch_id` bigint(20) NOT NULL COMMENT 'branch ID', `resource_id` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'resources ID', `table_name` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'Table name', `pk` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'Value corresponding to primary key', `gmt_create` datetime(0) NULL DEFAULT NULL COMMENT 'Creation time', `gmt_modified` datetime(0) NULL DEFAULT NULL COMMENT 'Modification time', PRIMARY KEY (`row_key`) USING BTREE, INDEX `idx_branch_id`(`branch_id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact; SET FOREIGN_KEY_CHECKS = 1;
For example, the following figure:
The detailed process of TC side transaction interaction will be analyzed later.