唯一索引导致的死锁

一个事务可以通过回滚段号+槽号+序列号被唯一标示。

V$LOCKID1代表的是回滚段号+槽号,ID2代表序列号。

举例:假如ID11048576,根据以下方法可以换算成回滚段号和槽号。ID2不需要换算。

QL> select trunc(1048576/65536),mod(1048576,65536) from dual;

TRUNC(1048576/65536) MOD(1048576,65536)
-------------------- ------------------
                  16                  0

SQL> select XIDUSN,XIDSLOT,XIDSQN from v$transaction;--------------------查看事务表,XIDUSN代表回滚段号,XIDSLOT代表槽号。跟以上换算结果一致。

XIDUSN    XIDSLOT     XIDSQN
---------- ---------- ----------
        16          0     690881

事务没结束,会保护它所涉及的所有资源.

 

创建一个表,并在ID上建立唯一索引。

apollo@CRMG>create table wxh_tbd (id number);

 

Table created.

 

apollo@CRMG>create unique index xx_bt on wxh_tbd(id);

 

Index created.

 

1)  ORACLE不会对唯一索引的下一键值加锁。不同的SESSION 如果插入不同的值,可以获得各自的资源。(资源以ID1,ID2唯一标识)。典型的DML操作,一般都要获取SUB-EXCLUSIVETM,用来保护表结构,这种锁模式之间可以共享,因此可以对表进行并发的DML。还需要获得X模式的TX锁,保护事务。这种锁模式之间是互斥的(得ID1,ID2相同才行,不同资源的X模式的锁不会互斥)。

 

SESSION 1 ,SID=2867,执行如下语句:

 

apollo@CRMG>insert into wxh_tbd values(1);

 

1 row created.

 

apollo@CRMG>select * from v$lock where (sid=(select sid from v$mystat where rownum=1) or sid=1268) and type<>'AE' ORDER BY SID;

 

ADDR             KADDR                   SID TYPE        ID1        ID2      LMODE    REQUEST      CTIME      BLOCK

---------------- ---------------- ---------- ---- ---------- ---------- ---------- ---------- ---------- ----------

000000009E135F88 000000009E136000       2867 TX       131075     672232          6          0        380          0

0000002A96FF79E8 0000002A96FF7A48       2867 TM       145617          0          3          0        380          0

 

 

SESSION 2,SID=1268,执行如下语句

 

apollo@CRMG>insert into wxh_tbd values(2);

 

1 row created.

 

apollo@CRMG>/

 

ADDR             KADDR                   SID TYPE        ID1        ID2      LMODE    REQUEST      CTIME      BLOCK

---------------- ---------------- ---------- ---- ---------- ---------- ---------- ---------- ---------- ----------

00000000B41F62D8 00000000B41F6350       1268 TX      1310738     679249          6          0          9          0

0000002A96FF79E8 0000002A96FF7A48       1268 TM       145617          0          3          0          9          0

000000009E135F88 000000009E136000       2867 TX       131075     672232          6          0        486          0

0000002A96FF79E8 0000002A96FF7A48       2867 TM       145617          0          3          0        486          0

 

SESSION 1SESSION 2都各自获得了自己的资源。因为他们需要SUB-EXCLUSIVE型的TM资源,他们之间不互斥。

需要获得的TX资源,虽然都为X模式,但是不是同一资源(ID1,ID2判断),也不互斥。

 

2)接着上面的继续。

SESSION 1,插入一个值2,这个2,上面已经在SESSOIN 2插入过了,没提交。

 

apollo@CRMG>insert into wxh_tbd values(2);-------------------------------------------会产生等待。

 

apollo@CRMG>select * from v$lock where (sid=2867or sid=1268) and type<>'AE' ORDER BY SID;

 

ADDR             KADDR                   SID TYPE        ID1        ID2      LMODE    REQUEST      CTIME      BLOCK

---------------- ---------------- ---------- ---- ---------- ---------- ---------- ---------- ---------- ----------

00000000B41F62D8 00000000B41F6350       1268 TX      1310738     679249          6          0        642          1

0000002A96FF6AB0 0000002A96FF6B10       1268 TM       145617          0          3          0        642          0

000000009E135F88 000000009E136000       2867 TX       131075     672232          6          0       1119          0

000000009C79FB80 000000009C79FBD8       2867 TX      1310738     679249          0          4         56          0

0000002A96FF6AB0 0000002A96FF6B10       2867 TM       145617          0          3          0       1119          0

 

SESSION 2拥有资源ID1=1310738,ID2=679249

由于SESSION 1需要获得SESSION 2ID1=1310738,ID2=679249的资源而发生等待。而且请求的锁模式是4,即共享模式。

SESSION 1请求的共享模式SSESSION 2拥有的X模式不兼容,因此发生等待。

这里ORACLE通过什么实现的这种锁,我不清楚,可能象我们想的通过脏读,发现已经插入2了,就等待2的资源。

 

 

3)如果这个时候,SESSION 2再插入1.那么死锁就会发生。

 

查看跟踪文件,这个时候你就会发现一个比较有意思的现象,由于都请求双方的共享锁而发生的死锁。可能很多人一直以为死锁都是X型产生的,死锁与锁模式无关。

Deadlock graph:

                       ---------Blocker(s)--------  ---------Waiter(s)---------

Resource Name          process session holds waits  process session holds waits

TX-00020003-000a41e8       551    2867     X            686    1268           S

TX-00140012-000a5d51       686    1268     X            551    2867           S

 

session 2867: DID 0001-0227-0000BDCC    session 1268: DID 0001-02AE-00001EA9

session 1268: DID 0001-02AE-00001EA9    session 2867: DID 0001-0227-0000BDCC

 

Rows waited on:

  Session 2867: obj - rowid = 000238D1 - AAAjjRABFAAANPIAAA

  (dictionary objn - 145617, file - 69, block - 54216, slot - 0)

  Session 1268: obj - rowid = 000238D2 - AAAjjSABFAAANPTAAA

  (dictionary objn - 145618, file - 69, block - 54227, slot - 0)

 

 

4)延伸一下。加入我们退回到步骤2SESSION 2提交的话,是一个报错,唯一索引冲突

 

如果回滚呢?

会顺利插入。重点看下,回滚前后,V$LOCK的变化。

回滚前:

apollo@CRMG>select * from v$lock where (sid=1547 or sid=1268) and type<>'AE' ORDER BY SID;

 

ADDR             KADDR                   SID TYPE        ID1        ID2      LMODE    REQUEST      CTIME      BLOCK

---------------- ---------------- ---------- ---- ---------- ---------- ---------- ---------- ---------- ----------

0000002A970730B0 0000002A97073110       1268 TM       145617          0          3          0         52          0

00000000B41F62D8 00000000B41F6350       1268 TX       524319     842480          6          0         52          1

00000000B3EB08E0 00000000B3EB0958       1547 TX       131097     672790          6          0          9          0

0000002A970730B0 0000002A97073110       1547 TM       145617          0          3          0          9          0

00000000B27BC828 00000000B27BC880       1547 TX       524319     842480          0          4          9          0

 

 

回滚后:

apollo@CRMG>select * from v$lock where (sid=1547 or sid=1268) and type<>'AE' ORDER BY SID;

 

ADDR             KADDR                   SID TYPE        ID1        ID2      LMODE    REQUEST      CTIME      BLOCK

---------------- ---------------- ---------- ---- ---------- ---------- ---------- ---------- ---------- ----------

00000000B3EB08E0 00000000B3EB0958       1547 TX       131097     672790          6          0         47          0

0000002A96FF6AB0 0000002A96FF6B10       1547 TM       145617          0          3          0         47          0

 

SESSION 1将请求的ID1=524319,ID2=842480的资源获取后,替换为自身的事务信息,这是因为锁所保护的事务资源已经被修改了。

 

fj.png11.jpg

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/22034023/viewspace-689838/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/22034023/viewspace-689838/

LangChain实战:用FAISS搭建本地文档问答系统(含Word文件处理避坑指南) 本文详细介绍了如何利用LangChain框架和FAISS向量数据库构建本地化智能文档问答系统,特别针对Word文档处理中的技术难点提供实用解决方案。通过模块化设计、本地化支持和多格式兼容,实现高效文档处理与精准问答,满足企业对数据隐私和安全的需求。 阅读详情

相关推荐

编写一个期货跨期套利的程序,谈谈思路及案例

🏆本文收录于《CSDN问答解惑-专业版》专栏,主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!

**My Coding Family** 1678

MySQL死锁套路之唯一索引下批量插入顺序不一致

前言 死锁的本质是资源竞争,批量插入如果顺序不一致很容易导致死锁,我们来分析一下这个情况。为了方便演示,把批量插入改写为了多条 insert。 先来做几个小实验,简化的表结构如下 CREATE TABLE `t1` ( `id` int(11) NOT NULL AUTO_INCREMENT, `a` varchar(5), `b` varchar(5), PRIMARY KEY (`id`), UNIQUE KEY `uk_name` (`a`,`b`) ); 实验1: 在记录不存在的情况下,两个同样顺序的批量 insert 同时执行,第二个会进行锁等待状态 t1 t

万特WF-36低压故障排除电气回路图

万特WF-36低压故障排除电气回路图,word格式。

[MySQL]-死锁案例-唯一索引上的并发插入

死锁,是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等的进程称为死锁进程。要找到问题的原因所在,解决自己的盲区问题的复现也要做到准确,去寻找技巧问题的解决需要真正做到可行,但同时也需要理清方案的优缺点。

liangsena的博客 3760

MySQL 唯一索引为什么会导致死锁

唯一性索引unique影响 唯一性索引表创建 ????DROP?TABLE?IF?EXISTS?`sc`; ????CREATE?TABLE?`sc`?( ??????`id`?int(11)?NOT?NULL?AUTO_INCREMENT, ??????`name`?varchar(200)?CHARACTER?SET?utf8?DEFAULT?NULL, ??????`class`?varchar(200)?CHARACTER?SET?utf8?DEFAULT?NULL, ??????`score`?i

web15870359587的博客 541

MySQL——插入加锁/唯一索引插入死锁/批量插入效率

本篇主要介绍MySQL跟加锁相关的一些概念、MySQL执行插入Insert时的加锁过程、唯一索引下批量插入可能导致死锁情况,以及分别从业务角度和MySQL配置角度介绍提升批量插入的效率的方法;

娜娜米的博客 1万+

死锁:多线程同时删除唯一索引上的同一行

1死锁问题背景1 1.1一个不可思议的死锁1 1.1.1初步分析3 1.2如何阅读死锁日志3 2死锁原因深入剖析4 2.1Delete操作的加锁逻辑4 2.2死锁预防策略5 2.3剖析死锁的成因6 3总结7 死锁问题背景 做MySQL代码的深入分析也有些年头了,再加上自己10年左右的数据库内核研发经验,自认为对于MySQL/In...

lgxzzz的博客 680

MySQL 唯一索引,并发插入导致死锁

一日志 ------------------------ LATEST DETECTED DEADLOCK ------------------------ 2020-07-27 16:28:53 0x7fc914aee700 *** (1) TRANSACTION: TRANSACTION 484991260, ACTIVE 0 sec setting auto-inc lock mysql tables in use 2, locked 2 LOCK WAIT 3 lock struct(s), h

bohu83的博客 3345

面试官:MySQL 唯一索引为什么会导致死锁

on duplicate key 在执行时,innodb引擎会先判断插入的行是否产生重复key错误,如果存在,在对该现有的行加上S(共享锁)锁,如果返回该行数据给mysql,然后mysql执行完duplicate后的update操作, 然后对该记录加上X(排他锁),最后进行update写入。insert ignore会忽略数据库中已经存在的数据(根据主键或者唯一索引判断),如果数据库没有数据,就插入新的数据,如果有数据的话就跳过这条数据.如果原有的记录被更新,则受影响行的值显示2;

m0_50180963的博客 317

mysql唯一索引导致死锁_InnoDB非唯一索引导致死锁

死锁日志获取最近发生的deadlock:SHOW ENGINE INNODB STATUS; 配置:innodb_print_all_deadlocks并在error log查看(无法截图,请点击查看大图)翻译:行号:"1: len 8; hex 000000000000B75; asc":B75(16进制) = 2933(10进制)。(1)WAITING FOR THIS LOCK TO BE ...

weixin_39641738的博客 647

MySQL 唯一索引 UNIQUE KEY 会导致死锁

命令添加unique: 删除: 唯一性索引作用: 先行插入部分数据: 再次查看表定义: 这时的Auto_Increment=5再次执行sql: 此时再次查看表定义,会发现Auto_Increment=6具体的区别:insert ignore: insert ignore会忽略数据库中已经存在的数据(根据主键或者唯一索引判断),如果数据库没有数据,就插入新的数据,如果有数据的话就跳过这条数据。 执行上面的语句,会发现并没有报错,但是主键还是自动增长了。 此时会发现吕布的班级跟年龄都改变了,但是id也变成最新的

Tongyao 1208

MySQL唯一索引并发插入导致死锁

共享与排他锁:S 锁:共享锁,允许其他事务并行读;禁止其他事务持有排它锁X 锁:排它锁,允许持有排它锁的事务对数据更新,禁止其他事务对数据持有共享锁或排它锁注:普通的 select * from user 属于快照读,不加任何锁。在 MySQL 事务进行读写时,需要先对表加意向读写锁,意向锁也分为共享和排他锁,记为 IS、IX。的,IX,IS是表级锁,不会和行级的X,S锁发生冲突,只会和表级的X,S发生冲突。

八戒的博客 926

科普文:软件架构数据库系列之【MySQL死锁案例分析:网上二唯一索引并发insert导致死锁及解决方案 ERROR 1213 (40001): Deadlock】

关于死锁,确切的说是innodb引擎表的死锁,在我们梳理的场景下,基本都是“行锁”导致的,而且隔离级别大多都是RR。案例剖析,MySQL唯一索引并发插入导致死锁 其实就是Gap Lock间隙锁导致死锁

为无为,事无事,味无味。 1118
上一篇: 通过v$sql_bind_capture 查看绑定变量。
下一篇: no_unnest,push_subq用法小试
cotchte0421
博客等级 码龄11年 5粉丝 110原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值