Skip to content
Snippets Groups Projects
Commit c5c955db authored by Xavier Morel's avatar Xavier Morel
Browse files

[FIX] core: work around ir_logging deadlock


DROP CONSTRAINT (even with IF EXISTS is specified) acquires an ACCESS
EXCLUSIVE lock on the table, preventing e.g. inserts in an other
transaction, so ir_logging would systematically deadlock if configured
to the same database and a warning would be triggered during install
or update (if that ran ir.logging's init).

1. hand-roll the "IF EXISTS" bit, to avoid taking an ACCESS EXCLUSIVE
lock on the table if the problematic constraint does not exist and
thus doesn't need to be dropped (which by now should be the vast
majority of cases).

Replacing DROP CONSTRAINT with DISABLE TRIGGER does not fix the
issue as *that* acquires SHARE ROW EXCLUSIVE. While that's less
constraitning than ACCESS EXCLUSIVE, it still conflicts with an
insert's ROW_EXCLUSIVE.

2. add a timeout to the logging INSERT anyway, the deadlock is still
an issue if we're updating a database which does have the
problematic constraint, and we want to preclude the possible
eventual introduction of new deadlocks in the future.

closes odoo/odoo#34243

Signed-off-by: default avatarXavier Morel (xmo) <xmo@odoo.com>
parent 455714c7
No related branches found
No related tags found
No related merge requests found
......@@ -34,4 +34,10 @@ class IrLogging(models.Model):
@api.model_cr
def init(self):
super(IrLogging, self).init()
self._cr.execute("ALTER TABLE ir_logging DROP CONSTRAINT IF EXISTS ir_logging_write_uid_fkey")
self._cr.execute("select 1 from information_schema.constraint_column_usage where table_name = 'ir_logging' and constraint_name = 'ir_logging_write_uid_fkey'")
if self._cr.rowcount:
# DROP CONSTRAINT unconditionally takes an ACCESS EXCLUSIVE lock
# on the table, even "IF EXISTS" is set and not matching; disabling
# the relevant trigger instead acquires SHARE ROW EXCLUSIVE, which
# still conflicts with the ROW EXCLUSIVE needed for an insert
self._cr.execute("ALTER TABLE ir_logging DROP CONSTRAINT ir_logging_write_uid_fkey")
......@@ -54,7 +54,7 @@ def LocalService(name):
path_prefix = os.path.realpath(os.path.dirname(os.path.dirname(__file__)))
class PostgreSQLHandler(logging.Handler):
""" PostgreSQL Loggin Handler will store logs in the database, by default
""" PostgreSQL Logging Handler will store logs in the database, by default
the current database, can be set using --log-db=DBNAME
"""
def emit(self, record):
......@@ -64,7 +64,8 @@ class PostgreSQLHandler(logging.Handler):
if not dbname:
return
with tools.ignore(Exception), tools.mute_logger('odoo.sql_db'), sql_db.db_connect(dbname, allow_uri=True).cursor() as cr:
cr.autocommit(True)
# preclude risks of deadlocks
cr.execute("SET LOCAL statement_timeout = 1000")
msg = tools.ustr(record.msg)
if record.args:
msg = msg % record.args
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment