-
Notifications
You must be signed in to change notification settings - Fork 10.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
PHP 8.0 PDO::rollback() now throws PDOException after implicit commit #35380
Comments
I'm investigating this. |
So, I've investigated this with the team and want to reply to some of your proposals:
We'd need to list every possible implicit commit trigger for MySQL/MariaDB. This is unfeasible and a lot of work. It's probably also quirky since we'd not be relying on the behavior of the engine directly.
Your code was already broken on PHP <8.0. It's just more explicit right now. I think the exception being exposed right now is a good thing.
The effect of the exception is correct. It throws a fatal error because you're ending a transaction prematurely with an implicit commit. I think atm I'm more leaning towards doing nothing since it's good that PHP 8 is finally exposing this explicitly. We can't catch the exception and modify it because we don't know what caused the transaction to be closed. It could be the If we'd really want to solve this codewise then listing implicit statements and checking those when a transaction is active and then throw an exception is the best way to go but that would be a lot of work and get cumbrsome. The best course of action here, I believe, would be to just document the use of I'll let @taylorotwell decide on this. |
Thanks for looking into this @driesvints, I completely agree, it is actually good it is throwing an explicit exception since the code was already broken.
I used Personally, I am fine with your proposal, I agree this should be properly documented on all transaction-related documentation, for example:
Yes, it will be almost impossible to do this, as you will never be able to 100% cover all cases(ie stored procedures) Note |
It shouldn't affect |
Oops, you are correct. It only affects the |
Yes, this only affects the DatabaseTransactions trait indeed. Thanks for your help here @stemis. I'll try to send in a PR to the docs shortly. |
Here it is: laravel/docs#6599 |
@driesvints so the only solution to this is to close the transaction before any implicit commit query ? like :
|
Due to an (issue)[laravel/framework#35380], in laravel 9 it fails. This resolves it also make it continue to work on Laravel 6.
PHP 8 is more strict about implicit commits within transactions laravel/framework#35380
PHP 8 is more strict about implicit commits within transactions laravel/framework#35380
Sorry for resurrecting this, but this can not be avoided if users will have a way to run statements on a separate PDO session/connection? DB::isolatedConnection('mysql')->statement('CREATE TABLE ....')
// or
DB::freshConnection('mysql')->statement('CREATE TABLE ...') I am thinking that running the above statement on a separate PDO connection it will not interfere with transactions started on default/resolved connection. Even the migrate command might use this. As in, to run migrations always on a separate connection because it executes statements which trigger implicit commit But i am not sure if this is possible in the framework |
Description:
As this is a difficult subject I will try my best to explain it properly, it is an issue that needs to be addressed properly.
PHP 8.0 changes
In PHP 8.0, the pdo transaction logic was rewritten to some extend.
When issuing a PDO::rollback(), this will now throw a PDOException if the transaction was already closed.
* I was not able to find any official documentation on this yet, but was able to confirm this with the different PHP versions
Background Implicit Commits with Transactions
MySQL has a thing called implicit commits, to demonstrate what this does I have created the following example. I have used MariaDB as this has access to the
in_transaction
session var to demonstrate the working.So imagine a UnitTest executing any Implicit commit commands, then it commits the transaction. So when running Migration command in a test, or stored procedures, or seeders that have implicit commands in them, a rollback is no longer possible as the transaction was already closed.
In php <=7.4.12 no exception was thrown, so most of the times, you would have no idea why you have data leakage in your test
PHP 8.0 now throwns an exception.
Laravel
How does this affect Laravel?
DB::transaction
, a newPDOException
is thrown.Consider the following test file:
This will generate the following error when running the test:
Dump of the exception object:
Laravel code
Laravel calls the PHP's rollback command as follows:
framework/src/Illuminate/Database/Concerns/ManagesTransactions.php
Lines 236 to 240 in 6ecfdb5
framework/src/Illuminate/Database/Concerns/ManagesTransactions.php
Lines 274 to 281 in 6ecfdb5
What has changed?
This exception was not thrown on PHP7.4.12, it is thrown on PHP 8.0RC5
I encountered this issue myself when trying to run my application on
8.0RC5
, I can imagine a lot of others will encounter this exception.Next steps?
Now the question arises what to do with the new Exception that is thrown? As it is currently quite vague as to why it is happening by just looking at the error message, and it cost me a lot of research to find out the cause of it.
I think we need to do at least the following:
DB::transaction()
when a rollback is initiated?Please let me know if I can help you out in any way with this issue.
Steps to reproduce
Run the following on PHP 8:
The text was updated successfully, but these errors were encountered: