Linee guida per la logica di riesecuzione per le transazioni in tabelle con ottimizzazione per la memoria
Esistono condizioni di errore che si verificano con le transazioni che accedono a tabelle ottimizzate per la memoria.
-
- Tentativo da parte della transazione corrente di aggiornare un record che è già stato aggiornato dopo l'avvio della transazione.
-
- Impossibile eseguire il commit della transazione corrente a causa di un errore di convalida di lettura ripetibile.
-
- Impossibile eseguire il commit della transazione corrente a causa di un errore di convalida serializzabile.
-
- Una transazione precedente da cui dipende la transazione corrente è stata interrotta. Impossibile eseguire il commit della transazione corrente.
Una causa comune di questi errori è con una transazione eseguita simultaneamente. L'azione correttiva normale consiste nel ripetere la transazione.
Per altre informazioni su queste condizioni di errore, vedere la sezione relativa ai controlli di rilevamento dei conflitti, convalida e commit delle dipendenze nelle transazioni nelle tabelle Memory-Optimized.
I deadlock (codice di errore 1205) non possono verificarsi per le tabelle ottimizzate per la memoria. I blocchi non vengono utilizzati per le tabelle ottimizzate per la memoria. Se tuttavia nell'applicazione è già presente la logica di riesecuzione per i deadlock, la logica esistente può essere estesa in modo da includere i nuovi codici di errore.
Considerazioni sulla riesecuzione
Nelle applicazioni si verificano in genere conflitti tra le transazioni ed è necessario implementare la logica di riesecuzione per risolverli. Il numero di conflitti rilevati dipende da una serie di fattori:
Contesa per singole righe. Il rischio di conflitti aumenta man mano che aumenta il numero di transazioni che tenta di aggiornare la stessa riga.
Numero di righe lette dalle transazioni REPEATABLE READ. Più righe vengono lette, maggiore è la probabilità che alcune di queste righe vengano aggiornate da transazioni simultanee. Questa condizione causa errori di convalida di lettura ripetibili.
Dimensioni degli intervalli di analisi utilizzati dalle transazioni SERIALIZABLE. Maggiori sono le dimensioni degli intervalli di analisi, maggiore è la probabilità che le transazioni simultanee introducano righe fantasma, causando errori di convalida serializzabili.
È difficile evitare questi conflitti in un'applicazione, pertanto è necessaria la logica di riesecuzione.
Importante
Le transazioni di lettura e scrittura che accedono a tabelle ottimizzate per la memoria richiedono la logica di riesecuzione.
Considerazioni sulle transazioni di sola lettura e sulle stored procedure compilate in modo nativo
Le transazioni di sola lettura che interessano una singola esecuzione di una stored procedure compilata in modo nativo non richiedono la convalida per le transazioni REPEATABLE READ e SERIALIZABLE. I conflitti di scrittura non possono verificarsi a causa di una transazione di sola lettura.
Gli errori di dipendenza possono tuttavia continuare a verificarsi. Gli errori di dipendenza sono meno comuni degli errori risultanti da conflitti. In molti casi non è quindi richiesta logica di riesecuzione specifica per le transazioni di sola lettura che interessano singole esecuzioni di stored procedure compilate in modo nativo.
Considerazioni sulle transazioni di sola lettura e sulle transazioni tra contenitori
Per le transazioni di sola lettura tra contenitori, ovvero transazioni che vengono avviate al di fuori del contesto di una stored procedure compilata in modo nativo, non viene eseguita la convalida se l'accesso alle tabelle ottimizzate per la memoria avviene nel livello di isolamento SNAPSHOT. Quando tuttavia si accede alle tabelle ottimizzate per la memoria nell'isolamento REPEATABLE READ o SERIALIZABLE, la convalida viene eseguita in fase di commit. In questo caso, potrebbe essere richiesta la logica di riesecuzione.
Per altre informazioni, vedere la sezione transazioni tra contenitori nei livelli di isolamento delle transazioni.
Implementare della logica di riesecuzione
Come per tutte le transazioni che accedono a tabelle ottimizzate per la memoria, è necessario considerare la logica di riesecuzione per gestire possibili errori, ad esempio conflitti di scrittura (codice di errore 41302) o errori di dipendenza (codice di errore 41301). Nella maggior parte delle applicazioni il tasso di errori sarà basso, ma è comunque necessario gestire gli errori rieseguendo la transazione. È consigliabile implementare la logica di riesecuzione nei due modi seguenti:
Tentativi sul lato client. I tentativi sul lato client costituiscono il modo consigliato per implementare la logica di riesecuzione nel caso generale. L'applicazione client rileva l'errore generato dalla transazione e riesegue la transazione. Se un'applicazione client esistente dispone di una logica di riesecuzione per la gestione di deadlock, è possibile estendere l'applicazione per gestire i nuovi codici di errore.
Utilizzo di una stored procedure del wrapper. Il client chiama una stored procedure Transact-SQL interpretata che chiama la stored procedure compilata in modo nativo o esegue la transazione. La procedura del wrapper utilizza la logica try/catch per rilevare l'errore e per ripetere la chiamata di procedura, se necessario. È possibile che i risultati vengano restituiti al client prima dell'errore e che il client non sia in grado di rimuoverli. Per essere sicuri, è pertanto preferibile utilizzare questo metodo solo con le stored procedure compilate in modo nativo che non restituiscono alcun set di risultati al client.
La logica di ripetizione dei tentativi può essere implementata in Transact-SQL o nel codice dell'applicazione nel livello intermedio.
Di seguito sono indicate due possibili motivi per considerare la logica di riesecuzione:
L'applicazione client dispone di logica di riesecuzione per altri codici di errore, ad esempio 1205, che è possibile estendere.
I conflitti sono rari ed è importante ridurre la latenza end-to-end mediante un'esecuzione preparata. Per altre informazioni sull'esecuzione di stored procedure compilate in modo nativo direttamente, vedere Stored procedure compilate in modo nativo.
L'esempio seguente illustra la logica di ripetizione dei tentativi in una stored procedure Transact-SQL interpretata che contiene una chiamata a una stored procedure compilata in modo nativo o a una transazione tra contenitori.
CREATE PROCEDURE usp_my_procedure @param1 type1, @param2 type2, ...
AS
BEGIN
-- number of retries - tune based on the workload
DECLARE @retry INT = 10
WHILE (@retry > 0)
BEGIN
BEGIN TRY
-- exec usp_my_native_proc @param1, @param2, ...
-- or
-- BEGIN TRANSACTION
-- ...
-- COMMIT TRANSACTION
SET @retry = 0
END TRY
BEGIN CATCH
SET @retry -= 1
-- the error number for deadlocks (1205) does not need to be included for
-- transactions that do not access disk-based tables
IF (@retry > 0 AND error_number() in (41302, 41305, 41325, 41301, 1205))
BEGIN
-- these error conditions are transaction dooming - rollback the transaction
-- this is not needed if the transaction spans a single native proc execution
-- as the native proc will simply rollback when an error is thrown
IF XACT_STATE() = -1
ROLLBACK TRANSACTION
-- use a delay if there is a high rate of write conflicts (41302)
-- length of delay should depend on the typical duration of conflicting transactions
-- WAITFOR DELAY '00:00:00.001'
END
ELSE
BEGIN
-- insert custom error handling for other error conditions here
-- throw if this is not a qualifying error condition
;THROW
END
END CATCH
END
END
Vedere anche
Informazioni sulle transazioni in tabelle con ottimizzazione per la memoria
Transazioni in tabelle con ottimizzazione per la memoria
Linee guida per i livelli di isolamento delle transazioni con tabelle con ottimizzazione per la memoria