11 min read

在Linux服务器上部署MySQL

在Linux服务器上部署MySQL

2/100

就自己的经历来看,目前(2021年)大多数的企业使用的数据库是MySQL,所以不论今后想要从事运维工程师这一职业,还是跳槽面试,MySQL大概率是会被问到一环。

我呢,运气比较差,毕业进入的第一个企业接触的业务线使用的SQLServer,服务器也几乎都是WindowsServer,所以不得不自己给自己模拟“生产环境”来玩MySQL。

在这里我想记录自己在摸索过程中遇到的问题与答案。我不太想用“教程”的方式来写作,如果你只想学习MySQL怎么安装,那么这篇文章可能不适合你。

我想记下自己部署过程的整个“工作流”,因此内容除了有安装部署MySQL数据库,还会有Linux的一些知识(主要是我不熟悉或者理解不深刻的),我会争取让整个“工作流”不留下自己无法解释的地方。(如果你有不理解的地方欢迎评论告诉我,我们一起研究!)

哦!对了,忘记是哪本书上讲的了,说SQL的发音应该是“sequel”,而不是自己平时习惯的“sē 扣”。当然,单子母发音S-Q-L是肯定没错啦,可以看看这篇关于读法的文章

开始啦!

最直接的方式--包管理器(yum,apt,etc.)

最简单直接的安装方式是使用包管理器安装,比如CentOS上的yum,Ubuntu上的apt等等。我接触的大多数企业生产环境使用的都是CentOS,这里也以CentOS为例。

团队每周都会有分享活动,我从DBA的分享中得到了一段通过yum安装MySQL的代码:

yum install mysql mysql-dev mysql-server mysql-share mysql-lib

Q:为什么安装了mysql还要安装mysql-server?
A:MySQL和SQLServer都有Server-Client的架构模式。平时使用的mysql命令是单纯的Client,真正的MySQL数据库应当是mysql-server

执行的时候出现了类似下面的问题👇

No package mysql-dev available.
No package mysql-server available.
No package mysql-share available.
No package mysql-lib available.

MySQL官网的教程上告诉我要先添加yum源。

https://dev.mysql.com/doc/refman/5.7/en/linux-installation-yum-repo.html

进去之后会发现源和自己系统的版本有匹配关系。

Q:假如不知道自己系统CentOS几版本,怎么查看?

A:$>: cat /etc/redhat-release

要下载的是一个rpm文件,需要放到机器上(用wegt直接下载)然后安装这个rpm文件(或者叫包)

yum localinstall xxx.rpm

之后就可以正常下载安装mysql-*相关的软件了。

怎么知道自己的机器装没装MySQL?其实这应该是安装前做的第一个步骤,以前的我会看机器有没有mysql命令。如果有,那说明原来是装了的。(这种办法是错误的❌)

现在理解这种方法为什么是错误的了,mysql命令代表的是mysql的Client,有这条命令只能说明安装了Client端,而不能证明安装了Server端。

使用下面的方式可以判断原来有没有安装

#如果使用刚刚的方式安装
rpm -qa|grep -i mysql
#Or
yum list installed | grep mysql-*

使用预编译的安装包安装

另一种安装方式就是编译安装了,实际上使用的是编译好的二进制包(也就是预编包,编译安装以后遇到了在更新文章好了)。

预编译的包可以直接从官网去下载,也可以自己编译。(有机会在更新)这里目的是为了熟悉使用预编译的包安装,所以我选择直接去官网找资源。

找到Compressed TAR Archive,复制链接,wegt下载。

这是官方提供的安装教程,先浏览一遍,里面有完整的步骤,心里有个数,然后再和实际的情况作作对比。

上面的步骤和DBA的材料里的第一步都是要建立一个专门用于启动mysqld(mysql-server)的用户,却没有直接说明为什么要这样做,我大概搜索了一下,一个比较靠谱的答案是“若以root权限用户启动mysqld进程,任何具有FILE权限的人都有权限控制整个操作系统“。(现在还不太理解这个很有hacker味道的答案,等研究明白了再更新。)

先创建一个用户组(groupadd mysql),然后创建一个用户并加入刚才的组(-g mysql)。

但自己实验时的研究发现可以只需要操作一次就能达到这样的效果:

使用-g mysql指定用户组的前提是那个组要存在,所以首先使用groupadd mysql。

但其实只用useradd达到同样的目的(或效果):

useradd -s /bin/false mysql

要理解为什么,需要先理解几个名词:

  • 主要组(primary group)
  • 私有组(private group)
  • 附加组(attached group)

推荐你阅读这篇文章理解上面的概念(我也是从这里学习的)

“一个用户可以属于多个组”的概念很好理解,一旦用户属于了多个组,好像确实有必要推举一个“Leader”,primary group的概念也就好解释它存在的意义了。(当然,我在自圆其说)但是一下子还想不到private groupattached group出现的意义和用途。(如果你知道,欢迎告诉我)

怎么突然出要了解primary group的概念?是因为先创建mysql组,然后添加mysql用户到组里后,我想要删除mysql这个组(mysql组里仍有mysql这个用户),用groupdel mysql就出现了下面的问题:

groupdel: cannot remove the primary group of user 'mysql'

总之,进行到这里,关于useradd和group的概念学到了两个点:

  1. 用户必须要依赖一个组才能存在。
  2. 如果创建用户没有指定组,那么useradd命令会默认创建一个同名的private group,并把用户加进去。

所以useradd帮我们创建了组,创建了/home/mysql家目录(虽然我没提及,但事实就是如此,可以自己试一下)我们只需要指定让mysql用户不具有登陆shell的权限即可(-s /bin/false)其实这里还有个遗留问题:/bin/false/bin/nolgoin的区别,以后研究明白了再更新。

在使用非root权限用户启动mysqld(mysql-server)程序之前,还需要进行“初始化”大概就是创建一些mysql的一些系统库等等,可以通过文档了解。

使用命令进行初始化:

解压tar.gz包, -C 指定解压(包)的目标地址。解压后使用命令 ln -s 建立一个"快捷方式"。
tar -zxvf mysql-5.7-xxxx.tar.gz -C /var/local/
ln -s /var/local/mysql-5.7-xxxx /var/local/mysql

通常,初始化完成之后,我们就可以直接使用mysqld --user=mysql启动MySQL服务端,进行登录了。

我登陆的时候,很快遇到了一个新问题:报错找不到mysql.socket文件。我尝试用-S 指定socket文件的位置(一般会在/tmp目录下)但是仍然没有找到...最后花了点时间才在/var/lib下找到了正确的socket文件。

问题一定出在初始化的时候,我应该告诉MySQL初始化时使用的每个文件的位置,而不是用它自己的默认。按照自己指定的目录存放相关的文件才是正确的初始化方式。

我从分享材料中了解到通常可以这样划分目录(/data是一个单独的分区,最好是一个单独的盘,使用xfs文件系统而不是常用的ext文件系统,这样会提高IO。)

/data/mysql_3306/data #存放mysql主要数据,比如库,schema等。具体内容可以查看网 --data-dir命令行的解释。
/data/mysql_3306/etc #mysql的配置文件 my.cnf,下面会仔细介绍,重要。
/data/mysql_3306/tmp
/data/mysql_3306/log

一个小Tip:一条命令就可以创建这4个目录:

mkdir -p /data/mysql_3306/{data,etc,tmp,log};cd $_

诀窍在于{}大括号扩展,会一次展开大括号里的内容。
cd $_的效果会进入 /data/mysql_3306/log/文件夹内,$_是个shell里的特殊变量,会返回上一条命令的参数。(在这里就是mkdir的数/data/mysql_3306/log。为什么?当然是因为大括号扩展啦)

目录准备好了,接下来就要指定相关的文件放到这里了。可以通过命令行直接指定,比如mysqld --initialize  --data-dir=xxx。也可以通过配置文件指定,配置文件里的每个属性都和命令行是等效且一样的,通过mysqld --verbose --help可以看到所有与mysqld相关的配置项目。更多详细内容可以看官方手册

是的,配置文件大概率需要从头写起。我也曾经怀疑过:按道理应该有一个模版配置文件才对。但是很不幸,没有。(至少我下载的MySQL5.7最新版没有)

具体的配置项前面也提到了和命令行是一摸一样的,使用--help就可以查到(mysqld需要加--verbose,mysql不用)

需要注意的是配置文件有分组的概念(group)用[mysqld]来表示mysqld分组。

分组的一个特性是:如果运行的实例名称和分组名称一样,那就会应用分组下的配置。比如配置文件里分组[mysql]那么所有mysql这个程序(即mysql客户端)都会应用和mysql有关的配置项(可以通过mysql --help查看完整配置项)

分组第二个特性:[client]分组的配置会应用到所有client上,这里我理解会影响jdbc之类的数据库接口,比如给所有接口统一设置密码。

既然是初始化MySQL,那么实例自然是mysqld,所以配置文件就这样子了:

[mysqld]
basedir = /usr/local/mysql  # mysql.tar.gz解压后的目录(上面部分做了软连接)
datadir = /data/mysql_3306/data #一定要空目录
pid-file = /data/mysql3306/data/mysql_3306.pid
socket = /data/mysql_3306/tmp/mysql.socket
tmpdir = /data/mysql_3306/tmp
log-error = /data/mysql_3306/log/mysql-error.log
slow-query-log-file =/data/mysql3306/log/slow_log/mysql_slow_query.log

重新初始化:

./bin/mysqld --defaults-file=/data/mysql_3306/etc/my.cnf --initialize-insecure --user=mysql

--defaults-file:按照配置文件设置

--intialize-insecure:初始化不设定root密码(后面自己再添加)

初始化完成后,MySQL其实就可以正常启动了:

./bin/mysqld_safe --defaults-file=/data/mysql3306/etc/my.cnf --user=mysq

使用mysqld_safe是因为比直接使用mysqld更”安全高效“。具体得要看看这个shell脚本才知道是怎么回事儿。(是的,他是个shell脚本)

好了,已经能够运行起来MySQL了,第一阶段的任务就完成了。但是现在启动起来还不是很优雅,要敲很长的命令,接下来研究怎么在Linux上配置一个服务。

Stay tuned!

Luo.

听歌放松一下!


🤔思考题:

  1. 以root身份启动mysqld会造成什么隐患?
  2. /bin/false和/bin/nologin区别?
  3. xfs系统和ext系统的差别。(为什么会提高IO)
  4. 研究研究mysqld_safe脚本,也许能学点魔法。