我们正在使用SQL Server2017。我们有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表大约有1200万行,而在上一步中插入数据时,staging表将被截断。
运行此命令时,我们经常会在insert
上遇到违反主键的情况。我的怀疑是,由于READ_COMMITTED_SNAPSHOT ON
,insert
和delete
锁没有互相阻塞,所以insert
发生在delete
没有吃完了吗但是,我认为将所有内容包装在交易中将防止出现此类问题?对于防止关闭这些主键问题而不必关闭READ_COMMITTED_SNAPSHOT
有什么建议?有没有办法仅在这张桌子上放它?
答案 0 :(得分:0)
这是一个数据库设置,您不能按表进行设置,但是...
如果仅将RCSI设置为ON,它只会将已提交的读操作更改为快照读。更新,插入和删除使用正常的事务隔离进行处理。
设置READ_COMMITTED_SNAPSHOT ON选项可以访问 默认的READ COMMITTED隔离级别下版本化的行。
Snapshot Isolation in SQL Server
在任何情况下,由于快照隔离,您都不会看到PK违规,尽管如果在同一行上有两个并发的更新/插入/删除,则可以看到更新冲突。
答案 1 :(得分:0)
运行此命令时,我们经常会在插入内容上遇到违反主键的情况。我的怀疑 是因为READ_COMMITTED_SNAPSHOT ON,插入和删除锁没有彼此阻塞,所以插入是在删除未完成时发生的吗?
对于每个命令,您要使用不同的事务,如果您希望在插入后将它们放入同一事务后进行删除,例如
开始交易 选择DISTINCT STAGING.MyTable.CategoryId INTO #categories_to_delete 来自STAGING.MyTable;
从PROD.MyTableProd中删除 从PROD.MyTableProd 内联#categories_to_delete 开启#categories_to_delete.CategoryId = PROD.MyTableProd.CategoryId; 提交;
开始交易; 选择DISTINCT STAGING.MyTable.ItemId INTO #items_to_delete 来自STAGING.MyTable;
从PROD.MyTableProd中删除 从PROD.MyTableProd 内联#items_to_delete 开启#items_to_delete.ItemId = PROD.MyTableProd.ItemId; 提交;
启用READ_COMMITTED_SNAPSHOT时,事务不会互相阻塞,因为所有事务在初始事务开始时都会读取表的快照。