排查MariaDB Galera Cluster与Apache Fetch语句的延迟问题
MariaDB Galera集群实时查询延迟随时间升高问题排查
近期将MariaDB Galera集群接入实时系统后,出现网站打开时间越久,数据库Fetch调用延迟越高的问题。具体表现为:查询初始延迟约20ms,20分钟后延迟升至200ms;由于用户可能连续数小时打开网站,且每秒执行一次Fetch请求,当延迟超过1秒时会引发内存泄漏。
补充背景:
- 该查询返回约50列数据,网站加载时会清空表,表数据量不大
- 此前使用单节点数据库无此问题,已确认所有程序连接同一集群节点
- 集群与网站工作站在同一网络,未经过流量管理器,节点间通过10GB交换机连接,同步速度快
- 开发PC上单节点MariaDB+Apache无延迟升高情况,测试时仅打开一个标签页,数据库未遭遇大量连接/重连请求(计划用Memcache优化)
代码示例
PHP查询语句
<?php //echo 'before'.utime(true); $dbquery= "SELECT * FROM `MyTable` WHERE Column = '$value' ORDER BY Id DESC LIMIT 1"; $result = $db->prepare($dbquery); $result->execute(); $myResults = $result->fetchAll(); //echo 'after:'.utime(true); echo json_encode($myResults); ?>
JavaScript定时调用代码
//javascript this.ahaTimeout = setTimeout(() => { this.ahaInterval = setInterval(tmpFunction => { fetch("myDBcall.php", { method: 'post', headers: { "Content-type": "application/x-www-form-urlencoded; charset=UTF-8" } }).then(response => response.json()).then(data => { //do stuff }, 1000) }, 1000 - new Date().getMilliseconds());
集群配置文件
my.cnf
[client-server] !includedir /etc/my.cnf.d [mysqld] query_cache_type=0 query_cache_size=0 max_allowed_packet=768M
server.cnf
[mysqld] datadir=/var/lib/mysql socket=/var/lib/mysql/mysql.sock bind-address=<nodeIPaddress> user=mysql innodb_autoinc_lock_mode=2 innodb_flush_log_at_trx_commit=0 innodb_buffer_pool_size=128M log-error=/var/log/mysqld/log [galera] wsrep_on=ON wsrep_provider=/usr/lib64/galera-4/libgalera_smm.so wsrep_node_name='mynode' wsrep_node_incoming_address='<nodeIPaddress>' wsrep_node_address='<10GBnetworkIPaddress>' wsrep_cluster_name='myCluster' wsrep_cluster_address="gcommm://<10GBnode1IP>:4567,<10GBnode2IP>:4567,<10GBnode3IP>:4567" wsrep_provider_options='gcache.size=300M;gcache.page_size=300M;gcs.max_packet_size=1024000' wsrep_slave_threads=4 wsrep_sst_method=rsync
排查思路与解决方案
数据库层面排查
- 调整InnoDB缓冲池:当前
innodb_buffer_pool_size=128M过小,频繁查询易导致缓存命中率下降、磁盘IO升高。建议根据服务器内存调整(如8核16G服务器可设为12G)。 - 监控Galera集群状态:执行
SHOW STATUS LIKE 'wsrep_%';,重点关注wsrep_flow_control_paused(是否触发流控)、wsrep_local_recv_queue_avg(接收队列平均长度),排查节点同步延迟是否拖慢查询。 - 开启慢查询日志:在
my.cnf中添加配置:
记录慢查询,确认是否存在执行计划随时间变化的情况。slow_query_log=1 slow_query_log_file=/var/log/mysql/slow.log long_query_time=0.05 - 检查连接与锁状态:执行
SHOW PROCESSLIST;,查看是否有未释放的连接或锁等待,排查Galera下隐式事务未提交的可能。
应用层面优化
- 修复SQL注入与执行计划缓存:当前PHP代码直接拼接
$value存在注入风险,且未正确使用参数绑定,改为:
参数绑定可让数据库缓存执行计划,避免重复解析SQL。$dbquery= "SELECT * FROM `MyTable` WHERE Column = ? ORDER BY Id DESC LIMIT 1"; $result = $db->prepare($dbquery); $result->execute([$value]); - 优化查询与索引:避免
SELECT *,只查询需要的列;创建联合索引CREATE INDEX idx_column_id ON MyTable(Column, Id DESC);,提升查询效率。 - 启用持久化连接:PHP使用PDO时添加
PDO::ATTR_PERSISTENT => true配置,复用数据库连接,减少连接建立开销。 - 调整前端轮询策略:每秒一次Fetch过于频繁,可根据业务需求延长间隔,或改用WebSocket推送替代轮询,降低服务器与数据库压力。
系统层面排查
- 监控磁盘IO:用
iostat或iotop查看磁盘读写情况,确认是否因磁盘性能瓶颈导致延迟升高。 - 检查内存与Swap:执行
free -m,确认是否存在内存不足触发Swap的情况,Swap会严重拖慢数据库性能。
内容的提问来源于stack exchange,提问作者squidmonkey
相关产品推荐
相关产品推荐

