回顾

各位朋友们好,继上一章我们就完成了用户、密码、权限创建的学习,推荐大家在进行维护时单独创建一个自己的超管用户,然后配置上相应的权限进行维护及学习管理,尽量养成此类习惯,避免直接使用root进行管理,从本章开始我们就进入到入门篇的尾声了,当然这也是最最基础的一章,SQL,本章中还涉及到Mysql中字符集的管理,预生产环境进行压力测试,还有两个小的故障问题原因解析,有SQL基础的同学可以再跟老师简单过一下,没有过学习的同学最好是从第一个SQL敲到最后一个,尽量全部过一遍,总结一份自己对函数的理解笔记,日后可以做到知其然知其所以然,这样才是对SQL理解了,当然最重要的还是在生产中如何去合理运用这些函数,这些就是经验所能带来的收获了,让我们先来开始SQL部分的学习


SQL学习

SQL组成部分:

1.select
2.字段名
3.表名
4.where条件
5.group by
6.order by

来看一条最简单的SQL:查找test表中id大于10的数据并将ID进行倒序处理
select * from test where id>10 order by id desc

SQL函数:

经常使用在where后的函数:
1.between:其结果集等于id>=1 and id<=5
mysql> select * from test where id between 1 and 5;
+----+------+
| id | name |
+----+------+
|  1 | a    |
|  2 | b    |
|  3 | c    |
|  4 | d    |
|  5 | e    |
+----+------+
5 rows in set

2.in / not in:在某个范围的 / 不在某个范围的值
mysql> select * from test where id in(1,2,3);
+----+------+
| id | name |
+----+------+
|  1 | a    |
|  2 | b    |
|  3 | c    |
+----+------+
not in 即为非1,2,3的id数据

3.like :通配符匹配,所有包含a的name行全部展示
mysql> select * from test where 
name like '%a%';
+----+------+
| id | name |
+----+------+
|  1 | a    |
+----+------+

4.regexp:正则匹配^行首 &行尾 .单个任意字符 [abc,a-c]单个字符  [^]非字符 x{3,}至少重复3次 x{3,5}最少3次最多5次(bbb,bbbbb) .*任意个任意字符
mysql> select * from test where name regexp '.*a.*
';
+----+------+
| id | name |
+----+------+
|  1 | a    |
+----+------+

mysql> select * from test where name regexp '[^a
]';
+----+------+
| id | name |
+----+------+
|  2 | b    |
|  3 | c    |
|  4 | d    |
|  5 | e    |
|  6 | f    |
+----+------+

5.逻辑判断:!逻辑非 and逻辑与 or逻辑或 xor逻辑异或(两个数值 一个有值 一个0 则返回true,两个有值/两个0返回false)
mysql> select * from test where name >'c' and name <'e'
;
+----+------+
| id | name |
+----+------+
|  4 | d    |
+----+------+

6.指定行数:limit
select * from xxx limit 5;    从第一行取,取五行(默认第一行ID为0)
mysql> select * from test
 limit 5; 
+----+------+------+
| id | name | num  |
+----+------+------+
|  1 | a    | NULL |
|  2 | b    | NULL |
|  3 | c    | NULL |
|  4 | d    | NULL |
|  5 | e    | NULL |
+----+------+------+

select * from xxx limit 5,2 / limit 2 offset 5(5.7方式);  从第五行取,取两行(第五行的ID为4)
mysql> select * from test limit 2 offset 5
; 
+----+------+------+
| id | name | num  |
+----+------+------+
|  6 | f    | NULL |
|  7 |      | NULL |
+----+------+------+
2 rows in set

mysql> select * from test limit 5,2
; 
+----+------+------+
| id | name | num  |
+----+------+------+
|  6 | f    | NULL |
|  7 |      | NULL |
+----+------+------+

7.添加统计
group by id with rollup 会在count(*)最后一行额外加一行总值
mysql> select name,count(*)
 from test group by name with rollup;
+------+----------+
| name | count(*) |
+------+----------+
|      |        2 |
| a    |        4 |
| b    |        2 |
| c    |        1 |
| d    |        1 |
| e    |        1 |
| f    |        1 |
| NULL |       12 |
+------+----------+

8.子查询:
where id > any (select id from xxx) any代表id大于select子查询中任何一个值就返回
mysql> select * from test where id > any (select id from test where id in (1,2
));
+----+------+------+
| id | name | num  |
+----+------+------+
|  2 | b    | NULL |
|  3 | c    | NULL |
|  4 | d    | NULL |
|  5 | e    | NULL |
|  6 | f    | NULL |
|  7 |      | NULL |
|  8 |      | NULL |
|  2 | b    | NULL |
| 10 | a    | 1.3  |
| 11 | a    | 1.5  |
+----+------+------+

where id > all (select id from xxx) all代表id大于select子查询中全部的值才能返回
mysql> select * from test where id > all (select id from test where id in (1,2
));
+----+------+------+
| id | name | num  |
+----+------+------+
|  3 | c    | NULL |
|  4 | d    | NULL |
|  5 | e    | NULL |
|  6 | f    | NULL |
|  7 |      | NULL |
|  8 |      | NULL |
| 10 | a    | 1.3  |
| 11 | a    | 1.5  |
+----+------+------+

9.exists:只看后面语句是否有行返回,决定是否执行主查询语句
where id exists (select id from xxx)  如果xxx表中id有数据返回(一行或任意行),则返回true,执行查询
where id not exists (select id from xxx) 如果xxx表中id没有数据返回(0行时),则返回true,执行查询,否则不执行
mysql> select * from test where exists (select id from test where id =100);
Empty set

mysql> select * from test where exists (select id from test where id =1
);
+----+------+------+
| id | name | num  |
+----+------+------+
|  1 | a    | NULL |
|  2 | b    | NULL |
|  3 | c    | NULL |
|  4 | d    | NULL |
|  5 | e    | NULL |
|  6 | f    | NULL |
|  7 |      | NULL |
|  8 |      | NULL |
|  1 | a    | NULL |
|  2 | b    | NULL |
| 10 | a    | 1.3  |
| 11 | a    | 1.5  |
+----+------+------+

10.查询合并:union / union all   union会将重复数据进行合并,union all会将重复数据全部显示不进行合并
mysql> select * from test where id=1 union select * from test where id=1 ;
+----+------+------+
| id | name | num  |
+----+------+------+
|  1 | a    | NULL |
+----+------+------+

mysql> select * from test where id=1 union all 
select * from test where id=1 ;
+----+------+------+
| id | name | num  |
+----+------+------+
|  1 | a    | NULL |
|  1 | a    | NULL |

经常使用在select后的函数:
1.case when then:条件判断当某行符合条件将做什么处理,未做处理的行将显示为NULL
mysql> select case id when 1 then 1111 end
 from test;
+------------------------------+
| case id when 1 then 1111 end |
+------------------------------+
|                         1111 |
| NULL                         |
| NULL                         |
| NULL                         |
| NULL                         |
| NULL                         |
+------------------------------+
https://www.cnblogs.com/vincentbnu/p/9495609.html 2.isnull:是否为NULL NULL为1 非NULL为0 参数为字段名 mysql> select isnull(name) from test; +--------------+ | isnull(name) | +--------------+ | 0 | | 0 | | 0 | | 0 | | 0 | | 0 | | 0 | | 1 | +--------------+ 3.开方,求余:sqrt(被开方),mod(被取余,取余数) = 3 0 参数为数字字段名,取余参数2为取余数 mysql> select sqrt(id) from test; +--------------------+ | sqrt(id) | +--------------------+ | 1 | | 1.4142135623730951 | | 1.7320508075688772 | | 2 | | 2.23606797749979 | | 2.449489742783178 | | 2.6457513110645907 | | 2.8284271247461903 | +--------------------+ mysql> select mod(id,2 ) from test; +-----------+ | mod(id,2) | +-----------+ | 1 | | 0 | | 1 | | 0 | | 1 | | 0 | | 1 | | 0 | +-----------+ 4.较小,较大:floor(1.3),ceil(1.5) = 1 2 floor取最近距离的小整数,ceil取最近距离的大整数,参数为字段名 mysql> select floor(num) from test where num is not null ; +------------+ | floor(num) | +------------+ | 1 | | 1 | +------------+ mysql> select ceil (num) from test where num is not null; +-----------+ | ceil(num) | +-----------+ | 2 | | 2 | +-----------+ 5.随机数:rand() = 0.xxxxx mysql> select rand() from test limit 1; +--------------------+ | rand() | +--------------------+ | 0.7435710660587727 | +--------------------+ 1 row in set mysql> select rand() from test limit 1; +--------------------+ | rand() | +--------------------+ | 0.7225432141893946 | +--------------------+ 随机整数 round(rand() * 10,0) mysql> select round(rand() * 10, 0) from test limit 1; +----------------------+ | round(rand() * 10,0) | +----------------------+ | 7 | +----------------------+ 6.截断:round(1.55,1),truncate(1.55,1),format(1.55,1)= 2 1 2 round四舍五入,truncate直接进行小数点后舍弃,format会进行四舍五入,参数1为字段,参数2为需要保留的小数点数量 mysql> select round(1.55,1),truncate(1.55,1),format(1.55,1) from test limit 1; +---------------+------------------+----------------+ | round(1.55,1) | truncate(1.55,1) | format(1.55,1) | +---------------+------------------+----------------+ | 1.6 | 1.5 | 1.6 | +---------------+------------------+----------------+ 7.字符个数:char_length('xxx') = 3 mysql> select char_length('xxx') from test limit 1; +--------------------+ | char_length('xxx') | +--------------------+ | 3 | +--------------------+ 8.字节长度:length('叉叉叉') = 3 mysql> select char_length('叉叉叉 ') from test limit 1; +-----------------------+ | char_length('叉叉叉') | +-----------------------+ | 3 | +-----------------------+ 9.拼接字符:concat('x','y') = xy mysql> select concat('x','y') fro m test limit 1; +-----------------+ | concat('x','y') | +-----------------+ | xy | +-----------------+ 10.分组并concat 与 oracle wm_concat一样 group_concat(xxx)指定分隔:concat_ws('-','x','y') = x-y 先分组再拼接 mysql> select group_concat( id,name) from test limit 1; +-------------------------------------+ | group_concat(id,name) | +-------------------------------------+ | 1a,2b,3c,4d,5e,6f,7,8,1a,2b,10a,11a | +-------------------------------------+ 先拼接再分组 mysql> select concat_ws('-',id,name ) from test limit 1; +------------------------+ | concat_ws('-',id,name) | +------------------------+ | 1-a | +------------------------+ 11.替换字符:insert('xxxx',2,4,'xx') 字符串,开始位置,替换字符数,替换后的字符串 insert('abc',2,1,'z') = azc mysql> select insert('abc',2,1,'z') from test limit 1; +-----------------------+ | insert('abc',2,1,'z') | +-----------------------+ | azc | +-----------------------+ 12.替换字符:replace('xxx','x','y') = yyy mysql> select replace(name,'a','aaaa') from test; +--------------------------+ | replace(name,'a','aaaa') | +--------------------------+ | aaaa | | b | | c | | d | | e | | f | | | | | | aaaa | | b | | aaaa | | aaaa | +--------------------------+ 13.转小写:lower('XXX') = xxx mysql> select lower('XXX') from test limit 1; +--------------+ | lower('XXX') | +--------------+ | xxx | +--------------+ 14.转大写:upper('xxx') = XXX mysql> select upper ('xxx') from test limit 1; +--------------+ | upper('xxx') | +--------------+ | XXX | +--------------+ 15.截取字符:left('xxx',2) right('xxy',2) = xxx 左边前2个字符xx xxy 右边前2个字符xy mysql> select left('xaa',2),right('xaa',2 ) from test limit 1; +---------------+----------------+ | left('xaa',2) | right('xaa',2) | +---------------+----------------+ | xa | aa | +---------------+----------------+ 截取字符:substring('xxx',1,3)/substring('xxx',-1,1) = xxx x 从第几位数字开始取 并取几位 mysql> select substring('abc',2,1 ) from test limit 1; +----------------------+ | substring('abc',2,1) | +----------------------+ | b | +----------------------+ 16.空格生成:space(4) = 几个空格 4个 mysql> select space(4) from test limit 1; +----------+ | space(4) | +----------+ | | +----------+ 17.字符位置:field('xx','xx','yy') = xx在 xx yy中第一次出现的位置1匹配到则true 匹配不到则false mysql> select field('xx','zz ','yy') from test limit 1; +-----------------------+ | field('xx','zz','yy') | +-----------------------+ | 0 | +-----------------------+ mysql> select field('xx','xx','yy') from test limit 1 ; +-----------------------+ | field('xx','xx','yy') | +-----------------------+ | 1 | +-----------------------+ 字符位置:find_in_set('xx','xx,yy,xy') = xx在一组字符出现位置1 匹配到则true 匹配不到则false mysql> select find_in_set('xx','zz, yy') from test limit 1; +---------------------------+ | find_in_set('xx','zz,yy') | +---------------------------+ | 0 | +---------------------------+ mysql> select find_in_set('xx','xx,yy ') from test limit 1; +---------------------------+ | find_in_set('xx','xx,yy') | +---------------------------+ | 1 | +---------------------------+ 18.字符反转:reverse('xy') = xy反转yx mysql> select reverse('xy') from test limit 1; +---------------+ | reverse('xy') | +---------------+ | yx | +---------------+ 19.转换类型 / 转换字符集 convert(123,signed)格式成整数类型 / convert('new string' USING gb2312) 格式化成gbk字符集 convert格式化时可选的类型如下: 字符型,可带参数 : CHAR() 日期 : DATE 时间: TIME 日期时间型 : DATETIME 浮点数 : DECIMAL 整数 : SIGNED 无符号整数 : UNSIGNED 20.去重:distinct mysql> select dist inct name from test; +------+ | name | +------+ | a | | b | | c | | d | | e | | f | | | +------+ 经常使用的时间函数:由于日期函数较为简单,大家要自己的环境进行练习即可,只要实现了函数显示的意义就是正确的 1.系统时间:current_time() / now() 2.系统日期:current_date() / now() 3.系统日期及时间:current_timestamp() / sysdate() / localtime() / now() 4.日期转秒:unix_timestamp(now()) = 从1970-1-1 00-00-00至now()的秒数 秒转日期:from_unixtime(1528948482) = 2018-06-13 16:59:42 5.取年份:year(now()) 6.取季度:quarter(now()) 7.取月份:month(now()) / 8.取周:week(now(),1)从周一为第1天开始计算 9.取天:dayofyear(now()) / dayofmonth(now()) /dayofweek(now())返回在一周的某一天(周日为第1天) 10.取分钟:minute(now()) = 提取当前时间的分钟 11.取秒:second(now()) = 提取当前时间的秒 12.单独提取:extract(month from now()) = 提取当前日期的月份 13.日期增加:date_add(now(),INTERVAL 1 second/year/month/day..) = 当前日期加1秒 14.日期减少:date_sub(now(),INTERVAL 1 second/year/month/day..) = 当前日期减1秒 15.时间增加:addtime(now(),'01:01:01') = 当前时间加1时1分1秒 16.时间减少:subtime(now(),'01:01:01') = 当前时间减1时1分1秒 17.时间间隔:datediff(date_add(now(),INTERVAL 1 day),now()) = 1 18.时间格式化:date_format(now(),'%Y_%m_%d %H:%i:%S')

以上只是简单介绍了SQL的部分函数及用法,但在生产中怎么去运用这些函数还是需要大家具体需求具体分析,SQL的东西说多有很多,说少也很少,因为要看你所在的公司是否有这块的需要,有的业务可能报表数据需求量大,那你的SQL必需有较高的执行效率,不仅仅是函数的使用,还要取决于你对业务的熟悉程度,并且以什么方式去写SQL会更好一些,尽量去避免哪些SQL书写方式,SQL执行计划的查看,索引创建的类型,执行计划是否是我们认为最佳的,这些都要去考虑,所以更多的SQL知识应该是在优化中体现的,而SQL只是基础中的基础,此篇文章只介绍了大部分使用到的函数,更多的语法如果大家有需要可以去度娘再进行查阅,基本的使用是很简单而且方便的,下面我们就开始进行Mysql中字符集配置的讲解


Mysql字符集

字符集通俗来讲就是我们生产中人与人使用的语言,如果你是中国人去和其他中国人交流,那最后做的事情基本就是对的,因为你和他在相同的语言环境,并且他理解你说的是中文,而如果你是与外国人交流,但是你以为外国人说的是中文,实际上并不是,此时就会出现错误,在数据库中的体现就是乱码的情况,所以在数据库建立初期我们就要将字符集进行配置好,一般情况下我们使用unicode:utf8字符集即可,但在Mysql中utf8其实并不是真正的utf8,为什么这么说呢,因为utf8并不支持一些4位字节表情的存储,所以Mysql后期又出了一款utf8的超集utf8mb4
MySQL在5.5版本后增加utf8mb4的编码,专门用来兼容四字节的unicode 大部分是表情类数据,并且utf8mb4是utf8的超集(超集可以理解为父子关系,utf8mb4是父集,utf8是子集,父集拥有子集的全部特征,并且承现的方式是一样的),如果要做迁移,除了将编码改为utf8mb4外不需要做其他转换,当然,如果没有这类的存储需求,为了节省空间,一般情况下使用utf8也就够了。

查看当前Mysql的字符集配置:

mysql> show variables like '%char%';
+--------------------------------------+----------------------------------+
| Variable_name                        | Value                            |
+--------------------------------------+----------------------------------+
| character_set_client                 | utf8mb4                          |
| character_set_connection             | utf8mb4                          |
| character_set_database               | utf8                             |
| character_set_filesystem             | binary                           |
| character_set_results                | utf8mb4                          |
| character_set_server                 | utf8                             |
| character_set_system                 | utf8

character_set_client:Mysql client端的字符集配置
character_set_connection:Mysql连接过程中的字符集配置
character_set_database:Mysql server端的字符集配置
character_set_filesystem:OS文件系统的字符集
character_set_results:Mysql返回结果的字符集配置
character_set_server:Mysql server变量的字符集配置

其实我们只需要将三个变量的字符集配置一致就不会出现乱码情况了:
1)终端 client:utf8
2)Mysql server:utf8
3)数据库:utf8

修改字符集配置:

只对当前运行环境生效,重启Mysql后会失效:set names utf8;

追加至配置文件中,重启后也会生效:
1)5.6需要配置[client] [mysql] [mysqld] :character-set-client=utf8
2)5.7配置[mysqld] 也决定了[client]:character-set-server=utf8

压力测试sysbench

当我们有新的业务需要上线,或想查看我们的硬件服务器最大可以支撑的多大的并发量时,我们可以用压力测试工具去进行数据库模拟测试读写,此类工具可以给我们对当前硬件环境可支撑的一个评测值,像老师经常在新业务上线时使用的工具:sysbench就是针对于Mysql进行并发读写的压测工具,此工具分为两部分,准备数据和跑数据,在最终会反馈给我们此次压测的结果,如:TPS值/QPS值/可能死锁数量,有了这些数据我们就可以和线上服务器监控性能进行对比,查看我们的新服务器是否可以足以支持未来的并发访问,同时我们也可以根据这些数据去向上级做报告,如果你的硬件不足以支持未来的压力情况,那我们就可以向上级进行反馈,至于最终能不能加新硬件那就不是我们能管控的事情了,至少我们已经做好我们需要做的了,我们下面来看一下如何去使用这款工具,并对最终结果进行分析,先来了解一下TPS、QPS的意义

1.tps 每秒事务处理量(包括增删改) 大概在几千,小公司在几百
2.qps 每秒请求处理数(包含增删改查)大概在几万,小公司在几千

下面我们开始进行压力测试工具sysbench安装及使用:

1.安装
  1)安装依赖包:yum -y install make automake libtool pkgconfig libaio-devel vim-common
  2)下载工具包:yum install sysbench

2.安装时问题:
1)cannot found –lmysqlclient_r 缺少函数库,但是有函数库文件
    1.sysbench软件版本过低 或 数据库版本高
    2.函数库变量未加载配置ld,配置文件/etc/ld.so.conf.d/mysql 添加/usr/local/mysql/lib/执行ldconfig
    3.操作系统与软件兼容问题

3.sysbench使用
1.构造数据(往内存中写数据)oltp-table-size=需要构造数据行数
 sysbench --test=oltp --mysql-db=test --mysql-table-engine=innodb --db-driver=mysql --mysql-user=root --mysql-password=123456 --mysql-host=localhost --mysql-socket=/data/mysql/mysql.sock --oltp-table-size=100000 prepare

 Creating table 'sbtest'...
Creating 100000 records in table 'sbtest'...

2.跑数据(从内存往磁盘写数据,thread数与cpu数量可以相同)
sysbench --test=oltp --mysql-db=test --mysql-table-engine=innodb --db-driver=mysql --mysql-user=root --mysql-password=123456 --mysql-host=localhost --mysql-socket=/data/mysql/mysql.sock ––oltp-table-size=100000 --num-threads=16 run

Running the test with following options:
Number of threads: 16
Random number generator seed is 0 and will be ignored

Doing OLTP test.
Running mixed OLTP test
Using Special distribution (12 iterations,  1 pct of values are returned in 75 pct cases)
Using "BEGIN" for starting transactions
Using auto_inc on the id column
Maximum number of requests for OLTP test is limited to 10000
Using 1 test tables
Threads started!
Done.

3.参数信息
--test=oltp使用OLTP方式(事务型)
--mysql-db=test测试使用的数据库
--mysql-table-engine=innodb根据你的业务选择存储引擎,一般为innodb
--db-driver=mysql连接Mysql使用的驱动
--mysql-user=root用户名
--mysql-password=123456密码
--mysql-host=localhost主机IP
--mysql-socket=/data/mysql/mysql.sock连接Socket文件 或 使用--mysql-port=3306
––oltp-table-size=100000构造的数据条目数量
--num-threads=16数据刷新至磁盘时的线程数量

4.其他参数
  1)oltp-read-only=off:不进行只读测试,使用读写模式
  2)report-interval=10:每10秒输出一次报告
  3)rand-type=uniform:随机类型为固定模式
  4)max-time=120:最大执行时间
  5)max-requests=0:最大请求数,因为设置了最大执行时间,此处设置了0
  6)percentile=99:采样比例,取99%的值取最大值

4.压力测试报告
  数据部分:
1)Transactions 每秒tps量
2)Read/write requests 每秒qps量
3)Deadlocks 处理死锁数
4)Total time 总花费时间

OLTP test statistics:
    queries performed:
        read:                            140238
        write:                           50044
        other:                           20020
        total:                           210302
    transactions:                        10003  (1648.70 per sec.)
    deadlocks:                           14     (2.31 per sec.)
    read/write requests:                 190282 (31362.37 per sec.)
    other operations:                    20020  (3299.71 per sec.)

General statistics:
    total time:                          6.0672s
    total number of events:              10003
    total time taken by event execution: 96.7289
    response time:
         min:                                  6.08ms
         avg:                                  9.67ms
         max:                                 25.05ms
         approx.  95 percentile:              12.06ms

Threads fairness:
    events (avg/stddev):           625.1875/24.81
    execution time (avg/stddev):   6.0456/0.01

由上面的结果我们可以看到老师这台服务器最大可以支撑1w/s的事物处理,一般在中小型公司此数据完全足以支撑业务访问,当然还是要具体对比你的生产业务服务器,这与你的磁盘类型也有很大的关系,如果是SAS与固态类磁盘此数据会差距很大,一般至少可以快上几倍,多则十几倍,因为只数据就是内存与磁盘交互的数据信息,此处老师的环境是SAS磁盘,现在一般生产上都会使用固态磁盘,因为现在磁盘发展的速度很快,并且现在固态也已经很廉价了,大概在两万左右就可以拿下一块固态盘,线上业务我们是拿的四块固态磁盘做RAID10,如果条件不足可以适当降级为RAID5,但是我不建议大家这样做,因为RAID的级别对Mysql的影响还是很大的,此处影响主要指在有磁盘发生故障时的读性能


Mysql连接问题Too many connections

出现此问题证明当前连接数量已经超过了我们配置Mysql允许的最大连接数量,我们可以来看一下当前配置的连接数是多少,来看一下操作

show variables like '%变量名%':这种方式可以查看当时某些变量的参数配置

root@db 09:46:  [(none)]> show variables like '%connections%';
+----------------------+-------+
| Variable_name        | Value |
+----------------------+-------+
| max_connections      | 2     |
| max_user_connections | 0     |
+----------------------+-------+

可以看到当前我们配置的是2,2只是为了实验使用,方便我们看错误信息,一般生产上配置512左右即可,此值是持续保持与Mysql连接的数量,所以我们有时单单配置这个参数还不足够,如果连接Mysql之后一直保持连接不断开,那些我们的连接总有不够用的时候,并且会占用连接资源,所以我们还需要配置如下的超时参数:

将以下两个timeout参数配置300即可,可以根据你的业务进行调整,建议两者配置一致
wait_timeout:非交互式超时时间
interactive_timeout:交互式超时时间

root@db 09:55:  [(none)]> show variables like 'wait_timeout'; 
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| wait_timeout  | 300   |
+---------------+-------+
root@db 09:55:  [(none)]> show variables like 'interactive_timeout';        
+---------------------+-------+
| Variable_name       | Value |
+---------------------+-------+
| interactive_timeout | 300   |
+---------------------+-------+

除了基本的外连接数量控制,超时连接配置,还有一个参数,因为每一个连接就需要一个线程去处理连接所有的请求,所以我们还需要对线程数量进行控制,如果线程数过多也会导致数据库负载过高down机情况!

线程最大数限制是否开启 默认0不开启代表不进行限制,如果并发会话不超过60 可以配置为0,如果并发用户忽高忽低 如 40 50 80 150 200  建议先配置成128 观察 再逐步降低或增加 如90 80  如果80性能最好 那最终配置成80,连接数量可以根据show full processlist的总数量去评估,一般要比此连接数大1.5倍左右

root@db 09:55:  [(none)]> show variables like 'innodb_thread_concurrency';
+---------------------------+-------+
| Variable_name             | Value |
+---------------------------+-------+
| innodb_thread_concurrency | 128   |
+---------------------------+-------+

来看一下,如果超过连接数时,Mysql端得到的错误信息如下,一般生产上按照之前我们配置文件中所写的参数值就足以支撑中小型业务了,如果你的公司对数据这部分比较重视的话,可以配合开发人员,让开发人员在程序端写一个连接线程池,将每次的连接可以进行复用,这样可以节省部分连接开启关闭的资源消耗,并且可以控制会话过多而导致数据库出现问题,Mysql商业版是有这个功能的,但是一般我们使用的都是社区版

[root@localhost ~]# /usr/local/mysql/bin/mysql -uroot -p
Enter password: 
ERROR 1040 (HY000): Too many connections

Mysql内存不足

在Mysql中内存是重中之重,我们的索引及数据都将放置到内存当中,如果内存不够大可以性能就会有影响,但如果内存配置过大,可以会导致操作系统承受不了相应的压力导致崩溃,而内存中最占大小的则是BUFFER_POOL,一般我们将此值配置为物理内存的50%-70%即可,初期建议配置为50%,后续可以慢慢增加,mysql5.7已经支持热增加BUFFER_POOL的大小了,我们来看一下当物理内存不足以支撑BUFFER_POOL大小配置时会发生的问题

1.Cannot allocate memory for the buffer pool(现有内存不能承担buffer pool)
2.ibdata1 is of a different size xx page than spacified in the .cnf file initial  xxx page  / could not open or create the system tablespace 
3.解决:
1)动态扩容(内存/磁盘)
2)释放内存(热数据快速加载回来)

一般生产下不会出现内存不足的情况,因为之前老师遇到过这个问题,是在练习环境下,但根据此问题大家应该了解不能将buffer_pool的大小配置过高,甚至超过物理内存的大小,这样是非常不合理的


小结

在本章中我们学习了常见SQL函数的使用,压力测试工具sysbench安装及使用,Mysql连接数控制,Buffer_pool的配置,本章内容对于老手来说算是很基础的部分了,但对于刚入门的同学,大家一定要将SQL部分多加练习,SQL是基础中的基础,在工作中也许会用很多,也许不会用太多,但是你一定要会,压力测试工具给我们带来的报告可以让我们根据反馈结果数据编写压力测试报告及解决方案,向上反馈给领导,领导看到也会觉得你工作比较规范比较专业,最后我们提到了连接数的问题,还有不懂的同学可以查阅一下官方文档,或向老师询问,尽量把入门这块的东西多练习一下,因为后面的知识会更多,前面如果掌握不好,就多来回练习几遍然后再开始进行基础篇学习,下章我们先将Mysql的日常管理命令及技巧进行一个总结,从而开始进行体系结构的学习,Mysql的体系与Oracle相似,但是也有其不同之处,Mysql的线程结构,Mysql的存储引擎,Mysql的物理文件等等我们都将一一学习,大家在下面的文章开始必须将全部的知识都掌握住,只要有不懂的地方就一定要问,同学们也可以在交流群里互相学习,让我们下章再会!