Tabelle sequentiell bzw unique lesen

Für Themen zu Datenbanken und Zugriff auf diese. Auch für Datenbankkomponenten.

Tabelle sequentiell bzw unique lesen

Beitragvon charlytango » 31. Okt 2017, 09:34 Tabelle sequentiell bzw unique lesen

Hi,

    Daten in einer MySQL Tabelle sollen abgearbeitet werden sollen.
    Die Reihenfolge der Bearbeitung muss nicht zwingend einer bestimmten Reihung folgen -- gelegentlich kann das aber auch nötig sein.
    Damit das schneller erfolgt sollen mehrere PCs/Programminstanzen/Clients daran arbeiten.
    Jeder Datensatz soll nur einmal bearbeitet werden.
    Das ganze soll auch performant sein
    edit: Clients sollen nach Bedarf zugeschaltet oder abgeschaltet werden können

Nun gibt es dazu die Möglichkeit einer Semaphordatei, die gesperrt wird solange die Abfrage eines Programms dauert. Die muss aber auf einem Netzwerklaufwerk liegen, was die Sache unelegant macht.

bisher habe ich folgende Strategie angewandt:
    Abfragen der nächsten 20 unbearbeiteten Datensätze
    zufälliges Auswählen eines Datensatzes aus den 20
    Versuch den ausgewählten Datensatz auf Rowlevel zu sperren
    falls das nicht klappt alles von vorne.

Das hat in der Vergangenheit ganz gut geklappt, allerdings kam es immer wie der zu Lockingproblemen und Timingproblemen.
Die (recht große) DB konnte nicht schnell genug 'liefern' was die Clients ins Timeout geschickt hat.

Frage:
Gibt es eine elegantere Lösung? z.B. eine Variante wie SELECT LAST_INSERT_ID() bei autoincrement Feldern ?
Trigger?
Stored Procedure?

Danke im voraus
Zuletzt geändert von charlytango am 31. Okt 2017, 10:08, insgesamt 1-mal geändert.
charlytango
 
Beiträge: 132
Registriert: 12. Sep 2015, 11:10
Wohnort: Wien
OS, Lazarus, FPC: Laz 1.8 | 
CPU-Target: Win 32Bit, 64bit
Nach oben

Beitragvon m.fuchs » 31. Okt 2017, 09:59 Re: Tabelle sequentiell bzw unique lesen

Wenn ich dein Problem richtig verstehe, würde ich es darüber lösen dass jeder Client nur einen bestimmten Bereich der Tabelle bearbeitet. Dann kommen die sich auch nicht ins Gehege und du musst nicht einzelne Datensätze sperren.
Bei zwei Clients zu Beispiel einer Datensätze mit ungerader, der andere gerader ID.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de
m.fuchs
 
Beiträge: 1971
Registriert: 22. Sep 2006, 18:32
Wohnort: Berlin
OS, Lazarus, FPC: Winux (L 1.8.4, FPC 3.0.4) | 
CPU-Target: x86, x64, arm
Nach oben

Beitragvon charlytango » 31. Okt 2017, 10:12 Re: Tabelle sequentiell bzw unique lesen

m.fuchs hat geschrieben:Bei zwei Clients zu Beispiel einer Datensätze mit ungerader, der andere gerader ID.


Danke, das bringt mich darauf dass ich die Angabe verbockt habe:
Clients sollen dynamisch zugeschaltet oder stillgelegt werden können ohne dass die Verteilung der Daten leidet.
Ich weiß vor dem Job also nicht wieviele Clients daran arbeiten werden und das ist über die Joblaufzeit auch nicht konstant.
charlytango
 
Beiträge: 132
Registriert: 12. Sep 2015, 11:10
Wohnort: Wien
OS, Lazarus, FPC: Laz 1.8 | 
CPU-Target: Win 32Bit, 64bit
Nach oben

Beitragvon m.fuchs » 31. Okt 2017, 10:17 Re: Tabelle sequentiell bzw unique lesen

Auch das wäre recht ähnlich möglich. Du unterteilst die Tabelle in Gruppen mit Datensätzen eines ID-Bereichs. (Beispiel: 1-100, 101-200, 201-300)

Jeder Client holt sich einen Bereich und sperrt diesen als in Bearbeitung. Wenn er fertig ist, markiert er den Bereich als fertig und sucht sich den nächsten freien. Du sperrst also nicht immer einen Datensatz sondern gleich 100.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de
m.fuchs
 
Beiträge: 1971
Registriert: 22. Sep 2006, 18:32
Wohnort: Berlin
OS, Lazarus, FPC: Winux (L 1.8.4, FPC 3.0.4) | 
CPU-Target: x86, x64, arm
Nach oben

Beitragvon Socke » 31. Okt 2017, 20:56 Re: Tabelle sequentiell bzw unique lesen

Nutzt du die Sperrung durch SELECT .. FOR UPDATE?

Du könntest neben der Datenbank einen eigenen Server zur Lastverteilung einrichten (gibt immer die ID des als nächsten zu bearbeitenden Datensatzes zurück); dieser muss dann natürlich neben der Datenbank laufen, damit die Clients arbeiten können.
Alternativ können die Daten auch auf Anwendungsebene durch ein entsprechendes Kennzeichen in der Datenbank gesperrt werden (ohne SELECT .. FOR UPDATE); die Sperrinformationen können dan aus Gründen der Performance in eine separate Tabelle ausgelagert werden.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
Socke
 
Beiträge: 2555
Registriert: 22. Jul 2008, 18:27
Wohnort: Köln
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 8.1/Debian GNU/Linux/Raspbian/openSUSE | 
CPU-Target: 32bit x86 armhf
Nach oben

Beitragvon charlytango » 2. Nov 2017, 15:09 Re: Tabelle sequentiell bzw unique lesen

Ein eigener Server oder Serverprozess als Lastverteiler wäre eher unpraktisch im gewünschten Szenario

ganz habe ich das trotzdem nicht verstanden...

könnte ich also mit
Code: Alles auswählen
SELECT top 1 WHERE.. FOR UPDATE
den einen Datensatz sperren der quasi der nächste ist ?
Wird dabei auch verhindert dass ihn gleichzeitig ein anderer Client anfordert?
Meine Gedanken kreisen weniger um das Blocken eines Datensatzes für andere. Das habe ich bislang mit drei Timestamps gemacht: Locked, InProgress, Ready

Damit kann ich auch Jobs identifizieren die während der Bearbeitung schief gegangen sind.

Ich mache mir eher Sorgen das zwei Clients die gleichen Daten versuchen zu sperren. Wie wird das von MySQL aufgelöst?
charlytango
 
Beiträge: 132
Registriert: 12. Sep 2015, 11:10
Wohnort: Wien
OS, Lazarus, FPC: Laz 1.8 | 
CPU-Target: Win 32Bit, 64bit
Nach oben

Beitragvon Socke » 2. Nov 2017, 16:34 Re: Tabelle sequentiell bzw unique lesen

charlytango hat geschrieben:könnte ich also mit
Code: Alles auswählen
SELECT top 1 WHERE.. FOR UPDATE
den einen Datensatz sperren der quasi der nächste ist ?
Wird dabei auch verhindert dass ihn gleichzeitig ein anderer Client anfordert?
Meine Gedanken kreisen weniger um das Blocken eines Datensatzes für andere. Das habe ich bislang mit drei Timestamps gemacht: Locked, InProgress, Ready

Damit kann ich auch Jobs identifizieren die während der Bearbeitung schief gegangen sind.

Ich mache mir eher Sorgen das zwei Clients die gleichen Daten versuchen zu sperren. Wie wird das von MySQL aufgelöst?

Da du bisher nichts von den Feldern geschrieben hattest, war ich mir unsicher, wie du die Sperren umsetzt. Was ist denn das Problem mit deinen Sperr-Feldern? Wenn die Aktualisierung der Sperrinformationen zu lange dauert (timeout), dann lager diese in eine eigene Tabelle aus (die dann optimaler Weise vollständige im Cache gehalten werden kann).

SELECT ... FOR UPDATE sperrt alle selektierten Datensätze bis zum Ende der Transaktion. Beendet ein Client die Verbindung (COMMIT oder ROLLBACK), werden die Sperren freigegeben und ein anderer Client kann die Datensätze sperren.
Solltest du mehrere Tabellen damit sperren, müssen diese immer in der gleichen Reihenfolge (1. Tabelle A, 2. Tabelle B usw.) in der gesamten Anwendung gesperrt werden um Deadlocks zu vermeiden.
Ein anderer Client kann den selben Datensatz gleichzeitig anfordern, muss dann aber warten bis der erste Client fertig ist. Die Auswahl des Datensatzes muss also wie bisher über die WHERE-Bedingung erfolgen.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
Socke
 
Beiträge: 2555
Registriert: 22. Jul 2008, 18:27
Wohnort: Köln
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 8.1/Debian GNU/Linux/Raspbian/openSUSE | 
CPU-Target: 32bit x86 armhf
Nach oben

• Themenende •

Zurück zu Datenbanken



Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 4 Gäste

porpoises-institution
accuracy-worried