diff --git a/core/lib/Drupal/Core/Database/Driver/mysql/Schema.php b/core/lib/Drupal/Core/Database/Driver/mysql/Schema.php
index ffe670f450..e011377e4d 100644
--- a/core/lib/Drupal/Core/Database/Driver/mysql/Schema.php
+++ b/core/lib/Drupal/Core/Database/Driver/mysql/Schema.php
@@ -522,6 +522,17 @@ public function dropPrimaryKey($table) {
     return TRUE;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function findPrimaryKeyColumns($table) {
+    if (!$this->tableExists($table)) {
+      return FALSE;
+    }
+    $result = $this->connection->query("SHOW KEYS FROM {" . $table . "} WHERE Key_name = 'PRIMARY'")->fetchAllAssoc('Column_name');
+    return array_keys($result);
+  }
+
   /**
    * {@inheritdoc}
    */
diff --git a/core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php b/core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php
index 15bcb11ce5..800357d041 100644
--- a/core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php
+++ b/core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php
@@ -715,6 +715,17 @@ public function dropPrimaryKey($table) {
     return TRUE;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function findPrimaryKeyColumns($table) {
+    if (!$this->tableExists($table)) {
+      return FALSE;
+    }
+    $result = $this->connection->query("SELECT a.attname, format_type(a.atttypid, a.atttypmod) AS data_type FROM pg_index i JOIN pg_attribute a ON a.attrelid = i.indrelid AND a.attnum = ANY(i.indkey) WHERE i.indrelid = '{" . $table . "}'::regclass AND i.indisprimary")->fetchAllAssoc('attname');
+    return array_keys($result);
+  }
+
   /**
    * {@inheritdoc}
    */
diff --git a/core/lib/Drupal/Core/Database/Driver/sqlite/Schema.php b/core/lib/Drupal/Core/Database/Driver/sqlite/Schema.php
index db2e348ef3..54e2e29d8c 100644
--- a/core/lib/Drupal/Core/Database/Driver/sqlite/Schema.php
+++ b/core/lib/Drupal/Core/Database/Driver/sqlite/Schema.php
@@ -512,6 +512,7 @@ protected function introspectSchema($table) {
     $indexes = [];
     $result = $this->connection->query('PRAGMA ' . $info['schema'] . '.index_list(' . $info['table'] . ')');
     foreach ($result as $row) {
+var_export($row);
       if (strpos($row->name, 'sqlite_autoindex_') !== 0) {
         $indexes[] = [
           'schema_key' => $row->unique ? 'unique keys' : 'indexes',
@@ -741,6 +742,17 @@ public function dropPrimaryKey($table) {
     return TRUE;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function findPrimaryKeyColumns($table) {
+    if (!$this->tableExists($table)) {
+      return FALSE;
+    }
+    $schema = $this->introspectSchema($table);
+    return $schema['primary key'];
+  }
+
   /**
    * {@inheritdoc}
    */
diff --git a/core/lib/Drupal/Core/Database/Schema.php b/core/lib/Drupal/Core/Database/Schema.php
index aafe1756ba..8baa83c0d3 100644
--- a/core/lib/Drupal/Core/Database/Schema.php
+++ b/core/lib/Drupal/Core/Database/Schema.php
@@ -408,6 +408,18 @@ public function fieldExists($table, $column) {
    */
   abstract public function dropPrimaryKey($table);
 
+  /**
+   * Finds the primary key columns of a table, from the database.
+   *
+   * @param string $table
+   *   The name of the table.
+   *
+   * @return string[]|false
+   *   A simple array with the names of the columns composing the table's
+   *   primary key, or FALSE if the table does not exist.
+   */
+  abstract public function findPrimaryKeyColumns($table);
+
   /**
    * Add a unique key.
    *
diff --git a/core/tests/Drupal/KernelTests/Core/Database/SchemaTest.php b/core/tests/Drupal/KernelTests/Core/Database/SchemaTest.php
index 9cbd186420..4f609f28a7 100644
--- a/core/tests/Drupal/KernelTests/Core/Database/SchemaTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Database/SchemaTest.php
@@ -12,6 +12,8 @@
 /**
  * Tests table creation and modification via the schema API.
  *
+ * @coversDefaultClass \Drupal\Core\Database\Schema
+ *
  * @group Database
  */
 class SchemaTest extends KernelTestBase {
@@ -149,7 +151,8 @@ public function testSchema() {
     db_field_set_default('test_table', 'test_field', 0);
     db_add_field('test_table', 'test_serial', ['type' => 'serial', 'not null' => TRUE], ['primary key' => ['test_serial']]);
 
-    $this->assertPrimaryKeyColumns('test_table', ['test_serial']);
+    // Test the primary key columns.
+    $this->assertSame(['test_serial'], Database::getConnection()->schema()->findPrimaryKeyColumns('test_table'));
 
     $this->assertTrue($this->tryInsert(), 'Insert with a serial succeeded.');
     $max1 = db_query('SELECT MAX(test_serial) FROM {test_table}')->fetchField();
@@ -163,7 +166,8 @@ public function testSchema() {
     // Test adding a new column and form a composite primary key with it.
     db_add_field('test_table', 'test_composite_primary_key', ['type' => 'int', 'not null' => TRUE, 'default' => 0], ['primary key' => ['test_serial', 'test_composite_primary_key']]);
 
-    $this->assertPrimaryKeyColumns('test_table', ['test_serial', 'test_composite_primary_key']);
+    // Test the primary key columns.
+    $this->assertSame(['test_serial', 'test_composite_primary_key'], Database::getConnection()->schema()->findPrimaryKeyColumns('test_table'));
 
     // Test renaming of keys and constraints.
     db_drop_table('test_table');
@@ -791,6 +795,87 @@ protected function assertFieldChange($old_spec, $new_spec, $test_data = NULL) {
     db_drop_table($table_name);
   }
 
+  /**
+   * @covers ::findPrimaryKeyColumns
+   */
+  public function testFindPrimaryKeyColumns() {
+    $connection = Database::getConnection();
+
+    $connection->schema()->createTable('table_with_pk_0', [
+      'description' => 'Table with primary key.',
+      'fields' => [
+        'id'  => [
+          'type' => 'int',
+          'not null' => TRUE,
+        ],
+        'test_field'  => [
+          'type' => 'int',
+          'not null' => TRUE,
+        ],
+      ],
+      'primary key' => ['id'],
+    ]);
+    $connection->schema()->createTable('table_with_pk_1', [
+      'description' => 'Table with primary key with multiple columns.',
+      'fields' => [
+        'id0'  => [
+          'type' => 'int',
+          'not null' => TRUE,
+        ],
+        'id1'  => [
+          'type' => 'int',
+          'not null' => TRUE,
+        ],
+        'test_field'  => [
+          'type' => 'int',
+          'not null' => TRUE,
+        ],
+      ],
+      'primary key' => ['id0', 'id1'],
+    ]);
+    $connection->schema()->createTable('table_with_pk_2', [
+      'description' => 'Table with primary key with multiple columns at the end and in reverted sequence.',
+      'fields' => [
+        'test_field_1'  => [
+          'type' => 'int',
+          'not null' => TRUE,
+        ],
+        'test_field_2'  => [
+          'type' => 'int',
+          'not null' => TRUE,
+        ],
+        'id3'  => [
+          'type' => 'int',
+          'not null' => TRUE,
+        ],
+        'id4'  => [
+          'type' => 'int',
+          'not null' => TRUE,
+        ],
+      ],
+      'primary key' => ['id4', 'id3'],
+    ]);
+    $connection->schema()->createTable('table_without_pk', [
+      'description' => 'Table without primary key.',
+      'fields' => [
+        'id'  => [
+          'type' => 'int',
+          'not null' => TRUE,
+        ],
+        'test_field'  => [
+          'type' => 'int',
+          'not null' => TRUE,
+        ],
+      ],
+    ]);
+
+    $this->assertSame(['id'], $connection->schema()->findPrimaryKeyColumns('table_with_pk_0'));
+    $this->assertSame(['id0', 'id1'], $connection->schema()->findPrimaryKeyColumns('table_with_pk_1'));
+    $this->assertSame(['id4', 'id3'], $connection->schema()->findPrimaryKeyColumns('table_with_pk_2'));
+    $this->assertSame([], $connection->schema()->findPrimaryKeyColumns('table_without_pk'));
+    $this->assertFalse($connection->schema()->findPrimaryKeyColumns('non_existing_table'));
+  }
+
   /**
    * Tests the findTables() method.
    */
@@ -849,46 +934,4 @@ public function testFindTables() {
     Database::setActiveConnection('default');
   }
 
-  /**
-   * Tests the primary keys of a table.
-   *
-   * @param string $table_name
-   *   The name of the table to check.
-   * @param array $primary_key
-   *   The expected key column specifier for a table's primary key.
-   */
-  protected function assertPrimaryKeyColumns($table_name, array $primary_key = []) {
-    $db_type = Database::getConnection()->databaseType();
-
-    switch ($db_type) {
-      case 'mysql':
-        $result = Database::getConnection()->query("SHOW KEYS FROM {" . $table_name . "} WHERE Key_name = 'PRIMARY'")->fetchAllAssoc('Column_name');
-        $this->assertSame($primary_key, array_keys($result));
-
-        break;
-      case 'pgsql':
-        $result = Database::getConnection()->query("SELECT a.attname, format_type(a.atttypid, a.atttypmod) AS data_type
-          FROM pg_index i
-          JOIN pg_attribute a ON a.attrelid = i.indrelid AND a.attnum = ANY(i.indkey)
-          WHERE i.indrelid = '{" . $table_name . "}'::regclass AND i.indisprimary")
-          ->fetchAllAssoc('attname');
-        $this->assertSame($primary_key, array_keys($result));
-
-        break;
-      case 'sqlite':
-        // For SQLite we need access to the protected
-        // \Drupal\Core\Database\Driver\sqlite\Schema::introspectSchema() method
-        // because we have no other way of getting the table prefixes needed for
-        // running a straight PRAGMA query.
-        $schema_object = Database::getConnection()->schema();
-        $reflection = new \ReflectionMethod($schema_object, 'introspectSchema');
-        $reflection->setAccessible(TRUE);
-
-        $table_info = $reflection->invoke($schema_object, $table_name);
-        $this->assertSame($primary_key, $table_info['primary key']);
-
-        break;
-    }
-  }
-
 }
