linghaiyan 发表于 2018-10-10 09:56:24

mysql read commited 和 REPEATABLE read 原因

  read commited 和 REPEATABLE read
  关于一致性读的问题。 参考 mysql 技术内幕--innodb 存储引擎
  session 1
  :
  mysql> begin;
  Query OK, 0 rows affected (0.00 sec)
  mysql> select * from t2;
  +------+

  |>  +------+
  |    1 |
  +------+
  1 row in set (0.00 sec)
  同时到session2:
  mysql>
  mysql>
  mysql> begin;
  Query OK, 0 rows affected (0.00 sec)
  mysql> select * from t2;
  +------+

  |>  +------+
  |    1 |
  +------+
  1 row in set (0.00 sec)

  mysql> update t2 set>  Query OK, 1 row affected (0.00 sec)
  Rows matched: 1Changed: 1Warnings: 0
  mysql>
  mysql> select * from t2;
  +------+

  |>  +------+
  |    2 |
  +------+
  1 row in set (0.00 sec)
  mysql> commit;
  Query OK, 0 rows affected (0.01 sec)
  再回到session1:
  如果是
  mysql>select @@tx_isolation;
  +----------------+
  | @@tx_isolation |
  +----------------+
  | READ-COMMITTED |
  +----------------+
  1 row in set (0.00 sec)
  mysql> select * from t2;
  +------+

  |>  +------+
  |    2 |
  +------+
  1 row in set (0.00 sec)
  在session1 的同一个事物中,两次查询t2,会看到不通的结果,
  如果是:
  mysql> select @@tx_isolation;
  +-----------------+
  | @@tx_isolation|
  +-----------------+
  | REPEATABLE-READ |
  +-----------------+
  1 row in set (0.00 sec)
  在session 1 中,看到
  mysql> begin;
  Query OK, 0 rows affected (0.00 sec)
  mysql> select * from t2;
  +------+

  |>  +------+
  |    2 |
  +------+
  1 row in set (0.00 sec)
  mysql> select * from t2;
  +------+

  |>  +------+
  |    2 |
  +------+
  1 row in set (0.00 sec)
  是同一个结果。
  这是由于mysql的一致性非锁定读 造成的。
  如果读取的行正在备其他事物执行update或delete操作,这时读取操作不会因此去等待行上锁
  的释放,innodb回去读一个快照数据。因为不需要等待访问的行上x锁的释放,所以称之为非锁定读。
  快照数据是指该行 的之前版本的数据(可能有多个版本)。是通过undo断来实现的,undo是用
  来在事物中回滚数据,因此快照数据没有额外开销。
  在REPEATABLE read下,快照读总是读取事物开始时的行版本数据;而在read commited下,
  是读取最新一份快照,所以一个查询会看到不通的结果。

页: [1]
查看完整版本: mysql read commited 和 REPEATABLE read 原因