diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php
index 1a3b943..a0adb9e 100644
--- a/core/lib/Drupal/Core/DrupalKernel.php
+++ b/core/lib/Drupal/Core/DrupalKernel.php
@@ -9,6 +9,7 @@
 use Drupal\Core\Config\BootstrapConfigStorageFactory;
 use Drupal\Core\Config\NullStorage;
 use Drupal\Core\Database\Database;
+use Drupal\Core\Database\DatabaseException;
 use Drupal\Core\DependencyInjection\ContainerBuilder;
 use Drupal\Core\DependencyInjection\ServiceModifierInterface;
 use Drupal\Core\DependencyInjection\ServiceProviderInterface;
@@ -621,7 +622,7 @@ public function handle(Request $request, $type = self::MASTER_REQUEST, $catch =
       // installed yet (i.e., if no $databases array has been defined in the
       // settings.php file) and we are not already installing.
       if (!Database::getConnectionInfo() && !drupal_installation_attempted() && PHP_SAPI !== 'cli') {
-        $response = new RedirectResponse($request->getBasePath() . '/core/install.php');
+        $response = new RedirectResponse($request->getBasePath() . '/core/install.php', 302, ['Cache-Control' => 'no-cache']);
       }
       else {
         $this->boot();
@@ -665,9 +666,49 @@ protected function handleException(\Exception $e, $request, $type) {
       $response->headers->add($e->getHeaders());
       return $response;
     }
-    else {
-      throw $e;
+
+    if (PHP_SAPI !== 'cli' && $this->isNotInstalledException($e)) {
+      return new RedirectResponse($request->getBasePath() . '/core/install.php', 302, ['Cache-Control' => 'no-cache']);
     }
+
+    throw $e;
+  }
+
+  /**
+   * Determines if the exception is for a missing or not installed database.
+   *
+   * @param \Exception $e
+   *   The exception to check.
+   *
+   * @return bool
+   *   TRUE if the exception is for a missing or not fully installed database,
+   *   FALSE otherwise.
+   */
+  protected function isNotInstalledException(\Exception $e) {
+    if (!($e instanceof \PDOException || $e instanceof DatabaseException)) {
+      return FALSE;
+    }
+
+    // If we're already in the installer, don't worry about Drupal not being
+    // installed.
+    if (drupal_installation_attempted()) {
+      return FALSE;
+    }
+
+    // Code 1049 is "missing database".
+    if ($e->getCode() == 1049) {
+      return TRUE;
+    }
+
+    // SQLSTATE[42S02] indicates a missing table. Since we should only get here
+    // in case a bootstrap step failed, we assume that whatever table is missing
+    // is missing because the installation is broken, incomplete, or not even
+    // started.
+    if ($e->getCode() == 0 && strpos($e->getMessage(), 'SQLSTATE[42S02]') !== FALSE) {
+      return TRUE;
+    }
+
+    return FALSE;
   }
 
   /**
