我有一个SQL Server 2014的生产实例,需要对其进行一些简单的维护。
本质上,我需要在一个事务中替换两个整个表的内容。我希望在数据更改过程中防止任何人查询任何一个表。这些表都很小,我预计操作时间不会超过几秒钟。
不幸的是,我没有为这个计划停机的好处。
因此,问题是我如何能够同时锁定多个对象-甚至整个数据库?
理想情况下,我只需使用数据库级别的锁,进行更改,并释放锁,但在Server 2014中,这似乎是不可能的。
发布于 2017-11-29 21:04:29
您可以首先使用UPDLOCK查询,以保护您不受整个事务的影响(除了脏读取之外)。
它不可能是一个锁,因为一个锁不能跨越对象。但我仍然相信,只要您没有对NOLOCK进行查询(如果您这样做了,您就得到了所要求的东西!),这就实现了您的目标。
BEGIN TRANSACTION;
SELECT pkcol FROM dbo.foo WITH (UPDLOCK, HOLDLOCK)
UNION ALL
SELECT pkcol FROM dbo.bar WITH (UPDLOCK, HOLDLOCK);
-- do other stuff
UPDATE dbo.foo SET ...;
UPDATE dbo.bar SET ...;
-- do other stuff
-- default isolation level users will be blocked until:
COMMIT TRANSACTION;使用NOLOCK,用户可能潜入其中,从两个表中进行查询,并在更新后从第一个表中获取数据,在更新之前从第二个表中获取数据。但是,当你允许NOLOCK的时候,这也是你得到的。
而且,在这种情况下,处于默认隔离级别的用户可能会查询bar并查看旧值,但他们会阻止foo。
发布于 2017-11-29 21:19:47
我会勉强赶上锁具的潮流。
如果您真的想为更新而锁定数据库,正如标题所述,您可以将数据库放在单用户模式中,并确保在进行更新时只有连接可以连接:
ALTER DATABASE AdventureWorks2012
SET SINGLE_USER
GO在你更新之后:
ALTER DATABASE whatever
SET MULTI_USER
GO但是,请注意,这可能很棘手--例如,SSMS通常会打开许多连接,因此在这种模式下会开始表现不佳。您最好的选择是在这种模式下使用sqlcmd。
https://dba.stackexchange.com/questions/192013
复制相似问题