回答

收藏

INSERT操作会导致死锁吗?

技术问答 技术问答 805 人阅读 | 0 人回复 | 2023-09-14

假设:
) D6 Z9 |% G2 ^/ e- b我正在使用REPEATABLE_READ或SERIALIZABLE事务隔离(每次访问都会保留锁)4 v6 e' e- ]- X0 `! z1 H% k
在访问多个表的同时,我们正在讨论多个线程。
我有以下问题:
8 t1 \7 E; V6 P6 T* L- v' }& @[ol]操作是否可能INSERT导致死锁?如果是这样,请提供一个详细的场景来演示如何发生死锁(例如,线程1会这样做,线程2会这样做,…,死锁)。
1 ?7 Z9 z) b2 q/ r为所有其他操作获得加分(如SELECT,UPDATE,DELETE)回答同样的问题。[/ol]更新    :3.超级奖励积分:在以下情况下如何避免僵局?
$ a$ k$ n. c; M3 x( n给定表:& U5 I) `4 ~% w3 p7 V" i# w
权限[id BIGINT PRIMARY KEY]7 ]8 c8 x7 d- A2 o, O. a! U
的公司[id BIGINT PRIMARY KEY,name VARCHAR(30),permission_id BIGINT NOT NULL,FOREIGN KEY (permission_id) REFERENCES permissions(id))
我创办了一家新公司,如下所示:' \9 W+ t( q1 T
INSERT INTO权限;-插入Permissions.id = 100! e( K( o- o" n  v0 y8 T  s, V
INSERT INTO公司(名称,permission_id)VALUES(“ Nintendo”,100);-插入companies.id = 200
删除公司如下:
  {7 w; d& U# l在公司ID = 选择200家公司Permission_id -返回Permissions_id = 100$ m" J0 u6 E' X9 g, x- m7 U. S
从ID删除200家公司;
7 d! d7 W: n6 x. o  Z: D! m4 _: Z从ID删除100权限;
在上述示例中,INSERT锁定顺序为[权限,公司],而DELETE锁定顺序是[公司,权限]。有没有办法解决这个例子的问题?REPEATABLE_READ或SERIALIZABLE隔离?
1 x+ H5 r+ ]: }* M) O* c6 a7 a7 R                                                               
& ]' `% {3 x8 L; N2 h9 I8 X6 R    解决方案:                                                                3 t. P# H: ?% W2 m0 S* Z
                                                                通常,所有的修改都可能导致死锁,但选择不会(稍后介绍)。
2 W+ a+ r! S5 g# n3 I9 g8 a* Y( ], I[ol]不,你不能忽视这些。- t# X8 Z$ k) P% J
您可以根据数据库和设置忽略选择,但其他选择会给您带来僵局。[/ol]你甚至不需要多个表。* C3 D3 ^& i/ `
产生死锁的最佳方法是按不同的顺序执行相同的操作。% J: h3 s1 a3 i
SQL Server示例:
, D6 Q5 _/ z' dcreate table A(    PK int primary key)第一场:$ n% c; \9 @6 K, |+ J
begin transactioninsert into A values(1)第二场:
. {0 g6 m" I7 ]  b% t0 K3 jbegin transaction    insert into A values(7)第一场:( ^6 Y8 a/ S3 {  N
delete from A where PK=7第二场:7 G1 p, O& @. V5 G/ E' i/ E
delete from A where PK=1你将陷入僵局。这证明了插入和删除可能会死锁。
  d$ J9 u& H3 W' m  u* Y更新类似:
1 v, W  V; k4 W( d; z第一场:) c& f: ~- v8 @  n! H, ], N
begin transaction    insert into A values(1)insert into A values(2)commitbegin transactionupdate A set PK=7 where PK=1第二场:0 L8 M: Z2 T! _. ~) p# c
begin transactionupdate A set pk=9 where pk=2    update A set pk=8 where pk=1第一场:! q* o+ |, d3 H9 {
update A set pk=9 where pk=2僵局!
$ F: p1 ^6 A# u/ I9 LSELECT永远不要死锁,但它会在某些数据库上死锁,因为它使用的锁会干扰一致的读取。但这只是数据库引擎设计的一个糟糕方法。0 C* x3 V3 r6 j
如果您使用SNAPSHOT ISOLATION,则SQL
) j* D* E1 G! QServer将不会锁定SELECT。Oracle&我认为Postgres永远不会锁定SELECT(除非你有FOR' z! p& D$ c6 e4 ?$ U
UPDATE,无论如何,它显然保留了更新)。! ]5 s: e; j9 ?5 P/ y9 c4 D
所以,基本上我觉得你有一些错误的假设。我想我已经证明了:& H5 S8 f* d3 S$ O4 U( x
[ol]更新可能导致死锁" U" f" h7 a2 X1 ~. s
删除可能导致死锁( V' m* C) U6 V" ]" F
插入会导致死锁8 N* s, O  }( F1 D9 z/ T
你不需要多张桌子+ \+ ~9 o' U/ s' }% z/ C
确实    需要多次会议[/ol]你只需要相信SELECT;),但这取决于你的数据库和设置。
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则