SQLite 학습 안내서(SQLite 온라인 백업)
다음 방법은 비교적 간단하고 자주 사용하는 SQLite 데이터베이스 백업 방식입니다. 다음 절차를 보십시오. 1)SQLite API 또는 Shell 도구를 사용하여 소스 데이터베이스 파일에 공유 잠금을 추가합니다. 2). Shell 도구(cp 또는copy)를 사용하여 데이터베이스 파일을 백업 디렉토리로 복사합니다. 3). 데이터베이스 파일의 공유 잠금을 해제합니다.상기 3단계는 대부분의 장면에 응용할 수 있고 속도도 비교적 빠르지만 일정한 강성 결함이 존재한다. 예를 들어 1).전체 복사 프로세스가 끝나고 파일 공유 잠금이 해제될 때까지 원본 데이터베이스에서 쓰기 작업을 수행하려는 모든 연결이 끊어져야 합니다. 2). 인메모리 데이터베이스에 데이터를 복사할 수 없습니다. 3). 복사 과정에서 백업 데이터베이스가 있는 호스트에 돌발적인 고장이 발생하면 백업 데이터베이스가 파괴될 수 있다.SQLite에서 온라인 데이터베이스 백업에 사용할 API 함수(C 인터페이스)를 제공하여 상술한 방법의 부족함을 잘 해결할 수 있습니다.이 그룹 함수를 통해 원본 데이터베이스의 내용을 다른 데이터베이스로 복사하고 대상 데이터베이스의 데이터를 덮어쓸 수 있습니다.전체 복사 과정은 증량적인 방식으로 완성될 수 있으며, 이 경우 원본 데이터베이스도 전체 복사 과정에서 잠기지 않고 실제 데이터를 읽을 때 공유 잠금을 추가할 필요가 없다.이렇게 하면 다른 사용자가 원본 데이터베이스에 접근할 때 끊기지 않는다.2. 온라인 백업 API 소개:
SQLite는 이 작업을 수행하기 위해 다음과 같은 3개의 API 함수를 제공합니다. 이 함수는 기본 사용법만 제시하고 자세한 내용은 SQLite 공식 사이트'API Reference'(http://www.sqlite.org/c3ref/backup_finish.html). 1). 함수 sqlite3_backup_init() sqlite3_ 만들기백업 대상, 이 대상은 이번 복사 작업의 핸들로 나머지 두 함수에 전달됩니다. 2). 함수 sqlite3_backup_step () 는 데이터 복사에 사용됩니다. 만약에 이 함수의 두 번째 매개 변수가 -1이라면 전체 복사 과정은 이 함수의 호출에서 완성됩니다. 3). 함수 sqlite3_backup_finish() sqlite3_ 방출backup_자원 유출을 피하기 위해 init () 함수로 신청한 자원입니다.전체 복사 과정에서 오류가 발생하면 목적 데이터베이스로 연결된 sqlite3_errcode () 함수는 구체적인 오류 코드를 가져옵니다.또한 sqlite3_backup_step () 호출 실패, sqlite3_backup_finish () 함수는 현재 연결된 오류 코드를 수정하지 않기 때문에 sqlite3_backup_finish () 다음에 오류 코드를 가져와서 코드에서 오류 처리를 줄였습니다.다음 코드 예제 (SQLite 공식 홈페이지에서 제공) 를 참조하십시오.
/*
** This function is used to load the contents of a database file on disk
** into the "main" database of open database connection pInMemory, or
** to save the current contents of the database opened by pInMemory into
** a database file on disk. pInMemory is probably an in-memory database,
** but this function will also work fine if it is not.
**
** Parameter zFilename points to a nul-terminated string containing the
** name of the database file on disk to load from or save to. If parameter
** isSave is non-zero, then the contents of the file zFilename are
** overwritten with the contents of the database opened by pInMemory. If
** parameter isSave is zero, then the contents of the database opened by
** pInMemory are replaced by data loaded from the file zFilename.
**
** If the operation is successful, SQLITE_OK is returned. Otherwise, if
** an error occurs, an SQLite error code is returned.
*/
int loadOrSaveDb(sqlite3 *pInMemory, const char *zFilename, int isSave){
int rc; /* Function return code */
sqlite3 *pFile; /* Database connection opened on zFilename */
sqlite3_backup *pBackup; /* Backup object used to copy data */
sqlite3 *pTo; /* Database to copy to (pFile or pInMemory) */
sqlite3 *pFrom; /* Database to copy from (pFile or pInMemory) */
/* Open the database file identified by zFilename. Exit early if this fails
** for any reason. */
rc = sqlite3_open(zFilename, &pFile);
if( rc==SQLITE_OK ){
/* If this is a 'load' operation (isSave==0), then data is copied
** from the database file just opened to database pInMemory.
** Otherwise, if this is a 'save' operation (isSave==1), then data
** is copied from pInMemory to pFile. Set the variables pFrom and
** pTo accordingly. */
pFrom = (isSave ? pInMemory : pFile);
pTo = (isSave ? pFile : pInMemory);
/* Set up the backup procedure to copy from the "main" database of
** connection pFile to the main database of connection pInMemory.
** If something goes wrong, pBackup will be set to NULL and an error
** code and message left in connection pTo.
**
** If the backup object is successfully created, call backup_step()
** to copy data from pFile to pInMemory. Then call backup_finish()
** to release resources associated with the pBackup object. If an
** error occurred, then an error code and message will be left in
** connection pTo. If no error occurred, then the error code belonging
** to pTo is set to SQLITE_OK.
*/
pBackup = sqlite3_backup_init(pTo, "main", pFrom, "main");
if( pBackup ){
(void)sqlite3_backup_step(pBackup, -1);
(void)sqlite3_backup_finish(pBackup);
}
rc = sqlite3_errcode(pTo);
}
/* Close the database connection opened on database file zFilename
** and return the result of this function. */
(void)sqlite3_close(pFile);
return rc;
}
3. 고급 응용 기교: 위의 예에서 우리는 sqlite3_를 통해backup_step () 함수의 호출로 전체 복사 과정이 완료되었습니다.이 실현 방식은 이전에 말한 다른 쓰기 액세스 연결을 끊는 문제가 여전히 존재한다. 이 문제를 해결하기 위해 우리는 계속해서 다른 고급 실현 방식인 분할 복사를 소개할 것이다. 그 실현 절차는 다음과 같다. 1).함수 sqlite3_backup_init() sqlite3_ 만들기백업 대상, 이 대상은 이번 복사 작업의 핸들로 나머지 두 함수에 전달됩니다. 2). 함수 sqlite3_backup_step () 는 데이터 복사에 호출됩니다. 이전 방법과 달리 이 함수의 두 번째 매개 변수는 -1이 아니라 일반적인 정수입니다. 호출할 때마다 복사할 페이지의 수량을 나타냅니다. 예를 들어 5. 3). 하면, 만약, 만약...backup_step () 호출이 끝난 후에도 더 많은 페이지가 복사되어야 합니다. 그러면 250ms를 자발적으로 휴면하고 2단계를 반복합니다. 4). 함수 sqlite3_backup_finish() sqlite3_ 방출backup_자원 유출을 피하기 위해 init () 함수로 신청한 자원입니다.상기 단계 3)에서 우리는 250ms를 자발적으로 휴면합니다. 이 기간 동안 이 복사 작업은 원본 데이터베이스에 어떠한 읽기 잠금도 가지고 있지 않으며 다른 데이터베이스 연결은 쓰기 작업을 할 때도 끊기지 않습니다.그러나 휴면 중에 다른 스레드나 프로세스가 원본 데이터베이스에 쓰기 작업을 하면 SQLite가 이 이벤트의 발생을 감지하여 다음 호출 sqlite3_backup_step () 함수 시 전체 복사 과정을 다시 시작합니다.유일한 예외는 원본 데이터베이스가 in-memory 데이터베이스가 아니라 복사 작업과 같은 프로세스에서 이루어지고 작업할 때 같은 데이터베이스 연결 핸들을 사용한다면 목적 데이터베이스에서 데이터도 이 작업과 동시에 자동으로 수정된다는 것이다.다음 호출 sqlite3_backup_step () 시에도 아무런 영향이 없습니다.사실 SQLite에서는 다른 두 개의 보조 함수 backup_를 제공합니다remaining () 및 backup_이 중 전자는 현재 백업 작업에서 복사해야 할 페이지가 얼마나 많은지, 후자는 이번 작업에서 복사해야 할 페이지 수를 되돌려줍니다.이 두 함수의 반환 결과를 통해 우리는 이번 백업 작업의 전체 진도를 실시간으로 표시할 수 있다. 계산 공식은 다음과 같다. Completion = 100% *(pagecount () - remaining ()/pagecount () 는 다음 코드 예시 (SQLite 홈페이지에서 온 것) 를 보십시오.
/*
** Perform an online backup of database pDb to the database file named
** by zFilename. This function copies 5 database pages from pDb to
** zFilename, then unlocks pDb and sleeps for 250 ms, then repeats the
** process until the entire database is backed up.
**
** The third argument passed to this function must be a pointer to a progress
** function. After each set of 5 pages is backed up, the progress function
** is invoked with two integer parameters: the number of pages left to
** copy, and the total number of pages in the source file. This information
** may be used, for example, to update a GUI progress bar.
**
** While this function is running, another thread may use the database pDb, or
** another process may access the underlying database file via a separate
** connection.
**
** If the backup process is successfully completed, SQLITE_OK is returned.
** Otherwise, if an error occurs, an SQLite error code is returned.
*/
int backupDb(
sqlite3 *pDb, /* Database to back up */
const char *zFilename, /* Name of file to back up to */
void(*xProgress)(int, int) /* Progress function to invoke */
){
int rc; /* Function return code */
sqlite3 *pFile; /* Database connection opened on zFilename */
sqlite3_backup *pBackup; /* Backup handle used to copy data */
/* Open the database file identified by zFilename. */
rc = sqlite3_open(zFilename, &pFile);
if( rc==SQLITE_OK ){
/* Open the sqlite3_backup object used to accomplish the transfer */
pBackup = sqlite3_backup_init(pFile, "main", pDb, "main");
if( pBackup ){
/* Each iteration of this loop copies 5 database pages from database
** pDb to the backup database. If the return value of backup_step()
** indicates that there are still further pages to copy, sleep for
** 250 ms before repeating. */
do {
rc = sqlite3_backup_step(pBackup, 5);
xProgress(
sqlite3_backup_remaining(pBackup),
sqlite3_backup_pagecount(pBackup)
);
if( rc==SQLITE_OK || rc==SQLITE_BUSY || rc==SQLITE_LOCKED ){
sqlite3_sleep(250);
}
} while( rc==SQLITE_OK || rc==SQLITE_BUSY || rc==SQLITE_LOCKED );
/* Release resources allocated by backup_init(). */
(void)sqlite3_backup_finish(pBackup);
}
rc = sqlite3_errcode(pFile);
}
/* Close the database connection opened on database file zFilename
** and return the result of this function. */
(void)sqlite3_close(pFile);
return rc;
}