Click here to view and discuss this page in DocCommentXchange. In the future, you will be sent there automatically.

SQL Anywhere 11.0.1 (中文) » SQL Anywhere 服务器 - 编程 » SQL Anywhere 数据访问 API » SQL Anywhere 嵌入式 SQL » 库函数参考

 

db_backup 函数

原型
void db_backup(
SQLCA * sqlca,
int op,
int file_num,
unsigned long page_num,
struct sqlda * sqlda);
授权

必须以具有 DBA 权限、REMOTE DBA 权限 (SQL Remote) 或 BACKUP 权限的用户身份进行连接。

说明
建议使用 BACKUP 语句

尽管此函数提供了一种向应用程序添加备份功能的方法,但建议您使用 BACKUP 语句来完成此任务。请参见BACKUP 语句

执行的操作取决于 op 参数的值:

  • DB_BACKUP_START   必须先调用此函数,然后才能开始备份。对于任何给定的数据库服务器,一个数据库一次只能运行一个备份。在备份完成之前禁用数据库检查点(直到使用 op 值 DB_BACKUP_END 调用 db_backup)。如果备份无法启动,则 SQLCODE 为 SQLE_BACKUP_NOT_STARTED。否则,将 sqlca 的 SQLCOUNT 字段设置为数据库页的大小。一次一页地对备份进行处理。

    忽略 file_numpage_numsqlda 参数。

  • DB_BACKUP_OPEN_FILE   打开由 file_num 指定的数据库文件,这允许使用 DB_BACKUP_READ_PAGE 备份指定文件的页。根数据库文件、事务日志文件的有效文件编号分别为:0 到 DB_BACKUP_MAX_FILE 和 0 到 DB_BACKUP_TRANS_LOG_FILE。如果指定的文件不存在,则 SQLCODE 为 SQLE_NOTFOUND。否则,SQLCOUNT 包含文件中的页数,SQLIOESTIMATE 包含一个标识数据库文件创建时间的 32 位值 (POSIX time_t),操作系统文件名位于 SQLCA 的 sqlerrmc 字段中。

    忽略 page_numsqlda 参数。

  • DB_BACKUP_READ_PAGE   读取由 file_num 指定的数据库文件的一页。使用 DB_BACKUP_OPEN_FILE 操作对 db_backup 调用成功后会在 SQLCOUNT 中返回一个页数,page_num 值应介于 0 到此页数减去一得到的数之间。否则,SQLCODE 将设置为 SQLE_NOTFOUND。sqlda 描述符应使用一个指向缓冲区的 DT_BINARY 或 DT_LONG_BINARY 类型的变量建立。使用 DB_BACKUP_START 操作调用 db_backup 时会在 SQLCOUNT 字段中返回一个大小值,该缓冲区应足以保存这一大小的二进制数据。

    DT_BINARY 数据包含一个后跟实际二进制数据的两字节长度值,因此缓冲区必须比页大小大两个字节。

    应用程序必须保存缓冲区

    此调用会在缓冲区中制作指定数据库页的一个副本,但应由应用程序将缓冲区保存到某种备份介质。

  • DB_BACKUP_READ_RENAME_LOG   此操作与 DB_BACKUP_READ_PAGE 只有一点不同:事务日志的最后一页返回之后,数据库服务器会重命名事务日志并启动一个新的事务日志。

    如果数据库服务器无法在当前时间重命名日志(例如,在 7.0.x 版或更早版本的数据库中可能存在未完成的事务),则会设置 SQLE_BACKUP_CANNOT_RENAME_LOG_YET 错误。在这种情况下,不要使用返回的页,而是要重新发出请求,直到收到 SQLE_NOERROR,然后写入页。继续读取页,直到收到 SQLE_NOTFOUND 条件。

    可能会在多个页上多次返回 SQLE_BACKUP_CANNOT_RENAME_LOG_YET 错误。您应该在重试循环中增加延迟,以便不会因请求过多而降低服务器的速度。

    当您收到 SQLE_NOTFOUND 条件时,事务日志已经成功备份且文件已经重命名。旧日志文件的名称在 SQLCA 的 sqlerrmc 字段中返回。

    您应在 db_backup 调用后检查 sqlda->sqlvar[0].sqlind 的值。如果此值大于零,则最后一个日志页已经写入且日志文件已经重命名。新名称仍然在 sqlca.sqlerrmc 中,但 SQLCODE 值是 SQLE_NOERROR。

    此后,您不应再次调用 db_backup(除非要关闭文件并完成备份),否则,您会获得备份日志文件的第二份副本并收到 SQLE_NOTFOUND。

  • DB_BACKUP_CLOSE_FILE   处理完一个文件后必须调用此函数以关闭由 file_num 指定的数据库文件。

    忽略 page_numsqlda 参数。

  • DB_BACKUP_END   备份结束时必须调用此函数。在此备份结束之前,任何其它备份都无法启动。会再次启用检查点。

    忽略 file_numpage_numsqlda 参数。

  • DB_BACKUP_PARALLEL_START   开始并行备份。与 DB_BACKUP_START 类似,对于任何给定的数据库服务器,一个数据库一次只能运行一个备份。在备份完成之前禁用数据库检查点(直到使用 op 值 DB_BACKUP_END 调用 db_backup)。如果备份无法启动,则将收到 SQLE_BACKUP_NOT_STARTED。否则,将 sqlca 的 SQLCOUNT 字段设置为数据库页的大小。

    file_num 参数指示数据库服务器在事务日志的最后一页返回之后重命名事务日志并启动一个新的日志。如果此值非零,则将重命名或重新启动事务日志。否则,不会重命名或重新启动事务日志。此参数消除了对 DB_BACKUP_READ_RENAME_LOG 操作的需要,并行备份操作期间不允许进行该操作。

    page_num 参数通知数据库服务器客户端缓冲区的最大大小(以数据库页为单位)。在服务器端,并行备份读取程序会尝试读取连续页块—此值可告知服务器应为这些块分配多大的内存空间:传递 N 值可告知服务器:客户端一次可以从服务器接收最多 N 个数据库页。如果服务器无法为 N 页块分配足够的内存,服务器可能会返回小于 N 的页块。如果客户端在调用 DB_BACKUP_PARALLEL_START 之前不清楚数据库页的大小,则可通过 DB_BACKUP_INFO 操作将此值提供给服务器。必须在首次调用前提供此值,以便检索备份页 (DB_BACKUP_PARALLEL_READ)。

    注意

    如果使用 db_backup 开始并行备份,db_backup 不会创建写入程序线程。db_backup 的调用程序必须接收数据并充当写入程序。

  • DB_BACKUP_INFO   此参数为数据库服务器提供关于并行备份的其它信息。file_num 参数指示所提供信息的类型,page_num 参数提供值。您可以使用 DB_BACKUP_INFO 指定以下其它信息:

    • DB_BACKUP_INFO_PAGES_IN_BLOCK   page_num 参数包含应在同一块内发回的最大页数。

    • DB_BACKUP_INFO_CHKPT_LOG   这是相当于 BACKUP 语句的 WITH CHECKPOINT LOG 选项的客户端。page_num 的值 DB_BACKUP_CHKPT_COPY 指示 COPY,而值 DB_BACKUP_CHKPT_NOCOPY 指示 NO COPY。如果未提供此值,则缺省为 COPY。

  • DB_BACKUP_PARALLEL_READ   此操作从数据库服务器上读取页块。调用此操作前,使用 DB_BACKUP_OPEN_FILE 操作打开所有要备份的文件。DB_BACKUP_PARALLEL_READ 会忽略 file_numpage_num 参数。

    sqlda 描述符应使用一个指向缓冲区的 DT_LONGBINARY 类型的变量建立。缓冲区大小应足以保存 N 页(在 DB_BACKUP_START_PARALLEL 操作或 DB_BACKUP_INFO 操作中指定)大小的二进制数据。有关此数据类型的详细信息,请参见嵌入式 SQL 数据类型中的 DT_LONGBINARY。

    服务器为特定数据库文件返回连续数据库页块。块内第一页的页码在 SQLCOUNT 字段中返回。页所属的文件号在 SQLIOESTIMATE 字段中返回,此值与在 DB_BACKUP_OPEN_FILE 调用中使用的文件号之一相匹配。返回的数据大小存储在 DT_LONGBINARY 变量的 stored_len 字段中,并且总是数据库页面大小的倍数。当此调用所返回的数据内包含某个给定文件的连续页块时,单独的数据块不一定会按顺序返回,某一数据库文件的所有页也不一定会在另一数据库文件的页之前全部返回。调用程序应该准备接收不按顺序的另一单个文件的一部分或在任何给定调用中打开的任何数据库文件的一部分。

    应用程序应该重复调用此操作,直到读取的数据大小为 0 或者 sqlda->sqlvar[0].sqlind 的值大于 0。如果备份启动时重命名/重新启动了事务日志,则 SQLERROR 可能设置为 SQLE_BACKUP_CANNOT_RENAME_LOG_YET。在这种情况下,不要使用返回的页,而是要重新发出请求,直到收到 SQLE_NOERROR,然后写入数据。可能会在多个页上多次返回 SQLE_BACKUP_CANNOT_RENAME_LOG_YET 错误。您应该在重试循环中增加延迟,以便不会因请求过多而降低数据库服务器的速度。继续读取页,直到满足上述两个条件之一。

dbbackup 实用程序使用下面的算法。注意,这不是 C 代码,不包括错误检查。

sqlda->sqld = 1;
sqlda->sqlvar[0].sqltype = DT_LONGBINARY

/* Allocate LONGBINARY value for page buffer. It MUST have */
/* enough room to hold the requested number (128) of database pages */
sqlda->sqlvar[0].sqldata = allocated buffer

/* Open the server files needing backup */
for file_num = 0 to DB_BACKUP_MAX_FILE
  db_backup( ... DB_BACKUP_OPEN_FILE, file_num ... )
  if SQLCODE == SQLE_NO_ERROR
    /* The file exists */
    num_pages = SQLCOUNT
    file_time = SQLE_IO_ESTIMATE
    open backup file with name from sqlca.sqlerrmc
end for

/* read pages from the server, write them locally */
while TRUE
  /* file_no and page_no are ignored */
  db_backup( &sqlca, DB_BACKUP_PARALLEL_READ, 0, 0, &sqlda );

  if SQLCODE != SQLE_NO_ERROR
     break;

  if buffer->stored_len == 0 || sqlda->sqlvar[0].sqlind > 0
     break;

  /* SQLCOUNT contains the starting page number of the block    */
  /* SQLIOESTIMATE contains the file number the pages belong to */
  write block of pages to appropriate backup file
end while

/* close the server backup files */
for file_num = 0 to DB_BACKUP_MAX_FILE
    /* close backup file */
    db_backup( ... DB_BACKUP_CLOSE_FILE, file_num ... )
end for

/* shut down the backup */
db_backup( ... DB_BACKUP_END ... )

/* cleanup */
free page buffer