|
Реализация уникальности без ключей и индексов
|
|||
---|---|---|---|
#18+
НеофитSQL "обречены на провал" у вас означает Но стоит уточнить что именно пытаешься сымитировать. Цель недопустить двух одинаковых ключей в таблице или сэмулировать поведение с уникальным индексом, то есть 1. При наличии закомиченой записи* - exception 2. При наличии незакомиченной записи* - висим на блокировке до тех пор пока 2.1 commit - получаем exception 2.2 rollback - отлипаем 2.3 ключ изменен или удалён - отлипаем 3. При полном отсутствии записи* идём дальше ? * - понимается [с тем же ключом] Как было сказано, если полностью убить конкурентный доступ сериализацией то возможно удасться гарантировать уникальность, но смысла в этом чуть менее чем никакого. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.11.2020, 19:35 |
|
Реализация уникальности без ключей и индексов
|
|||
---|---|---|---|
#18+
SY: я перестарался с выявлением дупликатов во время post, емулируя dirty reads. Без этого код должен стать проще. Кобанчег, Я слышал сериализацию упоминалась много раз. Сериализация большой транзакции несомненно замедляет систему, но в некоторых случаях сериализованный доступ неизбежен. В этих ситуациях имеет смысл говорить об уменьшении кода в критической секции (или другом механизме синхронизации доступа). Даже сиквенс имеет сериализованный код, это не значет что сиквенсы плохие или медленные. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.11.2020, 22:28 |
|
Реализация уникальности без ключей и индексов
|
|||
---|---|---|---|
#18+
Кобанчег Цель недопустить двух одинаковых ключей в таблице или сэмулировать поведение с уникальным индексом Цель - второе. Была высказана гипотеза что это невозможно, но доказать невозможность с моим уровнем знаний довольно трудно, поэтому я работаю над контрпримером, заодно обучаясь тонкостям многосессионности. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.11.2020, 22:32 |
|
Реализация уникальности без ключей и индексов
|
|||
---|---|---|---|
#18+
С улучшенным пониманием как работаet встроенный constraint уникальности (спасибо, Кабанчег, за серый текст!) предпринимаю новую попытку реализовать subj максимально приближенный по поведению к pk_key. Оговорки: пока работает только для операции insert. Полагается на строковый лок через update. Может содержать ошибки. Я протестировал из двух разных сессий commits и rollbacks. Вроде работает. Код: plsql 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.
... |
|||
:
Нравится:
Не нравится:
|
|||
16.11.2020, 02:14 |
|
Реализация уникальности без ключей и индексов
|
|||
---|---|---|---|
#18+
НеофитSQL С улучшенным пониманием как работаet встроенный constraint уникальности (спасибо, Кабанчег, за серый текст!) Ну о том, что надо сначала читать, потом переваривать и думать и только потом выкладывать свой бред на потеху публике высказалось уже множество людей. НеофитSQL Может содержать ошибки. Код: plsql 1. 2. 3. 4. 5. 6. 7. 8.
... |
|||
:
Нравится:
Не нравится:
|
|||
16.11.2020, 07:08 |
|
Реализация уникальности без ключей и индексов
|
|||
---|---|---|---|
#18+
Кобанчег, У меня почему-то работало. Для "before" триггера таблица не должна мутировать. Завтра разберусь. ... |
|||
:
Нравится:
Не нравится:
|
|||
16.11.2020, 08:29 |
|
Реализация уникальности без ключей и индексов
|
|||
---|---|---|---|
#18+
НеофитSQL, применение dbms_lock по сути не отличается от Вашего исходного варианта с unique constraint на дополнительной таблице, поскольку примитивом синхронизации остается PK на доп. таблице: Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21.
... |
|||
:
Нравится:
Не нравится:
|
|||
16.11.2020, 14:13 |
|
Реализация уникальности без ключей и индексов
|
|||
---|---|---|---|
#18+
andrey_anonymous, Я не использую DBMS lock в последнем варианте кода. > применение dbms_lock по сути не отличается от Вашего исходного варианта с unique constraint на дополнительной таблице, поскольку примитивом синхронизации остается PK на доп. таблице: Такое можно было бы сказать, если бы я использовал DBMS_LOCK на каждую строчку, но до такого я не додумался :) Использование одного уникального объекта схемы не приравнивается к использованию свойств PK. ... |
|||
:
Нравится:
Не нравится:
|
|||
16.11.2020, 18:41 |
|
Реализация уникальности без ключей и индексов
|
|||
---|---|---|---|
#18+
Кобанчег НеофитSQL С улучшенным пониманием как работаet встроенный constraint уникальности (спасибо, Кабанчег, за серый текст!) Ну о том, что надо сначала читать, потом переваривать и думать и только потом выкладывать свой бред на потеху публике высказалось уже множество людей. НеофитSQL Может содержать ошибки. Код: plsql 1. 2. 3. 4. 5. 6. 7. 8.
Да, я вижу то же самое у себя. Тесты делал с "insert into test32 values(n)", ошибок не было. Различие в поведении между двумя способами доступа мне непонятно - Оракл особо обрабатывает однострочный insert? Решение известно, например compound trigger. На время, сужаю применимость моего решения для одиночных insert. (про delete, update, truncate было сказано в начале). Можно ли считать мое решение неотличимым от PK в поведении для одиночных insert? ... |
|||
:
Нравится:
Не нравится:
|
|||
16.11.2020, 18:57 |
|
Реализация уникальности без ключей и индексов
|
|||
---|---|---|---|
#18+
НеофитSQL Да, я вижу то же самое у себя. Тесты делал с "insert into test32 values(n)", ошибок не было. Различие в поведении между двумя способами доступа мне непонятно - Оракл особо обрабатывает однострочный insert? INSERT/UPDATE/DELETE - атомарная операция независимо от числа вставляемых/изменяемых/удаляемых строк. Mutating - это когда состояние таблицы когда уже не до INSERT/UPDATE/DELETE но еще не после. А вот INSERT VALUES это тот единственный случай когда ORACLE точно знает - вставка одной строки и посему BEFORE EACH ROW это точно до INSERT. SY. ... |
|||
:
Нравится:
Не нравится:
|
|||
16.11.2020, 19:52 |
|
Реализация уникальности без ключей и индексов
|
|||
---|---|---|---|
#18+
Уточню. При условии BEFORE INSERT statement триггер таблицу не модифицировал - иначе и INSERT VALUES выдаст мутацию. SY. ... |
|||
:
Нравится:
Не нравится:
|
|||
16.11.2020, 20:17 |
|
Реализация уникальности без ключей и индексов
|
|||
---|---|---|---|
#18+
SY НеофитSQL Да, я вижу то же самое у себя. Тесты делал с "insert into test32 values(n)", ошибок не было. Различие в поведении между двумя способами доступа мне непонятно - Оракл особо обрабатывает однострочный insert? INSERT/UPDATE/DELETE - атомарная операция независимо от числа вставляемых/изменяемых/удаляемых строк. Mutating - это когда состояние таблицы когда уже не до INSERT/UPDATE/DELETE но еще не после. А вот INSERT VALUES это тот единственный случай когда ORACLE точно знает - вставка одной строки и посему BEFORE EACH ROW это точно до INSERT. SY. В случае "insert .. select 0 from dual" оракл тоже точно знает что одна строка, но не использует это знание. Получается, Оракл особым образом обрабатывает insert..values() не так, как вставку таблицы из одной строки. Я такой технической детали не знал. Если такое поведение задокументировано, я теперь могу написать триггер который позволит вставлять строчки только через values(), и никаким другим способом. Но вряд ли пригодится :) Интересно почему для values() Оракл не использовал общий код мультистрочной вставки. Сомневаюсь что для оптимизации скорости, однострочные вставки заведомо не помогают производительности. Возможно, внутри у Оракла есть системный триггер которому удобно читать из модифицируемой таблицы, и оракл сделал специальную обработку insert..values() чтобы помочь себе. ... |
|||
:
Нравится:
Не нравится:
|
|||
16.11.2020, 20:26 |
|
Реализация уникальности без ключей и индексов
|
|||
---|---|---|---|
#18+
SY Уточню. При условии BEFORE INSERT statement триггер таблицу не модифицировал - иначе и INSERT VALUES выдаст мутацию. SY. Мне это уточнение непонятно. Мой "before insert by row" триггер вылетал на строке которая только читала из таблицы триггера. Вот максимально упрощенный пример: Код: plsql 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.
... |
|||
:
Нравится:
Не нравится:
|
|||
16.11.2020, 20:36 |
|
Реализация уникальности без ключей и индексов
|
|||
---|---|---|---|
#18+
Переделал свое решение чтобы позволить мультистрочные вставки. Проверил из двух разных сессий, сессии помечены #1/#2. Код: plsql 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.
... |
|||
:
Нравится:
Не нравится:
|
|||
16.11.2020, 21:01 |
|
Реализация уникальности без ключей и индексов
|
|||
---|---|---|---|
#18+
С мультистрочными insert пока не тестировал. Просматриваю свой код на предмет race conditions (когда commit/rollback произойдет в другой сессии во время исполнения триггера, и сразу несколько ожидающих сессий разблокируются). Проверю с двумя-тремя ожидающими сессиями, потом запощу код. ... |
|||
:
Нравится:
Не нравится:
|
|||
16.11.2020, 21:26 |
|
Реализация уникальности без ключей и индексов
|
|||
---|---|---|---|
#18+
НеофитSQL На время, сужаю применимость моего решения для одиночных insert. 1. Может случится, что две параллельные сессии проверят что в test_u нет строк и каждая вставит по одной. 2. Нет никаких гарантий что вторая сессия (в которой инсерт запустили после первой) не захватит блокировку в test_u первой. итд Градус абсурда зашкаливает, я уже пожалел что влез в эту тему. ... |
|||
:
Нравится:
Не нравится:
|
|||
16.11.2020, 21:40 |
|
Реализация уникальности без ключей и индексов
|
|||
---|---|---|---|
#18+
Кобанчег НеофитSQL На время, сужаю применимость моего решения для одиночных insert. 1. Может случится, что две параллельные сессии проверят что в test_u нет строк и каждая вставит по одной. 2. Нет никаких гарантий что вторая сессия (в которой инсерт запустили после первой) не захватит блокировку в test_u первой. итд Градус абсурда зашкаливает, я уже пожалел что влез в эту тему. 1. не влияет на логику. test_u позволительно содержать дубликаты. 2. одинаково относится к PK, там нет гарантий очередности насколько мне известно. ... |
|||
:
Нравится:
Не нравится:
|
|||
16.11.2020, 22:02 |
|
Реализация уникальности без ключей и индексов
|
|||
---|---|---|---|
#18+
НеофитSQL SY Уточню. При условии BEFORE INSERT statement триггер таблицу не модифицировал - иначе и INSERT VALUES выдаст мутацию. SY. Мне это уточнение непонятно. Код: plsql 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.
SY. ... |
|||
:
Нравится:
Не нравится:
|
|||
17.11.2020, 00:44 |
|
Реализация уникальности без ключей и индексов
|
|||
---|---|---|---|
#18+
SY, Спасибо за иллюстрацию! В этом коде триггер пишет в таблицу, это выглядит невероятно взрывоопасно. Я так понял глобальная переменная помогает избежать бесконечной рекурсии триггера, но неужели кто-то такое пишет? ... |
|||
:
Нравится:
Не нравится:
|
|||
17.11.2020, 02:32 |
|
Реализация уникальности без ключей и индексов
|
|||
---|---|---|---|
#18+
НеофитSQL С мультистрочными insert пока не тестировал. Просматриваю свой код на предмет race conditions (когда commit/rollback произойдет в другой сессии во время исполнения триггера, и сразу несколько ожидающих сессий разблокируются). Проверю с двумя-тремя ожидающими сессиями, потом запощу код. с учетом многосессионности, и возможности что много сессий зависли на уникальном значении и их нужно правильно разблокировать поодиночке, кода получается не так уж мало. Код: plsql 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.
Пришлось в дополнение к вспомогательной таблице test_u, которая используется для row-level locks, завести GTT test_t, в которой находятся posted, not committed строчки из каждой сессии. Тело триггера стало напоминать псевдокод: Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20.
... |
|||
:
Нравится:
Не нравится:
|
|||
17.11.2020, 02:44 |
|
Реализация уникальности без ключей и индексов
|
|||
---|---|---|---|
#18+
НеофитSQL Пришлось Но и это не помогло реализовать unique Код: plsql 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.
... |
|||
:
Нравится:
Не нравится:
|
|||
17.11.2020, 09:48 |
|
Реализация уникальности без ключей и индексов
|
|||
---|---|---|---|
#18+
Реализация уникальности через триггер - идея заведомо обречённая на провал, т.к. есть операции при которых триггер не будет задействован. Можно сделать, что вы и продемонстрировали, кучу кода для вырожденного случая, но не более того. ... |
|||
:
Нравится:
Не нравится:
|
|||
17.11.2020, 09:53 |
|
Реализация уникальности без ключей и индексов
|
|||
---|---|---|---|
#18+
НеофитSQL SY, Спасибо за иллюстрацию! В этом коде триггер пишет в таблицу, это выглядит невероятно взрывоопасно. Я так понял глобальная переменная помогает избежать бесконечной рекурсии триггера, но неужели кто-то такое пишет? За всю Одессу я не скажу. Мой пример просто иллюстрация что в принципе таки можно. SY. ... |
|||
:
Нравится:
Не нравится:
|
|||
17.11.2020, 13:36 |
|
Реализация уникальности без ключей и индексов
|
|||
---|---|---|---|
#18+
env Реализация уникальности через триггер - идея заведомо обречённая на провал, т.к. есть операции при которых триггер не будет задействован. Можно сделать, что вы и продемонстрировали, кучу кода для вырожденного случая, но не более того. Я не сомневаюсь что самодельная реализация будет проигрывать встроенной, тут иллюзий нет. Мой constraint не покажется в списке constraints, его можно отключить деактивацией триггера, со вспомогательными таблицами можно проводить манипуляции, и т.д. Цель была - понять есть ли в языке достаточно возможностей для реализации несложных constraints по колонке. Уникальность была выбрана, потому что это наипростейший из встроенных, и его поведение хорошо описано. В данный момент я разбираюсь, в какой очередности select... for update отпускает сессии которые на нем застряли, и есть ли способ узнать попал ли select.. for update на лок, или успешно отработал. Мне не нравится моя конструкция с "nowait/retry", из-за возможных race conditions, а сериализировать эту часть кода нельзя. Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.
... |
|||
:
Нравится:
Не нравится:
|
|||
17.11.2020, 14:06 |
|
Реализация уникальности без ключей и индексов
|
|||
---|---|---|---|
#18+
Из моих экспериментов, Оракл соблюдает очередность для select.. for update, и мой row-locking код значительно упростился. Чтобы не утомлять публику частыми апдейтами, дам триггеру еще помариноваться. Вопрос по теме: как в Оракле можно эффективно реализовать constraint двуникальности? Чтобы в одной колонке находилось не более двух одинаковых значений? Эффективно - значит без table lock или строгой сериализации доступа к таблице. ... |
|||
:
Нравится:
Не нравится:
|
|||
17.11.2020, 14:15 |
|
|
start [/forum/topic.php?fid=52&msg=40019111&tid=1880705]: |
0ms |
get settings: |
8ms |
get forum list: |
12ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
179ms |
get topic data: |
9ms |
get forum data: |
2ms |
get page messages: |
70ms |
get tp. blocked users: |
1ms |
others: | 13ms |
total: | 302ms |
0 / 0 |