База данных как API
Наткнулся на баг в Firebird: http://tracker.firebirdsql.org/browse/CORE-2848
В трекере написано, что исправлено (после перехода на 2.5.3 и backup/restore) но у меня продолжает появлятся, причем только в сложносочиненных условиях (нагруженные продакшены, с сотнями апдейтов в секунду и сотнями юзеров).
Сама по себе ошибка глобальных проблем не несет - у меня процессы умеют в самовосстановление после ошибок, но иногда то ли эта же ошибка, то ли что-то смежное в менеджере блокировок приводит к странному эффекту: один из процессов fb_inet_server.exe зависает, начиная бесконечно крутится, кушая CPU в цикле рекурсивных вызовов типа
"fb_inet_server!down_grade+0x62", в то время, как все остальные процессы ждут завершения этого, ничего не записывая и не читая. Если грохнуть кушающий процесс - все продолжает работать, накрывается только работа того коннекта, который обрабатывал зависший процесс.
Воспроизвести на столе пока не получается, если по хорошему, то надо бы дампы повисшего сервера, базы данных и блокировок спихнуть разработчикам на изучение.
Один из вариантов обойти ошибку (и заодно добавить новой полезной функциональности) на данный момент: сократить нагрузку на таблицу, на которой возникает проблема (в ней сотни раз в секунду выполняются update, и в это же время ее читают несколько десятков транзакций). Это можно сделать, если изменения таблицы в БД заменить на изменения на ее копии в памяти сервера приложений, в БД скидывать результат раз в 15-30 секунд (чтобы восстановить состояние сервиса при его рестарте).
Так вот, внезапно при такой переделке оказывается, что БД и конкретно эта таблица у нас играет роль API между десятком различных модулей, UI и разного рода сервисами.
Т.е. самый прямой вариант обмениваться данными между подсистемами, который работает всегда - это реляционная БД, с транзакциями, лаконичным SQL в качестве языка преобразования данных в нужный формат и заодно разного рода аудитом на триггерах, при необходимости.
А если я это перенесу в сервис приложений, то внезапно вместо 3 почти однообразных клиентских подключений к СУБД (дельфи-клиенты, .NET веб-сервис и clojure сервис-приложений), у меня появится необходимость взаимодействовать с сервером приложений через некий велосипедный протокол (скорее всего, что-нибудь на тему RESTful сервисов, они на CRUD хорошо укладываются). Или же придется во всю эту конструкцию еще и добавлять MQ сервис и тащить в продакшен или ActiveMQ (жаба в виде кложури уже есть) или RabbitMQ (тогда нашим инженерам придется осиливать эксплуатацию эрланговских приложений), потому что задача на очереди укладывается еще лучше чем на БД.
И поверх этого - разного рода костыли и велосипеды на предмет аудита, преобразований и расширения данных (вот например, чем заменить join на справочники, если у тебя вместо таблицы в БД - какая-то хреновина не пойми на каком языке, да еще не факт что подключенная к БД, а не получающая информацию из очередей).
В трекере написано, что исправлено (после перехода на 2.5.3 и backup/restore) но у меня продолжает появлятся, причем только в сложносочиненных условиях (нагруженные продакшены, с сотнями апдейтов в секунду и сотнями юзеров).
Сама по себе ошибка глобальных проблем не несет - у меня процессы умеют в самовосстановление после ошибок, но иногда то ли эта же ошибка, то ли что-то смежное в менеджере блокировок приводит к странному эффекту: один из процессов fb_inet_server.exe зависает, начиная бесконечно крутится, кушая CPU в цикле рекурсивных вызовов типа
"fb_inet_server!down_grade+0x62", в то время, как все остальные процессы ждут завершения этого, ничего не записывая и не читая. Если грохнуть кушающий процесс - все продолжает работать, накрывается только работа того коннекта, который обрабатывал зависший процесс.
Воспроизвести на столе пока не получается, если по хорошему, то надо бы дампы повисшего сервера, базы данных и блокировок спихнуть разработчикам на изучение.
Один из вариантов обойти ошибку (и заодно добавить новой полезной функциональности) на данный момент: сократить нагрузку на таблицу, на которой возникает проблема (в ней сотни раз в секунду выполняются update, и в это же время ее читают несколько десятков транзакций). Это можно сделать, если изменения таблицы в БД заменить на изменения на ее копии в памяти сервера приложений, в БД скидывать результат раз в 15-30 секунд (чтобы восстановить состояние сервиса при его рестарте).
Так вот, внезапно при такой переделке оказывается, что БД и конкретно эта таблица у нас играет роль API между десятком различных модулей, UI и разного рода сервисами.
Т.е. самый прямой вариант обмениваться данными между подсистемами, который работает всегда - это реляционная БД, с транзакциями, лаконичным SQL в качестве языка преобразования данных в нужный формат и заодно разного рода аудитом на триггерах, при необходимости.
А если я это перенесу в сервис приложений, то внезапно вместо 3 почти однообразных клиентских подключений к СУБД (дельфи-клиенты, .NET веб-сервис и clojure сервис-приложений), у меня появится необходимость взаимодействовать с сервером приложений через некий велосипедный протокол (скорее всего, что-нибудь на тему RESTful сервисов, они на CRUD хорошо укладываются). Или же придется во всю эту конструкцию еще и добавлять MQ сервис и тащить в продакшен или ActiveMQ (жаба в виде кложури уже есть) или RabbitMQ (тогда нашим инженерам придется осиливать эксплуатацию эрланговских приложений), потому что задача на очереди укладывается еще лучше чем на БД.
И поверх этого - разного рода костыли и велосипеды на предмет аудита, преобразований и расширения данных (вот например, чем заменить join на справочники, если у тебя вместо таблицы в БД - какая-то хреновина не пойми на каком языке, да еще не факт что подключенная к БД, а не получающая информацию из очередей).
no subject
Варианты:
1. Впихивать пока впихивается.
2. Искать движки, более подходящие под требуемое подмножество задач.
3. Писать ещё один, свой.
no subject
Это можно сделать, если изменения таблицы в БД заменить на изменения на ее копии в памяти сервера приложений, в БД скидывать результат раз в 15-30 секунд (чтобы восстановить состояние сервиса при его рестарте).
Если в firebird действительно критические баги, то лучше уж на постгрес переехать.
(no subject)
(no subject)
no subject
no subject
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
no subject
Апдейт таблицы заменить на апдейт вьюшки.
Сделать триггер перед апдейтом, который выполняет роль шейпера - например, делает инсерт в другую таблицу.
Сервис по тихой грусти переебашивает вьюшку и апдейтит исходную табличку.
(no subject)
no subject