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 인 경우 비슷한 작업을 수행 할 수 있습니다.
$ 퓨저 개발 .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 페이지는 더 이상 사용할 수 없습니다. File Locking And Concurrency (파일 잠금 및 동시성) 페이지에는 v3에 도입 된 파일 잠금과 관련된 변경 사항이 설명되어 있으며 향후 독자에게 유용 할 수 있습니다. https://www.sqlite.org/lockingv3.html
SQLite 위키 데이터베이스 페이지는이 오류 메시지에 대한 좋은 설명을 제공합니다. 부분적으로는 분쟁의 원인이 내부 (오류를 발생시키는 프로세스)라고 명시하고있다.
이 페이지에서 설명하지 않는 것은 SQLite가 프로세스의 어떤 항목이 잠금을 유지하고 어떤 조건이 오 탐지를 일으킬 수 있는지 결정하는 방법입니다.
-journal 파일을 삭제하는 것은 끔찍한 생각처럼 들립니다. 충돌 후 sqlite가 데이터베이스를 일관된 상태로 롤백 할 수 있습니다. 데이터베이스가 일관성이없는 상태에서 삭제하면 데이터베이스가 손상됩니다. sqlite 사이트 에서 페이지 인용하기 :
충돌 또는 전원 손실이 발생하고 핫 저널이 디스크에 남아있는 경우 데이터베이스 파일이 다른 SQLite 프로세스에 의해 열리고 롤백 될 때까지 원래 데이터베이스 파일 및 핫 저널이 원래 이름으로 디스크에 남아 있어야합니다. . [...]
SQLite 복구에 대한 일반적인 실패 모드는 다음과 같이 발생합니다. 정전이 발생합니다. 전원이 복구되면 의미있는 사용자 나 시스템 관리자가 디스크에서 손상을 찾아보기 시작합니다. 데이터베이스 파일 "important.data"가 표시됩니다. 이 파일은 아마도 익숙 할 것입니다. 그러나 충돌 후 "important.data-journal"이라는 인기 저널도 있습니다. 그런 다음 사용자는 시스템 정리에 도움이된다고 생각하면서 핫 저널을 삭제합니다. 우리는 사용자 교육 외에는 이것을 막을 방법이 없습니다.
롤백은 다음에 데이터베이스를 열 때 자동으로 발생하지만 프로세스가 데이터베이스를 잠글 수 없으면 실패합니다. 다른 사람들이 말했듯이, 가능한 한 가지 이유는 다른 프로세스가 현재 열려 있기 때문입니다. 데이터베이스가 NFS 볼륨에있는 경우 오래된 NFS 잠금도 가능합니다. 이 경우, 해결 방법은 데이터베이스 파일을 NFS 서버에서 잠기지 않은 새 사본 (mv database.db original.db; cp original.db database.db)으로 바꾸는 것입니다. sqlite FAQ는 버그가 많은 NFS 파일 잠금 구현으로 인해 NFS 볼륨의 데이터베이스에 대한 동시 액세스와 관련하여주의 할 것을 권장합니다.
-journal 파일을 삭제하면 이전에는 불가능했던 데이터베이스를 잠글 수있는 이유를 설명 할 수 없습니다. 재현 할 수 있습니까?
그런데 -journal 파일이 있다고해서 반드시 충돌이 발생했거나 롤백 할 변경 사항이있는 것은 아닙니다. Sqlite에는 몇 가지 저널 모드가 있으며 PERSIST 또는 TRUNCATE 모드에서는 항상 저널 파일을 그대로두고 롤백 할 부분 트랜잭션이 있는지 여부를 표시하도록 내용을 변경합니다.
"데이터베이스가 잠겨 있습니다"오류를 제거하려면 다음 단계를 수행하십시오.
프로세스에 SQLite DB에 대한 잠금이 있고 충돌이 발생하면 DB는 영구적으로 잠금 상태를 유지합니다. 그게 문제입니다. 다른 프로세스에 잠금이있는 것은 아닙니다.
SQLite DB 파일은 파일 일 뿐이므로 첫 번째 단계는 읽기 전용이 아닌지 확인하는 것입니다. 다른 방법은 DB를 연 상태에서 GUI SQLite DB 뷰어가 없는지 확인하는 것입니다. 다른 쉘에서 DB를 열거 나 코드에서 DB를 열 수 있습니다. 일반적으로 다른 스레드 또는 SQLite Database Browser와 같은 응용 프로그램에 DB가 쓰기 위해 열려있는 경우이 문제가 나타납니다.
잠금은 프로세스 중단이 아니라 시스템 충돌로 인해 발생했습니다. 이 문제를 해결하기 위해 파일 이름을 바꾸고 원래 이름과 위치로 다시 복사했습니다.
리눅스 쉘을 사용하면 ...
mv mydata.db temp.db
cp temp.db mydata.db
나는 "Pooling=true
연결 문자열 "을 (를) 했으며 작동했습니다.
앱 내에서 이러한 문제가 발생하여 2 개의 연결에서 SQLite에 액세스 할 수 있습니다. 하나는 읽기 전용이고 두 번째는 쓰기 및 읽기입니다. 읽기 전용 연결이 두 번째 연결에서 쓰기를 차단 한 것 같습니다. 마지막으로, 사용 후 즉시 준비된 명령문을 마무리하거나 최소한 재설정해야한다는 것이 밝혀졌습니다. 준비된 명령문이 열릴 때까지 데이터베이스에 대한 쓰기가 차단되었습니다.
전화를 잊지 마십시오 :
sqlite_reset(xxx);
또는
sqlite_finalize(xxx);
INDEX와 같은 일부 기능은 시간이 오래 걸릴 수 있으며 실행되는 동안 전체 데이터베이스를 잠급니다. 그런 경우에는 저널 파일을 사용하지 않을 수도 있습니다!
따라서 프로세스가 실제로 데이터베이스에 쓰기 때문에 데이터베이스가 잠겨 있는지 확인하는 가장 좋은 방법은 파일을 두 번 md5 (또는 일부 시스템에서는 md5sum)하는 것입니다. . 다른 체크섬을 얻으면 데이터베이스가 작성되고 있으며 실제로 손상된 테이블 / 데이터베이스로 쉽게 종료 할 수 있기 때문에 실제로 해당 프로세스를 종료하지 않으려 고합니다.
중요한 점은 솔루션이 잠금 프로그램을 찾아서 죽이지 않는 것이 중요하기 때문에 반복 할 것입니다. 데이터베이스에 적절한 이유로 쓰기 잠금이 있는지 확인하고 거기에서 이동하는 것입니다. 때로는 올바른 해결책은 커피 브레이크 일뿐입니다.
이 잠겨 있지만 기록되지 않는 상황을 만드는 유일한 방법은 프로그램이 실행되는 경우입니다. BEGIN EXCLUSIVE
테이블을 변경하거나 무언가를 원했기 때문에 어떤 이유로 든 END
이후에 절대로 보내지 않으며 프로세스는 결코 끝나지 않습니다 . 세 가지 조건이 모두 올바르게 작성된 코드에서는 거의 발생하지 않으며, 누군가가 잠금 프로세스를 종료하려고 할 때 잠금 프로세스는 실제로 좋은 이유로 데이터베이스를 잠그고 있습니다. 프로그래머는 일반적으로BEGIN EXCLUSIVE
동시성을 방지하고 사용자 불만을 증가시키기 때문에 실제로 필요한 경우가 아니면 조건을 . SQLite 자체는 인덱싱과 같이 실제로 필요할 때만 추가합니다.
마지막으로, 몇 가지 답변에서 언급했듯이 파일 내부에 '잠금'상태가 존재하지 않습니다. 운영 체제의 커널에 있습니다. 실행 된 프로세스가 BEGIN EXCLUSIVE
OS에서 파일에 잠금을 설정하도록 요청했습니다. 독점 프로세스가 중단 되더라도 OS는 파일 잠금을 유지해야하는지 여부를 파악할 수 있습니다 !! 잠긴 데이터베이스로 끝나는 것은 불가능하지만 프로세스가 적극적으로 잠그고 있지는 않습니다 !! 어떤 프로세스가 파일을 잠그는 지 확인하는 경우 일반적으로 퓨저 대신 lsof를 사용하는 것이 좋습니다 (이는 /unix/94316/fuser-vs-lsof- 사용중인 파일 확인 ). 또는 DTrace (OSX)가있는 경우 파일에서 iosnoop을 사용할 수 있습니다.
이 링크는 문제를 해결합니다. : Sqlite가 제공하는 경우 : 데이터베이스 잠금 오류 내 문제를 해결하면 도움이 될 수 있습니다.
그리고 시작 트랜잭션과 종료 트랜잭션을 사용하여 나중에 데이터베이스를 잠그지 않도록 할 수 있습니다.
데이터베이스의 내부 문제 여야합니다 ...
저에게 "SQLite manager"를 사용하여 데이터베이스를 찾아 보려고 시도한 후에 나타났습니다.
따라서 다른 프로세스를 찾을 수없고 데이터베이스에 연결할 수없고이를 수정할 수없는 경우, 이 급진적 인 해결책을 시도하십시오.
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 faq 의이 지점 을 확인 하고 마운트 구성 옵션을 검토하여 여기에 설명 된대로 잠금을 피 하십시오 .
//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 파일 시스템에있었습니다. 두 대의 서버에서 데이터베이스에 대한 쿼리를 성공적으로 실행할 수있었습니다. 세 번째 서버에서 "데이터베이스가 잠겨 있습니다"라는 메시지가 나타납니다.
이 3 번째 머신은 공간이 남아 있지 않다는 것이 었습니다 /var
. 이 파일 시스템에있는 모든 SQLite 데이터베이스에서 쿼리를 실행하려고 할 때마다 "데이터베이스가 잠겨 있습니다"라는 메시지와 로그를 통해이 오류가 발생했습니다.
8 월 8 일 10:33:38 server01 커널 : 잠김 : 172.22.84.87을 모니터링 할 수 없음
그리고 이것도 :
8 월 8 일 10:33:38 server01 rpc.statd [7430] : 삽입 실패 : /var/lib/nfs/statd/sm/other.server.name.com 작성 : 장치에 남은 공간이 없습니다. 8 월 8 일 10:33 : 38 server01 rpc.statd [7430] : SM_MON이 172.22.84.87 인 경우 STAT_FAIL을 server01로
우주 상황이 처리 된 후 모든 것이 정상으로 돌아 왔습니다.
Chrome 데이터베이스 를 잠금 해제하여 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 파일을 제거합니다.