MySQL 基本内容
Paste_Image.png Paste_Image.png Paste_Image.png Paste_Image.png Paste_Image.png Paste_Image.pngMySQL的基础
DDL 数据定义语言 表、索引、视图、
DML 数据操纵语言 操作表中数据
存储过程 没有返回值的函数 procedure 仅仅对数据进行加工
存储函数 有返回结果的代码片段 fuction 对数据加工后,并可以调用,有返回值(输入和输出)
事件调度器 完成周期性的内键任务
物理层 打开表空间后,可以看到内容
逻辑层 表、空间、视图
视图层 用户最终看到的数据
连接线程 维护用户连接
守护线程 数据<——>磁盘,维护cashed和buffer
[mysqld]
[mysqld_safe]
[mysqld_multi] 多实例共享参数
[server] 服务器端都有效
[mysql] 客户端
[mysqldump] 备份、导入、导出
源码 有些功能需要自己设计
rpm 不需要太多的功能
SHOW ENGINES; 查看存储引擎
Paste_Image.png Paste_Image.png Paste_Image.png Paste_Image.png Paste_Image.png Paste_Image.png Paste_Image.png Paste_Image.png Paste_Image.png Paste_Image.pngMySQL 数据类型
char varchar text系列 不区分字符大小写
binary varbinary blob 区分字符大小写
unsigned 无符号,字段修饰符,紧跟数据类型之后,修饰类型本身,不是补充约束条件
ENUM 存储的是索引,不是字串(a字串-0索引),不能用来比较和查询
SET 储存最多64位的二进制数据,按位比较(a-100,b-011)
Paste_Image.pngSQL mode
修改全局,不会立即生效,只对新建的生效;
立即生效,修改会话级别;
% 任意长度的任意字符串
SHOW GLOBAL VARIABLES LIKE 'sql_%'
SHOW GLOBAL STATUS LIKE 'sql_%'
CREATE DATABASE mydb;
use mydb;
CREATE TABLE t1 (id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL, name CHAR(5) NOT NULL)
INSERT INTO t1 不指明,对两个都插入数据
INSERT INTO t1 (name) VALUES ('tom'),('blackberry'); 违反5个长度的规则,保留前5个字符,进行插入
SHOW WARNINGS; 查看警告
SELECT * FROM t1;
SET sql_mode='TRADITIONAL'; 修改当前会话,再次插入违反5个长度的规则,就error,不插入;
SET sql_mode='STRICT_ALL_TABLES'; 对已建立的会话无效,对新建的会话有效;
SHOW GLOBAL VARIABLES LIKE 'sql_mode'; 可以看到相应的值
使用SET修改,不论是全局/局部,mysql重启,都失效;
修改配置文件:可以全局、永久生效;
或者 启动mysql时,直接传递给mysql,做命令行参数进行
Paste_Image.png多表查询
代价高
一张表——>两个表——>需要连接
连接 需要按照指定字段之间的关系进行连接——>过滤出所需数据
笛卡尔乘积 最耗资源
可能无意义
等值连接 相同意义的行——>构建为新的行;不同意义的行——>不管它
Paste_Image.png
Paste_Image.png
Paste_Image.png
Paste_Image.png
Paste_Image.png
等值连接
Paste_Image.pngTeacherID=1有多个,那么TID会出现多次
Paste_Image.png Paste_Image.png Paste_Image.png Paste_Image.png某个同学的老师的名字
将两张表的数据按指定字段进行连接
查看索引 等值连接——代价较高
Paste_Image.png同学 ~ 班级
Paste_Image.png Paste_Image.png Paste_Image.png每位同学显示的班级、无班级的同学也要显示出来
等值连接
左外连接(左侧为基准):左侧(每一项都出现、有相应的等值条目)~右侧无,左侧显示,右侧留空
右外连接(右侧为基准):右侧(每一项都出现、有相应的等值条目)~左侧无,右侧显示,左侧留空
Paste_Image.png
Paste_Image.png
Paste_Image.png
Paste_Image.png子查询
建立在另一个查询基础之上,查询中嵌套者查询
MySQL的子查询性能差,建议不要使用子查询,可以使用单表查询或者多表查询
FROM语句的子查询 相当于VIEW(虚表、保存),但是不保存
年龄大于平均年龄的同学
先 平均年龄,再 年龄大于平均年龄
老师的年龄=同学的年龄
Paste_Image.png求每一个班级的同学的平均年龄 大于25的班级信息
Paste_Image.png Paste_Image.png使用FROM字句,大部分可以多加一个条件WHERE来使用
大多数子查询 可以拆为 多表查询
使用查询语句写出非常复杂的用法,完成其功能 需要练习
联合查询 两个SELECT语句的查询结果合并成一个
Paste_Image.png Paste_Image.png Paste_Image.png Paste_Image.png Paste_Image.png1 SELECT Name,Age FROM students WHERE Age>(SELECT avg(Age) FROM students);
参考网上
2 SELECT s.Name,scores.CourseID FROM students AS s LEFT JOIN scores ON scores.StuID = s.StuID WHERE scores.CourseID IN (1,2,4,7);
select students.name from students,(select distinct stuid from scores where courseid in (1,2,4,7))as s where s.stuid=students.stuid;
3 SELECT Name,avg(Score) FROM (SELECT * FROM students LIMIT 8) AS rj LEFT JOIN scores AS jr ON rj.StuID=jr.StuID GROUP BY Name ORDER BY avg(Score) DESC;
4 SELECT courses.Course,count(rj.StuID) FROM scores AS rj LEFT JOIN courses ON courses.CourseID=rj.CourseID GROUP BY rj.CourseID;
Paste_Image.png索引管理、视图、DML
单进程多线程(线程池管理客户端的众多请求)
用户连接连接线程
mysql提供给用户的视图3种
物理视图 ...
mysql数据文件文件类型
数据文件、索引文件
物理视图
重做日志、撤销日志、二进制日志(中继日志)、错误日志、查询日志、慢查询日志、
逻辑视图(以上日志——SQL接口映射——关系型数据库,应该具备的组成部分)
表(datablock)——映射——磁盘的block——映射——本地存储
转换为二维映射关系,依赖于SQL接口和存储引擎
逻辑视图在——SQL接口、storage engines
用户视图
终端用户访问的数据视图
Paste_Image.png
Paste_Image.png
DDL&DML
索引管理
按特定数据结构存储的数据(为算法的实施而设计——数据的查询)
聚集索引 非聚集索引 数据是否与索引存储在一起
主键索引 辅助索引
稠密索引 稀疏索引 是否索引了每一个数据
B-Tree/B+Tree(平衡树)索引
哈希索引(减值索引) 一对一查找 不能排序
R-TREE(空间)索引
左前缀索引 某一列数据过大,只取此列的一部分做索引,
LIKE "%abc%" 只查找中间的abc
最好左侧不要加% LIKE "abc%"
索引优化 查询语句的优化(改写) 对关系型数据库很重要 提高数十倍
简单索引、组合索引
名字和课程组合成一个索引
覆盖索引
通过查找索引就可以找到数据,而不用去找原数据
解析
(查询练习了 降龙18掌的同学,并不是查询所有,否则全部加载到内存后,耗内存资源)
整个数据——>取一列(#稠密索引)——>分成4段(首字母排序等),标识其相关内容(#稀疏索引)——>目的:提高搜索效率
索引 不包含数据本身 可能是一个文件,记录数据位置 特殊的数据结构 按照特定顺序存放
多级形式——顶级索引(稀疏)、最底层索引(稠密)
eg: 目标在索引级别4——需要5次IO(假如没有索引,目标在第100号,就需要100次IO)
插入数据到某一行,可能会导致整个数据的索引更改,提前预留空间,经常插入数据到数据库的某一行,索引的价值就不太大了,收益大于成本——就有价值
元数据
从原始文件中,加载出有限部分的数据块,并从中过滤出符合条件的行即可
#主键索引(约束) 每一个数据不允许重复出现(n个同学练习降龙18掌,出现n次,搜索较慢,主见约束可以解决此问题)
符合结果的可能只有一个
一对一的查询
#聚集索引 把数据抽出来按索引存放 索引可以指向数据位置——即必须是主键索引——1号、1号同学的数据存放在一起(索引和指向数据在一起)
找到索引,即找到数据
删除某行时,整个数据都要进行编排 麻烦
除了主见索引的,其他都叫#辅助索引
根据辅助索引查找——>聚集索引——>查找索引(目标)
#非聚集索引——索引和指向数据不存放在一起
辅助索引——>目标索引,没有谁是关键的索引
Paste_Image.png
Paste_Image.png
索引管理的途径
索引管理的途径
创建索引,创建表时设定,命令
创建或删除索引,通过修改表的命令
mysql
HELP CREATE TABLE: create_definition
HELP ALTER TABLE: ADD 增加 DROP 删除
删除索引
DROP INDEX
HELP CREATE INDEX:
不加索引 [选项] 就是指B-TREE索引
使用CREATE创建索引,必须使用Index_name
使用ALTER TABLE添加时,无需指定Index_name
ON tbl_name(指明在哪个表) index_col_name(指明在哪些字段,单个字段——单节字段/简单索引,多个字段——组合索引/符合索引)
指明长度length、降序ASC、升序DESC
HELP DROP INDEX
索引没必要修改,否则整个索引都要重新建立
创建索引,需要几分钟或几十分钟,千万不要对线上系统更新索引,代价太大,很多产品构建在现有的索引上,你一重建索引,数据库需要做原表扫描,需要时间,数据库会瞬间卡死,很多用户的请求就要等待此;
退出
bye
quit
;
quit
lftps
cd Files/
mget hellodb.sql
bye
mysql < hellodb.sql
mysql
SHOW DATABASES;
use hellodb;
SHOW TABLES;
SELECT * FROM classes;
SELECT * FROM courses;
SELECT * FROM students;
HELP SHOW INDEX
查看索引的命令
SHOW INDEXES FROM students;
创建表时,默认有主键,且建立在用户的id之上
EXPLAIN SELECT * FROM students WHERE(指明条件) StuID=3\G
EXPLAIN 分析而不是真正的执行语句,分析"查询语句"在执行过程中,是否用到了索引,以及如何实现数据获取的;
显示的是一个近似结果
查询时,可能用到了主键
PRIMARY——主键
type: const——1对1查询
type: all——全表扫描(耗费内存资源)
EXPLAIN SELECT * FROM students WHERE(指明条件) Age=53\G
年龄是53的有很多,所以会耗费内存资源
如果经常根据年龄来查询,那么可以根据年龄来创建一个索引;
创建索引的方法:HELP ALTER TABLE 或者 CREATE INDEX
ALTER TABLE tbl_name(指明表名) ADD INDEX [index_name][index_type](二者可省) index_col_name(指明添加索引的字段,用括号括起来即可)
ALTER TABLE students ADD INDEX(age);
SHOW INDEXES FROM students;
索引类型默认是BTREE
EXPLAIN SELECT * FROM students WHERE(指明条件) Age=53\G
此时,在查询,就可以节省很多资源
type: ref 不是const,可能已经参与了很多的搜索,需要有整体概念,才会理解;
记住一点:
索引很重要——对查询来讲;
在添加一个索引,创建在名字之上
desc students; (描述students)
CREATE INDEX name(索引名) ON(指明表名) students (Name)(在这个表的哪个字段创建)
SHOW INDEXES FROM students;
SELECT * FROM students WHERE Name LIKE(条件) 'X%';
搜索以X开头
EXPLAIN SELECT * FROM students WHERE Name LIKE 'X%';
EXPLAIN SELECT * FROM students WHERE Name LIKE 'X%'\G
type: range 范围查询
EXPLAIN SELECT * FROM students WHERE Name LIKE '%X%'\G(多加一个%,导致索引无效,坑)
type: all (全表扫描)耗费资源
视图 VIEW
虚表
存储SELECT语句,并针对此语句做SELECT查询或者修改
针对的不是物理表,而是被SELECT虚化后的表
HELP CREATE VIEW
CREATE VIEW view_name [column_list](字段) AS select_statement
把select语句的查询结果(select_statement)当做一个表,表的名字叫做view_name,事实上此表并不存在,
MySQL的视图功能相当不完善,能不用就不用
先SELECT查询,得到结果,再SELECT搜索这个SELECT的结果,效率低
物化视图 把一个实实在在的结果存下来,然后对其做查询
CREATE VIEW test AS SELECT StuID,Name,Age FROM students;
从students表里查询StuID,Name,Age的结果作为test视图
SHOW TABLES;
虽然是虚表,但也可以查询到test
SHOW TABLE STATUS LIKE 'test';
SHOW TABLE STATUS LIKE 'test'\G
所有内容都是空的NULL,只有Comment:VIEW(表名)——虚表的特征
SHOW TABLE STATUS LIKE 'students'\G 注意区别二者的不同
SELECT * FROM test
SELECT * FROM test WHERE Age=22; 可以显示出年龄为22的内容
EXPLAIN SELECT * FROM test WHERE Age=22;
EXPLAIN SELECT * FROM test WHERE Age=22\G
table: students 查询test表,实际是students表
删除视图
HELP DROP VIEW
DROP VIEW view_name
视图是否可以被修改——取决于基表的约束
视图中的数据,事实上存储于"基表"中,其修改操作针对基表实现;其修改操作受基表限制;
SELECT * FROM test WHERE Age=22;
SELECT * FROM students WHERE Age=22; 基表
此时,插入数据到视图表里,就是插入到其对应的基表里
基表要求需要非空数据,就不能插入此数据
如果不要求非空,就可以插入此数据,只不过内容为空而已
Paste_Image.png
DML
增删查改
INSERT,DELETE,UPDATE,SELECT
INSERT
一次插入一行或者多行数据;
多行数据需要插入——使用一次插入多行,只触发一次索引更新
HELP INSERT
INSERT tbl_name col_name VALUE (所有字段,指明值)
col_name 字段名,对这些字段进行插入数据;不写就是针对所有字段,都要插入数据
VALUE 针对所有字段,指明值 {VALUE|VALUES}
[ ON DUMPLICATE KEY UPDATE] 插入值与现有值相同,更新现有值,不报错
简化格式
INSERT tbl_name [(col1,...)] VALUE(S) (val1,...),(val21,...)
tbl_name (表名,区分大小写)
INSERT语句可以用replace语句替代,语法几乎相同;
INSERT语句,插入数据和现有数据冲突,会报错
replace语句,插入的数据,如果没有,就插入此行;有则会就替换此行;
格式1
DESC students;
Null : no——不允许为空;yes——允许为空;
INSERT [INTO] students (Name,Age,Gender) VALUES ('Jinjiao King',100,'M');
SELECT * FROM students;
可以看到增加的内容
格式2
INSERT tbl_name SET col_name1=expr1(值),...
INSERT [INTO] students SET Name='Yinjiao King',Age=98,Gender='M';
SELECT * FROM students;
格式3
INSERT tbl_name [(col_name)] SELECT ...
DELETE:
HELP DELETE
DELETE FROM tbl_name WHERE 条件
[WHERE where_condition]
[QRDER BY...]
[LIMIT row_count] 限制几行
没有where条件,整个表会被清空,切记
一定要有限制条件,否则整个表中的数据会被清空
UPDATE
HELP UPDATE
UPDATE table_reference SET col_name1=expr1,...
[WHERE where_condition]
[QRDER BY...]
[LIMIT row_count]
一定要有限制条件,否则修改所有行的指定字段
SELECT DQL
重要的组件Query Cache;
某些场景下有用;
非确定性查询语句select now(系统函数,显示当前时间),每次查询时间都不同
查询缓存未命中——>解析器
查询执行路径中的组件:
查询缓存、解析器、预处理器、查询优化器、查询执行引擎(过滤)、(IO)存储引擎
速度慢 缓存命中,效率快
MySQL服务器不止一台,都可以执行查询操作,提高缓存命中率的方法 (写操作)
前端显示,有多台服务器可以供用户使用,
1 多台前端服务器,可以基于相同的算法,此时,同一个语句必然发送到同一个MySQL服务器
一致性hash算法,是基于查询语句(myaql)或者URL做了粘性的
粘性在一定程度上损害了负载均衡的效果
2 引入第三方的公共缓存来使用(mamercat)
可以尝试关掉MySQL自己的缓存功能,我们从mysql查询到的结果,
由应用程序自行存在mamercat当中,任何一个服务器在查询任何语句时,
都发往mamercat服务器中来看缓存是否命中;这样可以避免MySQL的交互
mamercat的实现,仅仅是基于内存实现做缓存的,在缓存响应方面,会更快;
如果只有一个MySQL服务器的话,那么mamercash是没有必要的,因为MySQL自己的缓存性能会更好
多个MySQL服务器,需要引入多个mamercash(一个扛不住的),此时需要引入一致的hash算法;
具体如何应用,要看实际需要
使用MySQL自己的缓存,但是缓存能力有限,究竟缓存哪些数据,不缓存哪些数据,需要考虑到MySQL自己内置的缓存功能
如果进入第三方的公共缓存,把两种角色分开,事实上,就可以减轻MySQL的压力——>缓存功能有专置的缓存服务器来负责完成
将来做MySQL的主从复制以后,MySQL节点肯定也是不知一个;(?)
MySQL多个主机(服务器),考虑负载均衡
提高缓存命中率,就要进行一致性hash算法或者其他算法的实现
前端——1_负载均衡器(专门MySQL的查询路由)_2——多台MySQL server
负载均衡器(专门MySQL的查询路由)
此设备节点需要符合:
把前端应用程序的读请求负载均衡到多台MySQL主机;
把写请求仅仅发给主服务器;
主节点能写,从节点只读;
此时,前端不能在做一致性hash算法,只能在负载均衡器上做hash算法;
要在此节点上做hash算法,需要对此服务器所实现的查询路由软件程序做改进,自行写代码实现相关功能;
否则,只能使用mamercash,为多台MySQL服务器的查询结果做缓存
如果mamercash有缓存,mysql自己的缓存也可以用(两级缓存)
我们程序在对应的mamercash缓存数据时,都有其ttl(存活周期),ttl时间一到,缓存失效;
但是对于mysql server而言,原来的缓存仍可能有用;如果我们仍然开启缓存,会导致缓存的命中率不高;因为同一个语句可能会被调度至任何一个查询服务器上去;
Paste_Image.png
后端主机的建构形式
mysql的读写分离器
负责将INSERT等的写操作发往主节点,读操作发往从节点
Paste_Image.png
SELECT语句的运行
select查询后——分组——过滤
条件
查询函数
查询到的结果——分组——显示其一部分
SELECT语句的完整用法
Paste_Image.pngmysql的SELECT语句
流程
FROM Clause——>WHERE Clause——>GROUP BY——>HAVING Clause——>ORDER BY——>SELECT——>LIMIT
FROM 从哪个表完成查询操作
SELECT 决定挑选字段
WHERE 选择 挑选符合条件的行
SELECT 投影
MYSQL的单表查询
HELP SELECT (SELECT命令)
修饰符
DISTINCT 去除重复的内容 数据去重
SELECT * FROM students;
SELECT Gender FROM students; 性别
SELECT DISTINCT Gender FROM students; M F
SQL_CASH 显示指定存储查询结果于缓存之中
SQL_NO_CASH 显示查询结果不于缓存;
SHOW GLOBAL VARIABLES LIKE 'query%';
query_cache_type的值为ON时,查询缓存功能表示打开了(不想用可以改为OFF);SQL_CASH才会有用
SELECT的结果符合缓存条件即会缓存,否则不予缓存;
query_cache_type的值为DEMAND时,查询缓存功能按需进行;
显示指定SQL_NO_CACHE,不予缓存;
qiery_cash_size 缓存空间,如果为0,不予缓存;
SELECT SQL_CACHE 表示缓存 不带SQL_CACHE的不缓存
显示指定SQL_CACHE的SELECT语句才会缓存;但不一定会缓存,需要符合自己的常见缓存条件,才会缓存;其他均不予缓存;
MySQL的缓存命中率低,即使开启缓存,效率也会低,
查询命中的次数/查询的总次数(命中次数+未命中次数)=命中率;
命中率低不是没有用,如web缓存——稳当命中率+字节命中率
SHOW GLOBAL STATUS LIKE 'Qcache%';Qcache_hits 命中次数
SHOW GLOBAL STATUS LIKE 'Com_se%';Com_select 查询次数
缓存遇到缓存之前,缓存率低不代表事实就是这样,不理智
Paste_Image.png
Paste_Image.png
SELECT语句的使用
字段显示可以使用别名 表中的内容未被修改,只是在显示时被修改
Paste_Image.png
Paste_Image.png
Paste_Image.png
Paste_Image.png
WHERE
IN 多值等于 或的关系
LIKE 模糊比较 通配符、(模糊匹配)表达式(最好不用)
RLIKE 支持正则表达式 索引无法使用(最好不用)
逻辑操作符
满足一个条件还是多个条件
XOR 异或 二者不同为真,相同为假
MySQL内置的函数 比较操作 可能用到
Paste_Image.png
Paste_Image.png
Paste_Image.png
Paste_Image.png
Paste_Image.png
Paste_Image.png
Paste_Image.png
Paste_Image.png
GROUP
Paste_Image.png
求男女同学的平均年龄
Paste_Image.png分组并聚合
Paste_Image.png平均年龄大于20的
定义别名更为直观,尤其做函数运算;
Paste_Image.png
每个班有多少人
根据班级分组——计算班里人数(计算行数)——count统计
count * 执行性能最差,最好选择主键所在的字段做统计
ORDER BY
Paste_Image.png
Paste_Image.png
Paste_Image.png
Paste_Image.png
LIMIT 对显示的结果做限制
offset 偏移量
Paste_Image.png
Paste_Image.png
Paste_Image.png
Paste_Image.png
写锁 不能写,不能读
读锁 可以读
Paste_Image.png
Paste_Image.png
mysql < hellodb.sql
1 SELECT Gender(MAN) FROM students GROUP BY Age>25;(错误)
SELECT Name,Age FROM students WHERE Age>25 AND Gender='M';
2 SELECT avg(Age),ClassID FROM students GROUP BY ClassID;
SELECT avg(Age),ClassID FROM students WHERE ClassID IS NOT NULL GROUP BY ClassID ;
3 SELECT avg(Age) as AAge,ClassID FROM students GROUP BY ClassID HAVING AAge>30;
SELECT avg(Age),ClassID FROM students WHERE ClassID IS NOT NULL GROUP BY ClassID HAVING avg(Age) > 30;
4 SELECT * FROM students WHERE Name LKIE 'L%';
5 SELECT * FROM students WHERE TeacherID IS NOT NULL;默认为非空?
6 SELECT * FROM students ORDER BY Age DESC LIMIT 10;
7 SELECT * FROM students GROUP BY 20<=Age<=25;
SELECT * FROM students WHERE Age RLKIE 'Age>=20 && Age<=25';
SELECT * FROM students WHERE Age >=20 AND Age <=25;
SELECT * FROM students WHERE Age BETWEEN 20 AND 25;
SELECT * FROM students WHERE Age IN (20,21,22,23,24,25);
Paste_Image.png查询缓存
缓存——键值(缓存键)——hash表——再次查询,每个语句做hash计算——查找表里是否有与其对应的条目
查询缓存
MySQL不会解析、正则和参数化我们的查询语句
直接使用SQL语句和客户端发来的语言信息
存放在内存中,对整个内存空间的分配、回收等,也会额外的产生系统资源消耗
调整合适的值=调整CPU和消耗内存浪费 资源消耗和收益的平衡折中(消耗~收益)
提高缓存使用率
quire_cash_size 一旦调整,整个缓存空间必须重新进行分配,即整个缓存都会失效
尽量不要调整,不要频繁改变
Paste_Image.png
Paste_Image.png
Com_select
不是记录了所有的查询语句
MySQL执行的查询语句
free block 内存空间被分割成block以后,仍处于空闲阶段的块
缓存的内存空间不一定连续
quire_inserts 可缓存查询语句的结果,被放入缓存的次数
quire_lowmem_prunes 缓存空间(quire_size)太小导致清理缓存(利用lru算法清理)
qcashe_queries_in_cache 在当前的缓存空间里被缓存下来的查询的个数
16M——1000个查询
qcashe_total_blocks 整个查询缓存共有多少个内存块(单元)
是内存区段
不是分割后能够缓存内存查询结果的内存块
查询缓存
不是所有情况下都有效
物理服务器CPU、物理核心数很多
查询缓存可能成为瓶颈和单点 如果是,就要把查询缓存关闭
只要有用,就要开启,节约时间多
使用mamercash缓存,MySQL自己的缓存就不太重要,可以根据情况关闭
索引和explain
索引 ~ 键
数据库越大,索引越重要
Paste_Image.png
SELECT * FROM students WHERE Age+20>50
避免左侧(Age+20)参与布尔运算
mysql中char——长度固定(以字符长度为索引)与varchar——不固定
varchar、text——左前缀(左侧多少个字符)
多列索引
服务器对多个索引做相交操作 AND..(条件)AND...组合条件索引
联合操作 ALL
耗费大量的CPU和内存资源在算法的缓存排序上 单键索引
inodb 聚集索引
MyISAM表 不支持聚集索引
聚集索引 2次查询 非聚集索引——>聚集索引(索引+数据) 性能好
覆盖索引 查询、索引 查询索引,直接返回结果,不访问元数据 降低IO次数
Paste_Image.png
Paste_Image.png
explain
单表查询 1行
两表连接查询 2行
uninue查询 3行
maridb——explain extend、explain partitions(分区)
Paste_Image.png
Paste_Image.png
Paste_Image.png
Paste_Image.png
Paste_Image.png
Paste_Image.png
all 效率低
index 有序,但产生大量的随机IO
null 执行阶段不用访问索引,
const 固定值=常量
Paste_Image.png Paste_Image.pngPaste_Image.png Paste_Image.png Paste_Image.png Paste_Image.png事务
Paste_Image.png Paste_Image.png事务隔离级别
READ COMMITTED 并发性会提高,但是数据复制——不一致
级别 | 线程1 | 线程2 |
---|---|---|
READ UNCOMMITTED | 更改数据 | 读到新数据 |
READ UNCOMMITTED | 回滚 | 读到原数据 |
READ COMMITTED | 读到原数据 | 更改数据 |
READ COMMITTED | 读到新数据 | 更改数据+提交 |
REPEATABLE READ | 更改数据 | 读到原数据 |
REPEATABLE READ | 更改数据+提交 | 读到原数据(幻读) |
REPEATABLE READ | 更改数据+提交 | 提交——读到新数据 |
SERIALIZABILE | 访问阻塞 | 更改数据 |
SERIALIZABILE | 访问阻塞 | 更改数据+提交 |
2个线程执行相同的操作
Paste_Image.png事务日志
提高事务效率
使用事务日志存储引擎修改表中数据,只需修改内存拷贝,并记录事务日志中(追加),避免修改数据文件
事务日志2个或3个,不要太大(崩溃后恢复,不会耗费太长时间)(1、2、3)——事务日志组
先用日志1,1存满了,就及时将其存储于数据文件里,再用2,...,3满了,再用1
逻辑卷——对事务日志和事务文件——快照和备份——事务日志和磁盘必须放在一起
其他——事务日志和磁盘可以不放在一起
InnoDB有很多变量
崩溃后,回复时间——取决于事务日志的数量和文件大小
事务日志——存储引擎
InnoDB的参数——调整事务日志的位置和大小
编译MySQL
服务器特性
服务器、存储引擎各占一半
独特的存储引擎——自己手动编译MySQL
yum info cmake
yum install cmake
yum grouplist
yum install -y "Development Tools" "Server Platform Development"
下载源码
www.mariadb.org
lftps; cd Sources/sources/mariadb/; ls
mget mariadb-5.5.44-...; bye; ls
groupadd -r(系统) -g(gid) 306 mysql
useradd -r -g 306 -u 306 mysql; id mysql; ls
tar xf mariadb-5.5.44-...; cd mariadb-5.5.44; ls 源代码文件
此处步骤:如下图
make 比较耗时; fdisk /dev/sda——...+20G/8e/;如下图 (创建逻辑卷)
make install
Paste_Image.png
创建逻辑卷
Paste_Image.png
Paste_Image.png
Paste_Image.png
Paste_Image.png
make install完成后执行的操作
Paste_Image.png Paste_Image.png Paste_Image.png Paste_Image.png Paste_Image.png回顾:执行某些操作
第一次访问,应该运行;
给所有root用户设定密码,删除匿名用户的操作;
heap——memary
Paste_Image.png Paste_Image.pngcentos7 编译安装
rpm -qa|grep mariadb 查询是否安装
yum remove mariadb 如果安装,则删除
localectl set-locale LANG=en_US.UTF-8 把x-shell的汉语转换为英语
yum -y groupinstall "Development Tools"
yum install ncurses-devel openssl-devel libevent-devel jemalloc-devel cmake
下载mariadb的源码包
tar xf mariadb-5.5.46-...; cd mariadb-5.5.46/;
cmake ...
make && make install
vim /usr/lib/systemd/system/mariadb.service
粘贴内容(如下图)
systemctl daemon-reload
Paste_Image.png
Paste_Image.png
Paste_Image.png
Paste_Image.png
Paste_Image.png
Paste_Image.png
Paste_Image.png
Paste_Image.png
备份工具
备份策略——面试的话题
数据要备份多份~本地、自己、云端
MySQLdump~MySQL自带~几十到几百M~逻辑/物理备份都可以
几十到几百G~物理备份~文件系统级别、复制文件方式、实现备份
xtrebackup~并行、多数聚集同时备份、远程复制~
Paste_Image.png
备份是手段,恢复数据才是目的
mysqldump~备份程序文件~不能备份二进制文件
完全备份+二进制日志文件备份
二进制日志文件名、事件位置
change master 指明从主服务器的哪个二进制文件读取事件位置
二进制文件~线上修改,失效~不能手动删除~如何删除,后面阐述
磁盘设备
RAID设备
RAID1-0(有冗余能力)~4块磁盘~存放数据文件
RAID1~2块磁盘~存放二进制日志文件
InnoDB的事务日志~服务器启动后,崩溃恢复~存放于非数据磁盘或者数据磁盘
mysqldump + 二进制日志文件
一周~~做一次完全备份
每半天~~做一次复制二进制文件(滚动一次)~~增量备份
完全备份
二进制日志文件按顺序导出所有内容,恢复到数据库~~
导出第1次的所有内容,恢复到数据库~~
导出第2次的所有内容,恢复到数据库~~
一直到所有增量备份完成~~
取出最后一个增量备份以后新生成的二进制日志文件中的事件~~
再次replay到数据库
物理备份
commit——不支持热备和温备
逻辑卷、xtra...——几乎热备
逻辑卷——硬件的基础之上,加上软件,硬件损坏或者误删除,——很难恢复
B-TREE——试验阶段
主服务器出故障,备份文件需要还原至备用服务器,如果二进制日志开放状态,还原时,是否关闭;
备份文件还原至备用服务器的过程:是一个写操作,产生二进制事件,一般没有必要,建议关闭;
关闭方式——更改会话级别即可——如下图
Paste_Image.png
Paste_Image.png
Paste_Image.png
必须在同一个会话——即同一个窗口(复制,再开一个窗口,不可以)
source /root 不行,当前运行mysql的用户是mysql,
服务器端无权限读管理员家目录的文件,所以最好放在/tmp目录下;
Paste_Image.png
Paste_Image.png
Paste_Image.png
备份方式:逻辑卷 + 快照
lvm2 + cp/tar
基于lvm2,创造条件
Paste_Image.png
Paste_Image.png
可以再mkdir 一个文件夹,用于存放二进制文件,这里不再演示
/data/mysql——存放逻辑卷
fdisk /dev/sda 创建逻辑卷(7/20G)
partx -a /dev/sda
mke2fs -t ext4 /dev/myvg/mydata
Paste_Image.png
Paste_Image.png
Paste_Image.png
还原时,尽量关闭二进制文件
Paste_Image.png
由于此服务器在线上工作,需要对其做物理模式的备份,如何操作
Paste_Image.png
快照之后的修改,
先将原卷数据复制到快照卷上,再对原卷进行修改,
快照卷上的数据——原卷未修改——通过原卷访问
快照卷上的数据——原卷已经修改——通过快照卷上复制的修改之前的文件副本来访问
Paste_Image.png
Paste_Image.png
Paste_Image.png
为逻辑卷创建快照——目的:备份——大小
多大合适——用于备份的时间范围内~~所改变的数据量能够存储的下~~未必和原卷一样大
备份只需3个小时~~3h的数据量,在改变最多的时候,也不会超过1个G~~即创建1个G即可
Paste_Image.png
Paste_Image.png
Paste_Image.png
开始备份
挂载快照卷
Paste_Image.png
出错,重新做
Paste_Image.png Paste_Image.png Paste_Image.png Paste_Image.png Paste_Image.png锁定以后,马上滚动,再改数据
这里没有操作,后续利用二进制日志文件恢复至时间点,就不行了
都是你妈的瞎BB——mage教育
备份数据——从快照备份
备份二进制日志——从原卷备份
Paste_Image.png
以上为主机1
主机2
主机1
Paste_Image.png Paste_Image.png主机2
Paste_Image.png Paste_Image.png Paste_Image.png Paste_Image.png备份数据——从快照备份
备份二进制日志——从原卷备份
二进制日志——可以单独放在一个卷上,这个卷无需快照
Paste_Image.png
还原回来的数据要确保数据的属主和属组是否正确 cp -a
执行恢复时,通过重放二进制日志——进行时间点还原,需要把当前的二进制日志关闭
Paste_Image.png
问题
0:00-2:00备份
10:00 误操作
2h之后才意识到出错
解决
备用服务器——备份还原
二进制日志文件——导出至文本文件————从文本找到误操作后,删除——replay即可
xtrabackup
percona,www.percona.com
percona-server/oracle-mysql/mariadb
InnoDB(MYSQL)——>XtraDB
Xtrabackup