当前位置: 首页 > 知识库问答 >
问题:

在READ COMMITTED隔离级别中何时/什么锁被保持/释放

空慈
2023-03-14

我正在尝试了解SQL Server中的隔离/锁定。

我在读提交隔离级别(默认)中有以下场景

我们有一张桌子。

create table Transactions(Tid int,amt int)

with some records

insert into Transactions values(1, 100)
insert into Transactions values(2, -50)
insert into Transactions values(3, 100)
insert into Transactions values(4, -100)
insert into Transactions values(5, 200)

现在从msdn我明白了

当激发select时,将使用共享锁,因此其他事务无法修改数据(避免脏读)..文档还谈到了行级、页级、表级锁。我想跟着场景走

Begin Transaction

select * from Transactions

/*
some buisness logic which takes 5 minutes

*/

Commit

我想了解的是将获取共享锁的持续时间以及哪个(行、页、表)。

将仅在运行事务中的语句选择 * 时获取锁定,或者会获取整整 5 分钟,直到我们到达 COMMIT。

共有3个答案

敖永丰
2023-03-14

仅当运行从事务中选择 * 时,锁才会获取

您可以使用以下代码进行检查

打开sql会话并运行此查询

Begin Transaction

select * from Transactions

 WAITFOR DELAY '00:05'
/*
some buisness logic which takes 5 minutes

*/

Commit

打开另一个sql会话并运行下面的查询

Begin Transaction
Update Transactions
Set = ...
where ....
commit
申查猛
2023-03-14

你的问题很好。了解获取的锁类型可以深入了解DBMS。在SQL Server中,在所有隔离级别(读取未提交、读取已提交(默认)、可重复读取、可序列化)下,都会为写入操作获取独占锁。

无论隔离级别如何,事务结束时都会释放独占锁。

隔离级别之间的差异是指获取/释放共享(读取)锁的方式。

在Read Uncommitted隔离级别下,不会获取共享锁。在此隔离级别下,可能会出现称为“脏读”的并发问题(允许事务从已被另一个正在运行的事务修改但尚未提交的行中读取数据,因此可以回滚)。

在读取提交隔离级别下,为相关记录获取共享锁。当当前指令结束时,共享锁被释放。此隔离级别可以防止“脏读”,但由于其他并发事务可以更新记录,因此可以发生“不可重复读取”(事务A检索一行,事务B随后更新该行,事务A稍后再次检索同一行。事务A检索同一行两次,但看到不同的数据)或“幻影读取”(在事务过程中,执行两个相同的查询,第二个查询返回的行的集合不同于第一个查询)。

在“可重复读取”隔离级别下,将在事务持续时间内获取共享锁。阻止“脏读”和“非重复读”,但仍可能发生“幻像读”。

在可序列化隔离级别下,在事务持续期间获取范围共享锁。上面提到的并发性问题都不会发生,但是性能会显著降低,并且存在发生死锁的风险。

华泽语
2023-03-14

你问错问题了,你关心的是执行细节。您应该考虑和关注的是隔离级别的语义。肯德拉·利特尔有一张很好的海报来解释它们:免费海报!SQL Server隔离级别指南。

你的问题应该重新表述如下:

从项目中选择 *

问:我将看到哪些项目?< br >答:所有提交的项目

Q: 如果存在插入/删除/更新项目的未提交事务,会发生什么
A:您的SELECT将阻塞,直到提交(或回滚)所有未提交的项目。

问:如果在我运行上面的查询时插入/删除/更新了新项目,会发生什么?
A:结果未确定。您可能会看到一些修改,不会看到其他一些,并且可能会阻塞,直到其中一些提交。

一旦您的声明完成,READ COMMIT 不做任何promise,与交易的长度无关。如果您再次运行该语句,您将再次拥有与之前状态完全相同的语义,并且您之前看到的项目可能会更改、消失并出现新的项目。显然,这意味着可以在您选择后对项目进行更改。

更高的隔离级别提供了更强的保证:REPEATABLE READ保证在提交之前,您第一次选择的任何项目都不能被修改或删除。SERIALIZABLE添加了一项保证,即在提交之前,第二次选择中不会出现任何新项目。

这是你需要理解的,而不是实现机制是如何工作的。掌握了这些概念后,可能会问实现细节。它们都在事务处理:概念和技术中有所描述。

 类似资料:
  • 本文向大家介绍请解释下什么是cookie隔离?为什么要隔离?如何隔离?相关面试题,主要包含被问及请解释下什么是cookie隔离?为什么要隔离?如何隔离?时的应答技巧和注意事项,需要的朋友参考一下 什么是 Cookie 隔离? 或者说:请求资源的时候不要让它带 cookie 怎么做 cookie 隔离技术和传统的多域名拆分请求,提高浏览器并发请求数有点类似,均是采用多域名来处理请求 传统做法是将 c

  • JPA锁(乐观/悲观)和数据库隔离级别(以http://www . PostgreSQL . org/docs/9.1/static/transaction-iso . html为例)之间有没有相互影响? EJB3.2规范(8.3.2“隔离级别”)说Bean提供者负责设置事务的隔离级别,所以一般情况下我应该不会在意,但无论如何我还是很困惑。在PostgreSQL的示例中,根据提到的来源,默认隔离级

  • 日安,我了解什么是可序列化的隔离级别以及它与Postgres中的有何不同。可序列化事务能够检测读写周期,因此只有第一次提交会成功。 考虑到这一点,使用行版本控制的乐观锁定是否有意义?行版本控制的行为方式完全相同,如果版本列已更新,则将抛出 Java 异常,这将回滚事务。此外,根据Postgres维基,如果某些更新是在应用程序级代码之外完成的(例如由psql运行的纯SQL查询),则必须创建触发器。所

  • 我将spring应用程序连接到smartbaer servicev,在那里创建了虚拟数据源(Postgres)。 驱动程序类: 连接字符串(本地servicev虚拟服务器url): 应用程序.属性:- spring.datasource.driver-class-name=com.smartbear.servicev.jdbc.driver.jdbcvirtdriver spring.dataso

  • 我想使用eclipse链接设置隔离级别,我尝试了以下两种方法: > java.sql.连接 Database aseLogin setTransationIsolation方法 如您所见,getTransactionSolation()方法的返回值之间存在一些不一致。我的问题是,在这两种情况下真正设置了哪种事务隔离?我知道eclipse链接在默认情况下使用不同的连接进行读写操作,即Database

  • 问题内容: 我想将隔离级别设置为。如何使用gorm orm for postgres实现此目的。 示例代码: 问题答案: 我在这里有完全一样的问题: 和pg完全一样。