Transaction 1 |学习笔记

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 快速学习 Transaction 1

开发者学堂课程【高校精品课-上海交通大学-企业级应用体系架构:Transaction 1 】学习笔记,与课程紧密联系,让用户快速学习知识。

课程地址:https://developer.aliyun.com/learning/course/75/detail/15831


Transaction 1

 

内容介绍

Transactions in Java EE Applications

What Is a Transaction?

Container-Managed Transactions

Transaction Timeouts

Bean-Managed Transactions

 

一、Transactions in Java EE Applications

What Is a Transaction?

Container-Managed Transactions

Bean-Managed Transactions

Transaction Timeouts

Isolation and Database Locking

Updating Multiple Databases

在 Java 程序中如何管理事务管理事务是一种声明式也就是想告诉容器也就是像 Transactions  服务器应用配置的容器如何管理,还有一种是硬编码前一种方式会更实用Container-Managed Transactions Bean-Managed Transactions 事务的边界就是从什么时候开始到什么时候结束多个事务并行执行的时候数据库是怎么做隔离的彼此之间不会因为并行的去操作,数据库导致数据混乱当要操作多个数据库的时候它是怎么实现事务管理,就是所谓的分布式事务是怎么来实现的

1、In a Java EE application, a transaction

is a series of actions that must all complete successfully, or else all the changes in each action are backed out. Transactions end in either a commit or a rollback.

2、The Java Transaction API (JTA) allows applications

to access transactions in a manner that is independent of specific implementations

3、The JTA defines the UserTransaction interface that

applications use to start, commit, or roll back transactions.

Application components get a UserTransaction object through a JNDI lookup by using the name java : comp/UserTransaction or by requesting injection of a UserTransaction object.

java 的事务管理体系里面提供 jta 的规范,有各种各样的实现比如 java 自身,它会有相应的包去实践它jboss提供事务的实现如果用 spring 可以看到 spring 里面也有事务的实现jta 的作用就是在把各家不同的事务实现规范化,对着统一的 api 进行编程就可以对事务进行管理如果要编程管理事务的边界就要用到 UserTransaction 的接口接口也在 jndi 在应用服务器里面绑定某位置上按位置查找就能找到这一个接口的实践类比如 spring 的实现类spring 启动的时候就可以找到它,它进行管理这是 java 中提供的规范

 

二、What Is a Transaction?

1、Pseudocode:

begin transaction

debit checking account

credit savings account

Update history log

commit transaction

2、A transaction is often defined as an indivisible unit of work

Either all or none of the three steps must complete.

3、A transaction can end in two ways:

with a commit or with a rollback.

事务在数据库里面当对数据库进行操作的时候事务的意思是

操作可能包含多步骤在某地方确定开始事务到某个地方提交事务有可能事务失败需要回滚从begin到credit 中间的操作被定义成事务,特点是要么都做,要么都不做如果事务执行第一步成功,第二步成功第三步失败会把前两步成功的动作进行回滚,也就是把它恢复成在 begin 之前的状态一二三都执行,都不执行事情本身比较简单要看是不是只有数据库支持动作jms消息中间件消息属性里面有 groupid,表示消息属于哪一组在这一组里面的id它关联的下一组的 id 是什么这一组消息要么接收,要么都不接收,消息中间件里面有邮箱邮箱会把消息写到硬盘上quenu 会把消息写到硬盘上当用户读消息时候,这一组消息有五条把五条都读消息就算是被读走整个被从硬盘上删除如果只读走两个在读第三个的时候消息还没有读成功那么会尝试把三消息再转发,如果还是不成功把一二消息标记成未接收会让接收者要么五条都接收,要么五条都不接收,jms 连接工厂本身像数据库一样可以实现群发群收,也就是一组操作要么都执行,要么都不执行所以事务不只是发生在数据库上理论上发生在 resourece manage 资源管理器资源管理数据库是一种交易中间件是一种邮件服务器邮件的群发和群收一样的道理也是事务可以支持资源管理器只要是资源管理器,都有事务的能力都可以做群发群收类似要么都做,要么都不做所以一定要注意事务管理不是只有数据库还有其东西至少应该知道有消息服务器和邮件服务器都属于事务,资源管理器都支持事务的资源管理器利用内存它有很大的缓存当执行事务的时候,会把事务的结果写到缓存里当提交的时候就要看一下当前在内存里事情能不能提交真正写入到数据库或者消息中间件里面就是把它状态更新掉也就是把硬盘里面实际的状态关掉如果可以就做如果不行比如有些操作没有执行化没有明确的告诉事务要提交不管什么原因就是因为整个事务没有成功只要把内存里缓存的中间状态删掉就可以数据库里或者在消息中间的硬盘上最终存储的还是在事务执行之前的状态只要靠内存就可以所以没有什么特别神奇的地方为什么能管理事务就是靠大量的内存做缓存实现引申出附加的问题tomcatoracle定义的事务tomcat 里有变量 A注意事务从 commit 开始 a++,第二步把 oracle 的数据库比如里面的某一个账户钱减少一点第三步把另外账户加一点做转账操作a是程序里在记录到底执行过多少次转账操作事务提交掉第一步成功,第二步成功,第三步失败其中第一步和第二步发生在 oracle 数据库里,失败直接释放缓存数据库里存的仍然是原来的钱a能回来吗a的状态要自己去维护二三发生在数据库里a 是在 tomcat 里自己的程序里数据库没有办法直接把a恢复到a++之前的状态要靠自己引申出问题事务发生要让它回滚的时候可以告诉事务的资源管理器要回无论是数据操作放弃掉还是消息全部接收都是受事务型资源管理器控制的它可以做但是如果在事务当中涉及到对自己程序管理里面是自己控制的变量的操作要想回滚就必须要自己管理靠数据库回滚不了的这是引申出来的第三个问题

 

三、Container-Managed Transactions

In an enterprise bean with container-managed transaction

demarcation,

the EJB container sets the boundaries of the transactions.

事务需要有划分边界事务有四个特性 acida 是原子的操作,如果涉及到多条,要么都执行,要么都不执行不可能一部分执行,另外一部分没有执行原子操作本身对应什么要知道事务的边界从哪里开始原子操作操作一二三,三个动作从什么时候开始到什么时候结束,中间的操作都定义成事务里面的原子操作一致性因为有连续性,三个动作,比如要把账户减一,第二动作是减二三个动作是减三是把 n 个动作全部执行完之后如果能提交,就把它持久化到硬盘上,但是现在如果在数据约束上有要求账户里面的余额必须要大于等于一就是必须有一块钱如果余额有十块钱一个动作要减五块,第二动作减五块,第三个动作减五如果定义在一个事务里,先把它缓存,最后再提交到硬盘上把三个全部都执行一遍余额就会变成负不允许发生在数据上的约束,无论事务有多长,有多少条语句,最后执行完数据上的约束要一致所以三个操作必然有一个要失败大于等于零,所以减掉五还剩五在减掉第二个五的时候已经不能讲所以一致性是不管在事务里执行多少个操作,中间的状态,怎么去变化最终提交要满足数据约束不可能因为在缓存,然后一次性提交,变成负隔离性是如果要做转账操作现在银行里的余额是十块钱A来执行转账操作,给余额加五块b也做转账操作,要加五块那么加完之后余额是20各转五块但现在如果不做事务的隔离就会变成想转账的时候读余额是十块,因为它俩并行操作把钱加五块,那就变成15b加五块也是15a写回来写个10,ab执行两次转账操作,但实际上最后数据库里出现15这就是因为事务之间没有隔离所以隔离在病发的时候怎么让事务互相之间,不要干扰如果是执行两个,就要把两个效果都能体现出来B是持久性在缓存里执行当提交时,存储到硬盘上不会因为事务的原因,事务最后提交,但是了一会发现钱又回到十块不会出现这种状态最重要的就是要划分事务边界唯一能控制的事务的一致性是靠资源管理器,也就是数据库保证不会允许在数据上已经加过限制,余额大于一的情况下余额,隔离性告诉数据库,希望如何隔离持久性是数据库自带的一种属性当写进去之后,它一定会写入到硬盘上无论是数据库还是消息中间件还是其的东西自己可以带出去四个合到一起,事务的属性,a 和 i 是可以控制控制事务的边界这就所谓的事务边界去划分原子性操作的意义现在写两个代码果在第二个 bean 里面有方法叫做B X在定义里面有X叫做 method-a,method-a 在执行操作的时候系统开了一个事务是tx1,

method-A() {

bean-2. method-B ( )

}

整个事务tx1,整个 method-A tx1里面去执行调用 method-b,method-b在 tx1执行加入 tx1,是tx1的一部分声明式的事务属性管理会告诉未必允许更灵活的方式来执行可以让 method-b不一定非要在 tx1里,还可以其的选择

 

四、Transaction Timeouts

1、NotSupported

Invoking a method on an EJB with this transaction attribute suspends the transaction until the method is completed.

Transactional 里面可以写属性属性有六种不是spring自己定义的是 java 事务 api 里面定义的六种不同的属性决定方法 b 是不是在 tx1执行还是在其事务执行按照字母排序并不是按常用性排序NotSupported每个方法都会有事务属性先忽略 method a因为已经开个tx1,在方法前面加 Transactional属性是什么如果NotSupported,执行到这里方法不支持事务,所以把事务挂起在非事务的状态下执行当前的方法执行完之后再把原来的挂起,继续执行现在在tx1里面在执行事务执行因为是 NotSupported,所以会把tx1挂起然后method-b就会在没有任何事务的情况执行执行完之后把tx1恢复出来所以在这种情况下 method-a 里面一直到调用b之前的代码以及调用完b之后的代码都属于事务,但B是在非事务的状态下去执行的它既没有加入到 tx1也本身没有在任何处理执行,所以如果tx1要回滚回到tx1所有操作状态,但是B本身操作不会被忽略而因为B是在没有任何事务状态下执行,所以B如果失败不影响tx1,B如果失败,执行操作失败b记日志失败如果tx1其它操作都成功tx1的操作还是会被提交b不会加入到tx1里面

假如操作是在做转账操作把钱从a账户里面扣掉加到b的账户里面存进去在中间想做记日志的操作到本地的硬盘上写 log 文件发现本地的硬盘使用年限比较久它的性能不是很好容易出错转账本身是成功的只是记日志不成功要不要让整个事务回滚如果从提高用户可用性的角度不要回在这种情况下,日志能记就记日志记不记成功对于整个事务要不要提交不产生任何影响但是日志必须在这记,也就是a只要把钱取出来,必须记日志只是是否记成功都无所谓,能记就记,把 method-b设置成 NotSupported

它不影响 tx1的提交tx1成功与否与 B 成功与否没有任何关系而且B本身它在非事务状态下执行,所以它也不存在回滚不会因为记不上问题,还要把已经记的抹掉

2、Supports

This attribute means that the enterprise bean method will be included in the transaction scope if it is invoked within a transaction.

把 a 的钱扔掉,取出来调用 B把钱加到 B 的上代码仍然这么么写功能也是一样,它在记日志如果转账操作成功日志就一定要记成功只要有事务,成功就一定要记成功如果失败不记但是如果不管要不要回滚在没有事务的状态下去执行转账操作钱已经被扣但是存进去之后失败,也不需要回滚认为这件事无所谓是否人工调行,b在没有事务的状态下去执行成功就成功失败失败不是失败就不如果条件这样,那么事务属性就是 supports作用就是如果定义tx1,那 B 就是成为tx1的一部分如果转账,记日志失败回去因为转账成功,一定要把日志记上如果日志记不上,将来对账对不上,要把转账操作恢复回去所以B就会成为tx1一部分如果在某一次操作的时候没有开任何的事务,直接调用A认为这是非关键的操作在非事务的状态下执行,成功成功失败就失败不考虑回稳或者提交的动作用的是supports代码本身没有发生任何变化只是在 Transactional里换属性而已如果有事务就加入事务,如果没事务,就在非事务状态下,会拍事务,一定要在事务下记日志

3、Required

This attribute means that the enterprise bean method must be invoked within the

scope of a transaction.

如果之前的代码没有加Transaction因为不加默认就是 required一定要在事务执行上半部跟 supports是一样的如果操作在 tx1执行B 会加入到 tx1它会成为 tx1的一部分如果操作没有失误B 在 require 模式里面B 一定会自己先开事务,在事务里执行自己的逻辑小 a 和小 B 代码会合到一起执行,在非事务的状态下执行如果日志记错,会回,但是回滚不影响a和ba 和 b本身不存在回提交执行完直接持久化问题能得到简化a 方法有属性在执行第一条代码之后就开启事务 tx1,当时第二条,第三条,第四条,第五条是调用 require 的时候,B 自动加入到 tx1继续执行可以保证所有的方法在事务执行但是不跟事务合成一个事务,AB 操作,然后 b无论如何新事务执行,都不会加入到 a 和 B 里面所以 B 会在新开的 tx2事务执行ab 会合成事务或者在非事务状态下执行不管哪一种执行完B 操作记日志操作一定在单独的日志里面操作比如日志一定要写成功,要写三条谁登陆进来a减多少钱加到 B日志操作在写文件或者写数据库,反正是写日志写日志操作必须要么都写成,要么都不写但无论怎么样,成功与否不影响转账这件事情转账可以回滚,或者提交,写日志互相之间不干扰

4、Mandatory

This attribute means that the enterprise bean method must always be made part of the transaction scope of the calling client.

强制要求必须有事务否则报错如果有事务加上事务,如果没有就报错

5、Never

This attribute means that the enterprise bean method must not be invoked within the scope of a transaction.

强制没有事务在非事务状态下执行,就加入非事务状态如果有事务直接报错代码都是一样的执行完小a执行大B执行小b代码没有做任何修改但是赋予a和b不同的事务属性后,就会有不同的效果

Transaction Attribute

Client's Transaction

Business Method's Transaction

Required

=【】  

T2

Required

T1

T1

RequiresNew

None

T2

RequiresNew

T1

T2

Mandatory

None

Error

Mandatory

T1

T1

NotSupported

None

None

NotSupported

T1

None

Supports

None

None

Supports

T1

T1

Never

None

None

Never

T1

Error

转账操作由两个方法构成的wichdowdepositTransfer 和 wichdow 合到一起处境一样Transfer上面没有任何事务,deposit 会在什么情况下执行tomcat 获取事务管理器的逻辑它执行到 Transfer 事务属性是什么none要在非事务的状态下进行执行required 必须在事务下执行所以现在当前没有事务所以Transfer会一个事务,在T1下面执行,Transferwichdowdeposit假设全是 Require过来之后,现在没有事务,Transfer新开一个事务事务是t1,进去执行 wichdow当前执行线程上已经有t1事务Require 必须在事务里执行如果有加入进去因为现在线上已经有新事务,加入到里面wichdow 执行完的时候每个方法上面都写事务属性,所以每个方法结束完之后都会去检查一下方法只要 return 就检查一下required 事务是该提交还是回wichdow是执行完,T1是加入进来的不是在这里开的所以 tomcat 不会提交或者回滚,它继续往下执行执行到depositdeposit 同样道理,会加入到t1,执行完之后,每当执行一个方法,方法返回的时候,tomcat都会做检查deposit 执行完之后 Tomcat 看再做一次检查发现T1事务不是 deposit 开的从这里 begin所以也不做提动作,transfer 执行完之后再次检查发现T1事务就是 transfer 开的所以现在都正常执行完就提交掉在提交掉之后T1结束于是 wichdow 和 deposit 转账操作都在 T1事务里执行,都是 required,假设 wichdow transfer都是requireddeposit 是 requiresdnewtransfer 开t1,t1执行到 wichdowwichdow 也是 required加入到t1里面wichdow 执行完之后,尝试提交事务发现提交不因为t1不是开的所以继续往下执行,执行到 deposit按照 requiresdnew 逻辑当前如果有事务,就把事务挂起然后在新事务里执行当前的方法执行完之后,把事务恢复变成把t1挂起新开一个事务比如t2,deposit结束就要看t2要不要提交t2确实在 deposit 地方所以t2被提交掉t1被恢复出来再尝试t1要不要提交发现T1不是 deposit 开启,所以T1没有被提交transfer 结束再尝试t1要不要提交,因为现在线程关联的是 t1,发现 t1确实是 transfer 开启的所以T1提交掉Transfer 和wichdow在T1deposit在 T2如果想回假如t1回滚操作回滚不了T2想回滚单独回滚,在执行自己的时候可以单独回滚,但是回滚不回滚都对 T1不造成影响同样的代码,没做任何其的修改,只改上面的属性标签变成两个事务提交按照不同的事务属性进行不同的设置的时候,tomcat 会实现事务边界的不同的划分可能在一个事务里,可能在两个事务也可能直接报错代码没有做任何修改,靠 errorsession 不同的值告诉 tomcat 怎么管理事务,声明式的划分事务边界好处是比较简单代码不用做大量的修改缺点是力度到方法几wichdow 里面还有三个动作进一步做控制,做不到除非把三个动作再封装成不同的方法这种方式会比较简单声明式也叫容器管理,就是完全靠tomcat 管理,没有明显的通过自己的代码在哪里开始到哪里结束

Transaction attributes are specified by

decorating the enterprise bean class or method with

a javax. ejb. TransactionAttribute annotation

and setting it to one of the javax. ejb. TransactionAttributeType constants.

Transaction Attribute

TransactionAttributeType Constant

Required

TransactionAttribute Type.REQUIRED

RequiresNew

TransactionAttributeType.REQUIRES_ NEW

Mandatory

TransactionAttribute Type.MANDATORY

NotSupported

TransactionAttribute Type.NOT_ SUPPORTED

Supports

TransactionAttribute Type.SUPPORTS

Never

TransactionAttribute Type.NEVER

六个事务属性对应的就是看到全程不是 spring 的代码是 java 包里面定义的东西

The following code snippet demonstrates how to use

the @Trans actionAttribute annotation:

@TransactionAttribute (NOT_ SUPPORTED)

@Stateful

public class TransactionBean implements Transaction {

@TransactionAttribute(REQUIRES_ NEW)

public void firstMethod() {...}

@TransactionAttribute ( REQUIRED)

public void secondMethod() {...}

public void thirdMethod() {...}

public void fourthMethod() {...}

}

有的是用 spring名字叫 transaction,内容写里面例子类似的类接口里面的名字,六种当中的一种在定义的时候,对于类,可以定义类里所有的方法都用属性如果有些方法特殊,可以在方法上面特别的重载一下声明式的事务边界

Rolling Back a CMT

There are two ways to roll back a container-managed

transaction.

First, if a system exception is thrown, the container will automatically roll back the transaction.

Second, by invoking the setRollbackOnly method of

the EJBContext interface, the bean method instructs the container to

roll back the transaction.

If the bean throws an application exception, the rollback is not automatic

but can be initiated by a call to setRollbackOnly.

有时候可以提交,但有时候要回滚当碰到某一个事务,在执行的过程中,可能碰到某种异常应该把事务设置成只能回滚事务不能被正常提交在自己的代码里做 a++动作,再去执行数据库操作个定义成事务,后面一部分可以靠数据库在缓存里面搞定如果想要让容器做这样的动作,服务类实现接口,接口里有三个方法afterbegin事务开始之后用暂存的变量去存当前变量的值,afterCompletion 事务完成之后参数表示当前事务是如果失败了就把值恢复成缓存的时候自己的程序里面维护的变量加入到事务以后也能够有回滚的效果spring里面的实现不一样,但是基本道理是一样,在 java 企业版里面讲标准的实验方法,事务的实现复杂就是数据库里面开一块很大的缓存所有的操作都在缓存里,回滚的时候就把缓存里释放掉当提交的时候写入到数据库里,让其它人能看到就可以对于自己程序里面的一些变量的处理数据库管不到tomcat 会主动帮管需要自己处理,无论是tomcat 还是 deposit 应用服务器,也不知道定义的哪些变量希望回滚所以只开放接口让自己去想要不要回滚

 

五、Bean-Managed Transactions

In bean-managed transaction demarcation,

the code in the session or message-driven bean explicitly marks

the boundaries of the transaction.

Pseudocode:

begin transaction

update table-a

if ( condition-x)

commit transaction

else if (condition-y)

update table-b

commit transaction

else rollback transaction

begin transaction

update table-c

commit transaction

如果想做更细力度的控制怎么办自己去定义什么时候开始 transaction 什么时候提交每次都是在session上面定义transaction编程式的实现就是自己实现,自己人为实现事务边界的划分不推荐这种方式,因为这种方式写代码写的很烦,而且不灵活就以数据库为例要开大量缓存,把执行的中间结果都写在这里而且事务在进行操作的时候,通常在数据库里面,如果是一张表可能在上面要加锁占资源本身是个资源,事务不能让无休止的执行下去如果无休止执行下去,系统的性能会非常差所以在事务上可以设置 timeout强制要求在程序里面执行的事务在执行多长时间之后就一定要结束至于 timeout  之后是让它回滚还是提交,但是必须要设计timeout防止有些程序恶意的占用数据库的事务只能在给定时间内执行超过就全给剥夺掉访问数据库表表里面数据量很大执行的时间会非常长设置超时总是超时超时要根据估算去设置不能随便设置执行时间很长的事务叫做长事务控制逻辑不是现在这样不能加锁不能直接在这里回滚,或者提交

要用一种事后补偿的机制去执行直接写进数据库如果失败会标记事务失败,标记是否要执行一次补偿机制这是应对事务手段尽量避免长事务如果真碰到事务不要靠锁的机制去实现甚至不要定义事务,应该事后去做补偿事后去做补偿减少加锁的时间尽量减少占内存的空间只是事后发现执行不正常,到一步不正常的时候想办法做补偿所以这是在设计时候要去考虑的问

Managing Transactions in Spring

@Transactional propagation

事务传播行为

说明

@Transactional(propagation=Propagation.REQUIRED)

如果有事务,那么加入事务,没有的话新建一个(默认情况)

@Transactional(propagation=Propagation.NOT_ SUPPORTED)

容器不为这个方法开启事务

@Transactional(propagation= Propagation.REQUIRES_ NEW)

不管是否存在事务,都创建一个新的事务,原来的挂起,新的执行完毕,继续执行老的事务

@Transactional(propagation=Propagation.MANDATORY)

必须在一个已有的事务中执行,否则抛出异常

@Transactional(propagation=Propagation.NEVER)

必须在一个没有的事务中执行,否则抛出异常(与Propagation.MANDATORY相反)

@Transactional(propagation=Propagation.SUPPORTS)

如果其他bean调用这个方法,在其他bean中声明事务,那就

用事务。如果其他bean没有声明事务,那就不用事务

事务传播属性transfer 在t1wichdow 在t1里面transfer 把事务传播给 wichdowwichdow传播给deposit一样表达在 spring 里面只是标签不一样写法不一样意思都是一模一样在执行的时候之前没有做任何的设计是因为不需要定义的时候

默认的就是用的 require也可以去写,不写默认是 require在 book service 里面执行方法require类型的生命词事务,执行底下 update 操作的时候,一定会在事务执行这件事情要么成功,要么回不会插入到一半的时候两个属性进去,第三个属性没进去失败写进去不完整的记录不会出现这种情况spring的操作

BookingService.java

@Component

public class BookingService {

private final static Logger logger = LoggerFactory.getLogger(BookingService.clas);

private final JdbcTemplate jdbcTemplate;

public BookingService (JdbcTemplate jdbcTemplate) {

this.jdbcTemplate = jdbcTemplate;

}

@Transactional

public void book (String... persons) {

for (String person : persons) {

logger.info("Booking " + person+ " in a set...");

jdbcTemplate.update("insert into BOOKINGS(FIRST_ NAME) values (?)", person);

}

}

public List<String> findAllBookings() {

return jdbcTemplate.query("select FIRST_ NAME from BOOKINGS",

(rs, rowNum) -> rs.getString("FIRST_NAME"));

}}

相关文章
|
6月前
|
SQL 关系型数据库 MySQL
十四、事务Transaction
十四、事务Transaction
68 0
|
5月前
|
Go
【已解决】SendTransactionVM Exception while processing transaction: Transaction‘s maxFeePerGas (200000000
【已解决】SendTransactionVM Exception while processing transaction: Transaction‘s maxFeePerGas (200000000
35 0
|
4月前
|
算法 关系型数据库 MySQL
transaction
【7月更文挑战第21天】
52 7
|
12月前
|
Java 关系型数据库 MySQL
定时任务Quzrtz:Failed to override connection auto commit/transaction isolation
定时任务Quzrtz:Failed to override connection auto commit/transaction isolation
116 0
|
SQL 缓存 安全
Transaction 2 |学习笔记
快速学习 Transaction 2
135 0
Transaction 2 |学习笔记
|
设计模式 Java 数据库连接
Transaction接口|学习笔记
快速学习Transaction接口
191 0
Transaction接口|学习笔记
|
SQL 存储 安全
MySQL数据库(27):事务安全 transaction
MySQL数据库(27):事务安全 transaction
141 0
|
Python
sqlalchemy报错Please use '@@transaction_isolation' instead")
sqlalchemy报错Please use '@@transaction_isolation' instead")
141 0
|
Java Spring
【小家java】Spring事务嵌套引发的血案---Transaction rolled back because it has been marked as rollback-only(下)
【小家java】Spring事务嵌套引发的血案---Transaction rolled back because it has been marked as rollback-only(下)
【小家java】Spring事务嵌套引发的血案---Transaction rolled back because it has been marked as rollback-only(下)