speccore 8.3.290 → 8.3.296

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.
Files changed (101) hide show
  1. package/README.en.md +16 -3
  2. package/README.md +9 -7
  3. package/dist/cli.js +11 -0
  4. package/dist/cli.js.map +1 -1
  5. package/dist/commands/about.d.ts.map +1 -1
  6. package/dist/commands/about.js +5 -0
  7. package/dist/commands/about.js.map +1 -1
  8. package/dist/commands/analyze.d.ts.map +1 -1
  9. package/dist/commands/analyze.js +77 -5
  10. package/dist/commands/analyze.js.map +1 -1
  11. package/dist/commands/ask.js +2 -2
  12. package/dist/commands/ask.js.map +1 -1
  13. package/dist/commands/execute.js +1 -0
  14. package/dist/commands/execute.js.map +1 -1
  15. package/dist/commands/init.d.ts.map +1 -1
  16. package/dist/commands/init.js +25 -4
  17. package/dist/commands/init.js.map +1 -1
  18. package/dist/commands/iteration/taskify.d.ts.map +1 -1
  19. package/dist/commands/iteration/taskify.js +132 -7
  20. package/dist/commands/iteration/taskify.js.map +1 -1
  21. package/dist/commands/status-panel.d.ts +1 -0
  22. package/dist/commands/status-panel.d.ts.map +1 -1
  23. package/dist/commands/status-panel.js +65 -17
  24. package/dist/commands/status-panel.js.map +1 -1
  25. package/dist/commands/update-env-configs.d.ts.map +1 -1
  26. package/dist/commands/update-env-configs.js +6 -0
  27. package/dist/commands/update-env-configs.js.map +1 -1
  28. package/dist/commands/verify.d.ts.map +1 -1
  29. package/dist/commands/verify.js +78 -1
  30. package/dist/commands/verify.js.map +1 -1
  31. package/dist/core/deploy/engine.d.ts +11 -0
  32. package/dist/core/deploy/engine.d.ts.map +1 -1
  33. package/dist/core/deploy/engine.js +35 -7
  34. package/dist/core/deploy/engine.js.map +1 -1
  35. package/dist/core/git-integration.d.ts +2 -1
  36. package/dist/core/git-integration.d.ts.map +1 -1
  37. package/dist/core/git-integration.js +38 -14
  38. package/dist/core/git-integration.js.map +1 -1
  39. package/dist/core/global-counters.d.ts +3 -0
  40. package/dist/core/global-counters.d.ts.map +1 -1
  41. package/dist/core/global-counters.js +3 -1
  42. package/dist/core/global-counters.js.map +1 -1
  43. package/dist/core/prompt-builder.d.ts.map +1 -1
  44. package/dist/core/prompt-builder.js +7 -6
  45. package/dist/core/prompt-builder.js.map +1 -1
  46. package/dist/core/spec-paths.d.ts.map +1 -1
  47. package/dist/core/spec-paths.js +3 -0
  48. package/dist/core/spec-paths.js.map +1 -1
  49. package/dist/core/spec-skeleton.d.ts.map +1 -1
  50. package/dist/core/spec-skeleton.js +6 -2
  51. package/dist/core/spec-skeleton.js.map +1 -1
  52. package/dist/core/state.d.ts +11 -0
  53. package/dist/core/state.d.ts.map +1 -1
  54. package/dist/core/state.js +33 -2
  55. package/dist/core/state.js.map +1 -1
  56. package/dist/core/ui-verify/index.d.ts +2 -2
  57. package/dist/core/ui-verify/index.d.ts.map +1 -1
  58. package/dist/core/ui-verify/index.js +3 -1
  59. package/dist/core/ui-verify/index.js.map +1 -1
  60. package/dist/core/ui-verify/smoke-engine.d.ts.map +1 -1
  61. package/dist/core/ui-verify/smoke-engine.js +36 -0
  62. package/dist/core/ui-verify/smoke-engine.js.map +1 -1
  63. package/dist/core/ui-verify/spec-generator.d.ts +32 -1
  64. package/dist/core/ui-verify/spec-generator.d.ts.map +1 -1
  65. package/dist/core/ui-verify/spec-generator.js +205 -21
  66. package/dist/core/ui-verify/spec-generator.js.map +1 -1
  67. package/dist/core/ui-verify/types.d.ts +2 -0
  68. package/dist/core/ui-verify/types.d.ts.map +1 -1
  69. package/package.json +3 -2
  70. package/templates/api-design-example.md +338 -0
  71. package/templates/ci/github-actions.yml +44 -0
  72. package/templates/database-example.md +223 -0
  73. package/templates/deploy-docker/README.md +296 -0
  74. package/templates/deploy-docker/backend-node.Dockerfile +52 -0
  75. package/templates/deploy-docker/deploy-remote.sh +79 -0
  76. package/templates/deploy-docker/docker-compose.yml +113 -0
  77. package/templates/deploy-docker/frontend.Dockerfile +43 -0
  78. package/templates/deploy-docker/nginx.conf +30 -0
  79. package/templates/deploy-examples.yaml +511 -0
  80. package/templates/deploy-java/Dockerfile +50 -0
  81. package/templates/deploy-java/README.md +212 -0
  82. package/templates/deploy-java/deploy.sh +120 -0
  83. package/templates/deploy-java/spring-boot.service +35 -0
  84. package/templates/deploy-nginx/README.md +59 -0
  85. package/templates/deploy-nginx/nginx-site.conf +103 -0
  86. package/templates/deploy-scripts/README.md +61 -0
  87. package/templates/deploy-scripts/deploy-compose.sh +19 -0
  88. package/templates/deploy-scripts/deploy-ftp.sh +28 -0
  89. package/templates/deploy-scripts/deploy-password-ssh.sh +26 -0
  90. package/templates/deploy-scripts/deploy-python.sh +30 -0
  91. package/templates/deploy-scripts/trigger-jenkins.sh +30 -0
  92. package/templates/html/speccore-ask-explain.html +10 -0
  93. package/templates/html/speccore-ask-guide.html +10 -0
  94. package/templates/html/speccore-ask-match.html +10 -0
  95. package/templates/html/speccore-ask-pipeline.html +1 -0
  96. package/templates/html/speccore-ask-result.html +10 -0
  97. package/templates/html/speccore-help.html +241 -0
  98. package/templates/html/speccore-setup-guide.html +289 -0
  99. package/templates/security-example.md +226 -0
  100. package/templates/speccore-yml-example.yml +222 -0
  101. package/templates/verify-spec-example.yaml +142 -0
@@ -0,0 +1,338 @@
1
+ # API 设计规范示例
2
+
3
+ > 本文件为 RESTful API 设计规范示例,供新项目参考。
4
+ > 复制到项目后按需修改,或作为 `.speccore/RULES/api-design.md` 的素材。
5
+
6
+ ---
7
+
8
+ ## 1. 基础规范
9
+
10
+ ### 1.1 URL 设计
11
+
12
+ - **全部小写**,使用短横线 `-` 分隔单词
13
+ - **资源名用复数**:`/users` `/orders` `/products`
14
+ - **避免动词**:用 HTTP 方法表达动作,不要写 `/getUsers` `/createOrder`
15
+ - **嵌套不超过 3 层**:`/users/{id}/orders/{orderId}/items` ✅,`/users/{id}/orders/{orderId}/items/{itemId}/reviews/{reviewId}` ❌
16
+
17
+ ```
18
+ GET /users # 列表
19
+ GET /users/{id} # 详情
20
+ POST /users # 创建
21
+ PUT /users/{id} # 全量更新
22
+ PATCH /users/{id} # 部分更新
23
+ DELETE /users/{id} # 删除
24
+ ```
25
+
26
+ ### 1.2 HTTP 状态码
27
+
28
+ | 状态码 | 场景 | 说明 |
29
+ |:---|:---|:---|
30
+ | `200` | 成功 | GET/PUT/PATCH/DELETE 成功 |
31
+ | `201` | 创建成功 | POST 创建资源成功 |
32
+ | `204` | 无内容 | DELETE 成功,不返回 body |
33
+ | `400` | 参数错误 | 请求参数校验失败 |
34
+ | `401` | 未认证 | Token 缺失或过期 |
35
+ | `403` | 无权限 | 已登录但无权访问 |
36
+ | `404` | 不存在 | 资源不存在 |
37
+ | `409` | 冲突 | 资源已存在或状态冲突 |
38
+ | `422` | 业务规则冲突 | 请求语法正确但业务规则不允许 |
39
+ | `429` | 限流 | 请求过于频繁 |
40
+ | `500` | 系统错误 | 服务端未捕获异常 |
41
+
42
+ ### 1.3 请求/响应格式
43
+
44
+ **请求头必备:**
45
+ ```
46
+ Content-Type: application/json
47
+ Authorization: Bearer {token}
48
+ X-Request-Id: {uuid} # 链路追踪 ID
49
+ X-Client-Version: 1.2.0 # 客户端版本(可选)
50
+ ```
51
+
52
+ **统一响应体:**
53
+ ```json
54
+ {
55
+ "success": true,
56
+ "code": "OK",
57
+ "message": "success",
58
+ "data": { ... },
59
+ "traceId": "req-abc123",
60
+ "timestamp": "2026-09-10T12:00:00Z"
61
+ }
62
+ ```
63
+
64
+ **错误响应体:**
65
+ ```json
66
+ {
67
+ "success": false,
68
+ "code": "BIZ_001",
69
+ "message": "参数校验失败",
70
+ "details": [
71
+ { "field": "phone", "message": "手机号格式不正确" }
72
+ ],
73
+ "traceId": "req-abc123",
74
+ "timestamp": "2026-09-10T12:00:00Z"
75
+ }
76
+ ```
77
+
78
+ ---
79
+
80
+ ## 2. 分页规范
81
+
82
+ **请求:**
83
+ ```
84
+ GET /users?page=1&pageSize=20&sort=createdAt,desc&sort=name,asc
85
+ ```
86
+
87
+ **响应:**
88
+ ```json
89
+ {
90
+ "success": true,
91
+ "data": {
92
+ "list": [ ... ],
93
+ "pagination": {
94
+ "page": 1,
95
+ "pageSize": 20,
96
+ "total": 156,
97
+ "totalPages": 8,
98
+ "hasNext": true,
99
+ "hasPrev": false
100
+ }
101
+ }
102
+ }
103
+ ```
104
+
105
+ **规则:**
106
+ - `page` 从 1 开始,不是 0
107
+ - `pageSize` 默认 20,最大 100
108
+ - `sort` 支持多字段,格式 `字段名,asc|desc`
109
+ - 不分页接口必须显式声明,默认都分页
110
+
111
+ ---
112
+
113
+ ## 3. 鉴权规范
114
+
115
+ ### 3.1 Token 机制
116
+
117
+ - **Access Token:** JWT,有效期 2 小时,放在 `Authorization: Bearer {token}`
118
+ - **Refresh Token:** 有效期 7 天,用于换取新的 Access Token
119
+ - **Token 刷新:** 返回 401 时,客户端用 Refresh Token 换取新 Access Token,重试原请求
120
+
121
+ ### 3.2 接口鉴权分级
122
+
123
+ | 级别 | 说明 | 示例 |
124
+ |:---|:---|:---|
125
+ | `public` | 无需登录 | 登录接口、注册接口、公开数据 |
126
+ | `user` | 需登录 | 查看自己的订单、修改个人资料 |
127
+ | `admin` | 需管理员权限 | 用户管理、系统配置 |
128
+ | `super` | 需超级管理员 | 删除组织、修改全局配置 |
129
+
130
+ ### 3.3 权限校验顺序
131
+
132
+ 1. 校验 Token 有效性(是否过期、是否被吊销)
133
+ 2. 校验接口访问权限(该角色能否访问此接口)
134
+ 3. 校验数据权限(该用户能否操作此数据)
135
+ 4. 记录审计日志(谁、什么时间、访问了什么)
136
+
137
+ ---
138
+
139
+ ## 4. 版本控制
140
+
141
+ ### 4.1 URL 路径版本(推荐)
142
+
143
+ ```
144
+ /v1/users
145
+ /v2/users
146
+ ```
147
+
148
+ ### 4.2 Header 版本(备选)
149
+
150
+ ```
151
+ Accept: application/json; version=2.0
152
+ ```
153
+
154
+ **规则:**
155
+ - 主版本号变更(v1 → v2)才改 URL,内部迭代不改
156
+ - 老版本保留至少 6 个月,给客户端迁移时间
157
+ - 版本文档必须说明各版本差异和废弃计划
158
+
159
+ ---
160
+
161
+ ## 5. 文件上传
162
+
163
+ ### 5.1 直接上传(小文件 < 5MB)
164
+
165
+ ```
166
+ POST /files
167
+ Content-Type: multipart/form-data
168
+
169
+ file: (binary)
170
+ folder: avatars # 业务目录
171
+ ```
172
+
173
+ ### 5.2 预签名上传(大文件 > 5MB)
174
+
175
+ ```
176
+ POST /files/presign
177
+ {
178
+ "filename": "report.pdf",
179
+ "size": 10485760,
180
+ "mimeType": "application/pdf"
181
+ }
182
+
183
+ # 返回预签名 URL,客户端直传 OSS/S3
184
+ {
185
+ "success": true,
186
+ "data": {
187
+ "uploadUrl": "https://oss.example.com/...",
188
+ "fileUrl": "https://cdn.example.com/files/xxx.pdf",
189
+ "expiresAt": "2026-09-10T12:05:00Z"
190
+ }
191
+ }
192
+ ```
193
+
194
+ **规则:**
195
+ - 限制文件类型(白名单)
196
+ - 限制文件大小(单文件最大 50MB)
197
+ - 图片自动压缩、生成缩略图
198
+ - 敏感文件(身份证、营业执照)加密存储
199
+
200
+ ---
201
+
202
+ ## 6. 幂等性设计
203
+
204
+ ### 6.1 幂等键(Idempotency-Key)
205
+
206
+ ```
207
+ POST /orders
208
+ Idempotency-Key: {uuid}
209
+
210
+ {
211
+ "productId": 123,
212
+ "quantity": 2
213
+ }
214
+ ```
215
+
216
+ **规则:**
217
+ - 客户端生成唯一键,服务端缓存结果 24 小时
218
+ - 相同幂等键重复请求,返回相同结果(不重复执行业务)
219
+ - 适用于:支付、下单、转账等关键操作
220
+
221
+ ### 6.2 乐观锁(Version)
222
+
223
+ ```
224
+ PUT /users/{id}
225
+ {
226
+ "name": "张三",
227
+ "version": 5
228
+ }
229
+ ```
230
+
231
+ - 更新时校验 `version`,不一致返回 `409 Conflict`
232
+ - 适用于:并发修改同一资源的场景
233
+
234
+ ---
235
+
236
+ ## 7. 批量操作
237
+
238
+ ### 7.1 批量查询
239
+
240
+ ```
241
+ GET /users?ids=1,2,3,4,5
242
+ ```
243
+
244
+ - `ids` 最多 100 个
245
+ - 超过 100 个返回 `400`,提示分批查询
246
+
247
+ ### 7.2 批量创建/更新/删除
248
+
249
+ ```
250
+ POST /users/batch
251
+ {
252
+ "items": [
253
+ { "name": "张三", "phone": "13800138001" },
254
+ { "name": "李四", "phone": "13800138002" }
255
+ ]
256
+ }
257
+ ```
258
+
259
+ **规则:**
260
+ - 批量最多 100 条
261
+ - 部分失败返回 `207 Multi-Status`,明细说明每条结果
262
+ - 全部失败返回 `400`,不执行任何操作(事务回滚)
263
+
264
+ ---
265
+
266
+ ## 8. 限流与熔断
267
+
268
+ ### 8.1 限流规则
269
+
270
+ | 级别 | 阈值 | 说明 |
271
+ |:---|:---|:---|
272
+ | IP 级 | 100 次/分钟 | 防止单 IP 刷接口 |
273
+ | 用户级 | 1000 次/分钟 | 正常用户足够,异常行为拦截 |
274
+ | 接口级 | 根据业务设定 | 如短信接口 5 次/小时 |
275
+
276
+ ### 8.2 熔断策略
277
+
278
+ - 错误率 > 50% 持续 1 分钟 → 熔断 30 秒
279
+ - 熔断期间返回 `503`,提示"服务暂不可用"
280
+ - 熔断恢复后,先放行少量请求探测,正常后全开
281
+
282
+ ---
283
+
284
+ ## 9. 接口文档规范
285
+
286
+ ### 9.1 文档必备内容
287
+
288
+ 每个接口文档必须包含:
289
+ 1. **接口描述** — 一句话说明功能
290
+ 2. **请求方法 + URL** — 含路径参数说明
291
+ 3. **请求头** — 必填头列表
292
+ 4. **请求参数** — Query / Body / Path,含类型、必填、示例、约束
293
+ 5. **响应体** — 成功 + 失败示例
294
+ 6. **错误码** — 该接口可能返回的所有错误码
295
+ 7. **权限要求** — public / user / admin / super
296
+ 8. **幂等性** — 是否幂等,幂等键要求
297
+
298
+ ### 9.2 示例模板
299
+
300
+ ```markdown
301
+ ### 创建订单
302
+
303
+ **接口描述:** 用户创建新订单
304
+
305
+ **请求:**
306
+ ```
307
+ POST /v1/orders
308
+ Authorization: Bearer {token}
309
+ Idempotency-Key: {uuid}
310
+ ```
311
+
312
+ **请求体:**
313
+ | 字段 | 类型 | 必填 | 说明 | 示例 |
314
+ |:---|:---|:---:|:---|:---|
315
+ | productId | long | ✅ | 商品 ID | 123 |
316
+ | quantity | int | ✅ | 数量,1~99 | 2 |
317
+ | remark | string | ❌ | 订单备注,≤200字 | "请尽快发货" |
318
+
319
+ **响应:**
320
+ ```json
321
+ {
322
+ "success": true,
323
+ "data": {
324
+ "orderId": "ORD-20260910-001",
325
+ "status": "PENDING_PAYMENT",
326
+ "totalAmount": 19900,
327
+ "createdAt": "2026-09-10T12:00:00Z"
328
+ }
329
+ }
330
+ ```
331
+
332
+ **错误码:**
333
+ | 错误码 | 说明 |
334
+ |:---|:---|
335
+ | BIZ_001 | productId 不存在 |
336
+ | BIZ_005 | 库存不足 |
337
+ | BIZ_003 | 重复提交(相同幂等键) |
338
+ ```
@@ -0,0 +1,44 @@
1
+ # SpecCore CI — GitHub Actions
2
+ # Copy this file to your project: .github/workflows/speccore-ci.yml
3
+
4
+ name: SpecCore Validate
5
+
6
+ on:
7
+ push:
8
+ branches: [main, feature/*]
9
+ pull_request:
10
+ branches: [main]
11
+
12
+ jobs:
13
+ validate:
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+
18
+ - name: Setup Node.js
19
+ uses: actions/setup-node@v4
20
+ with:
21
+ node-version: '20'
22
+
23
+ - name: Install SpecCore
24
+ run: npm install -g speccore
25
+
26
+ - name: Validate Specs
27
+ run: |
28
+ speccore validate --full
29
+ if [ $? -ne 0 ]; then
30
+ echo "⚠️ Spec validation failed. Please fix the issues above."
31
+ exit 1
32
+ fi
33
+
34
+ - name: Check Project Health
35
+ run: speccore doctor
36
+
37
+ - name: Progress Report
38
+ run: speccore progress --format=json > progress.json
39
+
40
+ - name: Upload Progress Artifact
41
+ uses: actions/upload-artifact@v4
42
+ with:
43
+ name: spec-progress
44
+ path: progress.json
@@ -0,0 +1,223 @@
1
+ # 数据库设计规范示例
2
+
3
+ > 本文件为数据库设计规范示例,涵盖命名、字段、索引、分表等经典规则。
4
+ > 复制到项目后按需修改,或作为 `.speccore/RULES/database.md` 的素材。
5
+
6
+ ---
7
+
8
+ ## 1. 命名规范
9
+
10
+ ### 1.1 表命名
11
+
12
+ | 规则 | 示例 | 说明 |
13
+ |:---|:---|:---|
14
+ | 小写 + 下划线 | `user_profile` | 全部小写,单词间用 `_` 分隔 |
15
+ | 复数形式 | `orders` `users` | 表名用复数 |
16
+ | 业务前缀 | `oms_order` `cms_article` | 多模块项目加前缀区分 |
17
+ | 禁用保留字 | — | 不要用 `order` `group` `key` 等 SQL 保留字 |
18
+
19
+ ### 1.2 字段命名
20
+
21
+ | 规则 | 正例 | 反例 |
22
+ |:---|:---|:---|
23
+ | 小写 + 下划线 | `created_at` | `createdAt` `Created_At` |
24
+ | 外键格式 | `user_id` `order_id` | `uid` `oid` |
25
+ | 布尔字段 | `is_deleted` `is_active` | `deleted` `active` |
26
+ | 状态字段 | `status` + 枚举说明 | `state`(模糊) |
27
+ | 时间字段 | `created_at` `updated_at` | `create_time`(不一致) |
28
+
29
+ ### 1.3 索引命名
30
+
31
+ | 类型 | 命名格式 | 示例 |
32
+ |:---|:---|:---|
33
+ | 主键 | `pk_表名` | `pk_users` |
34
+ | 唯一索引 | `uk_表名_字段` | `uk_users_phone` |
35
+ | 普通索引 | `idx_表名_字段` | `idx_orders_user_id` |
36
+ | 联合索引 | `idx_表名_字段1_字段2` | `idx_orders_user_id_status` |
37
+
38
+ ---
39
+
40
+ ## 2. 字段设计规范
41
+
42
+ ### 2.1 必备字段(每张表必须有)
43
+
44
+ | 字段名 | 类型 | 默认值 | 说明 |
45
+ |:---|:---|:---|:---|
46
+ | `id` | `BIGINT UNSIGNED` | 自增 | 主键,建议使用雪花 ID |
47
+ | `created_at` | `DATETIME(3)` | `CURRENT_TIMESTAMP(3)` | 创建时间,毫秒精度 |
48
+ | `updated_at` | `DATETIME(3)` | `CURRENT_TIMESTAMP(3)` | 更新时间,ON UPDATE 自动更新 |
49
+ | `created_by` | `BIGINT UNSIGNED` | `NULL` | 创建人 ID |
50
+ | `updated_by` | `BIGINT UNSIGNED` | `NULL` | 更新人 ID |
51
+ | `deleted_at` | `DATETIME(3)` | `NULL` | 软删除时间,NULL 表示未删除 |
52
+ | `deleted_by` | `BIGINT UNSIGNED` | `NULL` | 删除人 ID |
53
+ | `version` | `INT UNSIGNED` | `0` | 乐观锁版本号 |
54
+
55
+ ### 2.2 常用字段类型选择
56
+
57
+ | 场景 | 推荐类型 | 不推荐 | 说明 |
58
+ |:---|:---|:---|:---|
59
+ | 主键 | `BIGINT UNSIGNED` | `INT` | 防止溢出 |
60
+ | 金额 | `BIGINT`(分) | `DECIMAL` `FLOAT` | 整数存储,避免精度问题 |
61
+ | 手机号 | `VARCHAR(20)` | `BIGINT` | 支持国际号码、国家码 |
62
+ | 邮箱 | `VARCHAR(128)` | `TEXT` | 有长度限制,可建索引 |
63
+ | 用户名 | `VARCHAR(64)` | `TEXT` | — |
64
+ | 密码 | `VARCHAR(255)` | `CHAR(32)` | 需兼容 bcrypt 等哈希长度 |
65
+ | 状态枚举 | `TINYINT UNSIGNED` | `VARCHAR` | 节省空间,配合代码枚举 |
66
+ | 大文本 | `TEXT` | `VARCHAR(65535)` | 文章、评论等内容 |
67
+ | JSON 数据 | `JSON` | `TEXT` | MySQL 5.7+ / PostgreSQL 原生支持 |
68
+ | IP 地址 | `VARBINARY(16)` | `VARCHAR(45)` | 兼容 IPv4/IPv6 |
69
+ | 时间戳 | `DATETIME(3)` | `TIMESTAMP` | DATETIME 无时区歧义,范围更大 |
70
+
71
+ ### 2.3 字段约束
72
+
73
+ - **NOT NULL 优先:** 尽量不让字段为 NULL,用默认值代替
74
+ - **状态字段必须有注释:** 说明每个值的含义
75
+ - **JSON 字段必须定义结构:** 即使类型是 JSON,也要在文档中定义字段结构
76
+ - **大字段单独表:** TEXT/BLOB 超过 1KB 建议拆到副表
77
+
78
+ ---
79
+
80
+ ## 3. 索引设计规范
81
+
82
+ ### 3.1 索引原则
83
+
84
+ 1. **where 条件字段必建索引** — 特别是高频查询条件
85
+ 2. **联合索引最左前缀** — `(a, b, c)` 可以覆盖 `a` `a,b` `a,b,c`,但不能覆盖 `b` `c`
86
+ 3. **覆盖索引优先** — 查询字段都在索引中,避免回表
87
+ 4. **索引不是越多越好** — 单表索引不超过 5 个,联合索引字段不超过 4 个
88
+ 5. **区分度低的字段放前面** — 性别(区分度 2)放前面,创建时间(区分度高)放后面
89
+ 6. **冗余索引清理** — `(a)` 和 `(a,b)` 并存时,`(a)` 是冗余的
90
+
91
+ ### 3.2 索引示例
92
+
93
+ ```sql
94
+ -- 用户表
95
+ CREATE TABLE users (
96
+ id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
97
+ phone VARCHAR(20) NOT NULL,
98
+ email VARCHAR(128),
99
+ username VARCHAR(64) NOT NULL,
100
+ status TINYINT UNSIGNED NOT NULL DEFAULT 1 COMMENT '1-正常 2-冻结 3-注销',
101
+ created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
102
+ updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
103
+ deleted_at DATETIME(3) DEFAULT NULL,
104
+
105
+ UNIQUE KEY uk_users_phone (phone),
106
+ UNIQUE KEY uk_users_email (email),
107
+ UNIQUE KEY uk_users_username (username),
108
+ KEY idx_users_status_created (status, created_at)
109
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
110
+ ```
111
+
112
+ ### 3.3 索引禁忌
113
+
114
+ - ❌ 不要在低区分度字段上单独建索引(如 `status` 只有 2 个值)
115
+ - ❌ 不要对频繁更新的字段建索引(更新成本 = 数据更新 + 索引更新)
116
+ - ❌ 不要在 WHERE 条件中对字段做函数运算(如 `WHERE DATE(created_at) = '2026-09-10'`)
117
+ - ❌ 不要用 `SELECT *`,只查需要的字段,尽量覆盖索引
118
+
119
+ ---
120
+
121
+ ## 4. 分表分库策略
122
+
123
+ ### 4.1 何时分表
124
+
125
+ | 条件 | 策略 |
126
+ |:---|:---|
127
+ | 单表数据 > 500 万 | 水平分表 |
128
+ | 单表数据 > 1 亿 | 水平分库 + 分表 |
129
+ | 字段数 > 50 | 垂直拆分(大字段拆副表) |
130
+ | 冷热数据明显 | 归档表(近 3 个月热数据 + 历史归档表) |
131
+
132
+ ### 4.2 分表路由键选择
133
+
134
+ | 场景 | 路由键 | 说明 |
135
+ |:---|:---|:---|
136
+ | 用户相关数据 | `user_id` | 按用户维度分片,查询集中在单分片 |
137
+ | 订单数据 | `order_id` 或 `user_id` | 订单号含时间戳可直接路由 |
138
+ | 时间序列数据 | `created_at` | 按时间范围分片,便于归档清理 |
139
+ | 地理位置数据 | `region_code` | 按地区分片,就近访问 |
140
+
141
+ ### 4.3 分表示例
142
+
143
+ ```sql
144
+ -- 订单表按 user_id % 128 分片
145
+ -- 物理表:order_000 ~ order_127
146
+ -- 路由规则:order_{user_id % 128}
147
+
148
+ CREATE TABLE order_000 (
149
+ id BIGINT UNSIGNED PRIMARY KEY,
150
+ order_no VARCHAR(32) NOT NULL,
151
+ user_id BIGINT UNSIGNED NOT NULL,
152
+ total_amount BIGINT NOT NULL COMMENT '金额(分)',
153
+ status TINYINT UNSIGNED NOT NULL,
154
+ created_at DATETIME(3) NOT NULL,
155
+
156
+ UNIQUE KEY uk_order_no (order_no),
157
+ KEY idx_user_id_created (user_id, created_at)
158
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
159
+ ```
160
+
161
+ ---
162
+
163
+ ## 5. 软删除与数据归档
164
+
165
+ ### 5.1 软删除实现
166
+
167
+ ```sql
168
+ -- 查询时默认过滤软删除数据
169
+ SELECT * FROM users WHERE deleted_at IS NULL;
170
+
171
+ -- 需要包含已删除数据时显式指定
172
+ SELECT * FROM users WHERE deleted_at IS NOT NULL;
173
+ ```
174
+
175
+ ### 5.2 数据归档策略
176
+
177
+ | 数据类型 | 保留时间 | 归档方式 |
178
+ |:---|:---|:---|
179
+ | 操作日志 | 90 天 | 超过后迁移到归档表或 OSS |
180
+ | 订单数据 | 3 年 | 冷数据归档到历史库 |
181
+ | 系统日志 | 30 天 | ELK 设置过期策略 |
182
+ | 审计日志 | 3 年 | 单独存储,不可删除 |
183
+
184
+ ---
185
+
186
+ ## 6. SQL 编写规范
187
+
188
+ ### 6.1 SELECT
189
+
190
+ - 必须指定字段,禁止 `SELECT *`
191
+ - 分页查询必须带 `ORDER BY`,否则结果不稳定
192
+ - 大批量查询使用 `LIMIT + 游标`,避免深分页 `OFFSET 1000000`
193
+
194
+ ### 6.2 INSERT/UPDATE/DELETE
195
+
196
+ - INSERT 必须指定字段名:`INSERT INTO t (a, b) VALUES (?, ?)`
197
+ - UPDATE 必须带 WHERE 条件,禁止全表更新
198
+ - DELETE 必须带 WHERE 条件,生产环境建议用软删除代替
199
+
200
+ ### 6.3 事务
201
+
202
+ - 事务尽量短,不要在事务中调外部接口
203
+ - 更新多个表时,按相同顺序加锁,避免死锁
204
+ - 批量操作使用 `INSERT ... ON DUPLICATE KEY UPDATE` 或 `REPLACE INTO`
205
+
206
+ ---
207
+
208
+ ## 7. 数据库评审清单
209
+
210
+ 新建或修改表时必须检查:
211
+
212
+ - [ ] 表名符合命名规范(小写 + 下划线 + 复数)
213
+ - [ ] 包含必备字段(id, created_at, updated_at, deleted_at, version)
214
+ - [ ] 主键使用 BIGINT UNSIGNED
215
+ - [ ] 金额字段用 BIGINT(分)存储
216
+ - [ ] 状态字段有注释说明每个值的含义
217
+ - [ ] 外键字段建立索引
218
+ - [ ] WHERE 条件字段建立索引
219
+ - [ ] 联合索引符合最左前缀原则
220
+ - [ ] 单表索引数量 ≤ 5
221
+ - [ ] 表和字段都有 COMMENT 注释
222
+ - [ ] 字符集使用 utf8mb4
223
+ - [ ] 引擎使用 InnoDB