|
|
|
Задачка
|
|||
|---|---|---|---|
|
#18+
И поделом мне. Классический случай который я только-что описал для andrey_anonymous. SY. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.10.2005, 01:53 |
|
||
|
Задачка
|
|||
|---|---|---|---|
|
#18+
SYИ поделом мне. Классический случай который я только-что описал для andrey_anonymous. SY. Бывает. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.10.2005, 01:56 |
|
||
|
Задачка
|
|||
|---|---|---|---|
|
#18+
SY ..... CREATE OR REPLACE TRIGGER BIUR_AAA_VIEW INSTEAD OF INSERT OR UPDATE ON AAA_VIEW FOR EACH ROW DECLARE v_cnt NUMBER; BEGIN SELECT COUNT(*) INTO v_cnt FROM AAA WHERE LAST_NAME = :NEW.LAST_NAME AND DEPARTMENT = :NEW.DEPARTMENT; -- -- а в это время в другой сессии тож вставили две записи :) -- IF v_cnt >= 3 .... [/src] SY. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.10.2005, 10:36 |
|
||
|
Задачка
|
|||
|---|---|---|---|
|
#18+
SYActually, I overlooked a major issue with your solution. It simply will not work. Assume session A inserts a row (for simplicity lets say table is empty). That row will have index value of 1/#/Q!Q/#/1. Session A does not commit/rollback yet. Now session B tries to insert a row. Obviously, table is locked and session B waits. Now the fun part - read consistency. Since session B transaction started before Session A committed, session B will not see any changes done by session A. So when session A will commit and release the lock, session B will also try to insert index value 1/#/Q!Q/#/1 and will get unique constraint violation. SY. "and will get unique constraint violation". Тем не менее ограничение целостности выполняется, хотя в случае конкурентного доступа может возникать ложная тревога. Получив данную ошибку нужно ещё два раза повторить попытку. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.10.2005, 10:39 |
|
||
|
Задачка
|
|||
|---|---|---|---|
|
#18+
__LEV__Да согласен, наверно можно упростить. По поводу дополнительных таблиц - блокировки (dbms_lock)тоже ведь хранятся в системных таблицах - теже таблицы,та же нагрузка на ввод/вывод. К тому же количество блокировок ограничено (порядок 10^9), боюсь "на всех не хватит". Могу ошибаться,но мне кажется, что без дополнительной таблицы (своей, системной и т.п.) не обойтись. Сами посудите: анализировать текущую таблицу в любом типе триггера(пакете и т.п.) - бесполезно - не видно не подтвержденных транзакций других сессий. Хочешь упорядочить операции - юзай оракл (ключи, юник индексы и т.п.). Мне кажется что ответив на этот вопрос(с доп таблицами), мы определимся в каком направлении копать. Я всегда думал, что пользовательские блокировки размещаются в оперативной памяти, более того, количество одновременно существующих блокировок далеко не 10^9, оно не превышает ENQUEUE_RESOURCES. При чём надо обратить внимание, что оркл вычисляет ENQUEUE_RESOURCES по умолчанию исходя из того, что пользовательских блокировок не будет. При использовании пользовательских блокировок значение этого параметра нужно увеличивать вручную. У меня с пользовательскими блокировками был случай. Когда параметры DML_LOCKS и ENQUEUE_RESOURCES оказались несогласованными при выделении большого числа пользовательских блокировок падал фоновый процесс сервера, ему не хватало очередизируемых ресурсов. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.10.2005, 11:11 |
|
||
|
Задачка
|
|||
|---|---|---|---|
|
#18+
Ещё вот такой вариант. Основан на использовании дополнительной таблицы с номерами однофамильцев. Триггер автоматически назначает свободный номер, который не занят незавершенными транзакциями. Если все номера заняты, ждёт освобождения одного из них и повторяет попытку. Если свободных номеров нет совсем, поднимается dup_val_on_index. Два триггера нужны для того, чтобы правильно отрабатывать ожидание и удаление 0 строк. Обновление 0 строк работает не совсем корректно, в том плане что ругается на нарушение уникальности, тогда как обновлять уже нечего. Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92. 93. 94. 95. 96. 97. 98. 99. 100. 101. 102. 103. 104. 105. 106. 107. 108. 109. 110. 111. 112. 113. 114. 115. 116. 117. 118. 119. 120. 121. 122. 123. 124. 125. 126. 127. 128. 129. 130. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.10.2005, 13:48 |
|
||
|
Задачка
|
|||
|---|---|---|---|
|
#18+
SYActually, I overlooked a major issue with your solution. It simply will not work. Assume session A inserts a row (for simplicity lets say table is empty). That row will have index value of 1/#/Q!Q/#/1. Session A does not commit/rollback yet. Now session B tries to insert a row. Obviously, table is locked and session B waits. Now the fun part - read consistency. Since session B transaction started before Session A committed, session B will not see any changes done by session A. So when session A will commit and release the lock, session B will also try to insert index value 1/#/Q!Q/#/1 and will get unique constraint violation. SY.Описанное Вами поведение имеет место быть, но... Как ни странно, это поведение присуще почти всем приведенным реализациям в той или иной форме, а именно: мы должны каким-либо образом "скоординировать" усилия _всех транзакций, производящих изменения, с точки зрения обеспечения уникальности "троичного" :) ключа. В предложенной реализации FBI я не стал этим заниматься, о чем сразу честно написал. При этом следует сразу отметить, что если таковая синхронизация технически возможна (в чем я почти не сомневаюсь), то ничто не мешает добавить ее в решение на FBI. НО, повторюсь, эта проблема в той или иной форме присуща _всем приведенным _работающим решениям. Теперь про "разрушенный" индекс. Обсуждаемое решение предназначено для обеспечения целостности. Оно изначально не предназначалось для обеспечения _поиска. Поэтому данная критика, хотя и справедлива, не имеет практического значения. Для DML-операций FBI реализует что-то вроде "стека" индексных ключей, чем и обеспечивает целостность. Я пока не нашел сценария, в котором "порушенные" ROWID помешают выполнению основной задачи. Попробую резюмировать: - оно работает - оно НЕ deterministic, и это надо четко понимать (dbms_output я включил специально дабы можно было понаблюдать за этим забавным процессом) - оно решает вполне конкретную задачу без претензий на "универсальность" - оно представляется надежнее "триггерных" решений, поскольку: как справедливо было отмечено, проверит целостность существующих данных уже при создании индекса. может либо работать целиком, либо не работать вообще (триггера, например, могут быть отключены по одному и включены обратно с предсказуемыми последствиями в виде сложно проверяемой нарушенной целостности данных) ВАЖНОЕ ЗАМЕЧАНИЕ : "добавочный" кусок кода - обязательная часть решения. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.10.2005, 15:35 |
|
||
|
Задачка
|
|||
|---|---|---|---|
|
#18+
andrey_anonymous Попробую резюмировать: - оно работает Код: plaintext 1. 2. 3. 4. 5. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.10.2005, 16:16 |
|
||
|
Задачка
|
|||
|---|---|---|---|
|
#18+
Stax. andrey_anonymous Попробую резюмировать: - оно работает Код: plaintext 1. 2. 3. 4. 5. Можно весь сценарий? И еще один момент - Вы "патчик" прикрутили? (иначе будут проблемы со сценариями, включающими rebuild индекса) =) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.10.2005, 17:43 |
|
||
|
Задачка
|
|||
|---|---|---|---|
|
#18+
andrey_anonymous Stax. andrey_anonymous Попробую резюмировать: - оно работает Код: plaintext 1. 2. 3. 4. 5. Можно весь сценарий? И еще один момент - Вы "патчик" прикрутили? (иначе будут проблемы со сценариями, включающими rebuild индекса) =) патчык не прыкручивал, токо инсерт и делете, правда я поле ID добавил в таблицу, мне так удобнее, счас удалю все и постараюсь поторить, или мона с Код: plaintext 1. 2. 3. 4. ........ Stax ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.10.2005, 18:17 |
|
||
|
Задачка
|
|||
|---|---|---|---|
|
#18+
Stax.жду ответа? Ладно пересоздал Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. Вторая сессия Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. ....... Stax ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.10.2005, 18:59 |
|
||
|
Задачка
|
|||
|---|---|---|---|
|
#18+
Stax.жду ответа? Млин, ну ведь терзали же душу смутные сомнения когда я решал - "взрывать" при переполнении или возвращать дублирующий ключ. Бага. Все строки Код: plaintext Код: plaintext - сессия1: delete все вхождения для заданного nom_otd, Name1 - сессия2: insert с переполнением для nom_otd, Name1 (висит, ждет) - сессия1: commit - сессия2: _диагностировано переполнение, но запись вставляется, поскольку "гарантированно дублированный ключ" .../#/1 только что удален. Индекс порушен. Но к ROWID это не имеет никакого отношения. Если при обнаружении переполнении просто рвать - все стастается. Вариант - иметь технологическую запись и в качестве "дублирующего" возвращать "технологический" ключ. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.10.2005, 20:23 |
|
||
|
Задачка
|
|||
|---|---|---|---|
|
#18+
[quot andrey_anonymousЕсли при обнаружении переполнении просто рвать - все стастается.[/quot] Не срастается :( Да, приведенный алгоритм организации "стека" ущербен. 1: insert 1: insert 1: commit; 1: delete all 2: insert 1: commit; 2: commit; тоже приведет к нарушению структуры индекса, поскольку последующий delete будут удалять ключ /#/1, а индексе останется /#/3 :( ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.10.2005, 20:41 |
|
||
|
Задачка
|
|||
|---|---|---|---|
|
#18+
andrey_anonymous[quot andrey_anonymousЕсли при обнаружении переполнении просто рвать - все стастается. Не срастается :( [/quot] во-во я тож пробовал fbi но на мутацию нарвался, а автономная не видит даже себя ..... Stax ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.10.2005, 21:04 |
|
||
|
Задачка
|
|||
|---|---|---|---|
|
#18+
Stax.во-во я тож пробовал fbi но на мутацию нарвался, а автономная не видит даже себя ..... StaxЯ этого так не оставлю Задача ставится так: необходимо обеспечить алгоритм формирования индексных ключей такой, что: 1. ключи различны для трех идентичных вхождений (nom_otd, name1). 2. ключ не должен формироваться для четвертого и последующих идентичных вхождений (nom_otd, name1). 3. ключ должен непротиворечиво вычисляться в операциях удаления и вставки узлов индекса. Собственно, задача - алгоритмическая. Цимус только в решении без привлечения "посторонних" табличек. Нужен дешевый способ проверки существования узла индекса с заданным ключем. Тогда delete сможет "пробовать" предполагаемые к удалению ключи, а insert - отыскивать возможные "дырки" и не давать ложных срабатываний. Можно было бы посмотреть в сторону indextype, но это неспортивно и не позволит оставить за собой приз ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.10.2005, 21:21 |
|
||
|
Задачка
|
|||
|---|---|---|---|
|
#18+
Подниму-ка... (искал материал по теме truncate vs alter table move вот и наткнулся :) ) Задачка интересная. Все сказанное ИМХО. Решение можно найти только тремя путями: (1) +доп таблица, (2) +доп колонка и (3) задействовать AQ. Что касается третьего, то все более-менее прозрачно, но уж очень хитро. А вот 1 и 2 -- близнецы, только 2-й путь более корявый. Итак, способ с доп таблицей. Код: plaintext 1. 2. 3. 4. 5. 6. Оговариваем особо -- все действия по записи в таблицу делать только через наш пакет: insert, move, rename, delete (вставка работника, перемещение меж отделами, смена фамилии, увольнение). Самый простой алгоритм -- для вставки. 0. savepoint lock_begin 1. Делаем insert в таблицу lock2 номера отдела и фамилии 2. Считаем количество однофамильцев в отделе 2.1. Если уже есть три -- rollback до lock_begin и нафик. 2.2. Иначе вставляем в таблицу полноценную запись 3. выполняем delete from lock2 строки с номером отдела и фамилией. 4. commit В случае переименования или перемещения -- в lock2 пишем две строки. Лучше за один раз, что бы избежать потенциального deadlock (соседняя сессия, к примеру, синхронно вставляет те же две строки, но в обратном порядке) Удаление -- ну тут как скажут, либо удаляем просто, либо помечаем как уволенного (к слову, у нас ОК не удаляет, employee_id уже за 50К перевалило) Предложенный способ должен кмк работать в любых случаях -- мы пользуемся стандартными локингами БД, второй инсерт в lock2 с теми же отделом и фамилией просто будет ждать окончательного коммита первого. При чем не мешая работе с другими парами. Алгоритм, надеюсь, понятен. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.09.2006, 18:39 |
|
||
|
Задачка
|
|||
|---|---|---|---|
|
#18+
Затык а том, что корректная проверка условия может быть осуществлена только при коммите. Два пути решения: 1. Было у Tom Kyte несколько раз, например тут Строится MV refresh on commit в котором считается число однофамильцев, а на MV создается check constraint. 2. Было в старом Oracle Magazine. В основной таблице создается дополнительная колонка с числом однофамильцев, поддерживается триггерами. На ней висит deferred constaraint, который при коммите проверяет, чтобы однофамильцев было не больше 3. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.09.2006, 19:30 |
|
||
|
Задачка
|
|||
|---|---|---|---|
|
#18+
Sergei.AgalakovЗатык а том, что корректная проверка условия может быть осуществлена только при коммите. Сергей, изюминка в том, что в моем способе получается, что с конкретной парой Отдел-Фамилия работает строго один процесс, остальные с такой же парой ждут. Если пара другая -- "мы друг другу не мешаем". =Максим ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.10.2006, 14:58 |
|
||
|
Задачка
|
|||
|---|---|---|---|
|
#18+
Офф. забавный термин: "стандартные локинги БД" хочется добавить: лэтчинги, коммитинги, процедуринги ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.10.2006, 15:35 |
|
||
|
|

start [/forum/topic.php?fid=52&msg=33333989&tid=1956403]: |
0ms |
get settings: |
6ms |
get forum list: |
15ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
36ms |
get topic data: |
8ms |
get forum data: |
2ms |
get page messages: |
58ms |
get tp. blocked users: |
1ms |
| others: | 210ms |
| total: | 342ms |

| 0 / 0 |
