分类目录归档:MySQL

arm环境vg损坏mysql数据库恢复

国庆节期间接到朋友咨询,原先在vg中的磁盘被重新pvcreate了,想恢复原磁盘中的mysql数据库
pvcreate


通过分析系统的history日志,发现操作不是简单的pvcreate,我简单梳理下操作步骤
故障之前磁盘情况

[root@0002 ~]# lsblk
NAME                  MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sr0                    11:0    1 1024M  0 rom  
vda                   253:0    0  200G  0 disk 
├─vda1                253:1    0  600M  0 part /boot/efi
├─vda2                253:2    0    1G  0 part /boot
└─vda3                253:3    0 38.4G  0 part 
  ├─klas-root         252:0    0 34.4G  0 lvm  /
  └─klas-swap         252:1    0    4G  0 lvm  [SWAP]
vdb                   253:16   0 1000G  0 disk 
└─vdb1                253:17   0  500G  0 part 
  └─mysql-mysql--mycg 252:2    0  500G  0 lvm  /mysql

这里可以看到出来vdb磁盘一共1000G,分区vdb1 为500G,然后这500G加入到vg中并分配了lv.

vdb磁盘现状

[root@0002 mysql]# lsblk /dev/vdb
NAME                  MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
vdb                   253:16   0 1000G  0 disk 
└─vdb1                253:17   0 1000G  0 part 

Disk /dev/vdb: 1000 GiB, 1073741824000 bytes, 2097152000 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x5a6aaeee

Device     Boot Start        End    Sectors  Size Id Type
/dev/vdb1        2048 2097151999 2097149952 1000G 8e Linux LVM

这里基本上可以确定,vdb1磁盘分区从以前的500G变成了1000G(也就是说被重新分区了,后续和现场沟通确认进行了重新分区操作)


通过history日志追述大概的操作过程

  898  [2025-09-28 11:55:13][root]fdisk -l
  899  [2025-09-28 11:55:21][root]df -h
  900  [2025-09-28 11:56:41][root]lsblk
  901  [2025-09-28 11:59:44][root]fdisk /dev/vdb
  902  [2025-09-28 12:00:46][root]partprobe /dev/vdb
  903  [2025-09-28 12:00:50][root]pvresize /dev/vdb1
  904  [2025-09-28 12:00:56][root]df -h
  905  [2025-09-28 12:01:25][root]vgdisplay mysql
  906  [2025-09-28 12:01:40][root]lsblk
  907  [2025-09-28 12:02:05][root]sudo partprobe /dev/vdb
  908  [2025-09-28 12:02:10][root]pvresize /dev/vdb1
  909  [2025-09-28 12:02:27][root]sudo pvresize /dev/vdb1
  910  [2025-09-28 12:03:07][root]sudo pvcreate /dev/vdb1
  911  [2025-09-28 12:03:22][root]sudo pvscan
  912  [2025-09-28 12:03:30][root]sudo pvdisplay
  913  [2025-09-28 12:05:37][root]parted /dev/vdb
  914  [2025-09-28 12:06:11][root]pvresize /dev/vdb1
  915  [2025-09-28 12:06:15][root]lsblk
  916  [2025-09-28 12:09:48][root]lvextend -l +100%FREE /dev/mysql/mysql--mycg
  917  [2025-09-28 12:10:00][root]cd /dev/mysql/
  918  [2025-09-28 12:10:01][root]ll
  919  [2025-09-28 12:10:20][root]pwd
  920  [2025-09-28 12:10:32][root]lvextend -l +100%FREE /dev/mysql/mysql-mycg
  921  [2025-09-28 12:10:55][root]lsblk /dev/vdb

基本上可以确定9月28日先进行了fdisk分区操作,然后尝试pvresize 操作[应该不会成功,因为重新分区导致pv信息丢失],然后进行了pvcreate之后再次进行parted分区操作,再pvresize,lvextend操作[同理pv信息丢失应该不会成功],然后10月5日继续进行的部分操作

  956  [2025-10-05 08:29:27][root]umount /mysql
  957  [2025-10-05 08:29:38][root]lsof /mysql
  958  [2025-10-05 08:29:58][root]service mysqld stop
  959  [2025-10-05 08:30:02][root]umount /mysql
  960  [2025-10-05 08:30:05][root]lsof /mysql
  961  [2025-10-05 08:30:23][root]cd /
  962  [2025-10-05 08:30:25][root]umount /mysql
  963  [2025-10-05 08:30:34][root]pvcreate --force /dev/vdb1
  964  [2025-10-05 08:30:47][root]vgextend mysql /dev/vdb1
  965  [2025-10-05 08:31:02][root]df -h
  966  [2025-10-05 08:31:33][root]pvdisplay /dev/vdb1
  967  [2025-10-05 08:31:41][root]pvcreate --force /dev/vdb1
  968  [2025-10-05 08:32:11][root]lvs | grep mysql-mysql--mycg
  969  [2025-10-05 08:32:19][root]dmsetup ls | grep mysql
  970  [2025-10-05 08:32:38][root]fuser /dev/vdb1
  971  [2025-10-05 08:32:41][root]lsof /dev/vdb1
  972  [2025-10-05 08:32:50][root]pvcreate --force /dev/vdb1
  973  [2025-10-05 08:33:14][root]reboot
  974  [2025-10-05 08:36:23][root]pvcreate --force /dev/vdb1
  975  [2025-10-05 08:36:47][root]lvdisplay /dev/mapper/mysql-mysql--mycg
  976  [2025-10-05 08:36:53][root]vgextend mysql /dev/vdb1
  977  [2025-10-05 08:37:10][root]lvextend -l +100%FREE /dev/mysql/mysql--mycg

初步看,应该是先尝试umount /dev/vdb1,但是没有成功,然后直接reboot重启了主机,起来之后,进行了pvcreate[操作成功],vgextend,lvextend等操作[失败,因为vg里面的之前的pv信息已经丢失],而且之前lv无法mount成功,数据库文件/备份均在这个lv里面,而且从库很久之前没有正常同步.基于这样的情况,就一定要对vdb磁盘中数据进行恢复.查看操作系统信息,确认是arm系统
arm


由于arm系统一般工具均无法正常解析,只能让客户把磁盘挂载到x86环境进行处理,通过专业恢复工具解析,运气不错可以直接读取数据
m1

传输数据到客户服务器中,并成功启动mysql,客户测试业务没有任何问题,数据完整恢复
2

发表在 Linux, MySQL恢复 | 标签为 , | 评论关闭

docker回收和mysql备份导入导致数据丢失恢复

最近遇到两例MySQL异常被删除的案例,一例是在docker环境中,由于对docker执行了删除操作,并回收了相关的挂载卷,导致数据彻底丢失
docker


另外一个客户使用备份导入生产库,导致生产库的数据全部被重置为了当时备份的状态,这是由于mysqldump导出数据的时候,默认带有DROP TABLE IF EXISTS `xifenfei`;语句,因此导入备份的时候会先删除掉存在的表,然后创建新表,再insert插入数据.
mysql

上述的这两个case,故障发生之后,都没有第一时间保护现场,反而对数据所在分区进行了不少的写入操作,导致覆盖概率相对增加很多.对于这样的故障,一般处理思路:
1. 停掉对该分区写入的业务,如果可以尽可能umount分区,然后做快照或者进项
2. 使用反删除软件对镜像的或者快照的分区进行分析,尝试恢复出来没有被覆盖的MySQL数据,主要是ibd和frm等文件
3. 使用碎片工具对镜像的或者快照的分区进行扫描,根据数据类型生产index和blob的page文件
scan-root

4. 对于2中恢复的ibd,frm文件,可以尝试通过DISCARD TABLESPACE/IMPORT TABLESPACE方式进行恢复,如果不行对ibd文件进行解析恢复,参考:又一起mysql rm删除数据库目录事故
5. 对于3中恢复出来的page文件,利用工具结合表结构对其进行解析,恢复数据
通过上述恢复,基本上是对于MySQL数据的drop table/truncate table/drop database/rm -rf/格式化等相关误操作的终极恢复思路,对于类似MySQL故障,我们可以实现比较好的恢复效果,如果需要专业恢复技术支持请联系我们:
电话/微信:17813235971    Q Q:107644445QQ咨询惜分飞    E-Mail:dba@xifenfei.com

发表在 MySQL恢复 | 标签为 , , , , , , | 评论关闭

文件系统格式化MySQL数据库恢复

有客户在做迁移的时候,不慎把存放mysql数据库的硬盘进行了重新分区格式化,重新初始化mysql,并且导入了部分历史数据,不能满足客户需求,希望我们帮忙进行数据恢复.里面大概有100套左右mysql数据库,每个库里面表结构相同,数据不一样.接手这个故障,第一操作就是对磁盘进行镜像,然后使用恢复工具进行底层分析,尝试从文件系统层面恢复出来被格式化之前的数据库文件(需要有对应库目录,不然也没有意义,因为每个库里面表结构一样的,没有正确的库名字无法做到有效的区分),通过底层扫描分析,没有发现一个有效数据文件
QQ20250618-232447


对于这样的情况,只能寄希望于mysql 数据块层面扫描恢复,通过工具扫描发现大量的数据块page文件
block-page

然后尝试分析字典信息,主要是对于0000000000000001.page对应的表创建语句为:

CREATE TABLE `SYS_TABLES` (
  `NAME` varchar(255) NOT NULL DEFAULT '',
  `ID` bigint(20) unsigned NOT NULL DEFAULT '0',
  `N_COLS` int(10) DEFAULT NULL,
  `TYPE` int(10) unsigned DEFAULT NULL,
  `MIX_ID` bigint(20) unsigned DEFAULT NULL,
  `MIX_LEN` int(10) unsigned DEFAULT NULL,
  `CLUSTER_NAME` varchar(255) DEFAULT NULL,
  `SPACE` int(10) unsigned DEFAULT NULL,
  PRIMARY KEY (`NAME`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

通过上述信息可以获取到name和id列的值(其中name中包含库名/表名),然后再通过0000000000000003.page文件结合对应的表创建语句:

CREATE TABLE `SYS_INDEXES` (
  `TABLE_ID` bigint(20) unsigned NOT NULL DEFAULT '0',
  `ID` bigint(20) unsigned NOT NULL DEFAULT '0',
  `NAME` varchar(120) DEFAULT NULL,
  `N_FIELDS` int(10) unsigned DEFAULT NULL,
  `TYPE` int(10) unsigned DEFAULT NULL,
  `SPACE` int(10) unsigned DEFAULT NULL,
  `PAGE_NO` int(10) unsigned DEFAULT NULL,
  PRIMARY KEY (`TABLE_ID`,`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

这个主要是或者表id和page id的对应关系(表id直接关联SYS_TABLES.ID,然后获取SYS_TABLES.NAME和SYS_INDEXES.ID对应关系,从而可以确定每一个表对应的需要恢复的page文件信息,再通过客户提供的表语句和对应的page关系,实现相关数据恢复,具体操作可以参考以往类似文章:
xfs文件系统mysql删库恢复
又一起mysql rm删除数据库目录事故
[MySQL异常恢复]恢复数据字典表讲解
[MySQL异常恢复]mysql drop table 数据恢复
mysql ibd文件反删除恢复之后异常处理
[MySQL异常恢复]使用工具直接抽取MySQL数据字典
MySQL drop database恢复(恢复方法同样适用MySQL drop table,delete,truncate table)

发表在 MySQL恢复 | 标签为 , | 评论关闭