【事务隔离级别】——深度探索数据库的事务隔离级别
2016-01-31 14:12
441 查看
设置事务隔离级别的方式有很多种,上篇文章中只简单提到了理论知识,这里数据库以MySQL为例,来动手设置一下事务的隔离级别并观察一下事务的隔离级别到底起到什么作用。
我们都知道,每启动一下MySQL,就会获得一个数据库连接,每个数据库连接有一个全局变量@@tx_isolation,表示当前连接中事务的隔离级别。
查看事务隔离级别
命令行登录mysql,查看当前事务隔离级别:
或者
可以看到mysql默认的事务隔离级别为REPEATABLE-READ
查看系统全局事务离级别可以用:
设置事务隔离级别
设置当前事务隔离级别
设置系统全局(默认)事务隔离级别
read uncommitted测试
打开一个客户端A,并设置当前事务模式为read uncommitted(未提交读),查询表account的初始值:
在客户端A的事务提交之前,打开另一个客户端B,更新表account:
这时,虽然客户端B的事务还没提交,但是客户端A就可以查询到B已经更新的数据:
一旦客户端B的事务因为某种原因回滚,所有的操作都将会被撤销,那客户端A查询到的数据其实就是脏数据:
read committed测试
针对上面的问题,把客户端A的事务隔离级别设置为read committed,再重复上面的步骤,会发现B在事务结束之前,A并不能查询到B所做的操作。
客户端A的执行结果
客户端B的执行结果
但是正如上文所说,这种隔离级别下可能导致前事务中多次读取特定记录的结果不相同,比如客户端A事务隔离级别为read committed,在A的一个事务中,执行两次相同的查询,在这两次查询的中间,客户端B对数据进行更改并提交事务,那么会导致客户端A的两次查询结果不一致,导致“不可重复读”的麻烦。
客户端A的执行结果
客户端B的执行结果
repeatable read测试
同理,如果设置了repeatable read隔离级别,就可以保证在当前事务中多次执行相同查询的结果集相同,实现“可重复读”。
同样以客户端A设置事务隔离级别为repeatable read为例,执行结果如下:
客户端A的执行结果
客户端B的执行结果
上篇文章说到,这种隔离级别会导致“幻读”,比如客户端A中事务操作表中符合条件的若干行,同时客户端B中事务插入符合A操作条件的数据行,然后再提交。究竟会发生什么nie~~
小编为此也进行了测试:
客户端A的执行结果
客户端B的执行结果
结果却不像我们预测的那样,为客户端A中的事务设置隔离级别为repeatable read,但在客户端B中的事务插入数据后,A并没有出现“幻读”的现象。查了资料才知道,原来在mysql中,不会出现幻读。mysql的实现和标准定义的RR隔离级别有差别。
当然,
上篇文章说到的只是SQL规范所规定的标准,不同的数据库具体的实现可能会有些差异,所以还是以实际为准~~
实践出真知,所以每接触到一些理论知识时,最好能够实践一把,自己动手去探索,总会带给你意想不到的收货哦。
我们都知道,每启动一下MySQL,就会获得一个数据库连接,每个数据库连接有一个全局变量@@tx_isolation,表示当前连接中事务的隔离级别。
查看事务隔离级别
命令行登录mysql,查看当前事务隔离级别:
[code] select @@tx_isolation;
或者
[code]select @@session.tx_isolation;
可以看到mysql默认的事务隔离级别为REPEATABLE-READ
查看系统全局事务离级别可以用:
[code]select @@global.tx_isolation;
设置事务隔离级别
设置当前事务隔离级别
[code]set session transaction isolation level repeatable read;
设置系统全局(默认)事务隔离级别
[code]set global transaction isolation level repeatable read;
read uncommitted测试
打开一个客户端A,并设置当前事务模式为read uncommitted(未提交读),查询表account的初始值:
在客户端A的事务提交之前,打开另一个客户端B,更新表account:
这时,虽然客户端B的事务还没提交,但是客户端A就可以查询到B已经更新的数据:
一旦客户端B的事务因为某种原因回滚,所有的操作都将会被撤销,那客户端A查询到的数据其实就是脏数据:
read committed测试
针对上面的问题,把客户端A的事务隔离级别设置为read committed,再重复上面的步骤,会发现B在事务结束之前,A并不能查询到B所做的操作。
客户端A的执行结果
客户端B的执行结果
但是正如上文所说,这种隔离级别下可能导致前事务中多次读取特定记录的结果不相同,比如客户端A事务隔离级别为read committed,在A的一个事务中,执行两次相同的查询,在这两次查询的中间,客户端B对数据进行更改并提交事务,那么会导致客户端A的两次查询结果不一致,导致“不可重复读”的麻烦。
客户端A的执行结果
客户端B的执行结果
repeatable read测试
同理,如果设置了repeatable read隔离级别,就可以保证在当前事务中多次执行相同查询的结果集相同,实现“可重复读”。
同样以客户端A设置事务隔离级别为repeatable read为例,执行结果如下:
客户端A的执行结果
客户端B的执行结果
上篇文章说到,这种隔离级别会导致“幻读”,比如客户端A中事务操作表中符合条件的若干行,同时客户端B中事务插入符合A操作条件的数据行,然后再提交。究竟会发生什么nie~~
小编为此也进行了测试:
客户端A的执行结果
客户端B的执行结果
结果却不像我们预测的那样,为客户端A中的事务设置隔离级别为repeatable read,但在客户端B中的事务插入数据后,A并没有出现“幻读”的现象。查了资料才知道,原来在mysql中,不会出现幻读。mysql的实现和标准定义的RR隔离级别有差别。
当然,
上篇文章说到的只是SQL规范所规定的标准,不同的数据库具体的实现可能会有些差异,所以还是以实际为准~~
实践出真知,所以每接触到一些理论知识时,最好能够实践一把,自己动手去探索,总会带给你意想不到的收货哦。
相关文章推荐
- 3.3mysql数据库设计--课程笔记
- 曲折的ubuntu14.04下用c的api去连接mysql
- postgresql数据库常用命令
- Oracle 优化 - CPU 问题
- mongodb 之 备份数据库
- Oracle 11g对大表中添加DEFAULT值的NOT NULL字段速度有大幅度的提升
- mysql - tmp_table_size & max_heap_table_size
- 触发器
- plsql导入一个目录下全部excel
- sql递归查询
- SQL serber 删除带有默认值的字段
- mysql分组后获取最大值的记录
- mongoose 数据库操作 - 分页
- redis 的无序集合和hash操作
- debian 安装MongoDB数据库
- 普通单表上建立分区索引测试
- 把数据库内容显示在listview上
- 数据库导入导出操作
- 241,使用mybatis向mysql插入中文时,出现乱码
- linux下安装redis,启动,停止,设置密码