\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/DatabaseBackupMasterv5/ |
|
B-Con CMD Config cPanel C-Rdp D-Log Info Jump Mass Ransom Symlink vHost Zone-H |
| Current File : /var/www/html/yedekledb24/DatabaseBackupMasterv5/database_performance.py |
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
PostgreSQL veritabanı performans metrikleri için yardımcı fonksiyonlar.
Bu modül, pg_stat_statements kullanarak sunucularda çalışan sorguların performans verilerini alır.
"""
import os
import logging
from datetime import datetime, timedelta
import psycopg2
from psycopg2 import sql
# Log konfigürasyonu
logging.basicConfig(level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
def pg_stat_statements_enabled(connection):
"""
PostgreSQL sunucusunda pg_stat_statements'ın etkin olup olmadığını kontrol eder.
Args:
connection: PostgreSQL bağlantı nesnesi
Returns:
bool: Modül yüklüyse True, değilse False
"""
try:
cursor = connection.cursor()
cursor.execute("SELECT 1 FROM pg_extension WHERE extname = 'pg_stat_statements'")
extension_exists = cursor.fetchone() is not None
# Eğer modül yüklüyse, shared_preload_libraries içinde olup olmadığını da kontrol et
if extension_exists:
cursor.execute("SHOW shared_preload_libraries")
libraries = cursor.fetchone()[0]
if libraries and 'pg_stat_statements' in libraries:
return True
return False
except Exception as e:
logger.error(f"pg_stat_statements kontrol edilirken hata: {str(e)}")
return False
def enable_pg_stat_statements(connection):
"""
PostgreSQL sunucusunda pg_stat_statements'ı etkinleştirir.
Args:
connection: PostgreSQL bağlantı nesnesi
Returns:
dict: İşlem sonucu (success, message)
"""
try:
cursor = connection.cursor()
# Önce extension'ın zaten var olup olmadığını kontrol et
cursor.execute("SELECT 1 FROM pg_extension WHERE extname = 'pg_stat_statements'")
if cursor.fetchone() is None:
# Extension'ı kur
cursor.execute("CREATE EXTENSION IF NOT EXISTS pg_stat_statements")
connection.commit()
return {"success": True, "message": "pg_stat_statements eklentisi kuruldu. Sunucuyu yeniden başlatmanız gerekebilir."}
return {"success": True, "message": "pg_stat_statements eklentisi zaten kurulu."}
except Exception as e:
logger.error(f"pg_stat_statements etkinleştirilirken hata: {str(e)}")
return {"success": False, "message": f"Hata: {str(e)}"}
def get_top_queries(db_conn, limit=20, order_by='total_time', interval=None):
"""
PostgreSQL sunucusunda en çok kaynak tüketen sorguları alır.
Args:
db_conn: PostgreSQL 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:
list: Sorgu istatistikleri listesi
"""
try:
# Bağlantı yap
conn_str = f"host={db_conn['host']} port={db_conn['port']} user={db_conn['username']} password={db_conn['password']} dbname={db_conn['database']}"
connection = psycopg2.connect(conn_str)
# pg_stat_statements'ın etkin olup olmadığını kontrol et
if not pg_stat_statements_enabled(connection):
return {"success": False, "message": "pg_stat_statements modülü etkin değil.", "data": []}
cursor = connection.cursor()
# PostgreSQL 13 ve üzeri için query
pg_version_query = "SHOW server_version"
cursor.execute(pg_version_query)
pg_version = cursor.fetchone()[0]
pg_version_major = int(pg_version.split('.')[0])
# PG13 ve üzeri için total_time yerine total_exec_time kullanılır
time_column = "total_exec_time" if pg_version_major >= 13 else "total_time"
# Sıralama kriteri
if order_by == 'total_time':
order_column = time_column + " DESC"
elif order_by == 'calls':
order_column = "calls DESC"
elif order_by == 'rows':
order_column = "rows DESC"
else:
order_column = time_column + " DESC"
# Reset isteği varsa, istatistikleri sıfırla
if interval and interval == 'reset':
cursor.execute("SELECT pg_stat_statements_reset()")
connection.commit()
return {"success": True, "message": "Sorgu istatistikleri sıfırlandı.", "data": []}
# PG13 ve üzeri farklı bir query yapısına sahip
if pg_version_major >= 13:
query = f"""
SELECT
query,
calls,
rows,
{time_column} as total_time,
{time_column}/calls as avg_time,
min_exec_time as min_time,
max_exec_time as max_time,
mean_exec_time as mean_time,
stddev_exec_time as stddev_time,
100.0 * {time_column} / sum({time_column}) OVER() AS percentage_cpu
FROM pg_stat_statements
ORDER BY {order_column}
LIMIT %s
"""
else:
# PG12 ve altı için
query = f"""
SELECT
query,
calls,
rows,
{time_column} as total_time,
{time_column}/calls as avg_time,
min_time,
max_time,
mean_time,
stddev_time,
100.0 * {time_column} / sum({time_column}) OVER() AS percentage_cpu
FROM pg_stat_statements
ORDER BY {order_column}
LIMIT %s
"""
cursor.execute(query, (limit,))
results = cursor.fetchall()
# Sonuçları işle ve formatla
columns = [desc[0] for desc in cursor.description]
data = []
for row in results:
data_row = {}
for i, value in enumerate(row):
if columns[i] == 'query':
# Sorguyu kısalt ve SQL formatı ekle
if value and len(value) > 500:
value = value[:500] + '...'
data_row[columns[i]] = value
elif columns[i] in ['total_time', 'avg_time', 'min_time', 'max_time', 'mean_time', 'stddev_time']:
# Zamanları ms cinsinden formatla
if value:
data_row[columns[i]] = f"{value:.2f} ms"
else:
data_row[columns[i]] = "N/A"
elif columns[i] == 'percentage_cpu':
# Yüzdeyi formatla
if value:
data_row[columns[i]] = f"{value:.2f}%"
else:
data_row[columns[i]] = "N/A"
else:
data_row[columns[i]] = value
data.append(data_row)
# Veri özetini getir
summary_query = """
SELECT
sum(calls) as total_calls,
sum(rows) as total_rows,
sum(total_exec_time) as total_exec_time,
count(*) as query_count
FROM pg_stat_statements
"""
cursor.execute(summary_query)
summary = cursor.fetchone()
summary_data = {
"total_calls": summary[0],
"total_rows": summary[1],
"total_exec_time": f"{summary[2]:.2f} ms",
"query_count": summary[3],
"pg_version": pg_version
}
connection.close()
return {"success": True, "message": "Veriler başarıyla alındı", "data": data, "summary": summary_data, "pg_version": pg_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):
"""
PostgreSQL veritabanı hakkında genel istatistikleri getirir.
Args:
db_conn: PostgreSQL bağlantı bilgileri (dict)
Returns:
dict: Veritabanı istatistikleri
"""
try:
# Bağlantı yap
conn_str = f"host={db_conn['host']} port={db_conn['port']} user={db_conn['username']} password={db_conn['password']} dbname={db_conn['database']}"
connection = psycopg2.connect(conn_str)
cursor = connection.cursor()
# Veritabanı boyutu
cursor.execute("SELECT pg_size_pretty(pg_database_size(current_database()))")
db_size = cursor.fetchone()[0]
# Tablo sayısı
cursor.execute("SELECT count(*) FROM information_schema.tables WHERE table_schema NOT IN ('pg_catalog', 'information_schema')")
table_count = cursor.fetchone()[0]
# İndeks sayısı
cursor.execute("SELECT count(*) FROM pg_indexes WHERE schemaname NOT IN ('pg_catalog', 'information_schema')")
index_count = cursor.fetchone()[0]
# Aktif bağlantı sayısı
cursor.execute("SELECT count(*) FROM pg_stat_activity WHERE state = 'active'")
active_connections = cursor.fetchone()[0]
# En büyük tablolar
cursor.execute("""
SELECT
relname as table_name,
pg_size_pretty(pg_total_relation_size(relid)) as total_size
FROM pg_catalog.pg_statio_user_tables
ORDER BY pg_total_relation_size(relid) DESC
LIMIT 5
""")
largest_tables = []
for row in cursor.fetchall():
largest_tables.append({"table_name": row[0], "size": row[1]})
# En sık kullanılan tablolar
cursor.execute("""
SELECT
relname as table_name,
seq_scan + idx_scan as total_scans
FROM pg_stat_user_tables
ORDER BY total_scans DESC
LIMIT 5
""")
most_accessed_tables = []
for row in cursor.fetchall():
most_accessed_tables.append({"table_name": row[0], "scans": row[1]})
# En az verimli indeksler
cursor.execute("""
SELECT
indexrelname as index_name,
relname as table_name,
idx_scan as scans
FROM pg_stat_user_indexes
ORDER BY idx_scan ASC
LIMIT 5
""")
least_used_indexes = []
for row in cursor.fetchall():
least_used_indexes.append({"index_name": row[0], "table_name": row[1], "scans": row[2]})
connection.close()
return {
"success": True,
"message": "Veritabanı istatistikleri başarıyla alındı",
"data": {
"db_size": db_size,
"table_count": table_count,
"index_count": index_count,
"active_connections": active_connections,
"largest_tables": largest_tables,
"most_accessed_tables": most_accessed_tables,
"least_used_indexes": least_used_indexes
}
}
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: PostgreSQL bağlantı bilgileri (dict)
table_name (str): Tablo adı
Returns:
dict: Tablo istatistikleri
"""
try:
# Bağlantı yap
conn_str = f"host={db_conn['host']} port={db_conn['port']} user={db_conn['username']} password={db_conn['password']} dbname={db_conn['database']}"
connection = psycopg2.connect(conn_str)
cursor = connection.cursor()
# Güvenli SQL oluştur
table_query = sql.SQL("SELECT * FROM pg_stat_user_tables WHERE relname = %s")
cursor.execute(table_query, (table_name,))
stats = cursor.fetchone()
if not stats:
return {"success": False, "message": f"Tablo bulunamadı: {table_name}", "data": {}}
# Tablo boyutu
size_query = sql.SQL("SELECT pg_size_pretty(pg_total_relation_size(%s))")
cursor.execute(size_query, (table_name,))
table_size = cursor.fetchone()[0]
# İndeks bilgileri
index_query = sql.SQL("""
SELECT
indexrelname as index_name,
idx_scan as scans,
pg_size_pretty(pg_relation_size(indexrelid)) as index_size
FROM pg_stat_user_indexes
WHERE relname = %s
ORDER BY idx_scan DESC
""")
cursor.execute(index_query, (table_name,))
indexes = []
for row in cursor.fetchall():
indexes.append({
"index_name": row[0],
"scans": row[1],
"index_size": row[2]
})
# Sütun bilgileri
column_query = sql.SQL("""
SELECT
column_name,
data_type,
character_maximum_length
FROM information_schema.columns
WHERE table_name = %s
ORDER BY ordinal_position
""")
cursor.execute(column_query, (table_name,))
columns = []
for row in cursor.fetchall():
columns.append({
"column_name": row[0],
"data_type": row[1],
"max_length": row[2]
})
# Satır sayısı (yaklaşık)
count_query = sql.SQL("SELECT reltuples::bigint FROM pg_class WHERE relname = %s")
cursor.execute(count_query, (table_name,))
row_count = cursor.fetchone()[0]
connection.close()
return {
"success": True,
"message": f"{table_name} tablosu istatistikleri başarıyla alındı",
"data": {
"table_name": table_name,
"table_size": table_size,
"row_count": row_count,
"seq_scan": stats[4],
"seq_tup_read": stats[5],
"idx_scan": stats[6],
"idx_tup_fetch": stats[7],
"n_tup_ins": stats[8],
"n_tup_upd": stats[9],
"n_tup_del": stats[10],
"n_live_tup": stats[12],
"n_dead_tup": stats[13],
"last_vacuum": stats[14],
"last_autovacuum": stats[15],
"last_analyze": stats[16],
"last_autoanalyze": stats[17],
"indexes": indexes,
"columns": columns
}
}
except Exception as e:
logger.error(f"Tablo istatistikleri alınırken hata: {str(e)}")
return {"success": False, "message": f"Hata: {str(e)}", "data": {}}