Сюрприз fsync() PostgreSQL

24.10.19

База данных - Администрирование СУБД

Предлагаю вашему вниманию продолжение перевода статьи Jonathan Corbet "PostgreSQL's fsync() surprise". Оригинал доступен по ссылке https://lwn.net/Articles/752063/

Разработчики СУБД в силу необходимости, озабочены тем, чтобы данные безопасно попадали в постоянное хранилище. Поэтому, когда сообщество PostgreSQL обнаружило, что то, как ядро обрабатывает ошибки ввода-вывода, может привести к потере данных без каких-либо ошибок, сообщаемых в пользовательское пространство, возникло немало недовольства. Проблема, которая усугубляется тем, что PostgreSQL выполняет буферизованный ввод-вывод, оказывается, не является уникальной для Linux, и ее будет нелегко решить даже там.

Крейг Рингер впервые сообщил о проблеме в список рассылки pgsql-hackers в конце марта. Короче говоря, PostgreSQL предполагает, что успешный вызов fsync() указывает на то, что все данные, записанные с момента последнего успешного вызова, безопасно перешли в постоянное хранилище. При сбое буферизованной записи ввода-вывода из-за аппаратной ошибки файловые системы реагируют по-разному, но такое поведение обычно включает удаление данных на соответствующих страницах и пометку их как чистых. Поэтому чтение блоков, которые были только что записаны, скорее всего, вернет что-то другое, но не записанные данные.

Что насчет отчетов об ошибках? Год назад на саммите Linux Filesystem, Storage и Memory-Management Summit (LSFMM) включал в себя сессию по сообщениям об ошибках, в которой это все было названо «беспорядком»; ошибки легко могут быть потеряны, так что ни одно приложение никогда их не увидит. Некоторые патчи, включенные 4.13, в ходе цикла разработки несколько улучшили ситуацию (и в 4.16 произошли некоторые изменения для её дальнейшего улучшения), однако существуют способы потери уведомлений об ошибках, как будет описано ниже. Если это происходит на сервере PostgreSQL, это может привести к автоматическому повреждению базы данных.

Разработчики PostgreSQL были недовольны. Том Лейн описал это "повреждением мозга ядра", в то время как Роберт Хаас назвал "100% глупостью". В начале обсуждения разработчики PostgreSQL достаточно четко понимали, как, по их мнению, должно работать ядро: страницы, которые не могут быть записаны, должны храниться в памяти в «грязном» состоянии (для последующих попыток), и соответствующий файловый дескриптор должен быть переведен в состояние постоянной ошибки, чтобы сервер PostgreSQL не мог пропустить наличие проблемы.
 

В каком месте что-то пошло не так


Однако еще до того, как в дискуссию вступило сообщество ядра, стало ясно, что ситуация не настолько проста, как может показаться. Томас Мунро сообщил, что Linux не уникален в подобном поведении; OpenBSD и NetBSD также могут не сообщать об ошибках записи в пространство пользователя. И, как выяснилось, то, как PostgreSQL обрабатывает буферизованные операции ввода-вывода, значительно усложняет картину.

Этот механизм был подробно описан Хаасом. Сервер PostgreSQL работает как набор процессов, многие из которых могут выполнять операции ввода-вывода в файлы базы данных. Задание вызова fsync(), однако, обрабатывается в одном процессе checkpointer («checkpointer» process), который касается поддержания дискового хранилища в согласованном состоянии, для восстановления после сбоев. Сheckpointer обычно не поддерживает все соответствующие файлы открытыми, поэтому ему часто приходится открывать файл перед вызовом fsync(). Именно здесь возникает проблема: даже в ядрах 4.13 и более поздних версиях checkpointer не увидит никаких ошибок, произошедших до открытия файла. Если что-то нехорошее случится до вызова open() checkpointer-a, то следующий вызов fsync() вернет успех. Существует несколько способов возникновения ошибки ввода-вывода вне вызова fsync(); например ядро может столкнуться с одной из них при выполнении фоновой обратной записи. Кто-то, вызывающий sync(), может также столкнуться с ошибкой ввода-вывода и «поглотить» полученное состояние ошибки.

Хаас описал такое поведение как неспособное соответствовать ожиданиям PostgreSQL:
 

Все, что у вас (или у кого-то) есть — в основном это недоказанное предположение о том,
какие файловые дескрипторы могут иметь отношение к конкретной ошибке, но так получилось, что PostgreSQL никогда не соответствовал ему. Вы можете продолжать говорить, что проблема в наших догадках, но мне кажется не правильно предполагать, что мы — единственная программа, которая их когда-либо делала.

В итоге Джошуа Дрейк перенес беседу в список разработки для ext4, включив часть сообщества разработчиков ядра. Дэйв Чиннер быстро охарактеризовал это поведение как "рецепт катастрофы, особенно в кросс-платформенном коде, где каждая платформа ОС ведет себя по-разному и почти никогда не соответствует ожидаемому". Вместо этого Тед Цо объяснил, почему затронутые страницы помечаются как чистые после возникновения ошибки ввода-вывода; короче говоря, самой распространенной причиной ошибок ввода-вывода является извлечение пользователем USB-накопителя не вовремя. Если какой-то процесс копировал на этот диск много данных, результатом будет накопление грязных страниц в памяти, возможно, до такой степени, что системе не хватит памяти для других задач. Таким образом, эти страницы не могут быть сохранены и будут очищены, если пользователь хочет, чтобы система оставалась пригодной для использования после такого события.

И Чиннер, и Цо, вместе с другими, заявили, что для PostgreSQL правильное решение — перейти на прямой ввод-вывод (DIO). Использование DIO дает больший уровень контроля над обратной записью (writeback) и вводом-выводом в целом; это включает в себя доступ к информации о том, какие именно операции ввода-вывода могли быть неудачными. Андрес Фройнд, как и ряд других разработчиков PostgreSQL, признал, что DIO является лучшим долгосрочным решением. Но он также отметил, что не стоит ждать, что разработчики сейчас по уши окунуться в реализацию этой задачи. Между тем, он сказал, что существуют другие программы (он упомянул dpkg), которые также подвержены этому поведению.
 

На пути к краткосрочному решению


В ходе обсуждения значительное внимание было уделено идее, что сбой записи должен приводить к тому, что затронутые страницы будут храниться в памяти в их грязном состоянии. Но разработчики PostgreSQL быстро отошли от этой идеи и не требовали этого. То, что им действительно нужно, в итоге — надежный способ узнать, что-то пошло не так. Учитывая это, обычные механизмы PostgreSQL для обработки ошибок могут справиться с этим; однако в его отсутствие мало что можно сделать.

В какой-то момент обсуждения Цо упомянул, что у Google есть собственный механизм обработки ошибок ввода-вывода. Ядро было проинструктировано сообщать об ошибках ввода-вывода через сокет netlink; выделенный процесс получает эти уведомления и отвечает соответственно. Все же этот механизм никогда не делал этого на входе. Фрейнд указал, что этот механизм будет «идеальным» для PostgreSQL, поэтому он может появиться в открытом доступе в ближайшее время.

Между тем Джефф Лейтон задумался над другой идеей: установить флаг в суперблоке файловой системы при возникновении ошибки ввода-вывода. Вызов syncfs() затем очистит этот флаг и вернет ошибку, если он был установлен. PostgreSQL checkpointer может периодически вызывать syncfs() для опроса ошибок в файловой системе, содержащей базу данных. Фройнд согласился, что это может быть жизнеспособным решением проблемы.

Конечно, любой такой механизм появится только в новых ядрах; тем временем установки PostgreSQL, как правило, работают на старых ядрах, поддерживаемых корпоративными дистрибутивами. В этих ядрах, по всей видимости, отсутствуют даже те улучшения, которые были включены в 4.13. Для таких систем мало что можно сделать, чтобы помочь PostgreSQL обнаруживать ошибки ввода-вывода. Может хватить запуска демона, который сканирует системный журнал и ищет там сообщения об ошибках ввода-вывода. Не самое элегантное решение, и оно осложняется тем, что разные драйверы блоков и файловые системы, как правило, сообщают об ошибках по-разному, но это может быть наилучшим доступным вариантом.

Следующим шагом, вероятно, станет обсуждение на мероприятии LSFMM 2018 года, которое состоится 23 апреля. Если повезет, появится какое-то решение, которое будет работать для заинтересованных сторон. Однако одна вещь, которая не изменится — это простой факт, что обработку ошибок трудно сделать правильно.

postgres linux i/o

См. также

Устранение ошибки выполнения скрипта "Создать сервис RAGENT" в ЦКК

Администрирование СУБД Платформа 1С v8.3 Конфигурации 1cv8 Россия Бесплатно (free)

В статье показано, как устранить ошибку выполнения скрипта "Создать сервис RAGENT" в системах 1С:Центр контроля качества или в 1С:Центр автоматизации. Будет полезна администраторам ЦКК и ЦА, которые только начали знакомство с этими системами.

вчера в 17:30    145    artemusII    0    

4

Долгая реструктуризация, замеры времени и очистка Ветис. Розница 2.3

HighLoad оптимизация Администрирование СУБД Платформа 1С v8.3 1С:Розница 2 Розничная и сетевая торговля (FMCG) Россия Бесплатно (free)

При подготовке к обновлению возникли проблемы на стадии тестирования и исправления базы данных, также при создании файлов РИБ для магазинов.

16.04.2024    248    xKaskadx    4    

0

Установка и получение лицензии на базовую конфигурацию 1С на Mac OS

Администрирование СУБД Платформа 1С v8.3 Бесплатно (free)

Установить купленную базовую конфигурацию 1С и получить лицензию на MAC OS не так просто, как кажется на первый взгляд и как хотелось бы. Официально в системных требованиях на базовую конфигурации 1С пишет всякие виндовсы и пару-тройку линуксов. МакОс там нет. В статье расскажу, как все-таки поставить на Мак базовую конфигурацию 1С.

11.04.2024    344    pahmutov    0    

2

Установка тонкого клиента 1С на Rasbian (Raspberry Pi 5)

Администрирование СУБД Платформа 1С v8.3 Бесплатно (free)

После приобретения Raspberry Pi 5 решил проверить, есть ли возможность использования устройства для организации тонкого клиента. В результате столкнулся с особенностью установки 1С: Предприятие 8.3.23 на Raspbian, решением которой я хочу поделиться с сообществом.

07.04.2024    608    Bessome    3    

5

Порционный шринк базы

Администрирование СУБД Бесплатно (free)

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

28.03.2024    1271    Garilia    3    

15

Создаем сценарии обслуживания SQL в Центре Контроля Качества 1С (Центр Администрирования)

Администрирование СУБД Платформа 1С v8.3 Бесплатно (free)

Данная статья научит вас, как создавать скрипты обслуживания MS SQL для Центра Контроля Качества (ЦКК) или Центра Администрирования (ЦА).

20.03.2024    742    Silenser    0    

5

Поинтегрируем: сервисы интеграции – новый стандарт или просто коннектор?

Обмен между базами 1C Администрирование СУБД Механизмы платформы 1С Платформа 1С v8.3 Бесплатно (free)

В платформе 8.3.17 появился замечательный механизм «Сервисы интеграции». Многие считают, что это просто коннектор 1С:Шины. Так ли это?

11.03.2024    5919    dsdred    54    

83

Инструкция по установке Postgres для OLTP приложений и 1С. Часть 1. Базовая конфигурация

Администрирование СУБД Платформа 1С v8.3 Бесплатно (free)

В Postgres достаточно подробная документация, и, видимо, поэтому при инсталляции Postgres для 1С большинство параметров приходится выставлять самим. Параметров в Postgres много, а составить эффективную комбинацию не так просто. Все упрощается, если рассмотреть профиль нагрузки, например, 1С это прежде всего профиль OLTP нагрузки – так устроены его метаданные (объекты). Если сосредоточиться на оптимизации профиля OLTP, понимание Postgres сразу упростится.

15.02.2024    2542    1CUnlimited    14    

28
Оставьте свое сообщение