解憂雜貨店:關於MySQL 5.7的188個精彩問答
編者按
為方便大家對MySQL 5.7的認識和學習,社群眾譯者傾力翻譯了MySQL 5.7 FAQ文檔,以解答大家在使用過程中的各種困惑。
由於篇幅過大,本文將摘錄部分精華,需要完整版的同學請務必點擊文末的鏈接或回複“FAQ”到DBAplus社群訂閱號下載珍藏~
文中部分內容涉及MySQL 5.7官方用戶手冊(以下簡稱“手冊”),建議在閱讀本文同時,登陸:https://dev.mysql.com/doc/refman/5.7/en/ 配合參考食用,效果更佳~而下載了完整版的同學則可直接點擊超鏈接跳轉至相應頁麵查看。
MySQL 5.7 FAQ目錄一覽
一、一般問題
二、存儲引擎
三、SQL服務器模式
四、存儲過程與函數
五、觸發器
六、視圖
七、INFORMATION_SCHEMA
八、Migration遷移
九、Security安全
十、MySQL Cluster
十一、中文、日文和朝鮮語字符集
十二、連接器和APIs
十三、複製
十四、MySQL企業線程池
十五、InnoDB變更緩衝區
十六、InnoDB表空間加密
十七、虛擬化支持
共計188個問答
精華摘錄
Part 1 MySQL Cluster
1、哪個版本的MySQL軟件支持NDB Cluster?我是否不得不使用源碼編譯?
在標準的MySQL Server5.7版本中NDB Cluster是不支持的。然而,MySQL NDB Cluster是作為一個單獨的產品來提供。目前,生產環境以下NDB Cluster版本序列可用:
-
NDB Cluster 7.2. 這個序列是NDB Cluster之前的一個通用版本,盡管我們推薦新部署采用NDB Cluster7.5的版本,目前來說,還是可以用於生產。最近的NDB Cluster 7.2版本可從https://dev.mysql.com/downloads/cluster/獲得。
-
NDB Cluster 7.3. 這個序列是NDB Cluster之前的一個通用版本,盡管我們推薦新部署采用NDB Cluster7.5的版本,目前來說,還是可以用於生產。最近的NDB Cluster 7.3版本可以從https://dev.mysql.com/downloads/cluster/獲得。
-
NDB Cluster 7.4. 這個序列是NDB Cluster最新的通用版本,它是基於NDB 7.4版本的存儲引擎和MySQL5.6,盡管我們推薦新部署采用NDB Cluster7.5的版本,目前來說,還是可以用於生產。最近的NDB Cluster 7.4版本可以從https://dev.mysql.com/downloads/cluster/獲得。
-
NDB Cluster 7.5. 這個序列是NDB Cluster最新的通用版本,它是基於NDB 7.5版本的存儲引擎和MySQL5.7. NDB Cluster 7.5可用作生產。在這個序列中,生產新部署建議采用NDB Cluster7.5的版本。當前的版本是NDB Cluster7.5.5。最近的NDB Cluster 7.5版本可以從https://dev.mysql.com/downloads/cluster/獲得。
任何新環境的部署,你應該使用NDB Cluster 7.5。如果你使用的是NDB Cluster的老版本,你應該盡可能快地升級到這個版本。(為了對NDB Cluster 7.5中的一些改進有大致了解,請看手冊21.1.4節“MySQL NDB Cluster7.5有什麼新功能”)
你可以使用以下命令來檢查你的MySQL Server是否支持NDB:
SHOW VARIABLES LIKE 'have_%', SHOW ENGINES, 或SHOW PLUGINS。
2、我需要什麼特殊的網絡來運行NDB Cluster嗎?集群中的計算機如何通訊?
NDB集群的目的是用於在高帶寬環境中,計算機使用TCP / IP連接。其性能直接取決於集群計算機之間的連接速度。NDB集群最小連接要求包括典型的100Mb以太網網絡或相當的網絡。隻要可用,我們建議你使用千兆以太網。
3、為了運行NDB Cluster我需要多少計算機,為什麼?
一個可行的集群至少需要3台計算機。然而,一個NDB Cluster推薦的最小計算機數是4:管理節點和SQL節點各需要一個節點,另外兩台計算機用作數據節點。設計兩個數據節點的目的是為了提供冗餘。管理節點必須運行在一個獨立的機器上,萬一某個數據節點故障,可以保證提供持續的仲裁服務。
為了提高吞吐量和高可用性,你應該使用多個SQL節點(連接到集群的MySQL服務器)。運行多個管理服務器也是可能的(雖然不是嚴格必要的)。
4、使用NDB Cluster需要多少RAM?完全使用磁盤內存是否可行?
以前NDB集群隻是運行在內存中。MySQL 5.1和以後還提供將NDB集群存儲在磁盤上的能力。(注意,我們沒有計劃將這種能力移植到以前版本)參見手冊21.5.13節“NDB集群磁盤數據表”,以獲取更多信息。
對於內存中的NDB表,你可以使用以下公式計算集群中的每個數據節點大致需要的內存的估計值:
(SizeofDatabase × NumberOfReplicas × 1.1 ) / NumberOfDataNodes
計算更準確的內存需求需要有些限定條件,對於集群數據庫中的每個表,每一行所需的存儲空間(詳情參見手冊12.8節,“數據類型存儲需求”)乘以行數。就像以下列出的,你也必須記住計算任何列索引的內存占用:
-
NDB Cluster表上創建每個主鍵或哈希索引需要21-25字節/記錄。這些索引使用IndexMemory。
-
每個排序的索引需要10字節/記錄,占用的是DataMemory。
-
創建的主鍵或唯一索引會同時創建一個排序的索引,除非創建索引時指定使用HASH。換句話說:
1)集群表的主鍵或唯一索引通常每條記錄占用31到35個字節。
2)然而,如果使用HASH來創建主鍵或唯一索引,那麼每條記錄隻需要21到25個字節。
在NDB Cluster表創建過程中,對於所有的主鍵和唯一索引,通常使用HASH的方式比不使用HASH的方式會讓更新會快很多,在一些情況下,甚至會快20%到30%。這是因為需要更少的內存(因為不會創建排序的索引),同時使用的CPU也更少(因為需要讀和可能更新的索引更少)。然而,這也意味著使用範圍掃描的查詢需要通過其它方式來滿足,否則會導致選擇變慢。
當計算集群內存需求, 在最近的MySQL 5.7版本,您可能會發現一個叫ndb_size.pl的工具可用。這個Perl腳本連接到當前的(非集群)MySQL數據庫,並創建一個關於“如果使用NDBCLUSTER存儲引擎,這個數據庫需要多少空間”的報告。有關更多信息,請參見手冊21.4.25節,“ndb_size.pl - NDBCLUSTER大小需求估計量”。
尤為重要的是,要記住,每一個NDB集群表必須有一個主鍵。如果一個都沒有定義,NDB存儲引擎會自動創建一個主鍵,並且這個自動創建的主鍵不使用HASH。
在特定的時間,通過使用ndb_mgm客戶端的REPORT MEMORYUSAGE命令,您可以確定有多少內存被用於存儲NDB集群數據和索引,參見手冊21.5.2 “NDB集群管理客戶端命令”以獲取更多信息。此外,當DataMemory或IndexMemory使用的內存達到80%,就會有警告寫到集群日誌,同樣,當使用達到85%,90%等就會再次寫入告警日誌。
5、我能在虛擬機(比如通過VMWare、Parallels或 Xen創建的虛擬機)運行NDB Cluster節點嗎?
從NDB Cluster 7.2開始,NDB Cluster就支持使用虛擬機。我們目前支持和測試使用Oracle VM。
一些NDB集群用戶已經成功使用其它虛擬化產品部署NDB集群;在這種情況下,Oracle可以提供NDB集群支持,但特定於虛擬環境問題必須提到產品的供應商。
6、我嚐試遷移到一個NDB Cluster數據庫。裝載過程過早結束並且我收到了如下錯誤信息:ERROR 1114: The table 'my_cluster_table' is full,為什麼會發生?
原因很可能是你的設置並沒有為所有表數據和索引提供足夠的RAM,包括NDB存儲引擎所需的主鍵,以及為可能存在的表定義中不包括主鍵的表自動創建的主鍵。
同樣值得注意的是,所有數據節點應該有相同數量的內存,因為對於任何數據節點而言,集群中沒有數據節點可以使用比最少可用內存更多的內存。例如,如果有四台電腦作為集群數據節點,三個有3 GB內存可用來存儲集群數據,而另外一個數據節點隻有1 GB內存,然後每個數據節點可以投入最多1 GB用於 NDB集群數據和索引。
在某些情況下,即使ndb_mgm -e "ALL REPORT MEMORYUSAGE"顯示有大量空閑的DataMemory,MySQL客戶端應用程序中可能返回 “Table is full”的錯誤。你可以強製NDB為NDB集群表創建額外的分區,因此,對於使用MAX_ROWS選項創建的表的哈希索引就有更多的內存可用。一般來說,設置MAX_ROWS為你希望存儲表中行數的兩倍應該就夠了。
出於類似原因,有時你也可能遇到數據負載很高的數據節點的重啟問題。在NDB集群7.1及以後,增加的MinFreePct參數通過保留一定比例(默認5%)的DataMemory和IndexMemory來幫助解決重啟過程中的問題。這個保留內存不用於存儲NDB表或數據。
7、我怎樣導入一個已經存在的MySQL數據庫到一個NDB Cluster?
你可以像任何其它版本的MySQL一樣導入數據庫到NDB Cluster。除了在這個FAQ提到的限製外,唯一的特殊要求是包含在集群中的表必須是NDB存儲引擎。這意味著創建這些表必須使用ENGINE=NDB或ENGINE=NDBCLUSTER。
通過使用一個或多個ALTER TABLE語句,也可以將現有使用其它存儲引擎的表轉換成NDBCLUSTER存儲引擎。然而,在進行轉換之前,表的定義必須兼容NDBCLUSTER存儲引擎。在MySQL 5.7中,也需要一個額外的方法,參見手冊21.1.6“NDB集群的已知的限製”獲取詳細信息。
8、NDB Cluster支持IPV6嗎?
SQL節點(MySQL服務器)之間的連接是支持IPv6的,但是其它類型的NDB Cluster節點之間的連接必須使用IPv4。
實際上,這意味著你可以在NDB Cluster之間的複製使用IPv6,但是同一個NDB Cluster中節點的連接必須使用IPv4。更多信息,參見手冊21.6.3“NDB集群複製已知的問題”。
9、在一個有多個MySQL服務器的NDB Cluster中怎樣管理MySQL的用戶?
MySQL用戶賬號和權限通常不會在訪問同一個集群的不同MySQL服務器之間自動傳播。MySQL NDB Cluster 7.2及以後版本提供分布式的權限支持。然而權限分發並不會自動啟用,你可以依據MySQL NDB Cluster文檔提供的過程來激活這個功能。參見手冊21.5.15節“NDB Cluster的分布式MySQL權限”。
10、我怎樣備份和還原NDB Cluster?
你可以在NDB管理的客戶端和ndb_restore程序中使用NDB Cluster原生的備份和恢複功能。詳見手冊21.5.3“在線備份NDB Cluster”和“ndb_restore-還原一個NDB Cluster備份”。
你也可以使用mysqldump和MySQL Server為備份恢複提供的傳統功能。更多信息請見手冊5.5.4“mysqldump-數據庫的備份程序”。
Part 2 存儲過程與函數
1、MySQL 5.7支持存儲過程和函數嗎?
是的。MySQL 5.7支持兩種類型的存儲例程:存儲過程和存儲函數。
2、有沒有關於MySQL存儲過程的論壇?
有。參見https://forums.mysql.com/list.php?98
3、一個給定數據庫中,有辦法查詢所有的存儲過程和存儲函數嗎?
有的。比如給定的數據庫名為dbname,可以對INFORMATION_SCHEMA.ROUTINES 表上進行如下查詢:
SELECT ROUTINE_TYPE, ROUTINE_NAME FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_SCHEMA='dbname';
更多信息,參見手冊24.20節“INFORMATION_SCHEMA ROUTINES 表”。
對於存儲例程內包體的查詢,可通過SHOW CREATE FUNCTION(對於存儲函數)和 SHOW CREATE PROCEDURE(對於存儲例程)語句來查詢。更多信息,參見手冊14.7.5.9節“查詢存儲過程定義”。
4、一個存儲過程能否訪問表?
可以。一個存儲過程可根據需要來對一張或多個表進行訪問。
5、能從MySQL 5.7的存儲例程中返回結果集嗎?
存儲過程可以,但存儲函數不可以。如果你在存儲過程中進行一般性查詢,其結果集會直接返回到客戶端。為此,你需要使用比MySQL 4.1或更高版本的客戶端/服務器端。這意味著需要使用MySQLi的擴展而不是舊的MySQL的擴展,比如在PHP程序中。
6、在複製時,存儲過程或函數的功能如何被執行?
MySQL會記錄存儲過程中的每個DML事件,並將其分解動作同步到備服務器中。存儲過程的具體調用執行將不會被同步。
存儲函數對數據的更改隻記錄為函數調用,而不記錄其帶來的操作事件。
7、有特殊安全需求的存儲過程或函數如何被複製?
是的。因為從屬服務器有權執行任何從主服務器讀取的二進製日誌,包括被複製的有特殊安全約束的存儲函數。如果複製或二進製日誌(為了基於時間點的恢複)記錄是正常的,DBA可以用兩種方式安全打開:
-
任何用戶想創建存儲函數必須被授予超級特權。
-
另外,DBA可以log_bin_trust_function_creators係統變量設置為1,這使得任何標準創建常規特權來創建存儲功能。
8、對複製存儲過程和函數的行為有什麼限製嗎?
不確定性(隨機)或存儲過程中基於時間的行為會導致不能正確地被複製。嵌入在存儲過程也可能不正確地複製。從本質上講,隨機產生的結果是無法預測、無法完全複製的。因此,同步到從庫的隨機動作可能和主庫不一致。聲明存儲函數為DETERMINISTIC或將係統變量log_bin_trust_function_creators設置為0將不允許random-valued操作調用。
此外,基於時間的行動不能複製到從數據庫上,因為這樣的行為在一個存儲過程的時機並不是通過複製使用的二進製日誌來再生的。它隻記錄DML事件和沒有時間限製的因素。
最後, 對於nontransactional表,因較多DML操作(如批量插入)發生的錯誤,可能會引起複製問題,這些問題會導致主庫中部分完成的變動在從數據庫中不會做任何變動。DML的功能模塊可對主庫中引起錯誤的動作中加上IGNORE,這樣同步到從數據庫中的動作,將會被忽略且不會引起錯誤。
9、上述的限製是否影響MySQL基於時間點的恢複功能?
對複製的影響與基於時間點恢複的影響相同。
10、如何彌補上述的局限性?
你可以選擇基於語句級的複製或基於行級的複製。先前複製的實現依賴基於語句級的二進製日誌。基於行的二進製日誌可解決前麵提到的局限性。
可以使用複製的混合模式(通過--binlog-format=mixed啟動服務)。通過這種混合,複製模式能智能地選擇是基於語句級的複製安全可用,還是基於行級的複製更適合。
更多信息,參見手冊18.2.1節“複製格式”。
Part 3 複製
1、備庫是否必須一直連接到主庫?
不是。備庫可以關掉或斷開幾小時甚至幾天,然後重新連接上並補上更新。例如,您可以通過撥號連接設置一個主/從關係,撥號連接隻是偶爾的和短時間的在線。這意味著,在任何給定的時間,備庫並不保證與主庫保持同步,除非你采取一些特殊的措施。
為了確保已經斷開連接的備庫可以繼續追趕(主庫),您不能從主庫刪除包含尚未複製到備庫信息的二進製日誌文件。異步複製隻有在備庫能夠繼續從上次讀取事件的點繼續閱讀二進製日誌才能工作。
2、為了啟用複製,我是否必須在主庫和備庫啟用網絡?
是的,必須在主庫和備庫上啟用網絡。如果沒有啟用網絡,備庫不能連接到主庫和傳輸二進製日誌。檢查主備服務器的配置文件都沒有啟用skip-networking選項。
3、設置雙向複製時,我應該注意哪些問題?
MySQL複製當前不支持任何保證在主備庫之間的分布式更新(跨服務器)的原子性的鎖定協議。換句話說,客戶端A對co-master 1進行更新,與此同時,在這個更新傳播到co-master2之前,客戶端B可以對co-master 2進行一個更新,這個(客戶端B的更新操作)使得客戶端A對co-master2的作用和對co-master1的作用存在變得不同的可能。
因此,當客戶端A對co-master2進行更新操作,即使來自co-master2的所有的更新都已經被傳播,它會產生與co-master1上不同的表。這意味著在一個雙向複製關係中,你不應該鏈接兩個服務器,除非你確信你的更新可以以任何順序發生並安全地執行,或者除非你在客戶端代碼以某種方法注意避免次序混亂的更新。
你也應該意識到雙向複製,考慮到更新實際上並不會提高很多性能(如果有的話)。就像隻有一台服務器那樣,每個服務器必須做相同數量的更新。唯一的區別,就是少一點鎖爭用,因為另一個服務器上更新,在一個slave線程中是串行的,甚至這個好處可能會被網絡延遲所抵消。
4、我如何使用複製來提高係統的性能?
設置一個主服務器,然後將所有的寫直接指向它。然後配置你的預算和機架空間允許的備庫,然後在主備庫之間分配讀請求。你也可以在備端使用--skip-innodb, --low-priority-updates和--delay-key-write=ALL選項來啟動備庫,從而獲得速度的提升。在這種情況下,備庫會使用非事務的MyISAM表替代InnoDB表來消除事務的開銷從而獲得更好的速度。
5、如何使用複製來提供冗餘或高可用?
如何實現冗餘是完全依賴於您的應用程序和環境。高可用性解決方案(用自動故障轉移)需要主動監測和自定義腳本或第三方工具提供從原來的MySQL服務器到備庫的故障轉移支持。
為了手工處理這個過程,您可以從失敗的主庫轉換到一個預先配置的備庫,可以通過改變應用程序跟新服務器交談,或通過調整MySQL服務器的DNS,從失敗的服務器到新服務器來實現。
更多信息和一些示例解決方案,請見手冊18.3.7節“故障切換過程中的主庫切換”。
Part 4 中文、日文和朝鮮語字符集
這組常見問題來源於MySQL的支持和開發團隊在處理許多詢問CJK(中文-日文-朝鮮語)相關問題的經驗。這裏隻做簡單呈現,具體請下載完整版閱讀。
1、從哪裏可以找到MySQL手冊的漢語,日語,和朝鮮語的翻譯?
MySQL 5.6日文的手冊可以從這裏下載: https://dev.mysql.com/doc/.
2、從哪裏可以獲得MySQL關於CJK和相關的問題的幫助?
下麵這些資源可用:
從https://wikis.oracle.com/display/mysql/List+of+MySQL+User+Groups可以找到MySQL用戶組的列表。
與字符集相關問題的特性請求,請看https://tinyurl.com/y6xcuf。
訪問MySQL字符集、排序、Unicode論壇。外語相關論壇,也可以訪問https://forums.mysql.com/.
Part 5 觸發器
1、MySQL 5.7支持語句級或行級的觸發器嗎?
是的。在MySQL 5.7中,觸發器是針對行級的。即觸發器在對插入、更新、刪除的行級操作時被觸發。但是,MySQL 5.7不支持FOR EACH STATEMENT。
2、一張表可以同時具有相同觸發事件和動作時間的多個觸發器嗎?
MySQL 5.7.2,對於一個給定的表有相同的觸發事件和動作時間,可以定義多個觸發器。例如,你可以為一張表創建兩個BEFORE UPDATE觸發器。默認情況下,有相同觸發事件和動作時間的觸發器會按被創建的順序所激活。對於相同觸發事件和動作時間的觸發器,可以在FOR EACH ROW後標注FOLLOWS 或 PRECEDES來影響觸發器的執行順序。使用FOLLOWS,新觸發器在已有觸發器之後激活。使用PRECEDES,新觸發器在已有觸發器之前激活。
3、觸發器能和複製模塊一起使用嗎?
可以。但是,複製的工作方式取決於使用的是MySQL各版本中均有的基於語句級傳統格式,還是MySQL 5.1中引入的基於行的複製格式。
當使用基於語句級的複製格式時,主庫中執行的語句將會同步到從數據庫中按語句執行。
當使用基於行級的複製,主數據庫中觸發器執行的語句會同步到到從數據庫,但不會在從數據庫上執行,而是將主庫中觸發器執行的改變同步到從數據庫中。有關更多信息,請參見手冊18.4.1.35節”複製和觸發器“。
4、觸發器在主庫中觸發的動作如何被同步到從數據庫?
同樣,這取決於是使用基於語句還是基於行級的複製。
基於語句的複製:
首先,在主庫中存在的觸發器將會在從數據庫重新創建。一旦完成,複製將其作為標準的DML語句參於複製工作。比如,主庫中的emp表,擁有AFTER插入操作的觸發器。相用的表和觸發器也會存在於從數據庫中。複製的流程如下:
-
創建對EMP表的插入語句;
-
激活EMP表的AFTER觸發器;
-
插入語句寫入二進製日誌;
-
複製進程會選出EMP表的插入語句並在從數據庫上執行;
-
從數據庫上將會存在AFTER觸發器並激活。
基於行的複製:
當使用基於行的複製時,主庫上執行觸發器帶來的變動將會應用在從數據庫上。但在使用基於行的複製時,觸發器並不真的在從數據庫上執行。這是因為,如果在主從數據庫都執行的同時,從數據庫再次應用了主庫上觸發器執行帶來的變動,將會在從數據庫上應用兩次,導致主從數據庫上數據不一致。
大數據情況下,基於語句的複製和基於行的複製結果是相同的。但當主從數據庫上的觸發器不同時,將不能使用基於行的複製格式。(這是因為基於行級的複製,主庫上觸發器執行同步到從數據庫上的是數據改變,而不是語句執行,並且相應的觸發器也不會在從數據庫上執行。)不同的是,在使用基於語句的複製時,觸發器執行的任何語句都將會被應用。
更多信息,請參見手冊18.4.1.35節“複製和觸發器”。
Part 6 InnoDB表空間加密
1、數據會被解密給被授權可以查看它的用戶嗎?
是的。InnoDB表空間加密是用來為客戶提供能夠在數據庫中透明地應用加密而不會影響現有應用程序。返回加密格式的數據將破壞大多數現有的應用程序。InnoDB表空間加密提供了加密的同時消除了傳統數據庫加密的解決方案中相應的開銷,通常這些開銷需要對應用程序,數據庫觸發器和視圖進行成本很高的和大量的修改。
2、InnoDB表空間加密使用的是什麼加密算法?
InnoDB表空間加密支持高級加密標準(AES356)的基於塊的加密算法。對於表空間密鑰的加密,它使用的是電子碼(ECB)塊加密模式,對於數據加密,它使用的是密碼塊鏈接(CBC)加密模式。
3、是否可以使用第三方提供的加密算法來替代InnoDB表空間加密特性提供的加密算法?
不能,不可以使用其它的加密算法。所提供的加密算法被廣泛地接受。
4、InnoDB表空間加密支持什麼數據類型和數據長度?
InnoDB表空間加密支持所有的數據類型,沒有數據長度限製。
5、InnoDB表空間加密與MySQL已經提供的加密函數有何不同?
MySQL有對稱和非對稱加密APIs可以用來手動加密數據庫中的數據。然而,應用程序必須通過調用API函數管理加密密鑰和執行所需的加密及解密操作。
InnoDB表空間加密不需要應用程序修改,對最終用戶是透明的,並提供自動化、內置密鑰管理功能。
原文發布時間為:2017-03-13
本文來自雲棲社區合作夥伴DBAplus
最後更新:2017-05-16 10:31:42