使用Sphinxsearch时Django MySQL后端获取特性报错求助
问题:Django连接Sphinx时因
@@SQL_AUTO_IS_NULL返回空字符串导致migrate失败 Django的MySQL后端每次建立连接时会评估MySQL相关设置,而Sphinx返回的@@SQL_AUTO_IS_NULL值为空字符串,无法转换为整数,执行migrate命令时抛出如下错误:
root@2d37585a3d96:/mealplanner/trunk# python manage.py migrate Traceback (most recent call last): File "manage.py", line 11, in <module> execute_from_command_line(sys.argv) File "/py36-default/lib/python3.6/site-packages/django/core/management/__init__.py", line 381, in execute_from_command_line utility.execute() File "/py36-default/lib/python3.6/site-packages/django/core/management/__init__.py", line 375, in execute self.fetch_command(subcommand).run_from_argv(self.argv) File "/py36-default/lib/python3.6/site-packages/django/core/management/base.py", line 323, in run_from_argv self.execute(*args, **cmd_options) File "/py36-default/lib/python3.6/site-packages/django/core/management/base.py", line 361, in execute self.check() File "/py36-default/lib/python3.6/site-packages/django/core/management/base.py", line 390, in check include_deployment_checks=include_deployment_checks, File "/py36-default/lib/python3.6/site-packages/django/core/management/commands/migrate.py", line 64, in _run_checks issues = run_checks(tags=[Tags.database]) File "/py36-default/lib/python3.6/site-packages/django/core/checks/registry.py", line 72, in run_checks new_errors = check(app_configs=app_configs) File "/py36-default/lib/python3.6/site-packages/django/core/checks/database.py", line 10, in check_database_backends issues.extend(conn.validation.check(**kwargs)) File "/py36-default/lib/python3.6/site-packages/django/db/backends/mysql/validation.py", line 9, in check issues.extend(self._check_sql_mode(**kwargs)) File "/py36-default/lib/python3.6/site-packages/django/db/backends/mysql/validation.py", line 13, in _check_sql_mode with self.connection.cursor() as cursor: File "/py36-default/lib/python3.6/site-packages/django/db/backends/base/base.py", line 256, in cursor return self._cursor() File "/py36-default/lib/python3.6/site-packages/django/db/backends/base/base.py", line 233, in _cursor self.ensure_connection() File "/py36-default/lib/python3.6/site-packages/django/db/backends/base/base.py", line 217, in ensure_connection self.connect() File "/py36-default/lib/python3.6/site-packages/django/db/backends/base/base.py", line 197, in connect self.init_connection_state() File "/py36-default/lib/python3.6/site-packages/django/db/backends/mysql/base.py", line 231, in init_connection_state if self.features.is_sql_auto_is_null_enabled: File "/py36-default/lib/python3.6/site-packages/django/utils/functional.py", line 80, in __get__ res = instance.__dict__[self.name] = self.func(instance) File "/py36-default/lib/python3.6/site-packages/django/db/backends/mysql/features.py", line 83, in is_sql_auto_is_null_enabled cursor.execute('SELECT @@SQL_AUTO_IS_NULL') File "/py36-default/lib/python3.6/site-packages/django/db/backends/utils.py", line 99, in execute return super().execute(sql, params) File "/py36-default/lib/python3.6/site-packages/django/db/backends/utils.py", line 67, in execute return self._execute_with_wrappers(sql, params, many=False, executor=self._execute) File "/py36-default/lib/python3.6/site-packages/django/db/backends/utils.py", line 76, in _execute_with_wrappers return executor(sql, params, many, context) File "/py36-default/lib/python3.6/site-packages/django/db/backends/utils.py", line 82, in _execute return self.cursor.execute(sql) File "/py36-default/lib/python3.6/site-packages/django/db/backends/mysql/base.py", line 71, in execute return self.cursor.execute(query, args) File "/py36-default/lib/python3.6/site-packages/MySQLdb/cursors.py", line 250, in execute self.errorhandler(self, exc, value) File "/py36-default/lib/python3.6/site-packages/MySQLdb/connections.py", line 50, in defaulterrorhandler raise errorvalue File "/py36-default/lib/python3.6/site-packages/MySQLdb/cursors.py", line 247, in execute res = self._query(query) File "/py36-default/lib/python3.6/site-packages/MySQLdb/cursors.py", line 413, in _query self._post_get_result() File "/py36-default/lib/python3.6/site-packages/MySQLdb/cursors.py", line 417, in _post_get_result self._rows = self._fetch_row(0) File "/py36-default/lib/python3.6/site-packages/MySQLdb/cursors.py", line 385, in _fetch_row return self._result.fetch_row(size, self._fetch_type) ValueError: invalid literal for int() with base 10: ''
在MySQL客户端连接Sphinx时执行SELECT @@SQL_AUTO_IS_NULL,返回结果为空字符串:
Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 1 Server version: 2.2.11-id64-release (95ae9a6) Copyright (c) 2000, 2023, Oracle and/or its affiliates. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> SELECT @@SQL_AUTO_IS_NULL; +--------------------+ | @@sql_auto_is_null | +--------------------+ | | +--------------------+ 1 row in set (0.00 sec)
解决方案
方案1:修改Sphinx配置强制返回合法值
在Sphinx的配置文件(通常为sphinx.conf)中,添加sql_query_pre指令,让Sphinx在每次处理查询前自动设置SQL_AUTO_IS_NULL的值:
sql_query_pre = SET SQL_AUTO_IS_NULL = 0
配置生效后,SELECT @@SQL_AUTO_IS_NULL会返回整数0,符合Django的类型要求。
方案2:自定义Django MySQL后端适配空字符串
如果无法修改Sphinx配置,可通过自定义数据库后端捕获转换异常:
- 创建自定义后端文件(如
custom_mysql/backends/mysql/base.py),继承原MySQL后端并重写特性类:
from django.db.backends.mysql.base import DatabaseWrapper as OriginalMySQLWrapper from django.db.backends.mysql.features import DatabaseFeatures as OriginalMySQLFeatures class DatabaseFeatures(OriginalMySQLFeatures): @property def is_sql_auto_is_null_enabled(self): try: return super().is_sql_auto_is_null_enabled except ValueError: # 空字符串时默认返回False(对应SQL_AUTO_IS_NULL=0) return False class DatabaseWrapper(OriginalMySQLWrapper): features_class = DatabaseFeatures
- 在Django的
settings.py中修改数据库配置,使用自定义后端:
DATABASES = { 'default': { 'ENGINE': 'custom_mysql.backends.mysql', # 其他数据库连接配置... } }
内容的提问来源于stack exchange,提问作者Vlad
相关产品推荐
相关产品推荐

