mirror of
https://github.com/tursodatabase/libsql.git
synced 2025-06-14 20:33:00 +00:00
.cargo
.github
bindings
bottomless
bottomless-cli
docker-compose
docs
libsql
libsql-ffi
libsql-hrana
libsql-replication
libsql-server
libsql-shell
libsql-sqlite3
art
autoconf
contrib
crates
doc
F2FS.txt
compile-for-windows.md
json-enhancements.md
lemon.html
libsql_extensions.md
pager-invariants.txt
testrunner.md
trusted-schema.md
vdbesort-memory.md
vfs-shm.txt
wal-lock.md
ext
mptest
src
test
tool
vsixtest
.gitignore
Dockerfile-wasm-udf
LIBSQL_VERSION
LICENSE.md
Makefile.in
Makefile.linux-gcc
Makefile.msc
README-SQLite.md
VERSION
aclocal.m4
config.guess
config.sub
configure
configure.ac
install-sh
libsql.pc.in
ltmain.sh
magic.txt
main.mk
manifest
manifest.uuid
spec.template
sqlite.pc.in
sqlite3.1
sqlite3.pc.in
sqlite_cfg.h.in
libsql-sys
tools
vendored
xtask
.dockerignore
.env
.gitignore
.gitmodules
CODE_OF_CONDUCT.md
Cargo.lock
Cargo.toml
Dockerfile
Dockerfile.dev
LICENSE.md
README-libsql.md
README.md
docker-entrypoint.sh
fly.toml
rust-toolchain.toml
89 lines
3.6 KiB
Markdown
89 lines
3.6 KiB
Markdown
![]() |
# Wal-Mode Blocking Locks
|
||
|
|
||
|
On some Unix-like systems, SQLite may be configured to use POSIX blocking locks
|
||
|
by:
|
||
|
|
||
|
* building the library with SQLITE\_ENABLE\_SETLK\_TIMEOUT defined, and
|
||
|
* configuring a timeout in ms using the sqlite3\_busy\_timeout() API.
|
||
|
|
||
|
Blocking locks may be advantageous as (a) waiting database clients do not
|
||
|
need to continuously poll the database lock, and (b) using blocking locks
|
||
|
facilitates transfer of OS priority between processes when a high priority
|
||
|
process is blocked by a lower priority one.
|
||
|
|
||
|
Only read/write clients use blocking locks. Clients that have read-only access
|
||
|
to the \*-shm file nevery use blocking locks.
|
||
|
|
||
|
Threads or processes that access a single database at a time never deadlock as
|
||
|
a result of blocking database locks. But it is of course possible for threads
|
||
|
that lock multiple databases simultaneously to do so. In most cases the OS will
|
||
|
detect the deadlock and return an error.
|
||
|
|
||
|
## Wal Recovery
|
||
|
|
||
|
Wal database "recovery" is a process required when the number of connected
|
||
|
database clients changes from zero to one. In this case, a client is
|
||
|
considered to connect to the database when it first reads data from it.
|
||
|
Before recovery commences, an exclusive WRITER lock is taken.
|
||
|
|
||
|
Without blocking locks, if two clients attempt recovery simultaneously, one
|
||
|
fails to obtain the WRITER lock and either invokes the busy-handler callback or
|
||
|
returns SQLITE\_BUSY to the user. With blocking locks configured, the second
|
||
|
client blocks on the WRITER lock.
|
||
|
|
||
|
## Database Readers
|
||
|
|
||
|
Usually, read-only are not blocked by any other database clients, so they
|
||
|
have no need of blocking locks.
|
||
|
|
||
|
If a read-only transaction is being opened on a snapshot, the CHECKPOINTER
|
||
|
lock is required briefly as part of opening the transaction (to check that a
|
||
|
checkpointer is not currently overwriting the snapshot being opened). A
|
||
|
blocking lock is used to obtain the CHECKPOINTER lock in this case. A snapshot
|
||
|
opener may therefore block on and transfer priority to a checkpointer in some
|
||
|
cases.
|
||
|
|
||
|
## Database Writers
|
||
|
|
||
|
A database writer must obtain the exclusive WRITER lock. It uses a blocking
|
||
|
lock to do so if any of the following are true:
|
||
|
|
||
|
* the transaction is an implicit one consisting of a single DML or DDL
|
||
|
statement, or
|
||
|
* the transaction is opened using BEGIN IMMEDIATE or BEGIN EXCLUSIVE, or
|
||
|
* the first SQL statement executed following the BEGIN command is a DML or
|
||
|
DDL statement (not a read-only statement like a SELECT).
|
||
|
|
||
|
In other words, in all cases except when an open read-transaction is upgraded
|
||
|
to a write-transaction. In that case a non-blocking lock is used.
|
||
|
|
||
|
## Database Checkpointers
|
||
|
|
||
|
Database checkpointers takes the following locks, in order:
|
||
|
|
||
|
* The exclusive CHECKPOINTER lock.
|
||
|
* The exclusive WRITER lock (FULL, RESTART and TRUNCATE only).
|
||
|
* Exclusive lock on read-mark slots 1-N. These are immediately released after being taken.
|
||
|
* Exclusive lock on read-mark 0.
|
||
|
* Exclusive lock on read-mark slots 1-N again. These are immediately released
|
||
|
after being taken (RESTART and TRUNCATE only).
|
||
|
|
||
|
All of the above use blocking locks.
|
||
|
|
||
|
## Summary
|
||
|
|
||
|
With blocking locks configured, the only cases in which clients should see an
|
||
|
SQLITE\_BUSY error are:
|
||
|
|
||
|
* if the OS does not grant a blocking lock before the configured timeout
|
||
|
expires, and
|
||
|
* when an open read-transaction is upgraded to a write-transaction.
|
||
|
|
||
|
In all other cases the blocking locks implementation should prevent clients
|
||
|
from having to handle SQLITE\_BUSY errors and facilitate appropriate transfer
|
||
|
of priorities between competing clients.
|
||
|
|
||
|
Clients that lock multiple databases simultaneously must be wary of deadlock.
|
||
|
|
||
|
|