Communitygithub.com

LDKTC/Agent-P-FullStack

Agent für KI Claude, Codex, Copilot und andere KIs

Was ist Agent-P-FullStack?

Diese Fähigkeit bietet spezifisches Datenbankwissen für MySQL und MariaDB. Sie stellt sicher, dass korrekte Datentypen und Zeichensätze (utf8mb4, DECIMAL für Geld, richtig dimensionierte VARCHAR/INT, ENUM-Kompromisse) verwendet werden. Der Agent unterstützt bei der InnoDB- und MyISAM-Indexauswahl, dem Query-Tuning mithilfe von EXPLAIN (korrekte Indexreihenfolge, abdeckende Indizes, sargable Prädikate, Keyset-Pagination) und behandelt Transaktionsisolationsstufen und Sperrmechanismen (REPEATABLE READ, Gap Locks, Deadlocks). Die Fähigkeit ist für Claude, Codex und andere KI-Assistenten geeignet und wird aktiv, wenn ein Projekt mysql2, mysql, mysql://-Verbindungszeichenfolgen oder entsprechende ORM-Dialekte (Prisma, Sequelize, TypeORM) verwendet. Sie ist keine allgemeine Datenbankschema- oder Backend-Fähigkeit, sondern das spezialisierte Wissen, das diese Fähigkeiten nutzen, wenn die Engine tatsächlich MySQL oder MariaDB ist.

Funktioniert mit✓Claude Code✓Codex CLI✓Cursor
npx skills add LDKTC/Agent-P-FullStack

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

MySQL

database-schema-dev und backend-dev besitzen eine MySQL-spezifische Expertise-Ebene: diese Agenten sind engine-agnostisch und passen sich dem jeweiligen Migrationstool/ORM an, das ein Projekt bereits verwendet — dieses Skill stellt das eigentliche MySQL-Wissen bereit, auf das sie zurückgreifen, wenn die Engine MySQL oder der eng kompatible Fork MariaDB ist. Wo MariaDB sich anders verhält, wird dies explizit erwähnt — gehe nicht von vollständiger Parität bei fortgeschrittenen Funktionen aus.

Schritt 1 — Überprüfen, ob die Engine tatsächlich MySQL/MariaDB ist

Überprüfe package.json auf mysql2/mysql, einen ORM-Dialekt/Provider (provider = "mysql" in Prisma, dialect: 'mysql' in Sequelize, type: 'mysql'/'mariadb' in TypeORM), einen docker-compose.yml-Dienst, der ein mysql/mariadb-Image ausführt, oder einen mysql://-Verbindungsstring. Falls nichts davon zutrifft, stoppe — verwende stattdessen die engine-agnostischen Standardeinstellungen von database-schema-dev/backend-dev oder das passende engine-spezifische Skill.

Schritt 2 — Zeichensatz, Kollation, Storage Engine

  • Standardzeichensatz ist utf8mb4, nicht utf8 — MySQLs utf8 ist ein auf 3 Byte begrenztes Alias, das die meisten Emoji/Astralzeichen nicht speichern kann — mit einer expliziten Kollation (utf8mb4_0900_ai_ci auf MySQL 8+; MariaDB hat keine 0900-Kollationen, verwende utf8mb4_unicode_ci für alles, das auf beide abzielt).
  • InnoDB außer es gibt einen spezifischen Grund für MyISAM (keine Transaktionen, keine Zeilensperren, keine FKs) — es ist seit MySQL 5.5/MariaDB 10.x die Standardeinstellung, daher bestätigt dies normalerweise nur, dass nichts es überschreibt.
  • _ci-Kollation bedeutet, dass '[email protected]' mit '[email protected]' übereinstimmt — verwende _bin/_cs (oder eine gehashte Spalte) für alles, das case-sensitiv verglichen werden muss (Tokens, Geheimnisse).

Schritt 3 — Korrekte Datentypen

  • Geld/exakte Dezimalstellen: DECIMAL(p,s), niemals FLOAT/DOUBLE — Binärfließkomma kann die meisten Basis-10-Brüche nicht exakt darstellen.
  • Ganzzahlen richtig dimensionieren (TINYINT/SMALLINT/INT/BIGINT) nach tatsächlichem Bereich, nicht aus Gewohnheit überall BIGINT — kleinere Typen bedeuten kleinere Indizes. UNSIGNED ist freie Reserve für eine ID-Spalte, die nie negativ ist.
  • DATETIME für einen Wanduhrzeitwert ohne Zeitzonenkonvertierung; TIMESTAMP (UTC-normalisiert, automatische Konvertierung pro Sitzungszeitzone, 2038-Bereichsbegrenzung) nur für einen tatsächlichen Zeitpunkt — verwende es nicht standardmäßig.
  • VARCHAR(n) auf die tatsächliche Einschränkung dimensioniert, nicht reflexartig VARCHAR(255); TEXT/BLOB für wirklich unbegrenzte Inhalte — keines akzeptiert einen Standardwert oder einen vollständigen (nicht-präfix) Index.
  • ENUM nur für eine feste, selten ändernde Menge — Werte sortieren nach Definitionsreihenfolge, nicht alphabetisch (eine Überraschung bei ORDER BY), und das Anhängen eines Werts ist auf MySQL 8 nur Metadaten, kann aber auf MariaDB/älterem MySQL die Tabelle umschreiben. Eine Nachschlagetabelle skaliert besser, sobald die Menge wächst oder Metadaten benötigt.
  • Natives JSON (MySQL 5.7.8+/MariaDB 10.2+ — MariaDBs JSON ist eigentlich LONGTEXT plus ein CHECK, kein Binärtyp, daher gelten keine von MySQLs Binärspeicher-/Teilaktualisierungsvorteilen) nur für wirklich schemalose Daten — alles, das regelmäßig gefiltert oder mit Joins verknüpft wird, gehört in eine echte Spalte.

Schritt 4 — Index-Design

  • Zusammengesetzte Indizes: Spalte(n) mit Gleichheitsfilter zuerst, die Bereichs-/Sortierspalte zuletzt — (status, created_at) bedient WHERE status = ? ORDER BY created_at; die umgekehrte Reihenfolge nicht.
  • Links-Präfix-Regel: Ein Index auf (a, b, c) bedient auch Lookups auf (a) und (a, b) — füge keinen redundanten (a)-Index daneben hinzu.
  • Ein abdeckender Index (jede ausgewählte Spalte enthalten) erlaubt MySQL, die Antwort nur aus dem Index zu beziehen (Using index in EXPLAIN) — lohnenswert für eine heiße, schmale Abfrage, nicht standardmäßig für jede Abfrage.
  • Präfix-Index (col(20)) für lange VARCHAR/TEXT — überprüfe COUNT(DISTINCT LEFT(col, n)) gegen COUNT(DISTINCT col), um n zu dimensionieren.
  • Tiefe Paginierung: LIMIT 20 OFFSET 100000 scannt und verwirft trotzdem 100.000 Zeilen pro Seite. Tasten-Paginierung (WHERE (created_at, id) < (:last_created, :last_id) ORDER BY created_at DESC, id DESC LIMIT 20) verwendet denselben zusammengesetzten Index wieder und springt direkt zum Cursor — verwende dies für unendliches Scrollen oder tiefe API-Paginierung anstelle von OFFSET.
  • Jeder Index kostet Schreibzeit und Speicherplatz — füge Indizes für reale Abfragemuster hinzu (database-schema-dev Schritt 1), nicht spekulativ pro Spalte.

Schritt 5 — EXPLAIN-gesteuerte Abfrageoptimierung

  • Führe EXPLAIN (oder EXPLAIN ANALYZE, MySQL 8.0.18+/MariaDB 10.4+) aus, bevor du einer Abfrage vertraust, dass sie schnell ist — beurteile nicht allein aus der Abfrageform.
  • type: ALL ist ein vollständiger Tabellenscan; ref/range/const bedeuten, dass ein Index tatsächlich verwendet wird — eine optimierungswürdige Abfrage sollte bei trivialer Tabellengröße kein ALL zeigen.
  • Extra: Using filesort/Using temporary bedeutet, dass MySQL außerhalb eines Index sortiert/materialisiert hat — normalerweise behoben durch einen Index, der dem ORDER BY/GROUP BY entspricht.
  • Eine umschließende Funktion oder implizite Typumwandlung auf einer indizierten Spalte (WHERE YEAR(created_at) = ..., Vergleich eines String-Spalte mit einer Zahl) macht den Index unwirksam — schreibe stattdessen als nackten Spaltenbereich um (created_at >= '2024-01-01' AND created_at < '2025-01-01').
  • SELECT * auf einer breiten Tabelle verhindert abdeckende Indizes und zieht TEXT/BLOB-Spalten, die niemand angefordert hat — wähle nur aus, was verwendet wird.

Schritt 6 — Transaktionen und Sperren

  • InnoDB sperrt Zeilen, nicht Tabellen, aber die Standardisolierung REPEATABLE READ nimmt auch Lückensperren bei Bereichsscans in UPDATE/DELETE/sperrendem SELECT — eine Bereichsbedingung kann mehr als die übereinstimmenden Zeilen blockieren. READ COMMITTED vermeidet Lückensperren, wenn wiederholbare Lesevorgänge nicht benötigt werden.
  • Dieser Snapshot deckt nur ein einfaches SELECT ab — ein sperrender Lesevorgang in derselben Transaktion (SELECT ... FOR UPDATE, UPDATE, DELETE) liest stattdessen die neuesten committeten Daten, sodass er eine Zeile sehen kann, die der Snapshot nie gezeigt hat. Gehe nicht davon aus, dass Snapshot-Isolation auch einen sperrenden Lesevorgang schützt.
  • Halte Transaktionen kurz — eine offene Transaktion hält ihre Sperren und blockiert unter REPEATABLE READ auch InnoDBs Bereinigung alter Zeilenversionen.
  • SELECT ... FOR UPDATE zum Sperren von Zeilen, die in einer Transaktion gelesen und dann geschrieben werden (Kontostandsprüfung vor Abbuchung); sperre in einer konsistenten Zeilenreihenfolge im gesamten Code, um Deadlocks zu vermeiden.
  • Ein Deadlock (ERROR 1213, SQLSTATE 40001) ist bei realer Konkurrenz zu erwarten — InnoDB rollt automatisch eine Seite zurück; fange diesen Code ab und wiederhole ihn, anstatt ihn mit einer längeren Transaktion zu "beheben". SHOW ENGINE INNODB STATUS → LATEST DETECTED DEADLOCK zeigt, was jede Seite gehalten/erwartet hat.
  • Autocommit ist standardmäßig pro Verbindung aktiv — atomare Mehrfachanweisungen benötigen eine explizite Transaktion (oder den ORM-Wrapper), nicht nur die Nachbarschaft im Code.

Schritt 7 — MySQL-spezifische Fallstricke und MariaDB-Abweichungen

  • sql_mode sollte STRICT_TRANS_TABLES enthalten (Standard seit MySQL 5.7/MariaDB 10.2) — ohne sie werden außerbereichs-/falsche Werte stillschweigend abgeschnitten statt einen Fehler zu verursachen; bestätige, dass es nicht gelockert wurde.
  • AUTO_INCREMENT-Werte sind nicht lückenlos (ein Rollback verbraucht trotzdem einen) — verlasse dich niemals auf fortlaufende IDs.
  • Die Sitzungs-time_zone beeinflusst die TIMESTAMP-Konvertierung, aber nicht DATETIME — ein Pool mit gemischten Zeitzonen pro Verbindung ist ein echter "falsche Stunde"-Fehler; setze sie explizit fest.
  • MariaDB hat eigene Erweiterungen ohne MySQL-Äquivalent (CREATE SEQUENCE, RETURNING bei Schreibvorgängen) — verwende sie nicht, wenn auch MySQL ein Ziel ist; Fensterfunktionen/CTEs benötigen MySQL 8.0+/MariaDB 10.2+, überprüfe zuerst die festgelegte Version.
  • MariaDBs Optimierer und EXPLAIN-Ausgabe sind nicht dieselbe Engine wie die von MySQL — führe EXPLAIN auf der tatsächlich verwendeten Engine erneut aus, anstatt einem Plan zu vertrauen, der auf der anderen abgestimmt wurde.

Schritt 8 — Selbstkontrolle vor Abschlussmeldung

Bestätige, dass jede neue/geänderte Spalte einen beabsichtigten Typ hat und der Zeichensatz auf utf8mb4 zurückfällt. Bestätige, dass jeder neue Index durch ein reales Abfragemuster mit EXPLAIN-Ausgabe untermauert wird, die seine Verwendung zeigt, und jeder tiefe/unbegrenzte Listenendpunkt Tasten-Paginierung anstelle von OFFSET verwendet. Bestätige, dass Mehrfachanweisungen-Schreibvorgänge in einer expliziten Transaktion eingeschlossen sind und das Isolationsverhalten eines sperrenden Lesevorgangs bewusst und nicht angenommen ist. Wenn die Compose-Datei/CI MariaDB festlegt, bestätige, dass nichts hinzugefügt wird, das eine reine MySQL-8-Funktion voraussetzt.

Was nicht zu tun ist

  • Verwende nicht den utf8-Zeichensatz oder FLOAT/DOUBLE für Geld — utf8mb4 und DECIMAL sind die korrekten Standardeinstellungen.
  • Füge keinen Index ohne dahinterstehendes Abfragemuster hinzu, oder bezeichne eine Abfrage nicht als "schnell", ohne EXPLAIN zu überprüfen.
  • Verwende nicht die OFFSET-Paginierung für eine Liste, die tief paginieren oder unbegrenzt laufen kann — verwende Tasten-Paginierung.
  • Lasse eine Transaktion nicht länger offen als die Arbeit, die sie schützt, insbesondere unter den Lückensperren von REPEATABLE READ.
  • Verlasse dich nicht auf AUTO_INCREMENT-Lückenlosigkeit oder implizite Typumwandlung für die Korrektheit.
  • Gehe nicht davon aus, dass ein MariaDB-Ziel reine MySQL-8-Funktionen besitzt (natives JSON, utf8mb4_0900_ai_ci), ohne die festgelegte Version zu überprüfen.
  • Schreibe den engine-agnostischen Migrations-/Zugriffsschicht-Code nicht selbst — das ist Aufgabe von database-schema-dev/backend-dev; dieses Skill ist das MySQL-Wissen, das sie darauf anwenden.

Verwandte Skills