|
|
|
Deadlock при добавлении строки
|
|||
|---|---|---|---|
|
#18+
Вобщем сделал понижение уровня изоляции транзакции до 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. Так что проблема все еще актуальна... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.12.2013, 13:44:01 |
|
||
|
Deadlock при добавлении строки
|
|||
|---|---|---|---|
|
#18+
Oleg8000, как-то странно у вас. Огласите полный набор действий от начала и до конца транзакции, которые приводят к блокировкам в случае insert ... on duplicate... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.12.2013, 16:33:13 |
|
||
|
Deadlock при добавлении строки
|
|||
|---|---|---|---|
|
#18+
Arhat109Огласите полный набор действий от начала и до конца транзакции, которые приводят к блокировкам в случае insert ... on duplicate... Я так проверял Oleg8000 Код: sql 1. 2. 3. 4. 5. Потом на пустой таблице Oleg8000 Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. результат аналогичен - дедлок. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.12.2013, 16:53:49 |
|
||
|
Deadlock при добавлении строки
|
|||
|---|---|---|---|
|
#18+
... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.12.2013, 17:14:50 |
|
||
|
Deadlock при добавлении строки
|
|||
|---|---|---|---|
|
#18+
просто отсортируй инсерты по ID сначала 5 потом 10 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.12.2013, 17:16:40 |
|
||
|
Deadlock при добавлении строки
|
|||
|---|---|---|---|
|
#18+
http://dev.mysql.com/doc/refman/5.5/en/innodb-record-level-locks.html http://dba.stackexchange.com/a/28289 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.12.2013, 17:18:37 |
|
||
|
Deadlock при добавлении строки
|
|||
|---|---|---|---|
|
#18+
tanglir, А теперь попробуйте мне внятно объяснить зачем ПЕРЕД insert делаете блокировку через select for update? Ссылки, привели верные. Ежели табличка пуста, то первая сессия своим селектом сразу же захватывает gap-ом всю табличку, и следующая сессия своим селектом делает тоже самое, что и приводит к нормальному дедлоку. Я понимаю, когда делают для последующего update - лочить конкретный набор строк, дабы по ним не пролетел ещё кто-то. А вот для инсерта, да ещё и с дубликатным апдейтом - нифига не понял. Потому что: 1. Если инсерт втыкает новую запись - он это сделает. 2. Если НЕ втыкает, то пройдет апдейт ровно одной записи. Насколько понимаю, втыкаем по одной записи... (впрочем он тут и для апдейта нафиг не нужен). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.12.2013, 20:07:22 |
|
||
|
Deadlock при добавлении строки
|
|||
|---|---|---|---|
|
#18+
Arhat109, select for update нужен для того чтобы заблочить запись, если таковая имеется, что чаще всего и случается. а вот если ее нет, тогда нужно добавить новую строку ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.12.2013, 20:15:39 |
|
||
|
Deadlock при добавлении строки
|
|||
|---|---|---|---|
|
#18+
Oleg8000, (*facepalm*)... это понятно. А сможете внятно объяснить неоходимость именно предварительного лока в вашем конкретном случае? :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.12.2013, 20:20:07 |
|
||
|
Deadlock при добавлении строки
|
|||
|---|---|---|---|
|
#18+
Arhat109, там интересен совсем другой вопрос: каким способом второй селект для апдейта ваще проходит? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.12.2013, 20:25:23 |
|
||
|
Deadlock при добавлении строки
|
|||
|---|---|---|---|
|
#18+
Arhat109, Селектом в начале транзакции, мы ищем баланс юзера. Если баланс юзера есть, значит в таблице есть запись. Мы ее блочим, для того, чтобы проделав некоторые операции с балансом (например, сохранить значение баланса до и после операции. т.е. обычный лог), в конце транзакции увеличить этот самый баланс. Ежели у юзера нет баланса, значит нет записи. Тогда добавляем запись, опять же логгируя значения баланса до и после. Пока вижу 2 пути: 1) после первого select for update, если записи нет, то заканчивать транзакцию, сбрасывая тем самым gap-ы. А дальше извращаться с insert on duplicate key update (пока вижу проблему с логгированием) 2) для юзера сразу заводить запись с нулевым балансом. Это, кажется более правильный путь, но смущают размеры таблицы. Юзеров реально до хрена, политика партии допускает наличие у пользователя неограниченного кол-ва аккаунтов. Из этой таблицы делаются ежеминутные выборки с целью списания абонентской платы. Сейчас объем таблицы под 10 млн. записей + ежесуточный прирост в 50-100 тыс. Поэтому и было решено вести балансы только активных юзеров. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.12.2013, 21:01:49 |
|
||
|
Deadlock при добавлении строки
|
|||
|---|---|---|---|
|
#18+
Arhat109Arhat109, там интересен совсем другой вопрос: каким способом второй селект для апдейта ваще проходит? Вы можете попробовать самостоятельно. tanglir чуть выше описал полную последовательность операций, которая приводит к дедлоку. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.12.2013, 21:06:53 |
|
||
|
Deadlock при добавлении строки
|
|||
|---|---|---|---|
|
#18+
ScareCrowпросто отсортируй инсерты по ID сначала 5 потом 10 К сожалению, это невозможно, т.к. это фактически идентификаторы юзеров. Да и если честно, я не представляю, как это можно сделать в разных потоках. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.12.2013, 21:09:14 |
|
||
|
Deadlock при добавлении строки
|
|||
|---|---|---|---|
|
#18+
Oleg8000, Дык и попробовал. Тоже лочится. Вот и не понимаю "почто так". Пока объяснение тока одно: гапы - разные. Тока не понимаю "в чём"? Таблица-то пустая! ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.12.2013, 21:10:52 |
|
||
|
Deadlock при добавлении строки
|
|||
|---|---|---|---|
|
#18+
Oleg8000, ну, во-первых: "операции с балансом". Если это "лог", то выборка значения "до" - осмыслена, а вот смысла в логировании "между" чтением и сохранением - собственно для чего нужна блокировка - уже нет. Какая нафиг разница, когда физически запишется лог? У вас есть исходное значение на момент начала транзакции, есть конечное... оттого, что вы лог чирканете "задним числом" (после изменения значения) - плохо? А если "заранее"? А если отдельно вставлять в лог предварительно пустую запись "заранее", а потом одним, многотабличным апдейтом одновременно менять баланс и запись лога? Никак? Я к тому, что если в процессе транзакции нет логики, изменяющей поведение транзакции, то она скорее всего избыточна и вполне достаточно "встроенных" блокировок на каждый запрос. Как-то так. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.12.2013, 21:21:30 |
|
||
|
Deadlock при добавлении строки
|
|||
|---|---|---|---|
|
#18+
Arhat109ну, во-первых: "операции с балансом". Если это "лог", то выборка значения "до" - осмыслена, а вот смысла в логировании "между" чтением и сохранением - собственно для чего нужна блокировка - уже нет. Какая нафиг разница, когда физически запишется лог? У вас есть исходное значение на момент начала транзакции, есть конечное... оттого, что вы лог чирканете "задним числом" (после изменения значения) - плохо? А если "заранее"? Если мы читаем значение баланса в начале транзакции, и не будем блокировать запись, то к моменту записи в лог это значение может быть уже неактуально, т.к. другая транзакция также в этот же момент времени прочитала значение баланса "до" и изменила баланс. Поэтому, без блокировки записи баланса, в логе запросто могут быть такие записи, при 2-х одновременных запросах user_id баланс до баланс после1 0 101 0 10 А в таблице баланса будет верное значение 20 Arhat109А если отдельно вставлять в лог предварительно пустую запись "заранее", а потом одним, многотабличным апдейтом одновременно менять баланс и запись лога? Никак? Надо подумать, пока плохо понял смысл... голова уже плохо соображает ) Arhat109Я к тому, что если в процессе транзакции нет логики, изменяющей поведение транзакции, то она скорее всего избыточна и вполне достаточно "встроенных" блокировок на каждый запрос. Как-то так. Логгирование - не единственная операция в транзакции. Есть и другие, которые как раз меняют логику, в зависимости от вида совершенного платежа. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.12.2013, 21:48:37 |
|
||
|
Deadlock при добавлении строки
|
|||
|---|---|---|---|
|
#18+
Oleg8000, В таком случае, надо смотреть почему первый select for update не блокирует запись для второго. Скорее всего это связано с разными gap, при отсутствии нужной записи. Тогда ваша мысля про "сначала проверять и если отсутствует - разблокировать", скорее всего верна. Но, в целом, явно наблюдается "косяк", имхо. Если табличка пуста, то gap с 0 по 5 должен блокировать gap с 0 по 10 - всяко. Впрочем и наоборот тоже. То есть данная последовательность (у меня воспроизводится тоже, MySQL 5.1.47) - симптом неверного перехлеста gap при оценке построчной блокировки. Надо заглянуть в код, давно не лазил. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.12.2013, 10:45:17 |
|
||
|
|

start [/forum/topic.php?fid=47&msg=38513611&tid=1835481]: |
0ms |
get settings: |
8ms |
get forum list: |
12ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
28ms |
get topic data: |
9ms |
get forum data: |
3ms |
get page messages: |
63ms |
get tp. blocked users: |
2ms |
| others: | 231ms |
| total: | 362ms |

| 0 / 0 |
