Repository navigation
Retry transaction errors on the MYSQLI adapter - #360
Merged
Merged
Conversation
sgiehl
force-pushed
the
fix-mysqli-transaction-error-tests
branch
from
October 26, 2026 16:39
7c50e53 to
d77264d
Compare
sgiehl
force-pushed
the
fix-mysqli-transaction-error-tests
branch
2 times, most recently
from
October 27, 2026 07:38
4672925 to
0318311
Compare
The mysqli adapter's isErrNo() reads the error number from the connection, which no longer has it once the failed statement was freed, so deadlocks, lock wait timeouts and snapshot isolation conflicts were never retried. Also accept the tracker DbException's code, which carries the number. The tests now fake these errors with a coded DbException, so the production check runs on both adapters, and one test raises a real lock wait timeout.
sgiehl
force-pushed
the
fix-mysqli-transaction-error-tests
branch
from
October 27, 2026 07:39
0318311 to
c6aa9f9
Compare
sgiehl
marked this pull request as ready for review
October 27, 2026 07:43
AltamashShaikh
approved these changes
Oct 27, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Follow-up to #348 and #349. On the MYSQLI database adapter, deadlocks, lock wait timeouts and snapshot isolation conflicts were never recognised as retryable, so the transaction was not restarted and the failed request set was cut short instead of retried. This predates #348: the earlier deadlock and lock wait retry used the same check, so it never worked on MYSQLI either. The handling from #348 and #349 therefore only ever applied on PDO.
The cause: the mysqli adapter's
isErrNo()reads the error number from the connection, not the exception. By the timeHandler::onException()runs, the failed statement has been freed, which clears the connection's error number, and the mysqli error message doesn't include it. The tracker'sDbExceptiondoes carry the number as its code, so the handler now accepts that too. On PDO the code is the integer value of the SQLSTATE, so it never matches these numbers, and detection there still comes from the message.This also explains why core's MYSQLI CI jobs fail on the #348/#349 tests (e.g. in matomo-org/matomo#25585) while this plugin's CI passed: it only ran on PDO.
Handleralso checks the code of the trackerDbException.DbExceptioncarrying the number, so the production check runs on both adapters. A new test raises a real lock wait timeout through a second connection. Without the fix it fails on MYSQLI. A unit test also covers an error whose number is only in the code, so every CI job checks the new branch, not just the MYSQLI one.Known limitation: on MYSQLI, two kinds of error still lose the number and are not recognised. Errors raised by the
fetch*methods of core's tracker mysqli adapter are rewrapped without the code, and prepare failures throw without the number. Tracking runs its writes and its one locking read throughquery(), which keeps the code, so this only matters for locking reads throughfetch*(e.g. under SERIALIZABLE isolation) or prepare-time errors (e.g. on Galera). The fix belongs in core.Follow-up: 5.x has the same bug (#350 in 5.2.1 also uses
isErrNo()only), so this needs a backport to 5.x-dev.Issue No
Related to #331
Steps to Replicate the Issue
adapter = "MYSQLI"in[database_tests]and runHandlerTest.Checklist