概述

************************************************

Mysql有四个事务隔离级别,默认隔离级别为RR,开启一个事务可以使用 START TRANSACTION。

START TRANSACTION
[transaction_characteristic [, transaction_characteristic] ...]

transaction_characteristic:
WITH CONSISTENT SNAPSHOT
| READ WRITE
| READ ONLY

START TRANSACTION默认为READ ONLY方式,但若在其中执行DML语句时,自动转化为READ WRITE方式。开启事务除非显式commit或者遇到DDL语句等,否则事务将一直停留

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec) mysql> select * from information_schema.innodb_trx\G;
Empty set (0.20 sec) ERROR:
No query specified mysql>
mysql>
mysql> insert into sbtest1(k,c,pad) select k,c,pad from sbtest1 limit 100000;
Query OK, 100000 rows affected (6.89 sec)
Records: 100000 Duplicates: 0 Warnings: 0 mysql> select * from information_schema.innodb_trx\G;
*************************** 1. row ***************************
trx_id: 10044
trx_state: RUNNING
trx_started: 2018-08-06 11:25:58
trx_requested_lock_id: NULL
trx_wait_started: NULL
trx_weight: 101373
trx_mysql_thread_id: 11
trx_query: select * from information_schema.innodb_trx
trx_operation_state: NULL
trx_tables_in_use: 0
trx_tables_locked: 2
trx_lock_structs: 1373
trx_lock_memory_bytes: 139472
trx_rows_locked: 101370
trx_rows_modified: 100000
trx_concurrency_tickets: 0
trx_isolation_level: REPEATABLE READ
trx_unique_checks: 1
trx_foreign_key_checks: 1
trx_last_foreign_key_error: NULL
trx_adaptive_hash_latched: 0
trx_adaptive_hash_timeout: 0
trx_is_read_only: 0
trx_autocommit_non_locking: 0
1 row in set (0.00 sec) ERROR:
No query specified mysql> commit;
Query OK, 0 rows affected (0.47 sec) mysql> select * from information_schema.innodb_trx\G;
Empty set (0.00 sec) ERROR:
No query specified

测试方法

***********************************************************

开启两个会话A与B,在会话B设置相应的事务隔离级别后,在会话A中插入数据(插入大量数据,而不是一条数据,延长DML事务的时间以观察效果),在会话B中查询SQL。大概分以下三种情况:

1. 会话A插入数据的时间点在会话B执行查询SQL之前

2. 会话A插入数据的时间点在会话B执行查询SQL之后,但查询SQL尚未结束时

2. 会话A正在插入数据一直未结束,会话B不断地执行查询SQL

查看当前事务隔离级别

**********************************************************************

mysql版本

mysql> select version();
+-----------+
| version() |
+-----------+
| 8.0.11 |
+-----------+
1 row in set (0.04 sec)

现线上运行数据库的事务隔离级别通常为RR级别,MVCC(Multiversion Concurrency Control,多版本并发控制)解决了幻读的问题。

mysql> show variables like '%isolation%';
+-----------------------+-----------------+
| Variable_name | Value |
+-----------------------+-----------------+
| transaction_isolation | REPEATABLE-READ |
+-----------------------+-----------------+
1 row in set (0.01 sec) mysql> select @@global.transaction_isolation;
+--------------------------------+
| @@global.transaction_isolation |
+--------------------------------+
| REPEATABLE-READ |
+--------------------------------+
1 row in set (0.00 sec) mysql> select @@session.transaction_isolation;
+---------------------------------+
| @@session.transaction_isolation |
+---------------------------------+
| REPEATABLE-READ |
+---------------------------------+
1 row in set (0.00 sec) mysql> select @@transaction_isolation;
+-------------------------+
| @@transaction_isolation |
+-------------------------+
| REPEATABLE-READ |
+-------------------------+
1 row in set (0.00 sec)

read uncommitted事务隔离级别

*****************************************************

会话A插入120万条记录数据

mysql> insert into sbtest1(k,c,pad) select k,c,pad from sbtest1 limit 1200000;

会话B设置事务隔离级别为read uncommitted
set session transaction isolation level read uncommitted;
start transaction;
select count(*) from sbtest1;

在会话A数据还没有commit还在不断的插入的过程中,会话B查询范围内的数据在不断地增加,也就是会话B可以看到会话A未提交的数据

mysql> select count(*) from sbtest1;
+----------+
| count(*) |
+----------+
| 14471333 |
+----------+
1 row in set (27.78 sec)

mysql> select count(*) from sbtest1;
+----------+
| count(*) |
+----------+
| 14863456 |
+----------+
1 row in set (22.86 sec)

mysql> select count(*) from sbtest1;
+----------+
| count(*) |
+----------+
| 15057947 |
+----------+
1 row in set (8.69 sec)

read committed事务隔离级别

*****************************************************

会话B设置事务隔离级别为read committed
set session transaction isolation level read committed;
start transaction;

mysql> select count(*) from sbtest1 where id > 10000000;
+----------+
| count(*) |
+----------+
| 9919550 |
+----------+
1 row in set (14.01 sec)

在会话B第二次查询之后,在会话A中插入1.2万条记录数据,用时10秒
mysql> insert into sbtest1(k,c,pad) select k,c,pad from sbtest1 limit 12000;
Query OK, 12000 rows affected (10.43 sec)
Records: 12000 Duplicates: 0 Warnings: 0

可以看到会话B查询的结果仍与之前一样,并没有因为会话A插入数据而改变,但会话B的查询时间变长了(由原来的14秒左右变为了41秒左右)
mysql> select count(*) from sbtest1 where id > 10000000;
+----------+
| count(*) |
+----------+
| 9919550 |
+----------+
1 row in set (41.61 sec)

RU离职级别存在脏读,而RC隔离级别中,每次select都会开启一个“一致性快照读”,所以会话A的事务还没有提交的话,读取的结果是一致的,因为快照中的事务列表没有变化。

同时,也正因为RC中是“每次select”都会开启一个“一致性快照读”,如果两次select之间有事务的变化,那么后面的select由于是一个新的快照读,所以可以查询到事务的变化。因此,

在会话B中进行第三次查询,即在会话Acommit之后查询,可以看到数据增加了1.2万条记录
mysql> select count(*) from sbtest1 where id > 10000000;
+----------+
| count(*) |
+----------+
| 9931550 |
+----------+
1 row in set (12.69 sec)

这种在同一个事务里,两次查询结果不一致的现象就是不可重复读

repeatable read事务隔离级别

****************************************************************************

RR事务隔离级别是Mysql数据库的默认事务隔离级别

set session transaction isolation level repeatable read;

RR级别的事务中,会话A中不断插入数据,会话B的结果不变;但会话A数据插入对会话B的查询依然有影响,无数据插入查询用时约0.3秒,插入10万记录,查询用时在4-10秒间波动。

mysql> set session transaction isolation level repeatable read;
Query OK, 0 rows affected (0.00 sec) mysql> show variables like '%isolation';
+-----------------------+-----------------+
| Variable_name | Value |
+-----------------------+-----------------+
| transaction_isolation | REPEATABLE-READ |
| tx_isolation | REPEATABLE-READ |
+-----------------------+-----------------+
2 rows in set (0.00 sec) mysql> start transaction;
Query OK, 0 rows affected (0.00 sec) mysql> select count(*) from sbtest1;
+----------+
| count(*) |
+----------+
| 1500000 |
+----------+
1 row in set (0.28 sec) mysql> select count(*) from sbtest1;
+----------+
| count(*) |
+----------+
| 1500000 |
+----------+
1 row in set (10.99 sec) mysql> select count(*) from sbtest1;
+----------+
| count(*) |
+----------+
| 1500000 |
+----------+
1 row in set (4.05 sec) mysql> select count(*) from sbtest1;
+----------+
| count(*) |
+----------+
| 1500000 |
+----------+
1 row in set (4.04 sec)

那RR又是怎么做到了可重复读呢?

前面说到RC是每次select都开启一个“一致快照读”,而RR是在事务中的第一次select时开启一致性快照读,后面的select不再开启,同一事务中所有select读取的是同一个一致性快照的事务,

所以,每次select得到的结果是一样的。这么做相对RC是有代价的,直接代价就是加锁的时间更长(RC是每次select结束时就自动释放了,RR是等你手工commit结束事务才释放),另外,在内部的实现上,需要更多的锁来保证这个功能。

my11_mysql事务隔离的更多相关文章

  1. sqlserver事务隔离小结

    SQL Server通过在锁资源上使用不同类型的锁来隔离事务.为了开发安全的事务,定义事务内容以及应在何种情况下回滚至关重要,定义如何以及在多长时间内在事务中保持锁定也同等重要.这由隔离级别决定.应用 ...

  2. SQL Server 中的事务与事务隔离级别以及如何理解脏读, 未提交读,不可重复读和幻读产生的过程和原因

    原本打算写有关 SSIS Package 中的事务控制过程的,但是发现很多基本的概念还是需要有 SQL Server 事务和事务的隔离级别做基础铺垫.所以花了点时间,把 SQL Server 数据库中 ...

  3. 30分钟全面解析-SQL事务+隔离级别+阻塞+死锁

    以前总是追求新东西,发现基础才是最重要的,今年主要的目标是精通SQL查询和SQL性能优化.  本系列主要是针对T-SQL的总结. [T-SQL基础]01.单表查询-几道sql查询题 [T-SQL基础] ...

  4. SQL Server 事务隔离级别详解

    标签: SQL SEERVER/MSSQL SERVER/SQL/事务隔离级别选项/设置数据库事务级别 SQL 事务隔离级别 概述 隔离级别用于决定如果控制并发用户如何读写数据的操作,同时对性能也有一 ...

  5. InnoDB事务隔离级别

    转载于:http://blog.csdn.net/wudongxu/article/details/8623610 SQL标准定义了4类隔离级别,包括了一些具体规则,用来限定事务内外的哪些改变是可见的 ...

  6. SQLServer 事务隔离级别

    MSSQL 事务级别 分类: 数据库2012-12-28 11:17 1050人阅读 评论(0) 收藏 举报 事务 级别 等级优化数据库 一个系统项目做大了,就会遇到性能问题.数据库的优化将是解决性能 ...

  7. Spring Trasnaction管理(1)- 线程间事务隔离

    问题导读 Spring中事务是如何实现的 Spring中各个线程间是如何进行连接.事务隔离的 Spring事务配置 Spring的事务管理应该是日常开发中总会碰到的,但是Spring具体是怎么实现线程 ...

  8. 1031MySQL事务隔离级别详解

    转自http://xm-king.iteye.com/blog/770721 SQL标准定义了4类隔离级别,包括了一些具体规则,用来限定事务内外的哪些改变是可见的,哪些是不可见的.低级别的隔离级一般支 ...

  9. 对于大于8046 bytes的行,RCSI/SI事务隔离级别无效

    自SQL Server 2005起,我们有了READ COMMITTED SNAPSHOT ISOLATION level (RCSI) 和SNAPSHOT ISOLATION level (SI)两 ...

随机推荐

  1. cocos2d-js 浏览器与JSB内存管理机制的不同

    写这边文章的主要目的是为了理解使用cocos3d-js开发app时,浏览器调试与真机情况不一致的原因 一.浏览器中内存管理机制 HTML5版本运行时,整个游戏只存在JS脚本与一些必要的资源文件,这时候 ...

  2. git在eclipse中的配置 完整版 转载

    http://www.cnblogs.com/zhxiaomiao/archive/2013/05/16/3081148.html

  3. nexus admin 从文件角度进行密码重置

    \sonatype-work\nexus\conf\security.xml 文件中保存账号密码信息. 打开 vi nexus-2.10.0-02-bundle\sonatype-work\nexus ...

  4. 20169219 《Linux内核原理与分析》 第十周作业

    进程地址空间 1.进程地址空间由进程可寻址的虚拟内存组成.Linux系统中的所有进程之间以虚拟方式共享内存. 2.进程只能访问有效内存区域内的内存地址. 内存区域可以包含各种内存对象: (1) 代码段 ...

  5. 对C语言中static的理解

    对C语言中的static关键字的深入理解 在一次面试的时候面试官问我static全局变量与全局变量的区别,之前虽然用过但是并没仔细去搞懂他,这次来细心的学习一下. 基本概念 使用static有三种情况 ...

  6. Java50道经典习题-程序41 猴子分桃

    题目:海滩上有一堆桃子,五只猴子来分.第一只猴子把这堆桃子凭据分为五份,多了一个,这只猴子把多的一个扔入海中,拿走了一份.第二只猴子把剩下的桃子又平均分成五份,又多了一个,它同样把多的一个扔入海中,拿 ...

  7. eclipse workspace 共享设置

    总结一下,复制工作空间配置步骤如下: 1 使用eclipse新建workspace. 2 将新建的workspace下的.metadata\.plugins内容全部删除. 3 将需要拷贝的worksp ...

  8. c/c++ 字符编码与标识符

    说明: 对于比较现代的语言来讲字符编码不是个大问题:java就可以使用中文作为变量名称,但对于C/C++来讲却不是这样,由于历史原因,标准和编译器厂商的实现总在不停的变化,相关编码信息到底是如何处理的 ...

  9. PDG转图像、PDF的若干方法

    作者:马健邮箱:stronghorse_mj@hotmail.com发布:2006.05.26更新:2008.08.24 补充说明:此文成文较早,其中对Pdg2Pic.FreePic2Pdf的描述早已 ...

  10. 字符串创建XML文档

    创建XML文档,方法与形式是多样的,下面Insus.NET再例举两种,可供参考. XmlDocument(namespace:System.Xml)在实例化之后,它有一个方法LoadXml(),可以把 ...