Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Esistono condizioni di errore che si verificano con le transazioni che accedono a tabelle ottimizzate per la memoria.
-
- La transazione corrente ha tentato di aggiornare un record aggiornato dall'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 a cui la transazione corrente ha assunto una dipendenza è stata interrotta e la transazione corrente non può più eseguire il commit.
Una causa comune di questi errori è l'interferenza tra l'esecuzione simultanea della transazione. L'azione correttiva comune consiste nel ritentare la transazione.
Per ulteriori informazioni su queste condizioni di errore, consultare la sezione relativa al rilevamento dei conflitti, alla convalida e al controllo delle dipendenze nel commit in Transazioni in tabelle Memory-Optimized.
I deadlock (codice di errore 1205) non possono verificarsi per le tabelle ottimizzate per la memoria. I bloccaggi non vengono usati nelle tabelle ottimizzate per la memoria. Tuttavia, se l'applicazione contiene già la logica di ripetizione dei tentativi per i deadlock, la logica esistente potrebbe essere estesa per includere i nuovi codici di errore.
Considerazioni sulla ripetizione dei tentativi
Le applicazioni riscontrano in genere conflitti tra le transazioni e devono implementare la logica di ripetizione dei tentativi per risolvere tali conflitti. Il numero di conflitti rilevati dipende da diversi fattori:
Contesa per singole righe. Il rischio di conflitti aumenta man mano che aumenta il numero di transazioni che tentano 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 concorrenti. Ciò causa errori di convalida di lettura ripetibili.
Dimensioni degli intervalli di analisi usati dalle transazioni SERIALIZABLE. Maggiore è l'intervallo di analisi, maggiore è la probabilità che le transazioni simultanee introducono righe fantasma, causando errori di convalida serializzabili.
È difficile per un'applicazione evitare questi conflitti, richiedendo la logica di ripetizione dei tentativi.
Importante
Le transazioni di lettura/scrittura che accedono alle tabelle ottimizzate per la memoria richiedono la logica di ripetizione dei tentativi.
Considerazioni per le transazioni Read-Only e le procedure archiviate nativamente compilate
Le transazioni di sola lettura che si estendono su 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.
Tuttavia, i fallimenti di dipendenza possono comunque verificarsi. Gli errori di dipendenza sono più rari rispetto agli errori risultanti da conflitti. Pertanto, in molti casi, la logica di ripetizione dei tentativi specifica non è necessaria per le transazioni di sola lettura che si estendono su singole esecuzioni di stored procedure compilate in modo nativo.
Considerazioni sulle transazioni Read-Only e sulle transazioni cross-container
Le transazioni tra contenitori di sola lettura, ovvero transazioni avviate all'esterno del contesto di una stored procedure compilata in modo nativo, non eseguono la convalida se le tabelle ottimizzate per la memoria sono tutte accessibili con isolamento SNAPSHOT. Tuttavia, quando si accede a tabelle ottimizzate per la memoria al livello di isolamento REPEATABLE READ o SERIALIZABLE, la convalida viene eseguita al momento del commit. In questo caso, potrebbe essere necessaria la logica di ripetizione dei tentativi.
Per altre informazioni, vedere la sezione transazioni tra contenitori nei livelli di isolamento delle transazioni.
Implementazione della logica di ripetizione dei tentativi
Come per tutte le transazioni che accedono a tabelle ottimizzate per la memoria, è necessario prendere in considerazione la logica di ripetizione dei tentativi per gestire potenziali errori, ad esempio conflitti di scrittura (codice di errore 41302) o errori di dipendenza (codice errore 41301). Nella maggior parte delle applicazioni la frequenza degli errori sarà bassa, ma è comunque necessario gestire gli errori ritentando la transazione. Esistono due modi consigliati per implementare la logica di ripetizione dei tentativi:
Tentativi sul lato client. I tentativi sul lato client sono il modo migliore per implementare la logica di ripetizione dei tentativi nel caso generale. L'applicazione client rileva l'errore generato dalla transazione e ritenta la transazione. Se un'applicazione client esistente ha una logica di ripetizione dei tentativi per gestire i deadlock, è possibile estendere l'applicazione per gestire i nuovi codici di errore.
Utilizzo di una *stored procedure* wrapper. Il client chiama una stored procedure interpretata, Transact-SQL, che a sua volta chiama la stored procedure compilata in modo nativo o esegue la transazione. La procedura wrapper usa quindi la logica try/catch per intercettare l'errore e ripetere la chiamata di procedura, se necessario. È possibile che i risultati vengano restituiti al client prima dell'errore e che il client non sappia rimuoverli. Pertanto, per essere sicuri, è consigliabile usare questo metodo solo con 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.
Due possibili motivi per considerare la logica di ripetizione dei tentativi sono:
L'applicazione client ha la logica di ripetizione dei tentativi per altri codici di errore, ad esempio 1205, che è possibile estendere.
I conflitti sono rari ed è importante ridurre la latenza end-to-end usando l'esecuzione anticipata. Per altre informazioni sull'esecuzione di stored procedure compilate in modo nativo direttamente, vedere Stored procedure compilate in modo nativo.
Nell'esempio seguente viene illustrata la logica di riprova di una stored procedure interpretata Transact-SQL che contiene una chiamata a una stored procedure compilata in modo nativo o a una transazione inter-container.
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 nelle tabelle Memory-Optimized
Transazioni nelle tabelle Memory-Optimized
Linee guida per i livelli di isolamento delle transazioni con tabelle Memory-Optimized