我正在运行 MariaDB 11.4.4 和一个繁忙的网站(Debian12+nginx+php-fpm)。
每隔几天 MariaDB 线程就会冻结一次,直到达到最大连接数。即使终止查询也不会释放线程。MariaDB 无法关闭 最后systemctl stop mariadb
我需要killall -9 mariadbd
恢复操作。mysql/error.log 或 slow_query.log 中没有任何意外
以下是在 MariaDB 完全锁定之前拍摄的 SHOW FULL PROCESSLIST、SHOW GLOBAL STATUS 和 SHOW ENGINE INNODB STATUS 图像:
https://pastejustit.com/mariadb-debug-info
显示变量在这里:
过去也曾有过类似的报告,但它们与旧版本的 MariaDB 有关,没有明确的解决方案,并且很可能在 MariaDB 10.6 中得到修复。*
有什么想法可以避免这个问题吗?
添加:fully_ping
表定义
CREATE TABLE `fully_ping` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`devid` varchar(255) NOT NULL,
`appid` int(11) NOT NULL DEFAULT 1,
`firstping_time` datetime DEFAULT NULL COMMENT 'UTC',
`lastping_time` datetime NOT NULL COMMENT 'UTC',
`message` mediumtext NOT NULL,
`pass` varchar(255) DEFAULT NULL,
`ip` varchar(255) DEFAULT NULL,
`serial` varchar(255) DEFAULT NULL,
`counter` int(11) NOT NULL DEFAULT 0,
`version` int(11) DEFAULT NULL,
`tls_version` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `devid` (`devid`(191)),
KEY `appid` (`appid`),
KEY `lastping_time` (`lastping_time`),
KEY `counter` (`counter`),
KEY `serial` (`serial`),
CONSTRAINT `fully_ping_ibfk_1` FOREIGN KEY (`appid`) REFERENCES `fully_apps` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=180169 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci
我在 Debian 上遇到了同样的问题。这可能是触发我的问题的原因: https://bugs.debian.org/cgi-bin/bugreport.cgi ?bug=1093243
请提供
SHOW CREATE TABLE fully_ping
这可能会有所帮助:
您能将 的声明改为 吗
devid
?VARCHAR(191)
或者其中一些太长了?并替换
经过
以及
嗯......状态/变量中有一些有趣的事情:
观察结果:
更重要的问题:
建议更改设置:
更改客户端以减少与 MariaDB 的连接积极性。当您有 600 个连接(参见 Max_used_connections)时,每个连接都会阻碍其他所有连接。如果您使用的是 Apache,请降低那里的子节点数量,并让它积累积压。
为什么有这么多 SET 命令?(987/秒)查看连接池(重新 987 个连接/秒)
让我们看看 slowlog - 那里可能有更多线索:( https://mysql.rjweb.org/doc.php/mysql_analysis#slow_queries_and_slowlog ) 这可能有助于解决正在创建的大量 tmp_tables 问题。
详细信息和其他观察结果:
( Key_blocks_used * 1024 / key_buffer_size ) = 0 * 1024 / 128M = 0
-- key_buffer 的使用百分比。高水位线。-- 降低 key_buffer_size(现在为 134217728)以避免不必要的内存使用。( Table_open_cache_misses ) = 115349902 / 120277 = 959 /sec
-- 可能需要增加 table_open_cache (现在为 2000)( Table_open_cache_misses / (Table_open_cache_hits + Table_open_cache_misses) ) = 115,349,902 / (1508587798 + 115349902) = 7.1%
-- table_open_cache 的有效性。-- 增加 table_open_cache(现在为 2000)并检查 table_open_cache_instances(现在为 8)。( binlog_cache_size * max_connections ) = (16M * 700) / 16384M = 68.4%
-- 用于在传输到 binlog 的途中缓存事务的 RAM。 -- 减少 binlog_cache_size(现在为 16777216)和/或 max_connections(现在为 700)( innodb_lru_scan_depth ) = 1,536
-- innodb_lru_scan_depth 是一个命名很差的变量。更好的名称应该是 innodb_free_page_target_per_buffer_pool。它是 InnoDB 尝试在每个缓冲池实例中保留的页面数,以加快读取和页面创建操作。--“InnoDB:page_cleaner:预期循环花费 1000ms ...”可以通过降低 lru_scan_depth 来修复( innodb_io_capacity ) = 200
-- 刷新时,使用这么多 IOP。-- 读取可能会很慢或不稳定。如果使用 SSD 驱动器,请使用 2000。( Innodb_buffer_pool_pages_free / Innodb_buffer_pool_pages_total ) = 418,553 / 648960 = 64.5%
-- 缓冲池的百分比当前未使用 -- innodb_buffer_pool_size(现在为 10737418240)是否大于必要的?( innodb_io_capacity_max / innodb_io_capacity ) = 2,000 / 200 = 10
-- 容量:最大/普通 -- 推荐 2。最大容量应大约等于 I/O 子系统可以处理的 IOP。(如果驱动器类型未知,2000/200 可能是合理的一对。)( Innodb_buffer_pool_bytes_data / innodb_buffer_pool_size ) = 3,774,693,376 / 10240M = 35.2%
-- 数据占用缓冲池的百分比 -- 较小的百分比可能表示缓冲池不必要的大。( Innodb_os_log_written ) = 505660239032 / 120277 = 4204130 /sec
-- 这是 InnoDB 繁忙程度的指标。-- 非常空闲或非常繁忙的 InnoDB。( Innodb_log_writes ) = 40547610 / 120277 = 337 /sec
( Uptime / 60 * innodb_log_file_size / Innodb_os_log_written ) = 120,277 / 60 * 2048M / 505660239032 = 8.51
-- InnoDB 日志轮换间隔分钟数 从 5.6.8 开始,innodb_log_file_size 可以动态更改;我不知道 MariaDB 的情况。一定要更改 my.cnf --(建议轮换间隔 60 分钟,这有点武断。)调整 innodb_log_file_size(现在为 2147483648)。(在 AWS 中无法更改。)( Innodb_num_open_files/innodb_open_files ) = 76/2000 = 3.8%
-- 当前正在使用的 InnoDB 文件缓存的百分比 (?) -- innodb_open_files (现在为 2000) 太小 = 浪费 RAM;太大:系统崩溃。( default_tmp_storage_engine ) = default_tmp_storage_engine =
( Innodb_row_lock_waits ) = 13945 / 120277 = 0.12 /sec
-- 获取行锁的延迟频率。-- 可能是由可以优化的复杂查询引起的。( innodb_flush_neighbors ) = innodb_flush_neighbors = 1
-- 将块写入磁盘时进行小幅优化。-- 对于 SSD 驱动器使用 0;对于 HDD 使用 1。( innodb_io_capacity ) = 200
-- 磁盘每秒可执行的 I/O 操作数。慢速驱动器为 100;旋转驱动器为 200;SSD 为 1000-2000;乘以 RAID 因子。限制每秒写入 IOPS。-- 首先:HDD:200;SSD:2000。( innodb_flush_log_at_trx_commit ) = 1
-- 1 = 安全;2 = 更快 -- (您决定)使用 1,以及 sync_binlog(现在为 0)=1,以获得最高级别的容错能力。0 最适合速度。2 是 0 和 1 之间的折衷。( sync_binlog ) = 0
-- 使用 1 来增加安全性,但会花费一些 I/O 成本 =1 可能会导致大量“查询结束”;=0 可能会导致“binlog 处于不可能的位置”并在崩溃时丢失事务,但速度更快。对于 Galera 来说 0 是可以的。( innodb_print_all_deadlocks ) = innodb_print_all_deadlocks = OFF
-- 是否记录所有死锁。-- 如果您受到死锁的困扰,请启用此功能。注意:如果您有大量死锁,这可能会将大量数据写入磁盘。( min( tmp_table_size, max_heap_table_size ) ) = (min( 256M, 256M )) / 16384M = 1.6%
-- 需要 MEMORY 表(每个表)或 SELECT 中的临时表(每个临时表每个某些 SELECT)时分配的 RAM 百分比。太高可能会导致交换。-- 将 tmp_table_size(现在为 268435456)和 max_heap_table_size(现在为 268435456)减少到 RAM 的 1%。( innodb_ft_result_cache_limit ) = 2,000,000,000 / 16384M = 11.6%
-- 全文结果集的字节限制。(它会根据需要增长。)-- 降低设置。( character_set_client ) = character_set_client = utf8mb3
-- -- 如果您要使用西欧以外地区的文本,请考虑切换到 utf8mb4。(超出了本讨论范围。)( character_set_connection ) = character_set_connection = utf8mb3
--( character_set_results ) = character_set_results = utf8mb3
--( log_warnings ) = log_warnings = 4
( Max_statement_time_exceeded ) = 594 / 120277 = 18 /HR
—— 识别已经中止的长时间运行的语句。( local_infile ) = local_infile = ON
-- local_infile(现在为 ON)= ON 是一个潜在的安全问题( Com_set_option ) = 118817521 / 120277 = 987 /sec
-- 使用 SET 选项的频率 -- 为什么这么高?( Questions ) = 937764234 / 120277 = 7796 /sec
-- 查询(SP 之外)--“qps”-->2000可能会给服务器带来压力( Queries ) = 937764234 / 120277 = 7796 /sec
-- 查询(包括 SP 内部)-- >3000可能会给服务器带来压力( Created_tmp_tables ) = 4922791 / 120277 = 41 /sec
——作为复杂 SELECT 的一部分创建“临时”表的频率。( Created_tmp_disk_tables ) = 3193850 / 120277 = 27 /sec
-- 作为复杂 SELECT 的一部分创建磁盘“临时”表的频率 -- 增加 tmp_table_size(现在为 268435456)和 max_heap_table_size(现在为 268435456)。检查使用 MEMORY 而不是 MyISAM 时的临时表规则。也许较小的架构或查询更改可以避免使用 MyISAM。更好的索引和查询的重新表述更有可能有所帮助。( Created_tmp_disk_tables / Created_tmp_tables ) = 3,193,850 / 4922791 = 64.9%
-- 溢出到磁盘的临时表的百分比 -- 可能增加 tmp_table_size(现在为 268435456)和 max_heap_table_size(现在为 268435456);改进索引;避免 blob 等。( tmp_table_size ) = 256M
-- 用于支持 SELECT 的MEMORY临时表的大小限制-- 减小 tmp_table_size(现在为 268435456)以避免 RAM 耗尽。可能不超过 64M。( Com_show_variables ) = 240531 / 120277 = 2 /sec
-- 显示变量...-- 为什么您如此频繁地请求变量?( Com_insert + Com_delete + Com_delete_multi + Com_replace + Com_update + Com_update_multi ) = (673370 + 23336 + 8020 + 5 + 117459591 + 0) / 120277 = 982 /sec
-- 写入次数/秒 -- 50 次写入次数/秒 + 日志刷新可能会使普通驱动器的 I/O 写入容量达到最大限度( binlog_format ) = binlog_format = MIXED
-- 语句/行/混合。-- 5.7 (10.3) 首选行( expire_logs_days ) = 1.9867897033691E-8M = 0.0208
-- 多久自动清除 binlog(这么多天后)。由 binlog_expire_logs_seconds 替换。-- 太大(或为零)= 消耗磁盘空间;太小 = 需要快速响应网络/机器崩溃。(如果 log_bin(现在为 OFF)= OFF,则不相关)( Max_used_connections ) = 604
-- 连接的高水位标记 -- 存在大量非活动连接是可以的;超过 100 个活动连接可能存在问题。Max_used_connections(现在为 604)无法区分它们;Threads_running(现在为 603)是即时的。( Connections ) = 118801097 / 120277 = 987 /sec
-- 连接 -- 增加 wait_timeout(现在为 28800);使用池?( Threads_connected / max_connections ) = 604 / 700 = 86.3%
-- 线程数,占最大允许数量的百分比 -- 增加 max_connection,减少 Apache 的 MaxClients,减少 wait_timeout(现在为 28800)( Threads_running - 1 ) = 603 - 1 = 602
-- 活动线程(数据收集时的并发性)-- 优化查询和/或架构。如果值超过 CPU 核心数的两倍,则可能表示超载。( Threads_running / thread_cache_size ) = 603 / 256 = 2.36
-- 线程:当前 / 缓存(使用线程池时不相关)-- 优化查询( thread_pool_max_threads ) = 65,536
-- MariaDB 线程池的众多设置之一 -- 降低值。您已将查询缓存关闭一半。您应该同时设置 query_cache_type = OFF 和 query_cache_size = 0 。据传言,QC 代码中有一个“错误”,除非您关闭这两个设置,否则某些代码会一直处于打开状态。
异常小:
异常大: