
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
Зависит от...