当我输入这个查询: 删除邮件中id = 71的所有邮件
SQLite返回以下错误:
SQL error: database is locked
我如何解锁数据库,以便这个查询将工作?
当我输入这个查询: 删除邮件中id = 71的所有邮件
SQLite返回以下错误:
SQL error: database is locked
我如何解锁数据库,以便这个查询将工作?
当前回答
我在多线程应用程序中也有“数据库被锁定”错误,这似乎是SQLITE_BUSY结果代码,我通过将sqlite3_busy_timeout设置为适当的长度(如30000)来解决这个问题。
(顺便说一句,对于一个7年前的问题,居然没有人发现这一点,这真奇怪!SQLite真的是一个奇特而神奇的项目…)
其他回答
在windows中,您可以尝试这个程序http://www.nirsoft.net/utils/opened_files_view.html,以找出进程正在处理db文件。尝试关闭该程序解锁数据库
在Linux和macOS中,你可以做类似的事情,例如,如果你锁定的文件是development.db:
$ fuser development.db
这个命令将显示哪个进程正在锁定该文件:
> development.db: 5430
只需终止进程……
杀死-9 5430
...您的数据库将被解锁。
有些函数,比如INDEX'ing,可能会花费很长时间——而且在运行时它会锁定整个数据库。在这种情况下,它甚至可能不使用日志文件!
因此,最好/唯一的方法来检查您的数据库是否被锁定,因为一个进程正在积极地写入它(因此你应该让它独自呆着,直到它完成它的操作)是md5(或md5sum在某些系统)文件两次。 如果你得到一个不同的校验和,数据库正在被写入,你真的真的真的不想杀死这个进程,因为如果你这样做,你很容易得到一个损坏的表/数据库。
我要重申一下,因为这很重要——解决方案不是找到锁程序并杀死它——而是找出数据库是否有一个很好的写锁,然后从那里开始。有时候正确的解决方法就是喝杯咖啡休息一下。
The only way to create this locked-but-not-being-written-to situation is if your program runs BEGIN EXCLUSIVE, because it wanted to do some table alterations or something, then for whatever reason never sends an END afterwards, and the process never terminates. All three conditions being met is highly unlikely in any properly-written code, and as such 99 times out of 100 when someone wants to kill -9 their locking process, the locking process is actually locking your database for a good reason. Programmers don't typically add the BEGIN EXCLUSIVE condition unless they really need to, because it prevents concurrency and increases user complaints. SQLite itself only adds it when it really needs to (like when indexing).
Finally, the 'locked' status does not exist INSIDE the file as several answers have stated - it resides in the Operating System's kernel. The process which ran BEGIN EXCLUSIVE has requested from the OS a lock be placed on the file. Even if your exclusive process has crashed, your OS will be able to figure out if it should maintain the file lock or not!! It is not possible to end up with a database which is locked but no process is actively locking it!! When it comes to seeing which process is locking the file, it's typically better to use lsof rather than fuser (this is a good demonstration of why: https://unix.stackexchange.com/questions/94316/fuser-vs-lsof-to-check-files-in-use). Alternatively if you have DTrace (OSX) you can use iosnoop on the file.
在选择重新启动选项之前,有必要看看能否找到sqlite数据库的用户。
在Linux上,可以使用fuser:
$ fuser database.db
$ fuser database.db-journal
在我的案例中,我得到了如下的回应:
philip 3556 4700 0 10:24 pts/3 00:00:01 /usr/bin/python manage.py shell
这表明我有另一个使用数据库的pid 3556 (manage.py)的Python程序。
SQLite db文件只是文件,所以第一步是确保它不是只读的。另一件要做的事情是确保在DB打开时没有某种GUI SQLite DB查看器。可以在另一个shell中打开DB,也可以在代码中打开DB。通常情况下,如果不同的线程或应用程序(如SQLite Database Browser)打开了数据库以便写入,则会看到这种情况。
我在一个场景中得到了这个错误,与这里描述的略有不同。
SQLite数据库位于由3个服务器共享的NFS文件系统上。在其中2个服务器上,我能够成功地对数据库运行查询,在第三个服务器上,我认为我得到了“数据库已锁定”消息。
第三台机器的问题是,在/var上没有剩余空间了。每次我试图在位于这个文件系统的任何SQLite数据库中运行查询时,我都得到了“数据库被锁定”的消息,并且在日志上出现了这个错误:
Aug 8 10:33:38 server01 kernel: lockd: cannot monitor 172.22.84.87
还有这个:
Aug 8 10:33:38 server01 rpc。statd[7430]: Failed to insert: writing /var/lib/nfs/statd/sm/other.server.name.com: No space left on device .日志含义 Aug 8 10:33:38 server01 rpc。statd[7430]: STAT_FAIL to server01 for SM_MON of 172.22.84.87
太空的情况处理好之后,一切都恢复正常了。