CentOS安装并配置MySQL
文章介绍了在centOS7上安装mysql数据库服务的配置及简单优化过程。在服务器上安装mysql服务网络上能够找到的资源很多了,因此本文没有作详细介绍,本文的重点在于后续的优化配置方面。
安装MySQL #
配置 #
mysql的配置文件在/etc/my.cnf
, 只是简单地配置了数据库编码为utf8
;
1### my.cnf配置内容
2# For advice on how to change settings please see
3# http://dev.mysql.com/doc/refman/5.7/en/server-configuration-defaults.html
4[client]
5default-character-set=utf8
6
7[mysql]
8default-character-set=utf8
9
10[mysqld]
11collation-server = utf8_unicode_ci
12collation-server = utf8_bin
13collation-server = utf8_general_ci
14init-connect='SET NAMES utf8'
15character-set-server = utf8
16default-storage-engine = INNODB
17datadir=/var/lib/mysql
18socket=/var/lib/mysql/mysql.sock
mysql有默认配置账户以及测试数据库, root账户也会默认分配密码, 安装 指引链接2官方文档中说明了默认账户密码:
1) 在 /var/log/mysqld.log
中记录了mysql root账户的默认密码
1[root@simple ~] cat /var/log/mysqld.log | grep -i 'temporary password'
2# 2019-10-15T07:08:33.627866Z 1 [Note] A temporary password is generated for
3# root@localhost: I6cpDa!wj.6&
2) 可以使用mysql_secure_installation
命令进行初始化设置,程序会询问一些默认设置,包括重置密码,删除匿名账户,禁止root远程登录等等配置
1[root@simple ~] mysql_secure_installation
2...
还可以通过
set password
或者>mysqladmin
修改密码:SET PASSWORD FOR 'username'@'scope' = PASSWORD('newpasswd') 或者 mysqladmin -uroot -poldpass password newpass;
其他的配置 比如设置数据库时间为服务器时间(默认为UTC时间)并没有成功
账户与权限 #
前已述及,mysql默认配置root账户,并且已经只能本地登录(出于安全考虑),并且不建议使用root账户进行数据库连接;
因此,需要新账户,并且要控制账户权限,防止一些不可预见的错误出现;
同时,账户创建之后需赋予适当的权限;
账户 #
使用以下命令创建账户:
1create user username@'scope' IDENTIFIED BY 'passwd@';
关于账户说明
mysql 5.7加入了
validate_password
机制,该机制迫使用户使用[强密码]--至少8位,且至少包含一个大写字母,一个小写字母,一个数字,一个特殊符号;若想关闭此功能,可在my.cnf
中的[mysqld]栏下配置validate_password=Off
;scope项指定用户可以从哪里登录,一般
localhost
只允许本地(或ssh登录),%
允许任意ip位置登录,
权限 #
mysql的权限可以简单介绍为:
权限 | 描述 |
---|---|
全局权限 | privilege for all schemas; 信息保存在mysql.user表中 |
schema权限 | privilege for all tables; 信息保存在mysql.db中 |
table权限 | privilege for all columns; 信息保存在mysql.tables_priv中 |
column权限 | privilege for column;信息保存在mysql.columns_priv中 |
子程序权限 | ? |
权限的细致说明以及,各类权限所保存的表,可参考:
最简单的查看用户权限的方法
1show grants for user;
2show grants for user@'localhost';
3# 查看root的权限
4mysql> show grants for root@'localhost';
5+---------------------------------------------------------------------+
6| Grants for root@localhost |
7+---------------------------------------------------------------------+
8| GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION |
9| GRANT PROXY ON ''@'' TO 'root'@'localhost' WITH GRANT OPTION |
10+---------------------------------------------------------------------+
112 rows in set (0.00 sec)
从上面可以看出,root有[*.*的所有权限],至于*.*,代表了ALLDB.ALLTABLES-即所有数据库的所有表,这是最高权限。
或者,可以通过查询mysql.user
表来获取权限信息
1select * from mysql.user where user='root'\G;
2*************************** 1. row ***************************
3 Host: localhost
4 User: root
5 Select_priv: Y
6 Insert_priv: Y
7 Update_priv: Y
8 Delete_priv: Y
9# ignore others
给用户授予权限 #
假设我们创建了一个用户test
,并且没有授予任何权限,name,这个用户的权限是这样的;
1mysql> show grants for test;
2+---------------------------------------+
3| Grants for hc_future@% |
4+---------------------------------------+
5| GRANT USAGE ON *.* TO 'hc_future'@'%' |
6+---------------------------------------+
71 row in set (0.00 sec)
可以看到,实际上test
并没有任何权限;
1mysql> select * from user where user='test'\G;
2*************************** 1. row ***************************
3 Host: %
4 User: hc_future
5 Select_priv: N
6 Insert_priv: N
7 Update_priv: N
8 Delete_priv: N
9*************************** 1. row ***************************
尝试使用该账户对mysql进行任何操作都会得到一个错误信息:
1[42000][1044] Access denied for user 'hc_future'@'%' to database 'test'
显然,我们应该给用户授予部分权限,已让其完成操作,mysql使用grant
来给用户授予权限
若我想给test
授予全局select,update权限:
1mysql> grant select, update on *.* to test@'%' identified by 'testT123!@#';
2Query OK, 0 rows affected, 1 warning (0.00 sec)
3mysql> show grants for test;
4+------------------------------------------------+
5| Grants for test@% |
6+------------------------------------------------+
7| GRANT SELECT, UPDATE ON *.* TO 'test'@'%' |
8+------------------------------------------------+
91 row in set (0.00 sec)
10mysql> select * from user where user ='test'\G;
11*************************** 1. row ***************************
12 Host: %
13 User: hc_future
14 Select_priv: Y
15 Insert_priv: N
16 Update_priv: Y
17 Delete_priv: N
18 Create_priv: N
19 # ignore others
mysql 5.7.28中, 如果grant命令执行的用户没有被创建,会默认创建该用户
更多关于grant的使用,参考官方文档 GRANT Syntax
数据备份与导入 #
主要使用mysqldump
和source
来进行数据库的备份和恢复
数据库的备份主要分为结构和数据的备份,备份为x.sql
形式的文件
从备份的结果来看,
- 备份结构主要生成
create table
语句 - 备份数据生成
insert into
语句
除此之外,备份的范围可从库到表之间多级变化, 总言之, mysqldump
满足绝大多数备份需求;
需要说明的是,若数据库中有视图,则需要谨慎行事了, 因为视图中存在一些对原数据库表的引用以及对 执行用户的DEFINER, 若恢复的数据库和备份的数据库名字以及用户一致,则不会存在问题,否则可能会出现找不到表的错误
而数据库的恢复则简单了,source x.sql
即可
更多关于数据库备份恢复的细节,查看: mysqldump 导入/导出 结构&数据&存储过程&函数&事件&触发器
使用SSL加密连接 #
在jdbc
连接数据库的过程中可能会出现这样的警告:
Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
有时候,设置useSSL=true
又会遇到这样的错误:
1Caused by: javax.net.ssl.SSLHandshakeException:
2sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException:
3unable to find valid certification path to requested target
4 at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
5 at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1946)
6 at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:316)
7 at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:310)
8 ... 67 more
上述错误的大意是没找到ssl证书, 那么问题出在了mysql配置服务端或者客户端的配置上
由于mysql 5.7以上默认开启了ssl,验证一下
查看mysql SSL状态信息 #
1# 使用root账户登录 mysql -u root -p
2# 查看ssl信息
3# Server version: 5.7.28 MySQL Community Server (GPL)
4mysql> show global variables like '%ssl%';
5+---------------+-----------------+
6| Variable_name | Value |
7+---------------+-----------------+
8| have_openssl | YES |
9| have_ssl | YES |
10| ssl_ca | ca.pem |
11| ssl_capath | |
12| ssl_cert | server-cert.pem |
13| ssl_cipher | |
14| ssl_crl | |
15| ssl_crlpath | |
16| ssl_key | server-key.pem |
17+---------------+-----------------+
189 rows in set (0.00 sec)
19#have_ssl = YES, 说明ssl已经启用
20
21#查看当前用户的连接信息
22mysql> \s;
23--------------
24mysql Ver 14.14 Distrib 5.7.28, for Linux (x86_64) using EditLine wrapper
25
26Connection id: 157
27Current database:
28Current user: root@localhost
29SSL: Not in use
30Current pager: stdout
31Using outfile: ''
32Using delimiter: ;
33Server version: 5.7.28 MySQL Community Server (GPL)
34Protocol version: 10
35Connection: Localhost via UNIX socket
36Server characterset: utf8
37Db characterset: utf8
38Client characterset: utf8
39Conn. characterset: utf8
40UNIX socket: /var/lib/mysql/mysql.sock
41Uptime: 23 hours 21 min 57 sec
42
43Threads: 5 Questions: 10325 Slow queries: 0 Opens: 5061 Flush tables: 1 Open tables: 1543 Queries per second avg: 0.122
44--------------
45
46ERROR:
47No query specified
48#SSL=Not in use 说明没有使用ssl连接
结果显示, mysql 5.7.28已经启用了ssl,并且可以不使用ssl登录
根据上面的错误, jdbc连接错误的原因是由于证书错误, 做个测试:
1[root@iZbp17pma26sz5vqqwb1v3Z ~]# mysql -u root -p --ssl-ca=
2Enter password:
3ERROR 2026 (HY000): SSL connection error: SSL_CTX_set_default_verify_paths failed
当使用SSL登录而不指定证书的时候我们无法登录
如果你的mysql没有开启SSL,当使用
mysql -u root -p --ssl
登录的时候,会得到如下错误:ERROR 2026(HY000): SSL connection error: SSL is required but the server doesn't support it
配置SSL安全连接 #
那么, mysql的证书在哪里? 可能根据安装方式不同, 配置文件路径不一样, 使用yum源安装mysql时,实际上可以在var/lib/mysql
里找到mysql的证书文件:
1[root@sample ~]# ll /var/lib/mysql/*.pem
2-rw------- 1 mysql mysql 1676 Oct 15 15:08 /var/lib/mysql/ca-key.pem
3-rw-r--r-- 1 mysql mysql 1112 Oct 15 15:08 /var/lib/mysql/ca.pem
4-rw-r--r-- 1 mysql mysql 1112 Oct 15 15:08 /var/lib/mysql/client-cert.pem
5-rw------- 1 mysql mysql 1680 Oct 15 15:08 /var/lib/mysql/client-key.pem
6-rw------- 1 mysql mysql 1680 Oct 15 15:08 /var/lib/mysql/private_key.pem
7-rw-r--r-- 1 mysql mysql 452 Oct 15 15:08 /var/lib/mysql/public_key.pem
8-rw-r--r-- 1 mysql mysql 1112 Oct 15 15:08 /var/lib/mysql/server-cert.pem
9-rw------- 1 mysql mysql 1680 Oct 15 15:08 /var/lib/mysql/server-key.pem
我们指定证书试试看:
1[root@sample ~]# mysql -u root -p --ssl-ca=/var/lib/mysql/ca.pem
2Enter password:
3Welcome to the MySQL monitor. Commands end with ; or \g.
4Your MySQL connection id is 161
5Server version: 5.7.28 MySQL Community Server (GPL)
1mysql> \s;
2--------------
3mysql Ver 14.14 Distrib 5.7.28, for Linux (x86_64) using EditLine wrapper
4
5Connection id: 161
6Current database:
7Current user: root@localhost
8**SSL: Cipher in use is ECDHE-RSA-AES128-GCM-SHA256**
9Current pager: stdout
10Using outfile: ''
11Using delimiter: ;
12Server version: 5.7.28 MySQL Community Server (GPL)
13Protocol version: 10
14Connection: Localhost via UNIX socket
15Server characterset: utf8
16Db characterset: utf8
17Client characterset: utf8
18Conn. characterset: utf8
19UNIX socket: /var/lib/mysql/mysql.sock
20Uptime: 1 day 14 min 19 sec
21
22Threads: 3 Questions: 10335 Slow queries: 0 Opens: 5061 Flush tables: 1 Open tables: 1543 Queries per second avg: 0.118
23--------------
24
25ERROR:
26No query specified
可以看到, 连接信息的SSL信息变成了Cipher in use is ECDHE-RSA-AES128-GCM-SHA256
, 说明mysql可以使用SSL登录
关于mysql ssl证书的生成,参考 creating-ssl-files-using-openssl
既然可以指定证书使用SSL, jdbc为什么报错?
/etc/my.cnf
里没有ssl配置?
如何使用SSL连接,参考 Use Encrypted Connections
在/etc/my.cnf
中添加
1[mysqld]
2ssl-ca=ca.pem
3ssl-cert=server-cert.pem
4ssl-key=server-key.pem
使用service mysqld restart
重启mysql server, 让后看看服务端ssl配置是否生效:
1[root@sample ~]# service mysqld restart
2Redirecting to /bin/systemctl restart mysqld.service
3[root@sample ~]# mysql -u root -p --ssl
4WARNING: --ssl is deprecated and will be removed in a future version. Use --ssl-mode instead.
5Enter password:
6Welcome to the MySQL monitor. Commands end with ; or \g.
7Your MySQL connection id is 2
8Server version: 5.7.28 MySQL Community Server (GPL)
9mysql> \s;
10--------------
11mysql Ver 14.14 Distrib 5.7.28, for Linux (x86_64) using EditLine wrapper
12
13Connection id: 2
14Current database:
15Current user: root@localhost
16SSL: Cipher in use is ECDHE-RSA-AES128-GCM-SHA256
17Current pager: stdout
18Using outfile: ''
19Using delimiter: ;
20Server version: 5.7.28 MySQL Community Server (GPL)
21Protocol version: 10
22Connection: Localhost via UNIX socket
23Server characterset: utf8
24Db characterset: utf8
25Client characterset: utf8
26Conn. characterset: utf8
27UNIX socket: /var/lib/mysql/mysql.sock
28Uptime: 12 sec
29
30Threads: 1 Questions: 5 Slow queries: 0 Opens: 105 Flush tables: 1 Open tables: 98 Queries per second avg: 0.416
31\--------------
看到,我们使用ssl登录mysql,这一次并没有指定证书,而mysql连接成功,说明mysql服务端ssl配置成功了
事实上,做到此步后,jdbc里使用
1jdbc:mysql://47.110.226.247:3306/hcfuture_bundule?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&useSSL=true
这样的数据库url仍然得到同样的错误;个人认为是由于当客户端设置useSSL=true
时,同样需要配置客户端的SSL证书信息
如何在客户端使用SSL,可以参考 connector-j-reference-using-ssl
以下内容摘自( https://www.sojpt.com/feedback/5723):
首先mysql服务端要支持ssl,支持ssl需要以下条件:
创建ssl证书和密钥--生成ca.pem server-cert.pem client-cert.pem 文件 mysql提供两种方式 一种方式用openssl编译的mysql版本可以在启动时生成(参考链接:https://dev.mysql.com/doc/refman/5.7/en/creating-ssl-rsa-files-using-mysql.html); 第二种方式用openssl生成(采用的方式),(参考链接:https://dev.mysql.com/doc/refman/5.7/en/creating-ssl-files-using-openssl.html)
配置服务器支持(参考链接:https://dev.mysql.com/doc/refman/5.7/en/using-encrypted-connections.html) 主要时需要在my.cnf中需要添加以下配置,文件路径自行修改;还可以指定某个用户必须使用ssl链接等,详情参考官方的链接
[mysqld] ssl-ca=ca.pem ssl-cert=server-cert.pem ssl-key=server-key.pem require_secure_transport=ON
客户端链接需要以下几个步骤
- 需要将服务端的pem证书转换成java支持的JKS证书,得到keystore.jks和truststore.jks: 参考链接1:(可用)https://biteeniu.github.io/ssl/convert_pem_to_jks/ 参考链接2:(官方但连不上不知道什么原因)https://dev.mysql.com/doc/connector-j/5.1/en/connector-j-reference-using-ssl.html
- 修改mysql链接,指定链接方式为ssl jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf-8&verifyServerCertificate=true&useSSL=true&requireSSL=true
- 加载生成的jks证书和密码到系统属性,要在ActiveRecordPlugin之前 // keystore.jks和truststore.jks所在的路径,及创建时的密码 System.setProperty("javax.net.ssl.keyStore", "path/keystore.jks"); System.setProperty("javax.net.ssl.keyStorePassword", "password"); System.setProperty("javax.net.ssl.trustStore","path/truststore.jks"); System.setProperty("javax.net.ssl.trustStorePassword", "password");
实在是很繁琐,不过我估计此法是可行的,实际上是配置客户端的certificate,我嫌繁琐并没有尝试
实际上,我在官方文档里看到了此段话:
By default, Connector/J establishes secure connections with the MySQL servers. Note that MySQL servers 5.7 and 8.0, when compiled with OpenSSL, can automatically generate missing SSL files at startup and configure the SSL connection accordingly.
As long as the server is correctly configured to use SSL, there is no need to configure anything on the Connector/J client to use encrypted connections (the exception is when Connector/J is connecting to very old server versions like 5.6.25 and earlier or 5.7.5 and earlier, in which case the client must set the connection property useSSL=true in order to use encrypted connections). The client can demand SSL to be used by setting the connection property requireSSL=true; the connection then fails if the server is not configured to use SSL. Without requireSSL=true, the connection just falls back to non-encrypted mode if the server is not configured to use SSL.
实际上,此前我们mysql server的SSL已经成功配置,已经验证通过mysql -u test -p -h your serverip
远程登录mysql后,通过status
查看连接信息可以看到是通过SSL连接的
结合此段声明, mysql 5.7以后的连接是加密的(需要服务端开启SSL),故无需费时在客户端进行ssl配置(特殊需求除外)
如果想使用jdbc连接配置SSL, 而不使用编码方式,可以参考 connector-j-reference-configuration-properties