MySQL 8 複製(九)——組複製聯機配置

lhrbest發表於2020-02-12

MySQL 8 複製(九)——組複製聯機配置


目錄


一、配置組複製模式


1. 單主模式


2. 多主模式


3. 聯機配置組複製模式


4. 配置併發寫例項數


5. 設定組的通訊協議版本


二、保證資料一致性


1. 組複製資料一致性簡介


2. 防止主庫故障轉移造成的過時讀取


3. 選擇適當的一致性級別


4. 一致性級別範圍


5. 一致性級別的影響


三、其它配置


1. 調整恢復


2. 網路分割槽


一、配置組複製模式

        組複製可以以單主模式或多主模式執行,預設採用單主模式。單主模式中只有一個可以讀寫的伺服器,其它伺服器只讀。多主模式中,所有伺服器均可讀寫。無論部署模式如何,組複製都不處理客戶端故障轉移,而必須由應用程式本身、聯結器或中介軟體(如MySQL router)處理此問題。


1. 單主模式

        在此模式下,組中具有單一可讀寫的主伺服器,通常是第一個引導組的伺服器,所有其它成員都為只讀。這種設定自動發生。當主伺服器失敗時,會自動選擇新的主伺服器,如圖1所示。


MySQL 8 複製(九)——組複製聯機配置

圖1

        選擇哪個伺服器作為新主庫由group_replication_member_weight系統變數控制,該變數值最高的成員將被選為新主庫。如果多個伺服器具有相同的group_replication_member_weight值,則組複製將根據按字典順序排列的server_uuid,優先選擇第一個線上伺服器作為新主庫。新主庫將自動設定為讀寫,其它伺服器仍為從庫,因此為只讀。


        新主庫只有在處理了來自舊主庫的所有事務後才可寫,這避免了在新主庫上並行執行新老事務的問題。將客戶端應用程式重新路由到新主庫之前,等待新主伺服器應用其複製相關的中繼日誌是一種很好的做法。


        如果組成員的MySQL版本不同,選舉新主庫的過程可能會受到影響。例如,如果有成員不支援group_replication_member_weight,則根據較低主版本成員的server_uuid順序選擇主庫;如果執行不同MySQL版本的所有成員都支援group_replication_member_weight,則根據較低主版本成員的group_replication_member_weight選擇主庫。


        主伺服器可由下面查詢確認:


mysql> select member_id, member_host, member_role from performance_schema.replication_group_members;

+--------------------------------------+-------------+-------------+

| member_id                            | member_host | member_role |

+--------------------------------------+-------------+-------------+

| 5c93a708-a393-11e9-8343-005056a5497f | hdp4        | SECONDARY   |

| 5f045152-a393-11e9-8020-005056a50f77 | hdp3        | PRIMARY     |

| 8eed0f5b-6f9b-11e9-94a9-005056a57a4e | hdp2        | SECONDARY   |

+--------------------------------------+-------------+-------------+

3 rows in set (0.00 sec)

2. 多主模式

        多主模式中所有伺服器角色等價,各伺服器都能讀寫。客戶端故障轉移如圖2所示。


MySQL 8 複製(九)——組複製聯機配置

圖2

        多主模式下部署組複製時,將進行以下檢查:


如果事務在SERIALIZABLE隔離級別下執行,則在與組同步時其提交失敗。

如果事務在具有級聯外來鍵約束的表上執行,則在與組同步時事務無法提交。

        通過將選項group_replication_enforce_update_everywhere_checks設定為FALSE,可以禁用這些檢查。單主模式下此選項必須設定為FALSE。


3. 聯機配置組複製模式

        可以使用一組依賴於組操作協調器的函式在組複製執行時聯機配置組,這些函式由版本8.0.13及更高版本中的組複製外掛提供。為使協調器能夠在正在執行的組上進行配置,所有成員必須MySQL 8.0.13或更高版本。


        配置整個組時,操作的分散式性質意味著它們與組複製外掛的許多程式互動,因此需要注意以下幾點:


可以在任何伺服器釋出配置操作,所有操作都以協調的方式傳送到所有組成員上執行。如果呼叫成員當機,任何已在執行的配置過程繼續在其它成員上執行。

配置更改期間,任何成員都無法加入組,在協調配置更改期間嘗試加入組的任何成員將離開該組並取消其加入過程。

一次只能執行一個配置。正在執行配置更改的組不能接受任何其它組配置更改,因為併發配置操作可能導致成員分歧。

不能在混合版本組上使用此配置功能。由於這些配置操作的分散式特性,所有成員必須識別它們才能執行。因此,組中不能存在舊版本的伺服器,否則操作被拒絕。

        可以在任何成員上執行函式。操作執行時可以通過發出以下命令來檢查其進度:


select event_name, work_completed, work_estimated from performance_schema.events_stages_current where event_name like "%stage/group_rpl%";

(1)更改主伺服器

        使用group_replication_set_as_primary() 函式更改單主組中的主伺服器,對於多主組此功能無效。只有主庫才允許寫入,因此如果該成員上正在執行非同步通道複製,則在非同步通道複製停止之前不允許切換。通過發出以下命令傳遞要成為該組新主伺服器成員的server_uuid:


mysql> select group_replication_set_as_primary('8eed0f5b-6f9b-11e9-94a9-005056a57a4e');

+--------------------------------------------------------------------------+

| group_replication_set_as_primary('8eed0f5b-6f9b-11e9-94a9-005056a57a4e') |

+--------------------------------------------------------------------------+

| Primary server switched to: 8eed0f5b-6f9b-11e9-94a9-005056a57a4e         |

+--------------------------------------------------------------------------+

1 row in set (0.02 sec)

(2)更改模式

        group_replication_switch_to_multi_primary_mode()函式用於單主改多主:


mysql> select member_id, member_host, member_role from performance_schema.replication_group_members;

+--------------------------------------+-------------+-------------+

| member_id                            | member_host | member_role |

+--------------------------------------+-------------+-------------+

| 5c93a708-a393-11e9-8343-005056a5497f | hdp4        | PRIMARY     |

| 5f045152-a393-11e9-8020-005056a50f77 | hdp3        | SECONDARY   |

| 8eed0f5b-6f9b-11e9-94a9-005056a57a4e | hdp2        | SECONDARY   |

+--------------------------------------+-------------+-------------+

3 rows in set (0.00 sec)

 

mysql> select group_replication_switch_to_multi_primary_mode();

+--------------------------------------------------+

| group_replication_switch_to_multi_primary_mode() |

+--------------------------------------------------+

| Mode switched to multi-primary successfully.     |

+--------------------------------------------------+

1 row in set (0.01 sec)

 

mysql> select member_id, member_host, member_role from performance_schema.replication_group_members;

+--------------------------------------+-------------+-------------+

| member_id                            | member_host | member_role |

+--------------------------------------+-------------+-------------+

| 5c93a708-a393-11e9-8343-005056a5497f | hdp4        | PRIMARY     |

| 5f045152-a393-11e9-8020-005056a50f77 | hdp3        | PRIMARY     |

| 8eed0f5b-6f9b-11e9-94a9-005056a57a4e | hdp2        | PRIMARY     |

+--------------------------------------+-------------+-------------+

3 rows in set (0.00 sec)

        下面驗證一下多主模式下對組複製的限制。


序列化隔離級別下報錯。

mysql> show create table test.t1\G

*************************** 1. row ***************************

       Table: t1

Create Table: CREATE TABLE `t1` (

  `a` bigint(20) NOT NULL AUTO_INCREMENT,

  PRIMARY KEY (`a`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

1 row in set (0.00 sec)

 

mysql> set transaction_isolation='serializable';

Query OK, 0 rows affected (0.00 sec)

 

mysql> insert into test.t1 select null;

ERROR 3098 (HY000): The table does not comply with the requirements by an external plugin.

mysql> set transaction_isolation='repeatable-read';

Query OK, 0 rows affected (0.00 sec)

 

mysql> insert into test.t1 select null;

Query OK, 1 row affected (0.01 sec)

Records: 1  Duplicates: 0  Warnings: 0

級聯更新報錯

mysql> create table stu(

    -> sid int unsigned primary key auto_increment,

    -> name varchar(20) not null);

stu(sid));

Query OK, 0 rows affected (0.02 sec)

mysql> 

mysql> create table sc(

    -> scid int unsigned primary key auto_increment,

    -> sid int unsigned not null,

    -> score varchar(20) default '0',

    -> index (sid), 

    -> foreign key (sid) references stu(sid));

Query OK, 0 rows affected (0.03 sec)

mysql> insert into stu (name) value ('zxf');

Query OK, 1 row affected (0.00 sec)

mysql> 

mysql> insert into sc(sid,score) values ('1','98');

Query OK, 1 row affected (0.01 sec)

mysql> drop table sc;

Query OK, 0 rows affected (0.02 sec)

mysql> drop table stu;

Query OK, 0 rows affected (0.01 sec)

mysql> create table stu(

    -> sid int unsigned primary key auto_increment,

    -> name varchar(20) not null);

Query OK, 0 rows affected (0.02 sec)

mysql> create table sc(

    -> scid int unsigned primary key auto_increment,

    -> sid int unsigned not null,

    -> score varchar(20) default '0',

    -> index (sid), 

    -> foreign key (sid) references stu(sid) on delete cascade on update cascade);

Query OK, 0 rows affected (0.02 sec)

mysql> insert into stu (name) value ('zxf');

Query OK, 1 row affected (0.00 sec)

mysql> 

mysql> insert into sc(sid,score) values ('1','98');

ERROR 3098 (HY000): The table does not comply with the requirements by an external plugin.

mysql> 

        group_replication_switch_to_single_primary_mode()函式用於多主改單主:


mysql> select group_replication_switch_to_single_primary_mode('8eed0f5b-6f9b-11e9-94a9-005056a57a4e');

+-----------------------------------------------------------------------------------------+

| group_replication_switch_to_single_primary_mode('8eed0f5b-6f9b-11e9-94a9-005056a57a4e') |

+-----------------------------------------------------------------------------------------+

| Mode switched to single-primary successfully.                                           |

+-----------------------------------------------------------------------------------------+

1 row in set (0.01 sec)

        如果未傳入任何字串,則新主節點的選擇由配置的選舉權重或server_uuid字典順序控制。


4. 配置併發寫例項數

        group_replication_get_write_concurrency()函式用於在執行時檢查組的最大並行可寫例項數。預設值為10適用於LAN上執行的組,對於通過較慢網路上(如WAN)執行的組,增加此數量可以微調組複製的效能。


mysql> select group_replication_get_write_concurrency();

+-------------------------------------------+

| group_replication_get_write_concurrency() |

+-------------------------------------------+

| 10                                        |

+-------------------------------------------+

1 row in set (0.00 sec)

        group_replication_set_write_concurrency()函式用於在執行時設定組的最大並行可寫例項數,值域為10-200。該函式是非同步執行的,可以呼叫group_replication_get_write_concurrency確認設定生效。


mysql> select group_replication_set_write_concurrency(1);

ERROR 1123 (HY000): Can't initialize function 'group_replication_set_write_concurrency'; Argument must be between 10 and 200.

mysql> select group_replication_set_write_concurrency(201);

ERROR 1123 (HY000): Can't initialize function 'group_replication_set_write_concurrency'; Argument must be between 10 and 200.

mysql> select group_replication_set_write_concurrency(10);

+-----------------------------------------------------------------------------------+

| group_replication_set_write_concurrency(10)                                       |

+-----------------------------------------------------------------------------------+

| UDF is asynchronous, check log or call group_replication_get_write_concurrency(). |

+-----------------------------------------------------------------------------------+

1 row in set (0.00 sec)

5. 設定組的通訊協議版本

        從MySQL 8.0.16開始,組複製具有通訊協議的概念。可以顯式管理組複製通訊協議版本,並將其設定為支援的最老的MySQL伺服器版本。這使得組可以由不同MySQL伺服器版本的成員組成,同時確保向後相容性。該組的所有成員必須使用相同的通訊協議版本,以便傳送所有組成員都能理解的訊息。


        如果組的通訊協議版本小於或等於X,則版本X的MySQL伺服器加入到複製組並達到ONLINE狀態。新成員加入複製組時,該組的現有成員會檢查加入成員的通訊協議版本。如果支援該版本,則將它加入該組並使用該組已宣佈的通訊協議。如果不支援通訊協議版本,則將其從組中移除。


        只有新成員的通訊協議版本與該組的通訊協議版本相容時,它們才能加入。加入該組的具有不同通訊協議版本的成員必須單獨加入。例如:


一個MySQL Server 8.0.16例項可以成功加入使用通訊協議版本5.7.24的組。

一個MySQL Server 5.7.24例項無法成功加入使用通訊協議版本8.0.16的組。

兩個MySQL Server 8.0.16例項無法同時加入使用通訊協議版本5.7.24的組。

兩個MySQL Server 8.0.16例項可以同時加入使用通訊協議版本8.0.16的組。

        group_replication_get_communication_protocol()函式用於檢查組使用的通訊協議,該函式返回該組支援的最老的MySQL伺服器版本。該組的所有現有成員都返回相同的通訊協議版本。


mysql> select group_replication_get_communication_protocol();

+------------------------------------------------+

| group_replication_get_communication_protocol() |

+------------------------------------------------+

| 8.0.16                                         |

+------------------------------------------------+

1 row in set (0.00 sec)

        group_replication_get_communication_protocol的返回值可能與傳遞給group_replication_set_communication_protocol 的版本號以及該組成員上正在使用的MySQL伺服器版本不同。如果需要更改組的通訊協議版本以便早期版本的成員可以加入,使用group_replication_set_communication_protocol()函式指定要允許的最老成員的MySQL伺服器版本。這使得該組在可能的情況下回退到相容的通訊協議版本。使用此函式需要GROUP_REPLICATION_ADMIN許可權,並且在發出語句時所有現有組成員必須處於線上狀態。


mysql> select group_replication_set_communication_protocol("5.7.25");

+-----------------------------------------------------------------------------------+

| group_replication_set_communication_protocol("5.7.25")                            |

+-----------------------------------------------------------------------------------+

| The operation group_replication_set_communication_protocol completed successfully |

+-----------------------------------------------------------------------------------+

1 row in set (0.01 sec)

 

mysql> select group_replication_get_communication_protocol();

+------------------------------------------------+

| group_replication_get_communication_protocol() |

+------------------------------------------------+

| 5.7.14                                         |

+------------------------------------------------+

1 row in set (0.00 sec)

        如果將複製組的所有成員升級到新的MySQL伺服器版本,則該組的通訊協議版本不會自動升級以匹配。必須使用group_replication_set_communication_protocol()函式將通訊協議版本設定為新MySQL伺服器版本。


mysql> select group_replication_set_communication_protocol("8.0.16");

+-----------------------------------------------------------------------------------+

| group_replication_set_communication_protocol("8.0.16")                            |

+-----------------------------------------------------------------------------------+

| The operation group_replication_set_communication_protocol completed successfully |

+-----------------------------------------------------------------------------------+

1 row in set (0.00 sec)

        group_replication_set_communication_protocol()函式作為組操作實現,因此它將在組的所有成員上同時執行。組操作開始緩衝訊息並等待傳遞已完成的任何傳出訊息,然後更改通訊協議版本併傳送緩衝的訊息。如果成員在更改通訊協議版本後加入該組,則組成員將使用新協議版本。


二、保證資料一致性

1. 組複製資料一致性簡介

        對分散式系統的一個重要需求是它能夠提供一致性保證。就分散式一致性而言,無論是在正常還是失敗修復的操作中,組複製始終是始終保持最終一致性。可以將影響資料一致性的事件分為兩類:一是手動或由故障自動觸發的控制操作;二是資料流。


(1)控制操作

        與一致性相關的組複製操作包括:新增或移除組成員、網路故障保護和主庫故障轉移。新增或移除組成員的資料一致性保障已經在“分散式恢復”中描述。


網路故障防寫

        當一個組成員離開復制組後,該成員不能繼續接收更新事務,否則只能在本地提交,造成資料不一致。為了提高安全性,執行STOP GROUP_REPLICATION時,在伺服器上啟用超級只讀模式。這將導致伺服器在離開組時預設只讀,無論它離開的原因是手動還是網路故障。


mysql> select member_id, member_host, member_role from performance_schema.replication_group_members;

+--------------------------------------+-------------+-------------+

| member_id                            | member_host | member_role |

+--------------------------------------+-------------+-------------+

| 5c93a708-a393-11e9-8343-005056a5497f | hdp4        | PRIMARY     |

| 5f045152-a393-11e9-8020-005056a50f77 | hdp3        | PRIMARY     |

| 8eed0f5b-6f9b-11e9-94a9-005056a57a4e | hdp2        | PRIMARY     |

+--------------------------------------+-------------+-------------+

3 rows in set (0.00 sec)

 

mysql> show variables like '%read_only%';

+-----------------------+-------+

| Variable_name         | Value |

+-----------------------+-------+

| innodb_read_only      | OFF   |

| read_only             | OFF   |

| super_read_only       | OFF   |

| transaction_read_only | OFF   |

+-----------------------+-------+

4 rows in set (0.00 sec)

mysql> stop group_replication;

Query OK, 0 rows affected (7.92 sec)

mysql> select member_id, member_host, member_role from performance_schema.replication_group_members;

+--------------------------------------+-------------+-------------+

| member_id                            | member_host | member_role |

+--------------------------------------+-------------+-------------+

| 5f045152-a393-11e9-8020-005056a50f77 | hdp3        |             |

+--------------------------------------+-------------+-------------+

1 row in set (0.00 sec)

mysql> show variables like '%read_only%';

+-----------------------+-------+

| Variable_name         | Value |

+-----------------------+-------+

| innodb_read_only      | OFF   |

| read_only             | ON    |

| super_read_only       | ON    |

| transaction_read_only | OFF   |

+-----------------------+-------+

4 rows in set (0.01 sec)

 

mysql> start group_replication;

Query OK, 0 rows affected (3.47 sec)

 

mysql> show variables like '%read_only%';

+-----------------------+-------+

| Variable_name         | Value |

+-----------------------+-------+

| innodb_read_only      | OFF   |

| read_only             | OFF   |

| super_read_only       | OFF   |

| transaction_read_only | OFF   |

+-----------------------+-------+

4 rows in set (0.01 sec)

mysql> select member_id, member_host, member_role from performance_schema.replication_group_members;

+--------------------------------------+-------------+-------------+

| member_id                            | member_host | member_role |

+--------------------------------------+-------------+-------------+

| 5c93a708-a393-11e9-8343-005056a5497f | hdp4        | PRIMARY     |

| 5f045152-a393-11e9-8020-005056a50f77 | hdp3        | PRIMARY     |

| 8eed0f5b-6f9b-11e9-94a9-005056a57a4e | hdp2        | PRIMARY     |

+--------------------------------------+-------------+-------------+

3 rows in set (0.00 sec)

主庫故障轉移

        單主模式中,當主庫發生故障,一個從庫被提升為主庫時,對於積壓事務與新事務有兩種可選的處理方式:1)可以立即服務應用程式,無論複製積壓的數量有多大;2)在處理積壓事務之前限制訪問。


        第一種方案中,系統將花費最少的時間在主庫故障之後通過選擇新主庫來保護穩定的組成員資格,然後在應用舊主庫積壓的事務時立即允許資料訪問。這種方式能夠保證寫入一致性,但可能讀取到過時的資料。使用第二種方法,系統將在主庫故障後保護穩定的組成員資格,並以與第一種方案相同的方式選擇新主庫。但在這種情況下,該組將等待新主庫應用所有積壓事務,之後才允許資料訪問。故障轉移所需的時間與積壓大小成正比,在均衡的複製組中,積壓應該很小。


        MySQL 8.0.14之前採用可用性最大化策略(第一種方法),並且不可配。MySQL 8.0.14及更高版本中可以使用group_replication_consistency變數配置組成員在主庫故障轉移期間提供的事務一致性保證級別。


(2)資料流

        資料流影響組一致性的方式基於讀取和寫入。單主模式中,通常將傳入的讀/寫事務進行拆分,寫入路由到主庫,讀取均勻分配給從庫。複製組對外應該表現為單個實體,因此可以合理地期望主庫上的寫入在從庫上即時可用。儘管組複製是在實現Paxos演算法的組通訊系統(GCS)協議之上編寫的,但組複製的某些部分是非同步的,這意味著資料非同步應用於從庫,因此可能出現這樣的情況,客戶端C1在主庫上寫入“A = 2 WHERE A = 1”,立即連線到從庫但讀取到“A = 1”。這是MySQL 8.0.14之前唯一可用的一致性級別。


        可以選擇在讀取或寫入時同步資料。如果在讀取時進行同步,則當前客戶端會話將等待一個給定點,即所有先前更新事務完成的時間點,然後才能開始執行。此方法僅影響當前會話,所有其它併發資料操作不受影響。如果在寫入時進行同步,則寫入會話將等待所有其它成員都寫入其資料。由於組複製遵循事務的總順序,這意味著需要等待其它成員執行佇列中所有先前的寫入及其本次寫入。這兩種可選方案都能確保前面例子中,即使立即連線到從庫,客戶端C1也將始終讀取“A = 2”。同步點的確定與系統工作負載直接相關。


        寫時同步適用場景:


組的寫入比讀取少的多,希望對讀取進行負載均衡,又不對讀取哪個伺服器進行額外限制以避免讀取舊資料。

主要是隻讀資料的組,希望讀寫事務一旦提交就應用到所有成員,以便後續讀取最新資料。

        讀時同步適用場景:


組的寫入比讀取多的多,希望對讀取進行負載均衡,又不對讀取哪個伺服器進行額外限制以避免讀取舊資料。

希望工作負載中的特定事務始終從組中讀取最新資料,以便每當更新敏感資料時強制讀取最新值。

        可以簡單但不夠嚴謹地理解為讀多寫時同步,寫多讀時同步,目的就是減少同步次數同時滿足資料一致性要求。後面會看到讀、寫兩個同步點以及兩者的組合,對應group_replication_consistency系統變數的可選值,用作選擇組複製一致性級別。


2. 防止主庫故障轉移造成的過時讀取

        組複製群集自動檢測故障並調整組成員檢視,即成員資格配置。如果組以單主模式部署,當成員資格更改時,將執行檢查以確定組中是否存在主庫。如果沒有,則在從庫成員列表中選擇一個作為新主庫,這就是所謂的從庫提升。使用者期望一旦發生從庫提升,新主庫資料與舊主庫資料處於完全相同的狀態,在新主庫上不能讀取或寫入舊資料。換句話說,當能夠讀取和寫入新主庫時,其上沒有積壓的複製事務。


        從MySQL 8.0.14開始,從庫提升後,使用者可以指定新主庫的行為。新增的group_replication_consistency系統引數用於控制新主庫是採用之前版本的最終一致性,還是阻止讀取和寫入,直到完全應用積壓事務。如果在具有group_replication_consistency='BEFORE_ON_PRIMARY_FAILOVER'設定的新主庫上執行事務時,該新主庫正在處理積壓,則事務將被阻止,直到完全應用待處理的積壓事務。這可確保在主庫發生故障轉移時,無論是自動觸發還是手工觸發,客戶端始終會在新主庫上看到最新值,因此防止了以下異常:


對於只讀和讀寫事務,沒有過時讀取。這可以防止新主庫將過時讀取外部化到應用程式。

讀寫事務沒有虛假回滾,因為與複製讀寫事務產生寫-寫衝突的事務仍處於待處理狀態。

讀寫事務沒有讀取偏差,例如:

-- 不會向t2插入從t1過時讀取的舊資料

insert into t2 select a from t1; 

        注意,該設定表明在可用性與一致性之間,使用者更重視資料一致性。畢竟和最終一致性相比,此設定可能使應用程式產生等待。這意味著客戶端必須能夠在應用積壓的情況下處理延遲。通常這種延遲應該很小,具體取決於積壓的大小。


        當group_replication_consistency ='BEFORE_ON_PRIMARY_FAILOVER'時,並非所有讀取都被阻止。例如,提升發生後,允許下面不修改資料的非阻塞查詢:


SHOW commands

SET option

DO

EMPTY

USE

SELECTing from performance_schema database

SELECTing from table PROCESSLIST on database infoschema

SELECTing from sys database

SELECT command that don’t use tables

SELECT command that don’t execute user defined functions

STOP GROUP_REPLICATION command

SHUTDOWN command

RESET PERSIST

        為了保證組不返回過時資料,組中所有成員都應該如下配置。從庫提升後阻塞新事務,直到新主庫應用所有積壓。


set persist group_replication_consistency= 'before_on_primary_failover';

3. 選擇適當的一致性級別

        group_replication_consistency系統變數用於配置組複製的一致性級別,不同配置對組處理的只讀(RO)和讀寫(RW)事務產生不同的影響。按增加事務一致性保證的順序,該變數有EVENTUAL、BEFORE_ON_PRIMARY_FAILOVER、BEFORE、AFTER、BEFORE_AND_AFTER五個可選值,預設為EVENTUAL。從上一小節已經瞭解了BEFORE_ON_PRIMARY_FAILOVER的作用,下面介紹其它四個可選值。


(1)EVENTUAL——預設值

        讀、寫事務都直接執行,不等待之前複製積壓的事務,也不等待其它組成員應用這些事務。這是MySQL 8.0.14之前的組複製行為。


流程圖



演算法描述

在組成員M1上開始事務T1。

T1執行到提交點,在該點事務資料已經傳送到所有組成員,包括髮起T1的成員M1。

每個成員檢查T1是否和之前的事務存在衝突,如果是則回滾T1,否則T1在M1上提交,並且進入其它成員的事務佇列,排隊執行和提交。

在成員M3接收到T1資料前開始事務T2。在M3上,T2將在T1之前執行,因此T2可能讀取到過時資料。

示例

        hdp3上鎖定表。


mysql> lock table t1 read;

Query OK, 0 rows affected (0.00 sec)

        hdp2上執行插入成功,不會產生等待。


mysql> insert into t1 values (1); 

Query OK, 1 row affected (0.01 sec)

        hdp3上執行查詢,由於表被鎖定,插入事務處於等待狀態,因此查詢結果為insert前的資料。表解鎖後,插入事務隨之執行和提交,查詢結果為insert後的資料。


mysql> select * from t1;

Empty set (0.00 sec)

mysql> unlock tables;

Query OK, 0 rows affected (0.00 sec)

mysql> select * from t1;

+---+

| a |

+---+

| 1 |

+---+

1 row in set (0.00 sec)

(2)BEFORE——讀時同步

        在開始執行之前,事務將等待所有先前的事務完成。這可確保此事務將在最新的資料快照上執行,而不管在哪個成員上執行。此一致性級別涵蓋BEFORE_ON_PRIMARY_FAILOVER提供的一致性保證。


流程圖



演算法描述

在組成員M1上使用EVENTUAL級別開始事務T1。

T1執行到提交點,在該點事務資料已經傳送到所有組成員,包括髮起T1的成員M1。

每個成員檢查T1是否和之前的事務存在衝突,如果是則回滾T1,否則T1在M1上提交,並且進入其它成員的事務佇列,排隊執行和提交。

在成員M3接收到T1資料前,使用BEFORE級別開始事務T2。T2將向所有群成員傳送訊息,提供T2的全域性順序。

當按順序接收和處理訊息時,M3從訊息流中獲取組複製應用程式的RECEIVED_TRANSACTION_SET,這是允許提交的遠端事務集合。無論這些事務是否實際已經提交,它們都包含在此集合中。這個集合提供了在T2之前存在的遠端事務。為了保證成員上的一致性讀,需要跟蹤遠端事務。儘管提供T2全域性順序的訊息已經傳送給所有組成員,但只有M3需要對其進行操作,其它成員丟棄此訊息而不進行任何其它操作。

事務T2僅在提交組複製應用程式RECEIVED_TRANSACTION_SET中的所有事務後才開始在M3上執行。這確保T2不會讀取和執行相對於其全域性順序過時的資料,這裡的順序為T1,T2。此等待僅發生在執行具有BEFORE一致性事務的伺服器上,本例中是M3,所有其它成員不受此等待的影響。

示例

        hdp3上,會話1中鎖定表。


mysql> lock table t1 read;

Query OK, 0 rows affected (0.00 sec)

        hdp2上執行插入成功,不會產生等待。


mysql> insert into t1 values (1); 

Query OK, 1 row affected (0.01 sec)

        hdp3上,會話2中在BEFORE級別下執行查詢,由於表被鎖定,插入事務處於等待狀態,因此查詢等待。


mysql> set @@session.group_replication_consistency='BEFORE' ;

Query OK, 0 rows affected (0.00 sec)

 

mysql> select * from t1;

        hdp3上,會話1中解鎖表。


mysql> unlock tables;

Query OK, 0 rows affected (0.00 sec)

        表解鎖後,插入事務隨之執行和提交,等待的查詢得以執行,結果為insert後的資料。因為單從輸出結果中無法區分是立即返回結果,還是先掛起一段時間後再返回的結果,所以這裡沒貼出查詢結果。


(3)AFTER——寫時同步

        讀寫事務將等待其更改已應用於其它成員,對只讀事務沒有影響。此模式確保在本地成員上提交事務時,後續事務會讀取最新值,而無論在哪個成員上執行。將此模式與主要只讀操作的組一起使用,保證應用的讀寫事務在提交後隨處可用。通過僅在讀寫事務上使用同步,減少了只讀事務上的同步開銷。此一致性級別涵蓋BEFORE_ON_PRIMARY_FAILOVER提供的一致性保證。


流程圖



演算法描述

在組成員M1上使用AFTER級別開始事務T1。

T1執行到提交點,在該點事務資料已經傳送到所有組成員,包括髮起T1的成員M1。

每個成員檢查T1是否和之前的事務存在衝突,如果是則回滾T1,否則執行第4步。

T1在其它成員上排隊執行。一旦事務進入準備階段,即資料在等待提交指令的儲存引擎上最終確定時,它將向所有成員傳送ACK確認。

一旦所有成員收到來自所有成員的確認,它們都提交事務。

在成員M3上的T1事務處於準備和提交之間時,使用EVENTUAL級別開始事務T2。此時T1還沒有提交,所以T2將等待T1提交完成後再開始執行。這確保T1後的事務都能讀取到T1的最新資料。

示例

        hdp3上,會話1中鎖定表。


mysql> lock table t1 read;

Query OK, 0 rows affected (0.00 sec)

        hdp2上在AFTER級別執行插入。因為表被鎖定,插入事務處於等待狀態。


mysql> set @@session.group_replication_consistency='AFTER' ;

Query OK, 0 rows affected (0.00 sec)

 

mysql> insert into t1 values (1); 

 

        hdp3上,會話2中執行查詢。由於插入事務處於等待狀態,因此查詢等待。


mysql> select * from t1;

 

        hdp3上,會話1中解鎖表。


mysql> unlock tables;

Query OK, 0 rows affected (0.00 sec)

        表解鎖後,插入事務隨之執行和提交,其後等待的查詢得以執行,結果為insert後的資料。基於和前面BEFORE示例中相同的原因,這裡沒貼出查詢結果。


(4)BEFORE_AND_AFTER——讀寫時都同步

        此事務開始執行時等待:1)所有該事務先前的事務都執行完成;2)該事務的變更已應用於其它成員。這可確保:1)此事務將在最新的資料快照上執行;2)一旦此事務完成,所有後續事務都會讀取到包含其更改的資料庫狀態,無論它們在哪個成員上執行。此一致性級別涵蓋BEFORE_ON_PRIMARY_FAILOVER提供的一致性保證。


流程圖



        BEFORE_AND_AFTER一致性級別的演算法流程是將BEFORE和AFTER組合在一起。讀寫事務等待之前所有的事務完成,並且等待其在所有節點上的變更結束。只讀事務需要等待之前所有的事務完成。


示例

        hdp2上,會話1中鎖定表,並執行更新。


mysql> lock table t1 write;

Query OK, 0 rows affected (0.00 sec)

mysql> insert into t1 values (1); 

Query OK, 1 row affected (0.01 sec)

        hdp3上,會話1中鎖定表,並執行更新。


mysql> lock table t1 write;

Query OK, 0 rows affected (0.00 sec)

mysql> insert into t1 values (2); 

Query OK, 1 row affected (0.00 sec)

        hdp2上,會話2中在BEFORE_AND_AFTER級別執行查詢。因為同一伺服器上的更新被鎖定,只讀查詢需要等待。


mysql> set @@session.group_replication_consistency='BEFORE_AND_AFTER' ;

Query OK, 0 rows affected (0.00 sec)

 

mysql> select * from t1;

 

        hdp2上,會話1中解鎖表。


mysql> unlock tables;

Query OK, 0 rows affected (0.00 sec)

        hdp2上,會話2中的查詢返回最新結果,距查詢開始已經等待了62.68秒。


mysql> select * from t1;

+---+

| a |

+---+

| 1 |

| 2 |

+---+

2 rows in set (1 min 2.68 sec)

        hdp2上,會話2中執行更新。因為hdp3上的更新被鎖定,讀寫事務需要等待。


mysql> insert into t1 values (3);

        hdp3上,會話1中解鎖表。


mysql> unlock tables;

Query OK, 0 rows affected (0.00 sec)

        表解鎖後,hdp2上會話2中執行的插入事務隨之執行和提交。


        BEFORE可以用於讀取和寫入事務,AFTER只用於寫事務。不同可選值提供了靈活性的一致性級別設定。


場景1:讀多寫少,不讀取過期資料的情況下對讀取進行負載平衡。選擇AFTER。

場景2:寫多讀少,不讀取過期資料。選擇BEFORE。

場景3:希望工作負載中的特定事務始終從組中讀取最新資料。選擇BEFORE。

場景4:複製組主要為只讀,希望讀寫事務一旦提交就應用於任何地方,以便後續讀取最新資料,並且不為只讀事務產生同步開銷。選擇AFTER。

場景5:複製組主要為只讀,希望讀寫事務始終從組中讀取最新資料,並在提交後隨處應用,以便後續讀取最新資料,並且不為只讀事務產生同步開銷。選擇BEFORE_AND_AFTER。

4. 一致性級別範圍

        選擇強制執行一致性級別的範圍非常重要,如果將它們設定在全域性範圍內,一致性級別可能會對效能產生負面影響。可以在全域性或會話級別設定group_replication_consistency系統變數:


-- 強制執行當前會話的一致性級別

set @@session.group_replication_consistency = 'before';

-- 強制執行所有會話的一致性級別

set @@global.group_replication_consistency = 'before';

        在特定會話上設定一致性級別的可能場景有:


場景6:只有一種更新,如設定對文件的訪問許可權,希望更改訪問許可權後,確保所有客戶端都能看到正確的許可權。其它更新沒有強一致性要求。只需要在該事務上執行 set @@session.group_replication_consistency = 'after',其它事務使用預設的EVENTUAL級別。

場景7:在場景6中描述的同一系統上,每天需要讀取最新資料進行一些分析處理。只需要在該特定事務上執行 set @@ session.group_replication_consistency = 'before'。

        作為原則,如果只有一些特性事務需要強一致性,就在會話級別設定group_replication_consistency。需要強調的一點是,所有事務在組複製中是完全排序的,因此即使發出以下命令僅設定當前會話的一致性級別為'AFTER':


set @@session.group_replication_consistency = 'after';

此事務也將等待其更改應用於所有組成員,即等待執行佇列上的此事務和所有先前事務。在實踐中,AFTER一致性級別將等待所有先前事務和當前事務在其它成員執行完。只能在狀態為ONLINE的組成員上設定BEFORE、AFTER和BEFORE_AND_AFTER的一致性級別,嘗試在其它狀態的成員上使用它們會導致會話錯誤。一致性級別不是EVENTUAL的事務等待的最長時間由wait_timeout系統變數指定,預設為8小時。如果超時,則丟擲ER_GR_HOLD_WAIT_TIMEOUT錯誤。


5. 一致性級別的影響

        可以根據對複製組其它成員的影響,對一致性級別進行分類。除了在事務流上排序之外,BEFORE一致性級別僅影響本地成員。也就是說,它不需要與其它成員協調,也不會對其它事務產生影響,或者說BEFORE僅影響使用它的事務。AFTER和BEFORE_AND_AFTER一致性級別對在其它成員上執行的併發事務具有副作用。這兩個一致性級別可以使其它成員事務陷入等待。假設一個事務T2在具有EVENTUAL級別的成員M2上啟動時,成員M1正在AFTER或BEFORE_AND_AFTER級別下執行一個事務T1,則T2必須等待T1在M2上提交後才能開始執行。對於其它成員也是如此,即使它們具有EVENTUAL一致性級別。就是說設定AFTER和BEFORE_AND_AFTER會影響所有ONLINE成員。


        為了進一步說明這一點,在具有M1、M2、M3三個成員的組試驗驗證。三個成員初始的group_replication_consistency均為預設值EVENTUAL。


(1)在成員M1上執行一個需要長時間提交的事務T1,這裡刪除一個具有2097152行資料的大表。


set @@session.group_replication_consistency = 'after';

begin; 

delete from num;

commit;

(2)上面SQL最後的commit命令執行過程中,在M2上開啟一個事務T2。


select count(*) from num for update;

        下面是兩次執行T2的輸出:


mysql> select count(*) from num for update;

+----------+

| count(*) |

+----------+

|  2097152 |

+----------+

1 row in set (1.66 sec)

 

mysql> select count(*) from num for update;

+----------+

| count(*) |

+----------+

|        0 |

+----------+

1 row in set (30.59 sec)

        第一次執行時,T1還沒有傳遞到M2時,T2可以正常查詢出刪除前的表記錄數。第二次執行時,T2開始等待,因為此時T1已經在M2的事務佇列中排隊,並且排在T2之前。即使T2的一致性級別為EVENTUAL,它也必須等待T1先完成提交。當等待了30秒後,T1提交完畢,T2開始執行,此時返回最新的表記錄數0。


三、其它配置

1. 調整恢復

        新成員加入複製組時,它會連線到一個合適的捐贈者(donor),從那裡獲取缺失的歷史資料,直到它變為線上狀態為止。此過程就是“MySQL 8 複製(七)——組複製基本原理”中詳細討論的分散式恢復。這裡側重如何設定分散式恢復相關的系統變數。


        捐贈者是從組中當前線上成員中隨機選擇的,這樣當多個成員進入組時,很大可能不會選擇同一伺服器作為捐贈者。如果新成員與捐贈者的連線失敗,會自動嘗試連線到另一個新的候選捐贈者。達到連線重試限制後,恢復過程將終止並顯示錯誤。組複製提供了強大的錯誤檢測機制,能夠在整個恢復過程中應對失敗。例如,當出現以下問題時,恢復都能檢測到錯誤並嘗試切換到新的捐贈者:


加入組的伺服器已經包含的資料與恢復期間來自所選捐贈者的資料存在衝突。

贈者包含新增成員已經清除(purge)GTID的資料。

恢復的接收執行緒或應用執行緒失敗。

(1)設定重連次數


        如果出現一些持續性故障甚至是瞬態故障,恢復將自動重試連線到相同或新的捐贈者。恢復資料傳輸依賴於二進位制日誌和現有的MySQL非同步複製框架,因此一些瞬態錯誤可能會導致接收執行緒或應用執行緒錯誤。在這種情況下,捐贈者切換程式具有重試功能,重試次數通過group_replication_recovery_retry_count外掛變數設定,預設值為10。該變數指定伺服器連線到每個合適的捐贈者的全域性嘗試次數。


mysql> show variables like 'group_replication_recovery_retry_count';

+----------------------------------------+-------+

| Variable_name                          | Value |

+----------------------------------------+-------+

| group_replication_recovery_retry_count | 10    |

+----------------------------------------+-------+

1 row in set (0.01 sec)

 

mysql> set group_replication_recovery_retry_count=10;

ERROR 1229 (HY000): Variable 'group_replication_recovery_retry_count' is a GLOBAL variable and should be set with SET GLOBAL

mysql> set global group_replication_recovery_retry_count=10;

Query OK, 0 rows affected (0.00 sec)

(2)設定休眠時間

        group_replication_recovery_reconnect_interval外掛變數定義恢復程式在捐贈者連線嘗試之間應休眠的時間,預設設定為60秒,可以動態更改。


mysql> show variables like 'group_replication_recovery_reconnect_interval';

+-----------------------------------------------+-------+

| Variable_name                                 | Value |

+-----------------------------------------------+-------+

| group_replication_recovery_reconnect_interval | 60    |

+-----------------------------------------------+-------+

1 row in set (0.02 sec)

 

mysql> set group_replication_recovery_reconnect_interval=60;

ERROR 1229 (HY000): Variable 'group_replication_recovery_reconnect_interval' is a GLOBAL variable and should be set with SET GLOBAL

mysql> set global group_replication_recovery_reconnect_interval=60;

Query OK, 0 rows affected (0.00 sec)

        並不是每次嘗試連線捐贈者後都休眠。只有當加入組的伺服器嘗試連線到該組中所有合適的捐贈者並且沒有剩餘時,恢復程式才會休眠由group_replication_recovery_reconnect_interval變數配置的秒數。


2. 網路分割槽

        事務複製、組成員身份更改,以及一些使組保持一致的內部訊息傳遞,都需要組成員達成共識。這要求大多陣列成員就特定決定達成一致。當大多陣列成員丟失時,組複製無法正常進行,因為無法保證多數或法定票數。例如,在一個5臺伺服器的複製組中,如果其中3臺異常當機,則大無法達到法定票數。事實上,剩下的兩個伺服器無法判斷其它三臺伺服器是否已崩潰,或者網路分割槽是否已將這兩臺伺服器單獨隔離,因此無法自動重新配置該組。


        另一方面,如果伺服器自願退出組,它們會指示組應該重新配置自己,這意味著離開的伺服器告訴其它成員它要退出。這種情況下其它成員可以正確地重新配置組,保持成員的資料一致性並重新計演算法定票數。在上述5個伺服器離開3個的場景中,如果3個離開的伺服器一個接一個地通知組它們要離開,那麼成員資格能夠從5調整到2,同時確保法定票數。法定票數喪失本身是不良計劃的結果。無論故障是連續發生,一次性發生,還是零星發生,通常容忍 f 個故障機所需的伺服器數量 n 為:n = 2 * f + 1。


        下面演示一個網路分割槽的例子。如下所示一個三個成員的單主模式複製組,成員均為線上狀態:


mysql> select member_id, member_host, member_state, member_role from performance_schema.replication_group_members;

+--------------------------------------+-------------+--------------+-------------+

| member_id                            | member_host | member_state | member_role |

+--------------------------------------+-------------+--------------+-------------+

| 5c93a708-a393-11e9-8343-005056a5497f | hdp4        | ONLINE       | SECONDARY   |

| 5f045152-a393-11e9-8020-005056a50f77 | hdp3        | ONLINE       | SECONDARY   |

| 8eed0f5b-6f9b-11e9-94a9-005056a57a4e | hdp2        | ONLINE       | PRIMARY     |

+--------------------------------------+-------------+--------------+-------------+

3 rows in set (0.00 sec)

現在用指令碼同時殺掉hdp3、hdp4上的MySQL例項,指令碼內容如下:


[mysql@hdp2~]$more kill_mysqld.sh 

#!/bin/bash

ssh hdp3 "ps -ef | grep mysqld | grep -v grep | awk '{print \$2}' | xargs kill -9"

ssh hdp4 "ps -ef | grep mysqld | grep -v grep | awk '{print \$2}' | xargs kill -9"

在hdp2上再次檢視成員狀態:


mysql> select member_id, member_host, member_state, member_role from performance_schema.replication_group_members;

+--------------------------------------+-------------+--------------+-------------+

| member_id                            | member_host | member_state | member_role |

+--------------------------------------+-------------+--------------+-------------+

| 5c93a708-a393-11e9-8343-005056a5497f | hdp4        | UNREACHABLE  | SECONDARY   |

| 5f045152-a393-11e9-8020-005056a50f77 | hdp3        | UNREACHABLE  | SECONDARY   |

| 8eed0f5b-6f9b-11e9-94a9-005056a57a4e | hdp2        | ONLINE       | PRIMARY     |

+--------------------------------------+-------------+--------------+-------------+

3 rows in set (0.00 sec)

        可以看到hdp2仍為線上狀態,但hdp3、hdp4處於不可到達狀態。而且,系統無法重新配置自己以改變成員資格,因為已經無法達到法定票數2。此時hdp2雖然線上,但無法執行任何事務,沒有外部干預就無法繼續提供服務。在這種特殊情況下,需要重置組成員資格以允許組複製繼續進行。此時有兩種選擇,一是重啟整個組複製:


-- hdp2上執行

stop group_replication;

set global group_replication_bootstrap_group=on;

start group_replication;

set global group_replication_bootstrap_group=off;

此方法實際上是重新初始化新的一個複製組,該複製組中只有hdp2一個成員(引導成員)。


        第二種方法是使用group_replication_force_members變數強制指定組成員。組複製可以通過強制執行特定配置來重置組成員身份列表。本例中hdp2是唯一線上伺服器,因此可以選擇強制hdp2的成員資格配置。必須強調,使用group_replication_force_members應被視為最後的補救措施,必須非常小心地使用,並且只能用於失敗伺服器大於等於法定票數的場景。如果誤用,可能會建立一個人工的裂腦情景或完全阻止整個系統。


        首先要檢查hdp2的組通訊識別符號,在hdp2上執行下面的查詢獲取此資訊。


mysql> select @@group_replication_local_address;

+-----------------------------------+

| @@group_replication_local_address |

+-----------------------------------+

| 172.16.1.125:33061                |

+-----------------------------------+

1 row in set (0.00 sec)

然後設定group_replication_force_members變數值為上面的查詢結果,強制組成員為hdp2:


mysql> set global group_replication_force_members="172.16.1.125:33061";

這會通過強制執行不同的配置來取消阻止該組。檢查hdp2上的replication_group_members以在此更改後驗證組成員身份。


mysql> select member_id, member_host, member_state, member_role from performance_schema.replication_group_members;

+--------------------------------------+-------------+--------------+-------------+

| member_id                            | member_host | member_state | member_role |

+--------------------------------------+-------------+--------------+-------------+

| 8eed0f5b-6f9b-11e9-94a9-005056a57a4e | hdp2        | ONLINE       | PRIMARY     |

+--------------------------------------+-------------+--------------+-------------+

1 row in set (0.00 sec)

        強制執行新的成員資格配置時,必須保證所有強制退出該組的伺服器確實已停止。在上面描述的場景中,如果hdp3、hdp4不可達(如斷網)但是MySQL例項可用,則它們可能已經形成了自己的網路分割槽(它們是3箇中的2個,因此佔大多數)。這種情況下強制使用hdp2的組成員列表可能會產生人為的裂腦情況。因此,在強制執行新的成員資格配置前,要確保排除的伺服器例項已關閉,然後再繼續執行。        使用group_replication_force_members系統變數成功強制新的組成員身份並取消阻止該組後,應該清除該系統變數。group_replication_force_members必須為空才能發出START GROUP_REPLICATION語句。


mysql> show variables like 'group_replication_force_members';

+---------------------------------+--------------------+

| Variable_name                   | Value              |

+---------------------------------+--------------------+

| group_replication_force_members | 172.16.1.125:33061 |

+---------------------------------+--------------------+

1 row in set (0.01 sec)

 

mysql> stop group_replication;

Query OK, 0 rows affected (13.13 sec)

 

mysql> start group_replication;

ERROR 3092 (HY000): The server is not configured properly to be an active member of the group. Please see more details on error log.

mysql> set group_replication_force_members="";

ERROR 1229 (HY000): Variable 'group_replication_force_members' is a GLOBAL variable and should be set with SET GLOBAL

mysql> set global group_replication_force_members="";

Query OK, 0 rows affected (0.01 sec)

 

mysql> set global group_replication_bootstrap_group=on;

Query OK, 0 rows affected (0.00 sec)

 

mysql> start group_replication;

Query OK, 0 rows affected (3.04 sec)

 

mysql> set global group_replication_bootstrap_group=off;

Query OK, 0 rows affected (0.00 sec)

        無論使用哪種方法恢復了組複製,都可以在hdp3、hdp4重新可用後,將它們重新新增到新的複製組。

啟動例項:


mysqld_safe --defaults-file=/etc/my.cnf &

啟動組複製:


start group_replication;

之後驗證組成員身份已經恢復到最初的狀態:

 


mysql> select member_id, member_host, member_state, member_role from performance_schema.replication_group_members;

+--------------------------------------+-------------+--------------+-------------+

| member_id                            | member_host | member_state | member_role |

+--------------------------------------+-------------+--------------+-------------+

| 5c93a708-a393-11e9-8343-005056a5497f | hdp4        | ONLINE       | SECONDARY   |

| 5f045152-a393-11e9-8020-005056a50f77 | hdp3        | ONLINE       | SECONDARY   |

| 8eed0f5b-6f9b-11e9-94a9-005056a57a4e | hdp2        | ONLINE       | PRIMARY     |

+--------------------------------------+-------------+--------------+-------------+

3 rows in set (0.00 sec)

 

————————————————

版權宣告:本文為CSDN博主「wzy0623」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處連結及本宣告。

原文連結:https://blog.csdn.net/wzy0623/article/details/96482662




About Me

........................................................................................................................

● 本文作者:小麥苗,部分內容整理自網路,若有侵權請聯絡小麥苗刪除

● 本文在itpub、部落格園、CSDN和個人微 信公眾號( xiaomaimiaolhr)上有同步更新

● 本文itpub地址: http://blog.itpub.net/26736162

● 本文部落格園地址: http://www.cnblogs.com/lhrbest

● 本文CSDN地址: https://blog.csdn.net/lihuarongaini

● 本文pdf版、個人簡介及小麥苗雲盤地址: http://blog.itpub.net/26736162/viewspace-1624453/

● 資料庫筆試面試題庫及解答: http://blog.itpub.net/26736162/viewspace-2134706/

● DBA寶典今日頭條號地址: http://www.toutiao.com/c/user/6401772890/#mid=1564638659405826

........................................................................................................................

● QQ群號: 230161599 、618766405

● 微 信群:可加我微 信,我拉大家進群,非誠勿擾

● 聯絡我請加QQ好友 646634621 ,註明新增緣由

● 於 2020-02-01 06:00 ~ 2020-02-31 24:00 在西安完成

● 最新修改時間:2020-02-01 06:00 ~ 2020-02-31 24:00

● 文章內容來源於小麥苗的學習筆記,部分整理自網路,若有侵權或不當之處還請諒解

● 版權所有,歡迎分享本文,轉載請保留出處

........................................................................................................................

小麥苗的微店https://weidian.com/s/793741433?wfr=c&ifr=shopdetail

小麥苗出版的資料庫類叢書http://blog.itpub.net/26736162/viewspace-2142121/

小麥苗OCP、OCM、高可用網路班http://blog.itpub.net/26736162/viewspace-2148098/

小麥苗騰訊課堂主頁https://lhr.ke.qq.com/

........................................................................................................................

使用 微 信客戶端掃描下面的二維碼來關注小麥苗的微 信公眾號( xiaomaimiaolhr)及QQ群(DBA寶典)、新增小麥苗微 信, 學習最實用的資料庫技術。

........................................................................................................................

歡迎與我聯絡

 

 



來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/26736162/viewspace-2675330/,如需轉載,請註明出處,否則將追究法律責任。

相關文章