Mysql
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Mysql

MySQL InnoDB Cluster 8.0 - Hướng dẫn hoạt động hoàn chỉnh:Phần thứ hai

Trong phần đầu tiên của blog này, chúng tôi đã giới thiệu hướng dẫn triển khai MySQL InnoDB Cluster với một ví dụ về cách các ứng dụng có thể kết nối với cụm thông qua một cổng đọc / ghi chuyên dụng.

Trong hướng dẫn hoạt động này, chúng tôi sẽ đưa ra các ví dụ về cách giám sát, quản lý và mở rộng Cụm InnoDB như một phần của các hoạt động bảo trì cụm đang diễn ra. Chúng tôi sẽ sử dụng cùng một cụm những gì chúng tôi đã triển khai trong phần đầu tiên của blog. Sơ đồ sau đây cho thấy kiến ​​trúc của chúng tôi:

Chúng tôi có Nhân rộng Nhóm MySQL ba nút và một máy chủ ứng dụng đang chạy với Bộ định tuyến MySQL. Tất cả các máy chủ đang chạy trên Ubuntu 18.04 Bionic.

MySQL InnoDB Cluster Command Options

Trước khi chúng ta đi sâu hơn với một số ví dụ và giải thích, bạn nên biết rằng bạn có thể nhận được giải thích về từng hàm trong cụm MySQL cho thành phần cụm bằng cách sử dụng hàm help (), như được hiển thị bên dưới:

$ mysqlsh
MySQL|localhost:3306 ssl|JS> shell.connect("[email protected]:3306");
MySQL|db1:3306 ssl|JS> cluster = dba.getCluster();
<Cluster:my_innodb_cluster>
MySQL|db1:3306 ssl|JS> cluster.help()

Danh sách sau đây hiển thị các chức năng có sẵn trên MySQL Shell 8.0.18, cho MySQL Community Server 8.0.18:

  • addInstance (instance [, options]) - Thêm một Instance vào cụm.
  • checkInstanceState (instance) - Xác minh trạng thái gtid thể hiện liên quan đến cụm.
  • description () - Mô tả cấu trúc của cụm.
  • ngắt kết nối () - Ngắt kết nối tất cả các phiên nội bộ được đối tượng cụm sử dụng.
  • tan ([options]) - Hủy kích hoạt sao chép và hủy đăng ký ReplicaSets khỏi cụm.
  • forceQuorumUsingPartitionOf (instance [, password]) - Khôi phục cụm khỏi mất túc số.
  • getName () - Truy xuất tên của cụm.
  • help ([member]) - Cung cấp trợ giúp về lớp học này và các thành viên của nó
  • options ([options]) - Liệt kê các tùy chọn cấu hình cụm.
  • reinInstance (instance [, options]) - Tham gia lại một Instance vào cụm.
  • removeInstance (instance [, options]) - Xóa một Phiên bản khỏi cụm.
  • quét lại ([tùy chọn]) - Quét lại cụm.
  • resetRecoveryAccountsPassword (tùy chọn) - Đặt lại mật khẩu của các tài khoản khôi phục của cụm.
  • setInstanceOption (instance, option, value) - Thay đổi giá trị của tùy chọn cấu hình trong thành viên Cluster.
  • setOption (tùy chọn, giá trị) - Thay đổi giá trị của tùy chọn cấu hình cho toàn bộ cụm.
  • setPrimaryInstance (instance) - Chọn một thành viên cụm cụ thể làm thành viên chính mới.
  • status ([options]) - Mô tả trạng thái của cụm.
  • switchToMultiPrimaryMode () - Chuyển cụm sang chế độ đa chính.
  • switchToSinglePrimaryMode ([instance]) - Chuyển cụm sang chế độ đơn chính.

Chúng tôi sẽ xem xét hầu hết các chức năng có sẵn để giúp chúng tôi theo dõi, quản lý và mở rộng quy mô cụm.

Giám sát Hoạt động Cụm InnoDB của MySQL

Trạng thái Cụm

Để kiểm tra trạng thái cụm, trước tiên hãy sử dụng dòng lệnh MySQL shell và sau đó kết nối dưới dạng [email protected]{one-of-the-db-nodes}:

$ mysqlsh
MySQL|localhost:3306 ssl|JS> shell.connect("[email protected]:3306");

Sau đó, tạo một đối tượng có tên "cluster" và khai báo nó là đối tượng toàn cầu "dba" cung cấp quyền truy cập vào các chức năng quản trị cụm InnoDB bằng cách sử dụng AdminAPI (xem tài liệu MySQL Shell API):

MySQL|db1:3306 ssl|JS> cluster = dba.getCluster();
<Cluster:my_innodb_cluster>

Sau đó, chúng ta có thể sử dụng tên đối tượng để gọi các hàm API cho đối tượng "dba":

MySQL|db1:3306 ssl|JS> cluster.status()
{
    "clusterName": "my_innodb_cluster",
    "defaultReplicaSet": {
        "name": "default",
        "primary": "db1:3306",
        "ssl": "REQUIRED",
        "status": "OK",
        "statusText": "Cluster is ONLINE and can tolerate up to ONE failure.",
        "topology": {
            "db1:3306": {
                "address": "db1:3306",
                "mode": "R/W",
                "readReplicas": {},
                "replicationLag": null,
                "role": "HA",
                "status": "ONLINE",
                "version": "8.0.18"
            },
            "db2:3306": {
                "address": "db2:3306",
                "mode": "R/O",
                "readReplicas": {},
                "replicationLag": "00:00:09.061918",
                "role": "HA",
                "status": "ONLINE",
                "version": "8.0.18"
            },
            "db3:3306": {
                "address": "db3:3306",
                "mode": "R/O",
                "readReplicas": {},
                "replicationLag": "00:00:09.447804",
                "role": "HA",
                "status": "ONLINE",
                "version": "8.0.18"
            }
        },
        "topologyMode": "Single-Primary"
    },
    "groupInformationSourceMember": "db1:3306"
}

Đầu ra khá dài nhưng chúng ta có thể lọc ra bằng cách sử dụng cấu trúc bản đồ. Ví dụ:nếu chúng ta chỉ muốn xem độ trễ của bản sao cho db3, chúng ta có thể làm như sau:

MySQL|db1:3306 ssl|JS> cluster.status().defaultReplicaSet.topology["db3:3306"].replicationLag
00:00:09.447804

Lưu ý rằng độ trễ sao chép là điều gì đó sẽ xảy ra trong sao chép nhóm, tùy thuộc vào cường độ ghi của thành viên chính trong tập hợp bản sao và các biến group_replication_flow_control_ *. Chúng tôi sẽ không trình bày chi tiết về chủ đề này ở đây. Hãy xem bài đăng trên blog này để hiểu thêm về hiệu suất nhân rộng của nhóm và kiểm soát luồng.

Một hàm tương tự khác là hàm description (), nhưng hàm này đơn giản hơn một chút. Nó mô tả cấu trúc của cụm bao gồm tất cả thông tin của nó, ReplicaSets và Instances:

MySQL|db1:3306 ssl|JS> cluster.describe()
{
    "clusterName": "my_innodb_cluster",
    "defaultReplicaSet": {
        "name": "default",
        "topology": [
            {
                "address": "db1:3306",
                "label": "db1:3306",
                "role": "HA"
            },
            {
                "address": "db2:3306",
                "label": "db2:3306",
                "role": "HA"
            },
            {
                "address": "db3:3306",
                "label": "db3:3306",
                "role": "HA"
            }
        ],
        "topologyMode": "Single-Primary"
    }
}

Tương tự, chúng ta có thể lọc đầu ra JSON bằng cách sử dụng cấu trúc bản đồ:

MySQL|db1:3306 ssl|JS> cluster.describe().defaultReplicaSet.topologyMode
Single-Primary

Khi nút chính gặp sự cố (trong trường hợp này là db1), kết quả trả về như sau:

MySQL|db1:3306 ssl|JS> cluster.status()
{
    "clusterName": "my_innodb_cluster",
    "defaultReplicaSet": {
        "name": "default",
        "primary": "db2:3306",
        "ssl": "REQUIRED",
        "status": "OK_NO_TOLERANCE",
        "statusText": "Cluster is NOT tolerant to any failures. 1 member is not active",
        "topology": {
            "db1:3306": {
                "address": "db1:3306",
                "mode": "n/a",
                "readReplicas": {},
                "role": "HA",
                "shellConnectError": "MySQL Error 2013 (HY000): Lost connection to MySQL server at 'reading initial communication packet', system error: 104",
                "status": "(MISSING)"
            },
            "db2:3306": {
                "address": "db2:3306",
                "mode": "R/W",
                "readReplicas": {},
                "replicationLag": null,
                "role": "HA",
                "status": "ONLINE",
                "version": "8.0.18"
            },
            "db3:3306": {
                "address": "db3:3306",
                "mode": "R/O",
                "readReplicas": {},
                "replicationLag": null,
                "role": "HA",
                "status": "ONLINE",
                "version": "8.0.18"
            }
        },
        "topologyMode": "Single-Primary"
    },
    "groupInformationSourceMember": "db2:3306"
}

Hãy chú ý đến trạng thái OK_NO_TOLERANCE, trong đó cụm vẫn đang hoạt động nhưng nó không thể chịu đựng thêm bất kỳ lỗi nào sau khi một trên ba nút không khả dụng. Vai trò chính đã được db2 tự động tiếp quản và các kết nối cơ sở dữ liệu từ ứng dụng sẽ được định tuyến lại đến đúng nút nếu chúng kết nối thông qua Bộ định tuyến MySQL. Sau khi db1 trực tuyến trở lại, chúng ta sẽ thấy trạng thái sau:

MySQL|db1:3306 ssl|JS> cluster.status()
{
    "clusterName": "my_innodb_cluster",
    "defaultReplicaSet": {
        "name": "default",
        "primary": "db2:3306",
        "ssl": "REQUIRED",
        "status": "OK",
        "statusText": "Cluster is ONLINE and can tolerate up to ONE failure.",
        "topology": {
            "db1:3306": {
                "address": "db1:3306",
                "mode": "R/O",
                "readReplicas": {},
                "replicationLag": null,
                "role": "HA",
                "status": "ONLINE",
                "version": "8.0.18"
            },
            "db2:3306": {
                "address": "db2:3306",
                "mode": "R/W",
                "readReplicas": {},
                "replicationLag": null,
                "role": "HA",
                "status": "ONLINE",
                "version": "8.0.18"
            },
            "db3:3306": {
                "address": "db3:3306",
                "mode": "R/O",
                "readReplicas": {},
                "replicationLag": null,
                "role": "HA",
                "status": "ONLINE",
                "version": "8.0.18"
            }
        },
        "topologyMode": "Single-Primary"
    },
    "groupInformationSourceMember": "db2:3306"
}

Nó cho thấy rằng db1 hiện đã có sẵn nhưng được coi là thứ yếu với chế độ chỉ đọc được bật. Vai trò chính vẫn được chỉ định cho db2 cho đến khi có sự cố xảy ra với nút, nơi nó sẽ tự động bị lỗi đối với nút có sẵn tiếp theo.

Kiểm tra Trạng thái Phiên bản

Chúng ta có thể kiểm tra trạng thái của một nút MySQL trước khi lên kế hoạch thêm nó vào cụm bằng cách sử dụng hàm checkInstanceState (). Nó phân tích phiên bản GTID được thực thi với các GTID được thực thi / đã thanh lọc trên cụm để xác định xem phiên bản có hợp lệ cho cụm hay không.

Phần sau hiển thị trạng thái phiên bản của db3 khi nó ở chế độ độc lập, trước một phần của cụm:

MySQL|db1:3306 ssl|JS> cluster.checkInstanceState("db3:3306")
Cluster.checkInstanceState: The instance 'db3:3306' is a standalone instance but is part of a different InnoDB Cluster (metadata exists, instance does not belong to that metadata, and Group Replication is not active).

Nếu nút đã là một phần của cụm, bạn sẽ nhận được như sau:

MySQL|db1:3306 ssl|JS> cluster.checkInstanceState("db3:3306")
Cluster.checkInstanceState: The instance 'db3:3306' already belongs to the ReplicaSet: 'default'.

Giám sát Bất kỳ Trạng thái "Có thể Truy vấn" nào

Với MySQL Shell, giờ đây chúng ta có thể sử dụng lệnh \ show and \ watch tích hợp sẵn để theo dõi bất kỳ truy vấn quản trị nào trong thời gian thực. Ví dụ:chúng ta có thể lấy giá trị thời gian thực của các luồng được kết nối bằng cách sử dụng:

MySQL|db1:3306 ssl|JS> \show query SHOW STATUS LIKE '%thread%';

Hoặc lấy danh sách quy trình MySQL hiện tại:

MySQL|db1:3306 ssl|JS> \show query SHOW FULL PROCESSLIST

Sau đó, chúng ta có thể sử dụng lệnh \ watch để chạy một báo cáo theo cách tương tự như lệnh \ show, nhưng nó làm mới kết quả theo định kỳ cho đến khi bạn hủy lệnh bằng Ctrl + C. Như minh họa trong các ví dụ sau:

MySQL|db1:3306 ssl|JS> \watch query SHOW STATUS LIKE '%thread%';
MySQL|db1:3306 ssl|JS> \watch query --interval=1 SHOW FULL PROCESSLIST

Khoảng thời gian làm mới mặc định là 2 giây. Bạn có thể thay đổi giá trị bằng cách sử dụng cờ --interval và chỉ định một giá trị từ 0,1 đến 86400.

Hoạt động quản lý cụm MySQL InnoDB

Công tắc chuyển mạch chính

Phiên bản chính là nút có thể được coi là người dẫn đầu trong một nhóm sao chép, có khả năng thực hiện các thao tác đọc và ghi. Chỉ cho phép một phiên bản chính cho mỗi cụm trong chế độ cấu trúc liên kết chính đơn. Cấu trúc liên kết này còn được gọi là tập hợp bản sao và là chế độ cấu trúc liên kết được đề xuất cho Nhân bản nhóm với khả năng bảo vệ chống xung đột khóa.

Để thực hiện chuyển đổi phiên bản chính, hãy đăng nhập vào một trong các nút cơ sở dữ liệu với tư cách là người dùng clusteradmin và chỉ định nút cơ sở dữ liệu mà bạn muốn quảng bá bằng cách sử dụng hàm setPrimaryInstance ():

MySQL|db1:3306 ssl|JS> shell.connect("[email protected]:3306");
MySQL|db1:3306 ssl|JS> cluster.setPrimaryInstance("db1:3306");
Setting instance 'db1:3306' as the primary instance of cluster 'my_innodb_cluster'...

Instance 'db2:3306' was switched from PRIMARY to SECONDARY.
Instance 'db3:3306' remains SECONDARY.
Instance 'db1:3306' was switched from SECONDARY to PRIMARY.

WARNING: The cluster internal session is not the primary member anymore. For cluster management operations please obtain a fresh cluster handle using <Dba>.getCluster().

The instance 'db1:3306' was successfully elected as primary.

Chúng tôi vừa quảng bá db1 làm thành phần chính mới, thay thế db2 trong khi db3 vẫn là nút phụ.

Tắt Cụm

Cách tốt nhất để tắt cụm một cách duyên dáng bằng cách dừng dịch vụ Bộ định tuyến MySQL trước (nếu nó đang chạy) trên máy chủ ứng dụng:

$ myrouter/stop.sh

Bước trên cung cấp khả năng bảo vệ cụm khỏi các ứng dụng ghi ngẫu nhiên. Sau đó tắt từng nút cơ sở dữ liệu tại một thời điểm bằng cách sử dụng lệnh dừng MySQL tiêu chuẩn hoặc thực hiện tắt hệ thống như bạn muốn:

$ systemctl stop mysql

Khởi động Cụm sau khi Tắt máy

Nếu cụm của bạn bị ngừng hoạt động hoàn toàn hoặc bạn muốn khởi động cụm sau khi tắt hoàn toàn, bạn có thể đảm bảo rằng nó được định cấu hình lại chính xác bằng cách sử dụng hàm dba.rebootClusterFromCompleteOutage (). Nó chỉ đơn giản là đưa một nhóm trở lại ONLINE khi tất cả các thành viên đang NGOẠI TUYẾN. Trong trường hợp một cụm đã dừng hoàn toàn, các phiên bản phải được bắt đầu và chỉ khi đó cụm mới có thể được bắt đầu.

Do đó, hãy đảm bảo tất cả các máy chủ MySQL được khởi động và chạy. Trên mọi nút cơ sở dữ liệu, hãy xem quá trình mysqld có đang chạy hay không:

$ ps -ef | grep -i mysql

Sau đó, chọn một máy chủ cơ sở dữ liệu làm nút chính và kết nối với nó thông qua MySQL shell:

MySQL|JS> shell.connect("[email protected]:3306");

Chạy lệnh sau từ máy chủ đó để khởi động chúng:

MySQL|db1:3306 ssl|JS> cluster = dba.rebootClusterFromCompleteOutage()

Bạn sẽ được giải đáp những câu hỏi sau:

Sau khi hoàn thành ở trên, bạn có thể xác minh trạng thái cụm:

MySQL|db1:3306 ssl|JS> cluster.status()

Tại thời điểm này, db1 là nút chính và là trình ghi. Phần còn lại sẽ là các thành viên phụ. Nếu bạn muốn bắt đầu cụm với db2 hoặc db3 là chính, bạn có thể sử dụng hàm shell.connect () để kết nối với nút tương ứng và thực hiện khởi động lạiClusterFromCompleteOutage () từ nút cụ thể đó.

Sau đó, bạn có thể khởi động dịch vụ Bộ định tuyến MySQL (nếu nó chưa được khởi động) và để ứng dụng kết nối lại với cụm.

Đặt Tùy chọn Cụm và Thành viên

Để nhận các tùy chọn trên toàn cụm, chỉ cần chạy:

MySQL|db1:3306 ssl|JS> cluster.options()

Ở trên sẽ liệt kê các tùy chọn chung cho tập hợp bản sao và cả các tùy chọn riêng lẻ cho mỗi thành viên trong cụm. Chức năng này thay đổi tùy chọn cấu hình Cụm InnoDB trong tất cả các thành viên của cụm. Các tùy chọn được hỗ trợ là:

  • clusterName:giá trị chuỗi để xác định tên cụm.
  • exitStateAction:giá trị chuỗi biểu thị hành động trạng thái thoát sao chép nhóm.
  • memberWeight:giá trị số nguyên với tỷ lệ phần trăm cho cuộc bầu cử sơ bộ tự động khi chuyển đổi dự phòng.
  • failoverConsistency:giá trị chuỗi biểu thị sự đảm bảo nhất quán mà cụm cung cấp.
  • nhất quán:giá trị chuỗi biểu thị sự đảm bảo nhất quán mà cụm cung cấp.
  • expelTimeout:giá trị số nguyên để xác định khoảng thời gian tính bằng giây mà các thành viên trong cụm phải đợi một thành viên không phản hồi trước khi loại bỏ thành viên đó khỏi cụm.
  • autoRejoinTries:giá trị số nguyên để xác định số lần một phiên bản sẽ cố gắng tham gia lại cụm sau khi bị loại bỏ.
  • disableClone:​​giá trị boolean được sử dụng để vô hiệu hóa việc sử dụng bản sao trên cụm.

Tương tự như các chức năng khác, đầu ra có thể được lọc trong cấu trúc bản đồ. Lệnh sau sẽ chỉ liệt kê các tùy chọn cho db2:

MySQL|db1:3306 ssl|JS> cluster.options().defaultReplicaSet.topology["db2:3306"]

Bạn cũng có thể lấy danh sách trên bằng cách sử dụng hàm help ():

MySQL|db1:3306 ssl|JS> cluster.help("setOption")

Lệnh sau hiển thị một ví dụ để đặt một tùy chọn có tên là memberWeight thành 60 (từ 50) trên tất cả các thành viên:

MySQL|db1:3306 ssl|JS> cluster.setOption("memberWeight", 60)
Setting the value of 'memberWeight' to '60' in all ReplicaSet members ...

Successfully set the value of 'memberWeight' to '60' in the 'default' ReplicaSet.

Chúng tôi cũng có thể thực hiện quản lý cấu hình tự động thông qua MySQL Shell bằng cách sử dụng hàm setInstanceOption () và chuyển máy chủ cơ sở dữ liệu, tên tùy chọn và giá trị tương ứng:

MySQL|db1:3306 ssl|JS> cluster = dba.getCluster()
MySQL|db1:3306 ssl|JS> cluster.setInstanceOption("db1:3306", "memberWeight", 90)

Các tùy chọn được hỗ trợ là:

  • exitStateAction:giá trị chuỗi biểu thị hành động trạng thái thoát sao chép nhóm.
  • memberWeight:giá trị số nguyên với tỷ lệ phần trăm cho cuộc bầu cử sơ bộ tự động khi chuyển đổi dự phòng.
  • autoRejoinTries:giá trị số nguyên để xác định số lần một phiên bản sẽ cố gắng tham gia lại cụm sau khi bị loại bỏ.
  • gắn nhãn mã định danh chuỗi của phiên bản.

Chuyển sang Chế độ Đa chính / Một chế độ chính

Theo mặc định, InnoDB Cluster được cấu hình với single-primary, chỉ một thành viên có khả năng thực hiện đọc và ghi tại một thời điểm nhất định. Đây là cách an toàn nhất và được khuyến nghị để chạy cụm và phù hợp với hầu hết các khối lượng công việc.

Tuy nhiên, nếu logic ứng dụng có thể xử lý các lần ghi phân tán, có lẽ bạn nên chuyển sang chế độ đa chính, nơi tất cả các thành viên trong cụm có thể xử lý đọc và ghi cùng một lúc. Để chuyển từ chế độ đơn chính sang chế độ đa chính, chỉ cần sử dụng hàm switchToMultiPrimaryMode ():

MySQL|db1:3306 ssl|JS> cluster.switchToMultiPrimaryMode()
Switching cluster 'my_innodb_cluster' to Multi-Primary mode...

Instance 'db2:3306' was switched from SECONDARY to PRIMARY.
Instance 'db3:3306' was switched from SECONDARY to PRIMARY.
Instance 'db1:3306' remains PRIMARY.

The cluster successfully switched to Multi-Primary mode.

Xác minh bằng:

MySQL|db1:3306 ssl|JS> cluster.status()
{
    "clusterName": "my_innodb_cluster",
    "defaultReplicaSet": {
        "name": "default",
        "ssl": "REQUIRED",
        "status": "OK",
        "statusText": "Cluster is ONLINE and can tolerate up to ONE failure.",
        "topology": {
            "db1:3306": {
                "address": "db1:3306",
                "mode": "R/W",
                "readReplicas": {},
                "replicationLag": null,
                "role": "HA",
                "status": "ONLINE",
                "version": "8.0.18"
            },
            "db2:3306": {
                "address": "db2:3306",
                "mode": "R/W",
                "readReplicas": {},
                "replicationLag": null,
                "role": "HA",
                "status": "ONLINE",
                "version": "8.0.18"
            },
            "db3:3306": {
                "address": "db3:3306",
                "mode": "R/W",
                "readReplicas": {},
                "replicationLag": null,
                "role": "HA",
                "status": "ONLINE",
                "version": "8.0.18"
            }
        },
        "topologyMode": "Multi-Primary"
    },
    "groupInformationSourceMember": "db1:3306"
}

Trong chế độ nhiều nút chính, tất cả các nút đều là nút chính và có thể xử lý đọc và ghi. Khi gửi một kết nối mới qua Bộ định tuyến MySQL trên cổng ghi đơn (6446), kết nối sẽ chỉ được gửi đến một nút, như trong ví dụ này, db1:

(app-server)$ for i in {1..3}; do mysql -usbtest -p -h192.168.10.40 -P6446 -e 'select @@hostname, @@read_only, @@super_read_only'; done

+------------+-------------+-------------------+
| @@hostname | @@read_only | @@super_read_only |
+------------+-------------+-------------------+
| db1        | 0           | 0                 |
+------------+-------------+-------------------+

+------------+-------------+-------------------+
| @@hostname | @@read_only | @@super_read_only |
+------------+-------------+-------------------+
| db1        | 0           | 0                 |
+------------+-------------+-------------------+

+------------+-------------+-------------------+
| @@hostname | @@read_only | @@super_read_only |
+------------+-------------+-------------------+
| db1        | 0           | 0                 |
+------------+-------------+-------------------+

Nếu ứng dụng kết nối với cổng nhiều người viết (6447), kết nối sẽ được cân bằng tải thông qua thuật toán round robin cho tất cả các thành viên:

(app-server)$ for i in {1..3}; do mysql -usbtest -ppassword -h192.168.10.40 -P6447 -e 'select @@hostname, @@read_only, @@super_read_only'; done

+------------+-------------+-------------------+
| @@hostname | @@read_only | @@super_read_only |
+------------+-------------+-------------------+
| db2        | 0           | 0                 |
+------------+-------------+-------------------+

+------------+-------------+-------------------+
| @@hostname | @@read_only | @@super_read_only |
+------------+-------------+-------------------+
| db3        | 0           | 0                 |
+------------+-------------+-------------------+

+------------+-------------+-------------------+
| @@hostname | @@read_only | @@super_read_only |
+------------+-------------+-------------------+
| db1        | 0           | 0                 |
+------------+-------------+-------------------+

Như bạn có thể thấy từ đầu ra ở trên, tất cả các nút đều có khả năng xử lý đọc và ghi với read_only =OFF. Bạn có thể phân phối các bản ghi an toàn cho tất cả các thành viên bằng cách kết nối với cổng nhiều người ghi (6447) và gửi các bản ghi xung đột hoặc nặng tới cổng một người ghi (6446).

Để chuyển về chế độ đơn chính, hãy sử dụng hàm switchToSinglePrimaryMode () và chỉ định một thành viên làm nút chính. Trong ví dụ này, chúng tôi chọn db1:

MySQL|db1:3306 ssl|JS> cluster.switchToSinglePrimaryMode("db1:3306");

Switching cluster 'my_innodb_cluster' to Single-Primary mode...

Instance 'db2:3306' was switched from PRIMARY to SECONDARY.
Instance 'db3:3306' was switched from PRIMARY to SECONDARY.
Instance 'db1:3306' remains PRIMARY.

WARNING: Existing connections that expected a R/W connection must be disconnected, i.e. instances that became SECONDARY.

The cluster successfully switched to Single-Primary mode.

Tại thời điểm này, db1 bây giờ là nút chính được định cấu hình với chế độ chỉ đọc bị vô hiệu hóa và phần còn lại sẽ được định cấu hình là nút phụ với chỉ đọc được bật.

MySQL InnoDB Cluster Scaling Operations

Mở rộng quy mô (Thêm nút DB mới)

Khi thêm một phiên bản mới, một nút phải được cấp phép trước trước khi nó được phép tham gia vào nhóm sao chép. Quá trình cung cấp sẽ được xử lý tự động bởi MySQL. Ngoài ra, bạn có thể kiểm tra trạng thái phiên bản trước xem nút có hợp lệ để tham gia cụm hay không bằng cách sử dụng hàm checkInstanceState () như đã giải thích trước đó.

Để thêm một nút DB mới, hãy sử dụng hàm addInstances () và chỉ định máy chủ:

MySQL|db1:3306 ssl|JS> cluster.addInstance("db3:3306")

Sau đây là những gì bạn sẽ nhận được khi thêm một phiên bản mới:

Xác minh kích thước cụm mới với:

MySQL|db1:3306 ssl|JS> cluster.status() //or cluster.describe()

Bộ định tuyến MySQL sẽ tự động đưa nút được thêm vào, db3 vào bộ cân bằng tải.

Giảm tỷ lệ (Xóa nút)

Để xóa một nút, hãy kết nối với bất kỳ nút nào trong số các nút DB ngoại trừ nút mà chúng ta sẽ xóa và sử dụng hàm removeInstance () với tên phiên bản cơ sở dữ liệu:

MySQL|db1:3306 ssl|JS> shell.connect("[email protected]:3306");
MySQL|db1:3306 ssl|JS> cluster = dba.getCluster()
MySQL|db1:3306 ssl|JS> cluster.removeInstance("db3:3306")

Sau đây là những gì bạn sẽ nhận được khi xóa một phiên bản:

Xác minh kích thước cụm mới với:

MySQL|db1:3306 ssl|JS> cluster.status() //or cluster.describe()

Bộ định tuyến MySQL sẽ tự động loại trừ nút đã loại bỏ, db3 khỏi bộ cân bằng tải.

Thêm một nô lệ sao chép mới

Chúng ta có thể mở rộng Cụm InnoDB với các bản sao nô lệ sao chép không đồng bộ từ bất kỳ nút cụm nào. Một nô lệ được liên kết lỏng lẻo với cụm và sẽ có thể xử lý tải nặng mà không ảnh hưởng đến hiệu suất của cụm. Nô lệ cũng có thể là một bản sao trực tiếp của cơ sở dữ liệu cho các mục đích khôi phục sau thảm họa. Trong chế độ đa chính, bạn có thể sử dụng máy chủ làm bộ xử lý chỉ đọc MySQL chuyên dụng để mở rộng khối lượng công việc đọc, thực hiện hoạt động phân tích hoặc như một máy chủ dự phòng chuyên dụng.

Trên máy chủ nô lệ, tải xuống gói cấu hình APT mới nhất, cài đặt nó (chọn MySQL 8.0 trong trình hướng dẫn cấu hình), cài đặt khóa APT, cập nhật repolist và cài đặt máy chủ MySQL.

$ wget https://repo.mysql.com/apt/ubuntu/pool/mysql-apt-config/m/mysql-apt-config/mysql-apt-config_0.8.14-1_all.deb
$ dpkg -i mysql-apt-config_0.8.14-1_all.deb
$ apt-key adv --recv-keys --keyserver ha.pool.sks-keyservers.net 5072E1F5
$ apt-get update
$ apt-get -y install mysql-server mysql-shell

Sửa đổi tệp cấu hình MySQL để chuẩn bị máy chủ cho nô lệ sao chép. Mở tệp cấu hình qua trình soạn thảo văn bản:

$ vim /etc/mysql/mysql.conf.d/mysqld.cnf

Và nối các dòng sau:

server-id = 1044 # must be unique across all nodes
gtid-mode = ON
enforce-gtid-consistency = ON
log-slave-updates = OFF
read-only = ON
super-read-only = ON
expire-logs-days = 7

Khởi động lại máy chủ MySQL trên máy chủ để áp dụng các thay đổi:

$ systemctl restart mysql

Trên một trong các máy chủ Cụm InnoDB (chúng tôi chọn db3), tạo một người dùng nô lệ nhân bản và theo sau là một kết xuất MySQL đầy đủ:

$ mysql -uroot -p
mysql> CREATE USER 'repl_user'@'192.168.0.44' IDENTIFIED BY 'password';
mysql> GRANT REPLICATION SLAVE ON *.* TO 'repl_user'@'192.168.0.44';
mysql> exit
$ mysqldump -uroot -p --single-transaction --master-data=1 --all-databases --triggers --routines --events > dump.sql

Chuyển tệp kết xuất từ ​​db3 sang tệp phụ:

$ scp dump.sql [email protected]:~

Và thực hiện khôi phục trên nô lệ:

$ mysql -uroot -p < dump.sql

Với master-data =1, tệp kết xuất MySQL của chúng tôi sẽ tự động định cấu hình giá trị được thực thi và xóa GTID. Chúng tôi có thể xác minh điều đó bằng câu lệnh sau trên máy chủ nô lệ sau khi khôi phục:

$ mysql -uroot -p
mysql> show global variables like '%gtid_%';
+----------------------------------+----------------------------------------------+
| Variable_name                    | Value                                        |
+----------------------------------+----------------------------------------------+
| binlog_gtid_simple_recovery      | ON                                           |
| enforce_gtid_consistency         | ON                                           |
| gtid_executed                    | d4790339-0694-11ea-8fd5-02f67042125d:1-45886 |
| gtid_executed_compression_period | 1000                                         |
| gtid_mode                        | ON                                           |
| gtid_owned                       |                                              |
| gtid_purged                      | d4790339-0694-11ea-8fd5-02f67042125d:1-45886 |
+----------------------------------+----------------------------------------------+

Có vẻ tốt. Sau đó, chúng tôi có thể định cấu hình liên kết sao chép và bắt đầu các chuỗi sao chép trên máy chủ:

mysql> CHANGE MASTER TO MASTER_HOST = '192.168.10.43', MASTER_USER = 'repl_user', MASTER_PASSWORD = 'password', MASTER_AUTO_POSITION = 1;
mysql> START SLAVE;

Xác minh trạng thái sao chép và đảm bảo trạng thái sau trả về 'Có':

mysql> show slave status\G
...
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
...

Tại thời điểm này, kiến ​​trúc của chúng tôi hiện đang trông như thế này:

Các vấn đề thường gặp với MySQL InnoDB Cluster

cạn kiệt bộ nhớ

Khi sử dụng MySQL Shell với MySQL 8.0, chúng tôi liên tục gặp lỗi sau khi các phiên bản được định cấu hình với 1GB RAM:

Can't create a new thread (errno 11); if you are not out of available memory, you can consult the manual for a possible OS-dependent bug (MySQL Error 1135)

Nâng cấp RAM của mỗi máy chủ lên 2GB RAM đã giải quyết được vấn đề. Rõ ràng, các thành phần của MySQL 8.0 yêu cầu nhiều RAM hơn để hoạt động hiệu quả.

Mất kết nối với Máy chủ MySQL

In case the primary node goes down, you would probably see the "lost connection to MySQL server error" when trying to query something on the current session:

MySQL|db1:3306 ssl|JS> cluster.status()
Cluster.status: Lost connection to MySQL server during query (MySQL Error 2013)

MySQL|db1:3306 ssl|JS> cluster.status()
Cluster.status: MySQL server has gone away (MySQL Error 2006)

The solution is to re-declare the object once more:

MySQL|db1:3306 ssl|JS> cluster = dba.getCluster()
<Cluster:my_innodb_cluster>
MySQL|db1:3306 ssl|JS> cluster.status()

At this point, it will connect to the newly promoted primary node to retrieve the cluster status.

Node Eviction and Expelled

In an event where communication between nodes is interrupted, the problematic node will be evicted from the cluster without any delay, which is not good if you are running on a non-stable network. This is what it looks like on db2 (the problematic node):

2019-11-14T07:07:59.344888Z 0 [ERROR] [MY-011505] [Repl] Plugin group_replication reported: 'Member was expelled from the group due to network failures, changing member status to ERROR.'
2019-11-14T07:07:59.371966Z 0 [ERROR] [MY-011712] [Repl] Plugin group_replication reported: 'The server was automatically set into read only mode after an error was detected.'

Meanwhile from db1, it saw db2 was offline:

2019-11-14T07:07:44.086021Z 0 [Warning] [MY-011493] [Repl] Plugin group_replication reported: 'Member with address db2:3306 has become unreachable.'
2019-11-14T07:07:46.087216Z 0 [Warning] [MY-011499] [Repl] Plugin group_replication reported: 'Members removed from the group: db2:3306'

To tolerate a bit of delay on node eviction, we can set a higher timeout value before a node is being expelled from the group. The default value is 0, which means expel immediately. Use the setOption() function to set the expelTimeout value:

Thanks to Frédéric Descamps from Oracle who pointed this out:

Instead of relying on expelTimeout, it's recommended to set the autoRejoinTries option instead. The value represents the number of times an instance will attempt to rejoin the cluster after being expelled. A good number to start is 3, which means, the expelled member will try to rejoin the cluster for 3 times, which after an unsuccessful auto-rejoin attempt, the member waits 5 minutes before the next try.

To set this value cluster-wide, we can use the setOption() function:

MySQL|db1:3306 ssl|JS> cluster.setOption("autoRejoinTries", 3)
WARNING: Each cluster member will only proceed according to its exitStateAction if auto-rejoin fails (i.e. all retry attempts are exhausted).

Setting the value of 'autoRejoinTries' to '3' in all ReplicaSet members ...

Successfully set the value of 'autoRejoinTries' to '3' in the 'default' ReplicaSet.

Kết luận

For MySQL InnoDB Cluster, most of the management and monitoring operations can be performed directly via MySQL Shell (only available from MySQL 5.7.21 and later).


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. MySQL Chèn vào nhiều bảng? (Chuẩn hóa cơ sở dữ liệu?)

  2. Làm thế nào để chuyển đổi thời gian MySQL

  3. Codeigniter - nhiều kết nối cơ sở dữ liệu

  4. Có khả năng ANY_VALUE cho mysql 5.6 không?

  5. Cách nhập tệp CSV vào bảng MySQL