在php项目中,当某张表的某个字段被修改时,我们经常需要通知其他模块或者执行额外业务逻辑,例如订单状态字段变更后推送消息。实现这种数据库字段变更通知,核心是要知道列什么时候被改了以及改成了什么。

一、使用数据库触发器加通知表
最传统的方式是在数据库里建触发器,当指定列更新时往一个通知表插入记录,php用脚本轮询该表。
-- 创建通知表
CREATE TABLE column_change_log (
id INT AUTO_INCREMENT PRIMARY KEY,
table_name VARCHAR(50),
column_name VARCHAR(50),
old_value VARCHAR(255),
new_value VARCHAR(255),
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
-- 监听用户表 balance 列修改
DELIMITER //
CREATE TRIGGER after_user_balance_update
AFTER UPDATE ON users
FOR EACH ROW
BEGIN
IF OLD.balance <> NEW.balance THEN
INSERT INTO column_change_log(table_name, column_name, old_value, new_value)
VALUES ('users', 'balance', OLD.balance, NEW.balance);
END IF;
END//
DELIMITER ;
php侧可用简单的定时任务读取日志表:
<?php
$pdo = new PDO('mysql:host=127.0.0.1;dbname=test', 'root', '');
$stmt = $pdo->query('SELECT * FROM column_change_log WHERE processed = 0 LIMIT 10');
foreach ($stmt as $row) {
// 触发业务逻辑,例如发送通知
file_put_contents('notify.log', $row['column_name'].':'.$row['old_value'].'->'.$row['new_value']."n", FILE_APPEND);
$pdo->exec('UPDATE column_change_log SET processed = 1 WHERE id = '.$row['id']);
}
?>
二、通过MySQL binlog监听列修改
如果希望实时且对业务代码无侵入,可以开启binlog,用php的binlog客户端库解析变更事件。
<?php
require 'vendor/autoload.php';
use MySQLReplicationMySQLReplicationFactory;
$config = [
'host' => '127.0.0.1',
'user' => 'repl',
'password' => 'repl_pass',
'db_name' => 'test'
];
$factory = new MySQLReplicationFactory($config);
while (true) {
$event = $factory->binLogEvent();
if ($event->getType() === 'UPDATE') {
$changes = $event->getValues();
// 判断特定列是否变化
if (isset($changes['balance'])) {
// 触发php业务逻辑
echo 'balance changed to '.$changes['balance']."n";
}
}
}
?>
三、在php业务层统一封装更新
若系统不大,可在php里把所有更新操作走同一个方法,在方法内对比旧值与新值。
<?php
class UserModel {
public function updateBalance($userId, $newBalance) {
$pdo = new PDO('mysql:host=127.0.0.1;dbname=test', 'root', '');
$old = $pdo->query('SELECT balance FROM users WHERE id='.$userId)->fetchColumn();
$pdo->exec('UPDATE users SET balance='.$newBalance.' WHERE id='.$userId);
if ($old != $newBalance) {
// 直接触发业务逻辑
$this->onBalanceChange($userId, $old, $newBalance);
}
}
private function onBalanceChange($id, $old, $new) {
file_put_contents('b.log', "$id:$old->$newn", FILE_APPEND);
}
}
?>
方案对比
| 方案 | 实时性 | 侵入性 | 复杂度 |
|---|---|---|---|
| 触发器加日志表 | 中 | 低 | 低 |
| binlog监听 | 高 | 无 | 高 |
| 业务层封装 | 高 | 高 | 低 |
实际项目中,若只是简单通知,用触发器或封装更新即可;若需跨系统解耦同步,binlog是更稳妥的选择。
phpdatabase_triggerbinlog修改时间:2026-07-28 02:54:22