2017-10-01 14 views
1

J'ai deux requêtes simples une lecture et une mise à jour d'une table. Comment puis-je verrouiller la lecture pour la requête de sélection pendant que la mise à jour est en cours d'exécution. En ce moment, dans MySQL InnoDB, j'ai remarqué que l'écriture/mise à jour est par défaut verrouillée mais la lecture/sélection récupère les anciennes données avant la transaction.Bloc MySQL lit pendant la mise à jour

J'ai essayé d'utiliser une transaction dans la requête de mise à jour, puis SELECT ... FOR UPDATE - en dehors de la transaction - mais cela n'a pas l'air de faire l'affaire. Aussi, je me demandais, à des fins de test, comment ralentir la requête UPDATE. Je suis tombé sur SLEEP (X), mais je ne sais pas comment l'implémenter dans la requête de mise à jour.

Comment puis-je faire en sorte que chaque requête attende en lecture/écriture jusqu'à ce qu'une écriture soit terminée.

Répondre

1

L'utilisation d'une transaction READ-COMMITTED affichera la dernière validation. modifications, et en utilisant SELECT ... LOCK IN SHARE MODE fera le bloc de lecture jusqu'à ce que toutes les mises à jour en suspens sont validées.

Essayez ceci. Dans un écran, démarrez une transaction et une mise à jour. Aucun SLEEP() requis, ne validez pas la transaction. Le verrou créé par UPDATE continuera d'exister jusqu'à ce que vous validiez.

BEGIN; 
UPDATE MyTable SET something = '1234' WHERE id = 3; 

Ne pas encore valider. Pendant ce temps, dans un deuxième écran, définissez l'isolation de votre transaction sur transaction validée en lecture. Pas besoin de démarrer une transaction explicite, car les requêtes InnoDB utilisent une transaction, même si elle est auto-validée. Le mode LOCK IN SHARE le fait attendre car il existe toujours un verrou exclusif en suspens créé par UPDATE.

Dans le premier écran:

COMMIT; 

Dans le second écran, le tour est joué! Le blocage de la lecture devient débloqué et vous voyez immédiatement le résultat de l'UDPATE sans avoir à actualiser votre transaction.

+0

En effet, je l'ai testé et cela fonctionne, si cela ne vous dérange pas, pourriez-vous m'expliquer rapidement une ou deux choses. Tout d'abord pourquoi 'SELECT ... FOR UPDATE' n'a pas fonctionné? Deuxièmement, j'ai essayé sans 'SET tx_isolation = 'READ-COMMITTED';' et cela a toujours fonctionné. Enfin, un commit le rend incapable d'écrire jusqu'à ce qu'il soit fini (ce n'est pas le cas par défaut). Je sais que certains d'entre eux peuvent être répondus par googling, mais je l'ai fait et je voulais les effacer un peu si cela ne vous dérange pas de passer un peu de votre temps. –

+1

'SELECT ... FOR UPDATE' devrait fonctionner de la même manière, je suppose que vous avez fait les étapes dans un ordre différent. Je ne sais pas. –

+1

Le mode read-committed agira exactement comme repeatable-read si vous utilisez autocommit, car chaque instruction démarre une nouvelle transaction. Mais si vous faites SELECT dans le cadre d'une transaction plus longue, vous voudrez utiliser read-committed. –