Run the provided function in a DB transaction. A rollback is performed if an exception is raised inside the transaction.
If the BEGIN or COMMIT SQL statements from the outermost transaction fail with SQLITE_BUSY
, they will be retried until they can be executed. A SQLITE_BUSY
(or any other) error code in any other operation inside a transaction will result in an Error (_, Sqlite_error (code, _))
exception being thrown, and a rollback performed. Refer to set_retry_on_busy
.
One consequence of this is that concurrency control is very simple if you use `EXCLUSIVE
transactions: the code can be written straightforwardly as S.transaction db (fun db -> ...)
, and their execution will be serialized (across both threads and processes). Note that, for `IMMEDIATE
and `DEFERRED
transactions, you will have to retry manually if an Error (_, Sqlite_error (Sqlite3.Rc.Busy, _))
is raised.
All SQL operations performed within a transaction will use the same worker. This worker is used exclusively by only one thread per instantiated module (see steal_worker
). That is, given
module S1 = Sqlexpr_sqlite.Make(Sqlexpr_concurrency.Id)
module S2 = Sqlexpr_sqlite.Make(Sqlexpr_concurrency.Lwt)
let db = S1.open_db somefile
there is no exclusion between functions from S1
and those from S2
.