Une condition de race peut-elle se produire dans SQL dans ces conditions?
Si j'ai cette mise à jour SQL exécutée dans un appel de thread IT Instruction 1: P>
Update Items Set Flag = C where Flag = A;
4 Réponses :
Serrure exclusive, utilisée pour les opérations de modification de données, telles que l'insertion, la mise à jour ou la suppression, sera utilisée dans ce scénario. P>
Un verrou exclusif garantit que plusieurs mises à jour ne peuvent pas être apportées à la même ressource en même temps. P>
Vous n'obtiendrez pas une condition de course dans ce scénario. P>
Si vous avez un scénario plus complexe impliquant plusieurs tables, vous pouvez obtenir des conditions de course ou des blocages. Il existe de nombreuses façons d'éviter cela, de simplifier et de séparer les requêtes, etc. p>
Vous pouvez également appliquer des conseils à des requêtes qui indiquent SQL quel type de serrure à utiliser. P>
http://msdn.microsoft.com /en-us/library/aa213026(V=SQL.80).aspx P>
Donc, le verrou exclusif est soulevé avant de trouver les enregistrements correspondant à la clause WHERE? Savons-nous que c'est certain?
On dirait que vous devriez lire le verrouillage. SQL Server dispose d'un ensemble complexe de logique et effectuera des verrous de table ou de rangée basés sur le nombre de lignes informatiques nécessaires aura besoin de mises à jour. À moins que vous ne le disiez spécifiquement que vous voulez qu'il effectue, cela peut même varier d'une requête à la requête. Habituellement, si vous modifiez un petit sous-ensemble de la table, il choisira un verrou de niveau de ligne. P>
SQL Server est conçu avec l'acide à l'esprit, il écrit donc des modifications à ses journaux avant d'effectuer des mises à jour réelles des données. Cela permet à toutes les mises à jour échouées à rouler et à permettre la cohérence entre les requêtes (comme votre question de poser). Vous pouvez effectuer des lectures sales pour contourner des problèmes de verrouillage, mais vous ne pouvez pas empêcher SQL Server de verrouiller des enregistrements insérés, mis à jour et / ou supprimés. P>
SQL Server Verrouiller < / p>
Edit: Voici un article sur l'acide. acide - Wikipedia p>
Toutes les bases de données SQL garantissent à peu près qu'une telle collision ne se produira pas. "Quand" le verrouillage se produit dépend de la question de savoir si le verrouillage est à la table, à la partition, à la page ou au niveau de la ligne. Ou, si vous avez désactivé un tel verrouillage dans votre base de données. P>
Que peut-il arriver, si vous avez des états de mise à jour simultanés et que plusieurs lignes sont mises à jour, c'est que Sone Row est mise à jour avec le premier, certains avec la seconde. P>
En général, je pense à la clause WHERE comme étant évaluée pour sélectionner le jeu de lignes, verrouille les lignes une à la fois, faites la mise à jour et déverrouillez. Cependant, cela dépend du type de verrouillage. Dans ce cas, le scénario ci-dessus se poursuivrait avec les valeurs qui se retournent. P>
Si vous êtes préoccupé par cette situation, utilisez le niveau de la table Verrouillage pour forcer la sérialisation lorsque des demandes de mise à jour simultanées sont en cours de traitement. P>
Aucune base de données conforme standard SQL standard ne va "retourner" les valeurs. La première instruction à exécuter va acquérir des verrous, modifier les valeurs et publiera les serrures sur validation. Certaines bases de données prendront des serrures supplémentaires. Par exemple, en fonction du niveau d'isolation des transactions, les «lacunes» avant et après que des gammes devraient être verrouillées.
Je n'ai pas dit que c'était un comportement standard. En tout cas, c'est ma confusion. Lire des indications non engagées sont autorisées dans au moins une base de données (SQL Server) sur les mises à jour ... mais l'indice est ignoré.
Dans certaines bases de données, MVCC est utilisé pour sélectionner des instructions, mais pas pour les autres DML. MYSQL INNODB non-SELECT DML est "semi-reproductible" lu pour cette raison, car la version la plus récente d'une ligne est toujours présentée à des instructions non sélectionnées. En aucun cas une situation ne peut survenir lorsque deux connexions obtiennent une serrure X sur la même ligne. Si cela se produit, alors une impasse doit être déclarée.
Juste pour être clair, la question ne concerne pas deux verrous sur la même rangée. Il s'agit de savoir si une requête de mise à jour verrouille d'abord toutes les lignes, puis les mises à jour, puis les déverrouillent (qui est le bon comportement). Ou si vous pouvez configurer le verrouillage différé, lequel verrouille uniquement une ligne lorsqu'il est sur le point d'être mis à jour. Il semble que la première approche nécessite une serrure d'écriture de niveau de table pendant le processus de verrouillage et je pensais que certaines bases de données vous permettent de vous déplacer. Remarque: Cela n'a aucun effet sur les mises à jour d'une seule ligne.
Vous n'avez pas à "verrouiller toutes les lignes" puis "mettre à jour toutes les lignes". Vous verrouillez les lignes lorsque vous les rencontrez, changeez-les, copier de vieilles versions en segments de restauration (ou quels que soient vos RDBRM les appelle) et en écrivant de nouvelles versions dans les journaux de Redo. Si, lors de l'acquisition de verrouillages, vous rencontrez un délai d'attente d'attente de verrouillage en attente des serrures d'une autre connexion, vous rentrouillez les modifications (à l'aide des segments de restauration) et relâchez les serrures. Si vous évitez d'acquérir vos serrures, vous récupérez la transaction ou la déclaration, en fonction de la SGBDM.
Si vous souhaitez verrouiller explicitement toutes les lignes en tant que programmeur, vous êtes autorisé à. Pour obtenir une serrure partagée, utilisez Sélectionnez ... verrouillage en mode partage. Pour obtenir des verrous exclusives, utilisez Sélectionner ... pour la mise à jour;
Tout d'abord, il y a trois contextes de verrouillage:
alors vous avez quatre modes de verrouillage: p>
ix et les verrous sont des serrures "intention". Ces serrures sont conservées avant d'acquérir d'autres types de serrures. Les verrous x sont des verrous exclusifs (écriture) et S sont des verrous partagés (lecture). P>
Les serrures (IX, IS, X ou S) Les serrures peuvent être prises à tout niveau de contexte. Un verrouillage X au niveau de la base de données bloquera toutes les autres opérations de la base de données par exemple. C'est le type de verrou qui prend SQLLITE. Un verrou de S est pris pour l'ensemble de la base de données pendant les lectures et une verroue X est prise pour l'ensemble de la base de données lors des écritures. Les écrivies attendront que tous les serrures sont terminés et bloqueront les nouveaux verrous S et X jusqu'à ce que le verrouillage de l'écriture soit libéré. Ceci fournit un niveau de transaction d'isolement sérialisable. P>
pour MySQL, le verrouillage dépend du moteur de stockage. Myisam prendra des verrous X et S sur des tables entières (ensembles de). X Les serrures attendront sur les verrous S ou X existants et bloquent de nouveaux serrures. Les nouveaux verrous X recevront une priorité plus élevée dans la file d'attente, déplacées devant les nouveaux verrous. Ce comportement peut être modifié en définissant Low_Priority_Updates, ce qui pourrait entraîner la famine d'écriture car les écrivies seront désagréatrices en faveur des lectures. P>
Il est possible dans MySQL d'obtenir une verrouillage X sur la base de données via la base de données en utilisant " Rincer les tables avec verrouillage de lecture '. P>
InnoDB verrouille les lignes car elles sont rencontrées via un indice Lire. InnoDB Locks Index enregistre et verrouille les enregistrements lorsque les enregistrements d'index sont traversés. InnoDB utilise des serrures spéciales appelées verrouillages «Gap» pour assurer un niveau d'isolation de transaction de lecture répétable. Les serrures sont conservées sur des entrées d'index. Donc, si une table n'est pas bien indexée pour une requête de mise à jour, de nombreuses lignes seront verrouillées. Notez que InnoDB ne crée pas de verrouiller S pour des requêtes de sélection normales. Il utilise la version de la ligne, pas le verrouillage de niveau de ligne pour des instantanés cohérents. P>
Lors de l'acquisition des verrous X, la base de données doit détecter des blocages. Considérez les éléments suivants: P>
>connection 1 start transaction; update T set c = c + 1 order by id asc; >connection 2 start transaction; update T set c = c - 1 order by id desc;
Oui, mais quand tentent-ils d'acquérir le verrou de X? Avant la clause où est évalué ou après? C'est ce que je tente de comprendre.
Cela dépend de la base de données. Si vous utilisez SQLLITE, alors le verrouillage X est acquis avant que la clause WHERE est évaluée, car le verrouillage est le niveau de la base de données. Si vous utilisez MyISAM, le verrouillage X est pris avant l'évaluation de la clause WHERE, car la clause X est une serrure de niveau de table. Si vous utilisez InnoDB (verrouillons de niveau de rangée), les verrouillons X sont pris lors de l'évaluation de la clause WHERE, car vous ne pouvez pas déterminer quelles lignes à verrouiller sans trouver les lignes en évaluant la clause WHERE. C'est pourquoi vous obtenez la sérialisation des mises à jour avec Myisam, mais une impasse avec InnoDB dans mon exemple de blocage.
Donc, sur InnoDB, cela évaluerait-il d'abord la condition de la rangée, puis lorsqu'il a une correspondance acquiert la serrure avant d'écrire?
Il verrouille toutes les entrées d'index qu'il traverse pour trouver les rangées. Cela signifie qu'une mise à jour qui n'est pas bien indexée verrouille plus de lignes que prévu. Les entrées d'index sont verrouillées et non les rangées elles-mêmes à InnoDB. La base de données dépend de la base de données, mais elles sont toujours prises de manière à ce qu'aucune race que vous ne craignez que vous puissiez arriver. Certaines bases de données (comme Berkley DB) utilisent le verrouillage de niveau de page, par exemple et verrouiller tous les enregistrements de chaque page qu'ils rencontrent.
MySQL> Démarrer la transaction; Mettre à jour T Set C2 = C2 + 1 où C2 = 2; Query OK, 1 rangée affectée (0,06 sec) Row (0.06 sec) Correspondance: 1 Modifié: 1 Avertissements: 0 Code>
9 Serrure (s) de verrouillage, Taille de tas 3112, 4105 verrouillage de rangée, annuler les entrées de journal 1
Vous pouvez voir que la déclaration de mise à jour n'a changé qu'une ligne, mais 4105 serrures ont été définies.
Ces serrures d'extra lignes ont été définies car Innodb verrouillait tous les enregistrements, car il devait traverser la clé primaire pour trouver chaque ligne, tout en appliquant la clause WHERE. InnoDB verrouille des enregistrements sur les entrées d'index qu'il traverse de satisfaire la clause WHERE, non seulement les enregistrements correspondant à la clause WHERE (dans le niveau d'isolation de lecture répétable). En lecture-commémoration, InnoDB libérera les verrous sur les rangées qui ne correspondaient pas à la condition où l'état, mais seulement après la fin de la déclaration, pour empêcher une course.
Justin merci. J'apprécie les longueurs que vous avez suivies pour expliquer cela. C'est très gentil de ta part.
Est-il possible que ces 4105 verrouillons sont des verrous partagés, mais pas avant que cela n'écrit que cela tente d'une serrure exclusive. J'ai vu dans SQL Server qui dispose d'une serrure de mise à jour permettant une lecture partagée jusqu'à ce que la lock exclusive soit acquise. Je suppose que j'ai encore des doutes sur les comportements dans toutes les instances. Ils ont fait cela pour empêcher les conditions d'impasse lors du passage du verrou partagé à l'exclusivité.
Dans MySQL, il est possible d'acquérir une serrure S sur des lignes avec sélection ... verrouillage en mode de partage; Vous pouvez ensuite effectuer une mise à niveau vers X Serrure avec une mise à jour ou une sélection ... pour la mise à jour;
Quelle base de données utilisez-vous?
La deuxième déclaration attendra jusqu'à ce que le premier soit engagé. Et c'est VRAIMENT B> facile à essayer avec le SGBD que vous utilisez.
docs.oracle.com/cd/b10501_01/server.920/ A96524 / C21CNSIS.HTM