2016-07-07 1 views
1

Bon, laissez-moi commencer par dire que je sais que c'est bizarre. Je fais.Ecriture de toute la table SQL à chaque fois que les données changent sur un serveur Node (bizarre, donc fais avec moi)

Mais ici va:

Disons que j'ai une base de données SQL qui stocke mes données. Et disons que je n'ai pas le choix, ça doit être SQL. L'application que je construis a quelque part environ 100 000 enregistrements dans sa base de données, et une fois que chaque enregistrement a été traité par les utilisateurs de l'application, ils partent tous et sont envoyés à une autre application entièrement. Donc, pour une courte période de temps, cette application sera utilisée, puis cesse d'être utilisée jusqu'à la même heure l'année prochaine. Pendant l'utilisation de l'application, aucune source externe ne touchera la base de données. Lorsque le serveur (nœud) démarre, il charge tout de la base de données, dans un littéral d'objet sur le serveur

Le côté client de cette application, à un niveau très basique, effectue des requêtes (vers une API sur le serveur) pour les données, et envoie les versions mises à jour des enregistrements au serveur une fois qu'ils ont été traités. Donc voici où ça devient bizarre: Disons que je ne veux pas que l'application côté client doive récupérer directement les enregistrements de la base de données, et je ne veux pas qu'elle puisse écrire dessus. Ainsi, les données de la base de données entière existe déjà en mémoire sur le serveur. Il y a un module sur le serveur qui peut gérer la modification de la représentation de ces données (encore une fois, parce que l'application client n'interagit qu'avec les API sur le serveur, le module de base de données existe pour faciliter cela).

Plusieurs utilisateurs accèdent au système en même temps, mais en raison du fonctionnement du système, deux utilisateurs ne peuvent pas recevoir le même enregistrement, donc deux utilisateurs n'enverront jamais une mise à jour pour le même enregistrement (les enregistrements sont traités individuellement et séquentiellement). Donc, disons que j'ai décidé que, puisque je gérais déjà toutes ces données en mémoire sur le serveur, je voudrais simplement envoyer une version mise à jour des données actuelles, dans son intégralité, à la base de données, chaque l'heure a changé.

La question est, où est-ce que ce classement sur l'échelle folle?

Les performances, écrire une base de données entière plutôt que des enregistrements individuels, en souffriraient évidemment. Mais, dans une base de données qui est seulement lu d'une fois (au démarrage de l'application), est-ce même une préoccupation? Si toutes les opérations autres que «Écrire tous les éléments lorsque l'un des éléments change» se sont produites en mémoire sur le serveur, est-ce que la durée de ces mises à jour importe? Si une nouvelle mise à jour de la base de données intervient pendant sa mise à jour, SQL s'en chargera sûrement? Il semble que le correct pour ce faire, soit que chaque utilisateur obtienne directement ses informations de la base de données, et effectue directement des mises à jour de la base de données (ou au moins interagit avec les points de terminaison API) arriver), mais, est juste ... ne pas faire cela, la folie absolue? Comme je l'ai dit, je sais que c'est bizarre, mais à part le fait que "ça fait mal", je ne suis pas sûr d'être convaincu que c'est complètement faux. Donc j'ai pensé que cet endroit aurait une opinion.

La façon dont je pense qu'il travaille actuellement est:

[SQL DB] est mis à jour chaque fois qu'un changement se produit sur {en mémoire DB} {en mémoire DB} est mis à jour de différentes manières en fonction de l'API appels au serveur effectue des demandes de données et envoie des mises à jour aux données, toutes deux traitées sur le DB en mémoire

Plusieurs demandes peuvent se produire en même temps à partir de l'application, mais les utilisateurs multiples ne peuvent pas voir le même enregistrement, car les enregistrements sont attribués à un utilisateur donné avant d'être envoyés

Plusieurs mises à jour peuvent provenir de plusieurs utilisateurs, chacun aboutissant à la base de données SQL entière avec le contenu du DB en mémoire. (Note: Je ne dis pas "est-ce la meilleure façon de le faire." Je demande juste, y at-il un argument significatif pour se soucier de la performance d'une base de données en cours d'écriture, si ça ne va pas à lire de nouveau à moins que le serveur ait besoin d'être redémarré)

+0

Le problème que je vois est concurrency: disons que la réécriture de la base de données prend 5 minutes.Vous devrez rendre le gestionnaire d'api asynchrone pour empêcher le navigateur web du client de sortir - pas de problème, vraiment, mais que se passe-t-il quand Bob soumet son changement, et ensuite Sally, 1 minute plus tard? La demande de Bob est toujours occupée à écrire (tout le jeu de données, comme vous le disiez), et la requête de Sally veut faire la même chose: vous devrez bloquer (long timeout + transaction lock ou cheap-n-nasty avec un booléen et setTimeout) pour éviter l'incohérence des données – daf

+0

Et si vous bloquez tout correctement, en supposant toujours le temps de sauvegarde de 5 minutes, vous espérez évidemment que vous n'obtiendrez pas plus d'une requête par fenêtre de 5 minutes, en moyenne, pour le temps qu'il faut pour démonter votre service ou votre base de données. Aussi, tout en verrouillant et en attendant de pousser toute la base de données, vous courez le risque de perdre des changements d'utilisateurs - car les changements sont seulement en mémoire: si le service api meurt - les changements sont perdus. – daf

+0

Je suis un peu perdu avec ce que vous suggérez, mais il semble que vous disiez que vous avez un serveur Middleware qui charge la base de données SQL entière en mémoire. Le middleware est mis à jour/communiqué par les utilisateurs côté client. Et maintenant vous vous demandez si vous allez mettre à jour de manière incrémentielle le SQL par middleware ou simplement renvoyer l'intégralité du jeu de données à sql. Je suppose que quel serait l'avantage de ce dernier? Vous n'avez pas à faire de suivi des modifications?Vous aurez certainement un impact beaucoup plus important sur les performances de votre backbone réseau/matériel, serveur SQL .... – Matt

Répondre

1

Ce que je pense que je ferais, dans cette situation, est d'ajouter un attribut à chaque enregistrement mis en cache pour indiquer que l'enregistrement est "sale". En d'autres termes, quelque chose a été fait par quelqu'un, car il a été lu à l'origine dans la base de données.

(Vous pouvez également ajouter un attribut qui indique que quelqu'un "a cet enregistrement particulier", de sorte que vous pouvez être sûr que les deux utilisateurs ne mettent pas à jour le même enregistrement en même temps.) À un moment opportun, vous pouvez ensuite parcourir la collection, en reportant les enregistrements «sales» dans la base de données. Utilisez une transaction SQL, non seulement pour l'efficacité, mais aussi pour être sûr que la mise à jour finale de la base de données est atomique.

Vous devez être très attentif à la possibilité de conditions de course. Une stratégie possible consiste à utiliser un horodatage Unix comme indicateur "sale". Un enregistrement est sélectionné pour être publié dans la base de données uniquement si son "temps de saturation" est supérieur ou égal à l'horodatage lors de la dernière exécution du processus de validation.

(Et, PS: « non, je l'ai même vu des choses « plus étranges » que cela, dans toutes mes années folles dans cette affaire folle ...)

+0

Merci pour cela - J'ai déjà un attribut qui enregistre qui a chaque enregistrement extrait, de sorte que ce côté est déjà en place. Mais oui, je peux voir que votre suggestion de mettre à jour régulièrement la dernière série de disques "sales" est beaucoup plus sensée que mon approche "cavalière". : D Encore une fois, je ne pensais pas que c'était une bonne idée, je voulais juste une clarification sur le niveau d'une mauvaise idée. Vous n'êtes peut-être pas surpris d'apprendre que je n'ai pas exactement des dizaines d'années d'expérience avec les bases de données. : D Merci beaucoup. :) – Nimmo

+0

* Meh ... * "Qui est-ce que nous sommes tous * vraiment bons * à faire semblant!" **; -) ** Oui, le remplacement total * est * "une très mauvaise idée". –

+0

Maintenant, * une autre * idée, que vous pourriez vouloir percoler parmi les cellules grises de votre cranium, est celle-ci: au lieu de charger "la base de données damnée" en mémoire au démarrage du programme, vous récupérez plutôt les enregistrements * *à la demande**. Commencez avec un hash * vide *. Chaque fois que l'utilisateur demande un enregistrement qui n'est pas encore en mémoire, allez le chercher et ajoutez-le au hachage. –