数据库事务
数据库事务
- 事务的ACID
- 事务的隔离级别
- 锁
- MVCC(多版本并发控制)
- 事务优化
事务的ACID
- 原子性(Atomicity):当前事务的操作要么同时成功,要么同时失败。原子性由undolog日志来实现。
- 一致性(Consistent):使用事务的最终目的,由其它3个特性以及业务代码正确逻辑来实现。
- 隔离性(Isolation):在事务并发执行时,他们内部的操作不能互相干扰。隔离性由MySQL的各种锁以及MVCC机制来实现。
- 持久性(Durable):一旦提交了事务,它对数据库的改变就应该是永久性的。持久性由redolog日志来实现。
事务的隔离级别
Mysql的默认隔离级别是可重复读;Oracle的默认隔离级别是读已提交
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
读未提交 | Y | Y | Y |
读已提交 | N | Y | Y |
可重复读 | N | N | Y |
串行化 | N | N | N |
脏读:读到事务未提交的数据
不可重复读:同一事务前后两次查询同一条数据结果不一致(中间有其他事务提交数据)
幻读:可以修改其他事务新增的数据,在本事务中修改之前通过select查不到该数据
锁
- 读锁(共享锁,S锁):一般的select语句不会加锁,如果想加锁使用select…lock in share mode。读锁是共享的,多个事务可以同时读取同一资源,但是不允许其他事务修改。
隔离级别为串行化时,读操作底层会自动加上读锁,其他隔离级别的读操作不会自动加读锁。 - 写锁(排他锁,X锁):insert,delete,update,select…for update 都会加写锁。写锁是排他的,会阻塞其他的写锁和读锁。
MVCC(多版本并发控制)
- 3个字段:rowid,trx_id(事务id),roll_pointer(回滚指针)
- 如果有主键,rowid用不着
- trx_id: 修改当前数据的事务id
- roll_pointer:指向当前数据的上一个版本,第一个版本指向回滚语句
事务优化
- 将查询等数据准备操作放到事务外
- 事务中避免远程调用,远程调用要设置超时,防止事务等待时间太久
- 事务中避免一次性处理太多数据,可以拆分成多个事务分次处理
- 更新等涉及加锁的操作尽可能放在事务靠后的位置
- 能异步处理的尽量异步处理
- 应用侧(业务代码)保证数据一致性,非事务执行–应用性能要求很高,且业务相对简单,不然容易出bug