侧边栏壁纸
  • 累计撰写 88 篇文章
  • 累计创建 41 个标签
  • 累计收到 4 条评论

目 录CONTENT

文章目录

MySQL 生产环境数据迁移

已删除用户
2022-10-13 / 0 评论 / 0 点赞 / 157 阅读 / 0 字

此处默认为不可停服情况下的迁移,即不仅需要迁移数据,还需要主从同步,在相关服务全部更新到新 MySQL 上时才可停止原 MySQL。

环境准备

两台 IP 分别为192.168.137.151192.168.137.152的 Ubuntu Server 22.04.1,分别为 A、B 服务器,都安装 MySQL:

# 安装 MySQL 服务端
$ sudo apt install mysql-server

# 登录 MySQL
$ sudo mysql

# 设置 root 用户密码(至少 8 位),如果没有先设置而是设置新密码会报这个错 
# Re-enter new password:
#  ... Failed! Error: SET PASSWORD has no significance for user 'root'@'localhost' as the authentication method used doesn't store authentication data in the MySQL server. Please consider using ALTER USER instead if you want to change authentication parameters.
mysql> ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password by 'newpassword';
Query OK, 0 rows affected (0.01 sec)

# 运行 MySQL 安全向导
$ sudo mysql_secure_installation

Securing the MySQL server deployment.

# 输入刚刚设置的 root 密码
Enter password for user root: 
The 'validate_password' component is installed on the server.
The subsequent steps will run with the existing configuration
of the component.
Using existing password for root.

Estimated strength of the password: 50
Change the password for root ? ((Press y|Y for Yes, any other key for No) : n

 ... skipping.
By default, a MySQL installation has an anonymous user,
allowing anyone to log into MySQL without having to have
a user account created for them. This is intended only for
testing, and to make the installation go a bit smoother.
You should remove them before moving into a production
environment.

# 是否删除测试用的匿名用户,即 mysql 命令直接可以进入的情况
Remove anonymous users? (Press y|Y for Yes, any other key for No) : y
Success.


Normally, root should only be allowed to connect from
'localhost'. This ensures that someone cannot guess at
the root password from the network.

# 是否禁用 root 用户远程访问,因为是本地,为了方便我们就不禁用好了
Disallow root login remotely? (Press y|Y for Yes, any other key for No) : n

 ... skipping.
By default, MySQL comes with a database named 'test' that
anyone can access. This is also intended only for testing,
and should be removed before moving into a production
environment.

# 是否删除测试用的“test”数据库
Remove test database and access to it? (Press y|Y for Yes, any other key for No) : y
 - Dropping test database...
Success.

 - Removing privileges on test database...
Success.

Reloading the privilege tables will ensure that all changes
made so far will take effect immediately.

# 是否重新加载权限表
Reload privilege tables now? (Press y|Y for Yes, any other key for No) : y
Success.

All done!

# 下载官方测试数据库
$ wget https://codeload.github.com/datacharmer/test_db/zip/refs/heads/master
# 安装解压 zip 的包
$ sudo apt-get install unzip
# 解压缩
$ unzip master

$ cd test_db-master/
# 导入 MySQL 实例(导入后就可以删除下载的数据库和解压后的目录了)
$ mysql -uroot -p -t < employees.sql

主从设置

假设 A 服务器为主,B 服务器为从。

主数据库(A 服务器)

# 先配置 A 服务器的 my.cnf 文件,在 [mysqld] 后添加
$ sudo vim /etc/mysql/my.cnf
[mysqld]
# 服务器 ID,唯一
server-id=151
# 启用二进制日志系统
log-bin=mysql-bin
# 需要同步的数据库,如果为多个库则逗号分隔,如果为所有库则注释此行(除了 ignore 的库)
binlog-do-db=xxx
# 忽略同步的库,如果为多个库则逗号分隔
binlog-ignore-db=mysql
# 确保 binlog 日志写入后与硬盘同步
sync_binlog=1
# 跳过现有才有 checksum 的事件,MySQL 5.6.5 以后值为 crc32,之前为 none
binlog_checksum=crc32
# bin-log 日志文件格式,设置为 mixed 可以防止主键重复
binlog_format=mixed

# 注释配置文件中的 IP 绑定以支持远程访问
$ sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf
[mysqld]
……
#bind-address            = 127.0.0.1
……

# 重启 MySQL
$ systemctl restart mysql

$ mysql -uroot -p

# 创建远程用户并授权,稍后用于从库连接
mysql > create user 'root'@'%' identified with mysql_native_password by 'newpassword';
mysql > grant all on *.* to 'root'@'%';
mysql > flush privileges;

# 数据库只读锁定,防止导出时有数据写入,解除锁定为 unlock tables;
mysql > flush tables with read lock;

# 查看主数据库状态,注意 File 和 Position 列,一会儿需要用到
mysql > show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 |      157 | xxx          | mysql            |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

# 主库导出数据
$ mysqldump -uroot bakdb -p > /tmp/bakdb.sql

# 将数据文件同步到 B 服务器上
$ rsync -e "ssh -p22" -avpgolr /tmp/bakdb.sql 192.168.137.152:/tmp

从数据库(B 服务器)

# 同样的需要先配置 my.cnf,在 [mysqld] 后添加
$ sudo vim /etc/mysql/my.cnf
[mysqld]
# 服务器 ID,唯一
server-id=152
# 启用二进制日志系统
log-bin=mysql-bin
# 需要同步的数据库,如果为多个库则逗号分隔,如果为所有库则注释此行(除了 ignore 的库)
binlog-do-db=xxx
# 忽略同步的库,如果为多个库则逗号分隔
binlog-ignore-db=mysql
# 跳过所有错误,继续执行复制操作
slave-skip-errors=all

# 同样的需要创建远程用户并配置,用于测试,此处同上略

# 重启 MySQL
$ systemctl restart mysql

$ mysql -uroot -p

# 在从库中创建数据库并导入原始数据
mysql > create database newdb character set utf8mb4 collate utf8mb4_general_ci;
mysql > use newdb;
mysql > source /tmp/bakdb.sql;

从数据库(B 服务器)启用主从

$ mysql -uroot -p

# 主从配置
mysql > change master to master_host='192.168.137.151',master_user='root',master_password='rootpwd',master_log_file='mysql-bin.000001',master_log_pos=157;

# 重启链路
mysql > stop slave;
mysql > start slave;

# 查看链路:Slave_IO_Running 和 Slave_SQL_Running 都为 Yes 表示同步正常
mysql > show slave status \G;
*************************** 1. row ***************************
               Slave_IO_State: Connecting to source
                  Master_Host: 192.168.137.151
                  Master_User: root
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000001
          Read_Master_Log_Pos: 157
               Relay_Log_File: ubuntu-relay-bin.000001
                Relay_Log_Pos: 4
        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: 157
              Relay_Log_Space: 337
              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: 0
               Last_SQL_Error:
  Replicate_Ignore_Server_Ids:
             Master_Server_Id: 0
                  Master_UUID:
             Master_Info_File: mysql.slave_master_info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Replica has read all relay log; waiting for more updates
           Master_Retry_Count: 86400
                  Master_Bind:
      Last_IO_Error_Timestamp:
     Last_SQL_Error_Timestamp:
               Master_SSL_Crl:
           Master_SSL_Crlpath:
           Retrieved_Gtid_Set:
            Executed_Gtid_Set:
                Auto_Position: 0
         Replicate_Rewrite_DB:
                 Channel_Name:
           Master_TLS_Version:
       Master_public_key_path:
        Get_master_public_key: 0
            Network_Namespace:
1 row in set, 1 warning (0.00 sec)

ERROR:
No query specified

# 重置绑定
# mysql > reset master;
# 重置同步日志,需要先执行 stop slave;
# mysql > reset slave;

测试

  • 增删改查主数据库中的数据,查询从库中是否同步。✔️

最后再等和主数据库的相关服务的数据库地址都改成了从数据库,就可以关掉主从了。

参考

0

评论区