在 mysql 5.5 中实现了类似mysql5.7中performance schema 的内存统计功能。

功能

1 展示mysql层内存总大小。

2 展示mysql层内存使用分布情况。

3 展示每个线程使用的内存总大小。

4 展示每个线程使用的内存分布情况。

演示

1 增加状态变量Memory_used 显示mysql层总体使用的内存大小。

mysql> show global status like 'Memory_used';
+---------------+----------+
| Variable_name | Value |
+---------------+----------+
| Memory_used | 30767584 |
+---------------+----------+
1 row in set (0.06 sec)

2 show memory展示mysql层内存使用分布情况。

mysql> show memory;
+----------------------------------------------+-------------+
| name | memory_used |
+----------------------------------------------+-------------+
| libmysql/MYSQL_STMT:mem_root | 0 |
| libmysql/MYSQL_STMT:result::alloc | 0 |
| sql/NET::buff | 16400 |
| sql/Protocol_local::m_rset_root | 0 |
| sql/TABLE | 58992 |
| mysys/my_dir | 0 |
| sql/TABLE::sort.io_cache | 0 |
| sql/THD::main_mem_root | 0 |
| sql/THD::transaction::mem_root | 0 |
| sql/THD::debug_sync_control | 0 |
| sql/debug_sync_control::debug_sync_action | 0 |
| sql/Filesort_info::addonbuf | 0 |
| sql/Filesort_info::record_pointers | 0 |
| sql/SORTPARAM::tmp_buffer | 0 |
| sql/SORT_ADDON_FIELD | 0 |
| sql/user_var_entry | 0 |
| mysys/IO_CACHE | 16400 |
| mysys/TREE | 0 |
| mysys/DYNAMIC_ARRAY | 352136 |
| sql/QUICK_RANGE_SELECT::alloc | 0 |
| sql/QUICK_INDEX_MERGE_SELECT::alloc | 0 |
| sql/QUICK_INDEX_MERGE_SELECT::alloc | 0 |
| sql/QUICK_ROR_INTERSECT_SELECT::alloc | 0 |
| sql/QUICK_ROR_UNION_SELECT::alloc | 0 |
| sql/QUICK_GROUP_MIN_MAX_SELECT::alloc | 0 |
| sql/SQL_SELECT::test_quick_select:alloc | 0 |
| sql/prune_partitions::exec | 0 |
| sql/READ_RECORD::cache | 0 |
| sql/table_mapping::m_mem_root | 0 |
| sql/Locked_tables_list::m_locked_tables_root | 0 |
| sql/Warning_info::m_warn_root | 0 |
| sql/READ_INFO | 0 |
| sql/Prepared_statement::main_mem_root | 0 |
| sql/JOIN_CACHE | 0 |
| sql/TABLE_SHARE::mem_root | 0 |
| sql/LOG_EVENT | 0 |
| sql/QUICK_RANGE_SELECT::multi_range | 0 |
| sql/QUICK_RANGE_SELECT::multi_range_buff | 0 |
| sql/table_def | 0 |
| sql/THD::handler_tables_hash | 0 |
| sql/hash_index_key_buffer | 0 |
| sql/ignore_db | 0 |
| sql/sql_acl_mem | 0 |
| sql/sql_acl_memx | 0 |
| sql/servers | 0 |
| sql/MYSQL_LOCK | 0 |
| sql/KEY_CACHE | 2456 |
| sql/Unique::sort_buffer | 0 |
| sql/Unique::merge_buffer | 0 |
| sql/frm | 0 |
| sql/Query_cache | 0 |
| sql/bision_stack | 0 |
| sql/user_conn | 96 |
| sql/THD::variables | 0 |
| sql/global_system_variables | 144 |
| sql/sercurity_context | 24 |
| sql/sp_head::main_mem_root | 0 |
| sql/sp_head::execute_mem_root | 0 |
| sql/sp_head::call_mem_root | 0 |
+----------------------------------------------+-------------+
59 rows in set (0.00 sec)

3 show processlist增加了Memory_used列展现线程的内存使用(或者 show status like 'Memory_used';)

mysql> show processlist;
+----+------+-----------------+------+---------+------+-------+------------------+-----------+---------------+-----------+-------------+
| Id | User | Host | db | Command | Time | State | Info | Rows_sent | Rows_examined | Rows_read | Memory_used |
+----+------+-----------------+------+---------+------+-------+------------------+-----------+---------------+-----------+-------------+
| 1 | root | 127.0.0.1:45516 | NULL | Query | 0 | NULL | show processlist | 0 | 0 | 1 | 43552 |
+----+------+-----------------+------+---------+------+-------+------------------+-----------+---------------+-----------+-------------+
1 row in set (0.00 sec)

4 新增information_schema.thread_memory_info表展现每个线程内存使用分布

mysql> select * from  information_schema.thread_memory_info;
+-----------+----------------------------------------------+-------------+
| thread_id | type | memory_used |
+-----------+----------------------------------------------+-------------+
| 1 | libmysql/MYSQL_STMT:mem_root | 0 |
| 1 | libmysql/MYSQL_STMT:result::alloc | 0 |
| 1 | sql/NET::buff | 16400 |
| 1 | sql/Protocol_local::m_rset_root | 0 |
| 1 | sql/TABLE | 0 |
| 1 | mysys/my_dir | 0 |
| 1 | sql/TABLE::sort.io_cache | 0 |
| 1 | sql/THD::main_mem_root | 0 |
| 1 | sql/THD::transaction::mem_root | 0 |
| 1 | sql/THD::debug_sync_control | 0 |
| 1 | sql/debug_sync_control::debug_sync_action | 0 |
| 1 | sql/Filesort_info::addonbuf | 0 |
| 1 | sql/Filesort_info::record_pointers | 0 |
| 1 | sql/SORTPARAM::tmp_buffer | 0 |
| 1 | sql/SORT_ADDON_FIELD | 0 |
| 1 | sql/user_var_entry | 0 |
| 1 | mysys/IO_CACHE | 0 |
| 1 | mysys/TREE | 0 |
| 1 | mysys/DYNAMIC_ARRAY | 264 |
| 1 | sql/QUICK_RANGE_SELECT::alloc | 0 |
| 1 | sql/QUICK_INDEX_MERGE_SELECT::alloc | 0 |
| 1 | sql/QUICK_INDEX_MERGE_SELECT::alloc | 0 |
| 1 | sql/QUICK_ROR_INTERSECT_SELECT::alloc | 0 |
| 1 | sql/QUICK_ROR_UNION_SELECT::alloc | 0 |
| 1 | sql/QUICK_GROUP_MIN_MAX_SELECT::alloc | 0 |
| 1 | sql/SQL_SELECT::test_quick_select:alloc | 0 |
| 1 | sql/prune_partitions::exec | 0 |
| 1 | sql/READ_RECORD::cache | 0 |
| 1 | sql/table_mapping::m_mem_root | 0 |
| 1 | sql/Locked_tables_list::m_locked_tables_root | 0 |
| 1 | sql/Warning_info::m_warn_root | 1048 |
| 1 | sql/READ_INFO | 0 |
| 1 | sql/Prepared_statement::main_mem_root | 0 |
| 1 | sql/JOIN_CACHE | 0 |
| 1 | sql/TABLE_SHARE::mem_root | 0 |
| 1 | sql/LOG_EVENT | 0 |
| 1 | sql/QUICK_RANGE_SELECT::multi_range | 0 |
| 1 | sql/QUICK_RANGE_SELECT::multi_range_buff | 0 |
| 1 | sql/table_def | 0 |
| 1 | sql/THD::handler_tables_hash | 0 |
| 1 | sql/hash_index_key_buffer | 0 |
| 1 | sql/ignore_db | 0 |
| 1 | sql/sql_acl_mem | 0 |
| 1 | sql/sql_acl_memx | 0 |
| 1 | sql/servers | 0 |
| 1 | sql/MYSQL_LOCK | 0 |
| 1 | sql/KEY_CACHE | 0 |
| 1 | sql/Unique::sort_buffer | 0 |
| 1 | sql/Unique::merge_buffer | 0 |
| 1 | sql/frm | 0 |
| 1 | sql/Query_cache | 0 |
| 1 | sql/bision_stack | 0 |
| 1 | sql/user_conn | 0 |
| 1 | sql/THD::variables | 0 |
| 1 | sql/global_system_variables | 0 |
| 1 | sql/sercurity_context | 0 |
| 1 | sql/sp_head::main_mem_root | 0 |
| 1 | sql/sp_head::execute_mem_root | 0 |
| 1 | sql/sp_head::call_mem_root | 0 |
+-----------+----------------------------------------------+-------------+
59 rows in set (0.04 sec)

实现

1 mysql层的封装的内存分配与释放的接口如下:

my_malloc, my_realloc,my_free

分别对应底层接口alloc,realloc,free.而calloc在mysql层没有调用过,这里可以忽略掉。

内存统计实现的方法是在内存分配时增加计数统计,在内存释放是减少计数统计。

为了实现内存的分类统计,内存的线程级别的监控。在内存分配时需要额外存储以下3条信息:

1) 内存分配的大小,在内存释放时减少内存计数大小。

2) 当前线程分配的内存是否是线程私有的,以区分公有内存,相对准确统计线程占用的内存大小。

3) 内存的类别,实现的内存的分类统计。

2 内存额外信息的来源

内存分配接口my_malloc, my_realloc都有参数my_flags用于存储一些标记信息。在这里上述的第2和3条信息都存储在my_flags中,在内存分配接口调用时指定。而第1条内存大小,原有接口就有。

1) 标示当前线程分配的内存是否是线程私有的。MY_THREAD_SPECIFIC标记是否是线程私有的线程,MY_THREAD_MOVE 标示内存是否在线程之间移动,只有在my_realloc时发生,目前这种情况还没有出现。

MY_THREAD_SPECIFIC  0x10000

MY_THREAD_MOVE      0x20000

2) 内存的类别,由enum memory_stat_type 定义,从0开始至MST_END。

为了将内存的类别存储在my_flags中,需要将类别值进行移位处理

#define SET_MEM_TYPE(v) ((v) << 18)

3 内存额外信息的存储

内存分配时额外分配MALLOC_PREFIX_SIZE大小的内存,用于存储内存额外信息,并且位于内存头部。

#define MALLOC_PREFIX_SIZE (sizeof(double))

GET_MEM_FLAG从my_flags中取出第2和3条信息。

#define GET_MEM_FLAG(v) ((v) >> 16)

MALLOC_STORE_SIZE将内存额外信息存储在内存头部ALLOC_PREFIX_SIZE大小的内存中。

这样内存释放时可以从内存头部取出这3条信息,来减少相应的内存统计计数。

4 主要接口和数据结构

1)global_status_var.memory_used mysql层占用内存总大小

2)show_mem_array  mysql层内存使用分类大小数组

3) THD::status_var.memory_used 线程占用内存大小

4)THD::mem_used  每个线程使用的内存分类大小数组

5) my_malloc_size_cb_func  增加和减少内存统计计数总入口。

6) mysqld_list_memory: show memory 显示mysql层内存使用分类大小

兼容性

information_schema.processlist 增加了一列MEMORY_USED

新增information_schema.thread_memory_info表

上述变动对升级没有影响。

参考

mysql5.7 http://dev.mysql.com/doc/refman/5.7/en/memory-summary-tables.html

mariadb https://mariadb.atlassian.net/browse/MDEV-4011

【附】

1 目前内存分的类别还不完善,只列了一些主要的分类。

2 虽然内存统计计数使用无锁算法,但还是会影响性能,待评估。

mysql 内存统计的更多相关文章

  1. mysql内存参数整理和条调优以及内存统计

    date:20140530auth:Jin 参考:http://dev.mysql.com/doc/refman/5.5/en/server-status-variables.html#http:// ...

  2. MySQL内存使用查看方式

    使用版本:MySQL 5.7 官方文档 在performance_schema有如下表记录内存使用情况 mysql> show tables like '%memory%summary%'; + ...

  3. MySQL内存计算器

    MySQL如何使用内存? 首先,介绍MySQL使用内存的一些方法: 1. 会话级别的内存消耗(连接私有内存):如sort_buffer_size等,每个会话都会开辟一个sort_buffer_size ...

  4. MySQL的统计信息学习总结

    统计信息概念 MySQL统计信息是指数据库通过采样.统计出来的表.索引的相关信息,例如,表的记录数.聚集索引page个数.字段的Cardinality.....MySQL在生成执行计划时,需要根据索引 ...

  5. 记录一次现网MySQL内存增长超限问题定位过程

    问题现象现网物理机内存近几日内爆涨使用率超过了90%,可用内存从250G,降低到20G以下,报告警.服务器使用情况来看,并没有什么异常.除了QPS缓慢增长外. MySQL内存分配结构 定位这个问题,先 ...

  6. 线上mysql内存持续增长直至内存溢出被killed分析(已解决)

    来新公司前,领导就说了,线上生产环境Mysql库经常会发生日间内存爆掉被killed的情况,结果来到这第一天,第一件事就是要根据线上服务器配置优化配置,同时必须找出现在mysql内存持续增加爆掉的原因 ...

  7. mysql内存消耗分析

    最近有些生产服务器老是mysql内存不停得往上涨,开发人员和维护反馈,用了不少的临时表,问题时常线上发生,测试又一直比较难重现. 经观察mysql内存的os占用趋势,发现从8:40开始,mysql内存 ...

  8. MySQL内存使用分析

    转自: http://www.jb51.net/article/38936.htm 本篇文章是对MySQL内存的使用说明(全局缓存+线程缓存)进行了详细的分析介绍,需要的朋友参考下    首先我们来看 ...

  9. MySQL内存----使用说明全局缓存+线程缓存) 转

    MySQL内存使用说明(全局缓存+线程缓存) 首先我们来看一个公式,MySQL中内存分为全局内存和线程内存两大部分(其实并不全部,只是影响比较大的 部分): per_thread_buffers=(r ...

随机推荐

  1. JavaScript -- Math

    ----- 016-Math.html ----- <!DOCTYPE html> <html> <head> <meta http-equiv=" ...

  2. vue传参页面刷新数据丢失问题

    在做vue的时候,经常会遇到组件之间数据的传递问题,通过params或者query传参,但是,当页面刷新的时候,数据会丢失,找不到数据.今天经过总结,解决了这个问题.通过了一下几种情况进行传值: 通过 ...

  3. vue导出excel数据表格功能

    前端工作量最多的就是需求,需求就是一直在变,比如当前端数据写完之后,需要用Excel把数据下载出来. 第一步安装依赖包,需要把代码下载你的项目当中 cnpm install  file-saver c ...

  4. docker 非root用户修改mount到容器的文件出现“Operation not permitted

    使用环境centos7 x86-64 内核版本4.19.9 docker使用非root用户启动,daemon.json配置文件内容如下: # cat daemon.json { "usern ...

  5. mysql数据库中实现内连接、左连接、右连接

    原文:http://www.cnblogs.com/xwdreamer/archive/2010/12/15/2297058.html 内连接:把两个表中数据对应的数据查出来 外连接:以某个表为基础把 ...

  6. 揭开Future的神秘面纱——任务执行

    前言 此文承接之前的博文 解开Future的神秘面纱之取消任务 补充一些任务执行的一些细节,并从全局介绍程序的运行情况. 系列目录 揭开Future的神秘面纱——任务取消 揭开Future的神秘面纱— ...

  7. 第一次项目上Linux服务器(七:——Tomcat+ngnix+域名的简单配置)

    1.准备工作 安装好jdk+tomcat+nginx相关配置,请参考历史博客 2.修改Nginx配置文件 修改配置文件如下: 3.修改Tomcat配置文件 修改配置文件如下: 配置文件连接: ngni ...

  8. k-近邻算法(KNN)

    最近邻算法可以说是最简单的分类算法,其思想是将被预测的项归类为和它最相近的项相同的类.我们通过简单的计算比较即将被预测的项与已有训练集中各项的距离(差距),选择其中差距最小的一项,该项的类别即为我们即 ...

  9. 并发编程之 wait notify 方法剖析

    前言 2018 元旦快乐. 摘要: notify wait 如何使用? 为什么必须在同步块中? 使用 notify wait 实现一个简单的生产者消费者模型 底层实现原理 1. notify wait ...

  10. Saving HDU(hdu2111,贪心)

    Saving HDU Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...