Примерно 20 лет назад была установлена СУБД Firebird, если не ошибаюсь, версии 1.0.3, на сегодняшний день база все еще жива и нужна, размер ее перевалил за 30ГБ, что по сегодняшним меркам очень мало, но и основной рост базы пришелся на начало века.

С повсеместным внедрением средств мониторинга захотелось снимать минимальную статистику и определять работоспособность СУБД и самой БД. Для мониторинга использую Zabbix установленный на Ubuntu 20.04 LTS, а сама СУБД находится на виртуальной машине с Windows 2008 Server. Версии на которых был использован метод мониторинга описанный ниже для СУБД Firebird 2.5.9, версия Zabbix 6.0. Но думаю что и с другими версиями проблем быть не должно.

Даная статья не ставит целью описать процесс установки СУБД Firebird, к слову он очень прост, или средства мониторинга Zabbix, эта статья покажет как за минимальное время можно "завести" СУБД Firebird в Zabbix, получать необходимые данные для мониторинга и реакции на сбои.

Первое что необходимо сделать это вспомнить о isql.exe который фактически является CLI для FB. Был написан небольшой скрипт которые достаёт данные из заранее подготовленной вьюшки MONITORING, которая в свою очередь собирает данные из таблиц мониторинга СУБД.

CREATE OR ALTER VIEW MONITORING(
    "Database_Name", "Page_Size", "ODS_Version", "Oldest_Tr",
    "Oldest_Active_Tr", "Oldest_Snapshot_Tr",
    "Next_Tr", "Page_Buffers", "SQL_Dialect",
    "Shutdown_Mode", "Sweep_Interval",
    "Read_Only", "Forced_Writes", "Reserve_Space",
    "Created_At", "Pages",
    "Size_MB", "Backup_State", "Nonindexed_Reads",
    "Indexed_Reads", "Records_Inserted",
    "Records_Updated", "Records_Deleted",
    "Records_Backed_Out", "Records_Purged",
    "Records_Expunged", "Page_Reads", "Page_Writes",
    "Page_Fetches", "Page_Marks", "Connections",
    "Stat group")
AS
SELECT
       db.mon$database_name,
       db.mon$page_size,
       db.mon$ods_major || '.' || db.mon$ods_minor,
       db.mon$oldest_transaction, db.mon$oldest_active,
       db.mon$oldest_snapshot, db.mon$next_transaction,
       db.mon$page_buffers, db.mon$sql_dialect,
       db.mon$shutdown_mode, db.mon$sweep_interval,
       db.mon$read_only, db.mon$forced_writes,
       db.mon$reserve_space, db.mon$creation_date,
       db.mon$pages,
       cast((db.mon$pages * db.mon$page_size / 1024.00 / 1024.00) as numeric(18,2)),
       db.mon$backup_state, r.mon$record_seq_reads,
       r.mon$record_idx_reads, r.mon$record_inserts,
       r.mon$record_updates, r.mon$record_deletes,
       r.mon$record_backouts, r.mon$record_purges,
       r.mon$record_expunges, io.mon$page_reads,
       io.mon$page_writes, io.mon$page_fetches,
       io.mon$page_marks,
       (select count(*) from mon$attachments),
       r.mon$stat_group
FROM mon$database db
left join mon$record_stats r on (db.mon$stat_id = r.mon$stat_id)
left join mon$io_stats io on (db.mon$stat_id = io.mon$stat_id)

Скрипт isql.cmd запрашивающий данные от СУБД выглядит так:

C:\Program Files\Firebird\Firebird_2_5\bin\isql.exe" -q -i "C:\zabbix\isql.sql

А сам SQL запрос isql.sql которрый "скармливается" isql.exe так:

CONNECT 'localhost:employee' user 'SYSDBA' password 'masterkey';
SET list on;
SELECT * FROM MONITORING;
EXIT;

Данный скрипт примечателен только выражением "SET list on", которое в дальнейшем упрощает разбор данных регулярными выражениями, т.к. предоставляет данные списком, а не таблицей.

В итоге после отработки скрипта получаем данные которые предоставила СУБД, а точнее строку приготовленной ранее вьюшки:

Результат работы isql.exe
Результат работы isql.exe

Теперь эти данные нужно передать в Zabbix. Передавать будем используя конфигурационный файл агента, а именно параметр UserParameter, выглядит это примерно так:

UserParameter=FirebirdData,C:\zabbix\isql.cmd

При запущенном агенте, сервер Zabbix сможет получать и обрабатывать эти данные. Нужно только немного ему в этом помочь, а именно определить новый шаблон, разметить с помощью регулярных выражений необходимые данные, настроить триггеры и графики.

Создаем новый шаблон и не забываем привязать этот шаблон к узлу на котором расположена СУБД:

Создание шаблона
Создание шаблона

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

Список готовых элементов данных
Список готовых элементов данных

Основной элемент данных, от которого зависят все остальные элементы это FirebirdData, это текст который передает агент Zabbix:

Элемент данных содержащий таблицу для разбора
Элемент данных содержащий таблицу для разбора

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

Элемент данных
Элемент данных
Предобработка элемента данных
Предобработка элемента данных

Перечислять все элементы данных нет необходимости они все очень похожи и отличаются только предобработкой. Какие-то параметры целочисленные, какие-то дробные или текстовые.

Теперь на основе имеющихся данных можно создать триггеры. Первый из триггеров будет определять, доступны ли данные о БД:

Триггер nodata
Триггер nodata

Определять в каком состоянии БД:

Триггер shutdown
Триггер shutdown

Ну и разницу между текущей транзакцией и OIT, что для версионных БД важно:

Триггер OIT
Триггер OIT

Можно "вытащить" из БД больше данных, собрать информацию по индексам или таблицам, но у меня в этом нет необходимости.

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

Графики мониторинга
Графики мониторинга

Здесь все достаточно просто, первый график показывает количество чтений из БД, второй операции удаления, обновления и создания, а последний показывает отставание OIT.

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

Комментарии (11)


  1. Naves
    20.04.2022 15:34
    +3

    1) а если на сервере несколько БД? у вас же жестко прописано, хотя бы в макрос на уровне хоста в заббиксе нужно перенести

    2) жестко прописанный пароль в скрипте? не надо так

    Мой вариант с использованием discovery, правда под линукс

    userparameter_firebird.conf

    UserParameter=firebird.stats_db[*],/etc/zabbix/scripts/firebird_stats.sh $1
    UserParameter=firebird.discovery_db,cat /var/zabbix/firebird_db.txt | awk 'BEGIN{printf "{\"data\":["}; {printf c"{\"{#DB}\":\""$0"\" }";c=", "}; END{print "]}"}'

    firebird_stats.sh

    #!/usr/bin/env bash
    
    SCRIPT_DIR=$(dirname "$0")
    
    . $SCRIPT_DIR/firebird_user.conf
    
    db=$1
    #"127.0.0.1:/data/database.fdb"
    #echo $db
    
    isql-fb -ch utf8 -user $ISC_USER -pass $ISC_PASSWORD -i $SCRIPT_DIR/firebird_stats.sql $db | egrep -v "RESULT|=="

    firebird_stats.sql, запрос сразу выдает все данные в одном столбце в json-формате

    SELECT
        '{' ||
           '"pages":'        || db.mon$pages ||','||
           '"page_buffers":' || mon$page_buffers ||','||
           '"db_size":'   || (db.mon$pages * db.mon$page_size ) ||','||
           '"seq_reads":' || r.mon$record_seq_reads ||','||
           '"idx_reads":' || r.mon$record_idx_reads ||','||
           '"record_inserts":'  ||r.mon$record_inserts ||','||
           '"record_updates":'  ||r.mon$record_updates ||','||
           '"record_deletes":'  ||r.mon$record_deletes  ||','||
           '"record_backouts":' ||r.mon$record_backouts ||','||
           '"record_purges":'   ||r.mon$record_purges   ||','||
           '"record_expunges":' ||r.mon$record_expunges ||','||
           '"record_locks":'    ||r.mon$record_locks    ||','||
           '"record_waits":'    ||r.mon$record_waits    ||','||
           '"record_conflicts":'||r.mon$record_conflicts||','||
           '"page_reads":'  ||io.mon$page_reads   ||','||
           '"page_writes":' ||io.mon$page_writes  ||','||
           '"page_fetches":'||io.mon$page_fetches ||','||
           '"page_marks":'  ||io.mon$page_marks ||','||
           '"connections":' ||(select count(*) from mon$attachments) ||','||
           '"memory_used":'      ||mem.mon$memory_used ||','||
           '"memory_allocated":' ||mem.mon$memory_allocated ||','||
           '"max_memory_used":'      ||mem.mon$max_memory_used ||','||
           '"max_memory_allocated":' ||mem.mon$max_memory_allocated ||
        '}' as result
        FROM mon$database db
        left join mon$record_stats r on (db.mon$stat_id = r.mon$stat_id)
        left join mon$io_stats io on (db.mon$stat_id = io.mon$stat_id)
        left join mon$memory_usage mem on (db.mon$stat_id = mem.mon$stat_id);

    для каждого хоста соответственно свои содержимое firebird_user.conf

    ISC_USER=sysdba
    ISC_PASSWORD=masterkey

    /var/zabbix/firebird_db.txt

    127.0.0.1:/data/database/db.fdb
    127.0.0.1:/data/database/tab.fdb
    127.0.0.1:/data/database/tab_test.fdb


    1. konstsch Автор
      20.04.2022 20:14

      Согласен что с дискавери будет интереснее если баз много. На счет логина и пароля все конечно же так, естественно их лучше вывести в окружение, но тогда ради этих же целей нужно использовать алиасы а не пути к бд как у вас. И не очень понял зачем тут json?


      1. Naves
        20.04.2022 21:37

        1) несколько алиасов или полных путей, разницы нет же. Ну и плюс возможность получать инфу из баз с других хостов. Бывает иногда и такое.

        127.0.0.1:baza1
        127.0.0.1:baza2

        2) json считается более правильным форматом для последующего парсинга. В общем и целом дело вкуса. Кто-то привык все значения и через регулярки получать.


  1. socketpair
    20.04.2022 21:30

    Меня одного смущает адовая окаменелость не только данной бд, но и заббикса, 2008 винды и вообще факт работы БД в винде? Убунта кстати тоже старая. Зачем так ?


    1. konstsch Автор
      20.04.2022 22:32

      Убунту старая? Припомните когда вышла следующая LTS версия после 20ой? А забикс очень любит именно LTS и не только забикс. Чем вам не нравится "винда" и FB?


      1. socketpair
        21.04.2022 18:56

        Да, старая. Два года, Карл. "Любит" что это за термин. Если заббикс не работает в современной ОС, то это проблема заббикса. Винда как сервер баз данных (кроме MS SQL) это извращение. Удивительно чтоб вообще работает. Ну а что до FB - я просто ослеп на неделю когда увидел его исходники (ибо пришлось дебажить баги в нём). Ну и подходы у него доставляющие во всех местах. А так - наелся я дерьма с ним. И нет, не не осилил. Осилил. Именно что. Больше не хочу.


        1. konstsch Автор
          21.04.2022 23:09
          +1

          Думаю многим будет интересно как вы "дебажили баги", запилите статью на обозрение.


    1. x25team
      22.04.2022 11:34

      Автор же сказал, что базе уже более 20 лет. Переносить её на новые платформы никто не собирается видимо, но пока еще пользуются.


  1. hbrsck
    21.04.2022 10:07

    С nodata аккуратней будьте. Если элемент станет неподдерживаемый или хост недоступный, этот триггер сработает.


    1. konstsch Автор
      21.04.2022 23:07

      Триггер сработает это лучше чем если промолчит, как бывало с ping


      1. hbrsck
        21.04.2022 23:11

        Можно навесить зависимость, тогда не будет гирляндой моргать.