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
'개발자의 길 > Database' 카테고리의 다른 글
[SQLite3][C++] database is malformed - DB 에 손상이 갔을 때. (0) | 2021.07.31 |
---|---|
[SQLite3][C++] SQLite3 에서 record 를 지워도 DB 용량이 줄어들지 않는 이유는? - page, vacuum, rbu vacuum. (0) | 2021.07.30 |
[SQLite3][C++] Sqlite3 의 journal file 에 대해 (0) | 2021.07.28 |
[SQLite3][C++] SQLite 의 file lock 매커니즘 (0) | 2021.07.18 |
[SQLite3][C++] sqlite3_busy_timeout (0) | 2021.07.18 |