📜 ⬆️ ⬇️

Basics of replication in MySQL

I got acquainted with the replication of MySQL servers relatively recently, and as I went through various experiments with tuning, I wrote down what I did. When there was a lot of material, an idea to write this article appeared. I tried to collect advice and solutions on some of the most basic issues that I faced. Along the way, I will provide links to documentation and other sources. I can not claim to be complete description, but I hope that the article will be useful.

Small introduction


Replication (from lat. Replico-repeat) is the replication of data changes from the main database server on one or several dependent servers. The main server will be called the master , and dependent servers - replicas .
Data changes that occur on the wizard are repeated on the replicas (but not vice versa). Therefore, data change requests (INSERT, UPDATE, DELETE, etc.) are executed only on the master, and data read requests (in other words, SELECT) can be executed on both replicas and the master. The replication process on one of the replicas does not affect the operation of the other replicas, and practically does not affect the operation of the wizard.
Replication is performed using binary logs conducted on the master. They contain all the queries that lead (or potentially lead) to changes in the database (the queries are not saved explicitly, so if you want to see them, you will have to use the mysqlbinlog utility). Binlogs are transferred to replicas (binlog downloaded from the wizard is called " relay binlog ") and saved queries are executed starting from a specific position. It is important to understand that during replication, it is not the changed data that is transmitted, but only the requests that cause changes.
When replicating the contents of the database is duplicated on multiple servers. Why use duplication? There are several reasons:

In addition, there are some other interesting features. Since not the data itself is sent to the replicas, but the queries that cause their changes, we can use a different table structure on the master and the replicas. In particular, the type of the table (engine) or a set of indexes may differ. For example, to perform full-text search, we can use the MyISAM table type on a replica, even though the wizard will use InnoDB.

Replication setup


Suppose we have a working MySQL database, already filled with data and included in the work. And for one of the reasons described above, we are going to enable replication of our server. Our raw data:

Wizard settings

Be sure to specify the unique server ID, the path for binary logs and the name of the database for replication in the [mysqld] section:
server-id = 1
log-bin = /var/lib/mysql/mysql-bin
replicate-do-db = testdb

Make sure you have enough disk space for binary logs.

Let's add the user replication under which rights replication will be made. The " replication slave " privilege will suffice:
mysql@master> GRANT replication slave ON "testdb".* TO "replication"@"192.168.1.102" IDENTIFIED BY "password";

Restart MySQL so that the changes in the config take effect:
root@master# service mysqld restart

If everything went well, the show master status command should show something like the following:
mysql@master> SHOW MASTER STATUS\G
File: mysql-bin.000003
Position: 98
Binlog_Do_DB:
Binlog_Ignore_DB:

The position value should increase as changes are made to the database on the master.
')
Replica settings

Specify the server ID, the database name for replication and the path to the relay-binlog in the [mysqld] section of the config, then restart MySQL:
server-id = 2
relay-log = /var/lib/mysql/mysql-relay-bin
relay-log-index = /var/lib/mysql/mysql-relay-bin.index
replicate-do-db = testdb

root@replica# service mysqld restart


We transfer data

Here we have to block the database for writing. To do this, you can either stop the application, or use the read_only checkbox on the wizard (note: this flag does not apply to users with the SUPER privilege). If we have MyISAM tables, let's also do the " flush tables ":
mysql@master> FLUSH TABLES WITH READ LOCK;
mysql@master> SET GLOBAL read_only = ON;


Let's see the status of the wizard with the command “show master status” and remember the values ​​of File and Position (after successful blocking of the wizard they should not change)
File: mysql-bin.000003
Position: 98

, :

mysql@master> SET GLOBAL read_only = OFF;

.

Finally, start the replication with the " change master to " and " start slave " commands and see if everything went well:
mysql@replica> CHANGE MASTER TO MASTER_HOST = "192.168.1.101 ", MASTER_USER = "replication ", MASTER_PASSWORD = "password ", MASTER_LOG_FILE = "mysql-bin.000003 ", MASTER_LOG_POS = 98;
mysql@replica> start slave;

We take the values ​​MASTER_LOG_FILE and MASTER_LOG_POS from the wizard.

Let's see how replication goes with the " show slave status " command:
mysql@replica> SHOW SLAVE STATUS\G
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.1.101
Master_User: replication
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000003
Read_Master_Log_Pos: 98
Relay_Log_File: mysql-relay-bin.001152
Relay_Log_Pos: 235
Relay_Master_Log_File: mysql-bin.000003
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB: testdb,testdb
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: 98
Relay_Log_Space: 235
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: 5


I selected the most interesting values ​​now. When replication is successfully started, their values ​​should be approximately the same as in the listing (see the description of the " show slave status " command in the documentation). The value of Seconds_Behind_Master can be any integer.
If replication is normal, the replica will follow the master (the log number in Master_Log_File and the position Exec_Master_Log_Pos will increase). The replica lag time from the master (Seconds_Behind_Master) should ideally be zero. If it does not contract or grows, it is possible that the load on the replica is too high — it simply does not have time to repeat the changes that occur on the master.
If the value of Slave_IO_State is empty, and Seconds_Behind_Master is NULL, replication has not started. See the MySQL log for the cause, fix it and rerun the replication:
mysql @ replica> start slave;

By these simple actions we get a replica, the data of which is identical to the data on the master.
By the way, the master lock time is the time to create a dump. If it is created unacceptably long, you can try to do this:

There are several ways to create a replica without stopping the wizard at all, but they do not always work.

Add replicas


Suppose we already have a working master and replica, and we need to add one more to them. Make it even easier than adding the first cue to the master. And much nicer is that there is no need to stop for this master.
First, let's configure MySQL on the second replica and make sure that we have entered the necessary parameters into the config:
server-id = 3
replicate-do-db = testdb


Now stop replication on the first replica:
mysql@replica-1> stop slave;

The replica will continue to work normally, but the data on it will no longer be relevant. Let's look at the status and remember the position of the master, to which the replica reached before stopping replication:
mysql@replica-1> SHOW SLAVE STATUS\G

We will need the values ​​Master_Log_File and Exec_Master_Log_Pos:
Master_Log_File: mysql-bin.000004
Exec_Master_Log_Pos: 155


Create a database dump and continue replication on the first replica:
mysql@replica-1> START SLAVE;

Recover data from dump on second replica. Then turn on replication:
mysql@replica-2> CHANGE MASTER TO MASTER_HOST = "192.168.1.101 ", MASTER_USER = "replication ", MASTER_PASSWORD = "password ", MASTER_LOG_FILE = "mysql-bin.000004 ", MASTER_LOG_POS = 155;
mysql@replica-2> START SLAVE;


The MASTER_LOG_FILE and MASTER_LOG_POS values ​​are respectively the values ​​of Master_Log_File and Exec_Master_Log_Pos from the result of the show slave status command on the first replica.
Replication should start from the position where the first replica was stopped (and accordingly, a dump was created). Thus, we will have two replicas with identical data.

Merge replicas


Sometimes this situation occurs: on the master there are two databases, one of which is replicated on one replica, and the second on the other. How to configure replication of two databases on both replicas without dumping them on the master and turning it off from work? Simple enough, using the " start slave until " command.
So, we have a master with the testdb1 and testdb2 databases, which are replicated on replica-1 and replica-2 replicas respectively . Set up the replication of both databases to replica-1 without stopping the wizard.
Stop replication on the replica-2 command and remember the position of the master:
mysql@replica-2> STOP SLAVE;
mysql@replica-2> SHOW SLAVE STATUS\G
Master_Log_File: mysql-bin.000015
Exec_Master_Log_Pos: 231


Create a testdb2 database dump and resume replication (this is the end of the replica-2 manipulations). Dump restore to replica-1.

The situation on replica-1 is as follows: the testdb1 database is in one master position and continues to replicate, the testdb2 database is restored from the dump from a different position. Sync them.

Stop replication and remember the position of the wizard:
mysql@replica-1> STOP SLAVE;
mysql@replica-1> SHOW SLAVE STATUS\G
Master_Log_File: mysql-bin.000016

Exec_Master_Log_Pos: 501

Make sure that in the config on replica-1 in the [mysqld] section the name of the second database is indicated:
replicate-do-db = testdb2

Restart MySQL for changes to take effect. By the way, it was possible to simply restart MySQL without stopping replication - from the log we would know at what position the wizard stopped replication.

Now we will replicate from the position at which replica-2 was suspended to the position at which we have just suspended replication:
mysql@replica-1> CHANGE MASTER TO MASTER_HOST = "192.168.1.101 ", MASTER_USER = "replication ", MASTER_PASSWORD = "password ", MASTER_LOG_FILE = "mysql-bin.000015 ", MASTER_LOG_POS = 231;
mysql@replica-1> start slave until MASTER_LOG_FILE = "mysql-bin.000016 ", MASTER_LOG_POS = 501;


Replication will end as soon as the replica reaches the specified position in the until section, after which both our databases will correspond to the same master position (at which we stopped replication on replica-1). Make sure of this:
mysql@replica-1> SHOW SLAVE STATUS\G
mysql@replica-1> START SLAVE;
Master_Log_File: mysql-bin.000016
Exec_Master_Log_Pos: 501

replica-1 [mysqld] :

replicate-do-db = testdb1
replicate-do-db = testdb2

: .

Restart MySQL and continue replication:
mysql@replica-1> CHANGE MASTER TO MASTER_HOST = "192.168.1.101 ", MASTER_USER = "replication ", MASTER_PASSWORD = "password ", MASTER_LOG_FILE = "mysql-bin.000016 ", MASTER_LOG_POS = 501;
After replica-1 will catch up with the master, the contents of their database will be identical. You can merge the database into replica-2 either in a similar way, or by making a complete dump of replica-1.

Castling Wizard and Replicas


It is sometimes necessary to switch a replica to master mode, for example, in the event of a master failure or when carrying out technical work on it. To enable such a switch, you need to configure a replica like a master, or make it a passive master .

Let's enable binary logging (in addition to relay binlog) in the [mysqld] section of the config:
log-bin = /var/lib/mysql/mysql-bin

And add a user to maintain replication:
mysql@master> GRANT replication slave ON 'testdb'.* TO 'replication'@'192.168.1.101′ IDENTIFIED BY "password ";

The passive master replicates just like a regular replica, but other than that it creates binary logies - that is, we can begin replication from it. Verify this with the " show master status " command:
mysql@replica> SHOW MASTER STATUS\G
File: mysql-bin.000001
Position: 61
Binlog_Do_DB:
Binlog_Ignore_DB:


Now, to put the passive master into active mode, you need to stop replication on it and enable replication on the former active master. To prevent data loss at the moment of switching, the active master must be blocked for writing.
mysql@master> FLUSH TABLES WITH READ LOCK
mysql@master> SET GLOBAL read_only = ON;
mysql@replica> STOP SLAVE;
mysql@replica> SHOW MASTER STATUS;
File: mysql-bin.000001
Position: 61
mysql@master> CHANGE MASTER TO MASTER_HOST = "192.168.1.102 ", MASTER_USER = "replication ", MASTER_PASSWORD = "password ", MASTER_LOG_FILE = "mysql-bin.000001 ", MASTER_LOG_POS = 61;
mysql@master> start slave;

Everything, so we changed the active master. You can remove the lock from the former master.

Conclusion



We learned a little about how to set up replication in MySQL and perform some basic operations. Unfortunately, the following important questions were left out of the article:

I hope to highlight these issues in future articles.
Thanks for attention!

Source: https://habr.com/ru/post/56702/


All Articles