note4cs/技术/MySQL/MySQL相关.md
2025-03-19 14:36:09 +08:00

110 lines
8.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## ACID vs BASE
**ACID**(原子性、一致性、隔离性、持久性)和 **BASE**(基本可用、软状态、最终一致性)是数据库事务和系统设计的两种核心理念,分别适用于不同场景。
### **ACID**
*适用于传统关系型数据库(如 MySQL、PostgreSQL*
1. **原子性Atomicity**:事务要么全部成功,要么全部失败回滚。
2. **一致性Consistency**:数据始终符合预定义规则(如约束、触发器)。
3. **隔离性Isolation**:并发事务互不干扰,结果等同于串行执行。
4. **持久性Durability**:事务提交后数据永久保存,即使系统崩溃也不丢失。
**典型场景**:银行转账、订单支付、库存扣减等对数据准确性要求极高的场景。
### **BASE**
*适用于分布式 NoSQL 系统(如 Cassandra、MongoDB*
1. **基本可用Basically Available**:系统即使部分故障,仍能响应请求(允许降级)。
2. **软状态Soft State**:数据可能随时间变化,无需实时同步。
3. **最终一致性Eventually Consistent**:数据更新会延迟同步,但最终全局一致。
**典型场景**:社交网络动态、电商商品浏览、日志存储等高并发、可容忍短暂不一致的场景。
### **核心差异**
| **维度** | **ACID** | **BASE** |
|----------------|-----------------------------------|-----------------------------------|
| **一致性** | 强一致性(实时) | 最终一致性(延迟) |
| **优先目标** | 数据安全与准确性 | 高可用性与扩展性 |
| **适用系统** | 单机/集中式数据库 | 分布式系统(如微服务、云原生) |
| **性能特点** | 读写延迟较高,吞吐量较低 | 读写延迟低,吞吐量高 |
**一句话总结**
- **ACID**:牺牲性能换安全,适合“钱不能错”(如银行系统)。
- **BASE**:牺牲强一致换高可用,适合“用户能等”(如微博评论)。
根据业务需求选择:**要么严格保数据,要么灵活保体验**。
## 索引的分类
-**「数据结构」** 分类B+tree索引、Hash索引、Full-text索引。
-**「物理存储」** 分类:聚簇索引(主键索引)、二级索引(辅助索引)。
-**「字段特性」** 分类:主键索引、唯一索引、普通索引、前缀索引。
-**「字段个数」** 分类:单列索引、联合索引。
## InnoDB默认索引
在创建表时InnoDB 存储引擎会根据不同的场景选择不同的列作为索引:
- 如果有主键默认会使用主键作为聚簇索引的索引键key
- 如果没有主键,就选择第一个不包含 NULL 值的唯一列作为聚簇索引的索引键key
- 在上面两个都没有的情况下InnoDB 将自动生成一个**隐式自增 id (不可见的名为row_id的列名为GEN_CLUST_INDEX的聚簇索引该列是一个6字节的自增数值)** 列作为聚簇索引的索引键key
其它索引都属于**辅助索引Secondary Index**,也被称为**二级索引或非聚簇索引**。创建的主键索引和二级索引默认使用的是 **B+Tree 索引**
## MySQL 的存储引擎有哪些为什么常用InnoDB
MySQL 的存储引擎常用的主要有 3 个:
- **InnoDB存储引擎**支持事务处理支持外键支持崩溃修复能力和并发控制。如果需要对事务的完整性要求比较高比如银行要求实现并发控制比如售票那选择InnoDB有很大的优势。如果需要频繁的更新、删除操作的数据库也可以选择InnoDB因为支持事务的提交commit和回滚rollback
- **MyISAM存储引擎**插入数据快空间和内存使用比较低。如果表主要是用于插入新记录和读出记录那么选择MyISAM能实现处理高效率。如果应用的完整性、并发性要求比 较低也可以使用。如果数据表主要用来插入和查询记录则MyISAM引擎能提供较高的处理效率
- **MEMORY存储引擎**所有的数据都在内存中数据的处理速度快但是安全性不高。如果需要很快的读写速度对数据的安全性要求较低可以选择MEMOEY。它对表的大小有要求不能建立太大的表。所以这类数据库只使用在相对较小的数据库表。如果只是临时存放数据数据量不大并且不需要较高的数据安全性可以选择将数据保存在内存中的Memory引擎MySQL中使用该引擎作为临时表存放查询的中间结果
**常用InnoDB的原因是支持事务且最小锁的粒度是行级锁。**
## 执行一条 SQL 查询语句,期间发生了什么?
- 连接器:建立连接,管理连接、校验用户身份;
- 查询缓存查询语句如果命中查询缓存则直接返回否则继续往下执行。MySQL 8.0 已删除该模块;
- 解析 SQL通过解析器对 SQL 查询语句进行词法分析、语法分析,然后构建语法树,方便后续模块读取表名、字段、语句类型;
- 执行 SQL执行 SQL 共有三个阶段:
- 预处理阶段:检查表或字段是否存在;将 select * 中的 * 符号扩展为表上的所有列。
- 优化阶段:基于查询成本的考虑, 选择查询成本最小的执行计划;
- 执行阶段:根据执行计划执行 SQL 查询语句,从存储引擎读取记录,返回给客户端;
![img](https://cdn.xiaolincoding.com/gh/xiaolincoder/mysql/sql%E6%89%A7%E8%A1%8C%E8%BF%87%E7%A8%8B/mysql%E6%9F%A5%E8%AF%A2%E6%B5%81%E7%A8%8B.png)
## MySQL 的 NULL 值是怎么存放的?
MySQL 的 Compact 行格式中会用「NULL值列表」来标记值为 NULL 的列NULL 值并不会存储在行格式中的真实数据部分。
NULL值列表会占用 1 字节空间,当表中所有字段都定义成 NOT NULL行格式中就不会有 NULL值列表这样可节省 1 字节的空间。
MySQL 怎么知道 varchar(n) 实际占用数据的大小?
MySQL 的 Compact 行格式中会用「变长字段长度列表」存储变长字段实际占用的数据大小。
## varchar(n) 中 n 最大取值为多少?
一行记录最大能存储 65535 字节的数据但是这个是包含「变长字段字节数列表所占用的字节数」和「NULL值列表所占用的字节数」。所以 我们在算 varchar(n) 中 n 最大值时,需要减去这两个列表所占用的字节数。
如果一张表只有一个 varchar(n) 字段,且允许为 NULL字符集为 ascii。varchar(n) 中 n 最大取值为 65532。
计算公式65535 - 变长字段字节数列表所占用的字节数 - NULL值列表所占用的字节数 = 65535 - 2 - 1 = 65532。
如果有多个字段的话,要保证所有字段的长度 + 变长字段字节数列表所占用的字节数 + NULL值列表所占用的字节数 <= 65535。
## 行溢出后MySQL 是怎么处理的?
如果一个数据页存不了一条记录InnoDB 存储引擎会自动将溢出的数据存放到「溢出页」中。
Compact 行格式针对行溢出的处理是这样的:当发生行溢出时,在记录的真实数据处只会保存该列的一部分数据,而把剩余的数据放在「溢出页」中,然后真实数据处用 20 字节存储指向溢出页的地址,从而可以找到剩余数据所在的页。
Compressed 和 Dynamic 这两种格式采用完全的行溢出方式,记录的真实数据处不会存储该列的一部分数据,只存储 20 个字节的指针来指向溢出页。而实际的数据都存储在溢出页中。
## B+索引
![B+Tree](https://ucc.alicdn.com/pic/developer-ecology/xtzmdbufapzy2_9c59c10539f54dddabf6438bd04896b3.png?x-oss-process=image/resize,w_1400/format,webp)
相比于标准的B+树InnoDB使用的B+树有如下特点:
- B+ 树的叶子节点之间是用「双向链表」进行连接,既能向右遍历、也能向左遍历
- B+ 树点节点内容是数据页,数据页里存放了用户的记录以及各种信息,每个数据页默认大小是 16 KB