Replicação SQLite3 -> PostgreSQL¶
Objetivo¶
Replicar um banco de metadados do Superset de SQLite3 para PostgreSQL.
Links¶
[1] Guia de configurações: https://superset.apache.org/docs/configuration/configuring-superset
[2] Migrando Superset para Postgres: https://medium.com/@aaronbannin/migrating-superset-to-postgres-63d2c96c5102
[3] Exportando dados no SQLite para CSV: https://www.sqlitetutorial.net/sqlite-export-csv/
[4] Importando dados em CSV para o Postgres: https://www.postgresqltutorial.com/postgresql-tutorial/import-csv-file-into-posgresql-table/
Dependências¶
[1] Docker, 26.0.0
[2] Superset, 3.1.0
Motivação¶
A versão padrão de desenvolvimento do Superset vem com SQLite3 como sistema de gerenciamento para seu banco de dados de metadados. Siga esse guia caso haja dashboards desenvolvidos nessa versão e seja necessário replicar o banco para um banco em PostgreSQL.
Atenção: esse guia funciona (ou, pelo menos, funcionou) para replicar exatamente de um banco para o outro, e não preserva as informações que já existirem no banco em PostgreSQL.
Replicação¶
Faça um backup do banco de dados:
cp superset.db superset.db.bkp
;Existem algumas maneiras de migrar do SQLite para Postgres. O mais simples é fazer um dump de todas as tabelas do banco para CSV. Porém, precisamos nos atentar para determinados tipos de colunas que dão problema com o Postgres. Por exemplo, as colunas
uuid
são armazenadas em binário, e precisamos convertê-las para hexadecimal. Usei um script como esse (deve ser rodado sob usuárioroot
.):
#!/bin/sh
set -e
# diretório para armazenar os csv gerados
mkdir bkp
# nomes da maioria das tabelas do banco de metadados do Superset
TABELAS="ab_permission report_schedule ab_permission_view report_schedule_user ab_permission_view_role rls_filter_roles ab_register_user rls_filter_tables ab_role row_level_security_filters ab_user saved_query ab_user_role sl_columns ab_view_menu sl_dataset_columns alembic_version sl_dataset_tables annotation sl_dataset_users annotation_layer sl_datasets cache_keys sl_table_columns css_templates sl_tables dashboard_roles slice_user dashboard_slices slices dashboard_user sql_metrics dashboards sqlatable_user dbs ssh_tunnels dynamic_plugin tab_state embedded_dashboards table_columns favstar table_schema filter_sets tables"
for tabela in $TABELAS; do
# imprimir nomes das colunas na tabela, transformar em uma linha separada por
# vírgulas, envolver todos os nomes em aspas duplas, e substituir "uuid" por hex(uuid).
colunas=$(sqlite3 -csv superset.db "SELECT name FROM pragma_table_info('$tabela');" | awk '$1=$1' RS= OFS=\",\" | sed 's/\"uuid\"/hex(uuid)/')
colunas="\"${colunas}\""
sqlite3 -header -csv superset.db "SELECT $colunas FROM $tabela;" > bkp/$tabela.csv
echo "Tabela $tabela exportada."
done
# tabela key_value é especial porque contém uma coluna "value" que também deve ser convertida para hex.
colunas=$(sqlite3 -csv superset.db "SELECT name FROM pragma_table_info('key_value');" | awk '$1=$1' RS= OFS=\",\" | sed 's/\"uuid\"/hex(uuid)/' | sed 's/\"value\"/hex(value)/')
colunas="\"${colunas}\""
sqlite3 -header -csv superset.db "SELECT $colunas FROM key_value;" > bkp/key_value.csv
echo "Tabela key_value exportada."
# resto das tabelas
TABELAS="tag keyvalue tagged_object logs url query user_attribute report_execution_log user_favorite_tag"
for tabela in $TABELAS; do
colunas=$(sqlite3 -csv superset.db "SELECT name FROM pragma_table_info('$tabela');" | awk '$1=$1' RS= OFS=\",\" | sed 's/\"uuid\"/hex(uuid)/')
colunas="\"${colunas}\""
sqlite3 -header -csv superset.db "SELECT $colunas FROM $tabela;" > bkp/$tabela.csv
echo "Tabela $tabela exportada."
done
Use o comando
COPY
do Postgres para copiar as tabelas em CSV para dentro do banco de dados. OBS: Nesse momento as tabelas no Postgres devem estar criadas e vazias. Se houver dados, é necessário truncar as tabelas. Usei os seguintes scripts (com as informações necessárias preenchidas) (devem ser rodados sob o superusuário do Postgres):
#!/bin/sh
set -e
TABELAS="ab_permission report_schedule ab_permission_view report_schedule_user ab_permission_view_role rls_filter_roles ab_register_user rls_filter_tables ab_role row_level_security_filters ab_user saved_query ab_user_role sl_columns ab_view_menu sl_dataset_columns alembic_version sl_dataset_tables annotation sl_dataset_users annotation_layer sl_datasets cache_keys sl_table_columns css_templates sl_tables dashboard_roles slice_user dashboard_slices slices dashboard_user sql_metrics dashboards sqlatable_user dbs ssh_tunnels dynamic_plugin tab_state embedded_dashboards table_columns favstar table_schema filter_sets tables key_value tag keyvalue tagged_object logs url query user_attribute report_execution_log user_favorite_tag"
for tabela in $TABELAS; do
psql -U usuario_no_postgres -d banco_de_metadados_superset -c "TRUNCATE $tabela CASCADE;"
done
#!/bin/sh
set -e
# nessa etapa, a ordem de cópia das tabelas é importante porque elas possuem dependências umas com as outras.
# não mude a ordem em que as tabelas aparecem nessa string.
TABELAS="ab_permission report_schedule ab_view_menu ab_permission_view report_schedule_user ab_role ab_permission_view_role rls_filter_roles ab_register_user rls_filter_tables row_level_security_filters ab_user dbs saved_query ab_user_role sl_columns sl_dataset_columns alembic_version sl_dataset_tables annotation sl_dataset_users annotation_layer sl_datasets cache_keys sl_table_columns css_templates sl_tables dashboard_roles slices slice_user dashboards dashboard_slices dashboard_user tables sql_metrics sqlatable_user ssh_tunnels dynamic_plugin query tab_state embedded_dashboards table_columns favstar table_schema filter_sets key_value tag keyvalue tagged_object logs url user_attribute report_execution_log user_favorite_tag"
for tabela in $TABELAS; do
psql -U usuario_no_postgres -d banco_de_metadados_superset -c "COPY $tabela FROM '/app/superset_home/bkp/$tabela.csv' DELIMITER ',' CSV HEADER;"
done
Com todas as tabelas copiadas, reinicie o Superset. Você deve poder acessar agora os usuários, papéis, dashboards e gráficos criados anteriormente (dado que o Superset tenha acesso ao mesmo banco usado para criar os gráficos originalmente).