首页 > 数据库 > > 8.12 优化MYSQL 服务器
参考官方文档:
https://dev.mysql.com/doc/refman/5.7/en/optimizing-server.html
本节讨论数据库服务器的优化技术,主要处理系统配置而不是调整SQL语句。 本节中的信息适用于想要确保他们管理的服务器的性能和可扩展性的DBA; 对于构建包括设置数据库的安装脚本的开发人员; 以及那些希望最大限度提高自身生产力的开发,测试等人员自己运行MySQL。
8.12.1 系统因素
一些系统级因素可能会以主要方式影响性能:
只要您只运行一台服务器,禁用外部锁定不会影响MySQL的功能。 请记住在运行myisamchk之前关闭服务器(或者锁定并冲洗相关表格)。 在某些系统中,强制禁用外部锁定是因为它无法工作。
唯一不能禁用外部锁定的情况是在同一数据上运行多个MySQL服务器(而不是客户端),或者如果您运行myisamchk检查(而不是修复)表而不告知服务器先刷新和锁定表。 请注意,除了使用NDB群集时,通常不建议使用多个MySQL服务器同时访问相同的数据。
LOCK TABLES和UNLOCK TABLES语句使用内部锁定,所以即使外部锁定被禁用,也可以使用它们。
注意:
MySQL Cluster目前在MySQL 5.7中不受支持。 希望从MySQL 5.0或5.1升级MySQL簇的用户应迁移到MySQL Cluster NDB 7.0或7.1; 这些都基于MySQL 5.1,但包含NDB的最新改进和修复。
8.12.2 优化mysql服务器参数
MySQL使用非常具有伸缩性的算法,因此通常可以使用很少的内存运行。 但是,通常情况下,您通过为MySQL提供更多内存来获得更好的性能
MySQL使用非常具有伸缩性的算法,因此通常可以使用很少的内存运行。 但是,通常情况下,您通过为MySQL提供更多内存来获得更好的性能
调整MySQL服务器时,要配置的两个最重要的变量是key_buffer_size和table_open_cache。 在尝试更改任何其他变量之前,您应该先确信自己已经设置了这些设置。
以下示例显示了不同运行时配置的一些典型变量值。
shell> mysqld_safe --key_buffer_size=64M --table_open_cache=256 \
--sort_buffer_size=4M --read_buffer_size=1M &
shell> mysqld_safe --key_buffer_size=16M --sort_buffer_size=1M
如果有很多同时连接,除非mysqld已配置为每个连接使用很少的内存,否则可能会发生交换问题。 如果你有足够的内存用于所有连接,mysqld性能会更好。
只需很少的内存和大量的连接,使用这样的东西:
shell> mysqld_safe --key_buffer_size=512K --sort_buffer_size=100K \
--read_buffer_size=100K &
或者甚至 这样:
shell> mysqld_safe --key_buffer_size=512K --sort_buffer_size=16K \
--table_open_cache=32 --read_buffer_size=8K \
--net_buffer_length=1K &
如果在比可用内存大得多的表上执行GROUP BY或ORDER BY操作,请增加read_rnd_buffer_size的值以加快排序操作后行的读取速度。
如果您在命令行上为mysqld或mysqld_safe指定了一个选项,则它仅在调用服务器时才有效。 要在每次运行服务器时使用该选项,请将其放入选项文件中。
要查看参数更改的效果,请执行以下操作:
shell> mysqld --key_buffer_size=32M --verbose --help
变量值列在输出结尾附近。 确保--verbose和--help选项是最后一个。 否则,在命令行上列出的任何选项的效果都不会反映在输出中。
8.12.3 优化磁盘I/O
本节介绍如何在您将更多更快的存储硬件投入数据库服务器时配置存储设备。
这意味着,对于MyISAM表,您可以将索引文件和数据文件从其在数据目录中的常用位置符号链接到另一个磁盘(也可以是条带化的)。 这使得查找和读取时间更好,假设磁盘也不用于其他目的 (现在条带化已经交给高速存储做了)
InnoDB表不支持符号链接。 但是,可以将InnoDB数据和日志文件放置在不同的物理磁盘上。
条带化意味着您有许多磁盘,并将第一个磁盘块,第二个磁盘上的第二个块和(N MOD number_of_disks)磁盘上的第N个块,依此类推。 这意味着如果您的正常数据大小小于条带大小(或完全对齐),则可以获得更好的性能。 分条非常依赖操作系统和条带大小,因此可以使用不同的条带大小对应用程序进行基准测试。
条纹的速度差异很大程度上取决于参数。 根据您设置条带参数和磁盘数量的方式,您可能会得到数量级差异。 您必须选择针对随机或顺序访问进行优化。
如果您不需要知道上次访问文件的时间(这在数据库服务器上并不真正有用),则可以使用-o noatime选项装入文件系统。 这会跳过对文件系统inode中最后一次访问时间的更新,从而避免一些磁盘搜索。
在许多操作系统上,可以通过将文件系统与-o async选项挂载来设置文件系统以异步更新。 如果您的计算机相当稳定,这应该可以提供更好的性能而不会牺牲太多的可靠性。 (这个标志在Linux上默认打开。)
在MYSQL 上使用NFS
建议在考虑使用NFS与MySQL时谨慎。 潜在问题因操作系统和NFS版本而异,其中包括:
在专业SAN环境或其他存储系统中使用NFS往往比在这种环境之外使用NFS提供更高的可靠性。 但是,SAN环境中的NFS可能比直接连接或总线连接的非循环存储要慢。
如果您选择使用NFS,建议使用NFS版本4或更高版本,与在部署到生产环境之前彻底测试NFS设置一样。
8.12.4 使用符号链接
您可以将数据库或表从数据库目录移动到其他位置,并用符号链接替换它们到新的位置。 例如,您可能希望这样做,即将数据库移动到具有更多可用空间的文件系统,或者通过将表分布到不同的磁盘来提高系统的速度。
对于InnoDB表,使用CREATE TABLE语句中的DATA DIRECTORY子句而不是符号链接,如第14.7.5节“在数据目录之外创建文件 - 每个表空间表空间”中所述。 这项新功能是支持的跨平台技术。
推荐的方法是将整个数据库目录符号链接到不同的磁盘。 Symlink MyISAM表仅作为最后的手段。
要确定数据目录的位置,请使用以下语句:
SHOW VARIABLES LIKE 'datadir';
---具体操作省略。。。
8.12.5 优化内存使用
8.12.4.1 Mysql 如何使用内存
以下列表描述了MySQL使用内存的一些方式。 在适用的情况下,引用相关的系统变量。 有些项目是存储引擎或功能特定的。
缓冲池的大小对系统性能很重要:
对于服务器打开的每个MyISAM表,索引文件将打开一次; 对于每个访问表的并发运行线程,数据文件都会打开一次。 对于每个并发线程,分配表结构,每列的列结构和大小为3 * N的缓冲区(其中N是最大行长度,不计算BLOB列)。 BLOB列需要5到8个字节加上BLOB数据的长度。 MyISAM存储引擎维护一个额外的行缓冲区供内部使用。
对于使用CREATE TABLE显式创建的MEMORY表,只有max_heap_table_size系统变量决定了表允许增长的大小,并且没有转换为磁盘格式。
连接缓冲区和结果缓冲区中的每一个都以等于net_buffer_length个字节的大小开始,但根据需要动态扩展到max_allowed_packet个字节。 在每个SQL语句之后,结果缓冲区缩小为net_buffer_length个字节。 当语句正在运行时,还会分配当前语句字符串的副本。
每个连接线程都使用内存来计算语句摘要。 服务器为每个会话分配max_digest_length字节。
MySQL还需要用于表定义缓存的内存。 table_definition_cache系统变量定义了可以存储在表定义缓存中的表定义数(来自.frm文件)。 如果您使用大量表,则可以创建大型表格定义缓存以加快表格的打开速度。 与表缓存不同,表定义缓存占用更少的空间,并且不使用文件描述符。
ps和其他系统状态程序可能会报告mysqld使用大量内存。 这可能是由不同内存地址上的线程堆栈引起的。 例如,Solaris的ps版本将堆栈之间未使用的内存计为已用内存。 要验证这一点,请检查swap -s的可用交换。 我们用几个内存泄漏检测器(商业和开源)测试mysqld,所以应该没有内存泄漏。
监控mysql 内存使用
以下示例演示如何使用Performance Schema和sys方案来监视MySQL内存使用情况。
大多数性能架构内存工具默认情况下处于禁用状态。 可以通过更新性能方案setup_instruments表的ENABLED列来启用仪器。 内存仪器具有 memory/code_area/instrument_name形式的名称,其中code_area是诸如sql或innodb之类的值,instrument_name是仪器详细信息。
1.要查看可用的MySQL内存工具,请查询Performance Schema setup_instruments表。 以下查询返回所有代码区域的数百个内存工具。
mysql> SELECT * FROM performance_schema.setup_instruments WHERE NAME LIKE '%memory%';
您可以通过指定代码区域来缩小结果。 例如,通过将innodb指定为代码区域,可以将结果限制为InnoDB内存仪器。
SELECT * FROM performance_schema.setup_instruments WHERE NAME LIKE '%memory/innodb%';
取决于您的MySQL安装,代码区可能包括performance_schema,sql, client, innodb, myisam, csv, memory, blackhole, archive, partition等。
2.要启用内存工具,请将性能架构工具规则添加到您的MySQL配置文件中。 例如,要启用所有内存工具,请将此规则添加到您的配置文件并重新启动服务器:
performance-schema-instrument='memory/%=COUNTED'
注意:
在启动时启用内存工具可确保启动时发生的内存分配计数。
重新启动服务器后,Performance Schema setup_instruments表的ENABLED列应为您启用的内存仪器报告YES。 对于内存工具,setup_instruments表中的TIMED列会被忽略,因为内存操作没有timed。
SELECT * FROM performance_schema.setup_instruments WHERENAME LIKE '%memory/innodb%';
3.查询内存仪器数据。 在此示例中,内存仪器数据在Performance Schema memory_summary_global_by_event_name表中查询,该表总结EVENT_NAME的数据。 EVENT_NAME是乐器的名称。
SELECT * FROMperformance_schema.memory_summary_global_by_event_nameWHERE EVENT_NAME LIKE 'memory/innodb/buf_buf_pool'\G
可以使用sys schema memory_global_by_current_bytes表查询相同的底层数据,该表显示全局服务器当前的内存使用情况,按分配类型细分。
SELECT * FROM sys.memory_global_by_current_bytes WHEREevent_name LIKE 'memory/innodb/buf_buf_pool'\G
此sys方案查询通过代码区域聚合当前分配的内存(current_alloc):
SELECT SUBSTRING_INDEX(event_name,'/',2) AS code_area,sys.format_bytes(SUM(current_alloc)) AS current_alloc FROMsys.x$memory_global_by_current_bytes GROUP BYSUBSTRING_INDEX(event_name,'/',2) ORDER BYSUM(current_alloc) DESC;

8.15.4.2 启用大页面支持
某些硬件/操作系统体系结构支持的内存页面大于默认值(通常为4KB)。 这种支持的实际实施取决于底层硬件和操作系统。 执行大量内存访问的应用程序可能通过使用大页面来获得性能改进,原因是减少了 Translation Lookaside Buffer(TLB)未命中。
在MySQL中,InnoDB可以使用大页面为其缓冲池和额外的内存池分配内存。
标准使用MySQL中的大页面将尝试使用支持的最大大小,最大为4MB。 在Solaris下,“超大页面”功能可以使用最多256MB的页面。 此功能适用于最新的SPARC平台。 可以使用--super-large-pages或--skip-super-large-pages选项启用或禁用它。
MySQL还支持大型页面支持的Linux实现(在Linux中称为HugeTLB)。
在Linux上可以使用大页面之前,必须启用内核来支持它们,并且需要配置HugeTLB内存池。 作为参考,HugeTBL API记录在Linux源代码的Documentation / vm / hugetlbpage.txt文件中。
最近的一些系统(如红帽企业Linux)的内核似乎默认启用了大页面功能。 要检查内核是否为真,请使用以下命令并查找包含“ huge”的输出行:
shell> cat /proc/meminfo | grep -i huge
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 4096 kB
非空命令输出表示存在大页面支持,但零值表示没有配置页面供使用。
如果您的内核需要重新配置以支持大页面,请参阅hugetlbpage.txt文件以获取说明。
假设您的Linux内核已启用大页面支持,请使用以下命令将其配置为供MySQL使用。 通常情况下,您将这些文件放入系统启动序列期间执行的rc文件或等效启动文件中,以便每次系统启动时执行这些命令。 在MySQL服务器启动之前,命令应该在引导序列中尽早执行。 请务必根据您的系统更改分配编号和组编号。
# Set the number of pages to be used.# Each page is normally 2MB, so a value of 20 = 40MB.# This command actually allocates memory, so this much# memory must be available.
echo 20 > /proc/sys/vm/nr_hugepages# Set the group number that is permitted to access this# memory (102 in this case). The mysql user must be a# member of this group.
echo 102 > /proc/sys/vm/hugetlb_shm_group# Increase the amount of shmem permitted per segment# (12G in this case).
echo 1560281088 > /proc/sys/kernel/shmmax# Increase total amount of shared memory. The value# is the number of pages. At 4KB/page, 4194304 = 16GB.echo 4194304 > /proc/sys/kernel/shmall
对于MySQL的用法,通常希望shmmax的值接近shmall的值。
要验证大页面配置,请按照前面所述再次检查/ proc / meminfo。 现在你应该看到一些非零值:
cat /proc/meminfo | grep -i huge
HugePages_Total: 20
HugePages_Free: 20
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 4096 kB
使用hugetlb_shm_group的最后一步是为MySQL用户提供一个“无限制”的memlock限制值。 这可以通过编辑/etc/security/limits.conf或将以下命令添加到mysqld_safe脚本来完成:
ulimit -l unlimited
将ulimit命令添加到mysqld_safe会导致root用户在切换到mysql用户之前将memlock限制设置为unlimited。 (这假定mysqld_safe是由root启动的。)
MySQL中的大页面支持默认是禁用的。 要启用它,请使用--large-pages选项启动服务器。 例如,您可以在服务器的my.cnf文件中使用以下行:
[mysqld]
large-pages
使用此选项,InnoDB会自动为其缓冲池和附加内存池使用大页面。 如果InnoDB无法做到这一点,它将回退到使用传统内存并向错误日志写入警告:
Warning: Using conventional memory pool
要验证是否正在使用大页面,请再次检查/ proc / meminfo:
shell> cat /proc/meminfo | grep -i huge
HugePages_Total: 20
HugePages_Free: 20
HugePages_Rsvd: 2
HugePages_Surp: 0
Hugepagesize: 4096 kB
8.12.6 优化 网络使用
8.12.6.1 mysql 使用线程的客户端连接
连接管理器线程处理服务器侦听的网络接口上的客户端连接请求。 在所有平台上,一个管理器线程处理TCP / IP连接请求。 在Unix上,这个管理器线程还处理Unix套接字文件连接请求。 在Windows上,管理器线程处理共享内存连接请求,另一个处理命名管道连接请求。 服务器不会创建线程来处理它不会听的接口。 例如,不支持命名管道连接的Windows服务器不会创建线程来处理它们。
连接管理器线程将每个客户端连接与专用于它的线程关联,以处理该连接的身份验证和请求处理。 管理器线程在必要时创建一个新线程,但尝试通过首先查询线程缓存来查看它是否包含可用于连接的线程来避免这样做。 当连接结束时,如果缓存未满,则其线程返回到线程缓存。
在这种连接线程模型中,线程数量与当前连接的客户端数量一样多,当服务器工作负载必须按比例扩展以处理大量连接时,会存在一些缺点。 例如,线程创建和处理变得昂贵。 另外,每个线程都需要服务器和内核资源,例如堆栈空间。 为了容纳大量的同时连接,每个线程的堆栈大小必须保持很小,导致它或者太小或者服务器消耗大量内存。 其他资源也可能耗尽,调度开销可能会变得很大。
要控制和监视服务器如何管理处理客户端连接的线程,几个系统和状态变量是相关的。
线程缓存的大小由thread_cache_size系统变量确定。 默认值为0(不缓存),这会导致为每个新连接设置线程,并在连接终止时处理线程。 将thread_cache_size设置为N以启用缓存N个不活动的连接线程。 thread_cache_size可以在服务器启动时设置,也可以在服务器运行时更改。 连接线程在与其关联的客户端连接终止时变为非活动状态。
要监视高速缓存中的线程数以及创建了多少线程,因为无法从高速缓存中获取线程,请监视Threads_cached和Threads_created状态变量。
您可以在服务器启动时或运行时设置max_connections,以控制可同时连接的最大客户端数量。
当线程堆栈太小时,这会限制服务器可以处理的SQL语句的复杂性,存储过程的递归深度以及其他耗费内存的操作。 要为每个线程设置N字节的堆栈大小,请使用--thread_stack = N启动服务器。
8.12.6.2 DNS lookup 优化器和 主机缓存
MySQL服务器在内存中维护一个包含客户端信息的主机缓存:IP地址,主机名和错误信息。 服务器为非本地TCP连接使用此缓存。 它不使用用于使用回环接口地址(127.0.0.1或 ::1)建立的TCP连接的缓存,也不使用使用Unix套接字文件,命名管道或共享内存建立的连接。
对于每个新的客户端连接,服务器都使用客户端IP地址来检查客户端主机名是否在主机缓存中。 如果没有,则服务器尝试解析主机名。 首先,它将IP地址解析为主机名,并将该主机名解析为IP地址。 然后将结果与原始IP地址进行比较,以确保它们相同。 服务器将有关此操作结果的信息存储在主机缓存中。 如果缓存已满,则丢弃最近最少使用的条目。
host_cache性能架构表公开了主机高速缓存的内容,以便可以使用SELECT语句进行检查。 这可以帮助您诊断连接问题的原因。
服务器像这样处理主机高速缓存中的条目:
如果操作系统支持,则服务器使用线程安全gethostbyaddr_r()和gethostbyname_r()调用执行主机名解析。 否则,执行查找的线程将锁定一个互斥锁,并调用gethostbyaddr()和gethostbyname()。 在这种情况下,除非拥有互斥锁的线程释放它,否则其他线程无法解析主机缓存中未包含的主机名。
服务器使用主机缓存有以下几个目的:
要取消阻塞阻止的主机,请发出FLUSH HOSTS语句或执行mysqladmin flush-hosts命令来刷新主机缓存。
如果阻止的主机在最后一次连接尝试之后发生其他主机的活动,即使没有FLUSH HOSTS,阻止的主机也可能被解除阻塞。 发生这种情况的原因可能是服务器放弃了最近最少使用的高速缓存条目,以便在连接从不在高速缓存中的客户端IP到达,高速缓存已满的时候,为新条目腾出空间。 如果放弃的条目用于阻止的主机,则该主机将变为未阻止状态。
主机缓存默认启用。 要禁用它,请在服务器启动时或运行时将host_cache_size系统变量设置为0。
要禁用DNS主机名查找,请使用--skip-name-resolve选项启动服务器。 在这种情况下,服务器仅使用IP地址,而不使用主机名将连接主机与MySQL授权表中的行匹配。 只能使用那些使用IP地址的表中指定的帐户。 (请确保存在指定IP地址的帐户,否则您可能无法连接。)
如果您的DNS和主机速度非常慢,则可以通过使用--skip-name-resolve禁用DNS查找或通过增大host_cache_size的值以使主机缓存更大来提高性能。
要完全禁止TCP / IP连接,请使用--skip-networking选项启动服务器。
某些连接错误与TCP连接无关,在连接过程中很早(即使在知道IP地址之前),或者并非特定于任何特定IP地址(例如内存不足条件)。 有关这些错误的信息,请检查Connection_errors_xxx状态变量
8.12.7 线程池插件
注意:
MySQL线程池是包含在MySQL企业版中的一个扩展,这是一个商业产品。 要了解有关商业产品的更多信息,请访问http://www.mysql.com/products/。
从MySQL 5.7.9开始,MySQL企业版包含MySQL线程池,使用服务器插件实现。 MySQL服务器中的默认线程处理模型执行每个客户机连接使用一个线程的语句。 随着更多客户端连接到服务器并执行语句,整体性能下降。 线程池插件提供了另一种线程处理模型,旨在减少开销并提高性能。 该插件实现了一个线程池,该线程池通过高效地管理大量客户端连接的语句执行线程来提高服务器性能
线程池解决了每个连接模型的一个线程的一些问题:
线程池插件仅包含在MySQL企业版中。它不包含在MySQL社区分发版中。
在Windows上,线程池插件需要Windows Vista或更高版本。在Linux中,该插件需要内核2.6.9或更高版本。
8.12.7.1 线程池组件和安装
线程池功能包含以下组件:
INFORMATION_SCHEMA表被命名为TP_THREAD_STATE,TP_THREAD_GROUP_STATE和TP_THREAD_GROUP_STATS。
其他相关变量由线程池插件实现; 除非启用,否则它们不可用:
---这部分暂时不介绍了,因为本来使用mysql 就是看中的开源,免费。如果还需要商业组件,那就违背了选着mysql的初衷了。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69946831/viewspace-3165701/ ,如需转载,请注明出处,否则将追究法律责任。