MySQL 8.0與MariaDB 10.4,誰更易於填坑補鍋?

本文由 dbaplus 社羣授權轉載。

本文我將列舉一些MySQL 8.0和MariaDB 10.4關鍵新特性的對比,以便大家在今後的數據庫版本升級維護中能根據自身情況更快更好地做出選擇,其他新特性請參考官網:

Authentication

一、身份認證插件改變

MySQL 8.0開始將caching_sha2_password作爲默認的身份驗證插件。如果你升級了數據庫至8.0版本,對應用程序jdbc驅動兼容性不友好,讓應用程序跑起來最快的方法需要將默認的caching_sha2_password改爲之前的mysql_native_password。

例:

ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password  BY 'password';

或者直接寫死在my.cnf,重啓mysqld服務永久生效。

[mysqld]
default_authentication_plugin = mysql_native_password

(注:推薦用這種方法,方便快捷)

MariaDB 10.4身份驗證插件仍爲mysql_native_password,沒有發生改變。

二、增加身份驗證插件 - Unix Socket

unix_socket認證插件允許用戶通過本地Unix套接字文件連接到MariaDB的時候使用操作系統的憑證。

通俗的講就是用Linux操作系統的賬號,去登錄MariaDB/MySQL數據庫。

這個功能是在MariaDB 10.4.6版本里添加的,目前也支持在MySQL 8.0.18版本中。

1)MySQL 8.0.18使用方法

① 安裝插件

mysql> INSTALL PLUGIN auth_socket SONAME 'auth_socket.so';
Query OK, 0 rows affected (0.01 sec)

② 創建數據庫賬號hechunyang

mysql> CREATE USER 'hechunyang'@'localhost' IDENTIFIED WITH auth_socket;
Query OK, 0 rows affected (0.00 sec)

③ 創建操作系統賬號hechunyang

# useradd hechunyang
# passwd hechunyang

以hechunyang用戶登錄操作系統。

④ 登錄MySQL 8.0.18

[root@localhost soft]# su - hechunyang
Last login: Fri Nov  8 16:40:53 CST 2019>[hechunyang@localhost ~]$
 [hechunyang@localhost ~]$ /usr/local/mysql/bin/mysql -S /tmp/mysql_hcy.sock -uhechunyang -e "select version();"
+-----------+
| version() |
+-----------+
| 8.0.18    |
+-----------+
[hechunyang@localhost ~]$

在此示例中,用戶hechunyang已登錄操作系統並具有完全shell訪問權限。他已經使用操作系統進行了身份驗證,並且他的MySQL帳戶已配置爲使用unix_socket身份驗證插件,因此他無需再次對數據庫進行身份驗證。MySQL接受他的操作系統憑證並允許他連接。

2)MariaDB 10.4.10使用方法

① 創建數據庫賬號hechunyang

MariaDB [(none)]> GRANT ALL ON *.* TO 'hechunyang' IDENTIFIED VIA unix_socket;
Query OK, 0 rows affected (0.001 sec)

後續操作和MySQL 8.0.18一樣。

InnoDB

一、數據字典改進支持原子DDL(atomic DDL)

MySQL 8.0使用新的數據字典,廢棄了MyISAM系統表。MySQL庫元信息存儲在數據目錄中mysql.ibd的innodb表空間文件中(.frm表結構信息文件移除)。

新的數據字典支持原子DDL(atomic DDL)功能,這意味着,當執行DDL時,數據字典更新、存儲引擎操作和二進制日誌中的寫入被組合成一個要麼完全執行、要麼不執行的單個原子事務。這提供了更好的可靠性,未完成的DDL不會留下任何不完整的數據。

比如當對大表做alter table modify變更時,kill -9 mysqld進程,在MySQL8.0之前的版本會留下臨時數據文件(例#sql-22a4_17.ibd),而在MySQL 8.0版本里將直接回滾掉。

二、instant ADD COLUMN億級大表毫秒級加字段

加字段是痛苦的,需要對錶進行重建,尤其是對億級別的大表,雖然Online DDL可以避免鎖表,但如果在主庫上執行耗時30分鐘,那麼再複製到從庫上執行,主從複製就出現延遲。使用instant ADD COLUMN特性(只需要修改元數據),彈下菸灰的時間,字段就加好了,享受MongoDB那樣的非結構化存儲的靈活方便。

限制

1)如果指定了AFTER,字段必須是在最後一列,否則會重新建立表。

(注:MariaDB 10.4支持加字段在任何位置上使用algorithm=instant算法)

2)不適用於ROW_FORMAT = COMPRESSED

3)DROP COLUMN需要重建表。

(注:MariaDB 10.4支持對DROP刪除字段使用algorithm=instant算法)

三、安全執行Online DDL

Online DDL從名字上看很容易誤導新手,以爲不論什麼情況,修改表結構都不會鎖表,理想很豐滿,現實很骨感,注意這個坑!

有以下兩種情況執行DDL操作會鎖表的,Waiting for table metadata lock(元數據表鎖)

1)增加、刪除字段或索引不會鎖全表,刪除主鍵、更改字段屬性會鎖全表。

2)在添加字段alter table表時,對該表的增、刪、改、查均不會鎖表。而在這之前,該表有被訪問時,需要等其執行完畢後,纔可以執行alter table,例如在會話一,故意執行一條大結果的查詢,然後在會話二執行增加字段age,此時還會出現表鎖。

針對第二種情況,MariaDB 10.3 增補AliSQL補丁-DDL FAST FAIL,讓其DDL操作快速失敗。

語法爲:

ALTER TABLE tbl_name [WAIT n|NOWAIT] ...
CREATE ... INDEX ON tbl_name (index_col_name, ...) [WAIT n|NOWAIT] ...
DROP INDEX ... [WAIT n|NOWAIT]
DROP TABLE tbl_name [WAIT n|NOWAIT] ...
LOCK TABLE ... [WAIT n|NOWAIT]
OPTIMIZE TABLE tbl_name [WAIT n|NOWAIT]
RENAME TABLE tbl_name [WAIT n|NOWAIT] ...
SELECT ... FOR UPDATE [WAIT n|NOWAIT]
SELECT ... LOCK IN SHARE MODE [WAIT n|NOWAIT]
TRUNCATE TABLE tbl_name [WAIT n|NOWAIT]

如果線上有某個慢SQL對該表進行操作,可以使用WAIT n(以秒爲單位設置等待)或NOWAIT在語句中顯式設置鎖等待超時,在這種情況下,如果無法獲取鎖,語句將立即失敗。WAIT 0相當於NOWAIT。

(注:MySQL 8.0目前不支持ALTER NOWAIT,僅僅支持SELECT FOR UPDATE NOWAIT)

四、clone克隆插件

從MySQL 8.0.17開始,MySQL提供了一個克隆插件,可以方便我們快速克隆出一個從庫或者MGR的Secondary節點。

1)克隆插件的安裝和驗證過程

① 安裝克隆插件

mysql> INSTALL PLUGIN CLONE SONAME 'mysql_clone.so'; 

② 檢查克隆插件是否處於活動狀態

mysql> SELECT PLUGIN_NAME, PLUGIN_STATUS  FROM 
INFORMATION_SCHEMA.PLUGINS  WHERE  PLUGIN_NAME  LIKE  'clone';
+-----------------------+--------------------------+
| PLUGIN_NAME  | PLUGIN_STATUS  |
+-----------------------+--------------------------+
| clone            | ACTIVE          |
+-----------------------+--------------------------+
1 row in set (0.00 sec)

③ 創建clone克隆賬號權限(所有節點都執行)

CREATE USER 'clone_user'@'%' IDENTIFIED BY '123456';
GRANT BACKUP_ADMIN,CLONE_ADMIN ON *.* TO 'clone_user'@'%';

2)克隆過程

① 設置提供數據的節點(捐贈者)

set global clone_valid_donor_list = '192.168.137.11:3306';

② 開始從遠程MySQL(捐贈者)克隆數據並將其傳輸到當前的MySQL實例

CLONE INSTANCE FROM [email protected]:3306 IDENTIFIED BY '123456';

③ 完成克隆後,新節點mysqld進程會自動重啓(原有數據會被自動刪除)

④ 狀態查看

select * from performance_schema.clone_status;
select * from performance_schema.clone_progress;

⑤ 開啓複製

CHANGE MASTER TO MASTER_HOST = '192.168.137.11', MASTER_PORT = 
3306,MASTER_USER='repl',MASTER_PASSWORD='repl',MASTER_AUTO_POSITION = 1;

start slave;

侷限性

  • 僅支持InnoDB存儲引擎。
  • TRUNCATE TABLE在克隆期間爲禁止狀態。
  • 如果DDL正在運行,則克隆操作將等待其執行完才能進行。

(注:MariaDB 10.4不支持clone克隆功能)

General Features

一、MariaDB 10.3支持自動KILL掉未提交的空閒事務

參數innodb_kill_idle_transaction(這個是Percona XtraDB引用的參數),意思爲當一個事務長時間未提交,那麼這個連接就不能關閉,內存就不釋放,併發一大,導致DB連接數增多,就會對性能產生影響。

默認是0秒,你可以根據自己的情況設定閾值。超過這個閾值,服務端自動殺死未提交的空閒事務。

MariaDB在10.2.6版本里將其移除,因不再捆綁Percona XtraDB,分道揚鑣。

MariaDB在10.3版本里,增加了3個參數,對標Percona的功能。

  • idle_transaction_timeout(所有的事務)
  • idle_write_transaction_timeout(寫事務)
  • idle_readonly_transaction_timeout(只讀事務)

單位爲秒。設置這個參數後只針對新的連接有效,正在執行的連接無效。

(注:Oralce MySQL 8.0不支持該功能)

二、MariaDB 10.3 系統版本表有效防止數據丟失

系統版本表是SQL:2011標準中首次引入的功能,它存儲所有更改的歷史數據,而不僅僅是當前時刻有效的數據。

舉個例子,同一行數據一秒內被更改了10次,那麼系統版本表就會保存10份不同時間的版本數據。就像電影《源代碼》裏的平行世界理論一樣,你可以退回任意時間裏,從而有效保障你的數據是安全的。也就是說,DBA手抖或是程序BUG引起的數據丟失,在MariaDB 10.3裏已然成爲過去。

具體操作詳見:https://dbaplus.cn/news-11-2057-1.html

三、MariaDB 10.3支持update多表ORDER BY and LIMIT

1)update連表更新,limit語句

update t1 join t2 on t1.id=t2.id set t1.name='hechunyang' limit 3;

2)update連表更新,ORDER BY and LIMIT語句

update t1 join t2 on t1.id=t2.id set t1.name='hechunyang' order by t1.id DESC limit 3;

MySQL 8.0 直接報錯

ERROR 1221 (HY000): Incorrect usage of UPDATE and LIMIT

四、MariaDB 10.3 解決掉了UPDATE不支持同一張表的子查詢更新

案例:

CREATE TABLE t1 (c1 INT, c2 INT);
INSERT INTO t1 VALUES (10,10), (20,20);
UPDATE t1 SET c1=c1+1 WHERE c2=(SELECT MAX(c2) FROM t1);

MySQL 8.0 直接報錯:

ERROR 1093 (HY000): You can't specify target table 't1' for update in FROM clause

MySQL目前只能改寫SQL實現,即max那條語句讓其產生衍生表就可以通過:

UPDATE t1 a, (SELECT MAX(c2) as m_c2 FROM t1) as b SET a.c1=a.c1+1 WHERE a.c2=b.m_c2;

五、MySQL 8.0解決Too many connections數據庫連接數被打滿

其實這個功能,MySQL增加的着實太晚了。在MariaDB 10.0和Percona5.6版本中,有個參數extra_port可以登錄“後門”解決。

在MySQL 8.0版本中,有個類似的參數實現了該功能。

admin_address  =   127.0.0.1
admin_port    =    13308
create_admin_listener_thread   =   ON

只需要指定13308端口號,就可以連接了。

(注:不支持動態修改,要寫死在my.cnf配置文件裏重啓mysqld進程生效)

六、MariaDB FLUSH TABLES命令只關閉未使用的表

會話一

select id,sleep(60) from t1;

因未執行完,t1表持有METADATA LOCK(MDL)元數據鎖。

會話二

FLUSH TABLES;

在MariaDB 10.4 版本以前,執行FLUSH TABLES會把所有的表強制關閉,因會話一持有MDL元數據鎖,固FLUSH TABLES會等待Waiting for table metadata lock。

在MariaDB 10.4 GA版本,將只關閉未使用的表,正在使用中的表忽略不受影響。(除非你手工指定表,如FLUSH TABLES t1,將會強制關閉t1表)

場景:MHA在線切換調用master_ip_online_change腳本時,第一步會執行FLUSH NO_WRITE_TO_BINLOG TABLES關閉所有表,此時如果你的數據庫有未執行完的慢SQL,FLUSH NO_WRITE_TO_BINLOG TABLES就會卡住,導致無法切換。

(注:MySQL 8.0.18版本不支持該功能)

Optimizer

一、Descending Index降序索引

MySQL 8.0開始支持降序索引(InnoDB引擎)。可以直接定義索引爲DESC,這樣在存儲的時候就是降序的,在降序掃描時會大幅度提升性能。當然,最大的好處是我們可以用索引處理 order by a desc ,b asc,c desc混合排序的查詢了,在之前的版本,排序的字段順序必須一致,否則使用不到索引,explain的結果中會出現filesort。

CREATE TABLE t1 (a INT PRIMARY KEY, b INT, KEY a_idx(a DESC, b ASC));

(注:MariaDB 10.4不支持該功能)

二、MySQL 8.0.18 Hash Join不支持left/right join左右連接

在MySQL 8.0.18中,增加了Hash Join新功能,它適用於未創建索引的字段,做等值關聯查詢。在之前的版本里,如果連接的字段沒有創建索引,查詢速度會是非常慢的,優化器會採用BNL(塊嵌套)算法。

Hash Join算法是把一張小表數據存儲到內存中的哈希表裏,並逐行去匹配大表中的數據,計算哈希值並把符合條件的數據,從內存中返回客戶端。

我們用explain format=tree命令可以查看到已經使用到hash join算法。

但目前8.0.18版本,僅支持join。left join和right join失效,explain執行計劃會顯示<not executable by iterator executor>,這裏請注意。

(注:MariaDB 10.4不支持該功能)

三、Explain Analyze在MySQL 8.0.18版本中的擴展使用

在之前的版本里,我們是用explain命令來查看SQL的具體執行計劃。在MySQL 8.0.18版本里新增了explain擴展,一個是explain format=tree,另一個是基於explain format=tree延伸擴展的Explain Analyze,今天我們查看下該命令是怎樣執行的。

測試用例:

explain analyze select count(*) from sbtest1;

這個結果很讓人奇怪,不加where條件,啥都不能顯示出來,貌似是個BUG?

加個where id>0再試試。

explain analyze select count(*) from sbtest1 where id>0;

注意看紅色劃線部分,它內部會運行查詢並測量執行時間。

含義解釋:

1) cost部分的rows=4932000,是和explain生成的結果一致,都是估算讀取的行數。

2)actual部分的rows=1000000,是執行這條SQL返回的真正結果,見如下圖所示。

3)actual time=5504.446(單位ms毫秒),轉換爲秒是這條SQL執行的時間爲5.5秒,但其實是有很大的誤差的,你看上面的執行時間0.24秒,誤差很大,因此我們不能真正相信這些數字。

MariaDB 10.4也實現了類似的功能,需要開啓優化器跟蹤,命令如下:

SET optimizer_trace='enabled=on';

然後查看select * from information_schema.optimizer_trace表即可。

四、MySQL 8.0資源組有效解決慢SQL引發CPU告警

資源組的作用是資源隔離(你可以理解爲開通雲主機時勾選的硬件配置),將線上的慢SQL線程id分配給CPU一個核,讓它慢慢跑,從而不影響CPU整體性能。

創建一個資源組

mysql> create resource group slowsql_rg type=user vcpu=3 
thread_priority=19 enable;
  • slowsql_rg爲資源組名字
  • type=user 來源是用戶端的慢SQL
  • vcpu=3 給它分配到哪個CPU核上(你可以用cat /proc/cpuinfo | grep processor查看CPU有多少核)
  • thread_priority爲優先級別,範圍是0到19,19是最低優先級,0是最高優先級。

查看資源組信息:

mysql> select * from information_schema.resource_groups;

查找慢SQL的線程ID:

SELECT THREAD_ID,PROCESSLIST_INFO,RESOURCE_GROUP,PROCESSLIST_TIME FROM 
performance_schema.threads WHERE PROCESSLIST_INFO REGEXP 
'SELECT|INSERT|UPDATE|DELETE|ALTER' AND PROCESSLIST_TIME > 10;

把THREAD_ID取出來的值,放入資源組裏做限制:

set resource group slowsql_rg for 379;

比如你想放寬的限制,也可以更改:

ALTER RESOURCE GROUP slowsql_rg VCPU = 3 
THREAD_PRIORITY = 0;

關閉資源組,解除限制:

ALTER RESOURCE GROUP slowsql_rg DISABLE FORCE;

(注:MariaDB 10.4不支持該功能)

五、Query Rewrite支持SELECT INSERT UPDETE DELETE REPLACE語句重寫

這個功能要點贊,比如開發上線時,有個SQL查詢字段索引忘記加了,直接把線上CPU打滿,此時,你可以將SQL重寫,讓業務先報錯,別打死數據庫,然後馬上通知開發回滾,等加完索引後再上線。

安裝插件:

mysql -S /tmp/mysql_hcy.sock -p123456 <./install_rewriter.sql

查看是否生效:

SHOW GLOBAL VARIABLES LIKE 'rewriter_enabled';

編寫重寫規則:

insert into query_rewrite.rewrite_rules(pattern, replacement, 
pattern_database) values (
"SELECT * from sbtest1 limit ?",
"SELECT k,c from sbtest1 limit ?",
"test");

意思爲將以下語句:

SELECT * from sbtest1 limit ?;

改寫成:

SELECT k,c from sbtest1 limit ?;

(注:問號?爲變量)

執行規則生效:

CALL query_rewrite.flush_rewrite_rules();

演示:

mysql> SELECT * from sbtest1 limit 1\G;
*************************** 1. row ***************************
k: 499284
c: 83868641912-28773972837-60736120486-75162659906-27563526494-20381887404-41576422241-93426793964-56405065102-33518432330
1 row in set, 1 warning (0.00 sec)

ERROR: 
No query specified

mysql> show warnings\G
*************************** 1. row ***************************
  Level: Note
   Code: 1105

Message: Query 'SELECT * from sbtest1 limit 1' rewritten to 'SELECT k,c from sbtest1 limit 1' by a query rewrite plugin
1 row in set (0.00 sec)

(注:MariaDB 10.4不支持該功能)

Backup

一、Percona Xtrabackup 8.0備份MySQL 8.0

隨着Percona XtraBackup 8.0的推出,Percona XtraBackup 2.4將繼續支持MySQL和Percona Server 5.6和5.7數據庫。

由於MySQL 8.0在數據字典,重做日誌和撤消日誌中引入的更改與以前的版本不兼容,因此Percona XtraBackup 8.0 目前不支持8.0之前的版本。

1)備份

# xtrabackup --defaults-file=/etc/my_hechunyang.cnf -S /tmp/mysql_hechunyang.sock 
--user='root' --password='123456' --slave-info --backup 
--compress --compress-threads=4 --target-dir=/data/bak/

(注:compress是開啓壓縮模式;compress-threads是開啓壓縮模式線程數)

壓縮模式需要先安裝Percona自研的qpress壓縮工具。

# yum install  https://repo.percona.com/yum/percona-release-latest.noarch.rpm  
# yum install qpress -y

2)解壓縮

# for bf in `find . -iname "*\.qp"`; do qpress -d $bf $(dirname $bf) && rm -f $bf; done

3)恢復備份期間增量數據(這一步類似innobackupex --apply-log)

# xtrabackup  --prepare --target-dir=/data/bak/

4)恢復

① 關閉mysqld進程

② 確保datadir目錄爲空,你可以把原目錄改個名字,再創建一個新的

③ 恢復

# xtrabackup --defaults-file=/etc/my_hechunyang.cnf --copy-back --target-dir=/data/bak/

④ 更改目錄屬性

# chown -R mysql:mysql /var/lib/mysql/

⑤ 啓動mysqld進程

二、MariaDB - Mariabackup熱備份工具

自MariaDB10.2.7(含)以上版本,不再支持使用Percona XtraBackup工具在線物理熱備份。

MariaDB 10.1引入了MariaDB獨有的功能,例如InnoDB頁面壓縮和靜態數據加密。這些獨家功能在MariaDB用戶中非常受歡迎。但是,來自MySQL生態系統的現有備份解決方案(如Percona XtraBackup)不支持這些功能的完全備份功能。

爲了滿足用戶的需求,MariaDB官方決定開發一個完全支持MariaDB獨有功能的備份解決方案。它基於Percona XtraBackup 2.3.8版本改寫擴展。

mariabackup工具使用(包含在二進制tar包bin目錄下)

1)備份

shell> mariabackup --defaults-file=/etc/my.cnf -S /tmp/mysql3306.sock --backup --target-dir=/data/bak/ --user=root --password=123456

2)恢復備份期間增量數據(這一步類似innobackupex --apply-log)

shell> mariabackup --prepare --target-dir=/data/bak/

(注:/data/bak/xtrabackup_binlog_pos_innodb文件,記錄主庫show master status的POS點)

3)恢復

步驟

① 關閉mysqld進程

② 確保datadir目錄爲空,你可以把原目錄改個名字,再創建一個新的

③恢復

# mariabackup --defaults-file=/etc/my.cnf --copy-back 
--target-dir=/data/bak/

④ 更改目錄屬性

# chown -R mysql:mysql /var/lib/mysql/

⑤ 啓動mysqld進程

如果你想在從庫上備份,並且想記錄從庫的show slave status的POS點,以便後續再接一個從庫,那麼你可以這樣搞:

mariabackup --defaults-file=/etc/my.cnf -S /tmp/mysql3306.sock 
--backup --slave-info --safe-slave-backup --target-dir=/data/bak/ 
--user=root --password=123456

(注:/data/bak/xtrabackup_slave_info文件,記錄從庫show slave status的POS點)

作者介紹

賀春暘,凡普金科DBA團隊負責人,《MySQL管理之道:性能調優、高可用與監控》第一、二版作者,曾任職於中國移動飛信、安卓機鋒網。致力於MariaDB、MongoDB等開源技術的研究,主要負責數據庫性能調優、監控和架構設計。

原文鏈接

https://mp.weixin.qq.com/s?__biz=MzI4NTA1MDEwNg==&mid=2650783694&idx=1&sn=11413422654a3d8d2d5799441d2d4d54&chksm=f3f90a5bc48e834d06061a493f2c26d5a54fabd36f8bc96486d173aa81ce63d79275edfe9175&scene=27#wechat_redirect

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章