mysql中Update未加索引导致的微服务模块不可用

 更新时间:2023年06月15日 10:00:56   作者:Cleaner  
本文主要介绍了mysql中Update未加索引导致的微服务模块不可用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

前言

阅读本文,你可以收获:

  • 线上问题定位和排查思路
  • Docker 和 MySQL 相关命令使用
  • MySQL 锁和索引相关知识学习

现象

开发环境一个微服务模块所有接口请求报错,对应页面无法访问。其他未涉及到该模块的接口和页面访问正常。

最近未更新过该服务,之前该服务也没有发生过不可用的情况。

错误排查

根据所观察到的现象,加上简单思考判断,可以确定是单个服务出现故障,而且大概率是服务运行一段时间后出现的问题,具体原因尚不清楚。

查看日志

日志是我们排查问题时的第一个入口,根据日志信息,可以进一步定位问题。

登陆到远程服务器,执行如下命令,查看容器日志。

docker ps // 查看容器 id
docker logs -f --tail 2000 容器id     // 查看容器最后2000行日志

日志中显示的报错信息如下

org.springframework.jdbc.CannotGetJdbcConnectionException: Failed to obtain JDBC Connection; nested exception is java.sql.SQLTransientConnectionException: HikariPool-1 - Connection is not available, request timed out after 30000ms.

报错信息显示连接池请求数据库连接超时,有几种可能的原因会导致该错误:

1、网络或数据库故障,这也是最先被排除的原因,因为其他微服务运行正常,说明网络连接没问题、数据库也没故障宕机。

2、连接池配置不足,因为业务请求量并不大,也查看了连接池配置,并无问题,因此这种原因可能性较小,但不排除;

3、连接池最大活跃连接数达到了上限,连接池的配置无问题,但因为异常原因导致了连接数达到了上限,这个原因可能性相对来说最高,但还要观察数据库的运行情况,收集更多信息才能进行下一步判断。

连接数据库

information_schema 数据库下有几张表可以帮助我们收集数据库的运行情况。

查看当前数据库运行的所有事务,确认是否有大事务长时间持有数据库连接。表 INNODB_TRX 记录了当前正在运行的事务信息,包括事务 ID、事务状态、事务开始时间、锁等待时间等。

// 查看当前运行的所有事务
select * from information_schema.INNODB_TRX;

查询结果如图。发现大量事务处于 LOCK WAIT 状态,只有一个事务处于 RUNNING 状态,被阻塞的事务都是在执行更新同一张表中的记录操作。

ba585b0c760dc1b474202c3cae27dd6c.png

进一步确认,查看当前数据库出现的锁信息。表 INNODB_LOCKS 记录了当前被锁定的对象以及相关的锁信息,包括事务 ID、锁类型、锁定模式、锁定对象等。注意 MySQL 8.0 版本之后没有此表

// 当前出现的锁
select * from infromation_schema.INNODB_LOCKS;
// MySQL 8.0之后执行下面语句
select * from performance_schema.data_locks;

查询结果如图。锁的记录数正好对应上面查询的事务数,并且都持有 X 锁(排他锁)

image-20221222142135836.png

问题定位&解决

至此,错误产生的原因已经明确:数据库中大量事务占用连接资源并处于阻塞状态,连接池最大连接数达到上限,无法获取新的连接来处理请求。只要找到事务阻塞的原因并且解决,那么问题就解决了。

查看事务执行的 SQL 语句和对应的表结构,发现 where 条件后的字段没有添加索引。更新导致了锁表!!!

解决:为字段加上索引(一个索引引发这么大问题!)。

alter table 表名 add index 索引名(列名)

问题

为什么服务运行了一段时间后,出现了这个问题?

服务刚运行的时候,连接池资源是够用的,业务也能正常使用。但是这条更新语句调用频繁,会不断产生新连接执行更新操作,然而同一时刻只能有一个事务执行(锁表),其他事务都会阻塞。阻塞的事务越来越多,事务又占有连接资源,可用的连接数越来越少,服务运行一段时间之后,就出现了问题。

update 没加索引,为什么会锁表?

数据库的事务隔离级别是“可重复读”。在 InnoDB 事务中,对记录加锁的基本单位是 next-key 锁(记录锁 + 间隙锁)。当 update 语句的 where 条件没有使用索引时,需要扫描整个表来找到满足 WHERE 条件的记录,于是就会对所有记录加上 next-key 锁,相当于把整个表锁住了。

update 加上索引,能避免锁表吗?

如果条件字段是唯一索引,next-key 锁会退化成记录锁,只会锁一条记录,不会锁表。

如果条件字段不是唯一索引,得看这条语句在执行过程中,优化器最终选择的是索引扫描,还是全表扫描,如果走了全表扫描,同样还是会锁表。

到此这篇关于mysql中Update未加索引导致的微服务模块不可用的文章就介绍到这了,更多相关mysql Update未加索引内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • MySQL存储过程的传参和流程控制示例讲解

    MySQL存储过程的传参和流程控制示例讲解

    这篇文章主要介绍了MySQL存储过程的传参和流程控制示例讲解, repeat和Loop区别是repeat有自己退出循环的语句until,Loop使用的是if判断语句,本文结合示例代码详细讲解,需要的朋友可以参考下
    2023-02-02
  • MySQL用户权限设置保护数据库安全

    MySQL用户权限设置保护数据库安全

    MySQL用户权限设置是保护数据库安全的重要措施之一。通过为用户设置不同的权限,可以控制用户对数据库的访问能力,包括读取、修改、删除、创建等操作。合理设置用户权限可以避免误操作、非法访问等安全问题
    2023-05-05
  • mysql如何让左模糊查询也能走索引

    mysql如何让左模糊查询也能走索引

    这篇文章主要介绍了mysql如何让左模糊查询也能走索引,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11
  • mysql8.0 JSON_CONTAINS的使用说明

    mysql8.0 JSON_CONTAINS的使用说明

    这篇文章主要介绍了mysql8.0 JSON_CONTAINS的使用说明,具有很好的参考价值,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-07-07
  • MySQL的使用中实现读写分离的教程

    MySQL的使用中实现读写分离的教程

    这篇文章主要介绍了MySQL的使用中实现读写分离的教程,文中分别介绍了mysql-proxy与mysqlnd_ms的使用,需要的朋友可以参考下
    2015-12-12
  • MySQL事务与锁实例教程详解

    MySQL事务与锁实例教程详解

    事务是指满足ACID特性的的一组操作,可以通过Commit提交事务,也可以也可以通过Rollback进行回滚。会存在中间态和一致性状态,也是真正在数据库表中存在的状态
    2022-11-11
  • MySQL数据表合并去重的简单实现方法

    MySQL数据表合并去重的简单实现方法

    这篇文章主要给大家介绍了关于MySQL数据表合并去重的简单实现方法,文中通过示例代码介绍的非常详细,对大家学习或者使用MySQL具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-05-05
  • Windows7下如何在命令行使用MySQL

    Windows7下如何在命令行使用MySQL

    这篇文章主要介绍了Windows7下如何在命令行使用MySQL的相关资料,需要的朋友可以参考下
    2015-12-12
  • MySQL日志管理详解

    MySQL日志管理详解

    这篇文章主要介绍了MySQL日志管理详解,本文讲解了日志种类、日志功能、MySQL中日志相关常用的服务器变量说明等内容,需要的朋友可以参考下
    2015-07-07
  • MySQL定期分析检查与优化表的方法小结

    MySQL定期分析检查与优化表的方法小结

    听DBA的人说,相比oracle,MySQL就是一个玩具级别的数据库,在网易门户中,DBA基本很少去管理到MySQL的东西,所以我们产品使用到的MySQL的一些配置和优化还是需要我们开发人员自己动手,下面就简单介绍一下实用的定期优化方法
    2014-06-06

最新评论