mysql教材
实验环境:ip 192.168.108.128
数据库原理
数据的分类

在数据的获取和使用的过程中,我们可以根据数据的结构类型,将数据分成三类,分别是:结构化数据,半结构化数据,非结构化数据。
结构化数据
结构化数据一般是指可以用二维表来逻辑表达实现的数据。是有固定的格式和有限长度的数据,可以用关系型数据库表示和存储。
其特点是:数据以行为单位,一行数据表示一个实体信息,每一行数据的属性是相同的,存储在数据库中;能够用统一的数据类型和结构加以表示;也能够用二维表结构来逻辑表达实现,包含属性和元组。
对于结构化数据来讲通常是先有结构再有数据。
范例:二维表
| no | name | age |
|---|---|---|
| 1 | 唐三 | 123 |
| 2 | 叶凡 | 456 |
半结构化数据
半结构化数据就是介于完全结构化数据和完全无结构的数据之间的数据。
半结构化数据是结构化数据的一种形式,它并不符合关系型数据库或其它数据表的形式关联起来的数据模型结构,但包含相关的标记,用来分隔语义元素及对记录和字段进行分层,数据的结构和内容混在一起,没有明显的区分,因此,这种数据也被称为自描述结构的数据。
例如:HTML文档,JSON,XML和一些NoSQL数据库等就属于半结构化数据。
对于半结构化数据来说则是先有数据再有结构。
范例:json
bash
[
{
"id":1,
"name": "唐三",
"age":123
},
{
"id":2,
"name": "叶凡",
"age":456
}
]
非结构化数据
顾名思义,就是没有固定结构的数据,这种数据没有固定格式和有限长度,无法用数据库二维逻辑表来表现其结构,对于这类数据,我们一般进行整体存储。
典型的非结构化数据包括:二进制文件,音视频文件,位置信息等
数据管理发展历史
如何有效管理大量数据,方法和手段都在随着计算机技术的发展而进步。
数据管理的发展经历了人工管理、文件系统和数据库系统三个发展阶段。
数据管理的三个阶段
人工管理阶段
时间:20世纪50年代中期以前
特点:当时的计算机主要用于科学计算。外部存储设备只有磁带,打孔纸带等,也没有专业的数据管理软件,所以在当时数据管理主要由人工完成。数据处理方式上基本是批处理。
文件系统管理阶段
时间:20世纪50年代后期至60年代中期
特点:随着时间的发展,计算机不仅用于科学计算,还用于信息管理,需要处理的数据量大增,数据存储,检索和维护等问题迫切需要解决,同一时期,在硬件方面,出现了磁盘,磁鼓等可以直接连机存取的设备,在此基础上,出现了基于文件系统的数据管理软件。使用磁盘文件的形式来管理数据,数据可以在系统中长期保存,文件也有了各种各样的格式。在数据处理方式上可以批处理,也可以联机实时处理。
数据库系统阶段
时间:20世纪60年代后期至今
特点:此时己经出现大容量的磁盘,且硬件价格开始下降。数据管理技术进入数据库系统阶段。数据库系统克服了文件系统的缺陷,提供了对数据更高级、更有效的管理。这个阶段的程序和数据的联系是通过数据库管理系统来实现的。数据库系统采用了复杂的结构化的数据模型,数据拥有高独立性,低冗余度。
文件管理系统的特点
优点
文件形式和格式多样化,数据可以长期保存,且数据具有一定的独立性,由文件系统进行管理。
缺点
应用程序对接不方便,没有统一接口,也不支持对文件的并发访问,无安全控制功能,难以按用户视图表示数据,数据间联系弱,数据冗余不可避免。
数据库管理系统
相关概念
数据库:Database
数据库是按照一定的数据结构来组织,存储和管理数据的仓库。
是一个长期存储在计算机内的、有组织的、可共享的、统一管理的大量数据的集合。
数据库管理系统:Database Management System(DBMS)
数据库管理系统是一种操纵和管理数据库的大型软件,用于建立,使用和维护数据库,简称DBMS。
它对数据库进行统一的管理和控制,以保证数据库的安全性和完整性。
数据库管理员:Database Administrator(DBA)
DBA是从事管理和维护数据库管理系统(DBMS)的相关工作人员的统称,属于运维工程师的一个分支,主要负责业务数据库从设计、测试到部署交付的全生命周期管理。
DBA的核心目标是保证数据库管理系统的稳定性、安全性、完整性和高可用性能。
应用程序:Application
一个应用程序通常是指能够执行某种功能的软件程序。
数据库管理系统特点
数据库管理系统中采用了复杂的数据模型表示数据结构,数据冗余小,易扩充,实现了数据共享。
具有较高的数据和程序独立性。数据库的独立性表现在物理独立性和逻辑独立性两个方面。
数据库管理系统为用户和应用程序提供了方便和统一的查询接口。
数据库管理系统的存在,使得数据可以和应用程序解耦。
数据库管理系统还具有并发控制,数据备份和恢复,完整性和安全性保障等功能。
数据库管理系统基本功能
-
数据的定义:DBMS提供了数据定义语言DDL(DataDefinition Language),供用户定义数据库的三级模式结构,两级映像以及完整性约束和保密限制等约束。DDL主要用于建立、修改数据库的库结构。DDL所描述的库结构仅仅给出了数据库的框架,数据库的框架信息被存放在数据字典中。
-
数据操作:DBMS提供数据操作语言DML(DataManipulation Language),供用户实现对数据的追加、删除、更新、查询等操作。
-
数据组织、存储与管理:DBMS要分类组织、存储和管理各种数据,包括数据字典、用户数据、存取路径等,需确定以何种文件结构和存取方式在存储级上组织这些数据,如何实现数据之间的联系。数据组织和存储的基本目标是提高存储空间利用率,选择合适的存取方法提高存取效率。
-
数据库的运行管理:数据库的运行管理功能是DBMS的运行控制、管理功能,包括多用户环境下的并发控制、安全性检查和存取限制控制、完整性检查和执行、运行日志的组织管理、事务的管理和自动恢复,即保证事务的原子性。这些功能保证了数据库系统的正常运行。
-
数据库的维护:这一部分包括数据库的数据载入、转换、转储、数据库的重组和重构以及性能监控等功能,这些功能分别由各个使用程序来完成。
-
数据库的保护:数据库中的数据是信息社会的战略资源,所以数据的保护至关重要。DBMS对数据库的保护通过4个方面来实现:数据库的恢复、数据库的并发控制、数据库的完整性控制、数据库安全性控制。DBMS的其他保护功能还有系统缓冲区的管理以及数据存储的某些自适应调节机制等。
-
通信:DBMS具有与操作系统的联机处理、分时系统及远程作业输入的相关接口,负责处理数据的传送。对网络环境下的数据库系统,还应该包括DBMS与网络中其他软件系统的通信功能以及数据库之间的互操作功能。
数据库管理系统的发展历史
自20世纪60年代中后期开始,使用电脑进行数据处理的规模越来越大,同时也出现了大容量的磁盘存储设备,操作系统也日渐成熟,为了解决数据的独立性问题,实现数据的统一管理,达到数据共享的目的,出现了数据库技术。
数据库技术从出现至今,经历了多次的迭代行进,在这个过程中,按时间和特性,可以将数据库管理系统分为三类。
层次数据库
层次模型数据库系统是最早研制成功的数据库系统,这种数据库中的数据被组织成一个树状模型,这种结构简单,但缺乏灵活性,各数据之间仅限于一对多的关系。
这种数据库最成功的典型代表是IBM的IMS(信息管理系统)。

网状数据库
网状数据库是采用网状原理和方法,以网状数据模型为基础建立的数据库。
网状数据模型是以记录类型为结点的网络结构,即一个结点可以有一个或多个下级结点,也可以有一个或多个上级结点,两个结点之间甚至可以有多种联系,两个记录类型之间的值可以是多对多的联系。

关系型数据库管理系统
关系数据库管理系统:Relational DatabaseManagement System(RDBMS)
是指包括相互联系的逻辑组织和存取这些数据的一套程序(数据库管理系统软件)。关系数据库管理系统就是管理关系数据库,并将数据逻辑组织的系统。
常见的关系型数据库管理系统有Oracle,MySQL,DB2,SQLServer等。
关系型数据库,是指采用了关系模型来组织数据的数据库,其以行和列的形式存储数据,以便于用户理解,关系型数据库这一系列的行和列被称为表,一组表组成了数据库。用户通过查询来检索数据库中的数据,而查询是一个用于限定数据库中某些区域的执行代码。关系模型可以简单理解为二维表格模型,而一个关系型数据库就是由二维表及其之间的关系组成的一个数据组织。
关系型数据库中的相关概念
在我们开始学习MySQL 数据库前,让我们先了解下RDBMS的一些术语:
数据库: 数据库是一些关联表的集合。
数据表: 表是数据的矩阵。在一个数据库中的表看起来像一个简单的电子表格。
列(column): 一列(数据元素) 包含了相同类型的数据, 例如邮政编码的数据。
行(Row): 一行(元组,或记录)是一组相关的数据,例如一条用户订阅的数据。
冗余: 存储两倍数据,冗余降低了性能,但提高了数据的安全性。
主键(Primary key): 主键是唯一的。一个数据表中只能包含一个主键。你可以使用主键来查询数据。
外键: 外键用于关联两个表。
复合键: 复合键(组合键)将多个列作为一个索引键,一般用于复合索引。
索引: 使用索引可快速访问数据库表中的特定信息。索引是对数据库表中一列或多列的值进行排序的一种结构。类似于书籍的目录。
参照完整性: 参照的完整性要求关系中不允许引用不存在的实体。与实体完整性是关系模型必须满足的完整性约束条件,目的是保证数据的一致性。
MySQL 为关系型数据库(Relational Database Management System), 这种所谓的"关系型"可以理解为"表格"的概念, 一个关系型数据库由一个或数个表格组成, 如图所示的一个表格:

表头(header): 每一列的名称;
列(col): 具有相同数据类型的数据的集合;
行(row): 每一行用来描述某条记录的具体信息;
值(value): 行的具体信息, 每个值必须与该列的数据类型相同;
键(key): 键的值在当前列中具有唯一性。
常见的关系型数据库系统
- MySQL:MySQL,MariaDB,Percona Server
- PostgreSQL:PgSQL,EnterpriseDB
- Oracle:Oracle
- SQLServer:MS SQLServer
- DB2
数据库软件排名
https://db-engines.com/en/ranking

关系型数据库理论
E-R模型
ER模型,全称为实体联系模型、实体关系模型或实体联系模式图(ERD:Entity-relationship model),它提供不受任何DBMS约束的面向用户的表达方法,在数据库设计中被广泛用作数据建模的工具。
E-R图模型的组成是由实体,属性和联系三部份组成。
实体:(Entity)实体是数据的使用者,代表软件系统中客观存在的生活中的实物,同一类实体构成实体集。在ER图中,实体用矩形表示。
属性:(Attribute)实体中的所有特性称为属性,每个属性描述的是实体的单个特性。在ER图中,属性用椭圆形表示。
联系:(Relationship)描述了实体的属性之间的关联规则。在ER图中,联系用菱形表示。ER模型范例:


联系类型
实体间的联系有三种类型:
**一对一联系(1:1):**一个 A 对应一个B,一个 B 对应一个A
例:
- 人 ↔ 身份证
- 丈夫 ↔ 妻子
**一对多联系(1:n):**一个 A 对应多个B,一个 B 只对应一个A
例:
- 一个班级 → 多个学生
- 一个老师 → 多个学生
- 一个部门 → 多个员工
**多对多联系(m:n):**一个 A 对应多个 B,一个 B 对应多个 A
例:
- 学生 ↔ 课程(一个学生选多门课,一门课多个学生)
- 商品 ↔ 订单
学生表一对---
| stu_id | name |
|---|---|
| 1 | 唐三 |
| 2 | 叶凡 |
老师表一对---
| teacher_id | name |
|---|---|
| 1 | gao |
| 2 | ma |
老师与课程一对多
| class_id | name | teacher_id |
|---|---|---|
| 1 | linux | 1 |
| 2 | golang | 1 |
| 3 | python | 2 |
| 4 | java | 2 |
学生与课程多对多
| class_id | stu_id |
|---|---|
| 1 | 1 |
| 1 | 2 |
| 2 | 1 |
| 2 | 2 |
| 3 | 1 |
| 3 | 2 |
数据的操作

数据库中对数据的操作主要包括增删改查
| SQL关键字 | 操作描述 | 作用 |
|---|---|---|
| Create / Insert | Insert | 增加数据 |
| Read / Select | Select | 读取数据 |
| Update / Update | Update | 更新数据 |
| Delete / Delete | Delete | 删除数据 |
数据库的正规化分析(理论)
数据库规范化,又称数据库或资料库的正规化、标准化,是数据库设计中的一系列原理和技术,以减少数据库中数据冗余,增进数据的一致性。设计关系数据库时,遵从不同的规范要求,设计出合理的关系型数据库,不同的规范要求被称为不同范式,各种范式呈递次规范,越高的范式数据库冗余越小。
目前关系数据库有六种范式:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴德斯科范式(BCNF)、第四范式(4NF)和第五范式(5NF,又称完美范式)。满足最低要求的范式是第一范式(1NF)。在第一范式的基础上进一步满足更多规范要求的称为第二范式(2NF),其余范式以次类推。一般数据库只需满足第三范式(3NF)即可。
第一范式1NF(确保每列保持原子性)
第一范式是最基本的范式。如果数据库表中的所有字段值都是不可分解的原子值,就说明该数据库表满足了第一范式。
第一范式需要根据系统的实际需求来定。其核心是要保证数据表中的列里面没有重复值,即实体中的某个属性不能有多个值或者不能有重复的属性,确保每一列的原子性。
列重复
| id | teacher_name | class_1 | class_2 | class_3 |
|---|---|---|---|---|
| 1 | ma | golang | linux | python |
| 2 | gao | golang | linu | |
| 3 | ma | golang |
列不重复
| id | teacher_name | class |
|---|---|---|
| 1 | ma | golang |
| 2 | ma | linux |
| 3 | ma | python |
| 4 | gao | golang |
| 5 | gao | linux |
| 6 | ma | golang |
第一范式(1NF)------原子性
**核心要求:**表中的每个字段都必须是不可再分的原子值。
反例:
bash
学生ID | 联系方式
001 | 13800138000, zhang@example.com
→ "联系方式"包含多个值,违反 1NF。
正例:
bash
学生ID | 手机号 | 邮箱
001 | 13800138000 | zhang@example.com
💡 简单说:每一列只能存一个值,不能是列表、集合或复合结构。
第二范式2NF(确保表中的每列都和主键相关)
第二范式在第一范式的基础之上更进一层。第二范式需要确保数据库表中的每一列都和主键相关,而不能只与主键的某一部分相关(主要针对联合主键而言)。也就是说在一个数据库表中,一个表中只能保存一种数据,不可以把多种数据保存在同一张数据库表中。
teacher_name 和city组成联合主键,city_code与city------对应,city_code依赖了部份主键,违反了第二范式
| teacher_name | city | age | city_code |
|---|---|---|---|
| gao | bj | 22 | 010 |
| teacher_name | city | age | city_code |
|---|---|---|---|
| ma | bj | 33 | 010 |
| gao | sh | 44 | 021 |
teacher_name与ctiy_id组成联合主键,再用city_id关联city_name和city_code,这样符合第二范式
| teacher_name | city_id | age |
|---|---|---|
| gao | 1 | 22 |
| ma | 1 | 33 |
| gao | 2 | 44 |
| city_id | city_name | city_code |
|---|---|---|
| 1 | bj | 010 |
| 2 | sh | 021 |
第二范式(2NF)------消除部分依赖
前提:已满足 1NF
**核心要求:**所有非主键字段必须完全依赖于整个主键(不能只依赖主键的一部分)。
适用于复合主键场景。
**部分依赖:**非主属性只依赖于主键中的某一部分。
反例(订单明细表):
bash
订单ID | 商品ID | 商品名称 | 数量
1001 | P001 | 苹果 | 5
主键 = (订单ID, 商品ID)
但"商品名称"只依赖于"商品ID",不依赖"订单ID" → 违反 2NF。
**解决方法:**拆表
- 商品表(商品ID, 商品名称)
- 订单明细表(订单ID, 商品ID, 数量)
💡 简单说:非主键字段不能"只认主键的一部分"。
第三范式3NF(确保每列都和主键列直接相关,而不是间接相关)
第三范式需要确保数据表中的每一列数据都和主键直接相关,而不能间接相关。
必须先满足第一范式才能满足第二范式,必须同时满足第一第二范式才能满足第三范式。
teacher 表一对一
| teacher_id | teacher_name |
|---|---|
| 1 | ma |
| 2 | gao |
| 3 | ma |
class表一对一
| class_id | class_name |
|---|---|
| 1 | golang |
| 2 | linux |
| 3 | python |
teacher与class多对多
| teacher_id | class_id |
|---|---|
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 2 | 1 |
| 2 | 2 |
| 2 | 3 |
第三范式(3NF)------消除传递依赖
前提:已满足 2NF
**核心要求:**非主键字段之间不能有依赖关系(即不能存在"传递依赖")。
传递依赖:A → B → C,则 C 传递依赖于 A。
所有非主属性必须直接依赖于主键,不能通过其他非主属性间接依赖。
反例:
bash
学生ID | 学院ID | 学院地址
2001 | CS01 | 北京中关村
主键 = 学生ID
依赖关系:学生ID → 学院ID → 学院地址
→ "学院地址"传递依赖于"学生ID",违反 3NF。
**解决方法:**拆表
- 学生表(学生ID, 学院ID)
- 学院表(学院ID, 学院地址)
💡 简单说:非主键字段之间不能"互相推导"。
总结:
总结对比
| 范式 | 核心目标 | 关键规则 |
|---|---|---|
| 1NF | 原子性 | 字段不可再分 |
| 2NF | 消除部分依赖 | 非主属性必须完全依赖整个主键 |
| 3NF | 消除传递依赖 | 非主属性之间不能相互依赖 |
越高范式,冗余越少,表越多。
实际开发:一般满足 3NF 即可。
SQL结构化查询语言
SQL:(StructureQueryLanguage),结构化查询语言。是一种数据库查询和程序设计语言,用于存取数据以及查询、更新和管理关系数据库系统,SQL语句就是用SQL语言写的用于操作数据库的语句。
关系型数据库一般工作于C/S模式下,使用专有协议进行通信,服务端程序监听特有端口,客户端程序发送查询语句到服务端,服务端将查询结果返回给客户端。
MySQL自带CLI接口,GUI接口可以使用第三方工具实现,在应用程序或后端开发语言中,使用相应的编程语言下的数据库驱动来进行与数据库服务端的通信。
MySQL安装和基本使用
MySQL介绍

MySQL 历史
MySQL 之父
关于 MariaDB、MySQL、MaxDB 名字的由来,这里有个不得不说的小插曲。Monty 有一个女儿,名叫 My,因此他将自己开发的数据库命名为 MySQL。Monty 还有一个儿子,名为 Max,因此在 2003 年,SAP 公司与 MySQL 公司建立合作伙伴关系后,Monty 又将与 SAP 合作开发的数据库命名为 MaxDB。而现在的 MariaDB 中的 Maria 是 Monty 小孙女(小女儿?)的名字。

Michael "Monty" Widenius, 1962 年 3 月 3 日出生于芬兰赫尔辛基。
开源 MySQL 数据库的创始成员、MySQL AB 公司的首席技术官、MySQL 数据库第一行代码的作者、MySQL 数据库命名人、MariaDB 创始人兼首席技术官;独自完成撰写 MySQL 数据库服务器端 95% 的代码。

MySQL历史
MySQL 的海豚标志的名字叫 "sakila",它是由 MySQL AB 的创始人从用户在 "海豚命名" 的竞赛中建议的大量的名字表中选出的。获胜的名字是由来自非洲斯威士兰的开源软件开发者 Ambrose Twebaze 提供。根据 Ambrose 所说,Sakila 来自一种叫 SiSwati 的斯威士兰方言,也是在 Ambrose 的家乡乌干达附近的坦桑尼亚的 Arusha 的一个小镇的名字
MySQL 的历史可以追溯到 1979 年。当时 Allan Larsson 和 Michael Widenius (Monty) 开了一家自己的咨询公司,取名 TcX,名字的由来已无从考证。有道是" 前世尽付真情,今生亦现福缘积厚"。那年一个夜黑风高的晚上,Michael 基于 BASIC 语言写出了他的第一款数据库报表工具 UNIREG。
有当年的天气记录为证,Michael 写完该工具时极光异常明亮,炫彩无比。大凡重大事情的发生,后来的著述人都会记录有一些类似的怪现象。比如刮风、下雨、冒仙气什么的,还有天上星星异常闪烁等等,反正就是说明这种事情很不简单。
最初的 UNIREG 是运行在瑞典人制造的 ABC800 计算机上的。ABC800 的内存只有 32KB,CPU 是频率只有 4MHz 的 Z80。在 1983 年 Monty 遇到了 David Axmark,两人相见恨晚,开始合作运营 TcX,Monty 负责技术,David 搞管理。后来 TcX 将 UNIREG 移植到其他更加强大的硬件平台,主要是 Sun 的平台。

一次 Monty 接到了一个项目,需要为当时的 UNIREG 提供更加通用的 SQL 接口,Monty 找到了 David Hughes --mSQL 的发明人,商讨合作事宜。然而,经过一番测试后,他们发现 mSQL 的速度并不尽如人意,无法满足客户的需求。
遇到这种问题,程序员出身的 Monty 无法委曲求全,毅然采取了革命性的态度--重新设计整个系统。
1995 年 5 月 23 日,MySQL 的第一个内部版本发行了,并在第二年对外公布了 MySQL 官方正式发行版 (3.11.1)。有趣的是,第一个 MySQL 正式版恰巧只能运行在 Sun Solaris 上,仿佛昭示了它日后被 Sun 收购的命运。
在接下来的两年中,MySQL 被移植到不同的平台,同时加入了不少新的特性。到 1998 时,MySQL 能够运行在 10 多种操作系统之上,其中包括应用非常广泛的 FreeBSD、Linux、Windows 95 和 Windows NT 等。很快 MySQL 3.22 也发布了,但它仍然存在很多问题--如不支持事务操作、子查询、外键、存储过程和视图等功能。正因为这些缺陷,当时许多 Oracle 和 SQL Server 的用户对 MySQL 根本不屑一顾。
大概在 1999 的冬天,下了很大一场雪。然后独立的商业公司 MySQL AB 就在瑞典的中部城市 Uppsala 成立了。并于同年发布了包含事务型存储引擎 BDB 的 MySQL 3.23。在集成 BDB 存储引擎的过程中,MySQL 开发团队得到了很好的锻炼,为后来能将 InnoDB 整合以及开发开放插件式的存储引擎架构打下了坚实的基础。
MySQL 从诞生之初就提供了双重的授权标准:个人使用是免费的,如果用于商业网站搭建或者 Windows 平台下就必须购买商业许可证。在 2000 年的时候 MySQL 做了一个重大的决定,改换成了 GPL 许可模式,也就是说商业用户也无需再购买许可证,但必须把他们的源码公开。虽然 MySQL AB 因此在收入上遭受了巨大的打击,损失了将近 80% 的收入,但他们依然坚持了 GPL 许可模式。
与此同时,芬兰公司 Heikki 开始接触 MySQL AB,讨论将 Heikki 的存储引擎 InnoDB 整合到 MySQL 数据库中的可行性。双方的合作非常顺利,并于 2001 年推出 MySQL 4.0 Alpha 版本。经过两年的公开测试和应用,到了 2003 年,包含 InnoDB 的 MySQL 已经变得非常稳定了。随即在同一年,MySQL 推出 4.1 版,第一次使得 MySQL 支持子查询,支持 Unicode 和预编译 SQL 等功能。
MySQL 4.1 还在 Alpha 版时,公司已决定并行开发 5.0 版。因为他们打算加快 MySQL 的开发速度以适应日益苛刻的市场需求。这个新版本是有史以来 MySQL 最大的变化,添加了存储过程、服务端游标、触发器、查询优化以及分布式事务等在大家看来一个" 正常数据库管理系统" 应当拥有的一整套功能。
2008 年 2 月,当时的业界开源老大 Sun Microsystems 动用 10 亿美元收购了 MySQL,造就了开源软件的收购最高价。这次交易给开源交易设立了一个新的基准。在此之前的交易金额 (JBoss、Zimbra、XenSource、Gluecode) 从没接近过 10 亿美元,全部加起来才差不多与 Sun Microsystems 购买 MySQL 的花费持平。MySQL 被收购之后,MySQL 图标停止使用,取而代之的是 Sun/MySQL 图标。
MySQL 和 Sun 合并之后,推出了 MySQL 5.1GA 版和 MySQL 5.4 Beta 版。5.4 的推出照搬了 4.1 和 5.0 当时的开发模式,让 5.4 和 6.0 并行处于 Beta 开发阶段。
螳螂捕蝉,黄雀在后。2009 年,数据库老大 Oracle 大笔一挥,开出 74 亿美元的支票,将 Sun Microsystems 和 MySQL 通盘收于旗下。
这里附带说明一下 Drizzle,它是 Sun/MySQL 的 Brian 在 2008 年提出的一个计划。目标是将开发一个更小、更轻、更快的数据库,用作云计算 (Cloud Computing) 和 Web 应用的基础架构。
标志性事件
-
1999 年,MySQL AB 在瑞典正式宣布成立。
-
2000 年,ISAM 华丽转身 MyISAM 存储引擎。同年 MySQL 开放了自己的源代码,并且基于 GPL 许可协议。同年 9 月 innoDB 推出。
-
2003 年,MySQL4.0 发布,正式集成 innodb
-
2005 年,MySQL 5.0 发布。同年 Oracle 把 InnoDB 引擎的开发公司 innobase 收购完成。MySQL 明确地表现出迈向高性能数据库的发展步伐。
-
2006 年,sun 公司收购了 MySQL 公司,出价 10 亿美元。
-
2009 年,Oracle 公司收购 sun,将 MySQL 纳入囊中。
-
2010 年,MySQL 5.5 正式版发布,Oracle 完成了大量改进,并将 innodb 改成默认引擎。
-
2013 年,MySQL 5.6 GA 版本发布。
-
近期 - MySQL 5.7 GA 版本横空出世,其性能、新特性、性能分析带来了质的改变。
全球最大网站Top20,90%在使用Mysql

-
WIKipedia.org - 维基百科
-
Live.com -- 微软新的电子邮件服务
-
qq.com -- 腾讯
-
Microsoft.com -- 微软产品 / 更新 / 下载
-
Baidu.com -- 百度
-
Msn.com -- 微软自有互联网信息
-
Blogger.com -- 博客平台
-
ASK.com - 搜索引擎
-
Taobao.com 淘宝
-
Twiter.com -- 实时通讯平台
-
Bing.com -- 必应
-
Sohu.com -- 搜狐
-
Apple.com -- 苹果
-
WrodPress.com -- 成行经历
-
Sina.com -- 新浪
-
Amazon.com - 亚马逊
全球MySQL行业应用

国内MySQL行业应用

MySQL 系列
尽管 MySQL 是最受欢迎的程序之一,但是许多开发人员认为有必要将其拆分成其他项目,并且每个分支项目都有自己的专长。该需求以及 Oracle 对核心产品增长缓慢的担忧,导致出现了许多开发人员感兴趣的子项目和分支。本文将讨论受人们关注的三个流行 MySQL 分支:Drizzle、MariaDB 和 Percona Server(包括 XtraDB 引擎)
MySQL
官方 MySQL,前身 MySQL AB / SUM / 最后被 Oracle 公司收入麾下。
Percona
Percona Server 就是这样一款产品,由领先的 MySQL 咨询公司 Percona 发布。Percona Server 是一款独立的数据库产品,为用户提供了换出其 MySQL 安装并换入 Percona Server 产品的能力。通过这样做,就可以利用 XtraDB 存储引擎。Percona Server 声称可以完全与 MySQL 兼容,因此从理论上讲,您无需更改软件中的任何代码。这确实是一个很大的优势,适合在您寻找快速性能改进时控制质量。因此,采用 Percona Server 的一个很好的理由是,利用 XtraDB 引擎来尽可能地减少代码更改。
此外,他们是 XtraDB 存储引擎的原作者。Percona 将此代码用作开源代码,因此您可以在其他产品中找到它,但引擎的最初创建者与编写此产品的是同一个人,所以您可以随心所欲地使用此信息。
Percona 团队的最终声明是 "Percona Server 是由 Oracle 发布的最接近官方 MySQL Enterprise 发行版的版本",因此与其他更改了大量基本核心 MySQL 代码的分支有所区别。Percona Server 的一个缺点是他们自己管理代码,不接受外部开发人员的贡献,以这种方式确保他们对产品中所包含功能的控制。
下面是 Percona Server 的声明,该声明来自它们自己的网站:
- 可扩展性:处理更多事务;在强大的服务器上进行扩展
- 性能:使用了 XtraDB 的 Percona Server 速度非常快
- 可靠性:避免损坏,提供崩溃安全 (crash-safe) 复制
- 管理:在线备份,在线表格导入 / 导出
- 诊断:高级分析和检测
- 灵活性:可变的页面大小,改进的缓冲池管理
MariaDB
MySQL 之父 Widenius 先生离开了 Sun 之后,觉得依靠 Sun/Oracle 来发 展 MySQL,实在很不靠谱,于是决定另开分支,这个分支的名字叫做 MariaDB;
在卖出 MySQL 之后 Widenius 发现两个主要问题:
- MySQL 核心开发团队是封闭的,完全没有 Oracle 之外的成员参加。很多高手即使 有心做贡献,也没办法做到
- MySQL 新版本的发布速度,在 Oracle 收购 Sun 之后大为减缓。Widenius 用数据比 较了收购之前和之后新版本的发布速度。有很多 bugfix 和新的 feature,都没有及 时加入到发布版本之中
目标是提供一个由社区开发的、稳定的、总是免费的 MySQL 分支,在用 户级别上兼容主流版本。我们为自己的版本和上游、社区版的互操作性 提高而努力;Monty Program 公司承诺 MariaDB 将会一直保持独立和开源。值得一提的是,Fedora 及 OpenSUSE Linux 更宣布将在 MariaDB 推出下 一个版本后抛弃 MySQL 使用 MariaDB。
MariaDB 提供了 MySQL 提供的标准存储引擎,即 MyISAM 和 InnoDB。因此,实际上,可以将它视为 MySQL 的扩展集,它不仅提供 MySQL 提供的所有功能,还提供其他功能。MariaDB 还声称自己是 MySQL 的替代,因此从 MySQL 切换到 MariaDB 时,无需更改任何基本代码即可安装它。
最后可能也是最重要的一点是,MariaDB 的主要创建者是 Monty Widenius,也是 MySQL 的初始创建者。Monty 成立了一家名为 Monty Program 的公司来管理 MariaDB 的开发,这家公司雇佣开发人员来编写和改进 MariaDB 产品。这既是一件好事,也是一件坏事:有利的一面在于他们是 Maria 功能和 bug 修复的佼佼者,但公司不是以赢利为目的,而是由产品驱动的,这可能会带来问题,因为没有赢利的公司不一定能长久维持下去。
MySQL 的特性
- MySQL是基于开源协议发布的,可以免费使用,也可以基于源码进行二次开发。
- MySQL使用标准SQL语言进行管理。
- MySQL可以运行于多个系统上,具有跨平台特性,并且支持多种语言。
- MySQL使用插件式存储引擎,不同的存储引擎,有着不同的功能和特性,使用者可以根据需要灵活选择。
- MySQL基于单进程,多线程的模式进行工作。
- MySQL提供了大量的测试组件和诸多的扩展。
MySQL安装
参考mysql安装手册
MySQL多实例
数据库多实例介绍
什么是数据库多实例
拿MySQL数据库来说明,就是在一台服务器上运行多个MySQL服务端进程,每个进程监听一个端口(3306,3307,3308),维护一套属于其自己的配置和数据,客户端使用不同的端口来连接具体服端进程,从而实现对不同的实例的操作。
多实例的优点
节约硬件资源:在某些场景下(比如说测试,调研,新旧业务并存等),需要配置不同的MySQL数据库版本,而又没有足够多的服务器资源,则可以选择在一台服务器上用不同的版本实现多开来满足需求。
便于对比:在一个完全相同的硬件环境中,运行不同的MySQL版本,使用相同的参数进行测试,调研时,可以最大程度的减少外部环境因素的影响,便于得出更准确的结论。
便于管理:在一台服务器上运行多个实例,同理,只需要在这一台服务器上配置安全规则,就可以完成对多个实例的访问授权,而且对于数据库的备份,停启等工作,也只需要在这一台服务器上完成。
多实例的缺点
资源抢占:一台服务器上运行多个服务实例,资源总量恒定,一个实例占用的资源无法被另一个实例所使用,在这种情况下,服务性能会受到影响,无法体现MySQL服务的实际性能。
存在单点风险:一台服务器上部署多个服务实例,如果该服务器当机,则这多个服务实例都会受影响。
MySQL多实例配置方案
可以用不同的MySQL版本实现多实例,也可以用相同的MySQL版本实现多实例。

MySQL组成和常用工具
MySQL主要组成
mysql基于C/S模式提供服务,主要有客户端程序和服务端程序组成,另外还有一些管理工具。
服务端主要组成
| 程序 | 功能 |
|---|---|
| mysqld_safe | 安全启动脚本 |
| mysqld | 服务端程序,是mysql服务的核心程序 |
| mysqld_multi | 多实例工具 |
客户端主要组成
| 程序 | 功能 |
|---|---|
| mysql | 基于mysql协议的交互式CLI工具 |
| mysqldump | 备份工具 |
| mysqladmin | 服务端管理工具 |
| mysqlimport | 数据导入工具 |
MyISAM存储引擎的管理工具
| 程序 | 功能 |
|---|---|
| myisamchk | 检测MyISAM库 |
| myisampack | 打包MyISAM表,只读 |
配置文件
不同版本配置文件略有不同
bash
# 查看MySQL主配置文件内容
[root@localhost ~]# cat /etc/my.cnf
#
# This group is read both both by the client and the server
# use it for options that affect everything
#
[client-server]
#
# include all files from the config directory
#
!includedir /etc/my.cnf.d
# 查看配置文件目录结构
[root@localhost ~]# tree /etc/my.cnf.d/
/etc/my.cnf.d/
├── client.cnf #客户端配置
bash
├── mysql-default-authentication-plugin.cnf
└── mysql-server.cnf #服务器端配置
0 directories, 3 files
生效顺序
bash
# 查看MySQL读取配置文件的顺序
[root@localhost ~]# mysql --help | grep my.cnf
order of preference, my.cnf, $MYSQL_TCP_PORT,
/etc/my.cnf /etc/mysql/my.cnf ~/.my.cnf
MySQL中的用户账户
详见MySQL用户管理
MySQL 命令类型
MySQL中的命令分为两类,分别是客户端命令和服务端命令。
客户端命令在本地执行。服务端命令发送到服务端执行,再返回执行结果到客户端上。
客户端命令和服务端命令,都是通过MySQL客户端工具进行输入输出。
查看所有客户端命令
bash
# 在MySQL交互界面中输入?查看所有客户端命令
mysql> ?
For information about MySQL products and services, visit:
http://www.mysql.com/
For developer information, including the MySQL Reference Manual, visit:
http://dev.mysql.com/
To buy MySQL Enterprise support, training, or other products, visit:
https://shop.mysql.com/
List of all MySQL commands:
Note that all text commands must be first on line and end with ';'
? (\?) Synonym for `help'.
clear (\c) Clear the current input statement.
connect (\r) Reconnect to the server. Optional arguments are db and host.
delimiter (\d) Set statement delimiter.
edit (\e) Edit command with $EDITOR.
ego (\G) Send command to mysql server, display result vertically.
exit (\q) Exit mysql. Same as quit.
go (\g) Send command to mysql server.
help (\h) Display this help.
nopager (\n) Disable pager, print to stdout.
notee (\t) Don't write into outfile.
pager (\P) Set PAGER [to_pager]. Print the query results via PAGER.
print (\p) Print current command.
prompt (\R) Change your mysql prompt.
bash
quit (\q) Quit mysql.
rehash (\#) Rebuild completion hash.
source (\.) Execute an SQL script file. Takes a file name as an argument.
status (\s) Get status information from the server.
system (\!) Execute a system shell command.
tee (\T) Set outfile [to_outfile]. Append everything into given outfile.
use (\u) Use another database. Takes database name as argument.
charset (\C) Switch to another charset. Might be needed for processing binlog with multi-byte charsets.
warnings (\W) Show warnings after every statement.
nowarning (\w) Don't show warnings after every statement.
resetconnection(\x) Clean session context.
query_attributes Sets string parameters (name1 value1 name2 value2 ...) for the next query to pick up.
For server side help, type 'help contents'
查看所有服务端命令
bash
# 查看服务端帮助目录分类
mysql> help contents
You asked for help about help category: "Contents"
For more information, type 'help <item>', where <item> is one of the following categories:
Account Management
Administration
Components
Compound Statements
Contents
Data Definition
Data Manipulation
Data Types
Functions
Geographic Features
Help Metadata
Language Structure
Loadable Functions
Plugins
Prepared Statements
Replication Statements
Storage Engines
Table Maintenance
Transactions
Utility
查看服务端命令具体项
bash
# 查看Administration分类下的所有命令
mysql> help Administration
You asked for help about help category: "Administration"
For more information, type 'help <item>', where <item> is one of the following topics:
BINLOG
CACHE INDEX
FLUSH
HELP COMMAND
bash
KILL
LOAD INDEX
RESET
RESET PERSIST
RESTART
SET
SET CHARACTER SET
SET CHARSET
SET NAMES
SHOW
SHOW BINARY LOGS
SHOW BINLOG EVENTS
SHOW CHARACTER SET
SHOW COLLATION
SHOW COLUMNS
SHOW CREATE DATABASE
SHOW CREATE EVENT
SHOW CREATE FUNCTION
SHOW CREATE PROCEDURE
SHOW CREATE SCHEMA
SHOW CREATE TABLE
SHOW CREATE TRIGGER
SHOW CREATE USER
SHOW CREATE VIEW
SHOW DATABASES
SHOW ENGINE
SHOW ENGINES
SHOW ERRORS
SHOW EVENTS
SHOW FIELDS
SHOW FUNCTION CODE
SHOW FUNCTION STATUS
SHOW GRANTS
SHOW INDEX
SHOW MASTER LOGS
SHOW MASTER STATUS
SHOW OPEN TABLES
SHOW PLUGINS
SHOW PRIVILEGES
SHOW PROCEDURE CODE
SHOW PROCEDURE STATUS
SHOW PROCESSLIST
SHOW PROFILE
SHOW PROFILES
SHOW RELAYLOG EVENTS
SHOW REPLICA STATUS
SHOW REPLICAS
SHOW SCHEMAS
SHOW SLAVE HOSTS
SHOW SLAVE STATUS
SHOW STATUS
SHOW TABLE STATUS
SHOW TABLES
SHOW TRIGGERS
SHOW VARIABLES
SHOW WARNINGS
bash
SHUTDOWN
查看详细帮助
bash
# 查看BINLOG命令的详细帮助文档
mysql> help BINLOG
Name: 'BINLOG'
Description:
Syntax:
BINLOG 'str'
BINLOG is an internal-use statement. It is generated by the mysqlbinlog program as the printable representation of certain events in binary log files. (See https://dev.mysql.com/doc/refman/8.0/en/mysqlbinlog.html.)
The 'str' value is a base 64-encoded string the that server decodes to determine the data change indicated by the corresponding event.
To execute BINLOG statements when applying mysqlbinlog output, a user account requires the BINLOG_ADMIN privilege (or the deprecated SUPER privilege), or the REPLICATION_APPLIER privilege plus the appropriate privileges to execute each log event.
URL: https://dev.mysql.com/doc/refman/8.0/en/binlog.html
MySQL客户端使用
MySQL服务基于C/S架构,用户主要使用客户端工具来与远程服务端进行连接,从而与MySQL服务进行交互。
MySQL客户端常用选项
格式:
bash
# 查看mysql客户端帮助信息
[root@localhost ~]# mysql --help
Usage: mysql [OPTIONS] [database]
#常用选项
-V|--version #显示客户端版本
-u|--user=name #指定远程连接用户名
-p|--password[=name] #指定密码,默认为空
-h|--host=host #指定服务端主机
-P|--port=port #指定端口,默认3306
-S|--socket=name #指定连接时使用的socket文件,该文件在服务端启动后生成
-D|--database=db #指定数据库
-H|--html #以html格式输出
-X|--xml #以xml格式输出
-t|--table #以table格式输出,默认项
-E|--vertical #垂直显示执行结果
-v|--verbose #显示详细信息,配合-t选项
-C|--compress #启用压缩
-G|--named-commands #启用长命令
-e|--execute=sql #执行完就退出,非交互式运行
-prompt=name #修改命令提示符
--line-numbers #输出行号
bash
--print-defaults #打印参数列表,放在最前面
--connect-timeout=N #连接超时时长,单位S
--max-allowed-packet=N #一次查交互发送或反回数据的大小,默认16MB,最大值为1GB,最小值为4096字节
范例:
bash
#免密登录
[root@localhost ~]# mysql -uroot -pHuawei@123
#将mysql root账号密码设置为空
mysql> alter user root@localhost identified by '';
#退出mysql
mysql> quit
#显示版本
[root@localhost ~]# mysql -V
mysql Ver 8.0.26 for Linux on x86_64 (Source distribution)
#指定用户名,主机,端口
[root@localhost ~]# mysql -uroot -h127.0.0.1 -P3306
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 22
Server version: 8.0.26 Source distribution
Copyright (c) 2000, 2021, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
#使用主机名
[root@localhost ~]# mysql --user=root --host=localhost --port=3306
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 23
Server version: 8.0.26 Source distribution
Copyright (c) 2000, 2021, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
#默认使用root连接,密码为空
[root@localhost ~]# mysql
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 24
Server version: 8.0.26 Source distribution
bash
Copyright (c) 2000, 2021, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
#打印参数列表,并不连接服务端,--print-defaults要放在第一个
[root@localhost ~]# mysql --print-defaults -uroot -hlocalhost --connect-timeout=2
mysql would have been started with the following arguments:
-uroot -hlocalhost --connect-timeout=2
#以html格式显示输出
[root@localhost ~]# mysql -H
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 25
Server version: 8.0.26 Source distribution
Copyright (c) 2000, 2021, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> select version();
<TABLE BORDER=1><TR><TH>version()</TH></TR><TR><TD>8.0.26</TD></TR></TABLE>1 row in set (0.00 sec)
范例:执行完退出,非交互式执行
bash
#环境准备
[root@localhost ~]# vim /root/test.sql
show databases;
#执行客户端命令
[root@localhost ~]# mysql -e "source /root/test.sql"
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
#管道执行
[root@localhost ~]# cat test.sql | mysql
Database
information_schema
mysql
bash
performance_schema
sys
#标准输入重定向执行
[root@localhost ~]# mysql -uroot < test.sql
Database
information_schema
mysql
performance_schema
sys
#以table格式输出
[root@localhost ~]# mysql -e "show databases;"
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
#垂直显示
[root@localhost ~]# mysql -e "show databases;" -E
*************************** 1. row ***************************
Database: information_schema
*************************** 2. row ***************************
Database: mysql
*************************** 3. row ***************************
Database: performance_schema
*************************** 4. row ***************************
Database: sys
范例:修改提示符
bash
# 登录时通过--prompt参数修改命令提示符为[test]
[root@localhost ~]# mysql --prompt=[test]
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 37
Server version: 8.0.26 Source distribution
Copyright (c) 2000, 2021, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
[test]
范例:指定数据库
bash
#默认
[root@localhost ~]# mysql
bash
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 38
Server version: 8.0.26 Source distribution
Copyright (c) 2000, 2021, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.00 sec)
mysql>
#指定数据库
[root@localhost ~]# mysql information_schema
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 41
Server version: 8.0.26 Source distribution
Copyright (c) 2000, 2021, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> SELECT DATABASE();
+--------------------+
| DATABASE() |
+--------------------+
| information_schema |
+--------------------+
1 row in set (0.01 sec)
mysql>
MySQL客户端常用命令
bash
# 查看所有客户端命令帮助
mysql> ?
For information about MySQL products and services, visit:
http://www.mysql.com/
For developer information, including the MySQL Reference Manual, visit:
http://dev.mysql.com/
To buy MySQL Enterprise support, training, or other products, visit:
https://shop.mysql.com/
List of all MySQL commands:
Note that all text commands must be first on line and end with ';'
? (\?) Synonym for `help'.
clear (\c) Clear the current input statement.
connect (\r) Reconnect to the server. Optional arguments are db and host.
delimiter (\d) Set statement delimiter.
edit (\e) Edit command with $EDITOR.
ego (\G) Send command to mysql server, display result vertically.
exit (\q) Exit mysql. Same as quit.
go (\g) Send command to mysql server.
help (\h) Display this help.
nopager (\n) Disable pager, print to stdout.
notee (\t) Don't write into outfile.
pager (\P) Set PAGER [to_pager]. Print the query results via PAGER.
print (\p) Print current command.
prompt (\R) Change your mysql prompt.
quit (\q) Quit mysql.
rehash (\#) Rebuild completion hash.
source (\.) Execute an SQL script file. Takes a file name as an argument.
status (\s) Get status information from the server.
system (\!) Execute a system shell command.
tee (\T) Set outfile [to_outfile]. Append everything into given outfile.
use (\u) Use another database. Takes database name as argument.
charset (\C) Switch to another charset. Might be needed for processing binlog with multi-byte charsets.
warnings (\W) Show warnings after every statement.
nowarning (\w) Don't show warnings after every statement.
resetconnection(\x) Clean session context.
query_attributes Sets string parameters (name1 value1 name2 value2 ...) for the next query to pick up.
For server side help, type 'help contents'
范例:显示当前数据库
bash
#显示当前数据库
mysql> \s
--------------
mysql Ver 8.0.26 for Linux on x86_64 (Source distribution)
Connection id: 8 #连接ID
Current database: #当前使用的数据库
bash
Current user: root@localhost #连接使用的用户名
SSL: Not in use #是否使用ssl
Current pager: stdout
Using outfile: ''
Using delimiter: ;
Server version: 8.0.26 Source distribution #版本
Protocol version: 10 #协议版本
Connection: Localhost via UNIX socket
Server characterset: utf8mb4 #服务器编码
Db characterset: utf8mb4 #数据库编码
Client characterset: utf8mb4 #客户端编码
Conn. characterset: utf8mb4
UNIX socket: /var/lib/mysql/mysql.sock #连接使用的socket文件
Binary data as: Hexadecimal
Uptime: 28 min 46 sec #服务器运行时长
Threads: 2 Questions: 6 Slow queries: 0 Opens: 117 Flush tables: 3 Open tables: 36 Queries per second avg: 0.003
--------------
范例:切换数据库
bash
# 切换当前使用的数据库为mysql
mysql> use mysql;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql>
范例:调用系统命令
bash
mysql> \! hostname #查看宿主机主机名,!号后面有空格
localhost.localdomain
mysql> \! clear #清屏
范例:修改提示符
bash
# 在MySQL交互界面中用prompt命令修改提示符,\h为主机名,\D为完整日期时间
mysql> prompt [\h--\D]
PROMPT set to '[\h--\D]'
[localhost--Mon Sep 15 22:09:09 2025]
[localhost--Mon Sep 15 22:10:01 2025]
# 将提示符修改为abcd
mysql> \R abcd
PROMPT set to 'abcd'
abcd
abcd
在配置文件中修改提示符
bash
# 编辑MySQL客户端配置文件
[root@localhost ~]# vim /etc/my.cnf.d/client.cnf
[client]
prompt=(\\u@\\h) [\\d]>\\

bash
# 验证效果
[root@localhost ~]# mysql
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 12
Server version: 8.0.26 Source distribution
Copyright (c) 2000, 2021, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
(root@localhost) [(none)]> #效果
提示符中可用的变量,全部可用的替换符用man mysql查看
bash
\C #计数器
\D #年月日时分秒
\d #当前使用的数据库
\h #服务器主机名
\l #命令分隔符,默认;
\m #当前时间,分钟
\n #换行
\O #月份,以英文显示
\o #月份,数字显示
\P #pm/am
\R #小时,24小时制
\r #小时,12小时制
\S #分号
\s #秒,数字显示
\t #tab键
\U #客户端用户名和主机
\u #客户端用户名
\v #服务端版本
\w #星期几,英文显示
\Y #年份,四位,数字显示
\y #年份,两位,数字显示
范例:执行SQL脚本
bash
# 编辑SQL脚本文件
[root@localhost ~]# vim test.sql
show databases;
# 在MySQL交互界面中用source命令执行SQL脚本文件
mysql> \. /root/test.sql
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.00 sec)
范例:重连
bash
# 登录MySQL
[root@localhost ~]# mysql
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 19
Server version: 8.0.26 Source distribution
Copyright (c) 2000, 2021, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
# 重连服务器
mysql> \r
Connection id: 20
Current database: *** NONE ***
# 先切换到mysql数据库
mysql> use mysql
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
# 再次重连,验证当前数据库是否保持
mysql> \r
Connection id: 21
Current database: mysql
mysql>
范例:往文件中保存输出结果
bash
mysql> tee db.txt #设置写到文件db.txt
Logging to file 'db.txt'
mysql> select version(); #执行SQL语句
+-----------+
| version() |
+-----------+
| 8.0.26 |
+-----------+
bash
1 row in set (0.00 sec)
mysql> \t #设置不写文件
Outfile disabled.
mysql> show databases; #执行SQL语句
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.00 sec)
mysql> quit #退出
Bye
[root@localhost ~]# cat db.txt #只记录了\t之前的命令
mysql> select version();
+-----------+
| version() |
+-----------+
| 8.0.26 |
+-----------+
1 row in set (0.00 sec)
mysql> \t
[root@localhost ~]#
范例:自定义
bash
#两条查询语句,默认用;分隔
mysql> select version();show databases;
+-----------+
| version() |
+-----------+
| 8.0.26 |
+-----------+
1 row in set (0.00 sec)
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.01 sec)
#设置$分隔
mysql> \d $
bash
mysql> select version()$show databases$
+-----------+
| version() |
+-----------+
| 8.0.26 |
+-----------+
1 row in set (0.01 sec)
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.00 sec)
范例:发送语句到服务端
bash
mysql> select version();
+-----------+
| version() |
+-----------+
| 8.0.26 |
+-----------+
1 row in set (0.01 sec)
# 使用\g发送语句到服务端,等同于;结尾
mysql> select version()\g
+-----------+
| version() |
+-----------+
| 8.0.26 |
+-----------+
1 row in set (0.00 sec)
# 使用\G发送语句到服务端并垂直显示结果
mysql> select version()\G
*************************** 1. row ***************************
version(): 8.0.26
1 row in set (0.00 sec)
#开启长命令格式
[root@localhost ~]# mysql --named-commands
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 26
Server version: 8.0.26 Source distribution
Copyright (c) 2000, 2021, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
bash
mysql> select version() #这里要断句
-> go
+-----------+
| version() |
+-----------+
| 8.0.26 |
+-----------+
1 row in set (0.00 sec)
mysql> select version() #这里要断句
-> ego
*************************** 1. row ***************************
version(): 8.0.26
1 row in set (0.00 sec)
范例:只输出不执行
bash
# 使用\p打印当前输入的命令但不执行
mysql> select version()\p
--------------
select version()
--------------
->
mysqladmin工具
mysqladmin也是用于管理mysql服务的本地工具
格式
bash
# 查看mysqladmin帮助信息
[root@localhost ~]# mysqladmin --help
mysqladmin Ver 8.0.26 for Linux on x86_64 (Source distribution)
Copyright (c) 2000, 2021, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners.
owners.
Administration program for the mysqld daemon.
Usage: mysqladmin [OPTIONS] command command....
--bind-address=name IP address to bind to.
-c, --count=# Number of iterations to make. This works with -i (#总共执行多少次,配合-i选项使用) (--sleep) only.
-#, --debug[=#] This is a non-debug version. Catch this and exit.
--debug-check This is a non-debug version. Catch this and exit.
--debug-info This is a non-debug version. Catch this and exit.
-f, --force Don't ask for confirmation on drop database; with multiple commands, continue even if an error occurs.
-C, --compress Use compression in server/client protocol. #启用压缩
--character-sets-dir=name
Directory for character set files.
bash
--default-character-set=name
Set the default character set.
-?, --help Display this help and exit. #显示帮助信息
-h, --host=name Connect to host. #指定服务器地址
-b, --no-beep Turn off beep on error.
-p, --password[=name] #指定连接服务器的密码
Password to use when connecting to server. If password is not given it's asked from the tty.
-P, --port=# Port number to use for connection or 0 for default to, in (#指定服务器端口,默认3306) order of preference, my.cnf, $MYSQL_TCP_PORT, /etc/services, built-in default (3306).
--protocol=name The protocol to use for connection (tcp, socket, pipe, #指定连接方式(tcp\socket\pipe\memory) memory).
-r, --relative Show difference between current and previous values when used with -i. Currently only works with extended-status.
-s, --silent Silently exit if one can't connect to server. #如果无法连接,则静默退出
-S, --socket=name The socket file to use for connection. #指定连接时使用socket文件
-i, --sleep=# Execute commands repeatedly with a sleep between. #持续执行命令,间隔N秒执行一次
--ssl-mode=name SSL connection mode.
--ssl-ca=name CA file in PEM format.
--ssl-capath=name CA directory.
--ssl-cert=name X509 cert in PEM format.
--ssl-cipher=name SSL cipher to use.
--ssl-key=name X509 key in PEM format.
--ssl-crl=name Certificate revocation list.
--ssl-crlpath=name Certificate revocation list path.
--tls-version=name TLS version to use, permitted values are: TLSv1, TLSv1.1, TLSv1.2, TLSv1.3
--ssl-fips-mode=name
SSL FIPS mode (applies only for OpenSSL); permitted values are: OFF, ON, STRICT
--tls-ciphersuites=name
TLS v1.3 cipher to use.
--server-public-key-path=name
File path to the server public RSA key in PEM format.
--get-server-public-key
Get server public key
-u, --user=name User for login if not current user. #指定用户名
-v, --verbose Write more information.
-V, --version Output version information and exit. #显示客户端版本
-E, --vertical Print output vertically. Is similar to --relative, but prints output vertically.
-w, --wait[=#] Wait and retry if connection is down. #如果连接失败,是否等待重试,如果指定了具体数字,则表示重试几次
--connect-timeout=# #指定连接超时时长
--shutdown-timeout=# #指定关机超时时长
--plugin-dir=name Directory for client-side plugins. #客户端插件目录
--default-auth=name Default authentication client-side plugin to use.
--enable-cleartext-plugin
Enable/disable the clear text authentication plugin.
bash
--show-warnings Show warnings after execution
--compression-algorithms=name
Use compression algorithm in server/client protocol. Valid values are any combination of 'zstd','zlib','uncompressed'.
--zstd-compression-level=#
Use this compression level in the client/server protocol, in case --compression-algorithms=zstd. Valid range is between 1 and 22, inclusive. Default is 3.
Variables (--variable-name=value)
and boolean options {FALSE|TRUE} Value (after reading options)
--------------------------------- ----------------------------------------
bind-address (No default value)
count 0
force FALSE
compress FALSE
character-sets-dir (No default value)
default-character-set auto
host (No default value)
no-beep FALSE
port 0
relative FALSE
socket (No default value)
sleep 0
ssl-ca (No default value)
ssl-capath (No default value)
ssl-cert (No default value)
ssl-cipher (No default value)
ssl-key (No default value)
ssl-crl (No default value)
ssl-crlpath (No default value)
tls-version (No default value)
tls-ciphersuites (No default value)
server-public-key-path (No default value)
get-server-public-key FALSE
user (No default value)
verbose FALSE
vertical FALSE
connect-timeout 43200
shutdown-timeout 3600
plugin-dir (No default value)
default-auth (No default value)
enable-cleartext-plugin FALSE
show-warnings FALSE
compression-algorithms (No default value)
zstd-compression-level 3
Default options are read from the following files in the given order:
/etc/my.cnf /etc/mysql/my.cnf ~/.my.cnf
The following groups are read: mysqladmin client
The following options may be given as the first argument:
--print-defaults Print the program argument list and exit. #显示运行参数
--no-defaults Don't read default options from any option file, except for login file.
bash
--defaults-file=# Only read default options from the given file #. #从指定文件中读取选项
--defaults-extra-file=# Read this file after the global files are read.
--defaults-group-suffix=#
Also read groups with concat(group, suffix)
--login-path=# Read this path from the login file.
Where command is a one or more of: (Commands may be shortened)
create databasename Create a new database #创建新的数据库
debug Instruct server to write debug information to log #开启调试模式,将调试信息写入log
drop databasename Delete a database and all its tables #删除指定数据库
extended-status Gives an extended status message from the server #显示扩展状态
flush-hosts Flush all cached hosts #刷新所有缓存的主机
flush-logs Flush all logs #刷新所有日志
flush-status Clear status variables #刷新状态变量
flush-tables Flush all tables #刷新所有表,会强制关闭已打开的表
flush-threads Flush the thread cache #刷新线程缓存
flush-privileges Reload grant tables (same as reload) #刷新访问权限
kill id,id,... Kill mysql threads
password [new-password] Change old password to new-password in current format #修改密码
ping Check if mysqld is alive #心跳检测
processlist Show list of active threads in server #显示活动线程列表
reload Reload grant tables #刷新授权信息
refresh Flush all tables and close and open logfiles #刷新所有数据库表,重新打开日志文件
shutdown Take server down #关闭服务
status Gives a short status message from the server #简短显示服务端状态
start-replica Start replication
start-slave Deprecated: use start-replica instead #开启主从同步
stop-replica Stop replication
stop-slave Deprecated: use stop-replica instead #停止主从同步
variables Prints variables available #显示服务端所有变量
version Get version info from server #显示客户端和服务端版本
范例:显示版本信息
bash
#客户端版本
[root@localhost ~]# mysqladmin -V
mysqladmin Ver 8.0.26 for Linux on x86_64 (Source distribution)
#客户端和服务端版本信息
[root@localhost ~]# mysqladmin version
mysqladmin Ver 8.0.26 for Linux on x86_64 (Source distribution)
Copyright (c) 2000, 2021, Oracle and/or its affiliates.
bash
Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners.
Server version 8.0.26
Protocol version 10
Connection Localhost via UNIX socket
UNIX socket /var/lib/mysql/mysql.sock
Uptime: 1 hour 44 min 34 sec
Threads: 4 Questions: 189 Slow queries: 0 Opens: 287 Flush tables: 3 Open tables: 206 Queries per second avg: 0.030
范例:显示状态信息
bash
# 查看mysqladmin简短状态信息
[root@localhost ~]# mysqladmin status
Uptime: 6352 Threads: 4 Questions: 191 Slow queries: 0 Opens: 287 Flush tables: 3 Open tables: 206 Queries per second avg: 0.030
范例:设置连接超时
bash
# 连接到不存在的主机1.2.3.4,超时时间2秒,执行ping命令
[root@localhost ~]# mysqladmin -h1.2.3.4 --connect-timeout=2 ping
mysqladmin: connect to server at '1.2.3.4' failed
error: 'Can't connect to MySQL server on '1.2.3.4:3306' (110)'
Check that mysqld is running on 1.2.3.4 and that the port is 3306.
You can check this by doing 'telnet 1.2.3.4 3306'
# 查看上一条命令的返回值,1表示失败
[root@localhost ~]# echo $?
1
#静默退出,不输出错误信息
[root@localhost ~]# mysqladmin -h1.2.3.4 --connect-timeout=2 -s ping
# 查看返回值
[root@localhost ~]# echo $?
1
范例:持续执行
bash
#每秒执行一次ping命令,一直执行下去
[root@localhost ~]# mysqladmin -i 1 ping
mysqld is alive
mysqld is alive
mysqld is alive
......
#每秒执行一次ping命令,总共执行3次
[root@localhost ~]# mysqladmin -i 1 -c 3 ping
mysqld is alive
mysqld is alive
mysqld is alive
范例:关闭服务
bash
#mysqladmin只能关闭服务,不能启动服务
[root@localhost ~]# mysqladmin shutdown
# 验证服务已关闭,ping会失败
[root@localhost ~]# mysqladmin ping
mysqladmin: connect to server at 'localhost' failed
error: 'Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)'
Check that mysqld is running and that the socket: '/var/lib/mysql/mysql.sock' exists!
# 查看返回值,1表示连接失败
[root@localhost ~]# echo $?
1
# 使用systemctl重新启动mysqld服务
[root@localhost ~]# systemctl start mysqld
范例:创建数据库和删除数据库
bash
#创建
[root@localhost ~]# mysqladmin create mysqladmin-db1
[root@localhost ~]# mysqladmin create mysqladmin-db2
# 查看当前所有数据库
[root@localhost ~]# mysql -e 'show databases'
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| mysqladmin-db1 |
| mysqladmin-db2 |
| performance_schema |
| sys |
+--------------------+
#删除
[root@localhost ~]# mysqladmin drop mysqladmin-db1
Dropping the database is potentially a very bad thing to do.
Any data stored in the database will be destroyed.
Do you really want to drop the 'mysqladmin-db1' database [y/N] y #回答y确认
Database "mysqladmin-db1" dropped
[root@localhost ~]# mysqladmin -f drop mysqladmin-db2 #强制删除,不需要确认
Database "mysqladmin-db2" dropped
[root@localhost ~]# mysql -e 'show databases' #验证mysqladmin-db1和mysqladmin-db2已经删除
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
[root@localhost ~]#
范例:修改连接密码
bash
#旧密码为空,root用户,localhost主机连接
[root@localhost ~]# mysqladmin password 123456 #设置密码为123456
mysqladmin: [Warning] Using a password on the command line interface can be insecure.
Warning: Since password will be sent to server in plain text, use ssl connection to ensure password safety.
[root@localhost ~]# mysqladmin ping #不使用密码不行
mysqladmin: connect to server at 'localhost' failed
error: 'Access denied for user 'root'@'localhost' (using password: NO)'
[root@localhost ~]# mysqladmin -uroot -hlocalhost -p123456 ping #使用密码
123456
mysqladmin: [Warning] Using a password on the command line interface can be insecure.
mysqld is alive
#用旧密码修改新密码
[root@localhost ~]# mysqladmin -uroot -p123456 -hlocalhost password abcde #更改密码为abcde
mysqladmin: [Warning] Using a password on the command line interface can be insecure.
Warning: Since password will be sent to server in plain text, use ssl connection to ensure password safety.
[root@localhost ~]# mysqladmin -uroot -p123456 -hlocalhost ping #使用原密码测试不行
mysqladmin: [Warning] Using a password on the command line interface can be insecure.
mysqladmin: connect to server at 'localhost' failed
error: 'Access denied for user 'root'@'localhost' (using password: YES)'
[root@localhost ~]# mysqladmin -uroot -pabcde -hlocalhost ping #使用新密码测试
mysqladmin: [Warning] Using a password on the command line interface can be insecure.
mysqld is alive
mycli 工具
MyCLI是基于Python开发的MySQL的命令行工具,具有自动完成和语法突出显示功能
bash
# 安装python39
[root@localhost ~]# yum install -y python39
# 配置pip3.9使用清华镜像源
[root@localhost ~]# pip3.9 config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
Writing to /root/.config/pip/pip.conf
# 使用pip3安装mycli 1.2.0版本
[root@localhost ~]# pip3 install mycli==1.2.0
#使用
[root@localhost ~]# mycli -uroot -pabcde
Connecting to socket /var/lib/mysql/mysql.sock, owned by user mysql
MySQL
mycli 1.38.4
Home: http://mycli.net
Bug tracker: https://github.com/dbcli/mycli/issues
Thanks to the contributor - Artem Bezsmertnyi
MySQL root@(none):(none)>

SQL语言
关系型数据库的构成
| 组件 | 关键字 | 说明 |
|---|---|---|
| 数据库 | database | 表的集合,一个数据库中可以有多个表,在文件系统中表出就是一个目录 |
| 表 | table | 在数据库中以二维表的形式出现,有行和列,数据库中的数据就是存放于表中的 |
| 索引 | index | 索引通常建立在一个列上,用以加快数据查询速度 |
| 视图 | view | 用SQL语言构建的虚拟表,可以临时把两个或多个表以逻辑关系关联上,对外提供查询 |
| 存储过程 | procedure | 存储过程是一组为了完成特定功能的SQL语句集合,客户端可以直接调用 |
| 存储函数 | function | 存储函数和存储过程一样,都是SQL语句集合,但可以使用参数 |
| 触发器 | tigger | 触发器也是有SQL语句的集合组成,但需要达到触发条件才能调用 |
| 事件调度器 | event scheduler | 数据库中的计划任务 |
| 用户 | user | 连接服务端时的用户名 |
| 权限 | privilege | 每个用户可以对哪些数据库或表进行操作,在什么IP能连接 |
SQL语言介绍
SQL:(Structured Query Language)结构化查询语言。
SQL语言是对IBM公司San Jose,California研究实验室的埃德加·科德的关系模型的第一个商业化语言实现。尽管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年改名为SQL。
1979年ORACLE公司首先提供商用的SQL,IBM公司在DB2和SQL/DS数据库系统中也实现了SQL。
1986年10月美国国家标准学会ANSI采用SQL作为关系数据库管理系统的标准语言(ANSIX3.135-1986)。
1987年成为国际标准化组织((ISO)采纳为国际标准。
1989年美国ANSI采纳在ANSIX3.135-1989报告中定义的关系数据库管理系统的SQL标准语言,称为ANSI SQL 89。
后续SQL标准经过了一系列的增订,加入了大量新特性,有各种版本:ANSISQL,SQL-1986,SQL-1989,SQL-1992,SQL-1999,SQL-2003,SQL-2008,SQL-2011。
目前,所有主要的关系数据库管理系统支持某些形式的SQL,大部分数据库至少遵守ANSISQL89标准。
虽然有这一标准的存在,但大部分的SQL代码在不同的数据库系统中并不具有完全的跨平台性。
业内标准微软和 Sybase 的T-SQL,Oracle 的 PL/SQL。
SQL语言规范
在数据库系统中,SQL语句不区分大小写,建议用大写。
SQL语句可单行或多行书写,默认以;结尾。
- 关键词不能跨多行或简写。
- 用空格和TAB缩进来提高语句的可读性。
- 子句通常位于独立行,便于编辑,提高可读性。
bash
#不区分大小写
# 查询主机名:关键字 select、变量 @@hostname 大小写混写仍可执行,说明SQL关键字不区分大小写
mysql> select @@hostname;
+-----------------------+
| @@hostname |
+-----------------------+
| localhost.localdomain |
+-----------------------+
1 row in set (0.00 sec)
# 同样的语句故意写成 SELect、@@HOSTname,结果完全一致
mysql> SELect @@HOSTname;
+-----------------------+
| @@HOSTname |
+-----------------------+
| localhost.localdomain |
+-----------------------+
1 row in set (0.00 sec)
#区分大小写
# 字段名 user、host 不区分大小写,下面小写查询成功
mysql> SELect user,host from mysql.user;
+------------------+-----------+
| user | host |
+------------------+-----------+
| mysql.infoschema | localhost |
| mysql.session | localhost |
| mysql.sys | localhost |
| root | localhost |
+------------------+-----------+
4 rows in set (0.01 sec)
# 表名 mysql.USER 写成大写报错:库名表名在Linux下区分大小写
mysql> SELect user,host from mysql.USER;
ERROR 1146 (42S02): Table 'mysql.USER' doesn't exist
# 列名 HOST 大写仍可查询:字段名不区分大小写
mysql> SELect user,HOST from mysql.USER;
ERROR 1146 (42S02): Table 'mysql.USER' doesn't exist
#字段不区分大小写,库名表名区分大小写
# 表名用小写 mysql.user 即可成功,列名 HOST 大写不影响
mysql> SELect user,HOST from mysql.user;
+------------------+-----------+
| user | HOST |
+------------------+-----------+
| mysql.infoschema | localhost |
| mysql.session | localhost |
| mysql.sys | localhost |
| root | localhost |
+------------------+-----------+
范例:跨行
bash
# 正常一行写完整条查询语句
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.01 sec)
# 关键字之间可以换行,mysql 用 -> 续行提示符,仍能成功
mysql> show
-> databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.00 sec)
#关键字不能跨行
# 把关键字 show databases 拆成 show data 与 bases 两行,关键字被截断,语法报错
mysql> show data
-> bases;
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 'data bases' at line 1
SQL语言中的注释
SQL语言中的标准注释
bash
-- select version()\G #单行注释:两个减号开头,注释掉本行
/* #多行注释:/* 开始,*/ 结束,中间内容不执行
select version()\G
select version()\G
*/
select version()\G # 仅这条未被注释,真正执行
范例:
bash
# 用 vim 编写 SQL 脚本文件 test.sql
[root@localhost ~]# vim test.sql
-- select version()\G
/*
select version()\G
select version()\G
*/
select version()\G
# 用 mysql 客户端重定向执行 test.sql,只有最后一条语句真正输出结果
[root@localhost ~]# mysql < test.sql
*************************** 1. row ***************************
version(): 8.0.26
MySQL中的注释
bash
# select version()\G; #MySQL中的注释:井号开头,注释掉本行
select version()\G; # 未注释的语句执行,输出版本号
范例:
bash
# 查看 test.sql 文件内容
[root@localhost ~]# cat test.sql
# select version()\G;
# select version()\G;
select version()\G;
# 执行脚本,仅最后一条井号未注释的语句输出结果
[root@localhost ~]# mysql < test.sql
*************************** 1. row ***************************
version(): 8.0.26
数据库对象和命名
数据库中的组件(对象)
数据库、表、索引、视图、用户、存储过程、函数、触发器、事件调度器等
组件命名规则
- 可以包括字母,数字和三个特殊字符(#_$)
- 不能使用MySQL的保留字
SQL 语句分类
| SQL语句类型 | 说明 | 具体语句 |
|---|---|---|
| DDL | Data Defination Language数据定义语言 | CREATE,DROP,ALTER |
| DML | Data Mainpulation Language数据操纵语言 | INSERT,DELETE,UPDATE |
| DQL | Data Query Language数据查询语言 | SELECT |
| DCL | Data Control Language数据控制语言 | GRANT,REVOKE |
| TCL | Transaction Control Language事务控制语言 | BEGIN,COMMIT,ROLLBACK,SAVEPOINT |
- DDL:定义结构(建库、建表、删表)
- DML:操作表中数据(增、删、改)
- DQL:查询表中数据(SELECT)
- DCL:权限控制(授权、收权)
- TCL:事务控制(提交、回滚)
SQL 语句构成
关键字keyword组成子句clause,多条clause组成语句
bash
# 查询 mysql.user 表中密码为空的 root 用户:SELECT 指定列,FROM 指定表,WHERE 过滤条件
mysql> SELECT host,user,authentication_string FROM mysql.user WHERE authentication_string = '';
+-----------+------+-----------------------+
| host | user | authentication_string |
+-----------+------+-----------------------+
| localhost | root | |
+-----------+------+-----------------------+
1 row in set (0.00 sec)
说明:
bash
SELECT host,user,authentication_string #select子句:指定要查询的列
FROM mysql.user #from子句:指定数据来自哪张表
WHERE authentication_string = ''; #where子句:只筛选 authentication_string 为空的行
命令行下查看帮助
bash
# 查看帮助目录总览,列出所有帮助类别
mysql> help contents;
You asked for help about help category: "Contents"
For more information, type 'help <item>', where <item> is one of the following categories:
Account Management
Administration
Components
Compound Statements
Contents
Data Definition
Data Manipulation
Data Types
Functions
Geographic Features
Help Metadata
Language Structure
Loadable Functions
Plugins
Prepared Statements
Replication Statements
Storage Engines
Table Maintenance
Transactions
Utility
#查看DDL帮助:列出所有数据定义类语句
mysql> help Data Definition #查看DDL帮助
You asked for help about help category: "Data Definition"
For more information, type 'help <item>', where <item> is one of the following topics:
ALTER DATABASE
ALTER EVENT
ALTER FUNCTION
ALTER INSTANCE
ALTER LOGFILE GROUP
ALTER PROCEDURE
ALTER SCHEMA
ALTER SERVER
ALTER TABLE
ALTER TABLESPACE
ALTER VIEW
CREATE DATABASE
CREATE EVENT
CREATE FUNCTION
CREATE INDEX
CREATE LOGFILE GROUP
CREATE PROCEDURE
CREATE SCHEMA
CREATE SERVER
CREATE SPATIAL REFERENCE SYSTEM
CREATE TABLE
CREATE TABLESPACE
CREATE TRIGGER
CREATE VIEW
DROP DATABASE
DROP EVENT
DROP FUNCTION
DROP INDEX
DROP PROCEDURE
DROP SCHEMA
DROP SERVER
DROP SPATIAL REFERENCE SYSTEM
DROP TABLE
DROP TABLESPACE
DROP TRIGGER
DROP VIEW
FOREIGN KEY
RENAME TABLE
TRUNCATE TABLE
# 查看 CREATE DATABASE 语句的具体语法
mysql> help CREATE DATABASE;
Name: 'CREATE DATABASE'
Description:
Syntax:
CREATE {DATABASE | SCHEMA} [IF NOT EXISTS] db_name
[create_option] ...
create_option: [DEFAULT] {
CHARACTER SET [=] charset_name
| COLLATE [=] collation_name
| ENCRYPTION [=] {'Y' | 'N'}
}
CREATE DATABASE creates a database with the given name. To use this statement, you need the CREATE privilege for the database. CREATE SCHEMA is a synonym for CREATE DATABASE.
URL: https://dev.mysql.com/doc/refman/8.0/en/create-database.html
字符集和排序
早期MySQL版本默认为latin1,从MySQL8.0开始默认字符集已经为utf8mb4
查看当前版本可用的字符集
bash
mysql> show CHARACTER SET; #查看所有支持的字符集
+----------+---------------------------------+---------------------+--------+
| Charset | Description | Default collation | Maxlen |
+----------+---------------------------------+---------------------+--------+
| armscii8 | ARMSCII-8 Armenian | armscii8_general_ci | 1 |
| ascii | US ASCII | ascii_general_ci | 1 |
| big5 | Big5 Traditional Chinese | big5_chinese_ci | 2 |
| binary | Binary pseudo charset | binary | 1 |
| cp1250 | Windows Central European | cp1250_general_ci | 1 |
| cp1251 | Windows Cyrillic | cp1251_general_ci | 1 |
| cp1256 | Windows Arabic | cp1256_general_ci | 1 |
| cp1257 | Windows Baltic | cp1257_general_ci | 1 |
| cp850 | DOS West European | cp850_general_ci | 1 |
| cp852 | DOS Central European | cp852_general_ci | 1 |
| cp866 | DOS Russian | cp866_general_ci | 1 |
| cp932 | SJIS for Windows Japanese | cp932_japanese_ci | 2 |
| dec8 | DEC West European | dec8_swedish_ci | 1 |
| eucjpms | UJIS for Windows Japanese | eucjpms_japanese_ci | 3 |
| euckr | EUC-KR Korean | euckr_korean_ci | 2 |
| gb18030 | China National Standard GB18030 | gb18030_chinese_ci | 4 |
| gb2312 | GB2312 Simplified Chinese | gb2312_chinese_ci | 2 |
| gbk | GBK Simplified Chinese | gbk_chinese_ci | 2 |
| geostd8 | GEOSTD8 Georgian | geostd8_general_ci | 1 |
| greek | ISO 8859-7 Greek | greek_general_ci | 1 |
| hebrew | ISO 8859-8 Hebrew | hebrew_general_ci | 1 |
| hp8 | HP West European | hp8_english_ci | 1 |
| keybcs2 | DOS Kamenicky Czech-Slovak | keybcs2_general_ci | 1 |
| koi8r | KOI8-R Relcom Russian | koi8r_general_ci | 1 |
| koi8u | KOI8-U Ukrainian | koi8u_general_ci | 1 |
| latin1 | cp1252 West European | latin1_swedish_ci | 1 |
| latin2 | ISO 8859-2 Central European | latin2_general_ci | 1 |
| latin5 | ISO 8859-9 Turkish | latin5_turkish_ci | 1 |
| latin7 | ISO 8859-13 Baltic | latin7_general_ci | 1 |
| macce | Mac Central European | macce_general_ci | 1 |
| macroman | Mac West European | macroman_general_ci | 1 |
| sjis | Shift-JIS Japanese | sjis_japanese_ci | 2 |
| swe7 | 7bit Swedish | swe7_swedish_ci | 1 |
| tis620 | TIS620 Thai | tis620_thai_ci | 1 |
| ucs2 | UCS-2 Unicode | ucs2_general_ci | 2 |
| ujis | EUC-JP Japanese | ujis_japanese_ci | 3 |
| utf16 | UTF-16 Unicode | utf16_general_ci | 4 |
| utf16le | UTF-16LE Unicode | utf16le_general_ci | 4 |
| utf32 | UTF-32 Unicode | utf32_general_ci | 4 |
| utf8 | UTF-8 Unicode | utf8_general_ci | 3 |
| utf8mb4 | UTF-8 Unicode | utf8mb4_0900_ai_ci | 4 |
+----------+---------------------------------+---------------------+--------+
41 rows in set (0.00 sec)
# show CHARSET 是 show CHARACTER SET 的简写,作用相同,下面无输出(结果同上)
mysql> show CHARSET; #查看所有支持的字符集
查看当前默认字符集
bash
# 查看与字符集相关的所有系统变量
mysql> show variables like 'character%';
+--------------------------+----------------------------+
| Variable_name | Value |
+--------------------------+----------------------------+
| character_set_client | utf8mb4 |
| character_set_connection | utf8mb4 |
| character_set_database | utf8mb4 |
| character_set_filesystem | binary |
| character_set_results | utf8mb4 |
| character_set_server | utf8mb4 |
| character_set_system | utf8mb3 |
| character_sets_dir | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.01 sec)
修改mysql-server的默认字符集
bash
# 编辑服务端配置文件,修改服务端默认字符集为 latin1
[root@localhost ~]# vim /etc/my.cnf.d/mysql-server.cnf
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
log-error=/var/log/mysql/mysqld.log
pid-file=/run/mysqld/mysqld.pid
character-set-server=latin1 #新加一行:设置服务端默认字符集
# 编辑客户端配置文件,修改客户端默认字符集为 latin1
[root@localhost ~]# vim /etc/my.cnf.d/client.cnf
[client]
default-character-set=latin1 #新加一ha:设置客户端默认字符集
#重启服务使配置生效
[root@localhost ~]# systemctl restart mysqld #重启服务
# 再次查看字符集变量,可见已变为 latin1
mysql> show variables like 'character%';
+--------------------------+----------------------------+
| Variable_name | Value |
+--------------------------+----------------------------+
| character_set_client | latin1 |
| character_set_connection | latin1 |
| character_set_database | latin1 |
| character_set_filesystem | binary |
| character_set_results | latin1 |
| character_set_server | latin1 |
| character_set_system | utf8mb3 |
| character_sets_dir | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.00 sec)
#再改回来,或者还原快照
查看当前版本可用的排序规则
bash
# 查看所有排序规则(collation),输出很长
mysql> SHOW COLLATION;
+----------------------------+----------+-----+---------+----------+---------+---------------+
| Collation | Charset | Id | Default | Compiled | Sortlen | Pad_attribute |
+----------------------------+----------+-----+---------+----------+---------+---------------+
| armscii8_bin | armscii8 | 64 | | Yes | 1 | PAD SPACE |
| armscii8_general_ci | armscii8 | 32 | Yes | Yes | 1 | PAD SPACE |
| ascii_bin | ascii | 65 | | Yes | 1 | PAD SPACE |
| ascii_general_ci | ascii | 11 | Yes | Yes | 1 | PAD SPACE |
| big5_bin | big5 | 84 | | Yes | 1 | PAD SPACE |
| big5_chinese_ci | big5 | 1 | Yes | Yes | 1 | PAD SPACE |
| binary | binary | 63 | Yes | Yes | 1 | NO PAD |
| cp1250_bin | cp1250 | 66 | | Yes | 1 | PAD SPACE |
| cp1250_croatian_ci | cp1250 | 44 | | Yes | 1 | PAD SPACE |
| cp1250_czech_cs | cp1250 | 34 | | Yes | 2 | PAD SPACE |
| cp1250_general_ci | cp1250 | 26 | Yes | Yes | 1 | PAD SPACE |
| cp1250_polish_ci | cp1250 | 99 | | Yes | 1 | PAD SPACE |
| cp1251_bin | cp1251 | 50 | | Yes | 1 | PAD SPACE |
| cp1251_bulgarian_ci | cp1251 | 14 | | Yes | 1 | PAD SPACE |
| cp1251_general_ci | cp1251 | 51 | Yes | Yes | 1 | PAD SPACE |
| cp1251_general_cs | cp1251 | 52 | | Yes | 1 | PAD SPACE |
| cp1251_ukrainian_ci | cp1251 | 23 | | Yes | 1 | PAD SPACE |
| cp1256_bin | cp1256 | 67 | | Yes | 1 | PAD SPACE |
| cp1256_general_ci | cp1256 | 57 | Yes | Yes | 1 | PAD SPACE |
| cp1257_bin | cp1257 | 58 | | Yes | 1 | PAD SPACE |
| cp1257_general_ci | cp1257 | 59 | Yes | Yes | 1 | PAD SPACE |
| cp1257_lithuanian_ci | cp1257 | 29 | | Yes | 1 | PAD SPACE |
| cp850_bin | cp850 | 80 | | Yes | 1 | PAD SPACE |
| cp850_general_ci | cp850 | 4 | Yes | Yes | 1 | PAD SPACE |
| cp852_bin | cp852 | 81 | | Yes | 1 | PAD SPACE |
| cp852_general_ci | cp852 | 40 | Yes | Yes | 1 | PAD SPACE |
| cp866_bin | cp866 | 68 | | Yes | 1 | PAD SPACE |
| cp866_general_ci | cp866 | 36 | Yes | Yes | 1 | PAD SPACE |
| cp932_bin | cp932 | 96 | | Yes | 1 | PAD SPACE |
| cp932_japanese_ci | cp932 | 95 | Yes | Yes | 1 | PAD SPACE |
| dec8_bin | dec8 | 69 | | Yes | 1 | PAD SPACE |
| dec8_swedish_ci | dec8 | 3 | Yes | Yes | 1 | PAD SPACE |
| eucjpms_bin | eucjpms | 98 | | Yes | 1 | PAD SPACE |
| eucjpms_japanese_ci | eucjpms | 97 | Yes | Yes | 1 | PAD SPACE |
| euckr_bin | euckr | 85 | | Yes | 1 | PAD SPACE |
| euckr_korean_ci | euckr | 19 | Yes | Yes | 1 | PAD SPACE |
| gb18030_bin | gb18030 | 249 | | Yes | 1 | PAD SPACE |
| gb18030_chinese_ci | gb18030 | 248 | Yes | Yes | 2 | PAD SPACE |
| gb18030_unicode_520_ci | gb18030 | 250 | | Yes | 8 | PAD SPACE |
| gb2312_bin | gb2312 | 86 | | Yes | 1 | PAD SPACE |
| gb2312_chinese_ci | gb2312 | 24 | Yes | Yes | 1 | PAD SPACE |
| gbk_bin | gbk | 87 | | Yes | 1 | PAD SPACE |
| gbk_chinese_ci | gbk | 28 | Yes | Yes | 1 | PAD SPACE |
| geostd8_bin | geostd8 | 93 | | Yes | 1 | PAD SPACE |
| geostd8_general_ci | geostd8 | 92 | Yes | Yes | 1 | PAD SPACE |
| greek_bin | greek | 70 | | Yes | 1 | PAD SPACE |
| greek_general_ci | greek | 25 | Yes | Yes | 1 | PAD SPACE |
| hebrew_bin | hebrew | 71 | | Yes | 1 | PAD SPACE |
| hebrew_general_ci | hebrew | 16 | Yes | Yes | 1 | PAD SPACE |
| hp8_bin | hp8 | 72 | | Yes | 1 | PAD SPACE |
| hp8_english_ci | hp8 | 6 | Yes | Yes | 1 | PAD SPACE |
| keybcs2_bin | keybcs2 | 73 | | Yes | 1 | PAD SPACE |
| keybcs2_general_ci | keybcs2 | 37 | Yes | Yes | 1 | PAD SPACE |
| koi8r_bin | koi8r | 74 | | Yes | 1 | PAD SPACE |
| koi8r_general_ci | koi8r | 7 | Yes | Yes | 1 | PAD SPACE |
| koi8u_bin | koi8u | 75 | | Yes | 1 | PAD SPACE |
| koi8u_general_ci | koi8u | 22 | Yes | Yes | 1 | PAD SPACE |
| latin1_bin | latin1 | 47 | | Yes | 1 | PAD SPACE |
| latin1_danish_ci | latin1 | 15 | | Yes | 1 | PAD SPACE |
| latin1_general_ci | latin1 | 48 | | Yes | 1 | PAD SPACE |
| latin1_general_cs | latin1 | 49 | | Yes | 1 | PAD SPACE |
| latin1_german1_ci | latin1 | 5 | | Yes | 1 | PAD SPACE |
| latin1_german2_ci | latin1 | 31 | | Yes | 2 | PAD SPACE |
| latin1_spanish_ci | latin1 | 94 | | Yes | 1 | PAD SPACE |
| latin1_swedish_ci | latin1 | 8 | Yes | Yes | 1 | PAD SPACE |
| latin2_bin | latin2 | 77 | | Yes | 1 | PAD SPACE |
| latin2_croatian_ci | latin2 | 27 | | Yes | 1 | PAD SPACE |
| latin2_czech_cs | latin2 | 2 | | Yes | 4 | PAD SPACE |
| latin2_general_ci | latin2 | 9 | Yes | Yes | 1 | PAD SPACE |
| latin2_hungarian_ci | latin2 | 21 | | Yes | 1 | PAD SPACE |
| latin5_bin | latin5 | 78 | | Yes | 1 | PAD SPACE |
| latin5_turkish_ci | latin5 | 30 | Yes | Yes | 1 | PAD SPACE |
| latin7_bin | latin7 | 79 | | Yes | 1 | PAD SPACE |
| latin7_estonian_cs | latin7 | 20 | | Yes | 1 | PAD SPACE |
| latin7_general_ci | latin7 | 41 | Yes | Yes | 1 | PAD SPACE |
| latin7_general_cs | latin7 | 42 | | Yes | 1 | PAD SPACE |
| macce_bin | macce | 43 | | Yes | 1 | PAD SPACE |
| macce_general_ci | macce | 38 | Yes | Yes | 1 | PAD SPACE |
| macroman_bin | macroman | 53 | | Yes | 1 | PAD SPACE |
| macroman_general_ci | macroman | 39 | Yes | Yes | 1 | PAD SPACE |
| sjis_bin | sjis | 88 | | Yes | 1 | PAD SPACE |
| sjis_japanese_ci | sjis | 13 | Yes | Yes | 1 | PAD SPACE |
| swe7_bin | swe7 | 82 | | Yes | 1 | PAD SPACE |
| swe7_swedish_ci | swe7 | 10 | Yes | Yes | 1 | PAD SPACE |
| tis620_bin | tis620 | 89 | | Yes | 1 | PAD SPACE |
| tis620_thai_ci | tis620 | 18 | Yes | Yes | 4 | PAD SPACE |
| ucs2_bin | ucs2 | 90 | | Yes | 1 | PAD SPACE |
| ucs2_croatian_ci | ucs2 | 149 | | Yes | 8 | PAD SPACE |
| ucs2_czech_ci | ucs2 | 138 | | Yes | 8 | PAD SPACE |
| ucs2_danish_ci | ucs2 | 139 | | Yes | 8 | PAD SPACE |
| ucs2_esperanto_ci | ucs2 | 145 | | Yes | 8 | PAD SPACE |
| ucs2_estonian_ci | ucs2 | 134 | | Yes | 8 | PAD SPACE |
| ucs2_general_ci | ucs2 | 35 | Yes | Yes | 1 | PAD SPACE |
| ucs2_general_mysql500_ci | ucs2 | 159 | | Yes | 1 | PAD SPACE |
| ucs2_german2_ci | ucs2 | 148 | | Yes | 8 | PAD SPACE |
| ucs2_hungarian_ci | ucs2 | 146 | | Yes | 8 | PAD SPACE |
| ucs2_icelandic_ci | ucs2 | 129 | | Yes | 8 | PAD SPACE |
| ucs2_latvian_ci | ucs2 | 130 | | Yes | 8 | PAD SPACE |
| ucs2_lithuanian_ci | ucs2 | 140 | | Yes | 8 | PAD SPACE |
| ucs2_persian_ci | ucs2 | 144 | | Yes | 8 | PAD SPACE |
| ucs2_polish_ci | ucs2 | 133 | | Yes | 8 | PAD SPACE |
| ucs2_romanian_ci | ucs2 | 131 | | Yes | 8 | PAD SPACE |
| ucs2_roman_ci | ucs2 | 143 | | Yes | 8 | PAD SPACE |
| ucs2_sinhala_ci | ucs2 | 147 | | Yes | 8 | PAD SPACE |
| ucs2_slovak_ci | ucs2 | 141 | | Yes | 8 | PAD SPACE |
| ucs2_slovenian_ci | ucs2 | 132 | | Yes | 8 | PAD SPACE |
| ucs2_spanish2_ci | ucs2 | 142 | | Yes | 8 | PAD SPACE |
| ucs2_spanish_ci | ucs2 | 135 | | Yes | 8 | PAD SPACE |
| ucs2_swedish_ci | ucs2 | 136 | | Yes | 8 | PAD SPACE |
| ucs2_turkish_ci | ucs2 | 137 | | Yes | 8 | PAD SPACE |
| ucs2_unicode_520_ci | ucs2 | 150 | | Yes | 8 | PAD SPACE |
| ucs2_unicode_ci | ucs2 | 128 | | Yes | 8 | PAD SPACE |
| ucs2_vietnamese_ci | ucs2 | 151 | | Yes | 8 | PAD SPACE |
| ujis_bin | ujis | 91 | | Yes | 1 | PAD SPACE |
| ujis_japanese_ci | ujis | 12 | Yes | Yes | 1 | PAD SPACE |
| utf16le_bin | utf16le | 62 | | Yes | 1 | PAD SPACE |
| utf16le_general_ci | utf16le | 56 | Yes | Yes | 1 | PAD SPACE |
| utf16_bin | utf16 | 55 | | Yes | 1 | PAD SPACE |
| utf16_croatian_ci | utf16 | 122 | | Yes | 8 | PAD SPACE |
| utf16_czech_ci | utf16 | 111 | | Yes | 8 | PAD SPACE |
| utf16_danish_ci | utf16 | 112 | | Yes | 8 | PAD SPACE |
| utf16_esperanto_ci | utf16 | 118 | | Yes | 8 | PAD SPACE |
| utf16_estonian_ci | utf16 | 107 | | Yes | 8 | PAD SPACE |
| utf16_general_ci | utf16 | 54 | Yes | Yes | 1 | PAD SPACE |
| utf16_german2_ci | utf16 | 121 | | Yes | 8 | PAD SPACE |
| utf16_hungarian_ci | utf16 | 119 | | Yes | 8 | PAD SPACE |
| utf16_icelandic_ci | utf16 | 102 | | Yes | 8 | PAD SPACE |
| utf16_latvian_ci | utf16 | 103 | | Yes | 8 | PAD SPACE |
| utf16_lithuanian_ci | utf16 | 113 | | Yes | 8 | PAD SPACE |
| utf16_persian_ci | utf16 | 117 | | Yes | 8 | PAD SPACE |
| utf16_polish_ci | utf16 | 106 | | Yes | 8 | PAD SPACE |
| utf16_romanian_ci | utf16 | 104 | | Yes | 8 | PAD SPACE |
| utf16_roman_ci | utf16 | 116 | | Yes | 8 | PAD SPACE |
| utf16_sinhala_ci | utf16 | 120 | | Yes | 8 | PAD SPACE |
| utf16_slovak_ci | utf16 | 114 | | Yes | 8 | PAD SPACE |
| utf16_slovenian_ci | utf16 | 105 | | Yes | 8 | PAD SPACE |
| utf16_spanish2_ci | utf16 | 115 | | Yes | 8 | PAD SPACE |
| utf16_spanish_ci | utf16 | 108 | | Yes | 8 | PAD SPACE |
| utf16_swedish_ci | utf16 | 109 | | Yes | 8 | PAD SPACE |
| utf16_turkish_ci | utf16 | 110 | | Yes | 8 | PAD SPACE |
| utf16_unicode_520_ci | utf16 | 123 | | Yes | 8 | PAD SPACE |
| utf16_unicode_ci | utf16 | 101 | | Yes | 8 | PAD SPACE |
| utf16_vietnamese_ci | utf16 | 124 | | Yes | 8 | PAD SPACE |
| utf32_bin | utf32 | 61 | | Yes | 1 | PAD SPACE |
| utf32_croatian_ci | utf32 | 181 | | Yes | 8 | PAD SPACE |
| utf32_czech_ci | utf32 | 170 | | Yes | 8 | PAD SPACE |
| utf32_danish_ci | utf32 | 171 | | Yes | 8 | PAD SPACE |
| utf32_esperanto_ci | utf32 | 177 | | Yes | 8 | PAD SPACE |
| utf32_estonian_ci | utf32 | 166 | | Yes | 8 | PAD SPACE |
| utf32_general_ci | utf32 | 60 | Yes | Yes | 1 | PAD SPACE |
| utf32_german2_ci | utf32 | 180 | | Yes | 8 | PAD SPACE |
| utf32_hungarian_ci | utf32 | 178 | | Yes | 8 | PAD SPACE |
| utf32_icelandic_ci | utf32 | 161 | | Yes | 8 | PAD SPACE |
| utf32_latvian_ci | utf32 | 162 | | Yes | 8 | PAD SPACE |
| utf32_lithuanian_ci | utf32 | 172 | | Yes | 8 | PAD SPACE |
| utf32_persian_ci | utf32 | 176 | | Yes | 8 | PAD SPACE |
| utf32_polish_ci | utf32 | 165 | | Yes | 8 | PAD SPACE |
| utf32_romanian_ci | utf32 | 163 | | Yes | 8 | PAD SPACE |
| utf32_roman_ci | utf32 | 175 | | Yes | 8 | PAD SPACE |
| utf32_sinhala_ci | utf32 | 179 | | Yes | 8 | PAD SPACE |
| utf32_slovak_ci | utf32 | 173 | | Yes | 8 | PAD SPACE |
| utf32_slovenian_ci | utf32 | 164 | | Yes | 8 | PAD SPACE |
| utf32_spanish2_ci | utf32 | 174 | | Yes | 8 | PAD SPACE |
| utf32_spanish_ci | utf32 | 167 | | Yes | 8 | PAD SPACE |
| utf32_swedish_ci | utf32 | 168 | | Yes | 8 | PAD SPACE |
| utf32_turkish_ci | utf32 | 169 | | Yes | 8 | PAD SPACE |
| utf32_unicode_520_ci | utf32 | 182 | | Yes | 8 | PAD SPACE |
| utf32_unicode_ci | utf32 | 160 | | Yes | 8 | PAD SPACE |
| utf32_vietnamese_ci | utf32 | 183 | | Yes | 8 | PAD SPACE |
| utf8mb4_0900_ai_ci | utf8mb4 | 255 | Yes | Yes | 0 | NO PAD |
| utf8mb4_0900_as_ci | utf8mb4 | 305 | | Yes | 0 | NO PAD |
| utf8mb4_0900_as_cs | utf8mb4 | 278 | | Yes | 0 | NO PAD |
| utf8mb4_0900_bin | utf8mb4 | 309 | | Yes | 1 | NO PAD |
| utf8mb4_bin | utf8mb4 | 46 | | Yes | 1 | PAD SPACE |
| utf8mb4_croatian_ci | utf8mb4 | 245 | | Yes | 8 | PAD SPACE |
| utf8mb4_cs_0900_ai_ci | utf8mb4 | 266 | | Yes | 0 | NO PAD |
| utf8mb4_cs_0900_as_cs | utf8mb4 | 289 | | Yes | 0 | NO PAD |
| utf8mb4_czech_ci | utf8mb4 | 234 | | Yes | 8 | PAD SPACE |
| utf8mb4_danish_ci | utf8mb4 | 235 | | Yes | 8 | PAD SPACE |
| utf8mb4_da_0900_ai_ci | utf8mb4 | 267 | | Yes | 0 | NO PAD |
| utf8mb4_da_0900_as_cs | utf8mb4 | 290 | | Yes | 0 | NO PAD |
| utf8mb4_de_pb_0900_ai_ci | utf8mb4 | 256 | | Yes | 0 | NO PAD |
| utf8mb4_de_pb_0900_as_cs | utf8mb4 | 279 | | Yes | 0 | NO PAD |
| utf8mb4_eo_0900_ai_ci | utf8mb4 | 273 | | Yes | 0 | NO PAD |
| utf8mb4_eo_0900_as_cs | utf8mb4 | 296 | | Yes | 0 | NO PAD |
| utf8mb4_esperanto_ci | utf8mb4 | 241 | | Yes | 8 | PAD SPACE |
| utf8mb4_estonian_ci | utf8mb4 | 230 | | Yes | 8 | PAD SPACE |
| utf8mb4_es_0900_ai_ci | utf8mb4 | 263 | | Yes | 0 | NO PAD |
| utf8mb4_es_0900_as_cs | utf8mb4 | 286 | | Yes | 0 | NO PAD |
| utf8mb4_es_trad_0900_ai_ci | utf8mb4 | 270 | | Yes | 0 | NO PAD |
| utf8mb4_es_trad_0900_as_cs | utf8mb4 | 293 | | Yes | 0 | NO PAD |
| utf8mb4_et_0900_ai_ci | utf8mb4 | 262 | | Yes | 0 | NO PAD |
| utf8mb4_et_0900_as_cs | utf8mb4 | 285 | | Yes | 0 | NO PAD |
| utf8mb4_general_ci | utf8mb4 | 45 | | Yes | 1 | PAD SPACE |
| utf8mb4_german2_ci | utf8mb4 | 244 | | Yes | 8 | PAD SPACE |
| utf8mb4_hr_0900_ai_ci | utf8mb4 | 275 | | Yes | 0 | NO PAD |
| utf8mb4_hr_0900_as_cs | utf8mb4 | 298 | | Yes | 0 | NO PAD |
| utf8mb4_hungarian_ci | utf8mb4 | 242 | | Yes | 8 | PAD SPACE |
| utf8mb4_hu_0900_ai_ci | utf8mb4 | 274 | | Yes | 0 | NO PAD |
| utf8mb4_hu_0900_as_cs | utf8mb4 | 297 | | Yes | 0 | NO PAD |
| utf8mb4_icelandic_ci | utf8mb4 | 225 | | Yes | 8 | PAD SPACE |
| utf8mb4_is_0900_ai_ci | utf8mb4 | 257 | | Yes | 0 | NO PAD |
| utf8mb4_is_0900_as_cs | utf8mb4 | 280 | | Yes | 0 | NO PAD |
| utf8mb4_ja_0900_as_cs | utf8mb4 | 303 | | Yes | 0 | NO PAD |
| utf8mb4_ja_0900_as_cs_ks | utf8mb4 | 304 | | Yes | 24 | NO PAD |
| utf8mb4_latvian_ci | utf8mb4 | 226 | | Yes | 8 | PAD SPACE |
| utf8mb4_la_0900_ai_ci | utf8mb4 | 271 | | Yes | 0 | NO PAD |
| utf8mb4_la_0900_as_cs | utf8mb4 | 294 | | Yes | 0 | NO PAD |
| utf8mb4_lithuanian_ci | utf8mb4 | 236 | | Yes | 8 | PAD SPACE |
| utf8mb4_lt_0900_ai_ci | utf8mb4 | 268 | | Yes | 0 | NO PAD |
| utf8mb4_lt_0900_as_cs | utf8mb4 | 291 | | Yes | 0 | NO PAD |
| utf8mb4_lv_0900_ai_ci | utf8mb4 | 258 | | Yes | 0 | NO PAD |
| utf8mb4_lv_0900_as_cs | utf8mb4 | 281 | | Yes | 0 | NO PAD |
| utf8mb4_persian_ci | utf8mb4 | 240 | | Yes | 8 | PAD SPACE |
| utf8mb4_pl_0900_ai_ci | utf8mb4 | 261 | | Yes | 0 | NO PAD |
| utf8mb4_pl_0900_as_cs | utf8mb4 | 284 | | Yes | 0 | NO PAD |
| utf8mb4_polish_ci | utf8mb4 | 229 | | Yes | 8 | PAD SPACE |
| utf8mb4_romanian_ci | utf8mb4 | 227 | | Yes | 8 | PAD SPACE |
| utf8mb4_roman_ci | utf8mb4 | 239 | | Yes | 8 | PAD SPACE |
| utf8mb4_ro_0900_ai_ci | utf8mb4 | 259 | | Yes | 0 | NO PAD |
| utf8mb4_ro_0900_as_cs | utf8mb4 | 282 | | Yes | 0 | NO PAD |
| utf8mb4_ru_0900_ai_ci | utf8mb4 | 306 | | Yes | 0 | NO PAD |
| utf8mb4_ru_0900_as_cs | utf8mb4 | 307 | | Yes | 0 | NO PAD |
| utf8mb4_sinhala_ci | utf8mb4 | 243 | | Yes | 8 | PAD SPACE |
| utf8mb4_sk_0900_ai_ci | utf8mb4 | 269 | | Yes | 0 | NO PAD |
| utf8mb4_sk_0900_as_cs | utf8mb4 | 292 | | Yes | 0 | NO PAD |
| utf8mb4_slovak_ci | utf8mb4 | 237 | | Yes | 8 | PAD SPACE |
| utf8mb4_slovenian_ci | utf8mb4 | 228 | | Yes | 8 | PAD SPACE |
| utf8mb4_sl_0900_ai_ci | utf8mb4 | 260 | | Yes | 0 | NO PAD |
| utf8mb4_sl_0900_as_cs | utf8mb4 | 283 | | Yes | 0 | NO PAD |
| utf8mb4_spanish2_ci | utf8mb4 | 238 | | Yes | 8 | PAD SPACE |
| utf8mb4_spanish_ci | utf8mb4 | 231 | | Yes | 8 | PAD SPACE |
| utf8mb4_sv_0900_ai_ci | utf8mb4 | 264 | | Yes | 0 | NO PAD |
| utf8mb4_sv_0900_as_cs | utf8mb4 | 287 | | Yes | 0 | NO PAD |
| utf8mb4_swedish_ci | utf8mb4 | 232 | | Yes | 8 | PAD SPACE |
| utf8mb4_tr_0900_ai_ci | utf8mb4 | 265 | | Yes | 0 | NO PAD |
| utf8mb4_tr_0900_as_cs | utf8mb4 | 288 | | Yes | 0 | NO PAD |
| utf8mb4_turkish_ci | utf8mb4 | 233 | | Yes | 8 | PAD SPACE |
| utf8mb4_unicode_520_ci | utf8mb4 | 246 | | Yes | 8 | PAD SPACE |
| utf8mb4_unicode_ci | utf8mb4 | 224 | | Yes | 8 | PAD SPACE |
| utf8mb4_vietnamese_ci | utf8mb4 | 247 | | Yes | 8 | PAD SPACE |
| utf8mb4_vi_0900_ai_ci | utf8mb4 | 277 | | Yes | 0 | NO PAD |
| utf8mb4_vi_0900_as_cs | utf8mb4 | 300 | | Yes | 0 | NO PAD |
| utf8mb4_zh_0900_as_cs | utf8mb4 | 308 | | Yes | 0 | NO PAD |
| utf8_bin | utf8 | 83 | | Yes | 1 | PAD SPACE |
| utf8_croatian_ci | utf8 | 213 | | Yes | 8 | PAD SPACE |
| utf8_czech_ci | utf8 | 202 | | Yes | 8 | PAD SPACE |
| utf8_danish_ci | utf8 | 203 | | Yes | 8 | PAD SPACE |
| utf8_esperanto_ci | utf8 | 209 | | Yes | 8 | PAD SPACE |
| utf8_estonian_ci | utf8 | 198 | | Yes | 8 | PAD SPACE |
| utf8_general_ci | utf8 | 33 | Yes | Yes | 1 | PAD SPACE |
| utf8_general_mysql500_ci | utf8 | 223 | | Yes | 1 | PAD SPACE |
| utf8_german2_ci | utf8 | 212 | | Yes | 8 | PAD SPACE |
| utf8_hungarian_ci | utf8 | 210 | | Yes | 8 | PAD SPACE |
| utf8_icelandic_ci | utf8 | 193 | | Yes | 8 | PAD SPACE |
| utf8_latvian_ci | utf8 | 194 | | Yes | 8 | PAD SPACE |
| utf8_lithuanian_ci | utf8 | 204 | | Yes | 8 | PAD SPACE |
| utf8_persian_ci | utf8 | 208 | | Yes | 8 | PAD SPACE |
| utf8_polish_ci | utf8 | 197 | | Yes | 8 | PAD SPACE |
| utf8_romanian_ci | utf8 | 195 | | Yes | 8 | PAD SPACE |
| utf8_roman_ci | utf8 | 207 | | Yes | 8 | PAD SPACE |
| utf8_sinhala_ci | utf8 | 211 | | Yes | 8 | PAD SPACE |
| utf8_slovak_ci | utf8 | 205 | | Yes | 8 | PAD SPACE |
| utf8_slovenian_ci | utf8 | 196 | | Yes | 8 | PAD SPACE |
| utf8_spanish2_ci | utf8 | 206 | | Yes | 8 | PAD SPACE |
| utf8_spanish_ci | utf8 | 199 | | Yes | 8 | PAD SPACE |
| utf8_swedish_ci | utf8 | 200 | | Yes | 8 | PAD SPACE |
| utf8_tolower_ci | utf8 | 76 | | Yes | 1 | PAD SPACE |
| utf8_turkish_ci | utf8 | 201 | | Yes | 8 | PAD SPACE |
| utf8_unicode_520_ci | utf8 | 214 | | Yes | 8 | PAD SPACE |
| utf8_unicode_ci | utf8 | 192 | | Yes | 8 | PAD SPACE |
| utf8_vietnamese_ci | utf8 | 215 | | Yes | 8 | PAD SPACE |
+----------------------------+----------+-----+---------+----------+---------+---------------+
272 rows in set (0.01 sec)
#utf8_general_ci 不区分大小写
#utf8_bin 区分大小写
查看当前使用的排序规则
bash
# 查看与排序规则相关的系统变量
mysql> SHOW VARIABLES LIKE 'collation%';
+----------------------+--------------------+
| Variable_name | Value |
+----------------------+--------------------+
| collation_connection | utf8mb4_0900_ai_ci |
| collation_database | utf8mb4_0900_ai_ci |
| collation_server | utf8mb4_0900_ai_ci |
+----------------------+--------------------+
3 rows in set (0.01 sec)
生产环境中,使用uf8mb4编码,使用默认排序规则
管理数据库
查看数据库列表
格式:
bash
SHOW DATABASES; # 列出当前数据库服务上的所有数据库
范例:
bash
#默认这四个系统库,不能删除
mysql> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.01 sec)
创建数据库
格式:
bash
# 查看创建数据库的语法帮助
mysql> help create database;
Name: 'CREATE DATABASE'
Description:
Syntax:
CREATE {DATABASE | SCHEMA} [IF NOT EXISTS] db_name
[create_option] ...
create_option: [DEFAULT] {
CHARACTER SET [=] charset_name
| COLLATE [=] collation_name
| ENCRYPTION [=] {'Y' | 'N'}
}
CREATE DATABASE creates a database with the given name. To use this statement, you need the CREATE privilege for the database. CREATE SCHEMA is a synonym for CREATE DATABASE.
URL: https://dev.mysql.com/doc/refman/8.0/en/create-database.html
格式:查询数据库创建语句
bash
SHOW CREATE DATABASE DBNAME; # 查看某个数据库的建库语句,含默认字符集
范例:
bash
# 创建数据库 testdb1
mysql> create database testdb1;
Query OK, 1 row affected (0.00 sec)
#如果已存在,再次创建会报错
mysql> create database testdb1;
ERROR 1007 (HY000): Can't create database 'testdb1'; database exists
#不报错,但也没有创建,if not exists表示如果不存在则创建
mysql> create database if not exists testdb1;
Query OK, 1 row affected, 1 warning (0.00 sec)
#查看数据库列表
mysql> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| testdb1 |
+--------------------+
5 rows in set (0.01 sec)
#查看创建语句,包含默认字符集
mysql> SHOW CREATE DATABASE testdb1;
+----------+---------------------------------------------------------------------+
| Database | Create Database |
+----------+---------------------------------------------------------------------+
| testdb1 | CREATE DATABASE `testdb1` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci */ /*!80016 DEFAULT ENCRYPTION='N' */ |
+----------+---------------------------------------------------------------------+
1 row in set (0.00 sec)
#创建时指定字符集
mysql> create database testdb2 DEFAULT CHARACTER SET latin1;
Query OK, 1 row affected (0.01 sec)
#查看创建语句
mysql> show create database testdb2;
+----------+-------------------------------------------------------------------+
| Database | Create Database |
+----------+-------------------------------------------------------------------+
| testdb2 | CREATE DATABASE `testdb2` /*!40100 DEFAULT CHARACTER SET latin1 */ /*!80016 DEFAULT ENCRYPTION='N' */ |
+----------+-------------------------------------------------------------------+
1 row in set (0.00 sec)
创建两个数据库,本质上是在硬盘上创建了两个目录
bash
# 在数据目录下查看新建的数据库目录
[root@localhost ~]# ls -d /var/lib/mysql/testdb*
/var/lib/mysql/testdb1 /var/lib/mysql/testdb2
修改数据库
bash
# 查看修改数据库的语法帮助
mysql> help ALTER DATABASE;
Name: 'ALTER DATABASE'
Description:
Syntax:
ALTER {DATABASE | SCHEMA} [db_name]
alter_option ...
alter_option: {
[DEFAULT] CHARACTER SET [=] charset_name
| [DEFAULT] COLLATE [=] collation_name
| [DEFAULT] ENCRYPTION [=] {'Y' | 'N'}
| READ ONLY [=] {DEFAULT | 0 | 1}
}
范例:修改字符集
bash
# 修改 testdb2 的字符集为 utf8mb4,并指定排序规则
mysql> ALTER DATABASE testdb2 character set utf8mb4 COLLATE utf8mb4_0900_ai_ci;
Query OK, 1 row affected (0.00 sec)
# 用 \G 竖排方式查看建库语句,确认字符集已改
mysql> show create database testdb2\G
*************************** 1. row ***************************
Database: testdb2
Create Database: CREATE DATABASE `testdb2` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci */ /*!80016 DEFAULT ENCRYPTION='N' */
1 row in set (0.00 sec)
删除数据库
格式:
bash
# 查看删除数据库的语法帮助
mysql> help DROP DATABASE
Name: 'DROP DATABASE'
Description:
Syntax:
DROP {DATABASE | SCHEMA} [IF EXISTS] db_name
范例:
bash
# 先看当前有哪些库
mysql> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| testdb1 |
| testdb2 |
+--------------------+
6 rows in set (0.00 sec)
#删除数据库
mysql> DROP DATABASE testdb2;
Query OK, 0 rows affected (0.00 sec)
#删除不存在的库
mysql> DROP DATABASE testdb2;
ERROR 1008 (HY000): Can't drop database 'testdb2'; database doesn't exist
#加if exists判断:库不存在时不报错,只产生警告
mysql> DROP DATABASE IF EXISTS testdb2;
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| testdb1 |
+--------------------+
5 rows in set (0.00 sec)
#testdb2对应的目录已不存在
[root@localhost ~]# ls -d /var/lib/mysql/testdb* -d
/var/lib/mysql/testdb1
mysqladmin命令也可以创建和删除数据库
bash
#创建数据库db1
[root@localhost ~]# mysqladmin create db1
# 登录后查看数据库列表,db1 已创建
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| db1 |
| information_schema |
| mysql |
| performance_schema |
| sys |
| testdb1 |
+--------------------+
6 rows in set (0.00 sec)
#删除数据库db1
[root@localhost ~]# mysqladmin drop testdb1
Dropping the database is potentially a very bad thing to do.
Any data stored in the database will be destroyed.
Do you really want to drop the 'testdb1' database [y/N] y #回答Y
Database "testdb1" dropped
# 删除后再次查看,testdb1 已消失
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| db1 |
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.00 sec)
删库跑路


数据类型
核心定义:数据库数据类型,是对数据库表中字段(列)所存储数据的类型、范围、格式进行的规范定义。简单说,就是规定"某一列只能存什么类型的数据",比如只能存数字、只能存文字,目的是保证数据存储的规范性、节省存储空间、提高查询效率,避免无效数据插入。
核心作用
- 规范数据:限制字段可存储的数据种类(如手机号字段只能存数字,不能存文字),避免数据混乱;
- 节省空间:不同数据类型占用存储空间不同(如整数比字符串占用空间小),合理选择可减少资源浪费;
- 提升效率:数据库可根据数据类型优化查询、排序操作,加快数据处理速度;
- 保证数据完整性:避免插入不符合要求的数据(如给"年龄"字段插入文字),减少数据错误。
MySQL 中定义数据字段的类型对你数据库的优化是非常重要的。
MySQL 支持多种类型,大致可以分为三类:数值、日期/时间和字符串(字符)类型。
对于任何一个数据表,每一行的每一列对应的元素都是下列数据类型的一种。
| 类型 | 关键字 |
|---|---|
| 整数类型 | TINYINT SMALLINT MEDIUMINT INT (INTEGER) BIGINT |
| 浮点类型 | FLOAT DOUBLE |
| 定点数类型 | DECIMAL |
| 位类型 | BIT |
| 日期时间类型 | YEAR TIME DATE DATETIME TIMESTAMP |
| 文本字符串类型 | CHAR VARCHAR TINYTEXT TEXT MEDIUMTEXT LONGTEXT |
| 枚举类型 | ENUM |
| 集合类型 | SET |
| 二进制字符串类型 | BINARY VARBINARY TINYBLOB BLOB MEDIUMBLOB LONGBLOB |
| JSON 类型 | JSON对象 JSON 数组 |
| 空间数据类型 (单值类型) | GEOMETRY POINT LINESTRING POLYGON |
| 空间数据类型 (集合类型) | MULTIPOINT MULTILINESTRING MULTIPOLYGON GEOMETRYCOLLECTION |
在常见数据表时,除了可以指定列的数据类型,还可以指定列的属性。
| 关键字 | 含义 |
|---|---|
| NULL | 数据列可包含 NULL 值 |
| NOT NULL | 数据列不允许包含 NULL 值 |
| DEFAULT | 默认值 |
| PRIMARY KEY | 主键 |
| AUTO_INCREMENT | 自动递增,适用于整数类型 |
| UNSIGNED | 无符号 |
| CHARACTER SET name | 指定一个字符集 |
常见数据库(MySQL)核心数据类型(必考分类)
- 数值类型(存储数字,最常用)
用于存储整数、小数等数值,按范围和精度分为两类:
- 整数类型:INT(最常用,存储-2147483648~2147483647,如年龄、学号)、TINYINT(小整数,如性别0/1)、BIGINT(大整数,如手机号、身份证号);
- 小数类型:DECIMAL(高精度小数,如金额、价格,推荐使用,避免精度丢失)、FLOAT(单精度小数)、DOUBLE(双精度小数)。
- 字符串类型(存储文字、符号,最常用)
- VARCHAR(n):可变长度字符串,n表示最大长度(如姓名、地址,推荐使用,节省空间);
- CHAR(n):固定长度字符串,n表示固定长度(如身份证号、手机号,长度固定的场景);
- TEXT:存储长文本(如备注、简介,长度超过VARCHAR上限时使用)。
- 日期时间类型(存储时间相关数据)
- DATETIME:存储日期+时间(如注册时间、交易时间,格式:YYYY-MM-DD HH:MM:SS);
- DATE:只存储日期(如出生日期,格式:YYYY-MM-DD);
- TIME:只存储时间(如打卡时间,格式:HH:MM:SS);
- TIMESTAMP:时间戳,自动记录数据插入/更新时间,范围比DATETIME小。
- 其他常用类型
- BOOLEAN:布尔类型,存储TRUE(1)或FALSE(0),如"是否有效""是否审核";
- ENUM:枚举类型,只能从预设的选项中选择一个值(如性别:'男','女')。
数值型
MySQL 支持所有标准 SQL 数值数据类型。
这些类型包括严格数值数据类型(INTEGER、SMALLINT、DECIMAL 和 NUMERIC),以及近似数值数据类型(FLOAT、REAL 和 DOUBLE PRECISION)。
关键字INT是INTEGER的同义词,关键字DEC是DECIMAL的同义词。
BIT数据类型保存位字段值,并且支持 MyISAM、MEMORY、InnoDB 和 BDB表。
作为 SQL 标准的扩展,MySQL 也支持整数类型 TINYINT、MEDIUMINT 和 BIGINT。下面的表显示了需要的每个整数类型的存储和范围。
| 类型 | 大小 | 范围(有符号) | 范围(无符号) | 用途 |
|---|---|---|---|---|
| TINYINT | 1 Bytes | (-128,127) | (0,255) | 小整数值 |
| SMALLINT | 2 Bytes | (-32 768,32 767) | (0,65 535) | 大整数值 |
| MEDIUMINT | 3 Bytes | (-8 388 608,8 388 607) | (0,16 777 215) | 大整数值 |
| INT或INTEGER | 4 Bytes | (-2 147 483 648,2 147 483 647) | (0,4 294 967 295) | 大整数值 |
| BIGINT | 8 Bytes | (-9 223 372 036 854 775 808,9 223 372 036 854 775 807) | (0,18 446 744 073 709 551 615) | 极大整数值 |
| FLOAT | 4 Bytes | (-3.402 823 466 E+38,-1.175 494 351 E-38),0,(1.175 494 351 E-38,3.402 823 466 351 E+38) | 0,(1.175 494 351 E-38,3.402 823 466 E+38) | 单精度浮点数值 |
| DOUBLE | 8 Bytes | (-1.797 693 134 862 315 7 E+308,-2.225 073 858 507 201 4 E-308),0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) | 0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) | 双精度浮点数值 |
| DECIMAL | 对DECIMAL(M,D),如果M>D,为M+2否则为D+2 | 依赖于M和D的值 | 依赖于M和D的值 | 小数值 |
日期和时间型
表示时间值的日期和时间类型为DATETIME、DATE、TIMESTAMP、TIME和YEAR。
每个时间类型有一个有效值范围和一个"零"值,当指定不合法的MySQL不能表示的值时使用"零"值。
TIMESTAMP类型有专有的自动更新特性,将在后面描述。
| 类型 | 大小 (bytes) | 范围 | 格式 | 用途 |
|---|---|---|---|---|
| DATE | 3 | 1000-01-01/9999-12-31 | YYYY-MM-DD | 日期值 |
| TIME | 3 | '-838:59:59'/'838:59:59' | HH:MM:SS | 时间值或持续时间 |
| YEAR | 1 | 1901/2155 | YYYY | 年份值 |
| DATETIME | 8 | '1000-01-01 00:00:00' 到 '9999-12-31 23:59:59' | YYYY-MM-DD hh:mm:ss | 混合日期和时间值 |
| TIMESTAMP | 4 | '1970-01-01 00:00:01' UTC 到 '2038-01-19 03:14:07' UTC结束时间是第2147483647 秒,北京时间 2038-1-19 11:14:07,格林尼治时间 2038年1月19日 凌晨 03:14:07 | YYYY-MM-DD hh:mm:ss | 混合日期和时间值,时间戳 |
字符串类型
字符串类型指CHAR、VARCHAR、BINARY、VARBINARY、BLOB、TEXT、ENUM和SET。该节描述了这些类型如何工作以及如何在查询中使用这些类型。
| 类型 | 大小 | 用途 |
|---|---|---|
| CHAR | 0-255 bytes | 定长字符串 |
| VARCHAR | 0-65535 bytes | 变长字符串 |
| TINYBLOB | 0-255 bytes | 不超过 255 个字符的二进制字符串 |
| TINYTEXT | 0-255 bytes | 短文本字符串 |
| BLOB | 0-65 535 bytes | 二进制形式的长文本数据 |
| TEXT | 0-65 535 bytes | 长文本数据 |
| MEDIUMBLOB | 0-16 777 215 bytes | 二进制形式的中等长度文本数据 |
| MEDIUMTEXT | 0-16 777 215 bytes | 中等长度文本数据 |
| LONGBLOB | 0-4 294 967 295 bytes | 二进制形式的极大文本数据 |
| LONGTEXT | 0-4 294 967 295 bytes | 极大文本数据 |
注意:char(n) 和 varchar(n) 中括号中 n 代表字符的个数,并不代表字节个数,比如 CHAR(30) 就可以存储 30 个字符。
CHAR 和 VARCHAR 类型类似,但它们保存和检索的方式不同。它们的最大长度和是否尾部空格被保留等方面也不同。在存储或检索过程中不进行大小写转换。
BINARY 和 VARBINARY 类似于 CHAR 和 VARCHAR,不同的是它们包含二进制字符串而不要非二进制字符串。也就是说,它们包含字节字符串而不是字符字符串。这说明它们没有字符集,并且排序和比较基于列值字节的数值值。
BLOB 是一个二进制大对象,可以容纳可变数量的数据。有 4 种 BLOB 类型:TINYBLOB、BLOB、MEDIUMBLOB 和 LONGBLOB。它们区别在于可容纳存储范围不同。
有 4 种 TEXT 类型:TINYTEXT、TEXT、MEDIUMTEXT 和 LONGTEXT。对应的这 4 种 BLOB 类型,可存储的最大长度不同,可根据实际情况选择。
DDL 语句
DDL语句主要用来操作数据库中的表。
同一个库中不同表可以使用不同的存储引擎,但建议使用同一种存储引擎。
创建表
格式
bash
#帮助
# 查看创建表的语法帮助
mysql> 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]
[partition_options]
[IGNORE | REPLACE]
[AS] query_expression
CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name
{ LIKE old_tbl_name | (LIKE old_tbl_name) }
.....
直接创建
bash
# 建表通用格式:表名后用括号列出各列定义,逗号分隔
CREATE TABLE [IF NOT EXISTS] 'tbl_name' (col1 type1 修饰符,col2 type2 修饰符,...)
#字段格式
col type1 #定义字段数据类型
PRIMARY KEY(col1,...) #将该字段设为主键
INDEX(col1,...) #设置为索引
UNIQUE KEY(COL1,...) #设置为联合主键
#表选项
ENGINE [=] engine_name
ROW_FORMAT [=] {DEFAULT|DYNAMIC|FIXED|COMPRESSED|REDUNDANT|COMPACT}
范例
bash
# 创建 student 表的 SQL 语句(先写好,后面在 mysql 中执行)
# id 列:int 整数类型,UNSIGNED 无符号,AUTO_INCREMENT 自增,PRIMARY KEY 主键
# name 列:VARCHAR(20) 变长字符串最多20字符,NOT NULL 非空
# age 列:tinyint 小整数,UNSIGNED 无符号
# gender 列:ENUM 枚举类型只能取 'M' 或 'F',DEFAULT 'M' 默认值为 M
CREATE TABLE student (
id int UNSIGNED AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(20) NOT NULL,
age tinyint UNSIGNED,
#height DECIMAL(5,2),
gender ENUM('M','F') default 'M'
)ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4;
#选择数据库:切换到 db1 库
mysql> use db1;
Database changed
#执行SQL语句:逐条输入上面的建表语句
mysql> CREATE TABLE student (
-> id int UNSIGNED AUTO_INCREMENT PRIMARY KEY,
-> name VARCHAR(20) NOT NULL,
-> age tinyint UNSIGNED,
-> #height DECIMAL(5,2),
-> gender ENUM('M','F') default 'M'
-> )ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4;
Query OK, 0 rows affected (0.02 sec)
#查看:列出当前库中的所有表
mysql> show tables;
+---------------+
| Tables_in_db1 |
+---------------+
| student |
+---------------+
1 row in set (0.00 sec)
#查看结构:desc 查看 student 表的列定义
mysql> desc student;
+--------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+------------------+------+-----+---------+----------------+
| id | int unsigned | NO | PRI | NULL | auto_increment |
| name | varchar(20) | NO | | NULL | |
| age | tinyint unsigned | YES | | NULL | |
| gender | enum('M','F') | YES | | M | |
+--------+------------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)
#插入一条数据:只给 name、age 赋值,id 自增、gender 用默认值
mysql> insert student (name,age)values('xiaoming',20);
Query OK, 1 row affected (0.01 sec)
#查询表中的所有数据:* 表示所有列
mysql> select * from student;
+----+----------+------+--------+
| id | name | age | gender |
+----+----------+------+--------+
| 10 | xiaoming | 20 | M |
+----+----------+------+--------+
1 row in set (0.00 sec)
#再次插入一条数据:指定 gender 为 'f'
mysql> insert student(name,age,gender)values('xiaohong',18,'f');
Query OK, 1 row affected (0.00 sec)
mysql> select * from student;
+----+----------+------+--------+
| id | name | age | gender |
+----+----------+------+--------+
| 10 | xiaoming | 20 | M |
| 11 | xiaohong | 18 | F |
+----+----------+------+--------+
2 rows in set (0.00 sec)
通过查询现存表创建,新表会被直接插入查询而来的数据
范例
bash
# 先查看 student 表结构
mysql> desc student;
+--------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+------------------+------+-----+---------+----------------+
| id | int unsigned | NO | PRI | NULL | auto_increment |
| name | varchar(20) | NO | | NULL | |
| age | tinyint unsigned | YES | | NULL | |
| gender | enum('M','F') | YES | | M | |
+--------+------------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)
#查询其他表创建:create table ... select 把查询结果连同数据一起建成新表
mysql> create table student2 select name,age from student;
Query OK, 2 rows affected (0.01 sec)
Records: 2 Duplicates: 0 Warnings: 0
#查看:student2 已出现
mysql> show tables;
+---------------+
| Tables_in_db1 |
+---------------+
| student |
| student2 |
+---------------+
2 rows in set (0.00 sec)
#查看结构:新表只含 select 的 name、age 两列,没有主键
mysql> desc student2;
+-------+------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+-------+
| name | varchar(20) | NO | | NULL | |
| age | tinyint unsigned | YES | | NULL | |
+-------+------------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
#数据也复制过来了
mysql> select * from student2;
+----------+------+
| name | age |
+----------+------+
| xiaoming | 20 |
| xiaohong | 18 |
+----------+------+
2 rows in set (0.00 sec)
通过复制现存的表的表结构创建,但不复制数据
范例
bash
# 查看 student 表结构
mysql> desc student;
+--------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+------------------+------+-----+---------+----------------+
| id | int unsigned | NO | PRI | NULL | auto_increment |
| name | varchar(20) | NO | | NULL | |
| age | tinyint unsigned | YES | | NULL | |
| gender | enum('M','F') | YES | | M | |
+--------+------------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)
# like 方式只复制表结构,不复制数据
mysql> create table student3 like student;
Query OK, 0 rows affected (0.01 sec)
mysql> show tables;
+---------------+
| Tables_in_db1 |
+---------------+
| student |
| student2 |
| student3 |
+---------------+
3 rows in set (0.00 sec)
# 新表结构与原表完全一致(含主键、自增)
mysql> desc student3;
+--------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+------------------+------+-----+---------+----------------+
| id | int unsigned | NO | PRI | NULL | auto_increment |
| name | varchar(20) | NO | | NULL | |
| age | tinyint unsigned | YES | | NULL | |
| gender | enum('M','F') | YES | | M | |
+--------+------------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)
# 但表中没有数据
mysql> select * from student3;
Empty set (0.00 sec)
查看表
格式
bash
# 查看列出表的语法帮助
mysql> help show tables
Name: 'SHOW TABLES'
Description:
Syntax:
SHOW [EXTENDED] [FULL] TABLES
[{FROM | IN} db_name]
[LIKE 'pattern' | WHERE expr]
列出数据库中的表
格式
bash
SHOW TABLES [FROM db_name] # 列出表,可指定库名
范例
bash
#查看当前库中所有表
mysql> show tables;
+---------------+
| Tables_in_db1 |
+---------------+
| student |
| student2 |
| student3 |
+---------------+
3 rows in set (0.00 sec)
#查看指定库中的表:from db1 等价于在 db1 库下查看
mysql> show tables from db1;
+---------------+
| Tables_in_db1 |
+---------------+
| student |
| student2 |
| student3 |
+---------------+
3 rows in set (0.00 sec)
查看建表语句
格式
bash
SHOW CREATE TABLE [db_name.]tbl_name # 查看建表语句
范例
bash
# 查看 student 的建表语句
mysql> show create table student;
+---------+----------------------------------------------------------------+
| Table | Create Table |
+---------+----------------------------------------------------------------+
| student | CREATE TABLE `student` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(20) NOT NULL,
`age` tinyint unsigned DEFAULT NULL,
`gender` enum('M','F') DEFAULT 'M',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |
+---------+----------------------------------------------------------------+
1 row in set (0.00 sec)
#查看指定数据库的数据表:用 \G 竖排输出,并带库名前缀
mysql> show create table db1.student\G
*************************** 1. row ***************************
Table: student
Create Table: CREATE TABLE `student` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(20) NOT NULL,
`age` tinyint unsigned DEFAULT NULL,
`gender` enum('M','F') DEFAULT 'M',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)
查看表结构
格式
bash
DESC [db_name.]tbl_name # 查看表结构,简写
SHOW COLUMNS FROM [db_name.]tbl_name # 查看表结构,完整写法
范例
bash
# desc 查看 student 表结构
mysql> desc student;
+--------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+------------------+------+-----+---------+----------------+
| id | int unsigned | NO | PRI | NULL | auto_increment |
| name | varchar(20) | NO | | NULL | |
| age | tinyint unsigned | YES | | NULL | |
| gender | enum('M','F') | YES | | M | |
+--------+------------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)
# show columns 作用与 desc 完全相同
mysql> show columns from student;
+--------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+------------------+------+-----+---------+----------------+
| id | int unsigned | NO | PRI | NULL | auto_increment |
| name | varchar(20) | NO | | NULL | |
| age | tinyint unsigned | YES | | NULL | |
| gender | enum('M','F') | YES | | M | |
+--------+------------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)
查看表状态
格式
bash
SHOW TABLE STATUS LIKE 'tbl_name' # 查看表的引擎、行数、大小等状态
范例
bash
# 查看 student 表状态
mysql> SHOW TABLE STATUS LIKE 'student';
+---------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+------------+--------------------+----------+------------+---------+
| Name | Engine | Version | Row_format | Rows | Avg_row_length | Data_length | Max_data_length | Index_length | Data_free | Auto_increment | Create_time | Update_time | Check_time | Collation | Checksum | Create_options | Comment |
+---------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+------------+--------------------+----------+------------+---------+
| student | InnoDB | 10 | Dynamic | 2 | 8192 | 16384 | 0 | 0 | 0 | 12 | 2025-09-18 22:10:21 | 2025-09-18 22:24:45 | NULL | utf8mb4_0900_ai_ci | NULL | | |
+---------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+------------+--------------------+----------+------------+---------+
1 row in set (0.00 sec)
# 用 \G 竖排查看表状态
mysql> SHOW TABLE STATUS LIKE 'student'\G
*************************** 1. row ***************************
Name: student
Engine: InnoDB
Version: 10
Row_format: Dynamic
Rows: 2
Avg_row_length: 8192
Data_length: 16384
Max_data_length: 0
Index_length: 0
Data_free: 0
Auto_increment: 12
Create_time: 2025-09-18 22:10:21
Update_time: 2025-09-18 22:24:45
Check_time: NULL
Collation: utf8mb4_0900_ai_ci
Checksum: NULL
Create_options:
Comment:
1 row in set (0.01 sec)
#不能有库名:LIKE 后写 db1.student 匹配不到,返回空
mysql> SHOW TABLE STATUS LIKE 'db1.student'\G
Empty set (0.00 sec)
查看库中所有表状态
格式
bash
SHOW TABLE STATUS FROM db_name # 查看某库中所有表的状态
范例
bash
# 竖排查看 db1 库中所有表的状态
mysql> SHOW TABLE STATUS FROM db1\G
*************************** 1. row ***************************
Name: student
Engine: InnoDB
Version: 10
Row_format: Dynamic
Rows: 2
Avg_row_length: 8192
Data_length: 16384
Max_data_length: 0
Index_length: 0
Data_free: 0
Auto_increment: 12
Create_time: 2025-09-18 22:10:21
Update_time: 2025-09-18 22:24:45
Check_time: NULL
Collation: utf8mb4_0900_ai_ci
Checksum: NULL
Create_options:
Comment:
*************************** 2. row ***************************
Name: student2
Engine: InnoDB
Version: 10
Row_format: Dynamic
Rows: 2
Avg_row_length: 8192
Data_length: 16384
Max_data_length: 0
Index_length: 0
Data_free: 0
Auto_increment: NULL
Create_time: 2025-09-18 22:35:06
Update_time: 2025-09-18 22:35:06
Check_time: NULL
Collation: utf8mb4_0900_ai_ci
Checksum: NULL
Create_options:
Comment:
*************************** 3. row ***************************
Name: student3
Engine: InnoDB
Version: 10
Row_format: Dynamic
Rows: 0
Avg_row_length: 0
Data_length: 16384
Max_data_length: 0
Index_length: 0
Data_free: 0
Auto_increment: 1
Create_time: 2025-09-18 22:49:14
Update_time: NULL
Check_time: NULL
Collation: utf8mb4_0900_ai_ci
Checksum: NULL
Create_options:
Comment:
3 rows in set (0.01 sec)
查看当前MySQL服务支持的引擎
格式
bash
SHOW ENGINES # 查看支持的存储引擎
范例
bash
# 列表方式查看所有存储引擎
mysql> SHOW ENGINES;
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| Engine | Support | Comment | Transactions | XA | Savepoints |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| FEDERATED | NO | Federated MySQL storage engine | NULL | NULL | NULL |
| MEMORY | YES | Hash based, stored in memory, useful for temporary tables | NO | NO | NO |
| InnoDB | DEFAULT | Supports transactions, row-level locking, and foreign keys | YES | YES | YES |
| PERFORMANCE_SCHEMA | YES | Performance Schema | NO | NO | NO |
| MyISAM | YES | MyISAM storage engine | NO | NO | NO |
| MRG_MYISAM | YES | Collection of identical MyISAM tables | NO | NO | NO |
| BLACKHOLE | YES | /dev/null storage engine (anything you write to it disappears) | NO | NO | NO |
| CSV | YES | CSV storage engine | NO | NO | NO |
| ARCHIVE | YES | Archive storage engine | NO | NO | NO |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
9 rows in set (0.01 sec)
# 竖排方式查看每个引擎详情
mysql> SHOW ENGINES\G
*************************** 1. row ***************************
Engine: FEDERATED
Support: NO
Comment: Federated MySQL storage engine
Transactions: NULL
XA: NULL
Savepoints: NULL
*************************** 2. row ***************************
Engine: MEMORY
Support: YES
Comment: Hash based, stored in memory, useful for temporary tables
Transactions: NO
XA: NO
Savepoints: NO
*************************** 3. row ***************************
Engine: InnoDB
Support: DEFAULT
Comment: Supports transactions, row-level locking, and foreign keys
Transactions: YES
XA: YES
Savepoints: YES
*************************** 4. row ***************************
Engine: PERFORMANCE_SCHEMA
Support: YES
Comment: Performance Schema
Transactions: NO
XA: NO
Savepoints: NO
*************************** 5. row ***************************
Engine: MyISAM
Support: YES
Comment: MyISAM storage engine
Transactions: NO
XA: NO
Savepoints: NO
*************************** 6. row ***************************
Engine: MRG_MYISAM
Support: YES
Comment: Collection of identical MyISAM tables
Transactions: NO
XA: NO
Savepoints: NO
*************************** 7. row ***************************
Engine: BLACKHOLE
Support: YES
Comment: /dev/null storage engine (anything you write to it disappears)
Transactions: NO
XA: NO
Savepoints: NO
*************************** 8. row ***************************
Engine: CSV
Support: YES
Comment: CSV storage engine
Transactions: NO
XA: NO
Savepoints: NO
*************************** 9. row ***************************
Engine: ARCHIVE
Support: YES
Comment: Archive storage engine
Transactions: NO
XA: NO
Savepoints: NO
9 rows in set (0.00 sec)
修改和删除表
bash
# ALTER TABLE 修改表的通用语法:ADD 加列、CHANGE 改列名和类型、MODIFY 改类型、DROP 删列、RENAME 改表名
ALTER TABLE tbl_name
[alter_option [, alter_option] ...]
[partition_options]
{ ADD COLUMN <列名> <类型>
| CHANGE COLUMN <旧列名> <新列名> <新列类型>
| ALTER COLUMN <列名> { SET DEFAULT <默认值>丨DROP DEFAULT }
| MODIFY COLUMN <列名> <类型>
| DROP COLUMN <列名>
| RENAME TO <新表名> }
范例
bash
#修改表名:把 student 改名为 stu
mysql> ALTER TABLE student RENAME stu;
Query OK, 0 rows affected (0.01 sec)
mysql> show tables;
+---------------+
| Tables_in_db1 |
+---------------+
| stu |
| student2 |
| student3 |
+---------------+
3 rows in set (0.00 sec)
mysql> desc stu;
+--------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+------------------+------+-----+---------+----------------+
| id | int unsigned | NO | PRI | NULL | auto_increment |
| name | varchar(20) | NO | | NULL | |
| age | tinyint unsigned | YES | | NULL | |
| gender | enum('M','F') | YES | | M | |
+--------+------------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)
#添加表字段:ADD phone varchar(11) AFTER name,在 name 列之后新增 phone 列
mysql> ALTER TABLE stu ADD phone varchar(11) AFTER name;
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> desc stu;
+--------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+------------------+------+-----+---------+----------------+
| id | int unsigned | NO | PRI | NULL | auto_increment |
| name | varchar(20) | NO | | NULL | |
| phone | varchar(11) | YES | | NULL | |
| age | tinyint unsigned | YES | | NULL | |
| gender | enum('M','F') | YES | | M | |
+--------+------------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)
#修改字段类型:MODIFY 把 phone 列改为 int 类型
mysql> ALTER TABLE stu MODIFY phone int;
Query OK, 2 rows affected (0.01 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> desc stu;
+--------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+------------------+------+-----+---------+----------------+
| id | int unsigned | NO | PRI | NULL | auto_increment |
| name | varchar(20) | NO | | NULL | |
| phone | int | YES | | NULL | |
| age | tinyint unsigned | YES | | NULL | |
| gender | enum('M','F') | YES | | M | |
+--------+------------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)
#修改字段名称和类型:CHANGE 把 phone 改名为 mobile,并改为 char(11)
mysql> ALTER TABLE stu CHANGE COLUMN phone mobile char(11);
Query OK, 2 rows affected (0.02 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> desc stu;
+--------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+------------------+------+-----+---------+----------------+
| id | int unsigned | NO | PRI | NULL | auto_increment |
| name | varchar(20) | NO | | NULL | |
| mobile | char(11) | YES | | NULL | |
| age | tinyint unsigned | YES | | NULL | |
| gender | enum('M','F') | YES | | M | |
+--------+------------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)
#删除字段:DROP COLUMN 删除 mobile 列
mysql> ALTER TABLE stu DROP COLUMN mobile;
Query OK, 0 rows affected (0.02 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> desc stu;
+--------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+------------------+------+-----+---------+----------------+
| id | int unsigned | NO | PRI | NULL | auto_increment |
| name | varchar(20) | NO | | NULL | |
| age | tinyint unsigned | YES | | NULL | |
| gender | enum('M','F') | YES | | M | |
+--------+------------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)
#修改表字符集
mysql> ALTER TABLE stu character SET utf8;
Query OK, 0 rows affected, 1 warning (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 1
#同时修改数据类型和字符集,只修改字符集,类型也不能少
mysql> ALTER TABLE stu CHANGE name name char(30) character set utf8;
Query OK, 2 rows affected, 1 warning (0.02 sec)
Records: 2 Duplicates: 0 Warnings: 1
#设置字段默认值:把 gender 默认值设为 'M'
mysql> alter table stu alter column gender set default 'M';
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0
#添加字段和修改字段:新增 is_del 布尔列默认 false,再改为默认 true
mysql> ALTER TABLE stu ADD is_del bool DEFAULT false;
Query OK, 0 rows affected (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> ALTER TABLE stu modify is_del bool DEFAULT true;
Query OK, 0 rows affected (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0
范例
bash
# 把 stu 表连同数据复制为 stu2
mysql> create table stu2 select * from stu;
Query OK, 2 rows affected (0.01 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> desc stu2;
+--------+------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+------------------+------+-----+---------+-------+
| id | int unsigned | NO | | 0 | |
| name | char(30) | YES | | NULL | |
| age | tinyint unsigned | YES | | NULL | |
| gender | enum('M','F') | YES | | M | |
| is_del | tinyint(1) | YES | | 1 | |
+--------+------------------+------+-----+---------+-------+
5 rows in set (0.00 sec)
#添加主键:把 id 列设为主键
mysql> ALTER TABLE stu2 ADD PRIMARY KEY (id);
Query OK, 0 rows affected (0.02 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> desc stu2;
+--------+------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+------------------+------+-----+---------+-------+
| id | int unsigned | NO | PRI | 0 | |
| name | char(30) | YES | | NULL | |
| age | tinyint unsigned | YES | | NULL | |
| gender | enum('M','F') | YES | | M | |
| is_del | tinyint(1) | YES | | 1 | |
+--------+------------------+------+-----+---------+-------+
5 rows in set (0.00 sec)
#删除主键
mysql> ALTER TABLE stu2 DROP PRIMARY KEY;
Query OK, 2 rows affected (0.02 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> desc stu2;
+--------+------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+------------------+------+-----+---------+-------+
| id | int unsigned | NO | | 0 | |
| name | char(30) | YES | | NULL | |
| age | tinyint unsigned | YES | | NULL | |
| gender | enum('M','F') | YES | | M | |
| is_del | tinyint(1) | YES | | 1 | |
+--------+------------------+------+-----+---------+-------+
5 rows in set (0.00 sec)
删除表
格式
bash
# DROP TABLE 删除表语法:可一次删多张表
DROP [TEMPORARY] TABLE [IF EXISTS]
tbl_name [, tbl_name] ...
[RESTRICT | CASCADE]
范例
bash
# 先看当前所有表
mysql> show tables;
+---------------+
| Tables_in_db1 |
+---------------+
| stu |
| stu2 |
| student2 |
| student3 |
+---------------+
4 rows in set (0.00 sec)
# 删除 student2,并带库名删除 db1.student3
mysql> drop table student2;drop table db1.student3;
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.01 sec)
mysql> show tables;
+---------------+
| Tables_in_db1 |
+---------------+
| stu |
| stu2 |
+---------------+
2 rows in set (0.00 sec)
DML 语句
DML语句包括INSERT,UDPATE,DELETE
插入数据
INSERT可以一次往表中插入一条或多条记录
格式
bash
# 查看 INSERT 语法帮助
mysql> help INSERT
Name: 'INSERT'
Description:
Syntax:
INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name
[PARTITION (partition_name [, partition_name] ...)]
[(col_name [, col_name] ...)]
{ {VALUES | VALUE} (value_list) [, (value_list)] ...
|
VALUES row_constructor_list
}
[AS row_alias[(col_alias [, col_alias] ...)]]
[ON DUPLICATE KEY UPDATE assignment_list]
INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name
[PARTITION (partition_name [, partition_name] ...)]
[AS row_alias[(col_alias [, col_alias] ...)]]
SET assignment_list
[ON DUPLICATE KEY UPDATE assignment_list]
INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name
[PARTITION (partition_name [, partition_name] ...)]
[(col_name [, col_name] ...)]
[AS row_alias[(col_alias [, col_alias] ...)]]
{SELECT ... | TABLE table_name}
[ON DUPLICATE KEY UPDATE assignment_list]
简化格式
bash
INSERT tbl_name [(col1,...)] VALUES (val1,...),(val21,...) # 简化插入格式
范例
bash
# 先查看 stu 表现有数据
mysql> select * from stu;
+----+----------+------+--------+--------+
| id | name | age | gender | is_del |
+----+----------+------+--------+--------+
| 10 | xiaoming | 20 | M | 0 |
| 11 | xiaohong | 18 | F | 0 |
+----+----------+------+--------+--------+
2 rows in set (0.00 sec)
#给出所有字段值(给出所有字段值,可以不用标明字段,只要顺序一一对应即可)
mysql> INSERT INTO stu VALUES(12,'xiaoli',19,'F',0);
Query OK, 1 row affected (0.01 sec)
#只给出部分字段值,因为有些字段值有默认值
mysql> INSERT INTO stu(name,age)VALUES('xiaozhou',20);
Query OK, 1 row affected (0.02 sec)
#一次插入多条:用逗号分隔多组 VALUES
mysql> INSERT INTO stu (name,age)VALUES('test1',20),('test2',21),('test3',22);
Query OK, 3 rows affected (0.01 sec)
Records: 3 Duplicates: 0 Warnings: 0
#有默认值的用默认值,没有默认值的用NULL值
mysql> INSERT stu (age,is_del)VALUES(23,0);
Query OK, 1 row affected (0.00 sec)
#查看
mysql> select * from stu;
+----+----------+------+--------+--------+
| id | name | age | gender | is_del |
+----+----------+------+--------+--------+
| 10 | xiaoming | 20 | M | 0 |
| 11 | xiaohong | 18 | F | 0 |
| 12 | xiaoli | 19 | F | 0 |
| 13 | xiaozhou | 20 | M | 1 |
| 14 | test1 | 20 | M | 1 |
| 15 | test2 | 21 | M | 1 |
| 16 | test3 | 22 | M | 1 |
| 17 | NULL | 23 | M | 0 |
+----+----------+------+--------+--------+
8 rows in set (0.00 sec)
#如果记录不存在就新增,如果存在就更新
mysql> SELECT * FROM stu WHERE id=12;
+----+--------+------+--------+--------+
| id | name | age | gender | is_del |
+----+--------+------+--------+--------+
| 12 | xiaoli | 19 | F | 0 |
+----+--------+------+--------+--------+
1 row in set (0.00 sec)
# 主键冲突直接插入会报错
mysql> INSERT INTO stu (id,name)VALUES(12,'zhangsan');
ERROR 1062 (23000): Duplicate entry '12' for key 'stu.PRIMARY'
# ON DUPLICATE KEY UPDATE:主键冲突时改为更新 name
mysql> INSERT INTO stu (id,name)VALUES(12,'zhangsan') ON DUPLICATE KEY UPDATE name='zhangsan';
Query OK, 2 rows affected (0.00 sec)
mysql> SELECT * FROM stu WHERE id=12;
+----+----------+------+--------+--------+
| id | name | age | gender | is_del |
+----+----------+------+--------+--------+
| 12 | zhangsan | 19 | F | 0 |
+----+----------+------+--------+--------+
1 row in set (0.00 sec)
#将查询结果当值插入:把 stu 中 id=11 的记录查出再插入
mysql> insert into stu (name,age,gender) select name,age,gender from stu where id=11;
Query OK, 1 row affected (0.01 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> select * from stu;
+----+----------+------+--------+--------+
| id | name | age | gender | is_del |
+----+----------+------+--------+--------+
| 10 | xiaoming | 20 | M | 0 |
| 11 | xiaohong | 18 | F | 0 |
| 12 | zhangsan | 19 | F | 0 |
| 13 | xiaozhou | 20 | M | 1 |
| 14 | test1 | 20 | M | 1 |
| 15 | test2 | 21 | M | 1 |
| 16 | test3 | 22 | M | 1 |
| 17 | NULL | 23 | M | 0 |
| 18 | xiaohong | 18 | F | 1 |
+----+----------+------+--------+--------+
9 rows in set (0.00 sec)
# 用 IN 条件一次把 id 在 (11,12) 的记录查出并插入
mysql> insert into stu (name,age,gender) select name,age,gender from stu where id in (11,12);
Query OK, 2 rows affected (0.01 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> select * from stu;
+----+----------+------+--------+--------+
| id | name | age | gender | is_del |
+----+----------+------+--------+--------+
| 10 | xiaoming | 20 | M | 0 |
| 11 | xiaohong | 18 | F | 0 |
| 12 | zhangsan | 19 | F | 0 |
| 13 | xiaozhou | 20 | M | 1 |
| 14 | test1 | 20 | M | 1 |
| 15 | test2 | 21 | M | 1 |
| 16 | test3 | 22 | M | 1 |
| 17 | NULL | 23 | M | 0 |
| 18 | xiaohong | 18 | F | 1 |
| 19 | xiaohong | 18 | F | 1 |
| 20 | zhangsan | 19 | F | 1 |
+----+----------+------+--------+--------+
11 rows in set (0.00 sec)
更新数据
更新数据一定要加条件限制,没有条件则会更新表中所有记录。
bash
# UPDATE 语法:SET 赋值,WHERE 限定条件,ORDER BY、LIMIT 可选
UPDATE [LOW_PRIORITY] [IGNORE] table_reference
SET assignment_list
[WHERE where_condition]
[ORDER BY ...]
[LIMIT row_count]
范例
bash
#不加条件表示更新所有:把所有行 age 改为 30、gender 改为 F
mysql> UPDATE stu set age=30,gender='F';
Query OK, 11 rows affected (0.00 sec)
Rows matched: 11 Changed: 11 Warnings: 0
mysql> select * from stu;
+----+----------+------+--------+--------+
| id | name | age | gender | is_del |
+----+----------+------+--------+--------+
| 10 | xiaoming | 30 | F | 0 |
| 11 | xiaohong | 30 | F | 0 |
| 12 | zhangsan | 30 | F | 0 |
| 13 | xiaozhou | 30 | F | 1 |
| 14 | test1 | 30 | F | 1 |
| 15 | test2 | 30 | F | 1 |
| 16 | test3 | 30 | F | 1 |
| 17 | NULL | 30 | F | 0 |
| 18 | xiaohong | 30 | F | 1 |
| 19 | xiaohong | 30 | F | 1 |
| 20 | zhangsan | 30 | F | 1 |
+----+----------+------+--------+--------+
11 rows in set (0.00 sec)
#根据条件更新:只把 id>15 的行 age 改为 31
mysql> update stu set age=31 WHERE id>15;
Query OK, 5 rows affected (0.01 sec)
Rows matched: 5 Changed: 5 Warnings: 0
mysql> select * from stu;
+----+----------+------+--------+--------+
| id | name | age | gender | is_del |
+----+----------+------+--------+--------+
| 10 | xiaoming | 30 | F | 0 |
| 11 | xiaohong | 30 | F | 0 |
| 12 | zhangsan | 30 | F | 0 |
| 13 | xiaozhou | 30 | F | 1 |
| 14 | test1 | 30 | F | 1 |
| 15 | test2 | 30 | F | 1 |
| 16 | test3 | 31 | F | 1 |
| 17 | NULL | 31 | F | 0 |
| 18 | xiaohong | 31 | F | 1 |
| 19 | xiaohong | 31 | F | 1 |
| 20 | zhangsan | 31 | F | 1 |
+----+----------+------+--------+--------+
11 rows in set (0.00 sec)
#多个条件,满足任何一个条件都更新 OR 可以写成 ||
mysql> update stu set age=21,gender='M' where (id=15 OR name is null);
Query OK, 2 rows affected (0.01 sec)
Rows matched: 2 Changed: 2 Warnings: 0
mysql> select * from stu;
+----+----------+------+--------+--------+
| id | name | age | gender | is_del |
+----+----------+------+--------+--------+
| 10 | xiaoming | 30 | F | 0 |
| 11 | xiaohong | 30 | F | 0 |
| 12 | zhangsan | 30 | F | 0 |
| 13 | xiaozhou | 30 | F | 1 |
| 14 | test1 | 30 | F | 1 |
| 15 | test2 | 21 | M | 1 |
| 16 | test3 | 31 | F | 1 |
| 17 | NULL | 21 | M | 0 |
| 18 | xiaohong | 31 | F | 1 |
| 19 | xiaohong | 31 | F | 1 |
| 20 | zhangsan | 31 | F | 1 |
+----+----------+------+--------+--------+
11 rows in set (0.00 sec)
#多个条件满足,AND 可以写成 &&
mysql> update stu set age=22,gender='M' WHERE (id=17 AND name is null);
Query OK, 1 row affected (0.02 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from stu;
+----+----------+------+--------+--------+
| id | name | age | gender | is_del |
+----+----------+------+--------+--------+
| 10 | xiaoming | 30 | F | 0 |
| 11 | xiaohong | 30 | F | 0 |
| 12 | zhangsan | 30 | F | 0 |
| 13 | xiaozhou | 30 | F | 1 |
| 14 | test1 | 30 | F | 1 |
| 15 | test2 | 21 | M | 1 |
| 16 | test3 | 31 | F | 1 |
| 17 | NULL | 22 | M | 0 |
| 18 | xiaohong | 31 | F | 1 |
| 19 | xiaohong | 31 | F | 1 |
| 20 | zhangsan | 31 | F | 1 |
+----+----------+------+--------+--------+
11 rows in set (0.00 sec)
#NULL要写 IS NULL:用 = NULL 匹配不到任何行,必须用 IS NULL
mysql> update stu set gender='F' where name=NULL;
Query OK, 0 rows affected (0.01 sec)
Rows matched: 0 Changed: 0 Warnings: 0
mysql> update stu set gender='F' where name IS NULL;
Query OK, 0 rows affected (0.00 sec)
Rows matched: 0 Changed: 0 Warnings: 0
保证无法在没有条件的情况下更新所有
bash
-U, --i-am-a-dummy Synonym for option --safe-updates, -U.
# 以安全更新模式登录 mysql
[root@localhost ~]# mysql -U
#该配置还可以写到配置文件中
[root@localhost ~]# vim /etc/my.cnf.d/client.cnf
[client]
safe-updates
#无法完全更新:不带 WHERE 主键条件会被安全模式拒绝
mysql> update stu set age=22;
ERROR 1175 (HY000): You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column.
# 即使带 WHERE 但没用到主键列,也被拒绝
mysql> update stu set age=23 where name='test3';
ERROR 1175 (HY000): You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column.
#必须要指定主键:WHERE 用 id 主键才允许更新
mysql> UPDATE stu SET age=23 WHERE id=17;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from stu;
+----+----------+------+--------+--------+
| id | name | age | gender | is_del |
+----+----------+------+--------+--------+
| 10 | xiaoming | 30 | F | 0 |
| 11 | xiaohong | 30 | F | 0 |
| 12 | zhangsan | 30 | F | 0 |
| 13 | xiaozhou | 30 | F | 1 |
| 14 | test1 | 30 | F | 1 |
| 15 | test2 | 21 | M | 1 |
| 16 | test3 | 31 | F | 1 |
| 17 | NULL | 23 | F | 0 |
| 18 | xiaohong | 31 | F | 1 |
| 19 | xiaohong | 31 | F | 1 |
| 20 | zhangsan | 31 | F | 1 |
+----+----------+------+--------+--------+
11 rows in set (0.00 sec)
删除数据
格式
bash
# DELETE 删除数据语法
DELETE [LOW_PRIORITY] [QUICK] [IGNORE]
tbl_name[.*] [, tbl_name[.*]] ...
FROM table_references
[WHERE where_condition]
DELETE [LOW_PRIORITY] [QUICK] [IGNORE]
FROM tbl_name[.*] [, tbl_name[.*]] ...
USING table_references
[WHERE where_condition]
范例
bash
#查看全部数据
mysql> select * from stu;
+----+----------+------+--------+--------+
| id | name | age | gender | is_del |
+----+----------+------+--------+--------+
| 10 | xiaoming | 30 | F | 0 |
| 11 | xiaohong | 30 | F | 0 |
| 12 | zhangsan | 30 | F | 0 |
| 13 | xiaozhou | 30 | F | 1 |
| 14 | test1 | 30 | F | 1 |
| 15 | test2 | 21 | M | 1 |
| 16 | test3 | 31 | F | 1 |
| 17 | NULL | 23 | F | 0 |
| 18 | xiaohong | 31 | F | 1 |
| 19 | xiaohong | 31 | F | 1 |
| 20 | zhangsan | 31 | F | 1 |
+----+----------+------+--------+--------+
11 rows in set (0.00 sec)
#根据条件删除:删除 id=10 的行
mysql> delete from stu where id=10;
Query OK, 1 row affected (0.00 sec)
mysql> select * from stu;
+----+----------+------+--------+--------+
| id | name | age | gender | is_del |
+----+----------+------+--------+--------+
| 11 | xiaohong | 30 | F | 0 |
| 12 | zhangsan | 30 | F | 0 |
| 13 | xiaozhou | 30 | F | 1 |
+----+----------+------+--------+--------+
| 14 | test1 | 30 | F | 1 |
| 15 | test2 | 21 | M | 1 |
| 16 | test3 | 31 | F | 1 |
| 17 | NULL | 23 | F | 0 |
| 18 | xiaohong | 31 | F | 1 |
| 19 | xiaohong | 31 | F | 1 |
| 20 | zhangsan | 31 | F | 1 |
+----+----------+------+--------+--------+
10 rows in set (0.00 sec)
在直实生产环境中,一般不会对数据做物理删除,而是用字段来标记为逻辑删除,将对应字段值设为某个特定项(is_del ),(is_del=1)认为是己删除
bash
# 逻辑删除:把 id=11 的记录标记为已删除(is_del 置 1),而不是真的 DELETE 掉
mysql> UPDATE stu SET is_del=1 WHERE id=11;
Query OK, 0 rows affected (0.00 sec)
Rows matched: 1 Changed: 0 Warnings: 0
# 再次查询全表,记录依然存在,只是 is_del 变成了 1
mysql> select * from stu;
+----+----------+------+--------+--------+
| id | name | age | gender | is_del |
+----+----------+------+--------+--------+
| 11 | xiaohong | 30 | F | 1 |
| 12 | zhangsan | 30 | F | 0 |
| 13 | xiaozhou | 30 | F | 1 |
| 14 | test1 | 30 | F | 1 |
| 15 | test2 | 21 | M | 1 |
| 16 | test3 | 31 | F | 1 |
| 17 | NULL | 23 | F | 0 |
| 18 | xiaohong | 31 | F | 1 |
| 19 | xiaohong | 31 | F | 1 |
| 20 | zhangsan | 31 | F | 1 |
+----+----------+------+--------+--------+
10 rows in set (0.00 sec)
清空表
bash
# TRUNCATE:DDL 语句,直接清空整张表重建,不支持事务回滚,效率更高
TRUNCATE TABLE tbl_name; #DDL语句,不支持事务,效率更高
# DELETE:DML 语句,逐行删除,支持事务回滚,可加 WHERE 条件
DELETE FROM tbl_name; #DML语句
DQL 语句
格式
bash
# 查看 SELECT 语句的完整帮助语法
mysql> help select
Name: 'SELECT'
Description:
Syntax:
SELECT
[ALL | DISTINCT | DISTINCTROW ]
[HIGH_PRIORITY]
[STRAIGHT_JOIN]
[SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]
[SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS]
select_expr [, select_expr] ...
[into_option]
[FROM table_references
[PARTITION partition_list]]
[WHERE where_condition]
[GROUP BY {col_name | expr | position}, ... [WITH ROLLUP]]
[HAVING where_condition]
[WINDOW window_name AS (window_spec)
[, window_name AS (window_spec)] ...]
[ORDER BY {col_name | expr | position}
[ASC | DESC], ... [WITH ROLLUP]]
[LIMIT {[offset,] row_count | row_count OFFSET offset}]
[into_option]
[FOR {UPDATE | SHARE}
[OF tbl_name [, tbl_name] ...]
[NOWAIT | SKIP LOCKED]
| LOCK IN SHARE MODE]
[into_option]
into_option: {
INTO OUTFILE 'file_name'
[CHARACTER SET charset_name]
export_options
| INTO DUMPFILE 'file_name'
| INTO var_name [, var_name] ...
}
说明
- 字段显示可以使用别名:col1 AS alias1,col2 AS alias2,...
- WHERE子句:指明过滤条件以实现"选择"的功能
- 过滤条件:布尔型表达式
- 算术操作符:+,-,*,/,%
- 比较操作符:=,<=>(相等或都为空),<>,!=(非标准SQL,>,>=,<,<=
- 范围查询:BETWEEN min_num AND max_num
- 不连续的查询:IN(element1,element2,...)
- 空查询:IS NULL,,IS NOT NULL
- DISTINCT去除重复行,范例:SELECT DISTINCT gender FROM students;
- 模糊查询:LIKE使用%表示任意长度的任意字符_表示任意单个字符
- RLIKE:正则表达式,索引失效,不建议使用
- REGEXP:匹配字符串可用正则表达式书写模式,同上
- 逻辑操作符:NOT,AND,OR,XOR
- GROUPBY:根据指定的条件把查询结果进行"分组"以用于做"聚合"运算
- 常见聚合函数:count(),sum(),max(),min(),avg(),注意:聚合函数不对null统计
- HAVING:对分组聚合运算后的结果指定过滤条件
- 一旦分组group by,select语句后只跟分组的字段,聚合函数
- ORDERBY:根据指定的字段对查询结果进行排序
- 升序:ASC
- 降序:DESC
- LIMIToffset,row_count]:对查询的结果进行输出行数数量限制,跳过offset,显示row_count 行,offset默为值为0。
- 对查询结果中的数据请求施加"锁"
- FOR UPDATE:写锁,独占或排它锁,只有一个读和写操作
- LOCK IN SHARE MODE:读锁,共享锁,同时多个读操作
单表操作
范例:查字符串和变量
bash
#直接查字符串
mysql> select 123;
+-----+
| 123 |
+-----+
| 123 |
+-----+
1 row in set (0.00 sec)
#指定别名:用 AS 给字符串列起别名 'laogao'
mysql> select 'gqd' as 'laogao';
+--------+
| laogao |
+--------+
| gqd |
+--------+
1 row in set (0.00 sec)
#数学计算:SELECT 可直接做算术运算 1+2*3
mysql> select 1+2*3;
+-------+
| 1+2*3 |
+-------+
| 7 |
+-------+
1 row in set (0.01 sec)
#查询变量:@@port 读取 MySQL 系统变量(监听端口)
mysql> select @@port;
+--------+
| @@port |
+--------+
| 3306 |
+--------+
1 row in set (0.01 sec)
#查询函数:now() 返回当前日期时间
mysql> select now();
+---------------------+
| now() |
+---------------------+
| 2025-09-21 20:52:19 |
+---------------------+
1 row in set (0.00 sec)
范例:指定字段和查询条件
bash
#全表扫描:SELECT * 取出 stu 表所有字段所有行
mysql> select * from stu;
+----+----------+------+--------+--------+
| id | name | age | gender | is_del |
+----+----------+------+--------+--------+
| 11 | xiaohong | 30 | F | 1 |
| 12 | zhangsan | 30 | F | 0 |
| 13 | xiaozhou | 30 | F | 1 |
| 14 | test1 | 30 | F | 1 |
| 15 | test2 | 21 | M | 1 |
| 16 | test3 | 31 | F | 1 |
| 17 | NULL | 23 | F | 0 |
| 18 | xiaohong | 31 | F | 1 |
| 19 | xiaohong | 31 | F | 1 |
| 20 | zhangsan | 31 | F | 1 |
+----+----------+------+--------+--------+
10 rows in set (0.00 sec)
#查询指定字段:id/name/age 三列,并用 AS 起中文别名
mysql> select id as 学号,name as 姓名,age as 年纪 from stu;
+--------+----------+--------+
| 学号 | 姓名 | 年纪 |
+--------+----------+--------+
| 11 | xiaohong | 30 |
| 12 | zhangsan | 30 |
| 13 | xiaozhou | 30 |
| 14 | test1 | 30 |
| 15 | test2 | 21 |
| 16 | test3 | 31 |
| 17 | NULL | 23 |
| 18 | xiaohong | 31 |
| 19 | xiaohong | 31 |
| 20 | zhangsan | 31 |
+--------+----------+--------+
10 rows in set (0.00 sec)
#根据条件查询:WHERE id=11 只取出 id 等于 11 的行
mysql> select id,name from stu where id=11;
+----+----------+
| id | name |
+----+----------+
| 11 | xiaohong |
+----+----------+
1 row in set (0.00 sec)
#多条:IN 取不连续的多个 id 值 (11,15,19)
mysql> select id,name from stu where id in(11,15,19);
+----+----------+
| id | name |
+----+----------+
| 11 | xiaohong |
| 15 | test2 |
| 19 | xiaohong |
+----+----------+
3 rows in set (0.00 sec)
#and 可以写为 &&:AND 表示并且,取 11<=id<14 的行
mysql> select id,name from stu where id>=11 and id <14;
+----+----------+
| id | name |
+----+----------+
| 11 | xiaohong |
| 12 | zhangsan |
| 13 | xiaozhou |
+----+----------+
3 rows in set (0.00 sec)
#or 可以写为 ||:OR 表示或者,取 id<=12 或 id>19 的行
mysql> select id,name from stu where id<=12 or id>19;
+----+----------+
| id | name |
+----+----------+
| 11 | xiaohong |
| 12 | zhangsan |
| 20 | zhangsan |
+----+----------+
3 rows in set (0.00 sec)
范例:NULL值
bash
# 错误写法:NULL 不能用 = 比较,查不出任何行(语法错误用法)
mysql> select id,name,age from stu where name=NUll; #语法错误
Empty set (0.01 sec)
#null值:判断空值必须用 IS NULL
mysql> select id,name,age from stu where name IS NULL;
+----+------+------+
| id | name | age |
+----+------+------+
| 17 | NULL | 23 |
+----+------+------+
1 row in set (0.00 sec)
#非null值:IS NOT NULL 取出 name 不为空的行
mysql> select id,name,age from stu where name is not null;
+----+----------+------+
| id | name | age |
+----+----------+------+
| 11 | xiaohong | 30 |
| 12 | zhangsan | 30 |
| 13 | xiaozhou | 30 |
| 14 | test1 | 30 |
| 15 | test2 | 21 |
| 16 | test3 | 31 |
| 18 | xiaohong | 31 |
| 19 | xiaohong | 31 |
| 20 | zhangsan | 31 |
+----+----------+------+
9 rows in set (0.00 sec)
范例:模糊匹配
bash
#以指定字符开头:LIKE 'x%',% 匹配任意长度任意字符
mysql> select id,name from stu where name like 'x%';
+----+----------+
| id | name |
+----+----------+
| 11 | xiaohong |
| 13 | xiaozhou |
| 18 | xiaohong |
| 19 | xiaohong |
+----+----------+
4 rows in set (0.00 sec)
#以指定字符开头:LIKE 'xiao%' 匹配 xiao 开头
mysql> select id,name from stu where name like 'xiao%';
+----+----------+
| id | name |
+----+----------+
| 11 | xiaohong |
| 13 | xiaozhou |
| 18 | xiaohong |
| 19 | xiaohong |
+----+----------+
4 rows in set (0.00 sec)
#以指定字符结尾:LIKE '%ng' 匹配 ng 结尾
mysql> select id,name from stu where name like '%ng';
+----+----------+
| id | name |
+----+----------+
| 11 | xiaohong |
| 18 | xiaohong |
| 19 | xiaohong |
+----+----------+
3 rows in set (0.00 sec)
#包含指定字符串:LIKE '%ou%' 中间任意位置含 ou
mysql> select id,name from stu where name like '%ou%';
+----+----------+
| id | name |
+----+----------+
| 13 | xiaozhou |
+----+----------+
1 row in set (0.00 sec)
#多个LIKE:OR 连接两个模糊条件,名字含 n 或含 i
mysql> select id,name from stu where name like '%n%' or name like '%i%';
+----+----------+
| id | name |
+----+----------+
| 11 | xiaohong |
| 12 | zhangsan |
| 13 | xiaozhou |
| 18 | xiaohong |
| 19 | xiaohong |
| 20 | zhangsan |
+----+----------+
6 rows in set (0.01 sec)
范例:区域间过滤
bash
#连续:BETWEEN ... AND ... 取闭区间 12~15
mysql> select id,name from stu where id between 12 and 15;
+----+----------+
| id | name |
+----+----------+
| 12 | zhangsan |
| 13 | xiaozhou |
| 14 | test1 |
| 15 | test2 |
+----+----------+
4 rows in set (0.00 sec)
#取反:NOT BETWEEN 取区间之外的行
mysql> select id,name from stu where id not between 12 and 15;
+----+----------+
| id | name |
+----+----------+
| 11 | xiaohong |
| 16 | test3 |
| 17 | NULL |
| 18 | xiaohong |
| 19 | xiaohong |
| 20 | zhangsan |
+----+----------+
6 rows in set (0.00 sec)
#不连续:IN 取指定的几个值
mysql> select id,name from stu where id in(12,15,19);
+----+----------+
| id | name |
+----+----------+
| 12 | zhangsan |
| 15 | test2 |
| 19 | xiaohong |
+----+----------+
3 rows in set (0.01 sec)
#不连续取反:NOT IN 取不在列表中的行
mysql> select id,name from stu where id not in (12,15,19);
+----+----------+
| id | name |
+----+----------+
| 11 | xiaohong |
| 13 | xiaozhou |
| 14 | test1 |
| 16 | test3 |
| 17 | NULL |
| 18 | xiaohong |
| 20 | zhangsan |
+----+----------+
7 rows in set (0.00 sec)
范例:统计和分组
bash
#统计表中的记录条数:count(*) 统计总行数(含 NULL),起别名 total
mysql> select count(*) as total from stu;
+-------+
| total |
+-------+
| 10 |
+-------+
1 row in set (0.00 sec)
#name字段中有null,不统计:count(字段) 自动跳过 NULL 值,所以是 9
mysql> select count(name) from stu;
+-------------+
| count(name) |
+-------------+
| 9 |
+-------------+
1 row in set (0.00 sec)
# count(id):id 非空,统计结果为 10
mysql> select count(id) from stu;
+-----------+
| count(id) |
+-----------+
| 10 |
+-----------+
1 row in set (0.00 sec)
#最大值,最小值,平均值:max/min/avg 三个聚合函数一起查
mysql> select max(id),min(id),avg(age) from stu;
+---------+---------+----------+
| max(id) | min(id) | avg(age) |
+---------+---------+----------+
| 20 | 11 | 28.8000 |
+---------+---------+----------+
1 row in set (0.00 sec)
#求和:sum(age) 求年龄总和
mysql> select sum(age) from stu;
+----------+
| sum(age) |
+----------+
| 288 |
+----------+
1 row in set (0.00 sec)
#分组统计:按 gender 分组,求每组年龄之和
mysql> select sum(age),gender from stu group by gender;
+----------+--------+
| sum(age) | gender |
+----------+--------+
| 183 | F |
| 105 | M |
+----------+--------+
2 rows in set (0.00 sec)
#分组统计:按 gender 分组,求每组记录数
mysql> select count(*),gender from stu group by gender;
+----------+--------+
| count(*) | gender |
+----------+--------+
| 6 | F |
| 4 | M |
+----------+--------+
2 rows in set (0.00 sec)
#分组带where条件:先 WHERE 过滤掉 name 为 NULL 的行,再按 gender 分组统计
mysql> select count(*),max(id),avg(age),gender from stu where name is not null
group by gender;
+----------+---------+----------+--------+
| count(*) | max(id) | avg(age) | gender |
+----------+---------+----------+--------+
| 6 | 19 | 30.5000 | F |
| 3 | 20 | 27.3333 | M |
+----------+---------+----------+--------+
2 rows in set (0.00 sec)
#分组后过滤:HAVING 对分组结果再过滤,只保留 total=3 的组
mysql> select count(*) as total,max(id),avg(age),gender from stu where name is
not null group by gender having total=3;
+-------+---------+----------+--------+
| total | max(id) | avg(age) | gender |
+-------+---------+----------+--------+
| 3 | 20 | 27.3333 | M |
+-------+---------+----------+--------+
1 row in set (0.00 sec)
#分组统计:按 gender 分组统计各聚合值(包含 name 为 NULL 的行)
mysql> select count(*),max(id),avg(age),gender from stu group by gender;
+----------+---------+----------+--------+
| count(*) | max(id) | avg(age) | gender |
+----------+---------+----------+--------+
| 6 | 19 | 30.5000 | F |
| 4 | 20 | 26.2500 | M |
+----------+---------+----------+--------+
2 rows in set (0.00 sec)
范例:排序
bash
#默认按ID升序排列:不加 ORDER BY 时默认按存储顺序(近似 id 升序)
mysql> select id,name,age from stu;
+----+----------+------+
| id | name | age |
+----+----------+------+
| 11 | xiaohong | 30 |
| 12 | zhangsan | 30 |
| 13 | xiaozhou | 30 |
| 14 | test1 | 30 |
| 15 | test2 | 21 |
| 16 | test3 | 31 |
| 17 | NULL | 23 |
| 18 | xiaohong | 31 |
| 19 | xiaohong | 31 |
| 20 | zhangsan | 31 |
+----+----------+------+
10 rows in set (0.00 sec)
# ORDER BY id 显式按 id 排序(默认升序 ASC)
mysql> select id,name,age from stu order by id;
+----+----------+------+
| id | name | age |
+----+----------+------+
| 11 | xiaohong | 30 |
| 12 | zhangsan | 30 |
| 13 | xiaozhou | 30 |
| 14 | test1 | 30 |
| 15 | test2 | 21 |
| 16 | test3 | 31 |
| 17 | NULL | 23 |
| 18 | xiaohong | 31 |
| 19 | xiaohong | 31 |
| 20 | zhangsan | 31 |
+----+----------+------+
10 rows in set (0.00 sec)
# ORDER BY id asc 显式指定升序
mysql> select id,name,age from stu order by id asc;
+----+----------+------+
| id | name | age |
+----+----------+------+
| 11 | xiaohong | 30 |
| 12 | zhangsan | 30 |
| 13 | xiaozhou | 30 |
| 14 | test1 | 30 |
| 15 | test2 | 21 |
| 16 | test3 | 31 |
| 17 | NULL | 23 |
| 18 | xiaohong | 31 |
| 19 | xiaohong | 31 |
| 20 | zhangsan | 31 |
+----+----------+------+
10 rows in set (0.00 sec)
#降序:ORDER BY id DESC 按 id 从大到小
mysql> select id,name,age from stu order by id desc;
+----+----------+------+
| id | name | age |
+----+----------+------+
| 20 | zhangsan | 31 |
| 19 | xiaohong | 31 |
| 18 | xiaohong | 31 |
| 17 | NULL | 23 |
| 16 | test3 | 31 |
| 15 | test2 | 21 |
| 14 | test1 | 30 |
| 13 | xiaozhou | 30 |
| 12 | zhangsan | 30 |
| 11 | xiaohong | 30 |
+----+----------+------+
10 rows in set (0.00 sec)
#降序变升序:ORDER BY -id DESC 相当于对 id 取反后降序,结果变回升序
mysql> select id,name,age from stu order by -id desc;
+----+----------+------+
| id | name | age |
+----+----------+------+
| 11 | xiaohong | 30 |
| 12 | zhangsan | 30 |
| 13 | xiaozhou | 30 |
| 14 | test1 | 30 |
| 15 | test2 | 21 |
| 16 | test3 | 31 |
| 17 | NULL | 23 |
| 18 | xiaohong | 31 |
| 19 | xiaohong | 31 |
| 20 | zhangsan | 31 |
+----+----------+------+
10 rows in set (0.00 sec)
#用分组结果排序:分组后用别名 sum_age 做 ORDER BY 升序
mysql> select sum(age) as sum_age,avg(age) avg_age,gender 性别 from stu where name
is not null group by gender order by sum_age asc;
+---------+---------+--------+
| sum_age | avg_age | 性别 |
+---------+---------+--------+
| 82 | 27.3333 | M |
| 183 | 30.5000 | F |
+---------+---------+--------+
2 rows in set (0.00 sec)
范例:去重
bash
# 先按年龄降序看原始数据(有重复年龄)
mysql> select id,name,age from stu order by age desc;
+----+----------+------+
| id | name | age |
+----+----------+------+
| 16 | test3 | 31 |
| 18 | xiaohong | 31 |
| 19 | xiaohong | 31 |
| 20 | zhangsan | 31 |
| 11 | xiaohong | 30 |
| 12 | zhangsan | 30 |
| 13 | xiaozhou | 30 |
| 14 | test1 | 30 |
| 17 | NULL | 23 |
| 15 | test2 | 21 |
+----+----------+------+
10 rows in set (0.00 sec)
#去重:DISTINCT 对 age 列去重,只保留不同年龄
mysql> select distinct age from stu order by age desc;
+------+
| age |
+------+
| 31 |
| 30 |
| 23 |
| 21 |
+------+
4 rows in set (0.00 sec)
#去重:distinct(age) 写法等价于 distinct age
mysql> select distinct(age) from stu order by age desc;
+------+
| age |
+------+
| 31 |
| 30 |
| 23 |
| 21 |
+------+
4 rows in set (0.00 sec)
范例:分页
bash
# 全表 id 列表,用于演示分页
mysql> select id,name from stu;
+----+----------+
| id | name |
+----+----------+
| 11 | xiaohong |
| 12 | zhangsan |
| 13 | xiaozhou |
| 14 | test1 |
| 15 | test2 |
| 16 | test3 |
| 17 | NULL |
| 18 | xiaohong |
| 19 | xiaohong |
| 20 | zhangsan |
+----+----------+
10 rows in set (0.00 sec)
#第一页,每页3条记录
# 0,3 跳过第0条从第一条开始,显示3条
# LIMIT offset,row_count:跳过 offset 行,取 row_count 行
mysql> select id,name from stu limit 0,3;
+----+----------+
| id | name |
+----+----------+
| 11 | xiaohong |
| 12 | zhangsan |
| 13 | xiaozhou |
+----+----------+
3 rows in set (0.00 sec)
#第二页,每页3条记录:跳过 3 行再取 3 行
mysql> select id,name from stu limit 3,3;
+----+-------+
| id | name |
+----+-------+
| 14 | test1 |
| 15 | test2 |
| 16 | test3 |
+----+-------+
3 rows in set (0.00 sec)
#第三页,每页3条记录:跳过 6 行再取 3 行
mysql> select id,name from stu limit 6,3;
+----+----------+
| id | name |
+----+----------+
| 17 | NULL |
| 18 | xiaohong |
| 19 | xiaohong |
+----+----------+
3 rows in set (0.01 sec)
多表查询
简单案例
准备表:yuangong(员工)、bumen(部门)
一、创建表(只有 员工表、部门表)
bash
-- 部门表
CREATE TABLE bumen (
bumen_id INT PRIMARY KEY, -- 部门ID
bumen_name VARCHAR(20) -- 部门名称
);
-- 员工表
CREATE TABLE yuangong (
yuangong_id INT PRIMARY KEY, -- 员工ID
name VARCHAR(20), -- 员工姓名
bumen_id INT -- 所属部门ID(用来关联)
);
二、插入测试数据
bash
-- 部门:技术部、产品部、运营部
INSERT INTO bumen VALUES
(1, '技术部'),
(2, '产品部'),
(3, '运营部');
-- 员工
INSERT INTO yuangong VALUES
(101, '张三', 1), -- 技术部
(102, '李四', 1), -- 技术部
(103, '王五', 2), -- 产品部
(104, '赵六', NULL); -- 没有部门
数据情况:
- bumen: 1 技术、2 产品、3 运营
- yuangong: 张三、李四、王五(有部门),赵六(无部门)
三、7 种多表查询
交叉连接 CROSS JOIN
两张表所有行两两组合,不看任何关联条件,叫笛卡尔积。
语法
语法介绍
- 不需要 ON 条件
- 结果行数 = 表 1 行数 × 表 2 行数
- 实际开发几乎不用,容易产生巨量数据
bash
SELECT 列名
FROM 表1
CROSS JOIN 表2;
完整SQL
bash
SELECT *
FROM bumen
CROSS JOIN yuangong;
结果:3 部门 × 4 员工 = 12 条数据
实际开发极少用。
内连接 INNER JOIN
只显示两边表能匹配上的数据(交集)。
部门存在、员工也归属这个部门,才显示。
语法
语法介绍
bash
INNER JOIN :内连接关键字
ON :必须写关联条件
只保留两边都存在的数据
完整SQL
bash
SELECT *
FROM bumen
INNER JOIN yuangong
ON bumen.bumen_id = yuangong.bumen_id;
结果:
- 张三、李四、王五 显示
- 赵六(无部门)、运营部(无人)都不显示
左连接 LEFT JOIN
左边表(bumen)全部保留
右边表(yuangong)能匹配就显示,不能匹配显示 NULL
语法
bash
LEFT JOIN = 左表全部保留
ON 关联条件必须写
左表数据一条都不会少
bash
SELECT 列名
FROM 表1
LEFT JOIN 表2
ON 表1.关联字段 = 表2.关联字段;
sql
bash
SELECT *
FROM bumen
LEFT JOIN yuangong
ON bumen.bumen_id = yuangong.bumen_id;
结果:
- 技术部、产品部、运营部 全部显示
- 运营部没有员工 → 员工部分为 NULL
右连接 RIGHT JOIN
右边表(yuangong)全部保留
左边表(bumen)能匹配就显示,不能匹配显示 NULL
语法
bash
RIGHT JOIN = 右表全部保留
右表数据一条都不会少
bash
SELECT 列名
FROM 表1
RIGHT JOIN 表2
ON 表1.关联字段 = 表2.关联字段;
sql
bash
SELECT *
FROM bumen
RIGHT JOIN yuangong
ON bumen.bumen_id = yuangong.bumen_id;
结果:
- 张三、李四、王五、赵六 全部显示
- 赵六没有部门 → 部门部分为 NULL
全连接 FULL JOIN(MySQL 模拟)
左边全部 + 右边全部,一条数据都不丢(并集)
MySQL 不支持直接 FULL JOIN,用 LEFT JOIN + UNION + RIGHT JOIN 实现
语法
bash
UNION :合并两个查询结果,自动去重
最终结果:所有部门 + 所有员工,一个不丢
SQL
bash
SELECT * FROM bumen LEFT JOIN yuangong ON bumen.bumen_id = yuangong.bumen_id
UNION
SELECT * FROM bumen RIGHT JOIN yuangong ON bumen.bumen_id = yuangong.bumen_id;
结果:
- 所有部门 + 所有员工,全部显示,缺的部分为 NULL
自连接 SELF JOIN
一张表自己连接自己,把同一张表当两张表用
常用于:员工 - 领导、分类 - 父分类
语法
- 同一张表:yuangong e 、yuangong l
- 必须起不同别名(e 员工,l 领导)
- 本质还是 JOIN,只是表是同一张
bash
SELECT 别名1.列名, 别名2.列名
FROM 表名 别名1
JOIN 表名 别名2
ON 别名1.字段 = 别名2.字段;
先加领导字段:
bash
# 给员工表增加 leader_id 列,记录直属领导的员工ID
ALTER TABLE yuangong ADD leader_id INT;
# 把李四(102)的领导设为张三(101)
UPDATE yuangong SET leader_id = 101 WHERE yuangong_id = 102;
含义:张三是李四的领导
查询:员工姓名 + 领导姓名
bash
SELECT
e.name AS 员工,
l.name AS 领导
FROM yuangong e
LEFT JOIN yuangong l
ON e.leader_id = l.yuangong_id;
结果:李四 → 领导张三
联合查询 UNION / UNION ALL
不是左右连接,是上下拼接结果
要求:列数相同、类型对应
- UNION:去重
- UNION ALL:不去重,速度更快
语法
bash
UNION :合并结果,自动去重
UNION ALL :合并结果,不去重,速度更快
字段数量必须一样
bash
查询1
UNION
查询2
示例:把部门名和员工名合并成一列展示
bash
# 把部门表的部门名取出来,别名 name
SELECT bumen_name AS name FROM bumen
UNION
# 上下拼接员工表的员工名
SELECT name FROM yuangong;
结果:
技术部、产品部、运营部、张三、李四、王五、赵六
(上下排成一列)
四、一句话终极总结(必背)
- CROSS JOIN:全组合,笛卡尔积
- INNER JOIN:两边匹配才显示(交集)
- LEFT JOIN:左表全保留
- RIGHT JOIN:右表全保留
- FULL JOIN:左右都保留(并集)
- SELF JOIN:自己连自己(层级关系)
- UNION:结果上下拼接
MySQL多表查询详解(王者荣耀实战案例)
一、准备工作:创建测试库 & 表 & 测试数据
我们用王者荣耀的真实业务场景,设计 4 张核心表,覆盖玩家、英雄、战绩、皮肤 4 个维度,完美适配多表查询的各种场景。
- 创建测试数据库
bash
-- 创建王者荣耀测试库,字符集用utf8mb4支持全字符
CREATE DATABASE IF NOT EXISTS wzry_test DEFAULT CHARACTER SET utf8mb4;
USE wzry_test;
- 创建 4 张测试表
bash
-- 1. 英雄表:存储所有英雄的基础信息
CREATE TABLE IF NOT EXISTS yingxiong (
yingxiong_id INT PRIMARY KEY AUTO_INCREMENT,
yingxiong_ming VARCHAR(50) NOT NULL COMMENT '英雄名',
zhiye VARCHAR(20) NOT NULL COMMENT '职业:刺客/法师/射手/辅助',
fenlu VARCHAR(20) NOT NULL COMMENT '分路:打野/中路/下路/游走'
) COMMENT '英雄表';
-- 2. 玩家表:存储玩家信息,包含邀请人字段(用于自连接案例)
CREATE TABLE IF NOT EXISTS wanjia (
wanjia_id INT PRIMARY KEY AUTO_INCREMENT,
wanjia_nicheng VARCHAR(50) NOT NULL COMMENT '玩家昵称',
duanwei VARCHAR(20) NOT NULL COMMENT '段位:青铜/星耀/王者',
yaoqingren_id INT COMMENT '邀请该玩家的人ID(关联自身玩家表)'
) COMMENT '玩家表';
-- 3. 皮肤表:存储英雄的皮肤信息,关联英雄表
CREATE TABLE IF NOT EXISTS pifu (
pifu_id INT PRIMARY KEY AUTO_INCREMENT,
yingxiong_id INT NOT NULL COMMENT '所属英雄ID',
pifu_ming VARCHAR(50) NOT NULL COMMENT '皮肤名',
jiage INT NOT NULL COMMENT '皮肤价格(点券)',
FOREIGN KEY (yingxiong_id) REFERENCES yingxiong(yingxiong_id)
) COMMENT '皮肤表';
-- 4. 战绩表:中间表,关联玩家和英雄,记录玩家用该英雄的对战数据
CREATE TABLE IF NOT EXISTS zhanji (
zhanji_id INT PRIMARY KEY AUTO_INCREMENT,
wanjia_id INT NOT NULL COMMENT '玩家ID',
yingxiong_id INT NOT NULL COMMENT '使用的英雄ID',
shenglv DECIMAL(4,1) NOT NULL COMMENT '胜率',
zongchangci INT NOT NULL COMMENT '总场次',
mvp_cishu INT NOT NULL COMMENT 'MVP次数',
FOREIGN KEY (wanjia_id) REFERENCES wanjia(wanjia_id),
FOREIGN KEY (yingxiong_id) REFERENCES yingxiong(yingxiong_id)
) COMMENT '对战战绩表';
- 插入王者荣耀测试数据
bash
-- 插入英雄数据
INSERT INTO yingxiong (yingxiong_ming, zhiye, fenlu) VALUES
('韩信', '刺客', '打野'),
('李白', '刺客', '打野'),
('妲己', '法师', '中路'),
('鲁班七号', '射手', '下路'),
('蔡文姬', '辅助', '游走'),
('澜', '刺客', '打野'),
('暃', '刺客', '打野'); -- 新出的英雄,暂时没人用
-- 插入玩家数据
INSERT INTO wanjia (wanjia_nicheng, duanwei, yaoqingren_id) VALUES
('国服韩信', '王者', NULL),
('野王妹妹', '星耀', 1),
('菜鸡互啄', '青铜', 2),
('新玩家小A', '青铜', NULL), -- 新玩家,还没打过任何战绩
('法王妲己', '王者', 1);
-- 插入皮肤数据
INSERT INTO pifu (yingxiong_id, pifu_ming, jiage) VALUES
(1, '街头霸王', 888),
(1, '白龙吟', 1188),
(2, '凤求凰', 1788),
(3, '魅力维加斯', 0),
(4, '电玩小子', 2888);
-- 插入战绩数据
INSERT INTO zhanji (wanjia_id, yingxiong_id, shenglv, zongchangci, mvp_cishu)
VALUES
(1, 1, 68.5, 1200, 450), -- 国服韩信玩韩信
(1, 2, 55.2, 300, 80), -- 国服韩信玩李白
(2, 1, 62.3, 500, 180), -- 野王妹妹玩韩信
(2, 6, 58.1, 400, 150), -- 野王妹妹玩澜
(5, 3, 72.8, 800, 320), -- 法王妲己玩妲己
(3, 4, 42.5, 200, 20); -- 菜鸡玩鲁班
二、MySQL外键关联详解(王者荣耀实战版)
外键(FOREIGN KEY)是多表关联的核心,也是保证数据完整性的关键,结合我们上面的王者荣耀4张表。
- 外键核心概念
外键是一张表中的字段,用来关联另一张表的主键,相当于两张表之间的"桥梁",目的是让两张表的数据产生关联,避免出现"无主数据"(比如没有对应英雄的皮肤、没有对应玩家的战绩)。
核心对应关系(结合我们的表):
- 皮肤表(pifu)的 yingxiong_id → 关联 → 英雄表(yingxiong)的 yingxiong_id(主键):皮肤必须属于某一个已存在的英雄
- 战绩表(zhanji)的 wanjia_id → 关联 → 玩家表(wanjia)的 wanjia_id(主键):战绩必须属于某一个已存在的玩家
- 战绩表(zhanji)的 yingxiong_id → 关联 → 英雄表(yingxiong)的 yingxiong_id(主键):战绩必须对应某一个已存在的英雄
简单说:外键就是"约束",约束当前表的字段值,必须在另一张表的主键中存在,不能乱填、不能填不存在的值。
- 外键的创建语法
外键创建分两种:建表时创建(最常用)、建表后添加,我们结合皮肤表、战绩表的案例,逐个讲解。
(1)建表时创建外键(推荐)
语法格式:FOREIGN KEY (当前表外键字段) REFERENCES 关联表名(关联表主键字段)
案例:皮肤表建表时,给yingxiong_id添加外键,关联英雄表的yingxiong_id-- 皮肤表完整建表语句(含外键)
bash
CREATE TABLE IF NOT EXISTS pifu (
pifu_id INT PRIMARY KEY AUTO_INCREMENT,
yingxiong_id INT NOT NULL COMMENT '所属英雄ID', -- 外键字段
pifu_ming VARCHAR(50) NOT NULL COMMENT '皮肤名',
jiage INT NOT NULL COMMENT '皮肤价格(点券)',
-- 外键关联:pifu.yingxiong_id 关联 yingxiong.yingxiong_id
FOREIGN KEY (yingxiong_id) REFERENCES yingxiong(yingxiong_id)
) COMMENT '皮肤表';
说明:这行外键代码,就相当于给皮肤表的 yingxiong_id 加了"规矩"------只能填英雄表中已经存在的 yingxiong_id 值。
(2)建表后添加外键(适合后期修改表结构)
语法格式:ALTER TABLE 当前表名 ADD FOREIGN KEY (外键字段) REFERENCES 关联表名(关联表主键);
案例:给玩家表的yaoqingren_id添加外键,关联玩家表自身的wanjia_id(自关联外键)-- 给wanjia表的yaoqingren_id添加外键,关联wanjia.wanjia_id(邀请人也是玩家)
bash
ALTER TABLE wanjia
ADD FOREIGN KEY (yaoqingren_id) REFERENCES wanjia(wanjia_id);
-- 验证:此时yaoqingren_id的值,只能填wanjia表中已存在的wanjia_id,或NULL(没有邀请人)
- 外键的核心作用
外键的核心是"保证数据完整性",主要体现在两个方面,我们用王者荣耀案例实际验证。
作用1:禁止插入"无主数据"(最核心)
bash
-- 错误案例:插入一个不存在英雄的皮肤(yingxiong_id=100,英雄表没有yingxiong_id=100的英雄)
INSERT INTO pifu (yingxiong_id, pifu_ming, jiage) VALUES (100, '测试皮肤', 688);
运行结果:报错(提示"Cannot add or update a child row: a foreign key constraint fails"),意思是"不能插入,外键约束失败"。
原因:yingxiong_id=100 在英雄表(yingxiong)中不存在,违反外键约束,避免出现"没有对应英雄的孤儿皮肤"。
作用2:禁止删除"被关联的数据"
bash
-- 错误案例:删除有皮肤的英雄(韩信yingxiong_id=1,有2个皮肤关联它)
DELETE FROM yingxiong WHERE yingxiong_id=1;
运行结果:报错,因为韩信(yingxiong_id=1)被皮肤表的多个皮肤关联,删除韩信后,这些皮肤就变成"无主皮肤",外键约束会阻止删除。
正确操作:先删除关联的皮肤,再删除英雄,或解除外键约束后删除。
- 外键的约束模式
默认情况下,外键是"严格约束"(不能删除被关联数据、不能插入无效数据),但实际开发中,我们可以根据需求设置约束模式,常用2种:ON DELETE CASCADE、ON DELETE SET NULL。
说明:为避免影响前面创建的4张核心表及后续实验,以下两个约束模式案例,均创建全新的测试表,独立运行、不干扰原有数据。
(1)ON DELETE CASCADE:级联删除(常用)
含义:当关联表的主键数据被删除时,当前表中关联的外键数据也会自动删除。
案例:创建全新测试表(英雄表_级联、皮肤表_级联),测试级联删除
bash
-- 1. 创建全新关联表(英雄表_级联),作为主表
CREATE TABLE IF NOT EXISTS yingxiong_jilian (
yingxiong_id INT PRIMARY KEY AUTO_INCREMENT,
yingxiong_ming VARCHAR(50) NOT NULL COMMENT '英雄名'
) COMMENT '英雄表_级联(用于测试级联删除)';
-- 2. 创建全新关联表(皮肤表_级联),作为从表,设置级联删除
CREATE TABLE IF NOT EXISTS pifu_jilian (
pifu_id INT PRIMARY KEY AUTO_INCREMENT,
yingxiong_id INT NOT NULL COMMENT '所属英雄ID',
pifu_ming VARCHAR(50) NOT NULL COMMENT '皮肤名',
-- 级联删除:删除主表(英雄表_级联)的英雄时,自动删除从表对应皮肤
FOREIGN KEY (yingxiong_id) REFERENCES yingxiong_jilian(yingxiong_id) ON DELETE CASCADE
) COMMENT '皮肤表_级联(用于测试级联删除)';
-- 3. 插入测试数据
INSERT INTO yingxiong_jilian (yingxiong_ming) VALUES ('韩信'), ('李白');
INSERT INTO pifu_jilian (yingxiong_id, pifu_ming) VALUES (1, '街头霸王'), (2, '凤求凰');
-- 4. 测试级联删除:删除主表的韩信(yingxiong_id=1)
DELETE FROM yingxiong_jilian WHERE yingxiong_id=1;
-- 5. 验证结果:韩信对应的皮肤会被自动删除
SELECT * FROM pifu_jilian; -- 仅显示李白的凤求凰,韩信的皮肤已被删除
(2)ON DELETE SET NULL:置空(常用)
含义:当关联表的主键数据被删除时,当前表中关联的外键数据会自动设为NULL(注意:外键字段必须允许为NULL)。
案例:创建全新测试表(玩家表_置空),测试置空约束
bash
-- 1. 创建全新测试表(玩家表_置空),自关联设置置空约束
CREATE TABLE IF NOT EXISTS wanjia_zhikong (
wanjia_id INT PRIMARY KEY AUTO_INCREMENT,
wanjia_nicheng VARCHAR(50) NOT NULL COMMENT '玩家昵称',
yaoqingren_id INT COMMENT '邀请人ID(允许为NULL,用于测试置空)',
-- 置空约束:删除邀请人(主数据)时,被邀请人的yaoqingren_id自动设为NULL
FOREIGN KEY (yaoqingren_id) REFERENCES wanjia_zhikong(wanjia_id) ON DELETE SET NULL
) COMMENT '玩家表_置空(用于测试置空约束)';
-- 2. 插入测试数据
INSERT INTO wanjia_zhikong (wanjia_nicheng, yaoqingren_id) VALUES
('国服韩信', NULL),
('野王妹妹', 1), -- 邀请人是国服韩信(wanjia_id=1)
('菜鸡互啄', 2); -- 邀请人是野王妹妹(wanjia_id=2)
-- 3. 测试置空约束:删除邀请人(国服韩信,wanjia_id=1)
DELETE FROM wanjia_zhikong WHERE wanjia_id=1;
-- 4. 验证结果:野王妹妹的yaoqingren_id自动变为NULL
SELECT * FROM wanjia_zhikong; -- 野王妹妹的yaoqingren_id显示NULL,菜鸡互啄的不变
- 外键的删除
如果不需要外键约束了,可以删除外键,语法格式:ALTER TABLE 表名 DROP FOREIGN KEY 外键名;
bash
-- 1. 查看wanjia_zhikong表的外键名(MySQL自动生成,通过以下语句查询)
SHOW CREATE TABLE wanjia_zhikong; -- 查看表结构,找到外键名(如:wanjia_zhikong_ibfk_1)
-- 2. 删除外键(替换外键名为查询到的名称,示例为wanjia_zhikong_ibfk_1)
ALTER TABLE wanjia_zhikong DROP FOREIGN KEY wanjia_zhikong_ibfk_1;
-- 验证:删除外键后,置空约束失效,可删除被关联的邀请人,且被邀请人的yaoqingren_id不会自动置空
-- 插入测试数据用于验证
INSERT INTO wanjia_zhikong (wanjia_nicheng, yaoqingren_id) VALUES
('上单老高', NULL),
('野王小帅', 2);
-- 删除邀请人(野王妹妹,wanjia_id=2)
DELETE FROM wanjia_zhikong WHERE wanjia_id=2;
-- 查看结果:野王小帅的yaoqingren_id仍为2(未置空),说明外键已删除、约束失效
SELECT * FROM wanjia_zhikong;
补充:测试完成后,可执行以下语句删除测试表,避免占用空间(不影响原有4张核心表):
bash
-- 删除约束模式测试用的临时表
DROP TABLE IF EXISTS pifu_jilian, yingxiong_jilian, wanjia_zhikong;
-
外键的注意事项(必记)
-
外键字段的数据类型,必须和关联的主键字段完全一致(比如yingxiong.yingxiong_id是INT,pifu.yingxiong_id也必须是INT),否则无法创建外键。
-
关联的表必须是InnoDB引擎(MySQL默认引擎),MyISAM引擎不支持外键。
-
外键字段可以允许为NULL(如玩家表的yaoqingren_id),但如果设置为NOT NULL,就必须填写关联表中存在的主键值。
-
外键是"表级约束",只影响数据的插入、删除、更新,不影响查询(多表查询的关联的是字段,和外键约束本身无关,但外键保证了关联数据的有效性)。
-
不要滥用外键:小项目、数据量小的场景可以用外键保证完整性;大数据量、高并发场景,建议不用外键(会降低效率),用程序逻辑控制数据关联。
三、多表查询核心类型 & 实战案例
多表查询的核心:把分散在多张表的数据,通过关联字段拼接成你需要的完整信息,下面逐个拆解所有常用类型。
- 交叉连接(CROSS JOIN):笛卡尔积
概念
最基础的连接,会把左表的每一行,和右表的所有行做组合,产生笛卡尔积,一般很少直接用,因为会产生大量无效数据。
案例:玩家和英雄的全组合
bash
# wj 为玩家表别名,yx 为英雄表别名,CROSS JOIN 两两组合
SELECT wj.wanjia_nicheng, yx.yingxiong_ming
FROM wanjia wj
CROSS JOIN yingxiong yx;
结果说明
5 个玩家 × 7 个英雄 = 35 行结果,大部分都是无效的(比如玩家根本没玩过这个英雄),所以交叉连接必须加过滤条件,否则数据量会爆炸。
- 内连接(INNER JOIN):只查匹配数据
概念
最常用的连接,只返回两张表中,关联字段能匹配上的数据,匹配不上的会被过滤掉。
案例:查询所有有对战记录的玩家 & 英雄战绩
bash
SELECT
wj.wanjia_nicheng AS 玩家昵称,
yx.yingxiong_ming AS 使用英雄,
zj.shenglv AS 胜率,
zj.zongchangci AS 总场次
FROM wanjia wj
-- 玩家表 关联 战绩表:玩家ID匹配
INNER JOIN zhanji zj ON wj.wanjia_id = zj.wanjia_id
-- 战绩表 关联 英雄表:英雄ID匹配
INNER JOIN yingxiong yx ON zj.yingxiong_id = yx.yingxiong_id;
查询结果
| 玩家昵称 | 使用英雄 | 胜率 | 总场次 |
|---|---|---|---|
| 国服韩信 | 韩信 | 68.5 | 1200 |
| 国服韩信 | 李白 | 55.2 | 300 |
| 野王妹妹 | 韩信 | 62.3 | 500 |
| 野王妹妹 | 澜 | 58.1 | 400 |
| 菜鸡互啄 | 鲁班七号 | 42.5 | 200 |
| 法王妲己 | 妲己 | 72.8 | 800 |
注意:新玩家新玩家小A 没有出现在结果里!因为他没有战绩,和战绩表匹配不上,被内连接过滤掉了。
- 左连接(LEFT JOIN):保留左表全部数据
概念
左表的所有行全部保留,右表只返回匹配上的数据,匹配不上的显示 NULL。
案例:查询所有玩家,哪怕没打过战绩也要显示
bash
SELECT
wj.wanjia_nicheng AS 玩家昵称,
yx.yingxiong_ming AS 使用英雄,
zj.shenglv AS 胜率,
zj.zongchangci AS 总场次
FROM wanjia wj
-- 左连接:玩家表是左表,所有玩家都要保留
LEFT JOIN zhanji zj ON wj.wanjia_id = zj.wanjia_id
LEFT JOIN yingxiong yx ON zj.yingxiong_id = yx.yingxiong_id;
查询结果
| 玩家昵称 | 使用英雄 | 胜率 | 总场次 |
|---|---|---|---|
| 国服韩信 | 韩信 | 68.5 | 1200 |
| 国服韩信 | 李白 | 55.2 | 300 |
| 野王妹妹 | 韩信 | 62.3 | 500 |
| 野王妹妹 | 澜 | 58.1 | 400 |
| 菜鸡互啄 | 鲁班七号 | 42.5 | 200 |
| 法王妲己 | 妲己 | 72.8 | 800 |
| 新玩家小 A | NULL | NULL | NULL |
新玩家出现在结果里了!他没有战绩,所以右表的字段全部是 NULL,完美保留了左表的所有数据。
- 右连接(RIGHT JOIN):保留右表全部数据
概念
和左连接相反,右表的所有行全部保留,左表只返回匹配上的数据,匹配不上的显示 NULL。
案例:查询所有英雄,哪怕没人用过也要显示
bash
SELECT
wj.wanjia_nicheng AS 玩家昵称,
yx.yingxiong_ming AS 英雄名,
zj.shenglv AS 胜率
FROM wanjia wj
RIGHT JOIN zhanji zj ON wj.wanjia_id = zj.wanjia_id
-- 右连接:英雄表是右表,所有英雄都要保留
RIGHT JOIN yingxiong yx ON zj.yingxiong_id = yx.yingxiong_id;
查询结果
| 玩家昵称 | 英雄名 | 胜率 |
|---|---|---|
| 国服韩信 | 韩信 | 68.5 |
| 国服韩信 | 李白 | 55.2 |
| 法王妲己 | 妲己 | 72.8 |
| 菜鸡互啄 | 鲁班七号 | 42.5 |
| NULL | 蔡文姬 | NULL |
| 野王妹妹 | 澜 | 58.1 |
| NULL | 暃 | NULL |
新英雄暃和没人用的蔡文姬都出现在结果里了!没人用他们,所以玩家和胜率字段都是 NULL。
- 全连接(FULL JOIN):保留所有表全部数据
概念
把左表和右表的所有行全部保留,不管有没有匹配上。
注意:MySQL 不支持直接写FULL JOIN ,我们用LEFT JOIN + UNION + RIGHT JOIN 来实现。
案例:查询所有玩家 + 所有英雄,不管有没有对战记录
bash
-- 左连接结果
SELECT wj.wanjia_nicheng, yx.yingxiong_ming
FROM wanjia wj
LEFT JOIN zhanji zj ON wj.wanjia_id = zj.wanjia_id
LEFT JOIN yingxiong yx ON zj.yingxiong_id = yx.yingxiong_id
UNION -- 合并去重
-- 右连接结果
SELECT wj.wanjia_nicheng, yx.yingxiong_ming
FROM wanjia wj
RIGHT JOIN zhanji zj ON wj.wanjia_id = zj.wanjia_id
RIGHT JOIN yingxiong yx ON zj.yingxiong_id = yx.yingxiong_id;
结果说明
结果会包含:
- 所有有战绩的玩家 + 英雄
- 没有战绩的新玩家
- 没人用的新英雄蔡文姬、暃
所有数据全部保留,没有遗漏。
- 自连接(SELF JOIN):自己连自己
概念
把同一张表,当成两张表来连接,用来处理表内的关联关系(比如邀请人、上下级这种自己关联自己的场景)。
案例:查询每个玩家,以及他的邀请人是谁
bash
SELECT
u.wanjia_nicheng AS 玩家昵称,
inviter.wanjia_nicheng AS 邀请人昵称
FROM wanjia u
-- 玩家表自己连自己:u是当前玩家,inviter是邀请人
LEFT JOIN wanjia inviter ON u.yaoqingren_id = inviter.wanjia_id;
查询结果
| 玩家昵称 | 邀请人昵称 |
|---|---|
| 国服韩信 | NULL |
| 野王妹妹 | 国服韩信 |
| 菜鸡互啄 | 野王妹妹 |
| 新玩家小 A | NULL |
| 法王妲己 | 国服韩信 |
完美!我们一眼就能看到:野王妹妹是国服韩信邀请的,菜鸡是野王妹妹邀请的,太清晰了。
- 联合查询(UNION/UNION ALL):合并多个结果集
概念
把多个 SELECT 查询的结果,合并成一个结果集。
bash
UNION :自动去重,效率稍低
UNION ALL :不做去重,直接合并,效率更高,优先用这个
案例:查询所有高胜率和低胜率的英雄,合并成一个结果
bash
-- 查胜率>70%的高胜率英雄
SELECT yx.yingxiong_ming, '高胜率英雄' AS 类型, zj.shenglv
FROM zhanji zj
JOIN yingxiong yx ON zj.yingxiong_id = yx.yingxiong_id
WHERE zj.shenglv > 70
UNION ALL
-- 查胜率<45%的低胜率英雄
SELECT yx.yingxiong_ming, '低胜率英雄' AS 类型, zj.shenglv
FROM zhanji zj
JOIN yingxiong yx ON zj.yingxiong_id = yx.yingxiong_id
WHERE zj.shenglv < 45;
查询结果
| 名字 | 类型 | 胜率 |
|---|---|---|
| 妲己 | 高胜率英雄 | 72.8 |
| 鲁班七号 | 低胜率英雄 | 42.5 |
四、多表查询注意事项
- 必须加关联条件:如果忘记加,会产生笛卡尔积,数据量会指数级爆炸。
- 优先用 UNION ALL:除非你需要去重,否则用 UNION ALL,效率比 UNION 高很多。
- 关联字段加索引:关联的字段(比如 wanjia_id、yingxiong_id)一定要建索引,否则大数据量下查询会很慢。
- 注意 NULL 值:左 / 右连接会产生 NULL 值,写 WHERE 条件的时候要注意,不要误把 NULL 过滤掉。
- 表别名简化 SQL:给表起短别名(比如 wj、yx、zj),可以大幅简化 SQL,提高可读性。
MySQL用户管理
MySQL服务的账户是独立存在的,只用于MySQL服务的登录验证。
虚拟用户:给服务和应用使用的用户账号。
系统用户:Linux系统使用的用户账号
在MySQL服务中,用户组成包括用户名,主机,密码等。
Host指主机,表示只有在该主机上,才能使用对应的账号连接MySQL服务器,主机限制了账号可以登录的位置。用户名可以相同,主机也可以相同,用户名和主机组合起来才能标识一个唯一用户。
其它数据库系统,例如SQLServer,Oracle等都没有此限制,只要账号和密码能校验通过即可登录。这也是MySQL与其它数据库系统的一个不同之处。
Host可以写成主机名,IP地址,网段。可以用%,来表示通配符,%表示任意长度的任意字符,表示一个字符。
范例:
bash
#主机名
gqd@'mysql.laogao.cloud'
gqd@'localhost'
#IP地址
gqd@'10.0.0.110'
gqd@'172.16.10.110'
#网段
gqd@′10.0.0.0/255.255.0.0'
gqd@′172.16.10.0/255.255.255.0'
#通配符
gqd@′10.0.%.%
gqd@'172.16.%.%'
MySQL8.0中默认没有可以远程登陆的用户
bash
# 切换到系统库 mysql
mysql> use mysql;
#前三个是MySQL服务自身使用
# 查询用户表中的用户名和主机
mysql> select User,Host from user;
+------------------+-----------+
| User | Host |
+------------------+-----------+
| mysql.infoschema | localhost |
| mysql.session | localhost |
| mysql.sys | localhost |
| root | localhost |
+------------------+-----------+
4 rows in set (0.00 sec)
#现在使用的是第四个
# user() 函数查看当前登录账号@主机
mysql> select user();
+----------------+
| user() |
+----------------+
| root@localhost |
+----------------+
1 row in set (0.00 sec)
#也可以用status命令来查看
mysql> status
--------------
mysql Ver 8.0.26 for Linux on x86_64 (Source distribution)
Connection id: 9
Current database: mysql
Current user: root@localhost
SSL: Not in use
Current pager: stdout
Using outfile: ''
Using delimiter: ;
Server version: 8.0.26 Source distribution
Protocol version: 10
Connection: Localhost via UNIX socket
Server characterset: utf8mb4
Db characterset: utf8mb4
Client characterset: utf8mb4
Conn. characterset: utf8mb4
UNIX socket: /var/lib/mysql/mysql.sock
Binary data as: Hexadecimal
Uptime: 38 min 22 sec
Threads: 2 Questions: 93 Slow queries: 0 Opens: 199 Flush tables: 3 Open
tables: 118 Queries per second avg: 0.040
--------------
#无法在远程主机上连接当前主机的MySQL服务
#192.168.108.128是mysql主机ip地址,自己ip -br a检测
#本地PC打开CMD 远程过来(192.168.108.1)
C:\Users\69466>mysql -uroot -h192.168.108.128 -phuawei
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 1130 (HY000): Host '192.168.108.1' is not allowed to connect to this MySQL
server
创建用户:CREATE USER
bash
#格式
CREATE USER 'USERNAME'@'HOST' [IDENTIFIED BY 'password'];
#范例:创建来自 192.168.108.0/24 网段的 test 用户,密码 123456
create user test@'192.168.108.0/255.255.255.0' identified by '123456';
# 创建 test2 用户,允许 192.168.108 网段任意主机登录
create user test2@'192.168.108.%' identified by '123456';
重命名用户:RENAME USER
bash
# RENAME USER 旧账号 TO 新账号
RENAME USER 'USERNAME'@'HOST' TO 'USERNAME'@'HOST';
删除用户:DROP USER
bash
DROP USER 'USERNAME'@'HOST'
#范例,删除gqd
DROP user test@'192.168.108.0/255.255.255.0'
DROP USER test2@'192.168.108.0.%';
修改密码
新版mysql中用户密码可以保存在mysql.user表的 authentication_string字段中,己经取消了password字段。
mariadb中某些版本 authentication_string,password字段共存,旧版以password字段为准,新版以authentication_string为准。
bash
#方式一:SET PASSWORD 直接给指定用户设置新密码
SET PASSWORD FOR 'user'@'host' = 'password';
#mysql8.0中取消了PASSWORD方法
mysql> select PASSWORD('123456');
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
'('123456')' at line 1
#MariaDB中还有
#在MYSQL8.0中可以使用此写法
#MYSQL8.0中的密码是放在 mysql.user 表中 authentication_string 字段中,但MariaDB中还保留了PASSWORD字段
mysql> select User,Host,authentication_string FROM mysql.user;
+------------------+-----------+-------------------------------------------------
-----------------------+
| User | Host | authentication_string
|
+------------------+-----------+-------------------------------------------------
-----------------------+
| mysql.infoschema | localhost |
$A$005$THISISACOMBINATIONOFINVALIDSALTANDPASSWORDTHATMUSTNEVERBRBEUSED |
| mysql.session | localhost |
$A$005$THISISACOMBINATIONOFINVALIDSALTANDPASSWORDTHATMUSTNEVERBRBEUSED |
| mysql.sys | localhost |
$A$005$THISISACOMBINATIONOFINVALIDSALTANDPASSWORDTHATMUSTNEVERBRBEUSED |
| root | localhost |
|
+------------------+-----------+-------------------------------------------------
-----------------------+
4 rows in set (0.00 sec)
#更新密码
#方式一:
mysql> set password for root@'localhost'='123456';
Query OK, 0 rows affected (0.00 sec)
mysql> select User,Host,authentication_string FROM mysql.user;
+------------------+-----------+-------------------------------------------------
-----------------------+
| User | Host | authentication_string
|
+------------------+-----------+-------------------------------------------------
-----------------------+
| mysql.infoschema | localhost |
$A$005$THISISACOMBINATIONOFINVALIDSALTANDPASSWORDTHATMUSTNEVERBRBEUSED |
| mysql.session | localhost |
$A$005$THISISACOMBINATIONOFINVALIDSALTANDPASSWORDTHATMUSTNEVERBRBEUSED |
| mysql.sys | localhost |
$A$005$THISISACOMBINATIONOFINVALIDSALTANDPASSWORDTHATMUSTNEVERBRBEUSED |
| root | localhost | *6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9
|
+------------------+-----------+-------------------------------------------------
-----------------------+
4 rows in set (0.00 sec)
#方式二
语法:ALTER USER test@'%' IDENTIFIED BY '123456';
#此方法通用:ALTER USER 修改 root 的密码
mysql> ALTER USER root@'localhost' IDENTIFIED BY '123456';
Query OK, 0 rows affected (0.00 sec)
#测试:用新密码 123456 登录
[root@localhost ~]# mysql -uroot -p123456
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 16
Server version: 8.0.26 Source distribution
Copyright (c) 2000, 2021, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
#方法三:mysqladmin 命令行改密,把当前密码 123456 改成 abcde
[root@localhost ~]# mysqladmin -uroot -p123456 password abcde
mysqladmin: [Warning] Using a password on the command line interface can be
insecure.
Warning: Since password will be sent to server in plain text, use ssl connection
to ensure password safety.
# 用新密码 abcde 登录验证
[root@localhost ~]# mysql -uroot -pabcde
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 19
Server version: 8.0.26 Source distribution
Copyright (c) 2000, 2021, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
忘记密码
bash
#方式一,保留原有数据
#1 启动时添加指定项
--skip-grant-tables
--skip-networking
#2 使用UPDATE命令修改管理员密码
#3 移除配置项重启
#方式一范例:在配置文件中加跳过授权表参数
[root@localhost ~]# vim /etc/my.cnf.d/mysql-server.cnf
[mysqld]
skip-grant-tables
skip-networking #MYSQL8.0不需要
# 重启 MySQL 使参数生效,之后可免密登录
[root@localhost ~]# systemctl restart mysqld.service
[root@localhost ~]# mysql
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 7
Server version: 8.0.26 Source distribution
Copyright (c) 2000, 2021, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
#步骤1:把 root 的密码字段清空
mysql> update mysql.user set authentication_string='' where user='root' and
host='localhost';
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
#步骤2:刷新权限表使其生效
mysql> flush privileges;
Query OK, 0 rows affected (0.01 sec)
#再执行下面命令:重新给 root 设置新密码 xiaomi
mysql> alter user root@'localhost' identified by 'xiaomi';
Query OK, 0 rows affected (0.00 sec)
# 编辑配置文件,注释掉 skip-grant-tables,恢复正常认证
[root@localhost ~]# vim /etc/my.cnf.d/mysql-server.cnf
[mysqld]
#pid-file=/run/mysqld/mysqld.pid
#skip-grant-tables
# 用新密码 xiaomi 登录验证
[root@localhost ~]# mysql -uroot -pxiaomi
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 9
Server version: 8.0.26 Source distribution
Copyright (c) 2000, 2021, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
范例:删库跑路之清空root密码方法
!!!学完就忘
bash
#方式二,会清除所有数据
#停止服务
[root@localhost ~]# systemctl stop mysqld.service
#删除数据目录下所有内容
[root@localhost ~]# rm -rf /var/lib/mysql/*
#重启服务,恢复空密码登陆
[root@localhost ~]# systemctl start mysqld.service
[root@localhost ~]# mysql
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.26 Source distribution
Copyright (c) 2000, 2021, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
在当前MYSQL服务中添加用户
bash
mysql> use mysql;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
# 创建允许远程客户端 192.168.108.1 登录的 root,密码 123456
mysql> create user root@'192.168.108.1' identified by '123456'; #需要远程连接本
mysql的客户端地址
Query OK, 0 rows affected (0.00 sec)
mysql> select User,Host from mysql.user;
+------------------+---------------+
| User | Host |
+------------------+---------------+
| root | 192.168.108.1 |
| mysql.infoschema | localhost |
| mysql.session | localhost |
| mysql.sys | localhost |
| root | localhost |
+------------------+---------------+
5 rows in set (0.00 sec)
到192.168.108.1(笔记本)操作

bash
#查看当前客户端连接时适用的用户名和主机
mysql> select user();
+--------------------+
| user() |
+--------------------+
| root@192.168.108.1 |
+--------------------+
1 row in set (0.00 sec)
#查看线程:show processlist 列出当前所有连接
mysql> show processlist;
+----+------+---------------------+-------+---------+------+-------+-------------
-----+
| Id | User | Host | db | Command | Time | State | Info
|
+----+------+---------------------+-------+---------+------+-------+-------------
-----+
| 11 | root | localhost | mysql | Sleep | 360 | | NULL
|
| 14 | root | 192.168.108.1:63707 | NULL | Query | 0 | init | show
processlist |
+----+------+---------------------+-------+---------+------+-------+-------------
-----+
2 rows in set (0.00 sec)
#查看数据库:新用户没权限,只能看到 information_schema
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
+--------------------+
1 row in set (0.00 sec)
#没有权限:连 msyql 库都进不去(注意原拼写为 msyql)
mysql> use msyql;
ERROR 1044 (42000): Access denied for user 'root'@'192.168.108.1' to database
'msyql'
# 没有权限创建库
mysql> create database db1;
ERROR 1044 (42000): Access denied for user 'root'@'192.168.108.1' to database
'db1'
权限管理和DCL语句
在MySQL服务中,新创建的用户仅仅只能连接,没有操作权限,需要配置相应的权限后才能使用。
权限类别
管理类
CREATE USER,FILE,SUPER,SHOW DATABASES,RELOAD,SHUTDOWN,REPLICATION SLAVE,REPLICATION CLIENT,LOCK TABLES,PROCESS,CREATE TEMPORARY TABLES
程序类针对FUNCTION、PROCEDURE、TRIGGER
CREATE,ALTER,DROP,EXCUTE
库和表级别针对DATABASE、TABLE
ALTER,CREATE,CREATE VIEW,DROP INDEX,SHOW VIEW,WITH GRANT OPTION(将自己获得的权限转赠给其他用户)
数据操作
SELECT,INSERT,DELETE,UPDATE
字段级别
SELECT(col1,coI2.,...),UPDATE(col1,col2,...),INSERT(col1,col2,...)
所有权限
ALL PRIVILEGES或ALL
授权
格式
bash
mysql> help grant
Name: 'GRANT'
Description:
Syntax:
GRANT
priv_type [(column_list)]
[, priv_type [(column_list)]] ...
ON [object_type] priv_level
TO user_or_role [, user_or_role] ...
[WITH GRANT OPTION]
[AS user
[WITH ROLE
DEFAULT
| NONE
| ALL
| ALL EXCEPT role [, role ] ...
| role [, role ] ...
#priv_type 要授予的权限ALL [PRIVILEGES]
#object_type 对象的类型TABLE|FUNCTION|PROCEDURE
#priv_level 范围
*|*.*|db_name.*|db_name.tbl_name|tbl_name|db_name.routine_name(指定库的函数,存储过程,触发器)
#with_option 选项
#GRANT OPTION 可以将自己的权限授权给其它账号
#MAX_QUERIES_PER_HOUR N 每小时最大查询次数
#MAX_UPDATES_PER_HOUR N 每小时最大更新次数
#MAX_CONNECTIONS_PER_HOUR N 每小时最大连接次数
#MAX_USER_CONNECTIONS N 最大用户连接数
#MAX_USER_CONNECTIONS 指的是瞬间的并发连接数,而MAX_CONNECTIONS_PER_HOUR指的是每小时累计的最大连接次数
#资源限制是对某一账号进行累计的,而不是对账号的一次连接进行累计的,当资源限制到达后,账号的任何一次相关操作都会被拒
范例:
bash
#只能查询,插入指定字段:给指定列授权 SELECT/INSERT
GRANT SELECT(col1),INSERT(col1,col2) ON mydb.mytbl TO 'someuser'@'somehost';
#有指定库的所有权限:授予 wordpress 库所有表的全部权限
GRANT ALL ON wordpress.* TO wordpress '10.0.0.%';
#授予所有权限:所有库所有表全部权限,并允许转授(WITH GRANT OPTION)
GRANT ALL PRIVILEGES ON *.* TO 'root'@'10.0.0.%' WITH GRANT OPTION;
#创建用户和授权同时执行的方式在MySQL8.0取消了
GRANT ALL ON wordpress.* TO wordpress@'192.168.108.%' IDENTIFIED BY 'huawei';
GRANT ALL PRIVILEGES ON *.* TO 'root'@'192.168.108.%' IDENTIFIED BY 'huawei' WITH GRANT OPTION;
取消权限
格式
bash
REVOKE
priv_type [(column_list)]
[, priv_type [(column_list)]] ...
ON [object_type] priv_level
FROM user_or_role [, user_or_role] ...
范例
bash
# 撤销 testuser 在所有库所有表上的 DELETE 权限
REVOKE DELETE ON *.* FROM 'testuser'@'172.16.0.%';
# 撤销 testuser 的所有权限
REVOKE ALL ON *.* FROM'testuser'@'172.16.0.%';
查看用户权限
格式
bash
#查看指定用户权限
SHOW GRANTS FOR 'user'@'host';
#查看当前使用中的用户的权限
SHOW GRANTS FOR CURRENT_USER[()];
注意
MariaDB服务进程启动时会读取mysql库中所有授权表至内存。
GRANT或REVOKE等执行权限操作会保存于系统表中,MariaDB的服务进程通常会自动重读授权表,使之生效。
对于不能够或不能及时重读授权表的命令,可手动让MariaDB的服务进程重读授权表:
mysql>FLUSH PRIVILEGES。
范例
bash
#本地操作
#创建用户:创建 root@192.168.108.% 允许整个网段登录
mysql> create user 'root'@'192.168.108.%' identified by '123456';
Query OK, 0 rows affected (0.01 sec)
mysql> select user,host from mysql.user;
+------------------+---------------+
| user | host |
+------------------+---------------+
| root | 19 |
| root | 192.168.108.% |
| root | 192.168.108.1 |
| mysql.infoschema | localhost |
| mysql.session | localhost |
| mysql.sys | localhost |
| root | localhost |
+------------------+---------------+
7 rows in set (0.01 sec)
#查看新用户的权限,默认只有 USAGE 权限,只能连接
mysql> show grants for 'root'@'192.168.108.%';
+----------------------------------------------+
| Grants for root@192.168.108.% |
+----------------------------------------------+
| GRANT USAGE ON *.* TO `root`@`192.168.108.%` |
+----------------------------------------------+
1 row in set (0.00 sec)
#远程连接,远程操作:用 192.168.108.128 上的客户端登录 MySQL 服务器
[root@localhost ~]# mysql -uroot -p123456 -h192.168.108.128
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 14
Server version: 8.0.26 Source distribution
Copyright (c) 2000, 2021, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
#查看权限,远程操作
mysql> SHOW GRANTS FOR CURRENT_USER;
+----------------------------------------------+
| Grants for root@192.168.108.% |
+----------------------------------------------+
| GRANT USAGE ON *.* TO `root`@`192.168.108.%` |
+----------------------------------------------+
1 row in set (0.00 sec)
#无权限创建,远程操作:还没授权,建库被拒
mysql> create database db1;
ERROR 1044 (42000): Access denied for user 'root'@'192.168.108.%' to database
'db1'
#本地操作:root@localhost 有权限,创建 db1、db2
mysql> create database db1;
mysql> create database db2;
mysql> use db1;
# 在 db1 库中创建 student 表
CREATE TABLE student (
id int UNSIGNED AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(20) NOT NULL,
age tinyint UNSIGNED,
#height DECIMAL(5,2),
gender ENUM('M','F') default 'M'
)ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4;
# 插入一条测试数据
mysql> insert student (name,age)values('xiaoming',20);
#授权能查看 db1 中的 student 表,本地操作:给远程用户授予 SELECT 权限
mysql> grant select on db1.student to root@'192.168.108.%';
Query OK, 0 rows affected (0.00 sec)
#远程用户再次刷新,远程操作:权限已多出一条 SELECT
mysql> SHOW GRANTS FOR CURRENT_USER;
+-----------------------------------------------------------+
| Grants for root@192.168.108.% |
+-----------------------------------------------------------+
| GRANT USAGE ON *.* TO `root`@`192.168.108.%` |
| GRANT SELECT ON `db1`.`student` TO `root`@`192.168.108.%` |
+-----------------------------------------------------------+
2 rows in set (0.00 sec)
#能看到数据库,远程操作:授权后能看到 db1
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| db1 |
| information_schema |
+--------------------+
2 rows in set (0.00 sec)
#远程操作
mysql> use db1;
Database changed
mysql> show tables;
+---------------+
| Tables_in_db1 |
+---------------+
| student |
+---------------+
1 row in set (0.00 sec)
#远程操作:查询 student 表数据
mysql> select * from student;
+----+----------+------+--------+
| id | name | age | gender |
+----+----------+------+--------+
| 10 | xiaoming | 20 | M |
+----+----------+------+--------+
1 row in set (0.00 sec)
#没有更新权限,远程操作:UPDATE 被拒绝
mysql> update student set age=25 where id=10;
ERROR 1142 (42000): UPDATE command denied to user 'root'@'192.168.108.1' for
table 'student'
#没有删除权限,远程操作:DELETE 被拒绝
mysql> delete from student where id=10;
ERROR 1142 (42000): DELETE command denied to user 'root'@'192.168.108.1' for
table 'student'
#继续授权,本地操作:追加 UPDATE、DELETE 权限
mysql> grant update,delete on db1.student to root@'192.168.108.%';
#再次查看,远程操作:权限变成 SELECT, UPDATE, DELETE
mysql> SHOW GRANTS FOR CURRENT_USER;
+---------------------------------------------------------------------------+
| Grants for root@192.168.108.% |
+---------------------------------------------------------------------------+
| GRANT USAGE ON *.* TO `root`@`192.168.108.%` |
| GRANT SELECT, UPDATE, DELETE ON `db1`.`student` TO `root`@`192.168.108.%` |
+---------------------------------------------------------------------------+
2 rows in set (0.00 sec)
#测试,远程操作:更新 id=10 的 age 为 25
mysql> update student set age=25 where id=10;
mysql> select * from student;
+----+----------+------+--------+
| id | name | age | gender |
+----+----------+------+--------+
| 10 | xiaoming | 25 | M |
+----+----------+------+--------+
1 row in set (0.00 sec)
# 删除 id=10 这条记录
mysql> delete from student where id=10;
mysql> select * from student;
Empty set (0.00 sec)
范例
bash
#创建数据库,本地操作
mysql> create database eshop;
Query OK, 1 row affected (0.00 sec)
#创建用户,本地操作:创建电商用户 eshoper
mysql> create user eshoper@'192.168.108.%' identified by '123456';
Query OK, 0 rows affected (0.00 sec)
#授权,本地操作:授予 eshop 库所有权限给 eshoper
mysql> grant all on eshop.* to eshoper@'192.168.108.%';
Query OK, 0 rows affected (0.00 sec)
#远程测试:用 eshoper 账号远程登录
C:\Users\69466>mysql -ueshoper -p123456 -h192.168.108.128
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 17
Server version: 8.0.26 Source distribution
Copyright (c) 2000, 2025, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| eshop |
| information_schema |
+--------------------+
2 rows in set (0.00 sec)
#创建表:在 eshop 库建 product 表
mysql> use eshop;
Database changed
mysql> create table product (id int,name varchar(10));
Query OK, 0 rows affected (0.10 sec)
mysql> show tables;
+-----------------+
| Tables_in_eshop |
+-----------------+
| product |
+-----------------+
1 row in set (0.00 sec)
MySQL图形化远程管理工具
在MySQL数据库中创建用户并授权后,可以使用相关图形化工具进行远程的管理。
常见的图形化管理工具包括Navicat,SQLyog,DBbear等。
Navicat 工具

SQLyog 工具

实现基于LAMP架构的开源网站
LAMP 架构说明
LAMP是指一组通常一起使用来运行动态网站的自由软件名称首字母的缩写。
- L是指Linux操作系统。
- A是指Apache,用来提供Web服务。
- M指MySQL,用来提供数据库服务。
- P指PHP,是动态网站的的一种开发语言。
LAMP是中小型动态网站的常见组合,虽然这些开放源代码程序本身并不是专门设计成同另几个程序一起工作的,但由于它们各自的特点和普遍性,使得这个组合在搭建动态网站这一领域开始流行起来。
PHP 简介
PHP:(Hypertext Preprocessor)超文本预处理器。


PHP是通用服务器端脚本编程语言,主要用于WEB开发实现动态WEB页面,也是最早实现将脚本嵌入HTML源码文档中的服务器端脚本语言之一。同时,PHP还提供了一个命令行接口,因此,其也可以在大多数系统上作为一个独立的SHELL来使用。Rasmus Lerdorf于1994年开始开发PHP,最初是一组被Rasmus Lerdorf称作"Personal Home PageTool"的Perl脚本,可以用于显示作者的简历并记录用户对其网站的访问。后来,Rasmus Lerdorf使用C语言将这些Perl脚本重写为CGI程序,还为其增加了运行Web forms的能力以及与数据库交互的特性,并将其重命名为"Personal Home Page/Forms Interpreter"或"PHP/FI"。此时,PHP/FI已经可以用于开发简单的动态WEB程序了,这即PHP1.0。1995年6月,Rasmus Lerdorf 把它的 PHP发布于comp.infosystems.www.authoring.cgi Usenet讨论组,从此PHP开始走进人们的视野。1997年,其2.0版本发布。
1997年,两名以色列程序员Zeev Suraski 和Andi Gutmans重写的PHP的分析器(parser)成为 PHP发展到3.0的基础,而且从此将PHP重命名为PHP:Hypertext Preprocessor。此后,这两名程序员开始重写整个PHP核心,并于1999年发布了Zend Engine1.0,这也意味着PHP 4.0的诞生。2004年7月,ZendEngine 2.0发布,由此也将PHP带入了PHP5时代。PHP5包含了许多重要的新特性,如增强的面向对象编程的支持、支持PDO(PHP Data Objects)扩展机制以及一系列对PHP性能的改进。
Zend Engine是开源的、PHP脚本语言的解释器,它最早是由以色列理工学院(Technion)的学生AndiGutmans和Zeev Suraski 所开发,Zend也正是此二人名字的合称。后来两人联合创立了ZendTechnologies公司。
Zend Engine1.0于1999年随PHP4发布,由C语言开发且经过高度优化,并能够做为PHP的后端模块使用。Zend Engine为PHP提供了内存和资源管理的功能以及其它的一些标准服务,其高性能、可靠性和可扩展性在促进PHP成为一种流行的语言方面发挥了重要作用。Zend Engine的出现将PHP代码的处理过程分成了两个阶段:首先是分析PHP代码并将其转换为称作Zend opcode的二进制格式opcode(类似Java的字节码),并将其存储于内存中;第二阶段是使用ZendEngine去执行这些转换后的Opcode。
PHP各种版本官方支持时间
https://www.php.net/supported-versions.php

/etc/php.ini配置文件格式
bash
[foo]: Section Header
directive = value
php.ini 配置参考文档
bash
php.ini的核心配置选项文档 http://php.net/manual/zh/ini.core.php
php.ini配置选项列表 http://php.net/manual/zh/ini.1ist.php
php常见配置项
bash
expose_php=On #响应报文显示首部字段x-powered-by:PHP/x.y.z,暴露php版本,建议为off
max_execution_time=30 #最长执行时间30s
memory_limit=128M #生产不够,可调大
display_errors=off #调试使用,不要打开,否则可能暴露重要信息
display_startup_errors=off #建议关闭
post_max_size=8M #最大上传数据大小,生产可能调大,比下面项大
upload_max_filesize=2M #最大上传文件,生产可能要调大
max_file_uploads=20 #同时上传最多文件数
date.timezone=Asia/shanghai #指定时区
short_open_tag=On #支持短标签
实现博客项目
服务器配置
通过Centos-Stream8-template克隆web
通过mysql克隆mysql
IP地址规划
| IP地址 | 主机名 | 作用 | 软件 |
|---|---|---|---|
| 192.168.108.100 | web | 提供WEB服务,PHP动态解析 | Apache,PHP |
| 192.168.108.101 | mysql | 提供数据库服务 | MySQL |
WordPress
WordPress是使用PHP语言开发的博客平台,用户可以在支持PHP和MySQL数据库的服务器上架设属于自己的网站。也可以把WordPress当作一个内容管理系统(CMS)来使用。
官方网站
具体实现
bash
#在100上安装apapche和PHP
[root@web ~]# yum -y install httpd php php-mysqlnd php-json php-gd php-xml php-mbstring php-zip
# 查看 PHP 版本
[root@web ~]# php -v
PHP 7.2.24 (cli) (built: Oct 22 2019 08:28:36) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies
#关闭防火墙
[root@web ~]# systemctl disable --now firewalld
#启动WEB服务
[root@web ~]# systemctl start httpd.service
#添加php测试页面:新建 test.php
[root@web ~]# vim /var/www/html/test.php
<?php
phpinfo();
通过浏览器访问

bash
#下载wordpress 源码
[root@web ~]# cd /var/www/html/
[root@web html]# wget https://cn.wordpress.org/latest-zh_CN.zip
[root@web html]# unzip latest-zh_CN.zip
[root@web html]# ls
latest-zh_CN.zip test.php wordpress
#修改属主属组:让 apache 用户对网站目录有读写权限
[root@web html]# chown -R apache.apache wordpress/
#切换到101节点,创建数据库
[root@mysql ~]# mysql -uroot -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 10
Server version: 8.0.26 Source distribution
Copyright (c) 2000, 2021, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
#创建数据库
mysql> create database wordpress;
Query OK, 1 row affected (0.02 sec)
#创建用户:创建 wordpresser 用于远程连接
mysql> create user 'wordpresser'@'192.168.108.%' identified by '123456';
Query OK, 0 rows affected (0.01 sec)
#授权:把 wordpress 库所有权限授给 wordpresser
mysql> grant all on wordpress.* to 'wordpresser'@'192.168.108.%';
Query OK, 0 rows affected (0.01 sec)
为项目配置域名
bash
#在web服务器上配置域名指向的目录
[root@web ~]# vim /etc/httpd/conf.d/blog.gqd.cloud.conf
<VirtualHost *:80>
ServerName blog.gqd.cloud
DocumentRoot "/var/www/html/wordpress"
<Directory "/var/www/html/wordpress">
AllowOverride all
Order allow,deny
Allow from all
</Directory>
</VirtualHost>
#重启httpd
[root@web ~]# systemctl restart httpd
#在物理机上为域名设置解析
#在C:\windows\System32\drivers\etc\hosts添中如下行
192.168.108.100 blog.gqd.cloud
在页面上填写相关配置






配置完成后,通过浏览器访问

mysql 5.x源码安装
环境准备:
使用CentOS-7-template模板克隆mysql01
bash
#设置主机名
[root@localhost ~]# hostnamectl set-hostname mysql01
#关闭防火墙
[root@mysql01 ~]# systemctl disable firewalld.service --now
mysql5.7稳定版安装
bash
#安装依赖包,ncurses(操作终端) ncurses-devel(编译软件时用)bison(解析语法) cmake(源码编译工具) gcc,gcc-c++(编译器)
[root@mysql01 ~]# yum -y install ncurses ncurses-devel bison cmake gcc gcc-c++
#配置程序用户(不允许终端登录)
[root@mysql01 ~]# useradd -s /sbin/nologin mysql
#解压mysql和boost包到指定目录,boost是支持mysql底层c++运行的仓库
[root@mysql01 ~]# tar zxvf mysql-5.7.17.tar.gz -C /opt/
[root@mysql01 ~]# tar zxvf boost_1_59_0.tar.gz -C /usr/local/
[root@mysql01 ~]# cd /usr/local/
[root@mysql01 ~]# mv boost_1_59_0 boost
#配置安装环境
[root@mysql01 ~]# cd /opt/mysql-5.7.17/
#cmake配置编译参数,反斜杠表示换行续行
[root@mysql01 mysql-5.7.17]# 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=/usr/local/boost \
-DWITH_SYSTEMD=1
#注释
cmake \
-DCMAKE_INSTALL_PREFIX=/usr/local/mysql \ #安装路径
-DMYSQL_UNIX_ADDR=/usr/local/mysql/mysql.sock \ #客户端连服务的通讯文件
-DSYSCONFDIR=/etc \ #mysql的配置文件
-DSYSTEMD_PID_DIR=/usr/local/mysql \ #pid进程文件存放位置
-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=/usr/local/boost \ #底层的c++支持库位置
-DWITH_SYSTEMD=1 #id号
------注意:如果在CMAKE的过程中有报错,当报错解决后,需要把源码目录中的CMakeCache.txt文件删除,然后再重新CMAKE,否则错误依旧------------
#编译和安装
[root@mysql01 mysql-5.7.17]# make && make install
#递归配置目录所属主和组
[root@mysql01 ~]# chown -R mysql.mysql /usr/local/mysql/
#编辑mysql的配置文件,直接全替换
[root@mysql01 ~]# vim /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
#配置文件所属主和组
[root@mysql01 ~]# chown mysql:mysql /etc/my.cnf
#配置环境变量
[root@mysql01 ~]# echo 'PATH=/usr/local/mysql/bin:/usr/local/mysql/lib:$PATH' >> /etc/profile
[root@mysql01 ~]# echo 'export PATH' >> /etc/profile
#加载修改过的配置
[root@mysql01 ~]# source /etc/profile
#数据库初始化
[root@mysql01 ~]# cd /usr/local/mysql/
[root@mysql01 mysql]# bin/mysqld \
--initialize-insecure \
--user=mysql \
--basedir=/usr/local/mysql \
--datadir=/usr/local/mysql/data
#拷贝systemd服务管理文件到系统目录
[root@mysql01 mysql]# cp /usr/local/mysql/usr/lib/systemd/system/mysqld.service /usr/lib/systemd/system/
#重新加载systemd配置
[root@mysql01 mysql]# systemctl daemon-reload
#启动mysqld服务
[root@mysql01 mysql]# systemctl start mysqld
#查看3306端口是否监听成功
[root@mysql01 mysql]# netstat -anpt | grep 3306
tcp6 0 0 :::3306 :::* LISTED
70276/mysqld
#设置mysqld开机自启
[root@mysql01 mysql]# systemctl enable mysqld
#给root账号设置密码为huawei
[root@mysql01 mysql]# mysqladmin -uroot password "huawei"
Enter password:
#登录mysql
[root@mysql01 ~]# mysql -uroot -phuawei
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 4
Server version: 5.7.17 Source distribution
Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
#授权远程登录
mysql> grant all privileges on *.* to 'root'@'%' identified by 'huawei' with grant option;
做完,拍摄快照
基础SQL语句
查询数据库
bash
#使用root用户登录数据库
[root@mysql01 ~]# mysql -u root -p
Enter password:`huawei`
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.7.17 Source distribution
Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
#查看数据库列表
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.00 sec)
创建和使用数据库
bash
#创建数据库school
mysql> create database school;
Query OK, 1 row affected (0.00 sec)
#查看数据库,看到新建的数据库school
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| school |
| sys |
+--------------------+
5 rows in set (0.00 sec)
#使用数据库school
mysql> use school;
Database changed
#查看表
mysql> show tables;
Empty set (0.00 sec)
mysql>
创建表结构
bash
#创建info表
mysql> CREATE TABLE info (
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
name CHAR(10) NOT NULL,
score DECIMAL(5,2),
address CHAR(50) DEFAULT '南京',
hobby INT NOT NULL
);
Query OK, 0 rows affected (0.02 sec)
#查看当前库中的表
mysql> show tables;
+------------------+
| Tables_in_school |
+------------------+
| info |
+------------------+
1 row in set (0.00 sec)
#查看info表结构
mysql> describe info;
+---------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | char(10) | NO | | NULL | |
| score | decimal(5,2) | YES | | NULL | |
| address | char(50) | YES | | 南京 | |
| hobby | int(11) | NO | | NULL | |
+---------+--------------+------+-----+---------+----------------+
5 rows in set (0.01 sec)
添加表信息
bash
#插入第一条记录:唐三,90分,广州
mysql> insert into info (name,score,address,hobby) values ('唐三',90,'广州',1);
Query OK, 1 row affected (0.01 sec)
#查询表中所有记录
mysql> select * from info;
+----+--------+-------+---------+-------+
| id | name | score | address | hobby |
+----+--------+-------+---------+-------+
| 1 | 唐三 | 90.00 | 广州 | 1 |
+----+--------+-------+---------+-------+
1 row in set (0.00 sec)
#插入第二条记录:叶凡,91分,伦敦
mysql> insert into info (name,score,address,hobby) values ('叶凡',91,'伦敦',2);
Query OK, 1 row affected (0.00 sec)
#插入第三条记录:喜羊羊,92分,地址为空
mysql> insert into info (name,score,address,hobby) values ('喜羊羊',92,'',3);
Query OK, 1 row affected (0.00 sec)
mysql> select * from info;
+----+-----------+-------+---------+-------+
| id | name | score | address | hobby |
+----+-----------+-------+---------+-------+
| 1 | 唐三 | 90.00 | 广州 | 1 |
| 2 | 叶凡 | 91.00 | 伦敦 | 2 |
| 3 | 喜羊羊 | 92.00 | | 3 |
+----+-----------+-------+---------+-------+
3 rows in set (0.00 sec)
#插入第四条记录:曹操,93分,地址用默认值南京
mysql> insert into info (name,score,address,hobby) values ('曹操',93,default,4);
Query OK, 1 row affected (0.00 sec)
mysql> select * from info;
+----+-----------+-------+---------+-------+
| id | name | score | address | hobby |
+----+-----------+-------+---------+-------+
| 1 | 唐三 | 90.00 | 广州 | 1 |
| 2 | 叶凡 | 91.00 | 伦敦 | 2 |
| 3 | 喜羊羊 | 92.00 | | 3 |
| 4 | 曹操 | 93.00 | 南京 | 4 |
+----+-----------+-------+---------+-------+
4 rows in set (0.00 sec)
修改表内容
bash
#将喜羊羊的地址改为华盛顿
mysql> update info set address='华盛顿' where name='喜羊羊';
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from info;
+----+-----------+-------+-----------+-------+
| id | name | score | address | hobby |
+----+-----------+-------+-----------+-------+
| 1 | 唐三 | 90.00 | 广州 | 1 |
| 2 | 叶凡 | 91.00 | 伦敦 | 2 |
| 3 | 喜羊羊 | 92.00 | 华盛顿 | 3 |
| 4 | 曹操 | 93.00 | 南京 | 4 |
+----+-----------+-------+-----------+-------+
4 rows in set (0.00 sec)
#将曹操的地址改为巴黎
mysql> update info set address='巴黎' where name='曹操';
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from info;
+----+-----------+-------+-----------+-------+
| id | name | score | address | hobby |
+----+-----------+-------+-----------+-------+
| 1 | 唐三 | 90.00 | 广州 | 1 |
| 2 | 叶凡 | 91.00 | 伦敦 | 2 |
| 3 | 喜羊羊 | 92.00 | 华盛顿 | 3 |
| 4 | 曹操 | 93.00 | 巴黎 | 4 |
+----+-----------+-------+-----------+-------+
4 rows in set (0.00 sec)
#将id为4的记录分数改为66.5、地址改为合肥
mysql> update info set score=66.5,address='合肥' where id=4;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from info;
+----+-----------+-------+-----------+-------+
| id | name | score | address | hobby |
+----+-----------+-------+-----------+-------+
| 1 | 唐三 | 90.00 | 广州 | 1 |
| 2 | 叶凡 | 91.00 | 伦敦 | 2 |
| 3 | 喜羊羊 | 92.00 | 华盛顿 | 3 |
| 4 | 曹操 | 66.50 | 合肥 | 4 |
+----+-----------+-------+-----------+-------+
4 rows in set (0.00 sec)
#按条件查询喜羊羊这条记录
mysql> select * from info where name='喜羊羊' ;
+----+------+-------+-----------+-------+
| id | name | score | address | hobby |
+----+------+-------+-----------+-------+
| 3 | 喜羊羊 | 92.00 | 华盛顿 | 3 |
+----+------+-------+-----------+-------+
1 row in set (0.00 sec)
mysql> select * from info;
+----+-----------+-------+-----------+-------+
| id | name | score | address | hobby |
+----+-----------+-------+-----------+-------+
| 1 | 唐三 | 90.00 | 广州 | 1 |
| 2 | 叶凡 | 91.00 | 伦敦 | 2 |
| 3 | 喜羊羊 | 92.00 | 华盛顿 | 3 |
| 4 | 曹操 | 66.50 | 合肥 | 4 |
+----+-----------+-------+-----------+-------+
4 rows in set (0.00 sec)
删除表内容
bash
#删除id为3的记录
mysql> delete from info where id=3;
Query OK, 1 row affected (0.00 sec)
mysql> select * from info;
+----+--------+-------+---------+-------+
| id | name | score | address | hobby |
+----+--------+-------+---------+-------+
| 1 | 唐三 | 90.00 | 广州 | 1 |
| 2 | 叶凡 | 91.00 | 伦敦 | 2 |
| 4 | 曹操 | 66.50 | 合肥 | 4 |
+----+--------+-------+---------+-------+
3 rows in set (0.00 sec)
python导出表
先配置pip源:
Windows系统:
在用户目录下(如 C:\Users\你的用户名\)创建一个名为 pip 的文件夹。
以我举例
C:\Users\69466

在 pip 文件夹内创建一个名为 pip.ini 的文件。

用记事本打开 pip.ini,输入以下内容并保存:
bash
[pip]
#配置阿里云PyPI镜像源地址
index-url = https://mirrors.aliyun.com/pypi/simple/
#信任该镜像主机,避免https告警
trusted-host = mirrors.aliyun.com
pycharm下载软件包
bash
#安装pandas数据处理库
pip install pandas
#安装sqlalchemy数据库连接框架
pip install sqlalchemy
#安装pymysql MySQL驱动
pip install pymysql
#安装openpyxl Excel读写库
pip install openpyxl
下图演示了pip install pandas,另外3个一样

代码如下
bash
#导入pandas并起别名pd
import pandas as pd
#从sqlalchemy导入create_engine创建连接引擎
from sqlalchemy import create_engine
#创建数据连接,连接本机school库
engine = create_engine('mysql+pymysql://root:huawei@192.168.108.142:3306/school')
#执行获取数据,查询info表全部内容
df = pd.read_sql('select * from info', engine)
#打印查询结果
print(df)
#导出到excel表格,index=False表示不导出行号
df.to_excel('info.xlsx', index=False)
print('excel 导出成功!')
右击项目,新建python文件

根据项目位置找到,输出的excel


mysql的备份与恢复
数据备份的重要性
在生产环境中,数据的安全性至关重要
任何数据的丢失都可能产生严重的后果
造成数据丢失的原因
- 程序错误
- 人为操作错误
- 运算错误
- 磁盘故障
- 灾难(如火灾、地震)和盗窃
数据库备份的分类
从物理与逻辑的角度,备份可分为
物理备份:对数据库操作系统的物理文件(如数据文件、日志文件等)的备份
物理备份方法
- 冷备份(脱机备份):是在关闭数据库的时候进行的
- 热备份(联机备份):数据库处于运行状态,依赖于数据库的日志文件
- 温备份:数据库锁定表格(不可写入但可读)的状态下进行备份操作
逻辑备份:对数据库逻辑组件(如:表等数据库对象)的备份
常见的备份方法
物理冷备
备份时数据库处于关闭状态,直接打包数据库文件
备份速度快,恢复时也是最简单的
专用备份工具mydump或mysqlhotcopy
mysqldump常用的逻辑备份工具
mysqlhotcopy仅拥有备份MylSAM和ARCHIVE表
启用二进制日志进行增量备份
进行增量备份,需要刷新二进制日志
第三方工具备份
免费的MySQL热备份软件PerconaXtraBackup
冷备份
bash
# 备份(推荐写法)
# 先停止服务
[root@mysql01 ~]# systemctl stop mysqld
#进入数据目录
[root@mysql01 ~]# cd /usr/local/mysql/data
#创建备份目录
[root@mysql01 data]# mkdir /mysql_bak
#打包当前目录所有文件为以日期命名的压缩包
[root@mysql01 data]# tar czf /mysql_bak/mysql-backup-$(date +%F).tar.gz *
# 备份完成后启动服务
[root@mysql01 data]# systemctl start mysqld
#测试服务正常
# 删除数据
# 先停止服务
[root@mysql01 ~]# systemctl stop mysqld
# 清空数据目录(谨慎操作!)
[root@mysql01 ~]# rm -rf /usr/local/mysql/data/*
#再次开启测试,发现数据库坏了
[root@mysql01 ~]# systemctl start mysqld
#停止数据库,恢复数据库
[root@mysql01 ~]# systemctl stop mysqld
#解压备份包到数据目录
[root@mysql01 ~]# tar xzf /mysql_bak/mysql-backup-2025-10-15.tar.gz -C /usr/local/mysql/data/
# 恢复权限
[root@mysql01 ~]# chown -R mysql:mysql /usr/local/mysql/data
# 启动服务
[root@mysql01 ~]# systemctl start mysqld
#再次测试,发现数据库恢复了
逻辑备份
bash
#备份数据库
#先启动mysqld服务
[root@mysql01 ~]# systemctl start mysqld
#使用mysqldump把school库备份为school.sql
[root@mysql01 ~]# mysqldump -u root -p school > /mysql_bak/school.sql
Enter password:
#查看备份文件是否生成
[root@mysql01 ~]# ls /mysql_bak/school.sql
mysql_bak/school.sql
#查看备份SQL内容
[root@mysql01 ~]# cat /mysql_bak/school.sql
#备份多个数据库
#同时备份school和mysql两个库
[root@mysql01 ~]# mysqldump -u root -p --databases school mysql > /mysql_bak/school-mysql.sql
Enter password:
[root@mysql01 ~]# cat /mysql_bak/school-mysql.sql
#备份所有数据库
#--opt启用优化选项,--all-databases备份全部库
[root@mysql01 ~]# mysqldump -u root -p --opt --all-databases > /mysql_bak/all.sql
Enter password:
[root@mysql01 ~]# cat /mysql_bak/all.sql
#备份整个表
#只备份school库中的info表
[root@mysql01 ~]# mysqldump -u root -p school info > /mysql_bak/info.sql
Enter password:
[root@mysql01 ~]# cat /mysql_bak/info.sql
恢复数据
bash
#登录mysql
[root@mysql01 ~]# mysql -u root -p
Enter password:
#进入school库
mysql> use school
#查看表
mysql> show tables;
+------------------+
| Tables_in_school |
+------------------+
| info |
+------------------+
1 row in set (0.00 sec)
#删除info表测试恢复
mysql> drop table info;
Query OK, 0 rows affected (0.01 sec)
#用source命令导入备份SQL恢复表
mysql> source /mysql_bak/info.sql
#再次查看表,info已恢复
mysql> show tables;
+------------------+
| Tables_in_school |
+------------------+
| info |
+------------------+
1 row in set (0.00 sec)
增量备份
bash
#编辑配置文件开启二进制日志
[root@mysql01 ~]# vim /etc/my.cnf
------------------------
[mysqld]
#开启binlog二进制日志,段末加这一行
log-bin=mysql-bin #这段下面最后加一行
#重启服务使配置生效
[root@web-server ~]# systemctl restart mysqld.service
#查看数据目录,已生成mysql-bin.000001二进制日志
[root@mysql01 ~]# ls /usr/local/mysql/data/
auto.cnf client-cert.pem ibdata1 ibtmp1 mysql-bin.index
public_key.pem server-key.pem
ca-key.pem client-key.pem ib_logfile0 mysql performance_schema
school sys
ca.pem ib_buffer_pool ib_logfile1 mysql-bin.000001 private_key.pem
server-cert.pem
#先进行完整性备份
[root@mysql01 ~]# mysqldump -uroot -p school > /opt/school.sql
Enter password:
#日志刷新生效,切割出新的binlog
[root@mysql01 ~]# mysqladmin -uroot -p flush-logs
Enter password:
#新产生的mysql-bin.000002只记录上次刷新后的操作
[root@mysql01 ~]# ls /usr/local/mysql/data/
auto.cnf client-cert.pem ibdata1 ibtmp1 mysql-bin.000002
private_key.pem server-cert.pem
ca-key.pem client-key.pem ib_logfile0 mysql mysql-bin.index
public_key.pem server-key.pem
ca.pem ib_buffer_pool ib_logfile1 mysql-bin.000001 performance_schema
school sys
#登录mysql
[root@mysql01 ~]# mysql -uroot -p
Enter password:
----------------------------------------
mysql> use school;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> select * from info;
+----+--------+-------+---------+-------+
| id | name | score | address | hobby |
+----+--------+-------+---------+-------+
| 1 | 唐三 | 90.00 | 广州 | 1 |
| 2 | 叶凡 | 91.00 | 伦敦 | 2 |
| 4 | 曹操 | 66.50 | 合肥 | 4 |
+----+--------+-------+---------+-------+
3 rows in set (0.00 sec)
#再次插入数据生产增量备份
mysql> insert into info (name,score,address,hobby) values ('美猴王',75,'武汉',1);
Query OK, 1 row affected (0.00 sec)
#退出mysql
mysql> exit
Bye
#再次刷新日志,切割出新的binlog
[root@mysql01 ~]# mysqladmin -uroot -p flush-log
Enter password:
#新产生mysql-bin.000003日志记录insert操作
[root@mysql01 ~]# ls /usr/local/mysql/data/
auto.cnf client-cert.pem ibdata1 ibtmp1 mysql-bin.000002
performance_schema school sys
ca-key.pem client-key.pem ib_logfile0 mysql mysql-bin.000003
private_key.pem server-cert.pem
ca.pem ib_buffer_pool ib_logfile1 mysql-bin.000001 mysql-bin.index
public_key.pem server-key.pem
#再次登录mysql
[root@mysql01 ~]# mysql -uroot -p
Enter password:
---------------------------------------------------------------
mysql> use school;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
#再插入一条超人记录
mysql> insert into info (name,score,address,hobby) values ('超人',83,'上海',2);
Query OK, 1 row affected (0.00 sec)
mysql> select * from info;
+----+-----------+-------+---------+-------+
| id | name | score | address | hobby |
+----+-----------+-------+---------+-------+
| 1 | 唐三 | 90.00 | 广州 | 1 |
| 2 | 叶凡 | 91.00 | 伦敦 | 2 |
| 4 | 曹操 | 66.50 | 合肥 | 4 |
| 5 | 美猴王 | 75.00 | 武汉 | 1 |
| 6 | 超人 | 83.00 | 上海 | 2 |
+----+-----------+-------+---------+-------+
5 rows in set (0.00 sec)
mysql> exit
Bye
#刷新日志生效
[root@mysql01 ~]# mysqladmin -uroot -p flush-log
Enter password:
#环境准备
[root@mysql01 ~]# mysql -uroot -p
Enter password:
--------------------------------------------------------------
mysql> use school;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
#删除内容
#删除id为6的超人记录
mysql> delete from info where id=6;
Query OK, 1 row affected (0.00 sec)
#删除id为5的美猴王记录
mysql> delete from info where id=5;
Query OK, 1 row affected (0.01 sec)
mysql> select * from info;
+----+--------+-------+---------+-------+
| id | name | score | address | hobby |
+----+--------+-------+---------+-------+
| 1 | 唐三 | 90.00 | 广州 | 1 |
| 2 | 叶凡 | 91.00 | 伦敦 | 2 |
| 4 | 曹操 | 66.50 | 合肥 | 4 |
+----+--------+-------+---------+-------+
3 rows in set (0.00 sec)
mysql> exit
Bye
#查看数据目录,已有000004日志
[root@mysql01 ~]# ls /usr/local/mysql/data/
auto.cnf client-cert.pem ibdata1 ibtmp1 mysql-bin.000002
mysql-bin.index public_key.pem server-key.pem
ca-key.pem client-key.pem ib_logfile0 mysql mysql-bin.000003
performance_schema school sys
ca.pem ib_buffer_pool ib_logfile1 mysql-bin.000001 mysql-bin.000004
private_key.pem server-cert.pem
#查看日志文件,vim看日志是乱码,需用mysqlbinlog解码
#解码查看000003日志内容
[root@mysql01 ~]# mysqlbinlog --no-defaults --base64-output=decode-rows -v /usr/local/mysql/data/mysql-bin.000003
#解码查看000004日志内容
[root@mysql01 ~]# mysqlbinlog --no-defaults --base64-output=decode-rows -v /usr/local/mysql/data/mysql-bin.000004
#恢复操作,恢复时如果被拒绝,是有其他mysql进程占用了
#把000003日志重放给mysql以恢复其中的insert操作
[root@mysql01 ~]# mysqlbinlog --no-defaults /usr/local/mysql/data/mysql-bin.000003 | mysql -uroot -p
Enter password:
#验证
[root@web-server ~]# mysql -uroot -p
Enter password:
mysql> use school;
mysql> select * from info;
+----+--------+-------+---------+-------+
| id | name | score | address | hobby |
+----+--------+-------+---------+-------+
| 1 | 唐三 | 90.00 | 广州 | 1 |
| 2 | 叶凡 | 91.00 | 伦敦 | 2 |
| 4 | 曹操 | 66.50 | 合肥 | 4 |
| 6 | 超人 | 83.00 | 上海 | 2 |
+----+--------+-------+---------+-------+
4 rows in set (0.00 sec)
主从复制和读写分离
主从复制 核心原理
必须记住 3 个核心组件
- binlog(二进制日志) ------ 主库
- IO 线程 ------ 从库
- SQL 线程 ------ 从库
完整流程(一步一步,逐句理解)
- 主库执行增删改(insert/update/drop)
- MySQL 把这些操作记录到 binlog 日志文件
- 从库的 IO 线程连接主库,请求 binlog
- 主库的 dump 线程把 binlog 发给从库
- 从库 IO 线程将内容写到本地 relay log(中继日志)
- 从库 SQL 线程读取中继日志,重放 SQL 语句
- 两个 Yes 代表正常:IO_Running、SQL_Running
- 从库数据和主库完全一致
使用目标:数据冗余和灾难恢复;提升并发能力、避免锁冲突。

MySQL读写分离原理
只在主服务器上写,只在从服务器上读
主数据库处理事务性查询,从数据库处理SELECT查询
数据库复制用于将事务性查询的变更同步到集群中的从数据库
读写分离方案
- 基于程序代码内部实现
- 基于中间代理层实现
- MySQL-Proxy
- Amoeba
- mycat

在每个事务更新数据完成之前,Master将这些改变记录进二进制日志。写入二进制日志完成后,Master通知存储引擎提交事务。
Slave将Master 的 Binary log复制到其中继日志(Relay log)。首先,Slave开始一个工作线程-I/0线程,I/0线程在Master上打开一个普通的连接,然后开始Binlog dump process。Binlog dump process从Master 的二进制日志中读取事件,如果已经跟上Master,它会睡眠并等待Master产生新的事件。I/0线程将这些事件写入中继日志。
SQL slave thread(SQL从线程)处理该过程的最后一步。SQL线程从中继日志读取事件,并重放其中的事件而更新Slave数据,使其与Master中的数据保持一致。只要该线程与I/0线程保持一致,中继日志通常会位于0S的缓存中,所以中继日志的开销很小。复制过程有一个很重要的限制,即复制在Slave上是串行化的,也就是说Master上的并行更新操作不能在Slave上并行操作。
实验拓扑图
使用Centos-7-template 模板克隆产生应用客户端和amoeba
使用mysql模板克隆产生mysql主服务器,mysql从节点1,mysql从节点2
根据下表,将IP地址,主机名更改好
| 主机名 | IP地址 | 作用 |
|---|---|---|
| mysql-master | 192.168.108.101 | mysql主服务器 |
| mysql-slave01 | 192.168.108.102 | mysql从节点1 |
| mysql-slave02 | 192.168.108.103 | mysql从节点2 |
| amoeba | 192.168.108.110 | amoeba |
| mysql-client | 192.168.108.111 | 应用客户端 |

时间同步
通过时间戳实现业务的一致性
bash
# 所有节点
#与阿里云时间服务器同步时间
ntpdate ntp.aliyun.com
#查看当前时区与时间
date -R
#关闭防火墙
systemctl disable firewalld --now
#临时关闭SELinux
setenforce 0
如果出现故障:使用此方法,对时完成后,无法重启mysqld服务
原因:之前在windows端使用navicat连接过mysql
解决:pkill -9 mysql;systemctl restart mysqld
mysql主从服务器配置
mysql主服务器配置
bash
#编辑主库配置文件
[root@mysql-master ~]# vim /etc/my.cnf
#主库server-id设为11,三台myslq id不能一致
server-id = 11
#开启主服务器二进制日志文件
log-bin = master-bin
#从服务器更新二进制日志(级联复制)
log-slave-updates = true
#重启mysqld使配置生效
[root@mysql-master ~]# systemctl restart mysqld
#登录mysql
[root@mysql-master ~]# mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 7
Server version: 5.7.17-log Source distribution
Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
#授权从库复制账号myslave
mysql> GRANT REPLICATION SLAVE ON *.* TO 'myslave'@'192.168.108.%' IDENTIFIED BY '123456';
Query OK, 0 rows affected, 1 warning (0.01 sec)
#刷新权限使授权生效
mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)
#查看主库状态,记录File和Position
mysql> show master status;
+-------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+-------------------+----------+--------------+------------------+-------------------+
| master-bin.000001 | 604 | | | |
+-------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
#检查有没有master-bin.000001
[root@mysql-master ~]# ls /usr/local/mysql/data
auto.cnf ibdata1 ib_logfile1 master-bin.000001 mysql
sys
ib_buffer_pool ib_logfile0 ibtmp1 master-bin.index performance_schema
mysql从服务器配置
mysql-slave01,mysql-slave02都要做如下操作
bash
#主从是克隆的要做这个操作,否则UUID一致
# mysql-slave
#停止mysqld服务
[root@mysql-slave01 ~]# systemctl stop mysqld
#删除自动生成的auto.cnf(内含UUID),避免UUID冲突
[root@mysql-slave01 ~]# rm -f /usr/local/mysql/data/auto.cnf
#启动mysqld服务,会重新生成auto.cnf
[root@mysql-slave01 ~]# systemctl start mysqld
#编辑从库配置文件
[root@mysql-slave01 ~]# vim /etc/my.cnf
#从库server-id设为22,另外一台为23
server-id = 22
#从主服务器同步日志文件记录到本地中继日志
relay-log = relay-log-bin
#定义relay-log的位置和名称索引文件
relay-log-index = slave-relay-bin.index
#重启mysqld使配置生效
[root@mysql-slave01 ~]# systemctl restart mysqld
#登录mysql
[root@mysql-slave01 ~]# mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.7.17 Source distribution
Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
#指定主库信息,连接主库进行复制
mysql> change master to
master_host='192.168.108.101',master_user='myslave',master_password='123456',master_log_file='master-bin.000001',master_log_pos=604;
#master_log_file,master_log_pos与前面查询的相同
Query OK, 0 rows affected, 2 warnings (0.03 sec)
#启动从库复制线程
mysql> start slave;
Query OK, 0 rows affected (0.02 sec)
#查看从库状态(\G竖排显示)
mysql> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.108.101
Master_User: myslave
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: master-bin.000001
Read_Master_Log_Pos: 604
Relay_Log_File: relay-log-bin.000002
Relay_Log_Pos: 321
Relay_Master_Log_File: master-bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 604
Relay_Log_Space: 526
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 11
Master_UUID: 5d895caf-a1e0-11f0-b3ec-000c29866c0f
Master_Info_File: /usr/local/mysql/data/master.info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set:
Executed_Gtid_Set:
Auto_Position: 0
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
1 row in set (0.00 sec)
ERROR:
No query specified
#mysql-slave02配置
#停止mysqld服务
[root@mysql-slave02 ~]# systemctl stop mysqld
#删除auto.cnf避免UUID冲突
[root@mysql-slave02 ~]# rm -f /usr/local/mysql/data/auto.cnf
#启动mysqld服务
[root@mysql-slave02 ~]# systemctl start mysqld
#编辑从库配置文件
[root@mysql-slave02 ~]# vim /etc/my.cnf
#第二台从库server-id设为23
server-id = 23
relay-log = relay-log-bin
relay-log-index = slave-relay-bin.index
#重启mysqld使配置生效
[root@mysql-slave02 ~]# systemctl restart mysqld
#登录mysql
[root@mysql-slave02 ~]# mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.7.17 Source distribution
Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
#指定主库信息
mysql> change master to
master_host='192.168.108.101',master_user='myslave',master_password='123456',master_log_file='master-bin.000001',master_log_pos=604;
Query OK, 0 rows affected, 2 warnings (0.04 sec)
#启动从库复制线程
mysql> start slave;
Query OK, 0 rows affected (0.01 sec)
#查看从库状态
mysql> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.108.101
Master_User: myslave
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: master-bin.000001
Read_Master_Log_Pos: 604
Relay_Log_File: relay-log-bin.000002
Relay_Log_Pos: 321
Relay_Master_Log_File: master-bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 604
Relay_Log_Space: 526
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 11
Master_UUID: 5d895caf-a1e0-11f0-b3ec-000c29866c0f
Master_Info_File: /usr/local/mysql/data/master.info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set:
Executed_Gtid_Set:
Auto_Position: 0
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
1 row in set (0.00 sec)
ERROR:
No query specified
mysql-slave01,mysql-slave02查询结果如下

验证主从同步
bash
# 主服务器上:
#用root登录主库
[root@mysql-master ~]# mysql -uroot -phuawei
#创建school库
mysql> create database school;
Query OK, 1 row affected (0.01 sec)
#进入school库
mysql> use school;
#创建student表
CREATE TABLE student (
id int UNSIGNED AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(20) NOT NULL,
age tinyint UNSIGNED,
#height DECIMAL(5,2),
gender ENUM('M','F') default 'M'
)ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4;
#插入一条路飞记录
mysql> insert student (name,age)values('路飞',20);
# 去从服务器上 show databases;
#登录从库验证同步
[root@mysql-slave01 ~]# mysql -uroot -phuawei
#查询student表数据
mysql> select * from school.student;
+----+--------+------+--------+
| id | name | age | gender |
+----+--------+------+--------+
| 10 | 路飞 | 20 | M |
+----+--------+------+--------+
1 row in set (0.00 sec)
amoeba服务器
读写分离 核心原理
基于 主从复制:
- 主库写入数据 → 自动同步到从库
- 应用程序收到 SQL:
- insert/update/delete → 走主库
- select → 走从库
bash
应用程序
↓
读写中间件(或代码判断)
↓
----------------------
写 → Master(主库)
读 → Slave 1
Slave 2
Slave 3
----------------------
从库可以有 1 台、2 台、多台,共同分担查询压力
主从复制保证数据一致
读写分离保证性能扩容
Amoeba 是一款基于 Java 开发的 MySQL 数据库代理中间件,核心定位是SQL 路由,帮你在应用与 MySQL 之间实现读写分离、负载均衡、高可用,对应用透明、配置简单,是早期企业实现 MySQL 读写分离的主流方案。
角色:应用 ↔ Amoeba ↔ MySQL 主从集群,Amoeba 是中间 "SQL 路由器"。
核心能力:自动识别 SQL 类型,写(INSERT/UPDATE/DELETE)走主库,读(SELECT)走从库,并对从库做负载均衡。
依赖前提:必须先搭好 MySQL 主从复制,Amoeba 只负责路由,不负责数据同步。
优势:零代码侵入、配置基于 XML(比 MySQL Proxy 的 Lua 简单)、轻量易运维。
工作流程(读写分离)
- 应用连接 Amoeba 代理(默认端口 8066),而非直接连 MySQL。
- Amoeba 解析 SQL:
- 写操作 → 转发到配置的 主库池(writePool)。
- 读操作 → 转发到配置的 从库池(readPool),并按轮询 / 权重做负载均衡。
- 主从复制保证从库数据与主库一致,应用无感知。
核心组件(配置文件)
Amoeba 核心配置在 $AMOEBA_HOME/conf/ 下,共 7 个,最关键 2 个:
| 配置文件 | 作用 |
|---|---|
| amoeba.xml | 代理核心配置:端口、认证、读写池、路由规则、线程池 |
| dbServers.xml | 定义后端 MySQL 节点(主 / 从)、连接信息、连接池 |
路由规则(读写分离核心)
在 amoeba.xml 中配置:
writePool:指定写操作转发的主库节点池。readPool:指定读操作转发的从库节点池(多从库自动轮询)。
规则优先级:readPools/writePools > defaultPools 。
bash
#普通linux克隆得出amoeba
#设置主机名为amoeba
[root@amoeba ~]# hostnamectl set-hostname amoeba
#关闭防火墙
[root@amoeba ~]# systemctl stop firewalld.service
#临时关闭SELinux
[root@amoeba ~]# setenforce 0
#给JDK安装包加可执行权限
[root@amoeba ~]# chmod +x jdk-6u14-linux-x64.bin
#执行JDK安装脚本
[root@amoeba ~]# ./jdk-6u14-linux-x64.bin
#到yes的时候,输入yes按enter
#移动JDK到标准目录
[root@amoeba ~]# mv jdk1.6.0_14/ /usr/local/jdk1.6
#编辑环境变量配置文件
[root@amoeba ~]# vim /etc/profile
最下面加
#java家目录
export JAVA_HOME=/usr/local/jdk1.6
#类环境和jre
export CLASSPATH=$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib
#把java命令加入PATH
export PATH=$JAVA_HOME/lib:$JAVA_HOME/jre/bin/:$PATH:$HOME/bin
#指定amoeba路径
export AMOEBA_HOME=/usr/local/amoeba
#把amoeba命令加入PATH
export PATH=$PATH:$AMOEBA_HOME/bin
#重新加载环境变量
[root@amoeba ~]# source /etc/profile
#创建amoeba安装目录
[root@amoeba ~]# mkdir /usr/local/amoeba
#解压amoeba安装包到指定目录
[root@amoeba ~]# tar zxvf amoeba-mysql-binary-2.2.0.tar.gz -C /usr/local/amoeba/
#递归给amoeba目录755权限
[root@amoeba ~]# chmod -R 755 /usr/local/amoeba/
#执行结果显示amoeba start|stop说明安装成功
[root@amoeba ~]# /usr/local/amoeba/bin/amoeba
amoeba start|stop
在三台mysql上添加权限开放给amoeba访问
bash
#amooba访问数据库的账号
#mysql-master
#授权test账号可从108网段登录
mysql> grant all on *.* to test@'192.168.108.%' identified by '123.com';
#mysql-slave01
mysql> grant all on *.* to test@'192.168.108.%' identified by '123.com';
#mysql-slave02
mysql> grant all on *.* to test@'192.168.108.%' identified by '123.com';
回到amoeba服务器
bash
#进入amoeba目录
[root@amoeba ~]# cd /usr/local/amoeba/
#编辑amoeba主配置文件
[root@amoeba amoeba]# vim conf/amoeba.xml
---30行--
#客户端访问amoeba账号
<property name="user">amoeba</property
----32行---------
#客户端访问ameoba密码
<property name="password">123456</property>
---117和120-去掉注释-
115行 <property name="defaultPool">master</property>
116
117
118行 <property name="writePool">master</property>
119行 <property name="readPool">slaves</property>
120
#数据库配置,编辑后端数据库节点文件
[root@amoeba amoeba]# vim conf/dbServers.xml
---23--注意!!!(mysql5.7,默认没有test数据库所以需要修改为mysql数据库)-(mysql5.5直接忽略)--
<!-- mysql schema -->
<property name="schema">mysql</property>
--25行到30行,第30行-->移动到28行后面
25 <!-- mysql user -->
26 <property name="user">test</property>
27
28 <!-- mysql password -->
29 <property name="password">123.com</property>
30
-----45到50行主服务器地址---
45行 <dbServer name="master" parent="abstractServer">
48行 <property name="ipAddress">192.168.108.101</property>
--52到57行从服务器主机名-
52行 <dbServer name="slave1" parent="abstractServer">
--55-从服务器地址-
55 <property name="ipAddress">192.168.108.102</property>
---52到57行复制一份在58行后面
原52行 <dbServer name="slave2" parent="abstractServer">
--55-从服务器地址-
原55 <property name="ipAddress">192.168.108.103</property>
---仅跟在上面的配置后面,multiPool行(本来就有,修改)
<dbServer name="slaves" virtual="true">
#不改,从库多节点连接池类
<poolConfig class="com.meidusa.amoeba.server.MultipleServerPool
#从库池包含slave1和slave2两个节点
<property name="poolNames">slave1,slave2</property>
</poolConfig> #不改
#后台启动amoeba
[root@amoeba ~]# /usr/local/amoeba/bin/amoeba start&
[1] 33499
#查看java进程监听端口
[root@amoeba ~]# netstat -anpt | grep java
tcp6 0 0 :::8066 :::* LISTEN
33499/java
tcp6 0 0 127.0.0.1:21128 :::* LISTEN
33499/java
tcp6 0 0 192.168.108.110:41754 192.168.108.101:3306 ESTABLISHED
33499/java
tcp6 0 0 192.168.108.110:41722 192.168.108.102:3306 ESTABLISHED
33499/java
tcp6 0 0 192.168.108.110:36956 192.168.108.103:3306 ESTABLISHED
33499/java
vim conf/dbServers.xml 结果如下


测试客户端
bash
#安装mysql客户端
[root@mysql-client ~]# yum install -y mysql
#连接amoeba服务器,8086端口在amoeba上执行netstat -anpt|grep java看
[root@mysql-client ~]# mysql -u amoeba -p123456 -h 192.168.108.110 -P8066
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MySQL connection id is 927449563
Server version: 5.1.45-mysql-amoeba-proxy-2.2.0
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MySQL [(none)]>

在MASTER上
bash
#登录主库
[root@mysql-master ~]# mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 10
Server version: 5.7.17-log Source distribution
Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> use school;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
#在主库插入鸣人记录
mysql> insert student (name,age)values('鸣人',20);
Query OK, 1 row affected (0.00 sec)
#此时会同步
#mysql-slave01
mysql> select * from student;
+----+--------+------+--------+
| id | name | age | gender |
+----+--------+------+--------+
| 10 | 路飞 | 20 | M |
| 11 | 鸣人 | 20 | M |
+----+--------+------+--------+
2 rows in set (0.00 sec)
#mysql-slave02
mysql> select * from student;
+----+--------+------+--------+
| id | name | age | gender |
+----+--------+------+--------+
| 10 | 路飞 | 20 | M |
| 11 | 鸣人 | 20 | M |
+----+--------+------+--------+
2 rows in set (0.00 sec)
在两台从上
bash
# mysql-slave01
#停止从库复制
mysql> stop slave;
# mysql-slave02
#停止从库复制
mysql> stop slave;
在客户端上插入数据,内容不会同步
bash
#mysql-client上添加,由于不会同步,只有mysql-master192.168.108.101节点有该记录
# mysql-client
MySQL [school]> insert student (name,age)values('卡卡西',30);
在mysql-slave01上
bash
#mysql-slave01
mysql> use school;
#在从库上插入卡卡西31
mysql> insert student (name,age)values('卡卡西',31);
mysql-slave02上
bash
# mysql-slave02
mysql> use school;
#在从库上插入卡卡西32
mysql> insert student (name,age)values('卡卡西',32);
验证主从复制
在mysql-slave01和mysql-slave02上查看
bash
# mysql-slave01
mysql> select * from student;
+----+-----------+------+--------+
| id | name | age | gender |
+----+-----------+------+--------+
| 10 | 路飞 | 20 | M |
| 11 | 鸣人 | 20 | M |
| 12 | 卡卡西 | 31 | M |
+----+-----------+------+--------+
3 rows in set (0.00 sec)
#mysql-slave02
mysql> select * from student;
+----+-----------+------+--------+
| id | name | age | gender |
+----+-----------+------+--------+
| 10 | 路飞 | 20 | M |
| 11 | 鸣人 | 20 | M |
| 12 | 卡卡西 | 32| M |
+----+-----------+------+--------+
3 rows in set (0.00 sec)
并没有将客户端写入的insert student (name,age)values('卡卡西',30);同步
在mysq-master上查看内容发现写入成功:
bash
# mysql-master
mysql> select * from student;
+----+-----------+------+--------+
| id | name | age | gender |
+----+-----------+------+--------+
| 10 | 路飞 | 20 | M |
| 11 | 鸣人 | 20 | M |
| 12 | 卡卡西 | 30 | M |
+----+-----------+------+--------+
3 rows in set (0.00 sec)
验证读写分离
在客户端上测试,第一次会向从服务器1读数,据-第二次会向从2读取
bash
#mysql-client
MySQL [(none)]> select * from school.student;
+----+-----------+------+--------+
| id | name | age | gender |
+----+-----------+------+--------+
| 10 | 路飞 | 20 | M |
| 11 | 鸣人 | 20 | M |
| 12 | 卡卡西 | 31 | M |
+----+-----------+------+--------+
3 rows in set (0.02 sec)
#第二次查询
MySQL [(none)]> select * from school.student;
+----+-----------+------+--------+
| id | name | age | gender |
+----+-----------+------+--------+
| 10 | 路飞 | 20 | M |
| 11 | 鸣人 | 20 | M |
| 12 | 卡卡西 | 32 | M |
+----+-----------+------+--------+
3 rows in set (0.00 sec)
emctl stop firewalld.service
#临时关闭SELinux
[root@amoeba ~]# setenforce 0
#给JDK安装包加可执行权限
[root@amoeba ~]# chmod +x jdk-6u14-linux-x64.bin
#执行JDK安装脚本
[root@amoeba ~]# ./jdk-6u14-linux-x64.bin
#到yes的时候,输入yes按enter
#移动JDK到标准目录
[root@amoeba ~]# mv jdk1.6.0_14/ /usr/local/jdk1.6
#编辑环境变量配置文件
[root@amoeba ~]# vim /etc/profile
最下面加
#java家目录
export JAVA_HOME=/usr/local/jdk1.6
#类环境和jre
export CLASSPATH=$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib
#把java命令加入PATH
export PATH=$JAVA_HOME/lib:$JAVA_HOME/jre/bin/:$PATH:$HOME/bin
#指定amoeba路径
export AMOEBA_HOME=/usr/local/amoeba
#把amoeba命令加入PATH
export PATH=$PATH:$AMOEBA_HOME/bin
#重新加载环境变量
[root@amoeba ~]# source /etc/profile
#创建amoeba安装目录
[root@amoeba ~]# mkdir /usr/local/amoeba
#解压amoeba安装包到指定目录
[root@amoeba ~]# tar zxvf amoeba-mysql-binary-2.2.0.tar.gz -C /usr/local/amoeba/
#递归给amoeba目录755权限
[root@amoeba ~]# chmod -R 755 /usr/local/amoeba/
#执行结果显示amoeba start|stop说明安装成功
[root@amoeba ~]# /usr/local/amoeba/bin/amoeba
amoeba start|stop
在三台mysql上添加权限开放给amoeba访问
bash
#amooba访问数据库的账号
#mysql-master
#授权test账号可从108网段登录
mysql> grant all on *.* to test@'192.168.108.%' identified by '123.com';
#mysql-slave01
mysql> grant all on *.* to test@'192.168.108.%' identified by '123.com';
#mysql-slave02
mysql> grant all on *.* to test@'192.168.108.%' identified by '123.com';
回到amoeba服务器
bash
#进入amoeba目录
[root@amoeba ~]# cd /usr/local/amoeba/
#编辑amoeba主配置文件
[root@amoeba amoeba]# vim conf/amoeba.xml
---30行--
#客户端访问amoeba账号
<property name="user">amoeba</property
----32行---------
#客户端访问ameoba密码
<property name="password">123456</property>
---117和120-去掉注释-
115行 <property name="defaultPool">master</property>
116
117
118行 <property name="writePool">master</property>
119行 <property name="readPool">slaves</property>
120
#数据库配置,编辑后端数据库节点文件
[root@amoeba amoeba]# vim conf/dbServers.xml
---23--注意!!!(mysql5.7,默认没有test数据库所以需要修改为mysql数据库)-(mysql5.5直接忽略)--
<!-- mysql schema -->
<property name="schema">mysql</property>
--25行到30行,第30行-->移动到28行后面
25 <!-- mysql user -->
26 <property name="user">test</property>
27
28 <!-- mysql password -->
29 <property name="password">123.com</property>
30
-----45到50行主服务器地址---
45行 <dbServer name="master" parent="abstractServer">
48行 <property name="ipAddress">192.168.108.101</property>
--52到57行从服务器主机名-
52行 <dbServer name="slave1" parent="abstractServer">
--55-从服务器地址-
55 <property name="ipAddress">192.168.108.102</property>
---52到57行复制一份在58行后面
原52行 <dbServer name="slave2" parent="abstractServer">
--55-从服务器地址-
原55 <property name="ipAddress">192.168.108.103</property>
---仅跟在上面的配置后面,multiPool行(本来就有,修改)
<dbServer name="slaves" virtual="true">
#不改,从库多节点连接池类
<poolConfig class="com.meidusa.amoeba.server.MultipleServerPool
#从库池包含slave1和slave2两个节点
<property name="poolNames">slave1,slave2</property>
</poolConfig> #不改
#后台启动amoeba
[root@amoeba ~]# /usr/local/amoeba/bin/amoeba start&
[1] 33499
#查看java进程监听端口
[root@amoeba ~]# netstat -anpt | grep java
tcp6 0 0 :::8066 :::* LISTEN
33499/java
tcp6 0 0 127.0.0.1:21128 :::* LISTEN
33499/java
tcp6 0 0 192.168.108.110:41754 192.168.108.101:3306 ESTABLISHED
33499/java
tcp6 0 0 192.168.108.110:41722 192.168.108.102:3306 ESTABLISHED
33499/java
tcp6 0 0 192.168.108.110:36956 192.168.108.103:3306 ESTABLISHED
33499/java
vim conf/dbServers.xml 结果如下
外链图片转存中...(img-cv980pva-1790215883970)
外链图片转存中...(img-fRsMcAPf-1790215883970)
测试客户端
bash
#安装mysql客户端
[root@mysql-client ~]# yum install -y mysql
#连接amoeba服务器,8086端口在amoeba上执行netstat -anpt|grep java看
[root@mysql-client ~]# mysql -u amoeba -p123456 -h 192.168.108.110 -P8066
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MySQL connection id is 927449563
Server version: 5.1.45-mysql-amoeba-proxy-2.2.0
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MySQL [(none)]>
外链图片转存中...(img-T5UD3TWP-1790215883970)
在MASTER上
bash
#登录主库
[root@mysql-master ~]# mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 10
Server version: 5.7.17-log Source distribution
Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> use school;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
#在主库插入鸣人记录
mysql> insert student (name,age)values('鸣人',20);
Query OK, 1 row affected (0.00 sec)
#此时会同步
#mysql-slave01
mysql> select * from student;
+----+--------+------+--------+
| id | name | age | gender |
+----+--------+------+--------+
| 10 | 路飞 | 20 | M |
| 11 | 鸣人 | 20 | M |
+----+--------+------+--------+
2 rows in set (0.00 sec)
#mysql-slave02
mysql> select * from student;
+----+--------+------+--------+
| id | name | age | gender |
+----+--------+------+--------+
| 10 | 路飞 | 20 | M |
| 11 | 鸣人 | 20 | M |
+----+--------+------+--------+
2 rows in set (0.00 sec)
在两台从上
bash
# mysql-slave01
#停止从库复制
mysql> stop slave;
# mysql-slave02
#停止从库复制
mysql> stop slave;
在客户端上插入数据,内容不会同步
bash
#mysql-client上添加,由于不会同步,只有mysql-master192.168.108.101节点有该记录
# mysql-client
MySQL [school]> insert student (name,age)values('卡卡西',30);
在mysql-slave01上
bash
#mysql-slave01
mysql> use school;
#在从库上插入卡卡西31
mysql> insert student (name,age)values('卡卡西',31);
mysql-slave02上
bash
# mysql-slave02
mysql> use school;
#在从库上插入卡卡西32
mysql> insert student (name,age)values('卡卡西',32);
验证主从复制
在mysql-slave01和mysql-slave02上查看
bash
# mysql-slave01
mysql> select * from student;
+----+-----------+------+--------+
| id | name | age | gender |
+----+-----------+------+--------+
| 10 | 路飞 | 20 | M |
| 11 | 鸣人 | 20 | M |
| 12 | 卡卡西 | 31 | M |
+----+-----------+------+--------+
3 rows in set (0.00 sec)
#mysql-slave02
mysql> select * from student;