sql >> Database teknologi >  >> RDS >> MariaDB

Kørsel af en MariaDB Galera Cluster uden Orchestration Tools - DB Container Management:Anden del

Som vi så i den første del af denne blog, spiller en stærkt konsistent databaseklynge som Galera ikke godt med containerorkestreringsværktøjer som Kubernetes eller Swarm. Vi viste dig, hvordan du implementerer Galera og konfigurerer processtyring til Docker, så du bevarer fuld kontrol over adfærden. Dette blogindlæg er en fortsættelse af, at vi skal se på drift og vedligeholdelse af klyngen.

For at opsummere nogle af hovedpunkterne fra del 1 af denne blog, implementerede vi en Galera-klynge med tre knudepunkter med ProxySQL og Keepalved på tre forskellige Docker-værter, hvor alle MariaDB-forekomster kører som Docker-containere. Følgende diagram illustrerer den endelige implementering:

Graceful nedlukning

For at udføre en yndefuld MySQL-nedlukning er den bedste måde at sende SIGTERM (signal 15) til containeren:

$ docker kill -s 15 {db_container_name}

Hvis du gerne vil lukke klyngen ned, skal du gentage kommandoen ovenfor på alle databasecontainere, en node ad gangen. Ovenstående svarer til at udføre "systemctl stop mysql" i systemd service for MariaDB. Brug af kommandoen "docker stop" er ret risikabelt for databasetjenesten, fordi den venter i 10 sekunders timeout, og Docker vil tvinge SIGKILL, hvis denne varighed overskrides (medmindre du bruger en ordentlig --timeout værdi).

Den sidste node, der lukker ned, vil have seqno ikke lig med -1 og safe_to_bootstrap flag er sat til 1 i /{datadir volume}/grastate.dat for Docker-værten, for eksempel på vært2:

$ cat /containers/mariadb2/datadir/grastate.dat
# GALERA saved state
version: 2.1
uuid:    e70b7437-645f-11e8-9f44-5b204e58220b
seqno:   7099
safe_to_bootstrap: 1

Detektering af den mest avancerede node

Hvis klyngen ikke lukkede elegant ned, eller knudepunktet, som du forsøgte at bootstrap, ikke var den sidste knude, der forlod klyngen, ville du sandsynligvis ikke være i stand til at bootstrap en af ​​Galera-knuderne og kan støde på følgende fejl :

2016-11-07 01:49:19 5572 [ERROR] WSREP: It may not be safe to bootstrap the cluster from this node.
It was not the last one to leave the cluster and may not contain all the updates.
To force cluster bootstrap with this node, edit the grastate.dat file manually and set safe_to_bootstrap to 1 .

Galera ærer noden, der har safe_to_bootstrap flag sat til 1 som den første referenceknude. Dette er den sikreste måde at undgå datatab og sikre, at den korrekte node altid bliver bootstrappet.

Hvis du fik fejlen, skal vi først finde ud af den mest avancerede node, før vi samler noden op som den første, der skal bootstrappes. Opret en forbigående beholder (med --rm flag), tilknytte den til samme datadir og konfigurationsmappe i den faktiske databasebeholder med to MySQL-kommandoflag, --wsrep_recover og --wsrep_cluster_address . Hvis vi f.eks. ønsker at kende mariadb1's sidste forpligtede nummer, skal vi køre:

$ docker run --rm --name mariadb-recover \
        --env MYSQL_ROOT_PASSWORD="PM7%[email protected]^1" \
        --volume /containers/mariadb1/datadir:/var/lib/mysql \
        --volume /containers/mariadb1/conf.d:/etc/mysql/conf.d \
        mariadb:10.2.15 \
        --wsrep_recover \
        --wsrep_cluster_address=gcomm://
2018-06-12  4:46:35 139993094592384 [Note] mysqld (mysqld 10.2.15-MariaDB-10.2.15+maria~jessie) starting as process 1 ...
2018-06-12  4:46:35 139993094592384 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins
...
2018-06-12  4:46:35 139993094592384 [Note] Plugin 'FEEDBACK' is disabled.
2018-06-12  4:46:35 139993094592384 [Note] Server socket created on IP: '::'.
2018-06-12  4:46:35 139993094592384 [Note] WSREP: Recovered position: e70b7437-645f-11e8-9f44-5b204e58220b:7099

Den sidste linje er, hvad vi leder efter. MariaDB udskriver klyngens UUID og sekvensnummeret for den senest begåede transaktion. Den node, der har det højeste antal, anses for at være den mest avancerede node. Siden vi specificerede --rm , fjernes beholderen automatisk, når den forlades. Gentag ovenstående trin på hver Docker-vært ved at erstatte --volumen stien til de respektive databasebeholdervolumener.

Når du har sammenlignet værdien rapporteret af alle databasecontainere og besluttet, hvilken container der er den mest opdaterede node, skal du ændre safe_to_bootstrap flag til 1 inde i /{datadir volume}/grastate.dat manuelt. Lad os sige, at alle noder rapporterer det samme nøjagtige sekvensnummer, vi kan bare vælge at mariadb3 skal bootstrappes ved at ændre safe_to_bootstrap værdi til 1:

$ vim /containers/mariadb3/datadir/grasate.dat
...
safe_to_bootstrap: 1

Gem filen, og start med at bootstrapping af klyngen fra den node, som beskrevet i næste kapitel.

Opstart af klyngen

Bootstrapping af klyngen svarer til den første docker run-kommando, vi brugte, da vi startede klyngen op for første gang. Hvis mariadb1 er den valgte bootstrap node, kan vi blot køre den oprettede bootstrap container igen:

$ docker start mariadb0 # on host1

Ellers, hvis bootstrap-beholderen ikke eksisterer på den valgte node, lad os sige på host2, kør bootstrap-beholderkommandoen og kortlæg de eksisterende mariadb2's volumener. Vi bruger mariadb0 som containernavnet på host2 for at indikere, at det er en bootstrap container:

$ docker run -d \
        --name mariadb0 \
        --hostname mariadb0.weave.local \
        --net weave \
        --publish "3306" \
        --publish "4444" \
        --publish "4567" \
        --publish "4568" \
        $(weave dns-args) \
        --env MYSQL_ROOT_PASSWORD="PM7%[email protected]^1" \
        --volume /containers/mariadb2/datadir:/var/lib/mysql \
        --volume /containers/mariadb2/conf.d:/etc/mysql/mariadb.conf.d \
        mariadb:10.2.15 \
        --wsrep_cluster_address=gcomm:// \
        --wsrep_sst_auth="root:PM7%[email protected]^1" \
        --wsrep_node_address=mariadb0.weave.local

Du bemærker måske, at denne kommando er lidt kortere sammenlignet med den tidligere bootstrap-kommando beskrevet i denne vejledning. Da vi allerede har proxysql-brugeren oprettet i vores første bootstrap-kommando, kan vi springe disse to miljøvariabler over:

  • --env MYSQL_USER=proxysql
  • --env MYSQL_PASSWORD=proxysqlpassword

Start derefter de resterende MariaDB-beholdere, fjern bootstrap-beholderen og start den eksisterende MariaDB-beholder på den bootstrappede vært. Grundlæggende vil rækkefølgen af ​​kommandoer være:

$ docker start mariadb1 # on host1
$ docker start mariadb3 # on host3
$ docker stop mariadb0 # on host2
$ docker start mariadb2 # on host2

På dette tidspunkt startes klyngen og kører med fuld kapacitet.

Ressourcekontrol

Hukommelse er en meget vigtig ressource i MySQL. Det er her bufferne og cacherne er gemt, og det er afgørende for MySQL at reducere virkningen af ​​at ramme disken for ofte. På den anden side er bytte dårligt for MySQL-ydeevnen. Som standard vil der ikke være nogen ressourcebegrænsninger på de kørende containere. Containere bruger så meget af en given ressource, som værtens kerne tillader. En anden vigtig ting er grænse for filbeskrivelser. Du kan øge grænsen for åben filbeskrivelse eller "nofile" til noget højere for at tage højde for antallet af filer, MySQL-serveren kan åbne samtidigt. Det skader ikke at indstille dette til en høj værdi.

For at begrænse hukommelsesallokering og øge fildeskriptorgrænsen til vores databasebeholder, ville man tilføje --hukommelse , --hukommelse-swap og --ulimit parametre ind i kommandoen "docker run":

$ docker kill -s 15 mariadb1
$ docker rm -f mariadb1
$ docker run -d \
        --name mariadb1 \
        --hostname mariadb1.weave.local \
        --net weave \
        --publish "3306:3306" \
        --publish "4444" \
        --publish "4567" \
        --publish "4568" \
        $(weave dns-args) \
        --memory 16g \
        --memory-swap 16g \
        --ulimit nofile:16000:16000 \
        --env MYSQL_ROOT_PASSWORD="PM7%[email protected]^1" \
        --volume /containers/mariadb1/datadir:/var/lib/mysql \
        --volume /containers/mariadb1/conf.d:/etc/mysql/mariadb.conf.d \
        mariadb:10.2.15 \
        --wsrep_cluster_address=gcomm://mariadb0.weave.local,mariadb1.weave.local,mariadb2.weave.local,mariadb3.weave.local \
        --wsrep_sst_auth="root:PM7%[email protected]^1" \
        --wsrep_node_address=mariadb1.weave.local

Vær opmærksom på, at hvis --memory-swap er indstillet til samme værdi som --hukommelse og --hukommelse er indstillet til et positivt heltal, vil beholderen ikke have adgang til at bytte. Hvis --hukommelse-swap ikke er indstillet, vil containerbytning som standard være --hukommelse gange med 2. Hvis --hukommelse og --hukommelse-swap er indstillet til samme værdi, vil dette forhindre containere i at bruge nogen swap. Dette er fordi --hukommelse-swap er mængden af ​​kombineret hukommelse og swap, der kan bruges, mens --hukommelse er kun mængden af ​​fysisk hukommelse, der kan bruges.

Nogle af containerressourcerne som hukommelse og CPU kan styres dynamisk via kommandoen "docker update", som vist i følgende eksempel for at opgradere hukommelsen for container mariadb1 til 32G på farten:

$ docker update \
    --memory 32g \
    --memory-swap 32g \
    mariadb1

Glem ikke at tune my.cnf i overensstemmelse hermed, så den passer til de nye specifikationer. Konfigurationsstyring forklares i næste afsnit.

Konfigurationsstyring

De fleste af MySQL/MariaDB-konfigurationsparametrene kan ændres under kørsel, hvilket betyder, at du ikke behøver at genstarte for at anvende ændringerne. Se MariaDB-dokumentationssiden for detaljer. Parameteren angivet med "Dynamisk:Ja" betyder, at variablen indlæses umiddelbart efter ændring, uden at det er nødvendigt at genstarte MariaDB-serveren. Ellers skal du indstille parametrene i den brugerdefinerede konfigurationsfil i Docker-værten. Foretag f.eks. ændringerne i følgende fil på mariadb3:

$ vim /containers/mariadb3/conf.d/my.cnf

Og genstart derefter databasebeholderen for at anvende ændringen:

$ docker restart mariadb3

Bekræft, at containeren starter processen ved at se på docker-logfilerne. Udfør denne handling på én node ad gangen, hvis du ønsker at foretage ændringer i hele klyngen.

Sikkerhedskopi

At tage en logisk backup er ret ligetil, fordi MariaDB-billedet også kommer med mysqldump binær. Du bruger blot kommandoen "docker exec" til at køre mysqldump og sende output til en fil i forhold til værtsstien. Følgende kommando udfører mysqldump backup på mariadb2 og gemmer den til /backups/mariadb2 inde i host2:

$ docker exec -it mariadb2 mysqldump -uroot -p --single-transaction > /backups/mariadb2/dump.sql

Binær backup som Percona Xtrabackup eller MariaDB Backup kræver processen for at få direkte adgang til MariaDB-datamappen. Du skal enten installere dette værktøj inde i containeren eller gennem maskinens vært eller bruge et dedikeret billede til dette formål, såsom "perconalab/percona-xtrabackup" billede for at oprette sikkerhedskopien og gemt den inde i /tmp/backup på Docker værten:

$ docker run --rm -it \
    -v /containers/mariadb2/datadir:/var/lib/mysql \
    -v /tmp/backup:/xtrabackup_backupfiles \
    perconalab/percona-xtrabackup \
    --backup --host=mariadb2 --user=root --password=mypassword

Du kan også stoppe containeren med innodb_fast_shutdown sæt til 0 og kopier over datadir-volumen til en anden placering i den fysiske vært:

$ docker exec -it mariadb2 mysql -uroot -p -e 'SET GLOBAL innodb_fast_shutdown = 0'
$ docker kill -s 15 mariadb2
$ cp -Rf /containers/mariadb2/datadir /backups/mariadb2/datadir_copied
$ docker start mariadb2

Gendan

Gendannelse er ret ligetil for mysqldump. Du kan blot omdirigere stdin'et til containeren fra den fysiske vært:

$ docker exec -it mariadb2 mysql -uroot -p < /backups/mariadb2/dump.sql

Du kan også bruge standard mysql klient kommandolinje eksternt med korrekt værtsnavn og portværdi i stedet for at bruge denne "docker exec" kommando:

$ mysql -uroot -p -h127.0.0.1 -P3306 < /backups/mariadb2/dump.sql

For Percona Xtrabackup og MariaDB Backup skal vi forberede sikkerhedskopien på forhånd. Dette vil rulle sikkerhedskopien frem til det tidspunkt, hvor sikkerhedskopieringen var færdig. Lad os sige, at vores Xtrabackup-filer er placeret under /tmp/backup af Docker-værten, for at forberede det, skal du blot:

$ docker run --rm -it \
    -v mysql-datadir:/var/lib/mysql \
    -v /tmp/backup:/xtrabackup_backupfiles \
    perconalab/percona-xtrabackup \
    --prepare --target-dir /xtrabackup_backupfiles

Den forberedte sikkerhedskopi under /tmp/backup af Docker-værten kan derefter bruges som MariaDB datadir til en ny container eller klynge. Lad os sige, at vi bare vil verificere gendannelse på en selvstændig MariaDB-container, vi ville køre:

$ docker run -d \
    --name mariadb-restored \
    --env MYSQL_ROOT_PASSWORD="PM7%[email protected]^1" \
    -v /tmp/backup:/var/lib/mysql \
    mariadb:10.2.15

Hvis du udførte en sikkerhedskopiering ved hjælp af stop og kopi-tilgang, kan du blot duplikere datadirigenten og bruge den duplikerede mappe som et volumen maps til MariaDB datadir for at køre på en anden container. Lad os sige, at sikkerhedskopien blev kopieret under /backups/mariadb2/datadir_copied, vi kan køre en ny container ved at køre:

$ mkdir -p /containers/mariadb-restored/datadir
$ cp -Rf /backups/mariadb2/datadir_copied /containers/mariadb-restored/datadir
$ docker run -d \
    --name mariadb-restored \
    --env MYSQL_ROOT_PASSWORD="PM7%[email protected]^1" \
    -v /containers/mariadb-restored/datadir:/var/lib/mysql \
    mariadb:10.2.15

MYSQL_ROOT_PASSWORD skal matche den faktiske root-adgangskode for den pågældende sikkerhedskopi.

Severalnines MySQL på Docker:Sådan containeriserer du din databaseOpdag alt hvad du behøver at forstå, når du overvejer at køre en MySQL-tjeneste oven på Docker containervirtualiseringDownload hvidbogen

Opgradering af databaseversion

Der er to typer opgradering - in-place opgradering eller logisk opgradering.

Opgradering på stedet involverer at lukke MariaDB-serveren ned, erstatte de gamle binære filer med de nye binære filer og derefter starte serveren på den gamle datamappe. Når du er startet, skal du køre mysql_upgrade script til at kontrollere og opgradere alle systemtabeller og også til at kontrollere brugertabellerne.

Den logiske opgradering involverer eksport af SQL fra den aktuelle version ved hjælp af et logisk sikkerhedskopieringsværktøj såsom mysqldump, kørsel af den nye container med de opgraderede versionsbinære filer og derefter anvendelse af SQL til den nye MySQL/MariaDB-version. Det ligner sikkerhedskopierings- og gendannelsesmetoden beskrevet i det foregående afsnit.

Ikke desto mindre er det en god tilgang altid at tage backup af din database, før du udfører nogen destruktive handlinger. Følgende trin er påkrævet, når du opgraderer fra det aktuelle billede, MariaDB 10.1.33 til en anden større version, MariaDB 10.2.15 på mariadb3 ligger på vært3:

  1. Sikkerhedskopier databasen. Det er lige meget fysisk eller logisk backup, men sidstnævnte ved hjælp af mysqldump anbefales.

  2. Download det seneste billede, som vi gerne vil opgradere til:

    $ docker pull mariadb:10.2.15
  3. Indstil innodb_fast_shutdown til 0 for vores databasebeholder:

    $ docker exec -it mariadb3 mysql -uroot -p -e 'SET GLOBAL innodb_fast_shutdown = 0'
  4. Luk ned for databasebeholderen:

    $ docker kill --signal=TERM mariadb3
  5. Opret en ny container med det nye billede til vores databasecontainer. Hold resten af ​​parametrene intakte undtagen at bruge det nye containernavn (ellers ville det være i konflikt):

    $ docker run -d \
            --name mariadb3-new \
            --hostname mariadb3.weave.local \
            --net weave \
            --publish "3306:3306" \
            --publish "4444" \
            --publish "4567" \
            --publish "4568" \
            $(weave dns-args) \
            --env MYSQL_ROOT_PASSWORD="PM7%[email protected]^1" \
            --volume /containers/mariadb3/datadir:/var/lib/mysql \
            --volume /containers/mariadb3/conf.d:/etc/mysql/mariadb.conf.d \
            mariadb:10.2.15 \
            --wsrep_cluster_address=gcomm://mariadb0.weave.local,mariadb1.weave.local,mariadb2.weave.local,mariadb3.weave.local \
            --wsrep_sst_auth="root:PM7%[email protected]^1" \
            --wsrep_node_address=mariadb3.weave.local
  6. Kør mysql_upgrade script:

    $ docker exec -it mariadb3-new mysql_upgrade -uroot -p
  7. Hvis der ikke opstod nogen fejl, skal du fjerne den gamle beholder, mariadb3 (den nye er mariadb3-ny):

    $ docker rm -f mariadb3
  8. Ellers, hvis opgraderingsprocessen mislykkes i mellemtiden, kan vi falde tilbage til den forrige container:

    $ docker stop mariadb3-new
    $ docker start mariadb3

Større versionsopgradering kan udføres på samme måde som den mindre versionsopgradering, bortset fra at du skal huske på, at MySQL/MariaDB kun understøtter større opgradering fra den tidligere version. Hvis du er på MariaDB 10.0 og gerne vil opgradere til 10.2, skal du først opgradere til MariaDB 10.1 efterfulgt af endnu et opgraderingstrin til MariaDB 10.2.

Vær opmærksom på de konfigurationsændringer, der introduceres og udfases mellem større versioner.

Failover

I Galera er alle noder mestre og har den samme rolle. Med ProxySQL på billedet vil forbindelser, der passerer gennem denne gateway, blive fejlet automatisk, så længe der er en primær komponent, der kører for Galera Cluster (det vil sige, at størstedelen af ​​noderne er oppe). Applikationen vil ikke bemærke nogen forskel, hvis en databasenode går ned, fordi ProxySQL blot vil omdirigere forbindelserne til de andre tilgængelige noder.

Hvis applikationen forbinder direkte til MariaDB'en uden om ProxySQL, skal failover udføres på applikationssiden ved at pege på den næste tilgængelige knude, forudsat at databasenoden opfylder følgende betingelser:

  • Status wsrep_local_state_comment er synkroniseret (tilstanden "Afsynkroniseret/donor" er også mulig, kun hvis wsrep_sst_method er xtrabackup, xtrabackup-v2 eller mariabackup).
  • Status wsrep_cluster_status er Primær.

I Galera betyder en tilgængelig node ikke, at den er sund, før ovenstående status er bekræftet.

Udskalering

For at udskalere kan vi oprette en ny container i det samme netværk og bruge den samme brugerdefinerede konfigurationsfil til den eksisterende container på den pågældende vært. Lad os f.eks. sige, at vi vil tilføje den fjerde MariaDB-container på host3, vi kan bruge den samme konfigurationsfil monteret til mariadb3, som illustreret i følgende diagram:

Kør følgende kommando på host3 for at skalere ud:

$ docker run -d \
        --name mariadb4 \
        --hostname mariadb4.weave.local \
        --net weave \
        --publish "3306:3307" \
        --publish "4444" \
        --publish "4567" \
        --publish "4568" \
        $(weave dns-args) \
        --env MYSQL_ROOT_PASSWORD="PM7%[email protected]^1" \
        --volume /containers/mariadb4/datadir:/var/lib/mysql \
        --volume /containers/mariadb3/conf.d:/etc/mysql/mariadb.conf.d \
        mariadb:10.2.15 \
        --wsrep_cluster_address=gcomm://mariadb1.weave.local,mariadb2.weave.local,mariadb3.weave.local,mariadb4.weave.local \
        --wsrep_sst_auth="root:PM7%[email protected]^1" \
        --wsrep_node_address=mariadb4.weave.local

Når containeren er oprettet, slutter den sig til klyngen og udfører SST. Den kan tilgås på port 3307 eksternt eller uden for Weave-netværket, eller port 3306 inden for værten eller inden for Weave-netværket. Det er ikke nødvendigt at inkludere mariadb0.weave.local i klyngeadressen længere. Når klyngen er skaleret ud, skal vi tilføje den nye MariaDB-container til ProxySQL-belastningsbalanceringssættet via administrationskonsollen:

$ docker exec -it proxysql1 mysql -uadmin -padmin -P6032
mysql> INSERT INTO mysql_servers(hostgroup_id,hostname,port) VALUES (10,'mariadb4.weave.local',3306);
mysql> INSERT INTO mysql_servers(hostgroup_id,hostname,port) VALUES (20,'mariadb4.weave.local',3306);
mysql> LOAD MYSQL SERVERS TO RUNTIME;
mysql> SAVE MYSQL SERVERS TO DISK;

Gentag ovenstående kommandoer på den anden ProxySQL-instans.

Til sidst til det sidste trin, (du kan springe denne del over, hvis du allerede har kørt "SAVE .. TO DISK"-sætningen i ProxySQL), tilføj følgende linje i proxysql.cnf for at gøre den vedvarende på tværs af containergenstart på vært1 og vært2:

$ vim /containers/proxysql1/proxysql.cnf # host1
$ vim /containers/proxysql2/proxysql.cnf # host2

Og tilføj mariadb4-relaterede linjer under mysql_server-direktivet:

mysql_servers =
(
        { address="mariadb1.weave.local" , port=3306 , hostgroup=10, max_connections=100 },
        { address="mariadb2.weave.local" , port=3306 , hostgroup=10, max_connections=100 },
        { address="mariadb3.weave.local" , port=3306 , hostgroup=10, max_connections=100 },
        { address="mariadb4.weave.local" , port=3306 , hostgroup=10, max_connections=100 },
        { address="mariadb1.weave.local" , port=3306 , hostgroup=20, max_connections=100 },
        { address="mariadb2.weave.local" , port=3306 , hostgroup=20, max_connections=100 },
        { address="mariadb3.weave.local" , port=3306 , hostgroup=20, max_connections=100 },
        { address="mariadb4.weave.local" , port=3306 , hostgroup=20, max_connections=100 }
)

Gem filen, og vi skulle være gode ved næste containergenstart.

Nedskalering

For at nedskalere, lukker du blot beholderen ned. Den bedste kommando ville være:

$ docker kill -s 15 mariadb4
$ docker rm -f mariadb4

Husk, at hvis databasenoden forlod klyngen ungerligt, var det ikke en del af nedskaleringen og ville påvirke kvorumsberegningen.

For at fjerne containeren fra ProxySQL skal du køre følgende kommandoer på begge ProxySQL-containere. For eksempel på proxysql1:

$ docker exec -it proxysql1 mysql -uadmin -padmin -P6032
mysql> DELETE FROM mysql_servers WHERE hostname="mariadb4.weave.local";
mysql> LOAD MYSQL SERVERS TO RUNTIME;
mysql> SAVE MYSQL SERVERS TO DISK;

Du kan derefter enten fjerne den tilsvarende post inde i proxysql.cnf eller bare lade den være sådan. Det vil alligevel blive registreret som OFFLINE fra ProxySQL-synspunkt.

Oversigt

Med Docker bliver tingene lidt anderledes end den konventionelle måde at håndtere MySQL- eller MariaDB-servere på. Håndtering af statelige tjenester som Galera Cluster er ikke så let som statsløse applikationer og kræver ordentlig test og planlægning.

I vores næste blog om dette emne vil vi evaluere fordele og ulemper ved at køre Galera Cluster på Docker uden nogen orkestreringsværktøjer.


  1. Hvordan kan jeg forhindre SQL-injektion i PHP?

  2. Fejl ved omdøbning af en kolonne i MySQL

  3. Automatisk stigning i tabelkolonnen

  4. PostgreSQL 9.3:Dynamisk pivottabel