Я получаю некоторые ошибки в некоторых сценариях, когда использую Pessimisti c Блокировка записи с уровнем изоляции SERIALIZABLE.
Вот класс MappingEntity:
@Data
@Entity(name = "asset_type_mapping")
@Table(
name = "asset_type_mapping",
uniqueConstraints =
@UniqueConstraint(
name = "UQ_MappingEntity",
columnNames = {
Constants.DATA_TYPE_VALUE,
Constants.DATA_TYPE_NAMESPACE_INDEX,
Constants.TENANT_ID,
Constants.ASSET_TYPE_NAME
}
)
)
public class MappingEntity {
@Id
@GeneratedValue(generator = "uuid")
@GenericGenerator(name = "uuid", strategy = "uuid2")
private String id;
@Column(name = Constants.DATA_TYPE_VALUE)
private long dataTypeValue;
@Column(name = Constants.DATA_TYPE_NAMESPACE_INDEX)
private int dataTypeNamespaceIndex;
@Column(name = Constants.ASSET_TYPE_NAME)
private String assetTypeName;
@Column(name = Constants.TENANT_ID)
private String tenantId;
}
Вот класс MappingRepository :
public interface MappingRepository extends JpaRepository<MappingEntity, String> {
@Lock(LockModeType.PESSIMISTIC_WRITE)
MappingEntity findMappingEntityWithLockByTenantIdAndAssetTypeName(
String tenantId, String assetTypeName);
}
Вот блок кода службы, где я получаю ошибки.
@Transactional(isolation = Isolation.SERIALIZABLE)
public void deleteAspectType(String tenantId, String aspectTypeId) {
MappingEntity mappingEntity = mappingRepository.findMappingEntityWithLockByTenantIdAndAssetTypeName(tenantId, assetTypeName);
mappingRepository.delete(mappingEntity);
}
Теперь позвольте мне объяснить мои шаги. В моей базе данных есть две строки в таблице MappingEntity, и я хочу удалить эти две строки одновременно. Для этого я отправляю два запроса одновременно. Два потока принимают этот запрос и вызывают метод deleteAspectType () одновременно. Эти два потока сначала запускают запрос выбора с блокировкой, а затем удаляют. Но один из потоков не удаляется, и выдается исключение:
ERROR: could not serialize access due to read/write dependencies among transactions
Detail: Reason code: Canceled on identification as a pivot, during write.
Hint: The transaction might succeed if retried.
Я в замешательстве. Потоки извлекают разные строки и блокируют их. Когда я изменяю уровень изоляции на Read Committed, я не беру это исключение и работает нормально. Или когда я добавляю в индекс эту таблицу с tenantId и assetTypeName, пока уровень изоляции все еще SERIALIZABLE, я тоже не беру это исключение.
Пожалуйста, кто-нибудь объяснит мне, почему я получаю это исключение, когда уровень изоляции SERIALIZABLE без индекса и почему этот код работает нормально, когда уровень изоляции Read Committed или уровень изоляции SERIALIZABLE с индексом?