事务的隔离级别和锁机制
mysql 相关
-
常用的 mysql 数据库引擎:
- InnoDB (推荐)
- MyiSAM
锁机制
-
一次封锁,在事务开始阶段对所有要用到的数据,全部加锁
缺点:在事务开始时,无法预知要使用到的所有数据
优点:可以避免死锁
-
两段锁
加锁阶段、解锁阶段
调度可串行化
事务并发可能出现的三个问题
事务并发可能出现同一事务两次读取到的数据不一致。脏读、不可重复读的粒度是数据项,
幻读的粒度是记录(行)
-
脏读(修改/事务回滚)
T1 T2 || 读数据A || || <==== || 修改A,错误数据未 commit 需 rollback (事务回滚情况) || 读数据A /\ || rollback \/ 两次读 A 不一致
脏数据,不是最终要写入数据库的数据(发生事务回滚)
同一个事务中对同一个数据项(列),两次读到的结果不同。在两次读的间隔时间里,另一个事务修改的这个数据项,但回滚的了事务
-
不可重复读(修改/事务提交)
T1 T2 || 读数据A || || <==== || 修改A,已 commit (事务提交情况) || 读数据A \/ || commit \/ 两次读 A 不一致
同一个事务中对同一个数据项(列),两次读到的结果不同。在两次读的间隔时间里,另一个事务修改的这个数据项,且提交的了事务
-
幻读(新增和删除)
T1 T2 || select type=1 || || <==== || 新增一条记录 || select type=1 \/ || \/ 两次读取记录数不一致
同一个事务中对同一个查询SQL,两次读到的记录数不同。在两次读的间隔时间里,另一个事务新增或删除了记录,且提交的了事务
使用锁来应对这三个问题
-
RU(read uncommited)不加锁。
会出现脏读、不可重复读和幻读问题
-
RC(read commited) 只对写加锁。封锁粒度行。避免脏数据
1、对被修改的行加锁(加写锁的数据无法被读) 2、直到事务提交或回滚才解锁。 3、能避免脏读、但无法避免不可重复读和幻读
-
RR(repeatable read) 对读写加锁。封锁粒度行。避免脏数据、不可重复读
1、读和写都加锁 2、加读锁排斥其他事务的写操作 3、加写锁排斥其他事务的读操作 4、RR 级别对行加锁
S(serialiable) 对读写加锁。封锁粒度表。不能插入数据行
事务级别和解决问题
transaction level | dirty read | non-repeatable read | phantom read |
---|---|---|---|
RU(read uncommited) | √ | √ | √ |
RC(read commited) | √ | √ | |
RR(repeatable read) | √ | ||
S(serialiable) |