POLARDB · 最佳實踐 · POLARDB不得不知道的祕密(二)

前言mysql

POLARDB For MySQL(下文簡稱POLARDB)目前是阿里雲數據庫團隊主推的關係型數據庫。線上已經有不少企業用戶在使用而且穩定運行了好久。固然,因爲POLARDB是爲雲上環境專門打造的數據庫,與原生的官方MySQL相比,有一些須要注意的事項。前幾個月的月報介紹了一些,詳見這篇[月報](http://mysql.taobao.org/monthly/2018/10/01/),結合筆者最近幾個月一線的開發和運維經驗,總結出如下幾點新的注意事項並給出了建議。sql

 

空表/空實例空間問題數據庫

因爲POLARDB除了實例費用外,用戶還須要支付實例佔用的存儲費用,而且是按照使用量來收費,即當前使用多少磁盤就付多少錢。這一點與RDS MySQL兼容版的預付費模式不太同樣,因此不少用戶對磁盤使用量很是敏感,除了上篇月報中提到的空間問題外,還有如下兩類問題:空實例空間問題和空表空間問題。緩存

空實例空間問題。經常有用戶會問,我剛買了一個POLARDB實例,可是纔剛建立完,空間就佔用了將近3GB(實際是2.8G左右),這是啥東西?個人磁盤被什麼東西佔用了?這裏解釋一下一個空實例大概有哪些文件以及他們佔用的磁盤大小。安全

* 系統表ibdata1文件。能夠查看系統變量`innodb_data_file_path`,ibdata默認大小就是200M,即在初始化後,ibdata就佔用了200M空間,後續會按需自動擴展。
* MySQL系統庫。目前權限信息,表的元信息等都放在MySQL庫下,因爲空表的空間佔用問題(下一小節介紹),將近60個文件,佔了230M左右的空間。
* Redolog文件。默認有兩個,每一個1G(Redolog也是預分配空間),其中一個是當前正在用的日誌文件,另一個是爲了提升性能而提早分配的redolog,主要是爲了減小Redolog切換時候的性能抖動。
* Undo文件。默認有8個,每一個10M。Undo空間能夠放在ibdata裏面,也能夠挪出來(ibdata裏面只留一個),POLARDB默認是把undo空間挪出來以獨立文件的形式存在,主要是爲了方便後續清理。
* Performance_schema表空間。雖然目前POLARDB 5.6兼容版本,不太建議使用Performance_schema,可是咱們仍是在編譯的時候把相關的功能給加上了,這就致使在初始化時候就會把Performance_schema相關的表空間給初始化好,佔用了一部分空間,因爲空表的空間佔用問題(下一小節介紹),50多個文件,佔了210M左右的空間。
* auto.cnf文件,存放server uuid。因爲空表的空間佔用問題(下一小節介紹),佔用4M。
* ib_checkpoint文件,存放checkpoint信息。由於Redolog是相似binlog順序遞增的,因此第一個ib_logfile可能被刪掉,因此checkpoint信息不能放在那裏。因爲空表的空間佔用問題(下一小節介紹),佔用4M。
* innodb_repl.info,存放物理複製相關的信息。主要是POLARDB數據庫內部使用,記錄複製位點,切換信息等。因爲空表的空間佔用問題(下一小節介紹),佔用4M。session

綜上所述,空實例的主要空間是被Redolog給佔用了,固然這個也是爲了性能考慮。每一個日誌文件大小1G,能在大多數場景下保證明例正常運行。隨着DML的執行,Redolog會被使用,使用完後會上傳OSS,以便恢復到時間點任務使用。多線程

空表空間問題。這個問題也經常被用戶提起,我建立了不少表,可是數據還沒導入,爲啥空間增加那麼快,差很少一千張空表就佔用了40G的空間。這個問題的主要緣由是POLARDB底層使用了自研的文件系統PolarFS,爲了提升性能,默認的文件塊被設置爲4M(Ext4文件系統這個值爲4K),換句話說,因爲一個文件至少佔用一個塊,因此文件大小最小爲4M,而在InnoDB上,一張普通的表默認有兩個文件,一個是FRM文件,一個是IBD文件,因此只要一張表成功建立,就會佔用8M的空間。固然,這些空間能夠理解爲提早分配預留的空間,當後續數據被寫入的時候,首先先使用這些預留的空間,只有被用完後,纔會再分配空間。這個行爲對大多數用戶來講影響不大,但對某些須要提早建立大量表可是數據量不大的用戶來講,影響比較大,會致使用戶存儲成本較高。不過幸運的是,針對這點,咱們的文件系統已經作了相應的優化,目前在內部測試階段,達到預約的穩定性要求好,咱們會盡快發佈到線上,目標是,在保證高性能和穩定性的狀況下,儘量的減小磁盤空間使用量。架構


複製延遲問題
主備數據庫的複製延遲是一個老生常談的問題,在傳統的主備架構下,只要主要壓力稍微大一點或者作了一個DDL,備庫有很大機率的發生延遲。發生延遲後,不只會影響應用從備庫讀取數據的正確性,也影響主備切換。因爲POLARDB在架構上的優點(只有一份數據),所以大部分用戶可能會誤認爲在POLARDB上理論上不該該發生延遲。由於主備都讀取一份數據,固然都應該看到一致的數據啦。可是實際上,複製延遲也仍是有的,由於雖然磁盤上的狀態一致了,可是內存上的狀態不必定一致。在POLARDB上,主庫和只讀庫經過物理複製來同步內存中的狀態,因爲同步的數據比較少,所以發生複製延遲的機率相比傳統的MySQL複製仍是小不少的。接下來簡單介紹一下複製的過程:運維

Primary節點會按期告訴Replica節點,可安全讀取的日誌位點上限,Replica在這個週期內,能夠安全讀取到這個位點如下的日誌,若是超過這個位點,可能會讀到Primary節點正在寫的日誌。Replica節點按期反饋應用日誌的位點,表示本身應用到的日誌位點,小於這個位點的必定已經應用完,大於這個的可能還沒應用或者正在應用。Primary節點當前寫到的日誌位點和Replica節點應用到的位點之差即爲複製延遲,若是複製延遲很大,就會致使Replica跟不上Primary。工具

另外,在POLARDB上,全部主庫上執行完的DDL都要等全部Replica應用完相應日誌後才能返回成功。換句話說,若是Replica有很大的複製延遲,可能會致使主庫執行DDL不成功。這一點能夠詳見上一篇月報中的「DDL與大事務」小節。

由此可看,咱們要儘量的減少複製延遲。物理複製有兩個階段,一個是日誌解析的階段,另一個是日誌應用的階段。任何一個階段慢了,均可能致使複製延遲。日誌解析,目前是單線程解析,在咱們測試狀況下,只有當寫入量超過每秒20W(最大規格)的狀況下,解析線程纔會成爲瓶頸。日誌應用階段,因爲應用比較慢,目前是多線程應用,不過在POLARDB中,咱們只須要應用在內存中的數據頁便可,換句話說,若是日誌涉及的數據頁不在內存中,咱們就不須要應用這些日誌(目前的方案是把這些日誌存在內存中),直到這些數據頁被讀入內存,咱們在IO線程中把這些拉下的日誌都應用掉。

用戶能夠在只讀節點上查詢`Innodb_replication_delay`這個status變量來獲取當前複製延遲。若是複製延遲比較大而且有不斷增大的趨勢,能夠調大參數`loose_innodb_slave_recv_hash_cells_max`和`loose_innodb_slave_recv_hash_cells_min`來減小延遲。這個參數的主要做用就是增長日誌hash桶的數量,從而減小日誌查找時候的開銷。另外,咱們的Proxy支持Session一致讀,即同一個session內的讀和寫保證是邏輯相關的,在寫以後當即讀,必定會讀到最新的數據(只有因爲讀寫分離,會把讀請求發到有延遲的只讀節點,從而致使讀取到歷史版本的數據)。

 

內存問題
有部分用戶發現,相比RDS MySQL兼容版,POLARDB的內存使用量會更多,這裏須要說明一下,這裏的主要緣由是咱們在不少地方使用了以空間換時間的方法,因此內存使用量上會有必定的上升。若是用戶發現內存佔用過多,能夠從如下幾個方面診斷:

* 調小`table_open_cache`,同時使用`flush tables`命令關閉全部表空間。這招對打開表數量不少且用戶鏈接不少的用戶來講,效果比較明顯。
* 關閉自適應哈希。`innodb_adaptive_hash_index`,這個功能可能會佔用不少的內存,可是在如今的SSD磁盤下,性能提高有限。
* 適當的調小buffer pool。這點比較適用於鏈接數多,同時又不少複雜查詢的用戶。不過目前調整Buffer pool須要聯繫售後。

大部分用戶的實例,在內存上漲到必定數量後,會中止上漲,這種狀況下,即便內存佔比比較高,也不用擔憂,由於咱們是儘量的使用內存,把內存儘量的都用起來,緩存數據,提升效率。可是若是發現實例內存不斷上漲,而後直到OOM,這種狀況,請馬上聯繫咱們,咱們會幫您在後臺開啓一個內存監控工具(依賴Jemalloc profiling工具,可是須要重啓數據庫),能夠用來發現這些內存去哪兒了,究竟是您使用的問題,仍是內存泄露問題,若是是咱們的問題,咱們會盡快解決並給與必定的補償,若是是您使用的問題,咱們也會給您指出,給出優化的建議等。

在後續的POLARDB版本上,咱們會增長更多的內存監控功能,方便用戶自行進行排查。

 

IOPS問題

目前POLARDB的每種規格的實例,都有IOPS限制。同時,RDS MySQL的實例也有IOPS限制。每每有不少用戶把這個兩個IOPS作比較,其實意義不大。

在RDS中,這個IOPS是指數據文件(後臺刷髒線程觸發)的寫盤次數,日誌文件每秒的寫盤次數(即主要是Redolog和Binlog加起來的寫盤次數限制)是不統計在裏面的。可是在POLARDB中,這個IOPS限制不但包括了日誌文件的寫盤次數限制,也包括了數據文件的寫盤限制,即二者加起來每秒寫盤的次數不能超過這個值。數據和日誌一塊兒限制,一塊兒隔離,這樣更加合理,也減小了由於磁盤壓力而產生的性能抖動。

所以,咱們在設置同一類型的規格IOPS參數時,POLARDB上的IOPS通常都比RDS上大好幾倍。多出來的IOPS主要是給日誌文件刷盤預留的。

目前臨時表的磁盤仍是普通的NVME本地磁盤,沒有放在自研的磁盤上,所以臨時表的IOPS暫時不計入總的IOPS,而RDS上這一部分是放在數據盤上,因此這部分IO會記錄到IOPS限制上。同時,咱們在MySQL內核代碼中,也有部分限制,主要是爲了防止某些用戶臨時表使用過多從而影響了其餘用戶。

錯誤日誌,審計日誌,慢日誌的寫盤操做一樣在本地盤,沒有計入IOPS限制。

另外,咱們在IO帶寬上,目前尚未硬的限制(目前POLARDB的實例達不到自研存儲的帶寬上線),可是很快,爲了資源隔離的更加完全,咱們也會加上IO帶寬的限制和隔離。

 

升級問題
因爲POLARDB是阿里雲自研的關係數據庫產品,咱們在上面不但開發了數據庫系統,還開發了一套對應的文件系統和塊存儲系統。很多用戶對咱們的指望很高,也提出了許多優化建議,所以POLARDB的系統升級頻率會比RDS家族的產品高。一方面,咱們須要修復一些極端狀況下會被觸發的BUG,另一方面,咱們須要知足用戶形形色色的需求。固然,咱們的系統升級都是熱升級,咱們竭盡所能儘量減小對用戶的影響,例如在系統升級時期的性能抖動時間,數據庫不可服務時間等等。若是系統要升級,咱們會提早給用戶發短信/郵件以及大客戶的電話通知,通常系統升級都在凌晨用戶設定的可運維時間,正常的升級流程可能會形成秒級的服務中斷,客戶只須要在應用端保證能重連數據庫便可。若是那天晚上,升級不太方便,請儘快提工單給咱們,咱們再約其餘時間。咱們後臺也在開發一套主動運維繫統,有了這套系統以後,用戶就能夠在控制檯上在指定的時間點內主動升級數據庫,同時不一樣版本的數據庫也會有詳盡的releasenote,便於用戶按需升級。

 

總結
這篇文件簡單解答了幾個用戶經常問到的問題。但願對你們有所幫助。

最後,歡迎使用POLARDB。

相關文章
相關標籤/搜索