Problem/Motivation
Truncate::__toString() in core/lib/Drupal/Core/Database/Query/Truncate.php emits DELETE FROM instead of TRUNCATE when a transaction is active. On MySQL, TRUNCATE is a DDL statement and causes an implicit commit, so the fallback is needed there. On PostgreSQL, TRUNCATE is fully transactional and can be rolled back. The pgsql driver inherits the fallback anyway.
DELETE FROM is slow on large tables. Each deleted row also becomes a dead tuple that autovacuum must clean up. Frequent cache table clears create this vacuum load on PostgreSQL sites.
Proposed resolution
Override __toString() in the pgsql driver's Truncate class to always emit TRUNCATE, also inside transactions.
Caveats: TRUNCATE takes an ACCESS EXCLUSIVE lock on the table, held until the transaction ends. It is not MVCC-safe for concurrent transactions using a snapshot taken before the truncation. The core docblock already describes the lock.
Steps to reproduce
On PostgreSQL, run a truncate query inside a transaction and log the queries. A DELETE FROM statement runs.
Remaining tasks
Review.
API changes
None.
Data model changes
None.
For the committer
The changes to the .gitlab-ci.yml file need to be removed before merging!
Issue fork drupal-3615225
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
- 3615225-truncate-queries-on
changes, plain diff MR !16585
Comments
Comment #3
daffie commentedUpdated the IS.
Comment #4
daffie commentedReady for a review.
Comment #5
daffie commentedDisclosure: I have used AI for the PR, the IS and the CR.
Comment #6
smustgrave commentedNote: Gitlab file should not be converted.
Reviewing the changes I actually have no feedback. Lets give it a shot.
Comment #9
catchI didn't know this about PostgreSQL, but the logic looks sound and the code comments explain it well. Committed/pushed to main and 11.x, thanks!