数据库损坏指南(1)--概述
2023-01-20 09:31 abce 阅读(140) 评论(0) 编辑 收藏 举报一、概念与类比
对于数据库,它是关于存储在磁盘上的数据的格式。当数据库产品(如PostgreSQL、MySQL或MongoDB)对磁盘进行写操作时,会使用某种格式来执行。当从磁盘读取数据时,数据库产品期望磁盘上数据的格式相同;磁盘上的任何部分数据格式不合适就是损坏。
总的来说,损坏只是一种不恰当的格式或数据序列。
损坏是不可读的数据格式的结果。我们知道,数据是以位(bit)的形式存储在磁盘上的。现在,在整数或数字的情况下,转换很简单。但是对于字符,每台机器都被设计成以字节(byte)的形式转换数据,字节是一组8位,每个字节都代表一个字符。从00000000(0)到11111111(255),每个字节有256种不同的组合。
为了以字符的形式读取字节,设计了一些格式,如ASCII、EBCDIC、BCD等。它们也被称为编码方案。在所有这些方案中,ASCII(美国信息交换标准代码)更受欢迎。在这种格式中,每个字节(所有256个组合)都被分配一个特定的字符。
就像,
01000001(65) - a 00101100(44) - ,
下面是查看所有ASCII码的链接。
https://www.rapidtables.com/code/text/ascii-table.html
在这里,如果任何字节存储了一个意外的位序列,机器将读取一个不同的字符。
例如,
假设字符A(65)存储为11000001(193)而不是01000001(65),即"Á"(不是英文字母A)。
现在,在这些提到的编码方案中,有些字符是人类可读的,而其余的则不是。但是,另一点需要注意的是,并不是所有的软件产品都是为了破译所有的字符而设计的。因此,在任何情况下,如果任何位置的字节被更改,则数据库可能无法读取字符,从而无法读取数据。那些不可读或不可解析的数据被认为是损坏的数据。
例如,
How are you?被存储为How are you¿,字符"¿"在英语中是不可用的,因此那些只能解析英语的字符集可能无法识别该字符。因此,它将无法读取该文本,并通过将其标记为不可读而抛出错误。在这里,只有一个字符无法识别,但整个文本将被标记为损坏的数据。
二、产生的原因
这点很神奇,因为我们可能永远都不知道任何损坏的真正原因。正如我上面提到的,损坏归因于比特/字节的变化,但是很难确定是哪个进程/线程导致了这种变化。这就是为什么任何与损坏相关的测试用例实际上都是不可复制的。我们唯一能做的就是找出可能的原因。
一些可能的原因如下:
·硬件问题
当RAID盘设计不合理或控制器故障时,可能会导致硬盘无法正常写入数据。在非raid硬盘中,机械设备也应该正常工作,因为硬盘故障也会导致比特无法正常存储。
严重的I/o也可能导致损坏。
·操作系统的Bug
有时,由于内核或代码有问题,操作系统会错误地对数据进行编码,然后将其写入磁盘。有时,I/o的效率很低时,操作系统会产生损坏的数据。
·数据库产品中的Bug
在有些情况下,数据库产品本身有时会在磁盘上存储错误的数据,或者由于低效的算法,它以错误的格式保存数据。
三、损坏的种类
每个数据库都包含不同类型的文件,例如数据文件、WAL文件、提交日志等等。这些文件包含各种数据库对象的数据,如表、索引、物化视图、WAL记录等。当这些数据库文件损坏时,一些查询会检索错误的数据或返回错误,
或者一些操作(例如恢复,重放)可能无法正常工作。作为一名DBA,需要确定哪些特定的对象会因为这种损坏而受到影响。为便于理解,将损坏分为不同类型;其中一些如下所示:
·数据损坏:
当data/toast页面存储错误的数据(就格式而言)时,在读取时可能会变得无法识别。因此,数据库会报错。
·WAL损坏:
WAL/Redo/Transaction日志文件以特定的格式存储数据,当读取它们时,WAL条目被解析和应用。在WAL损坏的情况下,WAL条目是不可解析的,这会影响WAL应答操作。
·页头损坏:
数据库中最底层的存储单位是块/页,它实际存储实际记录。为了保持数据完整性,一些信息存储在称为页头的单独部分中。页头中的任何不当信息都是页头损坏。这会影响数据的完整性。
四、总结
在磁盘上存储数据时,比特/字节的变化会导致损坏。当一个数据库产品(例如MySQL, PostgreSQL)没有得到预期格式的数据时,就是发生数据损坏。
数据库中的数据可能由于各种原因而损坏,例如硬件故障和有bug的OS/内核/数据库产品。