前言

目前已完成:php7及扩展、redis5的Dockerfile测试版编写,稍许完善后同步上传到github,(记下这里memcached还没有剥离安装)。
今天数据库,编程的一个重要原则是不要重复造轮子,php因为需要很多自定义插件、所以单独编译镜像,其实其他包括redis都应该使用官方的,直接pull就行。


参考官方镜像,根据官方镜像,准备的mysql、mysql_slave文件树,添加了个数据文件夹。

[]:~/tmp/dk/mysql/mysql_slave# tree ./
./
├── config
│   ├── conf.d #后面修改my.cnf后删掉
│   │   └── docker.cnf
│   └── my.cnf
└── data

1、创建mysql镜像

[]:~/tmp/dk# docker pull mysql:8.0
# 清空旧数据库数据
[]:~/tmp/dk# rm -rf /root/tmp/dk/mysql/data/* /root/tmp/dk/mysql_slave/data/*
[]:~/tmp/dk# docker run --name mm -p 3306:3306 \
    -v /root/tmp/dk/mysql/data:/var/lib/mysql \
    -v /root/tmp/dk/mysql/config:/etc/mysql \
    -e MYSQL_ROOT_PASSWORD=123456  -d mysql:8.0
[]:~/tmp/dk# docker run --name ms -p 3308:3306 \
    -v /root/tmp/dk/mysql_slave/data:/var/lib/mysql \
    -v /root/tmp/dk/mysql_slave/config:/etc/mysql \
    -e MYSQL_ROOT_PASSWORD=123456  -d mysql:8.0

退出后台运行的容器,按 Ctrl+D 进行退出容器,请牢记!
run后运行的容器进入:

a.旧式进入     []:~/tmp/dk# docker attach mm
b.命令进入     []:~/tmp/dk# docker exec -it mm /bin/bash(或/bin/sh)

参考《Docker容器进入的4种方式
a.普通进入:有一个问题。当多个窗口同时使用该命令进入该容器时,所有的窗口都会同步显示。如果有一个窗口阻塞了,那么其他窗口也无法再进行操作。所以docker attach命令不太适合于生产环境,平时自己开发应用时可以使用该命令。
b.推荐

-- 小内存主机需要开启swap交换分区,并加入开机启动:

[]:~/tmp/dk# vim /etc/rc.local 
# +swap
swapon /swapfile

-- mysql的重启:
不能进入容器、在容器中重启,会报 Unable to lock ./ibdata1 error: 11 的错误,容器无法对共享文件加锁。

# 重启mysql容器
[]:~# docker restart mm

2、mysql配置

[mysqld]
user            = mysql
pid-file        = /var/run/mysqld/mysqld.pid
socket          = /var/run/mysqld/mysqld.sock
datadir         = /var/lib/mysql

# 主从赋值增加项
log-bin=mysql-bin        #[必须]启用二进制日志
server-id=1              #[必须]服务器唯一ID,默认是1
binlog-do-db=test            #要同步的数据库名,从服务器不需要这几项
binlog-ignore-db = mysql     #不同步mysql库和sys库
binlog-ignore-db = sys
replicate-ignore-db=mysql
secure-file-priv= NULL
# 忽略表名大小写
lower_case_table_names        = 1

character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
init_connect='SET NAMES utf8mb4'
#是否对sql语句大小写敏感,1表示不敏感
lower_case_table_names=1

#最大连接数
max_connections = 150
#最大错误连接数
max_connect_errors=1000
#TIMESTAMP如果没有显示声明NOT NULL,允许NULL值
explicit_defaults_for_timestamp=true

#SQL数据包发送的大小,如果有BLOB对象建议修改成1G
max_allowed_packet=2M
#MySQL连接闲置超过一定时间后(单位:秒)将会被强行关闭
#MySQL默认的wait_timeout  值为8个小时, interactive_timeout参数需要同时配置才能生效
interactive_timeout = 1800
wait_timeout = 1800

sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION

#时区
default-time_zone = '+8:00'

3、主从同步数据

在主服务器添加用于同步的账户。上需要主从服务器端配合完成

a.初始化同步用户

### 主服务器端
mysql> CREATE USER 'repl'@'%' IDENTIFIED WITH mysql_native_password BY 'Ron_master_1';
mysql> GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
mysql> flush privileges;
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000003 |      825 | test         | mysql,sys        |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
## 建议执行reset master: 删除所有的binglog日志文件,并将日志索引文件清空,重新开始所有新的日志文件。用于第一次进行搭建主从库时,进行主库binlog初始化工作
mysql> reset master;
mysql> show master status;

b.手动同步初始数据

添加测试数据,适合从一台拓展至多台服务器的情况。如果库数据已同步,跳过此步骤。
现在master中已有数据,需要先同步到slave,登录master,执行锁表操作

### 主服务-容器mm(master)主服务器添加初始库、表,及后续操作
mysql> create database test;
Query OK, 1 row affected (0.01 sec)

mysql> use test
Database changed
mysql> create table sys ( id int unsigned auto_increment primary key, `column` varchar(255) not null );
Query OK, 0 rows affected (0.03 sec)
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000003 |     1272 | test         | mysql,sys        |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
#只读锁表,等待复制
mysql> FLUSH TABLES WITH READ LOCK;
Query OK, 0 rows affected (0.01 sec)
# 等待主从关系建立完成后,解锁写入
mysql> UNLOCK TABLES;
Query OK, 0 rows affected (0.00 sec)
### 从服务-容器ms(slave):从服务器导入master的库数据
xx@fd8bb25a86fc:/# mysql -uroot -p123456
mysql> create database test;
Query OK, 1 row affected (0.01 sec)
mysql> quit
Bye
root@fd8bb25a86fc:/# mysqldump -uroot -p -h remote_host -P3306 test > /tmp/test.dump
Enter password: 
# 或直接use然后source file
root@fd8bb25a86fc:/# mysql -u root -p test < /tmp/test.dump

c.建立主从关系,完成同步

这里需要注意的参数是master_log_file、master_log_pos改为与master当前值相同。

### 容器ms(slave):从服务器添加
# 查询当前状态:show slave status\G; 重置复制状态参数:reset slave all; 关闭:stop slave;
# remote_host可以是 192.168.1.102 的内网、公网地址
mysql> change master to master_host='remote_host',master_port=3306,master_user='repl',\
    master_password='Ron_master_1',master_log_file='mysql-bin.000003',master_log_pos=1272;
Query OK, 0 rows affected, 2 warnings (0.01 sec)

mysql> start slave;
Query OK, 0 rows affected (0.00 sec)
#查询设置结果
mysql> show slave status\G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: xx.xx.xx.xx 
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000003
          Read_Master_Log_Pos: 1272
               Relay_Log_File: 6e9640cfaa53-relay-bin.000003
                Relay_Log_Pos: 322
        Relay_Master_Log_File: mysql-bin.000003
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
... ...

Slave_IO_Running和 Slave_SQL_Running都是Yes,说明主从复制已经开启成功。

4、非docker部署主从

a.主、从服务器配置

[mysqld]
; 唯一
server-id=10
; STATEMENT,ROW,MIXED
binlog_format = MIXED 
expire_logs_days = 7
log-bin = G:/mysql-8.0.30-winx64/mysql-bin.log
slow-query-log-file = G:/mysql-8.0.30-winx64/sql-slow.log

b.主服务器其它配置

; 中继日志
relay-log = G:/mysql-8.0.30-winx64/mysql-relay-bin.log
; 设置需要同步的数据库
binlog-do-db=app_system
binlog-do-db=gva
binlog-do-db=lawyer_platform
binlog-do-db=wenshu_court
; 设置忽略同步的数据库
binlog-ignore-db=information_schema
binlog-ignore-db=mysql
binlog-ignore-db=performance_schema
binlog-ignore-db=sys
binlog-ignore-db=test

c.从服务器其它配置

; 中继日志
relay-log = G:/mysql-8.0.30-winx64/mysql-relay-bin.log
; 设置需要同步的数据库
replicate_wild_do_table=app_system.%
replicate_wild_do_table=gva.%
replicate_wild_do_table=lawyer_platform.%
replicate_wild_do_table=wenshu_court.%
; 设置忽略同步的数据库
replicate_wild_ignore_table=information_schema.%
replicate_wild_ignore_table=mysql.%
replicate_wild_ignore_table=performance_schema.%
replicate_wild_ignore_table=sys.%
replicate_wild_ignore_table=test.%

小结

a.失败问题

Slave_IO_Running:Connecting ; Slave_SQL_Running: Yes

可能的错误原因:

1.网络不通,防火墙
2.账户密码错误

Slave_IO_Running:No ; Slave_SQL_Running: Yes
Last_IO_Error: Got fatal error 1236 from master when reading data from binary log: 'Could not open log file'

参考《MySQL主从error1236》:
做如下操作:

从库:
#停止主从关系
mysql>stop slave;
mysql>flush logs;
主库
#刷新binlog日志和pos号
mysql>flush logs;
mysql>show master status;

重新主从操作。

这其中遇到很多问题,比如:mysql的容器无法启动(配置文件问题,或使用现成配置好的,通过docker logs mm查看日志解决),无法从内部重启(搜索良久,应该是官方的问题,也确实没有从外部方便,只是对不是用mysql命令restart的别扭而已),主从复制没好(要点:my.cnf配置,锁表/确定不写入也行,master_log_file、master_log_pos参数)。
以前只是看过些,浮于理论,实践完成后才感觉通畅。


沧浪水
97 声望12 粉丝