This issue has been created
There are 4 updates.
 
 
XWiki Platform / cid:jira-generated-image-avatar-f0b5edd0-5eaa-426c-b3fa-c96b1b66430d XWIKI-25019 Open

Acquiring a document lock can fail with a deadlock on MySQL

 
View issue   ·   Add comment
 

Issue created

 
cid:jira-generated-image-avatar-ed6a45ee-25fb-4e36-8c92-1e6c2c1447dc Marius Dumitru Florea created this issue on 17/Sep/26 19:39
 
Summary: Acquiring a document lock can fail with a deadlock on MySQL
Issue Type: cid:jira-generated-image-avatar-f0b5edd0-5eaa-426c-b3fa-c96b1b66430d Bug
Affects Versions: 18.8.0-rc-1
Assignee: Unassigned
Components: Old Core
Created: 17/Sep/26 19:39
Priority: cid:jira-generated-image-static-major-810ccec5-28fc-4a86-a83e-85950de22869 Major
Reporter: Marius Dumitru Florea
Description:

Symptom

Opening an administration section contributed through XWiki.ConfigurableClass is supposed to lock the configurable page (and unlock the one of the previously visited section). On MySQL this lock is sometimes silently not taken: the page stays unlocked, so another user can start editing it concurrently without being warned, and nothing is reported to the user who opened the administration section.

Navigating from one administration section to another is what triggers it, because that is the moment where several lock requests overlap. Leaving an administration page sends an unlock (cancel) request for both the configurable page and XWiki.XWikiPreferences, while the page being loaded sends a lock request for its own configurable page and for XWiki.XWikiPreferences — four concurrent writes on the xwikilock table.

Cause

Two of those concurrent transactions deadlock in InnoDB, and the loser is rolled back, so the lock is never inserted:

lock/.../TestConfigurable2?ajax=1&action=admin
  WARN  SqlExceptionHelper - SQL Error: 1213, SQLState: 40001
  ERROR SqlExceptionHelper - Deadlock found when trying to get lock; try restarting transaction
  ERROR XWikiHibernateBaseStore - Exception while closing the transaction
  javax.persistence.OptimisticLockException: LockAcquisitionException: could not execute statement
      at HibernateStore.endTransaction(HibernateStore.java:843)
      at XWikiHibernateBaseStore.execute(XWikiHibernateBaseStore.java:838)
      at XWikiHibernateStore.saveLock(XWikiHibernateStore.java:2049)
      at XWikiDocument.setLock
      at LockAction.action(LockAction.java:61)

Since XWIKI-22421, XWikiHibernateStore#saveLock is a DELETE ... WHERE docId = ? followed by an INSERT. Under REPEATABLE READ — the InnoDB default, hence MySQL and MariaDB — a DELETE that matches no row still takes a gap lock on the gap where the row would go, and a concurrent INSERT into that gap has to wait for an insert-intention lock. Two such transactions deadlock each other. PostgreSQL, Oracle and HSQLDB take no gap locks, which is why only the MySQL environment is affected.

The failure is invisible to everyone involved:

  • XWikiHibernateBaseStore#execute catches the exception thrown by the commit and only logs it, so saveLock returns normally and reports success on a rolled-back transaction.
  • On the browser side, XWiki.DocumentLock#lock fires the request with new Ajax.Request(...) and no failure handler, and it has already marked the document as locked before sending it — so the client also believes it holds a lock it does not have.

Evidence

The functional test ConfigurableClassIT#testLockingAndUnlocking catches this. On ci.xwiki.org it fails only in the MySQL environment (MySQL latest, Tomcat 11-jdk25, Filesystem, Chrome) and always on the same assertion — the one checking that the second configurable page got locked — while the PostgreSQL environment, which uses the same Chrome and Tomcat, always passes. It started failing on that assertion on 2026-08-29, right after XWIKI-22421 was merged.

Example: https://ci.xwiki.org/job/XWiki%20Environment%20Tests/job/xwiki-platform/job/master/1363/

Note

XWIKI-24997 has since made the store default hibernate.connection.isolation to READ COMMITTED when the Hibernate configuration does not set one. Under READ COMMITTED InnoDB disables gap locking for searches and index scans, which should remove the trigger described above for a default installation. That change landed after every CI build analysed here, so it has not been exercised yet, and it does not help an installation whose hibernate.cfg.xml pins REPEATABLE READ.

 
 

4 updates

 
cid:jira-generated-image-avatar-ed6a45ee-25fb-4e36-8c92-1e6c2c1447dc Changes by Marius Dumitru Florea on 17/Sep/26 19:39
 
Fix Version: 18.8.0
Assignee: Marius Dumitru Florea
Priority: Major Blocker
Labels: regression