Решение проблемы с ошибкой No space left on device на BTRFS

Так уж случилось, что на одном их серверов с Oracle данные экземпляра были размещены на томе с BTRFS. И вот в один прекрасный момент экземпляр останавливается с ошибкой:

..
ORA-00206: error in writing (block 3, # blocks 1) of control file
ORA-00202: control file: '/data/oradata/mydb/control01.ctl'
ORA-27061: waiting for async I/Os failed
Linux-x86_64 Error: 28: No space left on device
...

При этом команда df говорит нам, что места на разделе /data придостаточно.

# df -h /data
Filesystem      Size  Used Avail Use% Mounted on
dev/vdd         200G  112G   88G  57% /data

Что же делать?

Исходные данные: Oracle Linux Server 7.2 c BTRFS
Задача: Понять куда исчезло место на разделе BTRFS и исправить это.

Первым делом останавливаем экземпляр Oracle и смотрим сколько у нас занято место утилитой btrfs:

# btrfs filesystem show data
Label: 'data'  uuid: 7f831d86-a123-4a30-b94c-0405073458c5
        Total devices 1 FS bytes used 110.00GiB
        devid    1 size 200.00GiB used 200.00GiB path /dev/vdd

Мы видим, что на разделе размером 200GB все место использовано, но как?

Проверим есть ли у нас на разделе субтома:

# btrfs subvolume list -a /data

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

Смотрим сколько занимают все данные БД Oracle на разделе /data:

# du -sh /data/
85G     /data/

Попробуем проверить раздел на наличие ошибок:

# umount /data
# btrfs check --repair /dev/vdd

К счастью (или сожалению), в моем случае проверка не выявила проблем. Вывод проверки не привожу. Идем дальше.

Смотрим информацию по метаданным на разделе /data:

# btrfs filesystem df /data
Data, single: total=195.97GiB, used=108.50GiB
System, DUP: total=8.00MiB, used=48.00KiB
System, single: total=4.00MiB, used=0.00B
Metadata, DUP: total=2.00GiB, used=1.50GiB
Metadata, single: total=8.00MiB, used=0.00B

В строке «Metadata, DUP» мы видим, что метаданные заняли достаточно много места (used) по отношению к общему их количеству (total).
Но это не основной корень беды, в строке «Data, single» мы видим большое значение total по отношению к used, притом, что реальных данных на разделе менее 100 GB. А так же мы видим, что эти данные несколько не сходится с данными df и du (ниже в статье я напишу, почему эти данные не сходятся).

Давайте попробуем переназначить блоки данных и высвободить место, для этого выполним:

# btrfs fi balance start -dusage=5 /data
Done, had to relocate 43 out of 201 chunks

Эта команда будет пытаться переместить данные в пустые или почти пустые блоки (пока будем использовать не более 5%), это позволяет освободить место и переназначить данные. Обратите внимание, что между -d и usage не должно быть пробелов. Опция -d задает фильтр только для блоков данных, для блоков метаданных используется опция -m, для системных блоков используется опция -s. Фильтры могут задаваться через запятую, мы задали только один фильтр — usage=проценты, в нем участвуют только группы, заполненные менее чем на указанный процент.

Если команда балансера завершилась строкой Done и написано сколько блоков перемещено, то можно увеличить процент (до 10) и так далее.

Теперь если мы выполним:

# btrfs filesystem show data
Label: 'data'  uuid: 7f831d86-a123-4a30-b94c-0405073458c5
        Total devices 1 FS bytes used 109.96GiB
        devid    1 size 200.00GiB used 158.04GiB path /dev/vdd

Мы видим, что свободное место вернулось.

Я продолжал увеличивать процент в параметре usage добавляя 5% и так дошел до значения 30, до тех пор пока не получил сообщение:

Done, had to relocate 0 out of 140 chunks

Посмотрим теперь сколько места доступно:

# btrfs filesystem show data
Label: 'data'  uuid: 7f831d86-a123-4a30-b94c-0405073458c5
        Total devices 1 FS bytes used 109.96GiB
        devid    1 size 200.00GiB used 139.04GiB path /dev/vdd

Удалось освободить еще почти 20GB.

Смотрим расширенную информацию:

# btrfs filesystem usage /data
Overall:
    Device size:                 200.00GiB
    Device allocated:            139.04GiB
    Device unallocated:           60.96GiB
    Device missing:                  0.00B
    Used:                        111.52GiB
    Free (estimated):             85.46GiB      (min: 54.97GiB)
    Data ratio:                       1.00
    Metadata ratio:                   2.00
    Global reserve:                  0.00B      (used: 0.00B)

Data,single: Size:133.01GiB, Used:108.52GiB
   /dev/vdd      133.01GiB

Metadata,single: Size:8.00MiB, Used:0.00B
   /dev/vdd        8.00MiB

Metadata,DUP: Size:3.00GiB, Used:1.50GiB
   /dev/vdd        6.00GiB

System,single: Size:4.00MiB, Used:0.00B
   /dev/vdd        4.00MiB

System,DUP: Size:8.00MiB, Used:48.00KiB
   /dev/vdd       16.00MiB

Unallocated:
   /dev/vdd       60.96GiB

Исчезнувшие гигабайты мы вернули, но почему же они исчезли?

Ответ на это кроется в самом названии и основной особенности ФС BTRFS, а именно: Файловая система BTRFS — это ФС типа CoW (Copy on Write, новая версия данных записывается в свободное место, не затирая старых данных). То есть разделы с интенсивной записью данных подвержены фрагментации. Для томов с базами данных рекомендуется отключать механизм datacow при монтировании (опция nodatacow) или пофайлово (команда «chattr +C /file/name») иначе они фрагментируются на миллионы кусочков.

В BTRFS свободное место выделяется для данных и метаданных большими кусками (chunk) из общего пула. Размер свободного места в BTRFS — сложный вопрос: из пула свободного места при необходимости выделяются сегменты дисковых секторов (все указатели на экстенты работают с сегментными адресами вместо физических дисковых, что позволяет эффективно перемещать сегменты между дисками) для метаданных (по 256MB) и для данных (по 1GB) с учётом уровня RAID.

А теперь отвечу на вопрос, почему же команды du, df и btrfs filesystem df показывали разную информацию:
— Команда du показывает размер файла до сжатия без учёта метаданных (снимки учитываются дважды);
— Команда df показывает общее доступное место и занятое место с учётом метаданных, свободное место для этой точки монтирования без учёта сжатия и уровня RAID;
— Команда «btrfs filesystem df /mount/point» показывает выделенное место с учётом уровня RAID и использованное в выделенном для данных, метаданных и системы;
— Команда «btrfs filesystem show DEV» показывает общее занятое место, имеющееся и занятое место на каждом блочном устройстве;
— Команда «btrfs filesystem usage /mount/point» показывает более подробную информацию;

Так же хочу сделать небольшое отступление и дать рекомендацию: Если Вы выполняете копирование больших файлов на разделе BTRFS командой cp, то у неё имеет ключ «—reflink[=always]», который позволяет копировать файлы без увеличения используемого дискового пространства до изменения копии.

Теперь давайте посмотрим с какими опциями смонтирован наш том /data:

# cat /proc/mounts | grep data
/dev/vdd /data btrfs rw,seclabel,relatime,space_cache 0 0

# lsattr -d /data
---------------- /data

# lsattr -d /data/oradata/mydb
---------------- /data/oradata/mydb

Как мы видим том с дата-файлами БД смонтирован без опции nodatacow. На раздел, как и на каталог с файлами БД не выставлен соответствующий аттрибут.

В соответствии с рекомендациями я добавил опцию nodatacow в файл /etc/fstab, так же я добавил опцию ssd, т.к. раздел /data находятся на SSD накопителе.

ВНИМАНИЕ! Следует знать, что отключение механизма datacow так же отключает создание контрольных сумм (nodatasum), сжатие данных и вероятно шифрование данных. Рекомендуется не отключать datacow на уровне всего тома ФС, а выставлять соответствующий аттрибут на каталог с базой данных — это будет наиболее правильный вариант.

В моем случае я принял решение отключить datacow на уровне всего раздела.

Перемонтируем раздел с нужными опциями:

mount -o ssd,nodatacow,remount /data

Посмотрим результат:

# cat /proc/mounts | grep data
/dev/vdd /data btrfs rw,seclabel,relatime,nodatasum,nodatacow,ssd,space_cache 0 0

Теперь когда место на разделе появилось и мы нашли причину его исчезновения и исправили проблему, можно запустить экземпляр Oracle.

В статье использованы материалы с официального сайта BTRFS, а так же с сайта Сергея Богомолова.

На этом все, до скорых встреч. Если у Вас возникли вопросы или Вы хотите чтобы я помог Вам, то Вы всегда можете связаться со мной разными доступными способами.


Хотите оставить комментарий?