Skip to content

fix: clear transaction state when reconnect() replaces the socket - #10650

Open
KevinBlakeLopez wants to merge 3 commits into
codeigniter4:developfrom
KevinBlakeLopez:fix/10648-reconnect-clears-transaction
Open

KevinBlakeLopez wants to merge 3 commits into
codeigniter4:developfrom
KevinBlakeLopez:fix/10648-reconnect-clears-transaction

Conversation

@KevinBlakeLopez

@KevinBlakeLopez KevinBlakeLopez commented Oct 22, 2026 •

Copy link
Copy Markdown

Description

Fixes #10648.

reconnect() closes a dead socket and opens a new one. The server has already rolled back the transaction that was open on the old socket. transDepth and transStatus were left as they were, and ping() goes through simpleQuery(), which does not call handleTransStatus(). transComplete() then returned true while the pre-timeout insert was gone.

When the socket is replaced during a transaction, reconnect() now clears transDepth and marks the transaction failed. A later reconnect() while ping() is still true leaves the open transaction alone.

On develop (df8b96bee) the new live test failed before this change:

-    'depth' => 0,
-    'status' => false,
-    'completed' => false,
+    'depth' => 1,
+    'status' => true,
+    'completed' => true,
     'rows' => 0,

After the change, ReconnectDuringTransactionTest and PingTest pass (local MySQL 8.0.45, PHP 8.5.12, MySQLi).

Checklist:

  • Securely signed commits
  • Component(s) with PHPDoc blocks, only if necessary or adds value (without duplication)
  • Unit testing, with >80% coverage
  • User guide updated
  • Conforms to style guide

Made with Cursor

@carson-codeigniter4 carson-codeigniter4 Bot added the bug Verified issues on the current code behavior or pull requests that will fix them label Oct 22, 2026
@carson-codeigniter4

Copy link
Copy Markdown

Hi there, @KevinBlakeLopez! 👋

Thank you for sending this PR!

We expect the following in all Pull Requests (PRs).

Important

We expect all code changes or bug-fixes to be accompanied by one or more tests added to our test suite to prove the code works.

If pull requests do not comply with the above, they will likely be closed. Since we are a team of volunteers, we don't have any more time to work
on the framework than you do. Please make it as painless for your contributions to be included as possible.

See https://github.com/codeigniter4/CodeIgniter4/blob/develop/contributing/pull_request.md

@KevinBlakeLopez
KevinBlakeLopez force-pushed the fix/10648-reconnect-clears-transaction branch from 2dc7af6 to 6369d6b Compare October 22, 2026 23:37
@paulbalandan
paulbalandan requested a balanced review from Copilot October 23, 2026 05:41

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Failed reconnection attempts bypass transaction invalidation, and OCI8 recovery leaves autocommit disabled.

2 open issues
What changed in this PR

Addresses #10648 by invalidating transaction state when reconnect() replaces a lost database connection. Reviewed under the assumed develop patch-release policy.

Changes:

  • Clears transaction depth and marks interrupted transactions as failed.
  • Adds MySQLi live tests for lost and healthy connections during transactions.
  • Documents the behavior in the connection guide and changelog.

Validation used targeted source inspection; automated tests and the database-driver matrix remain for CI.

File Description
user_guide_src/​source/​database/​connecting.rst Explains transaction invalidation after reconnection.
user_guide_src/​source/​changelogs/​v4.7.6.rst Records the fix for #10648.
tests/​system/​Database/​Live/​ReconnectDuringTransactionTest.php Tests interrupted and preserved MySQLi transactions.
system/​Database/​BaseConnection.php Resets transaction state after replacing a connection.

Review effort: Balanced

Comment thread system/Database/BaseConnection.php Outdated
Comment thread system/Database/BaseConnection.php
KevinBlakeLopez and others added 2 commits October 25, 2026 15:09
The server rolls the open transaction back with the dead connection.
Keeping transDepth and transStatus made transComplete() return true.

Fixes codeigniter4#10648

Co-authored-by: Cursor <cursoragent@cursor.com>
reconnect() cleared transDepth and transStatus only after initialize()
returned. When initialize() threw, the old transaction state survived, and
a later query() that reconnected on its own let transComplete() report
success. The state is now cleared before initialize() runs.

OCI8 keeps its commit mode in PHP. Clearing the depth skipped
_transRollback(), so commitMode stayed OCI_NO_AUTO_COMMIT and later writes
were never committed. OCI8 now restores OCI_COMMIT_ON_SUCCESS when the
transaction is abandoned.

The guide and changelog now say this applies only when ping() reports the
connection lost. On PostgreSQL, pg_ping() re-establishes a broken connection
itself and returns true, so reconnect() does not clear the state there.

Refs codeigniter4#10648

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@KevinBlakeLopez
KevinBlakeLopez force-pushed the fix/10648-reconnect-clears-transaction branch from 1a7668c to 4a25d53 Compare October 25, 2026 22:32

@michalsn michalsn left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good overall. Please clarify that reconnect() does not resume the lost transaction and that failure handling must cover the entire operation, including nested transaction groups.

Comment thread user_guide_src/source/database/connecting.rst Outdated
Apply the review suggestion. The transaction-state reset only happens
when ping() returns false, and PostgreSQL's pg_ping() can re-establish a
broken connection and return true. The lost transaction is not resumed,
later writes may autocommit, and the code that owns the whole transaction
has to handle the failure before retrying.

Drop the issue link from the changelog entry to match the changelog style.

Co-authored-by: Michal Sniatala <459185+michalsn@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@michalsn michalsn left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Verified issues on the current code behavior or pull requests that will fix them

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: reconnect() keeps the old transaction on a replaced MySQLi socket

3 participants