sql >> Databáze >  >> RDS >> Mysql

Manipulace s připojením a omezení s ProxySQL

Schopnost utvářet provoz, který jde do databáze, je jednou z nejdůležitějších. V minulých dnech jste nad tím neměli tolik kontroly - aplikace posílaly provoz do databáze a to je tak vše. Běžně používané HAProxy také nemá možnost jemného řízení provozu. Se zavedením SQL-aware proxy, jako je ProxySQL, se administrátorům databází dostalo více možností. Podívejme se na možnosti zpracování připojení a omezení v ProxySQL.

Obsluha připojení v ProxySQL

Jak možná víte, ProxySQL funguje prostřednictvím pravidel dotazů. Je to seznam pravidel, podle kterých je každý dotaz testován a která přesně určují, jak bude ProxySQL s dotazem pracovat. Od začátku se aplikace připojuje k ProxySQL. Ověří se proti ProxySQL (proto musí ProxySQL ukládat všechny uživatele a hash hesel) a pak jej ProxySQL spustí pomocí pravidel dotazu, aby určil, do které hostitelské skupiny má být dotaz odeslán.

ProxySQL otevře fond připojení k backendovým serverům. Nejedná se o mapování 1:1, ve výchozím nastavení se pokouší znovu použít jedno backendové připojení pro co nejvíce frontendových připojení. Toto se nazývá multiplexování spojení. Podrobnosti závisí na přesném provozu, který musí zvládnout. Každá otevřená transakce musí být zpracována v rámci stejného připojení. Pokud je definován nějaký druh lokální proměnné, nelze toto spojení znovu použít. Možnost opětovného použití jednoho backendového připojení pomocí více frontendových připojení výrazně snižuje zátěž backendové databáze.

Jakmile je navázáno připojení k ProxySQL, jak jsme již zmínili, bude zpracováno podle pravidel dotazu. Zde může docházet k formování dopravy. Pojďme se podívat na možnosti

Omezení připojení v ProxySQL

Nejprve vynechme všechny SELECTy. Spouštíme naši „aplikaci“, Sysbench, následujícím způsobem:

[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

Jedná se o provoz pouze pro čtení, průměr by měl být 10 transakcí (140 dotazů) za sekundu. Protože se jedná pouze o SELECTy, můžeme snadno upravit jedno ze stávajících pravidel dotazu a zablokovat provoz:

To bude mít za následek následující chybu na straně aplikace:

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

To je samozřejmě drsné. Můžeme být zdvořilejší a jen prodloužit zpoždění pro SELECT dotazy.

To samozřejmě ovlivní výkon dotazů, protože se přidá 10 milisekund na každý SELECT, který je proveden.

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

Nastavili jsme zpoždění pro každý dotaz SELECT, což nemusí nutně dávat jiný smysl, než ukázat, že to dokážete. Obvykle byste chtěli použít zpoždění na některé problematické dotazy. Řekněme, že máme dotaz, který je velmi těžký a výrazně zatěžuje procesor databáze. A co je horší, byl zaveden nedávnou změnou kódu a pochází od všech hostitelů aplikací. Jistě, můžete počkat, až vývojáři změnu vrátí zpět nebo opraví, ale s ProxySQL můžete převzít kontrolu do svých rukou a buď zablokovat dotaz, nebo snížit jeho dopad i docela výrazně.

Předpokládejme, že když začnou zvonit poplašné zvonky, naše databáze se pěkně rozjede.

Rychlý pohled na metriky nám říká, že počet dotazů provedených ProxySQL klesá, zatímco využití CPU stoupá. Můžeme se podívat na Nejčastější dotazy v ProxySQL, abychom zjistili, zda si nevšimneme něčeho neobvyklého.

Je to skutečně neobvyklé - nový dotaz, který není součástí pravidelný mix dotazů, který jsme pozorovali v našem systému. Můžeme použít možnost vytvořit pravidlo dotazu.

Dotazu přidáme zpoždění 50 sekund nastavením Delay na 50000 ms.

Můžeme potvrdit, že pravidlo dotazu se používá a dotazy na něj narážejí .

Po krátké chvíli si také můžeme všimnout, že zatížení klesá a číslo počet provedených dotazů je opět v očekávaném rozsahu. Samozřejmě, místo přidávání zpoždění k dotazu jsme jej mohli jednoduše zablokovat. To by pro nás bylo ještě jednodušší, ale úplné zablokování dotazu může mít významný dopad na aplikaci.

Doufáme, že vám tento krátký příspěvek na blogu poskytne přehled o tom, jak vám ProxySQL může pomoci utvářet váš provoz a snižovat výkonnostní zásah způsobený nekontrolovatelnými dotazy.


  1. Jak opravit zastaralé oracle.sql.ArrayDescriptor, oracle.sql.STRUCT a oracle.sql.StructDescriptor

  2. Jak vytvořit prázdnou databázi v Accessu 2016

  3. Jak funguje Unicode() v SQLite

  4. Existuje způsob, jak zakázat přetížení funkcí v Postgresu