perf: delete purged connections in batches of 5000
The purge ran one DELETE over the whole retention cutoff in a single transaction, spiking undo/binlog and holding row locks on a table the fetch cron writes to. Now it loops in batches of 5000 rows with a short pause between batches, keeping each commit small.
This commit is contained in:
1 parent
4ce1502831
commit
b479f92a63
1 file changed
+22
-3
+22
-3
@@ -258,15 +258,34 @@ function frequent_ips(int $min_connections, ?string $since = null): array {
|
||||
|
||||
/**
|
||||
* Delete connections older than retention_days setting.
|
||||
* Rows are removed in batches so each transaction stays small — a single
|
||||
* giant DELETE would lock a large part of the table while the fetch cron
|
||||
* keeps inserting rows.
|
||||
*
|
||||
* Returns the number of rows deleted.
|
||||
*/
|
||||
function purge_old_connections(): int {
|
||||
$days = max(1, (int)get_setting('retention_days', '7'));
|
||||
$cutoff = date('Y-m-d H:i:s', time() - $days * 86400);
|
||||
|
||||
$s = db()->prepare(
|
||||
'DELETE FROM connections WHERE occurred_at < NOW() - INTERVAL ? DAY'
|
||||
'DELETE FROM connections
|
||||
WHERE occurred_at < ?
|
||||
ORDER BY id
|
||||
LIMIT 5000'
|
||||
);
|
||||
$s->execute([$days]);
|
||||
return $s->rowCount();
|
||||
|
||||
$total = 0;
|
||||
do {
|
||||
$s->execute([$cutoff]);
|
||||
$deleted = $s->rowCount();
|
||||
$total += $deleted;
|
||||
if ($deleted > 0) {
|
||||
usleep(100_000); // 100 ms between batches to ease lock pressure
|
||||
}
|
||||
} while ($deleted >= 5000);
|
||||
|
||||
return $total;
|
||||
}
|
||||
|
||||
// ── Upstream version check ────────────────────────────────────────────────────
|
||||
|
||||
Reference in new issue
Block a user