举个例子:不同隔离级别下,XA 分布式事务的数据可见性
我们通过两个具体的例子来对比 REPEATABLE READ
和 SERIALIZABLE
在分布式事务中的行为差异。
✅ 场景设定:
- MySQL 使用 XA 分布式事务机制。
- 一个事务 T1 修改了两个节点 A 和 B 的数据:
- A 上的数据从
a → a'
- B 上的数据从
b → b'
- A 上的数据从
- T1 先在节点 A 提交(commit),但还没在节点 B 提交。
- 此时另一个事务 T2 尝试读取这些数据。
🟢 REPEATABLE READ 下的表现
- T2 可以立即看到 T1 在节点 A 上提交后的结果
a'
。 - 因为
REPEATABLE READ
是快照读(MVCC),不会加锁。 - 所以即使 T1 还没有在节点 B 完成提交,T2 也能读取到 B 上的老数据
b
。
🔍 问题出现:T2 看到了 T1 的部分修改(看到了
a'
,但没看到b'
),这可能导致业务层面的数据不一致。
📌 结论:
在
REPEATABLE READ
隔离级别下,分布式事务可能出现“只看到部分更新”的情况,看起来像是脏读(虽然不是严格意义上的脏读),不符合 ACID 中的隔离性要求。
🔵 SERIALIZABLE 下的表现
- 在
SERIALIZABLE
隔离级别下,所有的SELECT
操作都会加共享锁(等价于SELECT ... LOCK IN SHARE MODE
)。 - 所以当 T2 尝试读取节点 B 上的数据
b
时,会被阻塞,直到 T1 在节点 B 上完成提交。
✅ 关键区别:T2 不会读到 B 上的老数据
b
,而是等到 T1 完全提交后才读到b'
。
📌 结论:
虽然
SERIALIZABLE
也无法改变分布式事务的两阶段提交流程,但它通过强制加锁,确保了一个事务一旦读到了某个分支的更新(如 A 的a'
),就不会再读到其他分支的老数据(如 B 的b
)。
这样就避免了“只看到一部分更改”的问题,更符合 ACID 中 Isolation(隔离性) 的要求。
🧾 总结对比
隔离级别 | 是否能看到部分提交? | 是否加锁? | 是否保证全局一致性? |
---|---|---|---|
REPEATABLE READ | ✅ 是 | ❌ 否 | ❌ 较弱 |
SERIALIZABLE | ❌ 否 | ✅ 是 | ✅ 更强 |
📌 最后一句话总结:
在分布式事务中,REPEATABLE READ
可能导致事务读到“部分更新”,而 SERIALIZABLE
则通过加锁机制,延迟读取操作,直到所有分支都完成提交,从而更好地保障了事务之间的隔离性和一致性。