SQLite 데이터베이스를 잠금 해제하려면 어떻게합니까?


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

데이터베이스 잠금을 해제하려면 어떻게해야합니까?


데이터베이스 파일에 액세스하는 다른 프로세스가있을 수 있습니다. lsof를 확인하셨습니까?
— 존재하지 않는

나는 같은 문제가 있었다. 문제는 안티 ​​바이러스에 있었는데, 앱을 비활성화하면 잘 작동하지만 앱을 활성화하면 "데이터베이스가 잠겨 있습니다"라는 오류가 발생하면 도움이되기를 바랍니다.
— user8510915

답변:


267

Windows 에서이 프로그램 http://www.nirsoft.net/utils/opened_files_view.html 을 사용하여 프로세스가 db 파일을 처리하고 있는지 확인할 수 있습니다. 데이터베이스 잠금 해제를 위해 해당 프로그램을 닫으십시오.

Linux 및 macOS에서는 예를 들어 잠긴 파일이 development.db 인 경우 비슷한 작업을 수행 할 수 있습니다.

$ 퓨저 개발 .db

이 명령은 파일을 잠그는 프로세스를 보여줍니다.

> development.db : 5430

그냥 프로세스를 죽여라 ...

죽이기 -9 5430

... 그리고 데이터베이스가 잠금 해제됩니다.


19
... 당신이하고있는 일을 알아야한다는 명백한 경고가 있습니다. 중요하지 않은 프로세스라면 kill괜찮을 것이지만 제대로 죽이려면 조심해야하며 kill -9잘못되었거나 과도 할 수 있습니다. 프로세스가 중단되고 다른 방법으로 죽지 않으면 때때로 필요합니다 kill -9. 그러나 주요 프로덕션 작업을 중단하고 죽이기를 원하지 않으므로 데이터베이스가 더 이상 잠겨 있지 않다고보고 할 수 있습니다!
— tripleee

가장 간단한 해결책은 컴퓨터를 다시 시작하는 것입니다.
— chacham15

7
@ chacham15 : 데이터베이스가 "내"컴퓨터에 있다고 가정하고 데이터베이스가 잠겨있는 것과 동일한 컴퓨터에서 많은 중요한 프로세스가 실행될 가능성을 무시합니다. "간단한"솔루션은 결코 간단하지 않습니다.)
— tzot

1
@KyleCarlson-sqlite와 mysql은 그 측면에서 근본적으로 다릅니다. SQLite-db-browser에는 특별한 문제가 없습니다.
— Berry Tsakala

6
이 솔루션은 파일을 잠그는 프로세스가 있다고 가정합니다. SQLite 파일을 사용할 수없는 상태로두고 프로세스가 중단되었을 수 있습니다. 이 경우 내 대답을 참조하십시오.
— robert mar


52

아래에 나열된 DatabaseIsLocked 페이지는 더 이상 사용할 수 없습니다. File Locking And Concurrency (파일 잠금 및 동시성) 페이지에는 v3에 도입 된 파일 잠금과 관련된 변경 사항이 설명되어 있으며 향후 독자에게 유용 할 수 있습니다. https://www.sqlite.org/lockingv3.html

SQLite 위키 데이터베이스 페이지는이 오류 메시지에 대한 좋은 설명을 제공합니다. 부분적으로는 분쟁의 원인이 내부 (오류를 발생시키는 프로세스)라고 명시하고있다.

이 페이지에서 설명하지 않는 것은 SQLite가 프로세스의 어떤 항목이 잠금을 유지하고 어떤 조건이 오 탐지를 일으킬 수 있는지 결정하는 방법입니다.


2
문제는 페이지가 잘못되었거나 오래된 것입니다. 잠긴 메시지를 받고있는 단일 INSERT 만 문자 그대로 처리하는 프로세스가 있습니다.이 프로세스로 인해 잠금이 발생하지 않았습니다. 문제는 다른 프로세스에서 동일한 DB와 통신하는 중이었습니다.
— Dan Jameson

4
@ converter42 링크가 끊어졌습니다.
— Ole Tange

32

-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 모드에서는 항상 저널 파일을 그대로두고 롤백 할 부분 트랜잭션이 있는지 여부를 표시하도록 내용을 변경합니다.


23

"데이터베이스가 잠겨 있습니다"오류를 제거하려면 다음 단계를 수행하십시오.

  1. 데이터베이스 파일을 다른 위치로 복사하십시오.
  2. 데이터베이스를 복사 된 데이터베이스로 바꾸십시오. 데이터베이스 파일에 액세스하는 모든 프로세스를 역 참조합니다.

2
위에서 설명한 것처럼 'fuser <DB>'를 시도했지만 작동하지 않았습니다. 이 간단한 단계는 저에게 효과적입니다.
— Jackie Yeh

내 경우에는 Jupyter Notebook을 다시 시작해야했습니다.
— Victor

15

프로세스에 SQLite DB에 대한 잠금이 있고 충돌이 발생하면 DB는 영구적으로 잠금 상태를 유지합니다. 그게 문제입니다. 다른 프로세스에 잠금이있는 것은 아닙니다.


48
DB를 잠금 해제하는 방법?
— Erik Kaplun

4
이것은 사실이 아닙니다. 잠금은 OS에서 유지 관리합니다. 아래 답변을 읽으십시오.
— JJ

13

SQLite DB 파일은 파일 일 뿐이므로 첫 번째 단계는 읽기 전용이 아닌지 확인하는 것입니다. 다른 방법은 DB를 연 상태에서 GUI SQLite DB 뷰어가 없는지 확인하는 것입니다. 다른 쉘에서 DB를 열거 나 코드에서 DB를 열 수 있습니다. 일반적으로 다른 스레드 또는 SQLite Database Browser와 같은 응용 프로그램에 DB가 쓰기 위해 열려있는 경우이 문제가 나타납니다.


4
내 경험상 SQLite Database Browser (SDB)는 데이터베이스를 사용하여 데이터를 편집 한 다음 SDB에 저장하지 않으면 데이터베이스를 재현 가능하게 잠급니다. 저장하면 잠금이 해제됩니다.
— Chelonian

삽입 할 수는 있지만 삭제할 수는 없습니다.
— Wennie

10

NFS 마운트에 저장된 원격 서버의 SQLite 데이터베이스를 사용하여 지금이 문제가 발생했습니다. 데이터베이스가 열려있는 동안 사용한 원격 셸 세션이 중단 된 후 SQLite가 잠금을 얻을 수 없습니다.

위에서 제안한 복구 방법은 저에게 효과적이지 않습니다 (데이터베이스를 먼저 이동 한 다음 다시 복사하는 아이디어 포함). 그러나 비 NFS 시스템에 복사 한 후 데이터베이스를 사용할 수있게되었으며 데이터가 손실되지 않은 것으로 보입니다.


9

잠금은 프로세스 중단이 아니라 시스템 충돌로 인해 발생했습니다. 이 문제를 해결하기 위해 파일 이름을 바꾸고 원래 이름과 위치로 다시 복사했습니다.

리눅스 쉘을 사용하면 ...

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

네트워크 드라이브의 데이터베이스 잠금 문제를 해결하는 매우 쉬운 솔루션입니다.
— Maverick2805


4

SQLite의 다양한 잠금 상태에 대한 문서 가 매우 유용 하다는 것을 알았습니다 . Michael, 읽기를 수행 할 수 있지만 데이터베이스에 대한 쓰기를 수행 할 수없는 경우 프로세스가 데이터베이스에서 예약 된 잠금을 받았지만 아직 쓰기를 실행하지 않았 음을 의미합니다. SQLite3를 사용하는 경우 더 이상 프로세스를 연결할 수 없지만 기존 연결에서 읽기를 수행 할 수있는 PENDING이라는 새로운 잠금이 있습니다. 따라서 이것이 문제인 경우 대신 살펴 봐야합니다.


4

파일이 공유 폴더와 같은 원격 폴더에있는 경우이 오류가 발생할 수 있습니다. 데이터베이스를 로컬 디렉토리로 변경했으며 완벽하게 작동했습니다.


3

앱 내에서 이러한 문제가 발생하여 2 개의 연결에서 SQLite에 액세스 할 수 있습니다. 하나는 읽기 전용이고 두 번째는 쓰기 및 읽기입니다. 읽기 전용 연결이 두 번째 연결에서 쓰기를 차단 한 것 같습니다. 마지막으로, 사용 후 즉시 준비된 명령문을 마무리하거나 최소한 재설정해야한다는 것이 밝혀졌습니다. 준비된 명령문이 열릴 때까지 데이터베이스에 대한 쓰기가 차단되었습니다.

전화를 잊지 마십시오 :

sqlite_reset(xxx);

또는

sqlite_finalize(xxx);

3

INDEX와 같은 일부 기능은 시간이 오래 걸릴 수 있으며 실행되는 동안 전체 데이터베이스를 잠급니다. 그런 경우에는 저널 파일을 사용하지 않을 수도 있습니다!

따라서 프로세스가 실제로 데이터베이스에 쓰기 때문에 데이터베이스가 잠겨 있는지 확인하는 가장 좋은 방법은 파일을 두 번 md5 (또는 일부 시스템에서는 md5sum)하는 것입니다. . 다른 체크섬을 얻으면 데이터베이스가 작성되고 있으며 실제로 손상된 테이블 / 데이터베이스로 쉽게 종료 할 수 있기 때문에 실제로 해당 프로세스를 종료하지 않으려 고합니다.

중요한 점은 솔루션이 잠금 프로그램을 찾아서 죽이지 않는 것이 중요하기 때문에 반복 할 것입니다. 데이터베이스에 적절한 이유로 쓰기 잠금이 있는지 확인하고 거기에서 이동하는 것입니다. 때로는 올바른 해결책은 커피 브레이크 일뿐입니다.

이 잠겨 있지만 기록되지 않는 상황을 만드는 유일한 방법은 프로그램이 실행되는 경우입니다. BEGIN EXCLUSIVE테이블을 변경하거나 무언가를 원했기 때문에 어떤 이유로 든 END이후에 절대로 보내지 않으며 프로세스는 결코 끝나지 않습니다 . 세 가지 조건이 모두 올바르게 작성된 코드에서는 거의 발생하지 않으며, 누군가가 잠금 프로세스를 종료하려고 할 때 잠금 프로세스는 실제로 좋은 이유로 데이터베이스를 잠그고 있습니다. 프로그래머는 일반적으로BEGIN EXCLUSIVE 동시성을 방지하고 사용자 불만을 증가시키기 때문에 실제로 필요한 경우가 아니면 조건을 . SQLite 자체는 인덱싱과 같이 실제로 필요할 때만 추가합니다.

마지막으로, 몇 가지 답변에서 언급했듯이 파일 내부에 '잠금'상태가 존재하지 않습니다. 운영 체제의 커널에 있습니다. 실행 된 프로세스가 BEGIN EXCLUSIVEOS에서 파일에 잠금을 설정하도록 요청했습니다. 독점 프로세스가 중단 되더라도 OS는 파일 잠금을 유지해야하는지 여부를 파악할 수 있습니다 !! 잠긴 데이터베이스로 끝나는 것은 불가능하지만 프로세스가 적극적으로 잠그고 있지는 않습니다 !! 어떤 프로세스가 파일을 잠그는 지 확인하는 경우 일반적으로 퓨저 대신 lsof를 사용하는 것이 좋습니다 (이는 /unix/94316/fuser-vs-lsof- 사용중인 파일 확인 ). 또는 DTrace (OSX)가있는 경우 파일에서 iosnoop을 사용할 수 있습니다.


2

내 웹 응용 프로그램은 데이터베이스에서 읽을 수 있지만 삽입 또는 업데이트를 수행 할 수 없었습니다. Apache를 재부팅하면 문제가 일시적으로 해결되었습니다.

그러나 근본 원인을 추적 할 수 있으면 좋을 것입니다.


2

Linux 환경에서 lsof 명령을 사용하면 파일을 열어 둔 상태에서 프로세스가 중단되었다는 것을 알 수있었습니다.
프로세스를 종료하고 문제가 해결되었습니다.



2

데이터베이스의 내부 문제 여야합니다 ...
저에게 "SQLite manager"를 사용하여 데이터베이스를 찾아 보려고 시도한 후에 나타났습니다.
따라서 다른 프로세스를 찾을 수없고 데이터베이스에 연결할 수없고이를 수정할 수없는 경우, 이 급진적 인 해결책을 시도하십시오.

  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 minets google-ing 후 나는 하나의 쉘 마녀가 DB를 사용하고 있지 않다는 것을 알았습니다. 그냥 닫고 다시 시도하십시오.)


1

나는 같은 문제가 있었다. 롤백 함수는 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 )

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 프로세스의 사용자 소유자에게 파일에 대한 r / w 권한이 있는지 확인하십시오.
  • 연결 구멍에서 잠금 모드를 강제로 시도하십시오.

    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

1

여기에 설명 된 것과 약간 다른 시나리오 에서이 오류가 발생했습니다.

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로

우주 상황이 처리 된 후 모든 것이 정상으로 돌아 왔습니다.


1

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

0

이전 의견에서 -journal 파일이 있다고 말했습니다.

이는 귀하가 (독점?) 거래를 개설했지만 아직 데이터를 커밋하지 않았 음을 의미 할 수 있습니다. 프로그램이나 다른 프로세스가 -journal을 남겼습니까?

sqlite 프로세스를 다시 시작하면 저널 파일을보고 커밋되지 않은 작업을 정리하고 -journal 파일을 제거합니다.


0

Seun Osewa가 말했듯이 때로는 좀비 프로세스가 가능하지 않다고 생각하더라도 잠금 장치가 필요한 터미널에 좀비 프로세스가 있습니다. 스크립트가 실행되고 충돌 한 후 프롬프트로 돌아가지만 라이브러리 호출로 인해 어딘가에 좀비 프로세스가 생성되고 해당 프로세스에 잠금이 있습니다.

OSX에있는 터미널을 닫으면 작동 할 수 있습니다. 재부팅이 작동합니다. 아무것도하지 않는 "파이썬"프로세스 (예 :)를 찾아서 죽일 수 있습니다.


0

당신은 이것을 시도 할 수 있습니다 : .timeout 100timeout을 설정하십시오. 명령 줄에서 어떤 일이 발생하는지 모르지만 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.