diff --git a/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php b/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php
index 0040ae076a..9d622ddcda 100644
--- a/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php
+++ b/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php
@@ -23,6 +23,20 @@
    */
   protected $deprecatedProperties = ['entityManager' => 'entity.manager'];
 
+  /**
+   * Information about the entity type.
+   *
+   * @var \Drupal\Core\Entity\ContentEntityTypeInterface
+   */
+  protected $entityType;
+
+  /**
+   * The entity type's field storage definitions.
+   *
+   * @var \Drupal\Core\Field\FieldStorageDefinitionInterface[]
+   */
+  protected $fieldStorageDefinitions;
+
   /**
    * The entity bundle key.
    *
@@ -44,6 +58,13 @@
    */
   protected $entityTypeBundleInfo;
 
+  /**
+   * The entity last installed schema repository.
+   *
+   * @var \Drupal\Core\Entity\EntityLastInstalledSchemaRepositoryInterface
+   */
+  protected $entityLastInstalledSchemaRepository;
+
   /**
    * Cache backend.
    *
@@ -71,8 +92,10 @@
    *   The memory cache backend.
    * @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entity_type_bundle_info
    *   The entity type bundle info.
+   * @param \Drupal\Core\Entity\EntityLastInstalledSchemaRepositoryInterface $entity_last_installed_schema_repository
+   *   The entity last installed schema repository.
    */
-  public function __construct(EntityTypeInterface $entity_type, EntityFieldManagerInterface $entity_field_manager, CacheBackendInterface $cache, MemoryCacheInterface $memory_cache = NULL, EntityTypeBundleInfoInterface $entity_type_bundle_info = NULL) {
+  public function __construct(EntityTypeInterface $entity_type, EntityFieldManagerInterface $entity_field_manager, CacheBackendInterface $cache, MemoryCacheInterface $memory_cache = NULL, EntityTypeBundleInfoInterface $entity_type_bundle_info = NULL, EntityLastInstalledSchemaRepositoryInterface $entity_last_installed_schema_repository = NULL) {
     parent::__construct($entity_type, $memory_cache);
     $this->bundleKey = $this->entityType->getKey('bundle');
     $this->entityFieldManager = $entity_field_manager;
@@ -82,6 +105,16 @@ public function __construct(EntityTypeInterface $entity_type, EntityFieldManager
       $entity_type_bundle_info = \Drupal::service('entity_type.bundle.info');
     }
     $this->entityTypeBundleInfo = $entity_type_bundle_info;
+    if (!$entity_last_installed_schema_repository) {
+      @trigger_error('Calling ContentEntityStorageBase::__construct() with the $entity_last_installed_schema_repository argument is supported in drupal:8.7.0 and will be required before drupal:9.0.0. See https://www.drupal.org/node/2549139.', E_USER_DEPRECATED);
+      $entity_last_installed_schema_repository = \Drupal::service('entity.last_installed_schema.repository');
+    }
+    $this->entityLastInstalledSchemaRepository = $entity_last_installed_schema_repository;
+
+    if ($last_installed_entity_type = $entity_last_installed_schema_repository->getLastInstalledDefinition($this->entityTypeId)) {
+      $this->entityType = $last_installed_entity_type;
+    }
+    $this->fieldStorageDefinitions = $entity_last_installed_schema_repository->getLastInstalledFieldStorageDefinitions($this->entityTypeId);
   }
 
   /**
@@ -93,10 +126,46 @@ public static function createInstance(ContainerInterface $container, EntityTypeI
       $container->get('entity_field.manager'),
       $container->get('cache.entity'),
       $container->get('entity.memory_cache'),
-      $container->get('entity_type.bundle.info')
+      $container->get('entity_type.bundle.info'),
+      $container->get('entity.last_installed_schema.repository')
     );
   }
 
+  /**
+   * Updates the wrapped entity type definition.
+   *
+   * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
+   *   The update entity type.
+   *
+   * @internal Only to be used internally by Entity API.
+   */
+  public function setEntityType(EntityTypeInterface $entity_type) {
+    if ($this->entityType->id() == $entity_type->id()) {
+      $this->entityType = $entity_type;
+    }
+    else {
+      throw new EntityStorageException("Unsupported entity type {$entity_type->id()}");
+    }
+  }
+
+  /**
+   * Updates the internal list of field storage definitions.
+   *
+   * @param \Drupal\Core\Field\FieldStorageDefinitionInterface[] $field_storage_definitions
+   *   An array of field storage definitions.
+   *
+   * @internal Only to be used internally by Entity API.
+   */
+  public function setFieldStorageDefinitions(array $field_storage_definitions) {
+    foreach ($field_storage_definitions as $field_storage_definition) {
+      if ($field_storage_definition->getTargetEntityTypeId() !== $this->entityType->id()) {
+        throw new EntityStorageException("Unsupported entity type {$field_storage_definition->getTargetEntityTypeId()}");
+      }
+    }
+
+    $this->fieldStorageDefinitions = $field_storage_definitions;
+  }
+
   /**
    * {@inheritdoc}
    */
@@ -985,7 +1054,7 @@ protected function populateAffectedRevisionTranslations(ContentEntityInterface $
    *   The sanitized list of entity key values.
    */
   protected function cleanIds(array $ids, $entity_key = 'id') {
-    $definitions = $this->entityFieldManager->getBaseFieldDefinitions($this->entityTypeId);
+    $definitions = $this->fieldStorageDefinitions;
     $field_name = $this->entityType->getKey($entity_key);
     if ($field_name && $definitions[$field_name]->getType() == 'integer') {
       $ids = array_filter($ids, function ($id) {
diff --git a/core/lib/Drupal/Core/Entity/EntityDefinitionUpdateManager.php b/core/lib/Drupal/Core/Entity/EntityDefinitionUpdateManager.php
index 5baf85fd1f..58aede1920 100644
--- a/core/lib/Drupal/Core/Entity/EntityDefinitionUpdateManager.php
+++ b/core/lib/Drupal/Core/Entity/EntityDefinitionUpdateManager.php
@@ -227,6 +227,7 @@ public function updateFieldableEntityType(EntityTypeInterface $entity_type, arra
 
     $original_field_storage_definitions = $this->entityLastInstalledSchemaRepository->getLastInstalledFieldStorageDefinitions($entity_type->id());
     $this->entityTypeListener->onFieldableEntityTypeUpdate($entity_type, $original, $field_storage_definitions, $original_field_storage_definitions, $sandbox);
+    $this->clearCachedDefinitions();
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Entity/EntityTypeListener.php b/core/lib/Drupal/Core/Entity/EntityTypeListener.php
index a8c90c4861..2333a00d9e 100644
--- a/core/lib/Drupal/Core/Entity/EntityTypeListener.php
+++ b/core/lib/Drupal/Core/Entity/EntityTypeListener.php
@@ -77,6 +77,7 @@ public function onEntityTypeCreate(EntityTypeInterface $entity_type) {
     if ($entity_type->entityClassImplements(FieldableEntityInterface::class)) {
       $this->entityLastInstalledSchemaRepository->setLastInstalledFieldStorageDefinitions($entity_type_id, $this->entityFieldManager->getFieldStorageDefinitions($entity_type_id));
     }
+    $this->entityTypeManager->clearCachedDefinitions();
   }
 
   /**
@@ -95,6 +96,7 @@ public function onEntityTypeUpdate(EntityTypeInterface $entity_type, EntityTypeI
     $this->eventDispatcher->dispatch(EntityTypeEvents::UPDATE, new EntityTypeEvent($entity_type, $original));
 
     $this->entityLastInstalledSchemaRepository->setLastInstalledDefinition($entity_type);
+    $this->entityTypeManager->clearCachedDefinitions();
   }
 
   /**
@@ -113,6 +115,7 @@ public function onEntityTypeDelete(EntityTypeInterface $entity_type) {
     $this->eventDispatcher->dispatch(EntityTypeEvents::DELETE, new EntityTypeEvent($entity_type));
 
     $this->entityLastInstalledSchemaRepository->deleteLastInstalledDefinition($entity_type_id);
+    $this->entityTypeManager->clearCachedDefinitions();
   }
 
   /**
@@ -135,6 +138,7 @@ public function onFieldableEntityTypeUpdate(EntityTypeInterface $entity_type, En
       if ($entity_type->entityClassImplements(FieldableEntityInterface::class)) {
         $this->entityLastInstalledSchemaRepository->setLastInstalledFieldStorageDefinitions($entity_type_id, $field_storage_definitions);
       }
+      $this->entityTypeManager->clearCachedDefinitions();
     }
   }
 
diff --git a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
index 2f770aede1..55c23c5e64 100644
--- a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
+++ b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
@@ -193,7 +193,7 @@ public function getFieldStorageDefinitions() {
    *   The entity last installed schema repository.
    */
   public function __construct(EntityTypeInterface $entity_type, Connection $database, EntityFieldManagerInterface $entity_field_manager, CacheBackendInterface $cache, LanguageManagerInterface $language_manager, MemoryCacheInterface $memory_cache = NULL, EntityTypeBundleInfoInterface $entity_type_bundle_info = NULL, EntityTypeManagerInterface $entity_type_manager = NULL, EntityLastInstalledSchemaRepositoryInterface $entity_last_installed_schema_repository = NULL) {
-    parent::__construct($entity_type, $entity_field_manager, $cache, $memory_cache, $entity_type_bundle_info);
+    parent::__construct($entity_type, $entity_field_manager, $cache, $memory_cache, $entity_type_bundle_info, $entity_last_installed_schema_repository);
     $this->database = $database;
     $this->languageManager = $language_manager;
     if (!$entity_last_installed_schema_repository) {
@@ -295,22 +295,19 @@ protected function getStorageSchema() {
   }
 
   /**
-   * Updates the wrapped entity type definition.
-   *
-   * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
-   *   The update entity type.
-   *
-   * @internal Only to be used internally by Entity API. Expected to be
-   *   removed by https://www.drupal.org/node/2274017.
+   * {@inheritdoc}
    */
   public function setEntityType(EntityTypeInterface $entity_type) {
-    if ($this->entityType->id() == $entity_type->id()) {
-      $this->entityType = $entity_type;
-      $this->initTableLayout();
-    }
-    else {
-      throw new EntityStorageException("Unsupported entity type {$entity_type->id()}");
-    }
+    parent::setEntityType($entity_type);
+    $this->initTableLayout();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setFieldStorageDefinitions(array $field_storage_definitions) {
+    parent::setFieldStorageDefinitions($field_storage_definitions);
+    $this->initTableLayout();
   }
 
   /**
@@ -357,9 +354,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);
-
-      $this->tableMapping = $this->getCustomTableMapping($this->entityType, $storage_definitions);
+      $this->tableMapping = $this->getCustomTableMapping($this->entityType, $this->fieldStorageDefinitions);
     }
 
     return $this->tableMapping;
@@ -463,7 +458,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->fieldStorageDefinitions;
     $values = [];
     foreach ($records as $id => $record) {
       $values[$id] = [];
@@ -582,7 +577,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->fieldStorageDefinitions;
       $result = $query->execute();
       foreach ($result as $row) {
         $id = $row[$record_key];
@@ -898,7 +893,7 @@ protected function doSaveFieldItems(ContentEntityInterface $entity, array $names
     }
     else {
       $table_mapping = $this->getTableMapping();
-      $storage_definitions = $this->entityFieldManager->getFieldStorageDefinitions($this->entityTypeId);
+      $storage_definitions = $this->fieldStorageDefinitions;
       $shared_table_fields = FALSE;
       $dedicated_table_fields = [];
 
@@ -1059,10 +1054,10 @@ protected function mapToStorageRecord(ContentEntityInterface $entity, $table_nam
     $table_mapping = $this->getTableMapping();
     foreach ($table_mapping->getFieldNames($table_name) as $field_name) {
 
-      if (empty($this->getFieldStorageDefinitions()[$field_name])) {
+      if (empty($this->fieldStorageDefinitions[$field_name])) {
         throw new EntityStorageException("Table mapping contains invalid field $field_name.");
       }
-      $definition = $this->getFieldStorageDefinitions()[$field_name];
+      $definition = $this->fieldStorageDefinitions[$field_name];
       $columns = $table_mapping->getColumnNames($field_name);
 
       foreach ($columns as $column_name => $schema_name) {
@@ -1229,9 +1224,11 @@ protected function loadFromDedicatedTables(array &$values, $load_from_revision)
     foreach ($bundles as $bundle => $v) {
       $definitions[$bundle] = $this->entityFieldManager->getFieldDefinitions($this->entityTypeId, $bundle);
       foreach ($definitions[$bundle] as $field_name => $field_definition) {
-        $storage_definition = $field_definition->getFieldStorageDefinition();
-        if ($table_mapping->requiresDedicatedTableStorage($storage_definition)) {
-          $storage_definitions[$field_name] = $storage_definition;
+        if (isset($this->fieldStorageDefinitions[$field_name])) {
+          $storage_definition = $this->fieldStorageDefinitions[$field_name];
+          if ($table_mapping->requiresDedicatedTableStorage($storage_definition)) {
+            $storage_definitions[$field_name] = $storage_definition;
+          }
         }
       }
     }
@@ -1321,7 +1318,11 @@ protected function saveToDedicatedTables(ContentEntityInterface $entity, $update
     }
 
     foreach ($definitions as $field_name => $field_definition) {
-      $storage_definition = $field_definition->getFieldStorageDefinition();
+      if (!isset($this->fieldStorageDefinitions[$field_name])) {
+        continue;
+      }
+
+      $storage_definition = $this->fieldStorageDefinitions[$field_name];
       if (!$table_mapping->requiresDedicatedTableStorage($storage_definition)) {
         continue;
       }
@@ -1420,8 +1421,7 @@ protected function saveToDedicatedTables(ContentEntityInterface $entity, $update
    */
   protected function deleteFromDedicatedTables(ContentEntityInterface $entity) {
     $table_mapping = $this->getTableMapping();
-    foreach ($this->entityFieldManager->getFieldDefinitions($entity->getEntityTypeId(), $entity->bundle()) as $field_definition) {
-      $storage_definition = $field_definition->getFieldStorageDefinition();
+    foreach ($this->fieldStorageDefinitions as $storage_definition) {
       if (!$table_mapping->requiresDedicatedTableStorage($storage_definition)) {
         continue;
       }
@@ -1448,8 +1448,7 @@ protected function deleteRevisionFromDedicatedTables(ContentEntityInterface $ent
     $vid = $entity->getRevisionId();
     if (isset($vid)) {
       $table_mapping = $this->getTableMapping();
-      foreach ($this->entityFieldManager->getFieldDefinitions($entity->getEntityTypeId(), $entity->bundle()) as $field_definition) {
-        $storage_definition = $field_definition->getFieldStorageDefinition();
+      foreach ($this->fieldStorageDefinitions as $storage_definition) {
         if (!$table_mapping->requiresDedicatedTableStorage($storage_definition)) {
           continue;
         }
@@ -1494,6 +1493,11 @@ public function requiresFieldDataMigration(FieldStorageDefinitionInterface $stor
    * {@inheritdoc}
    */
   public function onEntityTypeCreate(EntityTypeInterface $entity_type) {
+    // Ensure we have an updated entity type and field storage definitions.
+    $this->entityType = $entity_type;
+    $this->fieldStorageDefinitions = $this->entityFieldManager->getFieldStorageDefinitions($entity_type->id());
+    $this->initTableLayout();
+
     $this->wrapSchemaException(function () use ($entity_type) {
       $this->getStorageSchema()->onEntityTypeCreate($entity_type);
     });
@@ -1527,6 +1531,9 @@ public function onEntityTypeDelete(EntityTypeInterface $entity_type) {
    * {@inheritdoc}
    */
   public function onFieldableEntityTypeUpdate(EntityTypeInterface $entity_type, EntityTypeInterface $original, array $field_storage_definitions, array $original_field_storage_definitions, array &$sandbox = NULL) {
+    $this->entityType = $entity_type;
+    $this->fieldStorageDefinitions = $field_storage_definitions;
+    $this->initTableLayout();
     $this->wrapSchemaException(function () use ($entity_type, $original, $field_storage_definitions, $original_field_storage_definitions, &$sandbox) {
       $this->getStorageSchema()->onFieldableEntityTypeUpdate($entity_type, $original, $field_storage_definitions, $original_field_storage_definitions, $sandbox);
     });
@@ -1554,9 +1561,8 @@ public function onFieldStorageDefinitionUpdate(FieldStorageDefinitionInterface $
    * {@inheritdoc}
    */
   public function onFieldStorageDefinitionDelete(FieldStorageDefinitionInterface $storage_definition) {
-    $table_mapping = $this->getTableMapping(
-      $this->entityLastInstalledSchemaRepository->getLastInstalledFieldStorageDefinitions($this->entityType->id())
-    );
+    $this->fieldStorageDefinitions[$storage_definition->getName()] = $storage_definition;
+    $table_mapping = $this->getTableMapping($this->fieldStorageDefinitions);
 
     if ($table_mapping->requiresDedicatedTableStorage($storage_definition)) {
       // Mark all data associated with the field for deletion.
@@ -1733,7 +1739,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->fieldStorageDefinitions;
     $storage_definitions[$storage_definition->getName()] = $storage_definition;
     $table_mapping = $this->getTableMapping($storage_definitions);
 
diff --git a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php
index 1459f01c05..d44199bdae 100644
--- a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php
+++ b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php
@@ -462,6 +462,8 @@ protected function preUpdateEntityTypeSchema(EntityTypeInterface $entity_type, E
     $original_table_mapping = $original_storage->getCustomTableMapping($original, $original_field_storage_definitions);
     $original_storage->setTableMapping($original_table_mapping);
 
+    $sandbox['temporary_table_mapping'] = $temporary_table_mapping;
+    $sandbox['original_table_mapping'] = $original_table_mapping;
     $sandbox['new_table_mapping'] = $temporary_storage->getCustomTableMapping($entity_type, $field_storage_definitions);
     $sandbox['backup_table_mapping'] = $original_storage->getCustomTableMapping($original, $original_field_storage_definitions, 'old_');
 
@@ -498,9 +500,9 @@ protected function preUpdateEntityTypeSchema(EntityTypeInterface $entity_type, E
    */
   protected function postUpdateEntityTypeSchema(EntityTypeInterface $entity_type, EntityTypeInterface $original, array $field_storage_definitions, array $original_field_storage_definitions, array &$sandbox = NULL) {
     /** @var \Drupal\Core\Entity\Sql\TableMappingInterface $temporary_table_mapping */
-    $temporary_table_mapping = $sandbox['temporary_storage']->getTableMapping();
+    $temporary_table_mapping = $sandbox['temporary_table_mapping'];
     /** @var \Drupal\Core\Entity\Sql\TableMappingInterface $original_table_mapping */
-    $original_table_mapping = $sandbox['original_storage']->getTableMapping();
+    $original_table_mapping = $sandbox['original_table_mapping'];
     /** @var \Drupal\Core\Entity\Sql\TableMappingInterface $new_table_mapping */
     $new_table_mapping = $sandbox['new_table_mapping'];
     /** @var \Drupal\Core\Entity\Sql\TableMappingInterface $backup_table_mapping */
@@ -625,6 +627,7 @@ public function onFieldStorageDefinitionCreate(FieldStorageDefinitionInterface $
    * {@inheritdoc}
    */
   public function onFieldStorageDefinitionUpdate(FieldStorageDefinitionInterface $storage_definition, FieldStorageDefinitionInterface $original) {
+    $this->fieldStorageDefinitions[$storage_definition->getName()] = $storage_definition;
     $this->performFieldSchemaOperation('update', $storage_definition, $original);
   }
 
diff --git a/core/lib/Drupal/Core/Entity/Sql/SqlFieldableEntityTypeListenerTrait.php b/core/lib/Drupal/Core/Entity/Sql/SqlFieldableEntityTypeListenerTrait.php
index 4b31a185c5..e1e9e986f3 100644
--- a/core/lib/Drupal/Core/Entity/Sql/SqlFieldableEntityTypeListenerTrait.php
+++ b/core/lib/Drupal/Core/Entity/Sql/SqlFieldableEntityTypeListenerTrait.php
@@ -58,8 +58,12 @@ public function onFieldableEntityTypeUpdate(EntityTypeInterface $entity_type, En
         throw new EntityStorageException('Missing revision_translation_affected field.');
       }
 
+      $temporary_storage = $this->entityTypeManager->createHandlerInstance($entity_type->getStorageClass(), $entity_type);
+      $temporary_storage->setEntityType($entity_type);
+      $temporary_storage->setFieldStorageDefinitions($field_storage_definitions);
+
       $sandbox['original_storage'] = $original_storage;
-      $sandbox['temporary_storage'] = $this->entityTypeManager->createHandlerInstance($entity_type->getStorageClass(), $entity_type);
+      $sandbox['temporary_storage'] = $temporary_storage;
 
       $this->preUpdateEntityTypeSchema($entity_type, $original, $field_storage_definitions, $original_field_storage_definitions, $sandbox);
     }
diff --git a/core/lib/Drupal/Core/Field/FieldStorageDefinitionListener.php b/core/lib/Drupal/Core/Field/FieldStorageDefinitionListener.php
index e67629b759..3b7bb43bc1 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;
 
 /**
@@ -82,17 +80,7 @@ public function onFieldStorageDefinitionCreate(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);
     if ($storage instanceof FieldStorageDefinitionListenerInterface) {
       $storage->onFieldStorageDefinitionCreate($storage_definition);
     }
@@ -101,6 +89,7 @@ public function onFieldStorageDefinitionCreate(FieldStorageDefinitionInterface $
 
     $this->entityLastInstalledSchemaRepository->setLastInstalledFieldStorageDefinition($storage_definition);
     $this->entityFieldManager->clearCachedFieldDefinitions();
+    $this->entityTypeManager->clearCachedDefinitions();
   }
 
   /**
@@ -111,17 +100,7 @@ public function onFieldStorageDefinitionUpdate(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);
     if ($storage instanceof FieldStorageDefinitionListenerInterface) {
       $storage->onFieldStorageDefinitionUpdate($storage_definition, $original);
     }
@@ -130,6 +109,7 @@ public function onFieldStorageDefinitionUpdate(FieldStorageDefinitionInterface $
 
     $this->entityLastInstalledSchemaRepository->setLastInstalledFieldStorageDefinition($storage_definition);
     $this->entityFieldManager->clearCachedFieldDefinitions();
+    $this->entityTypeManager->clearCachedDefinitions();
   }
 
   /**
@@ -140,32 +120,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) {
@@ -176,6 +139,7 @@ public function onFieldStorageDefinitionDelete(FieldStorageDefinitionInterface $
 
     $this->entityLastInstalledSchemaRepository->deleteLastInstalledFieldStorageDefinition($storage_definition);
     $this->entityFieldManager->clearCachedFieldDefinitions();
+    $this->entityTypeManager->clearCachedDefinitions();
   }
 
 }
diff --git a/core/modules/content_moderation/tests/src/Kernel/ContentModerationStateTest.php b/core/modules/content_moderation/tests/src/Kernel/ContentModerationStateTest.php
index eaa4ad64d9..55b86c8978 100644
--- a/core/modules/content_moderation/tests/src/Kernel/ContentModerationStateTest.php
+++ b/core/modules/content_moderation/tests/src/Kernel/ContentModerationStateTest.php
@@ -13,7 +13,6 @@
 use Drupal\node\Entity\Node;
 use Drupal\node\Entity\NodeType;
 use Drupal\Tests\content_moderation\Traits\ContentModerationTestTrait;
-use Drupal\Tests\system\Functional\Entity\Traits\EntityDefinitionTestTrait;
 use Drupal\workflows\Entity\Workflow;
 
 /**
@@ -24,7 +23,6 @@
 class ContentModerationStateTest extends KernelTestBase {
 
   use ContentModerationTestTrait;
-  use EntityDefinitionTestTrait;
 
   /**
    * {@inheritdoc}
@@ -531,7 +529,8 @@ public function testNonLangcodeEntityTypeModeration() {
     \Drupal::state()->set('entity_test_rev.entity_type', $entity_type);
 
     // Update the entity type in order to remove the 'langcode' field.
-    $this->applyEntityUpdates('entity_test_rev');
+    $entity_update_manager = \Drupal::entityDefinitionUpdateManager();
+    $entity_update_manager->updateFieldableEntityType($entity_type, \Drupal::service('entity_field.manager')->getFieldStorageDefinitions($entity_type->id()));
 
     $workflow = $this->createEditorialWorkflow();
     $workflow->getTypePlugin()->addEntityTypeAndBundle('entity_test_rev', 'entity_test_rev');
diff --git a/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php b/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php
index 1bc41be84e..a164d2a1ab 100644
--- a/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php
+++ b/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php
@@ -186,9 +186,6 @@ public function setUp() {
     // Calculate REST Resource config entity ID.
     static::$resourceConfigId = 'entity.' . static::$entityTypeId;
 
-    $this->entityStorage = $this->container->get('entity_type.manager')
-      ->getStorage(static::$entityTypeId);
-
     // Create an entity.
     $this->entity = $this->createEntity();
 
@@ -227,6 +224,9 @@ public function setUp() {
         ->setTranslatable(FALSE)
         ->save();
 
+      $this->entityStorage = $this->container->get('entity_type.manager')
+        ->getStorage(static::$entityTypeId);
+
       // Reload entity so that it has the new field.
       $reloaded_entity = $this->entityStorage->loadUnchanged($this->entity->id());
       // Some entity types are not stored, hence they cannot be reloaded.
diff --git a/core/modules/system/tests/src/Functional/Entity/Traits/EntityDefinitionTestTrait.php b/core/modules/system/tests/src/Functional/Entity/Traits/EntityDefinitionTestTrait.php
index 00148b466b..dd4b2d4612 100644
--- a/core/modules/system/tests/src/Functional/Entity/Traits/EntityDefinitionTestTrait.php
+++ b/core/modules/system/tests/src/Functional/Entity/Traits/EntityDefinitionTestTrait.php
@@ -24,12 +24,6 @@
    */
   protected function applyEntityUpdates($entity_type_id = NULL) {
     $complete_change_list = \Drupal::entityDefinitionUpdateManager()->getChangeList();
-    if ($complete_change_list) {
-      // In case there are changes, explicitly invalidate caches.
-      \Drupal::entityTypeManager()->clearCachedDefinitions();
-      \Drupal::service('entity_field.manager')->clearCachedFieldDefinitions();
-    }
-
     if ($entity_type_id) {
       $complete_change_list = array_intersect_key($complete_change_list, [$entity_type_id => TRUE]);
     }
diff --git a/core/modules/user/tests/src/Traits/UserCreationTrait.php b/core/modules/user/tests/src/Traits/UserCreationTrait.php
index 11c4d9b0bc..e098f7c193 100644
--- a/core/modules/user/tests/src/Traits/UserCreationTrait.php
+++ b/core/modules/user/tests/src/Traits/UserCreationTrait.php
@@ -5,7 +5,6 @@
 use Drupal\Component\Render\FormattableMarkup;
 use Drupal\Core\Database\DatabaseExceptionWrapper;
 use Drupal\Core\Database\SchemaObjectExistsException;
-use Drupal\Core\Entity\EntityStorageException;
 use Drupal\Core\Session\AccountInterface;
 use Drupal\KernelTests\KernelTestBase;
 use Drupal\user\Entity\Role;
@@ -72,6 +71,10 @@ protected function setUpCurrentUser(array $values = [], array $permissions = [],
       throw new \LogicException('The anonymous user account cannot have additional roles.');
     }
 
+    if ($this instanceof KernelTestBase) {
+      $this->installEntitySchema('user');
+    }
+
     $original_permissions = $permissions;
     $original_admin = $admin;
     $original_values = $values;
@@ -86,23 +89,12 @@ protected function setUpCurrentUser(array $values = [], array $permissions = [],
     }
 
     // Save the user entity object and created its schema if needed.
-    try {
-      if ($autocreate_user_1) {
-        $permissions = [];
-        $admin = FALSE;
-        $values = [];
-      }
-      $user = $this->createUser($permissions, NULL, $admin, $values);
-    }
-    catch (EntityStorageException $e) {
-      if ($this instanceof KernelTestBase) {
-        $this->installEntitySchema('user');
-        $user = $this->createUser($permissions, NULL, $admin, $values);
-      }
-      else {
-        throw $e;
-      }
+    if ($autocreate_user_1) {
+      $permissions = [];
+      $admin = FALSE;
+      $values = [];
     }
+    $user = $this->createUser($permissions, NULL, $admin, $values);
 
     // Ensure the anonymous user account exists.
     if (!User::load(0)) {
diff --git a/core/tests/Drupal/KernelTests/Core/Entity/DefaultTableMappingIntegrationTest.php b/core/tests/Drupal/KernelTests/Core/Entity/DefaultTableMappingIntegrationTest.php
index a484b974e3..031a4aa0ef 100644
--- a/core/tests/Drupal/KernelTests/Core/Entity/DefaultTableMappingIntegrationTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Entity/DefaultTableMappingIntegrationTest.php
@@ -49,10 +49,10 @@ protected function setUp() {
       ->setRevisionable(FALSE);
     $this->state->set('entity_test_mulrev.additional_base_field_definitions', $definitions);
 
-    $this->tableMapping = $this->entityTypeManager->getStorage('entity_test_mulrev')->getTableMapping();
-
     // Ensure that the tables for the new field are created.
     $this->applyEntityUpdates('entity_test_mulrev');
+
+    $this->tableMapping = $this->entityTypeManager->getStorage('entity_test_mulrev')->getTableMapping();
   }
 
   /**
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 {
