Ma situation:
Tableau: User { Id, Name, Stone, Gold, Wood }
J'ai des fils "écrire":
UPDATE User SET Stone = @calculatedValue WHERE Id=@id UPDATE User SET Wood = @calculatedValue WHERE Id=@id
UPDATE User SET gold = @calculatedValue WHERE Id=@id
UPDATE User SET Wood = @calculatedValue WHERE Id=@id UPDATE User SET Stone= @calculatedValue WHERE Id=@id
Et avoir des demandes "écrire" des utilisateurs:
UPDATE User SET Stone(Wood,Gold) = @calculatedValue WHERE Id=@id
(La valeur calculée est calculée par le code logique de bussiness C #)
Dans ce cas, j'ai beaucoup de problèmes de "perte de mise à jour" si je mets le niveau d'isolement read_commited_snapshot . Mais si je mets sérialisable ou niveau d'instantané , tout fonctionne bien
Question
Je regardais un tableau de "comparaison des niveaux d'isolement" et j'ai vu que l'isolement sérialisable et instantané résout tous les problèmes liés aux transactions simultanées. Cependant, la sérialisation est très lente.
Puis-je utiliser l'isolement d'instantané pour toutes les transactions d'écriture?
Oui, mais en fonction de l'utilisation, un instantané validé en lecture peut être préférable.
L'isolement de l'instantané a-t-il des défauts?
Oui. Il doit stocker les versions de ligne de toutes les transactions actives, ce qui nécessite un disque/mémoire.
Quel niveau d'isolement est préférable pour les transactions en lecture seule?
snapshot isolation
, ou read committed snapshot
selon qu'il existe plusieurs instructions dépendantes les unes des autres et de la taille de la transaction. read committed
s'il y a beaucoup de mises à jour et que l'espace disque sur tempdb est un problème.
Le niveau d'isolement à utiliser dépend de votre cas d'utilisation et de la façon dont vous utilisez vos données dans les transactions. Commençons donc par une comparaison plus approfondie des niveaux.
SQL Server maintient la cohérence en utilisant deux techniques différentes: le verrouillage et le versionnement des lignes.
Le verrouillage fonctionne par SQL Server émet un verrou partagé sur les tables/lignes qu'il lit, empêchant les autres transactions de mettre à jour les données. Il en va de même pour les mises à jour, qui reçoivent un verrou exclusif, empêchant les autres transactions de lire les données. Le verrouillage se produit dans différentes parties de la base de données, dans lesquelles je n'entrerai pas, mais par exemple des tables, des lignes, des index.
READ COMMITTED utilise le verrouillage pour s'assurer qu'il ne lit que les données validées. Et qu'aucune autre transaction ne met à jour les données pendant leur lecture. Cela signifie qu'une instruction de mise à jour sur les lignes qu'une autre transaction sélectionne actuellement est bloquée. Et, une instruction select sur les lignes qu'une autre transaction met à jour est bloquée jusqu'à ce que les données soient validées.
READ UNCOMMITTED ignore tout, et ne prend aucun verrou. Cela signifie qu'une autre transaction peut effectuer une mise à jour sur les lignes que la transaction lit actuellement sans être bloquée, mais cela a également pour effet que la transaction recevra des données que l'autre transaction n'a peut-être pas encore validées.
SÉRIALISABLE faites le contraire et verrouille tout. Alors que READ COMMITTED libère les verrous lors de la lecture de la ligne ou lorsque l'instruction est terminée en fonction du verrou, SERIALIZABLE libère les verrous une fois la transaction validée. Cela signifie qu'une autre transaction qui souhaite mettre à jour les données que la transaction a lues au moins une fois, ou une autre transaction qui veut lire les données que la transaction a mises à jour sera bloquée jusqu'à ce que la transaction soit validée.
READ COMMITTED SNAPSHOT et SNAPSHOT ISOLATION utilisent à la place le versionnage des lignes. Le versionnage des lignes signifie que chaque fois qu'une ligne est modifiée, SQL Server stocke une version de la ligne, garantissant qu'elle restera la même lorsqu'elle sera lue par une autre transaction.
SNAPSHOT ISOLATION fonctionne de la même manière que lorsqu'une lecture est effectuée sur une table, il récupère la dernière version des lignes qui ont été validées au début de la transaction. Cela fournit un instantané cohérent des données dans la transaction. Les données modifiées après le début de la transaction ne seront pas visibles, mais en même temps la transaction ne sera pas bloquée. Pour se protéger contre les mises à jour perdues, si la transaction souhaite mettre à jour certaines lignes qui ont été modifiées par une autre transaction après le début de la transaction, elle mettra fin aux transactions en raison de données en conflit.
READ COMMITTED SNAPSHOT fonctionne de la même manière que l'isolement de l'instantané, mais au lieu de conserver l'instantané de la transaction entière, il ne le conserve que pendant la durée de l'instruction. Cela signifie que deux instructions de lecture dans une même transaction peuvent recevoir des résultats différents. Cependant, lorsque la transaction effectue une mise à jour, elle utilise la ligne réelle au lieu d'une version de ligne précédente et ne suit pas si la ligne a été modifiée.
Étant donné que SQL Server doit conserver chaque ligne modifiée pouvant être utilisée par les transactions actives disponible, il les stocke dans tempdb. Pour cette raison, tempdb doit être suffisamment grand pour intégrer tous les changements. Il existe un thread d'arrière-plan qui vérifie quelles lignes sont encore nécessaires et supprime le reste, mais s'il y a une transaction de longue durée, cela empêchera ces lignes d'être supprimées. Si tempdb manquera d'espace, aucune nouvelle version de ligne ne sera créée et toutes les transactions tentant d'accéder à ces lignes (non existantes) se termineront.
READ COMMITTED SNAPSHOT est en dehors de READ UNCOMMITTED le plus permissif en matière de simultanéité. Il ne bloque aucune autre instruction DML et conserve une vue cohérente des données dans chaque instruction.
L'INSTALLATION D'INSTANTANÉ est permissive et maintient une meilleure cohérence que INSTANTANÉ LECTURE COMMIS, avec l'inconvénient qu'en raison de sa résolution de conflit peut échouer lors des mises à jour. Il est garanti que plusieurs déclarations au sein d'une même transaction sont cohérentes entre elles.
READ COMMITTED est permissif en ce qui concerne les lectures simultanées, pas tant pour les mises à jour. En raison du verrouillage, il est également plus lent que les niveaux de version de ligne.
READ UNCOMMITTED n'est pas recommandé à utiliser car il lira des données sales, si cela ne vous inquiète pas, il est préférable de ne pas verrouiller et de ne pas conserver les anciennes versions de ligne.
SERIALIZABLE n'est pas recommandé car il garde les verrous sur tout et est donc lent et pas bon avec la concurrence.