Когда RAID начинает «врать»: история одного сервера и 665,000 ошибок

Прошлую неделю я провел в холодном серверном помещении, разбираясь с проблемой, которая могла стоить нам всей базы данных. Все началось с рутинной проверки логов, когда я заметил странные записи о проблемах чтения. Решил проверить состояние RAID-массивов и… ну что сказать, 665,472 ошибки в mismatch_cnt — это не то, что хочется видеть в понедельник утром.

Что такое mismatch_cnt и почему это важно

Для тех, кто не сталкивался с этой проблемой (и надеюсь, не столкнется), объясню простыми словами. В Linux системах с программным RAID файл /sys/block/mdX/md/mismatch_cnt показывает количество несоответствий данных между дисками в массиве.

Представьте RAID как группу людей, которые должны записывать одинаковую информацию. Если у одного в блокноте написано «2+2=4», а у другого «2+2=5», то у нас есть несоответствие. В идеальном мире этот счетчик должен быть равен нулю. Но жизнь, как известно, далека от идеала.

# Проверить количество ошибок
cat /sys/block/md0/md/mismatch_cnt

В моем случае результат был… впечатляющим. Не в хорошем смысле.

Диагностика: что происходит с массивом

Первым делом нужно понять общее состояние RAID-массива. Я всегда начинаю с базовых команд:

# Общая информация о состоянии
cat /proc/mdstat

# Подробная информация о конкретном массиве
sudo mdadm --detail /dev/md0

Вывод /proc/mdstat покажет текущую активность массивов. Если увидите что-то вроде [UU_] вместо [UUU], значит один из дисков «выпал» из массива. В моем случае все диски были активны, но mismatch_cnt кричал о проблемах.

Следующий шаг — проверка SMART-атрибутов дисков. Это критически важно, потому что большое количество несоответствий часто указывает на аппаратные проблемы:

# Для каждого диска в массиве
sudo smartctl -a /dev/sda
sudo smartctl -a /dev/sdb
sudo smartctl -a /dev/sdc

Особое внимание стоит обратить на:

  • Reallocated_Sector_Ct — количество переназначенных секторов
  • Current_Pending_Sector_Ct — сектора, ожидающие переназначения
  • Offline_Uncorrectable — неисправимые сектора

Любые ненулевые значения здесь — тревожный звонок.

Процесс восстановления: repair vs check

Существует два основных подхода к исправлению несоответствий:

Команда check

echo check > /sys/block/md0/md/sync_action

Эта команда только читает и сравнивает данные, фиксируя несоответствия, но не исправляя их автоматически.

Команда repair

echo repair > /sys/block/md0/md/sync_action

Эта команда не только находит несоответствия, но и пытается их исправить, используя избыточность массива.

В моей ситуации я выбрал repair — времени на деликатность не было. Процесс запустился, и я приготовился ждать. На массиве объемом 8TB процедура заняла почти 14 часов.

Мониторить прогресс можно несколькими способами:

# Общий прогресс
watch cat /proc/mdstat

# Более детальная информация
watch "cat /sys/block/md0/md/sync_completed && echo '---' && cat /sys/block/md0/md/mismatch_cnt"

Работа с несколькими массивами

На нашем сервере было несколько RAID-массивов, и возник вопрос — можно ли запустить repair для всех одновременно? Технически да, но я не рекомендую этого делать на продакшн-системах.

Вот скрипт для массовой проверки (используйте осторожно):

#!/bin/bash
for md_device in /sys/block/md*/md/sync_action; do
    md_name=$(echo $md_device | sed 's|/sys/block/||; s|/md/sync_action||')
    echo "Проверяю состояние $md_name..."
    
    # Проверяем, не запущен ли уже какой-то процесс
    current_action=$(cat $md_device)
    if [ "$current_action" = "idle" ]; then
        echo "Запускаю repair для $md_name"
        echo repair > $md_device
        sleep 30  # Даем время на инициализацию
    else
        echo "$md_name уже выполняет операцию: $current_action"
    fi
done

Однако в реальности я запускал repair по очереди — сначала для критически важных массивов, потом для остальных. Параллельный repair всех массивов может серьезно нагрузить диски и контроллер.

Влияние ошибок на систему

Большое количество mismatch_cnt — это не просто цифры в файле. Это реальная угроза целостности данных. За годы работы я видел разные последствия:

Коррупция баз данных. MySQL особенно чувствительна к повреждениям на уровне файловой системы. Один из клиентов потерял целую таблицу из-за игнорирования проблем с RAID.

Повреждение системных файлов. Если затронуты критические системные области, сервер может начать вести себя непредсказуемо — от странных ошибок в логах до kernel panic.

Молчаливая коррупция данных. Самое коварное — когда файлы читаются нормально, но содержат неверную информацию. Обнаружить такие проблемы можно только при детальной проверке.

В моем случае 665,472 ошибки означали реальную опасность для всей системы. После первого прогона repair количество снизилось до 440,000, что все еще критично много.

Что делать, если repair не помогает

Когда после полного цикла repair mismatch_cnt остается высоким, это обычно указывает на аппаратные проблемы. Мой план действий в таких случаях:

  1. Повторная проверка SMART-атрибутов всех дисков
  2. Тестирование дисков утилитой badblocks:
    # Неразрушающий тест (займет много времени)sudo badblocks -sv /dev/sda
    
  3. Проверка кабелей и контроллера — иногда проблема не в дисках
  4. Замена подозрительного диска — если SMART показывает проблемы

В моей ситуации виновником оказался один из дисков с растущим количеством переназначенных секторов. После замены диска и полной пересборки массива проблема исчезла.

Профилактика: регулярные проверки

Чтобы не попадать в подобные ситуации, я настроил регулярные проверки через cron:

# Добавить в /etc/crontab
# Проверка каждое первое воскресенье месяца в 2:00
0 2 * * 0 root [ $(date +\%d) -le 7 ] && echo check > /sys/block/md0/md/sync_action

# Мониторинг mismatch_cnt каждую неделю
0 6 * * 1 root /usr/local/bin/check_raid_mismatch.sh

Скрипт для мониторинга:

#!/bin/bash
# /usr/local/bin/check_raid_mismatch.sh

THRESHOLD=100  # Пороговое значение ошибок

for md_device in /sys/block/md*/md/mismatch_cnt; do
    if [ -f "$md_device" ]; then
        md_name=$(echo $md_device | sed 's|/sys/block/||; s|/md/mismatch_cnt||')
        mismatch_count=$(cat $md_device)
        
        if [ "$mismatch_count" -gt "$THRESHOLD" ]; then
            echo "ВНИМАНИЕ: $md_name имеет $mismatch_count ошибок несоответствия!" | \
            mail -s "RAID Alert: High mismatch count on $md_name" [email protected]
        fi
    fi
done

История с 665,000 ошибками научила меня нескольким важным вещам. Во-первых, RAID — это не волшебная палочка, которая защищает от всех проблем. Это инструмент, который требует постоянного внимания и мониторинга.

Во-вторых, раннее обнаружение проблем критически важно. Если бы я проверял mismatch_cnt регулярно, проблему можно было бы решить на стадии нескольких сотен ошибок, а не сотен тысяч.

И наконец, всегда имейте свежие бэкапы. RAID защищает от отказа дисков, но не от коррупции данных. В нашем случае все обошлось, но я предпочитаю не полагаться на удачу.

Сейчас все наши серверы проверяются автоматически, а критически важные данные дублируются в облако. Больше таких понедельников утром мне не нужно.

Оставить ответ

Ваш адрес email не будет опубликован. Обязательные поля помечены *