【数据库】Update两阶段提交
为什么要两阶段提交事务提交之后,redo log和bin log 都是需要1持久化到磁盘中,但是这两个是独立的逻辑,可能出现半成功的状态,这样就造成两份日记之间的逻辑不同等。如:
以id=1,name = ‘小明’实行
update stu set name = '小红' where id = 1
会出现如下两种情况:
[*]如果bin log写入了磁盘之后,,Mysql突然宕机了,而redo log还没来得及写入。由于redo log没有写入数据,重启之后主库不存在这条数据,但是从库已经同步了这条数据就会出现,主从不同等的情况
[*]如果在将redo log刷入到磁盘之后,Mysql突然宕机了,而bin log还没来得及写入。Mysql重启后,,通过redo log能将Buffer Pool中id = 1这行数据的name字段更新到‘小红’但是bin log由于没有写入,以是从库中的数据照旧‘小明’,出现了主从不同等的情况
两阶段提交把单个事务提交分为两个阶段,分别是“准备”和“提交”阶段
两阶段提交的过程是怎么样的
当客户端实行commit语句或者在主动提交的情况下,Mysql内部开启一个XA事务,分为两个阶段来完成XA事务的提交https://i-blog.csdnimg.cn/direct/d878aaa718a14809a4764243c08d62bf.png
事务提交的过程分为两个阶段,就是将redo log的写入拆分为两个步骤:prepare和commit,中央在穿插写入bin log,具体步骤如下:
[*]prepare阶段:将XID(内部XA事务的ID)写入到redo log,,同时将redo log对应的事务状态设置为prepare,然后将redo log持久化到磁盘
[*] commit阶段:将XID写入到bin log然后将bin log持久化到磁盘,接着提交事务,将redo log状态设置为commit,此时该状态并不需要持久化到磁盘,只需要写入到文件体系的缓存页中就可以,因为只要bin log写到磁盘中成功,就算redo log状态照旧prepare也没有关系,一样会被认为事务已经实行成功
非常重启会发送什么现象呢
https://i-blog.csdnimg.cn/direct/562ac02aa3c84489a894e0f6ad685f99.png
不管是时刻A(redo log写入磁盘,bin log没有)出现问题照旧时刻B(redo log和bin log都写入到磁盘,但是还没有写入commit标识)崩溃,此时得redo log都是处于prepare的状态
在Mysql重启之后,都会按照次序扫描redo log文件,遇到处于prepare状态的redo log,就会拿着redo log中的XID去bin log中去查找是否存在这个XID:
[*]如果bin log中没有当前内部XA事务的XID,阐明redo log完成了刷盘,但是bin log还没有刷盘,则回滚事务,对应时刻A
[*]如果bin log中有当前内部事务的XID,阐明redo log和bin log都已经完成了刷盘,则提交事务,对应时刻B
可以看到,对于处于prepare阶段的redo log,既可以提交事务,也可以回滚事务,这取决于能否在bin log中查找到与redo log相同的XID,如果有就提交事务,没有就回滚事务。这样就可以保证redo log和 bin log的同等性
两阶段提交出现的问题
两个阶段虽然保证了两个日记文件的数据同等性,但是性能不高,重要的缘故起因是:
[*]磁盘I/O次数过高:每一个事务提交都是需要两次刷盘(redo和bin)
[*]锁竞争激烈:两个阶段虽然可以保证“单个事务”的两个日记同等,但是不能保证“多个事务“情况下,两者提交的次序同等性。因此,在两个阶段提交流程的基础上,还需要加上一个锁来保证提交的原子性,从而保证多事务的情况下,两个日记提交的次序同等
为了办理上诉问题,引用有一个新的技能”组提交“,当多个事务提交的时间,会将多个bin log刷盘操作合并成一个,从而淘汰磁盘I/O的次数。如果10个事务一次列队刷盘的时间成本是10,那么将着10个事务一次性一起刷盘的时间成本近似.
引入组提交及之后,prepare阶段不变,只针对于commit阶段,将commit阶段拆分为三个过程:
[*]flush阶段:多个事务按照将进入的次序将bin log从cache写入文件(不刷盘)
[*]sync阶段:对于bin log文件举行fsyn操作(多个事务的bin log合并有一次刷盘)
[*]commit:各个事务按照次序做InnoDB的提交操作
上面的每一个阶段都有一个队列,每个阶段都有锁举行保证事务写入的次序性,第一个进入队列的事务会成为 leader,leader领导所在队列的所有事务,全权负责整队的操作,完成后通知队内其他事务操作结束
https://i-blog.csdnimg.cn/direct/529fd7b9ba374639b57a52f1be6534c3.png
每个阶段引入队列,锁只是针对队列举行保护,不会锁住整个提交事务的整个过程。锁的粒度减小了,这样就可以多个阶段并发实行,提拔效率
有 binlog 组提交,那有 redo log 组提交吗?
这个要看 MySQL 版本,MySQL 5.6 没有 redo log 组提交,MySQL 5.7 有 redo log 组提交
在 MySQL 5.6 的组提交逻辑中,每个事务各自实行 prepare 阶段,也就是各自将 redo log 刷盘,这样就没办法对 redo log 举行组提交。
以是在 MySQL 5.7 版本中,做了个改进,在 prepare 阶段不再让事务各自实行 redo log 刷盘操作,而是推迟到组提交的 flush 阶段,也就是说 prepare 阶段融合在了 flush 阶段。
这个优化是将 redo log 的刷盘延长到了 fush 阶段之中,sync 阶段之前。通过延长写 redo log 的方式为 redolog 做了一次组写入,这样 binlog 和 redo log 都举行了优化。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]