Alexey
18.09.2017
13:28:42
Пардон, там не уникальный индекс.
Просто табличка с полями дата (без времени), тип и ItemCount int, и кластерный ПК по всем этим трём полям.
Ilia
18.09.2017
13:29:17
Alexey
18.09.2017
13:29:26
Если цикл не делать, то 5-6 документов из 4000 при тесте не вставляются, т.к. происходит ошибка, то самое задвоение
Ilia
18.09.2017
13:29:44
Google
Alexey
18.09.2017
13:29:45
キリル
18.09.2017
13:30:05
pk автоматически подразумевает уникальный индекс на поле или набор полей
Ilia
18.09.2017
13:30:09
Вот в этом и проблема. Код давай, тогда поговорим
С какого перепугу ты цикл добалял ? Для чего?
Входящие транзакции вставки должны сериализоваться на изменении нового номера в таблице-генераторе, и получении его назад, поэтому никаких вставок с левыми (неправильными) номерами документов просто не может быть.
Всё
Alexey
18.09.2017
13:33:02
Хм, дело. Перевариваю.
キリル
18.09.2017
13:41:35
Ilia
18.09.2017
13:42:02
キリル
18.09.2017
13:42:31
update тоже в транзакции работает
Ilia
18.09.2017
13:42:42
Безусловно.
Google
Ilia
18.09.2017
13:43:01
Напомни мне ещё, НА КАКОМ УРОВНЕ ИЗОЛЯЦИИ UPDATE работат, а ?
キリル
18.09.2017
13:48:50
натурный эксперимент
сессия1:
create table t1(p1 integer);
create unique index i_t1 on t1(p1);
insert into t1 values(1);
commit;
update t1
set p1=p1+1
where p1=1;
заинсертилось
сессия 2:
update t1
set p1=p1+1
where p1=1;
блокировка
ничего неожиданного
Ilia
18.09.2017
14:00:22
Ну, так блокируется UPDATE, всё ОК?
Alexey
18.09.2017
14:36:26
Ох, перекопал ещё раз всё, а то мне тут понаговорили, что у меня 100%-ая какашка и надо делать Update.
Но ведь в условии сказано, что сессии не должны ждать друг друга. А если будет блокировка update внутри транзакции, то будет ожидание одной сессией, пока завершиться транзакция в другой сессии.
А при инсерте такого не будет.
Есть аргументы на эту мысль?
Ilia
18.09.2017
14:40:42
А за счёт чего ты будешь новый идентификатор генерировать в таком случае?
МОжет я не понял, ты объясни...
Alexey
18.09.2017
14:41:09
Ты видел мой код, там написано за счёт чего
Ilia
18.09.2017
14:41:29
Я не понял. Ладн, ща посмотрю.
Alexey
18.09.2017
14:42:12
*Я могу тут расписать всё, но мне кажется быстрее будет в коде разобраться :)
Ilia
18.09.2017
14:42:47
(Напоминаю, что код вижу только я)
Alexey
18.09.2017
14:43:59
хм, я смогу его всем только завтра показать ближе к полуночи
желающим могу кинуть в личку
Там вся суть, что я вместо апдейта таблицы с хранлищем номером, произвожу инсерт в неё.
А потом беру номер для нового документа так
select
@ItemIndexMax = max([ItemIndex])
from dbo.[Numbers]
where [Date] = @Date
and [TypeId] = @TypeId
Ilia
18.09.2017
14:45:40
Ну блин, там у тебя дофига мелких ошибок, не может это всё работать.
Alexey
18.09.2017
14:45:47
=D
Опять мелких ошибок
Ilia
18.09.2017
14:46:16
Как бы тут такая вещь, что все детали очень важны.
Alexey
18.09.2017
14:46:26
эта логика оправдывает мой пк на три поля, оправдывает цикл и что там ещё было
не оправдывает только отсутствие отката транзакции при raiserror, там да, косяк
попробуй принять, что там косяк только с отсутствием отката транзакции.
Может быть тогда логика станет понятной.
Ilia
18.09.2017
14:48:28
вот выбрал ты очередной номер, вот вставляешь его обратно в таблицу:
insert into dbo.[VelesTestDocsNumbers] (
Выбраться могут параллельно два одинаковых ключа.
Вставиться — нет, у тебя там ключ первичный по новому ID.
НО ты результат вставки нифига не проверяешь....
Если оно НЕ вставилось, ты так дальше и почапаешь...
Google
Ilia
18.09.2017
14:48:45
set transaction isolation level read uncommitted — - НАФИГА ?
Нет, нормально...
Alexey
18.09.2017
14:49:10
да всё для того же =D
и как же не проверяю результат вставки? там же try catch стоит. Не вставится, будет ошибка, попробуем ещё раз.
Ilia
18.09.2017
14:49:45
У тебя тут вообще-то SERIALIZABLE должно было бы быть, а не READ UNCOMMITED>
Я современный MS плохо знаю.
(это видимо он)
Alexey
18.09.2017
14:51:01
SERIALIZABLE - но ведь это самый высокий уровень изоляции. Тогда точно условие "сессии не должны ждать друг друга" не будет выполнено.
Ilia
18.09.2017
14:51:20
Оно должно быть на одном операторе.
Fike
18.09.2017
14:53:44
Всем привет.
Есть задачка. Я её решил по своему, мои тесты прошли. Но мне сказали, что я с ней не справился, пока без уточнения подробностей.
Мб кто подскажет другое решение? (своё пока не открываю)
Есть табличка с кучей записей, и туда постоянно вставляют новые записи, очень часто.
Каждая строка это документ, и у этого документа есть уникальный номер (varchar(32)), который формируется из даты его создания, его типа (А, Б, С, ...) и порядкового номера (int). И этот порядковый номер меняется от 1 до N в рамках дня создания(!) и типа документа(!).
Т.е. номера, например, будут такие:
20170917/А-1
20170918/А-1
20170918/А-2
20170918/Б-1
20170918/С-1
20170918/С-2
20170918/С-3
20170919/А-1
...
Уникальный индекс на этот номер вешать нельзя по условию.
При проверке запускается тест скрипт, четыре раза из четырёх разных сессий, который в цикле, с задержкой 50мс или около того, вставляет записи в эту табличку.
Как реализовать заполнение такой таблички с формирлованием такого номера для каждого документа, но что бы не было задвоения этих номеров?
0. Поставить READ COMMITTED
1. Получить максимальное значение за день
2. id = максимальное значение + 1
3. Вставить запись с указанным id
4. Проверить количество совпадений, если больше одного, откатить транзакцию и повторить
5. Вызвать на дуэль того домового, который придумал запрет на уникальный индекс
Alexey
18.09.2017
14:55:25
Fike
18.09.2017
14:55:38
почему они ждать-то будут?
Alexey
18.09.2017
14:55:44
lost
18.09.2017
14:55:45
Alexey
18.09.2017
14:56:00
lost
18.09.2017
14:56:08
латенси в триггерах - новый вид наркомании
о таком я еще не думал
Fike
18.09.2017
14:56:25
ну в принципе можете и понизить уровень изоляции, просто ложных срабатываний прибавите
Alexey
18.09.2017
14:57:27
Я просто напомню, что это именно задачка, а не практический пример. Поэтому извращение с тригером, задержками и запретом на уникальный индекс.
Google
Alexey
18.09.2017
14:57:37
желающим, могу кинуть код (задания и решения), только напишите в личку
Fike
18.09.2017
14:58:32
ну у вас ровно два решения
оптимистичная блокировка и пессимистичная блокировка
я предлагаю оптимистичную
Alexey
18.09.2017
14:59:27
крутые термины, секунду, прогуглю)
Fike
18.09.2017
14:59:29
ждать оно нигде не должно, write-локи если и есть, то только на добавляемые записи
Ilia
18.09.2017
15:00:13
А я - пессимистичненькую : )
Fike
18.09.2017
15:01:20
Да что там гуглить. Пессимистичная: сделаем все операции внутриэксклюзивно взятого ресурса. Оптимистичная: попробуем добавить, а если инвариант не выполнился, откатим.
Пессимистичная, кстати, у вас прям по задаче невозможна
лол
Ilia
18.09.2017
15:01:46
Fike
18.09.2017
15:01:51
Потому что при пессимстичной они будут вынуждены ждать друг друга
мы не рассматриваем плохо работающую систему в рамках задачи
Al
18.09.2017
15:03:23
Всем привет.
Есть задачка. Я её решил по своему, мои тесты прошли. Но мне сказали, что я с ней не справился, пока без уточнения подробностей.
Мб кто подскажет другое решение? (своё пока не открываю)
Есть табличка с кучей записей, и туда постоянно вставляют новые записи, очень часто.
Каждая строка это документ, и у этого документа есть уникальный номер (varchar(32)), который формируется из даты его создания, его типа (А, Б, С, ...) и порядкового номера (int). И этот порядковый номер меняется от 1 до N в рамках дня создания(!) и типа документа(!).
Т.е. номера, например, будут такие:
20170917/А-1
20170918/А-1
20170918/А-2
20170918/Б-1
20170918/С-1
20170918/С-2
20170918/С-3
20170919/А-1
...
Уникальный индекс на этот номер вешать нельзя по условию.
При проверке запускается тест скрипт, четыре раза из четырёх разных сессий, который в цикле, с задержкой 50мс или около того, вставляет записи в эту табличку.
Как реализовать заполнение такой таблички с формирлованием такого номера для каждого документа, но что бы не было задвоения этих номеров?
Какая редкостная хрень. И кто и зачем придумал этот бред?
Alexey
18.09.2017
15:04:04
Какой ответ ты хочешь на этот вопрос?
lost
18.09.2017
15:06:57
вы хотите не ждать в mvcc, это взаимоисключающие параграфы
Alexey
18.09.2017
15:06:59
Etki, Ilia Zviagin, и другие - спасибо за инфу, переварю.
Я пока убегаю. Завтра, если кому будет интересно, поделюсь какое решение предполагали авторы задачи.
Fike
18.09.2017
15:07:47
lost
18.09.2017
15:08:42
а по-идее не в каждой бд можно манагер блокировок затюнить
Google
lost
18.09.2017
15:08:51
он же де-факто пессимистичный
Ilia
18.09.2017
15:09:40
Alexey
18.09.2017
15:10:55
мне очень важно твоё мнение, я тебе обязательно перезвоню
Al
18.09.2017
15:14:54
Решение видимо очень простое. Заводим табличку счетчик. Читаем номер прибавляем 1. Вставляем новый номер для следующих сессий
В смысле все табличка из 1 строки с порядковым номером. Каждый день обнуляем его. Видел как то такой вариант. О.о
キリル
18.09.2017
15:20:22
lost
18.09.2017
15:21:22
и в некоторых случаях приходится делать такое
Alexey
18.09.2017
15:23:22
キリル
18.09.2017
15:23:45
да это я вернулся обратно в теме с пробелами в счетчике. у нас тут случилось разногласие по поводу видит ли 1 апдейт из 1 сессии данные другого
Какая изоляция транзакций, если там UPDATE ?
update тоже в транзакции работает
Да
я в одном проекте секвенс делал на таблице с автоинкрементом. хрень редкостная. после оракла с его секвенсами
Ilia
18.09.2017
15:26:13
キリル
18.09.2017
15:28:08
тогда я не понял то что вы мне хотели донести. все хорошо и все довольны))
Dmitriy
19.09.2017
06:40:03
Коллеги. На оракле кто то почистил таблицу, можно ли узнать кто? или хоть что, последние запросы и т.д.
Ilia
19.09.2017
07:02:01
Зависит от...