mysql tx_isolation

mysql事物隔离级别分为四种, (文档)

  • READ-UNCOMMITTED
  • READ-COMMITTED
  • REPEATABLE-READ
  • SERIALIZABLE

接下来会通过实践,来逐步介绍四种隔离级别的作用。mysql默认的隔离级别为repeatable-read。可通过select @@tx_isolation查看。如下图所示:
mysql tx_isolation_第1张图片
tx_isolation是mysql system variables, 其余system varaiables可通过官方文档查看。

READ-UNCOMMITTED

该事物隔离级别可读取其它事物未提交的结果
  1. 通过mysql -u username -p password 开启两个mysql连接, 分别为A连接, B连接。
  2. 输入set tx_isolation = 'read-uncommitted';将A连接的事务隔离级别设置为READ-UNCOMMITTED
  3. 在A,B连接的窗口分别查询test1表的数据, 表数据一致, 如下图所示
    mysql tx_isolation_第2张图片
  4. 在B连接的命令窗口输入start transaction;,并更新相应记录, 但不提交,如下图所示
    mysql tx_isolation_第3张图片
  5. 在A连接的命令窗口查看test1表, 结果如下图所示
    mysql tx_isolation_第4张图片
    通过结果发现。B连接,开启事物,修改数据,并未提交,A连接在read-uncommitted的隔离模式下仍然可以看到已更新的数据。
  6. B连接窗口输入rollback回滚数据,此时A,B连接所查询的数据,和初始时的数据是一样的。

READ-COMMITTED

该事物隔离级别只会读取已提交的数据,在事务中已更改但未读取的数据不会读取
  1. 同上A,B 两个连接
  2. 输入set tx_isolation = 'read-committed';将A连接的事务隔离级别修改
  3. B连接窗口开启事务,更新数据,但不提交,如下图所示
    mysql tx_isolation_第5张图片
    在B连接窗口查看数据已变更
  4. 在A连接窗口查看test1表格,如图
    mysql tx_isolation_第6张图片
    从结果可以看出A连接并未读取到B连接事务内未提交的更新数据
  5. 在B连接窗口提交事务,再到A连接窗口查看, 如图
    mysql tx_isolation_第7张图片
    A连接可以读取到B连接已提交的数据

REPEATABLE-READ

该事务隔离级别只会读取已提交的结果,与READ-COMMITTED不同的是,repeatable-read在开启事务的情况下,同一条件的查询返回的结果永远是一致的,无论其它事物是否提交了新的数据
  1. 和READ-COMMITTED的实验环境差不多,此时将A的隔离级别改为 repeatable-read,B还是一样开启事物,更新数据, 此事暂时不提交。但A开启事物查询数据。如图
    B连接
    mysql tx_isolation_第8张图片
    A连接
    mysql tx_isolation_第9张图片
    如结果所示,B未提交的数据,A读取不到

  2. 此时B提交事物, A继续查询,会发现A仍然读取不到B已提交的结果,这就是所谓的可重复读,如下图所示
    B连接
    mysql tx_isolation_第10张图片
    A连接
    mysql tx_isolation_第11张图片

  3. 此事A提交事物,在查看会查询到B更改的结果,如图
    mysql tx_isolation_第12张图片

SERIALIZABLE

这种隔离级别和repeatable-read类似,只会读取其它事物已提交的内容,有一点不同的地方在于,如果autocommit为false,那么每一条select语句会自动被转化为select ... lock in share mode.这样出现一些阻塞情况
English Explanation
This level is like REPEATABLE READ, but InnoDB implicitly converts all plain SELECT statements to SELECT ... LOCK IN SHARE MODE if autocommit is disabled. If autocommit is enabled, the SELECT is its own transaction. It therefore is known to be read only and can be serialized if performed as a consistent (nonlocking) read and need not block for other transactions. (To force a plain SELECT to block if other transactions have modified the selected rows, disable autocommit.)
  1. B开启事务, 并更新数据,但不提交
    mysql tx_isolation_第13张图片
  2. A 隔离级别改为serializable, 并且开启事务或者将autocommit设置为0, 并查询被修改数据,如图
    B
    mysql tx_isolation_第14张图片
    A(已经将autocommit设置为0)
    mysql tx_isolation_第15张图片
    结果表明A连接被阻塞住了, 同样的,如果A开启事务先查询, 未提交, B再去更新一样会被锁住。并且如果细心观察会发现,会发现很奇怪,按理来说lock in share mode应该是行锁定, 但是在我的机器上却成了表锁定,B只更新了id为4的记录,A查询ID为2的记录却仍然被锁定, 经过我测试在服务器上lock in share mode 确实是行锁定。经过多次测试发现如果查询数据中通过索引查询那么lock in share mode会根据索引锁行,如果查询条件中没有索引那么就直接锁表。

tips:serializable模式下, 如果设置了autocommit=0那么,会默认将select语句转为lock in share mode格式。

你可能感兴趣的:(mysql,mysql)