我想执行以下操作:
TRUNCATE TABLE Table1;
TRUNCATE TABLE Table2;
-- I do not want to allow possibly the viewing and definitely the modification
-- of Table1 or Table2 at this point, so that I can make changes to them atomically
-- possibly even regardless of the isolation level in other sessions (or this one).
-- So, I lock both tables. I want to remove any data that could have made its way into
-- the tables, due to the current isolation level, for example, and remove any rows.
-- Also, from this point on, I want the tables to be unviewable (all queries blocked)
-- and unmodifyable (all INSERTs, UPDATEs, DELETEs blocked)
DELETE FROM Table1 WITH(TABLOCKX, HOLDLOCK);
DELETE FROM Table2 WITH(TABLOCKX, HOLDLOCK);
-- This is a long running complex INSERT operation into Table1
INSERT INTO Table1... SELECT ...
-- This is a long running complex INSERT operation into Table2, based on the
-- data in Table1 and some other ancillary tables
INSERT INTO Table2... SELECT ... FROM Table1...
COMMIT;
我想阻止对表 Table1
和 Table2
的所有访问,从 TRUNCATE
命令完成到它们已完全构建,并且使用 COMMIT
提交更改。最好,即使是使用 READ_UNCOMMITTED 隔离级别的客户端,甚至是执行 NOLOCK
查询的客户端(如果可能的话)。
如有任何建议,我们将不胜感激。
最佳答案
使用分区切换。尽管人们普遍认为,分区切换并不需要对表进行分区。在临时表中准备新数据,快速切换它们并替换旧数据:
create table users (
id int identity(1,1) primary key,
name char(100));
go
insert into users (name)
values ('A'), ('B'), ('C'), ('D');
go
select * from users;
create table staging (
id int identity(1,1) primary key,
name char(100));
create table staging_empty (
id int identity(1,1) primary key,
name char(100));
go
insert into staging (name)
values ('Z'), ('Y'), ('X');
go
begin transaction;
alter table users switch partition 1 to staging_empty;
alter table staging switch partition 1 to users;
commit
go
select * from users;
go
参见Transferring Data Efficiently by Using Partition Switching .
关于sql-server - 表锁定建议,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8304343/