This procedure can be used to expand an LVM database volume on Amazon AWS (but also apply to any storage area network environment equally).
Let me start with this assumption: when you create volumes for database use in AWS using EBS, you stripe data across them in order to enhance performance. If you aren't doing this... well, you should :-)
Under this assumption, when you need to add more disk space to an existing database volume, you can't just add the disk(s) to the volume, as this would make the added space non striped, and would eventually create hotspots in the dataset. The correct approach in this situation is to create a number of new EBS disks enough to contain entire dataset plus the desired added space,so that you can grow the existing dataset while re-striping properly.
To make this clear, let's suppose you have a dataset volume of 3 TB, made of 3 1TB EBS volumes which are striped across, but space is running out. You are in a hurry, so you quickly add a new 1 TB EBS volume to the AWS server, add it to the dataset LVM, and expand the volume, as follows:
# add the new EBS disk to LVM
# add the new EBS disk to the dataset volume
vgextend dataset /dev/xvdl
# extend the dataset volume using the new EBS disk
lvextend -i 1 -r /dev/dataset/db /dev/xvdl
This will add space to the dataset volume, however, the fourth EBS volume is just appended to the original striped dataset volume, not striped, thus creating possible hotspots.
The good news is that this can be done without downtime, if you follow the steps below.
IMPORTANT: before proceeding, make sure you have valid backups of the database!!
Now, let's suppose you have added 4 EBS 1 TB disks to the server already, with following path:
The original volume, after you added the "emergency" 1 TB EBS disk above, is using:
The procedure involves migrating the dataset from one group of EBS disks to the other by setting up a mirror, let it sync, then dropping the old mirror side to release the old disks. The important step here is to create the mirror so that it will stripe across the EBS disks properly.
# add new EBS disks to dataset volume
vgextend dataset /dev/xvd[ponm]
# create a mirror out of existing dataset volume
lvconvert -b --stripes 4 -m1 --mirrorlog core /dev/dataset/db /dev/xvd[ponm]
The above commands just add the new disks to LVM, then to the volume, and then the mirror process is started.
You have to wait until the mirror sync is complete, this may take some time, even days depending on the dataset size. You can verify it is synced using the following command and output:
# lvs -a -o +devices LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert Devices bck backup -wi-ao---- 3.00t /dev/xvdi(0),/dev/xvdj(0),/dev/xvdk(0) db dataset mwi-aom--- 4.00t 100.00 db_mimage_0(0),db_mimage_1(0) [db_mimage_0] dataset iwi-aom--- 4.00t /dev/xvdf(0),/dev/xvdg(0),/dev/xvdh(0) [db_mimage_0] dataset iwi-aom--- 4.00t /dev/xvdl(0) [db_mimage_1] dataset iwi-aom--- 4.00t /dev/xvdm(0),/dev/xvdn(0),/dev/xvdo(0),/dev/xvdp(0)
You need to check that he copy sync column shows 100% synced. You can run this command to see progress at any time. The syncing is done at very low priority and there is little to no overhead, and zero impact on database. In the example above you can clearly see that the db_mimage0 logical volume, which includes the original side of the mirror, is actually made by 3 striped disks (f, g, h) and one single striped disk (l), this is what we want to avoid and if you look at db_mimage1 (the new mirror side) you can clearly see it is properly striped over 4 disks now.
Once the mirror is in sync we can safely drop the original side of the mirror, then remove the physical disks from LVM and destroy them on the EBS side:
lvconvert -m0 /dev/dataset/db /dev/xvd[fghl]
# removes EBS disks from the dataset VG
vgreduce dataset /dev/xvd[fghl]
# removes EBS disks from LVM
Done!! You can safely go to the AWS console and detach the EBS disks you just removed from LVM.
Be careful not to remove the wrong disks, or you will destroy your dataset and database!