-
-
Notifications
You must be signed in to change notification settings - Fork 389
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
DDL migrations produce errors on PHP 8.0 + MySQL in transactional mode #1104
Comments
It looks like this problem exists also at version
|
Just do it like pierres as a workaround until its fixed. class Version**** extends AbstractMigration
{
public function up(Schema $schema): void
{
// your migration
}
public function isTransactional(): bool
{
return false;
}
} |
I'm wondering if this issue should be moved to @morozov , what do you think? Should this be handled in |
An other option would be to catch the error here where he is thrown. |
I think that's an anti-pattern (at least in PHP, I think in python it would be… well pythonic). IIRC that's because exceptions are costly but I'm not sure this is true, it might be cultural. Anyway, it's not something that we usually do I think. Also, |
@greg0ire as far as I understand, it's the migrations who starts the transaction, executes the DDL and then commits the transaction that already has been implicitly committed. Why and how should the DBAL solve this problem? |
I did not spot this, and of course, you're correct. This issue is in the right repository 👍 |
I believe the fix could be a simple -if ($migration->isTransactional()) {
+if ($migration->isTransactional() && (!$this->connection->getWrappedConnection() instanceof PDOConnection || $this->connection->getWrappedConnection()->inTransaction())) { Can anybody try that? |
I had to add |
A way to do the same without resorting to a deprecated name would be to use |
Yes, |
@morozov I am not sure the DBAL could solve the issue, but it would definitely help to have In v2, this package has 4 occurrences of try {
$connection->beginTransaction();
$connection->executeSomeSQLWithDDLStatements(); // works fine and auto-commits
callUnrelatedToDatabaseThatThrows();
} catch (Throwable $e) {
$connection->rollBack();
} Alternate solution to adding All of my proposals would constitue BC-breaks in the DBAL though, so we would still have to complexify code here as a first step I'm afraid. Also, none of them feel really good to me, maybe you will have better ideas? |
Should it work with the non-PDO MySQL driver as well and only with the MySQL (PDO and non-PDO) drivers? |
I overlooked mysqli, and the link to php-src given by @lippok above points to a change that is about mysqli and only it, so that's weird. It does mean my fix is probaby incomplete, the condition should be complexify to handle mysqli too. |
On the other hand
I hit this issue too when upgraded to PHP8, right now I've used workaround with custom abstract migration class with @nicklog's |
Does mysqli complain if you COMMIT without an active transaction? I thought this was a PDO thing. |
I thought so too, but OP linked to a commit that seems to be about mysqli (php/php-src@990bb34) @lippok, or any of the 15 people that upvoted this, please try with mysqli and report back. |
When I'm using the driver I assume it has no influence, but I pass the db configuration with the option |
Furthermore, we can see that php/php-src@990bb34 is also included in 7.4.13, so we probably would have had a lot of bug reports if there was an issue with mysqli indeed. |
What are the expectation of the users who use transactional migrations and MySQL that doesn't respect them? |
Here, it's not end users that are asking for transactions, it's this package. Maybe not using transactions when MySQL is detected would be the best solution. We could fix this by having |
This way, the behavior of the migration is not portable. If the user runs it on say PostgreSQL and MySQL, they will have to be prepared that the migration won't be transactional in the worst case. Then what's the point in having it transactional with PostgreSQL? IMO, it's the party who builds and runs the migration that needs to decide whether it has to be transactional or not. If it has to be transactional, it cannot be run on MySQL. |
Sounds fair. This means:
|
Since it's the MySQL platform that doesn't support DDL in a transaction, why should the logic above depend on the PHP version and the driver? |
Keep in mind that a migration does not necessarily contain DDL statements. A migration that only consists of |
@morozov because apparently the issue is swept under the rug when using other configurations. If we make the condition based on the platform, then we will make a lot more migrations that could run properly with the expected outcome no longer valid. @derrabus ' remark makes me think that even this would not be possible, and that the only thing we can improve is the defaults, if we think the migrations he describes are the exception rather than the rule. |
@stingus regarding composer.lock - yes, my bad, agree; regarding composer require - why should I require the library outside of bundle? |
@yyaremenko my bad this time :) I've meant |
@stingus the problem here is since the lock file has an older requirement, upon new version of bundle installation you get an error
this can be fixed by running
but this updates quite a lot of dependencies aside from doctrine migrations. |
okay looks like I figured out the magic trick lol
looks like this one only updates the target library and the target bundle, leaving the rest of composer.lock intact. |
If you only want to update that bundle, why not run |
@NicoHaase good idea, thank you; but as I tried it, it updated the bundle from v3.0.2 to v3.0.3, and this is not what we want |
What does |
(I've already updated to 3.1.1) |
See linked issues and pull requests. I don't know why do you guys comment on closed issue... |
@ostrolucky I wonder if you actually read the comments before making your remark. Because if you did, you would understand that 'linked issues and pull requests' had nothing to do with the problem discussed. Oh and probably you would also understand why we comment on a closed issue. |
I had also updated doctrine/migrations and doctrine/doctrine-migrations-bundle to their latest versions, but started to receive this error again. Turned out that it was caused by a |
Still having this issue with 2.3.4 |
So i guess i should either add 'isTransactional()) methods to all migrations if using <3.0 version or use configuration to specify the same with >3.0 ? (at least these seem to be the simplest solutions) Thanks for the link |
The configuration only affects new migrations, so you will have to do the first item regardless of the version. It would be cool if there was a way to do this with Rector |
ok, thanks. |
Hi! The easiest solution is to provide needed version in composer.json
Transactions works correctly with php 8.0 + MySql 5.7 |
I'd rather not upgrade to 3 yet, it's not perfect when using multiple entityManagers (at least i haven't found a good way to make it work yet). But your solution might work for others. Thanks either way. |
This works for me, downgrade on php8 & MySQL 8.0.20 |
Same setup, can confirm, this works |
@greg0ire im getting this error too (without using doctrine migrations) by using doctrine/dbal and php8. any chance this fix might be ported to dbal too? i guess it wont be changed on the PHP-SRC side |
@digitalkaoz what fix? There is no fix, just don't attempt to use DDL + transactions with MySQL or Oracle, they do not support it. |
Following the doc : https://www.doctrine-project.org/projects/doctrine-migrations/en/3.3/reference/configuration.html If you are using Symfony and |
BC Break Report
Summary
When running the command
migrations:migrate
with a ddl sql statement (e.g.create table
) on php 8.0 I got an error:Previous behavior
Bevore php 8.0 the migration produces no errors.
Current behavior
DDL statements on mysql result in an implicit commit (see mysql documentation). This causes the explicit commit in transactional mode to fail. But only starting with php 8.0 an error is raised (probably due to php/php-src@990bb34).
To bypass the error I can disable the transactional mode by overwriting
isTransactional
in my migration, but in my opinion it's a breaking change in the behaviour when using php 8.I found the same issue in a bug report for the yii framework (yiisoft/yii2#18406) that helped me to figure out what happens. They fixed it by checking
PDO::inTransaction
before running the commit. If I'm not wrong this method is not wrapped by the dbal package and therefore not available here.How to reproduce
The text was updated successfully, but these errors were encountered: