Cela découle de cette question connexe , où je voulais savoir comment forcer deux transactions à se produire séquentiellement dans un cas trivial (où les deux ne fonctionnent que sur une seule ligne). J'ai obtenu une réponse - utiliser SELECT ... FOR UPDATE
comme première ligne des deux transactions - mais cela conduit à un problème: si la première transaction n'est jamais validée ou annulée, la deuxième transaction sera bloquée indéfiniment. La innodb_lock_wait_timeout
variable définit le nombre de secondes après lesquelles le client essayant d'effectuer la deuxième transaction se verra dire "Désolé, essayez à nouveau" ... mais pour autant que je sache, il essaiera à nouveau jusqu'au prochain redémarrage du serveur. Donc:
- Il doit sûrement y avoir un moyen de forcer un
ROLLBACK
si une transaction prend une éternité? Dois-je recourir à l'utilisation d'un démon pour tuer de telles transactions, et si oui, à quoi ressemblerait un tel démon? - Si une connexion est interrompue par
wait_timeout
ou en coursinteractive_timeout
de transaction, la transaction est-elle annulée? Existe-t-il un moyen de tester cela à partir de la console?
Clarification : innodb_lock_wait_timeout
définit le nombre de secondes pendant lesquelles une transaction attendra qu'un verrou soit libéré avant d'abandonner; ce que je veux, c'est un moyen de forcer le déverrouillage.
Mise à jour 1 : voici un exemple simple qui montre pourquoi innodb_lock_wait_timeout
n'est pas suffisant pour garantir que la deuxième transaction n'est pas bloquée par la première:
START TRANSACTION;
SELECT SLEEP(55);
COMMIT;
Avec le paramètre par défaut de innodb_lock_wait_timeout = 50
, cette transaction se termine sans erreur après 55 secondes. Et si vous ajoutez un UPDATE
avant la SLEEP
ligne, puis lancez une deuxième transaction à partir d'un autre client qui essaie sur SELECT ... FOR UPDATE
la même ligne, c'est la deuxième transaction qui expire, pas celle qui s'est endormie.
Ce que je recherche, c'est un moyen de forcer la fin du sommeil réparateur de cette transaction.
Mise à jour 2 : En réponse aux préoccupations de hobodave sur la réalité de l'exemple ci-dessus, voici un scénario alternatif: un DBA se connecte à un serveur en direct et s'exécute
START TRANSACTION
SELECT ... FOR UPDATE
où la deuxième ligne verrouille une ligne dans laquelle l'application écrit fréquemment. Ensuite, le DBA est interrompu et s'éloigne, oubliant de mettre fin à la transaction. L'application s'arrête jusqu'à ce que la ligne soit déverrouillée. Je voudrais minimiser le temps de blocage de l'application suite à cette erreur.
ROLLBACK
sur la première transaction si cela prend plus de n
secondes pour terminer. Existe-t-il un moyen de le faire?
MYSQL
n'a pas de configuration pour empêcher ce scénario. Parce qu'il n'est pas acceptable de bloquer le serveur en raison de l'irresponsabilité des clients. Je n'ai trouvé aucune difficulté à comprendre votre question et elle est si pertinente.