Studiul Bazelor de Date Distribuite Implementate In Mongodb

Studiul bazelor de date distribuite implementate in MongoDB

Proiect de diplomă

Cuprins

Introducere

Capitolul 1. Baze de date

1.1. Baze de date MySQL

1.1.1. Introducere

1.1.2. Tipuri de date

1.2.Baze de date NoSQL

1.2.1. MongoDB

1.2.1.1.Introducere

1.2.1.2. Caracteristici & Concepte

1.2.1.3. Arhitectura bazei de date

1.2.1.3.1. Documente

1.2.1.3.2.Colecții de documente

1.2.1.3.3. Subcolecții

1.2.1.3.4. Baza de date

1.2.1.4. Tipuri de date

1.2.1.5. Operații de bază CRUD

Capitolul 2. Baze de date distribuite

2.1. Replicarea

2.1.1. Introducere

2.2. Replicarea în MySQL

2.2.1. Compatibilitatea replicării în MySQL

2.2.2. Utilizarea replicării

2.2.3. Funcționarea replicării

2.2.4. Tipuri de replicare în MySQL

2.2.4.1. Replicarea bazată pe declarații

2.2.4.2. Replicarea bazată pe rânduri

2.3. Replicarea în MongoDB

2.3.1. Funcționarea

2.3.2. Replicarea Master-Slave

2.3.3. Setul de replicare

2.3.4. Sincronizarea

Capitolul 3. Topologii de replicare a bazelor de date MySQL și MongoDB

3.1. O stație master și mai multe stații slave

3.2. Două Stații Master-Master în modurile activ-activ

3.3. Două stații master în modurile active-pasiv

3.4. Stații master-master cu mai multe stații slave

3.5. Topologia de tip “inel”

3.6. Topologie ce conține o stație master, o stație distribuită de master și mai multe stații slave

3.7. Topologia de tip arbore sau piramidă

Capitolul 4. Configurarea bazelor de date și a replicării

4.1. Configurarea bazei de date

4.2. Configurarea replicării de tip Master-Slave în MongoDB

4.3. Configurarea replicării de tip Master-Slave în MySQL

Capitolul 5. Proiectarea Aplicației

5.1. Scopul Aplicației

5.2. Tehnologii utilizate

5.3. Descrierea Aplicației

5.4. Teste de performanță asupra bazei de date

Concluzii

Bibliografie

Anexe

Lista Acronimelor

BLOB- Binarry Large OBject

CSS- Cascading Style Sheet

DB- Database

FK- Foreign Key

GRIDFS- Protocol pentru stocarea fișierelor mari

HTML – HyperText Markup Language

JS- JavaScript

JSON- JavaScript Object Notation

MAP- Abstract data structure

MySQL- Open source relational database management system

NoSQL- Not Only SQL

PDF – Portable Document Format

PHP – PHP: Hypertext Preprocessor (Limbaj preprocesare hypertext)

PK- Primary Key

RDBMS- Relational DataBase Management System

SET- Abstract data structure

SGBD – Sistem de Gestiune a Bazelor de Date

SQL – Structured Query Language (Limbaj de interogare structurat)

VARCHAR- Variable Length Character String

Introducere

Sistemele de gestiune a bazelor de date au fost dezvoltate pentru a permite persoanelor fizice și organizațiilor să gestioneze datele necesare nevoilor lor. O bază de date bine concepută poate stoca, actualize și accesa ușor datele. Spre exemplificare, o companie de transport marfă poate utiliza o bază de date pentru a înregistra informații legate de fiecare transport, precum expeditorul și destinatarul, originea și destinația, timpul de livrare, locația actuală, prețul și multe alte informații necesare. Anumite date trebuiesc actualizate, în funcție de situația curentă al transportului. Starea curentă poate fi citită în orice momentdin baza de date, iar datele privitoare la toate transporturile efectuate pot fi rezumate în rapoarte.

Web-ul a adus o contribuție importantă în utilizarea bazelor de date, prin dezvoltarea de aplicații ce nu necesită instalarea vreunui soft pe computerul fiecărui utilizator. Adăugarea unei baze de date pe o aplicație web permite colectarea și utilizarea informațiilor în mod automat. De exemplu, un client poate accesa un magazin on-line, poate vedea ce există în stoc, poate plasa comenzi, poate prezenta informațiile de plată și poate urmări comanda până când bunurile sunt livrate. [1]

Capitolul 1. Baze de date

Încă de la începuturi, domeniul bazelor de date a fost printre cele mai cercetate și dezvoltate în informatică. O bază de date reprezintă un depozit de date, conceput pentru a stoca date. Pentru a corespunde diferitelor cerințe ale industriei au fost dezvoltate mai multe tipuri de baze de date. O bază de date poate fi specializată pentru stocarea diferitelor tipuri de informații: fișiere binare, documente, imagini, clipuri video, date relaționale, date tranzactionale, date analitice și multe altele.

Datele pot fi stocate în diferite forme, cele stocate sub formă de tabel fiind baze de date relaționale. În ultima vreme, au început foarte mult să se dezvolte bazele de date non relaționale, deoarece permit programatorilor stocarea datelor care nu au o schemă predefinită.

Un sistem de gestiune al bazelor de date (SGBD) reprezintă un set de instrumente software care se ocupă cu managementul bazelor de date. Acesta controlează accesul la baza de date, organizarea, stocarea, administrarea și menținerea datelor dintr-o bază de date.

Dezvoltarea Sistemelor de gestiune al bazelor de date a dus la apariția instrumentelor software de gestiune al bazelor de date relaționale (RDBMS). Sistemele de gestiune a bazelor de date relaționale au o importanță semnificativă în dezvoltarea aplicațiilor din diverse industrii, precum cel bancar, transport, sănătate și așa mai departe. [2]

Exemple de baze de date relaționale: MySQL, Oracle, PostreSQL, IBM DB2

Exemple de baze de date non relaționale: BaseX, Clusterpoint, MongoDB, Oracle NoSQL Batabase,OrientDB.

1.1. Baze de date MySQL

1.1.1. Introducere

MySQL este cea mai populară bază de date open source, dezvoltată de compania suedeză MySQL AB (http://www.mysql.com). MySQL este o bază de date de tip relațională și permite utilizatorilor să reprezinte relații complexe între mai multe baze de date, implementarea foarte eficientă reprezentând una dintre caracteristicile cele mai importante. Această bază de date a devenit celebră datorită următorilor factori:

-Dimensiune și viteză: MySQL nu necesită cerințe hardware foarte mari și utilizează resurse puține în timpul funcționării. Viteza cu care se pot accesa informațiilea făcut această bază de date una dintre favoritele dezvoltatorilor de aplicații web. MySQL AB a continuat dezvoltarea bazei de date prin adăugarea de caracteristici noi pentru aplicații de dimensiuni mari, dar arhitectura bazată pe module permite ignorarea acestor caracteristici avansate și menține viteza pentru care MySQl a devenit celebră.

-Ușor de instalat: MySQL poate fi instalat și configurat într-un mod rapid și fără multe dificultăți. Unele distribuții precum Linux includ MySQL și astfel instalarea se face aproape automat, partea de configurare fiind de asemenea destul de simplă.

-Standard mediu: MySQL folosește un standard ce permite unui utilizator să realizeze trecerea către un alt tip de bază de date fără prea multe probleme. Există mai multe standarde în contextul bazelor de date relaționale, permițând trecerea de la MySQL la o altă bază de date cu o ușurință mult mai mare față de alte baze de date.

-Comunitatea dezvoltatorilor: Există foarte multe comunități de dezvoltatori care pun la dispoziție orice noutate legată de MySQL.Orice programator poate accesa codul programului și poate găsi soluții pentru propria aplicație. De asemenea, pentru a utiliza MySQL pentru propriile date și nevoi nu este necesară taxă de licență, excepție făcând cazurile în care se dorește realizarea unui produs în jurul ei.

-Interfață simplă: MySQL se poate utiliza simplu ca parte al unui sistem software. Spre exemplificare: se pot scrie programe care să interacționeze direct cu o bază de date MySQL. Cele mai cunoscute limbaje de programare au biblioteci ce permit funcționarea împreună cu MySQL (C, PHP, Perl, Python, Ruby, și Microsoft. NET). [3]

1.1.2. Tipuri de date

-Numere întregi de tip INT: TINYINT pe 8 biți, SMALLINT pe 16 biți, MEDIUMINT pe 24biți, INT pe 32 biți, sau BIGINT pe 64 biți. Tipurile întregi se pot utiliza opțional împreună cu atributul UNSIGNED, ce nu permite valori negative.

-Numere reale cu parte fracționară de tip DOUBLE, DECIMAL sau FLOAT.

-Șiruri de caractere de tip VARCHAR sau CHAR.

-Tipuri de date de tip BLOB sau TEXT: sunt proiectate pentru a stoca volume mari de date, precum caractere sau șiruri de caractere binare. Acestea pot fi de forma TINYTEXT, SMALLTEXT, TEXT, MEDIUMTEXT,LONGTEXT iar tipurile binare pot fi de forma TINYBLOB, SMALLBLOB, BLOB, MEDIUMBLOB și LONGBLOB.

-Date de tip enum: pot stoca până la 65.535 valori distincte

-DATETIME: stochează data de forma: YYYYMMDDHHMMSS

-TIMESTAMP utilizează doar 4 octeți și stochează numărul de secunde scurse de la miezul nopții (Greenwich Mean Time)

-BIT – este utilizat pentru a stoca valorile de adevăr (TRUE/ FALSE) într-o coloană. Lungimea maximă a unei coloane BIT este de 64 de biți. Exemplu: BIT(1) definește un câmp ce conține un singur bit, BIT(2) conține doi biți și așa mai departe.

-SET – se folosește pentru combinarea într-un singur set a mai multor coloane ce conțin valori de adevăr (TRUE/ FALSE).

1.2.Baze de date NoSQL

1.2.1. MongoDB

1.2.1.1.Introducere

MongoDB a fost dezvoltat pentru prima dată de către compania 10gen în anul 2007, iar în anul 2009 a fost transformat într-un produs open source. Face parte din familia sistemelor de baze de date NoSQL, fiind o bază de date NoSQL orientată pe documente de tip Open-source.

MongoDB este un depozit de date puternic, flexibil și scalabil, ce combină capacitatea de a scala cu multe dintre caracteristicile cele mai utile ale bazelor de date relaționale, cum ar fi indicii secundari, interogările și sortarea. MongoDB are un model de date prietenos pentru dezvoltator, opțiuni de configurare rapidă și ușoară, ce încearcă să ajute programatorul, permițându-i să programeze fără îngrijorare cu privire la stocarea datelor.

MongoDB este o bază de date orientată pe documente, nu una relațională. Motivul principal pentru care s-a realizat trecerea de la modelul relațional a fost una esențială: scalarea rapidă și ușoară.

Ideea de bază este de a înlocui conceptul de "rând dintr-un tabel", cu un model mai flexibil, "Document", care să permită inserarea de documente încorporate și matrici, documentele orientate permițând realizarea relațiilor ierarhice complexe cu o singură înregistrare.

MongoDB este în același timp o bază de date de tip „schema-free”: cheile unui document nu sunt predefinite sau fixe în orice cale. Fără a schimba baza de date, migrațiile masive de date sunt de obicei inutile. Cheile noi sau cele care lipsesc se pot rezolva la nivel de aplicație, în loc de a impune tuturor datelor să aibe aceeași formă. Acest lucru oferă dezvoltatorilor avantaje de flexibilitate în modul în care lucrează cu aceste modele de date.

Dimensiunea datelor ce sunt stocate într-o bază de date se află într-o creștere continuă. Un terabyte de date este acum un lucru obișnuit.

Deoarece cantitatea de date necesară de stocare crește, dezvoltatorii se confruntă cu problema: cum ar trebui să scaleze bazele lor de date? Scalarea unei baze de date se reduce la alegerea dintre extindere (obținerea unei mașini mai mari) sau scalare (date partiționare peste mai multe mașini). Mașinile mari sunt de multe ori foarte scumpe, și în cele din urmă o limită fizică este atinsă în cazul în care o mașină mai puternică nu poate fi achiziționată de la orice preț. Alternativ, pentru a adăuga spațiu de stocare sau de a crește performanța, se poate cumpăra un alt server de stocare și se poate adăuga la cluster.

MongoDB a fost proiectat de la inceput pentru baze de date de dimensiuni foarte mari. Modelul permite împărțirea în mod automat a datelor pe mai multe servere. Volumul de date se poate echilibra și încărca pe un cluster, redistribuirea datelor realizîndu-se în mod automat. Astfel se ușurează munca și dacă este necesară o capacitate mai mare pentru date, se pot adăuga mașini noi in cluster si baza de date va organiza totul.

1.2.1.2. Caracteristici & Concepte

MongoDB prezintă caracteristici unice și utile, care nu sunt (toate) prezente în orice altă soluție de baze de date.

-Indexarea: MongoDB suportă indicite sau fixe în orice cale. Fără a schimba baza de date, migrațiile masive de date sunt de obicei inutile. Cheile noi sau cele care lipsesc se pot rezolva la nivel de aplicație, în loc de a impune tuturor datelor să aibe aceeași formă. Acest lucru oferă dezvoltatorilor avantaje de flexibilitate în modul în care lucrează cu aceste modele de date.

Dimensiunea datelor ce sunt stocate într-o bază de date se află într-o creștere continuă. Un terabyte de date este acum un lucru obișnuit.

Deoarece cantitatea de date necesară de stocare crește, dezvoltatorii se confruntă cu problema: cum ar trebui să scaleze bazele lor de date? Scalarea unei baze de date se reduce la alegerea dintre extindere (obținerea unei mașini mai mari) sau scalare (date partiționare peste mai multe mașini). Mașinile mari sunt de multe ori foarte scumpe, și în cele din urmă o limită fizică este atinsă în cazul în care o mașină mai puternică nu poate fi achiziționată de la orice preț. Alternativ, pentru a adăuga spațiu de stocare sau de a crește performanța, se poate cumpăra un alt server de stocare și se poate adăuga la cluster.

MongoDB a fost proiectat de la inceput pentru baze de date de dimensiuni foarte mari. Modelul permite împărțirea în mod automat a datelor pe mai multe servere. Volumul de date se poate echilibra și încărca pe un cluster, redistribuirea datelor realizîndu-se în mod automat. Astfel se ușurează munca și dacă este necesară o capacitate mai mare pentru date, se pot adăuga mașini noi in cluster si baza de date va organiza totul.

1.2.1.2. Caracteristici & Concepte

MongoDB prezintă caracteristici unice și utile, care nu sunt (toate) prezente în orice altă soluție de baze de date.

-Indexarea: MongoDB suportă indici secundari generici, care permit o varietate de interogări rapide, și oferă capabilități de indexare geospațiale.

-JavaScript: În locul procedurilor stocate, dezvoltatorii pot utiliza, stoca și folosi funcțiile JavaScript și pe partea de server.

-Agregarea: MongoDB suportă numeroase instrumente de agregare, printre care si MapReduce. [4] Aceasta este folosită in procesarea cantităților mari de date în mod distribuit și paralel pe un cluster. Sistemul administrează serverele distribuite și asigură rularea sarcinilor în paralel. [5]

-Colecții de dimensiuni fixe: Colecțiile sunt fixate în dimensiune și sunt utile pentru anumite tipuri de date.

-Stocarea de fișiere: MongoDB suportă un protocol ușor de utilizat pentru stocarea fișierelor de dimensiuni mari și fișiere metadata.

De asemenea, caracteristici comune ale bazelor de date relaționale nu sunt prezente în MongoDB, precum legăturile și tranzacțiile complexe. Acestea sunt decizii arhitecturale pentru a oferi scalabilitate, deoarece aceste două caracteristici ale bazelor de date relaționale sunt dificile pentru a fi furnizate eficient într-un sistem de baze de date distribuit.

Concepte ale bazei de date MongoDB

-Într-o bază de date Mongo, unitatea de bază de date este documentul, aproximativ echivalent cu un rând dint-un sistem relațional de gestionare a bazei de date.

-În mod similar, o colecție poate fi considerată echivalentul unui tabel.

-O singură instanță de MongoDB poate găzdui mai multe baze de date independente, în care fiecare dintre ele are propriile colecții și permisiuni.

– JavaScript are un rol foarte important în Mongo, deoarece este utilizat pentru administrarea și manipularea datelor.

-Fiecare document are o cheie specială, "_id", care este unic în colecția de documente.

1.2.1.3. Arhitectura bazei de date

MongoDB este o bază de date orientată pe documente.

1.2.1.3.1. Documente

Un document reprezintă un set ordonat de chei cu valori asociate. Reprezentarea unui document diferă în funcție de limbajul de programare, dar cele mai multe limbaje au o structură de date care este o potrivire naturală, cum ar fi o hartă, hash, sau dicționar. În JavaScript, de exemplu, documentele sunt reprezentate ca obiecte:

{"mesaj": "Hello World!"}

Acest document simplu conține o singură cheie, "mesaj", cu o valoarea "Hello World!". În realitate, aceste documente sunt complexe și conțin mai multe perechi de cheie / valoare:

{"mesaj": "Hello World!", "persoane": 100, "valoare": "testare" }

În MongoDB, perechile cheie / valoare în documente sunt ordonate-documentul. Astfel documentul

{"mesaj": "Hello World!", "persoane": 100, "valoare": "testare" }

este diferit de documentul

{"mesaj": "Hello World, "valoare": "testare", !", "persoane": 100}.

Cheile unui document sunt șiruri de caractere. Orice caracter UTF-8 este permis într-o cheie, cu câteva restricții:

– Cheile nu trebuie să conțină caracterul 0 (caracterul nul). Caracterul nul este utilizat pentru a semnifica sfârșitul unei chei.

-Caracterele $ au proprietăți speciale și trebuie utilizate numai în anumite circumstanțe. În general, acesta trebuie să fie considerat rezervat.

-Cheile care încep cu _ sunt considerate rezervate.

1.2.1.3.2.Colecții de documente

O colecție reprezintă un grup de documente. Realizând o comparație cu bazele de date relaționale, în MongoDB o colecție este similară cu o tabelă, iar un document din colecție cu un rând din acea tabelă.

Colecțiile pot avea o schemă variabilă și una liberă. Astfel, o colecție poate să conțină documente de mai multe forme diferite.

Următoarele documente se pot stoca în aceeași colecție în același timp:

{"mesaj": "Hello World!", "persoane": 100, "valoare": "testare" }

{"fructe": "măr" }

O colecție este identificată prin numele său. Numele poate fi format din orice caracter UTF-8, dar cu anumite restricții:

-Nu trebuie sa existe șir gol

-Numele unei colecții nu trebuie să conțină caracterul \ 0 (caracterul nul)

-Nu trebuiesc create colecții care încep cu „System” deoarece acest prefix este rezervat pentru

colecții de sistem. De exemplu: system.users, system.namespaces

-Nu trebuie să conțină caracterul „$” în nume deoarece aceasta este rezervată.

1.2.1.3.3. Subcolecții

Subcolecțiile se folosesc pentru organizarea unei colecții, nu au proprietați speciale și sunt utile și încorporate in mai multe instrumente MongoDB:

– GridFS, un protocol pentru stocarea fișierelor mari, folosește subcolecții pentru a stoca fișiere metadata separat de bucăți de conținut

-Consola web MongoDB organizează datele în secțiunea subcolecției DBTOP

Subcolecțiile reprezintă o modalitate foarte bună de a organiza datele în MongoDB, iar utilizarea lor este recomandată.

1.2.1.3.4. Baza de date

MongoDB permite gruparea documentelor în colecții, iar acestea la rândul lor sunt grupate în baza de date.

O singură instanță de MongoDB poate să găzduiasca mai multe baze de date, fiecare dintre ele putând fi considerat complet independent. O bază de date are propriile permisiuni, iar fiecare bază de date este stocată în fișiere separate pe disc.

Bazele de date separate sunt folosite atunci când stocarea datelor pentru mai multe aplicații se păstrează pe același server de MongoDB.

Numele unei baze de date respectă aceleași restricții ca și numele unei colecții, cu alte două noi cerințe: să conțină numai litere mici iar dimensiunea lor să nu depășească 64 de octeți, fiind limitată la această valoare.

Există baze de date diferite cu nume rezervate care pot fi accesate direct și au funcții speciale. Aceste baze de date sunt:

-admin: Reprezintă baza de date "root", în ceea ce privește autentificarea. Dacă un utilizator se adaugă la baza de date admin, utilizatorul moștenește în mod automat permisiuni pentru toate bazele de date. De asemenea, anumite comenzi la nivel de server, se pot rula numai de admin-ul bazei de date, cum ar fi listarea tuturor bazelor de date sau oprirea serverului.

-local: Această bază de date poate fi utilizat pentru a stoca orice colecție care trebuie să fie local pentru un singur server și nu se poate replica.

-config: Această bază de date este utilizată intern pentru a stoca informații atunci când MongoDB este utilizată pentru configurări.

1.2.1.4. Tipuri de date

Valorile din documente pot fi de mai multe tipuri. Documentele în MongoDB sunt de tipul "JSON", care este similar cu obiectele în JavaScript. JSON reprezintă o simplă reprezentare a datelor și conține șase tipuri de date. Deoarece capacitățile JSON sunt limitate, singurele tipuri de date fiind cele de tip null, boolean, numeric, string, matrice, și obiect, MongoDB adaugă suport pentru o serie de tipuri de date suplimentare, pe lângă cele oferite de JSON.

Tipuri de date de bază:

-null: {„x”: null}

-boolean: {„x”: false} sau {„x”: true}

-întregi pe 32 biți: Nu pot fi reprezentați. Valorile reale cu virgulă pe 64 biți sunt transformate în întregi pe 32 biți.

-întregi pe 64 biți: Nu pot fi reprezentați. Valorile reale cu virgulă pe 64 biți sunt transformate în întregi pe 64 biți.

-valori reale cu virgulă pe 64 biți: {„x”: 3,14}

-string: {„x”: „Hello World”}

-simbol: Nu poate fi reprezentat. Aceasta este transformată în string

-object id: {„x”: objectId() }

Reprezintă un id unic pentru documente. Se reprezintă pe 12 biți.

-dată: {„x”: new Date() }

-expresii regulate: {„x”: /Hello World/12}

Documentele conțin obiecte regulate folosind sintaxa JavaScript

-documente ce conțin cod JavaScript: {„x”: function() {*/ */} }

-date binare:șir de biți

-valori maxime: Documentele BSON conțin un tip de date speciale care reprezintă cea mai mare valoare posibilă

-valori minime: Documentele BSON conțin un tip de date specialecare reprezintă cea mai mică valoare posibilă

– valori nedefinite: {„x”: undefined}, se poate utiliza în documente și este diferit de tipul null.

-liste sau seturi: {„x”: [“a”, “b”, “c”] }

Numere

JavaScript conține un tip de date de tip "număr". MongoDB are trei tipuri de numere: întreg pe biți, întreg pe 8 biți, și valori reale pe 8 biți.

În mod implicit, orice număr scris în consolă este tratat de MongoDB ca un double. Dacă preluăm din baza de date un număr întreg pe 4 octeți, aceasta se va converti într-un număr real cu virgula mobilă.

Tipuri de tip Dată

Tipurile de tip dată sunt utilizate pentru stocarea informațiilor despre timp în MongoDB. Crearea unui obiect de tip Data se realizează folosind comanda new Date(). Apelarea constructorului ca funcție o să returneze data ca un șir, nu ca un obiect.

Datele sunt afișate în consolă folosind setările locale de fus orar. În baza de date informațiile despre dată nu au asociate și fusul orar. Pentru stocarea lor se folosește o altă cheie.

Arrays

Tipul de dată Arrays sau Tablouri poate conține diferite tipuri de date ca si valori. Acest tip de dată se poate utliza în operații unde trebuie respectată ordinea (liste, stive, sau cozi) dar și în operații ce nu necesită o ordine (Set).

Exemplu de un document de tip matrice: {"constanta": ["pi", 3.14]} . Într-o data de tip array se mai poate stoca un alt array.

Embedded Documents

Aceste tipuri de date sunt documente ce sunt folosite ca valoare pentru o cheie într-un alt document. De exemplu, într-un document ce conține denumirea persoanei se poate stoca un nou document despre adresa lui.

{

"nume": "Ozgean Septar",

"adresa": {

"strada": "Iuliu Maniu",

"oraș": "București"

}

}

Valoarea pentru cheia "adresa" din exemplul anterior este un alt document cu propriile valori pentru „stradă” și „oras”.Într-o bază de date relațională, documentul se modelează în rânduri diferite din 2 tabele diferite (tabela adrese și persoane). Documentele încorporate se folosesc pentru reprezentarea mai eficientă și naturală a informației.

_id and ObjectIds

Fiecare document în MongoDB are o cheie "_id". Valoarea cheii "_id” poate fi de orice tip. Implicit este de tipul ObjectId. Într-o colecție de documente, fiecare document trebuie să aibe o valoare unică pentru "_id", ce asigură ca fiecare document într-o colecție să poată fi identificat în mod unic.

ObjectId este tipul implicit pentru "_id". Acest tip de dată este generat într-un mod unic global pe mașini diferite. Deoarece MongoDB a fost proiectat de la început ca o bază de date distribuită, tipul ObjectId este foarte util.

1.2.1.5. Operații de bază CRUD

Interacțiunea cu baza de date MongoDB se realizează de la linia de comandă cu consola bazată pe JavaScript. Consola vine împreuna cu MongoDB și este un instrument esențial pentru efectuarea diferitelor operații asupra bazei de date.

Pentru început se pornește serverul cu comanda:

$ mongod

Ulterior se pornește consola, cu următoarea instrucțiune:

$ mongo

MongoDB shell version: 2.4.0

Conecting to: test

>use proiect

>db

proiect

Cele patru operații de bază ale consolei sunt cele de: create, read, update and delete (CRUD).

-Crearea (Create): Funcția de inserare adaugă un document nou la o colecție. Pentru stocarea unei cărți, se creează o variabilă numită carte, ce este un obiect JavaScript și reprezintă documentul. Câmpurile documentului sunt: "titlul", "autor", și "data" (data la care a fost publicat):

> carte = {"titlu": "Vremuri",

… "autor": "Un autor",

… "date": new Date ()}

{

"titlu": "Vremuri",

"autor": "Un autor",

"Data": ISODate("2014-05-12T19:45:09,982Z")

}

Acesta reprezintă un document MongoDB valabil, și salvăm documentul in colecția biblioteca, cu metoda de insert:

db.biblioteca.insert(carte)

> db.biblioteca.find()

{

"_id" : ObjectId("4u835321467df5f5k9b60a2d"),

"titlu": "Vremuri",

"autor": "Un autor",

"Data": ISODate("2014-05-12T19:45:09,982Z")

}

-Citirea (Read):Comanda în consolă pentru afișarea tutoror documentelor din colecție este:

> db.biblioteca.findOne()

-Actulizarea (Update):Comanda în consolă pentru actualizarea unui document din colecție sau adăugarea unui nou câmp este:

>db.blog.update({title : "Vremuri apuse"}, carte)

-Ștergerea (Delete): Comanda în consolă pentru actualizarea unui document din colecție sau adăugarea unui nou câmp este:

> db.blog.remove({title : "Vremuri apuse"}) [6]

Capitolul 2. Baze de date distribuite

2.1. Replicarea

2.1.1. Introducere

Replicarea reprezintă fundamentul pentru dezvoltarea aplicațiilor de dimensiuni mari și performante. Replicarea permite configurarea unuia sau a mai multor servere ca stații server de tip slave, sau replici ale altor servere. Replicarea este folosită și pentru alte activități precum partajarea datelor sau păstrarea unui server cu o copie a datelor în scopuri de testare sau de optimizare.

Principala problemă rezolvată de replicare constă în păstrarea unui server de date sincronizat cu alt server. Stațiile de tip slave se pot conecta doar la un singur master, și în același timp pot să acționeze în calitate de master pentru alte stații de tip slave. Stațiile de tip master și slave se pot aranja în diferite topologii. Se poate replica întregul server, anumite baze de date, sau chiar diferite tabele ce necesită a fi replicate.

MySQL suportă două tipuri de replicare: bazată pe declarații (statement) și bazată pe rânduri (rowbased replication). Replicarea bazată pe declarații este disponibilă începând cu versiunea MySQL 3.23 și este ceea ce mai utilizată în producție. Începând cu versiunea MySQL 5.1 este disponibilă și replicarea bazată pe rânduri. Ambele tipuri de replicare funcționează prin păstrarea modificărilor într-un log binar al stației master și reluarea acestui log de către stațiile slave. Stațiile master și slave sunt asincrone, deoarece copia datelor din stația slave nu se face instant. Replicarea datelor de stațiile de tip slave poate dura de la câteva mili-secunde până la câteva ore. [7]

2.2. Replicarea în MySQL

2.2.1. Compatibilitatea replicării în MySQL

Un server nou se poate adăuga într-un sistem si poate deveni o stație de tip slave pentru o stație deja existentă fără nicio problemă, însă nu poate să fi o stație de tip slave pentru un server deja existent. Serverele deja existente pot să fie în situația de a nu întelege noile caracteristici ale serverului nou introdus și pot exista diferențe în formatele de fișiere pe care le utilizează. De exemplu, nu se poate realiza replicarea de la o stație master MySQL 5.0 la o stație de tip slave MySQL 4.0.

O stație slave necesită o logare binară de la stația master pentru a fi funcțională în sistem. De asemenea, este nevoie de această logare binară și pentru recuperarea datelor (backup). În timpul funcționării normale, sarcina depusă pe master de către o stație de tip slave este mică.

Atașarea mai multor stații de tip slave la un master, presupune copierea și existența datelor pe mai multe servere. Replicarea poate fi costisitoare dacă există mai multe stații de tip slave decât necesarul de care este nevoie, deoarece resursele hardware sunt utilizate într-un mod ineficient.

2.2.2. Utilizarea replicării

-Distribuirea datelor

Este utilă pentru a menține o copie a datelor în diverse locații distribuite geografic, cum ar fi diverse centre de date. În funcție de necesități se pot adăuga sau elimina noi stații de tip slave.

-Echilibrarea încărcării datelor

Replicarea poate ajuta la distribuirea de interogări de citire în mai multe servere, ce funcționează foarte bine pentru aplicații ce folosesc la o scară foarte mare operațiile de citire.

-Recuperarea datelor (Backup)

Replicarea este o tehnică importanta ce ajută la recuperarea datelor.

-Disponibilitatea înaltă și failover

Replicarea asigură funcționarea în cazul unor defecte, problemă importantăpe piața muncii.Un failover bun presupune mai multe stații de tip slave replicate ce faciliteaza reducerea timpilor de așteptare în cazul defecțiunilor.

-Testarea noilor versiuni

Se realizează prin configurarea unei stații de tip slave cu o nouă versiune MySQL și testarea funcționării în parametri normali.

2.2.3. Funcționarea replicării

Procesul de replicare este alcătuit din trei părți:

1. Stația de tip master înregistrează modificările din baza de date în propriul log binar (binary log)

2. Stațiile de tip slave copiază logul binar al stației master

3. Stațiile de tip slave repetă înregistrările din logul binar al stației master și le aplică in propria bază de date.

Prima parte a procesului de replicare constă în logarea binară a statiilor de tip slave la stația de tip master. După fiecare operație realizată în baza de date, stația de tip master înregistrează modificările în logul binar. MySQL înregistrează serial tranzacțiile în logul binar, indiferent de durata execuției tranzacțiilor. După ce evenimentele au fost înregistrate în logul binar, stația de tip master execută tranzacțiile.

Următoarea etapă constă în copierea logului binar de către stațiile de tip slave pe propriul hard disk în logul de schimb (relay log). Pentru înnceput, se pornește un fir de execuție, numit I / O slave thread.. Firul de execuție I/O deschide o conexiune obișnuită cu stația de tip master și porneșteun proces special de depozitare numită binlog (nu există nici o comandă SQL corespunzătoare). Procesul binlog citește evenimente din logul binar al stației master. După citire procesul se oprește și așteaptă stațiile de tip master să semnaleze când au loc noi tranzacții. Firul de execuție I/O realizează scrierea evenimentelor pe logul stației slave.

Ultima parte a procesului de replicare este realizată de către firul de execuție SQL al stației de tip slave. Aceasta citește și replică datele din locul de schimb și actualizează baza de date. Logul de schimb este păstrat în memoria cache al stației de tip slave. Evenimentele pe care firul de execuție SQL le execută, opțional, se pot păstra în logul binar al stației slave.

Fig 2.1. Funcționarea replicării

Sursa: [A1]

Figura de mai sus este o reprezentare a funcționarii replicării. În imagine sunt reprezentate doar două fire de replicare care se execută pe stația de tip slave (I/O thread și SQL thread). De asemenea, mai există încă un fir de execuție pe stația master. Ca orice conexiune la un server MySQL, conexiunea pe care stația de tip slave o deschide la stația master pornește cu un fir de execuție pe stația master.

Această arhitectură replicare este asincronă și permite ca firul I/O să funcționeze independent de firul SQL. Replicarea se realizeazăîn mod serial pe stația de tip slave, ceea ce înseamnă că actualizările care se pot executa în paralel pe stația master, nu se pot paraleliza pe stația de tip slave. [8]

2.2.4. Tipuri de replicare în MySQL

2.2.4.1. Replicarea bazată pe declarații

Replicarea bazată pe declarații sau replicarea logică stă la baza tuturor versiunilor de MySQL, până la versiunea MySQL 5.0 inclusiv.

Replicarea bazată pe declarație funcționează prin înregistrarea interogărilor care au modificat bazele de date de pe stația master. Când stația de tip slave citește evenimentele din logul de schimbare (relay log) și le execută, aceasta reexecută interogările SQL din baza de date a stației de tip master. Acest tip de replicare are avantaje cât și dezavantaje.

Cel mai important avantaj constituie implementarea, ce este destul de simplu de realizat. Logarea și reluarea tuturor interogărilor care au modificat baza de date fac ca stația de tip slave să fie teoretic în sincronizare cu stația de tip slave. Un alt beneficiu al acestui tip de replicare constă în faptul că logul binar tinde să fie compact.

Prin urmare acesta replicare pe baza declarațiilor nu utilizează resurse foarte mari. O interogare ceactualizează date de ordinul gigabytes-ilor poate folosi doar câțiva zeci de bytes în logul binar. De asemenea, instrumentul mysqlbinlog este cel mai recomandat pentru acest tip de replicare.

Cu toate acestea, în practică, replicarea bazată pe declarații nu este la fel de simplă cum pare pentru că multe schimbări de pe stația de master pot depinde și de alți factori în afară de interogări. De exemplu, declarațiile se vor executa în timpi diferiți pe master și pe slave. Logul binar MySQL include pe lângă textul de interogare și fragmente de metadate, precum timpul la care se execută interogările. Chiar și așa, există unele declarații pe care nu se pot replica corect, cum ar fi interogări ce utilizează funcția CURRENT_USER. Altă problemă care apare este faptul că modificările trebuie să fie serializabile.Acest lucru necesită setări de configurare și caracteristici de server suplimentare.

2.2.4.2. Replicarea bazată pe rânduri

Replicarea bazată pe rânduri a fost introdusăîncepând cu versiunea MySQL 5.1 și este similar cu modul în care se realizează replicarea la diferite baze de date. Modificările de date sunt înregistrate în logul binar. Acest sistem are mai multe avantaje și dezavantaje.

Cel mai mare avantaj constă în replicarea corectă a fiecărei declarații și replicarea mult mai eficientă pentru anumite declarații. Principalul dezavantaj constă în dimensiunea foarte mare la care poate ajunge logul binar și astfel declarațiile de actualizare a bazei de date au o vizibilitate mai mică.

Replicarea bazată pe rânduri poate realiza replicarea diferitelor modificări mult mai eficient pentru că stația de tip slave nu trebuie să realizeze replicarea unei interogări întregi. De exemplu, o interogare realizează o interogare asupra unei tabele de dimensiuni foarte mari, dar rezultatul interogării se aplică doar la câteva rânduri din acest tabel. Reluarea unei interogări poate fi foarte costisitoare. Astfel, stația de tip slave, va replica doar modificările din acele câteva rânduri.

Pe de altă parte, există și situații în care replicarea bazată pe declarații este mult mai eficientă, spre exemplu, dacă se dorește modificarea tuturor elementelor de pe o coloană. Folosind replicarea bazată de rânduri, această interogare ar fi foarte costisitoare, deoarece fiecare rând ar trebui să fie scris în logul binar, ceea ce mărește foarte mult logul binar.

Pentru că niciun format nu este perfect pentru orice situație, MySQL 5.1 realizează automat selectarea tipului de replicare în funcție de necesități. În mod implicit, aceasta folosește replicare pe bază de declarație, dar atunci când se detectează un eveniment care nu poate fi replicat în mod corect cu o declarație, se trece la replicarea bazată de rânduri. Deși are numeroase avantaje, în producție cel mai mult se utilizează replicarea bazată pe declarații. [9]

2.3. Replicarea în MongoDB

2.3.1. Funcționarea

Configurarea replicării în MongoDB presupune existența a cel puțin doua servere sau noduri. Un nod este nodul master și este responsabil de tratarea cererilor venite de la client. Nodul slave este responsabil cu copierea datelor de la nodul master. Nodul master păstrează o evidență a tuturor operațiunilor care au fost efectuate pe ea. Nodul slave are rolul de a sonda periodic nodul master de noi operațiuni și apoi de a efectua copierea datelor. Prin efectuarea acestor operații pe nodul master, nodul slave păstrează datele de la nodul master.

2.3.2. Replicarea Master-Slave

Replicarea master-slave este modul de replicare general, susținut de MongoDB.

Acest mod este foarte flexibil și poate fi folosit pentru backup, failover, scalare. Replicarea se poate realiza pe o singură mașină, dar de cele mai multe ori este recomandat să se realizeze pe mai multe servere.

Fig 2.2. Replicarea de tip Master-Slave

Sursa: [A2]

Configurarea

Se pornește cu un nod principal și unul sau mai multe noduri secundare care cunosc adresa nodului principal.

Pornirea nodului principal(master) se realizează prin execuția comenzii:

mongod –master.

În mod similar, pornirea nodurilor secundare se realizează cu comanda:

mongod –slave –source master_address.

Master_address reprezintă adresa nodului principal carea fost pornit la început.

La realizarea replicării pe o singură mașină, se creează un director pentru master în care se vor stoca datele.

$ mkdir -p ~/dbs/ master

$ / Mongod –dbpath ~/dbs/ master –port 10000 –master

Pentru nodul secundar, se alege un director diferit de cel al masterului, un port diferit și trebuie specificat care este masterul.

$ mkdir -p ~/dbs/ slave

$ ./mongod –dbpath ~/dbs/ slave –port 10001 –slave –source localhost:10000

Acum nodurile secundare trebuie replicate de un nod principal. Replicarea nu se poate realiza de la un nod secundar. Numărul ideal de noduri secundare dintr-un cluster pentru ca sistemul să lucreze eficient este de 12.

2.3.3. Setul de replicare

Setul de replicare reprezintă un grup master-slave care face failover automat. Un cluster master-slave diferă față de un set de replicare prin faptul că cel din urmă nu are numai un singur master. Cu toate că sunt aproape similare, atunci când nodul master din setul de replicare pică, un nod slave devine master in timp ce masterul este picat.

Avantajul si ușurința setului de replicare este că toată transformarea se realizează automat.Setul de replicare asigură că functionarea sistemului fără neconcordanțe atunci când masterul curent pică. Driverul realizează failover automat și unul dintre nodurile slave devine master și se asigură funcționarea continuă. [10]

Failover reprezintă trecerea la un server redundant sau de așteptare când un server a fost defectat. Diferența dintre failover si switchover constă în funcționarea automată și fără avertismente față de switchover în care trecerea necesită intervenția umană. Capacitatea de failover este necesară pentru servere si sisteme care necesită disponibilitate continuă. [11]

Fig 2.3 Set de replicare

Sursa: [A2]

Set de replicare cu 2 servere. Când serverul master pică serverul secundar devine master.

Configurare:

Pentru început se creează directoarele de date și se aleg porturi pentru fiecare server:

$ mkdir -p ~/dbs/node1 ~/dbs/node2

Înainte de a porni serverele, setul de replicare trebuie sa fie denumit. Numele face referire la setul în ansamblu și ajută la distingerea dintre mai multe seturi. Fie setul denumit "blort" și MyPC ca hostname.

$ ./mongod –dbpath ~/dbs/node1 –port 10001 –replSet blort/MyPC: 10002

Pornim încă un server în același mod:

$ ./mongod –dbpath ~/dbs/node2 –port 10002 –replSet blort/MyPC: 10001

Se poate adăuga un nou sistem cu aceleași comenzi:

$ ./mongod –dbpath ~/dbs/node3 –port 10003 –replSet blort/MyPC: 10001

$ ./mongod –dbpath ~/dbs/node3 –port 10003 –replSet blort/MyPC: 10001, MyPC: 1002

Dacă într-un set de replicare se specifică un singur server din set, acesta detectează automat serverele din set și se conectează la restul serverelor automate. Pentru ca sistemul să funcționeze optim se realizează inițializarea setului de reproduceri din consolă. Inițializarea se realizează doar o singură dată si este necesară conectarea unui singur server la consolă si declararea tutoror serverelor printr-un script.

Într-un set de replicare există mai multe tipuri de noduri.

-Noduri standard

Poate să devină nod principal într-un set și participă la vot atunci când trebuie să fie ales un nou nod principal. Este un nod set de replicare regulat și stochează o copie completă a datelor replicate.

-Noduri pasive

Nu poate să devină nod principal într-un set dar participă la vot atunci când trebuie să fie ales un nou nod principal. Stochează de asemenea, o copie completă a datelor replicate.

-Noduri arbitru

Nu poate să devină nod principal într-un set și nu stochează copie a datelor replicate. Nodurile arbitru participă doar la votarea noului nod principal.

Fiecare nod dintr-un set are setat un nivel de prioritate. Nodurile pasive au setat mereu prioritatea 0 și nu vor deveni noduri principale. Nodurile cu prioritate diferită de zero vor fi selectate în ordinea descrescătoare a priorității. Dacă există noduri cu aceasi prioritate, nodul principal este ales in funcție de timpul cel mai scurt de reîmprospătare a datelor.

Exemple de configurări ale nodurilor standard, pasive si arbitru.

> Members.push ({

… "_id": 3,

… "host": "MyPC: 10003",

… "Priority": 5

…});

> Members.push ({

… "_id": 4,

… "host": "MyPC: 10004",

… "arbiterOnly": true

…}); [12]

2.3.4. Sincronizarea

Sincronizarea completă a datelor de pe nodul master se realizează de fiecare când este pornit un nou nod slave. Nodul slave va copia fiecare document de la nodul master. După ce operația devine completă, nodul slave începe interogarea nodului master.

Există posibilități în care nodul slave devine asincrondatorită timpului îndelugat de sicronizare sau rămânerii în urmă cu operațiile care se execută pe modul master. Acest nod rămas în urmă numai este capabil să continue operațiile care se execută pe nodul master, deoarece operațiile sunt prea “noi”.

Atunci când un nod slave nu se mai poate sincroniza, replicarea se oprește iar nodul slave trebuie să se sincronizeze din nou cu nodul master. Resincronizarea se poate realiza manual prin executarea comenzii {"resync": 1} sau automat prin repornirea nodului slave cu opțiunea –autoresync. Operatiunea de resincronizarea este foarte costisitoare și este o situație de evitat în replicarea datelor. [13]

Capitolul 3. Topologii de replicare a bazelor de date MySQL și MongoDB

Replicarea în MySQl se poate realiza pe orice configurație master-slave, cu restricția ca o instanță de slave să aibe un singur master. Se pot utiliza topologii de la cele mai simple până la cele mai complexe.

Regulile de bază ce trebuie respectate sunt:

-un slave MySQL poate avea doar un singur master

-fiecare slave trebuie să aibe un ID de server unic.

– un master poate avea mai multe instanțe de slave

-un slave poate propaga modificările de la master, și să fie master pentru alte instanțe de slave.

3.1. O stație master și mai multe stații slave

Reprezintă o configurație la fel de simplă precum configurația de tip master-slave. Stațiile de tip slave nu se conectează între ele și se vor lega numai la master. Această topologie simplă este utilizată când există multe operații de citire și un număr redus de operații de scriere. Această configurație permite setarea mai multor servere slave în același timp sau adăugarea de noi servere slave.Deși topologia este foarte simplă, sistemul este suficient de flexibil pentru a acoperimai multe cerințe:

-Utilizarea diverselor servere slave pentru diferite roluri (de exemplu: adăugarea de indici diferiți, utilizarea diferitelor motoare de căutare)

– Configurarea unuiserver slave ca un master în așteptare, cu niciun alt rol în topologie

-Posibilitatea ca un server slave să fie utilizat pentru recuperarea datelor în cazuri grave

-Întârzierea unuia sau mai multor instanțe de server slave pentru recuperarea datelor în cazuri grave

-Folosirea unui server slave pentru backup

Avantajul acestei topologii constă în complexitatea scăzută față de alte topologii.Dacă toate serverele slave se opresc în același punct al replicării, acestea vor porni din același punct de unde au fost oprite.De asemenea, sunt simplificate sarcinile administrative, cum ar fi trecerea unui server slave în server master.

Figura 3.1. Topologie cu un master și 3 stații de tip slave

Sursa: [A1]

3.2. Două Stații Master-Master în modurile activ-activ

Replicarea master-master (replicarea bidirecțională) implică două servere, fiecare configurat atât ca stație master cât și ca o stație slave al celuilalt server. Replicarea master-master în mod activ-activ are utilizări speciale. O utilizare a acestei topologii este utilă pentru birourile separate geografic, în care fiecare birou are nevoie de propria copie locală de scriere a datelor. Problema majoră a aceastei topologii constă în schimbarea fără conflicte a celor două servere.

Problemele apar de obicei atunci când o interogare schimbă același rând, simultan, pe ambele servere sau realizează operația de inserare folosind autoincrementarea, în același timp pe ambele servere.

MySQL 5.0 a adăugat unele caracteristici care fac acest tip de configurare replicare mai sigur: setările auto_increment_increment și auto_increment_offset. Aceste setări permit generarea de valori prin autoincrementare pentru ambele servere fără să apară conflicte. Cu toate acestea, probleme la această topologie apar în continuare la operația de scriere, de exemplu, dacă replicarea se oprește cu o eroare dar aplicația păstreză cererile de scriere pe ambele servere. Pentru evitarea acestor probleme, configurația unei topologii de 2 stații master-master în modurile active-pasiv este mai utilă.

Fig 3.2 Topologie de tip Master-Master

Sursa: [A1]

3.3. Două stații master în modurile active-pasiv

Această configurație permite schimbarea rolurilor de active și pasiv, de server înainte și înapoi foarte ușor, deoarece configurațiile pe servere sunt simetrice.Principala diferență față de topologia anterioară este că unul dintre stații este utilizată numai pentru citire. Astfel sistemul realizează failover și failback automat si ușor.De asemenea, sistemul permite efectuarea lucrărilor de mentenanță, optimizare, și updarea sistemului de operare fără să afecteze funcționarea continuă a sistemului.

Topologia permite evitarea multor probleme și limitări în MySQL. Pentru crearea și administrarea unui astfel de sistem, există un instrument, MySQL Master-Master Replication Manager care automatizează multe sarcini dificile, precum recuperarea și resincronizarea replicării, creearea de noi stații slave și așa mai departe.

Pentru configurarea master-master se efectueză aceiași pași pe ambele servere, deoarece cele 2 stații trebuie să fie simetrice.Când se realizează o operație de scriere pe stația principală, stația secundară execută interogarea și datele sunt replicate pe stația secundară. Această topologie este foarte importantă și este una dintre cele mai comune topologii de replicare.

Fig 3.3. Topologia de tip Master-Master în modurile activ-pasiv

Sursa: [A1]

3.4. Stații master-master cu mai multe stații slave

Această configurație leagă unul sau mai multe stații slave pentru fiecare stație co-master. Topologia are avantajul asigurării unei redundanțe suplimentare. Într-o topologiede replicare distribuită geografic, se elimină punctul unic de eșec la fiecare site.Configurația este utilă dacă se utilizează o topologie master-master la nivel local pentru a asigura un failover rapid. De asemenea, atunci când o stație master se defectează este posibilă trecerea unei stații slave într-o stație master, dezavantajul constând în operații complexe.

Fig 3.4 Topologie de tip Master-Master cu mai multe stații slave

Sursa: [A1]

3.5. Topologia de tip “inel”

Configurația de tip “inel” este bazată pe configurația de tip dual-master, are trei sau mai multe stații de master, și fiecare stație este tip slave pentru stația master anterioară în inel, și stație master pentru stația de după el. Această topologie se mai numește și replicare circulară. Față de celelalte topologii prezentate, nu are avantajul simetriei și procesul de failover nu este ușor de realizat. De asemenea, stațiile depind în întregime de funcționarea fiecărui nod din inel. Orice eliminare a unui nod din inel cauzează intrarea întregului sistem într-o buclă infinită. Topologia de tip “inel” este foarte fragilă și de cele mai multe ori evitată. Pentru a evita o parte din problemele cauzate de această topologie, se mai adaugă stații slave suplimentare pentru a asigura redundanță în fiecare punct. Și în acest caz, o defectare a unei stații din inel duce la pierdere importantă de putere și la spargerea întregului inel.

Fig 3.5. Topologia de tip “inel”

Sursa: [A1]

3.6. Topologie ce conține o stație master, o stație distribuită de master și mai multe stații slave

O stație distribuită de master este o stație slave care se conectează la stația master și care are ca scop izolarea stației principale direct de stațiile de tip slave. Stațiile de tip slave creează un fir de execuție pe stația master, care trimite înapoi datele către stația slave. Dacă există mai multe stații de tip slave și fiecare stație execută cereri către stația master în același timp, aceasta își poate opri funcționarea corectă și se poate defecta datorită numărului mare de solicitări. De asemenea, dacă stațiile slave solicită diferite cereri care numai există în sistemul de fișiere cache, pot apărea erori ale stației master care reduc performanțele acesteia.

Stația master de distribuție reduce astfel încărcarea stației master, izolând stațiile slave. Acestea se conectează la stația distribuită care realizează operația de citire de la stația master. Dacă operațiile sunt doar de scriere sau se replică doar o parte din tabele, stația distribuită poate să lipsească. În cazul unui număr foarte mare de stații slave, se pot utiliza mai multe stații distribuite. Stațiile master de distribuție se pot utiliza și cu alte scopuri, precum aplicarea de filtre sau pentru a rescrie regulile pentru evenimentele din jurnal binare.

Fig 3.6. Topologie ce conține o stație distribuită

Sursa: [A1]

3.7. Topologia de tip arbore sau piramidă

Această topologie se utilizează atunci când replicarea se face către un număr foarte mare de stații de tip slave, distribuite geografic sau pentru a crește performanțele întregului sistem. Utilizarea acestei topologii presupune gestionarea rapidă a sistemului.Un alt avantaj al acestui model este micșorarea sarcinii de pe stația master. Dacă o stație se defectează, atunci aceasta va afecta mai multe stații din alte straturi, lucru evitat dacă fiecare stație slave s-ar conecta direct la stația master. Aceasta este și dezavantajul acestei topologii. Numărul de straturi intermediare este direct proporțional cu soluționarea problemelor care apar dacă o stație se defectează. [14]

Fig 3.7 Topologie de tip arbore

Sursa: [A1]

Capitolul 4. Configurarea bazelor de date și a replicării

4.1. Configurarea bazei de date

În realizarea aplicației am utilizat o bază de date ce cuprinde 6 tabele. Acestea au următoarea structură.

Tabela `autori`

idAutor: Primary Key, Auto_Increment, INT

nume : varchar(255)

Tabela `carti`

idCarte: Primary Key, Auto_Increment, INT

nume: varchar (255)

autor: varchar (255)

categorie: varchar (255)

fișier: varchar(255)

content: varchar (255)

idAutor: Foreign Key, INT

idCategorie: Foreign key, INT

Tabela `categorii`

idCategorie: Primary Key, Auto_Increment, INT

nume: varchar (255)

Tabela `users`

idUser: Primary Key, Auto_Increment, INT

nume: varchar (255)

username : varchar (255)

parola: varchar (255)

email: varchar(255)

telefon: varchar (255)

admin: int(1)

benchmark: int(1)

Tabela `bench`

id: Primary Key, Auto_Increment, INT

timestamp: int(11)

query: text

duration: float(10,9)

hash: varchar(255)

type: varchar (255)

Tabela `config`

name: Primary Key, Auto_Increment, INT

value: varchar (255)

Fig 4.1. Diagrama ERR

4.2. Configurarea replicării de tip Master-Slave în MongoDB

Configurările au fost realizate pentru sistemul de operare Windows.

Pentru început se pornesc două sau mai multe servere mongod, unul pentru master care este unic și următoarele pentru slave.

Pornirea unei instanțe mongod:

Se deschide o fereastră cmd din windows și se ajunge la directorul bin al bazei de date MongoDB (C:\Program Files\MongoDB 2.6 Standard\bin).

Pentru pornirea unui master se execută următoarea comandă:

>mongod –master –dbpath /data/db

După ce se pornește masterul, aceasta afișează în consolă că funcționează și așteaptă conexiuni pe portul 27017 (cel default).

Se deschide din nou o fereastră cmd și se execută comanda următoare pentru a pornii stațiile slave.

>mongod –slave –port 27018–source localhost:27017 –dbpath /data/slaved

>mongod –slave –port 27019–source localhost:27017 –dbpath /data/slaved

Au pornit 2 stații de tip slave pe porturile 27018 și 27019. Este obligatoriu să se aleagă porturi diferite față de cel pe care rulează masterul. Argumentul –source se folosește pentru conectarea stației slave la master.

După pornirea stațiilor master și slave, următorul pas constă în specificarea bazei de date ce urmează să fie replicată. Se pornește din nou o fereastră cmd și se pornește o instanță de mongo.

C:\Program Files\MongoDB 2.6 Standard\bin > mongo.exe

>use local

>db.sources.insert ({“host”:”localhost”, only:”ozgean”});

4.3. Configurarea replicării de tip Master-Slave în MySQL

Logarea în MySQl ca root pe stația master

mysql -u root –p

Crearea unui utilizator pe stația master cu care stația slave va accesa masterul:

GRANT REPLICATION SLAVE ON *.* TO replicare@’%’ IDENTIFIED BY ‘parolareplicare’;

FLUSH PRIVILEGES;

Root reprezintă numele utilizatorului cu parola parolareplicare.

Se adaugă în fișierul de configurare my.ini următoarele configurări în secțiunea mysqld.

log-bin = mysql-bin

binlog-do-db=ozgean (baza de date ce va fi replicată)

server-id=10

Se repornește masterul, iar în fișierul de configurare my.ini al stației slave se adaugă următoareale linii de cod:

Server-id=5 (id stația slave)

master-host= 192.168.0.108 (ip stația master)

master-connect-retry= 60

master-user= replicare

master-password= parolareplicare

replicate-do-db= ozgean (baza de date)

relay-log= C:/work/slave-relay.log

relay-log-index= C:/work/slave-relay-index

Se reporneste statia slave.

Logarea pe stația slave: mysql -u root –p

Se execută comenzile:

slave stop;

CHANGE MASTER TO MASTER_HOST='192.168.0.108', MASTER_USER='replicare',

MASTER_PASSWORD='parolareplicare', MASTER_LOG_FILE='mysql-bin.000001',

MASTER_LOG_POS=106;

slave start;

Capitolul 5. Proiectarea Aplicației

5.1. Scopul Aplicației

Aplicația noastră are ca scop studiul , implementarea și analizarea performanțelor a două baze de date diferite: prima bază de date de tip SQL: MySQL și o bază de date de tip NO-SQL: MongoDB. Aplicația este de forma unei aplicații web care simulează gestionarea unei biblioteci online.

Codul aplicației se găsește în Anexa 2.

5.2. Tehnologii utilizate

HTML- utilizat pentru crearea paginilor web

PHP- utilizat pentru realizarea paginilor web dinamice

CSS- utilizat pentru formatarea elementelor unei pagini web

JavaScript- utilizat pentru funcționalități

MySQL- baza de date relațională

MongoDB- baza de date nerelațională

5.3. Descrierea Aplicației

În continuare, voi prezenta aplicația împreună cu funcționalitățile si ecranele acesteia.

Logarea

Fig 5.1. Secțiunea de autentificare

Dacă datele de autentificare sunt greșite, aplicația o să returneze un mesaj în care se precizează că datele introduse sunt greșite. După ce autentificarea se realizează cu succes, utilizatorul este redirecționat către pagina principală a aplicației.

Fig 5.2. Pagina principală

În pagina de start sunt prezentate numărul de cărți disponibile, numărul de autori, categoriile și utilizatorii aplicației. Meniul din stânga permite vizualizarea tuturor autorilor, cărților și categoriilor existente în baza de date.

Fig 5.3. Secțiunea Autori

De asemenea, meniul Căutare permite unui utilizator să caute cartea dorită în baza de date în funcție de criteriile selectate.

Fig 5.4. Secțiunea căutare

Ultima parte a aplicației este disponibilă doar pentru administratori. Administratorii au acces la meniurile Utilizatori, unde pot adăuga utilizatori noi, pot modifica setările site-ului și pot realiza măsurători de performanță.

Fig 5.5. Măsurători de performanță asupra operației de inserare

Fig 5.6. Măsurători de performanță asupra operației de actualizare

Fig 5.7. Măsurători de performanță asupra operației de selectare

5.4. Teste de performanță asupra bazei de date

Testarea bazelor de date a fost realizată prin studierea performanțelor de inserare, selectare și actualizare a celor două baze de date: MySQL și MongoDB.

Testele de performanță au fost realizate pe următorul sistem:

Procesor: Intel(R) Core (TM) i3 CPU M 350 @ 2.27 Ghz

Memoria RAM: 3 GB

Sistemul de operare: Windows 7 Professional, arhitectura pe 64 biti, Service Pack 1

În continuare, am realizat operații de Inserare asupra bazei de date MySQL, cât și asupra bazei de date MongoDB.

Figura 5.8 prezintă o comparație între timpii de inserare. Pe axa X se găsesc numărul de intrări iar pe axa Y se află durata în secunde a interogării de tip Insert. Timpii măsurați au fost realizați asupra unor tabele goale.

Fig 5.8. Performanțe 1

Figura 5.9. Prezintă timpii de inserare a datelor într-o tabelă ce cuprinde 500000 câmpuri. Se observă că timpii de inserare într-o bază de date goală sunt mult mai mici față de timpii de inserare într-o bază de date populată.

Fig 5.9. Performanțe 2

În figurile 5.10. și 5.11. se prezintă mai bine timpii de inserare în MongoDB, respectiv MySQL pentru o tabelă goală, respectiv o tabelă ce conține 500000 intrări.

Fig 5.10. Performanțe 3

Timpii de inserare pentru MySQL pentru o baza de date goală, respectiv cu 500000 de rânduri

Fig 5.4. Performanțe 4

Timpii de inserare pentru MongoDB atunci când baza de date este goalaă, respectiv cu 500000 documente

Am mai realizat teste de performanță asupra operațiilor de bază: Insert, Update, Select. Din figura 5.5. reiese că operația de inserare durează cel mai mult, fiind urmată de operațiile de Update și de Select. De precizat că interogările s-au realizat asupra unei tabele ce conține 100000 câmpuri.

Fig 5.4. Performanțe 5

Operațiile pentru o bază de date ce conține 100000 de rânduri

Ultimul test de performanță prezintă timpii de latență care rezultă în urma comunicării aplicației cu baza de date. Se observă că timpul necesar unei inserări din aplicație este mai mare față de cazul în care inserarea se face direct în baza de date.

Fig 5.6. Performanțe 6

Timpii de inserare în baza de date Mongo prin aplicație și direct în baza de date

Concluzii

Bazele de date distribuite se folosesc din ce în ce mai des în producție, ele oferind multe avantaje utilizatorilor și marilor companii. Cel mai important avantaj constă în păstrarea și utilizarea datelor de pe mai multe servere. O foarte mare creștere încep să aibă și bazele de date nerelaționale, de tip NO-SQL.

În această lucrare am studiat baza de date MongoDB de tip NO-SQL, simultan cu cea mai populară bază de date relațională MySQL. În urma testelor de performanță, am ajuns la concluzia că MongoDB prezintă foarte multe avantaje față de MySQL.

Replicarea la MongoDB este două feluri: Replicarea de tip Master-Slave și Replica Set. Implementarea funcționalităților pentru replicare este mult mai simplu de realizat la MongoDB. De asemenea, un foarte mare avantaj constituie proprietatea de a realiza failover automat. Dacă o stație de tip master devine nefuncțională, sistemul poate să aleagă automat un nou nod master. La MySQL, această operație se realizează numai cu intervenția omului.

În urma testelor de performanță realizate asupra bazelor de date, am ajuns la concluzia că MongoDB poate avea viteză de 3 sau 4 ori mai mare față de MySQL. Testele au fost realizate în aceleași condiții pe o stație. Inserarea unui număr de rânduri într-o tabelă, se realizează într-un timp scurt la MongoDB. De exemplu, inserarea a 10000 intrări într-o tabelă de tip MySQL durează 2,15 secunde, iar în MongoDB aproximativ 0,3 secunde.

MongoDB este utilizată în producție de multe companii importante precum LinkedIn, McAfee, MTV, CISCO sau Ebay.

Bibliografie

[1], [3] – TAHAGHOGHI S., HUGH E. W., Learning MySQL, First Edition, O`Reilly Media, Inc., United States of America, November 2006, ISBN: 078-0-506-00864-2

[2] –SHARMA N., PERNIU L., CHONG F. R., IYER A., NANDAN C., MITEA A-C., NONVINKERE M., DANUBIANU M., Database Fundamentals, First Edition, IBM Corporation, November 2010

[4], [6], [10], [12], [13] – CHODOROW K., DIRELF M., MongoDB: The Definitive Guide, First Edition, O’ReillyMedia, Inc., United States of America, September 2010, ISBN: 978-1-449-38156-1

[5] – http://ro.wikipedia.org/wiki/MapReduce accesat la data 29.05.2014

[7], [8], [9], [14] – SCHWARTZ B., ZAITSEV P., TKACHENKO V., ZAWODNY D. J., LENTZ A., BALLING J. D., High Performance MySQL, Second Edition, O’Reilly Media, Inc., United States of America, June 2008, ISBN: 978-0-596-10171-8

[11] – http://en.wikipedia.org/wiki/Failover accesat la data 31.05.2014

[A1]- SCHWARTZ B., ZAITSEV P., TKACHENKO V., ZAWODNY D. J., LENTZ A., BALLING J. D., High Performance MySQL, Second Edition, O’Reilly Media, Inc., United States of America, June 2008, ISBN: 978-0-596-10171-8

[A2]- CHODOROW K., DIRELF M., MongoDB: The Definitive Guide, First Edition, O’ReillyMedia, Inc., United States of America, September 2010, ISBN: 978-1-449-38156-1

Anexe

Index.php

<?

include "inc/include.php";

if(!$_SESSION['logged']){

header("Location: login/");

die();

}

$menu='home';

?>

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="utf-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<meta name="description" content="">

<meta name="author" content="">

<title><?=$cfg['titlu']?></title>

<link href="css/bootstrap.css" rel="stylesheet">

<link href="css/sb-admin.css" rel="stylesheet">

<link rel="stylesheet" href="font-awesome/css/font-awesome.min.css">

<link rel="stylesheet" href="http://cdn.oesmith.co.uk/morris-0.4.3.min.css">

<link rel="icon" type="image/ico" href="favicon.ico" />

<meta name='description' content="<?=$cfg['descriere']?>"/>

<meta name='keywords' content="<?=$cfg['keywords']?>"/>

</head>

<body>

<div id="wrapper">

<?

include "inc/header.php"

?>

<div id="page-wrapper">

<div class="row">

<div class="col-lg-12">

<h1>Bine ati venit! <small>Platforma gratuita pentru librarie online</small></h1>

</div>

</div><!– /.row –>

<div class="row">

<div class="col-lg-6">

<div class="panel panel-info">

<div class="panel-heading">

<div class="row">

<div class="col-xs-5">

<i class="fa fa-comments fa-5x"></i>

</div>

<div class="col-xs-6 text-right">

<p class="announcement-heading"><?=number_format(nr_tabel('carti'))?></p>

<p class="announcement-text">Carti</p>

</div>

</div>

</div>

<a href="cautare.php">

<div class="panel-footer announcement-bottom">

<div class="row">

<div class="col-xs-6">

Cauta o carte

</div>

<div class="col-xs-6 text-right">

<i class="fa fa-arrow-circle-right"></i>

</div>

</div>

</div>

</a>

</div>

</div>

<div class="col-lg-6">

<div class="panel panel-warning">

<div class="panel-heading">

<div class="row">

<div class="col-xs-6">

<i class="fa fa-check fa-5x"></i>

</div>

<div class="col-xs-6 text-right">

<p class="announcement-heading"><?=nr_tabel('autori')?></p>

<p class="announcement-text">Autori</p>

</div>

</div>

</div>

<a href="autori.php">

<div class="panel-footer announcement-bottom">

<div class="row">

<div class="col-xs-6">

Vezi autorii

</div>

<div class="col-xs-6 text-right">

<i class="fa fa-arrow-circle-right"></i>

</div>

</div>

</div>

</a>

</div>

</div>

</div>

<div class="row">

<div class="col-lg-6">

<div class="panel panel-danger">

<div class="panel-heading">

<div class="row">

<div class="col-xs-6">

<i class="fa fa-tasks fa-5x"></i>

</div>

<div class="col-xs-6 text-right">

<p class="announcement-heading"><?=nr_tabel('categorii')?></p>

<p class="announcement-text">Categorii</p>

</div>

</div>

</div>

<a href="categorii.php">

<div class="panel-footer announcement-bottom">

<div class="row">

<div class="col-xs-6">

Vezi categoriile

</div>

<div class="col-xs-6 text-right">

<i class="fa fa-arrow-circle-right"></i>

</div>

</div>

</div>

</a>

</div>

</div>

<div class="col-lg-6">

<div class="panel panel-success">

<div class="panel-heading">

<div class="row">

<div class="col-xs-6">

<i class="fa fa-comments fa-5x"></i>

</div>

<div class="col-xs-6 text-right">

<p class="announcement-heading"><?=nr_tabel('users')?></p>

<p class="announcement-text">Utilizatori</p>

</div>

</div>

</div>

<a href="#">

<div class="panel-footer announcement-bottom">

<div class="row">

<div class="col-xs-6">

online

</div>

<div class="col-xs-6 text-right">

<i class="fa fa-arrow-circle-right"></i>

</div>

</div>

</div>

</a>

</div>

</div>

</div><!– /.row –>

</div><!– /#page-wrapper –>

<?

include "inc/footer.php";

?>

</div><!– /#wrapper –>

<!– JavaScript –>

<script src="js/jquery-1.10.2.js"></script>

<script src="js/bootstrap.js"></script>

<!– Page Specific Plugins –>

<script src="http://cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js"></script>

<script src="http://cdn.oesmith.co.uk/morris-0.4.3.min.js"></script>

<script src="js/morris/chart-data-morris.js"></script>

<script src="js/tablesorter/jquery.tablesorter.js"></script>

<script src="js/tablesorter/tables.js"></script>

</body>

</html>

Setari.php

<?

include "inc/include.php";

if(!$_SESSION['logged']){

if(!isAdmin()){

header("Location: login/");

}

}

$menu='setari';

print_R($_POST);

if(isset($_POST['update'])){

foreach($_POST as $tag=>$val){

$q=db_select('config',"name='".$tag."'",0);

if($q){

$array['value']=$val;

db_update($array,'config',"name='".$tag."'");

}else{

$array['value']=$val;

$array['name']=$tag;

db_insert($array,'config');

}

}

$error['type']='success';

$error['message']='Setarile au fost modificate.';

unset($cfg);

$cf=db_select('config');

foreach($cf as $row){

$cfg[$row['name']]=$row['value'];

}

}

?>

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="utf-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<meta name="description" content="">

<meta name="author" content="">

<title>Setari site – <?=$cfg['titlu']?></title>

<link href="css/bootstrap.css" rel="stylesheet">

<link href="css/sb-admin.css" rel="stylesheet">

<link rel="stylesheet" href="font-awesome/css/font-awesome.min.css">

<link rel="stylesheet" href="http://cdn.oesmith.co.uk/morris-0.4.3.min.css">

<link rel="icon" type="image/ico" href="favicon.ico" />

<meta name='description' content="<?=$cfg['descriere']?>"/>

<meta name='keywords' content="<?=$cfg['keywords']?>"/>

</head>

<body>

<div id="wrapper">

<?

include "inc/header.php"

?>

<div id="page-wrapper">

<div class="row">

<div class="col-lg-12">

<h1>Setari site</h1>

<ol class="breadcrumb">

<li class="active"><i class="fa fa-dashboard"></i> Acasa</li>

<li><i class="fa fa-user"></i> Setari site</li>

</ol>

</div>

</div><!– /.row –>

<div class="row">

<div class="col-lg-6">

<?

include "inc/messages.php"

?>

<form role="form" action='' method='POST'>

<div class="form-group">

<label>Titlu site</label>

<input class="form-control" name='titlu' placeholder='Nume si Prenume' value='<?=$cfg['titlu']?>' required/>

</div>

<div class="form-group">

<label>Descriere</label>

<textarea class="form-control" name='descriere' placeholder='Descriere' rows=4/><?=$cfg['descriere']?></textarea>

</div>

<div class="form-group">

<label>Cuvinte cheie</label>

<textarea class="form-control" name='keywords' placeholder='Cuv. Cheie' rows=4/><?=$cfg['keywords']?></textarea>

</div>

<button type="submit" name='update' class="btn btn-default">Modifica</button>

</form>

</div>

</div><!– /.row –>

</div><!– /#page-wrapper –>

<?

include "inc/footer.php";

?>

</div><!– /#wrapper –>

<!– JavaScript –>

<script src="js/jquery-1.10.2.js"></script>

<script src="js/bootstrap.js"></script>

<!– Page Specific Plugins –>

<script src="js/tablesorter/jquery.tablesorter.js"></script>

<script src="js/tablesorter/tables.js"></script>

</body>

</html>

Autori.php

<?

include "inc/include.php";

if(!$_SESSION['logged']){

header("Location: login/");

die();

}

$menu='autori';

?>

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="utf-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<meta name="description" content="">

<meta name="author" content="">

<title>Autori – <?=$cfg['titlu']?></title>

<link href="css/bootstrap.css" rel="stylesheet">

<link href="css/sb-admin.css" rel="stylesheet">

<link rel="stylesheet" href="font-awesome/css/font-awesome.min.css">

<link rel="stylesheet" href="http://cdn.oesmith.co.uk/morris-0.4.3.min.css">

<link rel="icon" type="image/ico" href="favicon.ico" />

<meta name='description' content="<?=$cfg['descriere']?>"/>

<meta name='keywords' content="<?=$cfg['keywords']?>"/>

</head>

<body>

<div id="wrapper">

<?include "inc/header.php"?>

<div id="page-wrapper">

<div class="row">

<div class="col-lg-12">

<h1>Autori</h1>

<ol class="breadcrumb">

<li><i class="fa fa-dashboard"></i> Acasa</li>

<li><i class="fa fa-dashboard"></i> Carti</li>

<li class="active"><i class="fa fa-dashboard"></i> Autori</li>

</ol>

</div>

</div><!– /.row –>

<div class="row">

<div class="col-lg-12">

<?

$autori=db_select('autori')or die(mysql_error());

foreach($autori as $row){

?>

<div class="col-lg-3">

<a href="cautare.php?cauta=&show=50&autor=<?=$row['id']?>"><?=$row['nume']?></a><br/>

</div>

<?}

?>

</div>

</div><!– /.row –>

</div><!– /#page-wrapper –>

<?

include "inc/footer.php";

?>

</div><!– /#wrapper –>

<!– JavaScript –>

<script src="js/jquery-1.10.2.js"></script>

<script src="js/bootstrap.js"></script>

<!– Page Specific Plugins –>

<script src="http://cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js"></script>

<script src="http://cdn.oesmith.co.uk/morris-0.4.3.min.js"></script>

<script src="js/morris/chart-data-morris.js"></script>

<script src="js/tablesorter/jquery.tablesorter.js"></script>

<script src="js/tablesorter/tables.js"></script>

</body>

</html>

Categorii.php

<?

include "inc/include.php";

if(!$_SESSION['logged']){

header("Location: login/");

die();

}

$menu='categorii';

?>

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="utf-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<meta name="description" content="">

<meta name="author" content="">

<title>Categorii – <?=$cfg['titlu']?></title>

<link href="css/bootstrap.css" rel="stylesheet">

<link href="css/sb-admin.css" rel="stylesheet">

<link rel="stylesheet" href="font-awesome/css/font-awesome.min.css">

<link rel="stylesheet" href="http://cdn.oesmith.co.uk/morris-0.4.3.min.css">

<link rel="icon" type="image/ico" href="favicon.ico" />

<meta name='description' content="<?=$cfg['descriere']?>"/>

<meta name='keywords' content="<?=$cfg['keywords']?>"/>

</head>

<body>

<div id="wrapper">

<?include "inc/header.php"?>

<div id="page-wrapper">

<div class="row">

<div class="col-lg-12">

<h1>Categorii</h1>

<ol class="breadcrumb">

<li><i class="fa fa-dashboard"></i> Acasa</li>

<li><i class="fa fa-dashboard"></i> Carti</li>

<li class="active"><i class="fa fa-dashboard"></i> Categorii</li>

</ol>

</div>

</div><!– /.row –>

<div class="row">

<div class="col-lg-12">

<?

$categorii=db_select('categorii')or die(mysql_error());

foreach($categorii as $row){

?>

<div class="col-lg-4">

<a href="cautare.php?cauta=&show=50&categorie=<?=$row['id']?>"><?=$row['nume']?></a><br/>

</div>

<?}

?>

</div>

</div><!– /.row –>

</div><!– /#page-wrapper –>

<?

include "inc/footer.php";

?>

</div><!– /#wrapper –>

<!– JavaScript –>

<script src="js/jquery-1.10.2.js"></script>

<script src="js/bootstrap.js"></script>

<!– Page Specific Plugins –>

<script src="http://cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js"></script>

<script src="http://cdn.oesmith.co.uk/morris-0.4.3.min.js"></script>

<script src="js/morris/chart-data-morris.js"></script>

<script src="js/tablesorter/jquery.tablesorter.js"></script>

<script src="js/tablesorter/tables.js"></script>

</body>

</html>

Cautare.php

<?

include "inc/include.php";

if(!$_SESSION['logged']){

header("Location: login/");

die();

}

$menu='cautare';

if($_GET['categorie'])$q.=" AND categorie='".$_GET['categorie']."'";

if($_GET['autor'])$q.=" AND autor='".$_GET['autor']."'";

$limit=$_GET['show']?$_GET['show']:100;

$rez=db_select('carti'," nume like '%".str_replace(' ','%',$_GET['nume'])."%'".$q." limit 0,".$limit)or die(mysql_error());

?>

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="utf-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<meta name="description" content="">

<meta name="author" content="">

<title>Cautare – <?=$cfg['titlu']?></title>

<link href="css/bootstrap.css" rel="stylesheet">

<link href="css/sb-admin.css" rel="stylesheet">

<link rel="stylesheet" href="font-awesome/css/font-awesome.min.css">

<link rel="stylesheet" href="http://cdn.oesmith.co.uk/morris-0.4.3.min.css">

<link rel="icon" type="image/ico" href="favicon.ico" />

<meta name='description' content="<?=$cfg['descriere']?>"/>

<meta name='keywords' content="<?=$cfg['keywords']?>"/>

</head>

<body>

<div id="wrapper">

<?

include "inc/header.php"

?>

<div id="page-wrapper">

<div class="row">

<div class="col-lg-12">

<h1>Cautare</h1>

<ol class="breadcrumb">

<li><i class="fa fa-dashboard"></i> Acasa</li>

<li><i class="fa fa-dashboard"></i> Carti</li>

<li class="active"><i class="fa fa-dashboard"></i> Cautare</li>

</ol>

</div>

</div><!– /.row –>

<div class="row">

<div class="col-lg-4">

<form role="form" action='' method='GET'>

<div class="form-group">

<label>Numele Cartii</label>

<input class="form-control" name='nume' placeholder='Introduceti numele cartii cautate' value='<?=$_GET['nume']?>'/>

</div>

<div class="form-group">

<label>Autor</label>

<select class="form-control" name='autor'>

<option value=''>Toti</option>

<?

$autori=db_select('autori','1=1',0)or die(mysql_error());

foreach($autori as $row){

if($_GET['autor']==$row['id'])$sel='selected';else $sel='';

?>

<option value='<?=$row['id']?>' <?=$sel?>><?=$row['nume']?></option>

<?}?>

</select>

</div>

<div class="form-group">

<label>Categorie</label>

<select class="form-control" name='categorie'>

<option value=''>Toate</option>

<?

$categorii=db_select('categorii','1=1',0)or die(mysql_error());

foreach($categorii as $row){

if($_GET['categorie']==$row['id'])$sel='selected';else $sel='';

?>

<option value='<?=$row['id']?>' <?=$sel?>><?=$row['nume']?></option>

<?}?>

</select>

<input type='hidden' name='cauta'/>

</div>

<div class="form-group">

<label>Afiseaza</label>

<select class="form-control" name='show'>

<option value='50' <?if($_GET['show']==50)echo"selected"?>>50</option>

<option value='100' <?if($_GET['show']==100)echo"selected"?>>100</option>

<option value='200' <?if($_GET['show']==200)echo"selected"?>>200</option>

<option value='500' <?if($_GET['show']==500)echo"selected"?>>500</option>

</select>

</div>

<button type="submit" class="btn btn-default">Cautare</button>

<button type="reset" class="btn btn-default">Reseteaza formular</button>

</form>

</div>

<?if(isset($_GET['cauta'])){?>

<div class='col-lg-8'>

<h2>Rezultatele cautarii</h2>

<div class="table-responsive">

<table class="table table-bordered table-hover table-striped tablesorter">

<thead>

<tr>

<th>ID <i class="fa fa-sort"></i></th>

<th>Nume <i class="fa fa-sort"></i></th>

<th>Categorie <i class="fa fa-sort"></i></th>

<th>Autor <i class="fa fa-sort"></i></th>

<th>Descarcari <i class="fa fa-sort"></i></th>

</tr>

</thead>

<tbody>

<?

$i=1;

foreach($rez as $row){

$cat=db_select('categorii',"id='".$row['categorie']."'",0);

$aut=db_select('autori',"id='".$row['autor']."'",0);

?>

<tr>

<td><?=$i?></td>

<td><?=$row['nume']?></td>

<td><a href='cautare.php?cauta=&show=50&categorie=<?=$cat[0]['id']?>'><?=$cat[0]['nume']?></a></td>

<td><a href='cautare.php?cauta=&show=50&autor=<?=$cat[0]['id']?>'><?=$aut[0]['nume']?></a></td>

<td>121</td>

</tr>

<?$i++;}?>

</tbody>

</table>

</div>

</div>

<?}?>

</div><!– /.row –>

</div><!– /#page-wrapper –>

<?

include "inc/footer.php";

?>

</div><!– /#wrapper –>

<!– JavaScript –>

<script src="js/jquery-1.10.2.js"></script>

<script src="js/bootstrap.js"></script>

<!– Page Specific Plugins –>

<script src="http://cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js"></script>

<script src="http://cdn.oesmith.co.uk/morris-0.4.3.min.js"></script>

<script src="js/morris/chart-data-morris.js"></script>

<script src="js/tablesorter/jquery.tablesorter.js"></script>

<script src="js/tablesorter/tables.js"></script>

</body>

</html>

Contul meu

<?

include "inc/include.php";

if(!$_SESSION['logged']){

header("Location: login/");

}

$menu='acasa';

$info=$_USER;

if(isAdmin()){

if(isset($_GET['id'])){

$u = db_select('users',"id='".$_GET['id']."'");

$info= $u[0];

}

}

if(isset($_POST['edituser'])){

$array['nume'] = $_POST['nume'];

$array['telefon'] = $_POST['telefon'];

if(isAdmin()){

$array['admin'] = $_POST['admin'];

}

if($_POST['parola']){

$array['parola']=md5($_POST['parola']);

}

if($_POST['email']){

$d = db_select('users'," email='".$_POST['email']."' and id!='".$info['id']."'");

if($d){

$error['type']='danger';

$error['message']='E-mailul este folosit de catre altcineva!';

}else{

$array['email']=$_POST['email'];

}

}

if(!$error){

db_update($array,'users',"id='".$info['id']."'");

$info['nume']=$array['nume'];

$info['email']=$array['email'];

$info['telefon']=$array['telefon'];

$info['admin']=$array['admin'];

$error['type']='success';

$error['message']='Utilizatorul a fost modificat!';

}

}

?>

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="utf-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<meta name="description" content="">

<meta name="author" content="">

<title>Editeaza Cont – <?=$cfg['titlu']?></title>

<link href="css/bootstrap.css" rel="stylesheet">

<link href="css/sb-admin.css" rel="stylesheet">

<link rel="stylesheet" href="font-awesome/css/font-awesome.min.css">

<link rel="stylesheet" href="http://cdn.oesmith.co.uk/morris-0.4.3.min.css">

<link rel="icon" type="image/ico" href="favicon.ico" />

<meta name='description' content="<?=$cfg['descriere']?>"/>

<meta name='keywords' content="<?=$cfg['keywords']?>"/>

</head>

<body>

<div id="wrapper">

<?

include "inc/header.php"

?>

<div id="page-wrapper">

<div class="row">

<div class="col-lg-12">

<h1>Editeaza cont</h1>

<ol class="breadcrumb">

<li class="active"><i class="fa fa-dashboard"></i> Acasa</li>

<li><i class="fa fa-user"></i> Editeaza Cont</li>

</ol>

</div>

</div><!– /.row –>

<div class="row">

<div class="col-lg-6">

<?

include "inc/messages.php"

?>

<form role="form" action='' method='POST'>

<div class="form-group">

<label>Nume</label>

<input class="form-control" name='nume' placeholder='Nume si Prenume' value='<?=$info['nume']?>' required/>

</div>

<div class="form-group">

<label>Parola noua</label>

<input class="form-control" name='parola' placeholder='Parola pentru login' />

</div>

<div class="form-group">

<label>Email</label>

<input class="form-control" name='email' placeholder='Email' value='<?=$info['email']?>'/>

</div>

<div class="form-group">

<label>Telefon</label>

<input class="form-control" name='telefon' placeholder='Telefon' value='<?=$info['telefon']?>'/>

</div>

<?if(isAdmin()){?>

<div class="form-group">

<label>Tip</label>

<select class="form-control" name='admin'>

<option value=''>User</option>

<option value='1' <?if($info['admin']==1){?>selected<?}?>>Administrator</option>

</select>

</div>

<?}?>

<button type="submit" name='edituser' class="btn btn-default">Modifica</button>

</form>

</div>

</div><!– /.row –>

</div><!– /#page-wrapper –>

<?

include "inc/footer.php";

?>

</div><!– /#wrapper –>

<!– JavaScript –>

<script src="js/jquery-1.10.2.js"></script>

<script src="js/bootstrap.js"></script>

<!– Page Specific Plugins –>

<script src="js/tablesorter/jquery.tablesorter.js"></script>

<script src="js/tablesorter/tables.js"></script>

</body>

</html>

Utilizatori.php

<?

include "inc/include.php";

if(!$_SESSION['logged']){

if(!isAdmin()){

header("Location: login/");

die();

}

}

$menu='utilizatori';

if(isset($_POST['adduser'])){

$array['nume'] =$_POST['nume'];

$array['username'] =$_POST['username'];

$array['parola'] =md5($_POST['parola']);

$array['email'] =$_POST['email'];

$array['telefon'] =$_POST['telefon'];

$array['admin'] =$_POST['admin'];

$d = db_select('users',"username='".$array['username']."' or email='".$array['email']."'");

if($d){

$error['type'] ='danger';

$error['message'] ='Exista deja un utilizator cu numele si parola specificate';

}

if(!$error){

db_insert($array,'users');

$error['type'] ='success';

$error['message'] ='Utilizatorul a fost adaugat';

}

}

if(isset($_GET['delete'])){

$a['id'] = $_GET['delete'];

db_delete($a,'users');

$error['type'] ='info';

$error['message'] ='Utilizatorul selectat a fost sters';

}

?>

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="utf-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<meta name="description" content="">

<meta name="author" content="">

<title>Utilizatori – <?=$cfg['titlu']?></title>

<link href="css/bootstrap.css" rel="stylesheet">

<link href="css/sb-admin.css" rel="stylesheet">

<link rel="stylesheet" href="font-awesome/css/font-awesome.min.css">

<link rel="stylesheet" href="http://cdn.oesmith.co.uk/morris-0.4.3.min.css">

<link rel="icon" type="image/ico" href="favicon.ico" />

<meta name='description' content="<?=$cfg['descriere']?>"/>

<meta name='keywords' content="<?=$cfg['keywords']?>"/>

</head>

<body>

<div id="wrapper">

<?

include "inc/header.php"

?>

<div id="page-wrapper">

<div class="row">

<div class="col-lg-12">

<h1>Utilizatori</h1>

<ol class="breadcrumb">

<li class="active"><i class="fa fa-dashboard"></i> Acasa</li>

<li><i class="fa fa-dashboard"></i> Utilizatori</li>

</ol>

</div>

</div><!– /.row –>

<div class="row">

<div class="col-lg-4">

<?

include "inc/messages.php"

?>

<form role="form" action='' method='POST'>

<div class="form-group">

<label>Nume</label>

<input class="form-control" name='nume' placeholder='Nume si Prenume' required/>

</div>

<div class="form-group">

<label>Username</label>

<input class="form-control" name='username' placeholder='Numele de utilizator' required/>

</div>

<div class="form-group">

<label>Parola</label>

<input class="form-control" name='parola' placeholder='Parola pentru login' required/>

</div>

<div class="form-group">

<label>Email</label>

<input class="form-control" name='email' placeholder='Email'/>

</div>

<div class="form-group">

<label>Telefon</label>

<input class="form-control" name='telefon' placeholder='Telefon'/>

</div>

<div class="form-group">

<label>Tip</label>

<select class="form-control" name='admin'>

<option value=''>User</option>

<option value='1'>Administrator</option>

</select>

</div>

<button type="submit" name='adduser' class="btn btn-default">Adauga Utilizator</button>

<button type="reset" class="btn btn-default">Reseteaza formular</button>

</form>

</div>

<div class='col-lg-8'>

<h2>Lista utilizatori</h2>

<div class="table-responsive">

<table class="table table-bordered table-hover table-striped tablesorter">

<thead>

<tr>

<th>Id <i class="fa fa-sort"></i></th>

<th>Nume <i class="fa fa-sort"></i></th>

<th>Username <i class="fa fa-sort"></i></th>

<th>Email <i class="fa fa-sort"></i></th>

<th>Telefon <i class="fa fa-sort"></i></th>

<th>Tip <i class="fa fa-sort"></i></th>

<th>Actiuni <i class="fa fa-sort"></i></th>

</tr>

</thead>

<tbody>

<?

$bench=db_select('users','1=1 order by admin desc')or die(mysql_error());

$i=1;

foreach($bench as $row){

?>

<tr>

<td><?=$i?></td>

<td><?=$row['nume']?></td>

<td><?=$row['username']?></td>

<td><?=$row['email']?></td>

<td><?=$row['telefon']?></td>

<td><?=(($row['admin']==1)?'Administrator':'User')?></td>

<td align='right'><a href='contulmeu.php?id=<?=$row['id']?>' title='Editare utilizator'><i class="fa fa-edit"></i></a><a href='?delete=<?=$row['id']?>' onclick="return confirm('Sunteti sigur ca doriti sa stergeti acest utilizator?')"><i class="fa fa-trash-o"></i></a></td>

</tr>

<?}?>

</tbody>

</table>

</div>

</div>

</div><!– /.row –>

</div><!– /#page-wrapper –>

<?

include "inc/footer.php";

?>

</div><!– /#wrapper –>

<!– JavaScript –>

<script src="js/jquery-1.10.2.js"></script>

<script src="js/bootstrap.js"></script>

<!– Page Specific Plugins –>

<script src="js/tablesorter/jquery.tablesorter.js"></script>

<script src="js/tablesorter/tables.js"></script>

</body>

</html>

Insert.php

<?

include "inc/include.php";

function generate_carte(){

$substantive="Casa,Masa,Calul,Prietenul,Paharul,Masa,Cireasa,Monitorul,Tabla,Elefantul,Tatarul,Ecuatia,Masina,Bicicleta,Caminul,Canapeaua,Imprimanta,Creionul,Pixul,Mapa,Foaia,Mama,Tatal,Paharul";

$adjective="fericit,suparat,trist,obosit,ratacit,aiurit,frumos,rosu,albastru,galbena,verde,prietenos";

$altecuv="alearga,fuge,plange,mananca,se supara,se intristeaza,oboseste,licentiaza";

$sub=explode(',',$substantive);

$adj=explode(',',$adjective);

$alte=explode(',',$altecuv);

return $sub[array_rand ( $sub , 1)]." ".$adj[array_rand ( $adj , 1)]." ".$alte[array_rand ( $alte , 1)];

$z=0;

for ($i=0; $i <17893 ; $i++) {

$ins['nume'] =generate_carte();

$ins['autor'] =rand(1,80);

$ins['categorie'] =rand(1,32);

$ins['fisier'] = str_replace(' ','_',strtolower($ins[nume])).".txt";

# db_insert($ins,'carti');

$z++;

}

echo $z;

Bench.php

<?

include "inc/include.php";

if(!$_SESSION['logged']){

header("Location: login/");

die();

}

?>

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="utf-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<meta name="description" content="">

<meta name="author" content="">

<title>Benchmark – eBiblioteca 1.0</title>

<link href="css/bootstrap.css" rel="stylesheet">

<link href="css/sb-admin.css" rel="stylesheet">

<link rel="stylesheet" href="font-awesome/css/font-awesome.min.css">

<link rel="stylesheet" href="http://cdn.oesmith.co.uk/morris-0.4.3.min.css">

<link rel="icon" type="image/ico" href="favicon.ico" />

</head>

<body>

<div id="wrapper">

<?

include "inc/header.php"

?>

<div id="page-wrapper">

<div class="row">

<div class="col-lg-12">

<h1>Benchmark</h1>

<ol class="breadcrumb">

<li><i class="fa fa-dashboard"></i> Acasa</li>

<li><i class="fa fa-dashboard"></i> Carti</li>

<li class="active"><i class="fa fa-dashboard"></i> Cautare</li>

</ol>

</div>

</div><!– /.row –>

<div class="row">

<div class='col-lg-12'>

<div class="table-responsive">

<table class="table table-bordered table-hover table-striped tablesorter">

<thead>

<tr>

<th>ID <i class="fa fa-sort"></i></th>

<th>Tip <i class="fa fa-sort"></i></th>

<th>Data <i class="fa fa-sort"></i></th>

<th>Hash <i class="fa fa-sort"></i></th>

<th>Query <i class="fa fa-sort"></i></th>

<th>Durata <i class="fa fa-sort"></i></th>

</tr>

</thead>

<tbody>

<?

$bench=db_select('bench','1=1 order by id desc')or die(mysql_error());

$i=1;

foreach($bench as $row){

?>

<tr>

<td><?=$i?></td>

<td><?=$row['type']?></td>

<td><?=date('d.m.Y h:i:s',$row['timestamp'])?></td>

<td><?=$row['hash']?></td>

<td><?=$row['query']?></td>

<td><?=$row['duration']?>ms</td>

</tr>

<?$i++;}?>

</tbody>

</table>

</div>

</div>

</div><!– /.row –>

</div><!– /#page-wrapper –>

</div><!– /#wrapper –>

<!– JavaScript –>

<script src="js/jquery-1.10.2.js"></script>

<script src="js/bootstrap.js"></script>

<!– Page Specific Plugins –>

<script src="js/tablesorter/jquery.tablesorter.js"></script>

<script src="js/tablesorter/tables.js"></script>

</body>

</html>

Test.php

<?

include "inc/include.php";

print_r(db_select('categorii'));

?>

Teste.php

<?

include "inc/include.php";

if(!$_SESSION['logged']){

if(!isAdmin()){

header("Location: login/");

die();

}

}

$menu='teste';

function generate_carte(){

$substantive="Casa,Masa,Calul,Prietenul,Paharul,Masa,Cireasa,Monitorul,Tabla,Elefantul,Tatarul,Ecuatia,Masina,Bicicleta,Caminul,Canapeaua,Imprimanta,Creionul,Pixul,Mapa,Foaia,Mama,Tatal,Paharul";

$adjective="fericit,suparat,trist,obosit,ratacit,aiurit,frumos,rosu,albastru,galbena,verde,prietenos";

$altecuv="alearga,fuge,plange,mananca,se supara,se intristeaza,oboseste,licentiaza";

$sub=explode(',',$substantive);

$adj=explode(',',$adjective);

$alte=explode(',',$altecuv);

return $sub[array_rand ( $sub , 1)]." ".$adj[array_rand ( $adj , 1)]." ".$alte[array_rand ( $alte , 1)];

}

if(isset($_POST['insert'])){

$z=0;

$total=0;

for ($i=0; $i <$_POST['randuri'] ; $i++) {

$ins['nume'] =generate_carte();

$ins['autor'] =rand(1,80);

$ins['categorie'] =rand(1,32);

$ins['fisier'] =str_replace(' ','_',strtolower($ins[nume])).".txt";

$starttime = microtime(true);

db_insert($ins,'carti',0);

$endtime = microtime(true);

$duration = $endtime – $starttime; //calculates total time taken

$total+=$duration;

$z++;

}

$err1['type']='success';

$err1['message']="Au fost inserate cu succes <b>".$z."</b> randuri!<br/> Interogarea a durat: ".number_format($total,4)." secunde";

add_benchmark("INSERT","Inserare ".$z." randuri",$total);

}

if(isset($_POST['update'])){

$z=0;

$total=0;

for ($i=0; $i <$_POST['randuri'] ; $i++) {

$array['content']='Continut updatata!';

$rid=rand(1,100000);

$starttime = microtime(true);

db_update($array,'carti',"id='".$rid."'",0);

$endtime = microtime(true);

$duration = $endtime – $starttime; //calculates total time taken

$total+=$duration;

$z++;

}

$err2['type']='success';

$err2['message']="Au fost updatate cu succes <b>".$z."</b> randuri!<br/> Interogarea a durat: ".number_format($total,4)." secunde";

add_benchmark("UPDATE","Update ".$z." randuri",$total);

}

if(isset($_POST['select'])){

$starttime = microtime(true);

db_select('carti',"1=1 order by id desc limit 0,".$_POST['randuri'],0);

$endtime = microtime(true);

$duration = $endtime – $starttime; //calculates total time taken

$total=$duration;

$err3['type']='success';

$err3['message']="Au fost selectate cu succes <b>".$z."</b> randuri!<br/> Interogarea a durat: ".number_format($total,4)." secunde";

add_benchmark("SELECT","Select ".$_POST['randuri']." randuri",$total);

}

?>

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="utf-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<meta name="description" content="">

<meta name="author" content="">

<title>Teste performanta – <?=$cfg['titlu']?></title>

<link href="css/bootstrap.css" rel="stylesheet">

<link href="css/sb-admin.css" rel="stylesheet">

<link rel="stylesheet" href="font-awesome/css/font-awesome.min.css">

<link rel="stylesheet" href="http://cdn.oesmith.co.uk/morris-0.4.3.min.css">

<link rel="icon" type="image/ico" href="favicon.ico" />

<meta name='description' content="<?=$cfg['descriere']?>"/>

<meta name='keywords' content="<?=$cfg['keywords']?>"/>

</head>

<body>

<div id="wrapper">

<?

include "inc/header.php"

?>

<div id="page-wrapper">

<div class="row">

<div class="col-lg-12">

<h1>Teste performanta</h1>

<ol class="breadcrumb">

<li class="active"><i class="fa fa-dashboard"></i> Acasa</li>

<li><i class="fa fa-dashboard"></i> Teste performanta</li>

</ol>

</div>

</div><!– /.row –>

<div class="row">

<div class="col-lg-4">

<div class="panel panel-primary">

<div class="panel-heading">

<h3 class="panel-title"><i class="fa fa-bar-chart-o"></i> Insert</h3>

</div>

<div class="panel-body">

<?if($err1){?>

<div class="alert alert-<?=$err1['type']?> alert-dismissable">

<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>

<?=$err1['message']?>

</div>

<?}?> <form action='' method='post'>

<div class="form-group">

<label>Randuri</label>

<select class="form-control" name='randuri'>

<?for ($i=1000; $i <25000 ; $i+=1000) { ?>

<option value='<?=$i?>'><?=number_format($i)?></option>

<? }?>

</select>

</div>

<button type="submit" name='insert' class="btn btn-success">Insereaza si afiseaza timp</button>

</form>

</div>

</div>

</div>

<div class="col-lg-4">

<div class="panel panel-primary">

<div class="panel-heading">

<h3 class="panel-title"><i class="fa fa-bar-chart-o"></i> Update</h3>

</div>

<div class="panel-body">

<?if($err2){?>

<div class="alert alert-<?=$err2['type']?> alert-dismissable">

<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>

<?=$err2['message']?>

</div>

<?}?>

<form action='' method='post'>

<div class="form-group">

<label>Randuri</label>

<select class="form-control" name='randuri'>

<?for ($i=1000; $i <25000 ; $i+=1000) { ?>

<option value='<?=$i?>'><?=number_format($i)?></option>

<? }?>

</select>

</div>

<button type="submit" name='update' class="btn btn-warning">Updateaza si afiseaza timp</button>

</form>

</div>

</div>

</div>

<div class="col-lg-4">

<div class="panel panel-primary">

<div class="panel-heading">

<h3 class="panel-title"><i class="fa fa-bar-chart-o"></i> Select</h3>

</div>

<div class="panel-body">

<?if($err3){?>

<div class="alert alert-<?=$err3['type']?> alert-dismissable">

<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>

<?=$err3['message']?>

</div>

<?}?>

<form action='' method='post'>

<div class="form-group">

<label>Randuri</label>

<select class="form-control" name='randuri'>

<?for ($i=1000; $i <25000 ; $i+=1000) { ?>

<option value='<?=$i?>'><?=number_format($i)?></option>

<? }?>

</select>

</div>

<button type="submit" name='select' class="btn btn-info">Selecteaza si afiseaza timp</button>

</form>

</div>

</div>

</div>

</div><!– /.row –>

<div class="row">

<div class="col-lg-12">

<div class="panel panel-primary">

<div class="panel-heading">

<h3 class="panel-title"><i class="fa fa-bar-chart-o"></i> Benchmark</h3>

</div>

<div class="panel-body" style='height:500px; overflow-y:auto;'>

<div class="table-responsive">

<table class="table table-bordered table-hover table-striped tablesorter">

<thead>

<tr>

<th>ID <i class="fa fa-sort"></i></th>

<th>Tip <i class="fa fa-sort"></i></th>

<th style='width:100px;'>Data <i class="fa fa-sort"></i></th>

<th>Hash <i class="fa fa-sort"></i></th>

<th>Query <i class="fa fa-sort"></i></th>

<th style='width:100px;'>Durata <i class="fa fa-sort"></i></th>

</tr>

</thead>

<tbody>

<?

$bench=db_select('bench','1=1 order by id desc limit 0,50',0)or die(mysql_error());

$i=1;

foreach($bench as $row){

if($row['type']=='UPDATE'){

$cls='warning';

}

if($row['type']=='INSERT'){

$cls='success';

}

if($row['type']=='SELECT'){

$cls='info';

}

?>

<tr class="<?=$cls?>">

<td><?=$i?></td>

<td><?=$row['type']?></td>

<td style='font-size:10px;'><?=date('d.m h:i:s',$row['timestamp'])?></td>

<td><?=$row['hash']?></td>

<td><?=$row['query']?></td>

<td><?=number_format($row['duration'],4)?> sec</td>

</tr>

<?$i++;}?>

</tbody>

</table>

</div>

</div>

</div>

</div>

</div>

</div><!– /#page-wrapper –>

<?

include "inc/footer.php";

?>

</div><!– /#wrapper –>

<!– JavaScript –>

<script src="js/jquery-1.10.2.js"></script>

<script src="js/bootstrap.js"></script>

<!– Page Specific Plugins –>

<script src="js/tablesorter/jquery.tablesorter.js"></script>

<script src="js/tablesorter/tables.js"></script>

</body>

</html>

Login.php

<?

include "../inc/include.php";

if(isset($_GET['logout'])){

unset($_SESSION['logged'],$_SESSION['user_id']);

}

if(isset($_POST['submit'])){

$u = db_select('users',"username='".$_POST['username']."' and parola='".md5($_POST['parola'])."'");

if(!$u){

$error=1;

}else{

$_SESSION['logged']=1;

$_SESSION['user_id']=$u[0]['id'];

header("Location:../");

}

}

?>

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8">

<meta http-equiv="X-UA-Compatible" content="IE=edge">

<title>eBiblioteca Login</title>

<link rel="stylesheet" href="style/style.css"/>

</head>

<body>

<div style='position:absolute; width:450px; left:50%; margin-left:-225px; height:60px; margin-top:20px;'>

<?if($error){?>

<div class="error alert-message">

<a href="#" class="close">✘</a>

<p>Datele de login sunt gresite!</p>

</div>

<?}?>

</div>

<div id="container">

<div id="titlu">eBiblioteca Login</div>

<form action="" method='post'>

<center><img src="style/logo-login.png" alt=""></center>

<input type="text" class='text' name='username' placeholder='Username:'/>

<input type="password" class='text' name='parola' placeholder='Parola:'/>

<button type='submit' name='submit' class='button'>AUTENTIFICARE</button>

</form>

</div>

</body>

</html>

Bibliografie

[1], [3] – TAHAGHOGHI S., HUGH E. W., Learning MySQL, First Edition, O`Reilly Media, Inc., United States of America, November 2006, ISBN: 078-0-506-00864-2

[2] –SHARMA N., PERNIU L., CHONG F. R., IYER A., NANDAN C., MITEA A-C., NONVINKERE M., DANUBIANU M., Database Fundamentals, First Edition, IBM Corporation, November 2010

[4], [6], [10], [12], [13] – CHODOROW K., DIRELF M., MongoDB: The Definitive Guide, First Edition, O’ReillyMedia, Inc., United States of America, September 2010, ISBN: 978-1-449-38156-1

[5] – http://ro.wikipedia.org/wiki/MapReduce accesat la data 29.05.2014

[7], [8], [9], [14] – SCHWARTZ B., ZAITSEV P., TKACHENKO V., ZAWODNY D. J., LENTZ A., BALLING J. D., High Performance MySQL, Second Edition, O’Reilly Media, Inc., United States of America, June 2008, ISBN: 978-0-596-10171-8

[11] – http://en.wikipedia.org/wiki/Failover accesat la data 31.05.2014

[A1]- SCHWARTZ B., ZAITSEV P., TKACHENKO V., ZAWODNY D. J., LENTZ A., BALLING J. D., High Performance MySQL, Second Edition, O’Reilly Media, Inc., United States of America, June 2008, ISBN: 978-0-596-10171-8

[A2]- CHODOROW K., DIRELF M., MongoDB: The Definitive Guide, First Edition, O’ReillyMedia, Inc., United States of America, September 2010, ISBN: 978-1-449-38156-1

Anexe

Index.php

<?

include "inc/include.php";

if(!$_SESSION['logged']){

header("Location: login/");

die();

}

$menu='home';

?>

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="utf-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<meta name="description" content="">

<meta name="author" content="">

<title><?=$cfg['titlu']?></title>

<link href="css/bootstrap.css" rel="stylesheet">

<link href="css/sb-admin.css" rel="stylesheet">

<link rel="stylesheet" href="font-awesome/css/font-awesome.min.css">

<link rel="stylesheet" href="http://cdn.oesmith.co.uk/morris-0.4.3.min.css">

<link rel="icon" type="image/ico" href="favicon.ico" />

<meta name='description' content="<?=$cfg['descriere']?>"/>

<meta name='keywords' content="<?=$cfg['keywords']?>"/>

</head>

<body>

<div id="wrapper">

<?

include "inc/header.php"

?>

<div id="page-wrapper">

<div class="row">

<div class="col-lg-12">

<h1>Bine ati venit! <small>Platforma gratuita pentru librarie online</small></h1>

</div>

</div><!– /.row –>

<div class="row">

<div class="col-lg-6">

<div class="panel panel-info">

<div class="panel-heading">

<div class="row">

<div class="col-xs-5">

<i class="fa fa-comments fa-5x"></i>

</div>

<div class="col-xs-6 text-right">

<p class="announcement-heading"><?=number_format(nr_tabel('carti'))?></p>

<p class="announcement-text">Carti</p>

</div>

</div>

</div>

<a href="cautare.php">

<div class="panel-footer announcement-bottom">

<div class="row">

<div class="col-xs-6">

Cauta o carte

</div>

<div class="col-xs-6 text-right">

<i class="fa fa-arrow-circle-right"></i>

</div>

</div>

</div>

</a>

</div>

</div>

<div class="col-lg-6">

<div class="panel panel-warning">

<div class="panel-heading">

<div class="row">

<div class="col-xs-6">

<i class="fa fa-check fa-5x"></i>

</div>

<div class="col-xs-6 text-right">

<p class="announcement-heading"><?=nr_tabel('autori')?></p>

<p class="announcement-text">Autori</p>

</div>

</div>

</div>

<a href="autori.php">

<div class="panel-footer announcement-bottom">

<div class="row">

<div class="col-xs-6">

Vezi autorii

</div>

<div class="col-xs-6 text-right">

<i class="fa fa-arrow-circle-right"></i>

</div>

</div>

</div>

</a>

</div>

</div>

</div>

<div class="row">

<div class="col-lg-6">

<div class="panel panel-danger">

<div class="panel-heading">

<div class="row">

<div class="col-xs-6">

<i class="fa fa-tasks fa-5x"></i>

</div>

<div class="col-xs-6 text-right">

<p class="announcement-heading"><?=nr_tabel('categorii')?></p>

<p class="announcement-text">Categorii</p>

</div>

</div>

</div>

<a href="categorii.php">

<div class="panel-footer announcement-bottom">

<div class="row">

<div class="col-xs-6">

Vezi categoriile

</div>

<div class="col-xs-6 text-right">

<i class="fa fa-arrow-circle-right"></i>

</div>

</div>

</div>

</a>

</div>

</div>

<div class="col-lg-6">

<div class="panel panel-success">

<div class="panel-heading">

<div class="row">

<div class="col-xs-6">

<i class="fa fa-comments fa-5x"></i>

</div>

<div class="col-xs-6 text-right">

<p class="announcement-heading"><?=nr_tabel('users')?></p>

<p class="announcement-text">Utilizatori</p>

</div>

</div>

</div>

<a href="#">

<div class="panel-footer announcement-bottom">

<div class="row">

<div class="col-xs-6">

online

</div>

<div class="col-xs-6 text-right">

<i class="fa fa-arrow-circle-right"></i>

</div>

</div>

</div>

</a>

</div>

</div>

</div><!– /.row –>

</div><!– /#page-wrapper –>

<?

include "inc/footer.php";

?>

</div><!– /#wrapper –>

<!– JavaScript –>

<script src="js/jquery-1.10.2.js"></script>

<script src="js/bootstrap.js"></script>

<!– Page Specific Plugins –>

<script src="http://cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js"></script>

<script src="http://cdn.oesmith.co.uk/morris-0.4.3.min.js"></script>

<script src="js/morris/chart-data-morris.js"></script>

<script src="js/tablesorter/jquery.tablesorter.js"></script>

<script src="js/tablesorter/tables.js"></script>

</body>

</html>

Setari.php

<?

include "inc/include.php";

if(!$_SESSION['logged']){

if(!isAdmin()){

header("Location: login/");

}

}

$menu='setari';

print_R($_POST);

if(isset($_POST['update'])){

foreach($_POST as $tag=>$val){

$q=db_select('config',"name='".$tag."'",0);

if($q){

$array['value']=$val;

db_update($array,'config',"name='".$tag."'");

}else{

$array['value']=$val;

$array['name']=$tag;

db_insert($array,'config');

}

}

$error['type']='success';

$error['message']='Setarile au fost modificate.';

unset($cfg);

$cf=db_select('config');

foreach($cf as $row){

$cfg[$row['name']]=$row['value'];

}

}

?>

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="utf-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<meta name="description" content="">

<meta name="author" content="">

<title>Setari site – <?=$cfg['titlu']?></title>

<link href="css/bootstrap.css" rel="stylesheet">

<link href="css/sb-admin.css" rel="stylesheet">

<link rel="stylesheet" href="font-awesome/css/font-awesome.min.css">

<link rel="stylesheet" href="http://cdn.oesmith.co.uk/morris-0.4.3.min.css">

<link rel="icon" type="image/ico" href="favicon.ico" />

<meta name='description' content="<?=$cfg['descriere']?>"/>

<meta name='keywords' content="<?=$cfg['keywords']?>"/>

</head>

<body>

<div id="wrapper">

<?

include "inc/header.php"

?>

<div id="page-wrapper">

<div class="row">

<div class="col-lg-12">

<h1>Setari site</h1>

<ol class="breadcrumb">

<li class="active"><i class="fa fa-dashboard"></i> Acasa</li>

<li><i class="fa fa-user"></i> Setari site</li>

</ol>

</div>

</div><!– /.row –>

<div class="row">

<div class="col-lg-6">

<?

include "inc/messages.php"

?>

<form role="form" action='' method='POST'>

<div class="form-group">

<label>Titlu site</label>

<input class="form-control" name='titlu' placeholder='Nume si Prenume' value='<?=$cfg['titlu']?>' required/>

</div>

<div class="form-group">

<label>Descriere</label>

<textarea class="form-control" name='descriere' placeholder='Descriere' rows=4/><?=$cfg['descriere']?></textarea>

</div>

<div class="form-group">

<label>Cuvinte cheie</label>

<textarea class="form-control" name='keywords' placeholder='Cuv. Cheie' rows=4/><?=$cfg['keywords']?></textarea>

</div>

<button type="submit" name='update' class="btn btn-default">Modifica</button>

</form>

</div>

</div><!– /.row –>

</div><!– /#page-wrapper –>

<?

include "inc/footer.php";

?>

</div><!– /#wrapper –>

<!– JavaScript –>

<script src="js/jquery-1.10.2.js"></script>

<script src="js/bootstrap.js"></script>

<!– Page Specific Plugins –>

<script src="js/tablesorter/jquery.tablesorter.js"></script>

<script src="js/tablesorter/tables.js"></script>

</body>

</html>

Autori.php

<?

include "inc/include.php";

if(!$_SESSION['logged']){

header("Location: login/");

die();

}

$menu='autori';

?>

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="utf-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<meta name="description" content="">

<meta name="author" content="">

<title>Autori – <?=$cfg['titlu']?></title>

<link href="css/bootstrap.css" rel="stylesheet">

<link href="css/sb-admin.css" rel="stylesheet">

<link rel="stylesheet" href="font-awesome/css/font-awesome.min.css">

<link rel="stylesheet" href="http://cdn.oesmith.co.uk/morris-0.4.3.min.css">

<link rel="icon" type="image/ico" href="favicon.ico" />

<meta name='description' content="<?=$cfg['descriere']?>"/>

<meta name='keywords' content="<?=$cfg['keywords']?>"/>

</head>

<body>

<div id="wrapper">

<?include "inc/header.php"?>

<div id="page-wrapper">

<div class="row">

<div class="col-lg-12">

<h1>Autori</h1>

<ol class="breadcrumb">

<li><i class="fa fa-dashboard"></i> Acasa</li>

<li><i class="fa fa-dashboard"></i> Carti</li>

<li class="active"><i class="fa fa-dashboard"></i> Autori</li>

</ol>

</div>

</div><!– /.row –>

<div class="row">

<div class="col-lg-12">

<?

$autori=db_select('autori')or die(mysql_error());

foreach($autori as $row){

?>

<div class="col-lg-3">

<a href="cautare.php?cauta=&show=50&autor=<?=$row['id']?>"><?=$row['nume']?></a><br/>

</div>

<?}

?>

</div>

</div><!– /.row –>

</div><!– /#page-wrapper –>

<?

include "inc/footer.php";

?>

</div><!– /#wrapper –>

<!– JavaScript –>

<script src="js/jquery-1.10.2.js"></script>

<script src="js/bootstrap.js"></script>

<!– Page Specific Plugins –>

<script src="http://cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js"></script>

<script src="http://cdn.oesmith.co.uk/morris-0.4.3.min.js"></script>

<script src="js/morris/chart-data-morris.js"></script>

<script src="js/tablesorter/jquery.tablesorter.js"></script>

<script src="js/tablesorter/tables.js"></script>

</body>

</html>

Categorii.php

<?

include "inc/include.php";

if(!$_SESSION['logged']){

header("Location: login/");

die();

}

$menu='categorii';

?>

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="utf-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<meta name="description" content="">

<meta name="author" content="">

<title>Categorii – <?=$cfg['titlu']?></title>

<link href="css/bootstrap.css" rel="stylesheet">

<link href="css/sb-admin.css" rel="stylesheet">

<link rel="stylesheet" href="font-awesome/css/font-awesome.min.css">

<link rel="stylesheet" href="http://cdn.oesmith.co.uk/morris-0.4.3.min.css">

<link rel="icon" type="image/ico" href="favicon.ico" />

<meta name='description' content="<?=$cfg['descriere']?>"/>

<meta name='keywords' content="<?=$cfg['keywords']?>"/>

</head>

<body>

<div id="wrapper">

<?include "inc/header.php"?>

<div id="page-wrapper">

<div class="row">

<div class="col-lg-12">

<h1>Categorii</h1>

<ol class="breadcrumb">

<li><i class="fa fa-dashboard"></i> Acasa</li>

<li><i class="fa fa-dashboard"></i> Carti</li>

<li class="active"><i class="fa fa-dashboard"></i> Categorii</li>

</ol>

</div>

</div><!– /.row –>

<div class="row">

<div class="col-lg-12">

<?

$categorii=db_select('categorii')or die(mysql_error());

foreach($categorii as $row){

?>

<div class="col-lg-4">

<a href="cautare.php?cauta=&show=50&categorie=<?=$row['id']?>"><?=$row['nume']?></a><br/>

</div>

<?}

?>

</div>

</div><!– /.row –>

</div><!– /#page-wrapper –>

<?

include "inc/footer.php";

?>

</div><!– /#wrapper –>

<!– JavaScript –>

<script src="js/jquery-1.10.2.js"></script>

<script src="js/bootstrap.js"></script>

<!– Page Specific Plugins –>

<script src="http://cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js"></script>

<script src="http://cdn.oesmith.co.uk/morris-0.4.3.min.js"></script>

<script src="js/morris/chart-data-morris.js"></script>

<script src="js/tablesorter/jquery.tablesorter.js"></script>

<script src="js/tablesorter/tables.js"></script>

</body>

</html>

Cautare.php

<?

include "inc/include.php";

if(!$_SESSION['logged']){

header("Location: login/");

die();

}

$menu='cautare';

if($_GET['categorie'])$q.=" AND categorie='".$_GET['categorie']."'";

if($_GET['autor'])$q.=" AND autor='".$_GET['autor']."'";

$limit=$_GET['show']?$_GET['show']:100;

$rez=db_select('carti'," nume like '%".str_replace(' ','%',$_GET['nume'])."%'".$q." limit 0,".$limit)or die(mysql_error());

?>

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="utf-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<meta name="description" content="">

<meta name="author" content="">

<title>Cautare – <?=$cfg['titlu']?></title>

<link href="css/bootstrap.css" rel="stylesheet">

<link href="css/sb-admin.css" rel="stylesheet">

<link rel="stylesheet" href="font-awesome/css/font-awesome.min.css">

<link rel="stylesheet" href="http://cdn.oesmith.co.uk/morris-0.4.3.min.css">

<link rel="icon" type="image/ico" href="favicon.ico" />

<meta name='description' content="<?=$cfg['descriere']?>"/>

<meta name='keywords' content="<?=$cfg['keywords']?>"/>

</head>

<body>

<div id="wrapper">

<?

include "inc/header.php"

?>

<div id="page-wrapper">

<div class="row">

<div class="col-lg-12">

<h1>Cautare</h1>

<ol class="breadcrumb">

<li><i class="fa fa-dashboard"></i> Acasa</li>

<li><i class="fa fa-dashboard"></i> Carti</li>

<li class="active"><i class="fa fa-dashboard"></i> Cautare</li>

</ol>

</div>

</div><!– /.row –>

<div class="row">

<div class="col-lg-4">

<form role="form" action='' method='GET'>

<div class="form-group">

<label>Numele Cartii</label>

<input class="form-control" name='nume' placeholder='Introduceti numele cartii cautate' value='<?=$_GET['nume']?>'/>

</div>

<div class="form-group">

<label>Autor</label>

<select class="form-control" name='autor'>

<option value=''>Toti</option>

<?

$autori=db_select('autori','1=1',0)or die(mysql_error());

foreach($autori as $row){

if($_GET['autor']==$row['id'])$sel='selected';else $sel='';

?>

<option value='<?=$row['id']?>' <?=$sel?>><?=$row['nume']?></option>

<?}?>

</select>

</div>

<div class="form-group">

<label>Categorie</label>

<select class="form-control" name='categorie'>

<option value=''>Toate</option>

<?

$categorii=db_select('categorii','1=1',0)or die(mysql_error());

foreach($categorii as $row){

if($_GET['categorie']==$row['id'])$sel='selected';else $sel='';

?>

<option value='<?=$row['id']?>' <?=$sel?>><?=$row['nume']?></option>

<?}?>

</select>

<input type='hidden' name='cauta'/>

</div>

<div class="form-group">

<label>Afiseaza</label>

<select class="form-control" name='show'>

<option value='50' <?if($_GET['show']==50)echo"selected"?>>50</option>

<option value='100' <?if($_GET['show']==100)echo"selected"?>>100</option>

<option value='200' <?if($_GET['show']==200)echo"selected"?>>200</option>

<option value='500' <?if($_GET['show']==500)echo"selected"?>>500</option>

</select>

</div>

<button type="submit" class="btn btn-default">Cautare</button>

<button type="reset" class="btn btn-default">Reseteaza formular</button>

</form>

</div>

<?if(isset($_GET['cauta'])){?>

<div class='col-lg-8'>

<h2>Rezultatele cautarii</h2>

<div class="table-responsive">

<table class="table table-bordered table-hover table-striped tablesorter">

<thead>

<tr>

<th>ID <i class="fa fa-sort"></i></th>

<th>Nume <i class="fa fa-sort"></i></th>

<th>Categorie <i class="fa fa-sort"></i></th>

<th>Autor <i class="fa fa-sort"></i></th>

<th>Descarcari <i class="fa fa-sort"></i></th>

</tr>

</thead>

<tbody>

<?

$i=1;

foreach($rez as $row){

$cat=db_select('categorii',"id='".$row['categorie']."'",0);

$aut=db_select('autori',"id='".$row['autor']."'",0);

?>

<tr>

<td><?=$i?></td>

<td><?=$row['nume']?></td>

<td><a href='cautare.php?cauta=&show=50&categorie=<?=$cat[0]['id']?>'><?=$cat[0]['nume']?></a></td>

<td><a href='cautare.php?cauta=&show=50&autor=<?=$cat[0]['id']?>'><?=$aut[0]['nume']?></a></td>

<td>121</td>

</tr>

<?$i++;}?>

</tbody>

</table>

</div>

</div>

<?}?>

</div><!– /.row –>

</div><!– /#page-wrapper –>

<?

include "inc/footer.php";

?>

</div><!– /#wrapper –>

<!– JavaScript –>

<script src="js/jquery-1.10.2.js"></script>

<script src="js/bootstrap.js"></script>

<!– Page Specific Plugins –>

<script src="http://cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js"></script>

<script src="http://cdn.oesmith.co.uk/morris-0.4.3.min.js"></script>

<script src="js/morris/chart-data-morris.js"></script>

<script src="js/tablesorter/jquery.tablesorter.js"></script>

<script src="js/tablesorter/tables.js"></script>

</body>

</html>

Contul meu

<?

include "inc/include.php";

if(!$_SESSION['logged']){

header("Location: login/");

}

$menu='acasa';

$info=$_USER;

if(isAdmin()){

if(isset($_GET['id'])){

$u = db_select('users',"id='".$_GET['id']."'");

$info= $u[0];

}

}

if(isset($_POST['edituser'])){

$array['nume'] = $_POST['nume'];

$array['telefon'] = $_POST['telefon'];

if(isAdmin()){

$array['admin'] = $_POST['admin'];

}

if($_POST['parola']){

$array['parola']=md5($_POST['parola']);

}

if($_POST['email']){

$d = db_select('users'," email='".$_POST['email']."' and id!='".$info['id']."'");

if($d){

$error['type']='danger';

$error['message']='E-mailul este folosit de catre altcineva!';

}else{

$array['email']=$_POST['email'];

}

}

if(!$error){

db_update($array,'users',"id='".$info['id']."'");

$info['nume']=$array['nume'];

$info['email']=$array['email'];

$info['telefon']=$array['telefon'];

$info['admin']=$array['admin'];

$error['type']='success';

$error['message']='Utilizatorul a fost modificat!';

}

}

?>

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="utf-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<meta name="description" content="">

<meta name="author" content="">

<title>Editeaza Cont – <?=$cfg['titlu']?></title>

<link href="css/bootstrap.css" rel="stylesheet">

<link href="css/sb-admin.css" rel="stylesheet">

<link rel="stylesheet" href="font-awesome/css/font-awesome.min.css">

<link rel="stylesheet" href="http://cdn.oesmith.co.uk/morris-0.4.3.min.css">

<link rel="icon" type="image/ico" href="favicon.ico" />

<meta name='description' content="<?=$cfg['descriere']?>"/>

<meta name='keywords' content="<?=$cfg['keywords']?>"/>

</head>

<body>

<div id="wrapper">

<?

include "inc/header.php"

?>

<div id="page-wrapper">

<div class="row">

<div class="col-lg-12">

<h1>Editeaza cont</h1>

<ol class="breadcrumb">

<li class="active"><i class="fa fa-dashboard"></i> Acasa</li>

<li><i class="fa fa-user"></i> Editeaza Cont</li>

</ol>

</div>

</div><!– /.row –>

<div class="row">

<div class="col-lg-6">

<?

include "inc/messages.php"

?>

<form role="form" action='' method='POST'>

<div class="form-group">

<label>Nume</label>

<input class="form-control" name='nume' placeholder='Nume si Prenume' value='<?=$info['nume']?>' required/>

</div>

<div class="form-group">

<label>Parola noua</label>

<input class="form-control" name='parola' placeholder='Parola pentru login' />

</div>

<div class="form-group">

<label>Email</label>

<input class="form-control" name='email' placeholder='Email' value='<?=$info['email']?>'/>

</div>

<div class="form-group">

<label>Telefon</label>

<input class="form-control" name='telefon' placeholder='Telefon' value='<?=$info['telefon']?>'/>

</div>

<?if(isAdmin()){?>

<div class="form-group">

<label>Tip</label>

<select class="form-control" name='admin'>

<option value=''>User</option>

<option value='1' <?if($info['admin']==1){?>selected<?}?>>Administrator</option>

</select>

</div>

<?}?>

<button type="submit" name='edituser' class="btn btn-default">Modifica</button>

</form>

</div>

</div><!– /.row –>

</div><!– /#page-wrapper –>

<?

include "inc/footer.php";

?>

</div><!– /#wrapper –>

<!– JavaScript –>

<script src="js/jquery-1.10.2.js"></script>

<script src="js/bootstrap.js"></script>

<!– Page Specific Plugins –>

<script src="js/tablesorter/jquery.tablesorter.js"></script>

<script src="js/tablesorter/tables.js"></script>

</body>

</html>

Utilizatori.php

<?

include "inc/include.php";

if(!$_SESSION['logged']){

if(!isAdmin()){

header("Location: login/");

die();

}

}

$menu='utilizatori';

if(isset($_POST['adduser'])){

$array['nume'] =$_POST['nume'];

$array['username'] =$_POST['username'];

$array['parola'] =md5($_POST['parola']);

$array['email'] =$_POST['email'];

$array['telefon'] =$_POST['telefon'];

$array['admin'] =$_POST['admin'];

$d = db_select('users',"username='".$array['username']."' or email='".$array['email']."'");

if($d){

$error['type'] ='danger';

$error['message'] ='Exista deja un utilizator cu numele si parola specificate';

}

if(!$error){

db_insert($array,'users');

$error['type'] ='success';

$error['message'] ='Utilizatorul a fost adaugat';

}

}

if(isset($_GET['delete'])){

$a['id'] = $_GET['delete'];

db_delete($a,'users');

$error['type'] ='info';

$error['message'] ='Utilizatorul selectat a fost sters';

}

?>

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="utf-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<meta name="description" content="">

<meta name="author" content="">

<title>Utilizatori – <?=$cfg['titlu']?></title>

<link href="css/bootstrap.css" rel="stylesheet">

<link href="css/sb-admin.css" rel="stylesheet">

<link rel="stylesheet" href="font-awesome/css/font-awesome.min.css">

<link rel="stylesheet" href="http://cdn.oesmith.co.uk/morris-0.4.3.min.css">

<link rel="icon" type="image/ico" href="favicon.ico" />

<meta name='description' content="<?=$cfg['descriere']?>"/>

<meta name='keywords' content="<?=$cfg['keywords']?>"/>

</head>

<body>

<div id="wrapper">

<?

include "inc/header.php"

?>

<div id="page-wrapper">

<div class="row">

<div class="col-lg-12">

<h1>Utilizatori</h1>

<ol class="breadcrumb">

<li class="active"><i class="fa fa-dashboard"></i> Acasa</li>

<li><i class="fa fa-dashboard"></i> Utilizatori</li>

</ol>

</div>

</div><!– /.row –>

<div class="row">

<div class="col-lg-4">

<?

include "inc/messages.php"

?>

<form role="form" action='' method='POST'>

<div class="form-group">

<label>Nume</label>

<input class="form-control" name='nume' placeholder='Nume si Prenume' required/>

</div>

<div class="form-group">

<label>Username</label>

<input class="form-control" name='username' placeholder='Numele de utilizator' required/>

</div>

<div class="form-group">

<label>Parola</label>

<input class="form-control" name='parola' placeholder='Parola pentru login' required/>

</div>

<div class="form-group">

<label>Email</label>

<input class="form-control" name='email' placeholder='Email'/>

</div>

<div class="form-group">

<label>Telefon</label>

<input class="form-control" name='telefon' placeholder='Telefon'/>

</div>

<div class="form-group">

<label>Tip</label>

<select class="form-control" name='admin'>

<option value=''>User</option>

<option value='1'>Administrator</option>

</select>

</div>

<button type="submit" name='adduser' class="btn btn-default">Adauga Utilizator</button>

<button type="reset" class="btn btn-default">Reseteaza formular</button>

</form>

</div>

<div class='col-lg-8'>

<h2>Lista utilizatori</h2>

<div class="table-responsive">

<table class="table table-bordered table-hover table-striped tablesorter">

<thead>

<tr>

<th>Id <i class="fa fa-sort"></i></th>

<th>Nume <i class="fa fa-sort"></i></th>

<th>Username <i class="fa fa-sort"></i></th>

<th>Email <i class="fa fa-sort"></i></th>

<th>Telefon <i class="fa fa-sort"></i></th>

<th>Tip <i class="fa fa-sort"></i></th>

<th>Actiuni <i class="fa fa-sort"></i></th>

</tr>

</thead>

<tbody>

<?

$bench=db_select('users','1=1 order by admin desc')or die(mysql_error());

$i=1;

foreach($bench as $row){

?>

<tr>

<td><?=$i?></td>

<td><?=$row['nume']?></td>

<td><?=$row['username']?></td>

<td><?=$row['email']?></td>

<td><?=$row['telefon']?></td>

<td><?=(($row['admin']==1)?'Administrator':'User')?></td>

<td align='right'><a href='contulmeu.php?id=<?=$row['id']?>' title='Editare utilizator'><i class="fa fa-edit"></i></a><a href='?delete=<?=$row['id']?>' onclick="return confirm('Sunteti sigur ca doriti sa stergeti acest utilizator?')"><i class="fa fa-trash-o"></i></a></td>

</tr>

<?}?>

</tbody>

</table>

</div>

</div>

</div><!– /.row –>

</div><!– /#page-wrapper –>

<?

include "inc/footer.php";

?>

</div><!– /#wrapper –>

<!– JavaScript –>

<script src="js/jquery-1.10.2.js"></script>

<script src="js/bootstrap.js"></script>

<!– Page Specific Plugins –>

<script src="js/tablesorter/jquery.tablesorter.js"></script>

<script src="js/tablesorter/tables.js"></script>

</body>

</html>

Insert.php

<?

include "inc/include.php";

function generate_carte(){

$substantive="Casa,Masa,Calul,Prietenul,Paharul,Masa,Cireasa,Monitorul,Tabla,Elefantul,Tatarul,Ecuatia,Masina,Bicicleta,Caminul,Canapeaua,Imprimanta,Creionul,Pixul,Mapa,Foaia,Mama,Tatal,Paharul";

$adjective="fericit,suparat,trist,obosit,ratacit,aiurit,frumos,rosu,albastru,galbena,verde,prietenos";

$altecuv="alearga,fuge,plange,mananca,se supara,se intristeaza,oboseste,licentiaza";

$sub=explode(',',$substantive);

$adj=explode(',',$adjective);

$alte=explode(',',$altecuv);

return $sub[array_rand ( $sub , 1)]." ".$adj[array_rand ( $adj , 1)]." ".$alte[array_rand ( $alte , 1)];

$z=0;

for ($i=0; $i <17893 ; $i++) {

$ins['nume'] =generate_carte();

$ins['autor'] =rand(1,80);

$ins['categorie'] =rand(1,32);

$ins['fisier'] = str_replace(' ','_',strtolower($ins[nume])).".txt";

# db_insert($ins,'carti');

$z++;

}

echo $z;

Bench.php

<?

include "inc/include.php";

if(!$_SESSION['logged']){

header("Location: login/");

die();

}

?>

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="utf-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<meta name="description" content="">

<meta name="author" content="">

<title>Benchmark – eBiblioteca 1.0</title>

<link href="css/bootstrap.css" rel="stylesheet">

<link href="css/sb-admin.css" rel="stylesheet">

<link rel="stylesheet" href="font-awesome/css/font-awesome.min.css">

<link rel="stylesheet" href="http://cdn.oesmith.co.uk/morris-0.4.3.min.css">

<link rel="icon" type="image/ico" href="favicon.ico" />

</head>

<body>

<div id="wrapper">

<?

include "inc/header.php"

?>

<div id="page-wrapper">

<div class="row">

<div class="col-lg-12">

<h1>Benchmark</h1>

<ol class="breadcrumb">

<li><i class="fa fa-dashboard"></i> Acasa</li>

<li><i class="fa fa-dashboard"></i> Carti</li>

<li class="active"><i class="fa fa-dashboard"></i> Cautare</li>

</ol>

</div>

</div><!– /.row –>

<div class="row">

<div class='col-lg-12'>

<div class="table-responsive">

<table class="table table-bordered table-hover table-striped tablesorter">

<thead>

<tr>

<th>ID <i class="fa fa-sort"></i></th>

<th>Tip <i class="fa fa-sort"></i></th>

<th>Data <i class="fa fa-sort"></i></th>

<th>Hash <i class="fa fa-sort"></i></th>

<th>Query <i class="fa fa-sort"></i></th>

<th>Durata <i class="fa fa-sort"></i></th>

</tr>

</thead>

<tbody>

<?

$bench=db_select('bench','1=1 order by id desc')or die(mysql_error());

$i=1;

foreach($bench as $row){

?>

<tr>

<td><?=$i?></td>

<td><?=$row['type']?></td>

<td><?=date('d.m.Y h:i:s',$row['timestamp'])?></td>

<td><?=$row['hash']?></td>

<td><?=$row['query']?></td>

<td><?=$row['duration']?>ms</td>

</tr>

<?$i++;}?>

</tbody>

</table>

</div>

</div>

</div><!– /.row –>

</div><!– /#page-wrapper –>

</div><!– /#wrapper –>

<!– JavaScript –>

<script src="js/jquery-1.10.2.js"></script>

<script src="js/bootstrap.js"></script>

<!– Page Specific Plugins –>

<script src="js/tablesorter/jquery.tablesorter.js"></script>

<script src="js/tablesorter/tables.js"></script>

</body>

</html>

Test.php

<?

include "inc/include.php";

print_r(db_select('categorii'));

?>

Teste.php

<?

include "inc/include.php";

if(!$_SESSION['logged']){

if(!isAdmin()){

header("Location: login/");

die();

}

}

$menu='teste';

function generate_carte(){

$substantive="Casa,Masa,Calul,Prietenul,Paharul,Masa,Cireasa,Monitorul,Tabla,Elefantul,Tatarul,Ecuatia,Masina,Bicicleta,Caminul,Canapeaua,Imprimanta,Creionul,Pixul,Mapa,Foaia,Mama,Tatal,Paharul";

$adjective="fericit,suparat,trist,obosit,ratacit,aiurit,frumos,rosu,albastru,galbena,verde,prietenos";

$altecuv="alearga,fuge,plange,mananca,se supara,se intristeaza,oboseste,licentiaza";

$sub=explode(',',$substantive);

$adj=explode(',',$adjective);

$alte=explode(',',$altecuv);

return $sub[array_rand ( $sub , 1)]." ".$adj[array_rand ( $adj , 1)]." ".$alte[array_rand ( $alte , 1)];

}

if(isset($_POST['insert'])){

$z=0;

$total=0;

for ($i=0; $i <$_POST['randuri'] ; $i++) {

$ins['nume'] =generate_carte();

$ins['autor'] =rand(1,80);

$ins['categorie'] =rand(1,32);

$ins['fisier'] =str_replace(' ','_',strtolower($ins[nume])).".txt";

$starttime = microtime(true);

db_insert($ins,'carti',0);

$endtime = microtime(true);

$duration = $endtime – $starttime; //calculates total time taken

$total+=$duration;

$z++;

}

$err1['type']='success';

$err1['message']="Au fost inserate cu succes <b>".$z."</b> randuri!<br/> Interogarea a durat: ".number_format($total,4)." secunde";

add_benchmark("INSERT","Inserare ".$z." randuri",$total);

}

if(isset($_POST['update'])){

$z=0;

$total=0;

for ($i=0; $i <$_POST['randuri'] ; $i++) {

$array['content']='Continut updatata!';

$rid=rand(1,100000);

$starttime = microtime(true);

db_update($array,'carti',"id='".$rid."'",0);

$endtime = microtime(true);

$duration = $endtime – $starttime; //calculates total time taken

$total+=$duration;

$z++;

}

$err2['type']='success';

$err2['message']="Au fost updatate cu succes <b>".$z."</b> randuri!<br/> Interogarea a durat: ".number_format($total,4)." secunde";

add_benchmark("UPDATE","Update ".$z." randuri",$total);

}

if(isset($_POST['select'])){

$starttime = microtime(true);

db_select('carti',"1=1 order by id desc limit 0,".$_POST['randuri'],0);

$endtime = microtime(true);

$duration = $endtime – $starttime; //calculates total time taken

$total=$duration;

$err3['type']='success';

$err3['message']="Au fost selectate cu succes <b>".$z."</b> randuri!<br/> Interogarea a durat: ".number_format($total,4)." secunde";

add_benchmark("SELECT","Select ".$_POST['randuri']." randuri",$total);

}

?>

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="utf-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<meta name="description" content="">

<meta name="author" content="">

<title>Teste performanta – <?=$cfg['titlu']?></title>

<link href="css/bootstrap.css" rel="stylesheet">

<link href="css/sb-admin.css" rel="stylesheet">

<link rel="stylesheet" href="font-awesome/css/font-awesome.min.css">

<link rel="stylesheet" href="http://cdn.oesmith.co.uk/morris-0.4.3.min.css">

<link rel="icon" type="image/ico" href="favicon.ico" />

<meta name='description' content="<?=$cfg['descriere']?>"/>

<meta name='keywords' content="<?=$cfg['keywords']?>"/>

</head>

<body>

<div id="wrapper">

<?

include "inc/header.php"

?>

<div id="page-wrapper">

<div class="row">

<div class="col-lg-12">

<h1>Teste performanta</h1>

<ol class="breadcrumb">

<li class="active"><i class="fa fa-dashboard"></i> Acasa</li>

<li><i class="fa fa-dashboard"></i> Teste performanta</li>

</ol>

</div>

</div><!– /.row –>

<div class="row">

<div class="col-lg-4">

<div class="panel panel-primary">

<div class="panel-heading">

<h3 class="panel-title"><i class="fa fa-bar-chart-o"></i> Insert</h3>

</div>

<div class="panel-body">

<?if($err1){?>

<div class="alert alert-<?=$err1['type']?> alert-dismissable">

<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>

<?=$err1['message']?>

</div>

<?}?> <form action='' method='post'>

<div class="form-group">

<label>Randuri</label>

<select class="form-control" name='randuri'>

<?for ($i=1000; $i <25000 ; $i+=1000) { ?>

<option value='<?=$i?>'><?=number_format($i)?></option>

<? }?>

</select>

</div>

<button type="submit" name='insert' class="btn btn-success">Insereaza si afiseaza timp</button>

</form>

</div>

</div>

</div>

<div class="col-lg-4">

<div class="panel panel-primary">

<div class="panel-heading">

<h3 class="panel-title"><i class="fa fa-bar-chart-o"></i> Update</h3>

</div>

<div class="panel-body">

<?if($err2){?>

<div class="alert alert-<?=$err2['type']?> alert-dismissable">

<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>

<?=$err2['message']?>

</div>

<?}?>

<form action='' method='post'>

<div class="form-group">

<label>Randuri</label>

<select class="form-control" name='randuri'>

<?for ($i=1000; $i <25000 ; $i+=1000) { ?>

<option value='<?=$i?>'><?=number_format($i)?></option>

<? }?>

</select>

</div>

<button type="submit" name='update' class="btn btn-warning">Updateaza si afiseaza timp</button>

</form>

</div>

</div>

</div>

<div class="col-lg-4">

<div class="panel panel-primary">

<div class="panel-heading">

<h3 class="panel-title"><i class="fa fa-bar-chart-o"></i> Select</h3>

</div>

<div class="panel-body">

<?if($err3){?>

<div class="alert alert-<?=$err3['type']?> alert-dismissable">

<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>

<?=$err3['message']?>

</div>

<?}?>

<form action='' method='post'>

<div class="form-group">

<label>Randuri</label>

<select class="form-control" name='randuri'>

<?for ($i=1000; $i <25000 ; $i+=1000) { ?>

<option value='<?=$i?>'><?=number_format($i)?></option>

<? }?>

</select>

</div>

<button type="submit" name='select' class="btn btn-info">Selecteaza si afiseaza timp</button>

</form>

</div>

</div>

</div>

</div><!– /.row –>

<div class="row">

<div class="col-lg-12">

<div class="panel panel-primary">

<div class="panel-heading">

<h3 class="panel-title"><i class="fa fa-bar-chart-o"></i> Benchmark</h3>

</div>

<div class="panel-body" style='height:500px; overflow-y:auto;'>

<div class="table-responsive">

<table class="table table-bordered table-hover table-striped tablesorter">

<thead>

<tr>

<th>ID <i class="fa fa-sort"></i></th>

<th>Tip <i class="fa fa-sort"></i></th>

<th style='width:100px;'>Data <i class="fa fa-sort"></i></th>

<th>Hash <i class="fa fa-sort"></i></th>

<th>Query <i class="fa fa-sort"></i></th>

<th style='width:100px;'>Durata <i class="fa fa-sort"></i></th>

</tr>

</thead>

<tbody>

<?

$bench=db_select('bench','1=1 order by id desc limit 0,50',0)or die(mysql_error());

$i=1;

foreach($bench as $row){

if($row['type']=='UPDATE'){

$cls='warning';

}

if($row['type']=='INSERT'){

$cls='success';

}

if($row['type']=='SELECT'){

$cls='info';

}

?>

<tr class="<?=$cls?>">

<td><?=$i?></td>

<td><?=$row['type']?></td>

<td style='font-size:10px;'><?=date('d.m h:i:s',$row['timestamp'])?></td>

<td><?=$row['hash']?></td>

<td><?=$row['query']?></td>

<td><?=number_format($row['duration'],4)?> sec</td>

</tr>

<?$i++;}?>

</tbody>

</table>

</div>

</div>

</div>

</div>

</div>

</div><!– /#page-wrapper –>

<?

include "inc/footer.php";

?>

</div><!– /#wrapper –>

<!– JavaScript –>

<script src="js/jquery-1.10.2.js"></script>

<script src="js/bootstrap.js"></script>

<!– Page Specific Plugins –>

<script src="js/tablesorter/jquery.tablesorter.js"></script>

<script src="js/tablesorter/tables.js"></script>

</body>

</html>

Login.php

<?

include "../inc/include.php";

if(isset($_GET['logout'])){

unset($_SESSION['logged'],$_SESSION['user_id']);

}

if(isset($_POST['submit'])){

$u = db_select('users',"username='".$_POST['username']."' and parola='".md5($_POST['parola'])."'");

if(!$u){

$error=1;

}else{

$_SESSION['logged']=1;

$_SESSION['user_id']=$u[0]['id'];

header("Location:../");

}

}

?>

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8">

<meta http-equiv="X-UA-Compatible" content="IE=edge">

<title>eBiblioteca Login</title>

<link rel="stylesheet" href="style/style.css"/>

</head>

<body>

<div style='position:absolute; width:450px; left:50%; margin-left:-225px; height:60px; margin-top:20px;'>

<?if($error){?>

<div class="error alert-message">

<a href="#" class="close">✘</a>

<p>Datele de login sunt gresite!</p>

</div>

<?}?>

</div>

<div id="container">

<div id="titlu">eBiblioteca Login</div>

<form action="" method='post'>

<center><img src="style/logo-login.png" alt=""></center>

<input type="text" class='text' name='username' placeholder='Username:'/>

<input type="password" class='text' name='parola' placeholder='Parola:'/>

<button type='submit' name='submit' class='button'>AUTENTIFICARE</button>

</form>

</div>

</body>

</html>

Similar Posts