1. 环境

Mysql 主从

Mysql版本:5.1.49-log

系统:Red Hat Enterprise Linux Server release 5.4  64bit

2. 表面现象

数据库操作变慢,如用主键作为条件查询,有时也会超过1秒;

主库IO使用率一直在90%以上(平常io比较低20%以内),dirty 页占总数的90%左右,脏页刷不完;持续了几个小时~

3. 从系统上看

主库的iostat 的使用率一直在90%以上,Mysql data 所在目录的大小一直没变;主库的 ib_logfile 20分钟切换一次(主库上面的innodb log写得还是比较频繁),而从库的 ib_logfile 4小时切换一次。

4. 从mysql上看

在主库 Buffer pool hit rate 993 / 1000  innodb 的命中率一直维持在99%左右;

Innodb_buffer_pool_pages_dirty 的大小一直在增长,dirty 页占总数的90%左右,脏页刷不完。但这些脏页不像是正常操作产生的,因为主库上的读写操作都不大。并且从库上的同步没有延时,而且从库的dirty页也很少。

5. 从监控mysql报表上看

从监控到的mysql的读写,跟往常没什么区别;

而innodb 的 Data_free 从开始(100MB以内)

所有innodb的数据+索引的大小为:47.2GB

到恢复正常时data_free的大小为:32.3GB

所有innodb的数据+索引的大小为:45GB

可见在在innodb 数据+索引基本上没减少的情况下,data_free 变成32GB,这32GB来自undo的释放?为什么一下子释放这么多undo?

6. 再看看出现问题前的操作

原来3306实例下,有多个数据库,在出现问题前,刚好将一个数据库(频繁更新)迁移至其他服务器。迁移数据库 跟 这个问题 是巧合 or 触发?

7. 问题的原因

Undo 的释放?查看show engine innodb status中的:History list length (History list length是指在回滚空间中的未清除事务数。随着事务的提交,它的值会增加;随着清除线程的运行,它的值会减小)

发现History list length 的值很大,再查回以前的crt的log中的 History list length ,最近这个值一直在增长,一直增长到:78883366 (竟然有这么多的事务数未清除)

再看看出问题的时候,History list length 的变化情况(从crt log 中过滤出来,还好平时记录了操作的crt log;这回用上了):

# grep "History list length" app190.log

History list length 78883366

History list length 73091889

History list length 70069534

History list length 66194783

History list length 62209735

History list length 49672090

History list length 31489057

History list length 30877319

History list length 33

到恢复正常时,History list length 维持在100以内。

8. 查找History list length值太大的原因

为什么History list length一直未清理,innodb 在什么时候清理这些事务数?

看看innodb master thread的操作(参考:mysql技术内幕innodb存储引擎)

每10秒的操作包括:

刷新100个脏页到磁盘(可能)  注:后面的版本用 innodb_io_capacity 调整

合并至多5个插入缓冲(总是)

将日志缓冲刷新到磁盘(总是)

删除无用的undo页(总是)

刷新100个或者10个脏页到磁盘(总是)

产生一个检查点(总是)

Background loop 在没有用户活动(数据库空闲时)或者数据库关闭时,就会切换到这个循环,包括以下操作:

删除无用的undo页(总是)

合并20个插入缓冲(总是)

调回到主循环(总是)

不断刷新100个页,直到符合条件(可能,跳转到flush loop中完成)

由上可见,每10秒会删除无用的undo页,但为什么 History list length 还是这么大?

导致History list length值太大的原因,是跟迁移走的数据库(频繁更新)有关;这个数据库的应用,是采用连接池来连接mysql,并且mysql中使用的隔离级别是默认的:REPEATABLE-READ。在这个级别下,保证了多次读的结果一样(跟MVCC有关)。

而这个业务对于失败的事务不做任何操作,导致可能存在这个事务一直没commit,为了保持隔离级别REPEATABLE-READ 的特性,在undo中一直保留了这个事务以后的版本号,也就导致未清理的事务数越来越大,History list length 值也就越大。

可见,出现主库IO使用率一直在90%以上,是因为mysql 在清理undo 中的事务数。但有什么方法可以避免History list length 的值太大?

9. 避免History list length 值太大

1. 更改业务程序中的逻辑,比如对失败事务做相关的操作;

2. 在对业务没影响的情况下,可用隔离级别:read committed,在这个事务隔离级别下,只有事务commit,就会去清理undo中的事务(每10秒)。

由于对程序的更改没这么快,而且开发确认业务在 read committed 下也没影响,所以将业务的隔离级别更改为read committed :

在mysql 中执行:set global transaction isolation level read committed; 重启业务,重连数据库后生效,更改之后History list length 基本上保持在100以内。

 show global variables like '%iso%';
set global transaction isolation level read committed; pager grep "History list";
show innodb status;
nopager;

参考:

http://blog.chinaunix.net/uid-21879027-id-3348358.html

Mysql History list length 值太大引起的问题的更多相关文章

  1. double的值太大,以及补0

    当double的值太大的时候,比如1000000000 用DecimalFormat: double d = 1.0E7; System.out.println(new DecimalFormat(& ...

  2. ZTree id值太大,ZTree没有生成树,ZTree的id值过大

     ZTree id值太大,ZTree没有生成树,ZTree的id值过大 >>>>>>>>>>>>>>>> ...

  3. exception 值太大

      CreateTime--2018年2月5日09:45:01 Author:Marydon 异常: Cause: java.sql.SQLException: ORA-12899: 列 " ...

  4. oracle 11g 导入表时 提示 ***值太大错误

    导入数据库时,总是提示**值太大,实际值是**的错误. 具体忘了错误代码是什么了 ——! 经查询,这个是由于字符集设置的不是gbk的,导致导入时遇到中文字符出现的问题, 解决方法: 如果可以的话就把数 ...

  5. Oralce导入数据库出现某一列的值太大

    这是由于导出的文件所运行的Oracle,和导入所运行的Oracle机器字符集不相同导致的,在UTF-8中有的汉字占三个字节, 并不是所有的都占两个字节,

  6. Mysql文件太大导入失败解决办法总结

    Mysql文件太大导入失败解决办法总结 在使用phpmyadmin导入数据库的时候可能会碰到由于数据库文件太大而无法导入的问题! 英文提示如下:File exceeds the maximum all ...

  7. [转]MySql ibdata1文件太大如何缩小

    From : http://blog.chinaunix.net/uid-24373487-id-4223322.html 原文地址:MySql ibdata1文件太大如何缩小 作者:emailwht ...

  8. 【原创】Innodb中mysql如何快速删除2T的大表

    小漫画 来,先来看小漫画陶冶一下情操 OK,这里就说了.假设,你有一个表erp,如果你直接进行下面的命令 drop table erp 这个时候所有的mysql的相关进程都会停止,直到drop结束,m ...

  9. Innodb中MySQL如何快速删除2T的大表

    转自:http://database.51cto.com/art/201808/582324.htm OK,这里就说了.假设,你有一个表erp,如果你直接进行下面的命令: drop table erp ...

随机推荐

  1. ruby Logger日志

    1.logger创建 # 输出到标准输出 logger = Logger.new(STDERR) logger = Logger.new(STDOUT) # 输出到指定文件 logger = Logg ...

  2. ecshop漏洞修复 以及如何加固ecshop网站安全?

    由于8月份的ECSHOP通杀漏洞被国内安全厂商爆出后,众多使用ecshop程序源码的用户大面积的受到了网站被篡改,最明显的就是外贸站点被跳转到一些仿冒的网站上去,导致在谷歌的用户订单量迅速下降,从百度 ...

  3. 2018徐州网络赛H. Ryuji doesn't want to study

    题目链接: https://nanti.jisuanke.com/t/31458 题解: 建立两个树状数组,第一个是,a[1]*n+a[2]*(n-1)....+a[n]*1;第二个是正常的a[1], ...

  4. 仿造vue-resource的formdata传对象

    众插件不支持同步,也是没办法的事情,具体为啥就不分析了,确实搞不懂. 一直用vue-resource的post,觉得很舒服. 然,没办法只能仿造一个,自己提供一个同步方法 几个点先摆清楚 1. .th ...

  5. 封装一个ExcelHelper,方便将Excel直接转成Datatable对象

    public class ExcelHelper { /// <summary> /// Excel转换成DataTable /// </summary> /// <pa ...

  6. 实用脚本 4 -- Makefile(不同文件下的多个可执行文件or静态库编译到同一目录下)

    不同文件下的多个可执行文件编译到同一目录下,这样方便观察编译结果,从而方便进程操作.使用时根据自己的需要在进行局部修改(如 链接库.目标文件等等). 1..bashrc 中设置编译主目录(例如) ex ...

  7. Ubuntu 手机 app开发学习0

    # 相关网址 http://developer.ubuntu.com/zh-cn/apps/sdk/ 0. 环境搭建 首选需要一个Ubuntu 14.04操作系统.没啥好讲的,直接安装了一个虚拟机. ...

  8. 使用fiddler和jmeter进行简单的接口测试。

    初学接口测试,以下内容是记录首次使用fiddler和jmeter进行接口测试的步骤,可能步骤有点繁琐,如果有不对的地方,欢迎大家指正. 准备活动: 1.打开fiddler,打开fiddler以后会自动 ...

  9. 在测试时用到的一些mysql的小技巧(持续更新)

    经常使用的快捷键: 1.ctrl+q 打开查询窗口 2.ctrl+/ 注释sql语句 3.ctrl+shift +/ 解除注释 4.ctrl+r 运行查询窗口的sql语句 5.ctrl+shift+r ...

  10. (原创)最小生成树之Prim(普里姆)算法+代码详解,最懂你的讲解

    Prim算法 (哈欠)在创建最小生成树之前,让我们回忆一下什么是最小生成树.最小生成树即在一个待权值的图(即网结构)中用一个七拐八绕的折线串连起所有的点,最小嘛,顾名思义,要权值相加起来最小,你当然可 ...