文章目录
一、前言
最近在读《MySQL 是怎样运行的》、《MySQL技术内幕 InnoDB存储引擎 》,后续会随机将书中部分内容记录下来作为学习笔记,部分内容经过个人删改,因此可能存在错误,如想详细了解相关内容强烈推荐阅读相关书籍
系列文章内容目录:
- 【MySQL00】【 杂七杂八】
- 【MySQL01】【 Explain 命令详解】
- 【MySQL02】【 InnoDB 记录存储结构】
- 【MySQL03】【 Buffer Pool】
- 【MySQL04】【 redo 日志】
- 【MySQL05】【 undo 日志】
- 【MySQL06】【MVCC】
- 【MySQL07】【锁】
- 【MySQL08】【死锁】
二、事务
1. 事务的四大特性(ACID)
1.1. 原子性
一个事务中所有对数据库的操作是一个不可分割的操作序列,要么全做要么全不做
即事务是执行的最小单元,执行结果只有两个,要么成功,要么失败回滚。
1.2. 一致性
一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。数据不会因为事务的执行而遭到破坏。
比如,当数据库只包含成功事务提交的结果时,就说数据库处于一致性状态。如果数据库系统在运行中发生故障,有些事务尚未完成就被迫中断,这些未完成事务对数据库所做的修改有一部分已写入物理数据库,这时数据库就处于一种不正确的状态,或者说是不一致的状态。
1.3. 持久性
持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,接下来的任何操作和故障都不应该影响到已提交的事务执行结果。
例如我们在使用JDBC操作数据库时,在提交事务方法后,提示用户事务操作完成,当我们程序执行完成直到看到提示后,就可以认定事务以及正确提交,即使这时候数据库出现了问题,也必须要将我们的事务完全执行完成,否则就会造成我们看到提示事务处理完毕,但是数据库因为故障而没有执行事务的重大错误。
1.4. 隔离性
一个事务的执行不能其它事务干扰。即一个事务内部的操作及使用的数据对其它并发事务是隔离的,并发执行的各个事务之间不能互相干扰。
隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。
2. 脏写、脏读、不可重复读、幻读
-
脏写:如果一个事务修改了另一个未提交事务修改过的数据,就意味着发生了脏写。所有的隔离级别都不会出现这种情况。
-
脏读:脏读又称无效数据读出。一个事务读取另外一个事务还没有提交的数据叫脏读。
例如:事务T1修改了一行数据,但是还没有提交,这时候事务T2读取了被事务T1修改后的数据,之后事务T1因为某种原因Rollback了,那么事务T2读取的数据就是脏的。
-
不可重复读:不可重复读是指在同一个事务内,两个相同的查询返回了不同的结果。
例如:事务T1读取某一数据,事务T2读取并修改了该数据,T1为了对读取值进行检验而再次读取该数据,便得到了不同的结果。
解决:使用行级锁,锁定该行,事务A多次读取操作完成后才释放该锁,这个时候才允许其他事务更改刚才的数据
-
幻读:在同一事务内,两次相同的查询返回的数据条目数量不同,在RU、RC、RR级别下,都会出现幻读
例如:事务T1读取一次表中数据总量,事务T2修改了表中数据总量(插入或者删除了数据)。这是事务T1再次读取表中数据总量,发现和第一次读取的总量不同,好像产生了幻觉。
亦或者,在可重复读的隔离级别下,事务T1查询了记录a,发现不存在,准备插入记录a,但是此时事务T2开启并插入了记录a,此时事务T1才开始准备插入,但是T1插入会失败,因为库里已经存在记录a,此时T1即便再次查询记录a也无法查询到。这是因为mvcc的特性,由于T2比T1晚开启,T1是不会读取到T2修改的记录。解决:使用表级锁,锁定整张表,事务A多次读取数据总量之后才释放该锁,这个时候才允许其他事务新增数据。
注意:
- 脏写、脏读、不可重复读、幻读,解决该问题所需要的隔离级别,高低是:脏写 < 脏读 (读已提交)< 不可重复读(可重复读) < 幻读(可串行化)