解决事务引起的超时和死锁的问题

合集下载

数据库死锁处理方法

数据库死锁处理方法

数据库死锁是指两个或多个事务在同时访问数据库时,因为资源竞争而导致的线程或进程的永久停滞现象。

死锁是数据库管理系统中常见的问题之一,它可能导致数据库系统性能下降或数据丢失。

常见的数据库死锁处理方法如下:
●预防性死锁:避免死锁发生的最佳方法是通过设计数据库系统来预防死锁。

●检测死锁:当死锁发生时,数据库管理系统应该能够检测到死锁并采取适当
的措施来解决问题。

●解除死锁:当死锁发生时,数据库管理系统应该能够找到死锁并采取适当的
措施来解决问题。

●中止事务:如果无法解除死锁,可以考虑中止其中一个或多个事务来解除死
锁。

●使用超时机制:在事务等待超过一定时间后自动中止事务,避免死锁的长时
间占用系统资源。

●使用锁粒度:缩小锁的粒度可以减小互相等待的可能性,减小死锁的发生。

数据库中解决死锁的常用方法

数据库中解决死锁的常用方法

数据库中解决死锁的常用方法在数据库管理系统中,死锁是一种常见但麻烦的问题。

当多个事务同时请求数据库中的资源,并且这些资源被彼此占用,但是又无法相互释放时,就会发生死锁。

死锁的出现可能导致系统性能下降,甚至是数据库崩溃。

因此,解决死锁问题是数据库管理人员需要重视和解决的重要任务。

那么,在数据库中,有哪些常用的方法来解决死锁问题呢?下面将为大家介绍几种常见且有效的死锁解决方法。

第一种方法是通过设置超时时间来解决死锁。

当一个事务请求某个资源时,如果在规定的超时时间内无法获取到该资源,系统就会自动中断这个事务,并回滚所有已经执行的操作。

这种方法虽然简单,但是可能会引起一些业务问题,因为这样做会导致一些事务被中断,可能需要重新执行。

第二种方法是通过死锁检测来解决死锁。

这种方法通常通过算法来检测死锁,并且在检测到死锁时采取一些措施来解决它。

常见的死锁检测算法有银行家算法和图论算法。

这些算法可以在死锁发生时,找到导致死锁的事务,并且选择一个事务进行回滚,从而解除死锁。

但是,这种方法需要消耗系统资源,可能会影响数据库的性能。

第三种方法是通过锁粒度的优化来解决死锁。

将原本被一次性锁住的资源拆分为多个资源,可以降低死锁的概率。

例如,如果一个事务需要修改多个记录,可以将这些记录分开,分别为每个记录加锁。

这样做可以减少死锁的发生,但是也增加了系统的复杂性。

第四种方法是通过加锁顺序的优化来解决死锁。

如果多个事务都会请求相同的资源集合,可以约定一个统一的加锁顺序。

例如,可以规定按照资源的唯一标识符进行加锁,这样不同的事务就会按照相同的顺序加锁,避免了死锁的发生。

这种方法适用于事务之间需要访问多个资源的情况。

第五种方法是通过动态资源分配来解决死锁。

在数据库管理系统中,可以通过动态分配资源的方式来避免死锁。

例如,可以实时监测事务的资源请求情况,并根据当前系统情况来决定是否分配资源。

如果系统资源紧张,可以选择不分配资源,以避免死锁的发生。

数据库事务中死锁的检测与解决技巧

数据库事务中死锁的检测与解决技巧

数据库事务中死锁的检测与解决技巧在数据库管理系统中,事务是一组数据库操作的逻辑单元。

事务能够确保数据库操作的一致性和隔离性。

然而,在多个并发事务同时运行的情况下,可能会出现死锁的问题。

死锁指的是两个或多个事务无限期地等待对方释放资源的状态。

为了保证数据库的正常运行,必须进行死锁的检测和解决。

1. 死锁的检测与诊断死锁的检测是找出系统中存在死锁的事务并诊断其原因。

常用的死锁检测算法包括等待图算法和资源分配图算法。

等待图算法基于图论的理论,它将每个事务视为一个图节点,并根据其对资源的请求与释放建立边。

如果存在一个环,那么系统中就存在死锁。

等待图算法相对简单直观,但在大规模数据库中会降低性能。

资源分配图算法采用资源为节点,边表示资源的请求和释放关系。

通过遍历资源分配图,当发现环路时,就可以确定系统出现了死锁。

资源分配图算法相对来说更加高效,但有时会发生误判。

2. 死锁的解决技巧一旦系统中发现死锁,需要采取相应的措施解决。

以下是一些常用的死锁解决技巧:2.1 死锁超时机制在数据库中,可以设置一个死锁超时时间。

当一个事务等待锁的时间超过预设的阈值时,系统可以主动终止该事务并回滚操作。

然而,死锁超时机制可能会带来性能的下降,因为可能会终止一些本可以成功完成的事务。

2.2 死锁检测与解除这种技巧是在系统中定期检测是否有死锁的存在,一旦发现死锁,就采取相应的解锁方法来解除死锁。

常见的解锁方法包括"死锁分析"和"死锁回滚"。

死锁分析通过interrupt和 release等操作来解除死锁,并继续执行被堵塞的事务。

死锁回滚则是回滚一个或多个事务,以解除锁的冲突。

这两种方法都可以通过数据库日志进行操作记录的回滚操作。

2.3 死锁预防死锁预防是在设计和编写程序时,采取措施避免发生死锁。

一般来说,可以考虑以下几种策略:2.3.1 顺序分配资源通过顺序拍卖资源分配,排除环路的出现,并确保每个事务在进行操作时按照特定的顺序请求资源。

数据库死锁的产生与解决方法

数据库死锁的产生与解决方法

数据库死锁的产生与解决方法数据库作为现代信息系统的核心组成部分之一,承担着存储和管理大量数据的重要任务。

然而,在多用户并发访问数据库时,死锁问题可能会导致系统性能下降甚至崩溃。

本文将探讨数据库死锁的产生原因,以及常用的解决方法。

一、死锁的产生原因1. 互斥访问资源:死锁的产生是因为多个并发事务同时竞争访问同一资源,每个事务都要求独占资源,但资源无法同时满足所有请求,导致事务之间发生资源竞争。

2. 内存不足:当系统内存不足时,数据库管理系统可能会将一些数据和操作转移到虚拟内存中。

如果产生死锁并且没有充足的物理内存来满足事务需求,那么死锁就会发生。

3. 事务持有和等待:当一个事务获取一个资源时,它可能会继续请求其他资源,并在等待其他资源的同时持有已获取的资源。

如果其他事务需要这些已获取的资源,则会产生死锁。

4. 循环等待:多个事务形成环形等待资源的关系,每个事务都在等待下一个事务所持有的资源,导致死锁的产生。

二、死锁解决方法1. 死锁检测与恢复:死锁检测算法可以周期性地扫描系统,定期检查是否存在死锁。

一旦检测到死锁,可以使用死锁恢复算法将死锁事务进行回滚,释放资源,解除死锁状态。

2. 死锁预防:死锁预防方法旨在通过改变系统的策略和规则,防止死锁的发生。

常见的预防方法包括:- 破坏互斥条件:通过将资源设置为可共享而不是互斥性的,可以防止死锁的发生。

- 破坏占有和等待条件:要求一个事务在执行之前获取所有需要的资源,而不是持有部分资源后再去请求其他资源。

- 破坏不可抢占条件:允许系统抢占一些资源,以便在发生死锁时能够打破死锁链。

- 破坏循环等待条件:通过强制事务按照某种统一顺序来请求资源,避免循环等待。

3. 死锁避免:死锁避免方法在事务执行之前对事务进行检测,并根据预测的执行路径来避免潜在的死锁情况。

该方法需要提前获得事务的请求资源信息,以便进行检测和判断是否应该阻止某个事务。

避免死锁的常用算法包括银行家算法和资源分配图算法。

数据库死锁问题分析与解决步骤解读

数据库死锁问题分析与解决步骤解读

数据库死锁问题分析与解决步骤解读当多个并发的事务同时请求数据库中的资源时,可能会发生死锁现象。

数据库死锁是一个常见的问题,它会导致系统性能下降甚至完全停止响应。

因此,有效地解决和预防数据库死锁问题对于保证系统的稳定性和可靠性非常重要。

本文将详细介绍数据库死锁问题的分析与解决步骤。

一、死锁问题的概念与原因1.死锁概念:数据库死锁是指两个或多个事务彼此等待对方释放所占资源,从而无法继续执行下去的情况。

当一个事务锁定了某个资源,并请求另一个事务已经锁定的资源时,就可能发生死锁。

2.死锁原因:死锁通常由以下四个条件引起:(1)互斥:资源必须互斥地分配给事务,即每个资源一次只能由一个事务占用。

(2)持有并等待:一个事务可以持有一个或多个资源,并同时请求另一个已被其他事务所占用的资源。

(3)不可抢占:资源只能由占有者显式地释放,无法被其他事务抢占。

(4)循环等待:多个事务之间存在一个循环等待资源的序列。

二、数据库死锁的解决步骤1.检测死锁:第一步是确认系统中是否存在死锁。

可以使用系统自带的死锁检测工具或者编写自定义的监控程序来检测死锁。

死锁检测工具可以实时地监控系统的资源分配和请求情况,并进行死锁检测。

2.定位死锁:一旦系统检测到死锁,第二步是定位死锁。

通过分析死锁的日志和相关的系统信息,可以确定死锁的事务和资源。

3.解除死锁:一旦死锁被确认并定位,就需要解开死锁。

常用的死锁解除方法包括:(1)资源剥夺法:选择一个或多个事务,并强制终止其占用的资源,直到死锁被解除为止。

这种方法会造成部分事务的回滚以及数据的丢失,因此在使用时需要谨慎。

(2)撤销事务法:选择一个或多个事务,并进行回滚操作,使其释放所占用的资源。

这种方法会导致一部分数据回滚,但相较于资源剥夺法,对于数据的丢失会更少一些。

(3)资源预防法:通过设定适当的资源申请顺序,可以避免死锁的发生。

在编写事务的时候,需要明确指定事务申请资源的顺序,遵循相同的顺序来申请资源可以有效地避免死锁。

有效解决数据库死锁问题的方法与技巧

有效解决数据库死锁问题的方法与技巧

有效解决数据库死锁问题的方法与技巧数据库死锁是数据库管理系统中一种常见的并发控制问题。

当多个事务同时访问数据库中的资源,如果这些事务之间存在互相竞争的关系,可能导致死锁的发生。

死锁会造成事务的阻塞,降低数据库的性能和可用性。

因此,有效解决数据库死锁问题至关重要。

本文将介绍一些方法和技巧,帮助解决数据库死锁问题。

一、死锁的概念和原因在解决数据库死锁问题之前,我们需要了解死锁的概念和产生死锁的原因。

死锁是指两个或多个事务或进程因互相等待后继续执行而导致的循环等待现象。

死锁的产生通常由以下四个条件引起:1. 互斥条件:一个资源同时只能被一个事务所持有。

2. 破坏互斥条件的请求和保持条件:一个事务因请求资源而被阻塞时,不会释放已经持有的资源。

3. 破坏不剥夺条件的不可剥夺条件:已经被一个事务获得的资源不会被强制性地释放,只能由事务自行释放。

4. 破坏环路等待条件的环路等待条件:存在一个等待资源的循环链,从而形成死锁。

二、预防死锁的常用方法预防死锁是解决数据库死锁问题的最好方法。

下面介绍几种常用的预防死锁的方法:1. 加锁顺序:定义一个明确的加锁顺序,要求所有事务按照相同的顺序请求资源。

这样可以避免死锁产生的循环等待条件。

2. 一次性获取所有资源:将事务对多个资源的请求封装为一个原子操作,要求事务在执行前必须获取到所有需要的资源。

这样可以避免死锁产生的保持和等待条件。

3. 超时机制:为每个事务设置一个超时时间,在超时时间内未能成功获取资源的事务将主动释放已经获取的资源,以避免死锁的发生。

三、检测和解决死锁的常用方法即使采取了预防措施,死锁问题仍有可能发生。

下面介绍几种常用的检测和解决死锁的方法:1. 死锁检测:通过周期性地检测系统中是否存在死锁,当检测到死锁时,采取相应的解锁策略。

常用的死锁检测算法有资源分配图算法和银行家算法。

2. 死锁恢复:当检测到死锁时,可以通过解锁某些资源来打破死锁循环。

解锁资源的选择可以采用以下策略:撤销部分事务、回滚事务、选择牺牲代价最小的事务等。

MySQL中的死锁和解锁技巧

MySQL中的死锁和解锁技巧

MySQL中的死锁和解锁技巧MySQL是一种广泛使用的关系型数据库管理系统,许多应用程序和网站都依赖于MySQL来存储和管理数据。

在使用MySQL时,我们经常会遇到死锁的问题,这会导致数据库系统的性能下降甚至是崩溃。

本文将探讨MySQL中的死锁及其解锁技巧,以帮助读者更好地处理这类问题。

一、什么是死锁?死锁是指两个或多个事务在执行过程中,由于争夺资源而导致的一种相互等待的现象。

当多个事务同时持有某个资源,并试图获取对方持有的资源时,如果没有合适的机制来处理这种资源争夺,就会发生死锁。

二、死锁的产生原因1.事务并发执行:当多个事务同时并发执行时,它们会竞争相同的资源,如表、行级锁等。

2.事务中的锁顺序:如果多个事务以不同的顺序获取锁,则可能引发死锁。

3.资源争夺:当事务在操作一个资源时,由于其它事务也要访问相同的资源,就会发生争夺,进而可能导致死锁。

三、如何检测死锁1.查看MySQL的错误日志:死锁发生时,MySQL会将死锁信息写入错误日志文件。

通过查看错误日志,我们可以了解到具体的死锁事务、死锁相关的表和锁信息。

2.使用SHOW INNODB STATUS命令:该命令可以查看当前正在进行的事务、锁定的资源以及死锁信息。

四、死锁的处理方法1.超时设置:在MySQL的配置文件中,可以设置死锁超时时间,当事务等待超过超时时间后,会被自动回滚。

这样可以通过减少死锁时间来减轻死锁的影响。

2.避免死锁发生:在编写应用程序时,可以采用合适的事务隔离级别和锁机制,合理设计SQL语句,避免不必要的死锁。

3.通过监控解决死锁:通过监控系统或工具,可以及时发现死锁,并通过锁信息排查死锁的原因,从而解决死锁问题。

4.手动解锁:当发生死锁后,可以通过手动解锁来解决。

可以通过查看INNODB STATUS命令输出的信息,找到死锁事务的ID,并通过KILL命令终止该事务。

五、经验总结1.事务隔离级别:低隔离级别下,由于锁的范围较小,容易出现死锁;而高隔离级别下,锁的范围较大,减少了死锁的发生几率。

数据库死锁的分析与解决方法

数据库死锁的分析与解决方法

数据库死锁的分析与解决方法引言数据库是现代信息系统中不可或缺的组成部分,它的作用是存储和管理大量的数据,为各种业务提供支持。

然而,在多用户并发访问数据库的情况下,由于资源竞争产生的死锁问题时有发生。

本文将对数据库死锁的原因进行分析,并介绍一些解决死锁问题的方法。

一、死锁的原因1.1资源竞争数据库中的操作需要访问共享资源,如表、索引、缓存等。

多个事务在并发执行时,可能会出现对同一资源的竞争,从而导致死锁的发生。

1.2事务同时进行读写操作在数据库中,事务由一组操作组成,包括读取和修改数据。

当多个事务同时进行读写操作时,如果彼此之间存在依赖关系,就可能导致死锁的产生。

1.3锁的粒度过大锁的粒度是指锁定资源的程度。

如果锁的粒度过大,那么并发访问数据库的能力就会受到限制,容易引发死锁。

1.4事务执行顺序导致循环等待如果多个事务的执行顺序使得它们形成循环等待的关系,那么就会发生死锁。

每个事务都在等待其他事务释放资源,从而形成僵持状态。

二、死锁的影响2.1系统性能下降死锁会导致系统性能下降,因为资源被无效占用,其他事务无法正常执行,从而耗费系统资源。

2.2事务阻塞当死锁发生时,系统将不得不暂停其中一个事务,待死锁解除后再恢复执行。

这会导致事务的阻塞,影响了业务的正常进行。

三、解决死锁的方法3.1二段锁协议二段锁协议是一种常见的死锁预防方法。

在这种协议中,事务分为两个阶段:加锁(Growing)和释放锁(Shrinking)。

该协议要求事务在读取数据之前先加共享锁,在修改数据之前先加排他锁,在事务结束时释放所有锁。

通过严格的锁序和顺序释放锁,可以预防死锁的发生。

3.2超时机制超时机制是通过设置超时时间来解锁被占用的资源。

如果一个事务在超过一定时间后仍然无法获取所需的资源,那么系统将主动中断该事务并释放已经占用的资源。

通过这种方式,可以防止长时间的死锁情况发生。

3.3死锁检测与解除死锁检测是一种常见的死锁解决方法。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

--B 使用快照隔离 --此示例中,在快照隔离下运行的事务将读取数据,然后由另一个事务修改此数据。快照事 务 --不阻塞由其他事务执行的更新操作,他忽略数据的修改继续从版本化的行读取数据。也就 是 --说,读取到的是数据修改前的版本。但是,当快照事务尝试修改已由其他事务修改的数据 时, --他将生成错误并终止 --在会话 1 上: USE[AdventureWorks] GO --启用快照隔离 ALTERDATABASE[AdventureWorks]SET ALLOW_SNAPSHOT_ISOLATION ON GO --设置使用快照隔离级别 SETTRANSACTION ISOLATION LEVEL SNAPSHOT GO BEGINTRAN --查询 1 --查询返回员工有 48 小时假期 SELECT[EmployeeID],[VacationHours]FROM[HumanResources].[Employee]WHERE[Employe eID]=4 ----------------------------------------------------------------------------------------------在会话 2 上: USE[AdventureWorks] GO BEGINTRAN --修改 1 --假期时间减 8 --修改不会被会话 1 阻塞 UPDATE[HumanResources].[Employee]
解决事务引起的超时和死锁的问题
SQL 有两种行版本控制: --(1)行版本控制的已提交读隔离(read_committed_snapshot) --(2)直接使用 snapshot 事务隔离级别 --(1)(read_committed_snapshot):read_committed_snapshot 数据库选项为 ON 时, read_committed 事务通过使用行 --版本控制提供语句级读取一致性 --(2)(snapshot tion 数据库选项为 ON 时,snapshot 事务通过使用行版本 --控制提供事务级读取一致性
----------------------------------------------------------------------------------------------
--C 使用行版本控制的已提交读 --在此示例中,使用行版本控制的已提交读事务与其他事务并发运行。已提交读事务的行为 与快照事务的行为 --有所不同。与快照事务相同的是,即使其他事务修改了数据,已提交读事务也将读取版本 化的行。 --与快照事务不同的是,已提交读将执行下列操作: --(1)在其他事务提交数据更改之后,读取修改的数据 --(2)能够更新由其他事务修改的数据,而快照事务不能 --在会话 1 上: USE[AdventureWorks] GO --启用行版本控制的已提交读 --注意运行这句话的时候,不可以有其他连接同时使用[AdventureWorks] ALTERDATABASE[AdventureWorks]SET READ_COMMITTED_SNAPSHOT ON GO --设置使用已提交读隔离级别 SETTRANSACTION ISOLATION LEVEL READ COMMITTED GO BEGINTRAN --查询 1 --这里将返回初始值 48 SELECT[EmployeeID],[VacationHours]FROM[HumanResources].[Employee]WHERE[Employe eID]=4 -----------------------------------------------------------------------------------------------------在会话 2 上: USE[AdventureWorks] GO BEGINTRAN --修改 1 --假期时间减 8 --修改不会被会话 1 阻塞 UPDATE[HumanResources].[Employee]
--下列示例可以说明使用普通已提交读事务,行版本控制的快照隔离事务和行版本 --控制的已提交读事务的行为差异 --示例: --A 普通已提交事务 --在此示例中,一个普通 read committed 事务将读取数据,然后由另一事务修改此数据。执 行 --完的读操作不阻塞由其他事务执行的更新操作。但是,在其他事务已经做了更新操作后, 读 --操作会被阻塞住,直到更新操作事务提交为止 --在会话 1 上: USE[AdventureWorks] GO BEGINTRAN --查询 1 --这个查询将返回员工有 48 小时休假时间 SELECT[EmployeeID],[VacationHours]FROM[HumanResources].[Employee]WHERE[Employe eID]=4 ------------------------------------------------------------------------------------------------在会话 2 上: USE[AdventureWorks] GO BEGINTRAN --修改 1 --休假时间减去 8
SET[VacationHours]=[VacationHours]-8 WHERE[EmployeeID]=4 --查询 1 --确认值已经被修改为 40 SELECT[VacationHours]FROM[HumanResources].[Employee]WHERE[EmployeeID]=4 -------------------------------------------------------------------------------------------------在会话 1 上: --查询 2 --再次运行查询语句 --还是返回 48(修改前的值),因为会话 2 还没有提交 --会话 1 是从版本化的行读取数据 SELECT[EmployeeID],[VacationHours]FROM[HumanResources].[Employee]WHERE[Employe eID]=4 --------------------------------------------------------------------------------------------------在会话 2 上: --提交事务 COMMITTRAN GO ---------------------------------------------------------------------------------------------------在会话 1 上: --查询 3 --这里和范例 B 不同,会话 1 始终返回已提交的值 --这里返回 40,因为会话 2 已经提交了事务 SELECT[EmployeeID],[VacationHours]FROM[HumanResources].[Employee]WHERE[Employe eID]=4 --修改 2 --这里会成功 UPDATE[HumanResources].[Employee] SET[SickLeaveHours]=[SickLeaveHours]-8 WHERE[EmployeeID]=4 --可以回滚会话 1 的修改 --会话 2 的修改不会受影响 ROLLBACKTRAN GO
--在会话 1 上: --重新运行查询语句,会被会话 2 阻塞 --查询 2 SELECT[EmployeeID],[VacationHours]FROM[HumanResources].[Employee]WHERE[Employe eID]=4 ------------------------------------------------------------------------------------------------在会话 2 上: --提交事务 COMMITTRAN GO ------------------------------------------------------------------------------------------------在会话 1 上: --此时先前被阻塞的查询结束,返回会话 2 修改好的新数据:40 --查询 3 --这里返回 40,因为会话 2 已经提交了事务 SELECT[EmployeeID],[VacationHours]FROM[HumanResources].[Employee]WHERE[Employe eID]=4 --修改 2 --这里会成功 UPDATE[HumanResources].[Employee] SET[SickLeaveHours]=[SickLeaveHours]-8 WHERE[EmployeeID]=4 SELECT[SickLeaveHours]FROM[HumanResources].[Employee]WHERE[EmployeeID]=4 --可以回滚会话 1 的修改 --会话 2 的修改不会受影响
--修改不会被阻塞,因为会话 1 不会持有 S 锁不放 UPDATE[HumanResources].[Employee] SET[VacationHours]=[VacationHours]-8 WHERE[EmployeeID]=4 --查询 1 --现在休假时间只有 40 小时 SELECT[VacationHours]FROM[HumanResources].[Employee]WHERE[EmployeeID]=4 --------------------------------------------------------------------------------------------------
SET[VacationHours]=[VacationHours]-8 WHERE[EmployeeID]=4 --查询 1 --确认值已经被改成 40 SELECT[VacationHours]FROM[HumanResources].[Employee]WHERE[EmployeeID]=4 ------------------------------------------------------------------------------------------------在会话 1 上: --查询 2 --再次运行查询语句 --还是返回 48(修改前的值),因为会话 1 是从版本化的行读取数据 SELECT[EmployeeID],[VacationHours]FROM[HumanResources].[Employee]WHERE[Employe eID]=4 -------------------------------------------------------------------------------------------------在会话 2 上: --提交事务 COMMITTRAN GO --------------------------------------------------------------------------------------------------在会话 1 上: --查询 3 --再次运行查询语句 --还是返回 48(修改前的值),因为会话 1 还是从版本化的行读取数据 SELECT[EmployeeID],[VacationHours]FROM[HumanResources].[Employee]WHERE[Employe eID]=4 --修改 2 --因为数据已经被会话 2 修改过,会话 1 想做任何修改时 --会遇到 3960 错误 --事务会自动回滚 UPDATE[HumanResources].[Employee] SET[SickLeaveHours]=[SickLeaveHours]-8 WHERE[EmployeeID]=4 --会话 1 的修改会回滚 --会话 2 的修改不会回滚 ROLLBACKTRAN GO
相关文档
最新文档