mysql知识盘点【陆】_锁和事务级别

系列文章:

mysql知识盘点【壹】_SQL优化

mysql知识盘点【贰】_InnoDB引擎索引

mysql知识盘点【叁】_主从复制

mysql知识盘点【肆】_调优参数

mysql知识盘点【伍】_执行计划

 

1.锁

innodb存储引擎支持4种锁:

S:共享锁,可认为对一行数据的读锁;

X:排他锁,可认为对一行数据的写锁;

IS:意向共享锁,事务想获得一张表中几行数据的共享锁;

IX:意向排他锁,事务想获得一张表中几行数据的排他锁;

 

对于意向锁我们可以这样理解。基于前面的文章我们知道,sql的数据存储分为如下几个层次:首先是段segment,可先认为一张表即一个段;段下面有若干区extent,区是一个虚拟单位,默认包含16个页page;一个页默认64KB,具体的数据行就保存在页中。如果一个事务想对某行数据上X锁,那么它分别需要先对数据所在的表(段)和页上意向锁IX。如果上某一部分的意向锁需要等待,那么整个事务需要一起等待。

 

各种锁的兼容性如下: 

mysql知识盘点【陆】_锁和事务级别_第1张图片

 

2.事务隔离级别

一般数据库事务隔离级别有4种:读未提交、读已提交、可重复读、串行,总结如下:

mysql知识盘点【陆】_锁和事务级别_第2张图片 (此图只做展示用)

其中,

脏读是指读取到了其他事务未提交的数据;

不可重复读是指当其他事务提交数据更新,导致当前事务中连续两次对数据的获取值不同;

幻读是指当其他事务新增数据,导致当前事务中连续两次对数据的获取,第二次返回了之前不存在的行;

 

我们知道innodb采用的是行锁,共提供了3种行锁算法:

record lock:单行记录上锁;

gap lock:间隙锁,开区间;

next-key lock:包含record lock和gap lock,半开半闭区间;

 

其中record lock是基于聚集索引来实现,如果一张表没有设置主键,则根据隐式主键rowId来实现。

可重复读事务隔离级别默认使用next-key lock锁,当判断条件是主键且为等价判断,则降级为record lock锁,否则范围查询或非主键条件查询则是next-key lock锁。正式通过这种锁区间的方式,innodb的可重复读事务隔离级别下避免了幻读问题,这也是innodb存储引擎下可重复读事务隔离级别和其他数据库不一样的地方。

 

3.Innodb的事务方案

innodb存储引擎对于事务提供了redo和undo两种日志。

redo log记录的是每个页内数据更改的物理情况,在一个事务未提交之前会多次提交。当设备断电等情况,可用作数据恢复。它的存在,保证了ACID中的A和D。

undo log记录的是数据每次变更的版本。这里补充一下,mysql会为每条数据记录生成rowId(主键不存在时)、trxId(事务id)和roll_ptr(回滚指针)等不可见列。当事务中一行数据发生变成时,innodb会将该行数据修改前的版本保存到undo log中,包含trxId。如果事务发生回滚,则直接恢复到undo log中指定的版本即可。

mysql的MVCC实现,也正式基于undo log。这里就涉及到上面说的数据库隔离级别,读已提交和可重读读,在innodb是如何实现的。在读已提交级别下,事务每次读undo log都是最新版本的trxId,则可能出现不可重复读问题;但是在可重复读级别下,事务每次读undo log都是指定版本的trxId,这样可能出现读取的不是最新数据,但是可以保证每次读取出的数据是一样的

 

你可能感兴趣的:(数据库)