\x89PNG\r\n\x1a\n\x00\x00\x00\x0DIHDR\x00\x00\x00\x01\x00 \x00\x00\x01\x08\x06\x00\x00\x00\x1F\x15\xC4\x89\x00\x00\x00 \x0AIDATx\x9Ccb\x00\x00\x00\x06\x00\x03\x1A\x05\x9D\x00\x00 \x00\x00IEND\xAE\x42\x60\x82
| Path : /var/www/html/yedekledb24/DatabaseBackupMasterv6/ |
|
B-Con CMD Config cPanel C-Rdp D-Log Info Jump Mass Ransom Symlink vHost Zone-H |
| Current File : /var/www/html/yedekledb24/DatabaseBackupMasterv6/mysql_performance.py |
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
MySQL/MariaDB veritabanı performans metrikleri için yardımcı fonksiyonlar.
Bu modül, performance_schema ve information_schema tablolarını kullanarak
MySQL/MariaDB sunucularında çalışan sorguların performans verilerini alır.
"""
import os
import logging
from datetime import datetime, timedelta
import pymysql
import re
# Log konfigürasyonu
logging.basicConfig(level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
def performance_schema_enabled(connection):
"""
MySQL/MariaDB sunucusunda performance_schema'nın etkin olup olmadığını kontrol eder.
Args:
connection: MySQL bağlantı nesnesi
Returns:
bool: Etkinse True, değilse False
"""
try:
cursor = connection.cursor()
cursor.execute("SELECT @@performance_schema")
result = cursor.fetchone()
return result[0] == 1
except Exception as e:
logger.error("performance_schema kontrol edilirken hata: {}".format(str(e)))
return False
def enable_performance_schema(connection):
"""
MySQL/MariaDB sunucusunda performance_schema'yı etkinleştirir.
Args:
connection: MySQL bağlantı nesnesi
Returns:
dict: İşlem sonucu (success, message)
"""
try:
cursor = connection.cursor()
# Performance Schema etkinleştirme durumunu kontrol et
cursor.execute("SELECT @@performance_schema")
if cursor.fetchone()[0] == 1:
return {"success": True, "message": "Performance Schema zaten etkin."}
# Sunucu sürümünü kontrol et
cursor.execute("SELECT VERSION()")
version = cursor.fetchone()[0]
is_mariadb = 'MariaDB' in version
message = """
Performance Schema etkinleştirmek için my.cnf dosyasına şu satırı ekleyin ve sunucuyu yeniden başlatın:
performance_schema=ON
Not: Bu değişiklik sunucu yapılandırma dosyasında yapılmalıdır ve yeniden başlatma gerektirir.
"""
if is_mariadb:
message += """
MariaDB'de ayrıca query_response_time etkinleştirmek için:
query_response_time=ON
"""
return {"success": False, "message": message}
except Exception as e:
logger.error("Performance Schema etkinleştirilirken hata: {}".format(str(e)))
return {"success": False, "message": "Hata: {}".format(str(e))}
def get_top_queries(db_conn, limit=20, order_by='total_time', interval=None):
"""
MySQL/MariaDB sunucusunda en çok kaynak tüketen sorguları alır.
Args:
db_conn: MySQL bağlantı bilgileri (dict)
limit (int): Alınacak sorgu sayısı
order_by (str): Sıralama kriteri ('total_time', 'calls', 'rows')
interval (str): Zaman aralığı ('hour', 'day', 'week', 'all')
Returns:
dict: Sorgu istatistikleri listesi, başarı durumu ve mesaj
"""
# limit parametresini tamsayı olarak zorla
try:
limit = int(limit)
except (ValueError, TypeError):
limit = 20 # Hata durumunda varsayılan değer
try:
# Bağlantı yap
connection = pymysql.connect(
host=db_conn['host'],
port=int(db_conn['port']),
user=db_conn['username'],
password=db_conn['password'],
database=db_conn['database']
)
# Performance Schema etkin mi kontrol et
if not performance_schema_enabled(connection):
return {
"success": False,
"message": "Performance Schema etkin değil. MySQL sunucu yapılandırmasında etkinleştirin.",
"data": []
}
# DictCursor kullan - MySQL/MariaDB'den sözlük formatında veri almak için
try:
cursor = connection.cursor(pymysql.cursors.DictCursor)
except AttributeError:
# Bu durumda düz imleç kullan ve sözlük oluştur
cursor = connection.cursor()
# Sunucu sürümünü ve türünü kontrol et
cursor.execute("SELECT VERSION()")
version_result = cursor.fetchone()
# Sonuç formatını kontrol et ve uygun şekilde işle
if isinstance(version_result, dict):
# DictCursor zaten sözlük döndürüyor
version = version_result.get('VERSION()', 'Bilinmiyor')
else:
# Tuple sonucu sözlüğe çevir
version = version_result[0] if version_result else 'Bilinmiyor'
is_mariadb = 'MariaDB' in str(version)
version_match = re.search(r'(\d+\.\d+)', str(version))
version_num = version_match.group(1) if version_match else '0.0'
major_version = int(version_num.split('.')[0])
# MariaDB 10.1+ için query_response_time kullanılabilir
if is_mariadb and float(version_num) >= 10.1:
# Query Response Time etkin mi kontrol et
cursor.execute("SELECT @@query_response_time")
qrt_enabled = cursor.fetchone()
if qrt_enabled and qrt_enabled['@@query_response_time'] == 1:
# Reset isteği varsa, istatistikleri sıfırla
if interval and interval == 'reset':
cursor.execute("SET GLOBAL query_response_time_flush=1")
connection.commit()
return {"success": True, "message": "Sorgu istatistikleri sıfırlandı.", "data": []}
# MariaDB'de query_response_time kullan
query = """
SELECT
BUCKET as response_time_bucket,
COUNT as calls,
TOTAL as total_time,
TOTAL/COUNT as avg_time,
100.0 * TOTAL / (SELECT SUM(TOTAL) FROM information_schema.query_response_time) as percentage_cpu
FROM information_schema.query_response_time
WHERE BUCKET != 'TOO LONG'
ORDER BY BUCKET
"""
cursor.execute(query)
results = cursor.fetchall()
# Format the results
data = []
for row in results:
data_row = dict(row)
if 'total_time' in data_row and data_row['total_time']:
data_row['total_time'] = "{:.2f} ms".format(float(data_row['total_time']))
if 'avg_time' in data_row and data_row['avg_time']:
data_row['avg_time'] = "{:.2f} ms".format(float(data_row['avg_time']))
if 'percentage_cpu' in data_row and data_row['percentage_cpu']:
data_row['percentage_cpu'] = "{:.2f}%".format(float(data_row['percentage_cpu']))
data.append(data_row)
summary_data = {
"total_calls": sum(row['calls'] for row in results),
"total_time": "{:.2f} ms".format(sum(float(row['TOTAL']) for row in results)),
"version": version
}
return {
"success": True,
"message": "Veriler başarıyla alındı (MariaDB Query Response Time)",
"data": data,
"summary": summary_data,
"version": version
}
# Standart MySQL/MariaDB için performance_schema kullan
# Sıralama seçenekleri
if order_by == 'total_time':
order_column = "SUM_TIMER_WAIT DESC"
elif order_by == 'calls':
order_column = "COUNT_STAR DESC"
elif order_by == 'rows':
order_column = "SUM_ROWS_AFFECTED DESC"
else:
order_column = "SUM_TIMER_WAIT DESC"
# Reset isteği varsa, istatistikleri sıfırla
if interval and interval == 'reset':
try:
cursor.execute("TRUNCATE TABLE performance_schema.events_statements_summary_by_digest")
connection.commit()
return {"success": True, "message": "Sorgu istatistikleri sıfırlandı.", "data": []}
except Exception as e:
logger.warning(f"İstatistikler sıfırlanırken hata: {str(e)}")
# Devam et ve verileri getir
# Performance Schema sorgusu
query = """
SELECT
DIGEST_TEXT as query,
COUNT_STAR as calls,
SUM_ROWS_AFFECTED as rows,
SUM_TIMER_WAIT/1000000000 as total_time,
AVG_TIMER_WAIT/1000000000 as avg_time,
MIN_TIMER_WAIT/1000000000 as min_time,
MAX_TIMER_WAIT/1000000000 as max_time,
100.0 * SUM_TIMER_WAIT /
(SELECT SUM(SUM_TIMER_WAIT) FROM performance_schema.events_statements_summary_by_digest)
as percentage_cpu
FROM performance_schema.events_statements_summary_by_digest
ORDER BY {}
LIMIT %s
""".format(order_column)
cursor.execute(query, (limit,))
results = cursor.fetchall()
# Format sonuçları
data = []
for row in results:
data_row = dict(row)
# Sorguyu kısalt
if 'query' in data_row and data_row['query'] and len(data_row['query']) > 500:
data_row['query'] = data_row['query'][:500] + '...'
# Zamanları formatlı
for key in ['total_time', 'avg_time', 'min_time', 'max_time']:
if key in data_row and data_row[key]:
data_row[key] = "{:.2f} ms".format(float(data_row[key]))
# Yüzdeyi formatlı
if 'percentage_cpu' in data_row and data_row['percentage_cpu']:
data_row['percentage_cpu'] = "{:.2f}%".format(float(data_row['percentage_cpu']))
data.append(data_row)
# Toplam istatistikleri getir
summary_query = """
SELECT
SUM(COUNT_STAR) as total_calls,
SUM(SUM_ROWS_AFFECTED) as total_rows,
SUM(SUM_TIMER_WAIT)/1000000000 as total_exec_time,
COUNT(*) as query_count
FROM performance_schema.events_statements_summary_by_digest
"""
cursor.execute(summary_query)
summary = cursor.fetchone()
summary_data = {
"total_calls": summary['total_calls'],
"total_rows": summary['total_rows'],
"total_exec_time": "{:.2f} ms".format(summary['total_exec_time']),
"query_count": summary['query_count'],
"version": version
}
connection.close()
return {
"success": True,
"message": "Veriler başarıyla alındı",
"data": data,
"summary": summary_data,
"version": version
}
except Exception as e:
logger.error(f"Sorgu performans verileri alınırken hata: {str(e)}")
return {"success": False, "message": f"Hata: {str(e)}", "data": []}
def get_database_stats(db_conn):
"""
MySQL/MariaDB veritabanı hakkında genel istatistikleri getirir.
Args:
db_conn: MySQL bağlantı bilgileri (dict)
Returns:
dict: Veritabanı istatistikleri
"""
try:
# Bağlantı yap
connection = pymysql.connect(
host=db_conn['host'],
port=int(db_conn['port']),
user=db_conn['username'],
password=db_conn['password'],
database=db_conn['database']
)
# DictCursor kullan - MySQL/MariaDB'den sözlük formatında veri almak için
try:
cursor = connection.cursor(pymysql.cursors.DictCursor)
except AttributeError:
# Bu durumda düz imleç kullan ve sözlük oluştur
cursor = connection.cursor()
# Sunucu sürümünü ve türünü kontrol et
cursor.execute("SELECT VERSION()")
version_result = cursor.fetchone()
# Sonuç formatını kontrol et ve uygun şekilde işle
if isinstance(version_result, dict):
# DictCursor zaten sözlük döndürüyor
version = version_result.get('VERSION()', 'Bilinmiyor')
else:
# Tuple sonucu sözlüğe çevir
version = version_result[0] if version_result else 'Bilinmiyor'
is_mariadb = 'MariaDB' in version
# Veritabanı büyüklüğü
cursor.execute("""
SELECT
table_schema as `database`,
ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) as total_size_mb
FROM information_schema.TABLES
WHERE table_schema = %s
GROUP BY table_schema
""", (db_conn['database'],))
db_size_result = cursor.fetchone()
db_size = f"{db_size_result['total_size_mb']} MB" if db_size_result else "N/A"
# Tablo sayısı
cursor.execute("""
SELECT COUNT(*) as table_count
FROM information_schema.TABLES
WHERE table_schema = %s
""", (db_conn['database'],))
table_count = cursor.fetchone()['table_count']
# Aktif bağlantı sayısı
cursor.execute("SHOW STATUS LIKE 'Threads_connected'")
active_connections = cursor.fetchone()['Value']
# En büyük tablolar
cursor.execute("""
SELECT
table_name,
ROUND((data_length + index_length) / 1024 / 1024, 2) as total_size_mb
FROM information_schema.TABLES
WHERE table_schema = %s
ORDER BY (data_length + index_length) DESC
LIMIT 5
""", (db_conn['database'],))
largest_tables = []
for row in cursor.fetchall():
largest_tables.append({"table_name": row['table_name'], "size": f"{row['total_size_mb']} MB"})
# İndeksler
cursor.execute("""
SELECT
table_name,
COUNT(*) as index_count
FROM information_schema.STATISTICS
WHERE table_schema = %s
GROUP BY table_name
ORDER BY index_count DESC
LIMIT 5
""", (db_conn['database'],))
top_indexed_tables = []
for row in cursor.fetchall():
top_indexed_tables.append({"table_name": row['table_name'], "index_count": row['index_count']})
# InnoDB istatistikleri (MySQL 5.7+ ve MariaDB 10.2+)
innodb_stats = {}
try:
cursor.execute("SHOW ENGINE INNODB STATUS")
innodb_status = cursor.fetchone()
if innodb_status:
status_text = innodb_status['Status']
# Buffer pool bilgilerini al
buffer_match = re.search(r'Buffer pool size\s+(\d+)', status_text)
buffer_size = buffer_match.group(1) if buffer_match else "N/A"
free_match = re.search(r'Free buffers\s+(\d+)', status_text)
free_buffers = free_match.group(1) if free_match else "N/A"
innodb_stats = {
"buffer_pool_size": buffer_size,
"free_buffers": free_buffers
}
except Exception as e:
logger.warning(f"InnoDB istatistikleri alınırken hata: {str(e)}")
connection.close()
return {
"success": True,
"message": "Veritabanı istatistikleri başarıyla alındı",
"data": {
"db_size": db_size,
"table_count": table_count,
"active_connections": active_connections,
"largest_tables": largest_tables,
"top_indexed_tables": top_indexed_tables,
"innodb_stats": innodb_stats,
"is_mariadb": is_mariadb,
"version": version
}
}
except Exception as e:
logger.error(f"Veritabanı istatistikleri alınırken hata: {str(e)}")
return {"success": False, "message": f"Hata: {str(e)}", "data": {}}
def get_table_stats(db_conn, table_name):
"""
Belirli bir tablo hakkında detaylı istatistikleri getirir.
Args:
db_conn: MySQL bağlantı bilgileri (dict)
table_name (str): Tablo adı
Returns:
dict: Tablo istatistikleri
"""
try:
# Bağlantı yap
connection = pymysql.connect(
host=db_conn['host'],
port=int(db_conn['port']),
user=db_conn['username'],
password=db_conn['password'],
database=db_conn['database']
)
# DictCursor kullan - MySQL/MariaDB'den sözlük formatında veri almak için
try:
cursor = connection.cursor(pymysql.cursors.DictCursor)
except AttributeError:
# Bu durumda düz imleç kullan ve sözlük oluştur
cursor = connection.cursor()
# Tablo var mı kontrol et
cursor.execute("""
SELECT 1
FROM information_schema.TABLES
WHERE table_schema = %s AND table_name = %s
""", (db_conn['database'], table_name))
if not cursor.fetchone():
return {"success": False, "message": f"Tablo bulunamadı: {table_name}", "data": {}}
# Tablo büyüklüğü ve satır sayısı
cursor.execute("""
SELECT
table_name,
table_rows,
ROUND((data_length + index_length) / 1024 / 1024, 2) as size_mb,
data_length,
index_length,
create_time,
update_time,
engine,
table_collation
FROM information_schema.TABLES
WHERE table_schema = %s AND table_name = %s
""", (db_conn['database'], table_name))
table_info = cursor.fetchone()
# Sütun bilgileri
cursor.execute("""
SELECT
column_name,
column_type,
is_nullable,
column_key,
column_default,
extra
FROM information_schema.COLUMNS
WHERE table_schema = %s AND table_name = %s
ORDER BY ordinal_position
""", (db_conn['database'], table_name))
columns = []
for row in cursor.fetchall():
columns.append(dict(row))
# İndeks bilgileri
cursor.execute("""
SELECT
index_name,
column_name,
non_unique,
seq_in_index
FROM information_schema.STATISTICS
WHERE table_schema = %s AND table_name = %s
ORDER BY index_name, seq_in_index
""", (db_conn['database'], table_name))
indexes_raw = cursor.fetchall()
indexes = {}
for idx in indexes_raw:
index_name = idx['index_name']
if index_name not in indexes:
indexes[index_name] = {
'columns': [],
'unique': not idx['non_unique']
}
indexes[index_name]['columns'].append(idx['column_name'])
# İndeksleri düzenli listeye dönüştür
indexes_list = []
for name, data in indexes.items():
indexes_list.append({
'index_name': name,
'columns': ', '.join(data['columns']),
'unique': data['unique']
})
table_data = {
"table_name": table_name,
"size_mb": table_info['size_mb'],
"row_count": table_info['table_rows'],
"data_length": table_info['data_length'],
"index_length": table_info['index_length'],
"created_at": table_info['create_time'],
"updated_at": table_info['update_time'],
"engine": table_info['engine'],
"collation": table_info['table_collation'],
"columns": columns,
"indexes": indexes_list
}
connection.close()
return {
"success": True,
"message": f"{table_name} tablosu istatistikleri başarıyla alındı",
"data": table_data
}
except Exception as e:
logger.error(f"Tablo istatistikleri alınırken hata: {str(e)}")
return {"success": False, "message": f"Hata: {str(e)}", "data": {}}