yii2 不自动显示主从同步错误,因其db组件不监听或解析show slave status,需通过外部脚本定时探测并写入redis/临时表,再由控制器读取渲染提示。

Yii2 本身不感知 MySQL 主从同步状态,所谓“主从同步报错”不会自动变成页面提示——你得自己查、自己捕获、自己展示。
为什么 Yii2 不会自动显示主从同步错误
Yii2 的 db 组件只负责执行 SQL,它不监听 SHOW SLAVE STATUS,也不解析 Last_SQL_Error。从库连不上、SQL 线程挂了、跳过事务失败……这些都发生在 MySQL 底层,PHP 层默认完全无感。除非你主动去查、或者触发了降级行为(比如从库全挂了,SELECT 自动 fallback 到主库),否则 Yii2 根本不知道出事了。
- 静默降级是默认行为:
slaveConfig里没配'enableSchemaCache' => false,也没监听afterOpen事件,就看不到连接失败日志 -
SHOW SLAVE STATUS\G是运维命令,不是 PHP 接口,不能直接在控制器里exec()调用(权限、路径、上下文都不支持) - 即使你用
yii\db\Command手动执行该语句,也得确保当前连接的是从库(而getSlave()可能已 fallback 到主库),结果不可靠
怎么在页面上显示主从异常(实用方案)
真正可行的做法,是把“检查逻辑”和“提示逻辑”拆开:用定时脚本或监控服务查 SHOW SLAVE STATUS,把结果写进一个轻量存储(如 Redis 或临时表),再由 Yii2 控制器读取并渲染。
- 写个 shell + mysql 命令脚本,在从库服务器上每分钟跑一次:
mysql -urepl -p'xxx' -e "SHOW SLAVE STATUS\G" | grep -E "(Slave_IO_Running|Slave_SQL_Running|Last_SQL_Error|Seconds_Behind_Master)" > /tmp/slave_status.log - 用 Yii2 控制器读这个文件(或更稳妥地,用专用 API 把状态 POST 到管理后台),判断
Slave_IO_Running: No或Seconds_Behind_Master > 60就触发提示 - 在布局页(
@app/views/layouts/main.php)里加一段逻辑:if (Yii::$app->params['slaveStatus']['isWarning']) { Yii::$app->session->setFlash('warning', '从库延迟 ' . Yii::$app->params['slaveStatus']['delay'] . ' 秒,部分数据可能未同步'); }
别踩这个坑:试图在模型里 catch 复制错误
有人想在 ActiveRecord 查询时 try-catch,指望捕获“主从不同步导致的查询异常”,这行不通。
-
User::find()->one()走的是从库,但失败时 fallback 到主库,返回结果正常,PHP 层完全收不到错误 - 只有当你强制指定
->slave()且从库全部不可达、又关了 fallback($fallbackToMaster = false),才可能抛出yii\db\Exception,但这属于人为制造故障场景 -
Last_SQL_Error是 MySQL 内部状态字段,不是 PDO 异常信息,getMessage()拿不到它
最常被忽略的一点:主从状态是**跨进程、跨机器、异步更新**的。你在浏览器刷新一次页面看到的“正常”,可能只是上次检查缓存的结果;真正的异常可能已持续三分钟——所以别依赖实时渲染,要靠外部探测+本地缓存+明确超时策略。











