事务
什么是事务
事务是一个任务集合,包含了一系列逻辑相关的任务;
事务能够做什么
保证一系列任务的正确执行,即ACID特性;
事务特性 ACID
事务必须遵循 ACID 特性。
ACID
- A(Atomicity);原子性,即所有任务要么全部成功,要么全部失败;
-
- 任意一个任务失败,都会导致事务失败;
- 提交成功意味着所有任务都执行成功;
- C(Consistency);一致性,即数据在执行前和执行后应当是正确有效的,如A给B转账100元,事务执行完成后应该是B增加了100元,而A减少了100元,很大程度上需要应用层检测控制 (应用层控制) 。在事务执行前后,数据库的约束性条件没有被破坏(数据库层控制)
- I(Isolation);隔离性,即事务之间不能有所影响;如事务1修改用户A,此时事务2删除用户B,如果没有隔离性,那么同时执行时两个事务可能有一个会出错;(通过并发控制锁实现)
-
- 事务1操作数据A时,其他事务不能操作数据A;
- D(Durability);持久性,即事务只要提交成功,那么数据一定不会丢失;(通过redo文件和恢复机制实现)
-
- 提交成功意味着数据一定持久化保存了,即使系统崩溃;
如何保证原子性
通过undo log实现回滚,要么全部成功,要么全部失败。发生故障后,回滚之前的操作。
如何保证一致性
应用层保证。
如何保证隔离性
通过并发控制协议实现,不同的隔离级别下事务的可见性不同。
如何保证持久性
通过redo log实现,只要更新成功(事务提交成功),那么redo log必然生成,而更新成功后即使Buffer Poll未持久化,数据也会被重建。但如果更新失败(事务未提交或提交失败),那么redo log中关于当前事务的记录就不是完整的,需要后续回滚。
事务并发问题
数据管理系统会有多个用户同时使用,那么在使用过程中,如果多个用户同时操作时,那么可能会出现以下问题。
注意:本质上丢失修改和不可重复读是多线程并发读写问题;脏读是读取的不合法数据;
- 脏读(读了不可用的数据);事务读取了其他事务未提交的数据,由于其他事务发生了回滚,导致数据不一致;(必须解决)
-
- A=50
- 事务1修改了A=100;
- 事务2此时读取A=100;
- 事务1提交失败,回滚,此时A=50;
- 事务2返回,结果为A=100,但实际A=50,发生不一致;
- 幻读;范围读取多次,多次结果不一致;与不可重复读区别在于幻读是范围性的;
-
- 事务1统计有10行;
- 其他事务插入了一行新数据;
- 事务1重新统计数据发现是11行;
- 由于多次统计数据不一致,发生了幻读;
- 不可重复读(多线程并发读写问题);事务多次读取数据过程中,其他事务修改了数据导致事务多次读取数据不一致;
- 丢失更新(多线程并发写问题);顾名思义,即事务修改的数据丢失了;(必须解决)
-
- A=50;
- 事务1修改A=200;
- 事务2修改A=100;
- 事务1读取A=100,实际上事务1期望A=200,自身已经修改,但由于其他事务也修改了数据,因此发生了不一致;
事务隔离级别
通过并发控制协议实现了隔离性,基于此之上有多种隔离级别;
- 读未提交;一个未提交的事务对其他事务是可见的;会出现脏读问题;
- 读已提交;一个未提交的事务对其他事务是不可见的;解决了脏读的问题;
- 可重复读;保证一个事务多次读取结果一样;解决了不可重复读和丢失更新问题(写-写并发和读-写并发问题);
- 串行化;所有事务都线性执行执行;解决了幻读问题(一个表同时只能一个事务执行);性能非常低;