[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) <odo@openerp.com>
This commit is contained in:
Olivier Dony
2019-12-12 18:44:32 +00:00
parent d807e07949
commit e63fd04b51
+4 -1
View File
@@ -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