case:下面的一条sql语句,导致mysql实例内存暴涨:

  select * from tables where table_name not in(select table_name from partitions group by table_name having count(*)>1 );

  mysql 5.5, 1w+的innodb表。

下面看下调查的结果:

1.  sql的执行情况以及内存分配:

 

step1: 构造information_schema.tables临时表

1.1  构造临时表tables结构:

说明:func=create_schema_table; engine=heap

内存: tables是heap引擎的表,临时构造,使用堆内存;语句结束close_tmp_tables释放。

1.2 填充临时表tables数据:一共由三类表来填充tables的内存

  1. memory引擎:

说明:information_schema下的表,创建临时table,

内存: 使用堆内存,填充完数据后 close_tmp_tables,释放内存。

  2. mysiam引擎:

说明:information_schema下一部分表,是mysiam引擎的临时表。

内存: 使用堆内存,创建磁盘临时文件,close_tmp_tables,释放内存,删除临时文件。

3. innodb引擎和其它:

说明:使用正常的open_tables函数,创建table,table_share, handler对象。

内存: 使用堆内存

 

step2:构造information_schema.partition临时表

  步骤和step1一样,但partition因为blob的原因,系统创建的时候,指定了mysiam引擎的临时表,而非内存heap临时表。

如下图:

   

 

 2.  构造两张临时表的开销:

实例一共1w张表,加上系统表,大约10200张,为了构造这两个临时表:

a)  一共open了大约 10200*2 次,加上创建临时表,临时磁盘文件。

b)  而table_cache设置的400,所以opened_table基本没有复用,打开后马上关闭了。

两张并不存在的临时表,全部构造完成,以上为了构造临时表而open大量表所使用的堆内存,现在已经释放。

 

3.  下面可以执行sql

sql的执行计划是:

1   information_schema.tables

n   nest loops information_schema.partitions

nest loop即:对于tables每一条记录要扫描一次patitions。

 

4.  关键的问题是:

 

执行计划调用如下函数栈:

  mysql_select

   JOIN::exec

    do_select

      sub_select

      evaluate_join_record

        Item_subselect::exec

         subselect_single_select_engine::exec

          JOIN::exec

   

在JOIN::exec有以下的判断:

     if (table_list->schema_table_state && is_subselect)
{
table_list->table->file->extra(HA_EXTRA_NO_CACHE);
table_list->table->file->extra(HA_EXTRA_RESET_STATE);
table_list->table->file->ha_delete_all_rows();
free_io_cache(table_list->table);
filesort_free_buffers(table_list->table,);
table_list->table->null_row= ;
}
else
table_list->table->file->stats.records= ;
if (do_fill_table(thd, table_list, tab))
{

即: subselect子查询如果是schema_table, 并且在执行状态中, 需要全部删除 partition里的数据,每次nest loop都重新do_fill_table。

 

执行的结果就是:

a)  为了构造两个临时表,open了10200*2次表,

b)  又为了每次nest loop,删除并构造了10200次partition表,一共open了10200*10200次表。

table_cache可以完全无视了。

 

 

但为什么会占用大量的内存?

 

在整个构造的过程中:

1. 堆内存 : 在open所有表后,往临时表填充完数据,就free了,不用等语句结束。

2. 线程内存: 为了构造字段,table list这些,内存都是从thd->mem_root线程中分配的,需要等语句结束才释放。

 

如下,每次子查询执行一次,thd->mem_root增加的memory block;

gdb) p *(this->thd->mem_root)
$ = { min_malloc = , block_size = , block_num = 748, first_block_usage = , Breakpoint , JOIN::exec (this=0x7f9a2c01f508) at sql/sql_select.cc:
(gdb) p *(this->thd->mem_root)
$ = { min_malloc = , block_size = , block_num = 758, first_block_usage = , Breakpoint , JOIN::exec (this=0x7f9a2c01f508) at sql/sql_select.cc:
(gdb) p *(this->thd->mem_root)
$ = {f min_malloc = , block_size = , block_num = 767, first_block_usage = ,

所以:这个sql,因为open太多表,执行时间过长, 而thd内存因为语句没有结束,无法释放,内存一直往上涨, 等语句结束,thd->mem_root的内存全部通过free释放掉。

MySQL information_schema表查询导致内存暴涨的更多相关文章

  1. MySQL多表查询合并结果union all,内连接查询

    MySQL多表查询合并结果和内连接查询 1.使用union和union all合并两个查询结果:select 字段名 from tablename1 union select 字段名 from tab ...

  2. 记一次mysql多表查询(left jion)优化案例

    一次mysql多表查询(left jion)优化案例 在新上线的供需模块中,发现某一个查询按钮点击后,出不来结果,找到该按钮对应sql手动执行,发现需要20-30秒才能出结果,所以服务端程序判断超时, ...

  3. MySQL多表查询之外键、表连接、子查询、索引

    MySQL多表查询之外键.表连接.子查询.索引 一.外键: 1.什么是外键 2.外键语法 3.外键的条件 4.添加外键 5.删除外键 1.什么是外键: 主键:是唯一标识一条记录,不能有重复的,不允许为 ...

  4. Mysql 单表查询 子查询 关联查询

    数据准备: ## 学院表create table department( d_id int primary key auto_increment, d_name varchar(20) not nul ...

  5. (转)Mysql 多表查询详解

    MySQL 多表查询详解 一.前言  二.示例 三.注意事项 一.前言  上篇讲到mysql中关键字执行的顺序,只涉及了一张表:实际应用大部分情况下,查询语句都会涉及到多张表格 : 1.1 多表连接有 ...

  6. MySQL多表查询回顾

    ----------------------siwuxie095 MySQL 多表查询回顾 以客户和联系人为例(一对多) 1.内连接 /*内连接写法一*/ select * from t_custom ...

  7. python 3 mysql 单表查询

    python 3 mysql 单表查询 1.准备表 company.employee 员工id id int 姓名 emp_name varchar 性别 sex enum 年龄 age int 入职 ...

  8. python3 mysql 多表查询

    python3 mysql 多表查询 一.准备表 创建二张表: company.employee company.department #建表 create table department( id ...

  9. [自带避雷针]DropShadowEffect导致内存暴涨

    原文:[自带避雷针]DropShadowEffect导致内存暴涨  [自带避雷针]DropShadowEffect导致内存暴涨 周银辉 从学习WPF开始, 就知道"位图效果"不是什 ...

随机推荐

  1. C# ACM poj1006

    中国剩余定理 public static void acm1006(int a, int b, int c, int d) { * ; * ; * ; * * ; ) * z; ) * y; ) * ...

  2. [转载]《STL源码剖析》阅读笔记之 迭代器及traits编程技法

    本文从三方面总结迭代器   迭代器的思想   迭代器相应型别及traits思想   __type_traits思想 一 迭代器思想 迭代器的主要思想源于迭代器模式,其定义如下:提供一种方法,使之能够依 ...

  3. android开发之GenyMotion与intelliJ的配置

    (注意:这是在你的电脑上安装了intelliJ和安卓SDK后才进行的工作,如果没有intelliJ和安卓SDK,请先安装以上两样东西) 号称史上最快乐的模拟器GenyMotion,试一下. 第一步:下 ...

  4. POJ 1088 滑雪 -- 动态规划

    题目地址:http://poj.org/problem?id=1088 Description Michael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激.可是为了获得速度,滑的区域必须向下倾斜,而且当 ...

  5. 九度OJ 1163 素数

    题目地址:http://ac.jobdu.com/problem.php?pid=1163 题目描述: 输入一个整数n(2<=n<=10000),要求输出所有从1到这个整数之间(不包括1和 ...

  6. 【HeadFirst设计模式】8.模板方法模式

    模板方法 定义: 在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中.模板方法使用得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤. 策略模式: 定义一个算法家族,并让这些算法可以互 ...

  7. unix 常用命令

    (一)基本命令 命令格式: 命令 参数 1.ls 显示文件名,等同于dos下dir命令 命令格式:ls [option] file option: -l 显示详细列表 域1 :文件类型和文件权限 域2 ...

  8. JQuery 事件器的介绍

    基本用法 $(元素). 事件( 事件属性); 常见事件 示例 说明 $(selector).click()  被选元素的点击事件 $(selector).dblclick()  被选元素的双击事件 $ ...

  9. Sublime Text 3插件之Emmet:HTML/CSS代码快速编写神器

    一.快速编写HTML代码 1.  初始化 HTML文档需要包含一些固定的标签,比如<html>.<head>.<body>等,现在你只需要1秒钟就可以输入这些标签. ...

  10. 开发设计模式(九)门面模式(Facade Pattern)

    什么是门面模式? 门面模式要求一个子系统的外部与其内部的通信必须通过一个统一的门面(Facade)对象进行.门面模式提供一个高层次的接口,使得子系统更易于使用. 大家都写过纸质的信件吧,比如给女朋友写 ...