![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Тут пролетал запрос, возвращающий
dtm © (2003-09-23 17:51:00)
Уважаемые, напомните, плз. Вроде как его тут публиковал уважаемый Johnmen, но на тот момент я его скопировать не смог. Буду благодарен, если опубликуете его снова.
Zacho (2003-09-24 21:37:00) [1]
> kaif © (24.09.03 21:10) [47]
> Ты это сам придумал или есть хорошая книга (статья) о примерах
> использования разных параметров транзакций IB?
Единственная известная мне хорошая и подробная статья о транзакциях в IB - http://www.ibase.ru/devinfo/ibtrans.htmПравда, примера именно для такого использования SNAPSHOT TABLE STABILITY с явным резервированием таблицы protected write там вроде бы нет (и вообще с примерами не густо), но именно этой статьей я и руководствовался, когда понадобилось сделать "бездырочную" нумерацию.
kaif (2003-09-24 21:10:00) [2]
2 Zacho © (24.09.03 20:36) [46
Я уже как-то (и вроде даже не раз) приводил пример, как надо делать
Ни разу не читал об этом...
Век живи - век учись. Я никогда не использовал такие хитрые параметры транзакции...
consistency wait lock_write=<имя таблицы> exclusive
Мне это нравится. Конечно транзакция должна быть короткой. Но это как раз не проблема.
Ты это сам придумал или есть хорошая книга (статья) о примерах использования разных параметров транзакций IB? Я знал о существованиии режима wait lock write, но мне в голову не пришло использовать это для решения подобных задач с нумерацией...
Причем решение-то действительно классное!
Zacho (2003-09-24 20:36:00) [3]
> kaif © (24.09.03 20:18) [44]
Не надо так делать. Я уже как-то (и вроде даже не раз) приводил пример, как надо делать. Если кратко, то получение следующего номера (SELECT MAX(..)+1) и вставка записи - в отдельной короткой транзакции c параметрами consistency wait lock_write=<имя таблицы> exclusive. И не надо будет никаких циклов и обработок нарушений ПК.
kaif (2003-09-24 20:21:00) [4]
Пардон, в коде нужно в начале:
вместо NewN := QueryMaxN - 1
написать NewN := QueryMaxN + 1
kaif (2003-09-24 20:18:00) [5]
2 alex_raider © (24.09.03 19:40) [41]
А генерировать новый ID не на OnNewRecord, а в триггере BeforeInsert самой БД нельзя?
Тогда даже если юзер и отменит транзакцию(вставку документа), то номер не сгенерится.
Боюсь, сгенерится. Генераторы IB работают вне контекста транзакции, а триггеры - в контексте.
Так что при откате транзакции дырка все равно будет.
Вопрос в другом. На фиг вообще операции нумеровать? Если же эти номера имеют какое-то философское значение, то их нельзяуже менять и дырки от удалений (если таковые законодательством не возбраняются) обязаны будутприсуствовать. Если же кому-то в международных организациях или налоговых инспекциях не нравятся дырки, то причину этого странного явления нужно искать при помощи психоанализа З.Фрейда в их глубоком детстве или в арбитражном суде.
Если же просто хочется уменьшитькол-во дырок, возникающих из-за отката транзакций по вставке, то можно сделать какой-нибудь банальный код типа:
NewN := QueryMaxN - 1; //функция, возвращающая максимальный номер
//SELECT MAX(N) FROM TABLE1
while True do
try
DataSet.Edit;
DataSet.FieldByName("N").AsInteger := NewN;
DataSet.Post; //тут может вылететь на нарушении ключа
Transaction.CommitRetaining; //тут на еще каком конфликте
break;
except
NewN := NewN + 1; //пробуем следующий номер
end;
И никаких генераторов.
Генераторы использовать только для суррогатных ключей типа ID. Нумерация "без дырок" к таким ключам не относится, хотя поле N должно иметь уникальный индекс, который вызовет исключительную ситуацию в приведенном коде.
Решение может не самое быстрое, но практически приемлемое, ИМХО.
Правда сам я пока никогда так не делал :)
Но как-нибудь попробую.
MsGuns (2003-09-24 20:00:00) [6]
>dtm (24.09.03 18:28) [40]
Конечно, alex_raider © насчет неверной постановки всей задачи маненько загнул, но вот что действительно непонятно, так это твои попытки дергать генератор ДОвставки записи в таблицу (не путать с добавлением новой строки в грид).
Возможно, следует отказаться от редактирования данных в гриде, вынеся всю юзерскую активность в не DB-контролы в отд.панельке (или мод.форме), где и сделать кнопульки "Записать", "Отменить" и т.д. ?
alex_raider (2003-09-24 19:41:00) [7]
так что постановку задачи нужно пересмотреть :-)
alex_raider (2003-09-24 19:40:00) [8]
>Пользователь вызывают новую операцию, она должна уже на этапе >создания иметь уникальный номер - она его и имеет, получая от >генератор. Если пользователь отменил во время оформления >операцию - номер теряется, так как уже был сгенерирован. >Естественно, что в базе ничего не остаётся, так что >помечать "удалено, недоступно, заблокировано" просто нечего
А генерировать новый ID не на OnNewRecord, а в триггере BeforeInsert самой БД нельзя?
Тогда даже если юзер и отменит транзакцию(вставку документа), то номер не сгенерится.
Если вставил документ, а он не нужен, то
"САМ ДУРАК", все шито-крыто.
Короче, хочу подытожить,
резюме:
"Шаманство" с получением максимального номера -
есть дурной тон и его нужно избегать. Ты автоматически налетаешь на проблему с блокировками и транзакционностью (т.е. не safe для многопользовательской системы) и никак ее не избежишь, кроме как блокировкой таблицы в момент SELECT`a.
Я решал подобную задачу 4 года назад, правду тебе говорю :-)))
dtm (2003-09-24 18:28:00) [9]
Alex_Raider [32]
> У тебя сама постановка алгоритмики и способа решения неправильная.
>Следует сделать иначе - ничего не удалять,
а просто помечать записи(документы) как "удалено, недоступно, заблокировано".
;) Всё у меня правильно.
Пользователь вызывают новую операцию, она должна уже на этапе создания иметь уникальный номер - она его и имеет, получая от генератор. Если пользователь отменил во время оформления операцию - номер теряется, так как уже был сгенерирован. Естественно, что в базе ничего не остаётся, так что помечать "удалено, недоступно, заблокировано" просто нечего.
А есть ещё софтина, обрабатывающая информацию об операциях, поступающих из разных концов Беларуси, и по правилам ведения работы заказчика (а они определяются международной конвенцией) номера у документов должны быть по возможности последовательные, то есть без "дырок". Может, "дырки" всё равно будут, но для сертификации программы перед использованием я обязан вложить подобную функцию в программу. Иначе никак.
Так что не надо говорить, что кто-то поставил задачу неправильно...
Sandman25 (2003-09-24 16:12:00) [10]
:)
Alex_Raider (2003-09-24 16:01:00) [11]
>>Вы принципиальный сторонник отказа от оптимизации? Если >>клиента что-то не устраивает, пуст покупает четвертый винт и >>пятый процессор?
Нет, я сторонник здравого смысла.
:-)
Johnmen (2003-09-24 13:14:00) [12]
>MsGuns © (24.09.03 12:53)
Нет-нет-нет. Именно с теоретической. По-моему, "начальная дырка" это скорее всего "ближе к практике", если вообще тут можно о практике говорить... =o)
Sandman25 (2003-09-24 12:55:00) [13]
[34] Alex_Raider © (24.09.03 12:48)
Вы принципиальный сторонник отказа от оптимизации? Если клиента что-то не устраивает, пуст покупает четвертый винт и пятый процессор?
MsGuns (2003-09-24 12:53:00) [14]
>Johnmen © (24.09.03 11:43) [31]
Ты же сам говоришь, что это вопрос скорее теоретический и тут же принимаешься критиковать "начальную" дырку с чисто практической т.зр.
;))
Если же иметь в виду "вакантность" UID, то не вижу никакой разницы, откуда его выбирать, т.е. будет это 1 или 1001 - нет для физической модели БД никакой разницыДругими словами, мне больше по душе итоговая последовательность
1,2,3,56,57,58,59,101,102
нежели
56,57,58,59,60,61,62,101,102
Чисто эстетически.
Alex_Raider (2003-09-24 12:48:00) [15]
Каждому свое.
Извращайся до посинения,
если неспособен оценить трудоемкость/затраты решений.
А если хочешь экономить память и дисковое пространство - не используй версионники, C/S, и Windows вместе с Delphi.
Используй Zx Spectrum 48, все 49152 байта RAM твои...
Sandman25 (2003-09-24 12:31:00) [16]
>Следует сделать иначе - ничего не удалять,
а просто помечать записи(документы) как "удалено, недоступно, заблокировано".
Расходуется лишняя память, замедляется поиск и вставка записей.
Alex_Raider (2003-09-24 12:10:00) [17]
У тебя сама постановка алгоритмики и способа решения неправильная.
Следует сделать иначе - ничего не удалять,
а просто помечать записи(документы) как "удалено, недоступно, заблокировано".
И никаких "дырок" бы не появилось.
Вот так-то.
Johnmen (2003-09-24 11:43:00) [18]
Согласен с kaif ©, что рассматриваемый вопрос лежит не в плоскости практического применения, а с скорее в теоретической, не привязанной к реальным построениям систем.
А по поводу начальной дырки, так нет такого понятия. Поясню.
Есть интервал с дырками. Конечное значение интервала - максимальное значение ID. А вот минимальное почему же 0, или 1 ??? Вовсе нет. Минимальное - минимум ID. И никак иначе. В противном случае придем к нарушению понятия "дырки в интервале". По определению интервал не может начинаться с дырки.
Конечно можно считать минимумом 0 или 1. Но это уже искусственный частный случай.
И, конечно же, самое быстрое здесь это ХП.
(Не может быть, что я столько слов тут написал :))
>Sandman25 © (24.09.03 11:11)
Хороший запрос. И по идее, действительно, должен работать бастрее.
Посмотрел планы и того и другого. В общем, понятно, почему быстрее.
Val (2003-09-24 11:40:00) [19]
>Danilka © (24.09.03 11:25) [29]
:) на самом деле это - интервалы
Danilka (2003-09-24 11:25:00) [20]
Как говорил мне тесть "дыры, дырки и дырочки они у женщин, а это - отверстия".