Skip to content

01 快速上手数据库安装部署

你好,我是俊达。今天我们开始MySQL运维课程的第一讲,快速上手数据库安装部署。

你可能会有一些疑问,现在云数据库发展得这么好,只需要在云平台下单,就能自动获取一个安装配置好的数据库。就算不用云数据库,企业内部多半也会有一些运维管理平台,可以按需创建数据库环境。为什么还要学数据库安装这么基础的知识?

对这个问题我是这么理解的:首先,安装数据库是了解一个数据库的第一步。通过安装部署,你可以了解数据库的核心组件,数据库由哪些文件组成,服务是怎么启动和停止的。

其次,要深入掌握一门数据库技术,离不开大量的实践操作。你在文档或书籍上看到的知识,需要在真实的数据库环境中进行测试验证,这不仅能验证你看到的内容是否正确,也能加深你对相关知识的理解。所以你需要从零开始搭建数据库、创建用户、配置数据库、搭建数据库高可用环境,测试和验证数据库的各种功能。

最后,虽然云数据库已经将大量数据库运维管理的动作自动化了,但是背后还是需要有人去设计和运维云平台本身,而你将来可能就是云数据库背后的那个人。而且,在工作中,你可能需要解决不同环境下的各种千奇百怪的数据库问题。系统地掌握数据库从安装部署到运维管理整个环节,能帮你更好地应对各种环境下的复杂问题。

接下来我们分别来学习二进制安装、RPM包安装和源码编译安装这几种安装方式。我们使用CentOS 7.9操作系统来运行MySQL。请记住, 我们的目标并不仅仅是安装MySQL,而是通过安装部署来深入理解MySQL的运行方式

二进制安装

使用二进制包安装MySQL是比较常用的一种方式,主要分为六个步骤。

  1. 获取二进制安装包。
  2. 创建运行MySQL的用户。
  3. 规划数据目录,准备my.cnf参数文件。
  4. 初始化数据库。
  5. 启动数据库服务。
  6. 设置数据库初始密码。

第一步:获取二进制安装包

先到MySQL官网下载二进制安装包,选择8.0 GA最新版本,当前8.0最新GA版本是8.0.39。

图片

注:MySQL一般3个月左右出一个新的小版本,你看到这里的时候,可能又出了新的版本,但基本上不影响文章后面的讨论。

使用二进制安装时,操作系统选择“Linux - Generic”,操作系统版本要根据系统的glibc版本来选择,我们可以使用一些方法来确定glibc的版本,比如通过ldd命令。

# ldd --version
ldd (GNU libc) 2.17

可以先用浏览器下载安装包,再上传到服务器,也可以直接在服务器上使用wget、curl等工具下载。

wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.39-linux-glibc2.17-x86_64.tar.xz

安装包下载完成后使用md5sum工具检查文件校验码是否和官网上提供的一致。

# md5sum  mysql-8.0.39-linux-glibc2.17-x86_64.tar.xz
1c092c3814b10bfa0794077867f9f4ad  mysql-8.0.39-linux-glibc2.17-x86_64.tar.xz

如果一切正常,解压二进制包,将解压后的文件夹放到一个安装目录下,这里我们将安装包放到/opt目录下,并创建一个软链接。

# tar xvf mysql-8.0.39-linux-glibc2.17-x86_64.tar.xz
# mv mysql-8.0.39-linux-glibc2.17-x86_64 /opt
# ln -s /opt/mysql-8.0.39-linux-glibc2.17-x86_64 /opt/mysql80

到这里,MySQL软件其实就已经安装好了。接下来,我们熟悉一下MySQL安装目录下都有哪些文件。

bin目录下包含MySQL的服务端和客户端,以及一些命令行工具。lib目录中有MySQL客户端库,使用C API访问MySQL数据库时,需要用到这里面的库文件。lib目录下还有一个plugin目录,存放着MySQL的各类插件,包括我们在后续课程中会介绍的CLONE插件、半同步插件、组复制(MGR)插件。include目录下是C API的头文件,编译访问MySQL的C代码时会用到这些文件。share目录下有一些运行MySQL需要用到的文件,如不同语言的错误日志信息文件、字符集的定义文件。

下面表格对其中一些重要文件做了简单介绍。

图片

第二步:创建运行MySQL的用户

出于安全考虑,我们需要创建一个单独的用户来运行MySQL。

groupadd mysql
useradd mysql -g mysql

第三步:规划数据目录,准备my.cnf参数文件

我们需要规划一个数据目录,用来存放MySQL的数据文件,以及各类日志文件。如果你部署的MySQL将用于生产,那么我建议你使用满足一定性能要求的磁盘设备,如SSD,以保障性能。

这里提供一种我平时使用的目录规划方式。

mkdir -p /data/mysql3306/{data,log,binlog,relaylog,run,tmp}
# tree -d -L 2 /data
/data
|-- mysql3306
|   |-- binlog
|   |-- data
|   |-- log
|   |-- relaylog
|   |-- run
|   `-- tmp
|-- mysql3307
|   |-- binlog
|   |-- data
|   |-- log
|   |-- relaylog
|   |-- run
|   `-- tmp

其中data是挂载点,把文件系统挂载到/data。每个实例的所有文件,都放在同一个顶层目录中,以 mysql{$PORT} 的方式命名。data目录用来存放数据库的数据文件。binlog和relaylog目录分别用来存放binlog和relaylog。log目录存放日志文件,包括错误日志、慢SQL日志。run目录存放pid文件和sock文件。tmp目录用来存放MySQL运行过程中可能会产生的临时文件。配置文件my.cnf存放到实例的顶层目录中。

在这个目录规划下,一个基本的配置文件如下:

## /data/mysql3306/my.cnf
[mysql]
socket=/data/mysql3306/run/mysql.sock

[mysqld]
port=3306
mysqlx_port=33060

basedir=/opt/mysql80
lc_messages_dir=/opt/mysql80/share

datadir=/data/mysql3306/data
tmpdir=/data/mysql3306/tmp
log-error=/data/mysql3306/log/alert.log
slow_query_log_file=/data/mysql3306/log/slow.log
general_log_file=/data/mysql3306/log/general.log
socket=/data/mysql3306/run/mysql.sock

innodb_data_file_path=ibdata1:128M:autoextend
innodb_buffer_pool_size=2G

第四步:初始化数据库

使用mysqld初始化数据库,第一个参数必须是defaults-file,指向上一步准备好的my.cnf配置文件,第二个参数是initialize,指示mysqld进行初始化操作。

# /opt/mysql80/bin/mysqld --defaults-file=/data/mysql3306/my.cnf --initialize

初始化可能需要一定的时间,完成后会在数据目录(datadir)下生成默认数据库和相关的系统表。

# tree -L 1 -u -h -F /data/mysql3306/data
/data/mysql3306/data
|-- [root     576K]  #ib_16384_0.dblwr
|-- [root     8.6M]  #ib_16384_1.dblwr
|-- [root     4.0K]  #innodb_redo/
|-- [root     4.0K]  #innodb_temp/
|-- [root       56]  auto.cnf
|-- [root     1.7K]  ca-key.pem
|-- [root     1.1K]  ca.pem
|-- [root     1.1K]  client-cert.pem
|-- [root     1.7K]  client-key.pem
|-- [root     5.8K]  ib_buffer_pool
|-- [root     128M]  ibdata1
|-- [root     4.0K]  mysql/
|-- [root      25M]  mysql.ibd
|-- [root     4.0K]  performance_schema/
|-- [root     1.7K]  private_key.pem
|-- [root      452]  public_key.pem
|-- [root     1.1K]  server-cert.pem
|-- [root     1.7K]  server-key.pem
|-- [root     4.0K]  sys/
|-- [root      16M]  undo_001
`-- [root      16M]  undo_002

如果初始化没有成功,需要到错误日志中查看相关的报错信息,进行相应的处理。错误日志的路径由配置文件中的参数log-error指定。初始化成功后,可以看到错误日志的最后一行输出的mysql root账号的临时密码,我们要用这个密码来登录数据库。

# tail -10 /data/mysql3306/log/alert.log
2024-06-24T01:56:48.849579Z 0 [System] [MY-013169] [Server] /opt/mysql80/bin/mysqld (mysqld 8.0.39) initializing of server in progress as process 5352
2024-06-24T01:56:48.863677Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
2024-06-24T01:57:30.863543Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
2024-06-24T01:57:55.476711Z 6 [Note] [MY-010454] [Server] A temporary password is generated for root@localhost: YB%OojGi85?L

数据库初始化完成后,就可以启动了,不过在启动前,还需要做一件事情。如果初始化数据库时使用了Linux的root账号,还需要把mysql目录下的文件owner修改成mysql。

chown -R mysql:mysql /data/mysql3306/

第五步:启动数据库服务

我们有几种不同的方式来启动MySQL服务,下面的例子使用mysqld_safe脚本来启动MySQL,使用defaults-file指定参数文件的路径。

# /opt/mysql80/bin/mysqld_safe --defaults-file=/data/mysql3306/my.cnf &
[1] 5569

# mysqld_safe Logging to '/data/mysql3306/log/alert.log'.
mysqld_safe Starting mysqld daemon with databases from /data/mysql3306/data

如果启动失败,需要到错误日志中查看具体的报错信息。比较常见的问题有端口已经被占用了,或者参数文件中参数名写错了。

# tail -10 /data/mysql3306/log/alert.log

2024-06-24T02:17:43.215483Z 0 [ERROR] [MY-010262] [Server] Can't start server: Bind on TCP/IP port: Address already in use
2024-06-24T02:17:43.215527Z 0 [ERROR] [MY-010257] [Server] Do you already have another mysqld server running on port: 3306 ?
2024-06-24T02:17:43.215560Z 0 [ERROR] [MY-010119] [Server] Aborting
2024-06-24T02:17:45.035093Z 0 [System] [MY-010910] [Server] /opt/mysql80/bin/mysqld: Shutdown complete (mysqld 8.0.39)  MySQL Community Server - GPL.

MySQL服务启动成功后,可以在错误日志中看到“ready for connections”的日志信息。

[Server] /opt/mysql80/bin/mysqld: ready for connections. Version: '8.0.39'  socket: '/data/mysql3306/run/mysql.sock'  port: 3306  MySQL Community Server - GPL.

第六步:设置数据库初始密码

MySQL在数据库初始化时设置了一个临时密码,可以在错误日志中找到。

# grep password /data/mysql3306/log/alert.log
2024-06-24T01:57:55.476711Z 6 [Note] [MY-010454] [Server] A temporary password is generated for root@localhost: YB%OojGi85?L

使用临时密码登录数据库后,执行SQL会提示要先修改密码。

# mysql -uroot -h127.0.0.1 -p'YB%OojGi85?L'

mysql> select now();
ERROR 1820 (HY000): You must reset your password using ALTER USER statement before executing this statement.

使用alter user命令修改mysql root账号的密码后,就可以正常使用数据库了。

mysql> alter user 'root'@'localhost' identified by 'Abcd1234';
Query OK, 0 rows affected (1.45 sec)

mysql> select now();
+---------------------+
| now()               |
+---------------------+
| 2024-06-24 11:09:23 |
+---------------------+
1 row in set (0.00 sec)

这就是使用二进制方式安装MySQL的整个过程,可以看到过程并不复杂。使用二进制安装的主要优点就是你可以很方便地部署多实例,在同一台服务器运行多个版本的MySQL,可以方便地规划磁盘路径。

RPM安装

使用Linux的包管理器安装MySQL也是一种比较常用的方式,这里我们以CentOS 7.9为例来简单说明安装过程。

第一步:下载RPM包

选择8.0当前的最新版本。由于我们使用了CentOS 7.9,操作系统选择“Red Hat Eenterrise Linux / Oracle Linux”,操作系统版本选择“Red Hat Enterprise Linux 7 / Oracle Linux 7(x86,64-bit)”。

图片

下载mysql-8.0.39-1.el7.x86_64.rpm-bundle.tar,里面包含了安装MySQL需要的所有rpm包。

wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.39-1.el7.x86_64.rpm-bundle.tar

下载完成后验证md5,并解压。

# md5sum mysql-8.0.39-1.el7.x86_64.rpm-bundle.tar
1f59378ee4a9b40791672eed61366f52  mysql-8.0.39-1.el7.x86_64.rpm-bundle.tar

# tar xf mysql-8.0.39-1.el7.x86_64.rpm-bundle.tar

第二步:处理有冲突的包

如果服务器上已经安装了其他版本的MySQL或MariaDB的RPM包,就有可能会和待安装的RPM包发生冲突,需要先把这些RPM包卸载掉。注意,在生产环境卸载已经安装的包可能会引起问题,需要在服务器上线前就处理好这些问题。

# rpm -qa | egrep -i 'mysql|mariadb'
mariadb-libs-5.5.68-1.el7.x86_64

# yum remove mariadb-libs
Resolving Dependencies
......

Removed:
  mariadb-libs.x86_64 1:5.5.68-1.el7

Dependency Removed:
  postfix.x86_64 2:2.10.1-9.el7

第三步:安装RPM包

使用RPM命令安装RPM包,把server、client以及依赖的lib包都安装上。

# rpm -ivh mysql-community-libs-8.0.39-1.el7.x86_64.rpm \
  mysql-community-client-8.0.39-1.el7.x86_64.rpm \
  mysql-community-libs-compat-8.0.39-1.el7.x86_64.rpm \
  mysql-community-client-plugins-8.0.39-1.el7.x86_64.rpm \
  mysql-community-server-8.0.39-1.el7.x86_64.rpm \
  mysql-community-common-8.0.39-1.el7.x86_64.rpm \
  mysql-community-icu-data-files-8.0.39-1.el7.x86_64.rpm

warning: mysql-community-libs-8.0.39-1.el7.x86_64.rpm: Header V4 RSA/SHA256 Signature, key ID a8d3785c: NOKEY
  Preparing...                          ################################# [100%]
Updating / installing...
   1:mysql-community-common-8.0.39-1.e################################# [ 14%]
   2:mysql-community-client-plugins-8.################################# [ 29%]
   3:mysql-community-libs-8.0.39-1.el7################################# [ 43%]
   4:mysql-community-client-8.0.39-1.e################################# [ 57%]
   5:mysql-community-icu-data-files-8.################################# [ 71%]
   6:mysql-community-server-8.0.39-1.e################################# [ 86%]
   7:mysql-community-libs-compat-8.0.3################################# [100%]

第四步:启动MySQL服务

RPM包安装成功后,就可以使用service命令启动MySQL服务了。

# service mysqld start
Redirecting to /bin/systemctl start mysqld.service

使用RPM安装的MySQL,默认的错误日志文件路径为/var/log/mysqld.log。如果无法正常启动MySQL服务,可以到错误日志中查看相关报错信息。

# tail -100 /var/log/mysqld.log
......
2024-06-24T04:34:12.995336Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.0.39'  socket: '/var/lib/mysql/mysql.sock'  port: 3306  MySQL Community Server - GPL.
2024-06-24T04:34:12.995347Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Bind-address: '::' port: 33060, socket: /var/run/mysqld/mysqlx.sock

第五步:修改数据库默认密码

和二进制安装一样,使用RPM安装的MySQL,第一次访问时,也需要先修改数据库的默认密码。先从错误日志中找到临时密码。

# grep password /var/log/mysqld.log
2024-06-24T03:56:57.469312Z 6 [Note] [MY-010454] [Server] A temporary password is generated for root@localhost: ,6R&fqlf/5TS

再使用临时密码登录数据库,执行alter user命令修改密码。密码修改后,数据库就可以正常使用了。

# mysql -uroot -h 127.0.0.1 -p',6R&fqlf/5TS'

mysql> select 1;
ERROR 1820 (HY000): You must reset your password using ALTER USER statement before executing this statement.

mysql> alter user 'root'@'localhost' identified by 'Abcd1234';
ERROR 1819 (HY000): Your password does not satisfy the current policy requirements

mysql> alter user 'root'@'localhost' identified by 'ComplexPassword2024$';
Query OK, 0 rows affected (0.45 sec)

mysql> select 1;
+---+
| 1 |
+---+
| 1 |
+---+
1 row in set (0.00 sec)

注意,使用RPM包安装的MySQL,增加了数据库账号密码强度的验证。

二进制安装和RPM安装的区别

我们来对比下二进制安装和RPM包安装这两种安装方式的主要区别。

使用二进制安装时,我们需要做更多的准备工作,包括创建MySQL操作系统账号、创建数据库相关目录、准备参数文件。而使用RPM包安装时,自动包含了这些初始化动作。

使用二进制安装时,我们需要先创建初始化数据库。而使用RPM安装的MySQL,把初始化数据库的操作放到了service的启动脚本中。

# more /usr/lib/systemd/system/mysqld.service

[Service]
User=mysql
Group=mysql
......
# Needed to create system tables
ExecStartPre=/usr/bin/mysqld_pre_systemd

# Start main service
ExecStart=/usr/sbin/mysqld $MYSQLD_OPTS

执行service start mysql命令启动MySQL服务时,脚本mysqld_pre_systemd会检查数据目录是否存在,如果数据目录还没有创建,就会创建目录,并执行数据库初始化。并且mysqld_pre_systemd在初始化数据库时,还执行了下面这个SQL,启用了密码验证组件。

INSERT INTO mysql.component (component_id, component_group_id, component_urn) VALUES (1, 1, 'file://component_validate_password');

启用密码验证组件后,在MySQL中创建账号或修改账号密码时,需要使用有一定复杂度的密码。

二进制安装时,MySQL程序安装在一个统一的目录中,比如我们使用的/opt/mysql80。而使用RPM安装时,将MySQL程序安装在不同的路径下。mysqld安装在/usr/sbin路径下,其它程序安装在/usr/bin路径下,库文件安装在/usr/lib64/mysql下,字符集等相关支持文件放在/usr/share/mysql-8.0路径下。

二进制安装时,我们把参数文件、数据目录和其他运行MySQL的文件都放到了 /data/mysql{$PORT} 路径下,而RPM安装时,my.cnf默认放到/etc,数据目录放到/var/lib/mysql,错误日志使用了/var/log/mysqld.log。

如果你有单机多实例,或者在单台服务器上运行多个MySQL版本的需求,使用二进制安装更方便。

源码编译安装

通常我们会选择使用官方提供的二进制版本来部署MySQL,但是有些情况下也可能会采用源码编译的方式。比如,在一些信创环境下,官方可能没有提供目标系统的二进制安装包。或者我们需要安装一些非标准版本的MySQL,可能需要安装一些社区的patch、bugfix、扩展插件。或者想使用其他编译器或编译选项来编译MySQL,比如使用Intel的C编译器。或者出于学习的目的编译Debug版本的MySQL,用来调试一些功能。

第一步:准备build环境

编译MySQL本身不复杂,不过需要先准备好一个编译环境。编译MySQL 8.0需要以下几个基本工具。

  • cmake3
  • binutils
  • gcc 7.1以上版本
  • openssl
  • ncurse

CentOS 7.9默认的GCC版本太老了,需要安装一个新版本的GCC。当然你也可以使用其它的Linux发行版本。

安装cmake3。

yum install cmake3

安装GCC。

yum install centos-release-scl
yum install devtoolset-11-gcc devtoolset-11-gcc-c++ devtoolset-11-binutils

安装其它依赖库。

yum install -y ncurses-devel openssl openssl-devel

第二步:下载源码

在MySQL的下载页面,操作系统选择“Source Code”,操作系统版本选择“All operating Systems (Generic) (Architecture Independent)”。选择带C++ boost库的源码包,编译MySQL时需要这些代码。

图片

源码下载后,先验证一下文件校验码,确认没问题后再解压文件。

# wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-boost-8.0.39.tar.gz

# md5sum mysql-boost-8.0.39.tar.gz
07ee1d23908fc4ad7fc6a5cb8f2c99de  mysql-boost-8.0.39.tar.gz

# tar zxf mysql-boost-8.0.39.tar.gz

# tree -d -L 1 mysql-8.0.39
mysql-8.0.39
|-- archive_output_directory
|-- bin -> ./runtime_output_directory
|-- boost
|-- client
|-- cmake
|-- CMakeFiles
|-- components
|-- Docs
......

第三步:构建MySQL二进制

进入源码目录,这里我们演示使用cmake3来构建一个Debug版本的MySQL。如果执行cmake报错,需要查看错误信息,并做相应的处理。

# cd mysql-8.0.39
# cmake3  -DWITH_DEBUG=ON \
    -DWITH_BOOST=boost/boost_1_77_0 \
    -DCMAKE_INSTALL_PREFIX=/usr/local/mysql8.0

构建MySQL有很多选项,这里我介绍其中最基础的几个选项,完整的选项你可以到 官方文档 中查看。

图片

cmake成功后,使用make命令构建MySQL,使用参数 -j 指定编译的并发数,可以根据机器的配置选择合适的并发数,以加快构建的速度。

make -j 4

第四步:安装二进制

构建成功后,使用make install命令将MySQL安装到CMAKE_INSTALL_PREFIX指定的路径下。

make install

我们的例子中,MySQL安装到了/usr/local/mysql8.0下。

# tree -L 1 /usr/local/mysql8.0/
/usr/local/mysql8.0/
├── bin
├── docs
├── include
├── lib
├── LICENSE
├── mysql-test
├── README
└── share

我们构建出来的mysqld占用的空间比较大,如果要用在生产环境,可以使用strip命令对可执行文件进行裁剪,去掉二进制文件中的一些符号和调试信息。

# ls -lSh bin
total 1.2G
-rwxr-xr-x 1 root root 707M Jun 24 18:26 mysqld
-rwxr-xr-x 1 root root  39M Jun 24 17:47 mysqlxtest
-rwxr-xr-x 1 root root  22M Jun 24 17:39 mysqlpump
-rwxr-xr-x 1 root root  21M Jun 24 17:39 mysqlbinlog
......

### 使用strip减少文件大小
# strip mysqld

# ls -lSh
total 565M
-rwxr-xr-x 1 root root 128M Jun 25 10:32 mysqld
-rwxr-xr-x 1 root root  39M Jun 24 17:47 mysqlxtest
-rwxr-xr-x 1 root root  22M Jun 24 17:39 mysqlpump
-rwxr-xr-x 1 root root  21M Jun 24 17:39 mysqlbinlog

二进制文件安装完成后,接下来的步骤和“二进制安装”中的步骤没有区别,这里就不再重复了。

总结时刻

这一讲我们学习了在Linux操作系统下安装MySQL的几种方法。如果你需要安装部署大量MySQL服务器,我个人比较推荐使用二进制的方式安装。你需要制定一个标准规范,包括二进制安装路径、数据文件存放路径、服务器和数据库的标准参数配置等,并且按这个标准来部署所有的MySQL环境。

图片

思考题

早期的版本中,登录服务器本地的MySQL默认不需要密码。这存在一定的安全风险,因为你只要能登录到数据库服务器,就能访问这台服务器上的MySQL数据库。从5.7版本开始,给数据库的root账号设置了默认密码,首次登录时需要先修改密码。在部署一套MySQL数据库环境时,小明按规范修改了数据库root账号的密码,但是当时忘了将root密码记录下来,因此小明向你寻求帮助。你有办法帮小明解决这个问题吗?

欢迎你把你的答案分享到评论区,如果你觉得这节课的内容对你有帮助的话,也欢迎你分享给其他朋友,我们下节课再见!