Выводы из борьбы с deadlock
Feb. 23rd, 2011 12:06 pm![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
Загвоздка была (совершенно классически) в том, что несколько процессов одновременно пытались редактировать одну и ту же строку в таблице.
Процедура, о которую споткнулось приложение, принимала на вход сложный объект с атрибутами-массивами, данные из которых нужно было разложить по таблицам.
Первый вариант реализации был прост и незатейлив: существовала отдельная процедура, которая записывала результат для одной строки, и вызывалась в цикле (не оптимально, но удобно). Споткнулись о deadlock.
Второй вариант: заменила цикл на bulk merge (до вчерашнего дня и не подозревала, что bulk merge возможен наравне с bulk insert и bulk update). Не помогло. Вернее помогло частично: deadlock стал появляться не сразу, а через минуту где-то после запуска приложения.
Собралась с силами, переделала bulk merge в merge по select * from table (input_array). И, похоже, сработало. По крайней мере, тесты, оставленные гоняться ночью, ошибок не выкинули.
Мораль сей басни такова. Циклы must die — это раз. Bulk update/merge имеет смысл использовать только если обычный update/merge ну никак невозможен — это два.
Побочный эффект, который ещё придётся преодолеть: массив там не просто массив, а массив сложных объектов, каждый из которых также имеет атрибут-массив, который тоже нужно сохранить. Так что пора изобрести какой-то волшебный способ сделать прямой select из этого массива. Чем сейчас и займусь.
Процедура, о которую споткнулось приложение, принимала на вход сложный объект с атрибутами-массивами, данные из которых нужно было разложить по таблицам.
Первый вариант реализации был прост и незатейлив: существовала отдельная процедура, которая записывала результат для одной строки, и вызывалась в цикле (не оптимально, но удобно). Споткнулись о deadlock.
Второй вариант: заменила цикл на bulk merge (до вчерашнего дня и не подозревала, что bulk merge возможен наравне с bulk insert и bulk update). Не помогло. Вернее помогло частично: deadlock стал появляться не сразу, а через минуту где-то после запуска приложения.
Собралась с силами, переделала bulk merge в merge по select * from table (input_array). И, похоже, сработало. По крайней мере, тесты, оставленные гоняться ночью, ошибок не выкинули.
Мораль сей басни такова. Циклы must die — это раз. Bulk update/merge имеет смысл использовать только если обычный update/merge ну никак невозможен — это два.
Побочный эффект, который ещё придётся преодолеть: массив там не просто массив, а массив сложных объектов, каждый из которых также имеет атрибут-массив, который тоже нужно сохранить. Так что пора изобрести какой-то волшебный способ сделать прямой select из этого массива. Чем сейчас и займусь.