MySQL脏读、不可重复读、幻读及MVCC
脏读:
脏读是指事务读取到其他事务没提交的数据。
不可重复读:
不可重复读是指在同一次事务中前后查询不一致的问题。
幻读:
幻读是一次事务中前后数据量发生变化,导致用户遇到不可预料的问题。
小结:
脏读指读取到其他事务正在处理的未提交的数据。
不可重复读指并发更新时,另一个事务前后查询相同数据时的数据不一致。
幻读指并发新增、删除这种会产生数量变化的操作时,另一个事务前后查询相同数据不一致的问题。
事务隔离级别
获取当前事务隔离界别,默认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是基于”数据版本”对并发事务进行访问。
RR级别:Select1=张三 Select2=张三
RC级别:Select1=张三 Select2=张小三
RC级别下出现了“不可重复读”
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。
其实就是取当前版本链中最后一次提交的数据。
可重复读(RR):仅在第一次执行快照读时生成ReadView,后续快照读复用(有例外:后面会说)。
因为两次快照读使用相同的ReadView,所以可以实现可重复读。
RR级别下使用MVCC能避免幻读吗?
能,但不完全能!
连续多次快照读,ReadView会产生复用,没有幻读问题
特例:当两次快照读之间存在当前读,ReadView会重新生成,导致产生幻读