Communitygithub.com

LDKTC/Agent-P-FullStack

Agente para IA Claude, Codex, Copilot y otras IAs

¿Qué es Agent-P-FullStack?

Este skill proporciona una experiencia profunda y específica en bases de datos MySQL/MariaDB para agentes de IA como Claude, Codex, Copilot y otros asistentes de desarrollo. Se enfoca en la correcta definición de tipos de datos, charset y collation (como utf8mb4, DECIMAL para dinero, VARCHAR/INT dimensionados correctamente, y las compensaciones de ENUM), el diseño de índices y la optimización de consultas mediante EXPLAIN, incluyendo orden de índices compuestos, índices de cobertura, predicados sargables y paginación con keyset. También cubre el aislamiento de transacciones y bloqueos (REPEATABLE READ, gap locks, deadlocks) y las trampas específicas de MySQL. Es útil cuando un proyecto tiene mysql2 o mysql en package.json, el dialecto ORM está configurado para mysql (Prisma con provider = "mysql", Sequelize con dialect: 'mysql', TypeORM con type: 'mysql'/'mariadb'), un servicio docker-compose ejecuta una imagen mysql/mariadb, o hay una cadena de conexión mysql://. No reemplaza el flujo de trabajo de migración independiente del motor de base-schema-dev ni el código de capa de acceso de backend-dev; es el conocimiento de MySQL que ambos utilizan cuando el motor es MySQL/MariaDB.

Compatible con✓Claude Code✓Codex CLI✓Cursor
npx skills add LDKTC/Agent-P-FullStack

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación


name: mysql description: Experiencia profunda y específica en bases de datos MySQL/MariaDB: tipos de datos correctos y charset/collation (utf8mb4, DECIMAL para dinero, VARCHAR/INT dimensionados correctamente, compensaciones de ENUM), InnoDB vs MyISAM, diseño de índices y optimización de consultas mediante EXPLAIN (orden de índices compuestos, índices de cobertura, predicados sargables, paginación con keyset), aislamiento de transacciones y bloqueos (REPEATABLE READ, gap locks, deadlocks), y trampas de corrección específicas de MySQL. Úsalo cuando package.json liste mysql2 o mysql, el dialecto/proveedor de un ORM esté configurado para mysql (Prisma provider = "mysql", Sequelize dialect: 'mysql', TypeORM type: 'mysql'/'mariadb'), un servicio docker-compose ejecute una imagen mysql/mariadb, o haya una cadena de conexión mysql://, incluso cuando se te pida directamente (en tailandés o inglés) escribir o revisar un schema/query de MySQL que sea correcto y eficiente. No reemplaza el flujo de trabajo de migración independiente del motor de database-schema-dev ni el código de capa de acceso de backend-dev; es la experiencia de MySQL que ambos utilizan cuando el motor es MySQL/MariaDB.

MySQL

Capa de experiencia específica de MySQL de database-schema-dev y backend-dev: esos agentes son independientes del motor y coinciden con la herramienta de migración/ORM que ya tiene un proyecto — este skill es el conocimiento real de MySQL que ellos utilizan cuando el motor resulta ser MySQL, o su fork compatible MariaDB. Cuando MariaDB se comporta de manera diferente, se señala — no asumas paridad completa en características avanzadas.

Paso 1 — Confirmar que el motor es realmente MySQL/MariaDB

Revisa package.json para mysql2/mysql, un dialecto/proveedor de ORM (provider = "mysql" en Prisma, dialect: 'mysql' en Sequelize, type: 'mysql'/'mariadb' en TypeORM), un servicio en docker-compose.yml que ejecute una imagen mysql/mariadb, o una cadena de conexión mysql://. Si nada de esto se cumple, detente — usa los valores predeterminados independientes del motor de database-schema-dev/backend-dev, o el skill específico del motor correspondiente.

Paso 2 — Charset, collation, motor de almacenamiento

  • El charset predeterminado es utf8mb4, no utf8 — el utf8 de MySQL es un alias de máximo 3 bytes que no puede contener la mayoría de emojis/caracteres astrales — con una collation explícita (utf8mb4_0900_ai_ci en MySQL 8+; MariaDB no tiene collations 0900, usa utf8mb4_unicode_ci para cualquier cosa dirigida a ambos).
  • InnoDB a menos que haya una razón específica para MyISAM (sin transacciones, sin bloqueos de filas, sin claves foráneas) — es el predeterminado desde MySQL 5.5/MariaDB 10.x, así que esto generalmente es solo confirmar que nada lo sobrescribe.
  • La collation _ci significa que '[email protected]' coincide con '[email protected]' — usa _bin/_cs (o una columna con hash) para cualquier cosa que deba compararse distinguiendo mayúsculas/minúsculas (tokens, secretos).

Paso 3 — Tipos de datos correctos

  • Dinero/decimales exactos: DECIMAL(p,s), nunca FLOAT/DOUBLE — el flotante binario no puede representar la mayoría de fracciones en base 10 exactamente.
  • Enteros dimensionados correctamente (TINYINT/SMALLINT/INT/BIGINT) según el rango real, no BIGINT en todos lados por costumbre — tipos más pequeños significan índices más pequeños. UNSIGNED es espacio libre adicional en una columna de id, que nunca es negativa.
  • DATETIME para un valor de reloj sin conversión de zona horaria prevista; TIMESTAMP (normalizado a UTC, se convierte automáticamente según la zona horaria de la sesión, límite de rango 2038) solo para un instante real en el tiempo — no lo uses por defecto.
  • VARCHAR(n) dimensionado según la restricción real, no VARCHAR(255) por reflejo; TEXT/BLOB para contenido genuinamente ilimitado — ninguno acepta un valor predeterminado ni un índice completo (no de prefijo).
  • ENUM solo para un conjunto fijo que rara vez cambia — los valores se ordenan según el orden de definición, no alfabéticamente (una sorpresa en ORDER BY), y agregar un valor es solo metadatos en MySQL 8 pero puede reescribir la tabla en MariaDB/MySQL más antiguo. Una tabla de referencia escala mejor cuando el conjunto crece o necesita metadatos.
  • JSON nativo (MySQL 5.7.8+/MariaDB 10.2+ — el JSON de MariaDB es en realidad LONGTEXT más un CHECK, no un tipo binario, por lo que ninguna de las ventajas de almacenamiento binario/actualización parcial de MySQL se aplica) solo para datos genuinamente sin esquema — cualquier cosa que se filtre o se una regularmente debe estar en una columna real.

Paso 4 — Diseño de índices

  • Índices compuestos: columna(s) filtradas por igualdad primero, la columna de rango/orden al final — (status, created_at) sirve para WHERE status = ? ORDER BY created_at; el orden inverso no.
  • Regla del prefijo más a la izquierda: un índice en (a, b, c) también sirve para búsquedas en (a) y (a, b) — no agregues un índice redundante (a) junto a él.
  • Un índice de cobertura (cada columna seleccionada incluida) permite que MySQL responda solo con el índice (Using index en EXPLAIN) — vale la pena para una consulta caliente y estrecha, no por defecto en cada consulta.
  • Índice de prefijo (col(20)) para VARCHAR/TEXT largos — verifica COUNT(DISTINCT LEFT(col, n)) contra COUNT(DISTINCT col) para dimensionar n.
  • Paginación profunda: LIMIT 20 OFFSET 100000 todavía escanea y descarta 100,000 filas cada página. La paginación con keyset (WHERE (created_at, id) < (:last_created, :last_id) ORDER BY created_at DESC, id DESC LIMIT 20) reutiliza el mismo índice compuesto y busca directamente el cursor — úsala para desplazamiento infinito o paginación profunda de API en lugar de OFFSET.
  • Cada índice cuesta tiempo de escritura y espacio en disco — agrega índices para patrones de consulta reales (Paso 1 de database-schema-dev), no especulativamente por columna.

Paso 5 — Optimización de consultas mediante EXPLAIN

  • Ejecuta EXPLAIN (o EXPLAIN ANALYZE, MySQL 8.0.18+/MariaDB 10.4+) antes de confiar en que una consulta es rápida — no juzgues solo por la forma de la consulta.
  • type: ALL es un escaneo completo de tabla; ref/range/const significa que realmente se usa un índice — una consulta que vale la pena optimizar no debería mostrar ALL más allá de un tamaño de tabla trivial.
  • Extra: Using filesort/Using temporary significa que MySQL ordenó/materializó fuera de un índice — generalmente se soluciona con un índice que coincida con el ORDER BY/GROUP BY.
  • Una función envolvente o conversión implícita en una columna indexada (WHERE YEAR(created_at) = ..., comparar una columna de texto con un número) anula el índice — reescribe como un rango de columna simple en su lugar (created_at >= '2024-01-01' AND created_at < '2025-01-01').
  • SELECT * en una tabla ancha anula los índices de cobertura y trae columnas TEXT/BLOB que nadie pidió — selecciona solo lo que se usa.

Paso 6 — Transacciones y bloqueos

  • InnoDB bloquea filas, no tablas, pero la isolación predeterminada REPEATABLE READ también toma gap locks en escaneos de rango en UPDATE/DELETE/ bloqueos SELECT — una condición de rango puede bloquear más que las filas coincidentes. READ COMMITTED evita gap locks si no se necesitan lecturas repetibles.
  • Esa instantánea solo cubre un SELECT simple — una lectura con bloqueo en la misma transacción (SELECT ... FOR UPDATE, UPDATE, DELETE) lee los últimos datos confirmados en su lugar, por lo que puede ver una fila que la instantánea nunca mostró. No asumas que el aislamiento de instantánea también protege una lectura con bloqueo.
  • Mantén las transacciones cortas — una transacción abierta mantiene sus bloqueos y, bajo REPEATABLE READ, también bloquea la purga de versiones antiguas de filas de InnoDB.
  • SELECT ... FOR UPDATE para bloquear filas leídas y luego escritas en una transacción (verificación de saldo antes del débito); adquiere bloqueos en un orden consistente de filas en todo el código base para evitar deadlocks.
  • Un deadlock (ERROR 1213, SQLSTATE 40001) es esperado bajo contención real — InnoDB retrocede automáticamente un lado; captura ese código y reintenta en lugar de "arreglarlo" con una transacción más larga. SHOW ENGINE INNODB STATUS → LATEST DETECTED DEADLOCK muestra lo que cada lado mantenía/esperaba.
  • Autocommit está activado por conexión de forma predeterminada — la atomicidad de múltiples declaraciones necesita una transacción explícita (o el envoltorio del ORM), no solo adyacencia en el código.

Paso 7 — Trampas específicas de MySQL y divergencia con MariaDB

  • sql_mode debe incluir STRICT_TRANS_TABLES (predeterminado desde MySQL 5.7/MariaDB 10.2) — sin él, los valores fuera de rango/tipo incorrecto se truncan silenciosamente en lugar de dar error; confirma que no se ha relajado.
  • Los valores de AUTO_INCREMENT no están libres de huecos (un rollback aún consume uno) — nunca confíes en que los ids sean contiguos.
  • time_zone de la sesión afecta la conversión de TIMESTAMP pero no de DATETIME — un pool con zonas horarias mezcladas por conexión es un error real de "hora incorrecta"; fíjala explícitamente.
  • MariaDB tiene sus propias extensiones sin equivalente en MySQL (CREATE SEQUENCE, RETURNING en escrituras) — no las uses si MySQL también es un objetivo; las funciones de ventana/CTEs necesitan MySQL 8.0+/MariaDB 10.2+, verifica primero la versión fijada.
  • El optimizador y la salida EXPLAIN de MariaDB no son el mismo motor que los de MySQL — vuelve a ejecutar EXPLAIN en el motor real en uso en lugar de confiar en un plan ajustado en el otro.

Paso 8 — Autoverificación antes de informar como completado

Confirma que cada columna nueva/modificada tiene un tipo intencional y que el charset vuelve a utf8mb4. Confirma que cualquier índice nuevo está respaldado por un patrón de consulta real con salida EXPLAIN que muestre que se usa, y que cualquier endpoint de lista profunda/ilimitada usa keyset en lugar de OFFSET. Confirma que las escrituras de múltiples declaraciones están envueltas en una transacción explícita y que el comportamiento de aislamiento de una lectura con bloqueo es deliberado, no asumido. Si el archivo compose/CI fija MariaDB, confirma que nada agregado asume una característica solo de MySQL 8.

Qué no hacer

  • No uses charset utf8 ni FLOAT/DOUBLE para dinero — utf8mb4 y DECIMAL son los valores predeterminados correctos.
  • No agregues un índice sin un patrón de consulta detrás, ni llames a una consulta "rápida" sin verificar EXPLAIN.
  • No uses paginación con OFFSET en una lista que pueda paginarse profundamente o ejecutarse sin límite — usa keyset.
  • No dejes una transacción abierta más tiempo del necesario para el trabajo que protege, especialmente bajo bloqueos de rango de REPEATABLE READ.
  • No confíes en la contigüidad de AUTO_INCREMENT ni en la coerción de tipos implícita para la corrección.
  • No asumas que un objetivo MariaDB tiene características solo de MySQL 8 (JSON nativo, utf8mb4_0900_ai_ci) sin verificar la versión fijada.
  • No escribas el código de migración/capa de acceso independiente del motor tú mismo — eso es trabajo de database-schema-dev/backend-dev; este skill es el conocimiento de MySQL que ellos aplican sobre él.

Skills relacionados