MySQL事务学习-->隔离级别

6 事务的隔离级别

设置的目的

数据库操作中,为了有效保证并发读取数据的正确性,提出的事务隔离级别。

数据库是要被广大客户所共享访问的,那么在数据库操作过程中很可能出现以下几种不确定情况。

更新丢失

两个事务都同时更新一行数据,但是第二个事务却中途失败退出,导致对数据的两个修改都失效了。这是因为系统没有执行任何的锁操作,因此并发事务并没有被隔离开来。

脏读

一个事务开始读取了某行数据,但是另外一个事务已经更新了此数据但没有能够及时提交。这是相当危险的,因为很可能所有的操作都被回滚。

不可重复读(Non-repeatable Reads)

一个事务对同一行数据重复读取两次,但是却得到了不同的结果。它包括以下情况:

(1) 事务T1读取某一数据后,事务T2对其做了修改,当事务T1再次读该数据时得到与前一次不同的值。

(2) 幻读(Phantom Reads):事务在操作过程中进行两次查询,第二次查询的结果包含了第一次查询中未出现的数据或者缺少了第一次查询中出现的数据(这里并不要求两次查询的SQL语句相同)。这是因为在两次查询过程中有另外一个事务插入数据造成的。

解决方案

为了避免上面出现的几种情况,在标准SQL规范中,定义了4个事务隔离级别,不同的隔离级别对事务的处理不同。

未授权读取

也称为读未提交(Read Uncommitted):允许脏读取,但不允许更新丢失。如果一个事务已经开始写数据,则另外一个事务则不允许同时进行写操作,但允许其他事务读此行数据。该隔离级别可以通过“排他写锁”实现。

授权读取

也称为读提交(Read Committed):允许不可重复读取,但不允许脏读取。这可以通过“瞬间共享读锁”和“排他写锁”实现。读取数据的事务允许其他事务继续访问该行数据,但是未提交的写事务将会禁止其他事务访问该行。

可重复读取

可重复读取(Repeatable Read):禁止不可重复读取和脏读取,但是有时可能出现幻影数据。这可以通过“共享读锁”和“排他写锁”实现。读取数据的事务将会禁止写事务(但允许读事务),写事务则禁止任何其他事务。

序列化

序列化(Serializable):提供严格的事务隔离。它要求事务序列化执行,事务只能一个接着一个地执行,但不能并发执行。如果仅仅通过“行级锁”是无法实现事务序列化的,必须通过其他机制保证新插入的数据不会被刚执行查询操作的事务访问到。

隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大。对于多数应用程序,可以优先考虑把数据库系统的隔离级别设为Read Committed。它能够避免脏读取,而且具有较好的并发性能。尽管它会导致不可重复读、虚读和第二类丢失更新这些并发问题,在可能出现这类问题的个别场合,可以由应用程序采用悲观锁或乐观锁来控制。

在MySQL中设置事务隔离级别有2种方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
1 在my.cnf中设置,在mysqld选项中如下设置
[mysqld]
 transaction-isolation = READ-COMMITTED
 
2 在mysql窗口用set命令重置
[sql]
mysql> set global tx_isolation='REPEATABLE-READ'
Query OK, 0 rows affected (0.01 sec) 
    
mysql> 
查询当前的会话事务级别,可以使用:
[sql]
mysql> select @@tx_isolation; 
+----------------+ 
| @@tx_isolation | 
+----------------+ 
| READ-COMMITTED
+----------------+ 
1 row in set (0.00 sec) 
    
mysql> 
 
 
查询全局的事务隔离级别,可以使用
[sql]
mysql> select @@global.tx_isolation; 
+-----------------------+ 
| @@global.tx_isolation | 
+-----------------------+ 
| READ-COMMITTED       
+-----------------------+ 
1 row in set (0.00 sec) 
    
mysql> 
 
 
 
Serializable模式下。
[sql]
mysql> system cat /usr/local/mysql56m2/my.cnf |grep  transaction-isolation 
transaction-isolation = READ-COMMITTED 
mysql> 
 
 
 
复制二进制与隔离级别的关系
SERIALIZABLE模式下,Innodb存储引擎会对每个select语句自动加Lock in sharedmode,给每一个读操作加共享锁。因此在这个隔离级别下,读占用锁了,一致性的非锁定读不再予以支持。因为Innodb存储引擎在repeatable read 模式下就已经达到了3度的隔离,所以一般不在本地事务中使用serializable隔离级别,serializable的事务隔离级别主要用于innodb存储引擎的分布式事务。
 
Read committed的隔离模式下,除了唯一性约束检查以及外键约束检查需要Gap lock,innodb存储引擎不会使用gap lock的锁算法。不过使用read committed隔离级别需要注意一些问题,mysql5.1中,Read committed的事务隔离级别默认只能在replication的二进制为row格式下,如果二进制默认在statement模式下,则会报如下错误:
[sql]
mysql> select @@version; 
+-------------+ 
| @@version   | 
+-------------+ 
| 5.5.25a-log | 
+-------------+ 
1 row in set (0.00 sec) 
    
mysql> 
mysql> select @@binlog_format; 
+-----------------+ 
| @@binlog_format | 
+-----------------+ 
| STATEMENT       | 
+-----------------+ 
1 row in set (0.00 sec) 
    
mysql> select @@tx_isolation; 
+-----------------+ 
| @@tx_isolation  | 
+-----------------+ 
| REPEATABLE-READ
+-----------------+ 
1 row in set (0.00 sec) 
    
mysql> set tx_isolation='READ-COMMITTED'
Query OK, 0 rows affected (0.00 sec) 
    
mysql> use test; 
Database changed 
mysql> create table a (b int, primary key (b)) engine=innodb; 
ERROR 1050 (42S01): Table 'a' already exists 
mysql> select @@tx_isolation; 
+----------------+ 
| @@tx_isolation | 
+----------------+ 
| READ-COMMITTED
+----------------+ 
1 row in set (0.00 sec) 
    
mysql> begin 
    -> ; 
Query OK, 0 rows affected (0.00 sec) 
    
mysql> insert into a select 100000; 
ERROR 1665 (HY000): Cannotexecute statement: impossible to write to binary log since BINLOG_FORMAT =STATEMENT and at least one table uses a storage engine limited to row-basedlogging. InnoDB is limited to row-logging when transaction isolation level isREAD COMMITTED or READ UNCOMMITTED
 
 ERROR 1665 (HY000): Cannotexecute statement: impossible to write to binary log since BINLOG_FORMAT =STATEMENT and at least one table uses a storage engine limited to row-basedlogging. InnoDB is limited to row-logging when transaction isolation level isREAD COMMITTED or READ UNCOMMITTED.
[Note]:在mysql5.1以及mysql5.6模式下实验过都是如此。也许可以知道通过将innodb_locks_unsafe_for_binlog设置为1,来可以使binlog日志在statement下使用readcommitted的事务隔离级别:
[sql]
mysql> select @@innodb_locks_unsafe_for_binlog; 
+----------------------------------+ 
| @@innodb_locks_unsafe_for_binlog | 
+----------------------------------+ 
|                               0 | 
+----------------------------------+ 
1 row in set (0.00 sec) 
mysql> set global innodb_locks_unsafe_for_binlog=1; 
ERROR 1238 (HY000): Variable 'innodb_locks_unsafe_for_binlog' is a readonly variable 
mysql> 
 
 
此参数是只读模式,需要修改my.cnf重新启动才行。
在my.cnf里面的[mysqld]添加
[mysqld]
innodb_locks_unsafe_for_binlog = 1
然后重启,然后去check模仿一个事务操作,如下所示:
[sql]
mysql> select @@innodb_locks_unsafe_for_binlog; 
+----------------------------------+ 
| @@innodb_locks_unsafe_for_binlog | 
+----------------------------------+ 
|                               1 | 
+----------------------------------+ 
1 row in set (0.00 sec) 
    
mysql> 
mysql> use test; 
Reading table information for completion of table and column names 
You can turn off this feature to get a quicker startup with -A 
    
Database changed 
mysql> select @@tx_isolation; 
+----------------+ 
| @@tx_isolation | 
+----------------+ 
| READ-COMMITTED
+----------------+ 
1 row in set (0.00 sec) 
mysql> begin
Query OK, 0 rows affected (0.00 sec) 
    
mysql> insert into t select 15; 
Query OK, 1 row affected (0.00 sec) 
Records: 1  Duplicates: 0  Warnings: 0 
    
mysql> commit
Query OK, 0 rows affected (0.00 sec) 
mysql> select * from t; 
+--------+ 
| id     | 
+--------+ 
|      1 | 
|     12 | 
|     15 | 
|  11111 | 
| 111110 | 
+--------+ 
5 rows in set (0.00 sec) 

MySQL事务学习-->隔离级别的更多相关文章

  1. [转]MySQL事务学习-->隔离级别

    From : http://blog.csdn.net/mchdba/article/details/12837427 6 事务的隔离级别 设置的目的 在数据库操作中,为了有效保证并发读取数据的正确性 ...

  2. MySQL事务及隔离级别详解

    MySQL事务及隔离级别详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.MySQL的基本架构 MySQL的基本架构可以分为三块,即连接池,核心功能层,存储引擎层. 1> ...

  3. MySql事务及隔离级别

    在数据库中,所谓事务是指作为单个逻辑工作单元执行的一系列操作. 事务的操作: 先定义开始一个事务,然后对数据作修改操作, 这时如果提交(COMMIT),这些修改就永久地保存下来 如果回退(ROLLBA ...

  4. MySql事务的隔离级别及作用

    逻辑工作单元遵循一系列(ACID)规则则称为事务. 原子性:保证事务是一系列的运作,如果中间过程有一个不成功则全部回滚,全部成功则成功.保证了事务的原则性. 一致性:一致性指的是比如A向B转100块钱 ...

  5. MySQL事务及隔离级别(读书小结)

    标签: MySQL事务 隔离 0.什么是事务? 事务是指MySQL的一些操作看做是一个不可分割的执行单元.事务的特点是要么所有操作都执行成功,要么一个都不执行.也就是如果一个事务有操作执行失败,那么就 ...

  6. MySQL事务的隔离级别

    为什么需要隔离 当多个线程都开启事务操作数据库中的数据时,数据库系统要能进行隔离操作,以保证各个线程获取数据的准确性,在介绍数据库提供的各种隔离级别之前,我们先看看如果不考虑事务的隔离性,会发生的几种 ...

  7. mysql 事务、隔离级别

    一.事务的四大特性(ACID) 1.原子性(Atomicity):事务开始后所有操作,要么全部做完,要么全部不做,不可能停滞在中间环节.事务执行过程中出错,会回滚到事务开始前的状态,所有的操作就像没有 ...

  8. MySQL——事务ACID&隔离级别

    数据库事务ACID&隔离级别 什么是事务 事务是用户定义的一个数据库操作序列.这些操作要么全执行,要么全不执行,是一个不可分割的工作单元.在关系型数据库中,事务可以是一条SQL语句,也可以是一 ...

  9. MySQL 事务的隔离级别

    转载:https://developer.aliyun.com/article/743691?accounttraceid=80d4fddb3dc64b97a71118659e106221tozz 简 ...

随机推荐

  1. Java继承和接口

    接口最关键的作用,也是使用接口最重要的一个原因:能上溯造型至多个基础类.使用接口的第二个原因与使用抽象基础类的原因是一样的:防止客户程序员制作这个类的一个对象,以及规定它仅仅是一个接口.这样便带来了一 ...

  2. mybatis同时启用mapperscanner和传统DAO

    在通过MapperScannerConfigurer启用了mybatis的映射器之后,默认情况下,在basePackage下的所有接口类都会被无条件的自动代理,如下所示: <!--mapper ...

  3. Spring MVC处理异常的4种方式

    http://blog.csdn.net/ufo2910628/article/details/40399539 http://my.oschina.net/CandyDesire/blog/3333 ...

  4. fakeLoader页面加载前loading演示8种效果

    提高用户体验的插件fakeLoader页面加载前loading演示8种效果 在线预览 下载地址 示例代码 <div id="main"> <div class=& ...

  5. browser.html – HTML 实现 Firefox UI

    browser.html 是一个实验性的项目,用于证明一个概念:使用 HTML 重新实现 Firefox UI ,并作为一个应用程序.它是基于浏览器的 API ,并以浏览器的方式和系统的应用工作.即使 ...

  6. border-radius如何兼容IE

    目前而言firefox,opera,chrome等主流浏览器都已经支持border-radius属性,唯独IE8以及之前. 解决办法就是在用的border-radius属性的后面加上:behavior ...

  7. 原生JS:Date对象详细参考

    Date对象:基于1970年1月1日(世界标准时间)起的毫秒数 本文参考MDN做的详细整理,方便大家参考MDN 构造函数: new Date(); 依据系统设置的当前时间来创建一个Date对象. ne ...

  8. Jquery在线引用地址

    Jquery在线引用地址: 1. 很多网站都是使用这种方式引入,客户的浏览器可能已经缓存过了 jquery.可以直接调用本地的,速度更快… 2. Google code 使用了 cdn 技术在很多地方 ...

  9. iOS Assigning to 'id<XXXDelegate>' from incompatible type 'BViewController *__strong'

    在使用代理的时候, BViewController *BVC = [[BViewController alloc]init]; self.delegate = BVC; 出现这样的警告Assignin ...

  10. SharePoint 2013 使用 PowerShell 更新用户

    在SharePoint开发中,经常会遇到网站部署,然而,当我们从开发环境,部署到正式环境以后,尤其是备份还原,所有用户组的用户,还依然是开发环境的,这时,我们就需要用PowerShell更新一下: P ...