0%

一、关系型数据库概述

关系型数据库(RDBMS)基于关系模型,数据以表(Table)的形式组织,表之间有明确的关联关系,通过 SQL(Structured Query Language)进行操作。

阅读全文 »

一、什么是 REST

REST(Representational State Transfer)是一种架构风格,而不是协议或标准。它定义了一组约束,遵循这些约束设计的 API 被称为 RESTful API。

阅读全文 »

一、Express 是什么

Express 是 Node.js 最流行的 Web 应用框架,它基于 Node.js 原生 http 模块构建,在请求响应流程上抽象出中间件机制,使开发者能以声明式的方式组织请求处理逻辑。

阅读全文 »

一、Nginx 是什么

Nginx 是一个高性能的 HTTP 和反向代理服务器,以其高并发、低内存占用和丰富的功能特性成为目前最流行的 Web 服务器之一。常用于静态资源托管、反向代理、负载均衡、HTTPS 配置和 API 网关。

阅读全文 »

在 Linux 环境通过 npm 全局安装 pm2 后,运行 pm2 命令却显示没有找到该命令:-bash: pm2: command not found。上网查找资料发现,这是因为没有创建软连接导致的。

阅读全文 »

虽然响应式页面能够做到样式随着屏幕的变化保持一致,但对于移动端和 PC 端两个截然不同的体系来说,更好的用户体验无疑是为两者分别准备一套代码。也就是说,如果一个网站做了这样的设备适配,那么用户在移动端访问到的就是移动端的页面,在 PC 端访问到的就是 PC 端的页面。我们可以在 Nginx 服务器的 conf.d 文件中进行配置,以根据设备类型的不同来做页面的跳转。

阅读全文 »

在 nginx 服务器上准备调试 Nuxt 项目时,打开浏览器却发生了下图的情形。可以看到,样式发生明显错乱,图片资源也没有加载出来。而我在本地代码调试时,显示效果是正常的。在反复确认本地代码和服务端上的代码并无二致后,查看报错信息发现引入的 css 文件、js 文件以及图片资源都没有加载出来。

阅读全文 »

一、MongoDB 是什么

MongoDB 是一个文档型 NoSQL 数据库,以 JSON 风格的 BSON 格式存储数据。它不要求预定义 Schema,支持嵌入式文档和数组,天然适合表达复杂的数据结构。

阅读全文 »

一、连接与基本操作

1
2
3
4
5
mysql -u root -p                           # 连接
SHOW DATABASES; # 查看数据库
CREATE DATABASE myapp CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE myapp; # 使用数据库
SELECT DATABASE(); # 查看当前数据库

二、表操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
age INT DEFAULT 0,
status TINYINT DEFAULT 1 COMMENT '1:active 0:inactive',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

DESCRIBE users; -- 查看表结构
SHOW CREATE TABLE users; -- 查看建表语句

ALTER TABLE users ADD COLUMN phone VARCHAR(20);
ALTER TABLE users MODIFY COLUMN age TINYINT;
ALTER TABLE users DROP COLUMN phone;

DROP TABLE users; -- 删除表
TRUNCATE TABLE users; -- 清空表(重置自增 ID)

常用数据类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
数值:
TINYINT 1 字节 (-128~127 / 0~255)
INT 4 字节 (-21亿~21亿)
BIGINT 8 字节
DECIMAL(10,2) 定点数 (精确小数,用于金额)

字符串:
CHAR(n) 定长 (性能好,但浪费空间)
VARCHAR(n) 变长 (常用,最长 65535)
TEXT 文本 (最大 64KB)
LONGTEXT 大文本 (最大 4GB)

时间:
DATE 日期 (2026-07-28)
DATETIME 日期时间 (2026-07-28 10:00:00)
TIMESTAMP 时间戳 (带时区,2038 年问题)

三、CRUD

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
-- INSERT
INSERT INTO users (name, email, age) VALUES ('Alice', 'alice@example.com', 25);
INSERT INTO users (name, email, age) VALUES
('Bob', 'bob@example.com', 30),
('Charlie', 'charlie@example.com', 28);

INSERT INTO users SET name='David', email='david@example.com';

-- SELECT
SELECT * FROM users;
SELECT name, email FROM users WHERE age > 25;
SELECT * FROM users WHERE name LIKE 'A%';
SELECT * FROM users WHERE email IN ('alice@ex.com', 'bob@ex.com');
SELECT * FROM users WHERE age BETWEEN 20 AND 30;
SELECT * FROM users ORDER BY age DESC, created_at ASC LIMIT 10 OFFSET 0;

-- 聚合
SELECT COUNT(*), AVG(age), MAX(age), MIN(age) FROM users;
SELECT status, COUNT(*) FROM users GROUP BY status;
SELECT age, COUNT(*) FROM users GROUP BY age HAVING COUNT(*) > 1;

-- UPDATE
UPDATE users SET age = 26 WHERE name = 'Alice';
UPDATE users SET age = age + 1 WHERE id = 1;

-- DELETE
DELETE FROM users WHERE id = 3;
DELETE FROM users WHERE age < 18;

查询执行顺序

1
FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT

四、JOIN

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
CREATE TABLE orders (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
product VARCHAR(100),
amount DECIMAL(10, 2),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id)
);

-- INNER JOIN:两表都有的数据
SELECT u.name, o.product, o.amount
FROM users u
INNER JOIN orders o ON u.id = o.user_id;

-- LEFT JOIN:左表全保留,右表没有的为 NULL
SELECT u.name, o.product
FROM users u
LEFT JOIN orders o ON u.id = o.user_id;

-- 统计每个用户的订单数
SELECT u.name, COUNT(o.id) AS order_count, COALESCE(SUM(o.amount), 0) AS total
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
GROUP BY u.id;

-- 多表 JOIN
SELECT u.name, o.product, oi.quantity
FROM users u
JOIN orders o ON u.id = o.user_id
JOIN order_items oi ON o.id = oi.order_id;

JOIN 对比

JOIN 类型结果
INNER JOINA ∩ B(交集)
LEFT JOINA 全保留 + B 匹配的
RIGHT JOINB 全保留 + A 匹配的
FULL OUTER JOINA ∪ B(MySQL 不支持,用 UNION 模拟)

五、索引

1
2
3
4
5
6
7
8
9
10
11
-- 创建索引
CREATE INDEX idx_email ON users(email); -- 单列索引
CREATE UNIQUE INDEX idx_email ON users(email); -- 唯一索引
CREATE INDEX idx_name_age ON users(name, age); -- 复合索引
CREATE FULLTEXT INDEX idx_content ON articles(content); -- 全文索引(MyISAM / InnoDB 5.6+)

-- 查看索引
SHOW INDEX FROM users;

-- 删除索引
DROP INDEX idx_email ON users;

复合索引的最左前缀原则

1
2
3
4
5
6
-- 复合索引 (a, b, c)
WHERE a = 1 -- ✅ 用到索引
WHERE a = 1 AND b = 2 -- ✅ 用到索引
WHERE a = 1 AND b = 2 AND c = 3 -- ✅ 用到索引
WHERE b = 2 -- ❌ 无法用到索引
WHERE a = 1 AND c = 3 -- 只能用到 a 部分的索引

EXPLAIN 分析查询

1
EXPLAIN SELECT * FROM users WHERE email = 'alice@example.com';
1
2
3
4
5
6
关键字段:
type ALL(全表扫描) / ref(索引等值) / range(范围) / const(主键)
possible_keys 可能用到的索引
key 实际用到的索引
rows 扫描行数
Extra Using index(覆盖索引)/ Using filesort(额外排序)

六、事务

1
2
3
4
5
6
7
START TRANSACTION;

UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;

COMMIT; -- 提交
-- ROLLBACK; -- 回滚

ACID 特性

1
2
3
4
A(Atomicity)原子性:事务要么全部成功,要么全部回滚
C(Consistency)一致性:事务前后数据状态一致
I(Isolation)隔离性:并发事务互不干扰
D(Durability)持久性:提交后数据不会丢失

隔离级别

1
2
3
4
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SET TRANSACTION ISOLATION LEVEL READ COMMITTED; -- Oracle 默认
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; -- MySQL 默认
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
隔离级别脏读不可重复读幻读
READ UNCOMMITTED
READ COMMITTED
REPEATABLE READ
SERIALIZABLE

七、SQL 高级查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
-- 子查询
SELECT * FROM users WHERE id IN (
SELECT user_id FROM orders WHERE amount > 100
);

-- EXISTS(通常比 IN 快)
SELECT * FROM users u WHERE EXISTS (
SELECT 1 FROM orders o WHERE o.user_id = u.id AND o.amount > 100
);

-- 窗口函数(MySQL 8.0+)
SELECT
name,
age,
ROW_NUMBER() OVER (ORDER BY age DESC) AS rank,
RANK() OVER (ORDER BY age DESC) AS rank_with_gap,
DENSE_RANK() OVER (ORDER BY age DESC) AS dense_rank,
LAG(age, 1) OVER (ORDER BY age) AS prev_age,
LEAD(age, 1) OVER (ORDER BY age) AS next_age
FROM users;

-- UNION(合并结果集)
SELECT name, email FROM users
UNION
SELECT name, email FROM deleted_users;

-- CASE WHEN
SELECT
name,
CASE
WHEN age < 18 THEN '未成年'
WHEN age < 60 THEN '成年'
ELSE '老年'
END AS age_group
FROM users;

八、存储引擎

1
2
SHOW ENGINES;
SHOW TABLE STATUS WHERE Name = 'users';
特性InnoDB(默认)MyISAM
事务
外键
行级锁❌(表级锁)
全文索引5.6+ 支持
崩溃恢复需修复
适用场景OLTP 在线事务只读 / 日志表

始终使用 InnoDB,除非有特殊理由。

九、性能优化

1
2
3
4
5
6
7
8
9
10
11
12
13
SQL 优化原则:
├── 避免 SELECT *,只取需要的列
├── 用 EXPLAIN 检查是否走索引
├── 复合索引注意最左前缀
├── 避免在 WHERE 中对字段做函数操作
│ WHERE YEAR(created_at) = 2026 → ❌
│ WHERE created_at >= '2026-01-01' AND created_at < '2027-01-01' → ✅
├── 避免隐式类型转换
│ WHERE phone = 13800138000 → 字符串 vs 数字不匹配
├── 大分页优化
│ LIMIT 100000, 20 → 先查 id 再 JOIN
│ SELECT * FROM users WHERE id > 100000 LIMIT 20
└── 用覆盖索引(Extra: Using index)

十、面试题

Q1: MySQL 为什么用 B+ Tree 做索引

1
2
3
4
5
6
1. B+ Tree 非叶子节点只存索引,不存数据,比 B-Tree 更矮宽
→ 磁盘 IO 次数少(3-4 层即可支撑千万级数据)
2. 叶子节点通过链表相连
→ 范围查询(BETWEEN、>、<)不用回树查找,链表遍历即可
3. 所有数据都在叶子节点
→ 查询性能稳定(每次都要到叶子)

Q2: 聚簇索引和非聚簇索引的区别

1
2
3
4
5
6
7
8
9
10
11
聚簇索引(Clustered Index):
数据和索引存储在一起,InnoDB 的主键就是聚簇索引。
叶子节点存储整行数据。
一张表只能有一个聚簇索引。

非聚簇索引(Secondary Index):
叶子节点存储主键值。
通过非聚簇索引查询时,先找到主键,再回表查数据。
一张表可以有多个非聚簇索引。

覆盖索引:当查询所需字段都在索引中时,无需回表。

Q3: 如何优化慢查询

1
2
3
4
5
6
7
8
9
1. 开启慢查询日志
SET GLOBAL slow_query_log = ON;
SET GLOBAL long_query_time = 1; -- 超过 1 秒

2. 用 EXPLAIN 分析
3. 检查索引:是否无索引 / 索引失效 / 选错索引
4. 优化 SQL:避免函数操作、大分页、SELECT *
5. 读写分离:主库写、从库读
6. 分表分库:单表超过 500 万行考虑分区或分表

Q4: MVCC 是什么

1
2
3
4
5
6
7
8
9
MVCC(Multi-Version Concurrency Control)多版本并发控制。
InnoDB 通过 MVCC 实现 READ COMMITTED 和 REPEATABLE READ 隔离级别。

原理:
每行数据有隐藏的 trx_id(事务 ID)和 roll_pointer(回滚指针)。
事务读数据时,根据当前活跃事务列表,判断哪个版本可见。
不同隔离级别下,判断规则不同。

好处:读不阻塞写,写不阻塞读。