锋盈数科-知识库 Logo
首页
软件开发
计算机基础
Hello Halo
新手必读
关于本知识库
登录 →
锋盈数科-知识库 Logo
首页 软件开发 计算机基础 Hello Halo 新手必读 关于本知识库
登录
  1. 首页
  2. 软件开发
  3. 【MySQL系列】记插入产生的死锁问题

【MySQL系列】记插入产生的死锁问题

0
  • 软件开发
  • 发布于 2024-07-29
  • 12 次阅读
黄健
黄健

原文链接:https://blog.csdn.net/qyj19920704/article/details/140210085

一.问题背景

1.事务信息查询

SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX WHERE trx_query LIKE '%student%';

2.分析

从提供的日志信息来看,这是一个数据库事务(trx_id: 4165875)的状态报告,它显示了事务的一些关键信息。事务目前处于LOCK WAIT状态,意味着它正在等待获取一个它需要的锁。

以下是一些可能导致死锁的原因分析:

事务等待锁:trx_state: LOCK WAIT表明事务正在等待一个锁。trx_wait_started给出了等待开始的时间。

锁请求:trx_requested_lock_id显示了事务正在请求的锁的 ID,这有助于进一步分析锁请求的具体情况。

事务权重:trx_weight: 7可能表示事务的权重,这可能影响它获取锁的优先级。

MySQL 线程 ID:trx_mysql_thread_id: 9168表示与该事务关联的 MySQL 线程 ID。

插入操作:trx_query显示了一个INSERT语句,事务正在尝试插入数据到student表中。

锁定的行数:trx_rows_locked: trx_rows_modified: 5表明事务已经锁定了 5 行并修改了它们。

隔离级别:trx_isolation_level: REPEATABLE READ表示事务使用的是可重复读隔离级别,这可能导致更多的锁争用和死锁。

唯一性检查和外键约束:trx_unique_checks: 1和trx_foreign_key_checks: 1表示事务正在执行唯一性检查和外键约束检查,这可能会导致锁等待。

锁结构:trx_lock_structs: 2可能表示事务持有两个锁结构。

锁内存使用:trx_lock_memory_bytes: 1128显示了事务使用的锁内存字节数。

并发票据:trx_concurrency_tickets可能表示事务的并发票据数量,这可能影响其并发能力。

警告信息:日志末尾的1 row in set, 1 warning (0.04 sec)表明在执行过程中有一个警告,但没有提供警告的具体内容,这可能是导致死锁的一个线索。

二.分析步骤

1.表信息

CREATE TABLE student (

  doc_id varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,

  name varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,

  file_id varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',

  PRIMARY KEY (`doc_id`),

  UNIQUE KEY doc_id_key (`name`,`doc_id`),

  KEY file_id_idx (`file_id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

2.分析过程

根据您提供的student表的定义,我们可以分析一些可能导致死锁的原因:

唯一性约束:UNIQUE KEY doc_id_key (name,doc_id) 表示name和doc_id的组合必须是唯一的。如果在插入操作中尝试插入一个已经存在的name和doc_id组合,将会导致违反唯一性约束,从而触发锁等待。

主键约束:PRIMARY KEY (doc_id) 表示doc_id是表的主键,必须是唯一的。如果尝试插入一个已经存在的doc_id,同样会触发锁等待。

索引:KEY file_id_idx (file_id) 是一个索引,虽然它不直接导致唯一性冲突,但如果其他事务持有该索引的锁,当前事务在尝试插入数据时可能需要等待。

并发插入:如果多个事务同时尝试插入具有相同name和不同doc_id的记录,它们可能会互相等待对方释放锁,从而导致死锁。

隔离级别:事务使用的是REPEATABLE READ隔离级别,这可能会导致更多的锁争用和死锁,因为在这个隔离级别下,事务会锁定读取到的所有行,以防止其他事务修改它们。

锁的粒度:InnoDB 存储引擎使用的是行级锁,但在某些情况下,如在插入大量数据时,可能会升级为表级锁,这增加了死锁的可能性。

事务大小:如果事务包含了大量的插入操作,可能会导致锁的竞争更加激烈,从而增加死锁的风险。

3.策略建议

为了解决死锁问题,可以考虑以下策略:

确保插入的数据不违反任何唯一性约束。

优化事务的大小,避免大事务导致的锁竞争。

考虑使用更低的隔离级别,如READ COMMITTED,以减少锁的持续时间。

使用更细粒度的锁,如乐观锁,来减少锁争用。

分析并优化索引,以减少索引导致的锁等待。

在设计表结构时,考虑使用更合理的字段和约束,以减少潜在的死锁风险。

4.死锁可能得原因

根据提供的student表结构和事务日志信息,以下是可能导致死锁的原因:

违反唯一性约束:事务尝试插入一个具有已存在的name和doc_id组合的记录,由于表中有一个唯一索引doc_id_key,这将导致违反唯一性约束,事务将等待其他事务释放锁。

锁升级:如果事务开始时只锁定了行级锁,但在执行过程中需要锁定更多的行或整个表,可能会发生锁升级。如果其他事务已经持有相关行或表的锁,当前事务将等待这些锁被释放。

锁的顺序:如果两个或多个事务按照不同的顺序请求锁,它们可能会互相等待对方持有的锁,从而导致死锁。例如,如果事务 A 首先锁定了doc_id为 X 的记录,然后尝试锁定name为 Y 的记录,而事务 B 首先锁定了name为 Y 的记录,然后尝试锁定doc_id为 X 的记录,就会发生死锁。

长事务:长时间运行的事务持有锁不放,可能导致其他事务长时间等待,增加了死锁的风险。

高并发:在高并发环境下,许多事务同时请求相同的资源,增加了死锁的可能性。

隔离级别:使用REPEATABLE READ隔离级别可能会导致更多的锁争用,因为在这个级别下,事务会锁定读取到的所有行,以防止其他事务修改它们。

锁的兼容性问题:如果事务请求的锁与其他事务持有的锁不兼容,也可能导致死锁。

外键约束:如果KnowledgeDoc表与其他表之间存在外键关系,违反外键约束也可能导致死锁。

标签: #软件开发 1171 #JAVA 991 #新手必读 21
相关文章

万字:支付“核心系统”详解 2024-11-02 15:33

专栏作者:隐墨星辰 \| 主编:陈天宇宙 这篇文章也尝试化繁为简,探寻支付系统的本质,讲清楚在线支付系统最核心的一些概念和设计理念。 虽然支付行业已经过了风头最劲的时光,但跨境支付仍然在蓬勃发展,每年依然有很多新人进入这个行业,这篇文章尝试为这些刚入行的新人提供一点帮助。 文章只介绍一些支付行业十几

资深支付架构师视角:实战从问题定义到代码落地的完整套路 2024-11-02 15:33

前言 今天从一个实际案例入手,介绍站在架构师的角度,如何识别并定义问题,提炼需求,技术方案选型,再到详细设计,最后利用AI的能力协助写出核心的代码,验证与调优。 解决问题存在一定的模式,也可以称之为框架,总结出自己的思考和解题框架,以后再碰到同类型的问题就可以如庖丁解牛一样容易。 很多年前,我写代码

Spring 实现 3 种异步接口 2024-10-18 09:07

大家好,我是苏三~ 如何处理比较耗时的接口? 这题我熟,直接上异步接口,使用 Callable、WebAsyncTask 和 DeferredResult、CompletableFuture等均可实现。 但这些方法有局限性,处理结果仅返回单个值。在某些场景下,如果需要接口异步处理的同时,还持续不断地

重学SpringBoot3-集成Redis(五)之布隆过滤器 2024-10-08 11:24

更多SpringBoot3内容请关注我的专栏:《SpringBoot3》 期待您的点赞👍收藏⭐评论✍ 重学SpringBoot3-集成Redis(五)之布隆过滤器 1. 什么是布隆过滤器? * 基本概念 适用场景 2. 使用 Redis 实现布隆过滤器 * 项目依赖 Redis 配置

设计模式第16讲——迭代器模式(Iterator) 2024-10-08 11:24

一、什么是迭代器模式 迭代器模式是一种行为型设计模式,它提供了一种统一的方式来访问集合对象中的元素,而不是暴露集合内部的表示方式。简单地说,就是将遍历集合的责任封装到一个单独的对象中,我们可以按照特定的方式访问集合中的元素。 二、角色组成 抽象迭代器(Iterator):定义了遍历聚合对象所需的方法

vue2路由和vue3路由区别及原理 2024-10-08 11:24

一、Vue2 与 Vue3 路由的区别 1. 创建路由实例方式的不同 Vue 2 中,通过 Vue.use() 注册路由插件,并通过 new VueRouter() 来创建路由实例。 import Vue from 'vue';import VueRouter from 'vue-router';i

目录

IT 外包服务商

  • 意见投递
  • zyf6619

软件开发应用

主菜单

  • 首页
  • 软件开发
  • 计算机基础
  • Hello Halo
  • 新手必读
  • 关于本知识库
Copyright © 2024 your company All Rights Reserved. Powered by Halo.