本文已参与「新人创作礼」活动,一起开启掘金创作之路。
本文介绍数据库事务,包括:并发事务存在的问题、隔离级别、隔离级别与并发事务存在的问题之间的关系、MVCC
并发事务存在的问题
- 数据丢失:修改了已提交的值。示例:T1查询,T2查询,T1修改提交,T2修改提交并没有读到T1的修改。无锁的状态
- 脏读:读取到了未提交的数据。示例:T1改值后,T2读取到该值,T1回滚,T2读到了脏数据
- 不可重复读:同一个事务中执行完全相同的select语句时可能看到不一样的结果。示例:T1查询,T2改值提交,T1再次查询,得到了不同的值
- 幻读:示例:T1读取某范围数据,T2在该范围插入了新行提交,T1再次读取某范围数据,发现有了新的行
锁定义
- 排他锁(X锁):写数据时使用。锁住后,除非释放, 否则其他事务无法获得X锁
- 共享锁(S锁):主要用于读取数据。如果一个数据加了X锁,就没法加S锁,同样加了S锁,就没法加X锁。两个S锁读数据互不影响。
隔离级别
| 隔离级别 | 说明 |
|---|---|
| Read uncommitted | 最低的隔离级别。它充许另外一个事务可以看到这个事务未提交的数据,很少实际应用。可能出现脏读(写用排他锁) |
| Read committed | 大多数数据库系统默认隔离级别。一个事务只能看见已经提交事务所做的改变。可能出现不可重复读(写用排他锁,读用共享锁-立即释放) |
| Repeatable read | MySQL默认事务隔离级别。确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。可能出现幻读(写用排他锁,读用共享锁-事务提交释放) |
| Serializable | 最高的隔离级别。通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。可能导致大量的超时现象和锁竞争(串行化,读写都用排他锁) |
隔离级别与并发事务存在的问题之间的关系
| 隔离级别 | 数据丢失 | 脏读 | 不可重复读 | 幻读 |
|---|---|---|---|---|
| Read uncommitted | No | Yes | Yes | Yes |
| Read committed | No | No | Yes | Yes |
| Repeatable read | No | No | No | Yes |
| Serializable | No | No | No | No |
MVCC
Multi-Version Concurrency Control多版本并发控制,MVCC是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问。 为了提高数据库系统的并发性能,不再单纯的使用行锁来进行数据库的并发控制,实现了对读的非阻塞,读不加锁,读写不冲突。缺点是每行记录都需要额外的存储空间,需要做更多的行维护和检查工作。
ACID
ACID 是数据库管理系统为了保证事务的正确性而提出来的一个理论
- Atomicity(原子性):一个事务中的所有操作,要么全部完成,要么全部不完成,不会在中间某个环节结束。
- Consistency(一致性):在事务开始之前和事务结束以后,数据库的完整性没有被破坏。
- Isolation(隔离性):数据库允许多个并发事务同时对数据进行读写和修改的能力。隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。
- Durability(持久性):事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。