MySQL脏读、不可重复读、幻读及MVCC

脏读:

image-20210831100238416

脏读是指事务读取到其他事务没提交的数据。

不可重复读:

image-20210831100532688

不可重复读是指在同一次事务中前后查询不一致的问题。

幻读:

image-20210831101022899

幻读是一次事务中前后数据量发生变化,导致用户遇到不可预料的问题。

小结:

脏读指读取到其他事务正在处理的未提交的数据。
不可重复读指并发更新时,另一个事务前后查询相同数据时的数据不一致。
幻读指并发新增、删除这种会产生数量变化的操作时,另一个事务前后查询相同数据不一致的问题。

事务隔离级别

image-20210831101923121

获取当前事务隔离界别,默认RR可重复读
SHOW VARIABLES LIKE 'transaction_isolation'; # REPEATABLE-READ

设置当前会话事务隔离级别为“读未提交”
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

MySQL 5.1以后默认存储引擎就是InnoDB,因此MySQL默认RR也能解决幻读问题。

MVCC

​ 在MySQL InnoDB存储引擎下RC、RR基于MVCC(多版本并发控制)进行并发事务控制。MVCC是基于”数据版本”对并发事务进行访问。

image-20210831103239033

RR级别:Select1=张三 Select2=张三
RC级别:Select1=张三 Select2=张小三
RC级别下出现了“不可重复读”

image-20210831103730993

UNDO_LOG不是会被删除吗?中间数据万一被删了版本链不就断了?
UNDO_LOG版本链不是立即删除,MySQL会确保版本链数据不再被“引用”后再进行删除。

ReadView是什么?
ReadView是“快照读”SQL执行时MVCC提取数据的依据。
快照读就是最普通的Select查询语句。
当前读指代执行下列语句时进行数据读取的方式。
Insert、Update、Delete、
Select...for update
Select...lock in share mode

ReadView是一个数据结构,包含4个字段

  • m_ids:当前活跃的事务编号集合
  • min_trx_id:最小活跃事务编号
  • max_trx_id:预分配事务编号,当前最大事务编号+1
  • creator_trx_id:ReadView创建者的事务编号

读已提交(RC):在每一次执行快照读时生成ReadView。

image-20210831105713952

image-20210831105751871

image-20210831110840565

其实就是取当前版本链中最后一次提交的数据。

可重复读(RR):仅在第一次执行快照读时生成ReadView,后续快照读复用(有例外:后面会说)。

image-20210831111310645

因为两次快照读使用相同的ReadView,所以可以实现可重复读。

RR级别下使用MVCC能避免幻读吗?
能,但不完全能!

连续多次快照读,ReadView会产生复用,没有幻读问题
特例:当两次快照读之间存在当前读,ReadView会重新生成,导致产生幻读

posted @ 2021-09-03 10:44  Java程序员的进阶之路  阅读(280)  评论(0编辑  收藏  举报