公司早期主要用mysql5.5這個版本,今年我們把資料庫配置中心搭建起來,主要推的是mysql5.6這個版本,效能和功能上都有了一定的提升,mysql5.6也能支援gtid,但是無法在線在gtid模式與普通模式之間切換,同時5.6的同步性能還是無法讓人滿意,只能做到在多個db的情況啟動並行複製,業務上很難有這樣的保證,所以一旦寫入操作密集的業務,同步慢就會是個嚴重的問題;
所以,最近一直在考慮升級MySQL,升級MySQL首先面臨的一個問題就是選一個合適的版本,首先我們考慮是的採用mysql5.7,5.7今年已經連續發了多個正式版本了,目前使用範圍也比較廣,可以考慮在正式環境使用了。於是我們進行了線上比較測試,發現mysql5.7與我們線上的mysql5.6版本的效能有較大的差距(也許還是有些參數沒有調好的原因,5.7確實要複雜很多)。
與此同時,最近公司頻繁出現一些日誌性存儲,大多數都是採用innodb引擎,容量非常浪費,另一方面由於我們公司的標準mysql伺服器容量是1.3T左右,對於一些大容量需求的業務來說,容量上也存在瓶頸,如果要保留長時間的資料就難以滿足需求了。所以藉此機會我們打算把這塊一起考慮進去,目前Percona和Mariadb都支援Tokudb,Mariadb 10.2還是10.3也準備支援Myrocks了。
於是決定比較試一下,選擇了Percona 5.7.14、Mariadb 10.1.18與我們線上的MySQL 5.6進行了對比測試,經過壓測。
首先是都使用Innodb引擎的情況:
Mariadb與MySQL5.6測試結果接近
Percona 5.7.14與官方MySQL5.7的效能結果差不多,比起MySQL5.6有一定的差距(去掉performance_schema好一點,但也有落差)。
採用Tokudb引擎測試的結果與官方聲稱的有差距,使用snappy壓縮的情況下,insert比innodb約慢1/4,update只有innodb的一半左右。 Percona性能更差,就不考慮了。
最終選型Mariadb 10.1.18,並且在線上部署了一個業務,透過這個業務慢慢試用以後,逐步推廣開來。
在使用Mariadb的過程中,碰到了不少問題,這裡主要提一下我碰到的兩個較大的問題,供大家參考:
1、同步效能問題:
我們上的這個業務高峰期達到了9000多寫作業/秒,首先面臨的第一個問題就是同步效能跟不上,slave同步線程數加到了16個線程,勉強能追上,但是一旦資料庫從庫停一會,就有可能面臨永遠最不上的可能。當快絕望的時候,看了一下mariadb的官方文章(https://mariadb.com/kb/en/mariadb/parallel-replication/),Mariadb的並行複製支援好幾種模式,其中有in-order和out-of-order兩種,不過我們這個業務支援in-order,所以沒考慮out-of-order,在in-order模式下,又支援兩種:Conservative 和Optimistic,缺省情況下Conservative ,這種並行模式會嚴格保證事物的順序性,估計和5.7的group commit原理差不多;而Optimistic模式下,複製的時候會盡量啟動更多的會話,直到發現衝突時才會去處理衝突。果斷試了一下Optimistic,非常強勁,最高同步速度達到了14000次/秒。
2、"記憶體外洩"
系統部署結構為:兩個Mariadb做成主主複製,在前面部署了一個自己開發的分散式資料庫,業務方連接到分散式資料庫進程。系統上線了幾天,發現主庫會莫名其妙的掛掉,好在有分散式資料庫,並且會自動切換,Mariadb主庫掛了,會自動切到另外一個主庫上,業務方沒有感知。查看內核日誌,發現是OOM了,內核把MySQL殺掉了。
於是開始了各種嘗試,去掉Tokudb引擎配置,換Mariadb 10.1.19 ,都嘗試過,最後都會發生主函式庫掛掉的事情。一次偶然的機會,我把主庫上的slave停掉了,發現主庫的內存突然下降好多,並且內存不再增加了,但是一旦把主庫上的slave啟動就會發現,內存又逐漸身高。這個現像很像mysql線程內的記憶體分配機製造成的(基於mem_root的記憶體分配,線程停掉會全部釋放),所以初步懷疑是這個原因造成的。發現身為雙主中的另外一個Mariadb,就不會出現記憶體上升的問題。
發現上面的現像以後,就開始程式碼上的偵錯,用gdb啟動一個mariadb,另外一個用普通指令啟動,這兩個函式庫做成雙主:
第一種情況:測試作為從庫的時候,接收到的binlog事件情況
在普通命令啟動的mariadb上插入一行數據,gdb查看接收到的事件的順序如下:
### i ) Gtid_log_event ### ii) Table_map_log_event ### iii) Write_rows_log_event ### iv) Xid_log_event
第第二種情況:測試作為主庫的時候,接收到的binlog事件
在gdb启动的mariadb上插入一行记录,然后gdb观察接收到的事件为:
### 1)Rotate_log_event ### 2)Gtid_list_log_event ### 3)Rotate_log_event
Rotate_log_event事件是虚拟出来的,用于让主库跟上从库的同步位置,这基本上是一个空事件,没有做任何处理,所以初步怀疑是在处理Gtid_list_log_event事件的时候,出现了问题。
反复查看Gtid_list_log_event::do_appy_event函数中的调用情况,发现确实有些方法会调用thd->alloc来分配内存,但是没有回收,所以造成内存不断的增大,我考虑了一下,因为是主库对于同步性能要求也不高,所以在Gtid_list_log_event::do_apply_event函数的最后加了一行代码:free_root(thd->mem_root, MYF(MY_KEEP_PREALLOC)); 重新编译后,跑了一天,内存终于稳定了。
由于目前发现只有主库有该事件,主库同步处理性能要求不高,所以暂时先这样用着了。不知道mariadb官方版本什么时候会优化一下。
总体来看,Mariadb还是比较适合我们公司的,它有最新的功能、特性能够给我们提供很多解决方案。Tokudb可以解决日志型存储的问题;连接池可以解决大量连接情况下性能地下的问题;审计插件提供安全方面的审核;slave并发模式能够提供高性能的复制能力。除了这些常见功能以外,Mariadb还提供了Cassandra插件、图数据库插件等等,这些都给我们给业务的服务增加了想象力。
【相关推荐】
2. MySQL最新手册教程
3. 数据库设计那些事
以上是分享使用Mariadb時碰到的兩個問題的詳細內容。更多資訊請關注PHP中文網其他相關文章!