写在前的的话: 在IT技术日新月异的今天,老司机也可能在看似熟悉的道路上翻车,甚至是大型翻车现场!自己一个人开车过去翻个车不可怕,可怕的是带着整个团队甚至是整个公司一起翻车山崖下,解决办法就是:新出现的道路自己先过一遍,留好坑位标记,将来带队过去时不再翻车!!!
最近刚好在进行权限系统的微服务化改造,要重新搭一套开发服务器环境。今天搭的是MySQL数据库服务器,MySQL 8.0出来也有些年月了,现在(2020)大多数公司还没在生产上用上,于是乎就想尝个鲜,选择了在CentOS8.1上进行MySQL8.0服务器的搭建。当前来说CentOS8.1也算比较新了!
老样子,先装一个全新的CentOS8.1虚拟机,选择装配基本的Server软件包,网络模式选择【桥接模式(自动)】(主要为了让宿主机和虚拟机的网络处于等级),IP地址相关信息切记选择手工配置,不能用DHCP进行动态分配(有DNS服务器辅助除外),为什么呢?因为你是在配服务器,IP地址要固定下来,不然每次启动后的IP都不同,那就很尴尬了!
服务器操作系统准备好后该去下载MySQL8.0了,去哪里下呢?当然是MySQL8.0社区版官网!可是跑到网官一看,估计有些同学就一脸懵逼,纯英文的不说,安装包还各样种样的!怎么选呢?
首先要选定操作系统平台,我这边是CentOS8.1 x86_64位架构,那我要选Linux版本的,最好是CentOS专用的!结果找了一圈暂时还没有CentOS专用的版本(RedHat专用版本到是有,其实我们知道CentOS是就源自RedHat)...为了保险起见,我们选Linux通用版(Linux-Generic),结果出来的列表也不少!这么多都是些啥,见图标解吧:
我选择【64位通用二进制最小安装压缩包(不含调试组件及调式符号)】,理由:
- 我的目标操作系统是64位的CentOS;
- 我不需要做MySQL的调试;
- CentOS8.1上带有专用的解压安装工具tar;
- 小包从官网下载和上传到服务器都快(MySQL数据库功能也完整,别看小了那么多!);
点击Download后出现的界面中会建议你登录你的Oracle Web账号,不用登录(当然你有账号也可以登录),直接点下面的一小行字——“No thanks,just start my download.”
将目标包(mysql-8.0.20-linux-x86_64-minimal.tar.xz)下载好后,使用SecureCRT上传到服务器 /opt 目录下!(Linux众多目录的作用)
接下来开始正式安装MySQL8.0,记住我们的前提是:全新的、干净的CentOS8.1操作系统,之前没有装过MySQL的!如果之前装过MySQL是要先把相关目录和配置文件删除干净才能再装的!谨记!谨记!谨记!
第一步:使用yum包管理器检查并安装异步IO依赖包 libaio ,如果没装这个包,数据目录初始化和后续服务器的启动都将失败,如果检查发现没装,要将它装上:
# yum search libaio
# yum -y install libaio
第二步:由于CentOS是源自RedHat的,而RedHat系列的操作系统中没有MySQL通用二进制安装包(不管有没有压缩)中的MySQL客户端(bin/mysql)组件所需要的 /lib64/libtinfo.so.5 文件,为了解决这个问题,需要安装一个含有该文件的 ncurses-compat-libs 包(截图是已经装过一次的结果):
# yum -y install ncurses-compat-libs
第三步:转到 mysql-8.0.20-linux-x86_64-minimal.tar.xz 压缩包存放目录 /opt ,使用 tar 命令进行解压(直接解压到当前目录):
# cd /opt
# tar -xvf mysql-8.0.20-linux-x86_64-minimal.tar.xz
解压得到一个新目录:/opt/mysql-8.0.20-linux-x86_64-minimal ,该目录即为MySQL的真实安装目录;
第四步:创建用于运行MySQL的组和普通用户(非操作系统用户):
# groupadd mysql
# useradd -r -g mysql -s /bin/false mysql
第五步:在用户手动安装软件推荐安装目录 /usr/local 中创建MySQL的真实安装目录的软链接目录(软链接目录不能是已经存在的目录,相当于Windows快捷方式):
# cd /usr/local
# ln -s /opt/mysql-8.0.20-linux-x86_64-minimal mysql
第六步:在mysql软链接目录中创建导入导出操作安全目录(该目录用于使具有FILE权限的用户可以安全地执行导入导出操作):
# cd /usr/local/mysql
# mkdir mysql-files
# chown mysql:mysql mysql-files
# chmod mysql-files
(其实,第六步做完后就已经有办法可以临时点亮MySQL服务器了,这里不讲,因为我们要配的是一个长期运行的MySQL数据库服务器)
第七步:在mysql软链接目录下创建数据目录:
# cd /usr/local/mysql
# mkdir data
# chown mysql:mysql data
# chmod data
第八步:创建MySQL服务启动需要用到的静态配置文件(如果目录下已经有了同名文件,则需要换一个名字,之前没装过MySQL一般是不会有的!):
# cd /etc
# touch my.cnf
# chown root:root my.cnf
# chmod my.cnf
第九步:使用vi或vim打开第八步创建的配置文件 /etc/my.cnf ,加入MySQL服务的配置信息
[mysqld]
datadir=/usr/local/mysql/data
socket=/tmp/mysql.sock
port=3306
log-error=/usr/local/mysql/data/mysqldb.xgclassroom.err
user=mysql
secure_file_priv=/usr/local/mysql/mysql-files
local_infile=OFF
注意:配置中log-error的值一般中根据你安装操作系统时设置的Host名称相关,大家的不一样,当然你也可以直接指定新名字!
另外,如果要InnoDB的相关配置项,那么只能在数据目录初始化(第十步)之前在my.cnf中进行配置,主要有 innodb_data_home_dir,innodb_data_file_path,,innodb_log_file_size,innodb_log_group_home_dir 和 innodb_page_size 这几项,未配置的情况下,它们都使用默认值。
第十步:初始化第七步创建的数据目录(因为要用到第八和第九步创建的配置文件)
# cd /usr/local/mysql
# bin/mysqld --defaults-file=/etc/my.cnf --initialize
注意:数据目录初始化成功后,会在第九步所设置的log-error日志文件(我的是 /usr/local/mysql/data/mysqldb.xgclassroom.err)中生成 root@localhost 的初始密码(账号冒号后面的QdbB=9e!lT6=就是,要记住这个初始密码,后面登录root账号是要它来修改初始密码),类似下面的信息(可以使用cat命令查看):
...省略...
A temporary password is generated for root@localhost: yi5w%J*hws6E
...省略...
现在我们还缺了最最最重要的一项配置——让MySQL服务随操作系统的启动自动启动!继续配置ing!
在Linux系统中目前系统服务主要以 systemd 服务单元的形式存在(类似windows平台的services.msc下管理的各个服务),Linux系统下一切皆文件,systemd 服务单元也是由一个个systemd 服务单元配置文件组成,systemd 服务单元配置文件 = systemd 服务单元!配置文件名就是服务单元名!所有服务单元的配置文件统一放在 /usr/lib/systemd/system 目录下。
第十一步:在系统服务单元配置文件存放目下创建MySQL的服务单元配置文件:
# cd /usr/lib/systemd/system
# touch mysqld.service
# chmod mysqld.service
第十二步:使用vi或vim打开第十一步创建的MySQL服务单元配置文件 /usr/lib/systemd/system/mysqld.service,并加入MySQL服务单元配置信息:
[Unit]
Description=MySQL Server
Documentation=man:mysqld(8)
Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html
After=network.target
After=syslog.target [Install]
WantedBy=multi-user.target [Service]
User=mysql
Group=mysql # Have mysqld write its state to the systemd notify socket
Type=notify # Disable service start and stop timeout logic of systemd for mysqld service.
TimeoutSec=0 # Start main service
ExecStart=/usr/local/mysql/bin/mysqld --defaults-file=/etc/my.cnf $MYSQLD_OPTS # Use this to switch malloc implementation
EnvironmentFile=-/etc/sysconfig/mysql # Sets open_files_limit
LimitNOFILE = 10000 Restart=on-failure RestartPreventExitStatus=1 # Set environment variable MYSQLD_PARENT_PID. This is required for restart.
Environment=MYSQLD_PARENT_PID=1 PrivateTmp=false
第十三步:启用MySQL服务单元配置
# systemctl enable mysqld.service
经过上面的一系列安装和配置步骤后,此时我们已经可以通过systemctl工具手工管理MySQL服务了:
# systemctl {start|stop|restart|status} mysqld
第十四步:启动MySQL服务,并查看MySQL服务状态:
# systemctl start mysqld
# systemctl status mysqld
第十五步:重启服务器,检验MySQL服务是否随服务器一起启动了:
# reboot
...重启系统中...
# systemctl status mysqld
如果最终MySQL服务状态正常,那么CentOS8.1上MySQL8.0的安装就算是完成了,但是不要高兴的太早了!还有好多事要做:
1、将服务器上的MySQL客户端(bin/mysql)配置到系统环境变量PATH中:
如果不将MySQL客户端(bin/mysql)配到环境变量中,你会发现即使MySQL服务在正常运行,但直接在系统终端输入mysql是找不到该命令的:
[root@mysqldb /]# mysql
-bash: mysql: command not found
当然,你用完整MySQL客户端(bin/mysql)命令路径是可以运行该命令的(虽然报错,但那是正常的识别命令使用了):
[root@mysqldb /]# /usr/local/mysql/bin/mysql
ERROR (): Access denied for user 'root'@'localhost' (using password: NO)
系统环境变量PATH在环境变量配置文件 /etc/profile 中配置:
# vim /etc/profile 在文件的最后新起一行,插入: export PATH=$PATH:/usr/local/mysql/bin 保存退出后,使用下面的命令手动使修改生效: # source /etc/profile
现在你可以直接在任意目录下执行mysql命令了:
[root@mysqldb /]# mysql
ERROR (): Access denied for user 'root'@'localhost' (using password: NO)
2、root账号初始密码修改:
使用root初始密码(记录在第九步所设置的log-error日志文件)登录MySQL,并修改密码:
[root@mysqldb /]# mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is
Server version: 8.0. Copyright (c) , , Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql>alter user 'root'@'localhost' identified by '1qaz@WSX';
Query OK, 0 rows affected (0.00 sec)
3、进行root账号的服务器本机登录测试:
修改完root的默认密码后,退出MySQL并使用新密码重新尝试登录:
mysql> exit
Bye
[root@mysqldb /]# mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is
Server version: 8.0. MySQL Community Server - GPL Copyright (c) , , Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql>
4、对MySQL使用的端口号进行防火墙例外设置:
先用root账号登录MySQL,检查一下当前正在使用的端口号:
mysql> show global variables like 'port';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| port | |
+---------------+-------+
1 row in set (0.01 sec)
将目标端口号(例中为3306)添加到防火墙例外列表,并重新载入防火墙:
# firewall-cmd --zone=public --add-port=3306/tcp --permanent
success
# firewall-cmd --reload
success
注意1:一定要带上--permanent 参数才能永远生效,否则系统重启后丢失,另外 --zone 、--add-port 和 --permanent参数前面是两个-;
注意2:一定要重新载入防火墙,让设置生效;
5、创建远程登录和使用MySQL的普通用户(因为安全起见,root账号一般不要设置成可以远程登录,要设置也尽量设置成只可在固定的某个IP远程登录):
以root账号登录MySQL,使用以下SQL命令创建一个可以任意网络互通的点登录的账号xurm 密码 1qaz@WSX
create user xurm IDENTIFIED with mysql_native_password by '1qaz@WSX' account unlock;
select host,user from user;
grant all on *.* to xurm WITH GRANT OPTION;
FLUSH PRIVILEGES;
认认真真按上边的步骤和细节进行安装和配置后,现在可以从开发机的客户端,用普通账号登录远程MySQL服务器,愉快的玩耍了:
以下记录一次手贱导致的翻车现场:
使用 # systemctl stop mysqld.service 成功关闭mysql服务后,尝试直接使用 /usr/local/mysql/bin/mysqld 尝试启动mysql造成的后果:bin/mysqld 尝试启动时覆盖并破坏了第十步数据目录初始生成的有关文件,导至MySQL无法启动,这时尝试使用 # systemctl start mysqld.service也无法再启动MySQL服务~~~
....
2020-06-06T04:38:39.614356Z 1 [ERROR] [MY-012574] [InnoDB] Unable to lock ./ibdata1 error: 11
2020-06-06T04:38:40.618323Z 1 [ERROR] [MY-012574] [InnoDB] Unable to lock ./ibdata1 error: 11
2020-06-06T04:38:41.619650Z 1 [ERROR] [MY-012574] [InnoDB] Unable to lock ./ibdata1 error: 11
2020-06-06T04:38:41.620710Z 1 [ERROR] [MY-012592] [InnoDB] Operating system error number 11 in a file operation.
2020-06-06T04:38:41.621045Z 1 [ERROR] [MY-012596] [InnoDB] Error number 11 means 'Resource temporarily unavailable'
2020-06-06T04:38:41.621712Z 1 [ERROR] [MY-012215] [InnoDB] Cannot open datafile './ibdata1'
2020-06-06T04:38:41.622047Z 1 [ERROR] [MY-012959] [InnoDB] Could not open or create the system tablespace.
If you tried to add new data files to the system tablespace, and it failed here, you should now edit innodb_data_file_path in my.cnf back to
what it was, and remove the new ibdata files InnoDB created in this failed attempt. InnoDB only wrote those files full of zeros, but did not
yet use them in any way. But be careful: do not remove old data files which contain your precious data!
2020-06-06T04:38:41.622372Z 1 [ERROR] [MY-012930] [InnoDB] Plugin initialization aborted with error Cannot open a file.
2020-06-06T04:38:42.119489Z 1 [ERROR] [MY-010334] [Server] Failed to initialize DD Storage Engine
2020-06-06T04:38:42.122437Z 0 [ERROR] [MY-010020] [Server] Data Dictionary initialization failed.
2020-06-06T04:38:42.127147Z 0 [ERROR] [MY-010119] [Server] Aborting
2020-06-06T04:38:42.127857Z 0 [System] [MY-010910] [Server] /usr/local/mysql/bin/mysqld: Shutdown complete (mysqld 8.0.20) MySQL Community Server - GPL.
提示信息中让我在/etc/my.cnf配置文件中将 innodb_data_file_path 配置项的值改回原来的去,实际上我并没有在/etc/my.cnf配置文件配置该项,而是一直使用着默认的 innodb_data_file_path 配置;
提示信息让我删除启动失败的尝试中InnoDB生成的新ibdata相关文件,讲真的,因为一开始没有对比过data/目录中的文件,现在我都不知道哪些是InnoDB生成的新ibdata相关文件;
最后想了一下,我是刚刚安装的数据库系统,也还没有重要数据在上边,现在data/目录遭到破坏,那最快的办法就是清空data/目录,并重新初始化它,应该就能解决问题了(已经运行了段时间的生产数据库千万不要这么玩,要备份好所有数据文件,否则会死得很难看!!!最好另寻它法,最最最好就不要让这样的车祸出现!):
- 清空data/目录:
# rm -rf /usr/local/mysql/data/*
- 使用第十步中的命令重新初始化数据目录:
# cd /usr/local/mysql
# bin/mysqld --defaults-file=/etc/my.cnf --initialize
注意:数据目录重新初始化成功后,会在第九步所设置的log-error日志文件(我的是 /usr/local/mysql/data/mysqldb.xgclassroom.err)中生成新的 root@localhost 的初始密码
- 重启尝试启动MySQL服务:
# systemctl start mysqld
Job for mysqld.service failed because the control process exited with error code.
See "systemctl status mysqld.service" and "journalctl -xe" for details.
哦呵...又双叒叕翻车了,重启失败!!! 慌得一逼!继续...
- 查看一下日志文件/usr/local/mysql/data/mysqldb.xgclassroom.err
# cat mysqldb.xgclassroom.err
2020-06-06T05:31:31.249888Z 0 [System] [MY-013169] [Server] /opt/mysql-8.0.20-linux-x86_64-minimal/bin/mysqld (mysqld 8.0.20) initializing of server in progress as process 2662
2020-06-06T05:31:31.256260Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
2020-06-06T05:31:31.509465Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
2020-06-06T05:31:31.995068Z 6 [Note] [MY-010454] [Server] A temporary password is generated for root@localhost: iqaaJCdnj3&e
2020-06-06T05:33:09.978908Z 0 [System] [MY-010116] [Server] /usr/local/mysql/bin/mysqld (mysqld 8.0.20) starting as process 2714
2020-06-06T05:33:09.987836Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
2020-06-06T05:33:10.212686Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
2020-06-06T05:33:11.314035Z 0 [ERROR] [MY-011292] [Server] Plugin mysqlx reported: 'Preparation of I/O interfaces failed, X Protocol won't be accessible'
2020-06-06T05:33:11.314175Z 0 [ERROR] [MY-011300] [Server] Plugin mysqlx reported: 'Setup of bind-address: '*' port: 33060 failed, `bind()`
failed with error: Address already in use (98). Do you already have another mysqld server running with Mysqlx ?'
2020-06-06T05:33:11.314342Z 0 [ERROR] [MY-011300] [Server] Plugin mysqlx reported: 'Setup of socket: '/tmp/mysqlx.sock' failed,
another process with PID 1734 is using UNIX socket file'
2020-06-06T05:33:11.413373Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed.
2020-06-06T05:33:11.414505Z 0 [ERROR] [MY-010262] [Server] Can't start server: Bind on TCP/IP port: Address already in use
2020-06-06T05:33:11.414625Z 0 [ERROR] [MY-010257] [Server] Do you already have another mysqld server running on port: 3306 ?
2020-06-06T05:33:11.414918Z 0 [ERROR] [MY-010119] [Server] Aborting
2020-06-06T05:33:12.939872Z 0 [System] [MY-010910] [Server] /usr/local/mysql/bin/mysqld: Shutdown complete (mysqld 8.0.20) MySQL Community Server - GPL.
有个PID为1734的进程在占用3306和33060端口?而且还可能是另一个mysqld server,我造,不会是真的吧!使用# systemctl status mysqld 都查过了,没有服务了~
- 查看一下3306端口的占用情况先:
# netstat -anp | grep 3306
tcp6 0 0 :::33060 :::* LISTEN 1734/mysqld
tcp6 0 0 :::3306 :::* LISTEN 1734/mysqld
竟然真的有个mysqld进程(PID=1734)以tpc6的协议模式占着3306和33060端口~
- 查看一下这个mysqld进程的详情,看看它是是哪里来的:
# ps -aux | grep mysqld
mysql 0.5 19.0 1773244 352616 ? Sl 12:12 0:29 /usr/local/mysql/bin/mysqld
root 2786 0.0 0.0 12108 1080 pts/1 S+ 13:45 0:00 grep --color=auto mysqld
果然是手贱作的孽,直接通过/usr/local/mysql/bin/mysqld手动启动的服务没关彻底...
- 干掉占用3306和33060端口的无效mysqld进程:
# kill - 1734
- 再次使用# systemctl start mysqld 命令启动mysql:
# systemctl start mysqld
# systemctl status mysqld
● mysqld.service - MySQL Server
Loaded: loaded (/usr/lib/systemd/system/mysqld.service; enabled; vendor preset: disabled)
Active: active (running) since Sat -- :: CST; 20s ago
Docs: man:mysqld()
http://dev.mysql.com/doc/refman/en/using-systemd.html
Main PID: (mysqld)
Status: "Server is operational"
Tasks: (limit: )
Memory: 327.7M
CGroup: /system.slice/mysqld.service
└─ /usr/local/mysql/bin/mysqld --defaults-file=/etc/my.cnf Jun :: mysqldb.xgclassroom systemd[]: Starting MySQL Server...
Jun :: mysqldb.xgclassroom systemd[]: Started MySQL Server.
终于开回正路来了!!!使用日志文件/usr/local/mysql/data/mysqldb.xgclassroom.err中记录的新的初始密码登录mysql并修改初始化密码就可以了!