跳转到主内容
极星编程网:以代码为星,赴技术山海!

Yii框架如何定时清理数据_Yii框架自动化运维脚本【运维】

直接用crontab调用Yii控制台命令最稳妥,因Web请求生命周期短、易超时且并发不安全;应编写分批删除、带休眠和日志的console命令,并配置绝对路径crontab定时执行。 直接用
crontab
调用 Yii 控制台命令是最稳妥、最可控的方式,别碰
sleep
或后台常驻 PHP 进程。 为什么不能在 Web 请求里做定时清理 Web 请求生命周期短、超时限制严(通常 30–60 秒),而数据清理常涉及大批量查询、事务、I/O,极易被中断或触发
max_execution_time
错误;更危险的是,多个并发请求可能同时触发同一清理逻辑,导致重复删除、数据错乱或锁表。Yii 的
console
应用专为长时间、独占式任务设计,天然规避这些问题。 怎么写一个安全的清理命令(以清理过期订单为例) 在
console/controllers
下新建
CleanupController.php
:
namespace console\controllers;

use yii\console\Controller; use yii\db\Query; use yii\helpers\Console;

class CleanupController extends Controller { public function actionOrders($days = 90) { $cutoff = time() - ($days * 86400);

    // 先查再删,避免大事务卡死
    $ids = (new Query())
        ->select('id')
        ->from('order')
        ->where(['<', 'created_at', $cutoff])
        ->andWhere(['status' => 'cancelled'])
        ->column();

    if (empty($ids)) {
        $this->stdout("No expired cancelled orders found.\n", Console::FG_GREEN);
        return self::EXIT_CODE_NORMAL;
    }

    // 分批删除,每批最多 1000 条
    foreach (array_chunk($ids, 1000) as $batch) {
        \Yii::$app->db->createCommand()
            ->delete('order', ['id' => $batch])
            ->execute();
        usleep(10000); // 小休眠,减轻 DB 压力
    }

    $this->stdout("Deleted " . count($ids) . " orders.\n", Console::FG_YELLOW);
}
} 用
$days
参数控制保留窗口,方便测试和灰度 不直接
DELETE ... WHERE
大范围扫描,先
SELECT id
拿主键,再分批删,降低锁粒度和事务体积 加
usleep()
防止瞬间高负载冲击数据库 输出带颜色提示,便于日志识别状态 crontab 怎么配才不出错 运行
crontab -e
,添加这一行(路径必须绝对): WOC-YII开源站群管理系统1.3 WOC-YII是rschome.com基于yii framework 1.1.8框架所开发的一款开源简易站群管理系统。它的功能与WOC完全一样。目前版本为V1.3,新版本正在开发中,同时欢迎大家参与到开发中来! WOC-YII 1.3在1.2的基础上优化了登录系统(密码加密),优化了权限控制系统,新增seo管理功能,新增自动安装向导! 程序框架:yiiframework1.1.8 配置文件:p 下载
0 2 * * * /usr/bin/php /var/www/myapp/yii cleanup/orders --days=180 >> /var/log/yii-cleanup.log 2>&1
/usr/bin/php
必须写全路径,避免 cron 环境找不到 PHP
/var/www/myapp/yii
是项目根目录下的
yii
文件,不是
console.php
或其他入口
--days=180
是传递给命令的参数,等价于
$days = 180
>> /var/log/yii-cleanup.log 2>&1
把 stdout 和 stderr 合并追加到日志,方便排查失败原因(比如 DB 连接失败、权限不足) 别用
@daily
—— 它等价于
0 0 * * *
,但某些旧版 cron 解析不稳定,显式写
0 2 * * *
更可靠 磁盘空间没释放?先看是不是文件句柄还挂着 如果清理脚本本身也操作日志(比如用了
FileTarget
),删完后
df -h
发现空间没回来,跑这句检查:
lsof +L1 | grep 'runtime/logs'
若输出类似
php 12345 user 10w REG 8,1 1073741824 123456 /path/to/runtime/logs/app.error.log (deleted)
,说明某个长进程(如 queue worker、debug watch)还在往已删文件写。此时: 重启对应进程(如
supervisorctl restart my-queue
) 或改用
logrotate
+
copytruncate
,避免删文件,只清空内容 不要依赖“删了就立刻释放”,这是 Linux 文件系统行为,不是 Yii 的问题 真正容易被忽略的点是:清理命令的事务隔离级别和数据库连接池配置。如果用的是 MySQL,默认
REPEATABLE READ
可能导致大查询期间 MVCC 版本堆积;建议在命令开头加
\Yii::$app->db->beginTransaction();
并手动控制提交节奏,而不是靠框架自动 commit。

相关文章