实践理解Mysql事务隔离级别之可重复读

可重复读

Mysql的事务隔离级别,默认是可重复读(repeatable-read)。

以下通过具体的sql操作去理解可重复读。

建表

CREATE DATABASE test;

USE test;

CREATE TABLE `t_order` (
  `fid` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键,自增id',
  `forder_id` varchar(35) NOT NULL COMMENT '订单号,唯一',
  `fpay_status` varchar(15) DEFAULT '00' COMMENT '00:未支付,01:支付成功,02:支付失败,03:已下单,04:申请退款,05:退款成功,06:退款失败,10:订单关闭',
  PRIMARY KEY (`fid`),
  UNIQUE KEY `forder_id` (`forder_id`)
  )   ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='订单表';
	
SELECT * FROM t_order;

多个事务操作

如果使用的是navicat,可以新建两个"查询"窗口,模拟A、B两个事务。

1.在两个窗口,分别执行以下语句,开启事务:

BEGIN;

2.查询数据:

SELECT * FROM t_order WHERE forder_id='abc';

结果如下:

3.在A事务中,执行update语句,然后再次查询:

UPDATE t_order SET fpay_status='01' WHERE forder_id='abc' AND fpay_status='00';

SELECT * FROM t_order WHERE forder_id='abc';

结果如下:

在A事务中,执行update后,fpay_status变为'01'

4.在B事务中,查询数据,结果如下:

由于A事务还没有提交,在可重复读的事务隔离级别下,B事务中的数据还是初始的值'00'。

接着,在B事务中,执行update语句,如下:

UPDATE t_order SET fpay_status='01' WHERE forder_id='abc' AND fpay_status='00';

发现B事务会阻塞,原因是A事务执行update语句时加了行锁。

一段时间后,B事务会超时。

重新开启B事务:

BEGIN;

5.提交A事务:

COMMIT;

然后,在B事务中查询,结果如下:

发现B事务中的fpay_status还是初始的值'00',这是因为:

在可重复读的事务隔离级别下,读取的是快照数据,总是读取当前事务开始时的行数据版本。

6.提交B事务。

COMMIT;

然后再次查询:

提交事务后,查询到的就是最新的数据了,fpay_status为'01'。

posted on 2019-12-23 17:21  乐之者v  阅读(1400)  评论(0编辑  收藏  举报

导航