sqlite> DELETE FROM mails WHERE (`id` = 71);
SQL error: database is locked
Run Code Online (Sandbox Code Playgroud)
如何解锁数据库以便这样做?
小智 245
在Windows中,您可以尝试使用此程序http://www.nirsoft.net/utils/opened_files_view.html来查找正在处理db文件的进程.尝试关闭该程序以解锁数据库
在Linux和macOS中,您可以执行类似的操作,例如,如果您的锁定文件是development.db:
$ fuser development.db
此命令将显示锁定文件的进程:
> development.db:5430
只是杀了这个过程......
杀了-9 5430
...并且您的数据库将被解锁.
rob*_*ert 89
我在写入过程中使应用程序崩溃导致我的sqlite数据库被锁定.这是我如何修复它:
echo ".dump" | sqlite old.db | sqlite new.db
Run Code Online (Sandbox Code Playgroud)
摘自:http://random.kakaopor.hu/how-to-repair-an-sqlite-database
con*_*r42 52
SQLite wiki DatabaseIsLocked页面提供了对此错误消息的良好解释.它部分地说明争用的来源是内部的(对于发出错误的过程).
这个页面没有解释的是SQLite如何决定你的进程中的某些东西是否存在锁定以及哪些条件可能导致误报.
Aar*_*ron 32
删除-journal文件听起来像一个糟糕的主意.它允许sqlite在崩溃后将数据库回滚到一致状态.如果在数据库处于不一致状态时将其删除,则会留下损坏的数据库.引用sqlite站点的页面:
如果确实发生了崩溃或断电并且磁盘上留有热日志,则原始数据库文件和热日志必须保留在磁盘上并保留其原始名称,直到另一个SQLite进程打开数据库文件并回滚.[...]
我们怀疑SQLite恢复的常见故障模式是这样的:发生电源故障.电源恢复后,善意的用户或系统管理员开始在磁盘上查看损坏情况.他们看到他们的数据库文件名为"important.data".这个文件对他们来说可能很熟悉.但在崩溃之后,还有一个名为"important.data-journal"的热门期刊.然后用户删除热门日志,认为他们正在帮助清理系统.除了用户教育之外,我们知道无法阻止这种情况.
回滚应该在下次打开数据库时自动发生,但如果进程无法锁定数据库,则会失败.正如其他人所说,其中一个可能的原因是另一个流程目前正在开放.如果数据库位于NFS卷上,则另一种可能性是过时的NFS锁定.在这种情况下,解决方法是使用未在NFS服务器上锁定的新副本替换数据库文件(mv database.db original.db; cp original.db database.db).请注意,由于NFS文件锁定的错误实现,sqlite FAQ建议谨慎对NFS卷上的数据库进行并发访问.
我无法解释为什么删除-journal文件会让你锁定以前无法访问的数据库.这是可重复的吗?
顺便说一下,-journal文件的存在并不一定意味着发生了崩溃或者有回滚的变化.Sqlite有一些不同的日志模式,在PERSIST或TRUNCATE模式下,它始终保留-journal文件,并更改内容以指示是否存在要回滚的部分事务.
小智 19
如果要删除"数据库已锁定"错误,请按照下列步骤操作:
小智 15
如果进程锁定SQLite DB并崩溃,则数据库将永久锁定.那就是问题所在.并不是某些其他进程有锁定.
Hea*_*ser 11
SQLite db文件只是文件,因此第一步是确保它不是只读的.另一件事是确保在数据库打开的情况下没有某种GUI SQLite DB查看器.您可以在另一个shell中打开数据库,或者您的代码可能打开了数据库.通常,如果不同的线程或SQLite数据库浏览器等应用程序打开DB进行编写,您会看到这一点.
J.J*_*J.J 10
有些函数(例如 INDEX'ing)可能需要很长时间 - 并且它在运行时会锁定整个数据库。在这种情况下,它甚至可能不使用日志文件!
因此,检查数据库是否因进程正在主动写入而被锁定的最佳/唯一方法(因此您应该让它独自一人,直到其完成其操作)是对文件进行 md5(或某些系统上的 md5sum)两次。如果你得到一个不同的校验和,数据库正在被写入,你真的真的不想杀死 -9 该进程,因为如果你这样做,你很容易最终得到一个损坏的表/数据库。
我会重申,因为这很重要 - 解决方案不是找到锁定程序并杀死它 - 而是查找数据库是否有充分的理由具有写锁,然后从那里开始。有时,正确的解决方案就是喝杯咖啡休息一下。
创建这种锁定但未写入情况的唯一方法是,如果您的程序运行BEGIN EXCLUSIVE,因为它想要进行一些表更改或其他操作,那么无论出于何种原因,之后都不会发送END,并且进程永远不会终止。在任何正确编写的代码中,满足所有这三个条件的可能性极小,因此,当有人想要杀死 -9 他们的锁定进程时,百分之九十九的情况下,锁定进程实际上是出于充分的理由锁定您的数据库。BEGIN EXCLUSIVE除非确实需要,否则程序员通常不会添加条件,因为它会阻止并发并增加用户投诉。SQLite 本身仅在真正需要时添加它(例如索引时)。
最后,正如几个答案所述,“锁定”状态并不存在于文件内部 - 它驻留在操作系统的内核中。运行的进程BEGIN EXCLUSIVE已请求操作系统对文件加锁。即使您的独占进程崩溃了,您的操作系统也将能够确定是否应该保持文件锁定!不可能出现数据库被锁定但没有进程主动锁定它的情况!当要查看哪个进程正在锁定文件时,通常最好使用 lsof 而不是 fusionr (这是一个很好的演示,说明了原因:https ://unix.stackexchange.com/questions/94316/fuser-vs-lsof-检查正在使用的文件)。或者,如果您有 DTrace (OSX),则可以在该文件上使用 iosnoop。
我刚才遇到了这个问题,使用存储在NFS挂载上的远程服务器上的SQLite数据库.在我使用的远程shell会话在数据库打开时崩溃后,SQLite无法获得锁定.
上面提到的恢复配方对我来说不起作用(包括首先移动然后再复制数据库的想法).但是在将其复制到非NFS系统之后,数据库变得可用,并且数据似乎没有丢失.
我的锁定是由系统崩溃而不是由挂起进程引起的。为了解决这个问题,我只是简单地重命名了文件,然后将其复制回其原始名称和位置。
使用Linux外壳将是...
mv mydata.db temp.db
cp temp.db mydata.db
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
366621 次 |
| 最近记录: |