Tencent / 3TS

腾讯事务处理技术验证系统(Tencent Transaction Processing Testbed System)
Other
145 stars 53 forks source link

Dynamic testing of weak isolation levels #64

Open WeihuaSun opened 1 month ago

WeihuaSun commented 1 month ago

1. Changes to 'version_list':

In the previous implementation of 'version_list', an unexpected exception could occur: "Value exists, but did not successfully read." This happens when a read operation returns no results, but previous write operations updated values that should have been part of the read results. The problem arises because these updated values haven't been committed yet, making them invisible in isolation levels above Read Committed.

This is especially concerning under snapshot isolation because it only shows updates from transactions that were committed before the snapshot was created.

Example:

Preparation Steps:

  1. Create new tables and insert the necessary data.
    DROP TABLE IF EXISTS t1;
    CREATE TABLE t1 (k INT PRIMARY KEY, v INT);
    INSERT INTO t1 VALUES (0, 0);
    INSERT INTO t1 VALUES (2, 2);
    INSERT INTO t1 VALUES (4, 4);

Execution Steps:

  1. Start multiple transactions with the isolation level set to serializable.
  2. Run the following commands:
    • Q1-T1: BEGIN;
    • Q2-T1: INSERT INTO t1 VALUES (1, 1);
    • Q3-T2: BEGIN;
    • Q4-T2: SELECT * FROM t1 WHERE k=1; (This returns null)
    • Q5-T2: SELECT * FROM t1 WHERE k > 0 AND k < 2; (This also returns null)
    • Q6-T2: COMMIT;
    • Q7-T1: UPDATE t1 SET v=2 WHERE k=1;
    • Q8-T1: COMMIT;

Test Result:

Solution:

2. Handling Versions:

To see the latest version, I traversed the 'version_list' in reverse. If the first valid version is not the one that was read, it indicates that the read operation is using an older version. This approach helps prevent Intermediate Read anomalies.

3. Checking Loops for Weak Isolation Levels:

Different isolation levels handle loops in dependency graphs differently:

For snapshot isolation, if a loop exists, it must have at least two consecutive anti-dependency edges.

Implementation Note: Adya’s definitions are the minimum requirements for isolation levels, but the actual implementation might be stricter. For instance, the serializability implemented by SSI does not allow two consecutive anti-dependency edges.

MySQL's repeatable read is lower than PL-2.99, which allows loops with item anti-dependencies. And MySQL's repeatable read is not snapshot isolation, because it allows concurrent updates, which can cause lost updates. I use snapshot read visibility plus PL-1 rules to detect MySQL's repeatable read isolation level.

Verification Process: