Re: [sqlite] Concerns about checkin 1879
D. Richard Hipp [EMAIL PROTECTED] writes: More sophisticated programs that want more control can still have it, even with check-in [1879]. If thread A is trying to COMMIT and thread B is trying to UPDATE, you will get a busy handler callback from thread A and an SQLITE_BUSY reply from thread B. But the SQLITE_BUSY return from thread B did not clear any locks. There is nothing that prevents the program from rolling back thread A then reissuing the UPDATE statement of thread B. It seems that there's a (possibly difficult, depending upon the application architecture) bit of record keeping required in the application to track whether the busy handler was called. Might I suggest that SQLITE_BUSY_NOWAIT (a new error code) be returned whenever a busy condition is detected that does not go through the busy handler; and SQLITE_BUSY be returned after the busy handler times out. In the above example, thread A doing its COMMIT would call the busy handler callback and then, when necessary, return SQLITE_BUSY, while thread B doing its UPDATE, would immediately return SQLITE_BUSY_NOWAIT. There may be a more appropriate name for the new error code... SQLITE_BUSY_LOCKED maybe? Does this have merit? Derrell
Re: [sqlite] Concerns about checkin 1879
More sophisticated programs that want more control can still have it, even with check-in [1879]. If thread A is trying to COMMIT and thread B is trying to UPDATE, you will get a busy handler callback from thread A and an SQLITE_BUSY reply from thread B. But the SQLITE_BUSY return from thread B did not clear any locks. There is nothing that prevents the program from rolling back thread A then reissuing the UPDATE statement of thread B. OK, maybe I'm just not getting something here, but why on earth would I want to roll back a commit in order to allow an update? Shouldn't it be the other way around? If thread A has completed it's update, and is now in the process of committing that change, why does that *not* take precedence over a thread that is just now starting it's update?
Re: [sqlite] Concerns about checkin 1879
D. Richard Hipp wrote: Ned Batchelder wrote: Perhaps a pragma or database setting? At the very least, a compile-time switch? I have your request. In the meantime, the original code that does busy callbacks for RESERVED locks is still in pager.c, just commented out using #if 0. You can find it at line 2420 in the latest version of pager.c. You can easily change it back in your local copy. There is now a compile-time switch: SQLITE_BUSY_RESERVED_LOCK. A pragma is still under consideration. -- D. Richard Hipp -- [EMAIL PROTECTED] -- 704.948.4565
RE: [sqlite] Concerns about checkin 1879
Because thread A is a low-priority background task, and I don't mind if it has to start all over again, while thread B is a high-priority UI thread, and I don't want it to wait. The responsiveness of the system depends directly on how quickly B can get its work done. Thread A will only affect the overall throughput of the system, and I know it will eventually get its chance, so I don't mind if it has to redo a bunch of work. --Ned. -Original Message- From: Brass Tilde [mailto:[EMAIL PROTECTED] Sent: Thursday, August 19, 2004 9:24 AM To: [EMAIL PROTECTED] Subject: Re: [sqlite] Concerns about checkin 1879 More sophisticated programs that want more control can still have it, even with check-in [1879]. If thread A is trying to COMMIT and thread B is trying to UPDATE, you will get a busy handler callback from thread A and an SQLITE_BUSY reply from thread B. But the SQLITE_BUSY return from thread B did not clear any locks. There is nothing that prevents the program from rolling back thread A then reissuing the UPDATE statement of thread B. OK, maybe I'm just not getting something here, but why on earth would I want to roll back a commit in order to allow an update? Shouldn't it be the other way around? If thread A has completed it's update, and is now in the process of committing that change, why does that *not* take precedence over a thread that is just now starting it's update?
[sqlite] Concerns about checkin 1879
I'm confused about checkin 1879: Do not invoke the busy callback when trying to promote a lock from SHARED to RESERVED. This avoids a deadlock. Consider two threads that are deadlocking. Thread A has made changes, and is preparing to commit, so promotes its lock from reserved to pending. Thread B begins making changes, and wants to promote its lock from shared to reserved. At that point, no more progress can be made. Thread A can't go from pending to exclusive because B still has a shared lock. Thread B can't go from shared to reserved because Thread A has a pending lock. My experience with the code up to 3.0.3 is that both thread A and B will begin calling the busy handler. I've written my application so that my busy handler can choose which thread to force to rollback, using application-specific knowledge about the precedence of the threads (UI threads are given preference, and background threads roll back). It may happen that thread A is actually a background thread, so even if it has the more advanced lock, I will choose to roll it back, letting thread B continue on. With the change in checkin 1879, it looks like my busy handler doesn't get a chance to make a choice any more. Now thread B immediately gets a BUSY error, without invoking the busy handler. Personally, I was very pleased that the busy handler allowed me so much control. I can see the other side of the argument: for users who don't want to be bothered implementing a fancy busy handler, the fewer deadlocks the better. My application will continue to work (because all threads are prepared for deadlock errors), but I liked being able to make an intelligent choice. Wouldn't it be better to invoke the busy handler in all cases? Have I gotten something wrong? --Ned. http://nedbatchelder.com