美文网首页
mysql--mvcc

mysql--mvcc

作者: 机智的老刘明同志 | 来源:发表于2018-11-12 00:35 被阅读46次

    MVCC:

            从我们的直观理解上来看,要实现数据库的并发访问控制,最简单的做法就是加锁访问,即读的时候不能写(允许多个线程同时读,即共享锁S锁),写的时候不能读(一次最多只能有一个线程对同一份数据进行写操作,即排它锁X锁)。这样的加锁访问,其实并不算是真正的并发。因为它最终实现的是读写串行化,这样数据库的读写性能将会被大大降低。加锁访问其实就是和MVCC相对的LBCC,即基于锁的并发控制,是四种隔离级别中级别最高的Serialize隔离级别。                

            MVCC(多版本并发控制) 则是为了实现数据库的并发控制而设计的一种协议。它主要是为RR事务隔离级别做的。它的最大好处便是,读不加锁,读写不冲突。在MVCC中,读操作可以分成两类,快照读(Snapshot read)和当前读(current read)。

            快照读:读取的是记录的可见版本(可能是历史版本,即最新的数据可能正在被当前执行的事务并发修改),不会对返回的记录加锁

            当前读:读取的是记录的最新版本,并且会对返回的记录加锁,保证其他事务不会并发修改这条记录。

    InnoDB中实现MVCC:

            InnoDB的MVCC实现,是通过保存数据在某个时间点的快照来实现的。一个事务,不管其执行多长时间,其内部看到的数据是一致的。也就是事务在执行的过程中不会相互影响。

            MVCC在每行记录后面保存几个隐藏的列:DATA_TRX_ID,DATA_ROLL_PTR,DB_ROW_ID,DELETE BIT

            DATA_TRX_ID:6字节    标记了最新更新这条行记录的transaction id,每处理一个事务,其值自动+1(删除视为更新,将其标记为已删除)

            DATA_ROLL_PTR:7字节    指向当前记录项的rollback segment的undo log记录(写入回滚段的撤消日志记录),找之前版本的数据就是通过这个指针(若行已更新,则撤消日志记录包含在更新行之前重建行内容所需的信息)

            DB_ROW_ID:6字节  行标识

            DELETE BIT:位用于标识该记录是否被删除,这里的不是真正的删除数据,而是标志出来的删除。真正意义的删除是在commit的时候

    undolog:

            Undo日志记录某数据被修改前的值

    不考虑redo log 的情况下undo log的工作过程  

    redolog:

            用于在实例故障恢复时,继续那些已经commit但数据尚未完全回写到磁盘的事务

            大致的执行过程:begin->用排他锁锁定该行->记录redo log->记录undo log->修改当前行的值,写事务编号,回滚指针指向undo log中的修改前的行

    示例(RR隔离级别):

    SELECT

            1 InnoDB只查找版本早于当前事务版本的数据行(也就是数据行的版本必须小于等于事务的版本),这确保当前事务读取的行都是事务之前已经存在的,或者是由当前事务创建或修改的行

            2 行删除操作的版本一定是未定义的或者大于当前事务的版本号,确定了当前事务开始之前,行没有被删除

    INSERT

            InnoDB为每个新增行记录当前系统版本号作为行版本号。

    DELETE

            InnoDB为每个删除行的记录当前系统版本号作为行的删除标识。

    UPDATE

           变为insert和delete操作的组合,insert的行保存当前版本号为行版本号,delete则保存当前版本号到原来的行作为删除标识。

            由于旧数据并不真正的删除,所以必须对这些数据进行清理,innodb会开启一个后台线程执行清理工作,具体的规则是将删除版本号小于当前系统版本的行删除,这个过程叫做purge。

    相关文章

      网友评论

          本文标题:mysql--mvcc

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