Опубликован: 16.04.2007 | Доступ: свободный | Студентов: 5320 / 857 | Оценка: 4.18 / 4.08 | Длительность: 16:03:00
Лекция 4:

Проверка и восстановление таблиц

< Лекция 3 || Лекция 4: 1234 || Лекция 5 >

Сценарий mysqlhotcopy блокирует одновременно все таблицы базы данных, после чего очищает табличные буферы и копирует файлы. Сценарий можно запускать во время работы сервера, даже если в этот момент пользователи делают запросы к базе данных. Естественно, пока происходит копирование таблиц, пользователям будет запрещено вносить в них изменения.

Формат табличных файлов понятен только программе MySQL. Если же создать SQL-образы таблиц, то их можно будет перенести в другие СУБД. Кроме того, в некоторых ситуациях полезно просматривать такие SQL-инструкции. Предположим, к примеру, что потеря данных оставалась незамеченной на протяжении нескольких месяцев. Возможно, пользователи удалили какие-то записи и лишь позднее обнаружили, что это было сделано неправильно. Нужно восстановить только удаленные записи, но не известно, когда точно они были удалены. Если резервные копии хранятся в формате SQL, можно просмотреть архивы и поискать, когда последний раз встречались требуемые записи. Недостатком такого способа резервного копирования является то, что процедура восстановления занимает много времени, поскольку программа MySQL вынуждена выполнять каждую инструкцию из архива.

Для создания sql-образа таблицы предназначена утилита mysqldump. Она записывает текст инструкций в поток stdout, поэтому нужно перенаправить результаты ее работы в файл. В листинге 4.6 показан созданный этой утилитой образ таблицы db из базы данных mysql. Утилита была запущена с опцией --opt которая включает режим оптимальных установок.

# MySQL dump   
# 
# Host: localhost         Database: mysql
# 
# Server version          4.12.25-log
# 
# Table structure for table 'db' 
# 
DROP TABLE IF EXISTS db; 
CREATE TABLE db (
  Host char(60) binary NOT NULL default '',
  Db char(64) binary NOT NULL default '',
  User char(16) binary NOT NULL default '', 
  Select_priv enum('N', 'Y') NOT NULL default 'N', 
  Insert_priv enum('N', 'Y') NOT NULL default 'N',
  Update_priv enum('N', 'Y') NOT NULL default 'N',
  Delete_priv enum('N', 'Y') NOT NULL default 'N',
  Create_priv enum('N', 'Y') NOT NULL default 'N',
  Drop_priv enum('N', 'Y') NOT NULL default 'N',
  Grant_priv enum('N', 'Y') NOT NULL default 'N',
  References_priv enum('N', 'Y') NOT NULL default 'N',
  Index_priv enum('N', 'Y') NOT NULL default 'N',
  Alter_priv enum('N', 'Y') NOT NULL default 'N',
  PRIMARY KEY (Host, Db, User),
  KEY User (User)
)TYPE=MyISAM COMMENT = 'Database privileges';

tt
# Dumping data for table 'db'
#

LOCK TABLES db WRITE;
INSERT INTO db VALUES
('%', 'test', '', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'N', 'Y', 'Y', 'Y'),
('%', 'test\\_%', '', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'N', 'Y', 'Y', 'Y'),
('Localhost', 'freetime', 'httpd', 'Y', 'Y', 'Y', 'Y', 'N', 'N', 'N', 'N', 'N', 'N');
UNLOCK TABLES;
Листинг 4.6.

He забудьте заблокировать все таблицы для записи, прежде чем запускать утилиту mysqldump. В противном случае целостность результатов не гарантируется. Предположим, имеется приложение, которое хранит информацию о клиентах и их электронных адресах. Создание учетной записи нового клиента включает добавление записи в таблицу client и последующую вставку одной или нескольких записей в таблицу email_address. Если параллельно с этим создавать резервную копию базы данных, то может оказаться, что в промежутке между созданием образов таблиц client и email_address приложение попытается обновить обе эти таблицы. Доступ к первой таблице будет запрещен, а ко второй — нет. В результате в архиве появятся адреса, не соответствующие ни одной записи таблицы клиентов.

Чтобы восстановить данные из такого архива, достаточно выполнить SQL-сценарий в интерпретаторе mysql. Можно просто перенаправить сценарий на вход этой утилиты или же воспользоваться ее командой source. Интерпретатор выполнит все инструкции сценария так, как если бы они были введены в командной строке.

Утилита mysqldump имеет режим создания текстового образа таблицы. В этом режиме для каждой архивируемой таблицы создаются два файла. Один из них имеет расширение .sql и содержит соответствующую инструкцию CREATE TABLE. Второй файл имеет расширение .txt и содержит записи таблицы, причем для разделения полей применяются символы табуляции. В листинге 4.7 показана команда, создающая текстовый образ таблицы dictionary в каталоге /tmp.

[/tmp]# mysqldump --verbose --tab=/tmp test dictionary
# Connecting to localhost...
# Retrieving table structure for table dictionary...
# Sending SELECT query... 
# Disconnecting from localhost...
Листинг 4.7.

Для восстановления данных из такого архива необходимо сначала создать таблицу, а затем выполнить инструкцию LOAD DATA INFILE, которая вставит записи в таблицу. Стандартный формат файла, создаваемого утилитой mysqldump, соответствует тому формату, который по умолчанию распознается инструкцией LOAD DATA INFILE. В листинге 4.8 демонстрируется загрузка данных в таблицу dictionary в среде mysql.

mysql> source /tmp/dictionary.sql
Query OK, 0 rows affected (0.00 sec)
mysql> LOAD DATA INFILE '/tmp/dictionary.txt' INTO TABLE dictionary;
Query OK, 104237 rows affected (1 min 27.70 sec)
Records: 104237 Deleted: 0 Skipped: 0 Warnings: 0
Листинг 4.8.

Создать файл, понимаемый инструкцией LOAD DATA INFILE, позволяет также инструкция SELECT с предложением INTO (листинг 4.9). Схему таблицы необходимо получить другим путем, например с помощью инструкции SHOW CREATE TABLE.

mysql> SELECT * FROM dictionary INTO OUTFILE 'tmp/dictionary.txt';
Query OK, 104237 rows affected (6.42 sec)
Листинг 4.9.

Один из способов восстановления таблиц заключается в использовании двоичного журнала. Достаточно преобразовать его содержимое в SQL-инструкции и выполнить их. Предварительно необходимо заблокировать все таблицы для записи или отключить всех клиентов от сервера. Преобразование двоичного журнала осуществляется с помощью утилиты mysqlbinlog (листинг 4.10). Результаты ее работы нужно направить в файл или интерпретатору mysql. Обратите внимание: инструкция SET меняет метку текущего времени сеанса, чтобы дата создания таблицы осталась неизменной.

# mysqlbinlog --offset=1 --short-form red-bin.001
use freetime;
SET TIMESTAMP=991767105;
UPDATE session SET LastAction = now() WHERE ID='fNbbnOLBYYlqesqa';
use freetime;
SET TIMESTAMP=991767134;
UPDATE session SET LastAction = now() WHERE ID='fNbbnOLBYYlqesqa';
use freetime;
SET TIMESTAMP=991767134;
DELETE FROM project_view WHERE Project=2 AND User=2;
use freetime;
SET TIMESTAMP=991767135;
INSERT INTO project_view VALUES (2, 2, now());
Листинг 4.10.
< Лекция 3 || Лекция 4: 1234 || Лекция 5 >
Александра Каева
Александра Каева
Дмитрий Черепенин
Дмитрий Черепенин

Какого года данный курс?