美文网首页
mysql事务隔离级别

mysql事务隔离级别

作者: Easy的幸福 | 来源:发表于2019-10-14 15:59 被阅读0次
    msyql的事务隔离级别如下:
    • Read uncommitted(未提交读)

    事务中的修改,即使没有提交,对其它事务也是可见的. 脏读(Dirty Read).

    • Read committed(提交读)

    一个事务开始时,只能"看见"已经提交的事务所做的修改. 这个级别有时候也叫\color{red}{不可重复读}

    • Repeatable read(可重复读) 这是myslq默认的隔离级别
    • Serializable(串行化)

    强制事务串行执行,避免了上面说到的 脏读,不可重复读,幻读 三个的问题.

    mysql默认的隔离级别其实是没有解决可重复读和幻读的问题,但是它还是给解决了。
    mvcc多版本并发控制(Multi-Version Concurrency Control)

    InnoDB的MVCC是通过在每行记录后面保存2个隐藏的列来实现的,一列保存了行的创建时间,一列保存了行的过期时间(或删除时间),但它们实际都存储的是系统版本号。

    \color{red}{MVCC最大的作用是: 实现了非阻塞的读操作,写操作也只锁定了必要的行.}
    mysql的mvcc只在 Read Committed和 Repeatable read两个隔离级别下工作。

    在MVCC机制下,mysql\color{red}{默认隔离界}别下的增删改查变成如下模式。

    读模式:

    • InnoDB只查找版本早于当前事务版本的数据行(行的系统版本号小于等于事务的系统版本号)
    • 行的删除号要么未定义,要么大于当前事务版本号,这样可以确保事务读取到的行,在事务开始之前未被删除.

    写模式:

    • INSERT,InnoDB 为新插入的每一行保存当前系统版本号做为行版本号。
    • DELETE,INNODB 为删除的每一行保存当前系统版本号作为行删除标识。
    • UPDATE,InnoDB 为插入的每一行新记录,保存当前系统版本号作为行版本号,同时保存当前系统版本号到原来的行作为行删除标识.
    一致性非锁定读,是InnoDB存储引擎下的读取数据的方式( read committed 和 repeatable read).

    一致性非锁定读,我的理解是它的读取方式是把: 事务隔离级别,MVCC,InnoDB锁结合起来运用到实现 Mysql读的一种方式.

    • 在read committed隔离级别下:

    一致性非锁定读总是读取被锁定行的最新一份(最新的一行)快照数据. 产生了不可重复读的问题.

    • 在repeatable read 事务隔离级别下:

    一致性非锁定读总是读取事务开始时(第一行)的行数据版本. 解决不可重复读的问题

    一致性锁定读
    • select .... for update. 加X锁(排它锁)
    • select .... lock in share mode. 加S锁(共享锁)
    InnoDB 锁的算法
    • Record Lock: 单个行记录的锁
    • GAP Lock: 间隙锁,锁定一个范围,但不包含记录本身

    间隙锁,它会锁住两个索引之间的区域。比如select * from user where id>1 and id<10 for update,就会在id为(1,10)的索引区间上加Gap Lock。

    • Next-Key Lock: Gap Lock+Record Lock 锁定一个范围并锁定记录本身

    也叫间隙锁,它是Record Lock + Gap Lock形成的一个闭区间锁。比如select * from user where id>=1 and id<=10 for update,就会在id为[1,10]的索引闭区间上加Next-Key Lock

    \color{red}{innoDB在不同隔离级别下产生"不可重复读" 和 "幻读" 和解决它 的根本原因}

    • innerDB默认的事务隔离级别(repeatable read),采用的是Next-Key Locking的方式来加锁。

    • read committed隔离级别下采用的是: Record Lock 的方式来加锁。

    Next-key lock的具体实现:

    默认存储引擎下, 比如表A 上的id字段有索引, 并且id有 3,8,12,20这几个值,那么该索引可能被Next-key locking区间为:

    负无穷,3)[3,8)[8,12),[12,20),[20,正无穷),当事务T1锁定了 [8,12),[12,20)这2个区间时,当插入15时,上面的区间变成:[8,12),[12,15),[15,20)。

    此时如果执行如下语句:select * from A where id>16 for update. InnoDB会对(16,正无穷) 加锁,但在 read committed的事务隔离级别下,因为采用Record Lock,只会锁定20这个值.

    如果在此时另外一个事务T2,插入了22这个值,此时, read committed 隔离级别下就会产生"幻读"的问题.

    但在InnoDB默认存储引擎下的Next-key Lock 模式下,22是插入是会被阻塞的,直到事务T1提交后,释放X锁,才能提交22这值.这样,InnoDB就这样解决了幻读的问题.

    总结:
    • InnoDB用MVCC来实现非阻塞的读操作,不同隔离级别下,MVCC通过读取不同版本的数据来解决"不可重复读" 的问题
    • InnoDB的默认隔离级别采用Next-key Lock(间隙锁) 来解决幻读问题. 而 read committed隔离级别采用Record锁,因此会产生"幻读"问题.

    本文主要参考:https://blog.csdn.net/tangkund3218/article/details/47704527

    https://blog.csdn.net/suifeng629/article/details/99412343

    相关文章

      网友评论

          本文标题:mysql事务隔离级别

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