2009-05-20 9 views
1

mysql> mise à jour du nom de table set fieldname = 'C200900674' où fieldname - 'C200900673';Comportement de mise à jour MySQL

erreur 1062 (23000): entrée en double 'C200900674-2008-0-1' pour la touche 1

Toute pensée ou suggestions à ce sujet? Quelqu'un a accidentellement fait cette mise à jour avec un signe moins au lieu d'un signe égal. Il a apparemment essayé de changer tous les enregistrements moins que cette valeur? Même si c'est alphanumérique et vraiment assez incomplet. En plus de cela, une quantité d'enregistrements a été mise à jour avant d'avoir cette erreur et il n'y a pas eu de retour du tout. Rien de tel que "Query OK, X rows affected (0.00 sec)", donc nous n'avions aucune idée du nombre de changements. autocommit = 1 donc pas de possibilité de revenir en arrière.

De toute façon, juste à la recherche de conseils ou de pointeurs à ce sujet. Pourquoi cette requête a fait quoi que ce soit, il semble vraiment qu'il aurait dû me renvoyer une erreur. Autre que la réponse évidente de ne pas laisser les administrateurs inexpérimentés faire des choses osseuses bien sûr.

Répondre

0

Si votre table utilise le moteur de stockage InnoDB, aucun dommage n'a été causé. Même avec autocommit = 1, la requête est seulement exécutée "tout ou rien". Le fait que vous ayez reçu un message ERROR est la preuve que la base de données n'a pas touché vos données. Chaque fois que vous obtenez une erreur, le message "x rows affected" est omis.

Même dans le cas où la contrainte uniquess aurait pas eu violation de la requête aurait échoué avec une autre erreur:

ERROR 1292 (22007): Truncated incorrect DOUBLE value: 'fieldname'

En effet, le signe moins aurait causé MySQL pour essayer de calculer la valeur de la le contenu du champ moins quelque chose d'autre. Cela ne fonctionne pas. Vous n'avez pas vu cette erreur, car l'autre "est arrivé en premier".

+1

La table était en INNODB et apparemment nous avons * fait * l'expérience d'une quantité d'enregistrements en cours de modification. Toutes les preuves que j'ai pu découvrir jusqu'ici en sont la preuve. La journalisation binaire a été activée sur cette boîte de sorte que l'extraction incluait même "mysqlbinlog -s {logfile} | grep -i {identifiant unique pour cet enregistrement}". FWIW cette instruction de mise à jour * était * enregistrée dans le journal binlog. Je vais continuer à jouer avec cela et peut-être essayer de faire un DB de test et des tables et essayer de le reproduire dans un environnement contrôlé. Merci ... – wdingus

+0

Les cordes dans votre exemple sont-elles les vraies?Je peux voir cela se produire si au lieu de 'C200900674' vous avez quelque chose comme '200900674C' ou '2009C00674C', c'est-à-dire commençant par un nombre. –

+0

Oui, la seule chose que j'ai changé était les noms de la table et du champ. – wdingus

2

Chaque fois qu'il y a un doute sur la façon dont Mysql interprète une clause WHERE, inversez-la en SELECT.

SELECT fieldname - 'C200900673' FROM tablename; 

Et:

SELECT fieldname FROM tablename WHERE fieldname - 'C200900673'; 

Voir la valeur qui est renvoyée par la première sélection, et quelles lignes la seconde trouver. Malheureusement, puisque Mysql est assez laxiste sur les conversions numériques/chaînes, spécialement sur la série 4.x, et même sur les non-strictes 5.x, diable ... même stricte, il est difficile de dire exactement quoi a mal tourné sans tous les détails de votre configuration Mysql. Il pourrait être parce que le nom du champ a été jeté à un certain nombre, et qu'il était donc « C200900673 », essentiellement en cours d'exécution:

update tablename set fieldname = 'C200900674' where NUMBER - NUMBER; 

Ce qui pourrait se traduire par:

update tablename set fieldname = 'C200900674' where 1; 

Quoi qu'il en soit, je vous souhaite une sauvegarde!