文章目录
1、原题
1.1、英文原题
Which two options describe how MySQL Server allocates memory?
A. Each connection may have its own per-thread memory allocations.
B. Thread memory is pre-allocated up to thread cache size for performance.
C. Each thread allocates memory from a global pool.
D. Global memory resource are allocated at server startup.
1.2、中文翻译
哪两个选项描述了MySQL Server如何分配内存?
A. 每个连接可以有自己的线程内存分配。
B. 线程内存预先分配到线程缓存大小以提高性能。
C. 每个线程从全局池分配内存。
D. 在服务器启动时分配全局内存资源。
1.3、答案
A、D
2、题目解析
2.1、题干解析
本题考察的是MySQL的内存使用机制。
2.2、选项解析
- 每个连接都会有自己的内存分配,主要用于栈内存、连接缓冲区和结果缓冲区,另外根据实际情况,可能每个连接还会用到随机读缓冲区和排序缓冲区。所以选项A正确。
- 线程内存预分配时,连接缓冲区和结果缓冲区都会被分配到net_buffer_size大小,再根据需要进行调节。所以选项B错误。
- 缓冲池主要用于缓冲表数据、索引数据和查询缓存,每个线程分配的内存不是从缓冲池中分配的,所以选项C错误。
- 服务器启动时会分配缓冲池等全局内存资源,所以选项D正确。
3、知识点
3.1、知识点1:MySQL的内存使用机制
MySQL分配缓冲区和缓存以提高数据库操作的性能。默认配置旨在允许MySQL服务器在具有大约512MB内存的虚拟机上启动。你可以通过增加某些缓存和缓冲区相关系统变量的值来提高MySQL的性能。你也可以修改默认配置以在内存有限的系统上运行MySQL。
MySQL使用的内存主要作如下用途:
- InnoDB buffer pool(InnoDB缓冲池):InnoDB专用
- MyISAM key buffer:MyISAM专用
- MySQL Performance Schema(MySQL性能模式):性能模式是一项在低水平上监控MySQL服务器执行的功能。性能模式动态地分配内存,根据实际的服务器负载调整其内存使用,而不是在服务器启动期间分配所需的内存。一旦内存被分配,它就不会被释放,直到服务器被重新启动。
- 每个线程除了共享基础缓存(InnoDB缓冲池或MyISAM key buffer外),还会拥有自己的专用内存区,主要包括stack(栈内存空间)、connection buffer(连接缓冲区)、result buffer(结果缓冲区)。另外,每个连接因为执行的不同可能还会包括随机读缓冲区和排序缓冲区。
- read buffer(读缓冲区):每个对表进行顺序扫描的请求都会分配一个读取缓冲区。
- random-read buffer(随机读缓冲区):对表的随机读写会用到随机读缓冲区,从而避免磁盘搜索。
- sort buffer(排序缓冲区):大多数执行排序的请求会分配一个排序缓冲区。
- table cache(表缓存):所有使用中的表的处理程序结构都保存在表缓存中。
FLUSH TABLES 语句或 mysqladmin flush-tables 命令会一次性关闭所有不使用的表,并在当前执行的线程结束时将所有使用中的表标记为关闭。这有效地释放了大部分正在使用的内存。
3.1.1、InnoDB buffer pool(InnoDB缓冲池)
- 缓冲池是什么:InnoDB缓冲池是一个内存区域,用于保存表、索引和其他辅助缓冲区的InnoDB缓存数据。为了提高缓冲区管理的效率,缓冲区被实现为一个变种LRU算法的页面链表,从而很少使用的数据会从缓冲区中淘汰。
- 缓冲池的初始化:InnoDB在服务器启动时为整个缓冲池分配内存,使用malloc()操作。
- 缓冲池的大小:innodb_buffer_pool_size系统变量定义了缓冲池的大小。缓冲池的大小对系统性能很重要,一个太小的缓冲池可能会导致过度的搅动,因为页面从缓冲池中被冲走,但在很短的时间内又被需要。缓冲池太大,可能会因为对内存的竞争而导致交换。通常推荐innodb_buffer_pool_size值是系统内存的50%到75%。innodb_buffer_pool_size可以在服务器运行时动态配置。
- 多缓冲池:在有大量内存的系统中,可以通过将缓冲池划分为多个缓冲池实例来提高并发性。innodb_buffer_pool_instances系统变量定义了缓冲池实例的数量。
3.1.2、MyISAM key buffer
MyISAM key buffer是MyISAM引擎专享的缓冲区,是被所有线程共享的。key_buffer_size系统变量决定了其大小。
3.1.3、每个线程专用的内存空间
-
服务器用来管理客户端连接的每个线程都需要一些线程专用的空间。下面的列表指出了这些空间以及哪些系统变量控制它们的大小。
- A stack:栈内存空间,thread_stack系统变量控制大小。
- A connection buffer:连接缓冲区,net_buffer_length系统变量控制带下。
- A result buffer:结果缓冲区,net_buffer_length系统变量控制大小。
-
连接缓冲区和结果缓冲区开始时的大小都等于net_buffer_length字节,但根据需要动态地扩大到max_allowed_packet字节。在每个SQL语句之后,结果缓冲区会收缩到net_buffer_length字节。
-
每个连接线程使用内存来计算语句摘要。服务器为每个会话分配max_digest_length字节。
-
当一个线程不再需要时,分配给它的内存会被释放并返回到系统中,除非该线程回到线程缓存中。在这种情况下,该内存仍然被分配。
3.1.4、read buffer(读缓冲区)
每个对表进行顺序扫描的请求都会分配一个读取缓冲区。read_buffer_size系统变量决定了缓冲区的大小。
3.1.5、random-read buffer(随机读缓冲区)
当以任意顺序读取行时(例如,按照排序),可以通过被分配的随机读缓冲区从而避免磁盘搜索。read_rnd_buffer_size系统变量决定了缓冲区的大小。
3.1.6、sort buffer(排序缓冲区)
大多数执行排序的请求会分配一个排序缓冲区和0到2个临时文件,这取决于结果集的大小。
3.1.7、 table cache(表缓存)
MySQL需要内存和描述符用于表缓存。所有使用中的表的处理程序结构都保存在表缓存中,并以 “先进先出”(FIFO)的方式管理。table_open_cache系统变量定义了初始表缓存大小;
4、总结
- MySQL内存主要用于如下用途
- InnoDB缓冲池;缓冲表数据、索引数据,InnoDB专用。
- MyISAM Key Buffer:MyISAM专用。
- 每个线程专用内存:主要用于栈内存、连接缓冲区、结果缓冲区,如果涉及排序可能还有排序缓冲区,如果涉及随机读还有随机读缓冲区
- read buffer(读缓冲区):对每个表的读取都会分配读缓冲区。
- table cache(表缓存):缓存每张表的表结构。
- 线程内存的分配并不会从InnoDB缓冲池中分配,所以可以简单认为所有线程分配的内存+InnoDB缓冲池内存等于MySQL使用的总内存大小。