2008-10-21 17 views
6

estoy usando MySQL (5.0.32-Debian_7etch6-log) y tengo una carga a granel en funcionamiento nocturno PHP (5.2.6) guión (usando Zend_Db (1.5.1) vía PDO), que hace lo siguiente:mysql error de entrada duplicada cuando no hay ninguna entrada duplicada (carga a granel a través de php)

  1. truncando un conjunto de 4 tablas de 'importación'
  2. mayor inserción de datos en estas tablas 4 'Importar' (volver a usar los identificadores que también han estado en las tablas, pero trunqué toda la tabla, por lo que no debería ser un problema, a la derecha ?)
  3. si todo va bien, cambie el nombre de las tablas 'en vivo' a 'temp', las tablas de 'importación' a 'en vivo' y luego las tablas 'temp' (viejo 'en vivo') a 'importar'

Esto funcionó muy bien durante semanas. Ahora estoy recibiendo este de vez en cuando, en algún lugar en el medio de todo el proceso de carga a granel:

SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '911' for key 1

mente que eso, esta no es la primera ID que ha estado en la mesa antes de que el truncamiento ya. Cuando empiezo nuevamente el script manualmente, funciona como un amuleto.

¿Alguna idea? índices de sobra, algo que ver con el cambio de nombre tal vez?

Además, cuando reviso la tabla para una entrada con el id 911 después, ni siquiera está allí.

Respuesta

0

¿Se podría insertar algún otro script en la base de datos mientras se está ejecutando el script de importación?

0

¿Ha intentado habilitar el registro de consultas para ver si realmente ESTÁ insertando un duplicado?

¿Se puede reproducir en su entorno de prueba? No habilite el registro de consultas en producción.

Es posible que la tabla se haya dañado si el problema es genuino; esto podría deberse a varias cosas, pero el hardware poco fiable o el fallo de alimentación son posibilidades.

Compruebe el registro de mysql para ver si ha tenido algún problema (o se ha bloqueado) recientemente o durante el período.

Una vez más, todo lo que puedo sugerir es tratar de reproducirlo en su entorno de prueba. Cree cargas muy grandes de datos de prueba y cárguelos repetidamente.

1

Aparentemente hubo algunos problemas de bloqueo o algo así, pude reproducir el comportamiento disparando sentencias 'SELECT' a las tablas afectadas y relacionadas en una conexión paralela.

ahora he usado DELETE FROM en lugar de TRUNCATE y cambiaron las declaraciones RENAME TABLE (donde hice 3 cambia el nombre a la vez cada uno) a un grupo de ALTER TABLE xxx RENAME TO zzz declaraciones individuales y no se puede reproducir el error más.

por lo que esto podría ser resuelto. tal vez alguien más pueda sacar provecho de mi día dedicado a la investigación y un montón de intentos y errores.

0

¿Está utilizando transacciones?Puede eliminar muchos de estos tipos de problemas con las transacciones, especialmente si es posible bloquear las tablas o establecer el modo de aislamiento de transacciones en serializable. No estoy muy familiarizado con aquellos en MySQL, pero creo que las transacciones solo funcionan en tablas InnoDB (o que podrían ser conocimientos obsoletos).

2

Errores como este pueden ocurrir cuando una tabla MyISAM se daña. Al ejecutar el comando de reparación en la tabla en cuestión es todo lo que se requiere para solucionarlo:

> repair table mytablename; 

Una mejor solución no es utilizar MyISAM para las tablas donde los datos se cambia constantemente - InnoDB es mucho más a prueba de balas, y como Paul señala correctamente que puede usar transacciones en tablas InnoDB, pero no en MyISAM.

Por cierto, evitaría el cambio de nombre de las tablas sobre la marcha - eso es algo bastante complicado de hacer regularmente, y podría causar algunos resultados muy inesperados si alguna vez tiene otros usuarios en el sistema, mientras que el cambio de nombre es pasando. ¿Por qué no acaba de hacer algo como esto:

> truncate table temptable; 
> truncate table importtable; 

> #bulk insert new data 
> insert into importtable(col1,col2,col3) 
> values(1,2,3),(4,5,6),(7,8,9); 

> #now archive the live data 
> insert into temptable(col1,col2,col3) 
> select col1,col2,col3 from livetable; 

> #finally copy the new data to live 
> truncate table livetable; 
> insert into livetable(col1,col2,col3) 
> select col1,col2,col3 from importtable; 

Por supuesto, si va a insertar un número muy grande de filas entonces el riesgo sería que todos sus datos en vivo no está disponible durante el tiempo que el inserto se necesita para completar, pero, en general, este enfoque es mucho menos destructivo para los índices, desencadenantes o cualquier otra cosa que pueda estar vinculada a las tablas en cuestión.

0

Está creando un nuevo registro con el campo 'id' omitido (o NULO), PERO anteriormente ha actualizado otro registro y ha cambiado su 'id' por '911'. En otras palabras, no puede crear otro registro si se toma el valor AUTO_INCREMENT de su tabla.

Cuestiones relacionadas