前言
本篇主要介绍事务的特性、引发的问题以及处理问题,基本概念还是需要掌握理解的。
提示:以下是本篇文章正文内容,下面案例可供参考
一、事务的特性
事务的概念:是一组操作的集合,要么全部成功,要么全部失败。
- 原子性(Atomicity):一组事务的操作,要么全部成功,要么全部失败
- 一致性(Consistence):事务完成时,所有的数据必须保证一致状态
- 隔离性(Isolation):一个事务的修改在最终提交前对其他事务不可见
- 持久性(Durability):事务一旦提交或回滚,数据永久保存
A靠undolog保证,C靠AID保证,I靠MVCC保证,D靠redolog保证
- 缓冲池(buffer pool):内存中的一个区域,缓存磁盘上真实的数据,执行操作时先操作缓冲池的数据(没有则从磁盘加载),以一定频率刷到磁盘,减少IO。
- 数据页(datapage):InnoDB管理的最小单元,每个页默认16kb,页中存储行数据。
- undolog(回滚日志):用于记录数据修改前的信息,主要提供回滚和MVCC,是逻辑日志(记录反向操作)。
- redolog(重做日志):记录事务提交时数据页的物理修改,用来实现事务的持久性;当刷新脏页到磁盘发生错误时,进行数据恢复。
二、并发事务的问题
- 脏读:一个事务读到另外一个事务还没有提交的数据
- 不可重复读:一个事务先后读同一条记录,但两次读取的数据不同(数据被另一个事务update了)
- 幻读:一个事务两次读取时,出现不同的记录数(数据被另一个事务insert或delete了)
解决方案:增加事务的隔离级别
三、事务的隔离级别
- 读未提交(read uncommitted):出现脏读、不可重复读、幻读
- 读已提交(RC-read committed):出现不可重复读、幻读;解决脏读
- 可重复读(RR-repeatable read):出现幻读;解决脏读、不可重复读;mysql默认隔离级别
- 串行化(serializable):加锁,有超时和锁竞争问题;解决脏读、不可重复读、幻读
事务隔离级别越高,数据越安全,但性能越低。
四、MVCC多版本并发控制
首先熟悉2个概念:
- 当前读:读取最新版本的数据
- 快照读:读取历史版本的数据,当前行的历史版本数据存在undolog中
mvcc实现主要依靠:三个隐式字段、undolog、readview
三个隐式字段:在每行记录中都会存在这三个字段
- DB_TRX_ID:最近修改的事务ID
- DB_ROLL_PTR:回滚指针,指向这条记录的上一个版本
- DB_ROW_ID:6字节的隐藏主键
undolog版本链
不同事务或相同事务对同一条记录进行修改,会导致该记录的undolog生成一条记录版本链表,链表的头部是最新的旧记录,链表的尾部是最早的旧记录。
readview(读视图):是快照读sql执行mvcc提取数据的依据,记录并维护系统当前活跃的事务(未提交的)id
- m_ids(trx_list):记录活跃事务的id集合
- up_limit_id:最小的事务id
- low_limit_id:尚未分配的下一个事务id,即当前事务id+1
版本链数据的访问规则
- DB_TRX_ID < up_limit_id:成立则当前事务看见,可以访问该版本,说明数据已经提交了,否则进行下一步判断
- DB_TRX_ID >= low_limit_id:成立则对当前事务不可见,不可以访问该版本,说明该事务是在readview生成后开启的,否则进入下一步判断
- DB_TRX_ID是否在当前活跃的事务列表中,在则看不见;不在则看见,说明数据已经提交。
注意: 不同的隔离级别,生成readview的时间不同
- RR(可重复读):readview在事务开始之前生成,即只有在第一个快照读生成,后续复用
- RC(读已提交):readview在执行当前sql语句时生成,即每个快照读都生成一个,在持久化commint后失效
总结
本文主要介绍了mysql事务相关知识,理解事务的概念,事务引发的问题以及如何处理并发事务问题,掌握了基本的才能更好的进阶,去理解更深层次的东西。