sql >> Database >  >> RDS >> Mysql

Verbindingsverwerking en -beperking met ProxySQL

De mogelijkheid om vorm te geven aan het verkeer dat naar de database gaat, is een van de belangrijkste. De afgelopen dagen had je er niet zoveel controle over - applicaties stuurden het verkeer naar de database en dat was het dan ook. HAProxy, dat veel werd gebruikt, heeft ook geen optie voor fijnmazige controle over het verkeer. Met de introductie van de SQL-bewuste proxy's, zoals ProxySQL, kwamen er meer mogelijkheden voor databasebeheerders. Laten we eens kijken naar de mogelijkheden voor het afhandelen en beperken van verbindingen in ProxySQL.

Verbindingsafhandeling in ProxySQL

Zoals u wellicht weet, werkt ProxySQL via de queryregels. Het is een lijst met regels waar elke query op wordt getest en die precies bepalen hoe de ProxySQL de query zal behandelen. Vanaf het begin maakt de applicatie verbinding met ProxySQL. Het zal authenticeren tegen ProxySQL (daarom moet ProxySQL alle gebruikers en wachtwoord-hashes opslaan) en vervolgens zal ProxySQL het door de queryregels leiden om te bepalen naar welke hostgroep de query moet worden verzonden.

ProxySQL opent een pool van verbindingen met de backend-servers. Het is geen 1-op-1 mapping, standaard probeert het één backend-verbinding te hergebruiken voor zoveel mogelijk frontend-verbindingen. Dit wordt verbindingsmultiplexing genoemd. Details zijn afhankelijk van het exacte verkeer dat het moet verwerken. Elke openstaande transactie moet binnen dezelfde verbinding worden afgehandeld. Als er een soort lokale variabele is gedefinieerd, kan deze verbinding niet opnieuw worden gebruikt. Het kunnen hergebruiken van een enkele backend-verbinding door meerdere frontend-verbindingen vermindert de belasting van de backend-database aanzienlijk.

Zodra de verbinding met de ProxySQL tot stand is gebracht, zoals we eerder vermeldden, wordt deze verwerkt volgens de queryregels. Hier kan de traffic shaping plaatsvinden. Laten we eens kijken naar de opties

Verbindingsbeperking in ProxySQL

Laten we eerst alle SELECT's laten vallen. We voeren onze "applicatie", Sysbench, op de volgende manier uit:

[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

Het is volledig alleen-lezen verkeer, het zou gemiddeld 10 transacties (140 zoekopdrachten) per seconde moeten zijn. Aangezien dit alleen SELECT's zijn, kunnen we eenvoudig een van de bestaande queryregels wijzigen en het verkeer blokkeren:

Dit resulteert in de volgende fout aan de toepassingskant:

[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!!!

Dit is duidelijk hard. We kunnen beleefder zijn en de vertraging voor de SELECT-vragen verhogen.

Dit heeft uiteraard invloed op de prestaties van de zoekopdrachten aangezien er 10 milliseconden worden toegevoegd aan elke SELECT die wordt uitgevoerd.

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

We hebben vertragingen ingesteld voor elke SELECT-query, wat niet per se logisch is, behalve om te laten zien dat je het kunt. Normaal gesproken zou je de vertraging willen gebruiken voor sommige aanstootgevende vragen. Laten we zeggen dat we een zoekopdracht hebben die erg zwaar is en die de CPU van de database aanzienlijk belast. Erger nog, het is geïntroduceerd door een recente codewijziging en het komt van alle applicatiehosts. Natuurlijk kun je wachten tot de ontwikkelaars de wijziging ongedaan maken of een oplossing pushen, maar met ProxySQL kun je de controle in eigen handen nemen en ofwel de zoekopdracht blokkeren of de impact ervan zelfs aanzienlijk verminderen.

Laten we aannemen dat onze database goed doordraait als de alarmbellen gaan rinkelen.

Een snelle blik op de statistieken leert ons dat het aantal zoekopdrachten uitgevoerd door ProxySQL gaat omlaag terwijl het CPU-gebruik omhoog gaat. We kunnen kijken naar de Top Queries in ProxySQL om te zien of we iets ongewoons kunnen opmerken.

Het is inderdaad ongebruikelijk - een nieuwe zoekopdracht die geen deel uitmaakt van de reguliere query-mix die we op ons systeem hebben waargenomen. We kunnen de optie gebruiken om de queryregel te maken.

We voegen een vertraging van 50 seconden toe aan de zoekopdracht door Vertraging in te stellen op 50000 mw.

We kunnen bevestigen dat de queryregel in gebruik is en dat deze wordt toegepast .

Na een korte tijd kunnen we ook merken dat de belasting daalt en het aantal van de uitgevoerde query's ligt weer in het verwachte bereik. In plaats van de vertraging aan de zoekopdracht toe te voegen, kunnen we deze natuurlijk gewoon blokkeren. Dat zou voor ons nog gemakkelijker zijn geweest, maar het volledig blokkeren van de zoekopdracht kan aanzienlijke gevolgen hebben voor de toepassing.

We hopen dat deze korte blogpost je enig inzicht geeft in hoe ProxySQL je kan helpen om je verkeer vorm te geven en de prestatie die wordt veroorzaakt door op hol geslagen zoekopdrachten te verminderen.


  1. Hoe kan ik het aantal woorden in een string in Oracle tellen?

  2. C# oproep orakel opgeslagen functie

  3. Azure Database for MySQL Server maken en implementeren met behulp van Azure Portal en Workbench

  4. SSIS-taak voor het importeren van inconsistente kolommentelling?