Mysql事务实现原理及设计
一、事务基本概念
事务特性:AIDC(原子性、 隔离性、持久性、一致性)
并发问题:脏读:读取到未提交的数据。
不可重复读:两次读取的结果不同。
幻读:select操作得到的结果表征的数据状态无法支撑后续的业务操作。
隔离级别:
未提交读:最低隔离级别,会读取到其他事务为提交的数据。脏读
提交读:事务过程中可以读取到其他事务已提交的数据。不可重复读
可重复读:Mysql默认隔离级别。每次读取相同的结果集,不管其他事务是否提交。幻读
串行化:事务排队,隔离级别最高,性能最差。
二、事务实现原理(或者说实现的依靠)
1.MVCC:多版本并发控制,以隐藏列的方式解决读写冲突。
(1)当前读:读取的是记录数据的最新版本,并且当前读返回的记录都会加上锁,保证其他事务不会再并发的修改这条记录。
(2)快照读:读取的是记录数据的可见版本(可能是过期的数据),不用加锁。
(3)可见性判断:
不可见的事务:创建快照这一刻,还未提交的事务;创建快照之后创建的事务。不可见时就查快照读。
可见的事务:根据活跃事务列表、列表中最小事务ID、列表中最大事务ID进行判断。小于活跃事务最小事务ID,大于最小事务ID小于最大事务ID且不在活跃事务列表的事务。
2.undo log:Innodb的回滚日志。借此可实现数据的多版本。
delete undo log用于回滚,提交即清理。
update undo log用于回滚,同时实现快照读,不能随便删除。删除的条件:根据活跃事务列表的最小事务ID,小于最小事务ID即可删除。
引出一个问题:
为什么Innodb的count(*)的速度慢?
因为MVCC多版本的原因,并且会只返回可见的行数,所以行数会出现变动。
3.redo log:保证事务的持久性。
记录事务数据的修改,用于异常恢复,保证事务执行不会失败。
Innodb从操作到写入磁盘流程:
commit将事务操作记录循环写入文件,如下图:刷盘会覆盖原有的数据,事务提交之后这些操作修改已无意义。
刷盘时机:一般配置2。0出问题时会丢一秒钟的数据。1开销大。2比较柔和。
redo log的意义:体积小,纪录页的修改,比写入页代价低;修改末尾追加,随机写变顺序写。