Questa pagina è stata tradotta da PageTurner AI (beta). Non ufficialmente approvata dal progetto. Hai trovato un errore? Segnala problema →
Transazioni
Creazione e utilizzo delle transazioni
Le transazioni vengono create utilizzando DataSource o EntityManager.
Esempi:
await myDataSource.transaction(async (transactionalEntityManager) => {
// execute queries using transactionalEntityManager
})
oppure
await myDataSource.manager.transaction(async (transactionalEntityManager) => {
// execute queries using transactionalEntityManager
})
Tutte le operazioni da eseguire in una transazione devono essere contenute in una callback:
await myDataSource.manager.transaction(async (transactionalEntityManager) => {
await transactionalEntityManager.save(users)
await transactionalEntityManager.save(photos)
// ...
})
La restrizione più importante quando si lavora in una transazione è UTILIZZARE SEMPRE l'istanza fornita dell'entity manager -
transactionalEntityManager in questo esempio. NON UTILIZZARE L'ENTITY MANAGER GLOBALE.
Tutte le operazioni DEVONO essere eseguite utilizzando l'entity manager transazionale fornito.
Specifica del livello di isolamento
È possibile specificare il livello di isolamento per la transazione fornendolo come primo parametro:
await myDataSource.manager.transaction(
"SERIALIZABLE",
(transactionalEntityManager) => {},
)
Livelli di isolamento supportati
Le implementazioni dei livelli di isolamento non sono agnostiche tra tutti i database. Ogni driver dichiara quali livelli supporta, e TypeORM genererà un errore se si richiede un livello non supportato.
CockroachDB
READ COMMITTED— requires the cluster settingsql.txn.read_committed_isolation.enabled, which is enabled by default in recent versionsREPEATABLE READ— requires the cluster settingsql.txn.repeatable_read_isolation.enabled, which is disabled by default (introduced in v24.3.0)SERIALIZABLE(default)
CockroachDB maps weaker SQL isolation requests to stronger levels. The fallback behavior depends on the corresponding cluster settings. For example, when you request READ UNCOMMITTED, READ COMMITTED or REPEATABLE READ via SQL (e.g. BEGIN TRANSACTION ISOLATION LEVEL READ UNCOMMITTED), CockroachDB accepts the syntax and may run the transaction at a stricter level instead:
READ COMMITTED→ runs as:SERIALIZABLEifsql.txn.read_committed_isolation.enabledis false andsql.txn.repeatable_read_isolation.enabledis falseREPEATABLE READifsql.txn.repeatable_read_isolation.enabledis true andsql.txn.read_committed_isolation.enabledis false
READ UNCOMMITTED→ runs as:SERIALIZABLEifsql.txn.read_committed_isolation.enabledis false andsql.txn.repeatable_read_isolation.enabledis falseREAD COMMITTEDifsql.txn.read_committed_isolation.enabledis trueREPEATABLE READifsql.txn.repeatable_read_isolation.enabledis true andsql.txn.read_committed_isolation.enabledis false
REPEATABLE READ→ runs asSERIALIZABLEifsql.txn.repeatable_read_isolation.enabledis false
Google Spanner
REPEATABLE READ*SERIALIZABLE
* REPEATABLE READ on Spanner is currently in Preview and not yet generally available. It provides snapshot isolation and permits write-skew anomalies — use SELECT ... FOR UPDATE when that matters.
MariaDB
READ UNCOMMITTEDREAD COMMITTEDREPEATABLE READSERIALIZABLE
MS SQL Server
READ UNCOMMITTEDREAD COMMITTEDREPEATABLE READSERIALIZABLESNAPSHOT
SQL Server also supports driver-specific options.isolationLevel and options.connectionIsolationLevel settings, but these are subject to an upstream pool limitation. The top-level isolationLevel option covered on this page is not affected, because it is applied explicitly on each transaction.
MySQL
READ UNCOMMITTEDREAD COMMITTEDREPEATABLE READSERIALIZABLE
Isolation levels are not supported on the aurora-mysql driver. Requesting any level throws a validation error.
This is a transport limitation, not an engine limitation. Aurora MySQL the database engine fully supports the standard set, but the aurora-mysql driver talks to the cluster over the stateless RDS Data API instead of a persistent MySQL protocol connection, and the Data API provides no way to attach an isolation level to a transaction:
BeginTransactionaccepts onlyresourceArn,secretArn,database, andschema— there is no isolation parameter.- The Data API pools backend connections opaquely. A
SET TRANSACTION ISOLATION LEVEL ...sent as a separateExecuteStatementbeforeBeginTransactionhas no guaranteed affinity to the backend session that the transaction will run on, so the setting is silently dropped. - Multi-statement SQL is not supported, so
SET TRANSACTION ...; START TRANSACTION;cannot be sent as a single call either. - MySQL rejects
SET TRANSACTION ISOLATION LEVELinside an already-started transaction with error 1568, so the approach used for Aurora PostgreSQL (issuingSETas the first statement inside the started transaction) is not available on MySQL.
mysql driverIf per-transaction isolation levels are needed against an Aurora MySQL cluster, use the standard mysql driver pointed at the cluster writer endpoint instead of aurora-mysql. That path uses a regular MySQL protocol connection (via mysql2) and supports the full set of isolation levels listed above.
PostgreSQL
READ UNCOMMITTEDREAD COMMITTEDREPEATABLE READSERIALIZABLE
The same set of isolation levels is supported by the aurora-postgres driver, which talks to Aurora PostgreSQL clusters through the RDS Data API.
SAP HANA
READ COMMITTEDREPEATABLE READSERIALIZABLE
SQLite
READ UNCOMMITTED— only takes effect when shared-cache mode is enabled; in the default mode SQLite always usesSERIALIZABLEregardlessSERIALIZABLE
Livello di isolamento predefinito
Puoi configurare un livello di isolamento predefinito per tutte le transazioni impostando isolationLevel nelle opzioni di DataSource:
const dataSource = new DataSource({
type: "postgres",
isolationLevel: "SERIALIZABLE",
// ...
})
Una volta impostato, tutte le transazioni avviate senza un livello di isolamento esplicito utilizzeranno questo predefinito. Un livello di isolamento esplicito passato a transaction() o startTransaction() sovrascriverà il predefinito.
Utilizzo di QueryRunner per creare e controllare lo stato di una connessione database singola
QueryRunner fornisce una singola connessione al database.
Le transazioni vengono gestite tramite i query runner.
È possibile stabilire una singola transazione solo su un singolo query runner.
Puoi creare manualmente un'istanza di query runner e utilizzarla per controllare manualmente lo stato della transazione.
Esempio:
// create a new query runner
const queryRunner = dataSource.createQueryRunner()
// establish real database connection using our new query runner
await queryRunner.connect()
// now we can execute any queries on a query runner, for example:
await queryRunner.query("SELECT * FROM users")
// we can also access entity manager that works with connection created by a query runner:
const users = await queryRunner.manager.find(User)
// lets now open a new transaction:
await queryRunner.startTransaction()
try {
// execute some operations on this transaction:
await queryRunner.manager.save(user1)
await queryRunner.manager.save(user2)
await queryRunner.manager.save(photos)
// commit transaction now:
await queryRunner.commitTransaction()
} catch (err) {
// since we have errors let's rollback changes we made
await queryRunner.rollbackTransaction()
} finally {
// you need to release query runner which is manually created:
await queryRunner.release()
}
Esistono 3 metodi per controllare le transazioni in QueryRunner:
-
startTransaction- avvia una nuova transazione all'interno dell'istanza del query runner. -
commitTransaction- consolida tutte le modifiche apportate utilizzando l'istanza del query runner. -
rollbackTransaction- annulla tutte le modifiche apportate utilizzando l'istanza del query runner.
Ulteriori informazioni su Query Runner.