ssi*_*ono 5 sqlite locking command-line-interface thread-safety
我有一个 sqlite3 数据库文件,多个进程通过 shell 脚本中的 sqlite3 命令实用程序同时访问该文件。
这有时会导致database is locked编写时出现某种错误。
问题是我没有任何性能问题,但我只是希望每个查询都阻塞,直到数据库解锁,然后完成其工作。现在它只是失败了,所以唯一的方法就是捕获失败并继续重试。
有什么办法可以实现这一点吗?
我检查了有关sqlite 线程安全的文档,它基本上说序列化模式是最“线程友好”的。检查编译选项时
echo 'pragma compile_options' | sqlite3 db.db | grep -i threadsafe
Run Code Online (Sandbox Code Playgroud)
我知道THREADSAFE=1哪个确实是序列化的(默认)。
这是一个演示该问题的示例脚本:
#! /bin/bash
rm -f db.db
echo 'CREATE TABLE animals (
id integer primary key autoincrement,
name varchar
)' | sqlite3 db.db
echo "insert into animals(name) values('rabbit')" | sqlite3 db.db &
echo "insert into animals(name) values('rabbit')" | sqlite3 db.db &
echo "insert into animals(name) values('rabbit')" | sqlite3 db.db &
echo "insert into animals(name) values('rabbit')" | sqlite3 db.db &
echo "insert into animals(name) values('rabbit')" | sqlite3 db.db &
Run Code Online (Sandbox Code Playgroud)
输出是这样的
Error: near line 1: database is locked
Error: near line 1: database is locked
Error: near line 1: database is locked
Run Code Online (Sandbox Code Playgroud)
五只动物中只有两只被插入。我只希望每个查询都能成功,即使由于请求排队而需要更多时间。
sqlite3 版本 3.22.0
sqlite3 shell 的命令可用于指定在尝试打开锁定的数据库时在给出错误之前.timeout等待的毫秒数。因此,请尝试更改您的脚本来使用它;像这样的东西:
#!/bin/bash
# A 1 second busy timeout
timeout=1000
rm -f db.db
sqlite3 db.db <<EOF
CREATE TABLE animals (
id integer primary key autoincrement,
name text
);
EOF
sqlite3 db.db <<EOF &
.timeout $timeout
insert into animals(name) values('rabbit 1');
EOF
sqlite3 db.db <<EOF &
.timeout $timeout
insert into animals(name) values('rabbit 2');
EOF
sqlite3 db.db <<EOF &
.timeout $timeout
insert into animals(name) values('rabbit 3');
EOF
sqlite3 db.db <<EOF &
.timeout $timeout
insert into animals(name) values('rabbit 4');
EOF
Run Code Online (Sandbox Code Playgroud)
请注意使用heredocs,而不是使用echo. 当向脚本中的进程标准输入发送大量文字文本时,它们会派上用场。
这也与线程无关;这些都是单独的进程,而不是线程。