MySQL

修改用户

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;



(1)建表

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;


(2)改表

1.改表结构

--例子:

--在上表中添加一个手机号列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,进行伪删除

1.添加状态列state (0代表存在,1代表删除)


ALTER TABLE oldguo ADD state TINYINT NOT NULL DEFAULT 0 ;


2.使用update模拟delete

DELETE FROM oldguo WHERE id=6;

替换为

UPDATE oldguo SET state=1 WHERE id=6;

SELECT * FROM oldguo ;


3.业务语句修改

SELECT * FROM oldguo ;

改为

SELECT * FROM oldguo WHERE state=0;


1. select 

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.搞到ER图(PD)

3.啥都没有怎么怎么办?

(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 ;

---统计每个国家的城市个数

1.拿什么站队

GROUP BY  countrycode

2.拿什么统计

城市id,name

3.统计的是什么?

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

desc tables;

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 

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在备份时,同时备份触发器,如果没有会自动忽略



必加参数(2)

--master-data=2    

功能:

1.记录备份时的position

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点,数据由于某原因数据损坏。

处理思路:

1.挂出维护页

2.评估一下数据损坏状态

案例模拟及恢复:


1.进行周二全备

[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;


2.模拟全备之后到下午两点前的业务操作

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;

 

 

 

 

 

 


3.模拟损坏

\rm -rf /data/mysql/data/*

pkill mysqld

\rm -rf /data/mysql/data/*




4.初始化数据

[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


5.进行全备恢复

mysql> set sql_log_bin=0;

mysql> source /data/backup/full.sql

mysql> flush privileges;


6.找日志起点和终点

[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


7.恢复日志

mysql> set sql_log_bin=0;

mysql> source /data/backup/bin.sql


扩展:从全备中导出单表备份

1、获得表结构

# sed -e'/./{H;$!d;}' -e 'x;/CREATE TABLE `city`/!d;q'  full.sql>createtable.sql

2、获得INSERT INTO 语句,用于数据的恢复

# grep -i 'INSERT INTO `city`'  full.sqll >data.sql

3.获取单库的备份

# 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点,数据由于某原因数据损坏。

处理思路:

1.挂出维护页

2.评估一下数据损坏状态

2.1全部丢失-->推荐直接生产恢复

2.2部分丢失

3.整理合并所有备份:full+inc1+inc2

4.截取 周二晚上到周三下午午故障点的binlog日志

5.恢复全备,恢复binlog

6.检查数据完整性

7.恢复业务

处理结果:

1.经过70-80分钟处理,业务恢复

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 [email protected] " cat - > /data/mysql_backup.tgz"


 --stream=tar

 --use-memory=256M  

 --parallel=8


 4. MySQL数据迁移

## 4.0迁移前要考虑的问题

##技术方面

选择什么工具,MDP XBK

##非技术

停机时间

回退方案


## 4.1换主机

### 4.1.1数据量小

思路:

1.在线 MDP,XBK备份出来,scp到目标主机

2.追加所有备份后的日志

3.申请停机5分钟

4.剩余部分的binlog继续恢复(搭建主从的方式来替代)

5.校验数据

6.进行业务割接


### 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

你可能感兴趣的:(MySQL)