What is the default value of sqlite3_busy_timeout? - sqlite

This seems like it should be really easy to find out, but I don't see it documented anywhere. If I open a sqlite connection and begin a transaction without specifying a timeout by calling sqlite3_busy_timeout, what default value is used? Or will this somehow cause undefined behavior? The documentation of this method doesn't say.
My specific use case is the version bundled with iOS, but I'm guessing the answer is pretty much the same across platforms.

If neither sqlite3_busy_timeout() nor sqlite3_busy_handler() are set and a writer is active then step() returns SQLITE_BUSY immediately.
Note: In some cases SQLITE_IOERR_BLOCKED is returned
See also: Register A Callback To Handle SQLITE_BUSY Errors in the second paragraph where it states
If the busy callback is NULL, then SQLITE_BUSY or SQLITE_IOERR_BLOCKED is returned immediately upon encountering the lock. If the busy callback is not NULL, then the callback might be invoked with two arguments.

You can try doing this:
sqlite> PRAGMA busy_timeout = 30000;
It sets the busy_timeout pragma to 30 seconds.
https://www.sqlite.org/pragma.html#pragma_busy_timeout
From what I've read (the default is 0) which I assume is either immediate busy response or unlimited waiting. Docs don't say. However I am seeing when multiple processes write to db, they will sometimes throw a BUSY error.

Related

Can we compile procedure or function if there is DDL lock on that procedure?

procedure cannot be compiled? it is just running and nothing happened.
and I have try following code to check whether any block session make this. but I did not find any blocked session.
select
*
from
v$session
where
blocking_session is not NULL
order by
blocking_session;
You won't find it as a blocking session, nor in gv$lock, because it's a library object lock rather than a data object lock. Instead, look at gv$access and/or dba_ddl_locks. You can also look at gv$session for a plsql_object_id or plsql_entry_object_id matching the object_id of your procedure in either dba_objects or dba_procedures. That's not a sure-fire way of catching everything though, if you have chained PL/SQL calls... but gv$access and/or dba_ddl_locks will have what you need for sure.
If something is executing your procedure, you will have to wait for them to complete, or kill their session, before you can compile it. It's a weak point in Oracle, that prevents us from pushing code changes in without kicking everybody out first. But that's the way it is.
I found that there is a lot of rows in the table and whenever I try to compile procedure it can call that table too. So I Stop the compilation process at that time and execute the rollback statement. Therefore it takes time to rollback milions of rows one by one I have tracked those process through the following script.
select s.sid, s.serial#, s.client_info, t.addr, sum(t.used_ublk)
from v$transaction t, v$session s
where t.addr = s.taddr
group by s.sid, s.serial#, s.client_info, t.addr;
I just need to wait and might be I did not find any idea about to do anything except waiting. When all the transactions are rollbacked then I try to compile it and it compiled.

Checking for Null Statements in SQLite3

Does anyone know how to check if a statement has been prepared or not? I have searched through the SQLite documentation for statements and searched SO, DreamInCode, and DaniWeb but have found no references to my exact question.
I have a statement that I only call in specific circumstances and I only want to attempt to finalize it if it has been used since program crashes are happening by trying to finalize a statement that has not been used. I would rather use whatever SQLite has built-in instead of extra code but I will do just that if there is no null-checking for statements.
The documentation says:
Invoking sqlite3_finalize() on a NULL pointer is a harmless no-op.
So just ensure that your sqlite3_stmt* variables are initialized with NULL, and are reset to NULL when finalized.

Is there a way to acquire a lock in Redis? (Node.js)

My Node.js application accepts connections from the outside. Each connection handler reads a SET on Redis, eventually modifies the set itself, then moves on. The problem is that in the meanwhile another async connection can try to read the same SET and try to update it or decide its next step based on what it reads.
I know that Redis does its best to be atomic, but this is not quite sufficient for my use case. Think about this: the set is read to understand if it's FULL (there is a business rule for that). If it's FULL, then something happens. The problem is that if there is one only slot left, two semi-concurrent connections could think each one is the last one. And I get an overflow.
I there a way to keep a connection "waiting" for the very short time the other eventually needs to update the set state?
I think this is a corner case, very very unluckely... but you know :)
Using another key as the "lock" is an option, or does it stink?
How about using blpop to do locking. blpop key 5 to wait 5 seconds for key. At start put item(to identify queue is not empty) at key. The connection acquiring the lock should remove item from key. The next connect then can't acquire the lock, because empty, but blpop has the following nice property:
Multiple clients can block for the same key. They are put into a
queue, so the first to be served will be the one that started to wait
earlier, in a first-BLPOP first-served fashion.
When connection which acquired lock has finished task it should put back item back in queue, then the next connection waiting can acquire lock(item).
You may be looking for WATCH with MULTI/EXEC. Here's the pattern that both threads follow:
WATCH sentinel_key
GET value_of_interest
if (value_of_interest = FULL)
MULTI
SET sentinel_key = foo
EXEC
if (EXEC returned 1, i.e. succeeded)
do_something();
else
do_nothing();
else
UNWATCH
The way this works is that all of the commands between MULTI and EXEC are queued up but not actually executed until EXEC is called. When EXEC is called, before actually executing the queued instructions it checks to see if sentinel_key has changed at all since the WATCH was set; if it has, it returns (nil) and the queued commands are discarded. Otherwise the commands are executed atomically as a block, and it returns the number of commands executed (1 in this case), letting you know you won the race and do_something() can be called.
It's conceptually similar to the fork()/exec() Unix system calls - the return value from fork() tells you which process you are (parent or child). In this case it tells you whether you won the race or not.

PL/SQL wait for update in Oracle

How do I create PL/SQL function which waits for update on some row for specified timeout and then returns.
What I want to accomplish is - I have long running process which will update it's status to ASYNC_PROCESS table by process_id. I need function which returns with true/false when this process has completed, but also I need this function to wait some time for this process complete, return on timeout or return imediately with true, when process has completed. I don't want to use sleep(1 sec), because in such case I will be having 1 sec lag. I don't want to use sleep(1 msec), because in such case I am spending cpu resources (and 1msec lag).
Is there a good way how experienced programmer would accomplish this?
That function will be called from .NET (So I need minimal lag between DB operation and .NET/UI)
THNX,
Beef
I think the most sensible thing to do in this case is to use update triggers on that ASYNC_PROCESS table.
You should also look into the DBMS_ALERT package. Here's an edited excerpt from that doc:
Create an alert:
DBMS_ALERT.REGISTER('emp_table_alert');
Create a trigger on your table to fire the alert:
CREATE TRIGGER emptrig AFTER INSERT ON emp
BEGIN
DBMS_ALERT.SIGNAL('emp_table_alert', 'message_text');
END;
From your .net code, you can the use something that calls this:
DBMS_ALERT.WAITONE('emp_table_alert', :message, :status, :timeout);
Make sure you read the docs for what :status and :timeout do.
You should look at Oracle Advanced Queuing. It offers the kind of functions your looking for.
You'll probably need a separate queue table where a trigger on ASYNC_PROCESS inserts messages. You then use the AQ functions to retrieve (or wait for) the next message in the queue table.
If you're doing this in C#.NET, why wouldn't you simply spawn a worker thread to do the update (via ODAC)? Why hand the responsibility over to Oracle when (it seems) you want a .NET process to make the update call (in background) and have the main process be notified of its completion.
See here and here for examples, although there are several approaches in .NET for this (delegates, events, async callbacks, thread pools, etc)

Can I call SQLExecute after SQLFreeStmt without SQLPrepare?

I have the following sequence of code calls:
SQLPrepare
SQLExecute(hstmt, SQL_CLOSE);
SQLFreeStmt
//It works till here
SQLExecute //Now it fails.
Why am I required to call SQLPrepare again, I just freed the cursor. I shouldn't prepare the SQL statement again.
The correct behaviour is that SQLPrepare/SQLExecute/SQLFreStmt(stmt, SQL_CLOSE) should allow another SQLExecute on the same stmt handle without re-preparing. You can see this as a valid state transition in the ODBC Programmers Guide. You might use this sequence if you had done a SQLPrepare(sql) and only fetched some of the rows (instead of all of them) as without the SQLFreeStmt(stmt, SQL_CLOSE) or fetching until SQL_NO_DATA was returned you'd get an invalid cursor state if you issued another SQLExecute. SQLFreeStmt(stmt, SQL_DROP) is equivalent to SQLFreeHandle(SQL_HANDLESTMT,stmt) and frees the entire stmt handle meaning you cannot use it again at all.
SQLFreeStmt(hstmt, SQL_CLOSE) cleans up everything to do with that statement handle, take a look at the summary:
SQLFreeStmt stops processing
associated with a specific statement,
closes any open cursors associated
with the statement, discards pending
results, or, optionally, frees all
resources associated with the
statement handle.
If you don't want to use SQLPrepare again you can use SQLExecDirect instead.

Resources