原文地址:
[url]http://www.diybl.com/course/7_databases/mysql/myshl/200876/130767.html[/url]
下面的列表中列出了
mysqld服务器使用内存的一些方法。在适用的地方,给出了内存相关的系统变量名:
键缓存
(变量
key_buffer_size
)被所有线程共享;服务器使用的其它缓存则根据需要分配。
每个连接使用具体线程的空间:
堆栈
(默认
64KB,变量
thread_stack
)
连接缓存区
(变量
net_buffer_length
)
结果缓存区
(变量
net_buffer_length
)
连接缓存区和结果缓存区可以根据需要动态扩充到
max_allowed_packet。当某个查询运行时,也为当前查询字符串分配内存。
所有线程共享相同的基本内存。
只有压缩
MyISAM表映射到内存。这是因为
4GB的
32位内存空间不足以容纳大多数大表。当
64位地址空间的系统变得越来越普遍后,我们可以增加常规的内存映射支持。
对表进行顺序扫描的请求将分配一个
缓存区
(变量
read_buffer_size
)。
当按任意顺序读取行时
(例如,按照排序顺序
),将分配一个随机读
缓存区
(变量
read_rnd_buffer_size
)以避免硬盘搜索。
所有联合在一个令牌内完成,并且大多数联合甚至可以不用临时表即可以完成。大多数临时表是基于内存的
(
HEAP
)表。具有大的记录长度的临时表
(所有列的长度的和
)或包含
BLOB列的表存储在硬盘上。
如果某个内部
heap(堆积)表大小超过
tmp_table_size,
MySQL可以根据需要自动将内存中的
heap表改为基于硬盘的
MyISAM表。还可以通过设置
mysqld的
tmp_table_size选项来增加临时表的大小,或设置客户程序中的
SQL选项
SQL_BIG_TABLE。
进行排序的大多数请求将分配一个排序缓存区,并根据结果集的大小为两个临时文件分配零。
几乎所有解析和计算在局部内存中完成。小项目不需要内存,因此避免了普通的慢内存分配和释放。只为不期望的大字符串分配内存;使用函数
malloc()和
free()来完成。
对于每个打开的
MyISAM表,索引文件打开一次;数据文件为每个并行运行的线程打开一次。对于每个并行线程,将分配一个表结构、一个每个列的列结构和大小为
3 * N的缓存区
(其中
N是最大行的长度,而不是计算
BLOB列
)。一个
BLOB列需要
5至
8个字节加上
BLOB数据的长度。
MyISAM
存储引擎维护一个额外的行缓存区供内部应用。
对于每个具有
BLOB列的表,将对缓存区进行动态扩大以读入大的
BLOB
值。如果你扫描一个表,则分配一个与最大的
BLOB值一样大的缓存区。
所有使用的表的句柄结构保存在高速缓存中并以
FIFO 管理 。默认情况,高速缓存有
64个入口。如果某个表同时被两个运行的线程使用,高速缓存则为该提供两个入口。
当并行执行的线程结束时,
FLUSH TABLE语句或
mysqladmin flush-table 命令可以立即关闭所有不使用的表并将所有使用中的表标记为已经关闭。这样可以 有效 释放大多数使用中的内存。
FLUSH TABLE在关闭所有表之前不返回结果。
ps和其它系统状态程序可以报导
mysqld使用很多内存。这可以是在不同的内存地址上的线程栈造成的。例如,
Solaris版本的
ps将栈间未用的内存算作已用的内存。你可以通过用
swap -s检查可用交换区来验证它。我们用商业内存漏洞探查器测试了
mysqld,因此应该有没有内存漏洞。
MySQL如何使用DNS
当新的客户连接
mysqld时,
mysqld创建一个新的线程来处理请求。该线程先检查是否主机名在主机名缓存中。如果不在,线程试图解析主机名:
如果操作系统支持线程安全
gethostbyaddr_r ()和
gethostbyname_r()调用,线程使用它们来执行主机名解析。
如果操作系统不支持线程安全调用,线程锁定一个互斥体并调用
gethostbyaddr()和
gethostbyname()。在这种情况下,在第
1个线程解锁互斥体前,没有其它线程可以解析不在主机名缓存中的主机名。
你可以用
--skip-name-resolve选项启动
mysqld来禁用
DNS主机名查找。然而,在这种情况下,你只可以使用
MySQL中的授权表中的
IP号。
如果你有一个很慢的
DNS和许多主机,你可以通过用
--skip-name-resolve禁用
DNS查找或增加
HOST_CACHE_SIZE定义
(默认值:
128)并重新编译
mysqld来提高性能。
你可以用
--skip-host-cache选项启动服务器来禁用主机名缓存。要想清除主机名缓存,执行
FLUSH HOSTS语句或执行
mysqladmin flush-hosts命令。
如果你想要完全禁止
TCP/IP连接,用
--skip-networking选项启动
mysqld。