【问题标题】:SQL server select query with NOLOCK not working带有 NOLOCK 的 SQL 服务器选择查询不起作用
【发布时间】:2012-04-02 09:47:41
【问题描述】:

我有以下查询

 SELECT *
  FROM T1 with (NOLOCK )

选择查询可以像用户 (I) 那样去任何地方。

我的应用程序脚本正在插入 1000 行数据并删除旧数据: 所有这些语句都在我的java代码中。插入是批量插入。

--我在这里设置了autocommit false

truncate table T1
insert into table T1 values(x,y,z)
truncate table T2
insert into table T2 values(x,y,z)...and other

--我在这里提交事务

但是在截断和插入完成之前,我不会从 T1 获取数据。怎么可能避免这种情况呢?

【问题讨论】:

  • 请说明您在TRUNCATE / INSERT 序列中的哪个点执行SELECT
  • @BarryKaye 我已经编辑了这可能现在很清楚了。
  • 从我的测试插入不会产生问题,但会截断。如果您在 begin transaction 之前移动它们,则选择返回到目前为止插入的记录。我会尽力寻找解释。
  • TRUNCATE 在桌子上使用SCH-M 锁定。这与架构稳定性锁不兼容,即使是 SELECTNOLOCK 也需要。
  • @MartinSmith 那么这是否意味着我需要使用 Delete *

标签: java sql-server sql-server-2008


【解决方案1】:

您应该考虑将您的 INSERT INTO 语句替换为 BULK INSERT。还要考虑在运行脚本之前更改事务隔离级别并在运行脚本之后恢复,例如

alter database mydb set READ_COMMITTED_SNAPSHOT ON

甚至

alter database mydb set READ_UNCOMMITED_SNAPSHOT ON

这将有效地让您完全摆脱 NOLOCK 语句。

【讨论】:

  • 然后将数据转储到文件并使用 BULK INSERT 导入可能是一种便宜且简单的方法,可以将速度提高 5-10 倍或更多。
  • 不是一个选项,因为我无法写入远程服务器上的文件。
  • 您无需在远程服务器上写入文件即可使用 BULK INSERT,您可以在本地针对删除服务器运行它。
【解决方案2】:

在所有批次完成之前,您将无法看到数据。即使您正在执行读取未提交的选择,插入的数据也只会在完成插入命令时存在于表中

truncate table T1
insert into table T1 values(x,y,z)

**data available for dirty read on T1 here **

truncate table T2
insert into table T2 values(x,y,z)...and other

你可以通过这样做来测试我的意思:

truncate table T1
insert into table T1 values(x,y,'My test values')
**read data here**
insert into table T1 values(x,y,z)

如果您对在此处读取数据运行脏读,您将能够看到“我的测试值”

【讨论】:

    【解决方案3】:

    从 T1 中选择 *(无锁)

    跳过“与”。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-02-25
      • 2013-04-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多