Paralleler Schreibzugriff auf eine Datei ohne flock
opi
- perl
0 Christoph Schnauß0 opi0 Christoph Schnauß0 opi0 Christoph Schnauß0 opi
1 Christoph Zurnieden0 opi
Hallo zusammen,
ist ein paralleler Schreibzugriff auf eine Datei problemlos möglich?
Ich habe ca. 40-200 Prozesse, die sich in einer Datei registrieren
sollen. Die Datei hat einen strukturierten Aufbau:
--------------------------------------------------------------
| 30 Zeichen | 50 Zeichen | 6 Zeichen |
--------------------------------------------------------------
| Alias | verschiedene Parameter | Prozess ID |
--------------------------------------------------------------
Jeder Alias ist einzigartig.
Jeder Prozess soll seinen Eintrag in kurzen Intervallen aktualisieren.
Wenn der Prozess noch nicht existiert, dann hängt er sich mittels
O_APPEND hinten dran.
Nun möchte ich die Datei _nicht_ locken, damit es zu keinen Warte-
zuständen kommt. Kann die Datei fehlerhaft geschrieben werden, wenn
die Prozesse gleichzeit nur die Zeile aktualisieren, in der sie
registriert sind?
Worauf muss ich bei meinem Vorhaben insbesondere achten?
Für Hilfe wäre ich dankbar.
Greez,
opi
hallo,
ist ein paralleler Schreibzugriff auf eine Datei problemlos möglich?
Möglich ist es, aber nicht problemlos und auch nicht ratsam.
Kann die Datei fehlerhaft geschrieben werden, wenn
die Prozesse gleichzeit nur die Zeile aktualisieren, in der sie
registriert sind?
Genau das ist ist es meines Wissens, weshalb du keinen solchen "Verzicht" anstreben solltest. Der mögliche Zeitverlust, wenn die Prozesse aufeinander warten müssen, ist minimal.
Grüße aus Berlin
Christoph S.
Hallo,
hallo,
ist ein paralleler Schreibzugriff auf eine Datei problemlos möglich?
Möglich ist es, aber nicht problemlos und auch nicht ratsam.
Warum nicht problemlos? Was könnte passieren?
Kann die Datei fehlerhaft geschrieben werden, wenn
die Prozesse gleichzeit nur die Zeile aktualisieren, in der sie
registriert sind?Genau das ist es meines Wissens, weshalb du keinen solchen "Verzicht" anstreben solltest. Der mögliche Zeitverlust, wenn die Prozesse aufeinander warten müssen, ist minimal.
Ich habe das mal getestet und konnte keine Fehler entdecken, was
nicht heißt, dass es doch schief gehen könnte. Aber ich würde gerne
wissen was das sein könnte.
Mein Skript (parallel.pl):
#!/usr/bin/perl
use strict;
use warnings;
use Fcntl qw(:DEFAULT :flock);
my $arg = "@ARGV";
die "Usage: $0 <zeile x>\n" unless $arg =~ /^zeile \d$/;
for (my $i=0 ; $i < 1000000 ; $i++) {
my $uptime = <F> if open(F,'<',"/proc/uptime") or die $!;
$uptime =~ s/\..*$//;
chomp($uptime);
sysopen(FILE,"./testdatei",O_RDWR) or die $!;
my $index = [];
my $int = 0;
while (<FILE>) {
my $line = $_;
$index->[$int] = tell(FILE);
if ( $line =~ /^#/ ) {
$int++;
next;
}
(my $col1 = substr($line,0,10)) =~ s/\s+$//;
(my $col2 = substr($line,10,10)) =~ s/\s+$//;
(my $col3 = substr($line,20,10)) =~ s/\s+$//;
if ($col1 eq $arg) {
$int--;
$col2++;
seek(FILE,$index->[$int],0);
printf FILE '%-10s', $col1;
printf FILE '%-10s', $col2;
printf FILE '%-10s', $uptime;
last;
}
$int++;
}
close FILE;
}
Meine Datendatei (testdatei) vor dem Start:
#12345678901234567890123456789
zeile 1 0 uptime
zeile 2 0 uptime
zeile 3 0 uptime
zeile 4 0 uptime
zeile 5 0 uptime
So schaute die Datei beim Start aus.
Dann habe ich die Prozesse gestartet:
./parallel.pl zeile 1 &
./parallel.pl zeile 2 &
./parallel.pl zeile 3 &
./parallel.pl zeile 4 &
./parallel.pl zeile 5 &
Meine Datendatei danach:
#12345678901234567890123456789
zeile 1 1000000 21277
zeile 2 1000000 21319
zeile 3 1000000 21281
zeile 4 1000000 21333
zeile 5 1000000 21338
Greez,
opi
hallo,
ist ein paralleler Schreibzugriff auf eine Datei problemlos möglich?
Möglich ist es, aber nicht problemlos und auch nicht ratsam.
Warum nicht problemlos? Was könnte passieren?
Wenn zwei (oder mehr) Prozesse gleichzeitig schreibend auf ein und dieselbe Datei zugreifen, kann es passieren, daß sie ihre Eingaben gegenseitig überschreiben. flock soll genau das verhindern.
use Fcntl qw(:DEFAULT :flock);
Hier hast du zwar das richtige Modul angesprochen, aber im Script passiert dann nichts.
sysopen(FILE,"./testdatei",O_RDWR) or die $!;
Ups. Warum nimmst du sysopen?
Grüße aus Berlin
Christoph S.
Hallo Christoph,
Wenn zwei (oder mehr) Prozesse gleichzeitig schreibend auf ein und dieselbe Datei zugreifen, kann es passieren, daß sie ihre Eingaben gegenseitig überschreiben. flock soll genau das verhindern.
das kann ich nicht ganz nachvollziehen. Wie sollen sie sich
gegenseitig überschreiben, wenn sie völlig andere Zeilen bearbeiten
und sich beim überschreiben an feste Konventionen halten wie zum
Beispiel eine feste Spaltenlänge?
Datenbankprozesse warten auch nicht aufeinander, wenn sie 100 GB
große Datendateien bearbeiten. Oder doch?
use Fcntl qw(:DEFAULT :flock);
Hier hast du zwar das richtige Modul angesprochen, aber im Script passiert dann nichts.
Natürlich passiert was. Mittels sysopen wird die Datei ./testdatei
im Lese- und Schreibmodus mit O_RDWR geöffnet.
sysopen(FILE,"./testdatei",O_RDWR) or die $!;
Ups. Warum nimmst du sysopen?
Der Lockmechanismus kann nur einwandfrei funktionieren, wenn ich ihn
in all meinen Perlskripts einsetze. Hier locke ich zwar nichts, aber
es ist halt mein Standardmodul zum Öffnen von Dateien.
Greez,
opi
hallo,
Wenn zwei (oder mehr) Prozesse gleichzeitig schreibend auf ein und dieselbe Datei zugreifen, kann es passieren, daß sie ihre Eingaben gegenseitig überschreiben. flock soll genau das verhindern.
das kann ich nicht ganz nachvollziehen.
Auf einem Einzelrechner ist das auch kaum nachvollziehbar. Rufe mal dein Script über zwei verschiedene virtuelle hosts gleichzeitig auf, oder wenn du kannst, gleichzeitig über zwei oder mehrere Netzwerkrechner. Du könntest auch mal in SELFHTML nachlesen.
use Fcntl qw(:DEFAULT :flock);
Hier hast du zwar das richtige Modul angesprochen, aber im Script passiert dann nichts.
Natürlich passiert was. Mittels sysopen wird die Datei ./testdatei
im Lese- und Schreibmodus mit O_RDWR geöffnet.
Das war nicht gemeint. Du hast kein LOCK im Script stehen.
Der Lockmechanismus kann nur einwandfrei funktionieren, wenn ich ihn
in all meinen Perlskripts einsetze.
Das verstehe ich nicht. Spielt aber keine Rolle.
Grüße aus Berlin
Christoph S.
Hallo Christoph,
Auf einem Einzelrechner ist das auch kaum nachvollziehbar. Rufe mal dein Script über zwei verschiedene virtuelle hosts gleichzeitig auf, oder wenn du kannst, gleichzeitig über zwei oder mehrere Netzwerkrechner. Du könntest auch mal in SELFHTML nachlesen.
es ist ganz egal, von wo aus auf die Datei zugegriffen wird, da
jeder Prozess, egal von wo aus er auf die Datei zugreift, eine
eigene Zeile besitzt, in der er registriert ist. Nur auf diese
eine Zeile greift er zu. Nur diese eine Zeile wird von ihm
bearbeitet.
use Fcntl qw(:DEFAULT :flock);
Hier hast du zwar das richtige Modul angesprochen, aber im Script passiert dann nichts.
Natürlich passiert was. Mittels sysopen wird die Datei ./testdatei
im Lese- und Schreibmodus mit O_RDWR geöffnet.Das war nicht gemeint. Du hast kein LOCK im Script stehen.
Das muss ich doch auch nicht. Ohne den Lockmechanismus machen
open und sysopen eigentlich das Gleiche.
open sysopen
---------------------------------------------
< O_RDONLY
> O_WRONLY | O_TRUNC | O_CREAT
>> O_WRONLY | O_APPEND
Jede der beiden Funktionen kann etwas, was die andere nicht kann.
Ich bevorzuge die "Features" von sysopen.
Der Lockmechanismus kann nur einwandfrei funktionieren, wenn ich ihn
in all meinen Perlskripts einsetze.Das verstehe ich nicht. Spielt aber keine Rolle.
Aber ich erkläre es dir gerne. Was nützt es, in einem Perlskript
eine Datei mit
sysopen(FILE,$file,O_RDWR);
flock(FILE,LOCK_EX);
zu öffnen, wenn ich in einem anderen Perlkript auf die gleiche Datei
mittels
open(FILE,'>>',$file);
zugreife. open interessiert es nicht, ob die Datei gelockt ist.
Aus diesem Grund nutze ich in meiner gesamten Umgebung den flock-
Mechanismus. Nur so kann ich sicherstellen, das sich keine Skripts
in den Weg kommen.
Und das ich sysopen statt open in meinem Beispiel eingesetzt habe
liegt einfach daran, weil ich immer sysopen statt open nutze.
Ich kann mir aber noch immer nicht vorstellen, weshalb sich mehrere
Prozesse, die alle eine andere Zeile bearbeiten, in die Quere kommen
sollten.
Greez,
opi
Hi,
ist ein paralleler Schreibzugriff auf eine Datei problemlos möglich?
Das fordert doch geradezu eine Antwort im Stile Radio Eriwans heraus: im Prinzip nicht, aber ...
Ich habe ca. 40-200 Prozesse,
Hier wird nur zwischen "Einer" und "Mehrere" unterschieden, denn sobald es mehr als ein paralleler Zugiff ist, faengt der Aerger an.
die sich in einer Datei registrieren
sollen. Die Datei hat einen strukturierten Aufbau:
So, da waeren wir ja schon beim "aber" von oben.
| 30 Zeichen | 50 Zeichen | 6 Zeichen |
| Alias | verschiedene Parameter | Prozess ID |
Jeder Alias ist einzigartig.
Kannst Du das garantieren?
Wenn Du das auch noch ueberpruefen kannst, brauchst Du tatsaechlich keinen Locking Mechanismus.
Jeder Prozess soll seinen Eintrag in kurzen Intervallen aktualisieren.
Wenn der Prozess noch nicht existiert, dann hängt er sich mittels
O_APPEND hinten dran.
Was meint Prozess? Ein regulaerer Prozess? Der Alias ist dann die PID? Dann achte darauf, das Du einem evt Integeroverflow begegnest, denn wenn die PIDs am Ende angelangt sind, fangen sie evt wieder von vorne an.
Es gibt aber auch nur einen dokumentierten Fall, ist also _sehr_ unwahrscheinlich ;-)
Nun möchte ich die Datei _nicht_ locken, damit es zu keinen Warte-
zuständen kommt.
Das ist nun wirklich kein Grund! Das lineare Suchen in der Datei nach dem passendem Eintrag dauert mit Sicherheit laenger als ein Locking fuer das Einsortieren! ;-)
Aber Datei-Locking ist nicht sehr einfach und in den raren Faellen wenn es vermieden werden kann, sollte es auch vermieden werden. KISS ("Keep It Simmple, Stupid!") ist ein gutes Prinzip.
Kann die Datei fehlerhaft geschrieben werden, wenn
die Prozesse gleichzeit nur die Zeile aktualisieren, in der sie
registriert sind?
Wie gesagt: wenn Du dafuer Sorge tragen kannst, das sie wirklich nur die eine Zeile beharken und sich ansonsten nicht gegenseitig in's Gehege kommen sehe ich da keine Probleme.
Worauf muss ich bei meinem Vorhaben insbesondere achten?
Das Du hier nicht testen kannst, denn es ist durchaus moeglich, das sich die einzelnen Prozesse aus reinem Zufall nicht in's Gehege kommen (Du kannst halt nicht auf Fehler testen, nur auf Funktion), also muss schon das Design stimmen.
so short
Christoph Zurnieden
Hallo Christoph,
| 30 Zeichen | 50 Zeichen | 6 Zeichen |
| Alias | verschiedene Parameter | Prozess ID |
Jeder Alias ist einzigartig.
Kannst Du das garantieren?
Wenn Du das auch noch ueberpruefen kannst, brauchst Du tatsaechlich keinen Locking Mechanismus.
oh ja. Der Alias setzt sich zusammen aus
std_min_sec+pid+prozessname+ip_adresse
das ganze noch zu einem Key generiert. Hier bediene ich mich der
SHA2 Verschlüsselung, da ich schon eine fertige Funktion zum
generieren von Passwörtern habe.
Jeder Prozess soll seinen Eintrag in kurzen Intervallen aktualisieren.
Wenn der Prozess noch nicht existiert, dann hängt er sich mittels
O_APPEND hinten dran.Was meint Prozess? Ein regulaerer Prozess? Der Alias ist dann die PID? Dann achte darauf, das Du einem evt Integeroverflow begegnest, denn wenn die PIDs am Ende angelangt sind, fangen sie evt wieder von vorne an.
siehe oben...
Worauf muss ich bei meinem Vorhaben insbesondere achten?
Das Du hier nicht testen kannst, denn es ist durchaus moeglich, das sich die einzelnen Prozesse aus reinem Zufall nicht in's Gehege kommen (Du kannst halt nicht auf Fehler testen, nur auf Funktion), also muss schon das Design stimmen.
Das werde ich! DANKE :-)
Greez,
opi
Hi,
Der Alias setzt sich zusammen aus
std_min_sec+pid+prozessname+ip_adresse
Du musst Dich hier auf das OS verlassen, aber das sollte keine Probleme geben. Irgendwann nutzt auch die schoenste Paranoia nix mehr ;-)
das ganze noch zu einem Key generiert. Hier bediene ich mich der
SHA2 Verschlüsselung,
Hiermit erhoest Du die Chancen auf einen "Doppelfehler" wieder leicht.
Ich hoere schon das Raunen:"Hae?", also kurz erklaert:
Das Design des Alias ist gut, damit lassen sich bis zur Datumsumstellung 2038[1] sicher einzigartige Namen schaffen. Die Wahrscheinlichkeit zwei gleiche Namen zu erhalten ist also Null bei idealen Voraussetzungen (Das OS geht nach Vorschrift bei der Verteilung der PIDs). Wenn Du jedoch ein Hash erzeugst besteht immer eine Wahrscheinlichkkeit groesser Null, das zwei verschiedene Eingaben die gleiche Ausgabe erzeugen. Bei einem kryptographisch gutem Algorithms mit einer Ausgabelaenge von 128 Bit waeren das 1:2^80. Eine verdammt kleine Zahl, aber doch groesser als Null.
Aber die Praktikabilitaet eine Hashes laesst das verschmerzen glaube ich ;-)
Ein ordentlicher Programmierer prueft aber trotzdem nach dem Erzeugen und vor der ersten Nutzung, ob der Schluessel evt schon vorhanden ist. Es gibt ja auch noch andere Moeglichkeiten, das die Datei nicht mehr stimmt.
DANKE :-)
Ne Du, umarmen is' nich', hau bloss ab! ;-)
so short
Christoph Zurnieden
[1] Du musst sowieso irgendwo begrenzen, ansonsten braeuchtest Du unendlich grosse Aliase und ein Zeitrahmen ist meist eine gute Beschraenkung, so auch hier.
Hallo Christoph,
Hiermit erhoest Du die Chancen auf einen "Doppelfehler" wieder leicht.
Ich hoere schon das Raunen:"Hae?",
da hast du allerdings recht! :-)
also kurz erklaert:
Das Design des Alias ist gut, damit lassen sich bis zur Datumsumstellung 2038[1] sicher einzigartige Namen schaffen. Die Wahrscheinlichkeit zwei gleiche Namen zu erhalten ist also Null bei idealen Voraussetzungen (Das OS geht nach Vorschrift bei der Verteilung der PIDs).
und selbst wenn nicht ganz... ich glaube nicht, dass sich die
PIDs innerhalb einer Sekunde überrunden. Ausserdem sind wir auf
dem Weg zu 64bit Systemen. Bis 2038 vielleicht noch mehr... oder?
Was ich natürlich auch machen könnte - als DBA hätte ich da eher
drauf kommen können - kann ich mir doch eine Datei in Form einer
Sequence erstellen. Jeder Prozess lockt kurzfristig und bedient sich
der Zahl+1 und legt diese auch dort ab. Wenn es dann irgendwann Mal
soweit ist und ich bei dem Ende eines Doublewertes angekommen bin,
dann kann ich auch wieder bei 1 anfangen :-)
Aber die Praktikabilitaet eine Hashes laesst das verschmerzen glaube ich ;-)
Der Hash wird nicht von den Prozessen genutzt, sonder von einem
anderen Prozess, der diese Datei ausliest.
Ein ordentlicher Programmierer prueft aber trotzdem nach dem Erzeugen und vor der ersten Nutzung, ob der Schluessel evt schon vorhanden ist.
Ja das prüfe ich. Mein Algorythmus war, solange den Key neu zu
erzeugen bis er einzigartig ist.
Ne Du, umarmen is' nich', hau bloss ab! ;-)
Bin schon wech... nice Weekend! :-)
Greez,
opi
Hi,
und selbst wenn nicht ganz... ich glaube nicht, dass sich die
PIDs innerhalb einer Sekunde überrunden.
Wir sind hier nicht in einem theologischem Seminar, das hat mit Glauben nix zu tun. Entweder weist Du etwas oder nicht. Das einzige, was "Glauben" nahe kommt, waere statistische Wahrscheinlichkeit, aber auch das ist reine Mathematik.
Ausserdem sind wir auf
dem Weg zu 64bit Systemen. Bis 2038 vielleicht noch mehr... oder?
Das darf fuer das Design keine Rolle spielen, nur fuer die einzelnen Implementation. Der Zeitraum bezieht sich auch nur auf die moegliche maximale Gueltigkeitsdauer der Datei. Also ohne irgendeinen Neustart, Mainframelike.
Was ich natürlich auch machen könnte - als DBA hätte ich da eher
drauf kommen können - kann ich mir doch eine Datei in Form einer
Sequence erstellen. Jeder Prozess lockt kurzfristig und bedient sich
der Zahl+1 und legt diese auch dort ab. Wenn es dann irgendwann Mal
soweit ist und ich bei dem Ende eines Doublewertes angekommen bin,
dann kann ich auch wieder bei 1 anfangen :-)
Nichst selber basteln, was es schon fertig gibt.
Zudem holst Du Dir wirklich unnoetige Komplexitaet ohne irgendeinen GEwinn in's Haus. Lass es lieber, das Design ist gut wie es ist.
Aber die Praktikabilitaet eine Hashes laesst das verschmerzen glaube ich ;-)
Der Hash wird nicht von den Prozessen genutzt, sonder von einem
anderen Prozess, der diese Datei ausliest.
Auch das spielt keine Rolle beim Design, darf gar keine spielen.
Ein ordentlicher Programmierer prueft aber trotzdem nach dem Erzeugen und vor der ersten Nutzung, ob der Schluessel evt schon vorhanden ist.
Ja das prüfe ich. Mein Algorythmus war, solange den Key neu zu
erzeugen bis er einzigartig ist.
Das ist falsch.
Der Algorithmus zur Erzeugung des Alias ist sicher.
Wenn Du also einen doppelten Eintrag in der Datei findest, dann ist die Datei als korumpiert zu verwerfen und neu aufzubauen.
BTW: es ist natuerlich dafuer Sorge zu tragen, das die Datei auch wirklich *from scratch* neu aufgebaut werden kann!
so short
Christoph Zurnieden
Hallo Christoph,
Was ich natürlich auch machen könnte - als DBA hätte ich da eher
drauf kommen können - kann ich mir doch eine Datei in Form einer
Sequence erstellen. Jeder Prozess lockt kurzfristig und bedient sich
der Zahl+1 und legt diese auch dort ab. Wenn es dann irgendwann Mal
soweit ist und ich bei dem Ende eines Doublewertes angekommen bin,
dann kann ich auch wieder bei 1 anfangen :-)Nichst selber basteln, was es schon fertig gibt.
Zudem holst Du Dir wirklich unnoetige Komplexitaet ohne irgendeinen GEwinn in's Haus. Lass es lieber, das Design ist gut wie es ist.
Meinst du mein bisheriger Vorgang oder das es etwas in der Form
von Sequences für Perl gibt?
Greez,
opi
Hi,
Nichst selber basteln, was es schon fertig gibt.
Zudem holst Du Dir wirklich unnoetige Komplexitaet ohne irgendeinen GEwinn in's Haus. Lass es lieber, das Design ist gut wie es ist.Meinst du mein bisheriger Vorgang oder das es etwas in der Form
von Sequences für Perl gibt?
Du hast Dein Teil schon fertig, warum willst Du das umbauen? Zudem wolltest Du Locking vermeiden und baust es so doch wieder ein. Etwas einfacheres als das Design, das Du jetzt hast duerfte schwer zu finden sein. Viel einfacher ist es, die Sache auf dem Weg ungewollt zu komplizieren, wie man ja sieht.
Es kann hoechstens noch sein, das der Zweck, zu dem die Datei vorgehalten wird bei etwas anderem Design des Gesamtkunstwerkes wegfallen koennte. Aber ich kenne ja Dein Projekt nicht, kann nur das Detail beurteilen.
Wenn Du es also einfacher haben willst frage Dich oder andere (meinetwegen die Leute hier) ob Dein Gesamtkonzept stimmig ist. Wenn das nicht korrekt ist nuetzt das schoenste Algorithmusoptimieren rein gar nix.
so short
Christoph Zurnieden