系列文章
1.事务的特性
ACID
1.1原子性
事务中的操作,要么全部成功,要么全部失败;对于一个事务来说,不可能只执行其中的一部分操作
1.2一致性
数据库总是从一个一致性的状态转换到另一个一致性的状态
原子性
和一致性
的侧重点不同:原子性关注状态,要么全部成功,要么全部失败,不存在部分成功的状态。而一致性关注数据的可见性,中间状态的数据对外部不可见,只有最初状态和最终状态的数据对外可见
1.3隔离性
并发过程中,事务在最终提交之前是相互隔离的,不能相互干扰
1.4持续性
一旦事务提交,则其所做的修改不会永久保存到数据库
2事务并发产生的问题
2.1脏读
- 事务A第一次读取到price=100
- 同时事务B更新update price=120,但是此时的事务B还未commit
- 事务A读取的price=120
- 事务B->rollback操作
- 事务A读取到的是脏数据
2.2不可重复读
- 事务A第一次读取到price=100
- 同时事务B更新update price=120,并commit
- 事务A读取的price=120
- 事务A多次读取的结果不一致
2.3幻读
幻读和不可重复读的区别在于,幻读主要表现在数据的
删除
和插入
,而不可重复读表现在数据的更新
- 事务A第一次读取到price=100
- 同时事务B更新delete price=100 这条记录,并commit
- 事务A读取的price=100
- price这条记录已经不存在,但是事务A还是可以读取到
3数据库提供的解决方法
mysql提供了4种隔离级别
3.1read uncommitted 未提交读
2.1中脏读
的场景,事务A可以读取到事务B update->price = 120 还未提交的值,但是如果事务B没有commit而是rollback就会产生脏读
问题
这种隔离级别最低,但是并发性能最好,事务A不需要阻塞等待事务B去完成提交
3.2read committed 已提交读
可以解决上面脏读的问题
读取已经commit
的内容,事务A必须等事务Bcommit
之后再去读取price更新之后的值
但是它存在不可重复读
的问题,同一事务范围内多次读取的数据不一致
3.3repeatable read 可重复读
mysql默认的隔离级别
就是解决不可重复读
的问题,保证同一事务读取的值是一致的
3.4serializable 可串行化
多个事务并发,串行排队执行,事务A必须等待事务B全部执行完,才开始执行
这种隔离级别最高,但是并发性能最差,相当于java中synchronized
重量级锁
4.总结
数据隔离的级别越高,并发性能越差,反之亦然
四种隔离级别存在的问题,√表示依然存在问题,×表示已经不存在问题
注:InnoDB中虽然是
repeatable read
隔离级别,但是解决了幻读问题,通过Next-key Locks
+MVCC
的方式
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
read uncommitted(未提交读) | √ | √ | √ |
read committed(已提交读) | × | √ | √ |
repeatable read(可重复读) | × | × | √ (InnoDB为×) |
serializable(可串行化) | × | × | × |