mysql四种隔离级别和mvcc以及锁之间的关系

什么是事务的隔离级别

隔离级别:理解隔离级别之前需要先了解事务的四个特性,分别是:

A(Atomic):原子性是指数据库的事务是一个不可分割的工作单位,只有数据库事务都成功才算成功,任何一个SQL的失败,数据库状态都必须回退到事务开始前的状态 
C(Consistence):一致性是指事务将数据库的状态从一种状态转变为下一个一致的状态。在事务的开始和结束后,数据库的完整性约束都没有被破坏。 
I(Isolation):隔离性是指事务之间对数据对象的读写是相互隔离的,具体是提交后可见还是提交后也不可见取决于隔离等级,前面两种情况分别为提交读(RC)和可重复读(RR)。 
D(持久性):持久性是指事务一旦提交,其修改是永久性的,即使还未写入磁盘时发生宕机,也能恢复数据。 

由上面对事务隔离性的描述可以知道,事务的隔离级别主要是用来控制多事务并发时的数据可见性,即在一个事务开始后,能否看到另一个事务更新或插入的数据。

事务的隔离级别有四种:

READ-UNCOMMITTED(未提交读):一个事务可以读取到另一个事务未提交的数据,如果事务回滚时,会发生脏读(对错误数据进行了处理)

READ-COMMITTED(提交读):不会读到另一个事务未提交事务的数据,但是如果事务提交以后,再次查询,两次查询的数据不一致(在一个事务中,两次查询的数据不一致),也叫不可重复读。

REPEATABLE-READ(可重复读):同一个事务中,不论另一个事务是否删除、更新、插入,本次查询的数据一致(快照读,相当于给数据拍了一张照片),也叫可重复读,可重复读的实现就是通过mvcc和锁来实现的。

SERIALIZABLE(序列化):是最高的事务隔离级别,在该级别下,事务串行化顺序执行(锁表,只有当一个事务处理完成以后,另一个事务才能处理数据),可以避免脏读、不可重复读与幻读。但是这种事务隔离级别效率低下,比较耗数据库性能,一般不使用。

什么是mvcc

在讲述事务隔离级别的时候已经带出了mvcc了, mvcc是一种多版本并发控制机制,它使得大部分支持行锁的事务引擎,不再单纯的使用行锁来进行数据库的并发控制,取而代之的是把数据库的行锁与行的多个版本结合起来,只需要很小的开销,就可以实现非锁定读,从而大大提高数据库系统的并发性能。

MVCC主要是为Repeatable-Read事务隔离级别做的。在此隔离级别下,A、B事务所示的数据相互隔离,互相更新不可见。

我们可以通过InnoDB的MVCC实现来分析MVCC使怎样进行并发控制的. 

innodb存储的最基本row中包含一些额外的存储信息 DATA_TRX_ID,DATA_ROLL_PTR,DB_ROW_ID,DELETE BIT

  • 6字节的DATA_TRX_ID 标记了最新更新这条行记录的transaction id,每处理一个事务,其值自动+1

  • 7字节的DATA_ROLL_PTR 指向当前记录项的rollback segment的undo log记录,找之前版本的数据就是通过这个指针

  • 6字节的DB_ROW_ID,当由innodb自动产生聚集索引时,聚集索引包括这个DB_ROW_ID的值,否则聚集索引中不包括这个值.,这个用于索引当中
  • DELETE BIT位用于标识该记录是否被删除,这里的不是真正的删除数据,而是标志出来的删除。真正意义的删除是在commit的时候

具体的执行过程

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

上述过程确切地说是描述了UPDATE的事务过程,其实undo log分insert和update undo log,因为insert时,原始的数据并不存在,所以回滚时把insert undo log丢弃即可,而update undo log则必须遵守上述过程

下面分别以select、delete、 insert、 update语句来说明

SELECT

Innodb检查每行数据,确保他们符合两个标准:

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

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

符合了以上两点则返回查询结果。

INSERT

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

DELETE

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

UPDATE

InnoDB复制了一行。这个新行的版本号使用了系统版本号。它也把系统版本号作为了删除行的版本。

说明

insert操作时 “创建时间”=DB_ROW_ID,这时,“删除时间 ”是未定义的;

update时,复制新增行的“创建时间”=DB_ROW_ID,删除时间未定义,旧数据行“创建时间”不变,删除时间=该事务的DB_ROW_ID;

delete操作,相应数据行的“创建时间”不变,删除时间=该事务的DB_ROW_ID;

select操作对两者都不修改,只读相应的数据

在mysql中什么是锁

mysql中锁的概念有很多,乐观锁、悲观锁、共享锁、排他锁、表锁、行锁等,他们之间有什么关系呢

乐观锁

乐观锁大多是基于数据版本记录机制实现,一般是给数据库表增加一个"version"字段。读取数据时,将此版本号一同读出,之后更新时,对此版本号加一。此时将提交数据的版本数据与数据库表对应记录的当前版本信息进行比对,如果提交的数据版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据。

悲观锁

悲观锁依靠数据库提供的锁机制实现。MySQL中的共享锁和排它锁都是悲观锁。数据库的增删改操作默认都会加排他锁,而查询不会加任何锁。

共享锁(读锁)

共享锁指的就是对于多个不同的事务,对于一个资源共享同一个锁。对某一资源加共享锁,自身可可读该资源,其他人也可以读该资源(也可以再加共享锁,即共享锁共享多个内存),但无法修改。要想修改就必须等所有共享锁都释放完之后。语法:select * from table lock in share mode;

排它锁(写锁)

排它锁指的就是对于多个不同的事务,对同一个资源只能有一把锁。对某一资源加排它锁,自身可以进行增删改查,其他人无法进行加锁操作,更无法进行增删改操作。语法:select * from table for update

行锁

行锁就是给一行数据进行加锁,操作对象是数据表中的一行(共享锁和排他锁可能是行锁也可能是表锁,取决于对数据加锁的范围,是一行还是整个表)。是MVCC技术用的比较多的,但在MYISAM用不了,行级锁用mysql的储存引擎实现而不是mysql服务器。但行级锁对系统开销较大,处理高并发较好。

表锁

表锁就是对一张表进行加锁,操作对象是数据表。Mysql大多数锁策略都支持(常见mysql innodb),是系统开销最低但并发性最低的一个锁策略。事务t对整个表加读锁,则其他事务可读不可写,若加写锁,则其他事务增删改都不行。

PS

当前读、快照读,record lock(记录锁)、gap lock(间隙锁)、next-key lock

本来只有串读隔离级别才可以解决幻读问题,而实际上由于快照读的特性使可重复读也解决了幻读问题。

当前读是因为innodb默认为它加入了间隙锁,防止在事务期间对相关数据集插入记录,从而避免出现幻读。

在RR级别下,快照读是通过MVVC(多版本控制)和undo log来实现的,当前读是通过加record lock(记录锁)和gap lock(间隙锁)来实现的。如果需要实时显示数据,还是需要通过手动加锁来实现。这个时候会使用next-key技术来实现。

在mysql中,提供了两种事务隔离技术,第一个是mvcc,第二个是next-key技术。这个在使用不同的语句的时候可以动态选择。不加lock inshare mode之类的快照读就使用mvcc。否则 当前读使用next-key。mvcc的优势是不加锁,并发性高。缺点是不是实时数据。next-key的优势是获取实时数据,但是需要加锁。

Record lock
单条索引记录上加锁,record lock锁住的永远是索引,而非记录本身,即使该表上没有任何索引,那么innodb会在后台创建一个隐藏的聚集主键索引,那么锁住的就是这个隐藏的聚集主键索引。所以说当一条sql没有走任何索引时,那么将会在每一条聚集索引后面加X锁,这个类似于表锁,但原理上和表锁应该是完全不同的。

Gap Lock 

在索引记录之间的间隙中加锁,或者是在某一条索引记录之前或者之后加锁,并不包括该索引记录本身。gap lock的机制主要是解决可重复读模式下的幻读问题。

Next-Key Lock 

行锁和间隙锁组合起来就叫Next-Key Lock。

参考资料:https://blog.csdn.net/whoamiyang/article/details/51901888

                  https://www.cnblogs.com/chenpingzhao/p/5065316.html

  • 7
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值