手摇充电宝、太阳能转换器,这些“变态”的充电宝实用吗?
06-21
简介 当mysql出现坏块时,查询对应表时会报错,然后数据库崩溃。例如:即只有当我们查询有坏块的表时才会发现有坏块,而启动时则不会。
要检查坏块,我们如何知道数据库中哪些表有坏块呢?坏块如何处理? innochecksummysql提供了一个工具innochecksum来检查数据块。正常情况下,打印页面信息,如:code Language: shell copy (venv) 14:03:07 [root@ddcw21 mysql-8.0.37]#innochecksum /tmp/t.ibd -SFile::/tmp/t .ibd================页面类型摘要==============#PAGE_COUNTPAGE_TYPE============= ============= ====================== 1索引页 1SDI索引页 0撤消日志页 1Inode页 0插入缓冲区空闲列表页2新分配的页 1插入缓冲区位图 0系统页 0事务系统页 1文件空间标头 0范围描述符页 0BLOB页 0压缩 BLOB 页 0后续压缩 BLOB 页 0SDI BLOB 页 0压缩 SDI BLOB 页 0其他类型页============= ============= =====================附加信息:撤消页面类型:0插入,0更新,0其他撤消页面状态:0 active, 0 cached, 0 to_free, 0 to_purge, 0 prepared, 0 other(venv) 14:03:09 [root@ddcw21 mysql-8.0.37]#如果是坏块,则打印信息如下:代码语言:shell copy (venv) 14:03:56 [root@ddcw21 mysql-8.0.37]#innochecksum /tmp/test_badpage_.ibd -SFail: page 4 invalid超过了允许的最大校验和不匹配计数::0,这意味着你可以使用innochecksum来检查数据库是否有坏块,这个工具需要数据库停止运行。
也就是说,在检查之前必须停止数据库。否则会报如下错误:fcntl: 资源暂时不可用。
为了安全起见,就不管它了。那么这篇文章就结束了。
感谢您的观看!坏块验证原理有时候我们无法关闭数据库,但是如果我们要验证坏块,我们不能查询所有的表,如果有坏块,数据库就会挂掉。这没关系。
那么接下来就该深入研究一下innodbchecksum的源码了。我们先看一下验证原理,然后我们自己写一个脚本来验证一下。
我们仍然使用通用的gdb调试来做到这一点。代码语言:shell copy (echo -e "break main\nrun /data/ mysql_dev/data/db1/t.ibd -S -C crc32"; while true;do echo 'step';done) |gdb /root/mysql_source /mysql-8.0.37/bldx86/runtime_output_directory/innochecksum > /tmp/t_innochecksum .gdb.txt 2>&1 然后我们就得到了innochecksum的完整堆栈信息。
稍微整理一下,我们就可以得到调用过程:即crc32校验终于完成了。相关代码如下: 代码语言:c++ copy uint32_t buf_calc_page_crc32( const byte *page,bool use_legacy_big_endian /* = false */) { ut_crc32_func_t crc32_func = use_legacy_big_endian ? ut_crc32_legacy_big_endian : ut_crc32; const uint32_t c1 = crc32_func(页 + FIL_PAGE_OFFSET, FIL_PAGE_FILE_FLUSH_LSN - FIL_PAGE_OFFSET); const uint32_t c2 = crc32_func(页 + FIL_PAGE_DATA, UNIV_PAGE_SIZE - FIL_PAGE_DATA - FIL_PAGE_END_LSN_OLD_CHKSUM) ; return (c1 ^ c2);} 即对FIL_PAGE_HEADER^FIL_PAGE_DATA做crc的结果就是我们需要的crc32值。
FIL_PAGE_OFFSET之类的可以查看我之前写的文章:我们来画一张图。即只验证了部分头部和全部数据,甚至连PAGE_TYPE、SPACE_ID等都没有验证。
真有这么简单吗?我们来测试一下。对于crc32算法,我们还是参考之前解析校验表命令时使用的算法。
对比全部基于mysql。出色地。
(ibd的结构请查看:Studio代码运行 import struct,binasciifilename = '/tmp/t.ibd'f = open('/tmp/t.ibd','rb')data = f.read( 4 )checksum_field1 = struct.unpack('>L',data[:4])[0]checksum_field2 = struct.unpack('>L',data[-8:-4])[0]c1 = binascii.crc32 (数据[4:26])c2 = binascii.crc32(data[38:4-8])print(checksum_field1,checksum_field2,(c1^c2)&(2**32-1)) 哦,有什么区别吗?看CRC32C 和ut_crc32有关系,应该不是普通的crc32。否则,我们就直接调整zlib的crc32。
为什么要费力去写呢?当我们仔细查看storage/innobase/ut/crc32.cc的实现时,我们发现实际上是CRC32-C(循环冗余校验32位Castagnoli)。与普通的crc32相比,它使用了不同的生成多项式。
我找到了一篇相关的博文,里面解释得很详细,但是看起来比较费力:程序员必须让计算机理解指令,你必须编写简单的代码。从代码上看,基本上只是一个查表而已。
我们直接使用python重写代码语言: python代码运行次数: 0 复制Cloud Studio代码并运行 import structdef create_crc32c_table(): poly = 0x82f63b78 table = [] for i in range(): crc = i for _ in range (8): if crc & 1: crc = (crc >> 1) ^ poly else: crc >>= 1 table.append( crc) return tabledefcalculate_crc32c(data):crc = 0xFFFFFFFFfor byte in data:crc = crc32_slice_table[ (crc ^ byte) & 0xFF] ^ (crc >> 8)return crc ^ 0xFFFFFFFFcrc32_slice_table = create_crc32c_table() 虽然我们看不到代码,但是可以使用python重写。这就是蟒蛇的魅力。
我们再验证一下。测试让我们将其组织成脚本并进行测试。
首先,构造一个有坏块的文件。如果您有,则不需要此步骤。
代码语言:python 代码运行次数:0 复制Cloud Studio代码并运行 f1 = open ('/data/mysql_dev/data/db1/t.ibd','rb')f2 = open('/tmp/test_badpage_. ibd','wb')alldata = f1.read()baddata = alldata[:4 *4] + *b'ddcw' + alldata[4*4*4:]f2.write(baddata)f2.close() f1.close() 然后验证正常文件: 然后验证异常文件: bad 该区块确实验证通过了,也是我们故意破坏的位置。这意味着我们的验证工具没问题(太棒了!)。
综上所述,mysql ibd文件的坏块验证就是FIL_HEADER的crc32c值^FIL_DATA的crc32c值。然后将其与保存在文件开头/结尾的 crc32 值进行比较。
CRC32-C实际上有一个现成的库,可以使用pip install crc32c来安装。如果遇到坏块,可以使用ibd2sql工具来解析正常页面的数据。
用法我已经说过很多次了。我就不再介绍了。
参考:没有进行选项解析等。
版权声明:本文内容由互联网用户自发贡献,本站不拥有所有权,不承担相关法律责任。如果发现本站有涉嫌抄袭的内容,欢迎发送邮件 举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。
标签:
相关文章
06-17
06-18
06-17
06-06
06-06
06-18
06-06
最新文章
【玩转GPU】ControlNet初学者生存指南
【实战】获取小程序中用户的城市信息(附源码)
包雪雪简单介绍Vue.js:开学
Go进阶:使用Gin框架简单实现服务端渲染
线程池介绍及实际案例分享
JMeter 注释 18 - JMeter 常用配置组件介绍
基于Sentry的大数据权限解决方案
【云+社区年度征文集】GPE监控介绍及使用