我希望能够判断SQLite数据库文件是否已经以任何方式更新。我将如何实施?
我想到的第一个解决方案是比较校验和,但我没有任何使用校验和的经验。
答案 0 :(得分:6)
根据http://www.sqlite.org/fileformat.html,SQLite3在数据库文件的字节file change counter
中维护24..27
。它与文件更改时间无关,例如,在二进制恢复或回滚后可以更改而没有任何更改:
$ sqlite3 test.sqlite 'create table test ( test )'
$ od --skip-bytes 24 --read-bytes=4 -tx1 test.sqlite | sed -n '1s/[^[:space:]]*[[:space:]]//p' | tr -d ' '
00000001
$ sqlite3 test.sqlite "insert into test values ( 'hello world');"
$ od --skip-bytes 24 --read-bytes=4 -tx1 test.sqlite | sed -n '1s/[^[:space:]]*[[:space:]]//p' | tr -d ' '
00000002
$ sqlite3 test.sqlite "delete from test;"
$ od --skip-bytes 24 --read-bytes=4 -tx1 test.sqlite | sed -n '1s/[^[:space:]]*[[:space:]]//p' | tr -d ' '
00000003
$ sqlite3 test.sqlite "begin exclusive; insert into test values (1); rollback;"
$ od --skip-bytes 24 --read-bytes=4 -tx1 test.sqlite | sed -n '1s/[^[:space:]]*[[:space:]]//p' | tr -d ' '
00000003
要确定两个数据库文件“相等”,您只能在转储文件(.dump
)之后确定,将输出减少到INSERT
语句并对结果进行排序以进行比较(也许通过一些加密安全的校验和)。但这显然有点矫枉过正。
答案 1 :(得分:1)
根据数据库的大小,连续轮询和生成校验和可能对机器来说过于密集。
您是否考虑过监控存储在操作系统文件系统中的最后修改的元数据?
答案 2 :(得分:1)
如果其中一个sqlite数据库仅用作副本(只读),并且您想要检查原始数据库文件是否已更新,以便您可以更新副本(例如,从Web更新,而无需下载如果它与副本没有区别,那么你可以只比较两个数据库文件的前100个字节(数据库头)http://www.sqlite.org/fileformat.html
对于数据库头的字节24..27,SQlite doc说:
24..27 4
文件更改计数器。每次提交数据库事务时,此字段中存储的32位无符号整数的值都会递增
经过一些测试后,似乎在提交数据库事务时文件更改计数器没有递增,但只包含select语句,这是您在事务中包装选择并提交结束事务时所需的行为。