MySQL和MariaDB

我们都知道,MariaDB是MySQL的一个分支,那么他们之间的区别在哪呢?

图片

图片

图片

图片

MariaDB和Mysql的主要区别:

  • MariaDB有12个新的存储引擎,而MySQL有较少的存储引擎。

  • MariaDB具有更大的连接池,最多支持200,000个以上的连接,而MySQL具有较小的连接池。

  • 在MariaDB中,复制速度较快,而在MySQL中,复制速度较慢。

  • MariaDB是开源的,而MySQL在其企业版中使用了一些专有代码。

  • MariaDB不支持数据屏蔽和动态列,而MySQL支持。

  • 相对而言,MariaDB比MySQL快。


从市场份额看,MySQL比MariaDB还是要高非常多。




MySQL和MariaDB的复制技术


MySQL最简单的是异步复制,如下图所示:主实例可读写,备实例可读。

主备复制的架构图如下:传统的数据主从辅助属于异步复制,从库起IO线程连接主库,获取主库二进制日志写到本地中继日志,并更新master-info文件(存放主库相关信息),从库再利用SQL线程执行中继日志。

半同步复制是建立在基本的主从复制基础上,利用插件完成半同步复制,传统的主从复制,不管从库是否正确获取到二进制日志,主库不断更新,半同步复制则当确认了从库把二进制日志写入中继日志才会允许提交,如果从库迟迟不返回ack,主库会自动将半同步复制状态取消,进入最基本的主从复制模式。



第二种技术是组复制,简称MGR:

图片

MGR是MySQL官方于2016年12月推出的一个全新的高可用与高扩展的解决方案。MGR是MySQL官方在5.7.17版本引进的一个数据库高可用与高扩展的解决方案,以插件形式提供,实现了分布式下数据的最终一致性, 它是MySQL5.7版本出现的新特性,它提供了高可用、高扩展、高可靠的MySQL集群服务。


组复制是一种可用于实现容错系统的技术。复制组是一个通过消息传递相互交互的server集群。复制组由多个server成员组成,如上图的master1,master2,master3,所有成员独立完成各自的事务。当客户端先发起一个更新事务,该事务先在本地执行,执行完成之后就要发起对事务的提交操作了。在还没有真正提交之前需要将产生的复制写集广播出去,复制到其他成员。如果冲突检测成功,组内决定该事务可以提交,其他成员可以应用,否则就回滚。最终,这意味着所有组内成员以相同的顺序接收同一组事务。因此组内成员以相同的顺序应用相同的修改,保证组内数据强一致性。

图片

新成员加入组的简单流程:


  1. 当有新的成员加入组中,组内原有的成员会在二进制日志中插入一个视图切换的事件。

  2. 在组成员内找到一个donor捐赠之前缺失的数据,如果这个donor突然下线了,新成员会从新的donor获取缺失的数据,这时候组还在不断更新,新成员会将新的事件写到内存的一个临时空间

  3. 当获取到视图切换事件的时候,新成员将开始执行保存到内存临时空间的事件


MariaDB的复制主要有主备复制(和MySQL类似)和Galera两种,目前没看到类似MGR的技术。这里不再展开讨论。





OpenShift提供的MySQL容器镜像

如果我们想要实现MySQL的容器化,怎么做的?

红帽OpenShift提供MySQL的容器化镜像,可以看到最新的是MySQL 8.0.

图片

容器镜像安全程度很高:

图片

查看镜像dockerfile的部分内容,镜像基于RHEL8.1

图片

图片

查看容器镜像的package list:




以最简单的方式运行MySQL容器镜像

使用红帽提供的MySQL镜像,最简单的方法是直接运行(实验的时候,我们使用基于rhel7的mysql8镜像):

podman run -d --name mysql_database -e MYSQL_USER=user -e MYSQL_PASSWORD=pass -e MYSQL_DATABASE=db -p 3306:3306 rhscl/mysql-80-rhel7

查看运行的mysql容器:

上面展示的是最简单的运行mysql容器镜像的方式。这个镜像包含的环境变量和解释如下。

MYSQL_USERUser name for MySQL account to be created
MYSQL_PASSWORDPassword for the user account
MYSQL_DATABASEDatabase name
MYSQL_ROOT_PASSWORDPassword for the root user (optional)
The following environment variables influence the MySQL configuration file. They are all optional.
MYSQL_LOWER_CASE_TABLE_NAMES (default: 0)Sets how the table names are stored and compared
MYSQL_MAX_CONNECTIONS (default: 151)The maximum permitted number of simultaneous client connections
MYSQL_MAX_ALLOWED_PACKET (default: 200M)The maximum size of one packet or any generated/intermediate string
MYSQL_FT_MIN_WORD_LEN (default: 4)The minimum length of the word to be included in a FULLTEXT index
MYSQL_FT_MAX_WORD_LEN (default: 20)The maximum length of the word to be included in a FULLTEXT index
MYSQL_AIO (default: 1)Controls the innodb_use_native_aio setting value in case the native AIO is broken. See http://help.directadmin.com/item.php?id=529
MYSQL_TABLE_OPEN_CACHE (default: 400)The number of open tables for all threads
MYSQL_KEY_BUFFER_SIZE (default: 32M or 10% of available memory)The size of the buffer used for index blocks
MYSQL_SORT_BUFFER_SIZE (default: 256K)The size of the buffer used for sorting
MYSQL_READ_BUFFER_SIZE (default: 8M or 5% of available memory)The size of the buffer used for a sequential scan
MYSQL_INNODB_BUFFER_POOL_SIZE (default: 32M or 50% of available memory)The size of the buffer pool where InnoDB caches table and index data
MYSQL_INNODB_LOG_FILE_SIZE (default: 8M or 15% of available memory)The size of each log file in a log group
MYSQL_INNODB_LOG_BUFFER_SIZE (default: 8M or 15% of available memory)The size of the buffer that InnoDB uses to write to the log files on disk
MYSQL_DEFAULTS_FILE (default: /etc/my.cnf)Point to an alternative configuration file
MYSQL_BINLOG_FORMAT (default: statement)Set sets the binlog format, supported values are row and statementMYSQL_LOG_QUERIES_ENABLED (default: 0)To enable query logging set this to 1
MYSQL_DEFAULT_AUTHENTICATION_PLUGIN (default: caching_sha2_password)Set default authentication plugin. Accepts values mysql_native_password or caching_sha2_password.
You can also set the following mount points by passing the -v /host:/container flag to Docker./var/lib/mysql/dataMySQL data directory
当使用--memory参数集运行MySQL映像并且您未为某些参数指定值时,它们的值将根据可用内存自动计算。MYSQL_KEY_BUFFER_SIZE (default: 10%)key_buffer_size
MYSQL_READ_BUFFER_SIZE (default: 5%)read_buffer_size
MYSQL_INNODB_BUFFER_POOL_SIZE (default: 50%)innodb_buffer_pool_size
MYSQL_INNODB_LOG_FILE_SIZE (default: 15%)innodb_log_file_size
MYSQL_INNODB_LOG_BUFFER_SIZE (default: 15%)innodb_log_buffer_size


模板部署mysql

在上面小节中,我们使用pod直接运行mysql容器镜像,在生产上这样做显然是不合适的。我们可以通过mysql的模板在OCP上进行部署:

图片

可以直接部署mysql 8.0:

图片

部署成功:

# oc get pods |grep -i davidmysql-david-1-deploy      0/1     Completed   0          57smysql-david-1-qfvqm       1/1     Running     0          49s oc new-app mysql-80-rhel7:30~https://github.com/sclorg/mysql-container.git \

这种部署的方式也很方便。




定制化部署mysql

接下来,我们展示定制化部署mysql。使用S2I的方式进行定制化。builder image就是本文开头展示的mysql8.0镜像。s2i的源码地址:https://github.com/sclorg/mysql-container.git


首先导入红帽mysql容器镜像的is:

 oc import-image rhscl/mysql-80-rhel7 --from=registry.access.redhat.com/rhscl/mysql-80-rhel7 --confirm --all


接下来,利用image stream定制化部署mysql:

 oc new-app mysql-80-rhel7:30~https://github.com/sclorg/mysql-container.git \--name my-mysql-rhel7 \--context-dir=examples/extend-image \--env MYSQL_OPERATIONS_USER=opuser \--env MYSQL_OPERATIONS_PASSWORD=oppass \--env MYSQL_DATABASE=opdb \--env MYSQL_USER=user \--env MYSQL_PASSWORD=pass

我们查看上面输入参数examples/extend-image对应的目录:

mysql-cfg/ 启动容器时,该目录中的文件将用作mysqld守护程序的配置。在此文件上运行envsubst命令以仍然允许使用环境变量自定义镜像:

mysql-container/examples/extend-image/mysql-cfg/myconfig.cnf[mysqld]stored_program_cache = 524288--env MYSQL_USER=user \--env MYSQL_PASSWORD=pass


mysql-pre-init/ 此目录中可用的Shell脚本(* .sh)是在启动mysqld守护程序之前获取的。

mysql-container/examples/extend-image/mysql-data/init.sql
CREATE TABLE products (id INTEGER, name VARCHAR(256), price FLOAT, variant INTEGER);CREATE TABLE products_variant (id INTEGER, name VARCHAR(256));INSERT INTO products_variant (id, name) VALUES ('1', 'blue'), ('2', 'green');

mysql-init/ 在本地启动mysqld守护程序时,将获得此目录中可用的mysql-init / Shell脚本(* .sh)。在此阶段,使用$ {mysql_flags}连接到本地运行的守护程序,例如mysql $ mysql_flags <dump.sql

mysql-container/examples/extend-image/mysql-init/80-add-arbitrary-users.shcreate_arbitrary_users() {  # Do not care what option is compulsory here, just create what is specified  log_info "Creating user specified by MYSQL_OPERATIONS_USER (${MYSQL_OPERATIONS_USER}) ..."mysql $mysql_flags <<EOSQL    CREATE USER '${MYSQL_OPERATIONS_USER}'@'%' IDENTIFIED BY '${MYSQL_OPERATIONS_PASSWORD}';EOSQL

 log_info "Granting privileges to user ${MYSQL_OPERATIONS_USER} for ${MYSQL_DATABASE} ..."mysql $mysql_flags <<EOSQL      GRANT ALL ON \`${MYSQL_DATABASE}\`.* TO '${MYSQL_OPERATIONS_USER}'@'%' ;      FLUSH PRIVILEGES ;EOSQL}

if ! [ -v MYSQL_RUNNING_AS_SLAVE ]; then  create_arbitrary_usersfi

mysql-container/examples/extend-image/mysql-init/90-init-db.shinit_arbitrary_database() {  local thisdir  local init_data_file  thisdir=$(dirname ${BASH_SOURCE[0]})  init_data_file=$(readlink -f ${thisdir}/../mysql-data/init.sql)  log_info "Initializing the arbitrary database from file ${init_data_file}..."  mysql $mysql_flags ${MYSQL_DATABASE} < ${init_data_file}}

if ! [ -v MYSQL_RUNNING_AS_SLAVE ] && $MYSQL_DATADIR_FIRST_INIT ; then  init_arbitrary_databasefi



可以在提供给s2i的脚本中使用的变量:


mysql工具的$ mysql_flags参数,它将在初始化期间连接到本地运行的mysqld

$ MYSQL_RUNNING_AS_MASTER变量在使用run-mysqld-master命令运行容器时定义

$ MYSQL_RUNNING_AS_SLAVE变量,在使用run-mysqld-slave命令运行容器时定义


从空数据目录初始化容器时定义的$ MYSQL_DATADIR_FIRST_INIT变量


在s2i构建期间,将所有提供的文件复制到/opt/app-root/src目录中,并复制到结果镜像中。如果目标目录中存在某些配置文件,则具有相同名称的文件将被覆盖。同样,只有一个具有相同名称的文件可用于自定义,并且用户提供的文件比/usr/share/container-scripts/mysql /-中的默认文件更可取,因此可以覆盖它们。



查看mysql部署部分日志:

[[email protected] /opt/davidwei-cluster1/data]# oc logs -f my-mysql-rhel7-2-5lnts=> sourcing 20-validate-variables.sh ...=> sourcing 25-validate-replication-variables.sh ...=> sourcing 30-base-config.sh ...---> 16:35:48     Processing basic MySQL configuration files ...=> sourcing 60-replication-config.sh ...=> sourcing 70-s2i-config.sh ...---> 16:35:48     Processing additional arbitrary  MySQL configuration provided by s2i ...=> sourcing 20-default-authentication-plugin.cnf ...=> sourcing 40-paas.cnf ...=> sourcing 50-my-tuning.cnf ...---> 16:35:48     Initializing database ...---> 16:35:48     Running /opt/rh/rh-mysql80/root/usr/libexec/mysqld --initialize --datadir=/var/lib/mysql/data---> 16:35:53     Starting MySQL server with disabled networking ...---> 16:35:53     Waiting for MySQL to start ...---> 16:35:54     Waiting for MySQL to start ...2020-03-27T16:35:53.690350Z 0 [Warning] [MY-011070] [Server] 'Disabling symbolic links using --skip-symbolic-links (or equivalent) is the default. Consider not using this option as it' is deprecated and will be removed in a future release.2020-03-27T16:35:53.700015Z 0 [System] [MY-010116] [Server] /opt/rh/rh-mysql80/root/usr/libexec/mysqld (mysqld 8.0.17) starting as process 852020-03-27T16:35:54.410486Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed.2020-03-27T16:35:54.459936Z 0 [System] [MY-010931] [Server] /opt/rh/rh-mysql80/root/usr/libexec/mysqld: ready for connections. Version: '8.0.17'  socket: '/tmp/mysql.sock'  port: 0  Source distribution.2020-03-27T16:35:54.486976Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Socket: '/var/lib/mysql/mysqlx.sock'---> 16:35:55     MySQL started successfullymysql: [Warning] Using a password on the command line interface can be insecure.The mysql_upgrade client is now deprecated. The actions executed by the upgrade client are now done by the server.To upgrade, please start the new MySQL binary with the older data directory. Repairing user tables is done automatically. Restart is not required after upgrade.The upgrade process automatically starts on running a new MySQL binary with an older data directory. To avoid accidental upgrades, please use the --upgrade=NONE option with the MySQL binary. The option --upgrade=FORCE is also provided to run the server upgrade sequence on demand.It may be possible that the server upgrade fails due to a number of reasons. In that case, the upgrade sequence will run again during the next MySQL server start. If the server upgrade fails repeatedly, the server can be started with the --upgrade=MINIMAL option to start the server without executing the upgrade sequence, thus allowing users to manually rectify the problem.---> 16:35:55     Creating user specified by MYSQL_USER (user) ...---> 16:35:55     Creating database opdb ...---> 16:35:55     Granting privileges to user user for opdb ...---> 16:35:55     Initialization finished=> sourcing 40-datadir-action.sh ...---> 16:35:55     Running datadir action: upgrade-warn---> 16:35:55     Warning: Version of the data could not be determined. It is because the file mysql_upgrade_info is missing in the data directory, which is most probably because it was not created when initialization of data directory. In order to allow seamless updates to the next higher version in the future, the file mysql_upgrade_info will be created. If the data directory was created with a different version than 8.0, it is required to run this container with the MYSQL_DATADIR_ACTION environment variable set to 'force', or run 'mysql_upgrade' utility manually; the mysql_upgrade tool checks the tables and creates such a file as well. For upstream documentation about upgrading, see: https://dev.mysql.com/doc/refman/8.0/en/upgrading-from-previous-series.html---> 16:35:55     Storing version '8.0.17' information into the data dir '/var/lib/mysql/data/mysql_upgrade_info'=> sourcing 50-passwd-change.sh ...---> 16:35:55     Setting passwords ...---> 16:35:55     Shutting down MySQL ...2020-03-27T16:35:55.555498Z 15 [System] [MY-013172] [Server] Received SHUTDOWN from user root. Shutting down mysqld (Version: 8.0.17).2020-03-27T16:35:57.798891Z 0 [System] [MY-010910] [Server] /opt/rh/rh-mysql80/root/usr/libexec/mysqld: Shutdown complete (mysqld 8.0.17)  Source distribution.---> 16:35:58     Cleaning up environment variables MYSQL_USER, MYSQL_PASSWORD, MYSQL_DATABASE and MYSQL_ROOT_PASSWORD ...---> 16:35:58     Running final exec -- Only MySQL server logs after this point2020-03-27T16:35:58.909778Z 0 [Warning] [MY-011070] [Server] 'Disabling symbolic links using --skip-symbolic-links (or equivalent) is the default. Consider not using this option as it' is deprecated and will be removed in a future release.2020-03-27T16:35:58.911732Z 0 [System] [MY-010116] [Server] /opt/rh/rh-mysql80/root/usr/libexec/mysqld (mysqld 8.0.17) starting as process 12020-03-27T16:35:59.321049Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed.2020-03-27T16:35:59.353887Z 0 [System] [MY-010931] [Server] /opt/rh/rh-mysql80/root/usr/libexec/mysqld: ready for connections. Version: '8.0.17'  socket: '/var/lib/mysql/mysql.sock'  port: 3306  Source distribution.2020-03-27T16:35:59.460547Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Socket: '/var/lib/mysql/mysqlx.sock' bind-address: '::' port: 33060

对比git的源码内容gitclone后进行查看比对,可以从日志中看到了定制化脚本被执行:

[[email protected] /]# git clone https://github.com/sclorg/mysql-containerCloning into 'mysql-container'...
[[email protected] /]# cd mysql-container/[[email protected] /mysql-container]# ls5.5  5.6  5.7  8.0  common  examples  imagestreams  LICENSE  Makefile  README.md  root-common  s2i-common  test[[email protected] /mysql-container]# find ./ -name 50*./5.6/root-common/usr/share/container-scripts/mysql/cnf/50-my-tuning.cnf./5.6/root-common/usr/share/container-scripts/mysql/init/50-passwd-change.sh./root-common/usr/share/container-scripts/mysql/cnf/50-my-tuning.cnf./root-common/usr/share/container-scripts/mysql/init/50-passwd-change.sh


MySQL部署成功后如下图所示:

图片

 [[email protected] ~]# oc get svcNAME             TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGEmy-mysql-rhel7   ClusterIP   172.30.99.167   <none>        3306/TCP   20m[[email protected] ~]# oc rsh my-mysql-rhel7-1-zcwpc
sh-4.2$ mysql -h 172.30.99.167  -P 3306 -u user -ppassmysql: [Warning] Using a password on the command line interface can be insecure.Welcome to the MySQL monitor.  Commands end with ; or \g.Your MySQL connection id is 15Server version: 8.0.17 Source distributio
Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.Oracle is a registered trademark of Oracle Corporation and/or itsaffiliates. Other names may be trademarks of their respectiveowners.Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.mysql>


截止到目前,我们完成了在OpenShift中部署mysql单实例。




在OpenShift中部署MySQL复制


使用mysql主备复制模板进行部署。这是一个一主一从复制的模板。可以基于这个模板进行定制化。本文不做定制化修改:

(https://github.com/sclorg/mysql-container/blob/master/examples/replica/mysql_replica.json)

[[email protected] ~]# oc create -f mysql.jsontemplate.template.openshift.io/mysql-replication-example created

[[email protected] ~]# oc get templateNAME                        DESCRIPTION                 PARAMETERS        OBJECTSmysql-replication-example   MySQL Replication Example   8 (3 generated)   6

图片

图片


[[email protected] ~]# oc get podsNAME                      READY   STATUS              RESTARTS   AGEmy-mysql-rhel7-1-zcwpc    1/1     Running             0          42mmysql-master-2-deploy     1/1     Running             0          55smysql-master-2-zpvr5      0/1     ContainerCreating   0          47smysql-slave-2-deploy      1/1     Running             0          49smysql-slave-2-prlmq       0/1     ContainerCreating   0          41s
mysql> SHOW MASTER STATUS;
+------------------+----------+--------------+------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000002 |      107 | foo          |                  |
+------------------+----------+--------------+------------------+
1 row in set (0.00 sec)
mysql> SHOW SLAVE HOSTS;
+------------+-------------+------+------------+
| Server_id  | Host        | Port | Master_id  |
+------------+-------------+------+------------+
| 3314680171 | 172.17.0.20 | 3306 | 1301393349 |
| 3532875540 | 172.17.0.18 | 3306 | 1301393349 |
+------------+-------------+------+------------+
2 rows in set (0.01 sec)