什么是数据库事务?如果没有事务会有什么后果?事务的特性是什么?
把事务想象成转账,比如 A 给 B 转账 10 元,需要两个操作:
- 先将 A 的账户减去 10 元
- 然后给 B 的账户加上 10 元
这两个操作要么同时成功,要么同时失败,一旦出现一个失败一个成功的情况,钱的总数就不对了……
这就需要我们在这两个操作前建一个事务,只有当两个操作同时成功时才会将修改提交到数据库,一旦有一个操作失败,就进行事务的回滚,把数据库恢复成一个操作都没有进行之前的样子。
因此,事务需要具有以下 四个特性:
- 原子性: 处在一个事务中的操作要么同时成功,要么同时失败。
- 一致性: 需要与实际业务规则保持一致,如转账操作,两个账户的总金额要保持不变。
- 隔离性: 不同的事务之间没有影响,如脏读就是不同事务间的数据发生了影响。
- 持久性: 事务一旦提交成功,事务中的所有数据必须持久化到数据库中去,就算提交的时候数据库原地崩溃,重启后也要有办法恢复数据。
事务隔离级别
并发事务会遇到的问题
- 脏读: 读到了其他事务未提交的脏数据。
- 不可重复读: 由于其他事务对某个记录进行了 修改 而导致当前事务对某个数据的两次读取结果不同。
- 幻读: 由于其他事务 插入了一条记录 而导致当前事务对某个数据的两次读取结果不同。
四大隔离级别
| 隔离级别 | 可以处理的并发问题 | 描述 | 实现 | 性能 |
|---|---|---|---|---|
SERIALIZABLE (串行化) | 全部 | 事务一个接着一个执行 | 三级 + GAP 锁 | 1星 |
REPEATABLE READ (可重复读) | 脏读,不可重复读 | 所有被 SELECT 的数据不能被修改 | 三级 | 2星 |
READ COMMITTED (读已提交) | 脏读 | 不可重复读,幻读 | 二级 | 3星 |
READ UNCOMMITTED (读未提交) | 无 | 允许其他事务读取未提交的数据 | 啥都不用 | 4星 |
MySQL 默认的隔离级别是REPEATABLE READ,Oracle 默认的隔离级别是READ COMMITTED。
实现详见3.锁机制。