数据库的四大事务特征
在数据库中,事务要满足ACID:
Atomicity 原子性:
- 事务是一个原子性质的操作单元,事务里面的对数据库的操作要么都执行,要么都不执行。
- 例子:银行转账时,假设过程是A账号扣款,B账号加款。这两个步骤要么都执行,要么就都不执行。否则如果只执行了扣款语句,就提交了,此时如果突然断电,A账号已经发生了扣款,B账号却没收到加款,在生活中就会引起纠纷。
Consistent 一致性:
- 一致性是指在事务开始之前和事务结束以后,数据库的完整性约束没有被破坏。这是说数据库事务不能破坏关系数据的完整性以及业务逻辑上的一致性。
- 例子: 对银行转帐事务,不管事务成功还是失败,应该保证事务结束后ACCOUNT表中A和B的存款总额为x元不变。
Isolation 隔离性:
- 数据库允许多个并发事务同事对数据进行操作,隔离性保证各个事务相互独立,事务处理时的中间状态对其它事务是不可见的,以此防止出现数据不一致状态。
- 例子: 在Windows中,如果多个进程对同一个文件进行修改是不允许的,Windows通过这种方式来保证不同进程的隔离性。
Durable 持久性:
- 一个事务处理结束后,其对数据库的修改就是永久性的,即使系统故障也不会丢失。
脏读、幻读和不可重复读的概念
脏读:
所谓脏读是指一个事务中访问到了另外一个事务未提交的数据,如下图:
如果会话 2 更新 age 为 10,但是在 commit 之前,会话 1 希望得到 age,那么会获得的值就是更新前的值。或者如果会话 2 更新了值但是执行了 rollback,而会话 1 拿到的仍是 10。这就是脏读。
不可重复读:
一个事务查询同一条记录2次,得到的结果不一致:
由于在读取中间变更了数据,所以会话 1 事务查询期间的得到的结果就不一样了。
幻读:
一个事务查询2次,得到的记录条数不一致:
幻读是不可重复读的一种特殊场景。
MySQL 数据隔离级别
MySQL 里有四个隔离级别:
- Read uncommttied(可以读取未提交数据)
- Read committed(可以读取已提交数据)
- Repeatable read(可重复读)
- Serializable(可串行化)。
不同事务隔离级别有不同的效果:
在 InnoDB 中,默认为 Repeatable 级别,InnoDB 中使用一种被称为 next-key locking 的策略来避免幻读(phantom)现象的产生。
隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大。