MySQL 服务基础介绍
MySQL 起源介绍:
MySQL 这个名称是 My + SQL,是MySQL创始人以她的女儿My命名的一种数据库管理系统,MySQL在2008年被SUN公司收购,SUN公司又在2010年被收购。
MySQL 官网:https://www.mysql.com/
MySQL 两大版本:
- 社区版(CE):代码开源,可以免费使用。
- 企业版(EE):需要收费,但是提供了比开源版本更多的功能和插件。
MySQL 三大分支:
- MariaDB:当时SUN公司被Oracle收购后,担心 MySQL未来会闭源,所以MySQL创始人又以他小女儿的名字Maria,然后基于MySQL开发了一个新的分支。
- Oracle MySQL:最官方的 MySQL 版本,由 Oracle 进行维护。
- Percona Server:在MySQL基础上进行了优化,提供更高的性能和可靠性,特别适合高负载的生产环境。
MySQL 主流版本:
- MySQL 5.7:2015年发布,目前最新的版本是MySQL5.7.44,但是MySQL官方已经停止维护了。
- MySQL 8.0:2018年发布,性能更加稳定,功能更加强大,并发性能更好,是前官方主推版本。
MySQL 系统架构:
基于C/S架构开发而来,由客户端和服务端组成。
- 服务端:负责存储数据、处理数据操作请求。服务端采用单进程,多线程的架构进行设计,这使得在大量并发连接时,系统的资源开销小。并且 更适合 I/O 密集型的数据库工作负载。
- 客户端:客户端工具通过mysql协议与 MySQL 服务端进行交互。
MySQL 存储引擎
MySQL的存储引擎是MySQL存储、读取和管理数据的一种形式。MySQL 常用存储引擎有以下几种。
- MyISAM:MySQL 5.5之前的版本默认使用的存储引擎,适合读多写少的场景。不支持事务、外键、不支持行级锁。MySQL5.5及其后面的版本默认都没用MyISAM做为存储引擎了。
- InoDB:MySQL 5.5及其后续的版本默认使用的存储引擎,支持事务、外键、行级锁定,并发性能更好,并且有更好的数据奔溃恢复机制。
- MEMORY :MySQL中的information_schema和performance_schema这两个自带的数据库使用的MEMORY 这种存储引擎,特点在于将数据存储在内存中。
MySQL InoDB 引擎
InnoDB 引擎在 MySQL 中数据的物理存储结构:
MySQL | 数据库存储位置 | 表结构存储 | 表数据和索引存储 | 其他元数据(如外键)存储 |
---|---|---|---|---|
MySQL 5.7 及以前 | MySQL 数据目录下的 数据库名/ 目录 | 数据库目录下的 table_name.frm 文件 | 数据库目录下的 table_name.ibd 文件 | ibdata1 (系统表空间,位于数据目录下) |
MySQL 8.0 | MySQL 数据目录下的 数据库名/ 目录 | InnoDB 数据字典(存储于 ibdata1 ,无 .frm 文件) | 数据库目录下的 table_name.ibd 文件 | 同上,InnoDB 系统表空间中的系统表(如外键信息) |
InnoDB 引擎在 MySQL 中数据的存储机制:
MySQL 使用 InnoDB 引擎来管理数据时,数据是以 数据页(Page) 为最小单位进行磁盘存储和管理,类似于操作系统中的块(Block)或扇区。每个数据页的默认大小是 16KB,可以通过参数 innodb_page_size 配置(但只能在初始化时设置)。
数据发生变更后,MySQL 不会立即将每条记录单独写入磁盘,而是将变更写入内存中的缓冲池,使对应的数据页变成脏页(Dirty Page)。随后,MySQL 以“页”为单位批量刷新这些脏页到磁盘。
每个数据页都有一个 校验字段,用于检查数据页在存储过程中是否损坏,例如判断是否存在写入不完整或数据页被破坏的情况。
MySQL中的脏页就是数据页内容已经发生变更,但该变更只存在于内存中,还没有同步到硬盘上的 .ibd 文件中。
MySQL InnoDB 事务特性:
事务是MySQL中InnoDB引擎支持的一种特性,事务指的就是一组操作,这组操作要么全部成功,要么全部失败,不能出现某些操作成功,某些操作失败的情况。
MySQL 中中的一切操作皆是事务,包括DML、DDL以及MySQL内部的维护操作。这些都是在事务上下文中进行。但是只有 DML 操作受事务控制,意思就是只有DML操作可以被回滚。
MySQL 中事务四大特性:
MySQL 中事务的四大特性简称为ACID,A是原子性,C是一致性,I是隔离性,D是持久性。
1、事务的原子性:
- 原子性的理解:事务的操作像原子一样不可分割。所以要求事务内的所有操作要么都成功,那么都失败,不能只执行成功一部分。例如:某个事务包含多条数据更新语句,只要其中任意一条执行失败,整个事务就会被回滚,之前已经执行的操作也会被撤销,最终效果就像这个事务从未发生一样。
- 原子性的实现:InnoDB 存储引擎通过 Undo Log(回滚日志) 来实现原子性。当事务执行过程中对某条记录进行修改时,InnoDB 会先将该记录的原始数据写入 Undo Log。如果事务最终因为某些原因失败或被主动回滚,系统就可以利用 Undo Log 中记录的原始值,将数据恢复到事务开始前的状态,从而实现“全部撤销”,确保事务的原子性。
2、事务的一致性
- 一致性的概念:不论事务成功还是失败,数据需要是一致的。假设某个数据是100,事务执行失败后导致变为200就不行。
- 一致性的实现:是通过原子性、隔离性、持久性,以及数据库的约束机制共同配合实现的。
3、事务的隔离性:
- 隔离性的概念:多个事务并发执行时,彼此之间不会相互干扰,每个事务所看到的数据应当是事务自身的一致视角。
- 隔离性的实现:通过 MVCC(多版本并发控制)机制 实现,当某个事务修改一条记录时,InnoDB 会将该记录的原始数据写入 Undo Log 中;此时,其他并发事务如果尝试读取该记录,InnoDB 并不会阻塞它们,而是根据各自事务的 Read View(读视图),判断当前版本是否可见。如果不可见,则从 Undo Log 中构造一个该事务可见的历史版本,从而实现 非阻塞读。
4、事务的持久性:
- 持久性的概念:一旦事务成功提交,其对数据库所做的修改就必须被永久保留,即使系统发生崩溃、宕机等异常,也不能丢失。
- 是就行的实现:通过 WAL(Write-Ahead Logging,日志先行写入)机制 来实现持久性保障。具体流程如下:
- a、当事务提交时,InnoDB 会将修改操作记录为 Redo Log,并将 Redo Log 从内存中的日志缓冲区写入磁盘文件
- b、只有当 Redo Log 中的提交标志被成功写入磁盘后,事务才被视为真正提交成功,客户端才会收到提交成功的响应;
- c、此时即使数据页尚未真正写入磁盘(假设在硬盘缓冲区),因为 Redo Log 已持久化存储该部分数据,系统重启时就可以通过 Redo Log 重做事务操作,恢复数据,从而保证数据不丢失,实现持久性。
MySQL 数据崩溃恢复机制:
数据崩溃场景:服务器宕机、异常断电、进程崩溃退出等,导致部分数据尚未写入磁盘,造成数据不一致、数据页损坏等问题。
- Redo log 重新刷入标记过的事务:服务启动后,首先检查Redo log中是否存在已标记的事务,然后将这些已经标记过的事务再次执行刷盘操作写入硬盘。
- Udo Log 回滚未完成事务:如果存在某些事务没执行完,就进行回滚,将数据恢复到初始状态。
- MySQL 数据页修复:MySQL 会对数据页进行校验,如果发现数据页发生损坏。会从
Doublewrite Buffer
中读取完整数据来恢复受损页,从而确保数据文件的一致性。
Doublewrite Buffer(双写缓冲区) 是 InnoDB 存储引擎为防止数据页在写入磁盘过程中发生“写入一半”的页损坏问题而设计的机制。
当事务执行过程中修改了某些数据页,这些页会被标记为脏页(即被修改但尚未写入磁盘)。当脏页数量达到一定程度时,会将脏页写入磁盘。MySQL会先将这些页写入到共享表空间中的 Doublewrite Buffer 区域,再从该区域将页写入到目标 .ibd 文件中。
如果在将数据页写入目标文件的过程中发生宕机,MySQL 会在重启时发现页损坏,就会从 Doublewrite Buffer 中读取原始页内容进行恢复,从而确保数据文件的一致性和页的完整性。
MySQL 仍然崩溃无法恢复的原因:
MySQL 拥有完善的数据崩溃恢复机制,但极端情况下确实仍可能导致数据损坏,严重时甚至 MySQL 无法正常启动。最主要的原因就是数据页本身损坏后导致没有 redo/undo 能恢复,这样就会使得MySQL服务崩溃失败。
MySQL 字符编码
MySQL 中的字符编码由字符集和字符排序集两部分组成,他们的作用分别如下:
- 字符集:定义了字符到二进制的映射方式,即决定了一个字符在存储时用什么编码表示、占几个字节。
- 字符排序集:决定了字符串比较和排序的规则。一般字符集都有一个与之对应的默认字符排序集。
MySQL 常见的字符集:
- utfmb3(utf8 most bytes 3):是 MySQL中对UTF8(使用 1~4 个字节表示一个符号,根据不同的符号而变化字节长度)的一种具体实现。使用1 到 3 个字节来表示一个字符,由于使用 1 到 3 个字节的限制,表情符号和某些历史文字等无法被正确表示。
- uftmb4(utf8 most bytes 4 ):也是MySQL对UTF8的一种具体实现,使用1 到 4 个字节来表示一个字符,所以表情符号、更广泛的汉字以及其他特殊字符都可以通过这种字符集存储和表示。。
MySQL 常见的字符排序集:
- utf8mb4_bin:区分大小写、按二进制值比较
- utf8mb4_general_ci:字符比较时,不区分大小写(ci = case-insensitive)
- utf8mb4_unicode_ci:按照 Unicode 规范排序,不区分大小写
说明:带
_ci
后缀的不区分大小写,带_cs后
缀的区分大小写,带_bin
后缀的,按二进制值比较字符来区分大小写
例如:使用 utf8mb4_general_ci 这种字符排序集
# 两条语句等价
SELECT * FROM users WHERE username = 'John';
SELECT * FROM users WHERE username = 'john';
MySQL 三种引号
- 单引号和双引号:默认情况下两者作用一样的,都是用于表示字符串值
- 反引号的作用:用于引用标识符,也就是数据库对象,例如:数据库名、表名、字段名字。
例如:
# 会报语法错误,因为单引号只能用于字符串,这里是表名
show create table 'tb_device'\G
# 不会报错,因为反引号本来就是用于标识符
show create table "tb_device"\G
MySQL 系统数据库
sys
:从performance_schema数据库中获取的信息,存储易读版性能数据。information_schema
:这里存放的是数据库中数据对象的属性信息,存储在内存中,是自动生成的。performance_schema
:这里存储的是MySQL运行过程中的性能统计信息。mysql
:这是MySQL的核心系统数据库,MySQL的账号、密码、权限等信息都存储在该库中。
例如:查看当前MySQL存在的用户信息
mysql> select user,host from mysql.user;
+------------------+-----------+
| user | host |
+------------------+-----------+
| ehigh | % |
| replica | % |
| root | % |
| visitor | % |
| debian-sys-maint | localhost |
| ehigh | localhost |
| mysql.infoschema | localhost |
| mysql.session | localhost |
| mysql.sys | localhost |
| root | localhost |
+------------------+-----------+
10 rows in set (0.00 sec)
MySQL 账号管理:
MySQL的账号由用户名何主机名两部分组成,通过 @
符号进行分隔,这样设计的目的是为了提高安全性何精细化的权限控制。
- 用户名:可以使用任意字符进行命名,但是不推荐使用特殊字符,而是使用数字、字符和下划线的组合。
- 主机名:可以是一个具体的IP地址,也可以结合通配符进行匹配。(MySQL支持标准SQL常用的两个通配符 _ 和 %)
例如:
tom@'192.168.2.1'
tom@'192.168.%.%'
主机名 "%“和"localhost” 的区别:
%
:表示任何主机,任意一个主机都可以使用该账号连接到服务端。localhost
:代表本地主机,即数据库服务器本机,只有在MySQL服务端所在主机才能连接到服务端。
服务端本地使用user@'%'
和 user@'localhost'
连接服务端的区别:
user@'%'
:服务端会将%解析为具体IP地址,此时会通过TCP/IP 进行连接,服务端会使用主机名为 % 或具体IP地址的账号进行验证。
-user@'localhost
’:会使用本地的Unix 域套接字进行连接。使用主机名为 localhost 的账号进行验证