Sharding-JDBC 的事务处理小结

Sharding-JDBC 是由当当网推出的一款开源的分布式数据库中间件。它以 JDBC 的形式嵌入到应用程序中,无需额外部署。Sharding-JDBC 实现了分库分表、读写分离和分布式主键功能,并初步实现了柔性事务。

本文主要介绍 Sharding-JDBC 的事务处理。

Overview

Sharding-JDBC 由于性能方面的考量,决定不支持强一致性分布式事务。我们已明确规划线路图,未来会支持最终一致性的柔性事务。

  • 默认使用 “弱XA” 事务
  • 可选使用柔性事务:
    • BED(最大努力送达型)事务
    • TCC(补偿型)事务

“弱XA”事务

之所以加引号,是因为这个和 MySQL 的 XA 其实没有关系。

它的实现是很自然的:

  • Prepare 阶段(执行 SQL)过程遇到异常,则中止当前事务,对所有分库上的事务连接执行 conn.rollback()
  • Commit 阶段(提交事务)时对所有分库依次(其实可以并行)做 conn.commit();如果某个事务连接 commit 时抛出异常,由于无法回滚其他连接,所以仅仅是收集起来报给调用者,交由用户处理。不影响其他分库 commit。

文档中对使用注意事项也写的很明确:

不支持因网络、硬件异常导致的跨库事务。例如:同一事务中,跨两个库更新,更新完毕后、未提交之前,第一个库死机,则只有第二个库数据提交。

柔性事务

分布式场景下传统数据库 ACID 无法满足业务的性能要求,所以诞生了 BASE 理论。BASE是 Basically Available(基本可用)、Soft state(软状态)和 Eventually consistent(最终一致性)三个短语的简写,其中软状态是指允许系统中的数据存在中间状态。

Sharding-JDBC 的柔性事务是需要调用者显式开启的。以 BED 事务为例,客户需要先通过柔性事务管理器创建出 BEDSoftTransaction 对象,然后使用 begin() 开始柔性事务。

BED(最大努力送达型)事务

用户保证该数据库的操作最终一定可以成功,所以通过最大努力反复尝试

结合上图,执行过程可以分为 4 种情况:

  1. 同步执行成功
  2. 同步执行失败,同步重试成功
  3. 同步执行失败,同步重试失败,异步重试成功
  4. 同步执行失败,同步重试失败,异步重试失败,事务日志保留(人工介入处理)

BED 不保证 exactly once,所以使用 BED 的 SQL 需要满足幂等性,例如不能用 UPDATE SET x = x + 1 这样的 SQL。

TCC(补偿型)事务

目前还在规划中,没有实现。

参考资料