【发布时间】:2017-03-03 13:31:09
【问题描述】:
假设我们有以下数据库表:
create table department (
id bigint not null,
budget bigint not null,
name varchar(255),
primary key (id)
)
create table employee (
id bigint not null,
name varchar(255),
salary bigint not null,
department_id bigint,
primary key (id)
)
alter table employee
add constraint FKbejtwvg9bxus2mffsm3swj3u9
foreign key (department_id) references department
我们有 3 个department 行:
insert into department (name, budget, id)
values ('Department 1', 100000, 1)
insert into department (name, budget, id)
values ('Department 2', 75000, 2)
insert into department (name, budget, id)
values ('Department 3', 90000, 3)
我们还有 3 个employee 行:
insert into employee (department_id, name, salary, id)
values (1, 'CEO', 30000, 1)
insert into employee (department_id, name, salary, id)
values (1, 'CTO', 30000, 2)
insert into employee (department_id, name, salary, id)
values (2, 'CEO', 30000, 3)
假设我们有两个并发用户:Alice 和 Bob。
首先,Alice 锁定属于第一个department 的所有员工:
SELECT *
FROM employee
WITH (HOLDLOCK)
WHERE department_id = 1
现在,与此同时,预计 Bob 不能使用相同的 department_id 插入新的 employee:
INSERT INTO employee WITH(NOWAIT) (department_id, name, salary, id)
VALUES (1, 'Carol', 9000, 6)
上面的插入语句以Lock request time out period exceeded 结尾,这很好,因为 Alice 锁定了该特定范围。
但是,为什么下面的插入也被阻止了:
INSERT INTO employee WITH(NOWAIT) (department_id, name, salary, id)
VALUES (3, 'Dave', 9000, 7)
这个插入语句使用了一个超出 Alice 谓词锁范围的department_id 值。但是,这个插入语句也以Lock request time out period exceeded 异常结束。
为什么 SQL Server HOLDLOCK 谓词锁超出其范围?
更新
通过向 FK 添加索引:
create index IDX_DEPARTMENT_ID on employee (department_id)
将第一个和第二个department 中的employee 条目数增加到1000 个,我设法看到谓词锁的行为符合预期。
【问题讨论】:
标签: sql-server concurrency transactions locking predicate