Форум: "Базы";
Текущий архив: 2004.06.06;
Скачать: [xml.tar.bz2];
ВнизФундаментальный вопрос о правильном использовании транзакций. Найти похожие ветки
← →
Курдль © (2004-05-13 10:47) [0]После плодотворного общения на этом уважаемом форуме у меня сложилась стойкая ассоциация, что транзакция, это такая большая ручка от чемодана, которую прилепляют к багажнику "Жигулей", чтобы они ездили, как "Феррари" (еще ее называют спойлером).
Есть предложение раз и навсегда выработать общие рекомендации по работе с транзакциями и вынести результат куда-нить в ФАК.
У меня есть свой стиль, который я ни в коем случае никому не навязываю. Но очень хотел бы почитать всеобщую критическую оценку.
1. Я работаю только с кэшированными изменениями.
2. После работы с набором данных фиксирую обновления.
3. В 90% случаев не пользуюсь явными транзакциями, а просто делаю ApplyUpdates.
4. Пользуюсь явными транзакциями лишь в тех случаях, когда требуется откат изменений, сделанных во множественных таблицах со сложными связями.
5. Как правило код фиксации при такой работе занимает 5-10 строк.
У кого есть другие мнения? Может напишем общий "манифест о транзакциях"? Было бы здорово...
← →
asp © (2004-05-13 10:54) [1]С пунктом 3 у меня возникали сложности с тем, что BDE оставляло курсоры открытыми, что в многопользовательском режиме не есть хорошо. Другого способа как объявить явную транзакцию с параметром Database"а SQLPASSTHRU MODE=SHARED AUTOCOMMIT не нашел. (Возможно, мало искал.)
Работа в связке Client - BDE - DB2.
← →
Курдль © (2004-05-13 11:08) [2]Вот общий для IB, MSSQL, Sybase, Oracle (проверенный) код фиксации изменений, для наглядности выполненный на компонентах, надежно поддерживающих связь с перечисленными БД через ODBC:
procedure TForm1.SaveData;
begin
try
SDQuery1.CheckBrowseMode;
DB.ApplyUpdates([SDQuery1]);
except
on E: EDataBaseError do
Application.MessageBox(PChar(E.Message), "Ошибка записи", MB_ICONSTOP);
end;
end;
Вот и все! И никаких кодов для "onPost/onInsert" и т.п.
Хотелось бы посмотреть аналоги этого кода для других компонентов, например от мастеров IB-компонентов.
← →
Курдль © (2004-05-13 11:14) [3]
> Работа в связке Client - BDE - DB2.
К сожалению, ничего не могу сказать про BDE, т.к. политика фирм, в которых я работал на протяжении долгих лет, категорически запрещала их использование.
← →
bushmen © (2004-05-13 11:14) [4]>И никаких кодов для "onPost/onInsert"
На эти события вешаются не только commit"ы. Так что говорить о том, что НИКАКИХ КОДОВ я бы не стал.
← →
Курдль © (2004-05-13 11:16) [5]
> На эти события вешаются не только commit"ы. Так что говорить
> о том, что НИКАКИХ КОДОВ я бы не стал.
Это я в сердцах о коде из http://delphimaster.net/view/3-1084428403/
← →
Johnmen © (2004-05-13 11:25) [6]>Курдль ©
Ну опять же... Какое отношение имеет кеширование к управлению транзакциями ?
>В 90% случаев не пользуюсь явными транзакциями, а просто делаю ApplyUpdates.
Опять же. ApplyUpdates это конкретный метод конкретного класса. Для одного - это одно, для др. - другое. Причем он здесь ?
>Хотелось бы посмотреть ...
Вот из одного проекта (по поводу обращения с кешированными изменениями)...
with ...,pFIBDSReceiptsDetailR do begin;
...
if pFIBDSReceiptsR.State in dsEditModes then pFIBDSReceiptsR.Post;
UpdateTransaction.StartTransaction;
try
pFIBDSReceiptsR.ApplyUpdToBase; ApplyUpdToBase;
UpdateTransaction.Commit;
pFIBDSReceiptsR.CommitUpdToCach; CommitUpdToCach;
...
except
UpdateTransaction.Rollback;
pFIBDSReceiptsR.CancelUpdates; CancelUpdates;
ShowDlgMssg(Error,"Изменения не могут быть приняты !");
end;
...
← →
Курдль © (2004-05-13 11:32) [7]Posts pending cached updates for specified datasets to the database server.
procedure ApplyUpdates(const DataSets: array ofTDBDataSet);
Description
Call ApplyUpdates to post pending cached updates for a specific set of open datasets to the database server. ApplyUpdates is only meaningful if the CachedUpdates property of a specified dataset is True.
DataSets is a list of dataset names specifying the datasets for which to post pending updates. DataSets need not list every currently open dataset. For each listed dataset ApplyUpdates calls the dataset’s ApplyUpdates and CommitUpdates methods to post that dataset’s pending cached updates.
Applying updates is a two-phase process that takes place within the context of the database component’s transaction control. When an application calls ApplyUpdates, the following events take place:
1 A database transaction starts.
2 Cached updates are written to the database (Phase 1).
If the database write is successful:
1 Database changes are committed, ending the transaction.
2 Cached updates are committed, clearing the internal cache buffer (Phase 2).
If the database write fails database changes are rolled back, ending the transaction.
The two-phased approach allows for effective error recovery, especially when updating multiple and interrelated datasets (for example, the datasets associated with a master/detail form).
← →
Соловьев © (2004-05-13 11:32) [8]
> которую прилепляют к багажнику "Жигулей", чтобы они ездили,
> как "Феррари"
перешел с Фокса наверное? Транзакции не для скорости, а для правильности :)
Что будет с твоими кешированными изменениями, если допустим комп погаснет?
← →
Курдль © (2004-05-13 11:37) [9]
> Что будет с твоими кешированными изменениями, если допустим
> комп погаснет?
А что будет с документами Ворда, книгами Ёкселя, моделями Дизайнера и т.п.?
Кроме того, я давно не писал прог, где юзерам дается возможность сидеть и колбасить целые таблицы - все строго на формах ввода.
Одна запись - одно формализованное окно.
← →
Johnmen © (2004-05-13 11:40) [10]И что ? Ты не слышишь или не понимаешь, что говорят ? М.б. так понятней (в твоём стиле):
Writes a dataset’s pending cached updates to the database.
procedure ApplyUpdates;
Description
Call ApplyUpdates to write a dataset’s pending cached updates to a database. This method passes cached data to the database for storage, but the changes are not committed to the database. An application must explicitly call the database component’s Commit method to commit the changes to the database if the write is successful, or call the database’s Rollback method to undo the changes if there is an error.
Following a successful write to the database, and following a successful call to the database’s Commit method, an application should call the CommitUpdates method to clear the cached update buffer.
Note: The preferred method for updating datasets is to call a database component’s ApplyUpdates method rather than to call each individual dataset’s ApplyUpdates method. The database component’s ApplyUpdates method takes care of committing and rolling back transactions and clearing the cache when the operation is successful.
← →
Соловьев © (2004-05-13 11:41) [11]
> А что будет с документами Ворда, книгами Ёкселя, моделями
> Дизайнера и т.п.?
Это тут причем?
Мы же про БД разговариваем? Если ты транзакцию подтвердил, то данные уже физ. записаны на серваке, а кеш? кеш в памяти - и кранты... Пользователи в шоке - пол дня в урну :) А ты получишь по голове.
← →
Vlad © (2004-05-13 11:44) [12]
> Курдль © (13.05.04 11:37) [9]
По поводу кэшированных изменений.
Судя по всему, ты говоришь только о работе с InterBase и компонентами IBX(FIB). Там, как мы уже выяснили, смешаны механизмы транзакций и кэшированных изменений.
Если уж ты хочешь чтобы твои постулаты были вынесены в FAQ, как общие рекомендации по работе с транзакциями (а не к конкретной БД), то не надо сюда приплетать кэшированные изменения
← →
Johnmen © (2004-05-13 11:51) [13]>Vlad © (13.05.04 11:44) [12]
>Судя по всему, ты говоришь только о работе с InterBase и
>компонентами IBX(FIB).
А вот судя по выдернотому им тексту из хелпа - BDE
:)))
← →
Vlad © (2004-05-13 12:15) [14]
> Johnmen © (13.05.04 11:51) [13]
Да, я тут глянул BDE-шный метод ApplyUpdates также вызывает Commit транзакции.
Но правда это не дает повода обсуждать правильную работу с транзакциями и приплетать сюда кэшированные изменения.
В случае с БДЕ мне неясно другое. Ведь в БДЕ-алиасе есть явная настройка коммитов, т.е. можно указать - делать коммит автоматически или оставить его на совести разработчика.
А тут получается, что коммит выполняется независимо от этой настройки ? Как это понимать ?
← →
Курдль © (2004-05-13 12:17) [15]
> Johnmen © (13.05.04 11:40) [10]
> И что ? Ты не слышишь или не понимаешь, что говорят ? М.б.
> так понятней (в твоём стиле):
Давай конструктивнее! Что именно не соответствует моим постулатам? В родном хэлпе и, напр., в книге "Делфи и приложения БД" (с) Шумаков П.В. [*] написано одно и то же про транзакции и кэшированные изменения (это к вопросу: "Ну опять же... Какое отношение имеет кеширование к управлению транзакциями ?").
> Vlad © (13.05.04 11:44) [12]
> По поводу кэшированных изменений.
> Судя по всему, ты говоришь только о работе с InterBase и
> компонентами IBX(FIB).
Вообще-то я говорил как раз о том, что не силен в указанных тобой компонентах. Лейтмотив моего "выступления" - это моё личное убеждение, что связка "кэшированные изменения + неявная транзакция по ApplyUpdates" - самый оптимальный вариант организации обмена данными с БД.
← →
Курдль © (2004-05-13 12:20) [16]
> А тут получается, что коммит выполняется независимо от этой
> настройки ? Как это понимать ?
Как раз в [*] говорится про то, Commit автоматом вызывается лишь при SHARED AUTOCOMMIT.
← →
Vlad © (2004-05-13 12:23) [17]
> Курдль © (13.05.04 12:17) [15]
> самый оптимальный вариант организации обмена данными с БД.
Так ты почитай заголовок своей ветки, а так же то, что ты писал про "манифесты о транзакциях"
Как это вяжется вот с этим:
> моё личное убеждение, что связка "кэшированные изменения
> + неявная транзакция по ApplyUpdates" - самый оптимальный
> вариант организации обмена данными с БД
Ты определись, о чем ты говоришь - об оптимальном обмене данными с БД или все-таки конкретно о работе с транзакциями ?
Кстати, если уж на то пошло, то связка "кэшированные изменения + неявная транзакция по ApplyUpdates" - далеко не всегда оптимальный вариант обмена данными
← →
Vlad © (2004-05-13 12:27) [18]
> Как раз в [*] говорится про то, Commit автоматом вызывается
> лишь при SHARED AUTOCOMMIT.
Что такое [*] ?
Ты исходники почитай. ApplyUpdates вызывает безусловный коммит, независимо не от каких настроек.
← →
Курдль © (2004-05-13 12:29) [19]
> Ты определись, о чем ты говоришь - об оптимальном обмене
> данными с БД или все-таки конкретно о работе с транзакциями
> ?
Я говорю о том, что для оптимальной работы с БД вовсе незачем попусту размахивать транзакциями.
> Кстати, если уж на то пошло, то связка "кэшированные изменения
> + неявная транзакция по ApplyUpdates" - далеко не всегда
> оптимальный вариант обмена данными
"Оптимальный" - не значит "абсолютный". А я настаиваю, что оптимальный!
Цитата: "К преимуществам способа кэшированных изменений перед транзакционным способом можно отнести:
- минимизацию сетевого трафика;
- отсутствие блокировок на изменяемые записи."
← →
Johnmen © (2004-05-13 12:39) [20]>Курдль © (13.05.04 12:17) [15]
>Давай конструктивнее!
С удовольствием. На взаимной основе...
>Что именно не соответствует моим постулатам?
и далее...
>Лейтмотив моего "выступления" - это моё личное убеждение, что
>связка "кэшированные изменения + неявная транзакция по
>ApplyUpdates" - самый оптимальный вариант организации обмена
>данными с БД.
1. Если ты указываешь постоянно в своих постах некий ApplyUpdates, то указывай и класс, для которого этот метод ты подразумеваешь. На это я уже неоднократно намекал. Т.к. данный метод совершенно различен по реализации для разных классов.
2. Надежда на функционирование неявной транзакции может привести к неявным/непредсказуемым/неожиданным последствиям :)
3. По поводу оптимальности Vlad © уже сказал. Я с ним согласен.
← →
Курдль © (2004-05-13 12:49) [21]
> 1. Если ты указываешь постоянно в своих постах некий ApplyUpdates,
> то указывай и класс, для которого этот метод ты подразумеваешь.
Я имею в виду TDataBase и его наследников или аналогов(TIBDatabase, TSDDatabase, TOracleSession и т.п.).
← →
kaif © (2004-05-13 12:57) [22]ИМХО, политика транзакций для разных СУБД и разных задач - разная.
1. Не все СУБД поддерживают полный набор режимов изоляции транзакций (DirtyRead, RedCommitted, RepeatebleRead и т.д.)
2. Некоторые локальные СУБД, например, связка Paradox+BDE вообще имеют ограничение на количество обновлений в рамках одной транзакции и к ним не применимы обычные рекомендации, кажущиеся оптимальными в отношении серверных СУБД.
3. Правильная организация транзакций обычно прежде всего преследует достижение правильной координации совместной работы множества юзеров с базой данных и поэтому сильно зависит от задачи.
4. Сокращение программного кода "любой ценой" не может вообще служить критерием "правильного программирования".
5. Применение кешированных изменений не всегда оправдано (например, если редактируется результат объединения кучи таблиц и нужен Refresh для полного отображения результата редактирования текущей строки).
6. Как уже было замечено, и по-моему так оно и есть, абстракция кешированных изменений не регламентирует еще конкретной реализации подтверждения транзакции, так что с какими-то компонентами, возможно, ApplyUpdates не вызовет ни старта, ни подтверждения транзакции вообще, ни "явной", ни "неявной". Различение транзакций на "явные" и "неявные" может не иметь никакого отношения к сущности самих этих транзакций и вызывать дополнительные недоразумения. Например, транзакция стартовала неявно. Можно ли ее откатить? В старых IBX в документации было сказано, что нельзя. А я посмотрел в новых IBX реализацию этого "неявного" старта и не нашел никаких отличий от старта "явного". Таким образом, в новых IBX различия между "неявным" и "явным" стартом нет. То есть эти различия зависят от реализации и не носят принципиального характера, а для некоторых СУБД вообще бессмысленны. И это может сбить разработчиков с толку, если такую терминологию применять "в рекомендациях".
Вообще, ИМХО, любые рекомендации должны прояснять вопросы, а не только давать советы.
Так что, ИМХО, любой "набор рекомендаций вообще" был бы вредным для начинающих разработчиков, а приведенный набор рекомендаций - просто ошибочным. Может быть имеет смысл создать набор рекомендаций для "работающих с BDE", да и то для каждой СУБД - в отдельности. Примерно так пишутся хорошие книги.
И еще мне кажется, что увязывание вопросов кешированных изменений с вопросами транзакций говорит о том, что автор предлагает видимо вместо RollBack чаще использовать CancelUpdates, так как не находит (в большинстве случаев) между ними разницы. Может об этом стоит поговорить? Так есть ли разница и когда именно она проявляется? И тогда легче будет выработать более точные рекомендации. По крайней мере, станет понятнее пункт 4. Может быть следует сформулировать все сказанное так:
"Везде, где это возможно, применяйте на клиенте режимы CachedUpdates и метод CancelUpdates вместо посылки данных на сервер и отката транзакции".
Или так:
"Старайтесь вообще как можно меньше взаимодействовать с СУБД, и, если это возможно, всегда применяйте режим CachedUpdates".
Интересно, а такая рекомендация хороша или нет? Я лично затрудняюсь с лету ответить...
← →
Vlad © (2004-05-13 13:00) [23]Кстати, по поводу БДЕ, для меня пока так и не ясен ответ на вопрос [14]
автору:
Ну ты бы ветку с этого и начал: "Мужики, я хочу заявить, что считаю кэшированные изменения оптимальным методом работы с БД"
Ну и считай наздоровье.
"Если ты считаешь, что жена тебе не изменяет, значит она тебе действительно не изменяет" (с)Vlad
А начал-то с транзакций ?
← →
Курдль © (2004-05-13 13:04) [24]
> И еще мне кажется, что увязывание вопросов кешированных
> изменений с вопросами транзакций говорит о том, что автор
> предлагает видимо вместо RollBack чаще использовать CancelUpdates,
> так как не находит (в большинстве случаев) между ними разницы.
Да я просто предлагаю не разорять улей лишний раз! Потому и рекомендуюDataBase.ApplyUpdates([DataSet1, ... DataSetN]);
, чтобы не нагружать ни свой мозг, ни компьютерный лишними проблемами - указанная конструкция сама все сделает!
← →
Курдль © (2004-05-13 13:26) [25]
> kaif © (13.05.04 12:57) [22]
> ИМХО, политика транзакций для разных СУБД и разных задач
> - разная.
> 1. Не все СУБД поддерживают полный набор режимов изоляции
> транзакций (DirtyRead, RedCommitted, RepeatebleRead и т.д.)
> 2. Некоторые локальные СУБД, например, связка Paradox+BDE
> вообще имеют ограничение на количество обновлений в рамках
> одной транзакции и к ним не применимы обычные рекомендации,
> кажущиеся оптимальными в отношении серверных СУБД.
В заголовке топика значится [D6, Правильная БД], вряд ли следует относить к последним "Paradox+BDE"
> 3. Правильная организация транзакций обычно прежде всего
> преследует достижение правильной координации совместной
> работы множества юзеров с базой данных и поэтому сильно
> зависит от задачи.
Совершенно не согласен! Эта задача СУБД на 99%! Правильная организация транзакций преследует достижение правильного управления данными в рамках одной сессии (от одного юзера). Например, если юзер начал правку нескольких взаимосвязанных таблиц, изменения в которых допускаются только солидарные.
> 5. Применение кешированных изменений не всегда оправдано
> (например, если редактируется результат объединения кучи
> таблиц и нужен Refresh для полного отображения результата
> редактирования текущей строки).
Это совсем не понятно. Мне кажется, что сначала select-ом получают данные, потом их изменяют и возвращают в БД
> 6. Как уже было замечено, и по-моему так оно и есть, абстракция
> кешированных изменений не регламентирует еще конкретной
> реализации подтверждения транзакции, так что с какими-то
> компонентами, возможно, ApplyUpdates не вызовет ни старта,
> ни подтверждения транзакции вообще, ни "явной", ни "неявной".
> Различение транзакций на "явные" и "неявные" может не иметь
> никакого отношения к сущности самих этих транзакций и вызывать
> дополнительные недоразумения.
Я привел список компонентов, которые полностью поддерживают метод ApplyUpdates и исполняют его так, как описано в документации (методом двухфазного подтверждения).
← →
kaif © (2004-05-13 13:32) [26]2 Курдль © (13.05.04 13:04) [24]
А как такой пример?
1. Добавляем в справочник новый элемент (дубликат), который должен нарушить альтернативную (предметную) уникальность, например "наименование товара". Получаем для него ID (из генератора). В общем, все, как полагается...
2. Добавляем полученную ссылку на этот элемент в документ, например, в накладную. Все по-прежнему OK, так как на сервер ничего кроме запроса на новый ID от генератора не посылалось.
3. Применяем DataBase.ApplyUpdates([DataSet1, ... DataSetN]);
Получаем сообщение о нарушении уникального ключа в форме:
Violation of primary or unique key in table ...
4. Что теперь?
Я бы не стал закладываться на то, что в базе данных как правило:
1. Не используются широко "справочники".
2. Не используются уникальные ключи.
Неужели это и есть случай "сложных связей множества таблиц"? Или же это достаточно типичный случай "простых связей"?
Таким образом фраза "сложные связи" становится очень субъективно воспринимаемой и от рекомендаций ничего не остается, кроме самого исходного базового мотива "пореже осуществлять, если это возможно, команды update, insert, delete, чаще пользуясь механизмами кеширования на клиенте".
В общем, я бы сократил все вышесказанное до одной простой рекомендации:
Люди! Не пренебрегайте CachedUpdates!
А явный старт или не явный, много кода или мало... Это никакого отношения к делу в данном случае, ИМХО, не имеет...
← →
Vlad © (2004-05-13 13:42) [27]
> kaif © (13.05.04 13:32) [26]
> Люди! Не пренебрегайте CachedUpdates!
Это правильно. Пренебрегать конечно не стоит, тем более что в некоторых задачах это полезная вещь. А в некоторых - бессмысленная, и м.б. даже вредная.
Что касается применения ApplyUpdates(<array of TDataSet>), так это тоже не всегда хорошо. Зачастую необходимо сбросить из кэша данные только одного-двух датасетов из десяти(к примеру), не подтверждая транзакцию. Этот метод тут уже не подходит.
Поэтому если уж пользоваться им, то с головой. Т.е. надо понимать к чему это приведет.
И не надо говорить "всегда и везде пользуйтесь только этим". Оно неправильно.
← →
Курдль © (2004-05-13 13:45) [28]
> Я бы не стал закладываться на то, что в базе данных как
> правило:
> 1. Не используются широко "справочники".
> 2. Не используются уникальные ключи.
Я только этим и занимаюсь :)
Например, при создании нового лица (физ., юр.) в одной форме создаются до 5 записей в раздичных таблицах, типа адреса, телефоны, счета, паспорта и собснно лица. Ну и что? Все зависимые таблицы получают значение внешнего ключа, а главная - первичного ключа из заранее взятого значения типа GetIdentity.
Потом отрабатываетсяDataBase.ApplyUpdates([лица, адреса, телефоны, счета, паспорта]);
Вот приведенный в хэлпе способ обхода проблем с внешними ключами:procedure TForm1.DetailBeforeClose(DataSet: TDataSet);
begin
if Master.UpdatesPending or Detail.UpdatesPending then
if Master.UpdateStatus = usInserted then
Database1.ApplyUpdates([Master, Detail])
else
Database1.ApplyUpdates([Detail, Master]);
end;
← →
bushmen © (2004-05-13 13:49) [29]>первичного ключа из заранее взятого значения типа GetIdentity
Вот Вы уже переползли на конкретику. Что есть в одной СУБД, не обязательно есть в другой
← →
Vlad © (2004-05-13 13:50) [30]
> Вот приведенный в хэлпе способ обхода проблем с внешними
> ключами:
Тут закрытие Detail датасета приводит к неявному подтверждению всей транзакции. И что, это нормально ?
← →
kaif © (2004-05-13 13:51) [31]> 3. Правильная организация транзакций обычно прежде всего
> преследует достижение правильной координации совместной
> работы множества юзеров с базой данных и поэтому сильно
> зависит от задачи.
Совершенно не согласен! Эта задача СУБД на 99%! Правильная организация транзакций преследует достижение правильного управления данными в рамках одной сессии (от одного юзера). Например, если юзер начал правку нескольких взаимосвязанных таблиц, изменения в которых допускаются только солидарные.
Мне кажется, это заблуждение.
Зачем тогда полученный такой кровью режим ReadCommitted? Или режимы wait? Тогда достаточно иметь во всех случаях Snapshot. При таком подходе действительно между кешированием на клиенте и контекстом транзакции, возможно, и нет никакой разницы...
ИМХО, главное в нормальной СУБД - уникальность. Уникальность может быть проверена только при посылке данных на сервер. И больше никак. И уникальные индексы работают за пределами транзакций вообще. Таким образом, нельзя считать, что правильная организация транзакций преследует достижение правильного управления данными в рамках одной сессии . Так как уникальность в эти рамки никак не лезет. И то, подвердил другой юзер ту запись, которая в этой сессии приведет к нарушению уникальности или не подвердил, имеет первостепенное значение для того, чей именно апдейт рухнет. Я уже не говорю о тех случаях, когда возможный конфликт двух юзеров ставится целью (пессимистическая модель). Когда нельзя никак допустить продажу одного железнодорожного билета из двух касс. И тогда выбор способа изоляции транзакций полностью определяется самой задачей. Хотя, согласен, это редкий случай.
← →
Курдль © (2004-05-13 13:57) [32]
> Тут закрытие Detail датасета приводит к неявному подтверждению
> всей транзакции. И что, это нормально ?
Что значит "закрытие"? Если пройдет успешно 1-я фаза (запись данных) из обоих датасэтов, то ApplyUpdates неявно (т.е. не Вами инициированно) совершит фиксацию обновлений в БД, а если не успешно - откатит изменения в обоих датасетов и закроет транзакцию, неявно открытую им же перед началом всей цепочки изменений.
← →
kaif © (2004-05-13 14:00) [33]Курдль © (13.05.04 13:45) [28]
Как Ваш пример среагирует на дубликат?
Или в Вашей базе допускается создавать энное количество одного и того же контрагента?
Вы получили ID и думаете, что этого достаточно?
А завтра запросят "долг по этому контрагенту" и получат цифру, не соответствующую реальному долгу. После "расследования" (не без помощи программиста) выяснится, что имеется еще один "точно такой же", но с другим ID.
Как тогда Вы будете объяснять заказчику преимущества метода кешированных изменений на клиенте перед уникальньным индексом на ИНН и Rollback при попытке создания дубликата?
← →
kaif © (2004-05-13 14:01) [34]Курдль © (13.05.04 13:45) [28]
Как Ваш пример среагирует на дубликат?
Или в Вашей базе допускается создавать энное количество одного и того же контрагента?
Вы получили ID и думаете, что этого достаточно?
А завтра запросят "долг по этому контрагенту" и получат цифру, не соответствующую реальному долгу. После "расследования" (не без помощи программиста) выяснится, что имеется еще один "точно такой же", но с другим ID.
Как тогда Вы будете объяснять заказчику преимущества метода кешированных изменений на клиенте перед уникальньным индексом на ИНН и Rollback при попытке создания дубликата?
← →
Vlad © (2004-05-13 14:03) [35]
> Курдль © (13.05.04 13:57) [32]
> Что значит "закрытие"?
Закрытие - это то и значит. Close тоесть.
Если я где нибудь в коде сделаю детайл-датасету Close;Open, то это приведет к завершению транзакции.
← →
kaif © (2004-05-13 14:05) [36]Прошу прощения за дубликат. Вот - легок на помине. :)))) Клянусь, я тут не причем. Сервер долго не отвечал, а кнопка продолжала нажиматься... Вот Вам пример! Обе записи имеют свой отдельный ID, как можно заметить. Однако уникальность ничем не гарантирована.
← →
Курдль © (2004-05-13 15:16) [37]
> kaif © (13.05.04 14:00) [33]
> Курдль © (13.05.04 13:45) [28]
> Как Ваш пример среагирует на дубликат?
Дубликат чего? Уникального поля? Получит отлуп от СУБД и вернет все взад. Какая разница, на каком уровне активируются constraint-ы или триггеры БД, от одиночного поста, или пакета изменений?
> Если я где нибудь в коде сделаю детайл-датасету Close;Open,
> то это приведет к завершению транзакции.
При кэшированных изменениях это приведет всего лишь к refresh-у датасэта. А без них... Я не уверен, что к закрытию транзакции. Транзакция только в IB может открываться множественно, в остальных СУБД транзакция жестко привязана к сессии, а не к датасэту.
← →
Vlad © (2004-05-13 15:24) [38]
> Курдль © (13.05.04 15:16) [37]
> в остальных СУБД транзакция жестко привязана к сессии, а
> не к датасэту.
> При кэшированных изменениях это приведет всего лишь к refresh-у
> датасэта.
При любых изменениях. Не только при кэшированных.
Если ты на BeforeClose детайл-датасета вешаешь ApplyUpdates([....]), то его закрытие/открытие приведет к коммиту транзакции
И что это правильно по-твоему ?
← →
Курдль © (2004-05-13 15:30) [39]
> Если ты на BeforeClose детайл-датасета вешаешь ApplyUpdates([....]),
>
Да кто ж его туда вешает? Извращенцы, что ли??!!
← →
Курдль © (2004-05-13 15:32) [40]А! Сорри! Это про пример их хэлпа!
← →
Vlad © (2004-05-13 15:34) [41]
> Да кто ж его туда вешает? Извращенцы, что ли??!!
:-)
← →
Курдль © (2004-05-13 15:35) [42]Я его привел только как пример изящного обхода проблем с внешними ключами. На самом деле ApplyUpdates вызывается в конце бизнесс-процесса "ввод данных" преимущественно по команде юзера.
Например при закрытии по "Ок" модальной формы ввода или кнопкой "Сохранить" над гридом.
← →
Vlad © (2004-05-13 15:47) [43]
> Я его привел только как пример изящного обхода проблем с
> внешними ключами
А я тебе привел другой пример (на основе твоего же), когда ApplyUpdates может привести к нежелательным последствиям.
Так что, еще раз говорю, надежнее, когда транзакциями управляешь сам.
← →
Petr V. Abramov © (2004-05-13 16:06) [44]> у меня сложилась стойкая ассоциация, что транзакция, это такая
> большая ручка от чемодана, которую прилепляют к
> багажнику "Жигулей", чтобы они ездили, как "Феррари"
Скорее, "плюшевые кости на зеркале и корона на панели", чтобы все было как у людей :)
> У меня есть свой стиль, который я ни в коем случае никому не
> навязываю. Но очень хотел бы почитать всеобщую критическую
> оценку.
Ну стиль как стиль, неправильного ничего не вижу, так же как и технологического прорыва в управлении транзакциями.
> общие рекомендации по работе
Конечно, Ваш стиль на общность не тянет, так же как и мой. Но то, что Вы опубликовали, имеет ценность другого плана - если человек вообще не знает, с какой стороны подойти, это - один из хороших вариантов.
kaif © (13.05.04 12:57) [22]
> 3. Правильная организация транзакций обычно прежде всего
> преследует достижение правильной координации совместной работы
> множества юзеров с базой данных и поэтому сильно зависит от
> задачи.
Правильная организация транзакций преследует достижение логической целостности данных, то есть их соответствия бизнес-правилам (например, сходимости оборотов с остатками). Конечно, при этом она сильно зависит от задачи. При многопользовательской работе Правильная СУБД помогает в этом установкой блокировок и удержанием их до конца транзакции.
> Различение транзакций на "явные" и "неявные" может не иметь
> никакого отношения к сущности самих этих транзакций и вызывать
> дополнительные недоразумения.
С точки зрения Правильной СУБД все транзакции явные. Различение транзакций на "явные" и "неявные" с моей точки зрения есть вредная глупость, наверное, призванная упростить жизнь фокпрошникам, но реально ВСЕМ ее усложняющая.
← →
kaif © (2004-05-13 16:09) [45]Приведу аргумент в пользу явного управления вообще чем-либо. Вот, например, в паскале и в си управление типом переменных явное. А в интерпретаторах зачастую используется неявное управление типами переменных и, как следствие, изменение типов некоторых переменных "на ходу". Если здесь есть программисты, работавшие на интерпретаторах (я работал долго на FoxPro 2.6), то они не дадут соврать. Поиск и выявлении ошибок при неявном управлениии переменными иногда доводит до отчаяния... Никаких таких проблем не бывает априори в языках с жесткой типизацией. Хотя строк кода с виду больше. Аналогично, я подозреваю, дело обстоит и с транзакциями. Могу рассказать про мою личную "эволюцию". Когда я только начинал работать с IB, я использовал BDE и редко заморачивался на транзакции вообще. Затем я перешел на IBX и стал больше уделять этому внимание. Сейчас я абсолютно все транзакции, если это не readonly транзакция стартую и подтверждаю явно. Во-первых, так мне легче видеть логику того, что я делаю в тексте программы, так как это находится в одном месте. Так мне легче обрабатывать все блоках try, если это нреобходимо.
Никаких преимуществ в неявном управлении транзакциями, кроме недостатков, на сегодня я не знаю.
← →
Курдль © (2004-05-13 16:27) [46]
> Конечно, Ваш стиль на общность не тянет, так же как и мой.
> Но то, что Вы опубликовали, имеет ценность другого плана
> - если человек вообще не знает, с какой стороны подойти,
> это - один из хороших вариантов.
Так я именно о том, что первый раз купив себе машину, причем рындван от ВАЗ, не следует первым делом ставить на нее спойлер! Не поедет ОНО как Порш, хоть обос...сь!
Мысль о подобном топике возникала у меня время от времени, глядя на подобные образцы: http://delphimaster.net/view/3-1084428403/
> Правильная СУБД помогает в этом установкой блокировок и
> удержанием их до конца транзакции.
:)
Правильная СУБД, типа Оракла, с которой я больше всего работаю, вообще ничего не блокирует! Просто не даст ничего лишнего, что могло бы навредить. Задача транзакционного метода в таком случае - лишь правильно приподнести измененные данные и поправить их, если будет выявлена ошибка сервером.
← →
Vlad © (2004-05-13 16:35) [47]
> Правильная СУБД, типа Оракла, с которой я больше всего работаю,
> вообще ничего не блокирует!
Да ну ?
select * from table where ... for update // Выбрали, заблокировали
commit; // сняли блокировку
← →
Курдль © (2004-05-13 16:37) [48]
> Да ну ?
> select * from table where ... for update // Выбрали, заблокировали
> commit; // сняли блокировку
Так это оракл блокирует, или юзер?
← →
Petr V. Abramov © (2004-05-13 16:45) [49]> типа Оракла < ... > вообще ничего не блокирует!
Возьмите свои слова обратно, пока не Вас не накрыла буря эмоций. :) "Типа" может и не блокирует, а у Oracle с этим все ОК.
Об этом прям в первой книжке "Database Concepts" Part VII
"Data Protection" явно написано.
> Просто не даст ничего лишнего, что могло бы навредить.
Будем считать не очень удачным переводом слова "How Oracle Locks Data" (из Database Concepts :)
← →
Курдль © (2004-05-13 16:52) [50]А коротко можно о том, что блокирует оракл без спец. команды типа LOCK TABLE ... или ... FOR UPDATE?
← →
Petr V. Abramov © (2004-05-13 17:17) [51]Cделайте update и посмотрите v$lock и v$locked_object, найдите отличия от результата select ... for update.
Если заинтресуетесь, расскажу где почитать, какие вообще блокировки бывают и откуда берутся :)
← →
Курдль © (2004-05-13 17:21) [52]Оч. интересно. Расскажите, плз, где почитать.
Я и вправду так глубоко не копал. Только мне интересно, как это сказывается на работе клиента?
← →
Petr V. Abramov © (2004-05-13 17:33) [53]> Я и вправду так глубоко не копал.
А вот это на работе клиента может сказатся плачевно. В виде повисаний из-за ожидания освобождения блокировки или, еще хуже, "развала" данных из-за неустановки ее где надо. Почитайте обсуждение Allegro в "Потрепаться", там есть простой и наглядный пример.
← →
Курдль © (2004-05-13 18:14) [54]
> Почитайте обсуждение Allegro в "Потрепаться", там есть простой
> и наглядный пример.
К сожалению, не нашел.
← →
kaif © (2004-05-13 19:13) [55]2 Petr V. Abramov © (13.05.04 17:33) [53]
Кстати, насчет Allegro. Я обдумываю добавление и настройку ресурсов типа "критического склада" в Allegro, но у меня есть ряд вопросов, связанных с этой темой. В частности, какие ограничения я могу себе позволить наложить на юзеров в части редактирования документов "задним числом". Вы не будете возражать, если я напишу Вам на мейл?
Я хотел бы организовать такой ресурс на основе того, что IB не допускает подтверждения одновременного редактирования одной и той той же записи двумя юзерами, даже при изоляции ReadCommitted и nowait. Если сделать ресурс, работающий пои принципу:
update ... set quantity = quantity - :sale where id = :id
в коротких отдельных транзакциях на модификацию с предложением "повторить попытку" при "накладке", то пессимистическая задача решается корректно.
Я добавил в Allegro поддержку таких транзакций (вторая write-транзакция для IBX).
← →
Petr V. Abramov © (2004-05-13 19:54) [56]> kaif © (13.05.04 19:13) [55]
> Вы не будете возражать
Не буду :)
← →
Petr V. Abramov © (2004-05-13 21:18) [57]А лучше ICQ
Страницы: 1 2 вся ветка
Форум: "Базы";
Текущий архив: 2004.06.06;
Скачать: [xml.tar.bz2];
Память: 0.8 MB
Время: 0.036 c