Многопоточность серверного клиента FB2.5
Привет всем.
В FB2.5 реализация API стала защищенной в плане многопоточного использования в рамках одного подключения. Дословно:
The client libraries, including the embedded one, can now be used in multi-threaded applications without any application-level synchronization.
Тут возникает два риторических вопроса.
1. А это тестировалось?
Я имею в виду — «по-настоящему». Исходя из опыта работы с самим сервером (в процессе тестирования 2.5) — там с MT выплыло очень многое. К примеру, InMemory B+ дерево, которое меняло свое состояние при чтении и два читателя убивали сервер. Пользуясь случаем хочется передать привет Коле Самофатову.
Впрочем, с сервером в плане тестирования все понятно — у разработчиков есть (ведь правда — есть?) стрессовая система. Да и у нас тоже неплохая многопоточная страшилка для сервера. Этой страшилкой новейший IB2010 был завален без особых усилий. С FB2.5 на стареньком Q6600 — приходится реально попотеть. С FB2.5.1 наверное прийдется потеть кровью.
А вот с клиентом — непонятно. IBProvider самостоятельно выполняет всю необходимую синхронизацию, поэтому через него клиента особо то не потестишь. Ну, только если работу с разными подключениями. Что, фактически, и делается.
2. Ну и что?
Есть старые клиенты, где этой синхронизации нет.
Серверное API является «процедурно»-ориентированным. Все ресурсы представлены в виде дескрипторов. Новый fbclient.dll защищает именно дескрипторы. Но он защищает где? Внутри себя. А работа с ними (дескрипторами) состоит из двух этапов. Один — на верхнем уровне (скажем в компонентах доступа). А второй уровень — как раз в fbclient.dll. Любой, знакомый с принципами MT-синхронизации, понимает — защита должна распространяться на оба уровня. Чтобы не было так:
1. Поток 1. [USER] Транзакция_handle1 активна? Нет не, активна.
2. Поток 2. [USER] Транзакция_handle1 активна? Нет не, активна.
3. Поток 1. [ENTER in FBCLIENT] [MT-SAFE] Запуск транзакции_handle1
4. Поток 2. [ENTER in FBCLIENT] [MT-SAFE] Запуск транзакции_handle1
5. Поток 1. Все нормально.
6. Поток 2. Ошибка — транзакция_handle1 уже активна.
Навеяло
А зачем isc_start_transaction проверяет переданный (*tr_handle) на NULL?
Да вот как раз для этого и проверяет, чтобы не убить данные о другой транзакции, обслуживаемой этим дескриптором. Надо бы, конечно посмотреть — где именно он проверяем. До или после блокировки дескриптора. Но лень.
Навеяло2
По-злобному,
5.1 Поток1 [USER] Закрываем дескриптор транзации.
5.2 Поток1 [USER] Освобождаем память, в которой этой дескриптор хранился.
Так что… Пока API не станет
A. Самодостаточным. То есть, оно станет настолько совершенным, что ему высокоуровневые компоненты (второй слой) даром не нужны будут.
Б. Объектно-ориентированным. Это исключает появление болтающихся (на пользовательском уровне) дескрипторов.
обольщаться насчет 2.5 — не стоит. Синхронизация на уровне ваших любимых компонент доступа, работающих через ISC API, нужна. Правда, для полноценной MT-работы, одной только этой блокировки все равно не достаточно.
У FB.NET есть шанс удовлетворять обоим пунктам. Хотя, насколько я в курсе, его автор еще не дорос до мысли добавить MT-сихронизацию. По крайней мере, на его форуме мелькали сообщения о MT-проблемах. Да и у меня сомнения насчет совершенности интефейсов ADO.NET как таковых.
У Java-клиента — тоже. А может у него уже «все в шоколаде». Не в курсе абсолютно.
Немного позитива
Сейчас описание ошибок обращения к API стало хранится в TLS, а не в сетевом пакете. Это гуд, однозначно. Особенно для тех, кто в курсе, что конкретно это дает.
Хотя в IBProvider мы на это закладываться, скорее всего, не будем. Нет смысла … Хмм … По-моему, все таки заложились. В обработчике ошибок отмены текущей операции на сервере… Посмотрел. Ага, точно — заложились…. А может это мы заложились, а работает оно совсем по-другому …
Напоследок.
Строго между нами, девочками. IBProvider не только позволяет пользователю работать с одним подключением из разных потоков. Да он и сам это делает — в сервисном потоке пула запросов. Когда запускаешь тесты на VBS, которые заюзывают пул подключений, созерцание страницы потоков в ProcessExplorer-e просто завораживает. Главное, не пытаться думать «а что и как там конкретно сейчас работает» — может сорвать башню 🙂