Как отследить отключение пользователя от сервера Firebird
Как отследить отключение пользователя от сервера Firebird
Можно ли на уровне сервера Firebird 1.5 отследить момент отключения пользователя от БД и выполнить какие-либо действия, например, запустить хранимую процедуру?
процедуру выполнить нельзя, потому что все действия выполняются только в контексте пользовательских транзакций. а если пользователь отключается, то ... Он, собственно, вообще может не стартовать никаких транзакций.
Есть возможность через ibconsvc, она в лог или ext table пишет коннекты-дисконнекты, причем дисконнекты штатные или обрывы.
на след неделе выложу обновленный вариант.
Есть возможность через ibconsvc, она в лог или ext table пишет коннекты-дисконнекты, причем дисконнекты штатные или обрывы.
на след неделе выложу обновленный вариант.
Меня интересуют именно обрывы. Т.к. я делал блокировку записей почти аналогично второму варианту, предложенному в статье Пессимистическая блокировка записей в SQL. Но после нештатных ситуаций (зависание компьютера, сбои питания) в таблице останется информация о блокировке.
Как альтернативу решения этого вопроса можно сделать дополнительную программку, которая будет постоянно запущена на машине с сервером БД и должна проверять, подтвердила ли пользовательская программа свое соединение с БД обновив информацию о времени. Если разница между временем последнего подтверждения и текущим временем превышает допустимый предел, то значит пользователь, установивший блокировку, аварийно отключился и информацию о нем надо удалить.
Но может это можно сделать по другому?
Как альтернативу решения этого вопроса можно сделать дополнительную программку, которая будет постоянно запущена на машине с сервером БД и должна проверять, подтвердила ли пользовательская программа свое соединение с БД обновив информацию о времени. Если разница между временем последнего подтверждения и текущим временем превышает допустимый предел, то значит пользователь, установивший блокировку, аварийно отключился и информацию о нем надо удалить.
Но может это можно сделать по другому?
"информация о блокировке" при нормальной сети, даже при обрывах должна храниться не больше времени Connection_timeout, т.е. 3х минут (180 сек). Если сервер не в состоянии определить дисконнект клиента, то ты ничем не сможешь "разблокировать" записи, если только это не Classic (убить процесс, который запущен этим клиентом).
"Второй способ" как раз и приводит к таким проблемам, для которых не видно "красивого" решения.
Я делал по "первому способу". Что тебе в нем не нравится ?
Отсутствие информации о юзере, редактирующем документ ?
Я делал так:
1. Добавил по одному полю (назвал его Locker) к каждому документу (т.е. к соотв. таблице).
2. Создал простенькую табличку LockDoc с одним полем DocNum. Его же сделал ПК.
Тут надо, правда, отметить, что нумерация (ПК) у всех типов документов у меня в базе сквозная, т.е. нет никаких (каких бы то ни было) документов с одним номером. Но, думаю, это преодолимо.
3. При начале редактирования первым делом пытаемся вставить в таблицу LockDoc номер редактируемого документа. Если такой номер там уже есть, (это значит, что его кто-то уже редактирует), то получим нарушение ограничения ПК. Обрабатываем это исключение на клиенте, сообщая ему, что юзер такой-то уже начал изменять документ (о имени юзера см. следующий пункт).
4. Если вставка номера в таблицу LockDoc прошла успешно, то:
4.1. Транзакцию на обновление LockDoc оставляем открытой до конца редактирования документа.
4.2. В поле редактируемого документа Locker вписываем USER и завершаем эту транзакцию (для того, чтобы это имя можно было потом прочитать).
Если конкурирующий юзер нарвется на невозможность начать редактирования документа, то формируется запрос к этому документу, откуда мы и получим имя юзера - "блокировщика".
5. После окончания редактирования документа откатываем транзакцию для таблицы Locker (т.е. убираем от-туда номер заблокированного документа. Для тех, кто видит в откате плохой тон, можно Commit - Delete - Commit).
В отредактированном документе имя юзера в поле LockDoc просто оставляем - оно никому не мешает.
И не надо никаких дополнительных прог. Я к этому весьма стремился.
Я делал по "первому способу". Что тебе в нем не нравится ?
Отсутствие информации о юзере, редактирующем документ ?
Я делал так:
1. Добавил по одному полю (назвал его Locker) к каждому документу (т.е. к соотв. таблице).
2. Создал простенькую табличку LockDoc с одним полем DocNum. Его же сделал ПК.
Тут надо, правда, отметить, что нумерация (ПК) у всех типов документов у меня в базе сквозная, т.е. нет никаких (каких бы то ни было) документов с одним номером. Но, думаю, это преодолимо.
3. При начале редактирования первым делом пытаемся вставить в таблицу LockDoc номер редактируемого документа. Если такой номер там уже есть, (это значит, что его кто-то уже редактирует), то получим нарушение ограничения ПК. Обрабатываем это исключение на клиенте, сообщая ему, что юзер такой-то уже начал изменять документ (о имени юзера см. следующий пункт).
4. Если вставка номера в таблицу LockDoc прошла успешно, то:
4.1. Транзакцию на обновление LockDoc оставляем открытой до конца редактирования документа.
4.2. В поле редактируемого документа Locker вписываем USER и завершаем эту транзакцию (для того, чтобы это имя можно было потом прочитать).
Если конкурирующий юзер нарвется на невозможность начать редактирования документа, то формируется запрос к этому документу, откуда мы и получим имя юзера - "блокировщика".
5. После окончания редактирования документа откатываем транзакцию для таблицы Locker (т.е. убираем от-туда номер заблокированного документа. Для тех, кто видит в откате плохой тон, можно Commit - Delete - Commit).
В отредактированном документе имя юзера в поле LockDoc просто оставляем - оно никому не мешает.
И не надо никаких дополнительных прог. Я к этому весьма стремился.