Affects Version/s: 3.8.7, 4.0.7, 4.1.4, 4.2.0
Operating System: Linux 22.214.171.124-grsec
PHP Version: 4.4.6-0.dotdeb.2
Database and version: MySQL 5.0.32-Dotdeb_1.dotdeb.1-log
Browser (and version): ALL
When facing a huge number of objects in the trash ( > 10 k), it might not be possible to delete anything at all from the trash when using MySQL InnoDB or any other transactionnal database.
Cause of the problem : the $db->begin() and $db->commit() surround the whole loop on the total objects to purge.
Either the script will hit the PHP_TIME_LIMIT ( on a 10k+ objects purge and a 20k+ records in a content object tree ) without $db->commit() being issued : the whole first part of the purge is rollbacked internally in MySQL
Or the script will be the chosen victim of a InnoDB deadlock situation (hence an eZ Fatal Error without the commit being issued to the database)
Proposed enhancement : as the "empty trash" is a definitive destructive operation chosen by the user, one can reduce the atomicity of the operation by "batching" the content objects purge :
kernel/content/trash.php around line 92
( Not proposed as file attachement because it is a "rough" patch : one could wish to change the object count threshold - here 25 - according to its web server/database server architecture )
This enhancement also diminish the period of time during which InnoDB will maintain the locks on the impacted rows/tables (hence, limiting the number of deadlocks related eZ Fatal Errors on other pages calls).
If the script dies anyway, at least some of the trash has been emptied ( I was able to empty a 15k+ objects trash in four steps ).