插入时锁定表格

11

我有一个大表格是通过视图进行填充的。这么做是因为视图运行时间很长,而且将数据直接存储在表格中更加方便。每隔一段时间会运行一个过程来更新表格。

 TRUNCATE TABLE LargeTable

 INSERT INTO LargeTable
 SELECT * 
 FROM viewLargeView
 WITH (HOLDLOCK)

我想在插入数据时锁定表格,这样如果有人尝试选择记录,他们将不会在截断后收到无信息。我使用的锁似乎锁定的是视图而不是表格。

有没有更好的方法来解决这个问题?


1
在插入之前开启一个事务,然后在插入完成后关闭它怎么样? - Arnaud F.
当打开一个事务时,另一个用户能否从表中进行选择? - JBone
建议您使用DELETE而不是TRUNCATE,因为TRUNCATE是DDL而不是像DELETE这样的DML,因此需要更高的权限。另外,如果您将其包装在事务中(这是您问题的正确答案),它们将有效地执行相同的操作。 - RBarryYoung
在事务中使用TRUNCATE TABLE可能会锁定数据库元数据的长度,这可能会导致不良影响,如果被阻塞的话就更糟了。如果这是在运营期间(非工作时间),那么可能还好,但如果在用户与数据库交互时运行,可能会出现问题... - RBarryYoung
2个回答

9
"正确的锁定提示确实会影响源视图。"
"为了在插入时使任何人都无法从表中读取:"
insert into LargeTable with (tablockx)
...

在插入完成之前,您不需要采取任何措施使表看起来为空。插入始终在事务中运行,除非它们明确指定with (nolock)set transaction isolation level read uncommitted,否则没有其他进程可以读取未提交的行。就我所知,没有办法保护免受此类影响。


7
BEGIN TRY
 BEGIN TRANSACTION t_Transaction

 TRUNCATE TABLE LargeTable

 INSERT INTO LargeTable
 SELECT * 
 FROM viewLargeView
  WITH (HOLDLOCK)

 COMMIT TRANSACTION t_Transaction
END TRY 
BEGIN CATCH
  ROLLBACK TRANSACTION t_Transaction
END CATCH

不认为这会有任何影响。truncate 不受事务的影响,即使您没有指定一个事务,插入本身也是一个事务。 - Andomar
实际上,TRUNCATE操作是可以回滚的,但有一些注意事项。请参见此链接 - Tim Friesen
根据此链接 https://learn.microsoft.com/en-us/sql/t-sql/statements/truncate-table-transact-sql?view=sql-server-2017,“TRUNCATE TABLE 不能在事务内运行。” - Emo
2
@Emo,这仅适用于: “在Azure SQL数据仓库和并行数据仓库中,TRUNCATE TABLE无法在事务内运行。” - Amro
啊,是的,我现在看到了。 - Emo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接