备份与恢复
正如数据库持久化页面中所解释的那样,备份是一种在硬件故障时保护数据库的谨慎方法。备份可确保能够将数据库恢复到上次备份完成时的状态。SmartEDB提供了多种备份和恢复数据库的方法:
文件备份
SmartEDB 为使用持久数据库的应用程序提供了在后台线程中创建数据和日志文件副本的功能。可在正常数据库操作不受干扰的情况下进行。这是对磁盘数据库进行备份的最有效方式,因为在文件级别按顺序复制数据,而无需解释数据库页面的内容。
由于文件备份复制的是物理数据和日志文件,因此只需在设备定义中指定这些备份文件,并以常规方式打开数据库,即可“恢复”数据库。
文件备份过程的开销极小,因为只有在实际执行文件复制操作时才会对数据库性能产生影响。但需要注意的是,非常大的数据库文件复制起来可能需要很长时间,这会对数据库应用程序产生显著影响。
请使用以下链接查看针对您的开发环境的详细说明和示例:
功能 | 说明 |
---|---|
mco_disk_backup() | C 语言中的文件备份实现 |
fileBackup() | C++ 语言中的文件备份实现 |
select file_backup() | SQL 语言中的文件备份实现 |
xSQL fileba | xSQL中的文件备份实现 |
保存与加载
这是针对内存和/或持久数据库的导出/导入功能,其中包括集成的二进制模式演变,即可以将数据库保存为二进制图像,然后使用更改后的模式进行恢复。详情请参阅数据导出和导入页面。
SmartEDB 为内存数据库和持久数据库都提供了增量备份和还原 API,同时还为持久数据库提供了文件备份功能。
- 增量备份可以是整个数据库的完整快照(备份类型为 FULL),也可以是仅包含两个连续备份记录之间数据库内容差异的数据库增量备份(部分映像)(备份类型为 INCREMENTAL)。
- 在成功执行 INCREMENTAL 备份之前,必须至少执行一次 FULL 备份(快照)。
- 如果指定备份类型为 AUTO,则根据备份文件的内容创建 FULL 或 INCREMENTAL 备份。
- 如果文件中尚无快照,则备份过程将创建一个,否则创建部分备份。
增量备份必须由应用程序在运行时启用;由于 SmartEDB 运行时通过跟踪已修改的页面来记录对数据库的所有修改,因此这只会带来极小的开销。下一次调用备份时,它已具备所有必要信息,能够仅包含自上次备份以来已更改的页面来执行增量备份。
例如,如果应用程序在两次备份之间仅创建了几个对象/行,那么增量备份将仅包含一些数据页,即所谓的“备份簇”,其中包含已修改的页面和一些受影响的数据。增量备份过程不会阻塞正常的数据库处理。SmartEDB 运行时会在后台跟踪所有修改。然后,备份过程只需扫描那些修改标记,并复制数据页的内容,而不会影响事务处理或阻塞索引。
增量备份
此功能(在 7.1 版本中引入)允许应用程序对临时数据库和持久数据库执行完整或增量(部分)备份。
增量在线备份,意味着在执行数据库备份时,所有其他数据库服务都在运行,即应用程序可以不受限制地访问数据库。
推荐做法
为了确保数据库能够以最小的数据丢失量进行恢复,重要的是在数据库具有足够的初始内容时进行一次完整备份(快照)。
随后在适当的时间间隔内定期执行增量备份。备份过程可以从专门的任务或进程中运行。
该过程如下所示:
connect to the database
while (!stop)
{
backup( connection, file, label )
sleep with appropriate granularity
}
disconnect from the database
这段代码会生成多个备份,直到由某些外部逻辑设置停止变量为止。之后,如有必要,可以恢复数据库。上述代码可以在主数据库应用程序中作为专用任务运行,也可以作为单独的进程运行,甚至可以使用 xSQL 作为批处理文件来控制备份过程。
create the database
connect to the database
restore( connection, file, label )
perform normal database operations
disconnect from the database
一旦恢复完成,就应运行备份周期以生成新的备份。
注意事项
备份文件的大小可能与数据库的实际大小相等或超过其实际大小。
在数据库进行备份期间,除了备份过程结束时的一小段时间外,它可供读写操作。
每次备份结束时,数据库会被锁定,无法进行更新。应用程序可以知晓,写入事务会等待数据库可用时执行。
从备份中还原数据库需要独占访问该数据库。
备份协议可维护数据库的完整性,并且不允许从无序的备份中恢复数据库。
本地语言应用程序编程接口
增量备份/还原 API 与应用程序语言相关。请使用以下链接查看针对您的开发环境的详细说明和示例:
开发语言 | 说明 |
---|---|
C | C 语言中的增量备份/恢复 |
C++ | C++ 语言中的增量备份/恢复 |
SQL | SQL 语言中的增量备份/恢复,其他语言(Python、Java 和 C#)可通过 SQL 语句实现。 |
xSQL | xSQL 中的增量备份/恢复 |
实现
增量备份过程创建一个备份文件,该文件将数据库页面存储在以二进制会话头和页脚结构(称为备份记录)标记的块中。单个备份文件可以包含多个独立的备份,可能是不同类型的备份(完整备份或增量备份),或者具有不同的标记或时间戳。
对于全内存数据库,只创建备份文件。对于持久化数据库,关闭数据库操作将导致创建额外的Backup Map文件。
备份映射
此映射文件包含用于确定在一个增量备份和另一个增量备份之间修改的页面的信息。对于持久数据库,SmartEDB运行时维护计数器(备份位图)。当应用程序关闭数据库时,需要保存计数器的状态,然后在应用程序再次打开数据库时进行恢复。
如果没有这个映射文件,则在每次应用程序关闭和重新启动后都需要一个完整的数据库快照,因为备份过程将没有关于对数据库页面所做修改的数据。因此,当应用程序打开启用增量备份的持久数据库时,无论是否实际调用备份API, SmartEDB运行时都会在每次数据库关闭时创建备份位图文件。
备份映射用于跟踪备份算法处理的数据库页面。要执行增量备份,运行时需要跟踪所有数据库页面的修改。这是通过使用整数计数器来指示页面的内容版本来实现的。每次修改数据库页时,运行时都会增加与该页关联的计数器。
为每个数据库页保留单独的计数器是站不住脚的,因为数据库可能需要几tb的存储空间。因此,运行时为页面集群保留一个计数器。该集群的大小取决于参数backup_map_size
,该参数决定了数据库的计数器总数。运行时计算指定的backup_map_size
中可以容纳多少计数器,然后计算计数器(集群)将服务多少页。因此,对于较大的映射,集群中的页面数量较少,这意味着备份过程将为每个修改的页面存储较少的页面到备份文件。因此,备份速度会更快,备份文件也会更小。另一方面,映射是从数据库内存缓冲区分配的,因此对于更大的映射,缓冲区需要更大。
页面修改跟踪机制与内存数据库和持久化数据库(以及混合数据库,即数据库的内存部分和持久化部分)相似。不同之处在于页面版本计数器的位置:对于持久数据库,计数器位于备份位图中,而对于内存数据库,计数器包含在数据页中。为数据库分配的内存大小是通过数据库打开调用知道的,因此不需要为内存部分使用backup_map_size
参数,因为运行时会自动计算这个大小。但是对于持久数据库,应该指定一个合理的大小。
合理的地图尺寸计算方法如下:
sizeof(int) * <expected-persistent-part-size-in-bytes> / <disk-page-size> / <disk-pages-per-backup-cluster>
其中disk-pages-per-backup-cluster
是指即使修改了该集群的一个页面,也要存储到备份映射中的页面数。
例如,假设磁盘页面大小为4K,我们希望将修改存储在64K的束中;那么每个备份集群的磁盘页面数将是64 / 4 = 16。
然后,在64位系统上计算1G数据库的backup_map_size (sizeof(int) = 4)
,数学运算如下:
4 * 1G / 4K / 16 = (4G / 4K) / 16 = 1M / 16 = 64K
如果没有指定backup_map_size
,那么SmartEDB运行时使用最大持久数据库大小来计算它,它是MCO_INFINITE_DATABASE_SIZE
(64位数据库为1 tb, 32位数据库为4G);因此,默认的backup_map_size
计算如下:
64bit: 4 * 1T / 4K / 16 = (4T / 4K) / 16 = 1G / 16 = 64M
32bit: 4 * 4G / 4K / 16 = (16G / 4K) / 16 = 4M / 16 = 256K
备份过程
备份是一个迭代过程,由两个条件backup_max_passes
和backup_min_pages
控制。
该过程在与可能与数据库运行时交互的其他应用程序活动并行工作时,定期扫描数据库以查找修改。在每次传递中,它都会计算修改页面的数量。当它达到由参数backup_min_pages
或backup_max_passes
确定的阈值时,最后的独占备份传递在将修改过的页面写入备份文件时锁定数据库。参数backup_max_passes
定义了对数据库的备份过程扫描次数的限制。如果数据库的使用情况使得修改的页面很少,以至于可能无法达到backup_min_pages
阈值,那么可以将backup_max_passes
设置为少量的通道,这样当达到该阈值时,运行时将阻止数据库操作并启动最后的独占备份通道。