INSERT操作可以在一个僵局导致?(Can an INSERT operation result

2019-09-03 00:38发布

假设:

  • 我使用REPEATABLE_READ或SERIALIZABLE事务隔离(锁会保留我每次访问行时间)
  • 我们谈论的是多个线程同时访问多个表。

我有以下问题:

  1. 是否有可能为一个INSERT操作导致死锁? 如果有,请提供详细的方案演示如何可能会发生死锁(例如线程1这样做,线程2这样做,......,死锁)。
  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_READSERIALIZABLE隔离?

Answer 1:

一般来说,所有的修改可能会导致死锁,并选择不会(到后来)。 所以

  1. 不,你不能忽视这些。
  2. 你可以稍微忽略这取决于您的数据库,并设置中选择,但别人会给你死锁。

你甚至都不需要多个表。

创建僵局的最好办法是做同样的事情在不同的顺序。

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这显然是保留的更新反正)。

所以基本上我觉得你有一些不正确的假设。 我想我已经证明了:

  1. 更新可能导致死锁
  2. 删除可能导致死锁
  3. 插入可能导致死锁
  4. 你并不需要一个以上的表
  5. 需要不止一个会话

你只好把我的选择Word),但是这将取决于您的数据库和设置。



Answer 2:

除了LoztInSpace的回答, inserts可能导致死锁,即使没有deletesupdates的存在。 所有你需要的是一个独特的指数,反向操作顺序。

实施例中的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 !


Answer 3:

让我们假设你有两个关系, AB和两个用户XY 。 表A被写由用户X锁定和表B被写由Y.锁定,那么如果使用的用户X和Y.以下两个查询会给你一个死锁

Select * from A,B

因此,明确了Select是否参加涉及多个表是它的一部分业务操作可能导致死锁。 通常插入和删除操作涉及单个关系。 因此,他们可能不会引起死锁。



文章来源: Can an INSERT operation result in a deadlock?