L'application SaaS doit exporter/sauvegarder des données sur des sites clients individuels
nous avons une application SaaS basée sur le cloud et beaucoup de nos clients (systèmes scolaires) exigent qu'une sauvegarde de leurs données soit stockée sur place pour eux.
toutes les données de notre application sont stockées dans une seule base de données MS SQL. Au sommet de la hiérarchie" nous avons "Organisation". Cette organisation représente un client dans notre système. Chaque organisation possède de nombreuses tables/objets/données pour enfants. Chacun ayant des relations FK qui finissent finalement par "Organisation."
Il nous faut un moyen d'extraire un les données du client à partir de la base de données et les regrouper d'une manière ou d'une autre afin qu'elles puissent être téléchargées sur le site du client. De préférence dans une base de données SQL Express, SQLite ou access.
Par exemple: Organization -> Skill Area -> Program -> Target -> Target Data
sont toutes les tables du système. Chacun d'eux est relié au parent par un FK. Je dois obtenir toutes les données cibles, les cibles, les programmes et les domaines de compétences par organisation et exporter ces données.
Ne quelqu'un a des suggestions sur la façon de faire cela dans SQL Server, Un C# service, ou un 3-rd party tool?
j'ai besoin que cette solution soit facile à répliquer pour chaque client qui veut cette fonctionnalité "activée"
des Idées?
9 réponses
je suis un grand fan de l'utilisation de la messagerie pour propager des données en ce moment, donc voici une solution basée sur les messages qui permettra aux clients externes de garder une copie locale, synchronisée des données que vous fournissez sur le web.
l'architecture de base serait une liste en ligne, sécurisée par mot de passe et spécifique à l'Utilisateur des changements qui se sont produits dans le système. Du côté du serveur, cette liste serait ajoutée à chaque fois qu'il y aurait un changement à une entité qui est pertinente pour le client spécifique. Au client lancerait une application qui vérifie la liste des changements pour tout ce qu'il n'a pas encore reçu et les applique ensuite à sa base de données locale (dans l'ordre où ils se sont produits).
il y a un tas de façons différentes de faire le composant du système basé sur la liste, mais mon intuition est que vous seriez mieux d'utiliser quelque chose comme RSS pour faire ceci.
ci-Dessous est un scénario concret de la façon dont cela pourrait fonctionner:
- Un nouveau domaine de compétences est créé pour l'organisation "mon org"
- la compétence est ajoutée à la base de données centrale et associée au reccord" my org"
- un événement SkillAreaExists est également ajouté en même temps au RSS "my org" avec des données JSON ou XML spécifiant les propriétés du nouveau domaine de compétences
- un nouveau programme est ajouté au domaine de compétences qui vient d'être créé
- le programme est ajouté à la base de données centrale et associé au domaine de compétence
- Un Programme Existe event est également ajouté en même temps au RSS "my org" avec des données JSON ou XML spécifiant les propriétés du nouveau programme
- un événement SkillAreaHasProgram est également ajouté en même temps au RSS "my org" avec des données JSON ou XML spécifiant un identifiant pour le domaine de compétence et le programme
- l'agent client vérifie le flux RSS et voit les nouveaux messages et les traite dans l'ordre
- lorsque L'événement Skillareexists est traité, un nouveau domaine de compétences est ajouté le DB local
- lorsque L'événement ProgramExists est traité, un nouveau programme est ajouté à la base de données locale
- lorsque L'événement SkillAreaHasProgram est traité, le programme est lié au domaine de compétences
cette approche a tout un tas d'avantages par rapport à la réplication traditionnelle du point dans le temps.
- son en ligne, un consommateur de ce peut obtenir des mises à jour en temps réel si nécessaire
- la constance est maintenue par ordre, à tout moment dans le flux d'événements si vous arrêtez de recevoir des événements vous avez un DB local qui reflète avec précision le DB central comme à un moment donné dans le temps.
- Sa diff en fonction, vous avez seulement besoin de recevoir des modifications
- Son vérifiable, vous pouvez voir ce qui s'est passé réellement et pas seulement l'état actuel.
- son facilement récupérable, s'il y a un problème de cohérence des données, vous pouvez inverser la totalité de la base de données en rejouant le flux d'événements.
- il permet à plusieurs consommateurs, beaucoup de des copies individuelles des renseignements sur les clients peuvent exister et fonctionner de façon autonome.
nous avons eu beaucoup de succès avec ces techniques pour répliquer des données entre les sites, surtout quand elles ne sont que quelques fois en ligne.
bien qu'il y ait quelques solutions d'entreprise très intéressantes qui ont été suggérées, je pense que mon approche serait de développer un avion ancienne solution de sauvegarde programmée qui exporte simplement les données pour chaque organisation avec une procédure stockée ou juste un certain nombre de déclarations select.
Certes, vous devrez garder ceci à jour pendant que votre schéma de base de données change, mais si c'est une application de production, Je ne peux pas imaginer que cela se produise de façon très drastique.
il y en a nombre de technologies disponibles pour ce faire, que ce soit SSIS, un service windows personnalisé, ou même quelque chose d'aussi rudimentaire qu'une tâche programmée qui démarre une procédure stockée à partir de la ligne de commande.
Le format que vous choisissez à l'exportation est entièrement à vous, et devrait probablement être stimulée par la façon dont la sauvegarde est destinée à être utilisée. Je pourrais envisager d'écrire des données à un certain nombre de fichiers CSV et fermeture éclair le résultat de sorte qu'il pourrait être importé dans d'autres plates-formes si le besoin survenir.
D'autres options pourraient être de copier des données à travers une base de données scratch et ensuite créer simplement une sauvegarde SQL de cette base de données.
peu importe comment vous choisissez de procéder, je vous encourage à vous assurer que le processus est bien documenté et qu'il comporte autant d'installation et de configuration automatisées que possible. Les systèmes dont les dépendances sont faiblement couplées, comme les emplacements communs des fichiers ou les tâches programmées, ont tendance à être modifiés au fil du temps. Sans ces retouches et modifications enregistrées vous pouvez créer un système qui fonctionne mais ne peut pas être répliqué. Bientôt plus personne ne veut y toucher et personne ne se souvient exactement comment il fonctionne. Quand il a besoin de changer, ou pire, il casse, vous devez commencer la rétroingénierie avant de pouvoir le réparer.
dans un environnement basé sur le nuage, c'est particulièrement important parce que vous voulez être capable de vous déployer le plus rapidement possible. S'Il ya beaucoup de configuration qui doit être fait, vous êtes susceptible de faire des erreurs ou juste être incohérent. En créant un déploiement nuke-and-repave, vous disposez d'un point unique où vous pouvez changer l'installation et la configuration, en sachant que le changement sera cohérent dans tous les déploiements.
D'après ce que je comprends, vous avez une grande base de données pour tous les clients, vous utilisez des relations qui mènent à l'organisation de table pour savoir quelles données pour quel client, et vous voulez sauvegarder les données basées sur client => organisation.
Pour sauvegarder les données, vous pouvez utiliser l'une des méthodes suivantes:
comme les commentaires de @Phil, et @Kris vous pouvez utiliser SSIS pour la sauvegarde automatisée, Vérifiez ce lien pour la structure de sauvegarde, et vérifier cette lien pour comment exporter un résultat de requête vers un fichier en utilisant SSIS et au lieu de fichier de le faire à l'accès ou de base de données SQL Server.
construire une application\service en utilisant C# pour sélectionner les données et les exporter manuellement, besoin de temps, mais la personnalisation n'a pas de limites.
quand j'ai eu affaire à des sauvegardes de données relationnelles dans le passé (dans MySQL qui n'est pas très différent en termes de capacité de MSSQL que vous lancez) est de créer un fichier de sauvegarde "paquet" qui est essentiellement un fichier zip avec une extension de fichier différente afin que windows ne laissera pas les utilisateurs l'ouvrir.
si vous voulez vraiment obtenir Fantaisie, cryptez le fichier après fermeture éclair et changer l'extension. Je suppose que vous utilisez ASP pour vos SaaS et puisque je suis un intello PHP, Je ne peux pas aide trop avec le côté code des choses, mais la façon dont je l'ai géré avant était pour un script qui empaqueterait un site Joomla entier et la base de données pour la migration à un nouveau serveur.
//open the MySQL connection
$dbc = mysql_connect($cfg->host,$cfg->user,$cfg->password);
//select the database
mysql_select_db($cfg->db,$dbc);
output( 'Getting database tables
');
//get all the tables in the database
$tables = array();
$result = mysql_query('SHOW TABLES',$dbc);
while($row = mysql_fetch_row($result)) {
$tables[] = $row[0];
}
output( 'Found '.count($tables).' tables to be migrated.
Exporting tables:
');
$return = "";
//cycle through the tables and get their create statements and data
foreach($tables as $table) {
$result = mysql_query('SELECT * FROM '.$table);
$num_fields = mysql_num_fields($result);
$return.= 'DROP TABLE IF EXISTS '.$table.";\n";
$row2 = mysql_fetch_row(mysql_query('SHOW CREATE TABLE '.$table));
$return.= $row2[1].";\n";
while($row = mysql_fetch_row($result)) {
$return.= 'INSERT INTO '.$table.' VALUES(';
for($j=0; $j<$num_fields; $j++) {
$row[$j] = mysql_escape_string($row[$j]);
$row[$j] = ereg_replace("\n","\n",$row[$j]);
if (!empty($row[$j])) {
$return.= "'".$row[$j]."'" ;
} else {
$return.= "NULL";
}
if ($j<($num_fields-1)) {
$return.= ',';
}
}
$return.= ");\n";
}
}
C'est la partie pertinente du code en PHP qui boucle la structure de la base de données et stocke le script de récréation dans $result qui peut ensuite être produit dans un fichier.
dans votre cas, vous ne voulez pas recréer les bases de données, mais plutôt les données elles-mêmes. Vous avez aggravé la problème léger puisque vous avez un SaaS qui est sujet à des changements possibles de la structure des données que vous devrez être en mesure de rendre compte. Ma suggestion serait alors:
Utilisez un système similaire à celui ci-dessus pour vider les données pertinentes des tables individuelles. Je suis simplement en train de tirer toutes les données, mais vous pourriez tirer seulement les parties qui se rapportent à l'utilisateur individuel en utilisant des déclarations de jointure et ainsi de suite. Dump le contenu de chaque TABLE insert / replace des déclarations dans un fichier nommé d'après le table. Créez un fichier appelé manifeste.xml ou quelque chose de ce genre et le peupler avec la version actuelle de votre application SaaS, nom/information, ID unique, etc du client exportant les données.
empaqueter tous ces fichiers dans un fichier ZIP, changer l'extension à ce que vous voulez, le chiffrer si vous le souhaitez, etc. Laisse-les télécharger le fichier de sauvegarde et tu es prêt.
dans votre script d'importation, vous devrez lire le numéro de version des données exportées et comparer il à un algorithme qui peut gérer le remapping des données basées sur les révisions que vous faites plus tard. De cette façon, si vous avez besoin de ré-importer une de leurs sauvegardes plus tard, vous pouvez gérer correctement la transition des données à partir du moment où ils ont tiré la sauvegarde à la structure actuelle des données dans cette table maintenant.
j'espère que ça aide ;)
Parce que vous gardez toutes les données dans une seule base de données, il sera toujours difficile d'exportation/sauvegarde des données sur le client.
même si vous implémentez un tel scénario maintenant, vous finirez avec deux endroits différents dont vous avez besoin pour maintenir/modifier/tester chaque fois que vous modifiez le schéma de la base de données (correction de bogues, ajout de nouvelles fonctionnalités, optimisation, etc.).
je vous recommande de partager les données, disons, en utilisant une base de données par organisation. Puis vous changez votre application juste une fois (principalement autour de la construction d'une chaîne de connexion pour l'organisation spécifiée), et puis vous pouvez exporter/sauvegarder chaque base de données séparément en toute sécurité d'une manière que vous le voulez.
Il vous donne également beaucoup d'avantages supplémentaires "gratuitement" telles que l'évolutivité et la capacité de consacrer des ressources à chaque organisation de base (si elle est nécessaire dans le futur). Par exemple, vous avez un ensemble d'organisations de petite et de faible priorité (d'un point de vue commercial), et une grande et haute priorité. Si vous sera en mesure de garder un ensemble de petites bases de données de faible priorité sur un serveur, mais dédier un autre pour ce grand important spécifique. Ou si votre serveur DB actuel est surchargé (peut-être que vous avez beaucoup de données et beaucoup de requêtes dans la base de données), vous pouvez simplement obtenir un autre serveur bon marché et déplacer la moitié de la charge sans aucun changement dans votre système... Vous avez encore besoin d'écrire quelque chose afin de diviser la grande base de données existante en plusieurs petites, mais vous le faites juste une fois, et après il est fait cet "outil de migration" peut être jeté de sorte que vous n'avez plus besoin de le soutenir.
Avez-vous essayé Syncfram Framework? Jetez un oeil à article! Il explique comment synchroniser les données filtrées entre les bases de données en utilisant Sync Framework. Vous pouvez sync à la base de données du client ou sync à votre propre db vide et ensuite l'exporter en tant que Fichier.
avez-vous pensé à utiliser un ORM? (Objet Relational Mapper)
je sais, et l'utilisation, LLBLGen Pro (donc je ne peux parler que sur la fonction de cet ORM)
Quoi qu'il en soit, avec LLBLGen vous pouvez rétro-concevoir la base de données et créer une hiérarchie de classe qui mappent les tables et les relations de votre base de données.
maintenant si toutes les données d'un client sont accessibles via des relations, je peux dire à mon cadre ORM de charger un seul client (1 ligne d'une table spécifique) et ensuite, chargez toutes les données connexes dans la table correspondante.
si les données ne sont pas trop complexes, cela devrait être possible.
Si vous avez des centaines de tables auto-référencées ou des relations étranges, il peut être impossible, il dépend de vos données.
Si toutes les données d'un client unique est, disons, 10'000 lignes de 100 tableaux, il fonctionnera probablement.
Si toutes les données de est de 100 '000 lignes dans 1000 tableaux il "peut" travailler si vous avez quelques fois, et beaucoup de mémoire.
Si toutes les données sont 10'000'000 vous ne pouvez probablement pas charger tout à la fois, et vous aurez besoin d'un moyen plus efficace.
de toute façon, si vous pouvez charger toutes les données à la fois, alors vous aurez un bon graphique "en mémoire" avec toutes les données d'un seul client, et alors vous pouvez sérialiser ces données, ou les projeter sur un ensemble de données (obtenir un ensemble de données/relations) et ensuite sérialiser l'ensemble de données.
utilisation d'un ORM pour charger et exporter toutes les données d'un seul client comme expliqué, probablement, n'est pas la façon la plus efficace de faire les choses, mais quand faisable il est un moyen simple et bon marché.
Naturellement, avec ou sans ORM, vous pouvez trouver des centaines de différentes façon d'exporter ces données :-)
pour votre conception, vous auriez dû partager votre base de données pour les clients.
cependant, comme vous avez déjà développé le design de la base de données, je vous suggère de créer une base de données temp et de créer les nouvelles tables dans cette base de données temp en utilisant la relation FK.
pour cela, vous devez trier les tables en fonction de la relation FK et les créer dans la base de données temp.
ensuite, sélectionnez les données de la table de la base de données source et insérez-les dans le temp la base de données.
vous pouvez également utiliser cette technique pour shard votre base de données et de réorganiser votre conception de base de données.
Aravind