powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Deadlock при добавлении строки
25 сообщений из 42, страница 1 из 2
Deadlock при добавлении строки
    #38511967
Oleg8000
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Здравствуйте.

Есть такая задача: пополнение баланса пользователя.

По запросу на пополнение баланса выполняется простой алгоритм: Ищем в таблице балансов запись, которая принадлежит пользователю. Если у пользователя есть баланс, то такая запись присутствует, если баланса нет - записи тоже нет.
Если приходит одновременно несколько запросов на пополнение баланса одному юзеру, у которого нет записи (нулевой баланс), то случается deadlock.

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
START TRANSACTION;
SELECT * FROM `balances` WHERE id=1 FOR UPDATE;
...
// если существует запись, делается UPDATE - с этим проблем нет, т.к. существующая запись блокируется SELECT-ом в начале транзакции
UPDATE `balances` SET `balance` = `balance`+10 WHERE `id` = 1;

// если записи нет,  делается INSERT - вот тут появляется deadlock, если до этого момента началась вторая транзакция, т.к. SELECT в начале транзакции ничего не заблокировал
INSERT INTO `balances` (`id`, `balance`) VALUES (1, 10.00);

COMMMIT;



id - не является автоинкрементом, на самом деле это USER_ID

Пробовал INSERT ... ON ON DUPLICATE KEY UPDATE - также не решает проблемы.

Как решить проблему?
...
Рейтинг: 0 / 0
Deadlock при добавлении строки
    #38512036
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Oleg8000,

Дай определение таблицы balances.
В частности, интересно какие там индексы и какой движок используется. (storage engine).
...
Рейтинг: 0 / 0
Deadlock при добавлении строки
    #38512039
tanglir
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Oleg8000
Код: sql
1.
если существует запись, делается UPDATE - с этим проблем нет, т.к. существующая запись блокируется SELECT-ом в начале транзакции

Решение напрашивается само собой - сразу создавать для нового пользователя запись с нулевым балансом.
...
Рейтинг: 0 / 0
Deadlock при добавлении строки
    #38512077
Oleg8000
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MasterZiv,
Код: sql
1.
2.
3.
4.
5.
CREATE TABLE IF NOT EXISTS `balances` (
  `id` int(1) NOT NULL,
  `balance` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
...
Рейтинг: 0 / 0
Deadlock при добавлении строки
    #38512080
Oleg8000
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
tanglirРешение напрашивается само собой - сразу создавать для нового пользователя запись с нулевым балансом.
Не хотелось бы... юзеров будет очень много, поэтому решили вынести баланс в отдельную таблицу, чтобы работа с балансом была максимально быстрой
...
Рейтинг: 0 / 0
Deadlock при добавлении строки
    #38512084
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Oleg8000MasterZiv,
Код: sql
1.
2.
3.
4.
5.
CREATE TABLE IF NOT EXISTS `balances` (
  `id` int(1) NOT NULL,
  `balance` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;




Так просто ? Два поля ? Не верю...
...
Рейтинг: 0 / 0
Deadlock при добавлении строки
    #38512085
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Oleg8000tanglirРешение напрашивается само собой - сразу создавать для нового пользователя запись с нулевым балансом.
Не хотелось бы... юзеров будет очень много, поэтому решили вынести баланс в отдельную таблицу, чтобы работа с балансом была максимально быстрой

Это дурость.

Не в смысле вынесения, а в смысле надежды, что станет быстрее.
...
Рейтинг: 0 / 0
Deadlock при добавлении строки
    #38512091
tanglir
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivТак просто ? Два поля ? Не верю...Вытащили 2 поля из основной таблицы юзеров в отдельную. Видимо, во многих полях в исходной таблице был нулл/0, и надеялись, что за счёт отсутствия их в новой таблице работа ускорится. Но
MasterZivЭто дурость.

Не в смысле вынесения, а в смысле надежды, что станет быстрее.
...
Рейтинг: 0 / 0
Deadlock при добавлении строки
    #38512100
Oleg8000
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
тут еще интереснее стало...
даже если приходят запрос на пополнение баланса от разных юзеров. все равно вываливается deadlock

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
transaction 1> start transaction;
Query OK, 0 rows affected (0.00 sec)

transaction 1> select * from balances where id=5 for update;
Empty set (0.00 sec)


transaction 2> start transaction;
Query OK, 0 rows affected (0.00 sec)

transaction 2> select * from balances where id=10 for update;
Empty set (0.01 sec)

transaction 2> insert into balances (id, balance) values (10,10);
// висит ...

transaction 1> insert into balances (id, balance) values (5,5);
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

// вторая транзакция после делока первой, выполнилась
Query OK, 1 row affected (9.14 sec)



Мне кажется, это связано с блокировкой следующего ключа, но пока я плаваю в этой теме... В эту сторону копать?
...
Рейтинг: 0 / 0
Deadlock при добавлении строки
    #38512104
Oleg8000
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MasterZiv,
ну это просто для того чтоб легче примеры читались.
ситуация воспроизводится при такой структуре.
...
Рейтинг: 0 / 0
Deadlock при добавлении строки
    #38512106
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
tanglirсразу создавать для нового пользователя запись с нулевым балансом.+1
...
Рейтинг: 0 / 0
Deadlock при добавлении строки
    #38512115
Oleg8000
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Давайте рассмотрим эту проблему не с точки зрения архитектуры, а с точки зрения решения самой проблемы.
Структура таблицы есть. Воспроизвести проблему на локале - дело 1 минуты, достаточно открыть 2 терминала.
Deadlock есть. Как от него избавится?
...
Рейтинг: 0 / 0
Deadlock при добавлении строки
    #38512122
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну или ужесточите уровень изоляции.
...
Рейтинг: 0 / 0
Deadlock при добавлении строки
    #38512135
Oleg8000
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Akina,
вот кстати копаю в этом направлении ))
только не ужесточить, а наоборот понизить помогло.

Код: sql
1.
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;



тогда такой запрос работает как надо.

Код: sql
1.
insert into balances (id, balance) values (1,10) ON DUPLICATE KEY UPDATE balance = balance+10;



но это еще только первые вести с полей... возможно будут побочные эффекты
...
Рейтинг: 0 / 0
Deadlock при добавлении строки
    #38512188
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А был какой?
...
Рейтинг: 0 / 0
Deadlock при добавлении строки
    #38512206
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Oleg8000тут еще интереснее стало...
даже если приходят запрос на пополнение баланса от разных юзеров. все равно вываливается deadlock

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
transaction 1> start transaction;
Query OK, 0 rows affected (0.00 sec)

transaction 1> select * from balances where id=5 for update;
Empty set (0.00 sec)


transaction 2> start transaction;
Query OK, 0 rows affected (0.00 sec)

transaction 2> select * from balances where id=10 for update;
Empty set (0.01 sec)

transaction 2> insert into balances (id, balance) values (10,10);
// висит ...

transaction 1> insert into balances (id, balance) values (5,5);
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

// вторая транзакция после делока первой, выполнилась
Query OK, 1 row affected (9.14 sec)



Мне кажется, это связано с блокировкой следующего ключа, но пока я плаваю в этой теме... В эту сторону копать?


Странно, такого вроде бы быть не должно...
А точно между ними дедлок ?
попробуй только одну сессию пустить ...
...
Рейтинг: 0 / 0
Deadlock при добавлении строки
    #38512207
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AkinaНу или ужесточите уровень изоляции.

Куда уж жёсче ...
Некуда ужесточать...
...
Рейтинг: 0 / 0
Deadlock при добавлении строки
    #38512213
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Можно попробовать не делать SELECT... FOR UPDATE вообще,
делать UPDATE, что-то про UPDATE-илось -- ок, хорошо, нет -- вставлять.
...
Рейтинг: 0 / 0
Deadlock при добавлении строки
    #38512215
Oleg8000
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
AkinaА был какой?
был по дефолту REPEATABLE-READ
...
Рейтинг: 0 / 0
Deadlock при добавлении строки
    #38512218
Oleg8000
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MasterZivпопробуй только одну сессию пустить ...

по отдельности отрабатывают нормально
...
Рейтинг: 0 / 0
Deadlock при добавлении строки
    #38512229
Oleg8000
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MasterZivМожно попробовать не делать SELECT... FOR UPDATE вообще,
делать UPDATE, что-то про UPDATE-илось -- ок, хорошо, нет -- вставлять.

Без FOR UPDATE нельзя.
Это редкий случай - когда пришел запрос, а баланса у юзера нету.
Чаще происходит ситуации, когда у юзера есть баланс.

Если в начале транзакции будет просто SELECT ... WHERE id=1, а в конце UPDATE ... SET balance = balance+10 WHERE id=1
То при паралельных запросах один из них потеряется
...
Рейтинг: 0 / 0
Deadlock при добавлении строки
    #38512231
Фотография ScareCrow
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
insert on duplicate key update
...
Рейтинг: 0 / 0
Deadlock при добавлении строки
    #38512234
Oleg8000
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ScareCrowinsert on duplicate key update
а еще можно прочесть все сообщения в теме.
уже обсуждалось....
...
Рейтинг: 0 / 0
Deadlock при добавлении строки
    #38512240
Oleg8000
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ScareCrowinsert on duplicate key update
На самом деле это пока наилучший вариант, но требуется понизить уровень изоляции.
Это пока смущает...
...
Рейтинг: 0 / 0
Deadlock при добавлении строки
    #38512249
tanglir
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivСтранно, такого вроде бы быть не должно...
А точно между ними дедлок ?я ради интереса на пустой таблице (создал по ddl ТСа) попробовал - воспроизводится
на пустой! таблице
что оно там ухитряется залочить?..
...
Рейтинг: 0 / 0
25 сообщений из 42, страница 1 из 2
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Deadlock при добавлении строки
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]