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 文件 |
从 11820 节点的 replicalog 中恢复 sample.employee 的记录、lob 数据至 revertCS.revertCL 集合
sdbrevert --hosts localhost:11810 --targetcl sample.employee --logpath ./database/data/11820/replicalog/ --output revertCS.revertCL
恢复指定 oid 的记录数据。特殊字符 "$" 需要转义处理
sdbrevert --hosts localhost:11810 --targetcl sample.employee --logpath ./database/data/11820/replicalog/ --output revertCS.revertCL --matcher "{'_id': {'\$oid': '649aad16936f54aba362ff61'}}" --datatype doc
恢复指定 oid 的 lob 数据。oid 中的 key 与记录数据一样是 "_id"
sdbrevert --hosts localhost:11810 --targetcl sample.employee --logpath ./database/data/11820/replicalog/ --output revertCS.revertCL --matcher "{'_id': {'\$oid': '0000649aebfb3600042dd1e0'}}" --datatype 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 );