MariaDB
 sql >> Baza danych >  >> RDS >> MariaDB

Przewodnik po replikacji strumieniowej MySQL Galera Cluster:część druga

W pierwszej części tego bloga przedstawiliśmy przegląd nowej funkcji replikacji strumieniowej w MySQL Galera Cluster. Na tym blogu pokażemy, jak to włączyć, i przyjrzymy się wynikom.

Włączanie replikacji strumieniowej

Wysoce zalecane jest włączenie replikacji strumieniowej na poziomie sesji dla określonych transakcji, które wchodzą w interakcje z aplikacją/klientem.

Jak wspomniano w poprzednim blogu, Galera rejestruje swoje zestawy zapisu w tabeli wsrep_streaming_log w bazie danych MySQL. Może to potencjalnie spowodować wąskie gardło wydajności, zwłaszcza gdy potrzebne jest wycofanie. Nie oznacza to, że nie możesz korzystać z replikacji strumieniowej, oznacza to po prostu, że musisz wydajnie zaprojektować klienta aplikacji podczas korzystania z replikacji strumieniowej, aby uzyskać lepszą wydajność. Mimo to najlepiej jest mieć replikację strumieniową do obsługi i ograniczania dużych transakcji.

Włączenie replikacji strumieniowej wymaga zdefiniowania jednostki replikacji i liczby jednostek używanych do tworzenia fragmentów transakcji. Zmiennymi tymi sterują dwa parametry:wsrep_trx_fragment_unit i wsrep_trx_fragment_size.

Poniżej znajduje się przykład ustawienia tych dwóch parametrów:

SET SESSION wsrep_trx_fragment_unit='statements';

SET SESSION wsrep_trx_fragment_size=3;

W tym przykładzie fragment jest ustawiony na trzy instrukcje. Dla każdych trzech oświadczeń z transakcji węzeł wygeneruje, zreplikuje i poświadczy fragment.

Możesz wybierać pomiędzy kilkoma jednostkami replikacji podczas tworzenia fragmentów:

  • bajty - To określa rozmiar fragmentu w bajtach.
  • wiersze - Definiuje rozmiar fragmentu jako liczbę wierszy, które fragment aktualizuje.
  • wypowiedzi - Definiuje rozmiar fragmentu jako liczbę instrukcji we fragmencie.

Wybierz jednostkę replikacji i rozmiar fragmentu, które najlepiej pasują do konkretnej operacji, którą chcesz uruchomić.

Replikacja strumieniowa w akcji

Jak omówiliśmy w naszym innym blogu dotyczącym obsługi dużych transakcji w Mariadb 10.4, przeprowadziliśmy i przetestowaliśmy, jak działa replikacja strumieniowa po włączeniu, w oparciu o te kryteria...

  1. Podstawa, ustaw globalny wsrep_trx_fragment_size=0;
  2. ustaw globalne wsrep_trx_fragment_unit='wiersze'; ustaw globalne wsrep_trx_fragment_size=1;
  3. ustaw globalne wsrep_trx_fragment_unit='oświadczenia'; ustaw globalne wsrep_trx_fragment_size=1;
  4. ustaw globalne wsrep_trx_fragment_unit='oświadczenia'; ustaw globalne wsrep_trx_fragment_size=5;

I wyniki są

Transactions: 82.91 per sec., queries: 1658.27 per sec. (100%)

Transactions: 54.72 per sec., queries: 1094.43 per sec. (66%)

Transactions: 54.76 per sec., queries: 1095.18 per sec. (66%)

Transactions: 70.93 per sec., queries: 1418.55 per sec. (86%)

W tym przykładzie używamy Percona XtraDB Cluster 8.0.15 prosto z ich gałęzi testowej przy użyciu Percona-XtraDB-Cluster_8.0.15.5-27dev.4.2_Linux.x86_64.ssl102.tar.gz budować.

Następnie wypróbowaliśmy 3-węzłowy klaster Galera z poniższymi informacjami o hostach:

testnode11 = 192.168.10.110

testnode12 = 192.168.10.120

testnode13 = 192.168.10.130

Wstępnie wypełniliśmy tabelę z mojej bazy danych sysbench i próbowaliśmy usunąć bardzo duże wiersze.

[email protected][sbtest]#> select count(*) from sbtest1;

+----------+

| count(*) |

+----------+

| 12608218 |

+----------+

1 row in set (25.55 sec)

Na początku działa bez replikacji strumieniowej

[email protected][sbtest]#> select @@wsrep_trx_fragment_unit, @@wsrep_trx_fragment_size,  @@innodb_lock_wait_timeout;

+---------------------------+---------------------------+----------------------------+

| @@wsrep_trx_fragment_unit | @@wsrep_trx_fragment_size | @@innodb_lock_wait_timeout |

+---------------------------+---------------------------+----------------------------+

| bytes                     | 0 |                         50000 |

+---------------------------+---------------------------+----------------------------+

1 row in set (0.00 sec)

Następnie uruchom,

[email protected][sbtest]#> delete from sbtest1 where id >= 2000000;

Jednak skończyło się na wycofaniu...

---TRANSACTION 648910, ACTIVE 573 sec rollback

mysql tables in use 1, locked 1

ROLLING BACK 164858 lock struct(s), heap size 18637008, 12199395 row lock(s), undo log entries 11961589

MySQL thread id 183, OS thread handle 140041167468288, query id 79286 localhost 127.0.0.1 root wsrep: replicating and certifying write set(-1)

delete from sbtest1 where id >= 2000000

Korzystanie z pulpitów nawigacyjnych ClusterControl do zebrania przeglądu wszelkich wskazań kontroli przepływu, ponieważ transakcja przebiega wyłącznie w węźle głównym (aktywny zapis) do czasu zatwierdzenia, nie ma żadnego wskaźnika aktywności kontroli przepływu:

Jeśli się zastanawiasz, bieżąca wersja ClusterControl jeszcze nie działa mają bezpośrednie wsparcie dla PXC 8.0 z Galera Cluster 4 (ponieważ wciąż jest eksperymentalny). Możesz jednak spróbować go zaimportować ... ale wymaga drobnych poprawek, aby Twoje pulpity nawigacyjne działały poprawnie.

Powrót do procesu zapytania. Nie powiodło się, ponieważ zostało wycofane!

[email protected][sbtest]#> delete from sbtest1 where id >= 2000000;

ERROR 1180 (HY000): Got error 5 - 'Transaction size exceed set threshold' during COMMIT

niezależnie od wsrep_max_ws_rows lub wsrep_max_ws_size,

[email protected][sbtest]#> select @@global.wsrep_max_ws_rows, @@global.wsrep_max_ws_size/(1024*1024*1024);

+----------------------------+---------------------------------------------+

| @@global.wsrep_max_ws_rows | @@global.wsrep_max_ws_size/(1024*1024*1024) |

+----------------------------+---------------------------------------------+

|                          0 |               2.0000 |

+----------------------------+---------------------------------------------+

1 row in set (0.00 sec)

W końcu osiągnął próg.

W tym czasie tabela systemowa mysql.wsrep_streaming_log jest pusta, co oznacza, że ​​replikacja strumieniowa nie działa lub nie jest włączona,

[email protected][sbtest]#> select count(*) from mysql.wsrep_streaming_log;

+----------+

| count(*) |

+----------+

|        0 |

+----------+

1 row in set (0.01 sec)



[email protected][sbtest]#> select count(*) from mysql.wsrep_streaming_log;

+----------+

| count(*) |

+----------+

|        0 |

+----------+

1 row in set (0.00 sec)

i to jest weryfikowane na pozostałych 2 węzłach (testnode12 i testnode13).

Teraz spróbujmy włączyć to za pomocą replikacji strumieniowej,

[email protected][sbtest]#> select @@wsrep_trx_fragment_unit, @@wsrep_trx_fragment_size, @@innodb_lock_wait_timeout;

+---------------------------+---------------------------+----------------------------+

| @@wsrep_trx_fragment_unit | @@wsrep_trx_fragment_size | @@innodb_lock_wait_timeout |

+---------------------------+---------------------------+----------------------------+

| bytes                     | 0 |                      50000 |

+---------------------------+---------------------------+----------------------------+

1 row in set (0.00 sec)



[email protected][sbtest]#> set wsrep_trx_fragment_unit='rows'; set wsrep_trx_fragment_size=100; 

Query OK, 0 rows affected (0.00 sec)



Query OK, 0 rows affected (0.00 sec)



[email protected][sbtest]#> select @@wsrep_trx_fragment_unit, @@wsrep_trx_fragment_size, @@innodb_lock_wait_timeout;

+---------------------------+---------------------------+----------------------------+

| @@wsrep_trx_fragment_unit | @@wsrep_trx_fragment_size | @@innodb_lock_wait_timeout |

+---------------------------+---------------------------+----------------------------+

| rows                      | 100 |                      50000 |

+---------------------------+---------------------------+----------------------------+

1 row in set (0.00 sec)

Czego można się spodziewać po włączeniu replikacji strumieniowej Galera Cluster?

Kiedy zapytanie zostało wykonane w testnode11,

[email protected][sbtest]#> delete from sbtest1 where id >= 2000000;

To, co się dzieje, to fragmentowanie transakcji kawałek po kawałku w zależności od ustawionej wartości zmiennej wsrep_trx_fragment_size. Sprawdźmy to w innych węzłach:

Węzeł testowy hosta12

[email protected][sbtest]#> pager sed -n '/TRANSACTIONS/,/FILE I\/O/p'; show engine innodb status\G nopager; show global status like 'wsrep%flow%'; select count(*) from mysql.wsrep_streaming_log;

PAGER set to 'sed -n '/TRANSACTIONS/,/FILE I\/O/p''

TRANSACTIONS

------------

Trx id counter 567148

Purge done for trx's n:o < 566636 undo n:o < 0 state: running but idle

History list length 44

LIST OF TRANSACTIONS FOR EACH SESSION:

..

...

---TRANSACTION 421740651985200, not started

0 lock struct(s), heap size 1136, 0 row lock(s)

---TRANSACTION 553661, ACTIVE 190 sec

18393 lock struct(s), heap size 2089168, 1342600 row lock(s), undo log entries 1342600

MySQL thread id 898, OS thread handle 140266050008832, query id 216824 wsrep: applied write set (-1)

--------

FILE I/O

1 row in set (0.08 sec)



PAGER set to stdout

+----------------------------------+--------------+

| Variable_name                    | Value |

+----------------------------------+--------------+

| wsrep_flow_control_paused_ns     | 211197844753 |

| wsrep_flow_control_paused        | 0.133786 |

| wsrep_flow_control_sent          | 633 |

| wsrep_flow_control_recv          | 878 |

| wsrep_flow_control_interval      | [ 173, 173 ] |

| wsrep_flow_control_interval_low  | 173 |

| wsrep_flow_control_interval_high | 173          |

| wsrep_flow_control_status        | OFF |

+----------------------------------+--------------+

8 rows in set (0.00 sec)



+----------+

| count(*) |

+----------+

|    13429 |

+----------+

1 row in set (0.04 sec)

Węzeł testowy hosta13

[email protected][sbtest]#> pager sed -n '/TRANSACTIONS/,/FILE I\/O/p'; show engine innodb status\G nopager; show global status like 'wsrep%flow%'; select count(*) from mysql.wsrep_streaming_log;

PAGER set to 'sed -n '/TRANSACTIONS/,/FILE I\/O/p''

TRANSACTIONS

------------

Trx id counter 568523

Purge done for trx's n:o < 567824 undo n:o < 0 state: running but idle

History list length 23

LIST OF TRANSACTIONS FOR EACH SESSION:

..

...

---TRANSACTION 552701, ACTIVE 216 sec

21587 lock struct(s), heap size 2449616, 1575700 row lock(s), undo log entries 1575700

MySQL thread id 936, OS thread handle 140188019226368, query id 600980 wsrep: applied write set (-1)

--------

FILE I/O

1 row in set (0.28 sec)



PAGER set to stdout

+----------------------------------+--------------+

| Variable_name                    | Value |

+----------------------------------+--------------+

| wsrep_flow_control_paused_ns     | 210755642443 |

| wsrep_flow_control_paused        | 0.0231273 |

| wsrep_flow_control_sent          | 1653 |

| wsrep_flow_control_recv          | 3857 |

| wsrep_flow_control_interval      | [ 173, 173 ] |

| wsrep_flow_control_interval_low  | 173 |

| wsrep_flow_control_interval_high | 173          |

| wsrep_flow_control_status        | OFF |

+----------------------------------+--------------+

8 rows in set (0.01 sec)



+----------+

| count(*) |

+----------+

|    15758 |

+----------+

1 row in set (0.03 sec)

Zauważ, że kontrola przepływu właśnie się uruchomiła!

Kolejki wysyłania/odbierania WSREP również zostały wyrzucone:

Węzeł testowy hosta12 (192.168.10.120)  Węzeł testowy hosta13 (192.168.10.130)

Teraz omówimy więcej wyników z tabeli mysql.wsrep_streaming_log,

[email protected][sbtest]#> pager sed -n '/TRANSACTIONS/,/FILE I\/O/p'|tail -8; show engine innodb status\G nopager;

PAGER set to 'sed -n '/TRANSACTIONS/,/FILE I\/O/p'|tail -8'

MySQL thread id 134822, OS thread handle 140041167468288, query id 0 System lock

---TRANSACTION 649008, ACTIVE 481 sec

mysql tables in use 1, locked 1

53104 lock struct(s), heap size 6004944, 3929602 row lock(s), undo log entries 3876500

MySQL thread id 183, OS thread handle 140041167468288, query id 105367 localhost 127.0.0.1 root updating

delete from sbtest1 where id >= 2000000

--------

FILE I/O

1 row in set (0.01 sec)

następnie biorąc wynik,

[email protected][sbtest]#> select count(*) from mysql.wsrep_streaming_log;

+----------+

| count(*) |

+----------+

|    38899 |

+----------+

1 row in set (0.40 sec)

Informuje, jaka część fragmentu została zreplikowana przy użyciu replikacji strumieniowej. Teraz zróbmy podstawową matematykę:

[email protected][sbtest]#> select 3876500/38899.0;

+-----------------+

| 3876500/38899.0 |

+-----------------+

|         99.6555 |

+-----------------+

1 row in set (0.03 sec)

Pobieram wpisy dziennika cofania z wyniku SHOW ENGINE INNODB STATUS\G, a następnie dzielę całkowitą liczbę rekordów mysql.wsrep_streaming_log. Jak wcześniej ustaliłem, zdefiniowałem wsrep_trx_fragment_size=100. Wynik pokaże, ile wszystkich zreplikowanych dzienników jest obecnie przetwarzanych przez Galera.

Ważne jest, aby zwrócić uwagę na to, co próbuje osiągnąć replikacja strumieniowa... "węzeł dzieli transakcję na fragmenty, a następnie certyfikuje i replikuje je na urządzeniach podrzędnych, gdy transakcja jest nadal w toku postęp. Po certyfikacji fragmentu nie można już przerwać przez sprzeczne transakcje."

Fragmenty są uważane za transakcje, które zostały przekazane do pozostałych węzłów w klastrze, poświadczając pofragmentowaną transakcję, a następnie stosując zestawy zapisu. Oznacza to, że po poświadczeniu lub nadaniu priorytetu dużej transakcji wszystkie połączenia przychodzące, które mogą mieć zakleszczenie, będą musiały poczekać do zakończenia transakcji.

Teraz werdykt usunięcia ogromnego stołu?

[email protected][sbtest]#> delete from sbtest1 where id >= 2000000;

Query OK, 12034538 rows affected (30 min 36.96 sec)

Ukończy się pomyślnie bez żadnej awarii!

Jak to wygląda w innych węzłach? W węźle testowym12

[email protected][sbtest]#> pager sed -n '/TRANSACTIONS/,/FILE I\/O/p'|tail -8; show engine innodb status\G nopager; show global status like 'wsrep%flow%'; select count(*) from mysql.wsrep_streaming_log;

PAGER set to 'sed -n '/TRANSACTIONS/,/FILE I\/O/p'|tail -8'

0 lock struct(s), heap size 1136, 0 row lock(s)

---TRANSACTION 421740651985200, not started

0 lock struct(s), heap size 1136, 0 row lock(s)

---TRANSACTION 553661, ACTIVE (PREPARED) 2050 sec

165631 lock struct(s), heap size 18735312, 12154883 row lock(s), undo log entries 12154883

MySQL thread id 898, OS thread handle 140266050008832, query id 341835 wsrep: preparing to commit write set(215510)

--------

FILE I/O

1 row in set (0.46 sec)



PAGER set to stdout

+----------------------------------+--------------+

| Variable_name                    | Value |

+----------------------------------+--------------+

| wsrep_flow_control_paused_ns     | 290832524304 |

| wsrep_flow_control_paused        | 0 |

| wsrep_flow_control_sent          | 0 |

| wsrep_flow_control_recv          | 0 |

| wsrep_flow_control_interval      | [ 173, 173 ] |

| wsrep_flow_control_interval_low  | 173 |

| wsrep_flow_control_interval_high | 173          |

| wsrep_flow_control_status        | OFF |

+----------------------------------+--------------+

8 rows in set (0.53 sec)



+----------+

| count(*) |

+----------+

|   120345 |

+----------+

1 row in set (0.88 sec)

Zatrzymuje się na 120345 fragmentach, a jeśli ponownie wykonamy obliczenia matematyczne na ostatnich przechwyconych wpisach dziennika cofania (dzienniki cofania są takie same, jak w masterze),

[email protected][sbtest]#> select 12154883/120345.0;                                                                                                                                                   +-------------------+

| 12154883/120345.0 |

+-------------------+

|          101.0003 |

+-------------------+

1 row in set (0.00 sec)

Więc mieliśmy w sumie 120345 transakcje są fragmentowane w celu usunięcia 12034538 wiersze.

Po zakończeniu używania lub włączania replikacji strumienia nie zapomnij ją wyłączyć, ponieważ zawsze rejestruje ona ogromne transakcje i zwiększa wydajność klastra. Aby go wyłączyć, po prostu uruchom

[email protected][sbtest]#> set wsrep_trx_fragment_size=0;

Query OK, 0 rows affected (0.04 sec)

Wnioski

Przy włączonej replikacji strumieniowej ważne jest, abyś był w stanie określić, jak duży może być rozmiar twojego fragmentu i jaką jednostkę musisz wybrać (bajty, wiersze, instrukcje).

Bardzo ważne jest również, aby uruchomić go na poziomie sesji i oczywiście określić, kiedy wystarczy użyć replikacji strumieniowej.

Podczas wykonywania tych testów usunięcie dużej liczby wierszy do ogromnej tabeli z włączoną funkcją Streaming Replication wyraźnie spowodowało wysoki szczyt wykorzystania dysku i procesora. Pamięć RAM była bardziej stabilna, ale może to ze względu na stwierdzenie, które wykonaliśmy, nie jest zbyt dużą rywalizacją o pamięć.

Można śmiało powiedzieć, że replikacja strumieniowa może powodować wąskie gardła wydajności w przypadku dużych rekordów, więc korzystanie z niej powinno odbywać się z właściwą decyzją i ostrożnością.

Na koniec, jeśli używasz replikacji strumieniowej, nie zapomnij zawsze wyłączyć tej funkcji po wykonaniu tej czynności w bieżącej sesji, aby uniknąć niepożądanych problemów.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Objaśnienie operatora MariaDB MINUS

  2. Jak SIGN() działa w MariaDB

  3. Ustaw zestaw znaków i sortowanie bazy danych w MariaDB

  4. 4 sposoby na znalezienie wierszy zawierających wielkie litery w MariaDB

  5. Konfigurowanie uwierzytelniania LDAP i mapowania grup za pomocą MariaDB