Datenbankensperren
Moderator: Moderatoren
- andreas
- Der Entwickler von "Deep Thought"
- Beiträge: 1902
- Registriert: Mi, 28. Sep 2005 10:53
- Wohnort: Osnabrück
- Hat sich bedankt: 4 Mal
- Kontaktdaten:
Datenbankensperren
Hallo Leute,
ich habe bei einem Kunden ein Problem, vermuttlich bei der Dateisperre.
In einer Datei mit einem Datensatz wird die Nummern gespeichert, die für die forlaufende Nummerierung benutzt werden. Es gibt nur eine Funktion, die Zugriff auf diese Datei hat und die Nummern zurückgibt. Diese Funktion läuft in einer Endlosschleife so lange, bis die Datei exclusive geöffnet werden konnte.
Das Problemm ist, dass immer wieder doppelte Nummern vergeben werden.
Das Programm läuft im Netzwerk. Die Daten liegen auf einem Windows 2003 Server und werden über ein verbundenes Laufwerk benuzt.
Die Clients sind Windows 98 PCs wegen Produktionshalle und viel Dreck auf kleinen PCs mit CF-Karten anstatt Festplatten.
ich habe bei einem Kunden ein Problem, vermuttlich bei der Dateisperre.
In einer Datei mit einem Datensatz wird die Nummern gespeichert, die für die forlaufende Nummerierung benutzt werden. Es gibt nur eine Funktion, die Zugriff auf diese Datei hat und die Nummern zurückgibt. Diese Funktion läuft in einer Endlosschleife so lange, bis die Datei exclusive geöffnet werden konnte.
Das Problemm ist, dass immer wieder doppelte Nummern vergeben werden.
Das Programm läuft im Netzwerk. Die Daten liegen auf einem Windows 2003 Server und werden über ein verbundenes Laufwerk benuzt.
Die Clients sind Windows 98 PCs wegen Produktionshalle und viel Dreck auf kleinen PCs mit CF-Karten anstatt Festplatten.
-
- Rekursionen-Architekt
- Beiträge: 116
- Registriert: Fr, 23. Sep 2005 16:07
- Wohnort: Bad Oldesloe
- Kontaktdaten:
Hallo Andreas.
Ich habe eine ganz ähnliche Funktion im Einsatz, jedoch wird die Datenbank ganz normal geöffnet und
die laufende Nummer wird dann bei erfolgreicher Datensatzsperre (RLOCK()) erhöht. Insgesamt sind ca.
32 User im Parallelbetrieb und bisher wurde noch keine doppelte Nummer vergeben (Toi Toi Toi).
Aber vielleicht kannst Du uns Deine Funktion posten ?
Ich habe eine ganz ähnliche Funktion im Einsatz, jedoch wird die Datenbank ganz normal geöffnet und
die laufende Nummer wird dann bei erfolgreicher Datensatzsperre (RLOCK()) erhöht. Insgesamt sind ca.
32 User im Parallelbetrieb und bisher wurde noch keine doppelte Nummer vergeben (Toi Toi Toi).
Aber vielleicht kannst Du uns Deine Funktion posten ?
- andreas
- Der Entwickler von "Deep Thought"
- Beiträge: 1902
- Registriert: Mi, 28. Sep 2005 10:53
- Wohnort: Osnabrück
- Hat sich bedankt: 4 Mal
- Kontaktdaten:
Hallo Thomas,
ich habe das früher auch mit nur den Datensatz gesperrt gehabt, hat aber auch zum gleichen Problem geführt. Deswegen habe ich auf die Dateisperre umgestellt, was das Problem eigentlich beseitigen sollte. Gestern kamm aber wieder eine doppelnummer hintereinander.
Unten findest du die Funktionen. Ich lasse die auskommentierten Zeilen von der Datensatzsperre drin, damit du das sehen kannst, wie es vorher war.
ich habe das früher auch mit nur den Datensatz gesperrt gehabt, hat aber auch zum gleichen Problem geführt. Deswegen habe ich auf die Dateisperre umgestellt, was das Problem eigentlich beseitigen sollte. Gestern kamm aber wieder eine doppelnummer hintereinander.
Unten findest du die Funktionen. Ich lasse die auskommentierten Zeilen von der Datensatzsperre drin, damit du das sehen kannst, wie es vorher war.
Code: Alles auswählen
FUNCTION GetNummer(cAuswahl)
local nAuftragNeu:=0, cAuftragNeu:="", db:=select(), nJahr:=YEAR(date())
/*
Local aStruckt:={;
{"Jahr","N",2,0},;
{"Auftrag","N",7,0},;
{"LaufKarte","N",7,0},;
{"Behaelter","N",9,0},;
{"Liefersch","N",8,0};
}
*/
Default cAuswahl to "AUFTRAG"
/*
IF ! file("Nummern.dbf")
dbcreate("Nummern", aStruckt, "FOXCDX")
ENDIF
*/
IF len(alltrim(str(nJahr)))==4
nJahr:= val(substr(alltrim(str(nJahr)),3))
ENDIF
*use Nummern alias Nummern via "FOXCDX" new exclusive
do while ! DBNummerOpen()
enddo
*IF ! neterr()
IF lastrec()==0
dbappend()
replace nummern->jahr with nJahr
*dbrunlock()
ENDIF
go 1
*do while ! dbrlock()
*enddo
IF nJahr > nummern->jahr
**zurücksetzen der Werte, wenn das Jahr sich gewechselt hat
replace nummern->jahr with nJahr
replace nummern->auftrag with 0
replace nummern->LaufKarte with 0
replace nummern->Behaelter with 0
replace nummern->Liefersch with 0
ENDIF
IF upper(cAuswahl)=="AUFTRAG"
nAuftragNeu:=nummern->auftrag+1
replace nummern->auftrag with nAuftragNeu
cAuftragNeu:="A"+strzero(nJahr,2)+strzero(nAuftragNeu,7)
elseIF upper(cAuswahl)=="LAUFKARTE"
nAuftragNeu:=nummern->LaufKarte+1
replace nummern->LaufKarte with nAuftragNeu
cAuftragNeu:="LK"+strzero(nJahr,2)+strzero(nAuftragNeu,7)
elseIF upper(cAuswahl)=="BEHAELTER"
nAuftragNeu:=nummern->Behaelter+1
replace nummern->Behaelter with nAuftragNeu
cAuftragNeu:="B"+strzero(nJahr,2)+strzero(nAuftragNeu,9)
elseIF upper(cAuswahl)=="LIEFERSCHEIN"
nAuftragNeu:=nummern->Liefersch+1
replace nummern->Liefersch with nAuftragNeu
cAuftragNeu:="HL"+strzero(nJahr,2)+strzero(nAuftragNeu,8)
ENDIF
*dbrunlock()
close Nummern
*ENDIF
IF db>0
select (db)
ENDIF
RETURN cAuftragNeu
FUNCTION DBNummerOpen
local lOk := .f.
Local aStruckt:={;
{"Jahr","N",2,0},;
{"Auftrag","N",7,0},;
{"LaufKarte","N",7,0},;
{"Behaelter","N",9,0},;
{"Liefersch","N",8,0};
}
IF ! file("Nummern.dbf")
dbcreate("Nummern", aStruckt, "FOXCDX")
ENDIF
bSaveError := ErrorBlock()
ErrorBlock( {|e| Break(e)} )
BEGIN SEQUENCE
use Nummern alias Nummern via "FOXCDX" new exclusive
IF ! neterr()
lOk := .t.
else
lOk := .f.
endif
RECOVER
ErrorBlock( bSaveError )
lOk := .f.
END SEQUENCE
ErrorBlock( bSaveError )
RETURN lOk
-
- Rekursionen-Architekt
- Beiträge: 116
- Registriert: Fr, 23. Sep 2005 16:07
- Wohnort: Bad Oldesloe
- Kontaktdaten:
Hallo Andreas.
Deine Funktion sieht soweit Okay aus. Im Vergleich mit meiner Funktion vermisse ich bei Dir den DBCommit() vor der Zeile „close Nummern“. Vielleicht hilft das, zumindest hat meine Funktion per Heute schon 3.5 Mill. Unique Nummer vergeben.
Ein Tip : Ich benutze niemals „REPLACE“ ! (nummern->auftragnr := nummern->auftagnr+1)
Gruß
Thomas
Deine Funktion sieht soweit Okay aus. Im Vergleich mit meiner Funktion vermisse ich bei Dir den DBCommit() vor der Zeile „close Nummern“. Vielleicht hilft das, zumindest hat meine Funktion per Heute schon 3.5 Mill. Unique Nummer vergeben.
Ein Tip : Ich benutze niemals „REPLACE“ ! (nummern->auftragnr := nummern->auftagnr+1)
Gruß
Thomas
-
- Rekursionen-Architekt
- Beiträge: 116
- Registriert: Fr, 23. Sep 2005 16:07
- Wohnort: Bad Oldesloe
- Kontaktdaten:
Hallo Andreas.
Ich kann Dir leider die Frage nicht 100%tig beantworten, ob nach dem Schließen der Datenbank alle geänderten Daten auch drinstehen oder noch irgendwo im Cache sind. In Deinem Fall kann DbCommit() nicht schaden. Wie oft kommen eigentlich solche doppelten Nummer vor ?
Die Benutzung von Replace ist einfach eine Geschmacksache.
Gruß
Thomas
Ich kann Dir leider die Frage nicht 100%tig beantworten, ob nach dem Schließen der Datenbank alle geänderten Daten auch drinstehen oder noch irgendwo im Cache sind. In Deinem Fall kann DbCommit() nicht schaden. Wie oft kommen eigentlich solche doppelten Nummer vor ?
Die Benutzung von Replace ist einfach eine Geschmacksache.
Gruß
Thomas
- andreas
- Der Entwickler von "Deep Thought"
- Beiträge: 1902
- Registriert: Mi, 28. Sep 2005 10:53
- Wohnort: Osnabrück
- Hat sich bedankt: 4 Mal
- Kontaktdaten:
Ich glaube, dass es an gewonheit von Windows liegt, die Dateinamen in der Verknüpfung zu ändern, wenn die Datei nicht mehr da ist, wo die z.B. in diesen Moment umbenant wird. Der Kunde hatte nocht eine alte umbenannte Datei im Verzeichnis liegen, wo noch alte Methode mit Dbrlock() verwendet wurde. Es kann sein dass mindestens 2 PCs damit gearbeitet haben und das Problem verursacht haben. Da wäre das mit DBCommit() angesagt gewesen.
Ich habe erstmal die alte Datei gelöscht und werde erst abwarten, ob das Problem noch mal vorkommt.
Ich habe erstmal die alte Datei gelöscht und werde erst abwarten, ob das Problem noch mal vorkommt.