Django3 从 Sqlite3 迁移到 MySQL

django 真的非常好用,ORM 设计,加上开发时默认采用 SQLite 数据库,调试十分方便,默认的配置跑一些小的服务足够。但是,当数据变大时,SQLite 就不太够用了,我的某个项目现在 SQLite 数据库大小目前在 200 MB 左右,查询耗时,且 SQLite 不支持同步读取。服务器环境恰好已经建好 MySQL,遂打算迁移至 MySQL。下面记录一下操作过程。

安装必备的包

注意 python 的版本,我这里使用的是 ubuntu 20.04 LTS,安装下列包使默认 python 版本为 python3。

1
sudo apt install python-is-python3

给系统安装 MySQL 的客户端(我这里是 Ubuntu 20.04 LTS)。

1
sudo apt install default-libmysqlclient-dev

安装 Django 的 MySQL 驱动。

1
pip install mysqlclient

在 MySQL 里新建数据库

1
CREATE DATABASE dbname CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

也可以直接在 PHPMyAdmin 里新建一个用户,顺便建立同名表并给予权限(有 PHP 环境的话这样更方便)。

新建从数据库(slave)

根据刚才建好的表,填写 slave 数据库信息。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    },
    "slave": {
        "ENGINE": "django.db.backends.mysql",
        "NAME": "dbname",
        "USER": "dbuser",
        "PASSWORD": "passwd",
        "HOST": "localhost",
        "PORT": 3306,
    },
}

迁移表结构和字段到从数据库

1
python manage.py migrate --database slave

导出数据到 JSON 中间数据

1
python manage.py dumpdata > data.json

这一步需要耗费一些时间,导出的中间数据体积可能会翻倍。

切换主从数据库

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
DATABASES = {
    'slave': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    },
    "default": {
        "ENGINE": "django.db.backends.mysql",
        "NAME": "dbname",
        "USER": "dbuser",
        "PASSWORD": "passwd",
        "HOST": "localhost",
        "PORT": 3306,
    },
}

调换 slave 和 default,如上所示。

从 JSON 中间数据导入主数据库

1
python manage.py loaddata data.json

要注意这一步非常吃内存,我这里导入 400 MB 的 JSON 中间数据,内存 3GB+2GB SWAP 花了四十分钟才导入完毕(CPU Xeon E5-2697A v4 @ 2.60GHz KVM 划出双核),如果服务器配置不够,建议在工作机上远程连接数据库完成。