AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 318050
Accepted
John
John
Asked: 2022-10-11 12:11:17 +0800 CST2022-10-11 12:11:17 +0800 CST 2022-10-11 12:11:17 +0800 CST

写入者在快照隔离级别下相互锁定的更好点

  • 772

SQL Server 中的已提交读快照和快照隔离级别取消了大多数锁定,除了一个:写入者仍然锁定其他写入者。

文档蹑手蹑脚地说了这么多,随后没有记录任何其他非常有趣的内容:

它真的只是一个被独占锁定的修改行吗?或者它也可以是不相关的行(例如,在索引中相邻)或页面?

我确实查看了锁,sys.dm_tran_locks并且我只在未提交的事务期间看到修改行上的排他锁 - 页面仅锁定为IX.

我还测试了两个事务是否可以在一个非常小的表中的两个未提交事务期间同时修改两个不同的行,该表可能适合一页并且效果也很好。

如果确实只有修改的行被独占锁定,那么如果它确保没有两个连接同时写入同一行,那么这将为具有对数据库的独占访问权限的应用程序提供无锁写入的保证。

这在我想到的场景中是可能的——但是如果页面锁定起作用,几乎没有办法做这样的事情,因为无法预测哪些行会受到影响。

sql-server locking
  • 1 1 个回答
  • 115 Views

1 个回答

  • Voted
  1. Best Answer
    ypercubeᵀᴹ
    2022-10-12T02:29:50+08:002022-10-12T02:29:50+08:00
    锁定32分钟。对此答案的评论已被禁用,但它仍在接受其他交互。了解更多。

    关于锁和锁升级的一般规则:

    行级锁可以升级为表级(或分区级)锁。因此,在某些情况下,可能会锁定不相关的行。

    这些情况记录在这里。另请注意,可以使用LOCK_ESCALATIONtable 选项禁用锁定升级。

    还有一些查询计划使用页锁,一些查询计划需要读取被另一个事务锁定的行以确定是否应该修改它。例如update foo where someUnindexedColumn = 'someval',将需要读取每一行,因此将被任何其他写入器阻塞。

    请注意这一点(我们将在最后一段中需要它):

    (一) 重要

    选择事务隔离级别不会影响为保护数据修改而获取的锁。无论为该事务设置的隔离级别如何,事务总是在其修改的任何数据上获得排他锁,并持有该锁直到事务完成。对于读操作,事务隔离级别主要定义免受其他事务修改影响的保护级别。

    关于SNAPSHOT隔离级别的规则:

    术语“快照”反映了这样一个事实,即事务中的所有查询都看到数据库的相同版本或快照,基于事务开始时数据库的状态。快照事务中的底层数据行或数据页不会获取任何锁,这允许其他事务执行而不会被先前未完成的事务阻塞。修改数据的事务不会阻塞读取数据的事务,读取数据的事务不会阻塞写入数据的事务,因为它们通常会在 SQL Server 中的默认 READ COMMITTED 隔离级别下阻塞。这种非阻塞行为也显着降低了复杂事务发生死锁的可能性。

    简而言之,在这个隔离级别:

    • 行版本控制(而不是锁)用于保护其他事务的修改。
    • 读者不会阻止读者。
    • 读者不会阻止作者。
    • 作家不会阻止读者。

    但是,文档没有提到“作者不阻止作者”,因此我们可以安全地假设作者确实可以在 SNAPSHOT 隔离级别中阻止作者。

    有关快照如何工作的更多信息可以在事务锁定和行版本控制中找到:

    快照隔离还使用行版本控制,在读取操作期间不使用共享锁。
    ...
    当 READ_COMMITTED_SNAPSHOT 或 ALLOW_SNAPSHOT_ISOLATION 数据库选项为 ON 时,将为在数据库中执行的所有数据修改维护逻辑副本(版本)。每次特定事务修改行时,SQL Server 数据库引擎实例都会在 tempdb 中存储该行先前提交的映像的一个版本。...

    和下

    修改数据时的行为
    ...
    在快照隔离下运行的事务对数据修改采取乐观的方法,在执行修改之前获取数据锁定以强制执行约束。否则,在要修改数据之前不会在数据上获取锁。当数据行满足更新条件时,快照事务验证数据行没有被快照事务开始后提交的并发事务修改。如果数据行在快照事务之外被修改,就会发生更新冲突快照事务终止。更新冲突由 SQL Server 数据库引擎处理,无法禁用更新冲突检测。

    上面的这一段,尤其是在要修改数据之前确实获得了锁的部分解释了阻塞(作者对作者)行为(并考虑到顶部提到的“重要”注释):

    所以在SNAPSHOT隔离下:

    • 假设事务 A 读取各种数据。不获取锁。
    • 其他事务可以读取相同的数据并且也不会获取锁。
    • 当事务 A 尝试修改某些数据时,会获取并持有一个锁,直到事务结束,这可以是提交或回滚。
    • 其他事务仍然可以读取数据(当然他们会看到一些以前的版本)。没有锁定。
    • 但是,如果事务 B 尝试修改已由某个锁持有的数据(来自未提交的事务 A),那么它也会尝试放置一些锁,并且 B 将被阻塞。
    • 如果事务 A 在某个时刻提交,那么它的锁将被释放,因此事务 B 将被解除阻塞。但是 B 现在将看到更新冲突并且无法成功。
    • 如果事务 A 回滚,则其锁将被释放并删除其行版本,因此事务 B 将被解除阻塞并且其修改可以继续进行。
    • 5

相关问题

  • SQL Server - 使用聚集索引时如何存储数据页

  • 我需要为每种类型的查询使用单独的索引,还是一个多列索引可以工作?

  • 什么时候应该使用唯一约束而不是唯一索引?

  • 死锁的主要原因是什么,可以预防吗?

  • 如何确定是否需要或需要索引

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve