sdbrevert 是 SequoiaDB 巨杉数据库的数据恢复工具,用于从同步日志、归档日志中恢复被误删除的记录、lob 数据。
数据恢复步骤:
支持恢复的数据如下:
| 类型 | 说明 |
|---|---|
| delete doc | 记录数据误删除 |
| delete lob | lob 数据误删除 |
Note:
- 3.4.2 及以后版本 SequoiaDB 的日志才支持恢复 lob 数据
- 不支持发生移动的归档日志文件,如 archivelog.1.m
| 参数名 | 缩写 | 描述 |
|---|---|---|
| --help | -h | 打印帮助信息 |
| --version | -V | 打印版本号 |
| --hostname | 主机名 | |
| --svcname | 服务名(端口号) | |
| --hosts | 指定主机地址(hostname:svcname),用“,”分隔多个地址,默认值为 localhost:11810 | |
| --user | 数据库用户 | |
| --password | 数据库用户密码,如果不使用该参数指定密码,工具会通过交互式界面提示用户输入密码 | |
| --token | 密文的加密令牌 如果创建密文时未指定 token,可忽略该参数 |
|
| --cipherfile | 加密文件路径,默认路径为 ~/sequoiadb/passwd。关于密文模式可参考密码管理 |
|
| --ssl | 是否使用 SSL 连接,默认值为 false,不使用 SSL 连接 | |
| --targetcl | 恢复数据的目标集合 (csname.clname),必填 | |
| --logpath | 日志路径,用“,”分隔多个文件、路径按,支持复制日志、归档日志,必填 | |
| --datatype | 恢复的数据类型,默认为 "all",取值如下: all:同时恢复记录与 lob 数据 doc:仅恢复记录数据 lob:仅恢复 lob 数据 |
|
| --matcher | 数据过滤条件,json 格式 | |
| --starttime | 起始时间,格式 “YYYY-MM-DD-HH:mm:ss”,默认为 UTC 时间 1970-01-01-00:00:00 | |
| --endtime | 结束时间,格式 “YYYY-MM-DD-HH:mm:ss”,默认为 2037-12-31-23:59:59 | |
| --startlsn | 起始 LSN,默认为 0 | |
| --endlsn | 结束 LSN,默认不限制 | |
| --output | 保存数据的临时集合 (csname.clname),必填 | |
| --label | 标签,供用户标识不同批次恢复的记录数据。默认为 "" | |
| --jobs | 执行数据恢复的线程数量,默认为 1。多线程以日志文件为单位并发恢复数据 | |
| --stop | 单个线程执行失败时,其余线程是否需要停止执行。默认为 false,取值如下: false:其余线程继续执行 true:其余线程停止执行 |
|
| --fillhole | 是否以 0 填充 lob 数据的空洞。默认为 false,取值如下: false:不提填充,保留 lob 空洞 true:填充 |
|
| --tmppath | 临时路径,用于保存解压归档日志时产生的临时文件,默认保存在归档日志文件所属目录 |
Note:
- 恢复数据时,同一复制组内,仅需指定一个副本节点的日志,以免恢复的数据重复
- lob 数据以分片的形式分散存储在多个复制组中。在恢复 lob 数据时,需要确保指定的日志文件包含了完整的 lob 数据,以免恢复的 lob 数据不完整
- 如果多次创建、删除了相同 oid 的 lob 数据。在恢复该 oid 的 lob 数据时,以最新一次删除操作为准,所以最终恢复的结果不保证准确性。
- 时间范围为 [starttime, endtime),且是根据日志文件的最后一次修改时间进行过滤。最大时间范围 [1970-01-01-00:00:00, 2037-12-31-23:59:59)
- LSN 范围为 [startlsn, endlsn)
- 临时集合需要用户自行创建,且 sdbrevert 不会清除临时集合中的历史数据
- 对于 lob 数据,可写入的不连续分片不能超出 320 个,如果超出,则继续写该 lob 时会报 -319 错误。对于超大 lob,如 40MB 以上,sdbrevert 按分片恢复 lob 数据时,可能会出现写入的不连续 lob 分片超过 320 个。此时如果 --fillhole 取值为 false,则会跳过 -319 错误,最终恢复的超大 lob 数据不保证正确性。如果 --fillhole 取值为 true,则 sdbrevert 会以 0 填充 lob 空洞,以此合并不连续的 lob 分片,以免数量超出限制,最终保证恢复的 lob 的数据正确性,但该 lob 将不存在空洞
- 如果归档日志开启了压缩功能,且 sdbrevert 对归档日志所在路径没有写权限时,需要指定 --tmppath 参数。解压产生的临时文件最终会被 sdbrevert 自动删除。
sdbrevert 执行完成后,会返回如下信息:
| 字段名 | 描述 |
|---|---|
| Processed file num | 实际处理的日志文件数量,仅统计恢复范围内的有效日志文件 |
| LSN scope | 实际恢复的 LSN 范围 [startlsn, endlsn) |
| Parsed log num | 解析的日志条数 |
| Parsed doc num | 解析被删除的记录数量 |
| Parsed lob pieces num | 解析被删除的 lob 分片数量 |
| Reverted doc num | 恢复被删除的记录数量 |
| Reverted lob pieces num | 恢复被删除的 lob 分片数量 |
| Revert failed log file | 恢复失败的 lob 文件 |
记录数据被封装为如下格式保存在临时集合中
| 字段名 | 描述 |
|---|---|
| entry | 原始数据 |
| optype | 操作类型,当前仅为 "DOC_DELETE" |
| label | 自定义的标签 |
| lsn | 该记录在日志中的 LSN |
| source | 记录所属的日志文件 |
示例
{
"_id": {
"$oid": "649aad2e23300bc3c3fc7e06"
},
"entry": {
"_id": {
"$oid": "649aad16936f54aba362ff61"
},
"name": "Tom",
"age": 20
},
"optype": "DOC_DELETE",
"label": "",
"lsn": 393771196,
"source": "/opt/sequoiadb/11810/replicalog/sequoiadbLog.2"
}
将记录数据恢复至正式集合中
var matcher = { "entry._id": { "$oid": "649aad16936f54aba362ff61" } };
var selector = { "entry": "" };
// 从临时集合 revertCS.revertCL 获取数据
var cursor = db.revertCS.revertCL.find( matcher, selector );
while( cursor.next() )
{
// 将数据写入正式表 sample.employee 中
db.sample.employee.insert( cursor.current().toObj()["entry"] );
}
cursor.close();
如果临时集合中的数据量较多,可根据原始数据创建非唯一索引,以提升处理效率
var idxName = "dataIndex";
var idxDef = { "entry._id": 1 };
db.revertCS.revertCL.createIndex( idxName, idxDef );
lob 数据以普通格式保存在临时集合中,可使用 listLobs() 查看,示例如下
> db.revertCS.revertCL.listLobs();
{
"Size": 22020096,
"Oid": {
"$oid": "0000649aebfb3600042dd1e0"
},
"CreateTime": {
"$timestamp": "2023-06-27-14.05.02.552000"
},
"ModificationTime": {
"$timestamp": "2023-06-27-14.05.02.724000"
},
"Available": true
}
将 lob 数据恢复至正式集合中
var tmpFile = "/opt/sequoiadb/tmp.txt"; var lobId = "0000649aebfb3600042dd1e0"; db.revertCS.revertCL.getLob( lobId, tmpFile ); db.sample.employee.putLob( tmpFile, lobId );