Enhance database connection handling in BotDB class with error checking for file existence and access permissions. Implement methods for database integrity checks and WAL file cleanup. Update database initialization to use absolute project path for improved reliability.

This commit is contained in:
2025-08-26 19:33:11 +03:00
parent 86773cfe20
commit 62af3b73c6
3 changed files with 240 additions and 10 deletions

View File

@@ -23,11 +23,38 @@ class BotDB:
def connect(self):
"""Создание соединения и курсора."""
# Добавляем таймаут для предотвращения зависаний
self.conn = sqlite3.connect(self.db_file, timeout=10.0)
# Включаем WAL режим для лучшей производительности
self.conn.execute("PRAGMA journal_mode=WAL")
self.cursor = self.conn.cursor()
try:
# Проверяем существование файла базы данных
if not os.path.exists(self.db_file):
self.logger.error(f"Файл базы данных не найден: {self.db_file}")
raise FileNotFoundError(f"Файл базы данных не найден: {self.db_file}")
# Проверяем права доступа к файлу
if not os.access(self.db_file, os.R_OK | os.W_OK):
self.logger.error(f"Нет прав доступа к файлу базы данных: {self.db_file}")
raise PermissionError(f"Нет прав доступа к файлу базы данных: {self.db_file}")
# Добавляем таймаут для предотвращения зависаний
self.conn = sqlite3.connect(self.db_file, timeout=10.0)
# Включаем WAL режим для лучшей производительности
self.conn.execute("PRAGMA journal_mode=WAL")
self.conn.execute("PRAGMA synchronous=NORMAL")
self.conn.execute("PRAGMA cache_size=10000")
self.conn.execute("PRAGMA temp_store=MEMORY")
self.cursor = self.conn.cursor()
self.logger.info(f"Успешное подключение к базе данных: {self.db_file}")
except sqlite3.Error as e:
self.logger.error(f"Ошибка SQLite при подключении к базе данных: {e}")
raise
except (FileNotFoundError, PermissionError) as e:
self.logger.error(f"Ошибка файловой системы при подключении к базе данных: {e}")
raise
except Exception as e:
self.logger.error(f"Неожиданная ошибка при подключении к базе данных: {e}")
raise
def create_table(self, sql_script):
"""
@@ -1379,10 +1406,19 @@ class BotDB:
def close(self):
"""Закрытие соединения и курсора."""
if self.cursor:
self.cursor.close()
if self.conn:
self.conn.close()
try:
if self.cursor:
self.cursor.close()
self.cursor = None
except Exception as e:
self.logger.error(f"Ошибка при закрытии курсора: {e}")
try:
if self.conn:
self.conn.close()
self.conn = None
except Exception as e:
self.logger.error(f"Ошибка при закрытии соединения: {e}")
async def check_user_in_blacklist_async(self, user_id: int):
"""
@@ -1397,3 +1433,43 @@ class BotDB:
"""
loop = asyncio.get_event_loop()
return await loop.run_in_executor(self.executor, self.get_blacklist_users_by_id, user_id)
def check_database_integrity(self):
"""
Проверяет целостность базы данных и очищает WAL файлы.
"""
try:
self.connect()
# Проверяем целостность базы данных
self.cursor.execute("PRAGMA integrity_check")
integrity_result = self.cursor.fetchone()
if integrity_result and integrity_result[0] == "ok":
self.logger.info("Проверка целостности базы данных прошла успешно")
# Очищаем WAL файлы
self.cursor.execute("PRAGMA wal_checkpoint(TRUNCATE)")
self.logger.info("WAL файлы очищены")
else:
self.logger.warning(f"Проблемы с целостностью базы данных: {integrity_result}")
except Exception as e:
self.logger.error(f"Ошибка при проверке целостности базы данных: {e}")
raise
finally:
self.close()
def cleanup_wal_files(self):
"""
Очищает WAL файлы и переключает на DELETE режим для предотвращения проблем с I/O.
"""
try:
self.connect()
# Переключаем на DELETE режим для очистки WAL файлов
self.cursor.execute("PRAGMA journal_mode=DELETE")
self.cursor.execute("PRAGMA journal_mode=WAL")
self.logger.info("WAL файлы очищены и режим восстановлен")
except Exception as e:
self.logger.error(f"Ошибка при очистке WAL файлов: {e}")
raise
finally:
self.close()