精华内容
下载资源
问答
  • SQL数据库事务隔离级别总结
    2022-01-23 11:45:38

    概念

    保证一个事务的正确性,需要保证:

    • Atomicity 原子性:同一个事务中的操作,要么全部成功,要么全部失败。
    • Consistency 一致性:数据库中的数据保证合法,满足所有的约束(比如唯一约束)
    • Isolation 隔离性:不同的事务不能相互影响
    • Durability 持久性:事务提交,不管数据库是否崩溃重启,提交的事务所作出的修改都要生效

    如果不对事务进行隔离,多个事务同时发生在数据库中,将会导致以下的问题:

    • 脏读:一个事务读取到另一个未提交事务的修改。没保证原子性,如果当前事务基于这些脏数据进行操作,另一个事务回滚后,这些操作将会是错误的
    • 不可重复读:事务中,另外的事务提交了update或delete,导致当前事务前后读取到的数据不一致。没保证持久性,会导致当前事务覆盖另外事务的修改
    • 幻读:事务中,另外的事务提交了insert,导致当前事务前后读取到的数据总量不一致。当前事务先对唯一约束进行检查发现没有与将要插入的数据重复的,此时另外的事务提交了,导致当前事务进行插入后数据库中有两条相同的数据,破环了一致性

    为了避免上述的情况,数据库设置了不同的隔离级别:

    • read-uncommitted 读未提交:可以读到未提交的数据(完全不隔离)
    • read-committed 读已提交:只能读取已提交的数据(避免脏读)
    • repeatable-read 可重复读:只能读取到事务开始前,其它事务提交的数据(避免脏读、不可重复读)
    • serializable 串行化:所有事务一个一个执行,不进行并发(避免脏读、不可重复读、幻读)
    脏读不可重复读幻读
    读未提交‘✅隔离性
    读已提交原子性
    可重复读持久性
    串行化一致性

    实现

    以MySQL中的InnoDB为例。

    • 读未提交:不加锁
    • 读已提交:读取前加行锁,读取完毕释放
    • 可重复读:读取前加行锁,事务完成后释放
    • 串行化:读取前加表锁,事务完成后释放

    注意:MySQL中默认的事务隔离级别为可重复读。但是实际操作中会发现,事务中无法读取到另一个事务同时提交的insert数据。貌似MySQL的可重复读级别并没有幻读的问题。其实这是因为MySQL不仅使用锁机制来进行事务隔离,同时使用MVCC来增强。如果在事务中对另一个事务同时提交的insert数据进行update,会发现能够修改成功,并且修改后能够查询到数据。

    更多相关内容
  • 查看事务隔离级别 在 MySQL 中,可以通过show variables like ‘%tx_isolation%’或select @@tx_isolation;语句来查看当前事务隔离级别。 查看当前事务隔离级别的 SQL 语句和运行结果如下: mysql> show variables ...
  • 为什么会出现数据库的隔离级别呢? 数据库隔离级别是为了解决数据库并发访问过程中产生的各种数据安全问题. 事务的基本要素(ACID) ...隔离性(Isolation):同一时间,只允许一个事务请求同一数据,不同的事务之间
  • 数据库隔离级别有四种,应用《高性能mysql》一书中的说明:然后说说修改事务隔离级别的方法:1.全局修改,修改mysql.ini配置文件,在最后加上#可选参数有:READ-UNCOMMITTED,READ-COMMITTED,REPEATABLE-READ,...
  • 前言 ...我们都知道事务的几种性质,数据库中的一致性和隔离性等是实现事务的基本思想,在系统有大量的并发访问的情况下,了解和熟练应用数据库的本身的事务隔离级别,对于写出健壮性,并发处理能力强
  • MySQL 四种事务隔离级别详解及对比 按照SQL:1992 事务隔离级别,InnoDB默认是可重复读的(REPEATABLE READ)。MySQL/InnoDB 提供SQL标准所描述的所有四个事务隔离级别。你可以在命令行用–transaction-isolation选项...
  • 主要介绍了Spring事务隔离级别简介及实例解析,分享了相关代码示例,小编觉得还是挺不错的,具有一定借鉴价值,需要的朋友可以参考下
  •  我们都知道事务的几种性质,数据库为了维护这些性质,尤其是一致性和隔离性,一般使用加锁这种方式。同时数据库又是个高并发的应用,同一时间会有大量的并发访问,如果加锁过度,会极大的降低并发处理能力。所以...
  • 事务隔离 查询:默认事务隔离级别 mysql> select @@tx_isolation;当前会话的默认事务隔离级别 mysql> select @@session.tx_isolation;当前会话的默认事务隔离级别 mysql> select @@global.tx_isolation;全局的事务...
  • MySQL事务隔离级别

    2019-03-21 01:54:28
    NULL 博文链接:https://cuishuangjia.iteye.com/blog/964885
  • 数据库事务隔离级别 数据库事务隔离级别有4个,由低到高依次为 Read uncommitted:允许脏读。 Read committed: 防止脏读,最常用的隔离级别,并且是大多数数据库的默认隔离级别。 Repeatable read:可以防止脏...
  • 说说事务隔离级别吧? 老实说,事务隔离级别这个问题,无论是校招还是社招,面试官都爱问!然而目前网上很多文章,说句实在话啊,我看了后我都怀疑作者弄懂没!因为他们对可重复读(Repeatable Read)和串行化...
  • 主要介绍了MySql四种隔离级别,帮助大家更好的理解和学习MySQL,感兴趣的朋友可以了解下
  • 主要介绍了MySQL事务及Spring隔离级别实现原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • SQL标准定义了四种隔离级别隔离级别从低到高分别是:Read uncommitted 、Read committed 、Repeatable read 、Serializable。在各个隔离级别上被禁止出现的现象是: 脏读:一个事务读取了另一个并行未提交事务写入...
  • 事务隔离级别:一个事务对数据库的修改与并行的另一个事务的隔离程度
  • 这篇数据库教程SQLServer 事务隔离级别,教程操作方法:  数据库是要被广大客户所共享访问的,那么在数据库操作过程中很可能出现以下几种不确定情况。  更新丢失(Lost update)  两个事务都同时更新一行数据...
  • 数据库事务隔离级别

    2011-12-19 14:09:53
    介绍数据库事务的四种隔离级别,比较不同隔离级别的区别和影响
  • 之前在网上查询mysql事务隔离相关资料,一直只是脑子里有一个印象,久而久之还是会忘记,忘记后又要到网上查找相关资料,但是没实践过就对mysql事务隔离级别理解不是特别的深入,现在自己亲手实践体验一下这个这四个...
  • Isolation(隔离性): 事务允许多个用户对同一个数据进行并发访问,而不破坏数据的正 确性和完整性。同时,并行事务的修改必须与其他并行事务的修改 相互独立。 Durability(持久性): 事务结束后,事务处理的...
  • 事务隔离级别简单的说,就是当激活事务时,控制事务内因SQL语句产生的锁定需要保留多入,影响范围多大,以防止多人访问时,在事务内发生数据查询的错误。设置事务隔离级别将影响整条连接。
  • SQL标准定义了4种隔离级别,包括了一些具体规则,用来限定事务内外的哪些改变是可见的,哪些是不可见的。下面这篇文章通过实例详细的给大家分析了关于MySQL中的四种事务隔离级别的相关资料,需要的朋友可以参考下。
  • 数据库的事务隔离级别总结

    万次阅读 多人点赞 2019-06-07 12:23:03
    学习数据库的时候常常会接触到事务, ACID等概念,那么到底什么是数据库的事务,数据库事务又具有哪些特点,和ACID有怎样的关系,事务隔离级别又是做什么的呢?。 事务及其四大特性? 事务(Transaction):访问并...

    学习数据库的时候常常会接触到事务, ACID等概念,那么到底什么是数据库的事务,数据库事务又具有哪些特点,和ACID有怎样的关系,事务的隔离级别又是做什么的呢?。

    事务及其四大特性?

    事务(Transaction):访问并可能更新数据库中各种数据项的一个程序执行单元(unit),它通常由高级数据库操纵语言或编程语言(如SQL,C++或Java)书写的用户程序的执行所引起。当在数据库中更改数据成功时,在事务中更改的数据便会提交,不再改变。否则,事务就取消或者回滚,更改无效。

    举个例子来说,张三给李四转了1000元钱,那么在数据库操作时,就要先把张三的账户减去1000元,再把李四的账户加上1000元,两部分操作放在一起,才是一个完整的转账过程,也可称之为事务。

    (1)原子性(Atomicity)

    原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,这和前面两篇博客介绍事务的功能是一样的概念,因此事务的操作如果成功就必须要完全应用到数据库,如果操作失败则不能对数据库有任何影响。

    就像你买东西要么交钱收货一起都执行,要么要是发不出货,就退钱。

    (2) 一致性(Consistency)

    一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态

    拿转账来说,假设用户A和用户B两者的钱加起来一共是5000,那么不管A和B之间如何转账,转几次账,事务结束后两个用户的钱相加起来应该还得是5000,这就是事务的一致性。

    打个比方,你买东西这个事情,是不影响其他人的。

    (3)隔离性(Isolation)

    隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离

    即要达到这么一种效果:对于任意两个并发的事务T1和T2,在事务T1看来,T2要么在T1开始之前就已经结束,要么在T1结束之后才开始,这样每个事务都感觉不到有其他事务在并发地执行

    关于事务的隔离性数据库提供了多种隔离级别,稍后会介绍到。

    (4)持久性(Durability)

    持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。

    例如我们在使用JDBC操作数据库时,在提交事务方法后,提示用户事务操作完成,当我们程序执行完成直到看到提示后,就可以认定事务已经正确提交,即使这时候数据库出现了问题,也必须要将我们的事务完全执行完成,否则就会造成我们看到提示事务处理完毕,但是数据库因为故障而没有执行事务的重大错误。

    打个比方,你买东西的时候需要记录在账本上,即使老板忘记了那也有据可查。

    InnoDB引擎的事务实现

    InnoDB是mysql的一个存储引擎,大部分人对mysql都比较熟悉,这里简单介绍一下数据库事务实现的一些基本原理,在本地事务中,服务和资源在事务的包裹下可以看做是一体的。
    在这里插入图片描述
    而事务的ACID是通过InnoDB日志和锁来保证。事务的隔离性是通过数据库锁的机制实现的,持久性通过redo log(重做日志)来实现,原子性和一致性通过Undo log(回撤日志)来实现。Undo Log的原理很简单,为了满足事务的原子性,在操作任何数据之前,首先将数据备份到一个地方(这个存储数据备份的地方称为Undo Log)。然后进行数据的修改。如果出现了错误或者用户执行了roll back语句,系统可以利用Undo Log中的备份将数据恢复到事务开始之前的状态。 和Undo Log相反,Redo Log记录的是新数据的备份。在事务提交前,只要将RedoLog持久化即可,不需要将数据持久化。当系统崩溃时,虽然数据没有持久化,但是RedoLog已经持久化。系统可以根据Redo Log的内容,将所有数据恢复到最新的状态

    事务的隔离性及隔离级别

    以上介绍完事务的四大特性(简称ACID),现在重点来说明下事务的隔离性,当多个线程都开启事务操作数据库中的数据时,数据库系统要能进行隔离操作,以保证各个线程获取数据的准确性,在介绍数据库提供的各种隔离级别之前,我们先看看如果不考虑事务的隔离性,会发生的几种问题:
    在这里插入图片描述
    在这里插入图片描述
    3、幻读:一个事务在前后两次查询同一个范围的时候,后一次查询看到了前一次查询没有看到的行。如果事务中都使用快照读,那么就不会产生幻读现象,但是快照读和当前读混用就会产生幻读。关于快照读与当前读可参见《InnoDB对MVCC的实现》

    幻读和不可重复读都是读取了另一条已经提交的事务(这点就与脏读不同),所不同的是不可重复读查询的都是同一个数据项,而幻读针对的是一批数据整体(比如数据的个数)。

    “脏读”、“不可重复读”和“幻读”,其实都是数据库读一致性问题,必须由数据库提供一定的事务隔离机制来解决。数据库实现事务隔离的方式,基本上可分为以下两种:

    • 一种是在读取数据前,对其加锁,阻止其他事务对数据进行修改。
    • 另一种是不用加任何锁,通过一定机制生成一个数据请求时间点的一致性数据快照(Snapshot),并用这个快照来提供一定级别(语句级或事务级)的一致性读取。从用户的角度来看,好像是数据库可以提供同一数据的多个版本,因此,这种技术叫做数据多版本并发控制(MultiVersion Concurrency Control,简称MVCC或MCC),也经常称为多版本数据库。

    数据库的事务隔离越严格,并发副作用越小,但付出的代价也就越大,因为事务隔离实质上就是使事务在一定程度上 “串行化”进行,这显然与“并发”是矛盾的。同时,不同的应用对读一致性和事务隔离程度的要求也是不同的,比如许多应用对“不可重复读”和“幻读”并不敏感,可能更关心数据并发访问的能力。

    四种隔离级别

    为了解决“隔离”与“并发”的矛盾,ISO/ANSI SQL92定义了4个事务隔离级别,每个级别的隔离程度不同,允许出现的副作用也不同,应用可以根据自己的业务逻辑要求,通过选择不同的隔离级别来平衡 “隔离”与“并发”的矛盾。

    4个事务隔离级别:

    • Read uncommitted (读未提交):最低级别,以上问题均无法解决。
    • Read committed (读已提交):读已提交,可避免脏读情况发生。
    • Repeatable Read(可重复读):确保事务可以多次从一个字段中读取相同的值,在此事务持续期间,禁止其他事务对此字段的更新,可以避免脏读和不可重复读,仍会出现幻读问题。
    • Serializable (串行化):最严格的事务隔离级别,要求所有事务被串行执行,不能并发执行,可避免脏读、不可重复读、幻读情况的发生。

    这四种隔离级别,分别有可能产生问题总结如下:
    在这里插入图片描述

    很多人容易搞混不可重复读和幻读,确实这两者有些相似。但不可重复读重点在于update和delete,而幻读的重点在于insert。避免不可重复读需要锁行(某一行在select操作时,不允许update与delete)就行,避免幻读则需要锁表。如果使用锁机制来实现这两种隔离级别,在可重复读中,该sql第一次读取到数据后,就将这些数据加锁,其它事务无法修改这些数据,就可以实现可重复读了。但这种方法却无法锁住insert的数据,所以当事务A先前读取了数据,或者修改了全部数据,事务B还是可以insert数据提交,这时事务A就会发现莫名其妙多了一条之前没有的数据,幻读不能通过行锁来避免,需要Serializable隔离级别 ,读用读锁,写用写锁,读锁和写锁互斥,这么做可以有效的避免幻读、不可重复读、脏读等问题,但会极大的降低数据库的并发能力。所以说不可重复读和幻读最大的区别,就在于如何通过锁机制来解决他们产生的问题

    以上四种隔离级别最高的是Serializable级别,最低的是Read uncommitted级别,当然隔离级别越高,越能保证数据的完整性和统一性,但是执行效率就越低,对并发性能的影响也越大。像Serializable这样的级别,就是以锁表的方式(类似于Java多线程中的锁)使得其他的线程只能在锁外等待,所以平时选用何种隔离级别应该根据实际情况

    各类流行的数据库都实现了一些SQL标准中的事务隔离级别,但是他们的实现也是极其不一样的。Oracle仅仅实现了RC 和 SERIALIZABLE隔离级别。默认采用RC隔离级别,解决了脏读。但是允许不可重复读和幻读。其SERIALIZABLE则解决了脏读、不可重复读、幻读。MySQL支持全部4个隔离级别,但在具体实现时,有一些特点,比如在一些隔离级别下是采用MVCC一致性读,但某些情况下又不是。MySQL默认采用RR隔离级别,SQL标准是要求RR解决不可重复读的问题,但是因为MySQL通过nex-key lock在RR隔离级别下解决了幻读的问题。那么MySQL的SERIALIZABLE是怎么回事呢?MySQL的SERIALIZABLE采用了经典的实现方式,对读和写都加锁。

    查看MySQL数据库当前事务的隔离级别:

    select @@tx_isolation;
    

    在这里插入图片描述
    在MySQL数据库中设置事务的隔离级别:

    set  [glogal | session]  transaction isolation level 隔离级别名称;
    set tx_isolation=’隔离级别名称;’
    

    在这里插入图片描述

    互联网项目中MySQL用什么事务隔离级别

    Mysql默认的事务隔离级别是可重复读(Repeatable Read),那互联网项目中Mysql也是用默认隔离级别,不做修改么? OK,不是的,我们在项目中一般用读已提交(Read Commited)这个隔离级别! 居然是读已提交。

    我们先来思考一个问题,在Oracle、SqlServer中都是选择读已提交(Read Commited)作为默认的隔离级别,为什么Mysql不选择读已提交(Read Commited)作为默认隔离级别,而选择可重复读(Repeatable Read)作为默认的隔离级别呢?

    我们先明白一点!项目中是不用读未提交(Read UnCommitted)和串行化(Serializable)两个隔离级别,原因有二: 采用读未提交(Read UnCommitted),一个事务读到另一个事务未提交读数据,这个不用多说吧,从逻辑上都说不过去!采用串行化(Serializable),每个次读操作都会加锁,快照读失效,一般是使用Mysql自带的分布式事务功能时才使用该隔离级别!也就是说,我们该纠结都只有一个问题,究竟隔离级别是用读已经提交呢还是可重复读? 接下来对这两种级别进行对比,讲讲我们为什么选读已提交(Read Commited)作为事务隔离级别!

    MySQL间隙锁

    当我们用范围条件而不是相等条件检索数据,并请求共享或排他锁时,InnoDB会给符合条件的已有数据记录的索引项加锁;对于键值在条件范围内但并不存在的记录,叫做“间隙(GAP)”,InnoDB也会对这个“间隙”加锁,这种锁机制就是所谓的间隙锁(GAP LOCK)。举例来说,假如user表中只有101条记录,其empid的值分别是 1,2,…,100,101,下面的SQL:

    select * from  user where user_id > 100 for update;
    

    这是一个范围条件的检索且要求加上排他锁,InnoDB不仅会对符合条件的user_id值为101的记录加锁,也会对user_id大于101(这些记录并不存在)的“间隙”加锁。

    InnoDB使用间隙锁的目的,一方面是为了防止幻读(为了防止幻读去锁表则影响太大,会影响效率),以满足相关隔离级别的要求,对于上面的例子,要是不使用间隙锁,如果其他事务插入了user_id大于100的任何记录,那么本事务如果再次执行上述语句,就会发生幻读;另外一方面,是为了满足其恢复和复制的需要(发生幻读时的binlog,如果直接拿到备库去执行会发生了主备数据不一致的严重问题)

    很显然,在使用范围条件检索并锁定记录时,InnoDB这种加锁机制会阻塞符合条件范围内键值的并发插入,这往往会造成严重的锁等待。因此,在实际应用开发中,尤其是并发插入比较多的应用,我们要尽量优化业务逻辑,尽量使用相等条件来访问更新数据,避免使用范围条件;当然,对一条不存在的记录加锁,也会有间隙锁的问题。

    间隙锁在InnoDB的唯一作用就是防止其它事务的插入操作,以此来达到防止幻读的发生,所以间隙锁不分什么共享锁与排它锁。如果InnoDB扫描的是一个主键、或是一个唯一索引的话,那InnoDB只会采用行锁方式来加锁,而不会使用Next-Key Lock的方式,也就是说不会对索引之间的间隙加锁。

    要禁止间隙锁的话,可以把隔离级别降为读已提交,或者开启参数innodb_locks_unsafe_for_binlog。

    RC与RR在锁方面的区别

    1、RR要用到间隙锁,而RC则没有间隙锁。因为MySQL的RR需要间隙锁来解决幻读问题。而RC隔离级别则是允许存在不可重复读和幻读的。所以RC的并发一般要好于RR;在RR隔离级别下,存在间隙锁,导致出现死锁的几率比RC大的多;
    2、 RC 隔离级别,通过 where 条件过滤之后,不符合条件的记录上的行锁,会被释放掉,但是RR隔离级别,即使不符合where条件的记录,也不会释放行锁和间隙锁,所以从锁方面来看,RC的并发应该要好于RR;
    3、RC隔离级别时,事务中的每一条select语句会读取到他自己执行时已经提交了的记录,也就是每一条select都有自己的一致性读ReadView; 而RR隔离级别时,事务中的一致性读的ReadView是以第一条select语句的运行时,作为本事务的一致性读snapshot的建立时间点的,只能读取该时间点之前已经提交的数据

    展开全文
  • 本人认为事务隔离级别是通过锁的机制实现的,事务隔离级别是数据库开发商根据业务逻辑的实际需要定义的一组锁的使用策略。当我们将数据库的隔离级别定义为某一级别后如仍不能满足要求,我们可以自定义sql的锁来...

    一直没搞清楚spring事务与数据库事务与锁之间的关系。

    spring事务:

    spring事务本质上使用数据库事务,而数据库事务本质上使用数据库锁,所以spring事务本质上使用数据库锁,开启spring事务意味着使用数据库锁;

    那么事务的隔离级别与锁有什么关系呢?本人认为事务的隔离级别是通过锁的机制实现的,事务的隔离级别是数据库开发商根据业务逻辑的实际需要定义的一组锁的使用策略。当我们将数据库的隔离级别定义为某一级别后如仍不能满足要求,我们可以自定义 sql 的锁来覆盖事务隔离级别默认的锁机制。

    spring事务实际使用AOP拦截注解方法,然后使用动态代理处理事务方法,捕获处理过程中的异常,spring事务其实是把异常交给spring处理;

    spring事务只有捕获到异常才会终止或回滚,如果你在程序中try/catch后自己处理异常而没有throw,那么事务将不会终止或回滚,失去事务本来的作用;

    spring事务会捕获所有的异常,但只会回滚数据库相关的操作,并且只有在声明了rollbackForClassName="Exception"之类的配置才会回滚;

    spring事务会回滚同一事务中的所有数据库操作,本质上是回滚同一数据库连接上的数据库操作;

     

    spring事务总结:

    spring事务本质上使用数据库锁;

    spring事务只有在方法执行过程中出现异常才会回滚,并且只回滚数据库相关的操作;

     

    对象锁和spring事务的对比:

    对象锁可以保证数据一致性和业务逻辑正确性,但不能保证并发性;

    spring事务不能严格保证数据一致性和业务逻辑正确性,但具有较好的并发性,因为只锁数据库行数据;

     

    建议:

    如果只有insert操作,可以使用事务;

    如果涉及update操作但不涉及其他业务逻辑,可以保守使用事务;

    如果涉及update操作及其他业务逻辑,慎用事务,

    并且数据库查询跟数据库更新之间尽量间隔较短,中间不宜插入太多其他逻辑,减少数据一致性的风险;

    对数据一致性要求不高的情况下可以使用事务结合乐观锁,否则建议用锁;

     

    spring事务为什么不能保证数据一致性和业务逻辑正确性:

    1.如果事务方法抛异常,此时会回滚数据库操作,但已经执行的其他方法不会回滚,因此无法保证业务逻辑正确性;

    2.即使事务方法不抛异常,也不能保证数据一致性(因为事务接口里的数据库操作在整个接口逻辑执行结束后才提交到数据 库,在接口最后提交到数据库的前后很有可能带来数据一致性的问题),从而不能保证业务逻辑正确性;

     

    Spring 事务的传播属性

    所谓spring事务的传播属性,就是定义在存在多个事务同时存在的时候,spring应该如何处理这些事务的行为。这些属性在TransactionDefinition中定义,具体常量的解释见下表:

    常量名称常量解释
    PROPAGATION_REQUIRED支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择,也是 Spring 默认的事务的传播。
    PROPAGATION_REQUIRES_NEW新建事务,如果当前存在事务,把当前事务挂起。新建的事务将和被挂起的事务没有任何关系,是两个独立的事务,外层事务失败回滚之后,不能回滚内层事务执行的结果,内层事务失败抛出异常,外层事务捕获,也可以不处理回滚操作
    PROPAGATION_SUPPORTS支持当前事务,如果当前没有事务,就以非事务方式执行。
    PROPAGATION_MANDATORY支持当前事务,如果当前没有事务,就抛出异常。
    PROPAGATION_NOT_SUPPORTED以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
    PROPAGATION_NEVER以非事务方式执行,如果当前存在事务,则抛出异常。
    PROPAGATION_NESTED

    如果一个活动的事务存在,则运行在一个嵌套的事务中。如果没有活动事务,则按REQUIRED属性执行。它使用了一个单独的事务,这个事务拥有多个可以回滚的保存点。内部事务的回滚不会对外部事务造成影响。它只对DataSourceTransactionManager事务管理器起效。

    数据库隔离级别

     

    隔离级别隔离级别的值导致的问题
    Read-Uncommitted0导致脏读
    Read-Committed1避免脏读,允许不可重复读和幻读
    Repeatable-Read2避免脏读,不可重复读,允许幻读
    Serializable3串行化读,事务只能一个一个执行,避免了脏读、不可重复读、幻读。执行效率慢,使用时慎重

    Spring中的隔离级别

     

    常量解释
    ISOLATION_DEFAULT这是个 PlatfromTransactionManager 默认的隔离级别,使用数据库默认的事务隔离级别。另外四个与 JDBC 的隔离级别相对应。
    ISOLATION_READ_UNCOMMITTED这是事务最低的隔离级别,它充许另外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读。
    ISOLATION_READ_COMMITTED保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。
    ISOLATION_REPEATABLE_READ这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。
    ISOLATION_SERIALIZABLE这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。

    事务管理:

     
    1. <!-- 配置事务管理 -->

    2. <bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

    3. <property name="dataSource" ref="dataSource" />

    4. </bean>

    Spring-mybatis 事务声明方式

    xml配置声明方式:

     
    1. <!-- 声明式事务管理 -->

    2. <tx:advice id="transactionAdvice" transaction-manager="transactionManager">

     
    1. <!-- 声明式事务管理 -->

    2. <tx:advice id="transactionAdvice" transaction-manager="transactionManager">

    3. <tx:attributes>

    4. <tx:method name="add*" propagation="REQUIRED" rollback-for="Exception"/>

    5. <tx:method name="save*" propagation="REQUIRED" rollback-for="Exception"/>

    6. <tx:method name="update*" propagation="REQUIRED" rollback-for="Exception"/>

    7. <tx:method name="modify*" propagation="REQUIRED" rollback-for="Exception"/>

    8. <tx:method name="edit*" propagation="REQUIRED" rollback-for="Exception"/>

    9. <tx:method name="insert*" propagation="REQUIRED" rollback-for="Exception"/>

    10. <tx:method name="delete*" propagation="REQUIRED" rollback-for="Exception"/>

    11. <tx:method name="del*" propagation="REQUIRED" rollback-for="Exception"/>

    12. <tx:method name="remove*" propagation="REQUIRED" rollback-for="Exception" />

    13. <tx:method name="testTransaction*" propagation="REQUIRED" rollback-for="Exception" read-only="true"/>

    14. </tx:attributes>

    15. </tx:advice>

    事务切入切面:

     
    1. <!-- 配置切面 -->

    2. <aop:config>

    3. <aop:pointcut id="transactionPointcut" expression="execution(* com.youx.qd.app.*.dservice.*.*(..))" />

    4. <aop:advisor pointcut-ref="transactionPointcut" advice-ref="transactionAdvice" />

    5. </aop:config>

    测试事务方法:

     
    1. @Override

    2. //@Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.SERIALIZABLE,rollbackFor = Exception.class)

    3. public ResponseDto testTransactionA() {

    4. System.out.println("开始事务A");

    5. iTb****Service.update****(1559540272306292637L,2);

    6. try {

    7. Thread.sleep(10000L);

    8. }catch (Exception e){

    9. e.printStackTrace();

    10. }

    11. System.out.println("结束事务A");

    12.  
    13. return null;

    14. }

    测试结果:表示在事务控制中该操作只允许读取操作

    Spring的事务管理器

    Spring并不直接管理事务,而是提供了多种事务管理器,它们将事务管理的职责委托给JTA或其他持久化机制所提供的平台相关的事务实现。每个事务管理器都会充当某一特定平台的事务实现的门面,这使得用户在Spring中使用事务时,几乎不用关注实际的事务实现是什么。

    Spring提供了许多内置事务管理器实现:

    • DataSourceTransactionManager位于org.springframework.jdbc.datasource包中,数据源事务管理器,提供对单个javax.sql.DataSource事务管理,用于Spring JDBC抽象框架、iBATIS或MyBatis框架的事务管理;
    • JdoTransactionManager位于org.springframework.orm.jdo包中,提供对单个javax.jdo.PersistenceManagerFactory事务管理,用于集成JDO框架时的事务管理;
    • JpaTransactionManager位于org.springframework.orm.jpa包中,提供对单个javax.persistence.EntityManagerFactory事务支持,用于集成JPA实现框架时的事务管理;
    • HibernateTransactionManager位于org.springframework.orm.hibernate3包中,提供对单个org.hibernate.SessionFactory事务支持,用于集成Hibernate框架时的事务管理;该事务管理器只支持Hibernate3+版本,且Spring3.0+版本只支持Hibernate 3.2+版本;
    • JtaTransactionManager位于org.springframework.transaction.jta包中,提供对分布式事务管理的支持,并将事务管理委托给Java EE应用服务器事务管理器;
    • OC4JjtaTransactionManager位于org.springframework.transaction.jta包中,Spring提供的对OC4J10.1.3+应用服务器事务管理器的适配器,此适配器用于对应用服务器提供的高级事务的支持;
    • WebSphereUowTransactionManager位于org.springframework.transaction.jta包中,Spring提供的对WebSphere 6.0+应用服务器事务管理器的适配器,此适配器用于对应用服务器提供的高级事务的支持;
    • WebLogicJtaTransactionManager位于org.springframework.transaction.jta包中,Spring提供的对WebLogic 8.1+应用服务器事务管理器的适配器,此适配器用于对应用服务器提供的高级事务的支持。

    声明事务配置分享

    spring中PROPAGATION类的事务属性详解

    1. PROPAGATION_REQUIRED:         支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。 

    2. PROPAGATION_SUPPORTS:         支持当前事务,如果当前没有事务,就以非事务方式执行。 

    3. PROPAGATION_MANDATORY:      支持当前事务,如果当前没有事务,就抛出异常。 

    4. PROPAGATION_REQUIRES_NEW:   新建事务,如果当前存在事务,把当前事务挂起。

    5.  PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 

    6. PROPAGATION_NEVER:               以非事务方式执行,如果当前存在事务,则抛出异常。 

    7. PROPAGATION_NESTED:              支持当前事务,如果当前事务存在,则执行一个嵌套事务,如果当前没有事务,就新建一个事务。

    如何在Spring配置文件中定义事务管理器:

    声明对本地事务的支持:

    a)JDBC及iBATIS、MyBatis框架事务管理器

    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    通过dataSource属性指定需要事务管理的单个javax.sql.DataSource对象。在幕后DataSourceTransactionManager通过调用java.sql.Connection来管理事务,而后者是通过DataSource获取到的。通过调用连接的commit()方法来提交事务。同样,事务失败时通过调用rollback()方法进行回滚。

    参考文档:https://www.jianshu.com/p/6b275553b54f

    b)Jdo事务管理器

    <bean id="txManager" class="org.springframework.orm.jdo.JdoTransactionManager">
        <property name="persistenceManagerFactory" ref="persistenceManagerFactory"/>
    </bean>

    通过persistenceManagerFactory属性指定需要事务管理的javax.jdo.PersistenceManagerFactory对象。

    c)Jpa事务管理器

    <bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>

    通过entityManagerFactory属性指定需要事务管理的javax.persistence.EntityManagerFactory对象。

    还需要为entityManagerFactory对象指定jpaDialect属性,该属性所对应的对象指定了如何获取连接对象、开启事务、关闭事务等事务管理相关的行为。

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
            ……
            <property name="jpaDialect" ref="jpaDialect"/>
    </bean>
    <bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>

    d)Hibernate事务管理器

    <bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>

    在幕后HibernateTransactionManager将事务管理的职责委托给org.hibernate.Transaction对象,而后者是从Hibernate Session中获取到的。当事务成功完成时,HibernateTransactionManager将会调用Transaction对象的commit()方法来提交事务。同样,事务失败时通过调用Transaction的rollback()方法进行回滚。

    Spring对全局事务的支持:

    a)Jta事务管理器

    <beans xmlns="http://www.springframework.org/schema/beans"

        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:jee="http://www.springframework.org/schema/jee"
        xsi:schemaLocation="
           http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/jee
           http://www.springframework.org/schema/jee/spring-jee-3.0.xsd">
     
      <jee:jndi-lookup id="dataSource" jndi-name="jdbc/test"/>
      <bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager">
        <property name="transactionManagerName" value=" java:comp/TransactionManager"/>
      </bean>
    </beans>
    “dataSource”Bean表示从JNDI中获取的数据源,而txManager是JTA事务管理器,其中属性transactionManagerName指定了JTA事务管理器的JNDI名字,从而将事务管理委托给该事务管理器。
    

    <tx:method/> 有关的设置 

    展开全文
  • 事务隔离性就是指当多个事务同时运行时,各事务之间相互隔离,不可互相干扰。如果事务没有隔离性,就容易出现脏读、不可重复读和幻读等情况。事务概念针对不同的数据库基本同用,只是不同的数据库可能会有不同的...

    基本概念:
    事务的隔离性就是指当多个事务同时运行时,各事务之间相互隔离,不可互相干扰。如果事务没有隔离性,就容易出现脏读、不可重复读和幻读等情况。事务概念针对不同的数据库基本同用,只是不同的数据库可能会有不同的概念,针对不同的数据库区别可能是默认的事务隔离级别不同而已。
    mysql针对数据库事务有如下隔离级别表

    隔离级别脏读不可重复读幻读
    读未提交可能可能可能
    读已提交不可能可能可能
    可重复读不可能不可能可能
    串行化不可能不可能不可能

    注意:上图结构随着你的隔离级别的提高,数据库的效率会随着降低,所以根据我们项目的实际开发需要决定所用数据库,应该选择什么隔离级别。

    事务隔离级别实验:
    实验结果可参照上表。create table transaction(account_name varchar(40),money int),向其中插入数据,insert into transaction (account_name,money) values (‘godRxy’,10000)。查看当前表的具体信息在这里插入图片描述

    查看事务隔离级别select @@transaction_isolation。而我的mysql初始事务隔离级别如下图
    在这里插入图片描述
    由上图可知我的数据库事务隔离级别现在是读未提交。
    mysql中我们开启一个事务流程如下图所示:
    在这里插入图片描述
    注意:当我们启动了数据库事务操作的时候,要么是执行成功,要么是执行不成功,不存在执行一半的情况,也就是begin事务之后,要么commit,要么rollback。
    接下来我们进行实验。
    1.脏读
    (1)begin开启事务
    (2)更新transaction表中的money数据,pdate transaction set money = 15000 where account_name = ‘godRxy’;
    (3)新窗口中重新打开mysql,select * from transaction,这时表中的money应该还是10000,但是实际表中显示数据如下:在这里插入图片描述
    所以这即产生了脏读。解决方法,我们可以事务隔离级别表,升级事务隔离级别即可。
    我们可以针对本次会话重设隔离级别,set session transaction isolation level read committed,或者全局重设隔离级别set global transaction isolation level read committed。(全局:设置全局的事务隔离级别,该设置不会影响当前已经连接的会话,设置完毕后,新打开的会话,将使用新设置的事务隔离级别)。

    2.可重复读
    不可重复读(non-repeatable read),是指一个事务范围内,多次查询某个数据,却得到不同的结果。在第一个事务中的两次读取数据之间,由于第二个事务的修改,第一个事务两次读到的数据可能就是不一样的。
    3.幻读
    幻读(phantom read),是事务非独立执行时发生的一种现象。

    例如事务 T1 对一个表中所有的行的某个数据项做了从“1”修改为“2”的操作,这时事务 T2 又对这个表中插入了一行数据项为“1”的数据,并且提交给数据库。

    而操作事务 T1 的用户如果再查看刚刚修改的数据,会发现数据怎么还是 1?其实这行是从事务 T2 中添加的,就好像产生幻觉一样,这就是发生了幻读。
    参考博客数据库隔离级别

    展开全文
  • 好久没碰数据库了,只是想起自己当时在搞数据库的时候在事务隔离级别这块老是卡,似懂非懂的。现在想把这块整理出来,尽量用最简洁的语言描述出来,供新人参考。 首先创建一个表 account。创建表的过程略过(由于 ...
  • 隔离性(isolation): 事务之间相互不干扰。 持久性(durablility) 事务被提交,则对数据修改时永久性的。 事务状态: 活动(active):事务正在执行中 部分提交(partially committed):数据已提交到内存,

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 230,535
精华内容 92,214
关键字:

事务隔离性

友情链接: code-.rar