Skip to content

Commit

Permalink
Stop throwing exceptions on commit in PHP8+pdo_mysql combo
Browse files Browse the repository at this point in the history
MySQL commits implicitly after every DDL query, but since PHP 8, mysql_pdo started to throw exception when attempting to explicitly commit after it implicitly committed. This causes to interrupt the migration process even though all queries completed successfully.

Alternative would be to disable transaction for PHP8+pdo_mysql, but that would affect all queries, not only DDL ones like intended, hence going with guard check before each explicit commit.

Hopefully this will be fixed directly in DBAL in future, but so far this doesn't look very likely...
  • Loading branch information
ostrolucky committed Mar 13, 2021
1 parent a229b64 commit 670ed59
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Doctrine\Common\EventSubscriber;
use Doctrine\Migrations\Event\MigrationsEventArgs;
use Doctrine\Migrations\Events;
use Doctrine\Migrations\Tools\Console\TransactionHelper;

/**
* Listens for `onMigrationsMigrated` and, if the connection has autocommit
Expand All @@ -24,7 +25,7 @@ public function onMigrationsMigrated(MigrationsEventArgs $args): void
return;
}

$conn->commit();
TransactionHelper::commitIfInTransaction($conn);
}

/** {@inheritdoc} */
Expand Down
3 changes: 2 additions & 1 deletion lib/Doctrine/Migrations/Migrator.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Doctrine\Migrations\Exception\NoMigrationsToExecute;
use Doctrine\Migrations\Exception\UnknownMigrationVersion;
use Doctrine\Migrations\Tools\BytesFormatter;
use Doctrine\Migrations\Tools\Console\TransactionHelper;
use Doctrine\Migrations\Version\Direction;
use Doctrine\Migrations\Version\Version;
use Symfony\Component\Stopwatch\StopwatchEvent;
Expand Down Expand Up @@ -202,7 +203,7 @@ private function executeMigration(
}

if ($allOrNothing) {
$connection->commit();
TransactionHelper::commitIfInTransaction($connection);
}

return $sql;
Expand Down
26 changes: 26 additions & 0 deletions lib/Doctrine/Migrations/Tools/Console/TransactionHelper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

declare(strict_types=1);

namespace Doctrine\Migrations\Tools\Console;

use Doctrine\DBAL\Connection;
use PDO;

/**
* @internal
*/
final class TransactionHelper
{
public static function commitIfInTransaction(Connection $connection): void
{
$wrappedConnection = $connection->getWrappedConnection();

// Attempt to commit while no transaction is running results in exception since PHP 8 + pdo_mysql combination
if ($wrappedConnection instanceof PDO && ! $wrappedConnection->inTransaction()) {
return;
}

$connection->commit();
}
}
3 changes: 2 additions & 1 deletion lib/Doctrine/Migrations/Tracking/TableUpdater.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Doctrine\DBAL\Schema\AbstractSchemaManager;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\DBAL\Schema\Table;
use Doctrine\Migrations\Tools\Console\TransactionHelper;
use Throwable;

use function in_array;
Expand Down Expand Up @@ -66,7 +67,7 @@ public function updateMigrationTable(): void
throw $e;
}

$this->connection->commit();
TransactionHelper::commitIfInTransaction($this->connection);
}

/**
Expand Down
4 changes: 2 additions & 2 deletions lib/Doctrine/Migrations/Version/Executor.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use Doctrine\Migrations\Provider\SchemaDiffProviderInterface;
use Doctrine\Migrations\Stopwatch;
use Doctrine\Migrations\Tools\BytesFormatter;
use Doctrine\Migrations\Tools\Console\TransactionHelper;
use Throwable;

use function count;
Expand Down Expand Up @@ -257,8 +258,7 @@ private function executeMigration(
}

if ($migration->isTransactional()) {
//commit only if running in transactional mode
$this->connection->commit();
TransactionHelper::commitIfInTransaction($this->connection);
}

$version->setState(State::NONE);
Expand Down

0 comments on commit 670ed59

Please sign in to comment.