Sysbench je skvělý nástroj pro generování testovacích dat a provádění testů MySQL OLTP. Běžně by se při provádění benchmarku pomocí Sysbench prováděl cyklus příprava-spuštění-čištění. Ve výchozím nastavení je tabulka vygenerovaná Sysbenchem standardní základní tabulkou bez oddílů. Toto chování lze samozřejmě rozšířit, ale musíte vědět, jak to napsat ve skriptu LUA.
V tomto příspěvku na blogu ukážeme, jak generovat testovací data pro dělenou tabulku v MySQL pomocí Sysbench. To může být použito jako hřiště, abychom se dále ponořili do příčiny a účinku rozdělení tabulek, distribuce dat a směrování dotazů.
Rozdělení tabulky na jeden server
Rozdělení na jeden server jednoduše znamená, že všechny oddíly tabulky jsou umístěny na stejném serveru/instanci MySQL. Při vytváření struktury tabulky definujeme všechny oddíly najednou. Tento druh rozdělení je dobrý, pokud máte data, která časem ztrácejí svou užitečnost a lze je snadno odstranit z rozdělené tabulky zrušením oddílu (nebo oddílů), který obsahuje pouze tato data.
Vytvořte schéma Sysbench:
mysql> CREATE SCHEMA sbtest;
Vytvořte uživatele databáze sysbench:
mysql> CREATE USER 'sbtest'@'%' IDENTIFIED BY 'passw0rd';
mysql> GRANT ALL PRIVILEGES ON sbtest.* TO 'sbtest'@'%';
V Sysbench by bylo možné použít příkaz --prepare k přípravě serveru MySQL se strukturami schématu a generování řádků dat. Tuto část musíme přeskočit a strukturu tabulky definovat ručně.
Vytvořte rozdělenou tabulku. V tomto příkladu vytvoříme pouze jednu tabulku nazvanou sbtest1 a bude rozdělena sloupcem s názvem "k", což je v podstatě celé číslo v rozsahu od 0 do 1 000 000 (na základě možnosti --table-size, kterou jsme které se později použijí v operaci pouze vložení):
mysql> CREATE TABLE `sbtest1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`k` int(11) NOT NULL DEFAULT '0',
`c` char(120) NOT NULL DEFAULT '',
`pad` char(60) NOT NULL DEFAULT '',
PRIMARY KEY (`id`,`k`)
)
PARTITION BY RANGE (k) (
PARTITION p1 VALUES LESS THAN (499999),
PARTITION p2 VALUES LESS THAN MAXVALUE
);
Budeme mít 2 oddíly - První oddíl se nazývá p1 a bude ukládat data, kde je hodnota ve sloupci "k" nižší než 499 999 a druhý oddíl, p2, bude ukládat zbývající hodnoty . Vytvoříme také primární klíč, který obsahuje oba důležité sloupce - "id" je pro identifikátor řádku a "k" je klíč oddílu. Při rozdělování musí primární klíč zahrnovat všechny sloupce v rozdělovací funkci tabulky (kde používáme "k" ve funkci dělení rozsahu).
Ověřte, zda tam jsou oddíly:
mysql> SELECT TABLE_SCHEMA, TABLE_NAME, PARTITION_NAME, TABLE_ROWS
FROM INFORMATION_SCHEMA.PARTITIONS
WHERE TABLE_SCHEMA='sbtest2'
AND TABLE_NAME='sbtest1';
+--------------+------------+----------------+------------+
| TABLE_SCHEMA | TABLE_NAME | PARTITION_NAME | TABLE_ROWS |
+--------------+------------+----------------+------------+
| sbtest | sbtest1 | p1 | 0 |
| sbtest | sbtest1 | p2 | 0 |
+--------------+------------+----------------+------------+
Poté můžeme spustit operaci pouze vložení Sysbench, jak je uvedeno níže:
$ sysbench \
/usr/share/sysbench/oltp_insert.lua \
--report-interval=2 \
--threads=4 \
--rate=20 \
--time=9999 \
--db-driver=mysql \
--mysql-host=192.168.11.131 \
--mysql-port=3306 \
--mysql-user=sbtest \
--mysql-db=sbtest \
--mysql-password=passw0rd \
--tables=1 \
--table-size=1000000 \
run
Sledujte, jak se oddíly tabulky zvětšují, jak běží Sysbench:
mysql> SELECT TABLE_SCHEMA, TABLE_NAME, PARTITION_NAME, TABLE_ROWS
FROM INFORMATION_SCHEMA.PARTITIONS
WHERE TABLE_SCHEMA='sbtest2'
AND TABLE_NAME='sbtest1';
+--------------+------------+----------------+------------+
| TABLE_SCHEMA | TABLE_NAME | PARTITION_NAME | TABLE_ROWS |
+--------------+------------+----------------+------------+
| sbtest | sbtest1 | p1 | 1021 |
| sbtest | sbtest1 | p2 | 1644 |
+--------------+------------+----------------+------------+
Pokud spočítáme celkový počet řádků pomocí funkce COUNT, bude odpovídat celkovému počtu řádků hlášených oddíly:
mysql> SELECT COUNT(id) FROM sbtest1;
+-----------+
| count(id) |
+-----------+
| 2665 |
+-----------+
To je vše. Máme připravené rozdělení tabulky na jeden server, se kterým si můžeme pohrát.
Rozdělení tabulky na více serverů
Při dělení na více serverů budeme používat více serverů MySQL k fyzickému uložení podmnožiny dat konkrétní tabulky (sbtest1), jak ukazuje následující diagram:
Chystáme se nasadit 2 nezávislé uzly MySQL – mysql1 a mysql2. Tabulka sbtest1 bude rozdělena na tyto dva uzly a tuto kombinaci oddílu + hostitele budeme nazývat shard. Sysbench běží vzdáleně na třetím serveru a napodobuje aplikační vrstvu. Protože Sysbench nezná oddíly, potřebujeme mít databázový ovladač nebo router, který směruje databázové dotazy na správný fragment. K dosažení tohoto účelu použijeme ProxySQL.
Vytvořme pro tento účel další novou databázi s názvem sbtest3:
mysql> CREATE SCHEMA sbtest3;
mysql> USE sbtest3;
Udělte správná oprávnění uživateli databáze sbtest:
mysql> CREATE USER 'sbtest'@'%' IDENTIFIED BY 'passw0rd';
mysql> GRANT ALL PRIVILEGES ON sbtest3.* TO 'sbtest'@'%';
Na mysql1 vytvořte první oddíl tabulky:
mysql> CREATE TABLE `sbtest1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`k` int(11) NOT NULL DEFAULT '0',
`c` char(120) NOT NULL DEFAULT '',
`pad` char(60) NOT NULL DEFAULT '',
PRIMARY KEY (`id`,`k`)
)
PARTITION BY RANGE (k) (
PARTITION p1 VALUES LESS THAN (499999)
);
Na rozdíl od samostatného rozdělení definujeme v tabulce pouze podmínku pro oddíl p1, aby byly uloženy všechny řádky s hodnotami sloupce "k" v rozsahu od 0 do 499 999.
V mysql2 vytvořte další rozdělenou tabulku:
mysql> CREATE TABLE `sbtest1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`k` int(11) NOT NULL DEFAULT '0',
`c` char(120) NOT NULL DEFAULT '',
`pad` char(60) NOT NULL DEFAULT '',
PRIMARY KEY (`id`,`k`)
)
PARTITION BY RANGE (k) (
PARTITION p2 VALUES LESS THAN MAXVALUE
);
Na druhém serveru by měl uchovávat data druhého oddílu uložením zbývajících očekávaných hodnot sloupce "k".
Struktura naší tabulky je nyní připravena k naplnění testovacími daty.
Než budeme moci spustit operaci pouze vložení Sysbench, musíme nainstalovat server ProxySQL jako směrovač dotazů a fungovat jako brána pro naše fragmenty MySQL. Víceserverové sdílení vyžaduje, aby databázová připojení přicházející z aplikací byla směrována do správného datového fragmentu. Jinak by se zobrazila následující chyba:
1526 (Table has no partition for value 503599)
Nainstalujte ProxySQL pomocí ClusterControl, přidejte uživatele databáze sbtest do ProxySQL, přidejte oba servery MySQL do ProxySQL a nakonfigurujte mysql1 jako hostitelskou skupinu 11 a mysql2 jako hostitelskou skupinu 12:
Dále musíme zapracovat na tom, jak by měl být dotaz směrován. Ukázka dotazu INSERT, který provede Sysbench, bude vypadat nějak takto:
INSERT INTO sbtest1 (id, k, c, pad)
VALUES (0, 503502, '88816935247-23939908973-66486617366-05744537902-39238746973-63226063145-55370375476-52424898049-93208870738-99260097520', '36669559817-75903498871-26800752374-15613997245-76119597989')
Takže použijeme následující regulární výraz k filtrování dotazu INSERT na "k" => 500000, abychom splnili podmínku rozdělení:
^INSERT INTO sbtest1 \(id, k, c, pad\) VALUES \([0-9]\d*, ([5-9]{1,}[0-9]{5}|[1-9]{1,}[0-9]{6,}).*
Výše uvedený výraz se jednoduše pokouší filtrovat následující:
-
[0-9]\d* - Očekáváme zde celé číslo s automatickým přírůstkem, takže porovnáváme jakékoli celé číslo.
-
[5-9]{1,}[0-9]{5} - Hodnota odpovídá libovolnému celému číslu od 5 jako první číslice a 0-9 u posledních 5 číslic, aby odpovídala hodnotě rozsahu od 500 000 do 999 999.
-
[1-9]{1,}[0-9]{6,} - Hodnota odpovídá jakémukoli celému číslu od 1 do 9 jako první číslici a 0 až 9 na posledních 6 nebo větších číslicích, aby odpovídala hodnotě od 1 000 000 a větší.
Vytvoříme dvě podobná pravidla dotazu. První pravidlo dotazu je negace výše uvedeného regulárního výrazu. Tomuto pravidlu přiřadíme ID 51 a cílová skupina hostitelů by měla být skupina hostitelů 11, aby odpovídala sloupci "k" <500 000 a předala dotazy prvnímu oddílu. Mělo by to vypadat takto:
Věnujte pozornost "Negate Match Pattern" na výše uvedeném snímku obrazovky. Tato možnost je kritická pro správné směrování tohoto pravidla dotazu.
Dále vytvořte další pravidlo dotazu s pravidlem ID 52 pomocí stejného regulárního výrazu a cílová skupina hostitelů by měla být 12, ale tentokrát ponechte "Negate Match Pattern" hodnotu false, jak je uvedeno níže:
Potom můžeme spustit operaci pouze vložení pomocí Sysbench a vygenerovat testovací data . Informace související s přístupem k MySQL by měl být hostitel ProxySQL (192.168.11.130 na portu 6033):
$ sysbench \
/usr/share/sysbench/oltp_insert.lua \
--report-interval=2 \
--threads=4 \
--rate=20 \
--time=9999 \
--db-driver=mysql \
--mysql-host=192.168.11.130 \
--mysql-port=6033 \
--mysql-user=sbtest \
--mysql-db=sbtest3 \
--mysql-password=passw0rd \
--tables=1 \
--table-size=1000000 \
run
Pokud nevidíte žádnou chybu, znamená to, že ProxySQL směrovalo naše dotazy do správného fragmentu/oddílu. Měli byste vidět, že počet požadavků na pravidlo dotazu se zvyšuje, když je spuštěn proces Sysbench:
V části Nejčastější dotazy můžeme vidět souhrn směrování dotazů:
Pro dvojitou kontrolu se přihlaste do mysql1, vyhledejte první oddíl a zkontrolujte minimální a maximální hodnotu sloupce 'k' v tabulce sbtest1:
mysql> USE sbtest3;
mysql> SELECT min(k), max(k) FROM sbtest1;
+--------+--------+
| min(k) | max(k) |
+--------+--------+
| 232185 | 499998 |
+--------+--------+
Vypadá skvěle. Maximální hodnota sloupce „k“ nepřesahuje limit 499 999,-. Pojďme zkontrolovat počet řádků, které ukládá pro tento oddíl:
mysql> SELECT TABLE_SCHEMA, TABLE_NAME, PARTITION_NAME, TABLE_ROWS
FROM INFORMATION_SCHEMA.PARTITIONS
WHERE TABLE_SCHEMA='sbtest3'
AND TABLE_NAME='sbtest1';
+--------------+------------+----------------+------------+
| TABLE_SCHEMA | TABLE_NAME | PARTITION_NAME | TABLE_ROWS |
+--------------+------------+----------------+------------+
| sbtest3 | sbtest1 | p1 | 1815 |
+--------------+------------+----------------+------------+
Nyní se podíváme na druhý server MySQL (mysql2):
mysql> USE sbtest3;
mysql> SELECT min(k), max(k) FROM sbtest1;
+--------+--------+
| min(k) | max(k) |
+--------+--------+
| 500003 | 794952 |
+--------+--------+
Pojďme zkontrolovat počet řádků, které ukládá pro tento oddíl:
mysql> SELECT TABLE_SCHEMA, TABLE_NAME, PARTITION_NAME, TABLE_ROWS
FROM INFORMATION_SCHEMA.PARTITIONS
WHERE TABLE_SCHEMA='sbtest3'
AND TABLE_NAME='sbtest1';
+--------------+------------+----------------+------------+
| TABLE_SCHEMA | TABLE_NAME | PARTITION_NAME | TABLE_ROWS |
+--------------+------------+----------------+------------+
| sbtest3 | sbtest1 | p2 | 3247 |
+--------------+------------+----------------+------------+
Nádherný! Máme rozbité testovací nastavení MySQL se správným rozdělením dat pomocí Sysbench, se kterým si můžeme pohrát. Šťastné srovnávání!