Refactor for Reliability: Why Your Backend Needs a Database Overhaul
Бекендот ретко откажува затоа што едно барање е бавно. Откажува затоа што со години се насобираат разумни кратенки во податочен слој на кој никој целосно не му верува: дуплирани полиња, нејасна сопственост, недостасувачки ограничувања, кревки миграции и апликациски код што тивко компензира за сето тоа.
Тогаш ремонтот на базата на податоци престанува да биде инфраструктурна преференција и станува проект за доверливост. Целта не е да се замени секоја табела или да се брка идеализирана шема. Целта е базата на податоци да стане сигурна граница: место каде што важните факти се претставени еднаш, невалидните состојби тешко се создаваат, а промените може безбедно да се распоредат.
Доверливоста започнува со сопственоста на податоците
Многу бекенд-проблеми што изгледаат како API или PHP проблеми всушност се проблеми со сопственоста. Разгледајте ја е-поштата на клиентот за нарачка копирана во табела orders, табела users и табела за известување. Која вредност е авторитативна? Ако клиентот ја ажурира својата е-пошта, дали треба да се променат минатите нарачки? Ако не, таа копија може да биде намерна историска снимка. Ако да, таа претставува обврска за синхронизација.
Ремонтот ги изнесува овие одлуки на виделина. За секој важен концепт, дефинирајте што претставува, каде се наоѓа неговата канонска вредност и кои копии се намерно изведени. Таа јасност подобрува повеќе од шемата. Ги прави границите на услугите, API одговорите, невалидирањето на кешот и дебагирањето многу помалку двосмислени.
Моделирајте ги правилата таму каде што не може да се заобиколат
PHP валидацијата е неопходна, но не е доволна. Задачи, увози, административни скрипти и идни услуги може сите да запишуваат во истата база на податоци. Ако некое правило е важно без оглед на тоа која кодна патека го извршува запишувањето, базата на податоци треба да помогне во неговото спроведување.
- Користете примарни клучеви и надворешни клучеви за да изразите идентитет и односи.
- Користете
NOT NULLкога отсутната вредност нема валидно значење. - Користете уникатни ограничувања за вредности што не смеат да се дуплираат, како идентификатор од надворешен добавувач.
- Користете проверочни ограничувања каде што се поддржани и соодветни за стабилни правила на доменот.
- Изберете типови на податоци што одговараат на податоците, особено за временски ознаки, пари и статусни вредности.
Ограничувањата не се бирократија. Тие ја претвораат тивката корупција во видлив неуспех на границата на запишувањето, каде што обично е поевтино да се дијагностицира и да се закрепне.
Дизајнирајте ги миграциите како систем за распоредување
Промената на шемата е продукциски код. Потребни ѝ се верзионирање, преглед, тестирање и безбедна патека низ делумно распоредување. Ризичниот образец е да се смени колона и да се претпостави дека секоја активна инстанца на апликацијата веднаш ќе ја разбере новата форма.
Наместо тоа, користете пристап на проширување и стеснување. Прво додадете компатибилна структура. Потоа распоредете код што може да работи и со старото и со новото претставување. Пополнете ги постојните записи во контролирани серии. Префрлете ги читањата и запишувањата на новата патека. Дури откако старата патека повеќе не се користи, отстранете ја.
ALTER TABLE orders
ADD COLUMN customer_email_snapshot VARCHAR(255) NULL;
CREATE INDEX idx_orders_customer_email_snapshot
ON orders (customer_email_snapshot);
Додавањето на nullable колоната е чекорот на проширување, а не крајната цел. Дополнителното пополнување треба да може да продолжи и да биде набљудливо. Избегнувајте едно барање на апликацијата што ажурира милиони редови и бидете внимателни со долги трансакции што може да заклучат многу користени табели.
$lastId = 0;
do {
$rows = $pdo->prepare(
'SELECT id, customer_email
FROM orders
WHERE id > :lastId
AND customer_email_snapshot IS NULL
ORDER BY id
LIMIT 500'
);
$rows->execute(['lastId' => $lastId]);
$batch = $rows->fetchAll();
foreach ($batch as $order) {
$update = $pdo->prepare(
'UPDATE orders
SET customer_email_snapshot = :email
WHERE id = :id
AND customer_email_snapshot IS NULL'
);
$update->execute([
'email' => $order['customer_email'],
'id' => $order['id'],
]);
$lastId = $order['id'];
}
} while ($batch !== []);
Условното ажурирање ја прави операцијата побезбедна за повторување. Во продукциска миграција, исто така бележете го напредокот, мерете го пропусниот опсег, справувајте се со привремени неуспеси на базата на податоци и проверете го бројот на преостанати редови пред да го промените однесувањето на апликацијата.
Индексите треба да служат на реални обрасци на пристап
Индексите се еден од најбрзите начини за подобрување на бекендот, но не се бесплатни. Секој дополнителен индекс додава простор за складирање и работа при вметнувања, ажурирања и бришења. Вистинското прашање не е „кои колони изгледаат важни?“ Туку „кои барања апликацијата навистина ги извршува под оптоварување?“
Почнете со докази за бавни барања и репрезентативни планови за барања. Ако крајна точка вообичаено ги филтрира нарачките според сметка и датум, индекс што започнува со тие колони може да биде корисен. Ако пребарува со водечки џокер-знак, конвенционален индекс можеби воопшто нема да помогне. Ако барањето враќа илјадници редови за прикажување мала контролна табла, поголемиот проблем може да биде пагинацијата или премногу широк API договор.
На пример, ова барање предлага композитен индекс усогласен со неговиот филтер за еднаквост и подредување:
SELECT id, status, created_at
FROM orders
WHERE account_id = ?
AND created_at >= ?
ORDER BY created_at DESC
LIMIT 50;
Дизајнот на индексите зависи од механизмот на базата на податоци и целосната форма на барањето, затоа проверете со неговите алатки за планирање барања пред да прогласите успех. Ремонтот на базата на податоци го заменува фолклорот со мерење.
Трансакциите го дефинираат интегритетот на работниот тек
Доверливо API не само што го враќа точниот JSON по среќната патека. Тоа зачувува кохерентна состојба кога повратниот повик за плаќање се повторува, работникот откажува на половина од процесот или две барања пристигнуваат во исто време.
Користете трансакции за промени што мора да успеат или да откажат заедно. Одржувајте ги кратки, избегнувајте надворешни мрежни повици додека трансакцијата е отворена и направете го однесувањето при повторување експлицитно. Кога настан од трета страна може да биде доставен повеќе од еднаш, складирајте клуч за идемпотентност или идентификатор на настан од добавувачот под уникатно ограничување. Тогаш дупликат-доставувањето станува контролиран случај наместо дупликат наплата или дупликат испорака.
Апликацискиот код исто така треба да ги преведува предвидливите неуспеси на базата на податоци во корисни одговори на доменот. Прекршување на уникатно ограничување може да значи „ова барање веќе беше обработено“, додека неочекувана грешка на базата на податоци треба да се евидентира со доволно контекст за истрага, без да се откриваат внатрешни детали на API потрошувачите.
Направете ја оперативната едноставност дел од дизајнот
Чистата шема сè уште има потреба од здрав оперативен модел. Резервните копии мора да се тестираат со нивно обновување. Ограничувањата на конекциите мора да ги земат предвид PHP-FPM работниците, потрошувачите на редици, закажаните задачи и локалните Docker околини. Надзорот треба да прави разлика меѓу исцрпување на конекции, чекања за заклучување, доцнење во репликацијата каде што е применливо, бавни барања и притисок врз складирањето.
Docker може да го направи ова повторливо за развој: намерно дефинирајте ја верзијата на базата на податоци, однесувањето при иницијализација, портите и постојаниот волумен. Но продукциската доверливост не доаѓа само од дефиниција на контејнер. Таа доаѓа од знаењето како да мигрирате, закрепнете, проверите и продолжите напред кога распоредувањето не се однесува како што се очекува.
Добивката е посмирен бекенд
Ремонтот на базата на податоци е успешен кога обичната работа ја прави помалку драматична. Новите крајни точки бараат помалку одбранбени закрпи. Грешките имаат појасни причини. Позадинските задачи може безбедно да се повторат. Истражувањата на перформансите започнуваат со разбирливи барања наместо со вознемирени претпоставки.
Најдобриот резултат не е шема што изгледа паметно на дијаграм. Тоа е податочна основа што му овозможува на остатокот од бекендот да се менува со доверба. Кога базата на податоци сигурно ги заштитува вистините од кои зависи вашиот систем, PHP кодот, API-јата и тимовите сите добиваат поедноставни места на кои можат да стојат.