SQLite非独占的RESERVED锁是什么?

4
我一直在研究如何提高我的网站的SQLite性能,特别是关于事务处理。我希望找到一种方法来延迟进程中的数据库写入,以便可以一次性完成所有写入操作。然而,在我累积更新查询时,我希望其他进程能够读取和写入数据库,并且只有在进程发出提交命令后才锁定文件进行写入。
查看文档后,似乎一旦在事务中发出更新命令,进程就会获得一个保留锁,这意味着任何尝试将更新查询添加到自己的事务或提交事务的其他进程都无法执行,因此会被阻塞,直到拥有锁的进程提交事务。
我相信这种特殊功能存在非常好的数据完整性原因。我只能说,在我的情况下,同时执行这些更新没有危险。
一种解决方案是在每个进程中累积要调用的查询文本,然后在准备好写入时循环它,但我想知道是否可能让SQLite事务自动为我完成这项工作。
更新:当我说“一次性执行所有更新”时,实质上是使用SQLite中的事务,每个进程只获取一次排他锁并写入磁盘,而不是每个查询都获取一次锁。这可以使用SQLite实现100倍的速度提升。
我进行了一些基本测试,发现一旦有多个进程将查询添加到它们的事务中,一旦遇到更新查询,该进程就会尝试获取保留锁。由于只有一个进程可以拥有保留锁,这意味着任何其他尝试获取锁的进程都将被阻塞,直到拥有锁的进程完成事务。
我承认这个问题可能是一种过早优化,因为我还没有遇到任何性能损失,但我已经运行了一些简单的测试,在我的机器上,100个用户每个创建和运行具有100个查询的事务大约需要4秒钟的PHP时间。
2个回答

3

SQLite支持 ATTACH将一个数据库附加到另一个数据库。也许您可以在一个单独的数据库中累积数据,当您准备合并累积的行时,附加该单独的数据库,通过一个语句复制行,然后分离。

编辑:在sqlite-users的邮件列表线程上提出了类似于OP的建议,并进行了一些后续讨论mailing list thread


可能会起作用,但看起来像是一个丑陋的hack。它能获得什么样的性能? - Kyle Cronin
1
性能可以非常出色,因为每个数据库中的事务虽然没有连接,但彼此之间不会干扰。当数据累积在一个内存数据库中,并将其附加到主数据库时,这种方法尤其有效。 - Doug Currie

1
比附加数据库更好的方法是只创建临时表。(CREATE TEMPORARY ...)
并且看一下新的WAL日志模式,它可以自动完成您手动尝试做的事情,并允许同时写入和读取(不过不能同时写入)。
#pragma journal_mode=WAL

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