没想到吧, 又讲坏块的恢复, 本章为纯理论, 下一章才讲实现(如果可能的话)
对于"坏块",我们在ibd2sql-1.x版本是使用的try,except
来做, 即跳过"有问题的块". 当时为什么这么设计呢?
使用的try和except,未校验crc32c,故一些不相干的位置坏了(比如PAGE_N_DIRECTION), 并不影响数据的解析.
坏块的不可预见性太大了,于是我们就PASS了.
那么ibd2sql-2.x版本怎么做的呢? 忘记这个功能了, 所以来补一下, 顺便看看能不能救一下!
跳过了的那些坏块不要扔, 捡起来裹上面包糠,炸一下, 隔壁dba都馋哭了.
那么, 有哪些位置可能存在损坏呢? 怎么判断哪些部分损坏了呢?
我们先来回顾下FIL_PAGE_INDEX的结构吧.
对象 | 大小 | 描述 |
---|---|---|
FIL_HEADER | 38 | FIL_HEADER |
PAGE_HEADER | 56 | 一些页头信息, INDEX PAGE的时候再细看 |
INFIMUM | 13 | 最小的行(虚拟的) |
SUPEREMUM | 13 | 最大的行(虚拟的) |
USER RECORD | x | 实际的用户数据 |
FREE | y | 未使用的部分 |
PAGE_DIRECTORY | z | 方便页内快速查找数据的. (页内目录) |
FIL_TRAILER | 8 | FIL_TRAILER |
哪些位置可能有坏块呢? 都可能坏, 甚至全部都坏了... 坏得甚至认不出来是不是index page, 坏得连TM(parent node)都不认识.....
但并非有坏的就有影响, 比如free部分, 坏就坏了呗, 反正是未使用空间,也没得用户数据
怎么判断哪些部分损坏了呢? 判断不了, 我们只有整个page的校验值, 没有各模块的校验值, 这也是我们之前不解析坏块的原因, 比较都不知道哪坏了....
fil_header是每个page都有的, 也就是记录一些基础信息, 基本上影响不大,大不了我对于坏块全部强制解析呗. 格式和影响范围如下:
对象 | 大小(字节) | 描述 | 影响范围 |
---|---|---|---|
FIL_PAGE_SPACE_OR_CHECKSUM | 4 | 老版本(4.0)是space id,新版本是checksum, 我们就只把它当作checksum | 根据这个来校验是否有坏块的, 所以坏了只影响校验,不影响数据 |
FIL_PAGE_OFFSET | 4 | 这个PAGE在space的偏移量, 就是我们说的PAGE ID | 记录当前page属于space的哪个page, 如果是index page,则没有影响; 如果是blob相关的,则看数据文件是否完整, 若完整,则不影响(是通过f.seek定位pageid的), 若不完整(碎片页), 则有影响 |
FIL_PAGE_PREV/FIL_PAGE_SRV_VERSION | 4 | 上一页在哪? 对于index page(btr+),为了方便查找前后页,故存储了前后页的PAGEID. (如果是page0 则为mysql版本) | 不影响, 我们是一页页强制解析的. |
FIL_PAGE_NEXT/FIL_PAGE_SPACE_VERSION | 4 | 记录下一页的在这呢. (如果是page0 则为mysql版本, 实际上是1.) | 不影响 |
FIL_PAGE_LSN | 8 | LSN值 | 不影响 |
FIL_PAGE_TYPE | 2 | page的类型. (如果是压缩页, 这之后的信息就得压缩了) | 有一定影响, 毕竟都不知道这一页是哪种类型了. 如果是未知页, 则可以强制解析, 但如果变成了已知类型的页, 则可能出现未知错误, 毕竟我们只知道是否坏块,并不知道哪坏了 |
FIL_PAGE_FILE_FLUSH_LSN | 8 | 只有第1页才有的, 表示之前的LSN都落盘了, 实际上是0. | 不影响 |
FIL_PAGE_SPACE_ID (FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID) | 4 | 表空间id | 不影响, 通常我们使用indexid来区分是否是同一个btr+. |
page_header是FIL_PAGE_INDEX和FIL_PAGE_SDI才有的, 记录一些索引相关的信息, 比如indexid, 很多都是和查询有关的,影响不大. 结构和影响范围如下:
对象 | 大小 | 描述 | 影响范围 |
---|---|---|---|
PAGE_N_DIR_SLOTS | 2 | 记录PAGE_DIRECTORY的数量的 | 每行数据会记录下一行数据的未知, 所以只是PAGE_N_DIR_SLOTS坏了, 影响不大. |
PAGE_HEAP_TOP | 2 | pointer to record heap top, 就是最大的heap 可以简单理解为:这之后的空间未使用 | 不影响 |
PAGE_N_HEAP | 2 | 第15bit表示是否为new-style,剩余的表示(PAGE_N_HEAP&32767):本页记录的数据量(含INFIMUM和SUPEREMUM和被标记为delete的行) | 不影响, 我们全部解析 |
PAGE_FREE | 2 | 指向第一个被标记为delete的行, 没得的话就是0 | 不影响, 通常我们是要未删除的数据. 刚删除了数据,又发生了坏块,还没的备份和日志,这种是概率是比较小的. |
PAGE_GARBAGE | 2 | 有多少空间可以回收(就是PAGE_FREE有多少字节) | 不影响 |
PAGE_LAST_INSERT | 2 | 最后一次insert的位置, 如果是delete的话,就为0 (如果update更新再原来的位置不够,PAGE_HEAP_TOP后面也有足够空间的话, 也会更新这个值.) | 不影响 |
PAGE_DIRECTION | 2 | last insert direction (最后一条记录插入方向).PAGE_LEFT = 1;PAGE_RIGHT = 2;PAGE_SAME_REC = 3;PAGE_SAME_PAGE = 4;PAGE_NO_DIRECTION = 5 | 不影响 |
PAGE_N_DIRECTION | 2 | 同一个方向插入的数量, 方向变化后,就重置为0 (比如一直递增insert的话, 这个值大概率就是页内字段数量-1) | 不影响 |
PAGE_N_RECS | 2 | 页内的数据行数(不含INFIMUM和SUPEREMUM和被标记为delete的行) | 不影响 |
PAGE_MAX_TRX_ID | 8 | 最大事务ID(二级索引(叶子节点)和insert buffer才有的) | 不影响 |
PAGE_LEVEL | 2 | 当前page位于btr+的哪一层(0表示叶子节点, root page是最高层) | 影响不大, 毕竟rec_header也记录当前页是否为叶子节点. |
PAGE_INDEX_ID | 8 | 这页属于哪个索引. | 如果是碎片页,则影响. 否则不影响. |
PAGE_BTR_SEG_LEAF | 4+4+2 | 只有root page才有, 记录本索引对应的segment的spaceid,pageno,offset (leaf page信息) | 不影响 |
PAGE_BTR_SEG_TOP | 4+4+2 | 只有root page才有, 记录本索引对应的segment的spaceid,pageno,offset (root page信息) | 不影响 |
PAGE_DIRECTORY 方便页内快速查找数据的, 通常4-8行数据记录一下(使用2字节记录的是页内偏移量) PAGE_BTR_SEG_TOP和PAGE_BTR_SEG_LEAF通常相差192(一个segment大小), 8.0主键通常是434(38+12+1922(sdi的))和626(38+12+1922+192)
我们是根据INFIMUM来遍历页内数据行的, 如果INFIMUM坏了, 我们还可以根据PAGE_DIRECTORY来判断, 问题是我们并不知道究竟是哪坏了?
影响全部/部分页内数据. 就相当于某部分REC掉链子了. 我们还可以根据PAGE_DIRECTORY来辅助判断.
坏就坏了吧, 反正我也发现不了它.
如果user record正常, 则PAGE_DIRECTORY损坏没有影响. 否则会丢某部分数据.
对象 | 大小 | 描述 | 影响范围 |
---|---|---|---|
CHECKSUM | 4 | 校验值( | 影响校验 |
FIL_PAGE_LSN | 4 | LSN(低4字节, 即 | 不影响 |
我们都没法判断坏在哪了, 那么应该怎么恢复坏块中的数据呢?
我们要把坏块当作每个部分都坏了, 所以
初步打算这么设计, 但未作实际验证, 目前只是处于理论阶段. .
对于ibd2sql工具使用的设计, 我们要不影响原来的使用方法的前提下, 尽可能的方便使用者使用. 故
--log
和--output
,则坏块信息输出到stderr --log
,但没有--output
,则输出到stdout--output
,则输出文件以.warn
结尾--set bad-pages=force
为启用坏块的解析, 当启用时:自动添加--force,--set roono=0, --set leafno=0
选项先简单记录下相关原理,免得后面忘记了,万一实现不了的话, 就try吧-_-
代码未动,理论先行!
若各位大佬有更好的建议请随时沟通.
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。