개발자의 길/Database

[SQLite3][C++] sqlite3_busy_timeout

토아드 2021. 7. 18. 15:49
반응형

지난 포스팅에 이어, SQLite3 database 가 locked 상태인 경우에 일정 시간 대기를 하도록 설정이 가능한 sqlite3_busy_timeout 함수를 살펴보고자 한다.

 해당 함수에 대한 문서는 아래 주소를 참고 바란다.

https://www.sqlite.org/c3ref/busy_timeout.html

 

 sqlite3_step 을 통해 DB 에 접근을 하는 동작을 수행할 때 만약에 DB 가 Write 접근 - Read lock 이나 Read/Write 접근 - Write lock 인 상태에는 SQLITE_BUSY 를 즉시 리턴하게 된다. 여러 쓰레드/프로세스에서 해당 데이터베이스에 접근하는게 일반적인 상황이라면 즉시 접근실패를 하고 종료하는 것 보다 lock 을 놓을 때 까지 대기하는것이 일반적인 상황에서는 좋다. 이러한 기능을 지원해 주는 것이 sqlite3_busy_timeout 이다.

 

1
2
3
sqlite3 *pDb = NULL;
sqlite3_open_v2( "./DB.sq3"&pDb, SQLITE_OPEN_READWRITE, NULLNULL );
sqlite3_busy_timeout( pDb, 100 );
cs

 

 

위와 같이 사용을 한 뒤 pDB 로 prepare 된 sqlite3_stmt 객체 preparedStatement 를 아래와 같이 사용하면

 sqlite3_step( preparedStatement ) 

DB 가 lock 상태여서 접근할수가 없을 경우 즉시 sqlite3_step 이 SQLITE_BUSY 를 리턴하는게 아니라 100 ms 동안 DB lock 이 풀릴 때까지 접근을 반복적으로 시도하게 된다. 100ms 가 지난 이후에도 접근이 불가능한 경우 SQLITE_BUSY 를 리턴하게 된다.

 

 위 함수를 사용함에 있어서 주의할 사항이 있는데, HAVE_USLEEP 컴파일 옵션을 주지 않으면 DB lock 이 걸려있을 경우에 1000ms 간격으로 대기하며 DB 접근이 가능한지 확인한다는 것이다. 만약에 timeout 을 3000 으로 준다면, 총 3번 DB 접근이 가능한지 확인하기 때문에 매우 비효율적이고, DB 접근이 가능한지 확인하는 타이밍에만 DB lock 이 걸려있으면 3000 ms 대기 후 SQLITE_BUSY 를 리턴하게 된다.

 그래서 위 함수를 이용해서 동시접근 이슈를 해결하고 싶다면 HAVE_USLEEP 컴파일 옵션을 반드시 주길 추천한다. 해당 옵션을 주면 1ms -> 2ms -> 3ms -> 5ms -> ....  순으로 점진적으로 늘어나는 시간만큼 대기하면서 DB 접근이 가능한지 확인하게 된다. ( 정확한 값은 아니다. sqlite association 쪽에 문의했을 때 대략적으로 위와 같은 시간만큼 대기한다고 답변을 받았었다 )

 

 특정 DB Connection ( sqlite3_open_v2 로 열린 sqlite3* 객체 ) 에 대해 busy handler 는 하나밖에 존재하지 못하기 때문에, 다른 wait time 을 주고 싶다면 새로운 DB 객체를 열어서 위 함수를 호출하면 된다.

반응형