[sqlite] Releasing a read (SHARED) lock

2015-03-13 Thread Barry
Hmmm, I am guilty of not always stepping until I get SQLITE_DONE (I am
usually selecting by the primary key, and therefore know I will only get a
single result), but I make sure to always call sqlite_reset, so I don't
think that should be the issue.

On further reflection, I suspect it might be the 'obscure side-effect'
mentioned by Dinu. I do have functions that look like:

//bind all parameters
//...
//begin querying statement1:
//Note: stmt1 is only queried once (and hence is still 'open' for now)
sqlite3_step(stmt1);

//Use the results from statement1 to bind statement2
//...
//begin querying statement2:
while(SQLITE3_OK == sqlite3_step(stmt2)) {
  //Do things
  }

//reset both statements
sqlite3_reset(stmt2);
sqlite3_reset(stmt1);

So, in this situation I do in fact have two SELECT statements open
simultaneously, which should trigger the unreleasable lock. I will try
change my code and post results here.

On 13 March 2015 at 09:02, Dinu Marina  wrote:

> You should also check, as R.Smith and Slavin pointed, that you don't
> accidentally have a BEGIN [DEFERRED] somewhere, as that would trigger
> exactly this behavior: it will lock on the first select (the first step()
> actually)
>
>
> On 13.03.2015 02:44, Simon Slavin wrote:
>
>> On 13 Mar 2015, at 12:17am, Barry  wrote:
>>
>>  On 13 March 2015 at 01:21, Dinu Marina  wrote:
>>>
>>>  You should be also aware of a more common pitfall: unclosed result sets.
 Any lock is held until you read PAST the last row or you call
 stmt_finalize
 (or the equivalent abstraction in your DBAL). Always close select
 statements.

>>> Hi Dinu,
>>>
>>> Am I correct in my understanding then that it is not enough to call
>>> sqlite3_reset, I must call sqlite3_finalize after I am done with a
>>> statement?
>>>
>> In order to dispose of a statement you can do either sqlite3_reset() or
>> sqlite3_finalize().  The common mistake is to do something like this:
>>
>> SELECT * FROM myTable WHERE rowid = 36
>>
>> and then not do either _reset() or _finalize() because you know you have
>> asked for only one row so you expect SQLite to have done a _finalize() for
>> you.
>>
>> Simon.
>> ___
>> sqlite-users mailing list
>> sqlite-users at mailinglists.sqlite.org
>> http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users
>>
>
> ___
> sqlite-users mailing list
> sqlite-users at mailinglists.sqlite.org
> http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users
>


[sqlite] Releasing a read (SHARED) lock

2015-03-13 Thread Barry
On 13 March 2015 at 01:21, Dinu Marina  wrote:

> You should be also aware of a more common pitfall: unclosed result sets.
> Any lock is held until you read PAST the last row or you call stmt_finalize
> (or the equivalent abstraction in your DBAL). Always close select
> statements.


Hi Dinu,

Am I correct in my understanding then that it is not enough to call
sqlite3_reset, I must call sqlite3_finalize after I am done with a
statement?

Cheers,

 - Barry


> On Mar 12, 2015 11:40 AM, "R.Smith"  wrote:
>
> >
> >
> > On 2015-03-12 04:38 AM, Barry wrote:
> >
> >> Hello everybody,
> >>
> >> I have a situation where two processes are accessing the same SQLite
> >> database. One process only reads from the database, one process reads
> and
> >> writes.
> >>
> >> These processes keep a single database connection open for the lifetime
> of
> >> the process.
> >>
> >> It seems to me that once the reader process accesses the database (after
> >> it
> >> performs its first SELECT statement), it maintains a lock on the
> database
> >> until the connection is closed (when the program is exited). This
> prevents
> >> the writer process from updating the database.
> >>
> >
> > Hi Barry,
> >
> > This is the usual situation when one of your transactions in the "reading
> > only" database does not finalize. i.e. you started a transaction there
> and
> > did not end it with either "END TRANSACTION" or "COMMIT" or "ROLLBACK".
> >
> > In the non-WAL DB it will simply hold the lock preventing changes. In the
> > WAL DB it will hold the lock for its own view of the data but let the
> other
> > writer write.. however it won't see the changes for itself.
> >
> > This is very common actually. Just find every transaction you start
> > (explicitly or implicitly) and make sure you end it and when you end it,
> > see what the return value is from SQLite and whether it reports any
> error.
> >
> > HTH!
> > Ryan
> >
> >
> >
> >> I tried changing to WAL. This made the writer process able to commit its
> >> changes, but now the reader does not see any modifications made to the
> >> database until it is restarted (It seems to see a snapshot of the DB at
> >> the
> >> time of its first read).
> >>
> >> I am using prepared statements: On opening the DB, I create all my
> >> prepared
> >> statements. When I need to execute a statement, I bind to the statement,
> >> call sqlite3_step (possibly multiple times), then call sqlite3_reset. I
> do
> >> not finalise the statements until the program closes.
> >>
> >> In order to simulate 'save' behaviour, the writer process always holds a
> >> transaction open. When the user chooses 'save', the current transaction
> is
> >> committed and a new transaction is begun. (I understand that the reader
> >> will not see any changes in the uncommitted transaction, but is not
> seeing
> >> any committed transactions either).
> >>
> >> I have checked quite thoroughly through my code and cannot find any
> >> instances of statements executed without a sqlite3_reset quickly
> >> following.
> >>
> >> Is this intended behaviour - that once a connection has performed a
> read,
> >> it maintains its lock on the database for its lifetime? Is SQLite smart
> >> enough to know that the pages it holds in cache of the reader are
> invalid
> >> after the writer has made changes to the DB on disk?
> >>
> >> If this is not the intended behaviour - is there a way I can find out
> >> which
> >> statements are causing the lock to be held open? Or can I force SQLite
> to
> >> discard its cache?
> >>
> >> Any help would be appreciated.
> >>
> >> Regards,
> >>
> >> Barry Smith
> >> ___
> >> sqlite-users mailing list
> >> sqlite-users at mailinglists.sqlite.org
> >> http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users
> >>
> >
> > ___
> > sqlite-users mailing list
> > sqlite-users at mailinglists.sqlite.org
> > http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users
> >
> ___
> sqlite-users mailing list
> sqlite-users at mailinglists.sqlite.org
> http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users
>


[sqlite] Releasing a read (SHARED) lock

2015-03-13 Thread Dinu Marina
You should also check, as R.Smith and Slavin pointed, that you don't 
accidentally have a BEGIN [DEFERRED] somewhere, as that would trigger 
exactly this behavior: it will lock on the first select (the first 
step() actually)

On 13.03.2015 02:44, Simon Slavin wrote:
> On 13 Mar 2015, at 12:17am, Barry  wrote:
>
>> On 13 March 2015 at 01:21, Dinu Marina  wrote:
>>
>>> You should be also aware of a more common pitfall: unclosed result sets.
>>> Any lock is held until you read PAST the last row or you call stmt_finalize
>>> (or the equivalent abstraction in your DBAL). Always close select
>>> statements.
>> Hi Dinu,
>>
>> Am I correct in my understanding then that it is not enough to call
>> sqlite3_reset, I must call sqlite3_finalize after I am done with a
>> statement?
> In order to dispose of a statement you can do either sqlite3_reset() or 
> sqlite3_finalize().  The common mistake is to do something like this:
>
> SELECT * FROM myTable WHERE rowid = 36
>
> and then not do either _reset() or _finalize() because you know you have 
> asked for only one row so you expect SQLite to have done a _finalize() for 
> you.
>
> Simon.
> ___
> sqlite-users mailing list
> sqlite-users at mailinglists.sqlite.org
> http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users



[sqlite] Releasing a read (SHARED) lock

2015-03-13 Thread Dinu Marina
Na, it should be the same, everywhere I said finalize you can replace 
with reset; I had this problem come over and over from people forgetting 
to finalize (there was no intention to reuse the statement). But reset 
is the same. My point is just that if you don't have explicit 
transactions, a read lock is acquired by the first step() and not 
released until free() or reset() or step() returning SQLITE_MISUSE due 
to one too many calls and you should check one-rowers (COUNT is the 
usual suspect for me) first to make sure they are finalized (reset) 
properly because they are the easiest to miss, since they don't have an 
ugly loop following. Other than that, there is no reason a lock should 
be held in autocommit mode.

You could debug the reader client this way: create a second connection 
and try to create a write lock (BEGIN EXCLUSIVE) at various points. It 
will return SQLITE_BUSY when you have a leaked lock.


On 13.03.2015 02:17, Barry wrote:
> On 13 March 2015 at 01:21, Dinu Marina  wrote:
>
>> You should be also aware of a more common pitfall: unclosed result sets.
>> Any lock is held until you read PAST the last row or you call stmt_finalize
>> (or the equivalent abstraction in your DBAL). Always close select
>> statements.
>
> Hi Dinu,
>
> Am I correct in my understanding then that it is not enough to call
> sqlite3_reset, I must call sqlite3_finalize after I am done with a
> statement?
>
> Cheers,
>
>   - Barry
>
>
>> On Mar 12, 2015 11:40 AM, "R.Smith"  wrote:
>>
>>>
>>> On 2015-03-12 04:38 AM, Barry wrote:
>>>
 Hello everybody,

 I have a situation where two processes are accessing the same SQLite
 database. One process only reads from the database, one process reads
>> and
 writes.

 These processes keep a single database connection open for the lifetime
>> of
 the process.

 It seems to me that once the reader process accesses the database (after
 it
 performs its first SELECT statement), it maintains a lock on the
>> database
 until the connection is closed (when the program is exited). This
>> prevents
 the writer process from updating the database.

>>> Hi Barry,
>>>
>>> This is the usual situation when one of your transactions in the "reading
>>> only" database does not finalize. i.e. you started a transaction there
>> and
>>> did not end it with either "END TRANSACTION" or "COMMIT" or "ROLLBACK".
>>>
>>> In the non-WAL DB it will simply hold the lock preventing changes. In the
>>> WAL DB it will hold the lock for its own view of the data but let the
>> other
>>> writer write.. however it won't see the changes for itself.
>>>
>>> This is very common actually. Just find every transaction you start
>>> (explicitly or implicitly) and make sure you end it and when you end it,
>>> see what the return value is from SQLite and whether it reports any
>> error.
>>> HTH!
>>> Ryan
>>>
>>>
>>>
 I tried changing to WAL. This made the writer process able to commit its
 changes, but now the reader does not see any modifications made to the
 database until it is restarted (It seems to see a snapshot of the DB at
 the
 time of its first read).

 I am using prepared statements: On opening the DB, I create all my
 prepared
 statements. When I need to execute a statement, I bind to the statement,
 call sqlite3_step (possibly multiple times), then call sqlite3_reset. I
>> do
 not finalise the statements until the program closes.

 In order to simulate 'save' behaviour, the writer process always holds a
 transaction open. When the user chooses 'save', the current transaction
>> is
 committed and a new transaction is begun. (I understand that the reader
 will not see any changes in the uncommitted transaction, but is not
>> seeing
 any committed transactions either).

 I have checked quite thoroughly through my code and cannot find any
 instances of statements executed without a sqlite3_reset quickly
 following.

 Is this intended behaviour - that once a connection has performed a
>> read,
 it maintains its lock on the database for its lifetime? Is SQLite smart
 enough to know that the pages it holds in cache of the reader are
>> invalid
 after the writer has made changes to the DB on disk?

 If this is not the intended behaviour - is there a way I can find out
 which
 statements are causing the lock to be held open? Or can I force SQLite
>> to
 discard its cache?

 Any help would be appreciated.

 Regards,

 Barry Smith
 ___
 sqlite-users mailing list
 sqlite-users at mailinglists.sqlite.org
 http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users

>>> ___
>>> sqlite-users mailing list
>>> sqlite-users at mailinglists.sqlite.org
>>> 

[sqlite] Releasing a read (SHARED) lock

2015-03-13 Thread Kees Nuyt
On Fri, 13 Mar 2015 08:17:26 +0800, Barry  wrote:

>On 13 March 2015 at 01:21, Dinu Marina  wrote:
>
>> You should be also aware of a more common pitfall: unclosed result sets.
>> Any lock is held until you read PAST the last row or you call stmt_finalize
>> (or the equivalent abstraction in your DBAL). Always close select
>> statements.
>
>
>Hi Dinu,
>
>Am I correct in my understanding then that it is not enough to call
>sqlite3_reset, I must call sqlite3_finalize after I am done with a
>statement?

sqlite3_reset() is enough to release the state/context of a statement.
Aditionally, any BEGIN TRANSACTION should be paired with a COMMIT or ROLLBACK.

>Cheers,
>
> - Barry

-- 
Regards, Cordialement, Groet,

Kees Nuyt



[sqlite] Releasing a read (SHARED) lock

2015-03-13 Thread Simon Slavin

On 13 Mar 2015, at 12:17am, Barry  wrote:

> On 13 March 2015 at 01:21, Dinu Marina  wrote:
> 
>> You should be also aware of a more common pitfall: unclosed result sets.
>> Any lock is held until you read PAST the last row or you call stmt_finalize
>> (or the equivalent abstraction in your DBAL). Always close select
>> statements.
> 
> Hi Dinu,
> 
> Am I correct in my understanding then that it is not enough to call
> sqlite3_reset, I must call sqlite3_finalize after I am done with a
> statement?

In order to dispose of a statement you can do either sqlite3_reset() or 
sqlite3_finalize().  The common mistake is to do something like this:

SELECT * FROM myTable WHERE rowid = 36

and then not do either _reset() or _finalize() because you know you have asked 
for only one row so you expect SQLite to have done a _finalize() for you.

Simon.


[sqlite] Releasing a read (SHARED) lock

2015-03-12 Thread Richard Hipp
On 3/12/15, Barry  wrote:
> On 13 March 2015 at 01:21, Dinu Marina  wrote:
>
>> You should be also aware of a more common pitfall: unclosed result sets.
>> Any lock is held until you read PAST the last row or you call
>> stmt_finalize
>> (or the equivalent abstraction in your DBAL). Always close select
>> statements.
>
>
> Hi Dinu,
>
> Am I correct in my understanding then that it is not enough to call
> sqlite3_reset, I must call sqlite3_finalize after I am done with a
> statement?
>

One or the other.  Call sqlite3_reset() if you intend to reuse
prepared statement (run it again).  Call sqlite3_finalize() to destroy
the prepared statement and release all of its resources back to the
system to be reused.  Either is sufficient to release any locks held.

-- 
D. Richard Hipp
drh at sqlite.org


[sqlite] Releasing a read (SHARED) lock

2015-03-12 Thread Dinu Marina
There is also a more obscure side-effect exhibited by sqlite only: if 
you issue consecutive unfinalized select statements, it never releases 
the write lock (although they should be atomic), but it does trip the 
deadlock mechanism; any writer in the wait will receive SQLITE_BUSY at 
the very moment the second read statement is issued, regardless of the 
busy_timeout value.
This happens in non-WAL mode.

The usual culprit are one-record results, like SELECT COUNT(*)... 
usually the client expects one row and reads one row, but you need to 
either try to read 2 rows or explicitly free the cursor.

Do note (for evangelism sake) that DBs with random-access cursors do not 
free the read lock even when you read past the last record, because you 
could decide to rewind. So always free result sets.


[sqlite] Releasing a read (SHARED) lock

2015-03-12 Thread Dinu Marina
You should be also aware of a more common pitfall: unclosed result sets.
Any lock is held until you read PAST the last row or you call stmt_finalize
(or the equivalent abstraction in your DBAL). Always close select
statements.
On Mar 12, 2015 11:40 AM, "R.Smith"  wrote:

>
>
> On 2015-03-12 04:38 AM, Barry wrote:
>
>> Hello everybody,
>>
>> I have a situation where two processes are accessing the same SQLite
>> database. One process only reads from the database, one process reads and
>> writes.
>>
>> These processes keep a single database connection open for the lifetime of
>> the process.
>>
>> It seems to me that once the reader process accesses the database (after
>> it
>> performs its first SELECT statement), it maintains a lock on the database
>> until the connection is closed (when the program is exited). This prevents
>> the writer process from updating the database.
>>
>
> Hi Barry,
>
> This is the usual situation when one of your transactions in the "reading
> only" database does not finalize. i.e. you started a transaction there and
> did not end it with either "END TRANSACTION" or "COMMIT" or "ROLLBACK".
>
> In the non-WAL DB it will simply hold the lock preventing changes. In the
> WAL DB it will hold the lock for its own view of the data but let the other
> writer write.. however it won't see the changes for itself.
>
> This is very common actually. Just find every transaction you start
> (explicitly or implicitly) and make sure you end it and when you end it,
> see what the return value is from SQLite and whether it reports any error.
>
> HTH!
> Ryan
>
>
>
>> I tried changing to WAL. This made the writer process able to commit its
>> changes, but now the reader does not see any modifications made to the
>> database until it is restarted (It seems to see a snapshot of the DB at
>> the
>> time of its first read).
>>
>> I am using prepared statements: On opening the DB, I create all my
>> prepared
>> statements. When I need to execute a statement, I bind to the statement,
>> call sqlite3_step (possibly multiple times), then call sqlite3_reset. I do
>> not finalise the statements until the program closes.
>>
>> In order to simulate 'save' behaviour, the writer process always holds a
>> transaction open. When the user chooses 'save', the current transaction is
>> committed and a new transaction is begun. (I understand that the reader
>> will not see any changes in the uncommitted transaction, but is not seeing
>> any committed transactions either).
>>
>> I have checked quite thoroughly through my code and cannot find any
>> instances of statements executed without a sqlite3_reset quickly
>> following.
>>
>> Is this intended behaviour - that once a connection has performed a read,
>> it maintains its lock on the database for its lifetime? Is SQLite smart
>> enough to know that the pages it holds in cache of the reader are invalid
>> after the writer has made changes to the DB on disk?
>>
>> If this is not the intended behaviour - is there a way I can find out
>> which
>> statements are causing the lock to be held open? Or can I force SQLite to
>> discard its cache?
>>
>> Any help would be appreciated.
>>
>> Regards,
>>
>> Barry Smith
>> ___
>> sqlite-users mailing list
>> sqlite-users at mailinglists.sqlite.org
>> http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users
>>
>
> ___
> sqlite-users mailing list
> sqlite-users at mailinglists.sqlite.org
> http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users
>


[sqlite] Releasing a read (SHARED) lock

2015-03-12 Thread R.Smith


On 2015-03-12 04:38 AM, Barry wrote:
> Hello everybody,
>
> I have a situation where two processes are accessing the same SQLite
> database. One process only reads from the database, one process reads and
> writes.
>
> These processes keep a single database connection open for the lifetime of
> the process.
>
> It seems to me that once the reader process accesses the database (after it
> performs its first SELECT statement), it maintains a lock on the database
> until the connection is closed (when the program is exited). This prevents
> the writer process from updating the database.

Hi Barry,

This is the usual situation when one of your transactions in the 
"reading only" database does not finalize. i.e. you started a 
transaction there and did not end it with either "END TRANSACTION" or 
"COMMIT" or "ROLLBACK".

In the non-WAL DB it will simply hold the lock preventing changes. In 
the WAL DB it will hold the lock for its own view of the data but let 
the other writer write.. however it won't see the changes for itself.

This is very common actually. Just find every transaction you start 
(explicitly or implicitly) and make sure you end it and when you end it, 
see what the return value is from SQLite and whether it reports any error.

HTH!
Ryan


>
> I tried changing to WAL. This made the writer process able to commit its
> changes, but now the reader does not see any modifications made to the
> database until it is restarted (It seems to see a snapshot of the DB at the
> time of its first read).
>
> I am using prepared statements: On opening the DB, I create all my prepared
> statements. When I need to execute a statement, I bind to the statement,
> call sqlite3_step (possibly multiple times), then call sqlite3_reset. I do
> not finalise the statements until the program closes.
>
> In order to simulate 'save' behaviour, the writer process always holds a
> transaction open. When the user chooses 'save', the current transaction is
> committed and a new transaction is begun. (I understand that the reader
> will not see any changes in the uncommitted transaction, but is not seeing
> any committed transactions either).
>
> I have checked quite thoroughly through my code and cannot find any
> instances of statements executed without a sqlite3_reset quickly following.
>
> Is this intended behaviour - that once a connection has performed a read,
> it maintains its lock on the database for its lifetime? Is SQLite smart
> enough to know that the pages it holds in cache of the reader are invalid
> after the writer has made changes to the DB on disk?
>
> If this is not the intended behaviour - is there a way I can find out which
> statements are causing the lock to be held open? Or can I force SQLite to
> discard its cache?
>
> Any help would be appreciated.
>
> Regards,
>
> Barry Smith
> ___
> sqlite-users mailing list
> sqlite-users at mailinglists.sqlite.org
> http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users



[sqlite] Releasing a read (SHARED) lock

2015-03-12 Thread Barry
Hello everybody,

I have a situation where two processes are accessing the same SQLite
database. One process only reads from the database, one process reads and
writes.

These processes keep a single database connection open for the lifetime of
the process.

It seems to me that once the reader process accesses the database (after it
performs its first SELECT statement), it maintains a lock on the database
until the connection is closed (when the program is exited). This prevents
the writer process from updating the database.

I tried changing to WAL. This made the writer process able to commit its
changes, but now the reader does not see any modifications made to the
database until it is restarted (It seems to see a snapshot of the DB at the
time of its first read).

I am using prepared statements: On opening the DB, I create all my prepared
statements. When I need to execute a statement, I bind to the statement,
call sqlite3_step (possibly multiple times), then call sqlite3_reset. I do
not finalise the statements until the program closes.

In order to simulate 'save' behaviour, the writer process always holds a
transaction open. When the user chooses 'save', the current transaction is
committed and a new transaction is begun. (I understand that the reader
will not see any changes in the uncommitted transaction, but is not seeing
any committed transactions either).

I have checked quite thoroughly through my code and cannot find any
instances of statements executed without a sqlite3_reset quickly following.

Is this intended behaviour - that once a connection has performed a read,
it maintains its lock on the database for its lifetime? Is SQLite smart
enough to know that the pages it holds in cache of the reader are invalid
after the writer has made changes to the DB on disk?

If this is not the intended behaviour - is there a way I can find out which
statements are causing the lock to be held open? Or can I force SQLite to
discard its cache?

Any help would be appreciated.

Regards,

Barry Smith