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開始(危險!?。。。?/p>

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 root@10.0.0.52 " 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

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容