Comment mettez-vous à jour votre schéma de base de données / base de production sans causer de temps mort?

42

Quelles sont certaines techniques pour mettre à jour le schéma base de code / base de données d'un serveur de production sans causer de temps mort?

Olivier Lalonde
la source
1
Bonne question parce que je vois tant de gens négliger cela. Le temps, c'est de l'argent et les temps d'arrêt ne paraissent jamais bons pour les utilisateurs finaux, quelle que soit leur légitimité.
Dan McGrath
@Dan McGrath: qui suppose que vous puissiez réellement avoir un temps d'arrêt, je travaille pour un système en panne (normalement) seulement 4 fois par an (interruption trimestrielle) et pendant 15 minutes au maximum à chaque fois (pendant lequel le trafic est en file d'attente). .. les modifications apportées à la base de données sont minutieusement examinées :)
Matthieu M. le
2
Ce serait une excellente question pour dba.stackexchange.com , qui passe en version bêta publique dans quelques heures.
Larry Coleman

Réponses:

20

En règle générale, les sites Web sur lesquels j'ai travaillé et qui comportaient ce type d'exigence étaient tous situés derrière des équilibreurs de charge ou avaient des emplacements de basculement distincts. Dans cet exemple, je présume que vous disposez d'un seul équilibreur de charge, de 2 serveurs Web (A & B) et de 2 serveurs de base de données (M & N) - généralement, les serveurs de base de données sont liés via logshipping - au moins dans le monde SQL Server. )

  1. Le serveur Web A doit être déconnecté de l'équilibreur de charge (de sorte que tout le trafic entrant passe à B).
  2. L'envoi de journaux est arrêté (le serveur de base de données M va d'abord être mis à jour).
  3. Update Webserver A. Pointez la configuration sur DB Server M.
  4. Testez et vérifiez que la mise à jour a bien fonctionné (généralement, les utilisateurs saisissent directement l'adresse IP).
  5. Définissez l'équilibreur de charge pour que les sessions existantes continuent à passer à B. Les nouvelles sessions vont à A.
  6. Attendez que toutes les sessions sur B expirent (cela peut prendre une demi-heure ou plus, nous surveillons généralement la circulation et avons une heure de pause programmée).
  7. Mise à jour B et N.
  8. Testez et vérifiez que la mise à jour a fonctionné.
  9. Configurez à nouveau l'envoi des journaux et testez-le.
  10. Définissez l’équilibreur de charge sur un fonctionnement normal.

Dans les applications Web très compliquées, les étapes 1 à 5 peuvent prendre toute la nuit et constituer un tableur Excel de 50 pages avec les heures et les numéros de téléphone à contacter en cas d'urgence. Dans de telles situations, la mise à jour de la moitié du système est planifiée de 18 heures à 6 heures, tout en laissant le système à la disposition des utilisateurs. Le traitement de la mise à jour du site de reprise après incident est généralement planifié pour la nuit suivante - espérons que rien ne casse le premier jour.

Lorsque la disponibilité est une exigence, les correctifs sont d'abord testés sur l'environnement d'assurance qualité, qui correspond idéalement au même matériel que la production. S'ils ne montrent aucune perturbation, ils peuvent ensuite être appliqués selon un horaire régulier, généralement le week-end.

Tangurena
la source
7
Comment proposez-vous la fusion de nouvelles données de DB M et DB N? Ils auront tous deux des enregistrements nouveaux, mis à jour et supprimés que l’autre n’a pas.
Sixtyfootersdude
@Tangurena, pouvez-vous répondre au commentaire ci-dessus?
sino
9

Pour les bases de données classiques (Oracle par exemple), il est possible de modifier le schéma de la base de données tout en exécutant des requêtes en parallèle. Cela nécessite cependant une certaine planification.

Il y a quelques contraintes pour que le changement soit appliqué:

  • il devrait fonctionner avec le code existant, ce qui signifie qu'il devrait traiter à la fois de l'ancienne et de la nouvelle version du schéma
  • il ne devrait pas y avoir une telle charge sur le DB que les transactions s'arrêteraient (je vous regarde CREATE INDEX)
  • il ne devrait pas y avoir de perte de données (vous ne pouvez pas supprimer et recréer une table)

Pour que le schéma soit rétrocompatible, vous pouvez généralement AJOUTER ou MODIFIER une colonne, vous pouvez uniquement DROP quelque chose si le code existant ne l’utilise plus.

Si votre code ne peut pas gérer la modification de manière transparente, modifiez-le avant de modifier la base de données.

Conseils simples sur la planification à long terme: expliquez toujours les noms de colonne dans vos demandes de base de données (ne pas utiliser SELECT * FROM). De cette façon, vous n'aurez plus de nouvelles colonnes dans les anciennes requêtes.

Matthieu M.
la source
1
En fait, pour la planification et l’adaptabilité, sélectionner * de est infiniment mieux que de lister les colonnes manuellement. L'utilisation de noms de colonne explicites entraîne dans la plupart des cas beaucoup de dettes techniques. Si votre code sort de nouvelles colonnes, votre code est déjà cassé.
Morg.
@Morg: Pas vraiment. Pour la sécurité, vous devez utiliser des variables de liaison, qui dans le cadre que j’utilise (au moins) nécessite de fournir les variables sur lesquelles écrire, et il doit y avoir exactement autant de variables que de colonnes de sortie, ce select *qui signifie que le code est cassé si nouvelle colonne est ajoutée (faute d'une variable pour l'écrire). Bien sûr, cela peut être dû à l'utilisation d'un langage fortement typé.
Matthieu M.
Oui vraiment, il n'y a pas de sécurité supplémentaire à éviter de sélectionner *. Cela n'a rien à voir avec des langages fortement typés et tout à voir avec un très mauvais design. Si votre framework ne peut pas gérer le changement de manière transparente, il est inutile. Lorsque je change de colonne, mon application ne cesse jamais de fonctionner. Quand tu fais ça casse. Je ne pense pas qu'il soit question de savoir lequel est le plus fiable ou le plus sécurisé.
Morg.
@Morg .: Je ne vois pas en quoi select *c'est plus fiable et sécurisé. Si vous en aviez l'habitude, select one, two from ...alors vous n'utilisiez que oneet two; si thirdest ajouté à la table, alors vous ne l'utilisez pas (ici), il n'y a donc aucune raison de le récupérer. Et si vous avez besoin de l'utiliser soudainement, vous modifierez le code afin de modifier la requête à ce stade!
Matthieu M.
@Morg: Eh bien, il semblerait que nous parlions plus fort, probablement parce que nos expériences sont différentes. Je travaille sur des produits où la performance est une propriété primordiale, ce qui signifie que vous selectdevez être aussi sélectif que possible (et couvert par un index), sinon je suis rôti (même avant les jointures obligatoires). Je suis désolé de le dire, mais l’approche que vous décrivez a été un échec total pour ces produits.
Matthieu M.
5

Tous les systèmes ne le peuvent pas, il doit être configuré de manière à le prendre en charge.

Par exemple, l'un de nos principaux systèmes que j'ai aidé à mettre à niveau il y a quelques années devrait être disponible 24h / 24 et 7j / 7. Il se composait de plusieurs niveaux, y compris un niveau de communication pur entre la couche d'interface utilisateur et la couche de gestion hors site. En raison de la manière dont la couche de communication a été codée, toute modification future de la couche de gestion ou du schéma de base de données pourrait être mise en œuvre sans véritable interruption. Dans le pire des cas, un utilisateur subirait une pause de 10 à 30 secondes lorsque les modifications prendraient effet.

S'il s'agissait uniquement de modifications de code dans la couche de gestion, elles pourraient être mises en file d'attente et «réintégrées» avec un délai de seulement quelques millisecondes.

Cela pourrait le faire parce que:

  • La couche de communication peut contenir des messages. Cela nous a permis d'avoir une panne réelle sur l'un des niveaux autres que la couche d'interface utilisateur sans avoir à supprimer l'interface utilisateur.
  • La couche de gestion gérée par la MVDB appelée UniData . Ceci conserve tout le code en mémoire. Une fois le code compilé, vous pouvez utiliser une commande pour forcer le nouveau code objet en mémoire, en remplacement de l'ancien.

D'autres techniques impliquent la réplication de transactions sur un autre miroir du système existant. En appliquant la mise à jour à une, basculez et relisez toutes les transactions effectuées entre la mise à jour et le basculement. YMMV selon vos systèmes cependant.

Dan McGrath
la source
1

Voici une perspective différente du monde des systèmes de base de données intégrés et des systèmes intégrés. Les systèmes embarqués comprennent divers équipements d'infrastructure de réseau / de télécommunication et dans ce domaine, ils parlent souvent d'une disponibilité de 99,999% (cinq 9).

McObject est le fournisseur de la famille de produits de système de base de données eXtremeDB, notamment eXtremeDB High Availability.

Tout d’abord, comprenez que "base de données intégrée" signifie que le système de base de données est une bibliothèque compilée et liée au code de votre application; en ce sens, il est "intégré" dans votre application.

Avec eXtremeDB High Availability, il existe une instance MASTER de votre application (qui peut être un ou plusieurs processus) et une ou plusieurs instances REPLICA de votre application. Lorsqu'un réplica établit une connexion avec le maître, il reçoit une copie de la base de données du maître via un processus appelé "synchronisation initiale". Cela peut être fait pendant que l'application maître continue son travail. Une fois synchronisé, il reçoit les transactions du maître via la réplication. Par conséquent, une réplique a toujours des données actuelles et peut prendre le relais (via un processus appelé basculement) en cas de défaillance du maître.

Une caractéristique de la synchronisation initiale est appelée "évolution du schéma binaire". En clair, cela signifie que le processus de remplissage de la base de données du réplica tiendra compte des différences entre le schéma de base de données du réplica et le schéma de base de données du maître.

En pratique, cela signifie que vous pouvez créer une version plus récente de votre application (avec des tables nouvelles / supprimées, des champs nouveaux / supprimés / modifiés, des index nouveaux / supprimés), attacher cette nouvelle version de votre application à un maître, puis provoquer cette modification. le réplica le plus récent devient le nouveau maître (c'est-à-dire qu'il force le basculement vers le nouveau réplica pour qu'il devienne le maître et que l'ancien maître s'éteigne tout seul). Voila, vous avez migré votre application de la version N à N + 1, sans interrompre la disponibilité de votre système. Vous pouvez maintenant procéder à la mise à niveau de l'ancien maître et de tous les autres réplicas vers la version N + 1.


la source