事务的定义
- 事务:事务是一个最小的不可在分的工作单元;通常一个事务对应一个完整的业务(例如银行账户转账业务,该业务是一个最小的工作单元)
- 一个完整的业务需要批量的DML(insert、update、delete)语句共同联合完成。
- 事务只和DML语句有关,或者说DML语句才有事务。这个和业务逻辑有关,业务逻辑不同,DML语句的个数不同。
设置事务的目的
多条SQL要么同时成功,要么同时失败。
事务相关的术语
- 开启事务:Start Transaction
- 事务结束:End Transaction
- 事务提交: Commit Transaction
- 事务回滚: Rollback Transaction
在MySQL中,事务提交与回滚
对t_act进行提交和回滚操作
(1).提交操作(非事务成功)
update t_act set balance=400 where actno=1;
update t_act set balance=200 where actno=2;
(2).提交操作(非事务失败)
update t_act set balance=400 where actno=1;
update t_act set balance=200 where actno=2 w;
(3).提交操作(事务成功)
- start transaction #开始事务
- DML语句
- commit #事务提交
start transaction;#手动开启事务
update t_act set balance=400 where actno=1;
update t_act set balance=200 where actno=2;
commit;#commit之后即可改变底层数据库数据
(4).提交操作(事务失败)
start transaction;#手动开启事务
update t_act set balance=400 where actno=1;
update t_act set balance=200 where actno=2w; #这个地方故意让第二个语句出错
commit;#commit之后即可改变底层数据库数据
(5).回滚操作(事务失败)
回滚操作指的是当我们事务提交失败的时候,就需要我们将数据回滚到失败前的时间段
比如,delete一张表,忘加限制条件,整张表没了。
误操作后,能快速回滚数据是非常重要的。
- start transaction
- DML语句
- rollback
start transaction;#手动开启事务
delete from t_act;
rollback;
事务的特性
1.原子性(A):指一个事物是一个不可分割的工作单位,其中的操作要么都成功,要么都失败。
当事务发现有些语句不能执行时,需要将数据恢复到事务执行前,通过undo log实现。
undo log是mysql中比较重要的事务日志之一,顾名思义,undo log是一种用于撤销回退的日志, 在事务没提交之前,MySQL会先记录更新前的数据到 undo log日志文件里面, 当事务回滚时或者数据库崩溃时,可以利用 undo log来进行回退。
事务提交到redolog日志池中,提交进去后叫undolog日志,如果监测undolog日志没有问题,再去让它操作数据。
2.持久性(I): 指事务一旦提交,它对数据库的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
持久性问题的产生:
背景:Mysql为了保证存储效率,每次读写文件都是先对缓存池(Buffer Pool)操作, 缓冲池再定期刷新到磁盘中(这一过程称为刷脏)。
产生:由于数据不是直接写到磁盘,那么如果主机断电,就会有一部分数据丢失。
解决:通过重做日志(redo log)恢复数据。在每次修改数据之前, 都会将相应的语句写到redo log中,如果主机断电,那么再次启动时可通过redo log回复。
拓展:redo log也需要在事务提交时将日志写入磁盘,它比缓冲池写入快的原因有两点: redo log是追加文件写,属于顺序IO,缓冲池是属于随机IO,且刷脏是以页为单位, 有一点修改就要整页写入。
造成持久性危机的是因为两段式提交。
commit提交提交到缓冲池中,当前数据池会定期刷脏,检测当前redolog,修改数据。
3.隔离性(D): 隔离性是指,事务内部的操作与其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
与原子性、持久性侧重于研究事务本身不同,隔离性研究的是不同事务之间的相互影响。
下边讲到的事务并发问题就是隔离性的问题,MVCC就是解决这些问题的。
4.一致性(C):指事务执行结束后,数据库的完整性约束没有被破坏,开始1000块钱,后面转账结束了,也得是1000块钱。
实现:前面提到的原子性、持久性和隔离性,都是为了保证数据库状态的一致性。
事务的隔离等级
- 读未提交 read uncommitted
- 读已提交 read committed
- 可重复读 repeatable read
- 串行化 serializable
并发问题总结
1.脏读:事务A读取到了事务B修改但未提交的数据。
2.不可重复读:事务A读取到了事务B提交后的数据,对于事务A来说,读取数据在事务B提交之前和之后是不一样的。
3.幻读:当事务A要去查询表当中的数据,与此同时第二个事务对表进行了增删改操作,那么对于事务A来说,查询不到事务B的任何操作,就跟出现了幻觉一样。
隔离级别与一致性的关系
对于MySQL来说,它设置的隔离级别就是可重复读的隔离级别。