修改用戶
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開始(危險!?。。。?/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在備份時,同時備份觸發器,如果沒有會自動忽略
--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