MySQL事务实现原理
目录
MySQL事务介绍
事务基础及其实现原理
回滚日志
MVCC多版本并发控制
事务的特性
多个事务同时执行出现的三种现象
四种隔离级别及其实现原理
尽量不要使用长事务
MySQL事务介绍
要保证⼀组数据库操作,要么全部成功,要么全部失败
事务是在存储引擎层实现的,MySQL是支持多存储引擎的系统,不是所有的存储引擎都支持事务,目前最常用的存储引擎InnoDB是支持事务的
事务基础及其实现原理
回滚日志
回滚日志是一种用于撤销回退的日志。回滚日志会记录一次事务所有操作细节。
当事务回滚就使用回滚日志恢复到以前的那个版本。
回滚日志格式: 事务ID 和 指向版本日志的回归指针 组成,一系列的回滚指针组成版本链。
MVCC多版本并发控制
MVCC是通过 读视图 + 回滚日志 实现的
读视图: 记录事务快照时的活跃事务信息,用于判断数据版本的可见性。
回滚日志: 存储数据的旧版本,读视图通过行数据间接关联到回滚日志实现历史版本的回滚。
事务的特性
原子性: 事务操作是不可分割的
实现原理: 通过回滚日志实现的
一致性: 事务操作前后数据库保存一致性状态
实现原理: 通过持久性+隔离性+原子性来保证。
隔离性: 多个事务同时使用相同的数据,不会相互干扰,对其他事务隔离
实现原理: 通过MVCC多版本并发控制或锁机制来保证。
持久性: 对数据的修改是永久的
实现原理: 通过redo log物理日志来实现的
多个事务同时执行出现的三种现象
脏读: 读取到未提交的数据
不可重复读: 读取到已经提交的数据,但是读两次仅内容不一样,原因是另一个事务提交更新引起
幻读: 读取到已经提交的数据,但是读两次仅行数不一样,原因是是另一个事务提交删除和插入引起
不可重复读和幻读的聚焦点不一样!
如果读两次内容和行数都不一样,这种现象称为幻读的扩展表现(就是既出现了幻读现象,又出现了不可重复读现象)
四种隔离级别及其实现原理
为了解决这些问题,我们提出了隔离级别这个概念
在谈论隔离级别之前,要明确一个事情,隔离的越严实,效率就越低,不是隔离越严实越好,只是在这二者之间找到一个平衡点
读未提交
出现的现象: 脏读、不可重复读、幻读
原理: 直接读取最新数据即可
读已提交(Oracle的默认级别)
出现的现象: 不可重复读、幻读
原理:事务每次读取数据时生成独立的读视图,通过当前事务ID对读视图里面的事务ID进行对比判断事务的状态是否已经提交,从而确定是否可见,这种原理也叫做MVCC版本并发控制
可重复读(MySQL的默认级别)
很大程度上避免幻读、不可重复读(不是彻底解决)
快照读有可能是历史版本的数据,不是最新数据
当前读一定是最新数据
原理
快照读:整个事务都用第一次快照读生成的读视图,此时屏蔽了其他事务的修改,避免了幻读。
当前读:通过行锁和间隙锁禁止其他事务进行数据修改来解决幻读
可重复读出现幻读、不可重复读的情况
首先使用快照读来让整个事务都用第一次快照读生成的读视图,其实这种情况下没有阻止其他事务的修改只是屏蔽,后面再使用当前读读取最新数据。
此时其他事务修改行内容就出现不可重复读现象,其他事务添加或者删除数据就出现幻读现象
串行化
一个事务修改,其他事务不能操作
尽量不要使用长事务
由上面的原理可以知道,事务操作避免不了使用读视图来进行控制,长事务意味着系统回存放很老的读视图,读视图在事务提交之前都必须保留,就会导致大量占用存储空间,而且长事务也可会占用锁资源,拖垮整个数据库