On Tue, 2005-09-06 at 16:07 -0400, D. Richard Hipp wrote:
> On Tue, 2005-09-06 at 15:49 -0400, Mark Drago wrote:
> 
> > 2. I could continue to write to the database in the single thread, but
> > if the write fails, add the data to a queue and continue.  Then, when
> > another piece of data has to be logged, and it succeeds, empty the queue
> > and write all of the data from it into the sqlite DB. 
> 
> This is what I would do.  Except I would make the queue a
> separate SQLite database which was connected to the primary
> database using ATTACH.
> 
> Suppose the "queue" database is named "pending.db".  Then
> when you open the primary database always immediately do
> this:
> 
>     ATTACH DATABASE 'pending.db' AS pending;
> 
> Then when you want to make a log entry do the following
> statements:
> 
>    INSERT INTO pending.log VALUES(...);
>    INSERT INTO main.log SELECT * FROM pending.log;
>    DELETE FROM pending.log;
> 
> When doing the above, abort after the first failure.
> If the database is locked then the second statement will
> fail, the DELETE will never occur and information will
> accumulate in the "pending" database.  If the second
> statement succeeds, then the information is subsequently
> deleted from the pending database.
> 
> If you really want to make sure that the transfer from
> pending to main is atomic, enclose the last two statements
> in a transaction.

Thanks a bunch for this idea.  I've implemented this and I'm getting an
odd error.  The scenario is thus:

I insert the log into the attached database:
INSERT INTO pending.log VALUES(...);

I then begin a transaction:
BEGIN TRANSACTION;

If this does not return a SQLITE_OK, I just leave the log in the queue
and hopefully the next log attempt will be able to work it out.

Once in the transaction, I run the INSERT INTO log SELECT * FROM ...:
INSERT INTO main.log SELECT * FROM pending.log;

If this does not return a SQLITE_OK, I run 'ROLLBACK TRANSACTION;' and
leave that log data in the pending db.

Provided the move from the queue to the main log succeeds, I delete the
entries from the pending log:
DELETE FROM pending.log;

If this does not return a SQLITE_OK, I run 'ROLLBACK TRANSACTION;' and
leave that log data in the pending db.

Provided the delete succeeded, I run 'COMMIT TRANSACTION;' and all
should be well.


The problem I'm seeing is that (I'm half guessing) after I run a
rollback, when I try and run 'begin transaction' I get: 'cannot start a
transaction within a transaction'.  As far as I can tell there is no way
to get out of this part of my code without running either a rollback or
a commit.  I've executed 'pragma synchronous=off' on this database as
I'll be writing to it very often and the data isn't life-or-death
important.  I don't think this should impact anything, but I figured I
would share.  Any ideas?

Mark.

Attachment: signature.asc
Description: This is a digitally signed message part

Reply via email to