orm: Syntax error or access violation: 1305 SAVEPOINT DOCTRINE_x does not exist
Feature Request
Q | A |
---|---|
New Feature | yes |
RFC | yes |
BC Break | no? |
Summary
Hi,
We see exception Syntax error or access violation: 1305 SAVEPOINT DOCTRINE_205 does not exist
every now&then.
It comes from https://github.com/doctrine/orm/blob/ccfc97c32f63aaa0988ac6aa42e71c5590bb794d/lib/Doctrine/ORM/UnitOfWork.php#L485
Im looking for ways to debug it, but i’m worried the original exception is hidden.
Im wondering if we could try/catch it and let the original exception bubble up.
About this issue
- Original URL
- State: closed
- Created 5 months ago
- Comments: 19 (6 by maintainers)
Because without savepoints, the transaction level is pretty much a boolean?
Just read the full thread while trying to find out what @ro0NL meant by “eg. due
SAVEPOINT DOCTRINE_2 does not exist
” in #11423 … wouldn’t the next logical step be to file a DBAL bug report?So, if I understand the issue correctly, the DBAL does not detect a deadlock correctly and thus assumes a wrong transaction nesting level? This needs to be fixed in the DBAL then.
both errors are real to me 😅 i mean, in both cases “concurrent mysql” is the issue
im not sure how to deal with it on DBAL/ORM side either. That’s future work for maintainers 😃
for now im going to opt-out our command from running transactional (it’s not a real requirement for this specific case), that solves the issue as well. Im not really happy with try/catching the commit/rollback flow really, even though the “return bool” API allows for it.
eventually maybe just take some error percentage for granted as well, but time will tell.
but we cant in case of concurrency, because “mysql”. Note im not an infrastructural expert 😉
also IIUC doctrine/orm:^3 will enforce savepoints either way
i just thought it was nice to have command execution wrapped in a transaction by default
i think i’ll rewrite our transaction middleware so that it only creates an outer transaction, and thus avoid nested savepoints in this case.
I can reproduce it locally 😃
Test without savepoint
START TRANSACTION;
UPDATE tbl1 SET b = 1 WHERE id = 1;
START TRANSACTION;
UPDATE tbl2 SET b = 1 WHERE id = 1;
UPDATE tbl2 SET b = 1 WHERE id = 1;
UPDATE tbl1 SET b = 1 WHERE id = 1;
COMMIT;
ROLLBACK;
rollback
Test with savepoints
START TRANSACTION;
UPDATE tbl1 SET b = 1 WHERE id = 1;
START TRANSACTION;
SAVEPOINT savepoint_1;
UPDATE tbl2 SET b = 1 WHERE id = 1;
UPDATE tbl2 SET b = 1 WHERE id = 1;
UPDATE tbl1 SET b = 1 WHERE id = 1;
COMMIT;
ROLLBACK TO savepoint_1;
rollback
(ERROR)Sorry for more SQL.
By documentation from MySQL https://dev.mysql.com/doc/refman/8.0/en/innodb-error-handling.html DEADLOCK will lead rollback the entire transaction. As result, in session #2 after deadlock error we CANNOT execute
rollback to savepoint
, because MySQL roll back ENTIRE transaction, but by default logic inEntityManager::flush (UnitOfWork::commit)
- after catched error system try to executerollback
.P.S. This is only possible if save points are enabled. If savepoints are disabled (by default in
Dbal 3.*
) - developers not see this error, because system not open savepoints.Correct, and not that i’m aware of 😅
Since we already had a custom connection middleware, i’ve added this gem to
exec()
for now:Will monitor prod today to see if it reveals our issue 👍