Datenbank bei jedem Zugriff öffnen und schließen oder nur einmal öffnen



  • Ich glaube, dass ich mir seitdem eher mal die DB sperre, also Parallelabfragen (oder was auch immer, da suche ich noch) nicht mehr möglich sind.
    Ich hoffe, ich denke dran, wenn ich den Fehler mal wieder habe, dann werde ich es mal testen. 🙂



  • Martin Richter schrieb:

    Wenn alle 30 Sekunden ein Zugriff erfolgt würde ich die Datenbank offen lassen.
    Das Problem sehe ich an sich schon in der Verwendung einer Access Datenbank.

    Für diese Client Menge ist das Ding wirklich nicht gebaut. Bei einer gleichmässigen Verteilung hast Du wenigstens 3 Updates pro Sekunde mit sicherlich nicht geringen Wachstum der Datenbank.

    Ich würde Dir von einer AccessDB abraten. Wenn jetzt noch lesende Clients dazukommen wird das zur keimenden Kartoffel.

    Aloha Martin,

    nee, haste Dich verlesen. Nur der Server greift auf die DB !!!
    Und das passiert dann tatsächlich ca. bis zu 300 x die Minute, das aber auch nur in Spitzenzeiten.

    Vorteil der Access DB ist, dank der Jet Engine läuft sie nun in einer Umgebung, auf die ich nicht wirklich Zugriff habe und wo auch kein Access installiert ist.

    Meine Frage ist nach wie vor, ist es ungewöhnlich die DB die komplette Laufzeit offen zu lassen ?

    Grüße und Danke

    BOA



  • estartu schrieb:

    Ich glaube, dass ich mir seitdem eher mal die DB sperre, also Parallelabfragen (oder was auch immer, da suche ich noch) nicht mehr möglich sind.
    Ich hoffe, ich denke dran, wenn ich den Fehler mal wieder habe, dann werde ich es mal testen. 🙂

    Aloha,

    genau das scheint mein Porblem ich bekomme ne Meldung

    Das Microsoft Jet-Datenbankmodul hat den Vorgang angehalten, da Sie und ein weiterer Benutzer gleichzeitig versuchen, dieselben Daten zu verändern.

    Grüße

    BOA



  • Hast du nun eigentlich nur den Server, der nur ein Recordset hat und damit schreibt er? 😕
    Wenn das der Fall ist, dürftest du ja gar keine Parallelzugriffe haben.

    Oder wie ist das gelöst? Wann wird geschrieben?



  • estartu schrieb:

    Hast du nun eigentlich nur den Server, der nur ein Recordset hat und damit schreibt er? 😕
    Wenn das der Fall ist, dürftest du ja gar keine Parallelzugriffe haben.

    Oder wie ist das gelöst? Wann wird geschrieben?

    Aloha,

    nein, wenn der Client eine Message schickt, öffnet der Server eine Tabelle und filtert nach der Client - ID einen bestimmten Datensatz der Tabelle raus ändert diesen, macht ein Update und schließt die Tabelle danach wieder.

    Dann könnte die nächste Message abgearbeitet werden...

    Grüße

    BOA



  • 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.


  • Mod

    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...


  • Mod

    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


  • Mod

    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


  • Mod

    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


Anmelden zum Antworten