sqlite3_backup * sqlite3_backup_init( sqlite3 * pDest,/ *目标数据库句柄* / const char * zDestName,/ *目标数据库名称* / sqlite3 * pSource,/ *源数据库句柄* / const char * zSourceName / *源数据库名称* / ); int sqlite3_backup_step(sqlite3_backup * p,int nPage); int sqlite3_backup_finish(sqlite3_backup * p); int sqlite3_backup_remaining(sqlite3_backup * p); int sqlite3_backup_pagecount(sqlite3_backup * p);
备份API将一个数据库的内容复制到另一个数据库中。它对于创建数据库备份或将内存数据库复制到持久文件或从持久文件复制都很有用。
另请参见:使用SQLite Online Backup API
在备份操作期间,SQLite会在目标数据库文件上保持打开的写事务。仅在读取源数据库时将其锁定。对于整个备份操作,它不会连续锁定。因此,可以在正在进行的源数据库上执行备份,而不会阻止其他数据库连接在正在进行备份时读取或写入源数据库。
要执行备份操作:
sqlite3_backup_init(D,N,S,M)的D和N参数分别是与目标数据库和数据库名称关联的 数据库连接。对于主数据库,数据库名称是“ main”,对于临时数据库,数据库名称是“ temp”,或者对于附加数据库,在ATTACH语句中的AS关键字之后指定的名称。传递给sqlite3_backup_init(D,N,S,M)的S和M参数分别标识数据库连接 和源数据库的数据库名称。源和目标数据库连接(参数S和D)必须不同,否则sqlite3_backup_init(D,N,S,M)将失败并显示错误。
如果在目标数据库上已经存在可读写的事务,则对sqlite3_backup_init()的调用将失败,并返回NULL。
如果在sqlite3_backup_init(D,N,S,M)中发生错误,则返回NULL,并且错误代码和错误消息存储在目标数据库连接D中。失败调用sqlite3_backup_init()的错误代码和消息可以可以使用sqlite3_errcode(),sqlite3_errmsg()和/或 sqlite3_errmsg16()函数进行检索。成功调用sqlite3_backup_init()会返回一个指向sqlite3_backup对象的指针 。所述sqlite3_backup对象可以与sqlite3_backup_step()和sqlite3_backup_finish()函数被用于执行指定的备份操作。
函数sqlite3_backup_step(B,N)将在sqlite3_backup对象B指定的源数据库和目标数据库之间最多复制N个页面。如果N为负,则将复制所有剩余的源页面。如果sqlite3_backup_step(B,N)成功复制了N页,并且还有更多页面要复制,则该函数返回SQLITE_OK。如果sqlite3_backup_step(B,N)成功完成了将所有页面从源复制到目标的操作,则返回SQLITE_DONE。如果在运行sqlite3_backup_step(B,N)时发生错误,则将返回错误代码。与SQLITE_OK和 SQLITE_DONE一样,对sqlite3_backup_step()的调用也可能返回SQLITE_READONLY, SQLITE_NOMEM,SQLITE_BUSY,SQLITE_LOCKED或 SQLITE_IOERR_XXX扩展错误代码。
该sqlite3_backup_step()可能返回SQLITE_READONLY如果
如果sqlite3_backup_step()无法获得所需的文件系统锁,则将 调用busy-handler函数(如果已指定)。如果忙处理程序在锁可用之前返回非零值,则 SQLITE_BUSY返回给调用方。在这种情况下,可以稍后重试对sqlite3_backup_step()的调用。如果在 调用sqlite3_backup_step()时使用了源 数据库连接来写入源数据库,则将立即返回SQLITE_LOCKED。同样,在这种情况下,稍后可以重试对sqlite3_backup_step()的调用。如果是 SQLITE_IOERR_XXX,SQLITE_NOMEM或 SQLITE_READONLY返回,则重试对sqlite3_backup_step()的调用没有任何意义。这些错误被认为是致命的。应用程序必须接受备份操作失败,然后将备份操作句柄传递给sqlite3_backup_finish()才能释放关联的资源。
第一次调用sqlite3_backup_step()会获得目标文件的排他锁。在调用sqlite3_backup_finish()或备份操作完成且sqlite3_backup_step()返回SQLITE_DONE之前,不释放排他锁。每次调用sqlite3_backup_step()都会获得一个共享锁在sqlite3_backup_step()调用期间持续存在的源数据库上。由于在两次调用sqlite3_backup_step()之间未锁定源数据库,因此可以在备份过程中途修改源数据库。如果源数据库是通过外部过程或通过数据库连接修改的,而不是通过备份操作使用的数据库连接修改的,则备份将在下一次调用sqlite3_backup_step()时自动重新启动。如果使用与备份操作相同的数据库连接来修改源数据库,则备份数据库将同时自动更新。
当sqlite3_backup_step()返回SQLITE_DONE时,或者当应用程序希望放弃备份操作时,应用程序应通过将sqlite3_backup传递给sqlite3_backup_finish()来销毁它。sqlite3_backup_finish()接口释放与sqlite3_backup对象关联的所有资源。如果sqlite3_backup_step()尚未返回SQLITE_DONE,则将回滚目标数据库上的任何活动写事务。所述sqlite3_backup对象是无效的,并且可能不跟随到sqlite3_backup_finish一个呼叫(使用)。
如果没有发生sqlite3_backup_step()错误,则无论sqlite3_backup_step()是否完成,sqlite3_backup_finish返回的值均为SQLITE_OK。如果在同一sqlite3_backup对象上进行任何先前的sqlite3_backup_step()调用期间发生了内存不足的情况或IO错误,则sqlite3_backup_finish()返回相应的错误代码。
从sqlite3_backup_step()返回SQLITE_BUSY或SQLITE_LOCKED不是永久错误,并且不会影响sqlite3_backup_finish()的返回值。
sqlite3_backup_remaining()和sqlite3_backup_pagecount()
sqlite3_backup_remaining()例程返回在最新的sqlite3_backup_step()结束时仍要备份的页面数。sqlite3_backup_pagecount()例程在最新的sqlite3_backup_step()结束时返回源数据库中的页面总数。这些函数返回的值仅由sqlite3_backup_step()更新。如果以更改源数据库大小或剩余页数的方式修改了源数据库,则直到下一个sqlite3_backup_step()之后,这些更改才会反映在sqlite3_backup_pagecount()和sqlite3_backup_remaining()的输出中。
数据库句柄的并发使用
在备份操作正在进行或正在初始化时,应用程序可以将源数据库连接用于其他目的。如果将SQLite编译并配置为支持线程安全数据库连接,则可以从其他线程中同时使用源数据库连接。
但是,应用程序必须确保在调用sqlite3_backup_init()之后和对sqlite3_backup_finish()的相应调用之前,不将目标 数据库连接传递给任何其他API(通过任何线程)。SQLite当前不检查应用程序是否错误地访问了目标数据库连接 ,因此未报告任何错误代码,但是操作仍然可能会出错。在备份过程中使用目标数据库连接也可能会导致互斥锁死锁。
如果以共享缓存模式运行,则应用程序必须保证在备份运行时不会访问目标数据库使用的共享缓存。在实践中,这意味着应用程序必须保证正在备份的磁盘文件不会被进程内的任何连接访问,而不仅仅是传递给sqlite3_backup_init()的特定连接。
所述sqlite3_backup对象本身是部分线程。多个线程可以安全地同时调用sqlite3_backup_step()。但是,严格说来,sqlite3_backup_remaining()和sqlite3_backup_pagecount()API并不是线程安全的。如果在另一个线程正在调用sqlite3_backup_step()的同时调用它们,则可能返回无效值。