1. You have already known about "Read Consistency" — 如果数据在语句/事务开始时没变化,就返回这行数据;否则,从回滚段里读它的Snapshot. 这叫做"Consistent Read"
2. 与之相对的是
“Current Read” — 不去读回滚段,而是从当前数据文件里去读。
a. When does it happen? 在准备修改数据时进行Current Read
b. 举例说明,
Update t set y = 1 where x = 5
i.首先会执行 "select .. from t where x = 5",这个过程使用的是"Consistent Read",即找到回滚段里满足 x = 5的记录
ii.在准备执行 "set y = 1" 时会再检查一下数据文件中该条记录是否仍满足 "x = 5".这个过程使用的就是"Current Read"
iii.如果这时该记录已经被另一个事务变成了"x = 6"了,那会怎么办?
3.
如果"current read"时发现数据已经变了(不再满足原来的where条件),则重启整条语句。
a.重启后的执行步骤和原来一样,也是先用Consistent Read找到记录,再通过Current Read判断数据是否已经不再满足where条件
b.唯一的不同是重新运行时会用 select … for update 找到数据并锁住
c.如果重启后执行仍不成功,则再次重启,如此往复…
4.
重启的后果:
a.
Before类型的触发器会执行两次!“试修改”时执行一次,正式修改时又执行一次!
b.
重启可能会影响性能。
如果一条语句在更新1000条记录被其它事务引发重启,该条语句又要从头开始运行,前面的1000条更新都白做了。
5.
Before类型的触发器本身也可能引发重启。如果这类触发器引用的列值与Where子句中的列值有交叠,那它在执行时也会做一下Current Read,然后与where子句中的条件进行比较,如果不一致就会引发重启。所以用这种触发器时要小心。