powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Deadlock при добавлении строки
17 сообщений из 42, страница 2 из 2
Deadlock при добавлении строки
    #38513081
Oleg8000
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Вобщем сделал понижение уровня изоляции транзакции до READ COMMITTED с использованием INSERT ON DUPLICATE KEY UPDATE.
И вот как чувствовал, что что-то не то...

На локале все потестил, все нормально, со всех ракурсов.
На бой вынес и повалились ошибки

Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engi ne limited to row-based logging. InnoDB is limited to row-logging when transaction isolation level is READ COMMITTED or READ UNCOMMITTED.
Так что проблема все еще актуальна...
...
Рейтинг: 0 / 0
Deadlock при добавлении строки
    #38513364
Arhat109
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Oleg8000,

как-то странно у вас. Огласите полный набор действий от начала и до конца транзакции, которые приводят к блокировкам в случае insert ... on duplicate...
...
Рейтинг: 0 / 0
Deadlock при добавлении строки
    #38513403
tanglir
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Arhat109Огласите полный набор действий от начала и до конца транзакции, которые приводят к блокировкам в случае insert ... on duplicate...
Я так проверял
Oleg8000
Код: 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;

Потом на пустой таблице
Oleg8000
Код: 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 при добавлении строки
    #38513430
Фотография ScareCrow
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Deadlock при добавлении строки
    #38513435
Фотография ScareCrow
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
просто отсортируй инсерты по ID
сначала 5 потом 10
...
Рейтинг: 0 / 0
Deadlock при добавлении строки
    #38513438
Фотография ScareCrow
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Deadlock при добавлении строки
    #38513561
Arhat109
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
tanglir,

А теперь попробуйте мне внятно объяснить зачем ПЕРЕД insert делаете блокировку через select for update?

Ссылки, привели верные. Ежели табличка пуста, то первая сессия своим селектом сразу же захватывает gap-ом всю табличку, и следующая сессия своим селектом делает тоже самое, что и приводит к нормальному дедлоку.

Я понимаю, когда делают для последующего update - лочить конкретный набор строк, дабы по ним не пролетел ещё кто-то. А вот для инсерта, да ещё и с дубликатным апдейтом - нифига не понял. Потому что:

1. Если инсерт втыкает новую запись - он это сделает.
2. Если НЕ втыкает, то пройдет апдейт ровно одной записи.

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

select for update нужен для того чтобы заблочить запись, если таковая имеется, что чаще всего и случается.
а вот если ее нет, тогда нужно добавить новую строку
...
Рейтинг: 0 / 0
Deadlock при добавлении строки
    #38513572
Arhat109
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Oleg8000,

(*facepalm*)... это понятно. А сможете внятно объяснить неоходимость именно предварительного лока в вашем конкретном случае? :)
...
Рейтинг: 0 / 0
Deadlock при добавлении строки
    #38513579
Arhat109
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Arhat109,

там интересен совсем другой вопрос: каким способом второй селект для апдейта ваще проходит?
...
Рейтинг: 0 / 0
Deadlock при добавлении строки
    #38513601
Oleg8000
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Arhat109,

Селектом в начале транзакции, мы ищем баланс юзера. Если баланс юзера есть, значит в таблице есть запись. Мы ее блочим, для того, чтобы проделав некоторые операции с балансом (например, сохранить значение баланса до и после операции. т.е. обычный лог), в конце транзакции увеличить этот самый баланс.

Ежели у юзера нет баланса, значит нет записи. Тогда добавляем запись, опять же логгируя значения баланса до и после.

Пока вижу 2 пути:
1) после первого select for update, если записи нет, то заканчивать транзакцию, сбрасывая тем самым gap-ы. А дальше извращаться с insert on duplicate key update (пока вижу проблему с логгированием)

2) для юзера сразу заводить запись с нулевым балансом. Это, кажется более правильный путь, но смущают размеры таблицы. Юзеров реально до хрена, политика партии допускает наличие у пользователя неограниченного кол-ва аккаунтов. Из этой таблицы делаются ежеминутные выборки с целью списания абонентской платы. Сейчас объем таблицы под 10 млн. записей + ежесуточный прирост в 50-100 тыс. Поэтому и было решено вести балансы только активных юзеров.
...
Рейтинг: 0 / 0
Deadlock при добавлении строки
    #38513603
Oleg8000
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Arhat109Arhat109,

там интересен совсем другой вопрос: каким способом второй селект для апдейта ваще проходит?
Вы можете попробовать самостоятельно. tanglir чуть выше описал полную последовательность операций, которая приводит к дедлоку.
...
Рейтинг: 0 / 0
Deadlock при добавлении строки
    #38513604
Oleg8000
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ScareCrowпросто отсортируй инсерты по ID
сначала 5 потом 10
К сожалению, это невозможно, т.к. это фактически идентификаторы юзеров.
Да и если честно, я не представляю, как это можно сделать в разных потоках.
...
Рейтинг: 0 / 0
Deadlock при добавлении строки
    #38513606
Arhat109
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Oleg8000,

Дык и попробовал. Тоже лочится. Вот и не понимаю "почто так". Пока объяснение тока одно: гапы - разные. Тока не понимаю "в чём"? Таблица-то пустая!
...
Рейтинг: 0 / 0
Deadlock при добавлении строки
    #38513611
Arhat109
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Oleg8000,

ну, во-первых: "операции с балансом". Если это "лог", то выборка значения "до" - осмыслена, а вот смысла в логировании "между" чтением и сохранением - собственно для чего нужна блокировка - уже нет.

Какая нафиг разница, когда физически запишется лог? У вас есть исходное значение на момент начала транзакции, есть конечное... оттого, что вы лог чирканете "задним числом" (после изменения значения) - плохо? А если "заранее"?

А если отдельно вставлять в лог предварительно пустую запись "заранее", а потом одним, многотабличным апдейтом одновременно менять баланс и запись лога? Никак?

Я к тому, что если в процессе транзакции нет логики, изменяющей поведение транзакции, то она скорее всего избыточна и вполне достаточно "встроенных" блокировок на каждый запрос. Как-то так.
...
Рейтинг: 0 / 0
Deadlock при добавлении строки
    #38513632
Oleg8000
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Arhat109ну, во-первых: "операции с балансом". Если это "лог", то выборка значения "до" - осмыслена, а вот смысла в логировании "между" чтением и сохранением - собственно для чего нужна блокировка - уже нет.

Какая нафиг разница, когда физически запишется лог? У вас есть исходное значение на момент начала транзакции, есть конечное... оттого, что вы лог чирканете "задним числом" (после изменения значения) - плохо? А если "заранее"?


Если мы читаем значение баланса в начале транзакции, и не будем блокировать запись, то к моменту записи в лог это значение может быть уже неактуально, т.к. другая транзакция также в этот же момент времени прочитала значение баланса "до" и изменила баланс. Поэтому, без блокировки записи баланса, в логе запросто могут быть такие записи, при 2-х одновременных запросах

user_id баланс до баланс после1 0 101 0 10

А в таблице баланса будет верное значение 20

Arhat109А если отдельно вставлять в лог предварительно пустую запись "заранее", а потом одним, многотабличным апдейтом одновременно менять баланс и запись лога? Никак?

Надо подумать, пока плохо понял смысл... голова уже плохо соображает )

Arhat109Я к тому, что если в процессе транзакции нет логики, изменяющей поведение транзакции, то она скорее всего избыточна и вполне достаточно "встроенных" блокировок на каждый запрос. Как-то так.
Логгирование - не единственная операция в транзакции. Есть и другие, которые как раз меняют логику, в зависимости от вида совершенного платежа.
...
Рейтинг: 0 / 0
Deadlock при добавлении строки
    #38513960
Arhat109
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Oleg8000,

В таком случае, надо смотреть почему первый select for update не блокирует запись для второго. Скорее всего это связано с разными gap, при отсутствии нужной записи. Тогда ваша мысля про "сначала проверять и если отсутствует - разблокировать", скорее всего верна.

Но, в целом, явно наблюдается "косяк", имхо. Если табличка пуста, то gap с 0 по 5 должен блокировать gap с 0 по 10 - всяко. Впрочем и наоборот тоже. То есть данная последовательность (у меня воспроизводится тоже, MySQL 5.1.47) - симптом неверного перехлеста gap при оценке построчной блокировки. Надо заглянуть в код, давно не лазил.
...
Рейтинг: 0 / 0
17 сообщений из 42, страница 2 из 2
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Deadlock при добавлении строки
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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