【问题标题】:What sql server isolation level should I choose to prevent concurrent reads?我应该选择什么 sql server 隔离级别来防止并发读取?
【发布时间】:2010-04-09 13:50:47
【问题描述】:

我有以下交易:

  1. SQL 将 1 条新记录插入到名为 tbl_document 的表中
  2. SQL 删除与另一个名为 tbl_attachment 的表中的条件匹配的所有记录
  3. SQL 将多条记录插入到 tbl_attachment 中

在此事务完成之前,我不希望其他用户知道 (1) tbl_document 中的新记录、(2) tbl_attachment 中已删除的记录以及 (3) tbl_attachment 中已修改的记录。

Read Committed Isolation 是正确的隔离级别吗?

【问题讨论】:

  • 什么版本的 SQL Server?如果是 2005 年或更高版本,则应通过快照自动正确处理(默认情况下)。

标签: sql-server transactions


【解决方案1】:

写入的事务隔离级别无关紧要。重要的是您的读取的隔离级别。通常读取将不会看到您的插入/更新/删除,直到提交。唯一可以看到未提交更改的隔离级别是 READ UNCOMMITTED。如果并发线程使用脏读,则 没有 您可以在写操作中阻止它。

READ UNCOMMITTED 可以设置为隔离级别,也可以使用 (NOLOCK) 表提示显式请求。脏读可以看到不一致的事务数据(例如,借方不平衡操作的贷方),还可以导致重复读取(从表中多次读取同一行)并触发神秘的键违规。

【讨论】:

  • 快照隔离不会阻止 READ UNCOMMITTED 和 NOLOCK 读取吗?
  • @KM:没有。您可以轻松地测试自己。来自 SNAPSHOT 事务的未提交写入对并发未提交读取完全可见。
【解决方案2】:

是的,像这样:

BEGIN TRANSACTION

   insert into tbl_document ...
   delete tbl_attachment where ...
   inserts into tbl_attachment ...

COMMIT

您可以阻止/锁定用户,直到您完成并提交/回滚事务。此外,有人可以在您插入 tbl_document 之后但在您删除之前从 tbl_attachment 中选择您的行。如果您需要防止这种情况发生,请执行以下操作:

BEGIN TRANSACTION

   select tbl_attachment with (UPDLOCK,HOLDLOCK) where ...
   insert into tbl_document ...
   delete tbl_attachment where ...
   inserts into tbl_attachment ...

COMMIT

或者在插入 tbl_document 之前删除 tbl_attachment 并忘记带有锁定提示的选择。

【讨论】:

  • 我注意到您没有指定隔离级别。这是因为 SQL Server 2005 默认读取已提交吗?如果我在 tbl_document 上进行更新而不是插入,这段代码是否也能正常工作?
  • 如果运行您的应用程序的每个人都在使用read commited,那么他们只能读取已提交的更改。如果您尝试读取正在更改的数据(事务仍在进行中),您将等到事务完成后再处理您的读取。就像您问题中的删除一样,存在时间问题。有人将能够在您的BEGIN TRANSACTION 和您的实际UPDATE 之间读取您打算更新的行。使用插入,这不是问题(它们是新的,在您放入之前它们不存在)。
  • 继续.. 在您进行事务时获取锁。如果您在 update 之前的交易中做了很多事情,并且您希望从交易开始的那一刻起冻结人们阅读这些行,那么您可以尝试在开始时使用 SELECT ... WITH (UPDLOCK,HOLDLOCK)交易。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多