Надёжность

29.1. Надёжность

Надёжность — это важное свойство любой серьёзной СУБД и PostgreSQL делает всё что только можно, чтобы гарантировать надёжность своего функционирования. Однин из аспектов надёжности состоит в том, что все данные записываются с помощью подтверждённых транзакций, которые сохраняются в энергонезависимой области, которая защищена от потери питания, сбоев операционной системы и аппаратных отказов (разумеется, за исключением отказа самой энергонезависимой области). Успешная запись данных в постоянное место хранения (диск или эквивалентный носитель) обычно всё, что требуется. Фактически, даже если компьютер полностью вышел из строя, если диски выжили, то они могут быть переставлены в другой похожий компьютер и все подтверждённые транзакции останутся неповрежёнными.

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

Далее, кэширование также может осуществляться контроллером диска; в особенности это касается RAID контроллеров. В некоторых случаях это кэширование работает в режиме write-through, что означает, что запись осуществляется на диск как только приходят данные. В других случаях, возможна работа в режиме write-back, что означает, что запись осуществляется некоторое время спустя. Такой режим кэширование может создавать риск для надёжности, потому что память контроллера диска непостоянна и будет потеряна в случае потери питания. Более лучшие контроллеры имеют так называемую батарею резервного питания (battery-backup units) (BBUs), которая сохраняет кэш контроллера на батарее если пропадёт системное питание. После возобновления питания, данные, оставшиеся в кэше контроллера будут записаны на диски.

И наконец, многие диски имеют кэширование. На каких-то дисках оно работает в режиме write-through, на других в режиме write-back, что приводит к тем же проблемам потери данных для write-back кэширования, что и у контроллеров дисков. IDE и SATA диски потребительского класса, особенно часто имеют write-back кэширование, что приводит к потере кэша, если пропадает питание. Многие SSD накопители также имеют зависимые от питания write-back кэширование.

Обычно, такое кэширование можно выключить; однако, то как это делается различается для операционной системы и для типа диска:

  • В Linux, параметры IDE дисков могут быть получены с помощью команды hdparm -I; кэширование записи включено, если за строкой Write cache следует *. Для выключения кэширования записи, может быть использована команда hdparm -W. Параметры SCSI дисков могут быть получены с помощью утилиты sdparm. Используйте sdparm --get=WCE чтобы проверить включено ли кэширование записи и sdparm --clear=WCE, чтобы выключить его.

  • На FreeBSD, параметры IDE дисков могут быть получены с помощью команды atacontrol, а кэширование записи выключается при помощи устанвовки параметра hw.ata.wc=0 в файле /boot/loader.conf; Для SCSI дисков, используется утилита sdparm.

  • На Solaris, кэширование записи на диски управляется с помощью format -e. (Использование файловой системы Solaris ZFS, при включеном кэшировании записи на диск, является безопасным, потому что она использует собственные команды сброса кэша на диск.)

  • На Windows, если параметр wal_sync_method установлен в open_datasync (по умолчанию), кэширование записи на диск может быть выключено, снятием галочки My Computer\Open\disk drive\Properties\Hardware\Properties\Policies\Enable write caching on the disk. В качестве альтернативы, можно установить параметр wal_sync_method в значение fsync или fsync_writethrough, что предотвращает кэширование записи.

  • На Mac OS X, кэширование записи может быть предотвращено с помощью установки параметра wal_sync_method в значение fsync_writethrough.

Новые модели SATA дисков (которые соответствуют стандарту ATAPI-6 или более позднему) предлагают команду сброса кэша на диск (FLUSH CACHE EXT), а SCSI диски уже давно поддерживают похожую команду SYNCHRONIZE CACHE. Эти команды недоступны из PostgreSQL напрямую, но некоторые файловые системы (например, ZFS, ext4), могут использовать их для сброса данных из кэша на пластины диска при включенном режиме кэширования write-back. К сожалению, такие файловые системы ведут себя неоптимально при комбинировании с батареей резервного питания (BBU) дискового контроллера. В таких случаях, команда синхронизации принуждает сохранять все данные на диск из кэша контроллера, сводя преимущество BBU к нулю. Вы можете запустить модуль pg_test_fsync, чтобы увидеть что вы попали в эту ситуацию. Если это так, преимущества производительности BBU могут быть восстановлены с помощью выключения барьеров записи (write barriers) для файловой системы или переконфигурирования контроллера диска, если это возможно. Если барьеры записи выключены, убедитесь, что батарея работает; сбой батареи может потенциально привести к потери данных. Есть надежда, что разработчики файловых систем и контроллеров дисков, в конце концов, устранят это неоптимальное поведение.

Когда операционная система отправляет запрос на запись к аппартаному обеспечению для хранения данных, она мало что может сделать, чтобы убедиться, что данные действительно сохраненны в какой-либо энергронезависимой области. Скорее, это является зоной ответственности администратора, убедиться в целостности данных на всех компонентах хранения. Избегайте дисковых контроллерв, которые не имеют батарей резервного питания для кэширования записи. На уровне диска, запретите режим кэширования write-back, если диск не может гарантировать, что данные будут записаны перед выключением. Если вы используете SSD, знайте, что многие их них по умолчанию не выполняют команды сброса кэша на диск. Вы можете протестировать надёжность поведение подсистемы ввода/вывода, используя diskchecker.pl.

Другой риск потери данных состоит в самой записи на пластины диска. Пластины диска разделяются на секторы, обычно по 512 байт каждый. Каждая операция физического чтения или записи обрабатывает целый сектор. Когда дисковый накопитель получает запрос на запись, он может соответствовать нескольким секторам по 512 байт (PostgreSQL обычно за один раз записывает 8192 байта или 16 секторов) и из-за отказа питания процесс записи может закончится неудачей в любое время, что означает, что некоторые из 512-байтовых секторов будут записаны, а некоторые нет. Чтобы защититься от таких сбоев, перед изменением фактической страницы на диске, PostgreSQL периодически записывает полные образы страниц на постоянное устройство хранения WAL. С помощью этого, во время восстановления после краха, PostgreSQL может восстановить из WAL страницы, которые записаны частично. Если у вас файловая система, которая защищена от частичнной записи страниц (например, ZFS), вы можете выключить работу с образами страниц, выключив параметр full_page_writes. Батарея резервного питания (BBU) контроллера диска не защищает от частичной записи страниц, если не гарантируется, что данные записаны в BBU как полные (8kB) страницы.

Back to top

(С) Виктор Вислобоков, 2008-2023