假设:
- 我使用REPEATABLE_READ或SERIALIZABLE事务隔离(锁会保留我每次访问行时间)
- 我们谈论的是多个线程同时访问多个表。
我有以下问题:
- 是否有可能为一个
INSERT
操作导致死锁? 如果有,请提供详细的方案演示如何可能会发生死锁(例如线程1这样做,线程2这样做,......,死锁)。 - 奖励积分:回答所有其他操作同一个问题(如SELECT,UPDATE,DELETE)。
UPDATE:3.超级奖励积分:我怎样才能避免在以下情况下的僵局?
鉴于表:
- 权限
[id BIGINT PRIMARY KEY]
- 公司
[id BIGINT PRIMARY KEY, name VARCHAR(30), permission_id BIGINT NOT NULL, FOREIGN KEY (permission_id) REFERENCES permissions(id))
我创建了一个新的公司如下:
- INSERT INTO权限; - 插件permissions.id = 100
- INSERT INTO公司(名称,permission_id)VALUES( '任天堂',100); - 插入companies.id = 200
我删除公司如下:
- 选择permission_id FROM公司WHERE ID = 200; - 返回permission_id = 100
- DELETE FROM公司里的id = 200;
- DELETE FROM权限WHERE ID = 100;
在上面的例子中,INSERT锁定顺序是[权限,公司]而DELETE锁定顺序是[公司,权限。 有没有办法来解决这个例子REPEATABLE_READ
或SERIALIZABLE
隔离?
一般来说,所有的修改可能会导致死锁,并选择不会(到后来)。 所以
- 不,你不能忽视这些。
- 你可以稍微忽略这取决于您的数据库,并设置中选择,但别人会给你死锁。
你甚至都不需要多个表。
创建僵局的最好办法是做同样的事情在不同的顺序。
SQL Server的实例:
create table A
(
PK int primary key
)
会议1:
begin transaction
insert into A values(1)
第二节:
begin transaction
insert into A values(7)
会议1:
delete from A where PK=7
第二节:
delete from A where PK=1
你会得到一个僵局。 所以这证明了刀片和删除可以死锁。
更新是相似的:
会议1:
begin transaction
insert into A values(1)
insert into A values(2)
commit
begin transaction
update A set PK=7 where PK=1
第二节:
begin transaction
update A set pk=9 where pk=2
update A set pk=8 where pk=1
会议1:
update A set pk=9 where pk=2
僵局!
SELECT不应该死锁,但在某些数据库会因为锁它使用干扰持续读。 这只是蹩脚的数据库引擎的设计,虽然。
如果你使用快照隔离SQL Server将不会在选择锁定。 甲骨文:我觉得Postgres将永远在选择锁定(除非你有FOR UPDATE这显然是保留的更新反正)。
所以基本上我觉得你有一些不正确的假设。 我想我已经证明了:
- 更新可能导致死锁
- 删除可能导致死锁
- 插入可能导致死锁
- 你并不需要一个以上的表
- 你需要不止一个会话
你只好把我的选择Word),但是这将取决于您的数据库和设置。
除了LoztInSpace的回答, inserts
可能导致死锁,即使没有deletes
或updates
的存在。 所有你需要的是一个独特的指数,反向操作顺序。
实施例中的Oracle:
create table t1 (id number);
create unique index t1_pk on t1 (id);
--thread 1 :
insert into t1 values(1);
--thread 2
insert into t1 values(2);
--thread 1 :
insert into t1 values(2);
--thread 2
insert into t1 values(1); -- deadlock !
让我们假设你有两个关系, A
和B
和两个用户X
和Y
。 表A被写由用户X锁定和表B被写由Y.锁定,那么如果使用的用户X和Y.以下两个查询会给你一个死锁
Select * from A,B
因此,明确了Select
是否参加涉及多个表是它的一部分业务操作可能导致死锁。 通常插入和删除操作涉及单个关系。 因此,他们可能不会引起死锁。