mysql事务隔离级别测试
隔离性
mysql提供了4种不同的隔离级别以支持多版本并发控制(MVCC)
较低级别的隔离通常可以执行更高的并发,系统的开销也更低
read uncommited(未提交读)
read commited(提交读)
repeatable read(可重复读)
serializable(可串行化)
默认repeatable-read
建议最好不要修改默认的隔离级别,修改隔离级别会对mysql复制产生影响
isolation-table.sql
DROP TABLE IF EXISTS transaction_test;
CREATE TABLE transaction_test(
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
val VARCHAR(20) NOT NULL,
created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY(id)
) ENGINE=InnoDB DEFAULT CHARSET latin1; #初始化数据
insert into transaction_test(val) values ('a'),('b'),('c');
1.REPEATABLE-READ(可重复读)
解决了脏读问题.该级别保证了在同一事物中多次读取同样的记录结果是一样的。但是在理论上,可重复读隔离级别还是无法解决另外一个幻读问题
所谓幻读,是指当某个事务在读取某个范围的记录时,另外一个事务又在该范围内插入了新的记录,当之前的事务再次读取该范围的记录时,会产生幻行
innodb和XtraDB存储引擎通过多版本并发控制(MVCC)解决幻读问题。
select @@global.tx_isolation,@@session.tx_isolation;
+-----------------------+------------------------+
| @@global.tx_isolation | @@session.tx_isolation |
+-----------------------+------------------------+
| READ-UNCOMMITTED | READ-UNCOMMITTED |
+-----------------------+------------------------+
set @@global.tx_isolation='REPEATABLE-READ';
mysql> select @@global.tx_isolation,@@session.tx_isolation;
+-----------------------+------------------------+
| @@global.tx_isolation | @@session.tx_isolation |
+-----------------------+------------------------+
| REPEATABLE-READ | REPEATABLE-READ |
+-----------------------+------------------------+
第一个会话窗口
start transaction;
select * from transaction_test;
select sleep(20);
insert into transaction_test (val) values (@@session.tx_isolation);
select * from transaction_test;
commit;
在第一个会话正在运行时在第二个会话窗口里运行
start transaction;
insert into transaction_test (val) values ('x'),('y'),('z');
select * from transaction_test;
commit;
均执行结束后
mysql> select * from transaction_test;
+----+-----------------+---------------------+
| id | val | created |
+----+-----------------+---------------------+
| 1 | a | 2017-01-08 20:38:06 |
| 2 | b | 2017-01-08 20:38:06 |
| 3 | c | 2017-01-08 20:38:06 |
| 4 | x | 2017-01-08 20:38:41 |
| 5 | y | 2017-01-08 20:38:41 |
| 6 | z | 2017-01-08 20:38:41 |
| 7 | REPEATABLE-READ | 2017-01-08 20:38:59 |
+----+-----------------+---------------------+
7 rows in set (0.00 sec)
可以看到在第二个会话中,添加了3个新行,并在第一个会话事务完成前提交了数据
会话1里的执行状态
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec) mysql> select * from transaction_test;
+----+-----+---------------------+
| id | val | created |
+----+-----+---------------------+
| 1 | a | 2017-01-08 20:45:48 |
| 2 | b | 2017-01-08 20:45:48 |
| 3 | c | 2017-01-08 20:45:48 |
+----+-----+---------------------+
3 rows in set (0.00 sec) mysql> select sleep(20);
+-----------+
| sleep(20) |
+-----------+
| 0 |
+-----------+
1 row in set (20.00 sec) mysql> insert into transaction_test (val) values (@@session.tx_isolation);
Query OK, 1 row affected (0.00 sec) mysql> select * from transaction_test;
+----+-----------------+---------------------+
| id | val | created |
+----+-----------------+---------------------+
| 1 | a | 2017-01-08 20:45:48 |
| 2 | b | 2017-01-08 20:45:48 |
| 3 | c | 2017-01-08 20:45:48 |
| 7 | REPEATABLE-READ | 2017-01-08 20:47:16 |
+----+-----------------+---------------------+
4 rows in set (0.00 sec) mysql> commit;
Query OK, 0 rows affected (0.06 sec)
第一个会话事务不知道第二个会话事务已完成的结果,整个事务过程中多次读取的数据是一致的(无论外表是否发生改变)
但会阻塞 truncate 操作,delete ,insert,
事务里做的修改(update,delete)未提交 会将这些数据锁定,阻塞其它的操作
2.READ-COMMITTED(读取提交内容)
TRUNCATE transaction_test;
insert into transaction_test(val) values ('a'),('b'),('c');
set @@global.tx_isolation='READ-COMMITTED';
mysql> select @@global.tx_isolation,@@session.tx_isolation;
+-----------------------+------------------------+
| @@global.tx_isolation | @@session.tx_isolation |
+-----------------------+------------------------+
| READ-COMMITTED | READ-COMMITTED |
+-----------------------+------------------------+
在session1中运行
start transaction;
select * from transaction_test;
select sleep(20);
insert into transaction_test (val) values (@@session.tx_isolation);
select * from transaction_test;
commit;
同时在session2中运行
start transaction;
insert into transaction_test (val) values ('x'),('y'),('z');
select * from transaction_test;
commit;
session1的运行显示
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec) mysql> select * from transaction_test;
+----+-----+---------------------+
| id | val | created |
+----+-----+---------------------+
| 1 | a | 2017-01-08 21:11:26 |
| 2 | b | 2017-01-08 21:11:26 |
| 3 | c | 2017-01-08 21:11:26 |
+----+-----+---------------------+
3 rows in set (0.00 sec) mysql> select sleep(20);
+-----------+
| sleep(20) |
+-----------+
| 0 |
+-----------+
1 row in set (20.00 sec) mysql> insert into transaction_test (val) values (@@session.tx_isolation);
Query OK, 1 row affected (0.01 sec) mysql> select * from transaction_test;
+----+----------------+---------------------+
| id | val | created |
+----+----------------+---------------------+
| 1 | a | 2017-01-08 21:11:26 |
| 2 | b | 2017-01-08 21:11:26 |
| 3 | c | 2017-01-08 21:11:26 |
| 4 | x | 2017-01-08 21:11:50 |
| 5 | y | 2017-01-08 21:11:50 |
| 6 | z | 2017-01-08 21:11:50 |
| 7 | READ-COMMITTED | 2017-01-08 21:12:02 |
+----+----------------+---------------------+
7 rows in set (0.00 sec) mysql> commit;
Query OK, 0 rows affected (0.07 sec)
可以看到,在session1事务期间,事务内的数据结果发生了改变,以反映一个已提交的事务
这仅仅是一个演示,可能应用程序永远不会需要在某个事务期间,多次选择相同的信息
作为隔离级别的默认值,REPEATABLE-READ是最广泛使用和测试的隔离级别,应当优先于READ-COMMITED使用
3.READ-UNCOMMITED(读取未提交内容)
事务中的修改,即使没有提交,对其它事务也都是可见的。事务可以读取未提交的数据,这也称为脏读。这个级别会导致很多问题,从性能上来说不会比其它级别好太多,但缺乏其它级别的很多好处!
set @@global.tx_isolation='READ-UNCOMMITED';
运行之前的测试语句
先执行会话1
在执行会话2 不提交事务
等会话1执行完再提交会话2的事务
会发现会话1读到了会话2未提交的事务
4.SERIALIZABLE(序列化,可串行化)
此种情况下,在共享模式下对表进行了有效锁定,这会迫使事务阻塞其它事务
按照之前的测试语句
对于第一个会话,输出效果相同 ,造成第二个会话中insert的延迟,该insert将会被阻塞,直到第一个会话完成
set @@global.tx_isolation='SERIALIZABLE';
会话1
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec) mysql> select * from transaction_test;
+----+-----+---------------------+
| id | val | created |
+----+-----+---------------------+
| 1 | a | 2017-01-08 22:34:59 |
| 2 | b | 2017-01-08 22:34:59 |
| 3 | c | 2017-01-08 22:34:59 |
+----+-----+---------------------+
3 rows in set (0.00 sec) mysql> select sleep(20);
+-----------+
| sleep(20) |
+-----------+
| 0 |
+-----------+
1 row in set (20.00 sec) mysql> insert into transaction_test (val) values (@@session.tx_isolation);
Query OK, 1 row affected (0.00 sec) mysql> select * from transaction_test;
+----+--------------+---------------------+
| id | val | created |
+----+--------------+---------------------+
| 1 | a | 2017-01-08 22:34:59 |
| 2 | b | 2017-01-08 22:34:59 |
| 3 | c | 2017-01-08 22:34:59 |
| 7 | SERIALIZABLE | 2017-01-08 22:36:12 |
+----+--------------+---------------------+
4 rows in set (0.00 sec) mysql> commit;
Query OK, 0 rows affected (0.34 sec)
会话2
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec) mysql> insert into transaction_test (val) values ('x'),('y'),('z');
Query OK, 3 rows affected (13.04 sec)
Records: 3 Duplicates: 0 Warnings: 0 mysql> select * from transaction_test;
+----+--------------+---------------------+
| id | val | created |
+----+--------------+---------------------+
| 1 | a | 2017-01-08 22:34:59 |
| 2 | b | 2017-01-08 22:34:59 |
| 3 | c | 2017-01-08 22:34:59 |
| 4 | x | 2017-01-08 22:35:59 |
| 5 | y | 2017-01-08 22:35:59 |
| 6 | z | 2017-01-08 22:35:59 |
| 7 | SERIALIZABLE | 2017-01-08 22:36:12 |
+----+--------------+---------------------+
7 rows in set (0.00 sec)
mysql> commit;
Query OK, 0 rows affected (0.39 sec)
值得注意的是
auto_increment 列的顺序
所显示的顺序是实际语句初始化的顺序,
因为auto_increment列的值是作为对该表保持的一个单独的内部全局变量值而进行管理的,在执行期间,可以在内部独占的互斥体内获得该值
它独立于隔离级别而发挥作用,与实际sql数据的serializable相反,即数据直到加锁事务完成insert操作后,才会释放第二个会话的锁定
|
隔离级别 |
脏读可能性 |
不可重复读可能性 |
幻读可能性 |
加锁读 |
|
read uncommited |
Yes |
Yes |
Yes |
No |
|
read commited |
No |
Yes |
Yes |
No |
|
repeatable read |
No |
No |
Yes |
No |
|
seralizable |
No |
No |
No |
Yes |
表的外键和级联
DROP TABLE IF EXISTS trans_parent;
CREATE TABLE trans_parent (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
val VARCHAR(10) NOT NULL,
PRIMARY KEY (id),
UNIQUE KEY (val)
) ENGINE=InnoDB DEFAULT CHARSET latin1; 外键约束
DROP TABLE IF EXISTS trans_child;
CREATE TABLE trans_child (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
parent_id INT UNSIGNED NOT NULL,
created TIMESTAMP NOT NULL,
PRIMARY KEY (id),
INDEX (parent_id),
FOREIGN KEY (parent_id) REFERENCES trans_parent(id)
) ENGINE=InnoDB DEFAULT CHARSET latin1;
看一张表的索引
show index from trans_child;
看一张表的外键
use INFORMATION_SCHEMA; select TABLE_NAME,COLUMN_NAME,CONSTRAINT_NAME,REFERENCED_TABLE_NAME,REFERENCED_COLUMN_NAME from KEY_COLUMN_USAGE where table_name = 'trans_child'; +-------------+-------------+--------------------+-----------------------+------------------------+
| TABLE_NAME | COLUMN_NAME | CONSTRAINT_NAME | REFERENCED_TABLE_NAME | REFERENCED_COLUMN_NAME |
+-------------+-------------+--------------------+-----------------------+------------------------+
| trans_child | id | PRIMARY | NULL | NULL |
| trans_child | parent_id | trans_child_ibfk_1 | trans_parent | id |
+-------------+-------------+--------------------+-----------------------+------------------------+
如果删除trans_parent里的一条与trans_child有外键关联的表 会报错
级联约束
alter table trans_child
drop foreign key trans_child_ibfk_1,
add foreign key (parent_id) references trans_parent(id) on delete cascade; delete from trans_parent where id=1;//trans_child表里parent_id=1的纪录也会被删除
mysql事务隔离级别测试的更多相关文章
- MySQL事务隔离级别测试实例
https://www.cnblogs.com/huanongying/p/7021555.html MySQL事务隔离级别 事务隔离级别 脏读 不可重复读 幻读 读未提交(read-uncommit ...
- MySQL事务隔离级别(一)
本文实验的测试环境:Windows 10+cmd+MySQL5.6.36+InnoDB 一.事务的基本要素(ACID) 1.原子性(Atomicity):事务开始后所有操作,要么全部做完,要么全部不做 ...
- 面试突击61:说一下MySQL事务隔离级别?
MySQL 事务隔离级别是为了解决并发事务互相干扰的问题的,MySQL 事务隔离级别总共有以下 4 种: READ UNCOMMITTED:读未提交. READ COMMITTED:读已提交. REP ...
- [51CTO]新说MySQL事务隔离级别!
新说MySQL事务隔离级别! 事务隔离级别这个问题,无论是校招还是社招,面试官都爱问!然而目前网上很多文章,说句实在话啊,我看了后我都怀疑作者弄懂没!本文所讲大部分内容,皆有官网作为佐证,因此对本文内 ...
- 查询mysql事务隔离级别
查询mysql事务隔离级别 查询mysql事务隔离级别 分类: DB2011-11-26 13:12 2517人阅读 评论(0) 收藏 举报 mysqlsessionjava 1.查看当前会话隔离 ...
- Mysql事务-隔离级别
MYSQL事务-隔离级别 事务是什么? 事务简言之就是一组SQL执行要么全部成功,要么全部失败.MYSQL的事务在存储引擎层实现. 事务都有ACID特性: 原子性(Atomicity):一个事务必须被 ...
- MySQL事务隔离级别 解决并发问题
MySQL事务隔离级别 1. 脏读: 骗钱的手段, 两个窗口或线程分别调用数据库转账表,转账后未提交,对方查看到账后,rollback,实际钱没转. 演示方法: mysql默认的事务隔离级别为repe ...
- mysql事务隔离级别、脏读、幻读
Mysql事务隔离级别本身很重要,再加上可能是因为各大公司面试必问的缘故,在博客中出现的概率非常高,但不幸的是,中国的技术博客要么是转载,要么是照抄,质量参差不齐,好多结论都是错的,对于心怀好奇之心想 ...
- mysql事务隔离级别与设置
mysql数据库,当且仅当引擎是InnoDB,才支持事务: 1.隔离级别 事务的隔离级别分为:未提交读(read uncommitted).已提交读(read committed).可重复读(repe ...
随机推荐
- 使用Xcode IDE写node.js
最近在玩node.js 但是发现很多IDE就是用不顺手 后来发现Xcode可以剖析java script 于是试着使用Xcode来当做node.js的编辑器 首先,在Mac上必须先安装node.js的 ...
- java web 实体类生成
工具下载地址:https://download.csdn.net/download/g342105676/10813246
- 从 Spring Cloud 开始,聊聊微服务架构实践之路
[编者的话]随着公司业务量的飞速发展,平台面临的挑战已经远远大于业务,需求量不断增加,技术人员数量增加,面临的复杂度也大大增加.在这个背景下,平台的技术架构也完成了从传统的单体应用到微服务化的演进. ...
- GDI+ 双缓冲字体模糊
只是记录自己的UI库,对其他估计没什么帮助 void CListCtrlUI::ReFillRect(HDC hdc){ if (!m_pImage) { Graphics gs(hdc); int ...
- 在linux上用jmeter压测时出现很多异常java.net.NoRouteToHostException: Cannot assign requested address.
今天压力测试时, 刚开始出现了很多异常, 都是 java.net.NoRouteToHostException: Cannot assign requested address. 经网上查资料, 是由 ...
- hdu 5975 Aninteresting game
Aninteresting game Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Other ...
- python面向对象编程 继承 组合 接口和抽象类
1.类是用来描述某一类的事物,类的对象就是这一类事物中的一个个体.是事物就要有属性,属性分为 1:数据属性:就是变量 2:函数属性:就是函数,在面向对象里通常称为方法 注意:类和对象均用点来访问自己的 ...
- vs2013出现错误提示error C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s
这个问题是vs准备弃用strcpy带来的,因为觉得他不太安全 可以尝试在main函数前面加上#pragma warning(disable:4996)即可解决这个问题
- h5启动原生APP总结
许久没有写博客了,最近有个H5启动APP原生页面的需求,中间遇上一些坑,看了些网上的实现方案,特意来总结下 一.需要判断客户端的平台以及是否在微信浏览器中访问 1.客户端判断 在启动APP时,Andr ...
- 手把手教你怎么用ArcgisOnline发布地图服务
Arcgis推出了Arcgis Online,但是大家都不知道这是个什么东西,怎么用这个东西,今天这篇文章手把手的教你如何使用Arcgisonline发布地图服务. 一.ArcgisOnline简介 ...