Més desenvolupadors haurien de saber-ho sobre les bases de dades

Nota. transl.: Jaana Dogan és una enginyera experimentada de Google que actualment treballa en l'observabilitat dels serveis de producció de la companyia escrits a Go. En aquest article, que va guanyar una gran popularitat entre el públic de parla anglesa, va recollir en 17 punts importants detalls tècnics sobre SGBD (i de vegades sistemes distribuïts en general) que són útils per tenir en compte per als desenvolupadors d'aplicacions grans i exigents.

Més desenvolupadors haurien de saber-ho sobre les bases de dades

La gran majoria dels sistemes informàtics fan un seguiment del seu estat i, en conseqüència, requereixen algun tipus de sistema d'emmagatzematge de dades. Vaig acumular coneixements sobre bases de dades durant un llarg període de temps, fent errors de disseny que van provocar pèrdues i interrupcions de dades. En els sistemes que processen grans volums d'informació, les bases de dades es troben al cor de l'arquitectura del sistema i actuen com a element clau per triar la solució òptima. Malgrat que es presta molta atenció al treball de la base de dades, els problemes que els desenvolupadors d'aplicacions intenten preveure sovint són només la punta de l'iceberg. En aquesta sèrie d'articles, comparteixo algunes idees que seran útils per als desenvolupadors que no estiguin especialitzats en aquest camp.

  1. Tens sort si el 99,999% del temps la xarxa no està causant problemes.
  2. ÀCID significa moltes coses diferents.
  3. Cada base de dades té els seus propis mecanismes per garantir la coherència i l'aïllament.
  4. El bloqueig optimista ve al rescat quan costa mantenir l'habitual.
  5. Hi ha altres anomalies a més de les lectures brutes i la pèrdua de dades.
  6. La base de dades i l'usuari no sempre estan d'acord sobre el curs d'acció.
  7. La fragmentació a nivell d'aplicació es pot moure fora de l'aplicació.
  8. L'increment automàtic pot ser perillós.
  9. Les dades obsoletes poden ser útils i no cal bloquejar-les.
  10. Les distorsions són típiques per a qualsevol font de temps.
  11. El retard té molts significats.
  12. Els requisits de rendiment s'han d'avaluar per a una transacció específica.
  13. Les transaccions imbricades poden ser perilloses.
  14. Les transaccions no han d'estar vinculades a l'estat de l'aplicació.
  15. Els planificadors de consultes us poden dir molt sobre les bases de dades.
  16. La migració en línia és difícil, però possible.
  17. Un augment significatiu de la base de dades comporta un augment de la imprevisibilitat.

M'agradaria agrair a Emmanuel Odeke, Rein Henrichs i altres els seus comentaris sobre una versió anterior d'aquest article.

Tens sort si el 99,999% del temps la xarxa no està causant problemes.

La qüestió continua sent sobre quina fiabilitat són les tecnologies de xarxa modernes i amb quina freqüència els sistemes estan caient a causa de fallades de la xarxa. La informació sobre aquest tema és escassa i la investigació sovint està dominada per grans organitzacions amb xarxes, equips i personal especialitzats.

Amb una taxa de disponibilitat del 99,999% per a Spanner (la base de dades distribuïda globalment de Google), Google afirma que només 7,6% els problemes estan relacionats amb la xarxa. Al mateix temps, l'empresa anomena a la seva xarxa especialitzada el “principal pilar” de l'alta disponibilitat. Estudiar Bailis i Kingsbury, realitzada el 2014, desafia una de les “idees errònies sobre la informàtica distribuïda", que Peter Deutsch va formular el 1994. És realment fiable la xarxa?

La recerca exhaustiva fora de les empreses gegants, realitzada per a Internet més àmplia, simplement no existeix. Tampoc hi ha prou dades dels principals actors sobre quin percentatge dels problemes dels seus clients estan relacionats amb la xarxa. Som ben conscients de les interrupcions a la pila de xarxa dels grans proveïdors de núvol que poden eliminar una part sencera d'Internet durant diverses hores simplement perquè són esdeveniments d'alt perfil que afecten un gran nombre de persones i empreses. Les interrupcions de la xarxa poden causar problemes en molts més casos, encara que no tots aquests casos estiguin en el punt de mira. Els clients dels serveis al núvol tampoc no saben res sobre les causes dels problemes. Si hi ha un error, és gairebé impossible atribuir-lo a un error de xarxa per part del proveïdor de serveis. Per a ells, els serveis de tercers són caixes negres. És impossible avaluar l'impacte sense ser un gran proveïdor de serveis.

Tenint en compte el que informen els grans jugadors sobre els seus sistemes, és segur dir que estàs d'enhorabona si les dificultats de la xarxa només representen un petit percentatge dels possibles problemes de temps d'inactivitat. Les comunicacions de xarxa encara pateixen coses tan quotidianes com errors de maquinari, canvis de topologia, canvis de configuració administrativa i talls d'energia. Recentment, em va sorprendre saber que es va afegir la llista de possibles problemes mossegades de tauró (sí, heu sentit bé).

ÀCID significa moltes coses diferents

L'acrònim ACID significa Atomicity, Consistency, Isolation, Reliability. Aquestes propietats de les transaccions estan destinades a garantir la seva validesa en cas de fallades, errors, fallades de maquinari, etc. Sense ACID o esquemes similars, als desenvolupadors d'aplicacions seria difícil diferenciar entre de què són responsables i de què és responsable la base de dades. La majoria de bases de dades transaccionals relacionals intenten ser compatibles amb ACID, però nous enfocaments com NoSQL han donat lloc a moltes bases de dades sense transaccions ACID perquè són cars d'implementar.

Quan vaig entrar per primera vegada a la indústria, el nostre responsable tècnic va parlar de la rellevància del concepte ACID. Per ser justos, ACID es considera una descripció aproximada més que un estàndard d'implementació estricte. Avui el trobo sobretot útil perquè planteja una categoria específica de problemes (i suggereix una sèrie de possibles solucions).

No tots els DBMS són compatibles amb ACID; Al mateix temps, les implementacions de bases de dades que admeten ACID entenen el conjunt de requisits de manera diferent. Una de les raons per les quals les implementacions d'ACID són irregulars és a causa de les nombroses compensacions que s'han de fer per implementar els requisits d'ACID. Els creadors poden presentar les seves bases de dades com a compatibles amb ACID, però la interpretació dels casos límit pot variar dràsticament, així com el mecanisme per gestionar esdeveniments "poc probables". Com a mínim, els desenvolupadors poden obtenir una comprensió d'alt nivell de les complexitats de les implementacions bàsiques per obtenir una comprensió adequada del seu comportament especial i els seus compromisos de disseny.

El debat sobre si MongoDB compleix els requisits d'ACID continua fins i tot després del llançament de la versió 4. MongoDB fa molt de temps que no és compatible registre, tot i que de manera predeterminada les dades es van comprometre al disc no més d'una vegada cada 60 segons. Imagineu el següent escenari: una aplicació publica dues escriptures (w1 i w2). MongoDB emmagatzema w1 amb èxit, però w2 es perd a causa d'una fallada de maquinari.

Més desenvolupadors haurien de saber-ho sobre les bases de dades
Diagrama que il·lustra l'escenari. MongoDB es bloqueja abans que pugui escriure dades al disc

Compromís amb el disc és un procés costós. En evitar les commits freqüents, els desenvolupadors milloren el rendiment de la gravació a costa de la fiabilitat. Actualment, MongoDB admet el registre, però les escriptures brutes encara poden afectar la integritat de les dades, ja que els registres es capturen cada 100 ms de manera predeterminada. És a dir, un escenari semblant encara és possible per als registres i els canvis que s'hi presenten, encara que el risc és molt menor.

Cada base de dades té els seus propis mecanismes de coherència i aïllament

Dels requisits d'ACID, la consistència i l'aïllament compten amb el major nombre d'implementacions diferents perquè la gamma de compensacions és més àmplia. Cal dir que la coherència i l'aïllament són funcions força cares. Requereixen coordinació i augmenten la competència per la coherència de les dades. La complexitat del problema augmenta significativament quan és necessari escalar la base de dades horitzontalment a través de diversos centres de dades (especialment si es troben en diferents regions geogràfiques). Aconseguir un alt nivell de coherència és molt difícil, ja que també redueix la disponibilitat i augmenta la segmentació de la xarxa. Per a una explicació més general d'aquest fenomen, us recomano que feu referència Teorema CAP. També val la pena assenyalar que les aplicacions poden gestionar petites quantitats d'incoherència i els programadors poden entendre els matisos del problema prou bé com per implementar una lògica addicional a l'aplicació per gestionar la inconsistència sense dependre molt de la base de dades per gestionar-la.

Els SGBD sovint proporcionen diferents nivells d'aïllament. Els desenvolupadors d'aplicacions poden triar el més efectiu en funció de les seves preferències. Un aïllament baix permet augmentar la velocitat, però també augmenta el risc d'una cursa de dades. Un aïllament elevat redueix aquesta probabilitat, però alenteix el treball i pot provocar competència, cosa que provocarà frens a la base que comencen les fallades.

Més desenvolupadors haurien de saber-ho sobre les bases de dades
Revisió dels models de concurrència existents i les relacions entre ells

L'estàndard SQL defineix només quatre nivells d'aïllament, encara que en teoria i pràctica n'hi ha molts més. Jepson.io ofereix una visió general excel·lent dels models de concurrència existents. Per exemple, Google Spanner garanteix la serialització externa amb la sincronització del rellotge i, tot i que es tracta d'una capa d'aïllament més estricta, no es defineix a les capes d'aïllament estàndard.

L'estàndard SQL esmenta els nivells d'aïllament següents:

  • Serialitzable (el més estricte i car): l'execució serialitzable té el mateix efecte que algunes execucions de transaccions seqüencials. L'execució seqüencial significa que cada transacció posterior comença només després de completar l'anterior. Cal tenir en compte que el nivell Serialitzable sovint s'implementa com l'anomenat aïllament d'instantània (per exemple, a Oracle) a causa de diferències d'interpretació, tot i que l'aïllament d'instantània en si no està representat a l'estàndard SQL.
  • Lectures repetibles: els registres no compromesos de la transacció actual estan disponibles per a la transacció actual, però els canvis fets per altres transaccions (com ara files noves) no visible.
  • Llegir compromès: les dades no compromeses no estan disponibles per a les transaccions. En aquest cas, les transaccions només poden veure dades compromeses i es poden produir lectures fantasma. Si una transacció insereix i confirma noves files, la transacció actual podrà veure'ls quan se li faci una consulta.
  • Llegir sense compromís (nivell menys estricte i car): es permeten lectures brutes, les transaccions poden veure els canvis no compromesos fets per altres transaccions. A la pràctica, aquest nivell pot ser útil per a estimacions aproximades, com ara consultes COUNT(*) a la taula.

Nivell Serialitzable minimitza el risc de curses de dades, alhora que és el més car d'implementar i resulta en la càrrega competitiva més alta del sistema. Altres nivells d'aïllament són més fàcils d'implementar, però augmenten la probabilitat de curses de dades. Alguns SGBD us permeten establir un nivell d'aïllament personalitzat, d'altres tenen preferències fortes i no tots els nivells són compatibles.

El suport per als nivells d'aïllament s'anuncia sovint en un SGBD determinat, però només un estudi acurat del seu comportament pot revelar què està passant realment.

Més desenvolupadors haurien de saber-ho sobre les bases de dades
Revisió d'anomalies de concurrència a diferents nivells d'aïllament per a diferents SGBD

Martin Kleppmann en el seu projecte ermita Compara diferents nivells d'aïllament, parla sobre anomalies de concurrència i si la base de dades és capaç d'adherir-se a un nivell d'aïllament determinat. La investigació de Kleppmann mostra com els desenvolupadors de bases de dades pensen de manera diferent sobre els nivells d'aïllament.

El bloqueig optimista ve al rescat quan costa mantenir l'habitual.

El bloqueig pot ser molt car, no només perquè augmenta la competència a la base de dades, sinó també perquè requereix que els servidors d'aplicacions es connectin constantment a la base de dades. La segmentació de la xarxa pot agreujar les situacions de bloqueig exclusiu i conduir a bloquejos difícils d'identificar i resoldre. En els casos en què el bloqueig exclusiu no és adequat, el bloqueig optimista ajuda.

Bloqueig optimista és un mètode en el qual quan es llegeix una cadena, té en compte la seva versió, suma de comprovació o hora de la darrera modificació. Això us permet assegurar-vos que no hi ha cap canvi de versió atòmica abans de canviar una entrada:

UPDATE products
SET name = 'Telegraph receiver', version = 2
WHERE id = 1 AND version = 1

En aquest cas, actualitzar la taula products no es durà a terme si una altra operació prèviament ha fet canvis en aquesta fila. Si no s'han realitzat altres operacions en aquesta fila, es produirà el canvi d'una fila i podem dir que l'actualització ha estat correcta.

Hi ha altres anomalies a més de les lectures brutes i la pèrdua de dades

Quan es tracta de la coherència de les dades, l'atenció se centra en el potencial de condicions de carrera que poden provocar lectures brutes i pèrdua de dades. Tanmateix, les anomalies de dades no s'aturen aquí.

Un exemple d'aquestes anomalies és la distorsió de l'enregistrament (escriure esbiaixades). Les distorsions són difícils de detectar perquè normalment no es busquen activament. No es deuen a lectures brutes o pèrdua de dades, sinó a violacions de les restriccions lògiques imposades a les dades.

Per exemple, considerem una aplicació de supervisió que requereix que un operador estigui de guàrdia en tot moment:

BEGIN tx1;                      BEGIN tx2;
SELECT COUNT(*)
FROM operators
WHERE oncall = true;
0                               SELECT COUNT(*)
                                FROM operators
                                WHERE oncall = TRUE;
                                0
UPDATE operators                UPDATE operators
SET oncall = TRUE               SET oncall = TRUE
WHERE userId = 4;               WHERE userId = 2;
COMMIT tx1;                     COMMIT tx2;

En la situació anterior, es produirà un registre de corrupció si les dues transaccions es realitzen amb èxit. Tot i que no hi va haver lectures brutes ni pèrdua de dades, la integritat de les dades es va veure compromesa: ara es consideren dues persones de guàrdia alhora.

L'aïllament serialitzable, el disseny d'esquemes o les limitacions de la base de dades poden ajudar a eliminar la corrupció de l'escriptura. Els desenvolupadors han de ser capaços d'identificar aquestes anomalies durant el desenvolupament per evitar-les en producció. Al mateix temps, les distorsions de gravació són extremadament difícils de buscar a la base de codi. Especialment en sistemes grans, quan diferents equips de desenvolupament s'encarreguen d'implementar funcions basades en les mateixes taules i no es posen d'acord en les especificitats de l'accés a les dades.

La base de dades i l'usuari no sempre estan d'acord sobre què fer

Una de les característiques clau de les bases de dades és la garantia de l'ordre d'execució, però aquesta ordre en si pot no ser transparent per al desenvolupador de programari. Les bases de dades executen les transaccions en l'ordre en què es reben, no en l'ordre que pretenen els programadors. L'ordre de les transaccions és difícil de predir, especialment en sistemes paral·lels altament carregats.

Durant el desenvolupament, especialment quan es treballa amb biblioteques que no bloquegen, l'estil deficient i la poca llegibilitat poden fer que els usuaris creguin que les transaccions s'executen de manera seqüencial, quan de fet podrien arribar a la base de dades en qualsevol ordre.

A primera vista, al programa següent, T1 i T2 s'anomenen seqüencialment, però si aquestes funcions no bloquegen i retornen immediatament el resultat en la forma promesa, llavors l'ordre de les trucades vindrà determinat pels moments en què van entrar a la base de dades:

resultat1 = T1() // els resultats reals són promeses
resultat2 = T2()

Si cal l'atomicitat (és a dir, totes les operacions s'han de completar o avortar) i la seqüència és important, les operacions T1 i T2 s'han de realitzar dins d'una única transacció.

La fragmentació a nivell d'aplicació es pot moure fora de l'aplicació

La fragmentació és un mètode de partició horitzontal d'una base de dades. Algunes bases de dades poden dividir automàticament les dades horitzontalment, mentre que d'altres no, o no són molt bones. Quan els arquitectes/desenvolupadors de dades són capaços de predir exactament com s'accedirà a les dades, poden crear particions horitzontals a l'espai d'usuari en lloc de delegar aquest treball a la base de dades. Aquest procés s'anomena "sharding a nivell d'aplicació" (fragmentació a nivell d'aplicació).

Malauradament, aquest nom sovint crea la idea errònia que sharding viu als serveis d'aplicacions. De fet, es pot implementar com una capa separada davant de la base de dades. Segons el creixement de les dades i les iteracions de l'esquema, els requisits de fragmentació poden arribar a ser força complexos. Algunes estratègies poden beneficiar-se de la capacitat d'iterar sense haver de tornar a desplegar servidors d'aplicacions.

Més desenvolupadors haurien de saber-ho sobre les bases de dades
Un exemple d'arquitectura en què els servidors d'aplicacions estan separats del servei de fragmentació

Moure la fragmentació a un servei independent amplia la capacitat d'utilitzar diferents estratègies de fragmentació sense necessitat de tornar a desplegar aplicacions. velocitat és un exemple d'aquest sistema de fragmentació a nivell d'aplicació. Vitess proporciona fragmentació horitzontal per a MySQL i permet als clients connectar-s'hi mitjançant el protocol MySQL. El sistema segmenta les dades en diferents nodes de MySQL que no saben res els uns dels altres.

L'increment automàtic pot ser perillós

AUTOINCREMENT és una manera habitual de generar claus primàries. Sovint hi ha casos en què les bases de dades s'utilitzen com a generadors d'ID i la base de dades conté taules dissenyades per generar identificadors. Hi ha diverses raons per les quals generar claus primàries mitjançant l'increment automàtic està lluny de ser ideal:

  • En una base de dades distribuïda, l'increment automàtic és un problema greu. Per generar l'identificador, cal un bloqueig global. En canvi, podeu generar un UUID: això no requereix interacció entre diferents nodes de base de dades. L'increment automàtic amb bloqueigs pot provocar conflictes i reduir significativament el rendiment de les insercions en situacions distribuïdes. Alguns SGBD (per exemple, MySQL) poden requerir una configuració especial i una atenció més acurada per organitzar correctament la rèplica mestre-mestre. I és fàcil cometre errors en la configuració, cosa que provocarà errors en la gravació.
  • Algunes bases de dades tenen algorismes de partició basats en claus primàries. Els identificadors consecutius poden provocar punts calents impredictibles i augmentar la càrrega en algunes particions, mentre que altres romanen inactives.
  • Una clau primària és la manera més ràpida d'accedir a una fila d'una base de dades. Amb millors maneres d'identificar registres, els identificadors seqüencials poden convertir la columna més important de les taules en una columna inútil plena de valors sense sentit. Per tant, sempre que sigui possible, escolliu una clau primària única i natural a nivell mundial (per exemple, nom d'usuari).

Abans de decidir un enfocament, tingueu en compte l'impacte de l'increment automàtic d'ID i UUID en la indexació, la partició i la fragmentació.

Les dades obsoletes poden ser útils i no requereixen bloqueig

El control de concurrència multiversió (MVCC) implementa molts dels requisits de coherència que s'han comentat breument anteriorment. Algunes bases de dades (per exemple, Postgres, Spanner) utilitzen MVCC per "alimentar" les transaccions amb instantànies: versions anteriors de la base de dades. Les transaccions instantànies també es poden serialitzar per garantir la coherència. Quan es llegeix d'una instantània antiga, es llegeixen dades obsoletes.

La lectura de dades una mica obsoletes pot ser útil, per exemple, quan es generen analítiques a partir de les dades o es calculen valors agregats aproximats.

El primer avantatge de treballar amb dades heretades és la baixa latència (sobretot si la base de dades es distribueix en diferents geografies). El segon és que les transaccions de només lectura estan lliures de bloqueig. Aquest és un avantatge important per a les aplicacions que llegeixen molt, sempre que puguin gestionar dades obsoletes.

Més desenvolupadors haurien de saber-ho sobre les bases de dades
El servidor d'aplicacions llegeix dades de la rèplica local que estan obsoletes 5 segons, encara que la darrera versió estigui disponible a l'altra banda de l'oceà Pacífic.

Els SGBD purguen automàticament les versions anteriors i, en alguns casos, us permeten fer-ho a petició. Per exemple, Postgres permet als usuaris fer-ho VACUUM a petició, i també realitza periòdicament aquesta operació automàticament. Spanner gestiona un col·lector d'escombraries per desfer-se de les instantànies de més d'una hora.

En qualsevol moment les fonts estan subjectes a distorsió

El secret més ben guardat de la informàtica és que totes les API de cronometratge menteixen. De fet, les nostres màquines no saben l'hora exacta actual. Els ordinadors contenen cristalls de quars que generen vibracions que s'utilitzen per mantenir el temps. No obstant això, no són prou precises i poden estar per davant/enrere de l'hora exacta. El torn pot arribar als 20 segons al dia. Per tant, l'hora dels nostres ordinadors s'ha de sincronitzar periòdicament amb la de xarxa.

Els servidors NTP s'utilitzen per a la sincronització, però el procés de sincronització en si està subjecte a retards de xarxa. Fins i tot la sincronització amb un servidor NTP al mateix centre de dades requereix un temps. És evident que treballar amb un servidor NTP públic pot provocar una distorsió encara més gran.

Els rellotges atòmics i els seus homòlegs GPS són millors per determinar l'hora actual, però són cars i requereixen una configuració complexa, de manera que no es poden instal·lar a tots els cotxes. Per això, els centres de dades utilitzen un enfocament escalonat. Els rellotges atòmics i/o GPS mostren l'hora exacta, després de la qual s'emet a altres màquines a través de servidors secundaris. Això vol dir que cada màquina experimentarà un cert desplaçament de l'hora exacta.

La situació s'agreuja pel fet que les aplicacions i les bases de dades sovint es troben en màquines diferents (si no en centres de dades diferents). Per tant, el temps diferirà no només en els nodes de base de dades distribuïts en diferents màquines. També serà diferent al servidor d'aplicacions.

Google TrueTime adopta un enfocament completament diferent. La majoria de la gent creu que el progrés de Google en aquesta direcció s'explica per la transició banal als rellotges atòmics i GPS, però això només és una part del panorama general. Així és com funciona TrueTime:

  • TrueTime utilitza dues fonts diferents: GPS i rellotges atòmics. Aquests rellotges tenen modes de fallada no correlacionats. [vegeu la pàgina 5 per a més detalls aquí -aprox. trad.), de manera que el seu ús conjunt augmenta la fiabilitat.
  • TrueTime té una API inusual. Retorna el temps com un interval amb error de mesura i incertesa incorporats. El moment real en el temps es troba entre els límits superior i inferior de l'interval. Spanner, la base de dades distribuïda de Google, simplement espera fins que es pugui dir que l'hora actual està fora de l'abast. Aquest mètode introdueix una certa latència al sistema, sobretot si la incertesa dels màsters és alta, però garanteix la correcció fins i tot en una situació distribuïda globalment.

Més desenvolupadors haurien de saber-ho sobre les bases de dades
Els components de l'Spanner utilitzen TrueTime, on TT.now() retorna un interval, de manera que l'Spanner simplement dorm fins al punt en què pot estar segur que l'hora actual ha passat un determinat punt.

La reducció de la precisió en la determinació del temps actual significa un augment de la durada de les operacions de la clau i una disminució del rendiment. Per això és important mantenir la màxima precisió possible tot i que és impossible obtenir un rellotge completament precís.

El retard té molts significats

Si pregunteu a una dotzena d'experts sobre què és un retard, probablement obtindreu respostes diferents. En DBMS, la latència sovint s'anomena "latència de base de dades" i és diferent del que percep el client. El fet és que el client observa la suma del retard de la xarxa i el retard de la base de dades. La capacitat d'aïllar el tipus de latència és fonamental quan es depuren problemes creixents. En recopilar i mostrar mètriques, sempre intenteu vigilar ambdós tipus.

Els requisits de rendiment s'han d'avaluar per a una transacció específica

De vegades, les característiques de rendiment d'un SGBD i les seves limitacions s'especifiquen en termes de rendiment d'escriptura/lectura i latència. Això proporciona una visió general dels paràmetres clau del sistema, però quan s'avalua el rendiment d'un nou SGBD, un enfocament molt més complet és avaluar per separat les operacions crítiques (per a cada consulta i/o transacció). Exemples:

  • Escriviu el rendiment i la latència en inserir una fila nova a la taula X (amb 50 milions de files) amb les restriccions especificades i el farciment de files a les taules relacionades.
  • Retard en mostrar els amics d'amics d'un usuari determinat quan el nombre mitjà d'amics és de 500.
  • Latència en recuperar les 100 entrades principals de l'historial d'un usuari quan l'usuari segueix 500 usuaris més amb X entrades per hora.

L'avaluació i l'experimentació poden incloure aquests casos crítics fins que estigueu segurs que la base de dades compleix els requisits de rendiment. Una regla general similar també té en compte aquest desglossament a l'hora de recopilar mètriques de latència i determinar els SLO.

Tingueu en compte l'alta cardinalitat en recopilar mètriques per a cada operació. Utilitzeu registres, recopilació d'esdeveniments o traça distribuïda per obtenir dades de depuració d'alta potència. A l'article "Voleu depurar la latència?» us podeu familiaritzar amb les metodologies de depuració de retard.

Les transaccions imbricades poden ser perilloses

No tots els DBMS admeten transaccions imbricades, però quan ho fan, aquestes transaccions poden provocar errors inesperats que no sempre són fàcils de detectar (és a dir, hauria de ser obvi que hi ha algun tipus d'anomalia).

Podeu evitar l'ús de transaccions imbricades mitjançant biblioteques de client que les poden detectar i evitar. Si les transaccions imbricades no es poden abandonar, tingueu especial cura en la seva implementació per evitar situacions inesperades en què les transaccions completades s'avortin accidentalment a causa de les imbricades.

Encapsular transaccions en diferents capes pot conduir a transaccions imbricades inesperades i, des del punt de vista de la llegibilitat del codi, pot dificultar la comprensió de les intencions de l'autor. Fes una ullada al següent programa:

with newTransaction():
   Accounts.create("609-543-222")
   with newTransaction():
       Accounts.create("775-988-322")
       throw Rollback();

Quina serà la sortida del codi anterior? Revertirà les dues transaccions o només la interna? Què passa si confiem en diverses capes de biblioteques que encapsulen la creació de transaccions per a nosaltres? Serem capaços d'identificar i millorar aquests casos?

Imagineu una capa de dades amb múltiples operacions (p. ex. newAccount) ja està implementat en les seves pròpies transaccions. Què passa si els executeu com a part de la lògica empresarial de nivell superior que s'executa dins de la seva pròpia transacció? Quin seria l'aïllament i la coherència en aquest cas?

function newAccount(id string) {
  with newTransaction():
      Accounts.create(id)
}

En lloc de buscar respostes a preguntes tan infinites, és millor evitar les transaccions imbricades. Després de tot, la vostra capa de dades pot realitzar fàcilment operacions d'alt nivell sense crear les seves pròpies transaccions. A més, la pròpia lògica de negoci és capaç d'iniciar una transacció, realitzar-hi operacions, confirmar o avortar una transacció.

function newAccount(id string) {
   Accounts.create(id)
}
// In main application:
with newTransaction():
   // Read some data from database for configuration.
   // Generate an ID from the ID service.
   Accounts.create(id)
   Uploads.create(id) // create upload queue for the user.

Les transaccions no han d'estar vinculades a l'estat de l'aplicació

De vegades és temptador utilitzar l'estat de l'aplicació en les transaccions per canviar determinats valors o ajustar paràmetres de consulta. El matís crític a considerar és l'àmbit d'aplicació correcte. Els clients sovint reinicien les transaccions quan hi ha problemes de xarxa. Si la transacció depèn d'un estat que s'està canviant per algun altre procés, pot escollir el valor incorrecte en funció de la possibilitat d'una cursa de dades. Les transaccions han de tenir en compte el risc de les condicions de carrera de dades a l'aplicació.

var seq int64
with newTransaction():
    newSeq := atomic.Increment(&seq)
    Entries.query(newSeq)
    // Other operations...

La transacció anterior augmentarà el número de seqüència cada vegada que s'executi, independentment del resultat final. Si la confirmació falla a causa de problemes de xarxa, la sol·licitud s'executarà amb un número de seqüència diferent quan ho torneu a provar.

Els planificadors de consultes us poden dir molt sobre una base de dades

Els planificadors de consultes determinen com s'executarà una consulta en una base de dades. També analitzen les peticions i les optimitzen abans d'enviar-les. Els planificadors només poden proporcionar algunes estimacions possibles basades en els senyals de què disposen. Per exemple, quin és el millor mètode de cerca per a la consulta següent?

SELECT * FROM articles where author = "rakyll" order by title;

Els resultats es poden recuperar de dues maneres:

  • Escaneig de taula completa: podeu mirar cada entrada de la taula i tornar articles amb un nom d'autor que coincideix, i després ordenar-los.
  • Exploració de l'índex: podeu utilitzar un índex per trobar identificadors coincidents, obtenir aquestes files i ordenar-les.

La feina del planificador de consultes és determinar quina estratègia és la millor. Val la pena tenir en compte que els planificadors de consultes només tenen capacitats predictives limitades. Això pot portar a males decisions. Els DBA o els desenvolupadors poden utilitzar-los per diagnosticar i ajustar les consultes amb un rendiment baix. Les noves versions del SGBD poden configurar planificadors de consultes i l'autodiagnòstic pot ajudar a l'actualització de la base de dades si la nova versió comporta problemes de rendiment. Els registres de consultes lents, els informes de problemes de latència o les estadístiques de temps d'execució poden ajudar a identificar les consultes que necessiten optimització.

Algunes mètriques presentades pel planificador de consultes poden estar subjectes a soroll (sobretot quan s'estima la latència o el temps de CPU). Una bona addició als programadors són les eines per rastrejar i fer el seguiment del camí d'execució. Us permeten diagnosticar aquests problemes (per desgràcia, no tots els SGBD ofereixen aquestes eines).

La migració en línia és difícil però possible

La migració en línia, la migració en directe o la migració en temps real significa passar d'una base de dades a una altra sense temps d'inactivitat ni corrupció de dades. La migració en directe és més fàcil de dur a terme si la transició es produeix dins del mateix DBMS/motor. La situació es complica quan cal passar a un nou SGBD amb diferents requisits de rendiment i esquema.

Hi ha diferents models de migració en línia. Aquí teniu un d'ells:

  • Habiliteu la doble entrada a les dues bases de dades. La nova base de dades en aquesta fase no té totes les dades, però només accepta les dades més recents. Quan estigueu segur d'això, podeu passar al següent pas.
  • Habilita la lectura de les dues bases de dades.
  • Configureu el sistema de manera que la lectura i l'escriptura es realitzin principalment a la nova base de dades.
  • Deixeu d'escriure a la base de dades antiga mentre continueu llegint-ne dades. En aquesta fase, la nova base de dades encara no té algunes dades. S'han de copiar de la base de dades antiga.
  • La base de dades antiga és només de lectura. Copieu les dades que falten de la base de dades antiga a la nova. Un cop finalitzada la migració, canvieu els camins a la nova base de dades i atureu l'antiga i suprimiu-la del sistema.

Per obtenir informació addicional, us recomano contactar article, que detalla l'estratègia de migració de Stripe basada en aquest model.

Un augment significatiu de la base de dades comporta un augment de la imprevisibilitat

El creixement de la base de dades comporta problemes impredictibles associats a la seva escala. Com més sabem sobre l'estructura interna d'una base de dades, millor podem predir com s'escalarà. Tanmateix, alguns moments encara són impossibles de preveure.
A mesura que la base creix, els supòsits i expectatives anteriors sobre el volum de dades i els requisits d'amplada de banda de la xarxa poden quedar obsolets. Aquí és quan sorgeix la qüestió de revisions importants del disseny, millores operatives a gran escala, replantejaments de desplegaments o migració a altres SGBD per evitar possibles problemes.

Però no us penseu que un coneixement excel·lent de l'estructura interna de la base de dades existent és l'únic necessari. Les noves escales portaran amb elles noves incògnites. Els problemes impredictibles, la distribució desigual de dades, l'amplada de banda i els problemes de maquinari inesperats, el trànsit cada cop més gran i els nous segments de xarxa us obligaran a repensar el vostre enfocament de base de dades, model de dades, model de desplegament i mida de la base de dades.

...

En el moment que vaig començar a pensar en publicar aquest article, ja hi havia cinc articles més a la meva llista original. Després va venir un gran nombre noves idees sobre què més es pot cobrir. Per tant, l'article toca els problemes menys evidents que requereixen la màxima atenció. Tanmateix, això no vol dir que el tema s'hagi esgotat i ja no hi tornaré en els meus futurs materials i no faré canvis a l'actual.

PS

Llegeix també al nostre blog:

Font: www.habr.com

Afegeix comentari