superset 升级和迁移中的那些坑

superset是一个优秀的开源数据展示软件,但是在一些支持上还有所欠缺。

笔者目前遇到一个任务: 需要将superset的数据库从sqlite迁移到mysql上,并升级superset,在这个过程中遇到了很多问题。

任务

  1. 迁移superset meta,sqlite -> mysql
  2. 升级superset, 0.28.1 -> 0.34.0rc1
  3. 使用docker启动superset

步骤1: 导出基础数据

使用superset自带命令导出数据源和数据配置:

superset export_datasources > datasources.yaml
superset export_dashboards > dashboards.json

问题1:版本不一致,无法直接导入数据

最开始笔者使用了0.34.0rc1的superset导入步骤1中的yaml和json,因为格式不一致,无法成功导入。 查看了源代码发现在这几个版本中,更改了大量的数据库schema,即superset的export不能跨版本导入。

步骤2:使用旧版本连接mysql,并导入数据

使用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保持一致了,理论上打开网页后查看图表的效果是没有区别的

步骤3:升级superset及其数据库

现在我们有了一个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数据

问题2:升级过程中出现"table already exist"错误

首先会遇到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_versionversion_num column中,表已存在的问题即解决

问题3:升级过程中出现Alter错误

导入依然不能成功,出现了下面的错误:

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查看报表了。

问题4:页面报出无法收藏报表的错误

查看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的迁移也完成了。最后总结一下经验:

  1. 导入导出要在同一版本进行,跨版本无法保证schema一致
  2. 无法自动升级的schema可以手动操作
  3. 在任何更改schema、更改版本的操作后,务必记住执行superset db upgradesuperset init,缺一不可
  4. 操作过程中记得随时备份数据,以防意外

你可能感兴趣的:(其它程序)