Size: a a a

2020 November 22

VE

Vladimir Eliseev in MySQL
Ребят, подскажите пожалуйста.
Почему, если несколько параллельных потоков будут выполнять такие транзакции, то номера employers.number будут инкрементировать последовательно:
start transaction;

SELECT max(number)+1 as cnt
FROM employers
FOR UPDATE;

insert into employers(...) values(cnt+1, ...);

commit;



НО!!!
Если убрать FOR UPDATE из поиска максимального номера, то параллельные транзакции пишут номера криво?
источник

DE

Denis Efremov in MySQL
Nikolay Semenov
DESCRIBE call; почему так не вызывается
Call зарезервированно
источник

MN

Max N. in MySQL
Vladimir Eliseev
Ребят, подскажите пожалуйста.
Почему, если несколько параллельных потоков будут выполнять такие транзакции, то номера employers.number будут инкрементировать последовательно:
start transaction;

SELECT max(number)+1 as cnt
FROM employers
FOR UPDATE;

insert into employers(...) values(cnt+1, ...);

commit;



НО!!!
Если убрать FOR UPDATE из поиска максимального номера, то параллельные транзакции пишут номера криво?
Ответ в твоем вопросе, потому что FOR UPDATE, почитай что он делает
источник

MN

Max N. in MySQL
AUTO INCREMENT  делает то, что ты навелосипедил в своей транзакции если что
источник

VE

Vladimir Eliseev in MySQL
Max N.
AUTO INCREMENT  делает то, что ты навелосипедил в своей транзакции если что
Ну, это ни совсем я.
Я просто пытаюсь исправить чужой косяк.

Объяснять всю логик не буду. Но смысл в том, что есть поле, которому нельзя задать auto increment.
Да, бывают такие ситуации.
Например, если есть таблица обращений. Назовем ее appeals.
В этой таблице есть поле id и оно под auto increment'ом.
Третьим полем этой таблицы, которое я хочу обозначить является поле create. Как ни странно, там хранится дата создания обращения.
Так же имеется мое "любимое поле" number. Условие состоит в том, что поле number должно увеличиваться в рамках текущего года.
Т.е. надо чтобы в рамках 2020 года number инкрементировалось относительно максимального number в этом году.

Я нашел 2 варианта решения проблемы:
1. Создать новую таблицу, напирмер number_year_max. И в нех ранить это максимальное число.
2. Делать все это в одной транзакции.
Мне понравился второй вариант.
Но только мне не ясно, почему оно работает. Уровень изоляции у меня  repeatable read.
источник

MN

Max N. in MySQL
Работает потому что FOR UPDATE получает эксклюзивную блокировку, параллельная транзакция не сможет считать MAX(number) пока текущая транзакция ее блокирует
источник

G

Grigorij in MySQL
Но вообще, ты так вроде пол таблицы блокируешь
источник

G

Grigorij in MySQL
Что есть не очень хорошо
источник

G

Grigorij in MySQL
Ну и твой вариант медленный. И/или требует отдельного индексы
источник

DE

Denis Efremov in MySQL
Vladimir Eliseev
Ну, это ни совсем я.
Я просто пытаюсь исправить чужой косяк.

Объяснять всю логик не буду. Но смысл в том, что есть поле, которому нельзя задать auto increment.
Да, бывают такие ситуации.
Например, если есть таблица обращений. Назовем ее appeals.
В этой таблице есть поле id и оно под auto increment'ом.
Третьим полем этой таблицы, которое я хочу обозначить является поле create. Как ни странно, там хранится дата создания обращения.
Так же имеется мое "любимое поле" number. Условие состоит в том, что поле number должно увеличиваться в рамках текущего года.
Т.е. надо чтобы в рамках 2020 года number инкрементировалось относительно максимального number в этом году.

Я нашел 2 варианта решения проблемы:
1. Создать новую таблицу, напирмер number_year_max. И в нех ранить это максимальное число.
2. Делать все это в одной транзакции.
Мне понравился второй вариант.
Но только мне не ясно, почему оно работает. Уровень изоляции у меня  repeatable read.
Что, каждый новый год оно на ноль сбрасывается?
источник

DE

Denis Efremov in MySQL
Vladimir Eliseev
Ну, это ни совсем я.
Я просто пытаюсь исправить чужой косяк.

Объяснять всю логик не буду. Но смысл в том, что есть поле, которому нельзя задать auto increment.
Да, бывают такие ситуации.
Например, если есть таблица обращений. Назовем ее appeals.
В этой таблице есть поле id и оно под auto increment'ом.
Третьим полем этой таблицы, которое я хочу обозначить является поле create. Как ни странно, там хранится дата создания обращения.
Так же имеется мое "любимое поле" number. Условие состоит в том, что поле number должно увеличиваться в рамках текущего года.
Т.е. надо чтобы в рамках 2020 года number инкрементировалось относительно максимального number в этом году.

Я нашел 2 варианта решения проблемы:
1. Создать новую таблицу, напирмер number_year_max. И в нех ранить это максимальное число.
2. Делать все это в одной транзакции.
Мне понравился второй вариант.
Но только мне не ясно, почему оно работает. Уровень изоляции у меня  repeatable read.
Условие состоит в том, что поле number должно увеличиваться в рамках текущего года.

В рамках года это как?
источник

MN

Max N. in MySQL
Grigorij
Но вообще, ты так вроде пол таблицы блокируешь
Это почему? 1 запись блокирует
источник

DE

Denis Efremov in MySQL
Denis Efremov
Что, каждый новый год оно на ноль сбрасывается?
Если так, то это вообще не нужно хранить. Это вычисляется из id записи минус id последней записи в предыдущем году.
источник

MN

Max N. in MySQL
Max N.
Это почему? 1 запись блокирует
А хотя MAX(number), какие там индексы хз, я чет думал что это pk)
источник

IZ

Ilia Zviagin in MySQL
Vladimir Eliseev
Ребят, подскажите пожалуйста.
Почему, если несколько параллельных потоков будут выполнять такие транзакции, то номера employers.number будут инкрементировать последовательно:
start transaction;

SELECT max(number)+1 as cnt
FROM employers
FOR UPDATE;

insert into employers(...) values(cnt+1, ...);

commit;



НО!!!
Если убрать FOR UPDATE из поиска максимального номера, то параллельные транзакции пишут номера криво?
Потому что и то и то неправильно
источник

VE

Vladimir Eliseev in MySQL
Grigorij
Что есть не очень хорошо
Согласен.
источник

VE

Vladimir Eliseev in MySQL
Значит лучше хранить максимальный номер в отдельной таблице, тогда не придется блокировать "крупную" часть таблицы.
источник

DE

Denis Efremov in MySQL
Переслано от Denis Efremov
Если так, то это вообще не нужно хранить. Это вычисляется из id записи минус id последней записи в предыдущем году.
источник

VE

Vladimir Eliseev in MySQL
Denis Efremov
Переслано от Denis Efremov
Если так, то это вообще не нужно хранить. Это вычисляется из id записи минус id последней записи в предыдущем году.
Да, читал...
Интересный подход.
Тогда +1 метод к решению задачи!
источник

MN

Max N. in MySQL
Denis Efremov
Переслано от Denis Efremov
Если так, то это вообще не нужно хранить. Это вычисляется из id записи минус id последней записи в предыдущем году.
Ты имеешь ввиду вычитать из колонки авто-инкремента?
источник