`

通过例子理解事务的4种隔离级别

 
阅读更多

SQL标准定义了4种隔离级别,包括了一些具体规则,用来限定事务内外的哪些改变是可见的,哪些是不可见的。

低级别的隔离级一般支持更高的并发处理,并拥有更低的系统开销。

 

首先,我们使用 test 数据库,新建 tx 表,并且如图所示打开两个窗口来操作同一个数据库:

 


第1级别:Read Uncommitted(读取未提交内容)
(1)所有事务都可以看到其他未提交事务的执行结果
(2)本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少
(3)该级别引发的问题是——脏读(Dirty Read):读取到了未提交的数据

复制代码
#首先,修改隔离级别
set tx_isolation='READ-UNCOMMITTED';
select @@tx_isolation;
+------------------+
| @@tx_isolation   |
+------------------+
| READ-UNCOMMITTED |
+------------------+

#事务A:启动一个事务
start transaction;
select * from tx;
+------+------+
| id   | num  |
+------+------+
|    1 |    1 |
|    2 |    2 |
|    3 |    3 |
+------+------+

#事务B:也启动一个事务(那么两个事务交叉了)
       在事务B中执行更新语句,且不提交
start transaction;
update tx set num=10 where id=1;
select * from tx;
+------+------+
| id   | num  |
+------+------+
|    1 |   10 |
|    2 |    2 |
|    3 |    3 |
+------+------+

#事务A:那么这时候事务A能看到这个更新了的数据吗?
select * from tx;
+------+------+
| id   | num  |
+------+------+
|    1 |   10 |   --->可以看到!说明我们读到了事务B还没有提交的数据
|    2 |    2 |
|    3 |    3 |
+------+------+

#事务B:事务B回滚,仍然未提交
rollback;
select * from tx;
+------+------+
| id   | num  |
+------+------+
|    1 |    1 |
|    2 |    2 |
|    3 |    3 |
+------+------+

#事务A:在事务A里面看到的也是B没有提交的数据
select * from tx;
+------+------+
| id   | num  |
+------+------+
|    1 |    1 |      --->脏读意味着我在这个事务中(A中),事务B虽然没有提交,但它任何一条数据变化,我都可以看到!
|    2 |    2 |
|    3 |    3 |
+------+------+
复制代码

 


第2级别:Read Committed(读取提交内容)

(1)这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)
(2)它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变
(3)这种隔离级别出现的问题是——不可重复读(Nonrepeatable Read):不可重复读意味着我们在同一个事务中执行完全相同的select语句时可能看到不一样的结果。
     |——>导致这种情况的原因可能有:(1)有一个交叉的事务有新的commit,导致了数据的改变;(2)一个数据库被多个实例操作时,同一事务的其他实例在该实例处理其间可能会有新的commit

复制代码
#首先修改隔离级别
set tx_isolation='read-committed';
select @@tx_isolation;
+----------------+
| @@tx_isolation |
+----------------+
| READ-COMMITTED |
+----------------+

#事务A:启动一个事务
start transaction;
select * from tx;
+------+------+
| id   | num  |
+------+------+
|    1 |    1 |
|    2 |    2 |
|    3 |    3 |
+------+------+

#事务B:也启动一个事务(那么两个事务交叉了)
       在这事务中更新数据,且未提交
start transaction;
update tx set num=10 where id=1;
select * from tx;
+------+------+
| id   | num  |
+------+------+
|    1 |   10 |
|    2 |    2 |
|    3 |    3 |
+------+------+

#事务A:这个时候我们在事务A中能看到数据的变化吗?
select * from tx; --------------->
+------+------+                |
| id   | num  |                |
+------+------+                |
|    1 |    1 |--->并不能看到!  |
|    2 |    2 |                |
|    3 |    3 |                |
+------+------+                |——>相同的select语句,结果却不一样
                                  |
#事务B:如果提交了事务B呢?            |
commit;                           |
                                  |
#事务A:                            |
select * from tx; --------------->
+------+------+
| id   | num  |
+------+------+
|    1 |   10 |--->因为事务B已经提交了,所以在A中我们看到了数据变化
|    2 |    2 |
|    3 |    3 |
+------+------+
复制代码

 


第3级别:Repeatable Read(可重读)
(1)这是MySQL的默认事务隔离级别
(2)它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行
(3)此级别可能出现的问题——幻读(Phantom Read):当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影” 行
(4)InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了该问题

复制代码
#首先,更改隔离级别
set tx_isolation='repeatable-read';
select @@tx_isolation;
+-----------------+
| @@tx_isolation  |
+-----------------+
| REPEATABLE-READ |
+-----------------+

#事务A:启动一个事务
start transaction;
select * from tx;
+------+------+
| id   | num  |
+------+------+
|    1 |    1 |
|    2 |    2 |
|    3 |    3 |
+------+------+

#事务B:开启一个新事务(那么这两个事务交叉了)
       在事务B中更新数据,并提交
start transaction;
update tx set num=10 where id=1;
select * from tx;
+------+------+
| id   | num  |
+------+------+
|    1 |   10 |
|    2 |    2 |
|    3 |    3 |
+------+------+
commit;

#事务A:这时候即使事务B已经提交了,但A能不能看到数据变化?
select * from tx;
+------+------+
| id   | num  |
+------+------+
|    1 |    1 | --->还是看不到的!(这个级别2不一样,也说明级别3解决了不可重复读问题)
|    2 |    2 |
|    3 |    3 |
+------+------+

#事务A:只有当事务A也提交了,它才能够看到数据变化
commit;
select * from tx;
+------+------+
| id   | num  |
+------+------+
|    1 |   10 |
|    2 |    2 |
|    3 |    3 |
+------+------+
复制代码

 


第4级别:Serializable(可串行化)
(1)这是最高的隔离级别
(2)它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。
(3)在这个级别,可能导致大量的超时现象和锁竞争

复制代码
#首先修改隔离界别
set tx_isolation='serializable';
select @@tx_isolation;
+----------------+
| @@tx_isolation |
+----------------+
| SERIALIZABLE   |
+----------------+

#事务A:开启一个新事务
start transaction;

#事务B:在A没有commit之前,这个交叉事务是不能更改数据的
start transaction;
insert tx values('4','4');
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
update tx set num=10 where id=1;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
复制代码

 


           

转自:http://www.cnblogs.com/snsdzjlz320/p/5761387.html

分享到:
评论

相关推荐

    MySQL事务隔离级别详解.docx

    通过一个实例来理解这四种事务隔离级别。首先,我们创建一个test数据库,并新建一个test表。然后,我们修改隔离级别为Read Uncommitted,启动两个事务A和B。事务A执行select * from test;,事务B执行update test set...

    2019-8-7-MySQL的四种事务隔离级别1

    理解并选择合适的事务隔离级别对于数据库的设计和优化至关重要,因为它直接影响到系统的并发性能和数据的一致性。在实际应用中,需要根据业务需求平衡并发性和数据完整性,合理设定事务隔离级别。

    mysql数据库事务隔离级别[参照].pdf

    事务隔离级别是数据库系统用来解决并发问题,保证数据正确性的一种策略。MySQL数据库提供了四种不同的事务隔离级别,它们分别是读未提交(Read Uncommitted)、读已提交(Read Committed)、可重复读(Repeatable ...

    事务的传播行为和隔离级别.docx

    通过以上介绍,我们可以看到事务的传播行为和隔离级别是事务管理中的两个重要概念。正确理解和应用它们对于保证应用程序的一致性和完整性至关重要。在实际开发过程中,应根据业务需求和系统特性灵活选择合适的传播...

    Spring事务隔离级别简介及实例解析

    Spring事务隔离级别简介及实例解析 本文主要介绍了Spring事务隔离级别的概念和实例解析,涵盖了四个事务隔离级别...本文详细介绍了Spring事务隔离级别的概念和实例解析,帮助读者更好地理解和应用Spring事务隔离级别。

    C#事务原理与实例

    【C#事务原理详解】 事务在C#编程中扮演着至关重要的角色,特别是在涉及数据库操作时,它确保了数据的一致性和完整性。...因此,理解事务的原理和隔离级别选择,是编写高效、健壮的C#数据库应用程序的关键。

    spring学习笔记(十六)-声明式事务的例子

    事务的五大属性包括:Propagation(传播行为)、Isolation(隔离级别)、Read Only(只读事务)、Timeout(超时时间)和Rollback For(触发回滚的异常类型)。其中,Propagation是最重要的一个,常见的有REQUIRED...

    WCF中使用Transaction的例子,通过这个例子学会事务的使用

    6. **事务隔离级别**:事务的隔离级别决定了并发操作之间的可见性。在配置或代码中,可以设置适当的隔离级别,如ReadUncommitted、ReadCommitted、RepeatableRead、Serializable等。 在提供的"Transactional ...

    注解版本声明事务小例子

    虽然注解方式更简洁,易于理解和维护,但XML配置提供了更多的灵活性,例如可以更精细地控制事务属性,如传播行为、隔离级别、超时等。传播行为如REQUIRED(默认,如果有事务就加入,没有就新建)、REQUIRES_NEW...

    Mysql事务隔离级别之读提交详解

    “读提交”是MySQL的四种事务隔离级别之一,其他三种包括读未提交(READ-UNCOMMITTED)、可重复读(REPEATABLE-READ,MySQL的默认级别)和串行化(SERIALIZABLE)。每种隔离级别决定了事务在读取数据时如何处理其他...

    JDBC事务操作例子所需jar包

    3. **Transaction隔离级别**:事务有四种隔离级别,包括读未提交(READ UNCOMMITTED)、读已提交(READ COMMITTED)、可重复读(REPEATABLE READ)和串行化(SERIALIZABLE)。每个级别决定了一个事务在执行时能看到...

    WCF写的小例子涉及到WCF中的事务

    6. **配置连接**:在服务和客户端的配置文件中,需要正确配置事务处理相关的设置,如事务超时、事务隔离级别等。 通过以上步骤,我们可以实现一个基于WCF的银行转账服务,该服务使用事务确保了转账操作的完整性和...

    day36 09-Hibernate中的事务:事务处理

    在Hibernate的配置文件中,可以设置事务相关的属性,比如默认的事务隔离级别、是否自动开始事务等。例如: ```xml <property name="hibernate.connection.isolation">2</property> <!-- 2对应READ_COMMITTED隔离...

    Mysql事务以及锁原理讲解.pdf

    根据不同的事务隔离级别,MySQL的锁策略也会有所不同。不同的隔离级别能够防止不同种类的数据不一致性问题,但同时也会影响数据库的性能。隔离级别从低到高包括:读未提交(Read Uncommitted)、读已提交(Read ...

    Hibernate事务(源码)

    根据数据库系统的不同,Hibernate支持四种事务隔离级别:READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ和SERIALIZABLE。不同的隔离级别会带来不同的并发控制效果,开发者需要根据实际需求选择合适的级别。 ##...

    spring 的3种事务配置方式

    事务隔离级别包括`ISOLATION_DEFAULT`(使用数据库默认级别)、`ISOLATION_READ_UNCOMMITTED`(读未提交)、`ISOLATION_READ_COMMITTED`(读已提交)、`ISOLATION_REPEATABLE_READ`(可重复读)和`ISOLATION_...

    全面了解MySql中的事务

    MySQL中的事务是数据库操作的重要概念,它主要用于确保一组...理解事务的概念、特性和隔离级别对于开发高效且可靠的数据库应用至关重要。在实际使用中,根据业务需求选择合适的隔离级别,以平衡数据安全与系统性能。

    spring 自定义事务管理器,编程式事务,声明式事务@Transactional使用

    `@Transactional`可以设置不同的属性,如`propagation`(传播行为)、`isolation`(隔离级别)、`rollbackFor`(触发回滚的异常类型)等。下面是一个声明式事务的例子: ```java @Service public class UserService...

    spring 简单实例 事务回滚

    2. 注解驱动:我们可以使用`@EnableTransactionManagement`注解启用基于注解的事务管理,并配置事务属性,比如传播行为、隔离级别和超时设置。 3. 使用`@Transactional`:在需要进行事务控制的方法上添加`@...

Global site tag (gtag.js) - Google Analytics