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.