John, thanks for the reply.
you mean you do the synchronization by your selve rather than let it do sqlite internally ? Marcus John Stanton wrote: > We have been using such a server embadding Sqlite for some time with > success. We actually use pthreads exclusive and read only mutexes for > synchronization since all Sqlite access is threaded in the one process. > JS > > Marcus Grimm wrote: >> Hi all, >> >> a few weeks ago I discovered sqlite3 and found it extremely >> exiting and I decided to make an attempt to use it as a >> replacement for an access-based (via ODBC) database server. >> Our server is actually a quite simple application but using >> access via ODBC of course may run into serious limitations >> due to the non threadsafe nature of the jet driver. >> >> Now, since a few weeks I read a lot concerning the thread issue >> within sqlite, I parsed this mailing list and read about >> some limitations and recommendations and I came to the conclusion >> that for my project it should work. To validate this I started >> to integrate sqlit3 into my code and did some tests to see >> wether I should go on. >> I want to share my findings and hopefully get some comments from >> the users because I'm still not really sure if I should go on. >> >> Here is a rough description about the server (Win32) application: >> >> The server can be seen as a main application that listens on a >> socket for incoming connections from a client PC. Each running >> connection creates a thread inside the main application. >> Within the "line-threads" it is required to access the database, >> same is true for the main process that frequently queries the >> database as well. >> >> First attempt was to open only one DB connection using sqlite3_open_v2 >> within the main process and having all threads using this single >> connection: >> This seems to work quite good -- of course it has a major performance >> issue when one thread makes an UPDATE statement while another simply >> tries to query a table. Although the client connections sleeps most of >> the time I want to avoid that in case of a collision the server times out. >> In this mode it looks that also only one thread is able to query the >> database, >> if such a query will take 500ms the others are often blocked for this time. >> >> I read that it is recommended to open one DB connection for every thread, so >> I tried this and run into the famous SQLITE_BUSY and SQLITE_LOCKED issue >> which >> drives me crasy. anyway, here is the simple structure: >> >> 1. server-main opens one connection using sqlite_open_v2, this remains open >> for the life time of the server. >> 2. each time a connect request starts the server opens a new connection using >> sqlite_open_v2 and assigns this to the thread, if the connection is >> closed >> the DB connection is closed as well using sqlite3_close. >> >> To test this approach I connect 3 clients to the server and let them do >> queries with maximum speed (in order to increase the likelyhood >> of a collision). What the clients do during this test are 95% SELECT >> statements >> on a single Table and probably 5% UPDATES on a single table row. The tables >> are not very big -- One has about 10000 rows, the other one about 100000. >> >> The first connections runs quite good and queries the database with high >> speed. >> Then I connect a 2nd and 3rd test client: The problem here was that the >> sqlite DB >> almost immediately runs into the SQLITE_BUSY state, sometimes during a SELECT >> fetch cycle sometimes in the UPDATE statement. >> Okay, the doku tells that in this case I should try again -- So I added a >> loop around all sqlite3_step() that tests for busy state >> and retries the sqlite3_step() for some time: No way! - I can wait for >> minutes >> to get a return value other than SQLITE_BUSY, there is a dead lock. Seems >> that one thread wait to get his UPDATE statement throuh meanwhile another is >> waiting for his SELECT fetch and none of them gets a lock on the database. >> I added the busy_timeout: It doesn't really help neither do the busy_handler. >> Actually it looks that the busy handler is not even called when a >> sqlite3_step() >> returns SQLITE_BUSY -- This is confirmed by some statements in the sqlite >> dokumentation and indicates a deadlock rather than a real busy state. >> But why ? Even if all lines wait in a busy loop and sleep none of them gets >> back the right >> to access the database! >> Please note that during this testing the database is busy all the time with >> maximum speed that can be achieved -- to find these kind of collision. >> >> Okay, looking deeper into the documents I found some functions to try that >> may help >> and I finally got it running without the deadlocks -- but I don't really >> understand >> why and that's where I would like to share this with other: >> Seems that a call of >> >> sqlite3_enable_shared_cache( 1 ); >> >> after I open the main database connection, does something useful for my >> case... >> After this I got "real" busy states and for about 30 minutes the server runs >> with maximum load, after this I got more SQLITE_LOCKED return values and >> sooner or later the server stops working. Probably related to a weak error >> handling on my side. >> >> Anyway, then I added: >> >> PRAGMA read_uncommitted = true; >> >> because I don't care if a client thread doesn't get the last updated table >> content. >> With this statement the busy-handler situation improves further. >> Now my server can run under heavy load, deals with some busy loops after >> sqlite3_step() >> returns that state, but finally runs for a couple of hours and I stop the >> test. >> >> So the final way to open a sqlite database is: >> >> 1. On server startup it opens the main database connection with: >> sqlite3_open_v2(..., &MainDB, SQLITE_OPEN_READWRITE); >> sqlite3_enable_shared_cache( 1 ); >> sqlite3_busy_timeout(MainDB, 100); >> execute "PRAGMA read_uncommitted = true;" on the MainDB >> >> 2. A thread connection is opened via: >> sqlite3_open_v2(..., &ThreadDB, SQLITE_OPEN_READWRITE); >> sqlite3_busy_timeout(ThreadDB, 100); >> execute "PRAGMA read_uncommitted = true;" on the ThreadDB >> >> >> Please note that the linethread may use his DB connection within >> additional working threads, so the ThreadID used within the mutex handling >> inside sqlite3 may differ from the one that openes the database connection. >> I know that this is not recommened but I can't fully avoid this. >> However, there is no pararallel usage of a single DB connection. >> >> Now to my main question: >> >> The above way seems to work -- any comments if this is a good way to >> use sqlite ? >> >> Why the enable_share cache has an effect on the busy handling inside >> the library ? Actually I use this call only to improve the deadlock >> situation -- from the memory point of view I have no need to save >> memory... >> >> In this way the server may open upto 50 connections on the same >> database file... Is there any known issue about this ? I'm wondering >> if it is healthy to open a file 50 times... >> >> Maybe the way I test my server is not fair because I use the >> maximum traffic that I can produce which is not the normal way the >> server will work later on. But the database (or my implementation) >> should be able to deal with this, right? >> >> I'm not saying that I'm looking for a "real" server based database >> like MySQL! I don't need that and sqlite3 would perfectly fit in. :-) >> >> I think sqlite is a wonderful piece of software -- and I really >> want to use it for my project. But I'm a bit nervous because >> it turns out to be a bit "try and error" like, for newbies like me. >> >> Any comment is welcome >> >> Thank you! >> >> Marcus >> >> PS: I'm using the latest sqlite3 code on WinXP or Vista >> >> >> _______________________________________________ >> sqlite-users mailing list >> [email protected] >> http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users > > _______________________________________________ > sqlite-users mailing list > [email protected] > http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users > -- Marcus Grimm, MedCom GmbH Darmstadt, Rundeturmstr. 12, 64283 Darmstadt Tel: +49(0)6151-95147-10 Fax: +49(0)6151-95147-20 -------------------------------------------------- MedCom slogans of the month: "Vacation ? -- Every day at MedCom is a paid vacation!" "Friday I have monday in my mind." "MedCom -- Every week a vacation, every day an event, every hour a cliffhanger, every minute a climax." "Damned, it's weekend again!" _______________________________________________ sqlite-users mailing list [email protected] http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users

