[{"content":"Mesajul pe canalul Slack al echipei de infrastructură era din acelea care te fac să ridici capul de la ecran: \u0026ldquo;Disc la 95% pe db-ul de producție. Cine poate să se uite?\u0026rdquo;\nServerul era un MySQL 8.0 pe Rocky Linux, un sistem de gestiune folosit de aproximativ o sută de utilizatori. Baza de date în sine ocupa circa 40 GB — nimic extraordinar. Dar în directorul de date se aflau 180 GB de binary log. Șase luni de binlog pe care nimeni nu se gândise să le gestioneze.\nNu e prima dată când văd acest scenariu. De fapt, aș spune că este unul dintre cele mai recurente pattern-uri din tichetele care îmi ajung pe masă. Binary log-ul este una din acele funcționalități MySQL care lucrează în tăcere, fără să ceară nimic — până când discul se umple.\nCe sunt binary log-urile, concret #Binary log -ul este un registru secvențial al tuturor evenimentelor care modifică datele din baza de date. Fiecare INSERT, UPDATE, DELETE, fiecare DDL — totul se scrie în fișiere binare numerotate progresiv: mysql-bin.000001, mysql-bin.000002 și așa mai departe.\nNumele este ușor înșelător. Nu e un \u0026ldquo;log\u0026rdquo; în sensul syslog-ului sau al error log-ului — nu este făcut pentru a fi citit de un om. Este un flux binar structurat pe care MySQL îl folosește intern pentru două scopuri fundamentale:\nReplicare: slave-ul citește binlog-urile master-ului pentru a replica aceleași operațiuni Point-in-time recovery (PITR) : după restaurarea unui backup, poți \u0026ldquo;reaplica\u0026rdquo; binlog-urile pentru a aduce datele până la un moment precis Fără binary log, nu poți face nici una, nici cealaltă. Acesta e motivul pentru care primul instinct — \u0026ldquo;dezactivăm binlog-urile ca să nu umple discul\u0026rdquo; — este aproape întotdeauna greșit.\nCum generează MySQL binlog-urile #Binary logging-ul se activează prin parametrul log_bin. De la MySQL 8.0 este activat implicit — o schimbare importantă față de versiunile anterioare unde trebuia activat explicit.\n[mysqld] log_bin = /var/lib/mysql/mysql-bin server-id = 1 MySQL creează un nou fișier binlog în mai multe circumstanțe:\nCând serverul pornește sau repornește Când fișierul curent atinge dimensiunea definită de max_binlog_size (implicit: 1 GB) Când execuți FLUSH BINARY LOGS Când are loc o rotație manuală Fiecare fișier binlog are un fișier index asociat (mysql-bin.index) care ține evidența tuturor fișierelor binlog active. Acest fișier este critic: dacă îl corupi sau îl editezi manual, MySQL nu mai știe ce binlog-uri există.\nSHOW BINARY LOGS; +------------------+-----------+ | Log_name | File_size | +------------------+-----------+ | mysql-bin.000147 | 1073741824| | mysql-bin.000148 | 1073741824| | mysql-bin.000149 | 1073741824| | ... | | | mysql-bin.000318 | 524288000| +------------------+-----------+ 172 rows in set O sută șaptezeci și două de fișiere. Fiecare de aproximativ un gigabyte. Calculul se confirmă: 180 GB de binlog-uri niciodată purgate.\nRolul în replicare #Într-o arhitectură master-slave, binary log-ul este mecanismul de transport al datelor. Fluxul este acesta:\nMaster-ul scrie fiecare tranzacție în binlog Slave-ul are un thread (I/O thread) care se conectează la master și citește binlog-urile Slave-ul scrie ce primește în propriul relay log Un al doilea thread (SQL thread) pe slave execută evenimentele din relay log Aceasta înseamnă că binlog-urile pe master trebuie să rămână disponibile până când toate slave-urile le-au citit. Dacă ștergi un binlog pe care slave-ul nu l-a consumat încă, replicarea se rupe.\nÎnainte de a atinge orice binlog pe un master, comanda de executat este:\nSHOW REPLICA STATUS\\G -- sau, pe versiuni mai vechi: SHOW SLAVE STATUS\\G Câmpul care interesează este Relay_Master_Log_File (sau Source_Log_File în versiunile recente): îți spune ce binlog citește slave-ul în acel moment. Toate fișierele anterioare sunt sigure de eliminat.\nPoint-in-time recovery: celălalt motiv pentru care binlog-urile există #Al doilea uz — adesea subestimat — este point-in-time recovery. Scenariul este acesta: ai un backup făcut la ora 3 noaptea. La 14:30 cineva execută un DROP TABLE greșit. Fără binlog, poți restaura backup-ul și pierzi tot ce s-a întâmplat între 3:00 și 14:30. Cu binlog-urile, faci restore-ul și apoi reaplici binlog-urile până la 14:29.\n# Găsirea evenimentului DROP TABLE mysqlbinlog --start-datetime=\u0026#34;2026-03-30 14:00:00\u0026#34; \\ --stop-datetime=\u0026#34;2026-03-30 15:00:00\u0026#34; \\ /var/lib/mysql/mysql-bin.000318 | grep -i \u0026#34;DROP\u0026#34; # Reaplicarea binlog-urilor până în momentul dinaintea dezastrului mysqlbinlog --stop-datetime=\u0026#34;2026-03-30 14:29:00\u0026#34; \\ /var/lib/mysql/mysql-bin.000310 \\ /var/lib/mysql/mysql-bin.000311 \\ ... \\ /var/lib/mysql/mysql-bin.000318 | mysql -u root -p În practică, binlog-urile sunt asigurarea ta. Backup-ul este baza, binlog-urile acoperă delta. Ștergerea binlog-urilor fără un backup recent e ca și cum ai anula asigurarea cu o zi înainte de furtună.\nPURGE BINARY LOGS: modul corect de a face curățenie #Ne întoarcem la serverul nostru cu discul la 95%. Tentația de a face un rm -f mysql-bin.* e puternică. Dar e greșită, din două motive:\nMySQL nu știe că ai șters fișierele — fișierul index încă arată spre binlog-uri care nu mai există Dacă există o replică activă, riști să rupi sincronizarea Modul corect este comanda PURGE:\n-- Eliminarea tuturor binlog-urilor anterioare unui fișier specific PURGE BINARY LOGS TO \u0026#39;mysql-bin.000300\u0026#39;; -- Sau eliminarea tuturor binlog-urilor mai vechi decât o anumită dată PURGE BINARY LOGS BEFORE \u0026#39;2026-03-01 00:00:00\u0026#39;; PURGE face trei lucruri pe care rm nu le face:\nActualizează fișierul index Verifică dacă fișierele nu sunt necesare pentru replicare (teoretic — dar verifică tu mai întâi) Elimină fișierele în mod ordonat În cazul serverului nostru, mai întâi am verificat că nu existau slave-uri:\nSHOW REPLICAS; -- Empty set Nicio replică. Apoi am verificat care era binlog-ul curent:\nSHOW MASTER STATUS; +------------------+----------+ | File | Position | +------------------+----------+ | mysql-bin.000318 | 52428800 | +------------------+----------+ Păstrând ultimele 3 fișiere pentru siguranță:\nPURGE BINARY LOGS TO \u0026#39;mysql-bin.000316\u0026#39;; Rezultat: 175 GB eliberate în câteva secunde. Discul a coborât de la 95% la 28%.\nConfigurarea retenției automate #Rezolvarea urgenței e un lucru. A face ca problema să nu se mai repete e altceva. MySQL oferă doi parametri pentru gestionarea automată a retenției:\nexpire_logs_days (legacy) #[mysqld] expire_logs_days = 14 Elimină automat binlog-urile mai vechi de 14 zile. Simplu dar grosier — granularitatea este doar în zile.\nbinlog_expire_logs_seconds (MySQL 8.0+) #[mysqld] binlog_expire_logs_seconds = 1209600 # 14 zile în secunde Aceeași logică, dar cu granularitate la secundă. De la MySQL 8.0, acest parametru are prioritate asupra expire_logs_days. Dacă le setezi pe amândouă, câștigă binlog_expire_logs_seconds.\nÎntrebarea pe care mi-o pun mereu este: \u0026ldquo;Câte zile de retenție?\u0026rdquo;\nDepinde. Dar iată regulile mele practice:\nScenariu Retenție recomandată Server standalone, backup zilnic 7 zile Master cu replică, backup zilnic 7-14 zile Master cu replică lentă sau în zone diferite 14-30 zile Medii reglementate (finanțe, sănătate) 30-90 zile, cu arhivare Principiul este: retenția binlog-urilor trebuie să acopere cel puțin dublul intervalului dintre două backup-uri. Dacă faci backup în fiecare noapte, păstrează cel puțin 2-3 zile de binlog. Dacă faci backup săptămânal, cel puțin 14 zile.\nÎn cazul serverului nostru, nu fusese configurată nicio retenție. Valoarea implicită a MySQL 8.0 este 30 de zile — dar acea valoare fusese suprascrisă la 0 (fără expirare) într-un my.cnf personalizat de cineva care \u0026ldquo;voia să păstreze totul pentru siguranță\u0026rdquo;. Ironia: siguranța pe care voia s-o garanteze era pe cale să prăbușească serverul umplând discul.\nCele trei formate ale binlog-ului: STATEMENT, ROW, MIXED #Nu toate binlog-urile sunt la fel. MySQL suportă trei formate de înregistrare, iar alegerea are implicații concrete.\nSTATEMENT #Înregistrează instrucțiunea SQL așa cum a fost executată. Compact, lizibil, dar problematic: funcții ca NOW(), UUID(), RAND() produc rezultate diferite pe master și pe slave. Query-urile cu LIMIT fără ORDER BY pot produce rezultate nedeterministe.\nSET binlog_format = \u0026#39;STATEMENT\u0026#39;; ROW #Înregistrează modificarea la nivel de rând — înainte și după. Mai greu ca spațiu, dar determinist 100%. Dacă actualizezi 10.000 de rânduri, binlog-ul conține 10.000 de imagini before/after. Mare, dar sigur.\nSET binlog_format = \u0026#39;ROW\u0026#39;; MIXED #MySQL decide de la caz la caz: folosește STATEMENT când e sigur, trece automat la ROW când detectează operațiuni nedeterministe.\nSET binlog_format = \u0026#39;MIXED\u0026#39;; Sfatul meu: folosește ROW. Este valoarea implicită de la MySQL 5.7.7, este ceea ce Galera Cluster cere, este ceea ce toate tool-urile moderne de replicare așteaptă. STATEMENT este o moștenire din trecut, MIXED este un compromis care adaugă complexitate fără un beneficiu real.\nSingurul caz în care ROW devine o problemă este când faci operațiuni masive — un UPDATE pe milioane de rânduri generează un binlog enorm pentru că conține before și after-ul fiecărui rând. În acele cazuri, soluția nu e să schimbi formatul, ci să spargi operațiunea în batch-uri:\n-- În loc de asta (generează binlog gigantic): UPDATE orders SET status = \u0026#39;archived\u0026#39; WHERE order_date \u0026lt; \u0026#39;2025-01-01\u0026#39;; -- Mai bine așa (batch-uri de 10.000): UPDATE orders SET status = \u0026#39;archived\u0026#39; WHERE order_date \u0026lt; \u0026#39;2025-01-01\u0026#39; AND status != \u0026#39;archived\u0026#39; LIMIT 10000; -- Repetă până la 0 rows affected mysqlbinlog: citirea binlog-urilor când e nevoie #Tool-ul de linie de comandă `mysqlbinlog` este singura modalitate de a inspecta conținutul fișierelor binlog. Se folosește în două scenarii: debug la probleme de replicare și point-in-time recovery.\n# Citirea unui binlog în format lizibil mysqlbinlog /var/lib/mysql/mysql-bin.000318 # Filtrare pe interval de timp mysqlbinlog --start-datetime=\u0026#34;2026-03-30 10:00:00\u0026#34; \\ --stop-datetime=\u0026#34;2026-03-30 11:00:00\u0026#34; \\ /var/lib/mysql/mysql-bin.000318 # Filtrare pe bază de date specifică mysqlbinlog --database=gestionale /var/lib/mysql/mysql-bin.000318 # Dacă formatul e ROW, decodificare în SQL lizibil mysqlbinlog --verbose /var/lib/mysql/mysql-bin.000318 Cu format ROW, fără --verbose vezi doar blob-uri binare. Cu --verbose obții rândurile în format pseudo-SQL comentat — nu e frumos, dar se poate citi.\nPrincipiul: gestionează binlog-urile, nu le dezactiva #Din când în când cineva sugerează să rezolvi problema \u0026ldquo;din rădăcină\u0026rdquo; dezactivând binlog-urile:\n# NU FACE ASTA în producție skip-log-bin Da, rezolvă problema discului. Dar elimină:\nPosibilitatea de a configura o replică în viitor Point-in-time recovery Capacitatea de a analiza ce s-a întâmplat în baza de date după un incident Compatibilitatea cu instrumente de CDC (Change Data Capture) precum Debezium Binlog-urile nu sunt o problemă. Binlog-urile negestionate sunt o problemă. Diferența este un parametru de configurare și o verificare săptămânală. Pe serverul pe care l-am reparat, configurația finală a fost:\n[mysqld] log_bin = /var/lib/mysql/mysql-bin server-id = 1 binlog_format = ROW binlog_expire_logs_seconds = 604800 # 7 zile max_binlog_size = 512M Un max_binlog_size de 512 MB în loc de 1 GB implicit — fișierele mai mici sunt mai ușor de gestionat, transferat și purgat. Retenția la 7 zile, cu backup zilnic, garantează acoperire PITR completă cu ocupare de disc predictibilă.\nVerificare post intervenție #Înainte de a închide tichetul, am adăugat câteva query-uri la sistemul de monitorizare al clientului:\n-- Spațiu ocupat de binlog-uri SELECT COUNT(*) AS num_files, ROUND(SUM(file_size) / 1024 / 1024 / 1024, 2) AS total_gb FROM information_schema.BINARY_LOGS; -- MySQL 8.0+ / Performance Schema -- Sau, pentru toate versiunile: SHOW BINARY LOGS; -- și adună manual sau prin script # Alertă dacă binlog-urile depășesc 20 GB #!/bin/bash BINLOG_SIZE=$(mysql -u monitor -p\u0026#39;pwd\u0026#39; -Bse \\ \u0026#34;SELECT ROUND(SUM(file_size)/1024/1024/1024,2) FROM performance_schema.binary_log_status\u0026#34; 2\u0026gt;/dev/null) # Fallback pentru versiuni fără performance_schema.binary_log_status if [ -z \u0026#34;$BINLOG_SIZE\u0026#34; ]; then BINLOG_SIZE=$(du -sh /var/lib/mysql/mysql-bin.* 2\u0026gt;/dev/null | \\ awk \u0026#39;{sum+=$1} END {printf \u0026#34;%.2f\u0026#34;, sum/1024}\u0026#39;) fi if (( $(echo \u0026#34;$BINLOG_SIZE \u0026gt; 20\u0026#34; | bc -l) )); then echo \u0026#34;WARNING: binlog size ${BINLOG_SIZE} GB\u0026#34; fi La trei săptămâni după intervenție, binlog-urile ocupau 8 GB — exact în fereastra prevăzută. Discul nu a mai depășit 45%.\nBinlog-ul e ca uleiul de motor: nu te gândești niciodată la el până nu se aprinde martorul. Diferența e că motorul te avertizează. MySQL nu — continuă să scrie binlog-uri atâta timp cât filesystem-ul răspunde. Când nu mai răspunde, e prea târziu să te întrebi de ce nu configuraseși retenția.\nGlosar #Binary log — Registrul binar secvențial al MySQL care urmărește toate modificările de date (INSERT, UPDATE, DELETE, DDL), folosit pentru replicare și point-in-time recovery. Activat implicit de la MySQL 8.0.\nPITR — Point-in-Time Recovery: tehnică de restaurare care combină un backup complet cu binary log-urile pentru a readuce baza de date la orice moment în timp, nu doar la momentul backup-ului.\nRelay log — Fișier de log intermediar pe slave-ul MySQL care primește evenimentele din binary log-ul master-ului înainte de a fi executate local de thread-ul SQL.\nCDC — Change Data Capture: tehnică pentru interceptarea modificărilor de date în timp real prin citirea log-urilor de tranzacții. Instrumente precum Debezium citesc binary log-urile MySQL pentru a propaga modificările către sisteme externe.\nmysqlbinlog — Utilitar de linie de comandă MySQL pentru citirea, filtrarea și reaplicarea conținutului fișierelor binary log. Esențial pentru point-in-time recovery și debug-ul replicării.\n","date":"31 martie 2026","permalink":"https://ivanluminaria.com/ro/posts/mysql/binary-log-mysql/","section":"Database Strategy","summary":"\u003cp\u003eMesajul pe canalul Slack al echipei de infrastructură era din acelea care te fac să ridici capul de la ecran: \u0026ldquo;Disc la 95% pe db-ul de producție. Cine poate să se uite?\u0026rdquo;\u003c/p\u003e\n\u003cp\u003eServerul era un MySQL 8.0 pe Rocky Linux, un sistem de gestiune folosit de aproximativ o sută de utilizatori. Baza de date în sine ocupa circa 40 GB — nimic extraordinar. Dar în directorul de date se aflau 180 GB de binary log. Șase luni de binlog pe care nimeni nu se gândise să le gestioneze.\u003c/p\u003e","title":"Binary log în MySQL: ce sunt, cum le gestionezi și când le poți șterge"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/binlog/","section":"Tags","summary":"","title":"Binlog"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/categories/","section":"Categories","summary":"","title":"Categories"},{"content":" Diferența dintre un sistem care funcționează\nși unul care susține cu adevărat businessul nu este noroc.\nEste înțelegerea profundă a planurilor de execuție.\nEste controlul privilegiilor și securitatea datelor.\nEste modelarea datelor aliniată obiectivelor de business.\nEste performanță care rezistă pe măsură ce încărcarea crește.\nBazele de date reprezintă nucleul operațional al ecosistemului digital modern.\nSusțin procese critice, permit decizii bazate pe date și determină viteza și eficiența operațională.\nÎn Interiorul Motorului este spațiul în care analizez ce se întâmplă sub capota PostgreSQL, Oracle și MySQL: optimizare de performanță, securitate, arhitectură și decizii tehnice aplicabile în medii reale de producție.\nPentru că în lumea actuală orientată pe date, bazele de date nu sunt simple componente software.\nSunt active strategice care influențează competitivitatea, fiabilitatea și creșterea sustenabilă.\n","date":null,"permalink":"https://ivanluminaria.com/ro/posts/","section":"Database Strategy","summary":"\u003cblockquote\u003e\n\u003cp\u003eDiferența dintre un sistem care funcționează\u003cbr\u003e\nși unul care susține cu adevărat businessul nu este noroc.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eEste înțelegerea profundă a planurilor de execuție.\u003cbr\u003e\nEste controlul privilegiilor și securitatea datelor.\u003cbr\u003e\nEste modelarea datelor aliniată obiectivelor de business.\u003cbr\u003e\nEste performanță care rezistă pe măsură ce încărcarea crește.\u003cbr\u003e\u003c/p\u003e\n\u003cp\u003eBazele de date reprezintă nucleul operațional al ecosistemului digital modern.\u003cbr\u003e\nSusțin procese critice, permit decizii bazate pe date și determină viteza și eficiența operațională.\u003cbr\u003e\u003c/p\u003e\n\u003cp\u003eÎn Interiorul Motorului este spațiul în care analizez ce se întâmplă sub capota PostgreSQL, Oracle și MySQL: optimizare de performanță, securitate, arhitectură și decizii tehnice aplicabile în medii reale de producție.\u003cbr\u003e\u003c/p\u003e","title":"Database Strategy"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/disk-space/","section":"Tags","summary":"","title":"Disk-Space"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/","section":"Ivan Luminaria","summary":"","title":"Ivan Luminaria"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/mariadb/","section":"Tags","summary":"","title":"Mariadb"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/categories/mysql/","section":"Categories","summary":"","title":"Mysql"},{"content":"MySQL este baza de date care nu mai are nevoie de prezentare.\nEste motorul care a alimentat creșterea web-ului timp de peste douăzeci de ani.\nNăscut în 1995 în Suedia, în 2008 a fost achiziționat de Sun Microsystems — iar când Oracle a finalizat achiziția Sun în 2010, MySQL a ajuns în portofoliul celui mai mare furnizor de baze de date comerciale din lume. Eram angajat Oracle în acea perioadă și îmi amintesc bine atmosfera: pe de o parte curiozitatea de a vedea cum va gestiona Oracle un produs open source atât de popular, pe de altă parte teama că MySQL va fi marginalizat în favoarea bazei de date proprietare.\nAcea teamă l-a determinat pe Michael „Monty\u0026quot; Widenius — creatorul original al MySQL — să facă fork-ul în 2009, dând naștere MariaDB. Un proiect care împărtășește rădăcinile cu MySQL dar a luat propriile direcții pe motoare de stocare, optimizator și funcționalități avansate.\nIstoria a demonstrat că ambele proiecte au supraviețuit și au evoluat, dar alegerile lor arhitecturale diverge din ce în ce mai mult. Cunoașterea diferențelor nu este academică — este o necesitate operațională.\nÎn această secțiune explorez MySQL și MariaDB din perspectivă operațională: securitate, gestionarea utilizatorilor, performanță și decizii de proiectare care fac diferența în medii de producție.\nPentru că utilizarea MySQL nu înseamnă doar executarea de interogări.\nÎnseamnă înțelegerea modului în care motorul gestionează conexiunile, privilegiile și resursele sub sarcină reală.\n","date":null,"permalink":"https://ivanluminaria.com/ro/posts/mysql/","section":"Database Strategy","summary":"\u003cp\u003eMySQL este baza de date care nu mai are nevoie de prezentare.\u003cbr\u003e\nEste motorul care a alimentat creșterea web-ului timp de peste douăzeci de ani.\u003cbr\u003e\u003c/p\u003e\n\u003cp\u003eNăscut în 1995 în Suedia, în 2008 a fost achiziționat de Sun Microsystems — iar când Oracle a finalizat achiziția Sun în 2010, MySQL a ajuns în portofoliul celui mai mare furnizor de baze de date comerciale din lume. Eram angajat Oracle în acea perioadă și îmi amintesc bine atmosfera: pe de o parte curiozitatea de a vedea cum va gestiona Oracle un produs open source atât de popular, pe de altă parte teama că MySQL va fi marginalizat în favoarea bazei de date proprietare.\u003cbr\u003e\u003c/p\u003e","title":"MySQL"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/recovery/","section":"Tags","summary":"","title":"Recovery"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/replication/","section":"Tags","summary":"","title":"Replication"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/","section":"Tags","summary":"","title":"Tags"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/autovacuum/","section":"Tags","summary":"","title":"Autovacuum"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/bloat/","section":"Tags","summary":"","title":"Bloat"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/mvcc/","section":"Tags","summary":"","title":"Mvcc"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/performance/","section":"Tags","summary":"","title":"Performance"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/categories/postgresql/","section":"Categories","summary":"","title":"Postgresql"},{"content":"PostgreSQL nu este doar o bază de date open source.\nEste rezultatul a aproape patru decenii de evoluție academică și industrială.\nNăscut în 1986 la Universitatea Berkeley ca evoluție a Ingres, proiectul original POSTGRES a introdus concepte care la acea vreme erau avangardiste: extensibilitate, tipuri de date personalizate, reguli și un model relațional avansat.\nÎn 1996 a fost adăugat suportul SQL, iar numele a devenit PostgreSQL.\nLumea însă a continuat să-l numească simplu „Postgres”.\nȘi este perfect în regulă.\nÎn această secțiune explorez PostgreSQL din perspectivă arhitecturală și operațională: proiectare, performanță, securitate și decizii tehnice aplicabile în medii reale.\nPentru că alegerea PostgreSQL nu înseamnă doar alegerea unei baze de date open source.\nÎnseamnă alegerea unui motor conceput pentru a fi extins, analizat și înțeles în profunzime.\n","date":null,"permalink":"https://ivanluminaria.com/ro/posts/postgresql/","section":"Database Strategy","summary":"\u003cp\u003ePostgreSQL nu este doar o bază de date open source.\u003cbr\u003e\nEste rezultatul a aproape patru decenii de evoluție academică și industrială.\u003cbr\u003e\u003c/p\u003e\n\u003cp\u003eNăscut în 1986 la Universitatea Berkeley ca evoluție a Ingres, proiectul original POSTGRES a introdus concepte care la acea vreme erau avangardiste: extensibilitate, tipuri de date personalizate, reguli și un model relațional avansat.\u003cbr\u003e\u003c/p\u003e\n\u003cp\u003eÎn 1996 a fost adăugat suportul SQL, iar numele a devenit PostgreSQL.\u003cbr\u003e\nLumea însă a continuat să-l numească simplu „Postgres”.\u003cbr\u003e\nȘi este perfect în regulă.\u003cbr\u003e\u003c/p\u003e","title":"PostgreSQL"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/vacuum/","section":"Tags","summary":"","title":"Vacuum"},{"content":"Acum câțiva ani mi s-a cerut să verific un PostgreSQL în producție care \u0026ldquo;se încetinește în fiecare săptămână\u0026rdquo;. Mereu același tipar: luni merge bine, vineri e dezastru. În weekend cineva repornește serviciul și se începe de la capăt.\nBaza de date de aproximativ 200 GB. Tabelele principale ocupau aproape triplul spațiului efectiv al datelor. Query-uri care cădeau în sequential scan acolo unde nu ar fi trebuit. Timpii de răspuns creșteau zi de zi.\nAutovacuum era activ. Nimeni nu-l dezactivase. Dar nici nu-l configurase.\n🧠 MVCC: de ce PostgreSQL generează \u0026ldquo;gunoi\u0026rdquo; #Ca să înțelegi problema, trebuie un pas înapoi. PostgreSQL folosește MVCC — Multi-Version Concurrency Control. De fiecare dată când faci un UPDATE, baza de date nu suprascrie rândul original. Creează o versiune nouă și marchează pe cea veche ca \u0026ldquo;moartă\u0026rdquo;.\nLa fel pentru DELETE: rândul nu este șters fizic. Este marcat ca invizibil pentru tranzacțiile noi.\nAceste rânduri moarte se numesc dead tuples. Și rămân acolo, în paginile de date, ocupând spațiu pe disc și încetinind scanările.\nEste prețul pe care PostgreSQL îl plătește pentru izolarea tranzacțională fără lock-uri exclusive pe citiri. Un preț rezonabil — cu condiția ca cineva să facă curățenie.\n🔧 VACUUM: ce face de fapt #Comanda VACUUM face un lucru simplu: recuperează spațiul ocupat de dead tuples și îl face reutilizabil pentru inserări noi.\nNu returnează spațiu sistemului de operare. Nu reorganizează tabela. Nu compactează nimic. Marchează paginile ca rescriptibile.\nVACUUM reporting.transactions; Atât e suficient în majoritatea cazurilor. VACUUM este ușor, nu blochează scrierile și poate rula în paralel cu query-urile normale.\nDar VACUUM FULL? #VACUUM FULL e altă poveste. Rescrie fizic întreaga tabelă, eliminând tot spațiul mort. Returnează spațiu la filesystem.\nDar costul e brutal: ia un lock exclusiv pe tabelă pe toată durata operației. Nimeni nu citește, nimeni nu scrie. Pe tabele mari vorbim de minute sau ore.\nVACUUM FULL reporting.transactions; În producție, VACUUM FULL trebuie folosit foarte rar. În urgențe. Și întotdeauna în afara programului.\n⚙️ Autovacuum: paznicul tăcut #PostgreSQL are un daemon care rulează VACUUM automat: autovacuum.\nPornește când o tabelă acumulează destule dead tuples. Pragul se calculează astfel:\nvacuum threshold = autovacuum_vacuum_threshold + autovacuum_vacuum_scale_factor × n_live_tup Valorile implicite:\nautovacuum_vacuum_threshold: 50 dead tuples autovacuum_vacuum_scale_factor: 0.2 (20%) Tradus: pe o tabelă cu 10 milioane de rânduri, autovacuum pornește când dead tuples depășesc 2.000.050. Două milioane de rânduri moarte înainte ca cineva să facă curățenie.\nPentru o tabelă cu 500.000 de update-uri pe zi, asta înseamnă că autovacuum se activează poate la fiecare 4 zile. Între timp bloat-ul crește, scanările se încetinesc, indecșii se umflă.\nDe aceea luni totul mergea bine și vineri era dezastru.\n📊 Diagnostic: citirea pg_stat_user_tables #Primul lucru de făcut când suspectezi o problemă de vacuum este să interoghezi pg_stat_user_tables:\nSELECT schemaname, relname, n_live_tup, n_dead_tup, round(100.0 * n_dead_tup / NULLIF(n_live_tup + n_dead_tup, 0), 1) AS dead_pct, last_vacuum, last_autovacuum, autovacuum_count, vacuum_count FROM pg_stat_user_tables WHERE n_dead_tup \u0026gt; 10000 ORDER BY n_dead_tup DESC; În cazul clientului meu, situația arăta așa:\nrelname | n_live_tup | n_dead_tup | dead_pct | last_autovacuum -------------------+------------+------------+----------+------------------ transactions | 12.400.000 | 3.800.000 | 23,5% | acum 3 zile order_lines | 8.200.000 | 2.100.000 | 20,4% | acum 4 zile inventory_moves | 5.600.000 | 1.900.000 | 25,3% | acum 5 zile Aproape un sfert din rânduri erau moarte. Autovacuum rula, dar mult prea rar pentru a ține pasul.\n🎯 Tuning: adaptarea autovacuum la realitate #Trucul nu e să dezactivezi autovacuum. Niciodată. Trucul e să-l configurezi pentru tabelele care au nevoie.\nPostgreSQL permite setarea parametrilor de autovacuum per tabelă individuală:\nALTER TABLE reporting.transactions SET ( autovacuum_vacuum_scale_factor = 0.01, autovacuum_vacuum_threshold = 1000 ); Cu această setare, autovacuum pornește după 1.000 + 1% din rândurile vii de dead tuples. Pe 12 milioane de rânduri, se activează la ~121.000 dead tuples în loc de 2 milioane.\ncost_delay: nu sugruma vacuum-ul #Alt parametru critic este autovacuum_vacuum_cost_delay. Controlează cât de mult vacuum-ul \u0026ldquo;se frânează singur\u0026rdquo; pentru a nu suprasolicita I/O-ul.\nValoarea implicită e 2 milisecunde. Pe servere moderne cu SSD, e prea conservator. Reducerea la 0 sau 1 ms permite vacuum-ului să termine mai repede:\nALTER TABLE reporting.transactions SET ( autovacuum_vacuum_cost_delay = 0 ); max_workers #Valoarea implicită e 3 workeri de autovacuum. Dacă ai zeci de tabele cu trafic mare, 3 workeri nu sunt suficienți. Evaluează creșterea la 5–6, monitorizând impactul asupra CPU și I/O:\n-- în postgresql.conf autovacuum_max_workers = 5 📏 Măsurarea bloat-ului #Cum știi cât spațiu irosesc tabelele tale?\nQuery-ul clasic folosește pgstattuple:\nCREATE EXTENSION IF NOT EXISTS pgstattuple; SELECT pg_size_pretty(pg_total_relation_size(\u0026#39;reporting.transactions\u0026#39;)) AS total_size, pg_size_pretty(pg_total_relation_size(\u0026#39;reporting.transactions\u0026#39;) - pg_relation_size(\u0026#39;reporting.transactions\u0026#39;)) AS index_size, * FROM pgstattuple(\u0026#39;reporting.transactions\u0026#39;); Câmpurile cheie: dead_tuple_percent și free_space. Dacă dead_tuple depășește 20–30%, tabela are o problemă serioasă.\nO alternativă mai puțin precisă dar mai ușoară este estimarea bloat ratio comparând pg_class.relpages cu rândurile estimate — există query-uri consolidate în comunitate pentru asta (clasicul \u0026ldquo;bloat estimation query\u0026rdquo; de la PostgreSQL Experts).\n🛠️ Când VACUUM nu e suficient: pg_repack #Dacă bloat-ul a scăpat de sub control — tabele la 50–70% spațiu mort — VACUUM-ul normal nu recuperează totul. Eliberează dead tuples, dar spațiul fragmentat rămâne.\nVACUUM FULL funcționează, dar blochează totul.\nAlternativa în producție este pg_repack: reconstruiește tabela online, fără lock-uri exclusive prelungite.\npg_repack -d mydb -t reporting.transactions Nu e o soluție de folosit în fiecare săptămână. E cura de șoc pentru când situația a degenerat deja. Soluția reală e să nu ajungi acolo, cu un autovacuum bine configurat.\n💬 Principiul #Dezactivarea autovacuum este cel mai rău lucru pe care-l poți face unui PostgreSQL în producție. Am văzut-o făcută \u0026ldquo;pentru că încetinește query-urile în timpul zilei\u0026rdquo;. Sigur, pentru că între timp bloat-ul îți mănâncă baza de date din interior.\nAutovacuum cu valorile implicite PostgreSQL este proiectat pentru o bază de date generică. Nicio bază de date în producție nu e generică. Fiecare tabelă are propriul tipar de scriere, propriul volum, propriul ritm.\nTrei lucruri de reținut:\nVerifică pg_stat_user_tables regulat. Dacă n_dead_tup crește mai repede decât poate curăța autovacuum, ai o problemă.\nConfigurează scale_factor și threshold pentru tabelele cu trafic mare. Nu există o configurare universală.\nNu aștepta ca bloat-ul să ajungă la 50% pentru a interveni. În acel punct opțiunile sunt puține și toate dureroase.\nBazele de date nu se întrețin singure. Nici cele care au un daemon care încearcă.\nGlosar #VACUUM — Comandă PostgreSQL care recuperează spațiul ocupat de dead tuples, făcându-l reutilizabil pentru inserări noi fără a-l returna sistemului de operare.\nMVCC — Multi-Version Concurrency Control — modelul de concurență al PostgreSQL care menține mai multe versiuni ale rândurilor pentru a garanta izolarea tranzacțională fără lock-uri exclusive pe citiri.\nDead Tuple — Rând obsolet într-o tabelă PostgreSQL, marcat ca nevizibil după un UPDATE sau DELETE dar încă neșters fizic de pe disc.\nAutovacuum — Daemon PostgreSQL care rulează automat VACUUM și ANALYZE pe tabele când numărul de dead tuples depășește un prag configurabil.\nBloat — Spațiu mort acumulat într-o tabelă sau index PostgreSQL din cauza dead tuple-urilor neșterse, care umflă dimensiunea pe disc și degradează performanțele.\n","date":"24 martie 2026","permalink":"https://ivanluminaria.com/ro/posts/postgresql/vacuum-autovacuum-postgresql/","section":"Database Strategy","summary":"\u003cp\u003eAcum câțiva ani mi s-a cerut să verific un PostgreSQL în producție care\n\u0026ldquo;se încetinește în fiecare săptămână\u0026rdquo;. Mereu același tipar: luni merge\nbine, vineri e dezastru. În weekend cineva repornește serviciul și se\nîncepe de la capăt.\u003c/p\u003e\n\u003cp\u003eBaza de date de aproximativ 200 GB. Tabelele principale ocupau aproape\ntriplul spațiului efectiv al datelor. Query-uri care cădeau în\nsequential scan acolo unde nu ar fi trebuit. Timpii de răspuns creșteau\nzi de zi.\u003c/p\u003e","title":"VACUUM și autovacuum: de ce PostgreSQL are nevoie ca cineva să facă curățenie"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/ai/","section":"Tags","summary":"","title":"Ai"},{"content":"Acum câteva luni, într-o întâlnire cu un client din sectorul bancar, CTO-ul a spus ceva ce mi-a rămas în minte.\n„Avem nevoie de cineva care să gestioneze AI-ul. Nu cineva care îl folosește — cineva care îl guvernează.\u0026quot;\nAm dat din cap fără să vorbesc. Pentru că acea frază, în șapte secunde, descria un rol pe care piața îl caută fără să știe încă cum să-l numească.\n🧩 Neînțelegerea fundamentală #Există o confuzie răspândită, și o văd în fiecare proiect unde AI-ul intră în scenă.\nConfuzia este aceasta: a crede că „a adopta AI\u0026quot; înseamnă a integra un model, a conecta un API, a face un asistent să genereze text sau cod.\nNu. Aceasta este partea tehnică. Partea operațională. Este munca unui data scientist sau a unui inginer ML. Muncă importantă, fără îndoială. Dar nu este munca celui care guvernează.\nA guverna AI-ul într-un proiect înseamnă a răspunde la întrebări la care niciun model nu poate răspunde în locul tău:\nUnde AI-ul generează valoare reală și unde generează doar entuziasm? Cât costă să-l menții, nu doar să-l implementezi? Ce se întâmplă când modelul greșește — și cine răspunde? Cum se integrează cu arhitecturile existente fără a compromite stabilitatea și securitatea? Cum se asigură coerența între guvernanța datelor, conformitate și automatizare? Dacă nu ai răspunsuri la aceste întrebări, nu guvernezi AI-ul. Îl suferi.\n🏗️ Nu este un rol nou. Este un rol care nu avea încă un nume #Când mă gândesc la asta, realizez că fac această muncă cu mult înainte ca cineva să inventeze eticheta „AI Manager\u0026quot;.\nTreizeci de ani de arhitecturi de date. Sisteme mission-critical în Telco, Banking, Asigurări, Administrație Publică. Medii în care datele nu sunt un activ de monetizat — sunt o infrastructură de protejat.\nÎn acele contexte am făcut întotdeauna același lucru: am conectat strategia la realitatea tehnică. Am tradus nevoile de business în soluții care funcționează cu adevărat, nu pe slide ci în producție. Am mediat între cei care vor totul imediat și cei care știu că anumite lucruri necesită timp și arhitectură.\nAI-ul nu a schimbat acest tipar. L-a făcut mai vizibil.\nPentru că AI-ul, spre deosebire de o bază de date sau de un ETL, este un subiect care entuziasmează boardurile și sperie inginerii. Toți vor o bucată, puțini știu unde s-o pună. Iar rolul celui care stă la mijloc — între entuziasmul managementului și prudența infrastructurii — devine crucial.\n📍 Unde AI-ul generează valoare reală (și unde nu) #Am învățat ceva în ultimii trei ani, lucrând cu AI-ul în contexte de proiect concrete: valoarea AI-ului nu se află aproape niciodată acolo unde cred oamenii.\nNu se află în generarea automată de cod. Nu în chatbotul care răspunde clienților. Nu în raportul care se scrie singur.\nValoarea reală se află în trei locuri:\n1. Accelerarea analizei\nAI-ul este devastator când trebuie să analizeze context. Să citească mii de linii de cod, să coreleze loguri, să identifice tipare. Ce unui senior îi costă două ore, AI-ul face în secunde. Nu mai bine — mai repede. Iar viteza, într-un proiect cu termene limită, înseamnă bani.\n2. Reducerea zgomotului decizional\nÎn orice proiect complex există un moment când informațiile sunt prea multe și echipa nu mai știe ce este urgent și ce este important. AI-ul poate face triaj. Poate clasifica, prioritiza, evidenția anomalii. Nu decide în locul tău — îți prezintă datele astfel încât decizia să devină mai clară.\n3. Documentație și transfer de cunoștințe\nNimeni nu documentează cu plăcere. Nimeni. AI-ul poate genera documentație din cod, commituri, issues. Nu perfectă, dar suficientă pentru a nu pierde cunoștințe când cineva pleacă din proiect. Iar cine a gestionat proiecte știe cât costă asta.\nTot restul — demo-urile care strălucesc, prezentările cu procente bolduite, vendorii care promit ROI cu trei cifre — este zgomot. AI Managerul este cel care separă semnalul de zgomot.\n⚖️ Triunghiul pe care PM-ul trebuie să-l guverneze #În fiecare proiect unde AI-ul intră într-un mediu reglementat, există un triunghi care revine mereu:\nGuvernanța datelor — Conformitate — Automatizare.\nPoți avea cea mai eficientă automatizare din lume, dar dacă încalcă politicile de guvernanță a datelor, este un risc. Poți avea o guvernanță impecabilă, dar dacă blochează orice formă de automatizare, proiectul nu avansează. Poți fi perfect conform, dar dacă nu știi ce date folosești pentru a antrena sau interoga modelul, conformitatea este doar pe hârtie.\nAI Managerul trebuie să mențină în echilibru aceste trei vârfuri. Continuu. Nu o dată la începutul proiectului — în fiecare săptămână.\nAm văzut proiecte în care AI-ul era integrat fără ca nimeni să fi verificat proveniența datelor de antrenament. În banking. Cu date supuse GDPR. DPO-ul a aflat la trei luni distanță.\nNu este incompetență. Este absența guvernanței. Este absența cuiva care să pună întrebarea corectă la momentul potrivit.\n🔬 A integra, nu a înlocui #Un lucru pe care îl repet în fiecare kickoff meeting: AI-ul se integrează în arhitecturile existente. Nu le înlocuiește.\nPare evident, dar tentația este întotdeauna aceeași: vendorul care propune să „regândim infrastructura în cheie AI\u0026quot;, consultantul care vrea o arhitectură greenfield, managerul care a văzut un demo și acum vrea totul nou.\nNu.\nArhitecturile mission-critical nu se aruncă pentru că a apărut o tehnologie nouă. Evoluează. Se extind. Se protejează.\nAI Managerul este cel care spune „acest model se conectează aici, cu aceste precauții, cu acest plan de fallback\u0026quot;. Nu cel care spune „aruncăm totul și refacem cu AI\u0026quot;.\nÎn treizeci de ani de sisteme, am văzut cel puțin cinci tehnologii „revoluționare\u0026quot; care trebuiau să schimbe totul. Client-server. Internet. Cloud. Big Data. Acum AI. Niciuna nu a schimbat totul. Fiecare a schimbat ceva. Iar cei care au guvernat bine schimbarea sunt cei care au integrat-o cu inteligență — nu cu entuziasm.\n🎯 De ce AI-ul nu este magie #Există o frază pe care o folosesc des, și nu obosesc s-o repet.\nAI-ul nu este magie. Este arhitectură aplicată inteligenței.\nUn model este o componentă. Ca o bază de date, ca un message broker, ca un load balancer. Are nevoie de inputuri curate, de monitoring, de mentenanță, de guvernanță. Are nevoie de cineva care înțelege ce face, ce poate face și mai ales ce nu poate face.\nProject Managerul care ignoră aceste aspecte și deleagă totul echipei tehnice comite aceeași greșeală ca cel care delega securitatea administratorului de sistem și apoi se mira de breșa de date.\nAI-ul este o responsabilitate arhitecturală. Și ca toate responsabilitățile arhitecturale, se guvernează de sus. Nu de jos.\n💬 Pentru cine decide dacă AI-ul „e necesar\u0026quot; în proiectul său #Dacă evaluezi să introduci AI-ul într-un proiect — nu într-un experiment, într-un proiect real, cu termene limită, buget și stakeholderi — îți dau un sfat care valorează mai mult decât orice instrument.\nNu porni de la tehnologie. Pornește de la problemă.\nCare este blocajul? Unde pierde echipa cel mai mult timp? Unde deciziile sunt mai lente decât ar trebui? Unde se pierde cunoașterea?\nDacă răspunsul la vreuna dintre aceste întrebări are legătură cu analiza unor volume mari de date, cu clasificarea informațiilor, cu accelerarea proceselor repetitive — atunci AI-ul te poate ajuta. Dar doar dacă cineva îl guvernează.\nIar a-l guverna nu înseamnă a-l controla. Înseamnă a-l înțelege suficient de bine pentru a ști când să te bazezi pe el și când nu.\nAceasta este munca AI Managerului. Și, indiferent cum îl numești, este un rol de care orice proiect serios va avea nevoie.\nGlosar #AI Manager — Rol profesional care guvernează impactul inteligenței artificiale asupra arhitecturilor, proceselor și persoanelor, separând valoarea reală de zgomot.\nData Governance — Set de politici, procese și standarde care garantează calitatea, securitatea și conformitatea datelor în cadrul unei organizații.\nKnowledge Transfer — Proces de transfer al cunoștințelor între persoane, echipe sau sisteme, critic în proiectele IT unde pierderea know-how-ului poate compromite continuitatea operațională.\nROI — Return on Investment — raportul între beneficiul obținut și costul suportat pentru o investiție.\nCompliance — Conformitate cu reglementările, regulile și standardele aplicabile — în contextul AI include GDPR, reglementări sectoriale și politici interne privind utilizarea datelor.\n","date":"17 martie 2026","permalink":"https://ivanluminaria.com/ro/posts/project-management/ai-manager-project-management/","section":"Database Strategy","summary":"\u003cp\u003eAcum câteva luni, într-o întâlnire cu un client din sectorul bancar, CTO-ul a spus ceva ce mi-a rămas în minte.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003e„Avem nevoie de cineva care să gestioneze AI-ul. Nu cineva care îl folosește — cineva care îl guvernează.\u0026quot;\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eAm dat din cap fără să vorbesc. Pentru că acea frază, în șapte secunde, descria un rol pe care piața îl caută fără să știe încă cum să-l numească.\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"-neînțelegerea-fundamentală\" class=\"relative group\"\u003e🧩 Neînțelegerea fundamentală \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#-ne%c3%aen%c8%9belegerea-fundamental%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eExistă o confuzie răspândită, și o văd în fiecare proiect unde AI-ul intră în scenă.\u003c/p\u003e","title":"AI Manager și Project Management: când inteligența artificială intră în proiecte"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/ai-manager/","section":"Tags","summary":"","title":"Ai-Manager"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/governance/","section":"Tags","summary":"","title":"Governance"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/categories/project-management/","section":"Categories","summary":"","title":"Project Management"},{"content":"Am văzut project manageri care au făcut dezvoltatori seniori să plângă în ședințe. Am văzut echipe strălucite distruse de PM-uri care confundau autoritatea cu autoritarismul. Am văzut software livrat „la timp\u0026quot; care nu funcționa, și proiecte de milioane de euro care s-au terminat în nimic.\nȘi am văzut exact opusul: echipe mici, autonome, respectate — care construiau sisteme solide într-o fracțiune din timp și buget.\nDiferența nu a fost niciodată tehnologia. A fost întotdeauna metoda.\nDupă treizeci de ani în acest mesteria, un lucru l-am înțeles: oamenii nu dau ce au mai bun când le este frică. Dau ce au mai bun când au încredere.\nÎncredere în echipă. Încredere în proces. Încredere că dacă greșesc, nu vor fi pedepsiți — vor fi ajutați.\nProject managerul care funcționează nu este cel care controlează, terorizează și numără orele. Este cel care:\ndefinește obiective clare și dă echipei libertatea de a le atinge construiește competențe profunde și le protejează de rotație face team building în fiecare zi, nu o dată pe an la karting măsoară rezultatele, nu orele la birou folosește smart working-ul ca avantaj competitiv, nu ca o concesie când ceva merge prost, se pune în fața echipei, nu în spatele ei 📊 Cum lucrez eu #Abordarea mea este Scrum — dar Scrum făcut pe bune, nu liturgia notițelor lipicioase.\nScrum-ul care funcționează se bazează pe un pact: transparență radicală, responsabilitate partajată și autonomie în „cum\u0026quot;. PM-ul definește ce și de ce. Echipa decide cum. Pentru că cine scrie codul știe mai bine decât oricine cum să-l scrie.\nȘi acest pact funcționează și mai bine în smart working. Daily standup-ul? 15 minute într-un call. Sprint review-ul? Screen sharing cu clientul, care vede software-ul — nu slide-urile. Retrospectiva? O oră în care echipa spune adevărul, pentru că nu are PM-ul la doi metri care se uită fix la ea.\nMăsor puține lucruri, dar le măsor bine:\nMetrică Ce spune Velocity Cât livrează echipa per sprint Lead time Cât trece de la cerere la lansare Bug escape rate Câte defecte scapă în producție Sprint goal success % din obiectivele de sprint atinse Team happiness Cum se simte echipa — cea mai importantă metrică Ultima — team happiness — este cea pe care PM-urile tradiționale nu o măsoară niciodată. O echipă fericită nu este o echipă care se distrează. Este o echipă care se simte respectată, ascultată și valorizată. Și o astfel de echipă produce mai mult. Nu pentru că lucrează mai multe ore. Pentru că lucrează mai bine.\n📚 Despre ce scriu aici #Povești reale, numere concrete și lecții învățate. Nimic teorie de manual. Doar ce am văzut că funcționează — și ce am văzut că eșuează.\nScriu despre inteligența artificială aplicată în workflow, despre consultanța IT și costurile ei ascunse, despre smart working ca avantaj competitiv. Fiecare articol provine dintr-o experiență reală — a mea.\nNu e nevoie de revoluții. E nevoie de alegeri precise, implementate cu metodă.\nȘi de capacitatea de a spune „nu\u0026quot; celor care îți vând complexitate când soluția este simplă.\n","date":null,"permalink":"https://ivanluminaria.com/ro/posts/project-management/","section":"Database Strategy","summary":"\u003cp\u003eAm văzut project manageri care au făcut dezvoltatori seniori să plângă în ședințe. Am văzut echipe strălucite distruse de PM-uri care confundau autoritatea cu autoritarismul. Am văzut software livrat „la timp\u0026quot; care nu funcționa, și proiecte de milioane de euro care s-au terminat în nimic.\u003c/p\u003e\n\u003cp\u003eȘi am văzut exact opusul: echipe mici, autonome, respectate — care construiau sisteme solide într-o fracțiune din timp și buget.\u003c/p\u003e\n\u003cp\u003eDiferența nu a fost niciodată tehnologia. A fost întotdeauna \u003cstrong\u003emetoda\u003c/strong\u003e.\u003c/p\u003e","title":"Project Management"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/project-management/","section":"Tags","summary":"","title":"Project-Management"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/strategy/","section":"Tags","summary":"","title":"Strategy"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/consulting/","section":"Tags","summary":"","title":"Consulting"},{"content":"Un data warehouse nu este o bază de date cu tabele mai mari.\nEste un mod diferit de a gândi datele — orientat spre analiză, istorie, decizii.\nDiferența dintre un DWH care funcționează și unul care devine o problemă stă aproape întotdeauna în model. Tabele de fapte cu granularitatea greșită, dimensiuni prost proiectate, ierarhii care nu suportă interogările de agregare. Probleme care nu se văd în faza de dezvoltare, dar explodează când business-ul cere rapoarte pe care modelul nu le poate livra.\nÎn această secțiune împărtășesc cazuri reale de proiectare și restructurare de data warehouse-uri: modelare dimensională, ierarhii echilibrate, slowly changing dimensions, strategii de încărcare. Nu teorie din cartea lui Kimball, ci soluții aplicate în producție pe sisteme care servesc decizii de afaceri reale.\nPentru că un data warehouse nu se construiește pentru a conține date.\nSe construiește pentru a răspunde la întrebări.\n","date":null,"permalink":"https://ivanluminaria.com/ro/posts/data-warehouse/","section":"Database Strategy","summary":"\u003cp\u003eUn data warehouse nu este o bază de date cu tabele mai mari.\u003cbr\u003e\nEste un mod diferit de a gândi datele — orientat spre analiză, istorie, decizii.\u003cbr\u003e\u003c/p\u003e\n\u003cp\u003eDiferența dintre un DWH care funcționează și unul care devine o problemă stă aproape întotdeauna în model. Tabele de fapte cu granularitatea greșită, dimensiuni prost proiectate, ierarhii care nu suportă interogările de agregare. Probleme care nu se văd în faza de dezvoltare, dar explodează când business-ul cere rapoarte pe care modelul nu le poate livra.\u003cbr\u003e\u003c/p\u003e","title":"Data Warehouse"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/european-union/","section":"Tags","summary":"","title":"European-Union"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/freelance/","section":"Tags","summary":"","title":"Freelance"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/italy/","section":"Tags","summary":"","title":"Italy"},{"content":"Oracle este baza de date care m-a format profesional.\nLucrez cu ea din 1996, și în aproape treizeci de ani am văzut trecând versiuni, paradigme și tendințe — dar inima motorului a rămas aceeași: solidă, complexă, neiertătoare cu cei care nu o cunosc în profunzime.\nAm gestionat instanțe cu câteva sute de utilizatori și data warehouse-uri cu miliarde de rânduri. Am configurat Data Guard când încă se numea standby database, am scris PL/SQL când depanarea însemna DBMS_OUTPUT și răbdare, am proiectat scheme de partiționare înainte ca acestea să devină o funcționalitate de marketing.\nOracle nu este o bază de date pe care o înveți din tutoriale.\nO înveți din incidente, din migrări la trei dimineața, din planuri de execuție care se schimbă după o actualizare a statisticilor.\nÎn această secțiune povestesc ce am învățat pe teren: arhitectură, securitate, performanță și deciziile de proiectare care separă o instalare care funcționează de una care doar supraviețuiește.\nPentru că la Oracle nu este suficient să cunoști sintaxa.\nTrebuie să înțelegi cum gândește motorul.\n","date":null,"permalink":"https://ivanluminaria.com/ro/posts/oracle/","section":"Database Strategy","summary":"\u003cp\u003eOracle este baza de date care m-a format profesional.\u003cbr\u003e\nLucrez cu ea din 1996, și în aproape treizeci de ani am văzut trecând versiuni, paradigme și tendințe — dar inima motorului a rămas aceeași: solidă, complexă, neiertătoare cu cei care nu o cunosc în profunzime.\u003cbr\u003e\u003c/p\u003e\n\u003cp\u003eAm gestionat instanțe cu câteva sute de utilizatori și data warehouse-uri cu miliarde de rânduri. Am configurat Data Guard când încă se numea standby database, am scris PL/SQL când depanarea însemna DBMS_OUTPUT și răbdare, am proiectat scheme de partiționare înainte ca acestea să devină o funcționalitate de marketing.\u003cbr\u003e\u003c/p\u003e","title":"Oracle"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/payments/","section":"Tags","summary":"","title":"Payments"},{"content":"Prima dată când am lucrat cu un client internațional, mi s-a întâmplat ceva ciudat. M-au plătit în treizeci de zile.\nNu treizeci de zile de la sfârșitul lunii. Nu treizeci de zile de la data primirii facturii înregistrate și vizate de responsabilul administrativ. Treizeci de zile de la factură. Punct.\nAm verificat extrasul de cont de două ori. Am crezut că este o greșeală.\nNu era o greșeală. Era normalitatea — doar că nu era normalitatea italiană.\n🇮🇹 Normalitatea italiană: a aștepta face parte din meserie #În Italia, dacă ești consultant IT ca freelancer, ciclul de plată funcționează cam așa:\nLucrezi în octombrie. Facturezi la sfârșitul lui octombrie. Factura intră în ciclul administrativ al clientului în noiembrie. Clientul plătește la \u0026ldquo;60 de zile sfârșitul lunii\u0026rdquo; — ceea ce în practică înseamnă sfârșitul lui ianuarie. Dacă totul merge bine. Dacă nu există blocaj de plăți de sfârșit de an. Dacă biroul administrativ nu a \u0026ldquo;pierdut\u0026rdquo; factura. Dacă responsabilul a semnat aprobarea. Rezultat: lucrezi în octombrie, vezi banii în februarie. Patru luni.\nȘi nu vorbesc despre situații patologice. Vorbesc despre practica contractuală standard în consultanța IT italiană. Contracte care specifică negru pe alb \u0026ldquo;plată la 60 de zile de la data facturii sfârșit de lună\u0026rdquo; sau, mai rău, \u0026ldquo;90 de zile de la data facturii sfârșit de lună.\u0026rdquo;\nAm văzut contracte la 120 de zile. O sută douăzeci de zile. Patru luni declarate prin contract, care în realitate devin cinci sau șase. Semnate fără să clipești, pentru că \u0026ldquo;așa funcționează\u0026rdquo; și pentru că consultantul care protestează este consultantul care nu mai este chemat înapoi.\n🇪🇺 Ce spune Europa (și ce Italia se preface că nu aude) #Directiva Europeană 2011/7/UE privind combaterea întârzierii în efectuarea plăților în tranzacțiile comerciale este clară. Cristalină, aș spune:\nRegulă Ce prevede Termen standard 30 de zile de la data facturii Termen maxim între întreprinderi 60 de zile (doar cu acord explicit și dacă nu este grav inechitabil) Termen pentru Administrația Publică 30 de zile (extensibil la 60 doar în cazuri excepționale) Dobânzi de întârziere automate Rata BCE + 8% — fără necesitatea unei puneri în întârziere Compensație forfetară pentru recuperare 40€ minim pentru fiecare factură plătită cu întârziere Treizeci de zile. Nu nouăzeci. Nu o sută douăzeci. Treizeci.\nDirectiva a fost transpusă în dreptul italian prin Decretul Legislativ 231/2002 (modificat în 2012). Pe hârtie, regulile există. În practică, e ca și cum nu ar exista.\n🇩🇪 Cum funcționează în restul Europei #Când le povestesc colegilor mei germani, olandezi sau scandinavi că în Italia termenele de plată standard sunt de 60-90 de zile, reacția este mereu aceeași: mai întâi uimire, apoi un râs nervos.\nÎn Germania termenul mediu de plată este de 24 de zile. Nu pentru că germanii sunt mai generoși — pentru că sistemul o impune. O plată peste 30 de zile generează automat dobânzi de întârziere. Companiile știu asta și plătesc.\nÎn Țările de Jos termenul mediu este de 27 de zile. Asociația patronală MKB-Nederland publică anual statistici despre întârzieri, iar companiile care nu respectă termenele ajung pe liste publice.\nÎn țările nordice — Suedia, Danemarca, Finlanda — a plăti la 14 zile este normal. La 30 este deja considerat mult.\nȘi Italia? Termenul mediu efectiv de plată în Italia este de 80 de zile conform European Payment Report. Optzeci. Aproape de trei ori media europeană.\nȚară Termen mediu de plată (zile) Suedia 27 Germania 24 Țările de Jos 27 Franța 44 Spania 56 Italia 80 Termenul maxim Directiva UE 60 Italia nu doar că este în afara scalei comparativ cu nordul Europei. Este în afara scalei comparativ cu propria sa lege.\n💰 Impactul real asupra celor care lucrează #Să luăm un exemplu concret. Un consultant IT senior care facturează 250€ pe zi, 220 de zile lucrătoare pe an.\nVenituri anuale brute: 55.000€.\nCu plăți la 30 de zile, fluxul de numerar este gestionabil. În fiecare lună intră munca din luna precedentă. Consultantul poate planifica, investi, plăti impozitele fără să intre pe minus.\nCu plăți la 90 de zile sfârșitul lunii, tabloul se schimbă radical:\nLuna Muncă efectuată Încasat Credit în așteptare Ianuarie 5.500€ 0€ 5.500€ Februarie 5.500€ 0€ 11.000€ Martie 5.500€ 0€ 16.500€ Aprilie 5.500€ 0€ 22.000€ Mai 5.500€ 5.500€ 22.000€ În primele patru luni ale anului, consultantul lucrează pe credit. Șaisprezece până la douăzeci de mii de euro de muncă efectuată și neplătită. Între timp, impozitele nu așteaptă. Contribuțiile sociale nu așteaptă. Chiria nu așteaptă.\nAcel consultant își finanțează clientul. Gratuit. Fără dobânzi. Fără garanții.\nDacă te gândești bine, este un împrumut. Doar că nimeni nu-l numește așa. Îl numesc \u0026ldquo;condiții contractuale.\u0026rdquo;\n🏦 Mecanismul pervers: cine plătește finanțează pe cine încasează #Paradoxul este structural. Marile companii de consultanță — cele cu sute de angajați și cifre de afaceri cu șapte cifre — negociază termene lungi cu furnizorii (adică consultanții) și termene mai scurte cu clienții finali. Diferența dintre încasare și plată devine un float financiar pe care compania îl folosește ca lichiditate la cost zero.\nConsultantul freelancer este veriga cea mai slabă din lanț. Nu are putere de negociere, nu are departament juridic, nu are alternative imediate. Acceptă cele 90 de zile pentru că piața funcționează așa și pentru că a refuza înseamnă a rămâne fără proiecte.\nAm văzut situații și mai creative:\nContracte care prevăd \u0026ldquo;90 de zile de la data aprobării pontajului\u0026rdquo; — unde aprobarea vine cu săptămâni de întârziere Facturi \u0026ldquo;blocate\u0026rdquo; pentru erori formale inventate, pentru a muta plata la ciclul următor Plăți fracționate fără motiv aparent, cu soldul final care ajunge după șase luni Nu sunt excepții. Sunt tactici consolidate. Fiecare consultant italian cu puțină experiență le recunoaște instantaneu.\n⚖️ De ce nimeni nu aplică legea #Întrebarea legitimă este: dacă legea prevede 30 de zile și dobânzile de întârziere sunt automate, de ce nu le solicită nimeni?\nRăspunsul este simplu și amar: pentru că costul reputațional este mai mare decât costul financiar.\nUn consultant care trimite o cerere formală de dobânzi de întârziere clientului său este un consultant care nu va mai fi chemat. Nu pentru că greșește — are dreptate, legal și moral. Dar pentru că piața de consultanță IT din Italia este o piață de relații, iar într-o piață de relații, cine își exercită drepturile este perceput ca \u0026ldquo;dificil.\u0026rdquo;\nEste același mecanism prin care nimeni nu cere orele suplimentare plătite, nimeni nu refuză deplasarea de vineri seara și nimeni nu contestă tariful care scade la fiecare reînnoire de contract.\nSistemul se bazează pe docilitatea structurală a consultantului. Și funcționează, atâta timp cât funcționează.\n🛠️ Ce poți face concret #Nu am soluții magice. Dar am strategii pe care le folosesc de ani de zile și care funcționează — sau cel puțin limitează pagubele.\n1. Negociază termenele ÎNAINTE de a semna #Pare evident, dar majoritatea consultanților semnează contractul fără să citească clauza de plată. Momentul de negociere este înainte, nu după. Un \u0026ldquo;plată la 30 de zile de la data facturii\u0026rdquo; scris în contract valorează mai mult decât orice protest ulterior.\n2. Include o clauză explicită de dobânzi de întârziere #Chiar dacă legea le prevede automat, scrierea lor în contract are un efect de descurajare. Clientul știe că nu glumești. Eu folosesc o formulă simplă: \u0026ldquo;În caz de întârziere la plată se aplică dobânzi de întârziere conform Decretului Legislativ 231/2002, egale cu rata BCE plus 8 puncte procentuale.\u0026rdquo;\n3. Diversifică-ți clienții #Consultantul cu un singur client este consultantul cel mai vulnerabil. Dacă 100% din veniturile tale depind de cineva care plătește la 120 de zile, nu ai putere de negociere. Dacă ai trei clienți și unul plătește cu întârziere cronică, îți poți permite să-l lași.\n4. Evaluează clientul și prin prisma punctualității plății #Înainte de a accepta un angajament, întreabă-ți colegii. Lumea consultanței IT este mică. Cine plătește prost se știe. Cine plătește bine, de asemenea. Eu mențin o listă mentală — și nu este scurtă.\n5. Consideră clienții internaționali #Nu din anti-patriotism, ci din pragmatism. Clienții din nordul Europei plătesc mai bine, plătesc mai repede și au procese administrative mai transparente. Cu munca la distanță, a lucra pentru o companie olandeză din Roma nu mai este science fiction. Este marțea mea.\n📊 O comparație care dă de gândit #Să luăm același consultant IT — aceleași competențe, aceeași experiență, același tip de proiect. Se schimbă doar țara clientului.\n🇮🇹 Client italian 🇩🇪 Client german Tarif zilnic 250€ 450€ Termen de plată contractual 90 zile sfârșit de lună 30 zile Plată efectivă medie ~120 zile ~28 zile Dobânzi de întârziere solicitate niciodată (de frică) nu sunt necesare (plătesc la timp) Proces de aprobare a facturii labirintic un email de confirmare Reînnoirea contractului \u0026ldquo;vă anunțăm noi\u0026rdquo; planificată cu 3 luni în avans Nu spun că a lucra cu clienți italieni este întotdeauna mai rău. Spun că cifrele povestesc o poveste precisă, iar a o ignora de dragul liniștii nu este profesionalism. Este resemnare.\n💬 O chestiune de respect #Întârzierea cronică a plăților nu este doar o problemă financiară. Este o problemă de respect profesional.\nCând o companie plătește un consultant la 120 de zile, îi transmite: \u0026ldquo;Timpul tău și munca ta pot aștepta. Programul nostru vine înaintea ta.\u0026rdquo;\nEste același mesaj pe care îl transmit când îți cer să începi \u0026ldquo;luni\u0026rdquo; dar contractul ajunge după trei săptămâni. Când pontajul trebuie completat la minut dar factura poate sta într-un sertar luni de zile. Când proiectul este extrem de urgent dar plata nu.\nAm treizeci de ani de consultanță în spate. Am lucrat cu clienți care m-au plătit în 14 zile și clienți care au avut nevoie de opt luni. Calitatea relației profesionale nu a fost niciodată o chestiune de buget. A fost întotdeauna o chestiune de cum tratează pe cei care lucrează pentru ei.\nCei mai buni clienți pe care i-am avut plăteau la timp. Nu din generozitate — din organizare. Pentru că o companie care știe să-și gestioneze plățile este o companie care știe să-și gestioneze proiectele. Și invers.\nCine plătește prost, aproape întotdeauna, gestionează prost și tot restul.\nGlosar #DSO — Days Sales Outstanding — numărul mediu de zile pe care o companie le necesită pentru a-și încasa creanțele. În Italia media este de 80 de zile, aproape de trei ori media europeană.\nFloat Financiar — Lichiditate la cost zero generată de diferența dintre timpii de încasare de la clienți și timpii de plată către furnizori.\nDobânzi de Întârziere — Dobânzi automate prevăzute de lege (rata BCE + 8%) care se acumulează pe fiecare factură plătită cu întârziere, fără necesitatea unei somații formale.\nPartita IVA — Regim fiscal italian pentru lucrătorii independenți, care în consultanța IT implică asumarea directă a riscului de credit față de clienți.\nDirectiva 2011/7/UE — Directivă europeană privind întârzierile la plată care fixează termenul standard la 30 de zile, maximul la 60, și prevede dobânzi de întârziere automate.\n","date":"10 martie 2026","permalink":"https://ivanluminaria.com/ro/posts/project-management/pagamenti-60-90-120-giorni/","section":"Database Strategy","summary":"\u003cp\u003ePrima dată când am lucrat cu un client internațional, mi s-a întâmplat ceva ciudat. M-au plătit în treizeci de zile.\u003c/p\u003e\n\u003cp\u003eNu treizeci de zile de la sfârșitul lunii. Nu treizeci de zile de la data primirii facturii înregistrate și vizate de responsabilul administrativ. Treizeci de zile de la factură. Punct.\u003c/p\u003e\n\u003cp\u003eAm verificat extrasul de cont de două ori. Am crezut că este o greșeală.\u003c/p\u003e\n\u003cp\u003eNu era o greșeală. Era normalitatea — doar că nu era normalitatea italiană.\u003c/p\u003e","title":"Plăți la 60-90-120 de zile: normalitatea italiană care nu există în Europa"},{"content":"Descarca PDF | Profil LinkedIn\nProfil Profesional #Data Warehouse Architect si profesionist IT cu aproape 30 de ani de experienta in proiectarea, implementarea si gestionarea solutiilor DWH complexe si de inalta performanta in medii Oracle si PostgreSQL. Expert in metodologii de modelare multidimensionala a datelor (Kimball, Inmon) si in optimizarea proceselor ETL/ELT si a interogatiilor SQL pe seturi de date de la sute de milioane la miliarde de randuri. Capacitate demonstrata de a conduce proiecte DWH de la un capat la altul — de la analiza cerintelor pana la punerea in productie — asigurand integritatea, calitatea si disponibilitatea datelor pentru a sprijini deciziile de business. Leadership tehnic si mentalitate orientata catre rezolvarea problemelor in contexte internationale si full-remote.\nCompetente Tehnice # Metodologii DWH: Modelare Multidimensionala a Datelor (Kimball, Inmon), Star Schema, Snowflake Schema, Slowly Changing Dimensions (SCD Type 1/2/3), Bus Matrix design. Oracle Databases: Oracle Database (de la 8i la 21c), Oracle Exadata, Oracle RAC, Oracle Data Guard, Oracle Autonomous Database (ADB), Performance Tuning (AWR, ADDM, SQL Tuning Advisor), Storage Management (ASM), Backup \u0026amp; Recovery (RMAN), Oracle TDE. PostgreSQL: PostgreSQL (14+), Query Optimization, Table Partitioning, pg_stat_statements, PgBouncer, Logical Replication, VACUUM/Autovacuum tuning. Cloud: Oracle Cloud Infrastructure (OCI). Instrumente ETL/ELT: Pipeline ETL bazate pe PL/SQL, Unix Shell Scripting, Oracle Data Integrator (ODI), Oracle Warehouse Builder (OWB, proiecte legacy). Business Intelligence \u0026amp; Reporting: Oracle Analytics Cloud (OAC) — Semantic Model Designer, Reports, Dashboards. Limbaje de Programare si Scripting: SQL (avansat), PL/SQL, Unix Shell Scripting. Sisteme de Operare: Linux (RHEL, CentOS, Oracle Linux), Unix, Windows Server. Altele: Project Management (Agile/Scrum), Team Leadership (pana la 7 persoane), Training Tehnic. Experienta Profesionala #IDEA DB CONSULTING S.R.L. — Roma, Italia (Full Remote Europa) #Data Warehouse Architect | Oracle \u0026amp; PostgreSQL Expert | Administrator Unic | 2021 – Prezent\nDWH Architect (pentru ATRADIUS) | 2022 – 2026:\nProiectarea Data Warehouse-ului diviziei Surety pentru consolidarea datelor din Italia, Spania, Franta si tarile din nordul Europei. Integrarea surselor eterogene — baze de date Oracle, Microsoft SQL Server si fisiere plate din sisteme externe — intr-un DWH unificat bazat pe Oracle. Modelarea domeniilor de business principale: portofoliu clienti, polite, contracte, facturare, daune si tranzactii pe daune. Dezvoltarea intregului model de date si a nivelului ETL — peste 60.000 de linii de cod PL/SQL — cu un sistem de monitorizare a incarcaturilor in timp real. Ingestia zilnica completa din toate cele trei surse se finalizeaza in mai putin de 2 ore. DWH Architect (pentru FAI SERVICE) | 2021 – 2023:\nProiectarea unui model de date Snowflake Schema pe Oracle Analytics Cloud cu procese ETL ruland pe Oracle 19c in OCI. Dezvoltare de dashboarduri si rapoarte pe OAC pentru statistici de facturare, segmentare clienti, analiza portofoliului si urmarirea costurilor/veniturilor. Proiectare si Arhitectura DWH (Banking, Telepass si alti clienti):\nDefinirea si implementarea arhitecturilor Data Warehouse pentru clienti din sectorul bancar si parteneri Telepass, urmand metodologiile Kimball si Inmon. Aplicarea modelarii multidimensionale (Star Schema, Snowflake) pentru optimizarea analizei si raportarii pe seturi de date de peste 2 miliarde de randuri. Proiectarea si dezvoltarea fluxurilor ETL/ELT pentru integrarea datelor din peste 15 surse eterogene. Proiectarea si implementarea solutiilor DWH pe PostgreSQL ca alternative cost-effective la arhitecturile Oracle, incluzand strategii de partitionare si optimizare a performantei interogarilor. Gestionarea si Optimizarea Bazelor de Date Oracle:\nAdministrare avansata, tuning si optimizarea performantei bazelor de date Oracle, inclusiv medii OCI si Autonomous Database. Optimizarea interogarilor SQL complexe — reducerea timpilor de procesare batch de la 4 ore la mai putin de 30 de minute pe incarcaturi de lucru analitice critice. Leadership si Consultanta:\nIndrumare tehnica si training pentru echipele interne si clienti privind cele mai bune practici DWH si Oracle/PostgreSQL. Instalare si patching de baze de date Oracle, gestionare Oracle OEM si RMAN. Dezvoltare de rapoarte si dashboarduri cu Oracle Analytics Cloud (OAC). NIMIS CONSULTING S.R.L. — Roma, Italia (Full Remote) #Oracle DBA | DWH Architect | Oracle Performance \u0026amp; Tuning Expert (pentru TIM / HUAWEI) | 2020 – 2022\nAdministrarea Proiectelor DWH/DBA:\nGestionarea si administrarea a peste 30 de baze de date Oracle critice (70+ instante) pe clustere Oracle Exadata (3 si 5 noduri) pentru un client Telco major. Responsabil pentru disponibilitatea 24/7 a sistemelor de baze de date care sustin peste 20 de milioane de abonati mobili prepaid. Gestionarea tabelelor de fapte cu ingestia a pana la 800 de milioane de inregistrari de trafic telefonic pe zi, necesitand strategii avansate de partitionare si compresie. Performance Tuning Avansat:\nAnaliza aprofundata a performantei prin AWR, ADDM si tuning proactiv pentru asigurarea SLA-urilor sub 500ms timp de raspuns pe interogarile critice. Implementarea strategiilor de indexare, partitionare si compresie pentru imbunatatirea performantei sistemului DWH. Gestionarea securitatii datelor cu Oracle TDE (Transparent Data Encryption). IDEA DB CONSULTING S.R.L. — Roma, Italia (Full Remote) #PL/SQL Expert | Oracle DBA \u0026amp; Tuning Expert (pentru FINWAVE S.p.A.) | 2020 – 2022\nDezvoltare avansata PL/SQL si optimizarea interogarilor pentru aplicatii financiare care proceseaza milioane de tranzactii zilnice. Consultanta privind arhitecturile Oracle si cele mai bune practici de performance tuning. PROFESIONIST INDEPENDENT / CONSULTANT — Roma, Italia (Full Remote Europa) #Oracle DBA | Oracle Performance \u0026amp; Tuning Expert | DWH Architect | 2013 – 2020\nProiectarea si dezvoltarea de Data Warehouse-uri pentru clienti din sectoarele bancar, asigurari si telecomunicatii, aplicand metodologiile Kimball/Inmon pe platforme Oracle si PostgreSQL. Dezvoltarea proceselor ETL/ELT pentru incarcarea datelor DWH — construirea de pipeline-uri care gestioneaza peste 500 de milioane de randuri per ciclu de incarcare. Consultanta specializata pe baze de date Oracle si PostgreSQL, SQL performance tuning, arhitecturi DWH, PL/SQL si proiectare ETL. Conducerea echipelor (3-7 persoane) in contexte multiculturale, gestionarea activitatilor si prioritatilor cu metodologie Agile. Crearea de rapoarte si analiza datelor cu Oracle Analytics Cloud (OAC). AUSELDA AED GROUP S.P.A. — Roma, Italia #Data Warehouse Architect | Performance \u0026amp; Tuning Expert | Oracle Project DBA (pentru Administratia Publica) | 2009 – 2013\nProiectarea si modelarea Data Warehouse (Kimball/Inmon) pentru entitati ale Administratiei Publice. Dezvoltarea proceselor ETL/ELT si optimizarea interogarilor SQL complexe. Specialist al produsului Oracle Warehouse Builder (OWB). Gestionarea tehnica a proiectelor DWH si instruirea utilizatorilor. ORACLE ITALIA S.R.L. — Diverse locatii, Italia \u0026amp; Madrid, Spania #Data Warehouse Architect | Oracle DBA | DWH Designer | SQL \u0026amp; PL/SQL Developer | Training Specialist | 1999 – 2009\nRoluri Arhitecturale si de Dezvoltare DWH (2001-2009):\nProiectarea si dezvoltarea de Data Warehouse-uri pentru clienti de top in Telco (TIM, Vodafone, TRE), Finante (Banca d\u0026rsquo;Italia, Generali, RAS), Farmaceutic (Menarini) si alte sectoare. Implementarea modelelor de date (Kimball/Inmon) si a proceselor ETL/ELT cu Oracle Warehouse Builder. Consultanta in SQL Performance \u0026amp; Tuning, PL/SQL, BI Reports (Oracle Discoverer, HTMLDB), Oracle OLAP. Experienta internationala cu Vodafone Spania (Madrid). Training Specialist (2000-2001):\nSustinerea cursurilor Oracle: SQL (Baza si Avansat), PL/SQL (Baza si Avansat), Oracle Database Administration, Performance and Tuning, Oracle Discoverer, Forms, Reports. Web Developer | Oracle SQL \u0026amp; PL/SQL Developer (ETNOTEAM S.P.A. - 1999): Dezvoltare de portaluri web si aplicatii client-server.\nS.EL.DAT. S.P.A. — Roma, Italia #Software Developer (pentru Telecom, Rover Italia) | 1997 – 1999\nDezvoltare aplicatii client-server, Junior Oracle DBA, monitorizare BD. Educatie si Formare # Facultatea de Inginerie Informatica (Ingineria Software) | Universitatea Roma Tre, Roma | 1994 – 2000 Diploma de Bacalaureat Stiintific (EQF Nivel 4) | Liceo Scientifico Isacco Newton / Manieri Copernico, Roma | 1988 – 1993 Engleza Avansata (C1/C2) | The British Council (Nivel 4A), Roma | 2003 – 2004 Cursuri de Formare si Actualizare Selectionate:\nScrum Agile — Randstad/Forma.temp (Mai 2024) Project Management — Randstad/Forma.temp (Mai 2024) Data Wrangling, Analysis and AB Testing with SQL — Coursera, University of California Davis (Aprilie 2021) Data Science on Google Cloud Platform: Designing Data Warehouses — LinkedIn Learning (Septembrie 2020) Cursuri de specializare Oracle 12c (Administration, Security, Backup and Recovery, Advanced SQL, Performance Optimization) — LinkedIn Learning (2020) MySQL Installation and Configuration — LinkedIn Learning (August 2020) Learning Git and GitHub — LinkedIn Learning (August 2020) Limbi Straine # Italiana: Limba materna Engleza: C1/C2 (Fluent, profesional) Spaniola: C1 (Fluent) Romana: C1 (Fluent) Franceza: A1/A2 (Baza) Competente Transversale # Rezolvarea problemelor in mod analitic si creativ Lucru in echipa si colaborare in contexte internationale Project Management (Definirea cerintelor, Prioritizare, Diagrame Gantt, ERD) Comunicare eficienta si implicarea stakeholderilor Autorizez prelucrarea datelor mele personale conform Art. 13 din Regulamentul UE 2016/679 (GDPR).\nRoma, Martie 2026\nDescarca PDF | Profil LinkedIn | Inapoi la pagina anterioara\n","date":"10 martie 2026","permalink":"https://ivanluminaria.com/ro/resumes/dwh-architect/","section":"Know-How \u0026 Impact","summary":"\u003cp\u003e\u003cstrong\u003e\u003ca href=\"https://ivanluminaria.com/downloads/CV_DWH_Architect_Ivan_Luminaria_202603_EN.pdf\" target=\"_blank\" rel=\"noreferrer\"\u003eDescarca PDF\u003c/a\u003e\u003c/strong\u003e | \u003cstrong\u003e\u003ca href=\"https://www.linkedin.com/in/ivanluminaria\" target=\"_blank\" rel=\"noreferrer\"\u003eProfil LinkedIn\u003c/a\u003e\u003c/strong\u003e\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"profil-profesional\" class=\"relative group\"\u003eProfil Profesional \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#profil-profesional\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eData Warehouse Architect si profesionist IT cu aproape 30 de ani de experienta in proiectarea, implementarea si gestionarea solutiilor DWH complexe si de inalta performanta in medii Oracle si PostgreSQL. Expert in metodologii de modelare multidimensionala a datelor (Kimball, Inmon) si in optimizarea proceselor ETL/ELT si a interogatiilor SQL pe seturi de date de la sute de milioane la miliarde de randuri. Capacitate demonstrata de a conduce proiecte DWH de la un capat la altul — de la analiza cerintelor pana la punerea in productie — asigurand integritatea, calitatea si disponibilitatea datelor pentru a sprijini deciziile de business. Leadership tehnic si mentalitate orientata catre rezolvarea problemelor in contexte internationale si full-remote.\u003c/p\u003e","title":"Data Warehouse Architect"},{"content":"Descarca PDF | Profil LinkedIn\nProfil Profesional #Senior Oracle DBA si Performance Tuning Expert cu aproape 30 de ani de experienta specializata in administrarea, optimizarea si gestionarea bazelor de date Oracle complexe si critice, inclusiv medii Exadata, RAC si Oracle Cloud (OCI, Autonomous Database). Expertiza avansata in analiza performantei (AWR, ADDM, ASH), optimizarea interogatiilor SQL complexe, tuning-ul instantelor si rezolvarea problemelor de performanta. Cunostinte solide in practici legate de backup \u0026amp; recovery (RMAN), securitate (TDE), instalare, patching, migrari si gestionarea stocarii (ASM), performanta ramanand principala si cea mai aprofundata arie de expertiza, cruciala pentru integritatea, performanta si contributia la disponibilitatea ridicata a sistemelor Oracle in medii corporative exigente si internationale.\nCompetente Tehnice — Oracle DBA \u0026amp; Performance Tuning # Administrare Oracle Database: Oracle Database (de la 8i la 21c, Autonomous), Oracle Exadata, Oracle RAC (Real Application Clusters), Oracle Data Guard, Oracle GoldenGate (cunostinte de baza). Performance Tuning Avansat: Analiza si Diagnosticare: AWR, ADDM, ASH, Statspack, SQL Trace, TKPROF, Explain Plan. SQL Tuning: Optimizarea interogarilor complexe, Hints, SQL Profiles, SQL Plan Management (SPM). Instance Tuning: Memory Management (SGA, PGA), Parametri de Initializare, Analiza Wait Events. Proiectare Baze de Date pentru Performanta: Indexare (B-tree, Bitmap, Function-based), Partitioning (Range, List, Hash, Composite), Compresie. High Availability si Disaster Recovery: RMAN (Backup, Recovery, Cloning), Oracle Data Guard, Flashback Technologies. Securitate Baze de Date: Oracle TDE (Transparent Data Encryption), Gestionarea Utilizatorilor si Privilegiilor, Audit. Gestionare Stocare: ASM (Automatic Storage Management), Gestionare Tablespace. Instalare, Patching si Migrari: Instalarea de noi instante, aplicarea PSU/CPU/RU, upgrade-uri de versiune, migrari cross-platform. Instrumente Oracle: Oracle Enterprise Manager (OEM) Cloud Control, SQL Developer, SQL*Plus, Toad. Scripting: PL/SQL, SQL, Unix Shell Scripting (pentru automatizarea sarcinilor DBA). Cloud: Oracle Cloud Infrastructure (OCI) — Compute, Storage, Networking, Database Services (VM DB, Bare Metal, Exadata CS, Autonomous Database). Alte Tehnologii de Baze de Date: PostgreSQL (administrare, performance tuning, partitioning, replicare), MySQL (administrare, configurare, replicare, optimizare InnoDB). Sisteme de Operare: Linux (Red Hat, Oracle Linux), Unix (AIX, Solaris), Windows Server. Experienta Profesionala #IDEA DB CONSULTING S.R.L. — Roma, Italia (Full Remote Europa) #Senior Oracle DBA \u0026amp; Performance Tuning Expert / DWH Architect | Administrator Unic | 2021 – Prezent\nDBA MySQL \u0026amp; PostgreSQL (pentru POSTE ITALIANE) | Iul 2025 – Prezent:\nAdministrarea si gestionarea a aproximativ 1.500 de instante MySQL si PostgreSQL in medii de productie, staging si dezvoltare. Monitorizarea performantei, query tuning, gestionarea replicarii si planificarea capacitatii la scara enterprise. Oracle DBA \u0026amp; Tuning Expert (pentru GENERALI Assicurazioni) | Feb 2024 – Mai 2025:\nAdministrarea bazelor de date Oracle si performance tuning avansat pentru aplicatii din sectorul asigurarilor. Analiza AWR/ADDM, optimizare SQL si rezolvarea proactiva a blocajelor pe baze de date de la 500GB la 8TB. Oracle DBA (pentru ATRADIUS) | 2022 – 2026:\nAdministrarea si performance tuning-ul bazelor de date care sustin Data Warehouse-ul diviziei Surety pentru consolidarea datelor din Italia, Spania, Franta si tarile din nordul Europei. Gestionarea bazelor de date Oracle in medii OCI, sustinand peste 60.000 de linii de cod PL/SQL ETL cu ingestie zilnica completa in mai putin de 2 ore. Oracle DBA (pentru FAI SERVICE) | 2021 – 2023:\nAdministrarea si tuning-ul bazelor de date Oracle 19c in OCI pentru procese ETL si dashboarduri Oracle Analytics Cloud. DBA \u0026amp; Performance Tuning (Banking, Telepass si alti clienti):\nOptimizarea bazelor de date Oracle in medii OCI si Autonomous Database — reducerea timpilor de procesare batch de la 4 ore la mai putin de 30 de minute pe incarcaturi de lucru analitice critice. Proiectarea si dezvoltarea fluxurilor ETL/ELT pentru integrarea datelor din peste 15 surse eterogene pe seturi de date de peste 2 miliarde de randuri. Gestionarea RMAN, monitorizare Oracle OEM, instalare si patching de baze de date Oracle. Proiectarea si implementarea solutiilor DWH pe PostgreSQL ca alternative cost-effective la arhitecturile Oracle. NIMIS CONSULTING S.R.L. — Roma, Italia (Full Remote) #Senior Oracle DBA \u0026amp; Performance Tuning Expert (pentru TIM / HUAWEI) | 2020 – 2022\nAdministrarea si gestionarea a peste 30 de baze de date Oracle critice (70+ instante) pe clustere Oracle Exadata (3/5 noduri) pentru un client Telco de prim plan. Responsabilitate directa pentru performance tuning avansat: analiza AWR/ADDM, optimizare SQL, gestionare indecsi, partitioning si compresie. Implicare in activitati de gestionare a stocarii (ASM) si implementare Oracle TDE pentru securitatea datelor. Suport \u0026ldquo;ON-CALL\u0026rdquo; 24/7 pentru rezolvarea problemelor critice si mentinerea disponibilitatii ridicate. PROFESIONIST INDEPENDENT / CONSULTANT — Roma, Italia (Full Remote Europa) #Senior Oracle DBA \u0026amp; Performance Tuning Expert / DWH Architect | 2013 – 2020\nFurnizarea de servicii de consultanta ca Oracle DBA si specialist in Performance Tuning pentru diversi clienti. Optimizarea interogarilor SQL complexe si tuning-ul instantelor Oracle pentru imbunatatirea performantei aplicatiilor critice. Suport in instalarea, configurarea, patching-ul si upgrade-ul bazelor de date Oracle. Consultanta privind strategiile de backup si recovery cu RMAN. Proiectarea si implementarea configuratiilor Oracle Data Guard pentru disponibilitate ridicata si disaster recovery, inclusiv proceduri de switchover/failover. Gestionarea echipelor tehnice mici in proiecte de migrare si upgrade. AUSELDA AED GROUP S.P.A. — Roma, Italia #Project Oracle DBA / Performance \u0026amp; Tuning Expert (pentru Administratia Publica) | 2009 – 2013\nAdministrarea si optimizarea bazelor de date Oracle care sustin aplicatii ale Administratiei Publice. Tuning-ul interogarilor SQL si al proceselor ETL pentru sisteme de Data Warehousing. Implicare in activitati de instalare, patching si gestionare a securitatii bazelor de date. ORACLE ITALIA S.R.L. — Diverse locatii, Italia si Madrid, Spania #Oracle DBA / DWH Architect / SQL \u0026amp; PL/SQL Developer / Training Specialist | 1999 – 2009\nRoluri DBA si Performance (in crestere progresiva): Administrarea bazelor de date Oracle pentru clienti enterprise (TIM, Vodafone, Banca d\u0026rsquo;Italia, Generali). Implicare in activitati de SQL Performance \u0026amp; Tuning, troubleshooting si optimizare. Suport pentru instalarea si configurarea instantelor Oracle, gestionarea patch-urilor. Ca Training Specialist (2000-2001): Sustinerea de cursuri de Oracle Database Administration si Performance \u0026amp; Tuning. S.EL.DAT. S.P.A. — Roma, Italia #Software Developer (pentru Telecom, Rover Italia) | 1997 – 1999\nDezvoltare aplicatii client-server, Junior Oracle DBA, monitorizare DB. Educatie si Formare # Facultatea de Inginerie Informatica (Inginerie Software) | Universitatea Roma Tre, Roma | 1994 – 2000 Diploma de Liceu Stiintific (EQF Nivel 4) | Liceo Scientifico Isacco Newton / Manieri Copernico, Roma | 1988 – 1993 Engleza Avansata (C1/C2) | The British Council (Level 4A), Roma | 2003 – 2004 Cursuri Selectate de Formare si Educatie Continua:\nAdvanced SQL for Query Tuning and Performance Optimization — LinkedIn Learning (August 2020) Data Wrangling, Analysis and AB Testing with SQL — Coursera, University of California Davis (Aprilie 2021) Cursuri de specializare Oracle 12c (Administration, Security, Backup and Recovery, Advanced SQL, New Features) — LinkedIn Learning (2020) Limbi Straine # Italiana: Limba materna Engleza: C1/C2 (Fluent, profesional) Spaniola: C1 (Fluent) Romana: C1 (Fluent) Franceza: A1/A2 (Baza) Competente Transversale # Rezolvare Analitica si Metodica a Problemelor Gestionarea Prioritatilor si Respectarea Termenelor Capacitatea de a Lucra Sub Presiune Comunicare Tehnica Clara si Eficienta Atentie la Detalii si Precizie Invatare Continua si Adaptabilitate Tehnologica Autorizez prelucrarea datelor mele personale conform Art. 13 din Regulamentul UE 2016/679 (GDPR).\nRoma, Martie 2026\nDescarca PDF | Profil LinkedIn | Inapoi la pagina anterioara\n","date":"10 martie 2026","permalink":"https://ivanluminaria.com/ro/resumes/oracle-dba/","section":"Know-How \u0026 Impact","summary":"\u003cp\u003e\u003cstrong\u003e\u003ca href=\"https://ivanluminaria.com/downloads/CV_Oracle_DBA_Ivan_Luminaria_202603_EN.pdf\" target=\"_blank\" rel=\"noreferrer\"\u003eDescarca PDF\u003c/a\u003e\u003c/strong\u003e | \u003cstrong\u003e\u003ca href=\"https://www.linkedin.com/in/ivanluminaria\" target=\"_blank\" rel=\"noreferrer\"\u003eProfil LinkedIn\u003c/a\u003e\u003c/strong\u003e\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"profil-profesional\" class=\"relative group\"\u003eProfil Profesional \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#profil-profesional\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eSenior Oracle DBA si Performance Tuning Expert cu aproape 30 de ani de experienta specializata in administrarea, optimizarea si gestionarea bazelor de date Oracle complexe si critice, inclusiv medii Exadata, RAC si Oracle Cloud (OCI, Autonomous Database). Expertiza avansata in analiza performantei (AWR, ADDM, ASH), optimizarea interogatiilor SQL complexe, tuning-ul instantelor si rezolvarea problemelor de performanta. Cunostinte solide in practici legate de backup \u0026amp; recovery (RMAN), securitate (TDE), instalare, patching, migrari si gestionarea stocarii (ASM), performanta ramanand principala si cea mai aprofundata arie de expertiza, cruciala pentru integritatea, performanta si contributia la disponibilitatea ridicata a sistemelor Oracle in medii corporative exigente si internationale.\u003c/p\u003e","title":"Oracle DBA \u0026 Performance Tuning Expert"},{"content":"Descarca PDF | Profil LinkedIn\nProfil Profesional #Senior Oracle PL/SQL Developer cu aproape 30 de ani de experienta in proiectarea, dezvoltarea, testarea si optimizarea codului PL/SQL robust si eficient pentru aplicatii cu volume mari de date si sisteme Data Warehouse. Expertiza avansata in crearea de pachete, proceduri, functii, triggere si tipuri complexe, cu un accent constant pe performanta, mentenabilitate si calitatea codului. Expert in optimizarea interogarilor SQL complexe si gestionarea volumelor mari de date. Abilitate in transpunerea cerintelor de business in logica aplicativa performanta si scalabila in cadrul bazei de date Oracle. Parcurs consolidat si ca Oracle DBA si DWH Architect, oferind o viziune completa asupra ciclului de viata al datelor.\nCompetente Tehnice — Dezvoltare Oracle PL/SQL # Limbaje: PL/SQL (Avansat), SQL (Avansat, inclusiv Dynamic SQL, Analytic Functions, CTEs). Dezvoltare PL/SQL: Packages, Procedures, Functions, Triggers. Tipuri de Date PL/SQL (Records, Collections, Object Types). Gestionarea Erorilor si Exceptiilor. Bulk Processing (FORALL, BULK COLLECT). Dynamic SQL (DBMS_SQL, Execute Immediate). Optimizarea Codului PL/SQL (inclusiv utilizarea PL/SQL Hierarchical Profiler). Interactiunea cu Obiecte ale Bazei de Date (Tables, Views, Sequences, Synonyms). Optimizare SQL \u0026amp; Performanta: Analiza Planurilor de Executie (Explain Plan), SQL Trace, TKPROF. Tehnici de SQL Tuning (Hints, Query Rewriting, Indexes). Intelegerea impactului proiectarii bazei de date asupra performantei PL/SQL. Instrumente de Dezvoltare: SQL Developer, Toad, SQL*Plus. Oracle Database: Oracle Database (de la 8i la 21c, Autonomous Database). Concepte Conexe: Data Warehousing (dezvoltare logica ETL/ELT), Data Integration, Modelare Relationala si Multidimensionala a Datelor. Controlul Versiunilor: Git, GitHub. Scripting: Unix Shell Scripting (pentru automatizarea deployment-ului si gestionarea scripturilor). Cloud: Oracle Cloud Infrastructure (OCI) — cunostinte despre serviciile de baze de date. Experienta Profesionala #IDEA DB CONSULTING S.R.L. — Roma, Italia (Full Remote Europa) #Senior Oracle PL/SQL Developer \u0026amp; DWH Architect | 2022 – Prezent\nPL/SQL Developer (pentru ATRADIUS) | 2022 – 2026:\nDezvoltarea si intretinerea a peste 60.000 de linii de cod PL/SQL (pachete, proceduri, functii) pentru Data Warehouse-ul diviziei Surety, consolidand date de asigurari si credit din Italia, Spania, Franta si tarile din nordul Europei. Proiectarea de sabloane PL/SQL reutilizabile pentru procedurile de incarcare a datelor — standardizarea workflow-ului ETL intern cu puncte de control integrate pentru urmarirea si monitorizarea in timp real a fluxurilor de incarcare, permitand si dezvoltatorilor juniori sa urmeze un tipar consistent si repetabil. Implementarea monitorizarii in timp real a incarcarii prin pachete PL/SQL de logare personalizate, oferind vizibilitate imediata asupra starii pipeline-urilor ETL si gestionarea erorilor in toate fazele de incarcare. Optimizarea performantei batch: reducerea ciclului complet de ingestie zilnica de la 4+ ore la sub 2 ore prin rescrierea interogarilor, pattern-uri BULK COLLECT/FORALL si DML partition-aware. PL/SQL Developer (pentru FINWAVE S.p.A.) | 2020 – 2022:\nDezvoltarea de pachete PL/SQL pentru aplicatii de procesare a tranzactiilor financiare care gestioneaza milioane de operatiuni zilnice pentru clienti bancari si de asigurari. Optimizare avansata a interogarilor si tuning-ul codului PL/SQL pentru pipeline-uri de date financiare de volum mare. PL/SQL Developer (pentru FAI SERVICE) | 2021 – 2023:\nDezvoltarea procedurilor ETL in PL/SQL pe Oracle 19c/OCI pentru fluxuri de date de statistici de facturare, segmentare clienti si urmarire costuri/venituri. Construirea de module PL/SQL care alimenteaza dashboard-uri Oracle Analytics Cloud cu KPI-uri financiare agregate. Dezvoltare PL/SQL (Banking, Telepass si alti clienti):\nDezvoltarea de pachete PL/SQL pentru logica de business in aplicatii DWH din sectorul bancar, procesand seturi de date de peste 2 miliarde de randuri. Optimizarea codului PL/SQL si a interogarilor SQL existente — utilizarea Hierarchical Profiler pentru identificarea blocajelor si imbunatatirea timpilor de executie pe caile critice. Colaborare cu echipele de dezvoltare si analistii functionali pentru definirea cerintelor si proiectarea solutiilor bazate pe PL/SQL. NIMIS CONSULTING S.R.L. — Roma, Italia (Full Remote) #Senior Oracle DBA \u0026amp; Performance Expert cu Focus pe Dezvoltare (pentru TIM / HUAWEI) | 2020 – 2022\nSuport specializat echipelor de dezvoltare in optimizarea codului PL/SQL si a interogarilor SQL pentru aplicatii critice pe baze de date Exadata. Analiza si tuning-ul proceselor PL/SQL batch cu volume mari. Dezvoltarea de scripturi PL/SQL pentru sarcini de monitorizare si administrare. PROFESIONIST INDEPENDENT / CONSULTANT — Roma, Italia (Full Remote Europa) #Senior Oracle PL/SQL Developer \u0026amp; DBA / DWH Architect | 2013 – 2020\nProiectarea si dezvoltarea de solutii PL/SQL personalizate pentru diversi clienti, inclusiv pachete pentru logica ETL, proceduri de procesare a datelor si API-uri PL/SQL. Optimizare intensiva a codului PL/SQL si SQL pentru imbunatatirea performantei sistemelor existente. Dezvoltarea de module PL/SQL pentru extractia, transformarea si incarcarea (ETL) datelor in sisteme DWH. Formare si mentorat pentru dezvoltatorii juniori privind cele mai bune practici de dezvoltare PL/SQL. AUSELDA AED GROUP S.P.A. — Roma, Italia #Oracle PL/SQL Developer \u0026amp; DWH Specialist (pentru Administratia Publica) | 2009 – 2013\nDezvoltarea componentelor PL/SQL pentru sisteme Data Warehousing si aplicatii de gestiune ale Administratiei Publice. Mentenanta evolutiva si corectiva a codului PL/SQL. Optimizarea proceselor ETL bazate pe PL/SQL si OWB. ORACLE ITALIA S.R.L. — Diverse locatii, Italia si Madrid, Spania #SQL \u0026amp; PL/SQL Developer / DWH Architect / DBA / Training Specialist | 1999 – 2009\nRoluri de Dezvoltare PL/SQL (semnificative si in crestere): Dezvoltare intensiva de cod PL/SQL pentru proiecte DWH, BI si aplicatii personalizate pentru clienti enterprise din diverse sectoare (Telco, Finance, Farmaceutic). Crearea de pachete PL/SQL pentru logica de business complexa, proceduri de incarcare a datelor (ETL) cu Oracle Warehouse Builder si PL/SQL. Dezvoltare de Rapoarte BI si interfete HTMLDB (Apex) cu logica PL/SQL. Ca Training Specialist (2000-2001): Sustinerea de cursuri Oracle SQL (Basic si Advanced) si PL/SQL (Basic si Advanced). ETNOTEAM S.P.A. — Roma, Italia #Web Developer / Oracle SQL \u0026amp; PL/SQL Developer | 1999\nDezvoltare de portaluri web si aplicatii client-server cu interactiune puternica cu baze de date Oracle, utilizand SQL si PL/SQL pentru logica backend. S.EL.DAT. S.P.A. — Roma, Italia #Software Developer / Junior DBA | 1997 – 1999\nDezvoltare de aplicatii client-server cu backend Oracle; prime experiente cu SQL si PL/SQL. Educatie si Formare # Facultatea de Inginerie Informatica (Inginerie Software) | Universitatea Roma Tre, Roma | 1994 – 2000 Diploma de Liceu Stiintific (EQF Nivel 4) | Liceo Scientifico Isacco Newton / Manieri Copernico, Roma | 1988 – 1993 Engleza Avansata (C1/C2) | The British Council (Level 4A), Roma | 2003 – 2004 Cursuri Selectate de Formare si Educatie Continua:\nScrum Agile — Randstad/Forma.temp (Mai 2024) Project Management — Randstad/Forma.temp (Mai 2024) Data Wrangling, Analysis and AB Testing with SQL — Coursera, University of California Davis (Aprilie 2021) Advanced SQL for Query Tuning and Performance Optimization — LinkedIn Learning (August 2020) Cursuri de specializare Oracle 12c (Advanced SQL, New Features) — LinkedIn Learning (2020) Learning Git and GitHub — LinkedIn Learning (August 2020) Limbi Straine # Italiana: Limba materna Engleza: C1/C2 (Fluent, profesional) Spaniola: C1 (Fluent) Romana: C1 (Fluent) Franceza: A1/A2 (Baza) Competente Transversale # Abordare Analitica si Orientare spre Rezolvarea Problemelor Complexe Scrierea de Cod Clar, Eficient si Usor de Intretinut Competente Avansate de Debugging si Troubleshooting Intelegere Excelenta a Cerintelor Functionale si Tehnice Colaborare Eficienta in Echipele de Dezvoltare Atentie la Detalii si Calitatea Software-ului Autorizez prelucrarea datelor mele personale conform Art. 13 din Regulamentul UE 2016/679 (GDPR).\nRoma, Martie 2026\nDescarca PDF | Profil LinkedIn | Inapoi la pagina anterioara\n","date":"10 martie 2026","permalink":"https://ivanluminaria.com/ro/resumes/oracle-plsql/","section":"Know-How \u0026 Impact","summary":"\u003cp\u003e\u003cstrong\u003e\u003ca href=\"https://ivanluminaria.com/downloads/CV_Oracle_PLSQL_Ivan_Luminaria_202603_EN.pdf\" target=\"_blank\" rel=\"noreferrer\"\u003eDescarca PDF\u003c/a\u003e\u003c/strong\u003e | \u003cstrong\u003e\u003ca href=\"https://www.linkedin.com/in/ivanluminaria\" target=\"_blank\" rel=\"noreferrer\"\u003eProfil LinkedIn\u003c/a\u003e\u003c/strong\u003e\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"profil-profesional\" class=\"relative group\"\u003eProfil Profesional \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#profil-profesional\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eSenior Oracle PL/SQL Developer cu aproape 30 de ani de experienta in proiectarea, dezvoltarea, testarea si optimizarea codului PL/SQL robust si eficient pentru aplicatii cu volume mari de date si sisteme Data Warehouse. Expertiza avansata in crearea de pachete, proceduri, functii, triggere si tipuri complexe, cu un accent constant pe performanta, mentenabilitate si calitatea codului. Expert in optimizarea interogarilor SQL complexe si gestionarea volumelor mari de date. Abilitate in transpunerea cerintelor de business in logica aplicativa performanta si scalabila in cadrul bazei de date Oracle. Parcurs consolidat si ca Oracle DBA si DWH Architect, oferind o viziune completa asupra ciclului de viata al datelor.\u003c/p\u003e","title":"Oracle PL/SQL Developer"},{"content":"Descarca PDF | Profil LinkedIn\nProfil Profesional #Project Manager cu aproape 30 de ani de experienta in IT si un fundament tehnic solid in medii Data Warehouse si Oracle. Peste 10 proiecte livrate cu un istoric excelent de respectare a termenelor, gestionand echipe de 3-7 persoane in contexte multiculturale si remote, pe proiecte cu bugete in intervalul €100K-€500K. Competente concrete in planificare, managementul riscurilor, coordonarea resurselor si relatia cu stakeholderii — dezvoltate pe teren coordonand activitati de dezvoltare, release si mentenanta pentru clienti din sectoarele Bancar, Telco, Asigurari si Administratie Publica. Metodologii Agile (Scrum) aplicate in managementul zilnic al proiectelor, cu formare certificata. Fundament tehnic aprofundat (arhitectura DWH, Oracle DBA, PL/SQL, ETL/ELT) care permite comunicarea eficienta cu echipele de dezvoltare, evaluarea realista a fezabilitatii si identificarea timpurie a riscurilor tehnice.\nCompetente Cheie # Project Management \u0026amp; Metodologii: Planificarea proiectelor, definirea milestone-urilor si monitorizarea progresului. Managementul riscurilor si al criticalitatilor — identificare proactiva si planuri de mitigare. Metodologii Agile si Scrum (Sprint Planning, Daily Stand-up, Retrospective, Backlog Refinement) — Formare certificata. Definirea cerintelor, managementul scope-ului si relatia cu stakeholderii. Planificarea release-urilor si coordonarea livrarilor. Instrumente de Project Management \u0026amp; Productivitate: Microsoft Project si Jira (planificare, tracking, managementul backlog-ului). Microsoft Excel si Google Sheets (raportare, dashboard-uri de proiect, analiza datelor — utilizare zilnica). Git si GitHub (managementul codului, issue tracking, CI/CD, workflow-uri colaborative). Competente Tehnice de Suport pentru PM: Arhitectura Data Warehouse (Kimball, Inmon, Google Cloud Platform). Oracle Database: DBA, Performance Tuning, PL/SQL. SQL avansat, procese ETL/ELT, Business Intelligence. Evaluarea fezabilitatii tehnice si estimarea efortului de dezvoltare. Leadership \u0026amp; Comunicare: Coordonarea echipelor tehnice distribuite (3-7 persoane, multi-tara). Comunicare eficienta cu echipele tehnice, stakeholderii de business si managementul. Mentorat si dezvoltarea competentelor echipei. Facilitarea intalnirilor si managementul conflictelor. Experienta Profesionala #IDEA DB CONSULTING S.R.L. — Roma, Italia (Full Remote Europa) #Project Manager \u0026amp; Senior DWH Architect | 2022 – Prezent\nPM \u0026amp; DWH Lead (pentru GENERALI Asigurari) | Feb 2024 – Mai 2025:\nCoordonarea activitatilor de proiect si gestionarea prioritatilor pentru echipa de dezvoltare pe baze de date Oracle in sectorul asigurarilor. Interfata directa cu clientul pentru colectarea cerintelor, definirea scope-ului si prezentarea solutiilor. Monitorizarea progresului si gestionarea criticalitatilor pe baze de date de 500GB la 8TB. PM \u0026amp; DWH Lead (pentru ATRADIUS) | 2022 – 2026:\nGestionarea proiectului de consolidare a datelor pentru divizia Surety — coordonarea integrarii datelor din 4 tari europene (Italia, Spania, Franta, Europa de Nord). Planificarea release-urilor si managementul backlog-ului de dezvoltare pe peste 60.000 de linii de cod PL/SQL ETL. Tracking-ul activitatilor, raportare catre stakeholder si gestionarea dependentelor intre echipe. Project Coordinator (Banking, Telepass si alti clienti):\nCoordonarea proiectelor cu reducerea timpilor de procesare batch de la 4 ore la sub 30 de minute. Gestionarea integrarii datelor din peste 15 surse eterogene pe seturi de date depasindu 2 miliarde de randuri. Planificarea si supervizarea release-urilor in medii Oracle OCI si Autonomous Database. NIMIS CONSULTING S.R.L. — Roma, Italia (Full Remote) #Senior Oracle DBA \u0026amp; Performance Tuning Expert (pentru TIM / HUAWEI) | 2020 – 2022\nPlanificarea si executia activitatilor de mentenanta si patching pe peste 30 de baze de date Oracle critice (70+ instante) pe clustere Exadata. Coordonare cu echipa de dezvoltare pentru optimizarea interactiunilor cu baza de date si rezolvarea problemelor de performanta — suport tehnic specializat si prioritizarea interventiilor. Gestionarea autonoma a volumului de munca si a activitatilor de tuning, cu raportare catre responsabilul de proiect. PROFESIONIST INDEPENDENT / CONSULTANT — Roma, Italia (Full Remote Europa) #Project Manager \u0026amp; Senior DWH Consultant | 2013 – 2020\nGestionarea a aproximativ 10 proiecte in 7 ani pentru clienti din sectoarele Bancar, Telco si servicii, cu bugete in intervalul €100K-€500K si un istoric excelent de livrari la termen. Coordonarea echipelor de 3-7 persoane in contexte multiculturale si distribuite — atribuirea sarcinilor, facilitarea colaborarii si gestionarea prioritatilor cu abordare iterativa Agile. Interfata directa cu clientii pentru colectarea cerintelor, definirea scope-ului, prezentarea progreselor si gestionarea asteptarilor. Formare tehnica si mentorat pentru membrii echipei — dezvoltarea competentelor si integrarea noilor consultanti. AUSELDA AED GROUP S.P.A. — Roma, Italia #Senior Data Warehouse Specialist \u0026amp; Oracle DBA (pentru Administratia Publica) | 2009 – 2013\nColaborare cu responsabilii de proiect pentru definirea cerintelor tehnice, planificarea activitatilor si validarea solutiilor. Coordonarea activitatilor de dezvoltare si optimizare a Data Warehouse-urilor pentru entitati ale Administratiei Publice. Suport tehnic si formare pentru utilizatorii platformelor DWH. ORACLE ITALIA S.R.L. — Diverse locatii, Italia si Madrid, Spania #Senior Consultant / DWH Specialist / Training Specialist | 1999 – 2009\nParticipare la proiecte complexe de implementare DWH si BI pentru clienti primari (Telco, Finance, Farmaceutic), cu responsabilitati crescande in coordonarea activitatilor si sprijinirea consultantilor juniori. Gestionarea relatiilor cu referentii tehnici ai clientului si raportarea progresului activitatilor. Ca Training Specialist (2000-2001): Sustinerea de cursuri tehnice Oracle, gestionarea clasei si adaptarea continutului — competente de prezentare si formare direct aplicabile rolului de PM. Educatie si Formare # Facultatea de Inginerie Informatica (Inginerie Software) | Universitatea Roma Tre, Roma | 1994 – 2000 Diploma de Liceu Stiintific (EQF Nivel 4) | Liceo Scientifico Isacco Newton / Manieri Copernico, Roma | 1988 – 1993 Engleza Avansata (C1/C2) | The British Council (Level 4A), Roma | 2003 – 2004 Cursuri Selectate de Formare si Educatie Continua:\nProject Management — Randstad/Forma.temp (Mai 2024) Scrum Agile — Randstad/Forma.temp (Mai 2024) Data Wrangling, Analysis and AB Testing with SQL — Coursera, University of California Davis (Aprilie 2021) Data Science on Google Cloud Platform: Designing Data Warehouses — LinkedIn Learning (Septembrie 2020) Cursuri de specializare Oracle 12c (Administration, Security, Backup and Recovery, Advanced SQL, Performance Optimization) — LinkedIn Learning (2020) Learning Excel 2016 — LinkedIn Learning (August 2020) Learning Git and GitHub — LinkedIn Learning (August 2020) Limbi Straine # Italiana: Limba materna Engleza: C1/C2 (Fluent, profesional) Spaniola: C1 (Fluent) Romana: C1 (Fluent) Franceza: A1/A2 (Baza) Competente Transversale # Capacitatea de a transpune cerintele tehnice in planuri de proiect concrete si gestionabile Gestionarea simultana a mai multor proiecte cu prioritati concurente Comunicare eficienta la toate nivelurile (echipa tehnica, stakeholderi, management) Rezolvare Analitica a Problemelor si gestionare proactiva a riscurilor Experienta de lucru in echipe distribuite, multiculturale si full-remote Mentorat si dezvoltarea competentelor echipei Autorizez prelucrarea datelor mele personale conform Art. 13 din Regulamentul UE 2016/679 (GDPR).\nRoma, Martie 2026\nDescarca PDF | Profil LinkedIn | Inapoi la pagina anterioara\n","date":"10 martie 2026","permalink":"https://ivanluminaria.com/ro/resumes/project-manager/","section":"Know-How \u0026 Impact","summary":"\u003cp\u003e\u003cstrong\u003e\u003ca href=\"https://ivanluminaria.com/downloads/CV_Project_Manager_Ivan_Luminaria_202603_EN.pdf\" target=\"_blank\" rel=\"noreferrer\"\u003eDescarca PDF\u003c/a\u003e\u003c/strong\u003e | \u003cstrong\u003e\u003ca href=\"https://www.linkedin.com/in/ivanluminaria\" target=\"_blank\" rel=\"noreferrer\"\u003eProfil LinkedIn\u003c/a\u003e\u003c/strong\u003e\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"profil-profesional\" class=\"relative group\"\u003eProfil Profesional \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#profil-profesional\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eProject Manager cu aproape 30 de ani de experienta in IT si un fundament tehnic solid in medii Data Warehouse si Oracle. Peste 10 proiecte livrate cu un istoric excelent de respectare a termenelor, gestionand echipe de 3-7 persoane in contexte multiculturale si remote, pe proiecte cu bugete in intervalul €100K-€500K. Competente concrete in planificare, managementul riscurilor, coordonarea resurselor si relatia cu stakeholderii — dezvoltate pe teren coordonand activitati de dezvoltare, release si mentenanta pentru clienti din sectoarele Bancar, Telco, Asigurari si Administratie Publica. Metodologii Agile (Scrum) aplicate in managementul zilnic al proiectelor, cu formare certificata. Fundament tehnic aprofundat (arhitectura DWH, Oracle DBA, PL/SQL, ETL/ELT) care permite comunicarea eficienta cu echipele de dezvoltare, evaluarea realista a fezabilitatii si identificarea timpurie a riscurilor tehnice.\u003c/p\u003e","title":"Project Manager"},{"content":"Luni dimineața. Alarma la 6:40. Duș, mic dejun rapid, cheile mașinii pe masă. Ies din casă la 7:15.\nLocuiesc în zona Appio Latino. Biroul este pe Via Crescenzio, în Prati. Opt kilometri în linie dreaptă. Ar trebui să fie cincisprezece minute. La Roma, e altă poveste.\n🚗 Dimineața cu mașina #Via Appia Nuova e deja o parcare. Porta San Giovanni, o pâlnie. Lungotevere, o procesiune funebră cu claxoane.\nCincizeci de minute pentru opt kilometri. Cincizeci de minute de ambreiaj, semafoare, dublă parcare, scutere care îți taie calea și autobuze care opresc pe banda a doua.\nDar partea cea mai bună abia urmează.\nAjung în Prati și începe vânătoarea de parcare. Via Crescenzio, plină. Via Tacito, plină. Străzile laterale, pline. Dau ture o oră și jumătate. O oră și jumătate. Târându-mă prin străzile din Prati cu motorul pornit și răbdarea sub zero.\nÎn final, epuizat, mă predau. Parcarea etajată din Piazza Cavour. \u0026ldquo;Măcar aici găsesc loc\u0026rdquo;, gândesc.\nGăsesc loc. Găsesc și nota de plată: seara, când ies, bonul spune 35 de euro.\nTreizeci și cinci de euro pentru privilegiul de a fi lăsat mașina nemișcată toată ziua.\nSă facem bilanțul dimineții:\nElement Valoare Ora de plecare de acasă 7:15 Timp în trafic 50 de minute Timp căutând parcare 1 oră și 30 de minute Ora de sosire la birou 9:35 Cost parcare 35€ Nivel de stres ████████████ 200% Productivitatea primei ore aproape de zero Două ore și douăzeci de minute. Pentru opt kilometri. Și 35 de euro mai puțin în portofel.\nÎn acea seară mă întorc acasă gândindu-mă: \u0026ldquo;Trebuie să existe altă cale.\u0026rdquo;\n🚲 Săptămâna următoare: Brompton-ul electric #Lunea următoare schimb totul.\nIes din casă la 7:30 — cu cincisprezece minute mai târziu decât săptămâna trecută. Cobor cu Brompton-ul meu electric. Îl desfac în zece secunde pe trotuar. Cască, rucsac, la drum.\nAcelași traseu. Appio Latino → San Giovanni → Celio → Lungotevere → Prati.\nDar de data asta totul e diferit.\nÎn timp ce mașinile stau în coloană, eu trec. În timp ce scuterele fac slalom printre bare de protecție, pedalez liniștit pe pista de biciclete. Nu transpir — e o bicicletă electrică, asistența la pedalare își face treaba. Nu mă stresez — nimeni nu-mi claxonează. Nu caut parcare — pliez Brompton-ul și îl urc la birou.\nOptsprezece minute. Din ușă în ușă.\nElement Valoare Ora de plecare de acasă 7:30 Timp pe bicicletă 18 minute Timp căutând parcare 0 minute Ora de sosire la birou 7:50 Cost 0€ Nivel de stres ░░░░░░░░░░░░ 0% Productivitatea primei ore maximă La 7:50 eram deja la birou. Proaspăt. Treaz. Cu cafeaua în mână și capul deja la prima sarcină a zilei.\nCu o oră și patruzeci și cinci de minute mai devreme decât săptămâna trecută.\nTreizeci și cinci de euro economisiți.\nȘi mai ales: zero stres.\n📊 Cifrele pe un an întreg #Să facem calculele serioase. Pe 220 de zile lucrătoare:\n🚗 Mașină 🚲 Brompton Timp mediu ușă-la-ușă (dus) 50 min + 30 min parcare 18 min Timp zilnic (dus-întors) ~2h 40min ~36 min Timp anual în deplasare ~587 ore ~132 ore Ore economisite cu bicicleta ~455 ore Cost anual combustibil ~1.800€ 0€ Parcare/ZTL/amenzi ~1.200€ (estimare conservatoare) 0€ Asigurare + taxă + uzură ~2.500€ 0€ Cost anual mobilitate ~5.500€ ~50€ (întreținere) Economie anuală ~5.450€ 455 de ore economisite. Sunt 57 de zile lucrătoare. Două luni și jumătate de viață returnate.\nIar acei 5.450 de euro economisiți? Sunt o vacanță. O contribuție la pensie. Costul Brompton-ului în sine, amortizat în mai puțin de un an.\n💪 Beneficiile care nu se măsoară în euro #Dar cifrele economice sunt doar o parte a poveștii. Cele care contează cu adevărat sunt celelalte.\nSănătatea cardiovasculară #A pedala 36 de minute pe zi, chiar și cu asistență electrică, înseamnă activitate fizică moderată. Organizația Mondială a Sănătății recomandă cel puțin 150 de minute de activitate aerobică pe săptămână. Mergând la muncă pe bicicletă, faci 180 fără să te gândești.\nStudii publicate în British Medical Journal arată că navetiștii pe bicicletă au:\n41% risc mai mic de deces din orice cauză 52% risc mai mic de deces din boli cardiovasculare 45% risc mai mic de a dezvolta cancer Nu sunt cifrele mele. Sunt cifrele științei, pe un eșantion de peste 250.000 de navetiști britanici urmăriți timp de cinci ani.\nSănătatea mentală #Traficul din Roma nu e doar plictisitor. Este toxic pentru minte. Stresul cronic al navetei este corelat cu:\nniveluri crescute de cortizol tulburări de somn iritabilitate și anxietate crescute reducerea capacității de concentrare Pedalatul, în schimb, eliberează endorfine. Ajungi la muncă cu creierul oxigenat, dispoziție bună și un sentiment de autonomie pe care scaunul unei mașini în trafic nu ți-l va oferi niciodată.\nCalitatea aerului #O mașină blocată în traficul din Roma produce în medie 120-150 g de CO₂ pe kilometru. În trafic congestionat, chiar mai mult — pentru că motorul funcționează în gol, consumând fără să se miște.\nO bicicletă produce zero emisii.\nDacă doar 10% dintre navetiștii romani ar trece la utilizarea zilnică a bicicletei, s-ar economisi aproximativ 150.000 de tone de CO₂ pe an. Este echivalentul plantării a 7 milioane de copaci.\nNu e idealism. E aritmetică.\n🤔 \u0026ldquo;Dar plouă, e cald, e periculos\u0026hellip;\u0026rdquo; #Știu. Cunosc toate obiecțiile. Mi le-am pus și eu.\n\u0026ldquo;Dar când plouă?\u0026rdquo;\nPlouă cam 75 de zile pe an la Roma. În zilele de ploaie puternică, iau metroul de la San Giovanni la Lepanto. Cincisprezece minute. Fără mașină nici în potop. Brompton-ul se pliază și urcă în metrou cu mine.\n\u0026ldquo;Vara e prea cald.\u0026rdquo;\nCu asistența la pedalare nu transpiri. Și chiar dacă ai transpira ușor, mai bine 18 minute în aer liber decât 50 de minute într-un habitaclu fierbinte cu aerul condiționat care-ți usucă gâtul.\n\u0026ldquo;Străzile Romei nu sunt sigure.\u0026rdquo;\nAsta e adevărat și nu minimizez. Roma are nevoie de mai multă infrastructură pentru biciclete. Dar traseul meu — Appio Latino, Celio, Lungotevere — este rezonabil de sigur, mai ales în orele de vârf când traficul e atât de lent încât mașinile merg mai încet decât bicicleta.\n\u0026ldquo;Nu pot duce bicicleta la birou.\u0026rdquo;\nBrompton-ul se pliază în 20 de secunde și devine un bagaj care încape sub birou. Asta e superputerea lui: elimină complet problema parcării.\n🌍 Nu e doar o alegere personală #Fiecare persoană care lasă mașina acasă și ia bicicleta:\neliberează un loc de parcare pentru cineva care chiar are nevoie reduce traficul pentru cei care trebuie să conducă îmbunătățește calitatea aerului pentru toți reduce poluarea fonică din cartier demonstrează că un alt model e posibil Nu cer nimănui să-și vândă mașina. Spun că pentru multe deplasări urbane — cele sub 10 km — bicicleta este obiectiv superioară mașinii. Mai rapidă, mai ieftină, mai sănătoasă, mai sustenabilă.\nIar cu o pliabilă electrică, ultimele scuze cad una câte una.\n🇪🇺 În Europa deja fac asta — și funcționează #În timp ce la Roma discutăm dacă e posibil să mergi la muncă pe bicicletă, jumătate din Europa face asta de zeci de ani.\nAmsterdam are mai multe biciclete decât locuitori — 881.000 de biciclete pentru 872.000 de rezidenți. Problema nu e să convingi oamenii să pedaleze, ci unde să parchezi toate acele biciclete. La Gara Centrală au construit cea mai mare parcare de biciclete din lume: 12.500 de locuri pe trei niveluri subterane. Douăsprezece mii cinci sute. Nu locuri de mașini. Locuri de biciclete.\nCopenhaga a atins un reper istoric: peste 60% dintre rezidenți merg la muncă cu bicicleta. Nu din ideologie, ci din practicalitate. Drumul mediu durează 13 minute. Încercați să faceți același lucru cu mașina.\nMünchen, Berlin, Viena — orașe cu ierni mult mai aspre decât Roma — au rețele ciclabile capilare și procente de cicliști urbani de care la Roma doar visăm.\nȘi nu trebuie să privim dincolo de Alpi. Milano, Bologna, Ferrara, Padova — în nordul Italiei, a pedala la muncă e normal. Nu e eroism. Nu e excentricitate. E bun simț.\nCele șapte coline? Cu electrica nu mai sunt o scuză #Știu la ce vă gândiți. \u0026ldquo;Da, dar acelea sunt orașe plate. Roma are șapte coline.\u0026rdquo;\nE adevărat. Roma are urcușuri. Celio, Aventino, Gianicolo — nu sunt exact Câmpia Padului.\nDar această obiecție avea sens acum zece ani. Azi, cu o bicicletă electrică, cele șapte coline nu mai există. Motorul te asistă la urcare, ajungi sus fără să gâfâi, fără să transpiri, fără să regreți mașina.\nBrompton-ul meu electric abordează urcușul Celio ca și cum ar fi o ușoară denivelare. Lungotevere-ul e plat. Iar tronsonul final spre Prati e în coborâre.\nRoma are 300 de zile însorite pe an, un climat blând chiar și iarna, și distanțe urbane reduse. Este — paradoxal — unul dintre cele mai potrivite orașe italiene pentru bicicletă. Ne lipsesc doar infrastructurile. Și curajul de a schimba obiceiurile.\n🏠 Bicicletă și smart working: combinația perfectă #Există o legătură profundă între alegerea bicicletei și filosofia smart working-ului. Ambele pornesc de la aceeași întrebare: \u0026ldquo;Are sens ceea ce fac, sau fac asta doar pentru că s-a făcut mereu așa?\u0026rdquo;\nSmart working-ul elimină naveta în zilele în care nu trebuie să fii la birou. Bicicleta face naveta inteligentă în zilele în care trebuie să fii acolo.\nModelul ideal? 3 zile remote, 2 la birou — pe bicicletă.\nModel Ore săptămânale în deplasare Stres Cost 5 zile cu mașina ~13 ore ridicat ~110€/săptămână 5 zile mașină + smart working (3+2) ~5 ore mediu ~44€/săptămână 2 zile bicicletă + 3 smart working ~1,2 ore zero ~0€ De la 13 ore la 1 oră și 12 minute. De la 110 euro la zero.\nNu e utopie. E organizare.\nNu e lene. E inteligență.\nDacă companiile ar combina smart working-ul cu stimulente pentru mobilitate sustenabilă, rezultatul ar fi triplu: angajați mai sănătoși, mai productivi și orașe mai locuibile. Dar pentru a ajunge acolo, trebuie să renunțăm la ideea că \u0026ldquo;a munci\u0026rdquo; înseamnă \u0026ldquo;a sta într-un birou de la 9 la 18 după o oră de mașină.\u0026rdquo;\n🎯 Bilanțul meu personal #De când am făcut schimbarea, dimineața mea arată așa:\nOra Activitate 7:00 Trezire 7:00 — 7:25 Mic dejun liniștit, știri 7:30 Plecare de acasă cu Brompton-ul 7:48 Sosire la birou, bicicleta pliată sub birou 7:50 Operațional Fără stres. Fără costuri. Fără surprize de 35 de euro.\nIar seara, la fel în sens invers: 18 minute și sunt acasă. Nu o oră. Nu \u0026ldquo;depinde de trafic\u0026rdquo;. Optsprezece minute, mereu.\nAm recuperat timp. Am recuperat bani. Am recuperat energie mentală.\nDar mai ales, am recuperat plăcerea de a mă deplasa prin oraș în loc să-l suport.\n💬 Celor care sunt încă blocați în trafic #Dacă în fiecare dimineață petreci o oră în mașină pentru un traseu pe care l-ai face în douăzeci de minute pe bicicletă.\nDacă în fiecare seară ajungi acasă epuizat, nu de la muncă, ci de la drumul până acolo.\nDacă ai calculat vreodată cât cheltuiești pe benzină, parcare și sănătate mentală.\nÎncearcă. Chiar și doar o săptămână.\nIa o bicicletă — pliabilă, electrică, care-ți place — și fă același traseu.\nUită-te la ceas când ajungi. Uită-te cum te simți. Uită-te în portofel la sfârșitul lunii.\nCifrele vorbesc de la sine.\nDar zâmbetul cu care ajungi la birou, acela, nu are preț.\nGlosar #Brompton — Bicicletă pliabilă britanică considerată referința mondială pentru calitatea construcției, compactitatea în stare pliată și practicitatea în navetismul urban.\nPedalare Asistată — Sistem de propulsie electrică care amplifică forța de pedalare, eliminând problema pantelor și a transpirației pe traseele urbane.\nBicicletă Pliabilă — Bicicletă care se pliază în 10-20 secunde devenind un bagaj transportabil la birou, în metrou sau în tren.\nNavetism — Deplasarea zilnică casă-serviciu și retur, care în marile orașe poate absorbi 2-4 ore pe zi și sute de euro pe lună.\nCarbon Footprint — Cantitatea totală de gaze cu efect de seră emise de o activitate — o mașină în traficul roman produce 120-150 g de CO₂ pe km, o bicicletă zero.\nMobilitate Durabilă — Abordare a transportului urban care privilegiază mijloace cu impact scăzut asupra mediului, reducând emisiile, traficul și costurile.\n","date":"3 martie 2026","permalink":"https://ivanluminaria.com/ro/posts/project-management/bici-vs-auto-roma/","section":"Database Strategy","summary":"\u003cp\u003eLuni dimineața. Alarma la 6:40. Duș, mic dejun rapid, cheile mașinii pe masă. Ies din casă la 7:15.\u003c/p\u003e\n\u003cp\u003eLocuiesc în zona Appio Latino. Biroul este pe Via Crescenzio, în Prati. Opt kilometri în linie dreaptă. Ar trebui să fie cincisprezece minute. La Roma, e altă poveste.\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"-dimineața-cu-mașina\" class=\"relative group\"\u003e🚗 Dimineața cu mașina \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#-diminea%c8%9ba-cu-ma%c8%99ina\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eVia Appia Nuova e deja o parcare. Porta San Giovanni, o pâlnie. Lungotevere, o procesiune funebră cu claxoane.\u003c/p\u003e","title":"Bicicletă vs Mașină la Roma: dimineața care mi-a deschis ochii"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/cycling/","section":"Tags","summary":"","title":"Cycling"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/health/","section":"Tags","summary":"","title":"Health"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/smart-working/","section":"Tags","summary":"","title":"Smart-Working"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/sustainability/","section":"Tags","summary":"","title":"Sustainability"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/urban-mobility/","section":"Tags","summary":"","title":"Urban-Mobility"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/hugepages/","section":"Tags","summary":"","title":"Hugepages"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/kernel/","section":"Tags","summary":"","title":"Kernel"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/linux/","section":"Tags","summary":"","title":"Linux"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/categories/oracle/","section":"Categories","summary":"","title":"Oracle"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/oracle/","section":"Tags","summary":"","title":"Oracle"},{"content":"Clientul era o companie de logistică cu Oracle 19c Enterprise Edition pe Oracle Linux 8. Șaizeci de utilizatori concurenți, o aplicație ERP personalizată, circa 400 GB de date. Serverul era un Dell PowerEdge cu 128 GB de RAM și 32 de core-uri.\nPlângerile erau vagi dar persistente: \u0026ldquo;Sistemul e lent.\u0026rdquo; \u0026ldquo;Query-urile de dimineață durează dublu față de acum două luni.\u0026rdquo; \u0026ldquo;Din când în când se blochează totul câteva secunde.\u0026rdquo;\nCând m-am conectat pe server, primul lucru pe care l-am verificat nu a fost baza de date. A fost sistemul de operare.\ncat /proc/meminfo | grep -i huge sysctl vm.nr_hugepages cat /sys/kernel/mm/transparent_hugepage/enabled Rezultat: zero Huge Pages configurate, Transparent Huge Pages active, parametrii kernel la valorile implicite. Instalarea Oracle fusese făcută cu asistentul, sistemul de operare nu fusese atins.\nAsta era problema. Nu era Oracle. Era Linux care nu fusese pregătit pentru Oracle.\n🔍 Diagnosticul #Înainte de a schimba orice, am măsurat starea curentă. Ai nevoie de cifre, nu de impresii.\n# Starea SGA sqlplus -s / as sysdba \u0026lt;\u0026lt;SQL SELECT name, value/1024/1024 AS mb FROM v$sgainfo WHERE name IN (\u0026#39;Maximum SGA Size\u0026#39;, \u0026#39;Free SGA Memory Available\u0026#39;); SQL # Utilizarea memoriei sistemului free -h # Parametrii kernel curenți sysctl -a | grep -E \u0026#34;kernel.sem|kernel.shm|vm.nr_hugepages|vm.swappiness\u0026#34; # I/O scheduler-ul în uz cat /sys/block/sda/queue/scheduler # Limitele utilizatorului oracle su - oracle -c \u0026#34;ulimit -a\u0026#34; Iată ce am găsit:\nParametru Valoare curentă Valoare recomandată SGA Target 64 GB 64 GB (ok) vm.nr_hugepages 0 33280 Transparent Huge Pages always never vm.swappiness 60 1 kernel.shmmax 33554432 (32 MB) 68719476736 (64 GB) kernel.shmall 2097152 16777216 kernel.sem 250 32000 100 128 250 32000 100 256 I/O scheduler mq-deadline deadline (ok) oracle nofile 1024 65536 oracle nproc 4096 16384 oracle memlock 65536 KB unlimited Aproape totul era greșit. Nu din eroare — din omisiune. Nimeni nu se obosise să configureze sistemul de operare după instalare.\n📦 Huge Pages: parametrul care schimbă totul #Huge Pages sunt parametrul individual cu cel mai mare impact pentru Oracle pe Linux. Și sunt totodată cel mai des ignorat.\nDe ce contează #Implicit, Linux gestionează memoria în pagini de 4 KB. O SGA de 64 GB înseamnă aproximativ 16,7 milioane de pagini. Fiecare pagină are o intrare în Page Table, iar sistemul trebuie să traducă adrese virtuale în fizice pentru fiecare. TLB-ul (Translation Lookaside Buffer) al CPU-ului poate memora doar câteva mii de traduceri — restul e gestionat de MMU, care e lentă.\nHuge Pages sunt pagini de 2 MB. Aceeași SGA de 64 GB devine 32.768 de pagini. TLB-ul face față, presiunea pe MMU scade, performanța se îmbunătățește.\nCum se configurează #Am calculat numărul de Huge Pages necesare:\n# SGA = 64 GB = 65536 MB # Fiecare Huge Page = 2 MB # Pagini necesare = 65536 / 2 = 32768 # Adaug 1,5% marjă → 33280 echo \u0026#34;vm.nr_hugepages = 33280\u0026#34; \u0026gt;\u0026gt; /etc/sysctl.d/99-oracle.conf sysctl -p /etc/sysctl.d/99-oracle.conf Verificare:\ngrep -i huge /proc/meminfo Output așteptat:\nHugePages_Total: 33280 HugePages_Free: 33280 HugePages_Rsvd: 0 Hugepagesize: 2048 kB După repornirea instanței Oracle, SGA-ul se alocă în Huge Pages:\nHugePages_Total: 33280 HugePages_Free: 512 HugePages_Rsvd: 480 Diferența e măsurabilă: latch free waits și library cache contention scad dramatic.\n🧱 Memorie partajată și semafoare #Oracle folosește memoria partajată a kernel-ului pentru SGA. Dacă limitele sunt prea mici, instanța nu poate aloca memoria cerută — sau mai rău, fragmentează alocarea.\ncat \u0026gt;\u0026gt; /etc/sysctl.d/99-oracle.conf \u0026lt;\u0026lt; \u0026#39;SYSCTL\u0026#39; # Shared memory kernel.shmmax = 68719476736 kernel.shmall = 16777216 kernel.shmmni = 4096 # Semaphores: SEMMSL SEMMNS SEMOPM SEMMNI kernel.sem = 250 32000 100 256 SYSCTL sysctl -p /etc/sysctl.d/99-oracle.conf Parametru Semnificație Valoare shmmax Dimensiunea maximă a unui segment de memorie partajată 64 GB shmall Pagini totale de memorie partajată alocabile 64 GB în pagini de 4K shmmni Numărul maxim de segmente de memorie partajată 4096 sem SEMMSL, SEMMNS, SEMOPM, SEMMNI 250 32000 100 256 Nu sunt valori magice. Sunt dimensionate pentru SGA-ul bazei de date. Dacă SGA-ul se schimbă, parametrii trebuie recalculați.\n💾 I/O Scheduler #Default-ul pe RHEL/Oracle Linux 8 cu dispozitive NVMe este none sau mq-deadline. Pentru discuri SAS/SATA tradiționale, default-ul poate fi bfq sau cfq.\nPentru Oracle, recomandarea este deadline (sau mq-deadline pe kernel-uri mai noi):\n# Verificare setare curentă cat /sys/block/sda/queue/scheduler # Dacă nu e deadline/mq-deadline, setează-l echo \u0026#34;deadline\u0026#34; \u0026gt; /sys/block/sda/queue/scheduler # Fă-l permanent prin GRUB grubby --update-kernel=ALL --args=\u0026#34;elevator=deadline\u0026#34; cfq (Completely Fair Queuing) e conceput pentru workload-uri desktop — distribuie I/O-ul echitabil între procese. Dar Oracle nu are nevoie de echitate: are nevoie ca cererile I/O să fie servite în ordinea care minimizează seek-urile. deadline face exact asta.\n🚫 Dezactivarea Transparent Huge Pages #Acesta e parametrul cel mai insidios. Transparent Huge Pages (THP) e o funcție a kernel-ului care pare o idee bună: kernel-ul promovează automat paginile normale la pagini mari.\nPentru Oracle e un dezastru. Procesul khugepaged lucrează în fundal pentru a compacta paginile, cauzând vârfuri de latență imprevizibile — acele \u0026ldquo;blocaje de câteva secunde\u0026rdquo; pe care clientul le raporta.\nOracle spune explicit în documentație: dezactivați THP.\n# Verificare stare curentă cat /sys/kernel/mm/transparent_hugepage/enabled # Output tipic: [always] madvise never # Dezactivare la runtime echo never \u0026gt; /sys/kernel/mm/transparent_hugepage/enabled echo never \u0026gt; /sys/kernel/mm/transparent_hugepage/defrag # Permanentizare prin GRUB grubby --update-kernel=ALL --args=\u0026#34;transparent_hugepage=never\u0026#34; După reboot, verificare:\ncat /sys/kernel/mm/transparent_hugepage/enabled # Output așteptat: always madvise [never] Diferența e clară: micro-blocajele aleatorii dispar.\n🔒 Limite de securitate #Utilizatorul oracle are nevoie de limite ridicate pentru descriptori de fișiere deschise, procese și memorie blocabilă. Default-urile Linux sunt gândite pentru utilizatori interactivi, nu pentru software care gestionează sute de conexiuni simultane.\ncat \u0026gt;\u0026gt; /etc/security/limits.d/99-oracle.conf \u0026lt;\u0026lt; \u0026#39;LIMITS\u0026#39; oracle soft nofile 65536 oracle hard nofile 65536 oracle soft nproc 16384 oracle hard nproc 16384 oracle soft stack 10240 oracle hard stack 32768 oracle soft memlock unlimited oracle hard memlock unlimited LIMITS Limită Default Recomandat De ce nofile 1024 65536 Oracle deschide un descriptor pentru fiecare datafile, redo log, archive log nproc 4096 16384 Fiecare proces Oracle e un proces OS separat memlock 65536 KB unlimited Necesar pentru blocarea SGA-ului în Huge Pages stack 8192 KB 10240-32768 KB PL/SQL recursiv profund poate epuiza stack-ul Setarea memlock unlimited e critică: fără ea, Oracle nu poate bloca SGA-ul în Huge Pages, făcând inutilă configurarea anterioară.\n⚡ Swappiness #Valoarea implicită a vm.swappiness este 60. Asta înseamnă că Linux începe să facă swap când presiunea pe memorie e încă scăzută. Pentru un server de baze de date dedicat, asta e inacceptabil: vrei ca SGA-ul să rămână în RAM, mereu.\necho \u0026#34;vm.swappiness = 1\u0026#34; \u0026gt;\u0026gt; /etc/sysctl.d/99-oracle.conf sysctl -p /etc/sysctl.d/99-oracle.conf Nu zero — unu. Valoarea zero dezactivează complet swap-ul, ceea ce poate declanșa OOM killer în situații de presiune extremă. Valoarea unu îi spune kernel-ului: \u0026ldquo;Fă swap doar când chiar nu mai e alternativă.\u0026rdquo;\n📊 Înainte și după #După aplicarea tuturor configurărilor și repornirea instanței Oracle, am refăcut măsurătorile.\nMetrică Înainte După Variație SGA în Huge Pages Nu Da — Library cache hit ratio 92,3% 99,7% +7,4% Buffer cache hit ratio 94,1% 99,2% +5,1% Timp mediu așteptare (db file sequential read) 8,2 ms 1,4 ms -83% Micro-blocaje aleatorii (\u0026gt;1s) 5-8 pe zi 0 -100% Timp mediu batch matinal 47 min 22 min -53% Utilizare CPU medie 78% 41% -47% Swap utilizat 3,2 GB 0 MB -100% Cifrele vorbesc de la sine. Aceeași mașină, aceeași bază de date, aceeași sarcină de lucru. Singura diferență: sistemul de operare a fost configurat să-și facă treaba.\n📋 Checklist final #Pentru cine dorește un rezumat operațional, iată checklist-ul complet:\n# /etc/sysctl.d/99-oracle.conf vm.nr_hugepages = 33280 vm.swappiness = 1 kernel.shmmax = 68719476736 kernel.shmall = 16777216 kernel.shmmni = 4096 kernel.sem = 250 32000 100 256 # /etc/security/limits.d/99-oracle.conf oracle soft nofile 65536 oracle hard nofile 65536 oracle soft nproc 16384 oracle hard nproc 16384 oracle soft stack 10240 oracle hard stack 32768 oracle soft memlock unlimited oracle hard memlock unlimited # GRUB grubby --update-kernel=ALL --args=\u0026#34;transparent_hugepage=never elevator=deadline\u0026#34; Zece minute de configurare. Fără cost hardware. Fără licențe suplimentare.\nDar nimeni nu face asta, pentru că asistentul nu întreabă, documentația e îngropată într-o notă MOS, iar sistemul \u0026ldquo;funcționează și fără.\u0026rdquo; Funcționează. Prost. Iar vina cade mereu pe Oracle, niciodată pe faptul că nimeni nu a pregătit terenul.\nO bază de date e la fel de bună ca sistemul de operare pe care rulează. Iar un sistem de operare lăsat la valorile implicite e un sistem de operare care lucrează împotriva ta.\nGlosar #Huge Pages — Pagini de memorie de 2 MB (în loc de cele standard de 4 KB) care reduc drastic presiunea pe MMU și TLB, îmbunătățind performanțele Oracle pe Linux.\nTHP — Transparent Huge Pages — funcție a kernelului Linux care promovează automat paginile normale la pagini mari, dar care cauzează latențe imprevizibile și trebuie dezactivată pentru Oracle.\nSGA — System Global Area — zona de memorie partajată a Oracle Database care conține buffer cache, shared pool, redo log buffer și alte structuri critice pentru performanță.\nI/O Scheduler — Componentă a kernelului Linux care decide ordinea în care cererile de I/O sunt trimise către disc, cu impact direct asupra performanțelor bazei de date.\nSwappiness — Parametru kernel Linux (vm.swappiness) care controlează propensiunea sistemului de a muta pagini de memorie în swap, critic pentru serverele de baze de date.\n","date":"24 februarie 2026","permalink":"https://ivanluminaria.com/ro/posts/oracle/oracle-linux-kernel/","section":"Database Strategy","summary":"\u003cp\u003eClientul era o companie de logistică cu Oracle 19c Enterprise Edition pe Oracle Linux 8. Șaizeci de utilizatori concurenți, o aplicație ERP personalizată, circa 400 GB de date. Serverul era un Dell PowerEdge cu 128 GB de RAM și 32 de core-uri.\u003c/p\u003e\n\u003cp\u003ePlângerile erau vagi dar persistente: \u0026ldquo;Sistemul e lent.\u0026rdquo; \u0026ldquo;Query-urile de dimineață durează dublu față de acum două luni.\u0026rdquo; \u0026ldquo;Din când în când se blochează totul câteva secunde.\u0026rdquo;\u003c/p\u003e\n\u003cp\u003eCând m-am conectat pe server, primul lucru pe care l-am verificat nu a fost baza de date. A fost sistemul de operare.\u003c/p\u003e","title":"Oracle pe Linux: parametrii kernel pe care nimeni nu-i configurează"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/productivity/","section":"Tags","summary":"","title":"Productivity"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/remote-work/","section":"Tags","summary":"","title":"Remote-Work"},{"content":"6:47 într-o marți obișnuită. Sunt în parcul de lângă casă, echipat pentru alergare. Aerul e proaspăt, soarele abia răsare. Am făcut deja patru kilometri. Mă simt viu.\nLa 7:00 sunt la duș. La 7:20 iau micul dejun în liniște. La 7:45 sunt la birou, odihnit, concentrat, gata de lucru.\nLa aceeași oră, un coleg al meu e încă blocat pe Pontina. Sau pe raccordo, între Casilina și Tuscolana. Are deja telefonul în mână — nu ca să lucreze, ci ca să trimită mesajul clasic: \u0026ldquo;Scuze, întârzii, a fost un accident.\u0026rdquo;\nDoi oameni. Același job. Același contract.\nUnul e deja productiv. Celălalt își arde cele mai bune energii într-un habitaclu.\nAsta nu e o opinie. Sunt fapte.\nIar faptele au cifre.\n🚗 Costul invizibil al navetismului la Roma #Să fim sinceri: Roma nu e un oraș. E un organism haotic care se mișcă în sughițuri.\nPentru cine lucrează în consultanță IT și locuiește în afara centrului — iar la Roma, \u0026ldquo;în afara centrului\u0026rdquo; înseamnă practic peste tot — drumul casă-birou e o aventură zilnică.\nSă facem calculele pe un scenariu real:\nElement Valoare Distanța casă-birou ~30 km (un sfert din raccordo) Timp mediu dus 1h 15min — 2h 30min Timp mediu întors 1h — 1h 45min Timp total zilnic în mașină 2h 15min — 4h 15min Zile lucrătoare pe lună 21 Ore pierdute pe lună în mașină 47 — 89 ore Cost combustibil lunar (~30km x 2 x 21 zile) ~250-300€ Uzură mașină, asigurare, parcare ~150-200€/lună Cost total lunar navetism ~400-500€ Aproape 90 de ore pe lună în cazul cel mai rău. Sunt mai mult de două săptămâni de lucru petrecute în mașină. Nu lucrând. Nu gândind. Înjurând traficul.\nȘi încă n-am numărat stresul. Frustrarea. Energia mentală arsă înainte să apuci să pornești calculatorul.\n🏃 Cealaltă față a monedei: dimineața celui care lucrează de acasă #Iată ziua mea tipică:\nOra Activitate 6:00 Trezire 6:10 — 6:45 Alergare în parc (4-5 km) 6:50 — 7:10 Duș 7:10 — 7:30 Mic dejun în liniște 7:30 — 7:45 Pregătire stație de lucru, cafea, revizie agendă 7:45 Început lucru Ajung la birou după ce am făcut sport, după ce am respirat aer curat, după ce am avut timp să gândesc. Nu ajung după ce am luptat într-un război.\nDiferența nu e doar fizică. E cognitivă.\nUn consultant IT lucrează cu mintea. Analizează sisteme, scrie cod, proiectează arhitecturi, rezolvă probleme complexe. Dacă acea minte ajunge la birou deja descărcată, deja frustrată, deja obosită — cât valorează cu adevărat acea zi de muncă?\nAm lucrat cu echipe distribuite pe trei fusuri orare. Am gestionat baze de date critice conectându-mă de acasă la 3 noaptea pentru o urgență. N-am avut niciodată nevoie de un birou pentru a-mi face treaba. Am avut nevoie de o conexiune stabilă, un mediu liniștit și o minte limpede.\n📊 Cifrele pentru companie: ce nu vor să vadă directorii financiari #Companiile de consultanță IT din Roma au o problemă structurală pe care se prefac că nu o au.\nSă luăm o companie cu 50 de consultanți. Să facem calculele:\nCostul navetismului corporativ # Element Calcul Total anual Ore pierdute în mașină (medie 3h/zi x 50 persoane) 150 ore/zi x 220 zile 33.000 ore/an Valoarea orei de consultant (cost mediu companie) 33.000 x 35€/oră ~1.155.000€/an Chirie birou Roma (50 stații de lucru) ~800€/stație/lună ~480.000€/an Utilități, curățenie, întreținere ~60.000€/an Cost total estimat ~1.695.000€/an Un milion șapte sute de mii de euro. În fiecare an. Ca să ții cincizeci de oameni așezați în același loc.\nScenariul smart working (80% remote) # Element Calcul Total anual Ore recuperate (80% din 33.000) 26.400 ore convertite în muncă productivă Birou redimensionat (15 stații hot-desk) ~800€ x 15 ~144.000€/an Contribuție conectivitate angajați 50€/lună x 50 ~30.000€/an Buget echipament home office (o singură dată) 1.000€ x 50 50.000€ (anul 1) Cost total estimat (anul 1) ~224.000€ Cost total estimat (din anul 2) ~174.000€ Economie anuală: peste 1.400.000€.\nȘi fac estimări conservatoare.\nDar cifra cea mai importantă nu e cea financiară.\nCifra cea mai importantă sunt acele 26.400 de ore redate productivității.\nOre în care oamenii lucrează lucizi, odihniți, concentrați.\nNu ore în care se uită la un parbrize pe Cristoforo Colombo.\n🧠 Argumentul pe care nimeni nu are curajul să-l facă #O spun clar: prezentismul la birou în consultanța IT e un vestigiu cultural, nu o necesitate operațională.\nConsultantul IT nu lucrează pe bandă de montaj. Nu trebuie să fie fizic prezent lângă o mașină. Are nevoie de:\no conexiune la internet rapidă un mediu liniștit instrumente digitale adecvate comunicare clară cu echipa obiective măsurabile Toate acestea se fac mai bine de acasă decât într-un open space zgomotos unde telefonul sună la fiecare cinci minute și cineva te întrerupe să te întrebe \u0026ldquo;ai un minut?\u0026rdquo; (care nu e niciodată doar un minut).\nProblema reală e controlul. Unele companii nu știu să gestioneze munca pe obiective. Știu doar să gestioneze prezența. Și confundă cele două lucruri.\nDacă un consultant închide 20 de tichete într-o săptămână lucrând de acasă în pantaloni scurți, e mai productiv decât unul care închide 8 în costum la birou de la 9 la 18.\nCifrele nu mint. Scaunele de birou, da.\n🏢 \u0026ldquo;Dar cultura companiei? Spiritul de echipă?\u0026rdquo; #Aud asta des. Înțeleg. Nu sunt de acord, dar înțeleg.\nCultura companiei nu se construiește punând oamenii să stea unul lângă altul. Se construiește cu:\nobiective comune pe care toți le înțeleg comunicare transparentă pe care nimeni nu o suportă cu greu momente de întâlnire care au sens — nu ședința săptămânală unde toți se uită la telefon sub masă încredere reciprocă — care e exact ce lipsește când impui prezența O echipă care lucrează bine de la distanță e o echipă care a învățat să comunice cu adevărat. Nu prin proximitate fizică, ci prin claritate.\nAm văzut echipe la birou care nu-și vorbeau. Și echipe distribuite în trei țări care funcționau ca ceasurile elvețiene.\nDiferența nu e locul. E metoda.\n🎯 Propunerea concretă #Dacă gestionezi o companie de consultanță IT la Roma — sau în orice oraș mare cu probleme de mobilitate — iată ce îți sugerez:\n1. Adoptă un model 80/20\n80% remote, 20% la birou. Zilele la birou sunt pentru workshop-uri, revizii de proiect, momente reale de team building — nu pentru încălzit scaunul.\n2. Investește în stația de lucru de acasă\n1.000€ o singură dată per angajat: monitor, scaun ergonomic, căști cu microfon. E o investiție care se amortizează în două săptămâni de economie la chirie.\n3. Măsoară rezultatele, nu orele\nDefinește KPI clari: tichete închise, cod livrat, SLA respectate, clienți mulțumiți. Cine produce, produce — indiferent de unde se află.\n4. Redu spațiile fizice\nTreci de la 50 de birouri fixe la 15 hot desk-uri. Folosește spațiul economisit pentru o sală de ședințe decentă și o zonă de relaxare reală.\n5. Ai încredere în oamenii tăi\nDacă ai angajat profesioniști, tratează-i ca profesioniști. Dacă nu ai încredere în ei fără să-i vezi, problema nu e smart working-ul. E procesul de recrutare.\n💬 Pentru cei care se regăsesc în această poveste #Dacă în fiecare dimineață te trezești cu o oră mai devreme decât e necesar ca să \u0026ldquo;bați traficul\u0026rdquo; — și tot ajungi târziu.\nDacă cheltuiești 500€ pe lună pentru privilegiul de a sta în coadă.\nDacă ajungi la birou deja obosit, deja nervos, deja cu ziua compromisă.\nSă știi că nu trebuie să fie așa.\nExistă un mod diferit de a munci. Mai inteligent. Mai uman. Mai productiv.\nIar cifrele o demonstrează.\nNu e nevoie de revoluții. E nevoie de curajul de a privi acele cifre.\nȘi de a acționa în consecință.\nEu, între timp, mâine dimineață mă trezesc la 6, merg la alergat, și la 7:45 sunt operațional.\nCu zâmbetul pe buze. Fără trafic. Fără stres.\nȘi cu mintea deja la prima problemă de rezolvat.\nGlosar #Smart Working — Model de lucru flexibil care combină munca la distanță și prezența la birou, bazat pe obiective măsurabile în loc de program și prezență fizică.\nNavetism — Deplasarea zilnică casă-serviciu și retur, care în marile orașe poate absorbi 2-4 ore pe zi și sute de euro pe lună.\nPresenteism — Cultură organizațională care echivalează prezența fizică la birou cu productivitatea, indiferent de rezultatele efectiv produse.\nKPI — Key Performance Indicator — metrică măsurabilă care evaluează eficacitatea unei activități față de un obiectiv definit, folosită pentru a măsura rezultate concrete în loc de ore de prezență.\nHot Desk — Model de organizare a spațiilor de birou în care posturile nu sunt atribuite: cine vine la birou ocupă un birou liber.\n","date":"24 februarie 2026","permalink":"https://ivanluminaria.com/ro/posts/project-management/smartworking-consulenza-it/","section":"Database Strategy","summary":"\u003cp\u003e6:47 într-o marți obișnuită. Sunt în parcul de lângă casă, echipat pentru alergare. Aerul e proaspăt, soarele abia răsare. Am făcut deja patru kilometri. Mă simt viu.\u003c/p\u003e\n\u003cp\u003eLa 7:00 sunt la duș. La 7:20 iau micul dejun în liniște. La 7:45 sunt la birou, odihnit, concentrat, gata de lucru.\u003c/p\u003e\n\u003cp\u003eLa aceeași oră, un coleg al meu e încă blocat pe Pontina. Sau pe raccordo, între Casilina și Tuscolana. Are deja telefonul în mână — nu ca să lucreze, ci ca să trimită mesajul clasic: \u0026ldquo;Scuze, întârzii, a fost un accident.\u0026rdquo;\u003c/p\u003e","title":"Smart working în consultanța IT: cifrele pe care nimeni nu vrea să le vadă"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/tuning/","section":"Tags","summary":"","title":"Tuning"},{"content":"În aproape treizeci de ani de activitate nu mi-am schimbat profesia.\nAm schimbat profunzimea.\nFiecare rol pe care l-am asumat nu a fost o mișcare laterală.\nA fost o aprofundare verticală.\nCeea ce ofer astăzi nu este o listă de competențe.\nEste suma consecințelor pe care aceste competențe le generează.\nData Warehouse Architect #Experiența mea în Data Warehouse s-a dezvoltat în medii în care datele reprezintă infrastructură critică.\nAm lucrat pentru mari operatori Telco precum TIM, Wind, Vodafone și 3, în proiecte internaționale cu Huawei,\nîn sectorul asigurărilor cu Generali,\nîn medii instituționale precum Banca Italiei, Oficiul Italian pentru Schimburi și Cassa Depositi e Prestiti,\nîn industria farmaceutică,\nși în sectorul auto cu Rover și Alfa Romeo.\nDomenii diferite. Aceeași cerință: fiabilitate.\nÎn Telco contează scala.\nÎn banking și instituții publice contează precizia normativă.\nÎn asigurări contează coerența riscului.\nÎn farmaceutic contează conformitatea.\nÎn automotive contează sincronizarea proceselor și calitatea datelor pe întregul lanț de aprovizionare.\nAm proiectat arhitecturi de date în medii în care marja de eroare nu este acceptată.\n👉 Citește roadmap-ul competențelor și experienței mele ca Data Warehouse Architect | Descarcă PDF\nProject Manager cu background tehnic #Experiența mea în management de proiect s-a maturizat coordonând inițiative în medii complexe:\nTelecomunicații internaționale, Instituții financiare centrale, Asigurări, Farmaceutic, Automotive și Administrație Publică.\nÎn aceste sectoare, eroarea are un cost real.\nUn Project Manager tehnic înțelege impactul deciziilor. Știe când un compromis este acceptabil. Și când nu este.\nConectez viziunea strategică cu detaliul tehnic. Roadmap-urile cu implementarea. Deciziile cu consecințele.\n👉 Citește roadmap-ul competențelor și experienței mele ca Project Manager | Descarcă PDF\nOracle DBA \u0026amp; Performance Tuning Expert #Activitatea mea ca Oracle DBA s-a consolidat în medii mission-critical pentru operatori precum TIM, Wind, Vodafone și 3, în contexte tehnologice complexe precum Huawei, pentru instituții financiare precum Banca Italiei, Oficiul Italian pentru Schimburi și Cassa Depositi e Prestiti, pentru organizații de asigurări precum Generali, și în proiecte industriale din sectorul automotive.\nSisteme cu disponibilitate ridicată. Încărcări mari. Responsabilitate reală de on-call.\nAici tuning-ul nu este o îmbunătățire estetică. Este protecție operațională.\n👉 Citește roadmap-ul competențelor și experienței mele ca Oracle DBA | Descarcă PDF\nOracle PL/SQL – Senior \u0026amp; Mentor #Am dezvoltat PL/SQL în medii Telco, Banking, Asigurări, Automotive, Farmaceutic și Administrație Publică.\nÎn contexte precum Generali sau Banca Italiei, logica din baza de date este parte integrantă a stabilității sistemului. În automotive, coerența datelor influențează direct procesele de producție și lanțul de aprovizionare.\nTimp de ani de zile am predat SQL și PL/SQL, contribuind la creșterea tehnică a dezvoltatorilor care astăzi lucrează pe sisteme complexe.\nAstăzi nu mă limitez la a scrie cod. Pot conduce. Pot face mentoring. Pot ajuta dezvoltatorii să crească în profunzime tehnică și arhitecturală.\n👉 Citește roadmap-ul competențelor și experienței mele ca Oracle PL/SQL Developer | Descarcă PDF\n","date":null,"permalink":"https://ivanluminaria.com/ro/resumes/","section":"Know-How \u0026 Impact","summary":"\u003cp\u003eÎn aproape treizeci de ani de activitate nu mi-am schimbat profesia.\u003c/p\u003e\n\u003cp\u003eAm schimbat profunzimea.\u003c/p\u003e\n\u003cp\u003eFiecare rol pe care l-am asumat nu a fost o mișcare laterală.\u003cbr\u003e\nA fost o aprofundare verticală.\u003c/p\u003e\n\u003cp\u003eCeea ce ofer astăzi nu este o listă de competențe.\u003cbr\u003e\nEste suma consecințelor pe care aceste competențe le generează.\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"data-warehouse-architect\" class=\"relative group\"\u003eData Warehouse Architect \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#data-warehouse-architect\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eExperiența mea în Data Warehouse s-a dezvoltat în medii în care datele reprezintă infrastructură critică.\u003c/p\u003e","title":"Know-How \u0026 Impact"},{"content":" IVAN LUMINARIA Oracle, PostgreSQL \u0026 MySQL Expert | DWH Architect | Project Manager Profesionist IT cu aproximativ 30 de ani de experiență în proiectarea, implementarea și gestionarea soluțiilor de baze de date și Data Warehouse în medii Oracle, PostgreSQL și MySQL. LinkedIn: ivanluminaria\nEmail: ivan (dot) luminaria (at) gmail (dot) com Lucrez cu baze de date de aproximativ treizeci de ani.\nSuficient timp pentru a vedea cum se schimbă motoarele, limbajele, tendințele și sloganurile.\nSuficient timp pentru a ști că, dincolo de suprafață, regulile rămân aceleași.\nO bază de date nu este un simplu container.\nEste un organism.\nRespiră.\nObosește.\nSe blochează.\nSau scalează.\nAm început în medii Oracle mission-critical, când „mission-critical” nu era o expresie pentru slide-uri.\nEra diferența dintre un sistem care rezistă și unul care cade la trei dimineața.\nAm petrecut nenumărate ore analizând AWR, ASH și planuri de execuție.\nAm văzut sisteme încetinind „fără un motiv aparent”.\nȘi am învățat că există întotdeauna un motiv.\nTrebuie doar căutat metodic.\nApoi au venit PostgreSQL și MySQL.\nInstrumente diferite.\nFilosofii diferite.\nAceeași disciplină.\nÎnțelege motorul.\nNu lupta împotriva lui.\nNu cred în optimizări miraculoase.\nCred în statistici actualizate.\nÎn modele de date corecte.\nÎn diferența dintre „funcționează” și „rezistă”.\nPentru că o bază de date lentă nu este doar o problemă tehnică.\nEste o problemă de business.\nEste un raport care nu ajunge.\nUn client care așteaptă.\nO decizie luată prea târziu.\nȘi exact acolo îmi place să fiu —\nunde tehnologia produce impact real.\nCum lucrez #Nu mă limitez la a „administra” baze de date.\nLe observ.\nLe măsor.\nLe testez la limită.\nLe securizez.\nMă ocup de performance tuning în medii complexe — Oracle, RAC, Exadata — dar și de PostgreSQL și MySQL în contexte moderne, adesea open source, unde lipsa „magiei proprietare” te obligă să înțelegi cu adevărat ce se întâmplă sub capotă.\nProiectez arhitecturi Data Warehouse pentru că datele nu sunt menite să fie stocate.\nSunt menite să fie înțelese.\nAm lucrat cu modele multidimensionale, procese ETL/ELT și fluxuri care trebuie să fie fiabile înainte de a fi rapide.\nPentru că datele greșite, chiar dacă ajung în milisecunde, rămân greșite.\nScriu PL/SQL când este necesar.\nOptimizez când trebuie.\nRefactorizez când este inevitabil.\nNu mă interesează efectul spectaculos.\nMă interesează soliditatea.\nViziune #De-a lungul anilor am combinat profunzimea tehnică cu o perspectivă mai largă.\nAm coordonat echipe internaționale mici.\nAm transformat cerințe de business în decizii tehnice sustenabile.\nAm învățat că complexitatea nu dispare.\nSe gestionează.\nAgile, Scrum, procese structurate — instrumente utile.\nDar fără competență reală, rămân doar etichete.\nPentru mine, leadership înseamnă ceva simplu:\na lua decizii tehnice care rezistă în timp.\nDincolo de muncă #În afara muncii cultiv pasiuni care, în esență, vorbesc aceeași limbă.\nFotografia m-a învățat că lumina potrivită schimbă povestea.\nMuzica — învăț saxofonul și cânt la chitară — îmi amintește că tehnica fără sensibilitate este doar zgomot.\nGătitul este arhitectură comestibilă: echilibru, timp, proporție.\nȘahul este strategie pură: fiecare mutare este o alegere, fiecare alegere are consecințe.\nPoate de aceea mă simt confortabil în sisteme complexe.\nNu mă intimidează.\nMă fascinează.\nÎmi place să intru în detalii.\nDar doar pentru a face ca întregul să funcționeze mai bine.\nNu construiesc baze de date.\nConstruiesc soliditate.\n\u0026ldquo;Transform complexitatea datelor în valoare strategică pentru business.\u0026rdquo;\n","date":"20 februarie 2026","permalink":"https://ivanluminaria.com/ro/about/","section":"Ivan Luminaria","summary":"\u003cdiv class=\"profile-header flex flex-col sm:flex-row sm:items-center items-start\"\u003e\n  \u003cdiv class=\"flex-none\"\u003e\n    \u003cimg\n      src='https://ivanluminaria.com/img/ivan_luminaria_avatar.png'\n      alt=\"Ivan Luminaria\"\n      class=\"profile-avatar rounded-full shadow-xl border-4 border-slate-100\"\u003e\n  \u003c/div\u003e\n  \u003cdiv class=\"profile-text text-left\"\u003e\n    \u003ch1 class=\"mb-1\"\u003eIVAN LUMINARIA\u003c/h1\u003e\n    \u003ch3 class=\"mt-0 text-slate-500\"\u003e\n      Oracle, PostgreSQL \u0026 MySQL Expert | DWH Architect | Project Manager\n    \u003c/h3\u003e\n    \u003cp class=\"mt-4\"\u003e\n      Profesionist IT cu aproximativ \u003cstrong\u003e30 de ani de experiență\u003c/strong\u003e în proiectarea, implementarea și gestionarea soluțiilor de baze de date și Data Warehouse în medii Oracle, PostgreSQL și MySQL.\n    \u003c/p\u003e\n    \u003cp class=\"mt-2\" style=\"font-size: 0.9em;\"\u003e\n      \u003cstrong\u003eLinkedIn:\u003c/strong\u003e \u003ca href=\"https://www.linkedin.com/in/ivanluminaria/\" target=\"_blank\" rel=\"noopener\"\u003eivanluminaria\u003c/a\u003e\u003cbr\u003e\n      \u003cstrong\u003eEmail:\u003c/strong\u003e ivan (dot) luminaria (at) gmail (dot) com\n    \u003c/p\u003e\n  \u003c/div\u003e\n\u003c/div\u003e\n\u003chr\u003e\n\u003cp\u003eLucrez cu baze de date de aproximativ treizeci de ani.\u003c/p\u003e","title":"Despre mine"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/cluster/","section":"Tags","summary":"","title":"Cluster"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/galera/","section":"Tags","summary":"","title":"Galera"},{"content":"Tichetul era laconic, cum se întâmplă adesea când problema e gravă: \u0026ldquo;Baza de date a căzut din nou. Aplicația e oprită. A treia oară în două luni.\u0026rdquo;\nClientul avea un MariaDB pe un singur server Linux — o aplicație de gestiune de afaceri folosită de aproximativ două sute de utilizatori interni, cu vârfuri de încărcare în timpul închiderilor contabile de sfârșit de lună. De fiecare dată când serverul avea o problemă — un disc care se încetinea, o actualizare de sistem care necesita restart, un proces care consuma toată memoria RAM — baza de date cădea și cu ea întreaga operativitate a companiei.\nÎntrebarea nu era \u0026ldquo;cum reparăm serverul\u0026rdquo;. Întrebarea era: cum facem astfel încât data viitoare când un server are o problemă, aplicația să continue să funcționeze?\nRăspunsul, după douăzeci de ani de experiență cu acest tip de scenarii, era unul singur: Galera Cluster.\nDiagnosticul: un single point of failure clasic #Primul lucru pe care l-am făcut a fost să analizez infrastructura. Tabloul era familiar:\nUn singur server MariaDB, nicio replică Backup nocturn pe disc extern (măcar atât) Niciun mecanism de failover Aplicația indica direct IP-ul serverului de baze de date Fiecare oprire, chiar și de zece minute, însemna două sute de persoane blocate. În timpul închiderilor contabile, însemna întârzieri care se propagau în cascadă în procesele de afaceri.\nAm propus clientului o soluție bazată pe Galera Cluster: trei noduri MariaDB cu replicare sincronă multi-master. Orice nod acceptă citiri și scrieri, datele sunt coerente pe toate trei, iar dacă un nod cade, celelalte două continuă să servească aplicația fără întrerupere.\nClientul avea deja la dispoziție trei VM Linux — echipa de infrastructură le provizionase pentru un alt proiect care fusese amânat. Perfect: nu trebuia nici măcar să comande hardware.\nPlanul: trei noduri, zero single point of failure #Mașinile disponibile:\nNod Hostname IP Nod 1 db-node1 10.0.1.11 Nod 2 db-node2 10.0.1.12 Nod 3 db-node3 10.0.1.13 O premisă importantă: Galera nu este o opțiune nativă în MySQL Community. Se folosește MariaDB (care îl integrează nativ) sau Percona XtraDB Cluster (bazat pe MySQL). Clientul folosea deja MariaDB, deci alegerea era naturală și nu necesita migrare de motor.\nObiectivul era clar: migrarea de la o arhitectură cu un singur nod la un cluster cu trei noduri, fără a modifica aplicația în afară de adresa de conexiune.\nInstalare: aceeași versiune pe toate nodurile #Primul principiu nenegociabil: toate nodurile trebuie să aibă exact aceeași versiune de MariaDB. Am văzut clustere instabile luni de zile pentru că cineva actualizase un nod și nu pe celelalte.\nPe toate cele trei servere:\n# Adăugarea repository-ului oficial MariaDB (exemplu pentru 11.4 LTS) curl -LsS https://downloads.mariadb.com/MariaDB/mariadb_repo_setup | \\ sudo bash -s -- --mariadb-server-version=\u0026#34;mariadb-11.4\u0026#34; # Instalarea MariaDB Server și a plugin-ului Galera sudo dnf install MariaDB-server MariaDB-client galera-4 -y # Activare dar NU porni serviciul încă sudo systemctl enable mariadb Nu porni serviciul. Mai întâi se configurează. Întotdeauna.\nInima configurării: /etc/my.cnf.d/galera.cnf #Acesta este fișierul care definește comportamentul clusterului. Trebuie creat pe fiecare nod, cu diferențele corespunzătoare pentru adresa IP și numele nodului.\nIată configurarea completă pentru Nodul 1:\n[mysqld] # === Motor și charset === binlog_format=ROW default_storage_engine=InnoDB innodb_autoinc_lock_mode=2 innodb_flush_log_at_trx_commit=2 innodb_buffer_pool_size=1G # === Configurare WSREP (Galera) === wsrep_on=ON wsrep_provider=/usr/lib64/galera-4/libgalera_smm.so # Lista TUTUROR nodurilor din cluster wsrep_cluster_address=\u0026#34;gcomm://10.0.1.11,10.0.1.12,10.0.1.13\u0026#34; # Numele clusterului (trebuie să fie identic pe toate nodurile) wsrep_cluster_name=\u0026#34;galera_productie\u0026#34; # Identitatea ACESTUI nod (se schimbă pe fiecare server) wsrep_node_address=\u0026#34;10.0.1.11\u0026#34; wsrep_node_name=\u0026#34;db-node1\u0026#34; # Metoda SST (State Snapshot Transfer) wsrep_sst_method=mariabackup wsrep_sst_auth=\u0026#34;sst_user:parola_sigura_aici\u0026#34; # === Rețea === bind-address=0.0.0.0 Pentru Nodul 2 și Nodul 3, singurul lucru care se schimbă este:\n# Nod 2 wsrep_node_address=\u0026#34;10.0.1.12\u0026#34; wsrep_node_name=\u0026#34;db-node2\u0026#34; # Nod 3 wsrep_node_address=\u0026#34;10.0.1.13\u0026#34; wsrep_node_name=\u0026#34;db-node3\u0026#34; Tot restul este identic. Identic. Nu ceda tentației de a \u0026ldquo;personaliza\u0026rdquo; buffer pool sau alți parametri per nod: într-un cluster Galera, simetria este o virtute.\nDe ce contează fiecare parametru #Să vedem parametrii unul câte unul, pentru că fiecare are un motiv precis.\nbinlog_format=ROW #Galera necesită formatul ROW pentru binary log. Nu STATEMENT, nu MIXED. ROW și atât. Cu alte formate clusterul nici nu pornește — și pe bună dreptate, deoarece replicarea sincronă bazată pe certification depinde de precizia la nivel de rând.\ninnodb_autoinc_lock_mode=2 #Acest parametru setează modul de blocare pentru auto-increment la \u0026ldquo;interleaved\u0026rdquo;. Într-un cluster multi-master, două noduri pot genera INSERT simultan pe aceeași tabelă. Cu lock mode 1 (implicit) s-ar crea deadlock-uri. Cu valoarea 2, InnoDB generează auto-increment-urile fără lock global, permițând inserări concurente de pe noduri diferite.\nConsecința: ID-urile auto-increment nu vor fi secvențiale între noduri. Dacă aplicația ta depinde de secvențialitatea ID-urilor, ai o problemă arhitecturală de rezolvat în amonte.\ninnodb_flush_log_at_trx_commit=2 #Aici se face un compromis conștient. Valoarea 1 (implicită) garantează durabilitate totală — fiecare commit este scris și fsynced pe disc. Dar într-un cluster Galera, durabilitatea este deja garantată de replicarea sincronă pe trei noduri. Valoarea 2 scrie în buffer-ul sistemului de operare la fiecare commit și face fsync doar în fiecare secundă, îmbunătățind performanța de scriere cu 30-40% în testele noastre.\nDacă pierzi un nod, datele sunt pe celelalte două. Dacă pierzi întregul datacenter\u0026hellip; ei bine, asta e altă discuție.\nwsrep_sst_method=mariabackup #SST este mecanismul prin care un nod care se alătură clusterului primește o copie completă a datelor. Opțiunile sunt:\nMetodă Pro Contra rsync Rapid Nodul donator se blochează pe citire mariabackup Nu blochează donatorul Necesită instalare separată mysqldump Simplu Foarte lent, blochează donatorul Întotdeauna mariabackup. În producție, blocarea unui nod donator în timpul unui SST înseamnă degradarea clusterului exact în momentul în care ai cea mai mare nevoie de el.\n# Instalarea mariabackup pe toate nodurile sudo dnf install MariaDB-backup -y Firewall: porturile pe care Galera le necesită deschise #Acesta este punctul în care văd 50% din primele instalări eșuând. Galera nu folosește doar portul MySQL.\n# Pe toate cele trei noduri sudo firewall-cmd --permanent --add-port=3306/tcp # MySQL standard sudo firewall-cmd --permanent --add-port=4567/tcp # Comunicare cluster Galera sudo firewall-cmd --permanent --add-port=4567/udp # Replicare multicast (opțional) sudo firewall-cmd --permanent --add-port=4568/tcp # IST (Incremental State Transfer) sudo firewall-cmd --permanent --add-port=4444/tcp # SST (State Snapshot Transfer) sudo firewall-cmd --reload Dacă SELinux este activ (și ar trebui să fie), ai nevoie și de politici:\nsudo setsebool -P mysql_connect_any 1 Patru porturi. Patru. Nici unul în plus, nici unul în minus. Dacă uiți unul, clusterul se formează dar nu sincronizează — iar debug-ul devine un exercițiu de frustrare.\nMigrarea datelor și bootstrap-ul #Înainte de a porni clusterul, am migrat datele de pe serverul standalone pe Nodul 1 cu un dump complet:\n# Pe vechiul server standalone mysqldump --all-databases --single-transaction --routines --triggers \\ --events \u0026gt; /tmp/full_dump.sql # Transfer pe Nodul 1 scp /tmp/full_dump.sql db-node1:/tmp/ Apoi bootstrap-ul — momentul adevărului. Primul nod nu se pornește cu systemctl start mariadb. Se pornește cu comanda de bootstrap.\nDoar pe Nodul 1:\nsudo galera_new_cluster Această comandă pornește MariaDB cu wsrep_cluster_address=gcomm:// (gol), ceea ce înseamnă: \u0026ldquo;Eu sunt fondatorul, nu caut alte noduri.\u0026rdquo;\nImportul datelor și crearea utilizatorului SST:\n-- Importul dump-ului de pe vechiul server SOURCE /tmp/full_dump.sql; -- Crearea utilizatorului pentru transferul de date între noduri CREATE USER \u0026#39;sst_user\u0026#39;@\u0026#39;localhost\u0026#39; IDENTIFIED BY \u0026#39;parola_sigura_aici\u0026#39;; GRANT RELOAD, PROCESS, LOCK TABLES, REPLICATION CLIENT ON *.* TO \u0026#39;sst_user\u0026#39;@\u0026#39;localhost\u0026#39;; FLUSH PRIVILEGES; Verificare imediată:\nSHOW STATUS LIKE \u0026#39;wsrep_cluster_size\u0026#39;; -- +--------------------+-------+ -- | Variable_name | Value | -- +--------------------+-------+ -- | wsrep_cluster_size | 1 | -- +--------------------+-------+ Dacă valoarea este 1, bootstrap-ul a funcționat. Acum, pe celelalte două noduri:\nsudo systemctl start mariadb Aceste noduri citesc wsrep_cluster_address, găsesc Nodul 1, primesc un SST complet cu toate datele și se alătură clusterului.\nDupă pornirea tuturor celor trei:\nSHOW STATUS LIKE \u0026#39;wsrep_cluster_size\u0026#39;; -- +--------------------+-------+ -- | Variable_name | Value | -- +--------------------+-------+ -- | wsrep_cluster_size | 3 | -- +--------------------+-------+ Trei. Acesta este numărul magic. Momentul în care clientul a încetat să mai aibă un single point of failure.\nVerificarea stării de sănătate a clusterului #Aceasta este partea care contează cu adevărat pentru cine gestionează clusterul zi de zi. Nu este suficient să știi că wsrep_cluster_size este 3. Trebuie să știi să citești starea completă.\nQuery-ul de diagnostic pe care îl folosesc mereu #SHOW STATUS WHERE Variable_name IN ( \u0026#39;wsrep_cluster_size\u0026#39;, \u0026#39;wsrep_cluster_status\u0026#39;, \u0026#39;wsrep_connected\u0026#39;, \u0026#39;wsrep_ready\u0026#39;, \u0026#39;wsrep_local_state_comment\u0026#39;, \u0026#39;wsrep_incoming_addresses\u0026#39;, \u0026#39;wsrep_evs_state\u0026#39;, \u0026#39;wsrep_flow_control_paused\u0026#39;, \u0026#39;wsrep_local_recv_queue_avg\u0026#39;, \u0026#39;wsrep_local_send_queue_avg\u0026#39;, \u0026#39;wsrep_cert_deps_distance\u0026#39; ); Cum să interpretezi rezultatele # Variabilă Valoare sănătoasă Semnificație wsrep_cluster_size 3 Toate nodurile sunt în cluster wsrep_cluster_status Primary Clusterul este operațional și are quorum wsrep_connected ON Acest nod este conectat la cluster wsrep_ready ON Acest nod acceptă interogări wsrep_local_state_comment Synced Acest nod este sincronizat wsrep_flow_control_paused 0.0 Fără pauze de flow control wsrep_local_recv_queue_avg \u0026lt; 0.5 Coada de recepție este sub control wsrep_local_send_queue_avg \u0026lt; 0.5 Coada de trimitere este sub control Semnalele de pericol #wsrep_cluster_status = Non-Primary: nodul a pierdut quorum-ul. Este izolat. Nu va accepta scrieri (și nu trebuie). Acest lucru se întâmplă când un nod pierde conexiunea cu majoritatea clusterului.\nwsrep_flow_control_paused \u0026gt; 0.0: flow control activat. Înseamnă că un nod este prea lent în aplicarea tranzacțiilor și le cere celorlalte să încetinească. O valoare apropiată de 1.0 înseamnă că clusterul este în esență oprit, așteptând nodul cel mai lent.\nwsrep_local_recv_queue_avg \u0026gt; 1.0: tranzacțiile care sosesc se acumulează. Ar putea fi o problemă de I/O disc, CPU, sau un nod subdimensionat.\nScript de monitorizare #Am livrat clientului și un script pentru sistemul lor de monitorizare (Zabbix, în cazul lor):\n#!/bin/bash # galera_health_check.sh — de executat pe fiecare nod MYSQL=\u0026#34;mysql -u monitor -p\u0026#39;monitor_pwd\u0026#39; -Bse\u0026#34; CLUSTER_SIZE=$($MYSQL \u0026#34;SHOW STATUS LIKE \u0026#39;wsrep_cluster_size\u0026#39;\u0026#34; | awk \u0026#39;{print $2}\u0026#39;) CLUSTER_STATUS=$($MYSQL \u0026#34;SHOW STATUS LIKE \u0026#39;wsrep_cluster_status\u0026#39;\u0026#34; | awk \u0026#39;{print $2}\u0026#39;) NODE_STATE=$($MYSQL \u0026#34;SHOW STATUS LIKE \u0026#39;wsrep_local_state_comment\u0026#39;\u0026#34; | awk \u0026#39;{print $2}\u0026#39;) FLOW_CONTROL=$($MYSQL \u0026#34;SHOW STATUS LIKE \u0026#39;wsrep_flow_control_paused\u0026#39;\u0026#34; | awk \u0026#39;{print $2}\u0026#39;) if [ \u0026#34;$CLUSTER_SIZE\u0026#34; -lt 3 ] || [ \u0026#34;$CLUSTER_STATUS\u0026#34; != \u0026#34;Primary\u0026#34; ] || [ \u0026#34;$NODE_STATE\u0026#34; != \u0026#34;Synced\u0026#34; ]; then echo \u0026#34;CRITICAL: Galera cluster degradat\u0026#34; echo \u0026#34; Size: $CLUSTER_SIZE | Status: $CLUSTER_STATUS | State: $NODE_STATE | FC: $FLOW_CONTROL\u0026#34; exit 2 fi echo \u0026#34;OK: Galera cluster sănătos (3 noduri, Primary, Synced)\u0026#34; exit 0 Problema split-brain : de ce trei noduri și nu două #Când am prezentat soluția clientului, prima întrebare a fost: \u0026ldquo;Chiar avem nevoie de trei servere? Nu sunt suficiente două?\u0026rdquo;\nNu. Și nu e o chestiune de cost — e o chestiune de matematică.\nGalera folosește un algoritm de consens bazat pe **quorum** . Cu trei noduri, quorum-ul este 2: dacă un nod cade, celelalte două recunosc că sunt majoritatea și continuă să funcționeze. Cu două noduri, quorum-ul este 2: dacă un nod cade, cel rămas nu are quorum și se blochează pentru a preveni split-brain-ul.\nParametrul pc.ignore_quorum există pentru a forța un nod să funcționeze fără quorum, dar e ca și cum ai dezactiva alarma de incendiu pentru că sună prea des.\nTrei noduri este minimul pentru un cluster Galera în producție. Al treilea nod nu este un lux — este ceea ce permite clusterului să continue să funcționeze când lucrurile merg prost.\nCând un nod cade și revine #Unul dintre primele lucruri pe care le-am făcut după punerea în producție a fost să simulez o defecțiune — cu clientul urmărind.\nAm oprit Nodul 3. Aplicația a continuat să funcționeze fără întrerupere pe nodurile 1 și 2. Fără erori, fără timeout-uri. Două sute de utilizatori care nu au observat nimic.\nApoi am repornit Nodul 3. Ce s-a întâmplat:\nNodul a pornit și a contactat celelalte prin wsrep_cluster_address Gap-ul de tranzacții era mic, deci a primit un **IST** (Incremental State Transfer) — doar tranzacțiile lipsă În mai puțin de un minut era din nou în starea Synced Dacă nodul ar fi rămas oprit mai mult timp și gcache-ul ar fi fost depășit, ar fi primit un SST complet — întregul set de date. De aceea parametrul gcache.size este important:\nwsrep_provider_options=\u0026#34;gcache.size=512M\u0026#34; Un gcache mai mare înseamnă că clusterul poate tolera perioade mai lungi de inactivitate ale unui nod fără a necesita un SST complet. În cazul clientului, cu aproximativ 80-100 MB de tranzacții pe zi, un gcache de 512 MB acoperea aproape o săptămână de absență.\nClientul a privit Nodul 3 revenind în sync și a spus: \u0026ldquo;Deci data viitoare când trebuie să facem mentenanță pe un server, nu mai trebuie să oprim totul?\u0026rdquo; Exact. Acesta era scopul.\nChecklist de punere în producție #Înainte de a declara clusterul gata pentru client, am verificat fiecare punct:\nAceeași versiune MariaDB pe toate nodurile wsrep_cluster_size = 3 wsrep_cluster_status = Primary pe toate nodurile wsrep_local_state_comment = Synced pe toate nodurile Test de scriere pe Nodul 1, verificare de citire pe Nodul 2 și 3 Test de oprire a unui nod: clusterul continuă să funcționeze Test de rejoin: nodul revine la Synced fără SST complet Utilizator SST configurat și funcțional Firewall verificat pe toate porturile (3306, 4567, 4568, 4444) Monitorizare activă pe wsrep_cluster_status și wsrep_flow_control_paused Backup configurat (pe UN singur nod, nu pe toate trei) Aplicația reconfigurată să indice către load balancer sau VIP Șase luni mai târziu #Am aflat de la client la șase luni după punerea în producție. Între timp avuseseră două restartări programate pentru actualizări de sistem și o defecțiune neprevăzută a unui disc pe unul dintre noduri. În toate cele trei cazuri, aplicația nu a încetat niciodată să funcționeze. Zero downtime neplanificat.\nCe m-a impresionat cel mai mult a fost fraza lui: \u0026ldquo;Înainte trăiam cu anxietatea că baza de date va cădea. Acum nu ne mai gândim la asta.\u0026rdquo;\nAceasta este adevărata valoare a unui cluster Galera bine configurat. Nu este tehnologia în sine — este liniștea pe care o aduce. Certitudinea că o singură defecțiune nu mai oprește compania.\nPartea tehnică este cea mai simplă. Ceea ce face diferența este înțelegerea de ce fiecare parametru este setat într-un anumit fel, ce se întâmplă când lucrurile merg prost și cum să diagnostichezi problemele înainte ca ele să devină urgențe. Un cluster care funcționează în demo și unul care rezistă în producție: distanța dintre cele două stă toată în detaliile pe care le-am povestit aici.\nGlosar #Quorum — Mecanism de consens bazat pe majoritatea nodurilor. Cu 3 noduri quorum-ul este 2: dacă unul cade, celelalte două continuă să funcționeze. Este ceea ce previne split-brain-ul.\nSST — State Snapshot Transfer: mecanism prin care un nod care se alătură clusterului primește o copie completă a întregului set de date de la un nod donator. Metoda recomandată este mariabackup.\nIST — Incremental State Transfer: transferul doar al tranzacțiilor lipsă către un nod care revine în cluster după o absență scurtă. Mult mai rapid decât un SST complet.\nWSREP — Write Set Replication: API și protocol de replicare sincronă folosit de Galera Cluster. Fiecare tranzacție este replicată pe toate nodurile înainte de commit printr-un proces de certification.\nSplit-brain — Condiție critică în care două părți ale clusterului operează independent acceptând scrieri divergente. Quorum-ul o previne: doar partiția cu majoritatea nodurilor poate continua să funcționeze.\n","date":"17 februarie 2026","permalink":"https://ivanluminaria.com/ro/posts/mysql/galera-cluster-3-nodi/","section":"Database Strategy","summary":"\u003cp\u003eTichetul era laconic, cum se întâmplă adesea când problema e gravă: \u0026ldquo;Baza de date a căzut din nou. Aplicația e oprită. A treia oară în două luni.\u0026rdquo;\u003c/p\u003e\n\u003cp\u003eClientul avea un MariaDB pe un singur server Linux — o aplicație de gestiune de afaceri folosită de aproximativ două sute de utilizatori interni, cu vârfuri de încărcare în timpul închiderilor contabile de sfârșit de lună. De fiecare dată când serverul avea o problemă — un disc care se încetinea, o actualizare de sistem care necesita restart, un proces care consuma toată memoria RAM — baza de date cădea și cu ea întreaga operativitate a companiei.\u003c/p\u003e","title":"Galera Cluster cu 3 noduri: cum am rezolvat o problemă de disponibilitate pe MySQL"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/high-availability/","section":"Tags","summary":"","title":"High-Availability"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/wsrep/","section":"Tags","summary":"","title":"Wsrep"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/ash/","section":"Tags","summary":"","title":"Ash"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/awr/","section":"Tags","summary":"","title":"Awr"},{"content":"Vineri, ora 18:40. Aveam deja geaca pe mine, gata de plecare. Telefonul vibrează. E project managerul.\n\u0026ldquo;Ivan, avem o problemă. Sistemul merge foarte lent. Mâine dimineață e go-live-ul.\u0026rdquo;\nNu e prima dată când primesc un astfel de apel. Dar tonul era diferit. Nu era plângerea obișnuită despre lentoare. Era panică.\nMă reconectez prin VPN, deschid o sesiune pe baza de date Oracle 19c a clientului. Primul lucru pe care îl fac e o verificare rapidă:\nSELECT metric_name, value FROM v$sysmetric WHERE metric_name IN (\u0026#39;Database CPU Time Ratio\u0026#39;, \u0026#39;Database Wait Time Ratio\u0026#39;, \u0026#39;Average Active Sessions\u0026#39;); CPU Time Ratio: 12%. În condiții normale era peste 80%.\nAverage Active Sessions: 47. Pe un server cu 16 core-uri.\nPatruzeci și șapte de sesiuni active. Baza de date se îneca.\n🔥 Simptomele #Echipa de dezvoltare terminase ultimul deploy al codului aplicativ în acea după-amiază. Totul părea să funcționeze pe mediul de test. Dar când au lansat batch-ul de verificare pre-go-live — cel care simulează sarcina de producție — timpii de răspuns au explodat.\nQuery-urile care în mod normal rulau în 2-3 secunde durau 45. Batch-urile care terminau în 20 de minute erau încă în execuție după o oră. Wait event -urile dominante erau db file sequential read și db file scattered read — semn clar de I/O fizic masiv.\nCeva citea cantități enorme de date de pe disc. Ceva care înainte nu era acolo.\n📊 AWR: fotografia problemei #AWR — Automatic Workload Repository — este cel mai puternic instrument de diagnostic pe care Oracle îl pune la dispoziție. În fiecare oră, Oracle face o captură (snapshot ) a statisticilor de performanță și o stochează în repository-ul intern. Comparând două snapshot-uri, obții un raport care îți spune exact ce s-a întâmplat în acea perioadă.\nAm generat un snapshot manual pentru a captura situația curentă:\nEXEC DBMS_WORKLOAD_REPOSITORY.create_snapshot; Apoi am căutat snapshot-urile disponibile:\nSELECT snap_id, begin_interval_time, end_interval_time FROM dba_hist_snapshot WHERE begin_interval_time \u0026gt; SYSDATE - 1/6 ORDER BY snap_id DESC; Aveam un snapshot de la 18:00 (înainte de problema vizibilă) și cel tocmai creat la 18:45. Am generat raportul AWR:\nSELECT output FROM TABLE(DBMS_WORKLOAD_REPOSITORY.awr_report_text( l_dbid =\u0026gt; (SELECT dbid FROM v$database), l_inst_num =\u0026gt; 1, l_bid =\u0026gt; 4523, l_eid =\u0026gt; 4524 )); Ce spunea raportul #Secțiunea Top 5 Timed Foreground Events era grăitoare:\nEvent Waits Time (s) % DB time db file scattered read 1.247.832 3.847 58,2% db file sequential read 423.109 1.205 18,2% CPU + Wait for CPU — 892 13,5% log file sync 12.445 287 4,3% direct path read 8.221 198 3,0% db file scattered read la 58%. Sunt full table scan -uri. Ceva citea tabele întregi, bloc cu bloc, fără a folosi indecși.\nSecțiunea SQL ordered by Elapsed Time arăta un singur SQL_ID care consuma 71% din timpul total al bazei de date: g4f2h8k1nw3z9.\nAcum știam ce să caut.\n🔍 ASH: microscopul #AWR îmi dăduse fotografia de ansamblu. Dar trebuia să înțeleg când a început acel SQL, cine îl executa și ce program l-a lansat.\nASH — Active Session History — înregistrează starea fiecărei sesiuni active o dată pe secundă. Este microscopul DBA-ului: unde AWR îți arată medii pe o oră, ASH îți arată ce se întâmpla secundă cu secundă.\nSELECT sample_time, session_id, sql_id, sql_plan_hash_value, event, program, module FROM v$active_session_history WHERE sql_id = \u0026#39;g4f2h8k1nw3z9\u0026#39; AND sample_time \u0026gt; SYSDATE - 1/24 ORDER BY sample_time DESC; Rezultatele erau clare:\nProgram: JDBC Thin Client — aplicația Java a batch-ului Module: BatchVerificaProduzione Event: db file scattered read în 92% din eșantioane Prima apariție: 17:12 — exact după deploy-ul din după-amiază SQL_PLAN_HASH_VALUE: 2891047563 Planul de execuție se schimbase. Înainte de deploy, acea query folosea un plan diferit.\n🧩 Planul de execuție #Am recuperat planul curent:\nSELECT * FROM TABLE(DBMS_XPLAN.display_awr( sql_id =\u0026gt; \u0026#39;g4f2h8k1nw3z9\u0026#39;, plan_hash_value =\u0026gt; 2891047563 )); Rezultatul mi-a făcut problema evidentă imediat:\n--------------------------------------------------------------------------- | Id | Operation | Name | Rows | Cost | --------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | | 48721 | | 1 | HASH JOIN | | 2.1M | 48721 | | 2 | TABLE ACCESS FULL | MOVIMENTI_TEMP | 2.1M | 41893 | | 3 | INDEX RANGE SCAN | IDX_CLIENTI_PK | 1 | 2 | --------------------------------------------------------------------------- TABLE ACCESS FULL pe MOVIMENTI_TEMP. O tabelă temporară cu 2,1 milioane de rânduri, citită integral de fiecare dată. Fără index. Fără filtru eficient.\nAm verificat ce exista înainte de deploy consultând planul anterior în AWR:\nSELECT plan_hash_value, timestamp FROM dba_hist_sql_plan WHERE sql_id = \u0026#39;g4f2h8k1nw3z9\u0026#39; ORDER BY timestamp; Planul anterior (hash 1384726091) folosea un INDEX RANGE SCAN pe un index care — descoperire — fusese eliminat în timpul deploy-ului. Scriptul de migrare includea un DROP TABLE MOVIMENTI_TEMP urmat de o recreare, dar fără a recrea indexul.\n⚡ Soluția #Zece minute. Din momentul conectării până la identificarea cauzei. Nu din pricepere — din cauza instrumentelor.\nFix-ul era simplu:\nCREATE INDEX idx_movimenti_temp_cliente ON movimenti_temp (id_cliente, data_movimento) TABLESPACE idx_data; După crearea indexului, am forțat un re-parse al query-ului:\nEXEC DBMS_SHARED_POOL.purge(\u0026#39;g4f2h8k1nw3z9\u0026#39;, \u0026#39;C\u0026#39;); Am cerut echipei să relanseze batch-ul. Timp de execuție: 18 minute. Identic cu testele anterioare.\nGo-live-ul de sâmbătă dimineață a decurs normal.\n📋 AWR vs ASH: când să folosești ce #După acel episod am formalizat o regulă pe care o urmez întotdeauna:\nCaracteristică AWR ASH Granularitate Snapshot-uri orare (configurabile) Eșantion în fiecare secundă Adâncime istorică Până la 30 zile (implicit 8) 1 oră în memorie, apoi în AWR Caz de utilizare principal Analiză de tendințe, comparare perioade Diagnostic punctual, izolare SQL View principal DBA_HIST_* V$ACTIVE_SESSION_HISTORY View istoric — DBA_HIST_ACTIVE_SESS_HISTORY Licență necesară Diagnostic Pack Diagnostic Pack Output tipic Raport HTML/text Query-uri ad hoc Regula empirică: AWR ca să înțelegi ce s-a schimbat, ASH ca să înțelegi de ce.\nAWR îți spune: \u0026ldquo;Între 17:00 și 18:00, 58% din timpul bazei de date a fost petrecut pe full table scan-uri.\u0026rdquo; ASH îți spune: \u0026ldquo;La 17:12:34, sesiunea 847 executa query-ul g4f2h8k1nw3z9 cu un full table scan pe MOVIMENTI_TEMP, lansat de programul BatchVerificaProduzione.\u0026rdquo;\nSunt complementare. Să folosești doar unul e ca și cum ai diagnostica o problemă uitându-te doar la CT sau doar la analizele de sânge.\n🛡️ Query-urile pe care orice DBA ar trebui să le aibă pregătite #De-a lungul anilor am construit un set de query-uri de diagnostic pe care le am mereu la îndemână. Le împărtășesc pentru că într-o urgență nu ai timp să le scrii de la zero.\nTop SQL după timp de execuție (ultima oră) #SELECT sql_id, COUNT(*) AS samples, ROUND(COUNT(*) / 60, 1) AS est_minutes, MAX(event) AS top_event, MAX(program) AS program FROM v$active_session_history WHERE sample_time \u0026gt; SYSDATE - 1/24 AND sql_id IS NOT NULL GROUP BY sql_id ORDER BY samples DESC FETCH FIRST 10 ROWS ONLY; Distribuția wait event-urilor pentru un SQL specific #SELECT event, COUNT(*) AS samples, ROUND(COUNT(*) * 100 / SUM(COUNT(*)) OVER(), 1) AS pct FROM v$active_session_history WHERE sql_id = \u0026#39;\u0026amp;sql_id\u0026#39; AND sample_time \u0026gt; SYSDATE - 1/24 GROUP BY event ORDER BY samples DESC; Compararea planurilor de execuție în timp #SELECT plan_hash_value, MIN(timestamp) AS first_seen, MAX(timestamp) AS last_seen, COUNT(*) AS executions_in_awr FROM dba_hist_sqlstat WHERE sql_id = \u0026#39;\u0026amp;sql_id\u0026#39; GROUP BY plan_hash_value ORDER BY first_seen; 🎯 Ce am învățat în acea seară #Trei lecții pe care le port cu mine.\nPrima: deploy-ul nu este doar cod. Este și structură. Când lansezi în producție, trebuie să verifici că indecșii, constraint-urile, statisticile și grant-urile sunt coerente cu ce era acolo înainte. Un script care face DROP TABLE și CREATE TABLE fără a recrea indecșii e o bombă cu ceas.\nA doua: AWR și ASH nu sunt instrumente pentru DBA seniori. Sunt instrumente de primă linie, ca un defibrilator. Trebuie să știi să le folosești înainte de a avea nevoie de ele, nu în timpul urgenței.\nA treia: zece minute de diagnostic corect valorează mai mult decât trei ore de încercări oarbe. Când sistemul e în genunchi, tentația e să repornești, să omori sesiuni, să adaugi resurse. Dar fără să știi ce se întâmplă, tragi în întuneric.\nÎn acea seară am plecat de la birou la 19:20. La patruzeci de minute de la apelul telefonic. A doua zi go-live-ul a pornit fără probleme, iar luni sistemul mergea normal.\nNu sunt un erou. Am folosit doar instrumentele potrivite.\nGlosar #AWR — Automatic Workload Repository. Componenta integrata in Oracle care colecteaza statistici de performanta prin snapshot-uri periodice si genereaza rapoarte de diagnostic comparative.\nASH — Active Session History. Componenta Oracle care esantioneaza starea fiecarei sesiuni active o data pe secunda, stocand-o in memorie si apoi in AWR. Este microscopul DBA-ului pentru diagnosticarea punctuala.\nFull Table Scan — Operatie de citire in care Oracle citeste toate blocurile unei tabele fara a folosi indecsi. In wait event-uri apare ca db file scattered read.\nWait Event — Eveniment de asteptare inregistrat de Oracle de fiecare data cand o sesiune nu poate continua pentru ca asteapta o resursa (I/O, lock, CPU, retea). Analiza wait event-urilor este baza metodologiei de diagnostic Oracle.\nSnapshot — Captura punctuala a statisticilor de performanta preluata periodic de AWR (implicit la fiecare 60 de minute). Compararea a doua snapshot-uri genereaza raportul AWR.\n","date":"10 februarie 2026","permalink":"https://ivanluminaria.com/ro/posts/oracle/oracle-awr-ash/","section":"Database Strategy","summary":"\u003cp\u003eVineri, ora 18:40. Aveam deja geaca pe mine, gata de plecare. Telefonul vibrează. E project managerul.\u003c/p\u003e\n\u003cp\u003e\u0026ldquo;Ivan, avem o problemă. Sistemul merge foarte lent. Mâine dimineață e go-live-ul.\u0026rdquo;\u003c/p\u003e\n\u003cp\u003eNu e prima dată când primesc un astfel de apel. Dar tonul era diferit. Nu era plângerea obișnuită despre lentoare. Era panică.\u003c/p\u003e\n\u003cp\u003eMă reconectez prin VPN, deschid o sesiune pe baza de date Oracle 19c a clientului. Primul lucru pe care îl fac e o verificare rapidă:\u003c/p\u003e","title":"AWR, ASH și cele 10 minute care au salvat un go-live"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/diagnostic/","section":"Tags","summary":"","title":"Diagnostic"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/go-live/","section":"Tags","summary":"","title":"Go-Live"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/grant/","section":"Tags","summary":"","title":"Grant"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/privileges/","section":"Tags","summary":"","title":"Privileges"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/revoke/","section":"Tags","summary":"","title":"Revoke"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/roles/","section":"Tags","summary":"","title":"Roles"},{"content":"Prima dată când am lucrat serios cu PostgreSQL veneam după ani de experiență cu alte baze de date. Căutam comanda CREATE USER. O găseam. Apoi vedeam CREATE ROLE. Apoi ALTER USER. Apoi ALTER ROLE.\nPentru câteva minute am gândit: „Bine, aici cineva se distrează încurcând lumea.”\nÎn realitate, nu. PostgreSQL este mult mai coerent decât pare. Doar că este coerent în felul lui.\nÎn PostgreSQL nu există utilizatori. Există roluri. #Cheia este aceasta: în PostgreSQL totul este un ROLE.\nUn ROLE poate:\navea drept de login\\ să nu aibă drept de login\\ deține obiecte\\ moșteni privilegii de la alte roluri\\ fi utilizat ca un container de privilegii Ceea ce în alte sisteme numești „utilizator” în PostgreSQL este pur și simplu un rol cu atributul LOGIN.\nDe fapt:\nCREATE USER mario; nu este decât un shortcut pentru:\nCREATE ROLE mario WITH LOGIN; La fel și ALTER USER: este doar un alias pentru ALTER ROLE.\nDe ce există, în realitate, doar CREATE ROLE și ALTER ROLE?\nPentru că PostgreSQL nu face distincție conceptuală între utilizator și rol. Este același obiect cu atribute diferite. Minimalist. Elegant. Coerent.\nDacă un rol are LOGIN, se comportă ca un utilizator.\nDacă nu are LOGIN, este un container de privilegii.\nCând înțelegi cu adevărat acest lucru, modul în care proiectezi securitatea se schimbă.\nModelul mental corect #Astăzi gândesc astfel:\nCreez roluri „funcționale” care reprezintă seturi de privilegii\\ Atribui aceste roluri utilizatorilor reali\\ Evit să acord permisiuni direct utilizatorilor De ce? Pentru că utilizatorii se schimbă. Rolurile nu.\nDacă mâine se alătură un coleg nou, nu rescriu jumătate din grants.\nÎi atribui rolul potrivit și atât.\nArhitectură curată. Fără magie. Fără haos.\nO poveste reală (fără nume incomode) #Cu ceva timp în urmă mi s-a cerut să creez un utilizator read-only pentru un sistem de monitorizare.\nCerere aparent simplă: „Trebuie să citească anumite tabele. Fără scriere.”\nClasicul „e doar read-only”.\nCapcana este mereu aceeași: dacă rulezi doar un GRANT SELECT pe tabelele existente, funcționează azi.\nPeste trei luni cineva creează un tabel nou și sistemul de monitorizare începe să dea erori.\nȘi ghici pe cine sună.\nSoluția corectă necesită atenție la patru niveluri:\nPermisiunea de conectare la bază de date\\ Permisiunea de utilizare a schemei (USAGE)\\ Permisiuni SELECT pe tabelele și secvențele existente\\ Default privileges pentru obiectele viitoare Dacă omiți o piesă, mai devreme sau mai târziu plătești prețul.\nExemplu: crearea corectă a unui utilizator read-only #Să presupunem că dorim să creăm un utilizator read-only pe două scheme.\nMai întâi creez rolul cu login:\nCREATE ROLE srv_monitorizare WITH LOGIN PASSWORD \u0026#39;ParolaSigura123#\u0026#39;; Îl securizez:\nALTER ROLE srv_monitorizare NOSUPERUSER NOCREATEDB NOCREATEROLE NOINHERIT; Permit conexiunea la baza de date:\nGRANT CONNECT ON DATABASE mydb TO srv_monitorizare; Permisiune de utilizare a schemelor:\nGRANT USAGE ON SCHEMA schema1 TO srv_monitorizare; GRANT USAGE ON SCHEMA schema2 TO srv_monitorizare; Permisiuni de citire pe obiectele existente:\nGRANT SELECT ON ALL TABLES IN SCHEMA schema1 TO srv_monitorizare; GRANT SELECT ON ALL TABLES IN SCHEMA schema2 TO srv_monitorizare; GRANT SELECT ON ALL SEQUENCES IN SCHEMA schema1 TO srv_monitorizare; GRANT SELECT ON ALL SEQUENCES IN SCHEMA schema2 TO srv_monitorizare; Și acum partea pe care mulți o uită:\nALTER DEFAULT PRIVILEGES IN SCHEMA schema1 GRANT SELECT ON TABLES TO srv_monitorizare; ALTER DEFAULT PRIVILEGES IN SCHEMA schema2 GRANT SELECT ON TABLES TO srv_monitorizare; Astfel, și tabelele viitoare vor fi accesibile pentru citire.\nNotă importantă: ALTER DEFAULT PRIVILEGES se aplică rolului care creează obiectele. Dacă mai mulți owners creează tabele în aceleași scheme, configurația trebuie replicată pentru fiecare dintre ei.\nDe ce acest model este puternic #Faptul că totul este un ROLE îți permite să construiești ierarhii curate.\nExemplu avansat:\nCREATE ROLE role_readonly; GRANT SELECT ON ALL TABLES IN SCHEMA schema1 TO role_readonly; CREATE ROLE srv_monitorizare WITH LOGIN PASSWORD \u0026#39;...\u0026#39;; GRANT role_readonly TO srv_monitorizare; Acum pot atribui role_readonly la zece utilizatori diferiți fără a duplica grants.\nAsta înseamnă design. Nu doar sintaxă.\nConcluzie #PostgreSQL nu complică noțiunea de utilizator. O simplifică.\nExistă un singur tip de obiect: ROLE. Depinde de noi să-l folosim corect.\nDacă îl tratezi ca pe un simplu „utilizator cu parolă”, funcționează.\nDacă îl folosești ca pe un bloc arhitectural, devine un instrument puternic pentru a proiecta o securitate curată, scalabilă și mentenabilă.\nDiferența nu este în comenzi.\nEste în modelul mental pe care îl folosești când le aplici.\nGlosar #ROLE — Entitatea fundamentală a PostgreSQL care unifică conceptul de utilizator și grup de permisiuni: un ROLE cu LOGIN este un utilizator, fără LOGIN este un container de privilegii.\nDEFAULT PRIVILEGES — Mecanism PostgreSQL care definește automat privilegiile de atribuit tuturor obiectelor viitoare create într-o schemă, evitând repetarea manuală a GRANT-urilor.\nSchema — Namespace logic în cadrul unei baze de date care grupează tabele, vizualizări, funcții și alte obiecte, permițând organizarea și separarea permisiunilor.\nGRANT — Comandă SQL pentru atribuirea privilegiilor specifice unui utilizator sau rol pe baze de date, tabele sau coloane.\nLeast Privilege — Principiu de securitate care prevede atribuirea fiecărui utilizator doar a permisiunilor strict necesare pentru îndeplinirea funcției sale.\n","date":"10 februarie 2026","permalink":"https://ivanluminaria.com/ro/posts/postgresql/postgresql_roles_and_users/","section":"Database Strategy","summary":"\u003cp\u003ePrima dată când am lucrat serios cu PostgreSQL veneam după\nani de experiență cu alte baze de date. Căutam comanda \u003ccode\u003eCREATE USER\u003c/code\u003e. O găseam.\nApoi vedeam \u003ccode\u003eCREATE ROLE\u003c/code\u003e. Apoi \u003ccode\u003eALTER USER\u003c/code\u003e. Apoi \u003ccode\u003eALTER ROLE\u003c/code\u003e.\u003cbr\u003e\nPentru câteva minute am gândit: „Bine, aici cineva se distrează\nîncurcând lumea.”\u003c/p\u003e\n\u003cp\u003eÎn realitate, nu. PostgreSQL este mult mai coerent decât pare.\nDoar că este coerent în felul lui.\u003c/p\u003e\n\u003ch2 id=\"în-postgresql-nu-există-utilizatori-există-roluri\" class=\"relative group\"\u003eÎn PostgreSQL nu există utilizatori. Există roluri. \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#%c3%aen-postgresql-nu-exist%c4%83-utilizatori-exist%c4%83-roluri\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eCheia este aceasta: \u003cstrong\u003eîn PostgreSQL totul este un ROLE\u003c/strong\u003e.\u003c/p\u003e","title":"Roluri și utilizatori în PostgreSQL: de ce totul este (doar) un ROLE"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/security/","section":"Tags","summary":"","title":"Security"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/bug-fixing/","section":"Tags","summary":"","title":"Bug-Fixing"},{"content":"Mă sună un client. Voce tensionată, cuvinte măsurate.\n\u0026ldquo;Ivan, avem o problemă. De fapt, avem problema.\u0026rdquo;\nCunosc tonul ăsta. E tonul celui care a încercat deja să rezolve lucrurile intern, a eșuat, și acum caută pe cineva care să-i spună adevărul fără ocolișuri.\nProblema este un software de gestiune — nu un site web, nu o aplicație — un sistem critic pe care rulează procese de business importante. Are câțiva ani. A crescut repede, cum se întâmplă întotdeauna când business-ul aleargă mai repede decât arhitectura. Și acum s-a acumulat totul: bug-uri deschise pe care nimeni nu le închide, cereri de evoluție pe care nimeni nu le planifică, dezvoltatori care lucrează pe versiuni diferite ale codului fără să știe ce face celălalt.\nScenariul clasic care, în cuvinte, \u0026ldquo;funcționează\u0026rdquo;. Dar pe dinăuntru e un câmp minat.\n🧠 Prima întâlnire: a înțelege ce nu funcționează cu adevărat #Când intru într-un proiect ca acesta, nu mă uit mai întâi la cod.\nMă uit la oameni. Mă uit cum comunică. Mă uit unde se pierd informațiile.\nEchipa era formată din patru dezvoltatori buni. Serioși. Competenți.\nDar lucrau așa:\ncodul stătea într-un folder partajat în rețea modificările erau comunicate prin email sau într-un tabel Excel bug-urile erau raportate verbal, pe chat, prin tichete — fără un criteriu unic nimeni nu știa cu certitudine care era versiunea \u0026ldquo;bună\u0026rdquo; a software-ului Și știi ce se întâmplă în situațiile astea?\nFiecare are dreptate din punctul lui de vedere. Dar proiectul, în ansamblu, e scăpat de sub control.\nProblema nu e tehnică. E organizatorică.\nȘi aici se schimbă totul.\n📌 Propunerea: GitHub ca coloană vertebrală a proiectului #Primul lucru pe care l-am pus pe masă a fost clar, direct, fără fasoane:\nAdoptăm GitHub. Tot codul trece pe acolo. Fără excepții.\nNu e o chestie de modă. Nu e pentru că \u0026ldquo;fac toți așa\u0026rdquo;.\nE pentru că GitHub rezolvă, cu instrumente concrete, probleme pe care niciun tabel Excel nu le va putea gestiona vreodată:\nVersionare reală: fiecare modificare e urmărită, comentată, reversibilă Branch-uri și Pull Request-uri : fiecare dezvoltator lucrează pe copia lui, apoi propune modificările echipei — nu suprascrie munca celorlalți Issue tracker integrat: bug-urile și cererile de evoluție trăiesc în același loc cu codul Istoric complet: cine a făcut ce, când, de ce Am văzut fața dezvoltatorului senior. Un amestec de curiozitate și neîncredere.\n\u0026ldquo;Dar noi am făcut mereu așa.\u0026rdquo;\nI-am răspuns calm: \u0026ldquo;Știu. Și rezultatul e motivul pentru care sunt aici.\u0026rdquo;\nN-am spus-o ca să provoc. Am spus-o pentru că e adevărul.\nIar adevărul, când e spus în modul potrivit, nu jignește. Eliberează.\n🔬 Al doilea pas: AI ca accelerator, nu ca înlocuitor #Odată definit fluxul de lucru pe GitHub — branch-uri, review, merge controlate — am făcut a doua propunere.\n\u0026ldquo;Integrăm inteligența artificială în procesul de rezolvare a bug-urilor.\u0026rdquo;\nLiniște.\nÎnțeleg reacția. Când spui \u0026ldquo;AI\u0026rdquo; într-o cameră plină de dezvoltatori, jumătate se gândesc la ChatGPT care generează cod la întâmplare, cealaltă jumătate crede că le spui că locul lor de muncă nu mai e necesar.\nNiciuna dintre cele două.\nCe am propus e foarte diferit:\nCând un dezvoltator preia un bug, înainte de a scrie o linie de cod, folosește AI-ul pentru a analiza contextul AI-ul citește codul implicat, logurile, descrierea problemei Propune ipoteze. Nu soluții definitive — ipoteze argumentate Dezvoltatorul evaluează, verifică, și apoi implementează AI-ul nu înlocuiește programatorul.\nAI-ul îi economisește primele două ore de analiză — alea în care citești cod scris de altcineva, încercând să înțelegi ce naiba se întâmplă.\nIar cele două ore, înmulțite cu fiecare bug, cu fiecare dezvoltator, cu fiecare săptămână, devin un număr care schimbă calculele proiectului.\n📊 Numerele pe care le-am pus pe masă #N-am vândut vise. Am prezentat estimări conservative.\nEchipa gestiona în medie 15-20 de bug-uri pe săptămână.\nTimpul mediu de rezolvare era de aproximativ 6 ore per bug (între analiză, fix, testare, deploy).\nCu introducerea GitHub + AI în workflow, estimarea mea era:\nMetrică Înainte După (estimare) Timp mediu analiză bug ~2.5 ore ~15/20 minute Timp total rezolvare ~6 ore ~30 minute Bug-uri rezolvate pe săptămână 15-20 180-240 Conflicte de cod frecvente rare Vizibilitate stare proiect niciuna completă O reducere de peste 90% din timpul total de rezolvare.\nO creștere de 12 ori a capacității echipei de a închide tichete.\nFără să angajezi pe nimeni. Fără să schimbi oamenii. Schimbând metoda.\n🛠️ Cum funcționează în practică #Workflow-ul pe care l-am desenat e simplu. Intenționat simplu.\n1. Bug-ul ajunge ca Issue pe GitHub\nTitlu clar, descriere, etichetă de prioritate. Gata cu emailurile, gata cu chat-ul.\n2. Dezvoltatorul creează un branch dedicat\nfix/issue-234-eroare-calcul-tva — numele spune tot.\n3. Înainte de a atinge codul, consultă AI-ul\nÎi pasează codul implicat, eroarea, contextul. AI-ul returnează o analiză structurată: unde ar putea fi problema, ce fișiere sunt implicate, ce teste trebuie verificate.\n4. Dezvoltatorul implementează fix-ul\nCu un avantaj enorm: știe deja unde să se uite.\n5. Pull Request cu review Un coleg revizuiește codul. Nu de formă — pentru calitate.\n6. Merge în branch-ul principal\nDoar după aprobare. Codul \u0026ldquo;bun\u0026rdquo; rămâne bun.\n7. Issue-ul se închide automat\nTrasabilitate completă. De la problemă la soluție, totul documentat.\n📈 Ce s-a schimbat după trei săptămâni #Primele zile au fost cele mai grele. Mereu așa e.\nInstrumente noi, obiceiuri noi, tentația de a reveni la \u0026ldquo;cum se făcea înainte\u0026rdquo;.\nDar după trei săptămâni s-a întâmplat ceva.\nDezvoltatorul senior — cel care se uitase la mine cu neîncredere — mi-a scris:\n\u0026ldquo;Ivan, ieri am rezolvat un bug care anul trecut m-a blocat două zile. Cu AI-ul mi-a luat patruzeci de minute. Nu pentru că AI-ul a scris codul. Ci pentru că mi-a arătat imediat unde era problema.\u0026rdquo;\nUite. Ăsta e punctul.\nAI-ul nu scrie cod mai bun decât un dezvoltator experimentat.\nAI-ul accelerează drumul dintre problemă și înțelegerea problemei.\nIar înțelegerea e mereu pasul cel mai scump.\n🎯 Lecția pe care o duc acasă #De fiecare dată când intru într-un proiect în dificultate, găsesc același tipar:\nOameni competenți Instrumente inadecvate Procese absente sau informale Frustrare crescândă Soluția nu e niciodată \u0026ldquo;lucrați mai mult\u0026rdquo;.\nSoluția e lucrați diferit.\nGitHub nu e un instrument pentru dezvoltatori. E un instrument pentru echipe.\nAI-ul nu e o jucărie. E un multiplicator de competență.\nDar niciunul nu funcționează dacă nu e cineva care privește proiectul de sus, înțelege unde se pierd orele, și are curajul să spună: \u0026ldquo;Schimbăm.\u0026rdquo;\n💬 Pentru cei care se recunosc în această poveste #Dacă gestionezi un proiect software și te regăsești în ce am descris — codul împrăștiat, bug-urile care revin, echipa care muncește mult dar închide puțin — să știi că nu e vina oamenilor.\nE vina sistemului în care lucrează.\nIar sistemul poate fi schimbat.\nTrebuie schimbat.\nNu sunt necesare revoluții. Sunt necesare alegeri precise, implementate cu metodă.\nUn repository partajat. Un flux de lucru clar. Un asistent inteligent care accelerează analiza.\nTrei lucruri. Trei decizii.\nCare transformă haosul în control.\nGlosar #Pull Request — Cerere formală de incorporare a modificărilor dintr-un branch în branch-ul principal, cu code review obligatoriu. Mecanismul care garantează că codul \u0026ldquo;bun\u0026rdquo; rămâne bun.\nVersion Control — Sistem care urmărește fiecare modificare a codului, menținând istoricul complet. Git este standardul; GitHub adaugă colaborare peste Git.\nIssue Tracker — Sistem integrat de urmărire pentru bug-uri și cereri de funcționalități. Pe GitHub, issue-urile trăiesc în același loc cu codul, cu trasabilitate de la problemă la soluție.\nCode Review — Revizuirea codului de către un coleg înainte de merge. Surprinde bug-uri, îmbunătățește calitatea și răspândește cunoașterea codebase-ului în echipă.\nBranch — Linie de dezvoltare independentă care permite lucrul pe modificări izolate fără a afecta codul principal până la merge-ul aprobat.\n","date":"3 februarie 2026","permalink":"https://ivanluminaria.com/ro/posts/project-management/ai-github-project-management/","section":"Database Strategy","summary":"\u003cp\u003eMă sună un client. Voce tensionată, cuvinte măsurate.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003e\u0026ldquo;Ivan, avem o problemă. De fapt, avem \u003cstrong\u003eproblema\u003c/strong\u003e.\u0026rdquo;\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eCunosc tonul ăsta. E tonul celui care a încercat deja să rezolve lucrurile intern, a eșuat, și acum caută pe cineva care să-i spună adevărul fără ocolișuri.\u003c/p\u003e\n\u003cp\u003eProblema este un software de gestiune — nu un site web, nu o aplicație — un sistem critic pe care rulează procese de business importante. Are câțiva ani. A crescut repede, cum se întâmplă întotdeauna când business-ul aleargă mai repede decât arhitectura. Și acum s-a acumulat totul: bug-uri deschise pe care nimeni nu le închide, cereri de evoluție pe care nimeni nu le planifică, dezvoltatori care lucrează pe versiuni diferite ale codului fără să știe ce face celălalt.\u003c/p\u003e","title":"Când haosul devine metodă: AI și GitHub pentru gestionarea unui proiect pe care nimeni nu voia să-l atingă"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/github/","section":"Tags","summary":"","title":"Github"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/software-evolution/","section":"Tags","summary":"","title":"Software-Evolution"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/workflow/","section":"Tags","summary":"","title":"Workflow"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/agile/","section":"Tags","summary":"","title":"Agile"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/audit/","section":"Tags","summary":"","title":"Audit"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/meeting/","section":"Tags","summary":"","title":"Meeting"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/scrum/","section":"Tags","summary":"","title":"Scrum"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/standup/","section":"Tags","summary":"","title":"Standup"},{"content":"Prima zi de luni a proiectului. Echipă nouă, metodologie nouă, speranțe noi. PM-ul propune standup-ul zilnic. Toți dau din cap. \u0026ldquo;Cincisprezece minute, în picioare, trei întrebări. Simplu.\u0026rdquo;\nPrima săptămână funcționează. La 9:15 începe, la 9:28 ești deja la birou. Fiecare spune ce are de spus în două minute, se semnalează blocajele, se salută. Eficiență pură.\nA doua săptămână cineva ridică mâna în mijlocul rundei: \u0026ldquo;Pot să explic un moment problema pe care o am cu integrarea?\u0026rdquo; Cinci minute de discuție tehnică între două persoane. Ceilalți șase stau și ascultă ceva ce nu-i privește.\nA treia săptămână standup-ul durează treizeci și cinci de minute. Cineva aduce laptopul. Altcineva se așază. Runda celor trei întrebări a devenit o ședință de status cu discuții libere, demo-uri improvizate și dezbateri arhitecturale.\nÎn a patra săptămână echipa începe să sară peste standup. \u0026ldquo;Oricum durează jumătate de oră, n-am timp.\u0026rdquo;\nAm văzut această secvență de cel puțin zece ori în cariera mea. Nu e ghinion. E un pattern.\n⏱️ De ce constrângerea de 15 minute nu e negociabilă #Standup-ul are un singur scop: să sincronizeze echipa. Nu e o ședință de analiză. Nu e un moment de rezolvare de probleme. Nu e o sesiune de design. E un punct rapid de aliniere.\nIar constrângerea de timp este ceea ce îl face să fie așa.\nCând standup-ul durează 15 minute, se întâmplă lucruri specifice:\nOamenii se pregătesc înainte de ședință, pentru că știu că au două minute Problemele sunt semnalate, nu rezolvate. Rezolvarea are loc după, între persoanele implicate Echipa menține percepția că standup-ul este util și respectuos cu timpul lor Nimeni nu vine gândindu-se \u0026ldquo;iată, încă o jumătate de oră pierdută\u0026rdquo; Când standup-ul depășește 20 de minute, mecanismul se strică:\nDurată Efect asupra echipei 10-15 min Focus ridicat, participare activă, percepție pozitivă 15-20 min Acceptabil, dar unii încep să se distragă 20-30 min Persoanele neinvolucrate în thread-urile lungi se deconectează mental 30-45 min Echipa percepe standup-ul ca pierdere de timp. Încep absențele 45+ min Standup-ul e mort. A devenit o ședință de status deghizată în practică agilă Cel mai periculos lucru nu este depășirea în sine. E că se întâmplă gradual. Trei minute în plus azi, cinci mâine. Nimeni nu observă până nu e prea târziu.\n❓ Cele trei întrebări — și nimic altceva #Standup-ul clasic se bazează pe trei întrebări:\nCe am făcut ieri? Ce voi face azi? Mă blochează ceva? Simplu. Dar simplitatea e trădătoare, pentru că tentația de a extinde e constantă.\n\u0026ldquo;Ce am făcut ieri\u0026rdquo; nu înseamnă să-ți povestești ziua. Înseamnă să spui: \u0026ldquo;Am terminat migrarea tabelelor lookup\u0026rdquo; sau \u0026ldquo;Am lucrat la bug-ul #247, nu l-am rezolvat încă.\u0026rdquo; Zece secunde, nu trei minute.\n\u0026ldquo;Ce voi face azi\u0026rdquo; nu e un plan detaliat. E o declarație de intenție: \u0026ldquo;Azi termin bug-ul #247 și încep testele de integrare.\u0026rdquo;\n\u0026ldquo;Mă blochează ceva?\u0026rdquo; e întrebarea cea mai importantă. Pentru că aici apar dependențele, bottleneck-urile, problemele pe care cineva singur nu le poate rezolva. Dar — și asta e fundamental — blocajul se semnalează, nu se rezolvă în direct.\nCând cineva spune \u0026ldquo;Sunt blocat pentru că nu am acces la mediul de staging\u0026rdquo;, răspunsul corect nu e o discuție de cincisprezece minute despre cine trebuie să dea accesul, cum se configurează și de ce nu funcționa ieri. Răspunsul corect e: \u0026ldquo;Ok, vorbim după standup, eu și tu.\u0026rdquo;\nAceastă disciplină este ceea ce menține standup-ul sub 15 minute. Fără ea, fiecare blocaj devine o ședință în interiorul ședinței.\n💀 Când standup-ul moare #Am identificat o listă destul de precisă a modurilor în care un standup poate muri. Le enumăr nu din pesimism, ci pentru că recunoașterea lor e singura cale de prevenire.\nThread killer-ul #O persoană descrie o problemă tehnică complexă. Altă persoană răspunde. Pornește un dialog între doi, în timp ce șase persoane stau. Facilitatorul nu intervine pentru că \u0026ldquo;e un subiect important\u0026rdquo;. Cincisprezece minute pierdute.\nDemo-ul improvizat #\u0026ldquo;Stați, vă arăt ce am făcut.\u0026rdquo; Screen share, navigare în aplicație, explicarea detaliilor de UI. Interesant? Poate. Relevant pentru standup? Nu.\nManagerul care pune întrebări #PM-ul sau team lead-ul începe să aprofundeze: \u0026ldquo;Feature-ul ăla e la 60% sau 70%? Când prevezi să termini? Ai vorbit cu clientul?\u0026rdquo; Standup-ul se transformă într-un raport individual.\nAbsența facilitatorului #Fără cineva care să țină ritmul, standup-ul devine o conversație liberă. Conversația liberă e minunată la cafenea, nu la 9:15 dimineața când opt persoane au de lucru.\nLaptopul deschis #Când oamenii aduc laptopul la standup, mesajul implicit e: \u0026ldquo;Această ședință nu merită atenția mea completă.\u0026rdquo; Și au dreptate — dacă standup-ul durează 40 de minute, chiar nu o merită.\n🛠️ Cum faci un standup să funcționeze — cu adevărat #După douăzeci de ani de proiecte, rețeta mea e aceasta. Nu e elegantă, nu e din manual, dar funcționează.\n1. Timer vizibil #Un cronometru pe ecranul partajat (sau un telefon pe masă) care pornește când începe standup-ul. Toți îl văd. Când arată 15 minute, standup-ul se termină. Punct.\nNu e autoritar. E un acord de echipă. Timer-ul nu e inamicul — e gardianul timpului tuturor.\n2. Facilitator cu mandatul de a tăia #Ai nevoie de o persoană — prin rotație sau fixă — al cărei singur rol e să spună: \u0026ldquo;Ok, asta o aprofundăm după. Următorul.\u0026rdquo; Nu e lipsă de respect. E respect pentru cele șase persoane care așteaptă.\nCel mai bun facilitator o face natural: \u0026ldquo;Interesant, discutăm imediat după. Marco, e rândul tău.\u0026rdquo;\n3. În picioare, cu adevărat #Nu e folclor. A sta în picioare are un efect psihologic concret: oamenii vor să termine repede. Când te așezi, te relaxezi. Când stai în picioare, tinzi spre sinteză.\nDacă echipa e la distanță, principiul se traduce în: camere pornite, fără multitasking. Semnalul trebuie să fie: \u0026ldquo;Aceste 15 minute au atenția mea completă.\u0026rdquo;\n4. Fără laptopuri, fără screen sharing #Standup-ul e verbal. Dacă ceva necesită un demo, o diagramă, o explicație vizuală — nu e material de standup. E material pentru o ședință separată, cu persoanele potrivite.\n5. Parking lot #De fiecare dată când apare un subiect care merită aprofundare, facilitatorul îl notează pe o listă vizibilă — \u0026ldquo;parking lot\u0026rdquo;. După standup, persoanele implicate rămân și discută. Ceilalți merg să lucreze.\nParking lot-ul e instrumentul cel mai subestimat în managementul standup-urilor. Permite să spui \u0026ldquo;discutăm după\u0026rdquo; fără ca subiectul să fie uitat.\n📊 Standup-ul în cifre #Să facem un calcul pe care nimeni nu-l face niciodată.\nO echipă de 8 persoane. Standup zilnic. 220 de zile lucrătoare pe an.\nScenariu Durată Ore/persoană/an Ore totale echipă/an Standup de 15 minute 15 min 55 ore 440 ore Standup de 30 minute 30 min 110 ore 880 ore Standup de 45 minute 45 min 165 ore 1.320 ore Diferența dintre un standup bine gestionat și unul scăpat de sub control este de 880 de ore pe an. Pentru o echipă de 8 persoane. Sunt 110 zile lucrătoare. Aproape cinci luni-om.\nȘi asta fără a număra efectul indirect: un standup de 45 de minute nu fură doar 45 de minute. Fură și cele 10-15 minute de concentrare necesare după pentru a reintra în fluxul de lucru.\n🔄 Standup remote vs în persoană #Din 2020 standup-urile sunt adesea remote. Se schimbă mijlocul, dar principiile rămân identice. Cu câteva precauții suplimentare.\nRemote e mai rău (dacă nu ești atent) # Latența audio creează suprapuneri care alungesc timpii Multitasking-ul e invizibil (dar real) Lipsa limbajului corporal face mai dificil pentru facilitator să știe când să taie Screen sharing-ul e la un click distanță, iar tentația de a-l folosi e mare Cum gestionezi standup-ul remote # Practică Motiv Ordine de vorbire predefinită Evită \u0026ldquo;cine vorbește?\u0026rdquo; și tăcerile stânjenitoare Camere pornite Semnalează prezență și atenție Chat pentru parking lot Captează subiecte în timp real fără a întrerupe Timer partajat pe ecran Același principiu ca standup-ul în persoană Toți pe mute cu excepția celui care vorbește Elimină zgomotul de fond și tentația de a întrerupe Cel mai eficient truc pe care l-am găsit pentru standup-urile remote este runda cu ștafetă: fiecare persoană, după ce vorbește, o numește pe următoarea. \u0026ldquo;Am terminat. Sara, e rândul tău.\u0026rdquo; Asta menține atenția activă și dă ritm ședinței.\n🎯 Standup-ul e un instrument, nu un ritual #Ce m-a frapat întotdeauna e ușurința cu care standup-ul devine un ritual gol. Îl faci pentru că \u0026ldquo;așa se face\u0026rdquo;, pentru că \u0026ldquo;suntem agili\u0026rdquo;, pentru că \u0026ldquo;framework-ul o cere\u0026rdquo;. Dar nimeni nu se mai întreabă: funcționează?\nUn standup funcționează când echipa îl percepe ca util. Când la 9:15 oamenii vin cu plăcere, spun ce au de spus în două minute, îi ascultă pe ceilalți, și la 9:30 sunt la birou știind exact ce se întâmplă în proiect.\nUn standup nu funcționează când oamenii îl percep ca o obligație. Când oftează uitându-se la ceas. Când verifică telefonul. Când se gândesc \u0026ldquo;puteam folosi jumătatea asta de oră să lucrez.\u0026rdquo;\nDiferența dintre cele două scenarii e aproape întotdeauna aceeași: dacă constrângerea de 15 minute e respectată sau nu.\nNu ai nevoie de framework-uri sofisticate. Nu ai nevoie de certificări. Ai nevoie de un timer, un facilitator cu coloană vertebrală și conștiința că timpul oamenilor are valoare.\nCincisprezece minute. Trei întrebări. Parking lot pentru rest.\nTot restul e zgomot.\nGlosar #Daily Standup — Ședință zilnică de maximum 15 minute în care fiecare membru al echipei răspunde la trei întrebări: ce am făcut ieri, ce voi face azi, ce mă blochează.\nParking Lot — Listă vizibilă de subiecte apărute în timpul unei ședințe care merită aprofundare dar sunt amânate pentru a respecta timeboxul.\nFacilitator — Persoană responsabilă de ghidarea unei ședințe menținând focusul, respectând timeboxul și garantând că toți au voce.\nTimeboxing — Tehnică de gestionare a timpului care atribuie un interval fix și nenegociabil unei activități, forțând încheierea în limita stabilită.\nScrum — Framework agil pentru gestionarea proiectelor care organizează munca în sprinturi cu durată fixă, cu roluri definite și ceremonii structurate.\n","date":"27 ianuarie 2026","permalink":"https://ivanluminaria.com/ro/posts/project-management/standup-meeting-15-minuti/","section":"Database Strategy","summary":"\u003cp\u003ePrima zi de luni a proiectului. Echipă nouă, metodologie nouă, speranțe noi. PM-ul propune standup-ul zilnic. Toți dau din cap. \u0026ldquo;Cincisprezece minute, în picioare, trei întrebări. Simplu.\u0026rdquo;\u003c/p\u003e\n\u003cp\u003ePrima săptămână funcționează. La 9:15 începe, la 9:28 ești deja la birou. Fiecare spune ce are de spus în două minute, se semnalează blocajele, se salută. Eficiență pură.\u003c/p\u003e\n\u003cp\u003eA doua săptămână cineva ridică mâna în mijlocul rundei: \u0026ldquo;Pot să explic un moment problema pe care o am cu integrarea?\u0026rdquo; Cinci minute de discuție tehnică între două persoane. Ceilalți șase stau și ascultă ceva ce nu-i privește.\u003c/p\u003e","title":"Standup meeting: de ce funcționează doar dacă durează 15 minute"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/team-management/","section":"Tags","summary":"","title":"Team-Management"},{"content":"Mi s-a întâmplat de mai multe ori: intru într-un mediu Oracle și găsesc aceeași situație. Toți utilizatorii aplicativi conectați ca schema owner, cu rolul DBA atribuit. Dezvoltatori, procese batch, instrumente de raportare — toți cu aceleași privilegii ca utilizatorul proprietar al tabelelor.\nCând întrebi de ce, răspunsul este mereu o variantă a: „Așa funcționează totul fără probleme de permisiuni.\u0026quot;\nSigur. Totul funcționează. Până în ziua în care un dezvoltator execută un DROP TABLE pe tabela greșită. Sau un batch de import face un TRUNCATE pe o tabelă de producție crezând că este în mediul de test. Sau cineva execută un DELETE FROM clienti fără clauza WHERE.\nÎn ziua aceea problema nu mai sunt permisiunile. Este că nu ai idee cine a făcut ce și nu ai niciun instrument pentru a preveni să se întâmple din nou.\nContextul: un tipar care se repetă #Clientul era o companie de dimensiuni medii cu o aplicație de gestiune pe Oracle 19c. Aproximativ douăzeci de utilizatori — un mix de dezvoltatori, conturi aplicative și operatori. Schema aplicativă — să o numim APP_OWNER — conținea aproximativ 300 de tabele, vreo șaizeci de vizualizări și câteva zeci de proceduri PL/SQL.\nProblema era ușor de descris:\nToți se conectau ca APP_OWNER APP_OWNER avea rolul DBA Niciun audit configurat Nicio separare între cine citește și cine scrie Parolele erau partajate prin email Nu era neglijență. Era inerție. Sistemul crescuse așa de-a lungul anilor, și nimeni nu se oprise să regândească modelul. Funcționa, și asta era suficient.\nPână când un operator a șters din greșeală datele de facturare ale unui trimestru întreg. Niciun log, nicio urmă, niciun vinovat identificabil. Doar un backup de acum două zile și o gaură în date care a necesitat săptămâni de muncă pentru a fi acoperită.\nCum funcționează securitatea în Oracle: modelul #Înainte de a povesti ce am făcut, trebuie înțeles cum structurează Oracle securitatea. Modelul este diferit de PostgreSQL și de MySQL, iar diferențele nu sunt cosmetice.\nUtilizator și schema: același lucru (aproape) #În Oracle, crearea unui utilizator înseamnă crearea unei scheme. Nu sunt două concepte separate: utilizatorul APP_OWNER este și schema APP_OWNER, iar obiectele create de acel utilizator trăiesc în acea schemă.\nCREATE USER app_read IDENTIFIED BY \u0026#34;ParolaSecura#2026\u0026#34; DEFAULT TABLESPACE users TEMPORARY TABLESPACE temp QUOTA 0 ON users; QUOTA 0 este intenționată: acest utilizator nu trebuie să creeze obiecte. Este un consumator, nu un proprietar.\nPrivilegii de sistem vs privilegii de obiect #Oracle face o distincție clară între:\nSystem privileges: operațiuni globale precum CREATE TABLE, CREATE SESSION, ALTER SYSTEM Object privileges: operațiuni pe obiecte specifice precum SELECT ON app_owner.clienti, EXECUTE ON app_owner.pkg_facturi Rolul DBA include peste 200 de system privileges. A-l atribui unui utilizator aplicativ este ca și cum ai da cheile întregii clădiri cuiva care trebuie doar să intre într-o cameră.\nRolurile: predefinite și personalizate #Oracle oferă roluri predefinite (CONNECT, RESOURCE, DBA) și permite crearea de roluri personalizate. Rolurile predefinite au o problemă istorică: CONNECT și RESOURCE includeau privilegii excesive în versiunile mai vechi. De la Oracle 12c au fost reduse, dar obiceiul de a le atribui fără să te gândești este greu de eliminat.\nCalea corectă este crearea de roluri personalizate calibrate la nevoile reale.\nImplementarea: trei roluri, zero ambiguitate #Am proiectat trei roluri: citire, scriere și administrare aplicativă.\n1. Rol de citire #CREATE ROLE app_read_role; -- Privilegii pe tabele GRANT SELECT ON app_owner.clienti TO app_read_role; GRANT SELECT ON app_owner.comenzi TO app_read_role; GRANT SELECT ON app_owner.facturi TO app_read_role; GRANT SELECT ON app_owner.produse TO app_read_role; GRANT SELECT ON app_owner.tranzactii TO app_read_role; -- Privilegii pe vizualizări GRANT SELECT ON app_owner.v_raport_vanzari TO app_read_role; GRANT SELECT ON app_owner.v_stare_comenzi TO app_read_role; Într-un mediu cu 300 de tabele nu le enumerezi una câte una manual. Am folosit un bloc PL/SQL pentru a genera grant-urile:\nBEGIN FOR t IN (SELECT table_name FROM dba_tables WHERE owner = \u0026#39;APP_OWNER\u0026#39;) LOOP EXECUTE IMMEDIATE \u0026#39;GRANT SELECT ON app_owner.\u0026#39; || t.table_name || \u0026#39; TO app_read_role\u0026#39;; END LOOP; END; / Simplu, repetabil și mai ales: documentat. Pentru că peste șase luni cineva va trebui să înțeleagă ce s-a făcut și de ce.\n2. Rol de citire și scriere #CREATE ROLE app_write_role; -- Moștenește totul din rolul de citire GRANT app_read_role TO app_write_role; -- Adaugă DML pe tabelele operaționale GRANT INSERT, UPDATE, DELETE ON app_owner.comenzi TO app_write_role; GRANT INSERT, UPDATE, DELETE ON app_owner.tranzactii TO app_write_role; GRANT INSERT, UPDATE ON app_owner.clienti TO app_write_role; -- Permisiune de execuție pe procedurile aplicative GRANT EXECUTE ON app_owner.pkg_comenzi TO app_write_role; GRANT EXECUTE ON app_owner.pkg_facturi TO app_write_role; Notă: niciun DELETE pe tabela clienti. Nu pentru că ar fi imposibil tehnic, ci pentru că procesul aplicativ prevede o dezactivare, nu o ștergere. Privilegiul reflectă procesul, nu comoditatea.\n3. Rol de administrare aplicativă #CREATE ROLE app_admin_role; -- Moștenește rolul de scriere GRANT app_write_role TO app_admin_role; -- Adaugă DDL controlat GRANT CREATE VIEW TO app_admin_role; GRANT CREATE PROCEDURE TO app_admin_role; GRANT CREATE SYNONYM TO app_admin_role; -- Poate gestiona tabelele de configurare GRANT INSERT, UPDATE, DELETE ON app_owner.parametri TO app_admin_role; GRANT INSERT, UPDATE, DELETE ON app_owner.lookup_tipuri TO app_admin_role; Niciun CREATE TABLE, niciun DROP ANY, niciun ALTER SYSTEM. Admin-ul aplicativ gestionează logica, nu structura fizică.\nCrearea utilizatorilor și atribuirea rolurilor #-- Utilizator pentru rapoarte (doar citire) CREATE USER srv_report IDENTIFIED BY \u0026#34;RptSecure#2026\u0026#34; DEFAULT TABLESPACE users TEMPORARY TABLESPACE temp QUOTA 0 ON users; GRANT CREATE SESSION TO srv_report; GRANT app_read_role TO srv_report; -- Utilizator aplicativ (citire și scriere) CREATE USER srv_app IDENTIFIED BY \u0026#34;AppSecure#2026\u0026#34; DEFAULT TABLESPACE users TEMPORARY TABLESPACE temp QUOTA 0 ON users; GRANT CREATE SESSION TO srv_app; GRANT app_write_role TO srv_app; -- DBA aplicativ (administrare) CREATE USER dba_app IDENTIFIED BY \u0026#34;DbaSecure#2026\u0026#34; DEFAULT TABLESPACE users TEMPORARY TABLESPACE temp QUOTA 10M ON users; GRANT CREATE SESSION TO dba_app; GRANT app_admin_role TO dba_app; Fiecare utilizator are propria parolă, un rol specific și o cotă de disc coerentă cu scopul său. srv_report nu are cotă pentru că nu trebuie să creeze nimic. dba_app are 10 MB pentru că trebuie să poată crea vizualizări și proceduri.\nRevocarea rolului DBA #Pasul cel mai delicat: eliminarea DBA de la APP_OWNER.\nREVOKE DBA FROM app_owner; O linie. Dar înainte de a o executa, am verificat că APP_OWNER mai avea privilegiile necesare pentru a-și deține obiectele:\nSELECT privilege FROM dba_sys_privs WHERE grantee = \u0026#39;APP_OWNER\u0026#39;; SELECT granted_role FROM dba_role_privs WHERE grantee = \u0026#39;APP_OWNER\u0026#39;; Și am acordat doar privilegiile strict necesare:\nGRANT CREATE SESSION TO app_owner; GRANT CREATE TABLE TO app_owner; GRANT CREATE VIEW TO app_owner; GRANT CREATE PROCEDURE TO app_owner; GRANT CREATE SEQUENCE TO app_owner; GRANT UNLIMITED TABLESPACE TO app_owner; APP_OWNER rămâne proprietarul obiectelor dar nu mai are puterea de a face orice pe baza de date. Este un proprietar, nu un zeu.\nAudit: a ști cine ce a făcut #A avea rolurile corecte nu este suficient. Trebuie să știi cine ce a făcut, mai ales pentru operațiunile critice.\nOracle de la versiunea 12c oferă Unified Audit, care înlocuiește vechiul audit tradițional cu un sistem centralizat.\n-- Audit pe operațiuni DDL critice CREATE AUDIT POLICY pol_ddl_critic ACTIONS CREATE TABLE, DROP TABLE, ALTER TABLE, TRUNCATE TABLE, CREATE USER, DROP USER, ALTER USER, GRANT, REVOKE; ALTER AUDIT POLICY pol_ddl_critic ENABLE; -- Audit pe accesul la date sensibile CREATE AUDIT POLICY pol_acces_date ACTIONS SELECT ON app_owner.clienti, DELETE ON app_owner.facturi, UPDATE ON app_owner.facturi; ALTER AUDIT POLICY pol_acces_date ENABLE; -- Audit pe autentificări eșuate CREATE AUDIT POLICY pol_login_esuat ACTIONS LOGON; ALTER AUDIT POLICY pol_login_esuat ENABLE WHENEVER NOT SUCCESSFUL; Pentru a verifica ce se înregistrează:\nSELECT * FROM unified_audit_trail WHERE event_timestamp \u0026gt; SYSDATE - 7 ORDER BY event_timestamp DESC; Auditul nu este paranoia. Este singura modalitate de a răspunde la întrebarea „cine ce a făcut?\u0026quot; fără a te baza pe intuiție.\nComparația cu PostgreSQL și MySQL #Acest articol este al treilea dintr-o serie despre gestionarea securității în bazele de date relaționale. Primele două acoperă PostgreSQL și MySQL.\nDiferențele dintre cele trei sisteme sunt substanțiale:\nAspect Oracle PostgreSQL MySQL Utilizator = schemă? Da Nu (independente) Da (baze de date separate) Model de roluri Predefinite + custom Totul este un ROLE Roluri de la MySQL 8.0 Identitate Nume utilizator Nume utilizator Pereche utilizator@host Audit nativ Unified Audit (12c+) pgAudit (extensie) Audit plugin Privilegii granulare System + Object Database/Schema/Object Global/DB/Table/Column GRANT ALL Există dar periculos Există, nerecomandat Există, nerecomandat În PostgreSQL totul este un ROLE, iar simplitatea modelului este punctul său forte. În MySQL identitatea este legată de host-ul de origine, ceea ce adaugă un nivel de complexitate (și securitate) pe care celelalte nu îl au. În Oracle modelul este cel mai bogat și cel mai granular, dar și cel mai ușor de configurat greșit din cauza numărului mare de opțiuni.\nPrincipiul rămâne același peste tot: dă fiecăruia doar ce are nevoie, niciun privilegiu în plus.\nCe s-a schimbat după #Tranziția a fost graduală — două săptămâni pentru implementarea completă, cu teste pe fiecare aplicație și procedură. Câteva scripturi au încetat să funcționeze pentru că presupuneau privilegii care nu le aparțineau. Fiecare eroare era de fapt o problemă ascunsă care înainte era invizibilă.\nRezultatul:\n20 utilizatori nominali în locul unui singur schema partajat 3 roluri personalizate în locul rolului DBA Audit activ pe DDL și operațiuni sensibile Zero incidente de ștergere accidentală în lunile următoare Clientul nu a observat îmbunătățiri de performanță. Nu acesta era obiectivul. A observat că atunci când cineva greșea, paguba era limitată și trasabilă. Și asta, într-un mediu de producție, valorează mai mult decât orice optimizare.\nConcluzie #GRANT ALL PRIVILEGES și rolul DBA sunt scurtături. Funcționează în sensul că elimină erorile de permisiuni. Dar elimină și orice strat de protecție.\nSecuritatea în Oracle nu este o problemă de instrumente — instrumentele există, și sunt puternice. Este o problemă de proiectare: a decide cine poate face ce, a documenta, a implementa și apoi a verifica că funcționează.\nNu este munca cea mai glamuroasă din lume. Dar este cea care face diferența între o bază de date care doar supraviețuiește și una care este cu adevărat sub control.\nGlosar #System Privilege — Privilegiu Oracle care autorizează operațiuni globale pe baza de date precum CREATE TABLE, CREATE SESSION sau ALTER SYSTEM, independente de orice obiect specific.\nObject Privilege — Privilegiu Oracle care autorizează operațiuni pe un obiect specific al bazei de date precum SELECT, INSERT sau EXECUTE pe o tabelă, vizualizare sau procedură.\nREVOKE — Comandă SQL pentru eliminarea privilegiilor sau rolurilor acordate anterior unui utilizator sau rol, complementară comenzii GRANT.\nUnified Audit — Sistem de audit centralizat introdus în Oracle 12c care unifică toate tipurile de audit într-o singură infrastructură, înlocuind vechiul audit tradițional.\nLeast Privilege — Principiu de securitate care prevede atribuirea fiecărui utilizator doar a permisiunilor strict necesare pentru îndeplinirea funcției sale.\n","date":"27 ianuarie 2026","permalink":"https://ivanluminaria.com/ro/posts/oracle/oracle-roles-privileges/","section":"Database Strategy","summary":"\u003cp\u003eMi s-a întâmplat de mai multe ori: intru într-un mediu Oracle și găsesc aceeași situație. Toți utilizatorii aplicativi conectați ca schema owner, cu rolul DBA atribuit. Dezvoltatori, procese batch, instrumente de raportare — toți cu aceleași privilegii ca utilizatorul proprietar al tabelelor.\u003c/p\u003e\n\u003cp\u003eCând întrebi de ce, răspunsul este mereu o variantă a: „Așa funcționează totul fără probleme de permisiuni.\u0026quot;\u003c/p\u003e\n\u003cp\u003eSigur. Totul funcționează. Până în ziua în care un dezvoltator execută un \u003ccode\u003eDROP TABLE\u003c/code\u003e pe tabela greșită. Sau un batch de import face un \u003ccode\u003eTRUNCATE\u003c/code\u003e pe o tabelă de producție crezând că este în mediul de test. Sau cineva execută un \u003ccode\u003eDELETE FROM clienti\u003c/code\u003e fără clauza \u003ccode\u003eWHERE\u003c/code\u003e.\u003c/p\u003e","title":"Utilizatori, roluri și privilegii în Oracle: de ce GRANT ALL nu este niciodată răspunsul"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/categories/data-warehouse/","section":"Categories","summary":"","title":"Data-Warehouse"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/dimensional-modeling/","section":"Tags","summary":"","title":"Dimensional-Modeling"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/etl/","section":"Tags","summary":"","title":"Etl"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/hierarchies/","section":"Tags","summary":"","title":"Hierarchies"},{"content":"Trei niveluri. Top Group, Group, Client. Pare o structură banală — tipul de ierarhie pe care o desenezi pe o tablă în cinci minute și pe care orice instrument de BI ar trebui să o gestioneze fără probleme.\nApoi descoperi că nu toți clienții aparțin unui grup. Și că nu toate grupurile aparțin unui top group. Și că rapoartele de agregare pe care business-ul le solicită — cifra de afaceri per top group, număr de clienți per grup, drill-down de la vârf la frunză — produc rezultate greșite sau incomplete pentru că ierarhia are goluri.\nÎn jargon tehnic se numește ragged hierarchy : o ierarhie în care nu toate ramurile ajung la aceeași adâncime. În lumea reală se numește „problema pe care nimeni nu o vede până nu deschide raportul și numerele nu se potrivesc.\u0026quot;\nClientul și modelul original #Proiectul era un data warehouse pentru o companie din sectorul energetic — distribuție de gaz și servicii conexe. Sistemul sursă gestiona un registru de clienți cu o structură ierarhică: clienții puteau fi grupați sub o entitate comercială (Group), iar grupurile puteau la rândul lor aparține unei entități superioare (Top Group).\nModelul din sursă era o singură tabelă cu referințele ierarhice:\nCREATE TABLE stg_clienti ( client_id NUMBER(10) NOT NULL, client_name VARCHAR2(100) NOT NULL, group_id NUMBER(10), group_name VARCHAR2(100), top_group_id NUMBER(10), top_group_name VARCHAR2(100), revenue NUMBER(15,2), region VARCHAR2(50), CONSTRAINT pk_stg_clienti PRIMARY KEY (client_id) ); Iată un eșantion de date:\nINSERT INTO stg_clienti VALUES (1001, \u0026#39;Rossi Energia Srl\u0026#39;, 10, \u0026#39;Consorzio Nord\u0026#39;, 100, \u0026#39;Holding Nazionale\u0026#39;, 125000.00, \u0026#39;Lombardia\u0026#39;); INSERT INTO stg_clienti VALUES (1002, \u0026#39;Bianchi Gas SpA\u0026#39;, 10, \u0026#39;Consorzio Nord\u0026#39;, 100, \u0026#39;Holding Nazionale\u0026#39;, 89000.00, \u0026#39;Piemonte\u0026#39;); INSERT INTO stg_clienti VALUES (1003, \u0026#39;Verdi Distribuzione\u0026#39;, 20, \u0026#39;Gruppo Centro\u0026#39;, 100, \u0026#39;Holding Nazionale\u0026#39;, 67000.00, \u0026#39;Toscana\u0026#39;); INSERT INTO stg_clienti VALUES (1004, \u0026#39;Neri Servizi\u0026#39;, 20, \u0026#39;Gruppo Centro\u0026#39;, NULL, NULL, 45000.00, \u0026#39;Lazio\u0026#39;); INSERT INTO stg_clienti VALUES (1005, \u0026#39;Gialli Utilities\u0026#39;, NULL, NULL, NULL, NULL, 38000.00, \u0026#39;Sicilia\u0026#39;); INSERT INTO stg_clienti VALUES (1006, \u0026#39;Blu Energia\u0026#39;, NULL, NULL, NULL, NULL, 52000.00, \u0026#39;Sardegna\u0026#39;); INSERT INTO stg_clienti VALUES (1007, \u0026#39;Viola Gas Srl\u0026#39;, 30, \u0026#39;Rete Sud\u0026#39;, NULL, NULL, 71000.00, \u0026#39;Campania\u0026#39;); INSERT INTO stg_clienti VALUES (1008, \u0026#39;Arancio Distribuzione\u0026#39;, 30, \u0026#39;Rete Sud\u0026#39;, NULL, NULL, 33000.00, \u0026#39;Calabria\u0026#39;); Uitați-vă la date cu atenție. Există patru situații diferite:\nClient 1001, 1002, 1003: ierarhie completă — Client → Group → Top Group Client 1004: are un Group dar Group-ul nu are Top Group Client 1005, 1006: fără Group, fără Top Group — clienți direcți Client 1007, 1008: au un Group (Rete Sud) dar Group-ul nu are Top Group Aceasta este o ragged hierarchy. Trei niveluri pe hârtie, dar în realitate ramurile au adâncimi diferite.\nProblema: rapoartele nu se potrivesc #Business-ul cerea un raport simplu: cifra de afaceri agregată per Top Group, cu posibilitate de drill-down per Group și apoi per Client. O cerere rezonabilă — tipul de lucru pe care îl aștepți de la orice DWH.\nInterogarea cea mai naturală:\nSELECT top_group_name, group_name, COUNT(*) AS num_clienti, SUM(revenue) AS cifra_afaceri_totala FROM stg_clienti GROUP BY top_group_name, group_name ORDER BY top_group_name, group_name; Rezultatul:\nTOP_GROUP_NAME GROUP_NAME NUM_CLIENTI CIFRA_AFACERI_TOTALA ------------------ ---------------- ----------- -------------------- Holding Nazionale Consorzio Nord 2 214000.00 Holding Nazionale Gruppo Centro 1 67000.00 (null) Gruppo Centro 1 45000.00 (null) Rete Sud 2 104000.00 (null) (null) 2 90000.00 Cinci rânduri. Și cel puțin trei probleme.\nGruppo Centro apare de două ori: o dată sub „Holding Nazionale\u0026quot; (clientul 1003 care are top group) și o dată sub NULL (clientul 1004 al cărui top group este NULL). Același grup, despicat pe două rânduri, cu totaluri separate. Oricine se uită la acest raport va crede că Gruppo Centro are 67K cifră de afaceri sub holding și 45K undeva în altă parte. În realitate este un singur grup cu 112K total.\nClienții direcți (Gialli Utilities și Blu Energia) ajung într-un rând cu două NULL-uri. Managementul nu știe ce să facă cu un rând fără nume.\nTotalul per Top Group este greșit pentru că lipsesc rândurile cu NULL. Dacă aduni doar rândurile cu top group, pierzi 239K din cifra de afaceri — 30% din total.\nAbordarea clasică: COALESCE și rugăciuni #Prima reacție, cea pe care o văd în 90% din cazuri, este să adaugi `COALESCE` în interogare:\nSELECT COALESCE(top_group_name, group_name, client_name) AS top_group_name, COALESCE(group_name, client_name) AS group_name, client_name, revenue FROM stg_clienti; Funcționează? Într-un fel da — umple golurile. Dar introduce probleme noi.\nClientul „Gialli Utilities\u0026quot; acum apare ca Top Group, Group și Client simultan. Dacă business-ul vrea să numere câte Top Group-uri sunt, numărul este umflat. Dacă vrea să filtreze pentru „adevăratele\u0026quot; top group-uri, nu are cum să le distingă de clienții promovați de COALESCE.\nȘi acesta este cazul simplu, cu trei niveluri. Am văzut ierarhii pe cinci niveluri gestionate cu lanțuri de COALESCE îmbricate, multiple CASE WHEN, și o logică de raportare atât de încâlcită încât nimeni nu mai îndrăznea să o atingă. Fiecare nouă cerere de business necesita modificări în cascadă în toate interogările.\nProblema de fond este că COALESCE este un plasture aplicat la nivelul de prezentare. Nu rezolvă problema structurală: ierarhia este incompletă și modelul dimensional nu știe acest lucru.\nSoluția: self-parenting #Principiul este simplu: cine nu are părinte devine propriul părinte. Această tehnică se numește self-parenting .\nUn Client fără Group? Acel client devine propriul Group. Un Group fără Top Group? Acel grup devine propriul Top Group. În acest mod ierarhia este întotdeauna completă pe trei niveluri, fără goluri, fără NULL.\nNu este un truc. Este o tehnică standard în modelarea dimensională, descrisă de Kimball și folosită în producție de decenii. Ideea este că dimensiunea ierarhică în DWH trebuie să fie echilibrată: fiecare înregistrare trebuie să aibă o valoare validă pentru fiecare nivel al ierarhiei. Dacă sursa nu garantează acest lucru, ETL -ul o face.\nTabela dimensională #CREATE TABLE dim_client_hierarchy ( client_key NUMBER(10) NOT NULL, client_id NUMBER(10) NOT NULL, client_name VARCHAR2(100) NOT NULL, group_id NUMBER(10) NOT NULL, group_name VARCHAR2(100) NOT NULL, top_group_id NUMBER(10) NOT NULL, top_group_name VARCHAR2(100) NOT NULL, region VARCHAR2(50), is_direct_client CHAR(1) DEFAULT \u0026#39;N\u0026#39;, is_standalone_group CHAR(1) DEFAULT \u0026#39;N\u0026#39;, CONSTRAINT pk_dim_client_hier PRIMARY KEY (client_key) ); Observați două lucruri. Primul: nicio coloană nu este nullable. Group și Top Group sunt NOT NULL. Al doilea: am adăugat două flag-uri — is_direct_client și is_standalone_group — care permit distingerea înregistrărilor echilibrate artificial de cele cu o ierarhie naturală. Acest lucru este important: business-ul trebuie să poată filtra „adevăratele\u0026quot; top group-uri de clienții promovați.\nLogica ETL #INSERT INTO dim_client_hierarchy ( client_key, client_id, client_name, group_id, group_name, top_group_id, top_group_name, region, is_direct_client, is_standalone_group ) SELECT client_id AS client_key, client_id, client_name, -- Dacă nu are group, clientul devine propriul group COALESCE(group_id, client_id) AS group_id, COALESCE(group_name, client_name) AS group_name, -- Dacă nu are top group, group-ul (sau clientul) devine propriul top group COALESCE(top_group_id, group_id, client_id) AS top_group_id, COALESCE(top_group_name, group_name, client_name) AS top_group_name, region, CASE WHEN group_id IS NULL THEN \u0026#39;Y\u0026#39; ELSE \u0026#39;N\u0026#39; END AS is_direct_client, CASE WHEN group_id IS NOT NULL AND top_group_id IS NULL THEN \u0026#39;Y\u0026#39; ELSE \u0026#39;N\u0026#39; END AS is_standalone_group FROM stg_clienti; Uitați-vă la cascada de COALESCE din transformare. Logica este:\ngroup_id: dacă clientul are group, folosește-l; altfel folosește clientul însuși top_group_id: dacă există top group, folosește-l; dacă nu dar există group, folosește group-ul; dacă nu există nici group, folosește clientul Fiecare nivel „lipsă\u0026quot; este completat de nivelul imediat inferior. Rezultatul este o ierarhie întotdeauna completă.\nRezultatul după echilibrare #SELECT client_key, client_name, group_name, top_group_name, is_direct_client, is_standalone_group FROM dim_client_hierarchy ORDER BY top_group_id, group_id, client_id; KEY CLIENT_NAME GROUP_NAME TOP_GROUP_NAME DIRECT STANDALONE ---- -------------------- ---------------- ------------------ ------ ---------- 1001 Rossi Energia Srl Consorzio Nord Holding Nazionale N N 1002 Bianchi Gas SpA Consorzio Nord Holding Nazionale N N 1003 Verdi Distribuzione Gruppo Centro Holding Nazionale N N 1004 Neri Servizi Gruppo Centro Gruppo Centro N Y 1007 Viola Gas Srl Rete Sud Rete Sud N Y 1008 Arancio Distribuzione Rete Sud Rete Sud N Y 1005 Gialli Utilities Gialli Utilities Gialli Utilities Y N 1006 Blu Energia Blu Energia Blu Energia Y N Opt rânduri, zero NULL. Fiecare client are un group și un top group. Flag-urile spun adevărul: Gialli și Blu sunt clienți direcți (self-parented la toate nivelurile), Gruppo Centro și Rete Sud sunt grupuri standalone (self-parented la nivelul top group).\nRapoartele după echilibrare #Aceeași interogare de agregare care anterior producea rezultate sparte:\nSELECT top_group_name, group_name, COUNT(*) AS num_clienti, SUM(f.revenue) AS cifra_afaceri_totala FROM dim_client_hierarchy d JOIN stg_clienti f ON d.client_id = f.client_id GROUP BY top_group_name, group_name ORDER BY top_group_name, group_name; TOP_GROUP_NAME GROUP_NAME NUM_CLIENTI CIFRA_AFACERI_TOTALA ------------------ ------------------ ----------- -------------------- Blu Energia Blu Energia 1 52000.00 Gialli Utilities Gialli Utilities 1 38000.00 Gruppo Centro Gruppo Centro 1 45000.00 Holding Nazionale Consorzio Nord 2 214000.00 Holding Nazionale Gruppo Centro 1 67000.00 Rete Sud Rete Sud 2 104000.00 Niciun NULL. Fiecare rând are un top group și un group identificabile. Totalurile se potrivesc.\nȘi dacă business-ul vrea doar „adevăratele\u0026quot; top group-uri, excluzând clienții promovați:\nSELECT top_group_name, COUNT(*) AS num_clienti, SUM(f.revenue) AS cifra_afaceri_totala FROM dim_client_hierarchy d JOIN stg_clienti f ON d.client_id = f.client_id WHERE d.is_direct_client = \u0026#39;N\u0026#39; AND d.is_standalone_group = \u0026#39;N\u0026#39; GROUP BY top_group_name ORDER BY cifra_afaceri_totala DESC; TOP_GROUP_NAME NUM_CLIENTI CIFRA_AFACERI_TOTALA ------------------ ----------- -------------------- Holding Nazionale 3 281000.00 Flag-urile fac totul filtrabil. Fără logică condițională în raport, fără CASE WHEN, fără COALESCE. Modelul dimensional conține deja toată informația necesară.\nDrill-down-ul complet #Adevăratul test al unei ierarhii echilibrate este drill-down-ul: de la nivelul cel mai înalt la cel mai de jos, fără surprize.\n-- Nivelul 1: total per Top Group SELECT top_group_name, COUNT(DISTINCT group_id) AS num_grupuri, COUNT(*) AS num_clienti, SUM(f.revenue) AS cifra_afaceri FROM dim_client_hierarchy d JOIN stg_clienti f ON d.client_id = f.client_id GROUP BY top_group_name ORDER BY cifra_afaceri DESC; TOP_GROUP_NAME NUM_GRUPURI NUM_CLIENTI CIFRA_AFACERI ------------------ ----------- ----------- ------------- Holding Nazionale 2 3 281000.00 Rete Sud 1 2 104000.00 Blu Energia 1 1 52000.00 Gruppo Centro 1 1 45000.00 Gialli Utilities 1 1 38000.00 -- Nivelul 2: drill-down în \u0026#34;Holding Nazionale\u0026#34; SELECT group_name, COUNT(*) AS num_clienti, SUM(f.revenue) AS cifra_afaceri FROM dim_client_hierarchy d JOIN stg_clienti f ON d.client_id = f.client_id WHERE d.top_group_name = \u0026#39;Holding Nazionale\u0026#39; GROUP BY group_name ORDER BY cifra_afaceri DESC; GROUP_NAME NUM_CLIENTI CIFRA_AFACERI ---------------- ----------- ------------- Consorzio Nord 2 214000.00 Gruppo Centro 1 67000.00 -- Nivelul 3: drill-down în \u0026#34;Consorzio Nord\u0026#34; SELECT client_name, f.revenue FROM dim_client_hierarchy d JOIN stg_clienti f ON d.client_id = f.client_id WHERE d.group_name = \u0026#39;Consorzio Nord\u0026#39; ORDER BY f.revenue DESC; CLIENT_NAME REVENUE ------------------- ---------- Rossi Energia Srl 125000.00 Bianchi Gas SpA 89000.00 Trei niveluri de drill-down, zero NULL, zero logică condițională. Ierarhia este echilibrată și numerele se potrivesc la fiecare nivel.\nDe ce COALESCE în rapoarte nu este suficient #Cineva ar putea obiecta: „Dar COALESCE în raport face același lucru, fără să modifici modelul.\u0026quot;\nNu. Face ceva asemănător, dar cu trei diferențe fundamentale.\nPrimul: COALESCE trebuie repetat peste tot. Fiecare interogare, fiecare raport, fiecare dashboard, fiecare extracție. Dacă ai douăzeci de rapoarte care folosesc ierarhia, trebuie să îți amintești să aplici COALESCE în toate douăzeci. Și când vine al douăzeci și unulea, trebuie să îți amintești din nou. Self-parenting-ul în modelul dimensional se face o dată în ETL și gata.\nAl doilea: COALESCE nu distinge. Nu știi dacă „Gialli Utilities\u0026quot; în câmpul top_group este un adevărat top group sau un client promovat. Cu flag-urile din modelul dimensional ai informația pentru a filtra. Fără flag-uri, business-ul este orb.\nAl treilea: performanța. Un GROUP BY cu COALESCE pe coloane nullable este mai puțin eficient decât un GROUP BY pe coloane NOT NULL. Optimizatorul Oracle gestionează mai bine coloanele cu constrângere NOT NULL — poate elimina verificările de NULL, poate folosi indecșii mai agresiv și poate produce planuri de execuție mai simple. Pe o tabelă dimensională cu milioane de rânduri, diferența se vede.\nCând să folosești self-parenting (și când nu) #Self-parenting-ul funcționează bine când:\nIerarhia are un număr fix de niveluri (de obicei 2-5) Cazul de utilizare principal este agregarea și drill-down-ul în rapoarte Modelul este un data warehouse sau un cub OLAP Nivelurile lipsă sunt excepția, nu regula Nu funcționează bine când:\nIerarhia este recursivă cu adâncime variabilă (ex. organigrame cu N niveluri) Trebuie navigat graful relațiilor (ex. rețele sociale, lanțuri de aprovizionare) Modelul este OLTP și self-parenting-ul ar crea ambiguitate în logicile aplicative Nivelurile ierarhiei se schimbă frecvent în timp Pentru ierarhiile recursive cu adâncime variabilă, abordarea corectă este diferită: tabele de bridge, closure tables sau modele parent-child cu CTE-uri recursive. Sunt instrumente puternice dar rezolvă o problemă diferită.\nSelf-parenting-ul rezolvă o problemă specifică — ierarhii cu niveluri fixe și ramuri incomplete — și o rezolvă în modul cel mai simplu posibil: echilibrând structura în amonte, în model, în loc de aval, în rapoarte.\nRegula care mă ghidează #Am proiectat zeci de dimensiuni ierarhice în douăzeci de ani de data warehousing. Regula pe care o port cu mine este întotdeauna aceeași:\nDacă raportul are nevoie de logică condițională pentru a gestiona ierarhia, problema este în model, nu în raport.\nUn raport ar trebui să facă GROUP BY și JOIN. Dacă trebuie și să decidă cum să gestioneze nivelurile lipsă, face munca ETL-ului. Și un raport care face munca ETL-ului este un raport care mai devreme sau mai târziu se strică.\nSelf-parenting-ul nu este elegant. Nu este sofisticat. Este o soluție pe care un informatician proaspăt absolvent ar putea-o găsi urâtă. Dar funcționează, este mentenabil, și transformă o problemă care infestează fiecare raport individual într-o problemă care se rezolvă o dată, într-un singur loc, și nu mai revine.\nUneori cea mai bună soluție este cea mai simplă. Aceasta este una dintre acele dăți.\nGlosar #COALESCE — Funcție SQL care returnează prima valoare non-NULL dintr-o listă de expresii. Adesea folosită ca workaround pentru ierarhiile incomplete în rapoarte, dar nu rezolvă problema structurală din modelul dimensional.\nDrill-down — Navigare în rapoarte de la un nivel agregat la un nivel de detaliu (ex. de la Top Group la Group la Client). Necesită o ierarhie completă și echilibrată pentru a funcționa corect fără NULL-uri sau linii lipsă.\nOLAP — Online Analytical Processing — procesare orientată spre analiza multidimensională a datelor, tipică pentru data warehouse-uri și cuburi de analiză. Contrapusă OLTP-ului (Online Transaction Processing) din sistemele tranzacționale.\nRagged hierarchy — Ierarhie în care nu toate ramurile ating aceeași adâncime: unele niveluri intermediare lipsesc. Frecventă în datele master de clienți, produse și structuri organizaționale unde nu toate entitățile au aceeași structură ierarhică.\nSelf-parenting — Tehnică de echilibrare a ierarhiilor dezechilibrate: cine nu are un părinte devine propriul părinte. Nivelul lipsă este completat cu datele de la nivelul inferior, eliminând NULL-urile din dimensiune și garantând un drill-down corect.\n","date":"20 ianuarie 2026","permalink":"https://ivanluminaria.com/ro/posts/data-warehouse/ragged-hierarchies/","section":"Database Strategy","summary":"\u003cp\u003eTrei niveluri. Top Group, Group, Client. Pare o structură banală — tipul de ierarhie pe care o desenezi pe o tablă în cinci minute și pe care orice instrument de BI ar trebui să o gestioneze fără probleme.\u003c/p\u003e\n\u003cp\u003eApoi descoperi că nu toți clienții aparțin unui grup. Și că nu toate grupurile aparțin unui top group. Și că rapoartele de agregare pe care business-ul le solicită — cifra de afaceri per top group, număr de clienți per grup, \u003cspan class=\"glossary-tip\" tabindex=\"0\" data-glossary-desc=\"Navigare în rapoarte de la un nivel agregat la un nivel de detaliu, tipică analizei OLAP și data warehouse-urilor.\" data-glossary-url=\"/ro/glossary/drill-down/\" data-glossary-more=\"Citește mai mult →\"\u003edrill-down\u003c/span\u003e\n de la vârf la frunză — produc rezultate greșite sau incomplete pentru că ierarhia are goluri.\u003c/p\u003e","title":"Ierarhii dezechilibrate: când clientul nu are părinte și grupul nu are bunic"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/olap/","section":"Tags","summary":"","title":"Olap"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/reporting/","section":"Tags","summary":"","title":"Reporting"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/authentication/","section":"Tags","summary":"","title":"Authentication"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/communication/","section":"Tags","summary":"","title":"Communication"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/conflict-management/","section":"Tags","summary":"","title":"Conflict-Management"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/team-leadership/","section":"Tags","summary":"","title":"Team-Leadership"},{"content":"Era o joi după-amiază, una dintre acele ședințe care pe hârtie trebuia să dureze o oră. Eram șapte, conectați într-un call. Ordinea de zi era simplă: să decidem strategia de migrare a unei baze de date Oracle din on-premise în cloud.\nSimplă, desigur. Pe hârtie.\nDupă douăzeci de minute, ședința se transformase într-un duel.\n🔥 Scânteia #De o parte era responsabilul de infrastructură. Om cu experiență, douăzeci de ani de datacentere în spate. Poziția lui era de granit: migrare lift-and-shift, zero modificări la arhitectură, mutăm totul așa cum este.\nDe cealaltă parte, lead developer-ul. Tânăr, strălucitor, cu idei clare. Voia să rescrie stratul aplicativ, să adopte servicii cloud-native, să containerizeze totul. Refacem de la zero, oricum codul e vechi.\nDouă poziții legitime. Două perspective reale. Doi oameni inteligenți.\nDar conversația luase o turnură familiară — și periculoasă.\n\u0026ldquo;Nu, n-are sens să mutăm totul în cloud fără să regândim arhitectura.\u0026rdquo;\n\u0026ldquo;Nu, să rescriem totul e un risc enorm și nu avem buget.\u0026rdquo;\nNu. Nu. Nu.\nFiecare frază începea cu \u0026ldquo;nu\u0026rdquo;. Fiecare răspuns era o negare a celui precedent. Brațele încrucișate, tonul ridicându-se, frazele scurtându-se. Cunosc acest tipar. L-am văzut de sute de ori. Și știu cum se termină: nu se termină. Ședința se închide fără o decizie, se reprogramează pentru săptămâna viitoare, și între timp nimeni nu face nimic pentru că \u0026ldquo;încă n-am decis\u0026rdquo;.\nProiectul se blochează. Nu din motive tehnice. Din orgoliu.\n🎭 Trei cuvinte care schimbă totul #În acel moment am făcut ceva foarte simplu. Am așteptat o pauză — pentru că în discuțiile aprinse există întotdeauna un moment în care toți își trag sufletul — și am spus:\n\u0026ldquo;Marco, ai dreptate: să mutăm totul în cloud fără să schimbăm nimic e calea cea mai rapidă spre producție. Și am putea identifica și două-trei componente care, odată cu migrarea, are sens să fie regândite în cheie cloud-native. Luca, tu pe care le-ai alege?\u0026rdquo;\nNimeni n-a spus \u0026ldquo;nu\u0026rdquo;. Nimeni n-a fost contrazis.\nMarco și-a văzut poziția validată — abordarea lui conservatoare era punctul de plecare. Luca a primit un rol concret — să aleagă ce să modernizeze, cu un mandat precis.\nÎn treizeci de secunde, doi oameni care se certau s-au regăsit colaborând pe aceeași tablă.\nȘedința s-a terminat mai devreme. Cu o decizie. Una reală.\n🧠 Ce este tehnica \u0026ldquo;Da-Și\u0026rdquo; #Ceea ce am făcut are un nume. Se numește \u0026ldquo;Yes-And\u0026rdquo; — în română, \u0026ldquo;Da-Și\u0026rdquo;. Vine din teatrul de improvizație, unde există o regulă fundamentală: nu nega niciodată propunerea partenerului tău de scenă.\nDacă cineva spune \u0026ldquo;Suntem pe o barcă în mijlocul oceanului\u0026rdquo;, nu răspunzi \u0026ldquo;Nu, suntem într-un birou\u0026rdquo;. Răspunzi \u0026ldquo;Da, și pare că se apropie o furtună\u0026rdquo;. Construiești. Adaugi. Mergi înainte.\nÎn managementul de proiect funcționează la fel.\nCând cineva propune ceva și răspunzi \u0026ldquo;Nu, dar\u0026hellip;\u0026rdquo;, iată ce se întâmplă la nivel psihologic:\ninterlocutorul se pune pe poziție defensivă nu mai ascultă ce vine după \u0026ldquo;dar\u0026rdquo; se concentrează pe cum să contraargumenteze, nu pe cum să rezolve conversația devine un ping-pong de negații Când răspunzi \u0026ldquo;Da, și\u0026hellip;\u0026rdquo;, se întâmplă contrariul:\ninterlocutorul se simte recunoscut își coboară gardele devine disponibil să asculte adăugarea ta conversația devine constructivă Nu e manipulare. Nu e diplomație goală. E o tehnică precisă pentru a face deciziile să avanseze fără a arde relațiile.\n🛠️ Cum funcționează în practica zilnică #În treizeci de ani de proiecte, am aplicat \u0026ldquo;Da-Și\u0026rdquo; în zeci de situații. Funcționează oriunde există o decizie de luat și mai multe persoane cu opinii diferite.\nÎn ședințele de proiect #În loc de: \u0026ldquo;Nu, timeline-ul de trei luni e nerealist.\u0026rdquo;\nÎncearcă cu: \u0026ldquo;Da, trei luni e obiectivul. Și ca să ajungem acolo, ar trebui să reducem scope-ul primului release la aceste trei funcționalități — restul le punem în faza doi.\u0026rdquo;\nObservi diferența? În prima versiune ai un zid. În a doua ai un plan.\nÎn code reviews #În loc de: \u0026ldquo;Nu, abordarea asta e greșită, ai scris prea complicat.\u0026rdquo;\nÎncearcă cu: \u0026ldquo;Da, funcționează. Și am putea simplifica extrăgând această logică într-o metodă separată — devine mai testabilă.\u0026rdquo;\nDeveloper-ul nu se simte atacat. Se simte ajutat. Și data viitoare vine la tine să ceară o părere înainte de a scrie codul, nu după.\nÎn negocierile cu stakeholderii #În loc de: \u0026ldquo;Nu, nu putem adăuga acea feature acum, suntem deja în întârziere.\u0026rdquo;\nÎncearcă cu: \u0026ldquo;Da, acea feature are sens. Și ca s-o includem fără să compromitem data de lansare, ar trebui s-o înlocuim cu aceasta care e mai puțin prioritară. Pe care dintre cele două o preferați?\u0026rdquo;\nStakeholderul nu aude un \u0026ldquo;nu\u0026rdquo;. Aude un \u0026ldquo;da, și acum decidem împreună cum s-o facem\u0026rdquo;.\n⚠️ Când \u0026ldquo;Da-Și\u0026rdquo; nu funcționează #Ar fi frumos să spun că funcționează mereu. Nu e așa. Sunt situații în care \u0026ldquo;Da-Și\u0026rdquo; e instrumentul greșit.\nProbleme de securitate. Dacă cineva propune să scoată autentificarea de pe baza de date de producție pentru că \u0026ldquo;încetinește query-urile\u0026rdquo;, răspunsul nu e \u0026ldquo;Da, și\u0026hellip;\u0026rdquo;. Răspunsul e \u0026ldquo;Nu. Punct.\u0026rdquo;\nÎncălcări de proces. Dacă un developer vrea să facă deploy în producție vineri seara fără teste, nu există \u0026ldquo;Da-Și\u0026rdquo; care să țină. Există un proces, și trebuie respectat.\nDeadline-uri non-negociabile. Când go-live-ul e luni și suntem joi, nu e momentul să construim pe ideile tuturor. E momentul să decidem, să executăm și să închidem.\nComportamente toxice. \u0026ldquo;Da-Și\u0026rdquo; funcționează cu oameni de bună-credință care au opinii diferite. Nu funcționează cu cei care vor doar să aibă dreptate, cu cei care sabotează, cu cei care nu ascultă din principiu. În acele cazuri e nevoie de alt tip de conversație — privată, directă și foarte sinceră.\nTehnica nu e o formulă magică. E un instrument. Și ca toate instrumentele, trebuie să știi când să-l folosești și când să-l lași deoparte.\n📊 Costul ascuns al lui \u0026ldquo;Nu, dar\u0026hellip;\u0026rdquo; #Am încercat să fac un calcul aproximativ pe un proiect pe care l-am gestionat acum doi ani. O echipă de opt persoane, ședințe de trei ori pe săptămână.\nSituație Durata medie a ședinței Decizii luate Înainte (cultura \u0026ldquo;Nu, dar\u0026hellip;\u0026rdquo;) 1h 20min 0.5 pe ședință După (cultura \u0026ldquo;Da, și\u0026hellip;\u0026rdquo;) 45min 1.8 pe ședință Echipa lua decizii de trei ori mai repede, iar ședințele durau aproape jumătate.\nNu am date științifice. Sunt date empirice, colectate pe un proiect specific. Dar tiparul e consistent cu ce am văzut în douăzeci de ani: echipele care discută constructiv merg mai repede decât cele care se ceartă. Nu pentru că evită conflictul — pentru că-l traversează mai bine.\n🎯 Ce am învățat #\u0026ldquo;Da-Și\u0026rdquo; nu e diplomație. Nu e evitarea confruntării. Nu e să spui da la orice.\nE să recunoști că majoritatea discuțiilor din proiectele IT nu sunt despre cine are dreptate. Sunt despre cum facem lucrurile să avanseze. Și lucrurile avansează când oamenii se simt ascultați, nu când sunt învinși.\nAm văzut proiecte blocându-se săptămâni la rând pentru că două persoane strălucite nu reușeau să înceteze a-și spune \u0026ldquo;nu\u0026rdquo; reciproc. Și am văzut aceleași proiecte deblocându-se în cincisprezece minute când cineva a avut bunul simț să spună \u0026ldquo;da, și\u0026hellip;\u0026rdquo;.\nNu e nevoie de un curs de comunicare. Nu e nevoie de un coach. E nevoie să încerci, data viitoare când cineva spune ceva cu care nu ești de acord, să răspunzi \u0026ldquo;Da, și\u0026hellip;\u0026rdquo; în loc de \u0026ldquo;Nu, dar\u0026hellip;\u0026rdquo;.\nUn exercițiu simplu. Care schimbă modul în care se iau deciziile.\nCare schimbă modul în care oamenii lucrează împreună.\nȘi care, uneori, salvează o ședință care era pe punctul de a exploda.\n💬 Pentru cine a pățit-o cel puțin o dată #Dacă ai fost vreodată într-o ședință unde doi oameni vorbeau peste ei și nimeni nu asculta pe nimeni. Dacă ai văzut vreodată un proiect blocându-se nu din cauza unei probleme tehnice, ci din cauza unei probleme de comunicare. Dacă te-ai gândit vreodată \u0026ldquo;de ce nu putem pur și simplu să decidem?\u0026rdquo;\nÎncearcă \u0026ldquo;Da-Și\u0026rdquo;. La următoarea ședință. O singură dată.\nNu costă nimic. Nu are nevoie de aprobare. Nu necesită buget.\nAre nevoie doar de capacitatea de a te abține o secundă înainte de a spune \u0026ldquo;nu\u0026rdquo; — și de a-l înlocui cu \u0026ldquo;da, și\u0026hellip;\u0026rdquo;.\nRezultatul te-ar putea surprinde.\nGlosar #Yes-And — Tehnică de comunicare născută în teatrul de improvizație care înlocuiește \u0026ldquo;Nu, dar\u0026hellip;\u0026rdquo; cu \u0026ldquo;Da, și\u0026hellip;\u0026rdquo;, transformând discuțiile în construcție colaborativă.\nStakeholder — Persoană sau grup cu un interes direct în rezultatul unui proiect: client, utilizator final, sponsor, echipă tehnică sau orice parte afectată de deciziile proiectului.\nScope — Perimetrul unui proiect care definește ce este inclus și ce este exclus: funcționalități, livrabile, constrângeri și limite convenite cu stakeholderii.\nLift-and-Shift — Strategie de migrare care mută un sistem dintr-un mediu în altul fără a-i modifica arhitectura, codul sau configurația.\nTimeboxing — Tehnică de gestionare a timpului care atribuie un interval fix și nenegociabil unei activități, forțând încheierea în limita stabilită.\nRezultatul te-ar putea surprinde.\n","date":"13 ianuarie 2026","permalink":"https://ivanluminaria.com/ro/posts/project-management/tecnica-si-e-yes-and/","section":"Database Strategy","summary":"\u003cp\u003eEra o joi după-amiază, una dintre acele ședințe care pe hârtie trebuia să dureze o oră. Eram șapte, conectați într-un call. Ordinea de zi era simplă: să decidem strategia de migrare a unei baze de date Oracle din on-premise în cloud.\u003c/p\u003e\n\u003cp\u003eSimplă, desigur. Pe hârtie.\u003c/p\u003e\n\u003cp\u003eDupă douăzeci de minute, ședința se transformase într-un duel.\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"-scânteia\" class=\"relative group\"\u003e🔥 Scânteia \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#-sc%c3%a2nteia\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eDe o parte era responsabilul de infrastructură. Om cu experiență, douăzeci de ani de datacentere în spate. Poziția lui era de granit: \u003cstrong\u003emigrare lift-and-shift, zero modificări la arhitectură, mutăm totul așa cum este\u003c/strong\u003e.\u003c/p\u003e","title":"Tehnica Da-Și: cum am evitat o discuție care era pe punctul de a exploda"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/users/","section":"Tags","summary":"","title":"Users"},{"content":"Acum câteva săptămâni un client mă sună. Ton pragmatic, cerere aparent banală:\n„Trebuie să creez un utilizator pe MySQL pentru o aplicație care trebuie să acceseze o bază de date. Te poți ocupa?\u0026quot;\nSigur. CREATE USER, `GRANT` , următorul.\nDoar că apoi adaugă: „Aplicația rulează pe două servere diferite. Și uneori ne vom conecta și local pentru mentenanță.\u0026quot;\nAici lucrurile nu mai sunt banale. Pentru că în MySQL, a crea „un utilizator\u0026quot; nu înseamnă ceea ce crezi.\nModelul de autentificare MySQL: utilizator + host #Primul lucru de înțeles — și pe care mulți DBA cu experiență în Oracle sau PostgreSQL îl descoperă pe propria piele — este că în MySQL identitatea unui utilizator nu este doar numele său.\nEste perechea 'utilizator'@'host'.\nAsta înseamnă că:\n\u0026#39;mario\u0026#39;@\u0026#39;localhost\u0026#39; \u0026#39;mario\u0026#39;@\u0026#39;192.168.1.10\u0026#39; \u0026#39;mario\u0026#39;@\u0026#39;%\u0026#39; nu sunt același utilizator. Sunt trei utilizatori diferiți. Cu parole diferite, privilegii diferite, comportamente diferite.\nCând MySQL primește o conexiune, se uită la două lucruri:\nNumele de utilizator furnizat Adresa IP (sau hostname-ul) de la care vine conexiunea Apoi caută în tabelul mysql.user rândul care corespunde perechii celei mai specifice. Nu primul găsit. Cel mai specific.\nDe ce acest model? #Alegerea de design nu este întâmplătoare. MySQL s-a născut în 1995 pentru web. Medii în care aceeași bază de date servește aplicații care rulează pe mașini diferite, rețele diferite, cu nevoi de acces diferite.\nModelul utilizator@host permite:\nacordarea accesului complet de pe localhost (pentru DBA) acordarea accesului limitat de pe un application server specific blocarea a orice altceva Fără firewall. Fără VPN. Direct în motorul de autentificare.\nEste un model puternic. Dar dacă nu îl înțelegi, te mușcă.\nCazul clientului: cum l-am rezolvat #Să revenim la cerere. Aplicația rulează pe două servere (192.168.1.20 și 192.168.1.21) și mai este nevoie și de acces local pentru mentenanță.\nTentația este să creezi un singur utilizator cu '%' (wildcard = orice host):\nCREATE USER \u0026#39;app_vanzari\u0026#39;@\u0026#39;%\u0026#39; IDENTIFIED BY \u0026#39;ParolaSigura#2026\u0026#39;; GRANT SELECT, INSERT, UPDATE ON vanzari_db.* TO \u0026#39;app_vanzari\u0026#39;@\u0026#39;%\u0026#39;; Funcționează? Da. Este corect? Nu.\nProblema cu '%' este că acceptă conexiuni de la orice IP. Dacă mâine cineva găsește parola, se poate conecta din orice punct al rețelei. Sau al lumii, dacă baza de date este expusă.\nSoluția corectă este să creezi utilizatori specifici pentru fiecare sursă:\n-- Acces de pe application server-ul primar CREATE USER \u0026#39;app_vanzari\u0026#39;@\u0026#39;192.168.1.20\u0026#39; IDENTIFIED BY \u0026#39;ParolaSigura#2026\u0026#39;; GRANT SELECT, INSERT, UPDATE ON vanzari_db.* TO \u0026#39;app_vanzari\u0026#39;@\u0026#39;192.168.1.20\u0026#39;; -- Acces de pe application server-ul secundar CREATE USER \u0026#39;app_vanzari\u0026#39;@\u0026#39;192.168.1.21\u0026#39; IDENTIFIED BY \u0026#39;ParolaSigura#2026\u0026#39;; GRANT SELECT, INSERT, UPDATE ON vanzari_db.* TO \u0026#39;app_vanzari\u0026#39;@\u0026#39;192.168.1.21\u0026#39;; -- Acces local pentru mentenanță (privilegii diferite) CREATE USER \u0026#39;app_vanzari\u0026#39;@\u0026#39;localhost\u0026#39; IDENTIFIED BY \u0026#39;ParolaMent#2026\u0026#39;; GRANT SELECT ON vanzari_db.* TO \u0026#39;app_vanzari\u0026#39;@\u0026#39;localhost\u0026#39;; Trei utilizatori. Același nume. Privilegii calibrate.\nUtilizatorul local are doar SELECT pentru că servește la verificări, nu la scrierea datelor. Parolă diferită pentru că contextul de utilizare este diferit.\nPrincipiul privilegiului minim . Aplicat în punctul potrivit.\nCapcana matching-ului: cine câștigă? #Aici se nasc majoritatea erorilor.\nDacă există atât 'mario'@'%' cât și 'mario'@'localhost', și Mario se conectează de pe localhost, care utilizator se folosește?\nRăspuns: 'mario'@'localhost'.\nMySQL sortează rândurile din tabelul mysql.user de la cel mai specific la cel mai puțin specific:\nHost literal exact (192.168.1.20) Pattern cu wildcard (192.168.1.%) Wildcard total (%) Și folosește prima potrivire în ordinea specificității.\nProblema clasică este aceasta: creezi 'mario'@'%' cu toate privilegiile. Apoi cineva creează 'mario'@'localhost' fără privilegii (sau cu o parolă diferită). Din acel moment, Mario nu mai poate intra de pe local și nimeni nu înțelege de ce.\nAm văzut acest scenariu de cel puțin o duzină de ori în producție. Soluția este mereu aceeași: verifică ce există înainte de a crea.\nSELECT user, host, authentication_string FROM mysql.user WHERE user = \u0026#39;mario\u0026#39;; Dacă nu o faci înainte, o vei face după. Cu mai multă urgență și mai puțin calm.\nMySQL vs MariaDB: diferențele care contează #Modelul utilizator@host este identic între MySQL și MariaDB. Dar există diferențe de implementare care merită cunoscute.\nAutentificarea implicită:\nVersiune Plugin implicit MySQL 5.7 mysql_native_password MySQL 8.0+ caching_sha2_password MariaDB 10.x mysql_native_password Dacă migrezi de la MariaDB la MySQL 8 (sau invers), clienții ar putea să nu se conecteze pentru că plugin-ul de autentificare este diferit. Nu e un bug. E o schimbare de configurație implicită.\nCrearea utilizatorilor:\nÎn MySQL 8, GRANT nu mai creează utilizatori implicit. Trebuie să faci CREATE USER mai întâi și GRANT după. Întotdeauna.\n-- MySQL 8: corect CREATE USER \u0026#39;app\u0026#39;@\u0026#39;10.0.0.5\u0026#39; IDENTIFIED BY \u0026#39;pwd123\u0026#39;; GRANT SELECT ON mydb.* TO \u0026#39;app\u0026#39;@\u0026#39;10.0.0.5\u0026#39;; -- MySQL 5.7 / MariaDB: încă funcționează (dar este depreciat) GRANT SELECT ON mydb.* TO \u0026#39;app\u0026#39;@\u0026#39;10.0.0.5\u0026#39; IDENTIFIED BY \u0026#39;pwd123\u0026#39;; Dacă scrii scripturi de provisioning, acest detaliu poate strica o pipeline CI/CD întreagă.\nRoluri:\nMySQL 8.0 a introdus rolurile. MariaDB le suportă din versiunea 10.0.5, dar cu sintaxă ușor diferită.\n-- MySQL 8.0 CREATE ROLE \u0026#39;role_citire\u0026#39;; GRANT SELECT ON vanzari_db.* TO \u0026#39;role_citire\u0026#39;; GRANT \u0026#39;role_citire\u0026#39; TO \u0026#39;app_vanzari\u0026#39;@\u0026#39;192.168.1.20\u0026#39;; SET DEFAULT ROLE \u0026#39;role_citire\u0026#39; FOR \u0026#39;app_vanzari\u0026#39;@\u0026#39;192.168.1.20\u0026#39;; -- MariaDB 10.x CREATE ROLE role_citire; GRANT SELECT ON vanzari_db.* TO role_citire; GRANT role_citire TO \u0026#39;app_vanzari\u0026#39;@\u0026#39;192.168.1.20\u0026#39;; SET DEFAULT ROLE role_citire FOR \u0026#39;app_vanzari\u0026#39;@\u0026#39;192.168.1.20\u0026#39;; Diferența pare cosmetică (ghilimele sau nu), dar în scripturi automatizate poate genera erori de sintaxă.\nUtilizatorul anonim: fantoma pe care nimeni n-a invitat-o #MySQL vine instalat cu un utilizator anonim : ''@'localhost'. Fără nume, fără parolă.\nAcest utilizator este un artefact istoric al instalărilor de dezvoltare. În producție este un risc de securitate pur.\nUtilizatorul anonim câștigă asupra 'mario'@'%' când conexiunea vine de pe localhost, pentru că 'localhost' este mai specific decât '%'.\nRezultat: Mario se conectează local, MySQL îl autentifică ca utilizator anonim, iar privilegiile lui Mario dispar.\nPrimul lucru de făcut pe orice instalare MySQL/MariaDB în producție:\nSELECT user, host FROM mysql.user WHERE user = \u0026#39;\u0026#39;; -- Dacă se găsește: DROP USER \u0026#39;\u0026#39;@\u0026#39;localhost\u0026#39;; DROP USER \u0026#39;\u0026#39;@\u0026#39;%\u0026#39;; -- dacă există FLUSH PRIVILEGES ; Nu este paranoia. Este igienă.\nChecklist operațional #După experiența cu clientul, am formalizat un checklist pe care îl folosesc de fiecare dată când trebuie să creez utilizatori pe MySQL sau MariaDB:\nVerifică utilizatorii existenți cu același nume pe host-uri diferite Elimină utilizatorii anonimi dacă sunt prezenți Creează utilizatori cu host-uri specifice, niciodată cu '%' în producție dacă nu este strict necesar Acordă doar privilegiile necesare — SELECT dacă e suficient SELECT Folosește CREATE USER + GRANT separate (obligatoriu pe MySQL 8) Verifică plugin-ul de autentificare dacă clienții au probleme de conexiune Documentează perechile utilizator/host — peste șase luni nimeni nu-și va aminti de ce există trei „app_vanzari\u0026quot; Concluzie #În MySQL și MariaDB un utilizator nu este un nume. Este un nume legat de un punct de origine.\nAcest model este puternic pentru că permite segmentarea accesului fără infrastructură suplimentară. Dar este și o sursă de erori subtile dacă nu îl înțelegi în profunzime.\nData viitoare când cineva îți cere „creează un utilizator pe MySQL\u0026quot;, înainte de a scrie primul CREATE USER, întreabă-te: de unde se va conecta?\nRăspunsul la această întrebare schimbă totul.\nGlosar #GRANT — Comandă SQL pentru atribuirea de privilegii unui utilizator sau rol. În MySQL 8 nu mai creează utilizatori implicit: mai întâi CREATE USER, apoi GRANT.\nLeast Privilege — Principiu de securitate care prevede atribuirea doar a permisiunilor strict necesare. În MySQL se aplică calibrând privilegiile per pereche utilizator/host.\nAuthentication Plugin — Modul care gestionează verificarea credențialelor. Default-ul se schimbă între MySQL 5.7 (mysql_native_password), MySQL 8 (caching_sha2_password) și MariaDB.\nAnonymous User — Utilizator MySQL fără nume (''@'localhost') creat automat în timpul instalării. Poate interfera cu matching-ul utilizatorilor legitimi și trebuie eliminat în producție.\nFLUSH PRIVILEGES — Comandă care reîncarcă tabelele de grant în memorie, făcând efective modificările manuale ale privilegiilor. Necesară după operații directe pe tabelul mysql.user.\n","date":"13 ianuarie 2026","permalink":"https://ivanluminaria.com/ro/posts/mysql/mysql-users-and-hosts/","section":"Database Strategy","summary":"\u003cp\u003eAcum câteva săptămâni un client mă sună. Ton pragmatic, cerere aparent banală:\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003e„Trebuie să creez un utilizator pe MySQL pentru o aplicație care trebuie să acceseze o bază de date. Te poți ocupa?\u0026quot;\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eSigur. \u003ccode\u003eCREATE USER\u003c/code\u003e, \u003cspan class=\"glossary-tip\" tabindex=\"0\" data-glossary-desc=\"Comandă SQL pentru atribuirea de privilegii specifice unui utilizator sau rol pe baze de date, tabele sau coloane. În MySQL 8 nu mai creează utilizatori implicit.\" data-glossary-url=\"/ro/glossary/grant/\" data-glossary-more=\"Citește mai mult →\"\u003e`GRANT`\u003c/span\u003e\n, următorul.\u003c/p\u003e\n\u003cp\u003eDoar că apoi adaugă: „Aplicația rulează pe două servere diferite. Și uneori ne vom conecta și local pentru mentenanță.\u0026quot;\u003c/p\u003e","title":"Utilizatori MySQL: de ce 'mario' și 'mario'@'localhost' nu sunt aceeași persoană"},{"content":"Cu câteva săptămâni în urmă, un client m-a contactat cu o problemă foarte comună:\n\u0026ldquo;Căutarea din consola administrativă este lentă. Uneori durează câteva secunde. Am redus deja JOIN-urile, dar problema nu a dispărut.\u0026rdquo;\nMediu: PostgreSQL în cloud managed.\nTabela principală: payment_report (~6 milioane de rânduri, 3 GB).\nColoana căutată: reference_code.\nQuery problematic:\nSELECT * FROM reporting.payment_report r JOIN reporting.payment_cart c ON c.id = r.cart_id WHERE c.service_id = 1001 AND r.reference_code LIKE \u0026#39;%ABC123%\u0026#39; ORDER BY c.created_at DESC LIMIT 100; 🧠 Prima observație: JOIN-urile nu erau problema #Am comparat:\nVersiunea AS-IS (3 JOIN-uri pe aceeași tabelă) Versiunea TO-BE (un singur JOIN) Rezultatul?\nPlanul de execuție arăta în ambele cazuri:\nParallel Seq Scan on payment_report Rows Removed by Filter: ~2,000,000 Buffers: shared read = sute de mii Execution Time: 14–18 seconds Reducerea JOIN-urilor a avut un impact marginal.\nProblema reală era alta.\n📌 Vinovatul: LIKE '%valoare%' fără un index adecvat #O căutare cu wildcard inițial (%valoare%) face inutilizabil un index B-Tree obișnuit.\nPostgreSQL este forțat să execute un scan secvențial al întregii tabele.\nÎn acest caz specific:\n~3 GB de date sute de mii de pagini de 8KB citite workload dominat de I/O secunde de latență Nu este o problemă de \u0026ldquo;SQL scris prost\u0026rdquo;. Este o problemă de access path.\n🔬 Înainte de a crea un index: analiza riscului #Clientul a întrebat pe bună dreptate:\n\u0026ldquo;Dacă creăm un index trigram (GIN), riscăm să încetinim tranzacțiile de plată?\u0026rdquo;\nAici intervine un concept adesea ignorat: **churn** .\nCe este churn-ul? #Reprezintă cât de mult se modifică o tabelă după inserarea rândurilor.\nFrecvență mare de: - UPDATE - DELETE\n→ churn ridicat\n→ cost mai mare de mentenanță al indexului\n→ posibilă degradare a scrierilor\nÎn cazul nostru:\nTabela payment_report: - ~12k inserări/zi - 0 update-uri - 0 delete-uri - 0 dead tuples\nProfil: append-only\nAcesta este cel mai bun scenariu posibil pentru introducerea unui index GIN.\n📊 Verificare esențială: sincron sau batch? #Tabela nu conținea timestamp de inserare.\nSoluție: analiză indirectă.\nAm corelat rândurile din payment_report cu timestamp-ul coșului (payment_cart.created_at) și am analizat distribuția orară.\nRezultat:\nmodel continuu 24/7 vârfuri în timpul zilei scădere noaptea corelație perfectă cu traficul coșurilor Concluzie: populare near real-time, nu batch nocturn.\n🛠️ Soluția #CREATE EXTENSION IF NOT EXISTS pg_trgm ; CREATE INDEX CONCURRENTLY idx_payment_report_reference_trgm ON reporting.payment_report USING gin (reference_code gin_trgm_ops); Precauții:\nCreare într-o fereastră off-peak Utilizarea modului CONCURRENTLY Monitorizarea I/O în timpul build-ului 📈 Rezultatul: planul de execuție înainte și după #Iată planul de execuție complet al interogării — înainte și după crearea indexului trigram.\nÎnainte (fără index trigram):\nNested Loop Inner Join → Nested Loop Inner Join → Nested Loop Inner Join → Seq Scan on payment_report as r Filter: ((reference_code)::text ~~ \u0026#39;%ABC123%\u0026#39;::text) → Index Scan using payment_cart_pkey on payment_cart as c Filter: (service_id = 1001) Index Cond: (id = r.cart_id) → Index Only Scan using payment_cart_pkey on payment_cart as c2 Index Cond: (id = c.id) → Index Only Scan using payment_cart_pkey on payment_cart as c3 Index Cond: (id = c.id) După (cu index trigram):\nNested Loop Inner Join → Nested Loop Inner Join → Nested Loop Inner Join → Bitmap Heap Scan on payment_report as r Recheck Cond: ((reference_code)::text ~~ \u0026#39;%ABC123%\u0026#39;::text) → Bitmap Index Scan using idx_payment_report_reference_trgm Index Cond: ((reference_code)::text ~~ \u0026#39;%ABC123%\u0026#39;::text) → Index Scan using payment_cart_pkey on payment_cart as c Filter: (service_id = 1001) Index Cond: (id = r.cart_id) → Index Only Scan using payment_cart_pkey on payment_cart as c2 Index Cond: (id = c.id) → Index Only Scan using payment_cart_pkey on payment_cart as c3 Index Cond: (id = c.id) Punctul cheie este la pașii 4–5: Seq Scan — care citea întreaga tabelă rând cu rând — a fost înlocuit cu un Bitmap Heap Scan condus de indexul trigram idx_payment_report_reference_trgm. PostgreSQL filtrează acum direct prin index și face recheck doar pe rândurile candidate.\nAceeași interogare, aceleași date, dar un access path complet diferit. De la secunde la milisecunde.\n🎯 Lecția cheie #Când o query este lentă:\nNu te opri la numărul de JOIN-uri. Analizează planul de execuție. Identifică dacă blocajul este CPU sau I/O. Evaluează churn-ul înainte de a introduce un index GIN. Măsoară întotdeauna înainte de a decide. De multe ori problema nu este „optimizarea query-ului\u0026quot;.\nEste oferirea indexului corect planner-ului.\n💬 De ce împărtășesc acest caz? #Pentru că este un scenariu extrem de comun:\nTabele mari Căutări de tip „conține\u0026quot; Teama de a introduce indexuri GIN Frica de degradarea performanței la scriere Cu date concrete, decizia devine tehnică, nu emoțională.\nOptimizarea nu este magie.\nEste măsurare, analiză de planuri și înțelegerea comportamentului real al sistemului.\nGlosar #GIN Index — Generalized Inverted Index: tip de index PostgreSQL care creează un mapping inversat de la fiecare element la înregistrările care îl conțin. Ideal pentru căutări \u0026ldquo;conține\u0026rdquo; pe text cu pg_trgm.\nB-Tree — Structură de date de arbore echilibrat, indexul implicit în bazele de date relaționale. Eficient pentru căutări de egalitate și interval, dar inutilizabil pentru LIKE '%valoare%'.\npg_trgm — Extensie PostgreSQL care descompune textul în trigrame (secvențe de 3 caractere), activând indexuri GIN pentru accelerarea căutărilor cu wildcard.\nChurn — Măsură a cât de mult se modifică o tabelă după inserare. Churn scăzut (append-only) este cel mai bun scenariu pentru introducerea unui index GIN fără degradarea scrierilor.\nExecution Plan — Secvență de operațiuni aleasă de baza de date pentru rezolvarea unei interogări. Citirea planului este primul pas pentru a identifica dacă problema este CPU, I/O sau un access path greșit.\n","date":"6 ianuarie 2026","permalink":"https://ivanluminaria.com/ro/posts/postgresql/like-optimization-postgresql/","section":"Database Strategy","summary":"\u003cp\u003eCu câteva săptămâni în urmă, un client m-a contactat cu o problemă\nfoarte comună:\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003e\u0026ldquo;Căutarea din consola administrativă este lentă. Uneori durează câteva\nsecunde. Am redus deja JOIN-urile, dar problema nu a dispărut.\u0026rdquo;\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eMediu: PostgreSQL în cloud managed.\u003cbr\u003e\nTabela principală: \u003ccode\u003epayment_report\u003c/code\u003e (~6 milioane de rânduri, 3 GB).\u003cbr\u003e\nColoana căutată: \u003ccode\u003ereference_code\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003eQuery problematic:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-sql\" data-lang=\"sql\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003eSELECT\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e*\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003eFROM\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ereporting\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003epayment_report\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003er\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003eJOIN\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ereporting\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003epayment_cart\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003ec\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eON\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003ec\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003eid\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003er\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003ecart_id\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003eWHERE\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003ec\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003eservice_id\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e1001\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"k\"\u003eAND\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003er\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003ereference_code\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eLIKE\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s1\"\u003e\u0026#39;%ABC123%\u0026#39;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003eORDER\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eBY\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003ec\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003ecreated_at\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eDESC\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003eLIMIT\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e100\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003chr\u003e\n\u003ch2 id=\"-prima-observație-join-urile-nu-erau-problema\" class=\"relative group\"\u003e🧠 Prima observație: JOIN-urile nu erau problema \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#-prima-observa%c8%9bie-join-urile-nu-erau-problema\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eAm comparat:\u003c/p\u003e","title":"Când un LIKE '%valoare%' încetinește totul: un caz real de optimizare PostgreSQL"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/indexes/","section":"Tags","summary":"","title":"Indexes"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/pg_trgm/","section":"Tags","summary":"","title":"Pg_trgm"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/query-tuning/","section":"Tags","summary":"","title":"Query-Tuning"},{"content":"Povestea pe care urmează să o spun este reală. Nu voi da nume — nu din diplomație, ci pentru că numele nu contează. Ceea ce contează este să înțelegem mecanismul. Pentru că acest mecanism se repetă, identic, în zeci de companii. Și costă milioane.\n🏢 Clientul: un grup de asigurări cu o ambiție legitimă #O companie solidă din sectorul asigurărilor. Operațiuni în Italia, Franța, țări din Europa de Nord, Spania. Mii de angajați, milioane de polițe gestionate, o afacere în creștere.\nLa un moment dat, conducerea ia o decizie rezonabilă: avem nevoie de un software de gestiune personalizat. Un sistem care să reflecte procesele noastre, regulile noastre de business, specificul normativ al fiecărei țări în care operăm.\nDecizie legitimă. Sensibilă. Chiar strategică.\nProblema nu este decizia.\nProblema este cui i-o încredințează.\n💰 Actul întâi: marea multinațională (2013–2018) #Este angajată — în plin outsourcing — una dintre marile nume ale consultanței IT mondiale. Un nume pe care toată lumea îl cunoaște. Mii de consultanți, birouri pe fiecare continent, prezentări PowerPoint care te-ar face să plângi de emoție.\nProiectul pornește. Se definesc cerințele. Se estimează bugetul. Se semnează contractele.\nTrec lunile. Apoi anii.\nLivrabilele sosesc — pe hârtie. Dar software-ul nu funcționează cum ar trebui. Specificațiile se schimbă. Costurile explodează. Consultanții se rotesc: cel care înțelesese domeniul pleacă, vine altul care o ia de la zero. Schema clasică a consultanței la pachet care devine, în practică, o consultanță pe termen nedeterminat.\nDin 2013 până în 2018: peste 2,5 milioane de euro cheltuiți.\nRezultatul: un software incomplet, instabil, pe care nimeni din interior nu știa să-l întrețină.\nPentru că codul îl scriseseră ei. Cu convențiile lor. Cu arhitectura lor. Și când au plecat, au luat cu ei și cunoștințele.\n🔄 Actul al doilea: schimbăm furnizorul (2018–2022) #Managementul, ars dar neresemnat, decide să schimbe. \u0026ldquo;Problema a fost furnizorul\u0026rdquo;, gândesc ei. \u0026ldquo;Să luăm unul mai bun.\u0026rdquo;\nIntră în scenă o altă multinațională. La fel de faimoasă. La fel de mare. La fel de scumpă.\nNou kickoff. Nouă analiză a cerințelor — pentru că, evident, nu pot porni de la munca furnizorului anterior. Slide-uri noi. Promisiuni noi.\nȘi istoria se repetă.\nAceleași probleme, actori diferiți. Rotația consultanților. Pierderea know-how-ului. Termene care se lungesc. Bugete care explodează. Ședințe interminabile în care se discută milestone-uri care nu mai sosesc.\nDin 2018 până în 2022: încă 1,5 milioane de euro.\nRezultatul: un alt software care nu satisface nevoile afacerii.\nTotal investit în aproape un deceniu: peste 4 milioane de euro.\nSoftware funcțional: zero.\n📊 Să facem bilanțul dezastrului # Perioadă Furnizor Investiție Rezultat 2013 – 2018 Multinațională A ~2.500.000 € Software incomplet, abandonat 2018 – 2022 Multinațională B ~1.500.000 € Software inadecvat, abandonat Total ~4.000.000+ € Niciun software în producție Patru milioane de euro. Aproape zece ani de proiect. Două dintre cele mai prestigioase nume ale consultanței IT globale.\nȘi la final, compania se regăsește exact la punctul de plecare.\nNu e ghinion. E un pattern.\nIar cine lucrează în acest sector de treizeci de ani, ca mine, îl recunoaște din prima.\n🧠 De ce se întâmplă: anatomia eșecului #Acest tip de eșec nu este un accident. Este rezultatul previzibil al unui model de business cu un defect structural.\n1. Incentivul este greșit.\nO mare firmă de consultanță câștigă bani vânzând zile-om. Cu cât proiectul durează mai mult, cu atât facturează mai mult. Nu există niciun stimulent real pentru a încheia proiectul rapid și bine. Există un stimulent pentru a-l menține în viață cât mai mult posibil.\n2. Rotația este endemică.\nMultinaționalele de consultanță au rate de rotație de 15-25% pe an. Într-un proiect care durează cinci ani, echipa se reînnoiește complet de cel puțin două ori. De fiecare dată se o ia de la capăt: nouă curbă de învățare, nouă interpretare a cerințelor, noi greșeli.\n3. Know-how-ul iese pe ușă (vendor lock-in ).\nCând furnizorul termină (sau este concediat), cunoașterea sistemului pleacă odată cu el. Clientul rămâne cu un software pe care nu-l înțelege, nu știe să-l întrețină și nu-l poate evolua.\n4. Specificațiile devin o armă (scope creep ).\nÎntr-un proiect custom de această amploare, specificațiile sunt întotdeauna incomplete — pentru că afacerea este complexă și în evoluție. Aceasta devine alibiul perfect: \u0026ldquo;software-ul nu funcționează pentru că specificațiile s-au schimbat\u0026rdquo;. Și e mereu vina altcuiva.\n✅ Punctul de cotitură: cumpără, nu construi #La final, după aproape un deceniu și peste 4 milioane arse, compania ia decizia pe care ar fi trebuit să o ia de la început:\nSă cumpere un software de piață deja funcțional și să-l adapteze intern la propriile nevoi.\nUn produs asigurător comercial, testat, cu o bază de cod stabilă și o comunitate de suport. Și o echipă internă — oameni care cunosc afacerea, care rămân în companie, care acumulează cunoștințe în loc să le disperseze — însărcinată să-l personalizeze și să-l evolueze.\nCostul? O fracțiune din ce s-a cheltuit în cei zece ani anteriori.\nRezultatul? Un sistem care funcționează. Care evoluează. Pe care compania îl deține cu adevărat.\nLecția este brutală în simplitatea ei:\nNu totul trebuie construit de la zero. Și mai ales, nu totul trebuie delegat celor care nu au interes să termine.\n🏗️ Comparația care doare: Data Warehouse-ul nostru #Și aici intră partea poveștii pe care o cunosc din interior. Pentru că pentru aceeași companie, în aceeași perioadă, eu și un coleg am construit ceva ce funcționează. În fiecare zi.\nUn **Data Warehouse** complet. Proiectat, dezvoltat, pus în producție și întreținut de două persoane.\nNu o demo. Nu un prototip. Un sistem de producție care:\nÎncarcă date în fiecare zi — întregul ciclu ETL rulează în o oră și jumătate Integrează 4 sisteme sursă diferite — fiecare cu formatul său, protocolul său, particularitățile sale Colectează date din 4 zone geografice: Italia, Franța, țări din Europa de Nord, Spania Cuprinde aproximativ 60.000 de linii de cod scrise în patru mâini Arhitectura a fost proiectată de mine — de la modelul de date la strategia de încărcare, de la gestionarea erorilor la istoricizare Software de gestiune custom Data Warehouse Echipă Două multinaționale (zeci de consultanți) 2 persoane Durata proiectului ~10 ani (și continuând) 3 ani Buget 4.000.000+ € O fracțiune Linii de cod Necunoscute (și abandonate) ~60.000 (documentate, întreținute) Rezultat Niciun software în producție Sistem în producție zilnică Timp de procesare — 1h 30min / zi Acoperire geografică — 4 țări, 4 sisteme sursă Know-how Pierdut la fiecare schimbare de furnizor Intern, stabil, documentat Două persoane. Trei ani. Un sistem care în fiecare dimineață se trezește, colectează date din patru colțuri ale Europei, le transformă, le încarcă și le pune la dispoziție pentru deciziile de afaceri. Într-o oră și jumătate.\nȘaizeci de mii de linii de cod. Fiecare gândită, testată, întreținută de cine a scris-o.\nNiciun PowerPoint. Niciun kickoff. Niciun consultant care pleacă luând cunoștințele cu el.\nDoar competență, arhitectură solidă și muncă făcută bine.\n🎯 Lecția #Când vorbesc cu companii care sunt pe punctul de a începe un mare proiect IT, le spun întotdeauna același lucru:\nNu plătiți pentru un brand. Plătiți pentru oameni.\nO echipă mică de profesioniști care cunosc domeniul, care rămân pe proiect, care sunt responsabili pentru rezultat — valorează mai mult decât o sută de consultanți în rotație care facturează zile.\nSoftware-ul nu se construiește cu slide-uri. Se construiește cu mâinile în cod, cu arhitectura în minte și cu responsabilitatea pe umeri.\nPatru milioane de euro în fum învață un singur lucru:\nCel mai mare cost nu este cel al furnizorului greșit pe care îl alegi.\nEste cel al timpului pe care îl pierzi înainte de a înțelege că soluția era mai simplă decât ce ți se vânduse.\n💬 Către cei care sunt pe punctul de a semna acel contract #Dacă compania ta este pe punctul de a încredința un proiect critic unei mari firme de consultanță, oprește-te un moment.\nÎntreabă-te:\nCine va scrie codul? Va mai fi în companie peste doi ani? Dacă furnizorul pleacă mâine, am putea întreține sistemul? Există un produs de piață care acoperă 80% din nevoile noastre? Putem construi o echipă internă mică, competentă și stabilă? Răspunsurile la aceste întrebări valorează mai mult decât orice propunere comercială.\nPentru că diferența dintre un proiect care funcționează și unul care arde milioane nu ține de tehnologie.\nȚine de oameni. De continuitate. De responsabilitate.\nȘi de capacitatea de a spune \u0026ldquo;nu\u0026rdquo; celor care îți vând complexitate când soluția este simplă.\nGlosar #Data Warehouse — Sistem centralizat de colectare și istoricizare a datelor din surse diverse, proiectat pentru analiză și suport al deciziilor de afaceri. În cazul descris, construit de două persoane cu 60.000 de linii de cod.\nETL — Extract, Transform, Load: procesul de extragere a datelor din sistemele sursă, transformare și încărcare în data warehouse. Ciclul ETL al DWH-ului descris rulează într-o oră și jumătate.\nVendor Lock-in — Dependență structurală de un furnizor extern care face schimbarea providerului dificilă. Se instaurează când know-how-ul și codul rămân în mâinile furnizorului.\nScope Creep — Expansiune necontrolată a cerințelor proiectului dincolo de perimetrul inițial. Specificațiile incomplete devin alibiul pentru întârzieri și costuri suplimentare.\nOutsourcing — Externalizarea activităților IT către furnizori externi. Riscant pentru proiecte strategice pe termen lung, unde rotația consultanților și pierderea know-how-ului pot arde milioane.\n","date":"30 decembrie 2025","permalink":"https://ivanluminaria.com/ro/posts/project-management/4-milioni-nessun-software/","section":"Database Strategy","summary":"\u003cp\u003ePovestea pe care urmează să o spun este reală. Nu voi da nume — nu din diplomație, ci pentru că numele nu contează. Ceea ce contează este să înțelegem mecanismul. Pentru că acest mecanism se repetă, identic, în zeci de companii. Și costă milioane.\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"-clientul-un-grup-de-asigurări-cu-o-ambiție-legitimă\" class=\"relative group\"\u003e🏢 Clientul: un grup de asigurări cu o ambiție legitimă \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#-clientul-un-grup-de-asigur%c4%83ri-cu-o-ambi%c8%9bie-legitim%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eO companie solidă din sectorul asigurărilor. Operațiuni în Italia, Franța, țări din Europa de Nord, Spania. Mii de angajați, milioane de polițe gestionate, o afacere în creștere.\u003c/p\u003e","title":"4 milioane de euro, două multinaționale, zero software: povestea reală a unui eșec anunțat"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/data-warehouse/","section":"Tags","summary":"","title":"Data-Warehouse"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/insurance/","section":"Tags","summary":"","title":"Insurance"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/outsourcing/","section":"Tags","summary":"","title":"Outsourcing"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/execution-plan/","section":"Tags","summary":"","title":"Execution-Plan"},{"content":"Două miliarde de rânduri. Nu este un număr la care ajungi într-o zi. Durează ani de tranzacții, mișcări, înregistrări zilnice care se acumulează. Și în tot acest timp baza de date funcționează, interogările răspund, rapoartele ies. Apoi într-o zi cineva deschide un ticket: „raportul lunar durează patru ore.\u0026quot;\nPatru ore. Pentru un raport care cu șase luni înainte dura douăzeci de minute.\nNu este un bug. Nu este o problemă de rețea sau de stocare lentă. Este fizica datelor: când o tabelă crește peste un anumit prag, abordările care funcționau nu mai funcționează. Și dacă nu ai proiectat structura să gestioneze acea creștere, baza de date face singurul lucru pe care îl poate face: citește totul.\nContextul: telecomunicații și volume industriale #Clientul era un operator de telecomunicații. Nimic exotic — un clasic mediu Oracle 19c Enterprise Edition pe Linux, stocare SAN, vreo treizeci de instanțe între producție, staging și dezvoltare. Instanța critică era cea de facturare: facturare, CDR (Call Detail Records), mișcări contabile.\nTabela din centrul problemei se numea TXN_MOVIMENTI. Colecta fiecare tranzacție individuală din sistemul de facturare din 2016. Structura era aproximativ aceasta:\nCREATE TABLE txn_movimenti ( txn_id NUMBER(18) NOT NULL, data_movimento DATE NOT NULL, cod_cliente VARCHAR2(20) NOT NULL, tipo_movimento VARCHAR2(10) NOT NULL, importo NUMBER(15,4), canale VARCHAR2(30), stato VARCHAR2(5) DEFAULT \u0026#39;ATT\u0026#39;, data_insert TIMESTAMP DEFAULT SYSTIMESTAMP, CONSTRAINT pk_txn_movimenti PRIMARY KEY (txn_id) ); 2,1 miliarde de rânduri. 380 GB de date. Un singur segment, un singur tablespace, fără partiții. Un monolit.\nIndecșii existau: unul pe cheia primară, unul pe data_movimento, unul compozit pe (cod_cliente, data_movimento). Dar când o tabelă depășește o anumită dimensiune, chiar și un index range scan nu mai este suficient, pentru că volumul de date returnat este în continuare enorm.\nSimptomele: nu este lentoare, este colaps #Problemele nu au apărut toate odată. Au venit treptat, cum se întâmplă întotdeauna cu tabelele care cresc fără control.\nPrimul semnal: rapoartele lunare. Interogarea agregată de facturare — care suma importurile per client pentru o lună dată — trecuse de la 20 de minute la 4 ore în decursul unui an. Planul de execuție arăta un index range scan pe dată, dar numărul de blocuri citite era monstruos: Oracle trebuia să parcurgă sute de mii de leaf block-uri ale indexului și apoi să facă table access by rowid pentru a recupera coloanele neacoperite.\nAl doilea semnal: mentenanța. ALTER INDEX REBUILD pe indexul datei dura șase ore. Colectarea statisticilor (DBMS_STATS.GATHER_TABLE_STATS) nu se termina într-o noapte. Backup-urile RMAN deveniseră o ruletă: uneori intrau în fereastră, alteori nu.\nAl treilea semnal: full table scan-urile involuntare. Interogări cu predicate pe dată pe care optimizatorul decidea să le rezolve cu un full table scan pentru că costul estimat al index scan-ului era superior. Pe 380 GB de date.\nPlanul de execuție al interogării de facturare era acesta:\nSELECT cod_cliente, TRUNC(data_movimento, \u0026#39;MM\u0026#39;) AS mese, SUM(importo) AS totale FROM txn_movimenti WHERE data_movimento BETWEEN DATE \u0026#39;2025-01-01\u0026#39; AND DATE \u0026#39;2025-01-31\u0026#39; AND stato = \u0026#39;CON\u0026#39; GROUP BY cod_cliente, TRUNC(data_movimento, \u0026#39;MM\u0026#39;); --------------------------------------------------------------------- | Id | Operation | Name | Rows | Cost | --------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 125K | 890K | | 1 | HASH GROUP BY | | 125K | 890K | | 2 | TABLE ACCESS BY INDEX ROWID| TXN_MOVIMENTI | 28M | 885K | |* 3 | INDEX RANGE SCAN | IDX_TXN_DATA | 28M | 85K | --------------------------------------------------------------------- 28 de milioane de rânduri doar pentru ianuarie. Indexul găsea rândurile, dar apoi Oracle trebuia să extragă fiecare rând individual din tabelă pentru a citi cod_cliente, importo și stato. Milioane de operații de I/O aleatoriu pe o tabelă de 380 GB dispersată pe mii de blocuri.\nSoluția: nu ai nevoie de un index mai bun, ai nevoie de o structură diferită #Am petrecut două zile analizând pattern-urile de acces înainte de a propune orice soluție. Pentru că partitioning-ul nu este o baghetă magică — dacă alegi greșit cheia de partiție, înrăutățești lucrurile.\nPattern-urile erau clare:\n90% din interogări aveau un predicat pe dată (data_movimento) Rapoartele erau întotdeauna lunare sau trimestriale Interogările operaționale (client individual) foloseau întotdeauna cod_cliente + data_movimento Datele mai vechi de 3 ani nu erau niciodată citite de rapoarte, doar de procesele anuale de arhivare Alegerea a căzut pe un interval partitioning lunar pe coloana data_movimento. Nu range partitioning clasic, unde trebuie să creezi manual fiecare partiție viitoare. Interval: definești intervalul o singură dată și Oracle creează partițiile automat când sosesc date pentru o nouă perioadă.\nImplementarea: CTAS, indecși locali și zero downtime (aproape) #Nu poți face ALTER TABLE ... PARTITION BY pe o tabelă existentă cu 2 miliarde de rânduri. Nu în Oracle 19c, cel puțin nu fără Online Table Redefinition. Și acea opțiune, pe o tabelă de aceste dimensiuni, are propriile riscuri.\nAm ales abordarea CTAS — Create Table As Select — cu paralelism. Creezi noua tabelă partițională, copiezi datele, redenumești.\nPasul 1: crearea tabelei partiționate #CREATE TABLE txn_movimenti_part PARTITION BY RANGE (data_movimento) INTERVAL (NUMTOYMINTERVAL(1, \u0026#39;MONTH\u0026#39;)) ( PARTITION p_before_2016 VALUES LESS THAN (DATE \u0026#39;2016-01-01\u0026#39;), PARTITION p_2016_01 VALUES LESS THAN (DATE \u0026#39;2016-02-01\u0026#39;), PARTITION p_2016_02 VALUES LESS THAN (DATE \u0026#39;2016-03-01\u0026#39;) -- Oracle va crea automat partițiile ulterioare ) TABLESPACE ts_billing_data NOLOGGING PARALLEL 8 AS SELECT /*+ PARALLEL(t, 8) */ txn_id, data_movimento, cod_cliente, tipo_movimento, importo, canale, stato, data_insert FROM txn_movimenti t; `NOLOGGING` este fundamental: fără el, copia generează redo log pentru fiecare bloc scris. Pe 380 GB ar însemna umplerea zonei de redo și punerea sistemului în mod archivelog timp de zile. Cu NOLOGGING copia a durat 3 ore și jumătate cu paralelism la 8.\nDupă copiere am restaurat logging-ul:\nALTER TABLE txn_movimenti_part LOGGING; Și am lansat un backup RMAN imediat, pentru că segmentele NOLOGGING nu sunt recuperabile în caz de restore.\nPasul 2: indecși locali #Designul indecșilor pe o tabelă partițională este diferit de o tabelă normală. Conceptul cheie este: index local vs index global.\nUn index **local** este partiționat cu aceeași cheie ca tabela. Fiecare partiție a tabelei are partiția de index corespunzătoare. Avantaj: operațiile de mentenanță pe o partiție nu le afectează pe celelalte.\nUn index global acoperă toate partițiile. Este mai eficient pentru interogări care nu filtrează pe cheia de partiție, dar orice operație DDL pe partiție (drop, truncate, split) invalidează indexul întreg.\n-- Cheie primară ca index global (necesar pentru lookup-uri punctuale) ALTER TABLE txn_movimenti_part ADD CONSTRAINT pk_txn_mov_part PRIMARY KEY (txn_id) USING INDEX GLOBAL; -- Index local pe dată (aliniat cu partiția) CREATE INDEX idx_txn_mov_data ON txn_movimenti_part (data_movimento) LOCAL PARALLEL 8; -- Index local compozit pentru interogări operaționale CREATE INDEX idx_txn_mov_cli_data ON txn_movimenti_part (cod_cliente, data_movimento) LOCAL PARALLEL 8; Cheia primară rămâne globală pentru că interogările pe txn_id nu includ niciodată data — ai nevoie de acces direct. Ceilalți indecși sunt locali pentru că se aliniază cu pattern-urile de utilizare: interogări pe dată, interogări pe client+dată.\nPasul 3: comutarea #-- Redenumirea tabelei originale (backup) ALTER TABLE txn_movimenti RENAME TO txn_movimenti_old; -- Redenumirea noii tabele ALTER TABLE txn_movimenti_part RENAME TO txn_movimenti; -- Reconstruirea sinonimelor dacă există -- Recompilarea obiectelor invalidate BEGIN FOR obj IN (SELECT object_name, object_type FROM dba_objects WHERE status = \u0026#39;INVALID\u0026#39; AND owner = \u0026#39;BILLING\u0026#39;) LOOP BEGIN IF obj.object_type = \u0026#39;PACKAGE BODY\u0026#39; THEN EXECUTE IMMEDIATE \u0026#39;ALTER PACKAGE billing.\u0026#39; || obj.object_name || \u0026#39; COMPILE BODY\u0026#39;; ELSIF obj.object_type IN (\u0026#39;PROCEDURE\u0026#39;,\u0026#39;FUNCTION\u0026#39;,\u0026#39;VIEW\u0026#39;) THEN EXECUTE IMMEDIATE \u0026#39;ALTER \u0026#39; || obj.object_type || \u0026#39; billing.\u0026#39; || obj.object_name || \u0026#39; COMPILE\u0026#39;; END IF; EXCEPTION WHEN OTHERS THEN NULL; END; END LOOP; END; / Downtime-ul efectiv a fost timpul celor două ALTER TABLE RENAME: câteva secunde. Tot restul — copia datelor, crearea indecșilor — s-a întâmplat în paralel cu sistemul activ.\nPasul 4: colectarea statisticilor #BEGIN DBMS_STATS.GATHER_TABLE_STATS( ownname =\u0026gt; \u0026#39;BILLING\u0026#39;, tabname =\u0026gt; \u0026#39;TXN_MOVIMENTI\u0026#39;, granularity =\u0026gt; \u0026#39;ALL\u0026#39;, estimate_percent =\u0026gt; DBMS_STATS.AUTO_SAMPLE_SIZE, degree =\u0026gt; 8 ); END; / Parametrul granularity =\u0026gt; 'ALL' este important: îi spune lui Oracle să colecteze statistici la nivel global, de partiție și de subpartiție. Fără el, optimizatorul ar putea lua decizii greșite pentru că nu cunoaște distribuția datelor în interiorul partițiilor individuale.\nÎnainte și după: cifrele #Aceeași interogare de facturare, după partitioning:\n------------------------------------------------------------------------ | Id | Operation | Name | Rows | Cost | ------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 125K | 12K | | 1 | HASH GROUP BY | | 125K | 12K | | 2 | PARTITION RANGE SINGLE | | 28M | 11K | | 3 | TABLE ACCESS FULL | TXN_MOVIMENTI | 28M | 11K | ------------------------------------------------------------------------ Uitați-vă la operația de la pasul 2: PARTITION RANGE SINGLE. Oracle știe că datele din ianuarie stau într-o singură partiție și citește doar aceea. Full table scan-ul care înainte teroriza este acum un full partition scan — pe aproximativ 4 GB în loc de 380.\nMetrică Înainte După Variație Timp interogare lunară 4 ore 3 minute -98% Consistent gets 48M 580K -98.8% Physical reads 12M 95K -99.2% Timp GATHER_TABLE_STATS 14 ore 25 min (per partiție) -97% Timp rebuild index 6 ore 12 min (per partiție) -97% Dimensiune backup incremental 380 GB ~4 GB/lună -99% Costul a trecut de la 890K la 12K. Nu este o îmbunătățire procentuală — este un ordin de mărime diferit.\nPartition pruning: adevărata magie #Mecanismul care face toate acestea posibile se numește **partition pruning** . Nu este ceva ce trebuie configurat — Oracle o face automat când predicatul interogării corespunde cheii de partiție.\nDar trebuie să știi când funcționează și când nu.\nFuncționează cu predicate directe pe coloana de partiție:\n-- Pruning activ: Oracle citește doar partiția din ianuarie WHERE data_movimento BETWEEN DATE \u0026#39;2025-01-01\u0026#39; AND DATE \u0026#39;2025-01-31\u0026#39; -- Pruning activ: Oracle citește doar partiția specifică WHERE data_movimento = DATE \u0026#39;2025-03-15\u0026#39; Nu funcționează când coloana este în interiorul unei funcții:\n-- Pruning DEZACTIVAT: Oracle trebuie să citească toate partițiile WHERE TRUNC(data_movimento) = DATE \u0026#39;2025-01-01\u0026#39; -- Pruning DEZACTIVAT: funcție pe coloană WHERE TO_CHAR(data_movimento, \u0026#39;YYYY-MM\u0026#39;) = \u0026#39;2025-01\u0026#39; -- Pruning DEZACTIVAT: expresie aritmetică WHERE data_movimento + 30 \u0026gt; SYSDATE Aceasta este eroarea cea mai comună pe care o văd după o implementare de partitioning: dezvoltatorii aplică funcții pe coloana de dată fără să realizeze că dezactivează pruning-ul. Și tabela revine la a fi citită integral.\nAm dedicat o jumătate de zi revizuirii tuturor interogărilor aplicației care atingeau TXN_MOVIMENTI. Am găsit unsprezece cu TRUNC(data_movimento) în WHERE. Unsprezece interogări care ar fi ignorat partitioning-ul.\nGestionarea ciclului de viață: drop partition #Unul dintre avantajele cele mai concrete ale partitioning-ului este gestionarea ciclului de viață al datelor. Înainte de partitioning, arhivarea datelor vechi însemna un DELETE de miliarde de rânduri — o operație care generează munți de redo și undo, blochează tabela ore întregi și riscă să facă să explodeze tablespace-ul de undo.\nCu partitioning:\n-- Arhivarea datelor din 2016 într-un tablespace read-only ALTER TABLE txn_movimenti MOVE PARTITION p_2016_01 TABLESPACE ts_archive; -- Sau, dacă datele nu mai sunt necesare ALTER TABLE txn_movimenti DROP PARTITION p_2016_01; Un DROP PARTITION pe o partiție de 4 GB durează mai puțin de o secundă. Nu generează undo. Nu generează redo semnificativ. Nu blochează celelalte partiții. Este o operație DDL, nu DML.\nAm configurat un job lunar care muta partițiile mai vechi de 5 ani în tablespace-ul de arhivă și le punea în read-only. Clientul a recuperat 120 GB de spațiu activ fără să șteargă un singur dat.\nCe am învățat (și erorile de evitat) #După cincisprezece ani de partitioning Oracle, am o listă de lucruri pe care mi-aș fi dorit să le fi știut mai devreme.\nCheia de partiție trebuie să corespundă pattern-ului de acces. Pare evident, dar am văzut tabele partiționate pe cod_cliente când 95% din interogări filtrează pe dată. Partitioning-ul funcționează doar dacă interogările pot face pruning.\nInterval partitioning este aproape întotdeauna mai bun decât range static. Cu range clasic trebuie să creezi manual partițiile viitoare, ceea ce înseamnă un job programat sau un DBA care și-l amintește. Cu interval Oracle le creează singur. O problemă mai puțin.\nIndecșii globali sunt o capcană. Funcționează bine pentru interogări, dar orice operație DDL pe partiție îi invalidează. Și reconstruirea unui index global pe 2 miliarde de rânduri durează ore. Folosește indecși locali unde este posibil și acceptă compromisul.\nNOLOGGING nu este opțional pentru operații masive. Fără NOLOGGING, un CTAS de 380 GB generează aceeași cantitate de redo. Zona ta de archivelog se va umple, baza de date va intra în așteptare, iar DBA-ul de gardă va primi un telefon la 3 dimineața.\nTestează pruning-ul înainte de a merge în producție. Nu te încrede: verifică cu EXPLAIN PLAN că fiecare interogare critică face efectiv pruning. Un singur TRUNC() în predicatul greșit și ai un full table scan de 380 GB.\nPartitioning-ul nu înlocuiește indecșii. Reduce volumul de date de examinat, dar în interiorul partiției ai nevoie în continuare de indecșii potriviți. O partiție lunară de 28 de milioane de rânduri fără index este tot o problemă.\nCând ai nevoie de partitioning #Nu toate tabelele au nevoie de partitioning. Regula mea empirică:\nSub 10 milioane de rânduri: probabil nu Între 10 și 100 de milioane: depinde de pattern-ul de acces și de ritmul de creștere Peste 100 de milioane: probabil da Peste un miliard: nu ai de ales Dar momentul potrivit pentru a-l implementa este înainte să devină urgent. Când tabela are deja 2 miliarde de rânduri, migrarea este un proiect în sine. Când are 50 de milioane și crește, este treabă de o după-amiază.\nCea mai mare eroare a mea cu partitioning-ul? Că nu l-am propus cu șase luni mai devreme, când toate semnalele erau deja acolo.\nGlosar #Partition Pruning — Mecanism automat Oracle care exclude partițiile nerelevante în timpul execuției unei interogări, citind doar cele care conțin date corespunzătoare predicatului.\nCTAS — Create Table As Select: tehnică pentru crearea unei tabele noi populate cu un SELECT într-o singură operație. Esențial pentru migrarea tabelelor cu miliarde de rânduri la partitioning.\nLocal Index — Index partiționat cu aceeași cheie ca tabela. Fiecare partiție are propria porțiune de index, făcând operațiile DDL independente între partiții.\nNOLOGGING — Mod Oracle care suprimă generarea de redo log în timpul operațiunilor masive, reducând timpii de la zile la ore. Necesită backup RMAN imediat după utilizare.\nTablespace — Unitate logică de stocare Oracle care grupează fișiere de date fizice. În partitioning, permite mutarea partițiilor vechi pe stocare de arhivă și gestionarea ciclului de viață al datelor.\n","date":"23 decembrie 2025","permalink":"https://ivanluminaria.com/ro/posts/oracle/oracle-partitioning/","section":"Database Strategy","summary":"\u003cp\u003eDouă miliarde de rânduri. Nu este un număr la care ajungi într-o zi. Durează ani de tranzacții, mișcări, înregistrări zilnice care se acumulează. Și în tot acest timp baza de date funcționează, interogările răspund, rapoartele ies. Apoi într-o zi cineva deschide un ticket: „raportul lunar durează patru ore.\u0026quot;\u003c/p\u003e\n\u003cp\u003ePatru ore. Pentru un raport care cu șase luni înainte dura douăzeci de minute.\u003c/p\u003e\n\u003cp\u003eNu este un bug. Nu este o problemă de rețea sau de stocare lentă. Este fizica datelor: când o tabelă crește peste un anumit prag, abordările care funcționau nu mai funcționează. Și dacă nu ai proiectat structura să gestioneze acea creștere, baza de date face singurul lucru pe care îl poate face: citește totul.\u003c/p\u003e","title":"Oracle Partitioning: când 2 miliarde de rânduri nu mai încap într-o interogare"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/partitioning/","section":"Tags","summary":"","title":"Partitioning"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/architecture/","section":"Tags","summary":"","title":"Architecture"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/data-guard/","section":"Tags","summary":"","title":"Data-Guard"},{"content":"Clientul era o companie de dimensiuni medii din sectorul asigurărilor. Trei sute de angajați, o aplicație de gestiune internă pe Oracle 19c, un singur server fizic în camera serverelor de la parter. Fără replică. Fără standby. Fără plan de disaster recovery.\nTimp de cinci ani totul funcționase. Și când lucrurile merg, nimeni nu vrea să cheltuie bani protejându-se de probleme pe care nu le-a văzut niciodată.\nZiua în care s-a oprit totul #Într-o dimineață de miercuri din noiembrie, la 8:47, discul grupului principal de date a suferit o defecțiune fizică. Nu o eroare logică, nu o corupție recuperabilă. O defecțiune hardware. Controlerul RAID a pierdut două discuri simultan — unul era degradat de săptămâni fără ca nimeni să observe, celălalt a cedat brusc.\nBaza de date s-a oprit. Polițele nu se emiteau. Daunele nu se procesau. Call center-ul le răspundea clienților cu \u0026ldquo;probleme tehnice, sunați mai târziu.\u0026rdquo;\nAm primit apelul la 9:15. Când am ajuns la sediu, administratorul de sistem căuta deja discuri compatibile. Le-a găsit după-amiaza devreme. Între înlocuire, reconstrucția RAID-ului și recuperarea bazei de date din backup-ul din noaptea precedentă, sistemul a revenit operațional la 15:20.\nȘase ore și jumătate de oprire totală. Și pierderea tuturor tranzacțiilor de la 23:00 seara precedentă până la 8:47 dimineața — aproximativ zece ore de date, pentru că backup-ul era doar nocturn și archived log-urile nu erau copiate pe altă mașină.\nCEO-ul a trimis în seara aceea un email întregii companii. A doua zi m-a sunat: \u0026ldquo;Ce trebuie să facem ca să nu se mai întâmple niciodată?\u0026rdquo;\nDesignul #Răspunsul era simplu ca și concept, mai puțin simplu în realizare: aveau nevoie de o a doua bază de date, sincronizată în timp real, gata să preia rolul primarului în caz de defecțiune.\nOracle Active Data Guard face exact asta. O bază de date primară generează redo log -uri, iar un standby le primește și le aplică continuu. Dacă primarul moare, standby-ul devine primar. Dacă totul e în ordine, standby-ul poate fi folosit și în mod read-only — pentru rapoarte, pentru backup-uri, pentru a ușura încărcarea.\nAm proiectat o arhitectură cu două noduri:\nPrimar (oraprod1): serverul existent, cu discuri noi, la sediul principal Standby (oraprod2): un server nou identic, în data center-ul providerului de hosting, la 12 km distanță Distanța nu era întâmplătoare. Suficient de departe pentru a supraviețui unui eveniment localizat (incendiu, inundație, pană de curent prelungită), suficient de aproape pentru a permite replicarea sincronă fără latență perceptibilă.\nConfigurarea #Pregătirea primarului #Primul pas a fost verificarea că primarul era în mod ARCHIVELOG cu FORCE LOGGING activ. Fără aceste două precondiții, Data Guard nu are ce replica.\n-- Verificare mod archivelog SELECT log_mode FROM v$database; -- Dacă e necesar, activare SHUTDOWN IMMEDIATE; STARTUP MOUNT; ALTER DATABASE ARCHIVELOG; ALTER DATABASE OPEN; -- Force logging: previne operațiunile NOLOGGING ALTER DATABASE FORCE LOGGING; FORCE LOGGING este fundamental. Fără el, orice operațiune cu clauza NOLOGGING — un CREATE TABLE AS SELECT, un ALTER INDEX REBUILD — nu generează redo și creează goluri în replicare. Am văzut asta întâmplându-se de trei ori în carieră. A treia oară am decis că FORCE LOGGING se activează întotdeauna, fără excepții.\nStandby redo log-uri #Pe primar am creat standby redo log-urile — grupuri dedicate care vor fi folosite când (și dacă) acest server devine standby după un switchover.\n-- Standby redo log-uri: n+1 față de redo log-urile online -- Dacă ai 3 grupuri online, creezi 4 standby ALTER DATABASE ADD STANDBY LOGFILE GROUP 4 SIZE 200M; ALTER DATABASE ADD STANDBY LOGFILE GROUP 5 SIZE 200M; ALTER DATABASE ADD STANDBY LOGFILE GROUP 6 SIZE 200M; ALTER DATABASE ADD STANDBY LOGFILE GROUP 7 SIZE 200M; Regula este n+1: dacă primarul are trei grupuri de redo log, standby-ul are nevoie de patru. Nu e documentată foarte clar, dar am învățat-o pe propria piele — cu trei grupuri egale, sub încărcare grea standby-ul se poate bloca așteptând un grup liber.\nConfigurarea rețelei #tnsnames.ora pe ambele noduri trebuie să cunoască atât primarul cât și standby-ul. Configurarea este simetrică:\nORAPROD1 = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.10.1)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = oraprod) ) ) ORAPROD2 = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = 10.0.5.1)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = oraprod) ) ) listener.ora pe standby trebuie să includă o intrare statică pentru baza de date, pentru că în timpul restore-ului standby-ul nu este încă deschis și listener-ul nu îl poate înregistra dinamic:\nSID_LIST_LISTENER = (SID_LIST = (SID_DESC = (GLOBAL_DBNAME = oraprod_DGMGRL) (ORACLE_HOME = /u01/app/oracle/product/19c) (SID_NAME = oraprod) ) ) Sufixul _DGMGRL este folosit de Data Guard Broker pentru a identifica instanța. Fără această intrare statică, broker-ul nu se poate conecta la standby și operațiunile de switchover eșuează cu erori criptice care te fac să pierzi o jumătate de zi.\nCrearea standby-ului #Pentru copia inițială a bazei de date am folosit un DUPLICATE prin RMAN prin rețea. Fără backup pe bandă, fără transfer manual de fișiere. Direct, de la primar la standby:\n-- Pe serverul standby, pornirea instanței în NOMOUNT STARTUP NOMOUNT PFILE=\u0026#39;/u01/app/oracle/product/19c/dbs/initoraprod.ora\u0026#39;; -- Din RMAN, conectat la ambele RMAN TARGET sys/password@ORAPROD1 AUXILIARY sys/password@ORAPROD2 DUPLICATE TARGET DATABASE FOR STANDBY FROM ACTIVE DATABASE DORECOVER SPFILE SET db_unique_name=\u0026#39;oraprod_stby\u0026#39; SET log_archive_dest_2=\u0026#39;\u0026#39; SET fal_server=\u0026#39;ORAPROD1\u0026#39; NOFILENAMECHECK; NOFILENAMECHECK se folosește când căile fișierelor sunt identice pe ambele mașini — aceeași structură de directoare, aceeași convenție de nume. Dacă căile diferă, sunt necesari parametrii DB_FILE_NAME_CONVERT și LOG_FILE_NAME_CONVERT.\nCopia a durat aproximativ trei ore pentru 400 GB printr-o linie dedicată de 1 Gbps. Nu cea mai rapidă, dar este o operațiune care se face o singură dată.\nData Guard Broker #Broker-ul este componenta care gestionează configurația Data Guard centralizat și permite switchover-ul cu o singură comandă. Fără Broker poți face totul manual, dar nu vrei să faci asta manual când primarul tocmai a căzut și CEO-ul te sună la fiecare cinci minute.\n-- Pe primar ALTER SYSTEM SET dg_broker_start=TRUE; -- Pe standby ALTER SYSTEM SET dg_broker_start=TRUE; Apoi, din DGMGRL pe primar:\nDGMGRL\u0026gt; CREATE CONFIGURATION dg_config AS PRIMARY DATABASE IS oraprod CONNECT IDENTIFIER IS ORAPROD1; DGMGRL\u0026gt; ADD DATABASE oraprod_stby AS CONNECT IDENTIFIER IS ORAPROD2 MAINTAINED AS PHYSICAL; DGMGRL\u0026gt; ENABLE CONFIGURATION; În acel moment, SHOW CONFIGURATION trebuie să returneze:\nConfiguration - dg_config Protection Mode: MaxPerformance Members: oraprod - Primary database oraprod_stby - Physical standby database Fast-Start Failover: DISABLED Configuration Status: SUCCESS Cuvântul pe care vrei să-l vezi este SUCCESS. Orice altceva înseamnă că există o problemă de rețea, configurare sau permisiuni de rezolvat înainte de a merge mai departe.\nPrimul switchover #La două săptămâni după punerea în funcțiune a arhitecturii, am făcut primul test de switchover. Într-o sâmbătă dimineața, cu aplicația oprită, dar cu CEO-ul prezent — voia să vadă cu ochii lui.\nDGMGRL\u0026gt; SWITCHOVER TO oraprod_stby; O singură comandă. Patruzeci și două de secunde. Primarul a devenit standby, standby-ul a devenit primar. Aplicațiile, configurate cu serviciul corect, s-au reconectat automat.\nDGMGRL\u0026gt; SHOW CONFIGURATION; Configuration - dg_config Protection Mode: MaxPerformance Members: oraprod_stby - Primary database oraprod - Physical standby database Fast-Start Failover: DISABLED Configuration Status: SUCCESS Apoi am făcut switchback-ul — revenirea la primarul original. Alte treizeci și opt de secunde. Curat.\nCEO-ul s-a uitat la ecran, s-a uitat la mine, și a spus: \u0026ldquo;Patruzeci și două de secunde versus șase ore. De ce n-am făcut asta mai devreme?\u0026rdquo;\nNu i-am dat răspunsul. Îl știam amândoi.\nCe nu-ți spun #Configurarea pe care am descris-o funcționează. Dar sunt lucruri pe care documentația Oracle nu le subliniază suficient.\nGap-ul de rețea. Replicarea sincronă (SYNC) garantează zero pierderi de date dar introduce latență la fiecare commit. Cu 12 km și o fibră bună, latența adăugată era de 1-2 milisecunde — acceptabilă. Dar la 100 km ar fi fost 5-8 ms, și pe o aplicație cu mii de commit-uri pe secundă, încetinirea s-ar fi simțit. De aceea am ales modul MaxPerformance (asincron) ca implicit, acceptând posibilitatea teoretică de a pierde câteva secunde de tranzacții în caz de dezastru total. Pentru acel client, pierderea a cinci secunde de date era infinit mai bună decât pierderea a zece ore.\nFișierul de parole. Fișierul de parole al utilizatorului SYS trebuie să fie identic pe primar și standby. Dacă îl schimbi pe unul și nu pe celălalt, redo transport-ul se oprește silențios. Nicio eroare evidentă, doar un gap care crește. Am descoperit asta după o oră de debugging într-o duminică seara.\nTablespace-urile temporare. Standby-ul nu replică tablespace-urile temporare. Dacă deschizi standby-ul în citire pentru rapoarte (Active Data Guard), trebuie să creezi manual tablespace-urile temporare, altfel query-urile cu sort sau hash join eșuează cu erori care n-au nicio legătură cu problema reală.\n-- Pe standby-ul deschis în mod read-only ALTER TABLESPACE TEMP ADD TEMPFILE SIZE 2G AUTOEXTEND ON; Patch-urile. Primarul și standby-ul trebuie să fie la același nivel de patch-uri. Dacă aplici o PSU pe primar fără să o aplici pe standby, redo-ul ar putea conține structuri pe care standby-ul nu le poate interpreta. Switchover-ul va funcționa, dar după aceea ai putea avea corupții silențioase. Procedura corectă este: patch pe standby mai întâi, switchover, patch pe vechiul primar (acum standby), switchback.\nCifrele #La șase luni de la implementare, bilanțul era clar:\nMetrică Înainte După RPO (Recovery Point Objective) ~10 ore (backup nocturn) \u0026lt; 5 secunde RTO (Recovery Time Objective) 6+ ore (restore din backup) \u0026lt; 1 minut (switchover) Disponibilitate rapoarte în paralel Nu Da (Active Data Guard) Cost infrastructură suplimentară — 1 server + linie dedicată Teste de switchover efectuate 0 6 (unul pe lună) Costul total al proiectului — server, licențe, linie dedicată, implementare — era aproximativ un sfert din cât costase acea singură zi de oprire. Nu în termeni tehnici. În termeni de polițe neemise, daune neprocesate, clienți neserviți.\nCe am învățat #Disaster recovery nu este o problemă tehnică. Este o problemă de percepție a riscului. Cât timp baza de date funcționează, DR-ul este o cheltuială. Când baza de date se oprește, DR-ul este o investiție care trebuia făcută cu șase luni înainte.\nNu poți convinge un CEO cu o diagramă arhitecturală. Poți doar să aștepți ca dezastrul să se întâmple și apoi să fii pregătit cu soluția. E cinic, dar așa funcționează în nouăzeci la sută din cazuri.\nSingurul lucru pe care îl poți face dinainte este să documentezi riscul, să pui în scris că l-ai semnalat, și să ții proiectul pregătit în sertar. Eu propusesem acel proiect cu optsprezece luni înainte. Fusese pus deoparte cu un \u0026ldquo;revenim anul viitor.\u0026rdquo;\nAnul viitor a sosit într-o dimineață de miercuri din noiembrie, la 8:47.\nGlosar #Data Guard — Tehnologie Oracle pentru replicarea in timp real a unei baze de date pe unul sau mai multe servere standby. Standby-ul primeste si aplica continuu redo log-urile primarului, permitand switchover in secunde.\nRedo Log — Fisiere de log in care Oracle inregistreaza fiecare modificare a datelor inainte de a o scrie in datafile-uri. Sunt baza recuperarii si replicarii Data Guard: fara redo, niciuna dintre aceste operatiuni nu este posibila.\nRPO — Recovery Point Objective. Cantitatea maxima de date pe care o organizatie si-o poate permite sa piarda in caz de dezastru, masurata in timp. Cu Data Guard asincron se reduce la cateva secunde.\nRTO — Recovery Time Objective. Timpul maxim acceptabil pentru restaurarea serviciului dupa o defectiune. Cu Data Guard si switchover automat, se trece de la ore la mai putin de un minut.\nRMAN — Recovery Manager. Instrumentul nativ Oracle pentru backup, restore si recovery, inclusiv crearea bazelor de date standby prin DUPLICATE ... FOR STANDBY FROM ACTIVE DATABASE.\n","date":"16 decembrie 2025","permalink":"https://ivanluminaria.com/ro/posts/oracle/oracle-data-guard/","section":"Database Strategy","summary":"\u003cp\u003eClientul era o companie de dimensiuni medii din sectorul asigurărilor. Trei sute de angajați, o aplicație de gestiune internă pe Oracle 19c, un singur server fizic în camera serverelor de la parter. Fără replică. Fără standby. Fără plan de disaster recovery.\u003c/p\u003e\n\u003cp\u003eTimp de cinci ani totul funcționase. Și când lucrurile merg, nimeni nu vrea să cheltuie bani protejându-se de probleme pe care nu le-a văzut niciodată.\u003c/p\u003e\n\u003ch2 id=\"ziua-în-care-s-a-oprit-totul\" class=\"relative group\"\u003eZiua în care s-a oprit totul \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#ziua-%c3%aen-care-s-a-oprit-totul\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eÎntr-o dimineață de miercuri din noiembrie, la 8:47, discul grupului principal de date a suferit o defecțiune fizică. Nu o eroare logică, nu o corupție recuperabilă. O defecțiune hardware. Controlerul RAID a pierdut două discuri simultan — unul era degradat de săptămâni fără ca nimeni să observe, celălalt a cedat brusc.\u003c/p\u003e","title":"De la single instance la Data Guard: ziua în care CEO-ul a înțeles DR-ul"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/disaster-recovery/","section":"Tags","summary":"","title":"Disaster-Recovery"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/switchover/","section":"Tags","summary":"","title":"Switchover"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/kimball/","section":"Tags","summary":"","title":"Kimball"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/scd/","section":"Tags","summary":"","title":"Scd"},{"content":"Directorul comercial apare la ședința de luni dimineața cu o întrebare simplă: \u0026ldquo;Câți clienți aveam în regiunea Nord în iunie trecut?\u0026rdquo;\nRăspunsul DWH-ului: liniște.\nNu pentru că sistemul era căzut, sau pentru că lipsea tabela. Datele erau acolo, tehnic vorbind. Dar erau greșite. DWH-ul returna clienții care astăzi sunt în regiunea Nord — nu pe cei care erau acolo în iunie. Pentru că în fiecare noapte, procesul de încărcare suprascria datele master ale clienților cu valorile curente, ștergând orice urmă a ceea ce fusese înainte.\nUn client care în iunie era în regiunea Nord și în septembrie s-a mutat în regiunea Centru? Pentru DWH, acel client fusese întotdeauna în regiunea Centru. Istoria nu exista.\nProiectul și modelul original #Contextul era un data warehouse în sectorul asigurărilor — gestionarea daunelor și portofoliului de clienți. Sistemul sursă conținea o înregistrare master pentru fiecare client: nume, regiune, agent alocat, clasă de risc, tip de poliță.\nDimensiunea din DWH era modelată astfel:\nCREATE TABLE dim_client ( client_id NUMBER(10) NOT NULL, nume VARCHAR2(100) NOT NULL, regiune VARCHAR2(50) NOT NULL, agent VARCHAR2(100), clasa_risc VARCHAR2(20), tip_polita VARCHAR2(50), CONSTRAINT pk_dim_client PRIMARY KEY (client_id) ); ETL -ul de noapte era un simplu MERGE : dacă clientul există, actualizează toate câmpurile; dacă nu există, inserează.\nMERGE INTO dim_client d USING stg_client s ON (d.client_id = s.client_id) WHEN MATCHED THEN UPDATE SET d.nume = s.nume, d.regiune = s.regiune, d.agent = s.agent, d.clasa_risc = s.clasa_risc, d.tip_polita = s.tip_polita WHEN NOT MATCHED THEN INSERT ( client_id, nume, regiune, agent, clasa_risc, tip_polita ) VALUES ( s.client_id, s.nume, s.regiune, s.agent, s.clasa_risc, s.tip_polita ); Simplu, curat, rapid. Și complet greșit pentru un data warehouse.\nAceasta este ceea ce Kimball numește SCD Tip 1 — Slowly Changing Dimension de Tip 1. Suprascrii valoarea veche cu cea nouă. Fără istorie, fără versionare. Valoarea actuală șterge valoarea anterioară.\nPentru un sistem OLTP este perfect: vrei întotdeauna adresa curentă a clientului, telefonul actualizat, email-ul valid. Dar un data warehouse nu este un sistem tranzacțional. Un data warehouse este o mașină a timpului. Și o mașină a timpului care suprascrie trecutul este inutilă.\nCe se pierde cu Tipul 1 #Directorul comercial nu era singurul care punea întrebări la care DWH-ul nu putea răspunde. Iată un eșantion din solicitările acumulate în trei luni:\n\u0026ldquo;Câți clienți au trecut de la clasa de risc Înaltă la Scăzută în ultimul an?\u0026rdquo; — Imposibil. Clasa anterioară nu mai există. \u0026ldquo;Agentul Rossi a pierdut clienți față de trimestrul trecut?\u0026rdquo; — Imposibil. Dacă un client a fost reatribuit agentului Bianchi, nu există nicio urmă că ar fi aparținut vreodată lui Rossi. \u0026ldquo;Cifra de afaceri a regiunii Sud a scăzut sau clienții s-au mutat?\u0026rdquo; — Imposibil de distins. Dacă un client de 200K s-a mutat din regiunea Sud în regiunea Centru, cifra de afaceri a Sudului scade dar nu pentru că business-ul merge prost — pur și simplu clientul și-a schimbat adresa. De fiecare dată răspunsul era același: \u0026ldquo;Sistemul nu păstrează istoria.\u0026rdquo; Ceea ce tradus în limbaj de business înseamnă: \u0026ldquo;Nu știm.\u0026rdquo;\nLa un moment dat, CFO-ul a cerut un raport de analiză trimestrială care să compare compoziția portofoliului de clienți între Q1 și Q2. Echipa de BI a încercat să-l construiască. Le-a luat trei zile. Rezultatul nu era fiabil pentru că datele din Q1 nu mai existau — fuseseră suprascrise cu datele din Q2. Raportul compara Q2 cu Q2 deghizat în Q1.\nAcela a fost momentul care a declanșat proiectul de restructurare.\nSCD Tip 2: principiul #Tipul 2 nu suprascrie. Versionează.\nCând un atribut se schimbă, înregistrarea curentă este închisă — i se atribuie o dată de sfârșit de valabilitate — și se inserează o nouă înregistrare cu valorile actualizate și o nouă dată de început de valabilitate. Înregistrarea veche rămâne în baza de date, intactă, cu toate valorile pe care le avea când era curentă.\nPentru ca acest lucru să funcționeze sunt necesare trei elemente suplimentare în tabela dimensională:\nO cheie surogat — un identificator generat de DWH, distinct de cheia naturală a sistemului sursă. Este necesar deoarece același client va avea mai multe înregistrări (câte una pentru fiecare versiune), deci cheia naturală nu mai este unică. Date de valabilitate — valid_from și valid_to — care definesc intervalul temporal în care fiecare versiune a înregistrării era curentă. Un flag de versiune curentă — is_current — care permite recuperarea rapidă a versiunii active fără a filtra pe date. Noua tabelă dimensională #CREATE TABLE dim_client ( client_key NUMBER(10) NOT NULL, client_id NUMBER(10) NOT NULL, nume VARCHAR2(100) NOT NULL, regiune VARCHAR2(50) NOT NULL, agent VARCHAR2(100), clasa_risc VARCHAR2(20), tip_polita VARCHAR2(50), valid_from DATE NOT NULL, valid_to DATE NOT NULL, is_current CHAR(1) DEFAULT \u0026#39;Y\u0026#39; NOT NULL, CONSTRAINT pk_dim_client PRIMARY KEY (client_key) ); CREATE INDEX idx_dim_client_natural ON dim_client (client_id, is_current); CREATE INDEX idx_dim_client_validity ON dim_client (client_id, valid_from, valid_to); CREATE SEQUENCE seq_dim_client START WITH 1 INCREMENT BY 1; client_key este cheia surogat — generată de secvență, niciodată preluată din sistemul sursă. client_id este cheia naturală — servește pentru a lega diferitele versiuni ale aceluiași client.\nvalid_to pentru înregistrarea curentă o fixez la DATE '9999-12-31' — o convenție standard care simplifică interogările temporale. Când cauți înregistrarea validă la o anumită dată, filtrul WHERE data_referinta BETWEEN valid_from AND valid_to funcționează fără cazuri speciale.\nLogica ETL #ETL-ul Tipului 2 are două faze: mai întâi închizi înregistrările care s-au schimbat, apoi inserezi noile versiuni. Ordinea contează — dacă inserezi înainte de a închide, există un moment în care coexistă două versiuni \u0026ldquo;curente\u0026rdquo; ale aceluiași client.\nFaza 1: identificarea și închiderea înregistrărilor modificate #MERGE INTO dim_client d USING ( SELECT s.client_id, s.nume, s.regiune, s.agent, s.clasa_risc, s.tip_polita FROM stg_client s JOIN dim_client d ON s.client_id = d.client_id AND d.is_current = \u0026#39;Y\u0026#39; WHERE (s.regiune != d.regiune OR s.agent != d.agent OR s.clasa_risc != d.clasa_risc OR s.tip_polita != d.tip_polita OR s.nume != d.nume) ) changed ON (d.client_id = changed.client_id AND d.is_current = \u0026#39;Y\u0026#39;) WHEN MATCHED THEN UPDATE SET d.valid_to = TRUNC(SYSDATE) - 1, d.is_current = \u0026#39;N\u0026#39;; WHERE-ul compară fiecare atribut urmărit. Dacă măcar unul este diferit, înregistrarea curentă este închisă: valid_to se setează pe ziua de ieri și is_current devine \u0026lsquo;N\u0026rsquo;.\nO notă practică: compararea cu != nu gestionează NULL-urile. Dacă agent poate fi NULL, ai nevoie de funcții de comparare NULL-safe. În Oracle folosesc DECODE:\nWHERE DECODE(s.regiune, d.regiune, 0, 1) = 1 OR DECODE(s.agent, d.agent, 0, 1) = 1 OR DECODE(s.clasa_risc, d.clasa_risc, 0, 1) = 1 -- ... DECODE tratează două NULL-uri ca egale — exact comportamentul de care ai nevoie.\nFaza 2: inserarea noilor versiuni #INSERT INTO dim_client ( client_key, client_id, nume, regiune, agent, clasa_risc, tip_polita, valid_from, valid_to, is_current ) SELECT seq_dim_client.NEXTVAL, s.client_id, s.nume, s.regiune, s.agent, s.clasa_risc, s.tip_polita, TRUNC(SYSDATE), DATE \u0026#39;9999-12-31\u0026#39;, \u0026#39;Y\u0026#39; FROM stg_client s WHERE NOT EXISTS ( SELECT 1 FROM dim_client d WHERE d.client_id = s.client_id AND d.is_current = \u0026#39;Y\u0026#39; ); Acest INSERT acoperă două cazuri: clienți complet noi (care nu există în dim_client) și clienți a căror versiune curentă tocmai a fost închisă în Faza 1 (care prin urmare nu mai au o înregistrare cu is_current = 'Y').\nvalid_from este data de astăzi. valid_to este \u0026ldquo;sfârșitul timpului\u0026rdquo; — 9999-12-31. client_key este generată de secvență.\nDatele: înainte și după #Să vedem un exemplu concret. Clientul 2001 — \u0026ldquo;Alfa Asigurări Srl\u0026rdquo; — este în regiunea Nord, alocat agentului Rossi, clasă de risc Medie.\nÎn iulie clientul este reatribuit agentului Bianchi. În octombrie clasa de risc se schimbă de la Medie la Înaltă.\nCu Tipul 1 (modelul anterior), în octombrie dim_client conține o singură linie:\nCLIENT_ID NUME REGIUNE AGENT CLASA_RISC --------- -------------------- ------- ------- ---------- 2001 Alfa Asigurări Srl Nord Bianchi Inalta Nicio urmă de Rossi. Nicio urmă de clasa Medie. Pentru DWH, acest client a aparținut întotdeauna agentului Bianchi cu clasă Înaltă.\nCu Tipul 2, în octombrie dim_client conține trei linii:\nKEY CLIENT_ID NUME REGIUNE AGENT CLASA VALID_FROM VALID_TO CURRENT ---- --------- -------------------- ------- ------- ------ ---------- ---------- ------- 1001 2001 Alfa Asigurări Srl Nord Rossi Medie 2025-01-15 2025-07-09 N 1002 2001 Alfa Asigurări Srl Nord Bianchi Medie 2025-07-10 2025-10-04 N 1003 2001 Alfa Asigurări Srl Nord Bianchi Inalta 2025-10-05 9999-12-31 Y Trei versiuni ale aceluiași client. Fiecare versiune spune o parte din poveste: cine era agentul, care era clasa de risc și în ce perioadă. Datele nu se suprapun. Flag-ul is_current identifică versiunea activă.\nInterogările temporale #Acum directorul comercial poate primi răspunsul său.\nCâți clienți în regiunea Nord în iunie? #SELECT COUNT(DISTINCT client_id) AS clienti_nord_iunie FROM dim_client WHERE regiune = \u0026#39;Nord\u0026#39; AND DATE \u0026#39;2025-06-15\u0026#39; BETWEEN valid_from AND valid_to; Interogarea este directă: ia toate înregistrările care erau valide pe 15 iunie 2025 și filtrează pe regiune. Fără CASE WHEN, fără logică condițională, fără aproximări.\nClienți care au schimbat clasa de risc în ultimul an #SELECT c1.client_id, c1.nume, c1.clasa_risc AS clasa_anterioara, c2.clasa_risc AS clasa_actuala, c1.valid_to + 1 AS data_schimbare FROM dim_client c1 JOIN dim_client c2 ON c1.client_id = c2.client_id AND c1.valid_to + 1 = c2.valid_from WHERE c1.clasa_risc != c2.clasa_risc AND c1.valid_to \u0026gt;= ADD_MONTHS(TRUNC(SYSDATE), -12) ORDER BY data_schimbare DESC; Două versiuni consecutive ale aceluiași client, unite prin data de tranziție. Dacă clasa de risc diferă între cele două versiuni, clientul a schimbat clasa. Data schimbării este ziua de după închiderea versiunii anterioare.\nComparație portofoliu Q1 vs Q2 #SELECT regiune, COUNT(DISTINCT CASE WHEN DATE \u0026#39;2025-03-31\u0026#39; BETWEEN valid_from AND valid_to THEN client_id END) AS clienti_q1, COUNT(DISTINCT CASE WHEN DATE \u0026#39;2025-06-30\u0026#39; BETWEEN valid_from AND valid_to THEN client_id END) AS clienti_q2 FROM dim_client WHERE DATE \u0026#39;2025-03-31\u0026#39; BETWEEN valid_from AND valid_to OR DATE \u0026#39;2025-06-30\u0026#39; BETWEEN valid_from AND valid_to GROUP BY regiune ORDER BY regiune; Un singur scan al tabelei, două contorizări distincte filtrate pe dată. CFO-ul are raportul trimestrial — cel real, nu cel care compara Q2 cu el însuși.\nTabela de fapte și cheile surogat #Un punct adesea subestimat: tabela de fapte trebuie să folosească cheia surogat, nu cheia naturală.\nCREATE TABLE fact_dauna ( dauna_key NUMBER(10) NOT NULL, client_key NUMBER(10) NOT NULL, -- FK la versiunea specifică data_key NUMBER(8) NOT NULL, suma NUMBER(15,2), tip_dauna VARCHAR2(50), CONSTRAINT pk_fact_dauna PRIMARY KEY (dauna_key), CONSTRAINT fk_fact_client FOREIGN KEY (client_key) REFERENCES dim_client (client_key) ); client_key din tabela de fapte indică spre versiunea clientului care era curentă în momentul daunei. Dacă o daună survine în mai, când clientul aparținea încă agentului Rossi, faptul indică spre versiunea cu agentul Rossi. Dacă altă daună survine în septembrie, cu clientul deja sub agentul Bianchi, faptul indică spre versiunea cu agentul Bianchi.\nRezultatul este că fiecare fapt este asociat cu contextul dimensional corect pentru momentul în care s-a produs. Interoghezi daunele din mai și vezi agentul Rossi. Interoghezi pe cele din septembrie și vezi agentul Bianchi. Fără nicio logică temporală în interogare — JOIN-ul direct între tabela de fapte și dimensiune returnează contextul corect.\n-- Daune pe agent, cu contextul corect din momentul daunei SELECT d.agent, COUNT(*) AS num_daune, SUM(f.suma) AS suma_totala FROM fact_dauna f JOIN dim_client d ON f.client_key = d.client_key GROUP BY d.agent ORDER BY suma_totala DESC; Fără clauză temporală. JOIN-ul pe cheia surogat face toată munca.\nDimensiunile Tipului 2 #Costul Tipului 2 este creșterea tabelei dimensionale. Cu Tipul 1, fiecare client este o linie. Cu Tipul 2, fiecare client poate avea N linii — câte una pentru fiecare schimbare de atribut urmărit.\nÎn proiectul de asigurări numerele arătau astfel:\nMetrică Valoare Clienți activi ~120.000 Atribute urmărite 4 (regiune, agent, clasă risc, tip poliță) Rata medie de schimbare ~8% din clienți/an Linii dim_client după 1 an ~140.000 Linii dim_client după 3 ani ~180.000 Linii dim_client după 5 ani ~220.000 De la 120K la 220K în cinci ani. O creștere de 83% — care pare mult în procente dar este neglijabilă în termeni absoluți. 220K linii sunt nimic pentru Oracle. Interogarea cu index pe cheia surogat rămâne în ordinul milisecundelor.\nProblema apare când ai milioane de clienți cu rate mari de schimbare. În acel caz monitorizezi creșterea, consideri partiționarea dimensiunii, și mai ales alegi cu grijă care atribute să le urmărești. Nu toate atributele merită Tip 2. Telefonul clientului? Tip 1, suprascriere. Regiunea comercială? Tip 2, pentru că impactează analiza cifrei de afaceri.\nAlegerea atributelor de urmărit cu Tip 2 este o decizie de business, nu tehnică. Întreabă business-ul: \u0026ldquo;Dacă acest câmp se schimbă, aveți nevoie să știți care era valoarea anterioară?\u0026rdquo; Dacă răspunsul este da, este Tip 2. Dacă este nu, este Tip 1.\nCând nu e nevoie de Tipul 2 #Nu toate dimensiunile au nevoie de istorie. Am văzut proiecte în care fiecare dimensiune era Tip 2 \u0026ldquo;pentru siguranță\u0026rdquo; — rezultatul era un model inutil de complex, ETL-uri lente, și nimeni care să fi interogat vreodată istoria dimensiunii \u0026ldquo;tip_plată\u0026rdquo; sau \u0026ldquo;canal_vânzare\u0026rdquo;.\nTipul 2 are un cost: complexitatea ETL-ului, creșterea tabelei, necesitatea de a gestiona cheile surogat în tabela de fapte. Este un cost care merită plătit când business-ul are nevoie de istorie. Dacă nu are, Tipul 1 este alegerea corectă.\nSunt și cazuri în care Tipul 2 nu este suficient. Dacă trebuie să știi nu doar ce s-a schimbat ci și cine a făcut schimbarea și de ce, atunci ai nevoie de un audit trail — o tabelă separată cu un log complet al modificărilor. Tipul 2 urmărește versiunile, nu cauzele.\nIar pentru dimensiuni cu schimbări foarte frecvente — prețuri care se schimbă zilnic, scoruri care se actualizează orar — Tipul 2 poate genera o creștere nesustenabilă. În acele cazuri se evaluează Tipul 6 (o combinație de Tipurile 1, 2 și 3) sau abordări de mini-dimensiune.\nDar pentru cazul cel mai frecvent — date master de clienți, produse, angajați, puncte de vânzare — Tipul 2 este instrumentul potrivit. Suficient de simplu pentru a fi implementat fără framework-uri exotice, suficient de puternic pentru a reda business-ului dimensiunea care-i lipsea: timpul.\nCe am învățat #Directorul comercial nu știa că are nevoie de istorie până când a avut nevoie de ea. Și când a avut nevoie, DWH-ul nu o avea.\nAcesta este punctul. Nu implementezi Tipul 2 pentru că \u0026ldquo;e best practice\u0026rdquo; sau pentru că \u0026ldquo;Kimball spune așa în capitolul 5\u0026rdquo;. Îl implementezi pentru că un data warehouse fără istorie este o bază de date operațională cu o star schema lipită deasupra. Funcționează pentru rapoartele lunii curente, dar nu răspunde la întrebarea pe care mai devreme sau mai târziu cineva o va pune: \u0026ldquo;Cum era înainte?\u0026rdquo;\nÎntrebarea vine întotdeauna. Singura întrebare este dacă DWH-ul tău este pregătit să răspundă.\nGlosar #Cheie surogat — Identificator numeric generat de data warehouse, distinct de cheia naturală a sistemului sursă. În SCD Tip 2 este esențială deoarece aceeași înregistrare poate avea mai multe versiuni, iar cheia naturală nu mai este unică.\nFact table — Tabela centrală a star schema-ului care conține măsurile numerice (sume, cantități, contorizări) și cheile externe către tabelele dimensionale. Fiecare linie reprezintă un eveniment sau o tranzacție de business.\nKimball — Ralph Kimball, autorul metodologiei de proiectare a data warehouse-ului bazată pe dimensional modeling, star schema și procese ETL bottom-up. Framework-ul său clasifică Slowly Changing Dimensions în tipurile de la 0 la 7.\nMERGE — Instrucțiune SQL care combină INSERT și UPDATE într-o singură operațiune: dacă înregistrarea există o actualizează, dacă nu există o inserează. În Oracle este cunoscută și ca \u0026ldquo;upsert\u0026rdquo; și este mecanismul de bază al ETL-ului pentru dimensiunile SCD.\nStar schema — Model de date tipic pentru data warehouse: o fact table centrală conectată la mai multe tabele dimensionale prin chei externe. Simplifică interogările analitice și optimizează performanța agregărilor.\n","date":"11 noiembrie 2025","permalink":"https://ivanluminaria.com/ro/posts/data-warehouse/scd-tipo-2/","section":"Database Strategy","summary":"\u003cp\u003eDirectorul comercial apare la ședința de luni dimineața cu o întrebare simplă: \u0026ldquo;Câți clienți aveam în regiunea Nord în iunie trecut?\u0026rdquo;\u003c/p\u003e\n\u003cp\u003eRăspunsul DWH-ului: liniște.\u003c/p\u003e\n\u003cp\u003eNu pentru că sistemul era căzut, sau pentru că lipsea tabela. Datele erau acolo, tehnic vorbind. Dar erau greșite. DWH-ul returna clienții care \u003cem\u003eastăzi\u003c/em\u003e sunt în regiunea Nord — nu pe cei care erau acolo în iunie. Pentru că în fiecare noapte, procesul de încărcare suprascria datele master ale clienților cu valorile curente, ștergând orice urmă a ceea ce fusese înainte.\u003c/p\u003e","title":"SCD Tip 2: istoria pe care business-ul nu știa că o vrea"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/csv-export/","section":"Tags","summary":"","title":"Csv-Export"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/multi-instance/","section":"Tags","summary":"","title":"Multi-Instance"},{"content":"Ticket-ul spunea: „Avem nevoie de un export CSV din tabelul ordini al aplicației de gestiune. Până la ora 14.\u0026quot;\nEra 11 dimineața. Trei ore pentru un SELECT cu INTO OUTFILE — treabă de cinci minute, mă gândeam. Apoi am deschis VPN-ul, m-am conectat la server și am înțeles că cinci minute n-o să fie de ajuns.\nServerul era o mașină CentOS 7 cu patru instanțe MySQL. Patru. Pe același host, cu patru servicii systemd diferite, patru porturi diferite, patru socket-uri Unix diferite, patru directoare de date diferite. Un setup pe care cineva îl pusese în picioare cu ani în urmă — probabil ca să economisească un al doilea server — și pe care de atunci nimeni nu-l mai atinsese și nici nu-l documentase.\nPrima problemă nu era query-ul. Prima problemă era: la care dintre cele patru instanțe trebuie să mă conectez?\nMediul: patru MySQL, un singur server #Mediile multi-instanță pe MySQL nu sunt atât de rare pe cât s-ar crede. Le întâlnesc mai des decât mi-aș dori, mai ales în companiile mici și medii unde serverele sunt puține și aplicațiile sunt multe. Logica e simplă: în loc să cumperi patru servere, cumperi unul puternic și rulezi patru instanțe MySQL pe el, fiecare cu baza ei de date, portul ei, fișierul ei de configurare.\nRezultatul funcționează, până când trebuie să faci mentenanță. Iar mentenanța pe un multi-instanță, fără documentație, e un exercițiu de arheologie informatică.\nPe acel server, situația era următoarea:\nsystemctl list-units --type=service | grep mysql mysqld.service loaded active running MySQL Server (porta 3306) mysqld-app2.service loaded active running MySQL Server (porta 3307) mysqld-reporting.service loaded active running MySQL Server (porta 3308) mysqld-legacy.service loaded active running MySQL Server (porta 3309) Patru servicii. Numele erau vag sugestive — „app2\u0026quot;, „reporting\u0026quot;, „legacy\u0026quot; — dar ticket-ul vorbea despre „aplicația de gestiune\u0026quot; fără să specifice care instanță găzduiește acea bază de date. Niciun wiki intern, niciun fișier README pe server, niciun comentariu în fișierele de configurare.\nGăsirea instanței corecte #Primul pas a fost să identific care instanță conține baza de date cu comenzile. Tehnica e mereu aceeași: pornești de la serviciul systemd, urci la fișierul de configurare, de acolo citești portul și socket-ul.\nsystemctl cat mysqld-app2.service | grep ExecStart ExecStart=/usr/sbin/mysqld --defaults-file=/etc/mysql/app2.cnf Fiecare serviciu avea un my.cnf diferit. Le-am verificat pe toate patru:\ngrep -E \u0026#34;^(port|socket|datadir)\u0026#34; /etc/mysql/app2.cnf port = 3307 socket = /var/run/mysqld/mysqld-app2.sock datadir = /data/mysql-app2 Pentru fiecare instanță am notat portul, socket-ul și datadir-ul. Apoi am făcut o trecere rapidă:\nmysql --socket=/var/run/mysqld/mysqld.sock -u root -p -e \u0026#34;SHOW DATABASES;\u0026#34; 2\u0026gt;/dev/null mysql --socket=/var/run/mysqld/mysqld-app2.sock -u root -p -e \u0026#34;SHOW DATABASES;\u0026#34; 2\u0026gt;/dev/null mysql --socket=/var/run/mysqld/mysqld-reporting.sock -u root -p -e \u0026#34;SHOW DATABASES;\u0026#34; 2\u0026gt;/dev/null mysql --socket=/var/run/mysqld/mysqld-legacy.sock -u root -p -e \u0026#34;SHOW DATABASES;\u0026#34; 2\u0026gt;/dev/null Baza de date gestionale_prod era pe a doua instanță — cea de pe portul 3307 cu socket-ul /var/run/mysqld/mysqld-app2.sock.\nUn detaliu care pare banal dar care într-un mediu multi-instanță face diferența: când te conectezi la MySQL specificând doar -h localhost, clientul nu folosește TCP. Folosește socket-ul Unix implicit, care aproape întotdeauna e cel al instanței primare de pe portul 3306. Dacă baza de date pe care o cauți e pe altă instanță, te conectezi la cea greșită fără să-ți dai seama.\nConexiunea și verificarea #Odată identificată instanța, m-am conectat specificând explicit socket-ul:\nmysql --socket=/var/run/mysqld/mysqld-app2.sock -u root -p Primul lucru după autentificare: verificarea că sunt pe instanța corectă.\nSHOW VARIABLES LIKE \u0026#39;port\u0026#39;; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | port | 3307 | +---------------+-------+ SELECT DATABASE(); USE gestionale_prod; SHOW TABLES LIKE \u0026#39;%ordini%\u0026#39;; +----------------------------------+ | Tables_in_gestionale_prod | +----------------------------------+ | ordini | | ordini_dettaglio | | ordini_storico | +----------------------------------+ Portul 3307, baza de date prezentă, tabelul ordini la locul lui. Conexiunea era cea corectă.\nVerificarea portului pare paranoia, dar nu este. Într-un mediu cu patru instanțe, a confunda care socket duce la care port e mai ușor decât crezi. Iar eroarea o descoperi doar când datele pe care le exporți nu sunt cele așteptate — sau mai rău, când faci o modificare crezând că ești pe baza de test și descoperi că erai în producție.\nPrima tentativă: INTO OUTFILE #Query-ul era simplu. Solicitantul voia comenzile din ultimul trimestru cu sumă, client și dată:\nSELECT o.id_ordine, o.data_ordine, c.ragione_sociale, o.importo_totale FROM ordini o JOIN clienti c ON o.id_cliente = c.id_cliente WHERE o.data_ordine \u0026gt;= \u0026#39;2025-07-01\u0026#39; ORDER BY o.data_ordine; Primul instinct a fost să folosesc `INTO OUTFILE` , metoda nativă a MySQL-ului pentru a scrie rezultate în fișier:\nSELECT o.id_ordine, o.data_ordine, c.ragione_sociale, o.importo_totale FROM ordini o JOIN clienti c ON o.id_cliente = c.id_cliente WHERE o.data_ordine \u0026gt;= \u0026#39;2025-07-01\u0026#39; ORDER BY o.data_ordine INTO OUTFILE \u0026#39;/tmp/export_ordini.csv\u0026#39; FIELDS TERMINATED BY \u0026#39;,\u0026#39; ENCLOSED BY \u0026#39;\u0026#34;\u0026#39; LINES TERMINATED BY \u0026#39;\\n\u0026#39;; Răspunsul MySQL-ului a fost sec:\nERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv option so it cannot execute this statement Iată zidul.\nsecure-file-priv : directiva care blochează totul (și face bine) #Variabila secure_file_priv este modul în care MySQL limitează operațiunile de citire și scriere pe fișiere. Controlează unde LOAD DATA INFILE, SELECT INTO OUTFILE și funcția LOAD_FILE() pot opera.\nSHOW VARIABLES LIKE \u0026#39;secure_file_priv\u0026#39;; +------------------+------------------------+ | Variable_name | Value | +------------------+------------------------+ | secure_file_priv | /var/lib/mysql-files/ | +------------------+------------------------+ Această variabilă are trei moduri:\nO cale specifică (ex. /var/lib/mysql-files/): operațiunile pe fișiere funcționează, dar doar în acel director Șir gol (\u0026quot;\u0026quot;): nicio restricție — MySQL poate citi și scrie oriunde utilizatorul său de sistem are permisiuni NULL: operațiunile pe fișiere sunt complet dezactivate Instanța mea era configurată cu o cale specifică. Tentativa de a scrie în /tmp/ fusese blocată pentru că /tmp/ nu este /var/lib/mysql-files/.\nPrima reacție — cea pe care o văd la mulți — ar fi fost: „schimbăm secure-file-priv la șir gol în my.cnf și repornim\u0026quot;. Nu. Absolut nu. Pe un server de producție cu patru instanțe MySQL, repornirea unei instanțe la 11:30 dimineața pentru un export CSV nu e o opțiune. Iar dezactivarea unei protecții de securitate nu e niciodată răspunsul corect, nici măcar în urgență.\nAlternativa evidentă era să scriu fișierul în directorul autorizat:\nSELECT o.id_ordine, o.data_ordine, c.ragione_sociale, o.importo_totale FROM ordini o JOIN clienti c ON o.id_cliente = c.id_cliente WHERE o.data_ordine \u0026gt;= \u0026#39;2025-07-01\u0026#39; ORDER BY o.data_ordine INTO OUTFILE \u0026#39;/var/lib/mysql-files/export_ordini.csv\u0026#39; FIELDS TERMINATED BY \u0026#39;,\u0026#39; ENCLOSED BY \u0026#39;\u0026#34;\u0026#39; LINES TERMINATED BY \u0026#39;\\n\u0026#39;; Dar era o altă problemă. Directorul /var/lib/mysql-files/ era cel al instanței primare (portul 3306). Instanța de pe portul 3307 avea datadir-ul separat în /data/mysql-app2/, iar secure_file_priv-ul ei indica spre /data/mysql-app2/files/ — un director care nu exista și pe care nimeni nu-l crease vreodată.\nAș fi putut crea directorul, să atribui permisiunile corecte utilizatorului mysql și să scriu acolo. Dar la acel punct deja pierdeam timp. Și există o metodă mai curată.\nSoluția: export din shell cu clientul mysql #Când INTO OUTFILE e blocat sau incomod, soluția cea mai practică e să ocolești complet mecanismul de scriere în fișier al MySQL-ului și să folosești clientul din linia de comandă pentru a redirecționa output-ul.\nTrucul stă în opțiunile -B (batch mode) și -e (execute):\nmysql --socket=/var/run/mysqld/mysqld-app2.sock \\ -u root -p \\ -B -e \u0026#34; SELECT o.id_ordine, o.data_ordine, c.ragione_sociale, o.importo_totale FROM ordini o JOIN clienti c ON o.id_cliente = c.id_cliente WHERE o.data_ordine \u0026gt;= \u0026#39;2025-07-01\u0026#39; ORDER BY o.data_ordine \u0026#34; gestionale_prod \u0026gt; /tmp/export_ordini.tsv Opțiunea -B produce un output tab-separated fără chenarele ASCII ale tabelelor. Rezultatul e un fișier TSV curat care se deschide fără probleme în orice foaie de calcul.\nDacă e nevoie de un CSV real cu virgule ca separator, e suficient un pas cu sed:\nmysql --socket=/var/run/mysqld/mysqld-app2.sock \\ -u root -p \\ -B -N -e \u0026#34; SELECT o.id_ordine, o.data_ordine, c.ragione_sociale, o.importo_totale FROM ordini o JOIN clienti c ON o.id_cliente = c.id_cliente WHERE o.data_ordine \u0026gt;= \u0026#39;2025-07-01\u0026#39; ORDER BY o.data_ordine \u0026#34; gestionale_prod | sed \u0026#39;s/\\t/,/g\u0026#39; \u0026gt; /tmp/export_ordini.csv Opțiunea -N elimină rândul de antet cu numele coloanelor. Dacă vrei antetul, scoate flag-ul.\nFișierul a fost gata în mai puțin de un minut. 12.400 de rânduri, 1,2 MB. L-am copiat pe mașina mea cu scp, am verificat deschiderea în LibreOffice Calc și l-am trimis solicitantului. Era 11:45. Ticket-ul care trebuia să dureze cinci minute consumase patruzeci și cinci — dar cel puțin nu repornisem nicio instanță.\nDe ce să nu dezactivezi secure-file-priv #Tentația de a seta secure_file_priv = \u0026quot;\u0026quot; e puternică, mai ales pe servere de dezvoltare sau pe mașini unde „oricum suntem doar noi\u0026quot;. Problema e că acea protecție există dintr-un motiv precis.\nFără secure_file_priv, un utilizator MySQL cu privilegiul FILE poate:\nCiti orice fișier accesibil utilizatorului de sistem mysql — inclusiv /etc/passwd, fișiere de configurare, chei SSH dacă permisiunile nu sunt blindate Scrie fișiere oriunde utilizatorul mysql are permisiuni de scriere — inclusiv în webroot-ul unui eventual Apache sau Nginx de pe același server Într-un context de SQL injection , privilegiul FILE combinat cu un secure_file_priv gol e o ușă deschisă. Atacatorul poate citi fișiere de sistem, scrie web shell-uri, face escaladare de privilegii. Nu e teorie — este unul dintre vectorii de atac cei mai documentați în testele de penetrare pe aplicații web cu MySQL în spate.\nRegula e simplă: secure_file_priv se configurează cu o cale specifică, se creează directoarele necesare pentru fiecare instanță în momentul setup-ului și se lasă acolo. Dacă trebuie să faci exporturi ocazionale, clientul mysql din shell face aceeași treabă fără să atingi configurația de securitate.\nLecții de la un ticket de cinci minute #Acel ticket mi-a reamintit trei lucruri pe care în treizeci de ani de lucru cu bazele de date le-am văzut confirmate de sute de ori.\nPrimul: într-un mediu multi-instanță, primul pas e întotdeauna identificarea instanței. Pare evident, dar cantitatea de erori care se nasc din conectarea la instanța greșită — crezând că ești în altă parte — e impresionantă. Un SHOW VARIABLES LIKE 'port' după fiecare conectare nu e paranoia, e igienă operațională.\nAl doilea: secure-file-priv nu e un obstacol, e o protecție. Când te blochează, nu e momentul s-o dezactivezi. E momentul să folosești o cale alternativă sau o metodă alternativă. Directiva există pentru că MySQL în mâinile unui utilizator cu privilegiul FILE și fără nicio constrângere pe filesystem e un risc concret.\nAl treilea: clientul mysql din linia de comandă e mai puternic decât îi recunosc majoritatea DBA-ilor. Cu -B, -N, -e și o pipe spre sed sau awk, poți face exporturi, transformări și automatizări fără să atingi vreodată INTO OUTFILE. E mai puțin elegant, poate. Dar funcționează mereu, nu necesită permisiuni speciale și nu depinde de faptul că cineva a creat directorul potrivit cu șase luni înainte.\nCSV-ul a ajuns la 11:45. Solicitantul n-a aflat niciodată că în spatele a cinci coloane și 12.400 de rânduri se ascundeau patruzeci și cinci de minute de arheologie de sistem. Dar așa funcționează ticket-urile: cine le deschide vede rezultatul, cine le rezolvă vede drumul.\nGlosar #secure-file-priv — Directivă de securitate MySQL care limitează directoarele în care serverul poate citi și scrie fișiere prin INTO OUTFILE, LOAD DATA INFILE și LOAD_FILE().\nUnix Socket — Mecanism de comunicare locală între procese pe sisteme Linux, folosit de MySQL ca metodă de conectare implicită la localhost.\nINTO OUTFILE — Clauză SQL MySQL pentru exportul rezultatelor interogărilor direct într-un fișier pe filesystem-ul serverului. Supusă restricțiilor secure-file-priv.\nsystemd — Manager de servicii pe Linux modern, folosit pentru gestionarea instanțelor multiple MySQL pe același server prin unit file separate.\nSQL Injection — Tehnică de atac care inserează cod SQL malițios în input-urile unei aplicații. Directiva secure-file-priv contribuie la mitigarea impactului acesteia.\n","date":"4 noiembrie 2025","permalink":"https://ivanluminaria.com/ro/posts/mysql/mysql-multi-istanza-secure-file-priv/","section":"Database Strategy","summary":"\u003cp\u003eTicket-ul spunea: „Avem nevoie de un export CSV din tabelul ordini al aplicației de gestiune. Până la ora 14.\u0026quot;\u003c/p\u003e\n\u003cp\u003eEra 11 dimineața. Trei ore pentru un SELECT cu INTO OUTFILE — treabă de cinci minute, mă gândeam. Apoi am deschis VPN-ul, m-am conectat la server și am înțeles că cinci minute n-o să fie de ajuns.\u003c/p\u003e\n\u003cp\u003eServerul era o mașină CentOS 7 cu patru instanțe MySQL. Patru. Pe același host, cu patru servicii \u003cspan class=\"glossary-tip\" tabindex=\"0\" data-glossary-desc=\"Sistem de inițializare și manager de servicii pe Linux, folosit pentru gestionarea instanțelor multiple MySQL/MariaDB pe același server prin unit file separate.\" data-glossary-url=\"/ro/glossary/systemd/\" data-glossary-more=\"Citește mai mult →\"\u003esystemd\u003c/span\u003e\n diferite, patru porturi diferite, patru socket-uri Unix diferite, patru directoare de date diferite. Un setup pe care cineva îl pusese în picioare cu ani în urmă — probabil ca să economisească un al doilea server — și pe care de atunci nimeni nu-l mai atinsese și nici nu-l documentase.\u003c/p\u003e","title":"MySQL multi-instanță: un ticket, un CSV și zidul secure-file-priv"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/secure-file-priv/","section":"Tags","summary":"","title":"Secure-File-Priv"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/socket/","section":"Tags","summary":"","title":"Socket"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/systemd/","section":"Tags","summary":"","title":"Systemd"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/troubleshooting/","section":"Tags","summary":"","title":"Troubleshooting"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/explain/","section":"Tags","summary":"","title":"Explain"},{"content":"Zilele trecute un coleg imi trimite o captura de ecran pe Teams. Un query care ruleaza pe o tabela de 2 milioane de randuri, 45 de secunde timp de executie. Imi scrie:\n\u0026ldquo;Am facut EXPLAIN ANALYZE, dar nu inteleg ce e in neregula. Planul pare corect.\u0026rdquo;\nSpoiler: planul nu era deloc corect. Optimizatorul alesese un nested loop join unde era nevoie de un hash join , iar motivul era banal — statistici neactualizate. Dar ca sa ajung acolo a trebuit sa citesc planul rand cu rand, si atunci mi-am dat seama ca majoritatea DBA-ilor pe care ii cunosc folosesc EXPLAIN ANALYZE ca pe un oracol binar: daca timpul e mare, query-ul e lent. Sfarsitul analizei.\nNu. EXPLAIN ANALYZE e un instrument de diagnostic, nu un verdict. Trebuie sa stii sa-l citesti.\n🔧 EXPLAIN, EXPLAIN ANALYZE, EXPLAIN (ANALYZE, BUFFERS): trei lucruri diferite #Sa incepem cu bazele, pentru ca confuzia e mai raspandita decat ai crede.\nEXPLAIN singur arata planul estimat. Optimizatorul decide ce ar face, dar nu executa nimic. Util pentru a intelege strategia, inutil pentru a intelege realitatea.\nEXPLAIN SELECT * FROM orders o JOIN customers c ON c.id = o.customer_id WHERE o.created_at \u0026gt; \u0026#39;2025-01-01\u0026#39;; EXPLAIN ANALYZE executa query-ul si adauga timpii reali. Acum vezi cat a durat fiecare nod, cate randuri a returnat efectiv. Dar lipseste o piesa.\nEXPLAIN ANALYZE SELECT * FROM orders o JOIN customers c ON c.id = o.customer_id WHERE o.created_at \u0026gt; \u0026#39;2025-01-01\u0026#39;; EXPLAIN (ANALYZE, BUFFERS) e ceea ce folosesc intotdeauna. Adauga informatii despre cate pagini de disc au fost citite, cate erau in cache (shared hit) si cate au trebuit incarcate de pe disc (shared read). Fara BUFFERS conduci noaptea fara faruri.\nEXPLAIN (ANALYZE, BUFFERS) SELECT * FROM orders o JOIN customers c ON c.id = o.customer_id WHERE o.created_at \u0026gt; \u0026#39;2025-01-01\u0026#39;; Regula personala: daca cineva imi trimite un EXPLAIN fara BUFFERS, i-l trimit inapoi.\n📖 Anatomia unui nod: ce sa citesti si in ce ordine #Un plan de executie e un arbore. Fiecare nod arata asa:\n-\u0026gt; Hash Join (cost=1234.56..5678.90 rows=50000 width=120) (actual time=12.345..89.012 rows=48750 loops=1) Buffers: shared hit=1200 read=3400 Iata ce sa urmaresti:\ncost — sunt doua numere separate de ... Primul e costul de startup (cat inainte de a returna primul rand), al doilea e costul total estimat. Sunt unitati arbitrare ale optimizatorului, nu milisecunde. Servesc pentru a compara planuri alternative, nu pentru a masura performanta absoluta.\nrows — randurile estimate de optimizator. Compara-le cu actual rows. Daca e un ordin de marime diferenta, ai gasit problema.\nactual time — timp real in milisecunde. Din nou doua valori: startup si total. Atentie la campul loops: daca loops=10, timpul total trebuie inmultit cu 10.\nBuffers — shared hit sunt paginile gasite in memorie, shared read cele citite de pe disc. Daca read domina, working set-ul tau nu incape in RAM.\n🚨 Semnalul de alarma numarul unu: randuri estimate vs randuri reale #Ma intorc la cazul colegului meu. Planul arata:\n-\u0026gt; Nested Loop (cost=0.87..45678.12 rows=150 width=200) (actual time=0.034..44890.123 rows=1950000 loops=1) Optimizatorul estima 150 de randuri. In realitate au venit aproape 2 milioane.\nCand estimarea e gresita cu 4 ordine de marime, planul e inevitabil gresit. Optimizatorul a ales un nested loop pentru ca a crezut ca itereaza peste 150 de randuri. Un nested loop pe 150 de randuri e fulgerator de rapid. Pe 2 milioane e un dezastru.\nUn hash join sau merge join ar fi fost alegerea corecta. Dar optimizatorul nu putea sti asta cu statisticile pe care le avea.\nRegula practica: daca raportul dintre randurile estimate si cele reale depaseste 10x, ai o problema de statistici. Peste 100x, planul e aproape sigur gresit.\n🔍 De ce mint statisticile #PostgreSQL mentine statistici despre tabele in pg_statistic (citibile prin pg_stats). Aceste statistici includ:\ndistributia valorilor (most common values) histograma valorilor numarul de valori distincte procentul de NULL Optimizatorul foloseste aceste informatii pentru a estima selectivitatea fiecarei conditii WHERE si cardinalitatea fiecarui join.\nProblema? Statisticile se actualizeaza cu `ANALYZE` — care poate fi manual sau gestionat de autovacuum. Dar autovacuum-ul lanseaza ANALYZE doar cand numarul de randuri modificate depaseste un prag:\nthreshold = autovacuum_analyze_threshold + autovacuum_analyze_scale_factor × n_live_tuples Implicit: 50 de randuri + 10% din randurile vii. Pe o tabela de 2 milioane de randuri, sunt necesare 200.000 de modificari inainte ca ANALYZE-ul automat sa se declanseze.\nIn cazul colegului meu, tabela orders crescuse de la 500.000 la 2 milioane de randuri in trei saptamani — un import masiv dintr-un sistem legacy. Autovacuum-ul nu actualizase statisticile pentru ca 10% din 500.000 (dimensiunea cunoscuta) era 50.000, iar randurile fusesera inserate in loturi care individual nu depasisera pragul.\nRezultat: optimizatorul ragiona inca ca si cum tabela ar fi avut 500.000 de randuri cu vechea distributie a valorilor.\n🛠️ Actualizarea statisticilor: primul lucru de facut #Solutia imediata era evidenta:\nANALYZE orders; Dupa ANALYZE, am relansat query-ul cu EXPLAIN (ANALYZE, BUFFERS):\n-\u0026gt; Hash Join (cost=8500.00..32000.00 rows=1940000 width=200) (actual time=120.000..2800.000 rows=1950000 loops=1) Buffers: shared hit=28000 read=4500 De la 45 de secunde la sub 3 secunde. Optimizatorul alesese un hash join, estimarea randurilor era corecta, si planul era complet diferit.\nDar nu m-am oprit aici. Daca problema a aparut o data, va aparea din nou.\n📊 default_statistics_target: cand 100 nu e suficient #PostgreSQL colecteaza 100 de valori de esantion pe coloana implicit. Pentru tabele mici sau cu distributie uniforma, e suficient. Pentru tabele mari cu distributie neuniforma, 100 de esantioane pot da o reprezentare distorsionata.\nIn cazul tabelei orders, coloana customer_id avea o distributie foarte asimetrica: 5% din clienti generau 60% din comenzi. Cu 100 de esantioane, optimizatorul nu capta aceasta asimetrie.\nSolutia:\nALTER TABLE orders ALTER COLUMN customer_id SET STATISTICS 500; ANALYZE orders; Dupa ce am crescut target -ul la 500, estimarile de cardinalitate ale optimizatorului pentru join-urile cu customers au devenit mult mai precise.\nRegula: daca o coloana e folosita frecvent in WHERE sau JOIN si are distributie neuniforma, creste target-ul. 500 e un bun punct de plecare. Poti ajunge la 1000, dar peste aceasta valoare rareori ajuta si incetineste ANALYZE-ul insusi.\n⚠️ Cand sa fortezi plannerul: enable_nestloop si enable_hashjoin #Uneori, chiar si cu statistici actualizate, optimizatorul ia un drum gresit. Se intampla cu query-uri complexe, multe tabele in join, sau cand corelatia intre coloane inseala estimarile.\nPostgreSQL ofera parametri pentru a dezactiva strategii specifice:\nSET enable_nestloop = off; Asta forteaza optimizatorul sa nu foloseasca nested loop. Nu e o solutie, e un plasture de diagnostic. Daca dezactivezi nested loop-ul si query-ul trece de la 45 de secunde la 3 secunde, ai confirmat ca problema era alegerea join-ului. Dar nu poti lasa enable_nestloop = off in productie pentru ca exista o mie de query-uri unde nested loop-ul e alegerea corecta.\nFolosesc acesti parametri doar in doua scenarii:\nDiagnostic: pentru a confirma care strategie de join e problema Urgenta: cand business-ul e blocat si trebuie sa repornesti un query critic in timp ce cauti solutia reala Dupa diagnostic, fix-ul corect e intotdeauna pe statistici, indecsi sau rescrierea query-ului.\n📋 Workflow-ul meu cand un query e lent #Dupa treizeci de ani facand aceasta meserie, procesul meu a devenit aproape mecanic:\n1. EXPLAIN (ANALYZE, BUFFERS) — intotdeauna cu BUFFERS. Salvez output-ul complet, nu doar ultimele randuri.\n2. Caut discrepanta de randuri — compar rows= estimat cu actual rows= real pe fiecare nod. Incep de la nodurile frunza si urc spre radacina. Prima discrepanta semnificativa e aproape intotdeauna cauza.\n3. Verific statisticile — ma uit la pg_stats pentru coloanele implicate. Verific last_autoanalyze si last_analyze in pg_stat_user_tables. Daca ultimul ANALYZE e vechi, il lansez si reevaluez.\n4. Evaluez BUFFERS — daca shared read e foarte mare fata de shared hit, problema ar putea fi I/O, nu planul. In acel caz fix-ul e shared_buffers sau working set-ul pur si simplu nu incape in RAM.\n5. Testez alternative — daca statisticile sunt actualizate dar planul e inca gresit, folosesc enable_nestloop, enable_hashjoin, enable_mergejoin pentru a intelege care strategie functioneaza mai bine. Apoi incerc sa ghidez optimizatorul spre acea strategie cu indecsi sau rescriere.\nNimic spectaculos. Niciun truc magic. Doar citirea sistematica a planului, un rand pe rand.\n💬 Lectia din acea zi #Colegul meu, dupa ce a vazut diferenta, mi-a zis: \u0026ldquo;Deci era de ajuns un ANALYZE?\u0026rdquo;\nDa si nu. In acel caz specific, da. Dar ideea nu e comanda. Ideea e sa stii sa citesti planul ca sa intelegi unde sa te uiti. EXPLAIN ANALYZE iti da datele. Tu trebuie sa le interpretezi.\nAm vazut DBA cu ani de experienta lansand EXPLAIN ANALYZE, uitandu-se la timpul total de la sfarsit, si zicand \u0026ldquo;query-ul e lent\u0026rdquo;. E ca si cum ai lua temperatura unui pacient si ai zice \u0026ldquo;are febra\u0026rdquo;. Da, dar de la ce?\nPlanul de executie iti spune de la ce. Fiecare nod e un organ. Randurile estimate fata de cele reale sunt valorile de laborator. Buffer-urile sunt radiografiile. Si ANALYZE-ul e antibioticul care rezolva 70% din cazuri.\nDar pentru acel 30% ramas, trebuie sa citesti. Rand cu rand. Nod cu nod. Nu exista scurtatura.\nGlosar #Execution Plan — secventa de operatii (scan, join, sort) pe care baza de date o alege pentru a rezolva o interogare SQL. Se vizualizeaza cu EXPLAIN si EXPLAIN ANALYZE.\nNested Loop — strategie de join care pentru fiecare rand din tabelul extern cauta corespondentele in tabelul intern. Ideala pentru putine randuri, dezastruoasa pe volume mari cand este aleasa din greseala de optimizator.\nHash Join — strategie de join care construieste o hash table din tabelul mai mic si apoi scaneaza tabelul mai mare cautand corespondente cu lookup-uri O(1). Eficienta pe volume mari fara indexuri.\nANALYZE — comanda PostgreSQL care colecteaza statistici despre distributia datelor in tabele, folosite de optimizator pentru a estima cardinalitatea si a alege planul de executie.\ndefault_statistics_target — parametrul PostgreSQL care defineste cate esantioane sa colecteze per coloana in timpul ANALYZE. Valoarea implicita este 100; pe coloane cu distributie asimetrica este recomandat sa fie crescut la 500-1000.\n","date":"28 octombrie 2025","permalink":"https://ivanluminaria.com/ro/posts/postgresql/explain-analyze-postgresql/","section":"Database Strategy","summary":"\u003cp\u003eZilele trecute un coleg imi trimite o captura de ecran pe Teams. Un query care ruleaza pe o tabela de 2 milioane de randuri, 45 de secunde timp de executie. Imi scrie:\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003e\u0026ldquo;Am facut EXPLAIN ANALYZE, dar nu inteleg ce e in neregula. Planul pare corect.\u0026rdquo;\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eSpoiler: planul nu era deloc corect. Optimizatorul alesese un \u003cspan class=\"glossary-tip\" tabindex=\"0\" data-glossary-desc=\"Nested Loop Join — strategia de join care scaneaza tabelul intern pentru fiecare rand al tabelului extern, ideala pentru seturi mici de date cu index.\" data-glossary-url=\"/ro/glossary/nested-loop/\" data-glossary-more=\"Citește mai mult →\"\u003enested loop\u003c/span\u003e\n join unde era nevoie de un \u003cspan class=\"glossary-tip\" tabindex=\"0\" data-glossary-desc=\"Hash Join — strategie de join optimizata pentru volume mari de date, bazata pe o hash table construita in memorie.\" data-glossary-url=\"/ro/glossary/hash-join/\" data-glossary-more=\"Citește mai mult →\"\u003ehash join\u003c/span\u003e\n, iar motivul era banal — statistici neactualizate. Dar ca sa ajung acolo a trebuit sa citesc planul rand cu rand, si atunci mi-am dat seama ca majoritatea DBA-ilor pe care ii cunosc folosesc EXPLAIN ANALYZE ca pe un oracol binar: daca timpul e mare, query-ul e lent. Sfarsitul analizei.\u003c/p\u003e","title":"EXPLAIN ANALYZE nu e suficient: cum sa citesti cu adevarat un plan de executie PostgreSQL"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/optimizer/","section":"Tags","summary":"","title":"Optimizer"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/fact-table/","section":"Tags","summary":"","title":"Fact-Table"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/grain/","section":"Tags","summary":"","title":"Grain"},{"content":"Ședința începuse bine. Directorul comercial al unei companii de distribuție industrială — vreo șaizeci de milioane cifră de afaceri, trei mii de clienți activi, catalog cu douăsprezece mii de referințe — deschisese prezentarea noului data warehouse cu un zâmbet. Cifrele se potriveau, dashboard-urile arătau bine, totalurile lunare pe agent și pe zonă băteau cu contabilitatea.\nApoi cineva a pus întrebarea greșită. Sau mai bine zis, pe cea corectă.\n\u0026ldquo;Pot să văd cât a cumpărat clientul Bianchi în luna martie, linie cu linie, produs cu produs?\u0026rdquo;\nLiniște.\nResponsabilul BI s-a uitat la mine. Eu m-am uitat la ecran. Ecranul arăta o fact table cu un rând per client per lună: sumă totală facturată, cantitate totală, număr de facturi. Niciun detaliu. Nicio linie de factură. Niciun produs.\nAcea fact table răspundea la o singură întrebare: cât a facturat fiecare client într-o lună dată? Tot restul — pe produs, pe familie de produse, pe factură individuală — era în afara razei.\n🔍 Grain-ul: decizia care determină totul #În modelarea dimensională , grain-ul (granularitatea) fact table-ului este prima decizie pe care o iei. Nu a doua, nu una dintre multe: prima. Kimball repetă asta în fiecare capitol, și are dreptate.\nGrain-ul răspunde la întrebarea: ce reprezintă un singur rând din fact table?\nÎn proiectul pe care l-am descris, cel care proiectase modelul alesese un grain lunar-client: un rând = un client într-o lună. Motivele păreau rezonabile: sistemul sursă exporta un sumar lunar, încărcarea era rapidă, tabelele erau mici, interogările simple.\nDar grain-ul determină întrebările la care data warehouse-ul poate răspunde. Dacă granularitatea este sumarul lunar per client, nu poți coborî sub acel nivel. Nu poți face drill-down pe produs. Nu poți ști dacă clientul Bianchi a cumpărat de zece ori același articol sau zece articole diferite. Nu poți compara marjele pe familie de produse.\nAi un total. Punct.\n📊 Cifrele problemei #Fact table-ul original avea această structură:\nCREATE TABLE fact_facturare_lunara ( sk_client INT NOT NULL, sk_timp INT NOT NULL, -- luna (YYYYMM) sk_agent INT NOT NULL, sk_zona INT NOT NULL, suma_totala DECIMAL(15,2), cantitate_totala INT, nr_facturi INT, nr_linii INT, FOREIGN KEY (sk_client) REFERENCES dim_client(sk_client), FOREIGN KEY (sk_timp) REFERENCES dim_timp(sk_timp) ); Rânduri pe an: aproximativ 180.000 (3.000 clienți × 12 luni × puțină variație). Mic, rapid, ușor de încărcat. ETL-ul rula în mai puțin de cinci minute.\nProblema? Măsurile aditive erau deja agregate. suma_totala era suma tuturor liniilor de factură ale lunii. Imposibil de reconstituit compoziția. Ca și cum ai avea totalul unui bon fără să știi ce ai cumpărat.\n🏗️ Restructurarea: coborârea la linia de factură #Soluția era una singură: schimbarea grain-ului. Aducerea fact table-ului la cel mai jos nivel disponibil în sistemul sursă — linia individuală de factură.\nCREATE TABLE fact_facturare_linie ( sk_linie_factura INT PRIMARY KEY, sk_factura INT NOT NULL, sk_client INT NOT NULL, sk_produs INT NOT NULL, sk_timp INT NOT NULL, -- zi (YYYYMMDD) sk_agent INT NOT NULL, sk_zona INT NOT NULL, sk_familie INT NOT NULL, cantitate INT, pret_unitar DECIMAL(12,4), suma_linie DECIMAL(15,2), discount_pct DECIMAL(5,2), suma_neta DECIMAL(15,2), cost_produs DECIMAL(15,2), marja DECIMAL(15,2), FOREIGN KEY (sk_client) REFERENCES dim_client(sk_client), FOREIGN KEY (sk_produs) REFERENCES dim_produs(sk_produs), FOREIGN KEY (sk_timp) REFERENCES dim_timp(sk_timp) ); Rânduri pe an: aproximativ 2,4 milioane (3.000 clienți × ~800 linii/an în medie). Cu un ordin de mărime mai mult. Dar fiecare rând aducea cu sine detaliul complet: ce produs, ce factură, ce preț, ce discount, ce marjă.\n⚡ Impactul asupra ETL-ului #Schimbarea grain-ului a avut un efect în cascadă asupra ETL-ului pe care nimeni nu-l anticipase — sau mai bine zis, pe care cel care alesese grain-ul agregat evitase să-l înfrunte.\nDimensiuni noi necesare:\nDimensiune Cardinalitate Note dim_produs ~12.000 Nu exista înainte: nu era necesară dim_familie ~180 Ierarhie de produse pe 3 niveluri dim_factura ~45.000/an Antet factură cu date master Noua fereastră de încărcare:\nFază Înainte După Extracție 40 sec 3 min Transformare 1 min 8 min Încărcare fact 30 sec 4 min Total ~2 min ~15 min Cincisprezece minute versus două. Un preț acceptabil pentru un data warehouse care acum răspundea la întrebări reale.\n🔬 Interogările care înainte erau imposibile #Cu noul grain, interogările pe care business-ul le dorea deveneau banale:\nDetalierea achizițiilor unui client pe produs:\nSELECT c.denumire_client, p.cod_produs, p.descriere, SUM(f.cantitate) AS bucati, SUM(f.suma_neta) AS facturat_net, SUM(f.marja) AS marja_totala FROM fact_facturare_linie f JOIN dim_client c ON f.sk_client = c.sk_client JOIN dim_produs p ON f.sk_produs = p.sk_produs JOIN dim_timp t ON f.sk_timp = t.sk_timp WHERE c.denumire_client = \u0026#39;Bianchi Srl\u0026#39; AND t.an = 2024 AND t.luna = 3 GROUP BY c.denumire_client, p.cod_produs, p.descriere ORDER BY facturat_net DESC; Top 10 produse după marjă într-un trimestru:\nSELECT p.cod_produs, p.descriere, fm.desc_familie, SUM(f.suma_neta) AS facturat, SUM(f.marja) AS marja, ROUND(SUM(f.marja) / NULLIF(SUM(f.suma_neta), 0) * 100, 1) AS marja_pct FROM fact_facturare_linie f JOIN dim_produs p ON f.sk_produs = p.sk_produs JOIN dim_familie fm ON f.sk_familie = fm.sk_familie JOIN dim_timp t ON f.sk_timp = t.sk_timp WHERE t.an = 2024 AND t.trimestru = 1 GROUP BY p.cod_produs, p.descriere, fm.desc_familie ORDER BY marja DESC LIMIT 10; Comparație între agenți: facturare medie pe linie:\nSELECT a.nume_agent, COUNT(*) AS nr_linii, SUM(f.suma_neta) AS facturat_total, ROUND(AVG(f.suma_neta), 2) AS media_per_linie FROM fact_facturare_linie f JOIN dim_agent a ON f.sk_agent = a.sk_agent JOIN dim_timp t ON f.sk_timp = t.sk_timp WHERE t.an = 2024 GROUP BY a.nume_agent ORDER BY facturat_total DESC; Niciuna dintre aceste interogări nu era posibilă cu grain-ul lunar-client. Niciuna. Nu era o problemă de tuning sau de indexare — era o problemă structurală, scrisă în ADN-ul modelului.\n📋 Regula Kimball pe care o ignoraserăm #Ralph Kimball o spune clar: \u0026ldquo;modelează întotdeauna la cel mai fin nivel de detaliu disponibil în sistemul sursă.\u0026rdquo;\nNu e o sugestie. Nu e o opțiune între mai multe. E principiul fondator al modelării dimensionale. Și motivul e simplu: poți oricând agrega de la detaliu la total, dar nu poți niciodată dezagrega un total în detaliul său.\nAgregarea este o operație ireversibilă. Ca amestecul culorilor: din roșu și galben obții portocaliu, dar din portocaliu nu te mai întorci niciodată la culorile originale.\nÎn proiectul nostru, alegerea grain-ului agregat fusese dictată de lene în proiectare, nu de o constrângere tehnică. Sistemul sursă avea detaliul pe linie de factură — pur și simplu nimeni nu voise să înfrunte complexitatea modelării, gestionarea dimensiunilor suplimentare, extinderea ferestrei ETL.\nRezultatul? Un data warehouse care a trebuit reconstruit de la zero la șase luni după go-live.\n🎯 Când grain-ul agregat are sens #Granularitatea fină nu e întotdeauna singura răspuns. Există cazuri legitime pentru fact table-uri agregate:\nTabele de agregare (aggregate fact table) alături de tabela de detaliu, pentru a accelera interogările cele mai frecvente Snapshot-uri periodice unde business-ul gândește efectiv pe perioade (sold lunar al unui cont, stoc la sfârșit de săptămână) Restricții de sursă când sistemul upstream nu expune detaliul și nu există modalitate de a-l obține Dar regula este: pornește de la detaliu, apoi agregă. Niciodată invers. Aggregate fact table-urile sunt o optimizare, nu un substitut pentru granularitatea fină.\nÎn cazul nostru, după restructurare, am creat și o vedere materializată cu sumarul lunar per client — aceeași structură ca înainte — pentru dashboard-urile executive care nu aveau nevoie de detaliu. Ce-i mai bun din ambele lumi, fără a sacrifica nimic.\nCe am învățat #Acel proiect m-a învățat ceva ce duc cu mine în fiecare angajament ulterior: prima jumătate de oră de proiectare a unui data warehouse, aceea în care se decide grain-ul, valorează mai mult decât toate optimizările care vor urma. Un ETL perfect, indexuri calibrate, hardware puternic — nimic din toate acestea nu compensează un grain greșit.\nDacă fact table-ul tău nu răspunde la întrebările business-ului, nu e vina interogărilor. E vina modelului. Și modelul se decide la grain.\nGlosar #Grain — Nivelul de detaliu (granularitatea) al unei fact table în data warehouse. Determină ce reprezintă fiecare rând și la ce întrebări poate răspunde modelul. Este prima decizie în proiectarea dimensională.\nFact table — Tabela centrală a star schema-ului care conține măsurile numerice (sume, cantități, marje) și cheile externe către dimensiuni. Granularitatea sa determină nivelul de analiză posibil.\nAdditive Measure — Măsură numerică ce poate fi sumată de-a lungul tuturor dimensiunilor (ex. sumă, cantitate). Odată agregată la nivel superior, detaliul original este pierdut ireversibil.\nDrill-down — Navigare în rapoarte de la nivelul agregat la detaliu, de-a lungul unei ierarhii. Posibilă doar dacă fact table-ul conține date la un nivel de granularitate suficient.\nStar Schema — Model de date cu o fact table centrală și tabele dimensionale legate. Cea mai utilizată structură în data warehouse pentru simplitatea interogărilor analitice.\nETL — Extract, Transform, Load: procesul de extracție, transformare și încărcare a datelor în data warehouse. O schimbare de grain impactează direct durata și complexitatea ETL-ului.\n","date":"21 octombrie 2025","permalink":"https://ivanluminaria.com/ro/posts/data-warehouse/fatto-grana-sbagliata/","section":"Database Strategy","summary":"\u003cp\u003eȘedința începuse bine. Directorul comercial al unei companii de distribuție industrială — vreo șaizeci de milioane cifră de afaceri, trei mii de clienți activi, catalog cu douăsprezece mii de referințe — deschisese prezentarea noului data warehouse cu un zâmbet. Cifrele se potriveau, dashboard-urile arătau bine, totalurile lunare pe agent și pe zonă băteau cu contabilitatea.\u003c/p\u003e\n\u003cp\u003eApoi cineva a pus întrebarea greșită. Sau mai bine zis, pe cea corectă.\u003c/p\u003e\n\u003cp\u003e\u003cem\u003e\u0026ldquo;Pot să văd cât a cumpărat clientul Bianchi în luna martie, linie cu linie, produs cu produs?\u0026rdquo;\u003c/em\u003e\u003c/p\u003e","title":"Granularitate greșită: când fact table nu răspunde la întrebările potrivite"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/granularity/","section":"Tags","summary":"","title":"Granularity"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/binary-log/","section":"Tags","summary":"","title":"Binary-Log"},{"content":"Alerta a venit într-o dimineață de luni, între trei ședințe și o cafea încă fierbinte. \u0026ldquo;Filesystem /mysql la 85% pe nodul primar.\u0026rdquo; Pe un alt nod era la 66%, pe al treilea la 25%. Într-un cluster, când cifrele nu se potrivesc între noduri, întotdeauna e ceva dedesubt.\nPrima întrebare care îți vine în minte este \u0026ldquo;cât spațiu mai trebuie?\u0026rdquo;. Dar e întrebarea greșită. Cea corectă este: \u0026ldquo;de ce se umple?\u0026rdquo;\nCauza: binary logs pe volumul greșit #Verificarea a fost rapidă:\nSHOW VARIABLES LIKE \u0026#39;log_bin\u0026#39;; Rezultat: ON. Binary logs erau active — cum e de așteptat într-un cluster. Dar calea era problema:\nSHOW VARIABLES LIKE \u0026#39;log_bin_basename\u0026#39;; /mysql/bin_log/binlog Binlog-urile stăteau pe același volum cu datele: /mysql. Un volum de aproximativ 3 TB care pe un nod era deja la 85%.\nAm verificat și retenția:\nSHOW VARIABLES LIKE \u0026#39;binlog_expire_logs_seconds\u0026#39;; 2592000 Treizeci de zile. Apoi am vrut să înțeleg cât cântărește de fapt această configurație. Am verificat dimensiunea fișierelor binlog individuale și ritmul de scriere: fiecare fișier avea aproximativ 1 GB, iar serverul genera unul la fiecare două ore. Douăsprezece fișiere pe zi, înmulțite cu treizeci de zile de retenție: aproximativ 360 GB de binary logs pe volumul principal. Pe un volum de 3 TB partajat cu datele, binlog-urile singure ocupau peste 10% din spațiu. Și acele fișiere nu stau doar pe primary — în Group Replication fiecare nod scrie propriile binlog-uri locale pentru sincronizare, deci problema se multiplica pe toate cele trei noduri.\nImaginea era clară: binary logs mâncau spațiul filesystem-ului principal. Nu un bug, nu o tabelă scăpată de sub control. Doar o alegere arhitecturală făcută la instalare și niciodată revizuită.\nCe tip de cluster este, mai exact? #Înainte de a atinge orice pe un server MySQL — înainte chiar de a te gândi să muți un fișier — trebuie să știi ce ai în față. \u0026ldquo;E un cluster\u0026rdquo; nu e suficient. MySQL are cel puțin patru moduri diferite de a face high availability, și fiecare are regulile sale.\nAm început cu replicarea clasică:\nSHOW SLAVE STATUS\\G Empty set pe ambele noduri verificate. Nicio replicare tradițională activă.\nApoi am încercat SHOW REPLICA STATUS — dar pe MySQL 8.0.20 acea comandă nu există încă. A fost introdusă în 8.0.22. Un detaliu pe care documentația online adesea uită să-l menționeze, lăsându-te să urmărești o eroare de sintaxă care nu e una.\nPasul următor — Group Replication:\nSELECT MEMBER_HOST, MEMBER_STATE, MEMBER_ROLE FROM performance_schema.replication_group_members; Și acolo era răspunsul:\nMEMBER_HOST MEMBER_STATE MEMBER_ROLE dbcluster01 ONLINE SECONDARY dbcluster02 ONLINE SECONDARY dbcluster03 ONLINE PRIMARY Trei noduri. Toate ONLINE. Un primary, două secondary. Group Replication în mod single-primary.\nConfirmare finală din plugin-uri:\nSHOW PLUGINS; În listă: group_replication | ACTIVE | GROUP REPLICATION | group_replication.so. Și din configurație:\nSHOW VARIABLES LIKE \u0026#39;group_replication_single_primary_mode\u0026#39;; ON Acum știam exact ce aveam în față. Nu replicare clasică, nu Galera, nu NDB Cluster. Un MySQL Group Replication single-primary cu trei noduri, GTID activat, format binlog ROW. Tabloul complet.\nTentația este întotdeauna să sari peste această fază. \u0026ldquo;Știu că e un cluster, hai să mergem.\u0026rdquo; Dar a sări peste diagnostic pe un cluster e ca și cum ai opera fără un CT: poți avea noroc, sau poți provoca un dezastru.\nSoluția: un volum dedicat pentru binary logs #Strategia era simplă: binlog-urile au nevoie de propriul volum. Nu pe același filesystem cu datele, nu pe un symlink improvizat, nu pe un director partajat. Un volum dedicat, montat pe aceeași cale pe toate cele trei noduri.\nAm cerut administratorilor de sistem să creeze un nou volum de 600 GB cu punct de montare /mysql/binary_logs pe fiecare dintre cele trei noduri.\nCând volumul a fost gata, am verificat pe toate trei:\ndf -h /mysql/binary_logs Nod /mysql /mysql/binary_logs dbcluster03 (PRIMARY) 85% 1% dbcluster02 (SECONDARY) 66% 1% dbcluster01 (SECONDARY) 25% 1% Spațiu proaspăt și dedicat. Fiecare volum pe un disc local al VM-ului corespunzător — trei discuri, trei volume, același mountpoint pe toate cele trei noduri. Administratorii de sistem făcuseră o treabă curată.\nVerificările înainte de a atinge MySQL #Înainte de a opri primul nod, am rulat trei verificări pe care le consider obligatorii.\nPermisiunile directorului. MySQL nu pornește dacă nu poate scrie în directorul de binlog. Pare evident, dar este una dintre cele mai frecvente cauze pentru \u0026ldquo;de ce nu repornește după schimbarea configurației?\u0026rdquo;\nls -ld /mysql/binary_logs Pe toate cele trei noduri permisiunile erau 755. Funcționează, dar nu e ideal din punct de vedere al securității — binlog-urile pot conține date sensibile. Le-am schimbat la 750:\nchmod 750 /mysql/binary_logs Rezultat: drwxr-x--- mysql mysql. Doar utilizatorul mysql poate citi și scrie.\nTest de scriere real. Înainte de a lăsa MySQL să scrie acolo, am verificat că filesystem-ul răspunde:\ntouch /mysql/binary_logs/testfile ls -l /mysql/binary_logs/testfile rm -f /mysql/binary_logs/testfile Dacă touch eșuează, problema e de storage sau permisiuni — și mai bine să afli acum decât după un restart de MySQL.\nStarea clusterului. Ultima verificare înainte de a continua:\nSELECT MEMBER_HOST, MEMBER_STATE, MEMBER_ROLE FROM performance_schema.replication_group_members; Trei noduri ONLINE. Quorum intact. Se poate porni.\nStrategia: un nod pe rând, primary-ul la urmă #Într-un Group Replication cu trei noduri, quorum-ul este doi. Dacă oprești un nod, celelalte două mențin grupul. Dacă oprești două — ai pierdut clusterul.\nRegula e simplă: un nod pe rând, așteptând ca precedentul să reintre în grup înainte de a atinge următorul. Și primary-ul se face la urmă.\nDe ce? Pentru că atunci când oprești primary-ul, se întâmplă ceva important: clusterul declanșează o alegere automată și unul dintre secondary devine noul primary. În acele secunde — puține, dacă totul e sănătos — conexiunile active pot fi întrerupte, tranzacțiile în curs pot eșua. E o întrerupere scurtă, dar e o întrerupere. Trebuie comunicată.\nOrdinea pe care am urmat-o:\ndbcluster01 (SECONDARY) dbcluster02 (SECONDARY) dbcluster03 (PRIMARY) Procedura, nod cu nod #Pe fiecare nod secvența este identică:\nA. Verifică rolul nodului. Înainte de a-l opri, confirmă că e ceea ce crezi:\nSELECT MEMBER_HOST, MEMBER_STATE, MEMBER_ROLE FROM performance_schema.replication_group_members; B. Oprește MySQL:\nsystemctl stop mysqld C. Modifică configurația. În my.cnf, schimbă parametrul log_bin:\nDin:\nlog_bin=/mysql/bin_log/binlog În:\nlog_bin=/mysql/binary_logs/mysql-bin O linie. O singură modificare. Nu atinge parametrii Group Replication, nu schimba server_id, nu reinventa motorul cu aburi în timp ce schimbi o roată.\nD. Pornește MySQL:\nsystemctl start mysqld E. Verifică. Trei lucruri de controlat:\nNoua cale:\nSHOW VARIABLES LIKE \u0026#39;log_bin_basename\u0026#39;; Trebuie să returneze /mysql/binary_logs/mysql-bin.\nRevenirea în grup:\nSELECT MEMBER_HOST, MEMBER_STATE, MEMBER_ROLE FROM performance_schema.replication_group_members; Nodul trebuie să revină ONLINE.\nNoile binlog-uri pe noua cale:\nls -lh /mysql/binary_logs/ Trebuie să apară noi fișiere mysql-bin.000001.\nDoar când nodul este ONLINE și clusterul arată din nou trei noduri active treci la următorul. Nu înainte.\nPentru primary — dbcluster03 — procedura este identică, dar înainte de a-l opri am verificat că ambele secondary erau ONLINE și deja migrate. În momentul opririi, clusterul a declanșat alegerea. Unul dintre secondary a devenit primary. Scurtă întrerupere, cum era de așteptat.\nCe să nu faci #Din experiența mea, acestea sunt cele mai comune capcane în acest tip de intervenție:\nNu copia binlog-urile vechi pe noua cale. În Group Replication nu e nevoie de arheologie binară. Noile binlog-uri se vor crea în noul director după restart. Cele vechi sunt necesare doar dacă ai nevoie de point-in-time recovery — și în cazul ăla știi deja unde le găsești.\nNu atinge două noduri în același timp. Cu trei noduri, quorum-ul e sacru. Un nod pe rând, fără excepții. Dacă oprești două împreună, joci Jenga cu ochii legați.\nNu începe cu primary-ul. Întotdeauna secondary întâi, primary la urmă. A face invers e modul elegant de a invita haosul la cină.\nNu șterge binlog-urile vechi imediat. După schimbare, calea veche /mysql/bin_log/ nu va mai fi folosită pentru fișierele noi. Dar nu te grăbi cu rm -rf /mysql/bin_log/*. Așteaptă. Verifică că clusterul e stabil, că noile binlog-uri se scriu pe noul mount, că nu sunt erori în log-ul MySQL. Doar după câteva zile de observare, gândește-te la curățenie.\nNu te baza doar pe faptul că \u0026ldquo;MySQL a pornit\u0026rdquo;. MySQL poate porni dar să nu reintre în grup. Trebuie să verifici trei lucruri: log_bin_basename indică noua cale, nodul este ONLINE în replication_group_members, și fișierele binlog se scriu efectiv în noul director.\nCe învață această operație #Un filesystem la 92% nu e o urgență — e un semnal. Problema reală nu era spațiul pe disc, ci o alegere arhitecturală făcută la momentul instalării și niciodată revizuită: binlog-uri și date pe același volum.\nSepararea binary logs pe un volum dedicat nu e doar un fix. E întărirea infrastructurii. E diferența dintre un sistem care \u0026ldquo;merge\u0026rdquo; și unul care e proiectat să meargă și când lucrurile cresc.\nȘi partea cea mai importantă a întregii intervenții nu a fost modificarea din my.cnf — aia e o linie. Partea importantă a fost diagnosticul: înțelegerea tipului de cluster, verificarea stării fiecărui nod, pregătirea storage-ului, testarea permisiunilor, planificarea ordinii de execuție. Totul înainte de a atinge un singur parametru.\nUn DBA senior și un DBA junior cunosc amândoi comanda systemctl stop mysqld. Diferența e în tot ce se întâmplă înainte.\nGlosar #Group Replication — Mecanismul nativ MySQL pentru replicare sincronă multi-nod cu failover automat și gestionarea quorum-ului. Suportă modurile single-primary și multi-primary.\nBinary log — Registrul binar secvențial al MySQL care urmărește toate modificările de date (INSERT, UPDATE, DELETE, DDL), folosit pentru replicare și point-in-time recovery.\nGTID — Global Transaction Identifier — identificator unic atribuit fiecărei tranzacții în MySQL, care simplifică gestionarea replicării și urmărirea tranzacțiilor între nodurile clusterului.\nQuorum — Numărul minim de noduri care trebuie să fie active și în comunicare pentru ca un cluster să poată continua să opereze. Într-un cluster cu 3 noduri, quorum-ul este 2.\nSingle-primary — Modul Group Replication în care un singur nod acceptă scrieri, iar celelalte sunt read-only cu failover automat.\n","date":"14 octombrie 2025","permalink":"https://ivanluminaria.com/ro/posts/mysql/mysql-group-replication-binlog-migration/","section":"Database Strategy","summary":"\u003cp\u003eAlerta a venit într-o dimineață de luni, între trei ședințe și o cafea încă fierbinte. \u0026ldquo;Filesystem /mysql la 85% pe nodul primar.\u0026rdquo; Pe un alt nod era la 66%, pe al treilea la 25%. Într-un cluster, când cifrele nu se potrivesc între noduri, întotdeauna e ceva dedesubt.\u003c/p\u003e\n\u003cp\u003ePrima întrebare care îți vine în minte este \u0026ldquo;cât spațiu mai trebuie?\u0026rdquo;. Dar e întrebarea greșită. Cea corectă este: \u0026ldquo;de ce se umple?\u0026rdquo;\u003c/p\u003e","title":"Disc plin pe un cluster MySQL: binary logs, Group Replication și o migrare care nu acceptă erori"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/group-replication/","section":"Tags","summary":"","title":"Group-Replication"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/tags/innodb-cluster/","section":"Tags","summary":"","title":"Innodb-Cluster"},{"content":"O additive measure (măsură aditivă) este o valoare numerică într-o fact table care poate fi sumată legitim de-a lungul oricărei dimensiuni: pe client, pe produs, pe perioadă, pe zonă.\nCum funcționează #Măsurile din fact table se clasifică în trei categorii:\nAditive: pot fi sumate de-a lungul tuturor dimensiunilor (ex. sumă vânzare, cantitate, cost). Cele mai comune și cele mai utile Semi-aditive: pot fi sumate de-a lungul unor dimensiuni dar nu de-a lungul timpului (ex. sold al unui cont: sumabil pe sucursală, nu pe lună) Non-aditive: nu pot fi sumate deloc (ex. procente, rapoarte, medii precalculate) La ce servește #Măsurile aditive sunt inima fiecărei fact table deoarece permit agregările pe care business-ul le cere: totaluri pe perioadă, pe regiune, pe produs. Regula cheie: stochează întotdeauna valorile atomice (detaliul), niciodată agregatele. Dintr-o sumă pe linie de factură poți obține totalul lunar; din totalul lunar nu poți reconstitui liniile individuale.\nCând se folosește #La proiectarea fact table-ului, fiecare măsură trebuie clasificată ca aditivă, semi-aditivă sau non-aditivă. Aceasta determină ce agregări sunt valide în rapoarte și care ar produce rezultate incorecte. O greșeală frecventă este tratarea unei măsuri semi-aditive (precum un sold) ca și cum ar fi aditivă — sumând solduri lunare pentru a obține un „total\u0026quot; care nu are semnificație de business.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/additive-measure/","section":"Glosar","summary":"\u003cp\u003eO \u003cstrong\u003eadditive measure\u003c/strong\u003e (măsură aditivă) este o valoare numerică într-o fact table care poate fi sumată legitim de-a lungul oricărei dimensiuni: pe client, pe produs, pe perioadă, pe zonă.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eMăsurile din fact table se clasifică în trei categorii:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eAditive\u003c/strong\u003e: pot fi sumate de-a lungul tuturor dimensiunilor (ex. sumă vânzare, cantitate, cost). Cele mai comune și cele mai utile\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eSemi-aditive\u003c/strong\u003e: pot fi sumate de-a lungul unor dimensiuni dar nu de-a lungul timpului (ex. sold al unui cont: sumabil pe sucursală, nu pe lună)\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eNon-aditive\u003c/strong\u003e: nu pot fi sumate deloc (ex. procente, rapoarte, medii precalculate)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"la-ce-servește\" class=\"relative group\"\u003eLa ce servește \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#la-ce-serve%c8%99te\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eMăsurile aditive sunt inima fiecărei fact table deoarece permit agregările pe care business-ul le cere: totaluri pe perioadă, pe regiune, pe produs. Regula cheie: stochează întotdeauna valorile atomice (detaliul), niciodată agregatele. Dintr-o sumă pe linie de factură poți obține totalul lunar; din totalul lunar nu poți reconstitui liniile individuale.\u003c/p\u003e","title":"Additive Measure"},{"content":"AI Manager este rolul profesional care guvernează introducerea și utilizarea inteligenței artificiale într-un proiect sau organizație. Nu este cel care folosește AI-ul — este cel care decide unde, cum și cu ce precauții să-l integreze în arhitecturile existente.\nCum funcționează #AI Managerul răspunde la întrebări la care niciun model nu poate răspunde: unde AI-ul generează valoare reală și unde generează doar entuziasm? Cât costă menținerea lui, nu doar implementarea? Ce se întâmplă când modelul greșește? Cum se integrează cu arhitecturile mission-critical fără a le compromite stabilitatea?\nLa ce servește #Separă semnalul de zgomot. Într-o piață unde fiecare furnizor promite ROI cu trei cifre, AI Managerul identifică cele trei domenii unde AI-ul generează valoare concretă: accelerarea analizei, reducerea zgomotului decizional și knowledge transfer automatizat. Tot restul sunt demo-uri care strălucesc.\nDe ce contează #Fără cineva care să guverneze AI-ul, organizațiile îl suferă în loc să-l valorifice. AI-ul este integrat fără a verifica proveniența datelor de training, fără plan de fallback, fără guvernanță. În domenii reglementate (bancar, administrație publică, sănătate) acesta este un risc care poate costa mult mai mult decât AI-ul însuși.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/ai-manager/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eAI Manager\u003c/strong\u003e este rolul profesional care guvernează introducerea și utilizarea inteligenței artificiale într-un proiect sau organizație. Nu este cel care folosește AI-ul — este cel care decide unde, cum și cu ce precauții să-l integreze în arhitecturile existente.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eAI Managerul răspunde la întrebări la care niciun model nu poate răspunde: unde AI-ul generează valoare reală și unde generează doar entuziasm? Cât costă menținerea lui, nu doar implementarea? Ce se întâmplă când modelul greșește? Cum se integrează cu arhitecturile mission-critical fără a le compromite stabilitatea?\u003c/p\u003e","title":"AI Manager"},{"content":"ANALYZE este comanda PostgreSQL care colecteaza statistici despre distributia datelor in tabele si le stocheaza in catalogul pg_statistic (citibil prin vizualizarea pg_stats). Optimizatorul foloseste aceste statistici pentru a estima cardinalitatea — cate randuri va returna fiecare operatie — si a alege cel mai eficient plan de executie.\nCe colecteaza #Statisticile colectate de ANALYZE includ:\nMost common values: valorile cele mai frecvente pentru fiecare coloana si procentul lor Histograme de distributie: cum sunt distribuite valorile ramase Numarul de valori distincte: cate valori unice are fiecare coloana Procentul de NULL: cate randuri au valoarea NULL pentru fiecare coloana Calitatea acestor statistici depinde de numarul de esantioane colectate, controlat de parametrul default_statistics_target.\nDe ce conteaza #Fara statistici actualizate, optimizatorul este fortat sa ghiceasca. Estimarile gresite duc la planuri de executie dezastruoase — cum ar fi alegerea unui nested loop pe milioane de randuri crezand ca sunt sute, sau ignorarea unui index perfect adecvat.\nCand trebuie executat #PostgreSQL executa ANALYZE automat prin autovacuum, dar pragul implicit (50 de randuri + 10% din randurile vii) poate fi prea mare pentru tabelele care cresc rapid. Situatii in care un ANALYZE manual este necesar:\nDupa importuri masive sau bulk load Dupa schimbari semnificative in distributia datelor Cand EXPLAIN ANALYZE arata estimari de cardinalitate foarte diferite de randurile reale Dupa modificarea default_statistics_target pentru o coloana ","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/postgresql-analyze/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eANALYZE\u003c/strong\u003e este comanda PostgreSQL care colecteaza statistici despre distributia datelor in tabele si le stocheaza in catalogul \u003ccode\u003epg_statistic\u003c/code\u003e (citibil prin vizualizarea \u003ccode\u003epg_stats\u003c/code\u003e). Optimizatorul foloseste aceste statistici pentru a estima cardinalitatea — cate randuri va returna fiecare operatie — si a alege cel mai eficient plan de executie.\u003c/p\u003e\n\u003ch2 id=\"ce-colecteaza\" class=\"relative group\"\u003eCe colecteaza \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#ce-colecteaza\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eStatisticile colectate de ANALYZE includ:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eMost common values\u003c/strong\u003e: valorile cele mai frecvente pentru fiecare coloana si procentul lor\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eHistograme de distributie\u003c/strong\u003e: cum sunt distribuite valorile ramase\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eNumarul de valori distincte\u003c/strong\u003e: cate valori unice are fiecare coloana\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eProcentul de NULL\u003c/strong\u003e: cate randuri au valoarea NULL pentru fiecare coloana\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eCalitatea acestor statistici depinde de numarul de esantioane colectate, controlat de parametrul \u003ccode\u003edefault_statistics_target\u003c/code\u003e.\u003c/p\u003e","title":"ANALYZE"},{"content":"Anonymous User (utilizatorul anonim) este un cont MySQL/MariaDB cu username gol (''@'localhost') care este creat automat în timpul instalării. Nu are nume și adesea nu are parolă.\nCum funcționează #Când un utilizator se conectează, MySQL caută potrivirea cea mai specifică în tabelul mysql.user. Utilizatorul anonim ''@'localhost' este mai specific decât 'mario'@'%' pentru o conexiune de pe localhost, deoarece 'localhost' bate '%' în ierarhia specificității. În consecință, Mario care se conectează local este autentificat ca utilizator anonim și pierde toate privilegiile sale.\nLa ce folosește #Utilizatorul anonim a fost gândit pentru instalări de dezvoltare unde se dorea permiterea conexiunilor fără credențiale. În producție nu are nicio utilitate și reprezintă un risc de securitate: poate captura conexiuni destinate altor utilizatori și acorda acces neautorizat.\nCând se folosește #Niciodată în producție. Prima operație pe orice instalare MySQL/MariaDB de producție este verificarea și eliminarea utilizatorilor anonimi cu SELECT user, host FROM mysql.user WHERE user = '' urmat de DROP USER ''@'localhost'.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/anonymous-user/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eAnonymous User\u003c/strong\u003e (utilizatorul anonim) este un cont MySQL/MariaDB cu username gol (\u003ccode\u003e''@'localhost'\u003c/code\u003e) care este creat automat în timpul instalării. Nu are nume și adesea nu are parolă.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eCând un utilizator se conectează, MySQL caută potrivirea cea mai specifică în tabelul \u003ccode\u003emysql.user\u003c/code\u003e. Utilizatorul anonim \u003ccode\u003e''@'localhost'\u003c/code\u003e este mai specific decât \u003ccode\u003e'mario'@'%'\u003c/code\u003e pentru o conexiune de pe localhost, deoarece \u003ccode\u003e'localhost'\u003c/code\u003e bate \u003ccode\u003e'%'\u003c/code\u003e în ierarhia specificității. În consecință, Mario care se conectează local este autentificat ca utilizator anonim și pierde toate privilegiile sale.\u003c/p\u003e","title":"Anonymous User"},{"content":"ASH (Active Session History) este o componenta a Oracle Database care esantioneaza starea fiecarei sesiuni active o data pe secunda si stocheaza datele intr-un buffer circular in memorie (view-ul V$ACTIVE_SESSION_HISTORY).\nCum functioneaza #In fiecare secunda Oracle inregistreaza pentru fiecare sesiune activa:\nSQL-ul in executie (SQL_ID) Wait event-ul curent Programul si modulul apelant Planul de executie utilizat (SQL_PLAN_HASH_VALUE) Datele mai vechi sunt descarcate automat in tabelele AWR (DBA_HIST_ACTIVE_SESS_HISTORY) si pastrate pentru perioada configurata.\nLa ce serveste #ASH este microscopul DBA-ului: unde AWR arata medii pe intervale orare, ASH permite reconstructia a ceea ce facea o singura sesiune intr-un moment precis. Este instrumentul ideal pentru:\nIdentificarea cine executa un SQL problematic Intelegerea cand a inceput o problema (la secunda) Corelarea sesiunilor, programelor si wait event-urilor in timp real Cand se foloseste #Se foloseste cand raportul AWR a identificat deja un SQL sau un wait event dominant si ai nevoie de detalii: ce sesiune, ce program, la ce ora exacta. Regula empirica: AWR ca sa intelegi ce s-a schimbat, ASH ca sa intelegi de ce.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/ash/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eASH\u003c/strong\u003e (Active Session History) este o componenta a Oracle Database care esantioneaza starea fiecarei sesiuni active o data pe secunda si stocheaza datele intr-un buffer circular in memorie (view-ul \u003ccode\u003eV$ACTIVE_SESSION_HISTORY\u003c/code\u003e).\u003c/p\u003e\n\u003ch2 id=\"cum-functioneaza\" class=\"relative group\"\u003eCum functioneaza \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-functioneaza\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eIn fiecare secunda Oracle inregistreaza pentru fiecare sesiune activa:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eSQL-ul in executie (\u003ccode\u003eSQL_ID\u003c/code\u003e)\u003c/li\u003e\n\u003cli\u003eWait event-ul curent\u003c/li\u003e\n\u003cli\u003eProgramul si modulul apelant\u003c/li\u003e\n\u003cli\u003ePlanul de executie utilizat (\u003ccode\u003eSQL_PLAN_HASH_VALUE\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eDatele mai vechi sunt descarcate automat in tabelele AWR (\u003ccode\u003eDBA_HIST_ACTIVE_SESS_HISTORY\u003c/code\u003e) si pastrate pentru perioada configurata.\u003c/p\u003e","title":"ASH"},{"content":"Un Authentication Plugin este modulul pe care MySQL sau MariaDB îl folosește pentru a verifica credențialele unui utilizator la momentul conexiunii. Fiecare utilizator din sistem este asociat cu un plugin specific care determină cum parola este hashată, transmisă și verificată.\nCum funcționează #Plugin-urile principale sunt: mysql_native_password (implicit în MySQL 5.7 și MariaDB), care folosește un hash SHA1 dublu; caching_sha2_password (implicit în MySQL 8.0+), care folosește SHA-256 cu caching pentru îmbunătățirea securității și performanței. Când un client se conectează, trebuie să suporte plugin-ul utilizatorului la care încearcă să se autentifice.\nLa ce folosește #Cunoașterea plugin-urilor de autentificare este esențială în timpul migrărilor între versiuni sau între MySQL și MariaDB. Un client care suportă doar mysql_native_password nu reușește să se conecteze la un utilizator cu caching_sha2_password — iar eroarea rezultantă este adesea criptică și greu de diagnosticat.\nCând se folosește #Plugin-ul se specifică la momentul creării utilizatorului (CREATE USER ... IDENTIFIED WITH \u0026lt;plugin\u0026gt; BY 'password') sau poate fi verificat și modificat cu ALTER USER. Când se scriu scripturi de provisioning care trebuie să funcționeze pe versiuni diferite de MySQL/MariaDB, este important să se specifice explicit plugin-ul.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/authentication-plugin/","section":"Glosar","summary":"\u003cp\u003eUn \u003cstrong\u003eAuthentication Plugin\u003c/strong\u003e este modulul pe care MySQL sau MariaDB îl folosește pentru a verifica credențialele unui utilizator la momentul conexiunii. Fiecare utilizator din sistem este asociat cu un plugin specific care determină cum parola este hashată, transmisă și verificată.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003ePlugin-urile principale sunt: \u003ccode\u003emysql_native_password\u003c/code\u003e (implicit în MySQL 5.7 și MariaDB), care folosește un hash SHA1 dublu; \u003ccode\u003ecaching_sha2_password\u003c/code\u003e (implicit în MySQL 8.0+), care folosește SHA-256 cu caching pentru îmbunătățirea securității și performanței. Când un client se conectează, trebuie să suporte plugin-ul utilizatorului la care încearcă să se autentifice.\u003c/p\u003e","title":"Authentication Plugin"},{"content":"Autovacuum este un daemon PostgreSQL care rulează automat VACUUM și ANALYZE pe tabele când numărul de dead tuples depășește un prag calculat ca: threshold + scale_factor × n_live_tup. Cu valorile implicite (threshold=50, scale_factor=0.2), pe o tabelă cu 10 milioane de rânduri se activează după 2 milioane de dead tuples.\nCum funcționează #Daemon-ul verifică periodic pg_stat_user_tables și lansează un worker pentru fiecare tabelă care depășește pragul. Numărul maxim de workeri simultani este controlat de autovacuum_max_workers (implicit 3). Parametrul autovacuum_vacuum_cost_delay controlează cât se autofrânează vacuum-ul pentru a nu supraîncărca I/O-ul.\nLa ce servește #Este custodele tăcut care împiedică tabelele să se umfle din cauza acumulării de dead tuples. Nu trebuie dezactivat niciodată — este cel mai rău lucru pe care îl poți face unui PostgreSQL în producție. Trebuie configurat per-tabelă: tabelele cu trafic intens necesită scale_factor-uri mici (0.01-0.05) și cost_delay redus.\nCe poate merge prost #Cu valorile implicite, autovacuum-ul este prea conservator pentru tabelele cu trafic intens. 3 workeri pentru zeci de tabele active nu sunt suficienți. Un scale_factor de 20% pe tabele mari generează milioane de dead tuples înainte de intervenție. Tuning-ul per-tabelă cu ALTER TABLE ... SET (autovacuum_vacuum_scale_factor = 0.01) este esențial.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/autovacuum/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eAutovacuum\u003c/strong\u003e este un daemon PostgreSQL care rulează automat VACUUM și ANALYZE pe tabele când numărul de dead tuples depășește un prag calculat ca: \u003ccode\u003ethreshold + scale_factor × n_live_tup\u003c/code\u003e. Cu valorile implicite (threshold=50, scale_factor=0.2), pe o tabelă cu 10 milioane de rânduri se activează după 2 milioane de dead tuples.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eDaemon-ul verifică periodic \u003ccode\u003epg_stat_user_tables\u003c/code\u003e și lansează un worker pentru fiecare tabelă care depășește pragul. Numărul maxim de workeri simultani este controlat de \u003ccode\u003eautovacuum_max_workers\u003c/code\u003e (implicit 3). Parametrul \u003ccode\u003eautovacuum_vacuum_cost_delay\u003c/code\u003e controlează cât se autofrânează vacuum-ul pentru a nu supraîncărca I/O-ul.\u003c/p\u003e","title":"Autovacuum"},{"content":"AWR (Automatic Workload Repository) este o componenta integrata in Oracle Database care colecteaza automat statistici de performanta ale sistemului la intervale regulate (implicit la fiecare 60 de minute) si le pastreaza pentru o perioada configurabila.\nCum functioneaza #AWR captureaza snapshot-uri periodice care includ:\nStatistici ale sesiunilor si wait events Metrici SQL (top SQL dupa timp de executie, I/O, CPU) Statistici ale structurilor de memorie (SGA, PGA) Statistici I/O per datafile si tablespace La ce serveste #Raportul AWR este instrumentul principal pentru diagnosticarea problemelor de performanta in Oracle. Comparand doua snapshot-uri se pot identifica:\nQuery-uri care consuma prea multe resurse Modificari in planurile de executie Blocaje pe I/O, CPU sau memorie Regresii de performanta dupa deploy-uri aplicative Cand se foloseste #AWR este primul instrument de consultat cand se primeste o raportare de incetinire. Impreuna cu ASH (Active Session History), permite reconstructia a ceea ce s-a intamplat in baza de date intr-un interval de timp specific, chiar si dupa ce problema s-a rezolvat.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/awr/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eAWR\u003c/strong\u003e (Automatic Workload Repository) este o componenta integrata in Oracle Database care colecteaza automat statistici de performanta ale sistemului la intervale regulate (implicit la fiecare 60 de minute) si le pastreaza pentru o perioada configurabila.\u003c/p\u003e\n\u003ch2 id=\"cum-functioneaza\" class=\"relative group\"\u003eCum functioneaza \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-functioneaza\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eAWR captureaza snapshot-uri periodice care includ:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eStatistici ale sesiunilor si wait events\u003c/li\u003e\n\u003cli\u003eMetrici SQL (top SQL dupa timp de executie, I/O, CPU)\u003c/li\u003e\n\u003cli\u003eStatistici ale structurilor de memorie (SGA, PGA)\u003c/li\u003e\n\u003cli\u003eStatistici I/O per datafile si tablespace\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"la-ce-serveste\" class=\"relative group\"\u003eLa ce serveste \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#la-ce-serveste\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eRaportul AWR este instrumentul principal pentru diagnosticarea problemelor de performanta in Oracle. Comparand doua snapshot-uri se pot identifica:\u003c/p\u003e","title":"AWR"},{"content":"B-Tree (Balanced Tree) este cea mai comună structură de date pentru indexuri în bazele de date relaționale și este tipul implicit de index în PostgreSQL, MySQL și Oracle. Menține datele sortate într-o structură de arbore echilibrat care garantează timpi de căutare logaritmici.\nCum funcționează #Un B-Tree organizează cheile în noduri sortate, cu fiecare nod conținând pointeri către noduri copil. Căutarea pornește de la rădăcină și coboară către frunze, înjumătățind spațiul de căutare la fiecare nivel. Pentru o tabelă cu 6 milioane de rânduri, un B-Tree necesită tipic 3-4 nivele de adâncime, adică 3-4 citiri de pagină pentru a găsi o valoare.\nLa ce folosește #B-Tree-urile sunt optime pentru căutări de egalitate (WHERE col = 'valoare'), intervale (WHERE col BETWEEN x AND y), sortare și căutări cu prefix (LIKE 'ABC%'). Nu pot fi însă folosite pentru căutări cu wildcard inițial (LIKE '%ABC%'), deoarece ordonarea B-Tree nu ajută la găsirea substringurilor în poziții arbitrare.\nCând se folosește #B-Tree este alegerea corectă pentru majoritatea indexurilor. Când e nevoie de o căutare \u0026ldquo;conține\u0026rdquo; pe text, trebuie trecut la un index GIN cu extensia pg_trgm. Alegerea între B-Tree și GIN depinde de tipul query-ului și de profilul de încărcare al tabelei.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/b-tree/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eB-Tree\u003c/strong\u003e (Balanced Tree) este cea mai comună structură de date pentru indexuri în bazele de date relaționale și este tipul implicit de index în PostgreSQL, MySQL și Oracle. Menține datele sortate într-o structură de arbore echilibrat care garantează timpi de căutare logaritmici.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eUn B-Tree organizează cheile în noduri sortate, cu fiecare nod conținând pointeri către noduri copil. Căutarea pornește de la rădăcină și coboară către frunze, înjumătățind spațiul de căutare la fiecare nivel. Pentru o tabelă cu 6 milioane de rânduri, un B-Tree necesită tipic 3-4 nivele de adâncime, adică 3-4 citiri de pagină pentru a găsi o valoare.\u003c/p\u003e","title":"B-Tree"},{"content":"O Bicicletă Pliabilă este o bicicletă proiectată să se plieze în dimensiuni compacte (de obicei 60×55×25 cm) în câteva secunde, devenind transportabilă ca un bagaj. Brompton este cel mai cunoscut model, cu mecanism de pliere în 10-20 secunde.\nCum funcționează #Un sistem de balamale și eliberări rapide permite plierea cadrului, ghidonului și pedalelor într-un pachet compact. Odată pliată, merge la birou sub birou, în metrou sau în portbagaj. În versiunea electrică, combină avantajele pedalării asistate cu portabilitatea totală.\nLa ce servește #Elimină complet problema parcării — care la Roma poate costa 35€ pe zi și o oră și jumătate de căutare. Nu există risc de furt pentru că bicicleta e mereu cu tine. Iar în zilele de ploaie puternică, se pliază și merge în metrou fără probleme.\nDe ce contează #Bicicleta pliabilă este \u0026ldquo;superputerea\u0026rdquo; care face navetismul pe bicicletă practicabil chiar și pentru cei fără parcare dedicată, cei care trebuie să ia transportul public pentru parte din traseu, sau cei care lucrează în birouri fără rastel. Este soluția ultimului kilometru pe care mașina nu o poate oferi.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/bicicletta-pieghevole/","section":"Glosar","summary":"\u003cp\u003eO \u003cstrong\u003eBicicletă Pliabilă\u003c/strong\u003e este o bicicletă proiectată să se plieze în dimensiuni compacte (de obicei 60×55×25 cm) în câteva secunde, devenind transportabilă ca un bagaj. Brompton este cel mai cunoscut model, cu mecanism de pliere în 10-20 secunde.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eUn sistem de balamale și eliberări rapide permite plierea cadrului, ghidonului și pedalelor într-un pachet compact. Odată pliată, merge la birou sub birou, în metrou sau în portbagaj. În versiunea electrică, combină avantajele pedalării asistate cu portabilitatea totală.\u003c/p\u003e","title":"Bicicletă Pliabilă"},{"content":"Binary log-ul (sau binlog) este un registru secvențial în format binar în care MySQL scrie toate evenimentele care modifică datele: INSERT, UPDATE, DELETE și operațiuni DDL. Fișierele sunt numerotate progresiv (mysql-bin.000001, mysql-bin.000002, etc.) și gestionate printr-un fișier index.\nCum funcționează #De la MySQL 8.0, binary log-ul este activat implicit prin parametrul log_bin. MySQL creează un nou fișier binlog când serverul pornește, când fișierul curent atinge max_binlog_size, sau când se execută FLUSH BINARY LOGS. Suportă trei formate de înregistrare: STATEMENT (înregistrează instrucțiunile SQL), ROW (înregistrează modificările la nivel de rând) și MIXED (alegere automată).\nLa ce folosește #Binary log-ul are două funcții fundamentale:\nReplicare: într-o arhitectură master-slave, slave-ul citește binlog-urile master-ului pentru a replica aceleași operațiuni Point-in-time recovery: după restaurarea unui backup, binlog-urile permit reaplicarea modificărilor până la un moment precis Când se folosește #Binary log-ul este activ implicit pe orice instalare MySQL 8.0+. Gestionarea activă (retenție, purge, monitorizarea spațiului) este necesară pentru a preveni ca fișierele acumulate să umple discul. Comanda PURGE BINARY LOGS este modul corect de a elimina fișierele obsolete.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/binary-log/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eBinary log-ul\u003c/strong\u003e (sau binlog) este un registru secvențial în format binar în care MySQL scrie toate evenimentele care modifică datele: INSERT, UPDATE, DELETE și operațiuni DDL. Fișierele sunt numerotate progresiv (\u003ccode\u003emysql-bin.000001\u003c/code\u003e, \u003ccode\u003emysql-bin.000002\u003c/code\u003e, etc.) și gestionate printr-un fișier index.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eDe la MySQL 8.0, binary log-ul este activat implicit prin parametrul \u003ccode\u003elog_bin\u003c/code\u003e. MySQL creează un nou fișier binlog când serverul pornește, când fișierul curent atinge \u003ccode\u003emax_binlog_size\u003c/code\u003e, sau când se execută \u003ccode\u003eFLUSH BINARY LOGS\u003c/code\u003e. Suportă trei formate de înregistrare: STATEMENT (înregistrează instrucțiunile SQL), ROW (înregistrează modificările la nivel de rând) și MIXED (alegere automată).\u003c/p\u003e","title":"Binary log"},{"content":"Bloat este acumularea de spațiu mort în cadrul unei tabele sau index PostgreSQL, cauzată de dead tuples care nu au fost încă eliminate de VACUUM. O tabelă cu 50% bloat ocupă de două ori spațiul necesar și forțează scanările secvențiale să citească de două ori mai multe pagini.\nCum funcționează #Bloat-ul se măsoară comparând dimensiunea efectivă a tabelei cu dimensiunea așteptată bazată pe rândurile vii. Extensia pgstattuple oferă câmpul dead_tuple_percent. Un bloat peste 20-30% este un semnal de alarmă; peste 50% este o urgență.\nLa ce servește #Monitorizarea bloat-ului este esențială pentru a înțelege dacă autovacuum-ul ține pasul. Interogarea pg_stat_user_tables cu n_dead_tup și last_autovacuum este primul instrument de diagnostic. Dacă bloat-ul este scăpat de sub control, pg_repack reconstruiește tabela online fără lock-uri exclusive prelungite — spre deosebire de VACUUM FULL.\nCe poate merge prost #VACUUM normal recuperează spațiul dead tuple-urilor dar nu compactează tabela — spațiul fragmentat rămâne. Dacă bloat-ul ajunge la 50-70%, VACUUM singur nu mai este suficient. Opțiunile sunt VACUUM FULL (lock exclusiv, blochează totul) sau pg_repack (online, dar necesită instalare). Adevărata soluție este să nu ajungi acolo, cu un autovacuum bine configurat.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/bloat/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eBloat\u003c/strong\u003e este acumularea de spațiu mort în cadrul unei tabele sau index PostgreSQL, cauzată de dead tuples care nu au fost încă eliminate de VACUUM. O tabelă cu 50% bloat ocupă de două ori spațiul necesar și forțează scanările secvențiale să citească de două ori mai multe pagini.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eBloat-ul se măsoară comparând dimensiunea efectivă a tabelei cu dimensiunea așteptată bazată pe rândurile vii. Extensia \u003ccode\u003epgstattuple\u003c/code\u003e oferă câmpul \u003ccode\u003edead_tuple_percent\u003c/code\u003e. Un bloat peste 20-30% este un semnal de alarmă; peste 50% este o urgență.\u003c/p\u003e","title":"Bloat"},{"content":"Un Branch (ramură) este o linie de dezvoltare independentă într-un repository Git. Fiecare branch conține o copie a codului pe care se poate lucra fără a afecta branch-ul principal (main) sau munca altor dezvoltatori.\nCum funcționează #Când un dezvoltator creează un branch (ex. fix/issue-234-eroare-calcul), Git creează un pointer la versiunea curentă a codului. Din acel moment, modificările făcute pe branch rămân izolate. La finalul lucrului, modificările se propun echipei prin Pull Request și, după aprobare, se unesc (merge) în branch-ul principal.\nLa ce folosește #Branch-urile elimină problema suprascrierilor accidentale și a conflictelor negestionate. Fiecare dezvoltator lucrează în propria zonă izolată: nu suprascrie munca celorlalți și nu strică codul funcțional. Branch-ul principal rămâne mereu într-o stare \u0026ldquo;bună\u0026rdquo; pentru că primește doar cod aprobat.\nCând se folosește #Se creează un branch pentru fiecare task, bug fix sau funcționalitate. Convenția de naming ajută la identificarea scopului: fix/ pentru bug-uri, feature/ pentru funcționalități noi, hotfix/ pentru corecții urgente. Branch-ul se șterge după merge pentru a menține repository-ul curat.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/branch/","section":"Glosar","summary":"\u003cp\u003eUn \u003cstrong\u003eBranch\u003c/strong\u003e (ramură) este o linie de dezvoltare independentă într-un repository Git. Fiecare branch conține o copie a codului pe care se poate lucra fără a afecta branch-ul principal (main) sau munca altor dezvoltatori.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eCând un dezvoltator creează un branch (ex. \u003ccode\u003efix/issue-234-eroare-calcul\u003c/code\u003e), Git creează un pointer la versiunea curentă a codului. Din acel moment, modificările făcute pe branch rămân izolate. La finalul lucrului, modificările se propun echipei prin Pull Request și, după aprobare, se unesc (merge) în branch-ul principal.\u003c/p\u003e","title":"Branch"},{"content":"Brompton este o bicicletă pliabilă fabricată la Londra din 1975, considerată referința mondială în categoria sa. Se pliază în 10-20 secunde atingând dimensiuni de aproximativ 58×56×27 cm — suficient de compactă pentru a încăpea sub un birou sau în portbagajul unei mașini mici.\nCum funcționează #Mecanismul brevetat permite plierea bicicletei în trei mișcări: cadru, ghidon și șa. În versiunea electrică (Brompton Electric), un motor în butucul frontal oferă pedalare asistată până la 25 km/h cu o autonomie de 40-70 km. Bateria este detașabilă și se încarcă în 4 ore.\nLa ce servește #Este soluția ideală pentru navetismul multimodal: pedalezi până la stație, pliezi, urci în metrou sau tren, deschizi și pedalezi până la birou. Odată ajuns, o pui sub birou. Zero parcare, zero furt, zero constrângeri.\nDe ce contează #În comparația directă mașină vs Brompton la Roma (Appio Latino → Prati), Brompton-ul face 18 minute față de 50 cu mașina plus 90 de minute de parcare. Cost zilnic: 0€ față de 35€. Brompton-ul se amortizează în mai puțin de un an doar din economiile la parcare.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/brompton/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eBrompton\u003c/strong\u003e este o bicicletă pliabilă fabricată la Londra din 1975, considerată referința mondială în categoria sa. Se pliază în 10-20 secunde atingând dimensiuni de aproximativ 58×56×27 cm — suficient de compactă pentru a încăpea sub un birou sau în portbagajul unei mașini mici.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eMecanismul brevetat permite plierea bicicletei în trei mișcări: cadru, ghidon și șa. În versiunea electrică (Brompton Electric), un motor în butucul frontal oferă pedalare asistată până la 25 km/h cu o autonomie de 40-70 km. Bateria este detașabilă și se încarcă în 4 ore.\u003c/p\u003e","title":"Brompton"},{"content":"BYOL (Bring Your Own License) este un program Oracle care permite organizatiilor sa transfere licentele software achizitionate pentru infrastructura on-premises catre Oracle Cloud Infrastructure (OCI), fara a fi nevoie sa achizitioneze licente cloud noi.\nCum functioneaza #Cand o organizatie detine deja licente Oracle — de obicei Enterprise Edition cu optiuni precum RAC, Data Guard sau Partitioning — le poate \u0026ldquo;lua cu sine\u0026rdquo; in migrarea catre OCI. Contractul de suport (Software Update License \u0026amp; Support) se mentine, iar licentele sunt asociate resurselor cloud in locul serverelor fizice.\nPe OCI, fiecare OCPU corespunde unei processor license, cu un raport 1:1 transparent. Acest lucru face calculul predictibil si conform cu politicile de licentiere Oracle.\nDe ce conteaza in migrari #BYOL este adesea factorul decisiv in alegerea OCI fata de alti furnizori cloud. Pe AWS sau Azure, Oracle aplica reguli de licentiere diferite: fiecare vCPU conteaza ca jumatate de procesor, iar optiuni precum RAC nu sunt suportate sau necesita licente suplimentare. Un audit Oracle pe un cloud non-OCI poate transforma o economie aparenta intr-un cost neprevazut foarte semnificativ.\nCe acopera # Oracle Database (toate editiile) Optiuni ale bazei de date (RAC, Data Guard, Partitioning, Advanced Compression, etc.) Oracle Middleware si alte produse Oracle cu licente eligibile BYOL nu este automat: trebuie solicitat si configurat la momentul provizionarii resurselor OCI, specificand licentele existente in contract.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/byol/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eBYOL\u003c/strong\u003e (Bring Your Own License) este un program Oracle care permite organizatiilor sa transfere licentele software achizitionate pentru infrastructura on-premises catre Oracle Cloud Infrastructure (OCI), fara a fi nevoie sa achizitioneze licente cloud noi.\u003c/p\u003e\n\u003ch2 id=\"cum-functioneaza\" class=\"relative group\"\u003eCum functioneaza \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-functioneaza\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eCand o organizatie detine deja licente Oracle — de obicei Enterprise Edition cu optiuni precum RAC, Data Guard sau Partitioning — le poate \u0026ldquo;lua cu sine\u0026rdquo; in migrarea catre OCI. Contractul de suport (Software Update License \u0026amp; Support) se mentine, iar licentele sunt asociate resurselor cloud in locul serverelor fizice.\u003c/p\u003e","title":"BYOL"},{"content":"Carbon Footprint (amprenta de carbon) este cantitatea totală de gaze cu efect de seră — în principal CO₂ — emise direct sau indirect de o activitate, produs sau individ, exprimată în tone de CO₂ echivalent.\nCum funcționează #Pentru navetismul urban, calculul este direct: o mașină blocată în traficul din Roma produce în medie 120-150 g de CO₂ pe kilometru. În trafic congestionat chiar mai mult, pentru că motorul funcționează în gol consumând fără a se deplasa. O bicicletă produce zero emisii directe.\nLa ce servește #Cuantifică impactul de mediu al alegerilor de mobilitate. Dacă doar 10% din navetiștii romani ar trece la bicicletă, s-ar economisi aproximativ 150.000 de tone de CO₂ pe an — echivalentul plantării a 7 milioane de copaci. Nu e idealism, e aritmetică.\nDe ce contează #Amprenta de carbon a navetismului este un cost externalizat pe care nimeni nu-l plătește direct dar pe care toți îl suferă: poluarea aerului, schimbările climatice, costurile sanitare. Alegerea între mașină și bicicletă nu e doar personală — are un impact colectiv măsurabil.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/carbon-footprint/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eCarbon Footprint\u003c/strong\u003e (amprenta de carbon) este cantitatea totală de gaze cu efect de seră — în principal CO₂ — emise direct sau indirect de o activitate, produs sau individ, exprimată în tone de CO₂ echivalent.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003ePentru navetismul urban, calculul este direct: o mașină blocată în traficul din Roma produce în medie 120-150 g de CO₂ pe kilometru. În trafic congestionat chiar mai mult, pentru că motorul funcționează în gol consumând fără a se deplasa. O bicicletă produce zero emisii directe.\u003c/p\u003e","title":"Carbon Footprint"},{"content":"CDC (Change Data Capture) este o tehnică pentru interceptarea modificărilor de date (INSERT, UPDATE, DELETE) în momentul în care au loc și propagarea lor către alte sisteme în timp real sau aproape real. Spre deosebire de abordările batch tradiționale (ETL periodic), CDC captează modificările în mod continuu și incremental.\nCum funcționează #Cea mai răspândită abordare este log-based CDC: o componentă externă citește log-urile de tranzacții ale bazei de date (binary log în MySQL, WAL în PostgreSQL, redo log în Oracle) și convertește evenimentele într-un flux de date consumabil de alte sisteme. Instrumente precum Debezium, Maxwell și Canal implementează această abordare pentru MySQL citind direct binary log-urile.\nLa ce folosește #CDC este folosit pentru:\nSincronizarea datelor între baze de date diferite în timp real Alimentarea data warehouse-urilor și data lake-urilor cu actualizări incrementale Popularea cache-urilor și indexurilor de căutare (Elasticsearch, Redis) Implementarea arhitecturilor event-driven și a microserviciilor Când se folosește #CDC necesită ca binary log-ul să fie activ și în format ROW (care înregistrează modificările la nivel de rând). Dezactivarea binary log-urilor sau folosirea formatului STATEMENT elimină posibilitatea de a utiliza instrumente CDC, făcând imposibilă integrarea în timp real cu sisteme externe.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/cdc/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eCDC\u003c/strong\u003e (Change Data Capture) este o tehnică pentru interceptarea modificărilor de date (INSERT, UPDATE, DELETE) în momentul în care au loc și propagarea lor către alte sisteme în timp real sau aproape real. Spre deosebire de abordările batch tradiționale (ETL periodic), CDC captează modificările în mod continuu și incremental.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eCea mai răspândită abordare este \u003cstrong\u003elog-based CDC\u003c/strong\u003e: o componentă externă citește log-urile de tranzacții ale bazei de date (binary log în MySQL, WAL în PostgreSQL, redo log în Oracle) și convertește evenimentele într-un flux de date consumabil de alte sisteme. Instrumente precum Debezium, Maxwell și Canal implementează această abordare pentru MySQL citind direct binary log-urile.\u003c/p\u003e","title":"CDC"},{"content":"Cheia surogat (surrogate key) este un identificator numeric secvențial generat intern de data warehouse, fără nicio semnificație de business. Este distinctă de cheia naturală — cea care vine din sistemul sursă (ex. codul clientului, numărul de angajat).\nDe ce este necesară #În SCD Tip 2, același client poate avea mai multe linii în tabela dimensională — câte una pentru fiecare versiune istorică. Cheia naturală (client_id) nu mai este unică, deci este nevoie de un identificator care să distingă fiecare versiune individuală: cheia surogat (client_key).\nCum funcționează #Este generată tipic de o secvență (Oracle) sau o coloană SERIAL/IDENTITY (PostgreSQL, MySQL). Nu este niciodată expusă utilizatorilor finali și nu are semnificație în afara data warehouse-ului.\nTabela de fapte folosește cheia surogat ca cheie externă, indicând spre versiunea specifică a dimensiunii care era validă în momentul faptului. Acest lucru garantează că fiecare tranzacție este asociată cu contextul dimensional corect pentru acel moment în timp.\nAvantaje # Permite versionarea dimensiunilor (SCD Tip 2) Join-urile între fapte și dimensiuni sunt pe numere întregi, deci rapide Izolează DWH-ul de schimbările în cheile sistemelor sursă Suportă încărcarea din surse multiple cu chei naturale potențial duplicate ","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/chiave-surrogata/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eCheia surogat\u003c/strong\u003e (surrogate key) este un identificator numeric secvențial generat intern de data warehouse, fără nicio semnificație de business. Este distinctă de cheia naturală — cea care vine din sistemul sursă (ex. codul clientului, numărul de angajat).\u003c/p\u003e\n\u003ch2 id=\"de-ce-este-necesară\" class=\"relative group\"\u003eDe ce este necesară \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#de-ce-este-necesar%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eÎn SCD Tip 2, același client poate avea mai multe linii în tabela dimensională — câte una pentru fiecare versiune istorică. Cheia naturală (\u003ccode\u003eclient_id\u003c/code\u003e) nu mai este unică, deci este nevoie de un identificator care să distingă fiecare versiune individuală: cheia surogat (\u003ccode\u003eclient_key\u003c/code\u003e).\u003c/p\u003e","title":"Cheie surogat"},{"content":"Churn-ul unei tabele este măsura a cât de mult se modifică datele sale după inserare. O tabelă cu churn ridicat suportă frecvente UPDATE-uri și DELETE-uri; o tabelă cu churn scăzut este predominant append-only (doar INSERT).\nCum funcționează #În PostgreSQL, fiecare UPDATE creează o versiune nouă a rândului (datorită modelului MVCC) iar versiunea veche devine un dead tuple. DELETE-urile creează de asemenea dead tuples. Cu cât churn-ul este mai mare, cu atât mai multă muncă trebuie să facă VACUUM și indexurile pentru a menține performanța. Un index GIN pe o tabelă cu churn ridicat poate degrada semnificativ performanța la scriere.\nLa ce folosește #Evaluarea churn-ului înainte de a crea un index este esențială pentru a evita rezolvarea unei probleme de citire prin crearea uneia de scriere. Pe o tabelă append-only (zero UPDATE, zero DELETE, zero dead tuples), un index GIN are impact minim asupra scrierilor. Pe o tabelă cu churn ridicat, același index ar putea deveni un blocaj.\nCând se folosește #Churn-ul se analizează verificând statisticile tabelei: numărul de UPDATE-uri și DELETE-uri zilnice, dead tuples, frecvența VACUUM. În PostgreSQL, pg_stat_user_tables furnizează aceste metrici. Decizia de a adăuga un index GIN sau trigram ar trebui să pornească întotdeauna de la această analiză.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/churn/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eChurn-ul\u003c/strong\u003e unei tabele este măsura a cât de mult se modifică datele sale după inserare. O tabelă cu churn ridicat suportă frecvente UPDATE-uri și DELETE-uri; o tabelă cu churn scăzut este predominant append-only (doar INSERT).\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eÎn PostgreSQL, fiecare UPDATE creează o versiune nouă a rândului (datorită modelului MVCC) iar versiunea veche devine un dead tuple. DELETE-urile creează de asemenea dead tuples. Cu cât churn-ul este mai mare, cu atât mai multă muncă trebuie să facă VACUUM și indexurile pentru a menține performanța. Un index GIN pe o tabelă cu churn ridicat poate degrada semnificativ performanța la scriere.\u003c/p\u003e","title":"Churn"},{"content":"COALESCE este o funcție SQL standard care acceptă o listă de expresii și returnează prima care nu este NULL. Dacă toate expresiile sunt NULL, returnează NULL.\nSintaxă #COALESCE(expresie1, expresie2, expresie3, ...) Echivalent cu un lanț de CASE WHEN:\nCASE WHEN expresie1 IS NOT NULL THEN expresie1 WHEN expresie2 IS NOT NULL THEN expresie2 WHEN expresie3 IS NOT NULL THEN expresie3 ELSE NULL END Utilizare în ierarhii #În contextul ragged hierarchies, COALESCE este adesea folosită pentru a completa nivelurile lipsă:\nCOALESCE(top_group_name, group_name, client_name) AS top_group_name Aceasta funcționează ca workaround în rapoarte, dar are limitări importante: trebuie repetată în fiecare interogare, nu distinge valorile originale de cele de fallback, și complică codul.\nAlternative pe baze de date # Oracle: NVL(a, b) pentru două valori, COALESCE pentru mai mult de două MySQL: IFNULL(a, b) pentru două valori, COALESCE pentru mai mult de două PostgreSQL: doar COALESCE (SQL standard) Abordare recomandată în DWH #Într-un data warehouse, este preferabil să folosești COALESCE în ETL pentru a popula tabela dimensională cu valori NOT NULL (self-parenting), în loc să o folosești repetat în rapoarte. Logica de gestionare a NULL-urilor trebuie să fie în model, nu în stratul de prezentare.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/coalesce/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eCOALESCE\u003c/strong\u003e este o funcție SQL standard care acceptă o listă de expresii și returnează prima care nu este NULL. Dacă toate expresiile sunt NULL, returnează NULL.\u003c/p\u003e\n\u003ch2 id=\"sintaxă\" class=\"relative group\"\u003eSintaxă \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#sintax%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-sql\" data-lang=\"sql\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eCOALESCE\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eexpresie1\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eexpresie2\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eexpresie3\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e...)\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eEchivalent cu un lanț de CASE WHEN:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-sql\" data-lang=\"sql\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003eCASE\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eWHEN\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eexpresie1\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eIS\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eNOT\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eNULL\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eTHEN\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eexpresie1\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e     \u003c/span\u003e\u003cspan class=\"k\"\u003eWHEN\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eexpresie2\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eIS\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eNOT\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eNULL\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eTHEN\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eexpresie2\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e     \u003c/span\u003e\u003cspan class=\"k\"\u003eWHEN\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eexpresie3\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eIS\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eNOT\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eNULL\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eTHEN\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eexpresie3\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e     \u003c/span\u003e\u003cspan class=\"k\"\u003eELSE\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eNULL\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eEND\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"utilizare-în-ierarhii\" class=\"relative group\"\u003eUtilizare în ierarhii \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#utilizare-%c3%aen-ierarhii\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eÎn contextul ragged hierarchies, COALESCE este adesea folosită pentru a completa nivelurile lipsă:\u003c/p\u003e","title":"COALESCE"},{"content":"Code Review este practica prin care un coleg examinează codul scris de un alt dezvoltator înainte ca acesta să fie incorporat în branch-ul principal. Pe GitHub are loc în interiorul Pull Request-urilor.\nCum funcționează #Dezvoltatorul deschide un Pull Request cu modificările sale. Un reviewer atribuit examinează diff-ul codului, lasă comentarii, sugerează îmbunătățiri și în final aprobă sau cere modificări. Procesul este asincron: nu sunt necesare ședințe, review-ul are loc pe instrument. Doar după aprobare codul se fuzionează în branch-ul principal.\nLa ce folosește #Code review-ul surprinde bug-uri pe care testele automate nu le găsesc, îmbunătățește calitatea codului și — aspect adesea subestimat — răspândește cunoașterea codebase-ului în echipă. Dacă doar o persoană cunoaște un modul și pleacă, proiectul are o problemă. Cu code review-urile, cel puțin două persoane cunosc fiecare bucată de cod.\nCând se folosește #La fiecare Pull Request, fără excepții. Nu e o formalitate: e o investiție în calitate. Timpul petrecut în review e întotdeauna mai mic decât timpul care s-ar petrece corectând bug-uri în producție descoperite prea târziu.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/code-review/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eCode Review\u003c/strong\u003e este practica prin care un coleg examinează codul scris de un alt dezvoltator înainte ca acesta să fie incorporat în branch-ul principal. Pe GitHub are loc în interiorul Pull Request-urilor.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eDezvoltatorul deschide un Pull Request cu modificările sale. Un reviewer atribuit examinează diff-ul codului, lasă comentarii, sugerează îmbunătățiri și în final aprobă sau cere modificări. Procesul este asincron: nu sunt necesare ședințe, review-ul are loc pe instrument. Doar după aprobare codul se fuzionează în branch-ul principal.\u003c/p\u003e","title":"Code Review"},{"content":"Compliance (conformitate normativă) este aderarea unei organizații la legile, reglementările și standardele de sector aplicabile activității sale. În contextul AI, include GDPR, reglementări bancare (SOX, PCI-DSS), reglementări sanitare și politici interne privind utilizarea datelor.\nCum funcționează #Conformitatea se verifică prin audituri, controale documentare și monitorizare continuă. Pentru proiectele AI, necesită trasabilitatea datelor folosite pentru training, documentarea deciziilor automatizate și capacitatea de a explica cum a ajuns modelul la un anumit output (explainability).\nLa ce servește #Garantează că organizația operează în limitele legale și de reglementare. Într-un proiect AI, conformitatea nu este opțională — este o constrângere de proiectare. Un model antrenat pe date supuse GDPR fără consimțământ nu este doar un risc tehnic, este o încălcare.\nDe ce contează #În triunghiul Guvernanță-Conformitate-Automatizare, conformitatea este vârful care nu poate fi niciodată sacrificat. AI Managerul trebuie să garanteze că fiecare automatizare respectă constrângerile normative — iar aceasta necesită o înțelegere profundă atât a tehnologiei cât și a contextului de reglementare. Nu e suficient ca AI-ul să funcționeze: trebuie să funcționeze respectând regulile.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/compliance/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eCompliance\u003c/strong\u003e (conformitate normativă) este aderarea unei organizații la legile, reglementările și standardele de sector aplicabile activității sale. În contextul AI, include GDPR, reglementări bancare (SOX, PCI-DSS), reglementări sanitare și politici interne privind utilizarea datelor.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eConformitatea se verifică prin audituri, controale documentare și monitorizare continuă. Pentru proiectele AI, necesită trasabilitatea datelor folosite pentru training, documentarea deciziilor automatizate și capacitatea de a explica cum a ajuns modelul la un anumit output (explainability).\u003c/p\u003e","title":"Compliance"},{"content":"CTAS (Create Table As Select) este o comandă SQL Oracle care creează o tabelă nouă și o populează într-o singură operație cu rezultatele unui SELECT. Este tehnica standard pentru migrarea datelor de la o structură la alta pe tabele de dimensiuni mari.\nCum funcționează #Comanda combină DDL și DML: creează tabela cu structura derivată din SELECT și inserează datele într-un singur pas. Cu hint-ul PARALLEL și modul NOLOGGING, copierea a sute de GB se poate completa în câteva ore. După copiere, tabela originală se redenumește, cea nouă îi ia locul, iar downtime-ul se limitează la cele câteva secunde ale redenumirii.\nLa ce folosește #CTAS este esențial când trebuie restructurată o tabelă fără a putea folosi ALTER TABLE direct — de exemplu, adăugarea partitioning-ului la o tabelă existentă cu miliarde de rânduri. Permite lucrul pe noua structură în timp ce sistemul este activ pe cea veche.\nCând se folosește #Se folosește pentru migrări la tabele partiționale, reorganizarea datelor fragmentate și crearea de copii ale tabelelor cu structuri diferite. În producție, trebuie combinat întotdeauna cu NOLOGGING (pentru reducerea redo log-urilor) și urmat de un backup RMAN imediat.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/ctas/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eCTAS\u003c/strong\u003e (Create Table As Select) este o comandă SQL Oracle care creează o tabelă nouă și o populează într-o singură operație cu rezultatele unui SELECT. Este tehnica standard pentru migrarea datelor de la o structură la alta pe tabele de dimensiuni mari.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eComanda combină DDL și DML: creează tabela cu structura derivată din SELECT și inserează datele într-un singur pas. Cu hint-ul \u003ccode\u003ePARALLEL\u003c/code\u003e și modul \u003ccode\u003eNOLOGGING\u003c/code\u003e, copierea a sute de GB se poate completa în câteva ore. După copiere, tabela originală se redenumește, cea nouă îi ia locul, iar downtime-ul se limitează la cele câteva secunde ale redenumirii.\u003c/p\u003e","title":"CTAS"},{"content":"Cutover-ul este momentul in care un sistem de productie este mutat de pe infrastructura veche pe cea noua. Este faza cea mai vizibila a unei migrari — cea pe care toata lumea si-o aminteste, in bine sau in rau.\nAnatomia unui cutover #Un cutover bine planificat urmeaza un runbook detaliat cu pasi numerotati, timpi estimati, criterii de succes si proceduri de rollback pentru fiecare pas. Componentele tipice:\nOprirea aplicatiei — inchiderea conexiunilor si verificarea ca nicio sesiune nu este activa Sincronizarea finala — intr-o migrare Data Guard, verificarea ca transport lag si apply lag sunt la zero Switchover/migrare — operatiunea tehnica care transfera serviciul Validare — teste de conectivitate, query-uri de verificare, teste functionale Deschidere graduala — readmiterea progresiva a utilizatorilor Downtime si ferestre #Downtime-ul unui cutover este timpul intre deconectarea ultimului utilizator si reconectarea primului. Cu Data Guard switchover, downtime-ul poate fi de ordinul minutelor. Cu Data Pump, poate fi de ore sau zile.\nFereastra de cutover se planifica in momentele de utilizare minima: nopti, weekenduri, sarbatori. Dar \u0026ldquo;utilizare minima\u0026rdquo; nu inseamna \u0026ldquo;utilizare zero\u0026rdquo; — in companiile de productie cu schimburi 24/7, nu exista un moment in care baza de date nu este necesara nimanui.\nRollback #Orice cutover trebuie sa aiba un plan de rollback. Cu Data Guard, rollback-ul este un al doilea switchover — relativ simplu. Cu Data Pump, rollback-ul inseamna repornirea bazei de date originale si acceptarea pierderii tranzactiilor aparute dupa inceputul migrarii. Calitatea planului de rollback este invers proportionala cu probabilitatea de a-l folosi — dar vai de cei care nu il au.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/cutover/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eCutover-ul\u003c/strong\u003e este momentul in care un sistem de productie este mutat de pe infrastructura veche pe cea noua. Este faza cea mai vizibila a unei migrari — cea pe care toata lumea si-o aminteste, in bine sau in rau.\u003c/p\u003e\n\u003ch2 id=\"anatomia-unui-cutover\" class=\"relative group\"\u003eAnatomia unui cutover \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#anatomia-unui-cutover\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eUn cutover bine planificat urmeaza un runbook detaliat cu pasi numerotati, timpi estimati, criterii de succes si proceduri de rollback pentru fiecare pas. Componentele tipice:\u003c/p\u003e","title":"Cutover"},{"content":"Daily Standup este o ședință zilnică scurtă (maximum 15 minute) în care fiecare membru al echipei răspunde la trei întrebări: ce am făcut ieri, ce voi face azi, mă blochează ceva. Scopul este sincronizarea echipei, nu rezolvarea problemelor.\nCum funcționează #Fiecare persoană are aproximativ două minute pentru actualizarea sa. Problemele sunt semnalate dar nu discutate: rezolvarea are loc după, între persoanele implicate. Constrângerea temporală este ceea ce face standup-ul eficient — fără ea, degenerează într-o ședință de status de 45 de minute.\nLa ce servește #Menține echipa aliniată la stadiul proiectului, scoate la suprafață blocajele înainte să devină critice și creează un ritm zilnic care dă structură muncii. Un standup bine gestionat înlocuiește zeci de emailuri și mesaje Slack.\nCe poate merge prost #Tiparul de degenerare este previzibil: prima săptămână durează 15 minute, a treia 35, a patra echipa începe să-l sară. Cauzele cele mai comune sunt \u0026ldquo;thread killerii\u0026rdquo; (discuții tehnice între două persoane în timp ce ceilalți așteaptă), demo-urile improvizate și managerii care pun întrebări de aprofundare.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/daily-standup/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eDaily Standup\u003c/strong\u003e este o ședință zilnică scurtă (maximum 15 minute) în care fiecare membru al echipei răspunde la trei întrebări: ce am făcut ieri, ce voi face azi, mă blochează ceva. Scopul este sincronizarea echipei, nu rezolvarea problemelor.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eFiecare persoană are aproximativ două minute pentru actualizarea sa. Problemele sunt semnalate dar nu discutate: rezolvarea are loc după, între persoanele implicate. Constrângerea temporală este ceea ce face standup-ul eficient — fără ea, degenerează într-o ședință de status de 45 de minute.\u003c/p\u003e","title":"Daily Standup"},{"content":"Data Governance este setul de politici, procese, roluri și standarde pe care o organizație le adoptă pentru a garanta că datele sale sunt corecte, sigure, conforme cu reglementările și utilizate în mod coerent.\nCum funcționează #Definește cine este responsabil de date (data owner, data steward), ce reguli de calitate se aplică, cum se clasifică datele după sensibilitate și cum se trasează proveniența lor (data lineage). Într-un context AI, include și verificarea provenienței și calității datelor folosite pentru training-ul modelelor.\nLa ce servește #Fără data governance, o organizație nu știe ce date are, unde sunt, cine le poate accesa și dacă sunt fiabile. În proiecte cu componente AI, guvernanța este prerequisitul pentru a preveni antrenarea modelelor pe date murdare, neautorizate sau supuse constrângerilor normative precum GDPR.\nDe ce contează #În fiecare proiect AI într-un mediu reglementat, triunghiul Guvernanță-Conformitate-Automatizare trebuie să rămână în echilibru. O automatizare AI eficientă care încalcă politicile de data governance este un risc. O guvernanță perfectă care blochează automatizarea oprește proiectul. AI Managerul menține în echilibru aceste trei vârfuri.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/data-governance/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eData Governance\u003c/strong\u003e este setul de politici, procese, roluri și standarde pe care o organizație le adoptă pentru a garanta că datele sale sunt corecte, sigure, conforme cu reglementările și utilizate în mod coerent.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eDefinește cine este responsabil de date (data owner, data steward), ce reguli de calitate se aplică, cum se clasifică datele după sensibilitate și cum se trasează proveniența lor (data lineage). Într-un context AI, include și verificarea provenienței și calității datelor folosite pentru training-ul modelelor.\u003c/p\u003e","title":"Data Governance"},{"content":"Data Guard este tehnologia Oracle care mentine una sau mai multe copii sincronizate (standby) ale unei baze de date de productie (primar). Standby-ul primeste si aplica continuu redo log-urile generate de primar, ramanand aliniat in timp real sau aproape.\nCum functioneaza #Primarul genereaza redo log-uri cu fiecare tranzactie. Aceste log-uri sunt transmise standby-ului prin retea, unde sunt aplicate in doua moduri posibile:\nPhysical standby: aplica redo-ul la nivel de bloc (replica exacta, byte cu byte) Logical standby: reconstruieste instructiunile SQL din redo si le reexecuta In caz de defectiune a primarului, standby-ul poate deveni noul primar prin switchover (planificat) sau failover (de urgenta).\nActive Data Guard #Varianta Active Data Guard permite deschiderea standby-ului in mod read-only in timp ce continua sa aplice redo-ul. Acest lucru permite folosirea sa pentru rapoarte, backup-uri si query-uri analitice, usurind sarcina primarului.\nModuri de protectie # Mod Comportament Pierdere de date MaxPerformance Replicare asincrona, fara impact asupra performantei primarului Posibila (cateva secunde) MaxAvailability Replicare sincrona, degradeaza la MaxPerformance daca standby-ul nu e accesibil Zero in conditii normale MaxProtection Replicare sincrona, primarul se opreste daca standby-ul nu confirma Zero garantat ","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/data-guard/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eData Guard\u003c/strong\u003e este tehnologia Oracle care mentine una sau mai multe copii sincronizate (standby) ale unei baze de date de productie (primar). Standby-ul primeste si aplica continuu redo log-urile generate de primar, ramanand aliniat in timp real sau aproape.\u003c/p\u003e\n\u003ch2 id=\"cum-functioneaza\" class=\"relative group\"\u003eCum functioneaza \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-functioneaza\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003ePrimarul genereaza redo log-uri cu fiecare tranzactie. Aceste log-uri sunt transmise standby-ului prin retea, unde sunt aplicate in doua moduri posibile:\u003c/p\u003e","title":"Data Guard"},{"content":"Un Data Warehouse (DWH) este un sistem de stocare a datelor proiectat specific pentru analiză, raportare și suport al deciziilor de afaceri. Spre deosebire de bazele de date operaționale (OLTP), un DWH colectează date din surse multiple, le transformă și le organizează în structuri optimizate pentru interogări analitice.\nCum funcționează #Datele sunt extrase din sistemele sursă (aplicații de gestiune, CRM, ERP), transformate prin procese ETL care le curăță, normalizează și îmbogățesc, și în final încărcate în DWH. Modelul de date tipic este star schema: o tabelă de fapte centrală cu măsurile numerice conectată la tabele dimensionale care descriu contextul (timp, client, produs, geografie).\nLa ce folosește #Un DWH permite răspunsul la întrebări de business pe care sistemele operaționale nu le pot gestiona: tendințe istorice, analize comparative între perioade, agregări cross-system, KPI-uri de afaceri. Separă sarcina analitică de cea tranzacțională, prevenind impactul interogărilor de raportare asupra performanței aplicațiilor operative.\nCând se folosește #Un DWH este necesar când o companie trebuie să integreze date din surse diverse pentru a produce analize consolidate. Complexitatea și costurile depind de numărul sistemelor sursă, volumul datelor și frecvența de actualizare necesară.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/data-warehouse/","section":"Glosar","summary":"\u003cp\u003eUn \u003cstrong\u003eData Warehouse\u003c/strong\u003e (DWH) este un sistem de stocare a datelor proiectat specific pentru analiză, raportare și suport al deciziilor de afaceri. Spre deosebire de bazele de date operaționale (OLTP), un DWH colectează date din surse multiple, le transformă și le organizează în structuri optimizate pentru interogări analitice.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eDatele sunt extrase din sistemele sursă (aplicații de gestiune, CRM, ERP), transformate prin procese ETL care le curăță, normalizează și îmbogățesc, și în final încărcate în DWH. Modelul de date tipic este star schema: o tabelă de fapte centrală cu măsurile numerice conectată la tabele dimensionale care descriu contextul (timp, client, produs, geografie).\u003c/p\u003e","title":"Data Warehouse"},{"content":"Un Dead Tuple este un rând într-o tabelă PostgreSQL care a fost actualizat (UPDATE) sau șters (DELETE) dar nu a fost încă eliminat fizic. Rămâne în paginile de date, ocupând spațiu pe disc și încetinind scanările.\nCum funcționează #Când PostgreSQL execută un UPDATE, nu suprascrie rândul original: creează o versiune nouă și o marchează pe cea veche ca \u0026ldquo;moartă.\u0026rdquo; Rândul vechi rămâne fizic în pagina de date până când VACUUM îl curăță. Dead tuple-urile sunt prețul modelului MVCC — necesare pentru a garanta izolarea tranzacțională.\nLa ce servește #Dead tuple-urile sunt un indicator cheie al sănătății unei tabele. Vizualizarea pg_stat_user_tables arată n_dead_tup și last_autovacuum — dacă dead tuple-urile cresc mai repede decât poate curăța autovacuum-ul, tabela are o problemă. Un dead_tuple_percent peste 20-30% este un semnal de alarmă.\nCe poate merge prost #Pe o tabelă cu 500.000 de update-uri pe zi și valorile implicite ale autovacuum-ului (scale_factor 0.2), VACUUM se activează la fiecare 4 zile. Între timp dead tuple-urile se acumulează, tabelele se umflă iar interogările încetinesc progresiv — tiparul \u0026ldquo;luni bine, vineri dezastru\u0026rdquo;.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/dead-tuple/","section":"Glosar","summary":"\u003cp\u003eUn \u003cstrong\u003eDead Tuple\u003c/strong\u003e este un rând într-o tabelă PostgreSQL care a fost actualizat (UPDATE) sau șters (DELETE) dar nu a fost încă eliminat fizic. Rămâne în paginile de date, ocupând spațiu pe disc și încetinind scanările.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eCând PostgreSQL execută un UPDATE, nu suprascrie rândul original: creează o versiune nouă și o marchează pe cea veche ca \u0026ldquo;moartă.\u0026rdquo; Rândul vechi rămâne fizic în pagina de date până când VACUUM îl curăță. Dead tuple-urile sunt prețul modelului MVCC — necesare pentru a garanta izolarea tranzacțională.\u003c/p\u003e","title":"Dead Tuple"},{"content":"DEFAULT PRIVILEGES este un mecanism PostgreSQL care permite definirea în avans a privilegiilor ce vor fi atribuite automat tuturor obiectelor viitoare create într-o schemă. Se configurează cu comanda ALTER DEFAULT PRIVILEGES.\nCum funcționează #Comanda ALTER DEFAULT PRIVILEGES IN SCHEMA schema1 GRANT SELECT ON TABLES TO srv_monitorizare face ca fiecare tabelă nouă creată în schema1 să fie automat citibilă de srv_monitorizare. Fără această configurare, tabelele viitoare ar necesita un GRANT manual de fiecare dată.\nLa ce servește #Este partea pe care majoritatea administratorilor o uită când creează utilizatori read-only. GRANT-urile pe ALL TABLES IN SCHEMA acoperă doar tabelele existente. Tabelele create ulterior necesită noi GRANT-uri — doar dacă nu se folosesc DEFAULT PRIVILEGES. Fără ele, utilizatorul de monitorizare încetează să funcționeze la prima tabelă nouă.\nCe poate merge prost #DEFAULT PRIVILEGES se aplică ROLE-ului care creează obiectele. Dacă într-o schemă mai mulți utilizatori creează tabele, default privileges trebuie configurate pentru fiecare creator. Acest detaliu cauzează adesea erori greu de diagnosticat: \u0026ldquo;GRANT-ul există, dar tabela nouă nu este citibilă.\u0026rdquo;\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/default-privileges/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eDEFAULT PRIVILEGES\u003c/strong\u003e este un mecanism PostgreSQL care permite definirea în avans a privilegiilor ce vor fi atribuite automat tuturor obiectelor viitoare create într-o schemă. Se configurează cu comanda \u003ccode\u003eALTER DEFAULT PRIVILEGES\u003c/code\u003e.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eComanda \u003ccode\u003eALTER DEFAULT PRIVILEGES IN SCHEMA schema1 GRANT SELECT ON TABLES TO srv_monitorizare\u003c/code\u003e face ca fiecare tabelă nouă creată în \u003ccode\u003eschema1\u003c/code\u003e să fie automat citibilă de \u003ccode\u003esrv_monitorizare\u003c/code\u003e. Fără această configurare, tabelele viitoare ar necesita un GRANT manual de fiecare dată.\u003c/p\u003e","title":"DEFAULT PRIVILEGES"},{"content":"default_statistics_target este parametrul PostgreSQL care defineste numarul de esantioane colectate de comanda ANALYZE pentru a construi statisticile fiecarei coloane. Valoarea implicita este 100.\nCum functioneaza #PostgreSQL esantioneaza un anumit numar de valori pentru fiecare coloana si le foloseste pentru a construi doua structuri:\nMost common values (MCV): lista valorilor celor mai frecvente, cu frecventele respective Histograma: distributia valorilor ramase, impartita in bucket-uri de populatie egala Parametrul default_statistics_target determina cate elemente vor avea aceste structuri. Cu valoarea implicita de 100, histograma va avea 100 de bucket-uri si lista MCV va contine pana la 100 de valori.\nCand trebuie crescut #Pentru tabele mici sau cu distributie uniforma, 100 de esantioane sunt suficiente. Pentru tabele mari cu distributie asimetrica (skewed) — unde putine valori domina majoritatea randurilor — 100 de esantioane pot da o reprezentare distorsionata, ducand optimizatorul la estimari de cardinalitate gresite.\nSe poate creste target-ul la nivel de coloana individuala:\nALTER TABLE orders ALTER COLUMN status SET STATISTICS 500; ANALYZE orders; Valori intre 500 si 1000 imbunatatesc semnificativ calitatea estimarilor pe coloane cu distributie neuniforma.\nLimite practice #Peste 1000 beneficiul este marginal si ANALYZE-ul insusi devine mai lent, pentru ca trebuie sa esantioneze mai multe randuri si sa construiasca structuri mai mari. Este o reglare fina: trebuie aplicata doar coloanelor care cauzeaza efectiv estimari gresite, nu tuturor coloanelor din toate tabelele.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/postgresql-default-statistics-target/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003edefault_statistics_target\u003c/strong\u003e este parametrul PostgreSQL care defineste numarul de esantioane colectate de comanda \u003ccode\u003eANALYZE\u003c/code\u003e pentru a construi statisticile fiecarei coloane. Valoarea implicita este 100.\u003c/p\u003e\n\u003ch2 id=\"cum-functioneaza\" class=\"relative group\"\u003eCum functioneaza \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-functioneaza\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003ePostgreSQL esantioneaza un anumit numar de valori pentru fiecare coloana si le foloseste pentru a construi doua structuri:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eMost common values (MCV)\u003c/strong\u003e: lista valorilor celor mai frecvente, cu frecventele respective\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eHistograma\u003c/strong\u003e: distributia valorilor ramase, impartita in bucket-uri de populatie egala\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eParametrul \u003ccode\u003edefault_statistics_target\u003c/code\u003e determina cate elemente vor avea aceste structuri. Cu valoarea implicita de 100, histograma va avea 100 de bucket-uri si lista MCV va contine pana la 100 de valori.\u003c/p\u003e","title":"default_statistics_target"},{"content":"Directiva 2011/7/UE este reglementarea europeană privind întârzierile la plată în tranzacțiile comerciale. Stabilește reguli clare: termen standard de 30 de zile, maxim 60 între întreprinderi (cu acord explicit), 30 pentru administrația publică, și dobânzi de întârziere automate la rata BCE + 8%.\nCum funcționează #Directiva a fost transpusă în dreptul italian prin D.Lgs. 231/2002 (modificat în 2012). Pe hârtie regulile există: 30 de zile standard, dobânzi automate, compensație forfetară de 40€ per factură plătită cu întârziere. În practica italiană e ca și cum n-ar exista — DSO-ul mediu italian este de 80 de zile, mult peste maximul de 60.\nLa ce servește #Ar trebui să protejeze furnizorii — în special întreprinderile mici și freelancerii — de întârzierile structurale la plată. În țări precum Germania (DSO 24 zile) și Țările de Jos (DSO 27 zile) directiva funcționează. În Italia decalajul dintre normă și realitate este abismal.\nDe ce contează #Directiva demonstrează că problema întârzierilor la plată din Italia nu este legislativă — legile există. Este culturală și structurală: costul reputațional al exercitării propriilor drepturi depășește beneficiul economic, iar sistemul se bazează pe docilitatea creditorului.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/direttiva-2011-7-ue/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eDirectiva 2011/7/UE\u003c/strong\u003e este reglementarea europeană privind întârzierile la plată în tranzacțiile comerciale. Stabilește reguli clare: termen standard de 30 de zile, maxim 60 între întreprinderi (cu acord explicit), 30 pentru administrația publică, și dobânzi de întârziere automate la rata BCE + 8%.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eDirectiva a fost transpusă în dreptul italian prin D.Lgs. 231/2002 (modificat în 2012). Pe hârtie regulile există: 30 de zile standard, dobânzi automate, compensație forfetară de 40€ per factură plătită cu întârziere. În practica italiană e ca și cum n-ar exista — DSO-ul mediu italian este de 80 de zile, mult peste maximul de 60.\u003c/p\u003e","title":"Directiva 2011/7/UE"},{"content":"Dobânzile de Întârziere sunt dobânzile care se acumulează automat pe fiecare factură plătită cu întârziere față de termenul contractual. Conform D.Lgs. 231/2002 italian (transpunerea Directivei UE 2011/7/UE), rata este egală cu rata BCE + 8 puncte procentuale, fără necesitatea unei somații formale.\nCum funcționează #Din ziua următoare scadenței facturii, dobânzile se acumulează automat. Creditorul are dreptul și la o compensație forfetară de 40€ pentru fiecare factură plătită cu întârziere, pentru cheltuielile de recuperare. Nu este necesară trimiterea unei somații — dreptul se naște din lege.\nLa ce servește #Sunt instrumentul legal principal pentru descurajarea întârzierilor la plată. În teorie, ar trebui să facă dezavantajos pentru debitor să întârzie. În practica italiană, aproape niciun consultant nu le solicită de teamă să nu piardă clientul — ceea ce face instrumentul ineficient.\nCe poate merge prost #Costul reputațional al solicitării dobânzilor de întârziere este perceput ca mai mare decât beneficiul financiar. Un consultant care trimite o cerere formală este un consultant care \u0026ldquo;nu va mai fi chemat.\u0026rdquo; Sistemul se bazează pe docilitatea structurală a furnizorului — și funcționează, până când nu mai funcționează.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/interessi-di-mora/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eDobânzile de Întârziere\u003c/strong\u003e sunt dobânzile care se acumulează automat pe fiecare factură plătită cu întârziere față de termenul contractual. Conform D.Lgs. 231/2002 italian (transpunerea Directivei UE 2011/7/UE), rata este egală cu rata BCE + 8 puncte procentuale, fără necesitatea unei somații formale.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eDin ziua următoare scadenței facturii, dobânzile se acumulează automat. Creditorul are dreptul și la o compensație forfetară de 40€ pentru fiecare factură plătită cu întârziere, pentru cheltuielile de recuperare. Nu este necesară trimiterea unei somații — dreptul se naște din lege.\u003c/p\u003e","title":"Dobânzi de Întârziere"},{"content":"Drill-down-ul este operațiunea de navigare în rapoarte care permite trecerea de la un nivel agregat la un nivel de detaliu mai mare, coborând de-a lungul unei ierarhii.\nCum funcționează #Într-o ierarhie Top Group → Group → Client:\nSe pornește de la nivelul cel mai înalt: cifra de afaceri totală pe Top Group Se face clic pe un Top Group pentru a vedea Group-urile sale (drill-down de primul nivel) Se face clic pe un Group pentru a vedea Clienții individuali (drill-down de al doilea nivel) Operațiunea inversă — revenirea de la detaliu la agregat — se numește drill-up (sau roll-up).\nCerințe pentru un drill-down corect #Pentru a funcționa fără erori, drill-down-ul necesită:\nO ierarhie completă: niciun nivel lipsă (fără NULL-uri) Coerența totalurilor: suma valorilor la nivel de detaliu trebuie să corespundă totalului de la nivelul superior Structură echilibrată: toate ramurile ierarhiei trebuie să aibă aceeași adâncime Dacă ierarhia este dezechilibrată (ragged hierarchy), drill-down-ul produce rezultate incomplete sau eronate. Self-parenting-ul rezolvă aceasta echilibrând structura în amonte.\nDrill-down vs filtru #Drill-down-ul nu este un simplu filtru: este o navigare structurată de-a lungul unei ierarhii predefinite. Un filtru arată un subset de date; un drill-down arată următorul nivel de detaliu într-un context ierarhic.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/drill-down/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eDrill-down-ul\u003c/strong\u003e este operațiunea de navigare în rapoarte care permite trecerea de la un nivel agregat la un nivel de detaliu mai mare, coborând de-a lungul unei ierarhii.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eÎntr-o ierarhie Top Group → Group → Client:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003eSe pornește de la nivelul cel mai înalt: cifra de afaceri totală pe Top Group\u003c/li\u003e\n\u003cli\u003eSe face clic pe un Top Group pentru a vedea Group-urile sale (drill-down de primul nivel)\u003c/li\u003e\n\u003cli\u003eSe face clic pe un Group pentru a vedea Clienții individuali (drill-down de al doilea nivel)\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003eOperațiunea inversă — revenirea de la detaliu la agregat — se numește \u003cstrong\u003edrill-up\u003c/strong\u003e (sau roll-up).\u003c/p\u003e","title":"Drill-down"},{"content":"DSO (Days Sales Outstanding) este metrica care măsoară numărul mediu de zile pe care o companie le necesită pentru a-și încasa creanțele după emiterea facturii. Este indicatorul principal al vitezei de plată într-o piață.\nCum funcționează #Se calculează ca: (Creanțe comerciale / Venituri) × Zile din perioadă. Un DSO de 30 înseamnă că în medie clienții plătesc într-o lună. În Italia DSO-ul mediu este de 80 de zile conform European Payment Report — aproape de trei ori media nordului Europei (24-27 zile).\nLa ce servește #Pentru un consultant freelancer, DSO-ul determină necesarul de capital circulant. Cu un DSO de 90 de zile și venituri de 5.500€/lună, sunt necesare cel puțin 16.500€ rezervă pentru a acoperi primele trei luni fără încasări. Fără rezervă, consultantul își finanțează clientul la cost zero.\nDe ce contează #Italia este în afara scalei față de Directiva UE care fixează termenul maxim la 60 de zile. Un DSO de 80 de zile nu este doar o problemă financiară — este un indicator structural al unei piețe unde puterea de negociere este dezechilibrată în favoarea clientului.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/dso/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eDSO\u003c/strong\u003e (Days Sales Outstanding) este metrica care măsoară numărul mediu de zile pe care o companie le necesită pentru a-și încasa creanțele după emiterea facturii. Este indicatorul principal al vitezei de plată într-o piață.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eSe calculează ca: \u003ccode\u003e(Creanțe comerciale / Venituri) × Zile din perioadă\u003c/code\u003e. Un DSO de 30 înseamnă că în medie clienții plătesc într-o lună. În Italia DSO-ul mediu este de 80 de zile conform European Payment Report — aproape de trei ori media nordului Europei (24-27 zile).\u003c/p\u003e","title":"DSO"},{"content":"ETL (Extract, Transform, Load) este procesul fundamental prin care datele sunt mutate din sistemele sursa (baze de date operationale, fisiere, API-uri) in data warehouse.\nCele trei faze # Extract: extragerea datelor din sistemele sursa. Poate fi completa (full load) sau incrementala (doar date noi sau modificate) Transform: curatarea, validarea, standardizarea si imbogatirea datelor. Aici se aplica regulile de business, lookup-urile pe dimensiuni, calculele derivate Load: incarcarea datelor transformate in tabelele data warehouse-ului (fact si dimension) De ce este critic #ETL este partea cea mai putin vizibila dar cea mai critica a unui data warehouse. Daca datele sunt extrase incomplet, transformate cu reguli eronate sau incarcate fara verificari, tot ce sta deasupra — rapoarte, dashboard-uri, decizii — va fi gresit.\nUn ETL bine proiectat determina si fereastra de incarcare: cat timp este necesar pentru actualizarea data warehouse-ului. In medii reale, trecerea de la 4 ore la 25 de minute poate face diferenta intre date actualizate dimineata sau dupa-amiaza.\nELT vs ETL #Odata cu aparitia data warehouse-urilor cloud si a motoarelor columnare de inalta performanta, s-a raspandit pattern-ul ELT (Extract, Load, Transform): datele sunt incarcate brute in warehouse si transformate direct acolo, valorificand puterea de procesare a motorului SQL. Conceptul de baza ramane acelasi — ceea ce se schimba este unde are loc transformarea.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/etl/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eETL\u003c/strong\u003e (Extract, Transform, Load) este procesul fundamental prin care datele sunt mutate din sistemele sursa (baze de date operationale, fisiere, API-uri) in data warehouse.\u003c/p\u003e\n\u003ch2 id=\"cele-trei-faze\" class=\"relative group\"\u003eCele trei faze \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cele-trei-faze\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eExtract\u003c/strong\u003e: extragerea datelor din sistemele sursa. Poate fi completa (full load) sau incrementala (doar date noi sau modificate)\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eTransform\u003c/strong\u003e: curatarea, validarea, standardizarea si imbogatirea datelor. Aici se aplica regulile de business, lookup-urile pe dimensiuni, calculele derivate\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eLoad\u003c/strong\u003e: incarcarea datelor transformate in tabelele data warehouse-ului (fact si dimension)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"de-ce-este-critic\" class=\"relative group\"\u003eDe ce este critic \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#de-ce-este-critic\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eETL este partea cea mai putin vizibila dar cea mai critica a unui data warehouse. Daca datele sunt extrase incomplet, transformate cu reguli eronate sau incarcate fara verificari, tot ce sta deasupra — rapoarte, dashboard-uri, decizii — va fi gresit.\u003c/p\u003e","title":"ETL"},{"content":"Exchange Partition este o operațiune DDL Oracle care permite schimbarea instantanee a conținutului unei partiții cu cel al unei tabele nepartiționate. Nu se mută niciun byte de date — operațiunea modifică doar pointerii din data dictionary.\nCum funcționează #Comanda ALTER TABLE ... EXCHANGE PARTITION ... WITH TABLE ... modifică metadatele din data dictionary astfel încât segmentele fizice ale partiției și ale tabelei de staging să își schimbe proprietarul. Tabela de staging devine partiția și invers. Operațiunea durează mai puțin de o secundă indiferent de volumul datelor, deoarece nu implică nicio mișcare fizică.\nLa ce servește #În data warehouse-uri, exchange partition este instrumentul principal pentru încărcarea masivă a datelor. Procesul tipic este: ETL-ul încarcă datele într-o tabelă de staging, construiește indexurile, validează datele, și apoi execută exchange-ul cu partiția țintă. În timpul exchange-ului, query-urile pe celelalte partiții continuă să funcționeze fără întrerupere.\nCe poate merge prost #Clauza WITHOUT VALIDATION omite verificarea că datele din tabela de staging se încadrează efectiv în intervalul partiției — accelerează operațiunea dar necesită ca ETL-ul să garanteze corectitudinea datelor. Dacă datele din staging conțin date în afara intervalului, ajung în partiția greșită fără nicio eroare. Clauza INCLUDING INDEXES necesită ca tabela de staging să aibă indexuri cu aceeași structură ca indexurile locale ale tabelei partiționate.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/exchange-partition/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eExchange Partition\u003c/strong\u003e este o operațiune DDL Oracle care permite schimbarea instantanee a conținutului unei partiții cu cel al unei tabele nepartiționate. Nu se mută niciun byte de date — operațiunea modifică doar pointerii din data dictionary.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eComanda \u003ccode\u003eALTER TABLE ... EXCHANGE PARTITION ... WITH TABLE ...\u003c/code\u003e modifică metadatele din data dictionary astfel încât segmentele fizice ale partiției și ale tabelei de staging să își schimbe proprietarul. Tabela de staging devine partiția și invers. Operațiunea durează mai puțin de o secundă indiferent de volumul datelor, deoarece nu implică nicio mișcare fizică.\u003c/p\u003e","title":"Exchange Partition"},{"content":"Un execution plan (plan de executie) este secventa de operatii pe care baza de date o alege pentru a rezolva o interogare SQL. Cand scrii un SELECT cu JOIN-uri, filtre WHERE si sortari, optimizatorul evalueaza zeci de strategii posibile si alege una pe baza statisticilor disponibile.\nCum functioneaza #Planul este reprezentat ca un arbore de noduri: fiecare nod este o operatie (scan, join, sort, aggregate) care primeste date de la nodurile copil si le transmite nodului parinte. In PostgreSQL se vizualizeaza cu EXPLAIN (plan estimat) sau EXPLAIN ANALYZE (plan real cu timpii efectivi si contoarele de randuri).\nOptimizatorul decide pentru fiecare nod ce strategie sa foloseasca: sequential scan sau index scan pentru accesul la tabele, nested loop, hash join sau merge join pentru jonctiuni, sort sau hash pentru grupari.\nDe ce conteaza #Citirea corecta a unui plan de executie este cea mai importanta competenta pentru optimizarea interogarilor. Nu este suficient sa te uiti la timpul total: trebuie sa compari randurile estimate cu cele reale nod cu nod, sa verifici bufferele de I/O si sa identifici unde optimizatorul a facut alegeri gresite.\nO estimare eronata chiar si pe un singur nod se poate propaga in cascada pe intregul plan, transformand o interogare de milisecunde intr-una de minute.\nCe poate merge prost #Cele mai frecvente probleme in planurile de executie:\nEstimari de cardinalitate gresite: optimizatorul crede ca un tabel returneaza 100 de randuri si ajung 2 milioane Join gresit: un nested loop ales acolo unde era nevoie de un hash join, din cauza statisticilor invechite Index ignorat: un sequential scan pe un tabel mare pentru ca statisticile nu reflecta distributia reala a datelor Spill pe disc: operatii de sort sau hash care nu incap in work_mem si sfarsesc prin a scrie pe disc ","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/execution-plan/","section":"Glosar","summary":"\u003cp\u003eUn \u003cstrong\u003eexecution plan\u003c/strong\u003e (plan de executie) este secventa de operatii pe care baza de date o alege pentru a rezolva o interogare SQL. Cand scrii un SELECT cu JOIN-uri, filtre WHERE si sortari, optimizatorul evalueaza zeci de strategii posibile si alege una pe baza statisticilor disponibile.\u003c/p\u003e\n\u003ch2 id=\"cum-functioneaza\" class=\"relative group\"\u003eCum functioneaza \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-functioneaza\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003ePlanul este reprezentat ca un arbore de noduri: fiecare nod este o operatie (scan, join, sort, aggregate) care primeste date de la nodurile copil si le transmite nodului parinte. In PostgreSQL se vizualizeaza cu \u003ccode\u003eEXPLAIN\u003c/code\u003e (plan estimat) sau \u003ccode\u003eEXPLAIN ANALYZE\u003c/code\u003e (plan real cu timpii efectivi si contoarele de randuri).\u003c/p\u003e","title":"Execution Plan"},{"content":"Facilitatorul este persoana însărcinată cu ghidarea desfășurării unei ședințe. Nu este cel care decide — este cel care garantează că decizia se ia în mod ordonat, în timpul prevăzut și cu contribuția tuturor participanților.\nCum funcționează #Facilitatorul ține timpul, gestionează turele de cuvânt, taie discuțiile în afara subiectului (\u0026ldquo;o notez în parking lot, discutăm după\u0026rdquo;) și se asigură că standup-ul nu depășește 15 minute. Rolul poate fi fix sau prin rotație în echipă.\nLa ce servește #Fără facilitator, ședințele se extind natural. Cineva vorbește mai mult decât ar trebui, altcineva nu vorbește niciodată, iar subiectele se multiplică fără control. Facilitatorul este gardianul timpului tuturor — nu este autoritar, este respectuos.\nDe ce contează #Cel mai bun facilitator este cel care taie cu naturalețe: \u0026ldquo;Interesant, discutăm imediat după. Marco, e rândul tău.\u0026rdquo; Fără această figură, standup-ul degenerează în trei săptămâni. Diferența între un standup de 15 minute și unul de 45 este aproape întotdeauna prezența (sau absența) unui facilitator cu coloană vertebrală.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/facilitatore/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eFacilitatorul\u003c/strong\u003e este persoana însărcinată cu ghidarea desfășurării unei ședințe. Nu este cel care decide — este cel care garantează că decizia se ia în mod ordonat, în timpul prevăzut și cu contribuția tuturor participanților.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eFacilitatorul ține timpul, gestionează turele de cuvânt, taie discuțiile în afara subiectului (\u0026ldquo;o notez în parking lot, discutăm după\u0026rdquo;) și se asigură că standup-ul nu depășește 15 minute. Rolul poate fi fix sau prin rotație în echipă.\u003c/p\u003e","title":"Facilitator"},{"content":"Fact table (tabela de fapte) este tabela centrală a unui star schema în data warehouse. Conține măsurile numerice — sume, cantități, contorizări, durate — și cheile externe care o conectează la tabelele dimensionale.\nStructură #Fiecare linie din fact table reprezintă un eveniment sau o tranzacție de business: o vânzare, o daună, o expediere, un acces. Coloanele se împart în două categorii:\nChei externe (foreign keys): indică spre tabelele dimensionale (cine, ce, unde, când) Măsuri: valorile numerice de agregat (sumă, cantitate, marjă) Tipuri de fact tables # Transaction fact: o linie per eveniment (ex. fiecare vânzare) Periodic snapshot: o linie per perioadă per entitate (ex. sold lunar per cont) Accumulating snapshot: o linie per proces, actualizată la fiecare milestone (ex. ciclul comandă-expediere-facturare) Relația cu SCD #Când dimensiunile folosesc SCD Tip 2, fact table-ul indică spre cheia surogat a dimensiunii — nu spre cheia naturală. Acest lucru garantează că fiecare fapt este asociat cu versiunea corectă a dimensiunii pentru momentul în care s-a produs.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/fact-table/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eFact table\u003c/strong\u003e (tabela de fapte) este tabela centrală a unui star schema în data warehouse. Conține măsurile numerice — sume, cantități, contorizări, durate — și cheile externe care o conectează la tabelele dimensionale.\u003c/p\u003e\n\u003ch2 id=\"structură\" class=\"relative group\"\u003eStructură \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#structur%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eFiecare linie din fact table reprezintă un eveniment sau o tranzacție de business: o vânzare, o daună, o expediere, un acces. Coloanele se împart în două categorii:\u003c/p\u003e","title":"Fact table"},{"content":"Float-ul Financiar este lichiditatea pe care o companie o generează din diferența dintre timpii de încasare de la clienții săi (mai scurți) și timpii de plată către furnizorii săi (mai lungi). Este efectiv un împrumut la cost zero obținut pe cheltuiala furnizorilor.\nCum funcționează #O firmă de consultanță încasează de la clientul final la 30 de zile dar plătește consultanții proprii la 90 de zile. Diferența de 60 de zile generează un float: pentru fiecare 100.000€ de venituri lunare, compania dispune de ~200.000€ de lichiditate gratuită pe care o poate investi sau folosi ca capital circulant.\nLa ce servește #Pentru companiile mari este o pârghie financiară structurală. Pentru consultanții freelanceri este mecanismul pervers prin care se trezesc finanțându-și clienții fără dobândă, fără garanții și fără alternativă — pentru că piața \u0026ldquo;funcționează așa.\u0026rdquo;\nDe ce contează #Float-ul financiar este un transfer de avere invizibil de la furnizor la client. Un consultant care lucrează în octombrie și încasează în februarie acordă un împrumut de patru luni. Nimeni nu-l numește așa — îl numesc \u0026ldquo;termeni contractuali.\u0026rdquo; Dar economic este identic.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/float-finanziario/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eFloat-ul Financiar\u003c/strong\u003e este lichiditatea pe care o companie o generează din diferența dintre timpii de încasare de la clienții săi (mai scurți) și timpii de plată către furnizorii săi (mai lungi). Este efectiv un împrumut la cost zero obținut pe cheltuiala furnizorilor.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eO firmă de consultanță încasează de la clientul final la 30 de zile dar plătește consultanții proprii la 90 de zile. Diferența de 60 de zile generează un float: pentru fiecare 100.000€ de venituri lunare, compania dispune de ~200.000€ de lichiditate gratuită pe care o poate investi sau folosi ca capital circulant.\u003c/p\u003e","title":"Float Financiar"},{"content":"FLUSH PRIVILEGES este o comandă MySQL/MariaDB care forțează serverul să reîncarce în memorie tabelele de privilegii din baza de date mysql. Face imediat efective modificările permisiunilor.\nCum funcționează #MySQL menține în memorie un cache al tabelelor de grant (mysql.user, mysql.db, mysql.tables_priv). Când se folosesc CREATE USER și GRANT, MySQL actualizează atât tabelele cât și cache-ul automat. Dar dacă tabelele de grant sunt modificate direct cu INSERT, UPDATE sau DELETE, cache-ul nu se actualizează. FLUSH PRIVILEGES forțează reîncărcarea cache-ului din tabele.\nLa ce folosește #Comanda este necesară după: ștergerea directă a utilizatorilor din tabelul mysql.user, modificări manuale ale privilegiilor prin DML, sau după un DROP USER al utilizatorilor anonimi ca parte a hardening-ului de securitate. Fără FLUSH, modificările nu au efect până la următorul restart al serverului.\nCând se folosește #După orice modificare directă a tabelelor de grant. Dacă se folosesc exclusiv CREATE USER, GRANT, REVOKE și DROP USER, FLUSH nu este tehnic necesar deoarece aceste comenzi actualizează cache-ul automat. Totuși, executarea lui după un DROP USER al utilizatorilor anonimi este o bună practică pentru a garanta consistența.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/flush-privileges/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eFLUSH PRIVILEGES\u003c/strong\u003e este o comandă MySQL/MariaDB care forțează serverul să reîncarce în memorie tabelele de privilegii din baza de date \u003ccode\u003emysql\u003c/code\u003e. Face imediat efective modificările permisiunilor.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eMySQL menține în memorie un cache al tabelelor de grant (\u003ccode\u003emysql.user\u003c/code\u003e, \u003ccode\u003emysql.db\u003c/code\u003e, \u003ccode\u003emysql.tables_priv\u003c/code\u003e). Când se folosesc \u003ccode\u003eCREATE USER\u003c/code\u003e și \u003ccode\u003eGRANT\u003c/code\u003e, MySQL actualizează atât tabelele cât și cache-ul automat. Dar dacă tabelele de grant sunt modificate direct cu \u003ccode\u003eINSERT\u003c/code\u003e, \u003ccode\u003eUPDATE\u003c/code\u003e sau \u003ccode\u003eDELETE\u003c/code\u003e, cache-ul nu se actualizează. \u003ccode\u003eFLUSH PRIVILEGES\u003c/code\u003e forțează reîncărcarea cache-ului din tabele.\u003c/p\u003e","title":"FLUSH PRIVILEGES"},{"content":"Full Table Scan (sau TABLE ACCESS FULL) este o operatie in care baza de date citeste toate blocurile de date ale unei tabele, de la inceput la sfarsit, fara a trece prin vreun index.\nCum functioneaza #Oracle solicita blocuri de pe disc (sau din cache) in secventa, folosind citiri multi-bloc (db file scattered read). Fiecare rand din tabela este examinat, indiferent daca indeplineste sau nu criteriile query-ului.\nCand este o problema #Un full table scan pe o tabela mare este adesea semnul unui index lipsa, al unor statistici depasit sau al unui plan de executie schimbat. In raportul AWR apare ca db file scattered read in sectiunea Top Wait Events, cu procente ridicate de DB time.\nCand este legitim #Pe tabele mici (cateva mii de randuri) sau cand query-ul trebuie efectiv sa citeasca majoritatea datelor, full table scan-ul poate fi mai eficient decat un acces prin index. Problema apare cand Oracle il alege pe tabele cu milioane de randuri pentru a extrage putine inregistrari.\nCum se identifica #In planul de executie (EXPLAIN PLAN sau DBMS_XPLAN) apare ca operatie TABLE ACCESS FULL. In wait event-urile AWR/ASH se manifesta ca db file scattered read dominant.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/full-table-scan/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eFull Table Scan\u003c/strong\u003e (sau TABLE ACCESS FULL) este o operatie in care baza de date citeste toate blocurile de date ale unei tabele, de la inceput la sfarsit, fara a trece prin vreun index.\u003c/p\u003e\n\u003ch2 id=\"cum-functioneaza\" class=\"relative group\"\u003eCum functioneaza \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-functioneaza\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eOracle solicita blocuri de pe disc (sau din cache) in secventa, folosind citiri multi-bloc (\u003ccode\u003edb file scattered read\u003c/code\u003e). Fiecare rand din tabela este examinat, indiferent daca indeplineste sau nu criteriile query-ului.\u003c/p\u003e","title":"Full Table Scan"},{"content":"Un GIN Index (Generalized Inverted Index) este un tip de index PostgreSQL proiectat pentru indexarea valorilor compuse: array-uri, documente JSONB, text cu trigrame și căutări full-text. Spre deosebire de B-Tree, un GIN creează un mapping inversat: de la fiecare element (cuvânt, trigramă, cheie JSON) la înregistrările care îl conțin.\nCum funcționează #Pentru fiecare valoare distinctă din datele indexate, GIN menține o listă de pointeri către rândurile care conțin acea valoare. În cazul pg_trgm, textul este descompus în trigrame (secvențe de 3 caractere) și fiecare trigramă este indexată. O căutare LIKE '%ABC%' este tradusă într-o intersecție de trigrame, evitând scanarea secvențială.\nLa ce folosește #GIN rezolvă problema căutărilor \u0026ldquo;conține\u0026rdquo; (LIKE '%valoare%') pe coloane de text, care cu un B-Tree ar necesita o scanare secvențială a întregii tabele. Pe tabele cu milioane de rânduri, diferența este între secunde și milisecunde.\nCând se folosește #GIN este ideal pe tabele append-only sau cu churn scăzut (puține UPDATE/DELETE), deoarece costul de mentenanță al indexului este mai mare decât al unui B-Tree. Crearea în producție trebuie făcută cu CREATE INDEX CONCURRENTLY pentru a evita lock-urile pe scrieri.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/gin-index/","section":"Glosar","summary":"\u003cp\u003eUn \u003cstrong\u003eGIN Index\u003c/strong\u003e (Generalized Inverted Index) este un tip de index PostgreSQL proiectat pentru indexarea valorilor compuse: array-uri, documente JSONB, text cu trigrame și căutări full-text. Spre deosebire de B-Tree, un GIN creează un mapping inversat: de la fiecare element (cuvânt, trigramă, cheie JSON) la înregistrările care îl conțin.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003ePentru fiecare valoare distinctă din datele indexate, GIN menține o listă de pointeri către rândurile care conțin acea valoare. În cazul \u003ccode\u003epg_trgm\u003c/code\u003e, textul este descompus în trigrame (secvențe de 3 caractere) și fiecare trigramă este indexată. O căutare \u003ccode\u003eLIKE '%ABC%'\u003c/code\u003e este tradusă într-o intersecție de trigrame, evitând scanarea secvențială.\u003c/p\u003e","title":"GIN Index"},{"content":"","date":null,"permalink":"https://ivanluminaria.com/ro/glossary/","section":"Glosar","summary":"","title":"Glosar"},{"content":"Grain-ul (granularitatea) este nivelul de detaliu al unei fact table într-un data warehouse. Definește ce reprezintă un singur rând: o tranzacție, un sumar zilnic, un total lunar, o linie de factură.\nCum funcționează #Alegerea grain-ului este prima decizie la proiectarea unei fact table. Toate celelalte decizii — măsuri, dimensiuni, ETL — decurg din ea:\nGrain fin (ex. linie de factură): flexibilitate maximă în interogări, mai multe rânduri de gestionat Grain agregat (ex. total lunar per client): mai puține rânduri, interogări mai rapide, dar imposibilitatea de a coborî în detaliu Principiul fundamental al lui Kimball: modelează întotdeauna la cel mai fin nivel de detaliu disponibil în sistemul sursă.\nLa ce servește #Grain-ul determină:\nLa ce întrebări poate răspunde data warehouse-ul Ce dimensiuni sunt necesare (un grain la nivel de linie necesită dim_produs, un grain lunar nu) Cât de mare este fact table-ul și cât durează ETL-ul Dacă drill-down-ul în rapoarte este posibil sau nu Când se folosește #Grain-ul se definește în faza de proiectare a modelului dimensional, înainte de a scrie orice DDL sau ETL. Schimbarea grain-ului după go-live echivalează cu reconstruirea data warehouse-ului de la zero — motiv pentru care alegerea inițială este atât de critică.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/grain/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eGrain-ul\u003c/strong\u003e (granularitatea) este nivelul de detaliu al unei fact table într-un data warehouse. Definește ce reprezintă un singur rând: o tranzacție, un sumar zilnic, un total lunar, o linie de factură.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eAlegerea grain-ului este prima decizie la proiectarea unei fact table. Toate celelalte decizii — măsuri, dimensiuni, ETL — decurg din ea:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eGrain fin\u003c/strong\u003e (ex. linie de factură): flexibilitate maximă în interogări, mai multe rânduri de gestionat\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eGrain agregat\u003c/strong\u003e (ex. total lunar per client): mai puține rânduri, interogări mai rapide, dar imposibilitatea de a coborî în detaliu\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003ePrincipiul fundamental al lui Kimball: modelează întotdeauna la cel mai fin nivel de detaliu disponibil în sistemul sursă.\u003c/p\u003e","title":"Grain"},{"content":"GRANT este comanda SQL folosită pentru atribuirea de privilegii unui utilizator sau rol pe obiecte specifice ale bazei de date. În MySQL și MariaDB, privilegiile se atribuie perechii 'utilizator'@'host', nu doar numelui de utilizator.\nCum funcționează #Sintaxa de bază este GRANT \u0026lt;privilegii\u0026gt; ON \u0026lt;baza_de_date\u0026gt;.\u0026lt;tabel\u0026gt; TO 'utilizator'@'host'. Privilegiile pot fi granulare (SELECT, INSERT, UPDATE, DELETE) sau globale (ALL PRIVILEGES). În MySQL 8, GRANT nu mai creează utilizatori implicit: e nevoie mai întâi de un CREATE USER explicit, apoi GRANT. În MySQL 5.7 și MariaDB, GRANT cu IDENTIFIED BY creează utilizatorul și atribuie privilegiile într-o singură comandă.\nLa ce folosește #GRANT este mecanismul fundamental pentru implementarea controlului accesului în bazele de date MySQL/MariaDB. Combinat cu modelul utilizator@host, permite calibrarea privilegiilor în funcție de originea conexiunii: acces complet de pe localhost pentru DBA, doar citire de pe application server.\nCând se folosește #De fiecare dată când se creează un utilizator sau se modifică permisiunile. Best practice-ul este să atribui întotdeauna privilegiul minim necesar (principiul least privilege) și să folosești SHOW GRANTS FOR 'utilizator'@'host' pentru a verifica privilegiile efective.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/grant/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eGRANT\u003c/strong\u003e este comanda SQL folosită pentru atribuirea de privilegii unui utilizator sau rol pe obiecte specifice ale bazei de date. În MySQL și MariaDB, privilegiile se atribuie perechii \u003ccode\u003e'utilizator'@'host'\u003c/code\u003e, nu doar numelui de utilizator.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eSintaxa de bază este \u003ccode\u003eGRANT \u0026lt;privilegii\u0026gt; ON \u0026lt;baza_de_date\u0026gt;.\u0026lt;tabel\u0026gt; TO 'utilizator'@'host'\u003c/code\u003e. Privilegiile pot fi granulare (SELECT, INSERT, UPDATE, DELETE) sau globale (ALL PRIVILEGES). În MySQL 8, GRANT nu mai creează utilizatori implicit: e nevoie mai întâi de un \u003ccode\u003eCREATE USER\u003c/code\u003e explicit, apoi GRANT. În MySQL 5.7 și MariaDB, GRANT cu \u003ccode\u003eIDENTIFIED BY\u003c/code\u003e creează utilizatorul și atribuie privilegiile într-o singură comandă.\u003c/p\u003e","title":"GRANT"},{"content":"Group Replication este mecanismul nativ al MySQL pentru crearea de clustere cu disponibilitate ridicată și replicare sincronă între mai multe noduri. Spre deosebire de replicarea clasică (asincronă, master-slave), Group Replication garantează că fiecare tranzacție este confirmată de majoritatea nodurilor înainte de a fi considerată committed.\nCum funcționează #Nodurile comunică printr-un protocol de grup (GCS — Group Communication System) care gestionează consensul distribuit. Fiecare nod menține o copie completă a datelor. Tranzacțiile sunt certificate de grup: dacă nu există conflicte, sunt aplicate pe toate nodurile. Dacă apare un conflict, tranzacția este anulată pe nodul care a inițiat-o.\nModuri de operare #MySQL Group Replication suportă două moduri: single-primary (un singur nod acceptă scrieri, celelalte sunt read-only) și multi-primary (toate nodurile acceptă scrieri). Modul single-primary este cel mai folosit în producție pentru că evită conflictele de scriere concurentă.\nDe ce contează #Group Replication gestionează automat failover-ul: dacă primary-ul cade, clusterul alege un nou primary dintre secondary în câteva secunde. Acest lucru îl face potrivit pentru medii care necesită disponibilitate ridicată fără intervenție manuală. Necesită minim trei noduri pentru a menține quorum-ul.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/group-replication/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eGroup Replication\u003c/strong\u003e este mecanismul nativ al MySQL pentru crearea de clustere cu disponibilitate ridicată și replicare sincronă între mai multe noduri. Spre deosebire de replicarea clasică (asincronă, master-slave), Group Replication garantează că fiecare tranzacție este confirmată de majoritatea nodurilor înainte de a fi considerată committed.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eNodurile comunică printr-un protocol de grup (GCS — Group Communication System) care gestionează consensul distribuit. Fiecare nod menține o copie completă a datelor. Tranzacțiile sunt certificate de grup: dacă nu există conflicte, sunt aplicate pe toate nodurile. Dacă apare un conflict, tranzacția este anulată pe nodul care a inițiat-o.\u003c/p\u003e","title":"Group Replication"},{"content":"GTID (Global Transaction Identifier) este un identificator unic atribuit automat fiecărei tranzacții confirmate pe un server MySQL. Formatul este server_uuid:transaction_id — de exemplu 3E11FA47-71CA-11E1-9E33-C80AA9429562:23.\nCum funcționează #Când GTID este activat (gtid_mode = ON), fiecare tranzacție primește un identificator care o face trasabilă pe orice server din clusterul de replicare. Replica știe exact ce tranzacții a executat deja și care îi mai lipsesc, fără a fi nevoie să specifice manual pozițiile binlog (fișier + offset).\nSetul tuturor GTID-urilor executate pe un server este stocat în variabila gtid_executed. Când o replică se conectează la sursă, compară propriul gtid_executed cu cel al sursei pentru a determina ce tranzacții lipsesc.\nLa ce servește #GTID simplifică radical gestionarea replicării MySQL:\nFailover automat: când sursa cade, o replică poate deveni noua sursă și celelalte replici se realiniază automat Verificarea consistenței: este posibil să verifici dacă două servere au executat exact aceleași tranzacții Backup și restore: instrumente precum mysqldump și mydumper trebuie să gestioneze corect GTID-urile pentru a evita conflictele de replicare după restore Când creează probleme #GTID-urile necesită atenție în timpul operațiunilor de backup și restore. Dacă se restaurează un dump pe un server cu GTID activ fără a configura corect --set-gtid-purged, se pot genera conflicte care rup lanțul de replicare.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/gtid/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eGTID\u003c/strong\u003e (Global Transaction Identifier) este un identificator unic atribuit automat fiecărei tranzacții confirmate pe un server MySQL. Formatul este \u003ccode\u003eserver_uuid:transaction_id\u003c/code\u003e — de exemplu \u003ccode\u003e3E11FA47-71CA-11E1-9E33-C80AA9429562:23\u003c/code\u003e.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eCând GTID este activat (\u003ccode\u003egtid_mode = ON\u003c/code\u003e), fiecare tranzacție primește un identificator care o face trasabilă pe orice server din clusterul de replicare. Replica știe exact ce tranzacții a executat deja și care îi mai lipsesc, fără a fi nevoie să specifice manual pozițiile binlog (fișier + offset).\u003c/p\u003e","title":"GTID"},{"content":"Hash join este o strategie de join proiectata pentru volume mari de date. Functioneaza in doua faze: mai intai construieste o structura de date in memorie, apoi o foloseste pentru a gasi corespondentele eficient.\nCum functioneaza #Baza de date citeste tabelul mai mic (build side) si construieste o hash table in memorie, indexand randurile dupa coloana de join. Apoi scaneaza tabelul mai mare (probe side) si pentru fiecare rand cauta corespondenta in hash table cu un lookup O(1).\nComplexitatea este liniara — proportionala cu suma randurilor din ambele tabele, nu cu produsul ca in nested loop. Nu sunt necesare indexuri: hash table-ul inlocuieste temporar indexul.\nCand este alegerea corecta #Optimizatorul alege hash join cand ambele tabele sunt mari si nu exista indexuri utile, sau cand statisticile indica ca numarul de randuri de combinat este prea mare pentru un nested loop eficient. Este una dintre cele mai comune strategii in data warehouse-uri si rapoarte care agrega milioane de randuri.\nCe poate merge prost #Punctul slab este memoria. Hash table-ul trebuie sa incapa in work_mem: daca tabelul mai mic nu incape, baza de date scrie loturi pe disc (batched hash join), cu o degradare semnificativa a performantei.\nwork_mem prea mic: hash table-ul este impartit in loturi pe disc, multiplicand I/O-ul Estimari gresite: optimizatorul alege ca build side tabelul gresit pentru ca statisticile indica mai putine randuri decat realitatea Skew in date: daca o valoare in coloana de join domina majoritatea randurilor, un bucket al hash table-ului devine enorm in timp ce restul raman goale ","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/hash-join/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eHash join\u003c/strong\u003e este o strategie de join proiectata pentru volume mari de date. Functioneaza in doua faze: mai intai construieste o structura de date in memorie, apoi o foloseste pentru a gasi corespondentele eficient.\u003c/p\u003e\n\u003ch2 id=\"cum-functioneaza\" class=\"relative group\"\u003eCum functioneaza \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-functioneaza\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eBaza de date citeste tabelul mai mic (build side) si construieste o hash table in memorie, indexand randurile dupa coloana de join. Apoi scaneaza tabelul mai mare (probe side) si pentru fiecare rand cauta corespondenta in hash table cu un lookup O(1).\u003c/p\u003e","title":"Hash Join"},{"content":"Hot Desk (hot desking) este un model de organizare a spațiilor de lucru în care birourile nu sunt atribuite angajaților individuali. Cine vine la birou ocupă un post de lucru liber, de obicei rezervabil printr-un sistem digital.\nCum funcționează #În loc de 50 de posturi fixe pentru 50 de angajați, compania amenajează 15-20 de posturi partajate (hot desks) echipate cu monitor, docking station și conectivitate. Angajații rezervă postul în zilele în care trebuie să fie la birou, folosind celelalte zile în smart working.\nLa ce servește #Reduce drastic costurile imobiliare: de la 50 de posturi la 15 se economisesc aproximativ 70% din spațiu și costurile aferente (chirie, utilități, curățenie, întreținere). Spațiul economisit poate fi convertit în săli de ședință adecvate și zone colaborative.\nCe poate merge prost #Fără un sistem de rezervare eficient, apar conflicte și frustrare. Angajații care nu au \u0026ldquo;propriul birou\u0026rdquo; se pot simți mai puțin ancorați în companie. Soluția este combinarea hot desk-urilor cu spații personale (dulapuri) și zone de echipă dedicate.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/hot-desk/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eHot Desk\u003c/strong\u003e (hot desking) este un model de organizare a spațiilor de lucru în care birourile nu sunt atribuite angajaților individuali. Cine vine la birou ocupă un post de lucru liber, de obicei rezervabil printr-un sistem digital.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eÎn loc de 50 de posturi fixe pentru 50 de angajați, compania amenajează 15-20 de posturi partajate (hot desks) echipate cu monitor, docking station și conectivitate. Angajații rezervă postul în zilele în care trebuie să fie la birou, folosind celelalte zile în smart working.\u003c/p\u003e","title":"Hot Desk"},{"content":"Huge Pages sunt pagini de memorie de 2 MB, față de cele standard de 4 KB ale Linux. Pentru o SGA Oracle de 64 GB, trecerea de la pagini de 4 KB (16,7 milioane de pagini) la Huge Pages de 2 MB (32.768 pagini) reduce de 500 de ori numărul de intrări în Page Table.\nCum funcționează #Se configurează prin parametrul kernel vm.nr_hugepages în /etc/sysctl.d/. Numărul necesar se calculează împărțind dimensiunea SGA la 2 MB și adăugând o marjă de 1,5%. După repornirea instanței Oracle, SGA este alocată în Huge Pages, verificabil din /proc/meminfo.\nLa ce servește #Reduc presiunea pe TLB-ul (Translation Lookaside Buffer) CPU-ului, care poate memora doar câteva mii de traduceri de adrese. Cu pagini normale, TLB-ul face overflow constant iar MMU-ul trebuie să gestioneze milioane de traduceri — cu impact măsurabil pe latch free waits și library cache contention.\nDe ce contează #Este singurul parametru cu cel mai mare impact pentru Oracle pe Linux, și cel ignorat cel mai des. Asistentul de instalare nu îl configurează, documentația e într-o notă MOS, iar sistemul \u0026ldquo;funcționează și fără.\u0026rdquo; Dar metricile înainte/după vorbesc clar: library cache hit ratio de la 92% la 99,7%, CPU de la 78% la 41%.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/huge-pages/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eHuge Pages\u003c/strong\u003e sunt pagini de memorie de 2 MB, față de cele standard de 4 KB ale Linux. Pentru o SGA Oracle de 64 GB, trecerea de la pagini de 4 KB (16,7 milioane de pagini) la Huge Pages de 2 MB (32.768 pagini) reduce de 500 de ori numărul de intrări în Page Table.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eSe configurează prin parametrul kernel \u003ccode\u003evm.nr_hugepages\u003c/code\u003e în \u003ccode\u003e/etc/sysctl.d/\u003c/code\u003e. Numărul necesar se calculează împărțind dimensiunea SGA la 2 MB și adăugând o marjă de 1,5%. După repornirea instanței Oracle, SGA este alocată în Huge Pages, verificabil din \u003ccode\u003e/proc/meminfo\u003c/code\u003e.\u003c/p\u003e","title":"Huge Pages"},{"content":"I/O Scheduler este componenta kernelului Linux care gestionează coada cererilor de citire și scriere către dispozitivele bloc (discuri). Decide ordinea de execuție a cererilor pentru a optimiza throughput-ul și a minimiza latența.\nCum funcționează #Linux oferă mai mulți scheduleri: cfq (Completely Fair Queuing, pentru desktop), deadline/mq-deadline (pentru servere și baze de date), noop/none (pentru SSD/NVMe). Pentru Oracle recomandarea este deadline, care servește cererile minimizând seek-urile discului. Se configurează prin /sys/block/sdX/queue/scheduler și se face permanent prin GRUB.\nLa ce servește #cfq-ul implicit distribuie I/O-ul egal între procese — ideal pentru desktop, dezastruos pentru o bază de date care are nevoie de prioritate pe cererile I/O critice. deadline garantează că nicio cerere nu rămâne în coadă prea mult timp, reducând latența db file sequential read.\nCe poate merge prost #Lăsarea valorii implicite (cfq sau bfq pe unele sisteme) înseamnă că Oracle concurează pentru I/O cu toate celelalte procese ale sistemului. Pe un server dedicat bazei de date este o risipă: baza de date ar trebui să aibă prioritate absolută pe operațiunile de disc.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/io-scheduler/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eI/O Scheduler\u003c/strong\u003e este componenta kernelului Linux care gestionează coada cererilor de citire și scriere către dispozitivele bloc (discuri). Decide ordinea de execuție a cererilor pentru a optimiza throughput-ul și a minimiza latența.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eLinux oferă mai mulți scheduleri: \u003ccode\u003ecfq\u003c/code\u003e (Completely Fair Queuing, pentru desktop), \u003ccode\u003edeadline\u003c/code\u003e/\u003ccode\u003emq-deadline\u003c/code\u003e (pentru servere și baze de date), \u003ccode\u003enoop\u003c/code\u003e/\u003ccode\u003enone\u003c/code\u003e (pentru SSD/NVMe). Pentru Oracle recomandarea este \u003ccode\u003edeadline\u003c/code\u003e, care servește cererile minimizând seek-urile discului. Se configurează prin \u003ccode\u003e/sys/block/sdX/queue/scheduler\u003c/code\u003e și se face permanent prin GRUB.\u003c/p\u003e","title":"I/O Scheduler"},{"content":"INTO OUTFILE este o clauză SQL MySQL care permite exportul rezultatului unei interogări direct într-un fișier pe filesystem-ul serverului de baze de date. Este metoda nativă pentru generarea de fișiere CSV, TSV sau cu separatori personalizați.\nCum funcționează #Clauza se adaugă la sfârșitul unui SELECT și specifică calea fișierului de destinație. Parametrii FIELDS TERMINATED BY, ENCLOSED BY și LINES TERMINATED BY controlează formatul output-ului. Fișierul este creat de utilizatorul de sistem MySQL (nu de utilizatorul care execută query-ul), deci trebuie să fie într-un director cu permisiunile corecte.\nLa ce folosește #INTO OUTFILE e util pentru exporturi masive de date din baza de date în fișiere text structurate. Este complementul lui LOAD DATA INFILE, care face operațiunea inversă (importă date din fișiere). Împreună formează mecanismul nativ MySQL pentru import/export în masă.\nCând se folosește #Utilizarea e guvernată de directiva secure-file-priv: fișierul de destinație trebuie să fie în directorul autorizat. Când secure-file-priv blochează calea dorită, alternativa e folosirea clientului mysql din shell cu -B -e și redirecționarea output-ului, care nu e supusă acelorași restricții.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/into-outfile/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eINTO OUTFILE\u003c/strong\u003e este o clauză SQL MySQL care permite exportul rezultatului unei interogări direct într-un fișier pe filesystem-ul serverului de baze de date. Este metoda nativă pentru generarea de fișiere CSV, TSV sau cu separatori personalizați.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eClauza se adaugă la sfârșitul unui \u003ccode\u003eSELECT\u003c/code\u003e și specifică calea fișierului de destinație. Parametrii \u003ccode\u003eFIELDS TERMINATED BY\u003c/code\u003e, \u003ccode\u003eENCLOSED BY\u003c/code\u003e și \u003ccode\u003eLINES TERMINATED BY\u003c/code\u003e controlează formatul output-ului. Fișierul este creat de utilizatorul de sistem MySQL (nu de utilizatorul care execută query-ul), deci trebuie să fie într-un director cu permisiunile corecte.\u003c/p\u003e","title":"INTO OUTFILE"},{"content":"Un Issue Tracker este un sistem pentru înregistrarea, atribuirea, prioritizarea și monitorizarea bug-urilor, cererilor de funcționalități și task-urilor de proiect. Pe GitHub este integrat direct în repository-ul de cod.\nCum funcționează #Fiecare problemă sau cerere este creată ca \u0026ldquo;issue\u0026rdquo; cu titlu, descriere, etichete de categorie/prioritate și atribuire unui dezvoltator. Issue-urile pot fi legate de branch-uri și Pull Request-uri: când un PR care referențiază un issue este fuzionat, issue-ul se închide automat. Aceasta creează o trasabilitate completă de la problemă la soluție.\nLa ce folosește #Issue tracker-ul înlocuiește emailurile, chat-ul, tabelele Excel și raportările verbale cu un sistem unic și structurat. Fiecare bug are o istorie: cine l-a raportat, cine lucrează la el, care e starea, ce cod l-a rezolvat. În proiectele haotice, issue tracker-ul este instrumentul care transformă confuzia în vizibilitate.\nCând se folosește #Pe orice proiect software, indiferent de dimensiune. Alternativa — raportări împrăștiate pe email, chat și Excel — este cauza principală a pierderii informațiilor și a duplicării muncii. GitHub Issues, Jira și Linear sunt cele mai răspândite platforme.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/issue-tracker/","section":"Glosar","summary":"\u003cp\u003eUn \u003cstrong\u003eIssue Tracker\u003c/strong\u003e este un sistem pentru înregistrarea, atribuirea, prioritizarea și monitorizarea bug-urilor, cererilor de funcționalități și task-urilor de proiect. Pe GitHub este integrat direct în repository-ul de cod.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eFiecare problemă sau cerere este creată ca \u0026ldquo;issue\u0026rdquo; cu titlu, descriere, etichete de categorie/prioritate și atribuire unui dezvoltator. Issue-urile pot fi legate de branch-uri și Pull Request-uri: când un PR care referențiază un issue este fuzionat, issue-ul se închide automat. Aceasta creează o trasabilitate completă de la problemă la soluție.\u003c/p\u003e","title":"Issue Tracker"},{"content":"IST (Incremental State Transfer) este mecanismul prin care un nod Galera care revine în cluster după o absență scurtă primește doar tranzacțiile lipsă, fără a fi nevoie să descarce întregul set de date.\nCum funcționează #Când un nod se reconectează la cluster, donatorul verifică dacă tranzacțiile lipsă sunt încă disponibile în gcache-ul său (Galera cache). Dacă gap-ul este acoperit de gcache, se execută un IST: doar tranzacțiile lipsă sunt trimise nodului, care le aplică și revine în starea Synced. Dacă gap-ul depășește gcache-ul, Galera recurge la un SST complet.\nLa ce folosește #IST face ca revenirea unui nod în cluster să fie mult mai rapidă decât un SST complet. Un nod care a fost offline câteva minute sau ore poate redeveni operațional în câteva secunde, fără impact asupra performanței clusterului.\nCând se folosește #IST este declanșat automat când condițiile o permit. Dimensiunea gcache-ului (gcache.size) determină câte tranzacții poate păstra clusterul în memorie pentru a suporta IST. Un gcache mai mare permite perioade mai lungi de inactivitate ale unui nod fără necesitatea unui SST.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/ist/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eIST\u003c/strong\u003e (Incremental State Transfer) este mecanismul prin care un nod Galera care revine în cluster după o absență scurtă primește doar tranzacțiile lipsă, fără a fi nevoie să descarce întregul set de date.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eCând un nod se reconectează la cluster, donatorul verifică dacă tranzacțiile lipsă sunt încă disponibile în gcache-ul său (Galera cache). Dacă gap-ul este acoperit de gcache, se execută un IST: doar tranzacțiile lipsă sunt trimise nodului, care le aplică și revine în starea Synced. Dacă gap-ul depășește gcache-ul, Galera recurge la un SST complet.\u003c/p\u003e","title":"IST"},{"content":"Kimball se referă la Ralph Kimball și la metodologia sa de proiectare a data warehouse-urilor, descrisă în cartea The Data Warehouse Toolkit (prima ediție 1996, a treia ediție 2013).\nAbordarea #Metodologia Kimball se bazează pe trei piloni:\nDimensional modeling: organizarea datelor în star schema cu fact tables și dimension tables, optimizate pentru interogări analitice Bottom-up: construirea DWH-ului pornind de la data mart-uri departamentale individuale, integrându-le progresiv prin dimensiuni conforme (conformed dimensions) Bus architecture: un framework pentru a garanta coerența între data mart-uri prin dimensiuni și fapte partajate Slowly Changing Dimensions #Kimball a definit clasificarea SCD (Slowly Changing Dimensions) în tipurile de la 0 la 7, care a devenit standardul de facto în industrie. Tipul 2 — cu chei surogat și date de valabilitate — este cel mai utilizat pentru urmărirea istoriei dimensiunilor.\nKimball vs Inmon #Alternativa principală este metodologia lui Bill Inmon, care propune o abordare top-down cu un enterprise data warehouse normalizat (3NF) din care se derivă data mart-urile. Cele două metodologii nu sunt mutual exclusive și multe proiecte reale adoptă elemente din ambele.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/kimball/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eKimball\u003c/strong\u003e se referă la Ralph Kimball și la metodologia sa de proiectare a data warehouse-urilor, descrisă în cartea \u003cem\u003eThe Data Warehouse Toolkit\u003c/em\u003e (prima ediție 1996, a treia ediție 2013).\u003c/p\u003e\n\u003ch2 id=\"abordarea\" class=\"relative group\"\u003eAbordarea \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#abordarea\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eMetodologia Kimball se bazează pe trei piloni:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eDimensional modeling\u003c/strong\u003e: organizarea datelor în star schema cu fact tables și dimension tables, optimizate pentru interogări analitice\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eBottom-up\u003c/strong\u003e: construirea DWH-ului pornind de la data mart-uri departamentale individuale, integrându-le progresiv prin dimensiuni conforme (conformed dimensions)\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eBus architecture\u003c/strong\u003e: un framework pentru a garanta coerența între data mart-uri prin dimensiuni și fapte partajate\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"slowly-changing-dimensions\" class=\"relative group\"\u003eSlowly Changing Dimensions \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#slowly-changing-dimensions\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eKimball a definit clasificarea SCD (Slowly Changing Dimensions) în tipurile de la 0 la 7, care a devenit standardul de facto în industrie. Tipul 2 — cu chei surogat și date de valabilitate — este cel mai utilizat pentru urmărirea istoriei dimensiunilor.\u003c/p\u003e","title":"Kimball"},{"content":"Knowledge Transfer (transfer de cunoștințe) este procesul prin care competențe, informații și know-how sunt transferate de la cei care le dețin la cei care au nevoie de ele — între colegi, între echipe, sau între persoane și sisteme de documentare.\nCum funcționează #Poate fi formal (documentare, sesiuni de training, wiki-uri) sau informal (pair programming, mentorat, însoțire). AI-ul poate accelera knowledge transfer-ul generând documentație din cod, commituri și issue-uri — nu perfectă, dar suficientă pentru a nu pierde cunoștințe când cineva părăsește proiectul.\nLa ce servește #Fiecare proiect IT depinde de cunoașterea tacită a persoanelor care lucrează la el. Când un developer senior părăsește echipa fără să-și fi documentat deciziile arhitecturale, costul pierderii este invizibil dar enorm: săptămâni de reverse engineering, bug-uri introduse din neînțelegere, decizii repetate pentru că nimeni nu își amintește raționalul.\nDe ce contează #Este unul dintre cele trei domenii unde AI-ul generează valoare concretă în project management. Nimeni nu documentează de bună voie — AI-ul poate acoperi acest gol. Dar knowledge transfer-ul nu este doar documentare: este și capacitatea de a transfera context, motivații și lecții învățate, nu doar instrucțiuni operaționale.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/knowledge-transfer/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eKnowledge Transfer\u003c/strong\u003e (transfer de cunoștințe) este procesul prin care competențe, informații și know-how sunt transferate de la cei care le dețin la cei care au nevoie de ele — între colegi, între echipe, sau între persoane și sisteme de documentare.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003ePoate fi formal (documentare, sesiuni de training, wiki-uri) sau informal (pair programming, mentorat, însoțire). AI-ul poate accelera knowledge transfer-ul generând documentație din cod, commituri și issue-uri — nu perfectă, dar suficientă pentru a nu pierde cunoștințe când cineva părăsește proiectul.\u003c/p\u003e","title":"Knowledge Transfer"},{"content":"Un KPI (Key Performance Indicator) este o metrică cuantificabilă folosită pentru a evalua succesul unei activități, proiect sau organizații față de obiective predefinite. În contextul muncii la distanță, KPI-urile înlocuiesc prezența fizică ca indicator de productivitate.\nCum funcționează #Un KPI eficient este specific, măsurabil și legat de un obiectiv concret. În consultanța IT: tickete închise, cod livrat, SLA-uri respectate, clienți satisfăcuți. Nu \u0026ldquo;ore la birou\u0026rdquo; — pentru că orele nu măsoară valoarea produsă, măsoară doar timpul petrecut.\nLa ce servește #Permite gestionarea muncii prin obiective în loc de prezență. Un consultant care închide 20 de tickete de acasă este mai productiv decât unul care închide 8 la birou. KPI-urile fac această diferență vizibilă și măsurabilă, eliminând spațiul pentru percepția subiectivă.\nDe ce contează #Companiile care nu știu să definească KPI-uri clare nu pot adopta smart working-ul serios. Fără metrici obiective, managementul recurge la controlul vizual — \u0026ldquo;dacă te văd la birou, lucrezi\u0026rdquo; — care este presupunerea greșită la baza presenteismului.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/kpi/","section":"Glosar","summary":"\u003cp\u003eUn \u003cstrong\u003eKPI\u003c/strong\u003e (Key Performance Indicator) este o metrică cuantificabilă folosită pentru a evalua succesul unei activități, proiect sau organizații față de obiective predefinite. În contextul muncii la distanță, KPI-urile înlocuiesc prezența fizică ca indicator de productivitate.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eUn KPI eficient este specific, măsurabil și legat de un obiectiv concret. În consultanța IT: tickete închise, cod livrat, SLA-uri respectate, clienți satisfăcuți. Nu \u0026ldquo;ore la birou\u0026rdquo; — pentru că orele nu măsoară valoarea produsă, măsoară doar timpul petrecut.\u003c/p\u003e","title":"KPI"},{"content":"Least Privilege (principiul privilegiului minim) este un principiu fundamental al securității informatice: fiecare utilizator, proces sau sistem trebuie să aibă doar permisiunile strict necesare pentru a-și îndeplini funcția, nimic mai mult.\nCum funcționează #În contextul bazelor de date, principiul se aplică atribuind privilegii granulare: SELECT dacă utilizatorul trebuie doar să citească, SELECT + INSERT + UPDATE dacă trebuie și să scrie, niciodată ALL PRIVILEGES dacă nu este strict necesar. Combinat cu modelul utilizator@host al MySQL, principiul poate fi aplicat și în funcție de originea conexiunii.\nLa ce folosește #Limitarea privilegiilor reduce suprafața de atac. Dacă o aplicație este compromisă, atacatorul moștenește privilegiile utilizatorului de bază de date al aplicației. Dacă acel utilizator are doar SELECT pe o bază de date specifică, daunele sunt limitate. Dacă are ALL PRIVILEGES, întregul server este în pericol.\nCând se folosește #Întotdeauna. Principiul least privilege este aplicabil în orice context: utilizatori de baze de date, utilizatori de sistem de operare, roluri aplicative, conturi de serviciu. Tentația de a atribui privilegii largi \u0026ldquo;pentru a nu avea probleme\u0026rdquo; este cauza cea mai frecventă a incidentelor de securitate evitabile.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/least-privilege/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eLeast Privilege\u003c/strong\u003e (principiul privilegiului minim) este un principiu fundamental al securității informatice: fiecare utilizator, proces sau sistem trebuie să aibă doar permisiunile strict necesare pentru a-și îndeplini funcția, nimic mai mult.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eÎn contextul bazelor de date, principiul se aplică atribuind privilegii granulare: \u003ccode\u003eSELECT\u003c/code\u003e dacă utilizatorul trebuie doar să citească, \u003ccode\u003eSELECT + INSERT + UPDATE\u003c/code\u003e dacă trebuie și să scrie, niciodată \u003ccode\u003eALL PRIVILEGES\u003c/code\u003e dacă nu este strict necesar. Combinat cu modelul \u003ccode\u003eutilizator@host\u003c/code\u003e al MySQL, principiul poate fi aplicat și în funcție de originea conexiunii.\u003c/p\u003e","title":"Least Privilege"},{"content":"Lift-and-Shift (rehosting) este o strategie de migrare care constă în mutarea unui sistem dintr-un mediu în altul — de obicei din on-premise în cloud — fără a-i modifica arhitectura, codul aplicativ sau configurația. Sistemul este luat ca atare și \u0026ldquo;ridicat și mutat\u0026rdquo;.\nCum funcționează #Infrastructura este replicată în mediul de destinație: aceleași mașini virtuale, aceleași baze de date, același middleware. Avantajul este viteza: nu există rescrierea codului, nu există reproiectare arhitecturală. Riscul este de a duce cu sine toate problemele din mediul original, inclusiv ineficiențele și datoria tehnică.\nCând se folosește #Când prioritatea este ieșirea rapidă dintr-un datacenter (expirare contract, dezafectare hardware), când bugetul nu permite o rearchitectură, sau ca primă fază a unei migrări incrementale unde componentele sunt apoi modernizate una câte una.\nCe poate merge prost #Un lift-and-shift către cloud fără optimizare poate costa mai mult decât infrastructura on-premise originală. Aplicațiile neproiectate pentru cloud nu profită de elasticitate, auto-scaling și servicii gestionate. Rezultatul este adesea un datacenter privat reconstruit în cloud la un preț superior.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/lift-and-shift/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eLift-and-Shift\u003c/strong\u003e (rehosting) este o strategie de migrare care constă în mutarea unui sistem dintr-un mediu în altul — de obicei din on-premise în cloud — fără a-i modifica arhitectura, codul aplicativ sau configurația. Sistemul este luat ca atare și \u0026ldquo;ridicat și mutat\u0026rdquo;.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eInfrastructura este replicată în mediul de destinație: aceleași mașini virtuale, aceleași baze de date, același middleware. Avantajul este viteza: nu există rescrierea codului, nu există reproiectare arhitecturală. Riscul este de a duce cu sine toate problemele din mediul original, inclusiv ineficiențele și datoria tehnică.\u003c/p\u003e","title":"Lift-and-Shift"},{"content":"Un Local Index este un index Oracle creat pe o tabelă partițională, care este automat partiționat cu aceeași cheie și aceleași limite ca tabela. Fiecare partiție a tabelei are o partiție de index corespunzătoare.\nCum funcționează #Când se creează un index cu clauza LOCAL, Oracle creează o partiție de index pentru fiecare partiție a tabelei. Dacă tabela are 100 de partiții lunare, indexul va avea 100 de partiții corespunzătoare. Operațiile DDL pe o partiție (DROP, TRUNCATE, SPLIT) invalidează doar partiția de index corespunzătoare, nu întregul index.\nLa ce folosește #Local Index este alegerea preferată pentru indexuri pe tabele partiționale deoarece menține independența partițiilor. Un DROP PARTITION durează mai puțin de o secundă și nu invalidează niciun alt index. Cu un index global, aceeași operație ar invalida întregul index, necesitând ore de rebuild.\nCând se folosește #Se folosește când indexul include cheia de partiție sau când interogările filtrează întotdeauna pe coloana de partiție. Pentru lookup-uri punctuale pe coloane non-partiție (ex. cheie primară), e nevoie de un index global. Regula: local unde e posibil, global doar unde e necesar.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/local-index/","section":"Glosar","summary":"\u003cp\u003eUn \u003cstrong\u003eLocal Index\u003c/strong\u003e este un index Oracle creat pe o tabelă partițională, care este automat partiționat cu aceeași cheie și aceleași limite ca tabela. Fiecare partiție a tabelei are o partiție de index corespunzătoare.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eCând se creează un index cu clauza \u003ccode\u003eLOCAL\u003c/code\u003e, Oracle creează o partiție de index pentru fiecare partiție a tabelei. Dacă tabela are 100 de partiții lunare, indexul va avea 100 de partiții corespunzătoare. Operațiile DDL pe o partiție (DROP, TRUNCATE, SPLIT) invalidează doar partiția de index corespunzătoare, nu întregul index.\u003c/p\u003e","title":"Local Index"},{"content":"MERGE este o instrucțiune SQL care combină operațiunile de INSERT și UPDATE (și opțional DELETE) într-un singur statement. Dacă înregistrarea există o actualizează, dacă nu există o inserează. Este numită informal \u0026ldquo;upsert\u0026rdquo;.\nSintaxă Oracle #MERGE INTO tabel_destinatie d USING tabel_sursa s ON (d.cheie = s.cheie) WHEN MATCHED THEN UPDATE SET d.camp = s.camp WHEN NOT MATCHED THEN INSERT (cheie, camp) VALUES (s.cheie, s.camp); Utilizare în data warehouse #În contextul ETL, MERGE este mecanismul de bază pentru încărcarea tabelelor dimensionale:\nSCD Tip 1: un singur MERGE care actualizează înregistrările existente și le inserează pe cele noi SCD Tip 2: MERGE-ul este folosit în prima fază pentru a închide înregistrările modificate (setând data de sfârșit de valabilitate), urmat de un INSERT pentru noile versiuni Disponibilitate # Oracle: suport complet din versiunea 9i PostgreSQL: nu are MERGE nativ până la versiunea 15. Alternativa este INSERT ... ON CONFLICT (upsert) MySQL: folosește INSERT ... ON DUPLICATE KEY UPDATE ca alternativă SQL Server: suport complet cu sintaxă similară cu Oracle ","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/merge-sql/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eMERGE\u003c/strong\u003e este o instrucțiune SQL care combină operațiunile de INSERT și UPDATE (și opțional DELETE) într-un singur statement. Dacă înregistrarea există o actualizează, dacă nu există o inserează. Este numită informal \u0026ldquo;upsert\u0026rdquo;.\u003c/p\u003e\n\u003ch2 id=\"sintaxă-oracle\" class=\"relative group\"\u003eSintaxă Oracle \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#sintax%c4%83-oracle\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-sql\" data-lang=\"sql\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eMERGE\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eINTO\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003etabel_destinatie\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ed\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003eUSING\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003etabel_sursa\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003es\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eON\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ed\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003echeie\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003es\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003echeie\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003eWHEN\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eMATCHED\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eTHEN\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eUPDATE\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eSET\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"n\"\u003ed\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003ecamp\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003es\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003ecamp\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003eWHEN\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eNOT\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eMATCHED\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eTHEN\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eINSERT\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003echeie\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ecamp\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"k\"\u003eVALUES\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003es\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003echeie\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003es\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003ecamp\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"utilizare-în-data-warehouse\" class=\"relative group\"\u003eUtilizare în data warehouse \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#utilizare-%c3%aen-data-warehouse\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eÎn contextul ETL, MERGE este mecanismul de bază pentru încărcarea tabelelor dimensionale:\u003c/p\u003e","title":"MERGE"},{"content":"Mobilitatea Durabilă este o abordare a transportului urban care privilegiază utilizarea mijloacelor cu impact scăzut asupra mediului — bicicletă, transport public, vehicule electrice, car sharing — față de mașina privată cu motor cu combustie internă.\nCum funcționează #Se bazează pe o schimbare de paradigmă: în loc să se construiască mai multe drumuri pentru mai multe mașini, se investește în infrastructură ciclabilă, transport public eficient și stimulente pentru mobilitatea activă. Orașe precum Amsterdam, Copenhaga și München demonstrează că modelul funcționează la scară largă.\nLa ce servește #Reduce emisiile, traficul, costurile individuale și colective, poluarea fonică și ocuparea terenului. Pentru navetistul individual, înseamnă economisirea a până la 5.450€ pe an și 455 de ore de timp comparativ cu mașina — două luni și jumătate de viață returnate.\nDe ce contează #Roma are 300 de zile însorite pe an, un climat blând și distanțe urbane conținute. Este paradoxal unul dintre orașele italiene cele mai potrivite pentru bicicletă. Lipsesc infrastructurile și curajul de a schimba obiceiurile. Modelul ideal combină smart working-ul (3 zile la distanță) cu mobilitatea durabilă (2 zile pe bicicletă): de la 13 ore săptămânale călătorind la 1 oră și 12 minute.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/mobilita-sostenibile/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eMobilitatea Durabilă\u003c/strong\u003e este o abordare a transportului urban care privilegiază utilizarea mijloacelor cu impact scăzut asupra mediului — bicicletă, transport public, vehicule electrice, car sharing — față de mașina privată cu motor cu combustie internă.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eSe bazează pe o schimbare de paradigmă: în loc să se construiască mai multe drumuri pentru mai multe mașini, se investește în infrastructură ciclabilă, transport public eficient și stimulente pentru mobilitatea activă. Orașe precum Amsterdam, Copenhaga și München demonstrează că modelul funcționează la scară largă.\u003c/p\u003e","title":"Mobilitate Durabilă"},{"content":"MVCC (Multi-Version Concurrency Control) este modelul de concurență folosit de PostgreSQL pentru a gestiona accesul simultan la date. Fiecare UPDATE creează o nouă versiune a rândului și o marchează pe cea veche ca \u0026ldquo;moartă\u0026rdquo;; fiecare DELETE marchează rândul ca nevizibil. Citirile nu blochează scrierile și invers.\nCum funcționează #Fiecare tranzacție vede un snapshot consistent al bazei de date din momentul începerii sale. Rândurile modificate de alte tranzacții neconfirmate sunt invizibile. Aceasta elimină nevoia de lock-uri exclusive pe citiri, permițând concurență ridicată — dar generează \u0026ldquo;gunoi\u0026rdquo; sub formă de dead tuples care trebuie curățate de VACUUM.\nLa ce servește #MVCC este compromisul arhitectural al PostgreSQL: concurență ridicată fără lock-uri, la prețul de a gestiona curățarea versiunilor obsolete. Este un preț rezonabil — cu condiția ca autovacuum-ul să fie configurat corect pentru a ține pasul cu ritmul de modificare al tabelelor.\nDe ce contează #Dacă VACUUM nu poate ține pasul cu rata de generare a dead tuple-urilor, tabelele se umflă (bloat), scanările secvențiale încetinesc iar indexurile devin ineficiente. Tiparul clasic: luni baza de date merge bine, vineri e un dezastru.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/mvcc/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eMVCC\u003c/strong\u003e (Multi-Version Concurrency Control) este modelul de concurență folosit de PostgreSQL pentru a gestiona accesul simultan la date. Fiecare UPDATE creează o nouă versiune a rândului și o marchează pe cea veche ca \u0026ldquo;moartă\u0026rdquo;; fiecare DELETE marchează rândul ca nevizibil. Citirile nu blochează scrierile și invers.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eFiecare tranzacție vede un snapshot consistent al bazei de date din momentul începerii sale. Rândurile modificate de alte tranzacții neconfirmate sunt invizibile. Aceasta elimină nevoia de lock-uri exclusive pe citiri, permițând concurență ridicată — dar generează \u0026ldquo;gunoi\u0026rdquo; sub formă de dead tuples care trebuie curățate de VACUUM.\u003c/p\u003e","title":"MVCC"},{"content":"mydumper este un instrument open source de backup logic pentru MySQL și MariaDB care implementează paralelism adevărat: nu doar între tabele diferite, ci și în interiorul aceleiași tabele, împărțind-o în chunk-uri bazate pe primary key.\nCum funcționează #mydumper se conectează la serverul MySQL, achiziționează un snapshot consistent cu FLUSH TABLES WITH READ LOCK (sau --trx-consistency-only pentru a evita lock-urile globale pe InnoDB), apoi distribuie munca între thread-uri multiple. Fiecare tabelă mare este spartă în chunk-uri — implicit bazate pe range-urile primary key-ului — și fiecare chunk este exportat de un thread separat.\nOutput-ul nu este un singur fișier SQL ci un director cu un fișier pentru fiecare tabelă (sau pentru fiecare chunk), plus fișierele de metadate, schemă și proceduri stocate.\nRestore-ul cu myloader #Companionul lui mydumper este myloader, care încarcă fișierele în paralel dezactivând verificările de foreign key și reconstruind indexurile la sfârșit. Această abordare face restore-ul semnificativ mai rapid comparativ cu încărcarea secvențială a unui singur fișier SQL.\nCând se folosește #mydumper este opțiunea recomandată pentru baze de date de producție peste 10 GB unde viteza de dump și restore este critică. Pe o bază de date de 60 GB cu 8 thread-uri, un dump care cu mysqldump necesită 3-4 ore se completează în 20-25 de minute.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/mydumper/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003emydumper\u003c/strong\u003e este un instrument open source de backup logic pentru MySQL și MariaDB care implementează paralelism adevărat: nu doar între tabele diferite, ci și în interiorul aceleiași tabele, împărțind-o în chunk-uri bazate pe primary key.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003emydumper se conectează la serverul MySQL, achiziționează un snapshot consistent cu \u003ccode\u003eFLUSH TABLES WITH READ LOCK\u003c/code\u003e (sau \u003ccode\u003e--trx-consistency-only\u003c/code\u003e pentru a evita lock-urile globale pe InnoDB), apoi distribuie munca între thread-uri multiple. Fiecare tabelă mare este spartă în chunk-uri — implicit bazate pe range-urile primary key-ului — și fiecare chunk este exportat de un thread separat.\u003c/p\u003e","title":"mydumper"},{"content":"mysqlbinlog este utilitarul de linie de comandă furnizat cu MySQL pentru citirea și decodificarea conținutului fișierelor binary log. Este singurul instrument capabil să convertească formatul binar al binlog-urilor în output lizibil sau în instrucțiuni SQL re-executabile.\nCum funcționează #mysqlbinlog citește fișierele binlog și produce output în format text. Suportă mai multe filtre:\nPe interval de timp: --start-datetime și --stop-datetime pentru a limita output-ul la o fereastră temporală Pe bază de date: --database pentru a filtra evenimentele unei baze de date specifice Pe poziție: --start-position și --stop-position pentru a selecta evenimente specifice Cu format ROW, flag-ul --verbose decodifică modificările la nivel de rând în format pseudo-SQL comentat, altfel output-ul este un blob binar ilizibil.\nLa ce folosește #mysqlbinlog este utilizat în două scenarii principale:\nPoint-in-time recovery: extragerea și reaplicarea evenimentelor de la backup până la momentul dorit, trimițând output-ul direct în clientul mysql Debug de replicare: analizarea evenimentelor pentru a înțelege ce a fost replicat, identificarea tranzacțiilor problematice sau reconstruirea secvenței de operațiuni care a cauzat o problemă Când se folosește #mysqlbinlog este esențial ori de câte ori trebuie să inspectezi ce s-a întâmplat în baza de date după un incident, sau când se execută un point-in-time recovery. Necesită acces la fișierele binlog pe filesystem-ul serverului sau posibilitatea de a se conecta la server cu --read-from-remote-server.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/mysqlbinlog/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003emysqlbinlog\u003c/strong\u003e este utilitarul de linie de comandă furnizat cu MySQL pentru citirea și decodificarea conținutului fișierelor binary log. Este singurul instrument capabil să convertească formatul binar al binlog-urilor în output lizibil sau în instrucțiuni SQL re-executabile.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003emysqlbinlog citește fișierele binlog și produce output în format text. Suportă mai multe filtre:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003ePe interval de timp\u003c/strong\u003e: \u003ccode\u003e--start-datetime\u003c/code\u003e și \u003ccode\u003e--stop-datetime\u003c/code\u003e pentru a limita output-ul la o fereastră temporală\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003ePe bază de date\u003c/strong\u003e: \u003ccode\u003e--database\u003c/code\u003e pentru a filtra evenimentele unei baze de date specifice\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003ePe poziție\u003c/strong\u003e: \u003ccode\u003e--start-position\u003c/code\u003e și \u003ccode\u003e--stop-position\u003c/code\u003e pentru a selecta evenimente specifice\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eCu format ROW, flag-ul \u003ccode\u003e--verbose\u003c/code\u003e decodifică modificările la nivel de rând în format pseudo-SQL comentat, altfel output-ul este un blob binar ilizibil.\u003c/p\u003e","title":"mysqlbinlog"},{"content":"mysqldump este utilitarul de backup logic inclus standard în fiecare instalare de MySQL și MariaDB. Produce un fișier SQL care conține toate instrucțiunile (CREATE TABLE, INSERT) necesare pentru a reconstrui complet schema și datele unei baze de date.\nCum funcționează #mysqldump se conectează la serverul MySQL și citește tabelele una câte una, generând instrucțiunile SQL corespunzătoare la ieșire. Operația este strict single-threaded: o tabelă după alta, un rând după altul. Fișierul produs poate fi comprimat extern (gzip, zstd) dar instrumentul în sine nu oferă compresie nativă.\nCu opțiunea --single-transaction, dump-ul se desfășoară în interiorul unei tranzacții cu isolation level REPEATABLE READ, care garantează un snapshot consistent pe tabelele InnoDB fără a achiziționa lock-uri pe scrieri.\nLa ce servește #mysqldump este instrumentul standard pentru:\nBackup logic al bazelor de date mici și medii Migrări între versiuni diferite de MySQL Exportul tabelelor individuale sau bazelor de date pentru transfer între medii Crearea de dump-uri lizibile și inspectabile manual Când devine o problemă #Pe baze de date peste 10-15 GB, dump-ul single-threaded devine un blocaj. O bază de date de 60 GB poate necesita 3-4 ore de dump și tot atât de restore. Lipsa paralelismului este limitarea structurală: nu există nicio modalitate de a accelera procesul decât trecând la instrumente precum mydumper.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/mysqldump/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003emysqldump\u003c/strong\u003e este utilitarul de backup logic inclus standard în fiecare instalare de MySQL și MariaDB. Produce un fișier SQL care conține toate instrucțiunile (CREATE TABLE, INSERT) necesare pentru a reconstrui complet schema și datele unei baze de date.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003emysqldump se conectează la serverul MySQL și citește tabelele una câte una, generând instrucțiunile SQL corespunzătoare la ieșire. Operația este strict single-threaded: o tabelă după alta, un rând după altul. Fișierul produs poate fi comprimat extern (gzip, zstd) dar instrumentul în sine nu oferă compresie nativă.\u003c/p\u003e","title":"mysqldump"},{"content":"mysqlpump este utilitarul de backup logic introdus de Oracle în MySQL 5.7 ca evoluție a mysqldump. Diferența principală este suportul pentru paralelism la nivel de tabelă și compresia nativă a output-ului (zlib, lz4, zstd).\nCum funcționează #mysqlpump poate face dump la mai multe tabele simultan folosind thread-uri paralele, configurabile cu --default-parallelism. Compresia se aplică direct în timpul dump-ului, fără a necesita pipe-uri externe către gzip. Suportă și dump-ul selectiv al utilizatorilor și conturilor MySQL.\nTotuși, paralelismul operează doar la nivel de tabelă întreagă: dacă o singură tabelă este mult mai mare decât celelalte, un thread se târăște singur în timp ce restul au terminat deja.\nProblema consistenței #Cu paralelismul activ, mysqlpump nu garantează consistența între tabele diferite — tabelele exportate de thread-uri diferite pot reflecta momente diferite în timp. Aceasta este o limitare critică pentru backup-urile de producție pe baze de date relaționale cu foreign key-uri.\nStarea actuală #Oracle a declarat mysqlpump depreciat în MySQL 8.0.34 și l-a eliminat complet în MySQL 8.4. Pentru cei care caută paralelism în backup-ul logic, mydumper este alternativa recomandată.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/mysqlpump/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003emysqlpump\u003c/strong\u003e este utilitarul de backup logic introdus de Oracle în MySQL 5.7 ca evoluție a mysqldump. Diferența principală este suportul pentru paralelism la nivel de tabelă și compresia nativă a output-ului (zlib, lz4, zstd).\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003emysqlpump poate face dump la mai multe tabele simultan folosind thread-uri paralele, configurabile cu \u003ccode\u003e--default-parallelism\u003c/code\u003e. Compresia se aplică direct în timpul dump-ului, fără a necesita pipe-uri externe către gzip. Suportă și dump-ul selectiv al utilizatorilor și conturilor MySQL.\u003c/p\u003e","title":"mysqlpump"},{"content":"Navetismul (commuting) este deplasarea zilnică între casă și locul de muncă. În marile orașe italiene precum Roma, naveta medie absoarbe 2-4 ore pe zi, cu costuri directe (combustibil, parcare, transport public) și indirecte (stres, oboseală, productivitate pierdută).\nCum funcționează #Un consultant IT care locuiește la 30 km de birou în Roma poate petrece 1h15-2h30 doar pentru dus. Pe 220 de zile lucrătoare, sunt 47-89 de ore pierdute pe lună — până la două săptămâni lucrătoare petrecute în mașină fără a produce nimic.\nDe ce contează #Navetismul nu este doar timp pierdut. Este energie mentală arsă înainte de a începe lucrul. Un consultant IT lucrează cu mintea: analizează sisteme, scrie cod, proiectează arhitecturi. Dacă acea minte ajunge deja epuizată după o oră de trafic, valoarea zilei de lucru este compromisă din start.\nCe poate merge prost #Companiile care ignoră costul navetismului plătesc un preț ascuns: pentru 50 de consultanți în Roma, costul estimat este de ~1.700.000 euro/an între ore pierdute, chirie birou și cheltuieli asociate. Smart working-ul la 80% reduce acest cost la ~174.000 euro/an din al doilea an.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/pendolarismo/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eNavetismul\u003c/strong\u003e (commuting) este deplasarea zilnică între casă și locul de muncă. În marile orașe italiene precum Roma, naveta medie absoarbe 2-4 ore pe zi, cu costuri directe (combustibil, parcare, transport public) și indirecte (stres, oboseală, productivitate pierdută).\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eUn consultant IT care locuiește la 30 km de birou în Roma poate petrece 1h15-2h30 doar pentru dus. Pe 220 de zile lucrătoare, sunt 47-89 de ore pierdute pe lună — până la două săptămâni lucrătoare petrecute în mașină fără a produce nimic.\u003c/p\u003e","title":"Navetism"},{"content":"Nested loop este cea mai simpla strategie de join: pentru fiecare rand din tabelul extern, baza de date cauta randurile corespunzatoare in tabelul intern. Functioneaza ca un dublu ciclu for imbricat — de aici numele.\nCum functioneaza #Optimizatorul alege un tabel ca \u0026ldquo;extern\u0026rdquo; (outer) si unul ca \u0026ldquo;intern\u0026rdquo; (inner). Pentru fiecare rand din tabelul extern, executa o cautare in tabelul intern pe coloana de join. Daca tabelul intern are un index pe coloana de join, fiecare cautare este un acces direct via B-tree. Fara index, fiecare cautare devine un sequential scan complet.\nCand este alegerea corecta #Nested loop este imbatabil cand tabelul extern are putine randuri si tabelul intern are un index pe coloana de join. Un join pe 100 de randuri externe cu un index B-tree pe tabelul intern este practic instantaneu: putine iteratii, acces direct, memorie minima.\nEste de asemenea strategia preferata pentru lookup-urile de dimensiuni in data warehouse-uri, unde un fact table filtrat (putine randuri) se uneste cu un dimension table indexat.\nCe poate merge prost #Devine un dezastru cand optimizatorul il alege pe seturi mari de date din greseala — de obicei pentru ca statisticile subestimeaza numarul de randuri. Un nested loop pe 2 milioane de randuri externe inseamna 2 milioane de cautari in tabelul intern. Fara index, fiecare cautare este un scan complet.\nIn aceste cazuri un hash join sau un merge join ar fi cu ordine de marime mai rapide. Cauza principala este aproape intotdeauna o estimare de cardinalitate gresita: statistici invechite sau un default_statistics_target prea mic.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/nested-loop/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eNested loop\u003c/strong\u003e este cea mai simpla strategie de join: pentru fiecare rand din tabelul extern, baza de date cauta randurile corespunzatoare in tabelul intern. Functioneaza ca un dublu ciclu \u003ccode\u003efor\u003c/code\u003e imbricat — de aici numele.\u003c/p\u003e\n\u003ch2 id=\"cum-functioneaza\" class=\"relative group\"\u003eCum functioneaza \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-functioneaza\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eOptimizatorul alege un tabel ca \u0026ldquo;extern\u0026rdquo; (outer) si unul ca \u0026ldquo;intern\u0026rdquo; (inner). Pentru fiecare rand din tabelul extern, executa o cautare in tabelul intern pe coloana de join. Daca tabelul intern are un index pe coloana de join, fiecare cautare este un acces direct via B-tree. Fara index, fiecare cautare devine un sequential scan complet.\u003c/p\u003e","title":"Nested Loop"},{"content":"NOLOGGING este un mod Oracle care dezactivează generarea de redo log în timpul operațiunilor de încărcare masivă. Operațiunile se completează mult mai rapid, dar datele nu sunt recuperabile prin redo în caz de crash înainte de un backup.\nCum funcționează #Când un segment (tabelă, index, partiție) este în mod NOLOGGING, operațiunile masive precum CTAS, INSERT /*+ APPEND */ și ALTER TABLE MOVE nu scriu redo log pentru blocurile de date. Pe o copie de 380 GB, acest lucru elimină generarea aceleiași cantități de redo, prevenind saturarea zonei de archivelog și reducând timpii de la zile la ore.\nLa ce folosește #NOLOGGING este esențial pentru operațiunile de migrare pe tabele de dimensiuni mari. Fără NOLOGGING, un CTAS de 380 GB ar genera 380 GB de redo log, punând sistemul în mod archivelog timp de zile. Cu NOLOGGING, aceeași operație se completează în câteva ore cu impact minim asupra sistemului.\nCând se folosește #Se activează înainte de operațiunea masivă și se dezactivează imediat după (ALTER TABLE ... LOGGING). Este obligatoriu să se execute un backup RMAN imediat după, deoarece segmentele NOLOGGING nu sunt recuperabile cu un restore din redo. Niciodată nu se lasă NOLOGGING activ permanent pe tabele de producție.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/nologging/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eNOLOGGING\u003c/strong\u003e este un mod Oracle care dezactivează generarea de redo log în timpul operațiunilor de încărcare masivă. Operațiunile se completează mult mai rapid, dar datele nu sunt recuperabile prin redo în caz de crash înainte de un backup.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eCând un segment (tabelă, index, partiție) este în mod NOLOGGING, operațiunile masive precum CTAS, \u003ccode\u003eINSERT /*+ APPEND */\u003c/code\u003e și \u003ccode\u003eALTER TABLE MOVE\u003c/code\u003e nu scriu redo log pentru blocurile de date. Pe o copie de 380 GB, acest lucru elimină generarea aceleiași cantități de redo, prevenind saturarea zonei de archivelog și reducând timpii de la zile la ore.\u003c/p\u003e","title":"NOLOGGING"},{"content":"Un Object Privilege în Oracle este o autorizare care permite executarea operațiunilor pe un obiect specific al bazei de date: o tabelă, o vizualizare, o secvență sau o procedură PL/SQL. Exemple tipice includ SELECT ON schema.tabela, INSERT ON schema.tabela și EXECUTE ON schema.procedura.\nCum funcționează #Privilegiile de obiect se acordă cu GRANT specificând operațiunea și obiectul țintă: GRANT SELECT ON app_owner.clienti TO srv_report. Pot fi atribuite utilizatorilor individuali sau rolurilor. Spre deosebire de privilegiile de sistem, operează pe un singur obiect și nu conferă puteri globale asupra bazei de date.\nLa ce servește #Privilegiile de obiect sunt instrumentul principal pentru implementarea principiului privilegiului minim în Oracle. Permit construirea modelelor de acces granulare: un utilizator de raportare primește doar SELECT, un utilizator aplicativ primește SELECT + INSERT + UPDATE pe tabelele operaționale, și așa mai departe. Combinate cu roluri personalizate, creează arhitecturi de securitate curate și ușor de întreținut.\nDe ce contează #Diferența între un GRANT SELECT ON app_owner.clienti și un GRANT DBA este diferența între a da cheia unei camere și a da cheile întregii clădiri. În medii cu sute de tabele, privilegiile de obiect se gestionează de obicei prin blocuri PL/SQL care generează automat grant-urile pentru toate tabelele dintr-o schemă.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/object-privilege/","section":"Glosar","summary":"\u003cp\u003eUn \u003cstrong\u003eObject Privilege\u003c/strong\u003e în Oracle este o autorizare care permite executarea operațiunilor pe un obiect specific al bazei de date: o tabelă, o vizualizare, o secvență sau o procedură PL/SQL. Exemple tipice includ \u003ccode\u003eSELECT ON schema.tabela\u003c/code\u003e, \u003ccode\u003eINSERT ON schema.tabela\u003c/code\u003e și \u003ccode\u003eEXECUTE ON schema.procedura\u003c/code\u003e.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003ePrivilegiile de obiect se acordă cu \u003ccode\u003eGRANT\u003c/code\u003e specificând operațiunea și obiectul țintă: \u003ccode\u003eGRANT SELECT ON app_owner.clienti TO srv_report\u003c/code\u003e. Pot fi atribuite utilizatorilor individuali sau rolurilor. Spre deosebire de privilegiile de sistem, operează pe un singur obiect și nu conferă puteri globale asupra bazei de date.\u003c/p\u003e","title":"Object Privilege"},{"content":"OCI (Oracle Cloud Infrastructure) este platforma cloud a Oracle, lansata in a doua generatie in 2018. Spre deosebire de alti furnizori cloud, OCI este proiectata nativ pentru workload-uri Oracle Database si ofera avantaje semnificative in ceea ce priveste licentierea si performanta.\nDe ce OCI pentru Oracle Database #Avantajul principal tine de licentiere. Pe OCI, Oracle recunoaste propriile OCPU (Oracle CPU) cu un raport 1:1 pentru calculul licentelor. Pe alti furnizori cloud precum AWS sau Azure, raportul vCPU-licente este mai putin favorabil si riscul de audit este real.\nProgramul BYOL (Bring Your Own License) permite reutilizarea licentelor on-premises existente pe OCI fara costuri suplimentare — un factor decisiv pentru organizatiile care au investit deja in licente Enterprise Edition.\nServicii principale pentru DBA # Bare Metal DB Systems: servere fizice dedicate cu Oracle Database preinstalat VM DB Systems: instante virtuale cu configuratie flexibila (Flex shapes) Exadata Cloud Service: Exadata complet gestionat in cloud Autonomous Database: baza de date complet gestionata cu tuning automat Networking si conectivitate #OCI ofera FastConnect pentru conexiuni dedicate de banda larga intre centrele de date on-premises si regiunile cloud, plus VPN site-to-site pentru scenarii cu cerinte de banda mai mici. Latenta si bandwidth-ul conexiunii sunt factori critici in migrarile cu Data Guard cross-site.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/oci/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eOCI\u003c/strong\u003e (Oracle Cloud Infrastructure) este platforma cloud a Oracle, lansata in a doua generatie in 2018. Spre deosebire de alti furnizori cloud, OCI este proiectata nativ pentru workload-uri Oracle Database si ofera avantaje semnificative in ceea ce priveste licentierea si performanta.\u003c/p\u003e\n\u003ch2 id=\"de-ce-oci-pentru-oracle-database\" class=\"relative group\"\u003eDe ce OCI pentru Oracle Database \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#de-ce-oci-pentru-oracle-database\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eAvantajul principal tine de licentiere. Pe OCI, Oracle recunoaste propriile OCPU (Oracle CPU) cu un raport 1:1 pentru calculul licentelor. Pe alti furnizori cloud precum AWS sau Azure, raportul vCPU-licente este mai putin favorabil si riscul de audit este real.\u003c/p\u003e","title":"OCI"},{"content":"OLAP (Online Analytical Processing) indică o abordare a procesării datelor orientată spre analiza multidimensională: agregări, drill-down, comparații temporale, slice-and-dice pe volume mari de date istorice.\nOLAP vs OLTP # Caracteristică OLAP OLTP Scop Analiză și raportare Tranzacții operative Model de date Star schema, denormalizat 3NF, normalizat Interogare tipică Agregări pe milioane de linii Citire/scriere a câtorva linii Utilizatori Analiști, management Aplicații, operatori Actualizare Batch (ETL periodic) Timp real Operațiuni OLAP #Operațiunile fundamentale ale analizei OLAP sunt:\nDrill-down: de la nivelul agregat la detaliu Drill-up (roll-up): de la detaliu la nivelul agregat Slice: selectarea unei \u0026ldquo;felii\u0026rdquo; de date fixând o dimensiune (ex. doar anul 2025) Dice: selectarea unui sub-cub specificând mai multe dimensiuni Pivot: rotirea dimensiunilor de analiză (linii ↔ coloane) Implementări # ROLAP (Relational OLAP): datele rămân în tabele relaționale, agregările sunt calculate cu interogări SQL. Este abordarea folosită în data warehouse-uri cu star schema MOLAP (Multidimensional OLAP): datele sunt pre-agregate în structuri multidimensionale (cuburi). Mai rapid pentru interogări dar necesită mai mult spațiu și timp de construire HOLAP (Hybrid): combinație a ambelor abordări ","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/olap/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eOLAP\u003c/strong\u003e (Online Analytical Processing) indică o abordare a procesării datelor orientată spre analiza multidimensională: agregări, drill-down, comparații temporale, slice-and-dice pe volume mari de date istorice.\u003c/p\u003e\n\u003ch2 id=\"olap-vs-oltp\" class=\"relative group\"\u003eOLAP vs OLTP \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#olap-vs-oltp\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003ctable\u003e\n  \u003cthead\u003e\n      \u003ctr\u003e\n          \u003cth\u003eCaracteristică\u003c/th\u003e\n          \u003cth\u003eOLAP\u003c/th\u003e\n          \u003cth\u003eOLTP\u003c/th\u003e\n      \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eScop\u003c/td\u003e\n          \u003ctd\u003eAnaliză și raportare\u003c/td\u003e\n          \u003ctd\u003eTranzacții operative\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eModel de date\u003c/td\u003e\n          \u003ctd\u003eStar schema, denormalizat\u003c/td\u003e\n          \u003ctd\u003e3NF, normalizat\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eInterogare tipică\u003c/td\u003e\n          \u003ctd\u003eAgregări pe milioane de linii\u003c/td\u003e\n          \u003ctd\u003eCitire/scriere a câtorva linii\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eUtilizatori\u003c/td\u003e\n          \u003ctd\u003eAnaliști, management\u003c/td\u003e\n          \u003ctd\u003eAplicații, operatori\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eActualizare\u003c/td\u003e\n          \u003ctd\u003eBatch (ETL periodic)\u003c/td\u003e\n          \u003ctd\u003eTimp real\u003c/td\u003e\n      \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\u003ch2 id=\"operațiuni-olap\" class=\"relative group\"\u003eOperațiuni OLAP \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#opera%c8%9biuni-olap\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eOperațiunile fundamentale ale analizei OLAP sunt:\u003c/p\u003e","title":"OLAP"},{"content":"Outsourcing-ul este practica de a încredința dezvoltarea, mentenanța sau gestionarea sistemelor IT unor furnizori externi companiei. Poate implica proiecte complete (dezvoltarea de software custom) sau servicii continue (gestionarea infrastructurii, suport aplicativ).\nCum funcționează #Compania client definește cerințele și semnează un contract cu un furnizor extern care se angajează să realizeze proiectul. Cele mai comune modele contractuale sunt: la pachet (preț fix pentru rezultat definit), pe timp și materiale (zile-om facturate), sau hibride. Furnizorul pune la dispoziție o echipă de consultanți care lucrează pe proiect, adesea cu rotație periodică a personalului.\nLa ce folosește #Înțelegerea riscurilor outsourcing-ului este fundamentală pentru a decide ce să externalizezi și ce să păstrezi intern. Riscurile principale sunt: vendor lock-in, pierderea know-how-ului, scope creep, rotația consultanților și dezalinierea stimulentelor (furnizorul câștigă pe timp, nu pe rezultat).\nCând se folosește #Outsourcing-ul poate funcționa pentru activități commoditizate sau bine definite. Devine riscant pentru proiecte strategice, custom și pe termen lung unde know-how-ul specific domeniului este critic. Alternativa adesea mai eficientă este o echipă internă mică și competentă, eventual susținută de consultanți pentru competențe specializate punctuale.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/outsourcing/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eOutsourcing-ul\u003c/strong\u003e este practica de a încredința dezvoltarea, mentenanța sau gestionarea sistemelor IT unor furnizori externi companiei. Poate implica proiecte complete (dezvoltarea de software custom) sau servicii continue (gestionarea infrastructurii, suport aplicativ).\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eCompania client definește cerințele și semnează un contract cu un furnizor extern care se angajează să realizeze proiectul. Cele mai comune modele contractuale sunt: la pachet (preț fix pentru rezultat definit), pe timp și materiale (zile-om facturate), sau hibride. Furnizorul pune la dispoziție o echipă de consultanți care lucrează pe proiect, adesea cu rotație periodică a personalului.\u003c/p\u003e","title":"Outsourcing"},{"content":"Parking Lot este o listă vizibilă — pe o tablă, un document partajat sau chat — unde facilitatorul notează subiectele care apar în timpul unei ședințe dar care nu pot fi discutate în timpul disponibil. Subiectele sunt \u0026ldquo;parcate\u0026rdquo; și abordate după ședință doar cu persoanele implicate.\nCum funcționează #Când în timpul unui standup cineva ridică o problemă complexă, facilitatorul spune: \u0026ldquo;O notez în parking lot, discutăm după.\u0026rdquo; Subiectul nu este ignorat — este doar mutat în contextul potrivit, unde poate fi abordat fără a pierde timpul celor neimplicați.\nLa ce servește #Este cel mai subestimat instrument în gestionarea standup-urilor și ședințelor în general. Permite să spui \u0026ldquo;discutăm mai târziu\u0026rdquo; fără ca subiectul să fie uitat. Rezolvă problema \u0026ldquo;thread killerilor\u0026rdquo; — acele discuții între două persoane care blochează întreaga ședință.\nDe ce contează #Fără parking lot, facilitatorul are două opțiuni proaste: lasă discuția să se extindă (și standup-ul depășește timpul), sau taie subiectul (și cineva se simte ignorat). Parking lot-ul oferă o a treia cale: recunoaște importanța subiectului și garantează că va fi abordat, dar la momentul potrivit.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/parking-lot/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eParking Lot\u003c/strong\u003e este o listă vizibilă — pe o tablă, un document partajat sau chat — unde facilitatorul notează subiectele care apar în timpul unei ședințe dar care nu pot fi discutate în timpul disponibil. Subiectele sunt \u0026ldquo;parcate\u0026rdquo; și abordate după ședință doar cu persoanele implicate.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eCând în timpul unui standup cineva ridică o problemă complexă, facilitatorul spune: \u0026ldquo;O notez în parking lot, discutăm după.\u0026rdquo; Subiectul nu este ignorat — este doar mutat în contextul potrivit, unde poate fi abordat fără a pierde timpul celor neimplicați.\u003c/p\u003e","title":"Parking Lot"},{"content":"Partita IVA este codul de identificare fiscală atribuit lucrătorilor independenți și întreprinderilor din Italia pentru operațiunile supuse TVA. În consultanța IT, \u0026ldquo;a lucra cu partita IVA\u0026rdquo; înseamnă a opera ca freelancer, facturând serviciile direct clientului.\nCum funcționează #Consultantul freelancer emite factură clientului la sfârșitul perioadei de lucru. Plata se face conform termenilor contractuali — care în Italia sunt de obicei 60-90-120 de zile sfârșit de lună. Între timp, consultantul suportă toate cheltuielile (contribuții sociale, impozite, chirie, utilități) din fonduri proprii.\nLa ce servește #Este regimul standard pentru consultanța IT din Italia. Oferă flexibilitate și autonomie, dar expune profesionistul la riscul de credit: dacă clientul nu plătește sau plătește cu întârziere, consultantul nu are protecții comparabile cu cele ale unui angajat. Nu există somaj, nu există compensație la concediere, nu există al 13-lea salariu.\nCe poate merge prost #Cu termene de plată de 90 de zile și un singur client, consultantul freelancer este veriga cea mai slabă din lanț. Nu are putere de negociere, nu are departament juridic, iar refuzul condițiilor înseamnă a rămâne fără proiecte. Diversificarea clienților este strategia defensivă principală.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/partita-iva/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003ePartita IVA\u003c/strong\u003e este codul de identificare fiscală atribuit lucrătorilor independenți și întreprinderilor din Italia pentru operațiunile supuse TVA. În consultanța IT, \u0026ldquo;a lucra cu partita IVA\u0026rdquo; înseamnă a opera ca freelancer, facturând serviciile direct clientului.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eConsultantul freelancer emite factură clientului la sfârșitul perioadei de lucru. Plata se face conform termenilor contractuali — care în Italia sunt de obicei 60-90-120 de zile sfârșit de lună. Între timp, consultantul suportă toate cheltuielile (contribuții sociale, impozite, chirie, utilități) din fonduri proprii.\u003c/p\u003e","title":"Partita IVA"},{"content":"Partition Pruning este mecanismul prin care Oracle, în timpul execuției unei interogări pe o tabelă partițională, identifică și exclude automat partițiile care nu pot conține date relevante pentru predicatul interogării.\nCum funcționează #Când o interogare include un predicat pe coloana de partiție (ex. WHERE data_movimento BETWEEN ...), Oracle consultă metadatele partițiilor și determină care partiții conțin date în intervalul solicitat. Doar acele partiții sunt citite. În planul de execuție apare ca PARTITION RANGE SINGLE sau PARTITION RANGE ITERATOR.\nLa ce folosește #Pe o tabelă de 380 GB cu partiții lunare, o interogare pe o singură lună citește doar ~4 GB în loc de întreaga tabelă. Pruning-ul transformă un full table scan de coșmar într-un full partition scan gestionabil, reducând I/O-ul cu 99%.\nCând se folosește #Pruning-ul este automat, dar funcționează doar cu predicate directe pe coloana de partiție. Aplicarea funcțiilor pe coloană (TRUNC(data), TO_CHAR(data)) dezactivează pruning-ul și forțează Oracle să citească toate partițiile. Verifică întotdeauna cu EXPLAIN PLAN că pruning-ul este activ.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/partition-pruning/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003ePartition Pruning\u003c/strong\u003e este mecanismul prin care Oracle, în timpul execuției unei interogări pe o tabelă partițională, identifică și exclude automat partițiile care nu pot conține date relevante pentru predicatul interogării.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eCând o interogare include un predicat pe coloana de partiție (ex. \u003ccode\u003eWHERE data_movimento BETWEEN ...\u003c/code\u003e), Oracle consultă metadatele partițiilor și determină care partiții conțin date în intervalul solicitat. Doar acele partiții sunt citite. În planul de execuție apare ca \u003ccode\u003ePARTITION RANGE SINGLE\u003c/code\u003e sau \u003ccode\u003ePARTITION RANGE ITERATOR\u003c/code\u003e.\u003c/p\u003e","title":"Partition Pruning"},{"content":"Pedalarea Asistată este un sistem de propulsie electrică montat pe o bicicletă care amplifică forța de pedalare a ciclistului printr-un motor electric. Motorul se activează doar când se pedalează și se dezactivează peste 25 km/h (limita europeană).\nCum funcționează #Un senzor detectează forța și cadența pedalării și activează motorul electric proporțional. Cu cât pedalezi mai tare, cu atât motorul ajută mai mult. Rezultatul este că urcări precum dealul Celio din Roma devin o pantă ușoară, iar la destinație ajungi fără să transpiri — un detaliu crucial pentru cine trebuie să se prezinte la birou.\nLa ce servește #Elimină cele două obiecții principale la adresa bicicletei ca mijloc de transport urban: pantele și transpirația. Cu pedalare asistată, un traseu urban de 8 km se parcurge în 18 minute indiferent de denivelări, ajungând proaspăt și gata de lucru. Autonomia tipică este de 40-80 km, mai mult decât suficient pentru o săptămână de navetă.\nDe ce contează #Cu un e-bike, argumentul \u0026ldquo;Roma are șapte coline\u0026rdquo; cade. Cele șapte coline nu mai există cu un motor care asistă la urcare. Aceasta face bicicleta competitivă cu mașina chiar și în orașe cu dealuri, eliminând ultima scuză pentru a rămâne în trafic.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/pedalata-assistita/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003ePedalarea Asistată\u003c/strong\u003e este un sistem de propulsie electrică montat pe o bicicletă care amplifică forța de pedalare a ciclistului printr-un motor electric. Motorul se activează doar când se pedalează și se dezactivează peste 25 km/h (limita europeană).\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eUn senzor detectează forța și cadența pedalării și activează motorul electric proporțional. Cu cât pedalezi mai tare, cu atât motorul ajută mai mult. Rezultatul este că urcări precum dealul Celio din Roma devin o pantă ușoară, iar la destinație ajungi fără să transpiri — un detaliu crucial pentru cine trebuie să se prezinte la birou.\u003c/p\u003e","title":"Pedalare Asistată"},{"content":"pg_stat_statements este o extensie PostgreSQL — inclusă în distribuția oficială dar neactivă implicit — care ține evidența statisticilor de execuție pentru toate query-urile SQL care trec prin server. Query-urile sunt normalizate (valorile literale înlocuite cu parametri) pentru a grupa execuțiile aceluiași pattern.\nCum funcționează #Extensia necesită încărcarea ca shared library la pornirea serverului prin parametrul shared_preload_libraries. Odată activă, înregistrează pentru fiecare query: numărul de execuții, timpul total și mediu, rândurile returnate, blocurile citite de pe disc și din cache. Parametrul pg_stat_statements.max controlează câte query-uri distincte sunt urmărite (implicit 5000).\nLa ce servește #Este instrumentul principal pentru identificarea query-urilor celor mai costisitoare pe un server PostgreSQL. Sortând după total_exec_time se obține imediat clasamentul query-urilor care consumă cele mai multe resurse. Combinat cu EXPLAIN ANALYZE, permite un workflow diagnostic complet: pg_stat_statements identifică problema, EXPLAIN explică cauza.\nCând se folosește #Ar trebui să fie activ pe orice instalare PostgreSQL de producție. Overhead-ul este neglijabil (1-2% CPU). Fără pg_stat_statements, orice activitate de performance tuning se bazează pe presupuneri în loc de date.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/pg-stat-statements/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003epg_stat_statements\u003c/strong\u003e este o extensie PostgreSQL — inclusă în distribuția oficială dar neactivă implicit — care ține evidența statisticilor de execuție pentru toate query-urile SQL care trec prin server. Query-urile sunt normalizate (valorile literale înlocuite cu parametri) pentru a grupa execuțiile aceluiași pattern.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eExtensia necesită încărcarea ca shared library la pornirea serverului prin parametrul \u003ccode\u003eshared_preload_libraries\u003c/code\u003e. Odată activă, înregistrează pentru fiecare query: numărul de execuții, timpul total și mediu, rândurile returnate, blocurile citite de pe disc și din cache. Parametrul \u003ccode\u003epg_stat_statements.max\u003c/code\u003e controlează câte query-uri distincte sunt urmărite (implicit 5000).\u003c/p\u003e","title":"pg_stat_statements"},{"content":"pg_trgm este o extensie PostgreSQL care implementează căutarea bazată pe trigrame — secvențe de trei caractere consecutive extrase din text. Activează utilizarea indexurilor GIN și GiST pentru a accelera căutări LIKE '%valoare%' și ILIKE, care altfel ar necesita scanări secvențiale.\nCum funcționează #Extensia descompune fiecare șir în trigrame: de exemplu, \u0026ldquo;hello\u0026rdquo; devine {\u0026quot; h\u0026quot;, \u0026quot; he\u0026quot;, \u0026ldquo;hel\u0026rdquo;, \u0026ldquo;ell\u0026rdquo;, \u0026ldquo;llo\u0026rdquo;, \u0026ldquo;lo \u0026ldquo;}. Un index GIN cu operator class gin_trgm_ops indexează aceste trigrame. Când se execută un LIKE '%ell%', PostgreSQL caută trigramele corespunzătoare în index în loc să scaneze întreaga tabelă.\nLa ce folosește #pg_trgm rezolvă una dintre cele mai comune probleme din PostgreSQL: căutarea \u0026ldquo;conține\u0026rdquo; pe coloane de text mari. Fără pg_trgm, un LIKE '%valoare%' pe o tabelă cu milioane de rânduri necesită o scanare completă. Cu pg_trgm și un index GIN, aceeași căutare folosește indexul și răspunde în milisecunde.\nCând se folosește #Se activează cu CREATE EXTENSION IF NOT EXISTS pg_trgm și se creează indexul cu USING gin (coloana gin_trgm_ops). Este ideal pe tabele cu churn scăzut (puține UPDATE/DELETE). Crearea indexului trebuie făcută cu CONCURRENTLY în producție pentru a evita lock-urile.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/pg-trgm/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003epg_trgm\u003c/strong\u003e este o extensie PostgreSQL care implementează căutarea bazată pe trigrame — secvențe de trei caractere consecutive extrase din text. Activează utilizarea indexurilor GIN și GiST pentru a accelera căutări \u003ccode\u003eLIKE '%valoare%'\u003c/code\u003e și \u003ccode\u003eILIKE\u003c/code\u003e, care altfel ar necesita scanări secvențiale.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eExtensia descompune fiecare șir în trigrame: de exemplu, \u0026ldquo;hello\u0026rdquo; devine {\u0026quot;  h\u0026quot;, \u0026quot; he\u0026quot;, \u0026ldquo;hel\u0026rdquo;, \u0026ldquo;ell\u0026rdquo;, \u0026ldquo;llo\u0026rdquo;, \u0026ldquo;lo \u0026ldquo;}. Un index GIN cu operator class \u003ccode\u003egin_trgm_ops\u003c/code\u003e indexează aceste trigrame. Când se execută un \u003ccode\u003eLIKE '%ell%'\u003c/code\u003e, PostgreSQL caută trigramele corespunzătoare în index în loc să scaneze întreaga tabelă.\u003c/p\u003e","title":"pg_trgm"},{"content":"PITR (Point-in-Time Recovery) este o tehnică de restaurare care permite readucerea unei baze de date la orice moment în timp, nu doar la momentul backup-ului. Se bazează pe combinarea unui backup complet cu log-urile de tranzacții (binary log în MySQL, WAL în PostgreSQL, redo log în Oracle).\nCum funcționează #Procesul se desfășoară în două faze:\nRestaurarea backup-ului: baza de date este restaurată la ultimul backup disponibil Replay-ul log-urilor: log-urile de tranzacții sunt reaplicate de la momentul backup-ului până la momentul dorit, excluzând evenimentul care a cauzat problema În MySQL, tool-ul mysqlbinlog extrage evenimentele din binary log-uri și le reproduce pe baza de date restaurată.\nLa ce folosește #PITR este esențial când apare o eroare umană (DROP TABLE, DELETE fără WHERE, UPDATE masiv greșit) și baza de date trebuie restaurată la starea imediat anterioară erorii, fără a pierde orele de lucru dintre ultimul backup și incident.\nCând se folosește #PITR necesită ca binary log-ul să fie activ și ca fișierele binlog să nu fi fost șterse. Retenția binlog-urilor trebuie să acopere cel puțin dublul intervalului dintre două backup-uri consecutive pentru a garanta o acoperire PITR completă.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/pitr/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003ePITR\u003c/strong\u003e (Point-in-Time Recovery) este o tehnică de restaurare care permite readucerea unei baze de date la orice moment în timp, nu doar la momentul backup-ului. Se bazează pe combinarea unui backup complet cu log-urile de tranzacții (binary log în MySQL, WAL în PostgreSQL, redo log în Oracle).\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eProcesul se desfășoară în două faze:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eRestaurarea backup-ului\u003c/strong\u003e: baza de date este restaurată la ultimul backup disponibil\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eReplay-ul log-urilor\u003c/strong\u003e: log-urile de tranzacții sunt reaplicate de la momentul backup-ului până la momentul dorit, excluzând evenimentul care a cauzat problema\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003eÎn MySQL, tool-ul \u003ccode\u003emysqlbinlog\u003c/code\u003e extrage evenimentele din binary log-uri și le reproduce pe baza de date restaurată.\u003c/p\u003e","title":"PITR"},{"content":"Presenteismul este cultura organizațională care măsoară valoarea muncii pe baza prezenței fizice a angajatului la birou, indiferent de calitatea și cantitatea rezultatelor produse. Este presupunerea că \u0026ldquo;dacă te văd la birou, lucrezi.\u0026rdquo;\nCum funcționează #Într-o organizație presenteistă, a fi la birou de la 9 la 18 este mai important decât închiderea task-urilor. A veni târziu este o problemă chiar dacă ai produs mai mult decât toți. A lucra de acasă este suspect chiar dacă rezultatele sunt excelente. Controlul se bazează pe vedere, nu pe metrici.\nDe ce contează #Presenteismul este principalul obstacol în adoptarea smart working-ului în consultanța IT. Un consultant IT nu lucrează pe bandă de montaj — are nevoie de concentrare, liniște și instrumente digitale, nu de un birou într-un open space zgomotos. Confuzia între prezență și productivitate este o moștenire culturală, nu o necesitate operațională.\nCe poate merge prost #Companiile care nu depășesc presenteismul plătesc un cost invizibil: ore de navetă neproductive, angajați care ajung stresați și epuizați, talente care pleacă către companii mai flexibile. Presenteismul nu protejează productivitatea — o distruge.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/presenteismo/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003ePresenteismul\u003c/strong\u003e este cultura organizațională care măsoară valoarea muncii pe baza prezenței fizice a angajatului la birou, indiferent de calitatea și cantitatea rezultatelor produse. Este presupunerea că \u0026ldquo;dacă te văd la birou, lucrezi.\u0026rdquo;\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eÎntr-o organizație presenteistă, a fi la birou de la 9 la 18 este mai important decât închiderea task-urilor. A veni târziu este o problemă chiar dacă ai produs mai mult decât toți. A lucra de acasă este suspect chiar dacă rezultatele sunt excelente. Controlul se bazează pe vedere, nu pe metrici.\u003c/p\u003e","title":"Presenteism"},{"content":"Un Pull Request (PR) este o cerere formală de incorporare a modificărilor dintr-un branch de dezvoltare în branch-ul principal al repository-ului. Este mecanismul central de colaborare pe GitHub și platforme similare.\nCum funcționează #Dezvoltatorul lucrează pe un branch dedicat (ex. fix/issue-234-eroare-calcul), completează modificările și deschide un PR. PR-ul arată diff-ul codului, permite colegilor să comenteze rând cu rând, să ceară modificări sau să aprobe. Doar după aprobare codul se unește (merge) în branch-ul principal. Aceasta garantează că codul \u0026ldquo;bun\u0026rdquo; rămâne bun.\nLa ce folosește #PR-ul transformă dezvoltarea dintr-o activitate individuală într-un proces de echipă. Previne suprascrierile accidentale, surprinde bug-uri înainte să ajungă în producție și creează un istoric complet al cine a făcut ce, când și de ce. În proiectele haotice, este diferența dintre control și dezordine.\nCând se folosește #La fiecare modificare de cod, fără excepții. Chiar și corecțiile mici trec printr-un PR, pentru că valoarea nu e doar în review ci în trasabilitate. Pe platformele GitLab aceeași funcționalitate se numește Merge Request.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/pull-request/","section":"Glosar","summary":"\u003cp\u003eUn \u003cstrong\u003ePull Request\u003c/strong\u003e (PR) este o cerere formală de incorporare a modificărilor dintr-un branch de dezvoltare în branch-ul principal al repository-ului. Este mecanismul central de colaborare pe GitHub și platforme similare.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eDezvoltatorul lucrează pe un branch dedicat (ex. \u003ccode\u003efix/issue-234-eroare-calcul\u003c/code\u003e), completează modificările și deschide un PR. PR-ul arată diff-ul codului, permite colegilor să comenteze rând cu rând, să ceară modificări sau să aprobe. Doar după aprobare codul se unește (merge) în branch-ul principal. Aceasta garantează că codul \u0026ldquo;bun\u0026rdquo; rămâne bun.\u003c/p\u003e","title":"Pull Request"},{"content":"Quorum-ul este numărul minim de noduri care trebuie să fie de acord pentru ca clusterul să fie considerat operațional. Într-un cluster cu 3 noduri, quorum-ul este 2 (majoritatea). Dacă un nod se deconectează, celelalte două recunosc că sunt majoritatea și continuă să funcționeze normal.\nCum funcționează #Galera Cluster folosește un protocol de comunicare de grup care verifică continuu câte noduri sunt accesibile. Calculul este simplu: quorum = (număr total noduri / 2) + 1. Cu 3 noduri quorum-ul este 2, cu 5 noduri este 3. Nodurile care pierd quorum-ul trec în starea Non-Primary și refuză scrierile pentru a evita inconsistențele.\nLa ce folosește #Quorum-ul previne split-brain-ul: situația în care două părți ale clusterului operează independent, acceptând scrieri diferite pe aceleași date. Fără quorum, o întrerupere de rețea ar putea duce la date divergente imposibil de reconciliat automat.\nCând se folosește #Quorum-ul este activ automat în orice cluster Galera. Din acest motiv, trei noduri este minimul în producție: cu două noduri, pierderea unuia lasă supraviețuitorul fără quorum și prin urmare blocat.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/quorum/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eQuorum-ul\u003c/strong\u003e este numărul minim de noduri care trebuie să fie de acord pentru ca clusterul să fie considerat operațional. Într-un cluster cu 3 noduri, quorum-ul este 2 (majoritatea). Dacă un nod se deconectează, celelalte două recunosc că sunt majoritatea și continuă să funcționeze normal.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eGalera Cluster folosește un protocol de comunicare de grup care verifică continuu câte noduri sunt accesibile. Calculul este simplu: quorum = (număr total noduri / 2) + 1. Cu 3 noduri quorum-ul este 2, cu 5 noduri este 3. Nodurile care pierd quorum-ul trec în starea Non-Primary și refuză scrierile pentru a evita inconsistențele.\u003c/p\u003e","title":"Quorum"},{"content":"RAC (Real Application Clusters) este tehnologia Oracle care permite mai multor instante ale bazei de date sa acceseze simultan acelasi storage partajat. Daca un nod se defecteaza, celelalte continua sa serveasca cererile fara intrerupere — failover-ul este transparent pentru aplicatii.\nCum functioneaza #Un cluster RAC este compus din doua sau mai multe servere (noduri) conectate printr-o retea privata de mare viteza (interconnect) si storage partajat (de obicei ASM — Automatic Storage Management). Fiecare nod ruleaza propria instanta Oracle, dar toate acceseaza aceleasi datafile-uri.\nProtocolul Cache Fusion gestioneaza coerenta datelor intre noduri: cand un bloc modificat de un nod este necesar altuia, este transferat direct prin interconnect fara a trece prin disc.\nDisponibilitate ridicata #Daca un nod cade, sesiunile active sunt transferate automat la nodurile ramase prin TAF (Transparent Application Failover) sau Application Continuity. Timpul de failover depinde de configuratie dar este de obicei de ordinul secundelor.\nImplicatii de licentiere #RAC este o optiune a Enterprise Edition cu costuri semnificative de licentiere. In migrarea cloud, calculul licentelor RAC este unul dintre aspectele cele mai delicate: pe OCI cu BYOL licentele on-premises se reutilizeaza, pe alti furnizori cloud costul se poate multiplica.\nCand este cu adevarat necesar #RAC este justificat cand sunt necesare disponibilitate ridicata cu failover automat si scalabilitate orizontala. Pentru medii cu putini utilizatori sau cerinte standard de uptime, un singur nod cu Data Guard este adesea o solutie mai simpla si mai putin costisitoare.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/rac/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eRAC\u003c/strong\u003e (Real Application Clusters) este tehnologia Oracle care permite mai multor instante ale bazei de date sa acceseze simultan acelasi storage partajat. Daca un nod se defecteaza, celelalte continua sa serveasca cererile fara intrerupere — failover-ul este transparent pentru aplicatii.\u003c/p\u003e\n\u003ch2 id=\"cum-functioneaza\" class=\"relative group\"\u003eCum functioneaza \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-functioneaza\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eUn cluster RAC este compus din doua sau mai multe servere (noduri) conectate printr-o retea privata de mare viteza (interconnect) si storage partajat (de obicei ASM — Automatic Storage Management). Fiecare nod ruleaza propria instanta Oracle, dar toate acceseaza aceleasi datafile-uri.\u003c/p\u003e","title":"RAC"},{"content":"O ragged hierarchy (ierarhie dezechilibrată) este o structură ierarhică în care nu toate ramurile ating aceeași adâncime. Unele niveluri intermediare lipsesc pentru anumite entități.\nExemplu concret #Într-o ierarhie cu trei niveluri Top Group → Group → Client:\nUnii clienți au toate cele trei niveluri (ierarhie completă) Unii clienți au un Group dar niciun Top Group Unii clienți nu au nici Group nici Top Group (clienți direcți) Rezultatul este o structură cu \u0026ldquo;goluri\u0026rdquo; care cauzează probleme în rapoartele de agregare: linii cu NULL, totaluri împărțite, drill-down-uri incomplete.\nDe ce este o problemă în DWH #Instrumentele de BI și interogările SQL se așteaptă la ierarhii complete pentru a funcționa corect. Un GROUP BY pe o coloană cu NULL-uri produce rezultate neașteptate: liniile cu NULL sunt grupate separat, totalurile nu se potrivesc, iar același grup poate apărea pe mai multe linii.\nCum se rezolvă #Tehnica standard este self-parenting-ul: o entitate fără părinte devine propriul părinte. Aceasta echilibrează ierarhia în amonte, în ETL, eliminând NULL-urile din tabela dimensională. Flag-uri suplimentare (is_direct_client, is_standalone_group) permit distingerea entităților echilibrate artificial de cele cu ierarhie naturală.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/ragged-hierarchy/","section":"Glosar","summary":"\u003cp\u003eO \u003cstrong\u003eragged hierarchy\u003c/strong\u003e (ierarhie dezechilibrată) este o structură ierarhică în care nu toate ramurile ating aceeași adâncime. Unele niveluri intermediare lipsesc pentru anumite entități.\u003c/p\u003e\n\u003ch2 id=\"exemplu-concret\" class=\"relative group\"\u003eExemplu concret \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#exemplu-concret\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eÎntr-o ierarhie cu trei niveluri Top Group → Group → Client:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eUnii clienți au toate cele trei niveluri (ierarhie completă)\u003c/li\u003e\n\u003cli\u003eUnii clienți au un Group dar niciun Top Group\u003c/li\u003e\n\u003cli\u003eUnii clienți nu au nici Group nici Top Group (clienți direcți)\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eRezultatul este o structură cu \u0026ldquo;goluri\u0026rdquo; care cauzează probleme în rapoartele de agregare: linii cu NULL, totaluri împărțite, drill-down-uri incomplete.\u003c/p\u003e","title":"Ragged hierarchy"},{"content":"Range Partitioning (partiționare pe intervale) este o strategie de partiționare a tabelelor în care rândurile sunt distribuite în partiții diferite pe baza valorii unei coloane relative la intervale predefinite. Coloana de partiționare este aproape întotdeauna o dată în data warehouse-uri.\nCum funcționează #Fiecare partiție este definită cu o clauză VALUES LESS THAN care stabilește limita superioară a intervalului. Oracle atribuie automat fiecare rând partiției corecte pe baza valorii coloanei de partiționare. Dacă un rând are data_vendita = '2025-03-15', este inserat în partiția al cărei interval include acea dată.\nCând se folosește #Range partitioning este alegerea naturală când datele au o dimensiune temporală dominantă — fact table-uri în data warehouse-uri, tabele de log, tabele de tranzacții. Granularitatea partiției (zilnică, lunară, trimestrială) depinde de volumul de inserare și de tipologia query-urilor: partițiile prea mici generează overhead de gestionare, cele prea mari reduc eficiența partition pruning-ului.\nAvantaje operaționale #Dincolo de performanța query-urilor, range partitioning permite operațiuni de gestionare a ciclului de viață al datelor imposibile pe tabele monolitice: drop instantaneu al unei partiții (fără DELETE), compresie selectivă a partițiilor istorice, mutare pe storage diferit (ILM — Information Lifecycle Management), și exchange partition pentru încărcări masive cu impact zero.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/range-partitioning/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eRange Partitioning\u003c/strong\u003e (partiționare pe intervale) este o strategie de partiționare a tabelelor în care rândurile sunt distribuite în partiții diferite pe baza valorii unei coloane relative la intervale predefinite. Coloana de partiționare este aproape întotdeauna o dată în data warehouse-uri.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eFiecare partiție este definită cu o clauză \u003ccode\u003eVALUES LESS THAN\u003c/code\u003e care stabilește limita superioară a intervalului. Oracle atribuie automat fiecare rând partiției corecte pe baza valorii coloanei de partiționare. Dacă un rând are \u003ccode\u003edata_vendita = '2025-03-15'\u003c/code\u003e, este inserat în partiția al cărei interval include acea dată.\u003c/p\u003e","title":"Range Partitioning"},{"content":"Redo Log este mecanismul prin care Oracle inregistreaza fiecare modificare a datelor (INSERT, UPDATE, DELETE, DDL) inainte ca aceasta sa fie scrisa definitiv in datafile-uri. Este garantia fundamentala a durabilitatii tranzactiilor.\nCum functioneaza #Oracle scrie modificarile in redo log-urile online secvential si continuu. Redo log-urile sunt organizate in grupuri circulare: cand un grup se umple, Oracle trece la urmatorul. Cand toate grupurile au fost folosite, Oracle revine la primul (log switch).\nOnline vs Archived # Online redo log: fisierele active unde Oracle scrie in timp real. Sunt circulare si se suprascriu Archived redo log: copii ale redo log-urilor online salvate inainte de suprascriere. Necesare pentru recuperarea point-in-time si pentru Data Guard Modul ARCHIVELOG al bazei de date activeaza crearea automata a archived log-urilor. Fara acesta, redo log-urile sunt suprascrise si recuperarea este limitata la ultimul backup complet.\nDe ce sunt importante #Redo log-urile sunt inima recuperarii si replicarii in Oracle. Fara redo:\nRecuperarea dupa un crash nu este posibila (instance recovery) Recuperarea point-in-time nu este posibila (media recovery) Data Guard nu poate functiona (replicarea se bazeaza in intregime pe redo) Flashback database nu este posibil ","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/redo-log/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eRedo Log\u003c/strong\u003e este mecanismul prin care Oracle inregistreaza fiecare modificare a datelor (INSERT, UPDATE, DELETE, DDL) inainte ca aceasta sa fie scrisa definitiv in datafile-uri. Este garantia fundamentala a durabilitatii tranzactiilor.\u003c/p\u003e\n\u003ch2 id=\"cum-functioneaza\" class=\"relative group\"\u003eCum functioneaza \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-functioneaza\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eOracle scrie modificarile in redo log-urile online secvential si continuu. Redo log-urile sunt organizate in grupuri circulare: cand un grup se umple, Oracle trece la urmatorul. Cand toate grupurile au fost folosite, Oracle revine la primul (log switch).\u003c/p\u003e","title":"Redo Log"},{"content":"Relay log-ul este un fișier de log intermediar prezent pe slave într-o arhitectură de replicare MySQL. Conține evenimentele primite din binary log-ul master-ului, în așteptarea de a fi executate local de către thread-ul SQL al slave-ului.\nCum funcționează #Fluxul replicării MySQL trece prin relay log în trei faze:\nI/O thread-ul slave-ului se conectează la master și citește binary log-urile Evenimentele primite sunt scrise în relay log-ul local SQL thread-ul slave-ului citește evenimentele din relay log și le execută pe baza de date locală Această arhitectură cu două thread-uri permite decuplarea recepției datelor de aplicarea lor: slave-ul poate continua să primească evenimente de la master chiar dacă execuția locală este temporar mai lentă.\nLa ce folosește #Relay log-ul este mecanismul care garantează consistența replicării. Funcționează ca un buffer între master și aplicarea locală a evenimentelor, permițând slave-ului să gestioneze diferențele de viteză fără a pierde date.\nCând se folosește #Relay log-ul este creat automat când se configurează replicarea MySQL. Nu necesită gestionare manuală directă, dar starea sa (poziția curentă, eventuala întârziere) este vizibilă prin SHOW REPLICA STATUS și este fundamentală pentru diagnosticarea problemelor de replica lag.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/relay-log/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eRelay log-ul\u003c/strong\u003e este un fișier de log intermediar prezent pe slave într-o arhitectură de replicare MySQL. Conține evenimentele primite din binary log-ul master-ului, în așteptarea de a fi executate local de către thread-ul SQL al slave-ului.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eFluxul replicării MySQL trece prin relay log în trei faze:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eI/O thread-ul\u003c/strong\u003e slave-ului se conectează la master și citește binary log-urile\u003c/li\u003e\n\u003cli\u003eEvenimentele primite sunt scrise în relay log-ul local\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eSQL thread-ul\u003c/strong\u003e slave-ului citește evenimentele din relay log și le execută pe baza de date locală\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003eAceastă arhitectură cu două thread-uri permite decuplarea recepției datelor de aplicarea lor: slave-ul poate continua să primească evenimente de la master chiar dacă execuția locală este temporar mai lentă.\u003c/p\u003e","title":"Relay log"},{"content":"REVOKE este comanda SQL care elimină privilegiile sau rolurile acordate anterior cu GRANT. Este complementul indispensabil al GRANT și instrumentul principal pentru restricționarea permisiunilor atunci când un model de securitate este restructurat.\nCum funcționează #Sintaxa urmează același tipar ca GRANT: REVOKE SELECT ON schema.tabela FROM utilizator sau REVOKE rol FROM utilizator. În Oracle, revocarea unui rol precum DBA elimină dintr-o singură lovitură toate privilegiile de sistem incluse în acel rol. Înainte de a executa un REVOKE critic, este esențial să se verifice că utilizatorul păstrează privilegiile necesare pentru funcțiile sale.\nCând se folosește #Cel mai frecvent caz este restructurarea modelului de securitate: eliminarea rolurilor excesive (precum DBA de la utilizatorii aplicativi) și înlocuirea lor cu roluri personalizate calibrate. Se folosește și când un utilizator își schimbă funcția, când un serviciu este dezafectat, sau când un audit relevă privilegii acordate în exces.\nCe poate merge prost #Un REVOKE prost planificat poate bloca aplicații în producție. Dacă o aplicație se conectează cu un utilizator care pierde privilegiul CREATE SESSION, încetează să funcționeze instantaneu. De aceea revocarea privilegiilor critice trebuie întotdeauna precedată de o analiză a dependențelor și un plan de implementare graduală.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/revoke/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eREVOKE\u003c/strong\u003e este comanda SQL care elimină privilegiile sau rolurile acordate anterior cu \u003ccode\u003eGRANT\u003c/code\u003e. Este complementul indispensabil al GRANT și instrumentul principal pentru restricționarea permisiunilor atunci când un model de securitate este restructurat.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eSintaxa urmează același tipar ca GRANT: \u003ccode\u003eREVOKE SELECT ON schema.tabela FROM utilizator\u003c/code\u003e sau \u003ccode\u003eREVOKE rol FROM utilizator\u003c/code\u003e. În Oracle, revocarea unui rol precum \u003ccode\u003eDBA\u003c/code\u003e elimină dintr-o singură lovitură toate privilegiile de sistem incluse în acel rol. Înainte de a executa un REVOKE critic, este esențial să se verifice că utilizatorul păstrează privilegiile necesare pentru funcțiile sale.\u003c/p\u003e","title":"REVOKE"},{"content":"RMAN (Recovery Manager) este instrumentul nativ Oracle pentru backup, restore si recovery al bazei de date. Este o utilitate de linie de comanda care gestioneaza toate operatiunile de protectie a datelor in mod integrat cu baza de date.\nCe face # Backup: complet, incremental, doar archived log-uri Restore: recuperarea datafile-urilor, tablespace-urilor sau a intregii baze de date Recovery: aplicarea redo log-urilor pentru a aduce baza de date la un punct specific in timp Duplicate: crearea de copii ale bazei de date, inclusiv baze de date standby pentru Data Guard RMAN si Data Guard #Pentru crearea unei baze de date standby, RMAN permite DUPLICATE ... FOR STANDBY FROM ACTIVE DATABASE — o copie directa prin retea de la primar la standby, fara nevoia de backup-uri intermediare pe banda sau disc. Comanda transfera toate datafile-urile si controlfile-urile si le configureaza automat pentru replicare.\nDe ce RMAN si nu copii manuale #RMAN cunoaste structura interna a bazei de date Oracle: stie ce blocuri s-au schimbat (pentru incrementale), ce fisiere sunt necesare, cum sa aplice redo-ul. O copie manuala a fisierelor (cu cp sau rsync) nu garanteaza consistenta si necesita ca baza de date sa fie inchisa. RMAN poate lucra cu baza de date deschisa, cu impact minim asupra performantei.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/rman/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eRMAN\u003c/strong\u003e (Recovery Manager) este instrumentul nativ Oracle pentru backup, restore si recovery al bazei de date. Este o utilitate de linie de comanda care gestioneaza toate operatiunile de protectie a datelor in mod integrat cu baza de date.\u003c/p\u003e\n\u003ch2 id=\"ce-face\" class=\"relative group\"\u003eCe face \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#ce-face\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eBackup\u003c/strong\u003e: complet, incremental, doar archived log-uri\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eRestore\u003c/strong\u003e: recuperarea datafile-urilor, tablespace-urilor sau a intregii baze de date\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eRecovery\u003c/strong\u003e: aplicarea redo log-urilor pentru a aduce baza de date la un punct specific in timp\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eDuplicate\u003c/strong\u003e: crearea de copii ale bazei de date, inclusiv baze de date standby pentru Data Guard\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"rman-si-data-guard\" class=\"relative group\"\u003eRMAN si Data Guard \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#rman-si-data-guard\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003ePentru crearea unei baze de date standby, RMAN permite \u003ccode\u003eDUPLICATE ... FOR STANDBY FROM ACTIVE DATABASE\u003c/code\u003e — o copie directa prin retea de la primar la standby, fara nevoia de backup-uri intermediare pe banda sau disc. Comanda transfera toate datafile-urile si controlfile-urile si le configureaza automat pentru replicare.\u003c/p\u003e","title":"RMAN"},{"content":"ROI (Return on Investment) este metrica care măsoară randamentul unei investiții raportând beneficiul net la costul suportat, exprimat ca procent. Un ROI de 200% înseamnă că fiecare euro investit a generat doi euro retur.\nCum funcționează #Se calculează ca: (Beneficiu - Cost) / Cost × 100. În contextul proiectelor IT cu componente AI, calculul ROI trebuie să includă nu doar costurile de implementare ci și cele de mentenanță, training al echipei, guvernanță și gestionare a erorilor modelului.\nLa ce servește #ROI este instrumentul principal pentru a evalua dacă o investiție în AI are sens economic. Dar pe piața actuală este și instrumentul cel mai abuzat: furnizori care promit ROI cu trei cifre bazându-se pe demo-uri controlate, fără a considera costurile operaționale reale. AI Managerul este cel care verifică dacă cifrele sunt reale, nu din slide-uri.\nCe poate merge prost #Un ROI calculat doar pe beneficiile imediate fără a număra costurile ascunse (mentenanța modelului, retraining periodic, gestionarea fals pozitivelor, conformitate GDPR) este un ROI fals. Diferența între un proiect AI de succes și un eșec costisitor stă aproape întotdeauna în calitatea calculului ROI inițial.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/roi/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eROI\u003c/strong\u003e (Return on Investment) este metrica care măsoară randamentul unei investiții raportând beneficiul net la costul suportat, exprimat ca procent. Un ROI de 200% înseamnă că fiecare euro investit a generat doi euro retur.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eSe calculează ca: \u003ccode\u003e(Beneficiu - Cost) / Cost × 100\u003c/code\u003e. În contextul proiectelor IT cu componente AI, calculul ROI trebuie să includă nu doar costurile de implementare ci și cele de mentenanță, training al echipei, guvernanță și gestionare a erorilor modelului.\u003c/p\u003e","title":"ROI"},{"content":"În PostgreSQL, ROLE este singura entitate de securitate. Nu există o distincție între \u0026ldquo;utilizator\u0026rdquo; și \u0026ldquo;rol\u0026rdquo;: totul este un ROLE. Un ROLE cu atributul LOGIN se comportă ca un utilizator; fără LOGIN, este un container de privilegii atribuibil altor ROLE-uri.\nCum funcționează #CREATE USER mario este pur și simplu o scurtătură pentru CREATE ROLE mario WITH LOGIN. ROLE-urile pot deține obiecte, moșteni privilegii de la alte ROLE-uri prin atributul INHERIT, și fi utilizate pentru a construi ierarhii de permisiuni. Un ROLE \u0026ldquo;funcțional\u0026rdquo; (fără LOGIN) grupează privilegii; ROLE-urile \u0026ldquo;utilizator\u0026rdquo; (cu LOGIN) le moștenesc.\nLa ce servește #Modelul unificat permite proiectarea arhitecturilor de securitate curate: se creează ROLE-uri funcționale precum role_readonly sau role_write, se atribuie privilegii ROLE-urilor funcționale, apoi se atribuie aceste ROLE-uri utilizatorilor reali. Când sosește un nou coleg, un singur GRANT role_readonly TO utilizator_nou este tot ce trebuie.\nDe ce contează #Simplitatea modelului este punctul său forte — dar și o capcană dacă nu este înțeles. Mulți administratori atribuie privilegii direct utilizatorilor în loc să folosească ROLE-uri funcționale, creând un ghem de GRANT-uri imposibil de întreținut. Modelul mental corect este: privilegiile merg la ROLE-uri, ROLE-urile merg la utilizatori.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/postgresql-role/","section":"Glosar","summary":"\u003cp\u003eÎn PostgreSQL, \u003cstrong\u003eROLE\u003c/strong\u003e este singura entitate de securitate. Nu există o distincție între \u0026ldquo;utilizator\u0026rdquo; și \u0026ldquo;rol\u0026rdquo;: totul este un ROLE. Un ROLE cu atributul \u003ccode\u003eLOGIN\u003c/code\u003e se comportă ca un utilizator; fără \u003ccode\u003eLOGIN\u003c/code\u003e, este un container de privilegii atribuibil altor ROLE-uri.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003e\u003ccode\u003eCREATE USER mario\u003c/code\u003e este pur și simplu o scurtătură pentru \u003ccode\u003eCREATE ROLE mario WITH LOGIN\u003c/code\u003e. ROLE-urile pot deține obiecte, moșteni privilegii de la alte ROLE-uri prin atributul \u003ccode\u003eINHERIT\u003c/code\u003e, și fi utilizate pentru a construi ierarhii de permisiuni. Un ROLE \u0026ldquo;funcțional\u0026rdquo; (fără LOGIN) grupează privilegii; ROLE-urile \u0026ldquo;utilizator\u0026rdquo; (cu LOGIN) le moștenesc.\u003c/p\u003e","title":"ROLE"},{"content":"RPO (Recovery Point Objective) este cantitatea maxima de date pe care o organizatie si-o poate permite sa piarda in caz de defectiune sau dezastru. Se masoara in timp: un RPO de 1 ora inseamna acceptarea pierderii a cel mult ultimei ore de tranzactii.\nCum se determina #RPO-ul depinde de strategia de backup si replicare:\nStrategie RPO tipic Backup nocturn pe banda 12-24 ore Backup + archived log-uri pe storage remote 1-4 ore Data Guard asincron (MaxPerformance) Cateva secunde Data Guard sincron (MaxAvailability) Zero RPO vs RTO #RPO si RTO sunt complementare dar distincte:\nRPO: cate date poti pierde (priveste inapoi in timp) RTO: cat timp dureaza restaurarea serviciului (priveste inainte in timp) O organizatie poate avea RPO=0 (zero pierderi de date) dar RTO=4 ore (dureaza 4 ore sa reporneasca), sau invers.\nDe ce conteaza #RPO-ul determina investitia necesara in infrastructura de replicare. Trecerea de la RPO=24 ore la RPO=0 poate costa cu ordine de marime mai mult, dar costul trebuie comparat cu valoarea datelor pierdute — ca in cazul a sase ore de polite de asigurare neemise.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/rpo/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eRPO\u003c/strong\u003e (Recovery Point Objective) este cantitatea maxima de date pe care o organizatie si-o poate permite sa piarda in caz de defectiune sau dezastru. Se masoara in timp: un RPO de 1 ora inseamna acceptarea pierderii a cel mult ultimei ore de tranzactii.\u003c/p\u003e\n\u003ch2 id=\"cum-se-determina\" class=\"relative group\"\u003eCum se determina \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-se-determina\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eRPO-ul depinde de strategia de backup si replicare:\u003c/p\u003e\n\u003ctable\u003e\n  \u003cthead\u003e\n      \u003ctr\u003e\n          \u003cth\u003eStrategie\u003c/th\u003e\n          \u003cth\u003eRPO tipic\u003c/th\u003e\n      \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eBackup nocturn pe banda\u003c/td\u003e\n          \u003ctd\u003e12-24 ore\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eBackup + archived log-uri pe storage remote\u003c/td\u003e\n          \u003ctd\u003e1-4 ore\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eData Guard asincron (MaxPerformance)\u003c/td\u003e\n          \u003ctd\u003eCateva secunde\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eData Guard sincron (MaxAvailability)\u003c/td\u003e\n          \u003ctd\u003eZero\u003c/td\u003e\n      \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\u003ch2 id=\"rpo-vs-rto\" class=\"relative group\"\u003eRPO vs RTO \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#rpo-vs-rto\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eRPO si RTO sunt complementare dar distincte:\u003c/p\u003e","title":"RPO"},{"content":"RTO (Recovery Time Objective) este timpul maxim acceptabil pentru restaurarea serviciului dupa o defectiune sau un dezastru. Se masoara din momentul defectiunii pana in momentul in care sistemul redevine operational.\nCum se determina #RTO-ul depinde de strategia de recuperare si de infrastructura disponibila:\nStrategie RTO tipic Restore din backup pe banda 4-12 ore Restore din backup pe disc 1-4 ore Data Guard cu switchover manual 1-5 minute Data Guard cu Fast-Start Failover 10-30 secunde RTO vs RPO # RTO: cat timp dureaza repornirea (priveste inainte) RPO: cate date poti pierde (priveste inapoi) Sunt metrici independente. Un restore din backup poate avea RTO=2 ore si RPO=24 ore. Un Data Guard sincron poate avea RTO=30 secunde si RPO=0.\nImpactul asupra business-ului #RTO-ul are un impact direct si masurabil: fiecare minut de oprire se traduce in operatiuni blocate, clienti nedeserviti, venituri pierdute. Diferenta intre RTO=6 ore si RTO=42 secunde — ca in cazul trecerii de la single instance la Data Guard — poate valora mai mult decat costul intregii infrastructuri.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/rto/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eRTO\u003c/strong\u003e (Recovery Time Objective) este timpul maxim acceptabil pentru restaurarea serviciului dupa o defectiune sau un dezastru. Se masoara din momentul defectiunii pana in momentul in care sistemul redevine operational.\u003c/p\u003e\n\u003ch2 id=\"cum-se-determina\" class=\"relative group\"\u003eCum se determina \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-se-determina\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eRTO-ul depinde de strategia de recuperare si de infrastructura disponibila:\u003c/p\u003e\n\u003ctable\u003e\n  \u003cthead\u003e\n      \u003ctr\u003e\n          \u003cth\u003eStrategie\u003c/th\u003e\n          \u003cth\u003eRTO tipic\u003c/th\u003e\n      \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eRestore din backup pe banda\u003c/td\u003e\n          \u003ctd\u003e4-12 ore\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eRestore din backup pe disc\u003c/td\u003e\n          \u003ctd\u003e1-4 ore\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eData Guard cu switchover manual\u003c/td\u003e\n          \u003ctd\u003e1-5 minute\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eData Guard cu Fast-Start Failover\u003c/td\u003e\n          \u003ctd\u003e10-30 secunde\u003c/td\u003e\n      \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\u003ch2 id=\"rto-vs-rpo\" class=\"relative group\"\u003eRTO vs RPO \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#rto-vs-rpo\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eRTO\u003c/strong\u003e: cat timp dureaza repornirea (priveste inainte)\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eRPO\u003c/strong\u003e: cate date poti pierde (priveste inapoi)\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eSunt metrici independente. Un restore din backup poate avea RTO=2 ore si RPO=24 ore. Un Data Guard sincron poate avea RTO=30 secunde si RPO=0.\u003c/p\u003e","title":"RTO"},{"content":"SCAN Listener (Single Client Access Name) este componenta Oracle RAC care ofera un singur nume DNS pentru accesul la cluster. Aplicatiile se conecteaza la SCAN name fara a fi nevoie sa cunoasca nodurile individuale: listener-ul distribuie automat conexiunile intre nodurile active.\nCum functioneaza #SCAN este un nume DNS care se rezolva la trei adrese IP virtuale (VIP), distribuite intre nodurile clusterului. Cand un client se conecteaza la SCAN name, DNS-ul returneaza una dintre cele trei IP-uri, iar listener-ul de pe acel IP redirectioneaza conexiunea catre nodul cel mai potrivit in functie de serviciul solicitat si de sarcina.\nAvantajul este ca connection string-urile aplicatiei nu se schimba niciodata: daca un nod este adaugat sau eliminat din cluster, SCAN gestioneaza totul in mod transparent.\nConfiguratie tipica #Un connection string care foloseste SCAN:\njdbc:oracle:thin:@//scan-name.example.com:1521/service_name Cele trei SCAN VIP ruleaza pe orice nod al clusterului. Intr-un cluster cu doua noduri, un nod gazduieste doua VIP-uri si celalalt unul (sau invers).\nIn migrari #In migrarile catre OCI, SCAN listener-ul este reconfigurat cu DNS-ul noii infrastructuri. Este unul dintre pasii cutover-ului: actualizarea connection string-urilor pentru a indica noul SCAN name pe OCI. Daca naming-ul este bine gestionat, este o modificare intr-un singur punct (connection pool-ul aplicatiei), nu in zeci de fisiere de configurare imprastiate.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/scan-listener/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eSCAN Listener\u003c/strong\u003e (Single Client Access Name) este componenta Oracle RAC care ofera un singur nume DNS pentru accesul la cluster. Aplicatiile se conecteaza la SCAN name fara a fi nevoie sa cunoasca nodurile individuale: listener-ul distribuie automat conexiunile intre nodurile active.\u003c/p\u003e\n\u003ch2 id=\"cum-functioneaza\" class=\"relative group\"\u003eCum functioneaza \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-functioneaza\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eSCAN este un nume DNS care se rezolva la trei adrese IP virtuale (VIP), distribuite intre nodurile clusterului. Cand un client se conecteaza la SCAN name, DNS-ul returneaza una dintre cele trei IP-uri, iar listener-ul de pe acel IP redirectioneaza conexiunea catre nodul cel mai potrivit in functie de serviciul solicitat si de sarcina.\u003c/p\u003e","title":"SCAN Listener"},{"content":"SCD (Slowly Changing Dimension) se refera la un set de tehnici folosite in data warehouse pentru gestionarea modificarilor in datele tabelelor dimensionale de-a lungul timpului.\nTipurile principale # Tipul 1: suprascrierea valorii anterioare. Nicio istorie conservata Tipul 2: inserarea unui rand nou cu date de valabilitate (data inceput, data sfarsit). Conserva toata istoria Tipul 3: adaugarea unei coloane pentru valoarea anterioara. Conserva doar ultima modificare De ce conteaza #Intr-o baza de date tranzactionala, cand un client isi schimba adresa se actualizeaza inregistrarea. Intr-un data warehouse acest lucru ar insemna pierderea istoriei: toate vanzarile anterioare ar aparea asociate noii adrese.\nSCD Tipul 2 rezolva aceasta problema mentinand un rand pentru fiecare versiune a datelor, cu date de valabilitate care permit reconstructia situatiei in orice moment in timp.\nCand se foloseste #Alegerea tipului depinde de cerinta de business. Daca conteaza doar valoarea curenta, Tipul 1 este suficient. Daca business-ul are nevoie de analize istorice precise — si in majoritatea data warehouse-urilor reale asa este — Tipul 2 este alegerea standard.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/scd/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eSCD\u003c/strong\u003e (Slowly Changing Dimension) se refera la un set de tehnici folosite in data warehouse pentru gestionarea modificarilor in datele tabelelor dimensionale de-a lungul timpului.\u003c/p\u003e\n\u003ch2 id=\"tipurile-principale\" class=\"relative group\"\u003eTipurile principale \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#tipurile-principale\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eTipul 1\u003c/strong\u003e: suprascrierea valorii anterioare. Nicio istorie conservata\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eTipul 2\u003c/strong\u003e: inserarea unui rand nou cu date de valabilitate (data inceput, data sfarsit). Conserva toata istoria\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eTipul 3\u003c/strong\u003e: adaugarea unei coloane pentru valoarea anterioara. Conserva doar ultima modificare\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"de-ce-conteaza\" class=\"relative group\"\u003eDe ce conteaza \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#de-ce-conteaza\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eIntr-o baza de date tranzactionala, cand un client isi schimba adresa se actualizeaza inregistrarea. Intr-un data warehouse acest lucru ar insemna pierderea istoriei: toate vanzarile anterioare ar aparea asociate noii adrese.\u003c/p\u003e","title":"SCD"},{"content":"O Schemă într-o bază de date relațională este un namespace logic care grupează obiecte precum tabele, vizualizări, funcții și secvențe. Funcționează ca un container organizațional în cadrul unei baze de date.\nCum funcționează #În PostgreSQL, schema prestabilită este public. Pentru a accesa un obiect dintr-o altă schemă este necesar prefixul: schema1.tabela. Privilegiul USAGE pe o schemă este prerequisit pentru accesarea oricărui obiect din ea — fără USAGE, nici măcar un GRANT SELECT pe tabele nu funcționează.\nLa ce servește #Schemele permit separarea logică a datelor: o schemă pentru aplicație, una pentru raportare, una pentru tabelele de staging. În Oracle, conceptul este diferit: fiecare utilizator este automat o schemă, iar obiectele create de acel utilizator trăiesc în schema sa. În PostgreSQL, schemele și utilizatorii sunt entități independente.\nDe ce contează #Gestionarea permisiunilor pe scheme este sursa cea mai comună de erori la crearea utilizatorilor cu acces limitat. Uitarea GRANT USAGE ON SCHEMA este greșeala clasică care generează \u0026ldquo;permission denied for schema\u0026rdquo; chiar și când permisiunile pe tabele sunt corecte.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/schema/","section":"Glosar","summary":"\u003cp\u003eO \u003cstrong\u003eSchemă\u003c/strong\u003e într-o bază de date relațională este un namespace logic care grupează obiecte precum tabele, vizualizări, funcții și secvențe. Funcționează ca un container organizațional în cadrul unei baze de date.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eÎn PostgreSQL, schema prestabilită este \u003ccode\u003epublic\u003c/code\u003e. Pentru a accesa un obiect dintr-o altă schemă este necesar prefixul: \u003ccode\u003eschema1.tabela\u003c/code\u003e. Privilegiul \u003ccode\u003eUSAGE\u003c/code\u003e pe o schemă este prerequisit pentru accesarea oricărui obiect din ea — fără \u003ccode\u003eUSAGE\u003c/code\u003e, nici măcar un \u003ccode\u003eGRANT SELECT\u003c/code\u003e pe tabele nu funcționează.\u003c/p\u003e","title":"Schema"},{"content":"Scope-ul (domeniul) unui proiect definește perimetrul a ceea ce proiectul trebuie să realizeze: funcționalități incluse, livrabile așteptate, constrângeri și limite convenite cu stakeholderii. Tot ce este în scope se face; tot ce este în afara, nu.\nCum funcționează #Scope-ul se definește în fazele inițiale ale proiectului prin documente precum Statement of Work sau Project Charter. Orice cerere de modificare ulterioară trebuie să treacă printr-un proces formal de gestionare a schimbărilor pentru a evalua impactul asupra termenelor, bugetului și resurselor.\nDe ce contează #Scope creep — expansiunea necontrolată a cerințelor — este printre cauzele principale ale eșecului proiectelor IT. Fiecare funcționalitate adăugată fără reevaluarea termenelor și bugetului erodează resursele disponibile. Un PM eficient știe să spună \u0026ldquo;da, și pentru a include asta trebuie să eliminăm cealaltă\u0026rdquo; — nu simplu \u0026ldquo;nu\u0026rdquo;.\nCând se folosește #În fiecare fază a proiectului: în planificare pentru definirea limitelor, în execuție pentru evaluarea cererilor de schimbare, în negocierile cu stakeholderii pentru redirecționarea așteptărilor. Claritatea asupra scope-ului este baza fiecărei decizii de proiect.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/scope/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eScope\u003c/strong\u003e-ul (domeniul) unui proiect definește perimetrul a ceea ce proiectul trebuie să realizeze: funcționalități incluse, livrabile așteptate, constrângeri și limite convenite cu stakeholderii. Tot ce este în scope se face; tot ce este în afara, nu.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eScope-ul se definește în fazele inițiale ale proiectului prin documente precum Statement of Work sau Project Charter. Orice cerere de modificare ulterioară trebuie să treacă printr-un proces formal de gestionare a schimbărilor pentru a evalua impactul asupra termenelor, bugetului și resurselor.\u003c/p\u003e","title":"Scope"},{"content":"Scope Creep este expansiunea progresivă și adesea necontrolată a scopului unui proiect față de ceea ce fusese definit inițial. Cerințe noi, modificări ale specificațiilor și funcționalități suplimentare se acumulează fără o ajustare corespunzătoare a bugetului și a termenelor.\nCum funcționează #Într-un proiect software, scope creep-ul începe de obicei cu cereri aparent mici: \u0026ldquo;hai să adăugăm și acest câmp\u0026rdquo;, \u0026ldquo;ar fi util și această funcție\u0026rdquo;. Fiecare modificare individuală pare rezonabilă, dar efectul cumulativ este devastator. Specificațiile devin o țintă mobilă, echipa nu reușește niciodată să atingă o baseline stabilă, iar proiectul intră într-un ciclu infinit de revizuiri.\nLa ce folosește #Recunoașterea scope creep-ului este primul pas pentru prevenirea lui. Mecanismele de apărare includ: cereri formale de modificare cu analiză de impact, înghețarea specificațiilor pe fază, prioritizare riguroasă și capacitatea de a spune \u0026ldquo;nu\u0026rdquo; — sau cel puțin \u0026ldquo;nu acum\u0026rdquo;.\nCând se folosește #Termenul descrie un anti-pattern de project management de evitat. În proiectele mari de consultanță, scope creep-ul devine adesea o armă în mâinile furnizorului: specificațiile incomplete justifică întârzierile și costurile suplimentare, transformând un proiect la pachet într-o consultanță pe termen nedeterminat.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/scope-creep/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eScope Creep\u003c/strong\u003e este expansiunea progresivă și adesea necontrolată a scopului unui proiect față de ceea ce fusese definit inițial. Cerințe noi, modificări ale specificațiilor și funcționalități suplimentare se acumulează fără o ajustare corespunzătoare a bugetului și a termenelor.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eÎntr-un proiect software, scope creep-ul începe de obicei cu cereri aparent mici: \u0026ldquo;hai să adăugăm și acest câmp\u0026rdquo;, \u0026ldquo;ar fi util și această funcție\u0026rdquo;. Fiecare modificare individuală pare rezonabilă, dar efectul cumulativ este devastator. Specificațiile devin o țintă mobilă, echipa nu reușește niciodată să atingă o baseline stabilă, iar proiectul intră într-un ciclu infinit de revizuiri.\u003c/p\u003e","title":"Scope Creep"},{"content":"Scrum este un framework agil pentru gestionarea proiectelor care organizează munca în iterații cu durată fixă numite sprinturi (de obicei 2 săptămâni). Definește trei roluri (Product Owner, Scrum Master, Development Team) și patru ceremonii (Sprint Planning, Daily Standup, Sprint Review, Sprint Retrospective).\nCum funcționează #Fiecare sprint începe cu o planificare, continuă cu standup-uri zilnice pentru sincronizare, și se termină cu o review (ce s-a făcut) și o retrospectivă (cum să îmbunătățim procesul). Timeboxing-ul este principiul fundamental: fiecare ceremonie are o durată maximă nenegociabilă.\nLa ce servește #Scrum oferă structură echipelor care lucrează la proiecte complexe cu cerințe în evoluție. Ciclul scurt al sprinturilor permite feedback rapid, corecții de direcție frecvente și vizibilitate continuă asupra stadiului proiectului. Standup-ul zilnic este una dintre cele mai recognoscibile ceremonii ale framework-ului.\nCe poate merge prost #Cel mai frecvent risc este adoptarea Scrum ca ritual fără înțelegerea principiilor sale. Echipe care fac standup dar nu respectă timeboxul, sprinturi fără un obiectiv clar, retrospective care nu produc acțiuni concrete. Scrum funcționează când este aplicat cu disciplină, nu când este doar o etichetă.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/scrum/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eScrum\u003c/strong\u003e este un framework agil pentru gestionarea proiectelor care organizează munca în iterații cu durată fixă numite sprinturi (de obicei 2 săptămâni). Definește trei roluri (Product Owner, Scrum Master, Development Team) și patru ceremonii (Sprint Planning, Daily Standup, Sprint Review, Sprint Retrospective).\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eFiecare sprint începe cu o planificare, continuă cu standup-uri zilnice pentru sincronizare, și se termină cu o review (ce s-a făcut) și o retrospectivă (cum să îmbunătățim procesul). Timeboxing-ul este principiul fundamental: fiecare ceremonie are o durată maximă nenegociabilă.\u003c/p\u003e","title":"Scrum"},{"content":"secure-file-priv este o variabilă de sistem MySQL care controlează unde instrucțiunile LOAD DATA INFILE, SELECT INTO OUTFILE și funcția LOAD_FILE() pot opera pe filesystem-ul serverului.\nCum funcționează #Variabila acceptă trei valori: o cale specifică (ex. /var/lib/mysql-files/), care limitează operațiunile pe fișiere la acel director; un șir gol (\u0026quot;\u0026quot;), care nu impune nicio restricție; sau NULL, care dezactivează complet operațiunile pe fișiere. Valoarea poate fi setată doar în fișierul de configurare (my.cnf) și necesită restart al serviciului pentru a fi modificată — nu poate fi schimbată la runtime.\nLa ce folosește #Directiva previne accesul arbitrar la filesystem din partea utilizatorilor MySQL cu privilegiul FILE. Fără această protecție, un atacator care exploatează o SQL injection ar putea citi fișiere de sistem (ex. /etc/passwd, chei SSH) sau scrie web shell-uri în webroot-ul unui server web de pe același host.\nCând se folosește #secure-file-priv trebuie configurată la momentul setup-ului fiecărei instanțe MySQL, specificând un director dedicat. În mediile multi-instanță, fiecare instanță ar trebui să aibă propriul director secure-file-priv. Dacă exportul pe fișier e blocat, alternativa recomandată e folosirea clientului mysql din shell cu opțiunile -B și -e pentru a redirecționa output-ul.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/secure-file-priv/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003esecure-file-priv\u003c/strong\u003e este o variabilă de sistem MySQL care controlează unde instrucțiunile \u003ccode\u003eLOAD DATA INFILE\u003c/code\u003e, \u003ccode\u003eSELECT INTO OUTFILE\u003c/code\u003e și funcția \u003ccode\u003eLOAD_FILE()\u003c/code\u003e pot opera pe filesystem-ul serverului.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eVariabila acceptă trei valori: o cale specifică (ex. \u003ccode\u003e/var/lib/mysql-files/\u003c/code\u003e), care limitează operațiunile pe fișiere la acel director; un șir gol (\u003ccode\u003e\u0026quot;\u0026quot;\u003c/code\u003e), care nu impune nicio restricție; sau \u003ccode\u003eNULL\u003c/code\u003e, care dezactivează complet operațiunile pe fișiere. Valoarea poate fi setată doar în fișierul de configurare (\u003ccode\u003emy.cnf\u003c/code\u003e) și necesită restart al serviciului pentru a fi modificată — nu poate fi schimbată la runtime.\u003c/p\u003e","title":"secure-file-priv"},{"content":"Self-parenting-ul este o tehnică de dimensional modeling folosită pentru a echilibra ierarhiile dezechilibrate (ragged hierarchies). Principiul este simplu: o entitate care nu are un nivel ierarhic superior devine propriul părinte la acel nivel.\nCum funcționează #Într-o ierarhie cu trei niveluri Top Group → Group → Client:\nUn Client fără Group folosește propriul nume/ID ca Group Un Group fără Top Group folosește propriul nume/ID ca Top Group Rezultatul este o tabelă dimensională fără NULL-uri în coloanele ierarhice, cu toate nivelurile întotdeauna populate.\nFlag-urile de distincție #Pentru a nu pierde informația despre care entități au fost echilibrate artificial, se adaugă flag-uri dimensiunii:\nis_direct_client = 'Y': clientul nu avea un Group în sursă is_standalone_group = 'Y': Group-ul nu avea un Top Group în sursă Aceste flag-uri permit business-ului să filtreze \u0026ldquo;adevăratele\u0026rdquo; top group-uri de clienții promovați.\nDe ce în ETL, nu în raport #Self-parenting-ul se aplică o dată în ETL, nu în fiecare raport individual. Un raport ar trebui să facă GROUP BY și JOIN, nu să decidă cum să gestioneze nivelurile lipsă. Dacă logica de echilibrare este în model, toate rapoartele beneficiază automat.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/self-parenting/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eSelf-parenting-ul\u003c/strong\u003e este o tehnică de dimensional modeling folosită pentru a echilibra ierarhiile dezechilibrate (ragged hierarchies). Principiul este simplu: o entitate care nu are un nivel ierarhic superior devine propriul părinte la acel nivel.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eÎntr-o ierarhie cu trei niveluri Top Group → Group → Client:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eUn Client fără Group folosește propriul nume/ID ca Group\u003c/li\u003e\n\u003cli\u003eUn Group fără Top Group folosește propriul nume/ID ca Top Group\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eRezultatul este o tabelă dimensională fără NULL-uri în coloanele ierarhice, cu toate nivelurile întotdeauna populate.\u003c/p\u003e","title":"Self-parenting"},{"content":"Sequential Scan (Seq Scan) este operația prin care PostgreSQL citește o tabelă de la început până la sfârșit, bloc cu bloc, fără a folosi vreun index. Este echivalentul PostgreSQL al Full Table Scan din Oracle.\nCând este normal #Pe tabele mici (câteva mii de rânduri), sequential scan-ul este adesea opțiunea cea mai eficientă. Citirea unei tabele întregi secvențial este mai rapidă decât lookup-urile pe un index când tabela încape în câteva pagini. Optimizer-ul alege sequential scan-ul când estimează că este mai ieftin decât un index scan.\nCând este o problemă #Pe tabele mari (milioane de rânduri), un sequential scan pentru a returna puține rânduri este un semnal de alarmă. Înseamnă că lipsește un index adecvat sau că statisticile tabelei sunt depășite și optimizer-ul face estimări greșite. pg_stat_statements ajută la identificarea acestor situații arătând query-urile cu cel mai prost raport blocuri citite / rânduri returnate.\nCum se diagnostichează #EXPLAIN arată \u0026ldquo;Seq Scan on tabel\u0026rdquo; în planul de execuție. Dacă filtrul ulterior elimină majoritatea rândurilor (rows removed by filter \u0026raquo; rows), aproape sigur este nevoie de un index pe coloana filtrului.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/sequential-scan/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eSequential Scan\u003c/strong\u003e (Seq Scan) este operația prin care PostgreSQL citește o tabelă de la început până la sfârșit, bloc cu bloc, fără a folosi vreun index. Este echivalentul PostgreSQL al Full Table Scan din Oracle.\u003c/p\u003e\n\u003ch2 id=\"când-este-normal\" class=\"relative group\"\u003eCând este normal \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#c%c3%a2nd-este-normal\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003ePe tabele mici (câteva mii de rânduri), sequential scan-ul este adesea opțiunea cea mai eficientă. Citirea unei tabele întregi secvențial este mai rapidă decât lookup-urile pe un index când tabela încape în câteva pagini. Optimizer-ul alege sequential scan-ul când estimează că este mai ieftin decât un index scan.\u003c/p\u003e","title":"Sequential Scan"},{"content":"SGA (System Global Area) este zona de memorie partajată principală a Oracle Database. Conține structurile de date fundamentale: buffer cache (pagini de date citite de pe disc), shared pool (planuri de execuție și dicționar de date), redo log buffer și large pool.\nCum funcționează #Dimensiunea SGA este controlată de parametrul SGA_TARGET sau SGA_MAX_SIZE. Oracle alocă SGA la pornirea instanței în memoria partajată a sistemului de operare. Parametrii kernel Linux shmmax și shmall trebuie dimensionați pentru a permite alocarea completă a SGA.\nLa ce servește #Toată activitatea de citire și scriere a bazei de date trece prin SGA. Un buffer cache eficient evită citirile fizice de pe disc. Un shared pool bine dimensionat evită re-parsing-ul interogărilor. SGA este inima performanțelor Oracle — și trebuie să rezide în Huge Pages pentru a maximiza eficiența.\nDe ce contează #O SGA nealocată în Huge Pages înseamnă milioane de intrări în Page Table și overflow constant al TLB. Rezultatul sunt latch free waits, library cache contention și CPU ridicat. Configurarea Huge Pages și a parametrului memlock unlimited pentru utilizatorul oracle este prerequisitul pentru orice tuning serios.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/sga/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eSGA\u003c/strong\u003e (System Global Area) este zona de memorie partajată principală a Oracle Database. Conține structurile de date fundamentale: buffer cache (pagini de date citite de pe disc), shared pool (planuri de execuție și dicționar de date), redo log buffer și large pool.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eDimensiunea SGA este controlată de parametrul \u003ccode\u003eSGA_TARGET\u003c/code\u003e sau \u003ccode\u003eSGA_MAX_SIZE\u003c/code\u003e. Oracle alocă SGA la pornirea instanței în memoria partajată a sistemului de operare. Parametrii kernel Linux \u003ccode\u003eshmmax\u003c/code\u003e și \u003ccode\u003eshmall\u003c/code\u003e trebuie dimensionați pentru a permite alocarea completă a SGA.\u003c/p\u003e","title":"SGA"},{"content":"shared_buffers este parametrul care controlează dimensiunea zonei de memorie partajată pe care PostgreSQL o folosește ca cache pentru blocurile de date citite de pe disc. De fiecare dată când PostgreSQL citește o pagină de date (8 KB), o păstrează în shared_buffers pentru citirile ulterioare.\nCum funcționează #PostgreSQL alocă memoria pentru shared_buffers la pornirea serviciului. Toate procesele backend partajează această zonă de memorie. Când un proces are nevoie de un bloc de date, caută mai întâi în shared_buffers. Dacă îl găsește (cache hit), citirea este imediată. Dacă nu (cache miss), trebuie să citească de pe disc — o operație cu ordine de mărime mai lentă.\nCât să aloci #Valoarea implicită este 128 MB — inadecvată pentru orice bază de date de producție. Regula empirică este să configurezi shared_buffers la 25% din RAM-ul disponibil. Pe un server cu 64 GB de RAM, 16 GB este un bun punct de pornire. Valori peste 40% din RAM rareori aduc beneficii deoarece PostgreSQL se bazează și pe cache-ul sistemului de operare.\nCum să-l monitorizezi #View-ul pg_stat_bgwriter arată raportul dintre buffers_alloc (blocuri nou alocate) și totalul blocurilor servite. Un cache hit ratio sub 95% sugerează că shared_buffers ar putea fi subdimensionat.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/shared-buffers/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eshared_buffers\u003c/strong\u003e este parametrul care controlează dimensiunea zonei de memorie partajată pe care PostgreSQL o folosește ca cache pentru blocurile de date citite de pe disc. De fiecare dată când PostgreSQL citește o pagină de date (8 KB), o păstrează în shared_buffers pentru citirile ulterioare.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003ePostgreSQL alocă memoria pentru shared_buffers la pornirea serviciului. Toate procesele backend partajează această zonă de memorie. Când un proces are nevoie de un bloc de date, caută mai întâi în shared_buffers. Dacă îl găsește (cache hit), citirea este imediată. Dacă nu (cache miss), trebuie să citească de pe disc — o operație cu ordine de mărime mai lentă.\u003c/p\u003e","title":"shared_buffers"},{"content":"Single-primary este modul de operare cel mai frecvent al MySQL Group Replication, în care un singur nod din cluster — primary-ul — acceptă operații de scriere. Celelalte noduri (secondary) sunt read-only (read_only=ON, super_read_only=ON) și primesc modificările prin replicarea sincronă a grupului.\nCum funcționează #Parametrul group_replication_single_primary_mode=ON activează acest mod. Primary-ul este singurul nod cu read_only=OFF. Dacă primary-ul este oprit sau devine inaccesibil, clusterul declanșează o alegere automată și unul dintre secondary devine noul primary în câteva secunde.\nDe ce se folosește #Modul single-primary evită conflictele de scriere concurentă tipice pentru multi-primary. În producție, majoritatea clusterelor MySQL folosesc acest mod pentru că este mai previzibil: aplicațiile scriu pe un singur endpoint, replicarea este liniară și debugging-ul este mai simplu.\nCe poate merge prost #Când primary-ul este oprit pentru mentenanță, clusterul face un failover automat. În acele secunde, conexiunile active pot fi întrerupte și tranzacțiile în curs pot eșua. Este o întrerupere scurtă dar trebuie comunicată. Regula practică: într-o intervenție de mentenanță pe un cluster single-primary, secondary-urile se ating primele, primary-ul la urmă.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/single-primary/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eSingle-primary\u003c/strong\u003e este modul de operare cel mai frecvent al MySQL Group Replication, în care un singur nod din cluster — primary-ul — acceptă operații de scriere. Celelalte noduri (secondary) sunt read-only (\u003ccode\u003eread_only=ON\u003c/code\u003e, \u003ccode\u003esuper_read_only=ON\u003c/code\u003e) și primesc modificările prin replicarea sincronă a grupului.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eParametrul \u003ccode\u003egroup_replication_single_primary_mode=ON\u003c/code\u003e activează acest mod. Primary-ul este singurul nod cu \u003ccode\u003eread_only=OFF\u003c/code\u003e. Dacă primary-ul este oprit sau devine inaccesibil, clusterul declanșează o alegere automată și unul dintre secondary devine noul primary în câteva secunde.\u003c/p\u003e","title":"Single-primary"},{"content":"Smart Working-ul (lucru agil) este un model organizațional care permite angajatului să lucreze de oriunde, combinând zile la birou și zile la distanță, cu program flexibil și evaluare bazată pe rezultate în loc de prezență.\nCum funcționează #Modelul tipic este 80/20: 80% la distanță, 20% la birou. Zilele la birou servesc pentru workshopuri, review-uri de proiect și team building — nu pentru a încălzi scaunul. Compania furnizează echipament pentru postul de lucru de acasă (monitor, scaun ergonomic, căști) și o contribuție pentru conectivitate.\nLa ce servește #În consultanța IT, smart working-ul elimină costul navetei (până la 90 de ore/lună pentru un consultant roman), reduce costurile imobiliare (de la 50 de posturi fixe la 15 hot desks) și restituie ore de productivitate reală. Un consultant care începe lucrul la 7:45 proaspăt și concentrat produce mai mult decât unul care ajunge la 9:30 stresat de trafic.\nDe ce contează #Smart working-ul nu este un beneficiu — este un model organizațional care necesită KPI-uri clare, încredere reciprocă și instrumente de comunicare adecvate. Companiile care îl adoptă ca \u0026ldquo;concesie\u0026rdquo; în loc de \u0026ldquo;strategie\u0026rdquo; îi pierd beneficiile. Cele care îl refuză din presenteism plătesc un cost invizibil în productivitate pierdută și talente în fugă.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/smart-working/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eSmart Working\u003c/strong\u003e-ul (lucru agil) este un model organizațional care permite angajatului să lucreze de oriunde, combinând zile la birou și zile la distanță, cu program flexibil și evaluare bazată pe rezultate în loc de prezență.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eModelul tipic este 80/20: 80% la distanță, 20% la birou. Zilele la birou servesc pentru workshopuri, review-uri de proiect și team building — nu pentru a încălzi scaunul. Compania furnizează echipament pentru postul de lucru de acasă (monitor, scaun ergonomic, căști) și o contribuție pentru conectivitate.\u003c/p\u003e","title":"Smart Working"},{"content":"Snapshot in Oracle este o captura punctuala a statisticilor de performanta ale bazei de date stocata in repository-ul AWR. Implicit Oracle genereaza un snapshot la fiecare 60 de minute si le pastreaza timp de 8 zile.\nCum functioneaza #Fiecare snapshot inregistreaza sute de metrici: wait events, statistici SQL, metrici de memorie (SGA, PGA), I/O per datafile, statistici de sistem. Compararea a doua snapshot-uri genereaza raportul AWR, care arata ce s-a schimbat intre cele doua momente.\nSnapshot-uri manuale #In situatii de urgenta se poate genera un snapshot manual pentru a captura starea curenta:\nEXEC DBMS_WORKLOAD_REPOSITORY.create_snapshot; Acest lucru este util cand vrei un punct de referinta imediat — de exemplu, inainte si dupa un deploy — fara a astepta ciclul automat.\nGestionare #Snapshot-urile sunt accesibile prin view-ul DBA_HIST_SNAPSHOT. Retentia (cate zile sa le pastrezi) si intervalul (la cate minute sa le generezi) se configureaza cu:\nEXEC DBMS_WORKLOAD_REPOSITORY.modify_snapshot_settings( retention =\u0026gt; 43200, -- 30 zile in minute interval =\u0026gt; 30 -- la fiecare 30 minute ); De ce sunt importante #Fara snapshot-uri, nu exista AWR. Fara AWR, diagnosticarea unui problem de performanta devine un exercitiu de intuitie in loc de o analiza bazata pe date. Snapshot-urile sunt fundatia observabilitatii in Oracle.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/snapshot-oracle/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eSnapshot\u003c/strong\u003e in Oracle este o captura punctuala a statisticilor de performanta ale bazei de date stocata in repository-ul AWR. Implicit Oracle genereaza un snapshot la fiecare 60 de minute si le pastreaza timp de 8 zile.\u003c/p\u003e\n\u003ch2 id=\"cum-functioneaza\" class=\"relative group\"\u003eCum functioneaza \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-functioneaza\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eFiecare snapshot inregistreaza sute de metrici: wait events, statistici SQL, metrici de memorie (SGA, PGA), I/O per datafile, statistici de sistem. Compararea a doua snapshot-uri genereaza raportul AWR, care arata ce s-a schimbat intre cele doua momente.\u003c/p\u003e","title":"Snapshot (Oracle)"},{"content":"Split-brain-ul este o condiție critică care apare când un cluster de baze de date se împarte în două sau mai multe partiții care nu pot comunica între ele, iar fiecare partiție continuă să accepte scrieri independent. Rezultatul sunt date divergente imposibil de reconciliat automat.\nCum funcționează #Într-un cluster cu 3 noduri, dacă rețeaua dintre Nodul 1 și Nodurile 2-3 se întrerupe, fără protecția quorum-ului ambele părți ar putea continua să accepte scrieri. Când rețeaua se restabilește, clusterul s-ar găsi cu două versiuni diferite ale acelorași date. Mecanismul de quorum previne acest scenariu: doar partiția cu majoritatea nodurilor (quorum) poate continua să funcționeze.\nLa ce folosește #Înțelegerea split-brain-ului este fundamentală pentru proiectarea de clustere de baze de date fiabile. Este motivul principal pentru care Galera Cluster necesită un număr impar de noduri (3, 5, 7) și implementează mecanismul de quorum. Cu un număr par de noduri, o partiție de rețea poate împărți clusterul în două jumătăți egale, niciuna dintre ele neavând quorum.\nCând se folosește #Termenul split-brain descrie un risc de evitat, nu o funcționalitate de activat. În Galera, protecția este automată: nodurile care pierd quorum-ul trec în starea Non-Primary și refuză scrierile. Parametrul pc.ignore_quorum dezactivează această protecție, dar folosirea lui în producție este puternic descurajată.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/split-brain/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eSplit-brain-ul\u003c/strong\u003e este o condiție critică care apare când un cluster de baze de date se împarte în două sau mai multe partiții care nu pot comunica între ele, iar fiecare partiție continuă să accepte scrieri independent. Rezultatul sunt date divergente imposibil de reconciliat automat.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eÎntr-un cluster cu 3 noduri, dacă rețeaua dintre Nodul 1 și Nodurile 2-3 se întrerupe, fără protecția quorum-ului ambele părți ar putea continua să accepte scrieri. Când rețeaua se restabilește, clusterul s-ar găsi cu două versiuni diferite ale acelorași date. Mecanismul de quorum previne acest scenariu: doar partiția cu majoritatea nodurilor (quorum) poate continua să funcționeze.\u003c/p\u003e","title":"Split-brain"},{"content":"SQL Injection este una dintre cele mai răspândite și periculoase vulnerabilități în aplicațiile web. Apare când input-urile furnizate de utilizator sunt inserate direct în interogările SQL fără validare sau parametrizare, permițând unui atacator să modifice logica interogării.\nCum funcționează #Atacatorul inserează fragmente de cod SQL în câmpurile de input ale aplicației (formulare de autentificare, câmpuri de căutare, parametri URL). Dacă aplicația concatenează aceste input-uri direct în interogările SQL, codul malițios este executat de baza de date cu privilegiile utilizatorului aplicativ. În combinație cu privilegiul FILE al MySQL-ului și un secure-file-priv neconfigurat, atacatorul poate citi fișiere de sistem sau scrie fișiere arbitrare pe server.\nLa ce folosește #Înțelegerea SQL injection este fundamentală pentru cine gestionează baze de date în producție, deoarece multe configurații de securitate (precum secure-file-priv, gestionarea privilegiilor și separarea utilizatorilor) există specific pentru a mitiga impactul acestui tip de atac.\nCând se folosește #Termenul descrie un atac de prevenit, nu o tehnică de utilizat. Contramăsurile principale sunt: interogări parametrizate (prepared statements), validarea input-urilor, principiul privilegiului minim pentru utilizatorii bazei de date și configurarea corectă a directivelor precum secure-file-priv.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/sql-injection/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eSQL Injection\u003c/strong\u003e este una dintre cele mai răspândite și periculoase vulnerabilități în aplicațiile web. Apare când input-urile furnizate de utilizator sunt inserate direct în interogările SQL fără validare sau parametrizare, permițând unui atacator să modifice logica interogării.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eAtacatorul inserează fragmente de cod SQL în câmpurile de input ale aplicației (formulare de autentificare, câmpuri de căutare, parametri URL). Dacă aplicația concatenează aceste input-uri direct în interogările SQL, codul malițios este executat de baza de date cu privilegiile utilizatorului aplicativ. În combinație cu privilegiul \u003ccode\u003eFILE\u003c/code\u003e al MySQL-ului și un \u003ccode\u003esecure-file-priv\u003c/code\u003e neconfigurat, atacatorul poate citi fișiere de sistem sau scrie fișiere arbitrare pe server.\u003c/p\u003e","title":"SQL Injection"},{"content":"SST (State Snapshot Transfer) este mecanismul prin care un nod Galera care se alătură clusterului (sau care a fost offline prea mult timp) primește o copie completă a întregului set de date de la un nod donator.\nCum funcționează #Când un nod se alătură clusterului și gap-ul de tranzacții lipsă depășește dimensiunea gcache-ului, clusterul inițiază un SST. Nodul donator creează un snapshot complet al bazei de date și îl transferă nodului receptor. Metodele disponibile sunt: mariabackup (nu blochează donatorul), rsync (rapid dar blochează donatorul pe citire), și mysqldump (lent și blocant).\nLa ce folosește #SST este esențial pentru două scenarii: adăugarea unui nod nou la cluster (primul join) și recuperarea unui nod care a fost offline atât de mult timp încât tranzacțiile lipsă nu mai sunt disponibile în gcache-ul donatorului.\nCând se folosește #SST este declanșat automat de Galera când este necesar. Alegerea metodei SST (wsrep_sst_method) se face în faza de configurare. În producție, mariabackup este alegerea recomandată deoarece nu blochează nodul donator, evitând degradarea clusterului în timpul transferului.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/sst/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eSST\u003c/strong\u003e (State Snapshot Transfer) este mecanismul prin care un nod Galera care se alătură clusterului (sau care a fost offline prea mult timp) primește o copie completă a întregului set de date de la un nod donator.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eCând un nod se alătură clusterului și gap-ul de tranzacții lipsă depășește dimensiunea gcache-ului, clusterul inițiază un SST. Nodul donator creează un snapshot complet al bazei de date și îl transferă nodului receptor. Metodele disponibile sunt: \u003ccode\u003emariabackup\u003c/code\u003e (nu blochează donatorul), \u003ccode\u003ersync\u003c/code\u003e (rapid dar blochează donatorul pe citire), și \u003ccode\u003emysqldump\u003c/code\u003e (lent și blocant).\u003c/p\u003e","title":"SST"},{"content":"Un Stakeholder este orice persoană, grup sau organizație cu un interes direct sau indirect în rezultatul unui proiect. Include clienți, sponsori, utilizatori finali, echipe de dezvoltare, management și furnizori externi.\nCum funcționează #În project management, stakeholderii sunt identificați, clasificați după nivelul de influență și interes, și gestionați cu strategii de comunicare diferențiate. Un stakeholder cu influență și interes ridicate (precum CTO) necesită implicare activă; unul cu influență scăzută necesită doar actualizări periodice.\nDe ce contează #Majoritatea eșecurilor de proiect nu sunt tehnice — sunt relaționale. Stakeholderi nealiniați, așteptări negestionate și comunicare deficitară sunt cauzele cele mai frecvente ale întârzierilor, scope creep-ului și conflictelor. PM-ul eficient dedică mai mult timp gestionării stakeholderilor decât gestionării cronogramelor.\nCând se folosește #În fiecare fază a proiectului: în definirea cerințelor (cine decide ce se construiește), în planificare (cine aprobă resursele), în execuție (cine validează livrabilele) și la închidere (cine acceptă rezultatul). Ignorarea unui stakeholder cheie este cel mai rapid mod de a deraia un proiect.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/stakeholder/","section":"Glosar","summary":"\u003cp\u003eUn \u003cstrong\u003eStakeholder\u003c/strong\u003e este orice persoană, grup sau organizație cu un interes direct sau indirect în rezultatul unui proiect. Include clienți, sponsori, utilizatori finali, echipe de dezvoltare, management și furnizori externi.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eÎn project management, stakeholderii sunt identificați, clasificați după nivelul de influență și interes, și gestionați cu strategii de comunicare diferențiate. Un stakeholder cu influență și interes ridicate (precum CTO) necesită implicare activă; unul cu influență scăzută necesită doar actualizări periodice.\u003c/p\u003e","title":"Stakeholder"},{"content":"Star schema (schema stea) este cel mai utilizat model de date în data warehouse. Își primește numele de la forma sa: o tabelă centrală de fapte (fact table) conectată la mai multe tabele dimensionale care o înconjoară, ca razele unei stele.\nStructură # Fact table în centru: conține măsurile numerice și cheile externe către dimensiuni Dimension tables în jurul ei: conțin atributele descriptive (cine, ce, unde, când) cu structură denormalizată Dimensiunile într-un star schema sunt tipic denormalizate — toate atributele într-o singură tabelă plată, fără ierarhii normalizate. Acest lucru simplifică interogările și îmbunătățește performanța agregărilor.\nDe ce funcționează #Star schema este optimizat pentru interogări analitice:\nJoin-urile sunt simple: fact table-ul se conectează direct la fiecare dimensiune cu un singur join Agregările sunt rapide: optimizatorii bazelor de date recunosc pattern-ul și îl optimizează Este intuitiv pentru utilizatorii de business: structura reflectă modul în care aceștia gândesc despre date (vânzări pe produs, pe regiune, pe perioadă) Star schema vs Snowflake #Snowflake schema normalizează dimensiunile, împărțindu-le în sub-tabele. Economisește spațiu dar complică interogările cu join-uri suplimentare. În practică, star schema este preferat în majoritatea cazurilor deoarece simplitatea interogărilor compensează pe deplin costul spațiului extra din dimensiuni.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/star-schema/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eStar schema\u003c/strong\u003e (schema stea) este cel mai utilizat model de date în data warehouse. Își primește numele de la forma sa: o tabelă centrală de fapte (fact table) conectată la mai multe tabele dimensionale care o înconjoară, ca razele unei stele.\u003c/p\u003e\n\u003ch2 id=\"structură\" class=\"relative group\"\u003eStructură \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#structur%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eFact table\u003c/strong\u003e în centru: conține măsurile numerice și cheile externe către dimensiuni\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eDimension tables\u003c/strong\u003e în jurul ei: conțin atributele descriptive (cine, ce, unde, când) cu structură denormalizată\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eDimensiunile într-un star schema sunt tipic denormalizate — toate atributele într-o singură tabelă plată, fără ierarhii normalizate. Acest lucru simplifică interogările și îmbunătățește performanța agregărilor.\u003c/p\u003e","title":"Star schema"},{"content":"Swappiness (vm.swappiness) este un parametru al kernelului Linux care controlează cât de agresiv mută sistemul pagini de memorie din RAM în swap pe disc. Valoarea variază de la 0 (swap doar în cazuri extreme) la 100 (swap agresiv). Valoarea implicită este 60.\nCum funcționează #Cu valoarea implicită de 60, Linux începe să facă swap când presiunea pe memorie este încă relativ scăzută. Pentru un server de baze de date dedicat, acest lucru este inacceptabil: SGA trebuie să rămână în RAM, întotdeauna. Valoarea recomandată pentru Oracle este 1 — nu 0, care ar dezactiva complet swap-ul și ar putea declanșa OOM killer-ul.\nLa ce servește #Valoarea 1 îi spune kernelului: \u0026ldquo;Fă swap doar dacă nu mai există cu adevărat altă alternativă.\u0026rdquo; Acest lucru garantează că SGA și structurile critice ale Oracle rămân în memoria fizică, evitând citirile din swap (cu ordine de mărime mai lente decât RAM-ul) în timpul execuției interogărilor.\nDe ce contează #Cu swappiness la 60, un server cu 128 GB de RAM și o SGA de 64 GB poate începe să facă swap la părți din SGA chiar și cu 20-30 GB de RAM liber. Rezultatul sunt performanțe degradate imprevizibil, cu vârfuri de latență care par probleme aplicative dar sunt de fapt sistemul de operare care mută memorie pe disc.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/swappiness/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eSwappiness\u003c/strong\u003e (\u003ccode\u003evm.swappiness\u003c/code\u003e) este un parametru al kernelului Linux care controlează cât de agresiv mută sistemul pagini de memorie din RAM în swap pe disc. Valoarea variază de la 0 (swap doar în cazuri extreme) la 100 (swap agresiv). Valoarea implicită este 60.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eCu valoarea implicită de 60, Linux începe să facă swap când presiunea pe memorie este încă relativ scăzută. Pentru un server de baze de date dedicat, acest lucru este inacceptabil: SGA trebuie să rămână în RAM, întotdeauna. Valoarea recomandată pentru Oracle este 1 — nu 0, care ar dezactiva complet swap-ul și ar putea declanșa OOM killer-ul.\u003c/p\u003e","title":"Swappiness"},{"content":"Switchover-ul este o operatiune planificata in Oracle Data Guard care inverseaza rolurile intre baza de date primary si standby. Primary-ul devine standby, standby-ul devine primary. Nicio data nu se pierde, nicio tranzactie nu esueaza — este o tranzitie curata si controlata.\nSwitchover vs Failover #Distinctia este fundamentala:\nSwitchover Failover Cand Planificat (mentenanta, migrare) Urgenta (defectiune a primary-ului) Pierdere de date Zero Posibila (depinde de mod) Reversibilitate Da, cu un alt switchover Nu, standby-ul devine primary permanent Timp Minute (de obicei 1-3) Secunde pana la minute Cum se executa #Cu Data Guard Broker, switchover-ul este o singura comanda:\nDGMGRL\u0026gt; SWITCHOVER TO standby_db; Broker-ul gestioneaza automat secventa: oprirea redo transport, aplicarea ultimelor redo pe standby, inversarea rolurilor, repornirea redo transport in directia opusa.\nUtilizare in migrari #Switchover-ul este strategia preferata pentru migrarile Oracle cross-site. Se configureaza Data Guard intre mediul sursa si cel de destinatie, se lasa sa se sincronizeze, iar la momentul cutover-ului se executa switchover-ul. Daca ceva nu merge bine pe noua infrastructura, un al doilea switchover readuce totul la punctul de plecare — o plasa de siguranta pe care Data Pump nu o poate oferi.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/switchover/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eSwitchover-ul\u003c/strong\u003e este o operatiune planificata in Oracle Data Guard care inverseaza rolurile intre baza de date primary si standby. Primary-ul devine standby, standby-ul devine primary. Nicio data nu se pierde, nicio tranzactie nu esueaza — este o tranzitie curata si controlata.\u003c/p\u003e\n\u003ch2 id=\"switchover-vs-failover\" class=\"relative group\"\u003eSwitchover vs Failover \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#switchover-vs-failover\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eDistinctia este fundamentala:\u003c/p\u003e\n\u003ctable\u003e\n  \u003cthead\u003e\n      \u003ctr\u003e\n          \u003cth\u003e\u003c/th\u003e\n          \u003cth\u003eSwitchover\u003c/th\u003e\n          \u003cth\u003eFailover\u003c/th\u003e\n      \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e\u003cstrong\u003eCand\u003c/strong\u003e\u003c/td\u003e\n          \u003ctd\u003ePlanificat (mentenanta, migrare)\u003c/td\u003e\n          \u003ctd\u003eUrgenta (defectiune a primary-ului)\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e\u003cstrong\u003ePierdere de date\u003c/strong\u003e\u003c/td\u003e\n          \u003ctd\u003eZero\u003c/td\u003e\n          \u003ctd\u003ePosibila (depinde de mod)\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e\u003cstrong\u003eReversibilitate\u003c/strong\u003e\u003c/td\u003e\n          \u003ctd\u003eDa, cu un alt switchover\u003c/td\u003e\n          \u003ctd\u003eNu, standby-ul devine primary permanent\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e\u003cstrong\u003eTimp\u003c/strong\u003e\u003c/td\u003e\n          \u003ctd\u003eMinute (de obicei 1-3)\u003c/td\u003e\n          \u003ctd\u003eSecunde pana la minute\u003c/td\u003e\n      \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\u003ch2 id=\"cum-se-executa\" class=\"relative group\"\u003eCum se executa \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-se-executa\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eCu Data Guard Broker, switchover-ul este o singura comanda:\u003c/p\u003e","title":"Switchover"},{"content":"Un System Privilege în Oracle este o autorizare care permite executarea operațiunilor globale pe baza de date, independent de un obiect specific. Exemple tipice includ CREATE TABLE, CREATE SESSION, ALTER SYSTEM, CREATE USER și DROP ANY TABLE.\nCum funcționează #Privilegiile de sistem se acordă cu GRANT și se revocă cu REVOKE. Pot fi atribuite direct unui utilizator sau unui rol. Rolul predefinit DBA include peste 200 de privilegii de sistem, motiv pentru care atribuirea sa utilizatorilor aplicativi este o practică periculoasă.\nLa ce servește #Privilegiile de sistem definesc ce poate face un utilizator la nivel de bază de date: crea obiecte, gestiona utilizatori, modifica parametri de sistem. Sunt cel mai înalt nivel de autorizare în Oracle și trebuie gestionate cu extremă precauție, urmând principiul privilegiului minim.\nCe poate merge prost #Un privilegiu de sistem precum DROP ANY TABLE permite ștergerea oricărei tabele din orice schemă. Dacă este acordat din greșeală unui utilizator aplicativ, o singură comandă poate distruge date de producție. Distincția între privilegiile de sistem și cele de obiect este fundamentală pentru construirea unui model de securitate robust.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/system-privilege/","section":"Glosar","summary":"\u003cp\u003eUn \u003cstrong\u003eSystem Privilege\u003c/strong\u003e în Oracle este o autorizare care permite executarea operațiunilor globale pe baza de date, independent de un obiect specific. Exemple tipice includ \u003ccode\u003eCREATE TABLE\u003c/code\u003e, \u003ccode\u003eCREATE SESSION\u003c/code\u003e, \u003ccode\u003eALTER SYSTEM\u003c/code\u003e, \u003ccode\u003eCREATE USER\u003c/code\u003e și \u003ccode\u003eDROP ANY TABLE\u003c/code\u003e.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003ePrivilegiile de sistem se acordă cu \u003ccode\u003eGRANT\u003c/code\u003e și se revocă cu \u003ccode\u003eREVOKE\u003c/code\u003e. Pot fi atribuite direct unui utilizator sau unui rol. Rolul predefinit \u003ccode\u003eDBA\u003c/code\u003e include peste 200 de privilegii de sistem, motiv pentru care atribuirea sa utilizatorilor aplicativi este o practică periculoasă.\u003c/p\u003e","title":"System Privilege"},{"content":"systemd este sistemul de inițializare și managerul de servicii implicit pe distribuțiile Linux moderne (CentOS/RHEL 7+, Ubuntu 16.04+, Debian 8+). În contextul bazelor de date, este mecanismul care pornește, oprește și monitorizează instanțele MySQL sau MariaDB.\nCum funcționează #Fiecare serviciu este definit de un fișier unit (ex. mysqld.service) care specifică comanda de pornire, fișierul de configurare, dependențele și comportamentul în caz de crash. Într-un setup multi-instanță, se creează fișiere unit separate pentru fiecare instanță (ex. mysqld-app2.service, mysqld-reporting.service), fiecare cu propriul --defaults-file care indică spre un my.cnf diferit.\nLa ce folosește #systemd permite gestionarea instanțelor MySQL ca servicii independente: pornirea, oprirea, repornirea și monitorizarea lor separat. Comanda systemctl cat \u0026lt;serviciu\u0026gt; e esențială pentru a urma traseul de la numele serviciului la fișierul de configurare al instanței, și de acolo la port, socket și datadir.\nCând se folosește #systemd este activ automat pe orice server Linux modern. În munca de DBA, interacționezi cu el prin systemctl start/stop/status/restart \u0026lt;serviciu\u0026gt;. În mediile multi-instanță, systemctl list-units --type=service | grep mysql este prima comandă pentru a identifica câte instanțe sunt active pe un server.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/systemd/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003esystemd\u003c/strong\u003e este sistemul de inițializare și managerul de servicii implicit pe distribuțiile Linux moderne (CentOS/RHEL 7+, Ubuntu 16.04+, Debian 8+). În contextul bazelor de date, este mecanismul care pornește, oprește și monitorizează instanțele MySQL sau MariaDB.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eFiecare serviciu este definit de un fișier unit (ex. \u003ccode\u003emysqld.service\u003c/code\u003e) care specifică comanda de pornire, fișierul de configurare, dependențele și comportamentul în caz de crash. Într-un setup multi-instanță, se creează fișiere unit separate pentru fiecare instanță (ex. \u003ccode\u003emysqld-app2.service\u003c/code\u003e, \u003ccode\u003emysqld-reporting.service\u003c/code\u003e), fiecare cu propriul \u003ccode\u003e--defaults-file\u003c/code\u003e care indică spre un \u003ccode\u003emy.cnf\u003c/code\u003e diferit.\u003c/p\u003e","title":"systemd"},{"content":"Un Tablespace este unitatea logică de organizare a stocării în Oracle Database. Fiecare tablespace este compus din unul sau mai multe fișiere de date (datafile) fizice pe disc, iar fiecare obiect al bazei de date (tabelă, index, partiție) rezidă într-un tablespace.\nCum funcționează #Oracle separă gestionarea logică (tablespace) de cea fizică (datafile). Un DBA poate crea tablespace-uri dedicate pentru scopuri diferite: unul pentru datele active, unul pentru indexuri, unul pentru arhivă. Aceasta permite distribuirea sarcinii de I/O pe discuri diferite și aplicarea de politici de gestionare diferențiate (ex. read-only pentru datele istorice).\nLa ce folosește #În contextul partitioning-ului, tablespace-urile permit strategii avansate de gestionare a ciclului de viață: mutarea partițiilor vechi pe tablespace-uri de arhivă economice, punerea lor în read-only pentru reducerea sarcinii de backup și recuperarea spațiului activ fără ștergerea datelor. Un ALTER TABLE MOVE PARTITION ... TABLESPACE ts_archive este o operație DDL care durează mai puțin de o secundă.\nCând se folosește #Fiecare instalare Oracle folosește tablespace-uri. Designul tablespace-urilor devine critic când se gestionează tabele de sute de GB cu partitioning, deoarece o bună distribuție pe tablespace-uri separate activează backup-uri incrementale eficiente și gestionarea ciclului de viață al datelor.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/tablespace/","section":"Glosar","summary":"\u003cp\u003eUn \u003cstrong\u003eTablespace\u003c/strong\u003e este unitatea logică de organizare a stocării în Oracle Database. Fiecare tablespace este compus din unul sau mai multe fișiere de date (datafile) fizice pe disc, iar fiecare obiect al bazei de date (tabelă, index, partiție) rezidă într-un tablespace.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eOracle separă gestionarea logică (tablespace) de cea fizică (datafile). Un DBA poate crea tablespace-uri dedicate pentru scopuri diferite: unul pentru datele active, unul pentru indexuri, unul pentru arhivă. Aceasta permite distribuirea sarcinii de I/O pe discuri diferite și aplicarea de politici de gestionare diferențiate (ex. read-only pentru datele istorice).\u003c/p\u003e","title":"Tablespace"},{"content":"THP (Transparent Huge Pages) este o funcție a kernelului Linux care promovează automat paginile de memorie de la 4 KB la 2 MB în fundal, fără configurare explicită. Spre deosebire de Huge Pages statice, sunt gestionate de procesul kernel khugepaged.\nCum funcționează #Când sunt active (implicit always), kernelul încearcă să compacteze paginile normale în pagini mari în fundal. Procesul khugepaged lucrează continuu pentru a găsi și uni grupuri de pagini contigue, cauzând micro-înghețări imprevizibile în timpul operațiunilor de compactare.\nDe ce contează #Pentru Oracle sunt un dezastru. Oracle declară explicit în documentație: dezactivați THP. \u0026ldquo;Blocajele de câteva secunde\u0026rdquo; de care utilizatorii se plâng sunt adesea cauzate de khugepaged. Se dezactivează cu echo never \u0026gt; /sys/kernel/mm/transparent_hugepage/enabled și prin GRUB pentru persistență la repornire.\nCe poate merge prost #Confuzia între Huge Pages (bune pentru Oracle, configurate static) și THP (dăunătoare pentru Oracle, active implicit) este una dintre cele mai comune greșeli. Un DBA care vede \u0026ldquo;Huge Pages\u0026rdquo; în documentație și nu dezactivează THP face lucrurile mai rău în loc de mai bine.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/thp/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eTHP\u003c/strong\u003e (Transparent Huge Pages) este o funcție a kernelului Linux care promovează automat paginile de memorie de la 4 KB la 2 MB în fundal, fără configurare explicită. Spre deosebire de Huge Pages statice, sunt gestionate de procesul kernel \u003ccode\u003ekhugepaged\u003c/code\u003e.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eCând sunt active (implicit \u003ccode\u003ealways\u003c/code\u003e), kernelul încearcă să compacteze paginile normale în pagini mari în fundal. Procesul \u003ccode\u003ekhugepaged\u003c/code\u003e lucrează continuu pentru a găsi și uni grupuri de pagini contigue, cauzând micro-înghețări imprevizibile în timpul operațiunilor de compactare.\u003c/p\u003e","title":"THP"},{"content":"Timeboxing este o tehnică de gestionare a timpului care constă în atribuirea unui interval temporal fix și nenegociabil unei activități. Când timpul expiră, activitatea se încheie — indiferent dacă a fost finalizată sau nu.\nCum funcționează #Se definește durata maximă (15 minute pentru un standup, 1 oră pentru o ședință de design, 2 săptămâni pentru un sprint) și constrângerea se respectă. Timeboxul forțează persoanele să se concentreze pe esențial, evitând discuțiile interminabile și perfecționismul paralizant.\nLa ce servește #În project management, timeboxing-ul stă la baza standup meeting-ului (15 minute maxim), a sprint-ului Scrum (durată fixă) și a oricărei ședințe bine gestionate. Fără constrângere temporală, ședințele se extind până ocupă tot timpul disponibil — legea lui Parkinson aplicată sălilor de ședință.\nDe ce contează #Un standup de 15 minute costă echipa 440 de ore pe an. Unul de 45 de minute costă 1.320. Diferența — 880 de ore — echivalează cu aproape 5 luni-om. Timeboxing-ul nu este rigiditate: este respectul pentru timpul oamenilor.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/timeboxing/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eTimeboxing\u003c/strong\u003e este o tehnică de gestionare a timpului care constă în atribuirea unui interval temporal fix și nenegociabil unei activități. Când timpul expiră, activitatea se încheie — indiferent dacă a fost finalizată sau nu.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eSe definește durata maximă (15 minute pentru un standup, 1 oră pentru o ședință de design, 2 săptămâni pentru un sprint) și constrângerea se respectă. Timeboxul forțează persoanele să se concentreze pe esențial, evitând discuțiile interminabile și perfecționismul paralizant.\u003c/p\u003e","title":"Timeboxing"},{"content":"Transport lag este intarzierea intre momentul in care baza de date primary genereaza un redo log si momentul in care acel redo log este primit de baza de date standby intr-o configuratie Oracle Data Guard. Este unul dintre cei mai importanti indicatori pentru evaluarea sanatatii replicarii.\nCum se masoara #Transport lag-ul se monitorizeaza printr-un query pe view-ul V$DATAGUARD_STATS sau prin Data Guard Broker:\nDGMGRL\u0026gt; SHOW DATABASE 'standby_db' 'TransportLagTarget'; Valoarea este exprimata in format timp (ex. +00 00:00:03 = 3 secunde intarziere). Un transport lag de cateva secunde este normal in modul Maximum Performance; un lag care creste constant indica o problema de bandwidth sau de redo generate rate.\nDiferenta fata de Apply Lag # Metrica Ce masoara Transport Lag Intarzierea in transmiterea redo-ului de la primary la standby Apply Lag Intarzierea in aplicarea redo-ului pe standby dupa receptie Transport lag-ul depinde de retea (bandwidth, latenta); apply lag-ul depinde de resursele standby-ului (CPU, I/O). In migrarile cross-site, transport lag-ul este cel mai frecvent bottleneck.\nImpact in migrari #In timpul unei migrari cu Data Guard cross-site, transport lag-ul trebuie monitorizat atent in fazele de incarcare maxima (batch-uri nocturne, varfuri de activitate). Un redo generate rate care depaseste capacitatea VPN-ului produce un transport lag crescator. Inainte de cutover, transport lag-ul trebuie sa fie aproape de zero pentru a garanta ca switchover-ul are loc fara pierdere de date.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/transport-lag/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eTransport lag\u003c/strong\u003e este intarzierea intre momentul in care baza de date primary genereaza un redo log si momentul in care acel redo log este primit de baza de date standby intr-o configuratie Oracle Data Guard. Este unul dintre cei mai importanti indicatori pentru evaluarea sanatatii replicarii.\u003c/p\u003e\n\u003ch2 id=\"cum-se-masoara\" class=\"relative group\"\u003eCum se masoara \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-se-masoara\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eTransport lag-ul se monitorizeaza printr-un query pe view-ul \u003ccode\u003eV$DATAGUARD_STATS\u003c/code\u003e sau prin Data Guard Broker:\u003c/p\u003e","title":"Transport Lag"},{"content":"Unified Audit (Oracle Unified Auditing) este sistemul de audit centralizat introdus în Oracle Database 12c care înlocuiește mecanismele de audit tradiționale cu o singură infrastructură unificată. Toate evenimentele de audit converg în vizualizarea UNIFIED_AUDIT_TRAIL.\nCum funcționează #Unified Audit se bazează pe audit policies: reguli declarative care specifică ce acțiuni să fie monitorizate (DDL, DML, autentificări, operațiuni administrative). Politicile se creează cu CREATE AUDIT POLICY, se activează cu ALTER AUDIT POLICY ... ENABLE și pot fi aplicate utilizatorilor specifici sau global. Înregistrările de audit sunt scrise într-o coadă internă și apoi persistate în tabela de sistem.\nLa ce servește #Răspunde la întrebarea fundamentală a securității: „cine a făcut ce, când și de unde?\u0026quot; Permite urmărirea operațiunilor critice precum DROP TABLE, GRANT, REVOKE, accesul la date sensibile și tentativele de autentificare eșuate. Este esențial pentru conformitate (GDPR, SOX, PCI-DSS) și pentru investigațiile post-incident.\nDe ce contează #Vechiul audit tradițional al Oracle fragmenta jurnalele între fișiere de sistem, tabela SYS.AUD$ și FGA_LOG$, făcând analiza complexă. Unified Audit centralizează totul într-un singur punct, cu performanțe mai bune și gestionare simplificată. Într-un mediu fără audit configurat, un incident de securitate devine imposibil de reconstruit.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/unified-audit/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eUnified Audit\u003c/strong\u003e (Oracle Unified Auditing) este sistemul de audit centralizat introdus în Oracle Database 12c care înlocuiește mecanismele de audit tradiționale cu o singură infrastructură unificată. Toate evenimentele de audit converg în vizualizarea \u003ccode\u003eUNIFIED_AUDIT_TRAIL\u003c/code\u003e.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eUnified Audit se bazează pe \u003cstrong\u003eaudit policies\u003c/strong\u003e: reguli declarative care specifică ce acțiuni să fie monitorizate (DDL, DML, autentificări, operațiuni administrative). Politicile se creează cu \u003ccode\u003eCREATE AUDIT POLICY\u003c/code\u003e, se activează cu \u003ccode\u003eALTER AUDIT POLICY ... ENABLE\u003c/code\u003e și pot fi aplicate utilizatorilor specifici sau global. Înregistrările de audit sunt scrise într-o coadă internă și apoi persistate în tabela de sistem.\u003c/p\u003e","title":"Unified Audit"},{"content":"Un Unix Socket (sau socket de domeniu Unix) este un endpoint de comunicare care permite la două procese de pe același sistem de operare să facă schimb de date fără a trece prin stiva de rețea TCP/IP. În MySQL, este metoda de conectare implicită când te conectezi la localhost.\nCum funcționează #Când un client MySQL se conectează specificând -h localhost, clientul nu folosește TCP. Folosește fișierul socket Unix (de obicei /var/run/mysqld/mysqld.sock) pentru a comunica direct cu procesul serverului MySQL. Această comunicare se desfășoară integral în kernel, fără overhead de rețea, și e mai rapidă decât o conexiune TCP chiar și pe același host.\nLa ce folosește #În mediile multi-instanță, fiecare instanță MySQL are propriul fișier socket (ex. mysqld.sock, mysqld-app2.sock). Specificarea socket-ului corect cu --socket=/path/to/socket e singura metodă fiabilă de a te conecta la instanța dorită. Fără a specifica socket-ul, clientul îl folosește pe cel implicit — care aproape întotdeauna indică spre instanța primară.\nCând se folosește #Socket-urile Unix se folosesc pentru toate conexiunile locale la MySQL. În mediile cu instanțe multiple, e esențial să specifici explicit socket-ul pentru fiecare conexiune. Pentru conexiuni de la distanță (de pe alt host), se folosește TCP cu -h \u0026lt;ip\u0026gt; -P \u0026lt;port\u0026gt;.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/unix-socket/","section":"Glosar","summary":"\u003cp\u003eUn \u003cstrong\u003eUnix Socket\u003c/strong\u003e (sau socket de domeniu Unix) este un endpoint de comunicare care permite la două procese de pe același sistem de operare să facă schimb de date fără a trece prin stiva de rețea TCP/IP. În MySQL, este metoda de conectare implicită când te conectezi la \u003ccode\u003elocalhost\u003c/code\u003e.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eCând un client MySQL se conectează specificând \u003ccode\u003e-h localhost\u003c/code\u003e, clientul nu folosește TCP. Folosește fișierul socket Unix (de obicei \u003ccode\u003e/var/run/mysqld/mysqld.sock\u003c/code\u003e) pentru a comunica direct cu procesul serverului MySQL. Această comunicare se desfășoară integral în kernel, fără overhead de rețea, și e mai rapidă decât o conexiune TCP chiar și pe același host.\u003c/p\u003e","title":"Unix Socket"},{"content":"VACUUM este comanda PostgreSQL care recuperează spațiul ocupat de dead tuples (rânduri moarte) și îl face disponibil pentru inserări noi. Nu returnează spațiu sistemului de operare, nu reorganizează tabela și nu compactează nimic — marchează paginile ca rescriptibile.\nCum funcționează #VACUUM tabela scanează tabela, identifică dead tuple-urile care nu mai sunt vizibile niciunei tranzacții și marchează spațiul lor ca reutilizabil. Este o operațiune ușoară care nu blochează scrierile și poate rula în paralel cu interogările normale. VACUUM FULL în schimb rescrie fizic întreaga tabelă cu lock exclusiv — de folosit foarte rar și doar în urgențe.\nLa ce servește #Fără VACUUM, tabelele cu trafic intens de UPDATE și DELETE acumulează dead tuples care ocupă spațiu pe disc și încetinesc scanările secvențiale. VACUUM este mecanismul esențial de curățare care echilibrează costul modelului MVCC al PostgreSQL.\nDe ce contează #Autovacuum rulează VACUUM automat, dar cu valorile implicite ale PostgreSQL se poate activa prea rar pe tabelele cu trafic intens. Pe o tabelă cu 10 milioane de rânduri, valoarea implicită așteaptă 2 milioane de dead tuples înainte de a acționa — suficient pentru a degrada vizibil performanțele.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/vacuum/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eVACUUM\u003c/strong\u003e este comanda PostgreSQL care recuperează spațiul ocupat de dead tuples (rânduri moarte) și îl face disponibil pentru inserări noi. Nu returnează spațiu sistemului de operare, nu reorganizează tabela și nu compactează nimic — marchează paginile ca rescriptibile.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003e\u003ccode\u003eVACUUM tabela\u003c/code\u003e scanează tabela, identifică dead tuple-urile care nu mai sunt vizibile niciunei tranzacții și marchează spațiul lor ca reutilizabil. Este o operațiune ușoară care nu blochează scrierile și poate rula în paralel cu interogările normale. \u003ccode\u003eVACUUM FULL\u003c/code\u003e în schimb rescrie fizic întreaga tabelă cu lock exclusiv — de folosit foarte rar și doar în urgențe.\u003c/p\u003e","title":"VACUUM"},{"content":"Vendor Lock-in este situația în care o companie devine dependentă de un furnizor extern până la punctul în care schimbarea devine extrem de costisitoare sau complex din punct de vedere tehnic. În contextul IT, apare când codul, arhitectura sau cunoașterea sistemului sunt în mâinile furnizorului, nu ale clientului.\nCum funcționează #Lock-in-ul se instaurează gradual: furnizorul scrie codul cu convențiile proprii, folosește tehnologii proprietare sau nedocumentate, iar echipa internă nu este implicată în dezvoltare. Când furnizorul pleacă — din proprie voință sau prin concediere — ia cu el know-how-ul. Clientul rămâne cu un software pe care nu-l înțelege, nu știe să-l întrețină și nu-l poate evolua fără a reangaja același furnizor sau a o lua de la zero.\nLa ce folosește #Înțelegerea vendor lock-in-ului este esențială pentru luarea deciziilor strategice privind outsourcing-ul și dezvoltarea software. Fiecare proiect ar trebui să prevadă măsuri de mitigare: documentație internă, code review, implicarea echipei interne, proprietatea codului sursă.\nCând se folosește #Termenul descrie un risc de evitat. Contramăsurile principale sunt: menținerea know-how-ului critic intern, preferarea tehnologiilor deschise și standard, asigurarea proprietății intelectuale a codului și evaluarea întotdeauna a opțiunii \u0026ldquo;buy vs build\u0026rdquo; înainte de a porni proiecte custom de mare amploare.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/vendor-lock-in/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eVendor Lock-in\u003c/strong\u003e este situația în care o companie devine dependentă de un furnizor extern până la punctul în care schimbarea devine extrem de costisitoare sau complex din punct de vedere tehnic. În contextul IT, apare când codul, arhitectura sau cunoașterea sistemului sunt în mâinile furnizorului, nu ale clientului.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eLock-in-ul se instaurează gradual: furnizorul scrie codul cu convențiile proprii, folosește tehnologii proprietare sau nedocumentate, iar echipa internă nu este implicată în dezvoltare. Când furnizorul pleacă — din proprie voință sau prin concediere — ia cu el know-how-ul. Clientul rămâne cu un software pe care nu-l înțelege, nu știe să-l întrețină și nu-l poate evolua fără a reangaja același furnizor sau a o lua de la zero.\u003c/p\u003e","title":"Vendor Lock-in"},{"content":"Version Control (controlul versiunilor) este un sistem care înregistrează fiecare modificare a fișierelor unui proiect, menținând un istoric complet al cine a schimbat ce, când și de ce. Git este cel mai utilizat sistem de version control din lume.\nCum funcționează #Fiecare modificare se înregistrează ca \u0026ldquo;commit\u0026rdquo; cu un mesaj descriptiv, un autor și un timestamp. Sistemul menține întreaga istorie a proiectului: poți reveni la orice versiune anterioară, compara versiuni diferite și înțelege evoluția codului în timp. Cu Git, fiecare dezvoltator are o copie completă a istoriei pe propriul computer.\nLa ce folosește #Fără version control, codul trăiește în foldere partajate unde suprascrierile accidentale sunt norma și nimeni nu știe care e versiunea \u0026ldquo;bună\u0026rdquo;. Cu version control, fiecare modificare e urmărită și reversibilă, conflictele între dezvoltatori sunt gestionate structurat, iar istoria proiectului este o resursă, nu un mister.\nCând se folosește #Întotdeauna, pe orice proiect software cu mai mult de un fișier sau mai mult de un dezvoltator. Absența version control-ului este primul semnal al unui proiect scăpat de sub control. GitHub, GitLab și Bitbucket sunt platforme care adaugă colaborare (Pull Request-uri, Issue tracker) peste Git.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/version-control/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eVersion Control\u003c/strong\u003e (controlul versiunilor) este un sistem care înregistrează fiecare modificare a fișierelor unui proiect, menținând un istoric complet al cine a schimbat ce, când și de ce. Git este cel mai utilizat sistem de version control din lume.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eFiecare modificare se înregistrează ca \u0026ldquo;commit\u0026rdquo; cu un mesaj descriptiv, un autor și un timestamp. Sistemul menține întreaga istorie a proiectului: poți reveni la orice versiune anterioară, compara versiuni diferite și înțelege evoluția codului în timp. Cu Git, fiecare dezvoltator are o copie completă a istoriei pe propriul computer.\u003c/p\u003e","title":"Version Control"},{"content":"Wait Event este un indicator de diagnostic al Oracle Database care identifica motivul pentru care o sesiune asteapta in loc sa lucreze activ. De fiecare data cand un proces nu poate continua — pentru ca asteapta un bloc de pe disc, un lock, un raspuns din retea sau un tur de CPU — Oracle inregistreaza un wait event specific.\nCele mai comune # Wait Event Semnificatie db file sequential read Citire un singur bloc — tipica accesului prin index db file scattered read Citire multi-bloc — tipica full table scan-urilor log file sync Asteptarea commit-ului in redo log enq: TX - row lock contention Conflict de lock pe rand direct path read Citire directa (ocolind buffer cache-ul) La ce servesc #Wait event-urile sunt baza metodologiei de diagnostic Oracle. Analizand ce evenimente domina DB time-ul (prin AWR sau ASH) se identifica imediat natura problemei: I/O, contention, CPU sau retea.\nUnde se gasesc # In timp real: V$SESSION_WAIT, V$ACTIVE_SESSION_HISTORY Istorice: rapoarte AWR (sectiunea Top Timed Foreground Events), DBA_HIST_ACTIVE_SESS_HISTORY Regula DBA-ului: nu ghici ce incetineste baza de date — uita-te la wait event-uri.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/wait-event/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eWait Event\u003c/strong\u003e este un indicator de diagnostic al Oracle Database care identifica motivul pentru care o sesiune asteapta in loc sa lucreze activ. De fiecare data cand un proces nu poate continua — pentru ca asteapta un bloc de pe disc, un lock, un raspuns din retea sau un tur de CPU — Oracle inregistreaza un wait event specific.\u003c/p\u003e\n\u003ch2 id=\"cele-mai-comune\" class=\"relative group\"\u003eCele mai comune \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cele-mai-comune\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003ctable\u003e\n  \u003cthead\u003e\n      \u003ctr\u003e\n          \u003cth\u003eWait Event\u003c/th\u003e\n          \u003cth\u003eSemnificatie\u003c/th\u003e\n      \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e\u003ccode\u003edb file sequential read\u003c/code\u003e\u003c/td\u003e\n          \u003ctd\u003eCitire un singur bloc — tipica accesului prin index\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e\u003ccode\u003edb file scattered read\u003c/code\u003e\u003c/td\u003e\n          \u003ctd\u003eCitire multi-bloc — tipica full table scan-urilor\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e\u003ccode\u003elog file sync\u003c/code\u003e\u003c/td\u003e\n          \u003ctd\u003eAsteptarea commit-ului in redo log\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e\u003ccode\u003eenq: TX - row lock contention\u003c/code\u003e\u003c/td\u003e\n          \u003ctd\u003eConflict de lock pe rand\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e\u003ccode\u003edirect path read\u003c/code\u003e\u003c/td\u003e\n          \u003ctd\u003eCitire directa (ocolind buffer cache-ul)\u003c/td\u003e\n      \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\u003ch2 id=\"la-ce-servesc\" class=\"relative group\"\u003eLa ce servesc \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#la-ce-servesc\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eWait event-urile sunt baza metodologiei de diagnostic Oracle. Analizand ce evenimente domina DB time-ul (prin AWR sau ASH) se identifica imediat natura problemei: I/O, contention, CPU sau retea.\u003c/p\u003e","title":"Wait Event"},{"content":"WSREP (Write Set Replication) este API-ul și protocolul pe care Galera Cluster îl folosește pentru replicarea sincronă multi-master. Fiecare tranzacție este capturată ca \u0026ldquo;write set\u0026rdquo; (set de modificări la nivel de rând) și replicată pe toate nodurile clusterului înainte de commit.\nCum funcționează #Când un nod execută o tranzacție, WSREP o interceptează la momentul commit-ului, o împachetează ca write set și o trimite tuturor nodurilor clusterului prin protocolul de comunicare de grup. Fiecare nod execută un proces de certification: verifică dacă tranzacția nu intră în conflict cu alte tranzacții concurente. Dacă certification-ul are succes, toate nodurile aplică tranzacția. Dacă eșuează, tranzacția este anulată pe nodul care a inițiat-o.\nLa ce folosește #WSREP garantează că toate nodurile clusterului au aceleași date în orice moment (replicare sincronă). Spre deosebire de replicarea asincronă tradițională MySQL, nu există întârziere între master și slave: când o tranzacție este confirmată pe un nod, este deja prezentă pe toate celelalte.\nCând se folosește #WSREP se activează cu parametrul wsrep_on=ON în configurarea MariaDB/Percona XtraDB Cluster. Variabilele de stare care încep cu wsrep_ (precum wsrep_cluster_size, wsrep_cluster_status, wsrep_flow_control_paused) sunt indicatorii principali pentru monitorizarea sănătății clusterului.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/wsrep/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eWSREP\u003c/strong\u003e (Write Set Replication) este API-ul și protocolul pe care Galera Cluster îl folosește pentru replicarea sincronă multi-master. Fiecare tranzacție este capturată ca \u0026ldquo;write set\u0026rdquo; (set de modificări la nivel de rând) și replicată pe toate nodurile clusterului înainte de commit.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eCând un nod execută o tranzacție, WSREP o interceptează la momentul commit-ului, o împachetează ca write set și o trimite tuturor nodurilor clusterului prin protocolul de comunicare de grup. Fiecare nod execută un proces de \u003cstrong\u003ecertification\u003c/strong\u003e: verifică dacă tranzacția nu intră în conflict cu alte tranzacții concurente. Dacă certification-ul are succes, toate nodurile aplică tranzacția. Dacă eșuează, tranzacția este anulată pe nodul care a inițiat-o.\u003c/p\u003e","title":"WSREP"},{"content":"Yes-And (Da-Și) este o tehnică de comunicare originară din teatrul de improvizație, aplicată în project management pentru a transforma discuțiile conflictuale în conversații constructive. Principiul este simplu: în loc să negi propunerea interlocutorului cu \u0026ldquo;Nu, dar\u0026hellip;\u0026rdquo;, o accepți cu \u0026ldquo;Da, și\u0026hellip;\u0026rdquo; adăugând propria contribuție.\nCum funcționează #Când cineva propune o idee, răspunsul \u0026ldquo;Nu\u0026rdquo; declanșează o reacție defensivă și blochează conversația. Răspunsul \u0026ldquo;Da, și\u0026hellip;\u0026rdquo; recunoaște validitatea propunerii și o extinde, menținând dialogul deschis. Nu înseamnă să fii de acord cu totul — înseamnă să construiești pe propunerea celuilalt înainte de a o redirecționa.\nCând se folosește #În ședințele de proiect unde două poziții se ciocnesc, în code review-uri unde feedback-ul riscă să sune ca o critică, în negocierile cu stakeholderii unde un \u0026ldquo;nu\u0026rdquo; sec arde relațiile. Este deosebit de eficientă când opinii diverse trebuie să convergă spre o decizie comună.\nCând nu funcționează #Nu se aplică la probleme de securitate, încălcări de proces sau deadline-uri nenegociabile. Dacă cineva propune eliminarea autentificării de pe baza de date de producție, răspunsul este \u0026ldquo;Nu\u0026rdquo;, punct. Yes-And funcționează cu persoane de bună credință; nu funcționează cu cei care vor doar să aibă dreptate.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/yes-and/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eYes-And\u003c/strong\u003e (Da-Și) este o tehnică de comunicare originară din teatrul de improvizație, aplicată în project management pentru a transforma discuțiile conflictuale în conversații constructive. Principiul este simplu: în loc să negi propunerea interlocutorului cu \u0026ldquo;Nu, dar\u0026hellip;\u0026rdquo;, o accepți cu \u0026ldquo;Da, și\u0026hellip;\u0026rdquo; adăugând propria contribuție.\u003c/p\u003e\n\u003ch2 id=\"cum-funcționează\" class=\"relative group\"\u003eCum funcționează \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-func%c8%9bioneaz%c4%83\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eCând cineva propune o idee, răspunsul \u0026ldquo;Nu\u0026rdquo; declanșează o reacție defensivă și blochează conversația. Răspunsul \u0026ldquo;Da, și\u0026hellip;\u0026rdquo; recunoaște validitatea propunerii și o extinde, menținând dialogul deschis. Nu înseamnă să fii de acord cu totul — înseamnă să construiești pe propunerea celuilalt înainte de a o redirecționa.\u003c/p\u003e","title":"Yes-And"},{"content":"ZDM (Zero Downtime Migration) este instrumentul pe care Oracle il pune la dispozitie pentru automatizarea migrarilor bazelor de date Oracle catre OCI (Oracle Cloud Infrastructure) sau catre baze de date on-premises de versiune superioara. Numele este putin optimist — downtime-ul nu este zero, dar este redus la minim.\nCum functioneaza #ZDM este in esenta un orchestrator care combina tehnologii Oracle existente intr-un flux automatizat unic. Suporta doua moduri:\nMigrare fizica (bazata pe Data Guard): creeaza un standby al bazei de date sursa pe destinatie, il sincronizeaza prin redo transport, apoi executa un switchover. Downtime de ordinul minutelor. Migrare logica (bazata pe Data Pump): executa export si import logic cu sincronizare incrementala prin GoldenGate sau Data Pump. Mai flexibil dar mai lent. Cand sa il folosesti #ZDM este indicat pentru migrari standard unde infrastructura sursa si destinatie sunt configurate conventional. Avantajul este automatizarea: reduce posibilitatea erorii umane in pasii repetitivi.\nCand sa nu il folosesti #Pentru configuratii complexe — RAC cu DB link-uri cross-engine, dependente externe non-standard, proceduri PL/SQL cu apeluri HTTP — stratul de automatizare al ZDM poate deveni un obstacol. In aceste cazuri, configurarea manuala a Data Guard ofera mai mult control asupra detaliilor si secventei operatiilor.\nCerinte #ZDM necesita un host dedicat (\u0026ldquo;ZDM service host\u0026rdquo;) cu acces SSH atat la baza de date sursa cat si la destinatie. Sursa trebuie sa fie Oracle 11.2.0.4 sau superior, iar destinatia poate fi pe OCI sau on-premises.\n","date":"1 ianuarie 0001","permalink":"https://ivanluminaria.com/ro/glossary/zdm/","section":"Glosar","summary":"\u003cp\u003e\u003cstrong\u003eZDM\u003c/strong\u003e (Zero Downtime Migration) este instrumentul pe care Oracle il pune la dispozitie pentru automatizarea migrarilor bazelor de date Oracle catre OCI (Oracle Cloud Infrastructure) sau catre baze de date on-premises de versiune superioara. Numele este putin optimist — downtime-ul nu este zero, dar este redus la minim.\u003c/p\u003e\n\u003ch2 id=\"cum-functioneaza\" class=\"relative group\"\u003eCum functioneaza \u003cspan class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100\"\u003e\u003ca class=\"group-hover:text-primary-300 dark:group-hover:text-neutral-700\" style=\"text-decoration-line: none !important;\" href=\"#cum-functioneaza\" aria-label=\"Link\"\u003e#\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp\u003eZDM este in esenta un orchestrator care combina tehnologii Oracle existente intr-un flux automatizat unic. Suporta doua moduri:\u003c/p\u003e","title":"ZDM"}]