美文网首页
InnoDB是怎样支持高并发的?

InnoDB是怎样支持高并发的?

作者: packet | 来源:发表于2019-02-21 19:31 被阅读0次

    世界是由矛盾组成的,并发的矛盾是什么?线程安全和线程效率,要保证线程安全,就得保证秩序(在处理临界资源的时候),所以难免有些线程需要等待,但这样会降低吞吐量。
    为什么Innodb会在当今大行其道?就是因为其有优秀的并发能力。这篇文章就主要谈谈这个问题。
    Innodb控制并发的手段有两个:锁 和 MVCC
    一 锁
    1.普通锁:读写都加锁,本质上是串行的。
    2.共享锁和排他锁(Share Locks,记为S;eXclusive Locks,记为X),只有两个共享锁不互斥,也就是说多个读操作是可以并行的,而读写操作是不能并行的。

    二 MVCC
    MVCC的核心思想是数据的多版本。
    当有写操作的是时候,data会可克隆出一个新版本V1,写操作操作的是V1,而读操作将读取老版本V0的数据。

    总结:
    普通锁:串行
    共享锁和排他锁:读读并行
    MVCC:读写并行

    那老数据是存储在什么地方呢?这里先介绍两个概念。

    什么是redo日志?
    数据库事务提交以后,不会马上刷新到磁盘上,因为磁盘随机IO性能太低,这样会影响数据库的吞吐量。
    优化方案是将写操作先写到redo日志里,这样就变成了顺序IO,再定期刷新到磁盘上,这样就能提高效率了。
    假设某个时刻数据库崩溃,有些数据还没有刷新到磁盘上,那么数据库重启后,会重做redo日志里的内容。

    什么是undo日志?
    数据库事务未提交时,修改前的数据的旧版本会存储在undo日志里,当数据库崩溃或者事务回滚时,会回恢复undo日志里的内容。

    总结:
    redo日志:保障已提交事务的acid特性
    undo日志:保障未提交事务的acid特性

    当数据库对数据做修改的时候,需要把数据页从磁盘读到buffer pool中,然后在buffer pool中进行修改,那么这个时候buffer pool中的数据页就与磁盘上的数据页内容不一致,称buffer pool的数据页为dirty page 脏数据,如果这个时候发生非正常的DB服务重启,那么这些数据还没在内存,并没有同步到磁盘文件中(注意,同步到磁盘文件是个随机IO),也就是会发生数据丢失,如果这个时候,能够在有一个文件,当buffer pool 中的data page变更结束后,把相应修改记录记录到这个文件(注意,记录日志是顺序IO),那么当DB服务发生crash的情况,恢复DB的时候,也可以根据这个文件的记录内容,重新应用到磁盘文件,数据保持一致。

    什么是回滚段?
    回滚段是undo日志的一种组织形式,UNDO内部由多个回滚段组成

    现在回到MVCC,旧版本数据存储在什么地方呢?
    就是存储在undo日志里。回滚段里存储的就是历史数据的快照,它们不会改变,其他事务可以肆无忌惮地读取这些数据快照。
    可见,innodb高并发的实现关键就是拥有多版本并发控制(Multi Version Concurrency Control, MVCC),通过读取旧版本数据(历史数据的快照)来实现并发。

    那么select读取的是什么?
    select * from t where id>2;
    这一句是快照读,不需要加锁。
    select * from t where id>2 lock in share mode;
    select * from t where id>2 for update;
    这两句显式加锁,是非快照读。

    以下是《高性能MySQL》中的描述:

    MVCC的定义:多版本控制: 指的是一种提高并发的技术。最早的数据库系统,只有读读之间可以并发,读写,写读,写写都要阻塞。引入多版本之后,只有写写之间相互阻塞,其他三种操作都可以并行,这样大幅度提高了InnoDB的并发度。
    InnoDB是在undo log中实现的,通过undo log可以找回数据的历史版本。找回的数据历史版本可以提供给用户读(按照隔离级别的定义,有些读请求只能看到比较老的数据版本),也可以在回滚的时候覆盖数据页上的数据。在InnoDB内部中,会记录一个全局的活跃读写事务数组,其主要用来判断事务的可见性。
    MVCC只在 READ COMMITTED 和 REPEATABLE READ 两个隔离级别下工作。其他两个隔离级别够和MVCC不兼容, 因为 READ UNCOMMITTED 总是读取最新的数据行, 而不是符合当前事务版本的数据行。而 SERIALIZABLE 则会对所有读取的行都加锁。

    参考:
    MySQL-InnoDB-MVCC多版本并发控制
    InnoDB并发如此高,原因竟然在这?
    说说MySQL中的Redo log Undo log都在干啥

    相关文章

      网友评论

          本文标题:InnoDB是怎样支持高并发的?

          本文链接:https://www.haomeiwen.com/subject/eovdyqtx.html