2009-05-23 5 views
5

On me donne chaque semaine une source de données que je vais analyser et mettre dans une base de données. Les données ne changeront pas beaucoup de semaine en semaine, mais je devrais mettre à jour la base de données sur une base régulière. Outre cette mise à jour hebdomadaire, les données sont statiques. Pour l'instant, la reconstruction de toute la base de données n'est pas un problème, mais éventuellement cette base de données sera en ligne et les gens pourraient interroger la base de données pendant que je la reconstruis. La quantité de données n'est pas petite (quelques centaines de mégaoctets), donc elle ne se chargera pas instantanément, et personnellement je veux un peu plus d'un système infaillible que "J'espère que personne ne questionne alors que la base de données est en désordre".Quelle est la meilleure façon de mettre à jour (ou de remplacer) une table de base de données entière sur une machine en direct?

J'ai réfléchi à plusieurs façons de résoudre ce problème et je me demandais quelle serait la meilleure méthode. Voici mes idées à ce jour:

  1. Au lieu de remplacer des tables entières, requête pour la différence entre ma base de données actuelle et ce que je veux placer dans la base de données. Cela semble toutefois être une quantité de travail inutile.

  2. Créer des tables de données fictives, puis effectuer un changement de nom de table (ou faire pointer le code du serveur vers les nouvelles tables de données). Il suffit de dire aux utilisateurs que le site est en cours de maintenance et de mettre le système hors ligne pendant quelques minutes. (Ce n'est pas préférable pour des raisons évidentes, mais si c'est de loin la meilleure réponse, je suis prêt à accepter cela.)

Réflexions?

+0

Un système de base de données particulier que vous avez en tête? –

+0

Actuellement, j'utilise MySQL, mais je peux finir par utiliser PostgreSQL. –

Répondre

5

Je ne peux pas parler pour MySQL, PostgreSQL, mais a DDL transactionnel. Ceci est une fonctionnalité merveilleuse, et signifie que votre deuxième option, le chargement de nouvelles données dans une table fictive, puis l'exécution d'un changement de nom de table, devrait fonctionner très bien. Si vous souhaitez remplacer la table foo par foo_new, il vous suffit de charger les nouvelles données dans foo_new et d'exécuter un script pour le renommer. Ce script devrait s'exécuter dans sa propre transaction, donc si quelque chose à propos du renommage devient mauvais, les deux foo et foo_new seront laissés intacts quand il reviendra.

Le principal problème avec cette approche est qu'il peut être un peu compliqué de gérer les clés étrangères à partir d'autres tables qui cliquent sur foo. Mais au moins, vous avez la garantie que vos données resteront cohérentes.

Une meilleure approche à long terme, je pense, est juste d'effectuer les mises à jour sur les données directement (votre première option). Une fois de plus, vous pouvez coller toute la mise à jour en une seule transaction, ce qui vous garantit une sémantique du tout ou rien. Mieux encore, il s'agirait de mises à jour en ligne, juste de mettre à jour les données directement à mesure que de nouvelles informations deviendraient disponibles. Cela peut ne pas être une option pour vous si vous avez besoin des résultats du travail par lots de quelqu'un d'autre, mais si vous pouvez le faire, c'est la meilleure option.

1

Quel serveur de base de données utilisez-vous? SQL 2005 et supérieur fournit une méthode de verrouillage appelée "Snapshot". Il vous permet d'ouvrir une transaction, de faire toutes vos mises à jour, puis de valider, tout en continuant à consulter les données pré-transaction. Normalement, votre transaction verrouillerait vos tables et bloquerait leurs requêtes, mais le verrouillage de snapshot serait parfait dans votre cas.

Plus d'infos ici: http://blogs.msdn.com/craigfr/archive/2007/05/16/serializable-vs-snapshot-isolation-level.aspx

Mais il faut SQL Server, donc si vous utilisez quelque chose d'autre ....

1

systèmes de base de données Plusieurs (puisque vous ne spécifiez pas le vôtre, je vais garder ce général) n'offrent le SQL: 2003 déclaration standard appelée MERGE qui vous permettra essentiellement de

  • insérer de nouvelles lignes dans une table cible à partir d'une source qui n'existent pas encore là
  • mise à jour des lignes existantes dans la table cible sur la base de nouvelles valeurs de la source
  • en option supprimer même les lignes de la cible qui ne se présentent pas dans la table d'importation plus

SQL Server 2008 est la première offre de Microsoft pour avoir cette déclaration - consultez plus here, here ou here.

Un autre système de base de données aura probablement des implémentations similaires - c'est une instruction SQL: 2003 Standard après tout.

Marc

3
BEGIN; 
DELETE FROM TABLE; 
INSERT INTO TABLE; 
COMMIT; 

Les utilisateurs verront le changement instantanément lorsque vous appuyez sur valider. Toutes les requêtes démarrées avant que la validation ne s'exécute sur les anciennes données, tout ce qui sera ensuite exécuté sur les nouvelles données. La base de données effacera réellement l'ancienne table une fois que le dernier utilisateur en a fini avec elle. Parce que tout est "statique" (vous êtes le seul à le changer, et seulement une fois par semaine), vous n'avez pas à vous soucier de problèmes de verrouillage ou de délais. Pour MySQL, cela dépend d'InnoDB. PostgreSQL le fait, et SQL Server l'appelle "snapshotting", et je ne peux pas me rappeler les détails du haut de ma tête puisque je l'utilise rarement.

Si vous "Google isolation des transactions" + le nom de la base de données que vous utilisez, vous trouverez des informations appropriées.

+1

Oui, mais si le chargement de plusieurs centaines de megs de données prend plusieurs minutes, votre système ne sera pas en mesure de servir son client pendant ce temps ... cette solution est idéale pour les petits ensembles de données VRAIMENT. En outre, que se passe-t-il si l'intégrité référentielle de vos données est activée? Vous pourriez tout simplement ne pas être en mesure d'effacer totalement votre table de base pour commencer .... –

+2

Oui, vous serez en mesure de servir le client pendant cette période. C'est le point de l'isolation de la transaction. Si vous avez une intégrité référentielle, vous devez supprimer les éléments dans le bon ordre, tout comme vous devez les insérer dans le bon ordre. –

+1

C'est clairement la bonne solution SQL, en utilisant les transactions. – bortzmeyer

1

Utilisez différents noms de tables (mytable_ [yyyy] _ [wk]) et une vue pour vous fournir un nom de constante (mytable). Une fois qu'une nouvelle table est complètement importée, mettez à jour votre vue afin qu'elle utilise cette table.

2

Nous avons résolu ce problème en utilisant le mécanisme d'héritage/contraintes de table de PostgreSQL. Vous créez un déclencheur qui crée automatiquement des sous-tables partitionnées en fonction d'un champ de date.

This l'article était la source que j'ai utilisée.

Questions connexes