Я обнаружил, что одним из лучших вложений, которые я когда-либо делал во избежание взаимоблокировок, было использование Object Relational Mapper, который мог бы заказывать обновления базы данных. Точный порядок не важен, если каждая транзакция записывает в одном и том же порядке (и удаляет точно в обратном порядке).
Причина, по которой это позволяет избежать большинства тупиковых ситуаций, заключается в том, что ваши операции: всегда сначала таблица A, затем таблица B, а затем таблица C (что, возможно, зависит от таблицы B).
Вы можете достичь аналогичного результата, если будете проявлять осторожность в своих хранимых процедурах или в коде доступа уровня данных. Единственная проблема заключается в том, что для этого требуется большой осторожность, чтобы делать это вручную, тогда как ORM с концепцией Unit of Work может автоматизировать большинство случаев.
ОБНОВЛЕНИЕ: удаление должно быть запущено вперед, чтобы убедиться, что все версии, которые вы ожидаете (вам все еще нужны номера версий записей или временные метки), а затем удалить в обратном направлении, когда все подтвердит. Поскольку все это должно происходить в одной транзакции, вероятность того, что что-то изменится из-под вас, не должна существовать. Единственная причина, по которой ORM делает это задом наперед, состоит в том, чтобы соблюдать ключевые требования, но если вы выполните проверку вперед, у вас будут все замки, которые вам нужны, уже под рукой.