mysql-patterns

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

MySQL Patterns

MySQL 模式

Use this skill when working on MySQL or MariaDB schema design, migrations, slow-query investigation, queue-style transactions, connection pools, or production database configuration. Prefer exact version checks before applying a feature-specific pattern because MySQL and MariaDB have diverged in several SQL details.
当你进行MySQL或MariaDB架构设计、迁移、慢查询排查、队列式事务、连接池配置或生产数据库配置时,可以使用本技能。在应用特定功能模式前,建议先精确检查版本,因为MySQL和MariaDB在若干SQL细节上已经出现差异。

Activation

适用场景

  • Designing MySQL or MariaDB tables, indexes, and constraints
  • Reviewing migrations before they run on large production tables
  • Debugging slow queries, lock waits, deadlocks, or connection exhaustion
  • Adding keyset pagination, upserts, full-text search, JSON columns, or queues
  • Configuring application connection pools, read replicas, TLS, or slow logs
  • 设计MySQL或MariaDB的表、索引与约束
  • 在大型生产表上执行迁移前进行审核
  • 调试慢查询、锁等待、死锁或连接耗尽问题
  • 实现键集分页、Upsert、全文搜索、JSON列或队列功能
  • 配置应用连接池、只读副本、TLS或慢查询日志

Version Check

版本检查

Start by identifying the engine and version:
sql
SELECT VERSION();
SHOW VARIABLES LIKE 'version_comment';
Keep MySQL and MariaDB guidance separate when syntax differs:
  • MySQL documents row aliases as the replacement for
    VALUES(col)
    in
    ON DUPLICATE KEY UPDATE
    ;
    VALUES(col)
    is deprecated there.
  • MariaDB documents
    VALUES(col)
    as the supported way to reference inserted values in
    ON DUPLICATE KEY UPDATE
    ; use it for cross-engine compatibility.
  • SKIP LOCKED
    is appropriate for queue-like work only. It skips locked rows and can return an inconsistent view, so do not use it for general accounting or integrity-sensitive reads.
首先确认数据库引擎和版本:
sql
SELECT VERSION();
SHOW VARIABLES LIKE 'version_comment';
当语法存在差异时,需区分MySQL和MariaDB的指导方案:
  • MySQL文档中,行别名是
    ON DUPLICATE KEY UPDATE
    VALUES(col)
    的替代方案;
    VALUES(col)
    在MySQL中已被弃用。
  • MariaDB文档中,
    VALUES(col)
    ON DUPLICATE KEY UPDATE
    中引用插入值的支持方式;若需跨引擎兼容,可使用该方案。
  • SKIP LOCKED
    仅适用于类队列场景。它会跳过锁定行,可能返回不一致视图,因此不要用于常规会计或对完整性敏感的读取操作。

Schema Defaults

架构默认配置

sql
CREATE TABLE orders (
    id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
    account_id BIGINT UNSIGNED NOT NULL,
    status VARCHAR(32) NOT NULL,
    total DECIMAL(15, 2) NOT NULL,
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    deleted_at DATETIME NULL,
    PRIMARY KEY (id),
    KEY idx_orders_account_status_created (account_id, status, created_at),
    KEY idx_orders_active (account_id, deleted_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
Default choices:
Use CasePreferAvoid
Surrogate primary keys
BIGINT UNSIGNED AUTO_INCREMENT
INT
for tables that can grow beyond 2B rows
UUID lookup keys
BINARY(16)
with conversion helpers
VARCHAR(36)
primary keys on hot tables
Money and exact quantities
DECIMAL(p, s)
FLOAT
or
DOUBLE
User-facing text
utf8mb4
tables and indexes
MySQL
utf8
/
utf8mb3
defaults
Application timestamps
DATETIME
with UTC managed by the app
Assuming
DATETIME
stores time zone metadata
Soft deletes
deleted_at DATETIME NULL
plus scoped indexes
Filtering soft-deleted rows without an index
Extensible status valueslookup table or constrained
VARCHAR
ENUM
when values change often
sql
CREATE TABLE orders (
    id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
    account_id BIGINT UNSIGNED NOT NULL,
    status VARCHAR(32) NOT NULL,
    total DECIMAL(15, 2) NOT NULL,
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    deleted_at DATETIME NULL,
    PRIMARY KEY (id),
    KEY idx_orders_account_status_created (account_id, status, created_at),
    KEY idx_orders_active (account_id, deleted_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
默认选择建议:
使用场景推荐方案避免方案
代理主键
BIGINT UNSIGNED AUTO_INCREMENT
对于可能超过20亿行的表使用
INT
UUID查找键搭配转换工具使用
BINARY(16)
在高频访问表上使用
VARCHAR(36)
作为主键
金额与精确数量
DECIMAL(p, s)
FLOAT
DOUBLE
用户可见文本表和索引使用
utf8mb4
MySQL默认的
utf8
/
utf8mb3
应用时间戳由应用管理UTC时间的
DATETIME
假设
DATETIME
存储时区元数据
软删除
deleted_at DATETIME NULL
加上范围索引
过滤软删除行时不使用索引
可扩展状态值查找表或带约束的
VARCHAR
当值频繁变化时使用
ENUM

Indexing

索引优化

Composite index order usually follows equality predicates first, then range or sort columns:
sql
CREATE INDEX idx_orders_account_status_created
    ON orders (account_id, status, created_at);

SELECT id, total
FROM orders
WHERE account_id = ?
  AND status = 'pending'
  AND created_at >= ?
ORDER BY created_at DESC
LIMIT 50;
Use
EXPLAIN
before adding or changing an index:
sql
EXPLAIN
SELECT id, total
FROM orders
WHERE account_id = 123 AND status = 'pending'
ORDER BY created_at DESC
LIMIT 50;
Signals to investigate:
FieldRisk Signal
type
ALL
on a large table
key
NULL
when a selective predicate exists
rows
Very high row estimate for an interactive path
Extra
Using temporary
,
Using filesort
, or broad
Using where
Avoid adding indexes blindly. Each index increases write cost, migration time, backup size, and buffer-pool pressure.
复合索引的顺序通常遵循:先等值条件列,再范围或排序列:
sql
CREATE INDEX idx_orders_account_status_created
    ON orders (account_id, status, created_at);

SELECT id, total
FROM orders
WHERE account_id = ?
  AND status = 'pending'
  AND created_at >= ?
ORDER BY created_at DESC
LIMIT 50;
添加或修改索引前使用
EXPLAIN
分析:
sql
EXPLAIN
SELECT id, total
FROM orders
WHERE account_id = 123 AND status = 'pending'
ORDER BY created_at DESC
LIMIT 50;
需要排查的风险信号:
字段风险信号
type
大型表上出现
ALL
(全表扫描)
key
存在选择性条件时
key
NULL
rows
交互式查询路径的预估行数极高
Extra
Using temporary
Using filesort
或宽泛的
Using where
避免盲目添加索引。每个索引都会增加写入成本、迁移时间、备份大小和缓冲池压力。

Query Patterns

查询模式

Upsert

Upsert

Cross-engine-compatible form:
sql
INSERT INTO user_settings (user_id, setting_key, setting_value)
VALUES (?, ?, ?)
ON DUPLICATE KEY UPDATE
    setting_value = VALUES(setting_value),
    updated_at = CURRENT_TIMESTAMP;
MySQL row-alias form:
sql
INSERT INTO user_settings (user_id, setting_key, setting_value)
VALUES (?, ?, ?) AS new
ON DUPLICATE KEY UPDATE
    setting_value = new.setting_value,
    updated_at = CURRENT_TIMESTAMP;
Use the row-alias form only after confirming the target is MySQL. Use
VALUES(col)
for MariaDB or mixed MySQL/MariaDB fleets.
跨引擎兼容格式:
sql
INSERT INTO user_settings (user_id, setting_key, setting_value)
VALUES (?, ?, ?)
ON DUPLICATE KEY UPDATE
    setting_value = VALUES(setting_value),
    updated_at = CURRENT_TIMESTAMP;
MySQL行别名格式:
sql
INSERT INTO user_settings (user_id, setting_key, setting_value)
VALUES (?, ?, ?) AS new
ON DUPLICATE KEY UPDATE
    setting_value = new.setting_value,
    updated_at = CURRENT_TIMESTAMP;
仅在确认目标为MySQL时使用行别名格式。对于MariaDB或混合MySQL/MariaDB集群,使用
VALUES(col)

Keyset Pagination

键集分页

sql
SELECT id, name, created_at
FROM products
WHERE (created_at, id) < (?, ?)
ORDER BY created_at DESC, id DESC
LIMIT 50;
Back it with an index that matches the cursor:
sql
CREATE INDEX idx_products_created_id ON products (created_at, id);
Do not use deep
OFFSET
pagination on large tables; it makes the server scan and discard rows before returning the page.
sql
SELECT id, name, created_at
FROM products
WHERE (created_at, id) < (?, ?)
ORDER BY created_at DESC, id DESC
LIMIT 50;
为其创建匹配游标条件的索引:
sql
CREATE INDEX idx_products_created_id ON products (created_at, id);
不要在大型表上使用深度
OFFSET
分页;这会导致服务器扫描并丢弃大量行后才返回目标页面。

JSON Fields

JSON字段

Use JSON columns for extension data, not for fields that need heavy relational filtering or constraints.
sql
CREATE TABLE events (
    id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    payload JSON NOT NULL,
    event_type VARCHAR(64)
        GENERATED ALWAYS AS (JSON_UNQUOTE(JSON_EXTRACT(payload, '$.type'))) STORED,
    KEY idx_events_type (event_type)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
For frequently queried JSON paths, expose a generated column and index that column. Keep foreign keys, ownership, tenancy, and lifecycle fields relational.
JSON列适用于扩展数据,不适用于需要大量关系型过滤或约束的字段。
sql
CREATE TABLE events (
    id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    payload JSON NOT NULL,
    event_type VARCHAR(64)
        GENERATED ALWAYS AS (JSON_UNQUOTE(JSON_EXTRACT(payload, '$.type'))) STORED,
    KEY idx_events_type (event_type)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
对于频繁查询的JSON路径,生成一个计算列并为该列创建索引。将外键、归属关系、租户信息和生命周期字段保留为关系型字段。

Full-Text Search

全文搜索

sql
ALTER TABLE articles ADD FULLTEXT KEY ft_articles_title_body (title, body);

SELECT id, title, MATCH(title, body) AGAINST (? IN NATURAL LANGUAGE MODE) AS score
FROM articles
WHERE MATCH(title, body) AGAINST (? IN NATURAL LANGUAGE MODE)
ORDER BY score DESC
LIMIT 20;
Use external search when you need typo tolerance, complex ranking, cross-table facets, or language-specific analysis beyond built-in full-text behavior.
sql
ALTER TABLE articles ADD FULLTEXT KEY ft_articles_title_body (title, body);

SELECT id, title, MATCH(title, body) AGAINST (? IN NATURAL LANGUAGE MODE) AS score
FROM articles
WHERE MATCH(title, body) AGAINST (? IN NATURAL LANGUAGE MODE)
ORDER BY score DESC
LIMIT 20;
当你需要容错拼写、复杂排序、跨表分面或超出内置全文搜索能力的特定语言分析时,使用外部搜索工具。

Transactions

事务管理

Keep transactions short and lock rows in a consistent order:
sql
START TRANSACTION;

SELECT id, balance
FROM accounts
WHERE id IN (?, ?)
ORDER BY id
FOR UPDATE;

UPDATE accounts SET balance = balance - ? WHERE id = ?;
UPDATE accounts SET balance = balance + ? WHERE id = ?;

COMMIT;
Deadlock and lock-wait checklist:
  • Lock rows in a deterministic order across code paths.
  • Do external API calls before opening the transaction, not inside it.
  • Add indexes for predicates used in
    UPDATE
    ,
    DELETE
    , and locking reads.
  • On deadlock, roll back and retry the whole transaction with a bounded retry budget.
  • Capture
    SHOW ENGINE INNODB STATUS\G
    soon after a deadlock; it is overwritten by later events.
Queue-style worker claim:
sql
START TRANSACTION;

SELECT id
FROM jobs
WHERE status = 'pending'
ORDER BY created_at
LIMIT 1
FOR UPDATE SKIP LOCKED;

UPDATE jobs
SET status = 'processing', started_at = CURRENT_TIMESTAMP
WHERE id = ?;

COMMIT;
Use
SKIP LOCKED
only for queue-like workloads where skipping a locked row is acceptable. It is not a replacement for normal transactional consistency.
保持事务简短,并以一致的顺序锁定行:
sql
START TRANSACTION;

SELECT id, balance
FROM accounts
WHERE id IN (?, ?)
ORDER BY id
FOR UPDATE;

UPDATE accounts SET balance = balance - ? WHERE id = ?;
UPDATE accounts SET balance = balance + ? WHERE id = ?;

COMMIT;
死锁与锁等待检查清单:
  • 在所有代码路径中以确定的顺序锁定行。
  • 在开启事务前完成外部API调用,不要在事务内部执行。
  • UPDATE
    DELETE
    和锁定读取中使用的条件添加索引。
  • 发生死锁时,回滚并在有限重试次数内重新执行整个事务。
  • 死锁发生后立即捕获
    SHOW ENGINE INNODB STATUS\G
    ;该信息会被后续事件覆盖。
类队列工作者任务认领:
sql
START TRANSACTION;

SELECT id
FROM jobs
WHERE status = 'pending'
ORDER BY created_at
LIMIT 1
FOR UPDATE SKIP LOCKED;

UPDATE jobs
SET status = 'processing', started_at = CURRENT_TIMESTAMP
WHERE id = ?;

COMMIT;
仅在类队列工作负载中使用
SKIP LOCKED
,这类场景下跳过锁定行是可接受的。它不能替代常规事务一致性。

Connection Pools

连接池配置

SQLAlchemy example:
python
from sqlalchemy import create_engine

engine = create_engine(
    "mysql+mysqlconnector://app:secret@db.internal/app",
    pool_size=10,
    max_overflow=5,
    pool_timeout=30,
    pool_recycle=240,
    pool_pre_ping=True,
    connect_args={"connect_timeout": 5},
)
Node.js
mysql2
example:
javascript
import mysql from 'mysql2/promise';

const pool = mysql.createPool({
  host: process.env.DB_HOST,
  user: process.env.DB_USER,
  password: process.env.DB_PASSWORD,
  database: process.env.DB_NAME,
  waitForConnections: true,
  connectionLimit: 10,
  queueLimit: 0,
  enableKeepAlive: true,
  keepAliveInitialDelay: 30000,
});

const [rows] = await pool.execute(
  'SELECT id, total FROM orders WHERE account_id = ? LIMIT 50',
  [accountId],
);
Keep application pool recycling below the server
wait_timeout
. If the server uses
wait_timeout = 300
, a
pool_recycle
around 240 seconds is coherent;
pool_pre_ping
still helps recover from network and failover events.
SQLAlchemy示例:
python
from sqlalchemy import create_engine

engine = create_engine(
    "mysql+mysqlconnector://app:secret@db.internal/app",
    pool_size=10,
    max_overflow=5,
    pool_timeout=30,
    pool_recycle=240,
    pool_pre_ping=True,
    connect_args={"connect_timeout": 5},
)
Node.js
mysql2
示例:
javascript
import mysql from 'mysql2/promise';

const pool = mysql.createPool({
  host: process.env.DB_HOST,
  user: process.env.DB_USER,
  password: process.env.DB_PASSWORD,
  database: process.env.DB_NAME,
  waitForConnections: true,
  connectionLimit: 10,
  queueLimit: 0,
  enableKeepAlive: true,
  keepAliveInitialDelay: 30000,
});

const [rows] = await pool.execute(
  'SELECT id, total FROM orders WHERE account_id = ? LIMIT 50',
  [accountId],
);
保持应用连接池的回收时间低于服务器的
wait_timeout
。如果服务器设置
wait_timeout = 300
,那么将
pool_recycle
设置为240秒左右是合理的;
pool_pre_ping
仍有助于从网络故障和故障转移事件中恢复。

Diagnostics

诊断工具

Useful first-pass commands:
sql
SHOW FULL PROCESSLIST;
SHOW ENGINE INNODB STATUS\G;
SHOW VARIABLES LIKE 'slow_query_log';
SHOW VARIABLES LIKE 'long_query_time';
Enable the slow log in a controlled environment:
sql
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1;
SET GLOBAL log_queries_not_using_indexes = 'ON';
Use
EXPLAIN ANALYZE
only when it is safe to execute the query. It runs the statement and can be expensive on production-sized data.
实用的初步排查命令:
sql
SHOW FULL PROCESSLIST;
SHOW ENGINE INNODB STATUS\G;
SHOW VARIABLES LIKE 'slow_query_log';
SHOW VARIABLES LIKE 'long_query_time';
在受控环境中启用慢查询日志:
sql
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1;
SET GLOBAL log_queries_not_using_indexes = 'ON';
仅在安全的情况下使用
EXPLAIN ANALYZE
执行查询。它会运行语句,在生产级数据上可能会消耗大量资源。

Replication

复制配置

Read replicas can lag. Do not route read-your-own-write paths, checkout flows, permission checks, or idempotency-key reads to a replica immediately after a write.
sql
-- MySQL legacy terminology, still common in existing fleets
SHOW SLAVE STATUS\G;

-- Newer terminology where supported
SHOW REPLICA STATUS\G;
Check the engine/version before standardizing on one command. Monitor replica SQL thread health, IO thread health, and lag, not just whether the TCP connection is alive.
只读副本可能存在延迟。写入操作完成后,不要立即将“读自己写的内容”路径、结账流程、权限检查或幂等键读取路由到副本。
sql
-- MySQL旧术语,在现有集群中仍常见
SHOW SLAVE STATUS\G;

-- 支持的新术语
SHOW REPLICA STATUS\G;
在标准化命令前检查引擎/版本。监控副本的SQL线程健康状态、IO线程健康状态和延迟情况,而不仅仅是TCP连接是否存活。

Security

安全配置

sql
CREATE USER 'app'@'%' IDENTIFIED BY 'use-a-secret-manager';
GRANT SELECT, INSERT, UPDATE, DELETE ON appdb.* TO 'app'@'%';

ALTER USER 'app'@'%' REQUIRE SSL;

SELECT user, host
FROM mysql.user
WHERE user = '';

DROP USER IF EXISTS ''@'localhost';
DROP USER IF EXISTS ''@'%';
Security review points:
  • Do not grant
    ALL PRIVILEGES
    or
    *.*
    to application users.
  • Require TLS for application users when traffic crosses hosts or networks.
  • Store credentials in the platform secret manager, not in examples, scripts, or repository files.
  • Separate migration/admin users from runtime application users.
  • Audit public network exposure and bind addresses before tuning performance.
sql
CREATE USER 'app'@'%' IDENTIFIED BY 'use-a-secret-manager';
GRANT SELECT, INSERT, UPDATE, DELETE ON appdb.* TO 'app'@'%';

ALTER USER 'app'@'%' REQUIRE SSL;

SELECT user, host
FROM mysql.user
WHERE user = '';

DROP USER IF EXISTS ''@'localhost';
DROP USER IF EXISTS ''@'%';
安全审核要点:
  • 不要为应用用户授予
    ALL PRIVILEGES
    *.*
    权限。
  • 当流量跨主机或网络传输时,要求应用用户使用TLS。
  • 将凭据存储在平台密钥管理器中,不要放在示例、脚本或仓库文件中。
  • 将迁移/管理员用户与运行时应用用户分离。
  • 在调优性能前,审核公网暴露情况和绑定地址。

Configuration

数据库配置

Example starting point for a dedicated database host:
ini
[mysqld]
innodb_buffer_pool_size = 4G
innodb_flush_log_at_trx_commit = 1
sync_binlog = 1

max_connections = 300
thread_cache_size = 50

wait_timeout = 300
interactive_timeout = 300
innodb_lock_wait_timeout = 10

slow_query_log = ON
long_query_time = 1
log_queries_not_using_indexes = ON

log_bin = mysql-bin
binlog_format = ROW
binlog_expire_logs_seconds = 604800
Treat configuration values as a prompt for review, not a universal preset. Size memory, connections, log retention, and durability settings from workload, hardware, backup policy, and recovery objectives.
专用数据库主机的示例初始配置:
ini
[mysqld]
innodb_buffer_pool_size = 4G
innodb_flush_log_at_trx_commit = 1
sync_binlog = 1

max_connections = 300
thread_cache_size = 50

wait_timeout = 300
interactive_timeout = 300
innodb_lock_wait_timeout = 10

slow_query_log = ON
long_query_time = 1
log_queries_not_using_indexes = ON

log_bin = mysql-bin
binlog_format = ROW
binlog_expire_logs_seconds = 604800
将配置值视为审核提示,而非通用预设。根据工作负载、硬件、备份策略和恢复目标调整内存、连接数、日志保留时间和持久性设置。

Anti-Patterns

反模式

Anti-PatternRiskBetter Pattern
SELECT *
in hot paths
Over-fetching and brittle clientsSelect explicit columns
Deep
OFFSET
pagination
Linear scans and slow pagesKeyset pagination
No index on foreign-key joinsSlow joins and lock-heavy deletesIndex FK columns intentionally
Long transactionsLock waits and large undo historyCommit small units of work
Direct DML against
mysql.user
Grant-table corruption riskUse
CREATE USER
,
ALTER USER
,
DROP USER
Application user with admin grantsHigh blast radiusLeast-privilege runtime user
Pool recycle above
wait_timeout
Stale pooled connectionsRecycle below timeout and pre-ping
Replica reads after writesStale user-facing statePin read-after-write flows to primary
反模式风险更优方案
高频路径中使用
SELECT *
过度获取数据且客户端易出错选择明确的列
深度
OFFSET
分页
线性扫描且页面加载缓慢键集分页
外键连接无索引连接缓慢且删除操作锁密集为外键列创建索引
长事务锁等待和大量回滚历史提交小单元的工作
直接对
mysql.user
执行DML
权限表损坏风险使用
CREATE USER
ALTER USER
DROP USER
应用用户拥有管理员权限影响范围大最小权限运行时用户
连接池回收时间高于
wait_timeout
连接池中的连接失效回收时间低于超时时间并启用预检测
写入后立即读取副本用户可见状态过时将写后读流程固定到主库

Output Expectations

输出预期

When this skill is used for review, return:
  1. Engine/version assumptions.
  2. Highest-risk correctness, lock, security, and migration issues.
  3. Exact SQL or code changes for the safe path.
  4. Validation plan:
    EXPLAIN
    , migration dry run, lock/deadlock check, and rollback criteria.
  5. Any MySQL/MariaDB syntax differences that affect the recommendation.
当使用本技能进行审核时,返回以下内容:
  1. 引擎/版本假设。
  2. 最高风险的正确性、锁、安全和迁移问题。
  3. 安全方案对应的精确SQL或代码修改。
  4. 验证计划:
    EXPLAIN
    分析、迁移预演、锁/死锁检查及回滚标准。
  5. 影响推荐方案的MySQL/MariaDB语法差异。

Related

相关内容

  • Skill:
    postgres-patterns
    - PostgreSQL-specific schema and query patterns
  • Skill:
    database-migrations
    - migration planning and rollout safety
  • Skill:
    backend-patterns
    - API and service-layer patterns
  • Skill:
    security-review
    - secret handling, auth, and least privilege
  • Agent:
    database-reviewer
    - broader database review workflow
  • Skill:
    postgres-patterns
    - PostgreSQL专属架构与查询模式
  • Skill:
    database-migrations
    - 迁移规划与发布安全
  • Skill:
    backend-patterns
    - API与服务层模式
  • Skill:
    security-review
    - 密钥处理、认证与最小权限
  • Agent:
    database-reviewer
    - 更全面的数据库审核工作流