事务特性(ACID)
-
原子性
-
一致性
-
隔离性
-
持久性
日志(innodb)
-
redo日志
事务提交后,需要把数据保存到磁盘,如果每次都刷盘,会影响效率。所以将修改行为先写到redo日志中,再定期将日志刷到磁盘中
-
undo日志
事务未提交时,会将修改前的旧版本存放到undo日志,事务回滚时,利用undo日志,撤销未提交事务对数据的影响。
存储undo的地方就是回滚段
insert操作,undo直接存数据的pk(row_id),回滚直接删除
delete/update,记录旧数据row,回滚直接恢复
隔离性
-
脏读。事务T1修改某条数据,事务T2读取该值,T1由于某种原因导致回滚,导致T2所读的数据是无效数据。
-
不可重复读。一个事务范围内,两个相同的查询却返回不同的值。由于在事务范围内,有其它事物修改了数据导致。
-
幻读。与不可重复读非常类似,指一个事务范围内,两次相同的查询,第二次比第一次少或多数据。
-

InnoDB四种事务隔离级别实现原理
-
read uncommitted
select语句不加锁,并发最高,一致性最差。
-
read commotted
普通读是快照读
加锁的select, update, delete等语句,除了在外键约束检查(foreign-key constraint checking)以及重复键检查(duplicate-key checking)时会封锁区间,其他时刻都只使用记录锁;此时,其他事务的插入依然可以执行,就可能导致,读取到幻影记录。
-
repeatable read
1、普通select是快照读 简介
2、加锁的select(select ... in share mode/select ... for update).update,delete等语句,它们的锁依赖于它们是否在唯一索引上使用了唯一的查询条件,或者范围查询条件。
在唯一索引上使用唯一的查询条件,会使用记录锁。
范围查询条件,会使用间隙锁与临键锁,锁住索引记录之间的范围。
-
serializable
所有select语句都会被隐式的转化为select ... in share mode,如果有事务正在修改该行,那么读会阻塞,这是并发最低,一致性最好的
锁
-
乐观锁
具体实现是,表中有一个版本字段,第一次读的时候,获取到这个字段。处理完业务逻辑开始更新的时候,需要再次查看该字段的值是否和第一次的一样。如果一样更新,反之拒绝。之所以叫乐观,因为这个模式没有从数据库加锁,等到更新的时候再判断是否可以更新。
-
悲观锁
悲观锁则是直接加锁。
小知识:
innodb只有通过索引检索数据,才会使用行锁,否则使用表锁。
innodb锁
-
自增锁
自增锁是一种特殊的表级别锁,专门正对插入包含自增的列,如果一个事务正在插入数据,那么其它事务的插入必须等待。
-
共享/排它锁(行级别)
读锁(S锁),写锁(X锁)。写锁是排它锁。读读可以并行,写写、读写是互斥。
-
意向锁(行级别)
意向锁是指,在某个时刻,事务可能要加共享/排它锁,先提前声明一个意向。意向锁分为意向共享锁(IS);意向排它锁(IX),意向锁之间不互斥。
S X
IS 兼容 互斥
IX 互斥 互斥
-
插入意向锁
上面提到插入有自增列的数据,有自增锁,如果插入没有自增列的数据,则是插入意向锁,它是间隙锁的一种,实施在索引上,专门正对insert操作。
-
记录锁
封锁索引记录,例如select * from user where id = 1 for update;
-
间隙锁
封锁第一条索引之后或者最后一条索引之前的数据。
例如:select * from user where id between 1 and 10 for update; 会锁定id 1-10的所有行,防治出现幻影数据,假如插入了一条id=5的记录,那么执行相同的sql会发现多了一条记录,出现幻影数据,所以这么做防治了不可重复读。
-
临键锁
临键锁,是记录锁与间隙锁的组合,它的封锁范围,既包含索引记录,又包含索引区间。临键锁会封锁索引记录本身,以及索引记录之前的区间。避免幻读。
来源:CSDN
作者:一只叫狗的猫
链接:https://blog.csdn.net/zgsxhdzxl/article/details/104457611