Как вы тестируете условия гонки в базе данных?

30

Я пытаюсь написать код базы данных, чтобы убедиться, что он не зависит от условий гонки, чтобы убедиться, что я заблокировал правильные строки или таблицы. Но я часто задаюсь вопросом: правильный ли мой код? Можно ли заставить какие-либо существующие расы проявить себя? Я хочу быть уверен, что если они произойдут в производственной среде, мое приложение будет работать правильно.

Я обычно точно знаю, какой параллельный запрос может вызвать проблему, но я не знаю, как заставить их запускаться одновременно, чтобы увидеть, происходит ли правильное поведение (например, я использовал правильный тип блокировки), что правильные ошибки брошенный и т. д.

Примечание: я использую PostgreSQL и Perl, поэтому, если на этот вопрос нельзя дать общий ответ, его, вероятно, следует пометить заново.

Обновление: я бы предпочел, чтобы решение было программным. Таким образом, я могу написать автоматизированные тесты, чтобы убедиться, что нет регрессий.

xenoterracide
источник
Под «состоянием гонки» вы подразумеваете «тупик»?
Гай
2
@ Гай ... нет, хотя я верю, что это один из возможных результатов некоторых условий гонки
ксенотеррацид
Условия гонки @Gaius в базе данных - это удаление таблицы перед ее созданием или обновление строки перед ее вставкой. Вообще, я бы предположил, что он обрабатывается логикой приложения вне самой базы данных.
Марк Д
обновить строку до того, как она была вставлена? это не вызовет проблемы с БД. никакое условие гонки не будет похоже на выбор строки и ее обновление, но если другой пользователь обновит его после получения строки, но до обработки вашего обновления.
ксенотеррацид
1
@MarkD - Нет. Существует много типов состояний гонки, которые возникают из-за неправильной инкапсуляции атомарной единицы работы в вашей базе данных. Вот пример. Помните, что «состояние гонки или опасность гонки - это ошибка в электронной системе или процессе, из-за которой выходные данные или результат процесса неожиданно и критически зависят от последовательности или времени других событий ». ( источник )
Ник Чаммас

Ответы:

11

Я делаю это все время с моими модулями T-SQL.

По сути, все, что вам нужно сделать, это запустить ваши модули из двух или более соединений в цикле в течение пары минут . Как правило, все потенциальные проблемы обнаруживаются в течение нескольких минут, при условии, что у вас есть блок SQL Server с достойными процессорами.

Я написал несколько примеров здесь и здесь .

Аляска
источник
4

Я обычно работаю с инструментом командной строки СУБД, просто запустив 2 (или более) экземпляра CLI. Затем вы можете воспроизвести один за другим и в виде гонки (которая будет выглядеть как action-RPG) SQL-операторов, отправляемых вашим прикладным уровнем. Вы должны поэкспериментировать / почувствовать работу систем блокировки в действии, так как ваш CLI немного «зависнет», ожидая снятия блокировок с других CLI.

Если это звучит как грязь, не стесняйтесь говорить об этом ;-)

Julien
источник
не могли бы вы привести пошаговый пример? и можно ли написать программные тесты, чтобы сделать то же самое?
ксенотеррацид
1

Условия гонки требуют многократного выполнения потока, поэтому для модульного тестирования вам понадобится запустить один или несколько потоков. В Oracle я бы использовал DBMS_Scheduler для запуска процесса для симуляции второго пользователя. Если в PostgreSQL / Perl есть способ инициировать второй процесс программно, то вы должны сделать что-то вроде этого:

Процесс 1 Процесс 2

Начать процесс 2. >>                            
Задержка, чтобы позволить 2 сделать свою работу. 
, Блокировка строк или изменение данных.
, Задержка, чтобы позволить 1 сделать свою работу.
Попытка заблокировать строки или изменить данные. ,
Убедитесь, что сделано правильное обращение. ,
Окончание. ,
                                                Окончание.

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

Ли Риффель
источник
Я бы не стал описывать такие тесты как юнит-тесты, потому что юнит-тесты должны каждый раз выполняться одинаково. Расовые условия терпят неудачу вовлекают процессы с перерывами, не совсем одинаково каждый раз.
AK
@AlexKuznetsov Вы правы в том, что неожиданные условия гонки могут периодически показывать себя, однако ОП ссылается на ожидаемые условия, которые, по его мнению, должен обрабатывать код. Эти конкретные условия могут быть точно воспроизведены, а обработка проверена с помощью модульного теста.
Ли Риффель
-2

Пока вы блокируете ряды, вы не должны попадать в состояние гонки, поскольку это обычно происходит, когда нет блокировки.

Но вы можете зайти в тупик, если один вопрос заблокирует ваш вопрос слишком долго.

Это трудно проверить, так как время для запросов может измениться при увеличении базы данных.

Запросы, которые хорошо работают с 100 000 строк тестовых данных, уходят с графика с 10 000 000 строк.

Этот тип проблемы может быть очень трудно найти заранее, но у многих БД есть какой-то метод выявления медленных запросов.

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

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

Ник Чаммас
источник
@darioo lol Я подумал, что, может быть, wn - это аббревиатура для чего-то ... idk, что бы он имел в виду под "сделать блокировку самостоятельно". Если он имеет в виду не с помощью ORM, я проверил код, который выводит мой ORM, но он определенно не выполняет блокировка справа. Это одна из причин, по которой я хотел бы проверить сценарий потенциальной гонки.
ксенотеррацид
Да, я имел в виду собственный, и обычно драйвер базы данных обрабатывает блокировку, строку, таблицу или, возможно, поле, но я просто открываю возможность того, что вы используете какую-то БД, которая не обрабатывает блокировку;)
... Я почти уверен, что если у меня будет транзакция с несколькими операторами, моя БД не будет знать, какие строки автоматически блокировать ... таких вещей, как select for updateесли бы они не существовали ...
xenoterracide