Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Deep Dive into Seata's AT Mode Mechanism

Tech May 14 1

Seata is an open-source solution designed to provide high-performance and easy-to-use distributed transaction services for microservice architectures. Originally utilized in commercial products on Alibaba Cloud and Finance Cloud, the project was open-sourced in January 2019 to foster a more robust technical ecosystem. Seata offers a comprehensive distributed solution by supporting multiple transaction models, including AT, TCC, SAGA, and XA.

Understanding the Seata AT Mode

The Seata AT (Automatic Transaction) mode is an evolution of the Two-Phase Commit (2PC) protocol. It ensures consistency across multiple database nodes by dividing the process into a preparation phase and a commit or rollback phase. The workflow relies on a Transaction Coordinator (TC) to manage the global transaction state.

Core Principles of AT Mode

To illustrate how the AT mode operates, let's examine a practical scenario involving an inventory management table.

Consider a database table named inventory with the following structure:

Initially, this table contains a single record representing a specific stock item:

Assume a branch transaction within the AT mode executes the following SQL to reduce stock:

UPDATE inventory SET quantity = 9 WHERE sku_code = 'ITEM_A';

The execution flow within the Seata AT mode is as follows:

Phase 1: Preparation and Local Commit

In this initial phase, the application performs the business logic and records a rollback log (Undo Log) within the same local database transaction. Before committing, it registers the branch with the TC and requests a global lock for the affected data.

The detailed steps are:

  1. SQL Parsing: The framework analyzes the SQL statement to identify the type (UPDATE), the target table (inventory), and the condition (sku_code = 'ITEM_A').
  2. Query Before Image: A query is generated to fetch the data state before modification. ``` SELECT id, sku_code, quantity FROM inventory WHERE sku_code = 'ITEM_A';
  3. Execute Business SQL: The actual update statement is executed to reduce the quantity to 9.
  4. Query After Image: The system queries the modified row using the primary key obtained from the previous step. ``` SELECT id, sku_code, quantity FROM inventory WHERE id = 101;
  5. Generate Undo Log: Using the before image, after image, and SQL metadata, a rollback log entry is constructed and inserted into the undo_log table. ``` { "branchId": 789123456, "xid": "global-tx-id-001", "undoItems": [{ "sqlType": "UPDATE", "tableName": "inventory", "beforeImage": { "rows": [{ "fields": [ {"name": "id", "type": 4, "value": 101}, {"name": "sku_code", "type": 12, "value": "ITEM_A"}, {"name": "quantity", "type": 4, "value": 10} ] }] }, "afterImage": { "rows": [{ "fields": [ {"name": "id", "type": 4, "value": 101}, {"name": "sku_code", "type": 12, "value": "ITEM_A"}, {"name": "quantity", "type": 4, "value": 9} ] }] } }] }
  6. Register Branch and Acquire Lock: Before submitting the local transaction, the branch registers with the TC (Seata Server) and requests a global lock for the record where id = 101.
  7. Local Commit: The local transaction is comimtted, persisting both the business data changes and the Undo Log. The result is reported back to the TC.

Phase 2: Global Commit or Rollback

In this phase, the TC decides the final outcome based on the status of all branches associated with the global XID.

  1. Global Commit: If all branch transactions executed successfully, the TC issues a commit command. Since the data was already committed locally in Phase 1, the transaction participants simply delete the corresponding Undo Log records asynchronously.
  2. Global Rollback: If any branch fails, the TC initiates a rollback. The steps for a transaction participant are:
    • Receive the rollback request and start a new local transaction.
    • Locate the specific Undo Log record using the XID and Branch ID.
    • Data Validation: Compare the afterImage stored in the Undo Log with the current data in the inventory table. If they differ, it means the data was modified by another transaction outside the current global scope. Handling depends on the configured strategy.
    • Generate Compensating SQL: If validation passes, construct a compensating SQL statement using the beforeImage and execute it. ``` UPDATE inventory SET quantity = 10 WHERE id = 101;
    • Commit the local transaction and report the rollback status to the TC.

The Seata AT model effectively extends standard database transaction concepts to a distributed scope: acquiring locks, writing transaction logs, and committing or rolling back.

Transaction Isolation in AT Mode

Just like local database transactions, distributed transactions must manage isolation levels to prevent concurrency issues such as dirty reads, non-repeatable reads, and phantom reads.

Write Isolation

Write isolation ensures that when multiple global transactions attempt to modify the same data record, operations are serialized. Seata achieves this using a global lock mechanism.

  • Before committing a local transaction in Phase 1, the branch must acquire the global lock for the record.
  • If the global lock cannot be acquired (because it is held by another transaction), the local transaction rollback is triggered, releasing the local lock.

Scenario Example: Two global transactions, GlobalTx1 and GlobalTx2, both attempt to update the quantity of id = 101 (initially 10).

  • GlobalTx1 starts, acquires the local lock, updates quantity to 9, acquires the global lock, commits the local transaction, and releases the local lock.
  • GlobalTx2 starts, acquires the local lock, updates quantity to 8, and attempts to acquire the global lock.
  • Since GlobalTx1 still holds the global lock (it hasn't finished Phase 2 yet), GlobalTx2 is blocked and cannot commit its local transaction.
  • Once GlobalTx1 completes Phase 2 (commit or rollback), it releases the global lock. GlobalTx2 can then acquire the global lock and proceed.

If GlobalTx1 must roll back, it needs to re-acquire the local lock to perform the compensation. It will retry until GlobalTx2 gives up waiting for the global lock and rolls back its local changes. This ensures that dirty writes are prevented.

Read Isolation

The default global isolation level in Seata AT mode is Read Uncommitted. This is because local transactions commit immediately in Phase 1, making modified data visible to other transactions before the global transaction is fully committed.

For scenarios requiring Read Committed isolation at the global level, Seata utilizes the SELECT FOR UPDATE statement.

  • When a SELECT FOR UPDATE statement is executed, Seata proxies the query to request the global lock.
  • If the global lock is held by another transaction, the statement is blocked (or retried), releasing the local lock if necessary.
  • The query returns only once the global lock is acquired, ensuring that the data read is from a committed global transaction.

For performance reasons, Seata applies this proxy mechanism specifically to SELECT FOR UPDATE statements, rather than all standard queries.

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.