diff --git a/core/lib/Drupal/Core/Database/Driver/pgsql/.Connection.php.swp b/core/lib/Drupal/Core/Database/Driver/pgsql/.Connection.php.swp
new file mode 100644
index 0000000000..e74ff231d2
Binary files /dev/null and b/core/lib/Drupal/Core/Database/Driver/pgsql/.Connection.php.swp differ
diff --git a/core/lib/Drupal/Core/Database/Driver/pgsql/Connection.php b/core/lib/Drupal/Core/Database/Driver/pgsql/Connection.php
index 80b30893ca..da392a07c8 100644
--- a/core/lib/Drupal/Core/Database/Driver/pgsql/Connection.php
+++ b/core/lib/Drupal/Core/Database/Driver/pgsql/Connection.php
@@ -454,6 +454,45 @@ public function upsert($table, array $options = []) {
     return new $class($this, $table, $options);
   }
 
+  /**
+   * Retrieves a sequence owned by a table and column.
+   *
+   * @param string $table
+   *   A table name that is not prefixed or quoted.
+   * @param string $column
+   *   The column name.
+   *
+   * @return string|null
+   *   The name of the sequence or NULL if it does not exist.
+   */
+  public function getSequence($table, $column) {
+    $args = [
+      ':table' => $this->prefixTables('{' . $table . '}'),
+      ':column' => $column,
+    ];
+    return $this
+      ->query("SELECT pg_get_serial_sequence(:table, :column)", $args)
+      ->fetchField();
+  }
+
+  /**
+   * Checks if a sequence exists at all.
+   *
+   * @param string $name
+   *   The fully-qualified sequence name.
+   *
+   * @return bool
+   *   TRUE if the sequence exists by the name.
+   *
+   * @see \Drupal\Core\Database\Connection::makeSequenceName()
+   */
+  public function sequenceExists($name) {
+    $args = [':name' => $name];
+    return (bool) $this
+      ->query("SELECT c.relname FROM pg_class as c INNER JOIN pg_namespace as ns ON (c.relnamespace = ns.oid) WHERE c.relkind = 'S' AND c.relname = :name", $args)
+      ->fetchField();
+  }
+
 }
 
 /**
diff --git a/core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php b/core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php
index 78517d8e72..bac10ea63b 100644
--- a/core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php
+++ b/core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php
@@ -995,7 +995,7 @@ public function changeField($table, $field, $field_new, $spec, $new_keys = []) {
       // not when altering. Because of that, the sequence needs to be created
       // and initialized by hand.
       $seq = $this->connection->makeSequenceName($table, $field_new);
-      $this->connection->query("CREATE SEQUENCE " . $seq);
+      $this->connection->query("CREATE SEQUENCE " . $seq . " OWNED BY {" . $table . "}." . $field_new);
       // Set sequence to maximal field value to not conflict with existing
       // entries.
       $this->connection->query("SELECT setval('" . $seq . "', MAX(\"" . $field . '")) FROM {' . $table . "}");
@@ -1053,6 +1053,24 @@ protected function _createKeys($table, $new_keys) {
     }
   }
 
+  /**
+   * Alters the ownership of a sequence.
+   *
+   * This is used for updating orphaned sequences.
+   *
+   * @param string $table
+   *   The unquoted or prefixed table name.
+   * @param string $column
+   *   The column name for the sequence.
+   *
+   * @internal
+   */
+  public function changeSequenceOwnership($table, $column) {
+    $seq = $this->connection->makeSequenceName($table, $column);
+    $table_name = $this->connection->prefixTables('{' . $table . '}');
+    $this->connection->query('ALTER SEQUENCE ' . $seq . ' OWNED BY ' . $table_name . '.' . $column);
+  }
+
   /**
    * Retrieve a table or column comment.
    */
diff --git a/core/modules/system/system.install b/core/modules/system/system.install
index 018d5d003e..930cb6e8c0 100644
--- a/core/modules/system/system.install
+++ b/core/modules/system/system.install
@@ -2357,3 +2357,122 @@ function system_update_8801() {
       ->save(TRUE);
   }
 }
+
+/**
+ * Fix any orphan sequences created from column changes in PostgreSQL.
+ */
+function system_update_8802(&$sandbox) {
+  $connection = \Drupal::database();
+  if ($connection->databaseType() !== 'pgsql') {
+    // This database update is a no-op for all other core database drivers.
+    $sandbox['#finished'] = 1;
+    return NULL;
+  }
+
+  if (!isset($sandbox['progress'])) {
+    $sandbox['fixed'] = 0;
+    $sandbox['tables'] = [];
+
+    // Discovers all custom tables with serial columns.
+    $modules = \Drupal::moduleHandler()->getModuleList();
+    foreach ($modules as $extension) {
+      $module = $extension->getName();
+      if (\Drupal::moduleHandler()->moduleExists($module)) {
+        module_load_include('install', $module);
+        $schema = \Drupal::moduleHandler()->invoke($module, 'schema');
+        if (!empty($schema)) {
+          foreach ($schema as $table_name => $table_info) {
+            foreach ($table_info['fields'] as $column_name => $column_info) {
+              if (substr($column_info['type'], 0, 6) === 'serial' && $connection->schema()->tableExists($table_name)) {
+                $sandbox['tables'][] = [
+                  'table' => $table_name,
+                  'column' => $column_name,
+                ];
+              }
+            }
+          }
+        }
+      }
+    }
+
+    // Discovers all content entity types with integer entity keys that are most
+    // likely serial columns.
+    $entity_types = \Drupal::entityTypeManager()->getDefinitions();
+    /** @var \Drupal\Core\Entity\EntityTypeInterface $entity_type */
+    foreach ($entity_types as $entity_type) {
+      $storage_class = $entity_type->getStorageClass();
+      if (is_subclass_of($storage_class, '\Drupal\Core\Entity\Sql\SqlContentEntityStorage')) {
+        $entity_class = $entity_type->getClass();
+        $id_key = $entity_type->getKey('id');
+        $revision_key = $entity_type->getKey('revision');
+
+        /** @var \Drupal\Core\Field\BaseFieldDefinition[] $baseFieldDefinitions */
+        $baseFieldDefinitions = $entity_class::baseFieldDefinitions($entity_type);
+        if ($baseFieldDefinitions[$id_key]->getType() === 'integer' &&
+            $connection->schema()->tableExists($table_name)) {
+          $sandbox['tables'][] = [
+            'table' => $entity_type->getBaseTable(),
+            'column' => $id_key,
+          ];
+        }
+
+        if ($entity_type->isRevisionable() &&
+          $baseFieldDefinitions[$revision_key]->getType() === 'integer' &&
+          $connection->schema()->tableExists($table_name)) {
+          $sandbox['tables'][] = [
+            'table' => $entity_type->getRevisionTable(),
+            'column' => $revision_key,
+          ];
+        }
+      }
+
+      $sandbox['max'] = count($sandbox['tables']);
+      $sandbox['progress'] = 0;
+    }
+  }
+  else {
+    // Adds ownership of orphan sequences to tables.
+    $to_process = array_slice($sandbox['tables'], $sandbox['progress'], 50);
+
+    // Ensures that a sequence is not owned first, then ensures that the a
+    // sequence exists at all before trying to alter it.
+    foreach ($to_process as $table_info) {
+      $owned = (bool) $connection->getSequence($table_info['table'], $table_info['column']);
+
+      if (!$owned) {
+        $sequence_name = $connection
+          ->makeSequenceName($table_info['table'], $table_info['column']);
+        $exists = $connection
+          ->sequenceExists($sequence_name);
+        if ($exists) {
+          $transaction = $connection->startTransaction($sequence_name);
+          try {
+            $connection
+              ->schema()
+              ->changeSequenceOwnership($table_info['table'], $table_info['column']);
+
+            $sandbox['fixed']++;
+          }
+          catch (\Drupal\Core\Database\DatabaseExceptionWrapper $e) {
+            $transaction->rollBack();
+          }
+        }
+      }
+
+      $sandbox['progress']++;
+    }
+  }
+
+  if ($sandbox['max'] && $sandbox['progress'] < $sandbox['max']) {
+    $sandbox['#finished'] = $sandbox['progress'] / $sandbox['max'];
+  }
+  else {
+    $sandbox['#finished'] = 1;
+
+    return \Drupal::translation()->formatPlural(
+      $sandbox['fixed'],
+      '1 orphaned sequence fixed.',
+      '@count orphaned sequences fixed');
+  }
+}
+
diff --git a/core/modules/system/tests/fixtures/update/drupal-8.pgsql-orphan-sequence.php b/core/modules/system/tests/fixtures/update/drupal-8.pgsql-orphan-sequence.php
new file mode 100644
index 0000000000..57fdb5135f
--- /dev/null
+++ b/core/modules/system/tests/fixtures/update/drupal-8.pgsql-orphan-sequence.php
@@ -0,0 +1,45 @@
+<?php
+// @codingStandardsIgnoreFile
+
+use Drupal\Core\Database\Database;
+
+$connection = Database::getConnection();
+$db_type = $connection->databaseType();
+
+if ($db_type === 'pgsql') {
+  // Creates a table, then adds a sequence without ownership to simulate tables
+  // that were altered from integer to serial columns.
+  $connection
+    ->schema()
+    ->createTable('pgsql_sequence_test', [
+      'fields' => [
+        'sequence_field' => [
+          'type' => 'int',
+          'not null' => TRUE,
+          'unsigned' => TRUE,
+        ],
+      ],
+      'primary key' => ['sequence_field'],
+    ]);
+  $seq = $connection
+    ->makeSequenceName('pgsql_sequence_test', 'sequence_field');
+  $connection->query('CREATE SEQUENCE ' . $seq);
+
+  // Enables the pgsql_test module so that the pgsql_sequence_test schema will
+  // be available.
+  $extensions = $connection
+    ->query("SELECT data FROM {config} where name = 'core.extension'")
+    ->fetchField();
+  $extensions = unserialize($extensions);
+  $extensions['module']['pgsql_test'] = 1;
+
+  $connection
+    ->update('config')
+    ->fields(['data' => serialize($extensions)])
+    ->condition('name', 'core.extension')
+    ->execute();
+  $connection
+    ->delete('cache_config')
+    ->condition('cid', 'core.extension')
+    ->execute();
+}
diff --git a/core/modules/system/tests/modules/pgsql_test/pgsql_test.info.yml b/core/modules/system/tests/modules/pgsql_test/pgsql_test.info.yml
new file mode 100644
index 0000000000..1413878bba
--- /dev/null
+++ b/core/modules/system/tests/modules/pgsql_test/pgsql_test.info.yml
@@ -0,0 +1,6 @@
+name: 'PostgreSQL Tests'
+type: module
+description: 'Supports testing pgsql driver.'
+package: Testing
+version: VERSION
+core: 8.x
diff --git a/core/modules/system/tests/modules/pgsql_test/pgsql_test.install b/core/modules/system/tests/modules/pgsql_test/pgsql_test.install
new file mode 100644
index 0000000000..e9f1577e09
--- /dev/null
+++ b/core/modules/system/tests/modules/pgsql_test/pgsql_test.install
@@ -0,0 +1,24 @@
+<?php
+
+/**
+ * @file
+ * Install, update and uninstall functions for the pgsql_test module.
+ */
+
+/**
+ * Implements hook_schema().
+ */
+function pgsql_test_schema() {
+  $schema['pgsql_sequence_test'] = [
+    'description' => 'Test sequence changes on pgsql driver.',
+    'fields' => [
+      'sequence_field' => [
+        'type' => 'serial',
+        'not null' => TRUE,
+        'description' => 'Primary Key: A serial integer field.',
+      ],
+    ],
+    'primary key' => ['sequence_field'],
+  ];
+  return $schema;
+}
diff --git a/core/modules/system/tests/modules/pgsql_test/pgsql_test.module b/core/modules/system/tests/modules/pgsql_test/pgsql_test.module
new file mode 100644
index 0000000000..ed9b9589df
--- /dev/null
+++ b/core/modules/system/tests/modules/pgsql_test/pgsql_test.module
@@ -0,0 +1,6 @@
+<?php
+
+/**
+ * @file
+ * Module functions for the pgsql_test module.
+ */
diff --git a/core/tests/Drupal/FunctionalTests/Core/Database/PostgreSqlSequenceUpdateTest.php b/core/tests/Drupal/FunctionalTests/Core/Database/PostgreSqlSequenceUpdateTest.php
new file mode 100644
index 0000000000..a306b064a0
--- /dev/null
+++ b/core/tests/Drupal/FunctionalTests/Core/Database/PostgreSqlSequenceUpdateTest.php
@@ -0,0 +1,47 @@
+<?php
+
+namespace Drupal\FunctionalTests\Core\Database;
+
+use Drupal\FunctionalTests\Update\UpdatePathTestBase;
+
+/**
+ * Tests that any unowned sequences created previously have a table owner.
+ *
+ * The update path only applies to Drupal sites using the pgsql driver.
+ *
+ * @group database
+ */
+class PostgreSqlSequenceUpdateTest extends UpdatePathTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setDatabaseDumpFiles() {
+    $this->databaseDumpFiles = [
+      __DIR__ . '/../../../../../modules/system/tests/fixtures/update/drupal-8.6.0.bare.testing.php.gz',
+      __DIR__ . '/../../../../../modules/system/tests/fixtures/update/drupal-8.pgsql-orphan-sequence.php',
+    ];
+  }
+
+  /**
+   * Asserts that a newly created sequence has the correct ownership.
+   */
+  public function testPostgreSqlSequenceUpdate() {
+    $database = $this->container->get('database');
+    $db_type = $database->databaseType();
+
+    // Run the updates.
+    $this->runUpdates();
+
+    if ($db_type === 'pgsql') {
+      $sequenceExists = (bool) $database
+        ->query("SELECT pg_get_serial_sequence('{" . $database->prefixTables('pgsql_sequence_test') . "}', 'sequence_field')")
+        ->fetchField();
+      $this->assertTrue($sequenceExists, 'Sequence is owned by the table and column.');
+    }
+    else {
+      $this->assertTrue(TRUE, 'Database update ran successfully on non-pgsql driver.');
+    }
+  }
+
+}
diff --git a/core/tests/Drupal/KernelTests/Core/Database/SchemaTest.php b/core/tests/Drupal/KernelTests/Core/Database/SchemaTest.php
index 2a86e3470f..d0d573df0b 100644
--- a/core/tests/Drupal/KernelTests/Core/Database/SchemaTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Database/SchemaTest.php
@@ -56,6 +56,9 @@ protected function setUp() {
    * Tests database interactions.
    */
   public function testSchema() {
+    // Tests for indexes are Database specific.
+    $db_type = $this->connection->databaseType();
+
     // Try creating a table.
     $table_specification = [
       'description' => 'Schema table description may contain "quotes" and could be long—very long indeed.',
@@ -94,7 +97,7 @@ public function testSchema() {
     // Assert that the column comment has been set.
     $this->checkSchemaComment($table_specification['fields']['test_field']['description'], 'test_table', 'test_field');
 
-    if ($this->connection->databaseType() === 'mysql') {
+    if ($db_type === 'mysql') {
       // Make sure that varchar fields have the correct collation.
       $columns = $this->connection->query('SHOW FULL COLUMNS FROM {test_table}');
       foreach ($columns as $column) {
@@ -161,6 +164,13 @@ public function testSchema() {
 
     // Change the new field to a serial column.
     $this->schema->changeField('test_table', 'test_serial', 'test_serial', ['type' => 'serial', 'not null' => TRUE, 'description' => 'Changed column description.'], ['primary key' => ['test_serial']]);
+    // Confirms that the new sequence is owned by the table in PostgreSQL.
+    if ($db_type == 'pgsql') {
+      $sequence_exists = (bool) $this->connection
+        ->query("SELECT pg_get_serial_sequence('{test_table}', 'test_serial')")
+        ->fetchField();
+      $this->assertTrue($sequence_exists, 'New sequence is owned by its table.');
+    }
 
     // Assert that the column comment has been set.
     $this->checkSchemaComment('Changed column description.', 'test_table', 'test_serial');
