diff --git a/core/lib/Drupal/Core/Command/DbDumpCommand.php b/core/lib/Drupal/Core/Command/DbDumpCommand.php
index aa81af041f..337fd7dd51 100644
--- a/core/lib/Drupal/Core/Command/DbDumpCommand.php
+++ b/core/lib/Drupal/Core/Command/DbDumpCommand.php
@@ -260,7 +260,7 @@ protected function getTableCollation(Connection $connection, $table, &$definitio
     $data = $query->fetchAssoc();
 
     // Set `mysql_character_set`. This will be ignored by other backends.
-    $definition['mysql_character_set'] = str_replace('_general_ci', '', $data['Collation']);
+    $definition['mysql_character_set'] = str_replace(['_general_ci', '_0900_ai_ci'], '', $data['Collation']);
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Database/Driver/mysql/Connection.php b/core/lib/Drupal/Core/Database/Driver/mysql/Connection.php
index 164f68a947..637f713b43 100644
--- a/core/lib/Drupal/Core/Database/Driver/mysql/Connection.php
+++ b/core/lib/Drupal/Core/Database/Driver/mysql/Connection.php
@@ -179,9 +179,18 @@ public static function open(array &$connection_options = []) {
     $connection_options += [
       'init_commands' => [],
     ];
+
+    $sql_mode = 'ANSI,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,ONLY_FULL_GROUP_BY';
+    // NO_AUTO_CREATE_USER is removed in MySQL 8.0.11
+    // https://dev.mysql.com/doc/relnotes/mysql/8.0/en/news-8-0-11.html#mysqld-8-0-11-deprecation-removal
+    $version_server = $pdo->getAttribute(\PDO::ATTR_SERVER_VERSION);
+    if (version_compare($version_server, '8.0.11', '<')) {
+      $sql_mode .= ',NO_AUTO_CREATE_USER';
+    }
     $connection_options['init_commands'] += [
-      'sql_mode' => "SET sql_mode = 'ANSI,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,ONLY_FULL_GROUP_BY'",
+      'sql_mode' => "SET sql_mode = '$sql_mode'",
     ];
+
     // Execute initial commands.
     foreach ($connection_options['init_commands'] as $sql) {
       $pdo->exec($sql);
@@ -190,6 +199,33 @@ public static function open(array &$connection_options = []) {
     return $pdo;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function escapeField($field) {
+    if (!isset($this->escapedNames[$field])) {
+      $escaped = preg_replace('/[^A-Za-z0-9_.]+/', '', $field);
+
+      // Quote fields so that MySQL reserved words like 'function' can be used
+      // as column names. Sometimes the 'table.column_name' format is passed in.
+      // For example,
+      // \Drupal\Core\Entity\Sql\SqlContentEntityStorage::buildQuery() adds a
+      // condition on "base.uid" while loading user entities.
+      $this->escapedNames[$field] = '"' . str_replace('.', '"."', $escaped) . '"';
+    }
+    return $this->escapedNames[$field];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function escapeAlias($field) {
+    if (!isset($this->escapedAliases[$field])) {
+      $this->escapedAliases[$field] = '"' . preg_replace('/[^A-Za-z0-9_]+/', '', $field) . '"';
+    }
+    return $this->escapedAliases[$field];
+  }
+
   /**
    * {@inheritdoc}
    */
diff --git a/core/lib/Drupal/Core/Database/Driver/mysql/Insert.php b/core/lib/Drupal/Core/Database/Driver/mysql/Insert.php
index 8b7c602e87..cd1f69b40a 100644
--- a/core/lib/Drupal/Core/Database/Driver/mysql/Insert.php
+++ b/core/lib/Drupal/Core/Database/Driver/mysql/Insert.php
@@ -44,6 +44,10 @@ public function __toString() {
     // Default fields are always placed first for consistency.
     $insert_fields = array_merge($this->defaultFields, $this->insertFields);
 
+    $insert_fields = array_map(function ($f) {
+      return $this->connection->escapeField($f);
+    }, $insert_fields);
+
     // If we're selecting from a SelectQuery, finish building the query and
     // pass it back, as any remaining options are irrelevant.
     if (!empty($this->fromQuery)) {
diff --git a/core/lib/Drupal/Core/Database/Driver/mysql/Schema.php b/core/lib/Drupal/Core/Database/Driver/mysql/Schema.php
index baac2eee5a..b742c2ce22 100644
--- a/core/lib/Drupal/Core/Database/Driver/mysql/Schema.php
+++ b/core/lib/Drupal/Core/Database/Driver/mysql/Schema.php
@@ -154,12 +154,15 @@ protected function createFieldSql($name, $spec) {
       if (isset($spec['length'])) {
         $sql .= '(' . $spec['length'] . ')';
       }
+      if (isset($spec['type']) && $spec['type'] == 'varchar_ascii') {
+        $sql .= ' CHARACTER SET ascii';
+      }
       if (!empty($spec['binary'])) {
         $sql .= ' BINARY';
       }
       // Note we check for the "type" key here. "mysql_type" is VARCHAR:
-      if (isset($spec['type']) && $spec['type'] == 'varchar_ascii') {
-        $sql .= ' CHARACTER SET ascii COLLATE ascii_general_ci';
+      elseif (isset($spec['type']) && $spec['type'] == 'varchar_ascii') {
+        $sql .= ' COLLATE ascii_general_ci';
       }
     }
     elseif (isset($spec['precision']) && isset($spec['scale'])) {
@@ -650,11 +653,11 @@ public function getComment($table, $column = NULL) {
       $condition->condition('column_name', $column);
       $condition->compile($this->connection, $this);
       // Don't use {} around information_schema.columns table.
-      return $this->connection->query("SELECT column_comment FROM information_schema.columns WHERE " . (string) $condition, $condition->arguments())->fetchField();
+      return $this->connection->query("SELECT column_comment as column_comment FROM information_schema.columns WHERE " . (string) $condition, $condition->arguments())->fetchField();
     }
     $condition->compile($this->connection, $this);
     // Don't use {} around information_schema.tables table.
-    $comment = $this->connection->query("SELECT table_comment FROM information_schema.tables WHERE " . (string) $condition, $condition->arguments())->fetchField();
+    $comment = $this->connection->query("SELECT table_comment as table_comment FROM information_schema.tables WHERE " . (string) $condition, $condition->arguments())->fetchField();
     // Work-around for MySQL 5.0 bug http://bugs.mysql.com/bug.php?id=11379
     return preg_replace('/; InnoDB free:.*$/', '', $comment);
   }
diff --git a/core/lib/Drupal/Core/Database/Schema.php b/core/lib/Drupal/Core/Database/Schema.php
index 279b5d41b0..4bd0a9bdf3 100644
--- a/core/lib/Drupal/Core/Database/Schema.php
+++ b/core/lib/Drupal/Core/Database/Schema.php
@@ -199,7 +199,7 @@ public function findTables($table_expression) {
     // couldn't use db_select() here because it would prefix
     // information_schema.tables and the query would fail.
     // Don't use {} around information_schema.tables table.
-    $results = $this->connection->query("SELECT table_name FROM information_schema.tables WHERE " . (string) $condition, $condition->arguments());
+    $results = $this->connection->query("SELECT table_name as table_name FROM information_schema.tables WHERE " . (string) $condition, $condition->arguments());
     foreach ($results as $table) {
       // Take into account tables that have an individual prefix.
       if (isset($individually_prefixed_tables[$table->table_name])) {
diff --git a/core/modules/system/tests/modules/database_test/database_test.install b/core/modules/system/tests/modules/database_test/database_test.install
index a5450b1064..ab952c746e 100644
--- a/core/modules/system/tests/modules/database_test/database_test.install
+++ b/core/modules/system/tests/modules/database_test/database_test.install
@@ -287,6 +287,10 @@ function database_test_schema() {
         'description' => 'A column with preserved name.',
         'type' => 'text',
       ],
+      'function' => [
+        'description' => 'A column with reserved name in MySQL 8.',
+        'type' => 'text',
+      ],
     ],
     'primary key' => ['id'],
   ];
diff --git a/core/modules/system/tests/src/Functional/Entity/Update/LangcodeToAsciiUpdateTest.php b/core/modules/system/tests/src/Functional/Entity/Update/LangcodeToAsciiUpdateTest.php
index 536fe41f79..653a437239 100644
--- a/core/modules/system/tests/src/Functional/Entity/Update/LangcodeToAsciiUpdateTest.php
+++ b/core/modules/system/tests/src/Functional/Entity/Update/LangcodeToAsciiUpdateTest.php
@@ -40,7 +40,8 @@ public function testLangcodeColumnCollation() {
     ];
     foreach ($tables as $table => $columns) {
       foreach ($columns as $column) {
-        $this->assertEqual('utf8mb4_general_ci', $this->getColumnCollation($table, $column), 'Found correct starting collation for ' . $table . '.' . $column);
+        // Depending on MYSQL versions you get different collations.
+        $this->assertContains($this->getColumnCollation($table, $column), ['utf8mb4_0900_ai_ci', 'utf8mb4_general_ci'], 'Found correct starting collation for ' . $table . '.' . $column);
       }
     }
 
diff --git a/core/tests/Drupal/KernelTests/Core/Database/InsertTest.php b/core/tests/Drupal/KernelTests/Core/Database/InsertTest.php
index 3812151bab..2082e8e074 100644
--- a/core/tests/Drupal/KernelTests/Core/Database/InsertTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Database/InsertTest.php
@@ -198,14 +198,20 @@ public function testInsertSelectAll() {
    * Tests that we can INSERT INTO a special named column.
    */
   public function testSpecialColumnInsert() {
-    $id = db_insert('test_special_columns')
+    $this->connection->insert('test_special_columns')
       ->fields([
         'id' => 2,
         'offset' => 'Offset value 2',
+        'function' => 'foobar',
       ])
       ->execute();
-    $saved_value = db_query('SELECT "offset" FROM {test_special_columns} WHERE id = :id', [':id' => 2])->fetchField();
-    $this->assertIdentical($saved_value, 'Offset value 2', 'Can retrieve special column name value after inserting.');
+    $result = $this->connection->select('test_special_columns')
+      ->fields('test_special_columns', ['offset', 'function'])
+      ->condition('test_special_columns.function', 'foobar')
+      ->execute();
+    $records = $result->fetch();
+    $this->assertSame('Offset value 2', $records->offset);
+    $this->assertSame('foobar', $records->function);
   }
 
 }
diff --git a/core/tests/Drupal/KernelTests/Core/Database/SchemaTest.php b/core/tests/Drupal/KernelTests/Core/Database/SchemaTest.php
index 259f5f559d..d501e1c97a 100644
--- a/core/tests/Drupal/KernelTests/Core/Database/SchemaTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Database/SchemaTest.php
@@ -72,7 +72,7 @@ public function testSchema() {
       $columns = db_query('SHOW FULL COLUMNS FROM {test_table}');
       foreach ($columns as $column) {
         if ($column->Field == 'test_field_string') {
-          $string_check = ($column->Collation == 'utf8mb4_general_ci');
+          $string_check = ($column->Collation == 'utf8mb4_general_ci' || $column->Collation == 'utf8mb4_0900_ai_ci');
         }
         if ($column->Field == 'test_field_string_ascii') {
           $string_ascii_check = ($column->Collation == 'ascii_general_ci');
