隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
read-unconmitted | √ | √ | √ |
read-conmitted | × | √ | √ |
repeatable-read | × | × | √ |
serializable | × | × | × |
1、事务的基本要素(ACID)
- 原子性(Atomicity):事务开始后所有操作,要么全部做完,要么全部不做,不可能停滞在中间环节。事务执行过程中出错,会回滚到事务开始前的状态,所有的操作就像没有发生一样。也就是说事务是一个不可分割的整体,就像化学中学过的原子,是物质构成的基本单位。
- 一致性(Consistency):事务开始前和结束后,数据库的完整性约束没有被破坏 。比如A向B转账,不可能A扣了钱,B却没收到。
- 隔离性(Isolation):同一时间,只允许一个事务请求同一数据,不同的事务之间彼此没有任何干扰。比如A正在从一张银行卡中取钱,在A取钱的过程结束前,B不能向这张卡转账。
- 持久性(Durability):事务完成后,事务对数据库的所有更新将被保存到数据库,不能回滚。
2、隔离级别
read-unconmitted
可以读到其他事务未提交的数据,是最低级别的事务隔离级别。
例如:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是错误的,称之为脏数据。
read-conmitted
为了解决脏读,就需要保证读取被事务提交的数据,也就是read-conmitted。
看一个例子:
事务A读一个数据,读到100. 此时另外一个线程执行事务B将数据改为200,并提交事务。 接下来事务A再次读该数据,读到200.
这种在一个事务中两次读取到数据不一致的情况,我们称之为不可重复读。
repeatable-read
为了解决不可重复读,就需要保证一个事务在操作一份数据时,不允许其他事务操作该数据。此时反应到数据库上,就是需要对行加锁。这种隔离级别称之为repeatable-read。
看一个例子:
事务A统计当天营业额(遍历表,计和),为1000. 事务B插入一条销售记录,200。 事务A再统计当天营业额,为1200.
这种一个事务中前后两次统计不一致的情况,称之为幻读。
serializable
为了解决幻读,只能严格要求所有线程的所有事务都按照顺序依次执行,也就是 表锁。
但是此种级别并发性太差,且一般也没有必要。
3、总结
我们需要区分事务的隔离级别和现象。
隔离级别是指导原则,现象是产生的问题,而数据库锁则是解决手段。
Mysql默认隔离级别是 repeatable-read。
Oracle默认隔离级别是 read-conmitted。