Databases / Linux Note / 运维笔记

LVM 浅析

Einic Yeo · 7月10日 · 2019年 · · · ·

一. 概念

LVM是 LogicalVolumeManager(逻辑卷管理)的简写,它由Heinz Mauelshagen在Linux2.4内核上实现。LVM将一个或多个硬盘的分区在逻辑上集合,相当于一个大硬盘来使用,当硬盘的空间不够使用的时候,可以继续将其它的硬盘的分区加入其 中,这样可以实现磁盘空间的动态管理,相对于普通的磁盘分区有很大的灵活性。

二. 优点

  • 使系统管理员可以更方便的为应用与用户分配存储空间。
  • 在LVM管理下的存储卷可以按需要随时改变大小与移除。
  • 允许按用户组对存储卷进行管理,可用更直观的名称如development代替物理磁盘名如sda来标识存储卷。

三. LVM基本术语

  • 物理存储:物理存储介质指系统的存储设备:硬盘,如:hda1等等,是存储系统最低层的存储单元。
  • 物理卷(pv):指硬盘分区或从逻辑上与磁盘分区具有同样功能的设备(如RAID),是LVM的基本存储逻辑块,包含了物理介质没有的LVM相关管理参数。
  • 卷组(vg):指由版权声明:本文遵循 CC 4.0 BY-SA 版权协议,若要转载请务必附上原文出处链接及本声明,谢谢合作!一个或多个物理卷组成的逻辑上的版权声明:本文遵循 CC 4.0 BY-SA 版权协议,若要转载请务必附上原文出处链接及本声明,谢谢合作!”物理硬盘”,可以在卷组上创建一个或多个“LVM分区”(逻辑卷)。
  • 逻辑卷(lv):逻辑卷类似于非LVM系统中的硬盘分区,在逻辑卷之上可以建立文件系统(比如/home或者/usr等)。
  • PE(physical extent):PE指每一个物理卷所划分的基本单元,默认大小为4M,具有唯一编号,是可以被LVM寻址的最小单元。
  • LE(physical extent):LE指每一个逻辑卷所划分的基本单元,大小与PE相同。

四. LVM基本使用

1.创建分区

使用分区工具(如fdisk等)创建LVM分区,却将分区标识为LVM的分区类型8e。

[root@localhost ~]# fdisk -l
……
Device Boot      Start         End      Blocks   Id  System
/dev/sdb1            2048    20971519    10484736    5  Extended
/dev/sdb5            4096     2101247     1048576   8e  Linux LVM
/dev/sdb6         2103296     4200447     1048576   8e  Linux LVM

2.创建PV

[root@localhost ~]# pvcreate /dev/sdb5          #将每个分区转换成PV
  Physical volume "/dev/sdb5" successfully created
[root@localhost ~]# pvcreate /dev/sdb6
  Physical volume "/dev/sdb6" successfully created

查看验证

[root@localhost ~]# pvdisplay
  ……

3.创建VG

[root@localhost ~]# vgcreate -s 16m vg01 /dev/sdb5 /dev/sdb6 /dev/sdb7
#创建名称为vg01的VG组,且PE修改为16m
 Volume group "vg01" successfully created

查看验证

注意:LVM 默认使用 4MB 的 PE 区块,即可默认的 LVM VG 会有 4M*65534/(1024M/G)=256G

4.创建LV

[root@localhost ~]# lvcreate -L 1g -n lv01 vg01
  Logical volume "lv01" created.

查看验证

[root@localhost ~]# lvdisplay

5.格式化

[root@localhost ~]# mkfs.xfs /dev/vg01/lv01             #格式化为相应的格式
meta-data=/dev/vg01/lv01         isize=256    agcount=4, agsize=65536 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=0        finobt=0
data     =                       bsize=4096   blocks=262144, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=0
log      =internal log           bsize=4096   blocks=2560, version=2
          =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0

6.挂载

[root@localhost ~]# mkdir /root/mylv01              #创建用于挂载的目录
[root@localhost ~]# mount /dev/vg01/lv01 /root/mylv01/      #挂载至相应目录
[root@localhost ~]# df -h                   #查看验证
Filesystem             Size  Used Avail Use% Mounted on
……
/dev/mapper/vg01-lv01 1014M   33M  982M   4% /root/mylv01

开机挂载

[root@localhost ~]# vi /etc/fstab
/dev/vg01/lv01  /root/mylv01    xfs defaults    0 0 #修改为开机挂载

7.创建LVM分区

首先,挂载虚拟硬盘到虚拟机上,这里挂了2个1T的硬盘。

$ lsblk
NAME            MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda               8:0    0  100G  0 disk 
├─sda1            8:1    0    1G  0 part /boot
└─sda2            8:2    0   99G  0 part 
  ├─centos-root 253:0    0   50G  0 lvm  /
  ├─centos-swap 253:1    0  9.8G  0 lvm  [SWAP]
  └─centos-home 253:2    0 39.2G  0 lvm  /home
sdb               8:16   0    1T  0 disk 
sdc               8:32   0    1T  0 disk 
sr0              11:0    1 1024M  0 rom  

// 创建物理卷
$ sudo pvcreate /dev/sdb
  Physical volume "/dev/sdb" successfully created.

// 创建卷组
$ sudo vgcreate VG1 /dev/sdb
  Volume group "VG1" successfully created

// 查看卷组剩多少PE
$ sudo vgdisplay
  ...
  --- Volume group ---
  VG Name               VG1
  System ID             
  Format                lvm2
  Metadata Areas        2
  Metadata Sequence No  7
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                1
  Open LV               0
  Max PV                0
  Cur PV                2
  Act PV                2
  VG Size               <2.00 TiB
  PE Size               4.00 MiB
  Total PE              524286
  Alloc PE / Size       262143 / <1024.00 GiB
  Free  PE / Size       262143 / <1024.00 GiB     //剩余空间大小
  VG UUID               DYPyVN-9ssj-pLxN-bksi-9U0V-m2wQ-aQ3IPe
  ...

// 将所有剩余空间创建为逻辑卷
$ sudo lvcreate -l 262143 -n MyLvm0 VG1
  Logical volume "MyLvm0" created.

// 创建完成
$ lsblk
NAME            MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda               8:0    0  100G  0 disk 
├─sda1            8:1    0    1G  0 part /boot
└─sda2            8:2    0   99G  0 part 
  ├─centos-root 253:0    0   50G  0 lvm  /
  ├─centos-swap 253:1    0  9.8G  0 lvm  [SWAP]
  └─centos-home 253:2    0 39.2G  0 lvm  /home
sdb               8:16   0    1T  0 disk 
└─VG1-MyLvm0    253:3    0 1024G  0 lvm        // 所创建的LVM逻辑卷
sdc               8:32   0    1T  0 disk 
sr0              11:0    1 1024M  0 rom

8.扩展LVM分区

上面使用了一块1T虚拟硬盘,下面将另外一块虚拟硬盘添加到刚才的逻辑卷中,实现扩展。

$ lsblk
NAME            MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda               8:0    0  100G  0 disk 
├─sda1            8:1    0    1G  0 part /boot
└─sda2            8:2    0   99G  0 part 
  ├─centos-root 253:0    0   50G  0 lvm  /
  ├─centos-swap 253:1    0  9.8G  0 lvm  [SWAP]
  └─centos-home 253:2    0 39.2G  0 lvm  /home
sdb               8:16   0    1T  0 disk 
└─VG1-MyLvm0    253:3    0 1024G  0 lvm        // 需要扩展的LVM逻辑卷
sdc               8:32   0    1T  0 disk       // 额外的空间
sr0              11:0    1 1024M  0 rom  

// 创建物理卷
$ sudo pvcreate /dev/sdc
  Physical volume "/dev/sdc" successfully created.

// 将它加入到卷组
$ sudo vgextend VG1 /dev/sdc
  Volume group "VG1" successfully extended

// 扩展逻辑卷MyLvm0
$ sudo lvextend -l +262142 /dev/VG1/MyLvm0
  Size of logical volume VG1/MyLvm0 changed from 1.00 TiB (262144 extents) to <2.00 TiB (524286 extents).
  Logical volume VG1/MyLvm0 successfully resized.

// 成功扩展
$ lsblk
NAME            MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda               8:0    0  100G  0 disk 
├─sda1            8:1    0    1G  0 part /boot
└─sda2            8:2    0   99G  0 part 
  ├─centos-root 253:0    0   50G  0 lvm  /
  ├─centos-swap 253:1    0  9.8G  0 lvm  [SWAP]
  └─centos-home 253:2    0 39.2G  0 lvm  /home
sdb               8:16   0    1T  0 disk 
└─VG1-MyLvm0    253:3    0    2T  0 lvm  
sdc               8:32   0    1T  0 disk 
└─VG1-MyLvm0    253:3    0    2T  0 lvm  
sr0              11:0    1 1024M  0 rom

五. LVM创建虚拟磁盘阵列

1.创建磁盘分区

目前做LVM分区比较推荐的工具还是fdisk,不是说parted不能做,而是fdisk可能更加方便一点。流程如下:

# fdisk /dev/nvme0n1
Command (m for help): n ## 新建
Command action
   e   extended
   p   primary partition (1-4)
p ## 主分区

Partition number (1-4): 1 ## 分区号
First cylinder (2048-543352123, default 2048):  ## 回车用默认的1
Last cylinder, +cylinders or +size{K,M,G} (2048-543352123, default 543352123): ## 回车默认大小大小

Command (m for help): t ## 改变toggle类型
Selected partition 1
Hex code (type L to list codes): 8e ## LVM 的分区代码8e
Changed system type of partition 1 to 8e (Linux LVM)

2.创建物理卷PV

在分区完成之后需要做的就是创建物理卷,直接将刚才创建的分区进行
pvcreate:

# pvcreate /dev/nvme0n1p1

3.创建虚拟卷VG

在创建玩物理卷之后,需要对该磁盘进行虚拟卷的创建。需要注意的是一个虚拟卷可以由多个物理卷构成。例如:

# vgcreate nvme /dev/nvme0n1p1 /dev/nvme1n1p1 /dev/nvme2n1p1

该命令的意义就在于创建一个叫做nvme的虚拟卷,由/dev/nvme0n1p1、 /dev/nvme1n1p1、 /dev/nvme2n1p1三个做了pv的分区构成

4.创建逻辑卷LG

到了这一步,基本上LVM的创建已经到了尾声了,最后一步就版权声明:本文遵循 CC 4.0 BY-SA 版权协议,若要转载请务必附上原文出处链接及本声明,谢谢合作!是从虚拟卷中创建一个逻辑卷。如下:

# lvcreate -L 2.91T -n data nvme

这条命令的意思为从虚拟卷nvme中创建一个2.91T的逻辑卷作为lvm分区并命名为data,如果想一次性全部用完版权声明:本文遵循 CC 4.0 BY-SA 版权协议,若要转载请务必附上原文出处链接及本声明,谢谢合作!所有的容量,也可以这样:

# lvcreate -l -n data nvme

此时在linux的/dev/文件夹下面我们可以看到有/nvme/data的文件结构。

5.挂载并更新文件

在创建完lvm分区后,我们需要将分区挂在到系统中的路径中。假设需要挂载的路径是/data。

# mkdir /data ##创建该路径
# mount /dev/mapper/nvme-data /data ##需要注意的时候这里推荐使用/dev/mapper/nvme-data作为挂载的设备路径,而不是/dev/nvme/data

之后通过blkid命令获取这个新的lvm分区的UUID,然后更新到/etc/fstab中就可以了

八. Replication+LVM Snapsho

基于快照和复制技术的结合可以保证我们得到一个实时的在线MySQL备份解决方案

当主库发生误操作时,只需要恢复备库上的快照,然后再根据binlog执行point-in-time的恢复即可

下面假定一个场景:

版权声明:本文遵循 CC 4.0 BY-SA 版权协议,若要转载请务必附上原文出处链接及本声明,谢谢合作!

主从架构,没有延迟,某DBA误操作:drop database

接下来我们按照以上场景进行备份恢复模拟测试

1.主库准备测试数据

mysql> create database cnfol;
Query OK, 1 row affected (0.00 sec)


mysql> create table cnfol.t (id int primary key);
Query OK, 0 rows affected (0.02 sec)


mysql> insert into cnfol.t select 1;
Query OK, 1 row affected (0.01 sec)
Records: 1  Duplicates: 0  Warnings: 0


mysql> insert into cnfol.t select 2;
Query OK, 1 row affected (0.00 sec)
Records: 1  Duplicates: 0  Warnings: 0

到备库确认:

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| cnfol              |
| mysql              |
| test               |
+--------------------+
4 rows in set (0.00 sec)

mysql> select * from cnfol.t;
+----+
| id |
+----+
|  1 |
|  2 |
+----+
2 rows in set (0.00 sec)

2.备库设置全局读锁

mysql> flush tables with read lock;
Query OK, 0 rows affected (0.00 sec)

3.备库所在分区创建快照

[root@localhost ~]# lvcreate --size 1G --snapshot --name backup_mysql /dev/vg/mysql
  Logical volume "backup_mysql" created

[root@localhost ~]# lvs
  LV           VG   Attr   LSize Origin Snap%  Move Log Copy%  Convert
  backup_mysql vg   swi-a- 1.00G mysql    0.00                        
  mysql        vg   owi-ao 2.00G                                      

4.备库获取二进制日志坐标

mysql> show master status;
+------------------+----------+--------------+------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000003 |      727 |              |                  |
+------------------+----------+--------------+------------------+
1 row in set (0.00 sec)

5.备库设置全局解锁

mysql> unlock tables;
Query OK, 0 rows affected (0.00 sec)

6.挂载快照

[root@localhost ~]# mount /dev/vg/backup_mysql  /mnt/backup
[root@localhost ~]# cd /mnt/backup/mysql/data/cnfol/ && ls -alh
总计 32K
drwx------ 2 mysql dba 4.0K 10-14 09:57 .
drwx------ 5 mysql dba 4.0K 10-14 09:57 ..
-rw-rw---- 1 mysql dba   61 10-14 09:57 db.opt
-rw-rw---- 1 mysql dba 8.4K 10-14 09:57 t.frm
-rw-rw---- 1 mysql dba   14 10-14 09:57 t.MYD
-rw-rw---- 1 mysql dba 2.0K 10-14 10:06 t.MYI

7.主库某无经验DBA误操作

mysql> drop database cnfol;
Query OK, 1 row affected (0.05 sec)
记录下此时时间:2013-10-14 10:17:10

备库确认是否存在库cnfol:
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| test               |
+--------------------+
3 rows in set (0.01 sec)

8.备份快照

[root@localhost backup]# pwd
/mnt/backup

[root@localhost backup]# tar -jcv -f /mnt/snapshot/mysql.tar.bz2 *

这里做备份的原因有2点

  • 其一,昂贵的IO,因为磁头要在快照区和系统区来回跑
  • 其二,快照区空间不足,因为是COW原理

9.删除快照

[root@localhost ~]# umount /mnt/backup
[root@localhost ~]# lvremove --force /dev/vg/backup_mysql 
  Logical volume "backup_mysql" successfully removed

10.格式化备库所在分区

[mysql@localhost ~]$ mysqladmin -uroot -poracle shutdown
131014 10:32:40 mysqld_safe mysqld from pid file /mnt/lvm/mysql/data/localhost.localdomain.pid ended
[1]+  Done                    mysqld_safe

[root@localhost ~]# umount /mnt/lvm
[root@localhost ~]# mkfs -t ext3 /dev/vg/mysql 

[root@localhost ~]# mount /dev/vg/mysql  /mnt/lvm
[root@localhost ~]# lvs
  LV    VG   Attr   LSize Origin Snap%  Move Log Copy%  Convert
  mysql vg   -wi-ao 2.00G                                      

[root@localhost ~]# vgs
  VG   #PV #LV #SN Attr   VSize VFree
  vg     4   1   0 wz--n- 3.81G 1.81G

11.解压缩快照到备库所在分区

# tar -jxv -f /mnt/snapshot/mysql.tar.bz2 -C /mnt/lvm/
[root@localhost lvm]# pwd
/mnt/lvm

[root@localhost lvm]# ls
lost+found  mysql

12.启动MySQL

13.利用binlog恢复数据

利用binlog执行point-in-time恢复

[mysql@localhost ~]$ mysqlbinlog --stop-datetime="2013-10-14 10:17:10" /mnt/lvm/mysql/data/mysql-bin.000003 | mysql -uroot -poracle

14.确认数据

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| cnfol              |
| mysql              |
| test               |
+--------------------+
4 rows in set (0.00 sec)

mysql> select * from cnfol.t;
+----+
| id |
+----+
|  1 |
|  2 |
+----+
2 rows in set (0.00 sec)

参考文献

https://access.redhat.com/documentation/zh-cn/red_hat_enterprise_linux/7/html/logical_volume_manager_administration/index

https://www.percona.com/blog

0 条回应