前言
从事务说起,事务(Transaction)就是访问和更新数据库的程序执行单元,事务中可能包含一个或多个sql语句,这些语句要么都执行,要么都不执行。
在数据库系统中,一个事务是指:由一系列数据库操作组成的一个完整的逻辑过程。例如银行转帐,从原账户扣除金额,以及向目标账户添加金额,这两个数据库操作的总和,构成一个完整的逻辑过程,不可拆分。这个过程被称为一个事务,具有ACID特性。
ACID是衡量事务的四个特性
- 原子性(Atomicity)
- 一致性(Consistency)
- 隔离性(Isolation)
- 持久性(Durability).
而ACID是衡量事务的四个特性,这并不意味着事务全部必须满足ACID的特性。在许多地方的实际应用中,这四个特性并没有被完全实现,比如MySQL的事务中就不支持原子性,所以后来这四个特性渐渐地变成了衡量事务的标准而不是事务的必须条件。
拿MySQL来说,逻辑备份日志(binlog)、重做日志(redolog)、回滚日志(undolog)、锁技术 + MVCC就是MySQL实现事务的基础。
- 原子性:通过undolog来实现。
- 持久性:通过binlog、redolog来实现。
- 隔离性:通过(读写锁+MVCC)来实现。
- 一致性:MySQL通过原子性,持久性,隔离性最终实现(或者说定义)数据一致性。
下面我们来仔细来聊聊下这四个特性
A-原子性
单个事务,为一个不可分割的最小工作单元
,整个事务中的所有操作要么全部commit成功,要么全部失败rollback,对于一个事务来说,不可能只执行其中的一部分SQL操作,这就是事务的原子性
begin transaction; update account set money = money-100 where name = '张三'; update account set money = money+100 where name = '李四'; commit transaction;
比如上述代码执行的一个事务中:俩条sql语句要么都成功要么都失败
事务通常是以BEGIN TRANSACTION 开始,以 COMMIT 或 ROLLBACK 结束。
- COMMIT 表示提交,即提交事务的所有操作并持久化到数据库中。
- ROLLBACK表示回滚,即在事务中运行的过程中发生了某种故障,事务不能继续执行,系统将事务中对数据库所有已完成的操作全部撤销,回滚到事务开始时的状态,这里的操作指对数据库的更新操作,已执行的查询操作不用管。这时候也就需要用到 undolog 来进行回滚。
C-一致性
事务必须使数据库从一个一致性状态变换到另外一个一致性状态。
换一种方式理解就是:事务按照预期生效,数据的状态是预期的状态。
举例说明:张三向李四转100元,转账前和转账后的数据是正确的状态,这就叫一致性,如果出现张三转出100元,李四账号没有增加100元这就出现了数据错误,就没有达到一致性。
I-隔离性
事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。
张三给李四转账,如果事务没有提交的话,那么在另外一个session中并不能查看另外一个session未提交的数据。
1)脏读:指的是读到了其他事务未提交的数据,未提交意味着这些数据可能会回滚,也就是可能最终不会存到数据库中,也就是不存在的数据。读到了并不一定存在的数据,这就是脏读。
2)可重复读:在一个事务内,最开始读到的数据和事务结束前的任意时刻读到的同一批数据都是一致的。
3)不可重复读:对比可重复读,不可重复读指的是在同一事务内,不同时刻读到的同一批数据可能是不一样的,可能会受到其他事务的影响,比如其他事务改了这一批数据并提交了。
4)幻读:幻读是针对数据插入操作来说的,假设事务A对某些行的内容做了更改,但是还未提交,此时事务B插入了与事务A更新签的记录相同的记录行,并且在事务A提交之前先提交了,而这时,在事务A中查询,会发现好像刚刚的更改对于某些数据未起作用,但其实事务B刚插入进来的,让用户感觉到魔幻,这就是幻读。
隔离级别 |
脏读 |
不可重复读 |
幻读 |
读未提交 | 可能 | 可能 | 可能 |
读已提交 | 不可能 | 可能 | 可能 |
可重复读 | 不可能 | 不可能 | 可能 |
串行化 | 不可能 | 不可能 | 不可能 |
D-持久性
一旦事务提交,则其所做的修改就会永久保存到数据库中。此时即使系统崩溃,修改的数据也不会丢失。
就是数据的持久化