MySQL内存计算器
MySQL如何使用内存?
首先,介绍MySQL使用内存的一些方法:
1. 会话级别的内存消耗(连接私有内存):如sort_buffer_size等,每个会话都会开辟一个sort_buffer_size来进行排序操作。
2. 全局的内存消耗(共享内存):例如:innodb_buffer_pool_size等,全局共享的内存段。
MySQL内存计算器:http://www.mysqlcalculator.com
全局内存消耗(共享内存)相关参数
1)innodb_buffer_pool_size
使用过Innodb的同学都知道,这块内存是Innodb存储引擎最重要的内存,直接关系到MySQL的读写性能。与MyISAM表只缓存索引,数据寄望于OS系统缓存不同。Innodb一般都会关闭OS的缓存,所有读到数据页和索引都直接存在数据库层的innodb_buffer_pool中的。
InnoDB缓冲池缓存着InnoDB表,索引,及其它辅助缓冲器中的数据。为了实现大容量读取操作的效率,缓冲池被分成可以容纳多行的页。为了缓存管理的效率,缓冲池被实现为页面的链接列表,很少使用的数据使用LRU算法的变体进行页面替换。
缓冲池的大小对于系统性能很重要:
- InnoDB使用malloc()方法在服务器启动时为整个缓冲池分配内存,通常,推荐innodb_buffer_pool_size值为系统内存的50%至75%。innodb_buffer_pool_size可以在服务器运行时动态配置。
- 在具有大量内存的系统上,你可以通过将缓冲池划分为多个缓冲池实例来提高并发性,其innodb_buffer_pool_instances系统变量用来定义缓冲池实例的数量。
- 缓冲池太小可能会导致过多的交换,因为页面从缓冲池中刷新后仅在短时间内可能再次需要。
- 缓冲池太大可能会因为内存竞争而导致交换。
2)innodb_additional_mem_pool_size
主要用于存放MySQL内部的数据结构和Innodb的数据字典,所以大小主要与表的数量有关,表越多值越大。庆幸的是这个值是可变的,如果不够用的话,MySQL会向操作系统申请的。该值默认8M,AWS所有规格都是统一的2M,由于这个值可以动态申请,所以我觉得2M应该是满足需求的。
3)innodb_log_buffer_size
这个是redolog的缓冲区,为了提高性能,MySQL每次写日志都将日志先写到一个内存Buffer中,然后将Buffer按照innodb_flush_log_at_trx_commit的配置刷到disk上。目前,我们所有实例的innodb_flush_log_at_trx_commit设置为了1,即每次事务提交都会刷新Buffer到磁盘,保证已经提交的事务,redo是不会丢的。AWS该值也设的是1(为了保证不丢数据),这个值的大小主要影响到刷磁盘的次数,设置的过小,Buffer容易满,就会增加fsync的次数,设置过大,占用内存。该值默认是8M,AWS所有规格统一128M,我觉得目前每次提交都会刷buffer,所以除非有大事务的情况,一般buffer不太可能被占满,所以没必要开的很大, 8M应该是满足需求的。
4)key_buffer_size
MyISAM表的key缓存,这个只对MyISAM存储引擎有效,所以对于我们绝大多数使用Innodb的应用,无需关心。
5)query_cache_size
MySQL对于查询的结果会进行缓存来节省解析SQL、执行SQL的花销,query_cache是按照SQL语句的Hash值进行缓存的,同时SQL语句涉及的表发生更新,该缓存就会失效,所以这个缓存对于特定的读多更新少的库比较有用,对于绝大多数更新较多的库可能不是很适用,比较受限于应用场景,所以AWS也把这个缓存给关了。我觉得这个值默认应该关闭,根据需求调整。
会话级别的内存消耗(连接私有内存)
上面这些就是MySQL主要的共享内存空间,这些空间是在MySQL启动时就分配的,但是并不是立即使用的。MySQL还有一部分内存是在用户连接请求到达时动态分配的,即每个MySQL连接都单独一个缓存,这部分缓存主要包括:
1)read_buffer_size
每个线程连续扫描时为扫描的每个表分配的缓存区的大小(字节)。如果进行多次连续扫描,可能还需要增加该值。默认值为1311072,只有当查询需要的时候,才分配read_buffer_size指定的全部内存。
2)read_rnd_buffer_size
当以任意顺序读取行时,可以分配随机读取缓冲区,通过该缓冲区读取行,以避免磁盘寻找。read_rnd_buffer_size系统变量决定缓冲器大小。
3)sort_buffer_size
每一个要做排序的请求,都会分到一个sort_buffer_size大的缓存,用于做order by和group by的排序,如果设置的缓存大小无法满足需要,MySQL会将数据写入磁盘来完成排序。因为磁盘操作和内存操作不在一个数量级,所以sort_buffer_size对排序的性能影响很大。由于这部分缓存是即使不用这么大,也会全部分配的,所以对系统内存分配开销是比较大的,如果是希望扩大的话,建议在会话层设置,默认值2M,AWS也是2M。
4)thread_stack
默认256K,AWS设置为256K,MySQL为每个线程分配的堆栈大小,当线程堆栈太小时,这限制了服务器可以处理的SQL语句的复杂性。
5)join_buffer_size
每个连接的每次join都分配一个,默认值128K,AWS设置为128K。
6)binlog_cache_size
类似于innodb_log_buffer_size缓存事务日志,binlog_cache_size缓存Binlog,不同的是这个是每个线程单独一个,主要对于大事务有较大性能提升。默认32K,AWS 32K。
7)tmp_table_size
默认16M,用户内存临时表的最大值,如果临时表超过该值,MySQL就会把临时表转换为一个磁盘上mysiam表。如果用户需要做一些大表的groupby的操作,可能需要较大的该值,由于是与连接相关的,同样建议在会话层设置。
MySQL 5.7 OOM问题诊断
其实导致OOM的直接原因并不复杂,就是因为服务器内存不足,内核需要回收内存,回收内存就是kill掉服务器上使用内存最多的程序,而MySQL服务是使用内存最多,所以就OOM了。今天,来谈谈MySQL的OOM(out of memory)问题诊断。之前,这类问题的定位对于普通用户来说并不怎么简单。但是在MySQL 5.7中,OOM问题的定位变得极其容易。还没掌握的小伙伴赶快来看下吧。通常来说,发生OOM时可在系统日志找到类似的日志提示:
1
2
3
4
5
|
Mar 26 00:00:20 AY1301300558264084667 kernel: [4687241.322857] Out of memory: Kill process 6726 (mysqld) score 96 or sacrifice child
Mar 26 00:00:20 AY1301300558264084667 kernel: [4687241.322922] Killed process 6726 (mysqld) total-vm:1673084kB, anon-rss:147984kB, file-rss:0kB
Mar 26 00:00:20 AY1301300558264084667 kernel: [4687241.947815] python invoked oom-killer: gfp_mask=0x201da, order=0, oom_adj=0, oom_score_adj=0
Mar 26 00:00:20 AY1301300558264084667 kernel: [4687241.947819] python cpuset=/ mems_allowed=0
Mar 26 00:00:20 AY1301300558264084667 kernel: [4687241.947822] Pid: 25708, comm: python Not tainted 3.2.0-29-generic #46-Ubuntu
|
MySQL 5.7的库performance_schema新增了以下这几张表,用于从各维度查看内存的消耗:
- memory_summary_by_account_by_event_name
- memory_summary_by_host_by_event_name
- memory_summary_by_thread_by_event_name
- memory_summary_by_user_by_event_name
- memory_summary_global_by_event_name
简单来说,就是可以根据用户、主机、线程、账号、全局的维度对内存进行监控。同时库sys也就这些表做了进一步的格式化,可以使得用户非常容易的观察到每个对象的内存开销:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
mysql> select event_name,current_alloc from memory_global_by_current_bytes limit 10;
+-----------------------------------------------------------------------------+---------------+
| event_name | current_alloc |
+-----------------------------------------------------------------------------+---------------+
| memory/mysys/IO_CACHE | 482.41 MiB |
| memory/performance_schema/events_statements_summary_by_thread_by_event_name | 198.38 MiB |
| memory/performance_schema/memory_summary_by_thread_by_event_name | 129.38 MiB |
| memory/performance_schema/events_statements_current | 80.41 MiB |
| memory/performance_schema/events_statements_history | 80.41 MiB |
| memory/performance_schema/events_waits_summary_by_thread_by_event_name | 74.39 MiB |
| memory/performance_schema/events_statements_current.sqltext | 57.50 MiB |
| memory/performance_schema/events_statements_current.tokens | 57.50 MiB |
| memory/performance_schema/events_statements_history.tokens | 57.50 MiB |
| memory/performance_schema/events_statements_history.sqltext | 57.50 MiB |
+-----------------------------------------------------------------------------+---------------+
10 rows in set (0.04 sec)
|
细心的同学可能会发现,默认情况下performance_schema只对performance_schema进行了内存开销的统计。根据你的MySQL安装代码区域可能包括performance_schema、sql、client、innodb、myisam、csv、memory、blackhole、archive、partition和其他。
但是在对OOM进行诊断时,需要对所有可能的对象进行内存监控。因此,还需要做下面的设置:
1
2
3
|
mysql> update performance_schema.setup_instruments set enabled = 'yes' where name like 'memory%';
Query OK, 306 rows affected (0.00 sec)
Rows matched: 376 Changed: 306 Warnings: 0
|
1
2
3
4
5
6
7
8
9
10
11
|
mysql> select * from performance_schema.setup_instruments where name like 'memory%innodb%' limit 5;
+-------------------------------------------+---------+-------+
| NAME | ENABLED | TIMED |
+-------------------------------------------+---------+-------+
| memory/innodb/adaptive hash index | YES | NO |
| memory/innodb/buf_buf_pool | YES | NO |
| memory/innodb/dict_stats_bg_recalc_pool_t | YES | NO |
| memory/innodb/dict_stats_index_map_t | YES | NO |
| memory/innodb/dict_stats_n_diff_on_level | YES | NO |
+-------------------------------------------+---------+-------+
5 rows in set (0.00 sec)
|
但是这种在线打开内存统计的方法仅对之后新增的内存对象有效:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
mysql> select event_name,current_alloc from memory_global_by_current_bytes where event_name like '%innodb%';
+-------------------------+---------------+
| event_name | current_alloc |
+-------------------------+---------------+
| memory/innodb/row0sel | 21.10 MiB |
| memory/innodb/btr0pcur | 89.53 KiB |
| memory/innodb/os0event | 33.73 KiB |
| memory/innodb/dict0dict | 32.05 KiB |
| memory/innodb/trx0undo | 30.94 KiB |
| memory/innodb/rem0rec | 13.35 KiB |
| memory/innodb/fil0fil | 5.57 KiB |
+-------------------------+---------------+
7 rows in set (0.04 sec)
|
如想要对全局生命周期中的对象进行内存统计,必须在配置文件中进行设置,然后重启:
1
2
|
[mysqld]
performance-schema-instrument='memory/%=COUNTED'
|
1
2
3
4
5
6
7
8
9
10
11
|
mysql> select event_name,current_alloc from memory_global_by_current_bytes limit 5;
+-----------------------------------------------------------------------------+---------------+
| event_name | current_alloc |
+-----------------------------------------------------------------------------+---------------+
| memory/mysys/IO_CACHE | 498.47 MiB |
| memory/performance_schema/events_statements_summary_by_thread_by_event_name | 198.38 MiB |
| memory/performance_schema/memory_summary_by_thread_by_event_name | 129.38 MiB |
| memory/performance_schema/events_statements_current | 80.41 MiB |
| memory/performance_schema/events_statements_history | 80.41 MiB |
+-----------------------------------------------------------------------------+---------------+
5 rows in set (0.04 sec)
|
通过上面的结果,是不是可以发现可疑的内存使用了呢?
另外可以看看buffer pool page的使用情况。
1
2
3
4
5
6
7
8
9
10
|
mysql> show engine innodb status\G
----------------------
INDIVIDUAL BUFFER POOL INFO
----------------------
---BUFFER POOL 0
Buffer pool size 49146
Free buffers 22120
Database pages 26248
Old database pages 9669
Modified db pages 1
|
对于MySQL 5.7,可以使用sys库下的memory_global_by_current_bytes表来查询相同的底层数据,该模式表显示了全局服务器内当前内存使用情况,按分配类型进行细分。
1
2
3
4
5
6
7
8
9
|
mysql> SELECT * FROM sys.memory_global_by_current_bytes WHERE event_name LIKE 'memory/innodb/buf_buf_pool'\G
*************************** 1. row ***************************
event_name: memory/innodb/buf_buf_pool
current_count: 1
current_alloc: 131.06 MiB
current_avg_alloc: 131.06 MiB
high_count: 1
high_alloc: 131.06 MiB
high_avg_alloc: 131.06 MiB
|
此sys模式查询通过current_alloc()代码区域聚合当前分配的内存:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
mysql> SELECT SUBSTRING_INDEX(event_name,'/',2) AS
code_area, sys.format_bytes(SUM(current_alloc))
AS current_alloc
FROM sys.x$memory_global_by_current_bytes
GROUP BY SUBSTRING_INDEX(event_name,'/',2)
ORDER BY SUM(current_alloc) DESC;
+---------------------------+---------------+
| code_area | current_alloc |
+---------------------------+---------------+
| memory/innodb | 843.24 MiB |
| memory/performance_schema | 81.29 MiB |
| memory/mysys | 8.20 MiB |
| memory/sql | 2.47 MiB |
| memory/memory | 174.01 KiB |
| memory/myisam | 46.53 KiB |
| memory/blackhole | 512 bytes |
| memory/federated | 512 bytes |
| memory/csv | 512 bytes |
| memory/vio | 496 bytes |
+---------------------------+---------------+
|
完结。。。
MySQL内存计算器的更多相关文章
- mysql内存优化
一.环境说明: 操作系统:CentOS 6.5 x86_64 数据库:Mysql 5.6.22 服务器:阿里云VPS,32G Mem,0 swap 二.问题情况: 1.某日发现公司线上系统的Mysql ...
- 线上mysql内存持续增长直至内存溢出被killed分析(已解决)
来新公司前,领导就说了,线上生产环境Mysql库经常会发生日间内存爆掉被killed的情况,结果来到这第一天,第一件事就是要根据线上服务器配置优化配置,同时必须找出现在mysql内存持续增加爆掉的原因 ...
- mysql内存消耗分析
最近有些生产服务器老是mysql内存不停得往上涨,开发人员和维护反馈,用了不少的临时表,问题时常线上发生,测试又一直比较难重现. 经观察mysql内存的os占用趋势,发现从8:40开始,mysql内存 ...
- MySQL内存使用分析
转自: http://www.jb51.net/article/38936.htm 本篇文章是对MySQL内存的使用说明(全局缓存+线程缓存)进行了详细的分析介绍,需要的朋友参考下 首先我们来看 ...
- MySQL内存----使用说明全局缓存+线程缓存) 转
MySQL内存使用说明(全局缓存+线程缓存) 首先我们来看一个公式,MySQL中内存分为全局内存和线程内存两大部分(其实并不全部,只是影响比较大的 部分): per_thread_buffers=(r ...
- Mysql内存表的用处
文章出自:http://blog.csdn.net/hitzhang/article/details/5994639 个人最欣赏mysql的地方就是他存储引擎的多样性和可扩展性,这样mysql也能拥有 ...
- MySQL内存体系架构及参数总结 ---图解
http://www.cnblogs.com/kissdb/p/4009614.html 内存结构: Mysql 内存分配规则是:用多少给多少,最高到配置的值,不是立即分配 图只做大概参考 全局缓存包 ...
- 18、MySQL内存体系架构及参数总结
内存结构: Mysql 内存分配规则是:用多少给多少,最高到配置的值,不是立即分配 图只做大概参考 全局缓存包括: global buffer(全局内存分配总和) = innodb_buffer ...
- MySQL内存表的特性与使用介绍 -- 简明现代魔法
MySQL内存表的特性与使用介绍 -- 简明现代魔法 MySQL内存表的特性与使用介绍
随机推荐
- 自制session
原理 1.面向对象中通过索引的方式访问对象,需要内部实现 __getitem__ .__delitem__.__setitem__方法 2.Tornado框架中,默认执行Handler的get/pos ...
- SecureCRT SSH连接一直提示密码错误
这是解决方法: http://www.linuxidc.com/Linux/2016-09/134925.htm
- Daily Scrum (2015/11/5)
这天晚上我们对爬虫进行了一些测试,发现仍然存在一些不小的BUG.现在我们的爬虫已经能完成基本的功能,焉域政同学也正在把他之前写的分类功能继续完善.在BUG的测试中,我们发现如果要求爬虫爬取特定的文件类 ...
- Mysql常用配置及优化
[client]# 该目录下的内容常用来进行localhost登陆,一般不需要修改port = 3306 # 端口号socket = /var/lib/mysql/mysql.sock # 套接字文件 ...
- <<梦断代码>>读后感
<梦断代码>中对软件工程所面临的种种困难与艰难的描述,即便再过5年读也许都不过时.因为正如原作者所说,书中描写的是一队人马并肩扛起代码大石,虽历经磨难仍欲将其推上山顶的故事,而正是这种故事 ...
- 《UML大战需求分析》-读后感三
用例图是用来描述什么角色通过某某系统能做什么的图,用例图关注的是系统的外在表示想爱你.系统与人的交互系统与其他系统的交互,小人执行者就是角色,角色 是对系统使用者的抽象,一个角色可以代表多个具体的人而 ...
- Beta Scrum Day 7 — 听说
7#听说
- Java Head First & 多态
package com.cwcec.tag; class Fruit { } class Apple extends Fruit{} class Animal { public Fruit eat(F ...
- WPF里面制作圆角文本框
转自:http://www.cnblogs.com/mengxin523/archive/2010/04/04/1704448.html 本以为WPF里面的XAML会很强大,可以设置很多属性,比如文本 ...
- Redis有序集内部实现原理分析(二)
Redis技术交流群481804090 Redis:https://github.com/zwjlpeng/Redis_Deep_Read 本篇博文紧随上篇Redis有序集内部实现原理分析,在这篇博文 ...