![]() |
Datenbank: SQL-Server • Version: 2016-2022 • Zugriff über: ADO
Hunderte Clients im Sekundentakt über gesperrte Datensätze informieren
Man stelle sich vor: Ein Kunde möchte, dass bis zu 100 Anwender gleichzeitig Datensätze in derselben Tabelle bearbeiten sollen. Jeder Datensatz muss aber nur einmal bearbeitet werden. Es gibt keinerlei Zuständigkeiten; jeder der 100 Anwender bearbeitet diejenigen Datensätze, die er möchte. So, dass am Ende jeder Datensatz einmal bearbeitet wurde.
Klingt verrückt? Ja klar! Aber: Was der Kunde will… Wenn man jetzt jeden Datensatz vor der Bearbeitung auf eine Sperre testen würde, würde das viel zu lange dauern. Ich habe daher dran gedacht, den aktuellen Bearbeitungsstatus sekündlich zu aktualisieren und die Datensätze, die gerade bearbeitet werden oder schon bearbeitet wurden farblich zu kennzeichnen. Wenn jeder der 100 Anwender jedoch sekündlich den SQL-Server nach dem Status aller Datensätze (bis zu 10000) befragen würde, ginge dieser wohl ganz schnell in die Knie. Wenn jedoch ein Anwender sekündlich den SQL-Server abfragt und das Ergebnis übers Netzwerk an die anderen 99 Anwender broadcastet, könnte das funktionieren. Oder jeder Anwender broadcastet seine aktuellen Änderungen an die anderen… Vielleicht gibts ja dafür auch noch ganz andere Methoden, die mir gerade nicht einfallen. Nach Möglichkeit soll kein neuer Server aufgesetzt werden. Eine gezielte oder zufällige Aufteilung der Datensätze an die 100 Anwender ist keine Option. Das machen wir schon seit 20 Jahren so. Jetzt soll was ganz Neues her :-) |
AW: Hunderte Clients im Sekundentakt über gesperrte Datensätze informieren
Also mich müsste man schon noch davon überzeugen, dass diese Vorgehensweise später für die Anwender überhaupt sinnvoll ist, bevor ich mir über die Umsetzung Gedanken mache.
Mal davon abgesehen, wäre eine sekündliche Abfrage der Datenbank kaum die richtige Lösung. Entweder man lässt sich von der Datenbank über Änderungen informieren (z.B. bei Interbase mit Events) oder schaltet einen Message-Broker dazwischen. Das bedingt dann aber natürlich einen weiteren Server bzw. Dienst wie Redis, RabbitMQ oder ähnliches. Oder man verbindet gar nicht direkt mit der Datenbank sondern setzt einen Server-Dienst mit Delphi auf (Rest mit JSON-Daten) und integriert hier ein Realtime-Messaging für alle aktiven Anwender z.B. über Websockets. Das kann ja auch ganz spannend werden bei der Umsetzung, aber wenn man jetzt dem Kunden vorrechnet, dass die Lösung deutlich aufwendiger und damit teurer wird als das gezielte Zuweisen der Datensätze an die Anwender, wird es vielleicht doch die einfachere Lösung :-D |
AW: Hunderte Clients im Sekundentakt über gesperrte Datensätze informieren
Jeder bearbeitet doch gleichzeitig nur einen Datensatz.
Zu Beginn würde dann eine Sperre gesetzt und wenn jemand Anderes will, wird beim "neuen" Sperren eine Fehlermeldung "besetzt" geworfen. Nur einmal beim Arbeitsbeginn die Liste laden und vielleicht alle Minuten manuell/automatisch refreshen. Alternativ: Mitarbeiter sagt "gib mir einen Datensatz" und eine Arbrage holt einfach den nächsten Freien und sperrt ihn gleichzeitig. Wenn fertig, wieder "gib mir einen Datensatz" und ... Da muß kein Mitarbeiter wissen/sehen, was es sonst noch gibt ... mit den gesperrten (in Arbeit) Datensätzen kann er ja sowieso nix anfangen. |
AW: Hunderte Clients im Sekundentakt über gesperrte Datensätze informieren
Zitat:
|
AW: Hunderte Clients im Sekundentakt über gesperrte Datensätze informieren
Zitat:
|
AW: Hunderte Clients im Sekundentakt über gesperrte Datensätze informieren
Zitat:
Zitat:
* entweder es gibt direkt in der Tabelle ein Feld mit der MitarbeiterID, welcher das aktuell gesperrt hat. (eventuell noch ein Feld mit der Zeit, oder ein allgemeines LastModified-Feld für den ganzen Datensatz, um zu langandauernde Sperren finden oder beseitigen zu können) * oder es gibt eine weitere Tablle mit DatensatzID, Mitarbeiter ID und vielleicht noch der Zeit ... einmal ist ein Index für den Zugriff schnell und dann gibt es sowieso nicht zu viele Datensätze (maximal je Einen, für die 100 Mitarbeiter) * oder auch, wenn man Lockingmechanismen der DB verwendet, wird sich das zeitlich kaum unterscheiden Und sekündlich ist eh ein Schwachsinn. erstmal brauchen nur die paar Mitarbeiter diese Liste, welche grade eben nach dem nächsten Datensatz suchen (die meiste Zeit werden sie doch wohl hoffentlich an den Datensätzen arbeiten) und selbst dann muß es nicht so oft aktualisiert werden ... NIEMAND liest die komplette Liste in einer Sekunde und wählt umgehend was aus * einmal zu Beginn des Guckens und dann z.B. alle 30, 60 oder vielleicht über 100 Sekunden * und falls doch eher, dann manuell auf Refresh klicken Mich würde es auch extrems nerven, wenn ich was anklicken will und es ständig unter der Maus wegrennt, weil die Liste dauernd aktualisiert wird und sich was verschieben kann. Dann doch lieber seltener aktualisieren und beim Auswählen ein "ohh, jemand war schneller ... nimm was Anderes" (vielleicht gleich ein/einige automatischer alternativer Vorschlag im Dialog, um schnell "nehm ich" sagen zu können) |
AW: Hunderte Clients im Sekundentakt über gesperrte Datensätze informieren
Jeder bekommt aus der allen Datensätzen einen bestimmten Anteil zugewiesen. Diese Datensätze hat sonst Niemand zur Verfügung. Dabei wird nicht die gesamte Menge aufgeteilt, wodurch Spätbeginner immer noch freie Datensätze bekommen können.
Aus diesem Kontingent kann dann ausgewählt, was man will. Ist alles abgearbeitet, kann ein Refresh für den nächsten Block an Datensätzen gemacht werden. Oder man macht ein Refresh, wenn keine Datensätze mehr da sind, die man bearbeiten möchte. Eventuell steuert man die Anteile noch über die Anzahl der angemeldeten Benutzer. Außerdem muss noch berücksichtigt werden, dass wegen der Verteilungskriterien kein unbearbeiteter Rest übrig bleibt. Alternativ wählt der Anwender vorher aus, welche Datensätze er bearbeiten möchte. Diese sind dann für die anderen für deren Vorauswahl gesperrt, bzw. werden gar nicht erst angezeigt. Hierbei muss berücksichtigt werden, dass es bei der Vorauswahl zeitlich Überschneidungen geben kann. Dies muss bei der anschließenden Zuweisung berücksichtigt werden. Selbst wenn man jede Sekunde prüfen würde, ist damit nicht sichergestellt, dass es Überschneidungen geben kann. Man wäre trotzdem darauf angewiesen vor der Bearbeitung eine Prüfung durchzuführen, ob der Datensatz gesperrt/schon bearbeitet wurde. |
AW: Hunderte Clients im Sekundentakt über gesperrte Datensätze informieren
Vielen Dank für eure Vorschläge. Wir sind uns wahrscheinlich alle einig, dass die Vorgaben ziemlich bescheuert sind. Daran ist aber nicht zu rütteln. Alle Anwender sollen gleichzeitig die Auswahl aus allen Datensätzen haben, sofern die Datensätze nicht schon bearbeitet wurden oder gerade durch einen anderen Anwender bearbeitet werden. Es soll keine Vorauswahl oder Zuteilung an die Anwender erfolgen.
Damit die Datensätze nicht unter der Maus „verschwinden“ war meine Idee, die Datensätze, die gerade von anderen Anwendern bearbeitet werden/wurden farblich zu kennzeichnen und für diese Datensätze die Bearbeitungsfunktionen zu deaktivieren - natürlich ist das nicht 100%ig. Daher suchte ich eine technische Möglichkeit, eine Liste mit allen „gesperrten“ Datensatz-IDs möglichst häufig (sekündlich) an alle Clients zu verteilen. Falls noch jemand Idee zur technischen Umsetzung hat… Wie gesagt: An den Vorgaben ist leider nicht zu rütteln; manche Geschäftsleitungen sind einfach beratungsresistent. Im Zweifel sage ich denen einfach ab - hab auch so genug zu tun :-) |
AW: Hunderte Clients im Sekundentakt über gesperrte Datensätze informieren
Sind die Clients alle im gleichen Netz - dann wären udp broadcasts vielleicht eine Möglichkeit.
Grüße Klaus |
AW: Hunderte Clients im Sekundentakt über gesperrte Datensätze informieren
Moin,
für unseren Kalender/Ressourcenplaner gab es ähnliche Anforderungen. Es sollte vernmieden werden, dass 2 Leute gleichzeitig einen Datensatz bearbeiten. Änderungen sollen sofort für alle Clients sichtbar sein. Gelöst haben wir das vor Jahren über einen ChatServer. Alle Clients sind Mitglieder des Chats. Änderungen/Locks (Datensatz ID/Status) werden in die Datenbank geschrieben und im Chat publiziert. Jeder Client prüft für sich, ob ein Refresh der aktuellen Ansicht nötig ist. Unmittelbar vor dem Bearbeiten eines Datensatzes wird noch einmal geprüft, ob er eventuell gesperrt ist (DB-Abfrage) und ggf. eine Meldung angezeigt. Anstelle eines Chatserver kann man das heute wohl eleganter lösen, aber das Prinzip sollte das gleiche sein ;) |
AW: Hunderte Clients im Sekundentakt über gesperrte Datensätze informieren
Muss die Anzeige denn tatsächlich so aktuell sein? Unabhängig davon wie oft Du die Anzeige aktualisierst ist sie wie Du auch schreibst nie 100%-ig aktuell. Dann brauchst Du also sowieso eine Routine, die prüft, ob der gewählte Datensatz noch zu bearbeiten ist.
Also: - Komplette Liste der noch zu bearbeitenden Datensätze wird angezeigt - Der Anwender wählt einen Datensatz zur Bearbeitung - Das Programm prüft, ob der inzwischen gesperrt ist oder schon bearbeitet wurde - Der Datensatz wird gesperrt und nach der Bearbeitung z.B. mit Änderungsdatum gekennzeichnet - Die Liste wird neu geladen Optional kann der Anwender die Liste auch manuell neu laden. Am besten sortiert man die Liste zufällig, damit nicht alle Anwender oben anfangen und sich um die ersten Datensätze streiten. Wenn es unbedingt sein muss, kannst Du natürlich trotzdem regelmässig mit einer separaten Abfrage ermitteln, welche Datensätze gesperrt oder bereits bearbeitet wurden. Wenn es ein Datumsfeld dafür gibt (Letzte Änderung) kannst Du gezielt nur die abfragen, die sich seit dem letzten Abruf geändert haben. Die Haupttabelle wird dann neu gezeichnet und dabei - wenn der Datensatz auch in der Änderungstabelle existiert - eingefärbt. Nach einer Bearbeitung durch den Anwender lädst Du automatisch neu, so dass er jetzt nur noch die Unbearbeiteten sieht. Eine Abfrage jede Sekunde ist dabei doch wahrscheinlich gar nicht notwendig solange es kein Wettbewerb ist und die Anwender alle gleichzeitig auf die Daten losgelassen werden und sich um "die besten Datensätze" streiten. Ansonsten eben einen Messagebroker einsetzen (als Ersatz für das Chattool, das rapante erwähnte) Oder wie Du schon schreibst, den Auftrag nicht annehmen, wenn man nicht davon überzeugt ist. |
AW: Hunderte Clients im Sekundentakt über gesperrte Datensätze informieren
Zitat:
|
AW: Hunderte Clients im Sekundentakt über gesperrte Datensätze informieren
Wenn jeder Anwender jeden Datensatz bearbeiten kann, dann lass sie das doch einfach machen. Beim Schreiben der Änderung in die DB kannst du ja mit einer WHERE-Klausel, die alle (relevanten) vorigen Werte enthält, sicherstellen, dass der Datensatz noch unverändert ist. Falls dem nicht so ist, ändert das UPDATE nichts und du kannst das ja dem Anwender mitteilen.
Bei FireDAC kann man das weitegehend automatisieren in dem in der Query bei UpdateOptions.UpdateMode das upWhereAll oder upWhereChanged einstellt. |
AW: Hunderte Clients im Sekundentakt über gesperrte Datensätze informieren
Zitat:
Da man ja auch einfach nur so durch eine solche Liste scrollen kann, um sich vielleicht die besten Einträge rauszusuchen, wollte ich die Auswahl des Datensatzes noch nicht in die DB schreiben sondern die ID des Datensatzes nur auf die Sperrliste nehmen und schnellstmöglich an alle anderen Anwender verteilen. |
AW: Hunderte Clients im Sekundentakt über gesperrte Datensätze informieren
Zitat:
|
AW: Hunderte Clients im Sekundentakt über gesperrte Datensätze informieren
Zitat:
|
AW: Hunderte Clients im Sekundentakt über gesperrte Datensätze informieren
Würde es nicht reichen, die Sperrung beim Versuch, den Datensatz zu bearbeiten, zu überprüfen?
Es mag vielleicht von dem konkreten Anwendungsfall abhängen, aber ich finde eine Live-Aktualisierung der aktuellen Sperrungen im Sekundentakt schon etwas übertrieben. |
AW: Hunderte Clients im Sekundentakt über gesperrte Datensätze informieren
Zitat:
|
AW: Hunderte Clients im Sekundentakt über gesperrte Datensätze informieren
Zitat:
Es geht bei den Aktualisierungsinformationen auch wirklich nur um die IDs der gesperrten Datensätze; was ein anderer Anwender mit dem Datensatz gemacht hat, ist völlig egal und muss auch nicht angezeigt werden. Nur eben der Status, dass dieser Datensatz nicht mehr bearbeitet werden kann. |
AW: Hunderte Clients im Sekundentakt über gesperrte Datensätze informieren
TL;DR;
Ich würde nicht versuchen die Tabelle selbst zu locken. Wäre es nicht denkbar mit einer zweiten, schnellen Lock-Tabelle zu arbeiten, bevor man dann die eigentliche Tabelle ändert? Der Erste, der da einen Record belegt setzt ein Flag mit Timestamp und der schnellere gewinnt. Wenn weitere den gleichen Record locken wollen, dann sollte es krachen. Danach kann man doch in aller Ruhe den Record bearbeiten. Zusätzlich könnte diese Lock-Tabelle eine Kopie des eigentlichen Records enthalten. Nach einer Änderung könnte man das dann wieder freigeben, indem man nur den Status auf READY ändert. Dann könnte ein anderer Prozess meinetwegen regelmäßg drüberlaufen und alle die READY sind abschliessen und zum Zielrecord übertragen. So würde keiner direkt auf der Ziel-Tabelle arbeiten, sondern immer nur über die "Shadow"-Tabelle, die nach einer Bearbeitung sich selbst aufräumen kann. Das Ganze könnte man noch mit StoredProcedures und Transactions garnieren. Ist es vielleicht sowas, was Dein Kunde sucht? |
AW: Hunderte Clients im Sekundentakt über gesperrte Datensätze informieren
Zitat:
|
AW: Hunderte Clients im Sekundentakt über gesperrte Datensätze informieren
Gerade viel mir ein, dass ich vor ca. 20 Jahren ein ähnliches Problem hatte.
Meine damalige Lösung: Sobald ein Datensatz gespeichert wird, wird die gesamte Liste aktualisiert und bearbeitete Datensätze hatten eine Markierung. Die Anwender konnten über einen Schalter auch die erledigten Datensätze ausblenden. Natürlich war der zuletzt bearbeitete Datensatz immer noch selektiert, damit man nicht wieder alles durchblättern musste. Der wesentliche Vorteil war, dass nach dem Refresh auf jeden Fall der aktuellste Stand verfügbar war und ein ständige Aktualisierung entfallen konnte. |
AW: Hunderte Clients im Sekundentakt über gesperrte Datensätze informieren
Das ist ein "Pick from the Rest" Verfahren.
Gibt es bei Maschinenzuordnungen, wo sich n Maschinen aus einem Stückpool sich was zur Bearbeitung picken und die Restmenge angezeigt wird. Wie wäre es damit: Neue Transaktionstabelle erstellen. Inhalt: REC ID In Process by User Start Date/Time (zur Deadlock Erkennung) HeaderEintrag, z.B. mit RecID -1 für den letzten Änderungseintrag. Das kann man mit wenig Zeitaufwend sekündlich abfragen (select ProcessingUser from Picklist where TargetID = -1). Ändert sich der Wert, kann man die Liste neu abrufen. Bei neuem Änderungsdurchlauf alle Datensatz IDs in diese Tabelle laden. Einer der Mitarbeiter pickt sich was raus. Alle anderen sehen den Rest (select * from picklist where ProcessingUser = NIL) Ist die Bearbeitung abgeschlossen, wird der Eintag aus der Tabelle gelöscht. Dadurch wird die Liste immer kürzer und es muss immer weniger geprüft, übertrag, etc. werden. |
AW: Hunderte Clients im Sekundentakt über gesperrte Datensätze informieren
achtung, langer text, vorn ein paar Erfahrungen, weiter hinten ein paar konkrete Vorschläge
Basierend auf Erfahrungen von einem vor langer Zeit von uns erstellten Projekt für einen sehr großen Konzern, bei dem 6 s2m isdn Karten mit je 30 isdn Kanälen gesteuert werden mussten und die vorherige Lösung (die nicht von uns kam) eine komplette Fehlkonstruktion war: Es ging um die Umsetzung einer callbox, sozusagen ein Anrufbeantworter, nur umgekehrt, der nahm keine Anrufe an, sondern musste einen freien der 180 isdn Kanäle auswählen und diesem dann eine passende Sounddatei vorspielen. Im Protokoll sollte dann enthalten sein, ob der Angerufene abgehoben hat, wie lange der Call aktiv war und noch ein paar andere Metadaten. Wenn abgehoben, dann wird der nicht wieder angerufen. Wenn nicht wird es je nach Auftrag nach x Minuten noch mal versucht. Was war das Problem der vorherigen Lösung: Ein Programmierer des Konzerns hatte dafür eine C++-Anwendung geschrieben, die Daten aus einer Postgres-Datenbank bekam und sich dort per random einen Call aus der Call Tabelle holte, versuchte diesen zu sperren, diesen auf dem isdn kanal zu verarbeiten und dann nach Durchführung die Metadaten zurück in die Datenbank zu schreiben. Auch nicht erfolgreiche sperren wurden versucht, in die datenbank zu schreiben. Das ganze System sollte ausgelegt werden für 50000 ausgehende Anrufe pro Tag und als Zeitraum war nur zwischen 08:00 und 20:00 wochentags erlaubt, also ein halber Tag. Das der gesamte Tag 86400 Sekunden hat, wissen die meisten von uns, es bleiben also nur 43200 Sekunden für 50000 Anrufe, also weniger als eine Sekunde pro Anruf, die aber leider inkl. der tüdelüt Melodie am anfang und am ende alle zwischen 25 und 35 sekunden braucht. Typischer Inhalt: Wir haben ihren auftrag erhalten und bearbeiten den so schnell wie möglich, ... Die Auftragsdaten kamen in die Datenbank von einer Konzern SAP Schnittstelle, an die der Inhalt der o.a. Metadaten dann später auch zurückgehen sollte. Was war das Problem der gewählten Anwendung c++? Der client wurde auf dem master control server in der anzahl der verfügbaren kanäle gestartet, also liefen ca 180 parallel laufende executables auf einer linux maschine, die schon ziemlichen dampf hatte. Wenn die nix machen wäre das auch kein problem. Gleichzeitig lief dort aber auch die Postgres Datenbank, mit der sich alle clients verbunden haben. Wenn ein call rausging, sorgte die executable dafür, das der s2m controller server, auf dessen kanal der Client konfiguriert war, dieser das dann erledigen sollte. Die s2m hardware einsteckkarte war auch wohl high end, dir hatten davon eine im office, angeblicher wert ca 10000 € (wir hatten zwar keinen s2m anschluss, aber für die programmierung ging das mit der karte in einem Simulationsmodus ganz gut und beim endkunden hatten wir zugriff auf eine reale maschine mit realen s2m). Um nicht zu weit auszuholen: die vorherige Anwendung war nach dem Serverstart innerhalb von 30-45 minuten je nach anzahl der Aufträge als Datenbank nicht mehr erreichbar, weil alle clients wie bekloppt immer die gesamten auftragsmenge runtergeladen habe, sich im client per random einen ausgesucht haben und den dann versuchten zu sperren. Das führte bei der Konstellation beim vorherigen Entwickler mit 50 Aufträgen und gerade mal 10 aktiven isdn kanälen zu ganz guten ergebnissen im testbetrieb, so das man damit versuchte, das System scharf zu schalten. Der reale Dateneingang, der auch schon bescheiden programmiert war, sorgte aber mit allen aktiven 180 Kanal executables dafür, das nicht mal mehr simple sql befehle vom postgres server innerhalb akzeptabler zeit beantwortet wurden (auch nach 60 minuten kam das zeitweise keine antwort). Das System lief komplett amok und wurde dafür dann wohl sogar in der Presse bekannt, das es eine Arztpraxis 24 Stunden am Tag ca alle 3-5 Minuten angerufen hat und egal, ob die abgenommen haben oder nicht, danach wieder angerufen wurde. Das ging wohl mehrere Tage so, obwohl angeblich die Daten aus dem System entfernt wurden. Da es auch ncoh die Notrufnummer dieser Arztpraxis war, konnte man die auch nicht so einfach abschalten. Man entschied sich dann nach dem Prssebericht in dem Konzern, die Lösung komplett abzuschalten, weil die auch nach mehreren reboots aller beteiligten Systeme der unkontrollierbare Amoklauf erneut losging. Die Technik (serverhardware) war auf jeden fall nicht schuld und als wir dann mit dem damaligen Projektleiter, zu dem wir im Rahmen eines anderen Projekts schon einen sehr guten Kontakt hatten, zu einer gemeinsamen Analyse des vorhandenen Systems eingeladen wurden, konnte ich mir mehrfach das schmunzeln nicht verkneifen. Alle Clients holten sich im Sekundentakt immer alle Aufträge in den eigenen Speicher von der Datenbank, es gab ein optimistisches locking, d.h. ob ein auftrag evtl schon von jemand gesperrt war oder nicht war dem client nicht bekannt, er versuchte einfach einen lock auf einen auftrag mit einem update. wenn der klappt, legte der los usw. Wenn der aber nicht klappt weil schon von jemand anders gesperrt solte der client sich die auftragsliste noch mal neu und es ging von vorne los (ohne in irgnedeiner art einen timeout zu haben). Ihr ahnt es, wenn 10000 calls in der Auftragsliste sind, ist für alle genug frei, zufällig was zu erwischen, was frei ist. wenn aber nur 20 oder 30 calls drin sind, laufen ca 150 von 180 clients komplett amok und bringen jede datenbank an die Belastungsgrenze oder wie in diesem Fall deutlich darüber hinaus. Wir haben das dann so gemacht, das wir statt postgres firebird genommen haben, weil wir uns damit besser auskennen und direkt mit einem eintrag eines neuen callauftrags von der sap schnittstelle sorgte ein trigger auf dem server dafür, das dieser schon einem kanal zugeordnet wird, der den abarbeiten soll. python scripte auf den servern mit dem s2m karten, für die es dafür saubere apis gab, holten sich immer nur den jeweils obersten eintrag aus der firebird db aus seiner kanal queue, vermerkt diesen einen datensatz mit einem Insert in eine andere Tabelle als "in arbeit" (also kein update auf dem record selbst), arbeitet den ab und verschiebt den nach ausführung in eine andere tabelle und trägt die metadaten in der job ausführungstabelle per insert nach. Wenn nix in seiner queue ist macht der client auch nix und wartet 10 sekunden. Wenn was gerade abgearbeitet wurde, wartet der aber nicht, sondern holt sich den nächsten call sofort. Wenn keiner da ist, dann eben wieder warten. inserts sind immer pflegeleichter für multithreaded datenbanken, weil die nix sperren müssen im gegenatz zu updates. Eine Datensatzsperre muss nicht zwingend das sein, was die Datenbank dafür fordert (so was wie in firebird zB mit "select ... for update" oder direkter update), weil das hässliche nebeneffekte haben kann, wie zum Beispiel erforderliche langlaufende Transaktionen für die dauer der sperre. Eine extra lock tabelle, die von dir selber erstellt wird mit unique pk von der datentabelle und timestamp/user/ip/connection id/was auch immer kannst du auch extra selber erstellen und via trigger dafür sorgen, das echte updates auf der eigentlichen Tabelle nur dann erlaubt sind, wenn zu den metadaten vom aktuellen client die in der lock tabelle übereinstimmen. So kann ein Lock auch mal minuten, stunden oder sogar tage gültig sein, ohne irgendwas blockierendes machen zu müssen wie transaktionen lang offen halten. Und ganz nebenbei kannst du darüber dann auch gleich anzeigen, wer was gerade gelockt hat und seit wann und wenn das gewünscht ist kann ein andere client einen fremden lock übernehmen oder löschen. Wenn eine Queue größer wird und warum auch immer nicht sauber abgearbeitet wird (s2m server reboot oder kaputt zB) dann wird der inhalt von seiner queue von einem server prozess, der als sp implementiert war, auf andere aktive queues verschieben, sofern die noch keine exec job log eintrag haben. Die Architektur was also eigentlich zentral von der firebird db gesteuert und nicht zufallsbedingt von hunderten Clients, die sich alle gegenseitig dauernd blockieren. Mich erinnerte die Anforderung deines Kunden sehr stark an die Programmierung, die unser Vorgänger da verbrochen hat. Hundert Clients wühlen sich durch die Daten, sucht sich irgendwas nach Lust und Laune zufällig aus, sperren das dann mit updates usw. Die Realität selbst in sehr großen Callcentern, die sich solche Forderungen gerne mal ausdenken, kann man oft in entsprechende Bahnen lenken, in dem man ähnlich wie den o.a. isdn kanälen automatische serverbasierende regeln hinterlegt, weil es auch keinerlei sinn ergibt, das sich 100 call center agents auf dem Screen alle die ersten 50 aktiven datensätze anglotzen, um dann irgendwas anzuklicken, was jemand anders aber vielleicht auch schon gemacht hat. 50 records im sekundentakt sind im durchschnitt 20ms zeit pro record. Es wäre kompletter Unsinn, die Arbeitszeit da von hunderten Mitarbeitern zu verplempern, in dem hunderte den selben kram auf dem screen sehen, von denen mit sehr hoher wahrscheinlichkeit schon alles gesperrt ist, wenn das dann auch ncoh wild herumflackert wird es noch verrückter. Clientbasierte filter, die tausende records vom server holen und erst lokal ausfiltern sind da auch ein NoGo in Enterpriseumgebungen. Mein tip also: versuch erst mal dem Kunden die Probleme seiner Idee zu verdeutlichen und versuch es gar nicht erst, das mit hunderten client executables zu implementieren, die das selber unkoordiniert für sich entscheiden. In der Firebird Welt wäre in meiner Umsetzung ein zentrales Regelwerk für die Queue Zuordnung automatisiert per trigger o.ä. zuständig und wenn ein client dann was für ihn relevantes neues sehen soll, wird der per event alterter benachrichtigt (zB weil sein username als eventname benutzt wird) und nur der, für den es was relevantes neues gibt, holt sich dann die notwendigen daten neu (zB nur die sperrmerkmale infos der für ihn relvanten records mit pk der zugehörigen daten,wie zum Beispiel adressen). alle schon bekannte daten kann man lokal vorhalten und muss nicht jedes mal den gesamten kram neu laden. Lade die die anzuzeigenden Daten nur dann neu wenn das erforderlich ist und trenne das ganz sauber vom laden der statusinfos, um zu wissen welchen status 10000 records haben brauchst du nichts anderes als die pks der daten mit dem zugehörigen pk des zustands. wenn da ein pk kommt, den dein client noch nicht kennt kann der die details dazu ja noch mal extra holen. und ganz wichtig: wenn der client keine lebenszeichen vom anwender erkennt, weil weder mousemove noch keypress erkannt wurde, muss man auch nichts in echtzeit aktualisieren, dann reicht auch refresh im minutentakt. wenn man das gut designt bekommt man mit brauchbarer Firebird Server Hardware ziemlich problemlos 5000 sqls pro Sekunde vom server beantwortet, auch weil der meiste kram im Rahmen von readonly Transaktionen geholt werden kann. wenn das nicht reicht kann man das über replikation auf mehrere Server verteilen, die dann je 5000 sqls pro sekunde können. dafür einen chatserver oder ähnliches dazwischen zu packen wäre für mich keinesfalls ein vorteil, die machen oft am ende noch dinge, die du dann gar nicht mehr unter kontrolle hast. versuch die relevanten infos vom datenbankserver auf das minimum einzuschränken,also mit sqls das zu holen oder zu senden was notwendig ist. Verlass dich nicht auf Komponenten, das die schon nur das machen was notwendig ist, das ist keineswegs der Fall (beispiel dataset recordcount, db lookup comboboxen und fields usw). über umsetzungen auf basis von ado/datasource/dataset/dbgrid usw wird dir das Projekt unter vollast sicherlich früher als später um die Ohren fliegen. Da sorgt oft der client serveseitig für deutlich mehr last als man denkt. da macht das auch keine unterschied ob es mssql oder firebird ist. Vielleicht sind in meinem langen post aber ja schon ein paar Anregungen für dich dabei, wenn dir der ganze text nicht zu lang war. p.s.: in dem o.a. Projekt, bei dem eigentlich 50000 calls als maximum pro Tag vorgesehen waren, fanden wir ca. 9 monate, nachdem das projekt live ging, aufgrund eines Streiks der Konzernmitarbeiter an einem Tag sogar 500000 calls, die da erfolgreich abgewickelt wurden. Da war man auf beiden seiten sehr froh, das selbst damit das von uns implementierte Gesamtsystem nicht überfordert war. |
AW: Hunderte Clients im Sekundentakt über gesperrte Datensätze informieren
Ich versuche mal eine kurze Zusammenfassung:
Stellen wir uns das mal praktisch vor: In einer Kiste liegen viele Teile, die ziemlich zügig und von vielen Mitarbeitern bearbeitet werden müssen. Ein Mitarbeiter nimmt sich ein Teil aus der Kiste um es zu bearbeiten. Und schon in diesem Augenblick muss feststehen (er sieht es ja auch), dass kein anderer Mitarbeiter dieses Teil in der Hand hat. Würde er es erst merken, wenn er das Teil in der Hand hält und müsste es dann zurücklegen, wäre wertvolle Arbeitszeit verschwendet worden. Daher müsste unsere Clientanwendung immer sehr zeitnah über Sperrungen informiert werden. Und das habe ich euch verschwiegen: Unsere Datenbanken laufen auf SQL-Servern, auf denen noch zahlreiche andere Datenbanken der Kunden laufen. Wenn jede Clientanwendung 1 x pro Sekunde die Sperr-Procedure abfragen würde, wären das locker 100 Abfragen pro Sekunden oder 6.000 pro Minute. Selbst wenn das hyper-performant wäre, würde der SQL-Admin schon bei der kleinsten Störung irgendeiner DB bei mir anrufen, weil auf unserer DB so viel Betrieb ist. Daher hatte mir die UDP-Broadcast-Idee ziemlich gut gefallen - wenn sie denn zuverlässig funktionieren würde. Damit gäbe es dann eine aktive Sperrbenachrichtigung und im Netzwerk würde sich nur etwas tun, wenn jemand tatsächlich arbeitet. Ansonsten wäre Funkstelle. Sieht so aus, als müsste man dann doch einen separaten TCP-Server oder so basteln, an dem sich alle Clients anmelden und aktiv über die Sperrungen benachrichtigt werden. Das scheint mir dann aber doch etwas zu aufwändig für so verrückte Kundenideen. Nochmals vielen Dank für eure Vorschläge. |
AW: Hunderte Clients im Sekundentakt über gesperrte Datensätze informieren
Zitat:
Wir machen es jetzt mal ganz anders, ist schnell gesagt.. Vielleicht sollte der Auftraggeber sich das noch mal in der Praxis vorstellen, bevor es ein teures Experiment wird. |
AW: Hunderte Clients im Sekundentakt über gesperrte Datensätze informieren
Mal so als Vorschlag ein Kompromiss:
Jeder Mitarbeiter bekommt eine eingeschränkte Zahl an Datensätzen angezeigt, die für ihn reserviert werden. Aus denen sucht er sich einen aus und in diesem Moment werden die restlichen wieder freigegeben. Ist er fertig, bekommt er wieder welche zur Auswahl. Das würde den Kundenwunsch berücksichtigen, verschwendet aber nicht so viel Arbeitszeit und Ressourcen, weil er nur z.B. 10 statt 10.000 Datensätzen zur Auswahl hat und ist technisch einfacher umzusetzen. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:07 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz