diff --git a/core/lib/Drupal/Core/Database/Driver/mysql/Connection.php b/core/lib/Drupal/Core/Database/Driver/mysql/Connection.php
index 687700e7859f62d1f23c50843b92f61bc570ea36..ef6027256cccea2920a56025e8257a441ac9d4a8 100644
--- a/core/lib/Drupal/Core/Database/Driver/mysql/Connection.php
+++ b/core/lib/Drupal/Core/Database/Driver/mysql/Connection.php
@@ -89,6 +89,35 @@ class Connection extends DatabaseConnection {
    */
   protected $identifierQuotes = ['"', '"'];
 
+  /**
+   * {@inheritdoc}
+   */
+  public function __construct(\PDO $connection, array $connection_options) {
+    // If the SQL mode doesn't include 'ANSI_QUOTES' (explicitly or via a
+    // combination mode), then MySQL doesn't interpret a double quote as an
+    // identifier quote, in which case use the non-ANSI-standard backtick.
+    //
+    // Because we still support MySQL 5.7, check for the deprecated combination
+    // modes as well.
+    //
+    // @see https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_ansi_quotes
+    $ansi_quotes_modes = ['ANSI_QUOTES', 'ANSI', 'DB2', 'MAXDB', 'MSSQL', 'ORACLE', 'POSTGRESQL'];
+    $is_ansi_quotes_mode = FALSE;
+    foreach ($ansi_quotes_modes as $mode) {
+      // None of the modes in $ansi_quotes_modes are substrings of other modes
+      // that are not in $ansi_quotes_modes, so a simple stripos() does not
+      // return false positives.
+      if (stripos($connection_options['init_commands']['sql_mode'], $mode) !== FALSE) {
+        $is_ansi_quotes_mode = TRUE;
+        break;
+      }
+    }
+    if ($this->identifierQuotes === ['"', '"'] && !$is_ansi_quotes_mode) {
+      $this->identifierQuotes = ['`', '`'];
+    }
+    parent::__construct($connection, $connection_options);
+  }
+
   /**
    * {@inheritdoc}
    */
diff --git a/core/tests/Drupal/KernelTests/Core/Database/SqlModeTest.php b/core/tests/Drupal/KernelTests/Core/Database/SqlModeTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..49dd61373db2c9f9a27a6f0a636bd75ad07238b4
--- /dev/null
+++ b/core/tests/Drupal/KernelTests/Core/Database/SqlModeTest.php
@@ -0,0 +1,50 @@
+<?php
+
+namespace Drupal\KernelTests\Core\Database;
+
+/**
+ * Tests compatibility of the MySQL driver with various sql_mode options.
+ *
+ * @group Database
+ */
+class SqlModeTest extends DatabaseTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp(): void {
+    parent::setUp();
+
+    if ($this->connection->databaseType() !== 'mysql') {
+      $this->markTestSkipped("Skipping test since sql_mode is a MySQL-only feature.");
+    }
+  }
+
+  /**
+   * Tests quoting identifiers in queries.
+   */
+  public function testQuotingIdentifiers() {
+    // Use SQL-reserved words for both the table and column names.
+    $query = $this->connection->query('SELECT [update] FROM {select}');
+    $this->assertEquals('Update value 1', $query->fetchObject()->update);
+    $this->assertStringContainsString('SELECT `update` FROM `', $query->getQueryString());
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getDatabaseConnectionInfo() {
+    $info = parent::getDatabaseConnectionInfo();
+
+    // This runs during setUp(), so is not yet skipped for non MySQL databases.
+    // We defer skipping the test to later in setUp(), so that that can be
+    // based on databaseType() rather than 'driver', but here all we have to go
+    // on is 'driver'.
+    if ($info['default']['driver'] === 'mysql') {
+      $info['default']['init_commands']['sql_mode'] = "SET sql_mode = ''";
+    }
+
+    return $info;
+  }
+
+}