mysql 理解隔离级别_mysql隔离级别理解

关于mysql隔离级别的实验

前言

本文参考高性能mysql一书用mysql对四种SQL隔离级别进行仿真实验,以加深对SQL隔离级别的理解。

简介

SQL定义了四种隔离级别。包括

READ UNCOMMITED(未提交读)

READ COMMITED(提交读)

REPEATABLE READ(可重复读)

REPEATABLE READ(可串行化)

其区别在于

表1

隔离级别

脏读可能性

不可重复读可能性

幻读可能性

加锁读

READ UNCOMMITED

Yes

Yes

Yes

No

READ COMMITED

No

Yes

No

No

REPEATABLE READ

No

Yes

Yes

No

SERAILIZABLE

No

No

No

Yes

个人理解,所涉及的几个名称的含义为:

脏读: 在一事务中读取到其他未提交事务的数据

不可重复读: 在一事务中读取到其他已提交事务的数据

幻读: 在一事务中读取到其他已提交事务的新增行

加锁读: 在一事务中对读取到的每一行数据都加锁

为了实验上述理解,以下建立一城市表进行各个隔离级别的仿真。

统一建立一城市表为

CREATE TABLE `isolationtest_city_innodb` (

`id` int(11) NOT NULL DEFAULT '0',

`name` varchar(128) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,

PRIMARY KEY (`id`),

KEY `id` (`id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8

并建立两个测试用城市:

INSERT INTO isolationtest_city_innodb(id, NAME) VALUES(131, '北京'), (289, '上海');

开启两个事务A,B。A,B的执行顺序为

时序

A

B

1

start transaction

2

start transaction

3

update isolationtest_city_innodb set name = ‘重庆’ where name = ‘北京’

4

select * from isolationtest_city_innodb

5

commit

6

select * from isolationtest_city_innodb

7

start transaction

8

insert isolationtest_city_innodb set id = 332, name = ‘天津’

9

select * from isolationtest_city_innodb

10

commit

11

select * from isolationtest_city_innodb

12

insert isolationtest_city_innodb set id = 332, name = ‘天津’

13

commit

后续实验都将建立在此基础上。

READ UNCOMMITED

根据表1所述,事务B在时序4,6,9,11上将均能获取到事务A的数据。为验证以上断言,在开启事务B前修改数据库隔离模式

set tx_isolation = 'READ-UNCOMMITTED';

测试得到时序4,6,9,11的结果分别是: 2 rows in set (0.00 sec)

时序

结果

4

+—–+——–+

| id | name |

+—–+——–+

| 131 | 成都 |

| 289 | 上海 |

+—–+——–+

6

+—–+——–+

| id | name |

+—–+——–+

| 131 | 成都 |

| 289 | 上海 |

+—–+——–+

2 rows in set (0.00 sec)

9

+—–+——–+

| id | name |

+—–+——–+

| 131 | 成都 |

| 289 | 上海 |

| 332 | 天津 |

+—–+——–+

3 rows in set (0.00 sec)

11

+—–+——–+

| id | name |

+—–+——–+

| 131 | 成都 |

| 289 | 上海 |

| 332 | 天津 |

+—–+——–+

3 rows in set (0.00 sec)

测试结果和理解上是一致的。

READ COMMITED

根据表1所述,事务B在事务A未提交事务前是看不到事务A的数据的。据此断言对于事务B,时序4将只能看到事务B的数据;时序6能看到事务A在时序5提交的数据;时序9看不到事务A的数据;时序11可以看到事务A在时序10提交的数据。

为验证以上断言,在开启事务 B前修改数据库隔离模式

set tx_isolation = 'READ-COMMITTED';

测试得到时序4,6,9,11的结果分别是:

时序

结果

4

+—–+——–+

| id | name |

+—–+——–+

| 131 | 北京 |

| 289 | 上海 |

+—–+——–+

2 rows in set (0.00 sec)

6

+—–+——–+

| id | name |

+—–+——–+

| 131 | 成都 |

| 289 | 上海 |

+—–+——–+

2 rows in set (0.00 sec)

9

+—–+——–+

| id | name |

+—–+——–+

| 131 | 成都 |

| 289 | 上海 |

+—–+——–+

2 rows in set (0.00 sec)

11

+—–+——–+

| id | name |

+—–+——–+

| 131 | 成都 |

| 289 | 上海 |

| 332 | 天津 |

+—–+——–+

3 rows in set (0.00 sec)

测试结果和理解上是一致的。

REPEATABLE READ

根据表1所述,事务B在事务A未提交事务前是看不到事务A的数据的。据此断言对于事务B,时序4将只能看到事务B的数据;时序6能看到事务A在时序5提交的数据;时序9看不到事务A的数据;时序11可以看到事务A在时序10提交的数据。

为验证以上断言,在开启事务 B前修改数据库隔离模式

set tx_isolation = 'READ-COMMITTED';

测试得到时序4,6,9,11,12的运行结果分别为

时序

结果

4

+—–+——–+

| id | name |

+—–+——–+

| 131 | 北京 |

| 289 | 上海 |

+—–+——–+

2 rows in set (0.00 sec)

6

+—–+——–+

| id | name |

+—–+——–+

| 131 | 北京 |

| 289 | 上海 |

+—–+——–+

2 rows in set (0.00 sec)

9

+—–+——–+

| id | name |

+—–+——–+

| 131 | 北京 |

| 289 | 上海 |

+—–+——–+

2 rows in set (0.00 sec)

11

+—–+——–+

| id | name |

+—–+——–+

| 131 | 北京 |

| 289 | 上海 |

+—–+——–+

2 rows in set (0.00 sec)

12

ERROR 1062 (23000): Duplicate entry ‘332’ for key ‘PRIMARY’

测试结果和预测的有所不同。在时序11中,事务B并没有读取到事务A插入的‘天津’行而产生幻读。然而,这种幻读的影响在时序12中体现出来。事务B因为事务A已插入了‘天津’行而无法重复插入相同主键行。似乎mysql只读数据过程中避免了幻读现象,而在写数据过程中却没能避免。更多的介绍可以参考http://blog.sina.com.cn/s/blog_499740cb0100ugs7.html

SERIALIZABLE

SERIALIZABLE通过强制事务串行执行,避免幻读问题《高性能mysql》

也就是,事务B将在事务A结束后才得以执行。因此,事务B将在时序4阻塞;在时序6读取到‘北京’被修改为‘成都’的信息;而事务A在时序7再次阻塞。后续时序将无法继续执行。

测试得时序4,6,7的结果分别为

时序

结果

4

6

+—–+——–+

| id | name |

+—–+——–+

| 131 | 成都 |

| 289 | 上海 |

+—–+——–+

2 rows in set (0.00 sec)

7

以上空结果表示查询阻塞。从结果上看,和断言是一致的。

总结

对SQL的四种隔离级别的理解基本正确。针对REPEATABLE READ,mysql似乎在读数据过程避免了幻读现象,然而在写数据过程上没有避免。

展望

后续对mysql的REPEATABLE READ在幻读问题上的处理进行进一步理解分析。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值