oracle并发与多版本控制

1 相关概念

1.1 并发控制

数据库对多个用户同时查询或者操作数据的管理。

1.2 多版本控制

oracle能物化多个版本的数据,使在一个时间点读一个表,保证在这个时间点读到的表数据是一致的。oracle的多版本控制机制是oracle提供读一致性的基础。

1.3 事务的作用

事务使数据库从一种一致性状态转变为另外一种一致性状态。

2 事务的隔离级别

并发访问可能导致的三种现象。

  • 脏读:读到别的事务中没有提交的数据
  • 不可重复读:一个时间点读取到的一行数据和在另外一个时间点读到同一行的数据不一致。
  • 幻读:一个时间点读到的数据的行数,同样的查询条件在另外一个时间点读取,发现行数增加了。
    根据并发访问可能导致的三种现象,定义事务的4种隔离级别

    读未提交:可以读取别的事务中未提交的数据
    读已提交:不能读取别的事务中未提交的数据,只能读取别的事务中已提交的数据
    可重复读:保证不同时间点读取同一行数据,数据不会发生变化
    可串行化:同样的查询条件,不同的时间点查询,数据和数据量都不会发生变化

3 oracle多版本控制机制

3.1 举例说明多版本控制机制

假设我们要查询这么一个表
select sum(account_balance) from accounts;

假设在查询开始前,数据如图7.2所示

SELECT语句开始执行,读取第1行、第2行等。在查询中的某个时刻,一个事务将$400.00从账户123转到账户987。这个事务完成了两个更新, 但是并没有提交。现在的数据表如图7-3所示。

此时发生更新的两行数据已被锁定,如果有人试图更新这两行,该用户就会被阻塞。

我们执行的查询要访问一个数据块,这个数据块中包含表最后已锁定的行(第34023行), 此时它应该会发现这一行中的数据在此查询开始执行之后有所改变。为了提供一个一致的答案,Oracle在这个时刻会复制这个块的数据到数据库高速缓存,然后根据undo数据回滚复制的块的数据,回滚到刚开始查询那一刻这个块已提交的数据。然后就可以读取到开始查询那一刻的数据(100),而不是读取修改后的数据(500)。这样统计出来的数据就能保证一致性。

3.2 长时间的查询导致I/O异常

一个耗时很长的SQL可能会导致I/O上升的非常高,因为这个sql在查询后面的块时,因为时间已过去很久,所以这些块很可能已经被别的事务修改过,oracle需要复制这些块,使用undo信息回滚这些复制的块,是复制的块的数据回滚到刚开始查询的样子。而复制和回滚的操作可能需要I/O获取。而且,如果undo信息已过期,即oracle无法根据undo信息回滚,就会报'ORA-1555 snapshot too old'的错误。

3.3 oracle重启动

重启动是指当前事务修改另外一个事务中没提交的数据,当前事务会阻塞,直到另外一个事务提交。另外一个事务提交后,当前事务执行sql,但是数据已经修改。所以当前事务会回滚这个sql再重新执行一遍sql。

重启动现象的案例:https://blog.51cto.com/webseven/1590985