这是我参与8月更文挑战的第3天,活动详情查看:8月更文挑战
定义
mysql事务是一组sql语句组成的逻辑处理单元,只要勇于处理操作量大,复杂度搞的数据。典型的场景是银行转账,账户A给账户B转账,必须要保证账户A减去的相应的金额,账户B增加了相应的金额,只有都操作成功了,才是一次事务完成
事务的特征(ACID)
原子性(Atomicity): 整个事务的所有操作,要么全部完成,要么全部失败,不能停留在中间某个环节。如果事务执行过程中发生错误,会被回滚到事务开始前的状态
一致性(Consistency): 事务在开始和结束后,数据库的完整性约束没有被破坏
隔离性(Isolation): 一个事务的执行不会被其他的事务干扰。即一个事务的内部操作与其他并发事务的操作是相互隔离,互不干扰
持久性(Durability): 在事务完成后,该事务对数据库所做的更改持久的保存在数据库中,不会被回滚
并发事务带来的问题
- 更新丢失(Lost Update): 事务A和事务B选择同一行,然后基于最初选定的值更新该行时,两个事务都不知道彼此的存在,就会发生更新丢失的问题
- 脏读(Dirty Reads): 事务A读取了事务B更新的数据,然后事务B做了回滚操作,那么事务A读取到的数据是脏数据
- 不可重复度(Non-Repeatable Reads): 事务A多次读取同一数据,事务B在事务A多次读取的过程中,对数据做了更新并提交,导致事务A多次读取同一数据时,结果不一致。
- 幻读(Phantom Reads): 幻读与不可重复度类似。他发生在一个事务A读取了几行数据,接着另外一个并发事务B插入了一些数据,在随后的查询中,事务A会发现多了一些原本不存在的记录,就好像发生了幻觉一样,所以称为幻读。
事务隔离级别
- Read-Uncommitted(读未提交):最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读和不可重复读
- Read-Committed(读已提交):允许并发事务已经提交的数据,可以阻止脏读,但是幻读和不可重复读人有可能发生
- Repeatable-read(可重复读):对同一个字段的多次读取结果都是一致的,除非数据被本身事务自己所修改,可以阻止脏读和不可重复读,但是幻读仍有可能发生。这也是mysql的 默认隔离级别
- 可串行化:最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰。该级别可以阻止脏读、不可重复读、幻读。
查看当前数据库的隔离级别
-- 5.7.20版本之前的写法
-- 方式一
show variables like 'tx_isolation';
-- 方式二
select @@tx_isolation;
-- 5.7.20版本之后的写法
-- 方式一
show variables like 'transaction_isolation';
-- 方式二
select @@transaction_isolation;
事务日志
InnoDB的事务操作原理
-
InnoDB使用日志来减少提交事务时的开销。因为日志中已经记录了事务,就无需在每个事务提交时把缓冲池的脏块刷新到磁盘中。
-
事务修改的数据和索引通常会映射到表空间的随机位置,所以刷新这些变更到磁盘需要很多随机IO。随机IO比顺序IO昂贵得多,因为一个IO请求需要把磁头一到正确的位置,然后等待磁盘上读出需要的部分,再转到开始位置。
-
InnoDB用日志把随机IO变成顺序IO。一旦日志安全写到磁盘,事务就持久化了,及时断电了,InnoDB重启可以通过redo log恢复已经提交的事务
-
InnoDB使用一个后台线程智能的刷新变更到数据文件。此线程可以批量组合写入,使得数据写入更顺序,一次提高效率
事务的实现
- 事务的实现是基于数据库的存储引擎实现的,不同的存储引擎对事务的支持程度不一样
- 事务的实现就是实现ACID特性。事务隔离性是通过锁实现,而事务的原子性、一致性和持久性则通过事务日志来实现。
事务的种类
- redo log(重做日志)
- undo log(回滚日志)
redo log实现持久性和原子性
- 在InnoDB引擎中,事务日志通过redo log和日志缓冲(InnoDB Log Buffer)实现
- 事务开启时,事务中的操作,都会先写入存储引擎的日志缓存中,在事务提交之前,这些缓存的日志都需要提前刷新到磁盘上持久化,这就是日志先行(Write-Ahead logging)
- 当事务提交之后,在Buffer Pool中映射的数据文件会慢慢的刷新到磁盘。此时如果宕机,那么系统重启进行恢复时,可以根据redo log中记录的日志,把数据库恢复到崩溃前的一个状态。未完成的事务,可以继续提交或者选择回滚,这基于恢复的策略而定
- 在系统启动的时候,就已经为redo log分配了一块连续的存储空间,以顺序追加的方式记录redo log,通过顺序IO改善性能。所有事务共享redo log的存储空间,他们的redo log按照语句的执行顺序,依次交替的记录在一起。
undo log(回滚日志)实现一致性
- undo log主要为事务的回滚服务
- undo log 记录了数据在某个操作前的状态,如果事务执行过程中需要回滚,就可以根据undo log进行回滚操作
- undo log记录的是已部分完成未写入磁盘的未完成的事务 4.单个事务的回滚,不会影响到其他事务做的操作。
redo log和undo log的区别
- 两种日志都是为了恢复操作
- redo log是恢复提交事务修改的页操作。而undo log是回滚行记录到特定版本
- 两者记录的内容也不同,redo log是物理日志,记录页的物理修改操作。而undo log是逻辑日志,根据每行记录继续记录。