>  기사  >  시스템 튜토리얼  >  IBD 파일을 사용한 MySQL 데이터 복구 팁?

IBD 파일을 사용한 MySQL 데이터 복구 팁?

PHPz
PHPz앞으로
2024-01-02 10:42:091380검색
소개 디스크 불량 섹터, 정전 및 기타 사고는 일반적이지 않지만 이러한 사고를 겪는 것만으로도 "스릴"이 생길 수 있습니다! 데이터베이스 손상으로 인해 데이터가 손실되어 Binlog를 더 이상 사용할 수 없는 경우 어떻게 해야 합니까? 단시간에 데이터를 무손실로 복원하여 비즈니스 안정성을 확보하기 위해 binlog를 활용하는 것 외에도 새로운 복구 기술도 연습했습니다!

전에 우리가 쓴 "통제 불가능한 R&D가 당신을 사랑하게 만드는 단 하나의 비법"을 기억하시나요? 앞서 언급했듯이 우리가 매일 가장 많이 사용하는 두 가지 데이터베이스 복구 방법은 다음과 같습니다.

IBD 파일을 사용한 MySQL 데이터 복구 팁?

위 두 가지 방법 모두 실시간 롤백이 가능하지만, 이 두 가지 기술만 있으면 충분하다고 생각하시나요?

안돼….!

이 복잡한 온라인 아키텍처에는 실제로 우리가 예측할 수 없는 알 수 없는 많은 이유가 있습니다. 예:

열심히 작업하여 수명을 잃은 디스크는 배드섹터가 발생하여 데이터베이스가 손상될 수 있습니다. 그리고 ibdata 파일과 binlog 파일이 손상되는 일이 일어났습니다. 그렇다면 아직도 예약 백업 + binlog 복구 솔루션을 생각한다면 고정 소수점 백업만 사용하여 복원할 수는 없나요? 운영 및 유지 관리 담당자로서 신중하게 고려한 후에는 비즈니스에 큰 영향을 미치기 때문에 최후의 수단으로 손실 롤백을 구현하지 않을 것입니다. 하지만 또 무엇을 할 수 있습니까? 다음으로 우리는 큰 움직임을 공개할 예정입니다! ! !

먼저 데이터베이스 환경을 확인하여 독립 테이블스페이스가 활성화되어 있는지 확인하세요. 활성화된 경우 축하합니다. 모든 데이터를 복구할 수 있는 가능성이 높습니다. 데이터 복구를 위해 각 데이터베이스 디렉토리의 frm 및 ibd 파일을 사용할 수 있습니다. 일반적으로 InnoDB를 사용하지만 독립 테이블 공간이 활성화되지 않은 경우 모든 데이터베이스 테이블 정보와 메타데이터가 ibdata 파일에 기록됩니다. 오랫동안 실행하면 ibdata 파일이 점점 커지고 데이터베이스 성능이 저하됩니다. InnoDB는 데이터를 독립적으로 저장할 수 있는 독립 테이블스페이스를 활성화하는 매개 변수를 제공합니다. 이러한 방식으로 ibdata 파일은 일부 엔진 관련 인덱스 정보를 저장하는 데만 사용되며 실제 데이터는 독립된 frm 및 ibd 파일에 기록됩니다.

좋아요, frm 및 ibd 파일을 사용하여 데이터 복구를 시도해 볼 수 있습니다. 이 과정은 binlog 복원보다 더 스릴 있고 흥미로워요! 먼저 ibd 및 frm에 대한 지침을 살펴보겠습니다.

.frm 파일: 테이블 구조 정의 등 각 테이블의 메타데이터를 저장합니다. 이 파일은 데이터베이스 엔진과 아무런 관련이 없습니다.

.ibd 파일: 테이블의 데이터와 인덱스를 저장하기 위해 독립 테이블스페이스가 활성화될 때(innodb_file_per_table = 1 in my.ini) InnoDB 엔진에서 생성되는 파일입니다.

InnoDB 데이터베이스의 경우 전체 데이터 디렉터리를 복사하지 않고 지정된 데이터베이스 디렉터리만 새 인스턴스에 복사하면 데이터베이스가 인식되지 않는다는 것은 모두가 알고 있는 사실입니다. 그렇다면 이 두 파일을 기반으로 데이터베이스를 복원하는 방법은 무엇입니까?

복구 아이디어:

엔진에 대한 일부 인덱스 정보가 ibdata 파일에 저장되어 있기 때문에 ibdata 파일이 손상되어 테이블 이름 인덱스가 손실되어 시작할 수 없게 됩니다. 그런 다음 먼저 전체 이전 데이터 디렉터리의 이름을 바꾸고 백업한 다음 데이터베이스를 다시 초기화하여 새 ibdata 파일을 생성한 다음 원본 데이터베이스와 해당 테이블을 다시 생성하고 마지막으로 백업 테이블스페이스 ID 번호를 다음으로 변경할 수 있습니다. 새 테이블스페이스 ID 번호(ibdata 파일에는 생성된 새 테이블 수만큼 증가되는 각 테이블에 대한 고유한 테이블스페이스 인덱스 ID가 포함되어 있음)를 사용하여 원래 데이터베이스를 복원할 수 있습니다.
예:
라이브러리 이름: test_restore
테이블 구조: db_struc.sql
테이블 파일: G_RESTORE.ibd, G_RESTORE.frm

1. 새 라이브러리를 만들고 테이블 구조를 가져옵니다

#mysql -uroot –p**** -e “데이터베이스 test_restore 생성”

#mysql -uroot –p**** test_restore 2. 새 인스턴스의 test_restore 라이브러리에 있는 테이블 ID를 보고 수정합니다 으아아아

깨진 문자로 직접 열어서 16진수로 변환하여 볼 수 있습니다. Vi에서 :%!xxd를 실행하여 16진수로 변환합니다. 결과는 :

IBD 파일을 사용한 MySQL 데이터 복구 팁?

사진과 같습니다. mysql 데이터베이스의 G_RESTORE 테이블 ID는 00fe입니다.

백업된 G_RESTORE.ibd 파일을 수정하세요. 조작은 위와 동일하지만, 먼저 백업을 해야 한다는 점에 유의하세요.

으아아아

IBD 파일을 사용한 MySQL 데이터 복구 팁?

011b를 00fe로 변경하세요. 알아채다. 수정이 완료되면 먼저 vim에서 실행해야 합니다: %!xxd -r

Wq를 다시 눌러 파일을 저장하고 종료하세요. 그렇지 않으면 저장된 결과는 16진수 보기입니다.

다음과 같이 결과를 저장하세요.

IBD 파일을 사용한 MySQL 데이터 복구 팁?

수정된 G_RESTORE.ibd 파일을 새 데이터베이스의 G_RESTORE.ibd 파일로 바꾸세요.

ibdata 테이블 ID에 대한 설명:

IBD 파일을 사용한 MySQL 데이터 복구 팁?

参考官方文档解释,每个表空间分配了4个字节存储了表空间id信息,最后偏移量地址为38。还有一组预留的表空间id,同样是4个字节,最后偏移量地址为42。

3. 验证并还原mysql数据

关闭mysql。修改my.conf。
innodb_force_recovery=6 innodb_purge_threads=0

启动数据库。如果不修改。数据库会认为G_RESTORE已被损坏。

Select 一下,即可查看到还原结果,但此时插入数据会报错,应尽快将数据dump出来 ,导回原来的实例中。

导出数据,再导入数据,恢复完毕!

#mysqldump -uroot –p****** test_restore > test_restore.sql

#mysql -uroot –p****** test_restore 
<p>说明:变更了新的space id后的.ibd表文件,启动数据库后只能认出数据,但不能写入,这是因为原ibdata文件不仅保存了space id索引,还同时保存了一些其它的元数据。为了使元数据补全,所以采取导出、再导入的操作。</p>
<p>以上举例为单个库表的恢复过程,看到这里大家一定会产生另一个疑问吧?线上的场景不可能是只有一个表的,数据库表很多的情况下,这样一个个表的修改,速度无疑是太慢了。那么存在大量表的情况下如何恢复呢?思路是,取得备份的ibd文件的id值,按id值顺序来建表,中间跨度随便建表语句来凑够数(每个表空间索引id由创建新表的数量依次递增)。实现方式如下:</p>
<p><span style="color: #339966;"><strong>1. 获取备份数据库ibd文件的space id号,并排序。</strong></span></p>
<pre class="brush:php;toolbar:false">for ibd in `find test_restore/ -name “*.ibd”` ; do  echo -e “${ibd///// }   /c” ;hexdump -C ${ibd} |head -n 3 |tail -n 1|awk ‘{print  strtonum(“0x”$6$7)}’ ;done | sort -n  -k 3 | column -t > /tmp/

生成的ibd.txt文件,格式如下:(库名–表名–SpaceId)

IBD 파일을 사용한 MySQL 데이터 복구 팁?
2. 新建表,查看当前表空间id(假设space id为10)

#mysql -uroot –p****** -e”create table test.tt(a bool)”

#hexdump -C mysql/test/tt.ibd |head -n 3 |tail -n 1|awk ‘{print  strtonum(“0x”$6$7)}’

3. 先创建所有库,准备所有表结构,写脚本,依据space id号自动创建新表

准备好数据库表结构,可以从备份文件里取出来(我们备份方式是把结构和数据分开备份的),或者从其他有相同表结构的服务器上备份再拷贝过来。

参考备份语句:

mysqldump -uroot –p****** -d ${db} –T /data/backup/${db}/

创建原有的数据库:

mysql -uroot –p****** -e “create database ${db}”

恢复表id创建表脚本:

#!/bin/bash
#因为前面假设为10,所以从11开始创建
oid=11

#打开前面生成的ibd.txt文件,按行读取”库名–表名–SpaceId”
cat /tmp/ibd.txt | while read db tb id ;do

#假如我们需要恢复catetory表,他的id为415,基于id是创表自增的原则,即415-11=404,
#我们还需要循环创建404个表后,才真正导入catetory表结构。
for ((oid;oid<id do mysql table test.t bool echo ok done let oid="oid+1">
<p><span style="color: #339966;"><strong>4. 检查表空间id 和备份的是否一致</strong></span></p>
<pre class="brush:php;toolbar:false">for ibd in `find test_restore/ -name “*.ibd”` ; do  echo -e “${ibd///// }   /c” ;hexdump -C ${ibd} |head -n 3 |tail -n 1|awk ‘{print  strtonum(“0x”$6$7)}’ ;done | sort -n  -k 3 | column -t > /tmp/ibd2.txt

确认一致后,拷贝备份的.ibd文件到新数据库实例目录下,修改my.cnf

innodb_force_recovery=6

innodb_purge_threads=0

启动数据库。后续步骤如同单表恢复,直接导出恢复到原来实例中即可。

当然,这种方式是在数据库出现极端情况下,不得不采取的一种方式,线上最重要的还是做好主从同步和定时备份,从而规避此类风险。

关于InnoDB引擎独立表空间说明:

使用过MySQL的同学,刚开始接触最多的莫过于MyISAM表引擎了,这种引擎的数据库会分别创建三个文件:表结构、表索引、表数据空间。我们可以将某个数据库目录直接迁移到其他数据库也可以正常工作。然而当你使用InnoDB的时候,一切都变了。

InnoDB默认会将所有的数据库InnoDB引擎的表数据存储在一个共享空间中:ibdata1,这样就感觉不爽,增删数据库的时候,ibdata1文件不会自动收缩,单个数据库的备份也将成为问题。通常只能将数据使用mysqldump导出,然后再导入解决这个问题。

但是可以通过修改MySQL配置文件[mysqld]部分中innodb_file_per_table的参数来开启独立表空间模式,每个数据库的每个表都会生成一个数据空间。

优点:

1.每个表都有自已独立的表空间。

2.每个表的数据和索引都会存在自已的表空间中。

3.可以实现单表在不同的数据库中移动。

4.空间可以回收(除drop table操作处,表空不能自已回收)

a) Drop table操作自动回收表空间,如果对于统计分析或是日值表,删除大量数据后可以通过:alter table TableName engine=innodb;回缩不用的空间。

b) 对于使innodb-plugin的Innodb使用turncate table也会使空间收缩。

c) 对于使用独立表空间的表,不管怎么删除,表空间的碎片不会太严重的影响性能,而且还有机会处理。

단점:

싱글 테이블이 100G가 넘는 등 너무 큽니다.

결론:

공유 테이블 공간은 삽입 작업에서 장점이 거의 없습니다. 다른 테이블스페이스는 독립 테이블스페이스만큼 성능이 좋지 않습니다. 독립 테이블스페이스를 활성화하는 경우 적절하게 조정하십시오: innodb_open_files.

구성 방법:
1.innodb_file_per_table 설정 방법:

my.cnf

의 [mysqld] 아래에 설정하세요.

innodb_file_per_table=1
2. 활성화되어 있는지 확인하세요:
mysql> '%per_table%'와 같은 변수 표시;

3. 전용 테이블 공간을 닫습니다
innodb_file_per_table=0은 독립 테이블 공간을 끕니다

mysql> '%per_table%'와 같은 변수 표시;

위 내용은 IBD 파일을 사용한 MySQL 데이터 복구 팁?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 linuxprobe.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제