Replication ของ MySQL

ว่าด้วยเรื่องการ Replication ของ MySQL เพื่อทำการ replicate ข้อมูลในฐานข้อมูล (database) จากเครื่องหลัก (Master) ไปยังเครื่องสำรอง (Slave) ได้

หลังจากที่คอนฟิก Replication ถูกต้องเรียบร้อย เมื่อมีการเปลี่ยนแปลงข้อมูลในฐานข้อมูลบนเครื่องหลัก (Master) ไม่ว่าจะเป็นการ INSERT, UPDATE, DELETE หรือ แก้ไข table การเปลี่ยนแปลงนี้จะถูกส่งต่อ (replicate) ไปยังเครื่องสำรอง (Slave) โดยอัตโนมัติ

การคอนฟิก Replication ส่วนใหญ่จะเป็นการ ทำเพือกระจายโหลดการทำงาน จากเครื่องหลัก ด้านการ Select ข้อมูล ไปยังเครื่อง Slave เพราะโดยธรรมชสติของการใช้งานแล้วเรามักจะใช้งานด้านการ Select มากกว่าการ INSERT, UPDATE, DELETE อยู่แล้ว ซึ่งในจุด นี้ ต้องเขียนให้ตัวซอฟแวร์สามารถรับรู้รองรับการแยกการ Select เครื่องด้วยน่ะครับ

1 ข้อควรจำใส่ใจ อย่างมาก Slave ต้องไม่มีการไปเขียนค่า INSERT, UPDATE, DELETE น่ะครับไม่งั้นข้อมูลจะเพี้ยนไม่ตรงกับเครื่องหลักเลยทีเดียว

2 ข้อควรจำสอง Replication เป็นการ ดึงข้อมูลจากตัวหลังตลอดเวลาให้ ตัว Slave มันมีข้อมูลเหมื่อนตัวแรก ไม่ใช้การแบล๊คอัพข้อมูลน่ะครับเกิดไปทำการที่ db ตัวหลักเสียหายเช่นไปลบ Slave ก็ ตามไปเหมื่อนกัน

ระบบทดสอบ

ตัวอย่างในบทความนี้ จะทดสอบบนเครื่องสองเครื่องที่ติดตั้ง CentOS 6.9 และ MySQL 5.1.73 ที่ติดตั้งผ่าน Yum ตามปกติ

เครื่อง Master

  • ip: 192.168.1.1
  • hostname: dba-mas

เครื่อง Slave

  • ip: 192.168.1.2
  • hostname: dba-slv

หมายเหตุ

yum install mysql-server ทั้งสองเครื่องให้เรียบร้อยน่ะครับถ้าเริ่มทำระบบใหม่ ๆ

ทั้งสองเครื่องต้อง ไม่ข้อมูล เท่า ๆ และ เหมื่อน ๆ กัน

ถ้า จะเพิ่ม slave หลังจาก ที่ระบบเดิมมีอยู่แล้ว ให้ mysqldump ข้อมูล จาก master มา slave ให้ข้อมูล ทั้งสองเครื่องตรงกันเป๊ะ ๆ ตรงนี้แนะนำว่าให้ปิดการบริการ master ระหว่างการทำงานไปน่ะ sync เสร็จค่อยเปิด

เครื่อง MASTER — สร้าง USER สำหรับ REPLICATION

เริ่มต้น ต้องสร้าง user ของ MySQL บนเครื่อง Master เพื่ออนุญาตสิทธิในการทำ ‘REPLICATION’ จากเครื่อง Slave คือสร้างสิทะ์ ให้เข้าไปอ่านได้นั่นแหละ หลักการคือมันจะวิ่งไปอ่านมาแล้วทำการ insert เข้าตัวมันเอง

ตัวอย่างการสร้าง user ชื่อ ‘repl’ และรหัส ‘repl1234’เพื่อให้สิทธิการทำ REPLICATION จากเครื่องที่มี ip 192.168.1.2

[root@dba-mas ~]# mysql -u root -pmysql> GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.1.2' IDENTIFIED BY 'repl1234';

เครื่อง MASTER — คอนฟิก REPLICATION MASTER

บนเครื่อง Master ปิดเซอร์วิส MySQL แล้วแก้ไขไฟล์ /etc/my.cnf เพื่อเปิดคุณสมบัติ binary log (log-bin) และเซ็ต server-id

[root@dba-mas ~]# service mysql stop
Shutting down MySQL..                                      [  OK  ]

ตัวอย่างไฟล์คอนฟิก /etc/my.cnf เพื่อคอนฟิกเป็น Replication Master

[root@dba-mas ~]# cat /etc/my.cnf
[mysqld]
log-bin=mysql-bin
server-id=1

ใช้คำสั่ง service เพื่อรันเซอร์วิส MySQL

[root@dba-mas ~]# service mysql start
Starting MySQL.                                            [  OK  ]

เครื่อง MASTER — ตรวจสอบสถานะของ MASTER BINARY LOG

บนเครื่อง Master ใช้คำสั่ง SHOW MASTER STATUS ตรวจสอบสถานะของ Master Binary Log

เราจะใช้ค่า ‘File’ และ ‘Position’ เพื่อระบุบนเครื่อง Slave

[root@dba-mas ~]# mysql -u root -pmysql> SHOW MASTER STATUS;
+------------------+----------+--------------+------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000001 |      224 |              |                  |
+------------------+----------+--------------+------------------+
1 row in set (0.00 sec)

เครื่อง SLAVE — คอนฟิก REPLICATION SLAVE

บนเครื่อง Slave ปิดเซอร์วิส MySQL เพื่อแก้ไขคอนฟิกไฟล์ /etc/my.cnf

[root@dba-slv ~]# service mysql stop
Shutting down MySQL..                                      [  OK  ]

เบื้องต้นบนเครื่อง Slave คอนฟิกแค่ ‘server-id’ ที่มีค่าแตกต่างจากเครื่อง Master

ถ้าทำ slave หลาย ๆ เครื่อง ก็เรียงเลข server-i d ไปครับอย่าให้เลขชนกันเป็นพอ

[root@dba-slv ~]# cat /etc/my.cnf
[mysqld]
server-id=2

รันเซอร์วิส MySQL บนเครื่อง Slave

[root@dba-slv ~]# service mysql start
Starting MySQL.                                            [  OK  ]

ใช้คำสั่ง CHANGE MASTER เพื่อระบุ ip ของ Master ชื่อ user, password ที่ใช้เพื่อการทำ Replication และต้องระบุค่า log_file (File) และ log_pos (Position) ที่ได้จากผลลัพธ์ในการรันคำสั่ง SHOW MASTER STATUS บนเครื่อง Master

mysql> CHANGE MASTER TO MASTER_HOST='192.168.1.1',
                        MASTER_USER='repl',
                        MASTER_PASSWORD='repl1234',
                        MASTER_LOG_FILE='mysql-bin.000001',
                        MASTER_LOG_POS=224;
Query OK, 0 rows affected (0.03 sec)

รันคำสั่ง START SLAVE เพื่อเริ่มต้นการทำ Replicate ข้อมูลจาก เครื่อง Master

mysql> START SLAVE;
Query OK, 0 rows affected (0.00 sec)

ตรวจสอบสถานะ Replication บนเครื่อง Slave

mysql> SHOW SLAVE STATUS \G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.1.1
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000001
          Read_Master_Log_Pos: 244
               Relay_Log_File: dba-slv-relay-bin.000004
                Relay_Log_Pos: 251
        Relay_Master_Log_File: mysql-bin.000001
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB:
          Replicate_Ignore_DB:
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table:
                   Last_Errno: 0
                   Last_Error:
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 244
              Relay_Log_Space: 411
              Until_Condition: None
               Until_Log_File:
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File:
           Master_SSL_CA_Path:
              Master_SSL_Cert:
            Master_SSL_Cipher:
               Master_SSL_Key:
        Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error:
               Last_SQL_Errno: 0
               Last_SQL_Error:
1 row in set (0.00 sec)

หากคอนฟิกถูกต้อง ค่า ‘Slave_IO_State’ จะแสดงเป็น ‘Waiting for master to send event’

ทดสอบการ REPLICATION

ทดสอบสร้าง database บนเครื่อง Master

[root@dba-mas ~]# mysql -u root -p
mysql> CREATE DATABASE test1;
Query OK, 1 row affected (0.01 sec)mysql> SHOW DATABASES;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| test1              |
+--------------------+
3 rows in set (0.00 sec)

ข้อมูลการสร้าง database จะถูกส่งต่อ (replicate) ไปยังเครื่อง Slave โดยอัตโนมัติ

[root@dba-slv ~]# mysql -u root -p
Enter password:
mysql> SHOW DATABASES;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| test1              |
+--------------------+
3 rows in set (0.00 sec)

สร้าง table และทดสอบการ INSERT ข้อมูล

[root@dba-mas ~]# mysql -u root -p
mysql> use test;
mysql> CREATE TABLE books (id INTEGER, name VARCHAR(255));
mysql> INSERT INTO books VALUES (1, 'data1');
mysql> INSERT INTO books VALUES (2, 'data2');mysql> SELECT * FROM books;
+------+-----------------+
| id   | name            |
+------+-----------------+
|    1 | data1  |
|    2 | data2  |
+------+-----------------+
2 rows in set (0.00 sec)

การเปลี่ยนแปลงบนเครื่อง Master จะถูก replicate ไปยังเครื่อง Slave โดยอัตโนมัติ

[root@dba-slv ~]# mysql -u root -p
mysql> use test;
mysql> SELECT * FROM books;
+------+-----------------+
| id   | name            |
+------+-----------------+
|    1 | data1  |
|    2 | data2  |
+------+-----------------+
2 rows in set (0.00 sec)