diff --git a/core/core.services.yml b/core/core.services.yml
index 20e5da30d8..08b09d9953 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -552,7 +552,7 @@ services:
     class: Drupal\Core\Cache\MemoryCache\MemoryCache
   entity_type.manager:
     class: Drupal\Core\Entity\EntityTypeManager
-    arguments: ['@container.namespaces', '@module_handler', '@cache.discovery', '@string_translation', '@class_resolver']
+    arguments: ['@container.namespaces', '@module_handler', '@cache.discovery', '@string_translation', '@class_resolver', '@entity.last_installed_schema.repository']
     parent: container.trait
     tags:
       - { name: plugin_manager_cache_clear }
diff --git a/core/lib/Drupal/Core/Entity/EntityFieldManager.php b/core/lib/Drupal/Core/Entity/EntityFieldManager.php
index cad945cddf..1b4f8b9641 100644
--- a/core/lib/Drupal/Core/Entity/EntityFieldManager.php
+++ b/core/lib/Drupal/Core/Entity/EntityFieldManager.php
@@ -55,6 +55,16 @@ class EntityFieldManager implements EntityFieldManagerInterface {
    */
   protected $fieldStorageDefinitions;
 
+  /**
+   * Static cache of active field storage definitions per entity type.
+   *
+   * Elements of the array:
+   *  - $entity_type_id: \Drupal\Core\Field\BaseFieldDefinition[]
+   *
+   * @var array
+   */
+  protected $activeFieldStorageDefinitions;
+
   /**
    * An array keyed by entity type. Each value is an array whose keys are
    * field names and whose value is an array with two entries:
@@ -445,6 +455,18 @@ public function getFieldStorageDefinitions($entity_type_id) {
     return $this->fieldStorageDefinitions[$entity_type_id];
   }
 
+  public function getActiveFieldStorageDefinitions($entity_type_id) {
+    if (!isset($this->activeFieldStorageDefinitions[$entity_type_id])) {
+      $this->activeFieldStorageDefinitions[$entity_type_id] = $this->keyValueFactory->get('entity.definitions.installed')->get($entity_type_id . '.field_storage_definitions', []);
+    }
+    return $this->activeFieldStorageDefinitions[$entity_type_id] ?: $this->getFieldStorageDefinitions($entity_type_id);
+  }
+
+  public function setActiveFieldStorageDefinitions($entity_type_id, array $storage_definitions) {
+    $this->fieldStorageDefinitions[$entity_type_id] = $storage_definitions;
+    return $this;
+  }
+
   /**
    * {@inheritdoc}
    */
@@ -569,6 +591,7 @@ public function clearCachedFieldDefinitions() {
     $this->baseFieldDefinitions = [];
     $this->fieldDefinitions = [];
     $this->fieldStorageDefinitions = [];
+    $this->activeFieldStorageDefinitions = [];
     $this->fieldMap = [];
     $this->fieldMapByFieldType = [];
     $this->entityDisplayRepository->clearDisplayModeInfo();
@@ -588,6 +611,7 @@ public function useCaches($use_caches = FALSE) {
       $this->fieldDefinitions = [];
       $this->baseFieldDefinitions = [];
       $this->fieldStorageDefinitions = [];
+      $this->activeFieldStorageDefinitions = [];
     }
   }
 
diff --git a/core/lib/Drupal/Core/Entity/EntityFieldManagerInterface.php b/core/lib/Drupal/Core/Entity/EntityFieldManagerInterface.php
index 327d9e309f..914adc93aa 100644
--- a/core/lib/Drupal/Core/Entity/EntityFieldManagerInterface.php
+++ b/core/lib/Drupal/Core/Entity/EntityFieldManagerInterface.php
@@ -61,6 +61,30 @@ public function getFieldDefinitions($entity_type_id, $bundle);
    */
   public function getFieldStorageDefinitions($entity_type_id);
 
+  /**
+   * Gets the active field storage definitions for a content entity type.
+   *
+   * @param string $entity_type_id
+   *   The entity type ID. Only content entities are supported.
+   *
+   * @return \Drupal\Core\Field\FieldStorageDefinitionInterface[]
+   *   An array of field storage definitions that are active in the current
+   *   request, keyed by field name.
+   */
+  public function getActiveFieldStorageDefinitions($entity_type_id);
+
+  /**
+   * Sets the active field storage definitions for a content entity type.
+   *
+   * @param string $entity_type_id
+   *   The entity type ID.
+   * @param \Drupal\Core\Field\FieldStorageDefinitionInterface[] $storage_definitions
+   *   An array of field storage definitions.
+   *
+   * @return $this
+   */
+  public function setActiveFieldStorageDefinitions($entity_type_id, array $storage_definitions);
+
   /**
    * Gets a lightweight map of fields across bundles.
    *
diff --git a/core/lib/Drupal/Core/Entity/EntityManager.php b/core/lib/Drupal/Core/Entity/EntityManager.php
index e46d9f9f48..bbebdacab7 100644
--- a/core/lib/Drupal/Core/Entity/EntityManager.php
+++ b/core/lib/Drupal/Core/Entity/EntityManager.php
@@ -209,6 +209,14 @@ public function getFieldStorageDefinitions($entity_type_id) {
     return $this->container->get('entity_field.manager')->getFieldStorageDefinitions($entity_type_id);
   }
 
+  public function getActiveFieldStorageDefinitions($entity_type_id) {
+    return $this->container->get('entity_field.manager')->getActiveFieldStorageDefinitions($entity_type_id);
+  }
+
+  public function setActiveFieldStorageDefinitions($entity_type_id, array $storage_definitions) {
+    return $this->container->get('entity_field.manager')->setActiveFieldStorageDefinitions($entity_type_id, $storage_definitions);
+  }
+
   /**
    * {@inheritdoc}
    *
@@ -786,6 +794,14 @@ public function hasDefinition($plugin_id) {
     return $this->container->get('entity_type.manager')->hasDefinition($plugin_id);
   }
 
+  public function getActiveDefinition($entity_type_id) {
+    return $this->container->get('entity_type.manager')->getActiveDefinition($entity_type_id);
+  }
+
+  public function setActiveDefinition(EntityTypeInterface $entity_type) {
+    return $this->container->get('entity_type.manager')->setActiveDefinition($entity_type);
+  }
+
   /**
    * {@inheritdoc}
    *
diff --git a/core/lib/Drupal/Core/Entity/EntityTypeListener.php b/core/lib/Drupal/Core/Entity/EntityTypeListener.php
index a8c90c4861..0d6afef21d 100644
--- a/core/lib/Drupal/Core/Entity/EntityTypeListener.php
+++ b/core/lib/Drupal/Core/Entity/EntityTypeListener.php
@@ -64,6 +64,11 @@ public function __construct(EntityTypeManagerInterface $entity_type_manager, Ent
   public function onEntityTypeCreate(EntityTypeInterface $entity_type) {
     $entity_type_id = $entity_type->id();
 
+    $this->entityTypeManager->setActiveDefinition($entity_type);
+    if ($entity_type->entityClassImplements(FieldableEntityInterface::class)) {
+      $this->entityFieldManager->setActiveFieldStorageDefinitions($entity_type_id, $this->entityFieldManager->getFieldStorageDefinitions($entity_type_id));
+    }
+
     // @todo Forward this to all interested handlers, not only storage, once
     //   iterating handlers is possible: https://www.drupal.org/node/2332857.
     $storage = $this->entityTypeManager->getStorage($entity_type_id);
@@ -75,7 +80,7 @@ public function onEntityTypeCreate(EntityTypeInterface $entity_type) {
 
     $this->entityLastInstalledSchemaRepository->setLastInstalledDefinition($entity_type);
     if ($entity_type->entityClassImplements(FieldableEntityInterface::class)) {
-      $this->entityLastInstalledSchemaRepository->setLastInstalledFieldStorageDefinitions($entity_type_id, $this->entityFieldManager->getFieldStorageDefinitions($entity_type_id));
+      $this->entityLastInstalledSchemaRepository->setLastInstalledFieldStorageDefinitions($entity_type_id, $this->entityFieldManager->getActiveFieldStorageDefinitions($entity_type_id));
     }
   }
 
diff --git a/core/lib/Drupal/Core/Entity/EntityTypeManager.php b/core/lib/Drupal/Core/Entity/EntityTypeManager.php
index 9fecdb542a..be7960eee1 100644
--- a/core/lib/Drupal/Core/Entity/EntityTypeManager.php
+++ b/core/lib/Drupal/Core/Entity/EntityTypeManager.php
@@ -58,6 +58,20 @@ class EntityTypeManager extends DefaultPluginManager implements EntityTypeManage
    */
   protected $classResolver;
 
+  /**
+   * The entity last installed schema repository.
+   *
+   * @var \Drupal\Core\Entity\EntityLastInstalledSchemaRepositoryInterface
+   */
+  protected $entityLastInstalledSchemaRepository;
+
+  /**
+   * A list of entity type definitions that are active for the current request.
+   *
+   * @var \Drupal\Core\Entity\EntityTypeInterface[]
+   */
+  protected $activeDefinitions;
+
   /**
    * Constructs a new Entity plugin manager.
    *
@@ -72,8 +86,10 @@ class EntityTypeManager extends DefaultPluginManager implements EntityTypeManage
    *   The string translation.
    * @param \Drupal\Core\DependencyInjection\ClassResolverInterface $class_resolver
    *   The class resolver.
+   * @param \Drupal\Core\Entity\EntityLastInstalledSchemaRepositoryInterface $entity_last_installed_schema_repository
+   *   The entity last installed schema repository.
    */
-  public function __construct(\Traversable $namespaces, ModuleHandlerInterface $module_handler, CacheBackendInterface $cache, TranslationInterface $string_translation, ClassResolverInterface $class_resolver) {
+  public function __construct(\Traversable $namespaces, ModuleHandlerInterface $module_handler, CacheBackendInterface $cache, TranslationInterface $string_translation, ClassResolverInterface $class_resolver, EntityLastInstalledSchemaRepositoryInterface $entity_last_installed_schema_repository) {
     parent::__construct('Entity', $namespaces, $module_handler, 'Drupal\Core\Entity\EntityInterface');
 
     $this->setCacheBackend($cache, 'entity_type', ['entity_types']);
@@ -82,6 +98,7 @@ public function __construct(\Traversable $namespaces, ModuleHandlerInterface $mo
     $this->discovery = new AnnotatedClassDiscovery('Entity', $namespaces, 'Drupal\Core\Entity\Annotation\EntityType');
     $this->stringTranslation = $string_translation;
     $this->classResolver = $class_resolver;
+    $this->entityLastInstalledSchemaRepository = $entity_last_installed_schema_repository;
   }
 
   /**
@@ -133,11 +150,25 @@ public function getDefinition($entity_type_id, $exception_on_invalid = TRUE) {
     throw new PluginNotFoundException($entity_type_id, sprintf('The "%s" entity type does not exist.', $entity_type_id));
   }
 
+  public function getActiveDefinition($entity_type_id) {
+    if (!isset($this->activeDefinitions[$entity_type_id])) {
+      $this->activeDefinitions[$entity_type_id] = $this->entityLastInstalledSchemaRepository->getLastInstalledDefinition($entity_type_id);
+    }
+
+    return $this->activeDefinitions[$entity_type_id] ?: $this->getDefinition($entity_type_id);
+  }
+
+  public function setActiveDefinition(EntityTypeInterface $entity_type) {
+    $this->activeDefinitions[$entity_type->id()] = $entity_type;
+    return $this;
+  }
+
   /**
    * {@inheritdoc}
    */
   public function clearCachedDefinitions() {
     parent::clearCachedDefinitions();
+    $this->activeDefinitions = [];
     $this->handlers = [];
   }
 
diff --git a/core/lib/Drupal/Core/Entity/EntityTypeManagerInterface.php b/core/lib/Drupal/Core/Entity/EntityTypeManagerInterface.php
index 4a5ec77745..521f44e93a 100644
--- a/core/lib/Drupal/Core/Entity/EntityTypeManagerInterface.php
+++ b/core/lib/Drupal/Core/Entity/EntityTypeManagerInterface.php
@@ -148,4 +148,18 @@ public function getDefinition($entity_type_id, $exception_on_invalid = TRUE);
    */
   public function getDefinitions();
 
+  /**
+   * @param $entity_type_id
+   *
+   * @return \Drupal\Core\Entity\EntityTypeInterface
+   */
+  public function getActiveDefinition($entity_type_id);
+
+  /**
+   * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
+   *
+   * @return $this
+   */
+  public function setActiveDefinition(EntityTypeInterface $entity_type);
+
 }
diff --git a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
index 2f770aede1..47131cee2b 100644
--- a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
+++ b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
@@ -207,6 +207,8 @@ public function __construct(EntityTypeInterface $entity_type, Connection $databa
     }
     $this->entityTypeManager = $entity_type_manager;
 
+    $this->entityType = $this->entityTypeManager->getActiveDefinition($entity_type->id());
+
     $this->initTableLayout();
   }
 
@@ -357,7 +359,7 @@ public function getTableMapping(array $storage_definitions = NULL) {
     // If we are using our internal storage definitions, which is our main use
     // case, we can statically cache the computed table mapping.
     if (!isset($this->tableMapping)) {
-      $storage_definitions = $this->entityFieldManager->getFieldStorageDefinitions($this->entityTypeId);
+      $storage_definitions = $this->entityFieldManager->getActiveFieldStorageDefinitions($this->entityTypeId);
 
       $this->tableMapping = $this->getCustomTableMapping($this->entityType, $storage_definitions);
     }
@@ -463,7 +465,7 @@ protected function mapFromStorageRecords(array $records, $load_from_revision = F
       $field_names = array_unique(array_merge($field_names, $this->tableMapping->getFieldNames($this->revisionTable)));
     }
 
-    $storage_definitions = $this->entityFieldManager->getFieldStorageDefinitions($this->entityTypeId);
+    $storage_definitions = $this->entityFieldManager->getActiveFieldStorageDefinitions($this->entityTypeId);
     $values = [];
     foreach ($records as $id => $record) {
       $values[$id] = [];
@@ -582,7 +584,7 @@ protected function loadFromSharedTables(array &$values, array &$translations, $l
         $all_fields = $table_mapping->getFieldNames($this->dataTable);
       }
 
-      $storage_definitions = $this->entityFieldManager->getFieldStorageDefinitions($this->entityTypeId);
+      $storage_definitions = $this->entityFieldManager->getActiveFieldStorageDefinitions($this->entityTypeId);
       $result = $query->execute();
       foreach ($result as $row) {
         $id = $row[$record_key];
@@ -898,7 +900,7 @@ protected function doSaveFieldItems(ContentEntityInterface $entity, array $names
     }
     else {
       $table_mapping = $this->getTableMapping();
-      $storage_definitions = $this->entityFieldManager->getFieldStorageDefinitions($this->entityTypeId);
+      $storage_definitions = $this->entityFieldManager->getActiveFieldStorageDefinitions($this->entityTypeId);
       $shared_table_fields = FALSE;
       $dedicated_table_fields = [];
 
@@ -1554,10 +1556,7 @@ public function onFieldStorageDefinitionUpdate(FieldStorageDefinitionInterface $
    * {@inheritdoc}
    */
   public function onFieldStorageDefinitionDelete(FieldStorageDefinitionInterface $storage_definition) {
-    $table_mapping = $this->getTableMapping(
-      $this->entityLastInstalledSchemaRepository->getLastInstalledFieldStorageDefinitions($this->entityType->id())
-    );
-
+    $table_mapping = $this->getTableMapping();
     if ($table_mapping->requiresDedicatedTableStorage($storage_definition)) {
       // Mark all data associated with the field for deletion.
       $table = $table_mapping->getDedicatedDataTableName($storage_definition);
@@ -1733,7 +1732,7 @@ public function countFieldData($storage_definition, $as_bool = FALSE) {
     // storage definition is added, so bypass the internal storage definitions
     // and fetch the table mapping using the passed in storage definition.
     // @todo Fix this in https://www.drupal.org/node/2705205.
-    $storage_definitions = $this->entityFieldManager->getFieldStorageDefinitions($this->entityTypeId);
+    $storage_definitions = $this->entityFieldManager->getActiveFieldStorageDefinitions($this->entityTypeId);
     $storage_definitions[$storage_definition->getName()] = $storage_definition;
     $table_mapping = $this->getTableMapping($storage_definitions);
 
diff --git a/core/lib/Drupal/Core/Field/FieldStorageDefinitionListener.php b/core/lib/Drupal/Core/Field/FieldStorageDefinitionListener.php
index e67629b759..3c2f5e4237 100644
--- a/core/lib/Drupal/Core/Field/FieldStorageDefinitionListener.php
+++ b/core/lib/Drupal/Core/Field/FieldStorageDefinitionListener.php
@@ -2,12 +2,10 @@
 
 namespace Drupal\Core\Field;
 
-use Drupal\Core\Database\DatabaseExceptionWrapper;
 use Drupal\Core\Entity\EntityLastInstalledSchemaRepositoryInterface;
 use Drupal\Core\Entity\EntityFieldManagerInterface;
 use Drupal\Core\Entity\EntityTypeManagerInterface;
 use Drupal\Core\Entity\FieldableEntityStorageInterface;
-use Drupal\Core\Entity\Sql\SqlContentEntityStorage;
 use Symfony\Component\EventDispatcher\EventDispatcherInterface;
 
 /**
@@ -80,19 +78,13 @@ public function __construct(EntityTypeManagerInterface $entity_type_manager, Eve
   public function onFieldStorageDefinitionCreate(FieldStorageDefinitionInterface $storage_definition) {
     $entity_type_id = $storage_definition->getTargetEntityTypeId();
 
+    $active_field_storage_definitions = $this->entityFieldManager->getActiveFieldStorageDefinitions($entity_type_id);
+    $active_field_storage_definitions[$storage_definition->getName()] = $storage_definition;
+    $this->entityFieldManager->setActiveFieldStorageDefinitions($entity_type_id, $active_field_storage_definitions);
+
     // @todo Forward this to all interested handlers, not only storage, once
     //   iterating handlers is possible: https://www.drupal.org/node/2332857.
-    $storage = clone $this->entityTypeManager->getStorage($entity_type_id);
-
-    // Entity type definition updates can change the schema by adding or
-    // removing entity tables (for example when switching an entity type from
-    // non-revisionable to revisionable), so CRUD operations on a field storage
-    // definition need to use the last installed entity type schema.
-    if ($storage instanceof SqlContentEntityStorage
-       && ($last_installed_entity_type = $this->entityLastInstalledSchemaRepository->getLastInstalledDefinition($entity_type_id))) {
-      $storage->setEntityType($last_installed_entity_type);
-    }
-
+    $storage = $this->entityTypeManager->getStorage($entity_type_id);
     if ($storage instanceof FieldStorageDefinitionListenerInterface) {
       $storage->onFieldStorageDefinitionCreate($storage_definition);
     }
@@ -109,19 +101,13 @@ public function onFieldStorageDefinitionCreate(FieldStorageDefinitionInterface $
   public function onFieldStorageDefinitionUpdate(FieldStorageDefinitionInterface $storage_definition, FieldStorageDefinitionInterface $original) {
     $entity_type_id = $storage_definition->getTargetEntityTypeId();
 
+    $active_field_storage_definitions = $this->entityFieldManager->getActiveFieldStorageDefinitions($entity_type_id);
+    $active_field_storage_definitions[$storage_definition->getName()] = $storage_definition;
+    $this->entityFieldManager->setActiveFieldStorageDefinitions($entity_type_id, $active_field_storage_definitions);
+
     // @todo Forward this to all interested handlers, not only storage, once
     //   iterating handlers is possible: https://www.drupal.org/node/2332857.
-    $storage = clone $this->entityTypeManager->getStorage($entity_type_id);
-
-    // Entity type definition updates can change the schema by adding or
-    // removing entity tables (for example when switching an entity type from
-    // non-revisionable to revisionable), so CRUD operations on a field storage
-    // definition need to use the last installed entity type schema.
-    if ($storage instanceof SqlContentEntityStorage
-       && ($last_installed_entity_type = $this->entityLastInstalledSchemaRepository->getLastInstalledDefinition($entity_type_id))) {
-      $storage->setEntityType($last_installed_entity_type);
-    }
-
+    $storage = $this->entityTypeManager->getStorage($entity_type_id);
     if ($storage instanceof FieldStorageDefinitionListenerInterface) {
       $storage->onFieldStorageDefinitionUpdate($storage_definition, $original);
     }
@@ -140,32 +126,15 @@ public function onFieldStorageDefinitionDelete(FieldStorageDefinitionInterface $
 
     // @todo Forward this to all interested handlers, not only storage, once
     //   iterating handlers is possible: https://www.drupal.org/node/2332857.
-    $storage = clone $this->entityTypeManager->getStorage($entity_type_id);
-
-    // Entity type definition updates can change the schema by adding or
-    // removing entity tables (for example when switching an entity type from
-    // non-revisionable to revisionable), so CRUD operations on a field storage
-    // definition need to use the last installed entity type schema.
-    if ($storage instanceof SqlContentEntityStorage
-       && ($last_installed_entity_type = $this->entityLastInstalledSchemaRepository->getLastInstalledDefinition($entity_type_id))) {
-      $storage->setEntityType($last_installed_entity_type);
-    }
+    $storage = $this->entityTypeManager->getStorage($entity_type_id);
 
     // Keep the field definition in the deleted fields repository so we can use
     // it later during field_purge_batch(), but only if the field has data.
-    try {
-      if ($storage_definition instanceof BaseFieldDefinition && $storage instanceof FieldableEntityStorageInterface && $storage->countFieldData($storage_definition, TRUE)) {
-        $deleted_storage_definition = clone $storage_definition;
-        $deleted_storage_definition->setDeleted(TRUE);
-        $this->deletedFieldsRepository->addFieldDefinition($deleted_storage_definition);
-        $this->deletedFieldsRepository->addFieldStorageDefinition($deleted_storage_definition);
-      }
-    }
-    catch (DatabaseExceptionWrapper $e) {
-      // This may happen when changing field storage schema, since we are not
-      // able to use a table mapping matching the passed storage definition.
-      // @todo Revisit this once we are able to instantiate the table mapping
-      //   properly. See https://www.drupal.org/node/2274017.
+    if ($storage_definition instanceof BaseFieldDefinition && $storage instanceof FieldableEntityStorageInterface && $storage->countFieldData($storage_definition, TRUE)) {
+      $deleted_storage_definition = clone $storage_definition;
+      $deleted_storage_definition->setDeleted(TRUE);
+      $this->deletedFieldsRepository->addFieldDefinition($deleted_storage_definition);
+      $this->deletedFieldsRepository->addFieldStorageDefinition($deleted_storage_definition);
     }
 
     if ($storage instanceof FieldStorageDefinitionListenerInterface) {
diff --git a/core/tests/Drupal/KernelTests/Core/Entity/FieldableEntityDefinitionUpdateTest.php b/core/tests/Drupal/KernelTests/Core/Entity/FieldableEntityDefinitionUpdateTest.php
index bff60a78f9..e157573e0f 100644
--- a/core/tests/Drupal/KernelTests/Core/Entity/FieldableEntityDefinitionUpdateTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Entity/FieldableEntityDefinitionUpdateTest.php
@@ -144,6 +144,10 @@ public function testFieldableEntityTypeUpdates($initial_rev, $initial_mul, $new_
       $this->setExpectedException(EntityStorageException::class, 'Converting an entity type from revisionable to non-revisionable or from translatable to non-translatable is not supported.');
     }
 
+    if ($data_migration_supported) {
+      $this->assertEntityData($initial_rev, $initial_mul);
+    }
+
     // Simulate a batch run since we are converting the entities one by one.
     $sandbox = [];
     do {
