数据库MySQL教程

目录

文章目录

  • 目录
  • MySQL 教程
  • 1.MySQL的5种常见数据类型
  • 2.MySQL 操作语句
    • DDL 库/表
      • - 库的操作
      • - 表的操作
    • DML 数据 增删改
      • 删和改
    • DQL 数据查询
      • 条件查询 where
      • 分组查询 group by
      • 筛选查询 having
      • 排序查询 order by
      • 限制查询 limit
      • exists 查询
      • 左右连接 查询
      • 内连接查询
      • 联合查询
    • DCL 数据库控制语言
      • 限制root用户登录IP
      • 用户密码
      • 创建用户并指定ip网段登录
      • 库表权限 授权与回收
      • 自定义sql结束符号
  • 3.MySQL 核心知识
    • 事物
    • 视图
    • 触发器
    • 存储过程介绍
    • 存储引擎介绍
    • 索引
      • 普通索引和唯一索引
      • 主键索引
      • 全文索引
      • 外键索引
      • 联合索引
  • 4.MySQL优化思路
    • 慢查询日志开启
    • MySQL 语句 步骤解析
    • MySQL 语句优化的几个小建议
  • 5.Mysql备份技能
    • 数据备份的基本知识
    • mysqldump备份与恢复
    • mysql物理备份
    • 利用二进制日志备份
    • 利用二进制日志恢复

MySQL 教程

教程使用 社区版mysql 5.7

安装MySQL 5.7 j教程

1.MySQL的5种常见数据类型

<1>整数型

类型 大小 范围(有符号) 范围(无符号unsigned) 用途
TINYINT 1 字节 (-128,127) (0,255) 小整数值
SMALLINT 2 字节 (-32768,32767) (0,65535) 大整数值
MEDIUMINT 3 字节 (-8388608,8388607) (0,16777215) 大整数值
INT 4 字节 (-2147483648,2147483647) (0,4294967295 大整数值
BIGINT 8 字节 () (0,2的64次方减1) 极大整数值

<2>浮点型

类型 大小 名称
FLOAT(m,d) 4 字节 单精度浮点型 备注:m代表总个数,d代表小数位个数
DOUBLE(m,d) 8 字节 双精度浮点型 备注:m代表总个数,d代表小数位个数

<3>定点型

类型 大小
DECIMAL(m,d) 依赖于M和D的值 存的是什么就是什么

<4>字符串类型

类型 大小 用途
CHAR 0-255字节 定长字符串
VARCHAR 0-65535字节 变长字符串
TINYTEXT 0-255字节 短文本字符串
TEXT 0-65535字节 长文本数据
MEDIUMTEXT 0-16777215字节 中等长度文本数据
LONGTEXT 0-4294967295字节 极大文本数据
 char的优缺点:存取速度比varchar更快,但是比varchar更占用空间
 varchar的优缺点:比char省空间。但是存取速度没有char快

<5>时间型

类型 大小 格式 用途
date 3 yyyy-MM-dd 存储日期值
time 3 HH:mm:ss 存储时分秒
year 1 yyyy 存储年
datetime 8 yyyy-MM-dd HH:mm:ss 存储日期+时间
timestamp 4 yyyy-MM-dd HH:mm:ss 存储日期+时间,可作时间戳

2.MySQL 操作语句

操作语句分为4类:

  • 1.DDL 数据定义语言: 如建库,建表
  • 2.DML 对表中数据进行增删改操作
  • 3.DQL 对数据进行查询操作
  • 4.DCL 对用户的权限进行设置

DDL 库/表

- 库的操作

创建库

# 普通创建
create database xiaoming;
# 判断数据库是否存在,如果不存在则创建
create database if not exists xiaoming;
# 创建数据库并制定字符集
create database xiaoming default character set UTF-8;

查看库

# 进入/切换库
use 库名
# 查看所有库
show databases;
# 查看当前库
select database();
# 查询库的创建信息
show create database xiaoming;

删除库

drop database xiaoming;

- 表的操作

创建表

# 语法:
CREATE TABLE 表名 (
                  字段名1 字段类型1 约束条件1 约束条件5 说明1,
                  字段名2 字段类型2 约束条件2 说明2,
                  字段名3 字段类型3 约束条件3 说明3
                  );

# 约束条件:
not null        ----不为空
default         ----默认值
unsigned        ----无符号(即正数,默认都是有符号的)
auto_increment  ----自增
zerofill        ----自动填充
unique key      ----唯一值
comment         -----注释/说明
# eg.
create table student (
id tinyint(5) zerofill auto_increment  comment '学生学号', # 00001 
name varchar(20) default null comment '姓名',
age tinyint not null comment '年龄',
class varchar(20) not null comment '班级',
sex char(5) not null comment '性别'				
);

复制表

# 只复制表结构 但不会复制主键信息
create table teacher as select * from where 1=2;
# 复制表结构+表信息
create table teacher as select * from where 1=1;

# 完全复制表结构
create table teacher like student; 

删除表

drop table 表名 ;
drop table if exists 表名;

查看表信息

# 查看当前库所有表
show tables;
# 查看表结构
desc 表名 ;
# 查看创建表的语句  (\G美化,省略分号)
show create table student\G

表结构的维护和删除

# 修改表名
rename table 旧表名 to 新表名;
# 修改字符集
alter table 表名 character set 字符集;

# 添加列
alter table add 列名 类型 comment '说明';
# 最前面添加一列
alter table 表名 add 列名 类型 first;
# 某个字段后添加一列
alter table 表名 add 列名 类型 after 字段名;

# 修改列类型
alter table 表名 modify 列名 新类型;
# 修改列名
alter table 表名 change 旧列名 新列名 类型;
# 删除列
alter table 表名 drop 列名;

DML 数据 增删改

# 创建公司的员工表,下面学习笔记会用到
CREATE TABLE employee(
    empno       INT  PRIMARY KEY comment '雇员编号',
    ename       VARCHAR(20) comment '雇员姓名',
    job         VARCHAR(20) comment '雇员职位',
    mgr         INT comment '雇员上级编号',
    hiredate    DATE comment '雇佣日期',
    sal         DECIMAL(7,2) comment '薪资',
    deptnu      INT comment '部门编号'
    );

向表中插入数据

# 如果省略字段名,字段对应值,必须全。
insert into 表名 (字段名) values (字段对应值);
# eg.
insert into employee (empno,ename,job,mgr,hiredate,sal,deptnu) values ('1000','小明','经理','10001','2019-03-03','12345.23','10');

# 一次性插入多组数据
insert into 表名  (字段名) values (对应值1),(对应值2),(对应值3); 

复制表内所有信息

# 复制表employee结构  名为emp
create table emp like employee;

# 蠕虫复制 将一张表的数据复制到另一张表中
# 复制数据
insert into emp select * from employee;
# 复制数据只复制某些字段
insert into emp (empno,ename) select empno,ename from employee;

# 建表复制
create table 表名1 as select 字段名1,字段名2 from 表名2;

删和改

# 修改数据
update 表名 set 字段名1=值1 where 字段名=值;
update 表名 set 字段名1=值1,字段名2=值2 where 字段名=值;

# 删除数据
delete from 表名 where 字段名=值;

# 删除整张表
truncate table 表名;
delete from 表名; # 不加条件 会删除表内所有数据
drop table 表名;

区别:
drop 表会被删除
delete 会把删除的操作记录给记录起来,以便数据回退,不会释放空间,而且不会删除定义
truncate不会记录删除操作,会把表占用的空间恢复到最初,不会删除定义
删除速度:
drop > truncate > delete	

DQL 数据查询

创建以下几个表,为我们提供练习操作

/*创建部门表*/
CREATE TABLE dept(
    deptnu      INT  PRIMARY KEY comment '部门编号',
    dname       VARCHAR(50) comment '部门名称',
    addr        VARCHAR(50) comment '部门地址'
);
​
某个公司的员工表
CREATE TABLE employee(
    empno       INT  PRIMARY KEY comment '雇员编号',
    ename       VARCHAR(50) comment '雇员姓名',
    job         VARCHAR(50) comment '雇员职位',
    mgr         INT comment '雇员上级编号',
    hiredate    DATE comment '雇佣日期',
    sal         DECIMAL(7,2) comment '薪资',
    deptnu      INT comment '部门编号'
)ENGINE=MyISAM DEFAULT CHARSET=utf8;
​
/*创建工资等级表*/
CREATE TABLE salgrade(
    grade       INT  PRIMARY KEY comment '等级',
    lowsal      INT comment '最低薪资',
    higsal      INT comment '最高薪资'
);
​
/*插入dept表数据*/
INSERT INTO dept VALUES (10, '研发部', '北京');
INSERT INTO dept VALUES (20, '工程部', '上海');
INSERT INTO dept VALUES (30, '销售部', '广州');
INSERT INTO dept VALUES (40, '财务部', '深圳');
​
/*插入emp表数据*/
INSERT INTO employee VALUES (1009, '唐僧', '董事长', NULL, '2010-11-17', 50000,  10);
INSERT INTO employee VALUES (1004, '猪八戒', '经理', 1009, '2001-04-02', 29750, 20);
INSERT INTO employee VALUES (1006, '猴子', '经理', 1009, '2011-05-01', 28500, 30);
INSERT INTO employee VALUES (1007, '张飞', '经理', 1009, '2011-09-01', 24500,10);
INSERT INTO employee VALUES (1008, '诸葛亮', '分析师', 1004, '2017-04-19', 30000, 20);
INSERT INTO employee VALUES (1013, '林俊杰', '分析师', 1004, '2011-12-03', 30000, 20);
INSERT INTO employee VALUES (1002, '牛魔王', '销售员', 1006, '2018-02-20', 16000, 30);
INSERT INTO employee VALUES (1003, '程咬金', '销售员', 1006, '2017-02-22', 12500, 30);
INSERT INTO employee VALUES (1005, '后裔', '销售员', 1006, '2011-09-28', 12500, 30);
INSERT INTO employee VALUES (1010, '韩信', '销售员', 1006, '2018-09-08', 15000,30);
INSERT INTO employee VALUES (1012, '安琪拉', '文员', 1006, '2011-12-03', 9500,  30);
INSERT INTO employee VALUES (1014, '甄姬', '文员', 1007, '2019-01-23', 7500, 10);
INSERT INTO employee VALUES (1011, '妲己', '文员', 1008, '2018-05-23', 11000, 20);
INSERT INTO employee VALUES (1001, '小乔', '文员', 1013, '2018-12-17', 8000, 20);
​
/*插入salgrade表数据*/
INSERT INTO salgrade VALUES (1, 7000, 12000);
INSERT INTO salgrade VALUES (2, 12010, 14000);
INSERT INTO salgrade VALUES (3, 14010, 20000);
INSERT INTO salgrade VALUES (4, 20010, 30000);
INSERT INTO salgrade VALUES (5, 30010, 99990);

条件查询 where

普通查询

#  简单查询
select * from 表;
select 字段1,字段2,字段3 as 字段3别名 from 表;

# 精确查询
select * from employee where ename='后裔';
select * from employee where sal != 50000;
select * from employee where sal <> 50000;
select * from employee where sal > 10000;

# 模糊条件查询
show variables like '%aracter%'; 
select * from employee  where ename like '林%';

# 范围查询
select * from employee where sal between 10000 and 30000;
select * from employee where hiredate between '2011-01-01' and '2017-12-1';

# 离散查询
select * from employee where ename in ('猴子','林俊杰','小红','小胡');

# 清除重复
select distinct(job) from employee;

统计查询(聚合函数)

# count 统计条数
select count(*) from employee;
select count(ename) from employee;

# sum 求和
select sum(sal) from employee;

# max() 计算最大值
select  max(sal) from employee;
select * from employee where sal= (select  max(sal) from employee);

# min() 计算最低值
select * from employee where sal= (select  min(sal) from employee);

# avg() 计算平均值
select avg(sal) from employee;

# concat 起到连接作用, aaa -> "唐僧 是 董事长"
select concat(ename,' 是 ',job) as aaaa from employee;

分组查询 group by

  • 作用:把行按字段进行分组
  • 语法:group by 列1,列2…列N
  • 适用场合:常用于统计场合,要和聚合函数连用
# 按deptnu部门编号分组,显示部门编号和每个部门编号下有多少员工
select deptnu,count(*) from employee group by deptnu;

# 按职位分组,每个岗位多少员工
select job,count(*) from employee group by job;

# 按照部门+职位分组,并计算这种分组下有多少员工
select deptnu,job,count(*) from employee group by deptnu,job;

筛选查询 having

一般都是和 聚合函数group by 合用

对查询的结果筛选操作,一般跟在group by 后面

# group by 中练习的 (按职位分组,每个岗位多少员)
select job,count(*) from employee group by job
# 上述基础上,只查询文员,或者叫 筛选出文员
select job,count(*) from employee group by job having job ='文员';

# 部门+职位 下的员工 >= 2人的
select  deptnu,job,count(*) from employee group by deptnu,job having count(*)>=2;
# having 后面不使用count(*),使用别名
select  deptnu,job,count(*) as 总数 from employee group by deptnu,job having 总数>=2;

排序查询 order by

  • 对结果进行排序
  • order by 字段2,字段2
  • 倒序 从大到小 order by 字段 desc;
  • 正序 从小到大 order by 字段 asc ; 默认order by 为 asc
select deptnu,job,count(*) as 总数 from employee group by deptnu,job having 总数>=2 order by deptnu;
顺序:where ---- group by ----- having ------ order by

限制查询 limit

查询结果 限制条数

语法: limit n,m

n代表 起始位置,不写默认0

m代表取出条数

select * from xiaoming.employee limit 4,5;

exists 查询

  • exists型子查询后面是一个受限的select查询语句
select * from 表名 a where exists (select 1 from 表名2 where 条件);

# 括号内的查询语句,如果查询为空 exists前的语句不执行,返回空
# 如果括号内查询语句有结果,则正常执行前面的语句。
# 是用select 1 ,查询到结果返回True,空则返回False

not exists 则相反 

左右连接 查询

它们都属于 外连接

# 简写 | 完整写法
left  join 表名 on 条件 |  left  outer 表名 Join on 条件
right join 表名 on 条件 |  right outer 表名 Join on 条件

连接查询首先要有 两张表

左连接: 以左表为准,全部显示取来,右表显示符合搜索条件的记录,没有的用null补

右连接:同理,以右表为基准

# 列出部门名称和这些部门的员工信息,同时列出那些没有的员工的部门
select a.dname,b.* from dept a  left join employee b on a.deptnu=b.deptnu;
select b.dname,a.* from employee a  right join  dept b on b.deptnu=a.deptnu;

内连接查询

获取两个表中 字段匹配的记录(条件)

INNER JOIN 表名 ON 条件

# 想查出员工张飞部门的所在地址
select a.addr from dept a inner join employee b on\
a.deptnu=b.deptnu and b.ename='张飞';

联合查询

就是把多个查询语句的查询结果结合在一起

把多个查询结果 拼接成一张表(上下拼接)。

union 多个表必须字段一致

(select * from employee a where a.job = '销售员' \ order by a.sal limit 999999 ) 
union  
(select * from employee b where b.job = '文员' \
order by b.sal desc limit 999999);

DCL 数据库控制语言

设置更改数据库用户,角色权限的语句。

限制root用户登录IP

myqsl 的用户表在 mysql.user表中

use mysql;
select user,host from user where user='root';
# host % 代表任何一台机器都可以登录

mysql -uroot -p              # 连接的是localhost
mysql -uroot -h127.0.0.1 -p  # 指定IP登录

# 更改允许的登录IP
update user set host='localhost' where user='root';
update mysql.user set host='localhost' where user='root';
# 刷新权限
flush privileges

用户密码

# 修改用户密码
# 方法1. 数据库内执行
set password for 用户@IP = password('密码');
# 方法2  终端命令行
mysqladmin -u用户 -p旧密码 password 新密码
# 方法3  修改表
select * from user where user='root' \G; 
#先查看密码的字段是什么,我的是 authentication_string
update mysql.user set authentication_string=password("123456") where user='root' ;
# 因为可能root有IP localhost多个,密码不同,所以where限制条件,最好再加上host,不然会更改全部root密码

如果忘记密码怎么办?

修改my.cnf (默认在/etc/my.cnf)
在[mysqld]下面加上 skip-grant-tables 跳过权限的意思
重启mysql服务,mysql -uroot -p 这时候无需密码登录进入
然后执行修改用户密码的操作即可。

创建用户并指定ip网段登录

# 语法
create user 'username'@'host' identified by 'password';
# 创建一个pig用户,并指定登录密码:123456,可以在任何一台远程主机都可以登录
create user 'pig'@'%' identified by '123456';
# 创建一个pig用户,并指定登录密码:为空,指定在120网段的机器登录
create user 'pig'@'120.%.%.%' identified by '';

# 查看创建的用户信息(包括权限)
select * from mysql.user where user='ping'\G
# 或者查看权限
show grants for 'pig'@'%';
USAGE: 无权限的意思

# 删除用户
drop user 'pig'@'host';
# 或者
delete from mysql.user where user='pig';

库表权限 授权与回收

# 授权
grant 权限1,权限2..... on 数据库对象 to '用户'
grant 权限1,权限2..... on 数据库对象 to '用户'@'host' identified by 'password';
# 回收
revoke 权限1,权限2..... on 数据库对象 from '用户'@'host';

all privileges   # 所有权限
select           # 查询权限
update           # 修改权限
insert           # 添加权限

实战

# 授权实战例子
# 对现有用户进行授权:对现有用户pig授予所有库所有表所有权限。
grant all privileges on *.*  to 'pig';
# 对没有的用户进行授权:创建一个新用户dog授予XD库的所有权限
# 登录密码123456,任何一台主机登录
grant all privileges on XD.* to 'dog'@'%' identified by '123456';
# 对没有的用户进行授权:创建一个新用户cat授予XD库的employee表 查与修改权限
# 登录密码123456,任何一台主机登录
grant select,update on XD.employee to 'cat'@'%' identified by '123456'


# 回收实战
# 回收pig用户的所有权限(注意:并没有回收它的登录权限)
revoke all privileges on *.*  from 'pig' @ '%';
flush privileges;

# 回收pig用户的所有权限(并回收它的登录权限)
delete from mysql.user where user='pig';
flush privileges;

# 回收cat用户对XD库的employee的查与修改权限
revoke select,update on XD.employee from 'cat'@'%';
flush privileges;

自定义sql结束符号

# sql结束符号默认为; 修改为//
delimiter //
# 改回来
delimiter ;

3.MySQL 核心知识

事物

事物的特性(ACID)

  • 原子性(Atomicity) : 原子工作单元,一个事物中的所有语句,要么全部成功,要么全部失败
  • 一致性(Consistency): 让数据保持逻辑上的’合理性’,比如发红包,小明给小红发10元,必须小明-10,小红+10
  • 隔离性 (Isolation) : 并发多个事物,每个事物独立执行
  • 持久性(Durability): 一个事务执行成功,则对数据来说应该是一个明确的硬盘数据更改,不仅仅是内存中.

注意 : MySQL 5.7 innode支持事物操作

事物开启   begin;
事物提交   commit;
事物回滚   rollback;

事物实战演习

# 创建一个账户表模拟转账,需要指定innodb引擎
create table account (
                         id tinyint(5) zerofill auto_increment  not null comment 'id编号',
                         name varchar(20) default null comment '客户姓名',
                         money decimal(10,2) not null comment '账户金额',
                         primary key (id)
                         )engine=innodb charset=utf8;
# 开始事务
begin;
# 插入数据
insert into account values ("1","张三"."98000");
# 查询发现有数据 
select * from account;

# 另外开一个窗口 ,再次查询,发现没有数据
# 因为执行插入命令的窗口内存中有,但是未提交,所以其他连接查询不到
# 当我们提交后,才能正常查询
# 如果我们回滚,两个都消失

自动提交 autocommit

# autocommit 默认为开启状态
# OFF(0):表示关闭 
# ON (1):表示开启

# 临时关闭 autocommit
set autocommit=0;

# 查询设置
show variables like 'autocommit';

# 开启autocommit(永久生效):
# 修改配置文件:vi /etc/my.cnf 在[mysqld]下面加上:
autocommit=1 
# 然后重启

# -------------------------------------------
autocommit 开启状态下为开启状态
update table set flag=1 where flag=3
与
update table set flag=1 where flag=3;
commit;
相同,
但是 如果手动begin,则也必须手动commit或roll
# -------------------------------------------
# autocommit设置为OFF后,事物并没有自动提交,则需要自己commit
update table set flag=1 where flag=3;
commit;

视图

视图: 是虚拟存在的表,逻辑存在的表,作为一个select语句 保存在数据字典中。

视图优点:

  • 简单 :使用视图的用户,不需要关心视图后面的表结构,关联关系和筛选条件

    对用户来说已经是过滤好的复合条件的结果集

  • 安全: 使用视图的用户只能访问他们被允许查询的结果集。

    ​ 表的权限管理不能具体到 行和列,但是通过视图就可以简单的实现。

  • 数据独立: 一旦视图的结构确定了,可以屏蔽表结构变化对用户的影响,

    ​ 源表增加列对视图没有影响;

    ​ 源表修改列名,则可以通过修改视图来解决,不会造成对访问者的影响。

  • 不占空间: 视图是逻辑上的表,不占用内存空间.

视图的创建以及修改

# 创建的基本语法是:
# 如果视图存在会报错
create view <视图名称> as select 语句;
create view <视图名称> (字段) as select 语句;
# 如果存在就代替,没存在就创建
create or replace view <视图名称>;

# 修改的语法是:
alter view <视图名称> as select 语句;

# 视图删除语法:
drop view <视图名称> ;
# 创建一个视图
create view employ as select empno,ename,job,mgr,deptnufrom employee;
# show tables 视图也会被展示出来,把这个视图当作表用即可。
select * from employ;

视图的缺点:

性能差: 视图查询 --> 基表查询 这中间会有转换,所以会比直接查询基表消耗更多资源。

修改限制: 当用户试图修改试图的某些信息时,数据库必须把它转化为对基本表的某些信息的修改,

​ 对于简单的试图来说,这是很方便的,但是,对于比较复杂的试图,可能是不可修改的。

触发器

触发器使用的不多,但还是要了解一下什么是触发器.

触发器简单来说就是监视某种情况,触发某种动作

# 触发器语法
create trigger 触发器名称  after/before   insert/update/delete on 表名  
        for each row
        begin
        sql语句;
        end

after/before:可以设置为事件发生前或后
insert/update/delete:它们可以在执行insert、update或delete的过程中触发
for each row:每隔一行执行一次动作

# 删除触发器的语法:
drop trigger 触发器名称;

触发器演练

# 创建一个员工迟到表:
create table work_time_delay(
            empno int not null comment '雇员编号',
            ename varchar(50) comment '雇员姓名',
            status int comment '状态'
            );

# 创建触发器
# 
create trigger trig_work after insert on work_time_delay
-> for each row
-> begin
-> update employee set sal=sal-100 where empno=new.empno;
-> end
-> ;
# new: 指的是事件发生before或者after保存的新数据

存储过程介绍

存储过程就是一个数据库的脚本
存储过程就是把复杂的一系列操作,封装成一个过程。

使用后,分库分表几乎变成不可能

优点是:
1)复杂操作,调用简单
2)速度快
缺点是:
1)封装复杂
2) 没有灵活性

# 创建存储过程语法
create procedure 名称 (参数....)
        begin
         过程体;
         过程体;# 可以多个
         end
         
         
参数:in|out|inout 参数名称 类型(长度)
       in:表示调用者向过程传入值(传入值可以是字面量或变量)
       out:表示过程向调用者传出值(可以返回多个值)(传出值只能是变量)
       inout:既表示调用者向过程传入值,又表示过程向调用者传出值(值只能是变量)
       
声明变量:declare 变量名 类型(长度) default 默认值;
给变量赋值:set @变量名=值;
调用存储命令:call 名称(@变量名);
删除存储过程命令:drop procedure 名称;
查看创建的存储过程命令:show create procedure 名称\G;

例子

# 创建 存储过程
create procedure name(in n int )
  begin
  select * from employee limit n;
  end;
# 赋值
set @n=5;
# 调用存储过程name
call name(@n)


# 在内部定义变量
create procedure  name()
  begin
  declare  n int default 6;
  select * from employee limit n;
  end
# 调用
call name()

存储引擎介绍

数据库引擎是数据库底层软件组件

不同的存储引擎,可以获得特定的功能。

比如 引技巧,锁定水平等功能

数据库引擎是基于表

查看引擎

# 查看支持的引擎
show engines;

# 查看当前数据的引擎
show create table 表名\G

# 查看当前库所有表的引擎
show table status\G

引擎修改命令

# 创建表的时候指定引擎
create table yingqin (id int,name varchar(20)) engine='InnoDB';

# 修改表的引擎
alter table 表名 engine='MyiSAm';

# 修改默认引擎
# vi /etc/my.cnf   
# [mysqld]下面 default-storage-engine=MyIsAM   然后重启

MyISAM与InnoDB的区别

MyISAM:
支持全文索引(full text);
不支持事务;
表级锁;
保存表的具体行数;
奔溃恢复不好

Innodb:
支持事务;
以前的版本是不支持全文索引,但在5.6之后的版本就开始支持这个功能了;
行级锁(并非绝对,当执行sql语句时不能确定范围时,也会进行锁全表例如: update table set id=3 where name like 'a%';);
不保存表的具体行数;奔溃恢复好

引擎选择

MyISAM:
•    一般来说MyISAM不需要用到事务的时候
•    做很多count计算

InnoDB:
•    可靠性要求高的,或者要求支持事务
•    想要用到外键约束的时候(讲外键的时候会讲)

推荐:
•    推荐用InnoDB

索引

索引优点

  • 通过创建唯一索引,来保证数据库表中的每一行数据的唯一性。
  • 可以加快数据的检索速度。
  • 可以保证表数据的完整性与准确性

索引缺点

  • 索引需要占用物理空间。
  • 对表中的数据进行改动时,索引也需要跟着动态维护,降低了数据的维护速度。

常见索引

  • index:普通索引
  • unique:唯一索引
  • primary key:主键索引
  • foreign key:外键索引
  • fulltext: 全文索引
  • 组合索引

创建索引注意点

索引并非越多越好,过多的索引会增加数据的维护速度还有磁盘空间的浪费。

• 当表的数据量很大的时候,可以考虑建立索引。

• 表中经常查数据的字段,可以考虑建立索引。

• 想要保证表中数据的唯一性,可以考虑建立唯一索引。

• 想要保证俩张表中的数据的完整性跟准确性,可以考虑建立外键约束。

• 经常对多列数据进行查询时,可以考虑建立联合索引。

普通索引和唯一索引

普通索引: index 主要任务就是提高查询速度。其特点是允许出现相同的索引内容,允许空(null)值
唯一索引: unique 顾名思义就是不可以出现相同的索引内容,但是可以为空(null)值

创建索引的方法

# 方法1
# 创建表的时候创建
create table test (
                        id int(7) zerofill auto_increment not null,
                        username varchar(20),
                        servnumber varchar(30),
                        password varchar(20),
                        createtime datetime,
                        unique (id)
                  )DEFAULT CHARSET=utf8;

# 方法2
# 直接为表添加索引
alter table 表名 add index 索引名称 (字段名称);
# eg. 注意:假如没有指定索引名称时,会以默认的字段名为索引名称
alter table test add unique unique_username (username);

# 方法3
# 直接创建索引
语法:create index 索引 on 表名 (字段名);
# eg.
create index index_createtime on test (createtime);

查看索引

show index from test\G

删除索引

drop index 索引名称 on 表名;
drop index unique_username on test;

alter table 表名 drop index 索引名;
alter table test drop index createtime;

主键索引

PRIMARY KEY

主键: 每张表只能拥有一个主键,主键加索引就是主键索引。

它是一种特殊的唯一索引,不允许有空值,而唯一索引(unique是允许为空值的)

 # 创建主键
 # 1.创建表的时候创建
 # 略
 # 2.直接为表添加主键索引
 alter table 表名 add primary key (字段名);
 alter table test add primary key (id);
 
 # 删除主键
 alter table 表名 drop primary key;
 
 # 如果主键为自增,需要先删除自增
 alter table test change id id int(7) unsigned zerofill not null;

全文索引

fulltex,全文索引

数据库储存文章和句子,查询内容的索引,单位是词

# 创建索引
# 创建表时候创建

create table command (
id int(5) unsigned primary key  auto_increment,
name varchar(10),
instruction varchar(60),
fulltex(instruction)
)engine=MyISAM;

# 通过alter添加
alter table command  add fulltext(instruction);


# 使用全文索引
select * from 表名 where match  (字段名) against ('检索内容');
select * from command where match(instruction) against ('sections');

# 查看匹配度
select * from command where match(instruction) against ('directory');

# 删除全文索引
alter table command drop index instruction;

# 详细使用
https://www.cnblogs.com/tommy-huang/p/4483684.html

外键索引

# 创建外键约束
foreign key (字段名) references 关联的表名(关联表的字段名)

# 创建表时候
CREATE TABLE `employee` (
  `empno` int(11) NOT NULL COMMENT '雇员编号',
  `ename` varchar(50) DEFAULT NULL COMMENT '雇员姓名',
  `job` varchar(30) DEFAULT NULL,
  `mgr` int(11) DEFAULT NULL COMMENT '雇员上级编号',
  `hiredate` date DEFAULT NULL COMMENT '雇佣日期',
  `sal` decimal(7,2) DEFAULT NULL COMMENT '薪资',
  `deptnu` int(11) DEFAULT NULL COMMENT '部门编号',
  PRIMARY KEY (`empno`),
 foreign key (deptnu) references dept(deptnu)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

# 向表中添加
alter table employee add foreign key (deptnu) references dept(deptnu);

# 删除外键约束
# 需要先删除约束,然后再删除索引
# 查询外键 show create table 表名\G ,查看外键约束
alter table employee drop foreign key employee_ibfk_1;
alter table employee drop index deptnu;

# 注意
# 俩个表,主键跟外键的字段类型一定要相同
# 要使用外键约束表的引擎一定得是InnoDB引擎,MyISAM是不起作用的
# 在干掉外键索引之前必须先把外键约束删除,才能删除索引

联合索引

复合索引 组合索引,多个索引。

# 添加
alter table 表名 add index(字段1,字段2,字段3);
alter table test add index(username,servnumber,password);

# 删除
alter table test drop index username;
# 联合索引的最左原则

4.MySQL优化思路

慢查询日志开启

# 1.查看是否已经开启了慢查询日志
show variables like 'slow%'

# 2.开启慢查询日志
set global slow_query_log = on ;
# 自定义日志路径
set global slow_query_log_file = '路径';

# 3.查看慢查询的时间临界值
show variables like '%long%';

# 4.设置慢查询的时间标准
set long_query_time=0.4;

# 重启服务, 设置会恢复到默认
# 永久设置后, 重启服务生效
[mysqld]
slow_query_log = 1
long_query_time = 0.1
slow_query_log_file =/usr/local/mysql/mysql_slow.log

MySQL 语句 步骤解析

# 执行查询
select * from test where servnumber="13670087879";

# 前面加上expain
expain select * from test where servnumber="13670087879" \G

# 查询性能详情是否开启
show variables like '%profiling%';

# 开启性能记录功能
set profiling = on ;

# 查询性能记录 
show profiles;

# 查看语句的执行性能详情
show profile for query 4;

MySQL 语句优化的几个小建议

1.尽量避免使用select *from ,尽量精确到想要的结果字段
2.尽量避免条件使用or
3.记得加上limit 限制行数,避免数据量过大消耗性能
4.使用模糊查询时,%放在前面是会使索引失效
5.要小心条件字段类型的转换

5.Mysql备份技能

数据备份的基本知识

数据备份类型

  • 完全备份

  • 部分备份

    ​ (1) 增量备份 以上一次为基础

    ​ (2) 差异备份 以一次完全备份为基础

数据备份方式

  • 逻辑备份 直接生成SQL语句,在恢复时候重现sql语句来实现
  • 物理备份 直接复制拷贝 相关数据库文件

数据备份场景

  • 热备份 数据库读写操作不会受到影响
  • 温备份 数据库可以读,但是备份期间不能执行写操作
  • 冷备份 备份时,禁止读写操作。

mysqldump备份与恢复

mysqldump 数据逻辑备份 完全备份

# 数据量不是很大的时候,mysqldump就够了
mysqldump -u 用户 -h host -p 密码 dbname tbale > 路径

常用例子

# 远程备份单库例子
mysqldump -uroot -pabc123456 -h120.25.93.69 zabbix | gzip  > /mysql_data_back/zabbix_users.sql.gz

# 远程备份单库例子并保留创建库语句
mysqldump -uroot -pabc123456 -h120.25.93.69 --databases zabbix | gzip  > /mysql_data_back/zabbix_bak.sql.gz

# 远程备份单库单表的例子
mysqldump -uroot -pabc123456 -h120.25.93.69 zabbix  users | gzip  > /mysql_data_back/zabbix_users.sql.gz

# 远程备份多库的例子
mysqldump -uroot -pabc123456 -h120.25.93.69 --databases zabbix XD | gzip  > /mysql_data_back/zabbix_XD.sql.gz

# 远程备份全库的例子
mysqldump -uroot -pabc123456 -h120.25.93.69 --all-databases  | gzip  > /mysql_data_back/all.sql.gz

恢复

# 远程恢复数据(备份的数据文件里有创建库的语句)
mysql -uroot -pabc123456 -h120.25.93.69  < zabbix_bak.sql

# 远程恢复数据(备份的数据文件里没有创建库的语句)
mysql -uroot -pabc123456 -h120.25.93.69  zabbix < zabbix_bak.sql

mysql物理备份

数据库源文件路径

# 查找数据库源文件路径(一)
show variables like 'datadir%';
# 查找数据库源文件路径(二)
cat /etc/my.cnf

数据库源文件

MyISAM表源文件
db.opt:创建库的时候生成,主要存储着当前库的默认字符集和字符校验规则
.frm :记录着表结构信息的文件
.MYI:记录着索引的文件
.MYD :记录着表的数据


InnoDB表源文件:InnoDB有着共享表空间跟独立表空间的概念。
db.opt:创建库的时候生成,主要存储着当前库的默认字符集和字符校验规则
.frm :记录着表结构信息的文件
.ibd :独立表空间,里边记录这个表的数据和索引
ibdata1:共享表空间,里边记录表的数据和索引

对于MyISAM,直接备份数据库文件夹即可

对于InnoDB,除了数据库文件夹,还需要备份 ib_logfile0 b_logfile1 ibdata1

Mysql上锁

# 请求全局读锁:
flush tables with read lock;
# 解锁
unlock tables;

利用二进制日志备份

二进制日志 记录着MySQL数据库的 增删改,不包含查询

可以利用二进制日志进行数据复制和恢复。

开启二进制日志会有1%的性能消耗!

查看二进制日志是否开启

show variables like 'log_bin%';

开启二进制日志 : vi /etc/my.cnf

[mysqld]
log-bin=/data/mydata/log_bin/mysql-bin
server-id=1

查看所有的binlog日志列表

mysql> show master logs;
+------------------+-----------+
| Log_name         | File_size |
+------------------+-----------+
| mysql-bin.000001 |     23638 |
+------------------+-----------+

刷新二进制日志:

flush logs;

重置(清空)二进制日志文件

mysql> show master logs;
+------------------+-----------+
| Log_name         | File_size |
+------------------+-----------+
| mysql-bin.000001 |      1091 |
+------------------+-----------+

使用mysqldump备份数据时,加上-F选项可以重新生成一个新的二进制日志文件

# 会使用mysqldump 备份数据库 XD.user表,并且重新生产一个文件002 记录二进制logbin文件
mysqldump -uroot -p XD user -F  > user_bak.sql

利用二进制日志恢复

mysqlbinlog mysql-bin.000002 
 # 如果报错
 # 第一种:在mysqlbinlog 后边加上 --no-defaults 
 # 第二种:注释掉配置文件里边的default-character-set=utf8
 
# 把二进制日志文件导出成普通文件 
mysqlbinlog --base64-output=DECODE-ROWS -v mysql-bin.000002 > mysqlbin.sql

# 找出关键字的行数 drop操作的行数
mysqlbinlog --no-defaults mysql-bin.000002 | cat -n  | grep -iw 'drop'
4180  DROP TABLE `user` /* generated by server */

# 打印出相关内容
mysqlbinlog --no-defaults mysql-bin.000002 | cat -n | sed -n '4170,4180p'
# ----------------------------------------
  4170  # at 59578
  4171  #190419  0:41:48 server id 1  end_log_pos 59609 CRC32 0x36cda2b7        Xid = 6380
  4172  COMMIT/*!*/;
  4173  # at 59609
  4174  #190419  0:41:48 server id 1  end_log_pos 59674 CRC32 0x8de2f06a        Anonymous_GTID  last_committed=145      sequence_number=146
  4175  SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
  4176  # at 59674
  4177  #190419  0:41:48 server id 1  end_log_pos 59787 CRC32 0x6b2edd2b        Query   thread_id=14    exec_time=0     error_code=0
  4178  use `XD`/*!*/;
  4179  SET TIMESTAMP=1555605708/*!*/;
  4180  DROP TABLE `user` /* generated by server */
# ----------------------------------------

# 把备份的数据表user恢复到数据库中
mysql -uroot -p XD < /mysql_data_back/user_bak.sql
# 利用上面找到的删除的位置进行恢复数据
mysqlbinlog --no-defaults --set-charset=utf8  --stop-position="59674" /data/mydata/log_bin/mysql-bin.000002 | mysql -uroot -p 

你可能感兴趣的:(SQL数据库)