加入收藏 | 设为首页 | 会员中心 | 我要投稿 PHP编程网 - 襄阳站长网 (https://www.0710zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 建站 > 正文

事务系统实现模式很简单?你确定没忽视这些差异?

发布时间:2019-02-21 04:36:53 所属栏目:建站 来源:hellocode
导读:副标题#e# 本文试图讨论这几个问题: MySQL的redo log和binlog为什么要用XA? MongoDB的oplog是按照什么顺序复制? Raft真的只能串行Apply吗? 数据库的复制和事务是完全独立的两回事? 为什么MySQL不早点做一个Raft插件,直接用Raft实现高可用? 本文旨在阐述Fa

由于直接复制Journal会引起一系列复杂的耦合问题,大部分数据库都选择单独写一个binlog/oplog来实现复制,不过在实现时可以做优化,因为如果真的写两个log会有原子性的问题(一个写成功了另一个没写成功)以及IO放大的问题。

这里的设计空间比较庞大,不做详细讨论,仅仅考虑在简化的模型下复制顺序的问题。

事务系统实现模式很简单?你确定没忽视这些差异?

对于并发执行的事务,为了确定复制顺序,这里维护一个称之为OpTime的自增ID。后续的复制会按照OpTime的顺序,OpTime小的先复制。如果OpTime仅仅是在事务的开始和结束之间分配,会带来问题:

  • 有冲突且并发的事务T1先Commit,具有较大的OpTime,也就意味会被后复制;
  • 后Commit的事务T2先Replication Commit,而先Commit的事务T1可能因为复制失败而Rollback;
  • 对于事务来说,这种场景下出现的异常类似Read-Uncommitted,事务T2读到了未Commit的数据。

因此,OpTime的分配需要有更强的限制:对于并发且有冲突的事务,OpTime的顺序要和事务的Serialization Order一样:

事务系统实现模式很简单?你确定没忽视这些差异?

在S2PL的场景中,我们把OpTime分配放到Lock之后Commit之前,即可满足这个要求。因为按照S2PL的调度,事务的Commit-Point就是Lock完成和Unlock之间。对照上面的例子,事务T2的OpTime被推迟到T1之后,复制的顺序也会相应改变,不会发生先前的异常了。

事务系统实现模式很简单?你确定没忽视这些差异?

推广到其他的并发控制方法也是类似,例如上面的Snapshot Isolation。提交之前会检查[begin, end]是否有冲突,有冲突直接重启事务。相当于在[begin, end]区间内分配OpTime即可。

这种方法通过OpTime,保留了Transaction Serialization Order和RSM的Order之间的关系:

  • 并发且有冲突的事务,其OpTime的顺序和事务Serialization Order一样;
  • 并发但没有冲突的事务,其OpTime顺序不确定,因为谁先提交都不会影响正确性;
  • 有先于关系的事务,OpTime也一定满足这个先于关系。

不过这里留下了一个问题,留待读者思考:

如何按照OpTime复制,因为有事务Abort的情况,OpTime做不到连续自增,仅仅是单调自增。

二、对比

第一种其实是Spanner,第二种是TiKV、Percolator,第三种是MySQL、MongoDB。

(编辑:PHP编程网 - 襄阳站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!