为什么MySQL没有负载,但交易却跑不动?

news2025/1/15 20:02:43

在这里插入图片描述
在MySQL的数据库中,我们有时会发现MySQL数据库明明没有负载,CPU、硬盘、内存和网络等资源都很空闲,但很多SQL都pending在哪儿,MySQL数据库无法处理交易。这是怎么回事呢?

在数据库系统中出现这种情况通常是锁竞争造成的,MySQL数据库更加容易出现这种情况,因为它的存储层和服务层是分开的,我们来看锁竞争在MySQL 5.7和8.0里的表现和解决办法。

5.7版本

查询锁竞争

在 MySQL 8.0 之前,必须SET GLOBAL innodb_status_output_locks=ON后才能在SHOW ENGINE INNODB STATUS中查到数据锁,例如下面这个事务:

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from t1 where intcol1=0 for update;
...
900 rows in set (0.00 sec)

在SHOW ENGINE INNODB STATUS中查到

---TRANSACTION 7827, ACTIVE 11 sec
222 lock struct(s), heap size 24784, 5720 row lock(s)
MySQL thread id 9912, OS thread handle 139967683151616, query id 11123 localhost root
TABLE LOCK table `mysqlslap`.`t1` trx id 7827 lock mode IX
RECORD LOCKS space id 25 page no 37 n bits 1056 index in_1 of table `mysqlslap`.`t1` trx id 7827 lock_mode X

...

修改了900行,却锁住了5720行。查询space id为25对应的对象:

mysql> select * from information_schema.INNODB_SYS_DATAFILES where space=25;
+-------+--------------------+
| SPACE | PATH               |
+-------+--------------------+
|    25 | ./mysqlslap/t1.ibd |
+-------+--------------------+
1 row in set (0.00 sec)

在另外一个session里执行

mysql> update t1 set intcol1=1 where intcol1=0;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

查询锁的情况


mysql> select * from information_schema.innodb_lock_waits;
+-------------------+-------------------+-----------------+------------------+
| requesting_trx_id | requested_lock_id | blocking_trx_id | blocking_lock_id |
+-------------------+-------------------+-----------------+------------------+
| 7829              | 7829:25:4:2       | 7827            | 7827:25:4:2      |
+-------------------+-------------------+-----------------+------------------+
1 row in set, 1 warning (0.00 sec)

mysql> select * from information_schema.innodb_locks;
+-------------+-------------+-----------+-----------+------------------+-----------------+------------+-----------+----------+----------------+
| lock_id     | lock_trx_id | lock_mode | lock_type | lock_table       | lock_index      | lock_space | lock_page | lock_rec | lock_data      |
+-------------+-------------+-----------+-----------+------------------+-----------------+------------+-----------+----------+----------------+
| 7829:25:4:2 | 7829        | X         | RECORD    | `mysqlslap`.`t1` | GEN_CLUST_INDEX |         25 |         4 |        2 | 0x000000000200 |
| 7827:25:4:2 | 7827        | X         | RECORD    | `mysqlslap`.`t1` | GEN_CLUST_INDEX |         25 |         4 |        2 | 0x000000000200 |
+-------------+-------------+-----------+-----------+------------------+-----------------+------------+-----------+----------+----------------+
2 rows in set, 1 warning (0.00 sec)

查询阻塞的线程:

SELECT b.trx_mysql_thread_id             AS 'blocked_thread_id' 
      ,b.trx_query                      AS 'blocked_sql_text' 
      ,c.trx_mysql_thread_id             AS 'blocker_thread_id'
      ,c.trx_query                       AS 'blocker_sql_text'
      ,( Unix_timestamp() - Unix_timestamp(c.trx_started) ) 
                              AS 'blocked_time' 
FROM   information_schema.innodb_lock_waits a 
    INNER JOIN information_schema.innodb_trx b 
         ON a.requesting_trx_id = b.trx_id 
    INNER JOIN information_schema.innodb_trx c 
         ON a.blocking_trx_id = c.trx_id 
WHERE  ( Unix_timestamp() - Unix_timestamp(c.trx_started) ) > 4; 
+-------------------+-----------------------------------------+-------------------+------------------+--------------+
| blocked_thread_id | blocked_sql_text                        | blocker_thread_id | blocker_sql_text | blocked_time |
+-------------------+-----------------------------------------+-------------------+------------------+--------------+
|              9921 | update t1 set intcol1=1 where intcol1=0 |              9917 | NULL             |          782 |
+-------------------+-----------------------------------------+-------------------+------------------+--------------+
1 row in set, 1 warning (0.00 sec)


根据线程号查询执行的SQL

SELECT a.sql_text, 
       c.id, 
       d.trx_started 
FROM   performance_schema.events_statements_current a 
       join performance_schema.threads b 
         ON a.thread_id = b.thread_id 
       join information_schema.processlist c 
         ON b.processlist_id = c.id 
       join information_schema.innodb_trx d 
         ON c.id = d.trx_mysql_thread_id 
where c.id=9917
ORDER  BY d.trx_started\G
*************************** 1. row ***************************
   sql_text: select * from t1 where intcol1=0 for update
         id: 9917
trx_started: 2023-05-26 13:24:59
1 row in set (0.00 sec)

注意这里查询出的SQL是阻塞事务的最后一条SQL,并不一定是阻塞的源头。

解决锁竞争

解决方法是针对where中的条件增加索引,使MySQL服务层的过滤能在存储层完成,例如

mysql> create index in_1 on t1(intcol1);
Query OK, 0 rows affected (0.04 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> show create table t1\G
*************************** 1. row ***************************
       Table: t1
Create Table: CREATE TABLE `t1` (
  `intcol1` int(32) DEFAULT NULL,
  `intcol2` int(32) DEFAULT NULL,
  `charcol1` varchar(128) DEFAULT NULL,
  `charcol2` varchar(128) DEFAULT NULL,
  `charcol3` varchar(128) DEFAULT NULL,
  KEY `in_1` (`intcol1`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)


再锁住同样的行

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from t1 where intcol1=0 for update;
...
900 rows in set (0.00 sec)

在SHOW ENGINE INNODB STATUS中查到

---TRANSACTION 7841, ACTIVE 15 sec
155 lock struct(s), heap size 24784, 1801 row lock(s)
MySQL thread id 9917, OS thread handle 139966608627456, query id 11227 localhost root
TABLE LOCK table `mysqlslap`.`t1` trx id 7841 lock mode IX
RECORD LOCKS space id 25 page no 37 n bits 1056 index in_1 of table `mysqlslap`.`t1` trx id 7841 lock_mode X


...

被锁住的记录从之前的5720条减少到1801条。

有索引后执行计划也不同,加索引之前的执行计划

mysql> explain select * from t1 where intcol1=0 for update;
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | t1    | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 6143 |    10.00 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

加了索引后的执行计划是:

mysql> explain select * from t1 where intcol1=0 for update;
+----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref   | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | t1    | NULL       | ref  | in_1          | in_1 | 5       | const |  900 |   100.00 | NULL  |
+----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)


对比一下可以发现后者的Extra字段中没有“Using where”,因为过滤再存储层已经完成了。

生产中可以先 select 出 主键id,再用 主键id 去 update

8.0版本

从 MySQL 8.0 开始,performance_schema.data_locks显示 InnoDB 数据锁。具体参见拙作《MySQL 8.0运维于优化》第18章第3节“优化索引”。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1149262.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C#,数值计算——Globals的计算方法与源程序

1 文本格式 using System; using System.Text; namespace Legalsoft.Truffer { public static partial class Globals { //const int FLT_RADIX 2; //const int DBL_MANT_DIG 53; //const int INT_DIGITS 32; //const float FLT_…

精密空调监控方法,让你一次全学会!

随着科技的迅猛发展,越来越多的领域和行业对温度和湿度等环境参数的高度控制需求日益增长。无论在哪里,对精密空调的依赖都在不断增加。 然而,要确保这些系统的高效运行和监测已经变得愈发复杂。为了解决这些挑战,精密空调监控系统…

【java学习—十】TreeSet集合(5)

文章目录 1. TreeSet1.1. 自然排序1.2. 定制排序 1. TreeSet TreeSet 是 SortedSet 接口的实现类, TreeSet 可以确保集合元素处于排序状态。     TreeSet 支持两种排序方法:自然排序和定制排序。默认情况下, TreeSet 采用自然排序。 1.1.…

java项目之学校招生信息网(ssm)

项目简介 学校招生信息网实现了以下功能: 管理员:个人中心、学生管理,党员风采管理,校园之家管理,师资队伍管理,院系简介管理,专业简介管理,录取信息管理、学生录取管理、系统管理…

【ChatGPT瀑布到水母】AI 在驱动软件研发的革新与实践

这里写目录标题 前言内容简介作者简介专家推荐读者对象目录直播预告 前言 计算机技术的发展和互联网的普及,使信息处理和传输变得更加高效,极大地改变了金融、商业、教育、娱乐等领域的运作方式。数据分析、人工智能和云计算等新兴技术,也在不…

Egg.js 中 Controller 的使用

如果需要了解Controller ,就得知道什么是mvc。 MVC概述 什么是mvc,这个概念,我相信绝大部分人肯定是了解的。MVC是模型(model)- 视图(view)- 控制器(controller)的缩写…

git跳过用户名密码验证,以及配置credential-helper

平时我们在使用git命令时,如果使用http方式拉取代码每次都需要使用填写用户名和密码,非常的麻烦。 如何才能绕过每次繁琐的填充? 如果想要绕过git的交互方式,首先需要了解git的密码存储机制。 git使用的使用是一种名叫**[credential helpe…

ssm搭建后404的错误

spring、mybatis 的配置文件一般不会出错(注解扫描路径要涵盖 controller层),controller 层 url 一般也不会写错,出现404,更容易忽略的是 文件路径位置。 首先是 idea 提示 servlet-mapping 找不到 , 我这里显然是有的…

Java-PriorityQueue 优先队列(结构与用法)

1. 数据结构 1.1 2.Java使用 2.1 核心要点 PriorityQueue是一个无限制的队列,并且动态增长。默认情况下,优先级队列的对象按自然顺序排序。PriorityQueue 不是线程安全的。多线程情况下可以使用PriorityBlockingQueue。 2.2 构造函数 PriorityQueu…

如何去掉Word文档中蓝色和红色波浪线

在Word2013文档中有些文字或者字母的下面会出现一些红色或蓝色的波浪线,这是因为Word会自动检查文档中拼写和语法错误所造成的,那么如何去掉这些蓝色红色的波浪线呢?下面就跟大家分享一下方法。 工具/原料 Word2013 方法/步骤 1 首先打开一个…

Widget必须在GUI线程中创建

背景:miniblink的vip版本,下载功能是独立线程,我希望在下载后弹出窗口,就在其中创建了QWidget子类对象。然后出现了上面的错误。 解决方法: 使用信号和槽来处理。 具体来讲,在独立线程中创建QObject子类…

【波形图】LabVIEW中的波形图和波形图表有什么区别?

波形图和波形图表在显示和更新数据的方式上有所不同。 波形图可接受各种类型的数据阵列,例如数组,波形或动态数据。波形图在接收到数据后将立即绘制所有接收到的数据点 。波形图不接受单点值。当您将包含数据点的数组连接到波形图时,波形图会…

深度学习中的FPN详解

深度学习入门小菜鸟,希望像做笔记记录自己学的东西,也希望能帮助到同样入门的人,更希望大佬们帮忙纠错啦~侵权立删。 目录 一、FPN提出原因 二、FPN的参考思想 三、特征金字塔 四、FPN具体思路 一、FPN提出原因 卷积网络中,深层网…

IDEA 使用技巧

文章目录 语言支持简化编写 有问题,可暂时跳过 个人常用快捷键插件主题插件功能插件 碰到过的问题 除了一些在Linux上用vim开发的大佬,idea算是很友好的集成开发工具了,功能全面,使用也很广泛。 记录一下我的 IDEA 使用技巧&#…

省钱兄短剧短视频视频滑动播放模块源码支持微信小程序h5安卓IOS

# 开源说明 开源省钱兄短剧系统的播放视频模块(写了测试弄了好久才弄出来、最核心的模块、已经实战了),使用uniapp技术,提供学习使用,支持IOSAndroidH5微信小程序,使用Hbuilder导入即可运行 #注意&#xff…

1.2 OSI安全架构

思维导图: 1.2 OSI安全架构 为了有效评估组织的安全需求并选择合适的安全产品和政策,安全管理员需要系统化地定义安全需求并描述满足这些需求的措施。这在集中式数据处理环境下就已经很困难,而在今天使用的局域网和广域网中更是如此。 OSI安…

Undefined reference错误处理及Linux设置动态链接库so的默认搜索路径

文章目录 1 问题的提出2 问题的分析3 问题的解决3.1 Windows的VS修改配置属性3.2 Linux系统里添加搜索路径json在/usr/llib目录中libcryto.so在/usr/lib64文件夹中 Linux设置动态链接库so的默认搜索路径方法一:修改 ld.so.conf 文件方法二:修改环境变量方…

3分钟搞定腾讯云轻量应用服务器和云服务器的区别

腾讯云轻量服务器和云服务器有什么区别?为什么轻量应用服务器价格便宜?是因为轻量服务器CPU内存性能比云服务器CVM性能差吗?轻量应用服务器适合中小企业或个人开发者搭建企业官网、博客论坛、微信小程序或开发测试环境,云服务器CV…

CentOS停更沉寂,RHEL巨变限制源代:Docker容器化技术的兴起助力操作系统新格局

一、概述 操作系统是计算机系统的核心软件,它管理和控制着计算机的硬件和软件资源,为用户和应用程序提供了一个统一、高效、安全的运行环境。操作系统的发展历史也是计算机技术的发展历史的重要组成部分,它见证了计算机从单机到网络&#xf…

GaussDB SQL基础语法示例-常见的条件表达式

目录 一、前言 二、条件表达式的概念及GaussDB中的常见条件表达式 三、GaussDB中常用的条件表达式(语法 示例) 1、CASE表达式 2、DECODE表达式 3、COALESCE表达式 4、NULLIF表达式 5、GREATEST/ LEAST表达式 6、NVL表达式 四、小结 一、前言 …