MySQL 8 内存的使用

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
日志服务 SLS,月写入数据量 50GB 1个月
简介: mysql内存使用的计算公式

MySQL内存分配公式

mysql内存使用的计算公式:

mysql使用的内存 = 全局共享内存+max_connections×线程独享内存

也就是:innodb_buffer_pool_size + innodb_log_buffer_size + thread_cache_size +table_open_cache + table_definition_cache +key_buffer_size +max_connections *( thread_stack+ sort_buffer_size+join_buffer_size + read_buffer_size+read_rnd_buffer_size+ binlog_cache_size+tmp_table_size)


全局共享内存

innodb_buffer_pool_size

innodb_buffer_pool_size这个参数是对Mysql数据库最重要的参数之一,它对 InnoDB 存储引擎的作用类似于 Key Buffer Cache 对 MyISAM 存储引擎的影响,主要区别是 InnoDB Buffer Pool 不仅仅缓存索引数据,会缓存表的数据,而且完全按照数据文件中的数据快结构信息来缓存,这一点和 Oracle SGA 中的 database buffer cache 类似,因此在SHOW ENGINE innodb status中查到的Buffer pool size要乘以16K。

可以通过 (Innodb_buffer_pool_read_requests - Innodb_buffer_pool_reads) / Innodb_buffer_pool_read_requests * 100% 计算得到 InnoDB Buffer Pool 的命中率。


innodb_change_buffering

change buffering是MySQL5.5加入的新特性,change buffering是insert buffer的加强,insert buffer只针对insert有效,change buffering对insert、delete、update(delete+insert)、purge都有效。当修改一个索引块(secondary index)时的数据时,索引块在buffter pool中不存在,修改信息就会被cache在change buffer中,当通过索引扫描把需要的索引块读取到buffer pool时,会和change buffer中修改信息合并,再择机写回disk。

目的还是为了减少随机IO带来性能损耗,说明白了:把随机IO尽量变成顺序IO。现在SSD盛行,在SSD上随机访问和顺序访问性能几乎差不多的情况下,change buffering特性不会带来多大的性能提升,但对于廉价的机械硬盘,这个参数还是能帮助提高性能的。

change buffering由参数innodb_change_buffering控制:


all:buffer inserts, delete-marking operations, and purges.

none:Do not buffer any operations.

inserts:Buffer insert operations.

deletes:Buffer delete-marking operations.

changes:Buffer both inserts and delete-marking.

purges:Buffer the physical deletion operations that happen in the background.

注意这个内存是在Innodb的buffer pool中分配的,计算总内存的时候不用算它。

innodb_change_buffer_max_size

表示change buffer在buffer pool中的最大占比,默认25%,最大50%。如果系统中有严重的insert、update并且还有活跃的delete时,就增大max_size;针对不更改数据的纯报表系统,可以减小该参数值。


innodb_log_buffer_size

这是 InnoDB 存储引擎的事务日志所使用的缓冲区。为了提高性能,也是先将信息写入 Innofb Log Buffer 中,当满足 innodb_flush_log_trx_commit 参数所设置的相应条件(或者日志缓冲区写满)之后,才会将日志写到文件(或者同步到磁盘)中。innodb_flush_log_trx_commit 参数可以设置为0,1,2,解释如下:


0:log buffer中的数据将以每秒一次的频率写入到logfile中,且同时会进行文件系统到磁盘的同步操作,但是每个事务的commit并不会触发任何log buffer 到log file的刷新或者文件系统到磁盘的刷新操作,该模式速度最快,但不太安全,mysqld进程的崩溃会导致上一秒钟所有事务数据的丢失;

1:在每次事务提交的时候将log buffer 中的数据都会写入到logfile,同时也会触发文件系统到磁盘的同步,该模式是最安全的,但也是最慢的一种方式;

2:事务提交会触发log buffer 到logfile的刷新,但并不会触发磁盘文件系统到磁盘的同步,该模式速度较快,也比0安全,只有在操作系统崩溃或者系统断电的情况下,上一秒钟所有事务数据才可能丢失。

thread_cache_size

线程池缓存大小,当客户端断开连接后将当前线程缓存起来,当在接到新的连接请求时快速响应无需创建新的线程 。这尤其对那些使用短连接的应用程序来说可以极大的提高创建连接的效率。可以通过(Connections - Threads_created) / Connections * 100% 计算出连接线程缓存的命中率。也可以通过如下几个MySQL状态值来适当调整线程池的大小:


mysql> show global status like 'Thread%';
+-------------------+-------+
| Variable_name     | Value |
+-------------------+-------+
| Threads_cached    | 2     |
| Threads_connected | 1     |
| Threads_created   | 3     |
| Threads_running   | 2     |
+-------------------+-------+
4 rows in set (0.01 sec)


当 Threads_cached 越来越少 但 Threads_connected 始终不降,且 Threads_created 持续升高,可适当增加 thread_cache_size 的大小。


table_open_cache

table_open_cache指定表高速缓存的大小,用来缓存表文件的文件句柄信息。当我们的客户端程序提交Query给MySQL的时候,MySQL需要对Query所涉及到的每一个表都取得一个表文件句柄信息,如果没有Table Cache,那么MySQL就不得不频繁的进行打开关闭文件操作,无疑会对系统性能产生一定的影响,每当MySQL访问一个表时,如果在表缓冲区中还有空间,该表就被打开并放入其中,这样可以更快地访问表内容。注意,这里设置的是可以缓存的表文件句柄信息的数目,而不是内存空间的大小。

通过检查峰值时间的状态值Open_tables和Opened_tables,可以决定是否需要增加table_open_cache的值。其中Open_tables是当前正在打开表的数量,Opened_tables是所有已经打开表的数量。注意,不能盲目地把table_open_cache设置成很大的值,设置太大超过了shell的文件描述符(通过ulimit -n查看),造成文件描述符不足,从而造成性能不稳定或者连接失败。如果发现open_tables等于table_open_cache,并且opened_tables在不断增长,那么你就需要增加table_open_cache的值了(上述状态值可通过SHOW GLOBAL STATUS LIKE ‘Open%tables’获得)。如果Open_tables的值已经接近table_cache的值,且Opened_tables还在不断变大,则说明mysql正在将缓存的表释放以容纳新的表,此时可能需要加大table_cache的值。对于大多数情况,比较适合的值:

Open_tables / Opened_tables >= 0.85

Open_tables / table_cache <= 0.95

建议把MySQL数据库放在生产环境中试运行一段时间,然后把参数的值调整得比Opened_tables的数值大一些,并且保证在比较高负载的极端条件下依然比Opened_tables略大。


table_definition_cache

table_definition_cache和table_open_cache类似,前者缓存frm文件,关于后者,文档中并没有说明,应该是ibd/MYI/MYD;

状态值:

Open_table_definitions:表定义文件.frm被缓存的数量

Opened_table_definitions:历史上总共被缓存过的,frm文件数量


key_buffer_size

key_buffer_size指定索引缓冲区的大小,它决定索引处理的速度,尤其是索引读的速度。通过检查状态值Key_read_requests和Key_reads,可以知道key_buffer_size设置是否合理。比例key_reads /key_read_requests应该尽可能的低,至少是1:100,1:1000更好(上述状态值可以使用SHOW STATUS LIKE ‘key_read%'获得)。key_buffer_size只对MyISAM表起作用。即使你不使用MyISAM表,但是内部的临时磁盘表是MyISAM表,也要使用该值。可以使用检查状态值created_tmp_disk_tables得知详情。


max_connections

MySQL的最大连接数,增加该值增加mysqld 要求的文件描述符的数量。如果服务器的并发连接请求量比较大,建议调高此值,以增加并行连接数量,当然这建立在机器能支撑的情况下,因为如果连接数越多,介于MySQL会为每个连接提供连接缓冲区,就会开销越多的内存,所以要适当调整该值,不能盲目提高设值。数值过小会经常出现ERROR 1040: Too many connections错误,可以过’conn%’通配符查看当前状态的连接数量,以定夺该值的大小。max_used_connections / max_connections * 100% (理想值≈ 85%) 如果max_used_connections跟max_connections相同 那么就是max_connections设置过低或者超过服务器负载上限了,低于10%则设置过大。

线程/会话/连接独享内存

binlog_cache_size

为每个session 分配的内存,在事务过程中用来存储二进制日志的缓存,可以提高记录bin-log的效率,默认32K,没有大事务,dml也不是很频繁的情况下可以设置小一点,如果事务大而且多,dml操作也频繁,则可以适当的调大一点。

数据库binlog_cache_size的使用情况,可以查看:Binlog_cache_disk_use表示因为我们binlog_cache_size设计的内存不足导致缓存二进制日志用到了临时文件的次数,Binlog_cache_use 表示 用binlog_cache_size缓存的次数

tmp_table_size和max_heap_table_size

tmp_table_size规定了内部内存临时表的最大值,每个线程都要分配。(实际起限制作用的是tmp_table_size和max_heap_table_size的最小值。)如果内存临时表超出了限制,MySQL就会自动地把它转化为基于磁盘的MyISAM表,存储在指定的tmpdir目录下,默认:


mysql> show variables like "tmpdir";
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| tmpdir        | /tmp/ |
+---------------+-------+


优化查询语句的时候,要避免使用临时表,如果实在避免不了的话,要保证这些临时表是存在内存中的。如果需要的话并且你有很多group by语句,并且你有很多内存,增大tmp_table_size(和max_heap_table_size)的值。这个变量不适用与用户创建的内存表(memory table).

可以比较内部基于磁盘的临时表的总数和创建在内存中的临时表的总数(Created_tmp_disk_tables和Created_tmp_tables),一般的比例关系是:

Created_tmp_disk_tables/Created_tmp_tables<5%


max_heap_table_size定义了用户可以创建的内存表(memory table)的大小.这个值用来计算内存表的最大行数值。这个变量支持动态改变,即set @max_heap_table_size=# 。

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
26天前
|
缓存 监控 关系型数据库
如何查看MySQL使用的内存
如何查看MySQL使用的内存
86 1
|
26天前
|
存储 缓存 监控
深入了解MySQL内存管理:如何查看MySQL使用的内存
深入了解MySQL内存管理:如何查看MySQL使用的内存
169 1
|
16天前
|
SQL 监控 关系型数据库
如何查看MySQL使用的内存
综合运用上述方法,您可以全方位地监控和管理MySQL的内存使用。从简单查看配置到深入分析实时内存占用,每种方法都有其适用场景和优势。定期检查和调整MySQL的内存配置,对于维持数据库性能和稳定性至关重要。
50 0
|
3月前
|
关系型数据库 MySQL
MySQl优化:使用 jemalloc 分配内存
MySQl优化:使用 jemalloc 分配内存
|
3月前
|
SQL 存储 关系型数据库
实时计算 Flink版产品使用问题之同步MySQL多张表的过程中,内存释放依赖于什么
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
|
4月前
|
SQL 缓存 关系型数据库
(十二)MySQL之内存篇:深入探寻数据库内存与Buffer Pool的奥妙!
MySQL是基于磁盘工作的,这句几乎刻在了每个后端程序员DNA里,但它真的对吗?其实答案并不能盖棺定论,你可以说MySQL是基于磁盘实现的,这点我十分认同,但要说MySQL是基于磁盘工作,这点我则抱否定的态度,至于为什么呢?这跟咱们本章的主角:Buffer Pool有关,Buffer Pool是什么?还记得咱们在《MySQL架构篇》中聊到的缓存和缓冲区么,其中所提到的写入缓冲区就位于Buffer Pool中。
252 1
|
5月前
|
缓存 关系型数据库 MySQL
MySQL数据库——InnoDB引擎-架构-内存结构(Buffer Pool、Change Buffer、Adaptive Hash Index、Log Buffer)
MySQL数据库——InnoDB引擎-架构-内存结构(Buffer Pool、Change Buffer、Adaptive Hash Index、Log Buffer)
94 3
|
3月前
|
存储 编译器 C语言
【C语言篇】数据在内存中的存储(超详细)
浮点数就采⽤下⾯的规则表⽰,即指数E的真实值加上127(或1023),再将有效数字M去掉整数部分的1。
298 0
|
5天前
|
存储 C语言
数据在内存中的存储方式
本文介绍了计算机中整数和浮点数的存储方式,包括整数的原码、反码、补码,以及浮点数的IEEE754标准存储格式。同时,探讨了大小端字节序的概念及其判断方法,通过实例代码展示了这些概念的实际应用。
13 1
|
10天前
|
存储
共用体在内存中如何存储数据
共用体(Union)在内存中为所有成员分配同一段内存空间,大小等于最大成员所需的空间。这意味着所有成员共享同一块内存,但同一时间只能存储其中一个成员的数据,无法同时保存多个成员的值。