django 1.5 select_for_update считается хрупким дизайном

В документации Django говорится

Если вы полагались на «автоматические транзакции» для обеспечения блокировки между select_for_update() и последующей операцией записи — чрезвычайно хрупкая конструкция, но, тем не менее, возможная — вы должны обернуть соответствующий код в atomic(). Начиная с Django 1.6.3, выполнение запроса с помощью select_for_update() в режиме автоматической фиксации вызовет TransactionManagementError.

Почему это считается хрупким? Я бы подумал, что это приведет к надлежащей транзакционности.


person Trent    schedule 11.05.2014    source источник


Ответы (3)


select_for_update не хрупкий.

Я написал, что «если вы полагались на «автоматические транзакции»», вам нужно пересмотреть свой код при обновлении с 1.5 с 1.6.

Если вы не полагались на «автоматическую транзакцию», и тем более, если эта концепция вам не знакома, то вам не нужно ничего делать.

Как указано в ответе yuvi (это очень хорошо, спасибо!) Django вызовет исключение, когда обнаружит недопустимый код. Не нужно думать об этом, пока вы не увидите TransactionManagementError, поднятое select_for_update.

person Aymeric Augustin    schedule 19.05.2014
comment
Первый пост основного разработчика платформы Django, fiesta! Просто там, чтобы сказать спасибо за вклад. Надеюсь, в будущем будут и другие посты от вас :-) - person Maxime Lorant; 19.05.2014

Ответ не за горами, в документации для select_for_update (выделено мной):

Оценка набора запросов с помощью select_for_update в режиме автоматической фиксации является ошибкой, поскольку в этом случае строки не блокируются. Если это разрешено, это упростит повреждение данных и может быть легко вызвано вызовом вне какой-либо транзакции кода, который должен выполняться в одной транзакции.

Другими словами, существует противоречивое поведение между autocommit и select_for_update, что может привести к повреждению данных. Вот обсуждение разработчиков django, где они впервые предложили решить эту проблему, процитирую (опять же, выделение мое):

[...] в Oracle в режиме автоматической фиксации автоматическая фиксация происходит сразу после выполнения команды, поэтому попытка получить результаты не удалась, поскольку выполняется в отдельной транзакции.

Однако с любым бэкэндом выбор для обновления в режиме автоматической фиксации не имеет большого смысла. Даже если он не ломается (как это происходит в Oracle), на самом деле он ничего не блокирует. Итак, IMO, выполнение запроса, который является выбором для обновления в режиме автоматической фиксации, вероятно, является ошибкой, и тот, который может вызвать ошибки, связанные с повреждением данных.

Поэтому я предлагаю изменить поведение запросов выбора для обновления, чтобы исключить ошибки [...] Это обратно несовместимое изменение [...] Эти проекты, вероятно, должны быть благодарны - они работали с тонкая ошибка, которая теперь выявляется, но все же.

Так что это была ошибка только для Oracle, которая пролила свет на более глубокую проблему, актуальную для всех серверных частей, и поэтому они приняли решение сделать это ошибкой в ​​django.

Atomic, с другой стороны, фиксирует данные в базе данных только после проверки отсутствия ошибок, тем самым решая проблему.

person yuvi    schedule 11.05.2014
comment
То, что вы написали, имеет смысл, но то, как написана документация, предполагает, что дизайн в 1.5 был хрупким. Если вы расчитывали на автоматические транзакции... для меня это говорит о том, что использование select_for_update в 1.5 для блокировки строк для обновления является хрупким дизайном, даже с отключенной автофиксацией базы данных (но все еще с использованием Django реализация приложения "autocommit") - person Trent; 12.05.2014
comment
Да, вы правы, он хрупок только при использовании автофиксации и считается таковым, потому что на самом деле ничего не блокирует. Он не хрупкий в общем смысле. И обратите внимание: ошибка решает эту проблему, поскольку она активируется только в конкретном случае использования select_for_update с автоматической фиксацией, так что все это имеет смысл. - person yuvi; 12.05.2014
comment
Итак, комментарий «чрезвычайно хрупкий дизайн» применим только к Django 1.6+? То, как написана документация, подразумевает, что для Django ‹ 1.6 select_for_update считается уязвимым. - person Trent; 14.05.2014
comment
@Taras select_for_update сам по себе не является хрупким, только при использовании вместе с auotcommit. Я не уверен, каковы последствия его использования с реализацией приложения Django 'autocommit'. И с технической точки зрения, поскольку дефектные ошибки дизайна исчезли из 1.6, то да, это в основном проблема с более ранними выпусками. - person yuvi; 14.05.2014

Эймерик пояснил по электронной почте, что такой дизайн является хрупким, поскольку он основан на границах неявных транзакций, сформированных неявными транзакциями Django 1.5.

select_for_update(...)
more_code()
save()

Этот код работает в простых случаях, но если more_code() приводит к операции записи в базу данных, транзакция закроется, что приведет к непреднамеренному поведению.

Принуждение пользователя указывать границы транзакций также приводит к более четкому коду.

person Trent    schedule 25.05.2014