sql >> Database teknologi >  >> RDS >> Mysql

Forbindelseshåndtering og drosling med ProxySQL

Evnen til at forme den trafik, der går til databasen, er en af ​​de vigtigste. I de sidste dage havde du ikke så meget kontrol over det - applikationer sendte trafikken til databasen, og det er om det. HAProxy, som var almindeligt anvendt, har heller ikke mulighed for finkornet kontrol over trafikken. Med introduktionen af ​​de SQL-bevidste proxyer, som ProxySQL, blev flere muligheder tilgængelige for databaseadministratorer. Lad os tage et kig på forbindelseshåndteringen og reguleringsmulighederne i ProxySQL.

Forbindelseshåndtering i ProxySQL

Som du måske ved, er den måde, ProxySQL fungerer på, gennem forespørgselsreglerne. Det er en liste over regler, som hver forespørgsel testes i forhold til, og som styrer præcis, hvordan ProxySQL vil håndtere forespørgslen. Startende fra begyndelsen opretter applikationen forbindelse til ProxySQL. Det vil autentificere mod ProxySQL (det er derfor, ProxySQL skal gemme alle brugere og kodeords-hash) og derefter vil ProxySQL køre det gennem forespørgselsreglerne for at bestemme, hvilken værtsgruppe forespørgslen skal sendes til.

ProxySQL åbner en pulje af forbindelser til backend-serverne. Det er ikke 1-til-1 kortlægning, som standard forsøger det at genbruge en backend-forbindelse til så mange frontend-forbindelser som muligt. Dette kaldes forbindelsesmultipleksing. Detaljer afhænger af den nøjagtige trafik, som den skal håndtere. Hver åben transaktion skal håndteres inden for samme forbindelse. Hvis der er defineret en slags lokal variabel, kan denne forbindelse ikke genbruges. At være i stand til at genbruge en enkelt backend-forbindelse med flere frontend-forbindelser reducerer betydeligt byrden på backend-databasen.

Når forbindelsen er oprettet til ProxySQL, som vi nævnte før, vil den blive behandlet i henhold til forespørgselsreglerne. Her kan trafikformningen finde sted. Lad os tage et kig på mulighederne

Forbindelsesregulering i ProxySQL

Først, lad os bare droppe alle SELECT. Vi kører vores "applikation", Sysbench, på følgende måde:

[email protected]:~# sysbench /root/sysbench/src/lua/oltp_read_only.lua --threads=4 --events=200 --time=0 --mysql-host=10.0.0.101 --mysql-user=sbtest --mysql-password=sbtest --mysql-port=6033 --tables=32 --report-interval=1 --skip-trx=on --table-size=100000 --db-ps-mode=disable --rate=10 run

sysbench 1.1.0-bbee5d5 (using bundled LuaJIT 2.1.0-beta3)



Running the test with following options:

Number of threads: 4

Target transaction rate: 10/sec

Report intermediate results every 1 second(s)

Initializing random number generator from current time




Initializing worker threads...



Threads started!



[ 1s ] thds: 4 tps: 5.97 qps: 103.49 (r/w/o: 103.49/0.00/0.00) lat (ms,95%): 244.38 err/s: 0.00 reconn/s: 0.00

[ 1s ] queue length: 0, concurrency: 4

[ 2s ] thds: 4 tps: 13.02 qps: 181.32 (r/w/o: 181.32/0.00/0.00) lat (ms,95%): 580.02 err/s: 0.00 reconn/s: 0.00

[ 2s ] queue length: 5, concurrency: 4

[ 3s ] thds: 4 tps: 14.99 qps: 228.81 (r/w/o: 228.81/0.00/0.00) lat (ms,95%): 669.89 err/s: 0.00 reconn/s: 0.00

[ 3s ] queue length: 1, concurrency: 4

[ 4s ] thds: 4 tps: 16.99 qps: 232.88 (r/w/o: 232.88/0.00/0.00) lat (ms,95%): 350.33 err/s: 0.00 reconn/s: 0.00

[ 4s ] queue length: 0, concurrency: 3

[ 5s ] thds: 4 tps: 8.99 qps: 99.91 (r/w/o: 99.91/0.00/0.00) lat (ms,95%): 369.77 err/s: 0.00 reconn/s: 0.00

[ 5s ] queue length: 0, concurrency: 1

[ 6s ] thds: 4 tps: 3.99 qps: 55.81 (r/w/o: 55.81/0.00/0.00) lat (ms,95%): 147.61 err/s: 0.00 reconn/s: 0.00

[ 6s ] queue length: 0, concurrency: 1

[ 7s ] thds: 4 tps: 11.06 qps: 162.89 (r/w/o: 162.89/0.00/0.00) lat (ms,95%): 173.58 err/s: 0.00 reconn/s: 0.00

[ 7s ] queue length: 0, concurrency: 2

[ 8s ] thds: 4 tps: 7.99 qps: 112.88 (r/w/o: 112.88/0.00/0.00) lat (ms,95%): 200.47 err/s: 0.00 reconn/s: 0.00

[ 8s ] queue length: 0, concurrency: 2

[ 9s ] thds: 4 tps: 9.01 qps: 110.09 (r/w/o: 110.09/0.00/0.00) lat (ms,95%): 71.83 err/s: 0.00 reconn/s: 0.00

[ 9s ] queue length: 0, concurrency: 0

[ 10s ] thds: 4 tps: 9.99 qps: 143.87 (r/w/o: 143.87/0.00/0.00) lat (ms,95%): 153.02 err/s: 0.00 reconn/s: 0.00

[ 10s ] queue length: 0, concurrency: 1

[ 11s ] thds: 4 tps: 12.02 qps: 177.28 (r/w/o: 177.28/0.00/0.00) lat (ms,95%): 170.48 err/s: 0.00 reconn/s: 0.00

[ 11s ] queue length: 0, concurrency: 1

[ 12s ] thds: 4 tps: 5.00 qps: 70.95 (r/w/o: 70.95/0.00/0.00) lat (ms,95%): 231.53 err/s: 0.00 reconn/s: 0.00

[ 12s ] queue length: 0, concurrency: 2

[ 13s ] thds: 4 tps: 10.00 qps: 137.01 (r/w/o: 137.01/0.00/0.00) lat (ms,95%): 223.34 err/s: 0.00 reconn/s: 0.00

[ 13s ] queue length: 0, concurrency: 1

[ 14s ] thds: 4 tps: 11.01 qps: 143.14 (r/w/o: 143.14/0.00/0.00) lat (ms,95%): 130.13 err/s: 0.00 reconn/s: 0.00

[ 14s ] queue length: 0, concurrency: 0

[ 15s ] thds: 4 tps: 5.00 qps: 100.99 (r/w/o: 100.99/0.00/0.00) lat (ms,95%): 297.92 err/s: 0.00 reconn/s: 0.00

[ 15s ] queue length: 0, concurrency: 4

[ 16s ] thds: 4 tps: 10.98 qps: 122.82 (r/w/o: 122.82/0.00/0.00) lat (ms,95%): 344.08 err/s: 0.00 reconn/s: 0.00

[ 16s ] queue length: 0, concurrency: 0

[ 17s ] thds: 4 tps: 3.00 qps: 59.01 (r/w/o: 59.01/0.00/0.00) lat (ms,95%): 287.38 err/s: 0.00 reconn/s: 0.00

[ 17s ] queue length: 0, concurrency: 2

[ 18s ] thds: 4 tps: 13.01 qps: 165.14 (r/w/o: 165.14/0.00/0.00) lat (ms,95%): 173.58 err/s: 0.00 reconn/s: 0.00

[ 18s ] queue length: 0, concurrency: 0

[ 19s ] thds: 4 tps: 6.99 qps: 98.79 (r/w/o: 98.79/0.00/0.00) lat (ms,95%): 253.35 err/s: 0.00 reconn/s: 0.00

[ 19s ] queue length: 0, concurrency: 1

[ 20s ] thds: 4 tps: 9.98 qps: 164.60 (r/w/o: 164.60/0.00/0.00) lat (ms,95%): 590.56 err/s: 0.00 reconn/s: 0.00

[ 20s ] queue length: 0, concurrency: 3

SQL statistics:

    queries performed:

        read:                            2800

        write:                           0

        other:                           0

        total:                           2800

    transactions:                        200    (9.64 per sec.)

    queries:                             2800   (134.89 per sec.)

    ignored errors:                      0      (0.00 per sec.)

    reconnects:                          0      (0.00 per sec.)



Throughput:

    events/s (eps):                      9.6352

    time elapsed:                        20.7573s

    total number of events:              200



Latency (ms):

         min:                                   44.36

         avg:                                  202.66

         max:                                  726.59

         95th percentile:                      590.56

         sum:                                40531.73



Threads fairness:

    events (avg/stddev):           50.0000/0.71

    execution time (avg/stddev):   10.1329/0.05

Det er en fuldstændig skrivebeskyttet trafik, den skal i gennemsnit have 10 transaktioner (140 forespørgsler) pr. sekund. Da det kun er SELECT'er, kan vi nemt ændre en af ​​de eksisterende forespørgselsregler og blokere trafikken:

Dette vil resultere i følgende fejl på applikationssiden:

[email protected]:~# sysbench /root/sysbench/src/lua/oltp_read_only.lua --threads=4 --events=200 --time=0 --mysql-host=10.0.0.101 --mysql-user=sbtest --mysql-password=sbtest --mysql-port=6033 --tables=32 --report-interval=1 --skip-trx=on --table-size=100000 --db-ps-mode=disable --rate=10 run

sysbench 1.1.0-bbee5d5 (using bundled LuaJIT 2.1.0-beta3)



Running the test with following options:

Number of threads: 4

Target transaction rate: 10/sec

Report intermediate results every 1 second(s)

Initializing random number generator from current time




Initializing worker threads...



Threads started!



FATAL: mysql_drv_query() returned error 1148 (SELECT queries are not allowed!!!) for query 'SELECT c FROM sbtest25 WHERE id=83384'

FATAL: `thread_run' function failed: /usr/local/share/sysbench/oltp_common.lua:426: SQL error, errno = 1148, state = '42000': SELECT queries are not allowed!!!

Nu er det her åbenlyst hårdt. Vi kan være mere høflige og blot øge forsinkelsen for SELECT-forespørgslerne.

Dette påvirker naturligvis ydelsen af ​​forespørgslerne, da der tilføjes 10 millisekunder til hver SELECT, der udføres.

SQL statistics:

    queries performed:

        read:                            2800

        write:                           0

        other:                           0

        total:                           2800

    transactions:                        200    (5.60 per sec.)

    queries:                             2800   (78.44 per sec.)

    ignored errors:                      0      (0.00 per sec.)

    reconnects:                          0      (0.00 per sec.)



Throughput:

    events/s (eps):                      5.6030

    time elapsed:                        35.6952s

    total number of events:              200



Latency (ms):

         min:                                  622.04

         avg:                                 7957.01

         max:                                18808.60

         95th percentile:                    15934.78

         sum:                              1591401.12



Threads fairness:

    events (avg/stddev):           50.0000/36.01

    execution time (avg/stddev):   397.8503/271.50

Vi sætter forsinkelser op for hver SELECT-forespørgsel, hvilket ikke nødvendigvis giver mening udover at vise, at du kan gøre det. Typisk vil du gerne bruge forsinkelsen på nogle stødende forespørgsler. Lad os sige, at vi har en forespørgsel, der er meget tung, og den tilføjer betydelig belastning på databasens CPU. Hvad værre er, det er blevet introduceret af den seneste kodeændring, og det kommer fra alle applikationsværterne. Selvfølgelig kan du vente på, at udviklerne fortryder ændringen eller skubber en rettelse, men med ProxySQL kan du tage kontrollen i dine egne hænder og blot enten blokere forespørgslen eller reducere dens indvirkning endda ganske betydeligt.

Lad os antage, at vores database går pænt videre, når alarmklokkerne begynder at ringe.

Et hurtigt kig på metrikken fortæller os, at antallet af forespørgsler udført af ProxySQL går ned, mens CPU-udnyttelsen går op. Vi kan se på topforespørgslerne i ProxySQL for at se, om vi kan bemærke noget usædvanligt.

Det er faktisk usædvanligt - en ny forespørgsel, der ikke er en del af regelmæssig forespørgselsmix, vi observerede på vores system. Vi kan bruge muligheden til at oprette forespørgselsreglen.

Vi tilføjer en 50 sekunders forsinkelse til forespørgslen ved at indstille Delay til 50000 ms.

Vi kan bekræfte, at forespørgselsreglen er i brug, og forespørgsler rammer den .

Efter kort tid kan vi også bemærke, at belastningen falder og antallet af udførte forespørgsler er igen i det forventede interval. I stedet for at tilføje forsinkelsen til forespørgslen kunne vi selvfølgelig bare blokere den. Det ville have været endnu nemmere for os at opnå, men fuldstændig blokering af forespørgslen kan have betydelig indflydelse på applikationen.

Vi håber, at dette korte blogindlæg giver dig et indblik i, hvordan ProxySQL kan hjælpe dig med at forme din trafik og reducere det præstationshit, der introduceres af løbske forespørgsler.


  1. MySQL &MariaDB Database Backup Ressourcer

  2. Oracle SQL Developer streng bogstavelig talt for lang fejl

  3. Helt ny produktionsdatabase

  4. Hvad er den bedste måde at implementere Polymorphic Association i SQL Server?