跳到主要内容

第14章 MySQL优化

针对 MySQL 5.7 的调优,可以从多个维度进行,包括服务器硬件配置、MySQL 配置参数调整、查询优化和监控等方面。以下是一些针对 MySQL 5.7 的调优最佳实践:

1.硬件优化

**存储**:使用 SSD 可以显著提高 I/O 性能

**内存**:增加服务器 ECC内存 可以让更多的数据和索引保持在内存中,减少磁盘 I/O,尤其是通过增加 InnoDB 的缓冲池大小。

**CPU**:使用更快的 CPU 或多核 CPU 可以提高计算能力,英特尔 至强xeon 处理器 E3 E5 E7 16C

**RAID:**建议RAID10,兼顾安全及速度

**云服务器:**一步到位,把自己优化掉


2.系统优化

优化内核参数:

文件参数:

系统文件最大打开数 --> Linux里一切皆文件,每一个网络连接其实都算是创建一个文件

调大进程间传递消息的数据量和数据大小

网络调优:

增加SYN建立连接状态的数量

减少SYN建立连接状态时重试发包的次数

减少TIME_WAIT等待时间

快速回收处于TIME_WAIT状态的连接

允许复用处于TIME_WAIT状态的连接

调大处于TIME_WAIT状态的连接最大数量



# 在内核配置文件下添加参数

vim /etc/sysctl.conf

net.core.netdev_max_backlog = 400000
net.core.somaxconn = 4096
net.ipv4.tcp_max_syn_backlog = 819200


# 复用处理TIME-WAIT状态的连接

net.ipv4.tcp_tw_reuse=1

# 更快地回收TIME-WAIT套接字

net.ipv4.tcp_tw_recycle=0

vim limits.conf
nofile 63000

分区挂载:

使用xfs分区

数据目录挂载独立的磁盘

避免使用LVM 软RAID


专机专用:

只允许MySQL服务,不允许任何抢占资源的软件


3.配置优化

连接层:

最大连接数

最大数据包传输大小

慢日志:

开启慢日志

慢语句超时的时间

不走索引的慢语句记录

binlog日志:

开启binlog

binlog日志存储路径

binlog单个文件最大容量

binlog文件保留时间

binlog记录格式

binlog刷盘模式

存储引擎:

InnoDB buffer poll缓存池容量大小 系统内存50-80%

InnoDB 行锁等待超时时间

死锁检测开启

死锁超时自动回滚事务

复制:

开启GTID模式

server_id要不同

从库允许保存binlog

从库可自身信息,用于自动识别、监控等。

将复制信息存储在表中,而非文件中,方便管理和持久化。


修改 /etc/my.cnf 或者 MySQL 的配置文件来调整以下参数:

连接层:


# 最大连接数,决定了同时能够建立的最大连接数。


# 当出现“Too many connections”错误时,可适当调大。


# 建议值:100~3000 或根据实际并发情况调整。

max_connections = 1000


# 当客户端连接出现错误次数达到该值后,服务器会暂时阻断这个客户端的连接。


# 建议值:100(若网络波动频繁可适当调大)。

max_connect_errors = 100


# 非交互连接的超时时间(秒)。当超过此时间没有任何操作后,服务器将断开连接。


# 例如后端脚本或应用程序连接超时。


# 建议值:600(10分钟)或根据实际需要调整。

wait_timeout = 600


# 交互式连接的超时时间(秒)。例如通过 MySQL 客户端终端交互式连接。


# 建议值:600(10分钟),交互式操作一般足够。

interactive_wait_timeout = 600


# MySQL 读取数据包超时时间(秒)。如果在此时间内没有收到数据包,则会断开连接。


# 建议值:30 或更高。

net_read_timeout = 30


# MySQL 写数据包超时时间(秒)。如果在此时间内无法写入数据包(网络异常等),则会断开连接。


# 建议值:30 或更高。

net_write_timeout = 30


# 最大允许的通信数据包大小(字节),通常用于控制 BLOB/TEXT 等大字段插入。


# 需要设置得足够大以保证大数据传输,但也不能过大以免浪费内存。


# 建议值:16M ~ 64M,一般 64M 足够。

max_allowed_packet = 64M

server层:


# 安全更新模式,防止在没有 WHERE 条件时执行 UPDATE 或 DELETE 操作。


# 开启后可减少误操作风险,但可能在某些场景需要临时关闭。


# 建议设置:1

sql_safe_updates = 1


# 是否开启慢查询日志,用于记录执行时间超过 long_query_time 的SQL。


# 建议在生产环境开启,方便排查性能问题。

slow_query_log = ON


# 慢查询日志存放的文件路径。


# 需确保 MySQL 有写入权限,并注意磁盘容量。

slow_query_log_file = /xxx/mysql-slow.log


# 定义慢查询的阈值(秒),执行时间大于该值将被记录到慢查询日志。


# 建议值:1~5 秒 或根据实际性能要求设置。

long_query_time = 1


# 是否记录未使用索引的查询。


# 建议开启,以便及时发现需要优化的查询。

log_queries_not_using_indexes = ON


# 每秒仅记录一定条数未使用索引的查询,避免日志量过大而影响性能。


# 建议值:10

log_throttle_queries_not_using_indexes = 10


# sort_buffer、join_buffer、read_buffer、read_rnd_buffer 是 MySQL 在对结果集进行排序、连接、扫描等操作时使用的内存空间大小。


# 这些参数通常在会话级别设置,值过大可能引起内存不足;过小则可能影响查询性能。


# 建议根据服务器内存大小和实际业务场景进行设置:


# sort_buffer_size = 2M ~ 4M


# join_buffer_size = 2M ~ 4M


# read_buffer_size = 2M ~ 4M


# read_rnd_buffer_size = 2M ~ 4M


# 这里仅做示例:

sort_buffer_size = 2M
join_buffer_size = 2M
read_buffer_size = 2M
read_rnd_buffer_size = 2M


# tmp_table_size / max_heap_table_size 决定了内存临时表的最大大小,


# 如果超过此大小会自动转为磁盘临时表,影响性能。


# 建议值:256M ~ 1G,需根据内存容量及临时表使用量调整。

tmp_table_size = 256M
max_heap_table_size = 256M


# sql_mode 用于定义 SQL 的语法行为和兼容性。建议保持相对严格的模式,防止潜在的数据问题。


# 常用推荐:STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION

sql_mode = "建议保持默认"


# 最大执行时间(毫秒)。超过此时间的语句将被强制终止,可防止低效语句长时间占用资源。


# 建议值:0 表示不限制,如要限制可根据业务需求设置。

max_execution_time = 0


# 锁等待超时时间(秒)。超过此时间将报告锁等待超时错误。


# 建议值:50~120。

lock_wait_timeout = 50


# 设置是否忽略表名大小写的差异。


# 0:区分大小写;1:不区分大小写。Windows 建议使用 1,与 Windows 文件系统一致。

lower_case_table_names = 1


# 线程缓存大小,用于缓存连接线程,减少创建/销毁线程的开销。


# 建议值:32~256,根据并发量和内存情况设置。

thread_cache_size = 64


# 服务器默认字符集,推荐使用 utf8mb4 支持更多字符。


# character_set_server = utf8 或者 utf8mb4

character_set_server = utf8mb4


# 日志时间戳使用的时区。SYSTEM 表示使用操作系统时间。

log_timestamps = SYSTEM


# 在每个客户端连接时执行的初始化语句,一般用于设置字符集等。


# 需与 character_set_server 保持一致。

init_connect = "SET NAMES utf8mb4"


# 是否开启事件调度器,默认 OFF。


# 在不需要定时任务执行时关闭可减少无用开销。

event_scheduler = OFF


# 安全导出/导入文件的路径,用于 LOAD DATA INFILE 或 SELECT ... INTO OUTFILE。


# 建议将其指向一个安全路径,避免数据泄露或被覆盖。

secure-file-priv = /xxx/mysql-files


# 二进制日志过期天数,超过该天数的 binlog 自动删除。


# 建议值:7~30 天,视备份及审计需求而定。

expire_logs_days = 10


# sync_binlog 用来控制每次事务提交时,是否立即将 binlog 刷新到磁盘。


# 1 表示每次事务提交都刷新;安全性高但性能低;可根据业务情况设置。

sync_binlog = 1


# 打开二进制日志,并指定存放路径。


# 注意目录的磁盘空间;生产环境建议与数据目录分开。

log-bin = /opt/log/mysql/blog/mysql-bin
log-bin-index = /opt/log/mysql/blog/mysql-bin.index


# 每个 binlog 文件的大小上限,超过此值会滚动生成下一个 binlog 文件。


# 建议值:100M ~ 1G。

max_binlog_size = 500M


# binlog_format 表示二进制日志的记录格式。推荐使用 ROW 格式更精确,但会增大日志体积。

binlog_format = ROW


# binlog 缓存大小,单个事务可以使用的 binlog 缓存大小。


# 当事务过大时,可增大该值避免写到临时文件。

max_binlog_cache_size = 2G


# 类似 max_binlog_cache_size,只用于语句缓存。

max_binlog_stmt_cache_size = 2G


存储引擎层:


# 事务隔离级别,推荐使用 READ-COMMITTED 或 REPEATABLE-READ。


# READ-COMMITTED 能减少行锁竞争,适合大多数应用场景。

transaction-isolation = "READ-COMMITTED"


# InnoDB 数据文件存放目录

innodb_data_home_dir = /xxx


# InnoDB redo 日志文件存放目录

innodb_log_group_home_dir = /xxx


# InnoDB redo 日志文件大小,增大该值可减少日志切换,但恢复时需要更长的扫描时间。


# 如果修改该值,需要先关闭 MySQL、删除或备份原日志文件,然后再启动 MySQL。


# 建议值:512M ~ 4G。常见为 1G ~ 2G。

innodb_log_file_size = 2048M


# InnoDB redo 日志文件组数量。通常 2~3 个即可,过多无明显收益。

innodb_log_files_in_group = 3


# 事务提交时刷新 redo 日志的策略:


# 0:不实时刷新(可能丢数据),1:实时刷新(最安全、性能一般),2:每秒刷新(安全性和性能折中)。


# 通常在 OLTP 应用中可设置为 1 或 2。

innodb_flush_log_at_trx_commit = 2


# 写数据到 InnoDB 文件时使用的刷新方法。O_DIRECT 能减少缓存重复,fsync 适用于不同操作系统。


# 如果所在文件系统支持 O_DIRECT,可优先使用;否则使用 fsync。

innodb_flush_method = O_DIRECT


# IO 能力设定。用于限制 InnoDB 后台刷脏页及其他 IO 操作的频率。


# 建议值:100 ~ 几千;若磁盘是 SSD,性能较好,可调大。

innodb_io_capacity = 1000


# IO 能力最大值。可在高负载时临时提高写入速度,避免积压过多脏页。

innodb_io_capacity_max = 4000


# InnoDB Buffer Pool 大小。主要用来缓存索引和数据,以提高性能。


# 通常建议配置为物理内存的 50% ~ 80%。需预留内存给系统和其他进程。


# 大型数据库可适当增大;这里示例 64G。

innodb_buffer_pool_size = 64G


# Buffer Pool 的实例数,避免单个 buffer pool 互斥导致的性能瓶颈。


# 一般每 4~8G 分配 1 个实例。示例设为 4。

innodb_buffer_pool_instances = 4


# InnoDB redo 日志缓存大小。若大事务较多,可适当增大。


# 建议值:8M ~ 128M。

innodb_log_buffer_size = 64M


# InnoDB 最大脏页比例,达到该比例后会加速刷脏页,避免崩溃时数据丢失过多。


# 默认值 75。若写入量大可适当调高到 85。

innodb_max_dirty_pages_pct = 85


# InnoDB 行锁等待超时时间(秒)。超过该时间将报错。


# 建议值:10~30。

innodb_lock_wait_timeout = 10


# InnoDB 能打开的表的数量限制,主要影响系统表缓存。


# 建议值:大于数据库内表总数,默认 300。可调整到几万。

innodb_open_files = 63000


# InnoDB 页面清理线程数,配合高并发或大 Buffer Pool 时可增加。


# 建议值:CPU 核心数/4 或根据压测结果设置。

innodb_page_cleaners = 4


# 排序相关的内存缓冲大小(InnoDB 特有)。


# 对大规模排序操作有帮助,但要注意不能过大导致内存不足。

innodb_sort_buffer_size = 64M


# 是否打印出所有死锁信息到错误日志。开启可帮助快速排查死锁。

innodb_print_all_deadlocks = 1


# 当超时或异常时,是否自动回滚事务。


# ON 可以避免长时间占用锁资源。

innodb_rollback_on_timeout = ON


# 是否开启死锁检测。如果大并发环境下经常出现死锁,可关闭以避免大量检测开销。


# 但关闭后不会自动检测死锁,需要通过超时处理。

innodb_deadlock_detect = ON

复制相关:


# relay_log 存放位置,注意磁盘空间。

relay_log = /opt/log/mysql/blog/relay
relay_log_index = /opt/log/mysql/blog/relay.index


# relay log 单个文件大小上限,超过将滚动生成下一个 relay log 文件。

max_relay_log_size = 500M


# 是否自动清理已经应用完成的 relay log。

relay_log_purge = ON


# 开启 relay log 的自动恢复功能,崩溃后自动恢复复制状态,减少手动干预。

relay_log_recovery = ON


# 半同步复制,主库在提交事务后,会等待至少一个从库确认才返回成功。


# 有助于减少数据丢失风险,但会增加主库延迟。

rpl_semi_sync_master_enabled = ON


# 主库等待从库确认的超时时间,单位毫秒。


# 超时后将自动切换为异步复制,避免阻塞过久。

rpl_semi_sync_master_timeout = 1000


# 半同步复制调试级别,范围 0~32,一般不需要特别调整。

rpl_semi_sync_master_trace_level = 32


# 主库等待的从库数量,通常为 1 即可保证至少一台从库收到事务。

rpl_semi_sync_master_wait_for_slave_count = 1


# 当没有从库可用时,主库是否继续等待。如果为 ON,且从库不可用,则会阻塞。


# 推荐 ON,确保数据安全;如果需要高可用则视情况选择。

rpl_semi_sync_master_wait_no_slave = ON


# 主库在事务提交的哪个阶段等待从库。AFTER_SYNC 表示已经写入 binlog 后再等待。


# 另一个常见值为 AFTER_COMMIT。

rpl_semi_sync_master_wait_point = AFTER_SYNC


# 从库是否启用半同步复制。

rpl_semi_sync_slave_enabled = ON


# 半同步复制调试级别,同 master_trace_level。

rpl_semi_sync_slave_trace_level = 32


# Binlog group commit 相关参数,用于批量同步,降低磁盘刷写次数,提高性能。


# binlog_group_commit_sync_delay:延迟指定微秒后再刷盘,可提升吞吐量但增加延时。


# binlog_group_commit_sync_no_delay_count:累计多少事务后再刷盘。

binlog_group_commit_sync_delay = 1
binlog_group_commit_sync_no_delay_count = 1000


# 是否开启 GTID(全局事务 ID),并强制一致性检查。


# 用于更可靠的复制,避免重复或丢失事务。

gtid_mode = ON
enforce_gtid_consistency = ON


# 是否验证主库传给从库的 binlog 校验和数据完整性。

master_verify_checksum = ON


# sync_master_info = 1 表示在每次事务后将复制信息同步到磁盘,提高安全性。


# 如果性能瓶颈较大,可以改为更低频率同步。

sync_master_info = 1


# 跳过自动启动从库复制进程。适用于需要人工控制复制启动的场景。

skip-slave-start = 1


# read_only 与 super_read_only 配合使用可以保护从库、只读环境。


# 若需要切换主从,或做维护时可打开。


# read_only = ON


# super_read_only = ON



# 是否在从库上记录更新到 binlog。若从库还需要继续复制下级从库时,需要设置为 ON。

log_slave_updates = ON


# server_id 表示实例唯一 ID,用于区分不同服务器的复制。

server_id = xxx


# 在主从架构中,从库可向主库报告自身信息,用于自动识别、监控等。

report_host = xxxx
report_port = 3306


# 并行复制的模式与并行线程数。LOGICAL_CLOCK 模式在 5.7+ 中表现较好。


# slave_parallel_workers 表示并行线程数量,需根据负载和硬件评估。

slave_parallel_type = LOGICAL_CLOCK
slave_parallel_workers = 4


# 将复制信息存储在表中,而非文件中,方便管理和持久化。

master_info_repository = TABLE
relay_log_info_repository = TABLE

4.SQL优化

**使用 EXPLAIN**:对查询使用 EXPLAIN 来分析和优化查询执行计划。

**索引优化**:确保使用有效的索引,定期检查和优化索引。

**避免全表扫描**:尽可能修改查询以使用索引,减少全表扫描。


5.监控和维护

**慢语句监控:**

**死锁监控:**

**使用性能模式**:使用 SHOW ENGINE INNODB STATUS 和 SHOW PROCESSLIST 监控数据库操作和性能状况。

**定期备份**:确保有定期的数据库备份和恢复策略。

**日志维护**:监控和维护错误日志、慢查询日志来帮助诊断问题。


6.使用工具和插件

**Percona Toolkit**:使用 Percona Toolkit 来帮助诊断和优化 MySQL 性能。

**MySQLTuner**:运行 MySQLTuner 脚本来分析 MySQL 配置并获得具体的调优建议。

以上是 MySQL 5.7 调优的一些基本方向和建议。实际操作中,每一步的调优都需要仔细考虑,并且可能需要根据具体的工作负载和应用场景进行

调整。在进行重大配置更改后,始终推荐进行充分的测试,以确保改动带来预期的效果。


更新: 2025-01-11 14:56:50