О блокировке записей
Модератор: kdv
-
- Сообщения: 14
- Зарегистрирован: 28 апр 2005, 23:07
О блокировке записей
Это в продолжение к теме о состоянии транзакций. Ноги вообщем-то растут из проблемы блокировки. У меня проблема вои в чем:
1. Пользователь <А> редактирует (создает) документ, в который вносит некоторое ID аналитики (ID записи справочника, причем справочник в общем случае сложный - состоящий из нескольких таблиц, имеющих временную привязку и т.д.). Commit - по решению пользователя (сохранить документ) (т.е. неизвестно когда).
2. Пользователь <B> редактирует другой документ, в котором тоже может быть выбрана в принципе эта же аналитика.
Как заблокировать эту строку аналитики так, чтобы пользователь <С> не смог ничего отредактировать в этой строке, пока активны транзакции пользователя A и B? Блокировка with lock не проходит, поскольку первая выставившая эту блокировку транзакция ее же и снимает, а если эта аналитика используется в другой транзакции, которая длится дольше? Вобщем то все можно придумать (доп.таблица, ID curent_transaction и т.п.), но все это хорошо до момента обрыва connecta и возникновения "ничьих" данных. Вот эти данные и хорошо бы идентифицировать, для того чтобы автоматически их "прибрать" исходя из того что по ID транзакции можно определить ее неактивность. Но боюсь, что ни фига такая информация разумным способом недоступна (ну не лазить же в базу файловым доступом, и нужно еще хорошо знать куда лезть).
1. Пользователь <А> редактирует (создает) документ, в который вносит некоторое ID аналитики (ID записи справочника, причем справочник в общем случае сложный - состоящий из нескольких таблиц, имеющих временную привязку и т.д.). Commit - по решению пользователя (сохранить документ) (т.е. неизвестно когда).
2. Пользователь <B> редактирует другой документ, в котором тоже может быть выбрана в принципе эта же аналитика.
Как заблокировать эту строку аналитики так, чтобы пользователь <С> не смог ничего отредактировать в этой строке, пока активны транзакции пользователя A и B? Блокировка with lock не проходит, поскольку первая выставившая эту блокировку транзакция ее же и снимает, а если эта аналитика используется в другой транзакции, которая длится дольше? Вобщем то все можно придумать (доп.таблица, ID curent_transaction и т.п.), но все это хорошо до момента обрыва connecta и возникновения "ничьих" данных. Вот эти данные и хорошо бы идентифицировать, для того чтобы автоматически их "прибрать" исходя из того что по ID транзакции можно определить ее неактивность. Но боюсь, что ни фига такая информация разумным способом недоступна (ну не лазить же в базу файловым доступом, и нужно еще хорошо знать куда лезть).
Чё-т ты мудришь. То ли с объяснением, то ли с собственным пониманием.
1. Какая разница, изменит С что-то до окончания работы А и Б или после, если ты пишешь в документ всё равно ссылку, а не значение? После вмешательства С при последующих чтениях документа по ссылке будет доставаться новое значение из чего-то невнятного, называемого справочником-аналитикой. Если же при редактриовании этого что-то в нём делаются не изменения, а создаётся его новое поколение с изменёнными значениями (привязка по времени?), то и ссылка на него будет новая, а документы от А и В будут ссылаться по старой на старое поколение.
2. Что значит
________
Блокировка with lock не проходит, поскольку первая выставившая эту блокировку транзакция ее же и снимает
________
Если ты делаешь блокировку от А, то В и С оба стоят в очереди, одновременной работы А и В нет. Вот кто из В и С первым достучится после отпускания - действительно неопределено. Что-то тут в консерватории не так. С не должен менять упомянутое что-то если кто-то другой с ним работает - это как бы понятно. Но тогда и читатели должны становиться в очередь, причём равноправную с С и следующий после его вмешательства читатель увидит уже новое. Если опять же "привязка по времени" в момент формирования документа не выполнена в виде поколений справочника с поиском по First 1 Where ID_Object=... And TimeStamp_Start_Of_Actuality<=... (Now?) Order By TimeStamp Desc. А в этом случае и блокировка вроде не нужна, каждый берёт что ему нужно, С плодит новые варианты на будущее с датой начала действия. Ссылка от документа тогда удобна двухсегментная - ID_Object,ID_Generation, чтобы по датам искать только при вставке, а при чтении по прямой ссылке объект-поколение. Если же речь о том, что работа А идёт в несколько последовательных транзакций и беспокоит отпускание блокировки в краткий миг между коммитом одной и стартом другой - кто мешает заделать ещё одну, чиста блокировочную, первым делом блокировать справочник, а работу с документом выполнять в каскаде других и отпускать блокировку в самом конце этого каскада?
1. Какая разница, изменит С что-то до окончания работы А и Б или после, если ты пишешь в документ всё равно ссылку, а не значение? После вмешательства С при последующих чтениях документа по ссылке будет доставаться новое значение из чего-то невнятного, называемого справочником-аналитикой. Если же при редактриовании этого что-то в нём делаются не изменения, а создаётся его новое поколение с изменёнными значениями (привязка по времени?), то и ссылка на него будет новая, а документы от А и В будут ссылаться по старой на старое поколение.
2. Что значит
________
Блокировка with lock не проходит, поскольку первая выставившая эту блокировку транзакция ее же и снимает
________
Если ты делаешь блокировку от А, то В и С оба стоят в очереди, одновременной работы А и В нет. Вот кто из В и С первым достучится после отпускания - действительно неопределено. Что-то тут в консерватории не так. С не должен менять упомянутое что-то если кто-то другой с ним работает - это как бы понятно. Но тогда и читатели должны становиться в очередь, причём равноправную с С и следующий после его вмешательства читатель увидит уже новое. Если опять же "привязка по времени" в момент формирования документа не выполнена в виде поколений справочника с поиском по First 1 Where ID_Object=... And TimeStamp_Start_Of_Actuality<=... (Now?) Order By TimeStamp Desc. А в этом случае и блокировка вроде не нужна, каждый берёт что ему нужно, С плодит новые варианты на будущее с датой начала действия. Ссылка от документа тогда удобна двухсегментная - ID_Object,ID_Generation, чтобы по датам искать только при вставке, а при чтении по прямой ссылке объект-поколение. Если же речь о том, что работа А идёт в несколько последовательных транзакций и беспокоит отпускание блокировки в краткий миг между коммитом одной и стартом другой - кто мешает заделать ещё одну, чиста блокировочную, первым делом блокировать справочник, а работу с документом выполнять в каскаде других и отпускать блокировку в самом конце этого каскада?
-
- Сообщения: 14
- Зарегистрирован: 28 апр 2005, 23:07
Дело вот в чем. User <A> редактирует документ, имеющий определенную дату. И аналитику он может внестив этот документ, удовлетворяющую этой дате (т.е. не моложе документа). <A> внес ссылку на эту аналиттику, сделал Post, и редактирует себе следующую строку и т.д. (commit пока не делает). А в это время коварный <С> возьми да измени конечную дату действия этой аналитики с открытой на дату, более раннюю, чеи дата документа <A> или вообще, гад, удаляет ее и делает commit. В итоге в документе у <A> в момент commita незаконная ссылка. Конечно, когда <С> изменяет даты, или удаляет аналитику, его посылаем подальше, если он некорректно себя ведет, но эта проверка - только по сохраненным докуметам. В принципе этой проблемы бы не было при работе с кэшированными делами - проверяй себе эти дела в событии UpdateRecord. Но кэш при навороченных и сложно связанных структурах - пустая затея. Можно конечно перед commit у <A> перетрусить весь Dataset - но уж больно некрасиво.
по-моему нет тут никакой проблемы. я не знаю, о каких "ссылках" речь, но при нормально организованной целостности (FK) "незаконных" ссылок быть не может.
То есть, или это попытка автоматизировать неавтоматизируемое, или некорректная реализация блокировок в приложении, или некорректная реализация модели прикладной области. Если надо блокировать - блокируй. Как это у тебя <C> может поменять что-то, от чего зависит целостность изменений <A>?
Мне опять вспомнился пример одного из моих курсантов в 1998 году - "какие транзакции? Вагон пришел, разгрузили, отправили обратно. Никаких блокировок.". В данном случае ситуация совершенно противоположная - хотим без блокировок чтобы параллельно туча людей модифицировала одну и ту же информацию. Нельзя так.
Так что, про "состояния транзакций" выкинь из головы вообще. Любая задача должна решаться штатным использованием транзакций, без необходимости проверки их состояния. На то они и транзакции.
www.ibase.ru/devinfo/pslock.htm ты вроде бы читал, но похоже, не осознал.
То есть, или это попытка автоматизировать неавтоматизируемое, или некорректная реализация блокировок в приложении, или некорректная реализация модели прикладной области. Если надо блокировать - блокируй. Как это у тебя <C> может поменять что-то, от чего зависит целостность изменений <A>?
Мне опять вспомнился пример одного из моих курсантов в 1998 году - "какие транзакции? Вагон пришел, разгрузили, отправили обратно. Никаких блокировок.". В данном случае ситуация совершенно противоположная - хотим без блокировок чтобы параллельно туча людей модифицировала одну и ту же информацию. Нельзя так.
Так что, про "состояния транзакций" выкинь из головы вообще. Любая задача должна решаться штатным использованием транзакций, без необходимости проверки их состояния. На то они и транзакции.
www.ibase.ru/devinfo/pslock.htm ты вроде бы читал, но похоже, не осознал.
Неверна модель. Конечной даты вообще быть не должно. Должна быть начальная и действующей всегда явлется просто последняя. А для оформлений задним числом ищем свежайшую из существовавших до интересующей даты. По-хорошему эти даты не редактируют, а при необходимости вставляют новую даже в середину последовательности, создавая новый диапазон актуальности в прошлом и меняют ссылки в уже существующих документах, ссылающихся после этого на "неправильное" поколение. Или не меняют, если такова постановка (документ уже узаконен за пределами нашей сферы влияния, умерла так умерла (С)).Viktor_Dnepropetrovsk писал(а):Дело вот в чем. User <A> редактирует документ, имеющий определенную дату. И аналитику он может внестив этот документ, удовлетворяющую этой дате (т.е. не моложе документа). <A> внес ссылку на эту аналиттику, сделал Post, и редактирует себе следующую строку и т.д. (commit пока не делает). А в это время коварный <С> возьми да измени конечную дату действия этой аналитики с открытой на дату, более раннюю, чеи дата документа
Хрен там ему дадут удалить если есть FK - системный контроль целостности осуществляется вне контекста транзакций, так что если есть ссылка, даже некоммиченная, пойдёт он лесом.Viktor_Dnepropetrovsk писал(а): <A> или вообще, гад, удаляет ее и делает commit.
-
- Сообщения: 14
- Зарегистрирован: 28 апр 2005, 23:07
Ну во, первых, это не теоретизирование, а реальная разработка, которая дала неплохие результаты по скорости, гибкости настройки и отчетным делам (предм.область - бухучет). По части дат - ребята, посмотрите на 1С - в справочниках убогий намек на временную историю параметра и очень слабое его использование. Мы пошли путем временной привязки в справочниках (там где это действительно нужно. а в реальной модели предприятия это нужно почти везде, ну может не надо в единицах измерения и подобном. Все течет, все меняется...). Так вот как правило сложный справочник - это
1. главная таблица где прописан основной ID аналитики, его псевдоним (как его USER обзовет), дата начала действия и конечная дата (для "открытой" аналитики конечная дата 3000 год - null нельзя по соображениям построения выборок, и для USERа мы эту дату преобразуем в controlax в пустую или типа "отрытый период").
2. несколько или одна (это уже по смыслу) таблица, где есть ссылка по FK на главную таблицу аналитики и прописаны реквизиты этой аналитики, которые тоже имеют временную привязку. (Напр. полное и краткое наименование предприятия, его инд.код, налоговый номер, ФИО руководителя, адрес и т.п. При смене реквизита(ов) строка дублируется и нужные изменяются с некоторой даты).
3. таблицы- списки (дети главной аналитики напр. предприятия - его расчетные счета или договора). Тоже имеет временную привязку.
4. Таблицы для временных связей владельцы - объекты (напр. участки - объекты расходов. Скажем теплоход в этом месяце был приписан к Запорожью, а со следующего его перевели в Днепропетровск. Кстати мы в старой Cliiperной системе из-за отсутсвия этой связи имеем большую головную боль).
...И ряд других типов таблиц.
Каждый справочник описывается в настроечных таблицах в виде набора типов связей и конфигурации полей из которого собственно и строится Select со всеми его join.
Как видите временных привязок до и больше, но все они коррелированы на главную аналитику. Это я я расписал для того, чтобы было понятно, что делается не задача типа "Учет движения зеленого горошка на складе № 6". Конечная дата аналитики - это "закрытие" этой аналитики для пользователя в при создании документа. Физ. смысл - расчетный счет закрыт, предприятие, цех ликвидированы, основное средство списано, работник уволился. Но отчеты то строятся за любой прошлый период, а там аналитика живет.
По поводу FK. Поскольку у нас типичный документ - это виртуальная таблица, построенная по набору типовых операций (изменяемому во времени), типовая операция - набор проводок (дебет-кредит), а к счетам в типовых проводках привязаны аналитические признаки (т.е. по сути объектная модель) + дополнительные поля (по настройке) из других таблиц, то понятно , что нет таблицы "Документ" с полем ID аналитики. В строке документа в общем случае может быть любое число аналитик , причем от строки к строке список различен(смотря какая типовая операция). Ну и какой FK? Кстати небухгалтерский документ вообще собирается по конфигурации из таблиц типов - String, Currency, Integer и т.д. Все проверки -через процедуры, щупающие таблицу проведенных операций, таблицу прочих документов, поэтому я и говорил о сохраненных документах. Сложно, но очень гибко и работает с хорошими временными характеристиками. К примеру вычитка виртуального реестра документов с набором пяти аналитик в трех типовых операциях (по четыре-пять проводок на операцию) с объемом реестра 2000 строк -менее секунды (реально вычитывается из таблицы проводок около 10000 записей, не считая таблиц аналитик и т.д.) (сервер Win2000 P4 1.7 512 ОЗУ сеть 100 Mbit)
А насчет блокировок идеально было бы так - пока любой пользователь, "выбравший" в свой докумет аналитику, не сохранил его или не откатил, редактировать эту аналитику (не всю а конкретное ID) нельзя. Выстраивать в очередь читающих пользователей? Вы пробовали в реальном проекте? Да вас порвут на части.
Решение есть - всякий выбор аналитики прописывать в отдельной короткой транзакции в таблицу блокировок с реквизитами ID, имя аналитики, ID current_transaction. Для <C> делается проверка на наличие желаемого для редактирования ID аналитики в этой таблице - есть ID - иди гуляй и подожди. По commit /rollback документа вычищается в таблице блокировок строки where ID_TRANSACTION = ID_current_transaction, запомненного в приложении в момент работы транзакции. Все хорошо, но при дисконнекте останутся "ничьи" заблокированные записи. На это то же есть решение - при запуске на следующий день (круглосуточно наши клиенты к счастью не работают) проверяется количество коннектов и если он один - то блокируетяс таблица блокировок и вся чистится. А вот в текущей работе - ничьи записи останутся висеть и блокировать. Вот в этом проблема. Даже сделав ручной режим снятия блокировки нужно различить "ничьи" записи и записи активных транзакций, ну или всех повыгонять с рабочих мест и позакрывать документы.
1. главная таблица где прописан основной ID аналитики, его псевдоним (как его USER обзовет), дата начала действия и конечная дата (для "открытой" аналитики конечная дата 3000 год - null нельзя по соображениям построения выборок, и для USERа мы эту дату преобразуем в controlax в пустую или типа "отрытый период").
2. несколько или одна (это уже по смыслу) таблица, где есть ссылка по FK на главную таблицу аналитики и прописаны реквизиты этой аналитики, которые тоже имеют временную привязку. (Напр. полное и краткое наименование предприятия, его инд.код, налоговый номер, ФИО руководителя, адрес и т.п. При смене реквизита(ов) строка дублируется и нужные изменяются с некоторой даты).
3. таблицы- списки (дети главной аналитики напр. предприятия - его расчетные счета или договора). Тоже имеет временную привязку.
4. Таблицы для временных связей владельцы - объекты (напр. участки - объекты расходов. Скажем теплоход в этом месяце был приписан к Запорожью, а со следующего его перевели в Днепропетровск. Кстати мы в старой Cliiperной системе из-за отсутсвия этой связи имеем большую головную боль).
...И ряд других типов таблиц.
Каждый справочник описывается в настроечных таблицах в виде набора типов связей и конфигурации полей из которого собственно и строится Select со всеми его join.
Как видите временных привязок до и больше, но все они коррелированы на главную аналитику. Это я я расписал для того, чтобы было понятно, что делается не задача типа "Учет движения зеленого горошка на складе № 6". Конечная дата аналитики - это "закрытие" этой аналитики для пользователя в при создании документа. Физ. смысл - расчетный счет закрыт, предприятие, цех ликвидированы, основное средство списано, работник уволился. Но отчеты то строятся за любой прошлый период, а там аналитика живет.
По поводу FK. Поскольку у нас типичный документ - это виртуальная таблица, построенная по набору типовых операций (изменяемому во времени), типовая операция - набор проводок (дебет-кредит), а к счетам в типовых проводках привязаны аналитические признаки (т.е. по сути объектная модель) + дополнительные поля (по настройке) из других таблиц, то понятно , что нет таблицы "Документ" с полем ID аналитики. В строке документа в общем случае может быть любое число аналитик , причем от строки к строке список различен(смотря какая типовая операция). Ну и какой FK? Кстати небухгалтерский документ вообще собирается по конфигурации из таблиц типов - String, Currency, Integer и т.д. Все проверки -через процедуры, щупающие таблицу проведенных операций, таблицу прочих документов, поэтому я и говорил о сохраненных документах. Сложно, но очень гибко и работает с хорошими временными характеристиками. К примеру вычитка виртуального реестра документов с набором пяти аналитик в трех типовых операциях (по четыре-пять проводок на операцию) с объемом реестра 2000 строк -менее секунды (реально вычитывается из таблицы проводок около 10000 записей, не считая таблиц аналитик и т.д.) (сервер Win2000 P4 1.7 512 ОЗУ сеть 100 Mbit)
А насчет блокировок идеально было бы так - пока любой пользователь, "выбравший" в свой докумет аналитику, не сохранил его или не откатил, редактировать эту аналитику (не всю а конкретное ID) нельзя. Выстраивать в очередь читающих пользователей? Вы пробовали в реальном проекте? Да вас порвут на части.
Решение есть - всякий выбор аналитики прописывать в отдельной короткой транзакции в таблицу блокировок с реквизитами ID, имя аналитики, ID current_transaction. Для <C> делается проверка на наличие желаемого для редактирования ID аналитики в этой таблице - есть ID - иди гуляй и подожди. По commit /rollback документа вычищается в таблице блокировок строки where ID_TRANSACTION = ID_current_transaction, запомненного в приложении в момент работы транзакции. Все хорошо, но при дисконнекте останутся "ничьи" заблокированные записи. На это то же есть решение - при запуске на следующий день (круглосуточно наши клиенты к счастью не работают) проверяется количество коннектов и если он один - то блокируетяс таблица блокировок и вся чистится. А вот в текущей работе - ничьи записи останутся висеть и блокировать. Вот в этом проблема. Даже сделав ручной режим снятия блокировки нужно различить "ничьи" записи и записи активных транзакций, ну или всех повыгонять с рабочих мест и позакрывать документы.
-
- Сообщения: 14
- Зарегистрирован: 28 апр 2005, 23:07
ну, открытий я тут не вижу, ибо оо-ориентированные хранилища я видел и делал лет 10 назад, а историю реквизитов тоже хранят масса народу без каких-то проблем с "блокировками" и т.п.
что такое OAT - загрузи IBAnalyst, и почитай. кроме того статьи в разделе транзакций на сайте. А то как бы, ты про блокировки и транзакции загибаешь, а элементарных вещей о транзакциях IB/FB не знаешь...
что такое OAT - загрузи IBAnalyst, и почитай. кроме того статьи в разделе транзакций на сайте. А то как бы, ты про блокировки и транзакции загибаешь, а элементарных вещей о транзакциях IB/FB не знаешь...
-
- Сообщения: 14
- Зарегистрирован: 28 апр 2005, 23:07
Это вы про Oldest active transaction ? Так о чем же и речь. Уже два (а может и больше) дня бьюсь на тему, как получить ее ID в приложении. И слышу только о том, что модель что-то не та, кто-то 10 лет назад то же чем-то баловался и т.п. В IBAnalyst ее как-то вытягивают, вот и спрашиваю как, если конечно это не военная тайна.
Re: О блокировке записей
Из этой фразы кто-то должен был понять, что тебя интересует именно OAT ? Извини, но тут написано другоеViktor_Dnepropetrovsk писал(а):по ID транзакции можно определить ее неактивность

Насчёт как её достать :
1. Для всех (IB и FB) - RTFM Services API, IBX - получаешь статистику header page и парсишь её
2. Для IB >= 7.х - TMP$xxx
3. Для FB >= 1.5 - isc_database_info + isc_info_oldest_active
ну получишь ты этот ID, а что ты с ним дальше-то будешь делать?Уже два (а может и больше) дня бьюсь на тему, как получить ее ID в приложении. И слышу только о том, что модель что-то не та, кто-то 10 лет назад то же чем-то баловался и т.п. В IBAnalyst ее как-то вытягивают, вот и спрашиваю как, если конечно это не военная тайна.
Если слышишь о том что модель кривая, и нигде таких проблем не было, может и правда стоит подумать о том, что что-то у тебя не так?
Я не утверждаю, но быть уверенным на > 100% в своей правоте, особенно при реализации бизнес-процессов - это, как бы, нехорошо...
p.s. IBAnalyst бесплатен для России и СНГ. Всего 1 мегабайт - мог бы и скачать вместо того чтобы спрашивать.
-
- Сообщения: 14
- Зарегистрирован: 28 апр 2005, 23:07
Да давно уже скачал, и пока БД не в реальной эксплуатации толк есть, но не очень много. А насчет правоты... 13 лет с бухгалтериями средних заводов и предприятий (транспорт, металлургия, услуги, торговля (хотя и на dbf (Cliiper5 сеть), но с хорошими результатами ) не очень то мы боимся и опыт есть. Все-таки ответ на свой вопрос я не получил. Чую, этот форум предназначен для того, чтобы потыкать носом студентов и прочих в статьи (кстати зачастую оторванные от реальной жизни) и немного на всех поплевать. Разочарован барским тоном и нежеланием помочь.
-
- Сообщения: 14
- Зарегистрирован: 28 апр 2005, 23:07
Всех с праздником!
Для hvlad. Большое спасибо (кстати, о барском тоне - это не к тебе). Да , для меня лучше было бы определить активности (или неактивность транзакций), но ОАТ тоже подойдет - ты сам сказал, все что ниже - неактивно. В принципе пока шла эта переписка пришла мысль о другом подходе. Можно было бы помимо "главной транзакции" в документе стартовать еще одну параллельную транзакцию - блокирующую. Тогда при внесении аналитики в документ, пакет нормативно-справочной информации (НСИ) выполняет в своей короткой транзакции Append в общую блокировочную таблицу аналитик(заносится ID аналитики, ее имя, ID главной транзакции) и выполняется COMMIT. Далее блокирующая транзакция перезапускается и выполняется
Select ... from <блокировочная таблица> where id_transaction = <ID "главной" транзакции документа> with lock.
Т.е. после каждого внесения аналитики блокируемый список увеличивается.
После COMMIT/ROLLBACK "главной" транзакции (и соответственно блокирующей) выполняется удаление из блокировочной таблицы записей с id_transaction = <ID "главной" транзакции документа> (понятно, что ее значение можно сохранить в приложении). (т.е. в таблице не идет накопления записей).
Далее схема понятна. При редактировании проверяется наличие записи в таблице блокирововк и т.д. Но по части дисконнекта тут все решается автоматически. Если был дисконнект - блокировка будет снята. Поэтому в пакете НСИ достаточно при его каждом вызове первоначально выполнять вычитку блокировочной таблицы с группировкой по id_transaction (что кстати должно попутно убрать лишние версии) и далее в цикле пытаться удалить группы записей. Получил исключение - транзакция активна, не получил - удаляем "ничьи" записи.
Попутно вопрос по поводу for update with lock. Я не пойму смысла использования for update. Просто with lock бокирует нужный диапазон (where). В этой же транзакции работает update, для других - lock confict. Так в чем тут тонкости?
Для hvlad. Большое спасибо (кстати, о барском тоне - это не к тебе). Да , для меня лучше было бы определить активности (или неактивность транзакций), но ОАТ тоже подойдет - ты сам сказал, все что ниже - неактивно. В принципе пока шла эта переписка пришла мысль о другом подходе. Можно было бы помимо "главной транзакции" в документе стартовать еще одну параллельную транзакцию - блокирующую. Тогда при внесении аналитики в документ, пакет нормативно-справочной информации (НСИ) выполняет в своей короткой транзакции Append в общую блокировочную таблицу аналитик(заносится ID аналитики, ее имя, ID главной транзакции) и выполняется COMMIT. Далее блокирующая транзакция перезапускается и выполняется
Select ... from <блокировочная таблица> where id_transaction = <ID "главной" транзакции документа> with lock.
Т.е. после каждого внесения аналитики блокируемый список увеличивается.
После COMMIT/ROLLBACK "главной" транзакции (и соответственно блокирующей) выполняется удаление из блокировочной таблицы записей с id_transaction = <ID "главной" транзакции документа> (понятно, что ее значение можно сохранить в приложении). (т.е. в таблице не идет накопления записей).
Далее схема понятна. При редактировании проверяется наличие записи в таблице блокирововк и т.д. Но по части дисконнекта тут все решается автоматически. Если был дисконнект - блокировка будет снята. Поэтому в пакете НСИ достаточно при его каждом вызове первоначально выполнять вычитку блокировочной таблицы с группировкой по id_transaction (что кстати должно попутно убрать лишние версии) и далее в цикле пытаться удалить группы записей. Получил исключение - транзакция активна, не получил - удаляем "ничьи" записи.
Попутно вопрос по поводу for update with lock. Я не пойму смысла использования for update. Просто with lock бокирует нужный диапазон (where). В этой же транзакции работает update, для других - lock confict. Так в чем тут тонкости?
Видишь ли, кроме представлений о предметной области, неплохо бы ещё понимать особенности применяемого инструмента и соответственно, способы реализации требуемой алгоритмики на нём. Твой пространный пост про изобретённый велосипед, признаться, ниасилил (С), но из просмотра по диагонали сложилось впечатление, что вместо отношений m:n применено складывание ссылок в безразмерные строки-атрибуты. Что не позволяет задействовать родной для сервера механизм контроля reference integrity. Возможно и не прав, но вникать в велосипед ломотно, надо ещё свой горошек покатать по 969 таблицам. Но вот что таки непонятно из области прынцыпов - почему редактирование "справочника" недопустимо во время редактирования документа, но допустимо после того, как документ на него сослался? Нелогичность какая-то. Ссылка всё равно может оказаться неверной. Как я уже говорил, редактирование справочников - это вообще дурной тон, просветлённые в Дао допускают в справочниках только инсёрт, а редактирование - фактически аварийный режим для исправления очепяток. Сдаёцца мне, что тебе надо всего лишь обеспечить _видимость_ устойчивого снимка "справочников" на протяжении сеанса редактирования "документа". Если это так - не мучь Муму с блокировками, а просто выполняй редактирование документа с чтением справочников в одном снапшоте и будет тебе щастье.Viktor_Dnepropetrovsk писал(а):Да давно уже скачал, и пока БД не в реальной эксплуатации толк есть, но не очень много. А насчет правоты... 13 лет с бухгалтериями средних заводов и предприятий (транспорт, металлургия, услуги, торговля (хотя и на dbf (Cliiper5 сеть), но с хорошими результатами ) не очень то мы боимся и опыт есть. Все-таки ответ на свой вопрос я не получил. Чую, этот форум предназначен для того, чтобы потыкать носом студентов и прочих в статьи (кстати зачастую оторванные от реальной жизни) и немного на всех поплевать. Разочарован барским тоном и нежеланием помочь.
ЗЫ Тон таков, каков есть. Разбираться в проблемах того, кто загоняет себя в угол с проектированием и сочинять как ему из этого угла вылезать - занятие неблагодарное, потому что из некоторых углов выходов нет ваапче, а из некоторых - ну очень хитропроктологические, а нервную энергию и со своей проктологией есть куда потратить. Помочь же в смысле указать на возможные концептуальные ошибки, лежащие на поверхности и ткнуть носом в нужную сторону - всегда пожалуйста.
ЗЗЫ Насчёт разницы select for update и просто select в указанной тебе статье всё разжёвано...
-
- Сообщения: 14
- Зарегистрирован: 28 апр 2005, 23:07
Не всякой редактирование недопустимо. Недопустимо удаление, смена даты (если есть в справочнике временная привязка и ее изменение не соответствует дате документа). А почему нельзя во время редактирования, а потому что ссылачная целостность обеспечивается не FK, а ручками - хранимыми процедурами, читающими задействованные ссылки в специальных таблицах, которые видны естественно после commit. Упаси боже, я не враг FK - там где можно чего себе жизнь осложнять. Но к сожалению FK - это жесткие структуры таблиц. Завтра изменится набор справочников для этой таблицы - будем вводить поле, создавать FK,перекачивать данные и т.п. Спасибо, знаем.Но вот что таки непонятно из области прынцыпов - почему редактирование "справочника" недопустимо во время редактирования документа, но допустимо после того, как документ на него сослался?
Да, согласен,что редактирование - редко используемый режим, но к сожалению не аварийный при временном подходе. Я приводил примеры "закрытия даты" основной записи аналитики - человека уволили, основное средство ликвидировали, р/счет закрыли и т.п. Не убирать эти аналитики из селекта по справочнику на дату документа -Ссылка всё равно может оказаться неверной. Как я уже говорил, редактирование справочников - это вообще дурной тон, просветлённые в Дао допускают в справочниках только инсёрт, а редактирование - фактически аварийный режим для исправления очепяток.
источник неприятностей, долгого рытья в данных и поиск крайнего.
Так что кроме инсёрта бывают и упдате. Вообще, я честно говоря не видел, чтобы кто-то серьезно морочил себе голову с временными привязками в справочниках бухгалтерских программ, а спросите толкового бухгалтера - ух как он этого захочет.
По поводу блокировки - уже все опробовано, дырок вроде бы нет, и нет мертвой блокировки (не требуется вмешательства сисадмина).
Ты мне скажи, пожалуйста, в чем разница для целей блокированияЗЗЫ Насчёт разницы select for update и просто select в указанной тебе статье всё разжёвано...
1. select ... from ... where a = ... for update with lock
2. select ... from ... where a = ... with lock
И еще. Я не знаю механизма with lock, (подозреваю, что создаются версии записей), поэтому спрашиваю - ни к чему плохому не приведет
select A from TBL where B =1 with lock
insert into TBL (A,B) values ('bbb',1)
select A from TBL where B =1 with lock
insert into TBL (A,B) values ('ccc',1)
select A from TBL where B =1 with lock
....
А смена даты при условии наличия ссылающихся документов допустима? Процедуркой-триггером проверим? Ну-ну.Viktor_Dnepropetrovsk писал(а): Не всякой редактирование недопустимо. Недопустимо удаление, смена даты (если есть в справочнике временная привязка и ее изменение не соответствует дате документа).
А вот FK видит до коммит и снимает всю эту массу гемора, в общем случае не разруливаемого. Для того и придуман.Viktor_Dnepropetrovsk писал(а): А почему нельзя во время редактирования, а потому что ссылачная целостность обеспечивается не FK, а ручками - хранимыми процедурами, читающими задействованные ссылки в специальных таблицах, которые видны естественно после commit.
Предпочитаешь постоянный гемор с сомнительным в общем случае многопользовательского режима успехом при текущей работе гипотетически-вероятному и незначительному при модификации модели? Насчёт перекачивания - ни пониль. Если в существующие записи надо добавить ссылки на новый справочник, то это надо сделать при любой модели. Если же не надо - кто мешает сделать FK по nullable полю? Или заполнить в старых ссылкой на запись "не определено" единым махом?Viktor_Dnepropetrovsk писал(а): Упаси боже, я не враг FK - там где можно чего себе жизнь осложнять. Но к сожалению FK - это жесткие структуры таблиц. Завтра изменится набор справочников для этой таблицы - будем вводить поле, создавать FK,перекачивать данные и т.п. Спасибо, знаем.
А ввести кроме даты ликвидации признак живой-дохлый для упрощения селектов действующих ныне снимков справочников, а даты оставить для действий задним числом?Viktor_Dnepropetrovsk писал(а): Я приводил примеры "закрытия даты" основной записи аналитики - человека уволили, основное средство ликвидировали, р/счет закрыли и т.п. Не убирать эти аналитики из селекта по справочнику на дату документа - источник неприятностей, долгого рытья в данных и поиск крайнего.
Не там смотрелViktor_Dnepropetrovsk писал(а): Вообще, я честно говоря не видел, чтобы кто-то серьезно морочил себе голову с временными привязками в справочниках бухгалтерских программ

Не верю (С) Станиславский. Но убеждать пространно не надо, искать случай, когда вылезет либо то, либо другое лень. Но он есть по определению.Viktor_Dnepropetrovsk писал(а): По поводу блокировки - уже все опробовано, дырок вроде бы нет, и нет мертвой блокировки (не требуется вмешательства сисадмина).
ЗЗЫ Насчёт разницы select for update и просто select в указанной тебе статье всё разжёвано...
Я один раз потратил вполне прилично времени на написание статьи и повторять то, что там написано, каждому в отдельности не намерен.Viktor_Dnepropetrovsk писал(а): Ты мне скажи, пожалуйста, в чем разница для целей блокирования
1. select ... from ... where a = ... for update with lock
2. select ... from ... where a = ... with lock
Зависит от уровня изоляции транзакций, размера записей и сетевых пакетов и того, что понимается под "плохим".Viktor_Dnepropetrovsk писал(а): И еще. Я не знаю механизма with lock, (подозреваю, что создаются версии записей), поэтому спрашиваю - ни к чему плохому не приведет
select A from TBL where B =1 with lock
insert into TBL (A,B) values ('bbb',1)
select A from TBL where B =1 with lock
insert into TBL (A,B) values ('ccc',1)
select A from TBL where B =1 with lock
....