@gordon.gan/specflow 1.4.0-beta → 1.4.2-beta
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/package.json +1 -1
- package/prompts/approval/database-guidance.md +79 -0
- package/prompts/approval/generate.md +600 -290
- package/skills/database/LICENSE +405 -0
- package/skills/database/ORIGIN.md +6 -0
- package/skills/database/README.md +30 -0
- package/skills/database/elasticsearch/LICENSE.txt +202 -0
- package/skills/database/elasticsearch/SKILL.md +199 -0
- package/skills/database/elasticsearch/examples/01-fulltext-search.md +215 -0
- package/skills/database/elasticsearch/examples/02-aggregation-report.md +206 -0
- package/skills/database/elasticsearch/examples/03-reindex-zero-downtime.md +200 -0
- package/skills/database/elasticsearch/examples/04-cluster-monitoring.md +204 -0
- package/skills/database/elasticsearch/references/01-query-dsl-fulltext.md +162 -0
- package/skills/database/elasticsearch/references/02-query-dsl-term.md +210 -0
- package/skills/database/elasticsearch/references/03-aggregations-metric.md +161 -0
- package/skills/database/elasticsearch/references/04-aggregations-bucket.md +236 -0
- package/skills/database/elasticsearch/references/05-mapping-types.md +134 -0
- package/skills/database/elasticsearch/references/06-analyzers.md +187 -0
- package/skills/database/elasticsearch/references/07-cluster-ops.md +225 -0
- package/skills/database/elasticsearch/references/08-elk-integration.md +170 -0
- package/skills/database/mysql/SKILL.md +195 -0
- package/skills/database/mysql/examples/01-connection-pool.md +75 -0
- package/skills/database/mysql/examples/02-slow-query-optimization.md +98 -0
- package/skills/database/mysql/examples/03-master-slave-setup.md +144 -0
- package/skills/database/mysql/examples/04-backup-strategy.md +212 -0
- package/skills/database/mysql/references/01-functions-string.md +103 -0
- package/skills/database/mysql/references/02-functions-date.md +152 -0
- package/skills/database/mysql/references/03-functions-aggregate-window.md +167 -0
- package/skills/database/mysql/references/04-functions-json.md +129 -0
- package/skills/database/mysql/references/05-sql-ddl-types.md +235 -0
- package/skills/database/mysql/references/06-index-optimization.md +232 -0
- package/skills/database/mysql/references/07-replication-ha.md +213 -0
- package/skills/database/mysql/references/08-backup-restore.md +207 -0
- package/skills/database/mysql/references/09-advanced-features.md +345 -0
- package/skills/database/oracle/LICENSE.txt +202 -0
- package/skills/database/oracle/SKILL.md +238 -0
- package/skills/database/oracle/examples/01-plsql-procedure.md +90 -0
- package/skills/database/oracle/examples/02-awr-analysis.md +99 -0
- package/skills/database/oracle/examples/03-rman-backup.md +108 -0
- package/skills/database/oracle/examples/04-dataguard-setup.md +146 -0
- package/skills/database/oracle/references/01-functions-string.md +91 -0
- package/skills/database/oracle/references/02-functions-date.md +71 -0
- package/skills/database/oracle/references/03-analytic-functions.md +103 -0
- package/skills/database/oracle/references/04-plsql-guide.md +303 -0
- package/skills/database/oracle/references/05-performance-tuning.md +164 -0
- package/skills/database/oracle/references/06-backup-recovery.md +115 -0
- package/skills/database/oracle/references/07-dataguard-rac.md +76 -0
- package/skills/database/oracle/references/08-security.md +170 -0
- package/skills/database/oracle/references/09-sql-syntax.md +152 -0
- package/skills/database/oracle/references/10-features.md +174 -0
- package/skills/database/postgresql/LICENSE.txt +202 -0
- package/skills/database/postgresql/SKILL.md +182 -0
- package/skills/database/postgresql/examples/.gitkeep +0 -0
- package/skills/database/postgresql/examples/01-jsonb-query.md +72 -0
- package/skills/database/postgresql/examples/02-cte-recursive.md +110 -0
- package/skills/database/postgresql/examples/03-performance-tuning.md +114 -0
- package/skills/database/postgresql/examples/04-streaming-replication.md +113 -0
- package/skills/database/postgresql/references/.gitkeep +0 -0
- package/skills/database/postgresql/references/01-functions-string.md +174 -0
- package/skills/database/postgresql/references/02-functions-datetime.md +54 -0
- package/skills/database/postgresql/references/03-functions-aggregate-window.md +142 -0
- package/skills/database/postgresql/references/04-functions-jsonb.md +117 -0
- package/skills/database/postgresql/references/05-fulltext-search.md +109 -0
- package/skills/database/postgresql/references/06-index-types.md +95 -0
- package/skills/database/postgresql/references/07-partition-fdw.md +133 -0
- package/skills/database/postgresql/references/08-replication-backup.md +215 -0
- package/skills/database/redis/LICENSE.txt +202 -0
- package/skills/database/redis/SKILL.md +922 -0
- package/skills/database/redis/examples/01-cache-usage.md +104 -0
- package/skills/database/redis/examples/02-session-storage.md +72 -0
- package/skills/database/redis/examples/03-leaderboard.md +63 -0
- package/skills/database/redis/examples/04-redis-cluster-setup.md +70 -0
- package/skills/database/redis/examples/05-stream-queue.md +65 -0
- package/skills/database/redis/references/command-quick-ref.md +180 -0
- package/skills/database/redis/references/commands-admin-key.md +413 -0
- package/skills/database/redis/references/commands-set-sorted-advanced.md +539 -0
- package/skills/database/redis/references/commands-string-hash-list.md +458 -0
- package/skills/database/redis/references/memory-optimization.md +150 -0
- package/skills/database/redis/references/redis-conf-production.md +139 -0
- package/skills/specflow-approval/SKILL.md +102 -181
- package/templates/approval.md +321 -221
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
# 索引与执行计划 (Index & Query Optimization)
|
|
2
|
+
|
|
3
|
+
## 简介
|
|
4
|
+
|
|
5
|
+
索引是 MySQL 性能优化的核心手段。正确的索引能大幅减少扫描行数,错误的索引设计则会导致全表扫描和性能灾难。
|
|
6
|
+
|
|
7
|
+
## 索引类型
|
|
8
|
+
|
|
9
|
+
| 索引类型 | 底层结构 | 版本要求 | 适用场景 |
|
|
10
|
+
|---------|---------|---------|---------|
|
|
11
|
+
| **B-Tree** | B+ 树 | 全版本 | 等值/范围/排序查询(默认) |
|
|
12
|
+
| **Hash** | 哈希表 | MEMORY 引擎 | 等值查询(不支持范围) |
|
|
13
|
+
| **Fulltext** | 倒排索引 | 5.6+ | 全文搜索 (MATCH AGAINST) |
|
|
14
|
+
| **Spatial** | R-Tree | 5.7+ | 空间数据查询 |
|
|
15
|
+
| **Descending** | B+ 树降序 | 8.0+ | 混合排序方向优化 |
|
|
16
|
+
| **Invisible** | 同 B-Tree | 8.0+ | 测试删除影响而不实际删除 |
|
|
17
|
+
| **Functional Key Parts** | 表达式索引 | 8.0.13+ | 函数/表达式索引 |
|
|
18
|
+
|
|
19
|
+
### B-Tree 索引创建
|
|
20
|
+
|
|
21
|
+
```sql
|
|
22
|
+
-- 普通索引
|
|
23
|
+
CREATE INDEX idx_name ON user (name);
|
|
24
|
+
|
|
25
|
+
-- 唯一索引
|
|
26
|
+
CREATE UNIQUE INDEX uk_email ON user (email);
|
|
27
|
+
|
|
28
|
+
-- 复合索引(最左前缀原则)
|
|
29
|
+
CREATE INDEX idx_city_age ON user (city, age);
|
|
30
|
+
|
|
31
|
+
-- 前缀索引(字符串前 N 字符)
|
|
32
|
+
CREATE INDEX idx_email_prefix ON user (email(10));
|
|
33
|
+
|
|
34
|
+
-- 全文索引
|
|
35
|
+
CREATE FULLTEXT INDEX ftx_content ON article (title, content);
|
|
36
|
+
|
|
37
|
+
-- 降序索引 (MySQL 8.0+)
|
|
38
|
+
CREATE INDEX idx_created_desc ON `order` (created_at DESC);
|
|
39
|
+
|
|
40
|
+
-- 不可见索引(测试用)
|
|
41
|
+
CREATE INDEX idx_test ON user (name) INVISIBLE;
|
|
42
|
+
ALTER TABLE user ALTER INDEX idx_test VISIBLE;
|
|
43
|
+
|
|
44
|
+
-- 函数索引 (MySQL 8.0.13+)
|
|
45
|
+
CREATE INDEX idx_phone_last4 ON user ((RIGHT(phone, 4)));
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## 复合索引最左前缀原则
|
|
49
|
+
|
|
50
|
+
复合索引 `idx_a_b_c (a, b, c)`:
|
|
51
|
+
|
|
52
|
+
| 查询条件 | 索引使用情况 |
|
|
53
|
+
|---------|-------------|
|
|
54
|
+
| `WHERE a = 1` | ✅ 使用 a |
|
|
55
|
+
| `WHERE a = 1 AND b = 2` | ✅ 使用 a, b |
|
|
56
|
+
| `WHERE a = 1 AND b = 2 AND c = 3` | ✅ 使用 a, b, c |
|
|
57
|
+
| `WHERE a = 1 ORDER BY b` | ✅ 使用 a(排序) |
|
|
58
|
+
| `WHERE a = 1 AND c = 3` | ✅ 使用 a(c 只能过滤) |
|
|
59
|
+
| `WHERE a IN (1, 2) AND b = 3` | ✅ 使用 a, b |
|
|
60
|
+
| `WHERE b = 2` | ❌ 跳过了 a |
|
|
61
|
+
| `WHERE c = 3` | ❌ 跳过了 a, b |
|
|
62
|
+
|
|
63
|
+
### 索引设计原则
|
|
64
|
+
|
|
65
|
+
1. **区分度高的列放前面**:选择性 = `COUNT(DISTINCT col) / COUNT(*)`
|
|
66
|
+
2. **等值条件列放前面**:`=` 比范围查询列放前面
|
|
67
|
+
3. **覆盖索引**:查询列全在索引中(Extra 显示 `Using index`),避免回表
|
|
68
|
+
4. **索引下推 (ICP)**:MySQL 5.6+,引擎层用 WHERE 条件过滤索引记录后再回表
|
|
69
|
+
|
|
70
|
+
## EXPLAIN 执行计划分析
|
|
71
|
+
|
|
72
|
+
### 使用 EXPLAIN
|
|
73
|
+
|
|
74
|
+
```sql
|
|
75
|
+
EXPLAIN SELECT u.name, o.order_no
|
|
76
|
+
FROM user u
|
|
77
|
+
JOIN `order` o ON u.id = o.user_id
|
|
78
|
+
WHERE u.id = 100;
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### EXPLAIN 输出列
|
|
82
|
+
|
|
83
|
+
| 列名 | 含义 | 关键值 |
|
|
84
|
+
|------|------|--------|
|
|
85
|
+
| `id` | SELECT 标识符,id 越大越先执行 | |
|
|
86
|
+
| `select_type` | 查询类型 | SIMPLE, PRIMARY, SUBQUERY, DERIVED, UNION |
|
|
87
|
+
| `table` | 表名 | |
|
|
88
|
+
| `partitions` | 扫描的分区 | |
|
|
89
|
+
| `type` | 访问类型(性能排序) | system > const > eq_ref > ref > range > index > **ALL** |
|
|
90
|
+
| `possible_keys` | 可能使用的索引 | |
|
|
91
|
+
| `key` | 实际使用的索引 | |
|
|
92
|
+
| `key_len` | 使用的索引字节长度 | 越大越好(匹配更多列) |
|
|
93
|
+
| `ref` | 索引匹配的列或常量 | |
|
|
94
|
+
| `rows` | 预估扫描行数 | 越小越好 |
|
|
95
|
+
| `filtered` | 过滤后百分比 | |
|
|
96
|
+
| `Extra` | 额外信息 | **🔑 重要** |
|
|
97
|
+
|
|
98
|
+
### type 访问类型(从优到劣)
|
|
99
|
+
|
|
100
|
+
| type | 说明 | 示例 |
|
|
101
|
+
|------|------|------|
|
|
102
|
+
| **system** | 表只有一行 | 最好 |
|
|
103
|
+
| **const** | 主键/唯一索引等值查询 | `WHERE id = 1` |
|
|
104
|
+
| **eq_ref** | JOIN 主键/唯一索引关联 | `ON u.id = o.user_id` |
|
|
105
|
+
| **ref** | 普通索引等值查询 | `WHERE name = '张三'` |
|
|
106
|
+
| **range** | 索引范围扫描 | `WHERE id > 100`, `LIKE '张%'` |
|
|
107
|
+
| **index** | 全索引扫描 | 不推荐 |
|
|
108
|
+
| **ALL** | 全表扫描 | **❌ 最差** |
|
|
109
|
+
|
|
110
|
+
### Extra 关键信息
|
|
111
|
+
|
|
112
|
+
| Extra 值 | 含义 |
|
|
113
|
+
|----------|------|
|
|
114
|
+
| **Using index** | 覆盖索引(无需回表)✅ 最佳 |
|
|
115
|
+
| **Using where** | 用 WHERE 过滤 |
|
|
116
|
+
| **Using index condition** | 索引下推 ICP ✅ |
|
|
117
|
+
| **Using temporary** | 使用临时表(需优化)❌ |
|
|
118
|
+
| **Using filesort** | 文件排序(需优化)❌ |
|
|
119
|
+
| **Using join buffer** | JOIN 未用索引 ❌ |
|
|
120
|
+
| **Using MRR** | 多范围读取优化 ✅ |
|
|
121
|
+
|
|
122
|
+
### EXPLAIN ANALYZE (MySQL 8.0.18+)
|
|
123
|
+
|
|
124
|
+
```sql
|
|
125
|
+
-- 实际执行并显示各步骤耗时和行数
|
|
126
|
+
EXPLAIN ANALYZE
|
|
127
|
+
SELECT u.name, COUNT(o.id) AS order_count
|
|
128
|
+
FROM user u
|
|
129
|
+
LEFT JOIN `order` o ON u.id = o.user_id
|
|
130
|
+
GROUP BY u.id
|
|
131
|
+
ORDER BY order_count DESC
|
|
132
|
+
LIMIT 10;
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## SQL 优化原则
|
|
136
|
+
|
|
137
|
+
```
|
|
138
|
+
★ 核心原则:减少扫描行数,减少回表,减少排序
|
|
139
|
+
|
|
140
|
+
1. WHERE 条件列建索引(符合最左前缀)
|
|
141
|
+
2. 避免 SELECT *,仅取需要的列(利用覆盖索引)
|
|
142
|
+
3. 用 EXISTS 代替 IN(大数据量下)
|
|
143
|
+
4. 用 UNION ALL 代替 UNION(不需要去重时)
|
|
144
|
+
5. 用 LIMIT 限制结果集大小
|
|
145
|
+
6. 大表分页用游标(WHERE id > last_id)而非 OFFSET
|
|
146
|
+
7. JOIN 的关联列必须有索引
|
|
147
|
+
8. GROUP BY / ORDER BY 的列尽量利用索引
|
|
148
|
+
9. 避免在 WHERE 条件列上使用函数或计算
|
|
149
|
+
10. 拆分大查询为多次小查询(减少锁范围)
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## 常见优化案例
|
|
153
|
+
|
|
154
|
+
### 隐式类型转换(索引失效)
|
|
155
|
+
|
|
156
|
+
```sql
|
|
157
|
+
-- ❌ phone 是 VARCHAR,传 INT 导致全表扫描
|
|
158
|
+
SELECT * FROM user WHERE phone = 13800138000;
|
|
159
|
+
|
|
160
|
+
-- ✅ 字符类型就传字符串
|
|
161
|
+
SELECT * FROM user WHERE phone = '13800138000';
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### WHERE 条件函数操作(索引失效)
|
|
165
|
+
|
|
166
|
+
```sql
|
|
167
|
+
-- ❌ DATE() 函数使索引失效
|
|
168
|
+
SELECT * FROM `order` WHERE DATE(created_at) = '2024-01-01';
|
|
169
|
+
|
|
170
|
+
-- ✅ 范围查询可用索引
|
|
171
|
+
SELECT * FROM `order` WHERE created_at >= '2024-01-01' AND created_at < '2024-01-02';
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### 大分页优化
|
|
175
|
+
|
|
176
|
+
```sql
|
|
177
|
+
-- ❌ OFFSET 越大越慢(先扫描再丢弃)
|
|
178
|
+
SELECT * FROM `order` ORDER BY id LIMIT 100000, 20;
|
|
179
|
+
|
|
180
|
+
-- ✅ 游标分页
|
|
181
|
+
SELECT * FROM `order` WHERE id > 100000 ORDER BY id LIMIT 20;
|
|
182
|
+
|
|
183
|
+
-- ✅ 子查询 + JOIN 方式
|
|
184
|
+
SELECT * FROM `order`
|
|
185
|
+
JOIN (SELECT id FROM `order` ORDER BY id LIMIT 100000, 20) AS tmp
|
|
186
|
+
ON `order`.id = tmp.id;
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### OR 改为 UNION
|
|
190
|
+
|
|
191
|
+
```sql
|
|
192
|
+
-- ❌ OR 可能用不到复合索引
|
|
193
|
+
SELECT * FROM user WHERE name = '张三' OR email = 'zhangsan@example.com';
|
|
194
|
+
|
|
195
|
+
-- ✅ UNION 分别用各自索引
|
|
196
|
+
SELECT * FROM user WHERE name = '张三'
|
|
197
|
+
UNION
|
|
198
|
+
SELECT * FROM user WHERE email = 'zhangsan@example.com';
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## 慢查询配置
|
|
202
|
+
|
|
203
|
+
```ini
|
|
204
|
+
# my.cnf
|
|
205
|
+
slow_query_log = ON # 开启慢查询
|
|
206
|
+
slow_query_log_file = /var/log/mysql/slow.log # 慢查询日志文件
|
|
207
|
+
long_query_time = 1 # 超过 1 秒的查询记录
|
|
208
|
+
log_queries_not_using_indexes = ON # 记录未使用索引的查询
|
|
209
|
+
min_examined_row_limit = 100 # 扫描行数超过此值才记录
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### 分析慢查询
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
# mysqldumpslow 排序取前10
|
|
216
|
+
mysqldumpslow -s t -t 10 /var/log/mysql/slow.log
|
|
217
|
+
|
|
218
|
+
# Percona Toolkit 分析
|
|
219
|
+
pt-query-digest /var/log/mysql/slow.log
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## 索引设计规范
|
|
223
|
+
|
|
224
|
+
1. 每个表必须有主键(推荐 BIGINT AUTO_INCREMENT 或有序 UUID)
|
|
225
|
+
2. 主键不宜过长(B+ 树二级索引过大)
|
|
226
|
+
3. 每个表索引数不超过 5-8 个(过多影响写入性能)
|
|
227
|
+
4. 大表(> 1000 万行)索引必须业务验证后创建
|
|
228
|
+
5. 字符串区分度低或长度大时用前缀索引
|
|
229
|
+
6. ORDER BY / GROUP BY / JOIN 的列考虑建索引
|
|
230
|
+
7. 不建索引的列:频繁更新、区分度极低(如性别)
|
|
231
|
+
8. 用 INVISIBLE 索引测试后再删除
|
|
232
|
+
9. 避免冗余索引(如 idx_a_b 和 idx_a 重复)
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
# 主从复制与高可用 (Replication & High Availability)
|
|
2
|
+
|
|
3
|
+
## 简介
|
|
4
|
+
|
|
5
|
+
MySQL 主从复制是生产环境中最常用的高可用和读写分离方案。主库(Master)记录二进制日志(Binlog),从库(Slave)通过网络读取并回放日志,实现数据同步。
|
|
6
|
+
|
|
7
|
+
## 复制原理
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
┌─────────────┐ ┌─────────────┐
|
|
11
|
+
│ Master │ │ Slave │
|
|
12
|
+
├─────────────┤ ├─────────────┤
|
|
13
|
+
│ Binlog │─────→ │ Relay Log │
|
|
14
|
+
│ (二进制日志) │ IO线程 │ (中继日志) │
|
|
15
|
+
└─────────────┘ └──────┬──────┘
|
|
16
|
+
│ SQL线程
|
|
17
|
+
▼
|
|
18
|
+
┌─────────────┐
|
|
19
|
+
│ Slave Data │
|
|
20
|
+
└─────────────┘
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**复制流程**:
|
|
24
|
+
1. Master 提交事务时写入 Binlog
|
|
25
|
+
2. Slave 的 IO 线程读取 Master 的 Binlog,写入 Relay Log
|
|
26
|
+
3. Slave 的 SQL 线程回放 Relay Log,应用到自身数据
|
|
27
|
+
|
|
28
|
+
## 主从同步配置
|
|
29
|
+
|
|
30
|
+
### Master 配置
|
|
31
|
+
|
|
32
|
+
```ini
|
|
33
|
+
# my.cnf
|
|
34
|
+
server-id = 1
|
|
35
|
+
log_bin = /var/log/mysql/mysql-bin
|
|
36
|
+
binlog_format = ROW # ROW 格式最安全(推荐)
|
|
37
|
+
binlog_expire_logs_seconds = 604800 # 保留 7 天
|
|
38
|
+
sync_binlog = 1 # 每次事务提交同步(最安全)
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
```sql
|
|
42
|
+
-- 创建复制用户
|
|
43
|
+
CREATE USER 'replicator'@'%' IDENTIFIED BY 'password';
|
|
44
|
+
GRANT REPLICATION SLAVE ON *.* TO 'replicator'@'%';
|
|
45
|
+
FLUSH PRIVILEGES;
|
|
46
|
+
|
|
47
|
+
-- 查看 Master 状态
|
|
48
|
+
SHOW MASTER STATUS;
|
|
49
|
+
-- File: mysql-bin.000001, Position: 1234
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Slave 配置
|
|
53
|
+
|
|
54
|
+
```ini
|
|
55
|
+
# my.cnf
|
|
56
|
+
server-id = 2
|
|
57
|
+
relay_log = /var/log/mysql/mysql-relay-bin
|
|
58
|
+
read_only = 1 # 只读(防止误写)
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
```sql
|
|
62
|
+
-- 设置主节点
|
|
63
|
+
CHANGE MASTER TO
|
|
64
|
+
MASTER_HOST = '192.168.1.100',
|
|
65
|
+
MASTER_PORT = 3306,
|
|
66
|
+
MASTER_USER = 'replicator',
|
|
67
|
+
MASTER_PASSWORD = 'password',
|
|
68
|
+
MASTER_LOG_FILE = 'mysql-bin.000001',
|
|
69
|
+
MASTER_LOG_POS = 1234;
|
|
70
|
+
|
|
71
|
+
-- 启动复制
|
|
72
|
+
START SLAVE;
|
|
73
|
+
|
|
74
|
+
-- 查看复制状态(关键字段)
|
|
75
|
+
SHOW SLAVE STATUS\G
|
|
76
|
+
-- Slave_IO_Running: Yes -- IO 线程正常
|
|
77
|
+
-- Slave_SQL_Running: Yes -- SQL 线程正常
|
|
78
|
+
-- Seconds_Behind_Master: 0 -- 延迟秒数(0 最佳)
|
|
79
|
+
|
|
80
|
+
-- 停止复制
|
|
81
|
+
STOP SLAVE;
|
|
82
|
+
|
|
83
|
+
-- 重置复制
|
|
84
|
+
RESET SLAVE ALL;
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### 复制状态监控关键字段
|
|
88
|
+
|
|
89
|
+
| 字段 | 说明 | 正常值 |
|
|
90
|
+
|------|------|--------|
|
|
91
|
+
| `Slave_IO_Running` | IO 线程状态 | Yes |
|
|
92
|
+
| `Slave_SQL_Running` | SQL 线程状态 | Yes |
|
|
93
|
+
| `Seconds_Behind_Master` | 延迟秒数 | 0(或很小) |
|
|
94
|
+
| `Last_IO_Error` | IO 线程错误 | 空 |
|
|
95
|
+
| `Last_SQL_Error` | SQL 线程错误 | 空 |
|
|
96
|
+
| `Relay_Log_Space` | Relay Log 大小 | 稳定值 |
|
|
97
|
+
| `Exec_Master_Log_Pos` | 已执行位置 | 持续增长 |
|
|
98
|
+
|
|
99
|
+
## 复制模式对比
|
|
100
|
+
|
|
101
|
+
| 模式 | 说明 | 一致性 | 性能 | 推荐度 |
|
|
102
|
+
|------|------|--------|------|--------|
|
|
103
|
+
| **异步 (ASYNC)** | Master 不等待 Slave 确认 | 最终一致性 | 最高 | 默认 |
|
|
104
|
+
| **半同步 (SEMISYNC)** | 至少一个 Slave 写入 Relay Log | 较高 | 略微降低 | ★★★★★ |
|
|
105
|
+
| **全同步 (Group Replication)** | 多数节点确认 | 强一致性 | 最低 | 特定场景 |
|
|
106
|
+
|
|
107
|
+
### 半同步复制配置
|
|
108
|
+
|
|
109
|
+
```sql
|
|
110
|
+
-- Master 和 Slave 都安装插件
|
|
111
|
+
INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
|
|
112
|
+
INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
|
|
113
|
+
|
|
114
|
+
-- Master 启用
|
|
115
|
+
SET GLOBAL rpl_semi_sync_master_enabled = 1;
|
|
116
|
+
SET GLOBAL rpl_semi_sync_master_timeout = 1000; -- 1s 超时降级为异步
|
|
117
|
+
|
|
118
|
+
-- Slave 启用
|
|
119
|
+
SET GLOBAL rpl_semi_sync_slave_enabled = 1;
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## 复制延迟处理
|
|
123
|
+
|
|
124
|
+
### 常见延迟原因
|
|
125
|
+
|
|
126
|
+
1. Slave 硬件弱于 Master
|
|
127
|
+
2. 大事务(一次 DELETE/UPDATE 百万行)
|
|
128
|
+
3. Slave 上存在慢查询锁竞争
|
|
129
|
+
4. 单线程 SQL 回放(MySQL 5.6+ 可开启并行复制)
|
|
130
|
+
|
|
131
|
+
### 并行复制配置 (MySQL 5.7+)
|
|
132
|
+
|
|
133
|
+
```ini
|
|
134
|
+
# my.cnf
|
|
135
|
+
slave_parallel_workers = 4
|
|
136
|
+
slave_parallel_type = LOGICAL_CLOCK
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### 应用层处理延迟
|
|
140
|
+
|
|
141
|
+
```sql
|
|
142
|
+
-- 关键读走主库(如支付成功后的订单查询)
|
|
143
|
+
-- 普通读走从库(容忍秒级延迟)
|
|
144
|
+
|
|
145
|
+
-- 判断延迟:如果从库读不到数据,降级读主库
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## 高可用方案
|
|
149
|
+
|
|
150
|
+
| 方案 | 原理 | 优点 | 缺点 | 推荐场景 |
|
|
151
|
+
|------|------|------|------|---------|
|
|
152
|
+
| **主从 + 手动切换** | 手动执行 CHANGE MASTER | 简单 | 切换时间 10min+ | 非关键业务 |
|
|
153
|
+
| **MHA** | 自动检测 Master 故障切换 | 成熟稳定 | 需独立管理节点 | 经典方案 |
|
|
154
|
+
| **Orchestrator** | 自动故障检测/拓扑管理 | 自动修复 | 复杂度中等 | **推荐方案** |
|
|
155
|
+
| **InnoDB Cluster** | Group Replication + MySQL Router | 原生方案 | 需 8.0+ | MySQL 官方方案 |
|
|
156
|
+
| **ProxySQL + 读写分离** | 中间层路由 | 灵活路由 | 引入代理层 | 配合复制使用 |
|
|
157
|
+
|
|
158
|
+
### Orchestrator 工作流程
|
|
159
|
+
|
|
160
|
+
```
|
|
161
|
+
1. 检测 Master 故障(心跳超时)
|
|
162
|
+
2. 选择最优 Slave(延迟最小、数据最新)
|
|
163
|
+
3. 自动提升为新 Master
|
|
164
|
+
4. 重新配置其他 Slave 指向新 Master
|
|
165
|
+
5. 通知应用层新 Master 地址(通过 API / Consul)
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## 读写分离架构
|
|
169
|
+
|
|
170
|
+
### 应用层实现
|
|
171
|
+
|
|
172
|
+
```text
|
|
173
|
+
// 伪代码
|
|
174
|
+
if (sql.startsWith("SELECT")) {
|
|
175
|
+
connection = slavePool.getConnection();
|
|
176
|
+
} else {
|
|
177
|
+
connection = masterPool.getConnection();
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### ProxySQL 实现
|
|
182
|
+
|
|
183
|
+
```sql
|
|
184
|
+
-- ProxySQL 配置读写分离组
|
|
185
|
+
INSERT INTO mysql_replication_hostgroups
|
|
186
|
+
(writer_hostgroup, reader_hostgroup, comment)
|
|
187
|
+
VALUES (10, 20, '读写分离');
|
|
188
|
+
|
|
189
|
+
-- SELECT 自动路由到从节点(reader_hostgroup=20)
|
|
190
|
+
-- DML 自动路由到主节点(writer_hostgroup=10)
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## 分库分表 (Sharding)
|
|
194
|
+
|
|
195
|
+
### 何时需要分库分表
|
|
196
|
+
|
|
197
|
+
单表 > 5000 万行或单实例 > 2TB 且预期继续增长。
|
|
198
|
+
|
|
199
|
+
### 方案选择
|
|
200
|
+
|
|
201
|
+
| 方案 | 类型 | 说明 |
|
|
202
|
+
|------|------|------|
|
|
203
|
+
| ShardingSphere | 中间件 + 客户端 | Java 生态首选 |
|
|
204
|
+
| MyCAT | 数据库中间件 | 传统方案 |
|
|
205
|
+
| Vitess | 分布式方案 | YouTube 开源 |
|
|
206
|
+
| TiDB | 原生分布式 | 彻底解决但需切换数据库 |
|
|
207
|
+
|
|
208
|
+
### 分库分表注意事项
|
|
209
|
+
|
|
210
|
+
1. **分片键选择**:`user_id % shard_count` 或 `order_id % shard_count`
|
|
211
|
+
2. **跨分片查询**:全局表、广播表、ER 分片
|
|
212
|
+
3. **分布式 ID**:雪花算法、Leaf、Segment
|
|
213
|
+
4. **分布式事务**:XA / TCC / Saga / Seata
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# 备份与恢复 (Backup & Restore)
|
|
2
|
+
|
|
3
|
+
## 简介
|
|
4
|
+
|
|
5
|
+
MySQL 备份分为逻辑备份(mysqldump)和物理备份(XtraBackup)。逻辑备份导出 SQL 语句,适合小规模和迁移场景;物理备份直接复制数据文件,适合大数据库的快速恢复。
|
|
6
|
+
|
|
7
|
+
## mysqldump — 逻辑备份
|
|
8
|
+
|
|
9
|
+
### 基本用法
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
# 备份单个数据库(推荐使用 --single-transaction 避免锁表)
|
|
13
|
+
mysqldump -u root -p --single-transaction --routines --triggers --events shop > shop_backup.sql
|
|
14
|
+
|
|
15
|
+
# 备份所有数据库
|
|
16
|
+
mysqldump -u root -p --all-databases --single-transaction > all_db_backup.sql
|
|
17
|
+
|
|
18
|
+
# 只备份表结构
|
|
19
|
+
mysqldump -u root -p --no-data shop > shop_schema.sql
|
|
20
|
+
|
|
21
|
+
# 只备份数据
|
|
22
|
+
mysqldump -u root -p --no-create-info shop > shop_data.sql
|
|
23
|
+
|
|
24
|
+
# 压缩备份
|
|
25
|
+
mysqldump -u root -p shop | gzip > shop_backup.sql.gz
|
|
26
|
+
|
|
27
|
+
# 备份特定表
|
|
28
|
+
mysqldump -u root -p shop user order product > critical_tables.sql
|
|
29
|
+
|
|
30
|
+
# 备份到远程服务器
|
|
31
|
+
mysqldump -u root -p shop | ssh user@backup-server "cat > /backups/shop.sql"
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### 关键参数说明
|
|
35
|
+
|
|
36
|
+
| 参数 | 说明 | 推荐 |
|
|
37
|
+
|------|------|------|
|
|
38
|
+
| `--single-transaction` | InnoDB 事务一致性备份,不锁表 | **必选**(InnoDB) |
|
|
39
|
+
| `--lock-tables` | MyISAM 表锁 | 仅 MyISAM 时需要 |
|
|
40
|
+
| `--routines` | 备份存储过程和函数 | ✅ 推荐 |
|
|
41
|
+
| `--triggers` | 备份触发器 | ✅ 推荐 |
|
|
42
|
+
| `--events` | 备份事件调度器 | ✅ 推荐 |
|
|
43
|
+
| `--quick` | 逐行导出(防止大表内存溢出) | ✅ 大表推荐 |
|
|
44
|
+
| `--opt` | 快速导出(默认开启) | 默认 |
|
|
45
|
+
|
|
46
|
+
### 恢复
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
# 基本恢复
|
|
50
|
+
mysql -u root -p shop < shop_backup.sql
|
|
51
|
+
|
|
52
|
+
# 恢复压缩备份
|
|
53
|
+
gunzip < shop_backup.sql.gz | mysql -u root -p shop
|
|
54
|
+
|
|
55
|
+
# 恢复多个数据库
|
|
56
|
+
mysql -u root -p < all_db_backup.sql
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## XtraBackup — 物理备份
|
|
60
|
+
|
|
61
|
+
Percona XtraBackup 是 MySQL 物理备份的事实标准,支持热备份 InnoDB 表而不影响读写。
|
|
62
|
+
|
|
63
|
+
### 安装
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
# macOS
|
|
67
|
+
brew install percona-xtrabackup
|
|
68
|
+
|
|
69
|
+
# Ubuntu
|
|
70
|
+
apt install percona-xtrabackup-80
|
|
71
|
+
|
|
72
|
+
# CentOS
|
|
73
|
+
yum install percona-xtrabackup-80
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### 全量备份与恢复
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
# 全量备份
|
|
80
|
+
xtrabackup --backup --target-dir=/data/backup/full/ --user=root --password=xxx
|
|
81
|
+
|
|
82
|
+
# 准备恢复(应用 redo log,使数据一致)
|
|
83
|
+
xtrabackup --prepare --target-dir=/data/backup/full/
|
|
84
|
+
|
|
85
|
+
# 恢复到 MySQL 数据目录
|
|
86
|
+
xtrabackup --copy-back --target-dir=/data/backup/full/
|
|
87
|
+
# 或手动复制
|
|
88
|
+
rsync -avrP /data/backup/full/ /var/lib/mysql/
|
|
89
|
+
chown -R mysql:mysql /var/lib/mysql/
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### 增量备份与恢复
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
# 全量备份(基础)
|
|
96
|
+
xtrabackup --backup --target-dir=/data/backup/full/
|
|
97
|
+
|
|
98
|
+
# 增量备份(基于全量)
|
|
99
|
+
xtrabackup --backup --target-dir=/data/backup/inc1/ \
|
|
100
|
+
--incremental-basedir=/data/backup/full/
|
|
101
|
+
|
|
102
|
+
# 第二个增量备份(基于前一个增量)
|
|
103
|
+
xtrabackup --backup --target-dir=/data/backup/inc2/ \
|
|
104
|
+
--incremental-basedir=/data/backup/inc1/
|
|
105
|
+
|
|
106
|
+
# 增量恢复流程
|
|
107
|
+
# 1. 准备全量(应用 log 但不回滚未提交事务)
|
|
108
|
+
xtrabackup --prepare --apply-log-only --target-dir=/data/backup/full/
|
|
109
|
+
|
|
110
|
+
# 2. 合并增量 1
|
|
111
|
+
xtrabackup --prepare --apply-log-only --target-dir=/data/backup/full/ \
|
|
112
|
+
--incremental-dir=/data/backup/inc1/
|
|
113
|
+
|
|
114
|
+
# 3. 合并增量 2(最后一次不用 --apply-log-only)
|
|
115
|
+
xtrabackup --prepare --target-dir=/data/backup/full/ \
|
|
116
|
+
--incremental-dir=/data/backup/inc2/
|
|
117
|
+
|
|
118
|
+
# 4. copy-back 恢复
|
|
119
|
+
xtrabackup --copy-back --target-dir=/data/backup/full/
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## 二进制日志与 PITR(时间点恢复)
|
|
123
|
+
|
|
124
|
+
PITR(Point-In-Time Recovery)允许恢复到某个精确的时间点,是应对误操作(DROP TABLE、DELETE 全表)的核心手段。
|
|
125
|
+
|
|
126
|
+
### 启用二进制日志
|
|
127
|
+
|
|
128
|
+
```ini
|
|
129
|
+
# my.cnf
|
|
130
|
+
log_bin = /var/log/mysql/mysql-bin
|
|
131
|
+
binlog_format = ROW # ROW 格式最安全
|
|
132
|
+
binlog_expire_logs_seconds = 604800 # 保留 7 天
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### 查看二进制日志
|
|
136
|
+
|
|
137
|
+
```sql
|
|
138
|
+
-- 查看 Binlog 是否开启
|
|
139
|
+
SHOW VARIABLES LIKE 'log_bin';
|
|
140
|
+
|
|
141
|
+
-- 列出所有 Binlog 文件
|
|
142
|
+
SHOW BINARY LOGS;
|
|
143
|
+
|
|
144
|
+
-- 查看 Binlog 事件
|
|
145
|
+
SHOW BINLOG EVENTS IN 'mysql-bin.000001' LIMIT 10;
|
|
146
|
+
|
|
147
|
+
-- 查看当前 Binlog 位置
|
|
148
|
+
SHOW MASTER STATUS;
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### PITR 恢复流程
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
# Step 1: 恢复最近的完整备份
|
|
155
|
+
mysql -u root -p shop < shop_backup.sql
|
|
156
|
+
|
|
157
|
+
# Step 2: 回放二进制日志到指定时间点
|
|
158
|
+
mysqlbinlog --stop-datetime="2024-01-15 10:00:00" \
|
|
159
|
+
/var/log/mysql/mysql-bin.* | mysql -u root -p
|
|
160
|
+
|
|
161
|
+
# 指定位置恢复
|
|
162
|
+
mysqlbinlog --stop-position=12345 \
|
|
163
|
+
/var/log/mysql/mysql-bin.000001 | mysql -u root -p
|
|
164
|
+
|
|
165
|
+
# 指定开始和结束范围
|
|
166
|
+
mysqlbinlog \
|
|
167
|
+
--start-datetime="2024-01-15 09:00:00" \
|
|
168
|
+
--stop-datetime="2024-01-15 10:00:00" \
|
|
169
|
+
/var/log/mysql/mysql-bin.000001 \
|
|
170
|
+
/var/log/mysql/mysql-bin.000002 \
|
|
171
|
+
| mysql -u root -p shop
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## 备份策略推荐
|
|
175
|
+
|
|
176
|
+
### 生产环境备份策略
|
|
177
|
+
|
|
178
|
+
```
|
|
179
|
+
┌──────────────────────────────────────────────┐
|
|
180
|
+
│ 生产环境备份策略: │
|
|
181
|
+
│ │
|
|
182
|
+
│ 每日凌晨 2:00: 全量备份 (XtraBackup 物理备份) │
|
|
183
|
+
│ 每 6 小时: 增量备份 (XtraBackup 增量) │
|
|
184
|
+
│ 实时: 二进制日志持续归档 (BINLOG) │
|
|
185
|
+
│ 保留周期: 最近 7 天全量 + 30 天增量 │
|
|
186
|
+
│ 异地备份: 备份文件同步到对象存储 (OSS/S3) │
|
|
187
|
+
│ 定期演练: 每月一次恢复测试 │
|
|
188
|
+
└──────────────────────────────────────────────┘
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### 备份检查清单
|
|
192
|
+
|
|
193
|
+
- [ ] 全量备份是否成功(检查 `xtrabackup` 退出码)
|
|
194
|
+
- [ ] 备份文件大小是否合理(过大/过小要排查)
|
|
195
|
+
- [ ] 异地备份是否同步完成
|
|
196
|
+
- [ ] 二进制日志是否连续不中断
|
|
197
|
+
- [ ] 每月恢复演练验证备份可用性
|
|
198
|
+
- [ ] 备份保留策略是否符合合规要求
|
|
199
|
+
|
|
200
|
+
## 注意事项
|
|
201
|
+
|
|
202
|
+
- **不要只依赖一种备份方式**:逻辑备份 + 物理备份 + Binlog 三者配合
|
|
203
|
+
- **测试恢复**:定期在测试环境演练恢复流程,确保备份可用
|
|
204
|
+
- **监控备份状态**:通过脚本监控备份成功率,发送告警
|
|
205
|
+
- **备份加密**:敏感数据的备份文件应加密存储
|
|
206
|
+
- **备份压缩**:物理备份建议用 `--compress` 参数,可节省 3-5 倍存储空间
|
|
207
|
+
- **mysqldump 对超大表(> 50GB)不适用**:导出和导入都极慢,建议用 XtraBackup
|