我有一个表,表B,该表具有表A的外键。两个表都比较大。
在表B的更新过程中,我首先禁用约束,更新内容,然后启用约束。
ALTER TABLE B NOCHECK CONSTRAINT ALL;
-- Update table b
ALTER TABLE B WITH CHECK CHECK CONSTRAINT ALL;
问题在于最后一行需要一段时间才能运行10-15分钟,而在运行时,从表A读取的速度确实很慢! Web应用程序需要表A,并且该应用程序在运行时将超时。
第一个问题:为什么会这样?我认为这只是对表A的共享锁,不会阻止其他读取。
第二个问题:如何避免这种情况?
谢谢!
答案 0 :(得分:2)
第一个问题:为什么会这样?
因为您要求每一行B都验证其FK中的每一个。
更改表B 要检查请检查所有内容;
这可能比仅在更新期间强制执行约束要昂贵得多。
您可以仅对FK到A(如果有多个)禁用/启用检查功能。或者,您可以禁用/不带nocheck来重新启用约束,但是对于在更新过程中所做的更改(并且不受查询优化器信任),使其不被强制执行。
更改表B 不检查检查所有约束;
然后您可以安排任务以检查所有行。
我认为这只是表A的共享锁,不会阻止其他读取。
ALTER TABLE同时影响A和B,因为对A的DELETE和UPDATE查询强制执行FK。因此,ALTER TABLE对A,B和FK对象采用Sch-M锁定。 EG:
pmap_lgl
输出:
use tempdb
drop table if exists B
drop table if exists A
create table A(id int primary key)
create table B(id int, aid int references A)
insert into A(id) values (1)
insert into b(id,aid) values (1,1)
begin transaction
ALTER TABLE B WITH CHECK CHECK CONSTRAINT ALL
select object_name(resource_associated_entity_id) object_name, request_mode
from sys.dm_tran_locks
where request_session_id = @@spid
and resource_type = 'OBJECT'
and request_mode = 'Sch-M'
rollback