개발자의 길/Database

[SQLite3][C++] database is locked 에러가 나올 때 ?

토아드 2021. 7. 17. 23:30
반응형

database is locked 에러가 나올 때

 SQLite 개발을 하다 보면 저런 에러메시지를 만나거나 에러코드 SQLITE_BUSY (5) 를 반환받아서 DB 에 대한 읽기/쓰기 가 불가능한 경우를 본 적이 있을 것이다.

 해당 에러코드가 리턴되는 경우는 DB 에 Write 작업을 하는 도중, Read/Write 를 하고자 접근을 한 경우이다.

 SQLite 는 기본적으로 Atomicity (원자성) 을 지키기 위해서 DB 에 write 작업이 발생을 할 경우 File 단위로 lock 을 걸어 버려서, 같은 Database 의 다른 table 에 접근한다 하더라도 lock 이 걸린 상태에서는 읽기/쓰기가 불가능하다.

 혹시나 SQLite3 Lib 을 이용한 프로그램에서 저런 문제가 나온다면, 읽기/쓰기가 동시에 이루어지는 경우에 대한 예외처리를 하지 않았는지 확인이 필요하다.

 

해결 방법은?

 기본적으로 sqlite3_busy_timeout 이나 sqlite3_busy_handler 등의 함수로 위와같은 동시접근 상황이 발생했을 경우에 대한 처리를 해주지 않았다면 sqlite3_step 함수는 즉시 SQLITE_BUSY 를 반환하게 된다. 따라서 프로그램에서 한 SQLite Database 에 동시접근을 하는 경우에 많다면 sqlite3_busy_timeout 등의 함수를 통해서 적절한 처리를 해 주어야 한다.

 sqlite3_busy_timeout 에 대한 자세한 내용은 아래 포스트를 참고 바란다.

https://makedotworld.tistory.com/56

 

 추가적으로 아래와 같은 상황이 있을 수 있다.

 1) DB 에 Update, Insert 문으로 query 를 날리려고 하는데 SQLITE_BUSY 가 나온다. DB 를 읽고 있지도 않은데 왜 그런지?

 -> sqlite3_step 으로 DB 를 읽은 후, sqlite3_reset 이나 sqlite3_finalize 로 sqlite3_stmt 객체를 초기화 해 주었는지 확인하라. sqlite3_step 이 SQLITE_DONE 을 리턴하거나 sqlite3_reset, sqlite3_fianlize 등으로 sqlite3_stmt 객체를 초기화 시켜주지 않으면 DB 는 계속 Read 중인 상태로 여겨질 것이다.

 

2) sqlite3_busy_timeout 을 설정해 주었는데도 DB Read 가 끝난 직후 sqlite3_step 이 SQLITE_DONE 을 리턴하면서 성공하지 않고 수 ms 대기후에 SQLITE_BUSY 를 리턴한다. 왜 그런지?

 -> 위의 sqlite3_busy_timeout 포스트를 참고 바란다. 

 

 SQLite3 의 Atomicity

 SQLite3 가 어떤 방식으로 Atomicity 를 지키는지 자세히 알아보기 위해서는 아래 페이지를 참고하면 된다. 왠만해서는 이정도 수준까지 알 필요는 없지만, 개발하는 프로그램이 동작할 system 이 언제든지 power failure 등으로 전원이 꺼질 수 있는 상태에서 SQLite3 DB 무결성을 지켜야 하는 상황이라면 아래 페이지를 참고 바란다. 별다른 설정 없이 위와같은 조건에서 SQLite3 가 무결성을 지켜주지는 않는다.

https://www.sqlite.org/atomiccommit.html

 

Atomic Commit In SQLite

Each transaction can be committed by overwriting the rollback journal header with zeros rather than deleting the journal file. This avoids having to modify the directory entry for the journal file and it avoids having to deallocate disk sectors associated

www.sqlite.org

 

 

 

반응형