sqlite3에서 동시 접속에 관련된 질문입니다!
글쓴이: 콩수니 / 작성시간: 월, 2012/02/27 - 5:51오후
안녕하세요
sqlite3를 이용해서 c프로그램을 짜고있는데요
동시접속에 관해서 이 기능안되는것인지 질문드립니다
하나의 프로그램에서는
2초마다 데이터가 수집되어 계속적으로 sqlite3 db에 저장을 합니다
그리고 또하나의 프로그램에서는 이 저장되 db중 일부를 가져다 쓰는데요
첫번째 프로그램에서 해당 db파일을 계속 열고있는 동안에는 다른 프로그램에서 접근을 할수없더군요
확실히 첫번째 프로그램이 종료가 되어야 다른 프로그램이 db를 가져다 쓸수있음을 확인했습니다
결국 동시에 db를 open을 할수없다는것인데
어떻게 해결할수있을까요?
쓰레드로 하면 해결할수있으련가요?
흠..
Forums:
파일락 문제 아닌가요?
sqlite의 경우 별도의 데이터베이스 엔진을 데몬형태로 띄우는 것이 아니라, 데이터베이스 파일만 존재하고, 엔진이 아니라 API가 바로 접근하리라 생각됩니다.
락관리가 OS 파일의 락에 의존하여, 서로 다른 곳에서 접근하지 못할 것으로 추정합니다.
그런것같아요
여러번 테스트해보니깐
sqlite경우 다른 dbms에 비해 경량화 하다보니
api로 접근을 해서 따로 원했던 기능은 가능하지 않는것같습니다.
대신에 멀티 쓰레드로 구성했더니 파일락을 통해서 잘 해주네요
감사합니다.
devband
다음과 같은 방법으로 중복 열기가 가능 하긴 합니다.
//==================================================
// Share Cashe Mode.. 변경.
//==================================================
sqlite3_enable_shared_cache(1);
//쓰기 읽기 모두 가능하게 연다.
//==================================================
// DB Open.
//==================================================
if ( SQLITE_OK !=sqlite3_open_v2(g_szDBFileName,&g_pSQLite,SQLITE_OPEN_NOMUTEX |SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE,NULL))
//==================================================
// 읽기 전용 열기.
//==================================================
if ( SQLITE_OK !=sqlite3_open_v2(pFileName,&m_pRead,SQLITE_OPEN_READONLY,NULL))
{
return FALSE;
}
//프라그마로 읽기 전용으로 열기.==> 중복 가능 열기.
if( SQLITE_OK != sqlite3_exec(m_pRead,"PRAGMA read_uncommitted=TRUE",NULL,NULL,NULL))
{
sqlite3_close(m_pRead);
m_pRead = NULL;
return FALSE;
}
위와 같이 하면.. 쓰기는 하나 쓰레드에서만 가능 하지만, 읽기는 여러곳에서 읽을수 있습니다.
데이터 동기화 문제. 100개를 쓰는 도중 읽을 경우, 동기화가 잘 안맞을 수 있습니다.
즉, 완전히 commit 한 이후에 데이터를 열고, 이것을 읽어야 데이터 동기화가 잘 맞다는 것입니다.
쓰레드로 여려군데서 쓰기를 원한다면, 크리티컬 섹션으로 함수를 래퍼해서 실행시에 잠시만 기다리게 하는 방법과 Timeout(slite 함수)함수로 시간을 지연시켜 쓰기 모드를 획득하는 방법이 있습니다.
제 경험으로는 권하는 방법은 sqlite 함수의 래퍼 함수를 만들고, 쓰기 실행하는 함수에 크리티컬 섹션으로 잠시 기다리게 하는 것이 좋습니다.
더 좋은 방법은...
SQLite를 래퍼하는 완전한 프로세스를 만들고,, IPC 나 TCP/IP통신으로 C/S를 만드는 방법입니다. ^^
그러면, 정해진 루트로만 데이터 접근이 이루어 지므로, 꽤 안정적입니다.
물론... 배보다 배꼽이 더 커질수도있습니다...
참고하겠습니다
이런기능의 함수도있군요
사실 영문이라서 모든 함수를 하나하나 살펴보는데는 -_-내적 한계가있네요.
글을 써주신 내용이라면 동시에 여러명이 접근할경우에는 동기화에 문제가 생길수도있다는것인가요?
사실 임계여역을 만들고 하는 방법도 생각했으나
말그대로 배꼽이 더커질까 두렵네요.
devband
동기화 문제.
동기화 문제는 이렇습니다.
A 쓰레드가 접속해서 쓰는 도중임.
B 와 C 동시에 접속 해서 읽는 도중.
A 는 실제로 50개 썼지만, B 에게는 30만 보이고, C 에게는 40개가 보임.
A 가 모두 쓰기 를 끝내고, commit까지 한 상태에서 접속을 끊음.
D 새로 접속하여 열기함. ==> 데이터가 정상적으로 50개로 보임.
50개가 단순히 쓴 상태에서(자동 커밋이라 하더라도) B와 c에겐 데이터가 상이하게 보일수 있습니다만, D 에게는 정상으로 보입니다.
실시간 데이터가 아주 중요한 경우라면, 저런 현상이 문제가 될 수 있습니다.
덧붙이면, 다중으로 쓰기를 할때에 Begin / Commit을 쓴다면, sqlite자체가 다중 트랜젝션을 지원하지 않기 때문에 내부에서 플래그로 현재 상태를 항상 살피면서 수행 해야 합니다.
댓글 달기