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 ...
随机推荐
- Linux 利用管道父子进程间传递数据
[原文] fork()函数:用于创建子进程,子进程完全复制父进程的资源,相当于父进程的拷贝.具体理解,运用父进程的同一套代码,通过判断进程ID来执行不同进程的不同任务. 返回值正常为子进程ID,出错返 ...
- hdu 5920 Wool 思路
Wool Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others) Problem D ...
- ZZ__知识点
1. DLL_PROCESS_ATTACH.DLL_PROCESS_DETACH 打印出相关信息 发现,Java Project 项目中,DLL 在 System.loadLibrary(...) 载 ...
- 探秘DPDK Virtio的不同路径
什么是Vhost/Virtio Vhost/Virtio是一种半虚拟化的设备抽象接口规范, 在Qemu和KVM中的得到了广泛的应用,在客户机操作系统中实现的前端驱动程序一般直接叫Virtio, 在宿主 ...
- SpringBoot实现多数据源(实战源码)
通过一个数据库的表数据去查询同步另一个数据库,之前的方式是通过写个小工具,然后jdbc方式进行处理,这个方式也挺好用的.学习了springboot后发现可以实现多数据源操作,然后就具体实现以下. 以下 ...
- 编辑器上的vim插件,常用到的快捷件
[vim]常用到的插件命令 [Esc] 退出编辑(输入,插入)模式,回到命令模式中(常用)i, I进入插入模式(Insert mode):i 为『从目前光标所在处插入』, I 为『在目前所在行的第一个 ...
- 新东方雅思词汇---7.4、cap
新东方雅思词汇---7.4.cap 一.总结 一句话总结: 抓住 capable 英 ['keɪpəb(ə)l] 美 ['kepəbl] adj. 能干的,能胜任的:有才华的 词组短语 capab ...
- 【CSAPP】一、计算机系统漫游
一.位+上下文 文本文件 / 二进制文件: 文本文件是只由ASCII码构成的文件 二.从源代码到可执行文件的顺序 源代码 ——> 可执行文件(机器代码)共有四步: 全过程代码 gcc hello ...
- Some Interview Questions About Python
一大波超链接即将袭来 Django认证流程 Python实现阶乘 Python文件处理 Python统计日志文件IP出现次数 JSON数据解析 JSON数据解析2 买卖股票的最佳时期 读取一个大文件比 ...
- Arcgis andoid开发之应用百度地图接口实现精准定位与显示
怀着激动.兴奋的心情,在这个漫天柳絮的季节写下了这片博文,为什么呢,因为困扰我很久的一个技术性的问题得到了解决,发次博文,供大家参观.学习,同时,也以慰藉我长期困扰的心情,好了,废话不再,言归正传,看 ...