首页
学习
活动
专区
圈层
工具
发布

MySQL 案例:Update 死锁详解

死锁的两个语句如下: UPDATE tbl_deadlock SET col1 = 1, col2 = 1, update_time = 1603685523 WHERE (id1 = 6247476)...MySQL 不触发死锁回滚,且未进入 lockwait_timeout 的时候,具备这个条件。 不剥夺条件:已获得的资源,在末使用完之前,不能强行剥夺。 MySQL 的锁机制天然具备这个条件。...由于 MySQL 的锁机制的原因,只需要判断出两个 SQL 语句的锁存在循环等待,那么死锁的条件就会成立了。...用户提出的疑问:使用的也是不同的索引,为什么会发送死锁?实际上二级索引上的记录锁,最终也会加到主键上。...因此本案例中,虽然死锁信息中记录的索引名称不一样,但是锁争用的条件是成立的,即:trx1 通过二级索引向主键上执行了加锁操作,而 trx2 在其他的二级索引上拿到了锁,但是主键锁拿不到,因此进入了等待状态

16.5K175

MySQL 使用 for update 引发死锁原因分析

在之前的一次开发需求中使用了 for update 实现悲观锁,最后导致出现了很多的 MySQL 死锁报警,现记录下死锁产生的原因。...但是后来发现这个修改逻辑造成 MySQL 死锁。...死锁原因分析造成死锁的原因主要和 for update 对数据加锁的过程有些关系,加锁过程描述:MySQL innodb 存储引擎默认的隔离级别时 RR 级别,而RR隔离级别,默认是使用Next-key...间隙锁只影响一般索引,对于唯一索引或者主键,如果查询的结果包含这个记录,那么另外的会话插入该记录前后,不会产生间隙锁;如果查询结果不包含这个记录,另外的会话插入该记录前后的间隙,会产生间隙锁。...,并对这部分数据进行修改时就会出现死锁的情况参考文章MySQL 锁类型总结MySQL 间隙锁,锁过程详解

2K40
  • 您找到你想要的搜索结果了吗?
    是的
    没有找到

    mysql insert duplicate key update 死锁分析

    背景 数据入库这块有离线和实时两套入库系统,写同一个db的同一批mysql表,两边用的都是insert into table on duplicate key update这种方式。...原因分析&解决方案 这里面分两种情况,一种是带主键的insert duplicate key update,一种是没有主键带唯一索引的insert duplicate key update。...1、带主键的insert duplicate key update 实时入库的batch大小是1w,离线入库的batch大小也是1w,为了提高入库效率 ,两边都开启了事务。...解决方案: 1、减少batch的大小,单个事务获取到的next-key锁的范围就会变少,减少死锁的概率。 2、重试。 3、插入数据时添加主键。...如果插入数据时带上主键,那么就不会产生next-key锁,会退化到第一种情况(带主键的insert duplicate key update)。

    5.1K11

    MySQL RC模式insert update 可能死锁的情况

    涉及的语句为 RC模式下 update根据主键更新和insert 其实这样的问题在RC模式下,要么是简单update问题,要么是insert造成的主键和唯一键检查唯一性时出现问题。...下面以主键问题为列子进行分析一下可能出现的情况。...update  where条件更新为主键,锁结构出现在单行主键上,辅助索引包含隐含锁结构,当前读RC非唯一索引模式没有GAP锁, insert  插入印象锁,主键和辅助索引上会出现隐含锁结构, 但是在RC...testlll set name='gaopeng1' where id=24;(堵塞) 死锁 锁结构: ---TRANSACTION 322809, ACTIVE 30 sec starting...update testlll set name='gaopeng1' where id=22;(堵塞) 死锁 这种情况比较简单不打印出锁结构 情况3 insert insert TX1:

    1.5K21

    MySQL 死锁 Debug 日志:订单系统 update 死锁的排查与解决方案

    以下为相关表结构示例(非订单表,但索引特性具有参考价值): sql CREATE TABLE `user` ( `id` int NOT NULL AUTO_INCREMENT COMMENT '主键...死锁排查全流程 在订单系统等高频并发场景中,MySQL 死锁往往像隐藏的定时炸弹,可能导致交易失败、用户投诉等连锁问题。掌握一套标准化的排查流程,能帮助我们快速定位根因并恢复服务。...二、定位日志:精准捕获死锁现场 找到异常信号后,下一步是获取死锁发生时的详细日志。MySQL 提供了两种关键方式记录死锁信息,需根据死锁频率选择合适方案。 1....改为 “唯一索引 + 主键” 组合(如user_id+order_id唯一索引),可将锁范围精确到单行。 复合索引顺序:遵循 “等值条件放前面,范围条件放后面” 原则。...此时需在应用层捕获 MySQL 的1213 错误码(死锁错误),实现智能重试机制。

    1.3K10

    Mysql Innodb 锁机制 select * from table where?insert?delete?update?3个insert的死锁2个update的死锁3个以上delete的死

    ,对主键加锁, 加锁的数据行数会受到Mysql是否支持Index Condition PushDown而影响(Mysql 5.6支持ICP),加锁的数量可能远远大于满足条件的记录数量 这里需要加两次锁的原因是...2个update的死锁 事务A 事务B begin; begin; update deadlocktest force index(I_b) set e = sleep(5) where b>0;...; try restarting transaction Rows matched: 4  Changed: 4  Warnings: 0 两个update事务,加锁顺序不一样导致的死锁 InnoDb...的行锁是对索引加锁的,对扫描的行边扫描边加锁,如果走的是二级索引(非聚簇索引)除了需要对二级索引加锁外,还需要根据二级索引里面的主键信息扫描主键的聚簇索引,对主键加锁 3个以上delete的死锁 事务A...3个delete的死锁比较难以复现,我是利用如下脚本完成的 MY_DB="mysql -hxxx -Pxxx -uxxx -pxxx" while : do echo "use test;begin;

    2.1K80

    Mysql查询语句使用select.. for update导致的数据库死锁分析

    如果要求更智能,oracle支持for update skip locked跳过锁区域,这样能不等待马上查询没有被锁住的下一个30条记录。 下面说下mysql for update导致的死锁。...经过分析,mysql的innodb存储引擎实务锁虽然是锁行,但它内部是锁索引的,根据where条件和select的值是否只有主键或非主键索引来判断怎么锁,比如只有主键,则锁主键索引,如果只有非主键,则锁非主键索引...但同样的select .. for update语句怎么就死锁了呢?...同样的sql语句查询条件和结果顺序都一致,按理不会导致一个锁了主键索引,等待锁非主键索引,另外一个锁了非主键索引,等待主键索引导致的死锁。...我们项目出现死锁,就是这个原理,一条sql语句先锁主键索引,再锁非主键索引;另外一条sql语句先锁非主键索引,再锁主键索引。

    5.6K10

    MySql 死锁

    死锁是指两个或多个事务在同一资源上相互占用,并请求锁定对方占用的资源,从而导致恶性循环的现象。当多个事务视图以不同的顺序锁定资源时,就可能产生死锁。多个事务同时锁定同一个资源,也会产生死锁。...UPDATE StockPrice SET high = 20.12 WHERE stock_id = 3 and date = '2002-05-02'; UPDATE StockPrice SET...,接着每个事务都尝试去执行第二条UPDATE语句,却发现该行已经被对方锁定,然后那个事务都等待对方释放锁,同时又持有对方需要的锁,则陷入死循环。...除非有外部因素介入才可能解除死锁。 死锁发生以后,只有部分或者完全回滚其中一个事务,才能打破死锁。对于事务型的系统,这是无法避免的,所以应用程序在设计时必须考虑如何处理死锁。...大多数情况下只需要重新执行因死锁回滚的事务即可。

    2K10

    讲讲insert on duplicate key update 的死锁坑

    当然如果你对锁不是很熟悉的话你可以先看我的这两篇文章看一下数据库锁的基础知识: 为什么开发人员必须要了解数据库锁:和记一次神器的mysql死锁排查 2.问题分析 数据库代码如下: CREATE TABLE...之前没有遇到过insert出死锁的情况,所以当时觉得是on dpulicate key update导致的。...一般的死锁日志都是由两个事务导致的,所以会给予一定的迷惑性,其实大部分的死锁都是由两个以上的事务导致的,这次其实也不例外,这其实是mysql的一个bug,https://bugs.mysql.com/bug.php...在 https://bugs.mysql.com/bug.php?...我们最后使用的就是这个方法,因为ON DUPLICATE KEY UPDATE 这个在代码中的确是没有必要 在数据库表中只建立主键,不建立其他唯一索引。

    24.4K41

    Mysql资料 主键

    表中的任何列都可以作为主键,只要它满足以下条件: 1、任何两行都不具有相同的主键值 2、每个行都必须具有一个主键值(主键列不允许NULL值) 除MySQL强制实施的规则外,应该坚持的几个普遍认为的最好习惯为...: 1、不更新主键列的值 2、不重用主键列的值 3、不在主键列中使用可能会更改的值(例如,如果使用一个名字作为主键以标识某个供应商,应该供应商合并和更改其名字时,必须更改这个主键) 总之:不应该使用一个具有意义的...这就要求同一个叶子节点内(大小为一个内存页或磁盘页)的各条数据记录按主键顺序存放,因此每当有一条新的记录插入时,MySQL会根据其主键将其插入适当的节点和位置,如果页面达到装载因子(InnoDB默认为15...2、.如果使用非自增主键(如果身份证号或学号等),由于每次插入主键的值近似于随机,因此每次新纪录都要被插到现有索引页得中间某个位置: 此时MySQL不得不为了将新记录插到合适位置而移动数据,甚至目标页面可能已经被回写到磁盘上而从缓存中清掉...如果没有显式地在表定义时指定主键,InnoDB存储引擎会为每一行生成一个6字节的ROWID,并一次作为主键。 mysql 在频繁的更新、删除操作,会产生碎片。而含碎片比较大的表,查询效率会降低。

    6.7K20

    MySQL的主键详解

    表中的任何列都可以作为主键,只要它满足以下主键值规则条件: 任两行不具相同的主键值 每行都必须具有一个主键值(主键列不允许NULL) 这里的规则是MySQL本身强制实施的。...除MySQL强制实施的规则外,还应该坚持的最佳实践: 不更新主键列中的值 不重用主键列的值 不在主键列中使用可能会更改的值 例如,如果使用一个名字作为主键以标识某个供应商,当该供应商合并和更改其 名字时...,必须更改这个主键) 联合主键 好处 可以直观的看到某个重复字段的记录条数 主键A跟主键B组成联合主键 主键A跟主键B的数据可以完全相同,联合就在于主键A跟主键B形成的联合主键是唯一的。...联合主键体现在多个表上,复合主键体现在一个表中的多个字段。 复合主键 主键通常定义在表的一列上,但这并不是必需的,也可使用多个列作为主键。...表的主键含有一个以上的字段组成,不使用无业务含义的自增id作为主键 将多个字段设置为主键,形成复合主键,这多个字段联合标识唯一性,其中,某几个主键字段值出现重复是没有问题的,只要不是有多条记录的所有主键值完全一样

    8K20

    MySQL主键设计盘点

    主键设计和应用原则 除了满足MySQL强制实施的规则(主键不可重复;一行中主键不可为空)之外,主键的设计和应用应当还遵守以下公认的原则: 不更新主键列中的值; 不重用主键列的值; 不在主键列中使用可能会更改的值...3、ID作为主键时在特定的环境会存在一些问题,比如需要排序的时候——UUID是无序的。 4、MySQL官方有明确的建议主键要尽量越短越好,36个字符长度的UUID不符合要求。...5、对MySQL索引不利:作为数据库主键,在InnoDB引擎下,UUID的无序性可能会引起数据位置频繁变动,严重影响性能。...关于MySQL 使用自增ID主键和UUID 作为主键的性能比较可以查看参考【8】。 结论: 1、uuid做主键适用于小规模分布式架构用。...结论: 用自建的id生成器做主键适用于大规模分布式架构 参考: 【1】:红心李 :MySQL主键设计 【2】:Uncle Nucky :MySQL数据库主键设计原则 【3】:ellis:设计套路:Mysql

    6.7K30

    MySQL主键约束使用

    MySQL主键约束是一种用于确保表中每行数据的唯一性的限制。每个表只能有一个主键,它可以是一个或多个列。创建表时添加主键约束在创建表时添加主键约束,需要在列名后面添加关键字"PRIMARY KEY"。...主键约束和自增列通常情况下,主键约束通常与自增列一起使用。自增列是指在插入新行时,自动为该行分配一个唯一的值。在MySQL中,可以使用AUTO_INCREMENT关键字来创建自增列。...这意味着在插入数据时,无需提供"id"列的值,MySQL会自动为其分配一个唯一的值。示例假设有一个用户表,其中包含以下列:id、name和email。...如果要更新用户的信息,可以使用UPDATE语句。...例如,以下是如何更新名为"John"的用户的电子邮件地址的示例:UPDATE usersSET email = 'new_email@example.com'WHERE name = 'John';在上面的示例中

    5.2K20
    领券