Блокировка таблицы для обновления / удаления / вставки при выполнении транзакции - PullRequest
0 голосов
/ 07 марта 2020

Я пытаюсь преобразовать свои операторы DELETE в TRUNCATE, используя Как удалить большие данные таблицы в SQL без журнала?

Вот то, что я пытаюсь,

   -- Move recent records from Main table to a Temp table
   -- TRUNCATE the Main table
   -- Return back data from Temp table to Main table

В этот период я ​​хочу прекратить выполнение любых операторов INSERT / UPDATE / DELETE (до выполнения инструкции TRUNCATE) в моей главной таблице, поскольку, если я разрешу, мы можем потерять некоторые данные во время TRUNCATE.

Ответы [ 3 ]

2 голосов
/ 07 марта 2020

TRUNCATE оператор получает блокировку SCH-M, это означает, что он создает блокировку изменения схемы

Второй тип блокировки - блокировка изменения схемы - SCH-M. Этот тип блокировки получается сеансами, которые изменяют метаданные и действуют в течение транзакции. Эту блокировку можно описать как супер-эксклюзивную блокировку, и она несовместима с любыми другими типами блокировок, включая намеренные блокировки

Блокировка на сервере Microsoft SQL (Часть 13 - Блокировки схемы)

В течение этого времени операторы обновления, выбора и удаления будут ожидать операции усечения таблицы. В результате операция CRUD автоматически остановится, пока не будет завершена инструкция TRUNCATE.

1 голос
/ 08 марта 2020

Ниже приведен пример сценария, который уменьшает запись в журнал модели полного восстановления с использованием SWITCH и TRUNCATE. SWITCH - это быстрая операция только с метаданными. Освобождение пространства, выполняемое TRUNCATE, выполняется асинхронным фоновым потоком с более крупными таблицами (64 МБ +), поэтому он также быстр и значительно сокращает журналирование по сравнению с DELETE;

Транзакция используется для обеспечения всех или нет поведение и блокировка изменения схемы удерживается на время транзакции, чтобы остановить изменения данных во время процесса.

Ниже приведено пространство журнала транзакций, используемое до и после процесса в примере с 1M строками изначально и 50K сохранено:

+--------+---------------+--------------------+
|        | Log Size (MB) | Log Space Used (%) |
+--------+---------------+--------------------+
| Before |      1671.992 |           27.50415 |
| After  |      1671.992 |           30.65533 |
+--------+---------------+--------------------+

Установка теста:

--example main table
CREATE TABLE dbo.Main(
      MainID int NOT NULL CONSTRAINT PK_Main PRIMARY KEY
    , MainData char(1000) NOT NULL
);
--staging table with same schema and indexes as main table
CREATE TABLE dbo.MainStaging(
      MainID int NOT NULL CONSTRAINT PK_MainStaging PRIMARY KEY
    , MainData char(1000) NOT NULL
);
--load 1M rows into main table for testing
WITH 
     t10 AS (SELECT n FROM (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) t(n))
    ,t1k AS (SELECT 0 AS n FROM t10 AS a CROSS JOIN t10 AS b CROSS JOIN t10 AS c)
    ,t1g AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS num FROM t1k AS a CROSS JOIN t1k AS b CROSS JOIN t1k AS c)
INSERT INTO dbo.Main WITH(TABLOCKX) (MainID, MainData) 
SELECT num, CAST(num AS char(1000))
FROM t1g
WHERE num <= 1000000;
GO

Пример сценария:

SET XACT_ABORT ON; --ensures transaction is rolled back immediately even if script is cancelled
BEGIN TRY

    BEGIN TRAN;

    --truncate in same transaction so entire script can be safely rerun
    TRUNCATE TABLE dbo.MainStaging;

    --ALTER TABLE will block other activity until committed due to schema modification lock
    --main table will be empty after switch
    ALTER TABLE dbo.Main SWITCH TO dbo.MainStaging;

    --keep 5% of rows
    INSERT INTO dbo.Main WITH(TABLOCKX) (MainID, MainData)
    SELECT MainID, MainData
    FROM dbo.MainStaging
    WHERE MainID > 950000;

    COMMIT;

END TRY
BEGIN CATCH

    IF @@TRANCOUNT > 0 ROLLBACK;
    THROW;

END CATCH;
GO
1 голос
/ 07 марта 2020

Попробуйте использовать транзакцию:

BEGIN TRANSACTION

SELECT TOP 1 *
FROM table_name
WITH (TABLOCK, HOLDLOCK)

-- do your stuff

COMMIT 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...