zoukankan      html  css  js  c++  java
  • MySQL事务隔离级别&锁

    事务的隔离级别如下所示:

    隔离级别 脏读 可重复读 幻象读
    RU 可能 可能 可能
    RC 不可能 可能 可能
    RR 不可能 不可能 可能
    Serializable 不可能 不可能 不可能

    脏读:当前事务可能读到其它事务未提交的数据。

    可重复读:当前事务内,多次读取同一份数据是一致的,不受其它事务的update,delete影响。

    幻象读:当前事务内,读到其它事务insert的数据。

    数据库在实现这些隔离级别时,底层是通过锁机制来支持的。

    在锁对象类型上,锁的类型分为表锁,行锁,Gap锁等。

    在锁读写方式上,锁分为读锁(S),写锁(X)等。

    RC隔离级别下,支持读已提交事务的数据。因为读取不加锁,写入,修改,删除是加行锁的。故不支持可重复读,有幻象读。

    RR隔离级别下,支持可重复读。因为读取时,会在行上加行锁读锁(S);写入,修改,删除时加行锁写锁(X),故支持可重复读,有幻象读。

    但是MySQL对此作了一定的优化,通过引入Gap锁,禁止在行区间范围内的写入操作,解决了幻象读的问题。故MySQL上RR隔离级别不会有幻象读。

    Serializable隔离级别下,支持可重复读,无幻象读。因为读取时,会在表上加表锁读锁(S),编辑时,会在表上加表锁写锁(X),故支持可重复读,不会存在幻象读。

    一般应用使用RC级别,在写入,修改,删除场景下,MySQL在where命中索引时,是会在命中行上加行锁。但是如果无法命中索引时,存储引擎返回MySQL Server时,会在表的所有记录上加上行锁。同样的情况,RR隔离级别下,会在表的所有行之间加上Gap锁。目前MySQL为了性能优化,会在MySQL Server过滤数据,在不满足过滤条件的记录上会解除行锁。但是不会释放Gap锁。

    MySQL的MVCC协议的镜像读&当前读

    MVCC协议保证了并发下的查询性能&一致性。该协议会使用乐观锁机制,基于事务版本号,在每一个行记录上加上了2个隐藏列,分别记录创建时的事务版本号,删除时的事务版本号。

    select时,会查询<=当前事务版本号的记录,过滤有删除版本号的记录。

    insert时,会记录当前事务版本号。

    delete时,会记录当前事务版本号为删除版本号。

    update时,会先删除原始记录,在原始记录上记录删除版本号;然后新增新记录,在新纪录上记录新增版本号。

    基于这个机制,那一般的select查询,都是镜像读,因为可能读取到历史版本,不一定是最新的版本。

    特殊的select比如:

    select * from xxx where ? lock in share mode(共享锁模式下的当前读。这种情况下,允许其它事务读当前记录,不允许写当前记录。)

    select * from xxx where ? for update;(排它锁模式下的当前读。这种情况下,不允许其它事务读写当前记录)

    与update,delete,insert等操作,都是当前读。当前读保证读取到记录的最新版本数据。

    参考资料:

    https://tech.meituan.com/2014/08/20/innodb-lock.html

    http://www.cppcns.com/shujuku/mysql/251595.html

  • 相关阅读:
    编写你的第一个程序(HelloWorld)
    有关数据库的一些基本关键字
    带箭头的面包屑导航栏
    浅析被element.style所覆盖的样式
    一些方便前端开发的小工具
    一道简单的闭包面试题
    First Article
    java8 lambda表达式 实现 java list 交集 并集 差集 去重复并集
    asp.net mvc5 WebUploader多文件大文件上传
    fastdfs安装部署
  • 原文地址:https://www.cnblogs.com/asfeixue/p/13294259.html
Copyright © 2011-2022 走看看