表锁定建议

时间:2011-11-29 00:36:11

标签: sql-server sql-server-2008 tsql sql-server-2008-r2

我想执行以下操作:

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查询的客户端,如果可能的话。

任何建议都将受到赞赏。

2 个答案:

答案 0 :(得分:3)

使用分区切换。尽管人们普遍认为,分区切换要求对表进行分区。在临时表中准备新数据,快速切换并替换旧数据:

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

答案 1 :(得分:0)

使用BEGIN TRANSACTION。除非您愿意将数据库置于单用户模式,否则AFAIK不能使用READ_UNCOMMITTED或NO_LOCK来阻止客户端。通过该事务,我认为您不需要DELETE...语句

我面前没有SQLEM,所以这可能不完美:

BEGIN TRANSACTION

TRUNCATE TABLE Table1;
TRUNCATE TABLE Table2;

ALTER DATABASE [Works] SET MULTI_USER WITH NO_WAIT

-- 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
INSERT INTO Table2... SELECT ... FROM Table1... 

ALTER DATABASE [Works] SET MULTI_USER WITH NO_WAIT

COMMIT;