RU(Read Uncommitted):读未提交
事务可以读取其他事务未提交的内容
此级别下会出现脏读,即A事务对数据进行修改,但未提交,此时B事务读取到了A修改后的数据,但A后续未提交内容采取回滚,导致B提前读到了错误数据
RC(Read Committed):读已提交(默认事务等级)
若有更新操作事务对数据进行更新,则读操作事务需要等待更新操作事务结束后才能读取数据
此级别下会出现不可重复度,即事务A开启了对数据的读操作,此时数据结果为a,但有另一事务B对数据a进行的更新使其变为b,读事务A直到事务B更新事务提交后才能读取到数据,且数据变为了b,前后不一致。
RR(Repeatable Read):可重复度
事务开启读取数据时,不在允许修改(update)操作(仅禁止update操作,insert仍可执行)
此级别下会出现幻读,即当事务A开启了对数据的读操作,显示数据结果有N条数据,此时有事务B插入了M条新数据(insert),当事务A再次根据同一搜索条件读取数据时,结果出现了N+M条数据
Serializable:可串行化
最高级别的隔离,事务串行执行,一次只有一个事务对数据进行修改,避免了脏读,不可重复度,幻读,但资源消耗大
MVCC
多版本并发控制(Multi-Version Concurrency Control)
主要用于发生读写
请求时,避免使用锁,从而提高数据库的并发性能,这是一种快照读
(相对的读写时加锁操作,为当前读——使用悲观锁防止数据不一致,但阻塞了的线程)
RR和RC的快照读都是基于MVCC实现的
MVCC的组成
1.undo log日志
:记录历史数据,每行数据除了数据本本身的字段还有事务id和回滚指针
2.版本链
:undo log中数据的回滚指针构成的版本链表
3.ReadView
:用于在版本链中确认选择哪一个版本,它的本质是一个对象
包含以下字段
m_ids:表示生成ReadView
时,当前系统中活跃的读写事务
的事务id列表,
min_trx_id:表示生成ReadView
时,当前系统中活跃的读写事务
中最小的事务id,即m_ids中的最小值
max_trx_id:表示生成ReadView
时,系统中应该分配给下一个事务的id,即m_ids中的最大值+1
creator_trx_id:表示生成该ReadView
的事务的事务id
PS:活跃的事务指没有commit的事务
ReadView如何判断版本链中的哪些版本可用
trx_id指当前事务id
trx_id == creatot_trx_id:可以访问此版本(表示当前事务读取自身创建的事务
)
trx_id < min_trx_id:可以访问此版本(小于min的事务id为已经提交的,所以可以访问
)
trx_id > max_trx_id:不可以访问此版本(大于max的事务id为还未进入版本链的事务,所以无法读取
)
min_trx_id <= trx_id <= max_trx_id:如果trx_id在m_ids中是不可以访问的,反之可以(如果trx_id包含于m_ids,说明当前事务是一个未commit的活跃事务,所以无法访问。相反如果不在其中,说明是一个已经commit的事务,则可以访问
)
通过ReadView就可以在版本链里读取应该读取的某一条记录
ReadView在RC中
在读已提交的情况下,每一个select语句生成一个ReadView,是以每个select查询为单位,因此,readView在确认需要查找的版本链时,
只会根据当前select时的版本链
来查找,所以无法找到后续update操作中加入的数据版本,从而出现不可重复度的问题
ReadView在RR中
在可重复读的情况下,每一个事务会生成一个ReadView,是以事务为单位,因此即使在读事务开启期间有其他update操作事务执行,读事务的后续select操作仍然以之前的ReadView为基准
,所以避免了不可重复度的情况
————————————————————————————
以上内容仅供学习记录
部分内容参考来源
IT老哥讲MySQL的MVCC