MySQL官方Docker鏡像的數據存儲問題
【編者的話】本文主要介紹在使用MySQL鏡像時遇到的一個實際問題,以及整個問題的解決過程。同時,該標題並不恰當,並非是MySQL官方鏡像的數據存儲方式有問題,而是想表達這樣一種思想,由於其特殊的存儲方式,不符合我們的使用場景,引起了我們在實際的類生產環境中遇到的問題。
問題起因:
MySQL官方鏡像的Dockerfile中,有這麼一條設置,即用了VOLUME這個關鍵字,同時後面設置了一個路徑,/var/lib/mysql,這個路徑是用來存儲資料庫的各種表的數據的。
那麼,這一條設置會起到什麼作用呢??
Docker官方文檔對VOLUME這個關鍵詞做了解釋,這個路徑下的數據或者修改,再重新commit一個新的鏡像時,該路徑下的所有變化都會被discard,即所有的修改都會被拋棄,不會被保存到新鏡像中。(詳見官方文檔)
那我們如果想把一些基礎數據在docker run的時候,不用重新導入基礎數據就能直接使用呢??(docker run很快,但是導入數據需要時間,兩個表大概需要二十分鐘,太影響效率!)
有兩種方法:
1、映射方法。在主機上創建不同的目錄(每個人建一個自己的目錄,拷貝一份基礎數據,這樣互不影響,各寫各的),在docker run的時候使用-v參數將宿主機上的目錄映射到容器里的/var/lib/mysql。
2、拷貝方法。既然/var/lib/mysql這個目錄被VOLUME關鍵詞給限制了,我們就先把數據拷貝到容器里的其他目錄,比如根目錄,然後修改docker run的啟動文件(姑且稱為啟動文件,各種軟體的docker鏡像都會有一個啟動腳本,在docker run的時候執行,做一些初始配置、拉起服務的進程),增加這樣一個邏輯:將我們拷貝到鏡像根目錄中的基礎數據拷貝或者移動到/var/lib/mysql目錄下,比如cp -r /mysql-basic-data /var/lib/mysql,這樣,我們的目的就達到了。
我們採用的第二種解決方法。
一些實際操作的問題:
1、如何從宿主機拷貝數據到容器中?
有個命令叫docker cp xxx 容器id:xxx
當然也能從容器中拷貝到宿主機上:
docker cp 容器id:xxx xxx
還有一種場景會用到——很多容器里不能使用vi或者vim編輯文件的,那麼你可以先拷貝到宿主機上,編輯修改保存,再拷貝回去。
2、區分Dockerfile和docker run的啟動腳本
Dockerfile是在docker build的時候執行命的,而啟動腳本是在docker run的時候執行的,注意區分其執行場景和時機!!
3、MySQL 5.6版本官方鏡像大小300+M,我們的數據大概300M,但是新的鏡像竟然達到了900+M大小,為什麼??
具體要看docker存儲原理!!
這裡簡單介紹一下,Docker使用的是聯合文件系統(AUFS,網上介紹很多),這個文件系統大概的原理是這樣的(Docker鏡像的存儲原理),關鍵一點是它是分層的,層層迭加,底層都是只讀層,最上層可以修改,每次修改它都會把你的修改重新從底層拷貝一份到最上層,即使你只有一份數據,AUFS也會把它搞成兩份數據,空間就會成倍增加。
同事給我舉了一個例子,即使你在容器里執行一條chown命令,鏡像的大小增加200M都是可能的!!
4、MySQL官方鏡像是區分大小寫的
這個大小寫包括資料庫表的命名,比如你的資料庫中有個dms.quertz_trigger,而你要連接的卻是大寫的dms.QUERTZ_TRIGGER(上層通過Driver,ORM比如Hibernate、Mybatis等),此時會報錯「xxx is not exsit」。(此時你不要驚訝,也不要氣餒,更不要抱怨「資料庫中明明是有這個表的嘛」,只需要耐心看下面的解決方法)
解決:修改鏡像中的/etc/mysql/my.cnf文件,在末尾加一行lower_case_table_names=1。(還有一個參數lower_case_file_system如果用到需要注意一下)
docker commit 容器id xxx:xxtag(將修改提交保存為一個鏡像),用新鏡像,搞定!
5、關於MySQL欄位值的大小寫敏感問題
欄位值的大小寫由Mysql的collate來控制。可以理解為,跟具體的字符集有關,比如 utf8字符集:
utf8_general_ci,表示不區分大小寫,這個是utf8字符集默認的collate;
utf8_general_cs,表示區分大小寫;
utf8_bin表示二進位比較,同樣也區分大小寫。
圖片來自第七城市「MySQL in Docker with Java Hibernate」:http://www.th7.cn/Program/java/201509/573373.shtml
TAG:你還是喜歡做技術 |