Navicat链接数据库出现的错误和MySQL学习笔记

在Navicat Premium 15中链接数据库的时候,可能会出现以下错误:

出现此错误的缘由是由于没有开启数据库服务

解决步骤:

1、桌面计算机图标右键打开管理,而后点击服务和应用程序,而后点击服务。java

2、找到mysq对于的安装版本,而后右键点击启动便可。node

3、而后去从新链接就行了。mysql

 

MySQL数据库学习笔记linux

第一章 数据库概述

1.一、数据库的好处

  1. 将数据持久化到本地程序员

  2. 提供结构化查询功能sql

1.二、数据库的常见概念

  1. DB:数据库,存储数据的仓库数据库

  2. DBMS:数据库管理系统,又称为数据库软件或者数据库产品,用于建立和管理数据库,常见的有MySQL、Oracle、SQL Servercentos

  3. DBS:数据库系统,数据库系统是一个通称,包括数据库、数据库管理系统、数据库管理人员等,是最大的范畴数组

  4. SQL:结构化查询语言,用于和数据库通讯的语言,不是某个数据库软件特有的,而是几乎全部的主流数据库软件通用的语言安全

1.三、数据库的存储特色

  1. 数据存放到表中,而后表再放到库中

  2. 一个库中能够有多张表,每张表具备惟一的表名用来标识本身

  3. 表中有一个或多个列,列又称为“字段”,至关于Java中“属性”

  4. 表中的每一行数据,至关于Java中“对象”

1.四、数据库的常见分类

  1. 关系型数据库:MySQL、Oracle、DB二、SQL Server

  2. 非关系型数据库:

    • 键值存储数据库:Redis、Memcached、MemcacheDB

    • 列存储数据库:HBase、Cassandra

    • 面向文档的数据库:MongDB、CouchDB

    • 图形数据库:Neo4J

1.五、SQL语言的分类

  1. DQL:数据查询语言:select、from、where

  2. DML:数据操做语言:insert、update、delete

  3. DDL:数据定义语言:create、alter、drop、truncate

  4. DCL:数据控制语言:grant、revoke

  5. TCL:事务控制语言:commit、rollback

第二章 MySQL概述

2.一、MySQL的背景

MySQL的前身是属于MySQL AB,08年被SUN公司收购,09年SUN公司又被Oracle公司收购

2.二、MySQL的优势

  1. 成本低、开源免费

  2. 性能高、移植性好

  3. 体积小、便于安装

2.三、MySQL的安装

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

2.四、MySQL的启动

net start MySQL

2.五、MySQL的中止

net stop MySQL

2.六、MySQL的登陆

mysql -h主机名 -P端口号 -u用户名 -p密码

2.七、MySQL的退出

exit

第三章 DQL语言

3.一、基础查询

1、语法

SELECT 查询列表8 FROM 表名;
mysql注释符有三种:
一、#...
二、"-- ",注意--后面有一个空格
三、/*...*/

2、特色

  1. 查询列表能够是字段、常量、函数、表达式

  2. 查询结果是一个虚拟表

3、示例

一、查询单个字段

SELECT 字段名 FROM 表名;

二、查询多个字段

SELECT 字段名,字段名 FROM 表名;

三、查询全部字段

SELECT * FROM 表名;

四、查询常量

SELECT 常量值;

注意:字符型和日期型的常量值必须用单引号引发来,数值型不须要

五、查询函数

SELECT 函数名(实参列表);

六、查询表达式

SELECT 100/25;

七、起别名

SELECT 字段名 AS "别名" FROM 表名;

注意:别名可使用单引号、双引号引发来,当只有一个单词时,能够省略引号,当有多个单词且有空格或特殊符号时,不能省略,AS能够省略

八、去重复

SELECT DISTINCT 字段名 FROM 表名;

九、作加法

一、 SELECT 数值+数值; 直接运算
二、 SELECT 字符+数值; 首先先将字符转换为整数,若是转换成功,则继续运算,若是转换失败,则默认为0,而后继续运算
三、 SELECT NULL+数值; NULL和任何数值参与运算结果都是NULL

十、【补充】ifnull函数

功能:判断某字段或表达式是否为null,若是为null,返回指定的值,不然返回本来的值

SELECT IFNULL(字段名, 指定值) FROM 表名;

十一、【补充】isnull函数

功能:判断某字段或表达式是否为null,若是是null,则返回1,不然返回0

SELECT ISNULL(字段名) FROM 表名;

3.二、条件查询

1、语法

SELECT 查询列表 FROM 表名 WHERE 筛选条件;

2、分类

  1. 条件(比较)运算符:>、>=、<、<=、=、<=>(彻底等于,能够判断空)、!=、<>(不等于)

  2. 逻辑运算符:and、or、not

  3. 模糊运算符:

    • like:%任意多个字符、_任意单个字符,若是有特殊字符,须要使用escape转义

    • between and

    • not between and

    • not 取反

    • in

    • not in

    • is null

    • is not null

3、演示

一、查询工资>12000的员工信息

SELECT 
  * 
FROM
  employees 
WHERE salary > 12000 ;

二、查询工资>=14000的员工信息

SELECT 
  * 
FROM
  employees 
WHERE salary >= 14000 ;

三、查询工资<12000的员工信息

SELECT 
  * 
FROM
  employees 
WHERE salary < 12000 ;

四、查询工资<=14000的员工信息

SELECT 
  * 
FROM
  employees 
WHERE salary <= 14000 ;

五、查询员工编号=100的员工信息

SELECT 
  * 
FROM
  employees 
WHERE employee_id = 100 ;  //注意sql的等于和Java的等于不一样

六、查询员工编号<=>100的员工信息

SELECT 
  * 
FROM
  employees 
WHERE employee_id <=> 100 ;

注意:=只能判断普通类型的数值,而<=>不只能够判断普通类型的数值还能够判断NULL

七、查询员工编号!=100的员工信息

SELECT 
  * 
FROM
  employees 
WHERE employee_id != 100 ;

八、查询员工编号<>100的员工信息

SELECT 
  * 
FROM
  employees 
WHERE employee_id <> 100 ;

注意:!=和<>都是判断不等于的意思,可是MySQL推荐使用<>

九、查询工资>12000&&工资<18000的员工信息

SELECT 
  * 
FROM
  employees 
WHERE salary > 12000 AND salary < 18000 ;
-- 或者 WHERE salary NOT BETWEEN 12000 AND 18000 ;

十、查询工资<=12000||工资>=18000的员工信息

SELECT 
  * 
FROM
  employees 
WHERE salary <= 12000 OR salary >= 18000 ;

十一、查询工资<=12000||工资>=18000的员工信息

SELECT 
  * 
FROM
  employees 
WHERE NOT (salary > 12000 AND salary < 18000) ;

十二、查询员工名中第一个字符为B、第四个字符为d的员工信息

SELECT 
  *
FROM
  employees 
WHERE last_name LIKE 'B__d%' ;  -- 两个下划线

1三、查询员工编号在100到120之间的员工信息

SELECT 
  * 
FROM
  employees 
WHERE employee_id BETWEEN 100 AND 120 ;

1四、查询员工编号不在100到120之间的员工信息

SELECT 
  * 
FROM
  employees 
WHERE employee_id NOT BETWEEN 100 AND 120 ;

1五、查询员工的工种编号是 IT_PROG、AD_VP、AD_PRES中的一个员工名和工种编号

SELECT 
  last_name,
  job_id 
FROM
  employees 
WHERE job_id IN ('IT_PROT', 'AD_VP', 'AD_PRES') ;

注意:in列表的值类型必须和字段的类型一致或兼容,in列表中不支持通配符%和_

1六、查询没有奖金的员工名和奖金率

SELECT 
  last_name,
  commission_pct 
FROM
  employees 
WHERE commission_pct IS NULL ;

1七、查询有奖金的员工名和奖金率

SELECT 
  last_name,
  commission_pct 
FROM
  employees 
WHERE commission_pct IS NOT NULL ;

注意:=、!=不能用来判断NULL、而<=>、<>、is null 、 is not null能够用来判断NULL,但注意<=>也能够判断普通类型的数值

3.三、排序查询

1、语法

SELECT 
  查询列表 
FROM
  表 
【WHERE 筛选条件】
ORDER BY 排序列表 【asc | desc】 ;

2、注意

  1. 排序列表能够是单个字段、多个字段、别名、函数、表达式

  2. asc表明升序,desc表明降序,若是不写,默认是asc

  3. order by的位置通常放在查询语句的最后(除limit语句以外)

3、示例

一、按单个字段排序:查询员工信息,要求按工资降序

SELECT 
  * 
FROM
  employees 
ORDER BY salary DESC ;

二、按多个字段查询:查询员工信息,要求先按工资降序,再按员工编号升序

SELECT 
  * 
FROM
  employees 
ORDER BY salary DESC, employee_id ASC ;

三、按别名排序查询:查询员工信息,要求按员工年薪升序

SELECT 
  *,
  salary * 12 * (1 + IFNULL(commission_pct, 0)) 年薪 
FROM
  employees 
ORDER BY 年薪 ASC ;

四、按函数排序查询:查询员工信息,要求按员工名字的长度降序

SELECT 
  LENGTH(last_name),
  last_name 
FROM
  employees 
ORDER BY LENGTH(last_name) DESC ;

五、按表达式排序:查询员工信息,要求按员工年薪升序

SELECT 
  *,
  salary * 12 * (1+ IFNULL(commission_pct, 0)) 
FROM
  employees 
ORDER BY salary * 12 * (1+ IFNULL(commission_pct, 0)) ASC ;

3.四、单行函数

1、语法

SELECT 函数名(实参列表) 【FROM 表】;

2、分类

  1. 字符函数

    • concat:链接字符

    • substr:截取子串

    • replace:替换字符

    • upper:变大写

    • lower:变小写

    • lpad:左填充

    • rpad:右填充

    • length:获取字节长度

    • trim:去除先后空格

    • instr:获取子串第一次出现的索引

    注意MySQL中的索引是从1开始的
  2. 数学函数

    • round:四舍五入,原理:加0.5向下取整

    • ceil:向上取整

    • floor:向下取整

    • mod:取模运算(a-a/b*b)

    • truncate:保留小数的位数,不进行四舍五入

    • rand:获取随机数,返回0-1之间的小数,(b-a+1)+a

  3. 日期函数

    • now:返回当前日期+时间

    • curdate:返回当前日期

    • curtime:返回当前时间

    • year:返回年

    • month:返回月

    • day:返回日

    • hour:小时

    • minute:分钟

    • second:秒

    • monthname:以英文形式返回月

    • datediff(a,b):返回两个日期相差的天数

    • date_format:将日期转换成字符

    • str_to_date:将字符转换成日期

    格式符:
    %Y:四位的年份
    %y:二位的年份
    %m:二位的月份(01,02,...,12)
    %c:一位的月份(1,2,...,12)
    %d:日(01,02,...,31)
    %H:小时(24小时制)
    %h:小时(12小时制)
    %i:分钟(00,01,02,...,59)
    %s:秒(00,01,02,...,59)    
  4. 控制函数

    • if:判断函数

    • case:分支函数

    一、IF(条件表达式,表达式1,表达式2):若是条件表达式成立,返回表达式1,不然返回表达式2
    ​
    二、case的格式一:
        CASE 变量或字段或表达式 
          WHEN 常量1 THEN 值1 
          WHEN 常量2 THEN 值2
          ...
          ELSE 值n 
        END ;
        
    三、case的格式二:
        CASE
          WHEN 条件1 THEN 值1 
          WHEN 条件2 THEN 值2
          ...
          ELSE 值n 
        END
  5. 其它函数

    • version:当前数据库的版本

    • database:当前打开的数据库

    • user:当前登陆的用户

    • password(‘字符’):返回该字符的密码形式

    • md5(‘字符’):返回该字符的md5加密形式

3、演示

一、concat

SELECT CONCAT('Hello',' ','World') AS out_put;

二、substr

#截取从指定索引处后面全部字符
SELECT SUBSTR('李莫愁爱上了陆展元',7)  AS out_put;
​
#截取从指定索引处指定字符长度的字符
SELECT SUBSTR('李莫愁爱上了陆展元',1,3) AS out_put;

三、replace

SELECT REPLACE('张无忌爱上了周芷若','周芷若','赵敏') AS out_put;

四、upper

SELECT UPPER('john') AS out_put;

五、lower

SELECT LOWER('john') AS out_put;

六、lpad

SELECT LPAD('殷素素',10,'*') AS out_put;
-- 当遇到"LPAD' 不是能够识别的 内置函数名称。"  
-- 在函数名前加上dbo.就能够了   'databaseobject'函數的全部者

七、rpad

SELECT RPAD('殷素素',10,'*') AS out_put;

八、length

SELECT LENGTH('john') AS out_put;

九、trim

#删除指定字符的左右空格
SELECT LENGTH(TRIM('    张翠山    ')) AS out_put;
​
#删除指定字符的指定字符
SELECT TRIM('aaa' FROM 'aaaaaaaaa张翠山aaaaaaaaa')  AS out_put;

十、instr

SELECT INSTR('杨不悔爱上了殷六侠','殷六侠') AS out_put;

注意:返回子串第一次出现的索引,若是找不到返回0

十一、round

#默认四舍五入
-- 默认0位小数
SELECT ROUND(-1.55) AS out_put;
​
#指定小数位数
SELECT ROUND(1.567,2) AS out_put;

注意:四舍五入和符号无关

十二、ceil

SELECT CEIL(-1.02) AS out_put;

注意:向上取整,返回>=该参数的最小整数

1三、floor

SELECT FLOOR(-9.99) AS out_put;

注意:向下取整,返回<=该参数的最大整数

1四、mod

SELECT MOD(10,3) AS out_put;

1五、truncate

SELECT TRUNCATE(1.69999,1) AS out_put;

1六、rand

SELECT RAND() AS out_put;

1七、now

SELECT NOW() AS out_put;

1八、curdate

SELECT CURDATE() AS out_put;

1九、curtime

SELECT CURTIME() AS out_put;

20、year

SELECT YEAR(NOW()) 年;

2一、month

SELECT MONTH(NOW()) 月;

2二、day

SELECT DAY(NOW()) 日;

2三、hour

SELECT HOUR(NOW()) 时;

2四、minute

SELECT MINUTE(NOW()) 分;

2五、second

SELECT SECOND(NOW()) 秒;

2六、monthname

SELECT MONTHNAME(NOW()) 月名;

2七、datediff

SELECT DATEDIFF('1995-2-7','1995-2-6') AS out_put;

2八、date_format

SELECT DATE_FORMAT(NOW(),'%Y年%m月%d日') AS out_put;

2九、str_to_date

SELECT STR_TO_DATE('1998-3-2','%Y-%c-%d') AS out_put;

30、if

SELECT IF(10 < 5, '大', '小') AS out_put;

3一、case的格式一

/*
案例:查询员工的工资,要求
    部门号=30,显示的工资为1.1倍
    部门号=40,显示的工资为1.2倍
    部门号=50,显示的工资为1.3倍
    其它部门,显示的工资为原工资
*/
​
SELECT 
  salary 原始工资,
  department_id,
  CASE
    department_id 
    WHEN 30 THEN salary * 1.1 
    WHEN 40 THEN salary * 1.2 
    WHEN 50 THEN salary * 1.3 
    ELSE salary 
  END AS 新工资 
FROM
  employees ;

3二、case的格式二

/*
案例:查询员工的工资状况
    若是工资>20000,显示A级别
    若是工资>15000,显示B级别
    若是工资>10000,显示C级别
    不然,显示D级别
*/
​
SELECT 
  salary,
  CASE
    WHEN salary > 20000 THEN 'A' 
    WHEN salary > 15000 THEN 'B' 
    WHEN salary > 10000 THEN 'C' 
    ELSE 'D' 
  END AS 工资级别 
FROM
  employees ;

3三、version

SELECT VERSION();

3四、database

SELECT DATABASE();

3五、user

SELECT USER();

3六、password(‘字符’)

SELECT PASSWORD('123456');

3七、md5(‘字符’)

SELECT MD5('123456');

3.五、分组函数

1、语法

SELECT 函数名(实参列表) 【FROM 表】;

2、分类

  1. sum:求和

  2. avg:平均值

  3. max:最大值

  4. min:最小值

  5. count:计算个数

一、sum、avg通常用于处理数值型,max、min、count能够处理任何类型
​
二、以上分组函数都忽略null值
​
三、能够和distinct搭配实现去重的运算:select sum(distinct 字段) from 表;
​
四、通常使用count(*)用做统计行数
​
五、和分组函数一同查询的字段要求是group by后的字段

3、演示

一、sum

SELECT SUM(salary) FROM employees;

二、avg

SELECT AVG(salary) FROM employees;

三、max

SELECT MAX(salary) FROM employees;

四、min

SELECT MIN(salary) FROM employees;

五、count

SELECT COUNT(salary) FROM employees;

3.六、分组查询

1、语法

SELECT 
  查询列表 
FROM
  表 
【where 筛选条件】 
GROUP BY 分组的字段 
【having 分组后的筛选】
【order BY 排序的字段】 ;
​

2、特色

一、和分组函数一同查询的字段必须是group by后出现的字段
​
二、筛选分为两类:分组前筛选和分组后筛选
                针对的表                 语句位置              链接的关键字
    分组前筛选    分组前的原始表            group by前           where
    分组后筛选    分组后的结果集            group by后           having
    
三、分组能够按单个字段也能够按多个字段
​
四、分组能够搭配着排序使用

3、演示

一、查询每一个工种的员工平均工资

SELECT 
  AVG(salary),
  job_id 
FROM
  employees 
GROUP BY job_id ;

二、查询每一个位置的员工部门个数

SELECT 
  COUNT(*),
  location_id 
FROM
  departments 
GROUP BY location_id ;

三、查询有奖金的每一个领导手下员工的平均工资

SELECT 
  AVG(salary),
  manager_id 
FROM
  employees 
WHERE commission_pct IS NOT NULL 
GROUP BY manager_id ;

四、查询哪一个部门的员工个数>5

SELECT 
  COUNT(*),
  department_id 
FROM
  employees 
GROUP BY department_id 
HAVING COUNT(*) > 5 ;

五、查询每一个工种有奖金的员工的最高工资>6000的最高工资和公众编号,按最高工资升序

SELECT 
  MAX(salary) m,
  job_id
FROM
  employees 
WHERE commission_pct IS NOT NULL 
GROUP BY job_id 
HAVING m > 6000 
ORDER BY m ;

六、查询每一个工种每一个部门的最低工资并按最低工资降序

SELECT 
  MIN(salary),
  job_id,
  department_id 
FROM
  employees 
GROUP BY job_id, department_id
ORDER BY MIN(salary) DESC ;

3.七、链接查询

1、含义

链接查询又称多表查询,当查询的字段来自于多个表时,就会用到链接查询

2、注意

笛卡尔乘积现象:表1 有m行,表2有n行,结果=m*n行
​
发生缘由:没有有效的链接条件
如何避免:添加有效的链接条件

3、分类

  1. 按年代分类

    sql92和sql99比较

    1.功能方面:sql99支持的较多 2.可读性:sql99实现了链接条件和筛选条件的分离,所以可读性较高

    • sql92标准:支持内链接

    • sql99标准:支持内链接、部分外链接(左外、右外)、交叉链接

  2. 按功能分类

    • 内链接

      • 等值链接

      • 非等值链接

      • 自链接

    • 外链接

      • 左外链接

      • 右外链接

      • 全外链接

    • 交叉链接

4、sql92标准演示

一、sql92标准:等值链接

#查询员工名和对应的部门名
​
SELECT 
  last_name,
  department_name 
FROM
  employees,
  departments 
WHERE employees.`department_id` = departments.`department_id` ;

二、sql92标准:非等值链接

#查询员工的工资和工资级别
​
SELECT 
  salary,
  grade_level 
FROM
  employees e,
  job_grades g 
WHERE salary BETWEEN g.`lowest_sal` AND g.`highest_sal` ;

三、sql92标准:自链接

#查询员工名和它对应上级的名称
​
SELECT 
  e.employee_id,
  e.last_name,
  m.employee_id,
  m.last_name 
FROM
  employees e,
  employees m 
WHERE e.`manager_id` = m.`employee_id` ;

3.八、sql99标准

1、语法

SELECT 
  查询列表 
FROM 表1 别名1 
【链接类型】 JOIN 表2 别名2 ON 链接条件 
【where 分组前筛选条件】
【group BY 分组列表】
【having 分组后筛选条件】
【order BY 排序列表】 ;

2、链接类型

  1. 内链接:inner

  2. 外链接

    • 左外链接:left 【outer】(左边的是主表)

    • 右外链接:right 【outer】(右边的是主表)

    • 全外链接:full 【outer】(两边都是主表,可是MySQL不支持全外链接、Oracle支持)

  3. 交叉链接:cross(交叉链接实际上是用sql99语法实现笛卡尔乘积)

3、演示

一、内链接:等值链接

#查询员工名和对应的部门名
​
SELECT 
  last_name,
  department_name 
FROM
  departments d 
INNER JOIN employees e ON e.`department_id` = d.`department_id` ;

二、内链接:非等值链接

#查询员工的工资和工资级别
​
SELECT 
  salary,
  grade_level 
FROM
  employees e 
INNER JOIN job_grades g ON e.`salary` BETWEEN g.`lowest_sal` AND g.`highest_sal` ;

三、内链接:自链接

#查询员工名和它对应上级的名称
​
SELECT 
  e.last_name,
  m.last_name 
FROM
  employees e 
INNER JOIN employees m ON e.`manager_id` = m.`employee_id` ;

四、外链接:左外链接

#查询哪一个部门没有员工
​
SELECT 
  d.`department_name`
FROM
  departments d 
LEFT OUTER JOIN employees e ON d.`department_id` = e.`department_id` 
WHERE e.`employee_id` IS NULL ;

五、外链接:右外链接

#查询哪一个部门没有员工
​
SELECT 
  d.`department_name`
FROM
  employees e 
RIGHT OUTER JOIN departments d ON d.`department_id` = e.`department_id` 
WHERE e.`employee_id` IS NULL ;

六、交叉链接

#使用交叉链接进行笛卡尔乘积查询
​
SELECT 
  b.*,
  bo.* 
FROM beauty b 
CROSS JOIN boys bo ;

3.九、子查询

1、含义

嵌套在其它语句内部的select语句称为子查询或内查询,外面的语句能够是insert、delete、update、select等,通常select做为外面语句较多,外面若是为select语句,则此语句称为外查询或主查询。

2、分类

  1. 按出现的位置划分

    • select后面:标量子查询

    • from后面:表子查询

    • where或having后面

      • 标量子查询

      • 列子查询

      • 行子查询

    • exists后面

      • 标量子查询

      • 列子查询

      • 行子查询

      • 表子查询

  2. 按结果集行列数划分

    • 标量子查询(单行子查询):结果集为一行一列

    • 列子查询(多行子查询):结果集为多行一列

    • 行子查询:结果集为多行多列

    • 表子查询:结果集为多行多列

3、特色

  1. 子查询放在小括号内

  2. 子查询通常放在条件的右侧

  3. 子查询的执行优先于主查询执行,主查询的条件用到了子查询的结果

  4. 标量子查询,通常搭配着单行操做符使用:>、>=、<、<=、!=、<>、=、<=>

  5. 列子查询,通常搭配着多行操做符使用:in、not in、any、some、all、exits

4、演示

一、select后面

#查询每一个部门的员工个数
​
SELECT 
  d.*, (
  SELECT 
    COUNT(*) 
  FROM
    employees e 
  WHERE e.department_id = d.`department_id`
) 个数 
FROM
  departments d ;

二、from后面

#查询每一个部门平均工资的工资等级
​
SELECT 
  ag_dep.*,
  g.`grade_level` 
FROM (
  SELECT 
    AVG(salary) ag,
    department_id 
  FROM
    employees 
  GROUP BY department_id
) ag_dep 
INNER JOIN job_grades g ON ag_dep.ag BETWEEN lowest_sal AND highest_sal ;

三、where或having后面

标量子查询:查询最低工资的员工姓名和工资

SELECT 
  last_name,
  salary 
FROM
  employees 
WHERE salary = (
    SELECT MIN(salary) FROM employees
) ;

列子查询:

#查询全部是领导的员工姓名
​
SELECT 
  last_name 
FROM
  employees 
WHERE employee_id IN (
    SELECT DISTINCT manager_id FROM employees
) ;
#返回其它工种中比job_id为‘IT_PROG’工种任一工资低的员工的员工号、姓名、job_id以及salary
​
SELECT 
  employee_id,
  last_name,
  job_id,
  salary 
FROM
  employees 
WHERE salary < ANY (
  SELECT DISTINCT salary FROM employees WHERE job_id = 'IT_PROG'
) AND job_id <> 'IT_PROG' ;
#返回其它部门中比job_id为‘IT_PROG’部门全部工资都低的员工的员工号、姓名、job_id以及salary
​
SELECT 
  employee_id,
  last_name,
  job_id,
  salary 
FROM
  employees 
WHERE salary < ALL (
  SELECT DISTINCT salary FROM employees WHERE job_id = 'IT_PROG'
) AND job_id <> 'IT_PROG' ;

行子查询:查询员工编号最小而且工资最高的员工信息

SELECT 
  * 
FROM
  employees 
WHERE (employee_id, salary) = (
    SELECT MIN(employee_id), MAX(salary) FROM employees
) ;

四、exists后面

#查询有员工的部门名
​
SELECT 
  department_name 
FROM
  departments d 
WHERE EXISTS (
    SELECT * FROM employees e
    WHERE e.`department_id` = d.`department_id`
) ;

3.十、分页查询

1、语法

SELECT 
  查询列表 
FROM
  表1 别名1
【链接类型】 JOIN 表2 别名2 ON 链接条件 
【WHERE 分组前的筛选】
【GROUP BY 分组字段】 
【HAVING 分组后的筛选 】
【ORDER BY 排序字段 ASC|DESC】
LIMIT 【offset, 】size ;

2、特色

  1. limit语句放在查询语句的最后

  2. offset表明起始索引,起始索引从0开始,size表明条目个数

  3. 分页语句:select 查询列表 from 表 limit (page-1)*size,size;

3、演示

#查询前五条员工信息
​
SELECT * FROM  employees LIMIT 0,5;   -- 打印前五行

3.十一、联合查询

1、语法

查询语句1
union 【all】
查询语句2
union 【all】
...

2、特色

  1. 要查询的结果来自于多个表且多个表没有直接的链接关系,但查询的信息一致时,可使用联合查询

  2. 要求多条查询语句的查询列数是一致的

  3. 要求多条查询语句的查询的每一列的类型和顺序最好一致

  4. union关键字默认去重,若是使用union all能够包含重复项

3、演示

#查询中国用户中男性的信息以及外国用户中年男性的用户信息

SELECT id,cname FROM t_ca WHERE csex='男'
UNION ALL
SELECT t_id,tname FROM t_ua WHERE tGender='male';

第四章 DML语言

4.一、插入语句

1、语法

#方式一:
INSERT INTO 表名(字段名,...) VALUES(值,...);

#方式二:
INSERT INTO 表名 SET 字段名=值,字段名=值,...;

2、特色

  1. 要求值的类型和字段的类型要一致或兼容

  2. 字段的个数和顺序不必定与原始表中的字段个数和顺序一致,但必须保证值和字段一一对应

  3. 假如表中有能够为null的字段,注意能够经过如下两种方式插入null值:①字段和值都省略、②字段写上,值使用null

  4. 字段和值的个数必须一致

  5. 字段名能够省略,默认全部列

  6. 方式一支持一次插入多行,语法以下:INSERT INTO 表名【(字段名,…)】 VALUES(值,…),(值,…),…;

  7. 方式一支持子查询,语法以下:INSERT INTO 表名 查询语句;

3、演示

一、方式一:插入数据

INSERT INTO beauty(id,name,sex,borndate,phone,photo,boyfriend_id) 
			VALUES(15,'唐艺昕','女','1997-12-05','15633029014',NULL,2);

二、方式二:插入数据

INSERT INTO beauty SET 
    id = 19,name = '张倩倩',
    sex = '女',
    borndate = '1997-12-05',
    phone = '15633029014',
    photo = NULL,
    boyfriend_id = 3 ;

4.二、修改语句

1、语法

一、单表更新
UPDATE 表名 SET 列 = 值,... WHERE 查询条件;

二、多表更新
#sql92语法: 
UPDATE 
  表1 别名,
  表2 别名 
SET
  列 = 值,
  ...
WHERE 链接条件 AND 筛选条件 ;

#sql99语法: 
UPDATE 
  表1 别名 
INNER | LEFT | RIGHT JOIN 表2 别名 ON 链接条件
  SET 列 = 值,
  ...
WHERE 筛选条件 ;

2、演示

一、单表更新

#修改beauty表中姓唐的女神的电话为13899888899

UPDATE beauty SET phone = '13899888899' WHERE NAME LIKE '唐%';

二、多表更新

#修改张无忌的女友的手机号为13899888899,魅力值为1000
sql92语法:
UPDATE 
  boys bo,
  beauty b 
  SET b.`phone` = '13899888899',
      bo.`userCP` = 1000 
WHERE bo.`id` = b.`boyfriend_id` AND bo.`boyName` = '张无忌' ;

#修改张无忌的女友的手机号为13899888899,魅力值为1000
sql99语法:
UPDATE 
  boys bo 
INNER JOIN beauty b ON bo.`id` = b.`boyfriend_id`
  SET b.`phone` = '13899888899',
      bo.`userCP` = 1000 
WHERE bo.`boyName` = '张无忌' ;

4.三、删除语句

1、语法

一、单表删除 
DELETE FROM 表名 【WHERE 筛选条件 】;

二、多表删除(级联删除)
sql92语法: 
DELETE 
  表1的别名,
  表2的别名 
FROM
  表1 别名,
  表2 别名 
WHERE 链接条件 AND 筛选条件 ;

sql99语法: 
DELETE 
  表1的别名,
  表2的别名 
FROM
  表1 别名 
INNER | LEFT | RIGHT JOIN 表2 别名 ON 链接条件 
WHERE 筛选条件 ;

2、演示

一、单表删除

#删除手机号以9结尾的女神信息

DELETE FROM beauty WHERE phone LIKE '%9';

二、多表删除

#删除黄晓明的信息以及他女友的信息
#sql92语法:
DELETE
  b,
  bo
FROM
  beauty b,
  boys bo
WHERE b.`boyfriend_id` = bo.`id` AND bo.`boyName` = '黄晓明' ; 

#删除黄晓明的信息以及他女友的信息
#sql99语法:
DELETE 
  b,
  bo 
FROM
  beauty b 
INNER JOIN boys bo ON b.`boyfriend_id` = bo.`id` 
WHERE bo.`boyName` = '黄晓明' ;

第五章 DDL语言

5.一、库的管理

5.1.一、库的建立

CREATE DATABASE 【IF NOT EXISTS】 库名 【 CHARACTER SET 字符集名】;

5.1.二、库的修改

#它已经被废弃
RENAME DATABASE 旧库名 TO 新库名;

#修改库字符集
ALTER DATABASE 库名 CHARACTER SET 字符集名;

5.1.三、库的删除

DROP DATABASE 【IF EXISTS】 库名;

5.二、表的管理

5.2.一、表的建立

CREATE TABLE 【IF NOT EXISTS】 表名 (
  字段名 字段类型 【约束】,
  字段名 字段类型 【约束】,
  ...
  字段名 字段类型 【约束】
) ;

5.2.二、表的修改

一、添加列
ALTER TABLE 表名 ADD COLUMN 列名 类型 【FIRST|AFTER 字段名】;

二、修改列的类型或约束
ALTER TABLE 表名 MODIFY COLUMN 列名 新类型 【新约束】;

三、修改列名
ALTER TABLE 表名 CHANGE COLUMN 旧列名 新列名 类型;

四、删除列
ALTER TABLE 表名 DROP COLUMN 列名;

五、修改表名
ALTER TABLE 表名 RENAME 【TO】 新表名;

5.2.三、表的删除

方式一:DROP TABLE 【IF EXISTS】 表名;

方式二:TRUNCATE TABLE 【IF EXISTS】 表名;

mysql之drop、truncate和delete的区别

delete
delete是DML(data maintain language),这个操做会被放到rollback segment中,事务提交以后才会生效,若是有相应的触发器trigger,那么执行的时候能够被触发
执行delete操做时,每次从表中删除一行,而且同时将该行的的删除操做记录在redo和undo表空间中以便进行回滚(rollback)和重作操做,但要注意表空间要足够大,须要手动提交(commit)操做才能生效,能够经过rollback撤消操做。
delete可根据条件删除表中知足条件的数据,若是不指定where子句,那么删除表中全部记录。
delete语句不影响表所占用的extent(就是表结构的中的区),高水线(high watermark)保持原位置不变。 (高水位线就存在于段(segment)中,它用于标识段中已使用过的数据块与未使用的数据块两者间交界,扫描表数据的时候,高水位线如下的全部数据块都必须被扫描。)
truncate
truncate是DDL(data define language)即操做会当即生效,原数据不会放到rollback segment中,不能回滚,也不会触发触发器

truncate会删除表中全部记录,而且将从新设置高水线和全部的索引,缺省状况下将空间释放到minextents的extent(就是表结构中的段内的区域),除非使用reuse storage(使用这句话,所在的extent空间不会被回收,只是将数据删除掉,数据删除以后的freespace空间,只能供本表使用,其余的不可使用)。不会记录日志,因此执行速度很快,但不能经过rollback撤消操做(若是一不当心把一个表truncate掉,也是能够恢复的,只是不能经过rollback来恢复)。

对于外键(foreign key )约束引用的表,不能使用 truncate table(会报错(Cannot truncate a table referenced in a foreign key constraint )),也不能使用drop table(会报错(Cannot delete or update a parent row: a foreign key constraint fails)),而应使用不带 where 子句的 delete 语句。

truncate table不能用于参与了索引视图的表。

drop
drop是DDL,会隐式提交,因此,不能回滚,不会触发触发器。
drop语句删除表结构及全部数据,并将表所占用的空间所有释放。
drop语句将删除表的结构所依赖的约束,触发器,索引,依赖于该表的存储过程/函数将保留,可是变为invalid状态。
总结
在速度上,通常来讲,drop> truncate > delete。
在使用drop和truncate时必定要注意,虽然能够恢复,但为了减小麻烦,仍是要慎重。
若是想删除部分数据用delete,注意带上where子句,回滚段要足够大;若是想删除表,固然用drop;
若是想保留表而将全部数据删除,若是和事务无关(不能回滚),用truncate便可;
若是和事务有关,或者想触发trigger,仍是用delete;
若是是整理表内部的碎片,能够用truncate跟上reuse stroage,再从新导入/插入数据。

5.2.四、表的复制

一、复制表的结构
CREATE TABLE 表名 LIKE 旧表;

二、复制表的某些字段
CREATE TABLE 表名 
SELECT 字段1,字段2,... FROM 旧表 WHERE 0;

三、复制表的结构+数据
CREATE TABLE 表名 
SELECT 查询列表 FROM 旧表 【WHERE 筛选条件】;

四、复制表的某些字段+数据
CREATE TABLE 表名 
SELECT 字段1,字段2,... FROM 旧表 【WHERE 筛选条件】;

5.三、数据类型

5.3.一、数值型

1、类型

类型 TINYINT SMALLINT MEDIUMINT INT/INTEGER BIGINT
字节 1 2 3 4 8

2、特色

  1. 均可以设置无符号和有符号,默认有符号,经过unsigned设置无符号

  2. 若是超出了范围,会报out or range异常,插入临界值(该类型的最大值或最小值即为临界值)

  3. 长度能够不指定,默认会有一个长度,长度表明显示的最大宽度,若是不够则左边用0填充,但须要搭配zerofill,而且默认变为无符号整型

  4. 若是对数据没有特殊要求,则优先考虑使用INT/INTEGER

5.3.二、浮点型

1、类型

  1. 定点数

    • DEC(M,D) :M+2字节

    • DECIMAL(M,D):M+2字节

  2. 浮点数

    • FLOAT(M,D) :4字节

    • DOUBLE(M,D):8字节

2、特色

  1. M表明整数部位+小数部位的个数,D表明小数部位

  2. 若是超出范围,则报out or range异常,而且插入临界值(该类型的最大值或最小值即为临界值)

  3. M和D均可以省略,但对于定点数,M默认为10,D默认为0

  4. 若是精度要求较高,则优先考虑使用定点数

  5. MySQL 分为两种方式:浮点数和定点数。浮点数包括 float(单精度)和 double(双精度),而定点数则只有 decimal 一种表示。 定点数在 MySQL 内部以字符串形式存放,比浮点数更精确,适合用来表示货币等精度高的数据。

    浮点数和定点数均可以用类型名称后加“(M,D)”的方式来进行表示,“(M,D)”表示该值一共显示 M 位数字(整数位+小数位),其中 D 位位于小数点后面,M 和 D 又称为精度和标度。 例如,定义为 float(7,4)的一个列能够显示为-999.9999。 MySQL 保存值时进行四舍五入,所以若是在 float(7,4)列内插入 999.00009,近似结果是 999.0001。 值得注意的是,浮点数后面跟“(M,D)”的用法是非标准用法,若是要用于数据库的迁移,则最好不要这么使用。 float 和 double 在不指定精度时,默认会按照实际的精度(由实际的硬件和操做系统决定)来显示, 而 decimal 在不指定精度时,默认的整数位为 10,默认的小数位为 0。

5.3.三、字符型

1、类型

类型 CHAR VARCHAR BINARY VARBINARY ENUM SET TEXT BLOB
描述 固定长度字符 可变长度字符 二进制字符串 二进制字符串 枚举 集合 文本 二进制大型对象

2、特色

  1. char:固定长度的字符,写法为char(M),最大长度不能超过M,其中M能够省略,默认为1

  2. varchar:可变长度的字符,写法为varchar(M),最大长度不能超过M,其中M不能够省略

  3. 若是对数据没有特殊要求,则优先考虑使用VARCHAR

5.3.四、日期型

1、类型

类型 YEAR DATE TIME DATETIME TIMESTAMP
描述 年份 日期 时间 日期+时间 日期+时间

2、特色

  1. TIMESTAMP比较容易受时区、语法模式、版本的影响,更能反映当前时区的真实时间,而DATETIME则只能反映出插入时的当地时区

  2. TIMESTAMP支持的时间范围较小,DATETIME的取值范围:1000-1-1 — 9999-12-31

  3. TIMESTAMP的属性受Mysql版本和SQLMode的影响很大

  4. 若是对数据没有特殊要求,则优先考虑使用DATETIME

5.四、常见约束

1、含义

约束是一种限制,用于限制表中的数据,为了保证表中的数据的准确和可靠性

2、分类

  1. NOT NULL:非空,该字段的值必填

  2. UNIQUE:惟一,该字段的值不可重复

  3. DEFAULT:默认,该字段的值不用手动插入有默认值

  4. CHECK:检查,MySQL不支持

  5. PRIMARY KEY:主键,该字段的值不可重复而且非空 unique+not null

  6. FOREIGN KEY:外键,该字段的值引用了另外的表的字段

3、特色

主键和惟一

#不一样点:
一、一个表至多有一个主键,但能够有多个惟一
二、主键不容许为空,惟一能够为空

#相同点:
一、都具备惟一性
二、都支持组合键,但不推荐

外键

一、用于限制两个表的关系,从表的字段值引用了主表的某字段值
二、外键列和主表的被引用列要求类型一致,意义同样,名称无要求
三、主表的被引用列要求是一个key(通常就是主键)
四、插入数据,先插入主表;删除数据,先删除从表


能够经过如下两种方式来删除主表的记录
#方式一:级联删除
ALTER TABLE stuinfo ADD CONSTRAINT fk_stu_major FOREIGN KEY(majorid) REFERENCES major(id) ON DELETE CASCADE;

#方式二:级联置空
ALTER TABLE stuinfo ADD CONSTRAINT fk_stu_major FOREIGN KEY(majorid) REFERENCES major(id) ON DELETE SET NULL;

4、演示

一、建立表时添加约束

CREATE TABLE 表名(
	字段名 字段类型 NOT NULL,#非空
    字段名 字段类型 DEFAULT 值,#默认
	字段名 字段类型 PRIMARY KEY,#主键
	字段名 字段类型 UNIQUE,#惟一
	CONSTRAINT 约束名 FOREIGN KEY(字段名) REFERENCES 主表(被引用列)
) ;

注意:

  1. 列级约束支持:非空、默认、主键、惟一,不能够起约束名

  2. 表级约束支持:主键、惟1、外键,能够起约束名,可是在MySQL中对主键无效

  3. 列级约束能够在一个字段上追加多个,中间用空格隔开,没有顺序要求

二、修改表时添加或删除约束

一、非空
添加非空(列级约束)
ALTER TABLE 表名 MODIFY COLUMN 字段名 字段类型 NOT NULL;
删除非空
ALTER TABLE 表名 MODIFY COLUMN 字段名 字段类型;

二、默认
添加默认(列级约束)
ALTER TABLE 表名 MODIFY COLUMN 字段名 字段类型 DEFAULT 值;
删除默认
ALTER TABLE 表名 MODIFY COLUMN 字段名 字段类型;

三、主键
添加主键(列级约束)
ALTER TABLE 表名 MODIFY COLUMN 字段名 字段类型 PRIMARY KEY;
添加主键(表级约束)
ALTER TABLE 表名 add 【CONSTRAINT 约束名】 PRIMARY KEY(字段名);
删除主键
ALTER TABLE 表名 DROP PRIMARY KEY;

四、惟一
添加惟一(列级约束)
ALTER TABLE 表名 MODIFY COLUMN 字段名 字段类型 UNIQUE;
添加惟一(表级约束)
ALTER TABLE 表名 add 【CONSTRAINT 约束名】 UNIQUE(字段名);
删除惟一
ALTER TABLE 表名 DROP INDEX 索引名;

五、外键
添加外键(表级约束)
ALTER TABLE 表名 add 【CONSTRAINT 约束名】 FOREIGN KEY(字段名) REFERENCES 主表(被引用列);
删除外键
ALTER TABLE 表名 DROP FOREIGN KEY 约束名;

5.五、自增加列

1、含义

自增加列又称为标识列,它能够不用手动的插入值,系统提供默认的序列值

2、特色

  1. 不用手动插入值,能够自动提供序列值,默认从1开始,步长为1,若是要更改起始值,第一次手动插入值,后续使用NULL,若是要更改步长,修改更改系统变量:SET auto_increment_increment = 值;

  2. 一个表至多有一个自增加列

  3. 自增加列只能支持数值型

  4. 自增加列必须为一个key

3、演示

一、建立表时添加自增加列

CREATE TABLE 表名 (
  字段名 字段类型 约束 AUTO_INCREMENT
) ;

二、修改表时添加或删除自增加列

添加自增加列
ALTER TABLE 表 MODIFY COLUMN 字段名 字段类型 约束 AUTO_INCREMENT;

删除自增加列
ALTER TABLE 表 MODIFY COLUMN 字段名 字段类型 约束;

第六章 DCL语言

关于受权的权限列表:

image-20200809204539412

6.一、建立用户

CREATE USER 用户名@'IP地址' IDENTIFIED BY '密码';
注意:'IP地址'能够设置为localhost(表明本机)或者'%'(表明容许全部IP地址登陆)

6.二、删除用户

DROP USER 用户名@'IP地址';
注意:'IP地址'能够设置为localhost(表明本机)或者'%'(表明容许全部IP地址登陆)

6.三、用户受权

GRANT 权限1,权限2,...... ON 数据库名.* TO 用户名@'IP地址' IDENTIFIED BY '密码';
注意:全部的数据库就用*.*,全部的权限就用all或者all privileges

6.四、撤销受权

REVOKE 权限1,权限2,...... ON 数据库名.* FROM 用户名@'IP地址' IDENTIFIED BY '密码';
注意:全部的数据库就用*.*,全部的权限就用all或者all privileges

6.五、刷新受权

FLUSH PRIVILEGES;

6.六、查看受权

SHOW GRANTS FOR 用户名@'IP地址';
注意:'IP地址'能够设置为localhost(表明本机)或者'%'(表明容许全部IP地址登陆)

6.七、修改密码

#修改密码
SET PASSWORD = PASSWORD('123456');
#登陆受权
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '123456';
#刷新受权
FLUSH PRIVILEGES;

6.八、忘记密码

一、能够在配置文件里加上 skip-grant-tables ,注意写到[mysqld]参数组下,表示跳过受权
二、重启MySQL再登陆就不须要密码,进去改密码,改完后,直接 FLUSH PRIVILEGES; 就可使用新密码来登陆了
(例:UPDATE mysql.user SET PASSWORD=PASSWORD("123456") WHERE USER="root" AND HOST="localhost";)
三、改完后记得去掉配置文件例的 skip-grant-tables,从新启动MySQL服务
四、再使用新的密码登陆就能够了

第七章 TCL语言

7.一、事务

1、含义

一条或多条sql语句组成一个执行单位,一组sql语句要么都执行要么都不执行

2、特色(ACID)

  1. 原子性:一个事务是不可再分割的总体,要么都执行要么都不执行

  2. 一致性:一个事务的执行不能破坏数据库数据的完整性和一致性

  3. 隔离性:一个事务不受其它事务的干扰,多个事务是互相隔离的

  4. 持久性:一个事务一旦提交了,则永久的持久化到本地

3、分类

  1. 隐式事务:没有明显的开启和结束,自己就是一条事务能够自动提交,好比insert、update、delete

  2. 显式事务:具备明显的开启和结束,例如如下格式:

一、开启事务
set autocommit=0;#关闭自动提交
start transaction;#开启事务机制

二、编写一组逻辑sql语句
注意:sql语句支持的是insert、update、delete

【设置回滚点,可选项】
savepoint 回滚点名;

三、结束事务
提交:commit;
回滚:rollback;
回滚到指定的地方: rollback to 回滚点名;

7.二、事务并发(读问题)

1、事物的并发问题如何发生?

并发:不是同时执行多个任务,知识执行一个任务的时间很短,看起来像同时执行同样;

并行:同时执行多个任务;

多个事务同时操做同一个数据库的相同数据时。

2、事务的并发问题都有哪些?

  1. 脏读:一个事务读到了另外一个事务还未提交的update数据,致使屡次查询的结果不同

  2. 不可重复读:一个事务读到了另外一个事务已经提交的update数据,致使屡次查询结果不一致

  3. 幻读:一个事务读到了另外一个事务已经提交的insert数据,致使屡次查询的结果不同

3、事物的并发问题如何解决?

经过设置隔离级别来解决并发问题

4、隔离级别

隔离级别 隔离描述 脏读 不可重复读 幻读
READ UNCOMMITTED 读未提交 × × ×
READ COMMITTED 读已提交 × ×
REPEATABLE READ 可重复读 ×
SERIALIZABLE 串行化

5、注意问题

  1. mysql 中默认第三个隔离级别 REPEATABLE READ
    oracle中默认第二个隔离级别 READ COMMITTED
  2. 查看隔离级别 SELECT @@tx_isolation;
    设置隔离级别 SET SESSION|GLOBAL TRANSACTION ISOLATION LEVEL 隔离级别;1

7.三、丢失更新(写问题)

1、定义

在事务的隔离级别内容中,可以了解到两个不一样的事务在并发的时候可能会发生数据的影响。细心的话能够发现事务隔离级别章节中,脏读、不可重复读、幻读三个问题都是由事务A对数据进行修改、增长,事务B老是在作读操做。若是两事务都在对数据进行修改则会致使另外的问题:丢失更新。

2、解决

  1. 悲观锁:认为两个事务更新操做必定会发生丢失更新

    • 解决:经过在语句后边添加for update来实现行级上锁,因此又称为“行级锁”,例如:select * from t_account t wheret.id=‘1’ for update;

  2. 乐观锁:认为事务不必定会产生丢失更新,让事务进行并发修改,不对事务进行锁定

    • 解决:由程序员本身解决,能够经过给数据表添加自增的version字段或时间戳timestamp,进行数据修改时,数据库会检测version字段或者时间戳是否与原来的一致,若不一致,抛出异常或者从新查询.

3、注意

对于帐户交易建议直接使用悲观锁,数据库的性能很高,并发度不是很高的场景二者性能没有太大差异。若是是交易减库存的操做能够考虑乐观锁,保证并发度。

第八章 高级部分

8.一、索引

1、含义

索引(index)是帮助MySQL高效获取数据的一种有序的数据结构

2、特色

  1. 优点:

    • 相似于书籍的目录索引,提升数据检索的效率,下降数据库的IO成本

    • 经过索引列对数据进行排序,下降数据排序的成本,下降CPU的消耗

  2. 劣势:

    • 实际上索引也是一张表,该表中保存了主键与索引字段,并指向实体类的记录,因此索引列也是要占用空间的

    • 虽然索引大大提升了查询效率,同时却也下降更新表的速度,如对表进行INSERT、UPDATE、DELETE。由于更新表时,MySQL 不只要保存数据,还要保存一下索引文件每次更新添加了索引列的字段,都会调整由于更新所带来的键值变化后的索引信息

3、语法

一、建立

CREATE 【 UNIQUE|FULLTEXT|SPATIAL 】 INDEX 索引名称 ON 表名(字段列表);

二、修改

先删除,在建立

三、删除

DROP INDEX 索引名称 ON 表名;

四、查看

SHOW INDEX FROM 表名;

五、alter命令

#该语句添加一个主键,这意味着索引值必须是惟一的,且不能为NULL
ALTER TABLE 表名 ADD PRIMARY KEY(字段列表); 
	
#这条语句建立索引的值必须是惟一的(除了NULL外,NULL可能会出现屡次)
ALTER TABLE 表名 ADD UNIQUE 索引名称(字段列表);
	
#添加普通索引,索引值能够出现屡次。
ALTER TABLE 表名 ADD INDEX 索引名称(字段列表);
	
#该语句指定了索引为FULLTEXT,用于全文索引	
ALTER TABLE 表名 ADD FULLTEXT 索引名称(字段列表);

4、注意

索引的设计能够遵循一些已有的原则,建立索引的时候请尽可能考虑符合这些原则,便于提高索引的使用效率,更高效的使用索引:

  1. 索引字段的选择,最佳候选列应当从where子句的条件中提取,若是where子句中的组合比较多,那么应当挑选最经常使用、过滤效果最好的列的组合

  2. 索引能够有效的提高查询数据的效率,但索引数量不是多多益善,索引越多,维护索引的代价天然也就水涨船高。对于插入、更新、删除等DML操做比较频繁的表来讲,索引过多,会引入至关高的维护代价,下降DML操做的效率,增长相应操做的时间消耗。另外索引过多的话,MySQL也会犯选择困难病,虽然最终仍然会找到一个可用的索引,但无疑提升了选择的代价

  3. 对查询频次较高,且数据量比较大的表创建索引

  4. 使用惟一索引,区分度越高,使用索引的效率越高

  5. 使用短索引,索引建立以后也是使用硬盘来存储的,所以提高索引访问的I/O效率,也能够提高整体的访问效率。假如构成索引的字段总长度比较短,那么在给定大小的存储块内能够存储更多的索引值,相应的能够有效的提高MySQL访问索引的I/O效率

  6. 使用组合索引,若是查询时where子句中使用了组成该索引的前几个字段,那么这条查询SQL能够利用组合索引来提高查询效率。例如:CREATE INDEX idx_name_email_status ON tb_seller(name,email,status); 就至关于对name 建立索引;对name , email 建立了索引;对name , email, status 建立了索引。

8.二、视图

1、含义

MySQL在5.1之后推出了视图(VIEW),自己是一个虚拟表,它的数据来自于表,经过执行时动态生成

2、特色

  1. 简化sql语句

  2. 提升了sql的重用性

  3. 保护基表的数据,提升了安全性

3、语法

一、建立

CREATE VIEW 视图名
AS
查询语句;

二、修改

#方式一:
CREATE OR REPLACE VIEW 视图名
AS
查询语句;

#方式二:
ALTER VIEW 视图名
AS
查询语句;

三、删除

DROP VIEW 视图1,视图2,...;

四、查看

#方式一:
DESC 视图名;

#方式二:
SHOW CREATE VIEW 视图名;

4、注意

视图通常用于查询的,而不是更新的,因此具有如下特色的视图都不容许更新:

  1. 包含分组函数、group by、distinct、having、union、join

  2. 常量视图

  3. where后的子查询用到了from中的表

  4. 用到了不可更新的视图

8.三、存储过程

8.3.一、语法

1、含义

存储过程,相似于Java中的方法,它是一组预先编译好的SQL语句的集合,理解成批处理语句

2、特色

  1. 简化sql语句

  2. 提升了sql的重用性

  3. 减小了编译次数而且减小了和数据库服务器的链接次数,提升了效率

3、语法

一、建立

#标准格式以下:
DELIMITER $
CREATE PROCEDURE 存储过程名(参数模式 参数名 参数类型,...)
BEGIN
	存储过程体(一组合法的SQL语句)
END $
DELIMITER ;

#参数模式in:参数类型是输入的
#参数模式out:参数类型是输出的
#参数模式inout:参数类型既能够输入也能够输出

#调用in模式的参数: CALL sp1('Hello,World');
#调用out模式的参数: SET @name; CALL sp1(@name); SELECT @name;
#调用inout模式的参数: SET @name=值; CALL sp1(@name); SELECT @name;
123456789101112131415

二、修改

先删除,在建立

三、删除

DROP PROCEDURE 存储过程名;

四、查看

SHOW CREATE PROCEDURE 存储过程名;

8.3.二、变量

1、分类

  1. 系统变量

    • 全局变量

    • 会话变量

  2. 自定义变量

    • 用户变量

    • 局部变量

2、语法

一、全局变量

描述:服务器层面上的,必须拥有super权限才能为系统变量赋值,做用域为整个服务器,也就是针对于全部链接(会话)有效,但不能跨重启

一、查看全部系统变量
SHOW GLOBAL VARIABLES;

二、查看知足条件的部分系统变量
SHOW GLOBAL VARIABLES LIKE '%char%';

三、查看指定的系统变量的值
SELECT @@global 系统变量名;

四、为某个系统变量赋值
方式一: SET GLOBAL 系统变量名=值;
方式二: SET @@global 系统变量名=值;

二、会话变量

描述:服务器为每个链接的客户端都提供了系统变量,做用域为当前的链接(会话)

一、查看全部系统变量
SHOW 【 SESSION 】 VARIABLES;

二、查看知足条件的部分系统变量
SHOW 【 SESSION 】 VARIABLES LIKE '%char%';

三、查看指定的系统变量的值
SELECT 【 SESSION 】系统变量名;

四、为某个系统变量赋值
SET 【 SESSION 】系统变量名=值;

三、用户变量

描述:针对于当前链接(会话)生效

位置:能够在begin end里面,也能够放在外面

一、声明并赋值
SET @变量名=值; 或
SET @变量名:=值; 或
SELECT @变量名:=值;

二、更新值
方式一:
	SET @变量名=值; 或
	SET @变量名:=值; 或
	SELECT @变量名:=值;
方式二:
	SELECT xxx INTO @变量名 FROM 表;
	
三、查看值
SELECT @变量名;

四、局部变量

描述:做用域:仅仅在定义它的begin end中有效 位置:只能放在begin end中,并且只能放在第一句

一、声明并赋值
DECLARE 变量名 类型 【 DEFAULT 值 】;

二、更新值
方式一:
	SET 变量名=值; 或
	SET 变量名:=值; 或
	SELECT @变量名:=值;
方式二:
	SELECT xxx INTO 变量名 FROM 表;
	
三、查看值
SELECT 变量名;

8.3.三、分支结构

8.3.3.一、if结构

1、语法

注意:只能应用在begin end中

IF 条件1 THEN 语句1;
ELSEIF 条件2 THEN 语句2;
ELSEIF 条件3 THEN 语句3;
....
【 ELSE 语句n; 】
END IF;

2、演示

#建立函数,实现传入成绩,若是成绩>90,返回A,若是成绩>80,返回B,若是成绩>60,返回C,不然返回D
DELIMITER $
CREATE FUNCTION test_if(score FLOAT) RETURNS CHAR
BEGIN
	DECLARE ch CHAR DEFAULT 'A';
	IF score>90 THEN SET ch='A';
	ELSEIF score>80 THEN SET ch='B';
	ELSEIF score>60 THEN SET ch='C';
	ELSE SET ch='D';
	END IF;
	RETURN ch;
END $
DELIMITER ;

#函数调用
SELECT test_if(87)$

8.3.3.二、case结构

1、语法

注意:只能应用在begin end中

语法1:
CASE 表达式或字段
WHEN 值1 THEN 语句1;
WHEN 值2 THEN 语句2;
...
【 ELSE 语句n; 】
END 【 CASE 】;

语法2:
CASE 
WHEN 条件1 THEN 语句1;
WHEN 条件2 THEN 语句2;
...
【 ELSE 语句n; 】
END 【 CASE 】;

2、演示

#建立函数,实现传入成绩,若是成绩>90,返回A,若是成绩>80,返回B,若是成绩>60,返回C,不然返回D
DELIMITER $
CREATE FUNCTION test_case (score FLOAT) RETURNS CHAR 
BEGIN
	DECLARE ch CHAR DEFAULT 'A' ;
	
	CASE 
	WHEN score>90 THEN SET ch='A';
	WHEN score>80 THEN SET ch='B';
	WHEN score>60 THEN SET ch='C';
	ELSE SET ch='D';
	END CASE;
	
	RETURN ch;
END $
DELIMITER ;

#函数调用
SELECT test_case(56);

8.3.四、循环结构

1、分类

image-20200728162123754

2、演示

8.3.4.一、while结构

#批量插入,根据次数插入到admin表中多条记录,若是次数>20则中止
#删除过程
DROP PROCEDURE IF EXISTS test_while;

#定义过程
DELIMITER $
CREATE PROCEDURE test_while(IN insertCount INT)
BEGIN
	DECLARE i INT DEFAULT 1;
	a:WHILE i<=insertCount DO
		#LEAVE表明Java中的break关键字;ITERATE表明Java中的continue关键字
		IF i>20 THEN LEAVE a;
		END IF;
		INSERT INTO admin(username,`password`) VALUES(CONCAT('xiaohua',i),'0000');
		SET i=i+1;
	END WHILE a;
END $
DELIMITER ;

#调用过程
CALL test_while(100);

8.3.4.二、repeat结构

#批量插入,根据次数插入到admin表中多条记录,若是次数>20则中止
#删除过程
DROP PROCEDURE IF EXISTS test_repeat;

#定义过程
DELIMITER $
CREATE PROCEDURE test_repeat(IN insertCount INT)
BEGIN
	DECLARE i INT DEFAULT 1;
	a:REPEAT 
		INSERT INTO admin(username,`password`) VALUES(CONCAT('xiaohua',i),'0000');
		SET i=i+1;
	UNTIL i>20		
	END REPEAT a;
END $
DELIMITER ;

#调用过程
CALL test_repeat(100);

8.3.4.三、loop结构

#批量插入,根据次数插入到admin表中多条记录,若是次数>20则中止
#删除过程
DROP PROCEDURE IF EXISTS test_loop;

#定义过程
DELIMITER $
CREATE PROCEDURE test_loop(IN insertCount INT)
BEGIN
	DECLARE i INT DEFAULT 1;
	a:LOOP 
		#LEAVE表明Java中的break关键字;ITERATE表明Java中的continue关键字
		IF i>20 THEN LEAVE a;
		END IF;
		INSERT INTO admin(username,`password`) VALUES(CONCAT('xiaohua',i),'0000');
		SET i=i+1;
	END LOOP a;
END $
DELIMITER ;

#调用过程
CALL test_loop(100);

8.3.五、游标

1、含义

游标是用来存储查询结果集的数据类型 , 在存储过程和函数中可使用光标对结果集进行循环的处理

2、语法

一、声明游标

DECLARE 游标名称 CURSOR FOR select结果集;

二、打开游标

OPEN 游标名称;

三、获取游标

FETCH 游标名称 INTO 变量列表(须要跟select结果集的字段对应);

四、关闭游标

CLOSE 游标名称;

3、演示

建数据表以用来演示

CREATE TABLE emp (
  id INT (11) NOT NULL AUTO_INCREMENT,
  NAME VARCHAR (50) NOT NULL COMMENT '姓名',
  age INT (11) COMMENT '年龄',
  salary INT (11) COMMENT '薪水',
  PRIMARY KEY (`id`)
) ENGINE = INNODB DEFAULT CHARSET = utf8 ;

INSERT INTO emp(id,NAME,age,salary) 
VALUES
(NULL,'金毛狮王',55,3800),
(NULL,'白眉鹰王',60,4000),
(NULL,'青翼蝠王',38,2800),
(NULL,'紫衫龙王',42,1800);

循环获取该表的内容

DELIMITER $
CREATE PROCEDURE getAllRowsForEmpTable()
BEGIN
  DECLARE e_id INT(11);
  DECLARE e_name VARCHAR(50);
  DECLARE e_age INT(11);
  DECLARE e_salary INT(11);
  DECLARE has_data INT DEFAULT 1;
  
  DECLARE emp_result CURSOR FOR SELECT * FROM emp;
  DECLARE EXIT HANDLER FOR NOT FOUND SET has_data=0;
  
  OPEN emp_result;
  
  REPEAT
    FETCH emp_result INTO e_id,e_name,e_age,e_salary;
    SELECT CONCAT('id=',e_id , ', name=',e_name, ', age=', e_age, ', salary=',e_salary) as emp_info;
    UNTIL has_data = 0
  END REPEAT;
  
  CLOSE emp_result;
END$
DELIMITER ; 

打开命令行调用查看

CALL getAllRowsForEmpTable();

8.四、函数

1、含义

其实函数就是一个有返回值的过程

2、语法

一、建立

DELIMITER $
CREATE FUNCTION 函数名(参数名 参数类型) 
RETURNS 返回类型
BEGIN
	函数过程体(一组合法的SQL语句)
END $
DELIMITER ;

二、修改

先删除,在建立

三、删除

DROP FUNCTION 函数名;

四、查看

SHOW CREATE FUNCTION 函数名;

五、调用

SELECT 函数名(实参列表);

3、注意

  1. 函数体中确定须要有return语句

  2. 存储过程和函数的区别在于函数必须有返回值,而存储过程没有

8.五、触发器

1、含义

MySQL在5.0之后推出了触发器(TRIGGER),触发器是与表有关的数据库对象,指在 insert/update/delete 以前或以后,触发并执行触发器中定义的SQL语句集合。触发器的这种特性能够协助应用在数据库端确保数据的完整性、日志记录 、数据校验等操做。使用别名 OLD 和 NEW 来引用触发器中发生变化的记录内容,这与其余的数据库是类似的。如今MySQL触发器还只支持行级触发,不支持语句级触发

2、分类

触发器类型 NEW 和 OLD的使用
INSERT 型触发器 NEW 表示将要或者已经新增的数据
UPDATE 型触发器 OLD 表示修改以前的数据 , NEW 表示将要或已经修改后的数据
DELETE 型触发器 OLD 表示将要或者已经删除的数据

3、语法

一、建立

DELIMITER $
CREATE TRIGGER 触发器名称 
BEFORE/AFTER INSERT/UPDATE/DELETE
ON 表名称 
【 FOR EACH ROW 】--行级触发器
BEGIN
	触发器过程体(一组合法的SQL语句)
END $
DELIMITER ;

二、更新

先删除,在建立

三、删除

DROP TRIGGER 触发器名称;

四、查看

SHOW TRIGGERS;

4、演示

建立数据表以用来演示

CREATE TABLE emp (
  id INT (11) NOT NULL AUTO_INCREMENT,
  NAME VARCHAR (50) NOT NULL COMMENT '姓名',
  age INT (11) COMMENT '年龄',
  salary INT (11) COMMENT '薪水',
  PRIMARY KEY (`id`)
) ENGINE = INNODB DEFAULT CHARSET = utf8 ;
INSERT INTO emp(id,NAME,age,salary) 
VALUES
(NULL,'金毛狮王',55,3800),
(NULL,'白眉鹰王',60,4000),
(NULL,'青翼蝠王',38,2800),
(NULL,'紫衫龙王',42,1800);

CREATE TABLE emp_logs (
  id INT (11) NOT NULL AUTO_INCREMENT,
  operation VARCHAR (20) NOT NULL COMMENT '操做类型, insert/update/delete',
  operate_time DATETIME NOT NULL COMMENT '操做时间',
  operate_id INT (11) NOT NULL COMMENT '操做表的ID',
  operate_params VARCHAR (500) COMMENT '操做参数',
  PRIMARY KEY (`id`)
) ENGINE = INNODB DEFAULT CHARSET = utf8 ;

编写触发器进行测试

建立 insert 型触发器,完成插入数据时的日志记录:

DELIMITER $
CREATE TRIGGER emp_logs_insert_trigger
AFTER INSERT 
ON emp 
FOR EACH ROW 
BEGIN
  INSERT INTO emp_logs (id,operation,operate_time,operate_id,operate_params) VALUES(NULL,'insert',NOW(),new.id,CONCAT('插入后(id:',new.id,', name:',new.name,', age:',new.age,', salary:',new.salary,')'));	
END $
DELIMITER ;

建立 update 型触发器,完成更新数据时的日志记录:

DELIMITER $
CREATE TRIGGER emp_logs_update_trigger
AFTER UPDATE 
ON emp 
FOR EACH ROW 
BEGIN
  INSERT INTO emp_logs (id,operation,operate_time,operate_id,operate_params) VALUES(NULL,'update',NOW(),new.id,CONCAT('修改前(id:',old.id,', name:',old.name,', age:',old.age,', salary:',old.salary,') , 修改后(id',new.id, 'name:',new.name,', age:',new.age,', salary:',new.salary,')'));                                                                      
END $
DELIMITER ;

建立delete 行的触发器 , 完成删除数据时的日志记录:

DELIMITER $
CREATE TRIGGER emp_logs_delete_trigger
AFTER DELETE 
ON emp 
FOR EACH ROW 
BEGIN
  INSERT INTO emp_logs (id,operation,operate_time,operate_id,operate_params) VALUES(NULL,'delete',NOW(),old.id,CONCAT('删除前(id:',old.id,', name:',old.name,', age:',old.age,', salary:',old.salary,')'));                                                                      
END $
DELIMITER ;

依次调用如下的语句,查看emp_logs是否有触发器保存的日志记录

INSERT INTO emp(id,NAME,age,salary) VALUES(NULL, '光明左使',30,3500);

UPDATE emp SET age = 39 WHERE id = 3;

DELETE FROM emp WHERE id = 5;

8.六、事件

1、含义

MySQL在5.1之后推出了事件调度器(Event Scheduler),与triggers的事件触发不一样,event相似与linux crontab计划任务,用于时间触发

2、特色

  1. 事件是一组SQL集合,简单说就是mysql中的定时器,时间到了就执行

  2. 事件由一个特定的线程来管理的,也就是所谓的事件调度器,可是事件不能直接调用,经过单独或调用存储过程使用,在某一特定的时间点,触发相关的SQL语句或存储过程

3、语法

一、建立

MySQL事件调度器event_scheduler负责调用事件,它默认是关闭的。这个调度器不断地监视一个事件是否要调用, 要建立事件,必须打开调度器。

#开启事件调度器(任意一个均可以)
SET GLOBAL event_scheduler = ON; 
SET @@global.event_scheduler = ON; 
SET GLOBAL event_scheduler = 1; 
SET @@global.event_scheduler = 1; 

#关闭事件调度器(任意一个均可以)
SET GLOBAL event_scheduler = OFF; 
SET @@global.event_scheduler = OFF; 
SET GLOBAL event_scheduler = 0; 
SET @@global.event_scheduler = 0;
1234567891011
DELIMITER $
CREATE EVENT 事件名称
ON SCHEDULE 执行时间和频率
-- 执行时间和频率有两种形式AT和EVERY
-- 	使用 AT     关键字只会执行一次,格式以下:
-- 	AT CURRENT_TIMESTAMP 或者 'YYYY-MM-DD HH:MM.SS'
-- 	使用 EVERY  关键字指定时间间隔,格式以下:
-- 	EVERY 1 [HOUR|MONTH|WEEK|DAY|MINUTE|...]

-- 可选项,使用 STARTS 关键字指定开始时间,格式以下:
-- STARTS CURRENT_TIMESTAMP 或者 'YYYY-MM-DD HH:MM.SS'
-- 可选项,使用 ENDS   关键字指定结束时间,格式以下:
-- ENDS CURRENT_TIMESTAMP 或者 'YYYY-MM-DD HH:MM.SS'

-- [ON COMPLETION [NOT] PRESERVE] 
-- 可选项,设定event的生命
--		ON COMPLETION NOT PRESERVE :即计划任务执行完毕后自动drop该事件(默认)
--		ON COMPLETION PRESERVE     :即计划任务执行完毕后不会drop该事件

-- [ENABLE | DISABLE] 
-- 可选项,设定event的状态
--		ENABLE	:表示系统尝试执行这个事件(默认)
--		DISABLE	:表示系统尝试关闭这个事件

-- [COMMENT 'comment'] 
-- 可选项,设定event的备注
DO
BEGIN
        /* 在这里写SQL语句或者调用存储过程 */
END$
DELIMITER ;

二、修改

先删除,在建立

三、删除

DROP EVENT 事件名称;

四、查看

SHOW EVENTS;

五、调用

#启用事件
ALTER EVENT 事件名称 ENABLE;

#禁用事件
ALTER EVENT 事件名称 DISABLE;

4、注意

  1. 默认建立事件存储在当前库中,也可显示指定事件建立在哪一个库中

  2. 经过show events只能查看当前库中建立的事件

  3. 事件执行完即释放,如当即执行事件,执行完后,事件便自动删除,屡次调用事件或等待执行事件能够查看到

  4. 若是两个事件须要在同一时刻调用,mysql会肯定调用他们的顺序,若是要指定顺序,须要确保一个事件至少在另外一个事件1秒后执行

  5. 对于递归调度的事件,结束日期不能在开始日期以前

  6. select能够包含在一个事件中,然而他的结果消失了,就好像没执行过

第九章 数据备份与恢复

9.一、数据导出

一、导出某张数据表

#格式:mysqldump -u帐户 -p密码 数据库名 数据表名 > 文件保存路径
mysqldump -uroot -p123456 test emp > D:/emp.sql

二、导出整个数据库

#格式:mysqldump -u帐户 -p密码 数据库名 > 文件保存路径
mysqldump -uroot -p123456 test > D:/test.sql

9.二、数据导入

一、导入某张数据表

#格式:mysql -u帐户 -p密码
#     use 数据库名;
#     source 文件保存路径
mysql -uroot -p123456
>use test;
>source D:/emp.sql

二、导入整个数据库

#格式:mysql -u帐户 -p密码 < 文件保存路径
mysql -uroot -p123456 < test.sql

第十章 安装MySQL单实例

10.一、准备虚拟机

虚拟机配置:全新系统,桌面版

image-20200824234229205

虚拟机地址:进入系统,可上网

image-20200824225209337

链接的工具:自行百度,在下载

SecureCRT:7.0.0

10.二、删除自带库

[root@caochenlei ~]# rpm -qa | grep mysql
mysql-libs-5.1.73-8.el6_8.x86_64
[root@caochenlei ~]# rpm -e mysql-libs-5.1.73-8.el6_8.x86_64 --nodeps
123

10.三、安装依赖包

[root@caochenlei ~]# yum -y install numactl perl libaio wget
1

10.四、下载服务端

下载:

[root@caochenlei ~]# wget https://cdn.mysql.com//Downloads/MySQL-5.6/MySQL-server-5.6.49-1.el6.x86_64.rpm
1

查看:

[root@caochenlei ~]# ll MySQL-server-5.6.49-1.el6.x86_64.rpm
-rw-r--r--. 1 root root 65467136 6月   3 13:36 MySQL-server-5.6.49-1.el6.x86_64.rpm
12

10.五、安装服务端

[root@caochenlei ~]# rpm -ivh MySQL-server-5.6.49-1.el6.x86_64.rpm
1

10.六、下载客户端

下载:

[root@caochenlei ~]# wget https://cdn.mysql.com//Downloads/MySQL-5.6/MySQL-client-5.6.49-1.el6.x86_64.rpm
1

查看:

[root@caochenlei ~]# ll MySQL-client-5.6.49-1.el6.x86_64.rpm
-rw-r--r--. 1 root root 21584380 6月   3 13:36 MySQL-client-5.6.49-1.el6.x86_64.rpm
12

10.七、安装客户端

[root@caochenlei ~]# rpm -ivh MySQL-client-5.6.49-1.el6.x86_64.rpm
1

10.八、启动数据库服务

[root@caochenlei ~]# service mysql start
Starting MySQL.Logging to '/var/lib/mysql/caochenlei.err'.
..                                                         [肯定]
123

10.九、查看初始化密码

[root@caochenlei ~]# cat /root/.mysql_secret
# The random password set for the root user at Mon Aug 24 23:06:53 2020 (local time): E4qT_4CJ9YNf0daG
12

10.十、修改初始化密码

登陆:

[root@caochenlei ~]# mysql -uroot -pE4qT_4CJ9YNf0daG
1

修改:

mysql> set password = password('123456');
Query OK, 0 rows affected (0.01 sec)
12

10.十一、远程的受权

受权:

mysql> grant all privileges on *.* to 'root'@'%' identified by '123456';
Query OK, 0 rows affected (0.00 sec)
12

刷新:

mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)
12

退出:

mysql> exit
Bye
12

10.十二、开放防火墙

[root@caochenlei ~]# /sbin/iptables -I INPUT -p tcp --dport 3306 -j ACCEPT
[root@caochenlei ~]# /etc/rc.d/init.d/iptables save
iptables:将防火墙规则保存到 /etc/sysconfig/iptables:     [肯定]
123

10.1三、添加自启动

[root@caochenlei ~]# chkconfig --add mysql
[root@caochenlei ~]# chkconfig mysql on
12

10.1四、测试链接

image-20200824232120251

10.1五、关闭系统

[root@caochenlei ~]# poweroff

Broadcast message from root@caochenlei
        (/dev/pts/1) at 23:24 ...

The system is going down for power off NOW!
123456

第十一章 安装MySQL主从复制

11.一、准备虚拟机

复制CentOS 6 64 bit-1 > CentOS 6 64 bit-2

image-20200824233313817

启动CentOS 6 64 bit-1:

image-20200824233645840

启动CentOS 6 64 bit-2:选择“我已复制该虚拟机”

image-20200824234110546

11.二、主从复制介绍

主从复制容许未来自一个MySQL数据库服务器(主服务器)的数据复制到一个或多个MySQL数据库服务器(从服务器)。

11.三、主从复制架构

实现目标:一主一从

image-20200825003631169

11.四、主节点配置

编辑:

注意:192.168.206.128为主节点

[root@caochenlei ~]# vi /usr/my.cnf
1

添加:

注意:在[mysqld]下一行添加如下信息

#日志名称
log-bin=mysql-bin
#日志格式:row、statement、mixed
binlog-format=row
#服务器ID标识
server-id=1
#刷写事务日志
innodb_flush_log_at_trx_commit=1
#执行写入1次同步1次
sync_binlog=1
#及时更新master_info
sync_master_info=1
123456789101112

重启:

[root@caochenlei ~]# service mysql restart
Shutting down MySQL...                                     [肯定]
Starting MySQL.....                                        [肯定]
123

链接:

[root@caochenlei ~]# mysql -uroot -p123456
1

受权:

mysql> grant replication slave on *.* to 'root'@'%' identified by '123456';
Query OK, 0 rows affected (0.03 sec)
12

刷新:

mysql> flush privileges;
Query OK, 0 rows affected (0.01 sec)
12

查看:

mysql> show master status\G
*************************** 1. row ***************************
             File: mysql-bin.000001
         Position: 397
     Binlog_Do_DB: 
 Binlog_Ignore_DB: 
Executed_Gtid_Set: 
1 row in set (0.00 sec)
12345678

11.五、从节点配置

编辑:

注意:192.168.206.129为从节点

[root@caochenlei ~]# vi /usr/my.cnf
1

添加:

注意:在[mysqld]下一行添加如下信息

#日志名称
log-bin=mysql-bin
#日志格式:row、statement、mixed
binlog-format=row
#服务器ID标识
server-id=2
#是否只读
read_only=1
12345678

中止:

[root@caochenlei ~]# service mysql stop
Shutting down MySQL..                                      [肯定]
12

删除:

注意:这里不能直接重启mysql是由于它们的auto.cnf中的server-uuid是同样的,在进行接下来的配置的时候会失败,因此要删除从库的server-uuid,让它在启动的时候自动生成一个全新的server-uuid

[root@caochenlei ~]# rm -f /var/lib/mysql/auto.cnf
1

启动:

[root@caochenlei ~]# service mysql start
Starting MySQL...                                          [肯定]
12

链接:

[root@caochenlei ~]# mysql -uroot -p123456
1

执行:

注意:MASTER_LOG_FILE=show master status的File、MASTER_LOG_POS=show master status的Position

CHANGE MASTER TO
MASTER_HOST='192.168.206.128',
MASTER_PORT=3306,
MASTER_USER='root',
MASTER_PASSWORD='123456',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=397;
1234567

开启:

mysql> start slave;
Query OK, 0 rows affected (0.03 sec)
12

查看:

注意:重点检查Master_Log_File、Read_Master_Log_Pos是否和主节点的信息一致,Slave_IO_Running、Slave_SQL_Running是否为YES

mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.206.128
                  Master_User: root
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000001
          Read_Master_Log_Pos: 397
               Relay_Log_File: caochenlei-relay-bin.000002
                Relay_Log_Pos: 283
        Relay_Master_Log_File: mysql-bin.000001
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB: 
          Replicate_Ignore_DB: 
           Replicate_Do_Table: 
       Replicate_Ignore_Table: 
      Replicate_Wild_Do_Table: 
  Replicate_Wild_Ignore_Table: 
                   Last_Errno: 0
                   Last_Error: 
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 397
              Relay_Log_Space: 461
              Until_Condition: None
               Until_Log_File: 
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File: 
           Master_SSL_CA_Path: 
              Master_SSL_Cert: 
            Master_SSL_Cipher: 
               Master_SSL_Key: 
        Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error: 
               Last_SQL_Errno: 0
               Last_SQL_Error: 
  Replicate_Ignore_Server_Ids: 
             Master_Server_Id: 1
                  Master_UUID: d7200ffb-e698-11ea-87e0-000c29e99cce
             Master_Info_File: /var/lib/mysql/master.info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it
           Master_Retry_Count: 86400
                  Master_Bind: 
      Last_IO_Error_Timestamp: 
     Last_SQL_Error_Timestamp: 
               Master_SSL_Crl: 
           Master_SSL_Crlpath: 
           Retrieved_Gtid_Set: 
            Executed_Gtid_Set: 
                Auto_Position: 0
1 row in set (0.02 sec)
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657

11.六、链接测试

测试链接:192.168.206.128(master)

image-20200825014102540

建立数据库:

CREATE DATABASE `mytest` CHARACTER SET utf8 ;
1

建立数据表:

CREATE TABLE `mytest`.`myuser` (
  `id` BIGINT NOT NULL AUTO_INCREMENT,
  `username` VARCHAR (20) NOT NULL,
  `password` VARCHAR (20) NOT NULL,
  PRIMARY KEY (`id`)
) ;
123456

添加数据集:

INSERT INTO `mytest`.`myuser` (`id`, `username`, `password`) VALUES ('1', 'zhangsan', '123456'); 
INSERT INTO `mytest`.`myuser` (`id`, `username`, `password`) VALUES ('2', 'lisi', '123456'); 
INSERT INTO `mytest`.`myuser` (`id`, `username`, `password`) VALUES ('3', 'wangwu', '123456'); 
123

查看数据集:

use mytest;
SELECT * FROM myuser;
12

链接测试:192.168.206.129(slave)

image-20200825014729798

查看数据集:

USE mytest; 
SELECT * FROM myuser;
12

最终的结论:

咱们会发现咱们只在192.168.206.128(master)建立数据库、建立表、添加数据,而它的从节点会自动的拉取主节点的内容,这就是所谓的主从复制了。

第十二章 安装MySQL读写分离

12.一、环境准备

复制CentOS 6 64 bit-2 > CentOS 6 64 bit-3

注意:由于CentOS 6 64 bit-2已是配置好的slave节点了,咱们只须要作少许修改就能实现一主两从的架构了,因此咱们复制CentOS 6 64 bit-2,固然,你要是时间容许,机器性能容许,您也能够从新按照主从复制的步骤在搭建一台slave,在这里咱们就不搭建了,只是进行一下复制修改,复制的时候,注意关机,先关闭slave,再关闭master,再复制,再重命名,先启动master,在启动slave,在启动新复制的那台slave

image-20200825111116521

启动CentOS 6 64 bit-3:选择“我已复制该虚拟机”

image-20200825142527374

12.二、读写分离介绍

以上已经完成了主从复制(一主一从)配置,然而这只是一个基本配置,加上一个proxysql实现MySQL读写分离,proxysql支持MySQL协议的的数据库代理,程序访问的再也不是具体的数据库,而是proxysql这个代理程序,用户请求发向proxysql,若是是写请求发往主节点,读请求发下从节点组中,以此实现读写分离必定程序上减轻了主数据库的io压力。

12.三、读写分离架构

实现目标:一主两从,基于上文中的一主一从,咱们从新复制一个从节点,进行少许修改便可

image-20200825201051126

12.四、修改从节点二

注意:主节点:CentOS 6 64 bit-1【128】、从节点一:CentOS 6 64 bit-2【129】、从节点二:CentOS 6 64 bit-3【130】

中止:

[root@caochenlei ~]# service mysql stop
Shutting down MySQL..                                      [肯定]
12

删除:

[root@caochenlei ~]# rm -f /var/lib/mysql/auto.cnf
1

修改:

[root@caochenlei ~]# vi /usr/my.cnf
1
#服务器ID标识
server-id=3
12

启动:

[root@caochenlei ~]# service mysql start
Starting MySQL.......                                      [肯定]
12

登陆:

[root@caochenlei ~]# mysql -uroot -p123456
1

查看:

USE mytest; 
SELECT * FROM myuser;
12

测试:

第一步:在主节点(192.168.206.128)插入数据

INSERT INTO `mytest`.`myuser` (`id`, `username`, `password`) VALUES ('9', 'xiaojiu', '123456');

USE mytest; 
SELECT * FROM myuser;
1234

第二步:在从节点(192.168.206.129)查看数据

USE mytest; 
SELECT * FROM myuser;
12

第三步:在从节点(192.168.206.130)查看数据

USE mytest; 
SELECT * FROM myuser;
12

注意:若是说从节点一或者从节点二有一个不正常工做,也就是不能主从复制,主要是它们的服务器ID标识复制的时候是同样的,开机由于已经添加了自启动,因此确定会冲突,有一个不可以链接到主节点,只要这个时候重启一下不能正常工做的那台机器的mysql服务就好了,由于从节点二咱们已经修改server-id=3了,这样它们两个从节点确定不会冲突了,到这里,一主两从的模式就搭建好了,接下来就是配置读写分离了。

12.五、安装proxysql

设下载源:

cat << EOF | tee /etc/yum.repos.d/proxysql.repo
[proxysql_repo]
name= ProxySQL YUM repository
baseurl=https://repo.proxysql.com/ProxySQL/proxysql-2.0.x/centos/\$releasever
gpgcheck=1
gpgkey=https://repo.proxysql.com/ProxySQL/repo_pub_key
EOF
1234567

安装依赖:

[root@caochenlei ~]# yum install -y mysql-libs perl-DBI perl-DBD-MySQL
1

开始安装:

[root@caochenlei ~]# yum install -y proxysql-2.0.13-1
1

开放端口:

[root@caochenlei ~]# /sbin/iptables -I INPUT -p tcp --dport 6032 -j ACCEPT
[root@caochenlei ~]# /etc/rc.d/init.d/iptables save
iptables:将防火墙规则保存到 /etc/sysconfig/iptables:[肯定]

[root@caochenlei ~]# /sbin/iptables -I INPUT -p tcp --dport 6033 -j ACCEPT
[root@caochenlei ~]# /etc/rc.d/init.d/iptables save
iptables:将防火墙规则保存到 /etc/sysconfig/iptables:[肯定]
1234567

添加自启动:

[root@caochenlei ~]# chkconfig --add proxysql
[root@caochenlei ~]# chkconfig proxysql on
12

删除文件:

[root@caochenlei ~]# rm -f /etc/proxysql.cnf
1

新增文件:

[root@caochenlei ~]# vi /etc/proxysql.cnf
1
datadir="/var/lib/proxysql"
errorlog="/var/lib/proxysql/proxysql.log"
admin_variables=
{
        #本地登陆的帐号和密码
        admin_credentials="admin:admin"
        #本地登陆的IP和端口号
        mysql_ifaces="0.0.0.0:6032"
}
mysql_variables=
{
        threads=4
        max_connections=2048
        default_query_delay=0
        default_query_timeout=36000000
        have_compress=true
        poll_timeout=2000
        #远程登陆的IP和端口号
        interfaces="0.0.0.0:6033"
        default_schema="information_schema"
        stacksize=1048576
        server_version="5.5.30"
        connect_timeout_server=3000
        #监控帐号的帐号和密码
        monitor_username="monitor"
        monitor_password="monitor"
        monitor_history=600000
        monitor_connect_interval=60000
        monitor_ping_interval=10000
        monitor_read_only_interval=1500
        monitor_read_only_timeout=500
        ping_interval_server_msec=120000
        ping_timeout_server=500
        commands_stats=true
        sessions_sort=true
        connect_retries_on_failure=10
}
#如下的配置咱们会采用动态语句的形式配置
mysql_servers =
(
)
mysql_users:
(
)
mysql_query_rules:
(
)
scheduler=
(
)
mysql_replication_hostgroups=
(
)
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253

注意:6032是链接proxysq的管理端口,6033是对外提供服务的端口。

启动服务:

[root@caochenlei ~]# service proxysql start
Starting ProxySQL: 2020-08-25 20:30:00 [INFO] Using config file /etc/proxysql.cnf
2020-08-25 20:30:00 [INFO] Using OpenSSL version: OpenSSL 1.1.1d  10 Sep 2019
2020-08-25 20:30:00 [INFO] No SSL keys/certificates found in datadir (/var/lib/proxysql). Generating new keys/certificates.
DONE!
12345

12.六、删除自带库

[root@caochenlei ~]# rpm -qa | grep mysql
mysql-libs-5.1.73-8.el6_8.x86_64
[root@caochenlei ~]# rpm -e mysql-libs-5.1.73-8.el6_8.x86_64 --nodeps
123

12.七、安装依赖包

[root@caochenlei ~]# yum -y install numactl perl libaio wget
1

12.八、下载服务端

下载:

[root@caochenlei ~]# wget https://cdn.mysql.com//Downloads/MySQL-5.6/MySQL-server-5.6.49-1.el6.x86_64.rpm
1

查看:

[root@caochenlei ~]# ll MySQL-server-5.6.49-1.el6.x86_64.rpm
-rw-r--r--. 1 root root 65467136 6月   3 13:36 MySQL-server-5.6.49-1.el6.x86_64.rpm
12

12.九、安装服务端

[root@caochenlei ~]# rpm -ivh MySQL-server-5.6.49-1.el6.x86_64.rpm
1

12.十、下载客户端

下载:

[root@caochenlei ~]# wget https://cdn.mysql.com//Downloads/MySQL-5.6/MySQL-client-5.6.49-1.el6.x86_64.rpm
1

查看:

[root@caochenlei ~]# ll MySQL-client-5.6.49-1.el6.x86_64.rpm
-rw-r--r--. 1 root root 21584380 6月   3 13:36 MySQL-client-5.6.49-1.el6.x86_64.rpm
12

12.十一、安装客户端

[root@caochenlei ~]# rpm -ivh MySQL-client-5.6.49-1.el6.x86_64.rpm
1

12.十二、启动数据库服务

[root@caochenlei ~]# service mysql start
Starting MySQL.Logging to '/var/lib/mysql/caochenlei.err'.
..                                                         [肯定]
123

12.1三、查看初始化密码

[root@caochenlei ~]# cat /root/.mysql_secret
# The random password set for the root user at Tue Aug 25 20:31:19 2020 (local time): IFIn7pcTznYpoLm1
12

12.1四、修改初始化密码

登陆:

[root@caochenlei ~]# mysql -uroot -pIFIn7pcTznYpoLm1
1

修改:

mysql> set password = password('123456');
Query OK, 0 rows affected (0.01 sec)
12

退出:

mysql> exit
Bye
12

12.1五、建立两个帐号

这个操做是在master节点进行的,建立完成后,会自动复制到从节点,方便proxysql后来的监控和远程登陆的认证链接

注意:可使用 select user,host from mysql.user; 查看全部用户

为proxysql建立监控帐号(主要作监控使用):

create user 'monitor'@'%' identified by 'monitor';
grant all privileges on *.* to 'monitor'@'%' identified by 'monitor';
flush privileges;
123

为proxysql建立远程帐号(主要是远程登陆):

create user 'proxysql'@'%' identified by 'proxysql';
grant all privileges on *.* to 'proxysql'@'%' identified by 'proxysql';
flush privileges;
123

退出:

mysql> exit
Bye
12

12.1六、配置proxysql

这个操做是在安装proxysql的这台机器上的操做,6032端口的默认帐号密码为admin,若是想要修改请在第12.5步修改,而后重启。

[root@caochenlei ~]# mysql -uadmin -padmin -h127.0.0.1 -P6032 --prompt 'admin>'
1

分别执行如下语句

# 配置主从复制的信息
insert into mysql_servers(hostgroup_id,hostname,port,weight,max_connections,max_replication_lag,comment) values(10,'192.168.206.128',3306,1,1000,10,'write mysql');
insert into mysql_servers(hostgroup_id,hostname,port,weight,max_connections,max_replication_lag,comment) values(20,'192.168.206.129',3306,1,10000,10,'read mysql');
insert into mysql_servers(hostgroup_id,hostname,port,weight,max_connections,max_replication_lag,comment) values(20,'192.168.206.130',3306,1,10000,10,'read mysql');

# 本地主机登陆的帐号:默认就是admin:admin不用再配置

# 配置远程登陆的帐号:以前在master主节点中已经建立了
insert into mysql_users(username,password,active,default_hostgroup,transaction_persistent) values('proxysql','proxysql',1,20,1);

# 设置转发规则
INSERT INTO mysql_query_rules(active,match_pattern,destination_hostgroup,apply) VALUES(1,'^SELECT.*FOR UPDATE$',10,1);
INSERT INTO mysql_query_rules(active,match_pattern,destination_hostgroup,apply) VALUES(1,'^SELECT',20,1);

# 马上加载配置
load mysql servers to runtime;
load mysql users to runtime;
load mysql variables to runtime;
load mysql query rules to runtime;

# 配置写到磁盘
save mysql servers to disk;
save mysql users to disk;
save mysql variables to disk;
save mysql query rules to disk;
12345678910111213141516171819202122232425

执行完成之后退出

12.1七、链接proxysql

注意:若是远程链接不上,请把防火墙所有关掉试试,若是不行,请从新启动一下proxysql,仍是不行,请重头排查一下问题,或者查看日志tail /var/lib/proxysql/proxysql.log

第一种:远程命令行链接测试

主节点、两个从节点随便找一台测试一下:

##链接
[root@caochenlei ~]# mysql -uproxysql -pproxysql -h192.168.206.131 -P6033

##查看全部数据库
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| mytest             |
| performance_schema |
| test               |
+--------------------+
5 rows in set (0.05 sec)
123456789101112131415

第二种:远程图形化窗口链接

注意这个端口是6033而不是3306,帐号和密码我以前设置的都是proxysql

image-20200825212223601

12.1八、查询监控数据

若是想要查看sql语句在哪一个数据库执行的,在proxysql机器上请执行如下语句

[root@caochenlei ~]# mysql -uadmin -padmin -h127.0.0.1 -P6032 --prompt 'admin>'
admin> select * from stats_mysql_query_digest;
12

第十三章 安装MySQL分片集群

13.一、环境准备

咱们使用以前的读写分离时候配置的一主两从这三台服务器,至于那个读写分离的数据库中间件proxysql服务器就用不着了,直接关机就好了,如下三台依次从主节点开始启动便可也就是CentOS 6 64 bit-一、CentOS 6 64 bit-二、CentOS 6 64 bit-3

image-20200825111116521

13.二、分片集群介绍

现在随着互联网的发展,数据的量级也是撑指数的增加,从GB到TB到PB。对数据的各类操做也是越发的困难,传统的关系性数据库已经没法知足快速查询与插入数据的需求。这个时候NoSQL的出现暂时解决了这一危机。它经过下降数据的安全性,减小对事务的支持,减小对复杂查询的支持,来获取性能上的提高。

可是,在有些场合NoSQL一些折衷是没法知足使用场景的,就好比有些使用场景是绝对要有事务与安全指标的。这个时候NoSQL确定是没法知足的,因此仍是须要使用关系性数据库。若是使用关系型数据库解决海量存储的问题呢?此时就须要作数据库集群,为了提升查询性能将一个数据库的数据分散到不一样的数据库中存储。简单来讲,就是指经过某种特定的条件,将咱们存放在同一个数据库中的数据分散存放到多个数据库(主机)上面,以达到分散单台设备负载的效果。而这其中,咱们须要使用一个数据库中间件来完成,它就是Mycat。

13.三、分片集群架构

实现目标:一主两从须要三组,再加上一个数据库中间件服务器,一共须要10台

image-20200825220142607

如何演示:但实际上呢,这个分片集群是在主从复制模式上进行的演进,说白了,上边的3组一主两从,随便拿出来一个都是一个主从复制模式,那咱们前一章已经完成了一主两从的学习,也就是已经配置好了这三台服务器,咱们要是再拷贝出来两组就显得太麻烦了,学习嘛,怎么简单怎么来,如今咱们手头只有一组,那咱们就在这一组上进行演示,也就是一组上建立三个数据库,咱们学习的架构就是下边这样了和上边的效果如出一辙,以下图:

image-20200826093129272

13.四、Mycat的介绍

Mycat 背后是阿里曾经开源的知名产品——Cobar。Cobar 的核心功能和优点是 MySQL 数据库分片,此产品曾经广为流传,听说最先的发起者对 MySQL 很精通,后来从阿里跳槽了,阿里随后开源的 Cobar,并维持到 2013 年年初,而后,就没有而后了。

Cobar 的思路和实现路径的确不错。基于 Java 开发的,实现了 MySQL 公开的二进制传输协议,巧妙地将本身假装成一个 MySQL Server,目前市面上绝大多数 MySQL 客户端工具和应用都能兼容。比本身实现一个新的数据库协议要明智的多,由于生态环境在哪里摆着。

Mycat 是基于 cobar 演变而来,对 cobar 的代码进行了完全的重构,使用 NIO 重构了网络模块,而且优化了 Buffer 内核,加强了聚合,Join 等基本特性,同时兼容绝大多数数据库成为通用的数据库中间件。

简单的说,MyCAT就是一个新颖的数据库中间件产品,支持mysql集群或者mariadb集群,提供高可用性数据分片集群。你能够像使用mysql同样使用mycat。对于开发人员来讲根本感受不到mycat的存在。

它支持的数据库产品很是的多如:

image-20200825215043387

13.五、Mycat的分片

分片就是指经过某种特定的条件,将咱们存放在同一个数据库中的数据分散存放到多个数据库(主机)上面,以达到分散单台设备负载的效果。

数据的切分(Sharding)根据其切分规则的类型,能够分为两种切分模式。

(1)一种是按照不一样的表(或者Schema)来切分到不一样的数据库(主机)之上,这种切分能够称之为数据的垂直(纵向)切分

img

(2)另一种则是根据表中的数据的逻辑关系,将同一个表中的数据按照某种条件拆分到多台数据库(主机)上面,这种切分称之为数据的水平(横向)切分。

image-20200825215350981

13.六、Mycat的安装

官方网址:Mycat

默认端口:8066

JDK:要求jdk必须是1.7及以上版本

MySQL:推荐mysql是5.5及以上版本

安装JDK8:

#查看软件
rpm -qa | grep java
rpm -qa | grep jdk

#批量卸载
rpm -qa | grep jdk | xargs rpm -e --nodeps
rpm -qa | grep java | xargs rpm -e --nodeps

#在线安装
yum install -y java-1.8.0-openjdk java-1.8.0-openjdk-devel

#经过yum方式安装默认安装在/usr/lib/jvm文件下,看看你本身安装的具体是哪一个版本
ll /usr/lib/jvm/

#编辑/etc/profile文件,在文件最后写入环境变量,而后保存退出
vi /etc/profile

# java environment
export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.262.b10-0.el6_10.x86_64
export JRE_HOME=$JAVA_HOME/jre
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/jre/lib/tools.jar:$JRE_HOME/lib:$CLASSPATH
export PATH=$JAVA_HOME/bin:$PATH

#使环境变量生效
source /etc/profile

#查看安装是否成功,这两个都能出来就安装成功了
[root@caochenlei ~]# java -version
openjdk version "1.8.0_262"
OpenJDK Runtime Environment (build 1.8.0_262-b10)
OpenJDK 64-Bit Server VM (build 25.262-b10, mixed mode)
[root@caochenlei ~]# javac -version
javac 1.8.0_262
123456789101112131415161718192021222324252627282930313233

下载:

注意:失效的话,请自行百度,而后上传到虚拟机

[root@caochenlei ~]# wget http://dl.mycat.org.cn/1.6-RELEASE/Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz
1

解压:

[root@caochenlei ~]# tar -zxvf Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz
1

安装:

[root@caochenlei ~]# mv mycat /usr/local
1

添加防火墙:

注意:mycat数据端口默认为8066,管理端口默认为9066,咱们都须要对外开放

[root@caochenlei ~]# /sbin/iptables -I INPUT -p tcp --dport 8066 -j ACCEPT
[root@caochenlei ~]# /sbin/iptables -I INPUT -p tcp --dport 9066 -j ACCEPT
[root@caochenlei ~]# /etc/rc.d/init.d/iptables save
iptables:将防火墙规则保存到 /etc/sysconfig/iptables:[肯定]
1234

添加域名解析:

[root@caochenlei ~]# vi /etc/hosts
1
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

#配置当前主机名称的域名解析
192.168.206.128 caochenlei

#配置一主两从服务的域名解析
192.168.206.128 master1
192.168.206.129 slave1
192.168.206.130 slave2
12345678910

经常使用命令:

  • /usr/local/mycat/bin/mycat start 启动

  • /usr/local/mycat/bin/mycat stop 中止

  • /usr/local/mycat/bin/mycat console 前台运行,能够显示日志,新手建议使用

  • /usr/local/mycat/bin/mycat restart 重启服务

  • /usr/local/mycat/bin/mycat pause 暂停

  • /usr/local/mycat/bin/mycat status 查看启动状态

13.七、Mycat的配置

第一步:登陆主节点建立三个数据库分别是db一、db二、db3

CREATE DATABASE `db1`CHARACTER SET utf8; 
CREATE DATABASE `db2`CHARACTER SET utf8; 
CREATE DATABASE `db3`CHARACTER SET utf8; 
123

第二步:修改schema.xml文件

删除原有配置

[root@caochenlei ~]# rm -f /usr/local/mycat/conf/schema.xml
1

新增咱们配置

[root@caochenlei ~]# vi /usr/local/mycat/conf/schema.xml
1
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
	<schema name="STOREDB" checkSQLschema="false" sqlMaxLimit="100">
		<!-- rule采用按主键范围分片,主键名为id(默认) -->
		<table name="TB_USERS" dataNode="dn1,dn2,dn3" rule="auto-sharding-long" />
		<!-- rule采用按哈希一致分片,主键名为order_id(本身修改) -->
		<table name="TB_ORDER" dataNode="dn1,dn2,dn3" rule="sharding-by-murmur-order" />
	</schema>

	<dataNode name="dn1" dataHost="OneMasterAndTwoSlave" database="db1" />
	<dataNode name="dn2" dataHost="OneMasterAndTwoSlave" database="db2" />
	<dataNode name="dn3" dataHost="OneMasterAndTwoSlave" database="db3" />

	<dataHost name="OneMasterAndTwoSlave" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
		<!-- 心跳语句 -->
		<heartbeat>select user()</heartbeat>
		<!-- 一主两从 -->
		<writeHost host="hostM1" url="master1:3306" user="root" password="123456">
			<readHost host="hostS1" url="slave1:3306" user="root" password="123456" />
			<readHost host="hostS2" url="slave2:3306" user="root" password="123456" />
		</writeHost>
	</dataHost>
</mycat:schema>
123456789101112131415161718192021222324

第三步:修改server.xml文件

server.xml几乎保存了全部mycat须要的系统配置信息,最经常使用的是在此配置用户名、密码及权限。

[root@caochenlei ~]# vi /usr/local/mycat/conf/server.xml
1

在system中添加UTF-8字符集设置,不然存储中文会出现问号。

<property name="charset">utf8</property>
1

修改user的设置 , 咱们这里为STOREDB数据库设置了两个用户。把它以前的两个用户删掉,把我们本身设置的放进去。

<user name="test">
	<property name="password">test</property>
	<property name="schemas">STOREDB</property>
</user>
<user name="root">
	<property name="password">root</property>
	<property name="schemas">STOREDB</property>
</user>
12345678

第四步:修改auto-sharding-rang-mod.txt文件

修改主键范围分片大小

删除:

[root@caochenlei ~]# rm -f /usr/local/mycat/conf/auto-sharding-rang-mod.txt
1

新增:

[root@caochenlei ~]# vi /usr/local/mycat/conf/auto-sharding-rang-mod.txt
1
0-500M=0
500M1-1000M=1
1000M1-1500M=2
123

注意:以上意思是主键id在0-500M的数据放在分片1中,500M1-1000M的数据放到分片2中,1000M1-1500M的数据放到分片3中,超过1500M1,就报错

第五步:修改rule.xml文件

[root@caochenlei ~]# vi /usr/local/mycat/conf/rule.xml
1

新增哈希订单主键,由于默认主键名都是id,要想是本身定义的,就拷贝一份,从新起个名,而后修改columns成你数据表的那个主键名称就好了

        <tableRule name="sharding-by-murmur-order">
                <rule>
                        <columns>order_id</columns>
                        <algorithm>murmur</algorithm>
                </rule>
        </tableRule>
123456

修改分片数量,由于如今有db一、db二、db3个分片,找到<function name="murmur"中的count,修改成3,如如下所示:

        <function name="murmur"
                class="io.mycat.route.function.PartitionByMurmurHash">
                <property name="seed">0</property><!-- 默认是0 -->
                <property name="count">3</property><!-- 要分片的数据库节点数量,必须指定,不然无法分片 -->
                <property name="virtualBucketTimes">160</property><!-- 一个实际的数据库节点被映射为这么多虚拟节点,默认是160倍,也就是虚拟节点数是物理节点数的160倍 -->
                <!-- <property name="weightMapFile">weightMapFile</property> 节点的权重,没有指定权重的节点默认是1。以properties文件的格式填写,以从0开始到count-1的整数值>也就是节点索引为key,以节点权重值为值。全部权重值必须是正整数,不然以1代替 -->
                <!-- <property name="bucketMapPath">/etc/mycat/bucketMapPath</property>
                        用于测试时观察各物理节点与虚拟节点的分布状况,若是指定了这个属性,会把虚拟节点的murmur hash值与物理节点的映射按行输出到这个文件,没有默认值,若是不
指定,就不会输出任何东西 -->
        </function>
12345678910

13.八、Mycat的启动

在启动以前,咱们须要作一个密码重置的工做,也不知道这是否是个BUG,可是,你要不作密码重置,极可能Mycat它启动不起来,我也是醉了,就这一个问题,搞了我一夜的心态,操做步骤以下:

依次在主节点、从节点1、从节点二执行如下四条语句:

use mysql;
update user set password = password('123456') where user = 'root';
flush privileges;
set password for 'root' = password('123456');
#若是上句报错使用下边这个,不报错就算了
set password = password('123456');
123456

而后再启动Mycat

[root@caochenlei ~]# /usr/local/mycat/bin/mycat start
Starting Mycat-server...
12

13.九、Mycat的测试

注意:在这里我使用图形化界面来操做,先测试是否连通,若是不能连上,请检查虚拟机防火墙是否关闭,那两个用户是否配对,若是Mycat重启不成功,请使用ps -ef | grep mycat查看,而后使用kill强制杀死,再而后从新启动,若是不知道什么问题,请使用前台运行,它会显示出错误信息,而后再解决

image-20200825235336310

建立用户表,而后插入数据,直接拷贝如下SQL代码到窗口,而后运行,必须一步一步来而且不要进行窗口操做对链接Mycat的那个链接,由于会报错

#第一步:删表
USE `STOREDB`;
DROP TABLE IF EXISTS `TB_USERS`;

#第二步:建表
CREATE TABLE `TB_USERS` (
  `id` bigint(20) NOT NULL,
  `username` varchar(20) NOT NULL,
  `password` varchar(20) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

#第三步:插入数据
insert  into `TB_USERS`(`id`,`username`,`password`) values (1,'zhangsan1','123456');
insert  into `TB_USERS`(`id`,`username`,`password`) values (2,'zhangsan2','123456');
insert  into `TB_USERS`(`id`,`username`,`password`) values (3,'zhangsan3','123456');
insert  into `TB_USERS`(`id`,`username`,`password`) values (5000001,'lisi1','123456');
insert  into `TB_USERS`(`id`,`username`,`password`) values (5000002,'lisi2','123456');
insert  into `TB_USERS`(`id`,`username`,`password`) values (5000003,'lisi3','123456');
insert  into `TB_USERS`(`id`,`username`,`password`) values (10000001,'wangwu1','123456');
insert  into `TB_USERS`(`id`,`username`,`password`) values (10000002,'wangwu2','123456');
insert  into `TB_USERS`(`id`,`username`,`password`) values (10000003,'wangwu3','123456');
12345678910111213141516171819202122

建立订单表,而后插入数据,直接拷贝如下SQL代码到窗口,而后运行,必须一步一步来而且不要进行窗口操做对链接Mycat的那个链接,由于会报错

#第一步:删表
USE `STOREDB`;
DROP TABLE IF EXISTS `TB_ORDER`;

#第二步:建表
CREATE TABLE `TB_ORDER` (
  `order_id` varchar(30) NOT NULL,
  `create_time` datetime NOT NULL,
  `pay_time` datetime NOT NULL,
  `total_fee` bigint(20) NOT NULL,
  `user_id` varchar(50) NOT NULL,
  PRIMARY KEY (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

#第三步:插入数据
insert  into `TB_ORDER`(`order_id`,`create_time`,`pay_time`,`total_fee`,`user_id`) values ('201708261157265358046058','2017-08-26 11:57:26','2017-08-26 12:48:22',1,'lijialong');
insert  into `TB_ORDER`(`order_id`,`create_time`,`pay_time`,`total_fee`,`user_id`) values ('201708261221397410698125','2017-08-26 12:21:39','2017-08-26 12:48:22',1,'lijialong');
insert  into `TB_ORDER`(`order_id`,`create_time`,`pay_time`,`total_fee`,`user_id`) values ('201708261234474784646997','2017-08-26 12:34:47','2017-08-26 12:48:22',1,'lijialong');
insert  into `TB_ORDER`(`order_id`,`create_time`,`pay_time`,`total_fee`,`user_id`) values ('201708261247443132289031','2017-08-26 12:47:44','2017-08-26 12:48:22',3,'lijialong');
insert  into `TB_ORDER`(`order_id`,`create_time`,`pay_time`,`total_fee`,`user_id`) values ('918773291320152064534354','2017-10-13 17:39:57','2017-08-26 12:48:22',5,'lijialong');
insert  into `TB_ORDER`(`order_id`,`create_time`,`pay_time`,`total_fee`,`user_id`) values ('918780410236788736453543','2017-10-13 18:08:14','2017-10-13 18:09:36',1,'lijialong');
insert  into `TB_ORDER`(`order_id`,`create_time`,`pay_time`,`total_fee`,`user_id`) values ('918806410983137280453453','2017-10-13 19:51:33','2017-10-13 19:51:47',1,'lijialong');
insert  into `TB_ORDER`(`order_id`,`create_time`,`pay_time`,`total_fee`,`user_id`) values ('918833486129815552274522','2017-10-13 21:39:08','2017-08-26 12:48:22',1,'lijialong');
insert  into `TB_ORDER`(`order_id`,`create_time`,`pay_time`,`total_fee`,`user_id`) values ('918835712999055360745325','2017-10-13 21:47:59','2017-10-13 21:49:28',1,'lijialong');
insert  into `TB_ORDER`(`order_id`,`create_time`,`pay_time`,`total_fee`,`user_id`) values ('919055625042825216545334','2017-10-14 12:21:50','2017-08-26 12:48:22',1,'lijialong');
insert  into `TB_ORDER`(`order_id`,`create_time`,`pay_time`,`total_fee`,`user_id`) values ('919059761058607104453433','2017-10-14 12:38:16','2017-10-14 12:38:24',2,'lijialong');
1234567891011121314151617181920212223242526

13.十、Mycat的效果

重开一个窗口,链接主节点,依次查看,db一、db二、db3上的TB_USERS、TB_ORDER,你会发现数据是均匀分布的,这就实现了咱们最终的分片集群了,具体效果图以下:

db1>TB_USERS

image-20200826020118355

db2>TB_USERS

image-20200826020137393

db3>TB_USERS

image-20200826020201015

db1>TB_ORDER

image-20200826020226630

db2>TB_ORDER

image-20200826020245571

db3>TB_ORDER

image-20200826020257914

13.十一、Mycat的踩坑

  1. Mycat只是一个数据库中间件,它并非一个真正的数据库,因此用窗口不能直接操做,须要使用SQL语句

  2. Mycat依赖于JDK1.7+,我建议使用JDK1.8

  3. Mycat只是帮你作了数据分片,真正的主从复制仍是靠你本身实现

  4. 当你建立表的时候,Mycat默认会把表名转换为大写,因此你建立的时候就直接把表名大写和数据库名大写,不然可能会找不到表,由于大小写不对应

  5. 当你的主键字段不是id的时候,直接在ruls.xml中拷贝一份相对应类型的tableRule,而后改个规则名称和字段名称就好了,而后再引用自定义的那个