好吧,这其实并不是啥高深的东西。如果你升级之前老老实实看了 Changelog,就肯定不会跟我这么倒霉了。
这件事情还是今天我们的 Gitlab CI 莫名其妙挂掉了。日志如下:
$ coverage run manage.py test --settings=takachiho.settings.testing --pattern="test_*.py" -v 2
DEBUG 2018-08-02 20:02:31,948 base 619 140240725620480 Configuring Raven for host: None
INFO 2018-08-02 20:02:31,949 base 619 140240725620480 Raven is not configured (logging is disabled). Please see the documentation for more information.
Creating test database for alias 'default' ('test_takachiho_temp')...
Operations to perform:
Synchronize unmigrated apps: admindocs, django_mptt_admin, messages, mptt, raven_contrib_django, staticfiles
Apply all migrations: admin, alarm, auth, contenttypes, django_celery_beat, locator, metadata, monitor, noise_reductor, request_locator, sessions, utils
Synchronizing apps without migrations:
Creating tables...
Running deferred SQL...
Running migrations:
Traceback (most recent call last):
File "/usr/local/lib/python3.6/site-packages/django/db/backends/utils.py", line 83, in _execute
return self.cursor.execute(sql)
File "/usr/local/lib/python3.6/site-packages/django/db/backends/mysql/base.py", line 71, in execute
return self.cursor.execute(query, args)
File "/usr/local/lib/python3.6/site-packages/MySQLdb/cursors.py", line 250, in execute
self.errorhandler(self, exc, value)
File "/usr/local/lib/python3.6/site-packages/MySQLdb/connections.py", line 50, in defaulterrorhandler
raise errorvalue
File "/usr/local/lib/python3.6/site-packages/MySQLdb/cursors.py", line 247, in execute
res = self._query(query)
File "/usr/local/lib/python3.6/site-packages/MySQLdb/cursors.py", line 412, in _query
rowcount = self._do_query(q)
File "/usr/local/lib/python3.6/site-packages/MySQLdb/cursors.py", line 375, in _do_query
db.query(q)
File "/usr/local/lib/python3.6/site-packages/MySQLdb/connections.py", line 276, in query
_mysql.connection.query(self, query)
_mysql_exceptions.ProgrammingError: (1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '(6) NOT NULL)' at line 1")
其中:
本地运行是 ok 的
master 分支的CI是 ok 的
挂掉的那个分支添加了新的依赖 anytree
大量被浪费的时间……
一开始我怀疑是代码的变更导致生成了不合法的 SQL,于是仔细看了一遍 migrations,没发现什么异常(这是白费功夫,因为显然 migrations 还没开始执行就挂了)。
于是尝试打印出来执行的 SQL,因为 CI 是在 docker 跑的,于是我直接进入 docker ,修改 SQL syntax error 的那个文件,打印出来 q
,结果如下:
Operations to perform:
Synchronize unmigrated apps: admindocs, django_mptt_admin, messages, mptt, raven_contrib_django, staticfiles
Apply all migrations: admin, alarm, auth, contenttypes, django_celery_beat, locator, metadata, monitor, noise_reductor, request_locator, sessions, utils
Synchronizing apps without migrations:
b'SHOW FULL TABLES'
Creating tables...
Running deferred SQL...
Running migrations:
b'SHOW FULL TABLES'
b'CREATE TABLE `django_migrations` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `app` varchar(255) NOT NULL, `name` varchar(255) NOT NULL, `applied` datetime(6) NOT NULL)'
Traceback (most recent call last):
File "/usr/local/lib/python3.6/site-packages/django/db/backends/utils.py", line 83, in _execute
return self.cursor.execute(sql)
File "/usr/local/lib/python3.6/site-packages/django/db/backends/mysql/base.py", line 71, in execute
return self.cursor.execute(query, args)
File "/usr/local/lib/python3.6/site-packages/MySQLdb/cursors.py", line 250, in execute
self.errorhandler(self, exc, value)
File "/usr/local/lib/python3.6/site-packages/MySQLdb/connections.py", line 50, in defaulterrorhandler
raise errorvalue
File "/usr/local/lib/python3.6/site-packages/MySQLdb/cursors.py", line 247, in execute
res = self._query(query)
File "/usr/local/lib/python3.6/site-packages/MySQLdb/cursors.py", line 413, in _query
rowcount = self._do_query(q)
File "/usr/local/lib/python3.6/site-packages/MySQLdb/cursors.py", line 376, in _do_query
db.query(q)
File "/usr/local/lib/python3.6/site-packages/MySQLdb/connections.py", line 276, in query
_mysql.connection.query(self, query)
_mysql_exceptions.ProgrammingError: (1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '(6) NOT NULL)' at line 1")
我把这行代码拷贝到本机的 Mysql 执行,没问题啊(废话,我为啥要这么做啊…… Docker里面的 mysql 和我电脑上的明显版本不一样)。
于是在 Docker 的 mysql 执行,嗯,确实语法错误。而且我确认了是支持 datetime
不支持 datetime(6)
mysql> CREATE TABLE `django_migrations` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `app` varchar(255) NOT NULL, `name` varchar(255) NOT NULL, `applied` datetime NOT NULL);
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TABLE `django_migrations` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `app` varchar(255) NOT NULL, `name` varchar(255) NOT NULL, `applied` datetime(6) NOT NULL);
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '(6) NOT NULL)' at line 1
但是为啥之前好好地,突然就有问题了呢?唉,这里浪费的时间就不说了,总之我后来终于顿悟发觉是依赖更新了导致的。因为 requirements.txt
添加了一个新的 package ,里面所有的东西都重新安装过(新建的 Docker image),然后因为我们的 pip 没有锁版本,最近 Django 发布 2.1,CI 的 image 由默认的 2.0 版本升级到 2.1 了。
我用两个 Django 版本跑测试,打印出来 SQL 日志,发现两个版本生成的 SQL 语法确实不一样。
其中,Django2.0 创建 migrations 生成的 SQL 如下:
CREATE TABLE `django_migrations` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `app` varchar(255) NOT NULL, `name` varchar(255) NOT NULL, `applied` datetime NOT NULL)
然后当前 pip 默认版本的 Django 2.1 创建 migrations 生成的 SQL 如下:
CREATE TABLE `django_migrations` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `app` varchar(255) NOT NULL, `name` varchar(255) NOT NULL, `applied` datetime(6) NOT NULL)
唯一的不同就是 datetime
变成了 datetime(6)
。
而我们的 CI image 用的是 python-3.6-jessie
,apt-get 安装的 mysql 版本是 5.5,不支持 datetime(6)
这种语法。
但是好好的 migrations 咋说更新就更新了呢? I blame Django。
然后我就发现人家明确说不支持 Mysql 5.5 了: Dropped support for MySQL 5.5
好吧,算我活该。
反思:
pip list
博客讲述了作者在使用Django2.1时遇到的问题,由于Django2.1版本的migrations在创建表格时使用了datetime(6)字段,而在MySQL5.5中不支持此语法,导致数据库迁移失败。这个问题在Django的更新日志中有提及,但作者在升级时未注意到。通过排查和测试,作者确定问题源于Django版本升级和MySQL版本不兼容。解决方案是将数据库升级到支持datetime(6)的版本或者回退Django到兼容的版本。
989

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



