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


30

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

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

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

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


Под «состоянием гонки» вы подразумеваете «тупик»?
Гай

2
@ Гай ... нет, хотя я верю, что это один из возможных результатов некоторых условий гонки
ксенотеррацид

Условия гонки @Gaius в базе данных - это удаление таблицы перед ее созданием или обновление строки перед ее вставкой. Вообще, я бы предположил, что он обрабатывается логикой приложения вне самой базы данных.
Марк Д

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

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

Ответы:


11

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

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

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


4

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

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


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

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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.