zoukankan      html  css  js  c++  java
  • 数据库 一致性读&&当前读

    今天小伙伴问了一个sql的问题:

      update t set status=2 where id in(select id from t where status=1)

    这个sql,在并发的情况下,会不会有问题?

    假设:下面的讨论,数据库的事务隔离级别是read_committed

    其实这个可以很容易测试一下,得出结论:存在丢失更新的问题。

    先来理解两个概念:

    1. 一致性读

      当前的数据库产品级别都实现了多版本一致性,即MVCC,那么有了MVCC,数据库实现了读写互不阻塞的效果。
    但为了达到read_committed事务隔离级别,以及语句级的读一致性,select语句需要构建一个版本,数据库会根据一个版本号,来构建。
    比如oracle使用scn号,为了构建这个版本,产生的读,称为一致性读。

    2. 当前读
      数据库在写入的过程中,比如update,因为要验证constraint,冲突等,需要读到当前数据,包括没有commit的事务,这样就产生了当前读。

    oracle中英文解释:

      一致性读:  Consistent read

      当前读:  Current read

    而上面的这个语句,就存在了两种读取。

      select: 会进行一致性读,
      update:会进行当前读。

    而在并发的情况下: 第二个update可能因为更新到同一行(其他更新本行的事务未提交),而被阻塞。
    当另一个事务提交后,第二个update会再次构建当前读,会把status从2再次更新成2.

    如何避免:

    1. 更改语句:
        update t set status=2 where id in(select id from t where status=1) and status=1;

    2. 调整事务的隔离级别

  • 相关阅读:
    学习笔记::有上下界的网络流
    zoj2314
    bzoj3261
    bzoj 1898
    bzoj4009
    bzoj4033
    bzoj3389
    bzoj2427
    uva 11825
    交换A与B值的四种方法
  • 原文地址:https://www.cnblogs.com/xpchild/p/3798195.html
Copyright © 2011-2022 走看看