[关闭]
@chenxuxiong 2016-05-29T05:14:00.000000Z 字数 2310 阅读 425

事务的隔离级别

数据库


1.事务的ACID是指什么?

答:
- 原子性(Atomic):事务中各项操作,要么全做要么全不做,任何一项操作的失败都会导致整个事务的失败;
- 一致性(Consistent):事务结束后系统状态是一致的;
- 隔离性(Isolated):并发执行的事务彼此无法看到对方的中间状态;
- 持久性(Durable):事务完成后所做的改动都会被持久化,即使发生灾难性的失败。通过日志和同步备份可以在故障发生后重建数据。

2.什么时候需要事务?

只有存在并发数据访问时才需要事务。

3.当多个事务访问同一数据时,会出现什么读取问题?事务的五类问题?

当多个事务访问同一数据时,可能会存在5类问题,包括3类数据读取问题(脏读、不可重复读和幻读)和2类数据更新问题(第1类丢失更新和第2类丢失更新)。

  1. 时间 转账事务A 取款事务B
  2. T1 开始事务
  3. T2 开始事务
  4. T3 查询账户余额为1000
  5. T4 取出500元余额修改为500
  6. T5 查询账户余额为500元(脏读)
  7. T6 撤销事务余额恢复为1000
  8. T7 汇入100元把余额修改为600
  9. T8 提交事务
  1. 时间 转账事务A 取款事务B
  2. T1 开始事务
  3. T2 开始事务
  4. T3 查询账户余额为1000
  5. T4 查询账户余额为1000
  6. T5 取出100元修改余额为900
  7. T6 提交事务
  8. T7 查询账户余额为900元(不可重复读)
  1. 时间 统计金额事务A 转账事务B
  2. T1 开始事务
  3. T2 开始事务
  4. T3 统计总存款为10000
  5. T4 新增一个存款账户存入100
  6. T5 提交事务
  7. T6 再次统计总存款为10100元(幻读)
  1. 时间 取款事务A 转账事务B
  2. T1 开始事务
  3. T2 开始事务
  4. T3 查询账户余额为1000
  5. T4 查询账户余额为1000
  6. T5 汇入100元修改余额为1100
  7. T6 提交事务
  8. T7 取出100元将余额修改为900
  9. T8 撤销事务
  10. T9 余额恢复为1000元(丢失更新)
  1. 时间 转账事务A 取款事务B
  2. T1 开始事务
  3. T2 开始事务
  4. T3 查询账户余额为1000
  5. T4 查询账户余额为1000
  6. T5 取出100元将余额修改为900
  7. T6 提交事务
  8. T7 汇入100元将余额修改为1100
  9. T8 提交事务
  10. T9 查询账户余额为1100元(丢失更新)

数据并发访问所产生的问题,在有些场景下可能是允许的,但是有些场景下可能就是致命的,数据库通常会通过锁机制来解决数据并发访问问题,按锁定对象不同可以分为表级锁和行级锁;按并发事务锁定关系可以分为共享锁和独占锁,具体的内容大家可以自行查阅资料进行了解。
直接使用锁是非常麻烦的,为此数据库为用户提供了自动锁机制,只要用户指定会话的事务隔离级别,数据库就会通过分析SQL语句然后为事务访问的资源加上合适的锁,此外,数据库还会维护这些锁通过各种手段提高系统的性能,这些对用户来说都是透明的(就是说你不用理解,事实上我确实也不知道)。

4.事务的隔离级别

为了避免上面出现的几种情况,在标准SQL规范中,定义了4个事务隔离级别,不同的隔离级别对事务的处理不同。

未授权读取

也称为读未提交(Read Uncommitted):允许脏读取,但不允许更新丢失。如果一个事务已经开始写数据,则另外一个事务则不允许同时进行写操作,但允许其他事务读此行数据。该隔离级别可以通过“排他写锁”实现。

授权读取

也称为读提交(Read Committed):允许不可重复读取,但不允许脏读取。这可以通过“瞬间共享读锁”和“排他写锁”实现。读取数据的事务允许其他事务继续访问该行数据,但是未提交的写事务将会禁止其他事务访问该行。

可重复读取(Repeatable Read)

可重复读取(Repeatable Read):禁止不可重复读取和脏读取,但是有时可能出现幻读数据。这可以通过“共享读锁”和“排他写锁”实现。读取数据的事务将会禁止写事务(但允许读事务),写事务则禁止任何其他事务。

序列化(Serializable)

序列化(Serializable):提供严格的事务隔离。它要求事务序列化执行,事务只能一个接着一个地执行,不能并发执行。仅仅通过“行级锁”是无法实现事务序列化的,必须通过其他机制保证新插入的数据不会被刚执行查询操作的事务访问到。

隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大。对于多数应用程序,可以优先考虑把数据库系统的隔离级别设为Read Committed。它能够避免脏读取,而且具有较好的并发性能。尽管它会导致不可重复读、幻读和第二类丢失更新这些并发问题,在可能出现这类问题的个别场合,可以由应用程序采用悲观锁或乐观锁来控制。

如下表所示:

  1. 隔离级别 脏读 不可重复读 幻读 第一类丢失更新 第二类丢失更新
  2. READ UNCOMMITED 允许 允许 允许 不允许 允许
  3. READ COMMITTED 不允许 允许 允许 不允许 允许
  4. REPEATABLE READ 不允许 不允许 允许 不允许 不允许
  5. SERIALIZABLE 不允许 不允许 不允许 不允许 不允许

需要说明的是,事务隔离级别和数据访问的并发性是对立的,事务隔离级别越高并发性就越差。所以要根据具体的应用来确定合适的事务隔离级别,这个地方没有万能的原则。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注