> For the complete documentation index, see [llms.txt](https://bohans.gitbook.io/ji-chu/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://bohans.gitbook.io/ji-chu/mysql/sql-you-hua/fu-zhi/an-zhuang/ji-yu-er-jin-zhi-ri-zhi-wen-jian-wei-zhi-de-fu-zhi.md).

# 基于二进制日志文件位置的复制

## 配置主节点

1. 修改主数据库服务器的配置文件 my.cnf，<mark style="color:blue;">**开启 BINLOG**</mark><mark style="color:blue;">，</mark>并<mark style="color:blue;">**设置 server-id 的值**</mark>。这两个参数的修改需要<mark style="color:orange;">**重新启动数据库服务**</mark>才可以生效。

   ```ini
   [mysqld]
   server-id=1
   log-bin=mysql-bin    # 一个相对路径，相对于 Data 存放的目录
   binlog_format=Row
   ```
2. 创建一个专门用于复制的用户，并授予 <mark style="color:blue;">**REPLICATION SLAVE**</mark> 的权限。

   <pre class="language-sql"><code class="lang-sql"><strong>CREATE USER 'repl'@'%' IDENTIFIED BY '123456';
   </strong><strong>GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
   </strong></code></pre>
3. 通过命令行客户端连接到源并启动一个会话，执行 <mark style="color:blue;">**FLUSH TABLES WITH READ LOCK**</mark> 语句来刷新所有表并阻止写入语句（这个操作是为了确保没有数据库操作，以便获得一个一致性的快照）。

   ```sql
   FLUSH TABLES WITH READ LOCK;
   ```
4. 启动另一个会话，使用 <mark style="color:blue;">**SHOW MASTER STATUS**</mark> 语句来确定当前的二进制日志文件名称和位置。

   ```sql
   SHOW MASTER STATUS\G;
   ```

   ```sql
   *************************** 1. row ***************************
                File: mysql-bin.000001
            Position: 154
        Binlog_Do_DB:
    Binlog_Ignore_DB:
   Executed_Gtid_Set:
   1 row in set (0.00 sec)
   ```

   **File** 列显示日志文件的名称，而 **Position** 列显示文件中的位置。在这个例子中，二进制日志文件是**mysql-bin.000003**，位置是 **154，**&#x5B83;们表示副本应该从主数据库开始处理的**复制坐标**。
5. 使用 <mark style="color:blue;">**mysqldump**</mark> 工具创建主数据库的快照（推荐使用 <mark style="color:blue;">**mysqldump**</mark> 特别是在使用 InnoDB 引擎时）。以下示例将所有数据库转储到名为 **dbdump.db** 的文件中，**包含 --master-data 选项会自动附加在副本上启动复制过程所需的 CHANGE MASTER TO 语句**：

   <pre class="language-properties"><code class="lang-properties"><strong>mysqldump -uroot -p --all-databases --master-data > dbdump.db
   </strong></code></pre>
6. **主数据库的备份完毕后，可以**<mark style="color:blue;">**恢复写操作**</mark>，剩下的操作只需要在从库上执行：

   <pre class="language-sql"><code class="lang-sql"><strong>UNLOCK TABLES;
   </strong></code></pre>

> 每个副本都使用 MySQL 的用户名和密码连接到主数据库，因此在主数据库上必须有一个用户帐户，副本可以使用该帐户进行连接。
>
> 当设置副本时，会通过 **CHANGE MASTER TO** 命令的 **MASTER\_USER** 选项指定用户名。**任何帐户都可以用于此操作，只要已授予 REPLICATION SLAVE 权限**。你可以选择为每个副本创建一个不同的帐户，或者使用相同的帐户连接到源。
>
> <mark style="color:orange;">**用于复制的用户名和密码会以明文的形式存储在从数据库元数据存储库中。因此，需要创建一个仅用于复制过程的帐户，以最小化对其他帐户的威胁。**</mark>

## 配置从节点

1. 修改从数据库的配置文件 my.cnf，<mark style="color:blue;">**增加 server-id 参数**</mark>。注意 <mark style="color:red;">**server-id 的值必须是唯一的**</mark>，不能和主数据库的配置相同，如果有多个从数据库服务器，每个从数据库服务器必须有自己唯一的 server-id值。

   ```ini
   [mysqld]
   server-id=10
   ```
2. 在从库上，使用 <mark style="color:blue;">**--skip-slave-start**</mark> 选项启动从数据库，这样不会立即启动从数据库服务上的复制进程，方便我们对从数据库的服务进行进一步的配置。
3. 将主库的快照文件（dbdump.db）复制到从节点服务器上，然后导入快照：

   ```properties
   mysql < dbdump.db
   ```
4. 对从数据库服务器做相应设置，指定复制使用的用户，主数据库服务器的 IP、端口以及开始执行复制的日志文件和位置等：

   ```ini
   CHANGE MASTER TO MASTER_HOST = '222.20.72.166',
       MASTER_USER = 'repl',
       MASTER_PASSWORD = '123456',
       MASTER_LOG_FILE = 'mysql-bin.000001',
       MASTER_LOG_POS = 154;
   ```
5. 启动 slave 线程：

   ```sql
   START SLAVE;
   ```
6. 查看复制状态：

   <pre class="language-sql" data-overflow="wrap"><code class="lang-sql">show slave status\G;
   *************************** 1. row ***************************
                  Slave_IO_State: Waiting for master to send event
                     Master_Host: 222.20.72.166
                     Master_User: repl
                     Master_Port: 3306
                   Connect_Retry: 60
                 Master_Log_File: mysql-bin.000001
             Read_Master_Log_Pos: 1249
                  Relay_Log_File: 1030dacf93dd-relay-bin.000002
                   Relay_Log_Pos: 614
           Relay_Master_Log_File: mysql-bin.000001
                Slave_IO_Running: Yes
               Slave_SQL_Running: No
                 Replicate_Do_DB: 
             Replicate_Ignore_DB: 
              Replicate_Do_Table: 
          Replicate_Ignore_Table: 
         Replicate_Wild_Do_Table: 
     Replicate_Wild_Ignore_Table: 
                      Last_Errno: 1049
                      Last_Error: Error 'Unknown database 'test'' on query. Default database: 'test'. Query: 'CREATE table test(id int)'
                    Skip_Counter: 0
             Exec_Master_Log_Pos: 448
                 Relay_Log_Space: 1629
                 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: NULL
   Master_SSL_Verify_Server_Cert: No
                   Last_IO_Errno: 0
                   Last_IO_Error: 
                  Last_SQL_Errno: 1049
                  Last_SQL_Error: Error 'Unknown database 'test'' on query. Default database: 'test'. Query: 'CREATE table test(id int)'
     Replicate_Ignore_Server_Ids: 
                Master_Server_Id: 1
                     Master_UUID: 2e7c13f7-92e1-11ec-b712-b42e99f272fa
                Master_Info_File: /var/lib/mysql/master.info
                       SQL_Delay: 0
             SQL_Remaining_Delay: NULL
         Slave_SQL_Running_State: 
              Master_Retry_Count: 86400
                     Master_Bind: 
         Last_IO_Error_Timestamp: 
        Last_SQL_Error_Timestamp: 231115 09:48:50
                  Master_SSL_Crl: 
              Master_SSL_Crlpath: 
              Retrieved_Gtid_Set: 
               Executed_Gtid_Set: 
                   Auto_Position: 0
            Replicate_Rewrite_DB: 
                    Channel_Name: 
              Master_TLS_Version: 
   1 row in set (0.01 sec)
   </code></pre>

> MySQL的复制功能并<mark style="color:orange;">**不要求副本必须启用二进制日志记录**</mark>。
>
> 但是，<mark style="color:blue;">**在副本上启用二进制日志记录意味着可以使用副本的二进制日志进行数据备份和崩溃恢复**</mark>。如果要在副本上启用二进制日志记录，可以在配置文件的 **\[mysqld]** 部分中使用 **log-bin** 选项。
>
> 对于之前未使用二进制日志的服务器，需要重新启动服务器以启动二进制日志记录。
