惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

G
Google Developers Blog
Jina AI
Jina AI
大猫的无限游戏
大猫的无限游戏
Martin Fowler
Martin Fowler
博客园 - 司徒正美
云风的 BLOG
云风的 BLOG
C
Cybersecurity and Infrastructure Security Agency CISA
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
S
Securelist
S
Security Affairs
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
L
LINUX DO - 热门话题
博客园 - 三生石上(FineUI控件)
T
Threatpost
T
The Blog of Author Tim Ferriss
C
CERT Recently Published Vulnerability Notes
IT之家
IT之家
P
Palo Alto Networks Blog
Microsoft Azure Blog
Microsoft Azure Blog
Spread Privacy
Spread Privacy
Cyberwarzone
Cyberwarzone
腾讯CDC
L
LangChain Blog
Know Your Adversary
Know Your Adversary
C
CXSECURITY Database RSS Feed - CXSecurity.com
GbyAI
GbyAI
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
I
Intezer
T
Tor Project blog
AWS News Blog
AWS News Blog
T
Tenable Blog
NISL@THU
NISL@THU
Security Latest
Security Latest
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
H
Hackread – Cybersecurity News, Data Breaches, AI and More
人人都是产品经理
人人都是产品经理
MongoDB | Blog
MongoDB | Blog
MyScale Blog
MyScale Blog
D
DataBreaches.Net
Microsoft Security Blog
Microsoft Security Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
量子位
美团技术团队
The Cloudflare Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
罗磊的独立博客
The GitHub Blog
The GitHub Blog
阮一峰的网络日志
阮一峰的网络日志
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Stack Overflow Blog
Stack Overflow Blog

博客园 - 老金

直接初始化和复制初始化 C++ 内连接与外连接 (转) Linux操作系统多线程信号总结 Linux操作系统多线程信号总结(转) 转-C/C++捕获段错误,打印出错的具体位置(精确到哪一行) 关键字restrict简介 使用SMTP 和POP3 协议实现收发邮件(C/C++) (转) C/C++中的日期和时间 time_t与struct tm Unicode(UTF-8, UTF-16)令人混淆的概念 跟着url走一圈(ASP.NET请求底层流转个人总结 二) 跟着url走一圈(ASP.NET请求底层流转个人总结 一) GDB教程详解&打印STL容器 C# 中的"yield"使用 谈谈.Net中的协变和逆变(转) 对象的比较与排序:IComparable和IComparer接口 jsoncpp在linux下的配置 在Ubuntu上安装并C++使用libmemcached C++ Primer 第十六章 模板与范型编程 C++ Primer 第十五章 面向对象编程
mysql-Innodb事务隔离级别-repeatable read详解(转)
老金 · 2013-09-23 · via 博客园 - 老金

一、事务隔离级别

ANSI/ISO SQL标准定义了4中事务隔离级别:未提交读(read uncommitted),提交读(read committed),重复读(repeatable read),串行读(serializable)。

对于不同的事务,采用不同的隔离级别分别有不同的结果。不同的隔离级别有不同的现象。主要有下面3种现在:

1、脏读(dirty read):一个事务可以读取另一个尚未提交事务的修改数据。

2、非重复读(nonrepeatable read):在同一个事务中,同一个查询在T1时间读取某一行,在T2时间重新读取这一行时候,这一行的数据已经发生修改,可能被更新了(update),也可能被删除了(delete)。

3、幻像读(phantom read):在同一事务中,同一查询多次进行时候,由于其他插入操作(insert)的事务提交,导致每次返回不同的结果集。

不同的隔离级别有不同的现象,并有不同的锁定/并发机制,隔离级别越高,数据库的并发性就越差,4种事务隔离级别分别表现的现象如下表:

隔离级别 脏读 非重复读 幻像读
read uncommitted 允许 允许 允许
read committed   允许 允许
repeatable read     允许
serializable      

二、数据库中的默认事务隔离级别

在Oracle中默认的事务隔离级别是提交读(read committed)。

对于MySQL的Innodb的默认事务隔离级别是重复读(repeatable read。可以通过下面的命令查看:

mysql> SELECT @@GLOBAL.tx_isolation, @@tx_isolation;

+———————–+—————–+

| @@GLOBAL.tx_isolation | @@tx_isolation  |

+———————–+—————–+

| REPEATABLE-READ | REPEATABLE-READ |

+———————–+—————–+

1 row in set (0.00 sec)

下面进行一下测试:

Time Session 1 Session 2
T1 set autocommit=0; set autocommit=0;
T2 mysql> select * from tmp_test;

+——+———+ | id   | version | +——+———+ |    1 |       1 | +——+———+

1 row in set (0.00 sec)

 
T3   mysql> update tmp_test set version=2 where id=1;

Query OK, 1 row affected (0.02 sec)

Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from tmp_test;

+——+———+ | id   | version | +——+———+ |    1 |       2 | +——+———+

1 row in set (0.00 sec)

T4 mysql> select * from tmp_test;

+——+———+ | id   | version | +——+———+ |    1 |       1 | +——+———+

1 row in set (0.00 sec)

【说明】 Session 2未提交,看到数据不变,无脏读。

 
T5   commit;
T6 mysql> select * from tmp_test;

+——+———+ | id   | version | +——+———+ |    1 |       1 | +——+———+

1 row in set (0.00 sec)

【说明】 Session 2已经提交,还是看到数据不变,即可以重复读。

 
T7 commit;  
T8 mysql> select * from tmp_test;

+——+———+ | id   | version | +——+———+ |    1 |       2 | +——+———+

1 row in set (0.00 sec)

【说明】 提交事务,看到最新数据。

 
T9   mysql> insert into tmp_test values(2,1);

Query OK, 1 row affected (0.00 sec)

mysql> select * from tmp_test;

+——+———+ | id   | version | +——+———+ |    1 |       2 | |    2 |       1 | +——+———+

2 rows in set (0.00 sec)

mysql> commit;

Query OK, 0 rows affected (0.00 sec)

T10 mysql> select * from tmp_test;

+——+———+ | id   | version | +——+———+ |    1 |       2 | +——+———+

1 row in set (0.00 sec)

【说明】 Session 2的insert事务已经提交,看到的数据和T8的时候一样,即未发生幻象读。

 
T11 mysql> commit;

Query OK, 0 rows affected (0.00 sec)

mysql> select * from tmp_test;

+——+———+ | id   | version | +——+———+ |    1 |       2 | |    2 |       1 | +——+———+

2 rows in set (0.00 sec)

【说明】 事务提交,看到最新数据。

 

上面的结果可以看到Innodb的重复读(repeatable read)不允许脏读,不允许非重复读(即可以重复读,Innodb使用多版本一致性读来实现)和不允许幻象读(这点和ANSI/ISO SQL标准定义的有所区别)。

另外,同样的测试:

1、当session 2进行truncate表的时候,这个时候session 1再次查询就看不到数据。

2、当session 2进行alter表的时候,这个时候session 1再次查询就看不到数据。

造成以上的原因是因为 mysql的持续非锁定读,在repeatable read级别下,读采用的是持续非锁定读。相关介绍见下面:

持续读意味着InnoDB使用它的多版本化来给一个查询展示某个时间点处数据库的快照。查询看到在那个时间点之前被提交的那些确切事务做的更改,并且没有其后的事务或未提交事务做的改变。这个规则的例外是,查询看到发布该查询的事务本身所做的改变。

如果你运行在默认的REPEATABLE READ隔离级别,则在同一事务内的所有持续读读取由该事务中第一个这样的读所确立的快照。你可以通过提交当前事务并在发布新查询的事务之后,为你的查询获得一个更新鲜的快照。

持续读是默认模式,在其中InnoDBzai在READ COMMITTED和REPEATABLE READ隔离级别处理SELECT语句。持续读不在任何它访问的表上设置锁定,因此,其它用户可自由地在持续读在一个表上执行的同一时间修改这些表。

注意,持续读不在DROP TABLE和ALTER TABLE上作用。持续读不在DROP TABLE上作用,因为MySQL不能使用已经被移除的表,并且InnoDB 破坏了该表。持续读不在ALTER TABLE上作用,因为它在某事务内执行,该事务创建一个新表,并且从旧表往新表中插入行。现在,当你重新发出持续读之时,它不能在新表中看见任何行,因为它们被插入到一个在持续读读取的快照中不可见的事务 里。