MySQL 服务器

文章目录

  • [mysql 数据库](#mysql 数据库)
    • [**1** **数据库原理**](#1 数据库原理)
      • [**1.1** **数据的时代**](#1.1 数据的时代)
      • [**1.2** **数据库的发展史**](#1.2 数据库的发展史)
        • [**1.2.1** **文件管理系统的缺点**](#1.2.1 文件管理系统的缺点)
        • [**1.2.2** **数据库系统发展阶段**](#1.2.2 数据库系统发展阶段)
      • [**1.3 DBMS** **数据库管理系统**](#1.3 DBMS 数据库管理系统)
      • [**1.4** **数据库管理系统(DBMS)的优点**](#1.4 数据库管理系统(DBMS)的优点)
      • [**1.5** **数据库管理系统的基本功能**](#1.5 数据库管理系统的基本功能)
      • [**1.6** **数据库系统的架构**](#1.6 数据库系统的架构)
      • [**1.7** **各种数据库管理系统**](#1.7 各种数据库管理系统)
        • [**1.7.1** **层次数据库**](#1.7.1 层次数据库)
        • [**1.7.2** **网状数据库**](#1.7.2 网状数据库)
        • [1.7.3 RDBMS关系型数据库](#1.7.3 RDBMS关系型数据库)
    • [**2 MySQL** **历史**](#2 MySQL 历史)
    • 关系型数据库和非关系型数据库
    • [3.安装 mysql 及优化](#3.安装 mysql 及优化)
      • [3.1 yum安装](#3.1 yum安装)
        • [**3.1.1 yum安装5.7版本**](#3.1.1 yum安装5.7版本)
        • [3.1.2 登录数据库](#3.1.2 登录数据库)
        • [3.1.3 rpm包安装](#3.1.3 rpm包安装)
      • [3.2 编译安装 mysql](#3.2 编译安装 mysql)
        • [3.2.1 安装相关依赖包](#3.2.1 安装相关依赖包)
        • 3.2.2**源码编译安装**
        • [3.2.3 **下载并解压缩源码包**](#3.2.3 下载并解压缩源码包)
      • [3.3二进制安装 mysql5.7](#3.3二进制安装 mysql5.7)
        • 1**准备用户**
        • [2. **准备数据目录,建议使用逻辑卷**](#2. 准备数据目录,建议使用逻辑卷)
        • 3.**准备二进制程序**
        • 4.**准备配置文件**
        • [**5** **创建数据库文件**生成root空密码](#5 创建数据库文件生成root空密码)
        • [**6** **准备服务脚本,并启动服务**](#6 准备服务脚本,并启动服务)
        • [**7 PATH路径**](#7 PATH路径)
        • [**8** **安全初始化**](#8 安全初始化)
        • 9测试登录
        • [10 一键安装脚本](#10 一键安装脚本)
      • [3.4 客户端命令行优化操作](#3.4 客户端命令行优化操作)
      • [3.5 **客户端程序**](#3.5 客户端程序)
        • [3.5.1 mysql:](#3.5.1 mysql:)
        • [3.5.2 mysqladmin命令](#3.5.2 mysqladmin命令)
        • [3.5. navicat](#3.5. navicat)
        • [3.6 **用户账号**](#3.6 用户账号)
    • [4 多实例](#4 多实例)
    • [5 安装 mycli 插件 客户端工具](#5 安装 mycli 插件 客户端工具)
    • 6基本操作
      • [6.1 SQL分类](#6.1 SQL分类)
      • [6.2 查看帮助信息](#6.2 查看帮助信息)
      • [6.3 查看支持的字符集](#6.3 查看支持的字符集)
      • [6.4 **管理数据库**](#6.4 管理数据库)
        • [6.4.1 **创建数据库**](#6.4.1 创建数据库)
          • [6.4.1.1 新建数据库](#6.4.1.1 新建数据库)
          • [6.4.1.2 新建数据库 指定字符集](#6.4.1.2 新建数据库 指定字符集)
          • [6.4.1.3 if no exists 先判断数据库是否存在](#6.4.1.3 if no exists 先判断数据库是否存在)
          • [6.4.1.4 生产例子](#6.4.1.4 生产例子)
        • [6.**4.2** **修改数据库**](#6.4.2 修改数据库)
        • 6.4.3**删除数据库**
        • 6.4.4**查看数据库列表**
        • [6.**4.5** **数据类型**](#6.4.5 数据类型)
          • [**6.4.5.1** **整数型**](#6.4.5.1 整数型)
          • [6.**4.5.2** 浮点型(float和double),近似值](#6.4.5.2 浮点型(float和double),近似值)
          • [**6.4.5.3** **定点数**](#6.4.5.3 定点数)
          • [6.**4.5.4** 字符串](#6.4.5.4 字符串)
          • [6.4.5.6**修饰符** 修饰数据的](#6.4.5.6修饰符 修饰数据的)
        • 6.4.6表操作
        • [6.4.7 DML语言 data manger language](#6.4.7 DML语言 data manger language)
          • [6.4.7.1 INSERT语句](#6.4.7.1 INSERT语句)
          • [6.4.7.2 **UPDATE** **语句**](#6.4.7.2 UPDATE 语句)
          • [6.**4.7.3 DELETE** **语句**](#6.4.7.3 DELETE 语句)
        • [6.**4.8 DQL** 语句 单表查询](#6.4.8 DQL 语句 单表查询)
          • [6.4.8.1 SELECT ----显示表格中一个或数个字段的所有数据记录](#6.4.8.1 SELECT ----显示表格中一个或数个字段的所有数据记录)
          • [6.4.8.2 WHERE --- 过滤查询](#6.4.8.2 WHERE --- 过滤查询)
          • [6.4.8.3 AND OR 且 或](#6.4.8.3 AND OR 且 或)
          • [6.4.8.4 DISTINCT 去除重复行](#6.4.8.4 DISTINCT 去除重复行)
          • [6.4.8.5 like 模糊查询 与 通配符](#6.4.8.5 like 模糊查询 与 通配符)
          • [6.4.8.6 数学函数:](#6.4.8.6 数学函数:)
          • [6.4.8.7 聚合函数](#6.4.8.7 聚合函数)
          • [6.4.8.8 字符串函数](#6.4.8.8 字符串函数)
          • [6.4.8.9 GROUP BY 分组](#6.4.8.9 GROUP BY 分组)
          • [6.4.8.10 排序 order by](#6.4.8.10 排序 order by)
          • [6.4.8.11 limit](#6.4.8.11 limit)
          • [6.4.8.12 having](#6.4.8.12 having)
          • [6.4.8.13 视图view 临时表](#6.4.8.13 视图view 临时表)
          • [6.4.8.14 正则表达式](#6.4.8.14 正则表达式)
        • [6.4.9 DQL 语句多表查询](#6.4.9 DQL 语句多表查询)
          • [6.4.9.1 子查询](#6.4.9.1 子查询)
          • [6.4.9.2 联合查询 纵向合并](#6.4.9.2 联合查询 纵向合并)
          • [6.4.9.3 交叉连接 横向合并](#6.4.9.3 交叉连接 横向合并)
          • [6.4.9.4 内连接](#6.4.9.4 内连接)
          • [6.4.9.5 外连接](#6.4.9.5 外连接)
          • [6.4.9.6 自连接](#6.4.9.6 自连接)
          • [6.4.9.7 三表查询](#6.4.9.7 三表查询)
      • [6.5 视图](#6.5 视图)
    • [7 用户管理](#7 用户管理)
      • [7.1 存放用户信息的表](#7.1 存放用户信息的表)
      • [7.2 查看当前使用用户](#7.2 查看当前使用用户)
      • [7.3 新建用户](#7.3 新建用户)
      • [7.4 修改用户名称](#7.4 修改用户名称)
      • 7.5删除用户
      • [7.6 修改用户密码](#7.6 修改用户密码)
      • [7.7 破解密码](#7.7 破解密码)
      • 7.8远程登录
      • [7.9 用户权限管理](#7.9 用户权限管理)
    • 8MySQL架构和性能优化
      • 8.1索引
      • [8.2 索引管理](#8.2 索引管理)
        • [8.2.1 查看索引](#8.2.1 查看索引)
        • [8.2.2 建立索引](#8.2.2 建立索引)
        • 8.2.3删除索引
      • [8.3EXPLAIN 工具](#8.3EXPLAIN 工具)
      • [8.4**使用** **profile** 工具 监控](#8.4使用 profile 工具 监控)
    • [9 **并发控制**](#9 并发控制)
    • [10. 存储引擎](#10. 存储引擎)
      • [10.1 **MyISAM** **引擎特点**](#10.1 MyISAM 引擎特点)
      • [10.2 InnoDB引擎特点](#10.2 InnoDB引擎特点)
      • 10.3**管理存储引擎**
      • [**10.4MySQL** **中的系统数据库**](#10.4MySQL 中的系统数据库)
      • [10.5 存储过程](#10.5 存储过程)
    • 11.日志
    • [12 备份](#12 备份)
      • 12.1**备份类型**
      • 12.2完全备份
        • [12.2.1 物理冷备份](#12.2.1 物理冷备份)
        • [12.2.2 mysqldump 备份与恢复](#12.2.2 mysqldump 备份与恢复)
      • [12.3 增量备份恢复](#12.3 增量备份恢复)
    • 13.主从复制
      • 13.1MySQL主从复制
      • [13.2主从复制 实战](#13.2主从复制 实战)
      • [13.3 **复制错误解决方法**](#13.3 复制错误解决方法)
      • [13.4 级联 主从复制](#13.4 级联 主从复制)
      • [13.5 半同步复制](#13.5 半同步复制)
      • [13.6 面试重点](#13.6 面试重点)
    • [14 **MySQL** **中间件代理服务器**](#14 MySQL 中间件代理服务器)
    • [15 mysql 高可用解决方案](#15 mysql 高可用解决方案)
    • 16.生产环境
      • [16.1 my.cnf 配置案例](#16.1 my.cnf 配置案例)
      • 16.2MySQL配置最佳实践
      • [16.3 基础规范](#16.3 基础规范)
      • [16.4 **命名规范**](#16.4 命名规范)
      • [16.5 **表设计规范**](#16.5 表设计规范)
      • [16.6 **字段设计规范**](#16.6 字段设计规范)
      • [16.7 索引设计规范](#16.7 索引设计规范)
      • [16.8 SQL使用规范](#16.8 SQL使用规范)
    • 16.生产环境
      • [16.1 my.cnf 配置案例](#16.1 my.cnf 配置案例)
      • 16.2MySQL配置最佳实践
      • [16.3 基础规范](#16.3 基础规范)
      • [16.4 **命名规范**](#16.4 命名规范)
      • [16.5 **表设计规范**](#16.5 表设计规范)
      • [16.6 **字段设计规范**](#16.6 字段设计规范)
      • [16.7 索引设计规范](#16.7 索引设计规范)
      • [16.8 SQL使用规范](#16.8 SQL使用规范)

mysql 数据库

1 数据库原理

1.1 数据的时代

  • 涉及的数据量大

  • 数据不随程序的结束而消失

  • 数据被多个应用程序共享

  • 大数据

数据的分类:

  • 结构化的数据:即有固定格式和有限长度的数据 例如填的表格就是结构化的数据,国籍:中华人民共和国,民族:汉,性别:男,这都叫结构化数据

  • 非结构化的数据:非结构化的数据越来越多,就是不定长、无固定格式的数据,例如网页,有时候非常长,有时候几句话就没了;例如语音,视频都是非结构化的数据

  • 半结构化数据:比如:XML或者HTML的格式的数据

数据库 是一个存储数据的 软件

文件系统软件, 专业的 数据库软件所替代

xfs

ext4

ntfs

word

excel

1.2 数据库的发展史

1.2.1 文件管理系统的缺点
  • 编写应用程序不方便

  • 数据冗余不可避免

  • 应用程序依赖性

  • 不支持对文件的并发访问

  • 数据间联系弱

  • 难以按用户视图表示数据

  • 无安全控制功能

1.2.2 数据库系统发展阶段
  • 萌芽阶段:文件系统

​ 使用磁盘文件来存储数据

  • 初级阶段:第一代数据库

​ 出现了网状模型、层次模型的数据库

  • 中级阶段:第二代数据库

​ 关系型数据库和结构化查询语言

  • 高级阶段:新一代数据库 非关系型数据库

    "关系-对象"型数据库

操作系统是 一类软件的集合 , 其中的核心是内核

数据库的 核心 是dbms

1.3 DBMS 数据库管理系统

  • Database:数据库是数据的汇集,它以一定的组织形式存于存储介质上 表结构, execel 表的集合
  • DBMS:是管理数据库的系统软件,它实现数据库系统的各种功能。是数据库系统的核心
  • DBA:负责数据库的规划、设计、协调、维护和管理等工作 oca ocp ocm
  • Application(应用程序): 指以数据库为基础的应用程序

1.4 数据库管理系统(DBMS)的优点

  • 程序与数据相互独立
  • 相互关联的数据的集合
  • 较少的数据冗余
  • 保证数据的安全、可靠
  • 最大限度地保证数据的正确性
  • 数据可以并发使用并能同时保证一致性

1.5 数据库管理系统的基本功能

  • 数据定义
  • 数据处理
  • 数据安全
  • 数据备份

1.6 数据库系统的架构

  • 单机架构
  • 大型主机/终端架构
  • 主从式架构(C/S)
  • 分布式架构

1.7 各种数据库管理系统

1.7.1 层次数据库
1.7.2 网状数据库
1.7.3 RDBMS关系型数据库
  • Relational Database Management System,关系模型最初由IBM公司的英国计算机科学家埃德加·科德(Edgar F. Codd)于1969年描述,1974年,IBM开始开发系统R,这是一个开发RDBMS原型的研究项目。

  • 然而,第一个商业上可用的RDBMS是甲骨文,于1979年由关系软件(现为甲骨文公司)发布

1.7.3.1关系统型数据库相关概念
  • 关系Relational :关系就是二维表,其中:表中的行、列次序并不重要
  • 行row:表中的每一行,又称为一条记录record
  • 列column:表中的每一列,称为属性,字段,域field
  • 主键Primary key:PK , 用于惟一确定一个记录的字段,一张表只有一个主键且不可以为null
  • 唯一键:Unique key:一个或多个字段的组合,用于唯一确定一个记录的字段,一张小可以有多个U看,而且Uk字段可以为null
  • 域domain:属性的取值范围,如,性别只能是'男'和'女'两个值,人类的年龄只能0-150
1.7.3.2 常用关系数据库

MySQL: MySQL, MariaDB, Percona Server

PostgreSQL: 简称为pgsql,EnterpriseDB

Oracle

MSSQL sql server

DB2 Ibm

磁盘 性能低下

持久化:

把数据永久保存,存 在硬盘上

redis 内存中 速度快 redis 怎么持久化 AOF

1.7.3.3 数据库排名

https://db-engines.com/en/ranking

1.8 关系型数据库理论

1.8.1 实体联系模型E-R

对于大型公司开发项目﹐需要根据产品经理的设计﹐先使用建模工具,如:power designer ,db desinger等这些软件来画出实体-关系模型(E-R模型)

  • 实体Entity:客观存在并可以相互区分的客观事物或抽象事件称为实体,在E-R图中用矩形框表示实体,把实体名写在框内

  • 属性:实体所具有的特征或性质

  • 联系:联系是数据之间的关联集合,是客观存在的应用语义链

    • 实体内部的联系:指组成实体的各属性之间的联系。如职工实体中,职工号和部门经理号之间有一种关联关系

    • 实体之间的联系:指不同实体之间联系。例:学生选课实体和学生基本信息实体之间

    • 实体之间的联系用菱形框表示

    E-R 模型范例:

1.8.2 联系类型

  • 一对一联系(1:1):在表A或表B中创建一个字段﹐存储另一个表的主键值 如: 一个人只有一个身份证
  • 一对多联系(1:n):外键 如: 部门和员工
  • 多对多联系(m:n):增加第三张表 如: 学生和课程
  • select 多表查询

1.8.3 数据的操作

开发工程师 CRUD (增加Create、查询Retrieve或 Read、更新Update、 删除Delete)

  • 数据提取:在数据集合中提取感兴趣的内容。SELECT
  • 数据更新:变更数据库中的数据。INSERT、DELETE、UPDATE

1.8.4 数据库规划流程

  1. 收集数据,得到字段

收集必要且完整的数据项

转换成数据表的字段

!

2 MySQL 历史

MySQL的历史可以追溯到1979年,它的创始人叫作Michael Widenius,他在开发一个报表工具的时候,设计了一套API,后来他的客户要求他的API支持sql语句,他直接借助于mSQL(当时比较牛)的代码,将它集成到自己的存储引擎中。但是他总是感觉不满意,萌生了要自己做一套数据库的想法。

直到1996年,MySQL 1.0发布,Michael Widenius的大女儿的简称就是MY,Michael Widenius大概也是把MySQL当成自己的女儿一样来对待.仅仅过了几个月的时间,1996年10月MySQL 3.11.1当时发布了Solaris的版本,一个月后,linux的版本诞生,从那时候开始,MySQL慢慢的被人所接受。

1999年,Michael Widenius成立了MySQL AB公司,MySQL由个人开发转变为团队开发,2000年使用GPL协议开源。

2001年,MySQL生命中的大事发生了,那就是存储引擎InnoDB的诞生!Oracle在2005年收购了InnoDB,只不过InnoDB一直以来都只能作为第三方插件供用户选择。直到现在,MySQL可以选择的众多存储引擎中,InnoDB依然是第一选择

2008年1月,MySQL AB公司被Sun公司以10亿美金收购,MySQL数据库进入Sun时代。Sun为MySQL的发展提供了绝佳的环境,2008年11月,MySQL 5.1发布,MySQL成为了最受欢迎的小型数据库。

2009年4月,Oracle公司以74亿美元收购Sun公司,MySQL也随之进入Oracle时代。

2010年12月,MySQL 5.5发布,Oracle终于把InnoDB做成了MySQL默认的存储引擎,MySQL从此进入了辉煌时代。

然而,从那之后,Oracle对MySQL的态度渐渐发生了变化,Oracle虽然宣称MySQL依然尊少GPL协议,但却暗地里把开发人员全部换成了Oracle自己人,开源社区再也影响不了MySQL发展的脚步,真正有心做贡献的人也被拒之门外,MySQL随时都有闭源的可能......看着自己辛苦养大的MySQL被Oracle搞成这样,Michael Widenius非常失望,决定在MySQL走向闭源前,将MySQL进行分支化,依然是使用了自己小女儿的名字MariaDB(玛莉亚DB)。MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在维护,采用GPL授权许可 MariaDB的目的是完全兼容MySQL,包括API和命令行,使之能轻松成为MySQL的代替品。在存储引擎方面,使用XtraDB来代替MySQL的InnoDB。MariaDB由MySQL的创始人Michael Widenius主导,由开源社区的大神们进行开发。因此,大家都认为,MariaDB拥有比MySQL更纯正的MySQL血脉。最初的版本更新与MySQL同步,相对MySQL5以后的版本,MariaDB也有相应的5.1~5.5的版本。后来MariaDB终于摆脱了MySQL,它的版本号直接从10.0开始,以自己的步伐进行开发,当然,还是可以对MySQL完全兼容。

复制代码
1979年:TcX公司 Monty Widenius,Unireg
1996年:发布MySQL1.0,Solaris版本,Linux版本
1999年:MySQL AB公司,瑞典
2003年:MySQL 5.0版本,提供视图、存储过程等功能
2008年:Sun公司 以10亿美元收购MySQL
2009年:Oracle公司以 74 亿美元收购 sun 公司
2009年:Monty成立MariaDB

MySQL 的三大主要分支

  • mysql
  • mariadb
  • percona Server

https://www.mysql.com/

http://mariadb.org/

https://www.percona.com

版本演变

MySQL:5.1 --> 5.5 --> 5.6 --> 5.7 ----->6.0 - --->7.0 --> 8.0

MariaDB:5.1 -->5.5 -->10.0--> 10.1 --> 10.2 --> 10.3 --> 10.4 --> 10.5

复制代码
MySQL被Sun收购后,搞了个过渡的6.0版本,没多久就下线了,后来被Oracle收购后,终于迎来了像样的5.6版本,之后就是5.7、8.0版本。由于6.0版本号已被用过,7.x系列版本专用于NDB Cluster,因而新版本号从8.0开始

关系型数据库和非关系型数据库

复制代码
1)描述主流的数据库系统
关系型数据库:
Mysql(Oracle公司) 、 SQL server(微软) 、access(微软公司office产品)
Oracle 、DB2(IBM公司),sybase(sybase) 等等



2)关系型数据库和非关系型数据库的区别
关系数据库:
关系数据库结构是二维数据库表,二维表当中每个字段(列)用来描述对象的一个属性,
每个记录(行)用来描述一个对象的信息(完整信息),关系数据库写到哪里也就是存储在硬盘当中 
读写系统就会受到的IO限制或者瓶颈 

其他
关系型数据库最典型的数据结构是表,由二维表及其之间的联系所组成的一个数据组织
优点:
1、易于维护:都是使用表结构,格式一致;
2、使用方便:SQL语言通用,可用于复杂查询;
3、复杂操作:支持SQL,可用于一个表以及多个表之间非常复杂的查询。
缺点:
1、读写性能比较差,尤其是海量数据的高效率读写;
2、固定的表结构,灵活度稍欠;
3、高并发读写需求,传统关系型数据库来说,硬盘I/O是一个很大的瓶颈。



缓存加速软件
非关系型数据库(NoSQL)
MongoDB 、 Redis(内存数据库/缓存数据库)K-V键值对、与之类似的Memcache,K-V键值对
redis-memecache对比:
相同点:存储高热数据(在内存中高速运行)
不同点:redis可以做持久化保存,可以存储对象


非关系型数据库严格上不是一种数据库,应该是一种数据结构化存储方法的集合,可以是文档或者键值对等。

优点:

1、格式灵活:存储数据的格式可以是key,value形式、文档形式、图片形式等等,文档形式、
图片形式等等,使用灵活,应用场景广泛,而关系型数据库则只支持基础类型。
2、速度快:nosql可以使用硬盘或者随机存储器作为载体,而关系型数据库只能使用硬盘;
3、高扩展性;
4、成本低:nosql数据库部署简单,基本都是开源软件。

缺点:

1、不提供sql支持,学习和使用成本较高;
2、无事务处理;
3、数据结构相对复杂,复杂查询方面稍欠。

3.安装 mysql 及优化

https://www.mysql.com/

3.1 yum安装

去官网下载yum源

老版本

bash 复制代码
[root@localhost ~]# yum info mariadb
可安装的软件包
名称    :mariadb
架构    :x86_64
时期       :1
版本    :5.5.68
发布    :1.el7
大小    :8.8 M
源    :base/7/x86_64
简介    : A community developed branch of MySQL
网址    :http://mariadb.org
协议    : GPLv2 with exceptions and LGPLv2 and BSD
描述    : MariaDB is a community developed branch of MySQL.
         : MariaDB is a multi-user, multi-threaded SQL database server.
         : It is a client/server implementation consisting of a server daemon (mysqld)
         : and many different client programs and libraries. The base package
         : contains the standard MariaDB/MySQL client programs and generic MySQL files.
         
MySQL被Sun收购后,搞了个过渡的6.0版本,没多久就下线了,后来被Oracle收购后,终于迎来了像样的5.6
版本,之后就是5.7、8.0版本。由于6.0版本号已被用过,7.x系列版本专用于NDB Cluster,因而新版本
号从8.0开始。
3.1.1 yum安装5.7版本
bash 复制代码
[root@localhost ~]#yum install mariadb-server -y
[root@localhost ~]#systemctl start mariadb.service
[root@localhost ~]#mysql
[root@localhost ~]#mysql_secure_installation 
#初始化设置  先输入密码 一路回车     




[root@centos7 ~]#tee /etc/yum.repos.d/mysql.repo <<EOF
[mysql]
name=mysql5.7
baseurl=https://mirrors.tuna.tsinghua.edu.cn/mysql/yum/mysql-5.7-community-el7-x86_64/
gpgcheck=0
EOF

清华大学  没有初始密码   5.7.41


[root@centos7 ~]#tee /etc/yum.repos.d/mysql.repo <<EOF
[mysql57-community]
name=MySQL 5.7 Community Server
baseurl=http://repo.mysql.com/yum/mysql-5.7-community/el/7/x86_64/
enabled=1
gpgcheck=0
EOF

官方源   5.7.3.

[root@centos7 ~]#cat >/etc/yum.repos.d/mysql.repo <<EOF
[mysql57-community]
name=MySQL 5.7 Community Server
baseurl=http://repo.mysql.com/yum/mysql-5.7-community/el/7/x86_64/
enabled=1
gpgcheck=0
EOF


http://repo.mysql.com/yum/mysql-5.7-community/el/7/x86_64/

[root@centos7 ~]#yum -y install mysql-community-server
[root@localhost yum.repos.d]# systemctl start mysqld
[root@localhost yum.repos.d]# ss -ntap |grep 3306
[root@localhost yum.repos.d]# mysql -u root -p
Enter password: 
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)

[root@centos7 ~]#grep password /var/log/mysqld.log
[root@localhost yum.repos.d]# mysql -u root -p'+8saq%5+ljzG'
#特殊符号用单引号引起来



myslq    
客户端软件
mysaladmin 




mysql> status
#必须改密码
ERROR 1820 (HY000): You must reset your password using ALTER USER statement before executing this statement.

set global validate_password_policy=0;
set global validate_password_length=1;
#修改密码策略

mysql> alter user root@'localhost' identified by 'Admin@123';
alter user root@'localhost' identified by 'abc123';

mysql> \h
#查看帮助



应用单多线程:
pstree -p
cat /proc/线程id/status
proc 存在内存中

mysql> system hostname
localhost.localdomain
#可以直接使用系统命令
#source 可以调用脚本


mysql> \h, help
mysql> \u,use
mysql> \s,status
mysql> \!,system

mysql [OPTIONS] [database]
命令格式

-A, --no-auto-rehash 禁止补全
-u, --user= 用户名,默认为root
-h, --host= 服务器主机,默认为localhost
-p, --passowrd= 用户密码,建议使用-p,默认为空密码
-P, --port= 服务器端口
-S, --socket= 指定连接socket文件路径
-D, --database= 指定默认数据库
-C, --compress 启用压缩
-e   "SQL" 执行SQL命令
-V, --version 显示版本
-v  --verbose 显示详细信息
--print-defaults 获取程序默认使用的配置

#默认空密码登录
mysql  -uroot  -p

mysql>use mysql #切换数据库
mysql> select database();                   #查看当前数据库
mysql>select user(); #查看当前用户
mysql>SELECT User,Host,Password FROM user;
mysql>system clear #清屏
mysql> ^DBye       #ctrl+d 退出

mysqladmin命令

mysqladmin [OPTIONS] command command...

#查看mysql服务是否正常,如果正常提示mysqld is alive
mysqladmin -u用户 -p密码   ping
mysqladmin -uroot -p123123  ping
#关闭mysql服务,但mysqladmin命令无法开启
mysqladmin -uroot -pcentos shutdown
#创建数据库testdb
mysqladmin -uroot -pcentos   create testdb 
#删除数据库testdb
mysqladmin -uroot -pcentos   drop testdb
#修改root密码
mysqladmin -uroot -pAdmin@123 password 'zhj'
#日志滚动,生成新文件/var/lib/mysql/mariadb-bin.00000N
mysqladmin -uroot -pcentos flush-logs
3.1.2 登录数据库

使用 清华源安装的数据库 默认自带 密码,初始密码在 /var/log/mysql.log

bash 复制代码
[root@centos7 ~]#grep password /var/log/mysqld.log
[root@localhost yum.repos.d]# mysql -u root -p'+8saq%5+ljzG'
#特殊符号用单引号引起来
3.1.3 rpm包安装
bash 复制代码
yum remove  mysql-libs   #卸载 mariadb的安装联系
rpm -ivh mysql-community-common-5.7.44-1.el7.x86_64.rpm 
rpm -ivh mysql-community-libs-5.7.44-1.el7.x86_64.rpm 
rpm -ivh mysql-community-client-5.7.44-1.el7.x86_64.rpm 
rpm -ivh mysql-community-server-5.7.44-1.el7.x86_64.rpm 

3.2 编译安装 mysql

建议:内存4G以上 硬盘空间 大于20G

3.2.1 安装相关依赖包
bash 复制代码
yum -y install gcc gcc-c++ cmake bison bison-devel zlib-devel libcurl-devel libarchive-devel boost-devel   ncurses-devel gnutls-devel libxml2-devel openssl-devel libevent-devel libaio-devel
3.2.2源码编译安装

编译安装说明

利用cmake编译,而利用传统方法,cmake的重要特性之一是其独立于源码(out-of-source)的编译功能,即编译工作可以在另一个指定的目录中而非源码目录中进行,这可以保证源码目录不受任何一次编译的影响,因此在同一个源码树上可以进行多次不同的编译,如针对于不同平台编译编译选项: https://dev.mysql.com/doc/refman/5.7/en/source-configuration-options.html

3.2.3 下载并解压缩源码包
bash 复制代码
tar xf  mysql-boost-5.7.20.tar.gz

[root@localhost opt]#cd mysql-5.7.20/
cmake \
-DCMAKE_INSTALL_PREFIX=/usr/local/mysql \
-DMYSQL_UNIX_ADDR=/usr/local/mysql/mysql.sock \
-DSYSCONFDIR=/etc \
-DSYSTEMD_PID_DIR=/usr/local/mysql \
-DDEFAULT_CHARSET=utf8  \
-DDEFAULT_COLLATION=utf8_general_ci \
-DWITH_INNOBASE_STORAGE_ENGINE=1 \
-DWITH_ARCHIVE_STORAGE_ENGINE=1 \
-DWITH_BLACKHOLE_STORAGE_ENGINE=1 \
-DWITH_PERFSCHEMA_STORAGE_ENGINE=1 \
-DMYSQL_DATADIR=/usr/local/mysql/data \
-DWITH_BOOST=boost \
-DWITH_SYSTEMD=1

#############模块解释#####################
-DCMAKE_INSTALL_PREFIX=/usr/local/mysql \
#指定mysql的安装路径
-DMYSQL_UNIX_ADDR=/usr/local/mysql/mysql.sock \
#指定mysql进程监听套接字文件(数据库连接文件)的存储路径
-DSYSCONFDIR=/etc \
#指定配置文件的存储路径
-DSYSTEMD_PID_DIR=/usr/local/mysql \
#指定进程文件的存储路径
-DDEFAULT_CHARSET=utf8  \
#指定默认使用的字符集编码,如utf8
-DDEFAULT_COLLATION=utf8_general_ci \
#指定默认使用的字符集校对规则
-DWITH_INNOBASE_STORAGE_ENGINE=1 \
#安装INNOBASE存储引擎
-DWITH_ARCHIVE_STORAGE_ENGINE=1 \
#安装ARCHIVE存储引擎
-DWITH_BLACKHOLE_STORAGE_ENGINE=1 \
#安装BLACKHOLE存储引擎
-DWITH_PERFSCHEMA_STORAGE_ENGINE=1 \
#安装FEDERATED存储引擎
-DMYSQL_DATADIR=/usr/local/mysql/data \
#指定数据库文件的存储路径
-DWITH_BOOST=boost \
#指定boost的路径,
-DWITH_SYSTEMD=1
#生成便于systemctl管理的文件
#############模块解释#####################


make -j2
make install

4、数据库目录进行权限调整
[root@localhost mysql-5.7.20]#chown -R mysql:mysql /usr/local/mysql/

5、调整配置文件
[root@localhost mysql-5.7.20]#vi /etc/my.cnf
[client]
port = 3306
default-character-set=utf8
socket = /usr/local/mysql/mysql.sock

[mysql]
port = 3306
default-character-set=utf8
socket = /usr/local/mysql/mysql.sock

[mysqld]
user = mysql
basedir = /usr/local/mysql
datadir = /usr/local/mysql/data
port = 3306
character_set_server=utf8
pid-file = /usr/local/mysql/mysqld.pid
socket = /usr/local/mysql/mysql.sock
server-id = 1

sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_AUTO_VALUE_ON_ZERO,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,PIPES_AS_CONCAT,ANSI_QUOTES


NO_ENGINE_SUBSTITUTION
如果需要的存储引擎被禁用或未编译,那么抛出错误。不设置此值时,用默认的存储引擎替代,并抛出一个异常
STRICT_TRANS_TABLES
在该模式下,如果一个值不能插入到一个事务表中,则中断当前的操作,对非事务表不做限制
NO_AUTO_CREATE_USER
禁止:GRANT创建密码为空的用户
NO_AUTO_VALUE_ON_ZERO
mysql中的自增长列可以从o开始。默认情况下自增长列是从1开始的,如果你插入值为0的数据会报错
NO_ZERO_IN_DATE
mysql数据库不允许插入零日期,插入零日期会抛出错误而不是警告
ERROR_FOR_DIVISION_BY_ZERO
在INSERT或UPDATE过程中,如果数据被零除,则产生错误而非警告。默认情况下数据被零除时MysQL返回NULL
IPES_AS_CONCAT
将"||"视为字符串的连接操作符而非或运算符,这和oracle数据库是一样的,
ANSI QUOTES
启用ANSI QUOTES后,不能用双引号来引用字符串,因为它被解释为识别符

[root@localhost mysql-5.7.20]#chown mysql:mysql /etc/my.cnf
#改变属主 属组


6、设置环境变量
echo 'PATH=/usr/local/mysql/bin:/usr/local/mysql/lib:$PATH' >> /etc/profile
echo 'export PATH' >> /etc/profile
source /etc/profile


7、初始化数据库
cd /usr/local/mysql/

bin/mysqld \
--initialize-insecure \
--user=mysql \
--basedir=/usr/local/mysql \
--datadir=/usr/local/mysql/data

cp usr/lib/systemd/system/mysqld.service /usr/lib/systemd/system/

8、数据库开启自启、 关闭、状态 
systemctl enable mysqld
systemctl start mysqld
systemctl stop mysqld
systemctl status mysqld
netstat -anpt | grep 3306


9、设置Mysql密码

mysqladmin -u root -p password
#开始初始密码为空  回车即可   然后输入新密码


update mysql.user set authentication_string=password('123123') where user='root' and host='127.0.0.1' or host='localhost';
update mysql.user set authentication_string=password('newpassword') where user='root' and host='127.0.0.1' or host='localhost';



10、登录数据库
mysql -u root -p 



#################提示:#############
如果出错,执行rm -f CMakeCache.txt
###################################
复制代码
cmake . \
-DCMAKE_INSTALL_PREFIX=/apps/mysql \
-DMYSQL_DATADIR=/data/mysql/ \
-DSYSCONFDIR=/etc/ \
-DMYSQL_USER=mysql \
-DWITH_INNOBASE_STORAGE_ENGINE=1 \
-DWITH_ARCHIVE_STORAGE_ENGINE=1 \
-DWITH_BLACKHOLE_STORAGE_ENGINE=1 \
-DWITH_PARTITION_STORAGE_ENGINE=1 \
-DWITHOUT_MROONGA_STORAGE_ENGINE=1 \
-DWITH_DEBUG=0 \
-DWITH_READLINE=1 \
-DWITH_SSL=system \
-DWITH_ZLIB=system \
-DWITH_LIBWRAP=0 \
-DENABLED_LOCAL_INFILE=1 \
-DMYSQL_UNIX_ADDR=/data/mysql/mysql.sock \
-DDEFAULT_CHARSET=utf8 \
-DDEFAULT_COLLATION=utf8_general_ci \
-DWITH_BOOST=/usr/local/src/mysql/boost

3.3二进制安装 mysql5.7

1准备用户
bash 复制代码
groupadd -r  -g  306 mysql
useradd  -r  -g  306 -u 306 -d /data/mysql mysql
2. 准备数据目录,建议使用逻辑卷
bash 复制代码
#可选做,后面的脚本mysql_install_db可自动生成此目录
mkdir /data/mysql   -p
chown mysql:mysql /data/mysql
3.准备二进制程序
bash 复制代码
tar xf mysql-5.7.44-linux-glibc2.12-x86_64.tar.gz 
ln -s /data/mysql-5.7.44-linux-glibc2.12-x86_64   /usr/local/mysql
4.准备配置文件
bash 复制代码
cp /etc/my.cnf{,.bak}
vim /etc/my.cnf
[mysqld]
datadir=/data/mysql
skip_name_resolve=1
socket=/data/mysql/mysql.sock        
log-error=/data/mysql/mysql.log
pid-file=/data/mysql/mysql.pid
[client]
socket=/data/mysql/mysql.sock
5 创建数据库文件生成root空密码
bash 复制代码
mysqld --initialize-insecure --user=mysql --datadir=/data/mysql


# 生成随机密码
mysqld --initialize   --user=mysql --datadir=/data/mysql
6 准备服务脚本,并启动服务
bash 复制代码
cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld
chkconfig --add mysqld
service mysqld start

systemctl  start  mysqld   
7 PATH路径
bash 复制代码
echo 'PATH=/usr/local/mysql/bin:$PATH' > /etc/profile.d/mysql.sh
. /etc/profile.d/mysql.sh
8 安全初始化
bash 复制代码
/usr/local/mysql/bin/mysql_secure_installation
9测试登录
复制代码
mysql -uroot
10 一键安装脚本
复制代码

3.4 客户端命令行优化操作

3.4.1 生成提示符
bash 复制代码
#查看mysql版本
[root@centos7 ~]#mysql -V

#修改提示符


man mysql
[root@localhost ~]#vim /etc/my.cnf                       
[mysql]
prompt=(\\u@\\h) [\\d]>\\_


mycli
3.4.2自动补全

yum安装可以 编译安装有问题

bash 复制代码
[mysql]
prompt=(mysql) [\\d]>\\_
auto-rehash
#自动补全 只能补全敲过的命令

3.5 客户端程序

  • mysql: 交互式或非交互式的CLI工具
  • mysqldump:备份工具,基于mysql协议向mysqld发起查询请求,并将查得的所有数据转换成 insert等写操作语句保存文本文件中
  • mysqladmin:基于mysql协议管理mysqld
  • mysqlimport:数据导入工具
  • MyISAM存储引擎的管理工具:
  • myisamchk:检查MyISAM库
  • myisampack:打包MyISAM表,只读
3.5.1 mysql:

客户端命令:本地执行,每个命令都完整形式和简写格式

mysql 复制代码
mysql> \h, help
mysql> \u,use
mysql> \s,status
mysql> \!,system

mysql命令使用格式

复制代码
mysql [OPTIONS] [database]

mysql客户端常用选项:

复制代码
-A, --no-auto-rehash 禁止补全

-u, --user= 用户名,默认为root
-h, --host= 服务器主机,默认为localhost
-p, --passowrd= 用户密码,建议使用-p,默认为空密码
-P, --port= 服务器端口
mysql  -uroot    -h192.168.91.100     -p'密码'  


-S, --socket= 指定连接socket文件路径
-D, --database= 指定默认数据库
-C, --compress 启用压缩
-e   "SQL" 执行SQL命令
-V, --version 显示版本
-v  --verbose 显示详细信息
--print-defaults 获取程序默认使用的配置

运行mysql命令:

mysql 复制代码
mysql> use mysql #切换数据库
mysql> select database();             #查看当前数据库
mysql> select user(); #查看当前用户
mysql> SELECT User,Host,Password FROM user;
mysql> system clear #清屏
mysql> quit      #ctrl+d 退出
3.5.2 mysqladmin命令

mysqladmin 命令格式

复制代码
mysqladmin [OPTIONS] command command....

例子

mysql 复制代码
#查看mysql服务是否正常,如果正常提示mysqld is alive
mysqladmin -uroot -pcentos   ping
#关闭mysql服务,但mysqladmin命令无法开启
mysqladmin -uroot -pcentos shutdown
#创建数据库testdb
mysqladmin -uroot -pcentos   create testdb 
#删除数据库testdb
mysqladmin -uroot -pcentos   drop testdb
#修改root密码
mysqladmin -uroot -pcentos password '123123'
#日志滚动,生成新文件/var/lib/mysql/mariadb-bin.00000N
mysqladmin -uroot -pcentos flush-logs

mysqladmin -uroot -pcentos status;
mysql 复制代码
create user test@'192.168.%.%' identified by '123123';
grant all privileges on *.* to test@'192.168.%.%' identified by '123123';
3.6 用户账号

mysql用户账号由两部分组成:

http 复制代码
'USERNAME'@'HOST'
zhou@'10.0.0.100'     只有100能访问后面单引号必加
zhou@'10.0.0.%'

说明:

HOST限制此用户可通过哪些远程主机连接mysql服务器

支持使用通配符:

http 复制代码
% 匹配任意长度的任意字符,相当于shell中*, 示例: 172.16.0.0/255.255.0.0 或 172.16.%.%
_ 匹配任意单个字符,相当于shell中?

4 多实例

  • 什么是数据库多实例

多实例类似微信双开,端口号类比微信账号,数据库类比聊天窗口,表类比聊天记录MySQL多实例就是在一台服务器上同时开启多个不同的服务端口(如:3306、3307、3308等),同时运行多个MySQL服务进程,这些服务进程通过不同的Socket监听不同的服务端口来提供服务。多实例可能是MySQL的不同版本,也可能是MySQL的同一版本实现

  • 多实例的好处

可有效利用服务器资源。当单个服务器资源有剩余时,可以充分利用剩余资源提供更多的服务,且可以实现资源的逻辑隔离节约服务器资源。例如公司服务器资源紧张,但是数据库又需要各自尽量独立的提供服务,并且还需要到主从复制等技术,多实例就是最佳选择

  • 多实例弊端

存在资源互相抢占的问题。比如:当某个数据库实例并发很高或者SQL查询慢时,整个实例会消耗大量的CPU、磁盘I/O等资源,导致服务器上面其他的数据库实例在提供服务的质量也会下降,所以具体的需求要根据自己的实际情况而定。

bash 复制代码
[root@localhost ~]# yum -y install mariadb-server
[root@localhost ~]#mkdir -pv /mysql/{3306,3307,3308}/{data,etc,socket,log,bin,pid}
[root@localhost ~]# chown -R mysql.mysql /mysql
[root@localhost ~]# tree -d /mysql/
[root@localhost ~]#mysql_install_db --user=mysql --datadir=/mysql/3306/data
#生成数据库文件重复三次
[root@localhost ~]#mysql_install_db --user=mysql --datadir=/mysql/3307/data
[root@localhost ~]#mysql_install_db --user=mysql --datadir=/mysql/3308/data
[root@localhost ~]#vim /mysql/3306/etc/my.cnf
#编辑配置文件
[mysqld]
port=3306
datadir=/mysql/3306/data
socket=/mysql/3306/socket/mysql.sock
log-error=/mysql/3306/log/mysql.log
pid-file=/mysql/3306/pid/mysql.pid
[root@localhost ~]#sed 's/3306/3307/' /mysql/3306/etc/my.cnf > /mysql/3307/etc/my.cnf
[root@localhost ~]#sed 's/3306/3308/' /mysql/3306/etc/my.cnf > /mysql/3308/etc/my.cnf

#######准备启动脚本
[root@localhost ~]#vim /mysql/3306/bin/mysqld
#!/bin/bash

port=3306
mysql_user="root"
mysql_pwd=""
cmd_path="/usr/bin"
mysql_basedir="/mysql"
mysql_sock="${mysql_basedir}/${port}/socket/mysql.sock"

function_start_mysql()
{
    if [ ! -e "$mysql_sock" ];then
      printf "Starting MySQL...\n"
      ${cmd_path}/mysqld_safe --defaults-file=${mysql_basedir}/${port}/etc/my.cnf  &> /dev/null  &
    else
      printf "MySQL is running...\n"
      exit
    fi
}


function_stop_mysql()
{
    if [ ! -e "$mysql_sock" ];then
       printf "MySQL is stopped...\n"
       exit
    else
       printf "Stoping MySQL...\n"
       ${cmd_path}/mysqladmin -u ${mysql_user} -p${mysql_pwd} -S ${mysql_sock} shutdown
   fi
}


function_restart_mysql()
{
    printf "Restarting MySQL...\n"
    function_stop_mysql
    sleep 2
    function_start_mysql
}

case $1 in
start)
    function_start_mysql
;;
stop)
    function_stop_mysql
;;
restart)
    function_restart_mysql
;;
*)
    printf "Usage: ${mysql_basedir}/${port}/bin/mysqld {start|stop|restart}\n"
esac



[root@localhost ~]#chmod +x /mysql/3306/bin/mysqld 
#重复上述过程,分别建立3307,3308的启动脚本   注意端口号

#######启动服务
[root@localhost ~]#/mysql/3306/bin/mysqld start
[root@localhost ~]#/mysql/3307/bin/mysqld start
[root@localhost ~]#/mysql/3308/bin/mysqld start
[root@localhost ~]#ss -ntl

#######登录实例
[root@localhost ~]#/mysql/3308/bin/mysqld start
#两种连接方法
[root@localhost ~]#mysql -h127.0.0.1 -P3308
[root@localhost ~]#mysql -uroot -S /mysqld/3306/socket/mysql.sock
#确认连接的端口

####关闭数据库,需要手动输入root的密码
[root@localhost ~]#/mysql/3308/bin/mysqld stop
Stoping MySQL...
Enter password: 
[root@localhost ~]#/mysql/3308/bin/mysqld start
Starting MySQL

##########修改密码
[root@localhost ~]#mysqladmin -uroot -S /mysql/3306/socket/mysql.sock password 
'123123' 
[root@localhost ~]#mysqladmin -uroot -S /mysql/3307/socket/mysql.sock password 
'123123' 
[root@localhost ~]#mysqladmin -uroot -S /mysql/3308/socket/mysql.sock password 
'123123'


#####测试连接
[root@localhost ~]#mysql -uroot -p -S /mysql/3306/socket/mysql.sock #提示输入口令才
能登录


######开机启动
[root@localhost ~]#vim /etc/rc.d/rc.local
#在最后一行加下面内容   开机自启动文件
for i in {3306..3308};do /mysql/$i/bin/mysqld start;done
[root@localhost ~]#chmod +x /etc/rc.d/rc.local

5 安装 mycli 插件 客户端工具

客户端工具和mysql, 根据实际环境升级python

bash 复制代码
[root@localhost opt]#yum -y install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel libpcap-devel xz-devel libffi-devel
[root@localhost opt]#tar zxvf Python-3.7.7_.tgz
[root@localhost Python-3.7.7]#cd Python-3.7.7/
[root@localhost Python-3.7.7]#./configure --prefix=/usr/local/Python-3.7.7/
[root@localhost Python-3.7.7]#make  -j2 &&   make install
[root@localhost Python-3.7.7]#make install
[root@localhost Python-3.7.7]#ln -s  /usr/local/Python-3.7.7/bin/python3.7  /usr/bin/python37
[root@localhost Python-3.7.7]#
ln -s  /usr/local/Python-3.7.7/bin/python3.7  /usr/bin/python37
ln -s /usr/local/Python-3.7.7/bin/pip3.7 /usr/bin/pip37
[root@localhost Python-3.7.7]#pip37 install --upgrade pip -i http://mirrors.aliyun.com/pypi/simple --trusted-host mirrors.aliyun.com
[root@localhost Python-3.7.7]#pip37 install mycli -i http://mirrors.aliyun.com/pypi/simple --trusted-host mirrors.aliyun.com

[root@localhost Python-3.7.7]#ln -s /usr/local/Python-3.7.7/bin/mycli /usr/bin/mycli


[root@localhost Python-3.7.7]#mycli -u root -p 123123






[root@localhost ~]#vim /etc/my.cnf                       
[mysql]
prompt=(\\u@\\h) [\\d]>\\_
auto-rehash



wget https://www.python.org/ftp/python/3.9.0/Python-3.9.0.tgz

图形化界面:

bash 复制代码
[mysqld]
skip_grant_tables

6基本操作

SQL Structured Query Language 结构化查询语言是对IBM公司San Jose,California研究实验室的埃德加·科德的关系模型的第一个商业化语言实现,这一模型在其1970年的一篇具有影响力的论文《一个对于大型共享型数据库的关系模型》中被描述。尽管SQL并非完全按照科德的关系模型设计,但其依然成为最为广泛运用的数据库语言1970年代初,由埃德加·科德发表将资料组成表格的应用原则(Codd's Relational Algebra)

1974年,同一实验室的D.D.Chamberlin和R.F. Boyce对Codd's Relational Algebra在研制关系数据库管理系统System R中,研制出一套规范语言-SEQUEL(Structured English Query Language)1976年11月的IBM Journal of R&D上公布新版本的SQL(叫SEQUEL/2)。1980年改名为SQL1979年ORACLE公司首先提供商用的SQL,IBM公司在DB2和SQL/DS数据库系统中也实现了SQL1986年10月美国国家标准学会ANSI采用SQL作为关系数据库管理系统的标准语言(ANSI X3. 135-1986)1987年成为国际标准化组织(ISO)采纳为国际标准1989年美国ANSI采纳在ANSI X3.135-1989报告中定义的关系数据库管理系统的SQL标准语言,称为ANSI SQL 89

后续SQL标准经过了一系列的增订,加入了大量新特性,有各种版本: ANSI SQL,SQL-1986, SQL-1989, SQL-1992, SQL-1999, SQL-2003,SQL-2008, SQL-2011目前,所有主要的关系数据库管理系统支持某些形式的SQL,大部分数据库至少遵守ANSI SQL89标准虽然有这一标准的存在,但大部分的SQL代码在不同的数据库系统中并不具有完全的跨平台性业内标准微软和Sybase的T-SQL,Oracle的PL/SQL

6.1 SQL分类

  • 数据库:database
  • 表:table,行:row 列:column
  • 索引:index
  • 视图:view
  • 存储过程:procedure
  • 存储函数:function
  • 触发器:trigger
  • 事件调度器:event scheduler,任务计划
  • 用户:user
  • 权限:privilege

SQL 语言规范

  • 在数据库系统中,SQL 语句不区分大小写,建议用大写
  • SQL语句可单行或多行书写,默认以 " ; " 结尾
  • 关键词不能跨多行或简写 select drop create
  • 用空格和TAB 缩进来提高语句的可读性
  • 子句通常位于独立行,便于编辑,提高可读性

数据库对象和命名

数据库的组件(对象):

数据库、表、索引、视图、用户、存储过程、函数、触发器、事件调度器等

命名规则:

必须以字母开头,后续可以包括字母,数字和三个特殊字符(# _ $)

不要使用MySQL的保留字,table select show databases

开启事务

命令开启事务功能

create database;

commit 提交事务 成功

oracle 手动 提交事务

SQL语句分类

  • DDL: Data Defination Language 数据定义语言

CREATE,DROP,ALTER

  • DML: Data Manipulation Language 数据操纵语言

INSERT,DELETE,UPDATE

软件开发:CRUD

  • DQL:Data Query Language 数据查询语言

SELECT

  • DCL:Data Control Language 数据控制语言

GRANT,REVOKE

  • TCL:Transaction Control Language 事务控制语言

COMMIT,ROLLBACK,SAVEPOINT

bash 复制代码
#DDL: Data Defination Language 数据定义语言
CREATE,DROP,ALTER

#DML: Data Manipulation Language 数据操纵语言
INSERT,DELETE,UPDATE

#DQL:Data Query Language 数据查询语言
SELECT 


#DCL:Data Control Language 数据控制语言
GRANT,REVOKE,COMMIT,ROLLBACK


SELECT *                 #SELECT子句
FROM products             #FROM子句
WHERE price>666         #WHERE子句

6.2 查看帮助信息

bash 复制代码
mysql> help create
#help 后面跟上具体命令可以查看帮助

6.3 查看支持的字符集

mysql 复制代码
mysql> show charset;
+----------+---------------------------------+---------------------+--------+
| Charset  | Description                     | Default collation   | Maxlen |
+----------+---------------------------------+---------------------+--------+
| big5     | Big5 Traditional Chinese        | big5_chinese_ci     |      2 |
| dec8     | DEC West European               | dec8_swedish_ci     |      1 |
| cp850    | DOS West European               | cp850_general_ci    |      1 |
| hp8      | HP West European                | hp8_english_ci      |      1 |
| koi8r    | KOI8-R Relcom Russian           | koi8r_general_ci    |      1 |
| latin1   | cp1252 West European            | latin1_swedish_ci   |      1 |
| latin2   | ISO 8859-2 Central European     | latin2_general_ci   |      1 |
| swe7     | 7bit Swedish                    | swe7_swedish_ci     |      1 |

####默认支持拉丁文

utf8     | UTF-8 Unicode   
#阉割版的

utf8mb4  | UTF-8 Unicode 
#真实的版本
6.3.1 查看默认使用的 字符集
mysql 复制代码
mysql> show variables like 'char%';
#查看当前默认字符
+--------------------------+----------------------------------+
| Variable_name            | Value                            |
+--------------------------+----------------------------------+
| character_set_client     | utf8                             |
| character_set_connection | utf8                             |
| character_set_database   | utf8                             |
| character_set_filesystem | binary                           |
| character_set_results    | utf8                             |
| #character_set_server    | utf8#默认使用的字符集    			 |
| character_set_system     | utf8                             | 
| character_sets_dir       | /usr/local/mysql/share/charsets/ |
+--------------------------+-------------------------

新建的数据库默认使用的是拉丁字符集

mysql 复制代码
mysql> create database test;
#新建数据库
Query OK, 1 row affected (0.00 sec)

mysql> show create database test;
#查看数据库的属性
+----------+-----------------------------------------------------------------+
| Database | Create Database                                                 |
+----------+-----------------------------------------------------------------+
| test     | CREATE DATABASE `test` /*!40100 DEFAULT CHARACTER SET latin1 */ |
+----------+-----------------------------------------------------------------+
1 row in set (0.00 sec)
6.3.2修改默认字符集
bash 复制代码
修改字符集
vim /etc/my.cnf
[mysqld]
character-set-server=utf8mb4

show create database test;

修改完后 再新建的数据库的字符集就会改变

mysql 复制代码
mysql> create database test1;
Query OK, 1 row affected (0.00 sec)

mysql> show database test1;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'database test1' at line 1
mysql> show create database test1;
+----------+-------------------------------------------------------------------+
| Database | Create Database                                                   |
+----------+-------------------------------------------------------------------+
| test1    | CREATE DATABASE `test1` /*!40100 DEFAULT CHARACTER SET utf8mb4 */ |
+----------+-------------------------------------------------------------------+
1 row in set (0.00 sec)

6.4 管理数据库

6.4.1 创建数据库

语法:

mysql 复制代码
CREATE DATABASE|SCHEMA [IF NOT EXISTS] 'DB_NAME'  CHARACTER SET 'character set name'  COLLATE 'collate name';

实际例子:

6.4.1.1 新建数据库
mysql 复制代码
mysql> create database db1;
#建立数据库  db1

mysql> show create database db1;
#查看数据库的基础信息
6.4.1.2 新建数据库 指定字符集
mysql 复制代码
mysql> create database db2 character set 'utf8';

mysql> create database db2 charset=utf8;
#指定utf8 字符集

mysql> show create database db1;
#查看数据库的基础信息

mysql> create database zabbix character set utf8 collate utf8_bin;         
#字符集 utf8  不区分大小写    collate utf8_bin这个排序规则  可以区分  
6.4.1.3 if no exists 先判断数据库是否存在
mysql 复制代码
mysql> create database IF NOT EXISTS db1;
Query OK, 1 row affected, 1 warning (0.00 sec)

mysql> show warnings;
#可以查看警告信息
+-------+------+----------------------------------------------+
| Level | Code | Message                                      |
+-------+------+----------------------------------------------+
| Note  | 1007 | Can't create database 'db1'; database exists |
+-------+------+----------------------------------------------+
1 row in set (0.00 sec)
6.4.1.4 生产例子
mysql 复制代码
mysql> create database zabbix character set utf8 collate utf8_bin;
6.4.2 修改数据库

当建立好数据库后可以使用 ALTER 命令修改

mysql 复制代码
ALTER DATABASE DB_NAME character set utf8;
#修改字符集
[root@node2 db2]#cat /usr/local/mysql/data/db2/db.opt 
#查看当前字符集   yum  安装可以用find 查找同名的数据库
default-character-set=latin1
default-collation=latin1_swedish_ci

例子:

mysql 复制代码
mysql> alter database school character set utf8 collate utf8_bin;
#修改默认字符集 和 排序规则





 mysql> create database zabbix character set utf8 collate utf8_bin;
6.4.3删除数据库

语法:

复制代码
格式:
DROP DATABASE|SCHEMA [IF EXISTS] 'DB_NAME';

例子:

mysql 复制代码
mysql> drop database db1;
You're about to run a destructive command.
Do you want to proceed? (y/n): y
Your call!
Query OK, 0 rows affected
Time: 0.005s
mysql> show databases;

例子:

mysql 复制代码
[root@localhost mysql]#cd /home/mysql/
#数据库其实 就是一个文件夹,删除数据库等于删除文件夹
[root@localhost mysql]#ls
auto.cnf  db2      ib_logfile0  localhost.localdomain.err  mysql       performance_schema  test
db1       ibdata1  ib_logfile1  localhost.localdomain.pid  mysql.sock  school
6.4.4查看数据库列表
mysql 复制代码
SHOW DATABASES;

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |#系统自带数据库  类似管理数据库
| bbs                |
| db2                |
| db3                |
| kgc                |
| mysql              |
| performance_schema |
| school             |
| sys                |
+--------------------+
9 rows in set
Time: 0.010s

例子:

mysql 复制代码
(mysql)[school]> show create database db1;
+----------+--------------------------------------------------------------+
| Database | Create Database                                              |
+----------+--------------------------------------------------------------+
| db1      | CREATE DATABASE `db1` /*!40100 DEFAULT CHARACTER SET utf8 */ |
+----------+--------------------------------------------------------------+
1 row in set (0.00 sec)



表结构   字段  

学号 数据类型 修饰符   姓名    年龄    性别  电话  
6.4.5 数据类型

数据类型

  • 数据长什么样
  • 数据需要多少空间来存放

数据类型

  • 系统内置数据类型
  • 用户定义数据类型

MySQL支持多种内置数据类型

  • 数值类型

  • 日期/时间类型 yy-mm-dd-

  • 字符串(字符)类型

数据类型参考链接

name

http 复制代码
https://dev.mysql.com/doc/refman/8.0/en/data-types.html

选择正确的数据类型对于获得高性能至关重要,三大原则:

  1. 更小的通常更好,尽量使用可正确存储数据的最小数据类型

  2. 简单就好,简单数据类型的操作通常需要更少的CPU周期

  3. 尽量避免NULL,包含为NULL的列,对MySQL更难优化

6.4.5.1 整数型
  • tinyint(m) 1个字节 范围(-128~127) 有一个正或负的表示符

  • smallint(m) 2个字节 范围(-32768~32767)

  • mediumint(m) 3个字节 范围(-8388608~8388607)

  • int(m) 4个字节 范围(-2147483648~2147483647)

  • bigint(m) 8个字节 范围(±9.22*10的18次方)

上述数据类型,如果加修饰符unsigned后,则最大值翻倍

如:tinyint unsigned的取值范围为(0~255)

6.4.5.2 浮点型(float和double),近似值
  • float(m,d) 单精度浮点型 8位精度(4字节) m总个数,d小数位, 注意: 小数点不占用总个数

  • double(m,d) 双精度浮点型16位精度(8字节) m总个数,d小数位, 注意: 小数点不占用总个数

设一个字段定义为float(6,3),如果插入一个数123.45678,实际数据库里存的是123.457,但总个数还以实际为准,即6位

6.4.5.3 定点数

在数据库中存放的是精确值,存为十进制 decimal(5.2) 100.01 - 999.99

格式 decimal(m,d) 表示 最多 m 位数字,其中 d 个小数,小数点不算在长度内

比如: DECIMAL(6,2) 总共能存6位数字,末尾2位是小数,字段最大值 9999.99 (小数点不算在长度内)

参数m<65 是总个数,d<30且 d<m 是小数位

MySQL5.0和更高版本将数字打包保存到一个二进制字符串中(每4个字节存9个数字)。

例如: decimal(18,9)小数点两边将各存储9个数字,一共使用9个字节:其中,小数点前的9个数字用4个字节,小数点后的9个数字用4个字节,小数点本身占1个字节浮点类型在存储同样范围的值时,通常比decimal使用更少的空间。float使用4个字节存储。double占用8个字节

因为需要额外的空间和计算开销,所以应该尽量只在对小数进行精确计算时

6.4.5.4 字符串

char(n) 固定长度,最多255个字符,注意不是字节如果超过限制 1是不让你录入, 2是将多余部分截断

varchar(n) 可变长度,最多65535个字符

tinytext 可变长度,最多255个字符

text 可变长度,最多65535个字符

mediumtext 可变长度,最多2的24次方-1个字符

longtext 可变长度,最多2的32次方-1个字符

BINARY(M) 固定长度,可存二进制或字符,长度为0-M字节

VARBINARY(M) 可变长度,可存二进制或字符,允许长度为0-M字节

内建类型:ENUM枚举, SET集合

char和varchar的比较:

参考:https://dev.mysql.com/doc/refman/8.0/en/char.html

name vachar(4) char 固定长度字符 varchar(4)

name 性别(男女)

1.char(n) 若存入字符数小于n,则以空格补于其后,查询之时再将空格去掉,所以char类型存储的字符串末尾不能有空格,varchar不限于此

2.char(n) 固定长度,char(4)不管是存入几个字符,都将占用4个字节,varchar是存入的实际字符数+1个字节(n< n>255),所以varchar(4),存入3个字符将占用4个字节

3.char类型的字符串检索速度要比varchar类型的快

面试题:varchar(50) 能存放几个 UTF8 编码的汉字?

复制代码
mysql 5.0以上版本 varchar(50) 指的是50字符,无论存放的是数字、字母还是 utf8 编码的汉字,都可以存放50个
学号(int ) 姓名(varchar10 not null unsinged ) 年龄(int)
1
2
3

id primary key

6.4.5.6修饰符 修饰数据的

适用所有类型的修饰符:

名称 含义
NULL 数据列可包含NULL值,默认值
NOT NULL 数据列不允许包含NULL值,*为必填选项
DEFAULT 默认值
PRIMARY KEY 主键,所有记录中此字段的值不能重复,且不能为NULL 一张表中只有一个主键
UNIQUE KEY 唯一键,所有记录中此字段的值不能重复,但可以为NULL
CHARACTER SET name 指定一个字符集

适用数值型的修饰符:

名称 作用
AUTO_INCREMENT 自动递增,适用于整数类型
UNSIGNED 无符号

建立表

mysql 复制代码
(mysql)[school]> help create table
#查看帮助
Name: 'CREATE TABLE'
Description:
Syntax:
CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name
    (create_definition,...)
    [table_options]
    [partition_options]

CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name
    [(create_definition,...)]
    [table_options]
    ..............................................................

URL: http://dev.mysql.com/doc/refman/5.6/en/create-table.html
6.4.6表操作
查看数据库结构
mysql 复制代码
#查看数据库
show create database db1;



#选择数据库,切换库类似于cd
show tables;
show tables in mysql;


####查看表结构(字段)####
格式:describe [数据库名.]表名;
desc user;
desc servers;
#查看表结构

desc mysql.servers;
#不想先使用数据库可以使用上面的

例子:

mysql 复制代码
desc student;




show create table student;

show tables;

show table status like 'student';
show table status like 'student'\G;
#分行
4.5.2 新建表
mysql 复制代码
create   table  student  (id int , name  varchar(10), gender char(2),phone varchar(11));



###2.创建新的表####
create table 表名 (字段1 数据类型,字段2 数据类型[,...] [,PRIMARY KEY (主键名)]);
#主键一般选择代表唯一性的字段不允许为空值(null),且一个表只能有一个主键###

例子:

mysql 复制代码
create table info (id int NOT NULL,name char(10) NOT NULL, age int, phone int
PRIMARY KEY (id) );
主键

create database hyf;
use hyf;
 create table student (id smallint unsigned primary key auto_increment, name varchar(10), age tinyint unsigned,gender enum('M','F') default 'M' );

unsigned
unsigned:取消负数
primary  key:主键
auto_increment: 自增长
enum('M','F'):多选 
default 'M':默认值为 M


insert student (name,age) values('ben',19);
#加入数据



insert student values();
#加入空字段
select * from student;
#查找 会发现多一条空记录

desc student;




show create table student;

show tables;

show table status like 'students';
show table status like 'student'\G;
#分行
4.5.3 修改表结构

alter 添加字段

例子:

mysql 复制代码
mysql [db1]> alter table student add   phone char(11) not null ;
             命令字  命令字  表名   关键字  子段名称字段属性 
  
mysql [db1]> desc student;
+--------+----------------------+------+-----+---------+----------------+
| Field  | Type                 | Null | Key | Default | Extra          |
+--------+----------------------+------+-----+---------+----------------+
| id     | smallint(5) unsigned | NO   | PRI | NULL    | auto_increment |
| name   | varchar(10)          | YES  |     | NULL    |                |
| age    | tinyint(3) unsigned  | YES  |     | NULL    |                |
| gender | enum('M','F')        | YES  |     | M       |                |
| phone  | char(11)             | NO   |     | NULL    |                |
+--------+----------------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)

change 修改字段 名称

例子:

mysql 复制代码
mysql [db1]> alter table student change phone mobile char(11);
mysql [db1]> desc student;
+--------+----------------------+------+-----+---------+----------------+
| Field  | Type                 | Null | Key | Default | Extra          |
+--------+----------------------+------+-----+---------+----------------+
| id     | smallint(5) unsigned | NO   | PRI | NULL    | auto_increment |
| name   | varchar(10)          | YES  |     | NULL    |                |
| age    | tinyint(3) unsigned  | YES  |     | NULL    |                |
| gender | enum('M','F')        | YES  |     | M       |                |
| mobile | char(11)             | YES  |     | NULL    |                |
+--------+----------------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)

drop 删除字段

例子:

mysql 复制代码
mysql [db1]> alter table student drop mobile;
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql [db1]> desc student;
+--------+----------------------+------+-----+---------+----------------+
| Field  | Type                 | Null | Key | Default | Extra          |
+--------+----------------------+------+-----+---------+----------------+
| id     | smallint(5) unsigned | NO   | PRI | NULL    | auto_increment |
| name   | varchar(10)          | YES  |     | NULL    |                |
| age    | tinyint(3) unsigned  | YES  |     | NULL    |                |
| gender | enum('M','F')        | YES  |     | M       |                |
+--------+----------------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)
4.5.4其他例子
mysql 复制代码
ALTER TABLE students RENAME s1;
ALTER TABLE s1 ADD phone varchar(11) AFTER name;
ALTER TABLE s1 MODIFY phone int;
ALTER TABLE s1 CHANGE COLUMN phone mobile char(11);
ALTER TABLE s1 DROP COLUMN mobile;
ALTER TABLE s1 character set utf8;
ALTER TABLE s1 change name name varchar(20) character set utf8;
ALTER TABLE students ADD gender ENUM('m','f');
ALETR TABLE students CHANGE id sid int UNSIGNED NOT NULL PRIMARY KEY; 
ALTER TABLE students DROP age;
DESC students;
#新建表无主键,添加和删除主键
CREATE TABLE t1 SELECT * FROM students;
ALTER TABLE t1 add primary key (stuid);
ALTER TABLE t1 drop primary key
6.4.7 DML语言 data manger language

DML: INSERT, DELETE, UPDATE

6.4.7.1 INSERT语句

功能:一次插入一行或多行数据

语法

mysql 复制代码
INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
   [INTO] tbl_name [(col_name,...)]
   {VALUES | VALUE} ({expr | DEFAULT},...),(...),...
   [ ON DUPLICATE KEY UPDATE #如果重复更新之
     col_name=expr
       [, col_name=expr] ... ]
INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
   [INTO] tbl_name
   SET col_name={expr | DEFAULT}, ...
   [ ON DUPLICATE KEY UPDATE
     col_name=expr
       [, col_name=expr] ... ]
INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]
   [INTO] tbl_name [(col_name,...)]
    SELECT ...
   [ ON DUPLICATE KEY UPDATE
     col_name=expr
       [, col_name=expr] ... ]

简化

mysql 复制代码
INSERT tbl_name [(col1,...)] VALUES (val1,...), (val21,...)

#解释
insert  表名[(字段)]  值(值1,值2....),(值1,值2)......;
使用 insert 语句时 如果不在表后加上字段就要一一对应填写上信息(注意 字符串用引号引起来)

也可以指定添加的字段 

例子:

mysql 复制代码
mysql [db1]> insert student(name,age,phone) values('mike',20,'10086');
#添加一条记录

mysql [db1]> insert student(name,age,phone) values('mike',20,'10086'),('peter',18,'10000');
#用逗号隔添加多条记录



mysql [db1]> insert student values(null,'小强',20,'M','10010');
#不指明添加字段,  学生编号有 自增长可以使用空
6.4.7.2 UPDATE 语句

语法:

mysql 复制代码
UPDATE [LOW_PRIORITY] [IGNORE] table_reference
    SET col_name1={expr1|DEFAULT} [, col_name2={expr2|DEFAULT}] ...
   [WHERE where_condition]
   [ORDER BY ...]
   [LIMIT row_count]
   
   
   
#解释
update  表名   set  字段=修改的值     指定哪条记录;

需要追加过滤条件    全部数据都修改了

注意:一定要有限制条件,否则将修改所有行的指定字段

例子:

mysql 复制代码
mysql [db1]> update student set gender='F' where id=6;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql [db1]> select * from student;
+----+--------+------+--------+-------+
| id | name   | age  | gender | phone |
+----+--------+------+--------+-------+
|  1 | ben    |   19 | M      |       |
|  2 | NULL   | NULL | M      |       |
|  3 | mike   |   20 | M      | 10086 |
|  4 | peter  |   18 | M      | 10000 |
|  5 | 小强   |   20 | M      | 10010 |
|  6 | 小红   |   20 | F      | 10010 |
+----+--------+------+--------+-------+
6 rows in set (0.00 sec)



mysql [db1]> update student set name='旺财' , age=15 where id=2;

mysql [db1]> select * from student;
+----+--------+------+--------+-------+
| id | name   | age  | gender | phone |
+----+--------+------+--------+-------+
|  1 | ben    |   19 | M      |       |
|  2 | 旺财   |   15 | M      |       |
|  3 | mike   |   20 | M      | 10086 |
|  4 | peter  |   18 | M      | 10000 |
|  5 | 小强   |   20 | M      | 10010 |
|  6 | 小红   |   20 | F      | 10010 |
+----+--------+------+--------+------
6.4.7.3 DELETE 语句

删除表中数据,但不会自动缩减数据文件的大小。

语法:

mysql 复制代码
DELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROM tbl_name
   [WHERE where_condition]
   [ORDER BY ...]
   [LIMIT row_count]
 可先排序再指定删除的行数
 
 #解释:
 delete  from  表名   指定条件

注意:一定要有限制条件,否则将清空表中的所有数据

如果想清空表,保留表结构,也可以使用下面语句,此语句会自动缩减数据文件的大小。

例子:

mysql 复制代码
mysql [db1]> delete from student where id=5;
Query OK, 1 row affected (0.01 sec)
6.4.8 DQL 语句 单表查询

select

添加脚本

mysql 复制代码
source /root/hellodb_innodb.sql 
mysql 复制代码
SELECT
 [ALL | DISTINCT | DISTINCTROW ]
 [SQL_CACHE | SQL_NO_CACHE]
 select_expr [, select_expr ...]
    [FROM table_references
    [WHERE where_condition]
    [GROUP BY {col_name | expr | position}
    [ASC | DESC], ... [WITH ROLLUP]]
    [HAVING where_condition]
    [ORDER BY {col_name | expr | position}
    [ASC | DESC], ...]
    [LIMIT {[offset,] row_count | row_count OFFSET offset}]
    [FOR UPDATE | LOCK IN SHARE MODE]
6.4.8.1 SELECT ----显示表格中一个或数个字段的所有数据记录

语法使用:

mysql 复制代码
select  字段 from  表名;   
#字段可以用* 表示 代表所有,也可以挑选出自己想要的

例子:

mysql 复制代码
select  age from students; 
select  age,name  from students;
6.4.8.2 WHERE --- 过滤查询

语法:

mysql 复制代码
语法:SELECT "字段" FROM "表名" WHERE "条件";

说明:

  • 过滤条件:布尔型表达式
  • 算术操作符:+, -, *, /, %
  • 比较操作符:=,<=>(相等或都为空), <>, !=(非标准SQL), >, >=, <, <=
  • 范例查询: BETWEEN min_num AND max_num
  • 不连续的查询: IN (element1, element2, ...)
  • 空查询: IS NULL, IS NOT NULL
  • 字段显示可以使用别名

例子:

mysql 复制代码
select * from students  where name="xi ren" 
select * from students where age=20;    #年龄等于20岁
select * from students where age >20;   #大于20岁
select * from students where age >=20 and age<=30; #20岁到30岁

例子: 从一个范围到另一个范围 BETWEEN min_num AND max_num

mysql 复制代码
select * from students where age between 20 and 30;   #20岁到30岁

例子: 不连续的查询: IN (element1, element2, ...)

mysql 复制代码
select * from students where age  in (20,22,30);

例子:空查询: IS NULL, IS NOT NULL

mysql 复制代码
select * from students where classid is null;
select * from students where classid is not null;

例子: 字段使用别名

mysql 复制代码
mysql>  select  age 年龄,classid 班级 from students;
+--------+--------+
| 年龄   | 班级   |
+--------+--------+
|     22 |      2 |
|     22 |      1 |


mysql<  select  age as 年龄,classid as 班级 from students;
6.4.8.3 AND OR 且 或

语法:

mysql 复制代码
SELECT "字段" FROM "表名" WHERE "条件1" {[AND|OR] "条件2"}+ ;

例子:

mysql 复制代码
select * from students where (age >20 and age <30) or age >50;    # 20到30之间或大于50
select * from students where age > 50 or   age <20;               # 大于50或者小于20
select * from students where age > 50   and   classid=2;          # 年龄大于50 且 班级id 是2的
select * from students where age < 20   and   gender="F";
6.4.8.4 DISTINCT 去除重复行

例子: 去掉重复的年龄

mysql 复制代码
select age from students;
select distinct age from students;     #去重
6.4.8.5 like 模糊查询 与 通配符
bash 复制代码
% :百分号表示零个、一个或多个字符   *
_ :下划线表示单个字符             ?     

'A_Z':所有以 'A' 起头,另一个任何值的字符,且以 'Z' 为结尾的字符串。例如,'ABZ' 和 'A2Z' 都符合这一个模式,而 'AKKZ' 并不符合 (因为在 A 和 Z 之间有两个字符,而不是一个字符)。
'ABC%': 所有以 'ABC' 起头的字符串。例如,'ABCD' 和 'ABCABC' 都符合这个模式。
'%XYZ': 所有以 'XYZ' 结尾的字符串。例如,'WXYZ' 和 'ZZXYZ' 都符合这个模式。
'%AN%': 所有含有 'AN'这个模式的字符串。例如,'LOS ANGELES' 和 'SAN FRANCISCO' 都符合这个模式。
'_AN%':所有第二个字母为 'A' 和第三个字母为 'N' 的字符串。例如,'SAN FRANCISCO' 符合这个模式,而 'LOS ANGELES' 则不符合这个模式。

语法: like

mysql 复制代码
语法:SELECT "字段" FROM "表名" WHERE "字段" LIKE   "匹配表达式";

例子:

mysql 复制代码
select * from students where name='Xu Zhu';    #精确查找
select * from students where name like 's%';   #找到s 开头的
select * from students where name like '%s%';  #包含s

例子:sql 注入攻击

mysql 复制代码
create table user (id int primary key auto_increment,name varchar(20) not null,password varchar(30) not null);

insert user values(null,'admin','123456');
insert user values(null,'test','123456');


select * from user where name='admin' and password='123456';   #找到数据就是 用户名密码正确。找不到就是错误
select * from user where name='admin' and password='' or '1'='1';

#其他例子:
select * from user where name='admin' and password='' or '1=1';
select * from user where name='admin'; -- ' and password='123';      #--代表注释的意思
select * from user where name='admin'; # ' and password='123';

例子:复制表结构

mysql 复制代码
create table test like students;
6.4.8.6 数学函数:
函数名 函数值
abs(x) 返回 x 的绝对值
rand() 返回 0 到 1 的随机数
mod(x,y) 返回 x 除以 y 以后的余数
power(x,y) 返回 x 的 y 次方
round(x ) 返回离 x 最近的整数
round(x,y) 保留 x 的 y 位小数四舍五入后的值
sqrt(x) 返回 x 的平方根
truncate(x,y) 返回数字 x 截断为 y 位小数的值
ceil(x) 返回大于或等于 x 的最小整数
floor(x) 返回小于或等于 x 的最大整数
greatest(x1,x2...) 返回集合中最大的值,也可以返回多个字段的最大的值
least(x1,x2...) 返回集合中最小的值,也可以返回多个字段的最小的值

例子:

mysql 复制代码
select abs(-100);   #取绝对值
select rand();      #随机数 0到1 间
select mod(10,3);   #10 除3 取余数
select power(2,3)   #求2的3次方
select round(2.6);   #返回离2.6最近的整数3
select sqrt(9);     #返回9 的平方根
select truncate (1.235,2);   #返回前两位值
select ceil (1.5);  #返回大于等于1.5 的值
select floor (1.5);  #返回小于等于1.5 的值
select greatest(1,2,3); #返回集合中的 最大值
select least(1,2,3);    #返回集合中的最小值 
6.4.8.7 聚合函数
函数名 函数意
avg() 返回指定列的平均值
count() 返回指定列中非 NULL 值的个数
min() 返回指定列的最小值
max() 返回指定列的最大值
sum(x) 返回指定列的所有值之和

语法格式:

bash 复制代码
select  函数(*)   from   表名;   # * 代表所有字段
select  函数(单个字段)   from   表名;  
  • avg

例子: avg 平均值

mysql 复制代码
select avg(age) from students;   #avg  所有人的平均值
select avg(age) from students where classid=1;  #求1班年龄平均值
  • count

例子: count 返回指定列中非 NULL 值的个数

mysql 复制代码
select count(classid) from students;       #统计非空classid 字段 一共有多少行记录

select count(distinct classid) from students;  #一共有几个班级 去重

select count(classid) from students;       #统计一共有多少个班级
select count(*) from students;             #统计一共有多少条数据

聚合函数 count()  括号中是具体的字段  如果有null 值不统计 
count()  括号中是  *   会统计 null
#count(*) 包括了所有的列的行数,在统计结果的时候,不会忽略列值为 NULL
#count(列名) 只包括列名那一列的行数,在统计结果的时候,会忽略列值为 NULL 的行
  • min

例子 : min 最小值

mysql 复制代码
select min(age) from students;
  • max

例子:max 最小值

mysql 复制代码
select max(classid) 班级最大序号 from students;
  • sum

例子:sum 求和

mysql 复制代码
select sum(age) from students;  #求年龄总和
select sum(age) from students where classid=1;   #求1班的年龄总和
6.4.8.8 字符串函数
函数名 函数意义
concat(x,y) 将提供的参数 x 和 y 拼接成一个字符串
substr(x,y) 获取从字符串 x 中的第 y 个位置开始的字符串,
substr(x,y,z) 获取从字符串 x 中的第 y 个位置开始长度为 z 的字符串
length(x) 返回字符串 x 的长度
replace(x,y,z) 将字符串 z 替代字符串 x 中的字符串 y
upper(x) 将字符串 x 的所有字母变成大写字母
lower(x) 将字符串 x 的所有字母变成小写字母
left(x,y) 返回字符串 x 的前 y 个字符
right(x,y) 返回字符串 x 的后 y 个字符
repeat(x,y) 将字符串 x 重复 y 次
space(x) 返回 x 个空格
strcmp(x,y) 比较 x 和 y,返回的值可以为-1,0,1
reverse(x) 将字符串 x 反转
  • concat

例子:

mysql 复制代码
#concat
select concat(name,classid) from students where stuid=1;   #将姓名字段和班级字段合在一起
select concat(name,'  ',classid) from students whereere classid=1;  #加空格
  • substr
mysql 复制代码
select substr(name,1,3) from students;  # 获取name 字段的  前1到3 个字符
select name from students where stuid=25;         #
select substr(name,3) from students where stuid=25;
select substr(name,1,3) from students  where stuid=25;

其他

mysql 复制代码
select length(name) from students where stuid=1;      #返回数据的长度
select replace(name,"y",11) from students where stuid=1;  # 将name 字段中的 y  换成11
select left(name,3) from students where stuid=1;   #显示name字段左边三个字符  即最开始的三个
select right(name,3) from students where stuid=1;  #显示name字段 右边三个字符 即最后三个
select repeat(name,2) from students where stuid=1; #将name 字段 重复显示2次
select lower(name) from students;   #返回结果全是小写字母
select reverse(name) from students where stuid=1;  # 反向显示字符串
6.4.8.9 GROUP BY 分组

对GROUP BY后面的字段的查询结果进行汇总分组,通常是结合聚合函数一起使用的GROUP BY 有一个原则,凡是在 GROUP BY 后面出现的字段,必须在 SELECT 后面出现;凡是在 SELECT 后面出现的、且未在聚合函数中出现的字段,必须出现在 GROUP BY 后面

语法:

mysql 复制代码
SELECT "字段1", 聚合函数("字段2") FROM "表名" GROUP BY "字段1";

例子:

mysql 复制代码
select  classid  from  students  group  by  classid;    #对 classid字段进行分组  一共有8组
select  gender   from  students  group  by  gender;     # 对性别进行分组  
select  age      from  students  group  by  age;        # 对性别进行分组




select  classid,count(*) from students group by classid;

select age,count(*)  from students group by age;  # 按年龄分组, 并显示每一组的 人数


select classid,count(*) from students group by classid;
凡是在 SELECT 后面出现的、且未在聚合函数中出现的字段,必须出现在 GROUP BY 后面

例子: 求男女的平均年龄

mysql 复制代码
select gender,avg(age) from students group by gender;    #按性别分组  求平均值

例子:求班级的年龄平均值

mysql 复制代码
select  classid,avg(age)  from students group by classid;

例子:错误例子

mysql 复制代码
select classid,name from students group by classid;
6.4.8.10 排序 order by

语法:

mysql 复制代码
SELECT "字段" FROM "表名" [WHERE "条件"] ORDER BY "字段" [ASC, DESC];
#ASC 是按照升序进行排序的,是默认的排序方式。
#DESC 是按降序方式进行排序。

例子:

mysql 复制代码
select * from students order by age;    #年龄升序排列
select * from students order by age desc;  #年龄降序排
select * from students order by age desc limit 3;


select * from students where classid=1 order by age;  #找出1班的人按升序排序
6.4.8.11 limit

LIMIT [[offset,]row_count]:对查询的结果进行输出行数数量限制,跳过offset,显示row_count行,offset默为值为0

例子: 取前5个数据

mysql 复制代码
select * from students order by age   limit 5;

例子:跳过前3个 往后取 5个, 一个页面可以显示商品也是靠limit 分页实现

复制代码
select * from students    limit 3,5;
6.4.8.12 having

HAVING 语句的存在弥补了 WHERE 关键字不能与聚合函数联合使用的不足

mysql 复制代码
select classid,count(classid) from students group by classid having classid > 3;

select classid,count(classid) from students where classid > 3 group by classid;

select classid,count(classid) from students group by classid where classid > 3;
6.4.8.13 视图view 临时表

视图:数据库中的虚拟表,这张虚拟表中不包含真实数据,只是做了映射

格式:

复制代码
create  view   视图名  as   查询结果

例子:

mysql 复制代码
create view v1 as select * from students where age > 50;
show tables;
select * from v1;

update students set age=90 where stuid=25;
select * from v1;
6.4.8.14 正则表达式
复制代码
匹配	   描述
^	     匹配文本的开始字符
$	     匹配文本的结束字符
.	    匹配任何单个字符
*		匹配零个或多个在它前面的字符
+		匹配前面的字符 1 次或多次字符串	匹配包含指定的字符串
p1|p2	匹配 p1 或 p2
[...]		匹配字符集合中的任意一个字符
[^...]	匹配不在括号中的任何字符
{n}		匹配前面的字符串 n 次
{n,m}	匹配前面的字符串至少 n 次,至多 m 次
{,m}   最多m次
{n,}    最少n次
?    匹配一个字符 

例子:

mysql 复制代码
select name from students where name regexp '^s'
select name from students where name regexp 's';
select name from students where name regexp 's.i';
select name from students where name regexp '^s|l';
6.4.9 DQL 语句多表查询
  • 子查询:在SQL语句嵌套着查询语句,性能较差,基于某语句的查询结果再次进行的查询

  • 联合查询:UNION

  • 交叉连接:笛卡尔乘积,cross join

  • 内连接:

    等值连接:让表之间的字段以"等值"建立连接关系

    不等值连接

  • 自然连接:去掉重复列的等值连接

  • 外连接:

    左外连接:FROM tb1 LEFT JOIN tb2 ON tb1.col=tb2.col

    右外连接:FROM tb1 RIGHT JOIN tb2 ON tb1.col=tb2.col

    完全外连接: FROM tb1 FULL OUTER JOIN tb2 ON tb1.col=tb2.col 注意:MySQL 不支持此SQL语法

  • 自连接:本表和本表进行连接查询

6.4.9.1 子查询

子查询 subquery 即SQL语句调用另一个SELECT子句,可以是对同一张表,也可以是对不同表,主要有以下常见的用法.

1.用于比较表达式中的子查询;子查询仅能返回单个值

例子: 先求出平均年龄 然后再找出比平均年龄大的

mysql 复制代码
select avg(age) from students;   #求平均年龄
select * from students where age > (select avg(age) from students);    #再找出比平均年龄大的

例子: 利用子查询更新数据

mysql 复制代码
SELECT avg(Age) FROM teachers   #先计算出 教师表的 平均年龄
update students set Age=(SELECT avg(Age) FROM teachers)  where stuid=25; # 再把第25个学生的年龄改成  教师表的平均年龄

例子: 将students 表里的 平均年龄,作为 值 赋给teacher表

mysql 复制代码
update teachers set age= (select avg(age) from students) where tid=4;
#将students  表里的 平均年龄,作为  值  赋给teacher表

2.用于IN中的子查询:子查询应该单独查询并返回一个或多个值重新构成列表

例子:找出 students 表中stuid 和teachers 表中 tid 相同的数据

mysql 复制代码
select  tid  from  teachers;
select name,stuid from students where stuid in (select tid from teachers);
6.4.9.2 联合查询 纵向合并

联合查询 Union 实现的条件,多个表的字段数量相同,字段名和数据类型可以不同,但一般数据类型是相同的.

例子: 合并两张表 纵向合并

mysql 复制代码
select name,age from students union select name,age from teachers;

默认union 是会自动去重的

mysql 复制代码
select * from teachers union  select *from teachers;

union all 是不会去重的

mysql 复制代码
select * from teachers union all select *from teachers;
6.4.9.3 交叉连接 横向合并

cross join 即多表的记录之间做笛卡尔乘积组合,并且多个表的列横向合并相加, "雨露均沾"

比如: 第一个表3行4列,第二个表5行6列,cross join后的结果为 3*5=15行 , 4+6=10列

交叉连接生成的记录可能会非常多,建议慎用

一般不用,产生的数据数量 10万 交叉 20 万 mysql 千万级瓶颈(需要分库 分表) 200亿

例子:

mysql 复制代码
select * from students cross join teachers;

select *from students
cross join 
teachers;
6.4.9.4 内连接

inner join 内连接取多个表的交集

语法:

mysql 复制代码
A表内容    inner join   第二张表  on  条件  stuid=tid

范例:内连接 学生表中的 teacherid 和教师表中的 tid 相同的行

mysql 复制代码
select *from students  inner join  teachers on   students.teacherid=teachers.tid;
+-------+-------------+-----+--------+---------+-----------+-----+---------------+-----+--------+
| StuID | Name        | Age | Gender | ClassID | TeacherID | TID | Name          | Age | Gender |
+-------+-------------+-----+--------+---------+-----------+-----+---------------+-----+--------+
|     1 | Shi Zhongyu |  22 | M      |       2 |         3 |   3 | Miejue Shitai |  77 | F      |
|     4 | Ding Dian   |  32 | M      |       4 |         4 |   4 | Lin Chaoying  |  93 | F      |
|     5 | Yu Yutong   |  26 | M      |       3 |         1 |   1 | Song Jiang    |  45 | M      |
+-------+-------------+-----+--------+---------+-----------+-----+---------------+-----+--------+
3 rows in set (0.01 sec)

例子:

mysql 复制代码
update students set teacherid=2 where stuid=7;
update students set teacherid=2 where stuid=22;
select *from students  inner join  teachers on   students.teacherid=teachers.tid;

例子: 可以挑选想要的列

mysql 复制代码
select  students.name,students.gender,students.teacherid,teachers.name  from students  inner joiin  teachers on   students.teacherid=teachers.tid;
+-------------+--------+-----------+---------------+
| name        | gender | teacherid | name          |
+-------------+--------+-----------+---------------+
| Shi Zhongyu | M      |         3 | Miejue Shitai |
| Ding Dian   | M      |         4 | Lin Chaoying  |
| Yu Yutong   | M      |         1 | Song Jiang    |
| Xi Ren      | F      |         2 | Zhang Sanfeng |
| Xiao Qiao   | F      |         2 | Zhang Sanfeng |
+-------------+--------+-----------+---------------+
5 rows in set (0.00 sec)

例子: 字段取别名

mysql 复制代码
select  students.name student_name ,students.gender,students.teacherid,teachers.name teacher_name  from students  inner join  teachers on   students.teacherid=teachers.tid;
+--------------+--------+-----------+---------------+
| student_name | gender | teacherid | teacher_name  |
+--------------+--------+-----------+---------------+
| Shi Zhongyu  | M      |         3 | Miejue Shitai |
| Ding Dian    | M      |         4 | Lin Chaoying  |
| Yu Yutong    | M      |         1 | Song Jiang    |
| Xi Ren       | F      |         2 | Zhang Sanfeng |
| Xiao Qiao    | F      |         2 | Zhang Sanfeng |
+--------------+--------+-----------+---------------+

例子: 对表格取别名

mysql 复制代码
 select  s.name student_name ,s.gender, s.teacherid ,t.name teacher_name  from students s  inner join  teachers t on   s.teacherid=t.tid;
+--------------+--------+-----------+---------------+
| student_name | gender | teacherid | teacher_name  |
+--------------+--------+-----------+---------------+
| Shi Zhongyu  | M      |         3 | Miejue Shitai |
| Ding Dian    | M      |         4 | Lin Chaoying  |
| Yu Yutong    | M      |         1 | Song Jiang    |
| Xi Ren       | F      |         2 | Zhang Sanfeng |
| Xiao Qiao    | F      |         2 | Zhang Sanfeng |
+--------------+--------+-----------+---------------+
5 rows in set (0.00 sec)
6.4.9.5 外连接

左连接: 以左表为主根据条件查询右表数据﹐如果根据条件查询右表数据不存在使用null值填充

右连接: 以右表为主根据条件查询左表数据﹐如果根据条件查询左表数据不存在使用null值填充

例子: 左外连接 学生表都有 , 教师表留一部分

mysql 复制代码
select * from students s left join teachers t  on s.teacherid=t.tid;

-------+---------------+-----+--------+---------+-----------+------+---------------+------+--------+
| StuID | Name          | Age | Gender | ClassID | TeacherID | TID  | Name          | Age  | Gender |
+-------+---------------+-----+--------+---------+-----------+------+---------------+------+--------+
|     5 | Yu Yutong     |  26 | M      |       3 |         1 |    1 | Song Jiang    |   45 | M      |
|     7 | Xi Ren        |  19 | F      |       3 |         2 |    2 | Zhang Sanfeng |   94 | M      |
|    22 | Xiao Qiao     |  20 | F      |       1 |         2 |    2 | Zhang Sanfeng |   94 | M      |
|     1 | Shi Zhongyu   |  22 | M      |       2 |         3 |    3 | Miejue Shitai |   77 | F      |
|     4 | Ding Dian     |  32 | M      |       4 |         4 |    4 | Lin Chaoying  |   93 | F      |
|     2 | Shi Potian    |  22 | M      |       1 |         7 | NULL | NULL          | NULL | NULL   |
|     3 | Xie Yanke     |  53 | M      |       2 |        16 | NULL | NULL          | NULL | NULL   |
|     6 | Shi Qing      |  46 | M      |       5 |      NULL | NULL | NULL          | NULL | NULL   |
|     8 | Lin Daiyu     |  17 | F      |       7 |      NULL | NULL | NULL          | NULL | NULL   |
|     9 | Ren Yingying  |  20 | F      |       6 |      NULL | NULL | NULL          | NULL | NULL   |
|    10 | Yue Lingshan  |  19 | F      |       3 |      NULL | NULL | NULL          | NULL | NULL   |
|    11 | Yuan Chengzhi |  23 | M      |       6 |      NULL | NULL | NULL          | NULL | NULL   |
|    12 | Wen Qingqing  |  19 | F      |       1 |      NULL | NULL | NULL          | NULL | NULL   |
|    13 | Tian Boguang  |  33 | M      |       2 |      NULL | NULL | NULL          | NULL | NULL   |
|    14 | Lu Wushuang   |  17 | F      |       3 |      NULL | NULL | NULL          | NULL | NULL   |
|    15 | Duan Yu       |  19 | M      |       4 |      NULL | NULL | NULL          | NULL | NULL   |
|    16 | Xu Zhu        |  21 | M      |       1 |      NULL | NULL | NULL          | NULL | NULL   |
|    17 | Lin Chong     |  25 | M      |       4 |      NULL | NULL | NULL          | NULL | NULL   |
|    18 | Hua Rong      |  23 | M      |       7 |      NULL | NULL | NULL          | NULL | NULL   |
|    19 | Xue Baochai   |  18 | F      |       6 |      NULL | NULL | NULL          | NULL | NULL   |
|    20 | Diao Chan     |  19 | F      |       7 |      NULL | NULL | NULL          | NULL | NULL   |
|    21 | Huang Yueying |  22 | F      |       6 |      NULL | NULL | NULL          | NULL | NULL   |
|    23 | Ma Chao       |  23 | M      |       4 |      NULL | NULL | NULL          | NULL | NULL   |
|    24 | Xu Xian       |  27 | M      |    NULL |      NULL | NULL | NULL          | NULL | NULL   |
|    25 | Sun Dasheng   |  77 | M      |    NULL |      NULL | NULL | NULL          | NULL | NULL   |
+-------+---------------+-----+--------+---------+-----------+------+---------------+------+--------+
25 rows in set (0.00 sec)



select * from students s left join teachers t  on s.teacherid=t.tid  where t.tid is null;

例子: 右外连接 教师表全部, 学生表一部分

mysql 复制代码
select * from students s  right join  teachers t on   s.teacherid=t.tid;
+-------+-------------+------+--------+---------+-----------+-----+---------------+-----+--------+
| StuID | Name        | Age  | Gender | ClassID | TeacherID | TID | Name          | Age | Gender |
+-------+-------------+------+--------+---------+-----------+-----+---------------+-----+--------+
|     1 | Shi Zhongyu |   22 | M      |       2 |         3 |   3 | Miejue Shitai |  77 | F      |
|     4 | Ding Dian   |   32 | M      |       4 |         4 |   4 | Lin Chaoying  |  93 | F      |
|     5 | Yu Yutong   |   26 | M      |       3 |         1 |   1 | Song Jiang    |  45 | M      |
|     7 | Xi Ren      |   19 | F      |       3 |         2 |   2 | Zhang Sanfeng |  94 | M      |
|    22 | Xiao Qiao   |   20 | F      |       1 |         2 |   2 | Zhang Sanfeng |  94 | M      |
+-------+-------------+------+--------+---------+-----------+-----+---------------+-----+--------+
5 rows in set (0.00 sec)
6.4.9.6 自连接

自连接, 即表自身连接自身

例子:

mysql 复制代码
#构建新表
create table emp (id int, name varchar(10),leaderid int);
insert emp values(1,'cxk',null),(2,'wyf',1),(3,'zhang',2),(4,'li',3);


select *  from emp e  left join  emp l on  e.leaderid=l.id;
+------+-------+----------+------+-------+----------+
| id   | name  | leaderid | id   | name  | leaderid |
+------+-------+----------+------+-------+----------+
|    2 | wyf   |        1 |    1 | cxk   |     NULL |
|    3 | zhang |        2 |    2 | wyf   |        1 |
|    4 | li    |        3 |    3 | zhang |        2 |
|    1 | cxk   |     NULL | NULL | NULL  |     NULL |
+------+-------+----------+------+-------+----------+
4 rows in set (0.00 sec)

select e.name emp_name, l.name leader_name  from emp e  left join  emp l on e.leaderid=l.id;
6.4.9.7 三表查询
mysql 复制代码
select * from  students inner join scores on students.stuid=scores.stuid;
select st.name,sc.CourseID,sc.score from  students st inner join scores sc on st.stuid=sc.stuid;
select st.name,co.CourseID,sc.score from  students st inner join scores sc on st.stuid=sc.stuid inner  join courses co on sc.courseid=co.courseid;
select * from  students st inner join scores sc on st.stuid=sc.stuid inner  join courses co on sc.courseid=co.courseid;

练习:

bash 复制代码
导入hellodb.sql生成数据库
1. 在students表中,查询年龄大于25岁,且为男性的同学的名字和年龄
2. 以ClassID为分组依据,显示每组的平均年龄
3. 显示第2题中平均年龄大于30的分组及平均年龄
4. 显示以L开头的名字的同学的信息
5. 显示TeacherID非空的同学的相关信息
6. 以年龄排序后,显示年龄最大的前10位同学的信息
7. 查询年龄大于等于20岁,小于等于25岁的同学的信息
8. 以ClassID分组,显示每班的同学的人数
9. 以Gender分组,显示其年龄之和
10. 以ClassID分组,显示其平均年龄大于25的班级
11. 以Gender分组,显示各组中年龄大于25的学员的年龄之和
12. 显示前5位同学的姓名、课程及成绩
13. 显示其成绩高于80的同学的名称及课程
14. 取每位同学各门课的平均成绩,显示成绩前三名的同学的姓名和平均成绩
15. 显示每门课程课程名称及学习了这门课的同学的个数
16. 显示其年龄大于平均年龄的同学的名字
17. 显示其学习的课程为第1、2,4或第7门课的同学的名字
18. 显示其成员数最少为3个的班级的同学中年龄大于同班同学平均年龄的同学
19. 统计各班级中年龄大于全校同学平均年龄的同学

6.5 视图

视图:虚拟表,保存有实表的查询结果,相当于别名

利用视图,可以隐藏表的真实结构,在程序中利用视图进行查询,可以避免表结构的变化,而修改程序,降低程序和数据库之间的耦合度

创建方法:

mysql 复制代码
CREATE   VIEW view_name [(column_list)]
         AS select_statement
         [WITH [CASCADED | LOCAL] CHECK OPTION]

查看视图定义:

mysql 复制代码
SHOW CREATE VIEW view_name #只能看视图定义
SHOW CREATE TABLE view_name # 可以查看表和视图

例子:建立视图

mysql 复制代码
select * from students  where stuid=5;
create view v1 as select * from students  where stuid=5;
show tables;


show table status like 'v1'\G;  #查看表结构
show table status like 'students'\G;

删除视图

mysql 复制代码
drop view v1

7 用户管理

7.1 存放用户信息的表

mysql 的用户 放在mysql数据库中的user表中

mysql 复制代码
select user,host,authentication_string from mysql.user;
+---------------+-----------+
| user          | host      |
+---------------+-----------+
| mysql.session | localhost |
| mysql.sys     | localhost |
| root          | localhost |
+---------------+-----------+


root@localhost     默认存在的, 并且只能  本地登录无法远程登录

7.2 查看当前使用用户

mysql 复制代码
(root@localhost) [(none)]> select user();

7.3 新建用户

格式:

bash 复制代码
CREATE USER '用户名'@'来源地址' [IDENTIFIED BY [PASSWORD] '密码'];
----------------------------------------------------------------------------------------------------------
'用户名':指定将创建的用户名
'来源地址':指定新创建的用户可在哪些主机上登录,可使用IP地址、网段、主机名的形式,本地用户可用localhost,允许任意主机登录可用通配符%
'密码':若使用明文密码,直接输入'密码',插入到数据库时由Mysql自动加密;
        若使用加密密码,需要先使用SELECT PASSWORD('密码'); 获取密文,再在语句中添加 PASSWORD '密文';
        若省略"IDENTIFIED BY"部分,则用户的密码将为空(不建议使用)
----------------------------------------------------------------------------------------------------------

'USERNAME'@'HOST'
'用户名'@'来源地址'

@'HOST': 主机名: user1@'web1.kgc.org'
IP地址或Network 
 通配符: %   _
 示例:zhou@172.16.%.%  
      user2@'192.168.1.%'
      kgc@'10.0.0.0/255.255.0.0'

例子:

mysql 复制代码
mysql  -u用户名  -p密码   -h远程主机  -P端口号



create user test@'192.168.%.%';   #建立远程登录用户
create user zhou@'192.168.91.%' identified by '123123';   #可以后面加密码
create user test1               identified by '123123';
select user,host,password from mysql.user;   #查看字段  密码为空

mysql -utest -h192.168.91.100  -p密码  #使用其他主机登录

alter user test@'192.168.%.%' identified by  '123123';    #新版可以  旧版的mariadb  不可以
ALTER  USER test@'192.168.%.%' IDENTIFIED BY 'centos';
gm871230

7.4 修改用户名称

格式:

mysql 复制代码
rename user '旧名字' to '新名字;

例子:

mysql 复制代码
rename user 'zhangsan'@'192.168.91.%' to 'lisi'@'192.168.91.%';

7.5删除用户

格式:

mysql 复制代码
drop  user '用户名';

例子:

mysql 复制代码
drop user liwu@'%';

7.6 修改用户密码

密码有安全性策略可以修改取消

mysql 复制代码
set global validate_password_policy=0;
set global validate_password_length=1;
#修改密码策略

格式:

mysql 复制代码
SET PASSWORD = PASSWORD('abc123');  #只能改自己当前

set password for '用户' = password('密码');    #

例子:

mysql 复制代码
set password = 'abc123';    #给当前用户修改密码

set password for 'lisi'@'192.168.91.%' = 'abc123';   #给其他用户修改密码

7.7 破解密码

1 修改配置文件啊

mysql 复制代码
vim /etc/my.cnf
[mysqld]
skip-grant-tables 
#数据库的单用户模式   此模式下权限受到限制,很多功能无法使用, 除了破解密码不要加此项
skip-networking  #MySQL8.0不需要

#然后清空密码
update mysql.user set authentication_string='' where user='root' and host='localhost';
#注意刷新后生效
flush privileges;

7.8远程登录

mysql 复制代码
mysql -utest -h192.168.91.100   -p'密码'  -P端口号

例子:

mysql 复制代码
vim /etc/my.cnf
[mysqld]
port = 9527

systemctl restart   mysqld


客户机
mysql -utest -h192.168.91.100   -p'Admin@123'  -P9527

7.9 用户权限管理

权限类别:

  • 管理类
  • 程序类
  • 数据库级别
  • 表级别
  • 字段级别

管理类:

  • CREATE USER
  • FILE
  • SUPER
  • SHOW DATABASES
  • RELOAD
  • SHUTDOWN
  • REPLICATION SLAVE
  • REPLICATION CLIENT
  • LOCK TABLES
  • PROCESS
  • CREATE TEMPORARY TABLES

库和表级别:针对 DATABASE、TABLE

  • ALTER
  • CREATE
  • CREATE VIEW
  • DROP INDEX
  • SHOW VIEW
  • WITH GRANT OPTION:能将自己获得的权限转赠给其他用户

数据操作

  • SELECT
  • INSERT
  • DELETE
  • UPDATE

字段级别

  • SELECT(col1,col2,...)
  • UPDATE(col1,col2,...)
  • INSERT(col1,col2,...)

所有权限

  • ALL PRIVILEGES 或 ALL
7.9.1查看权限
复制代码
SHOW GRANTS FOR 'lisi'@'%';
#USAGE权限只能用于数据库登陆,不能执行任何操作;USAGE权限不能被回收,即 REVOKE 不能删除用户。
7.9.2授予权限

GRANT语句:专门用来设置数据库用户的访问权限。当指定的用户名不存在时,GRANT语句将会创建新的用户;当指定的用户名存在时, GRANT 语句用于修改用户信息。

格式:

mysql 复制代码
GRANT 权限列表 ON 数据库名.表名 TO '用户名'@'来源地址' [IDENTIFIED BY '密码'];

----------------------------------------------------------------------------------------------------------
#权限列表:用于列出授权使用的各种数据库操作,以逗号进行分隔,如"select,insert,update"。使用"all"表示所有权限,可授权执行任何操作。
#数据库名.表名:用于指定授权操作的数据库和表的名称,其中可以使用通配符"*"。例如,使用"kgc.*"表示授权操作的对象为 kgc数据库中的所有表。
#'用户名@来源地址':用于指定用户名称和允许访问的客户机地址,即谁能连接、能从哪里连接。来源地址可以是域名、IP地址,还可以使用"%"通配符,表示某个区域或网段内的所有地址,如"%.kgc.com"、"192.168.80.%"等。
#IDENTIFIED BY:用于设置用户连接数据库时所使用的密码字符串。在新建用户时,若省略"IDENTIFIED BY"部分,则用户的密码将为空。
----------------------------------------------------------------------------------------------------------

例子:

mysql 复制代码
GRANT select ON kgc.* TO 'zhangsan'@'localhost' IDENTIFIED BY '123456';
#允许用户 zhangsan 在本地查询 kgc 数据库中 所有表的数据记录,但禁止查询其他数据库中的表的记录。


GRANT ALL [PRIVILEGES] ON *.* TO 'lisi'@'%' IDENTIFIED BY '123456';
#允许用户 lisi 在所有终端远程连接 mysql ,并拥有所有权限。
grant  all   on   *.*  to  lisi@'192.168.91.%';


flush privileges;
#不要忘记刷新
quit
复制代码
图形界面
create user lisi@'192.168.91.%' identified by 'Admin@123';
grant  all   on   *.*  to  lisi@'192.168.91.%';
flush privileges;
7.9.3 撤销权限

格式:

mysql 复制代码
REVOKE 权限列表 ON 数据库名.表名 FROM 用户名@来源地址;

例子:

mysql 复制代码
REVOKE ALL ON *.* FROM 'cxk'@'%';
7.9.4 远程连接图形界面
bash 复制代码
grant all privileges on *.* to test@'192.168.%.%' identified by '123123';
flush privileges;

8MySQL架构和性能优化

MySQL是C/S 架构的,connectors是连接器;可供Native C API、JDBC、ODBC、NET、PHP、Perl、Python、Ruby、Cobol等连接mysql;ODBC叫开放数据库(系统)互联,open database connection;JDBC是主要用于java语言利用较为底层的驱动连接数据库;以上这些,站在编程角度可以理解为连入数据库管理系统的驱动,站在mysql角度称作专用语言对应的链接器.任何链接器连入mysql以后,mysql是单进程多线程模型的,因此,每个用户连接,都会创建一个单独的连接线程;其实mysql连接也有长短连接两种方式,使用mysql客户端连入数据库后,直到使用quit命令才退出,可认为是长连接;使用mysql中的-e选项,在mysql客户端向服务器端申请运行一个命令后则立即退出,也就意味着连接会立即断开;所以,mysql也支持长短连接类似于两种类型;所以,用户连入mysql后,创建一个连接线程,完成之后,能够通过这个链接线程完成接收客户端发来的请求,为其处理请求,构建响应报文并发给客户端;由于是单进程模型,就意味着必须要维持一个线程池,跟之前介绍过的varnish很接近,需要一个线程池来管理这众多线程是如何对众多客户端的并发请求,完成并发响应的,组件connection pool就是实现这样功能;connection pool对于mysql而言,它所实现的功能,包括authentication认证,用户发来的账号密码是否正确要完成认证功能;thread reuse线程重用功能,一般当一个用户连接进来以后要用一个线程来响应它,而后当用户退出这个线程有可能并非被销毁,而是把它清理完以后,重新收归到线程池当中的空闲线程中去,以完成所谓的线程重用;connection limit 线程池的大小决定了连接并发数量的上限,例如,最多容纳100线程,一旦到达此上限后续到达的连接请求则只能排队或拒绝连接;check memory用来检测内存,caches实现线程缓存;整个都属于线程池的功能.当用户请求之后,通过线程池建立一个用户连接,这个线程一直存在,然后用户就通过这个会话,发送对应的SQL语句到服务器端.服务器收到SQL语句后,要对语句完成执行,首先要能理解sql语句需要有sql解释器或叫sql接口sql interface就可理解为是整个mysql的外壳,就像shell是linux操作系统的外壳一样;用户无论通过哪种链接器发来的基本的SQL请求,当然,事实上通过native C API也有发过来的不是SQL 请求,而仅仅是对API中的传递参数后的调用;不是SQL语句不过都统统理解为sql语句罢了;对SQL而言分为DDL 和DML两种类型,但是无论哪种类型,提交以后必须交给内核,让内核来运行,在这之前必须要告诉内核哪个是命令,哪个是选项,哪些是参数,是否存在语法错误等等;因此,这个整个SQL 接口就是一个完完整整的sql命令的解释器,并且这个sql接口还有提供完整的sql接口应该具备的功能,比如支持所谓过程式编程,支持代码块的实现像存储过程、存储函数,触发器、必要时还要实现部署一个关系型数据库应该具备的基本组件例如视图等等,其实都在sql interface这个接口实现的;SQL接口做完词法分析、句法分析后,要分析语句如何执行让parser解析器或分析器实现parser是专门的分析器,这个分析器并不是分析语法问题的,语法问题在sql接口时就能发现是否有错误了,一个语句没有问题,就要做执行分析,所谓叫查询翻译,把一个查询语句给它转换成对应的能够在本地执行的特定操作;比如说看上去是语句而背后可能是执行的一段二进制指令,这个时候就完成对应的指令,还要根据用户请求的对象,比如某一字段查询内容是否有对应数据的访问权限,或叫对象访问权限;在数据库中库、表、字段、字段中的数据有时都称为object,叫一个数据库的对象,用户认证的通过,并不意味着就能一定能访问数据库上的所有数据,所以说,mysql的认证大概分为两过程都要完成,第一是连入时需要认证账号密码是否正确这是authentication,然后,验证成功后用户发来sql语句还要验证用户是否有权限获取它期望请求获取的数据;这个称为object privilege,这一切都是由parser分析器进行的分析器分析完成之后,可能会生成多个执行树,这意味着为了能够达到访问期望访问到的目的,可能有多条路径都可实现,就像文件系统一样可以使用相对路径也可使用绝对路径;它有多种方式,在多种路径当中一定有一个是最优的,类似路由选择,因此,优化器就要去衡量多个访问路径中哪一个代价或开销是最小的,这个开销的计算要依赖于索引等各种内部组件来进行评估;而且这个评估的只是近似值,同时还要考虑到当前mysql内部在实现资源访问时统计数据,比如,根据判断认为是1号路径的开销最小的,但是众多统计数据表明发往1号路径的访问的资源开销并不小,并且比3号路径大的多,因此,可能会依据3号路径访问;这就是所谓的优化器它负责检查多条路径,每条路径的开销,然后评估开销,这个评估根据内部的静态数据,索引,根域根据动态生成的统计数据来判定每条路径的开销大小,因此这里还有statics;一旦优化完成之后,还要生成统计数据,这就是优化器的作用;如果没有优化器mysql执行语句是最慢的,其实优化还包括一种功能,一旦选择完一条路径后,例如用户给的这个命令执行起来,大概需要100个开销,如果通过改写语句能够达到同样目的可能只需要30个开销;于是,优化器还要试图改写sql语句;所以优化本身还包括查询语句的改写;一旦优化完成,接下来就交给存储引擎完成.mysql是插件式存储引擎,它就能够替换使用选择多种不同的引擎,MyISAM是MySQL 经典的存储引擎之一,InnoDB是由Innobase Oy公司所开发,2006年五月由甲骨文公司并购提供给MySQL的,NDB主要用于MySQL Cluster 分布式集群环境,archive做归档的等等,还有许多第三方开发的存储引擎;存储引擎负责把具体分析的结果完成对磁盘上文件路径访问的转换,数据库中的行数据都是存储在磁盘块上的,因此存储引擎要把数据库数据映射为磁盘块,并把磁盘块加载至内存中;进程实现数据处理时,是不可能直接访问磁盘上的数据的,因为它没有权限,只有让内核来把它所访问的数据加载至内存中以后,进程在内存中完成修改,由内核再负责把数据存回磁盘;对于文件系统而言,数据的存储都是以磁盘块方式存储的,但是,mysql在实现数据组织时,不完全依赖于磁盘,而是把磁盘块再次组织成更大一级的逻辑单位,类似于lvm中的PE或LE的形式;其实,MySQL的存储引擎在实现数据管理时,也是在文件系统之上布设文件格式,对于文件而言在逻辑层上还会再次组织成一个逻辑单位,这个逻辑单位称为mysql的数据块datablock 一般为16k ,对于关系型数据库,数据是按行存储的;一般一行数据都是存储在一起的,因此,MySQL 在内部有一个datablock,在datablock可能存储一行数据,也可能存放了n行数据;将来在查询加载一行数据时,内核会把整个一个数据数据块加载至内存中,而mysql存储引擎,就从中挑出来某一行返回给查询者,是这样实现的;所以整个存储是以datablock在底层为其最终级别的.事实上,整个存取过程,尤其是访问比较热点的数据,也不可能每一次当用户访问时或当某SQL语句用到时再临时从磁盘加载到内存中,因此,为了能够加上整个性能,mysql的有些存储引擎可以实现,把频繁访问到的热点数据,统统装入内存,用户访问、修改时直接在内存中操作,只不过周期性的写入磁盘上而已,比如像InnoDB,所以caches和buffers组件就是实现此功能的;MySQL为了执行加速,因为它会不断访问数据,而随计算机来说io是最慢的一环,尤其是磁盘io,所以为了加速都载入内存中管理;这就需要MySQL 维护cache和buffer缓存或缓冲;这是由MySQL 服务器自己维护的;有很多存储引擎自己也有cache和buffer

一个数据库提供了3种视图,物理视图就是看到的对应的文件系统存储为一个个的文件,MySQL的数据文件类型,常见的有redo log重做日志,undo log撤销日志,data是真正的数据文件,index是索引文件,binary log是二进制日志文件,error log错误日志,query log查询日志,slow query log慢查询日志,在复制架构中还存在中继日志文件,跟二进制属于同种格式;这是mysql数据文件类型,也就是物理视图;逻辑视图这是在mysql接口上通过存储引擎把mysql文件尤其是data文件,给它映射为一个个关系型数据库应该具备组成部分,比如表,一张表在底层是一个数据文件而已,里面组织的就是datablock,最终映射为磁盘上文件系统的block,然后再次映射为本地扇区的存储,但是整个mysql需要把他们映射成一个二维关系表的形式,需要依赖sql接口以及存储引擎共同实现;所以,把底层数据文件映射成关系型数据库的组件就是逻辑视图;DBA 就是关注内部组件是如何运作的,并且定义、配置其运作模式,而链接器都是终端用户通过链接器的模式进入数据库来访问数据;数据集可能非常大,每一类用户可能只有一部分数据的访问权限,这个时候,最终的终端用户所能访问到的数据集合称作用户视图;

为了保证MySQL运作还提供了管理和服务工具,例如:备份恢复工具,安全工具,复制工具,集群服务,管理、配置、迁移、元数据等工具

8.1索引

索引介绍

索引:是排序的快速查找的特殊数据结构,定义作为查找条件的字段上,又称为键key,索引通过存储引擎实现

索引的概念

  • 索引是一个排序的列表,在这个列表中存储着索引的值和包含这个值的数据所在行的物理地址(类似于C语言的链表通过指针指向数据记录的内存地址)。

  • 使用索引后可以不用扫描全表来定位某行的数据,而是先通过索引表找到该行数据对应的物理地址然后访问相应的数据,因此能加快数据库的查询速度。

  • 索引就好比是一本书的目录,可以根据目录中的页码快速找到所需的内容。

  • 索引是表中一列或者若干列值排序的方法。

  • 建立索引的目的是加快对表中记录的查找或排序。

索引的作用优点 1.加快查询速度,提高数据库性能

●设置了合适的索引之后,数据库利用各种快速定位技术,能够大大加快查询速度,这是创建索引的最主要的原因。

●当表很大或查询涉及到多个表时,使用索引可以成千上万倍地提高查询速度。避免排序和使用临时表

●可以降低数据库的IO成本(减少io次数),并且索引还可以降低数据库的排序成本。将随机I/O转为顺序I/O

●通过创建唯一性索引,可以保证数据表中每一行数据的唯一性。

●可以加快表与表之间的连接。

●在使用分组和排序时,可大大减少分组和排序的时间。

●建立索引在搜索和恢复数据库中的数据时能显著提高性能

缺点:

  • 占用额外的磁盘空间,影响插入速度 占用磁盘空间

创建索引的原则依据

索引虽可以提升数据库查询的速度,但并不是任何情况下都适合创建索引。因为索引本身会消耗系统资源,在有索引的情况下,数据库会先进行索引查询,然后定位到具体的数据行,如果索引使用不当,反而会增加数据库的负担。

●表的主键、外键必须有索引。因为主键具有唯一性,外键关联的是主表的主键,查询时可以快速定位。

●记录数超过300行的表应该有索引。如果没有索引,每次查询都需要把表遍历一遍,会严重影响数据库的性能。

●经常与其他表进行连接的表,在连接字段上应该建立索引。

●唯一性太差的字段不适合建立索引。

●更新太频繁地字段不适合创建索引。

●经常出现在 where 子句中的字段,特别是大表的字段,应该建立索引。

●在经常进行 GROUP BY、ORDER BY 的字段上建立索引;

●索引应该建在选择性高的字段上。

●索引应该建在小字段上,对于大的文本字段甚至超长字段,不要建索引。

索引优化

  • 独立地使用列:尽量避免其参与运算,独立的列指索引列不能是表达式的一部分,也不能是函数的参数,在where条件中,始终将索引列单独放在比较符号的一侧,尽量不要在列上进行运算(函数操作和表达式操作)

  • 左前缀索引:构建指定索引字段的左侧的字符数,要通过索引选择性(不重复的索引值和数据表的记录总数的比值)来评估,尽量使用短索引,如果可以,应该制定一个前缀长度

  • 多列索引:AND操作时更适合使用多列索引,而非为每个列创建单独的索引

  • 选择合适的索引列顺序:无排序和分组时,将选择性最高放左侧

  • 只要列中含有NULL值,就最好不要在此列设置索引,复合索引如果有NULL值,此列在使用时也不会使用索引

  • 对于经常在where子句使用的列,最好设置索引

  • 对于有多个列where或者order by子句,应该建立复合索引

  • 对于like语句,以 % 或者 _ 开头的不会使用索引,以 % 结尾会使用索引

  • 尽量不要使用not in和<>操作,虽然可能使用索引,但性能不高

  • 不要使用RLIKE正则表达式会导致索引失效

  • 查询时,能不要就不用,尽量写全字段名,比如:select id,name,age from students;

  • 大部分情况连接效率远大于子查询

  • 在有大量记录的表分页时使用limit

  • 对于经常使用的查询,可以开启查询缓存

  • 多使用explain和profile分析查询语句

  • 查看慢查询日志,找出执行时间长的sql语句优化

索引类型:

  • B+ TREE、HASH、R TREE、FULL TEXT
  • 聚簇(集)索引、非聚簇索引:数据和索引是否存储在一起
  • 主键索引、二级(辅助)索引
  • 稠密索引、稀疏索引:是否索引了每一个数据项
  • 简单索引、组合索引: 是否是多个字段的索引
  • 左前缀索引:取前面的字符做索引
  • 覆盖索引:从索引中即可取出要查询的数据,性能高

索引结构

参考链接 : https://www.cs.usfca.edu/\~galles/visualization/Algorithms.html

二叉树

参考链接: https://www.cs.usfca.edu/\~galles/visualization/BST.html

红黑树

参考链接:https://www.cs.usfca.edu/\~galles/visualization/RedBlack.html

B-Tree 索引

参考链接: https://www.cs.usfca.edu/\~galles/visualization/BTree.html

缺点:

1.连续范围查找都要从头开始,效率不稳定,快的很快,慢的就比较慢

2.所存数据量越大,查找次数越多

B+Tree索引

参考链接: https://www.cs.usfca.edu/\~galles/visualization/BPlusTree.html

B+Tree索引:按顺序存储,每一个叶子节点到根结点的距离是相同的;左前缀索引,适合查询范围类的数据

B+树

查找效率不统一

高度一般为2-3层,它就能满足千万级的数据存储,解决了btree 需要7-8层才能达到千万级别

http 复制代码
假设定义一颗B+树高度为2,即一个根节点和若干叶子节点。那么这棵B+树的存放总行记录数=根节点指针数*
单个叶子记录的行数。这里先计算叶子节点,B+树中的单个叶子节点的大小为16K,假设每一条目为1K,那么
记录数即为16(16k/1K=16),然后计算非叶子节点能够存放多少个指针,假设主键ID为bigint类型,那么长
度为8字节,而指针大小在InnoDB中是设置为6个字节,这样加起来一共是14个字节。那么通过页大小/(主键
ID大小+指针大小),即16384/14=1170个指针,所以一颗高度为2的B+树能存放16*1170=18720条这样的
记录。根据这个原理就可以算出一颗高度为3的B+树可以存放16*1170*1170=21902400条记录。所以在
InnoDB中B+树高度一般为2-3层,它就能满足千万级的数据存储

8.2 索引管理

8.2.1 查看索引
mysql 复制代码
show index from 表名;
show keys from 表名;

例子:

mysql 复制代码
show index from hellodb.students;
8.2.2 建立索引

格式:

mysql 复制代码
CREATE INDEX 索引名 ON 表名 (列名[(length)]);

例子:

mysql 复制代码
select * from students where name='xu xian';  #找许仙

create index idx_name on students(name(5));    #已name  为字段建立索引


show index from students;                     #查看 索引 会多一条
explain select * from students where name='xu xian';   #可以看到使用了索引


[root@localhost ~]# mysql  -uroot -p'自己的密码' hellodb < testlog.sql
#生成测试环境
(root@localhost) [hellodb]> call sp_testlog;
#生成  一百万条数据

create index index_name on testlog(name);  #建立索引
drop index inx_name on testlog;            #删除索引

create index index_name on students(name);  #给students 表加 name表
explain select * from students where name like 's%';  #找s开头的人看是否会用索引
explain select * from students where name like '%s';  #找s结尾的人是否会用
explain select * from students where name like '%s%'; #包含s的是否会调用索引
explain select * from students where name like 'x%';  #是否使用索引
8.2.3删除索引

●直接删除索引

mysql 复制代码
DROP INDEX 索引名 ON 表名;

8.3EXPLAIN 工具

以通过EXPLAIN来分析索引的有效性,获取查询执行计划信息,用来查看查询优化器如何执行查询

参考资料: https://dev.mysql.com/doc/refman/5.7/en/explain-output.html

语法:

复制代码
EXPLAIN SELECT clause

例子:

mysql 复制代码
 explain select * from stundets where stuid=20;

说明:

列名 说明
id 执行编号,标识select所属的行。如果在语句中没子查询或关联查询,只有唯一的select,每行都将显示1。否则,内层的select语句一般会顺序编号,对应于其在原始语句中的位置
select_type 简单查询:SIMPLE|复杂查询:PRIMARY(最外面的SELECT)、DERIVED(用于FROM中的子查询)、UNION(UNION语句的第一个之后的SELECT语句)、UNIONRESUlT(匿名临时表)、SUBQUERY(简单子查询)
table 访问引用哪个表(引用某个查询,如"derived3")
type 关联类型或访问类型,即MySQL决定的如何去查询表中的行的方式
possible_keys 查询可能会用到的索引
key 显示mysql决定采用哪个索引来优化查询
key_len 显示mysql在索引里使用的字节数
ref 当使用索引列等值查询时,与索引列进行等值匹配的对象信息
rows 为了找到所需的行而需要读取的行数,估算值,不精确。通过把所有rows列值
Extra 额外信息 Using index:MySQL将会使用覆盖索引,以避免访问表 Using where:MySQL服务器将在存储引擎检索后,再进行一次过滤 Using temporary:MySQL对结果排序时会使用临时表 Using filesort:对结果使用一个外部索引排序

说明: type显示的是访问类型,是较为重要的一个指标,结果值从好到坏依次是:NULL> system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery >range > index > ALL ,一般来说,得保证查询至少达到range级别,最好能达到ref

类型 说明
All 最坏的情况,全表扫描
index 和全表扫描一样。只是扫描表的时候按照索引次序进行而不是行。主要优点就是避免了排序, 但是开销仍然非常大。如在Extra列看到Using index,说明正在使用覆盖索引,扫描索引的数据,它比按索引次序全表扫描的开销要小很多
range 范围扫描,一个有限制的索引扫描。key 列显示使用了哪个索引。当使用=、 <>、>、>=、<、<=、IS NULL、<=>、BETWEEN 或者 IN 操作符,用常量比较关键字列时,可以使用 range
ref 一种索引访问,它返回所有匹配某个单个值的行。此类索引访问只有当使用非唯一性索引或唯一性索引非唯一性前缀时才会发生。这个类型跟eq_ref不同的是,它用在关联操作只使用了索引的最左前缀,或者索引不是UNIQUE和PRIMARY KEY。ref可以用于使用=或<=>操作符的带索引的列。
eq_ref 最多只返回一条符合条件的记录。使用唯一性索引或主键查找时会发生 (高效)
const 当确定最多只会有一行匹配的时候,MySQL优化器会在查询前读取它而且只读取一次,因此非常快。当主键放入where子句时,mysql把这个查询转为一个常量(高效)
system 这是const连接类型的一种特例,表仅有一行满足条件。
Null 意味着mysql能在优化阶段分解查询语句,在执行阶段甚至用不到访问表或索引(高效)

8.4使用 profile 工具 监控

mysql 复制代码
#打开后,会显示语句执行详细的过程
set profiling = ON;
#查看语句,注意结果中的query_id值
show profiles ;
#显示语句的详细执行步骤和时长
Show profile for query #  
show profile for query 1;

9 并发控制

9.1锁机制

锁类型:

  • 读锁:共享锁,也称为 S 锁,只读不可写(包括当前事务) ,多个读互不阻塞 只能读 不能写 别人也能看
  • 写锁:独占锁,排它锁,也称为 X 锁,写锁会阻塞其它事务(不包括当前事务)的读和写 写锁 别人看都看不了
  • S 锁和 S 锁是兼容 的,X 锁和其它锁都不兼容 ,举个例子,事务 T1 获取了一个行 r1 的 S 锁,另外事务 T2 可以立即获得行 r1 的 S 锁,此时 T1 和 T2 共同获得行 r1 的 S 锁,此种情况称为锁兼容 ,但是另外一个事务 T2 此时如果想获得行 r1 的 X 锁,则必须等待 T1 对行 r1 锁的释放,此种情况也称为锁冲突

锁粒度:

  • 表级锁:MyISAM 存储引擎 mysql
  • 行级锁:InnoDB

实现

  • 存储引擎:自行实现其锁策略和锁粒度
  • 服务器级:实现了锁,表级锁,用户可显式请求

分类:

  • 隐式锁:由存储引擎自动施加锁

  • 显式锁:用户手动请求

    锁策略:在锁粒度及数据安全性寻求的平衡机制

mysql 复制代码
update students set teacherid=1 where stuid=6;   #同时在两个窗口执行只有一个能成功

加锁:
LOCK TABLES 表名 [[AS] alias] 锁的类别  [, tbl_name [[AS] alias] lock_type] ...

锁的类别:
读锁
写锁


lock tables students  read;   #加读锁
update students set classid=2 where stuid=24;
unlock  tables;     #释放锁

flush tables  with  read  lock;   #整个数据库加锁
unlock  tables;

9.2事务(transactions)

事务的概念

●事务是一种机制、一个操作序列,包含了一组数据库操作命令,并且把所有的命令作为一个整体一起向系统提交或撤销操作请求,即这一组数据库命令要么都执行,要么都不执行。

●事务是一个不可分割的工作逻辑单元,在数据库系统上执行并发操作时,事务是最小的控制单元。

●事务适用于多用户同时操作的数据库系统的场景,如银行、保险公司及证券交易系统等等。

●事务通过事务的整体性以保证数据的一致性。

●事务能够提高在向表中更新和插入信息期间的可靠性。

进到 数据库 当中

默认开启了一次事务

ACID特性:

A:atomicity 原子性;整个事务中的所有操作要么全部成功执行,要么全部失败后回滚

C:consistency一致性;数据库总是从一个一致性状态转换为另一个一致性状态,类似于质量守恒定律(A1wB 0 A1w 给 B转1w 始终保持A+B=1w)

I: Isolation隔离性;一个事务所做出的操作在提交之前,是不能为其它事务所见;隔离有多种隔离级别,实现并发.(不最后提交看不到,脏数D:durability持久性;一旦事务提交,其所做的修改会永久保存于数据库中

mysql 复制代码
begin  开启事务




set autocommit=0  #是否自动提交事务  退出后要再加
insert teachers values(5,'test',50,'M');
set autocommit=0
delete from teachers;
rollback;     # create  drop alter  这些撤回不了

insert teachers values(null,'test',30,'M');

事务的好处提高效率
truncate   table testlog;
call sp_testlog;  

begin;
call sp_testlog;commit;   


自动发现   事务自动 随机

死锁:
两个或多个事务在同一资源相互占用,并请求锁定对方占用的资源的状态
范例:找到未完成的导致阻塞的事务
BEGIN;
#开启事务
update students set classid=10;
#终端1

update students set classid=20;
#终端2

show engine innodb status;
#在第三个会话中执行

mysql: 增加 1条 commit 减少2条数据 commit 加2条数据 commit 减1条数据 commit

oracle: 增加 1条 减少2条数据 加2条数据 减1条数据 commit

9.2.1 事务隔离级别

MySQL 支持四种隔离级别,事务隔离级别从上至下更加严格

mysql 复制代码
select @@tx_isolation;    #系统隔离级别,是系统自带变量
+-----------------+
| @@tx_isolation  |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set, 1 warning (0.00 sec)

vim  /etc/my.cnf
transaction-isolation='READ-UNCOMMITTED|READ-COMMITTED|REPEATABLEREAD|SERIALIZABLE'

SET tx_isolation='READ-UNCOMMITTED|READ-COMMITTED|REPEATABLEREAD|SERIALIZABLE'
隔离级别 脏读 可重复读 幻读 加读锁
读未提交 可以出现 可以出现 可以出现
读提交 不允许出现 可以出现 可以出现
可重复读 不允许出现 不允许出现 可以出现
序列化 不允许出现 不允许出现 不允许出现
  • READ UNCOMMITTED 未提交可读 可读取到未提交数据,产生脏读
  • READ COMMITTED 提交可读 可读取到提交数据,但未提交数据不可读,产生不可重复读,即可读取到多个提交数据,导致每次读取数据不一致可读
  • REPEATABLE READ 幻读
    可重复读,多次读取数据都一致,产生幻读,即读取过程中,即使有其它提交的事务修改数据,仍只能读取到未修改前的旧数据。此为MySQL默认设置
  • SERIALIZABLE 串读
    可串行化,未提交的读事务阻塞修改事务(加读锁,但不阻塞读事务),或者未提交的修改事务阻塞其它事务的读写(加写锁,其它事务的读,写都不可以执行)。会导致并发性能差

事务隔离 级别

A 开启了一个事务

B 是看不到的

A commit 提交后才可以看到

MVCC和事务的隔离级别:

MVCC(多版本并发控制机制)只在READ COMMITTED和REPEATABLE READ两个隔离级别下工作。其他两个隔离级别都和MVCC不兼容,因为READ UNCOMMITTED总是读取最新的数据行,而不是符合当前事务版本的数据行。而SERIALIZABLE则会对所有读取的行都加锁

演示实例:

可重复读 默认是此隔离级别

mysql 复制代码
#1.打开两个终端的 数据库,都开启事务
use hellodb;
begin;


#在其中一个终端上插入数据在未提交前,另一个终端的事务无法看到修改的结果,但是自己可以看见
insert teachers values(5,'a',79,'M');
select * from teachers;

#终端1 提交后  终端2只要不结束事务还是看不到,需要提交事务后才可以看到。

演示第一隔离级别 可看见脏读

mysql 复制代码
vim /etc/my.cnf
[mysqld]
transaction-isolation=READ-UNCOMMITTED

systemctl restart mysqld

select @@tx_isolation;   #查看隔离级别 

begin;
#在其中一个终端上插入数据在未提交前,另一终端也可以看见
insert teachers values(6,'c',80,'M');
select * from teachers;

演示串行化 最严格的隔离级别

mysql 复制代码
vim /etc/my.cnf
[mysqld]
transaction-isolation=SERIALIZABLE
systemctl restart mysqld

begin;
#开启事务两边可以同时读表,会互相锁
select * from teachers;
delete from teachers where tid=5;
#无法删除加锁  并发性较差

10. 存储引擎

  • storage limits(存储上限): myisam 256t innodb64 但是mysql 根本达不到这么大的数据量
  • transactions(事务): myisam 不支持 innodb64 支持
  • locking granularity(锁级别): myiasam 表级 innodb64 行级
  • 提高mvcc(多版本的并发控制) : 提高数据库的并发性
  • data caches (数据缓存):
id name 插入时间 删除时间
1 白植淳 1000 1500
2 郑海杰 2000 3000
3 陈恳 3000 3500

3200

10.1 MyISAM 引擎特点

  • 不支持事务
  • 表级锁定
  • 读写相互阻塞,写入不能读,读时不能写
  • 只缓存索引
  • 不支持外键约束
  • 不支持聚簇索引
  • 读取数据较快,占用资源较少
  • 不支持MVCC(多版本并发控制机制)高并发
  • 崩溃恢复性较差
  • MySQL5.5.5 前默认的数据库引擎

MyISAM 存储引擎适用场景

  • 只读(或者写较少)
  • 表较小(可以接受长时间进行修复操作)

MyISAM 引擎文件

  • tbl_name.frm 表格式定义
  • tbl_name.MYD 数据文件
  • tbl_name.MYI 索引文件

10.2 InnoDB引擎特点

  • 行级锁
  • 支持事务,适合处理大量短期事务
  • 读写阻塞与事务隔离级别相关
  • 可缓存数据和索引
  • 支持聚簇索引
  • 崩溃恢复性更好
  • 支持MVCC高并发
  • 从MySQL5.5后支持全文索引
  • 从MySQL5.5.5开始为默认的数据库引擎

其它存储引擎

  • Performance_Schema:Performance_Schema数据库使用

  • Memory :将所有数据存储在RAM中,以便在需要快速查找参考和其他类似数据的环境中进行快速访问。适用存放临时数据。引擎以前被称为HEAP引擎

  • MRG_MyISAM:使MySQL DBA或开发人员能够对一系列相同的MyISAM表进行逻辑分组,并将它们作为一个对象引用。适用于VLDB(Very Large Data Base)环境,如数据仓库

  • Archive :为存储和检索大量很少参考的存档或安全审核信息,只支持SELECT和INSERT操作;支持行级锁和专用缓存区

  • Federated联合:用于访问其它远程MySQL服务器一个代理,它通过创建一个到远程MySQL服务器的客户端连接,并将查询传输到远程服务器执行,而后完成数据存取,提供链接单独MySQL服务器的能力,以便从多个物理服务器创建一个逻辑数据库。非常适合分布式或数据集市环境

  • BDB:可替代InnoDB的事务引擎,支持COMMIT、ROLLBACK和其他事务特性

  • Cluster/NDB:MySQL的簇式数据库引擎,尤其适合于具有高性能查找要求的应用程序,这类查找需求还要求具有最高的正常工作时间和可用性

  • CSV:CSV存储引擎使用逗号分隔值格式将数据存储在文本文件中。可以使用CSV引擎以CSV格式导入和导出其他软件和应用程序之间的数据交换

  • BLACKHOLE :黑洞存储引擎接受但不存储数据,检索总是返回一个空集。该功能可用于分布式数据库设计,数据自动复制,但不是本地存储

  • example:"stub"引擎,它什么都不做。可以使用此引擎创建表,但不能将数据存储在其中或从中检索。目的是作为例子来说明如何开始编写新的存储引擎

10.3管理存储引擎

查看mysql支持的存储引擎

mysql 复制代码
show engines;

show table status like 'user'\G   #这张表用的是 myisam
show table status from mysql\G ;

查看当前默认的存储引擎

复制代码
show variables like '%storage_engine%';

设置默认的存储引擎

复制代码
vim /etc/my.cnf
[mysqld]
default_storage_engine = InnoDB

查看库中所有表使用的存储引擎

复制代码
show table status from db_name;

查看库中指定表的存储引擎

复制代码
show table status like  'tb_name';
show create table tb_name;

设置表的存储引擎:

复制代码
CREATE TABLE tb_name(... ) ENGINE=InnoDB;
ALTER TABLE tb_name ENGINE=InnoDB;

10.4MySQL 中的系统数据库

  • mysql 数据库

是mysql的核心数据库,类似于Sql Server中的master库,主要负责存储数据库的用户、权限设置、关键字等mysql自己需要使用的控制和管理信息

  • information_schema 数据库

MySQL 5.0之后产生的,一个虚拟数据库,物理上并不存在information_schema数据库类似与"数据字典",提供了访问数据库元数据的方式,即数据的数据。比如数据库名或表名,列类型,访问权限(更加细化的访问方式)

  • performance_schema 数据库

MySQL 5.5开始新增的数据库,主要用于收集数据库服务器性能参数,库里表的存储引擎均为PERFORMANCE_SCHEMA,用户不能创建存储引擎为PERFORMANCE_SCHEMA的表

  • sys 数据库

MySQL5.7之后新增加的数据库,库中所有数据源来自performance_schema。目标是把performance_schema的把复杂度降低,让DBA能更好的阅读这个库里的内容。让DBA更快的了解DataBase的运行情况

10.5 存储过程

存储过程:多表SQL的语句的集合,可以独立执行,存储过程保存在mysql.proc表中

存储过程优势

存储过程把经常使用的SQL语句或业务逻辑封装起来,预编译保存在数据库中,当需要时从数据库中直接调用,省去了编译的过程,提高了运行速度,同时降低网络数据传输量

mysql 复制代码
delimiter//
create procedure  name(IN id int)
begin
 select * from  students where stuid = id;
END//
delimiter;

call  name(2);

11.日志

MySQL 支持丰富的日志类型,如下:

  • 事务日志:transaction log

    事务日志的写入类型为"追加",因此其操作为"顺序IO";通常也被称为:预写式日志 write ahead logging事务日志文件: ib_logfile0, ib_logfile1

  • 错误日志 error log

  • 通用日志 general log

  • 慢查询日志 slow query log

  • 二进制日志 binary log

  • 中继日志 reley log,在主从复制架构中,从服务器用于保存从主服务器的二进制日志中读取的事件

语法:

复制代码
CREATE PROCEDURE sp_name ([ proc_parameter [,proc_parameter ...]])
routime_body 
proc_parameter : [IN|OUT|INOUT] parameter_name type

例子:

mysql 复制代码
delimiter //
CREATE PROCEDURE selectById(IN id SMALLINT UNSIGNED)
BEGIN
 SELECT * FROM students WHERE stuid = id;
END//
delimiter ;
call selectById(2);

11.1 事务日志

事务日志:transaction log

  • redo log:实现 WAL(Write Ahead Log) ,数据更新前先记录redo log
  • undo log:保存与执行的操作相反的操作,用于实现rollback

事务型存储引擎自行管理和使用,建议和数据文件分开存放

Innodb事务日志相关配置:

mysql 复制代码
show variables like '%innodb_log%';
innodb_log_file_size   50331648 #每个日志文件大小  字节
innodb_log_files_in_group 2     #日志组成员个数
innodb_log_group_home_dir ./ #事务文件路径

ll -h /var/lib/mysql

事务日志性能优化

bash 复制代码
innodb_flush_log_at_trx_commit=0|1|2




select @@innodb_flush_log_at_trx_commit;
#查看默认值

1 此为默认值,日志缓冲区将写入日志文件,并在每次事务后执行刷新到磁盘。 这是完全遵守ACID特性


0 提交时没有写磁盘的操作; 而是每秒执行一次将日志缓冲区的提交的事务写入刷新到磁盘。 这样可提供更好的性能,但服务器崩溃可能丢失最后一秒的事务


2 每次提交后都会写入OS的缓冲区,但每秒才会进行一次刷新到磁盘文件中。 性能比0略差一些,但操作系统或停电可能导致最后一秒的交易丢失
级别 0 1 2
安全性 较高 最高 最高
性能 最高 最差 较高

双 1 调优

高并发业务行业最佳实践,是使用第三种折衷配置(=2):

1.配置为2和配置为0,性能差异并不大,因为将数据从Log Buffer拷贝到OS cache,虽然跨越用户态与内核态,但毕竟只是内存的数据拷贝,速度很快

2.配置为2和配置为0,安全性差异巨大,操作系统崩溃的概率相比MySQL应用程序崩溃的概率,小很多,设置为2,只要操作系统不奔溃,也绝对不会丢数据

双1设置:

说明:

  • 设置为1,同时sync_binlog = 1表示最高级别的容错 (二进制日志)

  • innodb_use_global_flush_log_at_trx_commit=0 时,将不能用SET语句重置此变量( MariaDB 10.2.6 后废弃)

演示:

mysql 复制代码
[root@localhost ~]# mysql  -uroot -p'自己的密码' 随便数据库 < testlog.sql
#生成测试环境
(root@localhost) [hellodb]> call sp_testlog;
#生成  一百万条数据


修改参数:
set  global innodb_flush_log_at_trx_commit=1;
select @@innodb_flush_log_at_trx_commit;
call sp_testlog;

11.2错误日志

错误日志

  • mysqld启动和关闭过程中输出的事件信息
  • mysqld运行中产生的错误信息
  • event scheduler运行一个event时产生的日志信息
  • 在主从复制架构中的从服务器上启动从服务器线程时产生的信息

错误文件路径

复制代码
SHOW GLOBAL VARIABLES LIKE 'log_error' ;

yum  安装
cat /var/log/mysqld.log

记录哪些警告信息至错误日志文件*

bash 复制代码
#CentOS7 mariadb 5.5 默认值为1
#CentOS8 mariadb 10.3 默认值为2
log_warnings=0|1|2|3...         #MySQL5.7之前
log_error_verbosity=0|1|2|3...   #MySQL8.0

例子:

bash 复制代码
SHOW GLOBAL VARIABLES LIKE 'log_warnings';

11.3通用日志

通用日志:记录对数据库的通用操作,包括:错误的SQL语句

通用日志可以保存在:file(默认值)或 table(mysql.general_log表)

通用日志相关设置

复制代码
general_log=ON|OFF
general_log_file=HOSTNAME.log
log_output=TABLE|FILE|NONE

例子:

mysql 复制代码
范例: 启用通用日志并记录至文件中

select @@general_log;     #默认没开启
set global general_log=1; #开启

SHOW GLOBAL VARIABLES LIKE 'log_output';
#默认通用日志存放在文件中
select @@general_log_file;
#通用日志存放的文件路径

11.4 慢查询日志

慢查询日志:记录执行查询时长超出指定时长的操作

慢查询相关变量

mysql 复制代码
slow_query_log=ON|OFF #开启或关闭慢查询,支持全局和会话,只有全局设置才会生成慢查询文件
long_query_time=N #慢查询的阀值,单位秒,默认为10s
slow_query_log_file=HOSTNAME-slow.log  #慢查询日志文件
log_slow_filter = admin,filesort,filesort_on_disk,full_join,full_scan,
query_cache,query_cache_miss,tmp_table,tmp_table_on_disk 
#上述查询类型且查询时长超过long_query_time,则记录日志
log_queries_not_using_indexes=ON  #不使用索引或使用全索引扫描,不论是否达到慢查询阀值的语
句是否记录日志,默认OFF,即不记录
log_slow_rate_limit = 1 #多少次查询才记录,mariadb特有
log_slow_verbosity= Query_plan,explain #记录内容
log_slow_queries = OFF    #同slow_query_log,MariaDB 10.0/MySQL 5.6.1 版后已删除


set  global slow_query_log=1;
#开启
set long_query_time=1;


select sleep(10)

11.5 二进制日志 备份

  • 记录导致数据改变或潜在导致数据改变的SQL语句

  • 记录已提交的日志

  • 不依赖于存储引擎类型

功能:通过"重放"日志文件中的事件来生成数据副本

注意:建议二进制日志和数据文件分开存放

二进制日志记录三种格式

基于"语句"记录:statement,记录语句,默认模式( MariaDB 10.2.3 版本以下 ),日志量较少

基于"行"记录:row,记录数据,日志量较大,更加安全,建议使用的格式,MySQL8.0默认格式

混合模式:mixed, 让系统自行判定该基于哪种方式进行,默认模式( MariaDB 10.2.4及版本以上)

mysql 复制代码
show variables like 'binlog_format';

二进制日志文件格式

mysql 复制代码
有两类文件
1.日志文件:mysql|mariadb-bin.文件名后缀,二进制格式,如: on.000001,mariadb-bin.000002
2.索引文件:mysql|mariadb-bin.index,文本格式,记录当前已有的二进制日志文件列表

二进制日志相关的服务器变量:

bash 复制代码
sql_log_bin=ON|OFF:
#是否记录二进制日志,默认ON,支持动态修改,系统变量,而非服务器选项
log_bin=mysql-bin      默认是关闭
#指定文件位置;默认OFF,表示不启用二进制日志功能,上述两项都开启才可以
binlog_format=STATEMENT|ROW|MIXED:
#二进制日志记录的格式,mariadb5.5默认STATEMENT
max_binlog_size=1073741824:
#单个二进制日志文件的最大体积,到达最大值会自动滚动,默认为1G
#说明:文件达到上限时的大小未必为指定的精确值
binlog_cache_size=4m 
#此变量确定在每次事务中保存二进制日志更改记录的缓存的大小(每次连接)
max_binlog_cache_size=512m 
#限制用于缓存多事务查询的字节大小。
sync_binlog=1|0:
#设定是否启动二进制日志即时同步磁盘功能,默认0,由操作系统负责同步日志到磁盘
expire_logs_days=N:
#二进制日志可以自动删除的天数。 默认为0,即不自动删除

在线查看 二进制

mysql 复制代码
SHOW BINLOG EVENTS [IN 'log_name'] [FROM pos] [LIMIT [offset,] row_count]
例子:
show binlog events in 'mysql-bin.000001' from 6516 limit 2,3

离线查看二进制日志

mysqlbinlog:二进制日志的客户端命令工具,支持离线查看二进制日志

命令格式:

mysql 复制代码
mysqlbinlog [OPTIONS] log_file...
 --start-position=# 指定开始位置
 --stop-position=#
 --start-datetime=  #时间格式:YYYY-MM-DD hh:mm:ss
 --stop-datetime= 
 --base64-output[=name]
        -v -vvv
        
# at 328
#151105 16:31:40 server id 1 end_log_pos 431   Query   thread_id=1     
exec_time=0     error_code=0
use `mydb`/*!*/;
SET TIMESTAMP=1446712300/*!*/;
CREATE TABLE tb1 (id int, name char(30))
/*!*/;  
事件发生的日期和时间:151105 16:31:40
事件发生的服务器标识:server id 1
事件的结束位置:end_log_pos 431
事件的类型:Query 
事件发生时所在服务器执行此事件的线程的ID:thread_id=1
语句的时间戳与将其写入二进制文件中的时间差:exec_time=0
错误代码:error_code=0
事件内容:
GTID:Global Transaction ID,mysql5.6以mariadb10以上版本专属属性:GTID

例子:

mysql 复制代码
mysqlbinlog --start-position=678 --stop-position=752 /var/lib/mysql/mariadb-bin.000003 -v
mysqlbinlog  --start-datetime="2018-01-30 20:30:10"   --stop-datetime="2018-01-
30 20:35:22" mariadb-bin.000003 -vvv

二进制日志事件的格式:

bash 复制代码
# at 328
#151105 16:31:40 server id 1 end_log_pos 431   Query   thread_id=1     
exec_time=0     error_code=0
use `mydb`/*!*/;
SET TIMESTAMP=1446712300/*!*/;
CREATE TABLE tb1 (id int, name char(30))
/*!*/;  
事件发生的日期和时间:151105 16:31:40
事件发生的服务器标识:server id 1
事件的结束位置:end_log_pos 431
事件的类型:Query 
事件发生时所在服务器执行此事件的线程的ID:thread_id=1
语句的时间戳与将其写入二进制文件中的时间差:exec_time=0
错误代码:error_code=0
事件内容:
GTID:Global Transaction ID,mysql5.6以mariadb10以上版本专属属性:GTID

12 备份

12.1备份类型

  • 完全备份,部分备份

  • 完全备份:整个数据集

  • 部分备份:只备份数据子集,如部分库或表

  • 完全备份、增量备份、差异备份

  • 增量备份:仅备份最近一次完全备份或增量备份(如果存在增量)以来变化的数据,备份较快,还原复杂

    增量备份

差异备份:仅备份最近一次完全备份以来变化的数据,备份较慢,还原简单

注意:二进制日志文件不应该与数据文件放在同一磁盘冷、温、热备份

  • 冷备:读、写操作均不可进行,数据库停止服务

  • 温备:读操作可执行;但写操作不可执行

  • 热备:读、写操作均可执行

MyISAM:温备,不支持热备 不支持 事务

InnoDB:都支持

  • cp, tar等复制归档工具:物理备份工具,适用所有存储引擎;只支持冷备;完全和部分备份

  • LVM的快照:先加读锁,做快照后解锁,几乎热备;借助文件系统工具进行备份

  • mysqldump:逻辑备份工具,适用所有存储引擎,对MyISAM存储引擎进行温备;支持完全或部

    分备份;对InnoDB存储引擎支持热备,结合binlog的增量备份

  • xtrabackup:由Percona提供支持对InnoDB做热备(物理备份)的工具,支持完全备份、增量备份

  • MariaDB Backup: 从MariaDB 10.1.26开始集成,基于Percona XtraBackup 2.3.8实现

  • mysqlbackup:热备份, MySQL Enterprise Edition 组件

  • mysqlhotcopy:PERL 语言实现,几乎冷备,仅适用于MyISAM存储引擎,使用LOCK TABLES、

    FLUSH TABLES和cp或scp来快速备份数据库

12.2完全备份

12.2.1 物理冷备份

通过打包备份 数据库文件夹的方式备份(一般用于数据库迁移)

备份方式: 冷备份,一定要先停数据库

备份工具: cp tar 等

InnoDB存储引擎的数据库在磁盘上存储成三个文件:db.opt(表属性文件)、表名.frm(表结构文件)、表名.ibd(表数据文件)。

例子:

bash 复制代码
cd  /var/lib/
#在需要备份的主机上进入到数据库文件夹

tar zcvf /opt/mysql_back.tar.gz  mysql
#打包数据库文件夹

cd  /opt
scp mysql_back.tar.gz 192.168.91.100:/opt/
#远程拷贝


第二台主机
tar xf mysql_back.tar.gz
#解压

cd /var/lib/
mv mysql mysql.bak  -r
#先备份原来的 数据库

cp -a /opt/mysql     /var/lib/
12.2.2 mysqldump 备份与恢复
http 复制代码
mysqldump [OPTIONS] database [tables]   
#支持指定数据库和指定多表的备份,但数据库本身定义不备份
mysqldump [OPTIONS] -B DB1 [DB2 DB3...]
#支持指定数据库备份,包含数据库本身定义也会备份
mysqldump [OPTIONS] -A [OPTIONS]       
#备份所有数据库,包含数据库本身定义也会备份

mysqldump 常见通用选项:

bash 复制代码
-A, --all-databases 
#备份所有数据库,含create database
-B, --databases db_name...  
#指定备份的数据库,包括create database语句
-E, --events:
#备份相关的所有event scheduler
-R, --routines:
#备份所有存储过程和自定义函数
--triggers:
#备份表相关触发器,默认启用,用--skip-triggers,不备份触发器
-d, --no-data    
#只备份表结构,不备份数据,即只备份create table 
-t, --no-create-info 
#只备份数据,不备份表结构,即不备份create table 
-n,--no-create-db 
#不备份create database,可被-A或-B覆盖
--flush-privileges 
#备份mysql或相关时需要使用
-f, --force       
#忽略SQL错误,继续执行
--hex-blob        
#使用十六进制符号转储二进制列,当有包括BINARY, VARBINARY,BLOB,BIT的数据类型的列时使用,避免乱码
-q, --quick     
#不缓存查询,直接输出,加快备份速度

脚本

bash 复制代码
#!/bin/bash
TIME=`date +%F_%H-%M-%S`
DIR=/backup
DB=hellodb
PASS=magedu
[ -d $DIR ] || mkdir $DIR
mysqldump -uroot -p "$PASS" -F -E -R --triggers  --single-transaction --master-data=2 --default-character-set=utf8 -q  -B $DB | gzip > 
${DIR}/${DB}_${TIME}.sql.gz

1)完全备份一个或多个完整的库(包括其中所有的表)

语法:

bash 复制代码
mysqldump -u root -p[密码] --databases 库名1 [库名2] ... > /备份路径/备份文件名.sql	
#导出的就是数据库脚本文件

例子:

bash 复制代码
mysqldump -uroot -p'Admin@123' hellodb  > /data/hellodb.sql
#单库   --databases   不加无法保存库名,加了会保存库名

mysqldump -uroot -p'Admin@123' --databases hellodb db1  > /data/hellodb.sql
#多库

mysqldump -uroot -p'Admin@123' --all-databases > /data/all_data.sql
#全库

mysqldump -uroot -p'Admin@123' hellodb students > /data/students.sql
#单表

mysqldump -uroot -p'Admin@123' hellodb students teachers > /data/students.sql
#多表

mysqldump -uroot -p'Admin@123' -d  hellodb  students > /data/students.sql
#只保留表结构  -d



mysql -uroot -pAdmin@123 < /data/hellodb.sql

恢复例子:

bash 复制代码
mysql -uroot -pAdmin@123 -e 'show databases;'
#-e  在linux中执行数据库

mysql -uroot -pAdmin@123 -e 'drop database hellodb;'
# 删库

mysql -uroot -pAdmin@123 < /data/hellodb.sql

mysql -uroot -pAdmin@123 -e 'create database hellodb;'
mysql -uroot -pAdmin@123 hellodb < /data/hellodb.sql·
mysql -uroot -pAdmin@123 -e 'show tables from hellodb;'

12.3 增量备份恢复

备份

bash 复制代码
1开启二进制日志功能
vim /etc/my.cnf
[mysqld]
log-bin = mysql-bin
binlog_format = MIXED				#可选,指定二进制日志(binlog)的记录格式为 MIXED
server-id = 1

#二进制日志(binlog)有3种不同的记录格式:STATEMENT(基于SQL语句)、ROW(基于行)、MIXED(混合模式),默认格式是STATEMENT


systemctl restart mysqld
ls -l /var/lib/mysql-bin.*

2可每周对数据库或表进行完全备份
mysqldump -u root -pAdmin@123 hellodb students > /opt/my_h_s_$(date +%F).sql
mysqldump -u root -p --databases hellodb > /opt/my_$(date +%F).sql

3.可每天进行增量备份操作,生成新的二进制日志文件(例如 mysql-bin.000002)
mysqladmin -u root -p flush-logs

4.插入新数据,以模拟数据的增加或变更
use kgc;
insert into students values(3,'user3','male','game');
insert into students values(4,'user4','female','reading');

5.再次生成新的二进制日志文件(例如 mysql-bin.000003)
mysqladmin -u root -p flush-logs
#之前的步骤4的数据库操作会保存到mysql-bin.000002文件中,之后数据库数据再发生变化则保存在mysql-bin.000003文件中

6.查看二进制日志文件的内容
cp /usr/local/mysql/data/mysql-bin.000002 /opt/
mysqlbinlog --no-defaults --base64-output=decode-rows -v /opt/mysql-bin.000002
#--base64-output=decode-rows:使用64位编码机制去解码并按行读取
#-v:显示详细内容

恢复

bash 复制代码
1.一般恢复
(1)模拟丢失更改的数据的恢复步骤
use kgc;
delete from info1 where id=3;
delete from info1 where id=4;

mysqlbinlog --no-defaults /opt/mysql-bin.000002 | mysql -u root -pAdmin@123

(2)模拟丢失所有数据的恢复步骤
use kgc;
drop table info1;



2.断点恢复
mysqlbinlog --no-defaults --base64-output=decode-rows -v /opt/mysql-bin.000002
例:
# at 302
#201122 16:41:16
插入了"user3"的用户数据

# at 623
#201122 16:41:24
插入了"user4"的用户数据


(1)基于位置恢复
#仅恢复到操作 ID 为"623"之前的数据,即不恢复"user4"的数据
mysqlbinlog --no-defaults --stop-position='623' /opt/mysql-bin.000002 | mysql -uroot -p

#仅恢复"user4"的数据,跳过"user3"的数据恢复
mysqlbinlog --no-defaults --start-position='682' /opt/mysql-bin.000002 | mysql -uroot -p

(2)基于时间点恢复
#仅恢复到 16∶41∶24 之前的数据,即不恢复"user4"的数据
mysqlbinlog --no-defaults --stop-datetime='2020-11-22 16:41:24' /opt/mysql-bin.000002 |mysql -uroot -p

#仅恢复"user4"的数据,跳过"user3"的数据恢复
mysqlbinlog --no-defaults --start-datetime='2020-11-22 16:41:24' /opt/mysql-bin.000002 |mysql -uroot -p


如果恢复某条SQL语句之前的所有数据,就stop在这个语句的位置节点或者时间点
如果恢复某条SQL语句以及之后的所有数据,就从这个语句的位置节点或者时间点start

13.主从复制

服务性能扩展方式

一台 mysql 数据库是有

  • Scale Up,向上扩展,垂直扩展
  • Scale Out,向外扩展,横向扩展

13.1MySQL主从复制

13.1.1主从复制架构和原理
13.1.1.1 MySQL的主从复制
  • 读写分离

  • 复制:每个节点都有相同的数据集,向外扩展,基于二进制日志的单向复制

13.1.1.2 复制的功用
  • 负载均衡读操作
  • 备份
  • 高可用和故障切换
  • 数据分布
  • MySQL升级
13.1.1.3复制架构

一主一从复制架构 读写分离

一主多从复制架构

13.1.1.4 主从复制原理
复制代码
主从复制原理:
1主节点负责用户的写操作,用户发起写操作后,会修改数据库
2.数据库修改后,会更新主节点上的二进制日志
3.主服务器会产生一个  dump线程, 一边读取二进制日志一边将二进制日志通过 网络传给从服务器
4.从服务器会开启io线程,接收主服务器的二进制日志
5 会写入中继日志,这时只是生成了一个文件,并没有同步
6.从服务器再开启  sql线程将 中继日志中  操作写入数据库完成更新

主从复制相关线程

主节点:

dump Thread:为每个Slave的I/O Thread启动一个dump线程,用于向其发送binary log events从节点:

I/O Thread:向Master请求二进制日志事件,并保存于中继日志中

SQL Thread:从中继日志中读取日志事件,在本地完成同步

跟复制功能相关的文件:

  • master.info:用于保存slave连接至master时的相关信息,例如账号、密码、服务器地址等

  • relay-log.info:保存在当前slave节点上已经复制的当前二进制日志和本地relay log日志的对应关系

  • mysql-relay-bin.00000#: 中继日志,保存从主节点复制过来的二进制日志,本质就是二进制日志

中继日志 (relay log)只在主从服务器架构的从服务器上存在 。从服务器(slave)为了与主服务器(Master)保持一致,要从主服务器读取二进制日志的内容,并且把读取到的信息写入本地的日志文件 中,这个从服务器本地的日志文件就叫中继日志 。然后,从服务器读取中继日志,并根据中继日志的内容对从服务器的数据进行更新,完成主从服务器的数据同步

搭建好主从服务器之后,中继日志默认会保存在从服务器的数据目录下。

文件名的格式是:从服务器名 - relay-bin.序号。中继日志还有一个索引文件:从服务器名 - relay-bin.index,用来定位当前正在使用的中继日志。

13.1.1.5主从复制特点
  • 异步复制: 客户端性能良好
  • 主从数据不一致比较常见
13.1.1.6 各种复制架构
  • 一Master/一Slave
  • 一主多从
  • 从服务器还可以再有从服务器(减少主节点的性能压力,距离较远)
  • Master/Master
  • 一从多主:适用于多个不同数据库
  • 环状复制

复制需要考虑二进制日志事件记录格式

  • STATEMENT(5.0之前), Mariadb5.5 默认使用此格式
  • ROW(5.1之后,推荐),MySQL 8.0 默认使用此格式
  • MIXED: Mariadb10.3 默认使用此格式
13.1.2 实现主从复制配置

官网参考

http 复制代码
https://dev.mysql.com/doc/refman/8.0/en/replication-configuration.html
https://dev.mysql.com/doc/refman/5.7/en/replication-configuration.html
https://dev.mysql.com/doc/refman/5.5/en/replication-configuration.html
https://mariadb.com/kb/en/library/setting-up-replication/

主节点配置:

(1) 启用二进制日志

复制代码
主节点配置:
 (1) 启用二进制日志

(2) 为当前节点设置一个全局惟一的ID号

bash 复制代码
[mysqld]
server-id=#          #区分自己的日志 和别人的日志
log-basename=master  #可选项,设置datadir中日志名称,确保不依赖主机名

说明:

http 复制代码
server-id的取值范围
1 to 4294967295 (>= MariaDB 10.2.2),默认值为1
0 to 4294967295 (<= MariaDB 10.2.1),默认值为0,如果从节点为0,所有master都将拒绝此
slave的连接

(3) 查看从二进制日志的文件和位置开始进行复制

复制代码
SHOW MASTER STATUS;

(4) 创建有复制权限的用户账号

mysql 复制代码
GRANT REPLICATION SLAVE  ON *.* TO 'repluser'@'HOST' IDENTIFIED BY 'replpass';


#MySQL8.0 分成两步实现
mysql> create user repluser@'10.0.0.%' identified by '123456';
mysql> grant replication slave on *.* to repluser@'10.0.0.%';

从节点配置:

(1) 启动中继日志

bash 复制代码
[mysqld]
server_id=# 								#为当前节点设置一个全局惟的ID号
log-bin
read_only=ON 								#设置数据库只读,针对supper user无效
relay_log=relay-log 						#relay log的文件路径,默认值hostname-relay-bin
relay_log_index=relay-log.index  			#默认值hostname-relay-bin.index

(2) 使用有复制权限的用户账号连接至主服务器,并启动复制线程

bash 复制代码
CHANGE MASTER TO 
MASTER_HOST='192.168.', 
MASTER_USER='repluser', 
MASTER_PASSWORD='replpass', 
MASTER_LOG_FILE='mariadb-bin.xxxxxx', 
MASTER_LOG_POS=#;


START SLAVE [IO_THREAD|SQL_THREAD];
SHOW SLAVE STATUS;

范例:新建主从复制

主节点:

bash 复制代码
[root@localhost ~]#vim  /etc/my.cnf
#修改文件
[mysqld]
server_id=100
log-bin=/data/mysql/mysql-bin

[root@localhost ~]#mkdir /data/mysql/   -p
#建立文件夹
[root@localhost ~]#chown mysql.mysql /data/ -R
#注意修改权限
[root@localhost ~]#systemctl restart mysqld

select @@server_id;
#可以查看serverid  默认都是1
show master status;
#查看二进制日志位置


grant replication slave on *.* to test@'192.168.91.%' identified by 'Admin@123';
#建立复制用户

show processlist;
#查看线程

从节点

mysql 复制代码
[root@localhost ~]#vim  /etc/my.cnf
#修改文件
[mysqld]
server_id=102
log-bin=/data/mysql/mysql-bin
relay-log=relay-log-bin
relay-log-index=slave-relay-bin.index
#read only  #只读可加


[root@localhost ~]#mkdir /data/mysql/   -p
#建立文件夹
[root@localhost ~]#chown mysql.mysql /data/ -R
#注意修改权限
[root@localhost ~]#systemctl restart mysqld


CHANGE MASTER TO
  MASTER_HOST='192.168.91.100',
  MASTER_USER='test',
  MASTER_PASSWORD='Admin@123',
  MASTER_PORT=3306,
  MASTER_LOG_FILE='mysql-bin.001',
  MASTER_LOG_POS=448;



下面修改配置 命令较长可以使用帮助
help change master to


CHANGE MASTER TO
  MASTER_HOST='192.168.91.100',
  MASTER_USER='test',
  MASTER_PASSWORD='Admin@123',
  MASTER_PORT=3306,
  MASTER_LOG_FILE='mysql-bin.000001',
  MASTER_LOG_POS=448;
  注意最后分号

CHANGE MASTER TO
  MASTER_HOST='192.168.91.100',
  MASTER_USER='test',
  MASTER_PASSWORD='Admin@123',
  MASTER_PORT=3306,
  MASTER_LOG_FILE='mysql-bin.000001',
  MASTER_LOG_POS=154;


show slave status\G;
#查看设置的状态
Seconds_Behind_Master: NULL    #目前数据差

start slave;
#开启线程,开启主从复制



create database cxk;
#在主节点上建立数据测试

13.2主从复制 实战

假设主节点的数据库已经运行了一段时间,产生了一定量的数据,主从复制只能复制开启后数据,那之前的数据如何处理?

主节点

bash 复制代码
[root@localhost ~]#mysql -uroot -pAdmin@123 <hellodb_innodb.sql 



[root@localhost ~]#vim  /etc/my.cnf
#修改文件
[mysqld]
server_id=100
log-bin=/data/mysql/mysql-bin

[root@localhost ~]#mkdir /data/mysql/   -p
#建立文件夹
[root@localhost ~]#chown mysql.mysql /data/ -R
#注意修改权限
[root@localhost ~]#systemctl restart mysqld


mysqldump -uroot -p'Admin@123' -A -F --master-data=1 --single-transaction > /data/all.sql
#备份数据库      
-A      --all-databases      
-F      刷新日志
--master-data=1      会将 master 的修改语句写入dump文件中  1是写入   2是写入但是会被注释不生效
--single-transaction  已开启事务的方式备份

查看备份文件会生成  位置


scp /data/all.sql 192.168.91.101:/data/
#将备份文件拷贝过去

grant replication slave on *.* to test@'192.168.91.%' identified by 'Admin@123';
#建立复制用户

从节点

bash 复制代码
root@localhost ~]#vim  /etc/my.cnf
#修改文件
[mysqld]
server_id=102
log-bin=/data/mysql/mysql-bin
relay-log=relay-log-bin
relay-log-index=slave-relay-bin.index
#read only  #只读可加

[root@localhost ~]#mkdir /data/mysql/   -p
#建立文件夹
[root@localhost ~]#chown mysql.mysql /data/ -R
#注意修改权限
[root@localhost ~]#systemctl restart mysqld

[root@node2 data]#vim all.sql 
#直接在此配置文件中修改就可以了
  22 CHANGE MASTER TO
   MASTER_HOST='192.168.91.100',
   MASTER_USER='test',
   MASTER_PASSWORD='Admin@123',
   MASTER_PORT=3306,
  27  MASTER_LOG_FILE='mysql-bin.000002', MASTER_LOG_POS=154;
  
mysql> source /data/all.sql
mysql> show slave status \G
mysql> start slave;
mysql> show slave status \G

cat .mysql_history 
#看数据库的历史命令

13.3 复制错误解决方法

可以在从服务器忽略几个主服务器的复制事件,此为global变量,或指定跳过事件的ID

bash 复制代码
#系统变量,指定跳过复制事件的个数
SET GLOBAL sql_slave_skip_counter = N
#服务器选项,只读系统变量,指定跳过事件的ID
[mysqld]
slave_skip_errors=1007|ALL  

范例:复制冲突的解决

mysql 复制代码
create table info (id int,name char(10),age char(10));
#先在从上建表


#再在主上建表  插入信息
create table info (id int,name char(10),age char(10));
insert info values(1,'a',10);

#此时报错 从主机会报错
show  slave  status\G

#可以跳过错误
stop slave;
set global sql_slave_skip_counter=1;
start slave;

#方法2
vim /etc/my.cnf.d/mariadb-server.cnf
[mysqld]
slave_skip_errors=1007|ALL 

#systemctl restart mysqld

更换主从

复制代码
reset slave  all;
#清空主从配置

13.4 级联 主从复制

需要在中间的从服务器启用以下配置 ,实现中间slave节点能将master的二进制日志在本机进行数据库更新,并且也同时更新本机的二进制,从而实现级联复制

bash 复制代码
[mysqld]
server-id=18
log_bin
log_slave_updates     #级联复制中间节点的必选项,MySQL8.0此为默认值,可以不要人为添加
read-only

实例:

主节点

bash 复制代码
root@localhost ~]#vim  /etc/my.cnf
#修改文件
[mysqld]
server_id=100
log-bin=/data/mysql/mysql-bin

[root@localhost ~]#mkdir /data/mysql/   -p
#建立文件夹
[root@localhost ~]#chown mysql.mysql /data/ -R
#注意修改权限
[root@localhost ~]#systemctl restart mysqld


select @@server_id;
#可以查看serverid  默认都是1
show master status;
#查看二进制日志位置


grant replication slave on *.* to test@'192.168.91.%' identified by 'Admin@123';
#建立复制用户

show processlist;
#查看线程

2级节点

bash 复制代码
root@localhost ~]#vim  /etc/my.cnf
#修改文件
[mysqld]
server_id=101
log-bin=/data/mysql/mysql-bin
relay-log=relay-log-bin
relay-log-index=slave-relay-bin.index
log_slave_updates
#read only  #只读可加


[root@localhost ~]#mkdir /data/mysql/   -p
#建立文件夹
[root@localhost ~]#chown mysql.mysql /data/ -R
#注意修改权限
[root@localhost ~]#systemctl restart mysqld



下面修改配置 命令较长可以使用帮助
help change master to


CHANGE MASTER TO
  MASTER_HOST='192.168.91.100',
  MASTER_USER='test',
  MASTER_PASSWORD='Admin@123',
  MASTER_PORT=3306,
  MASTER_LOG_FILE='mysql-bin.000001',
  MASTER_LOG_POS=154;
  注意最后分号




show slave status\G;
#查看设置的状态
Seconds_Behind_Master: NULL    #目前数据差

start slave;
#开启线程,开启主从复制

show master logs;
#查看  从节点的复制位置

从节点

bash 复制代码
root@localhost ~]#vim  /etc/my.cnf
#修改文件
[mysqld]
server_id=102
log-bin=/data/mysql/mysql-bin
relay-log=relay-log-bin
relay-log-index=slave-relay-bin.index
#read only  #只读可加


[root@localhost ~]#mkdir /data/mysql/   -p
#建立文件夹
[root@localhost ~]#chown mysql.mysql /data/ -R
#注意修改权限
[root@localhost ~]#systemctl restart mysqld



下面修改配置 命令较长可以使用帮助
help change master to


CHANGE MASTER TO
  MASTER_HOST='192.168.91.101',
  MASTER_USER='test',
  MASTER_PASSWORD='Admin@123',
  MASTER_PORT=3306,
  MASTER_LOG_FILE='mysql-bin.000001',
  MASTER_LOG_POS=448;
  注意最后分号




show slave status\G;
#查看设置的状态
Seconds_Behind_Master: NULL    #目前数据差

start slave;
#开启线程,开启主从复制

13.5 半同步复制

默认情况下,MySQL的复制功能是异步的,异步复制可以提供最佳的性能,主库把binlog日志发送给从库即结束,并不验证从库是否接收完毕。这意味着当主服务器或从服务器端发生故障时,有可能从服务器没有接收到主服务器发送过来的binlog日志,这就会造成主服务器和从服务器的数据不一致,甚至在恢复时造成数据的丢失

实现:

bash 复制代码
rpm -ql mysql-community-server |grep semisync
#需要安装插件

[root@localhost ~]#vim  /etc/my.cnf
#修改文件
[mysqld]
server_id=100
log-bin=/data/mysql/mysql-bin
rpl_semi_sync_master_enabled=ON
rpl_semi_sync_master_timeout=3000
#修改此行,需要先安装semisync_master.so插件后,再重启,否则无法启动 开启半同步
#设置3s内无法同步,也将返回成功信息给客户端

[root@localhost ~]#mkdir /data/mysql/   -p
#建立文件夹
[root@localhost ~]#chown mysql.mysql /data/ -R
#注意修改权限
[root@localhost ~]#systemctl restart mysqld
[root@localhost ~]#mysql -uroot -pAdmin@123

mysql>INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so'; #永久安装插件
mysql>UNINSTALL PLUGIN rpl_semi_sync_master ;
mysql>rpm -ql mysql-community-server |grep semisync #查看插件
mysql>SET GLOBAL rpl_semi_sync_master_enabled=1; #临时修改变量
mysql>SET GLOBAL rpl_semi_sync_master_timeout = 3000;  #超时长1s,默认值为10s

mysql>SHOW GLOBAL VARIABLES LIKE '%semi%';
#查看半同步状态

show global status like '%semi%';
#查看半同步客户端

show  master  status;

grant replication slave on *.* to test@'192.168.91.%' identified by 'Admin@123';
#建立复制用户

从节点

bash 复制代码
INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
#安装插件

[root@slave1 ~]#vim /etc/my.cnf
[mysqld]
server-id=101
rpl_semi_sync_slave_enabled=ON #修改此行,需要先安装semisync_slave.so插件后,再重启,否则无法启动


CHANGE MASTER TO
  MASTER_HOST='192.168.91.100',
  MASTER_USER='test',
  MASTER_PASSWORD='Admin@123',
  MASTER_PORT=3306,
  MASTER_LOG_FILE='mysql-bin.000001',
  MASTER_LOG_POS=154;
  注意最后分号
  
  
  
show global status like '%semi%';
#查看状态  主从状态


mysql>INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
mysql>SET GLOBAL rpl_semi_sync_slave_enabled=1; #临时修改变量
mysql> SHOW GLOBAL VARIABLES LIKE '%semi%';

13.6 面试重点

13.6.1造成主从不一致的原因
  • 主库binlog格式为 Statement ,同步到从库执行后可能造成主从不一致。
  • 主库执行更改前有执行set sql_log_bin=0,会使主库不记录binlog,从库也无法变更这部分数据。
  • 从节点未设置只读,误操作写入数据
  • 主库或从库意外宕机,宕机可能会造成binlog或者relaylog文件出现损坏,导致主从不一致
  • 主从实例版本不一致,特别是高版本是主,低版本为从的情况下,主数据库上面支持的功能,从数
  • 据库上面可能不支持该功能
  • MySQL自身bug导致
13.6.2 主从不一致修复方法
  • 将从库重新实现

虽然这也是一种解决方法,但是这个方案恢复时间比较慢,而且有时候从库也是承担一部分的查询操作的,不能贸然重建。

  • 使用percona-toolkit工具辅助

PT工具包中包含pt-table-checksum和pt-table-sync两个工具,主要用于检测主从是否一致以及修复数据不一致情况。这种方案优点是修复速度快,不需要停止主从辅助,缺点是需要知识积累,需要时间去学习,去测试,特别是在生产环境,还是要小心使用关于使用方法,可以参考下面链接:https://www.cnblogs.com/feiren/p/7777218.html

  • 手动重建不一致的表

在从库发现某几张表与主库数据不一致,而这几张表数据量也比较大,手工比对数据不现实,并且重做整个库也比较慢,这个时候可以只重做这几张表来修复主从不一致这种方案缺点是在执行导入期间需要暂时停止从库复制,不过也是可以接受的

复制代码
数据不一致如何修复
 删除从数据库,重新复制
 
 
 数据损坏或丢失
Master:MHA + semisync replication
Slave: 重新复制


复制延迟
需要额外的监控工具的辅助
一从多主:mariadb10 版后支持
多线程复制:对多个数据库复制

14 MySQL 中间件代理服务器

数据库主要分为两大类:关系型数据库与 NoSQL 数据库。

关系型数据库,是建立在关系模型基础上的数据库,其借助于集合代数等数学概念和方法来处理数据库中的数据。主流的 MySQL、Oracle、MS SQL Server 和 DB2 都属于这类传统数据库。NoSQL 数据库,全称为 Not Only SQL,意思就是适用关系型数据库的时候就使用关系型数据库,不适用的时候也没有必要非使用关系型数据库不可,可以考虑使用更加合适的数据存储。主要分为临时性键值存储(Redis、memcached)、永久性键值存储(ROMA、Redis)、面向文档的数据库(MongoDB、CouchDB)、面向列的数据库(Cassandra、HBase),每种 NoSQL 都有其特有的使用场景及优点。

Oracle,mysql 等传统的关系数据库非常成熟并且已大规模商用,为什么还要用 NoSQL 数据库呢?主要是由于随着互联网发展,数据量越来越大,对性能要求越来越高,传统数据库存在着先天性的缺陷,即单机(单库)性能瓶颈,并且扩展困难。这样既有单机单库瓶颈,却又扩展困难,自然无法满足日益增长的海量数据存储及其性能要求,所以才会出现了各种不同的 NoSQL 产品,NoSQL 根本性的优势在于在云计算时代,简单、易于大规模分布式扩展,并且读写性能非常高

RDBMS和NOSQL的特点及优缺点:

MySQL 中间件各种应用

14.1 mycat

Mycat应用场景
  • Mycat适用的场景很丰富,以下是几个典型的应用场景
    • 单纯的读写分离,此时配置最为简单,支持读写分离,主从切换
    • 分表分库,对于超过1000万的表进行分片,最大支持1000亿的单表分片
    • 多租户应用,每个应用一个库,但应用程序只连接Mycat,从而不改造程序本身,实现多租户化报表系统,借助于Mycat的分表能力,处理大规模报表的统计
    • 替代Hbase,分析大数据,作为海量数据实时查询的一种简单有效方案,比如100亿条频繁查询的记录需要在3秒内查询出来结果,除了基于主键的查询,还可能存在范围查询或其他属性查询,此时Mycat可能是最简单有效的选择
  • Mycat长期路线图
    • 强化分布式数据库中间件的方面的功能,使之具备丰富的插件、强大的数据库智能优化功能、全面的系统监控能力、以及方便的数据运维工具,实现在线数据扩容、迁移等高级功能进一步挺进大数据计算领域,深度结合Spark Stream和Storm等分布式实时流引擎,能够完成快速的巨表关联、排序、分组聚合等 OLAP方向的能力,并集成一些热门常用的实时分析算法,让工程师以及DBA们更容易用Mycat实现一些高级数据分析处理功能不断强化Mycat开源社区的技术水平,吸引更多的IT技术专家,使得Mycat社区成为中国的Apache,并将Mycat推到Apache基金会,成为国内顶尖开源项目,最终能够让一部分志愿者成为专职的Mycat开发者,荣耀跟实力一起提升
mycat 可以简单概括为
  • 一个彻底开源的,面向企业应用开发的大数据库集群

  • 支持事务、ACID、可以替代MySQL的加强版数据库

  • 一个可以视为MySQL集群的企业级数据库,用来替代昂贵的Oracle集群

  • 一个融合内存缓存技术、NoSQL技术、HDFS大数据的新型SQL Server

  • 结合传统数据库和新型分布式数据仓库的新一代企业级数据库产品

  • 一个新颖的数据库中间件产品

mycat部署
mycat安装目录结构说明
  • bin :mycat命令,启动、重启、停止等运行目录
  • catlet: catlet为Mycat的一个扩展功能
  • conf :mycat 配置信息,重点关注
  • lib:mycat引用的jar包,Mycat是java开发的
  • logs日志文件,包括Mycat启动的日志和运行的日志
  • version.txt :mycat版本说明
Mycat的常用配置文件

Mycat的配置文件都在conf目录里面,这里介绍几个常用的文件:

  • server.xml :Mycat软件本身相关的配置文件,设置账号、参数等
  • schema.xml:Mycat对应的物理数据库和数据库表的配置,读写分离、高可用、分布式策略定制、节点控制
  • rule.xml:Mycat分片(分库分表)规则配置文件,记录分片规则列表、使用方法等
3.3 Mycat日志

Mycat的日志文件都在logs目录里面

  • wrapper.log :mycat启动日志
  • mycat.log :mycat详细工作日志
3.4 mycat 实现读写分离
1.环境准备

mycat服务器上不能装mysql

master服务器 192.168.59.113
slave1服务器 192.168.59.112
mycat服务器 192.168.59.114
客户机 192.168.59.118
2.初始化环境
bash 复制代码
#每台服务器上都初始化,关闭防火墙
systemctl stop --now firewalld
systemctl disable firewalld
setenforce 0
3.部署主从复制
bash 复制代码
###################### 主mysql服务器配置(192.168.91.100)########################
[root@localhost ~]#vim  /etc/my.cnf
#修改文件
[mysqld]
server_id=100
log-bin=/data/mysql/mysql-bin

[root@localhost ~]#mkdir /data/mysql/   -p
#建立文件夹
[root@localhost ~]#chown mysql.mysql /data/ -R
#注意修改权限
[root@localhost ~]#systemctl restart mysqld

select @@server_id;
#可以查看serverid  默认都是1
show master status;
#查看二进制日志位置


grant replication slave on *.* to test@'192.168.91.%' identified by 'Admin@123';
#建立复制用户

show processlist;
#查看线程


############################# 从mysql服务器配置(192.168.91.101)################
[root@localhost ~]#vim  /etc/my.cnf
#修改文件
[mysqld]
server_id=101
log-bin=/data/mysql/mysql-bin
relay-log=relay-log-bin
relay-log-index=slave-relay-bin.index
#read only  #只读可加


[root@localhost ~]#mkdir /data/mysql/   -p
#建立文件夹
[root@localhost ~]#chown mysql.mysql /data/ -R
#注意修改权限
[root@localhost ~]#systemctl restart mysqld



下面修改配置 命令较长可以使用帮助
help change master to


CHANGE MASTER TO
  MASTER_HOST='192.168.91.100',
  MASTER_USER='test',
  MASTER_PASSWORD='Admin@123',
  MASTER_PORT=3306,
  MASTER_LOG_FILE='mysql-bin.000001',
  MASTER_LOG_POS=448;
  注意最后分号

CHANGE MASTER TO
  MASTER_HOST='192.168.91.100',
  MASTER_USER='test',
  MASTER_PASSWORD='Admin@123',
  MASTER_PORT=3306,
  MASTER_LOG_FILE='mysql-bin.000001',
  MASTER_LOG_POS=154;


show slave status\G;
#查看设置的状态
Seconds_Behind_Master: NULL    #目前数据差

start slave;
#开启线程,开启主从复制



create database cxk;
#在主节点上建立数据测试


####################### 在master服务器上上传库文件,并在从服务器上验证主从同步 ############

#在主服务器上下载hellodb库文件,source后加绝对路径
[root@localhost ~]#mysql -uroot -pAdmin@123
#下载hellodb库文件
source /bak/hellodb.sql
show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| hellodb            |
| mysql              |
| performance_schema |
| sys                |
+--------------------+

#在从库中查看库文件hellodb是否已经同步
show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| hellodb            |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
4.安装mycat(192.168.59.114)
bash 复制代码
(1)主机上安装java(mycat基于java)
#yum安装java
[root@localhost ~]#yum install java -y
#确认安装成功
[root@localhost ~]#java -version
openjdk version "1.8.0_131"
OpenJDK Runtime Environment (build 1.8.0_131-b12)
OpenJDK 64-Bit Server VM (build 25.131-b12, mixed mode)

(2)切换至opt目录,下载mycat安装包
[root@localhost ~]#cd /opt
[root@localhost ~]#wget http://dl.mycat.org.cn/1.6.7.6/20210303094759/Mycat-server-1.6.7.6-release-20210303094759-linux.tar.gz

(3)创建/apps文件夹,并解压mycat包至/apps下
[root@localhost ~]#mkdir /apps
[root@localhost ~]#tar zxvf Mycat-server-1.6.7.6-release-20210303094759-linux.tar.gz -C /apps/

(4)设置变量环境
[root@localhost ~]#echo 'PATH=/apps/mycat/bin:$PATH' > /etc/profile.d/mycat.sh
[root@localhost ~]#source /etc/profile.d/mycat.sh

(5)启动mycat,查看日志文件,最后可以看到启动成功
[root@localhost ~]#mycat start
#注意内存小于2G 起不来
Starting Mycat-server...

[root@localhost ~]#tail -f /apps/mycat/logs/wrapper.log
#启动成功日志末尾会出现successfully
STATUS | wrapper  | 2021/12/09 21:04:10 | --> Wrapper Started as Daemon
STATUS | wrapper  | 2021/12/09 21:04:10 | Launching a JVM...
INFO   | jvm 1    | 2021/12/09 21:04:11 | Wrapper (Version 3.2.3) http://wrapper.tanukisoftware.org
INFO   | jvm 1    | 2021/12/09 21:04:11 |   Copyright 1999-2006 Tanuki Software, Inc.  All Rights Reserved.
INFO   | jvm 1    | 2021/12/09 21:04:11 | 
INFO   | jvm 1    | 2021/12/09 21:04:12 | MyCAT Server startup successfully. see logs in logs/mycat.log


(6)客户端连接数据库
#这里密码初始为123456   需要加端口
[root@localhost bin]#mysql -uroot -p123456 -h 192.168.59.114 -P8066
5.修改 mycat 配置文件 /apps/mycat/conf/server.xml
bash 复制代码
[root@localhost ~]#vim /apps/mycat/conf/server.xml

#去掉44行行注释,对应的在51行行末注释,删除50行行末注释,5 * 60 * 1000L; //连接空>    闲检查

#修改45行端口号为3306
45 <property name="serverPort">3306</property>

#配置Mycat的连接信息(账号密码),在110 和111行, 可以修改,这边不修改了
bash 复制代码
####参数解释说明####
110         <user name="root" defaultAccount="true">
111                 <property name="password">123456</property>
112                 <property name="schemas">TESTDB</property>
113                 <property name="defaultSchema">TESTDB</property>

116                 <!-- 表级 DML 权限设置 -->
117                 <!-- 
118                 <privileges check="false">
119                         <schema name="TESTDB" dml="0110" >
120                                 <table name="tb01" dml="0000"></table>
121                                 <table name="tb02" dml="1111"></table>
122                         </schema>
123                 </privileges>   
124                  -->

127         <user name="user">
128                 <property name="password">user</property>
129                 <property name="schemas">TESTDB</property>
130                 <property name="readOnly">true</property>
131                 <property name="defaultSchema">TESTDB</property>

user    用户配置节点
name    逻辑用户名,客户端登录MyCAT的用户名,也就是客户端用来连接Mycat的用户名。
password     客户端登录MyCAT的密码
schemas      数据库名,这里会和schema.xml中的配置关联,可配置多个,多个用逗号分开,例如:db1,db2
privileges   配置用户针对表的增删改查的权限
readOnly mycat   逻辑库所具有的权限。true为只读,false为读写都有,默认为false

##注意
1.#server.xml文件里登录mycat的用户名和密码可以任意定义,这个账号和密码是为客户机登录mycat时使用的账号信息
2.#逻辑库名(如上面的TESTDB,也就是登录mycat后显示的库名,切换这个库之后,显示的就是代理的真实mysql数据库的表)要在schema.xml里面也定义,否则会导致mycat服务启动失败!这里只定义了一个标签,所以把多余的都注释了。如果定义多个标签,即设置多个连接mycat的用户名和密码,那么就需要在schema.xml文件中定义多个对应的库!
6.修改 mycat 配置文件/apps/mycat/conf/schema.xml

​ schema.xml是最主要的配置项,此文件关联mysql读写分离策略,读写分离、分库分表策略、分片节点都是在此文件中配置的.MyCat作为中间件,它只是一个代理,本身并不进行数据存储,需要连接后端的MySQL物理服务器,此文件就是用来连接MySQL服务器的。

bash 复制代码
[root@localhost ~]#vim  /apps/mycat/conf/schema.xml
#删除所有内容,重新写入以下
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
        <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">
        #schema标签:数据库设置,此数据库为逻辑数据库,name与server.xml中schema对应。
        #name:逻辑数据库名,与server.xml中的schema对应;
        #checkSQLschema: 数据库前缀相关设置,这里为false;
        #sqlMaxLimit:  select时默认的limit,避免查询全表,否则可能会遇到查询量特别大的情况造成卡 死;
        #dataNode:表存储到哪些节点,多个节点用逗号分隔。节点为下文dataNode设置的name
</schema>
        <dataNode name="dn1" dataHost="localhost1" database="hellodb" />
        #dataNode标签: 定义mycat中的数据节点,也是通常说的数据分片,也就是分库相关配置
        #name: 定义数据节点的名字,与table中dataNode对应
        #datahost: 物理数据库名,与datahost中name对应,该属性用于定义该分片属于哪个数据库实例
        #database: 物理数据库中数据库名,该属性用于定义该分片属性哪个具体数据库实例上的具体库
        <dataHost name="localhost1" maxCon="1000" minCon="10" balance="1"
        #dataHost标签: 物理数据库,真正存储数据的数据库
        #name: 物理数据库名,与dataNode中dataHost对应
        #maxCon属性指定每个读写实例连接池的最大连接。也就是说,标签内嵌套的writeHost、readHost标  签都会使用这个属性的值来实例化出连接池的最大连接数
        #minCon属性指定每个读写实例连接池的最小连接,初始化连接池的大小
        #balance: 均衡负载的方式
       
                  writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
                  #writeType: 写入方式
                  #dbType: 数据库类型
                  #dbDriver指定连接后端数据库使用的 Driver,目前可选的值有 native 和 JDBC。用 native 的话,因为这个值执行的是二进制的 mysql 协议,所以可以使用 mysql 和maridb。其他类型的数据库则需要使用 JDBC 驱动来支持。
                  #switchType:  "-1" 表示不自动切换; "1" 默认值,自动切换; "2" 基于 MySQL主从同步的状态决定是否切换心跳语句为 show slave status; "3" 基于 MySQL galary cluster 的切换机制(适合集群)(1.4.1)心跳语句为 show status like 'wsrep%'.
                <heartbeat>select user()</heartbeat>
                #heartbeat: 心跳检测语句,注意语句结尾的分号要加
                <writeHost host="host1" url="192.168.59.113:3306" user="root" password="123456">
                #host:用于标识不同实例,一般 writeHost 我们使用*M1,readHost 我们用*S1。
                #url:后端实例连接地址。Native:地址:端口 JDBC:jdbc的url
                #user:后端存储实例需要的用户名字
                #password:后端存储实例需要的密码
                 <readHost host="host2" url="192.168.59.112:3306" user="root" password="123456"/>

                </writeHost>
        </dataHost>
</mycat:schema>


#schema.xml文件中有三点需要注意:balance="1",writeType="0" ,switchType="1" 
#schema.xml中的balance的取值决定了负载均衡对非事务内的读操作的处理。balance 属性负载均衡类型,目前的取值有 4 种:
##balance="0":不开启读写分离机制,所有读操作都发送到当前可用的writeHost上,即读请求仅            发送到writeHost上
##balance="1":一般用此模式,读请求随机分发到当前writeHost对应的readHost和standby的writeHost上。即全部的readHost与stand by writeHost 参与 select 语句的负载均衡,简单的说,当双主双从模式(M1 ->S1 , M2->S2,并且 M1 与 M2 互为主备),正常情况下, M2,S1, S2 都参与 select 语句的负载均衡
##balance="2":读请求随机分发到当前dataHost内所有的writeHost和readHost上。即所有读操作都随机的在writeHost、 readhost 上分发
##balance="3":读请求随机分发到当前writeHost对应的readHost上。即所有读请求随机的分发wiriterHost 对应的 readhost 执行, writerHost 不负担读压力,注意 balance=3 只在 1.4 及其以后版本有,1.3 没有

###writeHost和readHost标签,这两个标签都指定后端数据库的相关配置给mycat,用于实例化后端连接池。唯一不同的是:writeHost指定写实例、readHost指定读实例,组着这些读写实例来满足系统的要求。在一个dataHost内可以定义多个writeHost和eadHost。但是,如果writeHost指定的后端数据库宕机,那么这个writeHost绑定的所有readHost都将不可用。另一方面,由于这个writeHost宕机系统会自动的检测到,并切换到备用的writeHost上去   
               
#PS:Mycat主从分离只是在读的时候做了处理,写入数据的时候,只会写入到writehost,需要通过mycat的主从复制将数据复制到readhost
xml 复制代码
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
        <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1"></schema>
        <dataNode name="dn1" dataHost="localhost1" database="hellodb" />
        <dataHost name="localhost1" maxCon="1000" minCon="10" balance="1"
                  writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
                <heartbeat>select user()</heartbeat>
                <writeHost host="host1" url="192.168.91.100:3306" user="root" password="Admin@123">
                 <readHost host="host2" url="192.168.91.101:3306" user="root" password="Admin@123"/>
                </writeHost>
        </dataHost>
</mycat:schema>
7. 主服务器上授权
bash 复制代码
[root@localhost ~]#mysql -uroot -p123123
#授权
GRANT ALL ON *.* TO 'root'@'192.168.91.%' IDENTIFIED BY 'Admin@123';

#查看创建成功
use mysql;
select user,host from user;
8.重启mycat服务,客户机连接mycat
bash 复制代码
(1)在mycat服务器上,重启mycat服务,查看启动日志,文末出现successfully
 [root@localhost ~]#mycat restart  
 [root@localhost ~]#tail -f /apps/mycat/logs/wrapper.log
 INFO   | jvm 1    | 2021/12/09 21:15:40 | 
INFO   | jvm 1    | 2021/12/09 21:15:40 | MyCAT Server startup successfully. see logs in logs/mycat.log
STATUS | wrapper  | 2021/12/09 21:16:38 | TERM trapped.  Shutting down.
STATUS | wrapper  | 2021/12/09 21:16:39 | <-- Wrapper Stopped
STATUS | wrapper  | 2021/12/09 21:16:40 | --> Wrapper Started as Daemon
STATUS | wrapper  | 2021/12/09 21:16:40 | Launching a JVM...
INFO   | jvm 1    | 2021/12/09 21:16:40 | Wrapper (Version 3.2.3) http://wrapper.tanukisoftware.org
INFO   | jvm 1    | 2021/12/09 21:16:40 |   Copyright 1999-2006 Tanuki Software, Inc.  All Rights Reserved.
INFO   | jvm 1    | 2021/12/09 21:16:40 | 
INFO   | jvm 1    | 2021/12/09 21:16:41 | MyCAT Server startup successfully. see logs in logs/mycat.log

(2)查看3306端口,可以监听到主从服务器(192.168.59.113、192.168.59.112)
 [root@localhost ~]# ss -antp|grep 3306
 LISTEN     0      128         :::3306                    :::*                   users:(("java",pid=74936,fd=185))
TIME-WAIT  0      0        ::ffff:192.168.59.114:37344                ::ffff:192.168.59.112:3306               
ESTAB      0      0        ::ffff:192.168.59.114:58160                ::ffff:192.168.59.113:3306                users:(("java",pid=74936,fd=195))

 
(3)在客户机上登录mycat,这时可以不加端口直接进入数据库了
[root@localhost ~]#mysql -uroot -p123456 -h 192.168.59.114
#看是否能查到表   
create table student (id smallint unsigned primary key auto_increment, name varchar(10), age tinyint unsigned,gender enum('M','F') default 'M' );
show databases;
use TESTDB;
show tables;
+-------------------+
| Tables_in_hellodb |
+-------------------+
| classes           |
| coc               |
| courses           |
| scores            |
| students          |
| teachers          |
| toc               |
+-------------------+

#查看当前的查询来自哪台服务器,可以看到查询功能来自id为2的从服务器
select @@server_id;
+-------------+
| @@server_id |
+-------------+
|           2 |
+-------------+
9.客户端测试读写分离
bash 复制代码
(1)在主从服务器上都打开通用日志
[root@localhost ~]#mysql -uroot -p123123
#打开通用日志
set global general_log=1;
#查看通用查询日志是否开启
show variables like 'general%';
+------------------+-------------------------------------+
| Variable_name    | Value                               |
+------------------+-------------------------------------+
| general_log      | ON                                  |
| general_log_file | /usr/local/mysql/data/localhost.log |
+------------------+-------------------------------------+

set global general_log=1;
show variables like 'general%';

(2)在主从服务器上实时查看通用日志
[root@localhost ~]#tail -f /usr/local/mysql/data/localhost.log

(3)在客户机上的表中插入数据,并查看主从服务器实时日志,可以看到只有主服务器上有日志变化显示
[root@localhost ~]#mysql -uroot -p123456 -h 192.168.59.114
insert into teachers values(5,'Xiao Ming',46,'F');

(4)在客户机上select查表,并查看主从服务器实时日志,可以看到只有从服务器上有日志变化显示,从而实现了读写分离
select * from teachers;

15 mysql 高可用解决方案

  • MMM: Multi-Master Replication Manager for MySQL,Mysql主主复制管理器是一套灵活的脚本程序,基于perl实现,用来对mysql replication进行监控和故障迁移,并能管理mysql MasterMaster复制的配置(同一时间只有一个节点是可写的) 官网: http://www.mysql-mmm.org https://code.google.com/archive/p/mysql-master-master/downloads

  • MHA:Master High Availability,对主节点进行监控,可实现自动故障转移至其它从节点;通过提升某一从节点为新的主节点,基于主从复制实现,还需要客户端配合实现,目前MHA主要支持一主多从的架构,要搭建MHA,要求一个复制集群中必须最少有三台数据库服务器,一主二从,即一台充当master,一台充当备用master,另外一台充当从库,出于机器成本的考虑,淘宝进行了改造,目前淘宝TMHA已经支持一主一从 官方网站:https://code.google.com/archive/p/mysql-master-ha/ https://github.com/yoshinorim/mha4mysql-manager/releases https://github.com/yoshinorim/mha4mysql-node/releases/tag/v0.58

  • Galera Cluster:wsrep(MySQL extended with the Write Set Replication)通过wsrep协议在全局实现复制;任何一节点都可读写,不需要主从复制,实现多主读写

  • GR(Group Replication):MySQL官方提供的组复制技术(MySQL 5.7.17引入的技术),基于原生复制技术Paxos算法,实现了多主更新,复制组由多个server成员构成,组中的每个server可独立地执行事务,但所有读写事务只在冲突检测成功后才会提交

这3个节点互相通信,每当有事件发生,都会向其他节点传播该事件,然后协商,如果大多数节点都同意这次的事件,那么该事件将通过,否则该事件将失败或回滚。这些节点可以是单主模型的(single-primary),也可以是多主模型的(multi-primary)。单主模型只有一个主节点可以接受写操作,主节点故障时可以自动选举主节点。多主模型下,所有节点都可以接受写操作,所以没有master-slave的概念。

15.1MHA Master High Availability

15.1.1MHA工作原理和架构

MHA集群架构

  1. MHA利用 SELECT 1 As Value 指令判断master服务器的健康性,一旦master 宕机,MHA 从宕机崩溃的master保存二进制日志事件(binlog events)

  2. 识别含有最新更新的slave

  3. 应用差异的中继日志(relay log)到其他的slave

  4. 应用从master保存的二进制日志事件(binlog events)

  5. 提升一个slave为新的master

  6. 使其他的slave连接新的master进行复制

MHA软件

MHA软件由两部分组成,Manager工具包和Node工具包

Manager工具包主要包括以下几个工具:

复制代码
masterha_check_ssh       检查MHA的SSH配置状况
masterha_check_repl     检查MySQL复制状况
masterha_manger         启动MHA
masterha_check_status   检测当前MHA运行状态
masterha_master_monitor 检测master是否宕机
masterha_master_switch 故障转移(自动或手动)
masterha_conf_host     添加或删除配置的server信息
masterha_stop  --conf=app1.cnf 停止MHA
masterha_secondary_check 两个或多个网络线路检查MySQL主服务器的可用

Node工具包:这些工具通常由MHA Manager的脚本触发,无需人为操作)主要包括以下几个工具:

复制代码
save_binary_logs     #保存和复制master的二进制日志
apply_diff_relay_logs   #识别差异的中继日志事件并将其差异的事件应用于其他的slave
filter_mysqlbinlog   #去除不必要的ROLLBACK事件(MHA已不再使用此工具)
purge_relay_logs #清除中继日志(不会阻塞SQL线程)

MHA配置文件:

复制代码
global配置,为各application提供默认配置,默认文件路径 /etc/masterha_default.cnf
application配置:为每个主从复制集群
15.1.2 实现mha
复制代码
mha服务器: 192.168.91.103
master:   192.168.91.100
slave1:   192.168.91.101
slave2:   192.168.91.102

1.先安装 软件 和 基于key 验证 mha节点

bash 复制代码
####################主节点需要安装两个###############
[root@localhost opt]#yum install epel-release.noarch -y
#有依赖性用yum安装  需要先安装  epel源
[root@localhost opt]#ls
mha4mysql-manager-0.58-0.el7.centos.noarch.rpm  mha4mysql-node-0.58-0.el7.centos.noarch.rpm
[root@localhost opt]#yum -y install mha4mysql-*.rpm



################从节点仅安装node包################
yum install mha4mysql-node-0.58-0.el7.centos.noarch.rpm -y




##############主节点上 基于key验证:#####################
[root@localhost opt]#ssh-keygen 
[root@localhost opt]#cd
[root@localhost ~]#ssh-copy-id 127.0.0.1
#自己和自己实现免密钥登录


rsync -a .ssh   192.168.91.100:/root/
rsync -a .ssh   192.168.91.101:/root/
rsync -a .ssh   192.168.91.102:/root/
#注意.ssh 后不能加/
  1. 建立mha 文件夹 和配置文件
bash 复制代码
[root@localhost ~]#mkdir /etc/mastermha
[root@localhost ~]#vim /etc/mastermha/app1.cnf
[server default]
user=mhauser
password=Admin@123
manager_workdir=/data/mastermha/app1/
manager_log=/data/mastermha/app1/manager.log
remote_workdir=/data/mastermha/app1/
ssh_user=root
repl_user=test
repl_password=Admin@123
ping_interval=1
master_ip_failover_script=/usr/local/bin/master_ip_failover
#report_script=/usr/local/bin/sendmail.sh     可以不加
check_repl_delay=0
master_binlog_dir=/data/mysql/


[server1]
hostname=192.168.91.100
candidate_master=1

[server2]
hostname=192.168.91.101
candidate_master=1

[server3]
hostname=192.168.91.102

[root@localhost ~]#vim   master_ip_failover 
#!/usr/bin/env perl
use strict;
use warnings FATAL => 'all';
use Getopt::Long;
my (
$command, $ssh_user, $orig_master_host, $orig_master_ip,
$orig_master_port, $new_master_host, $new_master_ip, $new_master_port
);
my $vip = '192.168.91.188/24';    #设置Virtual IP   此处注释需要删除   *****
my $gateway = '192.168.91.2';     #网关Gateway IP   此处注释需要删除   *****
my $interface = 'ens33';
my $key = "1";
my $ssh_start_vip = "/sbin/ifconfig $interface:$key $vip;/sbin/arping -I $interface -c 3 -s $vip $gateway >/dev/null 2>&1";
my $ssh_stop_vip = "/sbin/ifconfig $interface:$key down";
GetOptions(
'command=s' => \$command,
'ssh_user=s' => \$ssh_user,
'orig_master_host=s' => \$orig_master_host,
'orig_master_ip=s' => \$orig_master_ip,
'orig_master_port=i' => \$orig_master_port,
'new_master_host=s' => \$new_master_host,
'new_master_ip=s' => \$new_master_ip,
'new_master_port=i' => \$new_master_port,
);
exit &main();
sub main {
print "\n\nIN SCRIPT TEST====$ssh_stop_vip==$ssh_start_vip===\n\n";
if ( $command eq "stop" || $command eq "stopssh" ) {
# $orig_master_host, $orig_master_ip, $orig_master_port are passed.
# If you manage master ip address at global catalog database,
# invalidate orig_master_ip here.
my $exit_code = 1;
eval {
print "Disabling the VIP on old master: $orig_master_host \n";
&stop_vip();
$exit_code = 0;
};
if ($@) {
warn "Got Error: $@\n";
exit $exit_code;
}
exit $exit_code;
}
elsif ( $command eq "start" ) {
# all arguments are passed.
# If you manage master ip address at global catalog database,
# activate new_master_ip here.
# You can also grant write access (create user, set read_only=0, etc) here.
my $exit_code = 10;
eval {
print "Enabling the VIP - $vip on the new master - $new_master_host \n";
&start_vip();
$exit_code = 0;
};
if ($@) {
warn $@;
exit $exit_code;
}
exit $exit_code;
}
elsif ( $command eq "status" ) {
print "Checking the Status of the script.. OK \n";
`ssh $ssh_user\@$orig_master_host \" $ssh_start_vip \"`;
exit 0;
}
else {
&usage();
exit 1;
}
}
# A simple system call that enable the VIP on the new master
sub start_vip() {
`ssh $ssh_user\@$new_master_host \" $ssh_start_vip \"`;
}
# A simple system call that disable the VIP on the old_master
sub stop_vip() {
`ssh $ssh_user\@$orig_master_host \" $ssh_stop_vip \"`;
}
sub usage {
print
"Usage: master_ip_failover --command=start|stop|stopssh|status --orig_master_host=host --orig_master_ip=ip --orig_master_port=port --new_master_host=host --new_master_ip=ip --new_master_port=port\n";
}




[root@localhost ~]#mv master_ip_failover  /usr/local/bin/
#准备脚本文件   注意注释


[root@localhost ~]#chmod +x /usr/local/bin/master_ip_failover 

3.准备主从复制

bash 复制代码
root@localhost ~]#vim  /etc/my.cnf
#修改文件
[mysqld]
server_id=100
log-bin=/data/mysql/mysql-bin
skip_name_resolve=1
general_log 

[root@localhost ~]#mkdir /data/mysql/   -p
#建立文件夹
[root@localhost ~]#chown mysql.mysql /data/ -R
#注意修改权限
[root@localhost ~]#systemctl restart mysqld


select @@server_id;
#可以查看serverid  默认都是1
show master status;
#查看二进制日志位置


grant replication slave on *.* to test@'192.168.91.%' identified by 'Admin@123';
#建立复制用户
grant all on *.* to mhauser@'192.168.91.%' identified by 'Admin@123';
#建立  mha管理账户

show processlist;
#查看线程




[root@localhost ~]#vim  /etc/my.cnf
#修改文件
[mysqld]
server_id=102
log-bin=/data/mysql/mysql-bin
relay-log=relay-log-bin
relay-log-index=slave-relay-bin.index
skip_name_resolve=1
general_log 
#read only  #只读可加
#skip_name_resolve=1  禁用反向解析

[root@localhost ~]#mkdir /data/mysql/   -p
#建立文件夹
[root@localhost ~]#chown mysql.mysql /data/ -R
#注意修改权限
[root@localhost ~]#systemctl restart mysqld



下面修改配置 命令较长可以使用帮助
help change master to


CHANGE MASTER TO
  MASTER_HOST='192.168.91.100',
  MASTER_USER='test',
  MASTER_PASSWORD='Admin@123',
  MASTER_PORT=3306,
  MASTER_LOG_FILE='mysql-bin.000001',
  MASTER_LOG_POS=154;
  注意最后分号




show slave status\G;
#查看设置的状态
Seconds_Behind_Master: NULL    #目前数据差

start slave;
#开启线程,开启主从复制

配置虚拟ip 在mysql 主节点上

bash 复制代码
[root@localhost ~]#ifconfig ens33:1 192.168.91.188/24

检查 mha 环境

bash 复制代码
[root@localhost ~]#masterha_check_ssh --conf=/etc/mastermha/app1.cnf
Sun Mar 19 10:57:24 2023 - [warning] Global configuration file /etc/masterha_default.cnf not found. Skipping.
Sun Mar 19 10:57:24 2023 - [info] Reading application default configuration from /etc/mastermha/app1.cnf..
Sun Mar 19 10:57:24 2023 - [info] Reading server configuration from /etc/mastermha/app1.cnf..
Sun Mar 19 10:57:24 2023 - [info] Starting SSH connection tests..
Sun Mar 19 10:57:26 2023 - [debug] 
Sun Mar 19 10:57:24 2023 - [debug]  Connecting via SSH from root@192.168.91.100(192.168.91.100:22) to root@192.168.91.101(192.168.91.101:22)..
Sun Mar 19 10:57:25 2023 - [debug]   ok.
Sun Mar 19 10:57:25 2023 - [debug]  Connecting via SSH from root@192.168.91.100(192.168.91.100:22) to root@192.168.91.102(192.168.91.102:22)..
Sun Mar 19 10:57:26 2023 - [debug]   ok.
Sun Mar 19 10:57:27 2023 - [debug] 
Sun Mar 19 10:57:25 2023 - [debug]  Connecting via SSH from root@192.168.91.102(192.168.91.102:22) to root@192.168.91.100(192.168.91.100:22)..
Sun Mar 19 10:57:26 2023 - [debug]   ok.
Sun Mar 19 10:57:26 2023 - [debug]  Connecting via SSH from root@192.168.91.102(192.168.91.102:22) to root@192.168.91.101(192.168.91.101:22)..
Sun Mar 19 10:57:26 2023 - [debug]   ok.
Sun Mar 19 10:57:27 2023 - [debug] 
Sun Mar 19 10:57:25 2023 - [debug]  Connecting via SSH from root@192.168.91.101(192.168.91.101:22) to root@192.168.91.100(192.168.91.100:22)..
Sun Mar 19 10:57:25 2023 - [debug]   ok.
Sun Mar 19 10:57:25 2023 - [debug]  Connecting via SSH from root@192.168.91.101(192.168.91.101:22) to root@192.168.91.102(192.168.91.102:22)..
Sun Mar 19 10:57:26 2023 - [debug]   ok.
Sun Mar 19 10:57:27 2023 - [info] All SSH connection tests passed successfully.




[root@mha-manager ~]#masterha_check_repl --conf=/etc/mastermha/app1.cnf
#如果设置了默认字符集起不来 
unknown variable 'default-character-set=utf8'

#查看状态
[root@mha-manager ~]#masterha_check_status --conf=/etc/mastermha/app1.cnf

ssh 有问题

没装客户端

没有建账户

开启mha

bash 复制代码
#开启MHA,默认是前台运行,生产环境一般为后台执行
nohup masterha_manager --conf=/etc/mastermha/app1.cnf &> /dev/null 
#非后台
masterha_manager --conf=/etc/mastermha/app1.cnf 

#查看状态
masterha_check_status --conf=/etc/mastermha/app1.cnf  

监听过程

bash 复制代码
[root@mha ~]#masterha_check_status --conf=/etc/mastermha/app1.cnf
app1 (pid:4563) is running(0:PING_OK), master:192.168.91.100


[root@mysql-master]#tail -f /var/lib/mysql/localhost.log 
#通用日志
2023-03-19T03:24:57.169576Z	   26 Query	SELECT 1 As Value
2023-03-19T03:24:58.169328Z	   26 Query	SELECT 1 As Value
2023-03-19T03:24:59.169945Z	   26 Query	SELECT 1 As Value
2023-03-19T03:25:00.171058Z	   26 Query	SELECT 1 As Value
2023-03-19T03:25:01.171974Z	   26 Query	SELECT 1 As Value
2023-03-19T03:25:02.172306Z	   26 Query	SELECT 1 As Value
2023-03-19T03:25:03.172317Z	   26 Query	SELECT 1 As Value

日志

bash 复制代码
[root@localhost ~]#tail -f /data/mastermha/app1/manager.log 

IN SCRIPT TEST====/sbin/ifconfig ens33:1 down==/sbin/ifconfig ens33:1 192.168.91.188/24;/sbin/arping -I ens33 -c 3 -s 192.168.91.188/24 192.168.91.2 >/dev/null 2>&1===

Checking the Status of the script.. OK 
Sun Mar 19 11:22:51 2023 - [info]  OK.
Sun Mar 19 11:22:51 2023 - [warning] shutdown_script is not defined.
Sun Mar 19 11:22:51 2023 - [info] Set master ping interval 1 seconds.
Sun Mar 19 11:22:51 2023 - [warning] secondary_check_script is not defined. It is highly recommended setting it to check master reachability from two or more routes.
Sun Mar 19 11:22:51 2023 - [info] Starting ping health check on 192.168.91.100(192.168.91.100:3306)..
Sun Mar 19 11:22:51 2023 - [info] Ping(SELECT) succeeded, waiting until MySQL doesn't respond..

测试:

停掉主服务器

复制代码

16.生产环境

配置文件生成工具参考链接:https://imysql.com/my_cnf_generator

参考硬件:内存 32G

16.1 my.cnf 配置案例

bash 复制代码
#打开独立表空间
innodb_file_per_table = 1
#MySQL 服务所允许的同时会话数的上限,经常出现Too Many Connections的错误提示,则需要增大此值
max_connections = 8000
#所有线程所打开表的数量
open_files_limit = 10240
#back_log 是操作系统在监听队列中所能保持的连接数
back_log = 300
#每个客户端连接最大的错误允许数量,当超过该次数,MYSQL服务器将禁止此主机的连接请求,直到MYSQL服
务器重启或通过flush hosts命令清空此主机的相关信息
max_connect_errors = 1000
#每个连接传输数据大小.最大1G,须是1024的倍数,一般设为最大的BLOB的值
max_allowed_packet = 32M
#指定一个请求的最大连接时间
wait_timeout = 10
# 排序缓冲被用来处理类似ORDER BY以及GROUP BY队列所引起的排序
sort_buffer_size = 16M 
#不带索引的全表扫描.使用的buffer的最小值
join_buffer_size = 16M 
#查询缓冲大小
query_cache_size = 128M
#指定单个查询能够使用的缓冲区大小,缺省为1M
query_cache_limit = 4M    
# 设定默认的事务隔离级别
transaction_isolation = REPEATABLE-READ
# 线程使用的堆大小. 此值限制内存中能处理的存储过程的递归深度和SQL语句复杂性,此容量的内存在每次
连接时被预留.
thread_stack = 512K 
# 二进制日志功能
log-bin=/data/mysqlbinlogs/
#二进制日志格式
binlog_format=row
#InnoDB使用一个缓冲池来保存索引和原始数据, 可设置这个变量到物理内存大小的80%
innodb_buffer_pool_size = 24G 
#用来同步IO操作的IO线程的数量
innodb_file_io_threads = 4
#在InnoDb核心内的允许线程数量,建议的设置是CPU数量加上磁盘数量的两倍
innodb_thread_concurrency = 16
# 用来缓冲日志数据的缓冲区的大小
innodb_log_buffer_size = 16M
在日志组中每个日志文件的大小
innodb_log_file_size = 512M 
# 在日志组中的文件总数
innodb_log_files_in_group = 3
# SQL语句在被回滚前,InnoDB事务等待InnoDB行锁的时间
innodb_lock_wait_timeout = 120
#慢查询时长
long_query_time = 2
#将没有使用索引的查询也记录下来
log-queries-not-using-indexes

16.2MySQL配置最佳实践

高并发大数据的互联网业务,架构设计思路是"解放数据库CPU,将计算转移到服务层",并发量大的情况下,这些功能很可能将数据库拖死,业务逻辑放到服务层具备更好的扩展性,能够轻易实现"增机器就加性能"

参考资料:

阿里巴巴Java开发手册:https://developer.aliyun.com/topic/java2020

58到家数据库30条军规解读:http://zhuanlan.51cto.com/art/201702/531364.htm

以下规范适用场景:并发量大、数据量大的互联网业务

16.3 基础规范

1)必须使用InnoDB存储引擎

解读:支持事务、行级锁、并发性能更好、CPU及内存缓存页优化使得资源利用率更高

(2)使用UTF8MB4字符集

解读:万国码,无需转码,无乱码风险,节省空间,支持表情包及生僻字

(3)数据表、数据字段必须加入中文注释

解读:N年后谁知道这个r1,r2,r3字段是干嘛的

(4)禁止使用存储过程、视图、触发器、Event

解读:高并发大数据的互联网业务,架构设计思路是"解放数据库CPU,将计算转移到服务层",并发量

大的情况下,这些功能很可能将数据库拖死,业务逻辑放到服务层具备更好的扩展性,能够轻易实现"增

机器就加性能"。数据库擅长存储与索引,CPU计算还是上移吧!

(5)禁止存储大文件或者大照片

解读:为何要让数据库做它不擅长的事情?大文件和照片存储在文件系统,数据库里存URI多好。

16.4 命名规范

(6)只允许使用内网域名,而不是ip连接数据库

(7)线上环境、开发环境、测试环境数据库内网域名遵循命名规范

业务名称:xxx

线上环境:xxx.db

开发环境:xxx.rdb

测试环境:xxx.tdb

从库在名称后加-s标识,备库在名称后加-ss标识

线上从库:xxx-s.db

线上备库:xxx-sss.db

(8)库名、表名、字段名:小写,下划线风格,不超过32个字符,必须见名知意,禁止拼音英文混用

(9)库名与应用名称尽量一致,表名:t_业务名称_表的作用,主键名:pk_xxx,非唯一索引名:idx_xxx,唯一键索引名:uk_xxx

16.5 表设计规范

(10)单实例表数目必须小于500

单表行数超过500万行或者单表容量超过2GB,才推荐进行分库分表。

说明:如果预计三年后的数据量根本达不到这个级别,请不要在创建表时就分库分表

(11)单表列数目必须小于30

(12)表必须有主键,例如自增主键

解读:

a)主键递增,数据行写入可以提高插入性能,可以避免page分裂,减少表碎片提升空间和内存的使用b)主键要选择较短的数据类型, Innodb引擎普通索引都会保存主键的值,较短的数据类型可以有效的减少索引的磁盘空间,提高索引的缓存效率

c) 无主键的表删除,在row模式的主从架构,会导致备库夯住

(13)禁止使用外键,如果有外键完整性约束,需要应用程序控制

解读:外键会导致表与表之间耦合,update与delete操作都会涉及相关联的表,十分影响sql 的性能,甚至会造成死锁。高并发情况下容易造成数据库性能,大数据高并发业务场景数据库使用以性能优先

16.6 字段设计规范

(14)必须把字段定义为NOT NULL并且提供默认值

解读:

a)null的列使索引/索引统计/值比较都更加复杂,对MySQL来说更难优化

b)null 这种类型MySQL内部需要进行特殊处理,增加数据库处理记录的复杂性;同等条件下,表中有较多空字段的时候,数据库的处理性能会降低很多

c)null值需要更多的存储空,无论是表还是索引中每行中的null的列都需要额外的空间来标识

d)对null 的处理时候,只能采用is null或is not null,而不能采用=、in、<、<>、!=、not in这些操作符号。如:where name!='shenjian',如果存在name为null值的记录,查询结果就不会包含name为null值的记录

(15)禁止使用TEXT、BLOB类型

解读:会浪费更多的磁盘和内存空间,非必要的大量的大字段查询会淘汰掉热数据,导致内存命中率急剧降低,影响数据库性能

(16)禁止使用小数存储货币

解读:使用整数吧,小数容易导致钱对不上

(17)必须使用varchar(20)存储手机号

解读:

a)涉及到区号或者国家代号,可能出现±()

b)手机号会去做数学运算么?

c)varchar可以支持模糊查询,例如:like"138%"

(18)禁止使用ENUM,可使用TINYINT代替

解读:

a)增加新的ENUM值要做DDL操作

b)ENUM的内部实际存储就是整数,你以为自己定义的是字符串?

16.7 索引设计规范

(19)单表索引建议控制在5个以内

(20)单索引字段数不允许超过5个

解读:字段超过5个时,实际已经起不到有效过滤数据的作用了

(21)禁止在更新十分频繁、区分度不高的属性上建立索引

解读:a)更新会变更B+树,更新频繁的字段建立索引会大大降低数据库性能

b)"性别"这种区分度不大的属性,建立索引是没有什么意义的,不能有效过滤数据,性能与全表扫描类

(22)建立组合索引,必须把区分度高的字段放在前面

解读:能够更加有效的过滤数据

16.8 SQL使用规范

(23)禁止使用SELECT *,只获取必要的字段,需要显示说明列属性

解读:

a)读取不需要的列会增加CPU、IO、NET消耗

b)不能有效的利用覆盖索引

c)使用SELECT *容易在增加或者删除字段后出现程序BUG

(24)禁止使用INSERT INTO t_xxx VALUES(xxx),必须显示指定插入的列属性

解读:容易在增加或者删除字段后出现程序BUG

(25)禁止使用属性隐式转换

解读:SELECT uid FROM t_user WHERE phone=13812345678 会导致全表扫描,而不能命中phone索引,猜猜为什么?(这个线上问题不止出现过一次)

(26)禁止在WHERE条件的属性上使用函数或者表达式

解读:SELECT uid FROM t_user WHERE from_unixtime(day)>='2017-02-15' 会导致全表扫描

正确的写法是:SELECT uid FROM t_user WHERE day>= unix_timestamp('2017-02-15 00:00:00')

(27)禁止负向查询,以及%开头的模糊查询

解读:

a)负向查询条件:NOT、!=、<>、!<、!>、NOT IN、NOT LIKE等,会导致全表扫描

b)%开头的模糊查询,会导致全表扫描

(28)禁止大表使用JOIN查询,禁止大表使用子查询

解读:会产生临时表,消耗较多内存与CPU,极大影响数据库性能

(29)禁止使用OR条件,必须改为IN查询

解读:旧版本Mysql的OR查询是不能命中索引的,即使能命中索引,为何要让数据库耗费更多的CPU帮

助实施查询优化呢?

(30)应用程序必须捕获SQL异常,并有相应处理

ndy0X-1774523057513)]

ssh 有问题

外链图片转存中...(img-N0tgZFeB-1774523057514)

没装客户端

外链图片转存中...(img-1gtMGleU-1774523057514)

没有建账户

外链图片转存中...(img-aNl1Kh6H-1774523057514)

开启mha

bash 复制代码
#开启MHA,默认是前台运行,生产环境一般为后台执行
nohup masterha_manager --conf=/etc/mastermha/app1.cnf &> /dev/null 
#非后台
masterha_manager --conf=/etc/mastermha/app1.cnf 

#查看状态
masterha_check_status --conf=/etc/mastermha/app1.cnf  

外链图片转存中...(img-Lm6fOMpC-1774523057514)

监听过程

bash 复制代码
[root@mha ~]#masterha_check_status --conf=/etc/mastermha/app1.cnf
app1 (pid:4563) is running(0:PING_OK), master:192.168.91.100


[root@mysql-master]#tail -f /var/lib/mysql/localhost.log 
#通用日志
2023-03-19T03:24:57.169576Z	   26 Query	SELECT 1 As Value
2023-03-19T03:24:58.169328Z	   26 Query	SELECT 1 As Value
2023-03-19T03:24:59.169945Z	   26 Query	SELECT 1 As Value
2023-03-19T03:25:00.171058Z	   26 Query	SELECT 1 As Value
2023-03-19T03:25:01.171974Z	   26 Query	SELECT 1 As Value
2023-03-19T03:25:02.172306Z	   26 Query	SELECT 1 As Value
2023-03-19T03:25:03.172317Z	   26 Query	SELECT 1 As Value

日志

bash 复制代码
[root@localhost ~]#tail -f /data/mastermha/app1/manager.log 

IN SCRIPT TEST====/sbin/ifconfig ens33:1 down==/sbin/ifconfig ens33:1 192.168.91.188/24;/sbin/arping -I ens33 -c 3 -s 192.168.91.188/24 192.168.91.2 >/dev/null 2>&1===

Checking the Status of the script.. OK 
Sun Mar 19 11:22:51 2023 - [info]  OK.
Sun Mar 19 11:22:51 2023 - [warning] shutdown_script is not defined.
Sun Mar 19 11:22:51 2023 - [info] Set master ping interval 1 seconds.
Sun Mar 19 11:22:51 2023 - [warning] secondary_check_script is not defined. It is highly recommended setting it to check master reachability from two or more routes.
Sun Mar 19 11:22:51 2023 - [info] Starting ping health check on 192.168.91.100(192.168.91.100:3306)..
Sun Mar 19 11:22:51 2023 - [info] Ping(SELECT) succeeded, waiting until MySQL doesn't respond..

测试:

停掉主服务器

复制代码

16.生产环境

配置文件生成工具参考链接:https://imysql.com/my_cnf_generator

参考硬件:内存 32G

16.1 my.cnf 配置案例

bash 复制代码
#打开独立表空间
innodb_file_per_table = 1
#MySQL 服务所允许的同时会话数的上限,经常出现Too Many Connections的错误提示,则需要增大此值
max_connections = 8000
#所有线程所打开表的数量
open_files_limit = 10240
#back_log 是操作系统在监听队列中所能保持的连接数
back_log = 300
#每个客户端连接最大的错误允许数量,当超过该次数,MYSQL服务器将禁止此主机的连接请求,直到MYSQL服
务器重启或通过flush hosts命令清空此主机的相关信息
max_connect_errors = 1000
#每个连接传输数据大小.最大1G,须是1024的倍数,一般设为最大的BLOB的值
max_allowed_packet = 32M
#指定一个请求的最大连接时间
wait_timeout = 10
# 排序缓冲被用来处理类似ORDER BY以及GROUP BY队列所引起的排序
sort_buffer_size = 16M 
#不带索引的全表扫描.使用的buffer的最小值
join_buffer_size = 16M 
#查询缓冲大小
query_cache_size = 128M
#指定单个查询能够使用的缓冲区大小,缺省为1M
query_cache_limit = 4M    
# 设定默认的事务隔离级别
transaction_isolation = REPEATABLE-READ
# 线程使用的堆大小. 此值限制内存中能处理的存储过程的递归深度和SQL语句复杂性,此容量的内存在每次
连接时被预留.
thread_stack = 512K 
# 二进制日志功能
log-bin=/data/mysqlbinlogs/
#二进制日志格式
binlog_format=row
#InnoDB使用一个缓冲池来保存索引和原始数据, 可设置这个变量到物理内存大小的80%
innodb_buffer_pool_size = 24G 
#用来同步IO操作的IO线程的数量
innodb_file_io_threads = 4
#在InnoDb核心内的允许线程数量,建议的设置是CPU数量加上磁盘数量的两倍
innodb_thread_concurrency = 16
# 用来缓冲日志数据的缓冲区的大小
innodb_log_buffer_size = 16M
在日志组中每个日志文件的大小
innodb_log_file_size = 512M 
# 在日志组中的文件总数
innodb_log_files_in_group = 3
# SQL语句在被回滚前,InnoDB事务等待InnoDB行锁的时间
innodb_lock_wait_timeout = 120
#慢查询时长
long_query_time = 2
#将没有使用索引的查询也记录下来
log-queries-not-using-indexes

16.2MySQL配置最佳实践

高并发大数据的互联网业务,架构设计思路是"解放数据库CPU,将计算转移到服务层",并发量大的情况下,这些功能很可能将数据库拖死,业务逻辑放到服务层具备更好的扩展性,能够轻易实现"增机器就加性能"

参考资料:

阿里巴巴Java开发手册:https://developer.aliyun.com/topic/java2020

58到家数据库30条军规解读:http://zhuanlan.51cto.com/art/201702/531364.htm

以下规范适用场景:并发量大、数据量大的互联网业务

16.3 基础规范

1)必须使用InnoDB存储引擎

解读:支持事务、行级锁、并发性能更好、CPU及内存缓存页优化使得资源利用率更高

(2)使用UTF8MB4字符集

解读:万国码,无需转码,无乱码风险,节省空间,支持表情包及生僻字

(3)数据表、数据字段必须加入中文注释

解读:N年后谁知道这个r1,r2,r3字段是干嘛的

(4)禁止使用存储过程、视图、触发器、Event

解读:高并发大数据的互联网业务,架构设计思路是"解放数据库CPU,将计算转移到服务层",并发量

大的情况下,这些功能很可能将数据库拖死,业务逻辑放到服务层具备更好的扩展性,能够轻易实现"增

机器就加性能"。数据库擅长存储与索引,CPU计算还是上移吧!

(5)禁止存储大文件或者大照片

解读:为何要让数据库做它不擅长的事情?大文件和照片存储在文件系统,数据库里存URI多好。

16.4 命名规范

(6)只允许使用内网域名,而不是ip连接数据库

(7)线上环境、开发环境、测试环境数据库内网域名遵循命名规范

业务名称:xxx

线上环境:xxx.db

开发环境:xxx.rdb

测试环境:xxx.tdb

从库在名称后加-s标识,备库在名称后加-ss标识

线上从库:xxx-s.db

线上备库:xxx-sss.db

(8)库名、表名、字段名:小写,下划线风格,不超过32个字符,必须见名知意,禁止拼音英文混用

(9)库名与应用名称尽量一致,表名:t_业务名称_表的作用,主键名:pk_xxx,非唯一索引名:idx_xxx,唯一键索引名:uk_xxx

16.5 表设计规范

(10)单实例表数目必须小于500

单表行数超过500万行或者单表容量超过2GB,才推荐进行分库分表。

说明:如果预计三年后的数据量根本达不到这个级别,请不要在创建表时就分库分表

(11)单表列数目必须小于30

(12)表必须有主键,例如自增主键

解读:

a)主键递增,数据行写入可以提高插入性能,可以避免page分裂,减少表碎片提升空间和内存的使用b)主键要选择较短的数据类型, Innodb引擎普通索引都会保存主键的值,较短的数据类型可以有效的减少索引的磁盘空间,提高索引的缓存效率

c) 无主键的表删除,在row模式的主从架构,会导致备库夯住

(13)禁止使用外键,如果有外键完整性约束,需要应用程序控制

解读:外键会导致表与表之间耦合,update与delete操作都会涉及相关联的表,十分影响sql 的性能,甚至会造成死锁。高并发情况下容易造成数据库性能,大数据高并发业务场景数据库使用以性能优先

16.6 字段设计规范

(14)必须把字段定义为NOT NULL并且提供默认值

解读:

a)null的列使索引/索引统计/值比较都更加复杂,对MySQL来说更难优化

b)null 这种类型MySQL内部需要进行特殊处理,增加数据库处理记录的复杂性;同等条件下,表中有较多空字段的时候,数据库的处理性能会降低很多

c)null值需要更多的存储空,无论是表还是索引中每行中的null的列都需要额外的空间来标识

d)对null 的处理时候,只能采用is null或is not null,而不能采用=、in、<、<>、!=、not in这些操作符号。如:where name!='shenjian',如果存在name为null值的记录,查询结果就不会包含name为null值的记录

(15)禁止使用TEXT、BLOB类型

解读:会浪费更多的磁盘和内存空间,非必要的大量的大字段查询会淘汰掉热数据,导致内存命中率急剧降低,影响数据库性能

(16)禁止使用小数存储货币

解读:使用整数吧,小数容易导致钱对不上

(17)必须使用varchar(20)存储手机号

解读:

a)涉及到区号或者国家代号,可能出现±()

b)手机号会去做数学运算么?

c)varchar可以支持模糊查询,例如:like"138%"

(18)禁止使用ENUM,可使用TINYINT代替

解读:

a)增加新的ENUM值要做DDL操作

b)ENUM的内部实际存储就是整数,你以为自己定义的是字符串?

16.7 索引设计规范

(19)单表索引建议控制在5个以内

(20)单索引字段数不允许超过5个

解读:字段超过5个时,实际已经起不到有效过滤数据的作用了

(21)禁止在更新十分频繁、区分度不高的属性上建立索引

解读:a)更新会变更B+树,更新频繁的字段建立索引会大大降低数据库性能

b)"性别"这种区分度不大的属性,建立索引是没有什么意义的,不能有效过滤数据,性能与全表扫描类

(22)建立组合索引,必须把区分度高的字段放在前面

解读:能够更加有效的过滤数据

16.8 SQL使用规范

(23)禁止使用SELECT *,只获取必要的字段,需要显示说明列属性

解读:

a)读取不需要的列会增加CPU、IO、NET消耗

b)不能有效的利用覆盖索引

c)使用SELECT *容易在增加或者删除字段后出现程序BUG

(24)禁止使用INSERT INTO t_xxx VALUES(xxx),必须显示指定插入的列属性

解读:容易在增加或者删除字段后出现程序BUG

(25)禁止使用属性隐式转换

解读:SELECT uid FROM t_user WHERE phone=13812345678 会导致全表扫描,而不能命中phone索引,猜猜为什么?(这个线上问题不止出现过一次)

(26)禁止在WHERE条件的属性上使用函数或者表达式

解读:SELECT uid FROM t_user WHERE from_unixtime(day)>='2017-02-15' 会导致全表扫描

正确的写法是:SELECT uid FROM t_user WHERE day>= unix_timestamp('2017-02-15 00:00:00')

(27)禁止负向查询,以及%开头的模糊查询

解读:

a)负向查询条件:NOT、!=、<>、!<、!>、NOT IN、NOT LIKE等,会导致全表扫描

b)%开头的模糊查询,会导致全表扫描

(28)禁止大表使用JOIN查询,禁止大表使用子查询

解读:会产生临时表,消耗较多内存与CPU,极大影响数据库性能

(29)禁止使用OR条件,必须改为IN查询

解读:旧版本Mysql的OR查询是不能命中索引的,即使能命中索引,为何要让数据库耗费更多的CPU帮

助实施查询优化呢?

(30)应用程序必须捕获SQL异常,并有相应处理

相关推荐
数据库幼崽2 小时前
ProxySQL官方文档之Architecture Overview
mysql
V1ncent Chen2 小时前
SQL大师之路 16 集合操作(Union/Intersect/Except)
数据库·sql·mysql·数据分析
Seven973 小时前
MySQL优化全攻略:索引、SQL与分库分表的最佳实践
mysql
华科大胡子3 小时前
MySQL安全加固十大硬核操作
mysql
Holen&&Beer3 小时前
mysql-bind-mount-to-named-volume-migration
数据库·mysql·adb
数据库幼崽3 小时前
ProxySQL官方文档之Audit Log
mysql
数据库幼崽3 小时前
Proxy SQL验证方式
数据库·mysql
feng68_3 小时前
MySQL-Router+MySQL-MGR
android·linux·运维·数据库·mysql·adb
不会写DN3 小时前
php 如何使用mysqli连接mysql
开发语言·mysql·php