Datenbank bei jedem Zugriff öffnen und schließen oder nur einmal öffnen
-
Kann es also vorkommen, dass der zwei gleichzeitig schreiben will?
Mach zur Not mal ein TRACE an den Anfang der Funktion und eins ans Ende, dann siehst du ob es daran liegt.
-
Also wenn nur der Server das Dingbraucht. Würde ich den gesamten Datenbankzugriff in einem Thread über eine Queue synchronisieren. Es würde sowieso synchronisiert werden, dann aber über die DB und das ist weitaus uneffektiver, als wenn Du alles in einer Queue sammelst und diese Queue von einem Thread abgearbeitet wird, der die ganze Zeit die DB natürlich offen hat.
-
Martin Richter schrieb:
Also wenn nur der Server das Dingbraucht. Würde ich den gesamten Datenbankzugriff in einem Thread über eine Queue synchronisieren. Es würde sowieso synchronisiert werden, dann aber über die DB und das ist weitaus uneffektiver, als wenn Du alles in einer Queue sammelst und diese Queue von einem Thread abgearbeitet wird, der die ganze Zeit die DB natürlich offen hat.
Aloha,
das ist gar keine schlechte Idee, danke für den Tip, werde ich mal andenken, ob ich das schnell umschreibe...
Und wie ich lese, ist es also auch nicht ungewöhnlich, dass die DB offen bleibt...
Danke und Grüße
-
estartu schrieb:
Kann es also vorkommen, dass der zwei gleichzeitig schreiben will?
Mach zur Not mal ein TRACE an den Anfang der Funktion und eins ans Ende, dann siehst du ob es daran liegt.Eigentlich sollte es nicht vorkommen, da nur alle 30 sekunden von einem Client eine Message geschickt wird. Soll heißen dergleiche Datensatz wird nur alle 30 Sekunden angefaßt....
Ich habe etwas gelesen, dass diese Fehlermeldung bei Access auch vorkommen kann, wenn die DB irgenwie beschädigt wurde. Man soll dann einfach alle Tabellen kopieren und in eine leere reinpacken.
Kennt sich damit jemand aus, geht das mit allen Tabellen auf einmal, oder nur einzeln ?
Grüße und Danke
BOA
-
BOA schrieb:
estartu schrieb:
Kann es also vorkommen, dass der zwei gleichzeitig schreiben will?
Mach zur Not mal ein TRACE an den Anfang der Funktion und eins ans Ende, dann siehst du ob es daran liegt.Eigentlich sollte es nicht vorkommen, da nur alle 30 sekunden von einem Client eine Message geschickt wird. Soll heißen dergleiche Datensatz wird nur alle 30 Sekunden angefaßt....
Kann es sein, dass die Meldung
Das Microsoft Jet-Datenbankmodul hat den Vorgang angehalten, da Sie und ein weiterer Benutzer gleichzeitig versuchen, dieselben Daten zu verändern.
heißt, dass du zweimal auf die gleiche Tabelle zugreifen willst?
Das dachte ich bisher immer, aber von Jet habe ich keine Ahnung.
Und das wäre nicht alle 30 Sekunden, sondern eben bis zu 100 mal öfter.

-
Aloha,
das ist eine gute Frage, ich hätte wie gesagt auf den Datensatz getippt.
Ich muß das mal eruieren....Aber ich denke, dass mit der DB auch etwas nicht stimmt, da in einzelnen Tabellen Werte geändert werden, ohne das ein Zugriff vom Server Proggi erfolgt...

Das ist schon spannend...
Grüße und Danke
BOA
-
Hi,
das hat tatsächlich geholfen, eine neue DB anzulegen und die Tabellen hineinzukopieren.
Ich bekomme keine Fehlermeldungen mehr und auch ominöse Änderungen finden nicht mehr statt in den Tabellen...
Erstaunlich....
Grüße
BOA
-
Wenn du kannst dann nimm den MSSQL 2005 Express. Ist wesentlich robuster und auch schön gratis. Einzig die Limitierung auf 2GB (oder waren es 4GB?) könnte u.U. lästig werden...
-
MSDE 2000 war auf 2GB limitiert
SQL 2005 Express auf 4GB
-
Martin Richter schrieb:
Also wenn nur der Server das Dingbraucht. Würde ich den gesamten Datenbankzugriff in einem Thread über eine Queue synchronisieren. Es würde sowieso synchronisiert werden, dann aber über die DB und das ist weitaus uneffektiver, als wenn Du alles in einer Queue sammelst und diese Queue von einem Thread abgearbeitet wird, der die ganze Zeit die DB natürlich offen hat.
Hi Martin,
zu dieser Queue Geschichte habe ich noch ne Frage.
Ich habe mir nun ne <list> m_listeMessagesangelegt und lasse per Timer jede Sekunde diese in folgender Manier durchlaufen :for(list<mes>::iterator itMes = m_listeMessages.begin(); itMes != m_listeMessages.end(); itMes++) { MessageReceive(itMes->message, itMes->sock); itMes = m_listeMessages.erase(itMes); itMes--; }Wie reagiert das Programm eigentlich ? Ich arbeite nun z.B. 7 Nachrichten in der Schleife ab, in der zwischenzeit loggt sich ein neuer User ein. Wird die Schleife erst abgearbeitet oder wird die neue Message gleich in die Liste gepackt ?

Hättest Du Deine Queue ähnlich gebastelt ?

Danke und Grüße
BOA
-
Wenn Du das so machst und ein anderer Thread fügt was in die Liste ein, dann wird es nicht lange dauern und Dein Listenobjekt ist zerstört.
Du musst in jedem Fall das Objekt blockieren durch eine Critical Section.
Und warum die Schleife durchlaufen?
CCriticalSection m_critical; list<mes> m_listeMessages; ... while (bProgramIsNotTerminated) { mes m; bool bDoit = false; { CSingleLock lock(&m_critical,TRUE); // Something to work if (m_listeMessages.size()) { m = m_listeMessages.front(); m_listeMessages.pop_front(); bDoit = true; } } if (bDoit) MessageReceive(m.message, m.sock); }So kann auch während MessageReceive ausgeführt wird etwas in die Liste gepackt werden.
Wichtig ist das beim einfügen auch die Criticalsection verwendet wird.
mes m; if (GetNextMes(m)) { CSingleLock lock(&m_critical,TRUE); m_listeMessages.push_back(m); }
-
Martin Richter schrieb:
Wenn Du das so machst und ein anderer Thread fügt was in die Liste ein, dann wird es nicht lange dauern und Dein Listenobjekt ist zerstört.
Du musst in jedem Fall das Objekt blockieren durch eine Critical Section.
Und warum die Schleife durchlaufen?
CCriticalSection m_critical; list<mes> m_listeMessages; ... while (bProgramIsNotTerminated) { mes m; bool bDoit = false; { CSingleLock lock(&m_critical,TRUE); // Something to work if (m_listeMessages.size()) { m = m_listeMessages.front(); m_listeMessages.pop_front(); bDoit = true; } } if (bDoit) MessageReceive(m.message, m.sock); }So kann auch während MessageReceive ausgeführt wird etwas in die Liste gepackt werden.
Wichtig ist das beim einfügen auch die Criticalsection verwendet wird.
mes m; if (GetNextMes(m)) { CSingleLock lock(&m_critical,TRUE); m_listeMessages.push_back(m); }Hallo,
vielen Dank für die schnelle Antwort.
Diese Technik ist mir neu, speziell das mit dem CSingleLock und CCriticalSection.Ich werde das einmal probieren umzusetzen und werde dann berichten, solange vielen Dank erstmal.
Beste Grüße
BOA
-
Wenn Du mehrere Threads benutzt, dann ist das Pflicht!
-
Martin Richter schrieb:
Wenn Du mehrere Threads benutzt, dann ist das Pflicht!
Hi,
ja ich benutze mehrere Threads, und hatte auch ab und zu einen undefinierten Absturz der exe mit einer Speicherzugriffsverletzung...
Ich teste mal, vielen Dank.
Beste Grüße
BOA
-
Hallo Martin,
wenn ich das wie Du angegeben hast in einen Message Queue Thread verpacke, wo diese while - Schleife immer läuft, solange das Programm läuft und schaut, ob ich eine neue Message zum Abarbeiten habe.
Das belastet aber den Prozessor mit 100%....
Kann ich nicht so etwas machen ?
CSingleLock lock(&m_critical,TRUE); for(list<mes>::iterator itMes = m_listeMessages.begin(); itMes != m_listeMessages.end(); itMes++) { MessageReceive(itMes->message, itMes->sock); itMes = m_listeMessages.erase(itMes); itMes--; }Muß ich nicht eigentlich nach einem Lock ein Unlock machen ?
Besten Dank und Grüße
BOA
-
Schau Dir mal bitte meinen Code an!
Dein Code kan nicht funktionieren. Er nimmt die Liste in Beschlag und gibt sie nicht frei!
Und ja. Du solltest ein Event haben, was diese Schleife nur bei Bedarf anstösst und ansonsten den Thread schlafen lässt!
-
Martin Richter schrieb:
Schau Dir mal bitte meinen Code an!
Dein Code kan nicht funktionieren. Er nimmt die Liste in Beschlag und gibt sie nicht frei!
Und ja. Du solltest ein Event haben, was diese Schleife nur bei Bedarf anstösst und ansonsten den Thread schlafen lässt!Hi,
mir fehlt irgendwie noch Background, aber ich finde auch nichts Vernünftiges im Net, was ich noch zusätzlich studieren könnte zu diesem Thema.
Ich habe mir Deinen Code angeschaut, und verstehe eigentlich nur nicht, wo der Lock wieder freigegeben wird und woran ich erkenne, welches Objekt genau gelockt wird.
Ich habe statt deinem Thread nen Timer genommen, was ja auch ein Thread ist ( glaube ich zumindestens, bitte um Korrektur, falls diese Annahme nicht stimmt ), und lasse dort die Schleife mit den Nachrichten durchlaufen.
Das einzigste Problem, was ich bis dato habe, ist, dass es wahrscheinlich in einem sehr ungünstigen Fall, wenn ich gerade die Liste durchlaufe zu einem Hinzufügen an einer anderen Stelle kommt ( Ein User loggt sich ggf. gerade an einem Socket ein, ein anderer Timer wird gestartet, ... )
Deswegen wollte ich Deine Lösung mit dem CSingleLock ( immer dort wo ich hinzufüge und bevor die Liste durchlaufen wird. siehe oben. ) ergänzen, dazu muss ich aber die Funktionalität genau begreifen, damit ich nicht noch mehr Schaden anrichte....
Danke und Grüße
BOA
-
Hallo Martin,
ich glaube ich habe Deine geschweiften Klammern übersehen.
Da wird das Objekt wieder freigegeben ? Ist das korrekt ?Ich habe meinen Code nun geändert ( Im Timer ) :
CSingleLock lock(&m_CriticalSection); lock.Lock(); CString ausgabe; ausgabe.Format("%d Nachrichten in der Queue",m_listeMessages.size()); m_info2.SetWindowText(ausgabe); for(list<mes>::iterator itMes = m_listeMessages.begin(); itMes != m_listeMessages.end(); itMes++) { MessageReceive(itMes->message, itMes->sock); itMes = m_listeMessages.erase(itMes); itMes--; } lock.Unlock();Zudem wird dann bei jedem Ergänzen der Liste folgender Code verwendet :
CSingleLock lock(&m_CriticalSection); lock.Lock(); mes tMes; tMes.message = "0200"; tMes.sock = 0; m_listeMessages.push_back(tMes); lock.Unlock();Macht das Sinn ?
Grüße
BOA
-
Meine Lösung ist insofern besser, weil beim Bearbeiten jedes Eintrages schon wieder Einträge in die Liste eingefügt werden können.
Sind bei Dir 20 Einträge drin steht für die gesamte Bearbeitung auhc das einfügen in die Liste.Schau Dir noch mal genau meine Methode an.
-
Martin Richter schrieb:
Meine Lösung ist insofern besser, weil beim Bearbeiten jedes Eintrages schon wieder Einträge in die Liste eingefügt werden können.
Sind bei Dir 20 Einträge drin steht für die gesamte Bearbeitung auhc das einfügen in die Liste.Schau Dir noch mal genau meine Methode an.
Ja, hi
das macht natürlich Sinn, was Du schreibst.
Das heißt aber, ich müsste den Thread ständig starten und in den Sleep Modus setzen. An welcher Stelle prüfe ich ab, ob ich ihn tatsächlich starten muss...
Wahrscheinlich starte ich ihn prinzipiell, wenn ich etwas hineinpacke in die Liste, oder ?Wäre das aber prinzipiell richtig, was ich da treibe ?
Besten Dank und Grüße
BOA