RAID basics with mdadm
mdadm manages Linux software RAID arrays. RAID 0 stripes for speed (zero redundancy), RAID 1 mirrors for safety, RAID 5/6 use parity to tolerate 1/2 disk failures, RAID 10 combines both. RAID is not a backup — it protects against hardware failure, not data loss.
A disk fails at 2 AM. If your data lives on a single drive, you are restoring from backup — and finding out exactly how old that backup is. If it lives on a RAID array, the system keeps running, you get an alert, and you replace the disk the next morning with zero downtime.
RAID is not magic. RAID 5 with four disks does not survive two simultaneous failures. RAID does not protect against accidental deletion, ransomware, or a filesystem bug corrupting all mirrors equally. Understanding what each RAID level actually protects against — and what it does not — is the difference between a false sense of security and a real one.
After this lesson you can explain what each common RAID level trades, create a software RAID array with mdadm, read /proc/mdstat, and articulate why RAID is not a backup.
RAID levels: what each trades.
| Level | Minimum disks | Usable capacity | Fault tolerance | Best for |
|---|---|---|---|---|
| RAID 0 | 2 | 100% | None (lose one disk = lose all data) | Temp scratch space, speed |
| RAID 1 | 2 | 50% | 1 disk failure | Boot disks, small critical volumes |
| RAID 5 | 3 | (N-1)/N | 1 disk failure | General storage — good balance |
| RAID 6 | 4 | (N-2)/N | 2 disk failures | Archives, slow rebuild tolerance |
| RAID 10 | 4 | 50% | 1 disk per mirror pair | Databases, high IOPS + redundancy |
# RAID 0: two 1 TB disks → 2 TB usable, zero redundancy
# One disk dies: all 2 TB lost
# RAID 1: two 1 TB disks → 1 TB usable, either disk can die
# Reads can come from either disk (read parallelism); writes go to both
# RAID 5: four 1 TB disks → 3 TB usable
# Parity is distributed: any one disk can fail
# Rebuild reads ALL remaining disks — risk window during rebuild
# RAID 6: four 1 TB disks → 2 TB usable
# Two parity stripes: survives any two simultaneous failures
# Slower writes than RAID 5 (double parity calculation)
# RAID 10: four 1 TB disks → 2 TB usable
# Mirrors first (1+1, 1+1), then stripes the mirror pairs
# Can survive 2 failures if they are in different mirror pairsCreating a software RAID array with mdadm.
# Scenario: four 1 TB disks (/dev/sdb, /dev/sdc, /dev/sdd, /dev/sde)
# Goal: RAID 5 with 3 TB usable + 1 disk parity
# Install mdadm if not present
sudo apt install mdadm
# Create the RAID 5 array
sudo mdadm --create /dev/md0 \
--level=5 \
--raid-devices=4 \
/dev/sdb /dev/sdc /dev/sdd /dev/sde
# mdadm: Defaulting to version 1.2 metadata
# mdadm: array /dev/md0 started.
# The array starts in a degraded state and begins syncing (building parity)
# Check sync progress (this takes hours for large arrays)
cat /proc/mdstat
# Personalities : [raid6] [raid5] [raid4]
# md0 : active raid5 sde[3] sdd[2] sdc[1] sdb[0]
# 3145728 blocks super 1.2 level 5, 512k chunk, algorithm 2 [4/4] [UUUU]
# [===================>.] resync = 96.8% (...)
# finish=0.4min speed=144000K/sec
# Save the array config so it reassembles at boot
sudo mdadm --detail --scan | sudo tee -a /etc/mdadm/mdadm.conf
sudo update-initramfs -u # include mdadm config in initramfs
# Format and mount once sync completes
sudo mkfs.ext4 /dev/md0
sudo mkdir /mnt/raid
sudo mount /dev/md0 /mnt/raid
# Add to /etc/fstab
# /dev/md0 /mnt/raid ext4 defaults,nofail 0 2Reading /proc/mdstat and mdadm —detail.
/proc/mdstat is your live RAID status window. Learn to read it quickly.
cat /proc/mdstat
# Personalities : [raid5]
# md0 : active raid5 sde[3] sdc[1] sdb[0]
# 3145728 blocks super 1.2 level 5, 512k chunk, algorithm 2 [4/3] [UUU_]
#
# unused devices: <none>
# Decode the status line:
# [4/3] = array expects 4 disks, currently has 3 (one is missing/failed)
# [UUU_] = disk state: U=up, _=missing/failed; 4th position is the failed disk
# sdd is absent from the device list — it failed
# For more detail:
sudo mdadm --detail /dev/md0
# ...
# Array Size : 3145728 (3.00 GiB 3.22 GB)
# Raid Level : raid5
# Raid Devices : 4
# Total Devices : 3
# State : clean, degraded
# Active Devices : 3
# Failed Devices : 1
# Spare Devices : 0
#
# Number Major Minor RaidDevice State
# 0 8 16 0 active sync /dev/sdb
# 1 8 32 1 active sync /dev/sdc
# - 0 0 2 removed <-- failed slot
# 3 8 80 3 active sync /dev/sdeLVM-RAID vs mdadm: when to use which.
Linux offers two paths to software RAID: mdadm (the classic kernel md layer) and LVM’s built-in RAID support (introduced in LVM 2.02.89).
# LVM RAID: create a mirrored LV directly in LVM
sudo lvcreate --type raid1 -m1 -L 100G -n dbdata myvg
# -m1 = 1 mirror (2 copies total, like RAID 1)
# LVM manages the RAID internally — no /dev/md* device
# Check LVM RAID status
sudo lvs -a -o +devices,raid_sync_action myvg
# LV Attr LSize Devices Sync Action
# dbdata rwi-aor--- 100.00g dbdata_rimage_0(0),dbdata_rimage_1(0) idle
# [dbdata_rimage_0] Iwi-aor--- 100.00g /dev/sdb(0)
# [dbdata_rimage_1] Iwi-aor--- 100.00g /dev/sdc(0)
| Aspect | mdadm | LVM RAID |
|---|---|---|
| Maturity | 20+ years, very stable | Solid since ~2013 |
| Visibility | /proc/mdstat + mdadm --detail | lvs -a + dmsetup |
| Integration with LVM | Stack LVM on top of /dev/md0 | Native — single tool |
| RAID 5/6 write hole | Mitigated by write intent bitmap | Journal-based protection |
| Tooling ecosystem | Broader — more documentation | Fewer external guides |
| Recommended for | Existing mdadm arrays, shared storage | New LVM-based setups |
For new setups where you are already using LVM, LVM-RAID is cleaner. For arrays shared across servers (e.g. iSCSI targets) or where you want maximum documentation coverage, mdadm remains the standard.
RAID is not a backup. Understand the failure modes it does not cover.
# What RAID protects against:
# - A single physical disk dying (RAID 1/5/6/10)
# - Two disks dying simultaneously (RAID 6, RAID 10 in some configs)
# What RAID does NOT protect against:
# - Accidental rm -rf /mnt/raid/important-dir
# -> deleted from all mirrors instantly
# - Ransomware encrypting files
# -> encrypted on all disks simultaneously
# - Filesystem corruption (kernel bug, power loss mid-write, bad RAM)
# -> written to all mirrors; the corruption is mirrored
# - RAID controller failure (all disks attached to a dead controller)
# -> array unusable until controller replaced or disks moved
# - Silent data corruption (bit rot)
# -> RAID 5/6 parity can detect but not always correct silent flips;
# use btrfs or ZFS with checksums for full bit-rot protection
# The mental model:
# RAID = high availability (tolerate hardware failure)
# Backup = data protection (recover from data loss)
# Both are required. Neither replaces the other.Creating a RAID 1 mirror for a boot-adjacent data volume.
# Scenario: two 500 GB SSDs (/dev/sdb, /dev/sdc) for a database WAL volume.
# Goal: RAID 1 — 500 GB usable, either disk can fail.
# 1. Zero the superblock to avoid old metadata confusion
sudo mdadm --zero-superblock /dev/sdb /dev/sdc
# 2. Create the array
sudo mdadm --create /dev/md1 --level=1 --raid-devices=2 /dev/sdb /dev/sdc
# mdadm: array /dev/md1 started.
# 3. Wait for initial sync (a mirror must be in sync before it protects you)
watch cat /proc/mdstat
# md1 : active raid1 sdc[1] sdb[0]
# 488386584 blocks super 1.2 [2/2] [UU]
# [===================>.] resync = 98.2% (...)
# Wait until [UU] appears with no resync line
# 4. Save config
echo "DEVICE partitions" | sudo tee /etc/mdadm/mdadm.conf
sudo mdadm --detail --scan | sudo tee -a /etc/mdadm/mdadm.conf
sudo update-initramfs -u
# 5. Create LVM on top of the RAID device (best practice for flexibility)
sudo pvcreate /dev/md1
sudo vgcreate walvg /dev/md1
sudo lvcreate -L 400G -n wal walvg
sudo mkfs.xfs /dev/walvg/wal
sudo mount /dev/walvg/wal /var/lib/postgresql/wal
# Now: disk failure = RAID absorbs it; LVM = flexibility for resizing later▸Common mistake
Never skip the initial RAID sync. When you create a RAID 5 or RAID 6 array and immediately write data to it before the parity calculation (initial resync) completes, you are writing to an array with inconsistent parity. If a disk fails during this window, the rebuild will produce corrupted data — not the data that was there before, because parity is wrong. The array will not warn you; the corruption will be silent. Always wait for /proc/mdstat to show [UUUU] with no resync line before treating a new RAID 5/6 array as production-safe.
▸Why this works
Why does RAID 5 have a “write hole” problem? In RAID 5, a write to a stripe requires updating the data block and recalculating the parity block. These are two separate disk writes. If the system loses power between them, the parity is now inconsistent with the data. On the next boot, the array does not know which write was partial — it cannot distinguish good data with stale parity from stale data with good parity. The write-intent bitmap (enabled with --bitmap=internal) tracks which stripes were being written and forces a resync of those stripes at next boot, shrinking the exposure window from the whole array to just the stripes that were in-flight. ZFS and btrfs avoid this with their copy-on-write design.
You have a RAID 5 array with 4 disks. /proc/mdstat shows [4/3] [UUU_]. A colleague says 'we are fine, RAID 5 tolerates one disk failure.' Are they right, and what should you do immediately?
mdadm manages Linux software RAID. RAID levels trade capacity for redundancy: RAID 0 stripes for full capacity with zero fault tolerance; RAID 1 mirrors at 50% capacity tolerating one failure; RAID 5 uses distributed parity for (N-1)/N capacity tolerating one failure; RAID 6 double-parity for two failures; RAID 10 mirrors then stripes for 50% capacity with the best IOPS and per-pair fault tolerance. Create arrays with mdadm --create, monitor with cat /proc/mdstat and mdadm --detail, save config to /etc/mdadm/mdadm.conf. LVM-RAID is the alternative for new LVM-based setups — same kernel md layer, single-tool management. RAID is not a backup: it protects against hardware failure but not against deletion, ransomware, or filesystem corruption, which propagate to all mirrors instantly.
Practice
Start at the top. Tasks go easiest → hardest: recall a fact, apply it to a case, then a senior-level stretch. Open one, attempt it, then reveal.
Something unclear?
Ask a question about this lesson. Questions are anonymous and go straight to the author to make the lesson better.