>我使用REPEATABLE_READ或SERIALIZABLE事务隔离(每次访问一个行时,锁都会保留)
>我们正在谈论同时访问多个表的多个线程.
我有以下问题:
> INSERT操作是否可能导致死锁?如果是这样,请提供详细的场景,说明如何发生死锁(例如,线程1执行此操作,线程2执行此操作,死锁).
>对于奖励积分:对所有其他操作(例如SELECT,UPDATE,DELETE)回答相同的问题.
更新:
3.对于超级奖励积分:如何在以下情况下避免死锁?
给定表:
>权限[id BIGINT PRIMARY KEY]
>公司[id BIGINT PRIMARY KEY,name VARCHAR(30),permission_id BIGINT NOT NULL,FOREIGN KEY(permission_id)REFERENCES权限(id))
我创建一个新公司如下:
> INSERT INTO权限; – 插入permissions.id = 100
> INSERT INTO companies(name,permission_id)VALUES(“Nintendo”,100); – 插入company.id = 200
我删除公司如下:
> SELECT permission_id FROM COMPANY WHERE id = 200; – 返回permission_id = 100
> DELETE FROM companies WHERE 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)
会话2:
begin transaction insert into A values(7)
会议1:
delete from A where PK=7
会话2:
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
会话2:
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不应该死锁,而是在某些数据库上,因为它使用的锁会干扰一致的读取.这只是数据库引擎设计的糟糕.
如果使用SNAPSHOT隔离,sql Server将不会锁定在SELECT上. Oracle&我认为Postgres永远不会锁定SELECT(除非你有明确保留更新的FOR UPDATE).
所以基本上我觉得你有一些不正确的假设.我想我已经证明:
>更新可能会导致死锁
>删除可能会导致死锁
>插入可能导致死锁
>你不需要多于一个表
>你需要多个会话
您只需要在SELECT上使用我的单词),但它将取决于您的数据库和设置.