superset是一个优秀的开源数据展示软件,但是在一些支持上还有所欠缺。
笔者目前遇到一个任务: 需要将superset的数据库从sqlite迁移到mysql上,并升级superset,在这个过程中遇到了很多问题。
使用superset自带命令导出数据源和数据配置:
superset export_datasources > datasources.yaml
superset export_dashboards > dashboards.json
最开始笔者使用了0.34.0rc1的superset导入步骤1中的yaml和json,因为格式不一致,无法成功导入。 查看了源代码发现在这几个版本中,更改了大量的数据库schema,即superset的export不能跨版本导入。
使用docker启动一个新的superset,版本和旧superset一致(0.28.1)
docker run -d -p 8088:8088 -v /root/superset:/home/superset amancevice/superset:0.28.1
在这里使用-v
挂在了本地的一个目录,目录里有superset_config.py
,其中配置了mysql作为meta数据库
假设我们使用了一个空的库,(实际上也应当使用空库),则需要执行一下命令初始化:
superset db upgrade
superset init
使用导入数据命令:
superset import_datasources -p datasources.yaml
superset import_dashboards -p dashboards.json
导入完成后,依然需要执行初始化命令:
superset db upgrade
superset init
导入后mysql数据就和sqlite保持一致了,理论上打开网页后查看图表的效果是没有区别的
现在我们有了一个0.28.1版本的mysql,需要把它升级到0.34.0rc1
关闭旧docker,启动superset:
docker run -d -p 8088:8088 -v /root/superset:/home/superset amancevice/superset:0.34.0rc1
执行命令:
superset db upgrade
这个命令会根据数据库变化自动更新数据库schema,merge数据
首先会遇到table已存在的错误:
(MySQLdb._exceptions.OperationalError) (1050, "Table 'clusters' already exists")
很奇怪,既然是升级,那么这个数据库必然是已经存在的,升级工具难道考虑不到这个情况?
google一下,找到了一个讨论:https://github.com/apache/incubator-superset/issues/4691
这里面最高赞的pammi22
说应该把sqlalchemy
降级到1.2,亲测不太好用,其实正确答案在pckhoi
这里:
Your alembic_version table is probably corrupted. In my case what I did was running fabmanager create-db --app superset initially instead of superset db upgrade, which create the tables but not the alembic_version table. To fix it I figured out the latest migration and ran this in
my database:CREATE TABLE alembic_version (version_num character varying(32) PRIMARY KEY); INSERT INTO alembic_version (version_num) VALUES ('d6ffdf31bdd4');
You’ll have to replace the version_num with your own appropriate value of course.
重点在于alembic_version
表里缺失了当前的version,没有当前版本,db upgrade
命令就不能正确地处理schema升级
于是我手动去sqlite里查询了这个表值,并将值填入了alembic_version
的version_num
column中,表已存在的问题即解决
导入依然不能成功,出现了下面的错误:
sqlalchemy.exc.DataError: (MySQLdb._exceptions.DataError) (1265, "Data truncated for column 'metric_name' at row 374") [SQL: 'ALTER TABLE sql_metrics MODIFY metric_name VARCHAR(255) NOT NULL']
看起来升级需要更改一个column的属性,VARCHAR(512)
-> VARCHAR(255)
但是没有更改成功
手动更改mysql中这个column的定义,问题解决。
下一个问题:
sqlalchemy.exc.OperationalError: (MySQLdb._exceptions.OperationalError) (1138, 'Invalid use of NULL value') [SQL: 'ALTER TABLE sql_metrics MODIFY expression TEXT NOT NULL']
同样的,升级要更改expression
字段为NOT NULL
,但是数据库里已有NULL值,更新失败。那么手动去掉数据库的NULL值即可。
你可能已经发现,在这个过程中错误比较清晰,如果升级不成功,我们就帮他升级,自然会绕过这个错误。
改完这些后,你已经可以打开0.34的superset查看报表了。
查看dashboard没问题了,但是在操作过程中,页面总是会有弹窗
There was an issue fetching the favorite status of this dashboard
搜索到一个讨论:https://github.com/apache/incubator-superset/issues/6824
根据里面的说法,在superset_config.py
中添加两行配置:
ENABLE_CORS = True
ENABLE_PROXY_FIX = True
然而没有解决问题,换个issue:https://github.com/apache/incubator-superset/issues/8121
这里kuckjwi0928
点出了问题的本质,db upgrade
后忘了init
!
init
会根据版本创建相关的数据表、用户和权限,由于没有init,就缺失了favstar的权限,因此一直报错。
在一系列复杂的操作后,superset的迁移也完成了。最后总结一下经验:
superset db upgrade
和superset init
,缺一不可