Совет по блокировке стола - PullRequest
2 голосов
/ 29 ноября 2011

Я хотел бы выполнить следующие операции:

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 ]

3 голосов
/ 29 ноября 2011

Использовать переключение разделов. Несмотря на распространенное мнение, переключение секций не требует разделения вашей таблицы. Подготовьте новые данные в промежуточной таблице (таблицах), быстро включите их и замените старые данные:

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

См. Эффективная передача данных с помощью переключения разделов .

0 голосов
/ 29 ноября 2011

Используйте 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;
...