Since Mysql releases all table locks anytime we query LOCK/UNLOCK TABLES, any subsequent call of JTable::_lock() or JTable::_unlock() during complex operations causes unlocking all tables so this breaks condition of atomicity.
Examples of such calls are calling to _lock() and _unlock() on assets table in JTableNested::delete() or calling JTableNested::moveByReference() inside JTableNested::store().
So I suggest my solution:
Create new static property JTable::$_locks_counter that is something like locks stack.
Create new method JTable::_getTablesForLocking() which returns array of tables that must be locked for the following procedure. It can be overriden by child classes and return array of all tables that they need to be locked. It can be soms kind of relations table for example. By default it returns current table and #__assets table if _trackAssets is set to true
Modify JTable::_lock() method so it really locks tables only when it is called first time. So that way any subsequent calls wouldn't release tables.
Modify JTable::_unlock() method to query UNLOCK TABLES only when number of calls to _unlock() equals to number of previous _lock() calls.
Since LOCK TABLES query locks tables for session, I think that it should be handled by JDatabaseDriver in future and since we want atomicity, the good way would be to get all tables that need to be locked in controller so we can store data in multiple tables without race condition.
It has been a very long time since this PR was submitted and as there has been no response to the comments and no tests I am closing this as an abandoned PR. It can always be reopened if updated
Can you look at resolving the conflicts so that this can be tested please.