在Azure中,SQLite3数据库被锁定

13

我在由Azure应用服务提供的Azure上运行了一个Flask服务器,并使用sqlite3作为数据库。 由于显示数据库被锁定,因此我无法更新sqlite3。

    2018-11-09T13:21:53.854367947Z [2018-11-09 13:21:53,835] ERROR in app: Exception on /borrow [POST]
    2018-11-09T13:21:53.854407246Z Traceback (most recent call last):
    2018-11-09T13:21:53.854413046Z   File "/home/site/wwwroot/antenv/lib/python3.7/site-packages/flask/app.py", line 2292, in wsgi_app
    2018-11-09T13:21:53.854417846Z     response = self.full_dispatch_request()
    2018-11-09T13:21:53.854422246Z   File "/home/site/wwwroot/antenv/lib/python3.7/site-packages/flask/app.py", line 1815, in full_dispatch_request
    2018-11-09T13:21:53.854427146Z     rv = self.handle_user_exception(e)
    2018-11-09T13:21:53.854431646Z   File "/home/site/wwwroot/antenv/lib/python3.7/site-packages/flask/app.py", line 1718, in handle_user_exception
    2018-11-09T13:21:53.854436146Z     reraise(exc_type, exc_value, tb)
    2018-11-09T13:21:53.854440346Z   File "/home/site/wwwroot/antenv/lib/python3.7/site-packages/flask/_compat.py", line 35, in reraise
    2018-11-09T13:21:53.854444746Z     raise value
    2018-11-09T13:21:53.854448846Z   File "/home/site/wwwroot/antenv/lib/python3.7/site-packages/flask/app.py", line 1813, in full_dispatch_request
    2018-11-09T13:21:53.854453246Z     rv = self.dispatch_request()
    2018-11-09T13:21:53.854457546Z   File "/home/site/wwwroot/antenv/lib/python3.7/site-packages/flask/app.py", line 1799, in dispatch_request
    2018-11-09T13:21:53.854461846Z     return self.view_functions[rule.endpoint](**req.view_args)
    2018-11-09T13:21:53.854466046Z   File "/home/site/wwwroot/application.py", line 282, in borrow
    2018-11-09T13:21:53.854480146Z     cursor.execute("UPDATE books SET stock = stock - 1 WHERE bookid = ?",(bookid,))
    2018-11-09T13:21:53.854963942Z sqlite3.OperationalError: database is locked

这里是路线 -

@app.route('/borrow',methods=["POST"])
def borrow():
    # import pdb; pdb.set_trace()
    body = request.get_json()
    user_id = body["userid"]
    bookid = body["bookid"]
    conn = sqlite3.connect("database.db")
    cursor = conn.cursor()
    date = datetime.now()
    expiry_date = date + timedelta(days=30)
    cursor.execute("UPDATE books SET stock = stock - 1 WHERE bookid = ?",(bookid,))
    # conn.commit()
    cursor.execute("INSERT INTO borrowed (issuedate,returndate,memberid,bookid) VALUES (?,?,?,?)",("xxx","xxx",user_id,bookid,))
    conn.commit()
    cursor.close()
    conn.close()

    return json.dumps({"status":200,"conn":"working with datess update"})

我尝试使用pragma检查数据库的完整性,但没有发现任何完整性损失。因此,我不知道是什么导致了那个错误。感谢任何帮助 :)


可能有其他程序正在使用该数据库并拥有独占锁。一次只能有一个连接写入sqlite数据库。 - Shawn
6个回答

11
我在Linux上使用Azure应用程序服务中的Docker,也遇到了相同的问题。如果您正在使用Windows上的Azure应用程序服务,则问题与我的不同。
问题是/home被挂载为CIFS文件系统,该文件系统无法处理SQLite3锁定。我的解决方法是将db.sqlite3文件复制到除/home以外的某个目录,并适当设置db.sqlite3文件及其目录的权限和所有权,然后让我的项目对其进行读/写操作。但是,这种解决方法非常笨拙。我不建议这样做。

1
你能详细解释一下“除了/home之外的某个目录”吗?我遇到了相同的问题,想知道是否可以将文件保存到类似于“/tmp”的地方,以便在需要操作该文件时使用,并在只需要持久存储它时将其移动到“/home”。 - Michael Xu
回复我的评论:我认为它正在工作.. 但如果有人对这是否是一个合理的方式有任何见解,仍然很想听听。 - Michael Xu
1
嗨。我记不清了,但我想我在 / 目录下创建了一个目录,或者我使用了 /tmp。如果没有错误的话,我认为它可以正常工作。 - seiichi
1
如果您将其存储在 /tmp 中,那么在 AppService 的基本重启后,该文件将会消失。 - Genfood

9

假设这个解决方案对于生产工作负载来说并不安全,但至少我通过执行以下命令使其正常工作:

sqlite3 <database-file> 'PRAGMA journal_mode=wal;'

在运行上述命令之后,我在一个Azure文件共享中存储的数据库可以在容器Web应用程序中运行。

这个解决方案对我很有效 - 在Azure文件共享中使用Linux上的Azure应用服务容器和数据库文件。 - sspaniel
我必须在 /tmp 上创建 DB 文件,运行命令,然后将其移动到已挂载的卷上。 - Yochai Lehman

5

我是通过以下配置设置 Azure 挂载选项来实现的:

dir_mode=0777,file_mode=0777,uid=0,gid=0,mfsymlinks,nobrl,cache=strict

但真正的解决方案是添加标志 nobrl (字节范围锁定)。

为kubernetes添加存储类示例:

---
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: azureclass
provisioner: kubernetes.io/azure-file
mountOptions:
  - dir_mode=0777
  - file_mode=0777
  - uid=0
  - gid=0
  - mfsymlinks
  - nobrl
  - cache=strict
parameters:
  skuName: Standard_LRS

我在运行在AKS上的一个带有这种存储类的pv上的pgadmin 4容器上遇到了同样的问题,在初始化时SQLite报错“数据库被锁定”。这个设置解决了我的问题。微软在其文档中也提供了一些相关参考此处。 谢谢! - pablo.bueti

1

此答案出现在典型谷歌搜索的顶部,因此我想添加一些额外的技巧:

对于那些运行JavaScript并使用Sequelize作为与SQLite DB的接口的人,在创建数据库之前运行

await sequelize.query('PRAGMA journal_mode=WAL;')

将使您能够在运行在Linux服务计划下的Azure Web应用程序中读取/写入DB文件。我有一个单独的脚本通过调用sequelize.sync()来创建它。我将DB文件存储在Linux容器文件系统中的/ home下的单独目录中。它似乎可以正常运行,而我的工作负载预计非常轻。请注意,当您的应用程序启动并尝试连接到数据库时,无需再次设置日志记录模式,该模式将设置在文件本身中(这在SQLite文档中并不明显)。


0
我之前在使用免费的F1级别的网络服务。升级到B1级别后问题得到解决。在应用了迁移后,我又成功地降回到了F1级别。

0

那个问题对我来说已经消失了。

sqlite3 v5.1.5

Azure Linux-Development (S1: 1)

NodeJS Web应用程序是默认设置的,主目录仍然作为CIFS挂载,可能更改的是模式-0777:

/home type cifs (rw,relatime,vers=3.1.1,cache=strict,username=secretuserid,uid=0,noforceuid,gid=0,noforcegid,addr=secretip,file_mode=0777,dir_mode=0777,soft,nounix,serverino,mapposix,nobrl,mfsymlinks,noperm,rsize=1048576,wsize=4194304,bsize=1048576,echo_interval=60,actimeo=1)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接