База данных MySQL ломается при выполнении слишком большого количества тестов в django
У меня есть проект Django с сотнями тестов, и после добавления еще около 50 тестов, когда я запускаю все тесты одновременно с помощью python manage.py test
, почти все тесты выдают следующую ошибку:
Traceback (most recent call last):
File ".../venv/lib/python3.9/site-packages/django/db/models/sql/compiler.py", line 1142, in execute_sql
cursor.execute(sql, params)
File ".../venv/lib/python3.9/site-packages/django/db/backends/utils.py", line 67, in execute
return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
File ".../venv/lib/python3.9/site-packages/django/db/backends/utils.py", line 76, in _execute_with_wrappers
return executor(sql, params, many, context)
File ".../venv/lib/python3.9/site-packages/django/db/backends/utils.py", line 79, in _execute
self.db.validate_no_broken_transaction()
File ".../venv/lib/python3.9/site-packages/django/db/backends/base/base.py", line 437, in validate_no_broken_transaction
raise TransactionManagementError(
django.db.transaction.TransactionManagementError: An error occurred in the current transaction. You can't execute queries until the end of the 'atomic' block.
During handling of the above exception, another exception occurred:
File ".../venv/lib/python3.9/site-packages/django/db/models/manager.py", line 82, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File ".../venv/lib/python3.9/site-packages/django/db/models/query.py", line 653, in first
for obj in (self if self.ordered else self.order_by('pk'))[:1]:
File ".../venv/lib/python3.9/site-packages/django/db/models/query.py", line 274, in __iter__
self._fetch_all()
File ".../venv/lib/python3.9/site-packages/django/db/models/query.py", line 1242, in _fetch_all
self._result_cache = list(self._iterable_class(self))
File ".../venv/lib/python3.9/site-packages/django/db/models/query.py", line 55, in __iter__
results = compiler.execute_sql(chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size)
File ".../venv/lib/python3.9/site-packages/django/db/models/sql/compiler.py", line 1145, in execute_sql
cursor.close()
File ".../venv/lib/python3.9/site-packages/MySQLdb/cursors.py", line 83, in close
while self.nextset():
File ".../venv/lib/python3.9/site-packages/MySQLdb/cursors.py", line 137, in nextset
nr = db.next_result()
MySQLdb._exceptions.OperationalError: (2006, '')
Но если я запускаю тесты по отдельности, все тесты проходят нормально и успешно. Поэтому я предполагаю, что есть проблема с базой данных, когда она запускает несколько тестов одновременно, но я не могу понять, в чем она заключается. Я уже пробовал решения по этому вопросу, но моя проблема не кажется такой же. Я также задавал этот вопрос, но решил задать еще один, поскольку тогда я не знал, что проблема, возможно, связана с количеством тестов в базе данных
Я использую python 3.9, Django 3.2 и MySQL 8.0.23
Кто-нибудь знает, как решить эту проблему? Для этого проекта очень важно, чтобы все тесты могли быть успешно запущены.
После последнего сообщения от python ваше соединение с сервером было прервано. Вы можете узнать больше об этом, найдя mysql 2006
на предпочитаемом вами поисковом сайте.
MySQLdb._exceptions.OperationalError: (2006, '')
Есть несколько причин, почему это происходит, когда мы выполняем много запросов, и одна из них - время, которое занимает запрос, или размер нашего пакета.
Попробуйте увеличить значения wait_timeout
и max_allowed_packet
до гораздо большего значения, просто чтобы посмотреть, работает ли это. Если это работает, конечно, вам нужно будет понять и адаптировать эти значения к вашей рабочей нагрузке, или исправить вашу рабочую нагрузку.
Если ваша таблица InnoDB и тест выполняет много запросов, вы также можете увеличить innodb_log_file_size
(например, 128MB) и innodb_buffer_pool_size
(например, по крайней мере 50% вашей оперативной памяти или намного больше, если MySQL работает один). Последний параметр обычно устанавливается на 80% оперативной памяти, но это может сильно варьироваться в зависимости от того, сколько у вас оперативной памяти и других факторов. Эти innodb_
настройки просто заставят запросы выполняться быстрее, если ваш тест перегружает базу данных.
Я понял, в чем дело. Некоторые из моих тестов имели следующую структуру
class MyTest(TestCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
...
def setUp(self):
...
def test_something(self):
...
В моем обновлении я внес значительные изменения, и некоторые из этих изменений сломали код внутри метода setUpClass
. Когда это произошло, база данных каким-то образом сломалась, и все тесты после этого теста также провалились, потому что базы данных больше не было.
Для предотвращения этого используйте метод setUpTestData. Этот метод вызывается setUpClass, что означает, что он будет запущен один раз перед всеми тестами в файле, но не сломается, если внутри него будет какая-то ошибка. (Вам также не нужно вызывать super
при использовании этого метода).