diff --git a/core/lib/Drupal/Core/Database/Driver/mysql/Connection.php b/core/lib/Drupal/Core/Database/Driver/mysql/Connection.php
index 016c283824..30f977a2d8 100644
--- a/core/lib/Drupal/Core/Database/Driver/mysql/Connection.php
+++ b/core/lib/Drupal/Core/Database/Driver/mysql/Connection.php
@@ -11,6 +11,7 @@
 use Drupal\Core\Database\DatabaseException;
 use Drupal\Core\Database\Connection as DatabaseConnection;
 use Drupal\Component\Utility\Unicode;
+use Drupal\Core\Database\TransactionNoActiveException;
 
 /**
  * @addtogroup database
@@ -417,6 +418,53 @@ protected function popCommittableTransactions() {
     }
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function rollBack($savepoint_name = 'drupal_transaction') {
+    try {
+      return parent::rollBack($savepoint_name);
+    }
+    catch (\PdoException $e) {
+    }
+
+    // Convert the \PdoException to a Drupal database exception.
+    if ($e->getMessage() === 'There is no active transaction') {
+      // Note that on PHP 7 this code is never called as an exception is not
+      // thrown by PDO in this case.
+      throw new TransactionNoActiveException($e->getMessage(), $e->getCode(), $e);
+    }
+    throw new DatabaseExceptionWrapper($e->getMessage(), $e->getCode(), $e);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function doCommit() {
+    try {
+      $success = parent::doCommit();
+    }
+    catch (\PdoException $e) {
+      if ($e->getMessage() !== 'There is no active transaction') {
+        throw new DatabaseExceptionWrapper($e->getMessage(), $e->getCode(), $e);
+      }
+      // On PHP 7 $this->connection->commit() does not throw an exception if
+      // there is no active transaction.In order to maintain consistent
+      // behaviour on PHP 8 we have to assume that all queries have been
+      // committed. This situation occurs when tables are altered or created
+      // (DDL transactions are not supported).
+      $success = TRUE;
+      if (!empty($this->rootTransactionEndCallbacks)) {
+        $callbacks = $this->rootTransactionEndCallbacks;
+        $this->rootTransactionEndCallbacks = [];
+        foreach ($callbacks as $callback) {
+          call_user_func($callback, $success);
+        }
+      }
+    }
+    return $success;
+  }
+
 }
 
 
diff --git a/core/tests/Drupal/KernelTests/Core/Database/TransactionTest.php b/core/tests/Drupal/KernelTests/Core/Database/TransactionTest.php
index 2592a9894d..7831307af2 100644
--- a/core/tests/Drupal/KernelTests/Core/Database/TransactionTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Database/TransactionTest.php
@@ -258,14 +258,16 @@ public function testTransactionWithDdlStatement() {
       $transaction = $this->connection->startTransaction();
       $this->insertRow('row');
       $this->executeDDLStatement();
+
       // Rollback the outer transaction.
       try {
         $transaction->rollBack();
         unset($transaction);
-        // @todo An exception should be triggered here, but is not because
-        // "ROLLBACK" fails silently in MySQL if there is no transaction active.
-        // @see https://www.drupal.org/project/drupal/issues/2736777
-        // $this->fail('Rolling back a transaction containing DDL should fail.');
+        // The PHP 7 MySQL driver does not trigger an exception when calling
+        // rollback and there is no active transaction.
+        if (PHP_VERSION_ID >= 80000) {
+          $this->fail('Rolling back a transaction containing DDL should fail.');
+        }
       }
       catch (TransactionNoActiveException $e) {
         // Expected exception; just continue testing.
