SQLiteデータベースのロックを解除するにはどうすればよいですか?


269
sqlite> DELETE FROM mails WHERE (`id` = 71);
SQL error: database is locked

これが機能するようにデータベースをロック解除するにはどうすればよいですか?


データベースファイルにアクセスする別のプロセスがある可能性があります-lsofを確認しましたか?
ユネキシスト

私も同じ問題を抱えていました。非アクティブ化したときにウイルス対策に問題がありましたが、アプリは正常に機能しますが、アクティブ化すると、「データベースがロックされています」というエラーが表示されます。
user8510915 2017

回答:


267

Windowsでは、このプログラムhttp://www.nirsoft.net/utils/opened_files_view.htmlを試して、プロセスがdbファイルを処理していることを確認できます。データベースのロックを解除するためにそのプログラムを閉じてみてください

LinuxおよびmacOSでは、たとえば、ロックされたファイルがdevelopment.dbの場合、同様のことができます。

$ fuser development.db

このコマンドは、ファイルをロックしているプロセスを表示します。

> development.db:5430

プロセスを強制終了します...

キル-9 5430

...そしてデータベースがロック解除されます。


19
...何をしているのかを知る必要があるという明らかな警告があります。それが重要でないプロセスである場合killは問題ありませんが、適切に強制終了するように注意する必要があり、kill -9おそらく間違っているか、やりすぎです。プロセスがハングしていて、他の方法で死なない場合は、必要になることもありますkill -9。ただし、データベースがロックされていないことを報告できるように、メインの本番ジョブを強制終了する必要はありません。
tripleee 2011年

より簡単な解決策は、コンピュータを再起動することです。
chacham15 2012年

7
@ chacham15:データベースが「マイ」コンピューター上にあると想定し、データベースがロックされているコンピューターと同じコンピューターで多数の重要なプロセスが実行される可能性を無視します。「より単純な」ソリューションは決して単純ではありません;)
tzot 2013年

1
@KyleCarlson-sqliteとmysqlはその点で根本的に異なります。SQLite-db-browserには特に問題はありません。
ベリーTsakala 2013

6
このソリューションは、ファイルをロックするプロセスがあることを前提としています。SQLiteファイルを使用できない状態のままにして、プロセスがクラッシュした可能性があります。その場合は、私の答えをご覧ください。
ロバート

90

書き込み中にアプリをクラッシュさせて、sqlite dbをロックしました。ここに私がそれを修正した方法があります:

echo ".dump" | sqlite old.db | sqlite new.db

取得元:http : //random.kakaopor.hu/how-to-repair-an-sqlite-database


4
sqlite3:sqlite> .dump PRAGMA foreign_keys=OFF; BEGIN TRANSACTION; /**** ERROR: (5) database is locked *****/ ROLLBACK; -- due to errors
14年

機能していないFOREIGN KEY constraint failed (RELEASE RESTOREPOINT)
gies0r

52

以下に示すDatabaseIsLockedページは使用できなくなりました。ファイルのロックと同時実行性のページでは、v3で導入されたファイルのロックに関連する変更について説明しており、将来の読者に役立つ可能性があります。https://www.sqlite.org/lockingv3.html

SQLite wikiのDatabaseIsLockedページは、このエラーメッセージの適切な説明を提供します。これは、部分的には、競合の原因は(エラーを出しているプロセスの)内部にあると述べています。

このページで説明していないのは、SQLiteがプロセス内の何かがロックを保持していると判断する方法と、誤検知の原因となる可能性がある条件です。


2
問題は、ページが正しくないか、古くなっていることです。私は、ロックされたメッセージを取得する単一のINSERT以外に何もしないプロセスを持っています。このプロセスがロックを引き起こした可能性はありません。問題は、同じDBと通信する別のプロセスにありました。
Dan Jameson

4
@ converter42リンクが壊れています。
Ole

32

-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ファイルを常に残し、内容を変更して、ロールバックする部分的なトランザクションがあるかどうかを示します。


23

「データベースがロックされています」エラーを削除する場合は、次の手順に従います。

  1. データベースファイルを他の場所にコピーします。
  2. データベースをコピーしたデータベースに置き換えます。これにより、データベースファイルにアクセスしていたすべてのプロセスが逆参照されます。

2
上記のように「fuser <DB>」を試しましたが、うまくいきませんでした。この簡単な手順でうまくいきます。
Jackie Yeh

私の場合、Jupyter Notebookも再起動する必要がありました。
ビクター

15

プロセスがSQLite DBをロックしてクラッシュした場合、DBは永続的にロックされたままになります。それが問題です。他のプロセスがロックしているわけではありません。


48
では、dbのロックを解除する方法は?
エリックカプルン

4
これは真実ではありません。ロックはOSによって維持されます。以下の答えを読んでください。
JJ

13

SQLite dbファイルは単なるファイルであるため、最初のステップは読み取り専用でないことを確認することです。もう1つ行うことは、DBを開いた状態でGUI SQLite DBビューアのようなものがないことを確認することです。別のシェルでDBを開いたり、コードでDBを開いたりすることができます。通常、これは、別のスレッド、またはSQLiteデータベースブラウザーなどのアプリケーションが書き込み用にDBを開いている場合に発生します。


4
私の経験では、SQLiteデータベースブラウザー(SDB)は、データベースを使用してデータを編集してもSDBに保存しないと、データベースを再現可能にロックします。保存するとロックが解除されます。
ケロニア語2012

挿入はできますが、削除はできません。
ウェニー

10

NFSマウントに保存されたリモートサーバー上のSQLiteデータベースを使用して、この問題が発生しました。SQLiteは、データベースが開いているときに、使用したリモートシェルセッションがクラッシュした後、ロックを取得できませんでした。

上記で提案された回復のレシピは私にはうまくいきませんでした(最初にデータベースを移動してからコピーするという考えを含みます)。しかし、それを非NFSシステムにコピーした後、データベースは使用可能になり、データが失われたようには見えません。


9

ロックの原因は、システムのクラッシュであり、ハングプロセスではありませんでした。これを解決するには、ファイルの名前を変更してから、元の名前と場所にコピーし直しました。

Linuxシェルを使用すると...

mv mydata.db temp.db
cp temp.db mydata.db

非常に簡単な解決策、ネットワークドライブ上のロックされたデータベースの私の問題を解決します。
Maverick2805

7

Pooling=true」を接続文字列に追加すると、うまくいきました。


4

SQLiteでのロックのさまざまな状態のドキュメントが非常に役立つことがわかりました。Michael、読み取りは実行できるがデータベースへの書き込みは実行できない場合、これは、プロセスがデータベースに対してRESERVEDロックを取得したが、まだ書き込みを実行していないことを意味します。SQLite3を使用している場合、PENDINGと呼ばれる新しいロックがあり、これ以上接続するプロセスは許可されませんが、既存の接続は読み取りを実行できます。これが問題である場合は、代わりに確認する必要があります。


4

このエラーは、ファイルが共有フォルダーなどのリモートフォルダーにある場合にスローされます。データベースをローカルディレクトリに変更したところ、問題なく動作しました。


3

アプリ内で2つの接続からSQLiteにアクセスするような問題があります。1つは読み取り専用で、もう1つは書き込みと読み取り用です。その読み取り専用接続が2番目の接続からの書き込みをブロックしたようです。最後に、使用後すぐに準備済みステートメントをファイナライズするか、少なくともリセットする必要があることがわかりました。準備されたステートメントが開かれるまで、データベースへの書き込みはブロックされていました。

電話を忘れないでください:

sqlite_reset(xxx);

または

sqlite_finalize(xxx);

3

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を使用できます。


2

似たようなことが起こりました。Webアプリケーションはデータベースから読み取ることができましたが、挿入や更新を実行できませんでした。Apacheを再起動すると、少なくとも一時的に問題が解決しました。

ただし、根本的な原因を突き止めることができるとよいでしょう。


2

Linux環境でlsofコマンドを使用すると、ファイルを開いたままプロセスがハングしていることがわかりました。
プロセスを強制終了し、問題は解決しました。



2

データベースの内部の問題である必要があります...
私にとっては、「SQLiteマネージャー」でデータベースを参照しようとした後に明らかになりました...
したがって、データベースに接続する別のプロセスが見つからず、修正できない場合は、この根本的な解決策を試してください:

  1. テーブルをエクスポートするために提供します(Firefoxでは「SQLiteマネージャー」を使用できます)
  2. 移行によってデータベーススキームが変更された場合は、最後に失敗した移行を削除します
  3. 「database.sqlite」ファイルの名前を変更します
  4. 「rake db:migrate」を実行して、新しい作業データベースを作成します
  5. テーブルのインポートのためにデータベースに適切な権限を与えるために提供します
  6. バックアップしたテーブルをインポートする
  7. 新しいマイグレーションを書く
  8. rake db:migrate」で実行

1

端末セッションからPythonスクリプトを実行しているMac OS X 10.5.7で同じ問題が発生しました。スクリプトを停止し、ターミナルウィンドウがコマンドプロンプトに座っていたとしても、次に実行したときにこのエラーが発生します。解決策は、ターミナルウィンドウを閉じてから再度開くことでした。私には意味がありませんが、うまくいきました。


1

同じエラーが発生しました。5ミネットのグーグルイングの後、私は1つのシェル魔女がdbを使用しているのを閉じなかったことがわかりました。それを閉じて、もう一度やり直してください;)


1

私も同じ問題を抱えていました。どうやら、ロールバック機能は、dbファイルと同じですが最新の変更がないジャーナルでdbファイルを上書きしているようです。以下のコードにこれを実装しましたが、それ以降は問題なく機能していますが、以前は、データベースがロックされたままの状態でコードがループに陥るだけでした。

お役に立てれば

私のpythonコード

##############
#### 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 )

1

この例外が発生する一般的な理由の1つは、読み取り操作用のリソースを保持したまま書き込み操作を行おうとしている場合です。たとえば、テーブルからSELECTを実行してから、最初にResultSetを閉じずに、選択したものを更新しようとした場合。


1

マルチスレッドアプリケーションでも「データベースがロックされています」エラーが発生していました。 SQLITE_BUSYの結果コードのようです。sqlite3_busy_timeoutを30000などの適切な長さに設定することで解決しました。

(余談ですが、7年前の質問で誰もこれをまだ見つけていないなんて奇妙です!SQLiteは本当に奇妙で素晴らしいプロジェクトです...)


1

再起動オプションを実行する前に、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プログラムがあることを示しています。


1

たくさんの答えを含む古い質問は、私が最近上記の答えを読んで従った手順ですが、私の場合、問題はCIFSリソース共有が原因でした。このケースは以前に報告されていないので、誰かを助けることを願っています。

  • Javaコードで開いたままの接続がないことを確認します。
  • 他のプロセスがlsofでSQLite dbファイルを使用していないことを確認します。
  • 実行中のjvmプロセスのユーザー所有者がファイルに対する読み取り/書き込み権限を持っていることを確認してください。
  • で接続開始時に強制的にロックモードを試してください

    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

1

このエラーは、ここで説明するシナリオとは少し異なるシナリオで発生しました。

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

宇宙の状況が処理された後、すべてが通常に戻りました。


1

あなたがロックを解除しようとしている場合はクロームデータベースにする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

0

以前のコメントから、-journalファイルが存在すると述べました。

これは、(排他的?)トランザクションを開いており、まだデータをコミットしていないことを意味します。プログラムやその他のプロセスで-journalを残しましたか?

sqliteプロセスを再起動すると、ジャーナルファイルが確認され、コミットされていないアクションがクリーンアップされ、-journalファイルが削除されます。


0

Seun Osewaが言ったように、たとえそれが可能だと思わなくても、ゾンビプロセスがロックを取得した状態でターミナルに座っていることがあります。スクリプトが実行されてクラッシュし、プロンプトに戻りますが、ライブラリの呼び出しによってどこかにゾンビプロセスが生成され、そのプロセスにロックが設定されています。

(OSXで)使用​​していた端末を閉じると動作する場合があります。再起動は機能します。たとえば、何も実行していない「python」プロセスを探して、強制終了することができます。


0

あなたはこれを試すことができます:.timeout 100タイムアウトを設定するために。コマンドラインで何が起こるかわかりませんが、C#.Netでこれを実行する"UPDATE table-name SET column-name = value;"と、データベースがロックされますが、これ"UPDATE table-name SET column-name = value"で問題ありません。

;を追加すると、sqliteはさらにコマンドを探します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.