From e63fd04b512b6a2358b3374cea081bdbd327fcd4 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Thu, 12 Dec 2019 18:44:04 +0000 Subject: [PATCH] [FIX] ir.attachment: make filestore GC yield to other transactions If a long-running transaction holds a write-lock on any row in ir.attachment, the GC job can wait an indefinite amount of time to acquire its table-wise SHARE LOCK. While sitting in the queue for this lock, it will conflict with any future transaction that tries to acquire a write-lock on any row [1]. So the GC transaction, which would normally execute very fast and immediately release its lock, will start to block other transactions and cause severe delays in response time. It basically depends on how long the tx holding the lock takes to complete... which is unknown. As a workaround, we force an arbitrary (but short) lock_timeout in the GC tx before attempting the lock. If it fails to acquire it, it will fail and raise, causing the whole operation to abort. The cron job will be rescheduled quickly because it failed to complete, giving the GC another chance to complete. 10 seconds seems a reasonable compromise, as it gives the blocking transaction(s) some time to complete before bailing out, yet should not be long enough to bring the system to a halt due to other transactions blocked by the GC one. I have no hard data to back this claim, though. [1] See the LOCK conflict table in the documentation: https://www.postgresql.org/docs/10/explicit-locking.html closes odoo/odoo#42128 X-original-commit: 8a093c74c209d492f066c927cc4ac61325aee3ae Signed-off-by: Olivier Dony (odo) --- odoo/addons/base/models/ir_attachment.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/odoo/addons/base/models/ir_attachment.py b/odoo/addons/base/models/ir_attachment.py index 51a386fce34..e15a685c794 100644 --- a/odoo/addons/base/models/ir_attachment.py +++ b/odoo/addons/base/models/ir_attachment.py @@ -156,7 +156,10 @@ class IrAttachment(models.Model): cr = self._cr cr.commit() - # prevent all concurrent updates on ir_attachment while collecting! + # prevent all concurrent updates on ir_attachment while collecting, + # but only attempt to grab the lock for a little bit, otherwise it'd + # start blocking other transactions. (will be retried later anyway) + cr.execute("SET LOCAL lock_timeout TO '10s'") cr.execute("LOCK ir_attachment IN SHARE MODE") # retrieve the file names from the checklist