大家好,我是云计算磊哥,从业20年的IT老鸟。运维培训15年,总结了一套从入门到精通的全运维开发宝典手册。准备用300天时间写一套博文,手把手从安装软件讲起,从行业到产品,从过去到未来,从理论到操作,从视频到文档工具,一站式。从零基础入门到20k运维开发工程师岗位诸多就业问题。多方位全方面的给你讲清楚云计算这个行业该如何做。关注我。后续AI大模型开发课程更精彩。
INDEX
1 索引简介
索引在MySQL中也叫做"键",是存储引擎用于快速找到记录的一种数据结构。索引对于良好的性能非常关键,尤其是当表中的数据量越来越大时,索引对于性能的影响愈发重要。索引优化应该是对查询性能优化最有效的手段了。索引能够轻易将查询性能提高好几个数量级。索引相当于字典的音序表,如果要查某个字,如果不使用音序表,则需要从几百页中逐页去查。
2 索引的分类
- 普通索引:加速查询,生成目录,占用空间,非where列不建议使用索引
- 唯一索引:unique 唯一索引,可以为空
- 全文索引:文章索引及其有效
- 单列索引:同普通索引
- 多列索引:单列的一种形式
- 空间索引:适用于空间数据(略)
3 索引测试实验
准备素材
mysql> create database school;
mysql> create table school.t2(id int,name varchar(30));
Query OK, 0 rows affected (1.33 sec)
通过存储过程,循环输入海量数据
mysql> delimiter $$
mysql> use school
mysql> create procedure autoinsert1()
BEGIN
declare i int default 1;
while(i<20000)do
insert into school.t2 values(i,'ccc');
set i=i+1;
end while;
END$$
mysql> delimiter ;
mysql> call autoinsert1();
未创建索引,测试查询过程
mysql> explain select * from school.t2 where id=20000;
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+
| 1 | SIMPLE | t2 | ALL | NULL | NULL | NULL | NULL | 44848 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+
1 row in set (0.00 sec)
创建索引
create index index_id on school.t2(id);
已创建索引,测试查询过程
explain select * from school.t2 where id=20000;
创建索引后,实时查询。观察用时
mysql> select * from school.t2 where id=20000;
+-------+------+
| id | name |
+-------+------+
| 20000 | ccc |
+-------+------+
1 row in set (0.00 sec)
4 创建索引语法
创建表时,同时创建索引
CREATE TABLE department10 (
dept_id INT,
dept_name VARCHAR(30) ,
comment VARCHAR(50),
INDEX index_dept_name (dept_name)
);
index_dept_name 索引名称可以省略
CREATE TABLE department11 (
dept_id INT,
dept_name VARCHAR(30) ,
comment VARCHAR(50),
UNIQUE INDEX index_dept_name (dept_name)
);
CREATE TABLE department12 (
dept_id INT,
dept_name VARCHAR(30) ,
comment VARCHAR(50),
log text,
FULLTEXT INDEX index_log (log)
);
CREATE TABLE department13 (
dept_id INT,
dept_name VARCHAR(30) ,
comment VARCHAR(50),
INDEX index_dept_name_comment (dept_name, comment)
);
CREATE在已存在的表上创建索引
CREATE INDEX index_dept_name ON department (dept_name);
CREATE UNIQUE INDEX index_dept_name ON department (dept_name);
CREATE FULLTEXT INDEX index_dept_name ON department (dept_name);
CREATE INDEX index_dept_name_ comment ON department (dept_name, comment);
ALTER TABLE在已存在的表上创建索引
ALTER TABLE department ADD INDEX index_dept_name (dept_name);
ALTER TABLE department ADD UNIQUE INDEX index_dept_name (dept_name);
ALTER TABLE department ADD FULLTEXT INDEX index_dept_name (dept_name);
ALTER TABLE department ADD INDEX index_dept_name_comment (dept_name,comment);
5 管理索引
SHOW CRETAE TABLE 表名\G
EXPLAIN SELECT * FROM department WHERE dept_name='hr';请关注查询记录的数量
show create table employee6;
DROP INDEX 索引名 ON 表名;
安全机制
1 权限级别
- Global level
- Database level
- Table level
- Column level
- procs level
- proxies level
2 查看权限记录表
Global level
select * from mysql.user\G;
Database level
select * from mysql.db\G;
Table level
select * from mysql.tables_priv\G;
Column level
select * from mysql.columns_priv\G;
3 mysql用户管理
3.1 创建用户
GRANT ALL ON *.* TO 'user3'@'localhost' IDENTIFIED BY 'xulei@123456';
FLUSH PRIVILEGES;
3.2 删除用户
DROP USER 'user1'@'localhost';
3.3 修改用户密码
UPDATE mysql.user SET authentication_string=password('new_password') WHERE user='root' AND host='localhost';
FLUSH PRIVILEGES;
3.4 登录和退出MySQL
mysql -h192.168.100.10 -P 3306 -u root -p123 mysql -e 'show tables'
-h 指定主机名 【默认为localhost】
-P MySQL服务器端口 【默认3306】 大P
-u 指定用户名 【默认root】
-p 指定登录密码 【默认为空密码】
此处mysql为指定登录的数据库
-e 接SQL语句
4 MySQL权限原理
语法: grant 权限列表 on 库名.表名 to '用户名'@'客户端主机' identified by '密码' with option参数;
赋予权限
grant all on *.* to admin1@'%' identified by 'xulei@13910604684';
回收权限
REVOKE DELETE ON *.* FROM admin1@'%'; //回收部分权限
REVOKE ALL PRIVILEGES ON *.* FROM admin2@'%'; //回收所有权限
REVOKE ALL PRIVILEGES,GRANT OPTION ON *.* FROM 'admin2'@'%';
物理备份
1 案例1 tar备份数据库
备份的过程
1停止数据库
systemctl stop mysqld
mkdir /backup
2. tar备份数据
tar -cf /backup/`date +%F`-mysql-all.tar /var/lib/mysql
3. 启动数据库
systemctl start mysqld
还原的过程
systemctl stop mysqld
rm -rf /var/lib/mysql/*
tar -xf /backup/2016-12-07-mysql-all.tar -C /
systemctl start mysqld
2 案例2 Lvm快照实现物理备份 + binlog
将已运行mysql迁移到LVM卷
1. 准备lvm及文件系统
lvcreate -n lv-mysql -L 2G datavg
mkfs.xfs /dev/datavg/lv-mysql
2. 将数据迁移到LVM
systemctl stop mysqld
mount /dev/datavg/lv-mysql /mnt/
cp -a /var/lib/mysql/* /mnt
umount /mnt/
chown -R mysql.mysql /var/lib/mysql
systemctl start mysqld
LVM快照备份流程
mysql> flush tables with read lock;
lvcreate -L 500M -s -n lv-mysql-snap /dev/datavg/lv-mysql
mysql -p'xulei@123' -e 'show master status' > /backup/`date +%F`_position.txt
mysql> unlock tables;
mount -o nouuid /dev/datavg/lv-mysql-snap /mnt/
cd /mnt/
tar -cf /backup/`date +%F`-mysql-all.tar ./*
cd; umount /mnt/
lvremove -f /dev/datavg/lv-mysql-snap
LVM快照恢复流程
systemctl stop mysqld
rm -rf /var/lib/mysql/*
tar -xf /backup/2016-12-07-mysql-all.tar -C /var/lib/mysql/
chown -R mysqlmysql /var/lib/mysql/
systemctl start mysqld
总结操作思路
1、flush table with read locak;全局读锁
2、create snapshot 创建快照,
3、show master status; show slave status; [可选] 查询二进制日志的位置,下次使用bin 作为依据。
4、unlock tables;然后释放锁。
5、Copy files from the snapshot 从快照卷,复制数据。
6、Unmount the snapshot. 卸载并删除快照。
7、Remove snapshot
3 案例3:percona-xtrabackup 物理备份 + binlog
安装
wget http://www.percona.com/downloads/percona-release/redhat/0.1-3/percona-release-0.1-3.noarch.rpm 下载YUM源
yum -y install percona-release-0.1-3.noarch.rpm 安装yum源
yum -y install percona-xtrabackup-24.x86_64 安装percona
rpm -ql percona-xtrabackup-24 查询安装结果,安装文件
1-1 完全备份流程
mkdir /xtrabackup/full -p
准备备份目录
innobackupex --user=root --password='xulei@123' /xtrabackup/full
连接数据库,开始备份。
请注意备份结果是否完成
xtrabackup: Transaction log of lsn (74182721) to (74182730) was copied.
171127 15:04:12 completed OK!
ls /xtrabackup/full/
查看备份目录。数据库,配置文件,日志文件
ls /xtrabackup/full/2017-08-01_00-00-02/
cat /xtrabackup/full/2017-08-01_00-00-18/xtrabackup_binlog_info
二进制日志位置
1-2 完全恢复流程
systemctl stop mysqld
rm -rf /var/lib/mysql/*
rm -rf /var/log/mysqld.log
rm -rf /var/log/mysql-slow/slow.log
innobackupex --apply-log /xtrabackup/full/2017-08-01_00-00-18/
innobackupex --copy-back /xtrabackup/full/2017-08-01_00-00-18/
ls /var/lib/mysql
chown -R mysql.mysql /var/lib/mysql
systemctl start mysqld
mysql -uroot -p'xulei@123'
2-1 增量备份流程
准备工作
mysql> create database testdb;
mysql> use testdb;
mysql> create table test(id int);
mysql> insert into test values (1);
mysql> select * from test;
mysql> select * from test;
+------+
| id |
+------+
| 1 |
+------+
1 row in set (0.00 sec)
完整备份:周一
rm -rf /xtrabackup/*
date 09010000
innobackupex --user=root --password='xulei@123' /xtrabackup
ll /xtrabackup/
2017-09-01_00-00-04
增量备份:周二
date 09020000 更新时间
mysql -uroot -p'xulei@123' -e 'insert into testdb.test values (2)'
innobackupex --user=root --password='xulei@123'
--incremental /xtrabackup/
--incremental-basedir=/xtrabackup/2017-09-01_00-00-04
basedir基于周一的备份。
会生成一个今天的。
ls /xtrabackup/
2017-09-01_00-00-04
2017-09-02_00-00-58
增量备份:周三
# date 09030000
# mysql -uroot -p'xulei@123' -e 'insert into testdb.test values (3)'
# innobackupex --user=root --password='xulei@123'
--incremental /xtrabackup/
--incremental-basedir=/xtrabackup/2017-09-02_00-00-26
# ls /xtrabackup/
2017-09-01_00-00-04
2017-09-02_00-00-58
2017-09-03_00-00-36
2-2 增量恢复流程
停止数据库
systemctl stop mysqld
清理环境
rm -rf /var/lib/mysql/*
周一
innobackupex --apply-log --redo-only /xtrabackup/2017-09-01_00-00-04
周二
innobackupex --apply-log --redo-only /xtrabackup/2017-09-01_00-00-04
--incremental-dir=/xtrabackup/2017-09-02_00-00-26
周三
innobackupex --apply-log --redo-only /xtrabackup/2017-09-01_00-00-04
--incremental-dir=/xtrabackup/2017-09-03_00-00-27
恢复
innobackupex --copy-back /xtrabackup/2017-09-01_00-00-06
chown -R mysql.mysql /var/lib/mysql
systemctl start mysqld
逻辑备份
mysqldump实现逻辑完全备份 + binlog
1 优势
- 自动记录position位置。
- 可用性,一致性
2 语法
mysqldump -h 服务器 -u用户名 -p密码 数据库名 > 备份文件.sql
参数说明
-A, --all-databases 所有库
school 数据库名
school stu_info t1 是指school数据库的表stu_info、t1
-B, --databases bbs test mysql 多个数据库
--single-transaction #InnoDB 一致性 服务可用性
--opt #同时启动各种高级选项
-R, --routines #备份存储过程和存储函数
-F, --flush-logs #备份之前刷新日志,截断日志。备份之后新binlog。
--triggers #备份触发器
--master-data=1|2 #该选项将会记录binlog的日志位置与文件名并追加到文件中,或添加注释
3 备份实战
3.1 准备库1
mysql> select * from testdb1.t1;
+------+
| id |
+------+
| 1 |
| 2 |
| 3 |
+------+
3.2 执行备份
[root@localhost ~]# mysqldump -p'xulei@123' \
--all-databases --single-transaction \
--master-data=2 \
--flush-logs \
> /backup/`date +%F-%H`-mysql-all.sql
3.3 观察备份细节
vim /backup/2016-11-25-14-mysql-all.sql
观察各种锁机制,用来保证数据一致性
LOCK TABLES `user` WRITE;
二进制日志截断位置。第22行
22 CHANGE MASTER TO MASTER_LOG_FILE='localhost-bin.000004', MASTER_LOG_POS=154;
3.4 备份后的,数据变更行为
在testdb2.t2 中插入数据1;
创testdb3库
切断二进制日志(重启数据库)
在testdb2.t2 中插入数据2;
删testdb3库
在testdb2.t2 中插入数据3;
4 恢复实战
4.1 备份日志文件
cp /var/lib/mysql/*bin* ~
4.2. 停止数据库
systemctl stop mysqld
4.3. 清理环境
rm -rf /var/lib/mysql/*
4.4.启动数据库
systemctl start mysqld
grep 'password' /var/log/mysqld.log
找密码,再改密码略。
4.5 .mysql恢复数据
mysql -p'xulei@1234' < /backup/2016-12-08-04-mysql-all.sql
mysql -p'xulei@1234' -e 'flush privileges'
登陆并验证数据恢复结果。请思考恢复的数据库有几个?
答:1个,因为这是备份点之前的数据。而备份点到灾难点的数据如何恢复呢?
4.6 二进制日志恢复
观察二进制截取记录
vim /backup/2016-11-25-14-mysql-all.sql
CHANGE MASTER TO MASTER_LOG_FILE='localhost-bin.0000010', MASTER_LOG_POS=154;
恢复
mysqlbinlog localhost-bin.000002 localhost-bin.000003
--start-position=154 | mysql -p'xulei@123'
注意后续有多少日志,要跟多少日志名字。
4.7.观察数据
数据恢复完成
5 记录的导出和导入
SELECT... INTO OUTFILE 导出文本文件
mysql> SELECT * FROM testdb1.t1 INTO OUTFILE '/backup/testdb1.t1.txt';
mysql 命令导出文本文件
mysql -uroot -p'xulei@123' -e 'select * from testdb1.t1' > /backup/testdb1.t2.txt
mysql -u root -p'xulei@123' --xml -e 'select * from testdb1.t1' > /backup/testdb1.t3.txt
mysql -u root -p'xulei@123' --html -e 'select * from testdb1.t1' > /backup/index.html
LOAD DATA INFILE 导入文本文件
注意目录权限
vim /etc/my.cnf
secure-file-priv=/backup
mysql不信任该目录
chown mysql.mysql /backup
mysql用户没有权限
删除表的内容
表的导出和导入只备份表记录,不会备分表结构。因此需要通过mysqldump备份表结构,恢复时先恢复表结构,再导入数据。
DELETE FROM testdb1.t1;
读取记录备份文件
LOAD DATA INFILE '/backup/testdb1.t1.txt'
INTO TABLE testdb1.t1;
输入到表中。
INTO TABLE testdb1.t1;
select * from testdb1.t1;
mysql阶段