Django 项目运行中的 MySQL 连接问题及解决方案

467 阅读4分钟

在日常开发中,使用 Django 与 MySQL 数据库进行连接是常见的操作。然而,在配置 MySQL 数据库时,有时会遇到驱动兼容性问题,导致项目无法正常运行。本文将以我今天遇到的一个实际问题为例,分析问题原因并提供解决方案,帮助开发者更好地理解 Django 与 MySQL 驱动的选择和配置。

问题背景

在一个基于 Django 框架的项目中,我尝试通过以下命令启动服务器:

python manage.py runserver 0.0.0.0:8123 --insecure

服务器成功启动后,却抛出了一个错误:

*** Error in `/root/anaconda3/envs/amis-django/bin/python': corrupted double-linked list: 0x00007f1ba807fb50 ***

image.png

这个错误主要与内存管理有关,提示系统中的某个双链表结构出现了问题。回溯日志进一步表明问题与 OpenSSL 和 MySQL 相关库存在冲突:

/lib64/libcrypto.so.1.1(ERR_load_ERR_strings+0x1dd)[0x7f1bafce43ed]
/root/anaconda3/envs/amis-django/lib/libmysqlclient.so.18(new_VioSSLConnectorFd+0x29)[0x7f1badf847e9]

image.png

从日志可以看出,问题出在 MySQL 相关库的 OpenSSL 依赖部分。在分析了项目配置后,发现使用的是 mysqlclient 作为 MySQL 驱动。

问题分析

mysqlclient 是 Django 官方推荐的 MySQL 数据库驱动,它依赖系统本地的 MySQL 或 MariaDB 客户端库,比如 libmysqlclientlibmariadbclient。这种依赖带来的问题是,如果本地的 MySQL 客户端库版本与 Python 项目中的依赖库(如 OpenSSL)版本不兼容,就会导致类似的错误。

我的环境中使用了 Anaconda 来管理 Python 环境,其中的 OpenSSL 是版本 1.1.1w,而 MySQL 服务器的版本是 5.7.24,客户端库是与该版本匹配的 libmysqlclient.so.18。显然,这两个库之间存在兼容性问题,导致程序运行时崩溃。

驱动选择的不同

在 Django 项目中,MySQL 数据库连接可以通过多种驱动来实现。常见的选择有以下两种:

  1. mysqlclient 驱动

    • 引擎: 'ENGINE': 'django.db.backends.mysql'
    • 依赖: 需要本地安装 MySQL 或 MariaDB 客户端库。
    • 优点: 性能优越,直接调用 MySQL 的 C API。
    • 缺点: 依赖于系统库,容易出现版本不兼容问题,特别是当 OpenSSL 或其他底层库不一致时。
  2. mysql-connector-python 驱动

    • 引擎: 'ENGINE': 'mysql.connector.django'
    • 依赖: 纯 Python 实现,不依赖本地 MySQL 客户端库。
    • 优点: 不依赖系统库,安装方便,环境兼容性更强。
    • 缺点: 性能相对 mysqlclient 略逊一筹。

解决方案

为了避免库之间的版本冲突,我决定尝试将 MySQL 驱动切换为 mysql-connector-python。这一驱动由 Oracle 官方维护,完全用 Python 实现,不依赖本地的 MySQL 客户端库,因此可以避免与 OpenSSL 等系统库的冲突。

1. 安装 mysql-connector-python

首先,安装 mysql-connector-python

pip install mysql-connector-python
2. 修改 Django 数据库配置

settings.py 中,将数据库配置的 ENGINE'django.db.backends.mysql' 修改为 'mysql.connector.django'

DATABASES = {
    'default': {
        'ENGINE': 'mysql.connector.django',
        'NAME': 'your_database_name',
        'USER': 'your_database_user',
        'PASSWORD': 'your_password',
        'HOST': 'your_host',
        'PORT': '3306',
    }
}
3. 测试连接

配置完成后,重新启动 Django 开发服务器:

python manage.py runserver 0.0.0.0:8123 --insecure

image.png 此次启动没有出现之前的内存错误,服务器正常运行,数据库连接也成功建立。

为什么选择 mysql-connector-python

mysql-connector-python 作为 MySQL 官方提供的纯 Python 驱动,虽然在性能上不及 mysqlclient,但它的优势在于环境兼容性更强,特别是在使用 Anaconda 等环境时,可以避免与本地系统库之间的依赖冲突。

对于不希望在开发过程中花费大量时间处理系统库兼容性问题的开发者来说,mysql-connector-python 是一个更为稳定和易于管理的选择。

总结

在 Django 项目中,选择合适的 MySQL 驱动至关重要。mysqlclient 提供了高性能的数据库访问,但可能在不同环境中引发依赖库的冲突,尤其是与 OpenSSL 和 MySQL 客户端库相关的兼容性问题。而 mysql-connector-python 由于是纯 Python 实现,避免了这些依赖问题,虽然性能稍逊,但对于很多开发场景已经足够。

如果你遇到与我类似的内存管理或库冲突问题,尝试切换 MySQL 驱动可能是一个有效的解决方案。