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 ...
随机推荐
- XP_SP3_专业汉化版__x86_cd_x14-80404
1.镜像文件: zh-hans_windows_xp_professional_with_service_pack_3_x86_cd_x14-80404.iso 来自 msdn itellyou 2. ...
- scala学习手记24 - 多参数函数值
上一节的函数值只有一个参数.函数值当然也是可以有多个参数的.看一下下面的inject方法: def inject(arr: Array[Int], initial: Int, operation: ( ...
- JNIjw02
1.VC6(CPP)的DLL代码: #include<stdio.h> #include "jniZ_JNIjw02.h" JNIEXPORT void JNICALL ...
- 2012 Multi-University Training Contest 7
2012 Multi-University Training Contest 7 A.As long as Binbin loves Sangsang B.Dead or alive C.Dragon ...
- Eclipse的编码格式设置
在使用Eclipse开发中,许多文件编码默认是ISO-8859-1,不支持中文(如常用的JSP).这样我们每次建文件都要手动改编码,其实我们可以在设置文件默认编码,今后再创建时就不用每次修改编码了, ...
- ps切图步骤
1.复制图层到新建 2.alt + i + r 裁剪 依次按 3.ctrl + alt + shift + s 保存 裁剪图标 复制到图层 , 删除背景,并复制样式 就可以做到 背景透明.
- css3+jQuery实现按钮水波纹效果
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name ...
- GO学习笔记:函数作为值、类型
在Go中函数也是一种变量,我们可以通过type来定义它,它的类型就是所有拥有相同的参数,相同的返回值的一种类型: type typeName func(input1 inputType1 , inpu ...
- pipenv安装库使用国内镜像
pipenv install django超级慢,卡住不动,最后不得不CTRL+C中止 这时有必要改成国内源了,打开Pipfile文件,发现内容是: [[source]] verify_ssl = t ...
- 亲测安装nginx1.8.1 日期2016年3月16日
1.安装nginx tar zxvf nginx-1.8.1.tar.gz cd nginx-1.8.1 ./configure make make install /usr/local/nginx/ ...