一、事务定义
- 事务:事务是一个最小的不可在分的工作单元;通常一个事务对应一个完整的业务(例如银行账户转账业务,该业务是一个最小的工作单元)
- 一个完整的业务需要批量的DML(insert、update、delete)语句共同联合完成。
- 事务只和DML语句有关,或者说DML语句才有事务。这个和业务逻辑有关,业务逻辑不同,DML语句的个数不同。
- 开启事务:Start Transaction
- 事务结束:End Transaction
- 事务提交: Commit Transaction
- 事务回滚: Rollback Transaction
1.为什么要设置事务:保证多条sql要么同时成功,要么同时失败。
2.一个事务理解的小例子:
转账业务:
分为非事务和事务两种情况
二、事务的四大特性(ACID,分别是原子性、一致性、持久性、隔离性)
1.原子性:指一个事物是一个不可分割的工作单位,其中的操作要么都成功,要么都失败.
1.1 undo log日志
undo log是mysql中比较重要的事务日志之一,顾名思义,undo log是一种用于撤销回退的日志,
在事务没提交之前,MySQL会先记录更新前的数据到 undo log日志文件里面,
当事务回滚时或者数据库崩溃时,可以利用 undo log来进行回退(事务回滚:rollback)。
2.持久性: 指事务一旦提交,它对数据库的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
2.1如何保证故障不会影响持久性的:
利用了缓存池(Buffer Pool)来刷脏(缓冲池再定期刷新到磁盘中)。事务提交不是直接提交到磁盘了,而是先提交到缓存池里面,再定期刷脏到磁盘中。
如果电脑出现了故障,通过重做日志(redo log)恢复数据
3.隔离性:事务内部的操作与其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
4.一致性:指事务执行结束后,数据库的完整性约束没有被破坏,例如转账之前总金额1000,转账之后,总金额没变化。
前面的原子性、隔离性和持久性都是为了保证数据库的一致性。
三、事务的并发问题
1.脏读:事务A读到了事务B修改但是没有提交的数据;
左边事务读到了右边事务没有提交的数据。
2.不可重复读:事务A查询同一条语句的前后结果不一样(B事务提交前后结果)。
对于左边事务,读取的两次数据不一样,原因是事务B进行了修改。
3.幻读:每个事务都处于自己的世界,不受别的事务影响,就像有幻觉一样
左边事务一直进行查询结果都一样,但是右边事务做了很多的修改操作,左边事务却处于自己的世界,不受任何影响。
四、事务的隔离级别
1.读未提交: read uncommitted ---隔离级别最低,什么并发问题都解决不了
set global transaction isolation level read uncommitted; #查看当前隔离级别 select @@global.tx_isolation,@@tx_isolation;
会产生脏读:事务A会读到B未提交的数据
2.读已提交: read committed ---可以解决脏读的问题,但是会出现不可重复读的问题
set global transaction isolation level read committed; 查看当前隔离级别 select @@global.tx_isolation,@@tx_isolation;
会产生不可重复读:事务A多次查询到的结果不一致(B事务前后提交前后)
3.可重复读:repeatable read --可以解决不可重复读,但是可能会导致幻读
set global transaction isolation level repeatable read; 查看当前隔离级别 select @@global.tx_isolation,@@tx_isolation;
mysql的默认隔离级别
会产生幻读:A事务和B事务都沉浸在自己的操作中,无法出来(在自己的事务环境中,别的事务改变自己不会收到任何影响)
4.串行化:serializable---解决了上面所有的问题---让事务一个一个执行
set global transaction isolation level serializable; 查看当前隔离级别 select @@global.tx_isolation,@@tx_isolation;
缺点:吞吐量太小,隔离级别太高,降低了效率
5.隔离级别和一致性的关系图: