Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Работаем с IB по сети [D5, IB6.x]


Страницы:   1 2

xmrz ©   (2003-05-27 00:22:00) 

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

/
SELECT ID FROM AUTOM WHERE (VIN = :VIN) AND (MODEL = :MODEL) INTO AID;

INSERT INTO DOC_POLICE (DATA,WHO_INS,SUMMA,OPERATION) VALUES (:INDATA,:INS,:SUMDAY,1);

SELECT MAX(ID) FROM DOC_POLICE WHERE (OPERATION=1) AND (WHO_INS=:INS) INTO PID;

INSERT INTO INOUT (IO_MOMENT,DATA,WHO_INS,FIO,AUTOM,OPERATION,DOC_ID)
VALUES (:MOMENT,:INDATA,:INS,:FIO,:AID,1,:PID);
\

В таблицах ID генерируются с помощью триггеров и генераторов BEFORE INSERT.
Таблицы - как видно имеют зависимости : ID из AUTOM и DOC_POLICE подставляются в INOUT.
Выполнение всех вышеперечисленных операций вызывается из одной процедуры, после вызова
процедуры клиентом сразу делается Transaction.Commit.
Опция ForcedWrites базы была выключена. Через какое-то время стали прооисходить сбои при
отключении эл. энергии, причём сервер не выключался, только клиенты. Сбои заключались в том, что
после возобновления питания в таблице INOUT записи вставленные с разных клиентов имели
один и тот же ID из табл. DOC_POLICE. А в DOC_POLICE оказывались 2 одинаковых ID, хотя по этому полю
создан уникальный индекс!
После включения ForcedWrites при сбоях с питанием таких вещей вроде не происходит, но зато безо всяких
на то причин стали появляться "пропуски" в таблицах DOC_POLICE и INOUT, т.е. триггер генерирует значения
вхолостую. Если бы я где то делал RollBack или где то во время выполнения ХП выскакивали Access Violation...
было бы всё понятно... В чём может быть причина, поделитесь пожалуйста своими соображениями.


Sergey13   (2003-05-27 11:44:00) [1]

2xmrz (27.05.03 11:13)
Если уж так важен номер без пропусков, то раздели в базе (и главное в голове) понятия ID и порядковый номер. Первое заполняется генератором и пропуски там пофигу. Второе можно обработать в тригере после вставки - проапдейтить поле номера как max(nomer)+1 с анализом того что такой номер уже может быть создан другим юзером. Для гарантии на номер тоже можно (нужно) повесить уникальность, особливо с признаком года, например, для нумерации по году.


Danilka   (2003-05-27 11:22:00) [2]

xmrz (27.05.03 11:13)
блокировка, max+1, запись и завершение транзакции - в одной процедуре, доли секунд, юзера и не заметят ничего.


Zacho   (2003-05-27 11:21:00) [3]


> xmrz (27.05.03 11:13)

Например, такой алгоритм.
После заполнения формы стартуется отдельная транзакция, в которой и происходит блокировка, получения номера и вставка данных. Если транзакция будет достаточно короткой, а операторов - не много, то может быть замедление работы будет практически незаметно.


xmrz   (2003-05-27 11:13:00) [4]

К сожалению блокировать таблицы нельзя, так как перед нажатием "Ok" при заполнении формы в Edit"ах и ComboBox"ах на onExit повешаны небольшие запросы, помогающие оператору заполнить форму и контролирующие некоторые параметры по бизнес-логике (для отлова попыток мошенничества) эти запросы тоже выполняются из ХП и возращают по 1..6 значений, но читают они из тех же таблиц. А если заблокировать таблицы на чтение, то работа грозит превратиться действительно в "однопользовательскую"?


Danilka   (2003-05-27 11:04:00) [5]

xmrz (27.05.03 10:59)
тогда, вероятно, только вот этот вариант:
Zacho © (27.05.03 10:59)

стартовать транзакцию, вставлять данные и завершать транзакцию в одной процедуре, перед печатью.


xmrz   (2003-05-27 10:59:00) [6]

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


Zacho   (2003-05-27 10:59:00) [7]


> xmrz (27.05.03 10:47)

Если нужна автоматически генерируемая последовательность номеров без пропусков, то сделать это можно следующим образом:
Стартуем транзакцию. При созданием нового документа блокируем таблицу (в том числе на чтение). Получаем MAX(ID)+1. Создаем документ, INSERT, Commit.
Естественно, редактировать номера и удалять документы - запрещаем.
Недостаток: это практически "однопользовательский" режим работы. При интенсивной работе нескольких операторов возможны приличные торможения. Задержки можно свести к минимуму, если получать номер непосредственно перед вставкой, в как можно более короткой транзакции.


Danilka   (2003-05-27 10:49:00) [8]

xmrz (27.05.03 10:47)
а когда нужна эта гарантированая последовательность?
если для отчетов, то ее можно генерировать во время отчета.
честно говоря, не знаю, в остальном чем могут помешать пропуски.


xmrz   (2003-05-27 10:47:00) [9]

Проблема возникла именно в пик работы операторов. Так что на select Max(ID) .. надеяться особо не приходится


Danilka   (2003-05-27 10:42:00) [10]

xmrz (27.05.03 10:38)
Вообще-то гарантированая последовательность номеров нужна только юзерам, в любых других случаях можно обойтись. Пусть они этим и занимаются. :))
А Max(ID) - очень вероятен глюк на нескольких пользователях, когда два или больше юзеров сделали max(id) в транзакциях, стартовавших примерно в одно время.


Alexandr   (2003-05-27 10:40:00) [11]

по разному можно в зависимости от задачи и от необходимости


xmrz   (2003-05-27 10:38:00) [12]

Тогда может порекомендуете механизм гарантирующий генерацию последовательных номеров? Использовать select Max(ID) ...?


Alexandr   (2003-05-27 10:33:00) [13]

какую проблему?


Danilka   (2003-05-27 10:33:00) [14]

xmrz (27.05.03 10:25)
Два раза уже сказал Alexandr ©, скажу третий раз: не надо привязываться к значениям генератора. Это не его задача.


xmrz   (2003-05-27 10:25:00) [15]

Что сможет решить эту проблему в принципе? Переход на трёхзвенную сруктуру? Кусок клиента отвечающий за запуск процедур вынести на сервер? Не работал раньше с Midas, даже страшно как то... :(


Alexandr   (2003-05-27 10:16:00) [16]

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

Да и вот еще. Если процедуру вызываешь на клиенте и спользуешь IBX , то возможен при определенных обстоятельствах двукратный вызов процедуры.


xmrz   (2003-05-27 10:12:00) [17]

> Alexandr © (27.05.03 09:55)

Я и сам сначала подумал про питание, но всвязи с тем что имею возможность реально следить за временем понимаю что искать ошибку надо в другом месте. Поэтому и решил обратиться за помощью к людям :)
А если теоретически предположить что запросы от двух клиентов пришли одновременно? Процедура ведь тяжёлая, UDF используются?

Ну хоть какие нибудь идеи?!


Alexandr   (2003-05-27 09:55:00) [18]

не бывает так.
ну не может генератор сам увеличиться...


xmrz   (2003-05-27 09:46:00) [19]

1) Генераторы получают новые значения автоматически при вставке новой записи:

SET TERM ^ ;
CREATE TRIGGER SET_INOUT_ID FOR INOUT
BEFORE INSERT AS
BEGIN
NEW.ID = GEN_ID(INOUT_GEN, 1);
END^
SET TERM ;^

2) Питание на тот момент не выключалось. Я слежу за временем, когда выполняются операции в IO_MOMENT


Danilka   (2003-05-27 09:37:00) [20]

гы, может я глючу, но в упор не вижу где здесь дергается генератор.
даже поиск по gen_id делал...


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо