spatie / laravel-queued-db-cleanup
安全删除大量记录
Requires
- php: ^8.2
- doctrine/dbal: ^3.0
- illuminate/contracts: ^10.0|^11.0
- laravel/serializable-closure: ^1.0
Requires (Dev)
- orchestra/testbench: ^8.0|^9.0
- phpunit/phpunit: ^10.5
README
使用 Laravel 一次性删除大量数据库记录存在一些需要注意的陷阱
- 删除记录可能是一个耗时的操作,可能需要很长时间
- 删除查询将获取许多行锁,并可能锁定整个表,其他查询将需要等待
- 即使在管理查询执行和清理时,在无服务器环境中也存在一个固定的最大执行时间
这些陷阱在 这篇博客文章 中有更详细的描述,该文章发布在 Flare 博客 上。
此包提供了一种安全删除大量记录的解决方案。以下是一个示例
Spatie\LaravelQueuedDbCleanup\CleanDatabaseJobFactory::new() ->query(YourModel::query()->where('created_at', '<', now()->subMonth())) ->deleteChunkSize(1000) ->dispatch();
上面的代码将调度一个清理作业,该作业将删除由查询选择的第一个1000条记录。当它检测到已删除1000条记录时,它将得出结论,可能并非所有记录都已删除,然后重新调度自身。
我们还将确保此清理作业从不重叠。这样就可以保持数据库连接数低。这也允许您通过 CRON 重复安排此清理作业,而无需检查是否存在现有的清理进程。
通过保持块大小小,查询执行得更快,潜在的表锁定时间不会很长。清理作业也会很快完成,因此您不会遇到执行时间限制。
支持我们
我们投入了大量资源来创建 一流的开放源代码包。您可以通过 购买我们的付费产品之一 来支持我们。
我们非常感谢您从家乡寄给我们明信片,说明您正在使用我们的哪个包。您可以在 我们的联系页面 上找到我们的地址。我们将在 我们的虚拟明信片墙上 发布所有收到的明信片。
安装
您可以通过 composer 安装此包
composer require spatie/laravel-queued-db-cleanup
此包使用锁来防止同一查询的多次删除同时执行。我们建议使用 Redis 存储锁。
在幕后,此包利用了 作业批处理。请确保您已创建了 Laravel 文档中提到的批次表。
可选地,您可以使用以下命令发布配置文件
php artisan vendor:publish --provider="Spatie\LaravelQueuedDbCleanup\LaravelQueuedDbCleanupServiceProvider" --tag="config"
这是发布配置文件的内容
return [ /* * To make sure there's only one job of a particular cleanup running, * this package uses a lock. Here, you can configure the default * store to be used by the lock and the release time. */ 'lock' => [ 'cache_store' => 'redis', 'release_lock_after_seconds' => 60 * 20 ], /* * The class name of the job that will clean that database. * * This should be `Spatie\LaravelQueuedDbCleanup\Jobs\CleanDatabaseJob` * or a class that extends it. */ 'clean_database_job_class' => Spatie\LaravelQueuedDbCleanup\Jobs\CleanDatabaseJob::class, /* * In order to handle deadlocks on a high traffic table, the package can * automatically retry the transaction that performs the delete query * a specified number of times */ 'delete_query_attempts' => 3, ];
用法
此代码将调度一个清理作业,该作业将删除由查询选择的第一个1000条记录。当它检测到已删除1000条记录时,它将得出结论,可能并非所有记录都已删除,然后重新调度自身。
Spatie\LaravelQueuedDbCleanup\CleanDatabaseJobFactory::new() ->query(YourModel::query()->where('created_at', '<', now()->subMonth())) ->deleteChunkSize(1000) ->dispatch();
当删除的记录数少于 deleteChunkSize
给定的数量时,作业不会重新调度自身。
在计划任务中启动清理
可以在计划任务中安全地启动清理过程。内部,该包将使用锁来确保同时没有两个使用相同查询的清理过程在运行。
如果在另一个清理过程仍在运行时计划任务启动清理过程,则新的清理过程将被取消。
自定义队列和连接名称
内部,该包使用作业批次。使用 getBatch
可以获取批次并在其上调用如 onConnection
和 onQueue
的方法。别忘了在最后通过调用 dispatch()
来分发批次。
Spatie\LaravelQueuedDbCleanup\CleanDatabaseJobFactory::new() ->query(YourModel::query()->where('created_at', '<', now()->subMonth())) ->deleteChunkSize(1000) ->getBatch() ->onConnection('redis') ->onQueue('cleanups') ->dispatch();
自定义数据库连接
使用 onDatabaseConnection
允许您在另一个连接上删除记录。
Spatie\LaravelQueuedDbCleanup\CleanDatabaseJobFactory::new() ->query(YourModel::query()) ->onDatabaseConnection('other_connection') ->deleteChunkSize(1000) ->dispatch();
手动停止清理过程
默认情况下,当检测到已删除的记录数少于块大小时,清理作业将不会再次重新调度自己。您可以通过调用 stopWhen
来自定义此行为。它应接收一个闭包。如果闭包返回 true
,则清理将停止。
CleanDatabaseJobFactory::forQuery(YourModel::query()) ->deleteChunkSize(10) ->stopWhen(function (Spatie\LaravelQueuedDbCleanup\CleanConfig $config) { return $config->pass === 3; }) ->dispatch();
stopWhen
接收一个 Spatie\LaravelQueuedDbCleanup\CleanConfig
实例。它包含这些属性以确定是否停止清理
pass
:包含清理作业为此特定清理启动的次数。rowsDeletedInThisPass
:本次遍历中删除的行数totalRowsDeleted
:所有遍历中删除的总行数。
使用批次停止清理过程
您可以使用批次 ID 来停止清理过程。
$batch = CleanDatabaseJobFactory::forQuery(YourModel::query()) ->deleteChunkSize(10) ->getBatch(); // you could store this batch id somewhere $batchId = $batch->id; $batch->dispatch();
在代码库的另一个地方,您可以检索存储的批次 ID 并使用它来取消批次,从而停止清理过程。
\Illuminate\Support\Facades\Bus::findBatch($batchId)->cancel();
事件
您可以监听这些事件。它们都有一个公共属性 cleanConfig
,它是 Spatie\LaravelQueuedDbCleanup\CleanConfig
的一个实例。
Spatie\LaravelQueuedDbCleanup\Events\CleanDatabasePassStarting
在清理过程中启动新遍历时触发。
Spatie\LaravelQueuedDbCleanup\Events\CleanDatabasePassCompleted
在清理过程中完成遍历时触发。
Spatie\LaravelQueuedDbCleanup\Events\CleanDatabaseCompleted
在完成整个清理过程时触发。
测试
composer test
变更日志
请参阅 CHANGELOG 了解最近更改的更多信息。
贡献
请参阅 CONTRIBUTING 了解详细信息。
安全漏洞
请参阅我们如何报告安全漏洞的 安全策略。
鸣谢
许可
MIT 许可证 (MIT)。请参阅 许可文件 了解更多信息。