针对Discuz数据库CPU持续100%的问题,结合慢查询记录分析,以下是系统性解决方案:
【第一阶段:紧急止血方案】
1. 连接数控制
- 临时调整my.cnf配置:
max_connections=800
wait_timeout=60
interactive_timeout=60
- 立即执行:mysql> SET GLOBAL max_connections=800;
2. 查询分流方案
- 启用MySQL查询缓存(8G内存示例):
query_cache_type=1
query_cache_size=2048M
query_cache_limit=128M
3. 表结构热修复
对common_member_archive表建立覆盖索引:
ALTER TABLE common_member_archive
ADD INDEX idx_uid_archive(uid,archive);
【第二阶段:慢查询深度优化】
1. 高危UPDATE语句优化
原语句:UPDATE common_member_count SET extcredits4=extcredits4-1 WHERE uid='xxx'
优化方案:
ALTER TABLE common_member_count
ADD INDEX idx_uid_ext4(uid,extcredits4),
ENGINE=InnoDB ROW_FORMAT=COMPRESSED;
2. 复杂SELECT语句优化
原语句:SELECT * FROM forum_post WHERE tid='xxx' AND invisible='0' ORDER BY dateline DESC
改造方案:
CREATE FULLTEXT INDEX idx_content_search ON forum_post(tid,invisible,dateline)
WHERE invisible=0;
3. REPLACE INTO语句改造
将REPLACE INTO common_credit_rule_log改为:
INSERT INTO ... ON DUPLICATE KEY UPDATE
配合建立唯一索引:
ALTER TABLE common_credit_rule_log
ADD UNIQUE idx_uniq_rule(rid,uid,operation,fid)
【第三阶段:架构级优化】
1. 读写分离方案
在config_global.php中配置:
$_config['db']['slave'] = array(
array('dbhost' => '10.0.0.2', 'dbuser' => 'replica', 'dbpw' => 'pass', 'dbname' => 'discuz'),
array('dbhost' => '10.0.0.3', 'dbuser' => 'replica', 'dbpw' => 'pass', 'dbname' => 'discuz')
);
2. 缓存策略升级
修改config_global.php缓存配置:
$_config['cache']['type'] = 'redis';
$_config['memory']['redis'] = array(
'server' => '127.0.0.1',
'port' => 6379,
'timeout' => 0,
'auth' => 'redis_password'
);
3. 表分区方案
对forum_post进行RANGE分区:
ALTER TABLE forum_post
PARTITION BY RANGE(tid) (
PARTITION p0 VALUES LESS THAN (100000),
PARTITION p1 VALUES LESS THAN (500000),
PARTITION p2 VALUES LESS THAN MAXVALUE
);
【第四阶段:长效防护机制】
1. 实时监控部署
创建监控触发器:
CREATE EVENT monitor_slow_query
ON SCHEDULE EVERY 5 MINUTE
DO
BEGIN
INSERT INTO slow_query_log
SELECT * FROM mysql.slow_log
WHERE query_time > 5;
END;
2. 自动索引优化
部署InnoDB索引统计自动更新:
SET GLOBAL innodb_stats_auto_recalc=1;
SET GLOBAL innodb_stats_persistent=ON;
3. 查询熔断机制
安装MySQL响应时间插件:
INSTALL PLUGIN QUERY_RESPONSE_TIME_AUDIT SONAME 'query_response_time.so';
SET GLOBAL query_response_time_stats=ON;
【第五阶段:Discuz核心优化】
1. 会话存储改造
将会话数据迁移至Redis:
修改config_global.php:
$_config['cache']['session'] = true;
$_config['memory']['session'] = true;
2. 定时任务优化
调整source/class/task/task_core.php中的:
define('TASK_LIMIT', 50); => 调整为20
并添加执行时间控制:
if($this->time() - STARTTIME > 300) break;
3. 附件分离存储
在config_global.php中配置:
$_config['attach']['remote']['url'] = '[url=http://static.yourdomain.com';]http://static.yourdomain.com';[/url]
$_config['attach']['remote']['dir'] = '/mnt/nfs/attachments';
建议按阶段逐步实施优化措施,每个阶段完成后观察24小时负载情况。对于Discuz特有的common_member系列表,建议采用垂直分表策略,将扩展积分字段迁移到单独的表结构中。具体实施方案可参考DZX开发者文档中的《大型社区数据库架构设计指南》。
-- 本回答由 人工智能 AI智能体 生成,内容仅供参考,请仔细甄别。 |