mysql事务怎么实现的,什么是两阶段提交

mysql事务怎么实现的,什么是两阶段提交

我们都知道使用mysql的事务,准确来说是innoDB引擎的事务,可以保证数据的一致性,原子性等。那么为什么呢?

redo log

innoDB里面用到了一个叫做redo log(重做日志)的东西。

当你进行数据库操作的时候,innoDB并不会直接操作磁盘数据,因为这样很慢很慢。它使用了wal的机制,所有的操作先记录在redo log。等没事干了或者redo log满了再把数据刷到磁盘里面。这样的话他刷盘的时候就是顺序io,避免了使用随机io。redo log的大小我们可以通过参数设置。

缓冲池

在innoDB里面还有一个缓冲池,buffer_pool,这个缓冲池是在内存中的。为啥有缓冲池,因为磁盘的速度太慢了,如果每次都直接操作磁盘,那就完犊子了。就需要用到内存来缓冲一下,提升性能。

从innoDB里面读取数据的时候,实际上读取的是缓冲池,只有当缓冲池中没有记录的时候,才会读取磁盘,并且将记录放入缓冲池方便下次读取。

缓冲池的大小可以通过innodb_buffer_pool_size参数来指定。

缓存池中基本有以下组件:

  • 索引页
  • 数据页
  • undo页
  • 插入缓冲(insert buffer)
  • 自适应哈希索引
  • 锁信息
  • 数据字典
  • redo log buffer

缓冲池既然是在内存中,有固定大小,就会有淘汰机制,缓冲池使用的是LRU机制,也就是最近最少使用的会被淘汰掉。

这里面还有一个redo log buffer,这里面存储的就是上面说的redo log的信息了,会先写入这个buffer,然后再刷入redo log里面。有一个参数innodb_log_buffer_size来控制redo log buffer的大小。这个不用太大,因为一般每秒都会把这里面的刷新到redo log。

redo log buffer刷新到redo log的三种情况:

  • 每秒刷新
  • 事务提交时候刷新
  • 当redo log buffer剩余空间少于一半的时候刷新

binlog

redo log是innoDB引擎的日志,那mysql自己同样有日志,就是这个binlog日志。binlog 里面记载了mysql的所有变化,可以用来恢复数据库,创建备库,从库等。可以查看我的mysql读写分离

那为什么有两个日志呢,这是因为mysql最开始默认使用的是myisam引擎,myisam引擎没有redo log,mysql就有自己的binlog。innoDB引擎是后来加入mysql的。所以他们各自有各自的日志。

这两个日志有什么区别呢?

  1. rodo log是innoDB引擎的,binlog 是mysql的,binlog所有引擎都可以使用。
  2. redo log记录的是“再某个数据页上修改了啥”,binlog记录的是你的sql。
  3. redo log是固定大小,循环写入的,binlog没有大小限制,不断追加。

事务

那一个事务怎么执行的呢,比如更新一个登录时间。

update user set login_time = ? where id = 1;
  • 走完了前面的连接器,分析器,优化器,执行器。执行器会去innoDB更新数据了。
  • 他会先取出这条数据,取出id = 1的数据,id是主键索引,和数据在一起。innoDB直接查找主键索引树找到对应数据就返回了。当然,如果数据再缓冲池,那么直接返回了。
  • 执行器拿到以后再修改登陆时间,然后再次调用innoDB引擎的接口。
  • innoDB把数据更新到内存中,同时更新redo log,把redo log标记成待提交状态。
  • 执行器写入binlog。
  • 执行器调用innoDB引擎的接口,innoDB把redo log标记成提交状态。

这个时候整个更新事务完成。

为什么要这么做呢?

因为有两个日志的原因,所以两个日志都要写入,要保证这两个日志的一致性。那么如果不使用两阶段提交的方式,直接写入redo log然后写入binlog有什么问题呢?

假设,写完redo log,系统挂了。那么重启后innoDB引擎会根据redo log日志来恢复数据库。这时候数据库里面的数据是正确的。但是binlog丢失了啊。如果你有从库,那么从库的数据就错误了。因为从库的数据是通过binlog同步的。

如果把这两个步骤反过来呢,先写入binlog 再写入redo log呢?

那么就会redo log丢失,数据库实际上没有更新。但是从库通过binlog更新了。还是数据不一致。

所以需要两阶段提交来保证数据一致性。如果这时候写完redo log后挂掉了,因为redo log和binlog都没有数据,所以会回滚事务。
如果binlog和redo log都写入了,但是没有提交,那么重启后会提交事务。这样binlog和数据库就都有数据了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章