AllInfo
Main: Info Blog Temp Mail


wrk 2024-07-09 17-10-14

MariaDB load



Для мониторинга транзакций в кластере Galera на MariaDB 10.6 и новее вы можете использовать mysqld_exporter (порт 9104). Этот экспортер позволяет собирать различные метрики MySQL/MariaDB, включая специфичные для Galera.
Для мониторинга транзакций и их распространения по кластеру Galera следует обратить внимание на следующие ключевые метрики:
wsrep_last_committed: Это глобальная переменная состояния, которая показывает номер последней выполненной транзакции на узле. Она может служить "транзакционным номером", о котором вы спрашивали.
wsrep_replicated: Эта метрика показывает количество транзакций, отправленных на репликацию другим узлам кластера.
wsrep_received: Показывает количество транзакций, полученных от других узлов кластера.
wsrep_local_recv_queue_avg: Средняя длина очереди входящих транзакций. Эта метрика может помочь оценить скорость "расползания" транзакций по кластеру.
Для настройки мониторинга:
Установите mysqld_exporter на каждом узле кластера Galera.
Создайте пользователя в MariaDB для экспортера:
sql
CREATE USER 'mysqld_exporter'@'localhost' IDENTIFIED BY 'StrongPassword' WITH MAX_USER_CONNECTIONS 2;
GRANT PROCESS, REPLICATION CLIENT, SELECT ON *.* TO 'mysqld_exporter'@'localhost';
FLUSH PRIVILEGES;

Настройте конфигурационный файл для экспортера.
Запустите mysqld_exporter как системный сервис.
Добавьте экспортер в конфигурацию Prometheus для сбора метрик.
Создайте дашборд в Grafana или другом инструменте визуализации, где вы сможете отслеживать указанные выше метрики.
Для оценки скорости распространения транзакций по кластеру вы можете сравнивать значения wsrep_last_committed между узлами и отслеживать динамику изменения wsrep_replicated и wsrep_received.
Помните, что Galera Manager также предоставляет возможности для мониторинга этих метрик, если вы его используете.

-------------------------------------- bash test load -------------------

#!/bin/bash

# Параметры подключения к MySQL
MYSQL_USER="root"
MYSQL_PASS="xxxxxx"

# Функция для выполнения SQL-запросов
execute_sql() {
mysql -u$MYSQL_USER -p$MYSQL_PASS -e "$1"
}

# Проверка версии MariaDB
echo "Версия MariaDB:"
execute_sql "SELECT VERSION();"

# Создание базы данных
execute_sql "CREATE DATABASE IF NOT EXISTS test_load;"

# Использование базы данных для последующих запросов
MYSQL_DB="test_load"

# Функция для выполнения SQL-запросов с указанной базой данных
execute_sql_db() {
mysql -u$MYSQL_USER -p$MYSQL_PASS $MYSQL_DB -e "$1"
}

# Создание таблицы
execute_sql_db "CREATE TABLE IF NOT EXISTS test_table (
id INT AUTO_INCREMENT PRIMARY KEY,
data VARCHAR(255),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);"

# Вставка данных
execute_sql_db "INSERT INTO test_table (data)
SELECT CONCAT('Data ', FLOOR(RAND() * 1000000))
FROM information_schema.columns
LIMIT 100000;"

# Выполнение запросов для создания нагрузки
execute_sql_db "SELECT COUNT(*) FROM test_table;"
execute_sql_db "SELECT * FROM test_table ORDER BY RAND() LIMIT 1000;"
execute_sql_db "UPDATE test_table SET data = CONCAT('Updated ', data) WHERE id % 100 = 0;"
execute_sql_db "DELETE FROM test_table WHERE id % 1000 = 0;"

# Пауза для наблюдения за нагрузкой
echo "Нагрузка создана. Пауза 30 секунд для наблюдения..."
sleep 30

# Удаление базы данных
execute_sql "DROP DATABASE IF EXISTS test_load;"

echo "Тест завершен. База данных удалена."

-------- Принудительное ожидание синхронизации с помощью WSREP_SYNC_WAIT ----------

#!/bin/bash

MYSQL_USER="root"
MYSQL_PASS="xxxxxx"
MYSQL_DB="test_load"

execute_sql() {
mysql -u$MYSQL_USER -p$MYSQL_PASS -e "$1"
}

execute_sql_db() {
mysql -u$MYSQL_USER -p$MYSQL_PASS $MYSQL_DB -e "$1"
}

echo "Версия MariaDB:"
execute_sql "SELECT VERSION();"

execute_sql "CREATE DATABASE IF NOT EXISTS $MYSQL_DB;"

execute_sql_db "CREATE TABLE IF NOT EXISTS test_table (
id INT AUTO_INCREMENT PRIMARY KEY,
data VARCHAR(255),
large_data LONGBLOB,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);"

# Большая транзакция
echo "Выполнение большой транзакции..."
execute_sql_db "START TRANSACTION;
INSERT INTO test_table (data, large_data)
SELECT
CONCAT('Data ', FLOOR(RAND() * 1000000)),
REPEAT('X', 1000000)
FROM information_schema.columns
LIMIT 1000;
UPDATE test_table SET data = CONCAT('Updated ', data) WHERE id % 2 = 0;
DELETE FROM test_table WHERE id % 10 = 0;
COMMIT;"

# Ожидание синхронизации
echo "Ожидание синхронизации..."
execute_sql_db "SET SESSION wsrep_sync_wait=1;
SELECT COUNT(*) FROM test_table;"

# Проверка состояния синхронизации
echo "Состояние синхронизации:"
execute_sql "SHOW STATUS LIKE 'wsrep_%';"

# Нагрузка на сеть с большими BLOB-полями
echo "Создание нагрузки на сеть..."
execute_sql_db "INSERT INTO test_table (data, large_data)
VALUES ('Large BLOB test', REPEAT('Y', 5000000));"

echo "Ожидание завершения синхронизации..."
sleep 10

echo "Финальная проверка состояния синхронизации:"
execute_sql "SHOW STATUS LIKE 'wsrep_%';"

# Удаление базы данных
execute_sql "DROP DATABASE IF EXISTS $MYSQL_DB;"

echo "Тест завершен. База данных удалена."

---------------- зачистка дискового пространства ----------
echo "Выполнение операций по освобождению дискового пространства..."

# Очистка буферного пула InnoDB
execute_sql "SET GLOBAL innodb_buffer_pool_evict='ALL';"

# Оптимизация всех таблиц во всех базах данных
execute_sql "SELECT CONCAT('OPTIMIZE TABLE ', table_schema, '.', table_name, ';')
FROM information_schema.tables
WHERE table_schema NOT IN ('information_schema', 'performance_schema', 'mysql');" |
while read -r query; do
execute_sql "$query"
done

# Очистка бинарных логов старше 1 дня
execute_sql "PURGE BINARY LOGS BEFORE DATE(NOW() - INTERVAL 1 DAY);"

echo "Операции завершены. Рекомендуется перезапустить сервер MariaDB для полного освобождения ресурсов."

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

#!/usr/bin/env python3

import mysql.connector
import sys
import random
import string
import argparse
import time

def create_database_and_table(cursor):
cursor.execute("CREATE DATABASE IF NOT EXISTS atm")
cursor.execute("USE atm")

cursor.execute("""
CREATE TABLE IF NOT EXISTS test_table (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50),
age INT,
email VARCHAR(120),
INDEX (name, age)
) ENGINE=InnoDB
""")

def check_replication_status(cursor):
cursor.execute("SHOW SLAVE STATUS;")
slave_status = cursor.fetchone()
if slave_status:
seconds_behind_master = slave_status[32] # 32 - это индекс Seconds_Behind_Master
print(f"Время отставания от мастера: {seconds_behind_master} секунд")
else:
print("Этот узел не является репликой.")

def main():
parser = argparse.ArgumentParser(description='Нагрузочное тестирование MariaDB')
parser.add_argument('--host', default='localhost', help='Хост MariaDB')
parser.add_argument('--port', type=int, default=3306, help='Порт MariaDB')
parser.add_argument('--user', required=True, help='Пользователь MariaDB')
parser.add_argument('--password', required=True, help='Пароль пользователя MariaDB')
parser.add_argument('--database', default='atm', help='База данных')
parser.add_argument('--iterations', type=int, default=10000, help='Количество итераций')
args = parser.parse_args()

try:
conn = mysql.connector.connect(
user=args.user,
password=args.password,
host=args.host,
port=args.port
)
except mysql.connector.Error as e:
print(f"Ошибка подключения к MariaDB: {e}")
sys.exit(1)

cur = conn.cursor()
create_database_and_table(cur)
conn.database = args.database

def random_string(length):
return ''.join(random.choices(string.ascii_letters + string.digits, k=length))

for i in range(args.iterations):
name = random_string(20)
age = random.randint(18, 65)
email = f"{name}@example.com"

# Вставка данных
start_insert_time = time.time()
try:
cur.execute("INSERT INTO test_table (name, age, email) VALUES (%s, %s, %s)", (name, age, email))
conn.commit()
except mysql.connector.Error as e:
print(f"Ошибка вставки данных: {e}")
continue
insert_duration = time.time() - start_insert_time

# Проверка времени отставания от мастера
check_replication_status(cur)

# Селект данных из таблицы
start_select_time = time.time()
cur.execute("SELECT * FROM test_table WHERE email = %s", (email,))
result = cur.fetchone()
select_duration = time.time() - start_select_time

if result:
print(f"Данные получены: {result}, Время вставки: {insert_duration:.6f} секунд, Время выборки: {select_duration:.6f} секунд")
else:
print(f"Данные не найдены для email: {email}")

print("Статистика кластера MariaDB:")
cur.execute("SHOW STATUS")
for row in cur:
print(row)

cur.execute("TRUNCATE TABLE test_table")
conn.commit()

cur.close()
conn.close()

if __name__ == '__main__':
main()

18.227.81.233 / 2024-12-21_18-36-35 UTC.