Архив рубрики: MySQL

Восстановление БД MySQL в формате InnoDB

Итак, случился «Ой». БД не запускается. Что делать?

  1. Смотрим размер ib_logfile0 файла:
root@pavel-All-Series:/var/lib/mysql# ls -l
drwxrwxrwx 2 root root 4096 авг. 31 14:22 bugify
-rwxrwxrwx 1 root root 79691776 авг. 31 13:56 ibdata1
-rwxrwxrwx 1 root root 67108864 авг. 31 13:56 ib_logfile0
-rwxrwxrwx 1 root root 67108864 июля 3 04:38 ib_logfile1
drwxrwxrwx 2 mysql mysql 4096 авг. 31 14:21 mysql
-rwxrwxrwx 1 root root 6 авг. 31 14:21 mysql_upgrade_info
drwxrwxrwx 2 mysql mysql 4096 авг. 31 14:21 performance_schema
drwxrwxrwx 2 mysql mysql 4096 авг. 11 2014 phpmyadmin

2. Запускаем mysql:

mysqld --innodb_log_file_size=<размер ib_logfile0> --innodb_force_recovery=6

Если все хорошо Вы должны увидеть следующее:
InnoDB: The user has set SRV_FORCE_NO_LOG_REDO on
InnoDB: Skipping log redo
070625 11:59:36 InnoDB: Started; log sequence number 0 0
InnoDB: !!! innodb_force_recovery is set to 6 !!!
070625 11:59:36 [Note] /usr/sbin/mysqld: ready for connections.
Version: ‘5.0.18’ socket: ‘/var/lib/mysql/mysql.sock’ port: 3306 SUSE MySQL

Далее дампим поднявшуюся базу данных:
mysqldump -u root -p database > database.sql

Если Вы получите следующее сообщение, это значит, что файлы системного журнала Innodb  повреждены:
Got error: 1146: Table ‘database.table’ doesn’t exist when using LOCK TABLES

Чтобы решить проблему с хранением ib_logfile0 файла нужна актуальная резервная копия, поэтому восстановите все файлы от старшей резервной копии. Это не безотказное решение, но ценная попытка.

Восстановите Ваши данные:
mysql -u root -p database < database.sql

Процедуры в MySQL..

Давно хотел попробовать переложить часть кода и логики на плечи MySQL.. По идее говорят за счет сокращения обмена сетевыми пакетами, скорость выполнения значительно увеличивается. В зависимости от задачи конечно. Ну попробовал.. Не очень понравилось. Писать на этом так называемом языке очень не удобно. Особенно эти «курсоры» в MySQL. В итоге пришел к выводу, что таки да. Смысл писать есть, но только если «очень -очень нада»..

Ниже пример процедуры заполнения таблицы на основании другой..

DROP PROCEDURE `pav_PrepareAgrmsTableForPredPlat`;
CREATE PROCEDURE `pav_PrepareAgrmsTableForPredPlat`(IN `gr_id` INT) COMMENT 'Пересчет' NOT DETERMINISTIC CONTAINS SQL SQL SECURITY DEFINER BEGIN
DECLARE done INT DEFAULT 0;
DECLARE agrm_idd INT;
DECLARE uider INT;
DECLARE balancer double;
DECLARE num CHAR(100);
DECLARE nam VARCHAR(100);
DECLARE mob CHAR(100);
DECLARE adr VARCHAR(200);
DECLARE agrms CURSOR FOR 
select accounts_addr.address,agreements.number,agreements.agrm_id as ag,agreements.uid as uuid,agreements.balance,accounts.name,accounts.mobile from 
vgroups inner join agreements on vgroups.uid=agreements.uid inner join accounts on agreements.uid=accounts.uid left join accounts_addr on accounts_addr.uid=accounts.uid
where vgroups.blocked<>10 and vgroups.uid in (select uid from usergroups_staff  where usergroups_staff.group_id=gr_id) and agreements.archive=0 and vgroups.archive=0 and LENGTH(accounts.mobile)>=10 and accounts_addr.type=1
group by agreements.agrm_id;
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;
delete from lanbpredplat where grp=gr_id;
OPEN agrms;                            
  REPEAT
   FETCH agrms INTO adr,num,agrm_idd,uider,balancer,nam,mob;
     if NOT done then
       insert into lanbpredplat (am_usl,am_inet,am_tv,agrm_id,grp,uid,balance,number,username,phone,address) values (0,0,0,agrm_idd,gr_id,uider,balancer,num,nam,mob,adr);
     END IF;	
  UNTIL done END REPEAT;
CLOSE agrms; 
end

 

Удаление миллионов записей из таблицы MySql

Если в таблице нужно удалить несколько миллионов записей, то MySQL может потребоваться на это несколько часов. Но можно поступить по другому: на время отключить ключи, а потом их снова включить. Например:

ALTER TABLE lanbsh_users DISABLE KEYS;
DELETE from lanbsh_users;
ALTER TABLE lanbsh_users ENABLE KEYS;

Обновление «Учет оргтехники и ТМЦ в браузере» до версии 3.49

Выложено на sourceforge.net

В основном эволюционные изменения. Ничего революционного нет. Исправлено ряд незначительных ошибок.

Из нового:

  • добавлено поле «в пути» в журнале имущества и в перемещениях
  • каждому пользователю можно добавить роли
  • добавлен модуль «управление устройствами» — можно например использовать для перезагрузок устройств
  • добавлен виджет — модуль «кто онлайн»
  • еще ряд мелочей

Работа с транзакциями MySQL на PHP

С часа три вероятно мучался вчера, пока подобрал вариант кода, который корректно отрабатывает.

$err="";
 $lb=new Tsql();
 $lb->connect($myrow["host"], $myrow["username"], $myrow["pass"], $myrow["basename"]);
 $lb->start_transaction();
 $sql="INSERT INTO payments (agrm_id,amount,comment,receipt,pay_date,local_date,status,mod_person,amount_cur) VALUES ('$agrm_id','$amount','Автоматически загруженный платеж','$uniid','$dat',now(),0,'$manager_id','$amount')";
 if ($err==""){
 $result2 = $lb->ExecuteSQL($sql);
 if ($result2=='') {$err="Error!";};
 };
 $sql="UPDATE agreements SET balance=balance+$amount where agrm_id='$agrm_id'";
 if ($err==""){
 $result2 = $lb->ExecuteSQL($sql);
 if ($result2=='') {$err="Error!";};
 };
 if ($err==""){
 $lb->commit();
 } else {
 $lb->rollback();
 PutLog('----ошибка занесения платежа(2): ' . $err);
 };
 unset($lb);

Использованный класс:

<?php
// Данный код создан и распространяется по лицензии GPL v3
// Изначальный автор данного кода - Грибов Павел
// http://грибовы.рф

class Tsql {
    var $idsqlconnection; // идентификатор соединения с БД

// соеденяемся с БД и выбираем таблицу, получаем $idsqlconnection    
function connect($host,$name,$pass,$base){
    global $codemysql;
      $this->idsqlconnection=new mysqli($host,$name,$pass,$base);
        if (mysqli_connect_errno()) {
            $serr=mysqli_connect_error();
            die("Error connect to Mysql or select base: $serr");
            }      
    $result = mysqli_query($this->idsqlconnection,"SET NAMES $codemysql");    
    mysqli_set_charset($this->idsqlconnection, "$codemysql");
    
 }   
 
function ExecuteSQL($sql){
    //echo "$sql<br>";
    $result = mysqli_query($this->idsqlconnection,$sql);               
    if ($result==""){echo mysqli_connect_error();};
    return $result;
 }   
 
 function start_transaction(){
     return mysqli_query($this->idsqlconnection,"START TRANSACTION");
   //return mysqli_begin_transaction($this->idsqlconnection);  
 }
 
 function commit (){
     return mysqli_query($this->idsqlconnection,"COMMIT");
   //return mysqli_commit($this->idsqlconnection);  
 }
 
 function rollback(){
     return mysqli_query($this->idsqlconnection,"ROLLBACK");
   //return mysqli_rollback($this->idsqlconnection);  
 }
 function close(){
 return mysqli_close($this->idsqlconnection);
 }
}

Как оказалось, главной фишкой — нельзя использовать внутри цикла begin transaction — commit (или rollback) обработку ошибок при помощи mysqli_error — PHP падает в FATAL ERROR.. Почему? Вопрос интересный.