陆敬尚,Apache ShardingSphere Committer,SphereEx 基础设施研发工程师,热爱开源,热爱数据库技术,目前专注于 Apache ShardingSphere 事务模块的开发。
背景
随着业务的快速发展,数据的不断膨胀,流量负载的增加,业务系统遇到了强烈的挑战,对数据库系统可扩展性提出了强烈的诉求。Oracle、MySQL、SQL Server、PostgreSQL 传统单机数据库在线扩展上的问题日益凸显。为了解决扩展问题,出现了可水平扩展的分布式数据库,于是分布式事务问题成为了必须面对的问题。
在这种背景下,ShardingSphere 提供了一套分布式数据库增强计算引擎,通过可插拔架构构建基于数据库之上的生态系统,提供了分布式事务的能力。
事务介绍
事务语义
事务语义定义了四个特性:原子性(Atomicity)、持久性(Durability)、一致性(Consistency)、隔离性(Isolatation)。
原子性(Atomicity)
在分布式场景下,一个事务的操作可能分布在多个物理节点上,保证在多个节点上的操作都成功,或都不成功。
持久性(Durability)
事务提交后,即使断电,事务的操作也是有效的。
一致性(Consistency)
注意:不是 CAP 理论中 C,CAP 中的 C 指的是多副本之间的数据一致问题,这里是不同层次的抽象。
站在用户的角度,数据从一个状态,转移到另外一个状态,两个状态都满足一定的约束。比如:
银行账户数据,账户 A 有 500 元,账户 B 有 500 元,总额 1000,在一个事务中,执行完 A 和 B 的转账操作后,A 和 B 的账户总额还是 1000。
隔离性(Isolatation)
事务并发执行时,保证并发时数据的正确性。比如:两个事务同时修改一条数据,保证两个事务按一定顺序执行,使数据保持在一个正确的状态。
面临的挑战
分布式事务相对单机事务来说面临下面的挑战:
- 原子性,对于单机事务来说,使用 undo log 和 redo log 就可以保证全部提交或者全部回滚。而分布式事务涉及多个物理节点,每个节点情况是不同的,有的节点日志写成功,有的节点日志写不成功。
- 网络的不稳定,对于单机来说,通讯是稳定的,任何操作都可以得到回复,不论成功与失败。而分布式场景下,网络是不稳定的,有可能一个操作是得不到回复的,怎样保证分布式事务的可用性(异常事务的清理、恢复等)是一个问题。
- 并发控制,随着 MVCC 的出现,操作的可线性化(linearizable)成为了刚需。在单机数据库中,可以很容易地产生全局单调递增的事务号,在分布式场景中则不然。
解决方案
原子提交
针对原子性和网络不稳定问题,目前主流的解决方案是 2PC,2PC 定义了两个角色 TM(Transaction Manager)、RM(Resource Manager)。
在分布式场景下,一个事务的操作可能分布在多个节点上,整个事务分两个阶段。
- 第一阶段,RM 锁定相关资源并执行具体操作,返回成功与否给 TM。
- 第二阶段,TM 更具第一阶段 RM 返回的结果,如果全部成功,执行最后的提交操作(事务状态的更改,锁状态删除等),如果有失败的,则回滚。
说明:当然会有一些优化点,比如不涉及多节点的事务转化为一阶段提交等。
注意:两阶段提交协议只解决了提交的问题,要么提交成功,要么不成功,不存在部分成功的中间状态。和事务隔离级别没有必然关系。
并发控制
并发控制,就是保证并发执行的事务在某一种隔离级别上的执行策略。自从多版本控制(MVCC)出现,主流数据库基本抛弃了以前的两阶段锁模型。
并发控制本质是对数据读和写的并发的控制。并发控制的策略决定了隔离级别,并发控制要解决两个问题。
- 决定并发的粒度,比如 MySQL 有行锁(粒度为一行),表锁(粒度为一个表)等
- 三种并发场景的行为:
a. 读读并发,不需要特殊处理,因为不涉及数据的变更。
b. 写写并发,不能同时并发,否则会产生数据混乱。
c. 读写并发,性能优化主要在这里做,有多种并发控制机制,基本都选择了多版本并发控制(MVCC)。
MVCC 并发控制模型
现有主流实现方式有两种:
- 基于事务 ID 和 ReadView
每次事务获取事务 ID,标识事务的开启顺序,通过活跃事务列表来获取快照,存储多个以事务 ID 为版本的数据,从而达到并发控制的效果。MySQL、Postgres-XL 都是采取的这种方案。
- 基于 timestamp
引入 timestamp,通过在数据中添加 timestamp 相关属性,通过对比数据的 commitTs(commit timestamp) 和 Snapshot timestamp 来判断可见性,从而达到可线性化的并发控制效果。Spanner 采用的这种方案。
上面两种方案都离不开全局事务号的生成,常见的全局事务号生成机制有 TrueTime(Spanner 采用),HLC(CockroachDB 采用有误差的 HLC),TSO(Timestamp Oracle),详细原理见参考文献。
ShardingSphere 事务设计
ShardingSphere 事务功能建立在存储 DB 的本地事务之上,提供 LOCAL、XA、BASE 三种模式事务,使用者只需使用原生事务方式(begin/commit/rollback),就可以使用三种模式,在一致性和性能做合适的权衡。
LOCAL
LOCAL 模式直接建立在存储 DB 的本地事务上的,会存在一定的原子性问题,当然性能是最高的,如果可以容忍这个问题,这将是一个不错的选择。
XA
XA 模式,XA 协议是基于 2PC 定义的一套交互协议,定义了 xa start/prepare/end/commit/rollback 等接口,常用的实现有 Narayana、Atomics, ShardingSphere 集成了 Narayana、Atomics 的 XA 实现。
- app 连接到 Proxy 上,Proxy 创建一个 session 的对象和这个 connection 绑定。
- app 执行 begin,Proxy 通过 Narayana TM 新建一个逻辑 transaction,和当前 session 绑定。
- app 执行具体 SQL,session 负责建立到存储 DB 的 connection,并把 connection 通过 Transaction.enlistResource() 接口把 connection 注册到 transaction,执行 XA START {XID} 开启事务,并执行路由改写后的 SQL。
- app 执行 commit 命令,transaction 中注册的连接存储 DB 的 connection,分别执行 xa prepare,当所有 connection 返回 ok,更新 transaction 状态为 prepared,每个 connection 执行 xa commit,都返回 ok 更新 transaction 状态为 commited,提交成功。如果 prepare 过程部分失败,用户可以通过 rollback 命令出发回滚,不处理则有后台进程进行清理。
- app 执行 rollback 命令,transaction 中注册的连接存储 DB 的 connection,分别执行 xa rollback,进行回滚。
BASE
Base(Basically Available, Soft State, Eventually Consistent)模式,BASE 事务是 CAP 理论中 C 和 A 权衡的结果,Seata 的 AT 模式是 Base 事务的一种实现,ShardingSphere 集成了 Seata 的 AT 实现。
- app 连接到 Proxy 上,Proxy 创建一个 session 的对象和这个 connection 绑定。
- app 执行 begin,Proxy 通过 Seata TM 新建一个逻辑 transaction,和当前 session 绑定,并注册到 Seata Server。
- app 执行一条逻辑 SQL,session 负责建立到存储 DB 的 connection,每个 connection 是 Seata 的 ConnectionProxy 实例,对路由改写后的 actual sql 进行解析, 做一些拦截,比如:如果是修改操作,执行 begin 获取本地锁,执行一条 SQL, 执行 commit 释放本地锁,上报分支事务结果到 Seata Server。
- app 执行 commit 命令,Proxy 中的 Seata TM 通知 Seata Server 后,直接返回 app,Seata Server 异步和 Proxy 交互,进行删除事务日志。
- app 执行 rollback 命令,Proxy 中的 Seata TM 通知 Seata Server 后,直接返回 app,Seata Server 异步和 Proxy 交互,执行补偿操作,删除事务日志。
详细流程参考 Seata 官网。
使用示例
安装包准备
以支持较好的 XA,集成 Narayana 的实现为例,进行介绍。由于 Narayana 的 License 问题,不能直接打包到安装包内,需要添加额外的依赖。
根据官网下载好安装包,解压到 ${ShardingSphere} 目录,往 ${ShardingSphere}/lib 目录下添加以下 jar 包。(下载地址:https://mvnrepository.com/)
<div class="output_wrapper" id="output_wrapper_id" style="font-size: 16px; color: rgb(62, 62, 62); line-height: 1.6; word-spacing: 0px; letter-spacing: 0px; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', 'Microsoft YaHei', Arial, sans-serif;"><pre style="font-size: inherit; color: inherit; line-height: inherit; margin: 0px; padding: 0px;">jta<span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">-5.12</span><span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">.4</span>.<span class="hljs-keyword" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(149, 90, 231); word-wrap: inherit !important; word-break: inherit !important;">Final</span>.jar
arjuna<span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">-5.12</span><span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">.4</span>.<span class="hljs-keyword" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(149, 90, 231); word-wrap: inherit !important; word-break: inherit !important;">Final</span>.jar
common<span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">-5.12</span><span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">.4</span>.<span class="hljs-keyword" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(149, 90, 231); word-wrap: inherit !important; word-break: inherit !important;">Final</span>.jar
jboss-connector-api_1<span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">.7</span>_spec<span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">-1.0</span><span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">.0</span>.<span class="hljs-keyword" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(149, 90, 231); word-wrap: inherit !important; word-break: inherit !important;">Final</span>.jar | ------------------------------------------------------------------------------------------------------------------------------------
jboss-logging<span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">-3.2</span><span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">.1</span>.<span class="hljs-keyword" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(149, 90, 231); word-wrap: inherit !important; word-break: inherit !important;">Final</span>.jar | ------------------------------------------------------------------------------------------------------------------------------------
jboss-transaction-api_1<span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">.2</span>_spec<span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">-1.0</span><span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">.0</span>.Alpha3.jar | ------------------------------------------------------------------------------------------------------------------------------------
jboss-transaction-spi<span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">-7.6</span><span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">.0</span>.<span class="hljs-keyword" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(149, 90, 231); word-wrap: inherit !important; word-break: inherit !important;">Final</span>.jar
mysql-connector-java<span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">-5.1</span><span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">.47</span>.jar | ------------------------------------------------------------------------------------------------------------------------------------
narayana-jts-integration<span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">-5.12</span><span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">.4</span>.<span class="hljs-keyword" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(149, 90, 231); word-wrap: inherit !important; word-break: inherit !important;">Final</span>.jar
shardingsphere-transaction-xa-narayana<span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">-5.1</span><span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">.1</span>-SNAPSHOT.jar
MySQL 实例准备
- 准备两个 MySQL 实例,127.0.0.1:3306,127.0.0.1:3307。
- 两个 MySQL 实例分别创建用户 root, 密码为 12345678。
- 两个 MySQL 实例分别创建 test 库。
ShardingSphere-Proxy 配置
修改 server.yaml 事务配置
<div class="output_wrapper" id="output_wrapper_id" style="font-size: 16px; color: rgb(62, 62, 62); line-height: 1.6; word-spacing: 0px; letter-spacing: 0px; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', 'Microsoft YaHei', Arial, sans-serif;"><pre style="font-size: inherit; color: inherit; line-height: inherit; margin: 0px; padding: 0px;"><span class="hljs-symbol" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(42, 146, 146); word-wrap: inherit !important; word-break: inherit !important;">rules:</span>
- !AUTHORITY
<span class="hljs-symbol" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(42, 146, 146); word-wrap: inherit !important; word-break: inherit !important;">users:</span>
- root@%<span class="hljs-symbol" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(42, 146, 146); word-wrap: inherit !important; word-break: inherit !important;">:root</span>
- sharding@<span class="hljs-symbol" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(42, 146, 146); word-wrap: inherit !important; word-break: inherit !important;">:sharding</span>
<span class="hljs-symbol" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(42, 146, 146); word-wrap: inherit !important; word-break: inherit !important;">provider:</span>
<span class="hljs-symbol" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(42, 146, 146); word-wrap: inherit !important; word-break: inherit !important;">type:</span> ALL_PRIVILEGES_PERMITTED
- !TRANSACTION
<span class="hljs-symbol" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(42, 146, 146); word-wrap: inherit !important; word-break: inherit !important;">defaultType:</span> XA
<span class="hljs-symbol" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(42, 146, 146); word-wrap: inherit !important; word-break: inherit !important;">providerType:</span> Narayana
修改 conf/conf-sharding.yaml
<div class="output_wrapper" id="output_wrapper_id" style="font-size: 16px; color: rgb(62, 62, 62); line-height: 1.6; word-spacing: 0px; letter-spacing: 0px; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', 'Microsoft YaHei', Arial, sans-serif;"><pre style="font-size: inherit; color: inherit; line-height: inherit; margin: 0px; padding: 0px;">dataSources:
ds_0:
url: jdbc:mysql://127.0.0.1:3306/<span class="hljs-built_in" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">test</span>?serverTimezone=UTC&allowPublicKeyRetrieval=<span class="hljs-literal" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">true</span>&useSSL=<span class="hljs-literal" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">false</span>
username: root
password: 12345678
connectionTimeoutMilliseconds: 30000
idleTimeoutMilliseconds: 60000
maxLifetimeMilliseconds: 1800000
maxPoolSize: 50
minPoolSize: 1
ds_1:
url: jdbc:mysql://127.0.0.1:3307/<span class="hljs-built_in" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">test</span>?serverTimezone=UTC&allowPublicKeyRetrieval=<span class="hljs-literal" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">true</span>&useSSL=<span class="hljs-literal" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">false</span>
username: root
password: 12345678
connectionTimeoutMilliseconds: 30000
idleTimeoutMilliseconds: 60000
maxLifetimeMilliseconds: 1800000
maxPoolSize: 50
minPoolSize: 1
rules:
- !SHARDING
tables:
account:
actualDataNodes: ds_<span class="hljs-variable" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(190, 70, 120); word-wrap: inherit !important; word-break: inherit !important;">${0..1}</span>.account<span class="hljs-variable" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(190, 70, 120); word-wrap: inherit !important; word-break: inherit !important;">${0..1}</span>
tableStrategy:
standard:
shardingColumn: id
shardingAlgorithmName: account_inline
keyGenerateStrategy:
column: id
keyGeneratorName: snowflake
defaultDatabaseStrategy:
standard:
shardingColumn: id
shardingAlgorithmName: database_inline
defaultTableStrategy:
none:
shardingAlgorithms:
database_inline:
<span class="hljs-built_in" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">type</span>: INLINE
props:
algorithm-expression: ds_<span class="hljs-variable" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(190, 70, 120); word-wrap: inherit !important; word-break: inherit !important;">${id % 2}</span><br> account_inline:<br> <span class="hljs-built_in" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">type</span>: INLINE<br> props:<br> algorithm-expression: account<span class="hljs-variable" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(190, 70, 120); word-wrap: inherit !important; word-break: inherit !important;">${id % 2}</span>
keyGenerators:
snowflake:
<span class="hljs-built_in" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">type</span>: SNOWFLAKE
props:
worker-id: 123
启动ShardingSphere-Proxy
参考如下命令启动 Proxy:
<div class="output_wrapper" id="output_wrapper_id" style="font-size: 16px; color: rgb(62, 62, 62); line-height: 1.6; word-spacing: 0px; letter-spacing: 0px; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', 'Microsoft YaHei', Arial, sans-serif;"><pre style="font-size: inherit; color: inherit; line-height: inherit; margin: 0px; padding: 0px;"><span class="hljs-built_in" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">cd</span> <span class="hljs-variable" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(190, 70, 120); word-wrap: inherit !important; word-break: inherit !important;">${ShardingSphere}</span>
./bin/start.sh
使用 ShardingSphere-Proxy
使用 MySQL Client 连接 ShardingSphere-Proxy 进行测试,参考如下命令。
<div class="output_wrapper" id="output_wrapper_id" style="font-size: 16px; color: rgb(62, 62, 62); line-height: 1.6; word-spacing: 0px; letter-spacing: 0px; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', 'Microsoft YaHei', Arial, sans-serif;"><pre style="font-size: inherit; color: inherit; line-height: inherit; margin: 0px; padding: 0px;"><span class="hljs-selector-tag" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(149, 90, 231); word-wrap: inherit !important; word-break: inherit !important;">mysql</span> <span class="hljs-selector-tag" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(149, 90, 231); word-wrap: inherit !important; word-break: inherit !important;">-h127</span><span class="hljs-selector-class" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(190, 70, 120); word-wrap: inherit !important; word-break: inherit !important;">.0</span><span class="hljs-selector-class" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(190, 70, 120); word-wrap: inherit !important; word-break: inherit !important;">.0</span><span class="hljs-selector-class" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(190, 70, 120); word-wrap: inherit !important; word-break: inherit !important;">.1</span> <span class="hljs-selector-tag" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(149, 90, 231); word-wrap: inherit !important; word-break: inherit !important;">-P3307</span> <span class="hljs-selector-tag" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(149, 90, 231); word-wrap: inherit !important; word-break: inherit !important;">-uroot</span> <span class="hljs-selector-tag" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(149, 90, 231); word-wrap: inherit !important; word-break: inherit !important;">-proot</span>
<div class="output_wrapper" id="output_wrapper_id" style="font-size: 16px; color: rgb(62, 62, 62); line-height: 1.6; word-spacing: 0px; letter-spacing: 0px; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', 'Microsoft YaHei', Arial, sans-serif;"><pre style="font-size: inherit; color: inherit; line-height: inherit; margin: 0px; padding: 0px;">mysql> use sharding_db;
Database changed
mysql> <span class="hljs-function" style="font-size: inherit; color: inherit; line-height: inherit; margin: 0px; padding: 0px; word-wrap: inherit !important; word-break: inherit !important;">create table <span class="hljs-title" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(87, 109, 219); word-wrap: inherit !important; word-break: inherit !important;">account</span>(<span class="hljs-params" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">id <span class="hljs-keyword" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(149, 90, 231); word-wrap: inherit !important; word-break: inherit !important;">int</span>, balance <span class="hljs-keyword" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(149, 90, 231); word-wrap: inherit !important; word-break: inherit !important;">float</span> ,transaction_id <span class="hljs-keyword" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(149, 90, 231); word-wrap: inherit !important; word-break: inherit !important;">int</span></span>)</span>;
Query OK, <span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">0</span> <span class="hljs-function" style="font-size: inherit; color: inherit; line-height: inherit; margin: 0px; padding: 0px; word-wrap: inherit !important; word-break: inherit !important;">rows <span class="hljs-title" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(87, 109, 219); word-wrap: inherit !important; word-break: inherit !important;">affected</span> (<span class="hljs-params" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;"><span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">0.12</span> sec</span>)
mysql> <span class="hljs-keyword" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(149, 90, 231); word-wrap: inherit !important; word-break: inherit !important;">select</span> <span class="hljs-keyword" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(149, 90, 231); word-wrap: inherit !important; word-break: inherit !important;">from</span> account</span>;
<span class="hljs-function" style="font-size: inherit; color: inherit; line-height: inherit; margin: 0px; padding: 0px; word-wrap: inherit !important; word-break: inherit !important;">Empty <span class="hljs-title" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(87, 109, 219); word-wrap: inherit !important; word-break: inherit !important;">set</span> (<span class="hljs-params" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;"><span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">0.02</span> sec</span>)
mysql> begin</span>;
Query OK, <span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">0</span> <span class="hljs-function" style="font-size: inherit; color: inherit; line-height: inherit; margin: 0px; padding: 0px; word-wrap: inherit !important; word-break: inherit !important;">rows <span class="hljs-title" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(87, 109, 219); word-wrap: inherit !important; word-break: inherit !important;">affected</span> (<span class="hljs-params" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;"><span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">0.09</span> sec</span>)
mysql> insert <span class="hljs-keyword" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(149, 90, 231); word-wrap: inherit !important; word-break: inherit !important;">into</span> <span class="hljs-title" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(87, 109, 219); word-wrap: inherit !important; word-break: inherit !important;">account</span>(<span class="hljs-params" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">id, balance, transaction_id</span>) <span class="hljs-title" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(87, 109, 219); word-wrap: inherit !important; word-break: inherit !important;">values</span>(<span class="hljs-params" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;"><span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">1</span>,<span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">1</span>,<span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">1</span></span>),(<span class="hljs-params" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;"><span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">2</span>,<span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">2</span>,<span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">2</span></span>)</span>;
Query OK, <span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">2</span> <span class="hljs-function" style="font-size: inherit; color: inherit; line-height: inherit; margin: 0px; padding: 0px; word-wrap: inherit !important; word-break: inherit !important;">rows <span class="hljs-title" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(87, 109, 219); word-wrap: inherit !important; word-break: inherit !important;">affected</span> (<span class="hljs-params" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;"><span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">0.53</span> sec</span>)
mysql> <span class="hljs-keyword" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(149, 90, 231); word-wrap: inherit !important; word-break: inherit !important;">select</span> <span class="hljs-keyword" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(149, 90, 231); word-wrap: inherit !important; word-break: inherit !important;">from</span> account</span>;
+------+---------+----------------+
| id | balance | transaction_id |
+------+---------+----------------+
| <span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">2</span> | <span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">2.0</span> | <span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">2</span> |
| <span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">1</span> | <span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">1.0</span> | <span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">1</span> |
+------+---------+----------------+
<span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">2</span> <span class="hljs-function" style="font-size: inherit; color: inherit; line-height: inherit; margin: 0px; padding: 0px; word-wrap: inherit !important; word-break: inherit !important;">rows <span class="hljs-keyword" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(149, 90, 231); word-wrap: inherit !important; word-break: inherit !important;">in</span> <span class="hljs-title" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(87, 109, 219); word-wrap: inherit !important; word-break: inherit !important;">set</span> (<span class="hljs-params" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;"><span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">0.03</span> sec</span>)
mysql> commit</span>;
Query OK, <span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">0</span> <span class="hljs-function" style="font-size: inherit; color: inherit; line-height: inherit; margin: 0px; padding: 0px; word-wrap: inherit !important; word-break: inherit !important;">rows <span class="hljs-title" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(87, 109, 219); word-wrap: inherit !important; word-break: inherit !important;">affected</span> (<span class="hljs-params" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;"><span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">0.05</span> sec</span>)
mysql> <span class="hljs-keyword" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(149, 90, 231); word-wrap: inherit !important; word-break: inherit !important;">select</span> * <span class="hljs-keyword" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(149, 90, 231); word-wrap: inherit !important; word-break: inherit !important;">from</span> account</span>;
+------+---------+----------------+
| id | balance | transaction_id |
+------+---------+----------------+
| <span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">2</span> | <span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">2.0</span> | <span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">2</span> |
| <span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">1</span> | <span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">1.0</span> | <span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">1</span> |
+------+---------+----------------+
<span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">2</span> <span class="hljs-function" style="font-size: inherit; color: inherit; line-height: inherit; margin: 0px; padding: 0px; word-wrap: inherit !important; word-break: inherit !important;">rows <span class="hljs-keyword" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(149, 90, 231); word-wrap: inherit !important; word-break: inherit !important;">in</span> <span class="hljs-title" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(87, 109, 219); word-wrap: inherit !important; word-break: inherit !important;">set</span> (<span class="hljs-params" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;"><span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(170, 87, 60); word-wrap: inherit !important; word-break: inherit !important;">0.02</span> sec</span>)
</span>
未来规划
现在 ShardingSphere 的分布式事务集成了第三方的 2PC 实现方案,提供了原子性的保证,隔离性依赖于存储 DB 的隔离保证,提供了可用的事务功能。未来基于全局 Timestamp 实现 MVCC,结合 2PC,对事务隔离语义提供更好的支持。欢迎大家关注 ShardingSphere 的成长。
如果大家对 Apache ShardingSphere 有任何疑问或建议,欢迎在 GitHub issue 列表提出,或可前往中文社区交流讨论。
GitHub issue:https://github.com/apache/shardingsphere/issues
贡献指南:https://shardingsphere.apache.org/community/cn/contribute/
中文社区:https://community.sphere-ex.com/
参考文献
1.ACID wiki:https://en.wikipedia.org/wiki/ACID
2.ANSI isolation levels:https://renenyffenegger.ch/notes/development/databases/SQL/transaction/isolation-level
3.《Distributed Transactions Are Evil》:https://wiki.c2.com/?DistributedTransactionsAreEvil
4.《Distributed transactions and why you should care》:https://towardsdatascience.com/distributed-transactions-and-why-you-should-care-116b6da8d72
5.《Fault-Tolerant Stream Processing at Internet Scale》:http://static.googleusercontent.com/media/research.google.com/en/us/pubs/archive/41378.pdf
6.《Oracle Two Phase Commit 2PC Tips》:http://www.dba-oracle.com/t_two_phase_commit_2pc.htm
7.《2PC: Concurrency Control and Recovery in Database Systems》:https://courses.cs.washington.edu/courses/cse551/09au/papers/CSE550BHG-Ch7.pdf
8.《An Empirical Evaluation of In-Memory Multi-Version Concurrency Control》:https://15721.courses.cs.cmu.edu/spring2018/papers/05-mvcc1/wu-vldb2017.pdf
9.《Concurrency Control And Recovery In Database Systems》:https://courses.cs.washington.edu/courses/cse551/09au/papers/CSE550BHG-Ch7.pdf
10.《Optimistic Concurrency Control》:[https://15721.courses.cs.cmu....)]()
11.《Base: An Acid Alternative》:https://queue.acm.org/detail.cfm?id=1394128
12.《Jepsen: CockroachDB beta-20160829》:https://jepsen.io/analyses/cockroachdb-beta-20160829
13.《Spanner: Google’s Globally-Distributed Database》:https://static.googleusercontent.com/media/research.google.com/en//archive/spanner-osdi2012.pdf
欢迎添加社区经理微信(ss_assistant_1)加入交流群,与众多 ShardingSphere 爱好者一同交流。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。