Mysql 数据库事务的隔离级别,MVCC,和Mysql锁的实现原理

一:事务隔离级别
1:READ UNCOMMITED(未提交读)
事务中的修改,即使没有提交,对其他事务也是可见的.脏读(Dirty Read).
2: READ COMMITTED(提交读)
一个事务开始时,只能看见已经提交的事务所做的修改.这个级别有时候也叫不可重复读(nonrepeatable read)。
3:REPEATABLE READ(可重复读)
该级别保证了同一事务中多次读取到的同样记录的结果是一致的.但理论上,该事务级别无法解决幻读的问题(Phantom Read)
幻读:当某个事务读取某个范围内的记录时,另外一个事务又在该范围内插入了新的记录,当之前的事务再次读取该范围时,会产生幻行(Phantom Row).
幻读的问题理应由更高的隔离级别来解决,但mysql和其他数据不一样,它同样可以在可重复读范围内解决这个问题。而oracle可能需要在Serializable事务隔离级别下才能解决幻读问题
4:SERIALIZABLE(可串行化)
强制事务串行执行,避免了上面说的脏读,不可重复读,幻读三个的问题。
二:MVCC(Multi-Version Concurrentcy Control)多版本并发控制
MVCC的实现,是通过保存数据在某个时间点的快照来实现的。
InnoDB的MVCC是通过在每行记录后面保存2个隐藏的列来实现的,一列保存了行的创建时间,一列保存了行的过期时间(或删除时间).但他们都存储的是系统版本号.

  • MVCC最大的作用是:实现了非阻塞的读操作,写操作页只锁定了必要的行。
  • MySQL的MVCC只在read commited和reapeat read2个隔离级别下工作。
    在MVCC的机制下,mysql InnoDB(默认隔离级别)的增删改查变成了如下模式:
    SELECT:
    1, InnoDB只查找版本早于当前事务版本的数据行(行的系统版本号小于等于事务的系统版本号)
    2, 行的删除号要么未定义,要么大于当前事务版本号,这样可以确保事务读取到的行,在事务开始之前未被删除.

    INSERT:
    InnoDB 为新插入的每一行保存当前系统版本号做为行版本号。

    DELETE: 
    INNODB 为删除的每一行保存当前系统版本号作为行删除标识

    UPDATE:
    InnoDB 为插入的每一行新记录,保存当前系统版本号作为行版本号,同时保存当前系统版本号到原来的行作为行删除标识.
    三:InnoDB锁
    InnoDB的锁大致分为:
    3.1行锁
    支持并发高,带来最大的锁开销,在存储引擎层实现,服务器感知不到。
    3.2表锁
    服务器会为注入:ALter Table 之类的语句使用表锁,而忽略存储引擎的锁机制。
    锁的类型细分又分为:
    (1).共享锁(S Lock),允许事务读取一行数据
    (2).排他锁(X Lock),允许事务删除或者更新一行数据
    3.3意向锁
    InnoDB还实现了一种锁,叫意向锁(Intention Lock).意向锁是将锁定的对象分为多个层次.

    总结:
    1, InnoDB用MVCC来实现非阻塞的读操作,不同隔离级别下,MVCC通过读取不同版本的数据来解决”不可重复读” 的问题.

    2, InnoDB的默认隔离级别解决2个问题,”不可重复读” 和 “幻读”, oracle需要在串行读中解决”幻读”问题. InnoDB的实现方式和一般隔离级别的定义不一致.

    3, InnoDB的默认隔离级别采用Next-key Lock(间隙锁) 来解决幻读问题. 而 read committed隔离级别采用Record锁,因此会产生”幻读”问题.

    4, InnoDB的存储引擎不存在锁升级的问题(太多的行锁升级为表锁),来降低锁的开销. 因为不是根据记录来产生行锁的,根据页对锁进行管理.

    打赏作者

    《Mysql 数据库事务的隔离级别,MVCC,和Mysql锁的实现原理》上有1条评论

    发表评论

    电子邮件地址不会被公开。