我可以等待在 cli 上释放 sqlite 锁吗?

Can i wait for sqlite lock to be released on the cli?

我有一个 sqlite3 数据库文件,多个进程通过来自 shell 个脚本的 sqlite3 命令实用程序同时访问它。

这有时会在写入时导致一些 database is locked 类错误。

问题是我没有任何性能问题,但我只想让每个查询都阻塞,直到数据库解锁,然后再执行它的工作。现在它只是失败了,所以唯一的办法就是抓住失败并继续重试。

有什么办法可以实现吗?

我查看了关于thread safety with sqlite的文档,基本上说序列化模式是最多的"thread friendly"。检查编译选项时

echo 'pragma compile_options' | sqlite3 db.db | grep -i threadsafe

我得到 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 &

输出类似于

Error: near line 1: database is locked
Error: near line 1: database is locked
Error: near line 1: database is locked

5 只动物中只有 2 只被插入。我只希望每个查询都能成功,即使由于请求排队需要更多时间。


sqlite3 版本 3.22.0

sqlite3 shell的.timeout命令可用于指定wait while trying to open a locked database出现错误前的毫秒数。因此,请尝试更改您的脚本以使用它;像这样:

#!/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

注意使用 heredocs,而不是使用 echo。在将大量文字文本发送到脚本中的进程标准输入时,它们会派上用场。

这也与线程无关;这些都是独立的进程,而不是线程。