--- name: database-connect description: 连接 MySQL 数据库并完成安全的查询、数据写入、更新、删除、表结构探查、事务处理和数据库诊断。用户要求 Codex 连接 MySQL、查看或修改数据库数据、分析表结构、执行 SQL、排查数据库连接或查询问题时使用。 --- # MySQL 数据库连接 ## 目标 按照“发现配置、验证连接、了解结构、最小化操作、核对结果”的流程连接项目 MySQL,并完成用户授权范围内的数据库操作。优先复用项目已有的驱动、配置和命令,不擅自安装依赖或改变数据库环境。 ## 安全边界 - 将数据库凭据视为机密。读取 `.env`、`.env.example`配置,只提取连接所需值,绝不在回复、日志、补丁或命令输出中打印密码、完整连接串或令牌。 - 禁止把密码直接写在命令行参数、SQL、源码或新建文件中。优先使用项目现有的安全配置、环境变量、凭据助手或 MySQL 客户端配置文件。 - 默认使用只读方式探查:`SELECT`、`SHOW`、`DESCRIBE`、`EXPLAIN` 和 `information_schema` 查询可以先执行;不要把探查语句改成写入语句。 - 执行 `INSERT`、`UPDATE`、`DELETE`、`REPLACE`、`TRUNCATE`、`DROP`、`ALTER`、`CREATE`、批量导入、权限变更或存储过程时,先说明目标、范围、预计影响和事务策略。 - 对删除、清空、改表、批量更新等不可逆或高影响操作,先展示将执行的精确 SQL(敏感值脱敏)并请求用户确认;用户已在当前请求中明确给出精确语句和范围时,可视为已确认,但仍先做影响评估。 - 不执行未限定范围的 `UPDATE` 或 `DELETE`,不执行生产库上的 `DROP DATABASE`、`TRUNCATE` 或全表更新,除非用户明确确认精确目标和范围。 - 不为了“修复连接”而修改防火墙、开放公网端口、重置密码、创建高权限账号或暴露数据库服务;这些需要单独授权。 ## 标准工作流 ### 1. 发现连接方式 按以下顺序检查,找到一种可用方式后停止扩散搜索: 1. 查看项目的 `README`、数据库迁移配置和应用配置,识别 host、port、database、user 的来源。密码只在本地使用,不回显。 2. 检查当前环境变量,如 `MYSQL_HOST`、`MYSQL_PORT`、`MYSQL_DATABASE`、`MYSQL_USER`、`MYSQL_PASSWORD` 或项目自定义变量。优先确认变量是否存在,不输出其值。 3. 检查项目依赖和现有数据库访问代码。Java 项目优先复用 JDBC/迁移工具,Node.js 项目优先复用现有 MySQL 驱动,Python 项目优先复用已安装的驱动。 4. 检查 `mysql` 客户端是否可用及版本。客户端不可用时,先报告缺少的工具,并优先使用项目已有驱动;不要未经授权下载或安装软件。 连接参数不完整时,只询问缺少的参数。接受用户提供的 `host`、`port`、数据库名和用户名,但不要要求用户把密码粘贴到聊天中;建议通过环境变量或本地凭据配置提供密码。 ### 2. 验证连接 建立连接后先执行轻量验证,不直接操作业务数据: ```sql SELECT DATABASE() AS current_database, USER() AS connected_user, VERSION() AS mysql_version; ``` 验证以下事项: - 实际连接的主机、端口、数据库和账号是否符合目标;不要仅凭配置文件推断已经连对。 - 当前账号是否有完成任务所需的最小权限。 - 是否存在只读副本、开发库和生产库混淆的风险。发现环境不明确时暂停写操作并询问。 - 字符集和时区是否可能影响结果,必要时读取 `SELECT @@character_set_connection, @@time_zone`。 连接失败时按错误码和现象诊断:先区分 DNS/网络不可达、端口拒绝、认证失败、数据库不存在、权限不足、TLS 配置错误和客户端/驱动缺失;不要用反复重试掩盖根因。记录可公开的错误类型和下一步,不回显凭据。 ### 3. 探查结构和数据 在写操作前确认表、列、键和约束。按需执行: ```sql SHOW TABLES; SHOW CREATE TABLE `table_name`; SELECT TABLE_NAME, TABLE_ROWS FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE(); SELECT COLUMN_NAME, COLUMN_TYPE, IS_NULLABLE, COLUMN_KEY, COLUMN_DEFAULT FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'table_name' ORDER BY ORDINAL_POSITION; ``` - 从实际结构确认表名、列名、主键、唯一键、外键、默认值和软删除字段;不要根据名称猜测 schema。 - 样本数据只取必要列并加 `LIMIT`,避免 `SELECT *` 扫描大表。需要总量时优先 `COUNT(*)`,需要性能判断时使用 `EXPLAIN`。 - 识别敏感列(密码、身份证、手机号、令牌、支付信息等),查询结果脱敏或只返回聚合结果。 - 表名和列名不能用普通 SQL 参数绑定。对动态标识符只允许来自已探查且白名单校验通过的名称,并使用 MySQL 反引号转义。 ### 4. 执行查询或修改 - 复杂任务拆成可验证的小步骤,每一步说明目的和结果。 - 所有用户输入值使用驱动的参数绑定(如 `?`、`:name`),不要拼接值生成 SQL。只在无法参数化的标识符上使用白名单。 - 先用等价的 `SELECT` 验证筛选条件,再执行 `UPDATE`/`DELETE`。修改前记录主键集合或预估影响行数。 - 查询大表时必须有合理的过滤条件、索引或分页;避免在未了解数据量时执行全表排序、笛卡尔积和无条件扫描。 - 对写操作优先使用事务:开始事务,执行变更,检查受影响行数和关键结果,确认无误后提交;异常时回滚。不要在无法确认事务状态时重复提交。 - 批量操作分批执行并记录每批结果。遇到锁等待、死锁、超时或影响行数异常时停止后续批次,回滚当前事务并报告。 - DDL 可能隐式提交,执行前明确告知这一点;涉及表结构变更时先备份/导出或确认已有恢复方案。 通用写操作模板: ```sql START TRANSACTION; -- 先用同一 WHERE 条件确认目标和数量 SELECT `primary_key` FROM `table_name` WHERE ... LIMIT 1000; -- 使用参数绑定执行精确变更 UPDATE `table_name` SET `column_name` = ? WHERE `primary_key` IN (...); -- 核对受影响行数和结果后再提交 COMMIT; -- 任一步失败时执行 ROLLBACK; ``` ### 5. 核对并汇报 操作完成后重新查询关键结果,核对实际影响行数、唯一性、关联完整性和业务约束。向用户报告:使用的连接环境(不含密码)、执行的操作、结果摘要、是否提交事务、异常或未验证事项;不要粘贴大批量原始数据。 ## 工具选择 - 已有应用或迁移工具能安全提供连接时,优先使用它,避免引入第二套连接配置。 - 使用 `mysql` CLI 时,把密码交给安全凭据机制或交互式输入,不使用 `--password=明文`。长 SQL 用受控的临时文件或标准输入传递,并在使用后清理临时文件。 - 使用脚本时复用项目锁定的依赖和配置,设置连接超时、查询超时(若驱动支持)和结果上限;脚本结束时关闭连接。 - 不把结果写入仓库,不提交临时凭据,不把生产数据导出到工作区。确需导出时先确认文件位置、字段范围和保留期限。 ## 常见问题处理 - `Access denied`: 核对实际用户名、认证插件、目标主机和账号来源;不要通过授予 `ALL PRIVILEGES` 规避权限问题。 - `Unknown database`: 确认数据库名和当前连接环境,先列出允许访问的数据库或检查 Compose/迁移配置。 - `Table doesn't exist`: 核对大小写、schema、迁移状态和连接库,不要直接创建同名表覆盖问题。 - `Lock wait timeout` 或死锁: 回滚当前事务,识别长事务和索引缺失,缩小批次;不要盲目重试写入。 - 字符集乱码: 检查连接、表和列的字符集与排序规则,先读取并评估已有数据,再决定是否迁移。 - 结果数量异常: 重新检查 JOIN 条件、NULL 语义、时区、软删除条件和分页边界,并保留可复现的只读查询。 ## 完成标准 只有在连接目标已验证、操作范围已确认、SQL 使用参数绑定、写操作结果已核对且事务状态明确时,才报告数据库任务完成。任何凭据、环境或影响范围无法确认时,保持只读并明确阻塞原因。