Mysql数据库事务及隔离级别学习测试
参考了这篇文章的一些内容:
http://xm-king.iteye.com/blog/770721
记住以下这张表:

我在springdemo库里面建了一个表:
CREATE TABLE `tx` (
`id` bigint(11) NOT NULL auto_increment,
`num` bigint(11) default 0 COMMENT '用户名',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='事务隔离级别测试表';
Mysql通过以下语句可以查询
SELECT @@tx_isolation;
SELECT @@global.tx_isolation;
SELECT @@session.tx_isolation;
默认的是 REPEATABLE-READ
可以通过以下方式修改隔离级别:
set tx_isolation='read-committed';
mysql> select @@tx_isolation;
+-----------------+
| @@tx_isolation |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set (0.00 sec)
mysql> set tx_isolation='read-committed';
Query OK, 0 rows affected (0.00 sec)
mysql> select @@tx_isolation;
+----------------+
| @@tx_isolation |
+----------------+
| READ-COMMITTED |
+----------------+
1 row in set (0.00 sec)
但是,注意以上的改动,只能针对当前会话。
另起一个客户端,输入
select @@tx_isolation;
+-----------------+
| @@tx_isolation |
+-----------------+
| REPEATABLE-READ |
+-----------------+
————————————————————————————————
以下是各种情况的测试:
READ-UNCOMMITTED
update tx set num=11 where id=1;
ERROR 1665 (HY000): Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engine limited to row-based logging. InnoDB is limited to row-logging when transaction isolation level is READ COMMITTED or READ UNCOMMITTED.
READ-COMMITTED
update tx set num=11 where id=1;
ERROR 1665 (HY000): Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engine limited to row-based logging. InnoDB is limited to row-logging when transaction isolation level is READ COMMITTED or READ UNCOMMITTED.
REPEATABLE-READ
A:
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec) mysql> select * from tx; (B更新前)
+----+------+
| id | num |
+----+------+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
+----+------+
3 rows in set (0.00 sec) mysql> select * from tx; (B更新后)
+----+------+
| id | num |
+----+------+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
+----+------+
3 rows in set (0.00 sec) mysql> commit;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from tx;
+----+------+
| id | num |
+----+------+
| 1 | 10 |
| 2 | 2 |
| 3 | 3 |
+----+------+
可以看出,A的事务中,看不到B对数据的更新。
同样是 REPEATABLE-READ
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec) mysql> select * from tx;
+----+------+
| id | num |
+----+------+
| 1 | 10 |
| 2 | 2 |
| 3 | 3 |
+----+------+
3 rows in set (0.00 sec) mysql> select * from tx;
+----+------+
| id | num |
+----+------+
| 1 | 10 |
| 2 | 2 |
| 3 | 3 |
+----+------+
3 rows in set (0.00 sec)
mysql> rollback;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from tx;
+----+------+
| id | num |
+----+------+
| 1 | 10 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
+----+------+
4 rows in set (0.00 sec)
另一个客户端,insert 了一条记录.
对于正常的repeatable-read级别,是有可能出现幻读的情况,也就是说,第二遍的时候,A能够读到新插入的数据。
但是,InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了该问题。
所以我上面用InnoDB引擎创建的数据库,就没有出现幻读的情况。
SERIALIZABLE
这里注意,只需要对使用事务Transaction的客户端设置SERIALIZABLE ,其他客户端的级别是什么都行,比如REPEATABLE-READ .
A
mysql> select @@tx_isolation;
+----------------+
| @@tx_isolation |
+----------------+
| SERIALIZABLE |
+----------------+
1 row in set (0.00 sec) mysql> start transaction;
Query OK, 0 rows affected (0.00 sec) mysql> select * from tx;
+----+------+
| id | num |
+----+------+
| 1 | 10 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
| 5 | 5 |
+----+------+
5 rows in set (0.00 sec) mysql> rollback;
Query OK, 0 rows affected (0.00 sec)
B
mysql> select @@tx_isolation;
+-----------------+
| @@tx_isolation |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set (0.00 sec) mysql> insert into tx values(5,5);
Query OK, 1 row affected (0.09 sec) mysql> insert into tx values(6,6); Query OK, 1 row affected (31.60 sec)
这里,有2点需要注意:
1. A没有使用(select)表tx的时候,B仍然能够向tx表中插入数据;
2. A使用(select)表tx之后,B再进行insert操作,就会hang住,直到A表transaction结束。所以可以看到B的insert操作耗时31秒。当然了,也可能超时失败。
比如:
mysql> insert into tx values(10,10);
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
以上这条语句,看起来是锁了整个表。但是其实深层次的目的,是为了保证事务的完整性,以及让A两次操作的REPEATABLE_READ;
比如 使用 select * from tx limit 1; 后面就仍然可以insert。因为不改变之前select的结果。
如果 select * from tx limit 10; 而最终只检出8条。这时候就不能insert,因为insert了的话,下次同样select得到的结果就不一样。
同理,如果select了某条记录,那么update同一条记录就不行,update其他的记录就可以。而且在事务中能够读到新更新的数据。
所以记住,事务的隔离级别的要求,只对事务过程中已经获取过的数据有关。跟没获取过、其他不可见的数据,无关。
Mysql数据库事务及隔离级别学习测试的更多相关文章
- Mysql数据库事务的隔离级别和锁的实现原理分析
Mysql数据库事务的隔离级别和锁的实现原理分析 找到大神了:http://blog.csdn.net/tangkund3218/article/details/51753243 InnoDB使用MV ...
- MySQL数据库事务各隔离级别加锁情况--read uncommitted篇(转)
本文转自https://m.imooc.com/article/details?article_id=17291,感谢作者 1.目的 1.1 合适人群 1.数据库事务特征我只是背过,并没有很深刻的理解 ...
- MySQL数据库事务各隔离级别加锁情况--read committed && MVCC(转载)
http://www.imooc.com/article/17290 http://www.51testing.com/html/38/n-3720638.html https://dev.mysql ...
- MySQL数据库事务各隔离级别加锁情况--read committed && MVCC(转)
本文转自https://m.imooc.com/article/details?article_id=17290 感谢作者 上篇记录了我对MySQL 事务 隔离级别read uncommitted的理 ...
- MySQL数据库事务各隔离级别加锁情况--Repeatable Read && MVCC(转)
本文转自https://m.imooc.com/article/details?article_id=17289 感谢作者 上节回顾 上两篇记录了我对MySQL 事务 隔离级别read uncommi ...
- MySQL数据库事务各隔离级别加锁情况--read committed && MVCC
之前已经转载过几篇相关的文章,此次基于mysql 5.7 版本,从测试和源码角度解释一下RR,RC级别为什么看到的数据不一样 先补充一下基础知识 基本知识 假设对于多版本(MVCC)的基础知识,有所了 ...
- 「DB」数据库事务的隔离级别
*博客搬家:初版发布于 2017/04/10 00:37 原博客地址:https://my.oschina.net/sunqinwen/blog/875833 数据库事务的隔离级别 讲事务的隔离 ...
- Spring中事务的传播行为,7种事务的传播行为,数据库事务的隔离级别
Propagation.REQUIRED 代表当前方法支持当前的事务,且与调用者处于同一事务上下文中,回滚统一回滚(如果当前方法是被其他方法调用的时候,且调用者本身即有事务),如果没有事务,则自己新建 ...
- 数据库事务ACID/隔离级别
参考博客 1. 事务的定义 事务是用户定义的一个数据库操作序列.这些操作要么全执行,要么全不执行,是一个不可分割的工作单元.在关系型数据库中,事务可以是一条SQL语句,也可以是一组SQL语句或整个程序 ...
随机推荐
- HTTP协议--请求与响应
1.简介 HTTP 是一个属于应用层的面向对象的协议,由于其简捷.快速的方式,适用于分布式超媒体信息系统.它于1990 年提出,经过几年的使用与发展,得到不断地完善和扩展.目前在WWW 中使用的是HT ...
- 牛客练习赛3 F - 监视任务
链接:https://www.nowcoder.net/acm/contest/13/F来源:牛客网 题目描述
- CSUOJ 1901 赏赐 OR 灾难 单调栈
Description 大G南征北战终于打下了大片土地成立了G国,大G在开国大典上传召帮助自己南征北战的三大开国元勋小A,小B,小C进殿,并要赏赐三人大量宝物以显示天恩浩荡.大G在征服其他国家的时候抢 ...
- List元素为泛型时的注意事项
最近的项目赶得非常紧,这节奏跟最近的天气一点也不搭调. 编码的过程,遇到一个关于List的小问题. 在调用List.add(E e)的时候范了一个小毛病,很自然地认为list中存储的是 E 对象的另 ...
- NOIP2018 生气记
今年的题都不怎么难 只是考到的东西相当相当的奇怪... 不想写题解,写出来感觉只是伤心的事 .................... Day1 一进考场就感受到了比去年要严一些... 花了1小时30分 ...
- 写在OI退役后和高中毕业前的一些话
更新日志: 2017.02.13 开坑 2017.02.13 更新[零][壹] 2017.02.14 更新[贰] 2017.02.26 更新[叁][肆] 2017.03.04 锅多如狗,停更一周 20 ...
- 网站(Web)压测工具Webbench源码分析
一.我与webbench二三事 Webbench是一个在linux下使用的非常简单的网站压测工具.它使用fork()模拟多个客户端同时访问我们设定的URL,测试网站在压力下工作的性能.Webbench ...
- Shell 学习笔记之运算符
基本运算符 算术运算符 val = expr 2 + 2 需要注意的是 表达式和运算符之间需要有空格(比如2 + 2,不能是2+2) 两边最外面的字符是`,在esc键下面,不是引号哦 乘号* 前面必须 ...
- Python学习笔记(七)—字典的学习
总结内容: 1.字典的定义 2.字典的好处 3.字典的增删改查 4.字典常用方法及内置函数 5.字典的多层嵌套 6.字典的循环 7.字典小练习 1.字典的定义 字典是另一种可变容器模型,且可存储任意类 ...
- 成为一名JAVA高级工程师你需要学什么【转】
宏观上: 1.技术广度方面至少要精通多门开源技术吧,研究过struts\spring等的源码. 2.项目经验方面从头到尾跟过几个大项目,头是指需求阶段,包括需求调研.尾是指上线交付之后,包括维护阶段. ...