Проблемы с удалением и вставкой в ​​SQL Server с READ_COMMITTED_SNAPSHOT ON - PullRequest
0 голосов
/ 12 июня 2019

Мы используем SQL Server 2017. У нас есть READ_COMMITTED_SNAPSHOT ON. У нас есть запрос, который выполняет удаление, а затем вставку, подобную этой:

begin transaction
SELECT DISTINCT STAGING.MyTable.CategoryId
INTO #categories_to_delete
FROM STAGING.MyTable;
commit;

begin transaction;
SELECT DISTINCT STAGING.MyTable.ItemId
INTO #items_to_delete
FROM STAGING.MyTable;
commit;

begin transaction;
DELETE FROM PROD.MyTableProd
FROM PROD.MyTableProd
INNER JOIN #categories_to_delete
ON #categories_to_delete.CategoryId = PROD.MyTableProd.CategoryId;
commit;

begin transaction;
DELETE FROM PROD.MyTableProd
FROM PROD.MyTableProd
INNER JOIN #items_to_delete
ON #items_to_delete.ItemId= PROD.MyTableProd.ItemId;
commit;

begin transaction;
INSERT INTO PROD.MyTableProd
SELECT
    CategoryId
    , ItemId
    , <other_columns>
FROM
STAGING.MyTable;
commit;

Первичный ключ на PROD.MyTableProd и STAGING.MyTable равен ItemId. Таблица prod содержит около 12 миллионов строк, а промежуточная таблица усекается при вставке данных на предыдущем шаге.

При этом мы будем часто получать нарушения первичного ключа на insert. Я подозреваю, что из-за READ_COMMITTED_SNAPSHOT ON блокировки insert и delete не блокируют друг друга, поэтому insert происходит, когда delete еще не закончился? Тем не менее, я думал, что завершение всех транзакций предотвратит такие проблемы? Любые предложения по предотвращению этих первичных ключевых проблем без необходимости выключать READ_COMMITTED_SNAPSHOT? Есть ли способ отключить это только для этого стола?

Ответы [ 2 ]

0 голосов
/ 13 июня 2019

При этом мы часто получим нарушения первичного ключа на вставке.Я подозреваю, что из-за READ_COMMITTED_SNAPSHOT ON блокировка вставки и удаления не> блокирует друг друга, поэтому вставка происходит, когда удаление не завершено?

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

начать транзакцию SELECT DISTINCT STAGING.MyTable.CategoryId INTO #categories_to_delete FROM STAGING.MyTable;

УДАЛИТЬ ИЗ PROD.MyTableProd ИЗ PROD.MyTableProd ВНУТРЕННЕЕ СОЕДИНЕНИЕ #categories_to_delete ON #ateg_to_delete.CategoryId = PROD.MyTableProd.CategoryId;commit;

начать транзакцию;ВЫБЕРИТЕ DISTINCT STAGING.MyTable.ItemId INTO #items_to_delete FROM STAGING.MyTable;

УДАЛИТЕ ИЗ PROD.MyTableProd ИЗ ПРОД.commit;

При включенном READ_COMMITTED_SNAPSHOT транзакции не блокируют друг друга, поскольку все транзакции читают снимок таблицы при запуске начальной транзакции.

0 голосов
/ 12 июня 2019

это параметр базы данных, вы не можете сделать это по таблице, но ....

Если для RCSI установлено только ON, он просто изменяет совершенные операции чтения на чтение снимка.Обновления, вставки и удаления обрабатываются с использованием обычной транзакционной изоляции.

Установка опции READ_COMMITTED_SNAPSHOT ON обеспечивает доступ к версионным строкам с уровнем изоляции READ COMMITTED по умолчанию.

Изоляция моментального снимка в SQL Server

В любом случае вы не должны видеть нарушения PK из-за изоляции моментального снимка, хотя вы можете увидеть конфликты обновлений, если есть два одновременных обновления / вставки / удаления нате же строки.

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