XA事务的隔离级别算啥级别

同意上面的观点: serializable 隔离级别下, XA 事务是能够避免脏读的。
仔细想一下就能明白:XA 事务由于不同节点 commit 的先后顺序,导致有些节点上的已提交数据在 XA 事务 “真正” 完成 commit 前会被其他事务读到。 但是,XA 只要保证这些这些 “提前读到数据” 的事务,在访问其他节点时,也读到相同的已提交数据就 OK。
换句话说,就是 XA 事务修改了节点 A 上的数据 a --\u0026gt; a\u0026#39;, 节点 B 上的数据 b --\u0026gt; b\u0026#39;,在提交阶段,可能 a\u0026#39; 被其他事务读到,这时候只要保证读到 a\u0026#39; 的事务也同时读到 b\u0026#39; ,就是一致的。反过来,如果其他事务读到的是 a\u0026#39;, b 或者 a, b\u0026#39;, 就违反了一致性,产生了脏读。
想通了这点,就能明白 mysql 为什么要求 XA 事务跑在 serializable 隔离级别了:因为 serializable 级别下 mysql 会对所有 读加锁。还是上面的例子,如果 XA 事务中在节点 A commit 之后,有事务读到了 a\u0026#39;,那么这个事务在读节点 B 时一定会阻塞,不可能读到数据 b。
反之,如果有事务提前读到了 a, 那么其他事务一定会在写入 a --\u0026gt; a\u0026#39; 时阻塞,保证当前事务只会读到 b。不会出现中间事务修改了 a --\u0026gt; a\u0026#39;, b --\u0026gt; b\u0026#39; 再 commit,结果让当前事务读到 b\u0026#39; 的情况。
至于有中间事务执行了 b --\u0026gt; b\u0026#39;\u0026#39;, 让当前事务读到 a, b\u0026#39;\u0026#39; 的情况 —— 由于中间事务从来没有访问过 a, 从 serializable 的角度我们完全可以认为这个中间事务发生于当前事务之前嘛,不违反一致性。
至于问题 2,分布式事务有没有办法实现 Repeatable-Read 以上的隔离级别,结论当然是可以,而且不需要依赖 XA 这种粗糙的加锁方式。工作相关,就不在这里回答了。

■网友
这是一个很有趣的问题,值得讨论。我理解,这里XA要求下层使用serializable隔离级别,等价于读加长谓词锁和长写锁,所有读写都这么做且是两阶段锁,是能避免脏读的。而且,这样得到的XA事务也是serializable的。因为这里XA事务没有中心节点推进事务版本或者true time,似乎想不到提供repeatable read而非serializable的其他方法。
■网友
【XA事务的隔离级别算啥级别】 我觉得第一个问题,读提交(Read committed),我也不是很懂XA,事务,这些的,XA在预提交阶段,数据并不会入库,但会写入到XA日志文件中(5.6以支持),得到响应之后才会正式入库,只要是写入了XA日志文件,就算在正式入库时连接错误,也可以在次提交入库,所以说是不会出现(脏读)

■网友
问题1.MySQL中SERIALIZABLE级别读操作加读锁、写操作加写锁,REPEATABLE READ级别读操作不加锁,采用多版本读,写操作加写锁。在MySQL的XA事务中,由于REPEATABLE READ的多版本读是本地多版本不是全局多版本,会导致读取不一致的数据,也就是脏读。
下面给出REPEATABLE READ级别的一个操作案例
T1从A账户转X元转到B账户,A,B账户分别在两个节点。T2读取A与B账户的总额。
XA事务的隔离级别算啥级别

在t6时刻,T2读取的账户总额是A+X+B,是脏数据。
如果采用SERIALIZABLE,读写均加锁,可以避免上面的结果。
问题2.MySQL中XA采用SERIALIZABLE级别,全局事务可以达到SERIALIZABLE的级别。但是大量的读锁会耗费很多资源,同时在读写并发时,会带来更多的等待时间。这也是为什么采用mvcc多版本的原因。PG社区中,有PGXC和PGXL的方案,采用的并发机制是全局mvcc+本地写锁。PGXC是维持了全局活跃事务列表,从而提供全局mvcc。在上面的案例中,在t6时刻,由于全局事务没有结束,T2从节点1读到A,从节点2读到B,总额是A+B。


推荐阅读