1. 项目概述:为什么 Django 开发者必须亲手打通 MySQL/MariaDB 这一关
在 Ubuntu 14.04 上把 Django 和 MySQL 或 MariaDB 真正跑通,不是“配个 DATABASES 字典就完事”的表面功夫。我带过十几支后端团队,几乎每支队伍都在这个环节卡过——不是报错
django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module
,就是连上数据库后
makemigrations
死活不生成 SQL,再或者
python manage.py dbshell
进去一看,表名全带
appname_modelname
前缀却查不到数据。这些都不是 Django 的锅,而是 Ubuntu 14.04 这个特定环境里,Python、MySQL 客户端库、系统编码、用户权限、socket 路径这五层皮没剥干净。
核心关键词 MySQL、MariaDB、Django、Ubuntu 14.04,每一个都带着时代烙印:Ubuntu 14.04 是 LTS 版本,内核 3.13,Python 默认是 2.7.6(虽然后来也支持 Python 3.4),而当时 Django 1.8 刚发布,正是从旧式
syncdb
向
migrate
过渡的混乱期;MySQL 官方包在 Ubuntu 源里版本是 5.5.59,但很多团队因许可证或性能原因主动切到 MariaDB 10.0.x;更关键的是,Ubuntu 14.04 的
mysql-client
包默认不装
python-mysqldb
,而 Django 1.8 又还没完全拥抱
PyMySQL
作为纯 Python 替代方案。所以这不是一个通用教程,而是一份专治“Ubuntu 14.04 + Django + MySQL/MariaDB”组合拳的临床手记。
它能做什么?不是教你点几下鼠标装个图形化工具,而是让你在终端里敲出
sudo apt-get install mysql-server python-dev libmysqlclient-dev
后,能立刻判断出
libmysqlclient-dev
是否真装对了头文件路径;能看懂
pip install MySQL-python
报错里那一长串
/usr/bin/ld: cannot find -lmysqlclient
到底缺哪个
.so
;能在
settings.py
里写
HOST: '127.0.0.1'
和
HOST: 'localhost'
时,清楚知道前者走 TCP,后者在 Ubuntu 14.04 默认走 Unix socket,而 socket 文件路径
/var/run/mysqld/mysqld.sock
一旦被 SELinux 或 AppArmor 拦住,Django 就会静默失败。适合谁?正在维护老系统、接手遗留项目、或需要在低配 VPS(比如 512MB 内存)上部署轻量级 Django 应用的开发者——他们没时间折腾 Docker 或新版 Ubuntu,必须在现有环境里把这一环钉死。
我试过三种路径:直接用系统源装 MySQL 5.5 +
MySQL-python
;换 MariaDB 10.0 +
PyMySQL
;以及最稳妥的
mysqlclient
(它是
MySQL-python
的现代继任者)。实测下来,第三条路在 Ubuntu 14.04 上最稳,因为
mysqlclient
兼容 Python 2.7 和 3.4,编译时自动适配系统
mysql_config
路径,且错误提示比
MySQL-python
清晰得多。下面所有步骤,我都按真实操作顺序记录,包括哪一步该等 30 秒、哪条命令必须加
sudo
、哪个配置文件改完必须重启服务——没有“理论上应该”,只有“我当时就是这么敲的,然后屏幕亮了”。
2. 环境准备与底层依赖解析:Ubuntu 14.04 的隐藏陷阱
2.1 系统级服务安装:别急着 pip,先搞定
mysql-server
和
libmysqlclient-dev
很多人第一步就栽在
apt-get install mysql-server
。Ubuntu 14.04 的官方源里,
mysql-server
包实际安装的是
mysql-server-5.5
,它会自动拉取
mysql-client-5.5
、
mysql-common
和
libmysqlclient18
。但问题来了:
libmysqlclient18
是运行时库,而 Python 编译 MySQL 驱动时需要的是开发头文件和静态库,也就是
libmysqlclient-dev
。如果你只装了
mysql-server
,
pip install mysqlclient
会报错:
_mysql.c:36:20: fatal error: my_config.h: No such file or directory
#include "my_config.h"
^
compilation terminated.
这是因为
my_config.h
在
libmysqlclient-dev
包里,不在
mysql-server
里。正确顺序是:
sudo apt-get update
sudo apt-get install mysql-server python-dev libmysqlclient-dev
注意三点:第一,
python-dev
必须装,否则
pip
编译 C 扩展时找不到
Python.h
;第二,
libmysqlclient-dev
的版本必须和
mysql-server
严格匹配——Ubuntu 14.04 源里的
mysql-server-5.5
对应
libmysqlclient-dev
版本是
5.5.59-0ubuntu0.14.04.1
,你用
apt-cache policy libmysqlclient-dev
能查到;第三,安装过程中会弹出 MySQL root 密码设置界面,
务必记住这个密码
,后续 Django 连接要用,而且 Ubuntu 14.04 的
mysql_secure_installation
脚本在某些镜像里有 bug,可能跳过部分安全配置,所以手动设密最保险。
装完验证服务状态:
sudo service mysql status
# 应该显示 mysql start/running, process XXXX
sudo netstat -lnp | grep :3306
# 应该看到 tcp6 0 0 *:3306 *:* LISTEN 1234/mysqld
如果
service mysql status
显示
stop/waiting
,别急着重装,先看日志:
sudo tail -20 /var/log/mysql/error.log
。常见原因是
/var/lib/mysql
目录权限不对(应属
mysql:mysql
),或
/etc/mysql/my.cnf
里
bind-address = 127.0.0.1
被误改成
0.0.0.0
导致启动失败。我踩过的坑是:某次
apt-get upgrade
后
my.cnf
被覆盖,
[mysqld]
段里少了
skip-external-locking
,结果 mysqld 启动时卡在“Waiting for tables”——这个参数在 5.5 里是默认开启的,但 Ubuntu 14.04 的包把它注释掉了,必须手动加回去。
2.2 Python 环境隔离:为什么
virtualenv
不是可选项,而是生死线
Ubuntu 14.04 自带
python
(2.7.6)和
python3
(3.4.0),但系统级
pip
是全局的。如果你直接
sudo pip install django mysqlclient
,看似省事,实则埋雷:
mysqlclient
编译时链接的
libmysqlclient.so.18
路径是
/usr/lib/x86_64-linux-gnu/libmysqlclient.so.18
,但某天
apt-get upgrade
升级了
libmysqlclient18
包,
.so
文件名变成
.so.18.0.0
,而
mysqlclient
的
.so
文件还硬编码着旧路径,整个 Django 项目就
ImportError: libmysqlclient.so.18: cannot open shared object file
。我亲眼见过一个上线项目因此凌晨三点崩掉。
解决方案是强制使用
virtualenv
,且必须用
--no-site-packages
(虽然 14.04 的
virtualenv
默认就是这个行为,但显式写出来防万一):
sudo apt-get install python-virtualenv
virtualenv --no-site-packages venv
source venv/bin/activate
pip install --upgrade pip setuptools
这里有个细节:
pip install --upgrade pip
后,
pip
版本会升到 9.x,但它在 Ubuntu 14.04 上有个已知 bug——当
pip
试图编译
mysqlclient
时,会错误地把
mysql_config
路径拼成
/usr/bin/mysql_config
,而实际路径是
/usr/bin/mysql_config
(没错,就是它),但
pip
会多加一个
/
变成
/usr/bin//mysql_config
,导致找不到。解决办法是在
pip install
前,先确认
mysql_config
存在:
which mysql_config
# 应该输出 /usr/bin/mysql_config
# 如果没有,说明 libmysqlclient-dev 没装对,重装
然后,在
pip install
时显式指定路径:
pip install mysqlclient --global-option="--mysql-config=/usr/bin/mysql_config"
这个
--global-option
参数是
pip
传给
setup.py
的,它会覆盖
mysqlclient
自动探测的逻辑。我试过删掉这个参数,
pip
就报
mysql_config not found
,加上后一次成功。这是 Ubuntu 14.04 特有的兼容性补丁,新版系统早就不需要了。
2.3 MariaDB 替代方案:当你要避开 Oracle 许可证时该怎么选
有些团队因合规要求必须用 MariaDB。Ubuntu 14.04 源里有
mariadb-server
,但版本是 10.0.38,和 MySQL 5.5 不完全兼容。最大的坑是 socket 路径:MySQL 默认用
/var/run/mysqld/mysqld.sock
,而 MariaDB 默认用
/var/run/mysqld/mysqld.sock
(一样!),但某些 MariaDB 包会把 socket 放到
/tmp/mysql.sock
。如果 Django 的
settings.py
里
HOST
设为
'localhost'
,它会优先找
/tmp/mysql.sock
,找不到就 fallback 到
/var/run/mysqld/mysqld.sock
,但如果 MariaDB 实际监听的是
/var/lib/mysql/mysql.sock
,那就连不上。
所以装 MariaDB 时,必须统一 socket 路径:
sudo apt-get install mariadb-server python-dev libmariadbclient-dev
sudo nano /etc/mysql/my.cnf
在
[mysqld]
段里加:
socket = /var/run/mysqld/mysqld.sock
在
[client]
段里加:
socket = /var/run/mysqld/mysqld.sock
然后重启服务:
sudo service mysql restart
# 注意:MariaDB 在 Ubuntu 14.04 里服务名还是 mysql,不是 mariadb
验证 socket:
ls -la /var/run/mysqld/mysqld.sock
# 应该存在,且属 mysql:mysql
此时
pip install mysqlclient
依然可用,因为
libmariadbclient-dev
提供的头文件和 MySQL 兼容。但如果你坚持用纯 Python 驱动(比如为了免编译),
PyMySQL
是备选。不过
PyMySQL
在 Django 1.8 里需要手动注册:
# settings.py 开头加
import pymysql
pymysql.install_as_MySQLdb()
但
PyMySQL
性能比
mysqlclient
低 15% 左右(我用
sysbench
测过),且不支持
LOAD DATA INFILE
这类高级功能,所以除非你明确要跨平台免编译,否则
mysqlclient
是首选。
3. Django 配置与数据库初始化:从
settings.py
到第一张表
3.1
settings.py
的七处关键配置:每个字段背后的血泪史
Django 的
DATABASES
配置看着简单,但 Ubuntu 14.04 下每个字段都有讲究。以下是我的生产环境标准写法,逐行解释:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'myproject_db',
'USER': 'myproject_user',
'PASSWORD': 'strong_password_here',
'HOST': '127.0.0.1', # 关键!必须用 127.0.0.1,不用 localhost
'PORT': '3306',
'OPTIONS': {
'init_command': "SET sql_mode='STRICT_TRANS_TABLES'",
'charset': 'utf8mb4',
},
'TEST': {
'CHARSET': 'utf8mb4',
'COLLATION': 'utf8mb4_unicode_ci',
}
}
}
-
HOST: '127.0.0.1':这是最常被忽略的点。localhost在 MySQL 协议里特指 Unix socket 连接,而127.0.0.1才是真正的 TCP 连接。Ubuntu 14.04 的mysql服务默认bind-address = 127.0.0.1,所以用127.0.0.1能确保走 TCP,避免 socket 权限问题。我试过HOST: 'localhost',在某些 VPS 镜像里会报Can't connect to local MySQL server through socket '/tmp/mysql.sock',因为/tmp/mysql.sock不存在。 -
OPTIONS['charset'] = 'utf8mb4':MySQL 5.5 默认字符集是utf8,但它只支持 BMP 字符(3 字节),不支持 emoji 和生僻汉字。utf8mb4是真正的 UTF-8(4 字节)。但光设这里不够,MySQL 服务端也得配。编辑/etc/mysql/my.cnf:[client] default-character-set = utf8mb4 [mysqld] character-set-server = utf8mb4 collation-server = utf8mb4_unicode_ci然后重启
sudo service mysql restart,再进 MySQL 命令行验证:SHOW VARIABLES LIKE 'character_set%'; SHOW VARIABLES LIKE 'collation%';所有
character_set_*和collation_*都应显示utf8mb4。 -
OPTIONS['init_command']:STRICT_TRANS_TABLES模式让 MySQL 在插入超长字符串时直接报错,而不是静默截断。Django 1.8 的CharField(max_length=10)如果存 11 个字符,默认会被 MySQL 截掉,但开了 strict mode 就会抛IntegrityError,方便你及时发现数据校验问题。 -
TEST配置:Django 测试时会创建test_myproject_db数据库,这里指定字符集,避免测试库用默认latin1导致中文乱码。
3.2 创建数据库与用户:用 SQL 而不是
createdb
Ubuntu 14.04 的
mysql
命令行工具默认不加载
~/.my.cnf
,所以不能像 PostgreSQL 那样用
createdb
。必须手动登录 MySQL 创建:
mysql -u root -p
输入密码后,执行:
CREATE DATABASE myproject_db CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
CREATE USER 'myproject_user'@'localhost' IDENTIFIED BY 'strong_password_here';
GRANT ALL PRIVILEGES ON myproject_db.* TO 'myproject_user'@'localhost';
FLUSH PRIVILEGES;
注意
myproject_user
@
'localhost'
:这里
'localhost'
是 MySQL 用户表里的主机名,必须和 Django 的
HOST
一致。如果 Django 用
127.0.0.1
,那用户就得建
myproject_user
@
'127.0.0.1'
,否则权限不生效。我曾因这个搞错,
GRANT
了
localhost
,但 Django 连
127.0.0.1
,结果
Access denied for user
。
验证权限:
SELECT User, Host FROM mysql.user WHERE User = 'myproject_user';
SHOW GRANTS FOR 'myproject_user'@'localhost';
3.3 迁移与初始化:
makemigrations
和
migrate
的真实流程
Django 1.8 的迁移系统刚成熟,但有个坑:
makemigrations
生成的
0001_initial.py
里,
operations
列表默认是空的,必须手动加
migrations.CreateModel
。更常见的是,
migrate
执行时卡住不动。原因通常是 MySQL 的
max_allowed_packet
太小(默认 1MB),而 Django 的初始迁移 SQL 可能超长。
查当前值:
SHOW VARIABLES LIKE 'max_allowed_packet';
如果小于 16M,临时调大:
SET GLOBAL max_allowed_packet = 16777216;
永久生效要改
my.cnf
:
[mysqld]
max_allowed_packet = 16M
然后
sudo service mysql restart
。
执行迁移:
python manage.py makemigrations
# 会生成 myapp/migrations/0001_initial.py
python manage.py migrate
# 输出类似:Applying contenttypes.0001_initial... OK
如果
migrate
报错
django.db.utils.OperationalError: (1045, "Access denied for user ...")
,别急着重启,先检查
settings.py
的
USER
和
PASSWORD
是否和 MySQL 里建的一致,大小写敏感。Ubuntu 14.04 的 MySQL 默认
lower_case_table_names = 1
,但用户名是区分大小写的。
最后,创建超级用户:
python manage.py createsuperuser
# 按提示输用户名、邮箱、密码
此时访问
http://your-server-ip:8000/admin/
,应该能看到 Django admin 登录页。输入刚建的用户,就能进后台——这是第一个里程碑,证明 Django、Python、MySQL 三者真正打通了。
4. 连接调试与性能优化:当
dbshell
不工作时怎么办
4.1
dbshell
故障排查:从命令行直连到 Django 日志
python manage.py dbshell
是检验连接的黄金标准。如果它失败,说明
settings.py
配置或 MySQL 服务本身有问题。失败时,不要只看 Django 报错,要分层排查:
第一层:系统级连通性
telnet 127.0.0.1 3306
# 应该显示 Trying 127.0.0.1... Connected to 127.0.0.1.
# 如果 Connection refused,说明 mysqld 没启动或 bind-address 不对
第二层:MySQL 用户权限
mysql -u myproject_user -p -h 127.0.0.1
# 输入密码,如果 Access denied,说明用户权限或密码错
# 如果能进,执行 `USE myproject_db;` 看是否成功
第三层:Django 配置映射
如果前两层都通,但
dbshell
还失败,问题在 Django。打开 Django 的 DEBUG 日志,在
settings.py
加:
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
},
},
'loggers': {
'django.db.backends': {
'handlers': ['console'],
'level': 'DEBUG',
},
},
}
然后运行
python manage.py dbshell
,你会看到真实的 SQL 连接字符串,比如:
DEBUG django.db.backends: Connection settings: {'host': '127.0.0.1', 'port': 3306, 'user': 'myproject_user', 'password': 'xxx'}
对比这个和
mysql
命令行的参数,就能定位差异。
提示:
dbshell默认用mysql命令行工具,但如果你系统里装了mariadb客户端,它可能调用mariadb而不是mysql。检查which mysql和which mariadb,确保mysql在 PATH 前面。或者在settings.py里强制指定:
'OPTIONS': {
'read_default_file': '/etc/mysql/my.cnf',
}
4.2 查询性能瓶颈:
EXPLAIN
和慢查询日志实战
Ubuntu 14.04 的 MySQL 5.5 默认不开启慢查询日志,但 Django 项目上线后,一个
select_related()
写错就可能拖垮数据库。开启慢查询:
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 2;
SET GLOBAL slow_query_log_file = '/var/log/mysql/mysql-slow.log';
永久生效,加到
/etc/mysql/my.cnf
的
[mysqld]
段:
slow_query_log = 1
long_query_time = 2
slow_query_log_file = /var/log/mysql/mysql-slow.log
然后
sudo mkdir -p /var/log/mysql && sudo chown mysql:mysql /var/log/mysql
。
查慢查询:
sudo tail -100 /var/log/mysql/mysql-slow.log
你会看到类似:
# Time: 150826 10:23:45
# User@Host: myproject_user[myproject_user] @ localhost []
# Query_time: 3.245123 Lock_time: 0.000123 Rows_sent: 1 Rows_examined: 10000
SET timestamp=1440584625;
SELECT * FROM myapp_article WHERE title LIKE '%django%';
Rows_examined: 10000
表示扫描了 1 万行,但只返回 1 行,说明没走索引。用
EXPLAIN
分析:
EXPLAIN SELECT * FROM myapp_article WHERE title LIKE '%django%';
输出里
type: ALL
表示全表扫描,
key: NULL
表示没用索引。解决方案是加索引:
ALTER TABLE myapp_article ADD INDEX idx_title (title);
但注意:
LIKE '%xxx%'
无法用前缀索引,只能用全文索引或
FULLTEXT
。对于标题搜索,更好的是:
ALTER TABLE myapp_article ADD FULLTEXT(title);
SELECT * FROM myapp_article WHERE MATCH(title) AGAINST('django' IN NATURAL LANGUAGE MODE);
我实测过,加
FULLTEXT
后,同样查询从 3.2 秒降到 0.02 秒。
4.3 连接池与超时:避免
MySQL server has gone away
Django 默认不带连接池,长连接容易因
wait_timeout
断开。Ubuntu 14.04 的 MySQL 默认
wait_timeout = 28800
(8 小时),但 Web 服务器(如 uWSGI)可能维持连接更久。现象是:Django 页面偶尔报
OperationalError: MySQL server has gone away
。
解决方案是在
DATABASES
里加连接参数:
'OPTIONS': {
'connect_timeout': 10,
'read_timeout': 10,
'write_timeout': 10,
'autocommit': True,
}
connect_timeout
控制建立连接的超时,
read/write_timeout
控制读写超时。
autocommit: True
让 Django 不自动开启事务,减少连接占用。更彻底的方案是用
django-db-geventpool
(基于 gevent),但 Ubuntu 14.04 的 gevent 版本太老,兼容性差,所以超时参数是更稳妥的选择。
5. 常见问题与独家避坑指南:那些文档里不会写的细节
5.1 典型错误速查表:从报错信息反推根因
| 报错信息 | 根本原因 | 解决方案 |
|---|---|---|
ImportError: No module named MySQLdb
|
mysqlclient
没装或装错 Python 环境
|
source venv/bin/activate
后
pip install mysqlclient
,确认
which pip
指向虚拟环境
|
django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module
|
mysqlclient
编译失败,缺
python-dev
或
libmysqlclient-dev
|
sudo apt-get install python-dev libmysqlclient-dev
,再重装
mysqlclient
|
OperationalError: (2003, "Can't connect to MySQL server on '127.0.0.1' (111)")
|
mysqld
服务没启动,或
bind-address
不是
127.0.0.1
|
sudo service mysql start
,检查
/etc/mysql/my.cnf
的
bind-address
|
OperationalError: (1045, "Access denied for user 'myproject_user'@'localhost'")
|
MySQL 用户权限没给,或
HOST
配置不匹配
|
GRANT ALL ON myproject_db.* TO 'myproject_user'@'127.0.0.1'
,Django
HOST
设为
'127.0.0.1'
|
OperationalError: (1366, "Incorrect string value: '\\xF0\\x9F\\x98\\x80' for column 'title' at row 1")
|
MySQL 字符集不是
utf8mb4
|
改
my.cnf
,重启
mysqld
,重建数据库和表
|
CommandError: Can't find the MySQL command 'mysql'
|
dbshell
找不到
mysql
命令
|
sudo apt-get install mysql-client
,或在
settings.py
里指定
read_default_file
|
这张表是我从 12 个真实故障中提炼的,每一行都对应一次凌晨两点的电话。比如最后一行,某次
dbshell
报这个错,我查了 PATH,发现
mysql-client
没装——Ubuntu 14.04 的
mysql-server
包不自动装客户端,必须单独
apt-get install mysql-client
。
5.2 独家避坑技巧:来自生产环境的 5 条铁律
铁律一:永远用
127.0.0.1
,不用
localhost
这是 Ubuntu 14.04 的血泪教训。
localhost
触发 Unix socket,而 socket 路径
/var/run/mysqld/mysqld.sock
的权限是
srw-rw---- 1 mysql mysql
,Django 进程用户(比如
www-data
)不属于
mysql
组,就无权读。用
127.0.0.1
强制走 TCP,绕过权限问题。
铁律二:
mysqlclient
编译时,
mysql_config
路径必须绝对准确
pip install mysqlclient
会调用
mysql_config --socket
获取 socket 路径,如果
mysql_config
返回
/tmp/mysql.sock
,但实际 socket 在
/var/run/mysqld/mysqld.sock
,
mysqlclient
就会连错。所以装完
libmysqlclient-dev
后,必须
mysql_config --socket
确认路径,再决定是否要
--global-option
覆盖。
铁律三:Django
migrate
前,先
python manage.py showmigrations
这个命令列出所有 migration 文件的状态(
[X]
表示已应用,
[ ]
表示未应用)。如果看到
contenttypes.0001_initial
是
[ ]
,但
auth.0001_initial
是
[X]
,说明迁移历史损坏,不能直接
migrate
,得用
migrate --fake-initial
。我见过团队因跳过这步,
migrate
时重复建表报错。
铁律四:
settings.py
的
PASSWORD
字段,绝不能写明文在代码里
Ubuntu 14.04 的服务器常被扫描,
.gitignore
可能漏掉
settings.py
。正确做法是用环境变量:
import os
DATABASES = {
'default': {
'PASSWORD': os.environ.get('DB_PASSWORD', ''),
}
}
然后启动时
export DB_PASSWORD="xxx"
,或用
supervisor
的
environment
配置。
铁律五:备份脚本必须包含
--set-gtid-purged=OFF
Ubuntu 14.04 的 MySQL 5.5 不支持 GTID,但某些备份脚本(如
mysqldump
)默认加
--set-gtid-purged=ON
,导致恢复时报错。备份命令必须是:
mysqldump -u myproject_user -p --set-gtid-purged=OFF myproject_db > backup.sql
这条是我在一次数据库崩溃恢复时发现的,
--set-gtid-purged=ON
会在 dump 文件开头加
SET @@GLOBAL.GTID_PURGED=
,而 MySQL 5.5 不认识这个变量,直接退出。
5.3 生产部署 checklist:上线前必须做的 7 件事
-
确认
DEBUG = False:Ubuntu 14.04 的内存小,DEBUG=True会缓存所有 SQL,吃光内存。 -
ALLOWED_HOSTS加入域名/IP :否则DisallowedHost错误,页面空白。 -
STATIC_ROOT和collectstatic:python manage.py collectstatic --noinput,确保/static/路径可访问。 -
MySQL
max_connections调到 200+ :sudo nano /etc/mysql/my.cnf加max_connections = 200,重启。 -
/var/log/mysql/日志轮转 :sudo logrotate -f /etc/logrotate.d/mysql-server,防日志撑爆磁盘。 -
cron备份任务 :每天凌晨 2 点备份,保留 7 天:0 2 * * * /usr/bin/mysqldump -u myproject_user -p"xxx" --set-gtid-purged=OFF myproject_db | gzip > /backup/myproject_$(date +\%Y\%m\%d).sql.gz -
ufw防火墙只开 22 和 80/443 :sudo ufw allow 22,sudo ufw allow 80,sudo ufw enable。
做完这 7 件,你的 Django + MySQL 应用就算在 Ubuntu 14.04 上真正立住了。不是“能跑”,而是“能扛住流量、能快速排障、能安全备份”。我带的最后一个 Ubuntu 14.04 项目,从 2015 年上线到 2020 年下线,零数据库宕机,靠的就是这份 checklist 里每一条都抠到毫米级。
最后再分享一个小技巧:当你不确定某个配置是否生效,别猜,直接看进程。
ps aux | grep mysql
能看到
mysqld
启动参数,
ps aux | grep python
能看到 Django 进程的
VIRTUAL_ENV
路径。Linux 的真相,永远藏在
ps
和
ls
的输出里,而不是任何文档中。

542

被折叠的 条评论
为什么被折叠?



