首页 > 数据库 >【Mysql 数据库 undo log 文件无限膨胀,性能下降问题解决方案】

【Mysql 数据库 undo log 文件无限膨胀,性能下降问题解决方案】

时间:2024-12-03 14:30:05浏览次数:12  
标签:+-----------------+--------+ NAME Mysql undo innodb mysql log

数据库 undo log 文件无限膨胀,性能下降问题解决方案

1. 问题描述

在 Mysql 数据目录中发现有个 undo 文件非常大,并且持续增长
在这里插入图片描述

  • 并且 History list length 非常大
------------
TRANSACTIONS
------------
Trx id counter 3569860310
Purge done for trx's n:o < 3185146100 undo n:o < 0 state: running but idle
History list length 194564756
LIST OF TRANSACTIONS FOR EACH SESSION:
  • 并且可能会发现同时如下问题:
    • Mysql 的性能在下降,TPS 并不高的情况下 IO wait 非常高,服务器负载也上升。
    • 如果是从库,那么主从复制延迟也会增加。

2. 问题原因

  • 复制延迟会导致从库的 History list length 增加,因为未处理的事务会保留在undo日志中,此时 undo log 就会膨胀。
  • 长查询和事务锁会导致 History list length 增加,因为相关的undo日志无法被及时清理,此时 undo log 就会膨胀。
  • Mysql 写入负载太重
  • 存在失败的垃圾事务,并且无法清理掉。

3. 问题排查过程

  • 使用sys.session或sys.processlist视图来查找活动事务。

    SELECT * FROM sys.session WHERE trx_state IS NOT NULL;

  • 使用 SHOW ENGINE INNODB STATUS; 命令查看InnoDB的状态信息,特别关注 TRANSACTIONS 部分,重点关注History list length , 以及是否存在死锁 。
    在这里插入图片描述

  • SELECT * FROM information_schema.INNODB_TRX; 查看当前正在运行的事务
    在这里插入图片描述

    • 在 show processlist; 中也会发现这个语句!

4. 解决方案

4.1. 清理长时间没有执行完成的事物

kill 247570;

4.2. 检查 innodb_undo_log_truncate 功能是否开启

  • 在MySQL 5.7及更高版本中,可以使用独立的undo tablespace,并通过相关参数来控制undo log的生成和回收。

    • 设置 innodb_max_undo_log_size 可以限制单个undo tablespace文件的大小,当文件大小超过这个阈值时,MySQL会自动触发truncate操作来回收空间。

    • 设置 innodb_purge_rseg_truncate_frequency 参数可以控制回收undo log的频率。

          mysql> show variables like '%undo%';
          +--------------------------+------------+
          | Variable_name            | Value      |
          +--------------------------+------------+
          | innodb_max_undo_log_size | 1073741824 |
          | innodb_undo_directory    | ./         |
          | innodb_undo_log_encrypt  | OFF        |
          | innodb_undo_log_truncate | ON         |
          | innodb_undo_tablespaces  | 2          |
          +--------------------------+------------+
          5 rows in set (0.10 sec)
          ```
      
    • 所以为了尽快收缩 undo 文件,我们可以将 innodb_purge_rseg_truncate_frequency 值调小,提高 purge 线程释放回滚段的频率

      • 例如: SET GLOBAL innodb_purge_rseg_truncate_frequency=32;
  • MySQL8.0 新增支持使用 SQL 语句来管理 undo 表空间
    Oracle/MySQL undo表空间设置自动扩展,如果业务上有跑批量或者大表的DML操作时,引起大事物或针对多张大表关联更新时间较长,可能短时间内会将undo"撑大",Oracle可通过创建一个新的undo,通过在线替换的方式,将膨胀的undo使用drop删除以释放空间。
    MySQL 8.0同样可以使用这种方式来处理,因大事物或长事物引起的undo过大占用空间较多的情况。

    • 示例: /mnt/mysqldata/undo_002 文件膨胀严重,需要清理

      ```sh
       mysql> SELECT NAME, STATE FROM INFORMATION_SCHEMA.INNODB_TABLESPACES WHERE NAME LIKE '%undo%';
       +-----------------+--------+
       | NAME            | STATE  |
       +-----------------+--------+
       | innodb_undo_001 | active |
       | innodb_undo_002 | active |
       +-----------------+--------+
       2 rows in set (0.05 sec)
       # 创建一个新的
       create undo tablespace undo_003 add datafile '/mnt/mysqldata/undo_003.ibu';
       
       # 查看三个 undo 文件状态
       cd /mnt/mysqldata
       ll -h
       -rw-r----- 1 mysql mysql 1.1G 2024-03-17 14:58:55 undo_001
       -rw-r----- 1 mysql mysql 110G 2024-11-20 18:34:15 undo_002
       -rw-r----- 1 mysql mysql  10M 2024-11-20 18:34:15 undo_003.ibu
      
       # 手动禁用 innodb_undo_002
       ALTER UNDO TABLESPACE innodb_undo_002 SET INACTIVE;
      
       # 手动设置 innodb_undo_002 inactive 后,undo 表空间被标记为截断,purge 线程会增加返回频率,快速清空并最终截断 undo 表空间,状态变为 empty。(需要等待一段时间)
       mysql> SELECT NAME, STATE FROM INFORMATION_SCHEMA.INNODB_TABLESPACES WHERE NAME LIKE '%undo%';
       +-----------------+--------+
       | NAME            | STATE  |
       +-----------------+--------+
       | innodb_undo_001 | active |
       | innodb_undo_002 | empty  |
       | undo_003        | active |
       +-----------------+--------+
      
       # 最后: empty 状态的 undo 表空间可以重新激活使用
       mysql> ALTER UNDO TABLESPACE innodb_undo_002 SET ACTIVE;
       Query OK, 0 rows affected (0.00 sec)
       
       mysql> SELECT NAME, STATE FROM INFORMATION_SCHEMA.INNODB_TABLESPACES WHERE NAME LIKE '%undo%';
       +-----------------+--------+
       | NAME            | STATE  |
       +-----------------+--------+
       | innodb_undo_001 | active |
       | innodb_undo_002 | active |
       | undo_003        | active |
       +-----------------+--------+
       3 rows in set (0.01 sec)
       ```
      
      • 附录: MySQL8.0 支持删除 undo 表空间(DROP UNDO TABLESPACE xxx;),但前提是该表空间为 empty 状态
        # 先禁用
        mysql> ALTER UNDO TABLESPACE undo_003 SET INACTIVE;
        Query OK, 0 rows affected (0.01 sec)
        mysql> SELECT NAME, STATE FROM INFORMATION_SCHEMA.INNODB_TABLESPACES WHERE NAME LIKE '%undo%';
        +-----------------+--------+
        | NAME            | STATE  |
        +-----------------+--------+
        | innodb_undo_001 | active |
        | innodb_undo_002 | active |
        | undo_003        | empty  |
        +-----------------+--------+
        3 rows in set (0.01 sec)
        
        # 后删除表空间
        mysql> DROP UNDO TABLESPACE undo_003;
        Query OK, 0 rows affected (0.02 sec)
        
        mysql> SELECT TABLESPACE_NAME, FILE_NAME FROM INFORMATION_SCHEMA.FILES WHERE FILE_TYPE LIKE 'UNDO LOG';
        +-----------------+------------+
        | TABLESPACE_NAME | FILE_NAME  |
        +-----------------+------------+
        | innodb_undo_001 | ./undo_001 |
        | innodb_undo_002 | ./undo_002 |
        +-----------------+------------+
        2 rows in set (0.01 sec)
        
        • Undo tablespace是存储undo log的物理空间。
          在MySQL中,可以配置多个undo tablespace,以便更好地管理undo log的存储和回收。

4.3. 终极方案: 若发现按上面的方案执行后,如果 undo log 文件依然不会自动减少,并且 History list length 持续增加。

  • 重启数据库: sudo systemctl restart mysqld

  • 修改隔离级别

     SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED;
    
    • 注意,这个设置是全局的,并且会影响从库上的所有新会话。现有的会话可能会继续使用它们自己的隔离级别设置,直到它们被关闭并重新打开。
  • 检查效果:

          #查看 History list length 是否逐渐减少
          SHOW ENGINE INNODB STATUS;
    
  • 更多参考: Mysql 数据库 History list length 超长

标签:+-----------------+--------+,NAME,Mysql,undo,innodb,mysql,log
From: https://blog.csdn.net/UserFrank/article/details/144213089

相关文章

  • mysql的information_schema数据库包含的表
    1.information_schema 数据库的系统表系统表说明schemata存储数据库的信息,包括名称、字符集、排序规则。tables提供数据库中各个表的信息,包括表类型(如BASETABLE、VIEW)、存储引擎、行格式、行数、创建时间等信息。columns存储关于每个表的列的信息,包括列名、数......
  • Mysql如何实现原子性(MVCC实现原理)
    Mysql如何实现原子性(MVCC实现原理)Mysql实现原子性主要通过一下机制锁MVCC多版本并发控制MVCC的实现原理在介绍MVCC的实现原理之前需要先介绍一下Mysql表中的隐藏字段,以及undo_log版本链以及readview1.Mysql中的隐藏字段Mysql在创建表的时候除了我们所定义的字段......
  • blog.core MemoryCacheExtensions 为空处理
    usingSystem.Collections;usingSystem.Reflection;usingSystem.Reflection.Emit;usingMicrosoft.Extensions.Caching.Memory;namespaceBlog.Core.Common.Caches.Extensions;publicstaticclassMemoryCacheExtensions{#regionMicrosoft.Extensions.Cachin......
  • mySQL数据库自动完整备份 centos
    1#!/bin/bash2#远程地址3dbhost='localhost'4#端口5dbport='3308'6#需要备份的数据库,多个数据库用空格分开7dbnames=("db1""db2""db3""dd4dd5")8#用户名9username='root'10#密码11password=......
  • python 创建mysql数据库脚(执行sql)脚本代码
    安装依赖库mysql-connector-pythonpipinstallmysql-connector-python执行创建数据库的sql脚本代码importmysql.connectorfrommysql.connectorimportErrordefcreate_database(db_name,host_name="192.168.0.33",user_name="root",user_password="SHU......
  • 如何备份 Z-BlogPHP 数据库和文件?
    备份Z-BlogPHP的数据库和文件是非常重要的,尤其是在进行升级或重大更改之前。备份数据库的步骤如下:备份数据库:使用phpMyAdmin或其他数据库管理工具,导出你的Z-BlogPHP数据库。选择导出格式为SQL文件,并保存到安全的位置。备份文件:通过FTP或SFTP客户端,下载Z-Bl......
  • 如何在 Z-BlogPHP 中进行系统升级?
    在Z-BlogPHP中进行系统升级是一个简单而重要的过程,确保你的博客始终运行在最新版本,以获得最新的功能和安全更新。以下是详细的升级步骤:进入后台管理:登录Z-BlogPHP后台管理界面,使用你在安装时设置的管理员用户名和密码。访问应用中心:在后台管理界面中,找到并点击“应......
  • 在进行空间迁移时,如何修改 Z-BlogPHP 的配置文件?
    在进行空间迁移时,修改Z-BlogPHP的配置文件 c_option.php 是一个关键步骤,确保你的博客在新服务器上能够正常运行。以下是详细的步骤和注意事项:备份原文件:在修改配置文件之前,务必备份原文件。可以通过FTP或SFTP下载 c_option.php 文件到本地计算机,确保在修改过程中出......
  • 如果 Z-BlogPHP 版本低于 1.6.0,如何开启固定域名功能?
    如果你的Z-BlogPHP版本低于1.6.0,直接使用 ZC_PERMANENT_DOMAIN_FORCED_URL 配置项可能不起作用,因为这个配置项是在1.6.0及之后的版本中引入的。为了在低版本中实现固定域名功能,你需要采取以下步骤:步骤备份现有文件:在进行任何修改之前,建议备份现有的 zb_system 文件......
  • CentOS 7 上安装 MySQL 8步骤:
    二、安装MySQL1.下载MySQL安装包官网下载:访问MySQL官网下载所需版本。使用wget下载:wgethttps://downloads.mysql.com/archives/get/p/23/file/mysql-8.0.30-el7-x86_64.tar2.解压安装包进入安装目录:cd/usr/local/解压安装包:tar-xvfmysql-8.0.3......