MySQL este în continuare un standard excelent
- mysql
- prisma
- databases
- infrastructure
Fiecare proiect nou declanșează același dezbatere. Postgres sau MySQL? SQLite? Neon? Iată de ce continui să aleg MySQL 8.4 cu Prisma 7 și nu regret deloc.
Există un anumit ritual al dezvoltatorului: deschizi un repository gol, ai nevoie de o bază de date și deodată trei persoane de pe internet îți spun că alegerea ta este greșită. MySQL este legacy. SQLite nu scalează. Postgres este singura opțiune serioasă. Neon este viitorul. Am urmărit acest ciclu ani de zile. La NearYou am ales MySQL 8.4 cu Prisma 7 și adapterul mariadb. Funcționează perfect. Iată raționamentul complet.
Plictiseala este o funcționalitate
MySQL rulează sarcini de lucru în producție din 1995. Asta înseamnă trei decenii de cazuri limită, moduri de eșec și corecturi integrate în baza de cod. Când ceva se strică la 2 noaptea, vei găsi un thread pe Stack Overflow din 2014 care deja a rezolvat problema. Asta nu e un lucru minor. Bazele de date noi sunt interesante în postări de blog și epuizante în producție.
MySQL 8.4 este o versiune LTS. Corecțiile de erori apar după un program previzibil. Motorul de stocare este InnoDB, care îți oferă blocare la nivel de rând, impunerea cheilor externe și tranzacții ACID în mod implicit. Nu trebuie să configurezi nimic din acestea. Este activ. Optimizatorul gestionează corect majoritatea planurilor de interogare fără sugestii. Replicarea este matură. Dacă ai nevoie de replici de citire mai târziu, le adaugi fără a schimba codul aplicației.
Cea mai bună bază de date pentru un proiect nou este cea la care nu trebuie să te mai gândești niciodată.

UTF8MB4 de la început
O greșeală istorică autentică a MySQL a fost charset-ul utf8, care era de fapt o codificare pe 3 octeți ce nu putea stoca majoritatea caracterelor CJK și toate emoji-urile. Acea codificare se numește acum utf8mb3 și este depreciată. Înlocuitorul este utf8mb4, care este adevăratul UTF-8 pe 4 octeți și stochează totul: arabă, ebraică, japoneză, coreeană, tailandeză și da, fiecare emoji pe care utilizatorii tăi ți-l vor trimite.
NearYou are utilizatori în Tirolul de Sud, așa că conținutul sosește în germană, italiană, ladină și română. Setarea charset-ului și a colecției o singură dată la nivelul bazei de date înseamnă că nu mai trebuie să te gândești la asta la nivel de aplicație.
Un container lângă aplicație
Pentru dezvoltare și pentru deployment-uri mici în producție, MySQL rulează într-un container Docker pe același host ca și aplicația. Latența rețelei scade la sub milisecundă. Nu există un serviciu gestionat care să te factureze pentru timpul de inactivitate. Configurarea constă în patru rânduri de Docker Compose.
services:
db:
image: mysql:8.4
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
MYSQL_DATABASE: nearyou
MYSQL_USER: app
MYSQL_PASSWORD: ${DB_PASSWORD}
volumes:
- db_data:/var/lib/mysql
command: >
--character-set-server=utf8mb4
--collation-server=utf8mb4_unicode_ci
--default-authentication-plugin=caching_sha2_password
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${DB_ROOT_PASSWORD}"]
interval: 10s
timeout: 5s
retries: 5
app:
build: .
depends_on:
db:
condition: service_healthy
environment:
DATABASE_URL: mysql://app:${DB_PASSWORD}@db:3306/nearyou
volumes:
db_data:Healthcheck-ul contează. Fără el, containerul aplicației poate porni înainte ca MySQL să-și termine secvența de inițializare și pool-ul de conexiuni explodează la prima interogare. depends_on cu condition: service_healthy rezolvă asta curat.
Prisma 7: schemă, migrări, tipuri
Prisma este motivul pentru care această stivă este cu adevărat plăcută de utilizat. Scrii un singur fișier de schemă. Prisma generează migrări SQL din acesta, le execută pe baza de date și generează un client TypeScript cu tipuri care se potrivesc exact cu fiecare model. Fără afirmații de tip la runtime. Fără șiruri SQL scrise manual. Fără magie ORM care execută silențios interogări N+1.
Prisma 7 a adăugat suport de primă clasă pentru providerul mariadb, care acoperă MySQL 8.4 cu compatibilitate mai bună decât providerul legacy mysql pentru anumite cazuri limită legate de precizia datetime și gestionarea JSON. La NearYou îl folosim explicit.
// schema.prisma
generator client {
provider = "prisma-client-js"
previewFeatures = []
}
datasource db {
provider = "mariadb"
url = env("DATABASE_URL")
}
model Place {
id String @id @default(cuid())
name String @db.VarChar(255)
description String? @db.Text
lat Decimal @db.Decimal(10, 8)
lng Decimal @db.Decimal(11, 8)
category Category
ownerId String
owner User @relation(fields: [ownerId], references: [id], onDelete: Cascade)
events Event[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([lat, lng])
@@index([ownerId])
}
model User {
id String @id @default(cuid())
email String @unique @db.VarChar(320)
name String @db.VarChar(255)
places Place[]
createdAt DateTime @default(now())
}
enum Category {
RESTAURANT
CAFE
SHOP
EVENT_VENUE
OUTDOOR
OTHER
}Odată ce schema este la locul ei, două comenzi gestionează totul.
# Create and apply a migration (give it a descriptive name)
npx prisma migrate dev --name add-place-category-index
# Regenerate the TypeScript client after any schema change
npx prisma generateFișierul de migrare este SQL. Trăiește în controlul versiunilor. Îl poți citi, revizui într-un PR, da înapoi manual dacă ceva merge greșit. Nu există stare ascunsă. Comanda prisma migrate deploy execută migrările în așteptare în CI sau la pornirea serverului. Întregul flux este previzibil.
Cum lucrează un agent AI cu această stivă
Folosesc Claude Code ca agent AI de programare la NearYou. Agentul scrie scheme Prisma, generează migrări, interoghează baza de date prin client și depanează probleme de conexiune. Pentru ca aceasta să funcționeze fiabil între sesiuni, agentul are nevoie de memorie persistentă a configurației exacte: ce provider, ce versiune MySQL, ce convenții urmăm, ce capcane ne-au prins deja.
Rezolv aceasta cu un fișier AGENTS.md la nivel de proiect pe care agentul îl citește la fiecare sesiune. Nu este documentație pentru oameni. Este un fișier de context compact și precis care îi spune agentului cum să se comporte cu această stivă specifică. Agentul nu trebuie să redescopere că folosim mariadb ca provider Prisma, sau că migrările se află în prisma/migrations/, sau că formatul DSN pentru configurarea noastră Docker Compose folosește numele serviciului db ca hostname.

Iată secțiunea actuală a bazei de date din AGENTS.md-ul NearYou. Este scurtă. Este precisă. Fiecare rând își câștigă locul.
## Database (MySQL 8.4 + Prisma 7)
Provider: `mariadb` (not mysql — use this in schema.prisma)
DSN env var: `DATABASE_URL`
DSN format: `mysql://app:<pass>@db:3306/nearyou`
Schema file: `prisma/schema.prisma`
Migrations dir: `prisma/migrations/`
### Commands
- Dev migration: `npx prisma migrate dev --name <descriptive-name>`
- Deploy migrations: `npx prisma migrate deploy`
- Regenerate client: `npx prisma generate`
- Open Studio: `npx prisma studio`
- Reset dev DB: `npx prisma migrate reset` (DESTROYS DATA)
### Conventions
- All string PKs use cuid() not uuid() — smaller index footprint.
- All money values use Decimal, never Float.
- lat/lng use Decimal(10,8) and Decimal(11,8) respectively.
- Compound index on [lat, lng] on every Place-like model.
- onDelete: Cascade on all user-owned relations.
### Gotchas
- MySQL 8.4 default auth is caching_sha2_password. Old clients fail without upgrading.
- utf8mb4_unicode_ci is case-insensitive. Use utf8mb4_bin for case-sensitive fields like tokens.
- JSON columns in MySQL 8.4 do not support partial updates via Prisma — read, merge, write.
- Never run migrate reset in production. It drops and recreates all tables.Cu acest fișier prezent, agentul nu întreabă niciodată ce provider să folosească, nu ghicește niciodată formatul DSN și nu repetă niciodată o greșeală pe care am documentat-o deja. Citește fișierul, interiorizează constrângerile și operează stiva corect de prima dată. AGENTS.md devine memoria pe termen lung care supraviețuiește resetărilor ferestrei de context.
Singura regulă: backup-uri reale și testate
Tot ce este mai sus este confortabil. Singurul lucru non-negociabil sunt backup-urile. Nu un cron de backup despre care presupui că funcționează. Restaurări efectiv testate.
- Rulează
mysqldump --single-transaction --routines --triggerszilnic ca minimum. Flag-ul--single-transactionevită blocările tabelelor pe InnoDB. - Trimite dump-ul în afara site-ului imediat. Backup-urile pe același host nu sunt backup-uri, sunt un fals sentiment de siguranță.
- Testează restaurarea lunar. Pornește un container proaspăt, trimite dump-ul în el, verifică numărul de rânduri în tabelele critice.
- Dacă ești pe un host gestionat (Railway, PlanetScale, Render), verifică dacă recuperarea lor point-in-time acoperă efectiv cerința ta de retenție a datelor. Nu presupune.
- Migrările Prisma nu sunt un backup. Recreează schema, dar nu datele.
Verdictul
MySQL 8.4 cu Prisma 7 și adapterul mariadb nu este glamuros. Nu are o lucrare nouă strălucitoare de citat. Are treizeci de ani de întărire în producție, un ecosistem matur, instrumente excelente și zero surprize la scară. Pentru NearYou este alegerea corectă. Pentru majoritatea proiectelor noi este un standard complet defensibil. Alege-l, configurează utf8mb4 din prima zi, scrie un AGENTS.md real ca agentul tău AI să cunoască configurarea pe de rost și asigură-te că backup-urile tale sunt testate. Apoi oprește-te din gândit la baza de date și construiește produsul.