寫在前面的話
首先如果你看到了這篇文章,可能你就已經指定 Metabase 是啥了,我這里還是簡單的做個說明:
Metabase is the easy, open source way for everyone in your company to ask questions and learn from data。
官網是這樣描述的,這是一款 BI 開源工具,能讓你的數據以漂亮的圖表顯示出來,雖然我覺得並不是很好看,但是還是叫漂亮吧。同類的產品還有 Superset,Redash 等等。
感興趣的可以看看官網:
也可以研究下 GITHUB:
數據遷移
故事是醬嬸兒滴,公司准備搞一個這樣的系統,然后交給就讓我搭建了這幾個出來做橫向比較。當然,我就是把他運行起來,至於配置都丟給了數據組的老哥。然后這個環境就慢慢的配置越來越多。最后一拍腦門就選它了。於是不可能重新配置啊,這樣就得把項目遷移到雲上。
問題出現了,因為之前我是以 demo 形式搭建丟給他們的,所有數據庫這些啥都是默認是,Metabase 的默認是 H2 數據庫。在搞這個之前我根本不知道這是啥。然后網上找了很多導出數據的方式都特么扯皮。各種報錯或者根本不能用。
問題出在哪里呢?就處在將數據導出到 MySQL 的時候,報錯:Data too long xxxx
既然說到這里,那就先回顧一下我的遷移過程:
【1】首先我們先停止在運行 metabase 服務,我是直接 jar 形式運行的,kill 掉就行。
【2】此時我們可以看到默認運行的時候,在 jar 的目錄下存在兩個數據庫的文件:
上面兩個 db 文件就是用到 H2 數據庫了,我們把這 3 個文件移動到其他目錄備份,相當重要,不然掛了你就哭吧!!!
【3】此時我們新建一個 metabase 的庫(我的是 MySQL 5.7):
CREATE DATABASE metabase default charset utf8 COLLATE utf8_general_ci; grant all on metabase.* to 'metabase'@'%' identified by '123456';
【4】配置好連接數據庫的環境變量,由於我們是 jar 啟動的,這個服務會默認去先讀取環境變量(在 /etc/profile 里面追加):
export MB_DB_TYPE=mysql export MB_DB_DBNAME=metabase export MB_DB_PORT=3306 export MB_DB_USER=metabase export MB_DB_PASS=123456 export MB_DB_HOST=192.168.10.204 export MB_JETTY_PORT=8000 export MB_JETTY_HOST=0.0.0.0
我這里指定了數據庫連接,已經服務啟動以后監聽的 IP 和端口,當然,數據庫那一部分可以簡寫:
export MB_DB_CONNECTION_URI="mysql://192.168.10.204:3306/metabase?user=metabase&password=123456&useSSL=false"
寫成 jdbc 的樣式,這樣我們可以指定 SSL 為 false,否則日志有點惡心。
記得讓新增的環境變量生效:
source /etc/profile
【5】生效之后,我們就按照網上的方法開始同步,這也是問題開始的地方:
/opt/jdk1.8.0_45/bin/java -jar metabase.jar load-from-h2 ./metabase.db
我們 jdk 是沒有配置環境變量的,所有用的是絕對路徑,你們可以根據自己修改。一切就這樣往美滋滋的方向發展,MySQL 里面也已經開始創建新的表了。
正當一切過的美滋滋,准備搞完就休息的時候,不幸的事情發生了:
為了方便需要的兄弟更容易檢索這篇文章,我這里把錯誤貼出來:
Transfering 2224 instances of FieldValues...........[OK] Transfering 721 instances of Revision......BatchUpdateException: Message: Data truncation: Data too long for column 'object' at row 1 SQLState: 22001 Error Code: 1406 java.sql.BatchUpdateException: Data truncation: Data too long for column 'object' at row 1
提示數據過長,字段長度不夠,導致數據傳輸報異常,傳輸終止。於是我在這個問題上面卡了至少兩個小時,各種搜索文檔,找 issue,都沒有解決。可能是我英語太爛。
最后還是回歸到報錯本身,既然長度不夠,那我加長度唄,但是我下次同步會不會又把我的表干掉重新建立呢?最終抱着試一試的態度,我去修改表的字段。
問題又來了,那這報錯的表是哪一個呢?我們只知道字段啊。給大家推薦一個方法,遇到這種問題,我們完全可以把表結構導出來,然后去搜索指定的列。
最終,在 revision 表中找到了這個字段,此時再看報錯:Transfering 721 instances of Revision......BatchUpdateException:,這讓我們更加確定就是這個字段。
一看他的類型 text,於是我們將它改成 longtext。
再次執行之前的命令同步,后面還會有幾個字段出現類似的報錯,類似 report_card 這些表,只需要再度修改為 longtext 類型即可。這里就不再贅述。
【6】同步完成以后只需要啟動服務即可使用以 MySQL 作為數據庫的 Metabase 了。
這里附帶一個我的 jar 服務啟動腳本,可以方便我們管理這種單個服務:
#!/bin/bash ################################################################# # 作者:Dylan <1214966109@qq.com> # 時間:2018-03-29 # 用途:Metabase 啟動管理 ################################################################# if [ -f /etc/init.d/functions ]; then . /etc/init.d/functions fi ################################################################# # 定義變量 ################################################################# SERVICE_NAME='metabase' SERVICE_PACKAGE="${SERVICE_NAME}.jar" SERVICE_PATH='/opt/METABASE' LOG_PATH="${SERVICE_PATH}/logs" JAVA_CMD='/opt/jdk1.8.0_45/bin/java' ################################################################# # 判斷日志目錄 ################################################################# if [[ ! -d ${LOG_PATH} ]]; then mkdir -p ${LOG_PATH} fi ################################################################# # 定義命令 ################################################################# function START_COMMAND() { ${JAVA_CMD} -Duser.timezone=Asia/Shanghai -Xms4g -Xmx4g -jar ${SERVICE_PATH}/${SERVICE_PACKAGE} >> ${LOG_PATH}/${SERVICE_NAME}.log & if [[ $? -eq 0 ]]; then action "${SERVICE_NAME} start successed" /bin/true else action "${SERVICE_NAME} start failed" /bin/false fi } function STOP_COMMAND() { SERVICE_PID=`ps -ef | grep "${SERVICE_PACKAGE}" | grep -v 'grep' | awk '{print $2}'` if [[ ${SERVICE_PID} == '' ]]; then action "${SERVICE_NAME} is not running" /bin/false else kill -9 ${SERVICE_PID} >/dev/null 2>&1 if [[ $? -eq 0 ]]; then action "${SERVICE_NAME} stop successed" /bin/true else action "${SERVICE_NAME} stop failed" /bin/false fi fi } function STATUS_COMMAND() { SERVICE_PID=`ps -ef | grep "${SERVICE_PACKAGE}" | grep -v 'grep' | awk '{print $2}'` if [[ ${SERVICE_PID} == '' ]]; then action "${SERVICE_NAME} is not running" /bin/false else action "${SERVICE_NAME} is running" /bin/true fi } ################################################################# # 定義命令 ################################################################# case "$1" in start) START_COMMAND ;; stop) STOP_COMMAND ;; restart|reload) STOP_COMMAND START_COMMAND ;; status) STATUS_COMMAND ;; *) echo "Usage: $0 {start|stop|restart|status|reload}" ;; esac
小結
H2 遷移到 MySQL 出現問題可能大多都是字段的類型導致遷移失敗,另外我們在遷移的時候也可能會出現:
java.lang.IllegalArgumentException: No matching clause: :h2
這樣的報錯,這說明是環境變量的問題。
如果還有其它遷移問題,也可以留言或者加我 QQ 大家討論一下,如果你覺得這個還 OK,推薦 走一波~
另外,如果你喜歡我這博客園主題,在我博客首頁置頂文章有相關說明~