1.4.1 客户端连接层的改进

1.增加了身份验证插件auth_socket

当用户通过本地Unix套接字文件连接到MariaDB的时候,auth_socket身份验证插件允许用户使用操作系统的凭证进行登录访问,也就是说,使用Linux操作系统的账号登录即可访问MariaDB数据库。

在MariaDB 10.4.3及更高版本中,默认情况下已经安装了auth_socket身份验证插件,因此无须执行下面的命令:

下面就通过示例代码来演示auth_socket身份验证插件的使用方法。

1)创建数据库账号hechunyang,并赋予权限,命令如下:

2)创建操作系统账号hechunyang,命令如下:

3)以系统账号hechunyang登录操作系统,并访问MariaDB数据库,如图1-3所示。

在此示例中,用户hechunyang已登录操作系统,并具有完全Shell访问权限。由于该用户已经使用操作系统进行了身份验证,并且其MariaDB账户已配置为使用auth_socket身份验证插件,因此无须再在数据库中进行身份验证。MariaDB接受该用户的操作系统凭证并允许其进行连接。其他用户由于没有登录该操作系统,因此没有权限执行任何操作。

图1-3 使用auth_socket身份验证插件访问数据库

2.支持账户锁定功能

MariaDB支持管理员锁定、解锁用户账户,如果账户被锁定(现有连接不受影响),那么新的客户端将会不允许连接。

下面就通过示例代码来演示账户锁定的使用方法。

1)账户锁定,命令如下:

锁定账户后,通过该账户再次登录时,会提示如下信息:

2)查看账户的锁定信息,命令如下:

执行上述代码后会出现“ACCOUNT LOCK”的提示信息,代表账户已经被锁定,如图1-4所示。

图1-4 账户被锁定

3)解锁此账户,命令如下:

3.增加了用户密码到期功能

下面通过示例代码演示用户密码到期功能的使用方法。

1)设置用户密码到期时间,命令如下:

注意,单位默认只有DAY(天),最小为1天。

在用户密码到期后,登录时系统会提示修改密码,命令如下:

2)查看用户密码过期时间,命令如下:

以下查询代码可用于检查所有用户的当前密码过期时间:

上述代码段的执行结果如图1-5所示。

图1-5 用户密码过期时间查询

3)解除用户密码到期限制,命令如下:

4.支持角色授权与取消功能

在数据库中,为了便于对用户及其权限进行管理,可以将一组具有相同权限的用户组织在一起,这一组具有相同权限的用户就称为角色。在实际工作中,通常会有大量用户的权限是一样的,如果数据库管理员在每次创建完用户后,都要分别对各个用户进行授权,那么这将会是一件非常麻烦的事情,但如果把具有相同权限的用户集中在角色中进行管理,则会方便很多。

对一个角色进行权限管理,就相当于是对该角色中的所有成员进行管理。使用角色的好处是数据库管理员只需要对权限的种类进行划分,然后将不同的权限授予不同的角色即可,而不必关心具体有哪些用户。除此之外,当角色中的成员发生变化时,比如添加或删除成员,数据库管理员也无须为此进行任何关于权限的操作。

下面就通过示例代码来演示角色授权与取消功能的使用方法。

1)创建一个角色develop,命令如下:

2)为角色develop授予select、insert、update、delete权限,命令如下:

3)为用户zhangsan@'%'赋予角色develop,并创建密码“123456”,命令如下:

4)将用户zhangsan的默认角色设置为develop,命令如下:

注意,set default role语句允许为用户设置默认角色,用户连接时会自动启用此角色,即建立连接后立即执行隐式语句set role develop。

5)查看角色,命令如下:

执行结果如图1-6所示。

图1-6 角色信息查询

6)若要临时取消用户zhangsan的角色develop,可使用如下命令:

注意,临时取消用户的角色后,如果需要再次为用户赋予角色,就需要重新使用set default role语句对用户赋权。

7)回收用户zhangsan的角色develop的命令如下:

注意,使用revoke命令回收角色后,如果需要再次为用户赋予角色,就需要重新使用grant命令对用户赋权。

8)删除角色develop的命令如下:

5.支持线程池技术

默认情况下,数据库会为每个客户端连接分配一个线程(即“thread_handling=one-thread-per-connection”),该线程负责处理该客户端发来的所有指令,但随着并发请求数的增加,该模式的性能会下降。

为了满足不断增长的用户、查询和数据通信量对性能和扩展性的持续需求,MariaDB引入了线程池技术。线程池提供了一种具有高扩展性的线程处理模型,旨在减少客户端连接和语句执行线程的开销,减少CPU上下文的切换操作,非常适合高并发PHP短连接的应用场景。

注意,该技术不适用于长连接!如果生产环境采用的是阿里巴巴集团开源的druid连接池,则不需要开启线程池。

下面通过现实中的例子来解释线程池的作用。堵车的时候,所有人都想先走,你不让我,我不让你,结果就是谁都没法过去,都被堵着,这就好比是没有线程池的情况(如图1-7所示)。但如果有一个交警来指挥堵车路段的交通,大家按照次序排着队逐个通过,就能解决堵车的问题,这里交警的作用就好比是线程池的作用(如图1-8所示)。

使用线程池技术时,在my.cnf配置文件里设置参数thread_handling=pool-of-threads和thread_pool_size=128(其中thread_pool_size的值大小约为CPU内核数×2)可以显著提高性能(重启mysqld服务即可生效,不用设置其他参数)。

图1-7 没有线程池的情况

图1-8 有线程池的情况

下面看看使用线程池技术后若出现连接数不断增长的并发请求,以及通信量较大的在线应用,其性能和扩展性持续改善的效果(具体见表1-1和表1-2)。Facebook官方性能压力测试报告如图1-9和图1-10所示。

在sysbench只读模式下,未开启线程池和开启线程池每秒处理请求的次数(QPS)见表1-1中的测试数据。

表1-1 sysbench只读模式下的测试数据

图1-9 sysbench只读模式中的每秒处理请求的次数

由图1-9可以看到,在只读模式下,与未开启线程池相比,当并发连接数超过2048个时,参数thread_handling设置为pool-of-threads要比one-thread-per-connection更有优势。

在sysbench读写模式下,未开启线程池和开启线程池每秒处理请求的次数见表1-2中的测试数据。

表1-2 sysbench读写模式下的测试数据

图1-10 sysbench读写模式中的每秒请求数

在读写模式下,与未开启线程池相比,当并发连接数超过512个时,参数thread_handling设置为pool-of-threads要比one-thread-per-connection更有优势。

具体详情可参考官网地址:https://mariadb.com/kb/en/threadpool-benchmarks/。

6.开启TLS协议,加密服务器和客户端之间传输的数据

(1)安全连接概述

如果随着业务的发展,拥有DB账号的人越来越多,那么就会存在一个安全隐患,例如,假设周末我们在咖啡厅连接数据库排查问题时,被人用嗅探工具监听,那么发生数据泄密的概率就会大大增加。

为了避免出现泄密问题,需要用SSL(Secure Sockets Layer,安全套接层)协议来对客户端与服务器端之间的通信进行加密。加密后,如果没有密钥,就无法解开加密的数据,从而保证通信的私密性。

默认情况下,客户端(PHP/Java等)连接MySQL/MariaDB传输数据都是不加密的,关于这一点可以通过下面的命令来验证:

执行结果如图1-11所示。

图1-11 默认未开启SSL安全加密

如果服务器支持安全连接,则数据库内部系统中have_ssl的值将调整为YES;如果未编译TLS模块,则have_ssl的值将调整为NO;默认情况下为DISABLED,表示服务器已使用TLS模块进行编译,但未使用TLS模块启动。

(2)设置MariaDB SSL与安全客户端连接

SSL将密钥的加密技术(RSA)作为客户端与服务器端传送数据时的加密通信协议。SSL加密流程如图1-12所示。其中的ca-cert.pem、server-cert.pem、client-key.pem这三个条件缺一不可。

图1-12 SSL加密流程

下面来看一下创建SSL加密连接的步骤。

第一步:升级OpenSSL

由于CentOS 7.9自带的OpenSSL版本太低,其自身的漏洞可能会带来安全隐患,故这里需要先将其升级到最新版。

升级OpenSSL的命令如下:

执行结果如图1-13所示。

图1-13 OpenSSL版本信息

OpenSSL默认安装在/usr/local/bin/目录下。

第二步:创建CA证书

首先,创建CA证书目录mariadb_ssl,命令如下:

然后创建CA证书颁发机构的密钥文件,命令如下:

执行结果如图1-14所示。

图1-14 创建CA证书的密钥文件

最后创建CA证书颁发机构的证书文件,命令如下:

执行结果如图1-15所示。

这里需要注意如下两点。

□“Country Name (2 letter code) [AU]:CN”这里输入CN,表示中国。

□“Common Name (e.g. server FQDN or YOUR name) []:”这里的名字不能重复,请注意图1-15中框线所圈的内容,其值为MariaDB admin。

图1-15 创建CA证书颁发机构的证书文件

第三步:创建服务器端证书

1)创建服务器端密钥文件,命令如下:

执行结果如图1-16所示。

图1-16 创建服务器端密钥文件

这里同样需要注意如下两点。

□“Country Name (2 letter code) [AU]:CN”这里输入CN,表示中国。

□“Common Name (e.g. server FQDN or YOUR name) []:”这里的名字不能重复,请注意图1-16中框线所圈的内容,其值为MariaDB server。

2)创建服务器端RSA密钥文件,命令如下:

执行结果如图1-17所示。

图1-17 创建服务器端RSA密钥文件

3)创建服务器端证书,命令如下:

执行结果如图1-18所示。

图1-18 创建服务器端证书文件

第四步:创建客户端证书

1)创建客户端密钥文件,命令如下:

执行结果如图1-19所示。

图1-19 创建客户端密钥文件

注意,“-days 7”代表密钥有效期为7天,过期后密钥即失效。

这里也需要注意如下两点。

□“Country Name (2 letter code) [AU]:CN”这里输入CN,表示中国。

□“Common Name (e.g. server FQDN or YOUR name) []:”这里的名字不能重复,请注意图1-19中框线所圈的内容,其值为MariaDB client。

2)创建客户端RSA密钥文件,命令如下:

执行结果如图1-20所示。

图1-20 创建客户端RSA密钥文件

3)创建客户端证书,命令如下:

执行结果如图1-21所示。

图1-21 创建客户端证书文件

注意,“-days 7”表示证书有效期为7天,过期后即失效。

第五步:验证证书

以下命令可用于验证证书的有效性:

执行结果如图1-22所示。

图1-22 验证SSL证书

注意,图1-22中的两个“OK”代表SSL证书验证成功。

第六步:MariaDB服务端开启SSL加密

1)编辑my.cnf,添加如下参数:

2)更改SSL证书mysql用户组属性,命令如下:

3)重启mysqld进程,命令如下:

4)输入“show variables like '%ssl%';”查看SSL开启是否成功,如have_ssl的值为YES,则代表已成功开启SSL,执行结果如图1-23所示。

图1-23 SSL证书已开启

第七步:MariaDB客户端使用SSL加密连接

1)创建SSL账号权限,命令如下:

2)通过mysql命令行登录连接。将ca-cert.pem文件、client-cert.pem文件和client-key.pem文件复制到客户端目录下,然后输入下面的命令登录:

登录后,输入status命令,可以看到SSL已建立安全连接,执行结果如图1-24所示。

图1-24 SSL已建立安全连接

3)Sqlyog/Navicat客户端登录连接。因为本书使用的是目前最新版的OpenSSL,所以Sqlyog/Navicat客户端也需要下载最新版本才可以通过验证。

Navicat设置SSL安全连接的界面如图1-25所示。

第八步:SSL加密验证

先使用tcpdump工具嗅探,命令如下:

然后用未加密的用户进行连接,测试脚本如下:

测试结果如图1-26所示,从图中可以看出,非SSL用户数据为明文传输。

图1-25 Navicat设置SSL安全连接

图1-26 非SSL用户数据为明文传输

接着通过SSL加密用户进行连接,测试脚本如下:

测试结果如图1-27所示,从图中的数据表现为乱码形式可以看出,SSL用户数据为加密传输。

图1-27 SSL用户数据加密传输