修改用户
mysql> alter user root@'localhost' identified by '123';
授权用户管理
ALL:
SELECT,INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE
ALL :以上所有权限,一般是普通管理员拥有的
(1)语法:
grant ALL on wordpress.* to wordpress@'10.0.0.%' identified by '123';
grant权限 on 范围 to 用户 identified by '密码'
grant select,update,insert,delete on范围 to 用户 identified by '密码'
范围:
*.*
wordpress.*
wordpress.t1
(2)例子:
1.从windows中的navicat软件使用root管理mysql数据库
grant all on *.* to root@'10.0.0.%' identified by '123';
2.创建 zhihu业务用户能够对zhihu业务库进行业务操作
grant select,update,delete ,insert on zhihu.* to zhihu@'10.0.0.%' identified by '123';
(3)思考一个问题(课后自己进行验证):
1. grant select,update on *.* to oldboy@'10.0.0.%';
2. grant delete on wordpress.* to oldboy@'10.0.0.%';
3. grant insert on wordpress.t1 to oldboy@'10.0.0.%';
问,oldboy@'10.0.0.%'能对t1表具备什么权限?
MySQL中的权限是可以继承,多次授权是叠加的。
所以,想要取消某个权限,必须通过回收的方式实现,而不能多次重复授权。
(4)查看用户权限
mysql> show grants for root@'localhost';
(5)回收权限
mysql> revoke delete on zhihu.* from 'zhihu'@'10.0.0.%';
######MySQL的配置文件的配置常用参数####
[mysqld]
user=mysql
basedir=/application/mysql
datadir=/data/mysql/data
socket=/tmp/mysql.sock
server_id=6
port=3306
log_error=/data/mysql/data/mysql.log
log_bin=/data/mysql/data/mysql-bin
[mysql]
socket=/tmp/mysql.sock
#####数据定义语言#####
库
(1)建库
mysql> create database oldguo charset utf8mb4;
mysql> show databases;
mysql> show create database oldguo;
(2)改库
mysql> alter database oldguo1 charset utf8mb4;
(3)删库
mysql> drop database oldguo1;
表
create table oldguo (
ID int not null primary key AUTO_INCREMENT comment '学号',
name varchar(255) not null comment '姓名',
age tinyint unsigned not null default 0 comment '年龄',
gender enum('m','f','n') NOT null default 'n' comment '性别'
)charset=utf8mb4 engine=innodb;
--例子:
--在上表中添加一个手机号列15801332370.(重点*****)
-- alter table oldguo add telnum char(11) not null unique comment '手机号';
--练习:
--添加一个状态列
ALTER TABLE oldguo ADD state TINYINT UNSIGNED NOT NULL DEFAULT 1 COMMENT '状态列';
--查看列的信息
DESC oldguo;
--删除state列(不代表生产操作)
ALTER TABLE oldguo DROP state;
-- online-DDL : pt-osc (自己研究下***)
--在name后添加 qq 列 varchar(255)
ALTER TABLE oldguo ADD qq VARCHAR(255) NOT NULL UNIQUE COMMENT 'qq' AFTER NAME;
--练习 在name 之前添加wechat列
ALTER TABLE oldguo ADD wechat VARCHAR(255) NOT NULL UNIQUE COMMENT '微信' AFTER ID;
--在首列上添加 学号列:sid(linux58_00001)
ALTER TABLE oldguo ADD sid VARCHAR(255) NOT NULL UNIQUE COMMENT '学生号' FIRST;
--修改name数据类型的属性
ALTER TABLE oldguo MODIFY NAME VARCHAR(128) NOT NULL ;
DESC oldguo;
--将gender 改为 gg 数据类型改为 CHAR 类型
ALTER TABLE oldguo CHANGE gender gg CHAR(1) NOT NULL DEFAULT 'n' ;
DESC oldguo;
DML数据操作语言
7.2.1 INSERT
---最简单的方法插入数据
DESC oldguo;
INSERT INTO oldguo VALUES(1,'oldguo','22654481',18);
---最规范的方法插入数据(重点记忆)
INSERT INTO oldguo(NAME,qq,age) VALUES ('oldboy','74110',49);
---查看表数据(不代表生产操作)
SELECT * FROM oldguo;
7.2.2 UPDATE (注意谨慎操作!!!!)
UPDATE oldguo SET qq='123456' WHERE id=5 ;
7.2.3 DELETE (注意谨慎操作!!!!)
DELETE FROM oldguo WHERE id=5;
7.2.4生产需求:将一个大表全部数据清空
DELETE FROM oldguo;
TRUNCATE TABLE oldguo;
DELETE和 TRUNCATE 区别
1. DELETE逻辑逐行删除,不会降低自增长的起始值。
效率很低,碎片较多,会影响到性能
2. TRUNCATE,属于物理删除,将表段中的区进行清空,不会产生碎片。性能较高。
7.2.5生产需求:使用update替代delete,进行伪删除
ALTER TABLE oldguo ADD state TINYINT NOT NULL DEFAULT 0 ;
DELETE FROM oldguo WHERE id=6;
替换为
UPDATE oldguo SET state=1 WHERE id=6;
SELECT * FROM oldguo ;
SELECT * FROM oldguo ;
改为
SELECT * FROM oldguo WHERE state=0;
1.1作用
获取MySQL中的数据行
1.2单独使用select
1.2.1 select @@xxxx;获取参数信息。
mysql> select @@port;
mysql> show variables like '%innodb%';
1.2.2 select函数();
mysql> select database();
mysql> select now();
mysql> select version();
1.3 SQL92标准的使用语法
1.3.1 select语法执行顺序(单表)
select开始 ---->
from子句 --->
where子句--->
group by子句--->
select后执行条件--->
having子句 ---->
order by ---->
limit
--- 1.3.2 FROM
---例子:查询city表中的所有数据
USE world;
SELECT * FROM city; --->适合表数据行较少,生产中使用较少。
SELECT * FROM world.city;
---例子: 查询name和population的所有值
SELECT NAME , population FROM city;
SELECT NAME , population FROM world.city;
单表查询练习环境:world数据库下表介绍
SHOW TABLES FROM world;
city(城市):
DESC city;
id:自增的无关列,数据行的需要
NAME:城市名字
countrycode:城市所在的国家代号,CHN,USA,JPN。。。。
district :城市的所在的区域,中国是省的意思,美国是洲的意思
population:城市的人口数量
说明:此表是历史数据,仅供学习交流使用。
熟悉业务:
刚入职时,DBA的任务
1.搞清楚架构
通过公司架构图,搞清楚数据库的物理架构
1-2天
逻辑结构:
(1)生产库的信息(容易达到)
(2)库下表的信息(非常复杂)
(1) 找到建表语句,如果有注释,读懂注释。如果没有注释,只能根据列名翻译
(2) 找到表中部分数据 ,分析数据特点,达到了解列功能的目录
1.3.3 where
--- 1.3.3 WHERE
---例子:
--- WHERE配合 等值查询(=)
---查询中国的城市信息
SELECT *
FROM world.city
WHERE countrycode='CHN';
---查询美国的城市信息
SELECT *
FROM world.city
WHERE countrycode='USA';
--- WHERE配合 不等值(> < >= <= <>)
---查询一下世界上人口小于100人的城市
SELECT *
FROM world.city
WHERE population<100;
---查询世界上人口大于10000000的城市
略。
--- WHERE配合 模糊(LIKE)
---查询国家代号是C开头的城市
SELECT *
FROM world.city
WHERE countrycode
LIKE 'C%';
---注意:like 语句在MySQL中,不要出现%在前面的情况。因为效率很低,不走索引。
---错误的里
SELECT *
FROM world.city
WHERE countrycode
LIKE '%C%';
--- WHERE配合 逻辑连接符(AND OR)
---查询城市人口在1w到2w之间的城市
SELECT *
FROM city
WHERE population >= 10000
AND Population <= 20000;
SELECT *
FROM city
WHERE population
BETWEEN 10000 AND 20000;
---查询一下中国或美国的城市信息
SELECT *
FROM city
WHERE countrycode='CHN' OR countrycode='USA';
SELECT *
FROM city
WHERE countrycode IN ('CHN','USA');
建议改写为,以下语句:
SELECT *
FROM city
WHERE countrycode='CHN'
UNION ALL
SELECT *
FROM city
WHERE countrycode='USA';
--- 1.3.4 GROUP BY配合聚合函数应用
AVG()
COUNT()
SUM()
MAX()
MIN()
GROUP_CONCAT()
---统计每个国家的总人口
SELECT countrycode,SUM(population) FROM city GROUP BY countrycode ;
---统计每个国家的城市个数
GROUP BY countrycode
城市id,name
COUNT(id)
SELECT countrycode,COUNT(id) FROM city GROUP BY countrycode;
---统计并显示 每个国家的省名字列表
SELECT countrycode,GROUP_CONCAT(district) FROM city GROUP BY countrycode;
---统计中国每个省的城市名列表
SELECT District,GROUP_CONCAT(NAME)
FROM city
WHERE countrycode='CHN'
GROUP BY district;
---统计一下中国,每个省的总人口数
SELECT district ,SUM(population) FROM city
WHERE countrycode='CHN'
GROUP BY district
---统计一下中国,每个省的平均人口
SELECT district ,AVG(population) FROM city
WHERE countrycode='CHN'
GROUP BY district
--- 1.3.5 HAVING
---统计中国,每个省的总人口大于1000w的省及人口数
SELECT district ,SUM(population) FROM city
WHERE countrycode='CHN'
GROUP BY district
HAVING SUM(population)>10000000
说明: having后的条件是不走索引的,可以进行一些优化手段处理。
--- 1.3.6 ORDER BY
SELECT district ,SUM(population) FROM city
WHERE countrycode='CHN'
GROUP BY district
ORDER BY SUM(population) DESC ;
---例子:查询中国所有的城市,并以人口数降序输出
SELECT * FROM city WHERE countrycode='CHN' ORDER BY population DESC;
--- 1.3.7 LIMIT
SELECT *
FROM city
WHERE countrycode='CHN'
ORDER BY population DESC
LIMIT 5;
SELECT *
FROM city
WHERE countrycode='CHN'
ORDER BY population DESC
LIMIT 10;
SELECT *
FROM city
WHERE countrycode='CHN'
ORDER BY population DESC
LIMIT 5,3;
SELECT *
FROM city
WHERE countrycode='CHN'
ORDER BY population DESC
LIMIT 3 OFFSET 5;
LIMIT M,N跳过M行,显示N行
LIMIT X OFFSET Y跳过Y行,显示X行
1.4多表连接查询
1.4.1介绍4张测试表的关系
略。
1.4.2什么时候用?
需要查询的数据是来自于多张表时。
1.4.3怎么去多表连接查询
(1)传统的连接:基于where条件
1.找表之间的关系列
2.排列查询条件
select name,countrycode from city whrere population<100;
PCN
select name,surfacearea from country where code='PCN'
---人口数量小于100人的城市,所在国家的国土面积(城市名,国家名,国土面积)
select city.name,country.name ,country.surfacearea
from city,country
where city.countrycode = country.code
and city.population<100
(2)内连接 *****
A B
A.x B.y
1.找表之间的关系列
2.将两表放在join左右
3.将关联条件了放在on后面
4.将所有的查询条件进行罗列
select A.m,B.n
from
A join B
on A.x=B.y
where
group by
order by
limit
---例子:
--- 1.查询人口数量小于100人的国家名,城市名,国土面积
SELECT country.name,city.name,country.surfacearea
FROM
city JOIN country
ON city.countrycode=country.code
WHERE city.population<100;
--- 2.查询oldguo老师和他教课程名称
SELECT teacher.tname ,course.cname
FROM teacher
JOIN course
ON teacher.tno=course.tno
WHERE teacher.tname='oldguo';
SELECT teacher.`tname` ,course.`cname`
FROM teacher
JOIN course
ON teacher.`tno`=course.`tno`
WHERE teacher.`tname`='oldboy';
--- 3.统计一下每门课程的总成绩
SELECT course.cname,SUM(sc.score)
FROM course
JOIN sc
ON course.cno = sc.cno
GROUP BY course.cname;
-- 5.7版本会报错的情况,在sqlyog中以下操作没问题
--但是在命令行上是会报错
SELECT course.cno,course.cname,SUM(sc.score)
FROM course
JOIN sc
ON course.cno = sc.cno
GROUP BY course.cname;
mysql> SELECT course.cno,course.cname,SUM(sc.score)
-> FROM course
-> JOIN sc
-> ON course.cno = sc.cno
-> GROUP BY course.cname;
ERROR 1055 (42000): Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'school.course.cno' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
1.在select后面出现的列,不是分组条件,并且没有在函数中出现。
2.如果group by 后是主键列或者是唯一条件列,不会报出错误。如下:
SELECT
course.cno,course.cname,SUM(sc.score) FROM course
JOIN sc
ON course.cno = sc.cno
GROUP BY course.cno;
(3)外链接 ****
自连接(自己了解)
--- 4.查询oldguo老师教的学生姓名列表
SELECT teacher.tname,GROUP_CONCAT(student.sname)
FROM teacher
JOIN course
ON teacher.tno = course.tno
JOIN sc
ON course.cno = sc.cno
JOIN student
ON sc.sno = student.sno
WHERE teacher.tname='oldguo'
GROUP BY teacher.tname;
--- 5.查询所有老师教的学生姓名列表
SELECT teacher.tname,GROUP_CONCAT(student.sname)
FROM teacher
JOIN course
ON teacher.tno = course.tno
JOIN sc
ON course.cno = sc.cno
JOIN student
ON sc.sno = student.sno
GROUP BY teacher.tno;
--- 6.查询oldboy老师教的不及格学生的姓名
SELECT teacher.tname,GROUP_CONCAT(student.sname)
FROM teacher
JOIN course
ON teacher.tno = course.tno
JOIN sc
ON course.cno = sc.cno
JOIN student
ON sc.sno = student.sno
WHERE teacher.tname='oldboy' AND sc.score<60
GROUP BY teacher.tno;
--- 7.统计zhang3,学习了几门课
SELECT student.`sname` ,COUNT(sc.`cno`)
FROM student
JOIN sc
ON student.`sno`=sc.`sno`
WHERE student.sname='zhang3';
--- 8.查询zhang3,学习的课程名称有哪些?
SELECT student.sname,GROUP_CONCAT(course.`cname`)
FROM student
JOIN sc
ON student.`sno`=sc.`sno`
JOIN course
ON sc.`cno`=course.`cno`
WHERE student.`sname`='zhang3';
--- 9.查询oldguo老师教的学生名.
SELECT teacher.tname,GROUP_CONCAT(student.sname)
FROM teacher
JOIN course
ON teacher.tno = course.tno
JOIN sc
ON course.cno = sc.cno
JOIN student
ON sc.sno = student.sno
WHERE teacher.tname='oldguo'
GROUP BY teacher.tname;
--- 10.查询oldguo所教课程的平均分数
SELECT teacher.tname ,course.`cname`,AVG(sc.`score`)
FROM teacher
JOIN course
ON teacher.`tno`=course.`tno`
JOIN sc
ON course.`cno`=sc.`cno`
WHERE teacher.tname='oldguo';
--- 11.每位老师所教课程的平均分,并按平均分排序
SELECT teacher.tname ,course.`cname`,AVG(sc.`score`)
FROM teacher
JOIN course
ON teacher.`tno`=course.`tno`
JOIN sc
ON course.`cno`=sc.`cno`
ORDER BY AVG(sc.`score`);
--- 12.查询oldguo所教的不及格的学生姓名
SELECT teacher.tname,GROUP_CONCAT(student.sname)
FROM teacher
JOIN course
ON teacher.tno = course.tno
JOIN sc
ON course.cno = sc.cno
JOIN student
ON sc.sno = student.sno
WHERE teacher.tname='oldguo' AND sc.score<60
GROUP BY teacher.tno;
--- 13.查询所有老师所教学生不及格的信息
SELECT teacher.tname,GROUP_CONCAT(student.sname)
FROM teacher
JOIN course
ON teacher.tno = course.tno
JOIN sc
ON course.cno = sc.cno
JOIN student
ON sc.sno = student.sno
WHERE sc.score<60;
1. distinct去重复
select sum(单价*数量) from (select 牌子,单价,数量 from 啤酒
union all
select牌子,单价,数量 from 饮料
union all
select牌子,单价,数量 from 矿泉水);
2. 别名
表别名
SELECT a.tname ,GROUP_CONCAT(d.sname)
FROM teacher AS a
JOIN course AS b
ON a.tno = b.tno
JOIN sc as c
ON b.cno = c.cno
JOIN student AS d
ON c.sno = d.sno
WHERE a.tname='oldguo' AND c.score<60
GROUP BY a.tno;
列别名
select count(distinct(name)) as个数 from world.city;
3. 外连接
SELECT a.name,b.name ,b.surfacearea
FROM city AS a
LEFT JOIN country AS b
ON a.countrycode=b.code
WHERE a.population<100
4. information_schema.tables
元数据?
----> “基表”(无法直接查询和修改的)
----> DDL进行元数据修改
----> show ,desc(show),information_schema(全局类的统计和查询)
use information_schema
TABLE_SCHEMA表所在的库
TABLE_NAME表名
ENGINE表的存储引擎
TABLE_ROWS表的行数
AVG_ROW_LENGTH平均行长度
INDEX_LENGTH索引的长度
-- information_schema
---查询整个数据库中所有的库对应的表名
例如:
world city
world country
oldboy oldguo
SELECT table_schema,table_name
FROM information_schema.tables;
---查询world和school库下的所有表名
SELECT table_schema,table_name
FROM information_schema.tables
WHERE table_schema='world'
UNION ALL
SELECT table_schema,table_name
FROM information_schema.tables
WHERE table_schema='school';
---查询整个数据库中所有的库对应的表名,每个库显示成一行
SELECT table_schema,GROUP_CONCAT(table_name)
FROM information_schema.tables
GROUP BY table_schema;
---统计一下每个库下的表的个数
SELECT table_schema,COUNT(table_name)
FROM information_schema.tables
GROUP BY table_schema;
---统计一下每个库的真实数据量
每张表数据量=AVG_ROW_LENGTH*TABLE_ROWS+INDEX_LENGTH
SELECT
SUM(AVG_ROW_LENGTH*TABLE_ROWS+INDEX_LENGTH)/1024/1024 AS total_mb
FROM information_schema.TABLES
--- information_schema.tables+CONCAT(),拼接命令
---使用方法举例
mysql> SELECT CONCAT(USER,"@","'",HOST,"'") FROM mysql.user;
---生产需求1
mysqldump -uroot -p123 world city >/tmp/world_city.sql
---模仿以上命令,对整个数据库下的1000张表进行单独备份,
---排除sys,performance,information_schema
mysqldump -uroot -p123 world city >/tmp/world_city.sql
SELECT CONCAT("mysqldump -uroot -p123 ",table_schema," ",table_name," >/tmp/",table_schema,"_",table_name,".sql")
FROM information_schema.tables
WHERE table_schema NOT IN('sys','performance','information_schema')
INTO OUTFILE '/tmp/bak.sh';
vim /etc/my.cnf
secure-file-priv=/tmp
/etc/init.d/mysqld restart
---例子:模仿以下语句,批量实现world下所有表的操作语句生成
alter table world.city discard tablespace;
select concat("alter table ",table_schema,".",table_name,"discard tablespace;")
from information_schema.tables
where table_schema='world'
into outfile '/tmp/discard.sql';
show databases; 查看所有数据库名
show tables; 查看当前库下的表名
show tables from world; 查看world数据库下的表名
show create database 查看建库语句
show create table 查看建表语句
show grants for root@'localhost' 查看用户权限信息
show charset 查看所有的字符集
show collation 查看校对规则
show full processlist 查看数据库连接情况
show status 查看数据库的整体状态
show status like '%lock%' 模糊查看数据库的整体状态
show variables 查看数据库所有变量情况
show variables like '%innodb%' 查看数据库所有变量情况
show engines 查看所有支持存储引擎
show engine innodb status 查看所有innodb存储引擎状态情况
show binary logs 查看二进制日志情况
show binlog events in 查看二进制日志事件
show relaylog events in 查看relay日志事件
show slave status 查看从库状态
show master status 查看数据库binlog位置信息
show index from 查看表的索引情况
mysql> alter table t100w add index idx_k2(k2);
mysql> desc t100w
mysql> show index from t100w\G
mysql> alter table t100w add unique index idx_k1(k1);
mysql> alter table city add index idx_name(name(5));
mysql> alter table city add index idx_co_po(countrycode,population);
mysql> alter table city drop index idx_co_po;
show create table city;
表空间管理
alter table t1 discard tablespace;
alter table t1 import tablespace;
最大安全模式:
innodb_flush_log_at_trx_commit=1
innodb_flush_method=O_DIRECT
最大性能模式:
innodb_flush_log_at_trx_commit=0
innodb_flush_method=fsync
默认位置:
mysql> select @@log_error;
DATADIR/hostname.err
配置方式
vim /etc/my.cnf
log_error=/data/mysql/data/mysql.log
mkdir /data/binlog -p
[root@db01 ~]# vim /etc/my.cnf
log_bin=/data/binlog/mysql-bin
server_id=6
如何查看配置
mysql> show variables like '%log_bin%';
查看日志记录格式
select @@binlog_format;
查看正在使用的二进制日志
mysql> show binary logs;
查看mysql用到哪个position号
mysql> show master status ;
查看二进制日志事件
mysql> show master status ; ##确认当前再用的binlog
mysql> show binlog events in 'mysql-bin.000002'; ##查看2号binlog的事件
注释:每一行都是一个事件
Log_name:日志名
Pos:事件开始的position *****
Event_type:事件类型
Server_id:发生在哪台机器的事件
End_log_pos:事件结束的位置号 *****
Info:事件内容 *****
查看二进制日志内容
[root@db01 /data/binlog]# mysqlbinlog mysql-bin.000002 |grep -v "SET" >/tmp/aa.txt
[root@db01 /data/binlog]# mysqlbinlog --base64-output=decode-rows -vvv mysql-bin.000002
截取二进制日志核心在于,找起点和终点
[root@db01 ~]# mysqlbinlog --start-position=219 --stop-position=322 /data/binlog/mysql-bin.000002 >/tmp/bin.sql
恢复:
mysql> drop database oldboy1;
mysql> show databases;
mysql> set sql_log_bin=0;
mysql> source /tmp/bin.sql
基于时间点的截取(了解)
--start-datetime
--stop-datetime
开启GTID
vim /etc/my.cnf
gtid-mode=on
enforce-gtid-consistency=true
systemctl restart mysqld
查看本机GTID信息
mysql> create database gg;
mysql> show master status;
mysql> use gg;
mysql> create table t1 (id int);
mysql> insert into t1 values(1);
mysql> commit;
mysql> insert into t1 values(2);
mysql> commit;
mysql> insert into t1 values(3);
mysql> commit;
drop database gg;
基于GTID截取二进制日志
[root@db01 ~]# mysqlbinlog --include-gtids='ee956c61-9653-11e9-8518-000c29099eb6:1-5' /data/binlog/mysql-bin.000003 >/tmp/gtid.sql
(蓝色里面的系统号不一样)
正确的截取方法是
[root@db01 ~]# mysqlbinlog --skip-gtids --include-gtids='ee956c61-9653-11e9-8518-000c29099eb6:1-5' /data/binlog/mysql-bin.000003 >/tmp/gtids.sql
####跳过某些gtid不截取
mysqlbinlog --skip-gtids --include-gtids='ee956c61-9653-11e9-8518-000c29099eb6:1-5' --exclude-gtids='ee956c61-9653-11e9-8518-000c29099eb6:2,ee956c61-9653-11e9-8518-000c29099eb6:4' /data/binlog/mysql-bin.000003 >/tmp/gtids.sql
二进制日志其他操作
####临时关闭
set sql_log_bin=0;
说明:
临时关闭二进制日志记录,退出mysql窗口可以恢复
做数据恢复之前,使用以上参数
####自动清理
参数:
mysql> select @@expire_logs_days;
设置依据?
至少是一个全备周期+1,企业建议至少2个全备周期+1
怎么设置?
临时设置,重启失效
mysql> set global expire_logs_days=8;
永久设置,重启生效
vim /etc/my.cnf
expire_logs_days=8
####手工清理
PURGE BINARY LOGS BEFORE now() - INTERVAL 3 day;
PURGE BINARY LOGS TO 'mysql-bin.000003';
注意:不要手工 rm binlog文件
1. my.cnf binlog关闭掉,启动数据库
2.把数据库关闭,开启binlog,启动数据库
删除所有binlog,并从000001开始重新记录日志
删除所有binlog,从000001开始(危险!!!!)
mysql> reset master;
####日志滚动
重启数据库
flush logs
mysqladmin -uroot -p flush-logs
show variables like '%max_binlog_size%';
备份加一些参数,会触发滚动日志
优化相关日志-slowlog
### 1.3.1作用
记录慢SQL语句的日志,定位低效SQL语句的工具日志
开启慢日志(默认没开启)
开关:
slow_query_log=1
文件位置及名字
slow_query_log_file=/data/mysql/slow.log
设定慢查询时间:
long_query_time=0.1
没走索引的语句也记录:
log_queries_not_using_indexes
vim /etc/my.cnf
slow_query_log=1
slow_query_log_file=/data/mysql/slow.log
long_query_time=0.1
log_queries_not_using_indexes
systemctl restart mysqld
mysqldumpslow分析慢日志
mysqldumpslow -s c -t 10 /data/mysql/data/slow.log
基本备份参数
实现全库备份
[root@db01 ~]# mkdir -p /data/backup
[root@db01 ~]# mysqldump -uroot -p123 -A -S /tmp/mysql.sock >/data/backup/full.sql
-B备份 单个库或多个库数据
例子:备份oldboy和world数据库
[root@db01 ~]# mysqldump -uroot -p123 -B world oldboy -S /tmp/mysql.sock >/data/backup/db.sql
库名表名:备份某个库下的1张或多张表
例子:备份world数据库下的city和country表
[root@db01 ~]# mysqldump -uroot -p123 world city country -S /tmp/mysql.sock >/data/backup/tab.sql
必加参数(1)
-R在备份时,同时备份存储过程和函数,如果没有会自动忽略
-E 在备份时,同时备份EVENT,如果没有会自动忽略
--triggers在备份时,同时备份触发器,如果没有会自动忽略
--master-data=2
功能:
3.配合--single-transaction,减少锁的(innodb引擎)
--single-transaction
记录备份开始时position号 ,可以作为将来做日志截取的起点。
使用场景:
1. --set-gtid-purged=OFF,可以使用在日常备份参数中.
mysqldump -uroot -p -A -R -E --triggers --master-data=2 --single-transaction --set-gtid-purged=OFF >/data/backup/full.sql
2. auto , on:在构建主从复制环境时需要的参数配置
mysqldump -uroot -p -A -R -E --triggers --master-data=2 --max-allowed-packet=128M --single-transaction --set-gtid-purged=ON >/data/backup/full.sql
--max-allowed-packet=#
企业的备份恢复案例(mysqldump+binlog)年终故障恢复演练。
案例背景:某中小型互联网公司。MySQL 5.7.26,Centos 7.6 ,数据量级80G,每日数据增量5-6M
备份策略:每天mysqldump全备+binlog备份,每天23:00进行。
故障描述:周三下午2点,数据由于某原因数据损坏。
处理思路:
[root@db01 ~]# mysqldump -uroot -p123 -A -R --triggers -E --master-data=2 --single-transaction >/data/backup/full.sql
[root@db01 ~]# vim /data/backup/full.sql
SET @@GLOBAL.GTID_PURGED='ee956c61-9653-11e9-8518-000c29099eb6:1-2';
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000045', MASTER_LOG_POS=350;
mysql> create database mdp charset utf8mb4;
mysql> use mdp
mysql> create table t1(id int);
mysql> insert into t1 values(1),(2),(3);
mysql> commit;
mysql> insert into t1 values(11),(12),(13);
mysql> commit;
mysql> update t1 set id=20 where id>10;
mysql> commit;
\rm -rf /data/mysql/data/*
pkill mysqld
\rm -rf /data/mysql/data/*
[root@db01 /data/mysql/data]# mysqld --initialize-insecure --user=mysql --basedir=/application/mysql --datadir=/data/mysql/data
[root@db01 /data/mysql/data]# /etc/init.d/mysqld start
mysql> set sql_log_bin=0;
mysql> source /data/backup/full.sql
mysql> flush privileges;
[root@db01 ~]# vim /data/backup/full.sql
SET @@GLOBAL.GTID_PURGED='ee956c61-9653-11e9-8518-000c29099eb6:1-2';
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000045', MASTER_LOG_POS=350;
[root@db01 ~]# mysqlbinlog --skip-gtids --include-gtids='ee956c61-9653-11e9-8518-000c29099eb6:3-7' /data/binlog/mysql-bin.000045 >/data/backup/bin.sql
或者:
[root@db01 ~]# mysqlbinlog --skip-gtids --start-position=350 /data/binlog/mysql-bin.000045 >/tmp/aa.sql
mysql> set sql_log_bin=0;
mysql> source /data/backup/bin.sql
扩展:从全备中导出单表备份
# sed -e'/./{H;$!d;}' -e 'x;/CREATE TABLE `city`/!d;q' full.sql>createtable.sql
# grep -i 'INSERT INTO `city`' full.sqll >data.sql
# sed -n '/^-- Current Database: `world`/,/^-- Current Database: `/p' all.sql >world.sql
mysqldump -uroot -p123 -A -R --triggers --master-data=2 max_allowed_packet=128M --single-transaction|gzip > /backup/full_$(date +%F).sql.gz
2.XBK的应用
2.1安装
2.1.1安装依赖包:
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
yum -y install perl perl-devel libaio libaio-devel perl-Time-HiRes perl-DBD-MySQL libev
2.1.2下载软件并安装
wget https://www.percona.com/downloads/XtraBackup/Percona-XtraBackup-2.4.12/binary/redhat/7/x86_64/percona-xtrabackup-24-2.4.12-1.el7.x86_64.rpm
https://www.percona.com/downloads/XtraBackup/Percona-XtraBackup-2.4.4/binary/redhat/6/x86_64/percona-xtrabackup-24-2.4.4-1.el6.x86_64.rpm
yum -y install percona-xtrabackup-24-2.4.4-1.el7.x86_64.rpm
(主包在58期的QQ群里)
2.2、备份命令介绍:
xtrabackup
innobackupex ******
2.3备份方式——物理备份
(1)对于非Innodb表(比如 myisam)是,锁表cp数据文件,属于一种温备份。
(2)对于Innodb的表(支持事务的),不锁表,拷贝数据页,最终以数据文件的方式保存下来,
把一部分redo和undo一并备走,属于热备方式。
面试题:xbk在innodb表备份恢复的流程
0、xbk备份执行的瞬间,立即触发ckpt,已提交的数据脏页,从内存刷写到磁盘,并记录此时的LSN号
1、备份时,拷贝磁盘数据页,并且记录备份过程中产生的redo和undo一起拷贝走,也就是checkpoint LSN之后的日志
2、在恢复之前,模拟Innodb“自动故障恢复”的过程,将redo(前滚)与undo(回滚)进行应用
3、恢复过程是cp 备份到原来数据目录下
备份过程:
1. ckpt,记录ckpt后LSN ,to lsn
2.拷贝数据页 ,保存为数据文件
3.自动将备份过程redo,会一并备份走,提取最后的last LSN
恢复:
其实就是模拟了CSR过程
对比LAST LSN ,to lsn
使用redo进行前滚,对未提交的事务进行回滚
最后得到一个一致性备份
2.4、innobackupex使用
2.4.1全备
[root@db01 backup]# innobackupex --user=root --password=123 /data/bak
注意:
备份工具是依赖于/etc/my.cnf
[mysqld]
[client]
[innobackupex]
如果说配置文件没有在/etc,可以如下操作
[root@db01 backup]# innobackupex --defaults-file=xxxxx --user=root --password=123 /data/bak
自主定制备份路径名
[root@db01 backup]# innobackupex --user=root --password=123 --no-timestamp /data/bak/full_$(date +%F)
备份集中多出来的文件:
-rw-r----- 1 root root 24 Jun 29 09:59 xtrabackup_binlog_info
-rw-r----- 1 root root 119 Jun 29 09:59 xtrabackup_checkpoints
-rw-r----- 1 root root 489 Jun 29 09:59 xtrabackup_info
-rw-r----- 1 root root 2560 Jun 29 09:59 xtrabackup_logfile
xtrabackup_binlog_info:(备份时刻的binlog位置)
[root@db01 full]# cat xtrabackup_binlog_info
mysql-bin.000003 536749
79de40d3-5ff3-11e9-804a-000c2928f5dd:1-7
记录的是备份时刻,binlog的文件名字和当时的结束的position,可以用来作为截取binlog时的起点。
xtrabackup_checkpoints:
backup_type = full-backuped
from_lsn = 0上次所到达的LSN号(对于全备就是从0开始,对于增量有别的显示方法)
to_lsn = 160683027备份开始时间(ckpt)点数据页的LSN
last_lsn = 160683036备份结束后,redo日志最终的LSN
compact = 0
recover_binlog_info = 0
(1)备份时刻,立即将已经commit过的,内存中的数据页刷新到磁盘(CKPT).开始备份数据,数据文件的LSN会停留在to_lsn位置。
(2)备份时刻有可能会有其他的数据写入,已备走的数据文件就不会再发生变化了。
(3)在备份过程中,备份软件会一直监控着redo的undo,如果一旦有变化会将日志也一并备走,并记录LSN到last_lsn。
从to_lsn ----》last_lsn 就是,备份过程中产生的数据变化.
2.4.2全备的恢复
准备备份(Prepared)
将redo进行重做,已提交的写到数据文件,未提交的使用undo回滚掉。模拟了CSR的过程
[root@db01 ~]# innobackupex --apply-log /backup/full/
恢复备份
前提:
1、被恢复的目录是空
2、被恢复的数据库的实例是关闭
systemctl stop mysqld
创建新目录
[root@db01 backup]# mkdir /data/mysql1
数据授权
chown -R mysql.mysql /data/mysql1
恢复备份
[root@db01 full]# cp -a /backup/full/* /data/mysql1/
启动数据库
vim /etc/my.cnf
datadir=/data/mysql1
[root@db01 mysql1]# chown -R mysql.mysql /data/mysql1
systemctl start mysqld
2.4.3 XBK增量备份
备份方式:基于上次的备份的增量
增量备份不能单独恢复,必须合并到全备中,一起恢复
# 1.周日全备
innobackupex --user=root --password=123 --no-timestamp /data/bak/full_$(date +%F)
# 2.模拟周一数据变化
create database xbk charset utf8mb4;
use xbk
create table t1(id int);
insert into t1 values(1),(2),(3);
commit;
# 3.周一晚上增量备份
innobackupex --user=root --password=123 --no-timestamp --incremental --incremental-basedir=/data/bak/full_2019-06-26 /data/bak/inc_$(date +%F)
# 4.模拟周二白天的数据变化
use xbk
create table t2(id int);
insert into t2 values(1),(2),(3);
commit;
# 5.周二晚上的增量备份
innobackupex --user=root --password=123 --no-timestamp --incremental --incremental-basedir=/data/bak/inc_2019-06-26 /data/bak/inc2_$(date +%F)
2.4.5 XBK增量恢复演示
思路:
合并所有增量到全备
每个XBK备份都需要恢复准备(prepare)
--apply-log --redo-only
# 1.整理全备
innobackupex --apply-log --redo-only /data/bak/full_2019-06-26/
# 2.整理并合并周一增量到全备
innobackupex --apply-log --redo-only --incremental-dir=/data/bak/inc_2019-06-26 /data/bak/full_2019-06-26/
# 3.整理并合并周二的增量到全备
[root@db01 /data/bak]# innobackupex --apply-log --incremental-dir=/data/bak/inc2_2019-06-26 /data/bak/full_2019-06-26/
# 4.再次整理全备
innobackupex --apply-log /data/bak/full_2019-06-26
# 5.破坏数据库,恢复数据
[root@db01 /data/bak]# pkill mysqld
[root@db01 /data/bak]# \rm -rf /data/mysql/data/*
[root@db01 /data/bak]# innobackupex --copy-back /data/bak/full_2019-06-26
[root@db01 /data/mysql/data]# chown -R mysql.mysql /data/*
[root@db01 /data/mysql/data]# /etc/init.d/mysqld start
3.企业备份恢复案例(XBK full+inc+binlog)
案例背景:某中型互联网公司。MySQL 5.7.26,Centos 7.6 ,数据量级600G,每日数据增量15-50M
备份策略:周日XBK全备+周一到周六inc增量+binlog备份,每天23:00进行。
故障描述:周三下午2点,数据由于某原因数据损坏。
处理思路:
2.1全部丢失-->推荐直接生产恢复
2.2部分丢失
处理结果:
案例模拟:
# 1.模拟周日的全备
[root@db01 ~]# innobackupex --user=root --password=123 --no-timestamp /data/bak/full
# 2.模拟周一的数据变化
mysql> create database hisoss charset utf8mb4;
mysql> use hisoss;
mysql> create table his_order(id int);
mysql> insert into his_order values(1),(2),(3);
mysql> commit;
# 3.模拟周一的增量备份
[root@db01 /data/bak]# innobackupex --user=root --password=123 --no-timestamp --incremental --incremental-basedir=/data/bak/full /data/bak/inc1
# 4.模拟周二的数据变化
use hisoss;
insert into his_order values(11),(22),(33);
commit;
# 5.模拟周二的增量备份
innobackupex --user=root --password=123 --no-timestamp --incremental --incremental-basedir=/data/bak/inc1 /data/bak/inc2
# 6.模拟周三的数据变化
use hisoss;
insert into his_order values(111),(222),(333);
commit;
# 7.有一个傻子,把数据库data目录给rm掉了
pkill mysqld
\rm -rf /data/mysql/data/*
# 8.整理 合并备份
(1) 整理全备
[root@db01 ~]# innobackupex --apply-log --redo-only /data/bak/full
(2) inc1 合并并整理到full中
[root@db01 ~]# innobackupex --apply-log --redo-only --incremental-dir=/data/bak/inc1 /data/bak/full
(3) inc2 合并并整理到full中
[root@db01 ~]# innobackupex --apply-log --incremental-dir=/data/bak/inc2 /data/bak/full
(4) 整体的整理
innobackupex --apply-log /data/bak/full
# 9.恢复备份数据
cp -a /data/bak/full/* /data/mysql/data/
[root@db01 /data/bak]# chown -R mysql.mysql /data
# 10.截取二进制日志并恢复
mysqlbinlog --skip-gtids --include-gtids='180629c3-97ed-11e9-aeaa-000c29099eb6:5' /data/binlog/mysql-bin.000050 >/data/bak/bin.sql
恢复:
mysql> set sql_log_bin=0;
mysql> source /data/bak/bin.sql
扩展:
假如,只是少量数据被损坏,以上方法有哪些不妥的地方?
alter table t1 discard tablespace
alter table t1 import tablespace
innobackupex --user=root --password=123 --defaults-file=/etc/my.cnf --no-timestamp --stream=tar --use-memory=256M --parallel=8 /data/mysql_backup | gzip | ssh root@10.0.0.52 " cat - > /data/mysql_backup.tgz"
--stream=tar
--use-memory=256M
--parallel=8
## 4.0迁移前要考虑的问题
##技术方面
选择什么工具,MDP XBK
##非技术
停机时间
回退方案
## 4.1换主机
### 4.1.1数据量小
思路:
### 4.1.1数据量大
XBK备份出来,scp到目标主机
搭建主从的方式
申请停机15分钟
校验数据
进行业务割接
## 4.2换版本升级
例如:
5.6 -》 5.7
(1)方法一:
建议使用mysqldump逻辑备份方式,按业务库进行分别备份,排除掉 information_schema,performance_schema,sys
恢复完成后,升级数据字典
(2)方法二:
进行过滤复制,排除掉information_schema,performance_schema,sys
## 4.3异构迁移-系统不一样
只能用逻辑备份
## 4.4异构迁移-数据库产品不同
Oracle --OGG------> MYSQL
MySQL ---CSV--> MongoDB
MySQL ---JSON--> MongoDB