Ghid de migrare Oracle la SQL Server și SQL Server la Oracle - Pt. 3

Publicat: 2022-03-11

Prima și a doua parte a acestei serii au discutat diferențele dintre Oracle Database și Microsoft SQL Server în implementarea tranzacțiilor și capcanele rezultate din conversie, precum și unele elemente de sintaxă utilizate în mod obișnuit.

Această ultimă tranșă va acoperi noțiunea de consecvență a citirii Oracle și modul de conversie a arhitecturii, bazată pe această noțiune, într-o versiune Microsoft SQL Server. Se va aborda, de asemenea, utilizarea sinonimelor (și cum să NU le folosiți) și rolul procesului de control al schimbării în gestionarea mediului bazei de date.

Oracle Read Consistency și echivalentul său în SQL Server

Consecvența citirii Oracle este o garanție că toate datele returnate de o singură instrucțiune SQL provin din același moment singular în timp.

Înseamnă că, dacă ați emis o SELECT la 12:01:02.345 și a rulat timp de 5 minute înainte de a returna setul de rezultate, toate datele (și numai datele) care au fost comise în baza de date de la 12:01:02.345 o vor face. în setul de întoarcere. Setul dvs. de returnare nu va avea date noi adăugate în acele 5 minute în care a durat baza de date pentru a vă procesa extrasul, nici actualizări și nicio ștergere nu va fi vizibilă.

Arhitectura Oracle atinge consecvența citirii prin marcarea temporală internă a fiecărei modificări a datelor și construirea unui set de rezultate din două surse: fișiere de date permanente și un segment de anulare (sau „segment de rollback”, așa cum era cunoscut până la versiunea 10g).

Pentru a o susține, informațiile de anulare ar trebui păstrate. Dacă este suprascris, rezultă infama eroare ORA-01555: snapshot too old .

Lăsând deoparte anularea gestionării segmentelor – și cum să navigați în ORA-01555: snapshot too old – să ne uităm la implicațiile consecvenței citirii asupra oricărei implementări practice în Oracle. De asemenea, cum ar trebui să fie reflectat în SQL Server, care, așa cum este cazul altor implementări RDBMS, cu excepția posibilă și calificată a PostgreSQL, nu îl acceptă?

Cheia este că Oracle citește și scrie nu se blochează reciproc. De asemenea, înseamnă că setul dvs. de returnări de interogări de lungă durată poate să nu aibă cele mai recente date.

Citirile și scrierile care nu sunt blocate sunt un avantaj pe care Oracle îl are și afectează domeniul de aplicare al tranzacțiilor.

Dar consecvența citirii înseamnă, de asemenea, că nu aveți cea mai recentă stare a datelor. Când în unele scenarii este perfect bine (cum ar fi producerea unui raport pentru un anumit moment), ar putea crea probleme semnificative în altele.

A nu avea cele mai recente date – chiar și „murdare” sau neangajate – ar putea fi critică: scenariul clasic este un sistem de rezervare a camerelor de hotel.

Luați în considerare următorul caz de utilizare: aveți doi agenți de servicii clienți care acceptă simultan comenzi de rezervare a camerei. Cum vă puteți asigura că camerele nu devin suprarezervate?

În SQL Server, puteți începe o tranzacție explicită și SELECT o înregistrare din lista (care ar putea fi un tabel sau o vizualizare) a camerelor disponibile. Atâta timp cât această tranzacție nu este închisă (fie prin COMMIT sau ROLLBACK ), nimeni nu poate obține aceeași înregistrare a camerei pe care ați selectat-o. Acest lucru previne rezervarea dublă, dar face și toți ceilalți agenți să aștepte unul pe celălalt pentru a finaliza cererile de rezervare pe rând, secvenţial.

În Oracle, puteți obține același rezultat prin emiterea unei SELECT ... FOR UPDATE împotriva înregistrărilor care corespund criteriilor dvs. de căutare.

Notă: există soluții mai bune, cum ar fi setarea unui steag temporar care marchează o cameră „în luare în considerare” în loc să blochezi orbește accesul la ea. Dar acestea sunt soluții arhitecturale, nu opțiuni lingvistice.

Concluzie : Consecvența citirii Oracle nu este „tot bine” sau „tot rău”, ci o proprietate importantă a platformei care trebuie înțeleasă bine și este esențială pentru migrarea codului pe mai multe platforme.

Sinonime publice (și private) în Oracle și Microsoft SQL Server

„Sinonimele publice sunt rele.” Nu este tocmai descoperirea mea personală, dar am acceptat-o ​​ca evanghelie până când ziua, săptămâna și anul mi-au fost salvate prin sinonime publice.

În multe medii de baze de date - aș spune că toate mediile Oracle cu care am avut șansa să lucrez, dar niciunul pe care l-am proiectat - folosirea CREATE PUBLIC SYNONYM pentru fiecare obiect era o rutină pentru că „am procedat întotdeauna așa”.

În aceste medii, sinonimele publice aveau o singură funcție: să permită referirea la un obiect fără a specifica proprietarul acestuia. Și acesta este un motiv prost gândit pentru a face sinonime publice.

Cu toate acestea, sinonimele publice Oracle pot fi extrem de utile și oferă echipelor beneficii de productivitate care depășesc semnificativ toate dezavantajele lor, dacă sunt implementate și gestionate corect și cu un motiv. Da, am spus „productivitatea echipei”. Dar cum? Pentru aceasta, trebuie să înțelegem cum funcționează rezoluția numelor în Oracle.

Când analizatorul Oracle găsește un nume (un cuvânt cheie nerezervat), încearcă să-l potrivească cu un obiect de bază de date existent în următoarea ordine:

O diagramă flux care începe cu my_object ca intrare. Schema curentă a sesiunii emitente are un obiect numit my_object? Dacă da, am terminat. Dacă nu, schema curentă a sesiunii emitente are un sinonim privat numit my_object? Dacă da, rezolvăm sinonimul într-un obiect și am terminat. Dacă nu, există un sinonim public numit my_object? Dacă da, rezolvă-l și am terminat. Dacă nu, căutați o schemă cu acest nume. Dacă găsim unul, am terminat. Dacă nu, ridicați o eroare.

Notă: eroarea generată va fi ORA-00942: table or view does not exist pentru instrucțiunile DML, sau PLS-00201: identifier 'my_object' must be declared pentru procedurile stocate sau apelurile de funcții.

În această ordine de rezoluție a numelor, este ușor de observat că atunci când un dezvoltator lucrează în propria sa schemă, orice obiect local cu același nume ca un sinonim public va ascunde acest sinonim public. (Notă: Oracle 18c a implementat tipul de schemă „doar autentificare”, iar această discuție nu se aplică acestuia.)

Sinonime publice pentru Scaling Teams: Oracle Change Control

Să ne uităm acum la o echipă ipotetică de 100 de dezvoltatori care lucrează pe aceeași bază de date (care este ceva ce am experimentat). În plus, să presupunem că toți lucrează local pe stațiile lor de lucru personale și realizează în mod independent creări non-baze de date, toate legate la același mediu de dezvoltare a bazei de date. Rezolvarea fuziunii codului în codul care nu este baza de date (fie că este C#, Java, C++, Python sau orice altceva) se va face la momentul înregistrării controlului modificării și va intra în vigoare cu următoarea compilare a codului. Dar tabelele bazei de date, codul și datele trebuie schimbate de mai multe ori înainte și înapoi în timpul dezvoltării în curs. Fiecare dezvoltator face acest lucru independent și intră în vigoare imediat.

Pentru aceasta, toate obiectele bazei de date sunt create într-o schemă de aplicație comună. Aceasta este schema la care face referire aplicația. Fiecare dezvoltator:

  • Se conectează la baza de date cu contul personal/schema de utilizator
  • Începe întotdeauna cu o schemă personală goală
  • Face referire la schema comună numai prin rezoluția numelui la un sinonim public, așa cum este descris mai sus

Când un dezvoltator trebuie să facă modificări în baza de date - să creeze sau să modifice un tabel, să modifice codul de procedură sau chiar să modifice un set de date pentru a sprijini un scenariu de testare - creează o copie a obiectului în schema personală. Ei fac acest lucru prin obținerea codului DDL folosind comanda DESCRIBE și rulând-o local.

Din acest moment, codul acestui dezvoltator va vedea versiunea locală a obiectului și a datelor, care nu va fi vizibilă (și nici nu va avea un impact asupra) altcuiva. După finalizarea dezvoltării, codul modificat al bazei de date este verificat în controlul sursei și conflictele sunt rezolvate. Apoi, codul final (și datele, dacă este necesar) este implementat în schema comună.

După aceasta, întreaga echipă de dezvoltare poate vedea din nou aceeași bază de date. Dezvoltatorul care tocmai a livrat codul renunță la toate obiectele din schema personală și este pregătit pentru o nouă misiune.

Această capacitate de a facilita munca paralelă independentă pentru mai mulți dezvoltatori este principalul beneficiu al sinonimelor publice — o importanță greu de exagerat. Cu toate acestea, în practică, continui să văd echipe care creează sinonime publice în implementările Oracle „doar pentru că o facem întotdeauna”. În schimb, în ​​echipele care folosesc SQL Server, nu văd crearea de sinonime publice stabilită ca o practică comună. Funcționalitatea există, dar nu este folosită des.

În SQL Server, schema implicită curentă pentru un utilizator este definită în configurația utilizatorului și poate fi schimbată oricând dacă aveți privilegii de „modificare utilizator”. Poate fi implementată aceeași metodologie descrisă mai sus pentru Oracle. Cu toate acestea, dacă această metodă nu este utilizată, sinonimele publice nu ar trebui să fie copiate.

Deoarece Microsoft SQL Server nu asociază un nou cont de utilizator cu propria sa schemă în mod implicit (așa cum o face Oracle), asocierea ar trebui să facă parte din scriptul standard de „creare utilizator”.

Mai jos este un exemplu de script care creează scheme de utilizator dedicate și atribuie una unui utilizator.

Mai întâi, creați scheme pentru noii utilizatori care trebuie să fie încorporați în baza de date numită DevelopmentDatabase (fiecare schemă trebuie creată în propriul lot):

 use DevelopmentDatabase; GO CREATE SCHEMA Dev1; GO CREATE SCHEMA Dev2; GO

În al doilea rând, creați primul utilizator cu schema implicită atribuită:

 CREATE LOGIN DevLogin123 WITH PASSWORD = 'first_pass123'; CREATE USER Dev1 FOR LOGIN DevLogin123 WITH DEFAULT_SCHEMA = Dev1; GO

În acest moment, schema implicită pentru utilizatorul Dev1 ar fi Dev1 .

Apoi, creați celălalt utilizator fără schemă implicită:

 CREATE LOGIN DevLogin321 WITH PASSWORD = 'second_pass321'; CREATE USER Dev2 FOR LOGIN DevLogin321; GO

Schema implicită pentru utilizatorul Dev2 este dbo .

Acum modificați utilizatorul Dev2 pentru a-și schimba schema implicită în Dev2 :

 ALTER USER Dev2 WITH DEFAULT_SCHEMA = Dev2; GO

Acum, schema implicită pentru utilizatorul Dev2 este Dev2 .

Acest script demonstrează două moduri de a atribui și de a modifica o schemă implicită pentru un utilizator în bazele de date Microsoft SQL Server. Deoarece SQL Server acceptă mai multe metode de autentificare a utilizatorilor (cea mai comună este autentificarea Windows) și integrarea utilizatorilor poate fi gestionată de administratorii de sistem, mai degrabă decât de DBA, metoda ALTER USER de atribuire/modificare a schemei implicite va fi mai utilizabilă.

Notă: am făcut ca numele schemei să fie identic cu numele unui utilizator. Nu trebuie să fie așa în SQL Server, dar este preferința mea pentru că (1) se potrivește cu modul în care se face în Oracle și (2) simplifică gestionarea utilizatorilor (abordând cea mai mare obiecție din partea unui DBA de a face acest lucru corect în primul rând) — cunoașteți numele unui utilizator și cunoașteți automat schema implicită a utilizatorului.

Concluzie : Sinonimele publice sunt un instrument important pentru construirea unui mediu de dezvoltare multi-utilizator stabil și bine protejat. Din păcate, în observația mea în industrie, este mai des folosit din motive greșite - lăsând echipele suferind confuzia și alte dezavantaje ale sinonimelor publice fără să-și dea seama de beneficiile lor. Schimbarea acestei practici pentru a obține beneficii reale din sinonimele publice poate aduce beneficii reale fluxului de lucru de dezvoltare al unei echipe.

Procese de management al accesului la baze de date și management al schimbărilor

Cum tocmai am vorbit despre sprijinul pentru dezvoltarea paralelă de către echipe mari, merită să abordăm un subiect separat și adesea neînțeles: procesele de control al schimbării.

Managementul schimbării devine adesea o formă de birocrație controlată de liderii echipelor și DBA, disprețuită de dezvoltatorii rebeli care vor să livreze totul dacă nu „ieri”, apoi „acum”.

În calitate de DBA, am pus întotdeauna bariere de protecție pe drum în baza de date „mea”. Și am un motiv foarte bun pentru asta: o bază de date este o resursă partajată.

Tweet

Într-un context de control al sursei, managementul schimbărilor este în general acceptat, deoarece permite unei echipe să revină de la un cod nou, dar spart, la un cod vechi, dar funcțional. Dar, într-un context de bază de date, managementul schimbării poate părea un set de bariere și restricții nerezonabile impuse de DBA: este o nebunie pură care încetinește inutil dezvoltarea!

Să lăsăm deoparte dezbaterea acestui dezvoltator: sunt DBA și nu voi arunca cu pietre în mine! În calitate de DBA, am pus întotdeauna bariere de protecție în baza de date „mea”. Și am un motiv foarte bun pentru asta: o bază de date este o resursă partajată.

Fiecare echipă de dezvoltare – și fiecare dintre dezvoltatorii săi – are un obiectiv foarte specific definit și un livrabil foarte specific. Singurul obiectiv care se află pe biroul unui DBA în fiecare zi este stabilitatea bazei de date ca resursă partajată. Un DBA are rolul unic într-o organizație de a supraveghea toate eforturile de dezvoltare din toate echipele și de a controla o bază de date la care toți dezvoltatorii o accesează. DBA este cel care se asigură că toate proiectele și toate procesele rulează fără a interfera unele cu altele și că fiecare are resursele necesare pentru a funcționa.

Problema este atunci când atât echipele de dezvoltare, cât și echipele DBA stau blocate în turnurile lor de fildeș.

Dezvoltatorii nu știu, nu au acces și nici măcar nu le pasă ce se întâmplă în baza de date atâta timp cât funcționează bine pentru ei. (Nu este rezultatul lor și nici nu le va afecta evaluarea performanței.)

Echipa DBA păstrează baza de date aproape de cufăr, protejând-o de dezvoltatorii care „nu știu nimic” despre ea, deoarece obiectivul echipei lor este stabilitatea bazei de date. Iar cea mai bună modalitate de a asigura stabilitatea este de a preveni modificările distructive - deseori rezultând într-o atitudine de a proteja baza de date de orice modificări cât mai mult posibil.

Aceste atitudini conflictuale față de o bază de date pot duce, după cum am văzut, la animozitate între echipele de dezvoltare și DBA și pot duce la un mediu nefuncțional. Dar DBA și echipa de dezvoltare trebuie să lucreze împreună pentru a atinge un obiectiv comun: furnizarea unei soluții de afaceri, care este ceea ce i-a reunit în primul rând.

Fiind de ambele părți ale diviziunii între dezvoltatori și DBA, știu că problema este ușor de rezolvat atunci când DBA înțeleg mai bine sarcinile și obiectivele comune ale echipelor de dezvoltare. Pe partea lor, dezvoltatorii trebuie să vadă o bază de date nu ca un concept abstract, ci ca o resursă partajată – și acolo, un DBA ar trebui să își asume rolul de educator.

Cea mai frecventă eroare pe care o fac DBA care nu sunt dezvoltatori este restricționarea accesului dezvoltatorului la dicționarul de date și la instrumentele de optimizare a codului. Accesul la vizualizările de catalog Oracle DBA_ , vizualizările dinamice V$ și tabelele SYS pare multor DBA drept „privilegiat DBA”, când, de fapt, acestea sunt instrumente de dezvoltare critice.

Același lucru este valabil și pentru SQL Server, cu o complicație: accesul la unele vizualizări de sistem nu poate fi acordat direct, dar este doar o parte a rolului bazei de date SYSADMIN și acest rol nu ar trebui să fie acordat niciodată în afara echipei DBA. Acest lucru poate fi rezolvat (și ar trebui să fie rezolvat în cazul migrării unui proiect de la Oracle la SQL Server) prin crearea de vizualizări și proceduri stocate care se execută cu privilegii SYSADMIN , dar care sunt accesibile utilizatorilor non-DBA. Aceasta este sarcina DBA de dezvoltare pe care trebuie să o facă pe măsură ce este configurat un nou mediu de dezvoltare SQL Server.

Protecția datelor este una dintre principalele responsabilități ale unui DBA. În ciuda acestui fapt, este destul de obișnuit ca echipele de dezvoltare să aibă acces deplin la datele de producție nefiltrate pentru a permite depanarea biletelor legate de date. Aceștia sunt aceiași dezvoltatori care au acces limitat la structura de date - structura care a fost creată de ei sau pentru ei în primul rând.

Când se stabilesc relații de lucru adecvate între echipele de dezvoltare și DBA, crearea unui proces bun de control al schimbării devine intuitivă. Specificul și provocarea managementului schimbărilor din partea bazei de date este rigiditatea și fluiditatea unei baze de date în același timp - structura este rigidă, datele sunt fluide.

Se întâmplă adesea ca managementul schimbărilor privind modificarea structurii, adică pe limbajul de definire a datelor sau DDL, să fie bine stabilit, în timp ce modificările datelor au puțin sau deloc în ceea ce privește managementul schimbării. Justificarea este simplă - datele se schimbă tot timpul.

Dar dacă ne uităm la asta mai atent, vom vedea că, în orice sistem, toate datele se încadrează într-una din două categorii: datele aplicației și datele utilizatorului.

Datele aplicației sunt un dicționar de date care definește comportamentul unei aplicații și este la fel de critic pentru procesele sale ca orice cod de aplicație. Modificările aduse acestor date ar trebui să facă obiectul unor procese stricte de control al modificărilor, la fel ca în cazul oricărei alte modificări ale aplicației. Pentru a crea transparență în procesul de control al modificărilor pentru modificările datelor aplicației, datele aplicației și datele utilizatorului ar trebui separate în mod explicit.

În Oracle, ar trebui să se facă plasând datele aplicației și ale utilizatorului, fiecare în propria sa schemă. În Microsoft SQL Server, ar trebui să se facă plasând fiecare într-o schemă separată sau – mult mai bine – într-o bază de date separată. Efectuarea acestor alegeri ar trebui să facă parte din planificarea migrării: Oracle are rezoluție nume pe două niveluri (schemă/proprietar – nume obiect), în timp ce SQL Server are rezoluție nume pe trei niveluri (bază de date – schemă/proprietar – nume obiect).

O sursă comună de confuzie între lumea Oracle și SQL Server sunt, poate în mod surprinzător, termenii bază de date și server :

Termenul SQL Server Termenul Oracle Definiție
Server baza de date (utilizată interschimbabil cu serverul în limbajul obișnuit, cu excepția cazului în care se referă în mod specific la hardware-ul serverului, sistemul de operare sau elementele de rețea; pot exista una sau mai multe baze de date pe un server fizic/virtual) O instanță care rulează care poate „vorbește” cu alte instanțe prin porturile de rețea
baza de date (parte a unui server, conține mai multe scheme/proprietari) schema/proprietar Gruparea de cel mai înalt nivel

Această confuzie de terminologie ar trebui să fie înțeleasă clar în proiectele de migrare pe mai multe platforme, deoarece interpretarea greșită a termenilor poate duce la decizii de configurare incorecte care sunt greu de abordat retroactiv.

Separarea corectă a datelor aplicației și utilizatorilor permite unei echipe DBA să abordeze a doua cea mai importantă preocupare: securitatea datelor utilizatorilor. Deoarece datele utilizatorilor se află separat, va fi foarte simplu să implementați o procedură de spargere a sticlei pentru accesul la datele utilizatorilor, în funcție de necesități.

Concluzie : Procesele de control al schimbării sunt critice în orice proiect. În ingineria software, managementul schimbărilor din partea bazei de date este adesea neglijat, deoarece datele sunt considerate a fi „prea fluide”. Dar tocmai pentru că datele sunt „fluide” și „persistente” în același timp, un proces de control al schimbării bine conceput ar trebui să fie piatra de temelie a arhitecturii adecvate a mediului de baze de date.

Despre utilizarea instrumentelor de migrare a codului

Instrumentele standard de la prima parte, Oracle Migration Workbench și SQL Server Migration Assistant, pot fi utile în migrarea codului. Dar ceea ce trebuie luat în considerare este regula 80/20: când codul va fi migrat 80% corect, rezolvarea celor 20% rămase va necesita 80% din efortul dvs. de migrare.

Cel mai mare risc în utilizarea instrumentelor de migrare este de departe percepția „glonț de argint”. Cineva poate fi tentat să se gândească: „Va face treaba și va trebui doar să fac un pic de curățare și ordine.” Am observat un proiect care a eșuat din cauza unei astfel de atitudini din partea echipei de conversie și a conducerii sale tehnice.

Pe de altă parte, mi-au luat patru zile lucrătoare pentru a realiza conversia de bază a unui sistem Microsoft SQL Server 2008 de dimensiuni medii (aproximativ 200 de obiecte) folosind funcționalitatea de înlocuire în bloc a Notepad++ ca instrument principal de editare.

Niciunul dintre elementele critice de migrare pe care le-am abordat până acum nu poate fi rezolvat prin instrumente de migrare.

Sigur, folosiți instrumente de asistență pentru migrare, dar rețineți că acestea oferă doar asistență pentru editare. Textul de ieșire rezultat trebuie să aibă revizuire, modificare și, în unele cazuri, rescriere pentru a deveni cod demn de producție.

Dezvoltarea instrumentelor de inteligență artificială poate aborda aceste deficiențe ale instrumentelor de migrare în viitor, dar m-aș aștepta ca diferențele dintre bazele de date să se estompeze înainte de atunci și ca orice proces de migrare în sine să devină inutil. Așadar, atâta timp cât sunt necesare aceste tipuri de proiecte, va trebui să o facem în mod vechi, folosind inteligența umană de modă veche.

Concluzie : Utilizarea instrumentelor de asistență pentru migrare este utilă, dar nu este un „glonț de argint” și orice proiect de conversie necesită totuși o revizuire detaliată a punctelor de mai sus.

Migrații Oracle/SQL Server: Priviți întotdeauna mai atent

Oracle și Microsoft SQL Server sunt cele mai proliferate două platforme RDBMS în mediul de întreprindere. Ambele au conformitate de bază cu standardul ANSI SQL, iar segmentele mici de cod pot fi mutate cu foarte puține modificări sau chiar așa cum sunt.

Această similitudine creează o impresie înșelătoare că migrarea pe cele două platforme este o sarcină simplă și simplă și că aceeași aplicație poate fi adoptată cu ușurință de la utilizarea unui backend RDBMS la altul.

În practică, astfel de migrări ale platformei sunt departe de a fi banale și trebuie să țină cont de elementele fine ale funcționării interioare a fiecărei platforme și, mai ales, de modul în care implementează suport pentru cel mai critic element al managementului datelor: tranzacțiile.

Deși am acoperit două platforme RDBMS care se află în centrul experienței mele, același avertisment — „arata la fel nu înseamnă că funcționează la fel” — ar trebui aplicat pentru mutarea codului între orice alte sisteme de gestionare a bazelor de date compatibile cu SQL. Și în toate cazurile, primul punct de atenție ar trebui să fie asupra modului în care implementarea managementului tranzacțiilor diferă între platforma sursă și țintă.