sqlite> DELETE FROM mails WHERE (`id` = 71);
SQL error: database is locked
これが機能するようにデータベースをロック解除するにはどうすればよいですか?
sqlite> DELETE FROM mails WHERE (`id` = 71);
SQL error: database is locked
これが機能するようにデータベースをロック解除するにはどうすればよいですか?
回答:
Windowsでは、このプログラムhttp://www.nirsoft.net/utils/opened_files_view.htmlを試して、プロセスがdbファイルを処理していることを確認できます。データベースのロックを解除するためにそのプログラムを閉じてみてください
LinuxおよびmacOSでは、たとえば、ロックされたファイルがdevelopment.dbの場合、同様のことができます。
$ fuser development.db
このコマンドは、ファイルをロックしているプロセスを表示します。
> development.db:5430
プロセスを強制終了します...
キル-9 5430
...そしてデータベースがロック解除されます。
kill
は問題ありませんが、適切に強制終了するように注意する必要があり、kill -9
おそらく間違っているか、やりすぎです。プロセスがハングしていて、他の方法で死なない場合は、必要になることもありますkill -9
。ただし、データベースがロックされていないことを報告できるように、メインの本番ジョブを強制終了する必要はありません。
書き込み中にアプリをクラッシュさせて、sqlite dbをロックしました。ここに私がそれを修正した方法があります:
echo ".dump" | sqlite old.db | sqlite new.db
取得元:http : //random.kakaopor.hu/how-to-repair-an-sqlite-database
sqlite> .dump PRAGMA foreign_keys=OFF; BEGIN TRANSACTION; /**** ERROR: (5) database is locked *****/ ROLLBACK; -- due to errors
FOREIGN KEY constraint failed (RELEASE RESTOREPOINT)
以下に示すDatabaseIsLockedページは使用できなくなりました。ファイルのロックと同時実行性のページでは、v3で導入されたファイルのロックに関連する変更について説明しており、将来の読者に役立つ可能性があります。https://www.sqlite.org/lockingv3.html
SQLite wikiのDatabaseIsLockedページは、このエラーメッセージの適切な説明を提供します。これは、部分的には、競合の原因は(エラーを出しているプロセスの)内部にあると述べています。
このページで説明していないのは、SQLiteがプロセス内の何かがロックを保持していると判断する方法と、誤検知の原因となる可能性がある条件です。
-journalファイルを削除するのはひどい考えのようです。これは、クラッシュ後にsqliteがデータベースを一貫した状態にロールバックできるようにするためのものです。データベースが不整合な状態のときに削除すると、データベースが破損したままになります。sqliteサイトのページを引用する:
クラッシュまたは停電が発生し、ホットジャーナルがディスクに残っている場合、元のデータベースファイルとホットジャーナルは、データベースファイルが別のSQLiteプロセスによって開かれてロールバックされるまで、元の名前でディスク上に残ることが重要です。 。[...]
SQLiteリカバリーの一般的な障害モードは次のように発生すると思われます:電源障害が発生します。電源が回復した後、善意のあるユーザーまたはシステム管理者は、ディスクの損傷を探し始めます。「important.data」という名前のデータベースファイルが表示されます。このファイルはおそらくおなじみのものです。しかし、クラッシュ後、「important.data-journal」という名前のホットジャーナルもあります。次に、ユーザーはシステムのクリーンアップに役立っていると考えて、ホットジャーナルを削除します。これを防ぐ方法はユーザー教育以外にありません。
ロールバックは、次回データベースを開いたときに自動的に行われるはずですが、プロセスがデータベースをロックできない場合は失敗します。他の人が言ったように、これの考えられる理由の1つは、現在別のプロセスが開いていることです。データベースがNFSボリューム上にある場合、もう1つの可能性は古いNFSロックです。その場合の回避策は、NFSサーバー(mv database.db original.db; cp original.db database.db)でロックされていない新しいコピーでデータベースファイルを置き換えることです。sqlite FAQは、NFSファイルロックのバグのある実装のため、NFSボリューム上のデータベースへの同時アクセスに関する注意を推奨していることに注意してください。
-journalファイルを削除すると、以前はできなかったデータベースをロックできる理由を説明できません。それは再現可能ですか?
ちなみに、-journalファイルの存在は、必ずしもクラッシュが発生したことや、ロールバックされる変更があることを意味するわけではありません。Sqliteにはいくつかの異なるジャーナルモードがあり、PERSISTまたはTRUNCATEモードでは-journalファイルを常に残し、内容を変更して、ロールバックする部分的なトランザクションがあるかどうかを示します。
「データベースがロックされています」エラーを削除する場合は、次の手順に従います。
SQLite dbファイルは単なるファイルであるため、最初のステップは読み取り専用でないことを確認することです。もう1つ行うことは、DBを開いた状態でGUI SQLite DBビューアのようなものがないことを確認することです。別のシェルでDBを開いたり、コードでDBを開いたりすることができます。通常、これは、別のスレッド、またはSQLiteデータベースブラウザーなどのアプリケーションが書き込み用にDBを開いている場合に発生します。
ロックの原因は、システムのクラッシュであり、ハングプロセスではありませんでした。これを解決するには、ファイルの名前を変更してから、元の名前と場所にコピーし直しました。
Linuxシェルを使用すると...
mv mydata.db temp.db
cp temp.db mydata.db
「Pooling=true
」を接続文字列に追加すると、うまくいきました。
INDEXのような一部の関数は非常に長い時間がかかる可能性があり、実行中はデータベース全体をロックします。そのような場合、ジャーナルファイルを使用しないこともあります。
したがって、プロセスがアクティブにデータベースに書き込んでいるためにデータベースがロックされているかどうかを確認するための最良/唯一の方法(したがって、操作が完了するまでデータベースをそのままにしておく必要があります)は、ファイルをmd5(または一部のシステムではmd5sum)にすることです。別のチェックサムを取得した場合、データベースが書き込まれていて、本当にそのプロセスを強制終了したくないのです。そうすると、テーブルやデータベースが破損する可能性があるためです。
繰り返しますが、重要なのです。解決策は、ロックプログラムを見つけて強制終了することではありません。データベースに適切な理由で書き込みロックがあるかどうかを確認し、そこから移動することです。時々正しい解決策はただのコーヒーブレイクです。
このロックされているが書き込まれていない状況を作成する唯一の方法は、プログラムが実行されるかどうかです。これは、プログラムがBEGIN EXCLUSIVE
何らかのテーブルの変更または何かを実行したかったためです。その後、何らかの理由でEND
その後に送信することはなく、プロセスは終了しません。適切に作成されたコードでは、3つの条件がすべて満たされる可能性は非常に低いため、誰かがロックプロセスを強制終了したい場合、100のうち99回は、ロックプロセスが実際にデータベースをロックしています。プログラマは通常BEGIN EXCLUSIVE
、本当に必要な場合を除いて条件を追加しません。これにより、同時実行性が妨げられ、ユーザーの不満が増えるためです。SQLite自体は、本当に必要な場合(インデックス作成時など)にのみ追加します。
最後に、いくつかの回答が述べているように、「ロック」ステータスはファイル内に存在しません-それはオペレーティングシステムのカーネルに存在します。実行されたプロセスBEGIN EXCLUSIVE
は、OSからロックをファイルにかけるように要求しました。排他プロセスがクラッシュした場合でも、OSはファイルロックを維持する必要があるかどうかを判断できます。ロックされているデータベースを使用することはできませんが、アクティブにロックしているプロセスはありません。ファイルをロックしているプロセスを確認する場合は、通常、fuserではなくlsofを使用する方が適切です(これは、https://unix.stackexchange.com/questions/94316/fuser-vs-lsof-の優れた例です。 to-check-files-in-use)。または、DTrace(OSX)を使用している場合は、ファイルでiosnoopを使用できます。
このリンクは問題を解決します。:Sqliteが次の場合:データベースロックエラー これは私の問題を解決しました。
また、開始トランザクションと終了トランザクションを使用して、将来データベースをロックしないようにすることができます。
データベースの内部の問題である必要があります...
私にとっては、「SQLiteマネージャー」でデータベースを参照しようとした後に明らかになりました...
したがって、データベースに接続する別のプロセスが見つからず、修正できない場合は、この根本的な解決策を試してください:
rake db:migrate
」で実行私も同じ問題を抱えていました。どうやら、ロールバック機能は、dbファイルと同じですが最新の変更がないジャーナルでdbファイルを上書きしているようです。以下のコードにこれを実装しましたが、それ以降は問題なく機能していますが、以前は、データベースがロックされたままの状態でコードがループに陥るだけでした。
お役に立てれば
##############
#### Defs ####
##############
def conn_exec( connection , cursor , cmd_str ):
done = False
try_count = 0.0
while not done:
try:
cursor.execute( cmd_str )
done = True
except sqlite.IntegrityError:
# Ignore this error because it means the item already exists in the database
done = True
except Exception, error:
if try_count%60.0 == 0.0: # print error every minute
print "\t" , "Error executing command" , cmd_str
print "Message:" , error
if try_count%120.0 == 0.0: # if waited for 2 miutes, roll back
print "Forcing Unlock"
connection.rollback()
time.sleep(0.05)
try_count += 0.05
def conn_comit( connection ):
done = False
try_count = 0.0
while not done:
try:
connection.commit()
done = True
except sqlite.IntegrityError:
# Ignore this error because it means the item already exists in the database
done = True
except Exception, error:
if try_count%60.0 == 0.0: # print error every minute
print "\t" , "Error executing command" , cmd_str
print "Message:" , error
if try_count%120.0 == 0.0: # if waited for 2 miutes, roll back
print "Forcing Unlock"
connection.rollback()
time.sleep(0.05)
try_count += 0.05
##################
#### Run Code ####
##################
connection = sqlite.connect( db_path )
cursor = connection.cursor()
# Create tables if database does not exist
conn_exec( connection , cursor , '''CREATE TABLE IF NOT EXISTS fix (path TEXT PRIMARY KEY);''')
conn_exec( connection , cursor , '''CREATE TABLE IF NOT EXISTS tx (path TEXT PRIMARY KEY);''')
conn_exec( connection , cursor , '''CREATE TABLE IF NOT EXISTS completed (fix DATE, tx DATE);''')
conn_comit( connection )
マルチスレッドアプリケーションでも「データベースがロックされています」エラーが発生していました。 SQLITE_BUSYの結果コードのようです。sqlite3_busy_timeoutを30000などの適切な長さに設定することで解決しました。
(余談ですが、7年前の質問で誰もこれをまだ見つけていないなんて奇妙です!SQLiteは本当に奇妙で素晴らしいプロジェクトです...)
再起動オプションを実行する前に、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プログラムがあることを示しています。
たくさんの答えを含む古い質問は、私が最近上記の答えを読んで従った手順ですが、私の場合、問題はCIFSリソース共有が原因でした。このケースは以前に報告されていないので、誰かを助けることを願っています。
で接続開始時に強制的にロックモードを試してください
final SQLiteConfig config = new SQLiteConfig();
config.setReadOnly(false);
config.setLockingMode(LockingMode.NORMAL);
connection = DriverManager.getConnection(url, config.toProperties());
あなたは、NFS共有フォルダの上にSQLiteのDBファイルを使用している場合は、チェックこの時点 SQLiteのよくある質問のを、と説明されているように、必ずあなたの回避ロックを作るためにあなたのマウント設定オプションを確認し、ここで:
//myserver /mymount cifs username=*****,password=*****,iocharset=utf8,sec=ntlm,file,nolock,file_mode=0700,dir_mode=0700,uid=0500,gid=0500 0 0
このエラーは、ここで説明するシナリオとは少し異なるシナリオで発生しました。
SQLiteデータベースは、3台のサーバーで共有されるNFSファイルシステムに置かれていました。2台のサーバーでは、データベースに対してクエリを正常に実行できました。3番目のサーバーでは、「データベースがロックされています」というメッセージが表示されると考えていました。
この3台目のマシンの問題は、スペースが残っていないこと/var
です。このファイルシステムにある任意のSQLiteデータベースでクエリを実行しようとするたびに、「データベースがロックされています」というメッセージとログに対するこのエラーが表示されました。
8月8日10:33:38 server01カーネル:lockd:監視できません172.22.84.87
そしてこれも:
Aug 8 10:33:38 server01 rpc.statd [7430]:挿入に失敗しました:/var/lib/nfs/statd/sm/other.server.name.comを書き込んでいます:デバイスにスペースが残っていませんAug 8 10:33: 38 server01 rpc.statd [7430]:172.22.84.87のSM_MONのserver01に対するSTAT_FAIL
宇宙の状況が処理された後、すべてが通常に戻りました。
あなたがロックを解除しようとしている場合はクロームデータベースにするSQLiteのでそれを表示し、そしてちょうどChromeをシャットダウンします。
ウィンドウズ
%userprofile%\Local Settings\Application Data\Google\Chrome\User Data\Default\Web Data
or
%userprofile%\Local Settings\Application Data\Google\Chrome\User Data\Default\Chrome Web Data
マック
~/Library/Application Support/Google/Chrome/Default/Web Data
以前のコメントから、-journalファイルが存在すると述べました。
これは、(排他的?)トランザクションを開いており、まだデータをコミットしていないことを意味します。プログラムやその他のプロセスで-journalを残しましたか?
sqliteプロセスを再起動すると、ジャーナルファイルが確認され、コミットされていないアクションがクリーンアップされ、-journalファイルが削除されます。