<?php

# Это должно быть в отдельном конфиге
define('DB_DEBUG_SCREEN'0); # вывод ошибок на экран
define('DB_DEBUG_FILE''mysql_error.log'); # вывод ошибок в этот файл


/*
    ПРОШУ ОБРАТИТЬ ВНИМАНИЕ!!!
    Данный класс не полностью рабочий, он может быть полезен
    только тем, кто хочет решать проблему вылетания таблиц
    аналогичным образом. Здесь наглядно описан алгоритм действий.
    Обычными словами я объяснять не умею :)
*/

class database
{
        var 
$link;
        var 
$counter 0;


        
# вроде как главная функция

        
function query($sql$debug true$qc 1)
        {
                
$result mysql_query($sql$this->link);
                
$error  mysql_error($this->link);
                
$this->counter++;

                if (
$error)
                {
                    
# Если ошибка в запросе, то сразу die() и ниябе.
                    
if ($this->error_Syntax($error))
                    {
                        
$this->errorLog($error$debug);
                    }
                    else
                    {
                        
# Если мы уже боролись с проблемами, а толку не было
                        
if ($gc 5)
                        {
                            
# Здесь можно вставить отправку письма админу,
                            # чтобы немедленно разбирался с проблемой.

                            
$this->errorLog($error$debug);
                            return 
$result;
                        }
                    }

                    
# Если сервер "вылетел", подождем его запуск
                    
if ($this->error_HasGoneAway($error))
                    {
                        
sleep(5);
                        
$this->errorLog($errorfalse);

                        
# Опять коннектимся
                        
$this->Connect('localhost''root''pass');
                        
$this->SelectDB('mysqlbase');

                        
# Запрос
                        
$this->query($sql$debug$qc++);
                    }

                    
# Если сломалась таблица, то пытаемся ремонтировать.
                    
if ($this->error_CrashedTable($error))
                    {
                        
# Ремонт
                        
$this->repairTables();
                        
$this->errorLog($errorfalse);
                        
sleep(1);

                        
# и опять пытаемся получить то, что мы хотели в запросе
                        
$this->query($sql$debug$qc++);
                    }
                }

                return 
$result;

        }



        function 
errorLog($error$debug true)
        {
                   if (
defined('DB_DEBUG_SCREEN') && (DB_DEBUG_SCREEN == 1))
                   {
                       echo 
'<table border="1" width="500" align="center" cellpadding="5">';
                       echo 
'<tr><td colspan="2"><h3>MySQL ERROR</h3></td></tr>';
                       echo 
'<tr><td width="100" align="right"><b>SQL Query:</b></td><td>' htmlspecialchars($sql) . '</td></tr>';
                       echo 
'<tr><td width="100" align="right"><b>Description:</b></td><td>' htmlspecialchars($error) . '</td></tr>';
                       echo 
'</table>';
                   }

                   if (
defined('DB_DEBUG_FILE') && (DB_DEBUG_FILE != ''))
                   {
                       
$fp = @fopen(DB_DEBUG_FILE'a');
                       if (
$fp)
                       {
                           
$ip security_getIP();
                           
$host = @gethostbyaddr($ip);
                           
$url getEnv('HTTP_HOST') . getEnv('REQUEST_URI');
                           
$data "\r\n\r\n" $url "\r\n# # # # # " date('d.m.Y [H:i:s]') . ", IP: " $ip "" . ($host ", Host: " $host "") . "\r\n" $sql "\r\n---\r\n" $error "" . ($error2 "(" $error2 ")" "") . "\r\n# # # # #\r\n\r\n";
                           @
fwrite($fp$data);
                       }
                       @
fclose($fp);
                   }

                   if (
$debug) die();         }

        function 
error_HasGoneAway($error)
        {             
# MySQL server has gone away
            
return (strpos($error'has gone away') != 0);         }

        function 
error_CrashedTable($error)
        {             
# Table './base/table' is marked as crashed and should be repaired
            # Incorrect key file for table './base/table.MYI'; try to repair it
            
$a = (strpos($error'crashed') != 0);
            
$b = (strpos($error'try to repair') != 0);

            return (
$a || $b);         }

        function 
error_Syntax($error)
        {             
# #1064 - You have an error in your SQL syntax;
            # Но мы делаем хитрее, так как 1064 ошибка "не одна такая".
            
$a $this->error_HasGoneAway($error);
            
$b $this->error_CrashedTable($error);
            return !(
$a || $b);         }

        function 
repairTables()
        {             
$tables $this->sql2array('SHOW TABLES'0);
            if (
$tables)
            {
                foreach (
$tables as $k=>$t)
                {                     
# 'Tables_in_base'
                    
$k array_keys($t);
                    
$k $k[0];
                    
$status $this->sql2array('CHECK TABLE `' $t[$k] . '`'0);

                    
$tables[$k] = $status[0];
                    if (
$status[0]['Msg_text'] != 'OK')
                    {
                        list(
$h$table) = explode('.'$status[0]['Table']);
                        
$this->query('REPAIR TABLE `' $table '`');
                        
$this->query('OPTIMIZE TABLE `' $table '`');
                        
$r date("Y-m-d H:i:s ") .  $table "\r\n";

                        
# Ведем статистику поломок по таблицам
                        
$this->errorLog($rfalse);
                    }
                }
            }         }


};


highlight_file(__FILE__);

?>