运维必会之MySQL篇
第一章 SQL语句
语言分类
1)DDL(data definition language)数据定义语言(create、alter、drop)
管理基础数据
例如:库、表 #<==运维要熟练,开发也要熟练。
2)DCL(data control language)数据控制语言(grant、revoke、commit、rollback)
用户授权,权限收回,数据提交,回滚等
3)DML(data manipulation language)数据操作语言(select、insert、delete、update)
针对表里的数据进行操作,记录
第二章 命令详解
修改数据库密码
库外修改:
1)mysqladmin -uroot -pnfsnobody -S /data/3306/mysql.sock passwordnfsnobody123
库内修改:
1)grant all on *.* to admin@'%' identified by 'nfsnobody123' with grant option;
查看:show grants for admin@'%';
2)update mysql.user set password = password('nfsnobody123') where user = 'root' and host = 'localhost'; #修改root@localhost密码为nfsnobody123
flush privileges; #刷新统权表
库基础命令
创建数据库
create database <数据库名>
例:
mysql> create database test1;
查看数据库
show databases;
例:
mysql> show databases;
+--------------------------------+
| Database |
+---------------------------------+
| information_schema |
| mysql |
| test1 |#刚才创建的库
+---------------------------------+
查看建库语句
show create database <数据库名>\G
例:
mysql> show create database test1\G
*************************** 1. row***************************
Database: test1#库名
Create Database: CREATE DATABASE `test1`/*!40100 DEFAULT CHARACTER SET utf8 */ #字符集
创建任意已知字符集数据库
create database <数据库名> character set <字符集> collate <全称>;
例:
mysql> create database test2 character set gbk collate gbk_chinese_ci; #创建字符集为gbk的库
查看:
mysql> show create database test2\G
*************************** 1. row ***************************
Database: test2
Create Database: CREATE DATABASE `test2` /*!40100 DEFAULT CHARACTER SET gbk */
create database nfsnobody; #<==默认数据库配置,相当于创建拉丁字符集数据库
create database nfsnobody_gbk DEFAULT CHARACTER SET gbk COLLATE gbk_chinese_ci; #<==创建gbk字符集数据库
create database nfsnobody_utf8 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; #<==创建utf8字符集数据库
查询指定数据库
show databases like <条件>;
例:
mysql> show databases like '%te%'; # “%“ 模糊匹配
+-------------------------+
| Database (%te%) |
+-------------------------+
| test |
| test1 |
| test2 |
+-------------------------+
切换数据库
use <数据库名>
例:
mysql> use test1;
Database changed
mysql> use test2
Database changed
查看当前所在库
select database();
例:
mysql> select database();
+-------------------+
| database() |
+-------------------+
| test2 |
+-------------------+
查看库中表
show tables;
例:
mysql> show tables;
Empty set (0.00 sec) #表示此库中没有表
查询用户
select user,host from mysql.user;
例:
mysql> select user,host from mysql.user;
+----------+------------------+
| user| host |
+----------+------------------+
| admin | % |
| root| 127.0.0.1 |
| root| ::1 |
|| d01 |
| root| d01 |
|| localhost |
| root| localhost |
+----------+------------------+
删除用户
drop user <user> <host>;
例:
mysql> drop user admin@'%';
查看:
mysql> select user,host from mysql.user;
+----------+------------------+
| user| host |
+----------+------------------+
| root| 127.0.0.1 |
| root| ::1 |
|| d01 |
| root| d01 |
|| localhost |
| root| localhost |
+----------+------------------+
***** 当drop无法删除时候 *****
delete from mysql.user where user='<用户>' andhost='<主机>';
例:
mysql> delete from mysql.user whereuser='root' and host='db01';
查看:
mysql> select user,host from mysql.user;
+----------+------------------+
| user| host |
+----------+------------------+
| root| 127.0.0.1 |
| root| ::1 |
|| d01 |
|| localhost |
| root| localhost |
+----------+------------------+
用户授权
grant <权限> on <数据库>.<表> to <用户>@<主机>identified by <密码>;
例:
mysql> grant all on *.* touser@'10.0.0.%' identified by '123456';
***** 权限说明 *****
权限 | 说明 |
---|---|
select | 查询权限 |
insert | 插入权限 |
update | 更新用户、密码权限 |
delete | 删除权限 |
drop | 删除权限 |
reload | 重新读取权限 |
shutdown | 关闭权限 |
process | 查询用户进程权限 |
file | 文件权限 |
references | 将其它表字段作为外键约束权限 |
index | 索引权限 |
alter | 添加,删除索引权限 |
showdatabases | 查看数据库权限 |
super | 超级管理员权限 |
createtemporary tables | 创建临时表权限 |
locktables | 锁表权限 |
execute | 执行权限 |
replicationslave | 主从同步权限 |
replicationclient | 复制客户端权限 |
createview | 创建查看权限 |
showview | 查看创建查看权限 |
createroutine | 所有创建权限 |
alterroutine | 所有增加、删除权限 |
createuser | 创建用户权限 |
event | 事件权限 |
trigger | 触发权限 |
createtablespace | 创建表空间权限 |
生产场景常用重要命令小结:
show processlist; #查看数据库里正在执行的SQL语句,可能无法看全完整SQL语句。
show full processlist #查看正在执行的完整SQL语句,完整显示。
set global key_buffer_size =1024*1024*32 #不重启数据库调整数据库参数,直接生效,重启后失效。
show variables; #查看数据库的配置参数信息,例如:my.cnf里参数的生效情况。
show variables like'%log_bin%';"
kill ID #杀掉SQL线程的命令,ID为线程号。
show session status #查看当前会话的数据库状态信息
show global status; #查看整个数据库运行状态信息,很重要,要分析并要做好监控。
show engine innodb status; #显示innodb引擎的性能状态(早期版本show innodbstatus)。
表基础命令
建表语法
create table student( #<== createtable 表示创建表的固定关键字,student为表名
id int(4) not null, #<== 学号列,数字类型,长度为4,不为空值。
name char(20) not null, #<== 名字列,定长字符类型,长度20,不为空值。
age tinyint(2) NOT NULL default '0', #<== 年龄列,很小的数字类型,长度为2,不为空,默认为0值。
dept varchar(16) default NULL #<== 系别列,变长字符类型,长度16,默认为空。
) ENGINE=InnoDB DEFAULT CHARSET=latin1; #<== 引擎和字符集,引擎默认为innodb,字符集,继承库的latin1
***** 数字类型 *****
列类型 | 需要的存储量 |
---|---|
TINYINT | 1字节 |
SMALLNT | 2个字节 |
MEDIUMINT | 3个字节 |
INT | 4个字节(4294967296) |
BIGINT | 8个字节 |
FLOAT(X) | 4如果X <=24 或 8 如果25<=x <=53 |
FLOAT | 4个字节 |
***** 日期类型*****
列类型 | 需要的存储量 |
---|---|
DATE | 3字节 |
DATETIME | 8个字节 |
TIMESTAMP | 4个字节 |
TIME | 3个字节 |
YEAR | 1个字节 |
***** 字符串类型 *****
列类型 | 需要的存储量 |
---|---|
CHAR(M) | M字节,1<=M<=255字节 |
VARCHAR(M) | L+1字节,在此L<=M和1<=M<=255 |
TINYBLOB,TINYTEXT | L+1字节,在此L< 2 ^ 8 |
BLOB,TEXT | L+2字节,在此L< 2 ^ 16 |
***** 一幅图说明 VARCHAR 之间的差别 *****
值 | CHAR(4) | 存储需求 | VARCHAR | 存储需求 |
---|---|---|---|---|
‘‘ | ’ ‘ | 4个字节 | ‘‘ | 1个字节 |
’ab’ | ‘ab ‘ | 4个字节 | ‘ab’ | 3个字节 |
‘abcd’ | ‘abcd’ | 4个字节 | ‘abcd’ | 5个字节 |
‘abcdefgh’ | ‘abcd’ | 4个字节 | ‘abcd’ | 5个字节 |
生产环境创建表
CREATE TABLE`subject_comment_manager` (
`subject_comment_manager_id` bigint(12) NOT NULL auto_increment COMMENT'主键',
`subject_type` tinyint(2) NOT NULL COMMENT '素材类型',
`subject_primary_key` varchar(255) NOT NULL COMMENT '素材的主键',
`subject_title` varchar(255) NOT NULL COMMENT '素材的名称',
`edit_user_nick` varchar(64) default NULL COMMENT '修改人',
`edit_user_time` timestamp NULL default NULL COMMENT '修改时间',
`edit_comment` varchar(255) default NULL COMMENT '修改的理由',
`state` tinyint(1) NOT NULL default '1' COMMENT '0代表关闭,1代表正常',
PRIMARY KEY(`subject_comment_manager_id`),
KEY `IDX_PRIMARYKEY` (`subject_primary_key`(32)), #<==括号内的32表示对前32个字符做前缀索引。
KEY `IDX_SUBJECT_TITLE` (`subject_title`(32))
KEY `index_nick_type` (`edit_user_nick`(32),`subject_type`)#<==联合索引,此行为新加的,用于给大家讲解的。实际表语句内没有此行。
) ENGINE=InnoDB AUTO_INCREMENT=1DEFAULT CHARSET=utf8;
创建索引
查看索引方法:
descstudent; ##大致查看
showindex from student; ##详细查看
showindex from student\G ##竖着查看
主键索引:要求列的内容是唯一的。
普通索引:一个表内可以创建多个。
联合索引:多个表创建一个索引,加大唯一性。
唯一索引:生产使用不多,但是针对登录账号可以选择。
1)创建主键索引:
CREATE TABLE `student` (
`id` int(4) NOT NULL auto_increment,
`name` char(20) NOT NULL,
`age` tinyint(2) NOT NULL DEFAULT '0',
`dept` varchar(16) DEFAULT NULL,
primary key(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
如果在建表的时候,没有创建索引,可以使用alter来创建索引:
mysql> alter table student add primarykey(id);
查看:
mysql>desc student;
mysql> alter table student change id idint(4) auto_increment; #==》改为自增
2)创建普通索引:
CREATE TABLE `student` (
`id` int(4) NOT NULL auto_increment,
`name` char(20) NOT NULL,
`age` tinyint(2) NOT NULL DEFAULT '0',
`dept` varchar(16) DEFAULT NULL,
primary key(id),
KEY index_name(name)
);
其它创建索引方法:
mysql> create index ind_dept onstudent(dept);
mysql> alter table student add indexindex_age(age);
删除索引:
mysql> alter table student drop indexind_dept;
针对前八个字符创建索引:
alter table student add indexindex_dept(name(8));
create index index_dept onstudent(dept(8));
###的内容很多,可以取列的一部分来创建索引。
3)创建联合索引:
多个列创建联合索引,唯一值更少,数据更精确。
create index ind_name_dept onstudent(name,dept);
create index ind_name_deptnew onstudent(name(8),dept(8)); ##根据前8个字符创建联合索引
mysql> select count(distinct host) frommysql.user; #查看列的唯一值数量
mysql> select distinct user frommysql.user; #查看有哪些唯一数值
4)创建唯一索引(多用于创建登录账号):
mysql> create unique indexuni_index_name on student(name);
问题1、既然索引可以加快查询速度,那么就给所有的列建索引吧?
解答:因为索引不但占用存储空间,而且更新数据时还需要维护索引数据的,因此,索引是一把双刃剑,并不是越多越好,例如:数十到数百行的小表上无需建立索引,插入更新频繁,读取比较少的表要尽量不建立索引。
问题2、需要在哪些列上创建索引才能加快查询速度呢?
解答:select user,host from mysql.user where password=…,索引一定要创建在where后的条件上,而不是select后的选择数据的列上,另外,我们要尽量选择在唯一值多的大表上的列建立索引,例如,男女性别列唯一值少,不适合建立索引。
创建索引的基本知识小结:
1、索引类似书籍的目录,会加快查询数据的速度。
2、要在表的列(字段)上创建索引。
3、索引会加快查询的速度,但是也会影响更新的速度,因为更新要维护索引数据。
4、索引列并不是越多越好,要在频繁查询的表语句where后的条件列上创建索引。
5、小表或重复值很多的列上可以不创建索引。要在大表以及重复值少的条件列上创建索引。
6、多个联合索引有前缀生效特性。
7、当字段内容前N个字符已经接近唯一时,可以对字段的前N个字符创建索引。
8、索引从工作方式区分,有主键,唯一,普通索引。
9、索引类型会有BTREE(默认)和hash(适合做缓存(内蕴数据库))等、
创建索引相关命令小结:
1、创建主键索引:
alter table student change id id intprimary key auto_increment;
2、删除主键索引(主键列不能自增):
alter table student drop primary key;
3、创建普通索引:
alter table student add indexindex_dept(dept);
4、根据列的前n个字符创建普通索引:
create index index_dept onstudent(dept(8));
5、根据多个列创建联合普通索引:
create index ind_name_dept onstudent(name,dept);
6、根据多个列的前n个字符创建联合普通索引:
create index ind_name_dept onstudent(name(8),dept(10));
7、创建唯一索引:
create unique index uni_ind_name onstudent(name);
8、查看索引:
desc student;
show index from student;
9、删除普通索引与唯一索引:
alter table student drop index index_dept;
drop index index_dept on student;
10、查看表记录唯一值的数量:
select count(distinct user) frommysql.user;
select count(distinct (user,host)) frommysql.user;
增删改表的字段
1、增加字段语法:alter table 表名 add字段类型 其他;
练习:
首先创建一个新表
mysql> CREATE TABLE `test` (
-> `id` int(4) NOT NULLAUTO_INCREMENT,
-> `name` char(20) NOT NULL,
-> PRIMARY KEY (`id`)
-> ) ENGINE=InnoDBDEFAULT CHARSET=latin1;
查看:
增加一个字段:
mysql> alter table test add sex char(4);
查看:
在name后面增加一个age字段:
mysql> alter table test add age int(4)after name;
查看:
在第一行插入字段qq:
mysql> alter table test add qq varchar(15)first;
查看:
2、修改字段类型语法:alter table 表名 modify字段类型 其他;
把age字段的类型改为char(4)
mysql> alter table test modify agechar(4) after name;
查看:
3、修改字段名语法:alter table 表名 change 源字段名修改后的字段名 类型 其它;
将字段age改为testage:
mysql> alter table test change age testagechar(4) after name;
表中插数据
语法:insert into [( [,.. ])] values ( 值1 )[, ( 值n )]
添加id为1,名字为zzgx的数据到test表中
mysql> insert into test(id,name)values(1,'zzgx');
查看:
批量插入多条数据
mysql> insert into test(id,name) values(3,'zuma'),(4,'kaka');
查看:
删除表中内容
mysql> delete from test where id=2;
查看:
命令总结:
1、按规矩指定所有列名,并且每列都插入值
insert into test(id,name)values(1,’nfsnobody’);
2、由于id列为自增的,所以,可以只在name列插入值
insert into test(name) values(‘oldgirl’);
insert into test(id,name)values(null,’zhangsan’);
3、如果不指定列,就要按规矩为每列都插入恰当的值。
insert into test values(3,’inca’);
4、批量插入数据方法,提升效率
insert into testvalues(4,’zuma’),(5,’kaka’); <==批量插入2条记录,提升效率。
delete from test;
INSERT INTOtest
VALUES(1,’nfsnobody’),(2,’oldgirl’),(3,’inca’),(4,’zuma’),(5,’kaka’);
查表语句
查询test前2行:
mysql> select * from test limit 2;
查询test前3行:
mysql> select * from test limit 3;
默认升序查询:
mysql> select * from test where id>3or name='zuma' order by id;
按id倒叙查询:
mysql> select * from test where id>3or name='zuma' order by id desc;
查询小结:
1、查看表test中所有数据
(1)直接查询库下面表的数据
select * from nfsnobody.test; #方法1:没有进入nfsnobody数据库的情况
select id from nfsnobody.test; #查看id列的方法
select name from nfsnobody.test; #查看name列的方法
(2)进入指定库查询表的数据
use nfsnobody; #方法1:已经进入nfsnobody数据库的情况
select * from test;
(3)查看MySQL数据库的用户与主机
select user,host from mysql.user; #仅查看用户与主机
select user,host,password frommysql.user; #查看用户与主机与密码
2、根据指定条件查询表的部分信息
例子1:查看test表中的前2条信息
select * from test limit 2;
例子2:查看第1条记录后的两条记录
select * from test limit 1,2;
例子3:指定固定的条件查数据
select * from test where id = 1; #查看指定行的记录,整型一般不需要加引号,不然会导致不经过索引。
select * from test wherename='oldgirl'; #查询字符串的话要加引号
select * from test where id=2 andname='oldgirl'; #多个条件查询
例子4:指定固定条件范围查数据
select * from test where id>2 andid<5; #多个条件,and取交集
select * from test where id>2 orid<5; #多个条件都成立,也就是显示id>2和id<5的所有条件都会显示出来
3、其他查询功能
(1)按照id号进行正向排序
select * from test order by id asc;
(2)按照id号进行倒序排序
select * from test order by id desc;
其它查询:其他查询:子查询,join,union,多表关联查询,分组,having
连表查询
练习:
首先创建3个表:
表一:
mysql> create table student(
Sno int(10) NOT NULL COMMENT '学号',
Sname varchar(16) NOT NULL COMMENT '姓名',
Ssex char(2) NOT NULL COMMENT '性别',
Sage tinyint(2) NOT NULL default'0' COMMENT '学生年龄',
Sdept varchar(16) defaultNULL COMMENT '学生所在系别',
PRIMARY KEY (Sno) ,
key index_Sname (Sname)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=UTF8;
Query OK, 0 rows affected (0.02 sec)
表二:
mysql> create table course(
Cno int(10) NOT NULL COMMENT '课程号',
Cname varchar(64) NOT NULL COMMENT '课程名',
Ccredit tinyint(2) NOT NULL COMMENT '学分',
PRIMARY KEY (Cno)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=UTF8;
Query OK, 0 rows affected (0.00 sec)
表三:
mysql> CREATE TABLE `SC` (
SCid int(12) NOT NULL auto_incrementCOMMENT '主键',
`Cno` int(10) NOT NULL COMMENT '课程号',
`Sno` int(10) NOT NULL COMMENT '学号',
`Grade` tinyint(2) NOT NULL COMMENT '学生成绩',
PRIMARY KEY (`SCid`)
) ENGINE=InnoDB DEFAULT CHARSET=UTF8;
Query OK, 0 rows affected (0.01 sec)
查看:
往student表中插入内容:
mysql> INSERT INTO studentvalues(0001,'宏志','男',30,'计算机网络');
mysql> INSERT INTO studentvalues(0002,'王硕 ','男',30,'computer application');
mysql> INSERT INTO student values(0003,'nfsnobody','男',28,'物流管理');
mysql> INSERT INTO studentvalues(0004,'脉动','男',29,'computer application');
mysql> INSERT INTO studentvalues(0005,'oldgirl','女',26,'计算机科学与技术');
mysql> INSERT INTO student values(0006,'莹莹','女',22,'护士');
查看:
往course表中插入内容:
mysql> INSERT INTO coursevalues(1001,'Linux中高级运维',3);
mysql> INSERT INTO coursevalues(1002,'Linux高级架构师',5);
mysql> INSERT INTO coursevalues(1003,'MySQL高级Dba',4);
mysql> INSERT INTO course values(1004,'Python运维开发',4);
mysql> INSERT INTO coursevalues(1005,'Java web开发',3);
查看:
往SC表中插入数据:
mysql> INSERT INTOSC(Sno,Cno,Grade) values(0001,1001,4);
mysql> INSERT INTOSC(Sno,Cno,Grade) values(0001,1002,3);
mysql> INSERT INTOSC(Sno,Cno,Grade) values(0001,1003,1);
mysql> INSERT INTOSC(Sno,Cno,Grade) values(0001,1004,6);
mysql> INSERT INTOSC(Sno,Cno,Grade) values(0002,1001,3);
mysql> INSERT INTOSC(Sno,Cno,Grade) values(0002,1002,2);
mysql> INSERT INTO SC(Sno,Cno,Grade) values(0002,1003,2);
mysql> INSERT INTO SC(Sno,Cno,Grade) values(0002,1004,8);
mysql> INSERT INTO SC(Sno,Cno,Grade) values(0003,1001,4);
mysql> INSERT INTO SC(Sno,Cno,Grade) values(0003,1002,4);
mysql> INSERT INTO SC(Sno,Cno,Grade) values(0003,1003,2);
mysql> INSERT INTO SC(Sno,Cno,Grade) values(0003,1004,8);
mysql> INSERT INTO SC(Sno,Cno,Grade) values(0004,1001,1);
mysql> INSERT INTO SC(Sno,Cno,Grade) values(0004,1002,1);
mysql> INSERT INTO SC(Sno,Cno,Grade) values(0004,1003,2);
mysql> INSERT INTO SC(Sno,Cno,Grade) values(0004,1004,3);
mysql> INSERT INTO SC(Sno,Cno,Grade) values(0005,1001,5);
mysql> INSERT INTO SC(Sno,Cno,Grade) values(0005,1002,3);
mysql> INSERT INTO SC(Sno,Cno,Grade) values(0005,1003,2);
mysql> INSERT INTO SC(Sno,Cno,Grade) values(0005,1004,9);
查看:
连表查询:
mysql> selectstudent.Sno,student.Sname,course.Cname,SC.Grade from student,course,SC wherestudent.Sno=SC.Sno and course.Cno=SC.Cno;
第三章 MySQL优化
SQL语句优化
1、硬件层面优化
1.1数据库物理机采购:
1.2服务器硬件配置调整
1.2.1服务器BIOS调整:
1.2.2阵列卡调整:
2、软件层优化
2.1操作系统层面优化
2.1.1操作系统及MySQL实例选择
2.1.2文件系统层优化
2.1.3linux内核参数优化
2.2mysql数据库层面优化
2.2.1my.cnf参数优化
2.2.2关于库表的设计规范
2.2.3SQL语句的优化
3、网站集群架构上的优化
4、流程,制度,安全优化
使用explain优化SQL语句
1、抓慢查询SQL语句方法:
a、救火:紧急且重要:show full processlist;(登录数据库现场抓,连续执行2次,超过2秒)
mysql –uroot –pnfsnobody –S /data/3306/mysql.sock–e “show full processlist;”|egrep –vi “sleep”
b、未雨绸缪:重要不紧急,记录意思分析慢查询日志。
配置参数记录慢查询语句:
long_query_time = 2 ### 超过2秒,记录到Slow Log里。
log_queries_not_using_indexes ### 没有走索引的语句,记录到Slow Log里。
log-slow-queries = /data/3306/slow.log ### Slow Log 文件。
min_examined_row_limit ### 记录结果集大于指定值的SQL语句,5.6-5.7都可以使用
c、慢查询日志切割:
脚本:
#!/bin/bash
cd /data/3306/ &&\
/bin/mv slow.log slow.log.$(date +%F) &&\
mysqladmin -uroot -pnfsnobody123 -S /data/3306/mysql.sock flush-log
定时任务:
#cut mysql slow log
00 00 * * * /bin/sh /server/scripts/cut_slow_log.sh >/dev/null2>&1
2、explain语句检查索引执行情况:
mysql> explain select * from studentwhere Sname='nfsnobody'\G
mysql> explain select SQL_NO_CACHE *from student where Sname='nfsnobody'\G
3、对需要建索引的条件列建立索引
生产场景,大表高峰期不能建立索引,例如:300玩记录。
4、分析慢查询SQL的工具mysqlsla(每天早很发邮件给核心开发、运维、CTO)
5、按天切割慢查询日志,如果并发太大可以按小时,去重分析后发给大家。
a.mv然后flush进程。
b.cp复制,然后利用>清空。
c.定时任务 mv /data/3306/slow.log/opt/$(date +%F)_slow.log
d.mysqladmin –uroot–pnfsnobody –S /data/3306/mysql.sock flush-logs
6、日常优化
dba、总监、开发、CTO联合解决。
索引优化
1)白名单机制 – 百度,项目开发,DBA暗语,减少上线后的慢SQL数量;
抓出慢SQL
配置my.cnf
long_query_time = 2 ### 超过2秒,记录到Slow Log里。
log_queries_not_using_indexes ### 没有走索引的语句,记录到Slow Log里。
log-slow-queries = /data/3306/slow.log ### Slow Log 文件。
min_examined_row_limit ### 记录结果集大于指定值的SQL语句,5.6-5.7都可以使用
按天轮询:slow-log
2)慢查询日志分析工具 —–mysqlsla 或 pt-query-digest(推荐);
3)每天晚上0点定时分析慢查询,发到核心开发,DBA分析,及高级运维,CTO的邮箱里;
DBA分析给出优化建议 à 核心开发确认更改 à DBA线上操作处理;
4)定期使用pt-duplicate-key-checker检查并删除重复的索引;
定期使用pt-index-usage工具检查并删除使用频率很低的索引;
5)使用pt-online-schema-change来完成大表的ONLINE DDL 需求;
6)有时候mysql会使用错误的索引,对于这种情况使用USE INDEX;
7)使用explain及set profile 优化SQL语句;
8)打的复杂的SQL语句拆分成多个小的SQL语句;
子查询,JOIN连表查询,某个表4000万条记录;
9)数据库是存储数据的地方,但是不是计算数据的地方;
对于数据计算、应用处理、都要拿到前端应用解决、禁止在数据库上处理;
10)使用连接(JOIN)来代替子查询;
11)避免在整个表上使用count(*),他可能锁住整张表;
12)多表连接查询时,把结果集小的表作为驱动表;
13)多表联接并且有排序时,排序字段必须是驱动表里的,负责排序列无法用到索引;
14)尽量去掉”IN” ”OR”“<>”
15)类似分页功能的SQL,建议先用主键关联,然后返回结果集,效率会高很多;
第四章 MySQL日志
error log 错误日志
开启方法:
vim /etc/my.cnf
[mysqld_safe]
log-error=/data/3306/mysql_nfsnobody3306.err
在库内查看错误日志:
show variables like"%err%";
访问日志
开启方法:
vim /etc/my.cnf
[mysqld]
general_log = on
general_log_file =/data/3306/data/MySQL_nfsnobody.log
临时生效:
mysql> set globalgeneral_log_file = "/data/3306/data/MySQL_nfsnobody.log";
mysql> show variables like'general_log%';
mysql> set global general_log =on;
慢查询日志
开启方法:
vim /etc/my.cnf
long_query_time = 2 ### 超过2秒,记录到Slow Log里。
log_queries_not_using_indexes ### 没有走索引的语句,记录到Slow Log里。
log-slow-queries =/data/3306/slow.log ### Slow Log 文件。
min_examined_row_limit ### 记录结果集大于指定值的SQL语句,5.6-5.7都可以使用
二进制日志
介绍:
二进制日志(binary log):记录数据库里的数据被修改
(insert、update、delete、create、drop、alter)的相关语句,用户主从复制及增量恢复;
调整:
bin-log文件切割条件:
a、数据库重启,自动切割新文件;
b、mysqldump –F/mysqladmin flush-logs;
c、文件达到1.1G,自动切割;
d、认为配置及调整;
删除:
a、设置参数自动删除
vim /etc/my.cnf
expire_logs_days = 7 #<==删除7天前的日志
b、从头删到指定的文件位置
mysql> purge binary logs to'mysql-bin.000004';
Query OK, 0 rows affected (0.03 sec)
mysql> system ls -l/data/3306/mysql-bin*
-rw-rw---- 1 mysql mysql 126 8月 21 16:31 /data/3306/mysql-bin.000004
-rw-rw---- 1 mysql mysql 126 8月 21 16:32 /data/3306/mysql-bin.000005
-rw-rw---- 1 mysql mysql 15881 8月 28 19:16 /data/3306/mysql-bin.000006
-rw-rw---- 1 mysql mysql 84 8月 28 19:26 /data/3306/mysql-bin.index
c、按照时间删除
mysql> PURGE MASTER LOGS BEFORE'2016-08-28 13:00:00';
Query OK, 0 rows affected (0.02 sec)
mysql> system ls -l/data/3306/mysql-bin*
-rw-rw---- 1 mysql mysql 15881 8月 28 19:16 /data/3306/mysql-bin.000006
-rw-rw---- 1 mysql mysql 28 8月 28 19:28 /data/3306/mysql-bin.index
mysql> PURGE MASTER LOGS BEFOREDATE_SUB(NOW( ), INTERVAL 3 DAY);
Query OK, 0 rows affected (0.00 sec)
mysql> system ls -l/data/3306/mysql-bin*
-rw-rw---- 1 mysql mysql 15881 8月 28 19:16 /data/3306/mysql-bin.000006
-rw-rw---- 1 mysql mysql 28 8月 28 19:28 /data/3306/mysql-bin.index
Mysql binlog的三种模式
statement level (默认语句模式)
每一条被修改数据的sql都会记录到master的bin-log中。slave在复制的时候sql进程会解析成和原来master端执行过的相同sql来再次执行。
例如:
100w:
update nfsnobody setname=’tingting’
bin-log里面:
只记录一条:update nfsnobody setname=’tingting’
优点:statementlevel下的有点首先就是解决了row level下的缺点,不需要记录每一行数据变化,减少bin-log日志量,节约磁盘IO,提高性能。因为他只要记录在master上所执行的语句的细节,以及执行语句时候的上下文信息。
缺点:容易出现主从不一致。
row level(行级模式):
日志中会记录成每一行数据被修改的情况,然后在slave端再对数据进行修改。
例如:
100w:
update nfsnobody setname=’tingting’
bin-log里面:
100w条:update nfsnobody set name=’tingting’
优点:主从一致,逐行记录,记录很细。
缺点:占用大量磁盘空间,降低磁盘性能,消耗磁盘IO。
mixed(混合模式):
实际上就是前两种模式的结合,在mixed模式下mysql会根据执行的每一条具体的sql语句来区分对待记录的日志形式,也就是在statement和row之间选择一种。
例如:
智能模式
100w:
update nfsnobody setname=’tingting’
bin-log里面:
只记录一条:update nfsnobody setname=’tingting’使用语句模式
函数,触发器,存储过程:使用row-level
bin-log模式选择
a、互联网公司,使用mysql的功能相对少(存储过程、触发器、函数)
选择默认的语句模式,statement(默认)。
b、公司如果用到使用mysql的特殊功能(存储过程、触发器、函数)
则选择mixed模式。
c、公司如果用到使用mysql的特殊功能(存储过程、触发器、函数),又希望数据最大化一致
此时最好的选择:row-level模式。
解析bin-log日志方法
mysqlbinlog --base64-output=decode-rows -v mysql-bin.000007