Так уж случилось, что на одном их серверов с 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, а так же с сайта Сергея Богомолова.
На этом все, до скорых встреч. Если у Вас возникли вопросы или Вы хотите, чтобы я помог Вам, то Вы всегда можете связаться со мной разными доступными способами.
Профессионально занимаюсь системным администрированием Linux -серверов и баз данных (MySQL, POstgreSQL) на протяжении последних 24 лет.
Привлекала меня данная ФС своими возможностями.
Ровно до тех пор, пока при ПЕРЕМЕЩЕНИИ файлов из одного каталога в другой (на том же разделе) у меня не закончилось неожиданно место. Снэпшотов не было.
Инструкции из статьи не помогли. Не стал мучиться — благо данные было куда скопировать — сменил btrfs на ext4.
Пока все хорошо. )
Спасибо! помогло!