2010-02-13 8 views
7

J'essaie de trouver un moyen de faire un DELETE conditionnel sur une table InnoDB qui contient des millions d'enregistrements, sans le verrouiller (donc ne pas mettre le site web en panne).Supprimer de la table avec des millions d'enregistrements

J'ai essayé de trouver des informations sur mysql.com, mais en vain. Des conseils sur la façon de procéder?

+0

Y a-t-il beaucoup d'index sur cette table? –

+0

Indexez les colonnes qui géreront les conditions. Puis effectuez la suppression lorsque le trafic vers le site est faible (@ nuit probablement). –

+0

voir aussi http://stackoverflow.com/questions/23193761/delete-operation-locks-whole-table-in-innodb qui mentionne le verrouillage de l'espace – rogerdpack

Répondre

8

Je ne pense pas qu'il soit possible de supprimer sans verrouillage. Cela dit, je ne pense pas que le verrouillage du dossier que vous voulez supprimer soit un problème. Ce qui poserait un problème est le verrouillage d'autres lignes.

J'ai trouvé quelques informations sur ce sujet ici: http://dev.mysql.com/doc/refman/5.0/en/innodb-locks-set.html

Ce que je suggère, est d'essayer de faire un million supprime seule ligne. Je pense que si vous faites tout cela en une seule transaction, la performance ne devrait pas trop nuire. de sorte que vous obtiendrez quelque chose comme:

START TRANSACTION; 

DELETE FROM tab WHERE id = 1; 
.. 
.. 
DELETE FROM tab WHERE id = x; 

COMMIT; 

Vous pouvez générer les statments nécessaires en faisant quelque chose comme

SELECT CONCAT('DELETE FROM tab WHERE id = ', id) 
FROM tab 
WHERE <some intricate condition that selects the set you want to delete> 

donc l'avantage sur cette méthode au lieu de faire:

DELETE FROM tab 
WHERE <some intricate condition that selects the set you want to delete> 

est que dans la première approche, vous ne verrouillez que l'enregistrement que vous supprimez, alors que dans la seconde, vous risquez de bloquer d'autres enregistrements qui se trouvent dans la même plage que la ligne s vous supprimez.

+0

+1, solution prometteuse! Avez-vous déjà utilisé cette approche dans la pratique? – Frunsi

+0

@frunsi: J'avoue honnêtement que je n'ai pas.En règle générale, la suppression d'un million de lignes n'est pas un problème, mais les systèmes que je gère ne sont pas touchés par de nombreux utilisateurs en même temps. –

5

Si cela correspond à votre application, vous pouvez limiter le nombre de lignes à supprimer et configurer un cronjob pour répéter la suppression. E.g .:

DELETE FROM tab WHERE .. LIMIT 1000 

J'ai trouvé que c'était un bon compromis dans un scénario similaire.

+0

Je pense que le problème avec cette approche est que la LIMITE est évaluée après avoir isolé l'ensemble . Donc, le 'WHERE' est appliqué, ce qui pourrait bloquer les lignes qui se trouvent dans la même plage que les lignes que vous supprimez. Le fait que vous supprimiez seulement un nombre limité ne change rien au fait que les enregistrements ont déjà été verrouillés. Ce que cette méthode fait est de garder la taille de la transaction petite, ce qui est également bon. Mais cela n'empêche pas le verrouillage parasite pour autant que je comprenne. –

+0

@Roland: Vous pourriez avoir raison. Cette solution n'est peut-être pas idéale, mais fonctionne très bien en pratique (l'effacement limité est rapide, donc les verrous sont maintenus pour de très courts intervalles de temps, le paramètre limite peut être réglé sur les données réelles). J'ai fait quelques benchmarks avant d'utiliser cette approche, et le temps cumulé de toutes les suppressions limitées s'est terminé en moins de temps qu'un seul non-limité (mais à l'époque, il utilisait les tables MySQL 3.x et MyISAM). Cela fonctionne toujours, mais le benchmark sur les tables MySQL et InnoDB actuelles apporterait un peu de lumière dans les détails .. – Frunsi

+0

oui Je pense qu'il est sûr de dire que le scénario que vous décrivez, une table de verrouillage du moteur MyISAM sur une version de plus de 9 ans de la produit par rapport au moteur InnoDB qui dispose à la fois de contrôle de simultanéité multi-version et de verrouillage au niveau des lignes, pourrait en effet être quelque peu différent: p –

Questions connexes