M
y
S
Q
L
Руководаво администратора
M
y
S
Q
L
A d m i n i s t r a t o r ' s
G u i d e
MySQLAB
M y S Q L Press 800 East 96th Street, Indianapolis, Indiana 46240 USA
M
y
S
Q
L
Руководство администратора
Компания MySQL AB
Издательский дом "Вильяме" Москва • Санкт-Петербург • Киев 2005
ББК 32.973.26-018.2.75 МП УДК 681.3.07
Издательский дом "Вильяме" Зав. редакцией С.Н. Тригуб Перевод с английского Я.П. Волковой, Д.Я. Иваненко, НА.
Мухина
Под редакцией Ю.Н. Артпеменко По общим вопросам обращайтесь в Издательский дом "Вильяме" по адресу:
[email protected], http://www.williamspublishing.com 115419, Москва, а/я 783, 03150, Киев, а/я 152.
Компания MySQL AB. МИ MySQL. Руководство администратора. : Пер. с англ. — М. : Издательский дом "Вильяме", 2005. — 624 с. — Парал. тит. англ. ISBN 5-8459-0805-1 (рус.) Эта книга, написанная специалистами компании MySQL AB, является всеобъемлющим справочником по установке, обслуживанию и администрированию сервера баз данных MySQL. По сути — это официальная документация фирмы производителя. В книге рассмотрен весь спектр вопросов, касающихся администрирования MySQL, а также представлена информация, предназначенная для опытных пользователей и администраторов. Как известно, MySQL занимает лидирующие позиции среди множества систем управления базами данных с открытым исходным кодом. Благодаря высокой производительности и простоте настройки, богатому выбору API-интерфейсов, а также функциональным средствам работы с сетями, сервер MySQL стал одним из наиболее удачных вариантов для разработки Webприложений, взаимодействующих с базами данных. Книга рассчитана на администраторов и разработчиков Web-приложений любой квалификации, а также на студентов и преподавателей соответствующих дисциплин. ББК 32.973.26-018.2.75
Вес названия программных продуктов являются зарегистрированными торговыми марками соответствующих фирм. Никакая часть настоящего издания ни в каких целях не может быть воспроизведена в какой бы то ни было форме и какими бы то ни было средствами, будь то электронные или механические, включая фотокопирование и запись на магнитный носитель, если на это нет письменного разрешения издательства MySQL Press. Authorized translation from the English language edition published by MySQL Press, Copyright © 2004 All rights reserved. No part of this book may be reproduced or transmitted in any form or by any means, electronic or mechanical, including photocopying, recording or by any information storage retrieval system, without permission from the Publisher. Russian language edition published by Williams Publishing House according to the Agreement with R&I Enterprises International, Copyright © 2005
ISBN 5-8459-0805-1 (рус.) ISBN 0-672-32634-5 (англ.)
© Издательский дом "Вильяме", 2005 © MySQL AB, 2004
Оглавление Об этой книге
14
От издательства
14
Глава 1. Общая информация
15
Глава 2. Установка MySQL
76
Глава 3. Использование программ MySQL
202
Глава 4. Администрирование баз данных
212
Глава 5. Репликация в MySQL
365
Глава 6. Оптимизация MySQL
402
Глава 7. Клиентские программы и утилиты MySQL
460
Глава 8. Механизмы хранения и типы таблиц в MySQL
498
Глава 9. Механизм хранения InnoDB
523
Глава 10. Введение в MaxDB
582
Приложение А. Поиск и устранение неполадок в программах MySQL
588
Приложение Б. Переменные окружения
612
Предметный указатель
614
Содержание Об этой книге
14
От издательства
14
Глава 1. Общая информация 1.1. Что собой представляет это руководство 1.1.1. Соглашения, используемые в руководстве 1.2. Что такое система управления базами данных MySQL 1.2.1. История MySQL 1.2.2. Основные возможности MySQL 1.2.3. Стабильность MySQL 1.2.4. Размеры таблиц MySQL 1.2.5. Решение "проблемы 2000 года" 1.3. Компания MySQL AB 1.3.1. Бизнес-модель и услуги, оказываемые MySQL AB 1.3.2. Контактная информация 1.4. Поддержка и лицензирование MySQL 1.4.1. Поддержка, предоставляемая компанией MySQL AB 1.4.2. Авторские права и лицензии на MySQL 1.4.3. Лицензии на MySQL 1.4.4. Логотипы и торговые марки MySQL AB 1.5. План разработки MySQL 1.5.1. Кратко о MySQL 4.0 1.5.2. Кратко о MySQL 4.1 1.5.3. MySQL 5.0: Очередной разрабатываемый выпуск 1.6. MySQL и будущее (списки TODO) 1.6.1. Новые средства, запланированные для версии 4.1 1.6.2. Новые средства, запланированные для версии 5.0 1.6.3. Новые средства, запланированные для версии 5.1 1.6.4. Новые средства, запланированные на ближайшее будущее 1.6.5. Новые средства, запланированные на отдаленное будущее 1.6.6. Новые средства, которые не планируются к реализации 1.7. Источники информации по MySQL 1.7.1. Списки рассылки MySQL 1.7.2. Поддержка сообщества пользователей MySQL в IRC 1.8. Соответствие стандартам MySQL 1.8.1. Стандарты, которым соответствует MySQL 1.8.2. Выбор режимов SQL 1.8.3. Запуск MySQL в режиме ANSI 1.8.4. Расширения стандартного SQL в MySQL 1.8.5. Отличия MySQL от стандартного SQL 1.8.6. Как MySQL работает с ограничениями 1.8.7. Известные ошибки и недостатки дизайна MySQL
15 15 16 18 19 20 22 23 25 26 27 30 31 31 32 32 35 37 37 39 41 41 41 42 43 43 46 47 48 48 56 56 57 57 57 58 61 68 70
Содержание Глава 2. Установка MySQL 2.1. Общие вопросы установки 2.1.1. Операционные системы, поддерживаемые MySQL 2.1.2. Выбор дистрибутива MySQL для установки 2.1.3. Как получить MySQL 2.1.4. Проверка целостности пакета с помощью контрольных сумм MD5 или GnuPG 2.1.5. Расположение каталогов установки 2.2. Стандартная установка MySQL из бинарного дистрибутива 2.2.1. Установка MySQL под Windows 2.2.2. Установка MySQL под Linux 2.2.3. Установка MySQL под Mac OS X 2.2.4. Установка MySQL под NetWare 2.2.5. Установка MySQL в других Unix-подобных системах 2.3. Установка MySQL из исходного дистрибутива 2.3.1. Обзор установки из исходного дистрибутива 2.3.2. Типичные опции сценария configure 2.3.3. Установка из исходного дерева разработки 2.3.4. Решение проблем компиляции MySQL 2.3.5. Замечания по поводу потоков MIT-pthreads 2.3.6. Установка MySQL из исходных дистрибутивов под Windows 2.3.7. Компиляция клиентских программ MySQL под Windows 2.4. Настройки и тестирование после установки 2.4.1. Постустановочные процедуры под Windows 2.4.2. Постустановочные процедуры под Unix 2.4.3. Автоматический запуск и останов MySQL 2.4.4. Запуск сервера MySQL и устранение неисправностей 2.4.5. Защита начальных учетных записей MySQL 2.5. Модернизация MySQL и возврат к старой версии 2.5.1. Модернизация версии 4.1 до 5.0 2.5.2. Модернизация версии 4.0 до 4.1 2.5.3. Модернизация версии 3.23 до 4.0 2.5.4. Модернизация версии 3.22 до 3.23 2.5.5. Модернизация версии 3.21 до 3.22 2.5.6. Модернизация версии 3.20 до 3.21 2.5.7. Модернизация MySQL под Windows 2.5.8. Обновление таблиц привилегий 2.5.9. Копирование баз данных MySQL на другую машину 2.6. Замечания по поводу конкретных операционных систем 2.6.1. Замечания по поводу Linux 2.6.2. Замечания по Max OS X 2.6.3. Замечания по Solaris 2.6.4. Замечания по BSD 2.6.5. Замечания по другим системам Unix 2.6.6. Замечания по OS/2 2.6.7. Замечания по BeOS 2.7. Замечания по поводу установки Perl 2.7.1. Установка Perl под Unix
7 76 77 77 79 90 90 93 95 95 107 109 112 114 117 118 121 124 127 131 133 136 136 137 138 144 146 149 153 154 154 159 163 165 166 167 167 168 170 170 178 179 183 187 196 197 197 197
8
Содержание 2.7.2. Установка ActiveState Perl под Windows 2.7.3. Проблемы использования интерфейса Perl DBI/DBD
198 199
Глава 3. Использование программ MySQL 3.1. Обзор программ MySQL 3.2. Запуск MySQL-программ 3.3. Задание опций программы 3.3.1. Использование опций в командной строке 3.3.2. Использование файлов опций 3.3.3. Использование переменных окружения для задания опций 3.3.4. Использование опций для установки программных переменных
202 202 203 204 204 206 210 210
Глава 4. Администрирование баз данных 4.1. Сервер MySQL и сценарии запуска сервера 4.1.1. Обзор серверных сценариев и утилит 4.1.2. Расширенный MySQL-сервер mysqld-max 4.1.3. Сценарий запуска сервера mysqld_safe 4.1.4. Сценарий запуска сервера mysql.server 4.1.5. Программа mysqldmulti для управления множественными MySQL-серверами 4.2. Конфигурирование сервера MySQL 4.2.1. Опции командной строки mysqld 4.2.2. Режим SQL сервера 4.2.3. Системные переменные сервера 4.2.4. Переменные состояния сервера 4.3. Общие проблемы безопасности 4.3.1. Общие принципы, касающиеся безопасности системы 4.3.2. Как защитить MySQL от хакеров 4.3.3. Опции запуска для mysqld, касающиеся безопасности 4.3.4. Вопросы безопасности и оператор LOAD DATA LOCAL 4.4. Система привилегий доступа MySQL 4.4.1. Функции системы привилегий 4.4.2. Как работает система привилегий 4.4.3. Привилегии, предоставляемые MySQL 4.4.4. Подключение к серверу MySQL 4.4.5. Управление доступом, этап первый: верификация подключения 4.4.6. Управление доступом, этап второй: верификация запросов 4.4.7. Когда изменения в привилегиях вступают в силу 4.4.8. Причины появления ошибок отказа в доступе (Access denied) 4.4.9 Хеширование паролей в MySQL 4.1 4.5. Управление учетными записями пользователей MySQL 4.5.1. Имена пользователей и пароли в MySQL 4.5.2. Добавление новых учетных записей в MySQL 4.5.3. Удаление пользовательских учетных записей из MySQL 4.5.4. Ограничение ресурсов учетной записи 4.5.5. Назначение паролей для учетных записей 4.5.6. Как обезопасить свой пароль 4.5.7. Использование безопасных соединений 4.6. Предотвращение аварий и восстановление системы
212 212 212 213 215 218 219 223 223 232 234 260 265 265 268 270 271 272 272 273 277 281 282 286 289 289 295 301 301 303 306 307 309 310 311 318
Содержание 4.6.1. Резервное копирование баз данных 4.6.2. Обслуживание и восстановление таблиц после аварий 4.6.3. Установка графика обслуживания таблиц 4.6.4. Как получить информацию о таблице 4.7. Локализация MySQL и интернациональное применение 4.7.1. Набор символов для представления данных и сортировки 4.7.2. Установка языка сообщений об ошибках 4.7.3. Добавление нового набора символов 4.7.4. Массивы определения символов 4.7.5. Поддержка функций по упорядочиванию строк 4.7.6. Поддержка многобайтных символов 4.7.7. Проблемы с наборами символов 4.8. Журнальные файлы MySQL 4.8.1. Журнал ошибок 4.8.2. Общий журнал запросов 4.8.3. Журнал регистрации обновлений 4.8.4. Бинарный журнал регистрации 4.8.5. Журнал медленных запросов 4.8.6. Обслуживание журнальных файлов 4.9. Запуск нескольких серверов MySQL на одном и том же компьютере 4.9.1. Запуск нескольких серверов в Windows 4.9.2. Запуск нескольких серверов под Unix 4.9.3. Использование клиентских программ в окружении с несколькими серверами 4.10. Кэш запросов MySQL 4.10.1. Как работает кэш запросов 4.10.2. Опции SELECT для кэша запросов 4.10.3. Конфигурирование кэша запросов 4.10.4. Состояние кэша запросов и его обслуживание Глава 5. Репликация в MySQL 5.1. Введение в репликацию 5.2. Обзор реализации репликации 5.3. Детали реализации процесса репликации 5.3.1. Состояние потока репликации главного сервера 5.3.2. Состояние потока репликации ввода/вывода подчиненного сервера 5.3.3. Состояние потока SQL репликации подчиненного сервера 5.3.4. Журнал ретрансляции и файлы состояния 5.4. Настройка репликации 5.5. Совместимость репликации между версиями MySQL 5.6. Модернизация установок репликации 5.6.1. Модернизация репликации до версии 4.0 или 4.1 5.6.2. Модернизация репликации до версии 5.0 5.7. Возможности репликации и известные проблемы 5.8. Опции запуска репликации 5.9. Часто задаваемые вопросы по репликации 5.10. Поиск неисправностей в системе репликации 5.11. Сообщения об ошибках репликации
9 318 320 333 334 340 340 341 342 343 344 344 344 345 346 346 347 348 351 351 352 354 358 359 360 361 362 362 363 365 365 366 367 369 369 371 371 373 378 378 379 379 380 384 393 399 400
10
Содержание
Глава 6. Оптимизация MySQL 6.1. Обзор оптимизации 6.1.1. Ограничения и компромиссы конструкции MySQL 6.1.2. Проектирование переносимых приложений 6.1.3. Для чего мы использовали MySQL 6.1.4. Набор тестов производительности MySQL 6.1.5. Использование собственных тестов производительности 6.2. Оптимизация операторов SELECT и других запросов 6.2.1. Синтаксис оператора EXPLAIN (получение информации о SELECT) 6.2.2. Ожидаемая производительность запросов 6.2.3. Скорость выполнения запросов SELECT 6.2.4. Как MySQL оптимизирует конструкцию WHERE 6.2.5. Как MySQL оптимизирует выражения OR 6.2.6. Как MySQL оптимизирует IS NULL 6.2.7. Как MySQL оптимизирует DISTINCT 6.2.8. Как MySQL оптимизирует LEFT JOIN и RIGHT JOIN 6.2.9. Как MySQL оптимизирует ORDER BY 6.2.10. Как MySQL оптимизирует LIMIT 6.2.11. Как избежать сканирования таблиц 6.2.12. Скорость выполнения запросов INSERT 6.2.13. Скорость выполнения запросов UPDATE 6.2.14. Скорость выполнения запросов DELETE 6.2.15. Другие советы по оптимизации 6.3. Вопросы блокировки 6.3.1. Методы блокировки 6.3.2. Вопросы блокировки таблиц 6.4. Оптимизация структуры базы данных 6.4.1. Конструкторские решения 6.4.2. Делайте объем данных как можно меньше 6.4.3. Индексы столбцов 6.4.4. Составные индексы 6.4.5. Как MySQL использует индексы 6.4.6. Кэш ключей MylSAM 6.4.7. Как MySQL подсчитывает открытые таблицы 6.4.8. Как MySQL открывает и закрывает таблицы 6.4.9. Недостатки создания множества таблиц в одной базе данных 6.5. Оптимизация сервера MySQL 6.5.1. Настройка параметров системы и запуска 6.5.2. Настройка параметров сервера 6.5.3. Как компиляция и компоновка влияют на скорость MySQL 6.5.4. Как MySQL использует память 6.5.5. Как MySQL использует DNS 6.6. Вопросы использования дисков 6.6.1. Использование символических ссылок
402 402 403 403 405 405 406 407 408 415 416 416 418 419 419 420 421 423 424 424 426 427 427 430 430 433 435 435 435 436 437 438 441 446 446 447 448 448 449 451 453 454 455 456
Глава 7. Клиентские программы и утилиты MySQL 7.1. Обзор сценариев и утилит клиентской стороны
460 460
Содержание 7.2. myisampack - генератор сжатых таблиц MySQL, доступных только для чтения 7.3. Инструмент командной строки mysql 7.3.1. Команды mysql 7.3.2. Запуск SQL-операторов из текстового файла 7.3.3. Советы по mysql 7.4. Программа администрирования MySQL-сервера mysqladmin 7.5. Утилита работы с бинарными журналами mysqlbinlog 7.6. Центр управления MySQL - mysqlcc 7.7. Программа обслуживания и восстановления таблиц mysqlcheck 7.8. Программа резервного копирования баз данных mysqldump 7.9. Программа резервного копирования базы данных mysqhotcopy 7.10. Программа импорта данных mysqlimport 7.11. Программа просмотра баз данных, таблиц и столбцов mysqlshow 7.12. Утилита объяснения кодов ошибок реггог 7.13. Утилита замены строк replace
11
461 467 471 475 476 477 480 483 485 487 492 493 495 497 497
Глава 8. Механизмы хранения и типы таблиц в MySQL 8.1. Механизм хранения My IS AM 8.1.1. Опции запуска MylSAM 8.1.2. Пространство, необходимое для ключей 8.1.3. Форматы хранения данных в таблицах MylSAM 8.1.4. Проблемы, связанные с таблицами MylSAM 8.2. Механизм хранения MERGE 8.2.1. Проблемы, связанные с таблицами MERGE 8.3. Механизм хранения данных MEMORY (HEAP) 8.4. Механизм хранения данных BDB (BerkleyDB) 8.4.1. Операционные системы, поддерживающие BDB 8.4.2. Установка BDB 8.4.3. Опции запуска BDB 8.4.4. Характеристики таблиц BDB 8.4.5. Что должно быть исправлено в механизме хранения BDB 8.4.6. Ограничения при использовании таблиц BDB 8.4.7. Ошибки, которые могут возникать при использовании таблиц BDB 8.5. Механизм хранения ISAM
498 500 502 504 504 507 509 511 513 515 516 516 517 517 520 520 520 521
Глава 9. Механизм хранения InnoDB 9.1. Обзор InnoDB 9.2. Контактная информация, касающаяся InnoDB 9.3. Таблицы InnoDB в MySQL 3.23 9.4. Конфигурация InnoDB 9.5. Опции запуска InnoDB 9.6. Создание табличного пространства InnoDB 9.6.1. Проблемы, связанные с инициализацией InnoDB 9.7. Создание таблиц InnoDB 9.7.1. Как использовать транзакции InnoDB в разных API-интерфейсах 9.7.2. Преобразование таблиц MylSAM в формат InnoDB 9.7.3. Как работают столбцы AUTOJNCREMENT в InnoDB 9.7.4. Ограничения внешнего ключа (FOREIGN KEY)
523 523 524 524 525 530 534 535 535 536 537 538 539
12
Содержание 9.7.5. InnoDB и репликация в MySQL 9.7.6. Использование табличного пространства для каждой таблицы 9.8. Добавление и удаление файлов данных и файлов журналов InnoDB 9.9. Создание резервных копий и восстановление базы данных InnoDB 9.9.1. Принудительное восстановление 9.9.2. Контрольные точки 9.10. Перенос базы данных InnoDB на другой компьютер 9.11. Транзакционная модель InnoDB и блокирование 9.11.1. InnoDB и режим автоматической фиксации AUTOCOMMIT 9.11.2. InnoDB и уровень изоляции транзакций (TRANSACTION ISOLATION LEVEL) 9.11.3. Согласованное чтение без блокировки 9.11.4. Чтения с блокировкой: SELECT... FOR UPDATE и SELECT... LOCK IN SHARE MODE 9.11.5. Блокировка следующего ключа: устранение "проблемы с фантомом" 9.11.6. Пример работы согласованного чтения в InnoDB 9.11.7. Блокировка, устанавливаемая различными SQL-операторами в InnoDB 9.11.8. В каких случаях MySQL явно выполняет фиксацию или откат транзакции 9.11.9. Обнаружение взаимных блокировок и откат 9.11.10. Как справляться с взаимными блокировками 9.12. Советы по настройке производительности InnoDB 9.12.1. SHOW INNODB STATUS и мониторы InnoDB 9.13. Реализация многовариантности 9.14. Структуры таблиц и индексов 9.14.1. Физическая структура индекса 9.14.2. Буферизация вставок 9.14.3. Адаптивный хешированный индекс 9.14.4. Физическая структура записи 9.15. Управление файловым пространством и дисковый ввод-вывод 9.15.1. Дисковый ввод-вывод 9.15.2. Использование низкоуровневых устройств для табличного пространства 9.15.3. Управление файловым пространством 9.15.4. Дефрагментация таблицы 9.16. Обработка ошибок 9.16.1. Коды ошибок InnoDB 9.16.2. Коды ошибок операционной системы 9.17. Ограничения таблиц InnoDB 9.18. Поиск и устранение неполадок в InnoDB 9.18.1. Поиск и устранение неполадок в операциях словаря данных InnoDB
Глава 10. Введение в MaxDB 10.1. История MaxDB 10.2. Лицензирование и поддержка 10.3. Ссылки, касающиеся MaxDB 10.4. Базовые концепции MaxDB 10.5. Отличия возможностей MaxDB и MySQL
543 544 546 547 548 550 550 551 551 551 553 554 555 556 557 558 559 559 561 563 568 568 569 569 570 570 571 571 572 572 573 574 574 575 577 579 580 582 582 582 583 583 583
Содержание 10.6. Средства взаимодействия между MaxDB и MySQL 10.7. Зарезервированные слова MaxDB
13 584 584
Приложение А. Поиск и устранение неполадок в программах MySQL АЛ. Как определить причину проблемы А.2. Наиболее общие ошибки при работе с программами MySQL А.2.1. Доступ запрещен А.2.2.Невозможно подключиться к [локальному] серверу MySQL А.2.3. Клиент не поддерживает протокол аутентификации А.2.4. Пароль не принимается при интерактивном вводе А.2.5. Хост 'имяхоста' заблокирован А.2.6. Слишком много подключений А.2.7. Недостаточно памяти А.2.8. Сервер MySQL потерян А.2.9. Слишком большой пакет А.2.10. Ошибки связи и прерванные соединения А.2.11. Переполнение таблицы А.2.12. Невозможно создать/записать файл А.2.13. Команды не синхронизированы А.2.14. Игнорируется пользователь А.2.15. Таблица 'имятаблицы' не существует А.2.16. Невозможно инициализировать набор символов А.2.17. Файл не найден А.З. Вопросы, связанные с установкой А.3.1. Проблемы компоновки клиентской библиотеки MySQL А.З.2. Как запускать MySQL от имени обычного пользователя А.3.3. Проблемы с правами доступа к файлам А.4. Вопросы, касающиеся администрирования А.4.1. Как сбросить пароль для root А.4.2. Что делать, если MySQL терпит крах А.4.3. Как MySQL обрабатывает переполнение диска А.4.4. Где MySQL хранит временные файлы А.4.5. Как защитить или изменить файл сокета MySQL /tmp/mysql.sock А.4.6. Проблемы с временными зонами
588 588 590 590 590 592 593 593 594 594 594 595 597 598 598 599 599 599 600 600 601 601 603 603 604 604 606 609 609 610 611
Приложение Б. Переменные окружения
612
Предметный указатель
614
Об этой книге Исходными материалами для этой книги послужили разделы онлайновой документации по MySQL (http://www.mysql.com), посвященные вопросам установки, обслуживания и администрирования сервера баз данных MySQL. Книга представляет собой полезный и полный справочник по всему спектру вопросов, от установки до репликации, от оптимизации базы данных до хитросплетений механизма хранения InnoDB. Первоначально это руководство было написано Майклом Монти Видениусом (Michael "Monty" Widenius) и Дэвидом Аксмарком (David Axmark), а теперь его поддержкой занимается группа разработки документации по MySQL. Большой вклад в подготовку данной книги внесли Поль Дюбуа (Paul DuBois), Стефан Хинц (Stefan Hinz) и Аржен Ленц (Arjen Lentz) из группы разработки документации.
От издательства Вы, читатель этой книги, и есть главный ее критик и комментатор. Мы ценим ваше мнение и хотим знать, что было сделано нами правильно, что можно было сделать лучше и что еще вы хотели бы увидеть изданным нами. Нам интересно услышать и любые другие замечания, которые вам хотелось бы высказать в наш адрес. Мы ждем ваших комментариев и надеемся на них. Вы можете прислать нам бумажное или электронное письмо, либо просто посетить наш Web-сервер и оставить свои замечания там. Одним словом, любым удобным для вас способом дайте нам знать, нравится или нет вам эта книга, а также выскажите свое мнение о том, как сделать наши книги более интересными для вас. Посылая письмо или сообщение, не забудьте указать название книги и ее авторов, а также ваш обратный адрес. Мы внимательно ознакомимся с вашим мнением и обязательно учтем его при отборе и подготовке к изданию последующих книг. Наши координаты: E-mail: WWW:
[email protected] http: //www.williamspublishing.com
Информация для писем из: России:
115419, Москва, а/я 783
Украины:
03150, Киев, а/я 152
1 Общая информация
П
рограммное обеспечение MySQL® представляет собой очень быстрый, многопоточный, многопользовательский и надежный сервер баз данных SQL (Structured Query Language - язык структурированных запросов). Сервер MySQL предназначен как для обслуживания критически важных, сильно загруженных производственных систем, так и для встраивания в программное обеспечение массового применения. MySQL - торговая марка, принадлежащая MySQL AB. Программное обеспечение MySQL распространяется в соответствие с двойной лицензией (Dual License). Пользователь может использовать его либо как бесплатный продукт с открытым исходным кодом (Open Source/Free Software) на условиях общедоступной лицензии GNU General Public License, либо приобрести стандартную коммерческую лицензию у MySQL AB. Дополнительную информацию можно найти в разделе 1.4. Актуальная информация о программном обеспечении MySQL доступна на Web-сайте MySQL (http: //www. mysql. com/).
1.1. Что собой представляет это руководство Настоящее руководство составлено на основании тех разделов справочного руководства по MySQL (MySQL Referense Guide), которые посвящены вопросам администрирования баз данных. Здесь описывается установка программного обеспечения, конфигурирование сервера, ежедневные операции по обслуживанию, поддержке таблиц и репликации данных. Сопутствующая книга, "MySQL. Справочник по языку " ("MySQL Language Reference"), служит справочником по языку SQL, используемому для выполнения запросов к базам данных MySQL. В нем описываются языковые конструкции, функции и операции, типы данных столбцов таблиц и синтаксис операторов SQL. Это руководство касается MySQL 5.0.1, но также применимо и к более старым версиям MySQL (таким как 3.23 или 4.0), поскольку функциональные изменения между версиями специальным образом отмечаются. Поскольку настоящее руководство служит справочником, оно не включает в себя общие сведения об SQL и концепциях реляционных баз данных. Оно также не обучает работе с операционной системой или интерпретатором командной строки. Программное обеспечения баз данных MySQL постоянно развивается, и его справочное руководство обновляется настолько часто, насколько это возможно. Последняя версия руководства доступна в Internet по адресу http://dev.mysql.com/doc/ в различных форматах, включая HTML, PDF и Windows CHM.
16
Глава 1. Общая информация
Если у вас есть предложения, касающиеся любых дополнений и исправлений настоящего руководства, пожалуйста, присылайте их группе, занятой созданием документации, по адресу docs@mysql. com. Первоначально это руководство было написано Дэвидом Аксмарком (David Axmark) и Майклом Монти Видениусом (Michael "Monty" Widenius). Теперь его поддержкой занимается группа разработки документации по MySQL (MySQL Documentation Team), в состав которой входят Аржен Ленц (Arjen Lentz), Поль Дюбуа (Paul DuBois) и Стефан Хинц (Stefan Hinz). Авторские права на это руководство (2004 год) принадлежат шведской компании MySQL AB (см. раздел 1.4.2).
1.1.1. Соглашения, используемые в руководстве В настоящем руководстве приняты следующие типографские соглашения: • моноширинный Моноширинным шрифтом представляются имена и опции команд, SQLоператоры, имена баз данных, таблиц и столбцов, код на языках С и Perl, имена файлов и переменных окружения, а также URL-адреса. Например: "Чтобы увидеть, как работает mysqladmin, запустите его с опцией —help". • моноширинный с полужирным начертанием С помощью моноширинного шрифта с полужирным начертанием обозначается пользовательского ввод в примерах. • моноширинный с курсивным начертанием Моноширинный шрифт с курсивным начертанием используется для обозначения ввода изменяющейся информации, когда пользователь должен подставлять то или иное значение. • 'с1 Моноширинный шрифт и одинарные кавычки применяются для задания последовательностей символов, например: "Для определения шаблона используйте символ • %'". • курсив С помощью курсива выделяются важные слова и фраза, например, так. • полужирный Шрифт с полужирным начертанием используется для заголовков таблиц, а также для выделения особо важных фраз. Когда необходимо показать команды, которые выполняются в среде какой-либо программы, перед командами помещается специальное приглашение. Например, shell> обозначает, что команда запускается в среде оболочки, a mysql> показывает, что оператор выполняется с помощью клиентской программы mysql. shell> введите команду оболочки mysql> введите оператор mysql Здесь через "shell" обозначен используемый вами командный интерпретатор. В UNIX это обычно программа, подобная sh или csh. Эквивалентными программами в Windows являются command.exe или cmd.exe, обычно запускаемые в окне консоли.
1.1. Что собой представляет это руководство
17
При вводе команды или оператора, показанного в примере, приглашение вводить не нужно. В приведенном выше примере пользовательский ввод представлен полужирным начертанием. Изменяющаяся информация, вместо которой нужно подставлять выбранное вами значение, выделяется курсивным начертанием. Имена баз данных, таблиц и их столбцов часто подставляются в аргументы операторов. В настоящем руководстве такие подстановки обязательно выделяются: имя_БДу имя_таблицы, имя_столбца. Например, вы можете встретить в книге что-нибудь такое: mysql> SELECT имя_столбца FROM имя_БД.имя_таблицы; Это означает, что при вводе подобного оператора потребуется указать реальные имена базы данных, таблицы и столбца, например, следующим образом: mysql> SELECT author_name FROM biblio_db.author_list; Ключевые слова SQL нечувствительны к регистру, то есть их можно вводить как заглавными, так и прописными буквами. В настоящем руководстве ключевые слова представлены заглавными буквами. В описаниях синтаксиса для обозначения необязательных слов или конструкций используются квадратные скобки (' [' и ' ] ' ) . В приведенном ниже примере IF EXISTS является необязательной частью выражения: DROP TABLE [IF EXISTS] имя_таблицы; Когда элемент синтаксиса предусматривает несколько альтернатив, они разделяются с помощью вертикальной черты ('Г). Если из набора возможных альтернатив может быть выбран один элемент, последовательность вариантов помещается в квадратные скобки: TRIM [[BOTH | LEADING | TRAILING] [ост_строка] FROM строка]; В случае если из набора возможных альтернатив должен быть выбран один элемент, альтернативные варианты перечисляются в фигурных скобках: {DESCRIBE | DESC} имя_таблицы [имя_столбца \
групповой_символ];
С помощью троеточия ( . . . ) обозначается пропущенная часть выражения; это позволяет сократить представление сложного синтаксиса. Например, INSERT... SELECT представляет собой сокращенную форму записи оператора INSERT и следующего за ним оператора SELECT. Троеточие также означает, что предшествующий элемент синтаксиса может повторяться. В следующем примере можно задать множество значений опция_сброса, каждое из которых, кроме первого, предваряется запятой: RESET опция_сброса
[,
опция_сброса]
...
Команды установки значения переменных оболочки представлены в соответствие с синтаксисом оболочки Bourne. Например, последовательность, устанавливающая значение переменной оболочки и запускающая команду, выглядит следующим образом: s h e l l > ИМЯ_ПЕРЕМЕННОЙ=значение команда Если используется csh или tcsh, команды вводятся по-другому. Приведенная выше последовательность будет выглядеть так: s h e l l > setenv ИМЯ_ПЕРЕМЕННОЙ значение s h e l l > команда
18
Глава 1. Общая информация
1.2. Что такое система управления базами данных MySQL Разработкой, распространением и поддержкой MySQL, наиболее популярной системы управления базами данных (СУБД) с открытым исходным кодом, занимается компанией MySQL AB. MySQL AB - коммерческая компания, основанная разработчиками MySQL, строит свой бизнес на предоставлении услуг, так или иначе связанных с СУБД MySQL. Более подробную информацию о компании MySQL AB можно найти в разделе 1.3. Кроме того, на сайте MySQL (http://www.mysql.com/) представлена наиболее актуальная информация о СУБД MySQL и компании MySQL AB. • MySQL - это система управления базами данных. База данных представляет собой структурированный набор данных. Она может содержать различную информацию - от простого списка покупок до огромного объема данных, используемого в корпоративной сети. • MySQL - это система управления реляционными базами данных. Реляционная база данных хранит информацию в отдельных таблицах, а не в одном большом хранилище, благодаря чему достигается высокая производительность и гибкость. Часть "SQL" слова "MySQL" обозначает "Structured Query Language" ("Язык структурированных запросов"). SQL - наиболее общий стандартизованный язык доступа к базам данных; он соответствует стандарту ANSI/ISO SQL. Стандарт SQL впервые был принят в 1986 году и на настоящее время существует несколько его версий. В настоящем руководстве "SQL-92" ссылается на стандарт, принятый в 1992 году, "SQL: 1999" - на стандарт, принятый в 1999 году, и "SQL:2003" - на текущую версию стандарта. В дальнейшем под "стандартом SQL" имеется в виду текущая версия данного стандарта. • MySQL - это система с открытым исходным кодом. Открытость исходного кода означает, что любой желающий имеет возможность использовать и модифицировать это программное обеспечение по своему усмотрению. Получить и развернуть программное обеспечение MySQL можно из Internet, причем совершенно бесплатно. Каждый пользователь, при желании, может изучить исходные тексты и изменить их в соответствии со своими потребностями. Программное обеспечение MySQL распространяется по лицензии GPL (GNU General Public License), которая регламентирует, что разрешено, а что нет в отношении программного обеспечения. Если по тем или иным причинам лицензия GPL не устраивает либо код MySQL требуется встраивать в коммерческие приложения, следует приобрести коммерческую лицензированную версию у компании MySQL AB (см. раздел 1.4.3). • Сервер баз данных MySQL - очень быстрый, надежный и простой в эксплуатации сервер. Если это как раз то, что вы ищете, стоит с ним поработать. Сервер MySQL включает в себя практичный набор средств, разработанных в тесной кооперации с сообществом пользователей. Результаты сравнительных тестов производительности MySQL и других СУБД доступны по адресу http://dev.mysql.com/techresources/crash-me.php. Изначально сервер MySQL был разработан для более быстрого управления большими базами данных, чем существующие решения в
1.2. Что такое система управления базами данных MySQL
19
этой области, и на протяжении ряда лет успешно эксплуатировался в средах, к которым предъявлялись весьма высокие требования. Несмотря на то что MySQL пребывает в непрекращающемся процессе разработки, на сегодняшний день он предоставляет богатый набор удобных в эксплуатации средств и функций. Присущие серверу MySQL возможности сетевого взаимодействия, производительность и безопасность делают его удачным вариантом для работы с базами данных в Internet. • Сервер MySQL работает в клиент-серверных и встроенных системах. СУБД MySQL является клиент-серверной системой, включающей многопоточный SQL-сервер, поддерживающий различные платформы, несколько клиентских программ и библиотек, инструменты администрирования и широкий диапазон программных интерфейсов приложений (API-интерфейсов). Сервер MySQL существует также и в форме встраиваемое многопоточной библиотеки, которую можно связывать с разрабатываемыми приложениями, чтобы получить более компактные, быстрые и легкоуправляемые продукты. • Доступен огромный объем программного обеспечения MySQL, написанного независимыми разработчиками. Весьма вероятно, что предпочитаемое вами приложение и язык уже поддерживают сервер баз данных MySQL. "MySQL" произносится как "май-эс-кю-эл" (а не "май-сиквел"), однако никто не против, если вы будете произносить название "MySQL" как вам заблагорассудится.
1.2.1. История MySQL Все началось с намерения подключиться с помощью mSQL к нашим таблицам данных, используя наши собственные низкоуровневые (ISAM) процедуры. Не особо долгое тестирование показало, что mSQL не обладает достаточной производительностью и гибкостью, дабы полностью удовлетворить существующие у нас требования. В итоге был создан новый SQL-интерфейс к нашей базе данных, который обладал почти таким же APIинтерфейсом, что и mSQL. Этот API-интерфейс был разработан так, чтобы существенно упростить перенос кода независимых разработчиков, ориентированного на взаимодействие с mSQL, на новую платформу, связанную с MySQL. Происхождение наименования "MySQL" неоднозначно. Наименования нашего базового каталога и огромного количества библиотек и инструментов имели префикс " т у " в течение более 10 лет. С другой стороны, дочку одного из наших соучредителей, Монти Видениуса (Monty Widenius), тоже звали Май (My). Какое именно из этих двух обстоятельств стало причиной появления наименования MySQL - до сих пор является тайной за семью печатями, даже для нас. Кличка дельфина MySQL, изображенного на нашем логотипе - Сакила (Sakila) - была выбрана основателями компании MySQL AB из большого списка кличек, предложенных пользователями в процессе дискуссии "Дайте кличку дельфину". Победила кличка, предложенная Эмброузом Твибейзом (Ambrose Twebaze), разработчиком программного обеспечения с открытым исходным кодом из Свазиленда (Африка). Как утверждал Эмброуз, кличка Сакила своими корнями уходит в Си-Свати (SiSwati) - язык, на котором говорят в Свазиленде. Сакила - это также название города в Аруше (Танзания), рядом с родной страной Эмброуза, Угандой.
20
Глава 1. Общая информация
1.2.2. Основные возможности MySQL Ниже представлен список наиболее важных характеристик программного обеспечения баз данных MySQL. Дополнительную информацию о текущих и планируемых возможностях можно получить в разделе 1.5. • Внутренние характеристики и переносимость. • Написан на языках С и C++. • Протестирован на широком спектре различных компиляторов. • Работает на множестве различных платформ. • Для обеспечения переносимости использует инструменты GNU - Automake, Autoconf и Libtool. • Доступны API-интерфейсы для С, C++, Eiffel, Java, Perl, PHP, Python, Ruby и Tel. • Полностью многопоточный с использованием потоков ядра. Может работать в многопроцессорных системах. • Обеспечивает транзакционный и нетранзакционный механизмы хранения. • Использует очень быстрые дисковые таблицы (MylSAM) со сжатием индексов на основе бинарных деревьев (В-деревьев). • Сравнительно простое добавление другого механизма хранения. Это удобно, если требуется добавить SQL-интерфейс к базе данных собственной разработки. • Очень быстрая система распределения памяти, основанная на потоках. • Очень быстрые соединения, использующие оптимизированные однопроходные мультисоединения. • Хранимые в памяти хеш-таблицы, которые используются в качестве временных таблиц. • Функции SQL реализованы с использованием высоко оптимизированной библиотеки классов и должны выполняться предельно быстро. Как правило, какого-либо распределения памяти после инициализации запроса не выполняется. • Код MySQL протестирован с помощью инструментов поиска утечки памяти, как коммерческих, так и с открытым исходным кодом. • Сервер доступен как отдельная программа для использования в клиентсерверной сетевой среде. Кроме того, он также поставляется в виде библиотеки, которая может быть встроена в отдельные автономные приложения. Такие приложения могут применяться в изолированной среде или среде, не имеющей доступа к сети. • Типы столбцов • Множество типов данных для столбцов таблиц: знаковые/беззнаковые целые ДЛИНОЙ В 1, 2, 3, 4 И 8 байт; ТИПЫ FLOAT, DOUBLE, CHAR, VARCHAR, TEXT, BLOB, DATE, TIME, DATETIME, TIMESTAMP, YEAR, SET, ENUM и пространственные типы OpenGIS.
• Записи фиксированной и переменной длины. • Операторы и функции. • Полная поддержка операций и функций в конструкциях SELECT и WHERE запросов, например:
1.2. Что такое система управления базами данных MySQL
21
raysql> SELECT CONCAT(first_name, ' ' , lastjiame) -> FROM c i t i z e n -> WHERE income/dependents > 10000 AND age > 30; •
Полная поддержка конструкций GROUP BY и ORDER BY. Поддержка групповых функций (COUNT (), COUNT (DISTINCT . . . ) , AVG(), STD(), SUM(), MAX(), MIN() И GROUP_CONCAT()).
•
Поддержка LEFT OUTER JOIN и RIGHT OUTER JOIN как с синтаксисом SQL, так и с синтаксисом ODBC. • Поддержка псевдонимов для таблиц и столбцов, как того требует стандарт SQL. •
Операторы DELETE, INSERT, REPLACE и UPDATE возвращают количество строк, которые были изменены. Вместо этого можно задать возврат количества строк, соответствующих запросу, для чего потребуется установить соответствующий флаг при подключении к серверу. • Специфическая для MySQL команда SHOW может быть использована для извлечения информации о базах данных, таблицах и индексах. Команда EXPLAIN позволяет просмотреть, как оптимизатор выполняет запрос. •
Имена функций не конфликтуют с именами таблиц и столбцов. Например, ABS - абсолютно корректное имя столбца. Единственное ограничение, которое накладывается на вызов функций, - это то, что между именем функции и следующей за ним открывающей скобкой ' (' не должно быть пробелов.
•
Можно смешивать таблицы из разных баз данных в одном запросе (как в MySQL 3.22). • Безопасность. • Система, основанная на паролях и привилегиях, является исключительно гибкой и безопасной и позволяет организовать верификацию средствами хоста. Пароли защищены, поскольку весь трафик паролей во время соединения с сервером шифруется. • Масштабируемость и ограничения. • Поддерживает работу баз данных огромных объемов. Например, компания MySQL AB применяет сервер MySQL для обслуживания базы данных, содержащей 50 миллионов записей. Известна также организация, использующая сервер MySQL для обслуживания базы данных из 60 000 таблиц, которая хранит около 5 миллиардов записей. • Разрешается иметь до 64 индексов на таблицу (в версиях, предшествующих MySQL 4.1.2, допускалось до 32 индексов). Каждый индекс может содержать от 1 до 16 столбцов или частей столбцов. Максимальная ширина индекса составляет 1000 байт (500 байт в версиях, предшествующих MySQL 4.1.2). Для индекса может применяться префикс столбцов с типами CHAR, VARCHAR, BLOB и TEXT. • Сетевая связность • Клиенты могут подключаться к серверу MySQL, используя сокеты TCP/IP на любой платформе. В Windows-системах семейства NT (NT, 2000 или ХР) клиенты могут подключаться с использованием именованных каналов. В системах на базе UNIX клиенты могут подключаться через файлы сокетов UNIX-доменов.
22
Глава 1. Общая информация •
Интерфейс Connector/ODBC позволяет MySQL поддерживать клиентские программы, которые используют ODBC-соединения. Например, для подключения к серверу MySQL можно использовать MS Access. Клиентское программное обеспечение может выполняться под управлением Windows или UNIX. Исходные тексты интерфейса Connector/ODBC доступны. Поддерживаются все функции ODBC 2.5, равно как и множество других. • Интерфейс Connector/JDBC позволяет MySQL взаимодействовать с клиентскими программами на Java, в которых используются JDBC-подключения. Клиентское программное обеспечение может выполняться под управлением Windows или UNIX. Исходные тексты интерфейса Connector/JDBC доступны.
• Локализация • Сервер может выдавать клиентам сообщения об ошибках на разных языках. • Полностью поддерживаются несколько кодовых таблиц, включая l a t i n l (ISO8859-1), german, big5, ujis и другие. Например, в именах таблиц и столбцов разрешается применять скандинавские символы наподобие 'а', 'а' и 'б'. Начиная с версии MySQL 4.1, также обеспечивается поддержка Unicode. • Все данные сохраняются в выбранной кодировке. Все сравнения столбцов с нормальными строками чувствительны к регистру. • Сортировка выполняется в соответствии с выбранной кодировкой (по умолчанию используется шведский набор). Во время запуска сервера MySQL это можно изменить. В качестве примера весьма совершенной сортировки рекомендуется обратить внимание на код сортировки для чешского языка. Сервер MySQL поддерживает множество различных кодировок, причем они могут быть указаны как во время компиляции, так и во время выполнения. • Клиенты и инструменты. • Сервер MySQL имеет встроенную поддержку SQL-операторов для проверки, оптимизации и восстановления таблиц. Эти операторы можно выполнять в режиме командной строки, используя клиентское приложение mysqlcheck. MySQL включает также myisamchk - очень быструю утилиту командной строки для реализации тех же операций над таблицами MylSAM. • Все программы MySQL можно запускать на выполнение с опцией —help или -? для получения быстрой подсказки.
1.2.3. Стабильность MySQL Этот раздел отвечает на вопросы "Насколько стабилен сервер MySQL?" и "Можно ли положиться на MySQL в этом проекте?". Мы попытаемся прояснить это, а также ответить на некоторые важные вопросы, которые касаются множества потенциальных пользователей. Информация, представленная в этом разделе, основана на данных, собранных из списков рассылки и писем пользователей, которые проявляют завидную активность при обсуждении проблем и способов их решения. Основной программный код был разработан в начале восьмидесятых годов прошлого века. Он обеспечил стабильную базу и поддерживал формат таблиц ISAM, используемый оригинальным механизмом хранения, который остается обратно совместимым и по сей день. В ТсХ, компании-предшественнице MySQL AB, код MySQL без проблем работал в проектах, начиная со средины 1996 года. Когда программное обеспечение MySQL
1.2. Что такое система управления базами данных MySQL
23
впервые было представлено широкой публике, пользователи быстро нашли фрагменты, которые не был протестированы. Каждая новая реализация с тех пор имела все меньше и меньше проблем переносимости, несмотря на то, что в каждой из них также добавлялось множество новых возможностей. Каждый выпуск сервера MySQL была работоспособным. Проблемы возникали только тогда, когда пользователи имели дело с кодом из так называемых "серых зон". Естественно, новые пользователи не знают, что это за зоны, поэтому в настоящем разделе мы попытаемся документировать те из них, которые известны в настоящий момент. Это описание в большей степени касается версий MySQL 3.23 и MySQL 4.O. Все известные и документированные ошибки в последней версии были исправлены, за исключением тех, что перечислены в разделе ошибок, имеющих отношение к собственно проекту (см. раздел 1.8.7). Проект MySQL построен по многоуровневому принципу с независимыми модулями. Некоторые из новейших модулей перечислены ниже с указанием того, насколько хорошо они были протестированы. • Репликация (гамма-версия). Большая группа серверов, использующих репликацию, показали хорошие результаты во время производственной эксплуатации. В MySQL 5.x продолжается работа над расширенными средствами репликации. • Таблицы innoDB (стабильная версия). Транзакционный механизм хранения был объявлен стабильным в дереве выпусков MySQL 3.23, начиная с 3.23.49. Таблицы InnoDB используются в больших, сильно загруженных производственных системах. • Таблицы BDB (гамма-версия). Код Berkley DB очень стабилен, однако совершенствование интерфейса транзакционного механизма хранения BDB в сервере MySQL продолжается, поэтому еще пройдет некоторое время, прежде чем модуль обслуживания таблиц BDB можно будет объявить настолько же тщательно протестированным, как и соответствующие модули для других типов таблиц. • Полнотекстовый поиск (гамма-версия). Полнотекстовый поиск работает, но пока широко не используется. В версию MySQL 4.0 были внесены важные усовершенствования. • Connector/ODBC 3.51 (стабильная версия). Connector /ODBC 3.51 использует комплект ODBC SDK 3.51 и широко применяется в производственных системах. Некоторые его выпуски зависимы от приложений и не зависят от ODBC-драйвера или лежащего в основе сервера баз данных. • Автоматическое восстановление таблиц My ISAM (гамма-версия). Состояние "гамма" касается только нового кода в механизме хранения My ISAM, который при открытии таблиц проверяет, были ли они правильно закрыты и, если нет, выполняет автоматическую проверку и восстанавливает их.
1.2.4. Размеры таблиц MySQL В MySQL 3.22 существовало ограничение в 4 Гбайт на размер таблиц. С применением механизма хранения MylSAM в MySQL 3.23 предельный размер таблиц вырос до 8
24
Глава 1. Общая информация
миллионов Тбайт (2 6 3 байт). На практике это означает, что максимальные размеры таблиц теперь определяются ограничениями, накладываемыми операционной системой на размеры файлов, а не внутренними ограничениями MySQL. Механизм хранения таблиц InnoDB поддерживает таблицы InnoDB внутри табличных пространств, которые могут состоять из нескольких файлов. Это позволяет таблице превысить максимальный размер отдельного файла. Табличное пространство может включать неразмеченные дисковые разделы (находящиеся вне файловой системы ОС), что позволяет иметь чрезвычайно большие таблицы. Максимальный размер табличного пространства составляет 64 терабайта. В табл. 1.1 приведены некоторые примеры ограничений на размеры файлов, налагаемые операционными системами. Таблица 1.1. Ограничения на размеры файлов со стороны операционных систем Операционная система
Ограничение размера файла
Linux-Intel, 32-разрядная
2 Гбайт, при использовании файловой системы LFS значительно больше 8 Тбайт (?) 2 Гбайт (4 Гбайт с обновлениями) 4 Гбайт (может быть изменено с помощью флагов) 4 Гбайт 512 Гбайт 8 Тбайт
Linux-Alpha Solaris 2.5.1 Solaris 2.6 Solaris 2.7 Intel Solaris 2.7 UltraSPARC NetWare с файловой системой NSS
В Linux 2.2 можно иметь таблицы My ISAM размером свыше 2 Гбайт, если воспользоваться обновлением LFS (Large Files Support - поддержка больших файлов) для файловой системы ext2. В Linux 2.4 существуют также обновления поддержки больших файлов для файловой системы ReiserFS. Большинство современных дистрибутивов Linux базируются на ядре 2.4 и уже оснащены всеми необходимыми обновлениями LFS. Однако максимально доступный размер файлов по-прежнему зависит от ряда факторов, один из которых - это тип файловой системы, используемой для хранения таблиц MySQL. Детальный обзор LFS для Linux можно найти на странице Андреаса Джаегера (Andreas Jaeger) "Large File Support in Linux" ("Поддержка больших файлов в Linux") no адресу http://www.suse.de/~aj/linux_lfs.html. По умолчанию MySQL создает таблицы My ISAM с внутренней структурой, разрешащей максимальный размер таблицы в 4 Гбайт. Максимальный размер таблицы можно проверить с помощью команды SHOW TABLE STATUS или myisamchk -dv имя_таблицы. Если необходимо работать с таблицами My ISAM размером свыше 4 Гбайт (и ваша операционная система поддерживает файлы упомянутого размера), на этот случай в операторе CREATE TABLE предусмотрены опции AVG_ROW__LENGTH и MAX_R0WS. Эти опции также можно изменить с помощью команды ALTER TABLE уже после создания таблицы, и таким образом увеличить ее максимально допустимый размер. Ниже представлены другие способы преодоления ограничений на размер таблиц My ISAM, налагаемых операционной системой. • Если большая таблица используется только для чтения, с помощью утилиты myisampack ее можно сжать. Как правило, эта утилита сжимает таблицу примерно
1.2. Что такое система управления базами данных MySQL
25
до 50% от начального размера. В результате можно иметь дело со значительно большими таблицами. Посредством утилиты myisampack можно также объединить несколько таблиц в одну. •
Другой способ преодоления ограничений на размер файла операционной системы для таблиц My ISAM заключается в использовании опции RAID.
•
MySQL включает в себя библиотеку MERGE, которая позволяет управлять набором таблиц My ISAM с идентичной структурой, как одной объединенной таблицей.
1.2.5. Решение "проблемы 2000 года91 В сервере MySQL известная "проблема 2000 года" (Y2K) полностью решена. •
В MySQL используются функции времени Unix, которые обрабатывают даты вплоть до 2037 года как значения типа TIME STAMP. Для значений типа DATE и DATETIME допустима работа с датами вплоть до 9999 года.
•
Все функции времени MySQL хранятся в одном исходном файле - sql/time.cc; они реализованы настолько тщательно, что являются безопасными в контексте "проблемы 2000 года".
•
В MySQL 3.22 и последующих версиях столбцы типа YEAR могут хранить год 0 и значения лет от 1901 до 2155 в одном байте и отображать их в виде двузначного или четырехзначного числа. Все двузначные годы рассматриваются как принадлежащие диапазону от 1970 до 2069; это означает, что если в столбце YEAR сохраняется значение 01, MySQL трактует его как 2001 год.
Приведенный далее код служит простой демонстрацией того, что сервер MySQL не имеет проблем со значениями типов DATE и DATETIME вплоть до 9999 года, а со значениями типа TIMESTAMP - после 2030 года. mysql> DROP TABLE IF EXISTS y2k; Query OK, 0 rows a f f e c t e d ( 0 . 0 1 s e c ) (Запрос успешно выполнен, затронуто 0 строк (0.01 с)) mysql> CREATE TABLE y2k (date DATE, -> date_time DATETIME, -> time_stamp TIMESTAMP) ; Query OK, 0 rows a f f e c t e d ( 0 . 0 1 s e c ) mysql> -> -> -> -> -> -> -> -> -> -> -> -> -> ->
INSERT INTO y2k VALUES ('1998-12-31','1998-12-31 ('1999-01-01','1999-01-01 ('1999-09-09','1999-09-09 ('2000-01-01','2000-01-01 ('2000-02-28','2000-02-28 ('2000-02-29','2000-02-29 ('2000-03-01','2000-03-01 ('2000-12-31','2000-12-31 ('2001-01-01','2001-01-01 ('2004-12-31','2004-12-31 ('2005-01-01','2005-01-01 ('2030-01-01','2030-01-01 ('2040-01-01','2040-01-01 ('9999-12-31','9999-12-31
23:59:59',19981231235959), 00:00:00',19990101000000), 23:59:59',19990909235959), 00:00:00',20000101000000), 00:00:00',20000228000000), 00:00:00',20000229000000), 00:00:00',20000301000000), 23:59:59',20001231235959), 00:00:00',20010101000000), 23:59:59',20041231235959), 00:00:00',20050101000000), 00:00:00',20300101000000), 00:00:00',20400101000000), 23:59:59',99991231235959);
26
Глава 1. Общая информация Query OK, 14 rows a f f e c t e d (0.01 sec) Records: 14 D u p l i c a t e s : 0 Warnings: 2 (Записей: 14 Дубликатов: 0 Предупреждений: 2) mysql> SELECT * FROM y2k; I date 1998- •12-31 1999-•01-01 1999-•09-09 2000- •01-01 2000- •02-28 2000- •02-29 2000- •03-01 2000- •12-31 2001-•01-01 2004-•12-31 2005-•01-01 2030-•01-01 2040-•01-01 9999-•12-31
time_stamp
d a t e time 1998- 12-31 1999- 01-01 1999- 09-09 2000- 01-01 2000- •02-28 2000- 02-29 2000- •03-01 2000- •12-31 2001- •01-01 2004- •12-31 2005- •01-01 2030- •01-01 2040- •01-01 9999-•12-31
14 rows in set (0.00 sec) (14 записей в наборе (0.00
23:59: 59 00:00: 00 23:59: 59 00:00: 00 00:00: 00 00:00: 00 00:00: 00 23:59: 59 00:00: 00 23:59: 59 00:00: 00 00:00: 00 00:00; 00 23:59: 59
19981231235959 19990101000000 19990909235959 20000101000000 20000228000000 20000229000000 20000301000000 20001231235959 20010101000000 20041231235959 20050101000000 20300101000000 00000000000000 00000000000000
с))
Последние два значения столбца TIME_STAMP равны нулю, потому что последние два значения года (2040 и 9999) выходят за пределы, допустимые для типа данных TIMESTAMP. Этот тип данных, используемый для хранения текущего времени, поддерживает значения (со знаком) в диапазоне от 19700101000000 до 20300101000000 на 32разрядных машинах. На 64-разрядных машинах тип TIMESTAMP допускает значения (без знака) до 2106 года. Несмотря на то что сервер MySQL сам по себе безопасен с точки зрения "проблемы 2000 года", неприятности могут быть вызваны приложениями, которые небезопасны в этом плане. Например, многие старые приложения хранят и манипулируют датами, используя двузначную запись года вместо четырехзначной. Эта проблема может еще более усугубиться приложениями, которые трактуют значения года 00 и 99 как индикатор "потерянных" или неопределенных значений. К сожалению, упомянутые проблемы зачастую очень трудно исправить, поскольку различные приложения разработаны разными программистами, каждый из которых может использовать собственный набор соглашений и функций обработки дат. Таким образом, сам сервер MySQL защищен от "проблемы 2000 года", а ответственность за корректный ввод ложится на приложения.
1.3. Компания MySQL AB MySQL AB - это компания основателей и основных разработчиков MySQL. Она была основана в Швеции Дэвидом Аксмарком (David Axmark), Алланом Ларссоном (Allan Larsson) и Майклом Монти Видениусом (Michael "Monty" Widenius). Все разработчики сервера MySQL работают на компанию. MySQL AB - виртуальная организация, объединяющая людей из нескольких десятков стран мира. Каждый день мы
1.3. Компания MySQL AB
27
интенсивно общаемся через Internet друг с другом, с нашими пользователями, сторонниками и партнерами. Мы посвятили себя разработке программного обеспечения баз данных MySQL и продвижению его для новых пользователей. Компания MySQL AB владеет авторскими правами на исходные тексты MySQL, логотип и торговую марку MySQL, а также на данное руководство (см. раздел 1.2). Ключевые принципы MySQL показывают наше отношение к продукту и инициативе программного обеспечения с открытым исходным кодом. Компания MySQL AB стремится, чтобы программное обеспечение сервера MySQL соответствовало следующим критериям: • Лучший и наиболее широко используемый в мире. • Доступный всем. • Простой в эксплуатации. • Постоянно совершенствующийся без влияния на производительность и защищенность. • Приносящий удовольствие от использования и улучшения. • Свободный от ошибок. Далее перечислены принципы, которыми руководствуется компания MySQL AB и ее сотрудники. • Мы поддерживаем философию открытого исходного кода, а также сообщество пользователей программного обеспечения с открытым исходным кодом (Open Source). • Мы стремимся быть хорошими гражданами. • Мы предпочитаем работать с партнерами, которые разделяют наши взгляды и убеждения. • Мы отвечаем на электронную почту и обеспечиваем поддержку пользователей. • Мы - виртуальная компания, взаимодействующая через Internet. • Мы - противники патентования программного обеспечения. Web-сайт MySQL (http://www.mysql.com) предоставляет актуальную информацию по MySQL и компании MySQL AB. Кстати, часть "АВ" в имени компании означает шведское "aktiebolag" - "акционерная компания". То есть MySQL AB в английском варианте может выглядеть как MySQL, Inc. Фактически, MySQL, Inc. и MySQL GmbH являются представительствами MySQL AB, расположенными, соответственно, в США и Германии.
1.3.1. Бизнес-модель и услуги, оказываемые MySQL AB Один из наиболее часто задаваемых нам вопросов звучит так: "Как вы можете жить с того, что предоставляете бесплатно?". А вот как: • Компания MySQL AB зарабатывает деньги на поддержке, услугах, коммерческих лицензиях и авторских отчислениях. • Мы используем эти доходы для финансирования разработки и расширения бизнеса, связанного с MySQL.
28
Глава 1. Общая информация
Компания была прибыльной, начиная со дня ее основания. В октябре 2001 года мы получили финансирование от ведущих скандинавских инвесторов. Эти инвестиции использовались для упрочнения нашей бизнес-модели и заложили фундамент устойчивого роста.
1.3.1.1. Поддержка Компанией MySQL AB владеют и управляют учредители и основные разработчики СУБД MySQL. Наши разработчики взяли на себя обязательство осуществлять поддержку клиентов и других пользователей с тем, чтобы постоянно быть в курсе их нужд и проблем. Вся поддержка выполняется только квалифицированным персоналом. На самые каверзные вопросы отвечает сам Майкл Монти Видениус - автор и идеолог сервера MySQL. Коммерческие клиенты получают высококачественную поддержку непосредственно от MySQL AB. Компания также поддерживает множество списков рассылки, в которых любой может задать вопрос на интересующую его тему. Более подробная информация о поддержке разного уровня содержится в разделе 1.4. 1.3.1.2. Обучение и сертификация Компания MySQL AB распространяет продукт MySQL и проводит обучающие курсы по нему во всем мире. Мы предлагаем как открытые курсы, так и курсы на территории заказчика, в соответствии с нуждами вашей организации. Обучающие курсы по MySQL проводят также наши партнеры - авторизованные обучающие центры. В наших обучающих материалах используются те же примеры баз данных, что и в документации и типовых приложениях, поставляемых вместе с продуктом. Эти материалы постоянно обновляются, чтобы соответствовать самой последней версии MySQL. Наши инструкторы постоянно взаимодействуют с группой разработчиков, что гарантирует качество обучения и постоянное совершенствование учебного материала. Посещение наших обучающих курсов позволит быстрее достичь целей, которые ставятся при разработке MySQL-приложений. Кроме того, существуют и другие преимущества: • Экономия времени. • Повышение производительности приложений. • Повышение степени защищенности приложений. • Более полное удовлетворение потребностей заказчиков и сотрудников. • Подготовка к сертификации по MySQL. Если вы заинтересовались нашими обучающими курсами как потенциальный клиент или партнер, посетите соответствующий раздел на нашем сайте по адресу http://www.mysql.com/training/ либо свяжитесь с нами по электронной почте:
[email protected]. Подробная информация, касающаяся программы сертификации, доступна по адресу http://www.mysql.com/certification/. 1.3.1.3. Консультации Компания MySQL AB и ее авторизованные партнеры предоставляют консалтинговые услуги пользователям сервера MySQL и тем, кто встраивает сервер MySQL в собственные приложения, по всему миру.
1.3. Компания MySQL AB
29
Наши консультанты окажут квалифицированную помощь в проектировании и настройке баз данных, разработке эффективных запросов, настройке платформ для достижения оптимальной производительности, решении вопросов миграции, репликации, построении устойчивых транзакционных приложений и многом другом. Консультанты тесно сотрудничают с группой разработки, что обеспечивает высокое качество их профессиональных услуг. Период проведения консультаций может составлять от двух дней интенсивных сеансов до временных промежутков, исчисляемых несколькими неделями и месяцами. Консультации охватывают круг вопросов, связанных не только непосредственно с MySQL, но также и с языками программирования и написания сценариев, такими как Perl, PHP и так далее. Все, кто заинтересован в услугах наших консультантов или же в партнерстве в этой области, могут посетить соответствующий раздел нашего сайта по адресу http://www.mysql.com/consulting/ либо связаться с нами по электронной почте:
[email protected]. 1.3.1.4. Коммерческие лицензии СУБД MySQL распространяется на условиях общедоступной лицензии GNU (General Public License - GPL). Это означает, что в соответствии с GPL программное обеспечение MySQL может использоваться бесплатно. Если вы не согласны с требованиями GPL (такими, например, как то, что ваши приложения также должны распространяться на условиях лицензии GPL), можете приобрести коммерческую лицензию на этот же продукт у компании MySQL AB (https://order.mysql.com/). Поскольку права на исходный код MySQL принадлежат MySQL AB, у нас есть возможность применять практику двойного лицензирования, в соответствие с которым один и тот же продукт распространяется как на условиях GPL, так и по коммерческой лицензии. Это совершенно не означает, что компания MySQL AB отступает от принципов открытого исходного кода. Подробная информация о том, в каких случаях необходима коммерческая лицензия, содержится в разделе 1.4.3. Компания MySQL AB также продает коммерческие лицензии на продукты Open Source GPL независимых разработчиков, которые привносят некоторую новую функциональность в сервер MySQL. Хорошим примером может служить транзакционный механизм хранения innoDB, который предназначен для поддержки ACID, блокировок на уровне строк, восстановления после аварий, управления версиями, внешних ключей и так далее. 1.3.1.5. Партнерство Компания MySQL AB поддерживает глобальную партнерскую программу, включающую обучающие курсы, консультирование и поддержку, публикации, продажу и распространение MySQL и связанных с ним продуктов. Партнеры MySQL AB указаны на нашем Web-сайте по адресу http://www.mysql.com/. Там же имеется информация о правах на использование специальных версий торговых марок MySQL для идентификации партнерских продуктов и продвижения их на рынке. Если вы заинтересованы в том, чтобы стать партнером MySQL AB, обращайтесь к нам по адресу partner@mysql. com. Слово "MySQL" и логотип с дельфином MySQL являются торговыми марками компании MySQL AB (см. раздел 1.4.4). Признание и узнаваемость этих торговых марок говорят о значительном вкладе основателей MySQL в технологии СУБД с открытым исходным кодом.
30
Глава 1. Общая информация
Web-сайт MySQL (http://www.mysql.com) весьма популярен среди разработчиков и пользователей. В декабре 2003 года на нем было зарегистрировано около 16 миллионов посещений. Люди, проявляющие интерес к этому сайту, в большинстве своем представляют группу лиц, принимающих решения и выдающих рекомендации по поводу приобретения программного и аппаратного обеспечения. Двенадцать процентов визитеров уполномочены принимать такие решения, и только девять процентов не имеют отношения к этому процессу. Более 65% делали одну или более покупок за последние полгода и 70% планируют это в течение ближайших месяцев.
1.3.2. Контактная информация Web-сайт MySQL (http://www.mysql.com) предоставляет самую последнюю информацию о MySQL и компании MySQL AB. Если вы нуждаетесь в какой-то информации, не раскрытой в нашем разделе новостей (http://www.mysql.com/news-and-events/), присылайте запросы по электронной почте на адрес press@mysql. com. Если вы заключили договор о поддержке с компанией MySQL AB, вы получите своевременные исчерпывающие ответы на все технические вопросы относительно программного обеспечения MySQL. За подробной информацией обращайтесь в раздел 1.4.1, на наш сайт в раздел http://www.mysql.com/support или присылайте электронные письма по адресу sales@mysql. com. Информацию, касающуюся обучающих курсов по MySQL, можно получить на сайте http://www.mysql.com/training/ или по электронной почте, отправив запрос по адресу
[email protected]. Обратитесь также в раздел 1.3.1.2. Информация о программе сертификации MySQL доступна по адресу http://www.mysql.com/certification/. Обратитесь также в раздел 1.3.1.2. Если вы заинтересованы в консультациях, посетите соответствующий раздел на нашем сайте по адресу http://www.mysql.com/consulting/ или присылайте запрос по электронной почте:
[email protected]. Обратитесь также в раздел 1.3.1.3. Коммерческие лицензии можно приобрести через Internet по адресу https: //order .mysql. com/. Там же вы найдете информацию о том, как отправить факс с заказом в компанию MySQL AB. Дополнительная информация о лицензировании доступна по адресу http://www.mysql.com/products/pricing.html. Если у вас возникли вопросы относительно лицензирования, заполните контактную форму на Web-сайте http://www.mysql.com либо пришлите электронное письмо по адресу
[email protected] (по вопросам лицензирования) или по адресу
[email protected] (по вопросам приобретения). Обратитесь также в раздел 1.4.3. Если вы представляете компанию, заинтересованную в партнерских отношениях с MySQL AB, присылайте электронные письма по адресу
[email protected]. Обратитесь также в раздел 1.3.1.5. Более подробную информацию о политике торговой марки MySQL можно получить по адресу http://www.mysql.com/company/trademark.html либо через электронную почту:
[email protected]. Обратитесь также в раздел 1.4.4. Если вы заинтересованы поработать на компанию MySQL AB, обращайтесь в соответствующий раздел на сайте (http://www.mysql.com/company/jobs/) или пишите по адресу
[email protected]. Не отправляйте свое резюме как вложение, а размещайте его в виде простого текста в конце электронного сообщения.
1.4. Поддержка и лицензирование MySQL
31
Для подключения к дискуссиям с другими пользователями просмотрите перечень наших списков рассылки. Обратитесь также в раздел 1.7.1. Сообщения об ошибках, равно как и вопросы и комментарии, должны отправляться в общий список рассылки MySQL (см. раздел 1.7.1). Если вы обнаружили существенные ошибки в системе безопасности сервера MySQL, незамедлительно уведомьте об этом по адресу
[email protected] (см. раздел 1.7.1.3). Если вы располагаете результатами тестирования, которые стоит опубликовать, присылайте их по адресу benchmark@mysql. com. Если у вас есть предложения по дополнениям и исправлениям настоящего руководства, направляйте их группе документации (docs@mysql. com). Вопросы и комментарии относительно Web-сайта MySQL (http://www.mysql.com) присылайте по адресу webmaster@mysql. com. Компания MySQL AB имеет собственную политику конфиденциальности, с которой можно ознакомиться по адресу http://www.mysql.com/company/privacy.html. Вопросы по этой теме можно задавать и по электронной почте: privacy@mysql. com. По всем остальным вопросам обращайтесь по адресу inf o@mysql. com.
1.4. Поддержка и лицензирование MySQL В этом разделе описаны соглашения по поддержке и лицензированию MySQL.
1.4.1. Поддержка, предоставляемая компанией MySQL AB Техническая поддержка компанией MySQL AB означает предоставление индивидуальных ответов по поводу решения ваших уникальных проблем непосредственно от специалистов, которые занимаются разработкой СУБД MySQL. Компания MySQL AB старается обеспечить широкий и всеобъемлющий подход к оказанию технической поддержки. Почти любая проблема, касающаяся MySQL, важна для нас, если она важна для вас. Обычно нашим заказчикам необходима помощь в том, чтобы заставить работать различные команды и утилиты, устранить узкие места в производительности, восстановить систему после аварии, разобраться с влиянием операционной системы или сетевой среды на MySQL, настроить процедуры резервирования и восстановления данных, применять API-интерфейсы и так далее. Наша поддержка касается только сервера MySQL и наших собственных утилит, но не продуктов независимых разработчиков, которые взаимодействуют с сервером MySQL, хотя по возможности мы и стараемся оказать помощь и в отношении их. Детальная информация о различных типах поддержки доступна по адресу http://www.mysql.com/support/. Там же можно затребовать и поддержку в онлайновом режиме. Чтобы связаться с персоналом, который занимается продажами, обращайтесь по адресу
[email protected]. Техническая поддержка во многом похожа на страхование жизни. Вы можете счастливо жить без нее многие годы. Однако когда ваш час наступит, она становится критически важной, но тогда уже слишком поздно ее приобретать. Если вы эксплуатируете сервер MySQL для обслуживания важных приложений и сталкиваетесь с внезапными сложностями, самостоятельный поиск ответов может оказаться слишком накладным в смысле времени. Вам понадобится немедленно связаться с самыми опытными специалистами по устранению проблем, которые работают на компанию MySQL AB.
32
Глава 1. Общая информация
1.4.2. Авторские права и лицензии на MySQL Компания MySQL AB владеет авторскими правами на исходный текст MySQL, логотипы, торговые марки и настоящее руководство (см. раздел 1.3). Важно знать несколько лицензионных соглашений относительно распространения MySQL: 1. Исходный код сервера MySQL, библиотеки mysqlclient, клиентских утилит, а также GNU-библиотеки readline, подпадает под действие лицензии GNU General Public License (http://fsf.org/licenses/). Файл COPYING в дистрибутиве MySQL содержит текст этой лицензии. 2. Использование библиотеки GNU getopt регламентируется малой общедоступной лицензией GNU Lesser General Public License (http://www.fsf.org/licenses/). 3. Некоторые части исходных текстов (в частности, библиотека regexp) защищены авторскими правами стиля Berkley. 4. Версии MySQL, предшествующие MySQL 3.22, регламентируются более строгими лицензиями (http://www.mysql.com/products/mypl.html). Детальную информацию можно найти в документации по этим версиям. 5. Распространение справочного руководства по MySQL не подпадает под действие лицензии GPL. Использование этого руководства ограничено следующими условиями: • Допускается преобразование в старые форматы файлов, но текущее содержимое документа не может быть изменено или отредактировано каким-либо образом. • Разрешена подготовка печатных копий для личного использования. • Для любых других целей, таких как продажа печатных копий либо использование руководства или его частей в других публикациях, необходимо письменное согласие компании MySQL AB. • За дополнительной информацией или при возникновении желания принять участие в переводе документации присылайте предложения по адресу
[email protected]. Сведения о действии лицензий MySQL на практике представлены в разделах 1.4.3 и 1.4.4 настоящего руководства.
1.4.3. Лицензии на MySQL Программное обеспечение MySQL распространяется на условиях лицензии GNU General Public License (GPL), которая является, вероятно, наилучшей лицензией для систем с открытым исходным кодом. Формальные условия лицензии GPL доступны по адресу http://www.fsf.org/licenses/. Имеет смысл также просмотреть информацию по адресам http://www.fsf.org/licenses/gplfaq.html и http://www.gnu.org/philosophy/enforcinggpl.html. Наша лицензия GPL предполагает ряд необязательных исключений, которые позволяют многим приложениям, распространяемым на условиях Free/Libre and Open Source ("FLOSS"), включать в себя клиентские библиотеки MySQL, несмотря на тот факт, что не все лицензии FLOSS совместимы с GPL. Более подробную информацию по этому поводу можно найти на странице: http://www.mysql.com/products/licensing/foss-exception.html
1.4. Поддержка и лицензирование MySQL
33
Поскольку программное обеспечение MySQL распространяется на условиях GPL, оно зачастую может использоваться бесплатно, однако для некоторых целей требуется коммерческая лицензия MySQL AB. Приобрести упомянутую лицензию можно по адресу https://order.mysql.com/. Просмотрите также информацию по адресу http://www.mysql.com/products/licensing.html. Версии MySQL, предшествующие MySQL 3.22, подпадают под действие более строгих лицензий (http://www.mysql.com/products/mypl.html). Дополнительная информация доступна в документации по MySQL соответствующих версий. Обратите внимание на то, что использование программного обеспечения MySQL по коммерческой лицензии, GPL либо по старой лицензии MySQL не предоставляет автоматически права на использование торговой марки компании MySQL AB (см. раздел 1.4.4).
1.4.3.1. Использование программного обеспечения MySQL по коммерческой лицензии Лицензию GPL можно назвать "заразной" в том смысле, что когда программа связывается с GPL-программой, все исходные тексты всех частей результирующего продукта также подпадают под действие лицензии GPL. Если это требование не выполняется, тем самым нарушаются условия лицензии, а право на использование GPL-программы утрачивается. В этом случае вы рискуете тем, что от вас могут потребовать материальной компенсации за нарушение условий лицензии. Коммерческая лицензия необходима в перечисленных ниже случаях. • Если вы компонуете свою программу с любым кодом из состава программного обеспечения MySQL, который подпадает под действие лицензии GPL, и не хотите, чтобы результирующий продукт лицензировался на условиях GPL. Возможно, это необходимо из-за того, что вы разрабатываете коммерческий продукт либо по другим причинам желаете сохранить добавляемый вами код закрытым. Приобретая коммерческую лицензию, вы используете то же самое программное обеспечение MySQL, но только не в соответствие с лицензией GPL. • Если вы распространяете приложение, использование которого не регламентируется лицензией GPL, но которое работает только с программным обеспечением MySQL, и поставляете это приложение вместе с программным обеспечением MySQL. Этот вариант решения рассматривается как компоновка, даже если части результирующего продукта взаимодействуют только через сеть. • Если вы распространяете копии программного обеспечения MySQL без поставки исходного кода, как того требует лицензия GPL. • Если вы хотите содействовать дальнейшей разработке СУБД MySQL, даже когда коммерческая лицензия формально не нужна. Оплата услуг по поддержке непосредственно компании MySQL AB - еще один хороший способ содействия разработке программного обеспечения MySQL, причем с непосредственной выгодой для вас (см. раздел 1.4.1). Наша лицензия GPL предполагает ряд необязательных исключений, которые позволяют многим приложениям, распространяемым на условиях Free/Libre and Open Source ("FLOSS"), включать в себя клиентские библиотеки MySQL, несмотря на тот факт, что не все лицензии FLOSS совместимы с GPL. Более подробную информацию по этому поводу можно найти на странице: http://www.mysql.com/products/licensing/foss-exception.html
34
Глава 1. Общая информация
Если вы решили отдать предпочтение коммерческой лицензии, вам понадобится отдельная лицензия на каждую инсталляцию MySQL. Ее действие распространяется на системы с любым количеством процессоров и с любым числом клиентов, которые подключаются к серверу, причем любым способом. Для приобретения коммерческих лицензий посетите наш Web-сайт по адресу http://www.mysql.com/products/licensing.html. Чтобы заключить договор поддержки, обращайтесь по адресу http://www.mysql.com/support/. Если имеются какие-то специфические требования, свяжитесь с нашим персоналом, который занимается продажами, по электронной почте: sales@mysql. com.
1.4.3.1. Бесплатное использование программного обеспечения MySQL по лицензии GPL Бесплатное использование программного обеспечения MySQL по лицензии GPL допускается при условии выполнения требований GPL. Дополнительная информация о GPL, в том числе ответы на часто задаваемые вопросы, доступна в разделе FAQ фонда бесплатного программного обеспечения (Free Software Foundation) по адресу http://www.fsf.org/licenses/gpl-faq.html. Наша лицензия GPL предусматривает ряд необязательных исключений, которые позволяют многим приложениям, распространяемым на условиях Free/Libre and Open Source ("FLOSS"), включать в себя клиентские библиотеки MySQL, несмотря на тот факт, что не все лицензии FLOSS совместимы с GPL. Более подробно об этом см. http://www.mysql.com/products/licensing/foss-exception.html. Ниже перечислены общие примеры использования GPL. •
Когда вы распространяете собственное приложение вместе с исходными текстами и исходным кодом MySQL на условиях GPL. • Когда вы распространяете исходный код MySQL в связке с другими программами, которые не компонуются и функционально не зависят от MySQL, даже если эти программы распространяются на коммерческой основе. В лицензии GPL это называется "чистой агрегацией" ("mere aggregation"). •
Когда вы не распространяете никаких частей системы MySQL, вы можете ее использовать бесплатно. • Если вы являетесь поставщиком Internet-услуг, предоставляя своим клиентам Web-хостинг и доступ к серверу MySQL. Мы рекомендуем сотрудничать с поставщиками, у которых заключен договор поддержки MySQL, поскольку это дает уверенность в том, что поставщик располагает всеми ресурсами для решения любых возникающих проблем с MySQL. Даже если поставщик Internet-услуг не имеет коммерческой лицензии на сервер MySQL, его клиенты, как минимум, должны иметь доступ по чтению к исходным кодам инсталляции MySQL, дабы они могли убедиться, что выполнены все изменения и исправления. •
Когда вы используете программное обеспечение баз данных MySQL в комплекте с Web-сервером, вы не нуждаетесь в коммерческой лицензии (до тех пор, пока не это является распространяемым вами продуктом). Это верно даже в том случае, если функционирующий Web-сервер является коммерческим, и он использует сервер MySQL, поскольку распространение частей системы MySQL не осуществляется. Однако в этом случае рекомендуется заключить договор поддержки MySQL, так как программное обеспечение MySQL оказывает влияние на успешность вашего предприятия.
1.4. Поддержка и лицензирование MySQL
35
Если вы используете программное обеспечение баз данных MySQL и не нуждаетесь в коммерческой лицензии, мы все равно рекомендуем вам заключить договор поддержки с компанией MySQL AB. Это способ содействия дальнейшему развитию MySQL и одновременно получения непосредственной выгоды для вас (см. раздел 1.4.1). Если программное обеспечение баз данных MySQL применяется в коммерческих целях и от этого появляется некоторая прибыль, компания MySQL AB предлагает поддержать дальнейшее развитие MySQL за счет заключения договора на поддержку определенного уровня. Мы полагаем, что если СУБД MySQL помогает вашему бизнесу, то логично попросить вас о содействии компании MySQL AB. (В противном случае получается, что задавая вопросы, касающиеся поддержки, вы не только бесплатно пользуетесь тем, во что вложена немалая работа, но и просите предоставить бесплатную поддержку.)
1.4.4. Логотипы и торговые марки MySQL AB Многие пользователи СУБД MySQL желают размещать логотип с дельфином MySQL AB на своих Web-сайтах, в книгах или на коробках с программными продуктами. Мы приветствуем и поддерживаем это стремление, только при условии упоминания, что слово "MySQL" и логотип дельфина являются торговыми марками MySQL AB и могут использовать только так, как того требует наша политика относительно торговых марок (см. http://www.mysql.com/company/trademark.html).
1.4.4.1. Оригинальный логотип MySQL Логотип MySQL с изображением дельфина был разработан финским рекламным агентством Priority в 2001 году. Дельфин был признан подходящим символом для СУБД MySQL - столь же умное, быстрое, подвижное и свободно ориентирующееся в безбрежном океане данных существо. Оригинальный логотип MySQL может использоваться только как символ компании MySQL AB и только теми, кто имеет соответствующее письменное разрешение.
1.4.4.2. Логотипы MySQL, которые можно использовать без письменного разрешения Мы разработали набор специальных условно используемых логотипов, которые можно загрузить с нашего Web-сайта (http://www.mysql.com/press/logos.html) и использовать на Web-сайтах независимых разработчиков без заключения письменных соглашений с компанией MySQL AB. Применение этих логотипов не является полностью неограниченным, а регламентируется политикой относительно торговых марок, с которой можно ознакомиться на нашем сайте. Если вы планируете использовать их, внимательно изучите все положения упомянутой политики. Ниже перечислены основные требования. • Используйте требуемый логотип именно в том виде, в котором он представлен на сайте http://www.mysql.com. Разрешено масштабировать его до нужных размеров, однако нельзя изменять его цвета, дизайн, а также вносить любые другие изменения в этот графический образ. • Явно укажите, что именно вы, а не компания MySQL AB являетесь создателем и владельцем сайта, на котором представлено изображение торговой марки MySQL.
36
Глава 1. Общая информация • Не допускается использовать торговую марку способом, приносящим ущерб компании MySQL AB или ее торговым маркам. Мы оставляем за собой право отбирать права на использование торговых марок MySQL AB. • При размещении изображения торговой марки на Web-сайте, предусмотрите ссылку, ведущую непосредственно на сайт h t t p : //www.mysql. com. • Если вы используете СУБД MySQL на условиях лицензии GPL в приложении, это приложение должно быть с открытым исходным кодом и должно иметь возможность подключаться к серверу MySQL.
В случае если вас интересуют какие-то специальные условия, которые соответствуют вашим нуждам, свяжитесь с нами по электронной почте: trademark@mysql. com. 1.4.4.3. Когда необходимо иметь письменное разрешение на использование логотипов MySQL Письменное разрешение MySQL AB на использование логотипов MySQL необходимо получать в следующих случаях: • При использовании логотипов MySQL AB в любом другом месте, отличном от Web-сайта. • При использовании логотипа MySQL AB, не входящего в набор специальных условно используемых логотипов (о которых упоминалось выше) на Web-сайте или где-то еще. На основе юридических и коммерческих соображений мы следим за использованием торговой марки MySQL в продуктах, книгах и других местах. Обычно мы требуем плату за изображение логотипа MySQL в коммерческих продуктах, поскольку считаем справедливым, чтобы некоторая часть дохода возвращалась нам для обеспечения дальнейшего развития СУБД MySQL.
1.4.4.4. Партнерские логотипы MySQL AB Логотип партнера MySQL AB может использоваться только компанией, заключившей письменное соглашение о партнерстве с MySQL AB. Партнерские отношения предусматривают сертификацию кого-либо в качестве инструктора или консультанта по MySQL. Подробную информацию можно найти в разделе 1.3.1.5. 1.4.4.5. Использование слова "MySQL" в печатном тексте и презентациях Компания MySQL AB приветствует ссылки на СУБД MySQL, однако при условии упоминания о том, что слово "MySQL" является торговой маркой MySQL AB. По этой причине к первому или наиболее заметному упоминанию слова "MySQL" в тексте должен быть добавлен значок торговой марки (®), а там, где это уместно, должно быть указано, что MySQL представляет собой торговую марку компании MySQL AB. За более подробной информацией о нашей политике относительно торговых марок обращайтесь по адресу http://www.mysql.com/corapany/trademark.html. 1.4.4.6. Использование слова "MySQL" в названиях компаний и продуктов Использование слова "MySQL" в названиях компаний, продуктов или доменных именах Internet без письменного разрешения компании MySQL AB не допускается.
1.5. План разработки MySQL
37
1.5. План разработки MySQL В этом разделе в общих чертах представлен план разработки MySQL, включая основные средства, реализованные или планируемые для MySQL версий 4.0, 4.1, 5.0 и 5.1. Последующие разделы дают информацию о каждой серии выпусков. Серия производственных выпусков на момент написания этой книги - это MySQL 4.0, которая была представлена как устойчивая версия 4.0.12, ориентированная на производственное применение (выпущена в марте 2003 года). Это означает, что дальнейшие разработки в рамках линейки 4.0 будут сводится только к исправлению ошибок. В старой серии MySQL 3.23 будут исправляться только критические ошибки. Активная разработка MySQL сейчас сосредоточена на сериях MySQL 4.1 и MySQL 5.0. Это означает, что новые возможности будут добавляться только к MySQL 4.1 и MySQL 5.0. На момент написания книги MySQL 4.1 доступен в виде бета-версии, а MySQL 5.0 - в виде альфа-версии. Ниже подытожены планы реализации наиболее востребованных возможностей. Возможность
Серия MySQL
Объединения Подзапросы
4.0 4.1
R-деревья
4.1 (для таблиц My ISAM)
Хранимые процедуры Представления Курсоры Внешние ключи
5.0 5.0 5.0 5.1 (уже реализованы в версии 3.23 для InnoDB)
Триггеры Полные внешние соединения Ограничения
5.1 5.1 5.1
1.5.1. Кратко о MySQL 4.0 Долгожданная версия MySQL 4.0 теперь доступна как производственный продукт. Ее можно загрузить из сайта h t t p : //dev.mysql. com, а также с наших зеркальных сайтов. Версия MySQL 4.0 была протестирована большим числом пользователей и эксплуатируется на многих крупных Web-сайтах. Основные возможности, вошедшие в состав сервера MySQL 4.0, были разработаны в соответствии с текущими требованиями нашего бизнеса и потребностями сообщества пользователей. Новые функции совершенствуют сервер баз данных MySQL как решение для ответственных, сильно загруженных систем баз данных. Другие новые средства ориентируются на пользователей встроенных баз данных.
1.5.1.1. Возможности, доступные в MySQL 4.0 • Повышение скорости работы. • В версии MySQL 4.0 реализован кэш запросов, который обеспечивает существенный рост производительности для приложений, генерирующих повторяющиеся запросы.
38
Глава 1. Общая информация • В версии MySQL 4.0 еще более увеличилась скорость выполнения многих операций, таких как пакетные операторы INSERT, поиск по упакованным индексам, полнотекстовый поиск (с использованием индексов FULLTEXT), а также COUNT(DISTINCT). • Новый встроенный сервер MySQL. • С помощью новой библиотеки встроенного сервера можно легко создавать автономные и встроенные приложения. Встроенный сервер - это альтернатива MySQL в клиент-серверной среде. • Механизм хранения InnoDB в качестве стандарта. • Механизм хранения InnoDB теперь позиционируется как стандартная функциональная возможность сервера MySQL. Это означает полную поддержку ACID-транзакций, внешних ключей с каскадными операторами INSERT и DELETE, а также блокировок на уровне строки. • Новая функциональность. • Усовершенствованные поисковые свойства FULLTEXT в сервере MySQL 4.0 позволяют индексировать большие объемы текстовой информации, как для логики бинарного поиска, так и для поиска с применением естественного языка. Имеется возможность настройки минимальной длины слова и определения собственных списков недопустимых слов на любом естественном языке, что позволяет разрабатывать новый набор приложений, использующих MySQL-сервер. • Соответствие стандартам, переносимость и миграция • Сервер MySQL теперь поддерживает оператор UNION - долгожданную возможность стандартного языка SQL. • MySQL теперь функционирует и на платформе Novell Netware, начиная с версии NetWare 6.O. • Средства, упрощающие миграцию из других баз данных в среду сервера MySQL, включая TRUNCATE TABLE (как у Oracle). • Интернационализация • Немецкие, австрийские и швейцарские пользователи обратят внимание, что MySQL 4.0 поддерживает новый набор символов - l a t i n l d e , гарантирующий, что порядок сортировки немецких символов расположит слова с умляутами в порядке, принятом в немецких телефонных справочниках. • Удобство использования В процессе реализации новых средств для новых пользователей мы не забываем и о запросах со стороны сообщества постоянных пользователей наших продуктов. • Большинство параметров mysqld (опций запуска) теперь могут устанавливаться без необходимости остановки сервера. Это удобное средство для администраторов баз данных. • Добавлены многотабличные операторы DELETE и UPDATE. • В среде Windows управление символическими ссылками на уровне базы данных теперь по умолчанию включено. В среде UNIX механизм хранения My ISAM теперь поддерживает символические ссылки на уровне таблиц (а не только на уровне базы данных, как ранее).
1.5. План разработки MySQL •
39
Н о в ы е ф у н к ц и и SQL_CALC_FOUND_ROWS И FOUND_ROWS() ПОЗВОЛЯЮТ наЙТИ КОЛИ-
чество строк, которое должен вернуть оператор SELECT с конструкцией LIMIT, как если бы этой конструкции не было. В разделе новостей онлайнового руководства можно найти более детальный список возможностей (см. http://dev.mysql.com/doc/mysql/en/News.html).
1.5.1.2. Встроенный сервер MySQL Библиотека встроенного сервера libmysqld существенно расширяет сферу применения MySQL. Используя эту библиотеку, разработчики могут встраивать сервер MySQL в различные приложения и электронные устройства, при этом конечные пользователи могут даже не подозревать о лежащей в основе СУБД. Встроенный сервер MySQL идеален для использования в Internet-приложениях, общедоступных киосках, программноаппаратных устройствах, высокопроизводительных Internet-серверах, автономных базах данных, распространяемых на компакт-дисках, и так далее. Многие пользователи libmysqld получат несомненный выигрыш от двойного лицензирования MySQL. Для тех, кто не желает быть связанным ограничениями лицензии GPL, это программное обеспечение доступно по коммерческой лицензии. Библиотека встроенного MySQL использует тот же интерфейс, что и обычная клиентская библиотека, поэтому она проста и удобна в эксплуатации.
1.5.2. Кратко о MySQL 4.1 Сервер MySQL версии 4.0 заложил основу для появления новых возможностей, таких как подзапросы и поддержка Unicode, которые реализованы в версии 4.1, а также для работы над хранимыми процедурами, которая завершается в версии 5.0. Упомянутые возможности возглавляют список пожеланий большинства наших клиентов. С появлением этих усовершенствований критикам MySQL понадобится проявить гораздо большее воображение, чтобы указать на недостатки в СУБД MySQL. Уже широко зарекомендовавший себя как стабильный, быстрый и простой в эксплуатации, сервер MySQL теперь готов к тому, чтобы удовлетворить требования самых взыскательных потребителей. 1.5.2.1. Средства, доступные в MySQL 4.1 Все возможности MySQL 4.1, описанные в данном разделе, уже реализованы. Несколько других средств MySQL 4.1 только планируются к реализации (см. раздел 1.6.1). Набор возможностей, добавленных в версии 4.1, в основном утвержден. Большинство новых средств, пребывающих в состоянии разработки, уже доступны или будут доступны в MySQL 5.0 (см. раздел 1.6.2). MySQL 4.1 в настоящее время находится в стадии бета-тестирования, и его бинарные файлы доступны для загрузки по адресу: http://dev.mysql.com/downloads/mysql/4.1.html Все бинарные реализации прошли интенсивное тестирование без каких-либо ошибок на тех платформах, для которых они собраны. Для тех, кто желает использовать наиболее актуальные исходные тексты, находящиеся в процессе разработки, открыт доступ к нашему репозиторию BitKeeper для MySQL 4.1.
40
Глава 1. Общая информация
MySQL 4.1 проходит стадию альфа-тестирования (в течение которой новые средства могут быть добавлены или изменены), стадию бета-тестирования (когда новая разработка замораживается и выполняется только исправление ошибок) и стадию гамматестирования (означающую, что производственный выпуск должен появиться в течение нескольких недель). В конце этого процесса MySQL 4.1 становится новым производственным выпуском. • Поддержка подзапросов и порожденных таблиц. • "Подзапрос" - это оператор SELECT, вложенный внутри другого оператора. "Порожденная таблица" (неименованное представление) - это подзапрос в конструкции FROM другого оператора. • Увеличение скорости. • Ускоренный бинарный клиент-серверный протокол с поддержкой предварительно подготовленных операторов и связывание параметров. • Индексация BTREE теперь поддерживается для таблиц HEAP, значительно снижая время реакции при нечетком поиске. • Новая функциональность. •
Оператор CREATE TABLE имя_таблицы2 LIKE имя_таблицы1 позволяет с помощью единственного оператора создавать новую таблицу со структурой, точно такой же, как у существующей таблицы. • Механизм хранения My ISAM теперь поддерживает пространственные типы OpenGIS для хранения геометрических данных. • Репликация может выполняться через SSL-соединения.
• Соответствие стандартам, переносимость и миграция • Новый клиент-серверный протокол добавляет возможность передачи множественных предупреждений и сообщений клиенту вместо единственного результата, как было раньше. Это упрощает процесс поиска причин проблем, которые могут возникнуть в таких операциях, как пакетная загрузка данных. •
SHOW WARNINGS показывает предупреждения, касающиеся последней выполненной команды.
• Интернационализация • Для поддержки приложений, требующих использования национальных языков, программное обеспечение MySQL обеспечивает работу с кодировкой Unicode через символьные наборы utf8nucs2. •
Символьные наборы теперь можно задавать для столбца, таблицы и базы данных. Это обеспечивает высокую степень гибкости при проектировании приложений, в частности, многоязычных Web-сайтов.
• Удобство использования • В ответ на многочисленные просьбы мы добавили команду HELP серверной стороны, которая может предоставлять вспомогательную информацию об операторах SQL. Выгода от нахождения этой информации на стороне сервера заключается в том, что клиенту всегда доступна справка по той версии сервера, к которому он подключился. Поскольку эта информация доступна через оператор SQL, любой клиент можно написать так, чтобы к ней был доступ. Напри-
1.6. MySQL и будущее (списки TODO)
41
мер, команда help в клиенте командной строки mysql была соответствующим образом модифицирована. • В новом клиент-серверном протоколе множественные операторы могут быть отправлены одним вызовом. • Новый клиент-серверный протокол также поддерживает возврат множества результирующих наборов. Это может случиться, например, как результат множественного запроса. • Реализован новый синтаксис INSERT.. .ON DUPLICATE KEY UPDATE..., который позволяет выполнять оператор UPDATE для существующей записи, если оператор INSERT может привести к дублированию поля, служащего первичным ключом или ключом уникального индекса. • Введена новая агрегатная функция GROUP_CONCAT (), которая добавляет исключительно удобную возможность соединения значений столбцов из группированных строк в единственную результирующую строку. В разделе новостей онлайнового руководства можно найти более детальный список возможностей (см. http://dev.mysql.com/doc/mysql/en/News.html).
1.5.3. MySQL 5.0: Очередной разрабатываемый выпуск В настоящее время процесс разработки MySQL сфокусирован на выпуске 5.0, который будет оснащен хранимыми процедурами и другими новыми возможностями (см. раздел 1.6.2). Для тех, кто желает взглянуть на передний край разработки MySQL, открыт публичный доступ к репозиторию BitKeeper для MySQL 5.O. Начиная с декабря 2003 года, доступны также бинарные сборки версии 5.0.
1.6. MySQL и будущее (списки TODO) В этом разделе описаны возможности, которые запланированы к реализации в сервере MySQL. Позиции перечисляются по порядку номеров выпусков. Внутри списка позиции следуют в том порядке, в котором, предположительно, они будут реализованы. На заметку! Если вы пользователь уровня предприятия, испытывающий срочную потребность в каком-то конкретном средстве, свяжитесь с нашими специалистами по электронной почте (
[email protected]), чтобы обсудить возможности спонсирования. Целевое финансирование компаниями-спонсорами позволяет нам выделять дополнительные ресурсы для специфических целей. Одним из примеров реализации такого сотрудничества, имевшего место в прошлом, является репликация.
1.6.1. Новые средства, запланированные для версии 4.1 Перечисленные ниже средства в MySQL 4.1 пока не реализованы, но планируются к реализации до того момента, как MySQL 4.1 достигнет фазы бета-тестирования. Список того, что уже реализовано в MySQL 4.1, представлен в разделе 1.5.2.1. • Стабильная поддержка OpenSSL. (Поддержка SSL в MySQL 4.0 была в зачаточном состоянии и не на 100% протестирована.) • Дополнительно протестирован механизм предварительно подготовленных операторов.
42
Глава 1. Общая информация • Дополнительно протестирована поддержка множественных символьных наборов в одной таблице.
1.6.2. Новые средства, запланированные для версии 5.0 Перечисленные ниже средства планируются к включению в состав MySQL 5.O. Некоторые из них, например, хранимые процедуры, уже готовы и включены в выпуск MySQL 5.0 alpha, который уже доступен сейчас. Другие, такие как курсоры, готовы лишь частично. Ожидается, что эти и некоторые другие средства будут поддерживаться в будущих выпусках. Следует отметить, что поскольку мы имеем дело с множеством разработчиков, которые заняты в разных проектах, то и количество дополнительных средств должно быть значительным. Есть небольшая вероятность того, что часть из них войдут в выпуск MySQL 4.1. Список того, что уже реализовано в MySQL 4.1, представлен в разделе 1.5.2.1. Для тех, кто желает взглянуть на передний край разработки MySQL, открыт публичный доступ к репозиторию BitKeeper для MySQL 5.0. Начиная с декабря 2003 года, доступны также бинарные сборки версии 5.0. • Хранимые процедуры. • Хранимые процедуры в настоящее время реализованы на базе стандарта SQL:2003. • Новая функциональность. • Элементарная поддержка курсоров. • Возможность явного указания для таблиц My ISAM, что индекс должен быть построен как индекс RTREE (в MySQL 4.1 индексы RTREE используются внутренне для геометрических данных GIS, но не могут быть созданы по запросу). • Динамическая длина строк для таблиц MEMORY. • Соответствие стандартам, переносимость и миграция • Добавлена полноценная поддержка типа VARCHAR (ширина столбцов свыше 255 символов без усечения завершающих пробелов). В настоящее время существует поддержка этого в механизме хранения My ISAM, но пока это недоступно на уровне пользователя. • Увеличение скорости. • Оператору SHOW COLUMNS FROM имя_таблицы (используется клиентом mysql для того, чтобы позволить расширение имен столбцов) не требуется открывать таблицу, а только файл определений. Это требует меньших затрат памяти и получается значительно быстрее. • Оператору DELETE на таблицах MylSAM теперь разрешено использовать кэш записей. Чтобы обеспечить это, понадобилось обновлять кэш записей потоков при обновлении файлов .MYD. • Улучшенная поддержка таблиц MEMORY: Динамическая длина строк. Ускоренное управление строками (меньше копирования). • Удобство использования • Решение проблемы, возникающую при попытке выполнить RENAME TABLE для таблиц, включенных в активные таблицы MERGE (возможно повреждение таблиц).
1.6. MySQL и будущее (списки TODO)
43
В разделе новостей онлайнового руководства можно найти более детальный список возможностей (см. http: //dev.mysql. com/doc/mysql/en/News. html).
1.6.3. Новые средства, запланированные для версии5.1 • Новая функциональность. •
Поддержка внешних ключей (FOREIGN KEY) для всех типов таблиц, а не только для InnoDB.
• Ограничения уровня столбца. • Онлайновое резервное копирования с минимальным снижением производительности. Это позволит легко добавлять новые базы без необходимости останавливать репликацию. • Увеличение скорости. • Новый формат файлов определения таблиц (. f rm) и табличный кэш для определения таблиц. Это позволит выполнять более быстрые запросы к структурам таблиц и увеличить эффективность поддержки внешних ключей. • Оптимизация типа BIT для хранения одного бита (в настоящее время тип BIT хранится в байте и рассматривается как синоним TINYINT). • Удобство использования. • Добавление опций клиент-серверного протокола для получения информации о процессе выполнения команд, занимающих длительное время. • Реализация оператора RENAME DATABASE. Чтобы сделать это безопасным для всех механизмов хранения, он должен работать следующим образом: 1. Создать новую базу данных. 2. Переименовать каждую таблицу в другую базу, как это делается командой RENAME.
3. Удалить старую базу. • Изменение нового внутреннего интерфейса файлов. Это обобщит управление всеми файлами и станет возможным добавление расширений, подобных RAID.
1.6.4. Новые средства, запланированные на ближайшее будущее • Новая функциональность. • Представления, реализованные в пошаговой манере, вплоть до полной функциональности. • Подобные Oracle конструкции CONNECT BY PRIOR оператора SELECT для извлечения древовидных иерархических структур. • Добавление всех пропущенных стандартных типов SQL и ODBC 3.0. • Добавление SUM (DISTINCT). •
INSERT SQL_CONCURRENT и mysqld --concurrent-insert ДЛЯ параллельной вставки в конец таблицы, если таблица заблокирована по чтению.
44
Глава 1. Общая информация •
Разрешение обновления переменных оператором UPDATE, например, UPDATE foo
SET @a:=a+b, a=@a, b=@a+c.
•
Когда пользовательские переменные изменены, разрешение использования их в конструкции GROUP BY, как показано в следующем примере: SELECT i d , @a:=COUNT(*), SUM(sura_col)/@a FROM имя_таблицы GROUP BY id.
•
Добавление опции IMAGE к LOAD DATA INFILE, чтобы не обновлять столбцы TIMESTAMP И AUTO_INCREMENT.
•
Добавление синтаксиса LOAD DATA INFILE.. .UPDATE, работающего следующим образом:
•
•
Для таблиц с первичными ключами, если вводимая запись имеет значение первичного ключа, совпадающее с существующей записью, то последняя обновляется значениями столбцов вводимой записи. Столбцы, пропущенные во вводимой записи, остаются без изменений.
•
Для таблиц с первичными ключами, если вводимая запись не содержит первичного ключа, или же какая-то часть ключа пропущена, запись обрабатывается как LOAD DATA INFILE...REPLACE INTO.
Изменение оператора LOAD DATA INFILE, чтобы стал возможным такой синтаксис: LOAD DATA INFILE 'имя_файлa.txt f INTO TABLE имя_таблицы TEXT_FIELDS (текстовый_столбец1, текстовый_столбец2, текстовый_столбецЗ) SET столбец_таблицы!=CONCAT[текстовый_столбец1, текстовый_столбец2), текстовый_столбецЗ=23 IGNORE текстовый_столбецЗ Это может использоваться для того, чтобы пропустить лишние столбцы в текстовом файле или обновить столбцы на основе выражения, составленного из прочитанных данных.
•
Новые функции для работы со столбцами типа SET:
• •
ADD_TO_SET{значение, набор) REMOVE_FROM_SET{значение, набор)
Ш В настоящее время, если выполнение mysql прерывается посреди запроса, нужно открыть другое соединение и уничтожить этот выполняющийся запрос. Необходимо сделать так, чтобы такую ситуацию обнаруживал и разрешал сам сервер. •
Добавление интерфейса механизма хранения для табличной информации таким образом, чтобы его можно было использовать как системную таблицу. Это может несколько снизить скорость, если запрашивается информация обо всех таблицах, однако существенно увеличится гибкость. Необходимо реализовать SHOW INFO FROM имя__таблицы для базовой информации о таблице.
•
Реализация SELECT a FROM имя_таблицы1 LEFT JOIN имя_таблицы2 USING (a) ; здесь предполагается, что а поступает из таблицы имя__таблицы1.
•
Добавление опций DELETE и REPLACE к оператору UPDATE (чтобы при возникновении ошибки, связанной с дублированием ключа во время обновления, строки удалялись).
•
Изменение формата DATETIME, чтобы можно было хранить доли секунды.
1.6. MySQL и будущее (списки TODO)
45
• Обеспечение возможности использования новой библиотеки GNU regexp вместо применяемой сейчас (новая библиотека значительно быстрее). • Соответствие стандартам, переносимость и миграция. • Не добавлять автоматически значения по умолчанию к столбцам (DEFAULT). Генерировать ошибку для любого оператора INSERT, в котором пропущены значения столбцов, не имеющих значений DEFAULT. • Добавить групповые функции ANY (), EVERY () и SOME (). В стандартном языке SQL это работает только на столбцах с булевскими значениями, но мы можем расширить это для работы на всех столбцах или выражениях, трактуя нулевые значения как FALSE и ненулевые как TRUE. •
Исправить тип возврата функции МАХ (столбец), чтобы она возвращала тот же тип, что и ее аргумент: raysql> CREATE TABLE t l (a DATE); mysql> INSERT INTO t l VALUES (NOW()); mysql> CREATE TABLE t 2 SELECT MAX (a) FROM t l ; mysql> SHOW COLUMNS FROM t 2 ;
• Увеличение скорости. • He разрешать создание большего, чем определено, количества потоков при запуске восстановления My ISAM в одно и то же время. • Изменить оператор INSERT INTO.. .SELECT так, чтобы можно было при желании использовать параллельные вставки. • Добавить опцию периодического сбрасывания ключевых страниц для таблиц с задержанными ключами, если они долго не используются. • Разрешить объединения на частях ключей (для целей оптимизации). • Добавить анализатор файлов протоколов, чтобы можно было извлекать информацию о том, какие таблицы используются наиболее часто, насколько часто запрашиваются многотабличные объединения и так далее. Это поможет пользователям идентифицировать то, что подлежит оптимизации для более эффективного выполнения запросов. • Удобство использования. • Возвращать оригинальный тип столбца при выполнении SELECT MIN(column) . . . GROUP BY.
•
Обеспечить возможность указывать long_query_time с точностью до миллисекунд. • Скомпоновать код myisampack с сервером, чтобы он мог выполнять операции PACK И COMPRESS.
• Добавить временный буфер кэша ключей при выполнении INSERT, DELETE и UPDATE с тем, чтобы стало возможным восстановление в случае переполнения индексного файла. • Если выполняется оператор ALTER TABLE для таблицы, указанной через символическую ссылку и расположенной на другом диске, создавать временные таблицы на том же диске.
46
Глава 1. Общая информация •
Реализовать типы DATE и DATETIME так, чтобы они корректно обрабатывали информацию о временных зонах, тем самым упростив работу с датами в разных зонах.
•
Исправить configure, чтобы все библиотеки (подобно My ISAM) могли быть скомпилированы без потоков.
•
Разрешить применение пользовательских переменных в качестве аргументов LIMIT, например: LIMIT @а, @b.
•
Добавить автоматический вывод mysql в Web-браузер.
•
Добавить LOCK DATABASES (с различными опциями).
•
Дополнительная информация для SHOW STATUS. Чтение и обновление записей. Запросы к отдельным таблицам и запросы к объединениям. Среднее количество таблиц в запросе. Количество запросов с конструкциями ORDER BY и GROUP BY.
•
Операция копирования mysqladmin copy база_данных Это потребует добавления операции COPY в mysqld.
•
Вывод списка процессов должен показывать количество запросов/потоков.
•
SHOW HOSTS для вывода информации о кэше имен хостов.
•
Изменить имена таблиц с пустой строки на NULL для вычисляемых столбцов.
•
Не использовать Item_copy_string для числовых значений, чтобы избежать преобразования число-строка-число в случае наподобие:
новая_база_данных;.
SELECT COUNT(*)*(id+0) FROM имя_таблицы GROUP BY i d
•
•
Изменить оператор ALTER TABLE таким образом, чтобы он не прерывал клиентов, ВЫПОЛНЯЮЩИХ INSERT DELAYED.
•
Внести исправление, чтобы при ссылке на столбцы в конструкции UPDATE они содержали старые значения, которые были до начала обновления.
Новые операционные системы. •
Перенести MySQL на платформу LynxOS.
1.6.5. Новые средства, запланированные на отдаленное будущее •
Реализация функции get_changed_tables {тайм-аут, таблица!, таблица2, . . . ) .
•
Изменить чтение таблиц так, чтобы использовалась mmap (), где это возможно. В настоящее время mmap () используют только сжатые таблицы.
•
Сделать код автоматических временных меток более изящным. Добавить автоматические временные метки в протокол обновлений с SET TI ME STAMP=значение;
•
Использовать семафоры чтения-записи в некоторых местах для повышения скорости.
•
Автоматически закрывать некоторые таблицы, если таблица, временная таблица или временный файл получают ошибку 23 (слишком много открытых файлов).
•
Улучшенное распространение констант. Когда в выражении встречается имя_столбца=п, причем п - константа, заменять все вхождения имя__столбца в выражении на п. В настоящее время это выполняется только в некоторых случаях.
1.6. MySQL и будущее (списки TODO) •
47
Заменить все константные выражения вычисляемыми, если возможно.
• Оптимизировать сравнения ключ = выражение. В настоящее время оптимизируются только ключ = столбец и ключ - константа. • Объединить некоторые функции копирования для получения более изящного кода. • Заменить sql_yacc.yy на встроенный анализатор, чтобы уменьшить его размер и получить более удобную диагностику ошибок. • Изменить анализатор таким образом, чтобы использовать только одно правило для разного числа аргументов функции. • Использовать полные вычисленные имена в порядковой части (для СУБД Access 97). • Реализовать MINUS, INTERSECT и FULL OUTER JOIN (сейчас поддерживаются UNION и LEFT | RIGHT OUTER JOIN). • Разрешить использование SQLJDPTION MAX_SELECT_TIME=значение для указания временного ограничения в запросе. • Сделать возможной запись протоколов обновлений в базу данных. • Усовершенствовать LIMIT, чтобы обеспечить извлечение данных из конца результирующего набора. • Организовать выдачу предупреждений ния/чтения/записи.
клиентскими функциями подключе-
• Обратите внимание на изменения в mysqld_safe: согласно стандарту FSSTND (которому старается следовать Debian), PID-файлы должны размещаться в /уаг/гип/.р1с1, а файлы протоколов - в /var/log. Было бы неплохо, если бы можно было помещать "DATADIR" в первое объявление "pidfile" и "log", чтобы местоположение этих файлов можно было менять с помощью единственного оператора. • Разрешить клиенту запрашивать протоколирование. • Разрешить оператору LOAD DATA INFILE читать файлы, сжатые с помощью дzip. • Исправить сортировку и группирование столбцов BLOB (частично решено сейчас). • Использовать семафоры при подсчете потоков. Сначала потребуется реализовать библиотеку семафоров для потоков MIT-pthreads. • Добавить полную поддержку JOIN со скобками. • В качестве альтернативы модели "один поток на соединение" управлять пулом потоков для управления запросами. • Разрешить GETLOCK () получать более одной блокировки. При этом обрабатывать возможные взаимные блокировки, к которым это усовершенствование может привести.
1.6.6. Новые средства, которые не планируются к реализации Наша цель состоит в достижении как можно более полной совместимости со стандартом ANSI/ISO SQL. Нет таких средств, которые мы НЕ планируем реализовывать.
48
Глава 1. Общая информация
1.7. Источники информации по MySQL 1.7.1. Списки рассылки MySQL В этом разделе представлены списки рассылки MySQL и руководство по их использованию. После того, как вы подпишетесь на список рассылки, вам начнет поступать вся корреспонденция из этого списка по электронной почте. Кроме того, вы сможете отправлять свои вопросы, а также ответы на вопросы других подписчиков.
1.7.1.1. Перечень списков рассылки MySQL Чтобы подписаться или отказаться от подписки на любой список рассылки, упоминаемый в настоящем разделе, зайдите на http://lists.mysql.com. Не посылайте запросов на подписку или отказ от подписки в любой их списков, поскольку такие письма автоматически рассылаются тысячам подписчиков. Ваш локальный сайт может иметь множество подписчиков на списки рассылки MySQL. Если это так, имеет смысл завести локальные списки рассылки, чтобы сообщения, отправленные на lists.mysql.com, рассылались адресатам, занесенным в них. В этом случае обратитесь к системному администратору, чтобы он внес вас в локальный список рассылки MySQL. Если вы желаете, чтобы сообщения из рассылки попадали в отдельный почтовый ящик в вашей почтовой программе, настройте фильтр на базе заголовков сообщений. Для идентификации этих сообщений можно использовать заголовки List-ID: или Delivered-TO:. Ниже представлены списки рассылки MySQL. • anounce Это рассылка объявлений о новых версиях MySQL и сопутствующих программ. Это рассылка с малой активностью; на нее должны быть подписаны все пользователи MySQL. • mysql Это основная рассылка для общих дискуссий по вопросам MySQL. Стоит заметить, что некоторые темы более подробно обсуждаются в специальных рассылках. Если вы отправите письмо не в ту рассылку, то, вероятно, не получите ответа. • mysql-digest Это рассылка mysql в форме дайджеста. Если вы подпишетесь на эту рассылку, то будете ежедневно получать группу сообщений одним письмом. • bugs Эта рассылка может быть интересна, если вы хотите быть в курсе сообщений о последней версии MySQL или желаете включиться в процесс поиска и исправления ошибок. • bugs-digest Это рассылка bugs в форме дайджеста. • internals Эта рассылка предназначена в основном для тех, кто имеет дело с кодом MySQL. Это также форум для дискуссий о разработке MySQL и рассылки исправлений. • internals-digest Это рассылка internals в форме дайджеста.
1.7. Источники информации по MySQL •
• •
• •
• •
• •
• •
• •
• •
49
mysqldoc Эта рассылка для тех, кто работает над созданием документации MySQL: людей из MySQL AB, переводчиков и других членов сообщества. mysqldoc-digest Это рассылка mysqldoc в форме дайджеста. benchmarks Это рассылка для тех, кого интересуют вопросы производительности. Дискуссии сосредоточены вокруг производительности СУБД (не только MySQL), а также касаются более широких категорий, включая производительность ядра, файловых систем, дисковых систем и так далее. benchmarks-digest Это рассылка benchmarks в форме дайджеста. packagers Это рассылка для дискуссий об объединении в пакеты и распространении MySQL. В данном форуме участвуют те, кто занимается поддержкой распространения для обмена идеями о том, как формировать пакеты MySQL и как добиваться того, чтобы MySQL выглядел и работал насколько возможно единообразно на всех платформах и операционных системах. packagers-digest Это рассылка packagers в форме дайджеста Java Это рассылка для дискуссий, связанных с сервером MySQL и языком Java. В основном здесь обсуждаются JDBC-драйвера, включая MySQL Connector/J. java-digest Это рассылка j ava в форме дайджеста. Win32 Этот список предназначен для обсуждения всего, что касается использования MySQL под управлением операционных систем семейства Microsoft, таких как Windows 9x, Me, NT, 2000 и ХР. win32-digest Это рассылка Win32 в форме дайджеста. myodbc Эта рассылка относится ко всему, что связано с подключением к MySQL через ODBC. myodbc-digest Это рассылка myodbc в форме дайджеста. gui-tools Здесь обсуждаются инструменты MySQL с графическим интерфейсом пользователя, включая MySQL Administrator и графический клиент MySQL Control Center. gui-tools-digest Это рассылка gui-tools в форме дайджеста. plusplus Этот список рассылки касается вопросов программирования на C++ для MySQL.
50
Глава 1. Общая информация • plusplus-digest Это рассылка plusplus в форме дайджеста. • msql-mysql-modules Эта рассылка для всех вопросов, связанных с поддержкой MySQL языка Perl, в частности, модулем DBD:mysql. • msql-mysql-modules-digest Это рассылка msql-mysql-modules в форме дайджеста.
Если вы не можете получить ответ на заданный вопрос в списках рассылки MySQL, выходом может быть заключение договора поддержки с компанией MySQL AB. Это позволит вам напрямую контактировать с разработчиками MySQL (см. раздел 1.4.1). Ниже представлен перечень списков рассылки MySQL на других языках (кроме английского). Эти рассылки компанией MySQL AB не управляются. •
[email protected] Список рассылки на французском языке. •
[email protected] Список рассылки на корейском языке. Для подписки отправьте по адресу списка сообщение subscribe mysql ваш@почтовый, адрес. •
[email protected] Список рассылки на немецком языке. Для подписки отправьте по адресу списка сообщение subscribe mysql-de ваш@почтовый. адрес. Дополнительную информацию об этом списке можно найти по адресу h t t p : //www. 4t2.com/mysql. •
[email protected] Список рассылки на португальском языке. Для подписки отправьте по адресу списка сообщение subscribe mysql-br ваш@почтовый.адрес. •
[email protected] Список рассылки на испанском языке. Для подписки отправьте по адресу списка сообщение subscribe mysql ваш@почтовый.адрес.
1.7.1.2. Как задавать вопросы и сообщать об ошибках Прежде чем посылать вопрос или сообщение об ошибке, выполните следующие действия: • Начните с поиска в онлайновом руководстве по MySQL на http: / /dev. mysql. com/doc/. Мы стараемся поддерживать это руководство в актуальном состоянии, часто обновляя его по мере решения обнаруженных проблем. Полезной может оказаться и хронология изменений (http: //dev. mysql. com/doc/mysql/en/News .html), поскольку весьма вероятно, что в новых версиях та или иная проблема уже решена. • Просмотрите базу данных ошибок, которая доступна по адресу http://bugs.mysql.com/. Возможно, ошибка, о которой вы собираетесь сообщить, уже обнаружена и исправлена. • Поищите в архиве списков рассылки на http://lists.mysql.com/. • Воспользуйтесь поисковой службой http://www.mysql.com/search/ для поиска по всему Web-сайту MySQL AB, включая онлайновое руководство.
1.7. Источники информации по MySQL
51
Если вы не можете найти ответ в справочном руководстве и архивах, обратитесь к местному эксперту по MySQL. Если и он не даст ответа на вопрос, то перед тем как связаться с нами, изучите приведенную ниже инструкцию по отправке писем в списки рассылки MySQL.
1.7.1.3. Как сообщать об ошибках и проблемах Обычное место, куда нужно направлять сообщения об ошибках, это http://bugs.mysql.com/ - адрес нашей базы данных ошибок. Эта база общедоступна, любой может ее просматривать и выполнять в ней поиск. Если вы зарегистрируетесь в системе, то также сможете вводить в нее новые сообщения. Написание качественного отчета об ошибке требует немалого терпения, однако, составив его правильно, вы сэкономите как свое время, так и наше. Хороший отчет об ошибке должен содержать полное описание пути, приводящего к ее проявлению (случай тестирования); весьма вероятно, что мы исправим обнаруженную вами ошибку уже в очередном выпуске. Сведения, представленные в этом разделе, посвящены тому, как правильно составлять такие отчеты, дабы не пришлось впустую тратить время на то, что либо мало поможет нам, либо вообще не поможет. Для генерации отчета об ошибке (или сообщения о любой проблеме) мы рекомендуем использовать сценарий mysqlbug. Упомянутый сценарий находится в каталоге scripts (исходного дистрибутива) и в каталоге bin (бинарного дистрибутива MySQL). Если запустить mysqlbug не удается (например, если вы работаете в среде Windows), все равно важно включить всю необходимую информацию, указанную в настоящем разделе (и самое главное - описание операционной системы и версии MySQL). Сценарий mysqlbug поможет сгенерировать отчет об ошибке, собрав большую часть информации автоматически, но кое-что важное придется ввести вручную. Внимательно прочтите настоящий раздел и убедитесь, что вся перечисленная здесь информация должным образом отражена в отчете. Прежде всего, необходимо убедиться в наличии проблемы в последней производственной версии MySQL или версии, находящейся на стадии разработки. Любой может воспроизвести найденную ошибку, просто запустив mysql t e s t < файл^сценария или же запустив Perl-сценарий, включенный в отчет об ошибке. Все ошибки, отправленные в базу ошибок на http: //bugs .mysql. com/, будут исправлены или документированы в следующем выпуске MySQL. Если исправление ошибки требует только небольших изменений в коде, возможно, будет разослано только исправление. Если вы обнаружили существенную ошибку в системе безопасности MySQL, сообщение об этом необходимо прислать по адресу security@mysql. com. Если вы подготовили воспроизводимый отчет об ошибке, присылайте его в базу ошибок по адресу http://bugs.mysql.com/. Помните, что даже в этом случае желательно запустить сценарий mysqlbug для сбора информации о вашей системе. Любая ошибка, которую мы сможем воспроизвести, имеет хорошие шансы на то, чтобы быть исправленной в очередном выпуске MySQL. Сообщения о проблемах иного рода можно отправлять в списки рассылки MySQL. Помните, что мы можем ответить на сообщения, содержащие слишком много информации, но не можем ответить на те, что содержат ее слишком мало. Люди часто пропускают некоторые факты, поскольку думают, что имеют представление о причинах проблем, и предполагают, что детали значения не имеют. Хороший принцип, которым следует руководствоваться, может быть сформулирован следующим образом: если вы
52
Глава 1. Общая информация
сомневаетесь, стоит ли сообщать о чем-то, то сообщайте. Получится гораздо быстрее и проще, если вы напишите кучу дополнительных строк в сообщении, чем если нам придется запрашивать у вас дополнительную информацию, пропущенную в первичном сообщении, и ждать ответа. Наиболее часто встречающиеся ошибки в отчетах таковы: (а) не указан номер версии используемого дистрибутива MySQL и (Ь) не полностью описана платформа, на которой установлен сервер MySQL (включая тип платформы и номер версии). Это чрезвычайно важная информация, и в 99 случаях из 100 сообщение об ошибке без нее бесполезно. Очень часто мы получаем вопросы вроде такого: "Почему у меня то-то и то-то не работает?" Потом выясняется, что возможность просто в данной версии MySQL не реализована, или же эта ошибка известна и исправлена в более новой версии MySQL. Иногда ошибка оказывается зависимой от платформы и в этом случае мы не в состоянии исправить что-либо, не зная операционной системы и номера ее версии. Если вы скомпилировали MySQL из исходных текстов, не забудьте также указать информацию о компиляторе, если это связано с проблемой. Часто люди сталкиваются с ошибками компиляторов, а думают, что ошибки связаны с кодом MySQL. Большинство компиляторов находятся в постоянном процессе разработки и становятся лучше от версии к версии. Чтобы определить, не вызвана ли проблема компилятором, нам надо знать, какой компилятор вы используете. Помните, что любые проблемы с компиляцией должны рассматриваться как ошибки и сообщаться соответствующим образом. Лучше всего, если в отчет об ошибке включено исчерпывающее описание проблемы. Имеется в виду описание всего того, что вы делали и столкнулись с ошибкой, а также подробное описание самой проблемы. То есть наилучшими отчетами об ошибках являются такие, которые содержат полный пример, показывающий, как воспроизвести описанную ошибку или проблему. Если какая-то программа выдает сообщение об ошибке, очень важно включить это сообщение в отчет. Если мы попытаемся найти что-нибудь в архивах, лучше, чтобы сообщение об ошибке, сгенерированное программой, было точно в том виде, как вы его увидели (важен даже регистр символов). Никогда не пытайтесь воспроизвести по памяти это сообщение, а вместо этого просто скопируйте его и вставьте в отправляемый отчет. Если у вас возникла проблема с Connector/ODBC (MyODBC), пожалуйста, попытайтесь сгенерировать трассировочный файл MyODBC и прислать его вместе с отчетом. Помните, что многие люди, которые будут читать ваш отчет об ошибке, используют отображение с шириной 80 символов. Поэтому при генерации сообщения об ошибке с помощью mysqlbug применяйте опцию --vertical (или символ завершения операторов \G) для вывода, который может по ширине превысить общепринятые размеры (например, с оператором EXPLAIN SELECT, как показано выше в примере). В отправляемый отчет должна быть включена следующая информация: • Номер версии используемого дистрибутива MySQL, например, MySQL 4.0.12. Эту информацию можно получить, запустив mysqladmin version. Программа mysqladmin расположена в подкаталоге bin каталога с инсталляцией MySQL. • Производитель и модель компьютера, на котором возникла проблема. • Наименование и версия операционной системы. Если вы работаете под управлением Windows, получить эту информацию можно, выполнив двойной щелчок на пиктограмме My Computer (Мой компьютер) и выбрав в меню Help (Справка) пункт About (О программе). Для большинства Unix-подобных операционных систем эту информацию можно получить через команду uname -a.
1.7. Источники информации по MySQL
53
• Иногда важен объем памяти (физической и виртуальной). При наличии какихлибо сомнений, включите в отчет и эту информацию. • Если вы используете дистрибутив MySQL с исходными текстами, понадобится наименование и номер версии компилятора. Если дистрибутив только бинарный, потребуется его наименование. •
Если проблема возникает при компиляции, включите в отчет сообщение об ошибке компилятора и несколько строк из контекста, окружающего то место в исходном коде, где возникла ошибка.
•
Если mysqld аварийно завершился, сообщите в отчете текст запроса, приводящего к таким последствиям. Обычно это можно сделать, запустив mysqld с включенной опцией протоколирования запросов и заглянув в файл протокола после отказа mysqld.
•
Если к ошибке имеет отношение таблица базы данных, включите вывод mysqldump —nodata имя_базы_данных имя_таблицы. Это очень просто сделать и это отличный способ получить информацию о любой таблице в базе данных. В результате у нас появится возможность смоделировать сложившуюся у вас ситуацию.
• При описании проблем, имеющих отношение к скорости или к оператору SELECT, всегда необходимо включать вывод команды EXPLAIN SELECT . . . , а также, по меньшей мере, число строк, которое возвращает оператор SELECT. Также следует включить вывод команды SHOW CREATE TABLE имя^таблицы для каждой таблицы, участвующей в запросе. Чем больше информации о ситуации вы сообщите, тем более вероятно, что кто-то сможет вам помочь. Ниже представлен пример очень хорошего отчета об ошибке. Он может быть отправлен через сценарий mysqlbug. Этот пример использует утилиту командной строки mysql. Отметьте применение ограничителя операторов \G для тех из них, чей вывод превышает ширину отображения в 80 символов: mysql> SHOW VARIABLES; mysql> SHOW COLUMNS FROM . . . \ G mysql> EXPLAIN SELECT . . . \ G
mysql> FLUSH STATUS; mysql> SELECT . . . ;
Сокращенная версия вывода SELECT, включая время выполнения запроса> mysql> SHOW STATUS;
• Если ошибка или проблема возникает во время работы mysqld, постарайтесь предоставить сценарий, который воспроизводит аномалию. Этот сценарий должен включать все необходимые исходные файлы. Чем ближе к реальности сценарий сможет воспроизвести ситуацию, тем лучше. Если вы можете составить воспроизводимый случай тестирования, присылайте его по адресу http://bugs.mysql.com/ для высокоприоритетной обработки. Если вы не можете предоставить сценарий, по крайней мере, включите в отчет вывод команды mysqladmin variables extended-status processlist, чтобы дать представление о том, как ваша система настроена.
54
Глава 1. Общая информация • Если вы не можете предоставить случай тестирования в нескольких строках или же случай тестирования слишком большой, чтобы присылать его в группу рассылки (более 10 строк), вам потребуется сбросить дамп таблиц с помощью mysqldump и создать файл README с описанием проблемы. Создайте архив своих файлов с помощью утилит tar, gzip или zip и отправьте его через FTP-протокол по адресу ftp://ftp.mysql.cora/pub/mysql/upload/. Затем введите описание проблемы в базу данных ошибок по адресу h t t p : //bugs .mysql. com/. • Если вам кажется, что MySQL выдает странный результат запроса, включите не только собственно результат, а также ваше предположение, каким он должен быть, и опишите основания своих предположений относительно результата. • При описании примера возникновения проблемы лучше использовать имена переменных, таблиц и так далее такими, какими они были в вашей ситуации, а не придумывать новые имена. Проблема может иметь отношение к имени переменной или таблицы. Это случается редко, но лучше подстраховаться и не вносить искажений в описание проблемы. К тому же вам будет проще, да и нам удобней, если вы приведете пример реальной ситуации. Если у вас есть данные, которые вы не хотите показывать всем, их можно отправить через FTP-протокол по адресу ftp://ftp.mysql.com/pub/mysql/upload. Если же информация настолько секретна, что вы не хотите ее показывать даже нам, тогда приводите пример с измененными именами, но это только в крайнем случае. • Включите в отчет все опции всех программ, имеющих отношение к ошибочной ситуации, если это возможно. Так, например, укажите опции, которые вы использовали для запуска сервера mysqld, как и опции любых клиентских программ MySQL. Опции программ mysqld, mysql, сценария configure часто являются ключами к ответу и поэтому очень важны. Никогда не стоит пренебрегать этим. Если вы применяете модули, подобные Perl или РНР, пожалуйста, укажите номера их версий. • Если ваш вопрос имеет отношение к системе привилегий, включите в отчет вывод утилит mysqlaccess, mysqladmin reload и все сообщения об ошибках, которые выдаются при попытке подключения. Когда вы проверяете существующие привилегии, то должны сначала запустить mysqlaccess. После этого запустите mysqladmin reload version и попытайтесь подключиться с помощью той программы, которая приводила к проблемам. • Если вы располагаете модулем исправления ошибки, упомяните в отчете и о нем. Однако не ожидайте, что ваш модуль исправления - это все, что нам нужно или что мы его используем, особенно если переданный отчет об ошибке не включает в себя случай тестирования, который воспроизводит ошибку, фиксируемую модулем исправления. Мы можем обнаружить проблемы, связанные с вашим модулем исправления, или вообще не понять его. Если так случится, мы не станем его использовать. Если мы не можем проверить, для чего предназначен данный модуль исправления, мы также не станем его использовать. В этом нам помогут случаи тестирования. Покажите, что модуль исправления справляется со всеми ситуациями, которые могут возникнуть. Если мы обнаружим какие-то ограничения (даже очень редкие), при которых модуль исправления не работает, он может не пригодиться.
1.7. Источники информации по MySQL
55
• Предположения о природе обнаруженной ошибки, причинах ее возникновения или зависимостях, как правило, неверны. Даже группа разработчиков MySQL не может делать каких-то предположений, пока не воспользуется средствами отладки для нахождения истинной причины ошибки. • Отмечайте в отчете об ошибке, что вы просматривали руководство и архивы списков рассылки, чтобы остальные знали, что вы пытались решить проблему самостоятельно. • Если вы получили сообщение об ошибке "parse error" ("ошибка синтаксического анализа"), тщательно проверьте код на предмет корректности синтаксиса. Если вы не находите в нем ничего некорректного, вполне возможно, что ваша версия сервера MySQL не поддерживает используемый вами синтаксис. Если вы используете текущую версию сервера и руководство на h t t p : //dev.mysql.com/doc/ не описывает применяемый вами синтаксис, значит, сервер MySQL подобный запрос не поддерживает. В этом случае единственный выход для вас - реализовать требуемый синтаксис самостоятельно или отправить письмо по адресу licensing@mysql. com с просьбой реализовать его. Если в руководстве описан синтаксис, который вы применяете, но у вас более старая версия сервера MySQL, стоит просмотреть хронологию изменений MySQL, чтобы найти, когда этот синтаксис был реализован. В этом случае у вас есть возможность обновить сервер MySQL до более новой версии. • Если возникшая проблема связана с повреждением данных, либо ошибки возникают при попытке обращения к отдельной таблице, потребуется сначала проверить, а затем восстановить таблицы с помощью команд CHECK TABLE и REPAIR TABLE, либо с помощью утилиты myisamchk. Если вы работаете в среде Windows, убедитесь, что команда SHOW VARIABLES LIKE 'lower_case_table_names' возвращает значение 1 или 2. • Если повреждения таблиц случаются часто, попытайтесь выяснить, когда и почему это происходит. В этом случае протокол ошибок в словаре данных MySQL может содержать некоторую информацию о том, что происходит. (Это файл с суффиксом .err в имени). Включите в отчет об ошибке любую важную информацию из этого файла. Обычно mysqld никогда не портит таблиц, если только ничто не уничтожает его в процессе обновления данных. Если вы сможете выяснить причину краха mysqld, нам будет значительно легче помочь вам решить проблему. • Если возможно, загрузите и установите самую последнюю версию сервера MySQL и проверьте, осталась ли проблема нерешенной. Все версии программного обеспечения MySQL тестируются очень тщательно и должны функционировать без проблем. Мы стараемся обеспечить обратную совместимость, насколько это возможно, поэтому переход на новую версию должен пройти без особых проблем. Если вы - клиент, заключивший с нами договор поддержки, перешлите отчет об ошибке по адресу
[email protected] для высокоприоритетной обработки, а также отправьте этот отчет в соответствующий список рассылки, чтобы проверить, не сталкивался ли кто-нибудь с подобной проблемой и, возможно, каким-то образом решил ее. Если ответы направляются вам персонально, а не в группу рассылки, хорошим тоном считается резюмировать ответы и отправлять их в список рассылки, чтобы другие подписчики тоже получили пользу от ответов, которые помогли вам решить возникшую проблему.
56
Глава 1. Общая информация
1.7.1.4. Рекомендации по составлению ответов на вопросы из списков рассылки Если вы считаете, что ваш ответ может заинтересовать многих, возможно, имеет смысл отправить его в список рассылки вместо того, чтобы отвечать персонально тому, кто задал вопрос. Постарайтесь максимально обобщить ответ, дабы он принес пользу и другим, а не только тому, кто спрашивает. Отправляя ответ в список рассылки, убедитесь, что он не дублирует предыдущие ответы на тот же вопрос. Постарайтесь подытожить существенную часть вопроса в ответе, но не считайте необходимым полностью цитировать оригинальный вопрос. Не отправляйте почтовых сообщений с помощью браузера с включенным режимом HTML. Многие пользователи читают письма, не прибегая к услугам браузера.
1.7.2. Поддержка сообщества пользователей MySQL в IRC В дополнение к спискам рассылки MySQL опытных пользователей можно найти и в IRC (Internet Relay Chat - беседы в Internet). Ниже перечислены лучшие сети/каналы, известные на данный момент. • freenode (http://www.freenode.net/) •
#mysql. В основном обсуждаются вопросы, связанные с MySQL, но можно задавать вопросы и по другим СУБД и SQL. • #mysqlphp. Вопросы, связанные с использованием популярной комбинации продуктов - MySQL + PHP. •
#mysqlperl. Вопросы, связанные с использованием другой популярной комбинации продуктов - MySQL + Perl.
• EFnet (http://www.efnet.org/) •
#mysql. Вопросы по MySQL.
Если вам необходимо программное обеспечение IRC-клиента для подключения к сетям IRC, рекомендуем воспользоваться X-Chat (http://www.xchat.org/). X-Chat (регламентируется лицензией GPL) доступен как для Unix-, так и для Windows-платформ.
1.8. Соответствие стандартам MySQL В этом разделе представлена информация, касающаяся того, как MySQL соотносится со стандартами ANSI/ISO SQL. В сервере MySQL реализовано множество расширений стандарта SQL, и здесь вы найдете сведения о том, что они собой представляют и как их использовать. Кроме того, представлена информация о функциональности, которая отсутствует в сервере MySQL, а также о том, как преодолевать некоторые расхождения со стандартом. Стандарт SQL появился в 1986 году и на сегодняшний день существует несколько его версий. В настоящем руководстве "SQL-92" ссылается на стандарт, изданный в 1992 году, "SQL: 1999" - на стандарт, изданный в 1999 году, и "SQL:2003" - на текущую версию стандарта. Под "стандартом SQL" понимается последняя версия стандарта. Наша цель состоит в том, чтобы не сужать рамки применения сервера MySQL без веских на то причин. Даже если у нас не хватает ресурсов для разработки, ориентированной на любое возможное применение, мы всегда стараемся оказать помощь людям, которые пытаются применять сервер MySQL в новых областях.
1.8. Соответствие стандартам MySQL
57
Одна из главных задач при разработке этого продукта состоит в том, чтобы продолжать работу в направлении максимального соответствия стандарту SQL, однако, не жертвуя при этом производительностью и надежностью. Мы не боимся добавлять собственные расширения к SQL или поддерживать не-SQL средства, если это значительно увеличивает удобство применения сервера MySQL для большого сегмента нашей пользовательской базы. Примером такой стратегии может служить интерфейс HANDLER в сервере MySQL 4.O. Мы будем продолжать поддержку транзакционной и не-транзакционной баз данных, чтобы удовлетворить запросы как тех пользователей, которым нужна работа с ответственными данными по схеме "24 часа в сутки, 7 дней в неделю", так и тех, кому необходима напряженная работа с Web и регистрацией. Изначально сервер MySQL разрабатывался для баз данных средних размеров (10-100 миллионов записей, или около 100 Мбайт на таблицу) в малых компьютерных системах. Сегодня сервер MySQL обслуживает терабайтные базы данных, но его код по-прежнему может быть скомпилирован в ограниченную версию, применимую в портативных и встроенных системах. Компактный дизайн сервера MySQL делает возможным продолжение разработки в обоих направлениях, без каких-либо конфликтов в дереве исходного кода. В настоящее время мы не планируем поддержку систем реального времени, но, несмотря на это, средства репликации MySQL уже предлагают достаточно развитую функциональность. Поддержка кластеризованных баз данных планируется на основе интеграции приобретенной нами технологии NDB-кластеров с новым механизмом хранения, который стал доступным в 2004 году. Мы также готовимся предоставить поддержку XML на сервере баз данных.
1.8.1. Стандарты, которым соответствует MySQL Мы нацелены на реализацию полной поддержки стандарта ANSI/ISO, но без компромиссов в отношении производительности и качества кода. ODBC уровней 0-3.51.
1.8.2. Выбор режимов SQL Сервер MySQL может работать в различных режимах SQL и может по-разному применять эти режимы для различных клиентов. Это дает приложениям возможность приспосабливать функционирование сервера к существующим требованиям. Режимы определяют, какой синтаксис SQL должен поддерживать сервер MySQL и какой тип проверок он должен выполнять для данных. Это позволяет использовать MySQL во множестве различных сред, а также применять его вместе с другими серверами баз данных. Режим SQL по умолчанию устанавливается во время запуска mysqld с помощью опции --sql-mode="modes". Начиная с MySQL 4.1, можно изменять режим после запуска сервера путем установки переменной sqljnode с помощью оператора SET [SESSION|GLOBAL] sql_mode='modes'.
1.8.3. Запуск MySQL в режиме ANSI Чтобы перевести mysqld в ANSI-режим, запустите его с опцией —ansi.
58
Глава 1. Общая информация
Выполнение сервера в режиме ANSI эквивалентно его запуску со следующими опциями (значения —sql-mode должны указываться в одной строке): --transaction-isolation=SERIALIZABLE —sql-mode=REAL_AS_FLOAT,PIPES_AS_CONCAT/ANSI_QUOTESf IGNORE_SPACE,ONLY_FULL_GROUP_BY В MySQL 4.1 можно получить тот же результат с помощью следующих операторов: SET GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE; SET GLOBAL sql_mode = 'REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES, IGNORE_SPACE,ONLY_FULL_GROUP_BY'; См. раздел 1.8.2. В MySQL 4.1.1 опция sqljnode может быть также установлена так, как показано ниже: SET GLOBAL sql_mode='ansi'; В этом случае значением переменной sqljnode будут все опции, имеющие отношение к режиму ANSI. Вы можете проверить это так: mysql> SET GLOBAL sql_mode='ansi'; mysql> SELECT @@global.sqljnode; -> 'REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES, IGNORE_SPACE,ONLY_FULL_GROUP_BY,ANSI';
1.8.4. Расширения стандартного SQL в MySQL В состав сервера MySQL входит ряд расширений, которых, возможно, вы не найдете в других базах данных SQL. Помните, что если вы используете их, ваш код перестанет быть переносимым на другие серверы SQL. В некоторых случаях вы можете писать код, включающий расширения MySQL, но остающийся переносимым, используя для этого форму комментариев /*! . . . */. В этом случае сервер MySQL разбирает и выполняет код внутри комментария, как и любые другие SQL-операторы, а все другие серверы SQL расширение проигнорируют. Например: SELECT /*! STRAIGHT_JOIN */ имя_столбца FROM таблица1,таблица2 WHERE . . . Если после символа '!' добавить номер версии, синтаксис внутри комментария будет выполняться только сервером MySQL указанной и более поздних версий: CREATE /*132302 TEMPORARY */ TABLE t (a INT); Это означает, что если работа выполняется в версии MySQL 3.23.02 или более поздней, то ключевое слово TEMPORARY будет использовано. В приведенном ниже списке описаны расширения MySQL по категориям. • Организация данных на диске. Сервер MySQL отображает каждую базу данных на подкаталог внутри каталога данных MySQL, а таблицы внутри базы - на имена файлов в этом каталоге. Отсюда вытекает несколько следствий: •
Имена баз данных и таблиц MySQL зависят от регистра в средах операционных систем, в которых имена файлов чувствительны к регистру символов (большинство Unix-систем). • Можно использовать стандартные системные команды для резервного копирования, переименования, перемещения, удаления и копирования таблиц, управ-
1.8. Соответствие стандартам MySQL
59
ляемых механизмами хранения My ISAM или ISAM. Например, чтобы переименовать таблицу MylSAM, потребуется переименовать файлы .MYD, .MYI и .frm, которые относятся к таблице. Имена баз данных, таблиц, индексов, столбцов и псевдонимы могут начинаться с цифры (но не должны состоять только из цифр). •
•
Общий синтаксис языка. •
Строки могут ограничиваться и одиночными и двойными кавычками.
• •
Символ 'V используется в строках как управляющий. Внутри SQL-операторов можно получать доступ к таблицам из разных баз данных посредством синтаксиса имя_базы_данных. имя__таблицы. Некоторые серверы SQL предоставляют ту же функциональность, но называют ее пространством пользователя (User space). Сервер MySQL не поддерживает табличных пространств, как в следующем операторе: CREATE TABLE r a l p h . m y _ t a b l e . . .IN my_tablespace.
Синтаксис SQL-операторов. •
О п е р а т о р ы ANALYZE TABLE, CHECK TABLE, OPTIMIZE TABLE И REPAIR TABLE.
•
О п е р а т о р ы CREATE DATABASE И DROP DATABASE.
•
Оператор DO.
•
EXPLAIN SELECT - для получения описания способа объединения таблиц в запросе.
•
Операторы FLUSH и RESET.
•
Оператор SET.
•
Оператор SHOW.
•
LOAD DATA INFILE. Во многих случаях этот синтаксис совместим с аналогичным синтаксисом Oracle.
•
RENAME TABLE.
•
REPLACE вместо DELETE + INSERT.
•
Конструкции CHANGE имя^столбца, DROP имя_столбца, DROP INDEX, IGNORE и RENAME в операторе ALTER TABLE. Использование множественных конструкций ADD, ALTER, DROP И CHANGE В о п е р а т о р е ALTER TABLE.
•
Использование имен индексов, индексов в префиксах полей, а также конструкций INDEX ИЛИ KEY В операторе CREATE TABLE.
•
Использование IF EXISTS вместе с DROP TABLE.
•
Можно удалять несколько таблиц одним оператором DROP TABLE.
•
Конструкции ORDER BY и LIMIT в операторах UPDATE и DELETE.
•
Синтаксис INSERT INTO...SET имя_столбца =
•
Конструкция DELAYED в операторах INSERT и REPLACE.
•
Конструкция LOW_PRIORITY В операторах INSERT, REPLACE, DELETE И UPDATE.
•
Использование INTO OUTFILE и STRAIGHT_JOIN в операторе SELECT.
•
ОПЦИЯ SQL_SMALL_RESULT оператора SELECT.
60
Глава 1. Общая информация •
Нет необходимости перечислять все выбранные столбцы в конструкции GROUP BY. Это обеспечивает лучшую производительность для некоторых очень специфических, но вполне нормальных запросов.
•
Можно применять ASC или DESC вместе с GROUP BY.
•
Имеется возможность присваивать значения переменным с помощью операции присваивания : = в операторах: mysql> SELECT @a:=SUM(total),@b=COUNT(*),@a/@b AS avg -> FROM t e s t _ t a b l e ; mysql> SELECT @tl:=(@t2:=l)+@t3:=4,@tl,@t2,@t3;
• Типы столбцов. • Типы столбцов MEDIUMINT, SET, ENUM и различные варианты типов BLOB и TEXT. • Атрибуты столбцов AUTO_INCREMENT, BINARY, NULL, UNSIGNED И ZEROFILL. • Функции и операции. • Чтобы облегчить жизнь пользователям, привыкшим к другим SQL-средам, сервер MySQL поддерживает псевдонимы для многих функций. Например, все строковые функции поддерживают как стандартный синтаксис SQL, так и синтаксис ODBC. •
Сервер MySQL воспринимает операции && и | | как логическое " И " (AND) и логическое "ИЛИ" (OR), по аналогии с языком программирования С. В контексте сервера MySQL операции | | и OR являются синонимами, равно как и & & и AND. По этой причине MySQL не поддерживает стандартную SQL-операцию | | для конкатенации строк. Вместо этого необходимо применять функцию CONCAT (). Поскольку CONCAT () принимает любое количество аргументов, преобразовать все операции | | очень легко.
•
Использование COUNT (DISTINCT список), где список содержит более одного элемента. • Все сравнения строк по умолчанию чувствительны к регистру, а порядок сортировки определяется текущим выбранным набором символов (по умолчанию ISO-8859-1 Latin 1). Если это не подходит, потребуется объявить столбец с атрибутом BINARY либо воспользоваться приведением к BINARY, что заставит выполнять сравнение и сортировку в соответствии с кодами символов, а не в лексикографическом порядке. •
Операция % является синонимом функции MOD (). То есть, выражение N % м эквивалентно MOD(N, M). '%' поддерживается для удобства программистов на языке С и достижения совместимости с СУБД PostgresSQL.
•
Операции =, о , , « , » , , AND, OR и LIKE могут применяться для сравнения столбцов слева от конструкции FROM в операторах SELECT, например: mysql> SELECT coll=l AND col2=2 FROM имя^таблицы;
•
Функция LASTINSERTIDO AUTO_INCREMENT.
возвращает
самое
последнее
значение
•
LIKE можно применять к числовым столбцам.
•
Расширенные операции обработки регулярных выражений REGEXP и NOT REGEXP.
1.8. Соответствие стандартам MySQL
61
•
Функции CONCAT () и CHAR () принимают один и более аргументов.
•
Ф у н к ц и и B I T _ C 0 U N T ( ) , CASE, E L T ( ) , F R O M _ D A Y S ( ) , FORMAT ( ) , I F ( ) , PASSWORD ( ) , ENCRYPT ( ) , MD5 ( ) , ENCODE ( ) , DECODE ( ) , PERIOD_ADD ( ) , P E R I O D _ D I F F ( ) , TO_DAYS ( ) И WEEKDAY().
•
Применение TRIM() для усечения подстрок. Стандартный язык SQL поддерживает только удаление последовательностей одинаковых символов. • Возможность в конструкции GROUP BY обращаться к функциям STD(), BIT_OR(), BIT_AND(), BIT_XOR() И GROUP_CONCAT().
Для ознакомления с перечнем новых расширений, которые планируется добавить в сервер MySQL, а также с их приоритетностью, просмотрите список "TODO" по адресу http://dev.mysql.com/doc/mysql/en/TODO.html. В настоящем руководстве представлена последняя на данный момент версия списка "TODO". См. также раздел 1.6.
1.8.5. Отличия MySQL от стандартного SQL Мы стараемся, чтобы MySQL в основном следовал требованиям стандартов ANSI SQL и ODBC SQL, но в приведенных ниже случаях некоторые операции MySQL выполняет иначе: • В столбцах типа VARCHAR завершающие пробелы удаляются при сохранении значения (см. раздел 1.8.7). • В некоторых случаях столбцы типа CHAR скрыто преобразуются в VARCHAR, когда определяется либо изменяется структура таблицы. • Привилегии для таблицы при удалении таблицы автоматически не удаляются. Для этого необходимо явно вызвать оператор REVOKE. 1.8.5.1. Подзапросы MySQL 4.1 поддерживает подзапросы и вторичные таблицы. Подзапрос - это оператор SELECT, вложенный в другой оператор. Вторичная таблица (неименованное представление) - это подзапрос в конструкции FROM другого оператора. Для более старых версий MySQL большинство подзапросов могут быть переписаны в виде объединений или с использованием других методов. 1.8.5.2. Оператор SELECT INTO TABLE В сервере MySQL не реализована поддержка следующего расширения SQL от Sybase: SELECT... INTO TABLE... Вместо этого MySQL поддерживает стандартный SQLсинтаксис INSERT INTO... SELECT..., который в основном делает то же самое. INSERT INTO tbl_temp2 (fld_id) SELECT tbl_templ.fld_order_id FROM tbl_templ WHERE tbl_templ.fld_order_id > 100; В качестве альтернативы можно воспользоваться SELECT INTO OUTFILE... или CREATE TABLE SELECT... Начиная с версии 5.0, MySQL поддерживает SELECT.. .INTO с пользовательскими переменными.
62
Глава 1. Общая информация
1.8.5.3. Транзакции и атомарные операции Сервер MySQL (старшие выпуски версий 3.23 и все версии, начиная с 4.0) поддерживает транзакции в механизмах хранения innoDB и BDB. innoDB обеспечивает полную совместимость с ACID. Остальные нетранзакционные механизмы хранения MySQL (такие, как My ISAM) следуют различным парадигмам обеспечения целостности данных, которые называются "атомарными операциями". В терминологии транзакций таблицы My ISAM всегда работают в режиме AUTOCOMMIT=1. Атомарные операции часто предлагают сопоставимую целостность с более высокой производительностью. Поскольку сервер MySQL поддерживает обе парадигмы, вы сами решаете, будут ли ваши приложения лучше работать со скоростью атомарных операций или с использованием средств управления транзакциями. Этот выбор осуществляется на уровне таблиц. Как упоминалось ранее, различия в работе между транзакционными и нетранзакционными таблицами отражаются в основном на производительности. Транзакционные таблицы требуют значительно больших затрат памяти, дискового пространства и нагрузки на центральный процессор. С другой стороны, транзакционные таблицы, подобные InnoDB, также предлагают много существенных дополнительных возможностей. Модульная архитектура сервера MySQL допускает одновременное использование разных механизмов хранения для удовлетворения различным требованиям и достижения оптимальной производительности во всех ситуациях. Но как использовать средства сервера MySQL для поддержки строгих требований целостности данных даже на нетранзакционных таблицах My ISAM, и как эти средства сравнить с работой с транзакционными таблицами? 1. Если ваше приложение написано таким образом, что оно зависит от возможности вызывать ROLLBACK вместо COMMIT в критических ситуациях, транзакции более удобны. Транзакции также гарантируют, что незавершенные обновления или результаты сбоев не будут записаны в базу данных. Сервер имеет возможность выполнить автоматический откат и сохранить базу данных. Если же вы применяете нетранзакционные таблицы, сервер MySQL почти во всех случаях предоставляет вам возможность разрешить потенциальные проблемы, включив простые проверки перед обновлением или, запуская простые сценарии, которые проверяют базу данных на непротиворечивость и автоматически вносят исправления либо выдают предупреждения, если обнаружены какие-то противоречия. Стоит отметить, что даже просто включая протоколирование работы MySQL или добавляя дополнительный протокол, вы можете нормально исправить таблицы без потери целостности. 2. В большинстве случаев критические транзакционные обновления могут быть переписаны как атомарные операции. Вообще говоря, все проблемы целостности, которые решают транзакции, могут быть предотвращены блокировкой таблиц LOCK TABLE или атомарными обновлениями, гарантирующими, что вы никогда не будете автоматически прерваны сервером, что является общей проблемой транзакционных систем управления базами данных. 3. Даже транзакционные системы могут терять данные, если сервер отключается. Разница между системами состоит только в том, насколько мал промежуток времени, в течение которого возможна потеря данных. Нет систем, безопасных на 100%, а есть только "достаточно безопасные". Даже СУБД Oracle, имеющая репу-
1.8. Соответствие стандартам MySQL
63
тацию наиболее безопасной из транзакционных систем, периодически сообщает об утере данных в ситуациях подобного рода. Для безопасной работы с сервером MySQL, независимо от того используются или нет транзакционные таблицы, нужно иметь резервные копии и держать включенным бинарное протоколирование. В этом случае вы сможете восстановить данные после любой ситуации, в которую можно попасть, имея дело с другими системами. Вообще говоря, располагать актуальными резервными копиями полезно при работе с любой СУБД. Транзакционная парадигма обладает своими преимуществами и недостатками. Многие пользователи и разработчики приложений зависят от того, насколько просто можно написать код, моделирующий систему, для которой прерывание работы возможно или необходимо. Однако, даже если вы новичок в парадигме атомарных операций, либо лучше знакомы с транзакционной моделью, согласитесь, что выигрыш в производительности в 3-5 раз, который дает применение нетранзакционных таблиц по сравнению с наиболее быстрыми и оптимизированными транзакционными, весьма существенен. В ситуациях, когда целостность данных чрезвычайно важна, сервер MySQL демонстрирует надежность уровня транзакционных систем даже при работе с нетранзакционными таблицами. Если выполняется блокировка таблицы командой LOCK TABLE, все обновления приостанавливаются до тех пор, пока не выполнятся все проверки целостности. Если применяется блокировка READ LOCAL (в отличие от блокировки записи) для таблицы, допускающей параллельную вставку в конец, чтение разрешено, равно как и вставка другими клиентами. Вновь добавленные записи не будут видимы клиентом, установившим блокировку чтения, до тех пор, пока он не снимет блокировку. Применяя INSERT DELAYED, вы можете вставлять записи в локальную очередь до тех пор, пока не будет снята блокировка, не заставляя клиента ожидать завершения операции вставки. Слово "атомарный" в том смысле, в каком мы его понимаем, не несет в себе ничего сверхъестественного. Оно означает только то, что вы можете быть уверены, что пока специфическое обновление идет, никакой другой пользователь не может взаимодействовать с ним, и поэтому не будет никакого автоматического отката (что может случиться с транзакционными таблицами, если вы не проявите достаточную осторожность). Сервер MySQL также гарантирует, что не будет никаких недействительных результатов чтения (dirty read). Ниже перечислены некоторые приемы работы с нетранзакционными таблицами. • Циклы, которые нуждаются в транзакциях, обычно могут быть закодированы с помощью LOCK TABLES; необходимости иметь дело с курсорами для обновления записей на лету нет. • Для того чтобы избежать использования ROLLBACK, можно прибегнуть к следующей стратегии: 1. Используйте LOCK TABLES для блокировки всех таблиц, к которым нужен доступ. 2. Проверяйте все условия, которые должны быть истинными до начала обновлений. 3. Выполняйте обновления только если все в порядке. 4. Используйте UNLOCK TABLES для разблокирования таблиц. Обычно это значительно более быстрый метод, чем применение транзакций с возможными откатами, хотя и не всегда. Единственная ситуация, когда это реше-
64
Глава 1. Общая информация ние не удачно, это если кто-то прервет поток приложения во время обновления. В таком случае все блокировки будут сняты, но часть обновлений останется невыполненной. • Можно также использовать функции для обновления записей за одну операцию. Можно получить весьма эффективные приложения, применяя следующую технику: • Модифицировать столбцы в соответствии с их текущими значениями. • Обновлять только те столбцы, которые изменились. Например, когда выполняется обновление информации о заказчиках, мы обновляем только те данные, что изменились, либо данные, зависящие от измененных данных, сравнив их новые значения с исходными. Проверка измененных данных делается в конструкции WHERE оператора UPDATE. Если в результате запись не изменилась, потребуется выдать клиенту сообщение наподобие: "Некоторые из изменяемых вами данных изменены другим пользователем". Затем следует отобразить старую и новую версии записи о клиенте, чтобы пользователь решил, какую из них принять. Это обеспечивает механизм, подобный блокировке столбца, но на самом деле даже лучше, потому что мы обновляем только некоторые из столбцов, используя новые значения, зависящие от их текущих значений. Это означает, что типовые операторы UPDATE должны выглядеть, как показано ниже: UPDATE tablename SET pay_back=pay_back+125; UPDATE customer SET customer_date='current_date', address='new address', phone='new phone', money_owed_to_us=money_owed_to_us-125 WHERE customer_id=id AND address='old address' AND phone='old phone'; Такой подход весьма эффективен и работает, даже если другой клиент изменяет значения столбцов pay_back и money_owed_to_us. • Во многих случаях пользователи хотят применять LOCK TABLES и/или ROLLBACK для целей управления уникальными идентификаторами. Это также можно обработать гораздо более эффективно без блокировок и откатов, используя столбцы AUTO_INCREMENT И либо SQL-фунКЦИЮ LAST_INSERT_ID(), либо функцию С API С именем mysql_insert_id (). Обычно можно написать код, обслуживающий ситуации, когда требуется блокировка уровня строки. В некоторых ситуациях это действительно необходимо, и таблицы innoDB поддерживают такие блокировки. Для таблиц My ISAM можно воспользоваться столбцами-флагами и поступить примерно так: UPDATE имя_таблицы SET row_flag = 1 WHERE id = ID; MySQL вернет 1 в качестве количества обновленных записей, если строка найдена и rowf lag не был равен 1 в исходной строке. Можете думать об этом, как если бы сервер MySQL изменил предыдущий запрос на такой: UPDATE имя_таблицы SET row_flag = 1 WHERE id = ID AND row_flag 1;
1.8. Соответствие стандартам MySQL
65
1.8.5.4. Хранимые процедуры и триггеры Хранимые процедуры реализованы в MySQL 5.O. Триггеры запланированы к реализации в версии 5.1. Триггер - это разновидность хранимой процедуры, которая вызывается при наступлении какого-то события. Например, можно написать процедуру, которая отрабатывает каждый раз, когда запись удаляется из транзакционной таблицы, и эта процедура автоматически удаляет соответствующего заказчика из таблицы заказчиков, когда все его финансовые транзакции удалены.
1.8.5.5. Внешние ключи В сервере MySQL 3.23.44 и последующих версий механизм хранения InnoDB поддерживает проверку ограничений на внешние ключи, включая CASCADING, ON DELETE и ON UPDATE. Для других механизмов хранения MySQL анализирует синтаксис FOREIGN KEY в операторе CREATE TABLE, но не использует и не хранит его. В будущих реализациях планируется сохранять эту информацию в файле спецификаций таблиц, чтобы она могла быть извлечена с помощью mysqldump и через ODBC. На более поздней стадии ограничения внешних ключей будут реализованы и для таблиц My ISAM. Применение внешних ключей дает разработчикам баз данных некоторые преимущества: •
Если предположить, что отношения между таблицами спроектированы правильно, ограничения внешних ключей значительно затрудняют программистам возможность внести в базу данных какую-либо противоречивую информацию.
•
Централизованная проверка ограничений со стороны сервера делает излишней эту проверку со стороны приложения. Это исключает вероятность того, что некоторые приложения могут ее выполнять, а некоторые - нет.
•
Применением каскадных обновлений и удалений может существенно упростить код приложений.
•
Правильно спроектированные внешние ключи упрощают документирование отношений между таблицами.
Однако следует помнить, что эти выгоды достигаются за счет большей нагрузки на сервер баз данных, которому приходится выполнять все проверки. Это приводит к некоторому снижению производительности, что для ряда приложений может оказаться настолько нежелательным, что лучше обойтись без этого вообще. (Некоторые важные коммерческие программы по этой причине имеют встроенную проверку логики внешних ключей на уровне приложения.) MySQL дает возможность разработчикам выбирать требуемый подход. Если вам не нужны внешние ключи, и вы хотите избежать лишней нагрузки, связанной с проверками ссылочной целостности, вы можете выбрать другой тип таблиц, такой как My ISAM. Например, механизм хранения My ISAM обеспечивает очень высокую производительность для приложений, которые выполняют только операции INSERT и SELECT, поскольку вставки могут выполняться одновременно с выборками. Если вы предпочитаете обойтись без преимуществ проверки ссылочной целостности, вам следует иметь в виду следующее: •
При отсутствии проверки отношений внешних ключей со стороны сервера этим должно заниматься само приложение. Например, придется заботиться о вставке записей в таблицы в правильном порядке, избегая появления висячих дочерних
66
Глава 1. Общая информация записей. Приложение также должно быть готовым к восстановлению после ошибок, связанных с прерыванием операций массовой вставки записей. • Если приложению требуется только ссылочная целостность типа ON DELETE, следует отметить, что в MySQL 4.0 имеется возможность выполнять многотабличные операции DELETE для удаления записей из многих таблиц одним оператором. • Обходной путь, позволяющий компенсировать отсутствие ON DELETE, заключается в том, чтобы добавить соответствующие дополнительные операторы DELETE в приложение для удаления записей из таблиц, имеющих внешние ключи. На практике часто это работает так же быстро, как и автоматические внешние ключи, но при этом значительно более переносимо. Не забывайте, что применение внешних ключей иногда порождает проблемы: • Поддержка внешних ключей применима ко многим случаям, когда нужно обеспечить ссылочную целостность, но это не отменяет необходимости очень тщательного проектирования отношения ключей, чтобы избегать циклических зависимостей или некорректных комбинаций каскадного удаления. • Не столь уж необычна ситуация, когда администратор баз данных создает такую топологию отношений между таблицами, которая затрудняет восстановление отдельных таблиц из резервной копии. (MySQL смягчает сложность ситуаций подобного рода, позволяя временно отключать проверки внешних ключей на время загрузки данных в таблицы, зависящие от других таблиц. В MySQL 4.1.1 утилита mysqldump генерирует файлы дампа, которые это делают автоматически при загрузке.)
Следует помнить, что внешние ключи в SQL применяются для проверки и поддержания ссылочной целостности, но не для объединения таблиц. Если вам нужен результат запроса к множеству таблиц от одного оператора SELECT, вы делаете это за счет описания объединения между ними: SELECT * FROM tl, t2 WHERE tl.id = t2.id; Синтаксис FOREIGN KEY без ON DELETE... часто применяется в ODBC-приложениях для автоматической генерации конструкций WHERE.
1.8.5.6. Представления Представления в настоящее время реализованы и появятся в версии 5.0 сервера MySQL. Неименованные представления {вторичные таблицы, подзапросы в конструкции FROM оператора SELECT) уже реализованы в версии 4.1. Исторически сложилось так, что сервер MySQL больше всего использовался в приложениях и Web-системах, где разработчик имел полный доступ к используемой базе данных. Однако ситуация постепенно менялась, и теперь мы обнаружили, что все возрастающее число пользователей считают представления очень важным и полезным средством. Представления применяются для того, чтобы предоставить пользователям доступ к группе таблиц таким образом, как будто это одна таблица и тем самым ограничить доступ к ним. Представления также можно использовать для ограничения доступа к строкам таблицы (выделяя, таким образом, подмножество записей). Для ограничения доступа к столбцам представления не нужны, поскольку сервер MySQL обладает развитой системой привилегий.
1.8. Соответствие стандартам MySQL
67
Многие СУБД не разрешают выполнять операции обновления представлений. Вместо этого необходимо обновлять отдельные таблицы. При разработке механизма поддержки представлений в MySQL нашей целью было, оставаясь, насколько возможно, в рамках стандарта SQL, достичь полной совместимости с шестым правилом Кодда для реляционных баз данных. Все представления, теоретически обновляемые, должны быть обновляемы на практике.
1.8.5.7.'--' как начало комментария В ряде других СУБД ' — ' используется для обозначения начала комментария. Сервер MySQL в качестве начального символа комментария использует '#'. Также поддерживаются комментарии в стиле языка С: /* пример комментария */. Сервер MySQL 3.23.3 и более поздние версии поддерживают комментарии, начинающиеся с '—', предполагая, что за комментарием следует пробел (или управляющий символ вроде перевода строки). Требование, касающееся пробелов, предотвращает проблемы с автоматически сгенерированными SQL-запросами, которые используют чтонибудь наподобие показанного ниже кода, где вместо !payment! автоматически подставляется значение оплаты: UPDATE account SET credit=credit-'payment! Подумайте, что случится, если значение оплаты будет отрицательным, например, -1: UPDATE.account SET credit=credit—1 credit—1 - вполне корректное выражение на языке SQL, но если — интерпретируется как начало комментария, то часть выражения после этого фрагмента теряется. В результате получаем оператор, имеющий совершенно другой смысл, чем ожидалось: UPDATE account SET credit=credit Он не выполняет никакого обновления вообще! Это иллюстрирует то обстоятельство, что разрешение использовать в качестве начала комментария '--' чревато довольнотаки неприятными последствиями. Используя реализацию метода задания комментариев, поддерживаемую в MySQL 3.23.3 и последующих версиях, получаем безопасное выражение credit—1. Другое безопасная возможность состоит в том, что интерпретатор командной строки mysql удаляет строки, начинающиеся с ' - - ' . Приведенная далее информация справедлива, только если вы работаете с MySQL версий, предшествующих 3.23.3. Если у вас есть SQL-программа в текстовом файле, которая включает комментарии, начинающиеся с *—', вам придется с помощью утилита replace заменить их на комментарии с символом '#': shell> replace " —" " #" < text-file-with-funny-comments.sql \ | mysql имя_базы_данных
вместо обычного: shell> mysql имя_базы_данных < text-file-with-funny-comments.sql Можно также отредактировать командный файл на месте, заменив ' — ' на '#': shell> replace " —" " #" — text-file-with-funny-comments.sql Вернуться к исходному варианту можно следующим образом: shell> replace " #" " —" — text-file-with-funny-comments.sql
68
Глава 1. Общая информация
1.8.6. Как MySQL работает с ограничениями MySQL позволяет работать как с транзакционными таблицами, для которых возможен откат, так и с нетранзакционными, для которых откат не предусмотрен, поэтому работа с ограничениями (constraints) в MySQL несколько отличается от того, как это делается в других СУБД. Нам приходится иметь дело с ситуацией, когда нужно обновить множество строк в нетранзакционной таблице, причем нет возможности выполнить откат при возникновении ошибки. Базовая философия состоит в том, чтобы попытаться сгенерировать ошибку для всего, что можно обнаружить во время компиляции, но попытаться восстановиться после любой ошибки, возникшей во время выполнения. Мы достигаем этого в большинстве случаев, но пока еще не во всех (см. раздел 1.6.4). Выбор, который стоит перед MySQL сводится к тому, что в случае возникновения ошибки необходимо остановить выполнение оператора на полпути или восстановить данные настолько хорошо, насколько возможно, и продолжать работу. В последующих разделах описано, что происходит в этих случаях с различными типами ограничений.
1.8.6.1. Ограничение PRIMARY KEY/UNIQUE Нормально, если генерируется ошибка при попытке вставить или обновить запись, которая приводит к нарушению ограничений первичного ключа, внешнего ключа или уникального ключа. Если используется транзакционный механизм хранения, подобный innoDB, MySQL автоматически выполнит откат транзакции. Если же применяется нетранзакционный механизм хранения, MySQL остановится на некорректной записи и оставит все оставшиеся записи неизмененными. Чтобы облегчить жизнь, MySQL поддерживает ключевое слово IGNORE для большинства команд, которые могут привести к нарушению ключей (например, INSERT IGNORE или UPDATE IGNORE). В этих случаях MySQL просто игнорирует любые нарушения ограничений ключей и продолжает обрабатывать остальные строки. Информация о том, что предпринял MySQL, доступна через функцию mysql_info() API-интерфейса С. В MySQL 4.1 и последующих версиях можно также воспользоваться командой SHOW WARNINGS.
Стоит напомнить, что на данный момент внешние ключи поддерживают только таблицы InnoDB. Реализация внешних ключей для таблиц My ISAM запланирована в версии MySQL 5.1.
1.8.6.2. Ограничения NOT NULL и значения DEFAULT Чтобы обеспечить простое управление нетранзакционными таблицами, все столбцы таблиц в MySQL имеют значения по умолчанию. Если вы вставляете "неправильное" значение в столбец, такое как NULL в столбец, объявленный как NOT NULL, или же слишком большое значение в числовой столбец, MySQL установит его значение в "лучшее из возможных" вместо того, чтобы выдавать ошибку: •
Если вы попытаетесь сохранить в числовом столбце значение, выходящее за пределы допустимого диапазона, сервер MySQL вставит вместо него ноль, минимально возможное либо максимально возможное значение для этого столбца.
1.8. Соответствие стандартам MySQL
69
• В строковом столбце сервер MySQL сохранит либо пустую строку, либо самую длинную, которая может поместиться в данный столбец. • Если вы попытаетесь вставить строку, начинающуюся не с цифры, в числовой столбец, MySQL запишет туда 0. • Если попытаться вставить значение NULL в столбец, не допускающий значений NULL, MySQL вставит вместо этого 0 в числовой столбец и пустую строку - в символьный. (Однако такое поведение при вставке одиночных записей может быть изменено, если скомпилировать сервер MySQL с опцией компиляции -DONT_USE_DEFAULT_FIELDS.) Это заставит операторы INSERT генерировать ошибки, если только вы явно не зададите значения для всех столбцов, которые требуют значений NOT NULL. • MySQL позволит сохранить некоторые неправильные значения даты в столбцы типа DATE и DATETIME (например '2000-02-31' или '2000-02-00'). Идея состоит в том, что проверка корректности дат не является обязанностью сервера SQL. Если MySQL может сохранять значение даты и извлекать точно такое значение, он сохраняет его таким, как получил. Если дата абсолютно неправильная (за пределами возможностей сервера сохранить ее), то вместо нее сохраняется специальное значение '0000-00-00'. Причина существования изложенных правил заключается в том, что мы не можем проверить эти условия до тех пор, пока не начнется выполнение запроса. Мы не можем выполнить откат изменений, если сталкиваемся с проблемой после того, как несколько строк уже обновлены, поскольку данный тип таблиц может не поддерживать транзакции. Выбор в пользу прерывания выполнения оператора представляется неудачным - в этом случае получается, что обновление выполнено наполовину, что приводит к наихудшему сценарию. В этом случае предпочтительнее сделать "лучшее из возможного" и затем продолжить, как будто ничего не произошло. Это означает, что не стоит полагаться на MySQL в смысле проверки корректности данных столбцов. Вместо этого приложение само должно заботиться о том, чтобы отправлять серверу MySQL только правильные данные. В MySQL 5.0 мы планируем провести улучшения, выдавая предупреждения, когда происходит автоматическое преобразование столбцов, плюс опцию, позволяющую откатить оператор, который пытается выполнить запрещенное присваивание данных до тех пор, пока используются только транзакционные таблицы.
1.8.6.3. Ограничения ENUM и SET В MySQL 4.x ENUM не является настоящим ограничением, а просто наиболее эффективным способом определения столбцов, которые могут содержать значения только из заданного набора возможных значений. Если вы вставляете некорректное значение в столбец типа ENUM, оно устанавливается в зарезервированное перечислимое значение 0, которое отображается как пустая строка в строчном контексте. При попытке вставки некорректного значения в столбец типа SET это значение игнорируется. Например, если столбец может содержать значения ' а ' , ' Ь ' и ' с ' , попытка сохранить в столбце значения ' а, х, Ь, у' приведет к сохранению ' a, b ' .
70
Глава 1. Общая информация
1.8.7. Известные ошибки и недостатки дизайна MySQL 1.8.7.1. Ошибки в версии 3.23, исправленные в более поздних версиях MySQL Перечисленные ниже известные ошибки не были исправлены в версии 3.23, поскольку их исправление привело бы к изменению большой части кода, что могло, в свою очередь, вызвать появление других, даже намного худших ошибок. Эти ошибки классифицируются как "не критические" или "терпимые". • Можно возникнуть взаимная блокировка, если использовать LOCK TABLE для блокировки нескольких таблиц и затем в том же соединении удалить одну из них оператором DROP TABLE в то время, когда другой поток пытается ее заблокировать. (Для устранения взаимной блокировки можно с помощью команды KILL завершить любой из участвующих в ней потоков.) Эта проблема была решена в MySQL 4.0.12. •
SELECT МАХ {ключевой__столбец) FROM t l , t 2 , t 3 . . . , где одна из таблиц пуста, не возвращает NULL, а возвращает максимальное значение столбца. Это исправлено в MySQL 4.0.11.
•
DELETE FROM таблица_Пеар без конструкции WHERE не работает на блокированной НЕАР-таблице.
1.8.7.2. Ошибки в версии 4.0, исправленные в более поздних версиях Перечисленные ниже известные ошибки не были исправлены в версии 4.0, поскольку их исправление привело бы к изменению большой части кода, что могло, в свою очередь, вызвать появление других, даже намного худших ошибок. Эти ошибки также классифицируются, как "не критические" или "терпимые". • В UNION первый же оператор SELECT определяет свойства результирующих столбцов - тип, максимальную длину (max_length), возможность записи значений NULL. Это было исправлено в MySQL 4.1.1 - значения свойств столбцов определяются на основании строк из всех частей UNION. • В операторе DELETE по нескольким таблицам невозможно обращаться к таблицам по псевдонимам. Исправлено в MySQL 4.1.
1.8.7.3. Открытые ошибки и недостатки дизайна MySQL Следующие проблемы уже известны и решение их имеет наивысший приоритет: • Удаление ограничений FOREIGN KEY не работает на реплицированной копии, поскольку ограничение может иметь другое имя, чем в исходной базе. •
REPLACE (и LOAD DATA С опцией REPLACE) не вызывает ON DELETE CASCADE (каскадного удаления).
• Невозможно смешивать UNION ALL и UNION DISTINCT в одном и том же запросе. Если используется ALL для одного из UNION, это касается их всех. • Если один пользователь запустил долго выполняемую транзакцию, а другой удалил таблицу, которая обновлялась в этой транзакции, то существует небольшая вероятность того, что в бинарный протокол попадет команда DROP TABLE, прежде чем таблица будет задействована в транзакции. Мы планируем исправить это в
1.8. Соответствие стандартам MySQL
71
версии 5.0, заставив оператор DROP TABLE ожидать до тех пор, пока таблица используется хотя бы в одной транзакции. • При вставке больших целочисленных значений (между 2 6 3 и 2 6 4 - 1) в десятичный или строковый столбец, оно вставляется как отрицательное значение, поскольку число оценивается в контексте целого со знаком. Мы планируем исправить это в MySQL 4.1. •
FLUSH TABLES WITH READ LOCK не блокирует CREATE TABLE ИЛИ COMMIT, ЧТО может привести к проблемам с позицией в бинарном протоколе при выполнении полного резервного копирования таблиц и бинарного протокола.
• ANALYZE TABLE для таблиц BDB в некоторых случаях может приводить к тому, что таблицы становятся недоступными до тех пор, пока не будет перезапущен mysqld. Если это случается, в файл ошибок MySQL добавляется такая строка: 001207 22:07:56 bdb: log_flush: LSN past current end-of-log • MySQL принимает скобки в конструкции FROM оператора SELECT, но молча игнорирует их. Причина того, что сообщения об ошибках не выдаются, состоит в том, что очень многие клиенты при автоматической генерации запросов добавляют скобки в конструкцию FROM, даже если в этом нет необходимости. • Объединение многих RIGHT JOIN или комбинаций LEFT JOIN и RIGHT JOIN в одном запросе могут не приводить к корректному результату, потому что MySQL генерирует строки NULL для таблицы, следующей за LEFT JOIN или перед RIGHT JOIN. Это будет исправлено в 5.0, одновременно мы добавим поддержку скобок в предложение FROM. • Не выполняйте ALTER TABLE для таблицы BDB, участвующей в многотабличных транзакциях, до тех пор, пока все они не завершатся. (Транзакции могут быть проигнорированы.) • Команды ANALYZE TABLE, OPTIMIZE TABLE И REPAIR TABLE могут вызывать проблемы в таблицах, в которых используется INSERT DELAYED. • Выполнение LOCK TABLE... и FLUSH TABLES... не гарантирует, что в таблице не окажется наполовину завершенных транзакций. • Таблицы BDB открываются несколько медленно. Если в базе данных есть много таблиц BDB, потребуется немало времени, чтобы запустить клиент mysql с опцией -А или выполнить rehash. В особенности это касается тех случаев, когда имеется большой табличный кэш. • Репликация использует протоколирование уровня запросов. Реплицируемая база фиксирует выполняемые запросы в бинарном протоколе. Это очень быстрый, компактный и эффективный метод протоколирования, который в большинстве случаев работает превосходно. Однако, хотя нам и не известны такие случаи, существует теоретическая возможность того, что данные в исходной и целевой базе окажутся разными, если запрос составлен таким образом, что модификация данных будет недетерминированной. Это остается на совести оптимизатора запросов. (Вообще говоря, это очень плохая практика, даже за рамками темы репликации!). Например: • Операторы CREATE... SELECT или INSERT... SELECT, которые вставляют нулевые или NULL-значения в столбцы AUTO INCREMENT.
72
Глава 1. Общая информация •
DELETE, если выполняется для таблицы, имеющей внешние ключи со свойством ON DELETE CASCADE.
•
REPLACE. . .SELECT, INSERT IGNORE. . .SELECT, если ВО вставляемых присутствуют дублированные ключи.
данных
Если и только если все эти запросы не содержат конструкцию ORDER BY, гарантируется детерминированный порядок. Например, для INSERT... SELECT без ORDER BY, оператор SELECT может вернуть записи в другом порядке (что может оказаться результатом того, что записи имеют разный ранг и, следовательно, разные номера в столбцах AUTO_INCREMENT), в зависимости от того, как сработают оптимизаторы в исходной и целевой базах при репликации. Запросы могут быть оптимизированы различным образом в двух базах, если: •
Файлы, используемые в запросах, не одинаковы. Например, OPTIMIZE TABLE был запущен для исходных таблиц и не запускался для целевых (для исправления ЭТОГО, начиная С MySQL 4.1.1, OPTIMIZE TABLE, ANALYZE TABLE И REPAIR TABLE записываются в бинарный протокол).
•
Исходная и целевая таблицы обрабатываются разными механизмами хранения (это возможно; например, вы можете использовать InnoDB в исходной реплицируемой базе и My ISAM - в целевой базе, если в ней нет дискового пространства достаточного объема).
•
Размер буферов разный (key__buf f e r _ s i z e и так далее).
•
Исходная и целевая базы работают под управлением разных версий MySQL, и коды оптимизаторов у них отличаются.
Эта проблема может также затронуть восстановление базы с использованием mysqlbinlog|mysql. Наилучший способ избежать этих проблем во всех случаях - добавлять конструкцию ORDER BY к подобным недетерминированным запросам, дабы гарантировать, что строки сохраняются и модифицируются в одном и том же порядке. В будущих версиях MySQL мы будем автоматически добавлять ORDER BY туда, где это необходимо. Следующие проблемы известны и будут решены в надлежащее время: •
Имена файлов протоколов основаны на имени хоста (если только явно не указаны при запуске). На сегодняшний день, если изменяется имя хоста, нужно использовать опции наподобие —log-bin=старое_имя_хоста-Ып. Другой способ состоит в том, чтобы просто переименовать старые файлы в соответствии с изменением имени хоста.
•
mysqlbinlog не удаляет временные файлы, которые остаются после выполнения команды LOAD DATA INFILE.
•
RENAME не работает на временных таблицах и таблицах, используемых в таблицах MERGE.
•
При использовании функции RPAD () в запросах, выполнение которых потребует создания временных таблиц, во всех результирующих строках заключительные пробелы будут удалены. Ниже показан пример такого запроса.
1.8. Соответствие стандартам MySQL
73
SELECT RPAD(tl.columnl, 50, ' ') AS f2, RPAD(t2.column2, 50, ' ') AS fl FROM tablel as t l LEFT JOIN table2 AS t2 ON tl.record=t2.joinID ORDER BY t2.record; Вследствие этой ошибки вы не получите завершающих пробелов в результирующих значениях. Эта проблема также относится ко всем остальным строковым функциям, добавляющим пробелы справа. Причиной является то, что НЕАР-таблицы, которые используются вначале для временных таблиц, не могут работать со столбцами типа VARCHAR. Подобное поведение присуще всем версиям MySQL и будет исправлено в одном из выпусков в рамках серии 4.1. • Из-за способа хранения файла определений таблиц невозможно использовать символ 255 (CHAR (255)) в именах таблиц, столбцов или перечислений. Исправление запланировано в версии 5.1, когда мы будем иметь новый формат файлов определения таблиц. • При использовании SET CHARACTER SET невозможно использовать переведенные символы в именах баз данных, таблиц и столбцов. • Невозможно использовать шаблонные символы '_', '%' вместе с ESCAPE в LIKE... ESCAPE.
• Если есть столбец типа DECIMAL, в котором одно и то же число сохраняется в разных форматах (например, +01.00, 1.00, 01.00), то GROUP BY может рассматривать такие значения как различные. • Невозможно собрать сервер в другом каталоге при использовании потоков MITpthreads. Поскольку для этого нужно изменять потоки MIT-pthreads, по всей видимости, исправлять мы это не будем. • Значения типа BLOB не могут "надежно" применяться в GROUP BY, ORDER BY или DISTINCT. В этих случаях для сравнения значений BLOB используются только первые max_sort_length байт. Значение по умолчанию max_sort_length равно 1024 байта. Это может быть изменено во время запуска сервера. Чтобы обойти это ограничение, в большинстве случаев можно применить подстроки, например: SELECT DISTINCT LEFT {столбец_ЫоЬ, 2048) FROM имя_таблицы • Вычислительные операции выполняются над типами BIGINT и DOUBLE (оба они обычно имеют длину 64 байта). Какую точность вы получите, зависит от функции. Общее правило звучит так: поразрядные функции выполняются с точностью BIGINT, IF и ELT () - с точностью BIGINT или DOUBLE, все остальные - с точностью DOUBLE. Старайтесь избегать применения беззнаковых длинных значений, если они могут оказаться длиной более 63 бит (9223372036854775807) во всех случаях, кроме битовых полей. Версия MySQL 4.0 лучше справляется с BIGINT, чем версия MySQL 3.23. • У всех строковых столбцов, кроме BLOB и TEXT, при извлечении из базы автоматически удаляются завершающие пробелы. Для типа CHAR это нормально. Ошибка состоит в том, что столбцы VARCHAR обрабатываются точно так же. • В одной таблице можно иметь не более 255 столбцов типа ENUM и SET.
74
Глава 1. Общая информация • В MIN (), МАХ () и других агрегатных функциях в настоящее время столбцы типов ENUM и SET сравниваются по их строковым значениям вместо того, чтобы делать это по относительному положению строки в наборе. • mysqld_saf e перенаправляет все сообщения от mysqld в журнал mysqld. Одна связанная с этим проблема состоит в том, что если запустить mysqladmin refresh для закрытия и повторного открытия журнала, стандартный поток вывода stdout и стандартный поток ошибок stderr остаются перенаправленными в старый журнал. Если —log применяется интенсивно, нужно отредактировать mysqld_safe, чтобы он выводил протокол в имя_хоста.еп вместо имя_хоста.log. В этом случае можно легко использовать дисковое пространство, занятое старым журналом, удалив его и запустив mysqladmin refresh. • Оператор UPDATE обновляет столбцы слева направо. Если вы ссылаетесь на обновляемые столбцы, то получаете их новые значения вместо старых. Например, следующий оператор увеличит значение KEY на 2, а не на 1: mysql> UPDATE имя_таблицы
SET KEY=KEY+1,KEY=KEY+1;
• Можно обращаться к множеству временных таблиц в одном запросе, но нельзя обращаться к одной и той же временной таблице более одного раза. Например, приведенный ниже оператор не работает: mysql> SELECT * FROM temp_table, temp_table AS t 2 ; ERROR 1137: Can't reopen table: 'temp_table f (ERROR 1137: Невозможно повторно открыть таблицу: 'temp table') • Оптимизатор может обрабатывать DISTINCT по-разному, когда используются "скрытые" столбцы в объединении и когда они не используются. Скрытые столбцы в объединении считаются частью результата (даже если они не показываются), тогда как в нормальных запросах скрытые столбцы не участвуют в сравнениях для DISTINCT. Возможно, мы исправим это в будущем, чтобы скрытые столбцы никогда не участвовали в вычислении DISTINCT. Ниже представлены соответствующие примеры: SELECT DISTINCT mp3id FROM band_downloads WHERE u s e r i d = 9 ORDER BY id DESC; SELECT DISTINCT band_downloads.mp3id FROM band_downloads,band_mp3 WHERE band_downloads.userid = 9 AND band_mp3.id = band_downloads.mp3id ORDER BY band_downloads.id DESC; Во втором случае сервер MySQL 3.23.x может выдать две идентичные строки в результирующем наборе (поскольку значения скрытого столбца id у них различны). Отметим, что это случается с запросами, где в результате не выводятся столбцы, участвующие в конструкции ORDER BY. Поскольку MySQL позволяет работать с типами таблиц, для которых не поддерживаются транзакции, и поэтому невозможен откат, некоторые вещи работают здесь несколько иначе, чем в других серверах SQL. Это связано только с тем, чтобы гарантировать, что откат никогда не понадобится MySQL для выполнения
1.8. Соответствие стандартам MySQL
75
SQL-операторов. Иногда это может оказаться неудобным, потому что значения столбцов должны проверяться самим приложением, но это дает существенный выигрыш в скорости, так как позволяет MySQL выполнить оптимизацию, которую в противном случае было бы очень трудно реализовать. Если вы устанавливаете некорректное значение столбца, MySQL вместо отката пытается сохранить вместо него "наилучшее возможное" значение. Информацию о том, как это происходит, можно найти в разделе 1.8.6. • Если запускается PROCEDURE на запросе, возвратившем пустой результирующий набор, в некоторых случаях PROCEDURE не трансформирует столбцы. • При создании таблиц типа MERGE не выполняется проверка входящих в них таблиц на предмет соответствия типов. • Если вы используете ALTER TABLE вначале для добавления уникального индекса к таблице, включенной в MERGE, а затем пытаетесь добавить нормальный индекс к MERGE-таблице, порядок ключей будет разным, если существовал старый ключ, который был не уникальным для таблицы. Это происходит ввиду того, что ALTER TABLE помещает уникальные индексы перед нормальными индексами, чтобы как можно раньше обнаружить дублированные ключи. Далее перечислены известные ошибки в ранних версиях MySQL. • В описанных ниже случаях может случиться аварийный отказ ядра. • Обработчик отложенных вставок задерживает вставки в таблицу. • LOCK TABLE С WRITE. •
FLUSH TABLE.
• До версии сервера MySQL 3.23.2 оператор UPDATE, обновляющий значения ключей, упомянутых в конструкции WHERE, мог аварийно завершиться, поскольку ключи используются для поиска записей, и одни и те же строки могли быть найдены по нескольку раз: UPDATE имя_таблицы SET KEY=KEY+1 WHERE KEY > 100; Обходной путь выглядит следующим образом: UPDATE имя_таблицы SET KEY=KEY+1 WHERE KEY+0 > 100; Это работает потому, что сервер MySQL не использует индексы для выражений в КОНСТРУКЦИИ WHERE.
• До версии сервера MySQL 3.23 значения всех числовых типов трактовались как числа с фиксированной запятой. Это означало, что нужно было явно указывать, сколько десятичных знаков должно иметь поле с плавающей запятой. Все результаты возвращались с корректным количеством знаков.
2 Установка MySQL
в
настоящей главе описаны вопросы, связанные с получением и установкой MySQL. 1. Определите, поддерживается ли ваша платформа. Следует иметь в виду, что не все поддерживаемые системы одинаково хороши для выполнения MySQL. На некоторых платформах MySQL работает значительно надежнее, чем на других (см. раздел 2.1.1). 2. Выберите, какой дистрибутив устанавливать. Доступны несколько версий MySQL и большинство доступны в нескольких форматах дистрибутива. Вы можете выбирать между заранее упакованным дистрибутивом, содержащим бинарные (предварительно скомпилированные) программы, и дистрибутивом с исходным кодом. В случае возникновения каких-то сомнений выбирайте бинарный дистрибутив. Мы также предоставляем общий доступ к нашему текущему дереву исходных текстов для тех, кто желает ознакомиться с последними разработками и помочь нам тестировать новый код. Разобраться, какой версии и типу дистрибутива отдать предпочтение, позволит информация, представленная в разделе 2.1.2. 3. Загрузите дистрибутив, который хотите установить. Список сайтов, откуда можно получить MySQL, представлен в разделе 2.1.3. Целостность дистрибутива можно проверить, воспользовавшись инструкциями из раздела 2.1.4. 4. Установите дистрибутив. Для установки MySQL из бинарного дистрибутива воспользуйтесь инструкциями, предложенными в разделе 2.2. В установке MySQL из дистрибутива с исходным кодом или из нашего текущего дерева исходных текстов помогут инструкции в разделе 2.3. Если вы планируете обновить существующую версию MySQL более новой версией, а не выполнять полную установку, обратитесь в раздел 2.5, в котором представлена информация о процедуре обновления и о том, что необходимо сделать перед этим. Если вы столкнулись со сложностями во время установки, в разделе 2.6 находятся рекомендации по решению проблем для конкретных платформ. 5. Выполните необходимые настройки после установки. После установки MySQL почитайте раздел 2.4, в котором содержится важная информация о том, как убедиться, что сервер MySQL работает правильно. Там же описано, как обеспечить защиту начальных пользовательских учетных записей MySQL, которые не имеют паролей до тех пор, пока вы не зададите их явно. Этот раздел касается установки как из бинарного дистрибутива, так и из дистрибутива с исходным кодом. 6. Если вы хотите запустить сценарии, измеряющие производительность MySQL, в системе должна присутствовать поддержка языка Perl (см. раздел 2.7).
2.1. Общие вопросы установки
77
2.1. Общие вопросы установки Перед установкой MySQL потребуется выполнить следующие действия: 1. Определить, работает ли MySQL на вашей платформе. 2. Выбрать дистрибутив для установки. 3. Загрузить дистрибутив и проверить его на предмет целостности. В настоящем разделе представлена информация, которая необходима для выполнения этих шагов. После того, как они будут выполнены, можно приступать к собственно установке выбранного дистрибутива, воспользовавшись дальнейшими инструкциями из этой главы.
2.1.1. Операционные системы, поддерживаемые MySQL Ниже перечислены операционные системы, под управлением которых может выполняться MySQL. Мы пользуемся GNU Autoconf, поэтому существует возможность переноса MySQL на любую современную систему, в которой имеется компилятор C++ и работающая реализация потоков POSIX. (Поддержка потоков необходима для сервера. Для компиляции только клиентского кода единственным условием является наличие компилятора C++.) Мы используем и разрабатываем наше программное обеспечение преимущественно в среде Linux (SuSE и Red Hat), FreeBSD и Sun Solaris (версий 8 и 9). MySQL успешно компилируется на следующих комбинациях операционных систем и пакетов поддержки потоков. Следует иметь в виду, что для многих операционных систем встроенная поддержка потоков присутствует только в их последних версиях. • AIX 4.x, 5.x со встроенной поддержкой потоков. См. раздел 2.6.5.3. • Amiga. • BSDI 2.x с пакетом MIT-threads. См. раздел 2.6.4.5. • BSDI 3.0, 3.1 и 4.x со встроенной поддержкой потоков. См. раздел 2.6.4.5. • • • • • •
DEC UNIX 4.x со встроенной поддержкой потоков. См. раздел 2.6.5.5. FreeBSD 2.x с пакетом MIT-threads. См. раздел 2.6.4.1. FreeBSD 3.x и 4.x со встроенной поддержкой потоков. См. раздел 2.6.4.1. FreeBSD 4.x с поддержкой потоков LinuxThreads. См. раздел 2.6.4.1. HP-UX 10.20 с DCE-потоками из пакета MIT-threads. См. раздел 2.6.5.1. HP-UX 11.x со встроенной поддержкой потоков. См. раздел 2.6.5.2.
• Linux 2.0+ с Linux Threads 0.7.1+ или glibc 2.0.7+. См. раздел 2.6.1. • Mac OS X. См. раздел 2.6.2. • NetBSD 1.3/1.4 Intel и NetBSD 1.3 Alpha (требует наличия GNU make). См. раздел 2.6.4.2. • Novell NetWare 6.0. См. раздел 2.2.4. • OpenBSD > 2.5 со встроенной поддержкой потоков, OpenBSD < 2.5 с пакетом MIT-threads. См. раздел 2.6.4.3. • OS/2 Warp 3, FixPack 29 и OS/2 Warp 4, FixPack 4. См. раздел 2.6.6. • SCO OpenServer с последним портом пакета FSU Pthreads. См. раздел 2.6.5.8.
78
Глава 2. Установка MySQL • SCO UnixWare 7.1.x. См. раздел 2.6.5.9. • SGI Irix 6.x со встроенной поддержкой потоков. См. раздел 2.6.5.7. • Solaris 2.5 и выше со встроенной поддержкой потоков на SPARC и Intel. См. раздел 2.6.3. • SunOS 4.x с пакетом MIT-threads. См. раздел 2.6.3. • Тш64 Unix.
• Windows 9x, Me, NT, 2000 и ХР. См. раздел 2.2.1. Не на всех платформах MySQL работает одинаково хорошо. То, насколько подходит определенная платформа для сильно загруженного, ответственного сервера MySQL, определяется следующими факторами: • Общая стабильность библиотеки поддержки потоков. Платформа может иметь блестящую репутацию во всем остальном, но MySQL будет функционировать на ней лишь настолько стабильно, насколько хороша библиотека поддержки потоков, даже если все остальное работает великолепно. • Способность ядра и библиотеки потоков использовать преимущества симметричных многопроцессорных систем (SMP). Другими словами, когда процесс порождает поток, должна быть возможность выполнять эту поток на другом процессоре, отличном от того, на котором работает оригинальный процесс. • Способность ядра и библиотеки потоков выполнять множество потоков, устанавливающих и сбрасывающих семафоры (mutex) через короткие частые промежутки без чрезмерного переключения контекстов. Если реализация pthread_mutex_lock() будет отнимать слишком много процессорного времени, это катастрофическим образом скажется на работе MySQL. Если не позаботиться об этой проблеме, то добавление дополнительных процессоров только замедлит работу MySQL. • Общая стабильность и производительность файловой системы. • Если в базе данных будут храниться большие таблицы, важное значение имеет способность файловой системы работать с большими файлами вообще и, к тому же, работать с ними эффективно. • Уровень знакомства с платформой специалистов компании MySQL AB. Если мы знаем платформу хорошо, то можем выполнить специфическую для нее оптимизацию и исправления во время компиляции. Мы также сможем дать советы по оптимальной настройке вашей системы для эффективного функционирования MySQL. • Объем проведенного тестирования, выполненного нами для похожих конфигураций. • Количество пользователей, успешно эксплуатирующих сервер MySQL на данной платформе с похожими конфигурациями. Если оно велико, вероятность столкнуться со специфическими для данной платформы сюрпризами значительно меньше. На основании перечисленных критериев наилучшей платформой для работы MySQL на данный момент являются машины на базе процессоров х86, функционирующие под управлением операционной системы SuSE Linux с ядром версии 2.4 и файловой системой ReiserFS (или аналогичной версией Linux), а также SPARC с операционной системой Solaris (2.7-9). Операционная система FreeBDS идет третьей в списке, но мы надеемся, что эта система войдет в категорию наилучших, как только будет усовершенствована ее библиотека потоков. Мы также надеемся, что в какой-то момент мы сможем включить в эту категорию и другие платформы, на которых MySQL сегодня компилиру-
2.1. Общие вопросы установки
79
ется и функционирует достаточно хорошо, однако не с такими показателями стабильности и производительности. Это потребует некоторых усилий с нашей стороны и тесного взаимодействия с разработчиками операционных систем и библиотек компонентов, от которых зависит MySQL. Если вы заинтересованы в усовершенствовании одного из этих компонентов, занимаете должность, позволяющую повлиять на их разработку, и нуждаетесь в более подробных инструкциях относительно того, что нужно для того, чтобы СУБД MySQL функционировала лучше, присылайте предложения по электронной почте в группу рассылки MySQL i t e r n a l s (см. раздел 1.7.1.1). Имейте в виду, что цель приведенных выше сравнений состоит не в том, чтобы сказать, что одна операционная система (ОС) вообще лучше или хуже другой. Речь идет только о выборе ОС для специфической цели - нормальной работы MySQL. Памятуя об этом, результат сравнения будет другим, если учитывать большее число факторов. В некоторых случаях причиной того, что одна ОС оказывается лучше другой, может быть просто то обстоятельство, что у нас есть возможность приложить большие усилия для тестирования и оптимизации нашего продукта на конкретной платформе. Здесь мы просто делимся своим опытом, чтобы помочь вам принять решение, какую платформу использовать для внедрения MySQL.
2.1.2. Выбор дистрибутива MySQL для установки Во время подготовки к установке MySQL вы должны решить, какую версию выбрать для использования. Разработка MySQL идет по нескольким сериям выпусков, и вы можете выбрать тот, который в большей степени удовлетворяет ваши требования. После принятия решения о том, какую версию устанавливать, необходимо выбрать формат дистрибутива. Выпуски доступны в бинарном формате или в виде исходного кода.
2.1.2.1. Выбор версии MySQL для установки Первое решение, которое должно быть принято, связано с тем, какой выпуск нужен: производственный (стабильный) или же находящийся в стадии разработки. В процессе разработки MySQL сосуществуют несколько серий выпусков, пребывающих в разной степени готовности: •
MySQL 5.0 - новейшая серия выпусков, находящаяся в стадии очень активной разработки новых средств. Вплоть до последних дней она была доступна (в предварительной форме) в репозитории исходных текстов BitKeeper. Ранний альфавыпуск был представлен для широкого тестирования.
•
MySQL 4.1 - серия выпусков, находящаяся в разработке, к которой были добавлены важные новые средства. В настоящее время находится в стадии бетатестирования. Исходные тексты и бинарные дистрибутивы доступны для использования и тестирования в системах разработки.
•
MySQL 4.0 - текущая стабильная производственная серия выпусков. Новые выпуски выходят с исправлениями ошибок. Никаких новых средств, которые способны нарушить стабильность кода, не добавляется.
•
MySQL 3.23 - старая стабильная производственная серия выпусков. Данная серия закрывается, поэтому новые выпуски издаются только для исправления критических ошибок.
Мы не верим в полное замораживание работ, поскольку это означает также прекращение исправлений ошибок и отказ от вещей, которые "должны быть сделаны". "Час-
80
Глава 2. Установка MySQL
тично замороженное состояние" означает, что мы можем внести какие-то мелкие изменения, которые "почти наверняка не повлияют на то, что уже работает". Естественно, исправления существенных ошибок в ранних версиях распространяются и на более поздние серии продукта. Как правило, если вы только впервые начинаете использовать MySQL или пытаетесь перенести его в систему, для которой не существует бинарного дистрибутива, мы рекомендуем обратиться к серии производственных выпусков. В настоящее время это MySQL 4.0. Все выпуски MySQL, даже те, что относятся к сериям, пребывающим в разработке, до выхода в свет обязательно проверяются с помощью тестов производительности. Если вы эксплуатируете старую систему и хотите произвести обновление, но желаете, чтобы этот процесс прошел как можно более безболезненно, вам стоит обновить ее до последнего выпуска той серии, к которой относится и ваша система (следует обращать внимание на последнюю часть номера версии выпуска). Мы стараемся исправлять только критические ошибки и вносить небольшие, относительно безопасные изменения в эту версию. Если вы хотите использовать новые средства, которые еще не входят в выпуски производственной серии, можете взять версию из серии, находящейся на стадии разработки. Но при этом нужно помнить, что такие выпуски не настолько стабильны, как производственные. Если вы хотите иметь самые последние исходные тексты, которые содержат все текущие исправления, можете воспользоваться одним из наших репозиториев исходного кода BitKeeper. Это еще не будет выпуском в полном смысле, однако даст предварительное представление о коде, на котором будут базироваться будущие выпуски. Схема именования выпусков, принятая в MySQL, состоит из трех номеров и суффикса, например, mysql-4.1.2-alpha. Цифры в наименовании выпуска интерпретируются следующим образом: • Первое число (4) обозначает номер главной версии и также описывает формат файлов. Все выпуски версии 4 используют один и тот же формат файлов. • Второй номер (1) - это уровень выпуска. Взятые вместе номер главной версии и уровень выпуска составляют номер серии выпуска. • Третий номер (2) - это номер версии в серии выпусков. Эта цифра увеличивается с каждым новым выпуском. Обычно вам нужна самая последняя версия из выбранной серии. С каждым небольшим обновлением последний номер версии увеличивается. Когда добавляются существенные новые средства либо появляется малейшая несовместимость с предыдущими версиями, увеличивается второй номер. Когда меняется формат файлов, увеличивается первый номер. Наименование выпуска включает также суффикс, указывающий на уровень его стабильности. Имена выпусков в серии проходят через последовательность суффиксов, отражающих рост уровня стабильности. Ниже описаны возможные суффиксы. •
alpha (альфа) означает, что выпуск содержит некоторую крупную часть нового кода, который пока еще не был на 100% протестирован. Известные ошибки (обычно их еще нет) должны быть документированы в разделе новостей (News) онлайнового справочного руководства по адресу http://dev.mysql.com/doc/mysql/en/News.html. В большинстве альфа-выпусков появляются новые команды и расширения. Активная разработка, которая может включать изменения в основном коде, может осу-
2.1. Общие вопросы установки
81
ществляться в рамках альфа-выпуска, но все должно быть протестировано перед его изданием. По этой причине не должно быть никаких известных ошибок в любом выпуске MySQL. • beta (бета) означает, что весь новый код протестирован. Никаких существенных новых средств, которые могут повредить старому коду, не добавляется. Не должно существовать известных ошибок. Переход от альфа- к бета-выпуску происходит в случае, если документированных критических ошибок в альфа-версии не появлялось в течение, минимум, месяца, а также не планируется добавление новых средств, которые могли бы сделать любые старые команды ненадежными. • gamma (гамма) - это бета-версия, которая находится в эксплуатации достаточно долго и выглядит хорошо работающей. Были добавлены только минимальные исправления. Это то, что многие другие компании называют выпуском. • Если нет никакого суффикса, это означает, что версия эксплуатируется долго на многих различных сайтах без сообщений об ошибках, за исключением тех, которые зависят от платформы. В таком выпуске исправляются только критические ошибки. Это то, что мы называем производственным (стабильным) выпуском. MySQL использует схему наименований, которая несколько отличается от принятой в большинстве других продуктов. Вообще можно считать относительно безопасным использование любой версии, которая существует много недель без замены на новую в рамках той же серии выпусков. Все выпуски MySQL проходят испытания на производительность и тестирование, чтобы гарантировать их относительную безопасность в эксплуатации. Поскольку стандартные тесты со временем расширяются, чтобы покрыть все ранее найденные ошибки, наш тестовый набор становится со временем все лучше и лучше. Все выпуски тестируются, как минимум, с помощью следующих средств: • Внутренний тестовый набор. В каталоге mysql-test хранится обширный набор тестовых случаев. Мы прогоняем эти тесты для каждого бинарного дистрибутива сервера. • Набор тестов производительности. Этот набор выполняет множество общих запросов. Данные тесты служат также для проверки того, что последняя серия оптимизаций действительно делает код более быстрым (см. раздел 6.1.4). • Тест crash-me. Этот тест пытается определить, какие средства СУБД поддерживает и какие у нее есть возможности и ограничения (см. раздел 6.1.4). Еще одно тестирование, которое мы проводим, - это эксплуатация новейшей версии MySQL в нашей внутренней производственной среде, по крайней мере, на одной машине. Мы располагаем более чем 100 Гбайт данных, которые и задействуем во время тестирования.
2.1.2.2. Выбор формата дистрибутива После выбора версии MySQL для установки потребуется решить, какой дистрибутив использовать: бинарный или с исходным кодом. В большинстве случаев имеет смысл выбирать бинарный дистрибутив, если только он существует для вашей платформы. Бинарные дистрибутивы доступны в собственных форматах для многих платформ, например, в виде RPM-файлов для Linux или пакетных инсталляторов DMG для Mac OS X. Дистрибутивы также имеются в форме Zip-архивов и сжатых файлов tar. На выбор бинарного дистрибутива влияют следующие причины:
82
Глава 2. Установка MySQL •
Как правило, бинарные дистрибутивы проще устанавливать, чем исходные.
•
Для того чтобы удовлетворить различные требования пользователей, мы предоставляем две разных бинарных версии: одна скомпилирована с нетранзакционными механизмами хранения (небольшая и быстрая), а другая сконфигурирована с наиболее важными расширенными средствами, такими как безопасные транзакционные таблицы. Обе версии скомпилированы из одного исходного дистрибутива. Все собственные клиенты MySQL могут подключаться к серверам обеих версий. Расширенный бинарный дистрибутив MySQL отмечен суффиксом -шах и сконфигурирован с теми де опциями, что mysqld-max. См. раздел 4.1.2. Если вы хотите использовать RPM-модуль MySQL-Max, то сначала должны установить стандартный RPM-модуль MySQL-server.
Существуют и причины, по которым, возможно, лучше устанавливать MySQL с исходного дистрибутива: •
Требуется установить MySQL в некотором определенном окружении. Стандартные бинарные дистрибутивы готовы к запуску в любом месте, но вам может понадобиться большая гибкость в размещении компонентов MySQL там, где вы хотите.
•
Требуется сконфигурировать mysqld с некоторыми дополнительными средствами, которые не включены в состав стандартных бинарных дистрибутивов. Ниже перечислены некоторые общие дополнительные опции, которыми вы, возможно, воспользуетесь: --with-innodb (опция по умолчанию для MySQL 4.0 и выше) --with-berkleydb (доступна не на всех платформах) —with-raid —with-libwrap —with-names-z-libs (это сделано в некоторых бинарных дистрибутивах) —with-debug[=full]
•
Требуется настроить mysqld без некоторых средств, которые входят в состав стандартных бинарных дистрибутивов. Например, дистрибутивы обычно компилируются с поддержкой всех символьных наборов. Если вам нужен более компактный сервер MySQL, вы можете перекомпилировать его для работы только с необходимым набором символов.
•
У вас есть специальный компилятор (такой, например, как рдсс), либо вы хотите использовать опции компилятора, которые позволяют получить лучше оптимизированный для вашего процессора код. Бинарные дистрибутивы скомпилированы с опциями, которые позволяют им работать на различных процессорах из одного семейства.
•
Вы хотите использовать самые последние исходные тексты из нашего репозитория BitKeeper, чтобы получить код со всеми последними исправлениями ошибок. Например, если вы обнаружили ошибку и сообщили о ней группе разработчиков MySQL, ее исправление будет внесено в репозиторий исходных текстов, и вы сможете получить его оттуда. Исправление ошибок не включается в выпуск до его официального выхода.
2.1. Общие вопросы установки
83
• Вы хотите изучить (или изменить) исходный код MySQL на С и C++. Для этой цели потребуется получить исходный дистрибутив, поскольку исходный код - это первичное и наиболее исчерпывающее руководство. • Исходные дистрибутивы содержат больше тестов и примеров, чем бинарные. 2.1.2.3. Как и когда выходят изменения MySQL развивается достаточно быстро в MySQL AB, и мы хотим поделиться новыми разработками с другими пользователями MySQL. Мы стараемся издавать новые выпуски, когда у нас появляются какие-то новые полезные средства, которые могут понадобиться многим. Мы также стремимся помогать пользователям, запрашивающим у нас средства, которые легко реализовать. Мы отмечаем, что хотят иметь наши зарегистрированные пользователи, и особо отмечаем, чего хотят пользователи, поддерживаемые нами по электронной почте. Мы стараемся помочь им всем. Не нужно постоянно загружать новые выпуски. Раздел новостей (News) нашего онлайнового руководства предлагает информацию о том, содержит ли новый выпуск то, что вам нужно. См. http://dev.mysql.com/doc/mysql/en/News.html. При внесении изменений в MySQL мы придерживаемся следующей политики: • Выпуски выходят в каждой серии. Номер каждого выпуска - последнее число в номере версии - на единицу больше, чем у предыдущего выпуска той же серии. • Производственные (стабильные) выпуски появляются 1-2 раза в год. Однако если найдены небольшие ошибки, издается выпуск только с исправлениями ошибок. • Рабочие выпуски и/или исправления к старым выпускам появляются каждые 4-8 недель. • Бинарные дистрибутивы для различных платформ мы издаем для основных выпусков. Другие люди могут создавать бинарные дистрибутивы для других систем, но вероятно, не так часто. • Мы делаем исправления доступными сразу, как только идентифицируем и исправляем маленькие или некритичные, однако ощутимые ошибки. Исправления доступны немедленно через наши репозитории BitKeeper и включаются в следующий выпуск. • В любом случае, если в выпуске обнаружена критическая ошибка, мы издаем новый выпуск сколь возможно скоро. (Как бы хотелось, чтобы и другие компании поступали так же!)
2.1.2.4. Философия выпусков — ни одной известной ошибки! Мы тратим значительное время и усилия, чтобы сделать наши выпуски свободными от ошибок. Мы не выпускаем промежуточных версий MySQL с какими-либо известными "критическими" повторяющимися ошибками (Под "критической" ошибкой понимается то, что приводит к аварийному завершению MySQL в условиях нормальной эксплуатации, либо выдает неверные ответы на нормальные запросы, либо порождает проблемы, связанные с безопасностью.) Мы документируем все обнаруженные проблемы, ошибки и последствия проектных решений (см. раздел 1.8.7). Наша цель - исправить все, что можно исправить без риска нарушения стабильности версии MySQL. В определенных случаях это означает, что мы можем вносить исправле-
84
Глава 2. Установка MySQL
ния в версию, находящуюся в процессе разработки, но не в стабильную (производственную) версию. Естественно, подобного рода вещи тщательно документируются, дабы пользователи знали о них. Ниже представлено описание принятого у нас процесса сборки приложений. • Мы отслеживаем информацию об ошибках в списках поддержки пользователей, базе ошибок на http://bugs.mysql.com/ и во внешних списках рассылок, посвященных MySQL. • Все отчеты об ошибках текущей версии помещаются в базу данных ошибок. • Когда мы исправляем ошибку, то всегда стараемся создать для нее тестовый случай, который затем помещаем в нашу систему тестов, дабы гарантировать, что эта ошибка никогда не проявится вновь без того, чтобы быть обнаруженной. (Около 90% исправленных ошибок имеют такие тестовые случаи.) • Мы создаем тестовые случаи для всех новых средств, добавленных в MySQL. • Прежде чем начать сборку нового выпуска MySQL, мы убеждаемся, что все документированные повторяемые ошибки в версиях MySQL (3.23.x, 4.0.x и так далее) исправлены. Если что-то исправить невозможно (по причинам каких-то внутренних проектных решений в MySQL), мы соответствующим образом документируем это в руководстве. См. раздел 1.8.7. • Мы создаем сборку на всех платформах, для которых поддерживаем бинарные дистрибутивы (свыше 15 платформ) и запускаем на каждой их них существующие тестовые наборы. • Мы не издаем бинарных дистрибутивов для тех платформ, для которых тесты не проходят. Если проблема вызвана ошибкой в исходных текстах, мы исправляем ее и проводим сборку заново, а также тестируем все системы с нуля. • Процесс сборки и тестирования занимает 2-3 дня. Если мы получаем сообщение о критической ошибке в течение этого периода, мы исправляем ее и начинаем процесс сборки заново. • После публикации бинарных дистрибутивов на http://dev.mysql.com мы рассылаем уведомления об этом через списки рассылки mysql и announce (см. раздел 1.7.1.1). Уведомление включает список всех изменений в выпуске и всех известных проблем. • Чтобы предоставить быстрый доступ нашим пользователям к самым последним средствам MySQL, мы издаем новые выпуски каждые 4-8 недель. Снимки исходных текстов готовятся ежедневно и доступны по адресу: http://downloads.mysql.com/snapshots.php • Если, несмотря на все наши усилия, мы получаем сообщение об ошибке после того, как выпуск готов, значит, что-то не так со сборкой для конкретной платформы; мы сразу исправляем ее и собираем новый выпуск ' а' для этой платформы. Благодаря нашей огромной базе данных, проблемы обнаруживаются достаточно быстро. • Наша хронология создания качественных выпусков достаточно убедительна. За последние 150 выпусков нам пришлось делать новые сборки меньше, чем для 10. В трех случаях ошибка была вызвана библиотекой glibc и в одном - отказом машины, которая служила нам долгое время верой и правдой.
2.1. Общие вопросы установки
85
2.1.2.5. Бинарные дистрибутивы MySQL, скомпилированные в MySQL АВ В качестве одной из услуг компания MySQL АВ предоставляет пользователям набор бинарных дистрибутивов, скомпилированных на собственных системах компании или на системах, которые принадлежат людям, поддерживающим нас и любезно предоставляющим доступ к своим машинам. В дополнение к бинарным сборкам, поставляемым в формате пакетов, специфичных для отдельных платформ, для множества платформ мы предлагаем бинарные дистрибутивы в виде сжатых файлов t a r (файлов . t a r . g z ) . Более подробная информация доступна в разделе 2.2. Эти дистрибутивы генерируются с помощью сценария Build-tools/Do-compile, который компилирует исходный код и затем создает бинарный архив tar.gz, используя scripts/make_binary_distribution. Упомянутые дистрибутивы сконфигурированы и собраны с использованием перечисленных ниже опций и компиляторов. Ту же информацию можно получить, взглянув на переменные COMP_ENV_INFO и CONFIGURE_LINE внутри сценария bin/mysqlbug, входящего в каждый tar-файл дистрибутива. Следующие бинарные дистрибутивы собираются на системах для разработки MySQL АВ: • Linux 2.4.хх х86 с компилятором дсс 2.95.3: CFLAGS="-O2 -mcpu=pentiumpro" CXX=gcc CXXFLAGS="-O2 -mcpu=pentiumpro -felideconstructors" ./configure —prefix=/usr/local/mysql —with-extra-charsets=complex —enable-thread-safe-client —enable-local-infile —enable-assembler —disable-shared —with-client-ldflags=-all-static —with-mysqld-ldflags=-allstatic • Linux 2.4.xx Intel Itanium 2 с компилятором есс (Intel C++ Itanium Compiler 7.0): CC=ecc CFLAGS="-02 -tpp2 -ip -nolib_inline" CXX=ecc CXXFLAGS= "-02 -tpp2 -ip -nolib_inline" ./configure —prefix=/usr/local/mysql —with-extra-charsets=complex —enable-thread-safe-client —enable-local-infile • Linux 2.4.xx Intel Itanium с компилятором есс (Intel C++ Itanium Compiler 7.0): CC=ecc CFLAGS=-tppl CXX=ecc CXXFLAGS=-tppl ./configure —-prefix* /usr/local/mysql —with-extra-charsets=complex —enable-thread-safeclient —enable-local-infile •
Linux 2.4.xx alpha с компилятором ссс (Compaq С V6.2-505 / Compaq C + + V6.3-006): CC=ccc CFLAGS="-fast -arch generic" CXX=cxx CXXFLAGS="-fast -arch generic -noexceptions -nortti" ./configure —prefix=/usr/local/mysql —with-extracharsets=complex —enable-thread-safe-client —enable-local-infile —withmysqld-ldflags=-non_shared —with-client-ldflags=-non_shared —disable-shared
• Linux 2.x.xx ppc с компилятором дсс 2.95.4: CC=gcc CFLAGS="-03 -fno-omit-frame-pointer" CXX=gcc CXXFLAGS= "-03 -fno-omitframe-pointer -felide-constructors -fno-exceptions -fno-rtti" ./configure —prefix=/usr/local/mysql —localstatedir= /usr/local/mysql/data —libexecdir=/usr/local/mysql/bin —with-extra-charsets=complex —enable-threadsafe-client —enable-local-infile —disable-shared —with-embedded-server —with-innodb
86
Глава 2. Установка MySQL • Linux 2.4.хх s390 с компилятором gcc 2.95.3: CFLAGS=n-O2" CXX=gcc CXXFLAGS="-O2 -felide-constructors" ./configure —prefix=/usr/local/mysql —with-extra-charsets=complex —enable-thread-safe-client —enable-local-infile —disable-shared —with-client-ldflags=-all-static —with-mysqld-ldflags=-all-static • Linux 2.4.xx x86_64 (AMD64) с компилятором gcc 3.2.1: CXX=gcc ./configure —prefix=/usr/local/mysql —with-extra-charsets= complex —enable-thread-safe-client —enable-local-infile —disable-shared • Sun Solaris 8 x86 с компилятором gcc 3.2.3: CC=gcc CFLAGS="-O3 -fno-omit-frame-pointer" CXX=gcc CXXFLAGS="-O3 -fno-oraitframe-pointer -felide-constructors -fno-exceptions -fno-rtti" ./configure —prefix=/usr/local/mysql —localstatedir= /usr/local/mysql/data —libexecdir=/usr/local/mysql/bin —with-extra-charsets=complex —enablethread-safe-client —enable-local-infile —disable-shared —with-innodb • Sun Solaris 8 SPARC с компилятором gcc 3.2: COgcc CFLAGS="-O3 -fno-omit-frame-pointer" CXX=gcc CXXFLAGS="-O3 -fno-omitframe-pointer -felide-constructors -fno-exceptions - f n o - r t t i " ./configure —prefix=/usr/local/mysql —with-extra-charsets=complex —enable-thread-safeclient —enable-local-infile —enable-assembler —with-named-z-libs=no —withnamed-curses-libs=-lcurses —disable-shared • Sun Solaris 8 SPARC 64-bit с компилятором gcc 3.2: CC=gcc CFLAGS="-O3 -m64 -fno-omit-frame-pointer" CXX=gcc CXXFLAGS="-O3 -m64 -fno-omit-frame-pointer -felide-constructors -fno-exceptions - f n o - r t t i " ./configure —prefix=/usr/local/mysql —with-extra-charsets= complex —enable-threadsafe-client —enable-local-infile —with-named-z-libs=no —with-named-curseslibs=-lcurses —disable-shared • Sun Solaris 9 SPARC с компилятором gcc 2.95.3: COgcc CFLAGS="-O3 -fno-omit-frame-pointer" CXX=gcc CXXFLAGS="-O3 -fno-omitframe-pointer -felide-constructors -fno-exceptions - f n o - r t t i " ./configure —prefix=/usr/local/mysql —with-extra-charsets=complex —enable-thread-safeclient —enable-local-infile —enable-assembler —with-named-curses-libs=-lcurses —disable-shared • Sun Solaris 9 SPARC с компилятором ее-5.0 (Sun Forte 5.0): CC=cc-5.0 CXX=CC ASFLAGS="-xarch=v9" CFLAGS="-Xa -xstrconst -mt -D_FORTEC_ -xarch=v9" CXXFLAGS="-noex -mt -D_FORTEC_ -xarch=v9" ./configure —prefix=/usr/local/mysql —with-extra-charsets=complex —enable-thread-safeclient —enable-local-infile —enable-assembler —with-named-z-libs=no—enable-thread-safe-client —disable-shared • IBM AIX 4.3.2 ppc с компилятором gcc 3.2.3: CFLAGS="-O2 -mcpu=powerpc -Wa,-many " CXX=gcc CXXFLAGS="-O2 -mcpu= powerpc -Wa,-many -felide-constructors -fno-exceptions - f n o - r t t i " ./configure —prefix=/usr/local/mysql —with-extra-charsets=complex —enable-thread-safeclient —enable-local-infile —with-named-z-libs= no —disable-shared
2.1. Общие вопросы установки
87
• IBM AIX 4.3.3 ррс с компилятором xlC_r (IBM Visual Age C/C++ 6.0): CC=xlc_r CFLAGS="-ma -02 -qstrict -qoptimize=2 -qmaxmem=8192" CXX=xlC_r CXXFLAGS ="-ma -02 -qstrict -qoptimize=2 -maxmem=8192" ./configure —prefix=/usr/local/mysql —localstatedir=/usr/local/mysql/data —libexecdir=/usr/local/mysql/bin —with-extra-charsets=complex —enablethread-safe-client —enable-local-infile —with-named-z-libs= no -disableshared —with-innodb • I B M A I X 5.1.0 ррс с компилятором gcc 3.3: CFLAGS="-02 -mcpu=powerpc -Wa,-many" CXX=gcc CXXFLAGS="-02 -mcpu= powerpc -Wa, -many -felide-constructors -fno-exceptions -fno-rtti" ./configure —prefix=/usr/local/mysql —with-extra-charsets=complex —enable-thread-safeelient —enable-local-infile —with-named-z-libs= no —disable-shared • I B M A I X 5.2.0 ррс с компилятором x l C r (IBM Visual Age C/C++ 6.0): CC=xlc_r CFLAGS="-ma -02 -qstrict -qoptimize=2 -qmaxmem=8192" CXX=xlC_r CXXFLAGS="-ma -02 -qstrict -qoptimize=2 -qmaxmem=8192" ./configure —prefix=/usr/local/mysql —localstatedir=/usr/local/mysql/data —libexecdir=/usr/local/mysql/bin —with-extra-charsets=complex —enablethread-safe-client —enable-local-infile —with-named-z-libs= no -disableshared —with-embedded-server —with-innodb • H P - U X 10.20 pa-riscl.l с компилятором gcc 3.1: CFLAGS="-DHPUX -I/opt/dce/include -03 -fPIC" CXX=gcc CXXFLAGS= "-DHPUX -I/opt/dce /include -felide-constructors -fno-exceptions -fno-rtti -03 -fPIC" ./configure —prefix=/usr/local/mysql —with-extra-charsets=complex —enablethread-safe-client —enable-local-infile —with-pthread —with-named-threadlibs= -Idee —with-lib-ccflags=-fPIC —disable-shared • H P - U X 11.00 pa-risc с компилятором aCC (HP ANSI C + + B3910B A.03.50): CC=cc CXX=aCC CFLAGS=+DAportable CXXFLAGS=+DAportable ./configure —prefix=/usr/local/mysql —localstatedir=/usr/local/mysql/data —libexecdir=/usr/local/mysql/bin —with-extra-charsets=complex —enablethread-safe-client —enable-local-infile —disable-shared —with-embeddedserver —with-innodb • H P - U X 11.11 pa-risc2.0 64bit с компилятором aCC (HP A N S I C + + B3910B A.03.33): CC=cc CXX=aCC CFLAGS=+DD64 CXXFLAGS=+DD64 ./configure —prefix=/usr/local/mysql —with-extra-charsets=complex —enable-thread-safe-client —enable-local-infile —disable-shared • H P - U X 11.11 pa-risc2.0 32bit с компилятором aCC (HP ANSI C + + B3910B A.03.33): CC=cc CXX=aCC CFLAGS="+DAportable" CXXFLAGS=ll+DAportable" ./configure —prefix=/usr/local/mysql —localstatedir=/usr/local/mysql/data —libexecdir=/usr/local/mysql/bin —with-extra-charsets=complex —enable-threadsafe- client —enable-local-infile —disable-shared —with-innodb • H P - U X 11.22 ia64 64bit с компилятором aCC (HP aC++/ANSI С В3910В A.05.50):
88
Глава 2. Установка MySQL СС=сс СХХ=аСС CFLAGS="+DD64 +DSitanium2" CXXFLAGS="+DD64 +DSitanium2" ./configure —prefix=/usr/local/mysql —localstatedir=/usr/local/mysql/data —libexecdir=/usr/local/mysql/bin —with-extra-charsets=complex --enablethread-safe-client —enable-local-infile —disable-shared —with-embeddedserver —with-innodb • Apple Mac OS X 10.2 powerpc с компилятором gcc 3.1: CC=gcc CFLAGS="-O3 -fno-omit-frame-pointer" CXX=gcc CXXFLAGS="-O3 -fno-omitframe-pointer -felide-constructors -fno-exceptions - f n o - r t t i " ./configure —prefix=/usr/local/mysql —with-extra-charsets=complex —enable-thread-safeclient —enable-local-infile —disable-shared • FreeBSD 4.7 i386 с компилятором gcc 2.95.4: CFLAGS=-DHAVE_BROKEN_REALPATH ./configure —prefix=/usr/local/mysql —withextra-charsets=complex —enable-thread-safe-client —enable-local-infile —enable-assembler —with-named-z-libs=not-used —disable-shared • FreeBSD 4.7 i386 using LinuxThreads с компилятором gcc 2.95.4: CFLAGS="-DHAVE_BROKEN_REALPATH -D_USE_UNIX98 -D_REENTRANT -D_THREAD_SAFE - I / u s r / l o c a l / i n c l u d e / p t h r e a d / l i n u x t h r e a d s " CXXFLAGS= M
-DHAVE_BROKEN_REALPATH -D
USEJJNIX98 -D_REENTRANT -D_THREAD_SAFE
-I/usr/local/include/pthread/linuxthreads" ./configure —prefix= /usr/local/mysql —localstatedir=/usr/local/mysql/data —libexecdir= /usr/local/mysql/bin —enablethread-safe-client —enable-local-infile —enable-assembler —with-namedthread-libs= M
-DHAVE_GLIBC2_STYLE_GETHOSTBYNAME_R
-D_THREAD_SAFE - I
/usr/local/include/pthread/linuxthreads -L/usr/local/lib -11thread -llgcc_r" —disable-shared —with-embedded-server —with-innodb • QNX Neutrino 6.2.1 i386 с компилятором gcc 2.95.3qnx-nto 20010315: CC=gcc CFLAGS="-O3 -fno-omit-frame-pointer" CXX=gcc CXXFLAGS="-O3 -fno-omitframe-pointer -felide-constructors -fno-exceptions - f n o - r t t i " ./configure —prefix=/usr/local/mysql —with-extra-charsets=complex —enable-thread-safeclient —enable-local-infile —disable-shared Следующие бинарные сборки готовятся на системах, любезно предоставляемых нашими пользователями. Компания MySQL AB не имеет полного контроля над этими системами, поэтому мы можем предоставлять только ограниченную поддержку дистрибутивам, собранным на них. •
SCO Unix 3.2v5.0.6 i386 с компилятором gcc 2.95.3: CFLAGS="-O3 -mpentium" LDFLAGS=-static CXX=gcc CXXFLAGS="-O3 -mpentium -felideconstructors" ./configure —prefix=/usr/local/mysql —with-extra-charsets=complex —enable-thread-safe-client —enable-local-infile —with-named-z-libs=no —enable-thread-safe-client —disable-shared
•
SCO OpenUnix 8.0.0 i386 с компилятором СС 3.2: CC=cc CFLAGS="-O" CXX=CC ./configure —prefix=/usr/local/mysql —with-extracharsets=complex —enable-thread-safe-client —enable-local-infile —withnamed-z-libs=no —enable-thread-safe-client —disable-shared
2.1. Общие вопросы установки
89
• Compaq Tru64 OSF/1 V5.1 732 alpha с компилятором сс/схх (Compaq С V6.3-029i / DIGITAL C++V6.1-027): CC="cc -pthread" CFLAGS="-04 -ansi_alias -ansi_args -fast -inline speed -speculate a l l " CXX="cxx -pthread" CXXFLAGS="-O4 -ansi_alias -fast -inline speed -speculate a l l -noexceptions -nortti" ./configure —prefix=/usr/local/mysql —with-extra-charsets=complex —enable-thread-safe-client —enable-local-infile —with-prefix= /usr/local/mysql —with-named-thread-libs="-lpthread -lmach -lexc - l c " —disable-shared —with-mysqld-ldflags=-all-static • SGI Irix 6.5 IP32 с компилятором gcc 3.0.1: CC=gcc CFLAGS="-O3 -fno-omit-frame-pointer" CXXFLAGS="-O3 -fno-omit-framepointer -felide-constructors -fno-exceptions -fno-rtti" ./configure —prefix=/usr/local/mysql —with-extra-charsets=complex —enable-thread-safeclient —enable-local-infile —disable-shared • FreeBSD/sparc64 5.0 с компилятором gcc 3.2.1: CFLAGS=-DHAVEJ3ROKEN_REALPATH ./configure —prefix=/usr/local/mysql —localstatedir=/usr/local/mysql/data —libexecdir=/usr/local/mysql/bin —with-extracharsets=complex —enable-thread-safe-client —enable-local-infile -disableshared —with-innodb Следующие опции компиляции использовались компанией MySQL AB для сборки бинарных пакетов в прошлом. Эти бинарные пакеты больше не обновляются, тем не менее, мы приводим опции компиляторов в справочных целях. • Linux 2.2.хх SPARC с компилятором egcs 1.1.2: CC=gcc CFLAGS="-03 -fno-omit-frame-pointer" CXX=gcc CXXFLAGS="-O3 -fno-omitframe-pointer -felide-constructors -fno-exceptions -fno-rtti" ./configure —prefix=/usr/local/mysql —with-extra-charsets=complex —enable-thread-safeclient —enable-local-infile —enable-assembler —disable-shared • Linux 2.2.x with x686 с компилятором gcc 2.95.2: CFLAGS="-03 -mpentiumpro" CXX=gcc CXXFLAGS="-03 -mpentiumpro -felideconstructors -fno-exceptions -fno-rtti" ./configure —prefix=/usr/local/mysql —enable-assembler —with-mysqld-ldflags= - a l l - s t a t i c —disable-shared —withextra-charsets=complex • SunOS 4.1.4 2 sun4c с компилятором gcc 2.7.2.1 : CC=gcc CXX=gcc CXXFLAGS="-03 -felide-constructors" ./configure —prefix= /usr/local/mysql —disable-shared —with-extra-charsets=complex —enable-assembler • SunOS 5.5.1 (и предшествующие версии) sun4u с компилятором egcs 1.0.3а или 2.90.27, либо gcc 2.95.2 и более новой версии: CC=gcc CFLAGS="-03" CXX=gcc CXXFLAGS="-O3 -felide-constructors -fno-exceptions -fno-rtti" ./configure —prefix=/usr/local/mysql —with-low-memory —withextra-charsets=complex —enable-assembler • SunOS 5.6 i86pc с компилятором gcc 2.8.1:
90
Глава 2. Установка MySQL CC=gcc CXX=gcc CXXFLAGS=-O3 ./configure —prefix=/usr/local/mysql —with-lowmemory —with-extra-charsets=complex • BSDI BSD/OS 3.1 i386 с компилятором gcc 2.7.2.1: CC=gcc CXX=gcc CXXFLAGS=-0 ./configure ~prefix=/usr/local/mysql —with-extracharsets=complex • BSDI BSD/OS 2.1 i386 с компилятором gcc 2.7.2: CC=gcc CXX=gcc CXXFLAGS=-O3 ./configure —prefix=/usr/local/mysql —with-extracharsets=complex • AIX 2 4 c компилятором gcc 2.7.2.2: CC=gcc CXX=gcc CXXFLAGS=-O3 ./configure —prefix=/usr/local/mysql —with-extracharsets=complex
Любой, кому известны более оптимальные наборы опций для конфигурации компиляторов из приведенных выше перечней, может прислать их в список рассылки MySQL internals (см. раздел 1.7.1.1). Дистрибутивы в формате RPM до версии MySQL 3.22 предоставлены пользователями. Начиная с MySQL 3.22, дистрибутивы RPM генерируются специалистами компании MySQL AB. Если нужно собрать отладочную версию MySQL, добавьте опцию --with-debug или —with-debug=full к приведенным выше строкам конфигурации и удалите опции
-fomit-frame-pointer.
2.1.3. Как получить MySQL Получить информацию о текущей версии, а также инструкции по загрузке можно на домашней странице MySQL по адресу http://www.mysql.com/. Главный зеркальный сайт доступен по адресу h t t p : //mirrors. sunsite.dk/mysql/. Полный список зеркальных сайтов, на которых можно получить MySQL, находится по адресу http://dev.mysql.com/downloads/mirrors.html. Там же приводится информация о том, как добавить собственный зеркальный сайт MySQL и куда сообщать о недействительных зеркальных сайтах.
2.1.4. Проверка целостности пакета с помощью контрольных сумм MD5 или GnuPG После загрузки подходящего пакета MySQL и до его установки потребуется убедиться в его целостности, аутентичности и действительности. Компания MySQL AB предлагает три способа проверки целостности: • Контрольные суммы MD5. • Криптографические подписи с использованием системы защиты конфиденциальности GnuPG (GNU Privacy Guard). • Встроенный механизм верификации для RPM-пакетов. В приведенных ниже разделах эти методы описываются более подробно. Если обнаруживается, что контрольная сумма MD5 или GPG-подписи не совпадают, первым делом нужно попытаться загрузить соответствующий пакет еще раз, возможно, с другого зеркального сайта. Если повторная проверка целостности пакета ока-
2.1. Общие вопросы установки
91
зывается снова неудачной, известите нас об этом инциденте по электронной почте
[email protected] или
[email protected], включив в сообщение полное наименование пакета и адрес сайта, откуда он был загружен. Не используйте для этого систему уведомления об ошибках.
2.1.4.1. Проверка контрольной суммы MD5 После того, как пакет MySQL загружен, следует убедиться, что его контрольная сумма MD5 совпадает с той, которая указана на странице загрузки. Каждый пакет имеет индивидуальную контрольную сумму, которую можно проверить с помощью следующей команды (здесь имя_пакета - наименование выгруженного пакета): shell> md5sum имя_пакета Пример: shell> md5sum mysql-standard-4.0.17-pc-linux-i686.tar.gz 60f5fe969d61c8f82e4f7f62657elf06 mysql-standard-4.0.17-pc-linux-i686.tar.gz Вы должны убедиться, что результирующая контрольная сумма (строка шестнадцатеричных цифр) совпадает с указанной на странице загрузки непосредственно под именем соответствующего пакета. Помните, что не все операционные системы поддерживают команду md5sum. В некоторых из них она называется md5, а другие вовсе ее не имеют. В ОС Linux эта команда является частью пакета GNU Text Utilities, который доступен для широкого спектра платформ. Исходные тексты можно загрузить с http://www.gnu.org/software/textutils. Если в системе установлен пакет OpenSSL, можно воспользоваться командой openssl md5 имя_пакета. Реализации команды md5 для DOS/Windows доступны по адресу http://www.fourmilab.ch/md5.
2.1.4.2. Проверка подписи с использованием GnuPG Другой способ проверки целостности и подлинности пакета предполагает использование криптографических подписей. Это более надежный метод, чем контрольные суммы MD5, требующий, однако, больших усилий. Начиная с MySQL 4.0.10 (февраль 2003 года) MySQL AB стала подписывать загружаемые пакеты с помощью GnuPG (GNU Privacy Guard). GnuPG - это программа с открытым исходным кодом, представляющая собой альтернативу хорошо известной Pretty Good Privacy (PGP) от Фила Циммермана (Phil Zimmermann). Более подробную информацию о GnuPG, а также о том, как ее получить и установить, ищите на сайте http://www.gnupg.org. Большинство дистрибутивов Linux поставляются вместе с GnuPG, устанавливаемой по умолчанию. Дополнительная информация об OpenPGP доступна на сайте http://www.openpgp.org. Для проверки подписи конкретного пакета сначала нужно получить копию открытого ключа GPG от MySQL AB. Его можно загрузить с http: //www. keyserver.net. Ключ, который вам необходим, называется
[email protected]. В качестве альтернативы можете воспользоваться приведенным ниже текстом: Key ID: pub 1024D/5072E1F5 2003-02-03 MySQL Package signing key (www.mysql.com) Fingerprint: A4A9 4068 76FC BD3C 4567 70C8 8C71 8D3B 5072 E1F5 Public Key (ASCII-armored):
92
Глава 2. Установка MySQL BEGIN PGP PUBLIC KEY BLOCK Version: GnuPG vl.0.6 (GNU/Linux) Comment: For info see http://www.gnupg.org mQGiBD4+owwRBAC14GIfUfCyEDSIePvEW3SAFUdJBtoQHH/nJKZyQT7h9bPlUWC3RODjQReyCITR rdwyrKUGku2FmeVGwn2u2WmDMNABLnpprWPkBdCk96+OmSLN9brZfw2vOUgCmYv2hW0hyDHuvYlQ A/BThQoADgj8AW6/0Lo7VlW9/8VuHP0gQwCgvzV3BqOxRznNCRCRxAuAuVztHRcEAJooQKl+iSiu nZMYDlWufeXfshc57S/+yeJkegNWhxwR9pRWVArNYJdDRT+rf2RUe3vpquKNQU/hnEIUHJRQqYHo 8gTxvxXNQc7fJYLVK2HtkrPbP72vwsEKMYhhr0eKCbtLGfls9krjJ6sBgACyP/Vb7hiPwxh6rDZ7 ITnEkYpXBACmWpP8NJTkamEnPCia2ZoOHODANwpUkP43I7jsDmgtobZX9qnrAXw+uNDIQJEXM6FS bi0LLtZciNlYsafwAPEOMDKpMqAK6lyisNtPvaLd81H0bPAnWqcyefeprv0sxxqUEMcM3o7wwgfN 83POkDasDbs3pjwPhxvhz6//62zQJ7Q7TXlTUUwgUGFja2FnZSBzaWduaW5nIGtleSAod3d3Lml5 c3FsLmNvbSkgPGJlaWxkQG15c3FsLmNvbT6lXQQTEQIAHQUCPj6jDAUJCWYBgAULBwoDBAMVAwID FgIBAheAAAoJEIxxjTtQcuHlcY4AnilUwTXn8MatQOiG0a/bPxrvK/gCAJ4oinSNZRYTnblChwFa azt7PF3qzIhMBBMRAgAMBQI+PqPRBYMJZgC7AAoJEElQ4SqycpHyJOEAnlmxHijft00bKXvucSo/ pECUmppiAJ41M9MRVj5VcdH/KN/KjRtW6tHFPYhMBBMRAgAMBQI+QoIDBYMJYiKJAAoJELblzU3G uiQ/lpEAoIhpp6BozKI8p6eaabzF5MUH58pAKCu/ROofK8JEg2aLos+5zEYrB/LsrkCDQQ+PqMd EAgA7+GJfxbMdY4wslPnjH9rF4N2qfWsEN/lxaZoJYc3a6M02WCnH16ahT2/tBK2wlQI4YFteR47 gCvtgb6OUHffOo2HfLmRDRiRjdlDTCHqeyX7CHhcghj/dNRlW2Z015QFEcmV9U0Vhp3aFfWC4Uj fs3LU+hkAWzE7zaD5cH9J7yv/6xuZVw411x0h4UqsTcWMu0iMlBzELqXlDY7LwoPEb/O9Rkbf4fm LellEzIaCa4PqARXQZc4dhSinMt6K3X4BrRsKTfozBu74F47D8Ilbf5vSYHbuE5p/loIDznkg/p8 kW+3FxuWrycciqFTcNz215yyX39LXFnlLzKUb/F5GwADBQf+Lwqqa8CGrRfsOAJxim63CHfty5mU c5rUSnTslGYEIOCRlBeQauyPZbPDsDD9MZlZaSafanFvwFG6Llx9xkU7tzq+VKLoWkm4u5xf3vn5 5VjnSdlaQ9eQnUcXiL4cnBGoTbOWI39EcyzgslzBdC++MPjcQTcA7p6JUVsP6oAB3FQWg54tuUo0 Ec8bsM8b3Ev42LmuQT5NdKHGwHsXTPtl0klk4bQk4OajHsiylBMahpT27jWjJlMiJc+IWJ0mghkK Ht926s/ymfdf5HkdQlcyvsz5tryVI3Fx78XeSYfQvuuwqp2H139pXGEkg0n6KdUOetdZWhe70YGN PwlyjWJTlIhMBBgRAgAMBQI+PqMdBQkJZgGAAAoJEIxxjTtQcuH17p4An3rlQpVC9yhnW2cSAjq+ kr72GX0eAJ4295kl6NxYEuFApmrl+0uUq/SlsQ===YJkx END PGP PUBLIC KEY BLOCK
Выполните импорт этого ключа в персональное хранилище открытых ключей GPG с использованием команды gpg --import. Например, если ключ был сохранен в файле mysqljpubkey.asc, команда импорта будет выглядеть следующим образом: shell> gpg —import mysqljpubkey.asc В документации по GPG имеется информация о том, как работать с открытыми ключами. После загрузки открытого ключа приступайте к загрузке необходимого пакета MySQL и соответствующей подписи, которая находится на той же странице выгрузки. Файл подписи имеет то же имя, что и файл дистрибутива, и расширение .asc. Например: Distribution file mysql-standard-4.0.17-pc-linux-i686. t a r . gz Signature file mysql-standard-4.0.17-pc-linux-i686.tar.gz.asc Убедитесь, что оба файла расположены в одном и том же каталоге, после чего запустите следующую команду для проверки подписи файла дистрибутива: shell> gpg —verify имя_пакета.asс Пример: shell> gpg —verify mysql-standard-4.0.17-pc-linux-i686.tar.gz.asc gpg: Warning: using insecure memory!
2.1. Общие вопросы установки
93
gpg: S i g n a t u r e made Mon 03 Feb 2003 08:50:39 PM MET u s i n g DSA key ID 5072E1F5 gpg: Good s i g n a t u r e from "MySQL Package s i g n i n g key (www.mysql.com) " Сообщение "Good signature..." говорит о том, что все в порядке. Предупреждение " u s i n g i n s e c u r e memory" ("использование незащищенной памяти") можно проигнорировать.
2.1.4.3. Проверка подписи с использованием RPM Для пакетов в формате RPM не существует отдельных файлов подписей. Они имеют встроенные подписи GPG и контрольные суммы MD5. Проверить пакет можно с помощью следующей команды: s h e l l > rpm —checksig имя^пакета.rpm Пример: s h e l l > rpm —checksig MySQL-server-4.0.10-0.i386.rpm MySQL-server-4.0.10-0.i386.rpm: md5 gpg OK На заметку! Если вы используете RPM 4.1, и он выдает сообщение вида: "(GPG) NOT OK (MISSING KEYS: GPG#5072e1f5)"f даже если открытый ключ MySQL уже импортирован в ваше собственное хранилище ключей GPG, вначале потребуется выполнить импорт его в хранилище ключей RPM. Дело в том, что RPM 4.1 больше не использует хранилище ключей GPG (как и самого GPG). Вместо этого он поддерживает свое собственное хранилище, поскольку это приложение уровня системы, а хранилище ключей GPG - файл, специфичный для каждого пользователя. Чтобы импортировать открытый ключ MySQL в хранилище ключей RPM, вначале получите его, как описано в предыдущем разделе. Затем воспользуйтесь командой rpm —import для импорта ключа. Например, если открытый ключ хранится в файле mysql_pubkey. as с, команда импорта будет выглядеть так: s h e l l > rpm —import mysql_pubkey.asc
2.1.5. Расположение каталогов установки Этот раздел описывает расположение каталогов по умолчанию, которое получается при установке бинарного или исходного дистрибутивов, предоставляемых компанией MySQL AB. Если вы устанавливаете дистрибутив, полученный от другого поставщика, расположение каталогов может оказаться другим. В среде Windows каталогом установки по умолчанию является C:\raysql, при этом в нем содержатся следующие подкаталоги: Подкаталог
Содержит
bin
Клиентские программы и сервер mysqld.
data
Файлы журналов и баз данных.
Docs
Документация.
examples
Примеры программ и сценариев.
include
Включаемые файлы заголовков.
lib
Библиотеки.
scripts
Сценарии утилит.
share
Файлы сообщений об ошибках.
94
Глава 2. Установка MySQL
После установки, выполненной из RPM-дистрибутивов Linux, файлы располагаются в следующих каталогах: Каталог
Содержит
/usr/bin
Клиентские программы и сценарии.
/usr/sbin
Сервер mysqld.
/var/lib/mysql
Файлы журналов и баз данных.
/usr/ share/doc/packages
Документация.
include/usr/include/mysql
Включаемые файлы заголовков.
lib/usr/lib/mysql
Библиотеки.
/usr/share/mysql
Сообщения об ошибках и файлы символьных наборов.
sql-bench/usr/share/sql-bench
Тесты производительности.
В среде Unix бинарный дистрибутив из файла t a r устанавливается простой распаковкой его в каталог по вашему выбору (обычно /usr/ l o c a l /mysql). При этом создаются следующие подкаталоги: Подкаталог
Содержит
bin
Клиентские программы и сервер mysqld.
data
Файлы журналов и баз данных.
docs
Документация.
include
Включаемые файлы заголовков.
lib
Библиотеки.
scripts
mysql_install_db.
share/mysql
Файлы сообщений об ошибках.
sql-bench
Тесты производительности.
Исходный дистрибутив устанавливается после соответствующего конфигурирования и компиляции. По умолчанию на шаге установки файлы размещаются в следующих подкаталогах каталога /usr/local: Подкаталог
Содержит
bin
Клиентские программы и сценарии.
include /mysql
Включаемые файлы заголовков.
info lib/mysql libexec share /mysql sql-bench var
Документация в Info-формате. Библиотеки. Сервер mysqld. Файлы сообщений об ошибках. Тесты производительности. Файлы журналов и баз данных.
Внутри каталога установки расположение каталогов и файлов для исходного дистрибутива отличается от бинарного в следующих моментах: •
Сервер mysqld устанавливается в подкаталог l i b e x e c вместо подкаталога bin.
•
Подкаталог данных - v a r вместо data.
•
m y s q l _ i n s t a l l _ d b устанавливается в подкаталог b i n вместо s c r i p t s .
•
Подкаталоги библиотеки и файлов заголовков - соответственно, i n c l u d e /mysql и lib/mysql вместо include и lib.
2.2. Стандартная установка MySQL из бинарного дистрибутива
95
Вы можете создать собственную бинарную установку из скомпилированного исходного дистрибутива с помощью сценария scripts/make_binary_distribution, который находится в каталоге верхнего уровня исходного дистрибутива.
2.2. Стандартная установка MySQL из бинарного дистрибутива В настоящем разделе раскрываются особенности установки MySQL на платформах, для которых мы предлагаем дистрибутивы в родном формате пакетов этих платформ (то, на что часто ссылаются как на "бинарную установку"). Бинарные дистрибутивы доступны также и для множества других платформ. В разделе 2.2.5 представлены общие инструкции по установке этих пакетов, которые применимы для всех платформ. В разделе 2.1 можно найти информацию о том, какие другие бинарные дистрибутивы существуют и как их получить.
2.2.1. Установка MySQL под Windows Процесс установки MySQL под Windows включает следующие шаги: 1. Получение и установка дистрибутива. 2. Настройка файла опций, если необходимо. 3. Выбор сервера, который должен использоваться. 4. Запуск сервера. 5. Установка паролей для начальных пользовательских учетных записей MySQL. Дистрибутив MySQL дня платформы Windows доступен в следующих двух форматах: • Бинарный дистрибутив, содержащий программу установки, которая инсталлирует все необходимое таким образом, что можно будет запустить сервер немедленно. • Исходный дистрибутив, содержащий весь исходный код и файлы поддержки, необходимые для сборки исполняемых файлов с помощью компилятора VC++ 6.0. Вообще говоря, вы должны использовать бинарный дистрибутив. Это проще, и вам не понадобятся никакие дополнительные инструменты, чтобы поднять и запустить MySQL. В этом разделе объясняется, как устанавливать MySQL в среде Windows из бинарного дистрибутива. Вопросам установки из исходного дистрибутива посвящен раздел 2.3.6. 2.2.1.1. Требования к системе на базе Windows Для запуска MySQL под управлением Windows необходимы следующие компоненты: • 32-разрядная операционная система Windows, такая как 9х, Me, NT, 2000 или ХР. Семейство NT (Windows NT, 2000 и ХР) позволяет запускать сервер MySQL как системную службу (см. раздел 2.2.1.7). • Поддержка протокола TCP/IP. • Копия бинарного дистрибутива для Windows, которую можно загрузить с http://dev.mysql.com/downloads (см. раздел 2.1.3). 1
На заметку!
Jf В случае загрузки дистрибутива через FTP рекомендуем использовать адекватный FTP-клиент, с 'v. поддержкой догрузки, дабы избежать повреждения файлов в процессе загрузки.
96
Глава 2. Установка MySQL • WinZip или другой Windows-инструмент, способный читать файлы .zip, для распаковки файла дистрибутива. • Достаточный объем свободного пространства на жестком диске, чтобы распаковать, установить и создать базы данных в соответствии с существующими потребностями. • Если планируется подключение к серверу MySQL через интерфейс ODBC, понадобится также драйвер MyODBC. • Если понадобится оперировать с таблицами размером более 4 Гбайт, устанавливайте MySQL в раздел NTFS или более новой файловой системы. Не забывайте при создании таблиц использовать MAXROWS и AVGROWLENGTH.
2.2.1.2. Установка бинарного дистрибутива под Windows Для установки MySQL под управлением Windows с использованием бинарного дистрибутива выполните следующую процедуру: 1. Если вы работаете на компьютере под управлением Windows NT, 2000 или ХР, убедитесь, что вы вошли в систему от имени пользователя с привилегиями администратора. 2. Если осуществляется модернизация более ранней установки MySQL, необходимо остановить существующий сервер MySQL. На машинах с Windows NT, 2000 или ХР, если сервер запущен как системная служба Windows, остановите его командой: С:\> NET STOP MySQL Если вы планируете использовать другой сервер (например, mysqld-max вместо mysqld), удалите существующую службу: С:\> C:\mysql\bin\mysqld —remove Службу можно переустановить, чтобы после модернизации пользоваться правильным сервером. Если сервер MySQL выполняется не как системная служба, остановите его так: С:\> C:\raysql\bin\mysqladmin -u root shutdown 3. Завершите программу WinMySQLAdmin, если она выполняется. 4. Распакуйте файл дистрибутива во временный каталог. 5. Запустите программу setup.exe, чтобы начать процесс установки. Если вы хотите установить MySQL в каталог, отличный от каталога по умолчанию (C:\mysql), с помощью кнопки Browse (Обзор) укажите требуемый каталог. Если для установки MySQL выбран не каталог по умолчанию, то при каждом запуске сервера придется указывать его местоположение. Самый простой способ сделать это - воспользоваться файлом опций, как описано в разделе 2.2.1.3. 6. Завершите процесс установки.
На заметку! Ранние дистрибутивы альфа-версий MySQL 4.1 для Windows не содержали программы установки. Дистрибутив версии 4.1 - это просто Zip-файл, который нужно просто распаковать в каталог, в котором будет выполняться установка MySQL. Например, чтобы установить m y s q l - 4 . 1 . 1 alpha-win.zip в каталог C:\mysql, распакуйте файл дистрибутива на диск С:, затем переименуйте полученный в результате каталог из mysql-4.1.1-alpha в mysql.
2.2. Стандартная установка MySQL из бинарного дистрибутива
97
Если выполняется модернизация ранней версии до MySQL 4.1, вам понадобится предварительно сохранить существующий каталог data, который содержит таблицы привилегий и ваши собственные базы данных. Перед установкой версии 4.1 остановите сервер, если он запущен, и сохраните каталог data где-то в другом месте. После этого переименуйте существующий каталог С: \raysql или просто удалите его. Затем установите MySQL 4.1, как описано выше, и замените содержимое каталога data содержимым старого каталога data. Это позволит избежать потери ваших баз данных. Запустите новый сервер и обновите таблицы привилегий (см. раздел 2.5.8).
2.2.1.3. Подготовка MySQL-окружения для Windows Если при запуске сервера нужно использовать какие-то начальные опции, их можно указать в командной строке либо поместить в файл опций. Те из них, которые будут использоваться при каждом запуске сервера, удобнее поместить в файл, описывающий вашу конфигурацию MySQL. В частности, это справедливо при следующих обстоятельствах: • Размещение каталога установки или каталога данных отличается от принятого по умолчанию (С: \mysql и С: \mysql\data). • Требуется настроить установки сервера. Например, чтобы использовать транзакционные таблицы innoDB в MySQL 3.23, нужно вручную добавить несколько дополнительных строк в файл опций, как описано в разделе 9.4. (Как и в MySQL 4.0, InnoDB создает файлы данных и файлы журналов по умолчанию в каталоге data. Это означает, что необходимость в явном конфигурировании InnoDB отсутствует. Если хотите, можете по-прежнему это делать, и в этом случае вам поможет файл опций.) В среде Windows программа установки MySQL размещает каталог данных непосредственно внутри каталога, куда устанавливается MySQL. Если вы хотите разместить каталог данных в другом месте, туда нужно будет скопировать все его содержимое. Например, по умолчанию программа установки помещает MySQL в каталог C:\mysql, а данные - в С: \mysql\data. Если вы хотите выбрать в качестве каталога данных, скажем, Е: \raydata, потребуется выполнить следующие действия: • Перенести каталог данных из С: \mysql\data в Е: \mydata. • С помощью опции —datadir указать новое местоположение каталога данных при каждом запуске сервера. Сразу после запуска в среде Windows сервера MySQL ищет опции в двух файлах: my. ini в каталоге Windows и С: \my. cnf. Каталог Windows обычно имеет имя С: \WINDOWS или С: \WinNT. Точное его расположение хранится в переменной окружения WINDIR; отобразить содержимое этой переменной можно помощью следующей команды: С:\> echo %WINDIR% MySQL ищет опции сначала в файле my.ini, затем в my.cnf. Однако во избежание конфликтов лучше использовать только один их упомянутых файлов. Если ваш компьютер использует начальный загрузчик (boot loader), в котором диск С: не является загрузочным, то у вас только один выбор - использовать my. ini. Какой бы файл опций вы ни использовали, это должен быть простой двумерный текстовый файл. Файл опций можно создать и модифицировать с помощью любого текстового редактора наподобие Notepad (Блокнот). Например, если MySQL установлен в каталоге
98
Глава 2. Установка MySQL
E:\mysql, а каталогом данных является E:\mydata\data, можно создать файл опций и установить в его разделе [mysqld] следующие значения параметров basedir и datadir: [mysqld] # set basedir to your i n s t a l l a t i o n path # задайте для basedir каталог установки basedir=E:/mysql # set datadir to the location of your data directory # задайте для datadir каталог данных datadir=E:/raydata/data Обратите внимание, что пути каталогов Windows задаются в файле опций с обычными косыми чертами (с правым уклоном) вместо обратных (с левым уклоном). Если вы используете обратные косые черты, они должны дублироваться. Другой способ управления файлом опций предполагает работу с инструментом WinMySQLAdmin. Эта программа находится в каталоге bin вашей установки MySQL, там же хранится и справочный файл с инструкциями по ее применению. С помощью WinMySQLAdmin можно редактировать файл опций, однако следует помнить о следующих моментах: • WinMySQLAdmin работает только с файлом my. ini. • Если WinMySQLAdmin находит файл C:\my.cnf, то переименовывает его в С:\my_cnf .bak, чтобы таким образом его отключить. Теперь все готово к запуску сервера.
2.2.1.4. Выбор сервера для Windows Начиная с версии MySQL 3.23.38, дистрибутив для Windows включает бинарные файлы и нормального сервера, и сервера MySQL-Max. Ниже приведен список различных серверов MySQL, из которых можно выбрать тот, который наиболее точно соответствует существующим потребностям. Бинарный файл
Описание
mysqld
Скомпилирован с полной отладочной информацией, автоматической проверкой распределения памяти, символическими связями и поддержкой таблиц InnoDB и BDB.
mysqld-opt
Оптимизированный вариант. Начиная с версии 4.0, включает поддержку InnoDB. До версии 4.0 этот вариант не поддерживал транзакционные таблицы. Оптимизированный вариант сервера для Windows NT, 2000 и ХР с поддержкой именованных каналов. Оптимизированный вариант с поддержкой символических связей и таблиц InnoDB и BDB.
mysqld-nt mysqld-max mysqld-max-nt
To же самое, что и mysqld-max, но с поддержкой именованных каналов.
Все перечисленные программы оптимизированы для современных процессоров Intel, и должны работать на любом процессоре семейства Intel i386 или более новых. MySQL поддерживает протокол TCP/IP на всех Windows-платформах, mysqld-nt и mysqld-max-nt кроме того поддерживают именованные каналы в средах Windows NT, Windows 2000 и Windows ХР. Однако, независимо от платформы, протоколом по умол-
2.2. Стандартная установка MySQL из бинарного дистрибутива
99
чанию является TCP/IP. (Именованные каналы во многих конфигурациях Windows медленнее, чем TCP/IP.) Применение именованных каналов обусловлено следующими факторами: • Начиная с MySQL 3.23.50, именованные каналы включаются, только если сервер запущен с опцией —enabled-named-pipe. Эту опцию нужно указывать явно, потому что некоторые пользователи сталкивались с проблемами при остановке сервера, когда применялись именованные каналы. • Подключения по именованным каналам возможны только с серверами mysqld-nt и mysqld-max-nt, и только при запуске их под управлением версий Windows, поддерживающих этот протокол (NT, 2000, ХР). • Эти серверы могут работать в Windows 98 или Windows Me, но только если установлен протокол TCP/IP. Именованные каналы в этих случаях не могут быть использованы. • Под управлением Windows 95 эти серверы не работают. % На заметку! ?Л |? & il t; 1\
В большинстве примеров в последующих разделах в качестве имени сервера используется mysqld. Если для запуска выбран другой сервер, такой как mysqld-opt, соответствующим образом измените команды, приведенные в примерах. Существует одна важная причина для выбоpa другого сервера, а именно то обстоятельство, что в mysqld реализована полная поддержка отладки, и, следовательно, этот сервер использует больший объем памяти и функционирует медленнее, нежели другие серверы для Windows.
2.2.1.5. Запуск сервера в первый раз В средах Windows 95, 98 или Me клиенты MySQL всегда подключаются к серверу черех TCP/IP. (В результате к вашему серверу MySQL может подключиться любая машина в сети.) По этой причине перед запуском MySQL следует убедиться, что на машине корректно установлена поддержка TCP/IP. Файлы поддержки TCP/IP находятся на компакт-диске дистрибутива Windows. Необходимо отметить, что если используется старый выпуск Windows 95 (например, OSR2), весьма вероятно, что в нем установлен старый пакет Winsock. MySQL же требует применения Winsock 2. Новейший пакет Winsock можно получить на сайте http://www.microsoft.com. Windows 98 включает новую библиотеку Winsock 2, поэтому в этой системе ее обновлять не нужно. На NT-подобных системах, таких как Windows NT, 2000 или ХР, клиент может выбирать между TCP/IP и именованными каналами (разумеется, если сервер поддерживает подключения по именованным каналам). Информация о выборе программы сервера для запуска представлена в разделе 2.2.1.4. Настоящий раздел дает общее представление о запуске сервера MySQL. Последующие разделы предоставляют более подробную информацию для отдельных версий Windows. В приведенных здесь примерах предполагается, что MySQL установлен в каталог по умолчанию, C:\mysql. Если у вас MySQL установлен в другой каталог, должным образом исправьте имена каталогов, упомянутые в примерах. Тестирование лучше всего выполнять из командной строки в консольном окне (называемом еще "окном DOS"). В этом случае сообщения о состоянии сервера выдаются в то же окно. Если что-то не так с конфигурацией, эти сообщения помогут идентифицировать и решить любые проблемы.
102
Глава 2. Установка MySQL
Чтобы заставить MySQL работать с протоколом TCP/IP в Windows NT, потребуется установить пакет обновлений Service Pack 3 (или более новый). Перед установкой MySQL как службы Windows необходимо вначале остановить текущий сервер, если он запущен. Это делается с помощью следующей команды: С:\> C:\mysql\bin\mysqladmin -u root shutdown Эта команда запускает утилиту администрирования mysqladmin, которая подключается к серверу и посылает ему команду останова. Утилита подключается к серверу с использованием root - стандартной учетной записи администратора в системе привилегий MySQL. Следует отметить, что система привилегий MySQL совершенно не зависит от имен пользователей, которые применялись для входа в Windows. Теперь установите сервер как службу: С:\> mysqld --install Если при указании только имени сервера возникают проблемы с установкой mysqld как службы, попробуйте задать полный путь: С:\> C:\mysq\bin\mysqld —install Для версии MySQL 4.0.2 после опции — i n s t a l l можно указать также и имя службы. В MySQL 4.0.3 после имени службы можно дополнительно задать опцию —defaults-file, чтобы указать, откуда сервер должен получить настройки при запуске. Ниже представлены правила, определяющие имя службы и файлов опций, которые использует сервер. • Если вы не указываете имя службы, сервер использует имя по умолчанию, MySQL, и читает опции из раздела [mysqld] стандартного файла опций. • Если вы указываете имя службы после опции — i n s t a l l , сервер игнорирует раздел [mysqld] и вместо него читает опции из раздела, имя которого совпадает с именем службы в стандартном файле опций. • Если вы указываете опцию —defaults-file после имени службы, сервер игнорирует стандартный файл опций и читает их только из раздела [mysqld] названного файла.
? На заметку! % '^ || &
До версии MySQL 4.0.17 сервер, установленный как служба Windows, порождал проблемы при запуске, если его полный путь или имя службы содержали пробелы. По этой причине следует избегать установки MySQL в каталог вроде С: \Program F i l e s , а также использовать пробелы в имени службы.
В редком случае, когда вы устанавливаете сервер с опцией — i n s t a l l , но без имени службы, сервер устанавливается в виде службы с именем MySQL. В качестве более сложного примера рассмотрим приведенную ниже команду: С:\> С:\mysql\bin\mysqld —install mysql—defaults-file=C:\my-opts.cnf Здесь после опции - - i n s t a l l указывается имя службы. Если не задать опцию —defaults-file, эта команда заставит сервер читать раздел [mysql] стандартного файла опций (что не очень хорошо, поскольку этот раздел предназначен для клиентских программ). Однако, поскольку опция —defaults-file присутствует, сервер прочтет свои настройки из указанного файла, и только из его раздела [mysqld]. Опции можно также задать как Start parameters (Параметры запуска) в Windowsутилите Services.
2.2. Стандартная установка MySQL из бинарного дистрибутива
103
После того, как сервер MySQL установлен и сконфигурирован как служба, он будет автоматически стартовать при запуске Windows. Его также можно запустить немедленно с помощью утилиты Services либо по команде NET START MySQL. Команда NET не чувствительна к регистру символов. Когда сервер MySQL выполняется как служба, он не имеет доступа к консольному окну, поэтому нельзя увидеть никаких сообщений от него. Если mysqld не запустился, просмотрите журнал ошибок на предмет поиска причин проблемы. Журнал ошибок хранится в каталоге С: \mysql\data и представляет собой файл с расширением .err. Если mysqld выполняется как служба, его можно остановить той же утилитой Services, командой NET STOP MySQL или командой mysqladmin shutdown. Если на момент завершения работы Windows служба функционирует, она будет остановлена автоматически. Начиная с MySQL 3.23.44, имеется выбор устанавливать сервер как службу Manual, если вы не хотите, чтобы сервер MySQL запускался автоматически при загрузке системы. Для этого вместо опции - - i n s t a l l укажите опцию —install-manual: С:\> С:\mysql\bin\mysqld —install-manual Чтобы удалить сервер, установленный как служба, сначала остановите его. Затем воспользуйтесь опцией --remove для его удаления: С:\> С:\mysql\bin\mysqld —remove С версиями MySQL до 3.23.49 была связана одна проблема с автоматической остановкой службы, а именно: ОС Windows ожидала всего несколько секунд ее завершения, затем, по истечении некоторого лимита времени, прерывала процесс сервера. Это потенциально могло привести к возникновению проблем (например, механизму хранения InnoDB при следующем запуске приходилось выполнять восстановление после аварийного завершения). Начиная с MySQL 3.23.49, Windows ожидает завершения работы сервера MySQL дольше. Если вы обнаружите, что этого недостаточно, будет безопаснее не запускать сервер MySQL в виде службы. Вместо этого запускайте его из командной строки и останавливайте с помощью mysqladmin shutdown. Возможность увеличения времени для ожидания останова службы существует в Windows 2000 и ХР. Это не работает в Windows NT, где система ожидает останова службы всего 20 секунд, после чего прерывает процесс. Вы можете увеличить это время ожидания, открыв редактор системного реестра \winnt\system32\regedt32.exe и изменив значение WaitToKillServiceTimeout в разделе HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control дерева реестра. Время указывается в миллисекундах (например, значение 120000 соответствует 120-секундному ожиданию). Если вы не хотите выполнять mysqld в виде службы, запускайте его в командной строке. Соответствующие инструкции можно найти в разделе 2.2.1.6. 2.2.1.8. Запуск клиентских программ MySQL в среде Windows Проверить, функционирует ли сервер MySQL можно с помощью любой из приведенных ниже команд: С:\> С:\mysql\bin\mysqlshow С:\> C:\mysql\bin\mysqlshow -u root mysql С:\> C:\mysql\bin\mysqladmin version status proc C:\> C:\mysql\bin\mysql test
Глава 2. Установка MySQL
104
Если mysqld медленно реагирует на TCP/IP-соединения клиентских программ в среде Windows 9x/Me, возможно, существуют проблемы с системой доменных имен (DNS). В этом случае запустите mysqld с опцией —skip-name-resolve и используйте только localhost и IP-адреса в столбце Host таблиц привилегий MySQL. Можно также заставить клиент MySQL подключаться по именованному каналу вместо TCP/IP, указав опцию —pipe или же точку (.) в качестве имени хоста. С помощью опции —socket указывается имя канала. Для MySQL 4.1 необходимо использовать опцию —ptorocol=PIPE. Существуют две версии инструмента командной строки MySQL: Программа
Описание
mysql
Скомпилирована под Windows, предоставляет ограниченные возможности по редактированию текста. Скомпилирована с помощью компилятора Су gnus GNU с его библиотеками, предоставляет возможности редактирования readline.
mysql с
Если вы хотите работать с mysql с, у вас должна быть копия библиотеки cygwinbl9.dll, установленная в таком месте, где mysqlc сможет ее найти. Текущий дистрибутив MySQL содержит эту библиотеку в том же каталоге, где находится mysqlc (подкаталог bin базового каталога установки MySQL). Если ваш дистрибутив не содержит библиотеки cygwinbl9.dll в каталоге bin, поищите ее в каталоге l i b и скопируйте ее в системный каталог Windows (\Windows\System или подобный).
2.2.1.9. Сравнение MySQL для Windows и MySQL для Unix Версия MySQL для Windows в настоящее время доказала свою стабильность. Версия MySQL для Windows обладает теми же средствами, что и соответствующая версия для Unix, однако за некоторыми исключениями: • Windows 95 и потоки. Windows 95 теряет около 200 байт основной памяти при каждом создании потока. Каждое подключение к MySQL создает новый поток, поэтому вы не сможете выполнять mysqld в течение длительного времени под Windows 95, если ваш сервер обслуживает много подключений! Другие версии Windows этим недостатком не страдают. • Ограниченное количество портов. Системы Windows имеют около 4000 портов, доступных клиентским соединениям, и после того, как соединение закрывается, проходит от двух до четырех минут, прежде чем порт может использоваться заново. В ситуациях, когда клиенты часто подключаются к серверу и отключаются от него, может случиться, что все доступные порты окажутся занятыми на какое-то время. При этом MySQL станет недоступным, несмотря на то, что он попрежнему будет функционировать. Следует отметить, что порты могут быть заняты и другими приложениями, работающими на данной машине; в этом случае количество портов, доступных MySQL, еще более уменьшается. • Параллельное чтение. MySQL зависит от вызовов pread() и pwriteO, чтобы иметь возможность вперемешку выполнять операторы INSERT и SELECT. В настоящее время мы применяем семафоры (mutexes) для эмуляции pread()/pwrite (). Через какое-то время мы заменим интерфейс уровня файлов виртуальным интерфейсом, дабы можно было использовать интерфейсы readfile()/writefile О в Windows NT, 2000 и ХР для увеличения скорости. Текущая реализация ограничи-
2.2. Стандартная установка MySQL из бинарного дистрибутива
105
вает количество открытых файлов MySQL числом 1024, а это означает, что вы не сможете запустить так же много параллельных потоков под NT, 2000 и ХР, как под Unix. •
Блокирующее чтение. MySQL применяет блокирующее чтение для каждого соединения, что приводит к следующим последствиям, если включены соединения по именованным каналам: •
Соединение не будет автоматически прервано через восемь часов, как это происходит в Unix-версии MySQL.
•
Если соединение "зависло", невозможно прервать его без прерывания MySQL.
•
mysqladmin k i l l не работает на спящих соединениях.
•
mysqladmin единения.
shutdown не может остановить сервер, пока есть спящие со-
Мы планируем решить эти проблемы, когда наши Windows-разработчики подготовят хороший "обходной путь". •
ALTER TABLE. Пока выполняется оператор ALTER TABLE, таблица заблокирована от использования другими потоками. Это обусловлено тем, что в Windows нельзя удалить файл, который используется другим потоком. Возможно, в будущем мы найдем, как обойти эту проблему.
•
DROP TABLE. Оператор DROP TABLE для таблицы, используемой в таблице MERGE, не работает под Windows, поскольку MERGE делает отображение таблиц скрытым от верхнего уровня MySQL. Так как Windows не позволяет удалять открытые файлы, вам сначала надо сбросить таблицы MERGE (командой FLUSH TABLE), или удалить таблицу MERGE до выполнения DROP TABLE. Мы исправим это вместе с внедрением представлений.
•
DATA DIRECTORY и INDEX DIRECTORY. Опции DATA DIRECTORY И INDEX DIRECTORY команды CREATE TABLE в Windows-версии MySQL игнорируются, поскольку Windows не поддерживает символические ссылки. Эти опции также игнорируются в системах, имеющих не функциональный вызов r e a l p a t h ().
•
DROP DATABASE. Невозможно удалить базу данных, которую использует какой-то поток.
•
Прерывание MySQL из диспетчера задач (Task Manager). Нельзя уничтожить MySQL с помощью диспетчера задач или утилиты shutdown в Windows 95. Вы должны это делать командой mysqladmin shutdown.
•
Имена, чувствительные к регистру символов. Имена файлов в Windows не чувствительны к регистру символов, поэтому имена баз данных и таблиц MySQL в Windows также не чувствительны к регистру. Единственным ограничением является требование, что имя базы данных и таблицы должно указываться в одном и том же регистре на протяжении всего SQL-оператора.
•
Символ 'V для разделения имен каталогов в пути. Имена путей в Windows 95 разделяются символом ' \ \ который интерпретируется MySQL как управляющий. Если вы используете LOAD DATA INFILE или SELECT.. .INTO OUTFILE, применяйте разделители V в стиле Unix, например: mysql> LOAD DATA INFILE 'Ci/tmp/skr.txt' INTO TABLE skr; mysql> SELECT * INTO OUTFILE 'Cr/tmp/skr.txt f FROM skr;
106
Глава 2. Установка MySQL
В качестве альтернативы можно повторять символ 'V: mysql> LOAD DATA INFILE 'С:\\tmp\\skr.txt' INTO TABLE skr; mysql> SELECT * INTO OUTFILE 'C:\\tmp\\skr.txt' FROM skr; • Проблемы с каналами. Каналы не работают надежно в командной строке Windows. Если в канал передается символ AZ/CHAR(24), Windows интерпретирует его как конец файла и прерывает программу. Эта проблема проявляется, когда вы пытаетесь работать с бинарным журналом следующим образом: С:\> mysqlbinlog имя_бинарного_журнала | mysql —user=root Если возникают проблемы при работе с бинарным журналом, и вы предполагаете, что причина может быть связана с символом AZ/CHAR(24), можете воспользоваться следующим обходным путем: С:\> mysqlbinlog имя_бинарного_журнала —result-file=/tmp/bin.sql С:\> mysql —user=root —execute "source /tmp/bin.sql" Последняя команда также может быть применена для надежного чтения любого SQL-файла, который содержит бинарные данные. • Ошибка 'Can't open named pipe9 ('Невозможно открыть именованный канал9). Если используете сервер MySQL 3.23 в среде Windows NT с новейшими клиентскими программами MySQL, может возникнуть ошибка вида: error 2017: can't open named pipe to host: . pipe... ошибка 2017: невозможно открыть именованный канал для хоста: . канал... Это происходит потому, что данная версия MySQL использует в среде Windows NT именованные каналы по умолчанию. Избежать этой ошибки можно, если указать опцию —host=localhost в новых MySQL-клиентах, или же создать файл опций С: \my. cnf, включающий следующую информацию: [client] host = localhost Начиная с версии MySQL 3.23.50, именованные каналы включаются только в том случае, если mysqld-nt или mysql-max-nt запущены с опцией —enabled-named-pipe. • Ошибка 'Access denied for user 9 ('Доступ запрещен для пользователя9). Если вы пытаетесь запустить клиентскую программу MySQL, чтобы подключиться к серверу, работающему на той же машине, и получаете сообщение об ошибке, подобное: 'Access denied for user 'some-user@unknown' to database 'mysql'', это означает, что MySQL не может корректно преобразовать имя вашего хоста. Чтобы исправить подобную ситуацию, потребуется создать файл \windows\hosts, содержащий такую строку: 127.0.0.1
localhost
Ниже перечислены некоторые открытые задачи для тех, кто пожелает помочь нам усовершенствовать версию MySQL для Windows: • Разработать какие-нибудь симпатичные пиктограммы запуска и останова для установки MySQL. • Было бы очень хорошо иметь возможность прерывать mysqld из диспетчера задач в Windows 95. На сегодня это возможно только командой mysqladmin shutdown.
2.2. Стандартная установка MySQL из бинарного дистрибутива
107
• Перенести библиотеку readline под Windows, чтобы использовать в инструменте командной строки mysql. • Версии с графическим интерфейсом стандартных клиентов MySQL (mysql, mysqldhow, mysqladmin и mysqldump). • Было бы хорошо, если бы функции чтения и записи сокетов в net. с стали прерываемыми. Это позволило бы прерывать открытые потоки в Windows с помощью команды mysqladmin k i l l . • Добавить макросы для использования безопасных в отношении потоков методов инкремента/декремента, которые предоставляет Windows.
2.2.2. Установка MySQL под Linux Рекомендуемый способ установки MySQL под Linux предполагает использование RPMпакетов. Дистрибутивы MySQL в форме RPM-пакетов в настоящее время собираются в системе Linux SuSE 7.3, но должны работать в большинстве версий Linux, которые поддерживают rpm и glibc. О том, как получить RPM-пакеты, рассказывается в разделе 2.1.3. б На заметку! if* Л |f Щ % fj|
Часто дистрибутивы MySQL в формате RPM-пакетов предлагаются другими поставщиками. Имейте в виду, что они могут отличаться по составу средств и возможностей от тех, что поставляет компания MySQL AB, и поэтому инструкции из настоящего руководства не обязательно применимы в отношении их установки. В таки случаях имеет смысл пользоваться инструкциями поставщиков.
Если у вас возникают проблемы с RPM-файлом (например, если вы получаете сообщение об ошибке наподобие "Sorry, the host 'xxxx' could not be looked up" ("Извините, хост 'хххх' не доступен")), ознакомьтесь с материалами раздела 2.6.1.2. В большинстве случаев для получения работающей копии MySQL нужно установить только два пакета - MySQL-server и MySQL-client. Все остальные пакеты для стандартной установки не обязательны. Если вы хотите запускать сервер MySQL-Max, который обладает набором дополнительных возможностей, установите дополнительно RPMпакет MySQL-Max (см. раздел 4.1.2). При получении во время установки пакетов MySQL 4.0 сообщения об ошибке, связанной с зависимостями (например, "error: removing these packages would break dependencies: libmysqlclient.so.10 is needed by . . . " ("ошибка: удаление этих пакетов может разрушить зависимости: libmysqlclient.so.10 необходим для ...")), потребуется дополнительно установить пакет MySQL-shared-compat, который включает в себя две библиотеки общего использования для целей обратной совместимости (libmysqlclient. so. 12 для MySQL 4.0 и libmysqlclient. so. 10 для MySQL 3.23). Многие дистрибутивы Linux до сих пор поставляются вместе с MySQL 3.23, и они обычно динамически связывают приложения, чтобы сэкономить место на диске. Если эти библиотеки общего использования находятся в другом пакете (например, MySQLshared), достаточно просто оставить эти пакеты на месте и только выполнить модернизацию пакетов сервера и клиента MySQL (которые скомпонованы статически и не требуют библиотек общего использования). Для дистрибутивов с библиотеками общего использования в том же пакете, что и сервер MySQL (например, как в Red Hat Linux), вы можете либо установить версию 3.23 нашего пакета MySQL-shared, либо воспользоваться вместо нее пакетом MySQL-shared-compat.
108
Глава 2. Установка MySQL
Доступны следующие RPM-пакеты: • MySQL-server-ВЕРСИЯ.±386.rpm Сервер MySQL. Понадобится, если только вы не хотите подключаться к аналогичному серверу MySQL, который выполняется на другой машине. Следует отметить, что имена RPM-файлов сервера до версии 4.0.10 имели вид MySQLВЕРСИЯ. i386. rpm, то есть не имели в названии слова -server. • MySQL-Max-ВЕРСЯЯ. ±386. rpm Сервер MySQL-Max. Этот сервер обладает дополнительными возможностями, которых нет в RPM-пакете MySQL-server. Сначала необходимо установить RPMпакет MySQL-serve г, поскольку RPM-пакет MySQL-serve r зависит от него. • MySQL-client-ВЕРСЯЯ.±386.rpm Стандартные клиентские программы MySQL. Очевидно, что этот пакет устанавливается в любом случае. • MySQL-bench-ВЕРСЯЯ.±386.rpm Тесты и испытания производительности. Требуют наличия языка Perl с модулем DBD::mysql. • MySQL-devel-ВЕРСЯЯ.±386.rpm Библиотеки и файлы заголовков, которые понадобятся для компиляции других MySQL-клиентов, таких как модули Perl. • MySQL-shared-ВЕРСИЯ.±386.rpm Этот пакет содержит библиотеки общего использования (libmysqlclient.so*), которые нужны некоторым языкам и приложениям для динамической загрузки и взаимодействия с MySQL. • MySQL-shared-compat-ВЕРСИЯ.±386.rpm Этот пакет содержит разделяемые (общего использования) библиотеки как для MySQL 3.23, так и MySQL 4.O. Устанавливайте этот пакет вместо MySQL-shared. • MySQL-embedded-ВЕРСЯЯ.±386. rpm Библиотеки встроенного сервера MySQL (начиная с MySQL 4.0). • MySQL-ВЕРСЯЯ.src.rpm Здесь содержатся исходные тексты всех перечисленных выше пакетов. Может также использоваться для повторной сборки RPM-пакетов, ориентированных на другие архитектуры (например, Alpha или SPARC). Для просмотра полного списка файлов в RPM-пакете (например, в MySQL-server) воспользуйтесь следующей командой: shell> rpm -qpl MySQL-server-B£PCM.i386.rpm Для выполнения минимальной стандартной установки служат такие команды: shell> rpm - i MySQL-server-ВЕРСИЯ.i386.rpm shell> rpm - i MySQL-client-B£POlff.i386.rpm Чтобы установить только клиентский пакет, выполните приведенную ниже команду: shell> rpm - i MySQL-client-B£PO^.i386.rpm
2.2. Стандартная установка MySQL из бинарного дистрибутива
109
RPM предоставляет возможность проверить целостность и аутентичность пакетов перед их установкой. Дополнительную информацию по этой возможности можно найти в разделе 2.1.4. Пакет RPM сервера помещает данные в каталог /var/lib/mysql. Кроме того, он создает в системе пользовательскую учетную запись с именем mysql (если только она не существовала ранее), от имени которой будет запускаться сервер MySQL, и генерирует соответствующие записи в / e t c / i n i t . d для автоматического старта сервера во время загрузки системы. (Это означает, что если у вас на машине присутствовала предыдущая установка и вы вносили какие-то изменения в сценарии запуска, то их следует скопировать, чтобы не потерять при новой установке RPM). В разделе 2.4.3 представлена информация о том, как сервер MySQL может запускаться и останавливаться автоматически вместе с операционной системой. Если вы хотите установить RPM-пакет MySQL в систему с более старым дистрибутивом Linux, который не поддерживает инициализационные сценарии в / e t c / i n i t . d (непосредственно или через символические ссылки), то вам придется создать символическую ссылку, указывающую на реальное местоположение инициализационных сценариев. Например, если в вашей системе эти сценарии расположены в /etc/rc.d/init.d, то до начала установки RPM с помощью приведенных ниже команд создайте / e t c / i n i t . d как символическую ссылку, указывающую на упомянутое выше местоположение: shell> cd /etc shell> In -s r c . d / i n i t . d . Однако все современные дистрибутивы Linux уже должны поддерживать новую раскладку каталогов, которая использует /etc/init.d, поскольку того требует совместимость со стандартом LSB (Linux Standard Base). Если среди RPM-файлов, которые вы устанавливаете, имеется MySQL-server, то после завершения установки сервер mysqld должен быть поднят и запущен в работу. В таком случае вы немедленно можете приступить к работе с MySQL. Если что-то пойдет неправильно, вы можете найти более подробную информацию в разделе, посвященном бинарной инсталляции (см. раздел 2.2.5). ;
На заметку!
1;' Пользовательские учетные записи, перечисленные в таблицах привилегий MySQL, изначально h не имеют паролей. После запуска сервера вы должны установить для них пароли, как описано в \/ разделе 2.4.
2.2.3. Установка MySQL под Mac OS X Начиная с MySQL 4.0.11, существует возможность установки MySQL в среде Mac OS X ("Jaguar"), используя дистрибутив в формате бинарного пакета Mac OS X PKG вместо старого бинарного формата tar. Помните, что более старые версии Max OS (например, 10.1.x) этим пакетом не поддерживаются. Пакет находится внутри файла образа диска (.dmg), который вначале необходимо смонтировать двойным щелчком кнопкой мыши на его пиктограмме в Finder. После этого образ будет смонтирован и показано его содержимое. Информация о получении MySQL приведена в разделе 2.1.3.
Глава 2. Установка MySQL
110 На заметку!
Прежде чем приступать к инсталляции, убедитесь, что все экземпляры серверов MySQL остановлены. Это делается либо с помощью приложения MySQL Manager Application (в Mac OS X Server), либо по команде mysqladmin shutdown из командной строки.
Чтобы установить пакет MySQL PKG, выполните двойной щелчок на пиктограмме пакета. Это запустит программу Mac OS X Package Installer, которая проведет через весь процесс установки MySQL. Из-за ошибки в установщике пакетов Mac OS X в диалоговом окне выбора диска назначения может появиться следующее сообщение: You cannot install this software on this disk, (null) Невозможно установить данное программное обеспечение на выбранный диск, (null) Если такая ошибка произошла, просто щелкните на кнопке Go Back (Назад) один раз, чтобы вернуться на предыдущий экран. Затем щелкните на кнопке Continue (Продолжить), чтобы вызвать диалог выбора диска еще раз. На этот раз вы сможете выбрать диск без проблем. Мы сообщили об этой ошибке в компанию Apple, и они исследуют проблему. Пакет Mac OS X PKG MySQL устанавливает себя в каталог /usr/local/mysqlВЕРСИЯ и одновременно создает символическую ссылку /usr/local/mysql, указывающую на новое местоположение. Если каталог /usr/local/mysql уже существует, вначале он переименовывается на /usr/local/mysql.bak. Дополнительно установщик создает таблицы привилегий в базе данных mysql, выполняя непосредственно после установки сценарий mysql_install_db. Расположение файлов после установки такое же, как и при использовании бинарного дистрибутива в формате tar, - все исполняемые бинарные программы MySQL находятся в каталоге /usr/local/mysql/bin. Файл сокета MySQL создается по умолчанию как /tmp/mysql. sock. См. раздел 2.1.5. Установка MySQL требует наличия учетной записи пользователя Mac OS X с именем mysql. Пользовательская учетная запись с этим именем должна существовать по умолчанию в среде Mac OS X 10.2 и выше. Если вы работаете с Mac OS X Server, то, скорее всего, версия MySQL уже на нем присутствует. Версии MySQL, которые поставляются вместе с версиями Mac OS X Server, перечислены ниже: Версия Mac OS X Server
Версия MySQL
10.2-10.2.2 10.2.3-10.2.6 10.3 10.3.2
3.23.51 3.23.53 4.0.14 4.0.16
Настоящий раздел руководства посвящен только установке официального пакета MySQL Mac OS X PKG. Ознакомьтесь со справочной информацией Apple об установке MySQL: запустите приложение "Help View", выберите справку "Mac OS X Server", выполните в ней поиск "MySQL" и прочитайте раздел, озаглавленный "Installing MySQL". Для предварительно установленной версии MySQL в Mac OS X Server особо обратите внимание на то, что вам нужно запускать mysqld с помощью safejnysqld, а не mysqldsaf е, если версия MySQL выше 4.0.
2.2. Стандартная установка MySQL из бинарного дистрибутива
111
Если вы ранее работали с пакетом MySQL для Mac OS X от Марка Лайанейджа (Marc Liyanage) (http://www.entropy.ch), можете просто следовать инструкциям для пакетов с бинарной раскладкой файлов, описанным на сайте h t t p : //www. entropy. ch. Если вы обновляете версии 3.23.x MySQL для Mac OS X от Марка или версию MySQL, которая поставляется с Mac OS X Server, до официального пакета MySQL PKG, вам потребуется преобразовать существующие таблицы привилегий MySQL в современный формат, поскольку сейчас появились новые привилегии безопасности (см. раздел 2.5.8). Если вы предпочитаете, чтобы MySQL автоматически стартовал при запуске системы, вам нужно будет установить приложение MySQL Startup Item. Начиная с MySQL 4.0.15, эта часть образа инсталляционного диска имеет форму отдельного инсталляционного пакета. Просто выполните двойной щелчок на пиктограмме MySQLStartupItem.pkg, после чего следуйте инструкциям по установке. Обратите внимание на то, что приложение Startup Item нужно установить только однажды! Нет необходимости устанавливать его при каждом обновлении пакета MySQL. Приложение Startup Item устанавливается в каталог /Library/StartupItems/MySQLCOM. (До версии MySQL 4.1.2 его местоположением был каталог /Library/StartupItems/MySQL, что конфликтовало с MySQL Startup Item, установленным с системой Mac OS X Server.) Установка Startup Item добавляет переменную MYSQLCOM=-YES- в файл конфигурации системы /etc/hostconfig. Если необходимо отключить автоматический запуск сервера MySQL, просто измените значение этой переменной на MYSQLCOM=-NO-. В системе Mac OS X Server установка MySQL по умолчанию использует переменную MYSQL в файле /etc/hostconfig. Установщик Startup Item от компании MySQL AB отключает эту переменную, устанавливая MYSQL=-NO-. Это позволяет избежать конфликта с переменной MYSQLCOM, которую использует Startup Item от MySQL AB. Однако это не останавливает сервер MySQL, если он уже запущен. Останов потребуется выполнить самостоятельно. После установки MySQL можно запустить сервер MySQL, выдав в терминальном окне приведенные ниже команды. Вы должны иметь привилегии администратора. Если есть установленное приложение Startup Item: shell> sudo /Library/StartupItems/MySQL/MySQL s t a r t (Enter your password, if necessary) (Press Control-D or enter "exit" to exit the shell) (При необходимости введите пароль) (Нажмите Control-D или введите "exit" для завершения оболочки) Если же Startup Item нет, воспользуйтесь следующей последовательностью команд: shell> cd /usr/local/mysql shell> sudo ./bin/mysqld_safe (Enter your password, if necessary) (Press Control-Z) (При необходимости введите пароль) (Нажмите Control-Z) shell> bg (Press Control-D or enter "exit" to exit the shell) (Нажмите Control-D или введите "exit" для завершения оболочки) Теперь у вас можете подключиться /usr/local/mysql/bin/mysqld.
к серверу, например, запустив
112
Глава 2. Установка MySQL
|1 На заметку! Щ Пользовательские учетные записи, перечисленные в таблицах привилегий MySQL, изначально §f не имеют паролей. После запуска сервера вы должны установить для них пароли, как описано в Щ разделе 2.4.
Может возникнуть желание добавить псевдонимы в ресурсный файл оболочки, чтобы упростить доступ из командной строки к часто используемым программам, таким как mysql и mysqladmin. Ниже показан синтаксис для оболочки tcsh: alias mysql /usr/local/mysql/bin/mysql alias mysqladmin /usr/local/mysql/bin/mysqladmin А вот синтаксис для оболочки bash: alias alias
mysql=/usr/local/mysql/bin/mysql mysqladmirWusr/local/mysql/bin/mysqladmin
Еще лучше будет, если добавить путь /usr/local/mysql/bin в переменную окружения PATH. Например, добавьте следующую строку в файл $HOME/.tcshrc, если используется командная оболочка tcsh: setenv PATH ${PATH}:/usr/local/mysql/bin Если файл .tcshrc в вашем домашнем каталоге не существует, создайте его с помощью текстового редактора. Если вы обновляете существующую установку, обратите внимание, что установка нового пакета MySQL PKG не удаляет каталог старой установки. К сожалению, установщик MacOS X пока не обеспечивает функциональность, необходимую для корректного обновления ранее установленных пакетов. Чтобы после установки нового сервера MySQL можно было пользоваться существующими базами данных, нужно скопировать содержимое старого каталога данных в новый. Прежде чем делать это, убедитесь, что ни старый, ни новый сервер не выполняются. После успешного копирования файлов баз данных из старой установки и успешного запуска нового сервера имеет смысл удалить файлы старой установки, дабы освободить дисковое пространство. Дополнительно потребуется удалить старую версию каталогов Package Receipt, расположенную в /Library/Receipts/mysql-ВЕРСИЯ.ркд.
2.2.4. Установка MySQL под NetWare Перенос MySQL в среду NetWare был инициирован самой компанией Novell. Пользователи ОС Novell NetWare 6.5 получают в свое распоряжение встроенный MySQL в комплекте с автоматической коммерческой лицензией для всех серверов, работающих на основе упомянутой версии NetWare. Что касается версии 4.0.11, то сервер MySQL доступен для Novell Netware в форме бинарного пакета. MySQL для NetWare скомпилирован комбинацией Metrowerks CodeWarrior for NetWare и специальной кросс-компилирующей версией GNU autotools. Бинарный пакет для NetWare можно получить с http://dev.mysql.com/downloads/ (см. раздел 2.1.3). Для нормального функционирования MySQL сервер NetWare должен отвечать следующим требованиям: • NetWare версии 6.5 или NetWare версии 6.0 с установленным пакетом поддержки (Support Pack) версии 3. Он доступен по адресу: http://support.novell.com/filefinder/13659/index.html
2.2. Стандартная установка MySQL из бинарного дистрибутива
113
• Система должна отвечать требованиям Novell для работы соответствующей версии NetWare. • Данные MySQL, равно как и его программы, должны быть установлены на томе NSS; традиционные тома не поддерживаются. Для установки MySQL под NetWare потребуется выполнить следующую процедуру: 1. Если вы обновляете предыдущую установку, остановите сервер MySQL. Это делается в серверной консоли с помощью следующей команды: SERVER: mysqladmin -u root shutdown 2. Зарегистрируйтесь на сервере с клиентской машины, с которой имеется доступ к местоположению будущей установки MySQL. 3. Распакуйте Zip-файл бинарного пакета на сервер. Не забудьте обеспечить путь доступа к Zip-файлу. Проще всего распаковать его в SYS: \. При обновлении предыдущей установки может понадобиться скопировать каталог данных (например, SYS:MYSQL\DATA), а также файл my.cnf, если он настраивался вручную. Затем можно удалить старую копию MySQL. 4. Возможно, вы захотите переименовать каталог, указав для него более понятное и удобное имя. Мы советуем использовать SYS:MYSQL. Примеры в настоящем руководстве используют это имя для ссылки на каталог установки. 5. В серверной консоли добавьте к пути поиска каталог, в котором содержаться NLM-модули MySQL, например: SERVER: SEARCH ADD SYS:MYSQL\BIN 6. Если необходимо, инициализируйте каталог данных и таблицы привилегий, запустив mysqld_install_db в серверной консоли. 7. Запустите сервер MySQL с помощью команды m y s q l s a f e в серверной консоли. 8. Для завершения установки потребуется добавить приведенные ниже команды в файл autoexec.ncf. Например, если сервер MySQL установлен в каталог SYS:MYSQL и необходимо, чтобы он запускался автоматически во время старта системы, добавьте следующие строки: # S t a r t s t h e MySQL 4 . 0 . x database server #3апуск сервера баз данных MySQL 4 . 0 . x SEARCH ADD SYS:MYSQL\BIN MYSQLD_SAFE Если вы запускаете MySQL под управлением NetWare 6.0, настоятельно рекомендуем использовать опцию — s k i p - e x t e r n a l - l o c k i n g в командной строке: # S t a r t s t h e MySQL 4 . 0 . x database server #3апуск сервера баз данных MySQL 4 . 0 . x SEARCH ADD SYS:MYSQL\BIN MYSQLD_SAFE - - s k i p - e x t e r n a l - l o c k i n g Кроме того, понадобится использовать команды CHECK TABLE и REPAIR TABLE вместо myisamchk, так как myisamchk применяет внешнюю блокировку. Известно, что внешние блокировки в NetWare 6.0 порождают ряд проблем, которые благополучно решены в NetWare 6.5.
114
Глава 2. Установка MySQL mysqldsaf e в NetWare имеет экранное представление. Когда вы выгружаете (останавливаете) NLM-модуль mysqld_safe, экран по умолчанию не очищается. Вместо этого он ожидает пользовательского ввода: ** **
Если хотите, чтобы NetWare вместо этого закрывал экран автоматически, воспользуйтесь опцией —autoclose, например: # S t a r t s t h e MySQL 4 . 0 . x d a t a b a s e s e r v e r #3апуск с е р в е р а б а з данных MySQL 4 . 0 . x SEARCH ADD SYS:MYSQL\BIN MYSQLD_SAFE — a u t o c l o s e
Поведение mysqld_safe в среде NetWare описывается далее в разделе 4.1.3. Если на сервере существовала предыдущая установка MySQL, проверьте наличие команд запуска MySQL в autoexec.ncf и при необходимости отредактируйте или удалите их. |
На заметку!
;> ¥ С
Пользовательские учетные записи, перечисленные в таблицах привилегий MySQL, изначально не имеют паролей. После запуска сервера вы должны установить для них пароли, как описано в разделе 2.4.
2.2.5. Установка MySQL в других Unix-подобных системах
Этот раздел посвящен установке бинарного дистрибутива MySQL, предназначенного для разных платформ, в форме сжатых файлов t a r (файлов с расширением .tar.gz). Подробный список приведен в разделе 2.1.2.5. Информация о получении дистрибутивов MySQL доступна в разделе 2.1.3. Бинарные дистрибутивы MySQL в формате t a r имеют имена наподобие mysqlВЕРСИЯ-ОС.tar.gz, где ВЕРСИЯ- номер версии (например, 4.0.17), а ОС указывает на тип операционной системы, для которой предназначен дистрибутив (например, pc-linuxgnu-i586). В дополнение к этим общим пакетам, мы также предлагаем бинарные дистрибутивы в виде пакетов, форматы которых зависят от платформы. В разделе 2.2 можно найти информацию о том, как их устанавливать. Для установки бинарного дистрибутива в формате t a r необходимы следующие инструменты: • Утилита GNU gun zip для распаковки дистрибутива. • Подходящая программа t a r для распаковки дистрибутива. Хорошо работает, например, GNU tar. Некоторые операционные системы поставляются вместе с предустановленными версиями tar, о которых известно, что они имеют определенные проблемы. Например, версии t a r из комплекта Mac OS X и Sun характеризуются сложностями при работе с длинными именами файлов. В среде Mac OS X можно использовать предустановленную программу gnutar. В других системах с дефектными утилитами t a r вначале следует установить GNU t a r . Если вы сталкиваетесь с проблемами, всегда пользуйтесь mysqlbug перед отправкой вопросов в списки рассылки MySQL. Даже если проблема не вызвана ошибкой,
2.2. Стандартная установка MySQL из бинарного дистрибутива
115
mysqlbug соберет информацию о системе, которая поможет нам решить проблему. Не используя mysqlbug, вы снижаете вероятность получить решение. Вы найдете mysqlbug в каталоге bin после распаковки дистрибутива. См. раздел 1.7.1.3. Базовые команды, которые нужно выполнить для установки и использования бинарного дистрибутива MySQL, выглядят, как показано ниже: shell> groupadd mysql shell> useradd -g mysql mysql shell> cd /usr/local shell> gunzip < /путь/к/mysql-ВЕРСИЯ-ОС.tar.gz | tar xvf shell> In -s полный-путь-к-тузд1-ВЕРСИЯ-0С mysql shell> cd mysql shell> scripts/mysql_install_db --user=mysql shell> chown -R root . shell> chown -R mysql data shell> chgrp -R mysql . shell> bin/mysqld_safe —user=mysql & Для версий MySQL, предшествующих 4.0, в последней команде замените bin/mysqld_safе на bin/safe_mysqld. На заметку! Эта процедура не устанавливает паролей для пользовательских учетных записей MySQL. После выполнения описанной процедуры проделайте действия, указанные в разделе 2.4.
Ниже представлена более детальная версия процедуры установки бинарного дистрибутива. 1. Добавьте пользователя и группу для запуска mysqld: shell> groupadd mysql shell> useradd -g mysql mysql Эти команды добавляют новую группу mysql и пользователя mysql. Синтаксис команд groupadd и useradd может слегка отличаться в различных версиях Unix. Команды также могут иметь названия adduser и addgroup. Вы можете назвать пользователя и группу как-то иначе вместо mysql. Если это так, в последующих шагах учтите соответствующие изменения. 2. Выберите каталог для распаковки дистрибутива, и сделайте его текущим. В следующем примере дистрибутив распаковывается в /usr/local. (Предполагается, что у вас есть права на создание файлов и подкаталогов внутри /usr/local. Если каталог защищен, установка должна выполняться от имени пользователя root.) shell> cd /usr/local 3. Получите дистрибутив с одного из сайтов, перечисленных в разделе 2.1.3. Для текущего выпуска бинарные дистрибутивы для всех платформ собраны из одного и того же исходного дистрибутива MySQL. 4. Распакуйте дистрибутив, их которого будет создан каталог установки. Затем создайте символическую ссылку на этот каталог: shell> gunzip < /путь/к/mysql-ВЕРСИЯ-ОС.tar.gz | tar xvf shell> In -s noMHbiu-nyTb-K-mysql-BEPCM-OC mysql
116
Глава 2. Установка MySQL Команда t a r создает каталог с именем mysql-ВЕРСИЯ-ОС. Команда In создает символическую ссылку на этот каталог. Это позволит более просто обращаться к каталогу установки - /usr/local/mysql. В случае применения программы GNU tar нет необходимости отдельно вызывать gun zip. В данной ситуации можно заменить первую строку следующей альтернативной командой для распаковки и извлечения дистрибутива: shell> tar zxvf /путь/к/mysql-ВЕРСИЯ-ОС.tar.gz
5. Перейдите в каталог установки: s h e l l > cd mysql
В этом каталоге находятся несколько файлов и подкаталогов. Самыми важными для процесса установки являются подкаталоги bin и scripts: • bin. Этот каталог содержит программы сервера и клиентские программы. Вы должны добавить полный путь к этому каталогу в переменную окружения PATH, чтобы система правильно находила программы MySQL (см. приложение Б). • scripts. Этот каталог содержит сценарий mysql_install_db, используемый для инициализации базы данных, которая хранит таблицы привилегий с информацией о привилегиях доступа к серверу. 6. Если на машине MySQL ранее не устанавливался, потребуется создать таблицы привилегий: shell> scripts/mysql_install_db --user=mysql Если сценарий запускается от имени пользователя root, необходимо использовать опцию --user, как показано выше. Значение опции должно быть именем пользователя, который был зарегистрирован на первом шаге. Если команда выполняется от имени этого пользователя, опцию —user можно не указывать. Следует обратить внимание на то, что для версий MySQL, предшествующих 3.22.10, mysql_install_db оставляет сервер в работающем состоянии после создания таблиц привилегий. Теперь это не так. Вам понадобится перезапустить сервер после выполнения оставшихся шагов этой процедуры. 7. Измените владельца бинарных программ на root, а владельца каталога данных на пользователя, от имени которого будет запускаться сервер mysqld. Если предположить, что текущим каталогом является установочный (/usr/local/mysql), команды будут выглядеть так: shell> chown -R root . shell> chown -R mysql data shell> chgrp -R mysql . Первая команда изменяет владельца файлов на root. Вторая изменяет владельца каталога данных на mysql. Третья изменяет атрибут принадлежности к группе на mysql. 8. Если нужно, чтобы сервер MySQL запускался автоматически при загрузке системы, скопируйте support-files/mysql. server в место, где находятся сценарии запуска системы. Дополнительную информацию по этому поводу можно найти в самом сценарии support-files/mysql. server, а также в разделе 2.4.3.
2.3. Установка MySQL из исходного дистрибутива
117
9. Если установлены Perl-модули DBI и DBD: :mysql, новые пользовательские учетные записи можно создавать с помощью сценарии bin/mysql_setpermission. Инструкции содержатся в разделе 2.7. 10. Если нужно использовать mysqlaccess, а дистрибутив MySQL размещен в какомто нестандартном месте, потребуется изменить местоположение, в котором mysqlaccess ищет клиент mysql. Отредактируйте сценарий bin/mysqlaccess в районе 18-й строки. Найдите строку, которая выглядит так: $MYSQL = Vusr/local/bin/mysql 1 ;
# path to mysql executable # путь к исполняемому файлу mysql
Исправьте путь, чтобы он указывал на реальное местоположение mysql в системе. Если этого не сделать, то при запуске mysqlaccess вы получите сообщение об ошибке Broken pipe (разрушенный канал). После того, как все будет распаковано и установлено, дистрибутив необходимо протестировать. Запустите сервер MySQL с помощью следующей команды: shell> bin/mysqld_safe —user=mysql & Для версий MySQL, предшествующих 4.0, замените в команде bin/mysqld_safe на bin/safe_mysqld. Дополнительную информацию о mysqld_safe можно найти в разделе 4.1.3.
|! На заметку! ^ Пользовательские учетные записи, перечисленные в таблицах привилегий MySQL, изначально Ц не имеют паролей. После запуска сервера вы должны установить для них пароли, как описано в |< разделе 2.4.
2.3. Установка MySQL из исходного дистрибутива Прежде чем приступить к установке исходных текстов, проверьте, доступен ли бинарный дистрибутив для вашей платформы и будет он у вас работать. Мы тратим очень много усилий, чтобы добиться того, чтобы наши программы были собраны наилучшим образом. Информация о том, как получить исходный дистрибутив содержится в разделе 2.1.3. Исходные дистрибутивы MySQL предоставляются в виде tar-архивов и имеют имена вроде mysql-ВЕРСИЯ, t a r . gz, где ВЕРСИЯ - номер версии, например, 5.0.0-alpha. Для сборки и установки MySQL из исходных текстов понадобятся: • Утилита GNU gun zip для распаковки дистрибутива. • Подходящая программа t a r для распаковки дистрибутива. Хорошо работает, например, GNU tar. Некоторые операционные системы поставляются вместе с предустановленными версиями утилиты tar, о которых известно, что они имеют некоторые проблемы. Например, версии t a r из комплекта Mac OS X и Sun порождают сложности при работе с длинными именами файлов. В Mac OS X можно воспользоваться предустановленной программой gnutar. В других системах с дефектными утилитами t a r сначала потребуется установить GNU tar.
118
Глава 2. Установка MySQL
• Работающий компилятор ANSI C++. Среди компиляторов, о которых известно, что они работают хорошо, можно отметить: дсс 2.95.2 или более поздний, egcs 1.0.2 или более поздний, egcs 2.91.66, SGI C++ и SunPro C++. Библиотека libg++ не потребуется для дсс. дсс 2.11.x содержит ошибку, которая делает невозможной компиляцию некоторых абсолютно корректных файлов на C++, например, sql/sql_base.cc. Если вы располагаете только компилятором дсс 2.77.x, его необходимо обновить, дабы он смог компилировать исходные тексты MySQL, gcc 2.8.1 также известен наличием проблем на некоторых платформах, поэтому его лучше избегать, особенно ^сли для этой платформы существует какой-нибудь новый компилятор. • дсс 2.95.2 или более поздней версии рекомендуется для компиляции MySQL 3.23.x. • Хорошая программа make. GNU make всегда рекомендуется, а зачастую и требуется. В случае возникновения проблем советуем воспользоваться версией GNU make 3.75 или более новой. Если вы используете достаточно новую версию компилятора дсс, чтобы она понимала опцию —fno-exceptions, очень важно, чтобы вы указывали эту опцию. В противном случае вы соберете бинарные программы, которые будут произвольно выдавать сбои. Мы также рекомендуем указывать опции —felide-constructors и — f n o - r t t i вместе с —fno-exceptions. Если сомневаетесь, воспользуйтесь следующими опциями компиляции: CFLAGS="-O3" CXX=gcc CXXFLAGS="-O3 -felide-constructors \ —fno-exceptions -fno-rtti" ./configure \ —prefix=/usr/local/mysql —enable-assembler \ —with-mysqld-ldflags=-all-static В большинстве систем такой набор опций компилятора позволит получить быстрый и надежный двоичный код. Если вы сталкиваетесь с проблемами, всегда пользуйтесь mysqlbug перед отправкой вопросов в списки рассылки MySQL. Даже если проблема не вызвана ошибкой, mysqlbug соберет информацию о системе, которая поможет нам решить проблему. Не используя mysqlbug, вы снижаете вероятность получить решение. Вы найдете mysqlbug в каталоге bin после распаковки дистрибутива. См. раздел 1.7.1.3.
2.3.1. Обзор установки из исходного дистрибутива Базовый набор команд, которые нужно выполнить для установки исходного дистрибутива: shell> groupadd mysql shell> useradd -g mysql mysql shell> gunzip < mysql-ВЕРСИЯ.tar.gz | tar -xvf shell> cd mysql-ВЕРСИЯ shell> ./configure —prefix=/usr/local/mysql shell> make shell> make install shell> cp support-files/my-medium.cnf /etc/my.cnf shell> cd /usr/local/mysql shell> bin/mysql_install_db —user=mysql
2.3. Установка MySQL из исходного дистрибутива shell> shell> shell> shell>
119
chown -R root . chown -R mysql var chgrp -R mysql . bin/mysqld_safe —user=mysql &
Для версий MySQL, предшествующих 4.0, в последней команде замените bin/mysqld_safe на bin/safe_mysqld. Если вы работаете с исходным пакетом в формате RPM, запустите такую команду: s h e l l > rpm --rebuild — c l e a n MySQL-ВЕРСИЯ.src.rpm
Приведенная команда построит бинарный RPM-модуль, который затем можно будет установить. % На заметку! £; Эта процедура не устанавливает паролей для пользовательских учетных записей MySQL. После и
выполнения описанной процедуры проделайте действия, указанные в разделе 2.4.
Ниже представлено более детальное описание процедуры установки исходного дистрибутива: 1. Добавьте пользователя и группу для запуска mysqld: shell> groupadd mysql shell> useradd -g mysql mysql Эти команды добавляют новую группу mysql и пользователя mysql. Синтаксис команд groupadd и useradd может слегка отличаться в различных версиях Unix. Команды также могут иметь названия adduser и addgroup. Вы можете назвать пользователя и группу как-то иначе вместо mysql. Если это так, в последующих шагах учтите соответствующие изменения. 2. Выберите каталог, куда необходимо распаковать дистрибутив, и сделайте его текущим. 3. Получите дистрибутив с одного из сайтов, перечисленных в разделе 2.1.3. 4. Распакуйте дистрибутив в текущий каталог: shell> gunzip < /путь/'к/mysql-ВЕРСИЯ.tar.gz | tar xvf Эта команда создаст каталог с именем mysql-ВЕРСИЯ. При использовании утилиты GNU t a r отдельного вызова gunzip не требуется. С помощью следующей команды можно сделать это в один прием: shell> tar zxvf /путь/к/mysql-ВЕРСИЯ.tar.gz 5. Перейдите в каталог верхнего уровня распакованного дистрибутива: shell> cd mysql-БЕРСЯЯ Не забывайте, что конфигурирование и сборка MySQL осуществляется только из каталога верхнего уровня. 6. Сконфигурируйте выпуск и скомпилируйте все исходные тексты:
shell> ./configure —prefix=/usr/local/mysql shell> make При запуске configure можно указывать дополнительные опции. Для получения списка доступных опций введите команду ./configure --help. В разделе 2.3.2
120
Глава 2. Установка MySQL обсуждаются некоторые из наиболее часто применяемых опций. Если выполнение configure завершилось ошибкой, и вы собираетесь отправить сообщение в список рассылки MySQL с просьбой о помощи, включите в него все строки из configure.log, которые, по вашему мнению, могут помочь решить проблему. Кроме того, поместите в сообщение несколько последних строк из configure. При отправке отчета об ошибке пользуйтесь сценарием mysqlbug. См. раздел 1.7.1.3.
7. Выполните установку дистрибутива: shell> make install Если вы хотите настроить файл опций, используйте в качестве шаблона один из тех, что представлены в каталоге support-files, например: shell> cp support-files/my-medium.cnf /etc/my.cnf Возможно, эту команду понадобится запускать от имени пользователя root. Если вы хотите настроить поддержку таблиц innoDB, отредактируйте файл /etc/my.cnf, удалив символ # в начале строк опций, которые начинаются с c innodb_...', и соответствующим образом изменив значения опций. См. разделы 3.3.2 и 9.4. 8. Перейдите в каталог установки: shell> cd /usr/local/mysql 9. Если на машине MySQL ранее не устанавливался, потребуется создать таблицы привилегий: shell> bin/mysql_install_db —user=mysql Если сценарий запускается от имени пользователя root, необходимо использовать опцию —user, как показано выше. Значение опции должно быть именем пользователя, который был зарегистрирован на первом шаге. Если команда выполняется от имени этого пользователя, опцию —user можно не указывать. Следует обратить внимание на то, что для версий MySQL, предшествующих 3.22.10, mysql_install_db оставляет сервер в работающем состоянии после создания таблиц привилегий. Теперь это не так. Вам понадобится перезапустить сервер после выполнения оставшихся шагов этой процедуры. 10. Измените владельца бинарных программ на root, а владельца каталога данных на пользователя, от имени которого будет запускаться сервер mysqld. Если предположить, что текущим каталогом является установочный (/usr/local/mysql), команды будут выглядеть так: shell> chown -R root . shell> chown -R mysql data shell> chgrp -R mysql . Первая команда изменяет владельца файлов на root. Вторая изменяет владельца каталога данных на mysql. Третья изменяет атрибут принадлежности к группе на mysql. 11. Если нужно, чтобы сервер MySQL запускался автоматически при загрузке системы, скопируйте support-files/mysql. server в место, где находятся сценарии за-
2.3. Установка MySQL из исходного дистрибутива
121
пуска системы. Дополнительную информацию по этому поводу можно найти в самом сценарии support-files/mysql. server, а также в разделе 2.4.3. 12. Если установлены Perl-модули DBI и DBD::mysql, новые пользовательские учетные записи можно создавать с помощью сценарии bin/mysql_setpermission. Инструкции содержатся в разделе 2.7. После того, как все будет распаковано и установлено, нужно протестировать дистрибутив. Запустите сервер MySQL с помощью следующей команды: shell> bin/mysqld_safe —user=mysql & Для версий MySQL, предшествующих 4.0, замените в команде bin/mysqld_safe на bin/safe_mysqld. Если выполнение этой команды немедленно прерывается с выдачей сообщения raysqld ended (mysqld завершен), некоторую информацию, касающуюся причин, можно найти в файле host_name. err, расположенном в каталоге данных. Дополнительные сведения о mysqld_safe представлены в разделе 4.1.3.
f| На заметку! || Пользовательские учетные записи, перечисленные в таблицах привилегий MySQL, изначально f* не имеют паролей. После запуска сервера вы должны установить для них пароли, как описано в Ь разделе 2.4.
2.3.2. Типичные опции сценария configure Сценарий configure обеспечивает богатые возможности управления настройкой исходного дистрибутива MySQL. Обычно это делается через опции командной строки во время его запуска. В некоторой степени им можно также управлять через переменные окружения (см. приложение Б). Получить полный список опций, которые поддерживает configure, можно следующим образом:
shell> ./configure —help Ниже описаны наиболее часто используемые опции configure. • Для того чтобы скомпилировать только клиентские программы и библиотеки, без сервера, используйте опцию --without-server. Если у вас нет компилятора C++, mysql не скомпилируется (это единственная клиентская программа, которой требуется компилятор C++). В этом случае можете удалить из configure строки, проверяющие наличие компилятора C++, и затем опять запустить его с опцией —without-server. На шаге компиляции он опять попытается выполнить сборку mysql, но вы можете игнорировать любые сообщения, касающиеся mysql.ее. (Если программа make остановится, попробуйте запустить ее с ключом -к, который указывает, что сборку нужно продолжать, даже если встречаются ошибки.) • Если требуется собрать библиотеку встроенного MySQL (libmysqld.a), используйте опцию —with-embedded-server. • Если вы не хотите, чтобы журнальные файлы и каталоги данных находились в /usr/local/var, используйте configure следующим образом:
shell> ./configure —prefix=/usr/local/mysql
122
Глава 2. Установка MySQL shell> ./configure --prefix=/usr/local \ --localstatedir=/usr/local/mysql/data Первая команда изменяет префикс установки таким образом, чтобы все, что должно было копироваться в каталог /usr/local, помещалось в каталог /usr/local/mysql. Вторая команда сохраняет префикс установки, но изменяет местоположение каталога данных, которым по умолчанию является / u s r / l o c a l / v a r , на /usr/local/mysql/data. После того, как вы скомпилируете MySQL, эти значения можно изменить в файле опций (см. раздел 3.3.2).
• Если вы работаете в среде Unix и желаете, чтобы сокет MySQL располагался в месте, отличном от принятого по умолчанию (/tmp или /var/run), запустите команду configure так, как показано ниже: shell> ./configure \ —with-unix-socket-path=/usr/local/mysql/tmp/mysql.sock Имя файла сокета должно содержать полный путь. Вы также можете позже изменить местоположение mysql. sock в файле опций (см. раздел А.4.5). • Если требуется скомпилировать программы, связанные статически (например, чтобы получить более быстрый бинарный дистрибутив или обойти проблемы, характерные для некоторых версий Red Hat Linux), запускайте configure следующим образом: shell> ./configure —with-client-ldflags=-all-static \ —with-mysqld-ldflags=-all-static • Если вы пользуетесь gcc и не имеете установленных библиотек libg++ или libstdc++, можете указать configure, что в качестве компилятора C++ должен использоваться gcc: shell> CC=gcc CXX=gcc ./configure При использовании gcc в качестве компилятора C++, он не будет пытаться выполнять связывание с библиотеками libg++ и libstdc++. Это может оказаться полезным, даже если у вас эти библиотеки установлены, поскольку некоторые их версии могут в будущем послужить причиной возникновения странных проблем у пользователей MySQL. В следующем списке перечислены некоторые компиляторы и обычно используемые с ними значения переменных окружения: • gcc 2.7.2: CC=gcc CXX=gcc CXXFLAGS="-O3 -felide-constructors" •
egcs 1.0.3a: CC=gcc CXX=gcc CXXFLAGS="-03 -felide-constructors \ -fno-exceptions -fno-rtti"
• gcc 2.95.2: CFLAGS="-O3 -mpentiumpro" CXX=gcc CXXFLAGS="-03 -mpentiumpro \ -felide-constructors -fno-exceptions -fno-rtti" • pgcc 2.90.29 или более новые: CFLAGS="-03 -mpentiumpro -mstack-align-double" CXX=gcc \
2.3. Установка MySQL из исходного дистрибутива
123
CXXFLAGS="-O3 -mpentiumpro -mstack-align-double \ -felide-constructors -fno-exceptions -fno-rtti" Во многих случаях можно получить достаточно оптимальный код MySQL, применяя опции из приведенного списка и добавляя к строке configure еще и такие опции: —prefix=/usr/local/mysql —enable-assembler \ —with-mysqld-ldflags=-all-static Другими словами, полная строка запуска configure должна принять вид, подобный показанному ниже, для всех последних версий дсс: CFLAGS="-O3 -mpentiumpro" CXX=gcc CXXFLAGS="-O3 -mpentiumpro \ -felide-constructors -fno-exceptions - f n o - r t t i " ./configure \ —prefix=/usr/local/mysql —enable-assembler \ —with-mysqld-ldflags=-all-static Все бинарные дистрибутивы, доступные на http://www.mysql.com, скомпилированы с полной оптимизацией и должны превосходно работать у большинства пользователей (см. раздел 2.1.2.5). Существуют некоторые установки конфигурации, которые помогут собрать еще более быстрые двоичные программы, однако они ориентированы только на опытных пользователей (см. раздел 6.5.3). Если сборка завершилась ошибкой, связанной с тем, что ваш компилятор или компоновщик не в состоянии создать библиотеку общего использования l i b m y s q l c l i e n t . s o . # (где ' # ' - номер версии), эту проблему можно обойти, указав configure опцию —disable-shared. В этом случае configure не будет создавать библиотеку общего использования l i b m y s q l c l i e n t . s o . #. •
Можно сконфигурировать MySQL так, чтобы он не использовал значения столбцов по умолчанию (DEFAULT) для тех из них, которым запрещено иметь значения NULL (см. раздел 1.8.6.2): s h e l l > CXXFIAGS=-DDONTJJSEJ)EFAULT_FIELDS ./configure Эффект от применения этого флага состоит в том, что любой оператор INSERT завершится ошибкой, если в нем явно не заданы значения для всех столбцов с атрибутами NOT NULL.
•
По умолчанию MySQL использует набор символов l a t i n l (ISO-8859-1). Для изменения набора символов по умолчанию служит опция - - w i t h - c h a r s e t : shell> ./configure —with-charset=Ha6op При этом набор может принимать одно из следующих значений: big5, cpl251, ср1257, czech, danish, dec8, dos, eucjtr, gb2312, gbk, germanl, hebrew, hp8, hungarian, koi8_ru, koi8_ukr, l a t i n l , Iatin2, s j i s , swe7, tis620, ujis, usa7 и winl251ukr. За дополнительной информацией обращайтесь в раздел 4.7.1. Также можно задать способ сопоставления строк по умолчанию. По умолчанию MySQL использует сопоставление строк l a t i n l _ s w e d i s h _ c i . Для изменения этого применяется опция — with-collation: shell> ./configure —with-collation=collation Чтобы изменить одновременно и набор символов и способ сопоставления, укажите обе опции —with-charset и —with-collation. Порядок сопоставления должен
124
Глава 2. Установка MySQL быть разрешенным для данного набора символов. (С помощью команды SHOW COLLATION можно просмотреть, какие порядки сопоставления для каких наборов символов допустимы.) Если вас интересует преобразование набора символов между клиентом и сервером, ознакомьтесь с оператором SET CHARACTER SET. Эта тема обсуждается в книге "MySQL. Справочник по языку".
|
Внимание!
§} Щ §| || ||
Если вы измените набор символов после создания любых таблиц, то для каждой из них потребуется выполнить myisamchk - r -q —set-character-set=Ha6op. В противном случае индексы могут быть отсортированы неправильно. (Это может случиться в ситуации, когда вы установили MySQL, создали какие-то таблицы, затем переконфигурировали MySQL для применения другого набора символов и установили повторно.)
Указывая для configure опцию — with-extra-charsets=Cn#COiC, можно определить, с поддержкой каких дополнительных наборов символов должен быть скомпилирован сервер. Здесь СПИСОК - это либо список наборов символов, разделенных пробелами, либо complex, что означает включение всех наборов символов, которые не могут быть загружены динамически, либо a l l - включение всех наборов символов в бинарный код. • Чтобы сконфигурировать MySQL с отладочной информацией, укажите опцию —with-debug: shell> ./configure —with-debug Это заставит компоновщик включить в программу безопасный распределитель памяти, который может обнаруживать некоторые ошибки и генерировать сообщения о том, что происходит. • Если ваши клиентские программы используют потоки, вы также должны скомпилировать версию, безопасную в отношении потоков, клиентской библиотеки MySQL, указав опцию конфигурации — enable-thread-safe-client. В результате будет создана библиотека libmysqlclientr, с которой можно будет компоновать потоковые приложения. • Описание опций, специфичных для отдельных платформ, можно найти в части настоящего руководства, посвященной конкретным системам (см. раздел 2.6).
2.3.3. Установка из исходного дерева разработки |
Внимание!
Ц Этот раздел имеет смысл читать только в том случае, если вы хотите оказать нам помощь в тес|| тировании нового кода. Если вам нужно только получить MySQL для запуска в своей системе, |; выгружайте стандартный дистрибутив выпуска (бинарный или исходный).
Для получения последнего дерева исходных текстов потребуется выполнить следующие шаги: 1. Загрузите BitKeeper с http://www.bitmover.com/cgi-bin/download.cgi. Для доступа к нашему репозиторию понадобится BitKeeper 3.0 или более новый. 2. Установите его в соответствии с инструкциями.
2.3. Установка MySQL из исходного дистрибутива
125
3. После установки BitKeeper перейдите в каталог, из которого вы собираетесь работать, а затем воспользуйтесь одной из приведенных ниже команд для загрузки ветви выбранной версии MySQL. Для выгрузки старой ветви 3.23: shell> bk clone bk://mysql.bkbits.net/mysql-3.23 mysql-3.23 Для выгрузки стабильной ветви 4.0: shell> bk clone bk://mysql.bkbits.net/mysql-4.0 mysql-4.0 Для выгрузки ветви 5.0, находящейся в стадии разработки: shell> bk clone bk://mysql.bkbits.net/mysql-5.0 mysql-5.0 В представленных примерах исходные деревья расположатся соответственно в подкаталогах mysql-3.23/, mysql-4.0/, mysql-4.1/ и mysql-5.0/ текущего каталога. Если вы защищены брандмауэром и имеете возможность работать только через HTTP-соединения, можно взаимодействовать с BitKeeper по протоколу HTTP. Если вам необходимо использовать прокси-сервер, установите переменную окружения http_proxy, чтобы она указывала на него: shell> export httpjproxy="http://your.proxy,server:8080/" Теперь просто замените bk: // на http: //, например: shell> bk clone http://mysql.bkbits.net/mysql-4.! mysql-4.1 Начальная загрузка дерева исходных текстов может занять довольно длительное время, в зависимости от скорости вашего соединения. В общем, наберитесь терпения. 4. Вам понадобятся GNU make, autoconf 2.53 (или более новый), automake 1.5, libtool 1.4 и m4 для запуска следующего набора команд. Несмотря на то, что многие операционные системы уже поставляются со своими собственными реализациями make, высока вероятность того, что компиляция прервется со странными сообщениями об ошибках. Поэтому мы настоятельно рекомендуем пользоваться вместо них программой GNU make (иногда называемой gmake). К счастью, многие операционные системы уже поставляются с заранее установленным набором инструментов GNU, либо же включают его инсталляционные пакеты. В любом случае, их также можно загрузить со следующих сайтов: • http://www.gnu.org/software/autoconf/ • http://www.gnu.org/software/automake/ • http://www.gnu.org/software/libtool/ • http://www.gnu.org/software/m4/ • http://www.gnu.org/software/make/ Если вы пытаетесь сконфигурировать MySQL 4.1 или более позднюю версию, вам понадобится также GNU bison 1.75 или выше. Старые версии bison могут выдавать ошибку: sql_yacc.yy:#####: fatal error: maximum table size (32767) exceeded sql_yacc.yy:#####; таблицы (32767)
критическая ошибка: превышен максимальный размер
126
Глава 2. Установка MySQL
^ Примечание! /Л На самом деле максимальный размер таблицы не превышен, а сообщение вызвано ошибкой в / старых версиях bison.
Версии MySQL, предшествующие 4.1, могут также компилироваться с другими реализациями уасс (например, BSD yacc 91.7.30). Для более новых версий необходим GNU bison. В приведенном примере представлена типичная последовательность команд, необходимая для конфигурирования исходного дерева. Первая команда cd меняет текущий каталог на корневой каталог дерева. Замените при необходимости имя каталога mysql-4.0 в аргументе команды. shell> shell> shell> shell> shell> shell> shell>
cd mysql-4.0 bk -r edit aclocal; autoheader; autoconf; automake (cd innobase; aclocal; autoheader; autoconf; automake) (cd bdb/dist; sh s_all) ./configure # Добавьте здесь необходимые опции make
Командные строки, изменяющие текущий каталог на innobase и bdb/dist, нужны для конфигурирования механизмов хранения innoDB и Berkley DB (BDB). Если вам не нужна поддержка InnoDB и BDB, эти строки можно опустить. Если вы получите какие-то непонятные сообщения об ошибках на этой стадии, проверьте, установлена ли у вас библиотека libtool. Коллекция наших стандартных конфигурационных сценариев находится в подкаталоге BUILD/. Возможно, вы сочтете более удобным запускать сценарий BUILD/compile-pentium-debug вместо приведенной выше последовательности команд. Для компиляции на другой архитектуре исправьте сценарий, удалив все флаги, специфичные для процессора Pentium. 5. Когда сборка будет завершена, введите команду make i n s t a l l . Будьте осторожны с этим на рабочей машине. Так вполне можно перезаписать актуальную установку сервера. Если у вас на машине есть другой установленный экземпляр MySQL, рекомендуется запускать ./configure с другими значениями опций —prefix, --with-tcp-port и --unix-socket-path, нежели те, которые использовались для вашего рабочего сервера. 6. Интенсивно поработайте с новой установкой, попытайтесь вызвать сбой новых средств. Начните с запуска make test. 7. Если вы дошли до стадии make и дистрибутив не компилируется, пришлите сообщение об этом в нашу базу ошибок на h t t p : //bugs .mysql. com. Если вы установили новейшие версии необходимых инструментов GNU и они терпят крах при попытке обработать наши конфигурационные файлы, сообщите и об этом тоже. Однако если вы запускаете команду aclocal и получаете в ответ not found (не найдена) или какую-то подобную ошибку, не уведомляйте об этом. Вместо этого убедитесь, что все необходимые инструменты установлены, а значение переменной окружения PATH задано таким образом, что командный интерпретатор может их найти.
2.3. Установка MySQL из исходного дистрибутива
127
8. После начальной команды bk clone, с помощью которой вы получите дерево исходных текстов, периодически выполняйте bk pull, чтобы получать обновления. 9. Вы можете просмотреть историю изменений в дереве с помощью bk revtool. Если вы обнаружите какие-то незначительные расхождения или код, который вызовет вопросы, не стесняйтесь присылать сообщения в список рассылки MySQL internals (см. раздел 1.7.1.1). Кроме того, если у вас появились лучшие идеи относительно того, как реализовать что-то, присылайте сообщение туда же, приложив к нему обновление, bk dif fs сгенерирует для вас обновление после того, как вы внесете изменения в копию исходного кода на своей машине. Если у вас нет времени воплотить свою идею в коде, просто пришлите исчерпывающее описание. 10. BitKeeper обладает неплохой утилитой справки, к которой можно обратиться с помощью команды bk helptool. И.Учтите, что любые фиксации кода (выполненные по команде bk ci или bk citool) вызовут автоматическую отправку сообщения о внесенных в код изменениях в список рассылки MySQL internals, в точности так, как происходит обычное подтверждение openloging.org, даже если изменяются только комментарии. Вообще говоря, у вас нет необходимости выполнять фиксацию (поскольку общедоступный репозиторий не позволяет выполнять bk push). Вместо этого используйте метод bk dif f s, описанный выше. Вы также можете просматривать наборы изменений кода, комментарии и сам исходный текст в онлайновом режиме. Например, чтобы просмотреть эту информацию для MySQL 4.1, зайдите на http://mysql.bkbits.net: 8080/mysql-4.1. Справочное руководство находится в отдельном дереве, которое может быть загружено с помощью следующей команды: shell> bk clone bk://mysql.bkbits.net/mysqldoc mysqldoc Существуют также общедоступные деревья BitKeeper для приложений MySQL Control Center (Центр управления MySQL) и Connector/ODBC. Они также доступны для загрузки. Чтобы загрузить MySQL Control Center, введите команду: shell> bk clone http://mysql.bkbits.net/mysqlcc mysqlcc Для загрузки Connector/ODBC воспользуйтесь командой: shell> bk clone http://mysql.bkbits.net/myodbc3 myodbc3
2.3.4. Решение проблем компиляции MySQL Все программы MySQL компилируются в системах Linux и Solaris с использованием компилятора дсс без каких-либо предупреждений и ошибок. В других системах во время компиляции могут возникать некоторые предупреждения из-за разницы во включаемых системных файлах заголовков. В разделе 2.3.5 приведена информация о предупреждениях, которые могут возникать при использовании потоков MIT-pthreads. О других проблемах компиляции рассказывается ниже. Решение многих проблем может предполагать переконфигурирование. Если в этом есть необходимость, примите во внимание следующие моменты: • Если configure запускается после того, как уже запускался, он может использовать информацию, собранную во время предыдущего вызова. Эта информация
128
Глава 2. Установка MySQL помещается в файл config. cache. Когда сценарий configure стартует, он выполняет поиск этого файла. Если файл найден, configure читает его содержимое, предполагая, что собранная ранее информация корректна. Это предположение ошибочно, если необходимо выполнить переконфигурирование.
• Каждый раз после запуска configure необходимо снова запустить make для перекомпиляции. Однако имеет смысл удалить старые объектные файлы, оставшиеся после предыдущей сборки, прежде всего потому, что они были скомпилированы с использованием других конфигурационных опций. Для предотвращения использования устаревшей конфигурационной информации или объектных файлов, выполняйте приведенные ниже команды перед каждым перезапуском configure: shell> rm config.cache shell> make clean В качестве альтернативы можно запустить make distclean. В следующем списке перечислены проблемы, которые возникают наиболее часто во время компиляции MySQL. • Если во время компиляции s q l y a c c . c c вы получаете сообщения об ошибках вроде тех, что показаны ниже, это означает, что, скорее всего, превышен лимит использования памяти или пространства подкачки:
Internal compiler error: program cclplus got fatal signal 11 Внутренняя ошибка компилятора: программа cclplus получила фатальный сигнал 11 Out of v i r t u a l memory Яе хватает виртуальной памяти Virtual memory exhausted Виртуальная память исчерпана Проблема состоит в том, что дсс требует огромного объема памяти для компиляции sql_yacc.cc со встроенными функциями. Попробуйте запустить configure с опцией —with-low-memory: shell> ./configure —with-low-memory Эта опция требует также дополнительного указания опции —f no-inline, если вы применяете дсс, и -00 - если другой компилятор. Стоит попробовать задать —with-low-memory, даже если у вас много памяти и пространства подкачки, и вы уверены, что не столкнетесь с упомянутой проблемой. Возникновение этой проблемы наблюдалось даже на машинах с большим объемом ресурсов, при этом указание опции —with-low-memory обычно решало ее. • По умолчанию configure выбирает в качестве имени компилятора с++, который выполняет компоновку с -lg++. Если вы используете дсс, это поведение может привести к проблемам во время конфигурирования:
configure: error: installation or configuration problem: C++ compiler cannot create executables.
configure: ошибка: проблема установки или конфигурации: компилятор C++ не может создавать исполняемые файлы.
2.3. Установка MySQL из исходного дистрибутива
129
Вы также можете столкнуться с проблемами во время компиляции, которые связаны с g++, libg++ или libstdc++. ОДНОЙ ИЗ причин возникновения этих проблем может быть то, что у вас может отсутствовать д++, либо у вас имеется д++, но нет libg++ или libstdc++. Просмотрите файл conf ig. log. Он должен содержать точное объяснение причины, почему компилятор C++ не работает. Для обхода этих проблем можно выбрать дсс в качестве компилятора C++. Попробуйте присвоить переменной окружения СХХ значение дсс -03: shell> CXX="gcc -03"
./configure
Это работает потому, что дсс компилирует исходные тексты на C++ так же, как и д++, но не выполняет по умолчанию компоновку с библиотеками libg++ и libstdc++. Другой способ решения этой проблемы предполагает установку g++, libg++ и libstdc++. Однако, м ы рекомендуем отказаться от применения библиотек libg++ и libstdc++ вместе с M y S Q L , поскольку это только увеличивает размер mysqld, не принося какой-либо выгоды. Некоторые версии этих библиотек в прошлом служили причиной непонятных проблем у пользователей M y S Q L . Применение дсс в качестве компилятора C + + также необходимо, если вы хотите скомпилировать M y S Q L с поддержкой функциональности R A I D и вы используете дсс версии 3 и выше. Если при конфигурации с опцией —width-raid на стадии компоновки вы получаете сообщения об ошибках вроде тех, что приведены выше, попробуйте использовать дсс в качестве компилятора C++, указав его в переменной окружения СХХ: дсс -03 -DDBUG_OFF -rdynamic -о isamchk isamchk.o sort.о libnisam.a ../mysys/libmysys.a ../dbug/libdbug.a ../strings/libmystrings.a -Ipthread -lz -lcrypt -lnsl -lm -lpthread ../mysys/libmysys.a(raid.o)(.text+0x79): In function "my_raid_createf:: undefined reference to "operator new(unsigned)' ../mysys/libmysys.a(raid.o)(.text+Oxdd): In function 4 my_raid_create':: undefined reference to "operator delete(void*)' ../mysys/libmysys.a(raid.o)(.text+0xl29): In function "my_raid_openf:: undefined reference to "operator new(unsigned)' ../mysys/libmysys.a(raid.o)(.text+0xl89): In function "my raid open1:: undefined reference to "operator delete(void*)' ../mysys/libmysys.a(raid.o)(,text+0x64b): In function "my_raid_close':: undefined reference to "operator delete(void*)' collect2: Id returned 1 exit status • Если компиляция прерывается с выдачей сообщений об ошибках, которые показаны ниже, потребуется обновить свою версию make до G N U make. making all in mit-pthreads make: Fatal error in reader: Makefile, line 18: Badly formed macro assignment или make: file "Makefile' line 18: Must be a separator (: или pthread.h: No such file or directory
130
Глава 2. Установка MySQL
Известно, что в средах Solaris и FreeBSD приходится сталкиваться с некоторыми проблемами, связанными с make. С другой стороны, программа GNU make версии 3.75 зарекомендовала себя достаточно хорошо. • Если вы хотите определить флаги для использования с компиляторами С и C++, добавляйте их к переменным окружения CFLAGS и CXXFLAGS. Таким же способом можно задать имена компиляторов - через переменные СС и СХХ. Например: shell> shell> shell> shell> shell>
CC=gcc CFLAGS=-O3 CXX=gcc CXXFLAGS=-O3 export CC CFLAGS CXX CXXFLAGS
В разделе 2.1.2.5 представлен список флагов, применяемых в различных системах. • Если вы получите сообщение об ошибке, подобное показанному ниже, вам придется обновить компилятор: client/libmysql.c:273: parse error before N attribute ' client/libmysql.с:273: ошибка анализа перед ч атрибут ' Известно, что дсс 2.8.1 работает, но м ы рекомендуем вместо него пользоваться дсс 2.95.2 или egsc 1.0.3а. •
Если во время компиляции mysqld вы получаете ошибки вроде приведенных ниже, это значит, что configure не может корректно распознать последний аргумент accept(), getsockname() или getpeername(): схх: Error: mysqld.cc, line 645: In this statement, the referenced type of the pointer value ''length1' is ''unsigned long 1 1 , which is not compatible with ''int1'. new_sock = accept(sock, (struct sockaddr *)&cAddr, &length); Чтобы исправить это, отредактируйте файл config.h (сгенерированный configure). Найдите следующие строки: /* Define as the base type of the last arg to accept */ /* Определить в качестве базового типа для последнего аргумента */ #define SOCKET__SIZE_TYPE XXX Измените XXX на s i z e t или int, в зависимости от вашей операционной системы. (Помните, что вам придется это делать после каждого запуска configure, поскольку этот сценарий все время перезаписывает config.h.)
• Файл sql_yacc.cc генерируется из sql_yacc.yy. Обычно процесс сборки не нуждается в пересоздании sqlyacc.ee, потому что MySQL поставляется с готовой копией. Однако если вам понадобится пересоздать его, вы можете столкнуться с такой ошибкой: "sql_yacc.yy", line xxx f a t a l : default action causes p o t e n t i a l . . . Это знак того, что ваша версия уасс дефектна. Возможно, потребуется установить bison (версию уасс от GNU) и пользоваться ею.
2.3. Установка MySQL из исходного дистрибутива
131
•
В среде Debian Linux 3.0 вам нужно установить gawk вместо поставляемой по умолчанию mawk, если вы хотите компилировать MySQL 4.1 и выше с поддержкой Berkley DB.
•
Если необходимо отлаживать mysqld или клиенты MySQL, запустите configure с опцией —with-debug, затем перекомпилируйте и скомпонуйте ваши программы с новой клиентской библиотекой.
•
Если во время компиляции в среде Linux (например, SuSE Linux 8.1 или Red Hat Linux 7.3) выдаются сообщения об ошибках, похожие на следующие: libmysql.c:1329: warning: passing arg 5 of 4 gethostbyname_r' from incompatible pointer type libmysql.c:1329: too few arguments to function 4 gethostbyname_r' libmysql.c:1329: warning: assignment makes pointer from integer without a cast make[2]: *** [libmysql.lo] Error 1 то это вызвано тем, что по умолчанию сценарий configure пытается определить правильное число аргументов, используя компилятор C++ GNU g++. Эта проверка дает неверные результаты, если не установлен д++. Существуют два способа обойти эту проблему: •
Необходимо убедиться, что д++ из комплекта GNU C++ установлен. В некоторых дистрибутивах Linux требуемый пакет называется дрр, в других - дсс-с++.
•
Следует использоваться дсс в качестве компилятора C++, следующим образом установив значение переменной окружения СХХ: export CXX="gcc"
Не забудьте после этого перезапустить configure.
2.3.5. Замечания по поводу потоков MIT-pthreads Этот раздел касается некоторых вопросов, связанных с использованием потоков MITpthreads. В операционных системах Linux вы не должны использовать потоки MIT-p threads. Вместо них нужно работать с установленными реализациями LinuxThreads. См. раздел 2.6.1. Если ваша система не обладает встроенной поддержкой потоков, вам придется выполнять сборку MySQL с использованием пакета MIT-p threads. Это касается старых систем FreeBSD, SunOS 4.x, Solaris 2.4 и предшествующих версий, а также ряда других систем (см. раздел 2.1.1). Начиная с MySQL 4.0.2, MIT-pthreads больше не являются частью исходных дистрибутивов. Если вам нужен этот пакет, его придется загрузить отдельно http://www.mysql.com/Downloads/Contrib/pthreads-l_60_beta6-mysql.tar.gz. После загрузки извлеките исходный архив в корневой каталог исходных текстов MySQL. При этом будет создан новый подкаталог с именем m i t - p t h r e a d s . •
В большинстве систем можно принудительно использовать MIT-pthreads, запустив configure с опцией —with-mit-pthreads: shell> ./configure —with-mit-threads
132
Глава 2. Установка MySQL Сборка в каталогах, не относящихся к исходному дистрибутиву, не поддерживается при использовании MIT-pthreads, поскольку мы стремимся минимизировать изменения, вносимые в этот код.
•
Проверка того, где должны использоваться MIT-pthreads, происходит только во время процесса конфигурирования, имеющего отношение к коду сервера. Если вы сконфигурировали дистрибутив с опцией —without-server, чтобы собирать только клиентский код, программы-клиенты не знают, где использовать MITpthreads и будут по умолчанию открывать соединения через Unix-сокеты. А так как файлы Unix-сокетов не работают под MIT-pthreads на некоторых платформах, это означает, что вам придется запускать клиентские программы с ключами -h или — h o s t .
•
Когда MySQL компилируется с MIT-pthreads, системная блокировка по умолчанию отключается из соображений, связанных с производительностью. Вы можете заставить сервер применять системную блокировку с помощью опции —external-locking. Это может понадобиться только в случае, если вы хотите запускать два сервера MySQL для одних и тех же файлов данных, что не рекомендуется.
•
Иногда вызов bind () pthread-потока не может связаться с сокетом без сообщений об ошибках (по крайней мере, в среде Solaris). В результате все попытки соединения с сервером оказываются неудачными: s h e l l > mysqladmin version mysqladmin: connect to server at ? l failed; e r r o r : 'Can't connect to mysql server on localhost
(146)'
Решением может быть останов и перезапуск сервера mysqld. У нас это получалось, только если сервер останавливался и перезапускался немедленно. •
При использовании MIT-pthreads системный вызов s l e e p () не может быть прерван с помощью сигнала SIGINT (прервать). Об этом стоит помнить, только если вы запускаете mysqladmin — s l e e p . Вы должны ожидать завершения вызова s l e e p (), прежде чем прерывание отработает и процесс остановится.
•
Во время компоновки вы можете получить предупреждения, подобные показанным ниже (как минимум, в среде Solaris), которые можно игнорировать: Id: warning: symbol v _iob' has differing sizes: (file /my/local/pthreads/lib/libpthread.a(findfp.o) value=0x4; f i l e /usr/lib/libc.so value=0xl40); /my/local/pthreads/lib/libpthread.a(findfp.o) definition taken Id: warning: symbol ч iob 1 has differing s i z e s : (file /my/local/pthreads/lib/libpthread.a(findfp.o) value=0x4; f i l e /usr/lib/libc.so value=0xl40); /my/local/pthreads/lib/libpthread.a(findfp.o) definition taken
•
Ряд других предупреждений также можно проигнорировать: i m p l i c i t d e c l a r a t i o n of function i m p l i c i t d e c l a r a t i o n of function
•
4 4
int s t r t o l l ( . . . ) ' int strtoul(...)'
Мы не смогли заставить r e a d l i n e работать с MIT-pthreads (Вообще говоря, настоятельной необходимости в этом нет, но, возможно, кому-то будет интересно.)
2.3. Установка MySQL из исходного дистрибутива
133
2.3.6. Установка MySQL из исходных дистрибутивов под Windows В этом разделе описывается сборка бинарного дистрибутива MySQL версии 4.1 и выше под Windows. Приводятся инструкции по сборке из стандартного исходного дистрибутива или из дерева репозитория BitKeeper, содержащего самые последние версии исходных текстов. ;
На заметку!
Г ; у *
Инструкции, предложенные в настоящем разделе, предназначены строго для тех пользователей, которые хотят протестировать MySQL под Windows, собранный из исходного дистрибутива или же из дерева BitKeeper. Для производственного использования компания MySQL AB не советует применять сервер MySQL, самостоятельно собранный вами из исходных текстов. Обычно лучше воспользоваться заранее скомпилированным бинарным дистрибутивом MySQL, собранным 7, MySQL AB специально для обеспечения оптимальной производительности в среде Windows. Ин;, струкции по установке бинарного дистрибутива можно найти в разделе 2.2.1.
Для сборки MySQL под Windows вам понадобятся следующий компилятор и ресурсы, доступные в системе Windows: • Компилятор VC++ 6.0 (обновленный с использованием пакетов обновлений Service Pack 4 и Service Pack 5, а также пакета препроцесора). Пакет препроцессора необходим макроассемблеру. Дополнительную информацию можно найти по адресу: http://msdn.microsoft.com/vstudio/downloads/updates/sp/vs6/sp5/faq.aspx. • Около 45 Мбайт дискового пространства. • 64 Мбайт оперативной памяти. Вам также понадобится исходный дистрибутив MySQL для Windows. Существуют два способа получить исходный дистрибутив MySQL 4.1 и выше: 1. Получить исходный дистрибутив, упакованный компанией MySQL AB для конкретной версии MySQL, в которой вы заинтересованы. Предварительно упакованные исходные дистрибутивы версий официальных релизов MySQL доступны для загрузки по адресу http://dev.mysql.com/downloads. 2. Подготовить исходный дистрибутив самостоятельно из последнего дерева исходных текстов, хранящихся в репозитории BitKeeper. Если вы планируете поступить так, вам придется создать пакет в системе Unix, а затем перенести его в среду Windows. (Причина состоит в том, что некоторые шаги конфигурирования и сборки требуют использования инструментов, которые доступны только в Unix.) Подход с BitKeeper требует наличия: • системы на базе Unix или Linux; • установленного в этой системе BitKeeper 3.0. Его можно получить по адресу http://www.bitkeeper.com. Если у вас имеется исходный дистрибутив для Windows, вы можете перейти непосредственно к разделу 2.3.6.1. Для сборки из дерева BitKeeper обратитесь к разделу 2.3.6.2. Если вы обнаружите, что что-то не работает, как ожидалось, или у вас есть предложения по усовершенствованию текущего процесса сборки под Windows, присылайте свои предложения в список рассылки Win32 (см. раздел 1.7.1.1).
Глава 2. Установка MySQL
134 2.3.6.1. Сборка MySQL с использованием VC++ Щ На заметку!
Ц Файлы рабочих пространств VC++ для MySQL 4.1 и выше, тестируются персоналом MySQL AB Щ перед выходом каждого выпуска, и совместимы с Microsoft Visual Studio 6.0 и выше (7.0/.NET). Для сборки MySQL выполните следующие шаги: 1. Создайте рабочий каталог (например, С: \workdir). 2. Распакуйте исходный дистрибутив в упомянутый каталог с помощью WinZip или другого инструмента Windows, который может читать zip-файлы. 3. Запустите компилятор VC++ 6.0. 4. В меню File (Файл) среды VC++ выберите пункт Open Workspace (Открыть рабочее пространство). 5. Откройте файл рабочего пространства mysql.dsw, который находится в упомянутом выше каталоге. 6. В меню Build (Сборка) выберите пункт Set Active Configuration (Установить активную конфигурацию). 7. Выберите в диалоговом окне mysqld - Win32 и щелкните на кнопке ОК. 8. Нажмите клавишу для запуска сборки отладочной версии сервера, библиотек и набора клиентских приложений. 9. Аналогичным образом скомпилируйте окончательную версию. 10. Отладочные версии программ и библиотек помещаются в каталоги client_debug и lib_debug. Окончательные версии, соответственно, в c l i e n t _ r e l e a s e и l i b r e l e a s e . Если вы хотите собрать и отладочные и окончательные версии, выберите в меню Build пункт Build All (Собрать все). 11. Протестируйте сервер. Сервер, собранный по указанным выше инструкциям, предполагает, что базовым каталогом MySQL и каталогом данных будут по умолчанию, соответственно, C:\mysql и C:\mysql\data. Если вы хотите тестировать сервер, используя корневой каталог исходного дерева и его каталог данных, об этом нужно будет сообщить серверу. Это можно сделать либо с помощью опций командной строки —basedir и —datadir, либо поместить соответствующие опции в файл настроек (файл my.ini в каталоге Windows или файл С:\my.cnf). Если вы хотите использовать каталог данных, расположенный где-либо еще, укажите его путь. 12. Запустите сервер из каталога client_release или client_debug, в зависимости от того, какой сервер необходимо использовать. Общие инструкции по запуску сервера содержатся в разделе 2.2.1. Вам надо соответствующим образом адаптировать инструкцию, если применяется другой базовый каталог и каталог данных. 13. Когда сервер запущен на основе указанной вами конфигурации в виде автономного приложения или службы, попытайтесь подключиться к нему из интерактивной утилиты командной строки mysql, которая расположена в вашем каталоге client_release или client__debug. Как только вы убедитесь, что собранные вами программы функционируют корректно, остановите сервер. Затем установите MySQL, как описано ниже.
2.3. Установка MySQL из исходного дистрибутива
135
1. Создайте систему каталогов, куда MySQL должен быть установлен. Например, для установки в каталог С: \mysql потребуется выполнить следующие команды: С:\> С:\> С:\> С:\> С:\>
mkdir mkdir mkdir mkdir mkdir
C:\mysql C:\mysql\bin C:\mysql\data С:\mysql\share C:\mysql\scripts
Если вы хотите скомпилировать другие клиентские программы и присоединить их к MySQL, нужно будет создать еще несколько дополнительных каталогов: С:\> mkdir C:\mysql\include С:\> mkdir C:\mysql\lib С:\> mkdir C:\mysql\lib\debug С:\> mkdir C:\mysql\lib\opt Если вы хотите проводить тестирование производительности MySQL, создайте еще один каталог: С:\> mkdir C:\mysql\sql-bench Тестирование производительности требует поддержки языка Perl. 2. Из каталога workdir скопируйте в С: \mysql содержимое следующих подкаталогов: С:\> cd \workdir C:\workdir> copy client_release\*.exe C:\mysql\bin С:\workdir> copy client_debug\mysqld.exe С:\mysql\bin\mysqld-debug.exe C:\workdir> xcopy scripts\*.* C:\mysql\scripts /E C:\workdir> xcopy share\*.* C:\mysql\share /E Если вы хотите компилировать другие клиентские программы и подключать их к MySQL, нужно будет также скопировать некоторые библиотеки и файлы заголовков: C:\workdir> copy lib_debug\mysqlclient.lib C:\mysql\lib\debug C:\workdir> copy lib_debug\libmysql.* C:\mysql\lib\debug C:\workdir> copy lib_debug\zlib.* C:\mysql\lib\debug C:\workdir> copy lib_release\mysqlclient.lib C:\mysql\lib\opt C:\workdir> copy lib_release\libmysql.* C:\mysql\lib\opt C:\workdir> copy lib_release\zlib.* C:\mysql\lib\opt C:\workdir> copy include\*.h C:\mysql\include C:\workdir> copy libmysql\libmysql.def C:\mysql\include Если планируется проводить тестирование производительности MySQL, необходимо выполнить следующую команду: C:\workdir> xcopy sql-bench\*.* C:\mysql\bench /Е Установите и запустите сервер точно так же, как вы это делали для бинарного дистрибутива (см. раздел 2.2.1).
2.3.6.2. Создание исходного пакета для Windows из текстов, находящихся в разработке Чтобы создать исходный пакет для Windows из дерева, хранящегося в репозитории BitKeeper, воспользуйтесь следующими инструкциями. Обратите внимание, что эта процедура может быть выполнена на машинах под управлением Unix или Unix-подобной операционной системы. Так, например, известно, что она хорошо работает в среде Linux.
136
Глава 2. Установка MySQL
1. Загрузите исходное дерево MySQL (версии 4.1 или выше) из репозитория BitKeeper. Более подробная информация о том, как загружать исходное дерево, находится в разделе 2.3.3. 2. Сконфигурируйте и соберите дистрибутив. Сделать это можно с помощью следующей команды в корневом каталоге исходного дерева: shell> ./BUILD/coinpile-pentium-max 3. После того, как убедитесь, что процесс сборки завершился успешно, запустите следующий сценарий из корневого каталога исходного дерева: shell> ./scripts/make_win_src_distribution Этот сценарий создает исходный пакет для Windows. Сценарию можно указать различные опции, в соответствии с вашими потребностями: •
—help. Отобразить справочную информацию.
•
—debug. Выводить информацию о выполняемых операциях, не создавая пакета.
•
— dirname. Имя каталога для копирования файлов (промежуточного).
•
—silent. He выводить список обрабатываемых файлов.
•
--suffix. Суффикс имени пакета.
•
—tar. Создавать пакет . t a r . gz вместо .zip.
• —trap. Расположение временных файлов. По умолчанию сценарий make_win_src_distribution создает архив в формате Zip с именем mysql-BEPCH#-win-src.zip, где ВЕРСИЯ представляет номер версии MySQL исходного дерева. 4. Скопируйте или загрузите полученный исходный пакет на Windows-машину. Чтобы затем скомпилировать его, ознакомьтесь с инструкциями в разделе 2.3.6.1.
2.3.7. Компиляция клиентских программ MySQL под Windows В исходных файлах необходимо включить файл my_global.h перед mysql .h: #include <my_global.h> #include <mysql.h> myglobal.h включает все другие заголовочные файлы, необходимые для достижения совместимости с Windows (такие как windows.h), если вы компилируете программы для Windows. Скомпоновать свой код можно либо с динамической библиотекой libmysql.lib, которая служит оболочкой для загрузки libmysql .dll по требованию, либо со статической библиотекой mysqlclient. lib. Клиентские библиотеки MySQL компилируются с поддержкой потоков, поэтому вы должны также компилировать код, как многопоточный.
2.4. Настройки и тестирование после установки После установки MySQL остается еще ряд вещей, которые потребуется сделать. Например, в среде Unix вы должны инициализировать каталог данных и создать таблицы привилегий. На всех платформах важным обстоятельством, имеющим отношение к безопасности, является то, что начальные пользовательские учетные записи в MySQL не
2.4. Настройки и тестирование после установки
137
имеют паролей. Вы должны незамедлительно присвоить им пароли, дабы предотвратить неавторизованный доступ к серверу MySQL. В следующих разделах описаны постустановочные процедуры, которые специфичны для систем на базе Windows и Unix. Следующий раздел 2.4.4 касается всех платформ. Он объясняет, что делать, если доводится сталкиваться с проблемами во время запуска сервера. Раздел 2.4.5 также относится ко всем платформам. Вы должны выполнить инструкции этого раздела, чтобы гарантировать правильную защиту пользовательских учетных записей MySQL за счет установки для них паролей. Когда вы будете готовы к регистрации новых пользователей, можете ознакомиться с информацией о системе контроля доступа MySQL и управлении учетными записями (см. разделы 4.4 и 4.5).
2.4.1. Постустановочные процедуры под Windows В среде Windows каталог данных и таблицы привилегий создавать не нужно. Дистрибутив MySQL для Windows включает в себя таблицы привилегий с заранее установленными начальными пользовательскими учетными записями в базе данных mysql, находящейся в каталоге данных. Однако им потребуется назначить пароли. То, как это делается, описано в разделе 2.4.5. До установки паролей вы можете попробовать запустить некоторые клиентские программы, дабы убедиться, что вы можете подключаться к серверу и что он работает правильно. Убедившись в том, что сервер работает (см. раздел 2.2.1.5), выполните приведенные ниже команды, чтобы проверить, можете ли вы получать информацию от сервера. Вывод должен выглядеть примерно так, как показано ниже: С:\> C:\mysql\bin\mysqlshow I Databases | + + I mysql | I test I + +
С:\> C:\mysql\bin\mysqlshow mysql Database: mysql I Tables +
| +
I columns_priv I db I func host tables_priv user | + + C:\> C:\mysql\bin\mysql -e "SELECT Host,Db,User FROM db" mysql | host | db I %
| user |
| test% |
|
138
Глава 2. Установка MySQL
Если вы имеете дело с версией Windows, которая поддерживает службы, и хотите, чтобы MySQL запускался автоматически при старте Windows, обратитесь в раздел 2.2.1.7 за более детальной информацией.
2.4.2. Постустановочные процедуры под Unix После установки MySQL на Unix вам необходимо инициализировать таблицы привилегий, запустить сервер и убедиться в корректном его функционировании. Возможно, будет произведена настройка сервера таким образом, чтобы он стартовал и останавливался автоматически при запуске и останове системы. Вы также должны присвоить пароли учетным записям, содержащимся в таблицах привилегий. Таблицы привилегий в Unix устанавливаются программой mysql_install_db. При некоторых методах установки эта программа запускается автоматически: • Если вы устанавливаете MySQL под Linux, используя дистрибутив в форме пакета RPM, то сервер RPM запускает mysql_install_db. •
Если вы устанавливаете MySQL под Mac OS X, используя дистрибутив PKG, установщик также запускает mysql_install_db.
Во всех остальных случаях m y s q l i n s t a l l d b должен запускаться вручную. Следующая процедура описывает инициализацию таблицы привилегий (если это еще не было сделано) и последующий запуск сервера. Она также предлагает некоторые команды, которые можно использовать для тестирования сервера, чтобы убедиться в его правильной работе. Информацию об автоматическом запуске и останове сервера можно найти в разделе 2.4.3. После того, как вы завершите процедуру и получите функционирующий сервер, вы должны присвоить пароли учетным записям, созданным mysql_install_db. О том, как это сделать, рассказывается в разделе 2.4.5. В приведенных здесь примерах сервер запускается под идентификатором пользовательской учетной записи mysql. Предполагается, что упомянутая учетная запись существует. Либо создайте ее, если ее еще нет, либо подставьте имя другой учетной записи, с использованием которой вы собираетесь запускать сервер. 1. Измените текущий каталог на корневой каталог вашей установки MySQL, представленный здесь как БА30ВЫЙ_КАТАЛ0Г: shell> cd БА30ВЫЙ_КАТАЛ0Г По всей видимости, БА30ВЫЙ_КАТАЛ0Г будет чем-то вроде /usr/local/mysql или /usr/local. При выполнении следующих шагов предполагается, что вы находитесь в этом каталоге. 2. Если необходимо, запустите сценарий mysql_install_db, чтобы установить начальное содержимое таблиц привилегий, в которых находится информация о том, какие привилегии каким пользователям предоставляются для подключения к серверу. Это необходимо делать, если применяется дистрибутив, который не выполняет данное действие автоматически. Обычно mysql_install_db должен запускаться только один раз - при первой установке MySQL, поэтому можете пропустить этот шаг, если выполняется модернизация существующей установки. mysql_install_db не перезаписывает существующие таблицы привилегий, поэтому запускать его не опасно в любом случае. Чтобы инициализировать таблицы привилегий, воспользуйтесь одной из двух команд,
2.4. Настройки и тестирование после установки
139
приведенных ниже, в зависимости от того, где находится mysqlinstalldb - в подкаталоге bin или scripts: shell> bin/mysql_install_db —user=mysql shell > scripts /my sql_install_db —user=mysql Сценарий mysql_install_db создает каталог данных, базу данных mysql, которая содержит информацию обо всех привилегиях, и базу данных test, которую можно использовать для тестирования MySQL. Этот сценарий также создает записи в таблице привилегий для учетной записи root и анонимных учетных записей. Эти учетные записи изначально не имеют паролей. Описание их начальных привилегий можно найти в разделе 2.4.5. Привилегии позволяют учетной записи MySQL с именем root делать все что угодно, а остальным - создавать или использовать базу данных под названием t e s t или начинающуюся на t e s t . Важно убедиться, что каталоги баз данных и файлы принадлежат пользовательской учетной записи операционной системы mysql, чтобы сервер имел доступ по чтению и записи в эти каталоги позже, когда он будет запущен. Чтобы гарантировать это, при запуске сценария mysql_install_db должна указываться опция —user, если вы запускаете его от имени root. В противном случае он должен запускаться после входа в систему с использованием учетной записи mysql; тогда опцию —user можно опустить. mysql__install_db создает в базе данных mysql несколько таблиц: user, db, host, tables_priv, columns_priv, func и, возможно, ряд других, в зависимости от версии MySQL. Если вам не нужна база данных test, можете ее удалить с помощью команды mysqladmin -u root drop t e s t после старта сервера. В случае возникновения проблем с m y s q l i n s t a l l d b обратитесь в раздел 2.4.2.1 за пояснениями. Существуют некоторые альтернативы запуску сценария m y s q l i n s t a l l d b , как это предлагает дистрибутив MySQL: • Если вам нужны начальные привилегии, отличающиеся от устанавливаемых по умолчанию, можете модифицировать mysql_install_db перед его запуском. Однако гораздо предпочтительнее использовать операторы GRANT и REVOKE уже после того, как таблицы привилегий настроены. Другими словами, вы можете запустить m y s q l i n s t a l l d b , а потом с помощью mysql -u root mysql подключиться к серверу MySQL от имени учетной записи root и предоставить или отозвать требуемые привилегии. Если необходимо установить MySQL на множество машин с одними и теми же привилегиями, можете поместить операторы GRANT и REVOKE в файл, и потом выполнять его как сценарий с помощью mysql после запуска mysql_install_db. Например: shell> bin/mysql_install_db —user=mysql shell> bin/mysql -u root < ваш_файл_сценария Поступая подобным образом, вы избегаете необходимости вводить показанные операторы вручную на каждой машине.
Глава 2. Установка MySQL
140
• Существует возможность заново создать таблицы привилегий после того, как они были созданы. Это может понадобиться, если во время изучения операторов GRANT и REVOKE было внесено настолько много изменений после выполнения mysql_install_db, что проще все очистить и создать заново. Чтобы пересоздать таблицы привилегий, удалите все файлы . frm, .MYI и .MYD из каталога, содержащего базу данных mysql (это каталог с именем mysql, который расположен внутри каталога данных, выводимого в качестве значения datadir при выполнении команды mysqld --help). После этого запустите сценарий mysql_install_db заново.
|
На заметку!
Jf? Для версий MySQL, предшествующих 3.22.10, вы не должны удалять файлы . f r m . Если вы неff преднамеренно сделаете это, скопируйте их обратно в каталог mysql из дистрибутива MySQL до || запуска m y s q l _ i n s t a l l _ d b .
• mysqld можно запустить вручную с опцией —skip-grant-tables и добавить нужные привилегии с использованием mysql: shell> bin/mysqld_safe —user=mysql —skip-grant-tables & shell> bin/mysql mysql Из среды mysql выдайте команды SQL, содержащиеся в сценарии mysql_install_db. He забудьте затем запустить mysqladmin flush-privileges или mysqladmin reload, чтобы заставить сервер перечитать таблицы привилегий. Помните, что если вы не пользуетесь сценарием mysql_install_db, то не только должны будете заполнить таблицы привилегий вручную, но еще и предварительно создать их. 3. Запустите сервер MySQL: shell> bin/mysqldjsafe —user=mysql & Для версий MySQL, предшествующих 4.0, замените bin/mysqld_safe на bin/safe_mysqld. Важно, чтобы сервер MySQL запускался от имени учетной записи непривилегированного пользователя (не root). Для этого при запуске mysql_safe от имени root необходимо указать опцию —user. Если же сценарий запускается от имени пользователя mysql, опцию —user можно опустить. Дополнительную информацию о запуске MySQL от имени непривилегированного пользователя можно найти в разделе А.3.2. Если вы пренебрегаете созданием таблиц привилегий до выполнения этого шага, то при попытке запуска сервера в журнале ошибок появится следующее сообщение: mysqld: Can't find f i l e : 'host.frm 1 mysqld:
Невозможно найти файл:
'host.frm1
Если вы столкнетесь с какими-то другими проблемами во время запуска сервера, просмотрите раздел 2.4.4. 4. Воспользуйтесь mysqladmin для проверки функционирования сервера. Приведенные ниже команды обеспечивают проверку, запущен ли сервер и отвечает ли он на запросы соединений:
2.4. Настройки и тестирование после установки
141
shell> bin/mysqladmin version shell> bin/mysqladmin variables Вывод команды mysqladmin version слегка отличается от платформы к платформе и от версии к версии MySQL, но должен быть подобен показанному ниже: shell> bin/mysqladmin version mysqladmin Ver 8.40 Distrib 4.0.18, for linux on i586 Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB This software comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to modify and redistribute it under the GPL license Server version 4.0.18-log Protocol version 10 Connection Localhost via Unix socket TCP port 3306 UNIX socket /tmp/mysql.sock Uptime: 16 sec Threads: 1 Questions: 9 Slow q u e r i e s : 0 Opens: 7 Flush t a b l e s : 2 Open t a b l e s : 0 Queries per second avg: 0.000 Memory in u s e : 132K Max memory used: 16773K Чтобы посмотреть, что еще можно делать с помощью mysqladmin, запустите его с ключом --help. 5. Проверьте, можете ли вы остановить сервер: shell> bin/mysqladmin -u root shutdown 6. Проверьте, можете ли вы перезапустить сервер. Делайте это с использованием mysqld_saf e или вызывая mysqld непосредственно, например: shell> bin/mysqld_safe —user=mysql —log & Если mysqld_saf e не работает, обратитесь в раздел 2.4.4. 7. Выполните некоторые простые тесты, чтобы убедиться в возможности получения информации от сервера. Вывод должен быть похож на приведенный ниже: С: \> С: \mysql\bin\mysqlshow + + | Databases | + + I mysql | I test ! + + С:\> C:\mysql\bin\mysqlshow mysql Database: mysql I Tables | + + | columns_priv | I db | I func I I host | I tablesjpriv | I user |
142
Глава 2. Установка MySQL С:\> C:\mysql\bin\mysql -е "SELECT Host,Db,User FROM db" mysql + + + + I host | db | user | + + + + I % I test | |
I %
| testJ|
+
+
+
| +
8. В подкаталоге sql-bench находится комплект тестов производительности, с помощью которого можно сравнить, как работает MySQL на различных платформах. Эти тесты написаны на языке Perl с использованием модуля DBI, обеспечивающего независимый от базы данных интерфейс к различным базам. Для запуска этого комплекта тестов необходимы и другие дополнительные модули Perl. Понадобится установить следующие модули: DBI
DBD::mysql Data::Dumper Data::ShowTable Все эти модули можно получить на сайте CPAN (http://www.cpan.org). См. раздел 2.7.1. Каталог sql -bench/Results содержит результаты запуска многих тестов на различных базах данных и платформах. Чтобы запустить все тесты, выполните команды: shell> cd sql-bench shell> perl run-all-tests Если у вас нет каталога sql-bench, это означает, что возможно, MySQL был установлен с использованием других файлов RPM, а не тех, что содержат исходный дистрибутив (исходный RPM включает каталог sql-bench). В этом случае потребуется установить комплект тестов производительности. Начиная с MySQL 3.22, поставляется отдельный RPM-файл тестов под названием mysqlbench-ВЯРСИЯi386. rpm, который содержит код и данные. В исходном дистрибутиве также имеется каталог t e s t с другими тестами, которые можно запускать. Например, чтобы запустить тест autoincrement.tst, выполните следующую команду из корневого каталога исходного дистрибутива:
shell> mysql -wf test < ./tests/auto_increment.tst С ожидаемыми результатами этого теста можно ознакомиться в файле ./tests/auto_increment.res. 9. К этому моменту вы должны иметь работающий сервер. Однако ни одна их начальных учетных записей MySQL пока не имеет пароля, поэтому придется присвоить им пароли, пользуясь инструкциями из раздела 2.4.5.
2.4.2.1. Проблемы с выполнением mysqMnstalldb Назначение сценария mysql_install_db состоит в том, чтобы генерировать таблицы привилегий MySQL. Он не перезаписывает существующих таблиц привилегий и не затрагивает никакие другие данные.
2.4. Настройки и тестирование после установки
143
Если вы хотите пересоздать существующие таблицы привилегий, сначала остановите сервер mysqld. Переименуйте подкаталог mysql каталога данных, чтобы тем самым сохранить его, и затем запустите сценарий mysql_install_db: shell> mv каталог-данных-mysql/mysql каталог-данных-mysql/mysql-old shell> mysql_install_db —user=mysql В настоящем разделе перечислены проблемы, с которыми можно столкнуться при запуске mysql_install_db. • mysql_install_db не устанавливает таблицы привилегий. Вы можете обнаружить, что сценарий не установил таблицы привилегий и прервал выполнение с выдачей следующих сообщений: Starting mysqld daemon with databases from XXXXXX mysqld ended Запуск демона mysqld для баз данных из XXXXXX mysqld завершен В этом случае потребуется тщательно исследовать файл журнала ошибок. Журнал должен находится в каталоге XXXXXX, иметь имя, соответствующее сообщению об ошибке, и указывать на причину, по которой mysqld не смог запуститься. Если вы не можете понять, что случилось, включите этот журнал в сообщение об ошибке и отправьте его в MySQL AB (см. раздел 1.7.1.3). • Процесс mysqld уже выполняется. Это означает, что сервер уже запущен и в этом случае вполне вероятно, что таблицы привилегий уже созданы. Если это так, вам вообще не нужно запускать mysql_install_db, поскольку он должен запускаться только один раз (при первой установке MySQL). • Установка второго сервера mysqld не работает, когда функционирует первый сервер. Это может произойти, когда у вас уже есть существующая установка MySQL, но вы хотите выполнить новую установку в другой каталог. Например, в дополнение к рабочей копии требуется создать еще одну копию для целей тестирования. Вообще говоря, проблема, которая возникает при попытке запуска второго сервера, заключается в том, что он пытается использовать сетевой интерфейс, который уже занят первым сервером. В этом случае вы увидите одной из следующих сообщений об ошибках: Can't s t a r t server: Bind on TCP/IP port: Address already in use Can't s t a r t server: Bind on unix s o c k e t . . . . Невозможно запустить сервер: Привязка к порту TCP/IP: Адрес уже используется Невозможно запустить сервер: Привязка к сокету unix.... Инструкции по настройке нескольких серверов представлены в разделе 4.9. • Вы не имеете доступа по записи в каталог /tmp. Если у вас нет доступа по записи, чтобы создавать временные файлы или файлы сокетов Unix в каталоге по умолчанию (/tmp), эта ошибка возникает при запуске mysql_install_db или сервера mysqld.
144
Глава 2. Установка MySQL Можно указать другой каталог для временных файлов и файла сокета, выполнив приведенные ниже команды до запуска mysql_install_db или mysqld: shell> TMPDIR=/временный_каталог/ she 11 > MYSQLJJNIX_PORT=/some_tmpjiir/mysql. sock shell> export TMPDIR MYSQLJJNIX_PORT В качестве параметра временный_каталог должен быть указан полный путь к каталогу, для которого имеется доступ по записи. После этого у вас появится возможность выполнить mysql_install_db и запустить сервер: shell> bin/mysql_install_db —user=mysql shell> bin/mysqld_safe —user=mysql & Если mysql_install_db находится в каталоге scripts, поменяйте в первой команде bin на scripts. За дополнительной информацией обращайтесь в раздел А.4.5 и в приложение Б.
2.4.3. Автоматический запуск и останов MySQL Обычно сервер mysql запускается одним из следующих способов: • Прямым обращением к mysqld. Это работает на любой платформе. • Запуском сервера MySQL в виде службы Windows. Это можно сделать в Windows-системах, которые поддерживают системные службы (NT, 2000 и ХР). Служба может быть настроена на автоматический запуск при старте Windows либо на ручной запуск по запросу. Подробные инструкции приведены в разделе 2.2.1.7. • Вызовом сценария mysqld_saf е, который пытается определить подходящие опции для mysqld и затем запускает его с этими опциями. Этот сценарий используется в системах, базирующихся на BSD Unix. См. раздел 4.1.3. • Вызовом mysql. server. Этот сценарий применяется преимущественно при запуске и останове операционных систем, использующих каталог запуска в стиле System-V, где он обычно устанавливается под именем mysql. Сценарий mysql.server запускает сервер, вызывая, в свою очередь, mysqld_safe. См. раздел 4.1.4. • В системе Mac OS X можно установить отдельный пакет приложения MySQL Startup Item, чтобы обеспечить автоматический запуск MySQL при загрузке системы. Startup Item запускает сервер, вызывая mysql. server. См. раздел 2.2.3. Сценарии mysqld.server и mysqld_safe, а также Mac OS X Startup Item, могут использоваться для запуска сервера вручную или автоматического запуска во время старта системы. Кроме того, mysqld. server и Startup Item могут применяться для останова сервера. Чтобы запустить или остановить сервер вручную с помощью сценария mysql.server, вызывайте его, соответственно, с аргументами s t a r t и stop: shell> mysql.server start shell> mysql.server stop
2.4. Настройки и тестирование после установки
145
Прежде чем запустить сервер, mysql. server изменяет текущий каталог на каталог установки MySQL, после чего вызывает mysqld_saf е. Если требуется запускать сервер от имени какого-то специфического пользователя, добавьте соответствующую позицию user в раздел [mysqld] файла опций /etc/my, cnf, как показано ниже в настоящем разделе. (Возможно, вам придется отредактировать сценарий mysql.server, если бинарный дистрибутив MySQL был установлен в нестандартное место. Модифицируйте упомянутый сценарий так, чтобы перед запуском mysqldsafe по команде cd выполнялся переход в нужный каталог. Если это было сделано, то при будущих обновлениях измененная версия mysql.server может быть перезаписана, поэтому отредактированный вариант сценария необходимо скопировать в безопасное место.) mysql.server останавливает сервер, посылая ему сигнал. Сервер можно остановить также b вручную, выполнив команду mysqladmin shutdown. Чтобы MySQL запускался и останавливался автоматически на вашем сервере, необходимо добавить команды запуска и останова в соответствующие места в файлах /etc/rc*. Если используется RPM-пакет сервера для Linux (MySQL-server-ВЕРСЯЯ.грт), сценарий mysql.server автоматически устанавливается в каталог /etc/init.d под именем mysql. Нет необходимости устанавливать его вручную. Более подробная информация о пакетах RPM для Linux представлена в разделе 2.2.2. Некоторые поставщики предлагают RPM-пакеты, которые устанавливают сценарий запуска под другим именем, например, mysqld. Если вы устанавливаете MySQL из исходного дистрибутива либо используете бинарный дистрибутив в формате, который не выполняет автоматическую установку mysql.server, можете сделать это вручную. Сценарий расположен в подкаталоге support-files каталога установки MySQL или в дереве исходных текстов. Чтобы установить mysql.server вручную, скопируйте его в каталог / e t c / i n i t . d под именем mysql и сделайте его исполняемым: shell> cp mysql.server /etc/init.d/mysql shell> chmod +x /etc/init.d/mysql Более старые системы Red Hat используют каталог /etc/rc.d/init.d вместо /etc/init.d. В этих системах соответствующим образом уточните предыдущие команды. В качестве альтернативного решения, сначала создайте /etc/init.d как символическую ссылку, которая будет указывать на /etc/rc.d/init.d: shell> cd /etc shell> In -s re.d/init.d . После установки сценария команды его активизации зависят от используемой операционной системы. В Linux для этого применяется команда chkconf ig: shell> chkconfig —add mysql В некоторых Linux-системах для полной активизации сценария потребуется выдать следующую команду: shell> chkconfig —level 345 mysql on В системе FreeBSD сценарии запуска обычно должны устанавливаться в /usr/local/etc/rc.d/. Страницы man-руководства гс(8) указывают, что сценарии из этого каталога выполняются, только если их имена соответствуют шаблону *.sh. Все
146
Глава 2. Установка MySQL
остальные файлы и подкаталоги, находящиеся внутри этого каталога, молча игнорируются. Другими словами, в системе FreeBDS потребуется установить mysql. server как /usr/local/etc/rc.d/mysql. server. sh, чтобы обеспечить его автоматический запуск. В качестве альтернативы способу, описанному выше, некоторые операционные системы также используют /etc/rc.local или /etc/init.d/boot.local для запуска дополнительных служб во время загрузки. Чтобы запустить MySQL таким способом, добавьте в соответствующий файл запуска команду, подобную следующей: /bin/sh -с 'cd /usr/local/mysql; ./bin/mysqld_safe —user=mysql &' Для ознакомления с установкой сценария запуска в средах других операционных систем читайте документацию по системе. Опции для mysql.server можно добавить в глобальный файл /etc/my.cnf. Ниже показано типичное содержимое файла /etc/my. cnf: [mysqld] datadir=/usr/local/mysql/var socket=/var/tmp/mysql.sock port=3306 user=mysql [mysql.server] basedir=/usr/local/mysql Сценарий mysql. server понимает следующие опции: basedir, datadir и pid-f i l e . Если они должны быть указаны, их следует поместить в файл опций, а не в командную строку. В качестве аргументов командной строки mysql.server воспринимает только start и stop. Ниже перечислены группы опций, которые сервер и сценарий запуска читают из файла опций. Сценарий
Группы опций
mysqld
[mysqld], [server], [mysqld-старшая-версия]
mysql.server
[mysqld], [mysql.server]
mysqld_safe
[mysqld], [server], [mysqld_safe]
[mysqld-старшая-версия) означает, что группы с именами вроде [mysqld-4.0], [mysqld-4.1] и [mysqld-5.0] будут прочитаны серверами MySQL 4.0.x, 4.1.x, 5.0.x и так далее. Эта возможность появилась в MySQL 4.0.14. Она может использоваться для указания опций, которые будут прочитаны только серверами конкретных версий. Для достижения обратной совместимости mysql.server также читает группу [mysql_server], a mysqld_safe - группу [safejnysqld]. Однако все же потребуется обновить файлы опций, чтобы они вместо этого использовали группы [mysql.server] и [mysqld_safe], если работа выполняется с MySQL 4.0 или более поздней версией. См. раздел 3.3.2.
2.44. Запуск сервера MySQL и устранение неисправностей Если при запуске сервера возникли какие-то проблемы, попробуйте сделать следующие вещи:
2.4. Настройки и тестирование после установки
147
• Укажите специальные опции, необходимые используемому вами механизму хранения. • Убедитесь в том, что серверу известно местонахождение каталога данных. • Убедитесь в том, что сервер может работать с каталогом данных. Атрибуты владения и доступа, присвоенные каталогу данных и его содержимому, должны быть такими, чтобы обеспечивать серверу доступ к ним и возможность модификации. • Просмотрите журнал ошибок, чтобы разобраться, почему сервер не может стартовать. • Проверьте доступность сетевого интерфейса, который использует сервер. Некоторые механизмы хранения имеют опции, управляющие их поведением. Можно создать файл my.cnf и указать в нем опции для используемого механизма. Если вы будете использовать механизмы хранения, которые поддерживают транзакционные таблицы (innoDB, BDB), то перед запуском сервера убедитесь, что они должным образом настроены: • Если вы используете таблицы InnoDB, обратитесь к специфичным для InnoDB опциям запуска. В MySQL 3.23 InnoDB нужно конфигурировать явно, в противном случае сервер при запуске выдаст сбой. Начиная с MySQL 4.0, InnoDB использует значения по умолчанию для конфигурационных опций, которые не указаны явно. См. раздел 9.4. • Если вы используете таблицы BDB (Berkley DB), необходимо ознакомиться с различными специфическими для BDB опциями запуска. См. раздел 8.4.3. После запуска mysqld делает текущим каталог данных. Это место, где он ожидает найти базы данных и куда собирается писать файлы журналов. В среде Unix сервер mysqld также пишет в каталог данных файл pid (файл идентификатора процесса). Местоположение каталога данных по умолчанию прописывается в код сервера во время его компиляции. Если каталог данных находится где-то в другом месте системы, сервер не сможет правильно работать. Узнать значения путей по умолчанию можно, вызвав mysqld с опциями —verbose и —help (до версии 4.1 MySQL игнорировал опцию —verbose). Если пути по умолчанию не соответствуют раскладке установки MySQL в вашей системе, можете переопределить их с помощью опций командной строки для mysqld или mysqld_saf е. Их также можно задать в файле опций. Для явного указания местоположения каталога данных служит опция —datadir. Однако обычно можно указать mysqld местоположение базового каталога, в котором установлен MySQL, и он найдет каталог данных там. Это можно сделать с помощью опции —basedir. Чтобы проверить действие указания опций путей, вызовите mysqld с этими опциями и дополните их список —verbose и —help. Например, если вы измените местоположение на каталог, в котором установлен mysqld, а затем выполните приведенную ниже команду, она покажет, что сервер стартовал с базовым каталогом /usr/local: shell> ./mysqld —basedir=/usr/local —verbose —help Можно также задать и другие опции, подобные --datadir, но помните, что —verbose и —help должны быть последними. (Для версий MySQL, предшествующих 4.1, —verbose необходимо опустить.) Как только вы определите, что сервер соответствующим образом воспринял установки путей, запускайте его без опций —verbose и —help.
148
Глава 2. Установка MySQL
Если mysqld уже работает, узнать текущие установки путей можно с помощью следующей команды: shell> mysqladmin variables или shell> mysqladmin -h имя_хоста variables Здесь имя_хоста - это имя хоста, на котором работает сервер MySQL. Если при запуске mysqld выдается ошибка Err code 13 ("Permission denied" - "Нарушение прав доступа"), это означает, что установленные привилегии для каталога данных или его содержимого не позволяют серверу получить к нему доступ. В этом случае измените права доступа к каталогу и файлам, чтобы сервер смог работать с ними. Вы также можете запустить сервер от имени root, но это подвергает систему риску нарушения безопасности, поэтому такого способа следует избегать. В среде Unix перейдите в каталог данных и проверьте права владения для этого каталога и его содержимого, дабы убедиться, что сервер имеет к нему доступ. Например, если каталогом данных является /usr/local/mysql/var, введите команду:
shell> Is -la /usr/local/mysql/var Если каталог данных, его файлы или подкаталоги не принадлежат пользователю операционной системы, от имени которого запущен сервер, измените их права владения: shell> chown -R mysql /usr/local/mysql/var shell> chgrp -R mysql /usr/local/mysql/var Если сервер не может стартовать корректно, проверьте файл журнала ошибок на предмет наличия в нем объяснения причины. Файлы журналов размещаются в каталоге данных (обычно C:\mysql\data под Windows, /usr/local/mysql/data - для бинарных дистрибутивов Unix и /usr/local/var - для исходных дистрибутивов Unix). Ищите в этом каталоге файлы с именами имя_хоста. e r r и имя^хоста. log, где имя_хоста - это имя хоста вашего сервера. (Старые серверы под Windows в качестве имени файла журнала ошибок использовали mysql.err.) Затем просмотрите несколько последних строк этих файлов. В Unix для вывода нескольких последних строк можно воспользоваться командой t a i l : shell> t a i l имя_хоста.етг shell> t a i l имя_хоста.log Журнал ошибок содержит информацию о том, почему сервер не смог запуститься. Например, вы можете увидеть там нечто вроде: 000729 14:50:10 bdb: Recovery function for LSN 1 27595 failed 000729 14:50:10 bdb: warning: . / t e s t / t l . d b : No such f i l e or directory 000729 14:50:10 Can't i n i t databases Это означает, что вы не запустили mysqld с опцией — bdb-no-recover, а механизм хранения Berkley DB обнаружил, что у него что-то не так с собственными журнальными файлами, когда попытался восстановить базу данных. Чтобы продолжить работу, вам нужно переместить старые журнальные файлы Berkley DB из каталога данных в какоенибудь другое место, где их можно будет позже просмотреть. Журнальные файлы BDB называются последовательно, начиная с log.0000000001, где номер увеличивается каждый раз.
2.4. Настройки и тестирование после установки
149
Если вы запускаете mysqld с поддержкой таблиц BDB, и он выдает сбой во время старта, это может быть вызвано проблемами с журналом восстановления BDB. В этом случае можно попробовать запустить его с опцией —bdb-no-recover. Если это поможет, удалите все журнальные файлы BDB из каталога данных и попробуйте снова запустить mysqld без опции —bdb-no-recover. Если возникает одна из следующих ошибок, это означает, что какая-то другая программа (возможно, другой сервер mysqld) уже использует порт TCP/IP или Unix-сокет, которые пытается открыть mysqld: Can't s t a r t server: Bind on TCP/IP port: Address already in use Can't s t a r t server: Bind on unix socket... С помощью команды ps проверьте, не запущен ли на машине другой сервер mysqld. Если да, остановите его. (Если другой сервер выполняется, и вы действительно хотите, чтобы на машине функционировало несколько серверов, ознакомьтесь с информацией, представленной в разделе 4.9.) Если никакой другой сервер не запущен, попробуйте выполнить команду telnet имя-вашего-хоста номер-порта-tcp-ip (по умолчанию MySQL использует порт 3306), затем нажмите клавишу <Enter> несколько раз. Если вы не получите сообщение об ошибке вроде t e l n e t : Unable to connect to remote host: Connection refused ("telnet: Невозможно подключиться к удаленному хосту: Подключение отклонено"), значит, какая-то другая программа использует порт TCP/IP, который пытается открыть mysqld. Разберитесь, что это за программа, и отключите ее, или же с помощью опции —port сообщите mysqld, что он должен использовать другой порт. В этом случае номер порта также потребуется сообщать всем клиентским программам для подключения к серверу через TCP/IP. Другая причина, по которой порт оказывается недоступным, может быть связана с брандмауэром, которые блокирует соединения с портом. Если это так, измените настройки брандмауэра, чтобы разрешить доступ к требуемому порту. Если сервер запускается, но вы не можете подключиться к нему, убедитесь в наличии в файле /etc/hosts такой строки: 127.0.0.1 localhost Эта проблема возникает только в системах, которые не имеют работающей библиотеки поддержки потоков и для которых MySQL должен быть сконфигурирован с поддержкой MIT-pthreads. Если вы не можете заставить mysqld стартовать, попытайтесь создать трассировочный файл, чтобы затем найти причину проблемы, запустив mysqld с опцией —debug.
2.4.5. Защита начальных учетных записей MySQL Частью процесса установки MySQL является настройка базы данных mysql, содержащей таблицы привилегий: • Дистрибутивы MySQL для Windows включают предварительно инициализированные таблицы привилегий, которые устанавливаются автоматически. • В Unix таблицы привилегий заполняются сценарием mysql_install_db. При некоторых способах установки он запускается автоматически, другие способы требуют, чтобы этот сценарий запускался вручную. Детали можно найти в разделе 2.4.2.
150
Глава 2. Установка MySQL
Таблицы привилегий определяют начальные пользовательские учетные записи MySQL и их права доступа. Эти учетные записи настраиваются следующим образом: • Создаются две учетных записи с именем root. Это администраторы, которым разрешено делать все. Первоначально с ними связаны пустые пароли, поэтому любой может подключиться к серверу MySQL как root без пароля и получить все привилегии. • В Windows одна учетная запись root служит для подключения с локального хоста, а другая - для подключения с любого хоста. • В Unix обе учетных записи root предназначены для подключения с локального хоста. Подключения должны выполняться с локального хоста путем указания в качестве имени хоста localhost для одной записи и реального имени хоста или IP-адреса - для другой. • Создаются две учетных записи анонимных пользователей, каждая с пустым именем и паролем. Любой может их использовать для подключения к серверу MySQL. • В Windows одна анонимная учетная запись предназначена для подключения с локального хоста. Она имеет все привилегии, как и root. Другая анонимная учетная запись служит для подключения с любого хоста, имеет все привилегии только в базе данных test или других базах, имена которых начинаются с test__. • В Unix обе анонимных учетных записи предназначены для подключения с локального хоста. Подключения выполняются с локального хоста с указанием имени localhost для одной учетной записи и реального имени хоста или IPадреса - для другой. Эти учетные записи имеют все привилегии в базе данных t e s t и во всех базах, имя которых начинается с t e s t . Как упоминалось ранее, ни одна из начальных учетных записей не имеет пароля. Это значит, что ваша установка MySQL не защищена, пока вы сами не позаботитесь об этом: • Если вы хотите предотвратить подключения анонимных пользователей без пароля, вы должны либо присвоить им пароль, либо вообще удалить такие записи. • Вы должны присвоить пароль пользователям root. Представленная ниже инструкция регламентирует процесс присвоения паролей начальным учетным записям MySQL - сначала анонимным, затем root. Замените "яовый_пароль" в примерах реальным паролем, который хотите использовать. Инструкция также объясняет, как удалить анонимные учетные записи, если вы предпочтете не иметь с ними дела. Вы можете отложить установку паролей на более поздний период, если они не нужны на время дополнительной настройки и тестирования. Однако обязательно установите их до начала реальной работы с СУБД. Для установки паролей учетным записям анонимных пользователей применяется либо оператор SET PASSWORD, либо оператор UPDATE. В обоих случаях обязательно зашифруйте пароли с помощью функции PASSWORD (). Чтобы установить пароли под Windows, выполните следующие команды: shell> mysql -u root mysql> SET PASSWORD FOR " @'localhost 1 = PASSWORD (' новый_пароль ' ) ; mysql> SET PASSWORD FOR "@'%' = PASSWORD('новый пароль');
2.4. Настройки и тестирование после установки
151
Для установки паролей под Unix служат такие команды: s h e l l > mysql -u r o o t 1 mysql> SET PASSWORD FOR ' •§ ' l o c a l h o s t = PASSWORD (' новый_пароль ' ) ; mysql> SET PASSWORD FOR '•§'имя_хоста* = PASSWORD('новый_пароль'); Во втором операторе SET PASSWORD замените имя_хоста на актуальное имя хоста сервера. Это имя, указанное в столбце Host записи, отличной от l o c a l h o s t , для r o o t в таблице u s e r . Если имя хоста вам не известно, выполните следующую команду перед SET PASSWORD: mysql> SELECT Host, User FROM m y s q l . u s e r ; Найдите запись, в которой значение столбца User равно r o o t , а значение Host отличается от l o c a l h o s t . Затем используйте это значение Host во втором операторе SET PASSWORD. Другой способ назначения паролей анонимным учетным записям заключается в применении UPDATE для непосредственной модификации таблицы user. Подключитесь к серверу как пользователь r o o t и выполните оператор UPDATE для установки значений в столбце Password в соответствующих записях таблицы user. Процедура одинакова для Windows и Unix. Следующий оператор UPDATE присваивает пароль обоим анонимным пользователям одновременно: s h e l l > mysql -u r o o t mysql> UPDATE m y s q l . u s e r SET Password = PASSWORD('newpwd') -> WHERE User = ' ' ; mysql> FLUSH PRIVILEGES; После того, как вы обновите пароли непосредственно в таблице, используя UPDATE, нужно дать команду серверу перечитать таблицу привилегий с помощью FLUSH PRIVILEGES. В противном случае изменения не вступят в силу, пока сервер не будет перегружен. Если вы предпочитаете вместо этого удалить анонимные учетные записи, выполните следующие команды: s h e l l > mysql -u r o o t mysql> DELETE FROM m y s q l . u s e r WHERE User = mysql> FLUSH PRIVILEGES;
";
Оператор DELETE применим как для Windows, так и для Unix. В среде Windows, если вы хотите удалить только ту анонимную учетную запись, которая имеет те же привилегии, что и r o o t , вместо приведенного выше выполните такие операторы: s h e l l > mysql -u r o o t 1 mysql> DELETE FROM m y s q l . u s e r WHERE H o s t = ' l o c a l h o s t AND User = ' ' ; mysql> FLUSH PRIVILEGES; Эта учетная запись имеет анонимный доступ с полными привилегиями, поэтому ее удаление повышает безопасность системы. Присвоить пароли пользователям r o o t можно также различными способами. Ниже продемонстрированы три метода: •
Использование оператора SET PASSWORD.
•
Использование клиентской утилиты командной строки mysql admin.
•
Использование оператор UPDATE.
152
Глава 2. Установка MySQL
Чтобы назначить пароли с помощью SET PASSWORD, подключитесь к серверу от имени root и выполните два оператора SET PASSWORD. He забудьте зашифровать пароли с помощью функции PASSWORD (). В среде Windows выполните следующее: shell> mysql -u root mysql> SET PASSWORD FOR 'root1@'localhost1 = PASSWORD('новый_пароль'); mysql> SET PASSWORD FOR 'root' @' %' = PASSWORD('новый_пароль'); В среде Unix воспользуйтесь такими операторами: s h e l l > mysql -u root m y s q l > SET PASSWORD FOR ' r o o t 1 @ ' l o c a l h o s t 1 = P A S S W O R D ( ' н о в ы й _ п а р о л ь ' ) ; mysql> SET PASSWORD FOR 'root'@'имя_хоста' = PASSWORD('новый_пароль'); Во втором операторе SET PASSWORD замените имя_хоста актуальным именем хоста вашего сервера. Это то же имя, которое вы использовали, когда присваивали пароли анонимным пользователям. Чтобы назначить пароли пользователям root с помощью утилиты mysqladmin, выполните следующие команды: shell> mysqladmin -u root password "новый_пароль" shell> mysqladmin -u root -h имя__хоста password "новый_пароль" Эти команды применимы и для Windows, и для Unix. Во второй команде замените имя_хоста актуальным именем хоста вашего сервера. Двойные кавычки, обрамляющие новый пароль, не всегда обязательны, их нужно применять, если пароль содержит пробелы или другие символы, которые командный интерпретатор трактует как специальные. Если вы используете очень старую версию сервера MySQL, команда mysqladmin может завершиться с сообщением об ошибке parse error near 'SET password' (ошибка разбора вблизи 'SET password'). Для решения этой проблемы выполните модернизацию сервера до более новой версии MySQL. Можно также с помощью оператора UPDATE провести непосредственную модификацию таблицы USER. В следующем примере с его помощью присваиваются пароли обоим пользователям root одновременно: s h e l l > mysql -u root mysql> UPDATE mysql.user SET Password = PASSWORD('новый_пароль') -> WHERE User = ' r o o t ' ; mysql> FLUSH PRIVILEGES; Оператор UPDATE применим и для Windows, и для Unix. После установки пароли потребуется вводить при каждом подключении к серверу. Например, если вы хотите с помощью mysqladmin остановить сервер, вы должны делать это, используя следующую команду: shell> mysqladmin -u root -p shutdown Enter password: (enter root password here) Введите пароль: (введите здесь пароль для root) ; На заметку! v Если вы забыли пароль пользователя root после его присвоения, процедура его переустановки '„ описана в разделе А.4.1. Для настройки новой пользовательской учетной записи применяется оператор GRANT. За подробными инструкциями обращайтесь в раздел 4.5.2.
2.5. Модернизация MySQL и возврат к старой версии
153
2.5. Модернизация MySQL и возврат к старой версии В качестве общего правила, мы рекомендуем при обновлении MySQL от одной серии выпусков к другой, переходить непосредственно к следующей серии, а не пропускать их. Например, если вы эксплуатируете MySQL 3.23 и хотите обновить его до более новой серии, устанавливайте MySQL 4.0, а не 4.1 или 5.0. Ниже приведен список действий, которые следует выполнять всякий раз перед модернизацией программного обеспечения MySQL: • Изучите в онлайновом руководстве журнал изменений серии того выпуска, который собираетесь установить, чтобы узнать, какие новые средства можно использовать. Например, перед обновлением MySQL 4.1 до MySQL 5.0 ознакомьтесь с новыми позициями. См. http://dev.mysql.com/doc/mysql/en/News.html. • Прежде чем приступать к обновлению, создайте резервные копии всех баз данных. • Если вы пользуетесь MySQL под Windows, прочитайте раздел 2.5.7. • Обновление может потребовать изменений в таблицах привилегий, которые хранятся в базе данных mysql. Иногда, для поддержки новых средств, в них добавляются новые столбцы, а в базу данных - таблицы. Чтобы воспользоваться преимуществами этих новых средств, убедитесь, что ваши таблицы привилегий обновлены. Процедура модернизации таблиц привилегий описана в разделе 2.5.8. • Если вы применяете репликацию, просмотрите раздел 5.6. • Если вы устанавливаете дистрибутив MySQL-Max, который включает в себя сервер mysql-max, а затем выполняете его модернизацию до версии, отличной от MySQL-Max, имейте в виду, что mysqld_safe по-прежнему будет пытаться запускать сервер mysql-max. В этом случае нужно вручную удалить старый сервер mysql-max, чтобы гарантировать, что mysqld_saf e запустит новый сервер mysqld. Вы всегда можете перемещать форматы файлов MySQL и файлы данных между разными версиями в рамках одной и той же архитектуры до тех пор, пока остаетесь в пределах одной серии выпусков MySQL. Текущей рабочей серией выпусков является MySQL 4.O. Если вы меняете набор символов при запуске MySQL, то должны выполнить myisamchk -r -q —set-character- set=набор^символов на всех таблицах My ISAM. В противном случае индексы могут быть построены в неправильном порядке, поскольку смена набора символов также может изменить порядок сортировки. Если вы переходите от одной серии выпусков к другой (как вверх, так и вниз), то можете столкнуться с несовместимостью в формате хранения таблиц. В этом случае перед модернизацией можно с помощью mysqldump построить дампы таблиц. После обновления загрузите дампы и с использованием mysql пересоздайте эти таблицы. Если вы подходите с осторожностью к переходу на новые версии, вы всегда можете переименовать старый сервер mysqld и только затем устанавливать новый. Например, если вы применяете MySQL 4.0.18 и хотите перейти на версию MySQL 4.1.1, переименуйте существующую программу сервера mysqld на mysqld-4.0.18. Если выяснится, что новый mysqld делает что-то не так, можно просто остановить его и запустить старый. Если после обновления вы сталкиваетесь с проблемами при перекомпиляции клиентских программ, такими как "Commands out of sync" (Команды не синхронизируются) или неожиданными выдачами дампа ядра, возможно, это означает, что при компиляции
154
Глава 2. Установка MySQL
вы использовали старые библиотеки ли файлы заголовков. Проверьте даты файла mysql.h и библиотеки libmysqlclient.a, чтобы убедиться, что они относятся к новому дистрибутиву MySQL. Если нет, перекомпилируйте свои программы с новыми файлами заголовков и библиотек. В случае возникновения проблем, таких как невозможность запуска сервера mysqld или невозможность подключения без пароля, проверьте, не остался ли у вас файл my.cnf от прежней установки. Это можно сделать с помощью опции —print-defaults (например, mysqld —print-defaults). Если это выведет на экран что-то кроме имени программы, значит, у вас есть активный файл my. cnf, который влияет на функционирование сервера или клиентов. Неплохо выполнять повторную сборку и установку модуля Perl DBD: :mysql при каждой установке нового выпуска MySQL. To же касается и других интерфейсов MySQL, например, модуля Python MySQLdb.
2.5.1. Модернизация версии 4.1 до 5.0 При модернизации MySQL 4.1 до версии 5.0 потребуется выполнить следующие действия: • Прочитайте о новых средствах версии MySQL 5.0 в онлайновом руководстве (http://dev.mysql.com/doc/mysql/en/News.html). • Если вы работаете в MySQL под Windows, прочитайте раздел 2.5.7. • В MySQL 5.0 добавлена поддержка хранимых процедур. Это требует наличия таблицы ргос в базе данных mysql. Чтобы ее создать, запустите сценарий mysqlf ix_privilege_tables, как описано в разделе 2.5.8. • Если вы применяете репликацию, просмотрите раздел 5.6.
2.5.2. Модернизация версии 4.0 до 4.1 При модернизации MySQL 4.0 до версии 4.1 потребуется выполнить следующие действия: • Проверьте позиции в приведенном далее списке изменений на предмет того, могут ли они затронуть ваши приложения. • Прочитайте о новых средствах версии 4.1 в онлайновом руководстве (http://dev.mysql.com/doc/mysql/en/News.html). • Если вы работаете в MySQL под Windows, прочитайте раздел 2.5.7. :
" "' На заметку! Ранние дистрибутивы альфа-версий MySQL 4.1 для Windows не содержали программы установки. За подробной информацией обращайтесь в раздел 2.2.1.2.
• После обновления внесите изменения в структуру таблиц привилегий, которые теперь имеют более длинный столбец Password, необходимый для более безопасной работы с паролями. Процедура включает запуск mysql_f ix_privilege_tables, как описано в разделе 2.5.8. Реализация изменений в работе приложений с паролями рассматривается далее в настоящем разделе. • Если вы применяете репликацию, прочитайте раздел 5.6.
2.5. Модернизация MySQL и возврат к старой версии
155
• Обработчик таблиц Berkley DB обновлен до версии DB 4.1 (от 3.2) и поддерживает теперь новый формат журналов. Если вы захотите вернуться к версии 4.0, то должны будете с помощью mysqdump построить дампы своих таблиц BDB в текстовом формате и удалить все файлы log.XXXXXXXXXX, а только затем запускать MySQL 4.0 и загружать данные. • Усовершенствована поддержка наборов символов. Если в столбцах ваших таблиц хранится информация в одном из наборов данных, которые поддерживаются сервером 4.1 непосредственно, вы можете преобразовать их в соответствии с приведенными ниже инструкциями. • Если вы пользуетесь старым модулем DBD-mysql (Msql-MySQL-modules), то должны обновить его. Все версии модуля DBD-mysql выше 2.хх должны подходить. Если этого не сделать, некоторые методы (наподобие DBl->do ()) не смогут корректно обрабатывать ошибочные ситуации. Некоторые аспекты поведения в MySQL 4.1 по сравнению с MySQL 4.0 были изменены, чтобы исправить критические ошибки и обеспечить большую совместимость со стандартом SQL. Эти изменения могут затронуть ваши приложения. Часть функций MySQL 4.1 можно протестировать в версии MySQL 4.0 до проведения полной модернизации. В последних выпусках (начиная с 4.0.12) к mysqld была добавлена опция —new (см. раздел 4.2.1). Упомянутая опция вводит в действие наиболее критичные изменения версии 4.1. Вы также можете включить их для отдельного клиентского соединения с помощью команды SET @@new=l и выключить-с помощью команды SET @@new=0. Если вы считаете, что изменения в версии 4.1 затронут ваши приложения, мы рекомендуем до перехода на версию 4.1 загрузить самый последний выпуск MySQL 4.0 и запустить его с опцией —new, добавив в конфигурационный файл следующие строки: [mysqld-4.0] new Поступая подобным образом, вы можете протестировать новое поведение в версии 4.0 и проверить, работают ли с ним существующие приложения. Это поможет обеспечить более гладкий и безболезненный переход, когда позже вы соберетесь осуществлять полную модернизацию до версии MySQL 4.1. Помещение опции --new в раздел [mysqld-4.0] гарантирует, что позже вы не запустите случайно MySQL 4.1 с опцией —new. В следующем списке описываются изменения, которые могут затронуть приложения, и на которые следует обратить особое внимание при переходе на версию 4.1. Изменения в сервере: • Все таблицы и символьные столбцы теперь имеют ассоциированный с ними символьный набор. Информация о нем выводится командой SHOW CREATE TABLE и программой mysqldump. (В MySQL версии 4.0.6 и выше можно читать новые файлы дампов, в более старых версиях - нет.) Это изменение не должно затронуть приложения, которые работают только с одним набором символов. • Обычно сервер работает, используя по умолчанию набор символов l a t i n l . Если вы сохраняете данные столбцов, которые используют другой набор символов из числа тех, что сервер MySQL 4.1 поддерживает напрямую, то можете их конвертировать. Однако вы должны избегать попыток прямого преобразования из
Глава 2. Установка MySQL
156
l a t i n l в "реальный" набор символов. Это может привести к потере данных. Вместо этого преобразуйте столбец в бинарный тип, а затем из бинарного в небинарный, с требуемым набором символов. Преобразование в бинарный тип и обратно не приводит к каким-либо изменениям символов и предохраняет данные. Например, предположим, что у вас есть таблица MySQL 4.0 с тремя столбцами для хранения значений в символьных наборах latinl, I a t i n 2 n u t f 8 : CREATE TABLE t ( latinl_col CHAR(50), Iatin2_col CHAR(IOO), utf8_col CHAR(150) ); После модернизации до версии 4.1 необходимо преобразовать эту таблицу таким образом, чтобы оставить latinl_col как есть, но изменить столбцы Iatin2_col и utf 8_col, чтобы они имели наборы символов Iatin2 и utf 8 соответственно. Сначала создайте резервную копию вашей таблицы, затем преобразуйте столбцы: ALTER ALTER ALTER ALTER
TABLE TABLE TABLE TABLE
t t t t
MODIFY MODIFY MODIFY MODIFY
I a t i n 2 _ c o l BINARY(100); u t f 8 _ c o l BINARY(150); I a t i n 2 _ c o l CHAR(100) CHARACTER SET I a t i n 2 ; u t f 8 _ c o l CHAR(150) CHARACTER SET u t f 8 ;
Первые два оператора "изымают" информацию о наборе символов из столбцов Iatin2_col и utf 8_col. Следующие два оператора назначают им требуемые наборы символов. Если хотите, можете скомбинировать преобразование к бинарному типу и обратно в одном операторе: ALTER TABLE t MODIFY I a t i n 2 _ c o l BINARY(100), MODIFY u t f 8 _ c o l BINARY(150); ALTER TABLE t MODIFY I a t i n 2 _ c o l CHAR(100) CHARACTER SET I a t i n 2 , MODIFY u t f 8 _ c o l CHAR(150) CHARACTER SET u t f 8 ;
• Формат определения таблиц, используемый в файлах . frm, был слегка изменен в версии MySQL 4.1. Версии MySQL 4.0, начиная с выпуска 4.0.11, могут читать новый формат . frm напрямую, более старые - нет. Если вы хотите провести перенос таблиц из версии 4.1 в верии, предшествующие 4.0.11, то должны воспользоваться mysqldump. См. раздел 7.8. /
На заметку!
U Если производится модернизация сервера MySQL до версии 4.1.1 или выше, очень трудно будет ;;: вернуться к версии 4.0 или 4.1.0. Это связано с тем, что в ранних версиях для таблиц InnoDB не |/ поддерживались табличные пространства.
• Если вы запускаете более одного сервера на одной Windows-машине, то должны использовать разные значения опции —shared-memory-base-name для каждого сервера. • Интерфейс агрегатных UDF-функций немного изменился. Теперь вы должны объявлять функцию xxx_clear () для каждой агрегатной функции XXX ().
2.5. Модернизация MySQL и возврат к старой версии
157
Изменения в клиентах: • mysqldump теперь имеет опции --opt и —quote-names, включенные по умолчанию. Вы можете выключить их с помощью —skip-opt и --skip-quote-names. Изменения в SQL: • Сравнение строк теперь работает в соответствии с требованиями стандарта SQL: вместо удаления завершающих пробелов перед сравнением, более короткая строка теперь дополняется пробелами. Однако в связи с этим появилась проблема, что ' а' > f a \ t ' , чего ранее не было. Если у вас есть таблицы со столбцами типа CHAR или VARCHAR, в которых завершающий символ может быть меньше, чем ASCII (32), вы должны использовать в отношении них REPAIR TABLE или myisamchk, чтобы гарантировать корректность этих таблиц. • В многотабличных операторах DELETE вместо имен таблиц, из которых нужно удалять, должны использоваться псевдонимы. Например, вместо DELETE t e s t FROM t e s t AS t l , test2 WHERE . . . следует использовать: DELETE t l FROM test AS t l , test2 WHERE . . . •
TIMESTAMP теперь возвращается в виде строки в формате Y ' YYY-MM-DD HH:MM:SS\ (Начиная с версии 4.0.12, может быть использована опция —new, чтобы заставить сервер 4.0 вести себя подобно 4.1.) Если вы хотите получить результат в виде числа (как это делает 4.0), то должны добавлять в запросах к имени столбца +0: mysql> SELECT ts_col + О FROM tbl_name;
Отображаемая ширина столбцов TIMESTAMP больше не поддерживается. Например, если вы объявили столбец как TIMESTAMP (10), то (10) игнорируется. Эти изменения были необходимы для обеспечения совместимости со стандартом SQL. В будущих версиях будут внесены и дальнейшие изменения (обратно совместимые с этим), позволяющие длине столбцов TIMESTAMP отражать требуемое количество разрядов в долях секунды. • Двоичные значение, такие как OxFFDF, теперь рассматриваются как строки, а не числа. Это решает некоторые проблемы с символьными наборами, когда удобно вводить строки как бинарные значения. В связи с этим изменением вы должны использовать CAST (), если хотите сравнивать двоичные значения как целые числа: mysql> SELECT CAST(0xFEFF AS UNSIGNED INTEGER) -> < CAST(0xFF AS UNSIGNED INTEGER); -> 0 Если не применять CAST (), выполняется лексикографическое сравнение: mysql> SELECT OxFEFF < OxFF; -> 1 Использование двоичных значений в числовом контексте или сравнение их с помощью операции = должно работать как ранее. (Начиная с версии 4.0.13, может быть использована опция --new, чтобы заставить сервер 4.0 вести себя подобно 4.1.) • Для функций, которые возвращают значения типа DATE, DATETIME и TIME, тип возврата приведен к единому временному типу. Например, в MySQL 4.1 вы получите такой результат:
158
Глава 2. Установка MySQL mysql> SELECT CAST('2001-1-1' AS DATETIME); -> '2001-01-01 00:00:00' В MySQL 4.0 результат отличается: mysql> SELECT CAST('2001-1-1' AS DATETIME); -> '2001-01-01'
• Значения DEFAULT больше не могут быть указаны для столбцов AUTO_INCREMENT (в версии 4.0 DEFAULT игнорируется, в версии 4.1 вызывает ошибку). • LIMIT не принимает отрицательных значений. Используйте какое-нибудь большое значение (максимум 18446744073709551615) вместо - 1 . •
SERIALIZE больше не является корректным значением режима для переменной sql_mode. Вместо этого вы должны использовать SET TRANSACTION ISOLATION LEVEL SERIALIZABLE. SERIALIZE не является допустимым значением и для опции --sql-mode сервера mysqld. Используйте вместо этого --transaction-isolation= SERIALIZABLE.
Изменения в API-интерфейсе С: • Некоторые вызовы API-интерфейса С, такие как mysql_real_query(), в случае ошибки теперь возвращает 1, а не - 1 . Вам придется изменить некоторые старые приложения, если они содержат нечто вроде: if (mysql_real_query(mysql_object, query, query_length) == -1) {
printf("Ошибка"); } Измените вызов, чтобы осуществлялась проверка на ненулевое значение: if
(mysql_real_query(mysql_object, query, query_length)
!= 0)
{
printf("Ошибка"); } Изменения в работе с паролями Механизм хеширования паролей в версии MySQL 4.1 изменился, чтобы обеспечивать более надежную защиту, но это может приводить к проблемам совместимости, если у вас есть клиентские программы, использующие клиентскую библиотеку из версии 4.0 или предшествующих версий. (Это весьма вероятно, если у вас есть клиенты 4.0, которые подключаются с удаленных хостов, еще не обновленных до версии 4.1). В представленном ниже списке предложены некоторые возможные стратегии модернизации. Они представляют различные компромиссы между требованием обеспечения совместимости со старыми клиентами и требованиям к повышению безопасности. • Модернизируются только клиенты, чтобы использовались клиентские библиотеки версии 4.1. Поведение не меняется (кроме возвращаемых значений для некоторых вызовов API), вы не можете воспользоваться никакими новыми средствами, предлагаемыми новым клиент-серверным протоколом. (В MySQL 4.1 реализован расширенный протокол, который предлагает такие возможности, как предварительно подготовленные SQL-операторы и множественные результирующие наборы.) • Модернизируется все до версии 4.1 и запускается сценарий mysql_f ix_privilege_tables, расширяющий размер столбца Password таблицы user для хранения длинных хе-
2.5. Модернизация MySQL и возврат к старой версии
159
шированных паролей. Однако сервер запускается с опцией —old-passwords для обеспечения обратной совместимости, позволяющей клиентам старых версий подключаться к их коротко-хешированным учетным записям. В конце концов, когда все клиенты будут обновлены до версии 4.1, можно прекратить запускать сервер с опцией —old-passwords. Придется также изменить пароли всех учетных записей MySQL для использования более безопасного нового формата. • Модернизируется все до версии 4.1 и запускается сценарий mysqlf ixprivilegetables, расширяющий размер столбца Password таблицы user для хранения длинных хешированных паролей. Если вы знаете, что все клиенты уже обновлены до версии 4.1, не запускайте сервер с опцией —old-passwords. Вместо этого измените пароли существующих учетных записей, чтобы они использовали новый формат. Полностью совместимая с версией 4.1 установка является наиболее безопасной. Более подробно о хешировании паролей в контексте аутентификации пользователей и операций смены пароля можно почитать в разделах 4.4.9 и А.2.3.
2.5.3. Модернизация версии 3.23 до 4.0 При модернизации MySQL 3.23 до версии 4.0 потребуется выполнить следующие действия: • Проверьте позиции в приведенном далее списке изменений на предмет того, могут ли они затронуть ваши приложения. • Прочитайте о новых средствах версии 4.0 в онлайновом руководстве (http://dev.mysql.com/doc/mysql/en/News.html). • Если вы работаете в MySQL под Windows, прочитайте раздел 2.5.7. •
После модернизации обновите таблицы привилегий, добавив новые привилегии и средства. Эта процедура предполагает запуск сценария mysql_f ix_privilege_tables и подробно описана в разделе 2.5.8.
• Если вы применяете репликацию, прочитайте раздел 5.6. • Отредактируйте все сценарии запуска MySQL или файлы опций, чтобы нигде не использовались устаревшие опции, описанные далее в настоящем разделе. • Преобразуйте старые файлы ISAM в My ISAM. Единственный способ сделать это запустить сценарий mysql_convert_table_format. (Этот сценарий реализован на языке Perl; он требует, чтобы был установлен DBI). Для преобразования таблиц конкретной базы данных выполните такую команду: shell> mysql_convert_table_format database имя_базы_данных Имейте в виду, что это должно быть сделано, только если все таблицы в данной базе являются таблицами ISAM или My ISAM. Чтобы избежать преобразования таблиц других типов, вы можете явно перечислить имена таблиц ISAM в командной строке после имени базы данных. Отдельные таблицы могут быть преобразованы к My ISAM с помощью следующего оператора ALTER TABLE, который должен выдаваться для каждой из таких таблиц: mysql> ALTER TABLE имя^таблицы TYPE=MyISAM; Если вы не уверены насчет типа конкретной таблицы, воспользуйтесь командой:
mysql> SHOW TABLE STATUS LIKE ' имя_таблицы*
',
160
Глава 2. Установка MySQL
• Убедитесь, что у вас нет каких-то клиентов MySQL, которые используют разделяемые библиотеки (вроде модуля Perl DBD: :mysql). Если такие есть, их потребуется перекомпилировать, потому что структуры данных, от которых зависит libraysqlclient.so, также изменились. То же касается других интерфейсов MySQL, например, модуля Python MySQLdb. MySQL 4.0 будет работать, даже если вы не выполните перечисленных действий, однако вы не сможете использовать новые привилегии доступа MySQL 4.0 и столкнетесь с проблемами позже, при модернизации до версии MySQL 4.1 или более новой. Формат файлов ISAM по-прежнему работает в серии MySQL 4.0, но считается устаревшим, поэтому его поддержка по умолчанию не компилируется. Вместо него должны применяться таблицы My ISAM. Старые клиенты должны работать с версией 4.0 без проблем. Даже если вы выполните все описанные выше действия, у вас все равно остается возможность вернуться к версии MySQL 3.23.52 или более новой, если вы столкнетесь с проблемами в серии MySQL 4.O. В этом случае необходимо с помощью mysqldump подготовить дамп все таблицы, использующих полнотекстовые индексы, и перезагрузить файл дампа в сервер MySQL 3.23. Это необходимо, поскольку в версии 4.0 используется новый формат полнотекстовых индексов. В следующем списке описываются изменения, которые могут повлиять на приложения, и на которые следует обратить особое внимание при переходе на версию 4.0. Изменения в сервере: • MySQL 4.0 имеет множество новых привилегий в таблице mysql.user (см. раздел 4.4.3). Чтобы заставить новые привилегии работать, необходимо обновить таблицы привилегий. Соответствующая процедура описана в разделе 2.5.8. До тех пор, пока вы не сделаете этого, все учетные записи будут иметь привилегии SHOW DATABASES, CREATE TEMPORARY
TABLES И LOCK TABLES. П р и в и л е г и и SUPER И EXECUTE
п о л у ч а ю т СВОИ З н а ч е н и я ИЗ PROCESS. REPLICATION
SLAVE И REPLICATION CLIENT
берут свои значения из FILE. Если имеются сценарии, создающие новых пользователей MySQL, может понадобиться изменить их так, чтобы они выдавали создаваемым пользователям новые привилегии. Если вы не применяете команду GRANT в этих сценариях, то это вполне подходящий момент, чтобы воспользоваться ею вместо прямого изменения данных в таблицах привилегий. Начиная с версии 4.0.2, опция --safe-show-database считается устаревшей (и больше ничего не делает). См. раздел 4.3.3. Если вы получаете сообщение об ошибке "Access denied" ("Доступ запрещен") для новых пользователей в версии 4.0.2 и выше, проверьте, не нужно ли воспользоваться какими-то новыми привилегиями, которые не применялись ранее. В частности, потребуется привилегия REPLICATION SLAVE (вместо FILE) для новых подчиненных серверов. •
safe_mysqld переименован в mysqld_safе. Для достижения обратной совместимости бинарные дистрибутивы иногда включают в себя символические ссылки safejnysqld, которые указывают на mysqld_safе.
2.5. Модернизация MySQL и возврат к старой версии
161
•
Поддержка InnoDB теперь включена в бинарный дистрибутив по умолчанию. Если вы собираете MySQL из исходных текстов, InnoDB конфигурируется по умолчанию. Если вы не используете InnoDB и хотите сэкономить память сервера, которая расходуется на поддержку InnoDB, указывайте опцию запуска сервера —skip-innodb. Чтобы скомпилировать MySQL без поддержки InnoDB, запускайте configure с ключом —without-innodb.
•
Значения для myisam_max_extra_sort_file_size и myisam_raax_extra sort f i l e теперь задаются в байтах (до версии 4.0.3 они указывались в мегабайтах).
•
mysqldb теперь имеет опцию —temp-pool, включенную по умолчанию, поскольку это повышает производительность в средах некоторых операционных системах (в основном, в Linux).
•
Опции mysqldb —skip-locking и —enable-locking переименованы, соответственно, в —skip-external-locking и —external-locking.
•
Внешняя системная блокировка файлов MylSAM/lSAM теперь по умолчанию выключена. Ее можно включить с помощью опции —external-locking. (Однако большинство пользователей в ней никогда не нуждается.)
•
Перечисленные ниже переменные и опции запуска переименованы: Старое имя
Новое имя
myisam_bulk_insert_tree_size
bulk_insert__buffer_size
query_cache_startup_type
query_cache_type
record_buffer
read_buffer_size
record_rnd_buffer
read_rnd_buffer_size
sort_buffer
sort_buffer_size
warnings
log-warnings
—err-log
—log-error(для mysqld_safe)
size
Опции запуска record_buffer, sort_buffer и warnings пока поддерживаются в MySQL 4.0, но считаются устаревшими. Изменения в SQL: •
Следующие переменные SQL переименованы: Старое имя
Новое имя
SQL_BIG_TABLES
BIG_TABLES
SQL_LOW_PRIORITY_UPDATES
LOW_PRIORITY_UPDATES
SQL_MAX_JOIN_SIZE
MAX_JOIN_SIZE
SQL_QUERY_CACHE_TYPE
QUERY_CACHE_TYPE
Старые имена по-прежнему поддерживаются в MySQL 4.0, однако использовать их не рекомендуется. •
Вы должны использовать SET GLOBAL SQL_SLAVE_SKIP_COUNTER= число_пропусков вместо SET SQL_SLAVE_SKIP_COUNTER=число_пропусков.
•
SHOW MASTER STATUS теперь возвращает пустой набор, если бинарное протоколирование отключено.
162
Глава 2. Установка MySQL
•
SHOW SLAVE STATUS теперь возвращает пустой набор, если подчиненная база данных не инициализирована.
•
SHOW INDEX имеет дополнительных две столбца, которых не было в версии 3.23 (Null и Index_type).
• Изменился формат SHOW OPEN TABLES. • ORDER BY имя_столбца DESC выводит значения NULL в конце, начиная с версии MySQL 4.0.11. В версии 3.23 и более ранних выпусках 4.0 так было не всегда. • CHECK, LOCALTIME и LOCALTIMESTAMP отныне являются зарезервированными словами. •
DOUBLE и FLOAT теперь при хранении учитывают флаг UNSIGNED (ранее для таких столбцов он игнорировался).
• Результат всех бинарных операций (|, &, « , » и ~) теперь целое число без знака. Это может вызвать проблемы, если вы применяете эти операции в контексте, в котором ожидается результат со знаком. Щ На заметку! ;
fy Когда выполняется вычитание целых чисел, причем одно из них UNSIGNED, результат будет без\yl знаковым. Другими словами, прежде чем модернизировать сервер до версии MySQL 4.0, необ|| ходимо проверить существующие приложение на случаи вычитания из беззнакового целого, Щ когда ожидается отрицательное значение, или вычитания беззнакового целого из целочислен':;г- ного столбца. Вы можете отключить такое поведение с помощью опции —sql-mode= £' NO_UNSIGNED_SUBSTRACTION при запуске mysqld. См. раздел 4.2.2.
• Вы должны использовать целые для хранения значений столбцов BIGINT (вместо строк, как это было в MySQL 3.23). Применение строк по-прежнему работает, но использование целых более эффективно. • В MySQL 3.23 оператор INSERT INTO.. .SELECT всегда предполагал IGNORE включенным. Начиная с 4.0.1, MySQL по умолчанию остановит (и, возможно, осуществит откат) выполнение оператора в случае ошибки, если только не указать IGNORE ЯВНО.
• Вы должны использовать TRUNCATE TABLE, когда хотите удалить все строки таблицы и не нуждаетесь в их подсчете. (DELETE FROM имя_таблицы возвращает в версии 4.0 количество удаленных записей, a TRUNCATE TABLE работает быстрее.) •
При попытке выполнить TRUNCATE TABLE или DROP DATABASE, когда существуют активные транзакции или блокировки таблиц, вы получите ошибку.
• Чтобы использовать полнотекстовый поиск MATCH.. .AGAINST (...IN BOOLEAN MODE) в ваших таблицах, необходимо пересоздать их индексы с помощью REPAIR TABLE имя_таблицы USE_FRM. Если попытаться применить булевский полнотекстовый поиск без такого пересоздания индексов, получится неверный результат. • Функции LOCATE () и INSTR () чувствительны к регистру, если одним из аргументов является бинарная строка. В других случаях упомянутые функции к регистру не чувствительны. • Функция STRCMP () при сравнении строк теперь использует текущий набор символов. Это делает сравнение строк по умолчанию чувствительным к регистру, если только один или оба аргумента не являются бинарными строками.
2.5. Модернизация MySQL и возврат к старой версии •
163
HEX {строка) возвращает символы строка, преобразованные в шестнадцатеричный формат. Если вы хотите конвертировать десятичное число в шестнадцатеричное, убедитесь, что HEX () вызывается с числовым аргументом.
• Функция RAND {начальное_значение) в версии 4.0 возвращает другие последовательности чисел, чем в версии 3.23. Это было сделано для дальнейшего проведения различий между RAND {начальное_значение) и RAND (начальное_значение+1). • Тип возврата по умолчанию для IFNULL (А, В) стал более "общим" для типов А и В. (Порядок интерпретации от общего к частному - строка, REAL, INTEGER.) Изменения в API-интерфейсе С: • Старые функции mysql_drop_db (), mysql_create_db() и mysql_connect () APIинтерфейса С больше не поддерживаются, если только вы не компилируете MySQL с CFLAGS=-DUSE_OLD_FUNCTIONS. Однако лучше все-таки вместо этого изменить клиентские программы для использования нового API-интерфейса. • В структуре MYSQL_FIELD тип полей length и max_length изменился с unsigned int на unsigned long. Это не должно вызывать проблемы, кроме генерации предупреждений, когда они служат аргументами для семейства функций printf (). • Многопоточные клиентские программы должны использовать mysql_thread_init () и mysql_thread_end(). Другие изменения: • Если вы хотите перекомпилировать модуль Perl DBD: :mysql, используйте свежую его версию. Рекомендуется применять версию 2.9003. Версии, предшествующие 1.2218, использовать нельзя, поскольку в них применяется устаревший вызов mysql_drop_db().
2.5.4. Модернизация версии 3.22 до 3.23 Клиенты MySQL 3.22 и MySQL 3.21 будут работать с сервером MySQL 3.23 без каких-либо проблем. При модернизации до MySQL 3.23 от более старых версий обратите внимание на перечисленные ниже изменения. Изменения таблиц: • MySQL 3.23 поддерживает таблицы нового типа My ISAM и таблицы старого типа ISAM. По умолчанию все новые таблицы создаются в формате My ISAM, если только сервер mysqld не запущен с опцией —default-table-isam. Нет необходимости конвертировать старые таблицы ISAM для использования их в MySQL 3.23. Однако вы можете это сделать с помощью оператора ALTER TABLE имя_таблицы TYPE=MyISAM либо Perl-сценария mysql_convert_table_f ormat. • Все таблицы, использующие набор символов tis620, должны быть исправлены с помощью myisamchk -r или REPAIR TABLE. • Если вы применяете в таблицах ISAM порядок сортировки german, то должны исправить их с помощью isamchk -r, потому что мы внесли некоторые изменения в упомянутый порядок сортировки.
164
Глава 2. Установка MySQL
Изменения в клиентах: • Стандартный MySQL-клиент mysqld теперь по умолчанию запускается с опцией —no-named-commands (-g). Ее можно отключить, указав —enable-named-commands (-G). В некоторых случаях это может привести к проблемам совместимости, например, в SQL-сценариях, которые используют именованные команды без точек с запятой. Длинный формат команд по-прежнему работает с первой строки. • Если вы хотите, чтобы ваши файлы mysqldump были совместимы между версиями MySQL 3.22 и MySQL 3.23, не следует при запуске mysqldump указывать опции —opt и — a l l . Изменения в SQL: • Если выполнить DROP DATABASE для базы данных, указанной через символическую ссылку, то удаляется как сама база, так и эта ссылка. Этого не происходило в MySQL 3.22, потому что configure не мог определить доступность системного вызова readlink(). •
OPTIMIZE TABLE теперь работает только для таблиц My ISAM. Для других типов таблиц с целью оптимизации можно применять ALTER TABLE. Во время выполнения OPTIMIZE TABLE таблица блокируется, чтобы предотвратить обращение к ней из других потоков сервера. • Функции работы с датами, которые имеют дело с частью значения даты (подобные MONTH()), теперь возвращают 0 для даты 0000-00-00. В MySQL 3.22 они возвращали NULL. •
Тип возврата по умолчанию функции IF () теперь зависит от обоих аргументов, а не от одного.
• Столбцы AUTO_INCREMENT не должны использоваться для хранения отрицательных значений. Причина состоит в том, что отрицательные числа приводили к проблемам, когда обращались из -1 в 0. Вы также не должны сохранять значения 0 в столбцах AUTO_INCREMENT. CHECK TABLE будет предупреждать о значениях 0, поскольку они могут измениться, если таблицу выгрузить в дамп и потом загрузить обратно. AUTO_INCREMENT для таблиц MylSAM теперь обрабатываются на более низком уровне и значительно быстрее, нежели ранее. Вдобавок, в таблицах My ISAM старые значения больше не используются, даже если вы удалите строки из таблицы. •
CASE, DELAYED, ELSE, END, FULLTEXT, INNER, RIGHT, THEN И WHEN теперь ЯВЛЯЮТСЯ зарезервированными словами.
•
FLOAT (p) теперь возвращает значение с плавающей точкой, а не с фиксированным количеством разрядов, как ранее.
•
При объявлении столбцов типа DECIMAL [длина, дес_точка) аргумент длина отныне не включает в себя места под знак или десятичную точку. • Строка TIME должна быть теперь в одном из следующих форматов: [[[ДЕНЬ] [Ч]Ч:]ММ:]СС[.доли_сек] или [[[[[Ч]Ч]Ч]Ч]ММ]СС[.доли_сек]. •
LIKE теперь сравнивает строки, используя те же правила сравнения, что и операция =. Если нужно вернуть старое поведение, скомпилируйте MySQL с флагом CXXFLAGS=-DLIKE CMP TOUPPER.
2.5. Модернизация MySQL и возврат к старой версии
165
• Функция REGEXP теперь не чувствительна к регистру, если только аргумент - не бинарная строка. • Когда вы проверяете или восстанавливаете таблицы My ISAM (.MYI), то должны использовать оператор CHECK TABLE либо команду myisamchk. Для таблиц ISAM (.ISM) применяйте команду isamchk. • Проверьте все вызовы DATEFORMAT () на предмет наличия символа '%' перед каждым символом формата. (MySQL 3.22 уже воспринимал такой синтаксис, однако не требовал его.) • В MySQL 3.22 вывод SELECT DISTINCT... почти всегда был отсортированным. Для получения отсортированного вывода в MySQL 3.23 необходимо использовать GROUP BY ИЛИ ORDER BY.
•
SUM() теперь возвращает NULL вместо 0, если нет подходящих строк. Этого требует стандарт SQL.
• Операции AND или OR со значениями NULL теперь возвращают NULL вместо 0. Это в основном касается запросов, использующих NOT в выражениях AND/OR как NOT NULL = NULL.
• Функции LPAD () и RPAD () теперь укорачивают результирующую строку, если она длиннее, чем аргумент, задающий длину. Изменения в API-интерфейсе С: • m y s q l f e t c h f ields_direct () является функцией, а не макросом. Теперь она возвращает указатель на MYSQL_FIELD вместо MYSQL_FIELD. • mysql_num_fields () не может быть использована в объектах MYSQL* (теперь это функция, в качестве аргумента принимающая MYSQL__RES*). Сейчас вместо нее с объектами MYSQL* нужно использовать mysql_field_count ().
2.5.5. Модернизация версии 3.21 до 3.22 Между версиями MySQL 3.21 и MySQL 3.22 не изменилось ничего такого, что отразилось бы на совместимости. Единственной ловушкой можно считать то, что новые таблицы со столбцами типа DATE используют новый способ хранения дат. Вы не сможете получить доступ к новым столбцам DATE через старый сервер mysqld. При модернизации более ранних версий до MySQL 3.22 нужно помнить о следующих изменениях: • После установки версии MySQL 3.22 вы должны стартовать новый сервер и затем запустить сценарий mysqlf i x p r i v i l e g e t a b l e s . Это добавит новые привилегии, которые понадобятся для использования в команде GRANT. Если вы забудете об этом, то получите сообщение Access denied при попытке выполнить ALTER TABLE, CREATE INDEX или DROP INDEX. Процедура обновления таблиц привилегий описана в разделе 2.5.8. • В API-интерфейсе С-функция mysq_real_connect () изменилась. Если у вас есть старые клиентские программы, которые обращались к этой функции, вы должны добавить передачу значения 0 для нового аргумента db (или переписать клиенты, чтобы они передавали реальный элемент db для более быстрого подключения). Вы также должны вызывать mysql_init() перед вызовом mysq_real__connect ().
166
Глава 2. Установка MySQL Эти изменения были внесены, чтобы позволить новой функции mysql_options () сохранять опции в управляющей структуре MYSQL.
• Переменная mysqld key__buffer переименована в key_buffer_size, однако вы попрежнему можете использовать старое имя в файлах запуска.
2.5.6. Модернизация версии 3.20 до 3.21 Если вы работаете с версией сервера, более старой, чем 3.20.28, и хотите перейти на версию 3.21, потребуется предпринять следующие действия. Вы можете запускать сервер mysqld версии 3.21 с опцией —old-protocol, чтобы использовать его с клиентами из дистрибутива 3.20. В этом случае сервер выполняет старую проверку password () вместо нового метода. Кроме того, новая клиентская функция mysql_errno() не вернет никакую из ошибок сервера, а только CR_UNKNOWN_ERROR. С ошибками клиента эта функция работает. Если вы не применяете опцию —old-protocol, вам придется выполнить следующие изменения: • Весь клиентский код должен быть перекомпилирован. Если вы используете ODBC, вам понадобится новый драйвер MyODBC 2.x. • Сценарий scripts/add_long_password должен быть запущен для преобразования столбца Password таблицы mysql.user в CHAR(16). • Все пароли в mysql.user должны быть переустановлены, поскольку для них теперь используется длина в 62, а не 31 разряд. • Формат таблиц не изменился, поэтому преобразовывать их не нужно. MySQL 3.20.28 и последующие версии могут работать с новым форматом таблицы user, никак не затрагивая клиентов. Если вы имеете дело с версией MySQL, предшествующей 3.20.28, после преобразования таблицы user пароли работать перестанут. Поэтому, чтобы соблюсти все меры безопасности, нужно сначала модернизировать сервер, по крайней мере, до версии MySQL 3.20.28, а затем до версии MySQL 3.21. Новый клиентский код работает с сервером mysqld 3.20.x, поэтому если вы столкнулись с проблемами в версии 3.21.x, то можете вернуться к старому серверу 3.20.x без повторной компиляции клиентских приложений. Если не использовать опцию —old-protocol для mysqld, то старые клиенты не смогут подключиться и получат следующее сообщение об ошибке: ERROR: Protocol mismatch. Server Version = 10 Client Version = 9 ОШИБКА: Н е с о в п а д е н и е протокола. Версия сервера = 1 0 Версия клиента
=9
Интерфейс Perl DBI также поддерживают старый интерфейс mysqlperl. Единственное изменение, которое нужно внести при использовании mysqlperl, касается аргументов функции connect (). Новые аргументы таковы: host, database, user и password (заметьте, что изменились места аргументов user и password). Следующие изменения могут повлиять на запросы в старых приложениях: •
HAVING теперь необходимо указывать перед конструкцией ORDER BY.
• Параметры LOCATE () поменялись местами. • Появились новые зарезервированные слова. Наиболее важные из них: DATE, DATETIME И TIMESTAMP.
2.5. Модернизация MySQL и возврат к старой версии
167
2.5.7. Модернизация MySQL под Windows Для выполнения модернизации MySQL под Windows, выполните следующие шаги: 1. Загрузите последний дистрибутив MySQL под Windows. 2. Выберите время дня, когда нагрузка на сервер минимальна и допустим перерыв в обслуживании. 3. Предупредите о перерыве в обслуживании пользователей, которые остаются активными. 4. Остановите работающий сервер MySQL (например, командой NET STOP MySQL, утилитой Services или командой mysqladmin shutdown). 5. Выйдите из программы WinMySQLAdmin, если она работает. 6. Запустите сценарий установки дистрибутива, щелкнув на кнопке Install (Установить) в окне программы WinZip, и следуйте шагам установки. у\ На заметку! \( Ранние дистрибутивы альфа-версий MySQL 4.1 для Windows не содержали программы установ•'•';, ки. Инструкции по установке таких дистрибутивов представлены в разделе 2.2.1.2.
7. Вы можете либо перезаписать установку MySQL (обычно расположенную в C:\mysql), либо установить в другой каталог, например, C:\raysql4. Рекомендуется перезаписать старую установку. 8. Перезапустите сервер, например, с помощью команды NET START MySQL, если он выполняется как служба, либо напрямую вызвав mysqld. 9. Обновите таблицы привилегий. Эта процедура описана в разделе 2.5.8. Возможные ошибочные ситуации: A system error has occurred. System error 1067 has occurred. The process terminated unexpectedly. Возникла системная ошибка. Возникла системная ошибка 1067. Процесс неожиданно завершился.
Эти ошибки означают, что ваш файл настроек (по умолчанию C:\my.cnf) содержит опцию, которую не распознает MySQL. Это можно проверить, попытавшись запустить сервер после переименования файла опций, чтобы предотвратить его чтение сервером (например, переименуйте C:\my.cnf в C:\my.cnf.old). Если вы убедитесь, что это так, нужно будет выявить опцию, которая в этом виновата. Создайте новый файл my.cnf и перенесите в него по частям содержимое старого файла, каждый раз пытаясь перезапустить сервер до тех пор, пока не обнаружите опцию, из-за которой сервер не смог нормально запуститься.
2.5.8. Обновление таблиц привилегий Некоторые выпуски вносят изменения в структуры таблиц привилегий (таблицы в базе данных mysql), добавляя новые привилегии или средства. Дабы иметь уверенность, что структура ваших таблиц привилегий не устарела при обновлении MySQL, вы должны их также обновить.
168
Глава 2. Установка MySQL
В системах на базе Unix и Unix-подобных ОС это делается путем запуска сценария mysql_fix_privilege_tables: shell> mysql_fix_privilege_tables Этот сценарий должен выполняться при работающем сервере. Он пытается установить соединение с сервером, который функционирует на локальном хосте, от имени root. Если ваша учетная запись root требует пароля, укажите пароль в командной строке. Для MySQL 4.1 и выше это делается следующим образом: shell> mysql__fix_privilege_tables —'разз\юхб=пароль_пользователя_гооЬ Для более ранних версий MySQL это выглядит так: shell> mysql_fixjprivilege_tables пароль_пользователя_гооЬ Сценарий mysql_fixjprivilege_tables выполняет все действия, необходимые для преобразования в новый формат существующих таблиц привилегий. При этом он может выдать некоторые предупреждения наподобие Duplicate column names (Дублированные имена столбцов). Их можно проигнорировать. После завершения этого сценария перезапустите сервер. В Windows-системах не было простого пути обновить таблицы привилегий до версии MySQL 4.0.15. Начиная с этой версии, дистрибутив MySQL включает в себя SQLсценарий mysql_fix_privilege_tables.sql, который можно запустить с помощью клиента mysql. Если MySQL находится в каталоге С: \mysql, команды выглядят следующим образом: С:\> C:\mysql\bin\mysql -u root -p mysql mysql> SOURCE С:\mysql\scripts\mysql_fix_privilege_tables.sql Программа mysql запросит у вас пароль для root; введите его. Если ваша установка находится в другом каталоге, исправьте соответствующим образом команду. Как и при выполнении этой процедуры под Unix, во время работы mysql_fix_privilege_tables.sql могут быть выданы сообщения типа Duplicate column names. Их также можно проигнорировать. После завершения этого сценария перезапустите сервер.
2.5.9. Копирование баз данных MySQL на другую машину Если вы работаете с MySQL 3.23 или предшествующими версиями, можно копировать файлы .frm, .MYI и .MYD для таблиц MylSAM между различными архитектурами, которые поддерживают одинаковый формат чисел с плавающей точкой (MySQL позаботится о необходимой перестановке байтов). См. раздел 8.1. Файлы данных и индексов формата ISAM (.ISD и .ISM соответственно) являются архитектурно-зависимыми, и в некоторых случаях, зависимыми от операционной системы. Если вы хотите переместить свои приложения на другую машину, не пытайтесь перенести базы данных простым копированием файлов. Используйте для этого mysqldump. По умолчанию mysqldump создает файл, содержащий SQL-операторы. Вы можете перенести этот файл на другую машину и использовать в качестве входного для клиентской программы mysql. Запустите mysqldump —help, чтобы просмотреть доступные опции. Если вы переносите данные в более новую версию сервера MySQL, то должны использовать mysqldump —opt, чтобы получить преимущества от оптимизации, результатом которой будет более компактный файл дампа, который может быстрее обрабатываться.
2.5. Модернизация MySQL и возврат к старой версии
169
Простейший (но не самый быстрый) способ переместить базу данных между двумя машинами предполагает запуск следующих команды на машине, на которой расположена база данных: shell> mysqladmin -h 'имя другого хоста* create имя_базы_данных shell> mysqldump —opt db_name | mysql -h 'имя другого хоста' имя_базы_данных Если вы хотите скопировать базу данных с удаленной машины через медленную сеть, можно поступить так: shell> mysqladmin create имя_базы_данных shell> mysqldump -h 'имя другого хоста1 —opt —compress имя_базы_данных | mysql имя_базы_данных Вы можете также сохранить результат в файле, затем переместить этот файл на другую машину и там загрузить его в базу данных. Например, вы можете поместить базу данных в дамп на исходной машине следующим образом: shell> mysqldump —quick имя_базы_данных | gzip > имя_ базы_ да иных, con ten ts.gz Файл, полученный подобным образом, является сжатым. Переместите файл, содержащий данные из базы, на целевую машину и выполните там приведенные ниже команды: shell> mysqladmin create имя_базы_данных shell> gunzip < имя_базы_данных.contents.gz | mysql имя_базы_данных Для переноса базы данных можно также использовать mysqldump и mysql import. В случае больших таблиц это может оказаться значительно быстрее, чем при простом применении mysqldump. В следующем примере КАТАЛОГ_ДАМПА представляет собой полное имя пути к каталогу, куда помещается вывод mysqldump. Вначале создайте каталог для выходных файлов и постройте дамп базы данных: s h e l l > mkdir КАТАЛОГ_ДАМПА s h e l l > mysqldump —ЬаЬ=КАТАЛОГ_ДАМПА
имя_базы_данных
Затем перенесите файлы из каталога КАТАЛОГ_ДАМПА в какой-нибудь подходящий каталог на целевой машине и загрузите его в MySQL с помощью следующих команд: shell> mysqladmin create имя_базы_данных #создание базы данных s h e l l > cat КАТАЛОГ_ДАМПА/*. sql
| mysql имя_базы__данных #создание таблиц
#в базе данных shell> mysqlimport имя_базы_данных КАТАЛОГ_ДАМПА/*. txt #загрузка данных #в таблицы Также не забудьте скопировать базу данных mysql, поскольку в ней находятся таблицы привилегий user, db и host. Возможно, на новой машине понадобится запускать команды от имени пользователя root, чтобы получить работающую базу на новом месйосле импорта базы данных mysql на новую машину необходимо запустить mysqladmin f lushprivileges, чтобы сервер перезагрузил информацию из таблиц привилегий.
170
Глава 2. Установка MySQL
2.6. Замечания по поводу конкретных операционных систем 2.6.1. Замечания по поводу Linux В этом разделе обсуждаются некоторые моменты, специфичные для ОС Linux. Первые несколько подразделов дают общее представление об особенностях и проблемах, связанных с этой операционной системой, при установке из бинарного или исходного дистрибутивов, а также постустановочные действия. В остальных подразделах рассматриваются проблемы, связанные с Linux на специфических платформах. Следует иметь в виду, что большинство описанных проблем возникают в более старых версиях Linux. Если вы имеете дело с новейшими версиями, вполне вероятно, вы не столкнетесь ни с одной из них. 2.6.1.1. Замечания по операционной системе Linux MySQL требует, как минимум, Linux версии 2.0. Предупреждение
£
Мы сталкивались с некоторыми странными проблемами с Linux 2.2.14 и MySQL в SMP-системах (симметричных многопроцессорных системах). У нас также есть некоторые сообщения от пользователей MySQL, у которых возникали серьезные проблемы со стабильной работой MySQL на ядре 2.2.14. Если вы используете это ядро, обновите его до 2.2.19 (или более нового) или до 2.4. Если у вас многопроцессорная система, вам нужно всерьез рассмотреть переход на ядро 2.4, поскольку это даст ощутимое повышение производительности. Кроме того, ваша система станет более стабильной.
При использовании LinuxThreads вы увидите, по меньшей мере, три работающих процесса mysqld. На самом деле, это не процессы, а потоки. Один из них принадлежит диспетчеру LinuxThreads, один обслуживает подключения, и один - сигналы и сообщения. 2.6.1.2. Замечания по бинарным дистрибутивам для Linux Бинарные дистрибутивы Linux-Intel и RPM-совместимые выпуски MySQL сконфигурированы таким образом, чтобы обеспечить максимально возможную скорость. Мы всегда стараемся использовать наиболее быстрые и стабильные доступные компиляторы. Бинарные выпуски скомпилированы с опцией - s t a t i c , это означает, что, как правило, вам не нужно беспокоиться о версиях используемых системных библиотек. Также у вас нет необходимости устанавливать LinuxThreads. Программы, скомпонованные с ключом - s t a t i c немного больше по размеру, чем скомпонованные динамически, но они также и несколько быстрее работают (на 3-5%). Однако проблемой статически скомпонованных программ является то, что вы не сможете применять определенные пользователем функции (User-defined functions - UDF). Если вы собираетесь писать или использовать UDF (это нечто, предназначенное только для программистов на С и C++), вам нужно самостоятельно перекомпилировать MySQL с использованием динамической компоновки. Известная сложность с бинарными дистрибутивами состоит в том, что в старых Linux-системах, которые используют libc (таких как Red Hat 4.x и Slackware) можно столкнуться с некоторыми некритическими проблемами, касающимися преобразования имен хостов. Если ваша система использует libc вместо glibc2, то вы, вероятно, столкнетесь с трудностями при разрешении имен хостов и getpwnam(). Это происходит потому, что, к сожалению, glibc зависит от некоторых внешних библиотек, реализующих
2.6. Замечания по поводу конкретных операционных систем
171
эту функциональность, даже при компоновке с ключом - s t a t i c . Эта проблема проявляется в двух аспектах: • Возможно, во время выполнения mysql_install_db вы увидите следующее сообщение об ошибке: Sorry, the host 'xxxx' could not be looked up Извините, хост 'хххх'
не может быть найден
Вы можете справиться с этим, запустив mysql_install_db --force, при этом не будет выполняться тест resolveip в составе mysql_install_db. Плохая сторона этого решения заключается в том, что вы не сможете использовать имена хостов в таблицах привилегий. Вместо них (кроме localhost) придется указывать IPадреса. • При попытке выполнить mysqld с опцией —user вы можете увидеть следующее сообщение: getpwnam: No such f i l e or directory getpwnam: Несуществующий файл или
каталог
Чтобы обойти это, запустите mysqld, используя команду su вместо опции —user. Это вынудит систему изменить пользовательский идентификатор процесса mysqld и ему не придется делать это самому. Другой способ решить обе проблемы - не использовать бинарные дистрибутивы. Загрузите исходный дистрибутив MySQL (в формате RPM или .tar.gz) и установите его вместо бинарного. В некоторых системах Linux версии 2.2 вы можете получить сообщение об ошибке "Resource temporarily unavailable" ("Ресурс временно недоступен"), когда клиенты устанавливают множество соединений с сервером mysqld через TCP/IP. Эта проблема объясняется тем, что Linux выдерживает паузу между моментом закрытия TCP/IP-сокета и моментом, когда система действительно освобождает его. А так как в системе существует ограниченное число TCP/IP-cлотов, вы столкнетесь с недостатком ресурсов, если клиенты пытаются открыть слишком много TCP/IP-соединений за короткое время. Такую ошибку можно увидеть, если запустить тест производительности test-connect через TCP/IP. Нас извещали об этой проблеме несколько раз в различных списках рассылки, посвященных Linux, но мы пока не нашли подходящего решения. Единственный известный способ исправить это для клиентов - использовать постоянные соединения, или же, если сервер базы данных и клиенты работают на одной и той же машине, использовать сокеты Unix вместо TCP/IP-соединений.
2.6.1.3. Замечания по исходным дистрибутивам Linux Следующие замечания относительно glib с касаются только ситуаций, когда вы собираете MySQL из исходных текстов самостоятельно. Если вы работаете с Linux на машинах х86, в большинстве случаев гораздо лучше использовать наш бинарный дистрибутив. Мы компонуем бинарные программы с самыми последними исправленными версиями библиотеки glibc, которые можем получить, и с наилучшими комбинациями опций компилятора, стараясь обеспечить их работоспособность в сильно загруженных серверах. Для типичного пользователя, даже для установок, в которых осуществляется множество параллельных клиентских соединений, и размеры таблиц превышают предел
172
Глава 2. Установка MySQL
в 2 Гбайт, наши бинарные сборки являются наилучшим выбором в большинстве случаев. После прочтения последующего текста, если вы сомневаетесь, что лучше сделать, первым делом попробуйте наш бинарный дистрибутив, чтобы проверить, удовлетворит ли он ваши нужды. Если вы обнаружите, что он недостаточно хорош, тогда можете попытаться произвести собственную сборку. В этом случае мы будем благодарны за сообщение об этом, чтобы мы смогли сделать лучший вариант в следующий раз. MySQL под Linux использует LinuxThreads. Если вы работаете со старыми версиями Linux, в которых нет glibc2, то должны установить LinuxThreads, прежде чем компилировать MySQL. Вы можете загрузить его с http://dev.mysql.com/downloads/os-linux.htral. Имейте в виду, что glibc 2.1.1 и предшествующих версий содержит критическую ошибку в функции pthread_mutex_timedwait (), которая вызывается при выполнении оператора INSERT DELAYED. Мы рекомендуем не применять INSERT DELAYED до тех пор, пока не будет обновлена glibc. Имейте в виду также, что ядро Linux и библиотека LinuxThreads по умолчанию могут иметь не более 1024 потоков. Если вы планируете иметь более 1000 параллельных подключений, то должны внести некоторые изменения в LinuxThreads: • Увеличить значение PTHREAD_THREADS_MAX в sysdeps/unix/sysv/linux/bits/local_lim.h до 4096 и уменьшить STACK_SIZE в linuxthreads/internals .h до 256 Кбайт. Пути указаны относительно корневого каталога glibc. (Помните, что MySQL не будет стабильным при 600-1000 соединений, если размер STACKSIZE оставить по умолчанию равным 2 Мбайт). • Перекомпилировать LinuxThreads, чтобы получить новый файл библиотеки libpthread. а и скомпоновать MySQL еще раз. Страница http://www.volano.com/linuxnotes.html содержит дополнительную информацию об ограничениях, накладываемых на потоки LinuxThreads. Существует другое обстоятельство, которое причиняет ущерб производительности MySQL, особенно в SMP-системах. Реализация семафоров LinuxThreads в glibc 2.1 очень плоха для программ со множеством потоков, которые удерживают семафоры только в течение короткого времени. Это приводит к парадоксальным результатам: если скомпоновать MySQL с LinuxThreads без изменений, то во многих случаях изъятие процессоров в SMP-системах приводит к повышению производительности MySQL. Мы подготовили соответствующее исправление для glibc 2.1.3, которое доступно по адресу http://www.mysql.com/Downloads/Linux/linuxthreads-2.1-patch. MySQL 3.23.36 с glibc 2.2.2 использует адаптированные семафоры, которые значительно лучше, чем даже исправленные в glibc 2.I.3. Однако надо иметь в виду, что при некоторых условиях текущий вариант семафоров в glibc 2.2.2 может снижать производительность MySQL. Вероятность того, что это произойдет, может быть уменьшена, если с помощью команды nice повысить приоритет процесса mysqld. Мы также готовы исправить это поведение соответствующим обновлением, которое доступно по адресу http://www.mysql.com/Downloads/Linux/linuxthreads-2.2.2.patch. Это обновление комбинирует исправление снижения производительности, максимального количества потоков и размера стека. Вам понадобится применить его в каталоге linuxthreads командой patch -pO gcc -03 -g -02 -DDBUGJDFF -о thr__alarm . . . x ./thr_alarm.c: In function signal_hand': ./thr_alarm.c:556: too many arguments to function
4
sigwait'
Самое правильно, что можно сделать в этом случае, - это получить более новую версию дсс и перекомпилировать ее вашим текущим компилятором дсс. По крайней мере, для Solaris 2.5, почти все старые бинарные версии дсс имеют устаревшие файлы заголовков, которые разрушают все программы, использующие потоки, а может быть, и не только потоки! Solaris не поставляет статических версий системных библиотек ( l i b p t h r e a d s и l i b d l ) , поэтому вы не сможете скомпилировать MySQL с — s t a t i c . Если попытаетесь это сделать, получите одну их следующих ошибок: Id: f a t a l : library - l d l : not found undefined reference to 'dlopen' cannot find - l r t А если вы скомпонуете собственные клиентские программы, то при работе их может быть выдана такая ошибка: ld.so.l: fatal: libmysqlclient.so.#: open f a i l e d : No such f i l e or d i r e c t o r y Этой проблемы можно избежать одним из следующих способов: •
Выполняйте компоновку клиентов с флагом вместо -Ълуть.
•
Скопируйте l i b m y s q c l i e n t . s o в / u s r / l i b .
•
Добавьте путь к каталогу, где находится l i b m y s q c l i e n t . s o , к переменной окружения LD_RUN_PATH, прежде чем запускать клиентские программы.
-Wl,r/полный/путь/к/libmysqlclient.so
Если у вас возникают проблемы с configure при компоновке с - l z , когда нет установленной библиотеки z l i b , существуют два выбора: •
Если вы хотите использовать сжатый коммуникационный протокол, вам нужно получить z l i b из f t p . gnu. org и установить ее.
•
Запустить configure с опцией —with-named-z-libs=no во время сборки MySQL.
Если вы используете дсс и сталкиваетесь с проблемами при загрузке в MySQL определяемых пользователем функций (UDF), попробуйте добавить - l g c c в строку компоновки для UDF. Если вы хотите, чтобы MySQL запускался автоматически, можете скопировать support-files/mysql. server в / e t c / i n i t . d и создать символическую ссылку на него с именем /etc/гсЗ.d/S99mysql.server. Если случается так, что слишком много процессов пытаются быстро подключиться к mysqld, вы увидите в журнале ошибок MySQL следующую строку: Error in accept: Protocol error
Глава 2. Установка MySQL
182
Для того чтобы обойти это, можете попробовать запустить сервер с опцией —back_log=50. (До версии MySQL 4.0 используйте -0 back_log=50.) Solaris не поддерживает файлы образов памяти для приложений с вызовами setuid (), поэтому вы не сможете получить этот файл от raysqld, если указываете опцию —user.
2.6.3.1. Замечания по Solaris 2.7/2.8 Обычно вы можете использовать бинарные программы для Solaris 2.6 в Solaris 2.7 и 2.8. Большинство продуктов Solars 2.6 также используются в Solaris 2.7 и 2.8. MySQL 3.23.4 и выше должен быть готов автоматически определять новые версии Solaris и включать обходные пути для решения описанных ниже проблем. Solaris 2.7 и 2.8 имеют некоторые ошибки во включаемых файлах. Во время использования дсс может выдаваться следующая ошибка: /usr/include/widec.h:42: warning: Ngetwc' redefined /usr/include/wchar.h:326: warning: this is the location of the previous definition /usr/include/widee.h:42: предупреждение: *getwc' переопределена /usr/include/wchar.h:326: предупреждение: это расположение предыдущего определения Если такое случится, исправить ошибку можно, скопировав /usr/include/widec.h в .. /lib/gcclib/os/gcc-version/include и изменив строку 41 с #if
!defined(lint) && !defined(
lint)
на #if Idefined(lint) && !defined(
lint) && !defined(getwc)
В качестве альтернативы, можно отредактировать /usr/include/widec.h непосредственно. В любом случае, после этого исправления необходимо удалить config. cache и запустить configure снова. Причина возникновения следующих ошибок при запуске make состоит в том, что configure не находит файл curses.h (возможно, из-за ошибки в /usr/include/widec.h): In file included from mysql.ee:50: /usr/include/term.h:1060: syntax error before 4,' /usr/include/term.h:1081: syntax error before ;' Для решения этой проблемы можно предпринять следующие действия: •
И з м е н и т ь В . / c o n f i g u r e CFLAGS=-DHAVE_CURSES_H CXXFLAGS=-DHAVE_CURSES_H.
• Отредактировать /usr/include/widec.h, как показано выше, и перезапустить configure. • Удалить строку Idefine HAVEJTERM из файла config.h, после чего запустить make снова. Если ваш компоновщик не находит -lz при выполнении сборки ваших клиентских программ, возможно, проблема заключается в том, что файл libz.so установлен в каталоге /usr/local/lib. Решить ее можно одним из следующих способов: •
Добавить /usr/local/lib в LD_LIBRARY_PATH.
• Добавить ссылку на l i b z . so из /lib.
2.6. Замечания по поводу конкретных операционных систем
183
• Если вы работаете в Solaris 8, можете установить необязательную утилиту zlib из дистрибутива Solaris 8 на компакт-диске. • Запустить configure с опцией —with-named-z-libs=no при сборке MySQL.
2.6.3.2. Замечания по Solaris х8б В Solaris 8 для х86 сервер mysqld сбрасывает дамп памяти, если с помощью программы s t r i p удалить из бинарного кода отладочную информацию. Если вы используете дсс или egcs в Solaris x86 и сталкиваетесь с выдачей дампа памяти во время загрузки, выдайте следующую команду configure: CC=gcc CFLAGS="-O3 -fomit-frame-pointer -DHAVE_CURSES_H" \ CXX=gcc \ CXXFLAGS="-O3 -fomit-frame-pointer -felide-constructors \ -fno-exceptions -fno-rtti -DHAVE_CURSES_H" \ ./configure —prefix=/usr/local/mysql Это позволит избежать проблем, связанных с библиотекой libstdc++ и исключениями C++. Если это не поможет, скомпилируйте отладочную версию и запустите ее с файлом трассировки или в отладчике gdb.
2.6.4. Замечания по BSD В этом разделе представлена информация об использовании MySQL на различных вариациях BSD Unix. 2.6.4.1. Замечания по FreeBSD Для функционирования MySQL рекомендуется FreeBSD версии 4.0 и старше, поскольку в них гораздо лучше интегрирован пакет поддержки потоков. Чтобы получить защищенную и стабильную систему, вы должны использовать только те ядра FreeBSD, которые помечены как -RELEASE. Наиболее простой (и предпочтительный) способ установки MySQL предполагает использование пакетов mysql-server и mysql-clients, которые доступны на сайте http://www.freebsd.org/. Применение упомянутых пакетов обеспечивает следующие преимущества: • Работоспособный MySQL с включенной оптимизацией, о котором точно известно, что он будет работать под управлением вашей версии FreeBSD. • Автоматическое конфигурирование и сборка. • Сценарии запуска, установленные в каталоге /usr/local/etc/rc. d. • Возможность получить информацию об установленных файлах с помощью команды pkg_infо -L. • Возможность удаления установки MySQL с машины с помощью команды pkg_delete. Рекомендуется использовать MIT-pthreads в FreeBSD 2.x и встроенную поддержку потоков в версии FreeBSD 3 и выше. Вообще говоря, существует возможность работать со встроенными потоками в поздних версиях 2.2.x, однако вы можете столкнуться с проблемами при останове mysqld.
184
Глава 2. Установка MySQL
К сожалению, некоторые вызовы функций в FreeBSD пока еще не вполне безопасны в отношении потоков. В первую очередь следует упомянуть функцию gethostbynameO, которую использует MySQL для преобразования имен хостов в IP-адреса. При некоторых обстоятельствах процесс mysqld неожиданно загружает процессор на 100% и перестает реагировать на запросы. Если вы столкнетесь с этой проблемой, попробуйте запустить mysqld с опцией —skip-name-resolve. В качестве альтернативы, можете скомпоновать MySQL в FreeBSD с библиотекой LinuxThreads, которая решает часть проблем, существующих в реализации поддержки потоков FreeBSD. Очень хорошее сравнение LinuxThreads со встроенными потоками приведено в статье Джереми Заводны (Jeremy Zawodny) "FreeBSD or Linux for your MySQL Server?" ("FreeBSD или Linux для вашего сервера MySQL?"), оригинал которой доступен по адресу h t t p : //Jeremy, zawodny.com/blog/archives/000697 .html. Известная проблема при использовании LinuxThreads в среде FreeBSD состоит в том, что значение waittimeout не принимается во внимание (вероятно, из-за сложностей с обработкой сигналов FreeBSD/LinuxThreads). Ожидается, что это будет исправлено в FreeBSD 5.0. Симптомы проявляются в том, что постоянные подключения могут зависать на длительное время, не давая возможности их закрыть. Процесс сборки MySQL для своей работы требует GNU make (gmake). Если GNU make отсутствует, необходимо его установить до начала компиляции MySQL. Ниже представлен рекомендуемый способ компиляции и установки MySQL в среде FreeBSD с помощью дсс (версии 2.95.2 и выше): СС=дсс CFLAGS="-02 -fno-strength-reduce" \ СХХ=дсс CXXFLAGS="-02 -fno-rtti -fno-exceptions \ -felide-constructors -fno-strength-reduce" \ ./configure —prefix=/usr/local/mysql —enable-assembler gmake gmake install cd /usr/local/mysql bin/mysql_install_db —user=mysql bin/mysqld_safe & Если вы решите, что configure будет использовать MIT-pthreads, прочтите раздел 2.3.5. Если make i n s t a l l выдаст сообщение об ошибке, связанной с невозможности найти /usr/include/pthreads, значит, configure не может обнаружить MIT-pthreads. Для исправления этой проблемы удалите config. cache, после чего перезапустите configure с опцией —with-mit-pthreads. Убедитесь в том, что преобразование имен работает правильно. Иначе вы можете столкнуться с задержками или отказами при попытках подключения к mysqld. Также убедитесь в том, что позиция localhost корректно описана в файле /etc/hosts. Этот файл должен начинаться со строки, подобной приведенной ниже: 127.0.0.1 localhost localhost.ваш.домен Известно, что у FreeBSD установлен очень низкий лимит на число открытых файлов. См. раздел А.2.17. Запускайте сервер с опцией --open-files-limit для mysqld_safe, или увеличьте ограничения для пользователя mysqld в /etc/login.conf и пересоберите его с capjnkdb /etc/login.conf. Также убедитесь, что вы установили соответствующий
2.6. Замечания по поводу конкретных операционных систем
185
класс для пользователя в файле паролей, если вы не применяете соглашения по умолчанию (используйте chpass имя-пользователя-mysqld). См. раздел 4.1.3. Если объем памяти, который находится в вашем распоряжении, достаточно велик, стоит рассмотреть возможность перекомпиляции ядра, чтобы позволить MySQL использовать свыше 512 Мбайт памяти. Для получения более подробной информации взгляните на опцию MAXDSIZ в файле конфигурации LINT. В случае возникновения проблем с текущей датой в MySQL может помочь установка переменной TZ. См. приложение Б.
2.6.4.2. Замечания по NetBSD Для выполнения компиляции под NetBSD необходима GNU make. В противном случае процесс сборки прервется по ошибке, когда make попытается запустить l i n t для файлов C++. 2.6.4.3. Замечания по OpenBSD 2.5 В среде OpenBSD версии 2.5 можно скомпилировать MySQL со встроенными потоками, если использовать следующие опции: CFLAGS=-pthread CXXFLAGS=-pthread ./configure —with-mit-threads=no
2.6.4.4. Замечания по OpenBSD 2.8 Наши пользователи сообщили, что OpenBSD 2.8 содержит ошибку, связанную с потоками, которая приводит к проблемам в MySQL. Разработчики OpenBSD исправили ее, но по состоянию на 25 января 2001 года это исправление доступно только в ветви "-current". Симптомами этой ошибки являются замедленная реакция, высокая загрузка процессора и крах системы. Если вы получаете сообщение об ошибке вроде "Error in accept:: Bad f i l e descriptor" ("Ошибка при чтении:: Неверный дескриптор файла") или ошибку 9 при попытке открыть таблицы или каталоги, то возможно, причина в том, что для MySQL выделено недостаточное количество дескрипторов файлов. В этом случае попробуйте запустить mysql_safe от имени root со следующими ключами: roysqld_safe —user=mysql —open-files-limit=2048 & 2.6.4.5. Замечания по BSD/OS версии 2.x Если во время компиляции MySQL вы получили приведенное ниже сообщение об ошибкеj это значит, что ваш лимит виртуальной памяти ulimit слишком мал: item_func.h: In method v Item_func_ge: :Item_func_ge (const Item_func__ge &) ' : item_func.h:28: virtual memory exhausted make[2]: *** [item_func.o] Error 1 Попытайтесь установить ulimit -v 80000 и запустите make снова. Если вы используете командную оболочку bash и это не срабатывает, попробуйте перейти на оболочку csh или sh. Некоторые пользователи BSDI сообщали о проблемах с bash и ulimit. Если вы применяете дсс, возможно, вам стоит указать флаг —with-low-memory для configure, чтобы получить возможность скомпилировать sql_yacc.cc. Если у вас возникли проблемы с текущей датой в MySQL, возможно, поможет установка переменной TZ. См. приложение Б.
186
Глава 2. Установка MySQL
2.6.4.6. Замечания по BSD/OS версии 3.x Модернизируйте систему до версии BSD/OS 3.1. Если это невозможно, примените исправление BSDIpatch M300-038. При конфигурировании MySQL воспользуйтесь следующей командой: env CXX=shlicc++ CC=shlicc2 \ ./configure \ —prefix=/usr/local/mysql \ —localstatedir=/var/mysql \ —without-perl \ —with-unix-socket-path=/var/mysql/mysql.sock Приведенный ниже вариант тоже работает: env COgcc CXX=gcc CXXFLAGS=-O3 \ ./configure \ —prefix=/usr/local/mysql \ —with-unix-socket-path=/var/mysql/mysql.sock Если хотите, можете изменить местоположение каталога, или же использовать местоположение, принятое по умолчанию, не указав никакого. Если возникают проблемы с производительностью при большой нагрузке, попробуйте применить опцию —skip-thread-priority для mysqld. Это позволяет выполнять все потоки с одинаковыми приоритетами. В BSDI 3.1 это обеспечит более высокую производительность, по крайней мере, до тех пор, пока BSDI не исправит свой диспетчер потоков. Если во время компиляции вы получаете сообщение об ошибке наподобие "virtual memory exhausted" ("виртуальная память исчерпана"), нужно попробовать установить ulimit -v 80000 и запустить make снова. Если вы используете командную оболочку bash и это не срабатывает, попробуйте перейти на csh или sh. Некоторые пользователи BSDI сообщали о проблемах с bash и ulimit.
2.6.4.7. Замечания по BSD/OS версии 4.x BSDI 4.x имеет те же ошибки, связанные с потоками. Если вы хотите использовать MySQL в этой системе, вы должны применить все исправления, касающиеся потоков. Как минимум, потребуется применить М400-023. В некоторых системах BSDI 4.x вы можете столкнуться с проблемами, имеющими отношение к разделяемым библиотекам. Симптомом является невозможность запустить клиентскую программу, например mysqladmin. В этом случае нужно переконфигурировать сборку, указав configure опцию —disable-shared. Некоторые наши потребители сталкивались с проблемой в BSDI 4.0.1, которая выражалась в том, что mysqld в течение длительного времени не мог открыть таблицы. Это связано с тем, что некоторые библиотечные/системные ошибки заставляют mysqld сменять текущий каталог, хотя его об этом не просят. Для того чтобы исправить это, необходимо либо модернизировать MySQL как минимум, до версии 3.23.34, либо после запуска configure удалить #define HAVE_REALPATH из config.h перед запуском make. Заметьте, это означает, что в BSDI вы не сможете создавать символические ссылки, чтобы связать один каталог данных с другим или таблицу с другой базой данных (создание символических ссылок на другой диск работает нормально).
2.6. Замечания по поводу конкретных операционных систем
187
2.6.5. Замечания по другим системам Unix 2.6.5.1. Замечания по HP-UX версии 10.20 Существует несколько незначительных проблем при компиляции MySQL в среде HPUX. Мы советуем использовать дсс вместо встроенного компилятора HP-UX, так как дсс генерирует более качественный код. В HP-UX лучше всего применять дсс 2.95. Не используйте флаги включения высокой оптимизации (типа -Об), поскольку они могут оказаться небезопасными для HP-UX. Следующая строка configure должна работать с дсс 2.95: CFLAGS="-I/opt/dce/include -fpic" \ CXXFLAGS="-I/opt/dce/include -felide-constructors -fno-exceptions \ -fno-rtti" \ CXX=gcc \ ./configure —with-pthread \ —with-named-thread-libs='-Idee' \ —prefix=/usr/local/mysql —disable-shared Приведенная ниже строка configure должна работать с дсс 3.1: CFLAGS="-DHPUX -I/opt/dce/include -03 -fPIC" CXX=gcc \ CXXFLAGS="-DHPUX -I/opt/dce/include -felide-constructors \ -fno-exceptions -fno-rtti -03 -fPIC" \ ./configure —prefix=/usr/local/mysql \ —with-extra-charsets=complex —enable-thread-safe-client \ —enable-local-infile —with-pthread \ —with-named-thread-libs=-ldce —with-lib-ccflags=-fPIC —disable-shared
2.6.5.2. Замечания по HP-UX версии 11.x Для работы в среде HP-UX 11.x мы советуем выбирать MySQL 3.23.15 или более поздние версии. Из-за некоторых критических ошибок в стандартных библиотеках HP-UX вы должны применить следующие исправления, прежде чем можно будет успешно запускать MySQL под управлением HP-UX 11.x: PHKL_22840 Streams cumulative PHNE_22397 ARPA cumulative Это решает проблему возврата EWOULDBLOCK из recv() и EBADF из accept () в многопоточных приложениях. Если вы используете дсс 2.95.1 в системе HP-UX 11.x, в которой не применялись исправления, то получите сообщение об ошибке вида: In f i l e included from /usr/include/unistd.h:11, from ../include/global.h:125, from mysql joriv.h:15, from item.ee:19: /usr/include/sys/unistd.h:184: declaration of С function . . . /usr/include/sys/pthread.h:440: previous declaration . . . In file included from item.h:306, from mysql_jpriv.h: 158, from item.ee:19:
Глава 2. Установка MySQL
188
Проблема состоит в том, что HP-UX не определяет однозначно pthreads_atfork(). Существуют конфликтующие между собой прототипы в /usr/include/sys/unistd.h:184 и /usr/include/sys/pthread.h:440. Одним из решений может быть копирование / u s r / i n c l u d e / s y s / u n i s t d . h в mysql/include и редактирование unistd.h для приведения в соответствие с объявлением в pthreads. h. Найдите строку: extern
i n t pthread_atfork(void
(*prepare) ( ) , void ( * p a r e n t ) ( ) ,
Исправьте ее следующим образом: extern int pthread_atfork(void (^prepare)(void), void void (*child)(void));
void
(*child)());
(*parent)(void),
После внесения этого изменения следующая строка configure должна работать нормально: CFLAGS="-fomit-frame-pointer -03 -fpic" CXX=gcc \ CXXFLAGS="-felide-constructors -fno-exceptions -fno-rtti -03" \ ./configure —prefix=/usr/local/mysql —disable-shared Если вы имеете дело с MySQL 4.0.5 и компилятором HP-UX, можете воспользоваться следующей командой: СС=сс СХХ=аСС CFLAGS=+DD64 CXXFLAGS=+DD64 ./configure \ —with-extra-character-set=complex Ошибки приведенного ниже типа можно игнорировать: аСС: warning 901: unknown o p t i o n : documentation
ч
- 3 ' : use +help for o n l i n e
Если configure выдаст следующую ошибку, проверьте, не находится ли путь к компилятору K&R перед путем к компиляторам HP-UX С и C++: checking for cc option to accept ANSI С . . . по configure: e r r o r : MySQL requires an ANSI С compiler (and a C++ compiler). Try gcc. See the I n s t a l l a t i o n chapter in the Reference Manual. Другая причина невозможности компиляции может заключаться в том, что вы не определили флаг +DD64, как было указано выше. Можно воспользоваться бинарным дистрибутивом MySQL для HP-UX 10.20 на HPUX 11. У нас есть сообщения от ряда пользователей, у которых этот дистрибутив хорошо работает под управлением HP-UX 11. В случае возникновения каких-либо проблем проверьте уровень исправлений (patch level) своей системы HP-UX. 2.6.5.3. Замечания по IBM-AIX Автоматическое обнаружение компилятора х1С пропущено в Autoconf, поэтому перед запуском configure необходимо установить множество переменных. В следующем примере демонстрируется использование компилятора IBM: export CC="xlc_r -ma -03 - q s t r i c t -qoptimize=3 -qmaxmem=8192 " export CXX="xlC_r -ma -03 - q s t r i c t -qoptimize=3 -qmaxmem=8192" export CFLAGS="-I /usr/local/include" export LDFLAGS="-L /usr/local/lib" export CPPFLAGS=$CFLAGS export CXXFLAGS=$CFLAGS
2.6. Замечания по поводу конкретных операционных систем
189
./configure —prefix=/usr/local \ —localstatedir=/var/mysql \ —sysconfdir=/etc/mysql \ —sbindir='/usr/local/bin' \ —libexecdir='/usr/local/bin 1 \ —enable-thread-safe-client \ —enable-large-files Перечисленные опции используются для компиляции дистрибутива MySQL, который
можно найти по адресу http://www-frec.bull.com/. Если в предыдущей строке configure вы замените -03 на -02, то должны будете также удалить опцию - q s t r i c t . Это ограничение компилятора С от IBM. Если вы применяете дсс или egcs для компиляции MySQL, то должны использовать флаг -fno-exceptions, потому что поддержка исключений у gcc/egcs небезопасна в отношении потоков. (Проверено для egcs 1.1.) Существуют также некоторые проблемы с ассемблером IBM, из-за которых он генерирует неудачный код при работе с дсс. Мы советуем использовать следующую строку configure с egcs и дсс 2.95 на AIX: СС="дсс -pipe -mcpu=power -Wa,-many" \ СХХ="дсс -pipe -mcpu=power -Wa,-many" \ CXXFLAGS="-felide-constructors -fno-exceptions - f n o - r t t i " \ . / c o n f i g u r e — p r e f i x = / u s r / l o c a l / m y s q l —with-low-memory Опции -Wa и -many необходимы для успешной компиляции. В компании IBM знают об этой проблеме, однако не торопятся ее исправлять, поскольку существует возможность ее обхода. Мы не знаем, нужна ли опция -fno-exceptions для дсс 2.95, но так как код MySQL не использует исключений, и эта опция генерирует более быстрый код, рекомендуем всегда ее применять с компиляторами gcc/egcs. Если вы столкнетесь с проблемами в ассемблерном коде, попробуйте изменить значение опции -гасри=ххх, чтобы оно соответствовало типу вашего процессора. Возможно, понадобится указать power2, power или powerpc. Как альтернатива, может понадобиться 604 или 604е. Мы не на сто процентов уверены, но предполагаем, что значение power должно оказаться безопасным в большинстве случаев, даже если у вас машина power2. Если вы не знаете, какой тип процессора установлен, выполните команду uname -m. Она выдаст строку, которая выглядит как 000514676700, в формате xxyyyyyymmss, где хх и ss - всегда 00, уууууу - уникальный системный идентификатор и mm - идентификатор процессора. Описание этих значений доступно по адресу:
http://publib.boulder.ibm.com/doc_link/en_US/a_doc_lib/cmds/aixcmds5/uname.htm Это предоставит информацию о типе и модели машины, которую вы можете использовать для определения типа центрального процессора. Если возникают проблемы с сигналами (MySQL неожиданно зависает при высокой нагрузке), возможно, они связаны с ошибками операционной системы, которые касаются механизма потоков и сигналов. В этом случае вы можете указать MySQL не использовать сигналы, сконфигурировав его следующим образом:
CFLAGS=-DDONT_USE_THR_ALARM CXX=gcc \ CXXFLAGS="-felide-constructors -fno-exceptions -fno-rtti \ -DDONT_USE_THR_ALARM" \ ./configure —prefix=/usr/local/mysql —with-debug \ —with-low-memory
190
Глава 2. Установка MySQL
Это не повлияет на производительность MySQL, но приведет к побочному эффекту вы не сможете уничтожать спящие процессы клиентов, подключенных к серверу, с помощью команды mysqladmin k i l l или mysqladmin shutdown. Клиент зависнет при выдаче следующей команды. В некоторых версиях AIX компоновка с libbind.a приводит к сбросу образа памяти при вызове getservbyname (). Это ошибка AIX и о ней нужно сообщать в компанию IBM. С AIX 4.2.1 и дсс необходимо провести описанные далее изменения. После конфигурирования отредактировать config.h и include/my_config.h, изменив строку: #define HAVE_SNPRINTF I на: #undef HAVE_SNPRINTF В mysqld. ее добавить прототип initgroups (): #ifdef _AIX41 extern "C" int initgroups(const char *,int); tendif Если процессу mysqld нужно выделить много памяти, недостаточно просто воспользоваться ulimit -d unlimited. Вы можете также модифицировать mysqld_safe, добавив строку вроде следующей: export LDR_CNTRL='MAXDATA=0x80000000' Дополнительную информацию по использованию большого объема памяти можно найти по адресу http://publibl6.boulder.ibm.com/pseries/en_US/aixprggd/genprogc/ lrg_prg_support.htm.
2.6.5.4. Замечания по SunOS 4 В среде SunOS 4 для компиляции MySQL требуется поддержка потоков MITpthreads. В свою очередь, это означает необходимость использования GNU make. Некоторые системы SunOS 4 имеют проблемы с динамическими библиотеками и libtool. Во избежание этих проблем следует пользоваться приведенной ниже строкой configure: ./configure —disable-shared
—with-mysqld-ldflags=-all-static
Во время компиляции readline вы можете получить предупреждения о двойных определениях. Их можно проигнорировать. При компиляции mysqld могут выдаваться предупреждения типа "implicit declaration of function" ("неявное объявление функции"). Их также можно игнорировать.
2.6.5.5. Замечания по Alpha-DEC-Unix (Tru64) Если вы применяете eges 1.1.2 в среде Digital Unix, то должны модернизировать его до дсс 2.95.2, поскольку с eges на машинах DEC связаны серьезные ошибки. При компиляции многопоточных программ под Digital Unix документация рекомендует использовать опцию -pthread для компиляторов ее и есх, а также библиотек -lmach и -lexc (в дополнение к -lpthread). Вы должны запускать configure примерно так:
2.6. Замечания по поводу конкретных операционных систем
191
СС="сс -pthread" CXX="cxx -pthread -0" \ ./configure —with-named-thread-libs="-lpthread -lmach -lexc - l c " Во время компиляции mysqld, возможно, будет выдано несколько предупреждений, вроде таких:
mysqld.cc: In function void handle_connections()': mysqld.ee:626: passing long unsigned int *' as argument 3 of accept(int,sockadddr *, int * ) ' Вы можете спокойно проигнорировать эти предупреждения. Они появляются потому, что configure может обнаруживать только ошибки, но не предупреждения. Если вы запустите сервер непосредственно из командной строки, у вас могут возникнуть проблемы с его зависанием при выходе из системы. (При выходе из системы все ваши процессы получают сигнал SIGHUP.) Если это так, попробуйте запустить сервер следующим образом:
nohup mysqld [опции] & nohup заставляет последующую команду игнорировать все сигналы SIGHUP, поступающие от терминала. В качестве альтернативного способа запускайте сервер вызовом сценария mysqld_safe, который запускает mysqld, используя nohup. См. раздел 4.1.3. Если возникают проблемы при компиляции mysys/get_opt.c, просто удалите строку #def ine _NO_PROTO в начале этого файла. Для случая компилятора Compaq CC будет работать следующая строка configure:
СС="сс -pthread 11 CFLAGS="-O4 -ansi_alias -ansi_args -fast -inline speed all -arch host" CXX="cxx -pthread" CXXFLAGS="-O4 -ansi_alias -ansi_args -fast -inline speed a l l \ -arch host -noexceptions - n o r t t i " export CC CFLAGS CXX CXXFLAGS ./configure \ —prefix=/usr/local/mysql \ —with-low-memory \ —enable-large-files \ —enable-shared=yes \ —with-named-thread-libs="-lpthread -lmach -lexc - l c " gnumake Если во время компоновки mysql возникли проблемы с компиляцией с разделяемыми библиотеками, как показано выше, вы должны быть готовы обойти это, выполнив следующие команды: cd mysql
/bin/sh ../libtool —mode=link exx -pthread -03 -DDBUG_OFF \ -04 -ansi_alias -ansi_args -fast -inline speed \ -speculate all \ -arch host -DUNDEF_HAVE_GETHOSTBYNAME_R \ -o mysql mysql.о readline.o sql_string.o completion_hash.o \ ../readline/libreadline.a -leurses \ ../libmysql/.libs/libmysqlclient.so -lm cd .. gnumake gnumake install scripts/mysql_install__db
Глава 2. Установка MySQL
192
2.6.5.6. Замечания по Alpha-DEC-OSF/1 Если вы столкнулись с проблемами компиляции и работаете с компиляторами DEC СС и дсс, попробуйте запустить configure вот так: СС=сс CFLAGS=-0 СХХ=дсс CXXFLAGS=-O3 \ ./configure —prefix=/usr/local/mysql Если проблемы связаны с файлом casm.h, можно создать файл-заглушку c_asm.h: touch include/c_asm.h CC=gcc CFLAGS=-I./include \ CXX=gcc CXXFLAGS=-O3
\
./configure —prefix=/usr/local/mysql Имейте в виду, что следующие проблемы с программой Id можно решить, загрузив последний набор исправлений от DEC (Compaq) из http://ftp.support.compaq.com/ public/unix/. В операционной системе OSF/1 V4.0D с компилятором, именованным как " DEC С V5.6-071 on Digital Unix V4.0 (Rev. 878)", последний странно себя ведет (неопределенные символы asm), /bin/Id также выглядит поврежденным (проблемы с ошибками типа exit undefined во время компоновки mysqld). В этой системе нам удалось скомпилировать MySQL со следующей строкой configure, после замены /bin/Id версией из состава OSF 4.0C: CC=gcc CXX=gcc CXXFLAGS=-03 ./configure --prefix=/usr/local/mysql С компилятором от компании Digital "C++ V6.1-029" должно работать следующее: СС=сс -pthread CFLAGS=-04 -ansi_alias -ansi_args -fast -inline speed \ -speculate a l l -arch host CXX=cxx -pthread CXXFLAGS=-04 -ansi_alias -ansi_args -fast -inline speed \ -speculate a l l -arch host -noexceptions - n o r t t i export CC CFLAGS CXX CXXFLAGS ./configure —prefix=/usr/mysql/mysql \ —with-mysqld-ldflags=-all-static —disable-shared \ —with-named-thread-libs="-lmach -lexc - l c " В некоторых версиях OSF/1 повреждена функция alloca(). Это можно исправить, удалив из config.h строку, которая определяет HAVE_ALLOCA. Функция allocaO также может иметь неправильный прототип в /usr/include/ alloca.h. Предупреждение, которое появляется в результате этого, можно проигнорировать. configure использует автоматически следующие библиотеки потоков: —with-named-threadlibs="-lpthread -lmach -lexc - l c " . При использовании дсс вы можете запустить configure так, как показано ниже: CFLAGS=-D_PTHREAD_USE_D4 CXX=gcc CXXFLAGS=-03 . / c o n f i g u r e
...
Если возникают проблемы с сигналами (MySQL непредсказуемым образом сбоит при высокой нагрузке), это может быть связано с ошибками операционной системы, которые относятся к потокам и сигналам. В этом случае можно заставить MySQL не использовать сигналы:
2.6. Замечания по поводу конкретных операционных систем
193
CFLAGS=-DDONT_USE_THR_ALARM \ CXXFLAGS=-DDONT_USE_THR_ALARM \ ./configure ... Последнее не повлияет на производительность MySQL, однако приведет к побочному эффекту - вы не сможете уничтожать спящие процессы клиентов, подключенные к серверу, с помощью команды mysqladmin k i l l или mysqladmin shutdown. Клиент зависнет при выдаче очередной команды. При работе с компилятором дсс 2.95.2, возможно, вы получите следующее сообщение об ошибке:
sql_acl.cc:1456: Internal compiler error in 4scan_region', at except.c:2566 Please submit a full bug report. Чтобы это исправить, потребуется перейти в каталог sql и вырезать, а затем вставить последнюю строку вызова дсс, изменив -03 на -00 (или добавив -00 сразу после дсс, если в строке вызова компилятора опции -0 отсутствуют). После того, как это будет сделано, нужно вернуться в каталог верхнего уровня и запустить make снова.
2.6.5.7. Замечания по SGI Irix Если вы работаете в среде Irix версии 6.5.3 или более новой, mysqld сможет порождать потоки, только если вы запустите его от имени пользователя, имеющего привилегии CAP_SCHED_MGT (например, root), или же предоставив серверу mysqld эту привилегию с помощью следующей команды: cheap "CAP_SCHED_MGT+epi" /opt/mysql/libexec/mysqld Может потребоваться убрать определение некоторых символов после выполнения configure и перед запуском компиляции. В некоторых реализациях Irix функция a l l o c a ( ) сбоит. Если сервер mysqld зависает при выполнении некоторых операторов SELECT, удалите из config.h строку, содержащую HAVE_ALLOC и HAVE_ALLOC_H. Если не работает mysqladmin c r e a t e , удалите из config.h строку, определяющую HAVE_READDIR_R. Также может понадобиться удалить строку HAVE_TERM_H. SGI рекомендует применять все исправления, которые можно найти на странице:
http://support.sgi.com/surfzone/patches/patchset/б.2_indigo.rps.html Если во время компиляции mysqld. ее вы получаете что-то вроде: " / u s r / i n c l u d e / c u r s e s . h " , l i n e 82: e r r o r ( 1 0 8 4 ) : i n v a l i d combination of type введите следующую команду, находясь в корневом каталоге дерева исходных текстов MySQL:
extra/replace bool cursesjDool < /usr/include/curses.h > include/curses.h make Поступали также сообщения об ошибках, решение которых уже запланировано. Если работает только один поток, производительность низка. Преодолеть это можно, запустив еще одного клиента. Это приведет к возрастанию скорости от 2 до 10 раз для остальных. Упомянутую проблему с потоками в Irix понять трудно; можете поэкспериментировать в поисках лучшего решение, пока это не будет исправлено.
Глава 2. Установка MySQL
194
Если вы работаете с компилятором дсс, вызов configure должен выглядеть следующим образом: COgcc CXX=gcc CXXFLAGS=-O3 \ ./configure --prefix=/usr/local/mysql --enable-thread-safe-client \ —with-named-thread-libs=-lpthread В среде Irix 6.5 с родными компиляторами Irix С и C++ версии 1.3Л.2 работает такая команда: СС=сс СХХ=СС CFLAGS='-O3 -n32 -TARG:platform=IP22 -I/usr/local/include \ -L/usr/local/lib 1 CXXFLAGS='-03 -n32 -TARG:platform=IP22 \ -I/usr/local/include -L/usr/local/lib 1 \ ./configure —prefix=/usr/local/mysql —with-innodb —with-berkeley-db \ —with-libwrap=/usr/local \ —with-named-curses-libs=/usr/local/lib/libncurses.a 2.6.5.8. Замечания по SCO Текущий порт MySQL тестировался только в системах "sco3.2v5.0.5", "sco3.2v5.0.6" и "sco3.2v5.0.7". Кроме того, существенный прогресс достигнут в версии "sco 3.2v4.2". На данный момент для OpenServer мы рекомендуем пользоваться компилятором дсс 2.95.2. При этом должна получиться компиляция MySQL, если выполнено приведенное ниже конфигурирование: CC=gcc CXX=gcc ./configure ... [опции) 1. В среде OpenServer 5.0.x понадобится компилятор gcc 2.95.2pl или более новый, от компании Skunware. Зайдите на http://www.sco.com/skunkware/ и выберите обзор пакетов для OpenServer, или же выгрузите его через FTP с ftp2.caldera.com из каталога pub/skunkware/osr5/devtools/gcc. 2. Вам понадобится порт GCC 2.5.x этого продукта и система разработки (Development system). Они необходимы для данной версии SCO Unix. Недостаточно будет просто иметь GCC Dev system. 3. Вы должны будете получить пакет FSU Pthreads и установить его. Его можно найти по адресу http://moss.esc.ncsu.edu/~mueller/ftp/pub/PART/pthreads.tar.gz. 4. FSU Pthreads можно скомпилировать в среде SCO UNIX 4.2 с tcpip, либо в OpenServer 3.0, либо в Open Desktop 3.0 (OS 3.0 ODT 3.0) с установленным пакетом SCO Development System, включающим в себя порт GCC 2.5.x. Для ODT или OS 3.0 понадобится хороший порт GCC 2.5.x. Без этого может возникнуть множество проблем. Порт этого продукта требует наличия SCO Unix Development System. Без этого пакета у вас не будет нужных библиотек и компоновщика. 5. Чтобы собрать FSU Pthreads на вашей системе, выполните следующие шаги: 1. Запустите ./configure, находясь в каталоге threads/src, и выберите опцию SCO OpenServer. Эта команда скопирует Makefile.SC05 в Makefile. 2. Запустите make. 3. Чтобы установить в каталог по умолчанию /usr/include, войдите в систему как root, перейдите в каталог threads/src и запустите make i n s t a l l . 6. Помните, что при сборке MySQL необходимо применять GNU make.
2.6. Замечания по поводу конкретных операционных систем
195
7. Если mysqld_safe не запускается от имени root, возможно, вы получите только 110 открытых файлов на процесс, mysqld запишет сообщение об этом в файл журнала. 8. В системе SCO 3.2V5.0.5 вы должны использовать FSU Pthreads версии 3.5с или выше. Также нужно использовать компилятор дсс 2.95.2 или более новый. Следующая команда configure должна работать: ./configure —prefix=/usr/local/raysql
—disable-shared
9. В системе SCO 3.2V4.2 необходимо использовать FSU Pthreads версии 3.5с или выше. Работает следующая команда configure: CFLAGS="-D_XOPEN_XPG4" CXX=gcc CXXFLAGS="-D_XOPEN_XPG4" \ ./configure \ —prefix=/usr/local/mysql \ —with-named-thread-libs="-lgthreads -lsocket -lgen - I g t h r e a d s " \ —with-named-curses-libs="-lcurses" Возможно, вы столкнетесь с некоторыми проблемами во включаемых файлах. В этом случае можно загрузить новые специфичные для SCO включаемые файлы из http://www.mysql.com/Downloads/SCO/SCO-3.2v4.2-includes.tar.gz. Эти файлы потребуется распаковать в каталоге include дерева исходных текстов MySQL. Ниже представлены замечания по разработке в SCO. •
MySQL должен автоматически обнаружить FSU Pthreads и скомпоновать mysqld с -Igthreads -lsocket -Igthreads.
•
Библиотеки разработки SCO являются реентерабельными в FSU Pthreads. SCO требует от функций своих библиотек реентерабельности, поэтому они должны быть таковыми и в FSU Pthreads. FSU Pthreads в OpenServer пытается использовать схему SCO создания реентерабельных библиотек.
•
FSU Pthreads (по крайней мере, версия из сайта http://www.mysql.com/) поставляется скомпонованной с GNU ma 11 ос. Если вы обнаружите проблемы с использованием памяти, убедитесь, что gmalloc.o включен в l i b g t h r e a d s . a и libgthreads.so.
•
В FSU Pthreads следующие системные вызовы работают с потоками pthread: r e a d ( ) , w r i t e ( ) , getmsg(), connect(), a c c e p t ( ) , s e l e c t ( ) и w a i t ( ) .
•
Исправление CSSA-2001-SCO.35.2 (упомянуто в списке как "erg711905dscrremap security patch (version 2.0.0)") нарушает работу потоков FSU и делает mysqld нестабильным. Если вы хотите запускать mysqld на машине под управлением OpenServer 5.0.6, его потребуется удалить.
•
SCO предоставляет исправления для операционных систем OpenServer 5.0.x по адресу ftp://ftp.sco.com/pub/openserver5.
•
SCO предоставляет для OpenServer 5.0.x исправления, касающиеся защиты и libsocket.so.2, по адресам ftp://ftp.sco.com/pub/security/OpenServer и ftp://ftp.sco.com/pub/security/sse.
•
Исправления защиты для систем до OSR506. Исправления для telnetd достунпы по адресу ftp://stage.caldera.com/pub/security/openserver/ или ftp://stage.caldera.com/pub/security/openserver/CSSA-2001-SCO.10/; там же
Глава 2. Установка MySQL
196
находятся исправления для обеих библиотек - l i b s o c k e t . so. 2 и l i b r e s o l v . so. 1 - с инструкциями по установке в системах с версиями до OSR506. Возможно, имеет смысл установить эти ичсправления перед попытками компиляции и применения MySQL. 2.6.5.9. Замечания по SCO UnixWare версии 7.1.x В среде UnixWare 7.1.0 необходимо использовать версию MySQL, начиная с 3.22.13, чтобы получить исправления проблем переносимости и проблем операционной системы. Мы компилируем MySQL в UnixWare версии 7.1.x, используя следующую команду configure: СС=сс СХХ=СС ./configure
—prefix=/usr/local/mysql
Если вы хотите воспользоваться компилятором дсс, то должны иметь версию дсс 2.95.2 или более новую. СС=дсс СХХ=д++ ./configure
—prefix=/usr/local/raysql
S C O предлагает исправления д л я о п е р а ц и о н н ы х с и с т е м U n i x W a r e 7.1.1 и 7.1.3 н а ftp://ftp.sco.com/pub/unixware7, а для OpenUNIX 8.0.0 - на ftp://ftp.sco.com/pub/ openunix8. Информацию об исправлениях в системе безопасности SCO можно найти по адресу ftp://ftp.sco.com/pub/security/OpenUNIX для систем OpenUnix и по адресу ftp://ftp.sco.com/pub/security/UnixWare для систем UnixWare.
2.6.6. Замечания по OS/2 MySQL использует довольно много открытых файлов. В связи с этим вам придется добавить в файл CONFIG.SYS строку, подобную следующей: SET EMXOPT=-c - п - Ы 0 2 4
Если этого не сделать, скорее всего, вы столкнетесь с описанной ниже ошибкой: File 'xxxx' not found (Errcode: 24) При работе с MySQL в OS/2 Warp 3 необходимо, чтобы в системе был установлен пакет FixPack 2.9 или выше. Для OS/2 Warp 4 нужен FixPack 4 или выше. Это требование накладывается библиотекой Pthreads. MySQL должен быть установлен в разделе диска, поддерживающем длинные имена файлов, таком как HPFS, FAT32 и так далее. Сценарий INSTALL.CMD должен запускаться через собственный командный интерпретатор OS/2 CMD.EXE, поскольку он может не работать в среде альтернативных оболочек вроде 4OS2.EXE. Сценарий s c r i p t s / m y s q l - i n s t a l l - d b переименован. Теперь он называется i n s t a l l . c m d и является REXX-сценарием, который устанавливает параметры безопасности MySQL по умолчанию и создает пиктограмму Workplace Shell для MySQL. Поддержка динамических модулей скомпилирована, но еще недостаточно протестирована. Динамические модули должны компилироваться с использованием библиотеки времени выполнения Pthreads. gcc - Z d l l -Zmt - Z c r t d l l = p t h r d r t l - I . . / i n c l u d e - I . . / r e g e x - I . . \ -o example udf_example.cc - L . . / l i b - l m y s q l c l i e n t udf_example.def mv e x a m p l e . d l l example.udf
2.7. Замечания по поводу установки Perl -
197
На заметку!
;
В связи с ограничениями, накладываемыми OS/2, длина имен модулей UDF не должна превышать 8 символов (без расширения). Модули расположены в каталоге /mysql2/udf. Сценарий - safe-mysqld.cmd помещает этот каталог в переменную окружения BEGINLIBPATH. При ис' пользовании UDF-модулей указанные расширения имен игнорируются. Предполагается, что они '-' всегда будут .udf. Например, в Unix разделяемый модуль может иметь имя example.so и функции из него будет загружаться следующим образом: mysql> CREATE FUNCTION metaphon RETURNS STRING SONAME ' e x a m p l e . s o ' ; В среде OS/2 модуль должен называться example.udf, но указывать его расширение не придется: 1
mysql> CREATE FUNCTION metaphon RETURNS STRING SONAME ' e x a m p l e ;
2.6.7. Замечания по BeOS Некоторые разработчики BeOS сообщали нам, что MySQL перенесен в среду операционной системы BeOS на 80%, однако уже долгое время мы не получали от них дополнительных новостей.
2.7. Замечания по поводу установки Perl Поддержка языка Perl для MySQL обеспечивается за счет предоставления клиентского интерфейса DBI/DBD. Этот интерфейс требует наличия Perl версии 5.6.0 или более поздней. Он не работает для старых версий Perl. Если вы хотите применять транзакции вместе с Perl DBI, вам понадобится модуль DBI: :mysql версии 1.2216 или более новый. Рекомендуется версия 2.9003 и выше. Если вы используете клиентскую библиотеку MySQL 4.1, вам понадобится DBI: :mysql версии 2.9003 или выше. Начиная с MySQL 3.22.8, поддержка Perl больше не входит в состав дистрибутива MySQL. Вы можете получить необходимые модули для Unix на сайте http://search.cpan.org, или воспользоваться программой ActiveState ppm в среде Windows. В последующих разделах описано, как это сделать. Поддержку Perl для MySQL следует устанавливать, если вы хотите запускать сценарии тестов производительности. См. раздел 6.1.4.
2.7.1. Установка Perl под Unix Поддержка Perl для MySQL требует, чтобы на машине была установлена поддержка клиентских программ MySQL (библиотеки и заголовочные файлы). Большинство способов установки по умолчанию копируют все необходимые файлы. Однако если вы устанавливаете MySQL под Linux из RPM-файлов, убедитесь, что у вас установлен RPMмодуль разработчика. Клиентские программы находятся в клиентском RPM-модуле, однако поддержка для программирования - в RPM-модуле разработчика. Файлы, необходимые для установки поддержки Perl, можно получить из CPAN (Copmrehensive Perl Archive Network) по адресу h t t p : //search. cpan. org. Простейший способ установки Perl под Unix предполагает использование CPANмодулей. Например: shell> perl -MCPAN -e shell cpan> i n s t a l l DBI cpan> i n s t a l l DBD::mysql
198
Глава 2. Установка MySQL
Установка DBD: :mysql выполняет множество тестов. Эти тесты должны иметь возможность подключаться к локальному серверу MySQL от имени анонимного пользователя без пароля. Если вы уже удалили анонимные учетные записи или назначили им пароли, тесты не запустятся. С помощью force i n s t a l l DBD: rraysql можно проигнорировать тесты, завершившиеся неудачей. DBI требует наличия модуля Data::Dumper. Возможно, он уже установлен. Если нет, его нужно установить до установки DBI. Можно также загрузить дистрибутивы модулей в форме сжатого архива t a r и собрать их вручную. Например, процедура распаковки и сборки дистрибутив DBI выглядит следующим образом: 1. Распакуйте дистрибутив в текущем каталоге: shell> gunzip < DBI-ВЕРСИЯ.tar.gz
| tar xvf -
Эта команда создает каталог по имени DBI-ВЕРСИЯ. 2. Перейдите в корневой каталог распакованного дистрибутива: shell> cd ЬЫ-ВЕРСИЯ 3. Выполните сборку дистрибутива с компиляцией всех кодов: shell> perl Makefile.PL shell> make shell> make test shell> make install Команда make t e s t важна, поскольку она проверяет работоспособность модуля. Помните, что когда вы запускаете эту команду во время установки модуля DBD: :mysql, сервер MySQL должен быть запущен, иначе тесты не пройдут. Неплохо переустанавливать DBD::mysql всякий раз, когда устанавливается новый выпуск MySQL, особенно, если вы видите, что ваши DBI-сценарии перестали работать после обновления MySQL. Если у вас нет прав доступа для установки модулей Perl в системный каталог, или если вы хотите установить их локально, следующая ссылка может в этом помочь: http://servers.digitaldaze.com/extensions/perl/modules.htrallmodules. Читайте материал под заголовком "Installing New Modules that Require Locally Installed Modules" ("Установка новых модулей, которые требуют локально установленных модулей").
2.7.2. Установка ActiveState Perl под Windows Для того чтобы установить модуль DBD MySQL с ActiveState Perl под Windows, необходимо: • Получить ActiveState Perl по адресу ActivePerl/ и установить его.
http://www.activestate.com/Products/
• Открыть консольное окно ("окно DOS"). • Если необходимо, установить переменную окружения НТТРргоху, например, так: set HTTP_proxy=my.proxy,com:3128 • Запустить программу PPM: С:\> C:\perl\bin\ppm.pl
2.7. Замечания по поводу установки Perl
199
• Установить DBI, если это еще не сделано: ppm> install DBI • Если все прошло успешно, запустить следующую команду: install \ ftp://ftp.de.uu.net/pub/CPAN/authors/id/JWIED/DBD-raysql-l.2212.x86.ppd Эта процедура должна работать, по крайней мере, с ActiveState Perl версии 5.6. Если же данную процедуру выполнить не удается, вам придется установить вместо этого драйвер MyODBC и подключаться к серверу MySQL через ODBC: use DBI; $dbh= DBI->connect("DBI:ODBC:$dsn",$user,$password) || die "Ошибка $DBI::errstr при подключении к $dsn\n";
2.7.3. Проблемы использования интерфейса Perl DBI/DBD Если Perl сообщает, что не может обнаружить модуль .. /mysql/mysql. so, это значит, что он не может найти разделяемую библиотеку libmysql client .so. Это можно исправить одним из следующих методов: • Скомпилировать дистрибутив DBD: :mysql с помощью команды perl Makefile.PL - s t a t i c -config вместо perl Makefile.PL. • Скопировать библиотеку libmysqlclient. so в каталог, в котором хранятся другие разделяемые библиотеки (предположительно, /usr/lib или /lib). • Модифицировать опции -L, используемые для компиляции DBD: :mysql, чтобы они отражали реальное местоположение libmysqlclient .so. • В среде Linux можно добавить путь к каталогу, содержащему libmysqlclient.so, в файл /etc/Id.so.conf. • Добавить путь к каталогу, содержащему libmysqlclient.so, в переменную окружения LDRUNPATH. Некоторые системы используют вместо нее переменную LD_LIBRARY_PATH. Имейте в виду, что возможно, вам также понадобится модифицировать опции -L, если имеются и другие библиотеки, которых компоновщик не может найти. Например, если он не находит libc, потому что она находится в /lib, а команда компоновки указывает -L/usr/lib, измените эту опцию на -L/lib или добавьте ее в команду вызова компоновщика. Если DBD::mysql выдает приведенные ниже ошибки, вероятно, вы используете дсс (или старый бинарный код, скомпилированный с помощью дсс): /usr/bin/perl: can't resolve symbol ' moddi3' /usr/bin/perl: can't resolve symbol ' divdi3' Добавьте опцию -L/usr/lib/gcc-lib/... -lgcc к команде вызова компоновщика при сборке библиотеки mysql.so (проверяйте вывод make для mysql.so, когда компилируете Perl-клиент). Опция -L должна указывать путь к каталогу, в котором в вашей системе хранится библиотека libgcc. a. Другая причина возникновения этой проблемы может состоять в том, что Perl и MySQL не скомпилированы одним и тем же компилятором, то есть дсс. В этом случае их потребуется перекомпилировать с помощью дсс.
200
Глава 2. Установка MySQL
При запуске тестов вы можете получить следующее сообщение об ошибке от DBD::mysql:
t/OObase install_driver(mysql) failed: Can't load '../blib/arch/auto/DBD/mysql/mysql.so' for module DBD::mysql: ../blib/arch/auto/DBD/mysql/mysql.so: undefined symbol: uncompress at /usr/lib/perl5/5.00503/i586-linux/DynaLoader.pm line 169. Это означает, что вы должны включить библиотеку сжатия -lz в строку компоновки. Это можно сделать, изменив строку файла lib/DBD/mysql/Install .pm с $sysliblist .= " -lm"; на $sysliblist .= " -lm -lz"; После этого вы должны запустить make realclean и после этого выполнить установку сначала. Если вы собираетесь устанавливать DBI в среду SCO, то должны отредактировать файлы Makefile в DBl-xxx и всех его подкаталогах. Помните, что это предполагает использование компилятора дсс 2.95.2 или более нового: Старый:
Новый:
СС = ее
СС = дсс
CCCDLFLAGS = -KPIC -Wl,-Bexport
CCCDLFLAGS = -fpic
CCDLFLAGS = -wl,-Bexport
CCDLFLAGS =
LD = Id
LD = gee -G -fpic
LDDLFLAGS = -G -L/usr/local/lib LDFLAGS = -belf -L/usr/local/lib
LDDLFLAGS = -L/usr/local/lib LDFLAGS = -L/usr/local/lib
LD = Id
LD = gec -G -fpic
OPTIMISE = -Od
OPTIMISE = -01
Старый: CCCFLAGS = -belf -dy -wO -U M_XENIX -DPERL_SC05 -I/usr/local/include Новый: CCFLAGS = -U M_XENIX -DPERL_SC05
-I/usr/local/include
Эти исправления необходимы, поскольку динамический загрузчик не сможет загрузить модули DBI, если они скомпилированы с помощью ice или ее. Если вы хотите использовать модули Perl в системах, не поддерживающих динамическую компоновку (таких как SCO), можете сгенерировать статическую версию Perl, включающую в себя модуль DBD::mysql. Способ заставить это работать состоит в том, чтобы сгенерировать собственную версию Perl со статически скомпонованным в нее кодом DBI и затем установить его поверх существующей версии Perl. Затем необходимо использовать его для статической компоновки с кодом модуля DBD и утсановить еще раз. На SCO нужно иметь следующие установки переменных окружения: LD_LIBRARY_PATH=/lib:/usr/lib:/usr/local/lib:/usr/progressive/lib
2.7. Замечания по поводу установки Perl
201
или: LD_LIBRARY_PATH=/usr/lib:/lib:/usr/local/lib:/usr/ccs/lib:\ /usr/progressive/lib:/usr/skunk/lib LIBPATH=/usr/lib:/lib:/usr/local/lib:/usr/ccs/lib:\ /usr/progressive/lib:/usr/skunk/lib MANPATH=scohelp:/usr/man:/usr/locall/man:/usr/local/man:\ /usr/skunk/man: Сначала выполните сборку Perl, включающую скомпонованный статически модуль DBI, запустив в каталоге, в котором находится дистрибутив DBI, следующие команды: shell> shell> shell> shell>
perl Makefile.PL -static -config make make install make perl
Затем необходимо установить новую версию Perl. Вывод команды make perl покажет явно все команды make, которые нужно выполнить для целей установки. В среде SCO это будет make -f Makefile.aperl inst_perl MAP_TARGET=perl. После этого, используя только что собранную версию Perl, создайте другую версию Perl, которая статически включает модуль DBD: :mysql, выполнив приведенные ниже команды в каталоге, в котором расположен дистрибутив DBD: :mysql: shell> shell> shell> shell>
perl Makefile.PL -static -config make make install make perl
И, наконец, установите этот новый вариант Perl. Опять-таки, вывод make perl покажет все команды make, которые необходимо будет выполнить для установки.
3
Использование программ MySQL
В
настоящей главе дается краткий обзор программ, предлагаемых компанией MySQL AB, и описывается, каким образом задаются опции при работе с ними. Большинство опций являются специальными для той или иной программы, но синтаксис, с помощью которого они задаются, одинаковый для всех программ. В следующих главах предлагается более подробное описание каждой из программ, включая и то, какие опции она распознает.
3.1. Обзор программ MySQL Компания MySQL AB предоставляет несколько типов программ: • Сервер MySQL и сценарии запуска сервера: • mysqld - сервер MySQL. • mysqld_saf e, mysql. server и mysqldjnulti - сценарии запуска сервера. • mysql_install_db инициализирует каталог данных и начальные базы данных. Более подробно эти программы рассматриваются в главе 4. • Клиентские программы, получающие доступ к серверу: • mysql - клиент командной строки, используемый для выполнения SQLоператоров в интерактивном режиме или режиме пакетной обработки. • mysql с с (MySQL Control Center - Центр управления MySQL) представляет собой интерактивный графический инструмент для выполнения SQL-операторов и администрирования. • mysqladmin - клиент администрирования. • mysql check выполняет операции по обслуживанию таблиц. • mysqldump и mysqlhotcopy - создают резервные копии баз данных. • mysqlimport импортирует файлы данных. • mysql show отображает информацию о базах данных и таблицах. Эти программы более подробно описываются в главе 7.
3.2. Запуск MySQL-программ
203
• Утилиты, которые функционируют независимо от сервера: • myisamchk выполняет операции по обслуживанию таблиц. • myisampack генерирует сжатые таблицы, предназначенные только для чтения. • mysqlbinlog - инструмент для обработки файлов бинарных журналов. • perror отображает значение кода ошибки. Описание утилиты myisamchk дается в главе рассматриваются в главе 7.
4, остальные
программы
Большинство дистрибутивов MySQL включают все перечисленные выше программы кроме тех, которые зависят от конкретной платформы. (Например, сценарии запуска сервера в среде Windows не используются.) Исключение составляют RPM-дистрибутивы, которые являются еще более специализированными: существует отдельный RPM-пакет для сервера, отдельный RPM-пакет для клиентских программ и так далее. При отсутствии одной или нескольких программ обратитесь в главу 2, в которой представлена информация о типах дистрибутивов MySQL и о конкретном их составе. Может оказаться так, что придется установить какие-то дополнительные приложения.
3.2. Запуск MySQL-программ Чтобы запустить программу MySQL из командной строки (то есть из командной оболочки или командной строки), введите имя программы, после которого укажите опции или любые другие аргументы, необходимые для того, чтобы сообщить программе, какую операцию она должна выполнить. Ниже приведены примеры команд, вызывающих ту или иную программу. "shell>" представляет подсказку командного интерпретатора и не является частью вводимой команды. То, как именно выглядит подсказка, будет зависеть от конкретного интерпретатора. Типичными являются следующие подсказки: $ для sh или bash, % для csh или tcsh и С:\> для command.com или cmd.exe в Windows. shell> shell> shell> shell>
mysql test mysqladmin extended-status variables mysqlshow —help mysqldump —user=root personnel
Аргументы, начинающиеся с '-', представляют собой аргументы опций. Обычно через них задается тип соединения, которое программа должна установить с сервером, или изменения, вносимые в режим работы программы. Синтаксис опций описан в разделе 3.3. Аргументы, не относящиеся к опциям (в начале которых не стоит ' - ' ) , предоставляют дополнительную информацию для программы. Например, программа mysql интерпретирует первый аргумент такого типа (указанный без тире) как имя базы данных; таким образом, команда mysql t e s t означает, что вы хотите использовать базу данных с именем t e s t . В последних разделах, посвященных отдельным программам, перечисляются распознаваемые той или иной программой опции и разъясняются любые дополнительные аргументы помимо тех, что используются для опций. Некоторые опции являются общими для большинства программ. Основные из них это опции —host, —user и —password, с помощью которых задаются параметры соединения. В них указывается имя главного компьютера (хоста), на котором выполняется сервер MySQL, а также имя пользователя и пароль используемой учетной записи MySQL. Все клиентские программы MySQL распознают эти опции и позволяют конкре-
204
Глава 3. Использование программ MySQL
тизировать, к какому серверу будет производиться подключение, и какая учетная запись на нем будет использоваться. Для вызова программ MySQL может понадобиться указать путь к каталогу bin, в котором они установлены. Чаще всего это необходимо в том случае, когда вы получаете ошибку наподобие "program not found" ("программа не найдена") при каждой попытке запуска программы MySQL из каталога, отличного от bin. Для удобства можно добавить имя пути к каталогу bin в переменную окружения PATH. Тогда, чтобы запустить программу, потребуется указать только ее имя, а не весь путь. Для получения более подробной информации о настройке PATH смотрите соответствующую документацию по командному интерпретатору, поскольку синтаксис, используемый для установки переменных окружения, зависит от конкретного интерпретатора.
3.3. Задание опций программы Существует несколько способов задания опций для программ MySQL: • Опции можно задавать в командной строке, непосредственно после имени программы. Чаще всего таким образом задаются опции, применяемые для конкретного вызова программы. • Опции можно определять в файле опций, который программа считывает во время запуска. Таким образом лучше задавать те опции, которые вы хотите, чтобы программа считывала при каждом запуске. • Опции можно задавать в переменных окружения. Использовать переменные удобно для тех, опций, которые должны выполняться при каждом запуске программы, хотя на практике с такой же целью чаще применяются файлы опций. (В разделе 4.9.2 рассматривается ситуация, когда переменные окружения могут оказаться очень полезными: они используются для того, чтобы задать TCP/IP-порт и файл Unix-сокета для сервера и для клиентских программ одновременно.) Для определения указанных опций программы MySQL сначала просматривают переменные окружения, потом файл опций и только после этого командную строку. Если опция задана несколько раз, использоваться будет то ее значение, которое встречается последним. Это означает, что значения переменных окружения обладают самым низким приоритетом, а значения опций командной строки - самым высоким. Воспользоваться преимуществом такого вида обработки опций программами MySQL можно следующими образом: в файле опций для опций программы укажите значения по умолчанию, тогда эти опции не придется вводить при каждом запуске программы, но зато всегда при необходимости их можно будет перекрыть, задав нужные значения в командной строке.
3.3.1. Использование опций в командной строке Существуют следующие правила для задания программных опций в командной строке: • Опции указываются после имени команды. • Аргумент опции всегда начинается с одиночного или двойного тире ('-' или ' — ' ) , в зависимости от того, коротким или длинным является ее название. Многие опции принимают обе формы. Например, -? и —help представляют собой краткий и длинный варианты опции, сообщающей программе MySQL о необходимости вывести справочную информацию.
3.3. Задание опций программы
205
• Имена опций чувствительны к регистру символов. Опции -v и -V являются допустимыми, но совершенно разными (это краткие формы опций --verbose и —version соответственно). • Некоторые опции принимают значение, следующее за названием опции. Например, -h localhost и --host=localhost указывают клиентской программе хост сервера MySQL. Значение опции сообщает программе имя хоста, на котором выполняется сервер MySQL. •
Когда используется длинный вариант названия опции, принимающей значения, название опции и присваиваемое значение следует разделять знаком '='. В случае использования краткого варианта названия опции, принимающей значения, значение может следовать сразу за буквенным символом опции или отделяться от него пробелом, (-hlocalhost и -h localhost эквивалентны). Исключением из этого правила является опция для задания пароля MySQL. Она может указываться в длинном варианте как — password=3Ha<jeHne_napcui# или --password. В последнем случае (когда значение пароля отсутствует), программа предложит ввести пароль. Может также применяться короткая форма этой опции -рзначение_пароля или -р. Однако если используется короткая форма и указывается значение пароля, пробел между буквенным символом опции и значением пароля не ставится. Причина этого состоит в том, что при наличии пробела программа не может в точности определить, является ли следующий за пробелом аргумент значением пароля или же каким-либо другим аргументом. Поэтому приведенные ниже команды имеют абсолютно разные значения: shell> mysql -ptest shell> mysql -p test Первая команда указывает mysql использовать значение t e s t в качестве пароля, но не задает имя базы данных по умолчанию. Вторая команда указывает mysql на необходимость запроса пароля, a t e s t трактуется как имя базы данных по умолчанию.
MySQL 4.0 предлагает дополнительные возможности для задания опций. Эти изменения были появились в версии MySQL 4.O.2. Часть из них касается способа, которым задаются опции с режимами "enabled" ("включена") и "disabled" ("отключена"), а также использования опций, которые присутствуют в одной версии MySQL и отсутствуют в другой. Упомянутые возможности рассматриваются в данном разделе. К другим изменениям относятся методы применения опций для установки программных переменных. Этот вопрос более подробно излагается в разделе 3.3.4. Некоторые опции управляют поведенческими аспектами, которые могут быть включены или отключены. Например, клиент mysql поддерживает опцию —column-names, определяющую, отображать ли строку с именами столбцов в начале результата запроса. По умолчанию эта опция включена. Однако в некоторых случаях ее может понадобиться отключить, например, при отправке выходных данных mysql в другую программу, ожидающую получить только данные, а не строку начальных заголовков. Для отключения —column-names допускается использование следующих вариантов: —disable-column-names —skip-column-names —column-names=0
206
Глава 3. Использование программ MySQL
Указание префикса -disable или префикса -skip, или же суффикса =0 приводит к одному и тому же результату - опция будет отключена. Форма включения для данной опции может указываться следующими способами: —column-names —enable-column-names —column-names=l Еще одним изменением, касающимся обработки опций, которое было введено в MySQL 4.0, является то, что теперь для опций командной строки можно использовать префикс —loose. Когда перед опцией указывается такой префикс, программа, если она не распознает опцию, не завершает работу с выдачей сообщения об ошибке, а вместо этого отображает только предупреждение:
shell> mysql —loose-no-such-option mysql: WARNING: unknown option '—no-such-option' mysql: ПРЕДУПРЕЖДЕНИЕ: неизвестная опция ' —no-such-option' Использование префикса —loose может пригодиться, если программы запускаются сразу из нескольких установок MySQL на одном компьютере, по крайней мере, в тех случаях, когда версии установок не ниже 4.0.2. Этот префикс особенно полезен, когда опции перечисляются в файле опций. Опция, которая не распознается ни одной версией данной программы, может указываться с префиксом --loose (или loose в файле опций). Версии программы, которые не распознают эту опцию, будут выдавать соответствующее предупреждение и игнорировать ее. Для применения такого метода требуется, чтобы все используемые версии соответствовали версии MySQL 4.0.2 или выше, поскольку более старые версии не распознают обозначение --loose.
3.3.2. Использование файлов опций Программы MySQL могут считывать опции запуска из файлов опций (которые еще иногда называют "конфигурационными файлами"). Такие файлы обеспечивают удобный способ задания наиболее часто используемых опций, так что необходимость вводить эти опции в командной строке при каждом запуске программы отпадает. Файлы опций доступны, начиная с версии MySQL 3.22. Программы, поддерживающие файлы конфигурации, следующие: myisamchk, myisampack, mysql, mysql.server, mysqladmin, mysqlbinlog, mysqlcc, mysqlcheck, mysqld, mysqld_safe, mysqldump, mysqlhotcopy, mysqlimport и mysqlshow. В среде Windows программы MySQL считывают опции запуска из следующих файлов: Имя файла KATAJIOr_WINDOWS\my. i n i С: \my. cnf
Назначение Глобальные опции. Глобальные опции.
KATAJlor_WlNDOWS представляет расположение каталога вашей копии Windows. Чаще всего это C:\Windows или C:\WinNT. Точное местонахождение каталога можно определить с помощью переменной окружения, воспользовавшись следующей командой: С:\> echo %WINDIR% В среде Unix программы MySQL считывают опции запуска из следующих файлов:
3.3. Задание опций программы
207
Имя файла
Назначение
/etc/ray.cnf
Глобальные опции.
КАТАЛОГ_ДАННЫХ/ту. c n f
Специальные опции для сервера.
defaults-extra-file
Файл, заданный через —defaults-extra-fПе=луть, если он существует. Специальные опции для пользователя.
~ /. my. enf
КАТАЛОГ_ДАННЫХ представляет расположение каталога данных MySQL. Обычно это /usr/local/mysql/data для бинарной установки или /usr/local/var - для исходной. Обратите внимание, что это каталог данных, который был указан во время конфигурации, а не каталог, заданный с помощью —datadir при запуске mysqld. Использование —datadir во время выполнения не влияет на то, где сервер будет искать файлы опций, потому делает он это перед тем, как приступает к обработке аргументов командной строки. MySQL ищет файлы опций в описанном выше порядке и, если они существуют, считывает их. При наличии сразу нескольких файлов опций, опция, которая указана в файле, считанном позже, будет иметь преимущественное значение по сравнению с такой же опцией, указанной в файле, считанном раньше. Любая опция, которая может быть задана в командной строке во время работы с программой MySQL, может быть задана и в файле опций. Для получения списка доступных для данной программы опций, запустите ее с опцией —help. Синтаксис, с помощью которого задаются опции в файле опций, подобен синтаксису, используемому в командной строке, за исключением того, что двойное тире в начале имени опции можно опустить. Например, в командной строке указывается —quick и —host=localhost, а файле опций указывается quick и host=localhost. Опция — loose-имя_опции в файле опций задается в виде 1 ооse-имя^опции. Пустые строки в файлах опций игнорируются, а непустые могут принимать любую из следующих форм: • комментарий ;комментарий Строки комментариев начинаются с '#' или ' ; ' . В версии MySQL 4.0.14 и выше комментарий '#' может начинаться также и с середины строки. •
[группа)
группа - это имя программы или группы, для которой устанавливаются опции. После строки группы все остальные строки типа имя_опции или set-variable будут относиться к названной группе до конца файла или пока не будет указана другая строка группы. • имя_опции Данная форма эквивалента —имя_опции в командной строке. •
имя_ опции=значение Данная форма эквивалентна —имя_опции= значение в командной строке. В файле опций перед и после знака '=' можно поставить пробел, в командной строке это делать нельзя. Начиная с версии MySQL 4.0.16, для указания значения используются как двойные, так и одинарные кавычки. Это может пригодиться, если значение содержит символ комментария '#' или пробел.
208
Глава 3. Использование программ MySQL
•
set-variable = имя_переменной=значение Устанавливает определенное значение программной переменной имя_переменной. Данная форма эквивалентна —зеЬчаг1аЫе=имя_переменной=значение в командной строке. Пробелы можно ставить перед и после первого знака '=', но никак не перед и после второго. Начиная с версии MySQL 4.0, такой синтаксис считается устаревшим. Для получения более подробной информации об установке программных переменных обратитесь в раздел 3.3.4. Пробельные символы в начале и в конце имен и значений опций автоматически удаляются. Для отображения символов забоя, табуляции, новой строки, возврата каретки, обратной косой черты и пробела в значениях опций можно использовать следующие управляющие последовательности: *\b\ ' \ t ' , '\n\ '\г', '\\' и '\s\ В среде Windows путь должен указываться в опции с использованием разделителя 7 \ а не '\\ Если требуется применять символ *\\ его необходимо удвоить, то есть '\\\ поскольку символ ' \' в MySQL является управляющим. Если название группы опций и название программы совпадают, опции, указанные в группе, будут применяться конкретно для данной программы. Группа опций [client] считывается всеми клиентскими программами (но не mysqld). Это позволяет задавать в ней опции, которые будут применяться для каждого клиента. Например, группа [client] идеально подходит для того, чтобы указать в ней пароль, который используется вами для подключения к серверу. (Обязательно убедитесь, что доступ по чтению и записи имеется только у вас, чтобы другие пользователи не смогли узнать ваш пароль.) Прежде чем вносить опцию в группу [client], проверьте, распознается ли она всеми используемыми клиентскими программами. Те программы, которым данная опция неизвестна, после запуска сразу же завершат работу, предварительно выдав сообщение об ошибке. Начиная с версии MySQL 4.0.14, можно создавать группы опций, которые должны считываться только одной конкретной серией впусков сервера mysqld, используя для этих групп имена наподобие [mysqld-4.0], [mysqld-4.1 ] и так далее. Следующая группа указывает, что опция —new должна применяться только серверами MySQL с номерами версий 4.0.x: [mysqld-4.О] new Ниже показан пример типичного файла глобальных опций: [client] port=3306 socket=/tmp/mysql.sock [mysqld] port=3306 socket=/tmp/mysql.sock key_buffer_size=16M max_allowed_packet=8M [mysqldump] quick В этом файле опций используется синтаксис имя_переменной= значение для строк, устанавливающих значения переменных key_buffer_size и max_allowed_packet.
3.3. Задание опций программы
209
В версиях, предшествующих MySQL 4.0.2, вместо этого следует использовать синтаксис set-variable (описанный ранее в этом разделе). Ниже можно видеть пример типичного файла пользовательских опций: [client] # Следующий пароль будет отправлен всем стандартным клиентам MySQL password="my_password" [mysql] no-auto-rehash set-variable = connect_timeout=2 [mysqlhotcopy] interactive-timeout В этом файле для установки переменной connect_timeout применяется синтаксис set-variable. Начиная с версии MySQL 4.0.2, значение переменной можно установить и просто как connect_timeout=2. Если установлен исходный дистрибутив, образцы файлов опций с именами my-xxxx.cnf можно найти в каталоге support-files. Если установлен бинарный дистрибутив, то папку support-files следует искать в каталоге установки MySQL (обычно это C:\mysql в Windows, и /usr/local/mysql в Unix). На текущий момент там предложены образцы для малых, средних, больших и очень больших систем. Чтобы поэкспериментировать с одним из таких файлов, скопируйте его в C:\my.cnf (Windows) или в файл . my. cnf домашнего каталога (Unix). $ На заметку! Ц. В Windows расширение файла опций .cnf может не отображаться. Все программы MySQL, которые поддерживают файлы опций, используют следующие опции командной строки: • —no-defaults. He считывать файлы опций. • —print-defaults. Выводить имя программы и все опции, получаемые из конфигурационных файлов. • —defaults-file=HM#_nyTH. Использовать только данный файл опций. имя_путиэто полный путь к файлу. ^ • --defaults-extra-file=HM#_nyTn. Считывать данный файл опций после файла глобальных опций, но перед файлом пользовательских опций. имя_пути - это полный путь к файлу. Для корректной работы опций необходимо, чтобы каждая из них следовала сразу же за именем команды в командной строке, за исключением опции —print-defaults, которая может указываться сразу после —defaults-file или —defaults-extra-file. В основных сценариях для выполнения синтаксического анализа файлов опций используйте программу m y p r i n t d e f a u l t s . Ниже показан пример возможных выходных данных этой программы при запросе отобразить опции, которые будут найдены в группах [client] и [mysql]: shell> myj?rint_defaults client mysql ~port=3306 —socket=/tmp/mysql.sock —no-auto-rehash
Глава 3. Использование программ MySQL
210 .
На заметку!
р. § IE | || %'t §Й jf
Разработчикам стоит помнить следующее. Анализ файлов опций выполняется в клиентской библиотеке С просто путем обработки всех совпадающих опций (то есть опций, находящихся в COOTветствующих группах) до обработки любых аргументов, указываемых в командной строке. Это прекрасно подходит для программ, использующих последний из всех встречающихся экземпляров опции, которая была задана несколько раз. При наличии программы С или C++, которая может обрабатывать многочисленные заданные опции, но не может считывать файлы опций, потребуется добавить только две строки, чтобы предоставить ее возможность делать это. Просмотрите исходный код любого из стандартных клиентов MySQL, чтобы узнать, как добиться такого результата.
Интерфейсы к MySQL для других языков основаны на клиентской библиотеке С, и некоторые из них обеспечивают способ получения доступ к содержимому файлов опций. К ним относятся интерфейсы для языков Perl и Python. Более подробную информацию можно найти в документации по выбранному интерфейсу.
3.3.3. Использование переменных окружения для задания опций Чтобы задать опцию с помощью переменной окружения, установите значение переменной, применяя синтаксис, подходящий для вашего процессора комментариев. Например, в Windows или NetWare для задания имени учетной записи MySQL можно установить переменную USER. Для этого применяется следующий синтаксис: SET USER=ваше_имя В среде Unix синтаксис будет зависеть от командной оболочки. Предположим, необходимо задать порт TCP/IP через переменную MYSQL__TCP_PORT. Для командной оболочки Bourne и ее вариаций (sh, bash, zsh и так далее) синтаксис выглядит следующим образом: MYSQLJTCP_PORT=3306 Для оболочек c s h n t c s h синтаксис будет таким: setenv MYSQL_TCP_PORT 3306 Команды по установке переменных окружения могут выполняться непосредственно из командной строки, при этом они немедленно вступают в силу. Такие настройки будут действовать вплоть до выхода из программы. Чтобы эти же настройки действовали каждый раз при входе в программу, необходимо поместить их в соответствующую команду или команды в файле запуска, который считывается интерпретатором команд перед каждым запуском. Типичными файлами запуска являются: AUTOEXEC.BAT (для Windows), .bash_profile (для bash) и .tcshrc (для tcsh). Дополнительную информацию можно найти в документации по интерпретатору команд. В приложении Б перечислены все переменные окружения, которые оказывают влияние на работу программ MySQL.
3.3.4. Использование опций для установки программных переменных В большинстве программ MySQL существуют внутренние переменные, которые можно устанавливать и во время выполнения. Начиная с версии MySQL 4.0.2, программные переменные устанавливаются так же, как и любая опция с длинным именем, принимающая значение. Например, в mysql существует переменная max_allowed_packet,
3.3. Задание опций программы
211
с помощью которой контролируется максимальный размер коммуникационного буфера. Чтобы в mysql установить для этой переменной значение 16 Мбайт, воспользуйтесь одной из следующих команд: shell> mysql --max_allowed_packet=16777216 shell> mysql —max_allowed_packet=16M Первая команда указывает значение в байтах, а вторая - в мегабайтах. В качестве суффикса могут применяться символы К, м или G (как в верхнем, так и в нижнем регистре), обозначающие единицы измерения - килобайты, мегабайты или гигабайты соответственно. В файле опций двойное тире перед названием переменной не ставится: [mysql] max_allowed_packet=16777216 Можно записать и так: [mysql] max_allowed_packet=l6M По желанию символы подчеркивания ('_') в имени переменной могут заменяться знаками тире ('-'). В версиях, предшествующих MySQL 4.0.2, имена программных переменных не распознаются как имена опций. Поэтому для присвоения переменной значения необходимо пользоваться опцией —set-variable: shell> mysql shell> mysql
~set-variable=max__allowed_packet=16777216 —set-variable=max_allowedjpacket=16M
В файле опций двойное тире ('--') перед названием опции опускается: [mysql] set-variable = max_allowed_packet=16777216 Или так: [mysql] set-variable = max_allowed_packet=16M В версиях MySQL, предшествующих 4.0.2, при использовании опции --set-variable знаки подчеркивания в именах переменных заменять знаками тире нельзя. Опция —set-variable по-прежнему распознается в версиях MySQL 4.0.2 и выше, однако считается устаревшей. Некоторые серверные переменные можно устанавливать во время выполнения. Более подробная информация по данному вопросу представлена в разделе 4.23Л.2.
4
Администрирование баз данных fcrf настоящей главе описаны вопросы, касающиеся администрирования установлени и ^ ной копии MySQL, а именно - конфигурирование сервера, управление пользовательскими учетными записями и выполнение резервного копирования.
41. Сервер MySQL и сценарии запуска сервера Сервер MySQL - mysqld - это главная программа, выполняющая большую часть работы в рамках установленной копии MySQL. Вместе с сервером идут еще несколько сценариев, которые выполняют операции запуска во время установки MySQL или представляют собой вспомогательные программы, оказывающие помощь при запуске или останове сервера. В этом разделе предлагается обзор самого сервера и связанных с ним программ, а также информация о сценариях запуска. Сведения о конфигурировании сервера можно найти в разделе 4.2.
4.1.1. Обзор серверных сценариев и утилит Все программы MySQL используют огромное число различных опций. Однако каждая из них распознает специальную опцию —help, с помощью которой можно получить описание принимаемых данной программой опций. Например, попробуйте запустить mysqld —help. Для всех стандартных программ опции по умолчанию можно переопределить, указав необходимые из них в командной строке или файле опций (см. раздел 3.3). В приведенном ниже списке представлены краткие описания MySQL-сервера и связанных с ним программ: • mysqld. Демон SQL (то есть сервер MySQL). Для работы клиентских программ необходимо, чтобы mysqld был запущен и успешно функционировал, поскольку клиенты получают доступ к базам данных через соединение с сервером. См. раздел 4.2. • mysqld-max. Версия сервера, предлагающая дополнительные функциональные возможности. См. раздел 4.1.2.
4.1. Сервер MySQL и сценарии запуска сервера
213
• mysqld_safe. Сценарий запуска сервера. mysqld_safe пытается запустить сервер mysqld-max, если он существует, в противном случае запускает mysqld. См. раздел 4.1.3. • mysql. server. Сценарий запуска сервера. Применяется в системах, использующих каталоги запуска, в которых содержатся сценарии, запускающие системные службы для определенных уровней выполнения. Он вызывает mysqld_safe для запуска MySQL-сервера. См. раздел 4.1.4. • mysqldmulti. Сценарий запуска сервера, который может запускать или останавливать сразу несколько серверов, существующих на системе. См. раздел 4.1.5. • mysql_install_db. Данный сценарий создает таблицы привилегий MySQL с привилегиями по умолчанию. Обычно используется только один раз - при первой установке MySQL в системе. • mysql_fix_privilege_tables. Данный сценарий используется после модернизации для внесения в текущие таблицы привилегий любых изменений, появившихся в новой версии MySQL. Существуют еще и несколько других программ, которые также запускаются на главном компьютере сервера: • myisamchk. Утилита, необходимая для описания, проверки, оптимизации и исправления таблиц My ISAM. Более подробно рассматривается в разделе 4.6.2. • make_binary_distribution. Данная программа выполняет сборку бинарной версии скомпилированного MySQL. Для удобства других пользователей MySQL ее можно впоследствии отправить через FTP в каталог /pub/mysql/upload сайта ftp.mysql.com. • mysqlbug. Сценарий, отвечающий за составление отчетов об ошибках в MySQL. Может использоваться для отправки отчета об ошибке в список рассылки. (Для описания отчета в онлайновом режиме посетите сайт h t t p : //bugs .mysql.com/.)
4.1.2. Расширенный MySQL-сервер mysqld-max Сервер MySQL-Мах - это версия MySQL-сервера mysqld, разработанная для поддержки дополнительных функциональных возможностей. Выбор используемого дистрибутива зависит от платформы: • Windows. Бинарный дистрибутив MySQL включает как стандартный сервер (mysqld.exe), так и сервер MySQL-Max (mysqld-max.exe), поэтому в специальном дистрибутиве необходимости не будет. Просто воспользуйтесь стандартным дистрибутивом для Windows, который доступен по адресу http://dev.mysql.com/ downloads/mysql-4.0.html. См. раздел 2.2.1. • Linux. При установке MySQL с помощью дистрибутивов RPM сначала используйте обычный RPM-пакет MySQL-server для установки стандартного сервера под названием mysqld. Затем, используя RPM-пакет MySQL-Max, установите сервер mysqld-max. RPM-пакет MySQL-Max предполагает, что RPM-пакет стандартного сервера уже установлен. Более подробную информацию, касающуюся пакетов Linux RPM, можно найти в разделе 2.2.2.
214
Глава 4. Администрирование баз данных
• Все остальные дистрибутивы MySQL-Max содержат единственный сервер, называемый mysqld, однако обладающий дополнительными функциональными возможностями. Бинарные дистрибутивы MySQL-Max доступны на Web-сайте MySQL AB по адресу http://dev.mysql.com/downloads/mysql-max-4.О.html. Компания MySQL AB выполняет сборку серверов MySQL-Max с использованием следующих опций конфигурации: •
— with-server-suf f ix=-max. Данная опция добавляет суффикс -max к строке версии mysqld.
•
—with-innodb. Данная опция активизирует поддержку механизма хранения innoDB. Серверы MySQL-Max всегда включают поддержку innoDB, но фактически эта опция необходима только для версии MySQL 3.23. Начиная с MySQL 4, механизм хранения InnoDB входит в состав бинарных дистрибутивов по умолчанию, поэтому для получения поддержки InnoDB сервер MySQL-Max не нужен.
•
— with-bdb. Данная опция активизирует поддержку механизма хранения Berkley DB (BDB).
• CFLAGS=-DUSE_SYMDIR. Данное определение включает поддержку символических ссылок для Windows. Бинарные дистрибутивы MySQL-Max удобны для тех, кто хочет устанавливать заранее скомпилированные программы. При сборке сервера с помощью исходного дистрибутива появляется возможность создать свой собственный сервер Мах-типа, активизировав во время конфигурирования те же функции, с которыми собраны бинарные дистрибутивы MySQL-Max. Серверы MySQL-Max включают механизм хранения BDB (Berkeley DB) всегда, когда это возможно, однако не все платформы поддерживают BDB. Ниже показано, какие платформы обеспечивают такую поддержку для бинарных серверов MySQL-Max, а какие нет. Система
Поддержка BDB
AIX 4.3 HP-UX 11.0 Linux-Alpha Linux-IA-64 Linux-Intel Mac OS X NetWare SCO OSR5 Solaris-Intel Solaris-SPARC UnixWare Windows/NT
Нет Нет Нет Нет Да Нет Нет Да Нет Да Да Да
Чтобы узнать, какие механизмы хранения поддерживаются сервером, воспользуйтесь следующим оператором: mysql> SHOW ENGINES;
4.1. Сервер MySQL и сценарии запуска сервера
215
В версиях, предшествующих MySQL 4.1.2 оператор SHOW ENGINES не доступен. Вместо него используется приведенный ниже оператор, который позволяет проверить значение переменной для того или иного механизма хранения: mysql> SHOW VARIABLES LIKE •havejk 1 ; I + I I I I I I I I
Variable_name
| Value | + + have_bdb | NO I have_crypt | YES | have_innodb | YES | have_isam | NO | have_raid | NO | have_symlink | DISABLED | have_openssl | NO | have_query_cache | YES |
+
+
+
Значения во втором столбце указывают уровень поддержки сервером той или иной функции: Значение
Описание
YES
Функция поддерживается и активна.
N0
Функция не поддерживается.
DISABLED
Функция поддерживается, но была отключена.
Значение N0 указывает, что сервер компилировался без поддержки данной функции, поэтому о н а не может быть активизирована. Значение DISABLED появляется либо потому, что сервер запускался с опцией, отключающей данную функцию, либо потому, что были указаны не все опции, необходимые для работы с ней. В последнем случае файл журнала ошибок имя_хоста.еп будет содержать причину, по которой была отключена данная опция. С и т у а ц и я , когда появляется значение DISABLED, м о ж е т возникнуть п р и к о м п и л я ции InnoDB в M y S Q L 3.23. В M y S Q L 3.23 д л я н а с т р о й к и табличного п р о с т р а н с т в а InnoDB во в р е м я запуска сервера потребуется указать, п о крайней мере, о п ц и ю innodb_data_f i l e _ p a t h . Без нее InnoDB сам себя отключит. С м . раздел 9.3. Д л я BDB также можно задавать определенные опции конфигурации, однако даже если этого не делать, BDB автоматически отключаться не будет. См. раздел 8.4.3. Кроме того, значение DISABLED для InnoDB, BDB или ISAM может появляться и тогда, когда сервер компилировался с поддержкой таких механизмов хранения, но б ы л запущен с опциями — s k i p - i n n o d b , — s k i p - b d b или — s k i p i s a m . Начиная с версии 3.23, все серверы M y S Q L поддерживают таблицы My ISAM, поскольку My ISAM является механизмом хранения по умолчанию.
4.1.3. Сценарий запуска сервера mysqldsafe Сценарий mysqld_safe рекомендуется использовать для запуска сервера mysqld под управлением ОС Unix и NetWare. mysqld_safe обеспечивает набор дополнительных функций безопасности, таких как перезапуск сервера в случае ошибки и запись инфор-
Глава 4. Администрирование баз данных
216
мации времени выполнения в журнал ошибок. Особенности функционирования в NetWare перечислены ниже, в этом же разделе. £: На заметку! В версиях, предшествующих MySQL 4.0, сценарий mysqld_saf e называется safe_mysqld. В /•', целях обратной совместимости бинарные дистрибутивы MySQL еще некоторое время будут Ь включать s a f e j n y s q l d в качестве символической ссылки на mysqld_safе.
По умолчанию mysqld_safe пытается запустить исполняемый файл с именем mysqld-max, если таковой существует; в противном случае он запускает mysqld. Обратите внимание на следующие моменты: • В Linux поведение mysqld_safe имеет определенное значение для MySQL-Max RPM. RPM устанавливает исполняемый файл с именем mysqld-max, после чего mysqldsafe будет автоматически использовать этот файл. • При установке дистрибутива MySQL-Max, который включает сервер mysqld-max, и последующей модернизации MySQL до версии, отличной от Max, mysqld_safe будет по-прежнему пытаться запустить старый сервер mysqld-max. Поэтому после проведения модернизации подобного рода необходимо вручную удалить старый сервер mysqld-max; это гарантирует, что mysqld_safe будет использовать новый сервер mysqld. Чтобы изменить настройки по умолчанию и указать явно, какой сервер должен использоваться, для mysqldsafe потребуется задать опцию —mysqld или —mysqld-version. Большинство опций для mysqld_safe совпадают с таковыми для mysqld (см. раздел 4.2.1). Все опции, указанные для mysqldsafe в командной строке, передаются в mysqld. Если понадобится использовать любые опции, которые являются специфическими для mysqldsafe, но не поддерживаются mysqld, они не должны указываться в командной строке. Вместо этого их следует перечислить в группе [mysqld_safe] файла опций. См. раздел 3.3.2. mysqld_safe считывает все опции из разделов [mysqld], [server] и [mysqld_safe] в файлах опций. Для обратной совместимости он также читает и разделы [safejnysqld], хотя при использовании MySQL 4.0 и выше такие разделы следует переименовывать на [mysqld_safe]. mysqldsaf e поддерживает следующие опции: •
—basediг=луть. Путь к каталогу установки MySQL.
•
—core-f ile-size=pa3Mep. Размер файла ядра, который mysqld должен иметь возможность создать. Значение опции передается в ulimit -с.
•
—datadi r=путь. Путь к каталогу данных.
•
—defaults-extra-file=путь. Имя файла опций, который будет считываться дополнительно, помимо обычных файлов опций.
•
—defaults-file=nyTb. Имя файла опций, который будет считываться вместо обычных файлов опций.
•
—егг-1од=путь. Старая форма опции —log-error, используемая в версиях, предшествующих MySQL 4.O.
4.1. Сервер MySQL и сценарии запуска сервера •
217
—1ес11г=путь. Путь к каталогу, в котором установлена программа mysqld. Используйте данную опцию для явного указания местонахождения сервера.
• —1од-еггог=луть. Регистрирует ошибку в заданном файле. См. раздел 4.8.1. • —mysqld=nNM_nporpaMMbi. Имя программы сервера (в каталоге ledir), которую следует запустить. • --mysqld-versioп=cyффикc. Данная опция подобна опции —mysqld, но для имени программы сервера указывается только суффикс. Предполагается, что базовым именем является mysqld. Например, при использовании --mysqld-version=max сценарий mysqld_safe запустит программу mysqld-max из каталога l e d i r . Если аргумент —mysqld-version не указан, mysqld_safe использует mysqld из каталога ledir. •
—nice=приоритет. С помощью программы nice устанавливает заданный приоритет планирования для сервера.
• —no-defaults. He считывать никакие файлы опций. • —open-files-limit=KcwjwecTBo. Количество файлов, которые должны быть открыты mysqld. Значение опции передается в ulimit -n. Обратите внимание, что для корректной работы данной опции потребуется запускать mysqld_safe от имени привилегированного (root) пользователя. • —pid-f Ие=путь. Путь к файлу идентификатора процесса. • --port=HOMep_nopTa. Номер порта, который будет использоваться для прослушивания TCP/IP-соединений. • —socket=nyTb. Файл Unix-сокета, используемый для локальных соединений. • --timezone=3OHa. Присваивает определенное значение переменной часового пояса TZ. По вопросам допустимых форматов для указания часовых поясов обращайтесь в документацию по операционной системе. •
—user={имя_пользователя \ идентификатор_пользователя}. Запускает сервер mysqld от имени пользователя с именем имя_пользователя или числовым идентификатором идентификатор_пользователя. ("Пользователь" в данном контексте означает учетную запись для входа в систему, а не пользователя MySQL, указанного в таблицах привилегий.)
Сценарий mysqld_saf e написан так, что позволяет нормально запускать сервер, установленный как из исходного дистрибутива MySQL, так и бинарного, несмотря на то, что размещение сервера при каждом указанном виде установки осуществляется немного поразному. (См. раздел 2.1.5.) Для mysqld_safe обязательным является одно из следующих условий: • Сервер и базы данных могут должны быть найдены относительно каталога, из которого вызывается mysqldsafe. При использовании бинарных дистрибутивов mysqld_safe в своем рабочем каталоге ищет папки bin и data. При использовании исходных дистрибутивов mysqldsafe ищет папки libexec и var. Выполнение данного условия обязательно, если mysqld_saf e запускается из каталога установки MySQL (например, для бинарного дистрибутива этим каталогом будет
/usr /local /mysql).
218
Глава 4. Администрирование баз данных
• Если сервер и базы данных не могут быть найдены относительно рабочего каталога, mysqldsafe пытается найти их по абсолютным именам путей, обычно это /usr/local/libexec и /usr/local/var. Фактическое местонахождение сервера и базы данных определяется через значения, заданные в дистрибутиве во время его сборки. Они будут корректными, если MySQL установлен в каталоге, указанном во время конфигурирования. Поскольку mysqld_safe будет пытаться найти сервер и базы данных относительно своего собственного рабочего каталога, бинарный MySQL можно установить в любое место, при этом запуск mysqld_safe должен осуществляться из каталога установки MySQL: shell> cd каталог_установки_тузд1 shell> bin/mysqld_safe & Если не удается запустить mysqld_safe даже из каталога установки MySQL, можно задать опции —ledir и -datadir, чтобы указать каталоги, где в вашей системе размещаются сервер и базы данных. Обычно редактировать сценарий mysqld_safe не нужно. Вместо этого конфигурирование mysqldsafe осуществляется с помощью опций командной строки или опций в разделе [mysqld_safe] файла my.cnf. Лишь в редких случаях может понадобиться редактирование сценария mysqld_saf e для корректного запуска сервера. Однако тогда, при будущих модернизациях версий MySQL, модифицированный сценарий mysqld_safe будет заменен новым. Чтобы избежать этого, потребуется делать копию отредактированной версии, которую при необходимости можно будет установить повторно. В среде NetWare mysqld_safe - это загружаемый модуль NLM, который переносится с оригинального основного сценария Unix; выполняет он следующие действия: 1. Запускает набор проверок системы и опций. 2. Запускает проверку таблиц My ISAM и ISAM. 3. Обеспечивает экранное представление сервера MySQL. 4. Запускает mysqld, осуществляет текущий мониторинг, а также перезапуск в случае ошибки. 5. Регистрирует сообщение об ошибке в mysqld в журнале имя_хоста.еи, который находится в каталоге данных. 6. Регистрирует экранный вывод mysqld_safe в журнале имя^хоста. err, который находится в каталоге данных.
4.1.4. Сценарий запуска сервера mysql.server Дистрибутивы MySQL для Unix включают сценарий под названием mysql.server. Он может применяться в системах, подобных Linux и Solaris, которые используют каталоги запуска в стиле System V для запуска и завершения работы системных служб. Кроме того, этот же сценарий применяется компонентами запуска Mac OS Startup Item для MySQL. mysql.server можно найти в подкаталоге support-files каталога установки MySQL или в исходном дереве MySQL. При использовании RPM-пакета сервера Linux (MySQL-server-ВЕРСИЯ.грт), сценарий mysql. server будет уже установлен в каталоге /etc/init .d с именем mysql. Устанавли-
4.1. Сервер MySQL и сценарии запуска сервера
219
вать вручную его не придется. Более подробная информация о RPM-пакетах сервера Linux представлена в разделе 2.2.2. Некоторые производители предлагают RPM-пакеты программ, в которых сценарий запуска устанавливается под другим именем, таким как mysqld. При установке MySQL из исходного дистрибутива или при использовании бинарного формата, в котором автоматическая установка mysql. server не выполняется, mysql. server можно установить вручную. Необходимые для осуществления данной операции действия описаны в разделе 2.4.3. mysql.server считывает опции из разделов [mysql.server] и [mysqld] файлов опций. Для обратной совместимости он также считывает и разделы [mysql_server], хотя в версии MySQL 4.0 и выше такие разделы должны быть переименованы в [mysql.server].
4.1.5. Программа mysqld_multi для управления множественными MySQL-серверами Программа mysqldjnulti предназначена для управления несколькими процессами mysqld, которые отвечают за соединения через различные Unix-сокеты и TCP/IP-порты. Она может запускать и останавливать серверы или же выводить отчет об их текущем состоянии. Программа осуществляет поиск групп [mysqld#] в файле my.cnf (или в файле, указанном в опции —conf ig-f ile). # - это любое положительное целое число. В дальнейшем данное число будет называться номером группы опций, или GNR. Номера групп отличают группы опций друг от друга и используются в качестве аргументов для mysqldmulti, чтобы указать, какие серверы следует запустить, остановить, или о состоянии каких из них необходимо получить отчет. Опции, перечисленные в этих группах, - те же, что использовались бы в группе [mysqld] для запуска mysqld. (См. раздел 2.4.3.) Однако в случае с множественными серверами необходимо, чтобы каждый из них использовал свое собственное значение для опций, таких как файл сокета Unix и номер ТСРЛР-порта. Дополнительные сведения о том, какие опции должны быть уникальными для каждого сервера в окружении с множественными серверами, можно найти в разделе 4.9. Для вызова mysqldjnulti используйте следующий синтаксис: shell> mysqldjnulti [опции] {start|stop|report} [GNR[fGNR]...] s t a r t , stop и report обозначают операцию, которую необходимо выполнить. Указанная операция может быть выполнена на одном или сразу на нескольких серверах, в зависимости от списка номеров GNR, который следует за названием опции. Каждое значение GNR отображает номер группы опций или диапазон таких номеров. Значение должно представлять собой номер в конце названия группы в файле опций. Например, значением GNR для группы [mysqldl7] является число 17. Чтобы указать сразу несколько номеров, между первым и последним числом необходимо поставить тире. Значение GNR 10-13 представляет группы OT[mysqldlO] до [mysqldl3]. Множественные группы или блоки групп можно указывать в командной строке, разделив их запятыми. В списке GNR не должно быть никаких пропусков (пробелов или символов табуляции); все значения после таких пропусков игнорируются. Приведенная ниже команда запускает один сервер, используя группу опций [mysqldl7]: shell> mysqld__multi start 17
220
Глава 4. Администрирование баз данных
Следующая команда останавливает несколько серверов, используя группы опций [mysql8] йот [mysqldlO] ДО [mysqldl3]:
shell> mysqldjnulti start 8,10-13 Чтобы просмотреть пример файла опций, воспользуйтесь такой командой: shell> mysqldjnulti —example Ниже представлен список опций, которые поддерживает mysqldjnulti. •
--config-file=HM#. Указывает имя альтернативного файла опций. Это влияет на то, где mysqldjnulti будет искать группы опций [mysqld#]. Если данная опция отсутствует, все опции считываются из обычного файла my.cnf. Эта опция не влияет на то, откуда mysqldjnulti считывает свои собственные опции, которые всегда берутся из группы [mysqldjnulti] обычного файла my. cnf.
•
—example. Отображает пример файла опций.
•
—help. Отображает справочную информацию и завершает работу.
•
—1од=имя. Указывает имя файла журнала. Если он существует, выходные записи добавляются в конец файла. • —mysqladmin=HM#_nporpaMMb/. Бинарный файл mysqladmin, используемый для останова серверов. •
—туБО{Ы=имя_программы. Бинарный файл mysqld, который должен использоваться. Обратите внимание, что для данной опции в качестве значения можно также указывать mysqld_saf е. Только для этого следует убедиться, что в параметрах переменной окружения PATH присутствует каталог, в котором размещен mysqld, или должным образом настроить mysqld_saf е.
•
--no-log. Регистрировать данные в stdout, а не в системном журнале. По умолчанию выходные данные заносятся в системный журнал. • —password=napcwb. Пароль учетной записи MySQL, который будет использоваться при вызове mysqladmin. Обратите внимание, что значение пароля для данной опции, в отличие от других MySQL-программ, является обязательным. •
—tcp-ip. Подключается к каждому серверу MySQL через TCP/IP-порт, а не Unixсокет. (При отсутствии файла сокета сервер по-прежнему может работать, но доступ к нему будет возможен только через порт TCP/IP.) По умолчанию соединения устанавливаются только с использованием файла сокета Unix. Данная опция оказывает влияние на операции stop и report.
•
—изег=имя_пользователя. Имя пользователя учетной записи MySQL, которое будет использоваться при вызове mysqladmin.
•
—version. Отображает данные о версии и завершает работу.
Ниже представлены некоторые важные замечания по mysqldjnulti. • Удостоверьтесь, что учетная запись MySQL, используемая для останова серверов mysqld (с помощью программы mysqladmin) имеет одно и то же имя пользователя и пароль для каждого сервера. Также убедитесь в наличии привилегии SHUTDOWN. Если необходимые серверы используют много различных имен пользователей и паролей для доступа к административным учетным записям, возможно, понадобится создать учетную запись на каждом сервере с одинаковым паролем и именем
4.1. Сервер MySQL и сценарии запуска сервера
221
пользователя. Например, можно установить общую учетную запись multi_adrain, выполнив следующие команды для каждого сервера: shell> mysql -u root -S /tmp/mysql.sock --рпароль_гооЬ mysql> GRANT SHUTDOWN ON *.* -> TO 'multi^admin'e'localhost1 IDENTIFIED BY 'multipass1; См. раздел 4.4.2. Это потребуется сделать для каждого сервера mysqld. Соответствующим образом изменяйте параметры соединений при подключении к каждому из них. Обратите внимание, хост-часть учетной записи должна разрешать соединения через multiadmin с хоста, на котором вы хотите запускать mysqldjnulti. • Опция —pid-file чрезвычайно важна при использовании mysqld_safe для запуска mysqld (например, —mysqld=mysqld_safe). Каждый mysqld должен иметь свой собственный файл идентификатора процесса. Преимущество применения mysqld_safe вместо mysqld состоит в том, что mysqld_safe "оберегает" процесс mysqld и перезапустит его, если он будет остановлен вследствие сигнала, отправленного через k i l l -9, или по другим причинам, таким как ошибка сегментации. Обратите внимание, что может потребоваться запускать сценарий mysqld_safe из конкретного места. Это означает, что перед запуском mysqldjnulti придется соответствующим образом сменить текущий каталог. В случае возникновения проблем при запуске внимательно просмотрите сценарий mysqld_safe. В частности, просмотрите следующие строки: MY_PWD=4pwd4 # Check if we are starting this relative (for the binary release) # Проверяем,происходит ли запуск относительно каталога (для бинарных версий) if test -d $MY_PWD/data/mysql -a -f ./share/mysql/english/errmsg.sys -a \ -x ./bin/mysqld См. раздел 4.1.З. Тест, запускаемый указанными выше строками, должен пройти успешно, тем не менее, проблемы не исключены. • Файл сокета Unix и номер TCP/IP-порта должны быть разными для каждого mysqld. • Возможно указание опции —user для mysqld, однако тогда сценарий mysqldjnulti необходимо запустить от имени привилегированного (root) пользователя Unix. Наличие опции в файле опций роли не играет; вы просто получите предупреждение, если не являетесь суперпользователем и если процессы mysqld запущены от имени вашей учетной записи Unix.
1 Внимание! р! Убедитесь, что каталог данных полностью доступен для учетной записи Unix, через которую за^ пускается определенный процесс mysqld. Если вы не уверены в своих действиях, не используйте учетную запись r o o t в Unix. Очень важно перед использованием m y s q l d j n u l t i убедиться в том, что вы понимаете значения опций, передаваемых серверам mysqld, равно как в том, почему могут понадобиться отдельные процессы mysqld. He забывайте о риске при использовании множественных серверов mysqld с одним и тем же каталогом данных. Если вы не уверены в своих действиях, отдельные каталоги данных в таком случае - это лучший вариант. Запуск множественных серверов с одним и тем же каталогом данных отнюдь не повышает производительность многопоточной системе. См. раздел 4.9.
222
Глава 4. Администрирование баз данных
Следующий пример демонстрирует, как настроить файл опций для mysqld_multi. Первая и пятая группы [mysqld#] были намеренно исключены из примера, чтобы проиллюстрировать возможность наличия "прорех" в файле опций. Это обеспечивает большую гибкость. Порядок запуска или остановки программ будет зависеть от порядка, в котором они размещаются в файле опций. # Этот файл скорее всего должен находиться в вашем домашнем каталоге # (~/.my.cnf) или в /etc/my.cnf # Версия 2.1 от Яни Толонена (Jani Tolonen) [mysqld_multi] mysqld = /usr/local/bin/mysqld_safe mysqladmin = /usr/local/bin/mysqladmin user = multi_admin password = multipass [mysqld2] socket port pid-file datadir language user [mysqld3] socket port pid-file datadir language user
= = = = =
/tmp/mysql.sock2 3307 /usr/local/mysql/var2/hostname.pid2 /usr/local/mysql/var2 /usr/local/share/mysql/english
= John = = = = = =
/tmp/mysql.sock3 3308 /usr/local/mysql/var3/hostname.pid3 /usr/local/mysql/var3 /usr/local/share/mysql/swedish monty
[mysqld4] socket port pid-file datadir language user
= /tmp/mysql.sock4 = = = = =
3309 /usr/local/mysql/var4/hostname.pid4 /usr/local/mysql/var4 /usr/local/share/mysql/estonia tonu
[mysqld6] socket = /tmp/mysql.sock6 port = 3311 pid-file datadir language user
= = = =
/usr/local/mysql/var6/hostname.pid6 /usr/local/mysql/var6 /usr/local/share/mysql/japanese jani
См. раздел З.З.2.
4.2. Конфигурирование сервера MySQL
223
4.2. Конфигурирование сервера MySQL В данном разделе рассматриваются следующие вопросы, касающиеся конфигурирования сервера MySQL: • • • •
Поддерживаемые сервером опции запуска. Установка режима SQL для сервера. Системные переменные сервера. Переменные состояния сервера.
4.2.1. Опции командной строки mysqld При запуске сервера mysqld можно задавать программные опции, используя любой из методов, описанных в разделе 3.3. Обычно опции указываются в файле опций или в командной строке. Однако в большинстве случаев желательно удостовериться, что сервер использует одни и те же опции при каждом запуске. Лучший способ добиться этого - перечислить опции в файле опций (см. раздел 3.3.2). mysqld считывает опции из групп [mysqld] и [server], a mysqld_safe - из групп [mysqld], [server], [mysqld_safe] и [safejnysqld]. Сценарий mysql.server считывает опции из групп [mysqld] и [mysql.server. Встроенный сервер MySQL обычно считывает опции из групп [server], [embedded] и [xxxxx_SERVER], где ххххх - это имя приложения, в которое встроен сервер. mysqld принимает множество опций командной строки. Чтобы просмотреть их список, введите mysqld —help. В версиях, предшествующих MySQL 4.1.1, опция --help выводит полную справочную информацию. Что касается версии MySQL 4.1.1, то отображается короткое сообщение; для просмотра всего списка используйте: mysqld —verbose —help Ниже описаны некоторые из основных опций сервера. Дополнительные опции рассматриваются в других разделах книги. • Опции, влияющие на безопасность - см. раздел 4.3.3. • Опции, связанные с SSL - см. раздел 4.5.7.5. • Опции управления бинарным журналом - см. раздел 4.8.4. • Опции, относящиеся к репликации - см. раздел 5.8. • Опции, являющиеся специальными для My ISAM, BDB или InnoDB - см. разделы 8.1.1, 8.4.3 и 9.5. Установить значение для системной переменной сервера также можно с использованием имени переменной в качестве опции, как описывается далее в разделе. • —help, -?. Выводит короткое справочное сообщение и завершает работу. В версиях, предшествующих MySQL 4.1.1, опция —help отображает подробное справочное сообщение, начиная с версии 4.1.1. - только его сокращенный вариант. Чтобы просмотреть полный вариант, используйте опции —verbose и —help. •
—ansi. Использование стандартного синтаксиса SQL вместо синтаксиса MySQL. См. раздел 1.8.3. Для более точного контроля над режимом SQL сервера вместо --ansi используйте опцию —sql-mode.
224
Глава 4. Администрирование баз данных •
—basedi г=луть, -Ь путь. Путь к каталогу установки MySQL. Все пути обычно определяются относительно данного пути.
•
—big-tables. Разрешает работать с большими объемами результатов, сохраняя все временные данные в файлы. Данная опция позволяет предотвратить большинство ошибок типа "table full" ("таблица переполнена"), но при этом замедляет обработку запросов, для которых таблиц в памяти (in-memory) было бы вполне достаточно. В версии MySQL 3.23.2 и выше сервер обрабатывает большие объемы результатов автоматически, используя память для маленьких временных таблиц и, при необходимости, переключаясь на таблицы на диске.
•
—bind-address=IP. IP-адрес для связывания.
•
--console. Регистрировать ошибки в s t d e r r / s t d o u t , даже если задана опция —log-error. В Windows при использовании данной опции mysqld не будет закрывать экран консоли.
•
—character-sets-dir=nyTb. Каталог, в котором находятся наборы символов. См. раздел 4.7.1.
•
~chroot=nyTb. Размещает сервер mysqld в закрытом окружении во время запуска, используя системный вызов chroot (). Данная опция рекомендуется в качестве меры безопасности, начиная с версии MySQL 4.O. (Версия MySQL 3.23 не может обеспечить стопроцентную изоляцию chroot ().) Обратите внимание, что применение данной опции некоторым образом ограничивает функции LOAD DATA INFILE И SELECT...INTO OUTFILE.
•
— c o r e - f i l e . Записывает файл ядра в случае отказа mysqld. В некоторых системах для raysqld_safe также понадобится задать опцию — c o r e - f i l e - s i z e . См. раздел 4.1.3. Обратите внимание, что в определенных системах, таких как Solaris, файл ядра получить не удастся, если используется опция —user-option.
•
—datadir=nyrb, -h путь. Путь к каталогу данных.
•
—debug [=опции__отладки], -# [опции_отладш]. Если MySQL сконфигурирован с использованием --with-debug, с помощью данной опции можно получить файл трассировки выполняемых mysqld операций. Строка опции_отладки чаще всего выглядит приблизительно так: ' d: t : о, имя_файла'.
•
—default-character-set=Ha6op_CHMBCxtfOB. Использовать набор_символов как набор символов по умолчанию. См. раздел 4.7.1.
•
—default-collation=coпocтaвлeниe. Использовать сопоставление как сопоставление по умолчанию. Эта опция доступна, начиная с версии MySQL 4.1.1. См. раздел 4.7.1.
•
—default-storage-engine=Tnn. Данная опция является синонимом —defaulttable-type. Доступна, начиная с версии MySQL 4.I.2.
•
--def ault-table-type=THn. Установить для таблиц тип по умолчанию. См. главу 8.
•
— delay-key-write [= OFF | ON | ALL]. Указывает, как будет использоваться опция DELAYED KEYS. При записи ключей с задержкой буферы ключей не очищаются между записями для таблиц My ISAM. Значение OFF отключает запись ключей с задержкой. Значение ON активизирует запись ключей с задержкой для тех таблиц, которые были созданы с использованием опции DELAYED KEYS. Значение ALL от-
4.2. Конфигурирование сервера MySQL
225
срочивает запись ключей для всех таблиц My ISAM. Опция доступна, начиная с MySQL 4.0.3. См. раздел 6.5.2, а также раздел 8.1.1. \у На заметку! V" %, Если установить для данной переменной значение ALL, использовать таблицы My ISAM из дру% гой программы (например, с другого сервера MySQL или через myisamchik), когда таблица наf ходится в работе, не удастся, поскольку это приведет к повреждению индекса.
•
—delay-key-write-for-all-tables. Старая форма —delay-key-write=ALL, используемая в версиях, предшествующих MySQL 4.O.3. Начиная с версии MySQL 4.0.3, вместо нее следует применять —delay-key-write. • --des-key-file=HM#_$awia. Считывать из данного файла ключи по умолчанию, ИСПОЛЬЗуемые функциями DES_ENCRYPT () И DES_DESCRYPT (). •
—enable-named-pipe. Активизировать поддержку именованных каналов. Данная опция доступна только в Windows NT/200/XP и может использоваться только с серверами mysqld-nt и mysqld-max-nt, которые поддерживают соединения через именованные каналы.
•
—external-locking. Разрешить блокировку доступа к системе. Обратите внимание, что использование данной опции в системах, где lockd не работает полностью (например, в Linux), приводит к зависанию mysqld. Раньше эта опция называлась —enable-locking.
|! На заметку! \" ft \, 1 2
Если данная опция используется для активизации обновления таблиц My ISAM из множественных процессов MySQL, необходимо убедиться, что выполнены следующие условия: Запросы, которые используют таблицы, обновляемые другим процессом, не кэшируются. Для любых совместно используемых таблиц не применяются опции —delay-key-write=ALL или DELAY_KEY_WRITE=1.
I'
Самый простой способ достичь этого - всегда использовать — e x t e r n a l - l o c k i n g вместе с
£
—delay-key-write=OFF —query-cache-size=O.
f (По умолчанию это не выполняется, поскольку в большинстве установок полезно использовать J;: различные комбинации указанных выше опций.)
•
—exit-info[=флаги], -Т [флаги]. Битовая маска различных флагов, используемая для отладки сервера mysqld. He применяйте эту опцию, если не уверены в том, что четко понимаете, как она работает!
•
—flush. После каждого SQL-оператора сбрасывать на диск все изменения. Обычно MySQL делает запись всех изменений на диск только после каждого SQLоператора и позволяет выполнять синхронизацию данных операционной системе. См. раздел А.4.2.
•
—init-file=файл. Считывать SQL-операторы из указанного файла при запуске. Каждый оператор должен занимать одну строку и не содержать комментарии.
•
—1апдиаде=имя_языка, -L имя_языка. Выводить сообщения об ошибках клиента на указанном языке. Опция имя_языка может быть представлена в виде названия языка или как полный путь к каталогу, в котором находятся языковые файлы. См. раздел 4.7.2.
226
Глава 4. Администрирование баз данных
•
—log[=файл], -1 [файл]. Регистрировать соединения и запросы в указанном файле. См. раздел 4.8.2. Если имя файла не указано, MySQL будет использовать имя_хоста.1од.
•
—log-bin= [ файл]. Файл бинарного журнала. Заносить все запросы, приводящие к изменению данных, в этот файл. Используется для резервного копирования и репликации. См. раздел 4.8.4. Если имя файла не указано, MySQL в качестве имени будет использовать имя_хоста-Ып.
•
—log-bin-index [=файл]. Индексный файл для бинарных журналов. См. раздел 4.8.4. Если имя файла не указано, MySQL в качестве имени будет использовать имя_хоста-Ып. index.
•
—log-error [=файл]. Записывать сообщения об ошибках и запуске в этот файл. См. раздел 4.8.1. Если имя файла не указано, MySQL в качестве имени будет использовать имя_хоста. err.
•
—log-isam[=файл]. Регистрировать все изменения ISAM/MylSAM в этом файле (используется только во время отладки ISAM/My ISAM).
•
—log-long-format. Заносить некоторую дополнительную информацию в системные журналы (журнал обновлений, бинарный журнал обновлений, журнал медленных запросов, любой журнал, который был активизирован). Например, для запросов регистрируются имя пользователя и временная метка. Если применяются опции —log-slow-queries и —log-long-format, тогда запросы, не использующие индексов, также будут регистрироваться в журнале медленных запросов. Обратите внимание, что опция --log-long-format устарела; в версии MySQL 4.1 введена опция —log-short-format (в версии 4.1 и выше этот формат журнала устанавливается по умолчанию). Также следует знать, что, начиная с версии MySQL 4.1, доступна опция —log-queries-not-using-indexes, которая заносит запросы, не использующие индексы, в журнал медленных запросов.
•
—log-queries-not-using-indexes. Если вместе с данной опцией применяется опция —log-slow-queries, тогда запросы, не использующие индексов, также будут регистрироваться в журнале медленных запросов. Данная опция доступна, начиная с версии MySQL 4.1. См. раздел 4.8.5.
•
—log-short-format. Записывать минимальное количество данных в системные журналы (журнал обновлений, бинарный журнал обновлений, журнал медленных запросов, любой журнал, который был активизирован). Например, в таком случае имя пользователя и временная метка для запросов не регистрируются. Данная опция была введена в MySQL 4.1.
•
—log-slow-queries [=файл]. Регистрировать в журнале все запросы, выполнение которых, в секундах, заняло больше, чем указано в long_query_time. См. раздел 4.8.5. Обратите внимание, что количество регистрируемых по умолчанию данных в MySQL 4.1 изменилось. Для получения более подробной информации обратитесь к описанию опций —log-long-format и —log-short-format.
•
--log-update[=файл]. Регистрировать обновления в файл.Я, где # - это уникальный номер, если он не был указан. См. раздел 4.8.3. Журнал регистрации обновлений устарел, и в MySQL 5.0.0 отсутствует, вместо него следует использовать бинарный журнал регистрации (—log-bin). См. раздел 4.8.4. Начиная с версии
4.2. Конфигурирование сервера MySQL
227
5.0.0, использование —log-update будет просто активизировать журнал бинарных регистрации. •
—log-warnings, -W. Фиксировать предупреждения, такие как Aborted connect i o n . . . ("Соединение прервано") в журнал регистрации ошибок. Активизация данной опции рекомендуется, например, при репликации (вы получите дополнительную информацию о том, что происходит, например, сообщения о сбоях в сети и повторные соединения). Данная опция в MySQL 4.1.2 активна по умолчанию; чтобы отключить ее, используйте --skip-log-warnings. См. раздел А.2.10. До появления версии MySQL 4.0 данная опция называлась —warnings.
•
— l o w - p r i o r i t y - u p d a t e s . Операции по внесению изменений в таблицы (INSERT/DELETE/UPDATE) будут иметь более низкий приоритет, недели операции SELECT. Это также можно сделать через {INSERT | REPLACE | DELETE | UPDATE} LOW_PRIORITY . . . , чтобы понизить приоритет только одного запроса, или через SET LOW_PRIORITY_UPDATES=1, чтобы изменить приоритет в одном потоке. См. раздел 6.3.2.
•
—memlock. Блокировать процесс mysqld в памяти. Данная опция работает в системах, подобных Solaris, которые поддерживают системный вызов mlockall (). Это может оказаться полезным в случае возникновения проблемы, когда операционная система сбрасывает mysqld на диск во время подкачки. Обратите внимание, что при использовании данной опции сервер придется запускать от имени привилегированного (root) пользователя, что обычно нежелательно в смысле безопасности.
•
—myisam-recover [-опция[, опция...]]]. Установить режим восстановления My ISAM. Значением опции может быть любая комбинация значений DEFAULT, BACKUP, FORCE или QUICK. Если задается сразу несколько значений, их следует разделять запятыми. Чтобы отключить данную опцию, используйте значение "". Если же опция —myisam-recover используется, mysqld при открытии таблицы проверит, отмечена ли она как дававшая сбои, или была ли таблица закрыта некорректно (последняя операция возможна, только если применяется --skip-external-locking). При таких условиях mysqld запустит проверку таблицы. Если таблица повреждена, mysqld попытается ее восстановить. Следующие опции влияют на процесс восстановления: Опция
Описание
DEFAULT
To же самое, что и ситуация, когда не задаются никакие значения для —myisam-recover.
BACKUP
Если во время восстановления файл данных имя_та блицы. MYD изменяется, его резервная копия сохраняется как имя__таблицы-дата-время .ВАК.
FORCE
Запускается процесс восстановления, даже если при этом будет утеряно более одной строки из файла . MYD.
QUICK
Строки в таблице при отсутствии удаленных блоков проверяться не будут.
П е р е д автоматическим восстановлением т а б л и ц ы M y S Q L добавит о б э т о м запись в журнал регистрации о ш и б о к . Ч т о б ы исключить вмешательство пользователя в процессы восстановления таблиц после б о л ь ш и н с т в а п р о б л е м н ы х ситуаций, е л е -
228
Глава 4. Администрирование баз данных дует использовать опции BACKUP и FORCE. Это гарантирует запуск восстановления таблицы, даже если некоторые из строк удалены, и при этом будет сохраняться резервная копия старого файла данных, так чтобы всегда позже можно было проанализировать, что конкретно произошло. Данная опция доступна, начиная с версии MySQL 3.23.25.
•
—new. Начиная с версии 4.0.12, опция --new может использоваться, чтобы в определенных аспектах заставить сервер функционировать как сервер версии 4.1, тем самым значительно облегчая процесс обновления версий с 4.0 до 4.1: • TIMESTAMP возвращается в виде строки в формате ' YYYY-MM-DD HH :MM: SS'. Эта опция помогает посмотреть на поведение ваших приложений в MySQL 4.1 без фактической модернизации до версии 4.1.
•
—pid-file=nyTb. Путь к файлу идентификатора процесса, который использует mysqld_safe.
•
—рогt=HOMep__nopTa, -P номер_порта. Номер порта, используемого при прослушивании ТСРЛР-соединений.
•
--old-protocol, -о. Использовать протокол 3.20 для совместимости с некоторыми очень старыми клиентами. См. раздел 2.5.6.
•
—one-thread. Использовать только один поток (для отладки в Linux). Данная опция доступна при условии, что во время сборки сервера отладка была включена.
•
--open-files-limit=KOffH4ecTBO. Применяется для изменения количества файловых дескрипторов, доступных для mysqld. Если данная опция не установлена или установлена со значением 0, mysqld будет использовать это значение, чтобы зарезервировать файловые дескрипторы для применения с функцией setrlimit (). Если значение равно 0, тогда mysqld будет резервировать max_connections*5 или max_connections + table_cache*2 файлов (большее значение из них). Попытайтесь увеличить это число, если mysqld выдает ошибку "Too many open files" ("Слишком много открытых файлов").
•
—safe-mode. Пропускает некоторые шаги оптимизации.
•
—safe-show-database. С данной опцией оператор SHOW DATABASES отображает имена только тех баз данных, для которых у пользователя имеются определенные привилегии. В MySQL 4.0.2 эта опция устарела и не приводит к какому-либо эффекту (по умолчанию она установлена), поскольку теперь существует привилегия SHOW DATABASES, которую можно использовать, чтобы контролировать доступ к базам данных для каждой учетной записи. См. раздел 4.4.3.
•
—safe-user-create. Когда эта опция включена, пользователь не может создавать новых пользователей с помощью оператора GRANT, если он не имеет привилегии INSERT для таблицы mysql. user или для любого ее столбца.
•
—secure-auth. Запрещает аутентификацию для учетных записей, которые имеют старые (до версии 4.1) пароли. Данная опция доступна, начиная с версии MySQL 4.1.1.
•
—skip-bdb. Отключает механизм хранения BDB. В результате экономится память и может увеличиться скорость выполнения некоторых операций. Не используйте данную опцию, если есть необходимость в таблицах BDB.
4.2. Конфигурирование сервера MySQL
229
•
—skip-concurrent-insert. Отключает возможность одновременного выбора и вставки данных в таблицах My ISAM. (Используйте данную опцию, только если вам кажется, что вы нашли ошибку в работе описанной функции.)
•
—skip-delay-key-write. Для всех таблиц игнорировать опцию DELAY_KEY_WRITE. Начиная с MySQL 4.0.3, вместо этой опции следует использовать —delay-key-write= OFF. См. раздел 6.5.2.
•
—skip-external-locking. He использовать системную блокировку. Для применения isamchik или myisamchk потребуется завершить работу сервера. См. раздел 1.2.3. В MySQL 3.23 можно воспользоваться CHECK TABLE и REPAIR TABLE для проверки либо восстановления таблицы My ISAM. Раньше эта опция называлась —skip-locking.
•
—skip-grant-tables. При установке данной опции сервер совсем не будет использовать систему привилегий. Это предоставляет каждому полный доступ ко всем базам данных! (Можно сделать так, чтобы сервер снова начал использовать таблицы привилегий, с помощью команды mysldadmin flush-privileges или mysqladmin reload, или же оператора FLUSH PRIVILEGES.)
•
—skip-host-cache. He использовать внутренний кэш имен хостов для более быстрого преобразования имен в IP-адреса. Вместо этого запрашивать DNS-сервер каждый раз, когда пользователь устанавливает соединение. См. раздел 6.5.5.
•
—skip-innodb. Отключает механизм хранения innoDB. Это экономит память и может повысить скорость выполнения некоторых операций. Не используйте данную опцию, если есть необходимость в наличии таблиц InnoDB.
•
—skip-is am. Отключает ISAM. В MySQL 4.1 ISAM по умолчанию блокируется, поэтому данная опция применяется только в тех случаях, когда сервер конфигурировался с поддержкой ISAM. Эта опция была появилась в MySQL 4.1.1.
•
—skip-name-resolve. Во время проверки соединений клиентов не будет выполняться преобразование имен хостов. Используются только IP-адреса. В случае применения данной опции все значения в столбцах Host таблиц привилегий должны представлять собой IP-адреса или localhost. См. раздел 6.5.5.
•
--skip-networking. He прослушивать TCP/IP-соединения вообще. Взаимосвязь с mysqld должна осуществляться через именованные каналы (Windows) или файлы сокетов Unix (Unix). Эта опция особенно рекомендуется для систем, в которых доступ разрешен только локальным клиентам. См. раздел 6.5.5.
•
—skip-new. He использовать новые, возможно некорректные, процедуры.
•
--skip-symlink. Это старая форма —skip-symbolic-links, используемая в версиях, предшествующих MySQL 4.0.13.
•
--symbolic-links, --skip-symbolic-links. Включает или отключает поддержку символических ссылок. Данная опция по-разному функционирует в Windows и Unix: • В Windows она позволяет установить символическую связь с каталогом базы данных за счет создания файла directory.sym, который содержит путь к действительному каталогу. См. раздел 6.6.1.3.
230
Глава 4. Администрирование баз данных •
В Unix активизация символических ссылок означает возможность связать индексный файл My ISAM или файл данных с другим каталогом посредством опций INDEX DIRECTORY ИЛИ DATA DIRECTORY оператора CREATE TABLE. В случае удаления или переименования таблицы файлы, на которые указывают символические ссылки, также удаляются или переименовываются. Эта опция была добавлена в MySQL 4.0.13.
•
—skip-safemalloc. Если MySQL конфигурировался с —with-debug=full, все MySQL-программы проверяют показатели выхода за границы памяти при каждой операции загрузки или освобождения памяти. Процесс проверки происходит чрезвычайно медленно, поэтому, в отсутствие необходимости, его можно избежать, применив опцию —skip-safemalloc.
•
—skip-show-database. С этой опцией оператор SHOW DATABASES доступен только пользователям, имеющим привилегию SHOW DATABASES, и будет отображать имена всех баз данных. Без этой опции SHOW DATABASES доступен всем пользователям, но отображает имя каждой базы данных, только если пользователь имеет привилегию SHOW DATABASES или какую-нибудь другую привилегию для базы данных.
•
--skip-stack-trace. Данные трассировки стека записываться не будут. Эта опция полезна при запуске mysqld в отладчике. В некоторых системах она также необходима для получения файла ядра.
•
—skip-thread-priority. Отключает использование приоритетов потока с целью сократить время отклика.
•
—socket=nyTb. В Unix данная опция определяет файл сокета Unix, который будет использоваться для локальных соединений. По умолчанию установлено значение /tmp/mysql.sock. В Windows эта опция задает имя канала для локальных соединений, использующих именованный канал. По умолчанию имеет значение MySQL.
•
— з ц 1 - т о ( 1 е = з н а ч е н и е [, з н а ч е н и е [, значение...]]. У с т а н а в л и в а е т S Q L - р е ж и мд л я MySQL. См. раздел 4.2.2. Эта опция появилась в версии MySQL 3.23.41.
•
—temp-pool. С указанием этой опции большинство временных созданных сервером файлов будет использовать минимальный набор имен, а не уникальное имя для каждого нового файла. Опция позволяет справиться с проблемой ядра Linux, которая проявляется при создании большого количества новых файлов с разными именами. При старом поведении в Linux наблюдается утечка памяти, поскольку система размещается в кэше каталогов, а не в кэше диска.
•
—transaction-isolation=ypoBeHb. Устанавливает уровень изоляции транзакции ПО умолчанию: READ-UNCOMMITTED, READ-COMMITTED, REPEATABLE-READ И SERIALIZABLE.
•
--tmpdir=nyib, -t путь. Путь к каталогу, который будет использоваться для создания временных файлов. Эта опция может пригодиться, если каталог по умолчанию /tmp находится в разделе диска, который слишком мал, чтобы вместить временные таблицы. Начиная с версии MySQL 4.1, эта опция принимает несколько путей, используемых по циклическому принципу. Пути должны разделяться знаком двоеточия ( V ) в Unix и точкой с запятой (';') в ОС Windows, NetWare и OS/2. Если сервер MySQL функционирует как подчиненный сервер репликации, не следует задавать в —tmpdir значение, указывающее на каталог в файловой
4.2. Конфигурирование сервера MySQL
231
системе, зависящей от памяти, или на каталог, который очищается при перезапуске хоста сервера. Серверу необходимо, чтобы некоторые из его временных файлов оставались и после перезапуска машины так, чтобы он смог реплицировать временные таблицы или операции LOAD DATA INFILE. Если после перезапуска сервера файлы из каталога временных файлов будут удалены, репликацию провести не удастся. • —user= {имя_пользователя | идентификатор_пользователя}, -и {имя_пользователя I идентификатор_пользователя). Запускать сервер mysqld от имени пользователя имя_пользователя или от имени пользователя с числовым идентификатором идентификатор_пользователя. ("Пользователь" в данном контексте обозначает учетную запись для входа в систему, а не пользователя MySQL, указанного в таблицах привилегий.) Данная опция обязательна при запуске mysqld от имени привилегированного (root) пользователя. Сервер поменяет свой идентификатор пользователя во время запуска, что заставит его работать от имени конкретного пользователя, а не от имени пользователя root. См. раздел 4.3.1. Начиная с версий MySQL 3.23.56 и 4.0.12, во избежание возможных ошибок в системе безопасности, когда пользователь добавляет опцию —user=root в какойнибудь файл my.cnf (в результате чего сервер запускается как root), mysqld использует только первую заданную опцию —user и выдает предупреждение, если таких опций сразу несколько. Опции в /etc/my, cnf и в ка та л ог_ да иных/ my.cnf обрабатываются до опций командной строки, поэтому рекомендуется размещать опцию —user в /etc/my.cnf и указывать значение, отличное от root. Опция в файле /etc/my, cnf будет найдена раньше любых других опций --user, что гарантирует запуск сервера как обычного пользователя, а не как привилегированного (root), а также выдачу предупреждения в том случае, если будет обнаружена любая другая опция —user. •
—version, -V. Отобразить данные о версии программы и завершить работу.
Можно назначить значение системной переменной сервера путем использования опции в форме —имя_переменнои= значение. Например, —key_buffer_size=32M присваивает переменной key_buf f er_size значение 32 Мбайт. Обратите внимание, что при установке значения для переменной СУБД MySQL может автоматически корректировать его, чтобы оно не выходило за конкретные пределы, или округлять его до наиболее близкого допустимого значения, если разрешены только определенные значения. Также можно устанавливать переменные с использованием синтаксиса —set-variable= имя_переменной=значение или -0 имя_переменной=значение. Однако в версиях MySQL 4.0 и выше такой синтаксис считается устаревшим. Подробное описание всех переменных дается в разделе 4.2.3. Раздел 6.5.2, посвященный настройке параметров сервера, включает информацию по их оптимизации. Для функционирующего сервера значения большинства системных переменных можно изменять с помощью оператора SET. Чтобы ограничить максимальное значение, которое можно присвоить системной переменной с помощью оператора SET, при запуске сервера используйте опцию в виде —maximum-имя_переменной, где и укажите необходимый максимум. Например, чтобы во время выполнения значение query_cache_size нельзя было установить выше 32 Мбайт,
232
Глава 4. Администрирование баз данных
следует задать опцию —maximum-query_cache_size=32. Данная функция доступна, начиная с версии MySQL 4.O.2.
42.2. Режим SQL сервера Сервер MySQL может работать в разных режимах SQL и (начиная с MySQL 4.1) применять эти режимы дифференцированно для различных клиентов. Это позволяет приложениям настраивать работу сервера в соответствии с их требованиями. Режимы определяют, какой SQL-синтаксис MySQL должен поддерживать, и какой тип проверок корректности данных он будет выполнять. Это облегчает использование MySQL в разных окружениях и вместе с другими серверами баз данных. Установить режим SQL по умолчанию можно, запустив mysqld с опцией —sql-mode= "режимы". Начиная с версии MySQL 4.1, режим также можно изменять и после запуска, 1 задав переменную sqljnode через оператор SET [SESSION|GLOBAL] sql_mode='режимы . Установка переменной GLOBAL влияет на работу всех подключающихся с этого времени клиентов. Установка переменной SESSION влияет только на текущего клиента, modes это список различных режимов, разделяемых запятыми (','). Извлечь текущий режим можно с помощью оператора SELECT @@sqljnode. Значение по умолчанию - пустое (то есть режимы не установлены). Также оно должно быть пустым (—sql-mode=""), если вы хотите его сбросить. В нижеследующем списке представлены поддерживаемые режимы: •
ANSI_QUOTES. Трактовать ' " ' как символ кавычек идентификатора (т.е. как кавычки ' s ' ) , а не как строковый символ кавычек. По-прежнему можно использовать ' ч ' для идентификаторов в режиме ANSI. Активизировав ANSI_QUOTES, нельзя применять двойные кавычки для строковых литералов, поскольку в этом случае они будут интерпретироваться как идентификаторы. (Новая опция в MySQL 4.O.O.)
•
IGNORE_SPACE. Игнорировать пробелы между именем функции и символом '('• Это приводит к тому, что названия всех функций будут интерпретироваться как зарезервированные слова. В результате чтобы получить доступ к любой базе данных, столбцу или таблице, имя которой является зарезервированным словом, это имя потребуется взять в кавычки. Например, при использовании функции USERO, имя таблицы user в базе данных mysql и имя столбца User в этой таблице становятся зарезервированными словами* поэтому они должны быть заключены в кавычки: SELECT "User" FROM mysql."user"; (Новая опция в MySQL 4.0.0.)
•
NO_AUTO_VALUE_ON_ZERO. Опция NO_AUTO_VALUE_ON_ZERO влияет на обработку столбцов AUTO_INCREMENT. Обычно следующий порядковый номер для столбца создается путем вставки в него значения NULL или 0. NO_AUTO_VALUE_ON_ZERO исключает проведение такой операции при использовании значения 0, то есть только NULL будет создавать следующий порядковый номер. Такой режим может пригодиться, если 0 сохранен в столбце AUTO_INCREMENT таблицы. (Однако рекомендуемым он не является.) Например, после очистки таблицы с помощью mysqldump и перезагрузки MySQL обычно генерирует новые порядковые числа, когда сталкивается со значениями 0, что в результате приводит к появлению таблицы, содержимое которой отличается от исходного. Включение режима NOAUTOVALUEONZERO перед перезагрузкой файла дампа решит эту проблему. Начиная с MySQL 4.1.1,
4.2. Конфигурирование сервера MySQL
233
mysqldump автоматически вводит операторы в файлах дампа для активизации NO_AUTO_VALUE_ON_ZERO. (Новая опция в версии MySQL 4.O.O.) •
NO_DIR_IN_CREATE. Во время создания таблицы игнорировать все директивы INDEX DIRECTORY и DATA DIRECTORY. Эта опция полезна на подчиненных серверах репликации. (Новая опция в версии MySQL 4.0.15.)
•
NO_FIELD_OPTIONS. He отображать опции MySQL для столбцов в выходных данных SHOW CREATE TABLE. Используется функцией mysqlddump в режиме переносимости. (Новая опция в версии MySQL 4.1.1.)
•
NO_KEY_OPTIONS. He отображать опции MySQL для индексов в выходных данных SHOW CREATE TABLE. Используется функцией mysqlddump в режиме переносимости. (Новая опция в версии MySQL 4.1.1.)
•
NO_TABLE_OPTIONS. He отображать MySQL-опции для таблиц в выходных данных SHOW CREATE TABLE. Используется функцией mysqlddump в режиме переносимости. (Новая опция в версии MySQL 4.1.1.)
•
NO_UNSIGNED_SUBTRACTION. В операциях вычитания не отмечать результат как UNSIGNED, если один из операндов не имеет знака. Обратите внимание, что это приводит к тому, что UNSIGNED BIGINT не является на 100% используемым во всех контекстах. (Новая опция в версии MySQL 4.O.2.)
•
ONLYFULLGROUPBY. Запросы, которые в части GROUP BY относятся к невыбранному столбцу, учитываться не будут. (Новая опция в версии MySQL 4.O.O.)
•
PIPES_AS_CONCAT. Трактовать | | как операцию конкатенации строк (как и CONTACT ()), а не как синоним операции OR. (Новая опция в версии MySQL 4.O.O.)
•
REAL_AS_FLOAT. Рассматривать REAL как синоним FLOAT, а не как синоним DOUBLE. (Новая опция в версии MySQL 4.O.O.)
Следующие специальные режимы предлагаются как сокращенные варианты для комбинаций значений режимов из предыдущего списка. Они доступны, начиная с версии MySQL 4.1.1. •
ANSI. Эквивалентен REAL_AS_FLOAT, PIPES_AS__CONCAT, ANSI_QUOTES, IGNORE_SPACE, ONLY_FULL_GROUP_BY. См. раздел 1.8.3.
•
DB2. Эквивалентен PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, NO_KEY_OPTIONS, NO_TABLE_OPTIONS, NO_FIELD_OPTIONS.
•
MAXDB. Эквивалентен PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, NO_KEY_OPTIONS, NO_TABLE_OPTIONS, NO_FIELD_OPTIONS.
•
MSSQL. Эквивалентен PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, NO_KEY_OPTIONS, NO_TABLE_OPTIONS, NO_FIELD_OPTIONS.
•
MYSQL323. Э к в и в а л е н т е н NO_FIELD_OPTIONS.
•
MYSQL40. Эквивалентен NO_FIELD_OPTIONS.
•
ORACLE. Эквивалентен PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, NO_KEY_OPTIONS, NO_TABLE_OPTIONS, NO_FIELD_OPTIONS.
•
POSTGRESQL. Эквивалентен PIPES_AS_CONCAT, ANSI_QUOTES, NO KEY OPTIONS, NO TABLE OPTIONS, NO_FIELD OPTIONS.
IGNORE_SPACE,
234
Глава 4. Администрирование баз данных
4.2.3. Системные переменные сервера Сервер поддерживает большое количество системных переменных, характеризующих его конфигурацию. Все они имеют значения по умолчанию. Установить переменные можно во время запуска сервера, задав опции в командной строке или в файлах опций. Большинство из них можно установить и во время выполнения с помощью оператора SET. Начиная с версии MySQL 4.0.3, сервер mysqld поддерживает два вида переменных. Глобальные переменные оказывают влияние на общую работу сервера. Сеансовые переменные влияют на операции сервера, связанные с отдельными клиентскими соединениями. Во время запуска сервер устанавливает все глобальные переменные в их первоначальные значения по умолчанию. Эти значения можно изменить с помощью опций, указываемых в файлах опций или в командной строке. После запуска сервера глобальные переменные, которые являются динамическими, можно изменить, подключившись к серверу и выполнив оператор SET GLOBAL имя_переменной. Чтобы изменить любую глобальную переменную, необходимо иметь привилегию SUPER. Сервер также поддерживает набор сеансовых переменных для каждого подключившегося клиента. Сеансовые переменные клиента инициализируются во время соединения, используя текущие значения соответствующих глобальных переменных. Сеансовые переменные, которые являются динамическими, клиент может изменить с помощью оператора SET SESSION имя_переменной. Для установки сеансовой переменной специальной привилегии не требуется, однако клиент может изменять только свои собственные сеансовые переменные, а не переменные какого-нибудь другого клиента. Изменение глобальной переменной видят все клиенты, получающие к ней доступ. Однако оно отражается на соответствующей сеансовой переменной, инициализированной из глобальной переменной, только тех клиентов, которые подключились после изменения. На сеансовые переменные уже подключенных клиентов (и даже тех, которые используют оператор SET GLOBAL) это никак не повлияет. При установке переменных с помощью опции запуска их значения могут включать суффикс К, м или G для обозначения, соответственно, числа килобайт, мегабайт или гигабайт. Например, следующая команда запускает сервер, размер буфера ключей которого составляет 16 Мбайт: mysqld —key_buffer_size=16M В версиях, предшествующих MySQL 4.0, вместо этого используйте следующий синтаксис: mysqld
—set-variable=key_buffer_size=16M
Регистр букв в суффиксах роли не играет: 16М и 16т полностью эквивалентны. Для установки системных переменных во время выполнения используйте оператор SET. В таком контексте буквы в суффиксах использовать нельзя, но значение может принимать форму выражения: mysql> SET sort_buffer_size = 10 * 1024 * 1024; Чтобы явно указать, какая переменная устанавливается - глобальная или сеансовая используйте опции GLOBAL и SESSION: mysql> SET GLOBAL sortjbuffer_size = 10 * 1024 * 1024; mysql> SET SESSION sort_buffer_size = 10 * 1024 * 1024;
4.2. Конфигурирование сервера MySQL
235
Если ни та, ни другая опция не указываются, оператор устанавливает сеансовую переменную. Переменные, которые можно устанавливать во время выполнения, перечислены в разделе 4.2.3.1.2. Чтобы ограничить максимальное значение, которое разрешается присвоить системной переменной с помощью оператора SET, при запуске сервера используйте опцию —maximum-имя_переменной, где и укажите необходимый максимум. Например, чтобы во время выполнения значение query_cache_size нельзя было установить выше 32 Мбайт, задается опция —maximum-query_cache_size=32. Данная функция доступна начиная с версии MySQL 4.O.2. Просмотреть системные переменные и их значения можно с помощью оператора SHOW VARIABLES. Более подробная информация представлена в разделе 4.2.3.1. m y s q l > SHOW VARIABLES; Variable name back log basedir bdb cache size bdb home bdb_log_buffer_size bdb logdir bdb max lock bdb shared data bdb tmpdir bdb version I binlog cache size I bulk insert buffer size I character_set I character sets | concurrent insert I connect timeout I convert character_set I datadir I default week format I delay key write I delayed insert limit I delayed insert timeout I delayed queue size I flush | flush_time I ft boolean syntax | ft max word len | ft min word len | ft query expansion limit I ft stopword file I have bdb 1 have innodb
Value
|
50 /usr/local/mysql 8388572 /usr/local/mysql 32768
| | | | |
10000 OFF /tmp/ Sleepycat Software: ... 32768 8388608 latinl latinl big5 czech euc kr ON ~
| | | | | | |
5
1
/usr/local/mysql/data/
0 ON 100 300 I I 1 |
1000 OFF 0 + -> SET GLOBAL sort_buffer_size=3Ha4eHne; или: mysql> SET @@global.sort_buffer_size=3Ha4eHne; Чтобы установить значение переменной SESSION, используйте синтаксис: mysql> SET SESSION sort_buffer__si ге=зяачение; или: mysql> SET @@session.sort_buffer_size=3Ha4eHJ SET sort_buffer_size=3Ha4eHne; Если во время установки переменной значение GLOBAL, SESSION или LOCAL не указывается, по умолчанию будет установлено SESSION. Чтобы извлечь значение переменной GLOBAL, применяйте один из следующих операторов: mysql> SELECT @@global.sort_buffer_size; mysql> SHOW GLOBAL VARIABLES like 'sortjmffer_size'; Чтобы извлечь значение переменной SESSION, используйте один из следующих операторов: mysql> SELECT @@sort_buffer_size; mysql> SELECT @@session.sort_buffer_size; mysql> SHOW SESSION VARIABLES like 'sort_buffer_size'; Здесь также LOCAL представляет собой синоним SESSION. При извлечении переменной с помощью SELECT №имя_переменной (то есть не указывается ни global., ни session., ни local.), MySQL возвращает значение SESSION, если таковое существует, или в противном случае - значение GLOBAL. Что касается SHOW VARIABLES, если не указать GLOBAL, SESSION или LOCAL, MySQL возвращает значение SESSION.
4.2. Конфигурирование сервера MySQL
255
Причина такой необходимости в ключевом слове GLOBAL во время установки только глобальных переменных (GLOBAL), но не во время их извлечения, заключается в том, чтобы предотвратить проблемы в будущем. Если удаляется переменная SESSION с таким же именем, клиент, имеющий привилегию SUPER, может случайно изменить переменную GLOBAL, а не просто переменную SESSION для своего собственного соединения. Если добавляется переменная SESSION с таким же именем, клиент, который пытается изменить переменную GLOBAL, может обнаружить, что при этом изменилась только его собственная переменная SESSION. 4.2.3.1.1. Структурированные системные переменные Структурированные системные переменные поддерживаются, начиная с MySQL 4.1.1. Структурированная переменная отличается от обычной в двух аспектах: • Ее значение - это структура с компонентами, указывающими серверные параметры, которые считаются тесно связанными между собой. • Может существовать несколько экземпляров данного типа структурированной переменной. Все они имеют разные имена и ссылаются на разные ресурсы, поддерживаемые сервером. В настоящее время MySQL поддерживает один тип структурированных переменных. Он определяет параметры, которые отвечают за функционирование кэша ключей. Структурированная переменная кэша ключей имеет такие компоненты: •
key_buffer_size
•
key_cache_block_size
•
key_cache_division__limit
•
key_cache_age_threshold
Цель данного раздела состоит в том, чтобы описать синтаксис, необходимый для обращения к структурированным переменным. Переменные кэша ключей используются для примеров синтаксиса, но детальная информация, касающаяся непосредственно того, как функционируют кэши ключей, находится в разделе 6.4.6. Чтобы обратиться к компоненту экземпляра структурированной переменной, можно использовать составное имя в формате имя_экземпляра. имя_компонента. Ниже представлены примеры: hot_cache.key_buffer_size hot_cache.key_cache_block_size cold cache.key_cache_block_size Для каждой структурированной системной переменной экземпляр с именем default всегда предопределен. Если при обращении к компоненту структурированной переменной имя экземпляра не указывается, используется экземпляр default. Таким образом, и default.key_buffer_size, и key_buffer_size ссылаются на одну и ту же системную переменную. Правила присваивания имен экземплярам и компонентам структурированных переменных формулируются следующим образом: • Для данного типа структурированной переменной каждый экземпляр должен иметь имя, которое будет уникальным среди переменных такого типа. Однако имена экземпляров не обязательно должны быть уникальными среди типов структурированных переменных. Если бы не выполнялось это условие (то есть
256
Глава 4. Администрирование баз данных если бы два разных типа структурированных переменных могли бы совместно использовать имена-члены компонента), было бы непонятно, какую структурированную переменную использовать для ссылок на имена-члены, не уточненные через имя экземпляра.
• Если имя экземпляра структурированной переменной недопустимо в виде идентификатора без кавычек, обращайтесь к нему как к идентификатору в кавычках, используя кавычки типа ч \ Например, hot-cache - недопустимое имя, a hotcache N - допустимое. •
global, session и local не являются допустимыми именами экземпляров. Это помогает избежать конфликтов с обозначениями, такими как @ @ global. имя_переменной при обращении к неструктурированным системным переменным.
На данный момент первые два правила нарушить возможности нет, поскольку единственным типом структурированных переменных является тип для кэшей ключей. Эти правила приобретут большую значимость, если в будущем будет создан какой-нибудь новый тип структурированной переменной. За одним исключением разрешается обращаться к компонентам структурированных переменных, используя составные имена в любом контексте, где могут встречаться простые переменные. Например, можно назначить значение структурированной переменной с помощью опции командной строки: shell> mysqld —hot__cache.key_buffer_size=64K В файле опций укажите следующее: [mysqld] hot_cache.key_buffer_size=64K При запуске сервера с такой опцией будет создан кэш ключей hot_cache размером 64 Кбайт, помимо кэша ключей по умолчанию размером 8 Мбайт. Предположим, сервер запускается следующим образом: shell> mysqld --key_buffer_size=256K \ —extra_cache.key_buffer_size=128K \ —extra_cache.key_cachejDlock_size=2048 В таком случае сервер для размера кэша ключей по умолчанию устанавливает значение 256 Кбайт. (Также можно было бы написать --default.key_buffer_size=256K). Кроме этого, сервер создает второй кэш ключей extra_cache размером 128 Кбайт и устанавливает буферы, необходимые для кэширования индексных блоков таблиц, размером 2048 байт. Следующий пример запускает сервер с тремя разными кэшами ключей, размеры которых соотносятся как 3:1:1: shell> mysqld —key_buffer_size=6M \ —hot_cache.keyjbuffer_size=2M \ —cold_cache.key_buffer_size=2M Значения структурированных переменных также можно устанавливать и извлекать и во время выполнения. Например, чтобы для кэша ключей hotcache установить размер 10 Мбайт, воспользуйтесь одним из следующих операторов: mysql> SET GLOBAL hot_cache.keyjbuffer__size = 10*1024*1024; mysql> SET @@global.hot_cache.keyjbuffer_size = 10*1024*1024;
4.2. Конфигурирование сервера MySQL
257
Для извлечения значения размера кэша сделайте следующее: mysql> SELECT @@global.hot_cache.keyjbuffer_size;
Представленный ниже оператор не работает. Переменная интерпретируется не как составное имя, а как простая строка для операции сравнения с образцом LIKE. mysql> SHOW GLOBAL VARIABLES LIKE
'hotj:ache.keyjbuffer_size';
Это и есть то самое исключение, когда нельзя использовать имена структурированных переменных везде, где может встречаться имя простой переменной. 4.2.3.1.2. Динамические системные переменные Начиная с MySQL 4.0.3, многие системные переменные сервера являются динамическими и могут устанавливаться во время выполнения с помощью SET GLOBAL или SET SESSION. Также дается возможность выбирать их значения с помощью SELECT. См. раздел 4.2.3.1. В табл. 4.1 представлен полный список всех динамических системных переменных. В последней колонке указывается, какое значение - GLOBAL или SESSION (или оба) - применимо для каждой переменной. Таблица 4.1. Динамические системные переменные И м я переменной
Тип значения
Тип
autocommit big tables binlog_cache_size bulk insert buffer_size character set client character set connection character set results character_set_server collation connection collation server concurrent insert connect timeout convert_character_set default week format delay_key_write delayed insert limit delayed insert timeout delayed_queue_size error count flush flush_time foreign key checks
булевское булевское число число строка строка строка строка строка строка булевское число строка число OFF | ON | ALL число число число число булевское число булевское
SESSION SESSION GLOBAL GLOBAL | GLOBAL | GLOBAL | GLOBAL | GLOBAL | GLOBAL | GLOBAL | GLOBAL GLOBAL GLOBAL | GLOBAL | GLOBAL GLOBAL GLOBAL GLOBAL SESSION GLOBAL GLOBAL SESSION
SESSION SESSION SESSION SESSION SESSION SESSION SESSION
SESSION SESSION
258
Глава 4. Администрирование баз данных Продолжение табл. 4.1
Имя переменной
Тип значения
Тип
ft_boolean_syntax group concat max len identity insert id interactive_timeout key buffer size last_insert_id local__infile log_warnings long query time low priority updates max_allowed_packet max_binlog_cache_size max_binlog size max connect errors max connections max_delayed_threads max error count max_heap_table size max_insert_delayed_threads max join size max_relay_log_size max seeks for key max sort length max tmp tables max user connections max_write lock count myisam max extra sort file size myisam_max_sort file size myisam repair threads myisam sort buffer size net_buffer_length net read timeout net retry count net write timeout query alloc block size query cache limit
число
GLOBAL GLOBAL | SESSION SESSION SESSION GLOBAL | SESSION GLOBAL SESSION GLOBAL GLOBAL GLOBAL | SESSION GLOBAL | SESSION GLOBAL | SESSION GLOBAL GLOBAL GLOBAL GLOBAL GLOBAL GLOBAL | SESSION GLOBAL | SESSION GLOBAL GLOBAL | SESSION GLOBAL GLOBAL | SESSION GLOBAL | SESSION GLOBAL GLOBAL GLOBAL GLOBAL | SESSION GLOBAL | SESSION GLOBAL | SESSION GLOBAL | SESSION GLOBAL | SESSION GLOBAL | SESSION GLOBAL | SESSION GLOBAL | SESSION GLOBAL | SESSION GLOBAL
число число булевское число число число булевское булевское число булевское число число число число число число число число число число число число число число число число число число число число число число число число число число
4.2.
Конфигурирование сервера MySQL
259 Продолжение табл. 4.1
Имя переменной
Тип значения
Тип
query_cache_size query_cache_type query_cache_wlock_invalidate query_prealloc_size range_alloc_block_size read_buffer__size read_only read_rnd_buffer_size rpl_recovery_rank safe_show_database server_id slave_compressed_protocol slave_net_timeout slow_launch__time sort__buffer_size sql_auto_is_null sql_big_selects sql_big_tables sql_buffer_result sql_log_bin sql_log_off sql_log_update sql_low_priority__updates sql_max_join_size sql quote_show_create sql_safe_updates sql_select_limit sql_slave_skip_counter sql_warnings storage_engine table_cache table_type thread_cache_size time stamp tmp_table_size transaction_alloc_block_size transaction_prealloc_size
число перечисление булевское число число число число число число булевское число булевское число число число булевское булевское булевское булевское булевское булевское булевское булевское число булевское булевское число число булевское перечисление число перечисление число булевское перечисление число число
GLOBAL GLOBAL | SESSION GLOBAL | SESSION GLOBAL | SESSION GLOBAL | SESSION GLOBAL | SESSION GLOBAL GLOBAL | SESSION GLOBAL GLOBAL GLOBAL GLOBAL GLOBAL GLOBAL GLOBAL | SESSION SESSION SESSION SESSION SESSION SESSION SESSION SESSION GLOBAL | SESSION GLOBAL I SESSION SESSION SESSION SESSION GLOBAL SESSION GLOBAL | SESSION GLOBAL GLOBAL | SESSION GLOBAL SESSION GLOBAL I SESSION GLOBAL | SESSION GLOBAL | SESSION
260
Глава 4. Администрирование баз данных Окончание табл. 4.1
Имя переменной
Тип значения
Тип
tx_isolation unique_checks wait_timeout warning_count
перечисление булевское число число
GLOBAL | SESSION SESSION GLOBAL | SESSION SESSION
Переменные с типом "строка", принимают строковое значение. Переменные с типом с типом "число" принимают числовое значение. Значения переменных с типом "булевское" можно установить как 0, 1, ON или OFF. Переменным с типом "перечисление" обычно следует присваивать одно из доступных для переменной значений; также им можно присваивать число, соответствующее желаемому значению перечисления. Для системных переменных со перечислимым типом первое такое значение соответствует 0, в отличие от столбцов ENUM, для которых первое значение перечисления соответствует 1.
42.4 Переменные состояния сервера Сервер поддерживает большое количество переменных состояния, предоставляющих данные о его функционировании. Просмотреть эти переменные и их значения можно с помощью оператора SHOW STATUS: mysql> SHOW STATUS; I Variable name I I I I I I I I I I I I I I I I I
Aborted clients Aborted connects Bytes_received Bytes_sent Connections Created tmp disk tables Created tmp files Created tmp tables Delayed errors Delayed insert threads Delayed writes Flush commands Handler__delete Handler read first Handler_read key Handler read next Handler read prev Handler_read rndHandler read rnd next Handler update Handler write Key blocks used I Key_read__requests
Value 0 0 155372598 1176560426 30023 0 60 8340 0 0 0 1 462604 105881 27820558 390681754 I 6022500 30546748 I 246216530 I 16945404 I 60356676 | 14955 I 96854827
| 1 | | | 1 | | 1 1 1 | | |
4.2. Конфигурирование сервера MySQL Key_reads Key_write_requests Key_writes Max_used_connections Not_flushed_delayed_rows Not_flushed_key_blocks Open_files Open_streams Open_tables Opened_tables Qcache_free_blocks Qcache_free_memory Qcache_hits Qcache_inserts Qcache_lowmem_prunes Qcache_not_cached Qcache_queries_in_cache Qcache_total_blocks Questions Select_full_join Select_full_range_j oin Select_range Select_range_check Select_scan Slave_open_temp_tables Slave_running Slow_launch_threads Slow_queries Sort_merge_passes Sort_range Sort_rows Sort_scan Table_locks_immediate Table_locks_waited Threads_cached Threads_connected Threads_created Threads_running Uptime
261
162040 7589728 3813196 0 0 0 2 0 1 44600 36 138488 79570 27087 3114 22989 415 912 2026873 0 0 99646 0 30802 0 OFF 0 0 30 500 30296250 4650 1920382 0 0 1 30022 1 80380
Большинству переменных состояния с помощью оператора STATUS присваивается значение 0. То, что означают переменные состояния, описано ниже. Переменные счетчика операторов Сот_ххх появились, начиная с версии MySQL 3.23.47. Переменные кэша запросов Qcache_xxx были добавлены, начиная с MySQL 4.O.I. Все остальные переменные, для которых не указан номер версии, доступны, по крайней мере, начиная с версии MySQL 3.22. • Aborted_clients. Количество соединений, прерванных по причине отключения клиента без корректного закрытия соединения. См. раздел А.2.10. • Aborted_connects. Количество неудачных попыток подключения к серверу MySQL. См. раздел А.2.10.
262
Глава 4. Администрирование баз данных
•
Binlog__cache_use. Количество транзакций, использовавших временный кэш бинарного журнала. Эта переменная была добавлена в MySQL 4.I.2.
•
Binlog_cache__diskjjse. Количество транзакций, использовавших временный кэш бинарного журнала, но превысивших значение binlog_cache_size и создавших временный файл для сохранения операторов из транзакций. Эта переменная была добавлена в MySQL 4.1.2.
•
Bytesreceived. Количество байт, полученных от всех клиентов. Эта переменная была добавлена в версии MySQL 3.23.7.
•
Bytes_sent. Количество байт, отправленных всем клиентам. Эта переменная была добавлена в версии MySQL 3.23.7.
•
Comxxx. Количество раз, которое выполнялся каждый оператор ххх. Для каждого типа оператора существует только одна переменная состояния. Например, Comdelete и Cominsert подсчитывают количество выполнений операторов DELETE И INSERT.
•
Connections. Количество попыток (удачных и неудачных) подключения к серверу MySQL.
•
Created_tmp_disk_tables. Количество временных таблиц на диске, созданных сервером автоматически во время выполнения операторов. Эта переменная была добавлена в MySQL 3.23.24.
•
Created_tmp_f i l e s . Количество временных файлов, созданных mysqld. Эта переменная была добавлена в MySQL 3.23.28.
•
Created_tmp_tables. Количество временных таблиц в памяти, созданных сервером автоматически во время выполнения операторов. При большом значении Created_tmp_disk_tables может понадобиться увеличить значение tmp_table_size, чтобы временные таблицы зависели от памяти, а не от диска.
•
Delayed_errors. Количество записанных при помощи INSERT DELAYED строк, в которых произошли какие-либо ошибки (возможно, d u p l i c a t e key).
•
Delayed_insert_threads. Количество используемых потоков обработчика INSERT DELAYED.
• • •
Delayed__writes. Количество записанных строк INSERT DELAYED. Flushcommands. Количество выполненных операторов FLUSH. Handlercommit. Количество внутренних операторов COMMIT. Эта переменная была добавлена в MySQL 4.O.2.
•
H a n d l e r d e l e t e . Количество раз, которое строка удалялась из таблицы.
•
H a n d l e r _ r e a d _ f i r s t . Количество раз, которое первая запись считывалась из индекса. Если это значение высокое, то предполагается, что сервер очень часто осуществляет полное индексное сканирование, например, SELECT c o l l FROM foo, предполагая, что столбец c o l l проиндексирован.
•
Handler_read__key. Количество запросов на чтение строки по ключу. Если данное значение высокое, это хороший показатель того, что все ваши запросы и таблицы корректно проиндексированы.
4.2. Конфигурирование сервера MySQL •
263
Handle r r e a d n e x t . Количество запросов на чтение следующей строки в порядке расположения ключей. Это значение инкрементируется, если запрашивается индексный столбец с ограничениями по диапазону или если проводится индексное сканирование.
• Handler_read_prev. Количество запросов на чтение предыдущей строки в порядке расположения ключей. Данный метод считывания в основном используется для оптимизации ORDER BY... DESC. Эта переменная была добавлена в MySQL 3.23.6. •
Handlerreadrnd. Количество запросов на чтение строки, основанных на фиксированной позиции. Значение будет высоким, если выполняется много запросов, требующих сортировки результатов. Возможно, у вас слишком много запросов, для выполнения которых MySQL приходится сканировать целые таблицы, или имеются соединения, которые некорректно используют ключи.
•
Handler_read_rnd_next. Количество запросов на чтение следующей строки в файле данных. Данное значение будет высоким, если сканирование таблиц проводится часто. В целом это означает, что таблицы не проиндексированы надлежащим образом или что запросы не используют преимущества имеющихся индексов.
• Handler_rollback. Количество внутренних операторов ROLLBACK. • Handlerupdate. Количество запросов на обновление строки в таблице. • Handlerwrite. Количество запросов на вставку строки в таблицу. • Key_blocks_used. Количество используемых блоков в кэше ключей. Данное значение можно применять, чтобы определить, какой процент от объема кэша ключей используется; см. описание переменной key_buf f eresize в разделе 4.2.3. • Key_read_requests. Количество запросов на чтение блока ключей из кэша. • Key_reads. Количество физических считываний блока ключей с диска. Если значение Key_reads слишком большое, тогда значение key_buffer_size, возможно, слишком маленькое. Коэффициент неудач при обращениях к кэш-памяти можно вычислить через Key_reads/Key_read_requests. • Key_write_requests. Количество запросов на запись блока ключей в кэш. • Key_writes. Количество физических записей блока ключей на диск. • Max_used_connections. Максимальное количество соединений, используемых одновременно с момента запуска сервера. • Not_flushed_delayed_rows. INSERT DELAY.
Количество строк, ожидающих записи в очередь
• Not_f lushed_key_blocks. Количество блоков ключей в кэше ключей, которые были изменены, но пока не записаны на диск. • Open_f iles. Количество открытых файлов. • Openst reams. Количество открытых потоков (в основном используется для регистрации в журнале). • Open_tables. Количество открытых таблиц. • Opened_tables. Количество открывавшихся таблиц. Если значение Opened_tables большое, тогда значение table_cache, возможно, слишком маленькое. • Qcachef reeblocks. Количество свободных блоков памяти в кэше запросов.
264
Глава 4. Администрирование баз данных
• Qcache_f reejnemory. Объем свободной для кэша запросов памяти. • Qcache_hits. Количество удачных обращений в кэш. • Qcache_inserts. Количество добавленных в кэш запросов. • Qcache_lowmem_prunes. Количество запросов, удаленных из кэша по причине недостаточного объема памяти. • Qcache_not_cached. Количество запросов, не помещенных в кэш (либо потому что они не подлежат помещению в кэш, либо из-за значения query_cache_type). • Qcache_queries_in_cache. Количество записанных в кэш запросов. • Qcache_total_blocks. Общее количество блоков в кэше запросов. • Questions. Количество отправленных на сервер запросов. • Rpl_status. Состояние отказоустойчивой репликации (пока не реализовано). •
Select_full_join. Количество соединений (таблиц), в которых индексы не используются. Если данное значение не равно 0, следует тщательно проверить индексы ваших таблиц. Эта переменная была добавлена в MySQL 3.23.25.
•
Select_full_range_join. Количество соединений, для которых использовался поиск по диапазону в справочной таблице. Эта переменная была добавлена в MySQL 3.23.25.
•
Select_range. Количество соединений, для которых использовались диапазоны в первой таблице. (Обычно это значение не критично, даже если оно велико.) Эта переменная была добавлена в MySQL 3.23.25.
•
Select_range_check. Количество соединений без ключей, в которых использование ключей проверяется после каждой строки. (Если данное значение не равно О, внимательно проверьте индексы ваших таблиц.) Эта переменная была добавлена в MySQL 3.23.25.
•
Selectscan. Количество соединений, для которых проводилось полное сканирование первой таблицы. Эта переменная была добавлена в MySQL 3.23.25.
•
Slave_open_temp_tables. Количество временных таблиц, открытых на данный момент SQL-потоком подчиненного сервера. Эта переменная была добавлена в MySQL 3.23.29.
•
Slave_running. Имеет значение ON, если это подчиненный сервер, подключенный к главному серверу. Эта переменная была добавлена в MySQL 3.23.16. • Slow_launch_threads. Количество потоков, создание которых заняло больше, чем указано в slow_launch_time, секунд. Эта переменная была добавлена в MySQL 3.23.15. • Slow_queries. Количество запросов, занявших больше, чем указано в long_query_time, секунд. См. раздел 4.8.5. •
Sort_merge_passes. Количество проходов слияния, выполненных алгоритмом сортировки. Если данное значение велико, необходимо увеличить значение системной переменной sort_buffer_size. Эта переменная была добавлена в MySQL 3.23.28.
•
Sortrange. Количество сортировок, выполненных с использованием диапазонов. Эта переменная была добавлена в MySQL 3.23.25.
4.3. Общие проблемы безопасности
265
•
Sortrows. Количество отсортированных строк. Эта переменная была добавлена в MySQL 3.23.25.
•
Ssl__xxx. Переменные, используемые для SSL-соединений. Эти переменные были добавлены в MySQL 4.O.O.
• Tablelocksimmediate. Количество раз, когда блокировка таблицы осуществлялась немедленно. Эта переменная была добавлена, начиная с версии MySQL 3.23.33. •
Table_locks_waited. Количество раз, когда немедленная блокировка таблицы была невозможна, и требовалось время на ожидание. Если данное значение велико, и имеются проблемы с производительностью, сначала необходимо оптимизировать запросы, а затем либо провести разбивку таблицы или таблиц, либо прибегнуть к репликации. Эта переменная появилась, начиная с версии MySQL 3.23.33.
• Threads_cached. Количество потоков в кэше потоков. Эта переменная была добавлена в MySQL 3.23.17. • Threads_connected. Количество открытых на данный момент соединений. • Threads_created. Количество потоков, созданных для управления соединениями. Если значение Threads_created велико, может понадобиться увеличить значение thread__cache_size. Коэффициент удачных обращений в кэш можно вычислить через Threads_created/Connections. Эта переменная была добавлена в MySQL 3.23.31. • Threads_running. Количество потоков, не находящихся в режиме ожидания. • Uptime. Время работоспособного состояния сервера в секундах.
4.3. Общие проблемы безопасности В данном разделе описан ряд общих проблем, связанных с безопасностью, о которых следует знать, а также то, что можно сделать, чтобы еще больше защитить вашу систему MySQL от хакеров или недопустимой эксплуатации. Информация, касающаяся непосредственно системы управления доступом, которую MySQL использует для настройки учетных записей и проверки прав доступа к базам данных, находится в разделе 4.4.
4.3.1. Общие принципы, касающиеся безопасности системы Все, кто используют MySQL на компьютере, подключенном к Internet, должны прочитать этот раздел, дабы избежать наиболее распространенных ошибок, связанных с безопасностью системы. При обсуждении вопросов безопасности акцент делается на необходимости в абсолютной защите хоста сервера (а не только сервера MySQL) от всевозможных атак любого рода: несанкционированного перехвата данных, изменения и считывания информации или отказа в обслуживании. Здесь охвачены далеко не все аспекты, касающиеся работоспособности и отказоустойчивости сервера. В MySQL для всех соединений, запросов и других операций, которые пользователь может пытаться выполнить, используется система безопасности, основанная на списках контроля доступа (Access Control List - ACL). Она также включает поддержку SSL-
266
Глава 4. Администрирование баз данных
соединений между клиентами и серверами MySQL. Многие обсуждаемые в данном разделе принципы не являются характерными только для MySQL; основные общие понятия применимы почти ко всем приложениям. Работая с MySQL, по возможности руководствуйтесь следующими принципами: • Никогда и никому (кроме привилегированных (root) учетных записей MySQL) не предоставляйте доступ к таблице user в базе данных mysql! Это критически важно. Зашифрованный пароль - это реальный пароль в MySQL. Любой, кто знает указанный в таблице user пароль и имеет доступ к хосту, указанному для данной учетной записи, легко сможет войти в систему в качестве пользователя. • Изучите систему привилегий доступа MySQL. Операторы GRANT и REVOKE используются для управления доступом к MySQL. He предоставляйте привилегий больше, чем необходимо. И никогда не предоставляйте их всем хостам. Ниже представлены шаги по проверке. • Попробуйте выполнить оператор mysql -u root. Если при этом удастся успешно подключиться к серверу без приглашения ввести пароль, значит у вас проблемы. То есть любой сможет подсоединяться к вашему серверу MySQL как привилегированный (root) пользователь, обладающий всеми привилегиями! Еще раз просмотрите инструкции по установке, обращая особое внимание на информацию, касающуюся установки пароля для root. См. раздел 2.4.5. • Используйте оператор SHOW GRANTS, чтобы проверить, кто и к чему имеет доступ. Затем с помощью оператора REVOKE удалите ненужные привилегии. • Не храните в своей базе данных незашифрованных паролей. При дискредитации вашего компьютера злоумышленник может получить список всех паролей и воспользоваться ими. Поэтому лучше применяйте MD5(), SHAH) или какую-нибудь другую одностороннюю хеш-функцию. • Не выбирайте для паролей слова из словаря. Существуют специальные программы для взлома таких паролей. Даже пароли наподобие "xfish98" считаются очень плохими. Намного лучше будет пароль "duag98", который содержит то же слово "fish", но напечатан буквами, расположенными слева от них на одну букву на стандартной клавиатуре QWERTY. Другой метод предполагает применение паролей типа "Mhall", составляемых из первых букв каждого слова в предложении; в данном случае это предложение - "Mary had a little lamb". Такой пароль легко запомнить и легко вводить, но трудно разгадать тому, кто его не знает. • Не пожалейте средств на брандмауэр. Это позволит защититься, по крайней мере, от 50% всякого рода уязвимых мест в любом программном обеспечении. Размещайте MySQL за брандмауэром или в демилитаризованной зоне (DMZ). Ниже представлены шаги по проверке. • Попробуйте провести сканирование портов из Internet с помощью соответствующих инструментальных средств, таких как nmap. По умолчанию MySQL использует порт 3306. Этот порт с ненадежных хостов не должен быть доступен. Другой простой способ проверить, открыт или нет ваш MySQL-порт - с какой-нибудь удаленной машины попытаться выполнить следующую команду, где хост_сервера - имя хоста, на котором работает ваш сервер MySQL: shell> telnet хост_сервера 3306
4.3. Общие проблемы безопасности
267
Если соединение установить удается, и вы получаете какие-то посторонние символы, значит, порт открыт и его следует закрыть на брандмауэре или маршрутизаторе, пока не появится действительно веская причина оставить этот порт открытым. Если же telnet просто зависнет, или при попытке подключиться будет получен отказ, значит, все в порядке: порт заблокирован. • Не доверяйте никаким данным, которые вводят пользователи приложений. Они могут попытаться обхитрить ваш код посредством ввода последовательностей специальных или управляющих символов в Web-формах, полях URL-адресов или в любых созданных вами приложениях. Убедитесь, что защита приложения остается надежной, даже когда пользователь вводить что-нибудь типа "; DROP DATABASE mysql;". Хоть это и крайний случай, однако серьезные бреши в системе безопасности и потеря данных нередко становятся результатом действий хакеров, использующих подобные приемы, когда вы к ним не готовы. Самая типичная ошибка - это когда обеспечивается защита только для данных строкового типа. Не забывайте о необходимости в проверке также и числовых данных. Если приложение генерирует запрос типа SELECT * FROM table WHERE ID=234 с вводом значения 234, пользователь сможет ввести значение 234 OR 1=1, чтобы заставить приложение генерировать запрос SELECT * FROM table WHERE ID=234 OR 1=1. В результате сервер будет извлекать каждую запись из таблицы. Это приводит к отображению всех записей и излишней нагрузке на сервер. Самый простой способ защиты от подобного рода атак - это ставить апостроф с двух сторон числовой константы: SELECT * FROM table WHERE ID='234 f . При вводе пользователем дополнительной информации, она становится частью строки. В числовом контексте MySQL автоматически преобразует такую строку в число и удаляет из нее любые замыкающие нецифровые символы. Иногда некоторые думают, что если в базе данных содержатся только общедоступные данные, ее защита не имеет смысла. Такое мнение в корне не верно. Даже если разрешается отображать все записи из базы данных, по-прежнему должна предусматриваться защита от атак типа отказа в обслуживании (которые, к примеру, используют описанный выше прием, что приводит к трате ресурсов сервера). В противном случае ваш сервер может перестать отвечать на запросы авторизованных пользователей. Ниже представлены шаги по проверке. • Попробуйте ввести ' ' ' (апостроф) и '"' (кавычка) во всех ваших Web-формах. Если MySQL выдаст какую-нибудь ошибку, сразу же разберитесь, с чем была связана проблема. • Попробуйте модифицировать любые динамические URL-адреса путем добавления в них %22 (""), %23 ('#') и %27 (''') •
Попробуйте изменить типы данных в динамических URL-адресах с числовых на символьные, содержащие символы из предыдущих примеров. Защита приложения должна быть стабильна при атаках подобного рода. • Попробуйте вводить не цифры, а буквы, пробелы или специальные символы в числовых полях. Ваше приложение в таком случае должно удалять их перед передачей в MySQL или выдавать ошибку. Передавать в MySQL непроверенные значения очень опасно! • Проверяйте размеры данных перед передачей в MySQL.
268
Глава 4. Администрирование баз данных •
Продумайте использование для вашего приложения при подключении к базе данных пароля, отличного от имени пользователя, применяемого для целей администрирования. Не предоставляйте приложениям никаких привилегий доступа, которые не являются для них необходимыми.
• Многие API-интерфейсы предоставляют средства, позволяющие избежать использования специальных символов в значениях данных. При правильном применении таких средств пользователи приложений не смогут вводить значения, которые приводят к генерированию приложением операторов, не соответствующих вашим требованиям: • MySQL С API - используйте API-вызов m y s q l r e a l e s c a p e s t r i n g (). • MySQL++ - используйте модификаторы escape и quote для потоков запросов. • РНР - используйте функцию mysql_escape_string(), основанную на функции с таким же именем в MySQL С API. До РНР 4.0.3 вместо указанной используйте функцию addslashes (). • Perl DBI - используйте метод quote () или символы-заполнители. • Java JDBC - используйте объект PreparedStatement и символы-заполнители. Остальные API-интерфейсы имеют аналогичные возможности. • Не передавайте открытые (незашифрованные) данные через Internet. Такая информация доступна любому, у кого есть время и возможность перехватить и использовать ее в своих собственных целях. Вместо этого пользуйтесь протоколами с шифрованием данных, такими как SSL или SSH. MySQL поддерживает внутренние SSL-соединения, начиная с версии 4.0.0. Переадресация SSH-портов может использоваться, чтобы создать туннель, через который будут передаваться зашифрованные (и сжатые) данные. • Научитесь пользоваться утилитами tcpdump и strings. В большинстве случаев проверить, зашифрованы ли потоки данных MySQL, можно с помощью команды, подобной следующей: shell> tcpdump -I -i ethO -w - src or dst port 3306 | strings (Она работает в Linux и с незначительными изменениями должна работать в других системах.) Будьте внимательны: если вы не видите данных в читабельном формате, это не всегда означает, что они на самом деле зашифрованы. Если есть необходимость в высокой степени защиты, следует проконсультироваться у специалиста по подобным вопросам.
4.3.2. Как защитить MySQL от хакеров При подключении к серверу MySQL необходимо использовать пароль. Пароль не передается в виде открытого текста через соединение. Функции управления паролями во время подключения клиентов в MySQL 4.1.1 получили дополнительную степень защиты. При использовании старой версии MySQL или паролей старого (до версии 4.1.1) формата, алгоритм шифрования более уязвим, и сообразительный хакер, который имеет возможность перехватывать поток данных между клиентом и сервером, потратив определенные усилия, сможет такой пароль взломать. (За более подробной информацией о различных методах управления паролями обратитесь в раздел 4.4.9.) Если соединение между клиентом и сервером осуществляется через ненадежную сеть, следует использовать SSH-туннель для шифрования связи.
4.3. Общие проблемы безопасности
269
Вся остальная информация передается в виде текста, который может прочитать любой, имеющий возможность наблюдать за соединением. Если это вызывает беспокойство, попробуйте воспользоваться протоколом со сжатием данных (доступным в версиях MySQL 3.22 и выше), который значительно затрудняет дешифровку. Чтобы еще больше повысить степень безопасности соединения, следует использовать протокол SSH, который обеспечивает шифрованное TCP/IP-соединение между сервером и клиентом MySQL. Клиент Open Source SSH доступен на сайте http://www.openssh.org/, а коммерческий SSH-клиент - на сайте h t t p : //www. ssh. com/. В версии MySQL 4.0 и выше также доступна внутренняя OpenSSL-поддержка. См. раздел 4.5.7. Чтобы защитить систему MySQL, необходимо самым серьезным образом отнестись к перечисленным ниже рекомендациям. • Применяйте пароли для всех пользователей MySQL. Клиентскому приложению не обязательно известно, кто именно работает с ним. Для клиент-серверных приложений общепринято, что пользователь может указывать для клиентской программы любое имя пользователя. Например, каждый может воспользоваться программой mysql и подключиться под именем другого человека, просто вызвав ее через mysql -u другой^пользователь имя_базы__данных, если для пользователя другой_пользователь не установлен пароль. Если пароли есть у всех пользователей, подключиться при помощи учетной записи другого пользователя будет намного сложнее. Чтобы изменить для пользователя пароль, используйте оператор SET PASSWORD. Также можно обновить таблицу user прямо в базе данных mysql. Например, чтобы изменить пароль для всех учетных записей MySQL с именем пользователя root, потребуется предпринять следующие действия: shell> mysql> -> mysql>
mysql -u root UPDATE mysql.user SET Password=PASSWORD('новый_пароль') WHERE User='root 1 ; FLUSH PRIVILEGES;
• He запускайте сервер MySQL от имени привилегированного (root) пользователя Unix. Это очень опасно, поскольку любой, имеющий привилегию FILE, сможет создавать файлы как привилегированный (root) пользователь (например, -root/.bashrc). Чтобы предотвратить подобные действия, mysql отказывается запускаться от имени root до тех пор, пока это не будет указано явно, с помощью опции —user=root. Вместо этого mysqld можно запускать от имени простого непривилегированного пользователя. Также есть возможность создать отдельную запись Unix с именем mysql, чтобы обеспечить дополнительную степень защиты. Используйте эту учетную запись только для администрирования MySQL. Чтобы запустить mysqld от имени другого пользователя Unix, добавьте опцию user, определяющую имя пользователя, в группу [mysqld] файла опций /etc/my.cnf или файла опций my. cnf, который находится в каталоге данных сервера. Например: [mysqld] user=mysql
270
Глава 4. Администрирование баз данных Это приводит к запуску сервера от имени назначенного пользователя, независимо от того, запускается ли сервер вручную либо с помощью mysqldsafe или mysql. server. Более подробную информацию можно найти в разделе А.3.2. Запуск mysql от имени другого, непривилегированного (не root) пользователя Unix не означает, что нужно поменять имя пользователя root в таблице user. Имена пользователей для учетных записей MySQL не имеют ничего общего с именами пользователей для учетных записей Unix.
• Запретите использование символических ссылок на таблицы. (Данную функцию можно отключить с помощью опции —skipsymbolic-links.) Это особенно важно, если mysqld запускается от имени root, поскольку каждый, кто имеет доступ для записи в каталоги данных сервера, сможет удалить любой файл в системе! См. раздел 6.6.1.2. • Убедитесь, что только один пользователь Unix, имеющий привилегии чтения/записи в каталогах баз данных, является пользователем, от имени которого запускается mysqld. • Не предоставляйте привилегию PROCESS или SUPER обычным пользователям. Выходные данные команды mysqladmin processlist отображают текст обрабатываемых на данный момент запросов, поэтому любой пользователь, которому разрешено выполнять эту команду, сможет просмотреть запрос другого пользователя, такой, например, как UPDATE user SET password=PASSWORD('not_secure'). Сервер mysqld резервирует дополнительное соединение для пользователей, имеющих привилегию SUPER (или PROCESS в версиях до MySQL 4.0.2) так, чтобы привилегированный (root) пользователь MySQL смог войти в систему и проверить активность сервера, даже когда все обычные соединения на данный момент заняты. Привилегия SUPER может использоваться для завершения соединений клиентов, смены режима работы сервера путем изменения значения системных переменных и для управления серверами репликации. • Не предоставляйте привилегию FILE обычным пользователям. Любой пользователь, имеющий такую привилегию, в любом месте файловой системы сможет записать файл с привилегиями демона mysqld! Чтобы хоть как-то защититься от этого, в файлы, созданные с помощью SELECT... INTO OUTFILE, разрешена запись, однако перезаписывать существующие файлы нельзя. • Если вы не доверяете DNS, в таблицах привилегий используйте IP-адреса вместо имен хостов. В любом случае будьте предельно осторожны при создании для таблиц привилегий записей с именами хостов, которые содержат групповые символы! • Чтобы ограничить число разрешенных для одной учетной записи соединений, установите в mysqld переменную max_user_connections. Оператор GRANT тоже поддерживает опции управления ресурсами, ограничивающие допустимую для одного пользователя степень использования серверных ресурсов.
4.3.3. Опции запуска для mysqld, касающиеся безопасности Следующие опции mysqld влияют на степень безопасности системы:
4.3. Общие проблемы безопасности
271
•
—local-infile[={0 11} ]. Если запустить сервер с — local-infile=0, клиенты не смогут использовать операторы LOAD DATA. См. раздел 4.3.4.
•
—safe-show-database. При использовании данной опции оператор SHOW DATABASES будет отображать имена только тех баз данных, для доступа к которым у пользователя имеется хоть какая-нибудь привилегия. Начиная с версии 4.0.2, эта опция устарела и ни для чего не служит (по умолчанию включена). Теперь существует привилегия SHOW DATABASES, которую можно использовать, чтобы управлять доступом к базам данных для каждой учетной записи отдельно.
•
—safe-user-create. Если данная опция включена, пользователь не сможет создавать новых пользователей с помощью оператора GRANT до тех пор, пока у него не будет привилегии INSERT для таблицы mysql.user. Чтобы пользователь имел возможность создавать новых пользователей с теми привилегиями, которые у него есть право предоставлять, ему следует предоставить следующую привилегию: mysql> GRANT INSERT(user) ON mysql.user TO 'имя_пользователя}@'имя_хостах; Это гарантирует, что пользователь не сможет изменять непосредственно ни один из столбцов привилегий, и для предоставления привилегий другим пользователям ему придется использовать оператор GRANT.
•
—secure-auth. Запрещает аутентификацию учетным записям, использующим старые (до версии 4.1) пароли. Эта опция доступна, начиная с MySQL 4.1.1.
•
—skip-grant-tables. При установке данной опции сервер совсем не будет использовать систему привилегий. То есть каждый пользователь получает полный доступ ко всем базам данных! (Можно сделать так, чтобы сервер снова начал использовать таблицы привилегий, с помощью команды mysldadmin flushprivileges или mysqladmin reload, либо же оператора FLUSH PRIVILEGES.)
•
—skip-name-resolve. Преобразование имен хостов не выполняется. Все значения столбцов Host в таблицах привилегий должны хранить IP-адреса или localhost.
•
—skip-networking. Запрещает TCP/IP-соединения через сеть. Все подключения к mysqld должны осуществляться через файлы сокетов Unix. Эта опция не подходит для версий MySQL, предшествующих 3.23.27, которые используются вместе с пакетом MIT-pthreads, поскольку на тот момент файлы сокетов Unix не поддерживались потоками MIT-pthreads.
•
—skip-show-database. При установке данной опции оператор SHOW DATABASES доступен только пользователям, имеющим привилегию SHOW DATABASES, и отображает имена всех баз данных. Если эта опция не используется, SHOW DATABASES разрешен для всех пользователей, но отображает имя каждой базы данных, только если пользователь имеет привилегию SHOW DAATABASES или какую-нибудь другую привилегию для базы данных.
4.3.4. Вопросы безопасности и оператор LOAD DATA LOCAL Оператор LOAD DATA может загружать файл, находящийся на хосте сервера или на хосте клиента, когда указано ключевое слово LOCAL. При поддержке версии LOCAL операторов LOAD DATA существуют две потенциальные проблемы, касающиеся безопасности системы:
272
Глава 4. Администрирование баз данных
• Передача файла с хоста клиента на хост сервера инициируется сервером MySQL. Теоретически можно собрать сервер с исправлениями, который бы заставлял клиентскую программу передавать выбранный сервером файл, а не файл, указанный клиентом в операторе LOAD DATA. Такой сервер мог бы получать доступ к любому файлу на хосте клиента, к которому у пользователя имеется доступ по чтению. • В Web-среде, где клиенты подключаются с Web-сервера, пользователь мог бы использовать оператор LOAD DATA LOCAL для чтения любых файлов, к которым процесс Web-сервера имеет доступ для чтения (предполагается, что пользователь может выполнять любые команды, касающиеся SQL-сервера). В такой среде клиент по отношению к MySQL-серверу фактически является Web-сервером, а не программой, запускаемой пользователем, которая подключается к Web-серверу. Чтобы решить такие проблемы безопасности, для оператора LOAD DATA LOCAL в MySQL 3.23.49 и MySQL 4.0.2 (4.0.13 для Windows) были внесены определенные изменения: • По умолчанию все клиенты и библиотеки MySQL в бинарных дистрибутивах для совместимости с MySQL 3.23.48 и ниже компилируются с опцией —enablelocal-infile. • Если во время сборки MySQL из исходного дистрибутива при его конфигурировании опция —enable-local-infile не указывается, никакие клиенты не смогут использовать оператор LOAD DATA LOCAL до тех пор, пока он не будет записан явно ДЛЯ вызова raysql_options (. . . MYSQL_OPT_LOCAL_INFILE, 0). • Можно заблокировать все команды LOAD DATA LOCAL со стороны сервера, запустив mysqld с опцией —local-inf ile=0. • Для клиента командной строки mysql оператор LOAD DATA LOCAL можно разблокировать, задав опцию —local-inf i l e [=1], или заблокировать через опцию —local-infile=0. Аналогично для mysqlimport опция —local или -L разрешает локальную загрузку файлов данных. В любом случае, чтобы успешно использовать операцию локальной загрузки, сначала потребуется соответствующим образом настроить сервер. • Если оператор LOAD DATA LOCAL INFILE заблокирован на сервере или клиенте, клиент при попытке его выполнить получит следующее сообщение об ошибке: ERROR 1148: The used command is not allowed with this MySQL version ОШИБКА 1148:
Используемая
команда недопустима в данной версии MySQL
4.4. Система привилегий доступа MySQL В MySQL реализована расширенная, а не стандартная система привилегий и безопасности. В данном разделе описываются особенности ее функционирования.
4.4.1. Функции системы привилегий Первоначальная функция системы привилегий MySQL связаны с аутентификацией пользователя, подключающегося с определенного хоста, и ассоциированием его с привилегиями базы Данных, такими как SELECT, INSERT, UPDATE И DELETE.
4.4. Система привилегий доступа MySQL
273
Дополнительные функции включают возможность наличия анонимного пользователя и возможность предоставления привилегий специальным MySQL-функциям, таким как LOAD DATA INFILE и операции по администрированию.
4.4.2. Как работает система привилегий Система привилегий MySQL гарантирует, что каждый пользователь может выполнять только разрешенные ему операции. Когда вы подключаетесь к серверу MySQL как пользователь, ваша личность определяется по имени хоста, с которого вы подключаетесь, и по имени пользователя, которое вы указываете. Система привилегий предоставляет привилегии в соответствии с вашей личностью и тем, что вы хотите делать. Во время идентификации MySQL анализирует и имя хоста, и имя пользователя, так как процент того, что указанное имя пользователя принадлежит одному и тому же человеку во всей сети Internet, слишком мал. Например, пользователь joe, который подключается с office.com, совсем не обязательно тот же самый человек, что и пользователь joe, подключающийся с elswhere.com. MySQL справляется с этой проблемой, позволяя различать пользователей, подсоединяющихся с разных хостов, но имеющих одно и то же имя пользователя: можно предоставить joe один набор привилегий для подключений с office. com, и совершенно другой - для подсоединений с elswhere. com. В MySQL управление доступом подразумевает два этапа: • Первый этап: сервер проверяет, разрешено ли вам вообще подключаться. • Второй этап (предполагает, что разрешение на подключение у вас имеется): сервер проводит верификацию каждого вашего оператора на предмет достаточного количества привилегий для его выполнения. Например, при попытке выбрать строки в таблице базы данных или удалить таблицу из базы данных, сервер проверяет, есть ли у вас привилегия SELECT для таблицы или, во втором случае, привилегия DROP для базы данных. Если привилегии изменяются (вами или кем-либо другим) в то время, когда вы подключены к серверу, эти изменения не обязательно вступят в силу сразу же при выполнении следующего оператора. Более подробную информацию можно найти в разделе 4.4.7. Все решения, касающиеся управления доступом, основаны на копиях таблиц привилегий в памяти. Обычно обработка содержимого таблиц привилегий осуществляется косвенно, через использование операторов GRANT и REVOKE для настройки учетных записей и управления привилегиями, доступными каждой из них. В данном разделе описана базовая структура таблиц привилегий, также то, как сервер использует их содержимое при взаимодействии с клиентами. Сервер использует таблицы user, db и host из базы данных mysql на обоих этапах управления доступом. Столбцы этих таблиц привилегий представлены в табл. 4.2. На втором этапе управления доступом (верификация запросов), если запрос подразумевает обращение к таблицам, сервер может дополнительно провести сверку с таблицами tables_priv или columnspriv, что обеспечивает лучшее управление доступом на уровне таблиц и столбцов. Столбцы таких таблиц представлены в табл. 4.3.
274
Глава 4. Администрирование баз данных Таблица 4.2. Столбцы таблиц user, db и host
Таблица user
Таблица db
Таблица host
Host User Password
Столбцы контекста Host Db User
Host Db
Select priv Insert priv Update_priv Delete priv Index_priv Alter_priv Create priv Drop priv Grant_priv References priv Reload priv Shutdown priv Process_priv File priv Show db priv Super priv Create_tmp table priv Lock tables priv Execute priv Repl_slave_priv Repl client_priv ssl_type ssl cipher x509 issuer x509_subject max questions max updates max connections
Столбцы привилегий Select priv Insert priv Update priv Delete priv Index_priv Alter_priv Create priv Drop priv Grant_priv References priv
Select priv Insert priv Update priv Delete priv Index priv Alter priv Create priv Drop priv Grant priv References_priv
Create tmp table priv Lock tables priv
Create tmp table priv Lock_tables__priv
4.4. Система привилегий доступа MySQL
275
Таблица 4.3. Столбцы таблиц tables_priv и columns_priv Таблица tables_priv
Таблица columnsjpriv Столбцы контекста
Host Db
Host Db
User
User
Table_name
Table_name Column name
Столбцы привилегий
Table priv
Column priv
Column_priv Другие столбцы
Timestamp
Timestamp
Grantor Столбцы Timestamp и Grantor на данный момент не используются, и поэтому больше обсуждаться не будут. Каждая таблица привилегий содержит столбцы контекста и столбцы привилегий: • Столбцы контекста определяют область действия каждой записи (строки) в таблице, то есть контекст, в котором та или иная запись применяется. Например, строка таблицы user, значения в столбцах Host и User которой равны, соответственно, 'thomas.loc.gov' и 'bob', используется для аутентификации подключений к серверу с хоста thomas.loc.gov, осуществляемых клиентом с именем пользователя bob. Точно так же строка таблицы, значения в столбцах Host, User и Db которой хранятся ' thomas. loc. gov', 'bob' и ' reports', будет использоваться, когда bob попытается подключиться с хоста thomas.loc.gov, чтобы получить доступ к базе данных reports. Таблицы tables_priv и columns_priv содержат столбцы, с именами таблиц или комбинациями имен таблиц и столбцов, к которым применяется каждая запись. • В столбцах привилегий указаны привилегии, предоставляемые записью в таблице, то есть выполнение каких операций разрешено. Чтобы составить полное описание привилегий пользователя, сервер компонует информацию из самых разных таблиц привилегий. Правила, необходимые для осуществления этого процесса, перечислены в разделе 4.4.6. Столбцы контекста содержат строковые значения, объявленные так, как показано в табл. 4.4. Значение по умолчанию для каждого столбцов - пустая строка. До версии MySQL столбец Db был объявлен как CHAR (32) в одних таблицах и как CHAR(60) в других. Что касается проверки доступа, при сравнении значений Host регистр символов не учитывается. Значения User, Password, Db и Table_name от регистра зависят. Значения Column_name в MySQL 3.22.12 и последующих версиях к регистру не чувствительны.
276
Глава 4. Администрирование баз данных
Таблица 4.4. Столбцы контекста Имя столбца
Тип
Host User
CHAR(60)
Password
CHAR(16)
Db
CHAR(64)
Table_name
CHAR(60)
Column name
CHAR(60)
CHAR(16)
В таблицах user, db и host каждая привилегия указана в отдельном столбце, объявленном как ENUM (' N ' , ' Y') DEFAULT ' N'. Другими словами, каждая привилегия может быть включена или отключена; по умолчанию устанавливается значение ' N' (отключена). В таблицах tables_priv и columns_priv столбцы привилегий объявлены как столбцы SET. Значения в этих столбцах могут содержать любую комбинацию привилегий, контролируемых таблицей (см. табл. 4.5): Таблица 4.5. Столбцы привилегий Имя таблицы
Имя столбца
Возможные элементы набора
tables_priv
Table_priv
'Select f , ' I n s e r t ' , 'Update', 'Delete', 'Create', 'Drop', 'Grant', 'References', 'Index', 'Alter'
tables_priv
Columnjpriv
' S e l e c t ' , ' I n s e r t ' , 'Update', 'References'
columns_priv
Column_priv
'Select', ' I n s e r t ' , 'Update', 'References'
Если выражаться кратко, то сервер использует таблицы привилегий следующим образом: •
Столбцы контекста таблицы user определяют, отклонить или разрешить входящие соединения. Для разрешенных соединений любые предоставленные в таблице user привилегии обозначают глобальные привилегии пользователя (то есть это привилегии суперпользователя). Такие привилегии применяются ко всем хранящимся на сервере базам данных.
• Столбцы контекста таблицы db определяют, какие пользователи, с каких хостов и к каким базам данных могут получать доступ. Столбцы привилегий определяют, какие операции разрешены. Привилегия, предоставленная на уровне базы данных, распространяется на базу данных и все ее таблицы. •
Таблица host используется вместе с таблицей db, когда необходимо, чтобы определенная запись из таблицы db применялась сразу к нескольким хостам. Например, если требуется, чтобы пользователь мог получать доступ к базе данных с разных хостов сети, оставьте значение столбца Host в записи таблицы db этого пользователя пустым, а затем заполните таблицу host, внося записи для каждого из этих хостов. Данный механизм более подробно описывается в разделе 4.4.6.
4.4. Система привилегий доступа MySQL
|
277
На заметку!
Щ Применение операторов GRANT и REVOKE никак не отражается на таблице host. Большинство %, установок MySQL вообще не нуждается в этой таблице.
• Таблицы tables_priv и columnspriv схожи с таблицей db, но характеризуются разбиением более мелкого уровня: они применяются уже на уровнях таблиц и столбцов, а не на уровне базы данных. Привилегия, предоставляемая на уровне таблицы, распространяется на таблицу и все ее столбцы. Привилегия, предоставленная на уровне столбца, распространяется только на конкретный столбец. Административные привилегии (такие как RELOAD или SHUTDOWN) задаются только в таблице user, потому что операции администрирования представляют собой операции на самом сервере и не являются специальными для баз данных. Таким образом, перечислять эти привилегии в остальных таблицах привилегий не имеет смысла. Фактически, чтобы определить, имеете ли вы права на выполнение операции по администрированию, сервер должен обратиться только к таблице user. Привилегия FILE тоже задается только в таблице user. Она не представляет собой административную привилегию как таковую, но возможность считывания и записи файлов на хосте сервера не зависит от базы данной, к которой вы получаете доступ. Сервер mysqld считывает и заносит в память содержимое таблиц привилегий во время запуска. Заставить сервер провести повторное считывание таблиц можно с помощью оператора FLUSH PRIVILEGES или команд mysqladmin flush-privileges и mysqladmin reload. В разделе 4.4.7 описано, когда и как вносимые в таблицы привилегий изменения вступают в силу. При изменении содержимого таблиц привилегий не помешает убедиться, что вносимые изменения устанавливают привилегии в соответствии с вашими желаниями. Один из способов проверить предоставленные конкретной учетной записи привилегии предполагает использование оператора SHOW GRANTS. Например, чтобы определить привилегии, предоставленные учетной записи, значения Host и User которой соответствуют рс84. example. com и bob, введите следующую команду: mysql> SHOW GRANTS FOR 'bob'@'pc84.example.com•; Полезным инструментом диагностики является сценарий mysqlaccess, который для дистрибутива MySQL предоставил Ив Карлье (Yves Carlier). Чтобы узнать, как он работает, вызовите mysqlaccess с опцией —help. Обратите внимание, что mysqlaccess управляет доступом, используя только таблицы user, db и host. Привилегии, заданные в таблицах tables_priv и columnspriv, он не проверяет. Дополнительную справочную информацию по диагностике связанных с привилегиями проблем можно найти в разделе 4.4.8. Общие советы по вопросам обеспечения безопасности представлены в разделе 4.3.
44.3. Привилегии, предоставляемые MySQL Информация о привилегиях для учетных записей хранится в таблицах user, db, host, tables_priv и columnspriv базы данных mysql. Сервер MySQL считывает и заносит содержимое этих таблиц в память во время запуска, а повторное считывание осуществляет при обстоятельствах, описанных в разделе 4.4.7. Названия, используемые в данном руководстве для ссылки на предоставляемые MySQL привилегии, перечислены в табл. 4.6. При этом также представлены имена
278
Глава 4. Администрирование баз данных
столбцов таблицы, ассоциируемых с каждой привилегией в таблицах привилегий, и контекст, в котором применяется та или иная привилегия. Дополнительную информацию о значении каждой переменной можно найти в книге "MySQL. Справочник по языку ". Таблица 4.6. Названия для ссылки на предоставляемые MySQL привилегии Привилегия
Столбец
Контекст
ALTER
Alter_priv
таблицы
DELETE
Delete_priv
таблицы
INDEX
Index_priv
таблицы
INSERT
Insert_priv
таблицы
SELECT
Select_priv
таблицы
UPDATE
Update_priv
таблицы
CREATE
Create_priv
базы данных, таблицы или индексы
DROP
Drop_priv
базы данных или таблицы
GRANT
Grant_priv
базы данных или таблицы
REFERENCES
References_priv
базы данных или таблицы
Create_tmp_tablejpriv
администраторы сервера
CREATE TEMPORARY
TABLES
EXECUTE
Executejpriv
администраторы сервера
FILE
File_priv
доступ к файлам на хосте сервера
LOCK TABLES
Lock_tables_priv
администраторы сервера
PROCESS
Processjpriv
администраторы сервера
RELOAD
Reload_priv
администраторы сервера
REPLICATION
CLIENT
Repl_client_priv
администраторы сервера
REPLICATION
SLAVE
Repl_slave_priv
администраторы сервера
SHOW DATABASES
Show_dbj?riv
администраторы сервера
SHUTDOWN
Shutdown_priv
администраторы сервера
SUPER
Super_priv
администраторы сервера
П р и в и л е г и и CREATE REPLICATION
TEMPORARY
TABLES, EXECUTE, LOCK
TABLES, REPLICATION
CLIENT,
SLAVE, SHOW DATABASES И SUPER ПОЯВИЛИСЬ В M y S Q L 4 . 0 . 2 .
Привилегии EXECUTE и REFERENCES в настоящее время не используются. Привилегии SELECT, INSERT, UPDATE и DELETE позволяют выполнять операции со строками в существующих таблицах базы данных. Операторы SELECT требуют наличия привилегии SELECT, только если они на самом деле извлекают строки из таблицы. Некоторые операторы SELECT не обращаются к таблицам и могут быть выполнены даже без разрешения на доступ к базам данных. Например, можно использовать клиент raysql в качестве простого калькулятора для вычисления выражений, которые не ссылаются на таблицы: mysql> SELECT 1+1; mysql> SELECT PI()*2;
4.4. Система привилегий доступа MySQL
279
Привилегии CREATE и DROP позволяют создавать новые базы данных и таблицы и л и удалять существующие. П р и предоставлении привилегии DROP д л я доступа к базе д а н ных mysql пользователю, этот пользователь может удалить базу данных, в которой хранятся привилегии доступа M y S Q L ! Привилегия INDEX позволяет создавать и л и удалять индексы. О н а распространяется на существующие таблицы. П р и наличии привилегии CREATE д л я таблицы появляется возможность включать индексные д е ф и н и ц и и в оператор CREATE TABLE. Привилегия ALTER позволяет использовать оператор ALTER TABLE д л я изменения структуры таблиц, а также д л я и х переименования. Привилегия GRANT позволяет предоставлять другим пользователям те привилегии, к о торые имеются у вас самих. Привилегия FILE разрешает считывать и записывать ф а й л ы н а хосте сервера с помощ ь ю операторов LOAD DATA INFILE и SELECT...INTO OUTFILE. Пользователь, и м е ю щ и й привилегию FILE, может читать л ю б о й общедоступный либо доступный д л я M y S Q L файл н а хосте сервера. ( Э т о подразумевает, что пользователь может считывать л ю б о й файл и з любого каталога базы данных, поскольку сервер имеет доступ к каждому и з этих файлов.) Привилегия FILE также позволяет пользователю создавать новые файлы в л ю б о м каталоге, к которому сервер M y S Q L имеет доступ п о записи. Перезаписать существующие файлы невозможно. Остальные привилегии используются д л я операций администрирования, большинство из которых выполняется с п о м о щ ь ю программы mysqladmin и л и SQL-операторов. Таблица 4.7 иллюстрирует, какие команды mysqladmin разрешает выполнять каждая административная привилегия. Т а б л и ц а 4.7. Команды mysqladmin, разрешенные административными привилегиями Привилегия
Команды, разрешенные обладателю привилегий
RELOAD
flush-hosts, flush-logs, flush-privileges, flush-status, flush-tables,flush-threads, refresh, reload
SHUTDOWN
shutdown
PROCESS
processlist
SUPER
kill
Команда reload заставляет сервер выполнить повторное считывание и занесение в память таблиц привилегий, flushprivileges является синонимом reload. Команда refresh закрывает и открывает заново журнальные файлы, а также очищает все таблицы. Другие команды flush-xxx выполняют функции, подобные функциям refresh, но являются более специфическими, и поэтому в отдельных случаях их применение предпочтительней. Например, если необходимо очистить только журнальные файлы, лучше использовать команду flush-logs, чем refresh. Команда shutdown завершает работу сервера. Эта команда может быть выполнена только из программы mysqladmin. Соответствующий SQL-оператор не предусмотрен. Команда processlist отображает информацию о потоках на сервере (то есть об операторах, которые выполняются клиентами, соотнесенными с другими учетными записями). Команда k i l l удаляет все серверные потоки. Отображать или удалять собственные потоки можно всегда, но вот чтобы отобразить потоки, инициированные другими поль-
280
Глава 4. Администрирование баз данных
зователями, понадобится привилегия PROCESS, а чтобы удалить - привилегия SUPER. До версии MySQL 4.0.2, в которой была введена привилегия SUPER, за возможность как просматривать, так и удалять потоки других клиентов отвечала привилегия PROCESS. Привилегия CREATE TEMPORARY TABLES позволяет использовать ключевое слово TEMPORARY В операторах CREATE TABLE. Привилегия LOCK TABLES разрешает применение явных операторов LOCK TABLES при блокировке таблиц, для которых у вас имеется привилегия SELECT. Сюда входит использование блокировки записи, что предупреждает считывание заблокированной таблицы другим пользователем. Привилегия REPLICATION CLIENT ПОЗВОЛЯет ИСПОЛЬЗОВать SHOW MASTER STATUS И SHOW SLAVE STATUS. Привилегия REPLICATION SLAVE должна предоставляться учетным записям, которые используются подчиненными серверами, когда они подключаются к текущему серверу как к главному. Без этой привилегии подчиненный сервер не может запрашивать обновления, примененные к базам данных на главном сервере. Привилегия SHOW DATABASES разрешает учетной записи просматривать имена баз данных с помощью оператора SHOW DATABASE. Учетные записи, не имеющие данной привилегии, видят только базы данных, для доступа к которым у них есть хоть какая-нибудь привилегия, и совсем не могут использовать оператор, если сервер запускался с опцией —skip-show-database. В целом лучше всего предоставлять привилегии только тем учетным записям, которым они необходимы, но следует быть особенно осторожными при предоставлении привилегий администрирования: • Привилегия GRANT разрешает пользователями передавать свои привилегии другим пользователям. Два пользователя с разными привилегиями, получив привилегию GRANT, смогут объединить имеющиеся у них привилегии. • Привилегия ALTER может быть использована для разрушения всей системы привилегий путем переименования таблиц. • Не исключено злоупотребление привилегией FILE, когда в таблицу базы данных передаются любые файлы, которые сервер MySQL может считывать на хосте сервера. Сюда входят все общедоступные файлы и файлы из каталога данных сервера. Затем, получив доступ к этой таблице при помощи SELECT, ее содержимое можно будет перенести на хост клиента. • Не исключено злоупотребление привилегией SHUTDOWN, когда другим пользователям полностью отказывается в обслуживании путем завершения работы сервера. • Привилегия PROCESS может использоваться для просмотра нешифрованного текста выполняющихся на данный момент запросов, включая запросы, которые устанавливают или изменяют пароли. • Привилегия SUPER может быть использована для удаления других клиентов или изменения режима работы сервера. • Привилегии, предоставляемые для доступа к самой базе данных mysql, могут быть использованы для изменения паролей и другой информации, касающейся привилегий доступа. Пароли хранятся в зашифрованном виде, поэтому злоумышленник не может просто прочитать их и узнать, как они выглядят в обычном текстовом формате. Однако, пользователь, имеющий доступ для записи к столбцу
4.4. Система привилегий доступа MySQL
281
Password в таблице user, вполне может изменить пароль какой-нибудь учетной записи, а затем с помощью этой учетной записи подключиться к серверу MySQL. Для системы привилегий MySQL существуют и определенные запреты: • Нельзя явно указать, что какому-нибудь определенному пользователю в доступе должно быть отказано. Другими словами, выбрать пользователя, а затем запретить ему подключение не получится. • Нельзя указать, что пользователь имеет привилегии для создания и удаления таблиц в базе данных, но не имеет привилегий для создания и удаления самой базы данных.
4.4.4. Подключение к серверу MySQL Обычно при получении доступа к MySQL в клиентских программах указываются следующие параметры соединения: • Имя хоста, на котором работает сервер MySQL. • Ваше имя пользователя. • Ваш пароль. Например, клиент mysql можно запустить следующим образом из командной строки (обозначенной здесь через shell>): shell> mysql -h имя_хоста -и имя_пользователя -рпароль Альтернативными формами опций -h, -u и -р являются —hos 1=имя_хоста, —user= имя_пользователя и —password=napcwib. Обратите внимание на то, что пробел между -р или —password и следующим дальше паролем не допускается. Если используется опция -р или —password, но не указывается значение пароля, клиентская программа выдаст подсказку о необходимости ввода пароля. Во время ввода сам пароль не отображается. Это более безопасно, чем указывать пароль в командной строке. Любой пользователь вашей системы может увидеть указанный в командной строке пароль, выполнив команду типа auxww. См. раздел 4.5.6. Клиентские программы MySQL для любой не указываемой вами опции параметров соединения используют значения по умолчанию: • Значение по умолчанию для имени хоста - localhost. • Значение по умолчанию для имени пользователя - ODBC (в Windows) или регистрационное имя (в Unix). • Пароль не предоставляется, если отсутствует -р. Таким образом, для пользователя Unix с регистрационным именем joe все представленные ниже команды эквивалентны: shell> shell> shell> shell>
mysql -h localhost -u joe mysql -h localhost mysql -u joe mysql
Другие клиенты MySQL ведут себя аналогично. Можно задавать различные значения по умолчанию, которые будут использоваться во время установки соединения так, чтобы не приходилось вводить их в командной строке каждый раз при вызове клиентской программы, и сделать это можно двумя способами:
282
Глава 4. Администрирование баз данных
• Существует возможность задать параметры соединения в разделе [client] файла опций. Соответствующий раздел файла может выглядеть следующим образом: [client] host=ммя_хоста изег=имя_пользователя password=napcwib Файлы опций более подробно описаны в разделе 3.3.2. • Некоторые параметры соединения можно задать с помощью переменных окружения. Хост для mysql можно задать через MySQL_HOST, а имя пользователя MySQL с помощью USER (только для Windows и NetWare). Пароль может быть задан посредством MYSQLPWD, хотя это и небезопасно; см. раздел 4.5.6. Список переменных представлен в приложении Б.
4.4.5. Управление доступом, этап первый: верификация подключения При попытке подключиться к серверу MySQL сервер разрешает соединение либо отказывает в нем, основываясь на информации о вашей личности и том, можете ли вы подтвердить ее путем ввода правильного пароля. Если нет, сервер полностью отказывает вам в доступе. Если да, сервер разрешает соединение, затем инициирует этап второй и ожидает запросов. Ваша личность определяется по двум типам информации: • Хост клиента, с которого вы подключаетесь. • Ваше имя пользователя MySQL. Проверка личности выполняется с использованием информации из трех столбцов контекста в таблице user (Host, User и Password). Сервер разрешает подключение только в том случае, если значения в столбцах Host и USER таблицы user совпадают с введенными именем хоста клиента и именем пользователя и при этом клиент предоставляет пароль, указанный в столбце PASSWORD. Значения Host в таблице user могут быть заданы следующим образом: • Значение в столбце Host может соответствовать имени хоста или IP-адресу, либо же ' local host' для обозначения локального хоста. • В значениях столбца Host могут использоваться групповые символы '%' и '_'. Они имеют то же значение, что и в операциях сравнения с образцом, выполняемых оператором LIKE. Например, значение ' %' соответствует имени любого хоста, в то время как значение '%.mysql.com1 будет соответствовать имени любого хоста в домене mysql. com. • Начиная с версии MySQL 3.23, для значений Host, указанных в виде IP-адресов, можно задать сетевую маску, обозначающую число бит адреса для номера в сети, например: mysql> GRANT ALL PRIVILEGES ON db.* -> TO david@ f 192.58.197.0/255.255.255.0';
Это разрешает пользователю с именем david подключаться с любого хоста клиента с IP-адресом 1Р-адрес_клиента, для которого выполняется следующее условие: 1Р-адрес_клиента & сетевая_маска = 1Р-адрес_хоста
4.4. Система привилегий доступа MySQL
283
Таким образом, для вышеуказанного оператора GRANT: 1Р-адрес_клиента & 255.255.255.0 = 192.58.197.0 IP-адреса, которые отвечают этому условию и могут подсоединяться к серверу MySQL, находятся в диапазоне от 192.58.197.0 до 192.58.197.255. •
Пустое значение в столбце Host таблицы db означает, что предоставляемые им привилегии должны комбинироваться с привилегиями в записи таблицы host, соответствующей имени хоста клиента. Привилегии комбинируются с помощью операции AND (операции логического И), а не операции OR (операции логического ИЛИ). Более подробную информацию о таблице host можно найти в разделе 4.4.6. Пустое значение в столбце Host других таблиц привилегий будет обозначать то же, что и ' %'.
Поскольку в столбце Host могут использоваться значения группового IP-адреса (например, '144.155.166.%' для сопоставления с каждым хостом в подсети), злоумышленник может употребить это в своих целях, назвав хост 144.155.166.somewhere.com. Чтобы предупредить подобные попытки, MySQL запрещает сопоставление по именам хостов, которые начинаются с точки или цифры. Таким образом, имена хостов типа 1.2.foo.com никогда не будут сопоставляться со значениями в столбцах Host таблиц привилегий. Значению группового IP-адреса могут соответствовать только IP-адреса, но не имена хостов. В столбце User использовать групповые символы нельзя, но можно задавать пустое значение, соответствующее любому имени. Если в записи таблицы user, соответствующей входящему соединению, содержится пустое значение для имени пользователя, этот пользователь рассматривается как анонимный, не имеющий имени, а не как пользователь с именем, которое было на самом деле задано клиентом. Это означает, что пустое имя пользователя будет применяться для всех последующих проверок доступа на протяжении данного соединения (то есть во время второго этапа). Столбец Password может не содержать никакого значения (быть пустым). Это не групповой символ и вовсе не означает, что подойдет любой пароль, а только то, что пользователь должен подключаться без указания пароля. Непустые значения Password в таблице user представляют собой зашифрованные пароли. MySQL не хранит пароли в форме открытого текста, чтобы любой мог их увидеть. Наоборот, пароль, предоставляемый пользователем, который пытается подключиться к серверу, шифруется (с помощью функции PASSWORD ()). Зашифрованный пароль затем используется во время процесса подключения для проверки, является ли вводимый пароль корректным (при этом зашифрованный пароль никогда не пересылается через соединение). С точки зрения MySQL зашифрованный пароль является РЕАЛЬНЫМ, поэтому никому нельзя предоставлять к нему доступ! В частности, не разрешайте обычным пользователям доступ по чтению к таблицам в базе данных mysql! Начиная с версии 4.1, MySQL использует более сложный метод аутентификации, который обеспечивает лучшую, нежели в более ранних версиях, защиту паролей во время процесса подключения. Система остается безопасной, даже если перехвачены пакеты TCP/IP или сама база данных mysql. Шифрование паролей более подробно обсуждается в разделе 4.4.9. Приведенные в табл. 4.8 примеры иллюстрируют, как различные комбинации значений в столбцах Host и User таблицы user применяются к входящим соединениям.
Глава 4. Администрирование баз данных
284
Таблица 4.8. Примеры значений в столбцах Host и User Значение в столбце User
Значение в столбце Host
Совпавшие с записью подключения
'thomas.loc.gov'
'fred'
fred, подключающийся из thomas.loc.gov.
' thomas. loc. gov'
!
Любой пользователь, подключающийся из thomas.loc.gov.
'
' %'
' fred'
fred, подключающийся с любого хоста.
' %'
''
1
' fred'
Любой пользователь, подключающийся с любого хоста. fred, подключающийся с любого хоста в домене loc.gov. fred, подключающийся из х.у.net, х. у. com, х. у. edu и так далее (это, скорее всего, бесполезная комбинация). fred, подключающийся с хоста, IP-адрес которого выглядит как 144.155.166.177.
%. loc. gov'
'х.у.%'
'fred'
'144.155.166.177'
'fred'
'144.155.166.%'
'fred'
fred, подключающийся с любого хоста в подсети 144.155.166 класса С.
'144.155.166.0/255.255.255.0'
' fred'
To же, что и в предыдущем примере.
Вполне возможно, чтобы имя хоста клиента и имя пользователя входящего соединения соответствовали более чем одной записи в таблице user. Вышеуказанный набор примеров демонстрирует следующее: сразу несколько из представленных записей соответствуют соединению, устанавливаемому пользователем fred с thomas. loc. gov. Если соответствующих (совпадающих) записей несколько, сервер должен определять, какую из них использовать. Он разрешает эту проблему следующим образом: • Каждый раз, когда сервер считывает таблицу user, он выполняет сортировку записей. • Когда клиент пытается подключиться, сервер просматривает записи в отсортированном порядке. • Сервер использует первую запись, которая совпадает с именем хоста клиента и именем пользователя. Чтобы посмотреть, как это работает, предположим, что таблица user выглядит следующим образом: I + I I I I
Host
! User + % | root % I Jeffrey localhost | root localhost |
| + I I | I
4.4. Система привилегий доступа MySQL
285
При считывании таблицы сервер сначала упорядочивает записи с наиболее точными значениями в столбце Host. Таковыми являются буквенные имена хостов и цифровые номера IP-адресов. ' %' означает "любой хост" и является наименее точным. Записи с одинаковыми значениями в столбце Host упорядочиваются сначала по наиболее точным значениям столбца User (пустое значение в столбце User означает "любой пользователь" и является наименее точным). После сортировки представленная выше таблица будет выглядеть так: + ++ ! Host | User I ... + + +I localhost | root | ... I localhost ! | ... I % | Jeffrey | ... I % | root | ... + + +_ Когда клиент пытается подключиться, сервер просматривает отсортированные записи и использует первую подходящую. Для соединения, устанавливаемого Jeffrey из localhost, подходят стразу две записи в таблице: запись со значением 'localhost 1 в столбце Host и значением ' ' в столбце User, а также запись со значениями '%' и ' J e f f r e y ' соответственно. Первой в отсортированной таблице стоит запись 'localhost', она и будет использоваться сервером. Теперь рассмотрим другой пример. Предположим, что таблица user выглядит так: 4-
+
I Host
I User
+-
|
...
+ ++ I % I Jeffrey | ... I thomas.loc.gov | | ... + 44-После сортировки она будет выглядеть следующим образом: + ++ I Host I User I ... 4. + +| thomas.loc.gov | | ... I % I Jeffrey I ... 4. 4. 4— Для соединения, устанавливаемого Jeffrey из thomas.loc.gov, подходит первая запись, а для соединения, устанавливаемого j ef f rey из whitehouse. gov - вторая. Считается, что для данного имени пользователя, когда сервер пытается найти подходящую запись, первыми будут использоваться записи, явно хранящие имя этого пользователя. Это наиболее распространенное заблуждение. Так думать совершенно не правильно. И предыдущий пример это доказывает: первой подошедшей записью для соединения, устанавливаемого пользователем Jeffrey из thomas.loc.gov, стала не запись со значением 'Jeffrey' в столбце User, а запись, вообще не содержащая имени пользователя! В результате Jeffrey будет аутентифицирован как анонимный пользователь, хотя он и указал имя пользователя при подсоединении.
286
Глава 4. Администрирование баз данных
Если подключиться удается, но привилегии не соответствуют ожидаемым, возможно, вы аутентифицированы как какой-то другой пользователь. Чтобы узнать, какую учетную запись использовал сервер для вашей аутентификации, воспользуйтесь функцией CURRENT_USER (). Она возвратит значение в формате имя_пользователя®имя_хоста, означающем значения в столбцах User и Host из выбранной записи в таблице user. Предположим, что Jeffrey подключается и отправляет следующий запрос: mysql> SELECT CURRENTJJSER(); + + 1 CURRENTJJSER () |
•f I @localhost +
+ | +
Представленный здесь результат показывает, что выбранная в качестве подходящей запись в таблице user имеет пустое значение в столбце User. Другими словами, сервер воспринимает Jeffrey как анонимного пользователя. Функция CURRENTJJSER () доступна, начиная с версии MySQL 4.O.6. Также для диагностики проблем с аутентификацией можно сделать следующее: выведите таблицу user и проведите сортировку вручную, чтобы увидеть, где было установлено первое совпадение.
4.4.6. Управление доступом, этап второй: верификация запросов После того как соединение установлено, сервер переходит ко второму этапу управления доступом. Для каждого поступающего через данное соединение запроса сервер определяет, какую вы хотите выполнить операцию и затем проверяет, достаточно ли у вас для этого привилегий. Здесь свою роль начинают играть столбцы привилегий в таблицах привилегий. Привилегии могут браться из любой таблицы user, db, host, t a b l e s p r i v или columnspriv. (В разделе 4.4.2 дается перечень столбцов каждой из таких таблиц.) Таблица user предоставляет привилегии, назначенные вам по глобальному принципу и применяемые независимо от текущей базы данных. Например, если таблица user предоставляет привилегию DELETE, вы сможете удалять строки из любой таблицы любой базы данных на хосте сервера! Другими словами, привилегии в таблице user являются привилегиями суперпользователя. Разумнее всего предоставлять привилегии в таблице user только суперпользователям, таким как администраторы баз данных. Что касается остальных пользователей, для них в качестве привилегий в таблице user следует оставлять значение ( N' и предоставлять привилегии только на более конкретных уровнях. Можно предоставлять привилегии для определенных баз данных, таблиц или столбцов. Таблицы db и host предоставляют привилегии на уровне базы данных. Значения в столбцах контекста этих таблиц могут принимать следующие формы: • Групповые символы Т и ' _ ' могут использоваться в столбцах Host и DB любой из этих таблиц. Они имеют то же значение, что и для операций сравнения с образцом, выполняемых оператором LIKE. Если вы хотите использовать любой из этих символов буквально при предоставлении привилегий, его следует отменить с помощью обратной косой черты. Например, чтобы включить символ '_' в качестве части имени базы данных, укажите его как '\_' в операторе GRANT.
4.4. Система привилегий доступа MySQL
287
• Значение '%' в столбце Host таблицы db означает "любой хост". Пустое значение в столбце Host таблицы db означает "для дополнительной информации просматривать таблицу host" (этот процесс описывается чуть ниже в данном разделе). • Пустое значение или значение '%' в столбце Host таблицы host означает "любой хост". • Пустое значение или значение '%' в столбце Db любой из таблиц означает "любая база данных". • Пустое значение в столбце User любой из таблиц соответствует анонимному пользователю. Сервер считывает и сортирует таблицы host и db, одновременно считывая таблицу user. Сервер выполняет сортировку таблицы db по столбцам контекста Host, Db и User и сортировку таблицы host по столбцам Host и Db. Как и в случае с таблицей user, во время сортировки первыми размещаются наиболее точные значения, а последними наименее точные, и при поиске подходящих записей сервер использует первую совпавшую из числа найденных. Таблицы tables_priv и columns_priv предоставляют привилегии на уровне таблиц и столбцов. Значения в столбцах контекста этих таблиц могут принимать следующие формы: • Групповые символы '%' и '_' могут использоваться в столбце Host любой из этих таблиц. Они имеют то же значение, что и для операций сравнения с образцом, выполняемых оператором LIKE. • Пустое значение или значение ' %' в любой из таблиц означает "любой хост". • Столбцы Db, Table_name и Column_name не могут содержать групповых символов или пустых значений в любой из таблиц. Сервер выполняет сортировку таблиц tables_priv и columns_priv по столбцам Host, Db и User. Она подобна сортировке в таблице db, но намного проще, поскольку только в столбце Host могут содержаться групповые символы. Далее описывается процесс верификации запросов. (Если вы знакомы с исходным кодом проверки доступа, заметить, что предлагаемое здесь описание несколько отличается от используемого в коде алгоритма, будет нетрудно. Описание соответствует тому, что на самом деле делает код и дается по-другому только с целью упростить объяснение происходящего процесса.) Для запросов, требующих наличия административных привилегий, таких как SHUTDOWN или RELOAD, сервер проверяет только запись в таблице user, поскольку только в этой таблице задаются привилегии для администрирования. Доступ предоставляется, если данная запись разрешает запрашиваемую операцию, в противном случае в доступе будет отказано. Например, если вы хотите выполнить mysqladmin shutdown, но ваша запись в таблице user не предоставляет привилегии SHUTDOWN, сервер откажет в доступе даже без проверки таблиц db или host. (Они не содержат столбца Shutdown_priv, поэтому проверять их нет необходимости.) Что касается связанных с базами данных запросов (INSERT, UPDATE и так далее), сервер, прежде всего, проверит глобальные привилегии (то есть привилегии суперпользователя) путем просмотра записей в таблице user. Если соответствующая запись разрешает запрашиваемую операцию, доступ будет предоставлен. Если же глобальных привилегий
288
Глава 4. Администрирование баз данных
в таблице user недостаточно, сервер перейдет к определению привилегий пользователя на уровне баз данных, проверяя таблицы db и host: 1. Сервер ищет в таблице db запись с подходящими значениями в столбцах Host, Db и User. Значения в столбцах Host и User сопоставляются с именем хоста и именем пользователя MySQL, а значение в столбце Db - с именем базы данных, к которой пользователь желает получить доступ. Если запись с соответствующими значениями в столбцах Host и User отсутствует, в доступе будет отказано. 2. Если же имеется соответствующая запись в таблице db и значение в столбце Host не является пустым, эта запись определяет привилегии пользователя на уровне базы данных. 3. Если же значение в столбце Host таблицы db пустое, это означает, что в таблице host перечислены все хосты, которым должен быть разрешен доступ к базе данных. В таком случае дальнейший поиск подходящих значений в столбцах Host и Db будет выполняться по таблице host. Если совпадения в таблице host не найдены, в доступе будет отказано. В противном случае привилегии пользователя на уровне баз данных вычисляются через операцию логического умножения (а не логического сложения!) привилегий из записей в таблицах db и host, то есть это будут привилегии со значением 'Y1 в обеих записях. (Таким способом можно сначала предоставлять общие привилегии в записи таблицы db, а затем ограничивать их для каждого хоста отдельно через записи в таблице host.) Определив привилегии на уровне базы данных, предоставляемые записями в таблицах db и host, сервер добавляет их к глобальным привилегиям, предоставленным в таблице user. Если получившийся результат разрешает выполнение запрашиваемой операции, доступ будет предоставлен. В противном случае сервер поочередно проверяет привилегии пользователя на уровне таблиц и столбцов в таблицах tables_priv и colurans_priv, добавляет их к остальным привилегиям пользователя и, в зависимости от получившегося результата, либо разрешает, либо запрещает доступ. На языке булевской логики приведенное выше описание вычисления привилегий пользователя будет выглядеть так: глобальные привилегии OR {привилегии базы данных AND привилегии хоста) OR привилегии таблицы OR привилегии столбца Если изначально определено, что глобальных привилегий в записи таблицы user не достаточно для выполнения запрашиваемой операции, причина, по которой сервер затем начинает добавлять их к привилегиям на уровне баз данных, таблиц и столбцов, не вполне очевидна. А заключается она в том, что данный запрос может требовать наличия более чем одного типа привилегий. Например, чтобы выполнить оператор INSERT INTO.. .SELECT, понадобятся привилегии INSERT и SELECT. Одна из них может предоставляться записью в таблице user, а другая в это же время - записью в таблице db. В таком случае имеются все необходимые для выполнения запроса привилегии, но сервер не может знать об этом, проверив только одну из таблиц, ему необходимо скомбинировать привилегии, предоставляемые записями в обеих таблицах. Операторы GRANT и REVOKE никак не действуют на таблицу host, поэтому она и не используется в большинстве установок MySQL. При внесении изменений непосредствен-
4.4. Система привилегий доступа MySQL
289
но, ее можно будет использовать и для специальных целей, как, например, для поддержки списка защищенных серверов. Так, в ТсХ таблица host содержит список всех машин локальной сети. Им предоставлены все привилегии. Также таблицу host можно использовать для указания небезопасных хостов. Предположим, машина public.your.domain находится в общедоступной области, которую вы не считаете безопасной. С помощью записей в таблице host, подобным тем, которые представлены ниже, появляется возможность разрешить доступ абсолютно всем хостам, кроме именно этой небезопасной машины: I Host | Db | . . . + + +I public.your.domain | % I . . . (все привилегии установлены в ' N') I %. your, domain | % I . . . (все привилегии установлены в ' Y') Естественно, всегда следует тестировать записи в таблицах привилегий (например, с помощью SHOW GRANTS или mysqlaccess), дабы убедиться в том, что привилегии доступа установлены именно так, как вы думаете.
4.4.7. Когда изменения в привилегиях вступают в силу При запуске mysqld содержимое всех таблиц привилегий считывается и заносится в память, с этого момента все привилегии вступают в силу и управляют доступом к серверу. Когда сервер загружает таблицы привилегий повторно, это отражается на привилегиях для существующих клиентских соединений следующим образом: • Изменения в привилегиях на уровне таблиц и столбцов вступают в силу при следующем запросе клиента. • Изменения на уровне баз данных вступают в силу при следующем использовании оператора USE имя_базы_данных. • Изменения в глобальных привилегиях и паролях вступают в силу при следующем подключении клиента. Если изменения вносятся в таблицы привилегий с помощью GRANT, REVOKE или SET PASSWORD, сервер замечает их и незамедлительно снова перезагружает таблицы в память. Если изменения вносятся непосредственно, с помощью операторов INSERT, UPDATE или DELETE, они вступают в силу только после перезапуска сервера или только тогда, когда серверу будет указано, что таблицы должны быть перезагружены. Чтобы перезагрузить таблицы привилегий вручную, используйте оператор FLUSH PRIVILEGES либо команду mysqladmin flush-privileges или mysqladmin reload. Если внести изменения непосредственно, но не перезагрузить таблицы привилегий, изменения вступят в силу только после перезапуска сервера, так что не удивляйтесь, если сразу не увидите результата своих действий!
4.4.8. Причины появления ошибок отказа в доступе (Access denied) Если при попытке подключиться к серверу MySQL возникают проблемы, воспользуйтесь представленным ниже списком действий, которые можно предпринять для их решения:
290
Глава 4. Администрирование баз данных
• Убедитесь, что сервер функционирует. Если это не так, подключиться к нему нельзя. Например, причиной того, что при попытке подсоединиться к серверу появляется одно из следующих сообщений, может быть именно отсутствие активности сервера: shell> mysql ERROR 2003: Can't connect to MySQL server on 'host_name' (111) shell> mysql ERROR 2002: Can't connect to local MySQL server through socket '/tmp/mysql.sock1 (111) Еще одной причиной этому может служить то, что сервер работает, но при попытке подключиться используются TCP/IP-порт, именованный канал или файл сокета Unix, отличные от тех, которые прослушиваются сервером. Чтобы исправить такую ошибку, при вызове клиентской программы задайте опцию —port и укажите корректный порт, или опцию -socket и задайте правильный именованный канал или сокет Unix. • Таблицы привилегий должны быть корректно установлены, так чтобы сервер мог использовать их для управления доступом. При установке MySQL из бинарного дистрибутива в Windows или дистрибутива RPM в Linux, во время процесса установки создается база данных mysql, содержащая таблицы привилегий. При других типах установки MySQL создавать таблицы привилегий необходимо вручную, запустив сценарий mysql_install_db. См. раздел 2.4.2. Единственный способ определить, есть ли необходимость в инициализации таблиц привилегий, это проверить наличие каталога mysql в каталоге данных. (Каталог данных обычно имеет имя data или var и находится в каталоге установки MySQL). Убедитесь, что в каталоге баз данных mysql присутствует файл с именем user.MYD. Если его там нет, запустите сценарий mysql_install_db. После запуска сценария и сервера протестируйте исходные привилегии с помощью следующей команды: shell> mysql -u root test Подключение к серверу должно пройти без ошибок. • После новой установки необходимо подключиться к серверу, установить пользователей и права доступа для них. shell> mysql -u root mysql Сервер должен разрешить подсоединение, поскольку первоначально MySQLпользователь root не имеет пароля. Но это также представляет определенный риск для безопасности системы, поэтому во время настройки учетных записей других пользователей MySQL следует позаботиться и об установке пароля для учетной записи root. Информацию по установке исходных паролей можно найти в разделе 2.4.5. • Запускался ли сценарий mysql_f ix_privilege_tables после того, как была проведена модернизация существующей установки MySQL до более новой версии? Если нет, это необходимо сделать. Структура таблиц привилегий порой изменяется, когда добавляются новые функциональные возможности, поэтому после модернизации следует обязательно убедиться, что ваши таблицы имеют актуальную структуру. Для более подробной информации см. раздел 2.5.8.
4.4. Система привилегий доступа MySQL
291
• Если клиентская программа получает следующее сообщение об ошибке при попытке подсоединения к серверу, это значит, что сервер ожидает ввода паролей более нового, нежели доступен клиенту, формата: shell> mysql Client does not support authentication protocol requested by server; consider upgrading MySQL client Информация о том, что можно сделать в таких случаях, находится в разделах 4.4.9 иА.2.3. • Если при попытке подключиться к серверу в качестве привилегированного (root) пользователя, вы получаете следующую ошибку, это значит, что в таблице user нет записи со значением 'root 1 в столбце User, и сервер не может преобразовать имя хоста для вашего клиента: Access denied for user: lf@'unknown' to database mysql В таком случае потребуется перезапустить сервер с опцией —skip-grant-tables и отредактировать файл /etc/hosts или \windows\hosts, добавив в него запись для вашего хоста. • Не забывайте о том, что клиентские программы будут использовать параметры соединения, заданные в файлах опций или переменных окружения. Если отправляемые клиентской программой параметры соединения по умолчанию (когда в командной строке они не указываются) кажутся неверными, проверьте файлы конфигурации и все остальные используемые файлы опций. Например, если при запуске сервера без опций, вы получаете ошибку Access denied ("В доступе отказано"), убедитесь, что ни в одном из файлов опций не был указан старый пароль! Можно отменить использование файлов опций через клиентскую программу, вызвав ее с опцией --no-defaults, например: shell> mysqladmin —no-defaults -u root version Используемые клиентами файлы опций перечислены в разделе 3.3.2. Переменные окружения представлены в приложении Б. • Если вы получаете следующую ошибку, это означает, что используется некорректный пароль для root: shell> mysqladmin -u root -pxxxx ver Access denied for user: 'root'@'localhost'
(Using password: YES)
Если подобная ошибка появляется даже тогда, когда пароль не был задан, это значит, что в одном из файлов опций указан некорректный пароль. Попробуйте воспользоваться опцией --no-defaults, как описано в предыдущем пункте. Информация об изменении паролей находится в разделе 4.5.5. Если Вы забыли или потеряли пароль для root, можете перезапустить mysqld с опцией —skipgrant-tables, чтобы изменить пароль. См. раздел А.4.1. • При изменении пароля посредством SET PASSWORD, INSERT или UPDATE необходимо его зашифровать с использованием функции PASSWORD(). Если для указанных операторов не использовать функцию PASSWORD(), пароль работать не будет. Например, следующий оператор устанавливает пароль, но не шифрует его, поэтому впоследствии пользователь подключиться к серверу не сможет:
292
Глава 4. Администрирование баз данных 1
mysql> SET PASSWORD FOR ' a b e ' @ ' и м я _ х о с т а ' = ' e a g l e ;
Вместо этого пароль нужно устанавливать так: mysql> SET PASSWORD FOR 'abe'@'имя_хоста' = PASSWORD('eagle'); При задании пароля с помощью оператора GRANT или команды mysqladmin password указывать функцию PASSWORD не обязательно, поскольку в таком случае она используется для шифрования пароля автоматически. См. раздел 4.5.5. •
localhost является синонимом имени вашего локального хоста, а также используемым по умолчанию именем хоста, к которому будут пытаться подключиться клиенты, если хост явно задан не был. Однако соединения с localhost в системах Unix работать не будут, если используется версия MySQL, предшествующая 3.23.27, и потоки MIT-pthreads: соединения с localhost устанавливаются с помощью файлов сокетов Unix, которые в то время потоки MIT-pthreads не поддерживали. Во избежание этой проблемы на таких системах с помощью опции --host= 127.0.0.1 явно задавайте имя хоста. В результате будет установлено TCP/IPсоединение с локальным сервером mysqld. Установить TCP/IP-соединение можно и с помощью опции —host, в которой необходимо указать реальное имя локального хоста. В этом случае имя хоста должно быть задано в записи таблицы user на хосте сервера, даже если клиентская программа и сервер запускаются на одном и том же хосте.
• Если ошибка Access denied возникает, когда вы подключаетесь к базе данных с помощью mysql -u имя_пользователя, скорее всего, проблема заключается в таблице user. Проверить это можно с помощью команды mysql -u root mysql ИЛИ следующего SQL-оператора: mysql> SELECT * FROM user; Результат должен включать запись, значения в столбцах Host и User которой соответствуют имени хоста вашего компьютера и вашему имени пользователя MySQL. • Сообщение об ошибке Access denied будет содержать следующую информацию: под каким именем вы пытаетесь войти в систему, имя хоста клиента, с которого вы пытаетесь подсоединиться, и вводился ли вами пароль. Обычно в таблице user должна присутствовать только одна запись, в точности соответствующая имени хоста и имени пользователя, которые указаны в сообщении об ошибке. Например, "Using password: NO" в сообщении об ошибке будет означать, что вы пытались войти в систему без указания пароля. • Если при попытке подключиться с другого, не того, на котором работает сервер MySQL, хоста возникает приведенная ниже ошибка, это значит, что в таблице user отсутствует строка со значением в столбце Host, которое соответствует имени хоста клиента. Host . . . is not allowed to connect to this MySQL server Хосту . . . не разрешено подключаться к этому серверу MySQL
Устранить эту проблему можно путем установки для учетной записи комбинации из числа используемых для подключения имени клиентского хоста и имени пользователя.
4.4. Система привилегий доступа MySQL
293
Если IP-адрес или имя хоста машины, к которой выполняется подключение, не известно, в таблицу user необходимо добавить запись со значением ' % ' в столбце Host и перезапустить mysqld с опцией -log на машине сервера. После подключения с клиентской машины в журнале регистрации MySQL будет содержаться информация об этом самом подключении. (Затем потребуется заменить значение ' %' в записи таблицы user на реальное имя хоста, появившееся в журнале. В противном случае ваша система не будет безопасной, поскольку что она разрешает соединения с любого хоста для данного имени пользователя.) В среде Linux еще одна причина возникновения такой ошибки может заключаться и в том, что бинарная версия MySQL скомпилирована с другой, а не той, что используется, версией библиотеки glibc. В таком случае потребуется либо обновить версию операционной системы, либо версию glibc, или же загрузить исходный дистрибутив версии MySQL и скомпилировать его самостоятельно. Обычно установить и скомпилировать исходный RPM-модуль также не составляет особого труда, поэтому серьезной проблемой это не является. • Если при попытке подключиться вы указываете имя хоста, но получаете сообщение об ошибке, где имя хоста не отображено или представляет собой IP-адрес, это значит, что ошибка возникла, когда MySQL пытался преобразовать IP-адрес в имя клиентского хоста: shell> mysqladmin -u root -pxxxx -h some-hostname ver Access denied for user: ' r o o t ' G 1 1 (Using password: YES) Это говорит о проблеме с системой DNS. Для разрешения этой проблемы понадобится выполнить mysqladmin flush-hosts, чтобы сбросить внутренний кэш имен хостов DNS. См. раздел 6.5.5. Ниже представлены основные варианты решения этой проблемы: •
Попробуйте выяснить, что именно не так с сервером DNS, и устранить проблему. • В таблицах привилегий MySQL лучше указывать IP-адреса, а не имена хостов. • Добавьте запись для имени машины клиента в каталог /etc/hosts. •
Запустите mysqld с опцией --skip-name-resolve.
•
Запустите mysqld с опцией —skip-host-cache.
• В среде Unix, если сервер и клиент работают на одной и той же машине, подключайтесь к localhost. Для таких соединений используется файл сокета Unix, а не TCP/IP. • В среде Windows, если сервер и клиент работают на одной и той же машине, а также если сервер поддерживает соединения через именованные каналы, подключайтесь через имя хоста . (точка). Такие соединения используют именованные каналы, а не TCP/IP. • Если mysql -u root t e s t работает, а вот при выполнении mysql -h имя_хоста -u root (где имя_хоста - это реальное имя локального хоста) возникает ошибка Access denied, возможно, в таблице user неправильно указано имя вашего хоста. Основная проблема здесь заключается в том, что значение в столбце Host таблицы user соответствует неуточненному имени хоста, в то время как операции преобразования имен, выполняемые вашей системой, возвращают полностью уточ-
294
Глава 4. Администрирование баз данных ненное имя домена (или наоборот). Например, если в таблице user имеется запись со значением ' tcx 1 в качестве имени хоста, но система DNS передает MySQL имя хоста ' tcx. subnet. se', эта запись работать не будет. Попробуйте добавить в таблицу user запись, в которой для имени хоста в столбце Host указан IP-адрес. (Или же в таблицу user можно добавить запись, значение в столбце Host которой будет содержать групповой символ, например, 'tcx.% 1 . Однако, использовать имена хостов, заканчивающиеся на '%', небезопасно, и поэтому не рекомендуется.)
• Если команда mysql -u имя_пользователя t e s t работает, а команда mysql -и имя_пользователя имя_другой_базы_данных - нет, значит, данному пользователю не был предоставлен доступ к базе данных имя_другой_базы_данных. • Если команда mysql -u имя_пользователя на хосте сервера работает, а на удаленном хосте клиента нет, значит, для данного имени пользователя не был разрешен доступ к серверу с удаленного хоста. • Если причину появления ошибки Access denied выяснить никак не получается, удалите из таблицы user все записи со значениями в столбце Host, содержащими групповые символы (т.е. '%' или '_'). Наиболее распространенная ошибка состоит в том, что после вставки новой записи со значением '%' в столбце Host и 'пользователь' в столбце User пользователь считает, что это позволит ему задавать localhost для подключения с той же машины. Это не так, потому что привилегии по умолчанию включают запись со значением 'localhost' в столбце Host и значением ' ' в столбце User. Поскольку значение localhost является более точным, чем '%', то именно запись с таким значением, а не добавленная новая запись будет использоваться при подключении к localhost! Правильным будет добавить еще одну запись со значениями 'localhost' в столбце Host и 'пользователь' в столбце User, или же вообще удалить запись со значением 'localhost' в столбце Host и значением ' ' в столбце User. После удаления не забудьте выполнить оператор FLUSH PRIVILEGES, чтобы перезагрузить таблицы привилегий. • Если возникает следующая ошибка, возможно имеют место проблемы с таблицей db или таблицей host: Access to database denied В доступе к базе данных отказано Если выбранная из таблицы db запись содержит пустое значение в столбце Host, убедитесь, что в таблице host имеется, по крайней мере, одна или несколько соответствующих записей, указывающих, к каким хостам относится запись из таблицы db. • Если вы подключаетесь к серверу MySQL без проблем, но сообщение Access denied появляется каждый раз, когда используются операторы SELECT.. .INTO OUTFILE и LOAD DATA INFILE, значит, ваша запись в таблице user не имеет привилегии FILE. • Если изменения вносятся в таблицы привилегий непосредственно (с помощью операторов INSERT, UPDATE и DELETE) и при этом вроде как игнорируются, не забудьте о том, что необходимо выполнить оператор FLUSH PRIVILEGES или же команду flush-privileges, чтобы сервер осуществил повторное считывание таблиц привилегий. В противном случае изменения вступят в силу только после переза-
4.4. Система привилегий доступа MySQL
295
пуска сервера. Также помните, что после изменения пароля для root с помощью команды UPDATE задавать новый пароль до тех пор, пока не будет очищен список привилегий, не нужно, поскольку до этого времени сервер не будет знать о том, что пароль был изменен. • Если вам кажется, что ваши привилегии изменились непосредственно во время сеанса, скорее всего, их изменил администратор MySQL. Перезагрузка таблиц привилегий отразится не только на соединениях клиентов, но и на существующих соединениях, как описано в разделе 4.4.7. •
Если возникают проблемы с доступом при использовании программ Perl, PHP, Python или ODBC, попробуйте подсоединиться к серверу через mysql -u имя_пользователя имя_базы_данных ИЛИ mysql -и имя_пользователя -рпароль имя_базы_данных. Если установить соединение с помощью клиента mysql удается, значит, проблема связана с вашей программой, а не с привилегиями доступа. (Пробел между -р и паролем не ставится; для задания пароля можно также использовать синтаксис —passworс1=пароль. Если применяется только опция -р, MySQL запросит ввод пароля.)
• Для целей тестирования запустите сервер mysqld с опцией --skip-grant-tables. В этом случае можно будет внести изменения в таблицы привилегий MySQL и воспользоваться сценарием mysqlaccess, чтобы проверить, приводят ли они к ожидаемым результатам. Если результаты изменений удовлетворительные, выполните команду mysqladmin flush-privileges, чтобы сервер начал использовать новые таблицы привилегий. (Перезагрузка таблиц привилегий перекрывает опцию —skip-grant-tables, что позволяет заставить сервер начать снова использовать таблицы привилегий без остановки его работы и перезапуска.) • Если ничего не получается, запустите сервер mysqld с опцией отладки (например, —debug=d,general,query). Будут выведены данные хоста и пользователя о неудачных попытках соединения с сервером, а также информация о каждой команде, которая была использована. • При наличии любых других проблем с таблицами привилегий MySQL, которые, по вашему мнению, необходимо передать в список рассылки, всегда предоставляйте дамп таблиц привилегий MySQL. Получить такие данные можно с помощью команды mysqldump mysql, а отправить отчет о проблеме - с помощью сценария mysqlbug. См. раздел 1.7.1.3. В некоторых случаях для выполнения mysqldump может понадобиться перезапустить сервер.
4.4.9 Хеширование паролей в MySQL 4.1 Все учетные записи пользователей MySQL представлены в таблице user базы данных mysql. Для каждой из них назначен пароль, однако в столбце Password таблицы User хранится не пароль в виде открытого текста, а его хеш-значение. Хеш-значения паролей вычисляются с помощью функции PASSWORD (). MySQL использует пароли на двух этапах клиент-серверного взаимодействия: • Когда клиент пытается подключиться к серверу, он проходит первую стадию аутентификации, когда он должен ввести пароль, хеш-значение которого соответствует хеш-значению из таблицы user для выбранной клиентом учетной записи.
Глава 4. Администрирование баз данных
296 •
После подключения клиент, имея достаточно привилегий, может устанавливать или изменять хеш-значения паролей для учетных записей, представленных в таблице user. И делать он это может с помощью функции PASSWORD (), чтобы генерировать хеш-значение пароля, или с помощью операторов GRANT или SET PASSWORD.
Другими словами, сервер использует хеш-значения во время аутентификации, когда клиент сначала только пытается подключиться. Сервер генерирует хеш-значения, если уже подключившийся клиент вызывает функцию PASSWORD () или использует операторы GRANT или SET PASSWORD, чтобы установить или изменить пароль. Алгоритм хеширования паролей в MySQL 4.1 был усовершенствован с целью обеспечения более высокой степени безопасности и сокращения риска перехвата паролей. Однако работать с ним могут только клиенты и сервер версии 4.1, что приводит к возникновению ряда проблем с совместимостью. Клиент, использующий версию 4.1, может подключаться к серверу более ранней версии (до 4.1), поскольку клиент понимает как старые, так и новые алгоритмы хеширования паролей. А вот клиент, использующий версию, предшествующую 4.1, может столкнуться с трудностями при подключении к серверу версии 4.1. Например, клиент mysql версии 4.0 при попытке подсоединиться к серверу версии 4.1 может получить следующее сообщение об ошибке:
shell> mysql -h localhost -u root Client does not support authentication protocol requested by server; consider upgrading MySQL client Клиент не поддерживает протокол аутентификации, требуемый сервером; рекомендуется обновление версии клиента MySQL
Ниже предлагается описание различий между старым и новым алгоритмом паролей и что нужно делать, если выполняется модернизация сервера до версии 4.1 и при этом необходима поддержка обратной совместимости с клиентами, использующими более ранние (до 4.1) версии. Дополнительную информацию можно найти в разделе А.2.3. ;
На заметку!
В этом описании сопоставляются процессы хеширования паролей в версии 4.1 с процессами в { версиях, предшествующих 4.1, но фактически здесь уже подразумевается версия 4.1.1. Версию ' ' MySQL 4.1.0 можно назвать "лишней", поскольку используемый в ней алгоритм совсем незначи\ тельно отличается от алгоритма в версиях 4.1.1 и выше. Отличия версии 4.1.0 от более ранних '(' версий более подробно описаны в разделе 4.4.9.2. В версиях, предшествующих MySQL 4.1, хеш-значения паролей, вычисляемые с помощью функции PASSWORD (), имеют длину 16 байт и выглядят приблизительно так: mysql> SELECT PASSWORD('mypass'); PASSWORD('mypass') | + 6f8cll4b58f2ce9e |
Столбец Password таблицы user (в котором хранятся эти хеш-значения) в версиях до MySQL 4.1 также имеет длину 16 байт. Начиная с MySQL 4.1, функция PASSWORD () изменена и выдает более длинное хешзначение, длина которого составляет 41 байт:
4.4. Система привилегий доступа MySQL
297
mysql> SELECT PASSWORD('mypass'); +
I PASSWORD!'mypass1)
+
|
I *43c8aa34cdc98eddd3delfe9a9c2c2a9f92bb2098d75 | +
+
Соответственно, длина столбца Password таблицы user также должна равняться 41 байту, чтобы можно было хранить такие значения: • Если устанавливается новая версия, MySQL 4.1, длина столбца Password составит 41 байт автоматически. • Если проводилась модернизация с более старой версии MySQL до версии 4.1, необходимо запустить сценарий mysql_fix_privilege_tables, чтобы увеличить длину столбца Password с 16 до 41 байта. (Сценарий не изменяет существующие значения паролей, длина которых по-прежнему будет составлять 16 байт.) Расширенный столбец Password может хранить хеш-значения паролей как старого, так и нового формата. Формат любого хеш-значения можно определить двумя способами: • Явный отличительный признак - это длина хеш-значения (16 байт или 41 байт). • Второй отличительный признак: хеш-значения паролей в новом формате всегда начинаются с символа '*', в то время как хеш-значения в старом формате - никогда. Более длинный формат хеш-значений паролей обладает лучшими криптографическими свойствами, и аутентификация клиента по более длинным хеш-значениям безопаснее, чем аутентификация, во время которой используются старые короткие хешзначения. Различия между короткими и длинными хеш-значениями паролей имеют непосредственное отношение и к тому, как сервер будет использовать пароли во время аутентификации, и к тому, как он будет генерировать хеш-значения паролей для уже подключившихся клиентов, которые выполняют операции замены паролей. То, как сервер будет использовать хеш-значения паролей во время аутентификации, зависит от размера столбца Password: • Если столбец небольшой (короткий), будет использоваться только аутентификация по коротким хеш-значениям. • Если столбец большой (длинный), он может вмещать как короткие, так и длинные хеш-значения, поэтому сервер может использовать любой формат: • Клиенты, использующие версию, предшествующую 4.1, смогут подключаться к серверу, однако поскольку им знаком только старый алгоритм, аутентификация будет возможна только для учетных записей с короткими хеш-значениями паролей. • Клиенты, использующие версию 4.1, могут проводить аутентификацию для учетных записей как с короткими, так и с длинными хеш-значениями. Что касается учетных записей с короткими хеш-значениями, процесс аутентификации фактически немного более безопасен для клиентов версии 4.1, чем для клиентов более старых версий. В целом, степень безопасности при аутентификации тех или иных клиентов представлена ниже, в порядке возрастания: • Клиенты версий, предшествующих 4.1, выполняющие аутентификацию для учетных записей с короткими хеш-значениями паролей.
298
Глава 4. Администрирование баз данных
•
Клиенты версии 4.1, выполняющие аутентификацию для учетных записей с короткими хеш-значениями паролей.
•
Клиенты версии 4.1, выполняющие аутентификацию для учетных записей с длинными хеш-значениями паролей.
То, как сервер генерирует хеш-значения паролей для уже подключившихся клиентов, зависит от размера столбца Password и опции —old-passwords. Сервер версии 4.1 генерирует длинные хеш-хначения, только если выполнены следующие условия: размер столбца Password достаточно большой, чтобы вместить длинные значения, и опция —old-password не использовалась. Эти условия проверяются следующим образом: •
Размер столбца Password должен быть достаточно большим, чтобы вмещать длинные хеш-значения (41 байт). Если размер столбца не изменен и по-прежнему равен 16 байтам (это размер столбца в версиях ниже, чем 4.1.), сервер видит, что длинные значения в столбце не помещаются, и когда клиент выполняет операции по изменению пароля с помощью функции PASSWORD () или операторов GRANT и SET PASSWORD, он генерирует только короткие хеш-значения. Такое случается, если вы провели модернизацию до версии 4.1, но еще не запускали сценарий mysql_f ix_privilege_tables, который увеличивает размер столбца Password.
•
Большой размер столбца Password позволяет хранить как короткие, так и длинные хеш-значения. В этом случае при использовании функции PASSWORD () или операторов GRANT и SET PASSWORD будут генерироваться длинные хеш-значения, если только сервер не был запущен с опцией --old-passwords, которая вместо этого заставляет сервер генерировать короткие хеш-значения паролей.
Опция —old-passwords предназначена для поддержки обратной совместимости с клиентами, использующими версии ниже 4.1, в тех случаях, когда иначе сервер генерировал бы длинные хеш-значения паролей. Данная опция не влияет на аутентификацию (клиенты версии 4.1 по-прежнему могут использовать учетные записи с длинными хешзначениями паролей), но она запрещает создавать длинные хеш-значения в таблице user при операциях по изменению паролей. Случись такое, клиенты версии ниже 4.1 не смогли бы больше использовать такую учетную запись. Если опция —old-passwords не указывается, возможен следующий нежелательный сценарий: •
Клиент старой версии подключается к учетной записи с коротким хеш-значением пароля.
•
Клиент изменяет свой пароль. Если опция --old-passwords не используется, это приводит к появлению у учетной записи длинного хеш-значения пароля.
•
Когда клиент старой версии в следующий раз попытается подключиться к учетной записи, он этого сделать не сможет, потому что теперь учетная запись имеет длинное хеш-значение пароля, требующее во время аутентификации применения нового алгоритма хеширования. (Как только у учетной записи появляется длинное хеш-значение пароля, пытаться получить доступ к ней смогут только клиенты версии 4.1, поскольку клиенты более ранних версий не распознают хеш-значений, которые являются длинными.)
Данный сценарий иллюстрирует, что при необходимости в поддержке клиентов старых (до 4.1) версий, опасно запускать сервер версии 4.1 без опции —old-passwords. При запуске сервера с опцией --old-passwords операции по изменению пароля не будут генерировать длинные хеш-значения паролей и, таким образом, не приведут к тому, что
4.4. Система привилегий доступа MySQL
299
учетные записи станут недоступными для клиентов старых версий. (Такие клиенты не смогут случайно сами себя заблокировать, изменив пароль и, тем самым, получив длинные хеш-значения.) Недостатком применения опции —old-passwords является то, что любые создаваемые или изменяемые вами пароли будут использовать только короткие хеш-значения (это касается даже клиентов версии 4.1). Таким образом, дополнительная степень безопасности, предоставляемая длинными хеш-значениями паролей, теряется. Если требуется создать учетную запись с длинным хеш-значением, (например, для использования клиентами версии 4.1), это следует делать тогда, когда сервер запускается без опции —old-passwords. При работе с сервером версии 4.1 возможны следующие сценарии: Сценарий 1. Размер столбца Password в таблице user маленький. • В столбце Password могут храниться только короткие хеш-значения. • Во время аутентификации клиента сервер использует только короткие хешзначения. •
Уже подключившиеся клиенты в операциях по генерированию хеш-значений паролей с применением PASSWORD(), GRANT или SET PASSWORD смогут использовать исключительно короткие хеш-значения. При любом изменении в пароле учетной записи ее хеш-значение пароля все равно будет коротким.
•
Использовать опцию —old-password можно, но не нужно, поскольку если размер столбца Password маленький, сервер в любом случае будет автоматически генерировать только короткие хеш-значения паролей.
Сценарий 2. Размер столбца Password большой; сервер запускался без опции —old-password. •
В столбце Password могут храниться как короткие, так и длинные хеш-значения.
• Клиенты версии 4.1 могут проводить аутентификацию для учетных записей как с короткими, так и с длинными хеш-значениями. •
Клиенты старых (до 4.1) версий могут проводить аутентификацию только для учетных записей с короткими хеш-значениями.
•
Уже подключившиеся клиенты в операциях по генерированию хеш-значений паролей с применением PASSWORD!), GRANT или SET PASSWORD смогут использовать исключительно длинные хеш-значения. При любом изменении в пароле учетной записи ее хеш-значение пароля будет длинным.
Как упоминалось ранее, опасность при таком сценарии состоит в том, что учетные записи с коротким хеш-значением паролей могут стать недоступными для клиентов версий, предшествующих 4.1. Изменения, вносимые в пароли таких учетных записей с помощью функции PASSWORD () или операторов GRANT и SET PASSWORD, приводят к тому, что учетная запись получает длинное хеш-значение пароля. И с этого момента ни один клиент старой (до 4.1) версии не сможет получить к ней доступ до тех пор, пока он не будет модернизирован до версии 4.1. Чтобы решить эту проблему, можно изменять пароль особым способом. Например, обычно для изменения пароля учетной записи оператор SET PASSWORD используется следующим образом: mysql> SET PASSWORD FOR 'пользователь'@'хост
1
= PASSWORD('mypass');
300
Глава 4. Администрирование баз данных
Чтобы изменить пароль и при этом создать короткое хеш-значение, вместо оператора SET PASSWORD используйте функцию OLD_PASSWORD ():
mysql> SET PASSWORD FOR 'пользователь1@!хост' = OLD_PASSWORD('mypass'); Функция OLD_PASSWORD() полезна в ситуациях, когда вы явно хотите генерировать короткое хеш-значение. Сценарий 3. Размер столбца Password большой; сервер запускался с опцией —old-passwords. • В столбце Password могут храниться как короткие, так и длинные хеш-значения. • Клиенты версии 4.1 могут проводить аутентификацию для учетных записей как с короткими, так и с длинными хеш-значениями (однако обратите внимание на то, что создавать длинные хеш-значения можно только тогда, когда сервер запускался без опции —old-passwords). • Клиенты старых (до 4.1) версий могут проводить аутентификацию только для учетных записей с короткими хеш-значениями. • Уже подключившиеся клиенты в операциях по генерированию хеш-значений паролей с применением PASSWORD(), GRANT или SET PASSWORD смогут использовать исключительно короткие хеш-значения. При любом изменении в пароле учетной записи ее хеш-значение пароля все равно будет коротким. При таком сценарии нельзя создать учетные записи с длинными хеш-значениями паролей, потому что опция —old-passwords запрещает генерирование длинных хешзначений. Кроме того, даже если создать учетную запись с длинным хеш-значением до применения опции —old-passwords, изменения ее пароля во время действия этой опции приведет к тому, что она получит короткий пароль, потеряв тем самым все преимущества по безопасности, предоставляемые более длинными хеш-значениями. Негативные аспекты предложенных сценариев могут быть резюмированы следующим образом: При сценарии 1 нельзя воспользоваться преимуществами длинных хеш-значений, которые обеспечивают более безопасную аутентификацию. При сценарии 2 учетные записи с короткими хеш-значениями становятся недоступными для клиентов старых (до 4.1) версий, если во время изменения их паролей не была явно использована функция OLD_PASSWORD (). При сценарии 3 опция —old-passwords не допускает того, чтобы учетные записи с короткими хеш-значениями становились недоступными, но операции по изменению паролей приводят к тому, что учетные записи с длинными хеш-значениями снова получают короткие хеш-значения, и сделать их опять длинными нельзя до тех пор, пока действует опция --old-passwords. 4.4.9.1. Последствия внесения изменений в алгоритм хеширования паролей для прикладных программ Модернизация до версии MySQL 4.1 может привести к возникновению проблем с совместимостью приложений, которые используют функцию PASSWORD () для генерирования паролей в своих собственных целях. На самом деле приложения так делать не должны, поскольку функция PASSWORD!) предназначена непосредственно для управления паролями учетных записей MySQL. Но все равно некоторые из них используют функцию PASSWORD () в своих личных целях.
4.5. Управление учетными записями пользователей MySQL
301
Если вы провели модернизацию до версии 4.1 и сервер работает в режиме генерирования длинных хеш-значений паролей, приложение, использующее функцию PASSWORD () для создания своих собственных паролей, перестанет функционировать. Рекомендуемый способ действий - модифицировать приложение таким образом, чтобы для создания хешированных значений им использовалась какая-нибудь другая функция, например, SHA1O или MD5(). Если это невозможно, попробуйте применить функцию OLD_PASSWORD (), предназначенную для генерирования коротких хеш-значений старого формата. Но не забывайте о том, что может наступить день, когда функция OLD_PASSWORD () больше поддерживаться не будет. Если сервер работает в режиме генерирования коротких хеш-значений, функция OLD_PASSWORD () доступна, но ее работа эквивалентна работе функции PASSWORD ().
4.4.9.2. Хеширование паролей в MySQL 4.1.0 Хеширование паролей в MySQL 4.1.0 отличается от хеширования в версии 4.1.1 и выше и эти отличия следующие: •
Размер хеш-значений паролей равен 45 байт, а не 41 байту.
•
Функция PASSWORD () является неповторяющейся, то есть при данном аргументе х последовательные вызовы PASSWORD (x) генерируют разные пароли.
Эти отличия делают аутентификацию в версии MySQL 4.1.0 не совместимой с аутентификацией в последующих версиях. В случае модернизации до версии MySQL 4.1.0 рекомендуется как можно быстрее провести модернизацию до более новой версии. После этого необходимо переназначить все длинные пароли в таблице user так, чтобы их формат соответствовал 41 байту.
45. Управление учетными записями пользователей MySQL В настоящем разделе описано, как произвести установку учетных записей для клиентов сервера MySQL. Здесь обсуждаются следующие вопросы: •
Значение используемых в MySQL имен учетных записей и паролей в сравнении с именами и паролями, используемыми операционной системой.
•
Как устанавливать новые и удалять существующие учетные записи.
•
Как изменять пароли.
•
Правила безопасного использования паролей.
•
Как использовать безопасные соединения с помощью SSL.
4.5.1. Имена пользователей и пароли в MySQL Учетная запись MySQL определяется именем пользователя и именем хоста (или хостов) клиента, с которого пользователь может подключиться к серверу. Также учетная запись имеет пароль. Существует несколько различий между тем, как имена пользователей и пароли используются MySQL, и тем, как они используются вашей операционной системой: •
Имена пользователей, используемые MySQL для аутентификации, не имеют ничего общего с именами пользователей (регистрационными пользовательскими
302
Глава 4. Администрирование баз данных именами) Windows или Unix. В Unix большая часть клиентов по умолчанию пытаются войти в систему, используя в качестве имени пользователя MySQL текущее имя пользователя Unix, но делают они это только для удобства. Имена по умолчанию можно легко изменить, потому что клиентские программы позволяют задавать любое имя пользователя с помощью опции -и ИЛИ —user. Поскольку это означает, что любой может попытаться подключиться к серверу, используя любое имя пользователя, обеспечить безопасность для базы данных никак нельзя до тех пор, пока все учетные записи не будут иметь пароли. Каждый, кто укажет имя пользователя для учетной записи, не имеющей пароля, сможет успешно подсоединиться к серверу.
• В MySQL для имен пользователей разрешается использовать до 16 символов, а вот в ОС максимальное количество допустимых символов может быть другим. Например, имена пользователей Unix обычно ограничены 8 символами. • Пароли MySQL не имеют ничего общего с паролями, используемыми для входа в ОС. Не обязательно существует связь между паролем, который вводится для входа в Windows или Unix, и паролем, который необходим, чтобы получить доступ к серверу MySQL в данной ОС. • MySQL шифрует пароли с помощью своего собственного алгоритма. Такой тип шифрования отличается от шифрования, используемого Unix во время входа в систему. Шифрование паролей в MySQL эквивалентно шифрованию, осуществляемому с помощью SQL-функции PASSWORD (), а шифрование в Unix равнозначно шифрованию с помощью SQL-функции ENCRYPT (). Начиная с версии 4.1, MySQL использует более сложный метод аутентификации, который обеспечивает лучшую, чем в более ранних версиях, защиту паролей во время процесса подключения. Система остается безопасной, даже если перехвачены пакеты TCP/IP или сама база данных mysql. (В более ранних версиях, хотя пароли и хранятся в таблице user в зашифрованном виде, любой, кому удается узнать зашифрованный пароль, может использовать его, чтобы подключиться к серверу MySQL.) Во время установки MySQL в таблицы привилегий заносятся исходные учетные записи. Эти записи получают имена и привилегии доступа, описанные в разделе 2.4.5, где также обсуждается вопрос о назначении для них паролей. После этого, обычно, для установки, изменения или удаления учетной записи MySQL используются операторы GRANT И REVOKE.
При подключении к серверу через клиент MySQL необходимо указать имя пользователя и пароль для учетной записи, которая будет использоваться: shell> mysql —user=monty —password=guess имя_базы_данных Если вы предпочитаете короткие варианты опций, команда будет выглядеть следующим образом: shell> mysql -u monty -pguess имя_базы_данных Пробел между опцией -р и следующим за ней значением пароля не ставится. См. раздел 4.4.4. Предыдущие команды включают значение пароля в командной строке, что может представлять определенный риск для безопасности системы (см. раздел 4.5.6). Чтобы избежать этого, задавайте опцию —password или -р, не указывая после нее само значение пароля:
4.5. Управление учетными записями пользователей MySQL
303
shell> mysql —user=monty —password имя_базы_данных shell> mysql -u monty -p имя__базы_данных В таком случае программа клиента будет запрашивать ввод пароля. (В предложенных выше примерах имя_базы_данных не интерпретируется как пароль, потому что между имя_базы_данных и предшествующей ему опцией —password находится пробел.) В некоторых системах вызов библиотеки, который MySQL использует для запроса пароля, автоматически ограничивает пароль 8 символами. Причина этого заключается в системной библиотеке, а не в MySQL. В MySQL какие-либо ограничения по длине пароля отсутствуют. Чтобы обойти подобную проблему, сократите число символов в пароле MySQL до восьми или меньше, или же поместите пароль в файл опций.
4.5.2. Добавление новых учетных записей в MySQL Создавать учетные записи MySQL можно двумя способами: • С помощью операторов GRANT. • Путем внесения изменений непосредственно в таблицы привилегий MySQL. Более предпочтительным методом считается использование операторов GRANT, поскольку они более компактны и менее подвержены ошибкам. Операторы GRANT доступны, начиная с MySQL 3.22.11; синтаксис операторов описан в книге "MySQL. Справочник по языку ". Еще одна возможность для создания учетных записей предполагает использование одной из нескольких доступных сторонних программ, которые предлагают функции по администрированию учетных записей MySQL, такой, например, как программа phpMyAdmin. Приведенные ниже примеры иллюстрируют, как клиентская программа mysql используется для создания новых пользователей. Предполагается, что привилегии установлены со значениями по умолчанию, описанными в разделе 2.4.5. Это означает, что для того чтобы внести какие-либо изменения, необходимо подключиться к серверу MySQL от имени привилегированного (root) пользователя, учетная запись root при этом должна иметь привилегию INSERT для базы данных mysql и административную привилегию RELOAD. Сначала воспользуйтесь программой mysql для подключения к серверу от имени привилегированного (root) пользователя MySQL: shell> mysql —user=root mysql Если учетной записи root назначался пароль, в этой команде (и в других описываемых ниже командах) также понадобится указать опцию —password или -р. Подключившись к серверу от имени пользователя root, можно добавлять новые учетные записи. Следующие операторы GRANT создают четыре новых учетных записи: mysql> -> mysql> -> mysql> mysql>
GRANT ALL PRIVILEGES ON *.* TO ' m o n t y ' @ ' l o c a l h o s t 1 IDENTIFIED BY ' s o m e j > a s s ' WITH GRANT OPTION; GRANT ALL PRIVILEGES ON *.* TO 'monty 1 @'%' IDENTIFIED BY ' s o m e _ p a s s ' WITH GRANT OPTION; GRANT RELOAD,PROCESS ON *.* TO ' a d m i n ' @ ' l o c a l h o s t ' ; GRANT USAGE ON *.* TO ' d u m m y ' @ ' l o c a l h o s t ' ;
Учетные записи, созданные данными операторами GRANT, обладают следующими свойствами:
304
Глава 4. Администрирование баз данных
•
Две из представленных учетных записей с именем пользователя monty и паролем some_pass являются учетными записями суперпользователя и имеют абсолютно 1 все привилегии. Первая ('monty'@'localhost ) может использоваться только при подключениях с локального хоста. Вторая ('monty'@'%') - при подключениях с любого другого хоста. Обратите внимание на необходимость в том, чтобы обе учетные записи для monty могли подключаться к серверу с любого места от имени monty. Без учетной записи localhost учетная запись анонимного пользователя для localhost, создаваемая с помощью mysql_install_db, имела бы преимущество при подсоединении monty с локального хоста. В результате monty рассматривался бы как анонимный пользователь. Причина этого состоит в том, что учетная запись анонимного пользователя имеет более точное значение в столбце Host, чем запись •monty' @ ' % ' , и поэтому стоит первой в отсортированной таблице user. (Вопросы по сортировке таблицы user рассматриваются в разделе 4.4.5.)
•
Одна из учетных записей имеет имя пользователя admin и не имеет пароля. Она может использоваться только при подключении с локального хоста. Ей предоставлены административные привилегии RELOAD и PROCESS, которые позволяют выполнять команды mysqladmin reload, mysqladmin r e f r e s h и mysqladmin flush-xxx commands, а также mysqladmin p r o c e s s l i s t . Никаких привилегий для доступа к любым базам данных у нее нет, но такие привилегии можно добавить позже за счет выполнения дополнительных операторов GRANT.
•
Оставшаяся учетная запись имеет имя пользователя dummy и не имеет пароля. Она может использоваться только при подключениях с локального хоста. Привилегии ей предоставлены не были. Привилегия USAGE в операторе GRANT присваивает всем глобальным переменным значение ' N' и тем самым позволяет создавать учетную запись без привилегий. Предполагается, что такой учетной записи позже будут назначены отдельные привилегии.
В качестве альтернативы можно создать такие же учетные записи и напрямую, с помощью операторов INSERT, после чего заставить сервер провести перезагрузку таблиц привилегий:
shell> mysql --user=root mysql mysql> INSERT INTO user -> VALUES (' localhost', 'monty', PASSWORD (• somejaass •) , -> 'YVYVYVYVYVYVYVYVYVYVYVYVYVY'); mysql> INSERT INTO user
->
VALUES (' %' , 'monty' , PASSWORD (' some_pass') ,
-> 'YVYVY'/YVYVYVYVYVYVYVYVYVYVY'); mysql> INSERT INTO user SET Host='localhost',User='admin', -> Reload_priv='Y', Process_priv='Y'; mysql> INSERT INTO user (Host,User,Password) -> VALUES('localhost 1 ,'dummy', " ) ; mysql> FLUSH PRIVILEGES; Оператор FLUSH PRIVILEGES используется во время создания учетных записей с помощью INSERT для того, чтобы сервер перезагрузил таблицы привилегий. В противном случае изменения вступают в силу только после перезапуска сервера. При использовании оператора GRANT необходимости в FLUSH PRIVILEGES нет.
4.5. Управление учетными записями пользователей MySQL
305
Функция PASSWORD () здесь используется для шифрования пароля. Оператор GRANT сам шифрует пароль, поэтому функция PASSWORD () становится необязательной. Значения ' Y' активизируют привилегии для учетных записей. В зависимости от версии MySQL, можно использовать разное количество значений ' Y' в первых двух операторах INSERT. (Версии MySQL, предшествующие 3.22.11, включают меньшее число столбцов привилегий; начиная с версии 4.0.2 их становится больше.) Для учетной записи admin применяется более удобочитаемый расширенный синтаксис INSERT, включающий и операторы SET, который доступен, начиная с версии MySQL 3.22.11. В операторе INSERT для учетной записи dummy значения указаны только в столбцах Host, User и Password таблицы user. Ни одна из привилегий не была задана явно, потому абсолютно всем привилегиям MySQL присваивает значение по умолчанию ' N'. Это эквивалентно тому, что делает оператор GRANT USAGE. Обратите внимание, что для того, чтобы добавить учетную запись суперпользователя, создать запись со значениями ' Y' в столбцах привилегий необходимо только в таблице user. Привилегии в таблице user являются глобальными, поэтому вставлять записи в любых других таблицах привилегий не нужно. В следующих примерах создаются три учетных записи, которым предоставляется доступ к конкретным базам данных. Каждая из учетных записей имеет имя пользователя custom и пароль obscure. Чтобы создать учетные записи с помощью GRANT, используйте следующие команды: s h e l l > mysql — u s e r = r o o t mysql mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP -> ON b a n k a c c o u n t . * -> TO ' c u s t o m ' @ ' l o c a l h o s t ' -> IDENTIFIED BY ' o b s c u r e ' ; mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP -> ON e x p e n s e s . *
-> TO 'custom1@'whitehouse.gov' -> IDENTIFIED BY 'obscure'; mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP -> ON customer.* -> TO 'cus torn'@'server.domain' -> IDENTIFIED BY 'obscure'; Эти учетные записи могут использоваться следующим образом: • Первая учетная запись может получать доступ к базе данных bankaccount, но только с локального хоста. • Вторая учетная запись может получать доступ к базе данных expenses, но только с хоста whitehouse. gov. • Третья учетная запись может получать доступ к базе данных customer, но только с хоста server .domain. Для создания учетных записей custom без применения оператора GRANT, воспользуйтесь следующими командами INSERT, которые вносят изменения непосредственно в таблицы привилегий: shell> mysql —user=root mysql mysql> INSERT INTO user (Host,User,Password) -> VALUES('localhost','custom',PASSWORD('obscure'));
306
Глава 4. Администрирование баз данных
mysql> INSERT INTO user (Host,User,Password) 1 -> VALUES('whitehouse.gov','custom ,PASSWORD('obscure')); mysql> INSERT INTO user (Host,User,Password) -> VALUES('server.domain','custom',PASSWORD('obscure')); mysql> INSERT INTO db -> (Host,Db, User, Selectj?riv,Insert_jpriv, -> Update_priv, Deletejpriv, Createjpriv, Dropjpriv) -> VALUES('localhost','bankaccount','custom',
->
'YVYVYVYVYVY');
mysql> INSERT INTO db -> (Host,Db,User,Selectjpriv,Insert jpriv, - > Updatejpriv, DeleteJ?riv, Create_priv, Drop jpriv) -> VALUES('whitehouse.gov','expenses','custom', -> 'Yf,'Y','Y','Y','Y','Y'); mysql> INSERT INTO db -> (Hos t,Db,User,Select_priv,Insertjpriv, -> Updatejpriv, Delete_priv, Create_priv, Drop_priv) -> VALUES (' server.domain',' customer',' custom', -> 'Y','Y','Y','Y','Y','Y'); mysql> FLUSH PRIVILEGES; Первые три оператора INSERT добавляют записи в таблицу user, которые разрешают пользователю custom подключаться с различных хостов с данным паролем, но не предоставляют глобальных привилегий (всем глобальным привилегиям присвоено значение по умолчанию 'N'). Следующие три оператора INSERT добавляют записи в таблицу db, которые предоставляют привилегии для баз данных bankaccount, expenses и customer, но только при доступе к ним с определенных хостов. И, как обычно, когда изменения вносятся непосредственно в таблицы привилегий, должен быть выполнен оператор FLUSH PRIVILEGES, обеспечивающий перезагрузку таблиц, после которой внесенные изменения вступают в силу. Если конкретному пользователю необходимо предоставить доступ со всех машин в данном домене (например, mydomain.com), можно использовать оператор GRANT, указав групповой символ '%' в той части имени учетной записи, которая предназначена для имени хоста: mysql> GRANT ... -> ON *.* - > ТО ' myname' @ ' %. mydomain. com' -> IDENTIFIED BY 'mypass1; Чтобы сделать то же самое в случае, когда изменения вносятся непосредственно в таблицы привилегий, поступите следующим образом: mysql> INSERT INTO user (Host,User,Password,. . .) -> VALUES (' %.mydomain. com','myname', PASSWORD ('mypass '),...); mysql> FLUSH PRIVILEGES;
4.5.3. Удаление пользовательских учетных записей из MySQL Для удаления учетной записи служит оператор DROP USER, который был добавлен в MySQL 4.1.1. В более старых версиях вместо него применяется оператор DELETE.
4.5. Управление учетными записями пользователей MySQL
307
Для удаления учетной записи пользователя MySQL потребуется выполнить следующие шаги в указанном порядке: 1. С помощью оператора SHOW GRANTS определите, какие привилегии имеет учетная запись. 2. С помощью оператора REVOKE отмените отображенные оператором SHOW GRANTS привилегии. Это удалит записи для данного пользователя из всех таблиц привилегий, за исключением таблицы user, и отменит все глобальные привилегии, перечисленные в ней (в таблице user). 3. С помощью оператора DROP USER удалите учетную запись из таблицы user. Оператор DROP USER появился в MySQL 4.1.1. В версиях, предшествующих 4.1.1, сначала необходимо отменить привилегии учетной записи, как описано выше, и только после этого удалить запись в таблице user и очистить таблицы привилегий: mysql> DELETE FROM mysql.user -> WHERE User='имя_пользователя* and mysql> FLUSH PRIVILEGES;
Host='имя_хоста';
4.5.4. Ограничение ресурсов учетной записи До версии MySQL 4.0.2 единственным доступным методом ограничения использования ресурсов сервера MySQL была установка ненулевого значения системной переменной max_user_connections. Но этот метод является исключительно глобальным и не разрешает управлять отдельными учетными записями. Кроме того, он ограничивает только число одновременных соединений, устанавливаемых с помощью единственной учетной записи, а не те операции, которые может выполнять уже подключившийся клиент. Метод представляет интерес для большинства администраторов MySQL, особенно для поставщиков услуг Internet. Начиная с версии MySQL 4.0.2, появляется возможность ограничивать для определенных учетных записей следующие серверные ресурсы: • Количество разрешаемых для данной учетной записи запросов в час. • Количество разрешаемых для данной учетной записи обновлений в час. • Количество разрешаемых для данной учетной записи подключений к серверу в час. Все выполняемые клиентом операторы засчитываются как запросы. Только операторы, которые вносят изменения в базы данных и таблицы, учитываются как обновления. Учетная запись в таком контексте - одна запись в таблице user. Каждая учетная запись однозначно идентифицируется по своим значениям в столбцах User и Host. Необходимым условием для применения такой функции является то, что таблица user в базе данных mysql должна содержать столбцы, имеющие отношение к ресурсам. Значения, ограничивающие использование ресурсов сервера, хранятся в столбцах max_questions, max_updates и max_connections. Если эти столбцы отсутствуют, таблицу user необходимо обновить; см. раздел 2.5.8. Чтобы установить ограничения по ресурсам с помощью GRANT, воспользуйтесь конструкцией WITH, указывая имя каждого ограничиваемого ресурса и максимальное число раз, которое этот ресурс может использоваться в час. Например, для создания учетной записи, имеющей доступ к базе данных customer, но ограниченный, выполните следующие команды:
308
Глава 4. Администрирование баз данных
mysql> GRANT ALL ON c u s t o m e r . * TO ' f r a n c i s 1 @ ' l o c a l h o s t ' -> IDENTIFIED BY ' f r a n k ' -> WITH MAX_QUERIES_PER_HOUR 20 -> MAXJJPDATESJPERJtoUR 10 -> MAX_CONNECTIONS_PER_HOUR 5 ;
Типы ограничений не обязательно указываются с помощью WITH, но те, которые именно так и заданы, могут следовать в любом порядке. Значение для каждого ограничения должно представлять собой целое число, обозначающее количество запросов/обновлений/соединений в час. Если в операторе GRANT не используется конструкция WITH, значит, присвоено будет значение по умолчанию - 0 (то есть без ограничений). Чтобы установить или изменить ограничения для существующей учетной записи, используйте оператор GRANT USAGE на глобальном уровне (ON *. *). Следующий оператор изменяет для пользователя francis значение, ограничивающее число запросов, на 100: mysql> GRANT USAGE ON * . * TO ' f r a n c i s ' @ ' l o c a l h o s t ' -> WITH MAX__QUERIES_PER_HOUR 1 0 0 ;
Данный оператор сохраняет все имеющиеся у данной учетной записи привилегии и изменяет только указанные предельные значения. Чтобы удалить существующее предельное значение, ему необходимо присвоить значение 0. Например, чтобы удалить ограничения по количеству допустимых для francis соединений в час, выполните следующий оператор: mysql> GRANT USAGE ON * . * TO ' f r a n c i s ' @ ' l o c a l h o s t ' -> WITH MAX_CONNECTIONSJ>ER_HOUR 0 ;
Подсчет количества используемых ресурсов происходит тогда, когда любое из предельных значений любой учетной записи не равно 0. Во время работы сервер подсчитывает, сколько раз каждая учетная запись использует тот или иной ресурс. Если пользователь в течение часа достигает установленного для него предела по количеству соединений, то все его попытки подключиться до конца этого часа будут отклонены. То же самое происходит, и если пользователь исчерпал свой лимит по числу запросов или обновлений: до конца часа эти ресурсы будут ему недоступны. В каждом отдельном случае сервер будет выдавать соответствующее сообщение об ошибке. Подсчет ресурсов производится для каждой конкретной учетной записи, а не для каждого клиента. Например, если предельное значение по количеству запросов для данной учетной записи соответствует 50, увеличить его до 100, установив одновременно два клиентских соединения с сервером, не получится. Запросы, обрабатываемые на обоих соединениях, подсчитываются вместе. Текущие предельные значения можно сбросить (присвоить им значение 0) как глобально для всех учетных записей, так и индивидуально для каждого конкретного значения: • Чтобы для всех учетных записей в столбцах ресурсов предельное значение снова соответствовало 0, воспользуйтесь оператором FLUSH USER_RESOURCES или перезагрузите таблицы привилегий (например, с помощью оператора FLUSH PRIVILEGES или команды mysqladmin reload). • Для конкретной учетной записи текущее предельное значение можно обнулить, переназначив его. Для этого используется оператор GRANT USAGE, как описано выше, и указывается предельное значение, равное значению, которое на данный момент установлено для этой учетной записи.
4.5. Управление учетными записями пользователей MySQL
309
4.5.5. Назначение паролей для учетных записей Пароли можно назначать в командной строке, используя команду mysqladmin: shell> mysqladmin -u имя_пользователя -h имя_хоста password "новый_пароль" Учетной записью, для которой данная команда сбрасывает пароль, является та, которая имеет в таблице user запись с подходящими значением имя_пользователя в столбце User и значением имени хоста клиента, с которого вы подключаетесь, в столбце Host. Еще один способ назначить пароль для учетной записи - воспользоваться оператором SET PASSWORD: m y s q l > SET PASSWORD FOR ' J e f f r e y ' @ ' % '
= PASSWORD('biscuit');
Только пользователи, подобные root, которые имеют права доступа для обновления к базе данных mysql, могут изменять пароли других пользователей. Если вы подключились не как анонимный пользователь, то сможете изменить свой пароль, не указывая конструкцию FOR: mysql> SET PASSWORD = P A S S W O R D ( ' b i s c u i t ' ) ;
Воспользуйтесь оператором GRANT USAGE на глобальном уровне (ON *. *) для назначения пароля учетной записи и при этом сохранения всех ее текущих привилегий: m y s q l > GRANT USAGE ON * . * TO ' J e f f r e y ' @ ' % '
IDENTIFIED BY ' b i s c u i t ' ;
Хотя в целом предпочтительнее назначать пароли с помощью одного из описанных выше методов, это также можно сделать и путем внесения изменений непосредственно в таблицу user: •
Чтобы установить пароль во время создания новой учетной записи, укажите значение для столбца Password: shell> mysql> -> mysql>
•
mysql -u r o o t mysql INSERT INTO u s e r (Host,User,Password) VALUES('%','Jeffrey',PASSWORD('biscuit')); FLUSH PRIVILEGES;
Для изменения пароля уже существующей учетной записи используйте оператор UPDATE, чтобы установить значение в столбце Password: 'shell> mysql> -> mysql>
mysql -u root mysql UPDATE user SET Password = PASSWORD('bagel') WHERE Host = '%' AND User = ' f r a n c i s ' ; FLUSH PRIVILEGES;
Когда пароль назначается с помощью операторов SET PASSWORD, INSERT или UPDATE, обязательно нужно с помощью функции PASSWORD () зашифровать его. (Единственный случай, когда функция PASSWORD () не применяется, это если пароль имеет пустое значение.) Эта функция обязательна, потому что пароли хранятся в таблице user в зашифрованном виде, а не виде открытого текста. Если забыть об этом и установить пароль следующим образом: s h e l l > mysql -u root mysql mysql> INSERT INTO user (Host,User,Password) -> VALUES('%','Jeffrey','biscuit'); mysql> FLUSH PRIVILEGES;
Глава 4. Администрирование баз данных
310
то в таблице user в качестве пароля будет сохранено символьное, а не зашифрованное значение ' b i s c u i t ' . При попытке пользователя Jeffrey подключиться к серверу с помощью этого пароля, значение пароля шифруется и сравнивается с тем, которое хранится в таблице user. Однако поскольку в таблице находится символьное значение ' biscuit', совпадение обнаружено не будет и сервер отклонит запрос на соединение: shell> mysql -u Jeffrey -pbiscuit test Access denied В доступе отказано Если пароль устанавливается с помощью оператора GRANT.. .IDENTIFIED BY или команды mysqladmin password, шифрование (в обоих случаях) выполняется автоматически, и использовать функцию PASSWORD () не нужно.
\
На заметку! Шифрование паролей с помощью функции PASSWORD!) отличается от шифрования в Unix. См. раздел 4.5.1.
4.5.6. Как обезопасить свой пароль На административном уровне никогда нельзя предоставлять доступ к таблице mysql.user обычным пользователям. Пароли в таблице user хранятся в зашифрованном виде, но в версиях MySQL, предшествующих 4.1, знание зашифрованного пароля определенной учетной записи делает возможным подключение к серверу через эту запись. При запуске клиентской программы для подключения к серверу MySQL не рекомендуется указывать свой пароль таким образом, чтобы его могли увидеть другие пользователи. Возможные методы задания пароля в таком случае, а также степени риска при использовании каждого из них представлены ниже. • Использование опции -рпароль или —pass wo r б^пароль в командной строке, например: shell> mysql -u francis -pfrank имя_базы_данных Это удобно, но небезопасно, поскольку ваш пароль становится видимым для программ вывода состояния системы, таких как ps, которые могут быть вызваны другими пользователями в целях просмотра командных строк. Во время инициализации клиенты MySQL обычно перезаписывают аргументы пароля в командной строке с помощью нулей, но по-прежнему остается короткий промежуток времени, в течение которого значение пароля остается видимым. • Использование опции -р или —password без указания пароля. В этом случае программа клиента запрашивает пароль из терминала: shell> mysql -u francis -p имя_базы_данных Enter password: ******** Символы '*' указывают, где вводится пароль. Пароль во время ввода не отображается. Намного безопаснее вводить пароль таким образом, нежели задавать его в командной строке, поскольку в этом случае он невидим для других пользователей. Однако этот метод подходит только для программ, работающих в интерактивном режиме. При вызове клиента из неинтерактивного сценария ввести пароль с тер-
4.5. Управление учетными записями пользователей MySQL
311
минала не получится. В некоторых системах первая строка вашего сценария считывается и интерпретируется как ваш пароль (что совершенно неправильно). • Хранение пароля в файле опций. Например, в Unix его можно разместить в разделе [client] файла .my.cnf в домашнем каталоге: [client] pas s wo r (1=пароль Если пароль хранится в файле .my.cnf, нельзя, чтобы он был доступен комунибудь, кроме вас. Чтобы гарантировать это, в качестве режима доступа к файлу установите значение 400 или 600: shell> chmod 600 .my.cnf Более подробную информацию, касающуюся файлов опций, можно найти в разделе 3.3.2. • Хранение пароля в переменной окружения MYSQL_PWD. Такой метод является крайне небезопасным, потому применяться не должен. Некоторые версии программы ps включают опцию для отображения переменных окружения текущих процессов. То есть, если установить MYSQLPWD, ваш пароль будет виден всем пользователям, работающим с ps. Даже в системах, не использующих такую версию ps, предполагать, что других способов, с помощью которых пользователи могут проверить переменные окружения, не существует, крайне неразумно. См. приложение Б. В конечном итоге наиболее безопасными методами являются настройка клиентской программы для запроса на ввод пароля и указание пароля в защищенном надлежащим образом файле опций.
4.5.7. Использование безопасных соединений Начиная с версии 4.0.0, MySQL поддерживает безопасные (шифрованные) соединения между клиентами MySQL и сервером с помощью протокола защищенных сокетов (Secure Sockets Layer - SSL). В настоящем разделе описано использование SSLсоединений, а также установка SSH в среде Windows. Предполагается, что стандартная конфигурация MySQL должна быть максимально быстрой, поэтому шифрованные соединения по умолчанию не используются. В противном случае это бы замедляло передачу данных через клиент-серверный протокол. Шифрование данных приводит к дополнительной нагрузке на процессор и может задерживать выполнение других задач MySQL. Для приложений, безопасность которых должна обеспечиваться посредством шифрованных соединений, обязательно потребуются добавочные вычислительные операции. MySQL позволяет активизировать функцию шифрования данных для каждого соединения в отдельности. Предлагается возможность выбирать, в соответствии с требованиями того или иного приложения, что конкретно использовать: нешифрованное соединение или безопасное шифрованное SSL-соединение.
4.5.7.1. Основные сведения о SSL Чтобы понять, как MySQL использует SSL, прежде всего следует разобраться с основными понятиями SSL и Х509. Те, кто уже знаком с ними, могут пропустить этот раздел.
312
Глава 4. Администрирование баз данных
По умолчанию MySQL использует нешифрованные соединения между клиентом и сервером. Это значит, что любой, у кого есть доступ к сети, может просматривать весь ваш трафик, а также посылаемые/получаемые данные, и даже изменять их во время самой передачи. Чтобы хоть немного улучшить степень защиты, можно при вызове клиентских программ сжимать пересылаемые между клиентом и сервером данные с помощью опции -compress. Однако настойчивого хакера это никак не остановит. Если необходима безопасная передача информации через сеть, нешифрованное соединение в таком случае точно не подходит. Шифрование - это способ сделать любую информацию недоступной для прочтения. Фактически, на сегодняшний день алгоритмы шифрования требуют новых дополнительных элементов безопасности, чтобы суметь противостоять большей части уже известных типов атак, таких как изменение порядка зашифрованных сообщений или воспроизведение данных дважды. Протокол защищенных сокетов SSL - это протокол, который использует различные алгоритмы шифрования для гарантии, что получаемым через общедоступную сеть данным можно доверять. Он с помощью своих механизмов фиксирует любые вносимые в передаваемую информацию изменения, а также потерю или повтор данных. SSL также задействует алгоритмы, обеспечивающие верификацию с помощью стандарта Х509. Стандарт Х509 позволяет проводить идентификацию личности в Internet. Чаще всего он используется в приложениях электронной коммерции. Если кратко, то должна существовать некая компания под названием "Certificate Authority" ("Центр сертификации"), которая назначает электронные сертификаты любому, кому они нужны. Сертификаты основаны на ассиметричных алгоритмах шифрования, включающих два ключа (открытый и секретный). Владелец сертификата может предъявить его другой стороне в качестве подтверждения своей личности. Сертификат содержит открытый ключ владельца. Любые данные, зашифрованные с помощью этого открытого ключа, могут быть расшифрованы только при наличии соответствующего секретного ключа, который хранится у владельца сертификата. Для получения более подробной информации по SSL, X509 или шифрованию воспользуйтесь излюбленной поисковой машиной в Internet, набрав интересующие вас слова.
4.5.7.2. Требования Для использования соединений между сервером MySQL и программами клиентов, необходимо, чтобы система поддерживала OpenSSL, а версия MySQL была не ниже. 4.0.0. Чтобы безопасные соединения начали работать с MySQL, понадобится выполнить следующие действия: 1. Установите библиотеку OpenSSL. MySQL была протестирована с OpenSSL O.9.6. Найти OpenSSL можно по адресу http: //www.openessl .org. 2. Во время конфигурирования MySQL запустите сценарий configure с опциями —with-vio и —with-openessl. 3. Убедитесь, что таблицы привилегий обновлялись и теперь содержат столбцы для SSL в таблице mysql.user. Это необходимо, если используется версия MySQL, предшествующая 4.0.0. Процедура обновления описана в разделе 2.5.8. 4. Узнать, поддерживает ли сервер mysqld протокол OpenSSL, можно, проверив значение системной переменной have_openessl:
4.5. Управление учетными записями пользователей M y S Q L
313
mysql> SHOW VARIABLES LIKE 'have_openssl'; + + + | Variable_name | Value I + + + | have_openssl
| YES
|
Если значением является YES, значит, сервер поддерживает соединения OpenSSL.
4.5.7.3. Настройка SSL-сертификатов для MySQL Ниже представлен пример настройки SSL-сертификатов для MySQL: DIR=NpwdVopenssl PRIV=$DIR/private rakdir $DIR $PRIV $DIR/newcerts cp /usr/share/ssl/openssl.cnf $DIR replace ./demoCA $DIR -- $DIR/openssl.cnf # Создание необходимых файлов: $database, $serial и # каталог $new_certs_dir (необязательно) touch $DIR/index.txt echo "01" > $DIR/serial # # Создание Certificate Authority (CA)(Центра сертификации) # openssl req -new -x509 -keyout $PRIV/cakey.pem -out $DIR/cacert.pem\ -config $DIR/openssl.cnf # # # # # # # # # # # # # # # # # # # # # # # #
Образец выходных данных: Используется конфигурация из /horae/monty/openssl/openssl.cnf Генерация секретного ключа длиной 1024 бит с помощью шифрования RSA ++++++ ++++++ Запись нового секретного ключа в '/home/monty/openssl/private/cakey.pem1 Ввод парольной фразы в формате РЕМ: Верификация пароля - Введите парольную фразу в формате РЕМ: После этого последует запрос на ввод информации, которая будет включена в сертификат. Такая информация называется "отличительным именем", или DN (Distinguished Name). Строк для ввода всего несколько и некоторые из них можно оставить пустыми. Некоторым из них будет присвоено значение по умолчанию. При вводе '.' строка будет оставлена незаполненной. Страна (код из двух букв) [AU]:FI Штат или область (полностью) [какой-нибудь штат]:. Местонахождение (например, город) []: Название организации (например, компания) [Internet Widgits Pty Ltd]:MySQL AB
314
Глава 4. Администрирование баз данных
# Отдел [ ]: # Имя (например, ВАШЕ имя) []:администратор MySQL # Адрес электронной почты []: # # Создание запроса к серверу и ключа # openssl req -new -keyout $DIR/server-key.pem -out \ $DIR/server-req.pem -days 3600 -config $DIR/openssl.cnf # Образец выходных данных: # Используется конфигурация из /home/monty/openssl/openssl.cnf # Генерация секретного ключа размером 1024 бит с помощью # шифрования RSA # ++++++ # ++++++ # Запись нового секретного ключа в # '/home/monty/openssl/private/cakey.pem' # Ввод парольной фразы в формате РЕМ: # Верификация пароля - Введите парольную фразу в формате РЕМ: # # После этого последует запрос на ввод информации, которая будет # включена в сертификат. # Такая информация называется "отличительным именем", или DN # (Distinguished Name). # Строк для ввода всего несколько и некоторые из них # можно оставить пустыми. # Некоторым из них будет присвоено значение по умолчанию. # При вводе '.' строка будет оставлена незаполненной. # # Страна (код из двух букв) [AU]:FI # Штат или область (полностью) [какой-нибудь штат]:. # Местонахождение (например, город) []: # Название организации (например, компания) [Internet Widgits Pty Ltd]:MySQL AB # Отдел []: # Имя (например, ВАШЕ имя) []:администратор MySQL # Адрес электронной почты []: # # Пожалуйста, введите следующие 'дополнительные' атрибуты, # отсылаемые вместе с сертификатом # Пароль вызова[]: # Название компании (необязательно)[]: # # Удаление парольной фразы из ключа (необязательно) # openssl rsa -in $DIR/server-key.pem -out $DIR/server-key.pem # # Подписание сертификата сервера # openssl ca -policy policy_anything -out $DIR/server-cert.pem \ -config $DIR/openssl.cnf -infiles $DIR/server-req.pem
4.5. Управление учетными записями пользователей MySQL # # # # # # # # # # # # # # # # #
Образец выходных данных: Используется конфигурация из /home/monty/openssl/openssl.cnf Введите парольную фразу в формате РЕМ: Проверьте, чтобы подпись в запросе совпадала. Подпись совпала Отличительное имя будет выглядеть следующим образом: Страна :ВЫВОД:'FI' 1 Организация :ВЫВОД:'MySQL AB Имя :ВЫВОД:'MySQL admin' Сертификат действителен до 13 сентября 14:22:46 2005 (по Гринвичу) (в течение 365 дней) Подписать сертификат? [да(у)/нет(п)]:у (да)
Создано 1 из 1 сертификатов, продолжить? [да(у)/нет(п)]:у (да) Внесение новой записи в базу данных База данных обновлена
# # Создание запроса к клиенту и ключа # openssl req -new -keyout $DIR/client-key.pem -out \ $DIR/client-req.pem -days 3600 -config $DIR/openssl.cnf # # # # # # # # # # # # # # # # # # # # # # # # # # # #
Образец выходных данных: Используется конфигурация из /home/monty/openssl/openssl.cnf Генерация секретного ключа размером 1024 бит с помощью шифрования RSA ++++++ ++++++ Запись нового секретного ключа в '/home/monty/openssl/client-key.pem' Ввод парольной фразы в формате РЕМ: Верификация пароля - Введите парольную фразу в формате РЕМ: После этого последует запрос на ввод информации, которая будет включена в сертификат. Такая информация называется "отличительным именем", или DN (Distinguished Name). Строк для ввода всего несколько и некоторые из них можно оставить пустыми. Некоторым из них будет присвоено значение по умолчанию. При вводе '.' строка будет оставлена незаполненной. Страна (код из двух букв) [AU]:FI Штат или область (полностью) [какой-нибудь штат]:. Местонахождение (например, город ) []: Название организации (например, компания) [Internet Widgits Pty Ltd]:MySQL AB Отдел []: Имя (например, ВАШЕ имя) []:администратор MySQL Электронный адрес [ ]:
315
316
Глава 4. Администрирование баз данных
# •
# # # #
Пожалуйста, введите следующие 'дополнительные' атрибуты, отсылаемые вместе с сертификатом Пароль вызова[]: Название компании (необязательно)[]:
# # Удаление парольной фразы из ключа (необязательно) # openssl rsa -in $DIR/client-key.pem -out $DIR/client-key.pem # # Подписание сертификата клиента # openssl ca -policy policy_anything -out $DIR/client-cert.pem \ -config $DIR/openssl.cnf -infiles $DIR/client-req.pem # # # # # # # # # # # # # # # # # # # # #
Образец выходных данных: Используется конфигурация из /home/monty/openssl/openssl.cnf Введите парольную фразу в формате РЕМ: Проверьте, чтобы подпись в запросе совпадала. Подпись совпала Отличительное имя будет выглядеть следующим образом: Страна :ВЫВОД:•FI' Организация :ВЫВОД:'MySQL AB' Имя :ВЫВОД:'MySQL admin' Сертификат действителен до 13 сентября 14:22:46 2005 (по Гринвичу) (в течение 365 дней) Подписать сертификат? [да(у)/нет(п)]:у (да) Создано 1 из 1 сертификатов, продолжить? [да(у)/нет(п)]:у (да) Внесение новой записи в базу данных База данных обновлена Создание файла my.cnf, который можно использовать для тестирования сертификатов
cnf="" cnf="$cnf [client]" cnf="$cnf ssl-ca=$DIR/cacert.pem" cnf="$cnf ssl-cert=$DIR/client-cert.pem" cnf="$cnf ssl-key=$DIR/client-key.pem" cnf="$cnf [mysqld]" cnf="$cnf ssl-ca=$DIR/cacert.pem" cnf="$cnf ssl-cert=$DIR/server-cert.pem" cnf="$cnf ssl-key=$DIR/server-key.pem" echo $cnf | replace " " ' ' > $DIR/my.cnf Чтобы протестировать SSL-соединения, запустите сервер следующим образом: shell> mysqld --defaults-file=$DIR/my.cnf & где $DIR - это путь к каталогу, в котором находится образец файла опций my. cnf.
4.5. Управление учетными записями пользователей MySQL
317
Затем вызовите программу клиента с использованием того же самого файла опций:
shell> mysql --defaults-file=$DIR/my.cnf При наличии исходного дистрибутива MySQL, протестировать созданные сертификаты можно, изменив упомянутый выше файл my.cnf так, чтобы он ссылался на демонстрационные сертификаты и файлы ключей в каталоге SSL.
4.5.7.4. SSL-опции GRANT Кроме обычной аутентификации с помощью пароля и имени пользователя, MySQL может дополнительно проверять и атрибуты сертификатов Х509. Чтобы задать относящиеся к SSL опции для учетной записи MySQL, используйте конструкцию REQUIRE в операторе GRANT, как описано в книге "MySQL. Справочник по языку".
4.5.7.5. Опции командной строки SSL Ниже представлен список опций, с помощью которых задается использование SSL, файлов сертификатов и файлов ключей. Эти опции доступны, начиная с MySQL 4.O. Их можно задавать как в командной строке, так и в файле опций. •
—ssl. Для сервера данная опция указывает, что сервер разрешает использование SSL-соединений. Для программы клиента эта опция разрешает клиенту подключаться к серверу через SSL. Чтобы начать использовать SSL-соединение, одной этой опции не достаточно, необходимо также задать опции —sslca, —ssl-cert и —ssl-key. Опция —ssl чаще применяется в своей противоположной форме —skip-ssl или —SS1=0,TO есть, чтобы указать, что протокол SSL использоваться не должен. Обратите внимание, что --ssl не требует SSL-соединения. Например, если сервер или клиент скомпилированы без поддержки SSL, использоваться будет обычное нешифрованное соединение. Самый безопасный способ гарантировать использование SSL-соединения - это создать на сервере учетную запись, включающую конструкцию REQUIRE SSL в операторе GRANT, и затем применять ее для подключения к серверу, предварительно позаботившись о том, чтобы и для сервера и для клиента была активизирована поддержка SSL. • —ssi-са=имя_файла. Путь к файлу со списком доверяемых центров сертификации (СА) SSL. •
—ssi-capatЬ=имя_каталога. Путь к каталогу, в котором содержаться сертификаты доверяемых СА SSL в формате РЕМ (формат электронной почты повышенной секретности).
•
—s si-сет1=ммя_файла. Имя файла сертификата SSL, который должен использоваться для установки безопасного соединения.
•
—ssl-С1р\\ег=список_шифров. Список допустимых шифров, которые будут использоваться для SSL-шифрования. список_шфров имеет тот же формат, что и команда openssl ciphers. Пример: --ssl-cipher=ALL:-AES:-EXP
•
—ssl-keу=имя_файла. Имя файла ключей SSL, который должен использоваться для установки безопасного соединения.
318
Глава 4. Администрирование баз данных
4.5.7.6. Удаленное соединение с MySQL с использованием SSH в Windows В этом разделе представлены примечания о том, как установить безопасное соединение с удаленным сервером MySQL при помощи SSH, составленные Дэвидом Карлсоном (David Carlson,
[email protected]). 1. Установите SSH-клиент в своей системе Windows. Из всех, что удалось найти, лучший клиент (с точки зрения пользователей) - это клиент, предлагаемый SecureCRT (http://www.vandyke.com/). Еще один неплохой вариантом является f-secure (http://www.f-secure.com/). Кроме того, на Google по адресу http://directory.google.com/Top/Computers/Security/Products_and_Tools/Cry ptography/SSH/Clients/Windows/ можно найти и другие бесплатные версии. 2. Запустите Windows-клиент SSH. Установите Host_Name = ит-адрес_или_1РaMpec_cepBepa_MySQL, после чего установите user±6.=ваш_идентификатор_пользователя
для входа в систему. Значение userid может отличаться от имени пользователя учетной записи MySQL. 3. Задайте переадресацию портов: либо удаленного типа (local_port: 330б, remote_host: иЯ1-адрес_или_1Р-адрес_сервера__Му50Ь, remote_port: 3306), либо локального типа (port: 3306, host: localhost, remote port: 3306). 4. Сохраните все изменения; в противном случае, в следующий раз все придется устанавливать заново. 5. Подключитесь к серверу с помощью только что созданного сеанса SSH. 6. В Windows запустите какое-нибудь ODBC-приложение (например, Access). 7. Создайте новый файл в Windows и ссылку на MySQL с помощью ODBC-драйвера так, как это обычно делается, только вместо имя_сервера_Му8()1 для серверного хоста MySQL введите localhost. После этого у вас должно появиться ODBC-соединение с MySQL, шифруемое с использованием SSH.
46. Предотвращение аварий и восстановление системы В настоящем разделе рассматриваются вопросы, касающиеся резервного копирования баз данных и обслуживания таблиц. Синтаксис описываемых здесь SQL-операторов можно найти в книге MySQL. Справочник по языку. Большая часть информации этого раздела в первую очередь касается таблиц My ISAM. Процедуры резервного копирования баз данных InnoDB приводятся в разделе 9.9.
4.6.1. Резервное копирование баз данных Поскольку таблицы MySQL хранятся в виде файлов, их резервное копирование выполняется достаточно просто. Чтобы добиться согласованности резервных копий, сначала для соответствующих таблиц выполните LOCK TABLES, а затем для них же - FLUSH TABLES. Необходима только блокировка по чтению, поскольку это позволит другим клиентам продолжать запрашивать таблицы в то время, как будет создаваться копия файлов
4.6. Предотвращение аварий и восстановление системы
319
каталога базы данных. Оператор FLUSH TABLES нужен, чтобы гарантировать, что все активные страницы индексов будут записаны на диск до начала резервного копирования. Если требуется выполнить резервное копирование таблицы на уровне SQL, существует возможность воспользоваться операторами SELECT INTO.. .OUTFILE или BACKUP TABLE. Для SELECT INTO.. .OUTFILE выходной файл существовать не может; то же самое касается и BACKUP TABLE в версиях MySQL 3.23.56 и MySQL 4.0.12, поскольку это бы представляло угрозу для безопасности системы. Еще один способ провести резервное копирование базы данных - это использовать программу mysqldump или сценарий mysqlhotcopy. См. разделы 7.8 и 7.9. 1. Выполните полное резервное копирование базы данных: shell> mysqldump —tab=/путь/к/'определенному/каталогу —opt имя_базы_данных или shell> mysqlhotcopy имя_базы_данных /путь/к/определенному/каталогу Можно также просто скопировать все файлы таблиц (*.frm, *.MYD и *.MYI), пока сервер не осуществляет никаких обновлений. Сценарий mysqlhotcopy использует именно такой метод. Однако обратите внимание, что если база данных содержит таблицы innoDB, этот метод работать не будет. InnoDB не хранит файлы таблиц в каталогах баз данных, и поэтому mysqlhotcopy подходит только для таблиц My IS AM и ISAM. 2. Остановите mysqld, если он работает, и перезапустите его с опцией - - l o g - b i n [ = имя_файла]. См. раздел 4.8.4. В файлах бинарного журнала данные, необходимые для репликации, содержатся в такой же последовательности, в которой вносились изменения в базу данных, начиная с момента, когда была запущена программа mysqldump. Если сервер MySQL является подчиненным сервером репликации, тогда, независимо от выбранного метода резервного копирования, во время его проведения на таком сервере обязательно следует создавать также резервную копию файлов m a s t e r . i n f o и r e l a y log, info. Эти файлы всегда нужны для возобновления репликации после восстановления данных подчиненного сервера. Если во время репликации на подчиненном сервере используются команды LOAD DATA INFILE, потребуется сделать копии всех файлов SQL_LOAD-*, которые могут находиться в каталоге, указанном в опции - - s l a v e - l o a d tmpdir. (Если имя этого каталога не задано, по умолчанию ему будет присвоено значение переменной tmpdir). Подчиненному серверу понадобятся эти файлы, чтобы возобновить репликацию любых прерванных операций LOAD DATA INFILE. Если приходится восстанавливать таблицы My ISAM, попробуйте сначала сделать это с помощью REPAIR TABLE или myisamchk -г. В 99,9% случаев это должно сработать. Если myisamchk не помогает, попытайтесь выполнить следующее. (Обратите внимание, что это принесет результаты только в том случае, если была активизирована функция регистрирования данных в бинарном журнале путем запуска сервера с опцией — l o g - b i n ; см. раздел 4.8.4.) 1. Восстановите исходную резервную копию, полученную с помощью mysqldump, или бинарную копию.
320
Глава 4. Администрирование баз данных
2. Выполните следующую команду, чтобы запустить повторное обновление записей бинарного журнала: shell> mysqlbinlog имя_хоста-Ып. [0-9]* | mysql В отдельном случае может понадобиться запустить повторное обновление только определенных бинарных журналов (обычно выполняется повторное обновление всех записей, за исключением лишь некоторых некорректных запросов, занесенных в бинарные журналы, начиная с даты проведения резервного копирования после восстановления). За более подробной информацией, касающейся утилиты mysqlbinlog и ее применения, обращайтесь в раздел 7.5. Если используются журналы обновлений, обработать их содержимое можно следующим образом: shell> I s - I - t -г имя_хоста.[0-9]* | xargs cat | mysql Is используется, чтобы рассортировать файлы журнала обновлений в правильном порядке. Также можно осуществлять избирательное резервное копирование отдельных файлов: • Чтобы построить дамп таблицы, используйте SELECT * INTO OUTFILE химя_файла* FROM 'имя_ та блицы'. • Чтобы перезагрузить таблицу, используйте для восстановления LOAD DATA INFILE ' имя_файла' REPLACE... Во избежание появления дубликатов записей, у таблицы должен быть индекс UNIQUE или PRIMARY KEY. Применение ключевого слова REPLACE приводит к замене старых записей новыми, когда новая запись дублирует старую по значению уникального ключа. В случае проблем с производительностью сервера во время резервного копирования помочь может установка репликации и проведение копирования не на главном, а на подчиненном сервере. См. раздел 5.1. Если используется файловая система Veritas, резервное копирование можно осуществлять следующим образом: 1. Из программы клиента выполните FLUSH TABLES WITH READ LOCK. 2. Из другой командной оболочки выполните mount vxf s snapshot. 3. Из первого клиента выполните UNLOCK TABLES. 4. Скопируйте файлы из снимка. 5. Размонтируйте снимок.
4.6.2. Обслуживание и восстановление таблиц после аварий Ниже дается описание применения myisamchk для проверки или восстановления таблиц My ISAM (таблиц, хранящихся в файлах .MYI и .MYD). Те же самые концепции применимы и в отношении isamchk при проверках и восстановлении таблиц ISAM (таблиц, хранящихся в файлах . ISM и . ISD). См. главу 8. Утилиту myisamchk можно использовать для получения информации о таблицах базы данных или же для проверки необходимости исправления или оптимизации таблиц. В следующих разделах описывается, как вызвать myisamchk (включая описание доступных
4.6. Предотвращение аварий и восстановление системы
321
в ней опций), как настроить график обслуживания таблиц и как с помощью myisamchk выполнять различные функции. Хотя восстановление таблиц с помощью myisamchk - процесс достаточно безопасный, прежде чем приступать к нему (или любой другой операции по обслуживанию, подразумевающей внесение многочисленных изменений в таблицу), лучше все-таки сделать резервную копию. Выполняемые myisamchk операции, в которых задействуются индексы, могут привести к построению индексов FULLTEXT с такими полнотекстовыми параметрами, что они станут несовместимыми со значениями, используемыми сервером MySQL. Чтобы избежать этого, следуйте инструкциям из раздела 4.6.2.2. В большинстве случаев может оказаться намного проще для обслуживания таблиц My ISAM использовать SQL-операторы, которые выполняют те же операции, что и myisamchk: • Для проверки и восстановления таблиц MylSAM используйте CHECK TABLE или REPAIR TABLE. • Для оптимизации таблиц MylSAM используйте OPTIMIZE TABLE. • Для анализа таблиц MylSAM используйте ANALYZE TABLE. Эти операторы вводились в различных версиях, но все они доступны, начиная с версии MySQL 3.23.14. Их можно использовать напрямую или посредством клиентской программы mysqlcheck, обеспечивающей для них интерфейс командной стоки. Одно из преимуществ данных операторов по сравнению с myisamchk заключается в том, что при их использовании всю работу делает сервер. В случае, когда применяется утилита myisamchk, необходимо проверять, чтобы таблицы в это же время не использовались сервером. В противном случае не исключено нежелательное взаимодействие между myisamchk и сервером.
4.6.2.1. Синтаксис запуска myisamchk Запускайте myisamchk следующим образом: s h e l l > myisamchk [опции] имя^таблицы
В опциях указывается, что myisamchk должна делать. Сами опции описываются в следующих разделах. Также список опций можно просмотреть с помощью myisamchk —help. Если опции не заданы, myisamchk по умолчанию просто проверяет таблицу. Чтобы получить более подробную информацию или заставить myisamchk выполнить определенные корректирующие действия, необходимо задавать опции так, как описывается ниже. имя_таблицы - это таблица базы данных, которую следует проверить или восстановить. Если myisamchk запускается не из каталога базы данных, необходимо указать к нему путь, поскольку myisamchk не знает, где расположена база данных. На самом деле для myisamchk не имеет значения, размещены рабочие файлы в каталоге базы данных или нет. Файлы, соответствующие таблице базы данных, можно скопировать в другой каталог и провести в нем операции по их восстановлению. При желании можно задать имена нескольких таблиц в командной строке myisamchk. Также существует возможность указать таблицу через имя индексного файла (файл с суффиксом .MYI). Это позволяет задавать все таблицы из каталога с помощью шаблона
Глава 4. Администрирование баз данных
322
* .MYI. Например, находясь в каталоге базы данных, все таблицы My ISAM в этом каталоге можно проверить следующим образом: shell> myisamchk *.MYI Проверить все таблицы в каталоге базы данных, не находясь в нем, можно, указав путь к этому каталогу: shell> myisamchk /путь/к/каталогу_базы_данных/* .MYI Также, возможно даже проверить все таблицы во всех базах данных, указав групповой символ ('*') и путь к каталогу данных MySQL:
shell> myisamchk /путь/к/каталогу ^данных/*I* .MYI Для быстрой проверки всех таблиц My ISAM и ISAM рекомендуется следующий способ: shell> myisamchk —silent —fast /путь/к/каталогу данных/* /* .MYI shell> isamchk —silent /путь/к/каталогу_данных/*/*.ISM Если необходимо проверить все таблицы My ISAM и ISAM и восстановить поврежденные, можно воспользоваться следующими командами: shell> myisamchk —silent —force —fast —update-state \ -0 keyjbuffer=64M -0 sort_buffer=64M \ -0 read_buffer=lM -0 writeJmffer=lM \ /путь/к/каталогу_данных/*/*.MYI shell> isamchk —silent —force -0 keyJbuffer=64M \ -0 sortjDuffer=64M -0 read_buffer=lM -0 write_buffer=lM \ /путь/к/каталогу__данных/*/*. ISM Эти команды предполагают наличие более чем 64 Мбайт свободного пространства на диске. Детальнее вопрос о распределении памяти с помощью myisamchk рассматривается в разделе 4.6.2.6. Необходимо убедиться, что во время запуска утилиты myisamchk таблицы больше никакой другой программой не используются. В противном случае myisamchk при запуске может выдать следующее сообщение об ошибке: warning: clients are using or haven't closed the table properly предупреждение: клиенты используют или не закрыли должным образом таблицу Это указывает на попытку проверить таблицу, которая обновлялась другой программой (такой как, например, сервер mysqld), пока не закрывшей файл или завершившей свою работу, не успев корректно закрыть файл. Если mysqld выполняется, необходимо обязательно, с помощью FLUSH TABLES, заставить его очистить все находящиеся в буфере памяти изменения таблиц. После этого потребуется обеспечить, чтобы никто не использовал таблицы до тех пор, пока функционирует myisamchk. Самый простой способ избежать этой проблемы - для проверки таблиц вместо утилиты myisamchk использовать оператор CHECK TABLE.
4.6.2.2. Общие опции для myisamchk Опции, описываемые в этом разделе, могут использоваться для любого типа операций по обслуживанию таблиц, выполняемых утилитой myisamchk. В следующих после этого разделах рассматриваются опции, имеющие отношение только к конкретным операциям, таким как проверка или восстановление таблиц. •
—help, -?. Отображает справочное сообщение и завершает работу.
4.6. Предотвращение аварий и восстановление системы
323
•
—с1еЪид=опции_отладки, -# опции_отладки. Записывает отладочную информацию. Строка опции_отладки часто выглядит как ' d: t : о, имя_файла'.
•
— s i l e n t , -s. Режим минимального количества сообщений. Вывод данных только в случае возникновения ошибок. Можно использовать -s дважды (-ss) для достижения максимального эффекта.
•
--verbose, -v. Режим расширенных сообщений. Выводится больше информации. Может использоваться вместе с -d и -е. Чтобы максимально увеличить объем выходных данных, -v указывается многократно (-vv, -vvv).
•
— v e r s i o n , -V. Отображает данные о версии и завершает работу.
•
—wait, -w. Если таблица заблокирована, не выдавать ошибку, а ожидать, пока блокировка будет снята, прежде чем продолжить работу. Обратите внимание, что если mysqld запущен с опцией — s k i p - e x t e r n a l - l o c k i n g , таблица может быть заблокирована только другой командой myisamchk.
Кроме того, с помощью опций —имя_переменной= значение следующие переменные: Переменная
Значение по умолчанию
decode_bits
9
f t_max_word_len
Зависит от версии
ft_min_word_len
4
key_buffer_size
523264
myisam_block_size
1024
read_buffer_size
262136
sort_buffer_size
2097144
sort_key_blocks
16
write_buffer_size
262136
можно устанавливать
Устанавливать переменные можно и с помощью синтаксиса — s e t - v a r i a b l e = имя переменной^значение или -0 имя_переменной= значение. Однако в версии MySQL 4.0 такой синтаксис уже устарел. Изучить допустимые переменные myisamchk и их значения по умолчанию можно с помощью опции myisamchk — h e l p : •
s o r t _ b u f f e r _ s i z e применяется, когда ключи исправляются путем их сортировки, что далеко не редкость при использовании —recover.
•
key_buffer_size применяется при проверке таблиц с помощью —extend-check или при исправлении ключей путем их построчной вставки в таблицу (подобно осуществлению обычных вставок).
Исправления через буфер ключей необходимы в следующих случаях: •
При использовании — s a f e - r e c o v e r .
•
Когда временные файлы, необходимые для сортировки ключей, требуют в два (и выше) раза больше места, чем создание файла ключей непосредственно. Чаще всего это происходит, если в столбцах CHAR, VARCHAR или TEXT содержаться большие ключевые значения, поскольку во время операции сортировки их приходится
324
Глава 4. Администрирование баз данных сохранять полностью. При наличии большого объема пространства для временных файлов и возможности исправления таблиц через сортировку, можно использовать опцию —sort-recover.
Для операций по восстановлению таблиц посредством буфера ключей требуется значительно меньше пространства на диске, чем для проведения сортировки, однако в то же время выполняются они намного медленнее. Чтобы ускорить процесс восстановления таблиц, устанавливайте для переменных key_buffer_size и sort_buffer_size значения, соответствующие приблизительно 25% доступной памяти. Значения обеих переменных могут быть большими, поскольку за раз используется только одна из них. myisamblocksize - это размер, используемый для индексных блоков. Опция доступна, начиная с версии MySQL 4.O.O. Переменные f t_min_word_len и f t_max_word_len доступны, также начиная с версии MySQL 4.0.0, a f t s t o p w o r d f i l e - начиная с MySQL 4.0.19. f t_min_word_len и f t_max_word_len обозначают минимальную и максимальную длину слова для индексов FULLTEXT. f t_stopword_f i l e указывает имя файла стоп-слов. Эти опции необходимо устанавливать при описанных ниже обстоятельствах. Если myisamchk используется для выполнения операции, изменяющей табличные индексы (такой как операция исправления или операция анализа), индексам FULLTEXT присваиваются значения по умолчанию с полнотекстовыми параметрами для минимальной и максимальной длины слов, а также для файла стоп-слов, до тех пор, пока не будут заданы другие значения. Это может привести к невыполнению запросов. Проблема возникает из-за того, что эти параметры известны только серверу. В индексных файлах My ISAM они не сохранены. Чтобы избежать этой проблемы, когда изменены значения для максимальной и минимальной длины слов или файла стоп-слов на сервере, задайте утилите myisamchk те же самые, которые используются для mysqld, значения ft_min_word_len, ft_max_word_len и ft__stopword_file. Например, если для минимальной длины слова установлено значение 3, посредством myisamchk таблицу можно восстановить следующим образом: shell> myisamchk —recover —ft_min_word_len=3 имя_ та блицы. MYI Для гарантии, что myisamchk и сервер будут использовать одинаковые значения для полнотекстовых параметров, можно каждое из них разместить одновременно и в разделе [mysqld], и в разделе [myisamchk] файла опций: [mysqld] ft__min_word_len=3 [myisamchk] ft__min_word_len=3 Альтернативным вариантом для утилиты myisamchk является применение операторов REPAIR TABLE, ANALYZE TABLE, OPTIMIZE TABLE И ALTER TABLE. Эти операторы ВЫПОЛНЯЮТСЯ сервером, которому известно, какие использовать значения для полнотекстовых параметров.
4.6.2.3. Опции проверки для myisamchk Утилита myisamchk поддерживает следующие опции, необходимые для проведения операций по проверке таблиц:
4.6. Предотвращение аварий и восстановление системы
325
•
—check, -с. Проверить таблицу на наличие ошибок. Представляет собой операцию по умолчанию, если только не задается опция, явно указывающая тип необходимой операции.
•
—-check-only-changed, -С. Проверить только таблицы, которые были изменены с момента запуска последней проверки.
•
—extend-check, -e. Расширенная проверка таблицы. Процесс происходит очень медленно, если таблица содержит большое количество индексов. Эта опция должна использоваться только в крайних случаях. Обычно проверки при помощи myisamchk или myisamchk —medium-check вполне достаточно, чтобы определить наличие любых ошибок в таблице. При использовании —extend-check и доступности большого объема памяти, установка высокого значения для переменной key_buffer_size позволяет ускорить выполнение операций по исправлению.
•
—fast, -F. Проверить только таблицы, которые не были закрыты надлежащим образом.
•
—force, -f. Выполнять исправления автоматически, если myisamchk находит хоть одну ошибку в таблице. Тип исправления такой же, как и тот, что указан в опции —repair или -г.
•
—information, -i. Выводить статистические данные по проверенной таблице.
•
—medium-check, -m. Выполняет более быструю проверку, чем —extend-check. Находит только 99,99% ошибок, но этого должно оказаться вполне достаточно в большинстве случаев.
•
--read-only, -Т. Не отмечать таблицу как проверенную. Может пригодиться, если с помощью myisamchk проверяется таблица, которая используется каким-либо другим приложением, не применяющим блокировку (например, mysqld, запущенным с опцией —skip-external-locking).
•
—update-state, -U. Сохранять информацию о дате проверки или о повреждениях таблицы в файле .MYI. Опцию следует применять, чтобы извлечь максимальную пользу из —check-only-changed, и не следует - когда таблица используется сервером mysqld, который запущен с опцией --skip-external-locking.
4.6.2.4. Опции восстановления для myisamchk Утилита myisamchk поддерживает следующие опции, необходимые для проведения операций по восстановлению таблиц: •
—backup, -В. Сделать резервную копию файла .MYD в виде имя^файла- время .ВАК.
•
—character-sets-dir=nyTb. Каталог, в котором находятся наборы символов. См. раздел 4.7.1.
•
—correct-checksum. Откорректировать данные контрольной суммы для таблицы.
•
--data-file-length=#, -D #. Максимальный размер (длина) файла данных (при повторном создании такого файла, когда этот файл уже полностью "заполнен").
•
—extend-check, -e. Выполнить операцию по исправлению с восстановлением каждой возможной строки из файла данных. Обычно при этом восстанавливается
326
Глава 4. Администрирование баз данных и масса ненужных строк. Используйте эту опцию только тогда, когда ситуация становится полностью безвыходной.
•
—force, -f. Вместо аварийного прекращения работы перезаписывать старые временные файлы (то есть файлы с именами наподобие имя__таблицыЛШ)).
•
~keys-used=#, -k #. Для myisamchk значение опции указывает, какие индексы обновлять. Каждый двоичный бит значения опции соответствует индексу таблицы, где первый индекс - это бит 0. Для isamchk значение опции означает, что обновлять следует только первых # индексов. В обоих случаях значение 0 блокирует обновления для всех индексов, что может использоваться для ускорения вставок. Отключенные индексы могут быть активизированы снова при помощи myisamchk -г или isamchk -r.
•
—no-symlinks, - I . He учитывать символические ссылки. Обычно myisamchk исправляет таблицу, на которую указывает символическая ссылка. Данная опция не существует, начиная с версии MySQL 4.O. В версиях 4.0 и выше символические ссылки не удаляются во время операций по исправлению.
•
—parallel-recover, -p. Применяет те же приемы, что и -г или -п, но создает все ключи параллельно, используя разные потоки. Опция была добавлена в MySQL 4.0.2. Пребывает на стадии альфа-тестирования. Используйте исключительно на своп страх и риск!
•
— quick, -q. Ускоряет операции по восстановлению без изменения файла данных. Можно задавать двойную опцию -q, что заставит myisamchk изменять исходный файл данных в случае, если ключи дублируются.
•
—recover, -r. Исправляет почти все ошибки, за исключением проблем с уникальными ключами, которые таковыми не являются (в таблицах ISAM и My ISAM это крайне редкий случай). Если необходимо восстановить таблицу, данная опция является первой, которую следует использовать. Попробуйте применить -о, только если myisamchk выдает сообщение о том, что таблица не может быть восстановлена посредством -г (даже если это произойдет, что маловероятно, файл данных при этом останется незатронутым).
•
—safe-recover, -о. Выполняет операцию по исправлению с помощью старого метода восстановления, при котором считываются все строки подряд и на основе найденных строк осуществляется обновление всех индексных деревьев. Такая операция выполняется на порядок медленнее, чем при использовании -г, но помогает решить пару маловероятных проблем, с которыми опция -г справиться не может. Также при таком методе требуется намного меньше пространства на диске, нежели когда применяется -г. Обычно сначала всегда используется опция -г, и только если результат будет неудовлетворительным, используется опция -о. При наличии большого доступного объема памяти следует увеличить значение key_buffer__size.
•
—set-character-set=niwi. Изменяет таблицу символов, используемую при построении индексов.
•
—sort-recover, -n. Заставляет myisamchk использовать метод сортировки для преобразования ключей, даже если слишком большой размер временных файлов нежелателен.
4.6. Предотвращение аварий и восстановление системы
327
•
--tmpdir=nyrb, - t путь. Путь к каталогу, который будет использоваться для хранения временных файлов. Если данная опция не задана, myisamchk берет значение переменной окружения TMPDIR. Начиная с версии MySQL 4.1, в tmpdir можно указывать сразу несколько путей к каталогам, которые будут использоваться поочередно по циклическому принципу для создания временных файлов. В качестве разделительного символа между именами каталогов в Unix служит двоеточие (':'), а в Windows, NetWare и OS/2 - точка с запятой (';').
•
--unpack, -u. Распаковать таблицу, которая была упакована с помощью myisampack.
4.6.2.5. Другие ОПЦИИ ДЛЯ myisamchk Помимо опций для проверки и восстановления таблиц утилита myisamchk поддерживает и другие опции: •
--analyze, -а. Анализировать распределение ключей. Это повышает эффективность соединений, позволяя оптимизатору более правильно выбирать порядок, в котором следует соединять таблицы, и ключи, которые должны при этом использоваться. Для получения информации по распределению ключей воспользуйтесь командой myisamchk —description —verbose имя_таблицы или оператор SHOW KEYS FROM имя^таблицы.
•
—description, -d. Отображает информацию описательного характера о таблице.
•
—set-auto-increment[^значение], -А[значение]. Задает начало нумерации AUTO_INCREMENT для новых записей с определенного значения (или большего, если записи с таким значением AUTO_INCREMENT уже существуют). Если значение не указано, то в качестве первого значения для AUTO_INCREMENT будет использоваться наибольшее на данный момент в таблице значение плюс один.
•
—sort-index, -S. Сортирует блоки индексного дерева в порядке от наибольшего к меньшему. Это оптимизирует операции поиска и ускоряет операции сканирования по ключу.
•
—sort-records=#, -R #. Сортирует записи в соответствии с определенным индексом. Это повышает степень локализации данных и может ускорить выполнение интервальных операций SELECT и ORDER BY, использующих данный индекс. (При первом запуске этой опции сортировка может выполняться очень медленно.) Для определения номеров индексов применяйте оператор SHOW KEYS, который отображает индексы таблиц именно в том порядке, в каком их видит myisamchk. Нумерация индексов начинается с 1.
4.6.2.6. Использование памяти утилитой myisamchk При работе с утилитой myisamchk распределение памяти является важным вопросом. Утилита myisamchk не использует большего, чем задано в опции -0, объема памяти. В случае применения myisamchk для очень больших таблиц, первым делом потребуется продумать, какой объем памяти при этом потребуется. Присваиваемое по умолчанию значение для выполнения операций по исправлению составляет приблизительно 3 Мбайт. Установка больших значений ускоряет работу myisamchk. Например, при наличии более чем 32 Мб ОЗУ можно использовать и такие опции (помимо всех других задаваемых опций):
328
Глава 4. Администрирование баз данных
shell> myisamchk -О sort=16M -0 кеу=16М -О read=lM -О write=lM ... Значения -О sort=16M в большинстве случаев будет вполне достаточно. Помните о том, что myisamchk использует временные файлы в TMPDIR. Если TMPDIR указывает на файловую систему в ОЗУ, ошибки типа "недостаточно памяти" не исключены. Если подобное произойдет, сделайте так, чтобы TMPDIR указывал на каталог в файловой системе с большим свободным пространством и перезапустите myisamchk. Для выполнения операций по исправлению myisamchk также требует большого объема доступного дискового пространства: • Понадобится пространство размером как два файла данных (для исходного файла и его копии). При выполнении операции по исправлению с помощью —quick такое пространство не требуется, так как повторно создается только индексный файл. Однако оно необходимо в файловой системе, где находится исходный файл данных, поскольку копия создается в том же каталоге, в котором хранится оригинал. • Понадобится пространство для нового индексного файла, который заместит собой старый. В самом начале операции по восстановлению старый индексный файл усекается, поэтому занимаемое им пространство можно игнорировать. Дополнительное место потребуется в той файловой системе, в которой находится исходный индексный файл. • При использовании —recover или --sort-recover (но не —safe-recover) понадобится дополнительное пространство под буфер сортировки. Необходимый объем такого пространства вычисляется следующим образом: {наиболыпий_ключ + длина_указателя_строки) * количество_строк * 2 Узнать длину ключей и длина_указателя_строки можно с помощью myisamchk -dv имя_таблицы. Это пространство выделяется во временном каталоге (указанном с помощью TMPDIR или —tmpdiг=луть). При возникновении проблем, связанных с недостаточным объемом пространства на диске, во время выполнения операций по восстановлению, попробуйте указать —safe-recover вместо —recover. 4.6.2.7. Использование myisamchk для восстановления после аварий При запуске mysqld с опцией —skip-external-locking (являющейся опцией по умолчанию в некоторых системах, например, в Unix) надежность проверки таблицы посредством myisamchik, когда эта же таблица используется сервером mysqld, не гарантируется. Если есть абсолютная уверенность в том, что никто не попытается получить доступ к таблицам через mysqld в то время, когда будет работать myisamchk, тогда единственное, что нужно сделать перед проверкой таблиц, это выполнить команду mysqladmin flush-tables. Если такой уверенности нет, следует остановить mysqld на время, пока будут проверяться таблицы. В случае запуска myisamchik тогда, когда таблицы обновляются сервером mysqld, может появиться предупреждение о том, что таблица повреждена, даже если на самом деле это не так. При отсутствии опции —skip-external-locking использовать myisamchik для проверки таблиц можно в любое время. В таком случае, во время проверки всем клиентам, пытающимся обновить таблицу, придется ожидать, пока myisamchik не будет готова продолжить работу.
4.6. Предотвращение аварий и восстановление системы
329
Если myisamchik применяется в целях исправления или оптимизации таблиц, всегда обязательно позаботьтесь о том, чтобы во время проведения этих операций данная таблица не использовалась сервером mysqld (это также относится и к случаям, когда применяется опция —skip-external-locking). Необходимо, если не приостановить работу mysqld, то, по крайней мере, выполнить команду mysqladmin flush-tables, прежде чем запускать myisamchik. При одновременном доступе со стороны сервера и со стороны myisamchik не исключено повреждение таблиц. В данном разделе описывается, как проверить базы данных MySQL на наличие в них повреждений и что делать в случаях, когда повреждения данных были обнаружены. Если повреждение таблиц случается достаточно часто, следует попытаться выяснить причину, по которой это происходит. См. раздел А.4.2. В разделе, посвященном таблицам My ISAM, описываются причины, по которым может произойти повреждение данных в таблице. См. раздел 8.1.4. Для проведения операций по восстановлению после аварий чрезвычайно важно понимать, что каждой таблице My ISAM с именем имя_таблицы в базе данных соответствуют три файла в каталоге базы данных: Файл
Назначение
имя_таблицы. f rm
Файл определения (формата).
имя_ та блицы. MY D
Файл данных.
имя_ та блицы. MY I
Файл индекса.
Каждый из этих трех файлов подвержен своему типу повреждений, но чаще всего проблемы возникают с файлами данных и индексными файлами. Сначала myisamchik создает копию файла данных .MYD построчным методом. Этап исправления завершается удалением старого файла .MYD и присвоением новому файлу имени исходного файла. При использовании —quick утилита myisamchik не создает временный файл .MYD, предполагая, что файл .MYD является корректным, и поэтому генерирует только новый индексный файл, не затрагивая файл .MYD. Такой способ безопасен, поскольку myisamchik автоматически определяет, поврежден ли файл .MYD, и если это так, тут же прекращает операцию по исправлению. Для myisamchik также можно указывать опцию —quick дважды. В этом случае при возникновении некоторых ошибок (таких как, например, дублирование ключа) myisamchik не будет аварийно прекращать работу, а вместо этого попытается разрешить эти ошибки путем изменения файла .MYD. Обычно применять две опции —quick полезно тогда, когда свободного пространства на диске недостаточно для проведения стандартной операции по исправлению. В таком случае необходимо, по крайней мере, выполнить резервное копирование, прежде чем запускать myisamchik. 4.6.2.8. Как проверить таблицы MyiSAM на наличие ошибок Для проверки таблицы My ISAM используются следующие команды: • myisamchk имя_таблицы. Эта опция позволяет обнаружить 99,9% всех ошибок. Она не находит только повреждения, имеющие непосредственное отношение к файлу данных (которые маловероятны). Чтобы проверить таблицу, обычно следует запустить myisamchk без опций или с одной из опций -s или —silent.
330
Глава 4. Администрирование баз данных
• myisamchk -m имя_таблицы. Эта опция позволяет найти 99,999% всех ошибок. Она сначала отдельно проверяет все индексные записи на наличие ошибок, а затем просматривает все строки подряд. После этого вычисляется контрольная сумма для всех ключей во всех строках, которая сопоставляется с контрольной суммой ключей в индексном дереве. • myisamchk -e имя_таблицы. С помощью этой опции проводится полная и тщательная проверка абсолютно всех данных (-е означает расширенную проверку). Эта опция осуществляет проверочное считывание каждого ключа для каждой строки, проверяя, действительно ли ключи указывают на те строки, на которые нужно. Для больших таблиц с множеством ключей выполнение такой операции может занять много времени. Обычно myisamchk останавливается, обнаружив первую же ошибку. Чтобы получать больше данных, можно добавить опцию —verbose (-v). В таком случае myisamchk сможет не останавливаться до тех пор, пока количество ошибок не достигнет максимального числа 20. • myisamchk -e -i имя_таблицы. Схожа с предыдущей командой, но опция -i вынуждает myisamchk отображать также и некоторые статистические данные. В большинстве случаев просто запустить myisamchk, не указывая никаких других аргументов, кроме имени таблицы, оказывается вполне достаточно для проведения проверки.
4.6.2.9. Как исправлять таблицы В данном разделе описано, как использовать myisamchk для таблиц MylSAM (файлы с расширением .MYI и .MYD). Для таблиц ISAM (файлы с расширением .ISM и .ISD) вместо myisamchk следует использовать утилиту isamchk. Общие принципы применения обеих утилит одинаковы. В версии MySQL 3.23.16 и выше для проверки и исправления таблиц MylSAM можно (и нужно) использовать операторы CHECK TABLE и REPAIR TABLE. Признаками того, что таблица повреждена, служат неожиданное прерывание обработки запросов и появление ошибок, таких как: • Файл иыя__таблицы. f rm заблокирован для изменения. • Невозможно найти файл имя_таблицы.Ш1 (номер ошибки: ###). • Неожиданный конец файла. • Файл записей поврежден. • Получена ошибка ### от обработчика таблицы. Для получения более подробной информации об ошибке, можно запустить perror ###, где ### - номер ошибки. Ниже представлены выдаваемые perror номера наиболее распространенных ошибок, свидетельствующих о проблемах с таблицей, а также их значение: shell> perror 126 127 132 134 135 136 141 144 145 126 = Index f i l e is crashed / Wrong f i l e format Индексный файл поврежден / Неправильный формат файла
127 = Record-file is crashed Файл записей поврежден 132 = Old database file Файл из старой базы данных
4.6. Предотвращение аварий и восстановление системы
331
134 = Record was already deleted (or record f i l e crashed) Запись уже удалена (или файл записей поврежден) 135 = No more room in record f i l e В файле записей больше нет места 136 = No more room in index f i l e В индексном файле больше нет места 141 = Duplicate unique key or constraint on write or update Дублирование уникального ключа или ограничения по записи или по обновлению 144 = Table is crashed and l a s t repair failed Таблица повреждена и последняя операция по исправлению не была успешной 145 = Table was marked as crashed and should be repaired Таблица помечена как поврежденная и подлежит восстановлению Обратите внимание, что ошибки с номерами 135 ("В файле записей больше нет места") и 136 ("В индексном файле больше нет места") не являются ошибками, от которых можно избавиться с помощью простой операции исправления. В таком случае придется воспользоваться оператором ALTER TABLE, чтобы увеличить значения табличных ОПЦИЙ MAX_ROWS И AVG_ROW_LENGTH: ALTER TABLE имя_таблицы
MAX_ROWS=xxx
AVG_ROW_LENGTH=yyy;
Если текущие значения опций таблицы не известны, воспользуйтесь оператором SHOW CREATE TABLE имя_таблицы. Остальные ошибки требуют только выполнения операции по исправлению. myisamchk обычно может определить и исправить большую часть встречающихся неполадок. Процесс исправления включает до четырех стадий, которые описаны ниже. Прежде чем приступить к выполнению операции по исправлению, следует изменить местоположение каталога базы данных и проверить права доступа к файлам таблиц. В среде Unix убедитесь, что они доступны по чтению для пользователя, от имени которого запускается mysqld (а также вам, поскольку вам понадобится доступ к проверяемым файлам). Если появится необходимость в изменении файлов, у вас также должен быть к ним и доступ по записи. Опции myisamchk и isamchk для обслуживания таблиц описаны ранее в разделе 4.6.2. Ниже рассматриваются случаи, когда предложенные опции не действуют или если появляется необходимость пользоваться расширенными возможностями, предоставляемыми утилитами myisamchk и isamchk. При намерении осуществлять исправление таблиц из командной строки, первым делом обязательно следует остановить сервер. Обратите внимание, что когда mysqladmin shutdown выполняется на удаленном сервере, сервер mysqld еще некоторое время после возврата mysqladmin продолжает функционировать, пока не будут остановлены все запросы и все ключи не будут записаны на диск. Стадия 1: проверка таблиц Запустите myisamchk * .MYI или, при наличии времени, myisamchk -e * .MYI. Используйте опцию -s (режим минимальной выдачи сообщений), чтобы излишняя информация не отображалась. Если сервер mysqld остановлен, следует применить опцию —update-state, чтобы myisamchk начала отмечать таблицы как 'checked' ('проверенные').
Глава 4. Администрирование баз данных
332
Исправлению подлежат только те таблицы, для которых myisamchk выдает ошибку. В этом случае переходите к стадии 2. При получении "странных" ошибок (таких как "недостаточно памяти") или аварийном прекращении работы myisamchk переходите к стадии 3. Стадия 2: простое безопасное исправление |
На заметку!
щ Чтобы максимально ускорить операцию по исправлению, необходимо при запуске myisamchk и р, isamchk установить переменные s o r t _ b u f f e r _ s i z e и k e y _ b u f f e r _ s i z e так, чтобы значение '%, каждой из них соответствовало 25% доступной памяти.
Первым делом попробуйте запустить myisamchk -r -q имя_таблицы (где -г -q обозначает режим быстрого восстановления). Это приведет к попытке исправить индексный файл без изменения файла данных. Если файл данных содержит всю необходимую информацию, и удаленные ссылки указывают на те, что нужно позиции в файле данных, опция должна сработать, в результате чего таблица будет исправлена. Тогда можно переходить к исправлению следующей таблицы. В противном случае потребуется выполнить перечисленные ниже действия: 1. Подготовьте резервную копию файла данных, прежде чем продолжать. 2. Запустите myisamchk -r имя_таблицы (где -г обозначает режим восстановления). Это очистит файл данных от некорректных и удаленных записей, а индексный файл будет создан заново. 3. Если вызов myisamchk -г имя_ та блицы не поможет, воспользуйтесь—safe-recover имя_таблицы. Режим безопасного восстановления использует старый метод восстановления, справляющийся с несколькими случаями, с которыми стандартный режим восстановления справиться не может (однако старый метод медленнее). При получении "странных" ошибок (таких как "недостаточно памяти") или аварийном прекращении работы myisamchk переходите к стадии 3. Стадия 3: исправления обычной сложности Доходить до этой стадии следует только в тех случаях, когда первый блок размером 16 Кбайт в индексном файле запорчен или содержит некорректную информацию, либо же если индексный файл вообще отсутствует. В таком случае потребуется создать новый индексный файл. Для этого необходимо выполнить следующие шаги: 1. Переместите файл данных в какое-нибудь безопасное место. 2. Используйте файл описания таблицы, чтобы создать новые (пустые) файл данных и индексный файл. shell> mysql> mysql> mysql>
mysql имя_таблицы SET AUTOCOMMIT=1; TRUNCATE TABLE имя_таблицы; quit
Если в существующей версии MySQL оператор TRANCATE TABLE не доступен, вместо него используйте DELETE FROM имя_таблицы. 3. Скопируйте старый файл данных в только что созданный новый файл данных. (Не стоит просто переносить содержимое старого файла данных в новый; лучше сохранить копию файла данных на случай, если что-нибудь пойдет не так.)
4.6. Предотвращение аварий и восстановление системы
333
Вернитесь к стадии 2. Теперь опция myisamchk -r -q имя_ та блицы должна работать. (Тем не менее, превращать все это в бесконечный цикл не следует.) Начиная с версии MySQL 4.0.2, также можно использовать оператор REPAIR TABLE имя_таблицы USE_FRM, который выполняет всю описанную процедуру автоматически. Стадия 4: исправление повышенной сложности Доходить до этой стадии следует только, если файл описания . f rm тоже запорчен. Такое не должно случаться никогда, поскольку после создания таблицы файл описания не изменяется. 1. Восстановите файл описания из резервной копии и вернитесь к стадии 3. Также можно восстановить индексный файл и вернуться к стадии 2. В последнем случае начинать следует с myisamchk -r. 2. Если резервная копия отсутствует, но вы точно знаете, как была создана таблица, создайте копию таблицы в другой базе данных. Удалите новый файл данных, затем перенесите файл описания . f rm и индексный файл из той другой базы данных в поврежденную базу данных. Тем самым вы получите новый файл описания и новый индексный файл, а файл данных .MYD при этом остается незатронутым. Вернитесь к стадии 2 и попробуйте восстановить индексный файл.
4.6.2.10. Оптимизация таблиц Чтобы объединить фрагментированные записи и ликвидировать растрачиваемое впустую пространство, появляющееся после удаления или обновления записей, запустите myisamchk в режиме восстановления: shell> myisamchk -r имя_таблицы Таким же образом таблицу можно оптимизировать и с помощью SQL-оператора OPTIMIZE TABLE. Этот оператор исправляет таблицу, анализирует ключи, а также выполняет сортировку в индексном дереве, что ускоряет поиск ключей. Возможность нежелательного взаимодействия между утилитой и сервером исключается, поскольку когда используется OPTIMIZE TABLE, сервер выполняет всю работу сам. myisamchk также предлагает и ряд других опций, которые можно применять для повышения эффективности таблицы: •
-S, —sort-index
•
-R индексное_число, —sort-лесоЫБ=индексное_число
•
-а,—analyze
Подробное описание этих опций можно найти в разделе 4.6.2.1.
4.6.3. Установка графика обслуживания таблиц Конечно, лучше выполнять проверку таблиц регулярно, а не ждать, когда появятся проблемы. Один из способов проверить и исправить таблицу My ISAM - это воспользоваться операторами CHECK TABLE и REPAIR TABLE, которые доступны, начиная с версии MySQL 3.3.16. Другой способ - это использовать утилиту myisamchk. В целях профилактики можно применять myisamchk -s. Опция -s (сокращенный вариант - - s i l e n t ) заставляет
334
Глава 4. Администрирование баз данных
myisamchk работать в режиме минимальной выдачи сообщений, при котором сообщения отображаются только в случае возникновения ошибки. Совсем не помешает проверять таблицы и при запуске сервера. Например, обычно во время обновления, когда выполняется перезагрузка машины, то без проверки всех таблиц, которых это хоть как-то могло коснуться, обойтись нельзя (такие таблицы считаются "потенциально поврежденными"). Для автоматической проверки таблиц MylSAM запустите сервер с опцией —myisam-recover, доступной, начиная с версии MySQL 3.23.25. Если версия сервера старая и не поддерживает указанную опцию, можно к mysqldsafe добавить тест, который запустит myisamchk для проверки всех таблиц, которые были изменены за последние 24 часа, если только после перезагрузки не остался старый файл .pid (файл идентификатора процесса). Обычно файл .pid создается mysqld при запуске и удаляется в случае нормального завершения работы сервера. Наличие файла .pid во время запуска системы указывает на то, что работа mysqld не была завершена корректно. А еще лучше - проверить таблицы, дата последнего изменения которых более ранняя, чем у файла .pid. Также следует проверять таблицы регулярно даже тогда, когда система функционирует нормально. В компании MySQL AB раз в неделю запускается задание сгоп, которое провернет все важные таблицы; при этом в файле crontab используется такая строка: 35 0 * * 0 /путь/к/myisamchk —fast —silent /путь/к/каталогу_данных/*/* .MYI В этом случае выводится информация обо всех поврежденных таблицах, что позволяет, при необходимости, изучить и исправить их. Поскольку неожиданных повреждений таблиц (повреждение таблиц не по причинам проблем с оборудованием) за последние несколько лет компании MySQL AB не происходило (и это истинная правда!), то выполнения проверки один раз в неделю для нас более чем достаточно. Мы рекомендуем сначала запускать myisamchk -s каждую ночь на всех таблицах, которые обновлялись за последние 24 часа до тех пор, пока вы не станете доверять MySQL настолько, насколько этой системе доверяют в MySQL AB. Обычно таблицы MySQL в частом обслуживании не нуждаются. В случае изменения таблиц с динамическим размером строк (таблиц, содержащих столбцы VARCHAR, BLOB или TEXT) или при наличии таблиц с большим количеством удаленных строк может время от времени понадобиться дефрагментация либо восстановление пространства из таблиц (возможно, раз в месяц). Сделать это можно на таких таблицах с помощью оператора OPTIMIZE TABLE. Или же, если есть возможность приостановить сервер mysqld на некоторое время, перейдите в каталог данных и выполните следующую команду (пока сервер остановлен): shell> myisamchk -r -s —sort-index -0 sort_buffer_size=16M */*.MYI Аналогичная команда используется и для таблиц ISAM: shell> isamchk -г -s —sort-index -0 sort_buffer_size=16M */*.ISM
4.6.4. Как получить информацию о таблице Чтобы получить описание таблицы или статистику по ней, используйте представленные в данном разделе команды. Некоторая информация более подробно рассматривается позже:
4.6. Предотвращение аварий и восстановление системы •
335
myisamchk -d имя_таблицы. Запускает myisamchk в "режиме описания" для составления описания таблицы. В случае, когда сервер MySQL запускался с опцией
—skip-external locking, myisamchk может выдать сообщение об ошибке для таблицы, которая обновляется во время выполнения утилиты. Однако, поскольку myisamchk не изменяет таблицу в "режиме описания", риска повреждения данных нет. •
myisamchk -d -v имя_таблицы. При добавлении -v утилита myisamchk запускается в режиме расширенных сообщений, и будет выводить более подробную информацию о том, что она делает.
•
myisamchk - e i s имя_таблицы. Отображает только наиболее важную информацию из таблицы. Эта операция выполняется медленно, поскольку считывать приходится всю таблицу целиком.
•
myisamchk - e i v имя_таблицы. Подобна опции - e i s , но только еще и информирует о том, какие выполняются действия.
Ниже представлен пример выходных данных для некоторых из этих команд. Размеры файла данных и индексного файла рассматриваемой таблицы следующие: -rw-rw-r-- I monty tcx 317235748 Jan 12 17:30 company.MYD -rw-rw-r— 1 davida tcx 96482304 Jan 12 18:35 company.MYM Пример выходных данных myisamchk -d:
MylSAM file: company.MYI Record format: Fixed length Data records: 1403698 Deleted blocks: 0 Recordlength: 226 table description: Key Start Len Index Type 1 2 8 unique double 2 15 10 multip. text packed stripped 3 219 8 multip. double 4 63 10 multip. text packed stripped 5 167 2 multip. unsigned short 6 177 4 multip. unsigned long 7 155 4 multip. text 8 138 4 multip. unsigned long 9 177 4 multip. unsigned long 193 1 text Пример выходных данных myisamchk -d -v: MylSAM file: Record format: File-version: Creation time: Recover time: Status:
company Fixed length 1 1999-10-30 12:12:51 1999-10-31 19:13:01 checked
Data records: 1403698 Deleted blocks: 0 Datafile parts: 1403698 Deleted data: 0 Datafile pointer (bytes): 3 Keyfile pointer (bytes): 3 Max datafile length: 3791650815 Max keyfile length: 4294967294 Recordlength: 226
336
Глава 4. Администрирование баз данных
table description: Key Start Len Index Type Rec/key 1 2 8 unique double 1 2 2 15 10 multip. text packed stripped 73 3 219 8 multip. double 10 multip. text packed stripped 5 4 63 5 167 2 multip. unsigned short 4840 6 177 4 multip. unsigned long 1346 7 155 4 multip. text 4995 8 138 4 multip. unsigned long 87 9 177 4 multip. unsigned long 178 193 1 text
Root Blocksize 15845376 1024 25062400 1024 40907776 1024 1024 48097280 55200768 1024 1024 65145856 75090944 1024 85036032 1024 96481280 1024
Пример выходных данных myisamchk -eis: Checking MylSAM file: company Key: 1: Keyblocks used: 97% Packed: 0% Max levels: 4 Key: 2: Keyblocks used: 98% Packed: 50% Max levels: 4 Key: 3: Keyblocks used: 97% Packed: 0% Max levels: 4 Key: 4: Keyblocks used: 99% Packed: 60% Max levels: 3 Key: 5: Keyblocks used: 99% Packed: 0% Max levels: 3 Key: 6: Keyblocks used: 99% Packed: 0% Max levels: 3 Key: 7: Keyblocks used: 99% Packed: 0% Max levels: 3 Key: 8: Keyblocks used: 99% Packed: 0% Max levels: 3 Key: 9: Keyblocks used: 98% Packed: 0% Max levels: 4 Total: Keyblocks used: 98% Packed: 17% Records : 1403698 M.recordlength:: 226 Packed: 0% Recordspace used: 100% Empty space: 0% Blocks/Record: 1.00 Record blocks: 1403698 Delete blocks: 0 Recorddata: 317235748 Deleted data: 0 Lost space: 0 Linkdata: 0 User time 1626.51, System time 232.36 Maximum resident set size 0, Integral resident set size 0 Non physical pagefaults 0, Physical pagefaults 627, Swaps 0 Blocks in 0 out 0, Messages in 0 out 0, Signals 0 Voluntary context switches 639, Involuntary context switches 28966 Пример выходных данных myisamchk -eiv: Checking MylSAM file: company Data records: 1403698 Deleted blocks: - check file-size - check delete-chain block_size 1024: index 1: index 2: index 3: index 4: index 5: index 6: index 7:
0
4.6. Предотвращение аварий и восстановление системы
337
index 8: index 9: No recordlinks - check index reference - check data record references index: 1 Key: 1: Keyblocks used: 97% Packed: 0% Max levels: 4 - check data record references index: 2 Key: 2: Keyblocks used: 98% Packed: 50% Max levels: 4 - check data record references index: 3 Key: 3: Keyblocks used: 97% Packed: 0% Max levels: 4 - check data record references index: 4 Key: 4: Keyblocks used: 99% Packed: 60% Max levels: 3 - check data record references index: 5 Key: 5: Keyblocks used: 99% Packed: 0% Max levels: 3 - check data record references index: 6 Key: 6: Keyblocks used: 99% Packed: 0% Max levels: 3 - check data record references index: 7 Key: 7: Keyblocks used: 99% Packed: 0% Max levels: 3 - check data record references index: 8 Key: 8: Keyblocks used: 99% Packed: 0% Max levels: 3 - check data record references index: 9 Key: 9: Keyblocks used: 98% Packed: 0% Max levels: 4 Total: Keyblocks used: 9% Packed: 17% - check records and index references [LOTS OF ROW NUMBERS DELETED] Records: 1403698 M.recordlength: 226 Packed: 0% Recordspace used: 100% Empty space: 0% Blocks/Record: 1.00 Record blocks: 1403698 Delete blocks: 0 Recorddata: 317235748 Deleted data: 0 Lost space: 0 Linkdata: 0 User time 1639.63, System time 251.61 Maximum resident set size 0, Integral resident set size 0 Non physical pagefaults 0, Physical pagefaults 10580, Swaps 0 Blocks in 4 out 0, Messages in 0 out 0, Signals 0 Voluntary context switches 10604, Involuntary context switches 122798 Н и ж е дается объяснение типов выдаваемой myisamchk информации. "Keyfile" относится к индексному файлу. "Record" (запись) и "row" (строка) являются синонимами. • MylSAM file. И м я (индексного) файла MylSAM. • File-version. Версия формата MylSAM. Н а настоящий момент всегда 2. • Creation time. Когда в последний раз восстанавливался индексный файл/файл данных. • Data records. Количество записей в таблице. • Deleted blocks. Количество удаленных блоков, которые по-прежнему имеют зарезервированное для них пространство. М о ж н о оптимизировать таблицу, чтобы свести такое пространство к минимуму. См. раздел 4.6.2.10.
338
Глава 4. Администрирование баз данных
• Datafile parts. Для динамического формата записей это означает количество имеющихся блоков данных. Для оптимизированной таблицы, не содержащей фрагментированных записей, это то же самое, что Data records. •
Deleted data. Количество байт удаленных данных, которые не восстанавливались. Можно оптимизировать таблицу, чтобы свести такое пространство к минимуму. См. раздел 4.6.2.10.
•
Datafile pointer. Размер (в байтах) указателя файла данных. Обычно это 2, 3, 4 или 5 байт. Большинство таблиц работает с 2 байтами, но пока управлять данным значением из MySQL невозможно. Для фиксированных таблиц - это адрес записи, для динамических таблиц - адрес байта.
• Keyf i l e pointer. Размер (в байтах) указателя индексного файла. Обычно значение соответствует 1, 2 или 3 байтам. Большинство таблиц работает с 2 байтами, но этот размер вычисляется MySQL автоматически. Это всегда адрес блока. • Max datafile length. Насколько большим может быть размер файла данных таблицы (в байтах). • Max keyf i l e length. Насколько большим может быть размер индексного файла (в байтах). • Recordlength. Объем занимаемого каждой отдельной записью пространства (в байтах). • Record format. Формат, используемый для хранения табличных строк. В предложенных выше примерах использовался формат Fixed length. Другие возможные форматы - Compressed и Packed. • table description. Список всех ключей в таблице. Для каждого ключа myisamchk отображает некоторую информацию более низкого уровня: • Key. Номер данного ключа. •
Start. Где в записи начинается данная часть индекса.
•
Len. Длина данной части индекса. Для упакованных чисел это значение всегда должно соответствовать полной длине столбца. Для строк это значение может быть меньше полной длины индексированного столбца, поскольку есть возможность проиндексировать префикс строкового столбца.
•
Index. Допустимо ли в индексе многократное повторение значения ключа. Типы значений - unique и multiple.
•
Туре. Тип данных в данной части индекса. Это тип данных MylSAM. Возможные значения - packed, stripped или empty.
•
Root. Адрес корневого индексного блока.
•
Blocksize. Размер каждого индексного блока. По умолчанию составляет 1024, но значение может быть изменено во время компиляции в случае построения MySQL из исходного кода.
•
Rec/key. Это статистическое значение, используемое оптимизатором. Оно обозначает число записей на одно значение для данного ключа. Уникальному ключу всегда соответствует значение 1. Значение можно обновить после загрузки таблицы (или внесения в нее значительных изменений) с помощью myisamchk -a. Если его вообще не обновлять, по умолчанию будет присвоено значение 30.
4.6. Предотвращение аварий и восстановление системы
339
В таблице, рассматриваемой в примерах, девятому индексу соответствуют две строки table description. Это означает то, что данный индекс не является уникальным, а состоит из двух частей. •
Keyblocks used. Процент используемых ключей. Сразу после реорганизации таблицы с помощью myisamchk (как и в случае с таблицей, которая рассматривалась в примерах) значения крайне высоки (очень близки к теоретическому максимуму).
•
Packed (первое вхождение). MySQL пытается упаковать ключи с общим суффиксом. Может использоваться только для индексов в столбцах CHAR, VARCHAR или DECIMAL. Для длинных индексованных строк, имеющих схожие части слева, это позволяет существенно сократить объем занимаемого ими пространства. В третьем приводимом выше примере четвертый ключ включает 10 символов, и занимаемое им пространство уменьшено на 60%.
•
Max levels. Насколько глубоким является В-дерево для данного ключа. Для больших таблиц с длинными ключами значения Max levels будут высокими.
•
Records. Количество строк в таблице.
•
M.recordlength. Средняя длина записи. Это точная длина для таблиц с записями фиксированной длины, потому что в таких таблицах все записи имеют одинаковую длину.
•
Packed (второе вхождение). MySQL удаляет пробелы в конце строк. Значение Packed обозначает процент сэкономленного этим пространства.
•
Recordspace used. Какой процент файла данных используется.
•
Empty space. Какой процент файла данных не используется.
•
Blocks /Record. Среднее число блоков, приходящихся на одну запись (то есть количество ссылок, из которых состоит фрагментированная запись). Для таблиц фиксированного формата данное значение всегда составляет 1.0. Оно должно оставаться близким к 1.0 настолько, насколько это возможно. Если значение становится слишком большим, можно приступать к реорганизации таблицы.
•
Recordblocks. Количество используемых блоков (ссылок). Для фиксированного формата это значение будет совпадать с количеством записей.
•
Deleteblocks. Количество удаленных блоков (ссылок).
•
Recorddata. Сколько байтов в файле данных используется.
•
Deleted data. Сколько байтов в файле данных удалено (не используется).
•
Lost space. Если после обновления запись становится короче, некоторое пространство теряется. Данное значение отображает общую сумму утраченного в таких случаях пространства (в байтах).
•
Linkdata. Когда используется динамический формат таблиц, фрагменты записи объединяются посредством указателей (от 4 до 7 байт каждый). Linkdata отображает суммарный объем памяти, используемый такими указателями.
В случае сжатия таблицы с помощью myisampack опция myisamchk -d будет выводить дополнительную информацию о каждом столбце таблицы. Пример информации подобного рода и описание того, что она означает, можно найти в разделе 7.2.
340
Глава 4. Администрирование баз данных
4.7. Локализация MySQL и интернациональное применение 4.7.1. Набор символов для представления данных и сортировки По умолчанию MySQL использует набор символов ISO-8859-1 (Latin 1) с сортировкой в соответствии со шведскими/финскими правилами. Такой набор подходит для применения в США и большей части стран Западной Европы. Все бинарные дистрибутивы MySQL компилируются с —with-extra-charsets= complex. При этом во все стандартные программы добавляется код, который позволяет им работать с набором символов l a t i n l и многобайтными наборами символов в MySQL. Остальные наборы символов по необходимости загружаются из специального файла определений. Набор символов определяет, какие символы разрешается использовать в именах, а также то, каким образом будут сортироваться строки во время применения конструкций ORDER BY И GROUP BY оператора SELECT. С помощью опции --default-character-set можно изменять набор символов во время запуска сервера. Доступные наборы символов можно найти через опции configure: —with-charset=na6op и -with-extra-charsets=cnncofc-Ha6opoB | complex I a l l I none или в конфигурационных файлах наборов символов, перечисленных в КАТАЛ0Г_0БЩЕГ0_ИСП0ЛЬ30ВАНИЯ/charsets/Index. См. раздел 2.3.2.
Начиная с версии MySQL 4.1.1, при запуске сервера можно также изменить и тип сопоставления в наборе символов с помощью опции —default-collation. Однако этот тип сопоставления должен быть допустимым для набора символов по умолчанию. (Используйте оператор SHOW COLLATION для определения доступных типов сопоставления для каждого набора.) См. раздел 2.3.2. Если изменить набор символов во время работы MySQL, это может привести и к изменению порядка сортировки. Поэтому необходимо запустить myisamchk -r -q —setcharacter-set=Ha6op на всех таблицах, иначе не исключено некорректное упорядочивание индексов. При подключении клиента к серверу MySQL сервер указывает клиенту, какой набор символов по умолчанию используется. На время данного соединения клиент переключается на этот набор. Во время отмены управляющих символов в строках для SQL-запроса следует использовать функцию mysql_real_escape_string(). Она идентична старой функции mysql_escape_string(), но только в качестве первого параметра в ней выступает идентификатор соединения MySQL, так что при отмене управляющих символов учитывается и соответствующий набор символов. Во время компиляции клиента, когда были указаны другие пути, отличные от путей к каталогам, в которые устанавливался сервер, и когда пользователь, проводивший конфигурацию MySQL, не включил все наборы символов в двоичный файл MySQL, обязательно следует сообщить клиенту, где искать дополнительные наборы символов, которые могут ему понадобиться, если сервер работает с отличным от набора клиента набором символов.
4.7. Локализация MySQL и интернациональное применение
341
Это можно сделать с помощью опции — character-sets-dir, указав в ней путь к каталогу, в котором хранятся динамические наборы символов MySQL. Например, добавьте в файл опций следующую строку: [client] character-sets-dir=/usr/local/mysql/share/mysql/charsets Можно также заставить клиента использовать какой-нибудь определенный набор символов следующим образом: [client] default-character-set=Ha6op Однако обычно необходимости в этом нет.
4.7.1.1. Использование набора символов немецкого языка Чтобы сортировка происходила в соответствии с символами немецкого алфавита, следует запустить mysqld с опцией —default-characterset=latinl_de. Это влияет на поведение сервера следующим образом: • Во время сортировки и сравнения строк, перед тем как непосредственно выполнить сравнение, происходит следующее преобразование символов: а -> ае б -> ое и -> ие В -> ss • Все символы с ударением преобразуются в свои аналоги без ударения верхнего регистра. Абсолютно все буквы преобразуются в верхний регистр. • При сравнении строк с помощью LIKE преобразование символов из одного в два не происходит. Все буквы преобразуются в верхний регистр. Ударения удаляются со всех букв, кроме U, и, 0, б, А и а.
4.7.2. Установка языка сообщений об ошибках По умолчанию mysqld выдает сообщения об ошибках на английском языке, но они также могут отображаться и на одном из следующих языков: чешском, датском, голландском, эстонском, французском, немецком, греческом, венгерском, итальянском, японском, корейском, норвежском, новонорвежском, польском, португальском, румынском, русском, словацком, испанском и шведском. Чтобы задать определенный язык для сообщений об ошибках во время запуска mysqld, воспользуйтесь опцией —language или -L. В качестве значения этой опции можно указать как название языка, так и полный путь к файлу сообщений об ошибках, например: shell> mysqld —language=swedish
или: shell> mysqld —language=/usr/local/share/swedish Название языка необходимо вводить в нижнем регистре. Файлы языков находятся (по умолчанию) в папке share/ЯЗЫК базового каталога MySQL.
342
Глава 4. Администрирование баз данных
Чтобы изменить файл сообщений об ошибках, необходимо отредактировать файл errmsg. txt, а затем для создания файла errmsg. sys выполнить следующую команду: shell> comp_err errmsg.txt errmsg.sys При обновлении версии MySQL не забудьте повторно внести эти же изменения в новый файл errmsg.txt.
4.7.3. Добавление нового набора символов В данном разделе описываете* процедура по добавлению в MySQL другого набора символов. Представленные ниже действия применимы, только если установлен исходный дистрибутив MySQL. Чтобы выбрать подходящий способ, прежде всего, потребуется определить, добавляемый набор символов является простым или сложным: • Набор символов, при работе с которым не нужны ни специальные операции по упорядочиванию строк для сортировки, ни поддержка многобайтных символов, является простым. • Набор символов, при работе с которым такие возможности (хотя бы одна из них) необходимы, является сложным. Например, наборы символов l a t i n l и danish - простые, в то время как big5 и czech - сложные. В следующих примерах название набора символов представлено как MYSET. Чтобы добавить простой набор, необходимо выполнить перечисленные ниже действия. 1. Добавьте MYSET в конец файла sql/share/charsets/Index и назначьте для него уникальный номер. 2. Создайте файл sql/share/charsets/MYSET.conf. (В качестве основы для данного файла можно использовать копию sql/share/charsets/latinl. conf.) Синтаксис для создания этого файла крайне прост: • Комментарии начинаются с символа ' # ' и вводятся до конца строки. • Слова отделяются друг от друга любым количеством пробелов. •
При определении набора символов каждое слово должно быть представлено в виде шестнадцатеричного числа. • Массив ctype - это первые 257 слов. Затем идут массивы to_lower[], to__upper [ ] и sort_order [ ], которые занимают по 256 слов каждый. См. раздел 4.7.4.
3. Добавьте название набора символов в списки CHARSETS_AVAILABLE и COMPILED_CHARSETS файла conf igure. in. 4. Повторно сконфигурируйте, скомпилируйте и протестируйте систему. Для добавления сложного набора символов потребуется сделать следующее: 1. Создайте файл strings/ctype-MySET. с в исходном дистрибутиве MySQL. 2. Добавьте MYSET в конец файла sql/share/charsets/Index и назначьте для него уникальный номер.
4.7. Локализация MySQL и интернациональное применение
343
3. Просмотрите один из существующих файлов ctype-*.c (например, strings/ ctype-big5. с) с целью выяснения, что же необходимо определить. Обратите внимание на то, что имена массивов в файле должны выглядеть примерно следующим образом: ctype_MYS£T, t o_l о we r J4YSET и так далее. Они соответствуют именам массивов для простого набора символов. См. раздел 4.7.4. 4. Где-то в начале файла вставьте комментарий, подобный приведенному ниже: /* * Данный комментарий анализируется программой configure для * создания файлов типа ctype.c, поэтому не изменяйте его, * не будучи уверенными в том, что делаете. * .configure, number_MYSET=MYNUMBER * .configure. strxfrm_multiply_Mir5ET=N * .configure. mbmaxlen_MYSET=N */ Программа configure использует данный комментарий для автоматического включения набора символов в библиотеку MySQL. Строки strxfrmjnultiply и mbmaxlen объясняются ниже. Вводить их нужно только при необходимости в наличии функций по упорядочиванию строк или функций поддержки многобайтных наборов символов соответственно. 5. Затем потребуется создать некоторые из следующих функций: • my_strncoll_MYS£T() • my_strcoll_MYS£r() • my_strxfim_MYSET() • my_like_range_MYS£T() См. раздел 4.7.5. 6. Добавьте название набора символов в списки CHARSETS_AVAILABLE COMPILED_CHARSETS файла configure.in. 7. Повторно сконфигурируйте, скомпилируйте и протестируйте систему. 8. В файле sql/share/charsets/README содержатся дополнительные инструкции.
и
При желании, чтобы тот или иной набор символов был включен в дистрибутив MySQL, можно отправить исправление с ним в список рассылки MySQL internals. См. раздел 1.7.1.1.
4.7.4. Массивы определения символов Массивы to_lower [ ] и to_upper [ ] являются простыми и содержат символы верхнего и нижнего регистров, соответствующие каждому символу из того или иного набора, например: to_lower [' А1 ] должен содержать ' а' to_upper [' а' ] должен содержать ' А' s o r t o r d e r [ ] представляет собой карту, указывающую, каким образом символы должны упорядочиваться при их сортировке и сравнении. Достаточно часто (но не для всех наборов символов) значение sort_order[] эквивалентно значению to_upper[], то есть в таком случае регистр во время сортировки не учитывается. MySQL выполняет
344
Глава 4. Администрирование баз данных
сортировку символов, основываясь на значениях элементов s o r t o r d e r [ ]. Правила сортировки более подробно рассматриваются в описании функции по упорядочиванию строк в разделе 4.7.5. с type [ ] - массив битовых значений, где на каждый символ приходится один элемент. (Обратите внимание, что to_lower[], to_upper[] и sort_order[] индексируются по значению символа, a ctype[] - по значению символа плюс 1. Это давно принятые условные обозначения, позволяющие работать с признаком конца файла EOF). В файле mctype .h можно найти следующие определения битовых масок: #define U 01 #define L 02 #define N 04 #define _S 010 Idefine _P 020 #define С 040 #define в 0100 #define X 0200
/* /* /* /* /* /* /* /*
Верхний регистр */ Нижний регистр */ Цифра */ Пробельный символ */ Знак пунктуации */ Управляющий символ */ Пробел */ Шестнадцатеричная цифра */
Запись с type [ ] для каждого символа должна объединять в себе все подходящие значения битовых масок, которые его описывают. Например, 'А' является символом верхнего регистра, а также шестнадцатеричной цифрой (_х), поэтому ctype['A'+l] должна содержать следующее значение: _U + _Х = 01 + 0200 = 0201
4.7.5. Поддержка функций по упорядочиванию строк Если правила сортировки для используемого языка слишком сложны, чтобы обрабатываться с помощью sort_order [ ], понадобятся функции по упорядочиванию строк. На настоящий момент лучшей документацией по этому вопросу являются уже внедренные наборы символов. Для примера см. наборы big5, czech, gbk, s j i s и tisl60. В специальном комментарии, который размещается в начале файла, необходимо указать значение strxfrm_multiply _MYSET=N. Для N выбирается значение, соответствующее максимуму, который могут достигать строки во время выполнения my_strxfrm_MYSET (это должно быть положительное целое число).
4.7.6. Поддержка многобайтных символов Если есть необходимость обеспечить поддержку для нового набора символов, который включает многобайтные символы, потребуется использование специальных функций. На настоящий момент лучшей документацией по этому вопросу являются уже внедренные наборы символов. Для примера см. наборы символов euc_kr, gb2312, gbk, sjis и u j is. Эти наборы находятся в файлах ctype-' набор'. с каталога strings. В специальном комментарии, который размещается в начале исходного файла, необходимо указать значение mbmaxlen_MYSET=N. Для N выбирается значение, соответствующее размеру (в байтах) самого большого символа в наборе.
4.7.7. Проблемы с наборами символов При попытке использовать набор символов, который не компилировался в вашу библиотеку, можно столкнуться со следующими проблемами:
345
4.8. Журнальные файлы MySQL •
В используемой программе указан неправильный путь к каталогу, в котором хранятся наборы символов (По умолчанию это каталог /usr/local/mysql/share/ mysql/charsets). Исправить такую ошибку можно, указав опцию —characters e t s - d i r при запуске данной программы.
•
Необходимый набор символов является многобайтным набором, динамическая загрузка которого невозможна. В таком случае потребуется выполнить повторную компиляцию программы, включив поддержку данного набора.
•
Необходимый набор символов является динамическим набором, но конфигурационный файл для него отсутствует. В таком случае потребуется установить такой файл для данного набора символов из нового дистрибутива MySQL.
•
Если в имеющемся индексном файле не содержится имя для данного набора символов, программа выдаст следующее сообщение об ошибке: ERROR 1105: File '/usr/local/share/mysql/charsets/?.conf (Errcode: 2)
not found
В таком случае потребуется либо установить новый файл Index, либо вручную добавить в имеющийся файл название любого из недостающих наборов символов. Для таблиц My ISAM проверить название и номер используемого в данной таблице набора символов можно с помощью myisamchk -dvv имя_таблицы.
4.8. Журнальные файлы MySQL MySQL поддерживает несколько разных журнальных файлов, которые могут помочь узнать, что происходит внутри mysqld (табл. 4.9): Таблица 4.9. Журнальные файлы MySQL Журнальный файл
Тип заносимой в файл информации
Журнал ошибок
Регистрирует все ошибки, происходящие во время запуска, работы или остановки сервера.
Журнал таблиц ISAM
Регистрирует все вносимые в таблицы ISAM изменения. Используется только для отладки кода isam.
Журнал запросов
Регистрирует все установленные клиентом соединения и выполненные операторы.
Журнал регистрации обновлений
Регистрирует операторы, которые приводят к изменению данных. Этот журнал устарел.
Бинарный журнал регистрации
Регистрирует все операторы, которые приводят к изменению данных. Также используется при репликации.
Журнал медленных запросов
Регистрирует все запросы, выполнение которых заняло больше, чем указано в long_query_time, секунд, или запросы, которые не использовали индексов.
По умолчанию все журналы создаются в каталоге данных mysqld. Заставить mysqld закрыть и открыть журнальные файлы заново (а в некоторых случаях - переключится на новый журнал) можно с помощью оператора FLUSH LOGS или команд mysqladmin f l u s h - l o g s и mysqladmin r e f r e s h .
346
Глава 4. Администрирование баз данных
Если используются предлагаемые MySQL возможности репликации, тогда подчиненным сервером также будут поддерживаться и дополнительные журнальные файлы, называемые журналами ретрансляции. Такие журналы более подробно рассматриваются в главе 5.
4.8.1. Журнал ошибок Файл журнала ошибок содержит информацию о том, когда запускался и останавливался сервер, а также любые ошибки, возникшие во время его работы. Если произойдет неожиданное отключение сервера и mysqld_saf e понадобится перезапустить его, то mysqld_safe внесет в журнал ошибок соответствующую запись. Когда mysqld сталкивается с таблицей, которая нуждается в автоматической проверке или исправлении, сообщение об этом будет также занесено в журнал ошибок. В некоторых операционных системах журнал ошибок будет еще содержать и данные трассировки стека, если произойдет аварийное отключения сервера. Такие данные могут быть использованы для определения, где именно произошел сбой. Начиная с версии MySQL 4.0.10, с помощью опции —log-error [=имя_файла] можно задавать каталог, в котором mysqld должен хранить файл журнала ошибок. Если значение имя_файла не указано, mysqld использует имя имя_хоста. err и заносит этот файл в каталог данных. (В версиях ниже MySQL 4.0.10 для Windows имя журнала ошибок соответствует mysql.err.) При применении оператора FLUSH LOGS файл журнала ошибок будет переименован и сохранен с префиксом -old, a mysqld создаст новый пустой журнальный файл. В более старых версиях MySQL, используемых в системах Unix, для работы с журналом ошибок применялась опция mysqld_safe, которая выполняла перенаправление файла ошибок в имя_хоста.еп. Изменить такое имя файла можно, задав для mysqld_safe опцию —егг1од=имя_файла. Если не указывать —log-error или (в Windows) использовать опцию —console, ошибки будут заноситься в stderr (обычно это ваш терминал). В Windows ошибки всегда записываются в файл .err, если не была задана опция —console.
4.8.2. Общий журнал запросов При желании знать обо всем, что происходит внутри mysqld, следует запускать сервер с опцией —1 од[=имя_файла] или -1 [имя_файла]. (Если не указать значение имя_файла, будет по умолчанию использоваться имя имя_хоста. log). В таком случае все устанавливаемые соединения и выполняемые операторы будут регистрироваться в журнале запросов. Такой журнал может очень пригодиться, если есть подозрение о наличии у клиента ошибки и желании точно узнать, какие именно данные клиент отослал на mysqld. Более старые версии сценария mysql.server (начиная с MySQL 3.23.4 и до MySQL 3.23.8) передают safe_mysqld опцию —log, чтобы активизировать общий журнал запросов. Если необходима большая степень производительности при внедрении MySQL в производственную среду, можно удалить опцию —log из сценария mysql.server или заменить ее опцией --log-bin. См. раздел 4.8.4. mysqld записывает операторы в журнал запросов в том порядке, котором он их получает. Такой порядок может отличаться от порядка, в котором эти операторы выполняют-
4.8. Журнальные файлы MySQL
347
ся. Этим журнал запросов и отличается от бинарного журнала регистрации и журнала обновлений, которые заполняются после того, как обработан запрос, но перед тем, как будет отменена любая из блокировок. Перезапуск сервера и очистка журнала не приводят к созданию нового файла для общего журнала запросов (хотя команда FLUSH LOG закрывает и открывает журнал снова). В Unix можно переименовать файл или создать новый, используя следующие команды: shell> mv имя__хоста.log имя^хоста-old.log
shell> mysqladmin flush-logs
shell> cp имя_хоста-old.log каталог-резервных-копий shell> rm имя_хоста-old.log В Windows переименовать файл журнала, пока он открыт сервером, нельзя. Сначала следует остановить сервер, присвоить журналу новое имя, а затем перезапустить сервер для создания нового журнального файла.
4.8.3. Журнал регистрации обновлений |
На заметку!
I I Журнал регистрации обновлений устарел и был заменен бинарным журналом регистрации. См. |; раздел 4.8.4. Бинарный журнал обеспечивает выполнение всех тех же операций (и даже боль{I ше), что и журнал обновлений. Журнал обновлений недоступен, начиная с версии MySQL 5.O.O.
При запуске с опцией —log-update [=имя_файла] сервер mysqld создает журнальный файл, в котором будут содержаться все SQL-операторы, изменяющие данные. Если значение имя_файла не указано, для него по умолчанию будет использоваться имя хоста. Если значение имя^файла задано, но в нем не указан начальный путь к файлу, журнал будет занесен в каталог данных. Если имя_файла не имеет расширения, mysqld создает журнальные файлы с именами типа имя_файла.###, где ### представляет собой номер, увеличивающийся каждый раз при запуске сервера или выполнении команд по очистке журналов (FLUSH LOGS, mysqladmin flush-logs и mysqladmin refresh). I
На заметку!
Щ Ш
Чтобы такая схема присвоения имен работала, не следует создавать свои собственные файлы с именами, совпадающими с теми, которые могут использоваться для списка журнальных файлов.
Процесс регистрации обновлений носит интеллектуальный характер, потому что в журнал заносятся только операторы, которые действительно обновляют данные. Таким образом, операторы UPDATE или DELETE, конструкция WHERE которых не находит подходящих строк, в журнале не регистрируются. Также пропускаются даже те операторы UPDATE, которые присваивают столбцу уже имеющееся у него значение. Данные регистрируются в журнале обновлений сразу же после завершения обработки того или иного запроса, но прежде чем будет снята любая блокировка или зафиксирована любая транзакция. Это гарантирует занесение операторов в журнал только в порядке их выполнения. При желании обновить базу данных через файлы журнала обновлений можно сделать следующее (предполагается, что имена журналов обновлений имеют вид имя_файла . # # # ) : shell> Is - I - t -г имя_файла.[0-9]* | xargs cat | mysql Is используется для сортировки имен журнальных файлов в правильном порядке.
348
Глава 4. Администрирование баз данных
Это может пригодиться, если придется после аварии вернуться к резервной копии файлов, а затем повторно применить обновления, которые были внесены между датой создания резервной копии и датой аварии.
4.8.4. Бинарный журнал регистрации Бинарный журнал регистрации заменил собой старый журнал регистрации обновлений, который стал недоступным, начиная с версии MySQL 5.O. Вся информация журнала обновлений сохраняется в бинарном журнале в более эффективном формате и более безопасным способом. В бинарный журнал, подобно журналу обновлений, заносятся только операторы, которые действительно изменяют данные. Таким образом, операторы UPDATE или DELETE, конструкция WHERE которых не находит подходящих строк, в журнале не регистрируются. Также пропускаются даже те операторы UPDATE, которые присваивают столбцу уже имеющееся у него значение. Бинарный журнал содержит информацию и о том, сколько времени заняло выполнение каждого оператора, посредством которого были внесены изменения в базу данных. Операторы, не изменяющие никаких данных, в таком журнале не регистрируются. Если есть необходимость в регистрации абсолютно всех операторов (например, чтобы была возможность определить запрос, обработка которого оказалась проблематичной), в этих целях использоваться должен общих журнал запросов. См. раздел 4.8.2. Основное предназначение бинарного журнала - это предоставить возможность обновить базу данных во время операции восстановления настолько подробно, насколько это возможно, поскольку именно в бинарном журнале будут содержаться все обновления, произошедшие после того, как была сделана резервная копия всей системы. Бинарный журнал также используется на главных серверах в качестве списка операторов, которые подлежат отправке на подчиненные серверы. См. главу 5. Активизация бинарного журнала регистрации снижает производительность сервера на 1%. Однако предоставляемые таким журналом преимущества во время проведения операций по восстановлению или настройки репликации, в целом значительно перевешивают этот маленький недостаток. При запуске с опцией --log-bin [=имя_файла]сервер mysqld создает журнальный файл, в котором будут сохраняться все SQL-команды, обновляющие данные. Если значение имя_файла не указано, для него по умолчанию будет использоваться имя хоста с суффиксом -bin на конце. Если значение имя_файла задано, но пути оно не содержит, файл будет занесен в каталог данных. Если в имени журнального файла указать расширение (например, —log-bin= имя_файла. расширение), оно будет без предупреждения удалено и проигнорировано. mysqld присоединяет в конец имени бинарного журнала расширение в виде числа, а именно номера. Этот номер увеличивается каждый раз при перезапуске сервера или выполнении команд по очистке журналов (FLUSH LOGS, mysqladmin flush-logs и mysqladmin refresh). Новый бинарный журнал регистрации создается автоматически, когда размер текущего журнала достигает максимума, заданного в max__binlog_size. При использовании больших транзакций размер бинарного журнала может достигать и больших, чем указано в m a x b i n l o g s i z e размеров: каждая такая транзакция регистрируется в журнале целиком и никогда не распределяется между несколькими журналами.
4.8. Журнальные файлы MySQL
349
Чтобы получить возможность знать, какие файлы каких бинарных журналов применялись, mysqld также создает и индексный файл, в котором содержатся имена всех используемых файлов бинарного журнала. По умолчанию ему присваивается имя, такое же, как у файла бинарного журнала, но с расширением ' .index 1 . Изменять имя индексного файла бинарного журнала можно с помощью опции —log-bin-index= [имя_файла]. Во избежание путаницы редактировать этот файл вручную во время работы mysqld нельзя. Для удаления всех файлов бинарных журналов используется оператор RESET MASTER, а для удаления лишь некоторых из них - PURGE MASTER LOGS. Чтобы контролировать заносимые в бинарный журнал данные, можно применять следующие опции (также следует ознакомиться с пояснениями, идущими после данного списка): • —binlog-do-6Ъ=имя_базы_данных. Указывает главному серверу заносить обновления в бинарный журнал, если текущей базой данных (то есть базой данных, выбранной с помощью USE) является имя_базы_данных. Все остальные, не упомянутые явно, базы данных игнорируются. При использовании этой опции необходимо проверить, чтобы обновления выполнялись только в текущей базе данных. Ниже приводится пример того, что не работает так, как ожидается. В случае, когда сервер был запущен с опцией binlog-do-db=sales и выполняется оператор USE prices; UPDATE sales.January SET amount=amount+1000; •
в бинарный журнал этот оператор занесен не будет. —Ып1од-1дпоте-6Ь=имя_базы_данных. Указывает главному серверу не сохранять обновления в бинарном журнале, если текущей базой данных (то есть базой данных, выбранной через USE) является имя_базы_данных. При использовании этой опции необходимо проверить, чтобы обновления выполнялись только в текущей базе данных. Ниже приводится пример того, что не работает так, как ожидается. В случае, когда сервер был запущен с опцией binlog-ignore-db=sales и выполняется оператор USE prices; UPDATE sales.January SET amount=amount+1000; этот оператор будет занесен в бинарный журнал.
Чтобы регистрировать или игнорировать обновления сразу нескольких баз данных, задайте соответствующую опцию необходимое число раз, по одному для каждой базы данных. Правила, по которым обновления будут регистрироваться в бинарном журнале или игнорироваться, анализируются системой в следующем порядке: 1. Установлены ли правила с помощью —Ь1п1од-йо^Ь=имя_базь/_даняых или •
Если нет, записать оператор в бинарный журнал и завершить работу.
•
Если да, перейти к следующему шагу.
2. Определенные правила (—binlog-do-db= имя_базы_данных или —binlog-ignore6Ъ=имя_базы_данных) установлены. Имеется ли текущая база данных (была ли какая-нибудь база данных выбрана при помощи USE?)? • Если нет, не записывать оператор в бинарный журнал и завершить работу. •
Если да, перейти к следующему шагу.
350
Глава 4. Администрирование баз данных
3. Текущая база данных выбрана. Установлены ли какие-нибудь правила в binlog-do-db? •
Если да, соответствует ли текущая база данных правилам, указанным в binlog-do-db? Если да, записать оператор в бинарный журнал и завершить работу. Если нет, не записывать оператор в бинарный журнал и завершить работу.
•
Если нет, перейти к следующему шагу.
4. Определенные правила в binlog-ignore-db установлены. Соответствует ли текущая база данных любому, из указанных правил? • Если да, не записывать оператор в бинарный журнал и завершить работу. • Если нет, записать запрос и завершить работу. Например, подчиненный сервер, запущенный с опцией binlog-do-db=sales, не будет заносить в бинарный журнал операторы, в которых указано имя текущей базы данных, отличное от sales (другими словами, иногда binlog-do-db означает "игнорировать другие базы данных"). При использовании репликации не следует удалять старые файлы бинарных журналов до тех пор, пока не появится полная уверенность в том, что подчиненному серверу они больше не понадобятся. Единственный способ сделать это - выполнять команду mysqladmin flush-logs раз в день, после чего удалять любые журналы, созданные более трех дней назад. Удалять их можно вручную, но предпочтительнее - с помощью оператора PURGE MASTER LOGS, который плюс к этому еще и безопасным образом обновит индексный файл бинарного журнала (и в котором, начиная с версии MySQL 4.1, в качестве аргумента можно указывать и дату). Клиент с привилегией SUPER имеет возможность отключать регистрацию своих операторов в бинарном журнале, используя SET SQL__LOG_BIN=0. Для работы с файлами бинарных журналов можно использовать утилиту mysqlbinlog. Она полезна при желании повторно обработать операторы в журнале. Например, обновить сервер MySQL с помощью бинарного журнала можно следующим образом: shell> mysqlbinlog журнальный-файл | mysql -h имя^сервера Более подробная информация об утилите mysqlbinlog и том, как ее использовать, находится в разделе 7.5. Если применяются транзакции, для создания резервных копий вместо старого журнала обновлений следует использовать бинарный журнал регистрации MySQL. Данные регистрируются в бинарном журнале сразу же после завершения обработки того или иного запроса, но прежде чем будет снята любая блокировка или зафиксирована любая транзакция. Это гарантирует, что журнал будет заполняться в порядке выполнения операторов. Обновления нетранзакционных таблиц заносятся в бинарный журнал незамедлительно после их выполнения. Что касается таблиц BDB и InnoDB, все обновления (вносимые с помощью UPDATE, DELETE или INSERT и изменяющие таблицу) помещаются в кэш до тех пор, пока сервером не будет получен оператор COMMIT. В этот момент, до того как будет выполнен COMMIT, mysqld записывает всю транзакцию целиком в бинарный журнал. При запуске потока, который будет обрабатывать транзакцию, для буферизации запросов выделяется буфер размером binlog_cache_size. Если оператор превышает данный раз-
4.8. Журнальные файлы MySQL
351
мер, поток открывает временный файл для сохранения транзакции. После закрытия потока временный файл будет удален. Опцию max__binlog_cache_size (которой по умолчанию присваивается значение 4 Гбайт) можно использовать для ограничения общего объема памяти, выделяемого для кэширования транзакций с множественными операторами. При превышении указываемого в max_binlog_cache_size значения, выполнение транзакции будет прервано с осуществлением отката. Если используется журнал обновлений или бинарный журнал, то, когда применяется оператор CREATE.. .SELECT или INSERT.. .SELECT, параллельные операции вставок будут преобразовываться в стандартные. Это необходимо для того, чтобы обеспечить возможность воссоздания точной копии таблиц посредством применения журнала вместе с резервной копией. Форматы бинарного журнала в версиях 3.23, 4.0 и 5.0.0 разные. Изменения формата требовались для улучшения возможностей репликации. В версиях 4.0 и 4.1 формат бинарного журнала совпадает. См. раздел 5.5.
48.5. Журнал медленных запросов При запуске с опцией —log-slow-queries[=имя_файла] сервер mysqld создает журнальный файл, в который будут записываться все SQL-операторы, выполнение которых заняло больше, чем указано в longquerytime секунд. Время на начальную блокировку таблиц во времени выполнения запросов не учитывается. Если значение имя_файла не указано, по умолчанию в качестве имени файла присваивается имя хоста с суффиксом -slow.log. Если имя файла указано, но не задан путь к нему, файл размещается в каталоге данных. Оператор записывается в журнал медленных запросов только после того, как он был выполнен, и после того, как сняты все блокировки. Порядок размещения операторов в журнале может отличаться от порядка, в котором они выполнялись. Журнал медленных запросов может использоваться с целью выявления запросов, на выполнение которых ушло слишком много времени, а, значит, требующих оптимизации. Однако работать с большим журналом медленных запросов становится задачей не из простых. В таком случае лучше прогнать журнал через команду mysqldumpslow, которая отобразит список всех встречающихся в журнале запросов. Если во время регистрации медленных запросов применяется и опция —log-longformat, запросы, не использующие индексов, будут тоже записываться в журнал. См. раздел 4.2.1.
4.8.6. Обслуживание журнальных файлов Сервер MySQL может создавать целый ряд различных журнальных файлов, с помощью которых узнать о том, что происходит в процессе работы системы, особой сложности не представляет (см. раздел 4.8). Однако следует проводить регулярную чистку таких файлов, чтобы они не занимали слишком много пространства на диске. При использовании журналов в MySQL, скорее всего, возникнет потребность в периодическом удалении их старых файлов или в создании их резервной копии, а также может появиться необходимость заставить MySQL заносить данные в новые файлы. См. раздел 4.6.1. В Linux (Red Hat) для этого можно использовать сценарий mysql-log-rotate. Если MySQL устанавливался из дистрибутива RPM, то этот сценарий должен был установиться
352
Глава 4. Администрирование баз данных
автоматически. Будьте осторожны с данным сценарием, если для репликации применяется бинарный журнал! (Нельзя удалять бинарные журналы до тех пор, пока не появится полная уверенность в том, что их содержимое обработано всеми подчиненными серверами.) На других системах потребуется собственноручно установить небольшой сценарий для работы с журнальными файлами, запускаться который будет из сгоп. Заставить сервер начать использовать новые файлы журналов можно с помощью команды mysqladmin flush-logs или SQL-оператора FLUSH LOGS. В версии MySQL 3.21 следует применять команду mysqladmin refresh. Команда по очистке журналов выполняет следующее: • Если используется стандартный журнал (—log) или журнал медленных запросов (—log-slow-queries), журнальный файл (mysql.log и имя_хоста-slow.log no умолчанию) будет закрыт и открыт заново. • Если используется журнал обновлений (--log-update) или бинарный журнал регистрации (—log-bin), текущий журнальный файл будет закрыт, а новый журнальный файл с большим порядковым номером - открыт. Если используется только журнал обновлений, нужно просто переименовать старый журнальный файл, а затем очистить журналы, прежде чем приступать к резервному копированию. Например, можно выполнить следующее: shell> cd каталог-данных-mysql shell> mv mysql.log mysql.old shell> mysqladmin flush-logs После этого подготовьте резервную копию и удалите mysql. old.
49. Запуск нескольких серверов MySQL на одном и том же компьютере В некоторых случаях может понадобиться запустить сразу несколько серверов mysqld на одном и том же компьютере. Например, если нужно протестировать новую версию MySQL, при этом уже существующая в производственной среде установка должна остаться нетронутой. Или когда возникает потребность разным пользователям предоставить доступ к разным серверам mysqld, которыми они будут управлять сами. (Предположим, вы являетесь поставщиком услуг Internet и хотите обеспечить независимые конфигурации MySQL для разных клиентов.) При запуске нескольких серверов на одной единственной машине, каждый из серверов должен иметь уникальные значения некоторых рабочих параметров, которые можно задавать как в командной строке, так и в файлах опций. См. раздел 3.3. Различным для каждого сервера должны быть, по крайней мере, следующие опции: • —рогЬ=номер_порта —port управляет номером порта для TCP/IP-соединений. • —socket=path —socket в Unix указывает путь к файлу сокета Unix, а в Windows - имя именованного канала. В Windows обязательно следует указывать точные имена каналов только для тех серверов, которые поддерживают соединения через именованные каналы.
4.9. Запуск нескольких серверов MySQL на одном и том же компьютере
353
• —shared-memory-base-name=HM# Эта опция в настоящее время используется только в Windows. Она присваивает имя разделяемой области памяти, которая используется сервером Windows для разрешения клиентам подключаться через эту память. Это новая опция в MySQL 4.1. •
—pid-file=nyTb
Эта опция используется только в Unix. С ее помощью указывается имя файла, в котором сервер записывает свой идентификатор процесса. Если представленные ниже опции используются, их значения также должны быть разными для каждого сервера: • —log=путь • —1од-Ып=путь • —log-update=nyTb • —1од-еггог=путь •
—log-isam=nyTb
•
—bdb-logdir=nyTb
Опции, необходимые для работы с журнальными файлами, описаны в разделе 4.8.6. Чтобы улучшить производительность системы, можно также по-разному для каждого сервера задать и представленные ниже опции, что позволит распределять нагрузку между несколькими физическими дисками: • —tmpdir=путь • —bdb-tmpdiт=путь Помимо этого рекомендуется, чтобы временные каталоги тоже были разными; так будет намного легче определять, какой из серверов MySQL создал тот или иной временный файл. В общем случае, каждый сервер должен использовать отдельный каталог данных, путь к которому задается с помощью опции —datadir=путь. !
Внимание!
!;< Р h
Обычно ни в коем случае нельзя допускать, чтобы сразу два сервера обновляли данные в одной и той же базе данных! Это может привести к очень неприятным последствиям, если ваша операционная система не поддерживает функцию безотказной блокировки доступа! Если (даже несмотря на данное предупреждение) для сразу нескольких серверов указан один и тот же каталог ; данных и при этом используется функция регистрации в журналах, обязательно следует с помо|;-, щью соответствующих опций задать уникальные для каждого сервера имена журнальных файI лов. В противном случае серверы будут пытаться заносить данные в одни и те же файлы.
Это предупреждение относится и к окружениям, в которых используется сетевая файловая система (NFS). Разрешить сразу нескольким серверам MySQL доступ к общему каталогу данных через сетевую файловую систему - исключительно плохая идея! • Основная проблема состоит в том, что в таком случае сетевая файловая система станет критическим элементом, ограничивающим скорость передачи данных, а она предназначена вовсе не для этого. • Еще одна проблема - придется позаботиться об отсутствии конфликтов между серверами. Обычно в сетевой файловой системе за блокировку доступа отвечает демон lockd, но в настоящее время платформы, которая бы обеспечивала надежную на все 100% блокировку в любой ситуации, пока не существует.
354
Глава 4. Администрирование баз данных
Не усложняйте сами себе задачу, то есть о доступе сразу двух (или более) серверов к одной базе данных через сетевую файловую систему лучше забыть. Подходящим решением может быть использование одного компьютера с несколькими процессорами и операционной системы, эффективно управляющей потоками. При наличии нескольких установок MySQL на разных дисках, обычно для каждого сервера с помощью опции --basedir=nyTb указывается путь к основному каталогу установки, в результате чего каждый сервер будет использовать отдельные журнальные и PID-файлы, а также отдельный каталог данных. (Значения по умолчанию будут зависеть от каталога данных.) В таком случае дополнительно нужно будет задать только опции —socket и —port. Например, предположим, что устанавливаются разные версии MySQL с использованием бинарных дистрибутивов в форме файлов tar. Установлены они будут в разных местах, поэтому сервер (для каждой из установок) можно будет запускать с помощью команды bin/mysqldsafe из соответствующего каталога данных. mysqld_safe самостоятельно определит подходящую для передачи mysqld опцию —basedir; понадобится только указать для mysqld_safe опции —socket и —port. (В версиях MySQL, предшествующих 4.0, вместо mysqld_safe используйте safejnysqld.) Как уже рассказывалось в предыдущих разделах, существует также возможность запускать дополнительные серверы путем установки переменных окружения или путем указания соответствующих опций в командной строке. Однако если использовать нескольких серверов одновременно планируется на более постоянной основе, тогда лучше все значения, которые должны быть уникальными для того или иного сервера, указывать в файле опций.
4.9.1. Запуск нескольких серверов в Windows В Windows сразу несколько серверов можно запустить вручную из командной строки, указав для каждого соответствующие рабочие параметры. В системах Windows NT существует опция установки и запуска многочисленных серверов как служб Windows. Основные инструкции по запуску серверов MySQL из командной строки или в качестве служб перечислены в разделе 2.2.1. Также в этом разделе описывается, как обеспечить, чтобы все серверы запускались с разными значениями тех опций, которые должны быть уникальными для каждого сервера, как, например, каталог данных. Такие опции рассматриваются в разделе 4.9. 4.9.1.1. Запуск нескольких серверов в Windows из командной строки Чтобы запускать сразу несколько серверов вручную из командной строки, можно указать соответствующие опции в командной строке или в файле опций. Удобнее размещать опции в файле опций, но обязательно нужно позаботиться о том, чтобы у каждого сервера был свой собственный набор опций. Чтобы добиться такого результата, создайте отдельный файл опций для каждого сервера и с помощью опции —defaults-file сообщите серверу имя этого файла при запуске. Предположим, вы хотите запустить сервер mysqld на порте 3307 с каталогом данных C:\mydatal и сервер mysqld-max на порте 3308 с каталогом данных C:\mydata2 (прежде чем делать это, необходимо убедится в том, что оба каталога существуют и содержат каждый свою копию базы данных mysql, в которой хранятся таблицы привилегий). Создайте два файла опций. Например, один из них назовите C:\my-optsl.cnf, и выглядеть он должен так:
4.9. Запуск нескольких серверов MySQL на одном и том же компьютере
355
[mysqld] datadir = C:/mydatal port = 3307 Второй файл назовите С: \my-opts2. cnf: [mysqld] datadir = C:/mydata2 port = 3308 После этого запустите серверы, указав для каждого собственный файл опций: С:\> C:\mysql\bin\mysqld ~defaults-file=C:\my-optsl.cnf С:\> С:\mysql\bin\mysqld-max —defaults-file=C:\my-opts2.cnf В среде NT оба сервера запустятся в приоритетном режиме (до завершения сервера никаких других приглашений на ввод команд не появится), поэтому указанные выше команды понадобится выполнять в разных окнах консоли. Чтобы завершить работу серверов, необходимо подключиться к соответствующему порту: С:\> C:\mysql\bin\mysqladmin — port=3307 shutdown С:\> C:\mysql\bin\mysqladmin —port=3308 shutdown Серверы, сконфигурированные только что описанным способом, позволяют клиентам подключаться через TCP/IP. Если имеющаяся версия Windows поддерживает именованные каналы и есть желание разрешить установку соединения с сервером через них, используйте серверы mysqld-nt и mysqld-max-nt, задавая специальные разрешающие подобные соединения опции, в которых укажите имя соответствующего именованного канала. Каждый сервер, поддерживающий соединения через именованные каналы, должен использовать уникальное имя канала. Например, файл C:\my-optsl.cnf может выглядеть следующим образом: [mysqld] datadir = C:/mydatal port = 3307 enable-named-pipe socket = mypipel Тогда сервер должен запускаться так, как показано ниже: С:\> С:\mysql\bin\mysqld-nt —defaults-file=C:\my-optsl.cnf Таким же способом измените и файл С:\my-opts2.cnf, который используется вторым сервером. 4.9.1.2. Запуск нескольких серверов в Windows как служб В системах Windows NT сервер MySQL может запускаться и как одна из служб Windows. Процедуры установки, управления и удаления службы MySQL описаны в разделе 2.2.1.7. Начиная с версии MySQL 4.0.2, появилась возможность устанавливать и многочисленные серверы в качестве служб. В таком случае обязательно следует позаботиться о том, чтобы все серверы помимо уникальных для каждого сервера параметров использовали еще и разные имена служб. Предлагаемые ниже инструкции предполагают, что вы хотите запустить сервер mysqld-nt из двух разных версий MySQL, которые установлены в каталоге
Глава 4. Администрирование баз данных
356
С: \mysql-4.0.8 и каталоге С: \mysql-4.0.17 соответственно. (Такой вариант возможен, когда в производственной среде используется сервер версии 4.0.8, и прежде чем проводить модернизацию до версии 4.0.17, вы хотите эту версию протестировать.) Следующие принципы верны, когда служба MySQL устанавливается с опцией — i n s t a l l или —install-manual: • Если имя службы не указано, сервер использует имя по умолчанию MySQL и считывает опции из группы [mysqld] стандартных файлов опций. • Если указать имя службы после опции — i n s t a l l , сервер будет игнорировать группу опций [mysqld] и вместо этого считывать опции из группы с таким же именем, как и у службы. Сервер считывает опции из стандартных файлов опций. • Если после имени службы указать опцию —default-file, сервер будет игнорировать стандартные файлы опций и вместо этого будет считывать опции только из группы [mysqld] названного файла. & На заметку! "X С|; %, $ U щ || |jf $
В версиях MySQL, предшествующих 4.0.17, только сервер, при установке которого в качестве имени службы использовалось имя MySQL (то есть, значение по умолчанию), или сервер, при установке которого было явно задано имя службы mysqld, будет считывать опции из группы [mysqld] стандартных файлов опций. Начиная с версии MySQL 4.0.17, все серверы, если они читают стандартные файлы опций, обращаются к группе [mysqld], даже если они устанавливались с другим именем службы. Это позволяет в группе [mysqld] указывать те опции, которые должны использоваться всеми службами MySQL, а в группе опций, называемой именем определенной службы - опции, которые будут использоваться только установленным с таким же именем службы сервером.
Исходя из всего вышесказанного, можно сделать вывод о том, что существует несколько способов установки сразу нескольких служб MySQL на одном компьютере. Приведенное ниже описание этих способов включает и некоторые примеры. Прежде чем пытаться проверить любой из них, сначала убедитесь, что все существующие службы MySQL были закрыты и удалены. • Способ 1. Задавайте опции для всех служб в одном из стандартных файлов опций. Для этого необходимо для каждого сервера указать отдельное имя службы. Предположим, вы хотите запустить сервер mysqld-nt версии 4.0.8, используя имя службы mysqldl, и сервер mysqld-nt версии 4.0.17, используя имя службы mysqld2. В таком случае для сервера 4.0.8 можно указать группу [mysqldl ], а для сервера 4.0.17 - группу [mysqld2 ]. Например, файл С: \my. cnf может выглядеть так: # Опции для службы mysqldl [mysqldl] basedir = C:/mysql-4.0.8 port = 3307 enable-named-pipe socket = mypipel # Опции для службы mysqld2 [mysqld2] basedir = C:/mysql-4.0.17 port = 3308 enable-named-pipe socket = mypipe2
4.9. Запуск нескольких серверов MySQL на одном и том же компьютере
357
Установите службы, как показано ниже, указывая пути к серверу полностью; это гарантирует, что Windows будет регистрировать правильные выполняемые программы для каждой службы: С:\> C:\mysql-4.0.8\bin\mysqld-nt —install mysqldl С:\> C:\mysql-4.0.17\bin\mysqld-nt —install mysqld2 Чтобы запустить службы, используйте диспетчер служб или оператор NET START с соответствующими именами служб: С:\> NET START mysqldl С:\> NET START mysqld2 Чтобы завершить работу служб, используйте диспетчер служб или оператор NET STOP с соответствующими именами служб: С:\> NET STOP mysqldl С:\> NET STOP mysqld2 • Способ 2. Задавайте опции для каждого сервера в отдельном файле и, когда устанавливаете службы, применяйте —defaults-file, чтобы указать каждому серверу, какой файл он должен использовать. В таком случае все опции следует перечислять в группе [mysqld] каждого отдельного файла. При таком способе, чтобы указать опции для mysqld-nt версии 4.0.8, создайте файл С: \myoptsl. cnf, который должен выглядеть так: [mysqld] basedir = С:/mysql-4.0.8 port = 3307 enable-named-pipe socket = mypipel Для сервера mysqld-nt версии 4.0.17 создайте файл C:\my-opts2.cnf, который должен выглядеть так: [mysqld] basedir = С:/mysql-4.О.17 port = 3308 enable-named-pipe socket = mypipe2 Установите службы следующим образом (вводите каждую команду в одной строке): С:\> C:\mysql-4.0.8\bin\mysqld-nt —install mysqldl —defaults-file=C:\my-optsl.cnf C:\> C:\mysql-4.0.17\bin\mysqld-nt —install mysqld2 —defaults-file=C:\my-opts2.cnf При установке MySQL в качестве службы, чтобы использовать опцию --defaults-file, перед ней необходимо указывать имя службы. После того, как службы MySQL установлены, запустить или остановить их можно способами, описанными в предыдущем примере. Чтобы удалить службы MySQL, для каждой из них используйте опцию mysqld —remove, указывая после —remove имя службы. Если это имя MySQL (то есть имя, установленное по умолчанию), его можно и не указывать.
358
Глава 4. Администрирование баз данных
4.9.2. Запуск нескольких серверов под Unix Самый простой способ запустить несколько серверов в Unix - это скомпилировать их с разными TCP/IP-портами и файлами сокетов Unix, чтобы каждый из них прослушивал соединения через разные сетевые интерфейсы. Также компиляция с разными для каждой установки MySQL каталогами данных автоматически приводит к тому, что серверы будут использовать каждый свои журналы, PID-файлы и каталоги данных. Предположим, что существующий сервер сконфигурирован со значениями по умолчанию для TCP/IP-порта (3306) и файла сокета Unix (/tmp/mysql.sock). Для конфигурирования нового сервера с другими рабочими параметрами воспользуйтесь командой configure, подобной показанной ниже: shell> ./configure —with-tcp-porЬ=номер_порта \ —with-unix-socket-paЬЬ=имя_файла \ —prefix=/usr/local/mysql-4.0.17 Здесь номер_порта и имя_файла должны отличаться от устанавливаемых по умолчанию значений для номера TCP/IP-порта и пути к файлу сокета Unix, а в —prefix должен указываться каталог установки, не совпадающий с каталогом, в котором расположена текущая версия MySQL. При наличии сервера, прослушивающего соединения через определенный порт, можно выполнить следующую команду, чтобы узнать, какие рабочие параметры использует сервер для некоторых важных реконфигурируемых переменных, включая имя основного каталога и имя файла сокета Unix: shell> mysqladmin —hosЬ=имя_хоста —рогЬ=номер_порта variables Отображаемая с помощью этой команды информация позволяет понять, какие значения опций использовать не нужно при конфигурации дополнительного сервера. Обратите внимание, что если задать в качестве имени хоста local host, mysqladmin no умолчанию для соединения будет использовать файл сокета Unix, а не TCP/IP. В MySQL 4.1 можно явно указать протокол, который следует использовать для соединения, с помощью ОПЦИИ --protocol^TCP I SOCKET j PIPE | MEMORY}. He нужно компилировать новый сервер, чтобы просто запустить его с другими значениями для файла сокета Unix и номера порта TCP/IP. Данные значения можно задать и во время выполнения. Один из способов это сделать - использовать опции командной строки: shell> mysqld_safe —sockeЬ=имя__файла —рогЬ=номер_порта Для запуска второго сервера укажите другие значения в опциях —socket и —port и передайте для mysqld_safe опцию —datadir=nyTb, чтобы сервер использовал другой каталог данных. Еще один способ добиться подобных результатов - для установки имени файла сокета Unix и номера порта TCP/IP использовать переменные окружения: shell> MYSQL_UNIX_PORT=/tmp/mysqld-new. sock shell> MYSQL_TCP_PORT=3307 shell> export MYSQLJJNIXJ>ORT MYSQLJTCPJPORT shell> mysqlJLnstall^db —user=mysql shell> mysqld_safe —datadir=/путь/к/каталогу_даиных & Этот самый быстрый метод, позволяющий запустить второй сервер для целей тестирования. Его положительная сторона состоит в том, что настройки переменных окруже-
4.9. Запуск нескольких серверов MySQL на одном и том же компьютере
359
ния будут применяться ко всем клиентским программам, вызываемым из одной и той же командной оболочки. Таким образом, соединения для таких клиентов будут автоматически направляться второму серверу! В приложении Б представлен список переменных окружения, которые можно использовать для работы с mysqld. Для автоматического запуска сервера специальный сценарий, выполняемый во время начальной загрузки системы, должен выполнять следующую команду один раз для каждого сервера, в каждой их которых указывается соответствующий путь к файлу опций: mysqld_safe —defaults-file=nyrb
В каждом файле опций должны содержаться специальные для данного сервера значения опций. В Unix еще один способ запустить несколько серверов на одном компьютере предусматривает использование сценария mysqldjnulti. См. раздел 4.1.5.
4.9.3. Использование клиентских программ в окружении с несколькими серверами При необходимости подключить клиентскую программу к серверу MySQL, прослушивающему сетевые интерфейсы, отличные от тех, с которыми скомпилирован клиент, можно воспользоваться одним из следующих методов: • Запустите клиент с опцией —ho8Ь=имя_хоста —ро г t=HOMep_nopTa, чтобы подключиться через TCP/IP к удаленному серверу, или с опцией — host=127.0.0.1 —рогЬ=номер_порта, чтобы подключиться через TCP/IP к локальному серверу, или с опцией —host=localhost —sоскеЬ=имя_файла, чтобы подключиться к локальному серверу через файл сокета Unix либо именованный канал Windows. • Начиная с версии MySQL 4Л, можно запускать клиент с опцией —protocol=tcp, чтобы подсоединяться через TCP/IP, или с опцией --protocol=socket, чтобы подключаться через файл сокета Unix, или с опцией — protocol=memory, чтобы подсоединяться через совместно используемую память. Для TCP/IP-соединений также может понадобиться указывать опции --host и —port. Для других типов соединений может потребоваться задать опцию —socket, в которой указывается файл сокета Unix или именованный канал, или же опцию —shared-memory-base-name, в которой указывается имя совместно используемой памяти. Соединения через совместно используемую память поддерживаются только в Windows. • В Unix, прежде чем запускать клиенты, установите переменные окружения MYSQL_UNIX_PORT и MYSQL_TCP_PORT, в которых укажите файл сокета Unix или номер порта TCP/IP. Если обычно используется какой-то конкретный файл сокета или номер порта, можно поместить команды, задающие эти переменные окружения, в файл . login, тогда они будут применяться каждый раз при входе в систему. См. приложение Б. • Укажите используемые по умолчанию файл сокета Unix и номер порта TCP/IP в группе [client] файла опций. Например, это может быть файл опций С: \my.cnf в Windows или файл .my.cnf домашнего каталога в Unix. См. раздел 3.3.2.
Глава 4. Администрирование баз данных
360 •
В программе на С можно задать аргументы файла сокета и номера порта в вызове функции mysql_real_connect (). Также можно заставить программу считывать файлы опций, вызвав mysql_options ().
•
При использовании модуля Perl DBD::mysql можно считывать опции из файлов опций MySQL. Например: $dsn =
"DBI:mysql:test;mysql_read_default_group=client;" . "mysql_read_default_file=/usr/local/raysql/data/my.cnf'; $dbh = DBI->connect($dsn, $user, $password); Другие интерфейсы программирования для чтения файлов опций могут предлагать возможности, подобные описанным выше.
410. Кэш запросов MySQL Начиная с версии 4.0.1, сервер MySQL предлагает кэш запросов. При использовании кэш запросов сохраняет текст запроса SELECT вместе с соответствующим результатом, который был отправлен клиенту. Когда в следующий раз поступает идентичный запрос, сервер вместо того, чтобы снова анализировать и выполнять его, извлекает уже имеющиеся по такому запросу результаты из кэша. Кэш запросов крайне удобно использовать в среде, где (некоторые) таблицы не изменяются слишком часто и количество идентичных запросов велико. Такая ситуация является типичной для большинства Web-серверов, генерирующих огромное число динамических страниц, основанных на содержимом базы данных. Щ. На заметку! У: Кэш запросов не возвращает устаревшие данные. При изменении таблиц любые записи в кэше !/ запросов, имеющие отношение к этим изменениям, удаляются. £
На заметку!
; Кэш запросов не работает в среде, где сразу несколько серверов mysqld обновляют одни и те ;1 же таблицы.
Ниже представлены некоторые данные по функционированию кэша запросов. Они были собраны во время работы с контрольным комплектом MySQL в системе Linux Alpha 2 х 500 МГц с ОЗУ объемом 2 Гбайт и кэшем запросов размером 64 Мбайт. • Если все выполняемые запросы являются простыми, но при этом отличаются между собой настолько, что не могут быть помещены в кэш, непроизводительные издержки на использование кэша запросов соответствуют 13%. Это можно рассматривать как наихудший возможный вариант. На практике запросы обычно намного сложнее, а поэтому и издержки значительно ниже. •
Поиск строки в однострочной таблице происходит на 238% быстрее при наличии кэша запросов. Этот коэффициент можно рассматривать как близкий к минимальному коэффициент ускорения вычислений, ожидаемый для обработки запроса, который находится в кэше.
Чтобы отключить кэш запросов при запуске сервера, необходимо для системной переменной q u e r y c a c h e s i z e установить значение 0. В таком случае не будет никаких заметных непроизводственных издержек. Полностью исключить использование возможностей кэша запросов на сервере можно, указав во время компиляции MySQL в программе configure опцию —without-query-cache.
4.10. Кэш запросов MySQL
361
4.10.1. Как работает кэш запросов В данном разделе описывается, как работает кэш запросов, когда он активизирован, а в разделе 4.10.3 - как управлять его работой. Перед синтаксическим анализом запросы сравниваются, поэтому следующие два запроса рассматриваются кэшем запросов как разные: SELECT * FROM имя_таблицы S e l e c t * from имя_таблицы
Чтобы рассматриваться как идентичные, запросы должны быть абсолютно одинаковыми (байт в байт). Кроме того, строки запросов, являющиеся идентичными, могут трактоваться как отличающиеся друг от друга по каким-то другим причинам. Запросы, использующие разные базы данных, разные версии протоколов или разные наборы символов по умолчанию считаются неодинаковыми и помещаются в кэш по отдельности. При возвращении результата запроса из кэша запросов сервер увеличивает значение переменной состояния Qcache_hits, а не Com_select. См. раздел 4.10.4. Если таблица изменяется, все помещенные в кэш запросы, которые использовали данную таблицу, становятся недействительными и удаляются из кэша. (Сюда относятся и запросы, использующие таблицы MERGE, которые преобразовываются в измененную таблицу.) Таблица может быть изменена посредством самых разных типов операторов, т а к и х к а к INSERT, UPDATE, DELETE, TRUNCATE, ALTER TABLE, DROP TABLE ИЛИ DROP DATABASE.
Измененные транзакционные таблицы innoDB становятся недействительными при выполнении оператора COMMIT. В версии MySQL 4.0 кэш запросов блокируется во время выполнения транзакций (он не возвращает результатов). Начиная с версии MySQL 4.1.1, кэш запросов работает и во время выполнения транзакций при применении таблиц InnoDB (он использует номер версии таблицы, чтобы определить, является ли ее содержимое по-прежнему текущим). В версиях MySQL, предшествующих 5.0, запрос, начинающийся с комментария, может быть помещен в кэш, но вот выбран оттуда быть не может. В MySQL 5.0 упомянутая проблема устранена. Кэш работает С запросами типа SELECT SQL_CALC_FOUND_ROWS. . . И SELECT FOUND_ROWS(). FOUND_ROWS () возвращает правильное значение, даже если из кэша был выбран предыдущий запрос, потому что в кэше также хранится и число найденных строк. Запрос не может быть помещен в кэш, если он содержит любую из следующих функций: BENCHMARK()
CONNECTION_ID()
CURRENT_DATE()
CURRENT_TIME()
CURDATE()
CURT IME ()
DATABASE ()
ENCRYPT () (с о д н и м параметром)
FOUND_ROWS()
GET_LOCK()
LAST_INSERT_ID()
LOAD_FILE()
MASTER_POS_WAIT()
NOW ()
RANDO
RELEASE_LOCK()
SYSDATE()
UNIX_TIMESTAMP () ( б е з параметров)
USER ()
CURRENT_TIMESTAMP()
Запрос также не будет помещаться в кэш при следующих условиях: • Если он содержит определяемые пользователем функции (UDF). • Если он содержит переменные пользователя. • Если он относится к таблицам из системной базы данных mysql.
362
Глава 4. Администрирование баз данных
• Если он представлен в виде: SELECT SELECT SELECT SELECT
. . . IN SHARE MODE . . . INTO OUTFILE . . . . . . INTO DUMPFILE . . . * FROM . . . WHERE столбец_аиЬоincrement
IS NULL
Последний из перечисленных запросов не помещается в кэш, поскольку используется при работе с ODBC для получения значения идентификатора последней вставки. •
Если он использует таблицы TEMPORARY.
• Если он не использует никаких таблиц. • Если пользователь имеет привилегию на уровне столбцов для любой из используемых таблиц. • Перед тем как запрос будет выбран из кэша запросов, MySQL проверяет, имеет ли пользователь привилегию SELECT для любой из задействованных баз данных или таблиц, и если нет, то кэшированный результат не используется.
4.10.2. Опции SELECT для кэша запросов Существует две опции, имеющие отношение к кэшу запросов, которые можно задавать в операторе SELECT: • •
SQL_CACHE. Результат запроса будет помещен в кэш, если значение системной переменной query_cache_type равно ON или DEMAND. SQL_NO_CACHE. Результат запроса не будет помещен в кэш.
Примеры: SELECT SQL_CACHE id, name FROM customer; SELECT SQL_NO_CACHE id, name FROM customer;
4.10.3. Конфигурирование кэша запросов Системная переменная сервера have_query_cache указывает, доступен ли кэш запросов: f
mysql> SHOW VARIABLES LIKE 'have_query_cache ; + + + | Variable_name | Value | I have_query_cache
| YES
|
Несколько других системных переменных управляют работой кэша запросов. Их можно задавать в файле опций или в командной строке при запуске mysqld. Все системные переменные, имеющие отношение к кэшу запросов, начинаются с query_cache_. Кратко они описываются в разделе 4.2.3, а дополнительная информация по их конфигурации представлена здесь. Размер кэша запросов устанавливается в системной переменной query_cache_size. Если указать в ней значение 0, кэш запросов будет отключен. Значение по умолчанию равно 0, то есть кэш запросов не активизирован. Если кэш запросов используется, то значение переменной query_cache_size будет влиять на его работу. Могут быть установлены следующие значения:
4.10. Кэш запросов MySQL
363
•
0 или OFF ("выключено") - запросы не кэшируются и кэшированные результаты не извлекаются.
•
1 или ON ("включено") - в кэш помещаются все операторы за исключением тех, которые начинаются с SELECT SQL_NO_CACHE.
•
2 или DEMAND ("по требованию") - в кэш помещаются только те операторы, которые начинаются с SELECT SQL_CACHE.
Значение GLOBAL переменной query_cache_type определяет поведение кэша запросов для всех клиентов, подключающихся после того, как внесены изменения. Отдельные клиенты могут регулировать поведение кэша запросов для своих собственных соединений, устанавливая значение SESSION в переменной query_cache_type. Например, клиент может отключить использование кэша запросов для своих собственных запросов следующим образом: mysql> SET SESSION query_cache_type = OFF;
Чтобы ограничить максимальный размер помещаемых в кэш результатов отдельных запросов, установите значение переменной query_cache_limit. Значение по умолчанию составляет 1 Мбайт. Результат запроса (данные, которые были отправлены клиенту) сохраняется в кэш запросов во время извлечения результатов. Поэтому данные обычно не обрабатываются одной большой порцией. Кэш запросов выделяет блоки для сохранения данных по необходимости, таким образом, когда один блок заполнен, создается новый. Поскольку операция по распределению памяти обходится дорого (то есть занимает немалый промежуток времени), кэш запросов выделяет блоки с минимальным размером, указанным в системной переменной query__cache_min_res_unit. После того, как запрос выполнен, последний блок с результатами усекается в соответствии с фактическим размером данных, тем самым высвобождается неиспользуемая память. В зависимости от выполняемых сервером типов запросов, можно варьировать значения query_cache_min_res_unit: • По умолчанию значение query_cache_min_res_unit составляет 4 Кбайт и должно подходить в большинстве случаев. • При большом количестве запросов с маленькими результатами, использование принятого по умолчанию размера блоков может привести к фрагментации памяти, поскольку в таком случае количество свободных блоков велико. Фрагментация, в свою очередь, не исключает удаления (отсечения) запросов из кэша по причине недостаточного количества доступной памяти. В такой ситуации следует уменьшить значение query_cache_min_res_unit. Число свободных блоков и запросов, удаленных в результате описанного отсечения указано в переменных состояния Qcache_free_blocks и Qcache_lowmem_prunes. • Если результаты практически всех запросов большие (проверьте значения переменных состояния Qcache_total_blocks и Qcache_queries_cache), повысить производительность системы можно, увеличив query_cache_min_res_unit. Однако следите за тем, чтобы оно не оказалось слишком большим (см. предыдущий пункт).
4.10.4. Состояние кэша запросов и его обслуживание Проверить наличие кэша запросов в MySQL можно с помощью следующего оператора:
364
Глава 4. Администрирование баз данных
mysql> SHOW VARIABLES LIKE ' h a v e _ q u e r y _ c a c h e ' ; + + +
I Variable_name + I have_query_cache
I Value + I YES
I + |
С помощью оператора FLUSH QUERY CACHE можно выполнить дефрагментацию кэша запросов для лучшего использования его памяти. Никаких запросов из кэша данный оператор не удаляет. Оператор RESET QUERY CACHE удаляет все результаты запросов из кэша запросов. То же самое делает и оператор FLUSH TABLES. Контролировать эффективность кэша запросов можно с помощью оператора SHOW STATUS, который позволяет просмотреть переменные состояния кэша: mysql> SHOW STATUS LIKE l Qcache% ! ; I Variable_name I Value I + + + I Qcache_free_blocks I 36 | I Qcache_free_memory I 138488 | I Qcachejiits I 79570 | I Qcache_inserts I 27087 | I Qcache_lowmem_prunes I 3114 | I Qcache_not_cached I 22989 | i Qcache_queries_in_cache | 415 | I Qcache_total_blocks I 912 | + + + Описание каждой из этих переменных дается в разделе 4.2.4. Использование некоторых из них рассматривается ниже. Общее число запросов SELECT равняется: Com_select + Qcache_hits + запросы с ошибками, обнаруженные анализатором
Значение Com_select состоит из: Qcache_inserts + Qcache_not_cached + запросы с ошибками, обнаруженные во время проверки столбцов/прав Кэш использует блоки переменной длины, поэтому значения Qcache_total_blocks и Qcache_free_blocks могут означать фрагментацию памяти кэша запросов. После использования оператора FLUSH QUERY CACHE остается только один свободный блок. Для каждого кэшированного запроса требуется минимум два блока (один для текста запроса, а другой или другие для результатов запроса). Также для каждой используемой в запросе таблицы тоже нужен один блок. Однако если два или более запросов используют одну и ту же таблицу, выделяется только один блок. Данные, предоставляемые переменной состояния Qcache_lowmem_prunes, могут помочь выбрать подходящее значение для размера кэша запросов. Переменная подсчитывает количество запросов, удаленных из кэша с целью освобождения памяти для кэширования новых запросов. При удалении запросов кэш выбирает запросы с наиболее давним использованием (least recently used - LRU). Информация о настройке кэша содержится в разделе 4.10.3.
5
Репликация в MySQL
В
озможности репликации позволяют базе данных на одном сервере MySQL дублироваться на другом, на котором установлен MySQL версии не ниже 3.23.15. В настоящей главе описаны различные средства репликации, предоставляемые MySQL. В ней представлены основные концепции репликации, объяснено, как настраивать сервер репликации, и предложено руководство по доступным опциям репликации. Глава также включает список наиболее часто задаваемых вопросов (с ответами) и советы по устранению неисправностей. Описание синтаксиса операторов SQL, касающихся репликации, можно найти в книге MySQL. Справочник по языку. Мы советуем почаще заглядывать на наш сайт http://www.mysql.com на предмет ознакомления с изменениями к настоящей главе. Репликация постоянно развивается, поэтому руководство часто обновляется.
5.1. Введение в репликацию MySQL 3.23.15 и выше поддерживает одностороннюю репликацию. Один сервер выступает ведущим, или главным (master), в то время как один или более серверов - ведомыми, или подчиненными (slave). Главный сервер записывает изменения в свои файлы бинарных журналов и поддерживает индекс файлов для отслеживания ротации журналов. Эти журналы хранят записи об изменениях данных, которые должны быть разосланы подчиненным серверам. Когда подчиненный сервер подключается к главному, он информирует его о позиции в журналах, до которой было выполнено последнее удачное обновление данных. Подчиненный сервер затем захватывает все изменения, которые накопились с тех пор на главном сервере, блокируется и ожидает извещений от главного сервера о новых изменениях. Подчиненный сервер также может быть одновременно и главным, если вы хотите построить цепочку реплицируемых серверов. Помните, что когда вы используете репликацию, все изменения в таблицах, которые реплицируются, должны выполняться на главном сервере. В противном случае потребуется предельная внимательность во избежание конфликтов между изменениями, которые пользователи выполняют в таблицах главного сервера, и изменениями, которые они могут провести в таблицах подчиненного. Односторонняя репликация обладает преимуществами в плане устойчивости, скорости и простоте администрирования:
366
Глава 5. Репликация в MySQL • Устойчивость растет при установке главного/подчиненного серверов. В случае возникновения проблем на главном сервере, вы можете переключиться на подчиненный, как на резервный. • Лучшее время ответа для клиентов может быть достигнуто разделением нагрузки клиентских процессов между главным и подчиненным серверами. SELECT может быть отправлен подчиненному серверу, чтобы снизить запросную нагрузку главного. Операторы, модифицирующие данные, должны по-прежнему направляться только главному серверу, поэтому главный и подчиненный всегда остаются синхронизированными. Стратегия балансирования нагрузки эффективна, если доминируют немодифицирующие запросы, и это нормальный случай. • Другая выгода применения репликации состоит в том, что вы можете выполнять резервное копирование данных с подчиненного сервера, не беспокоясь о главном. Главный сервер продолжает обновлять данные, пока выполняется резервное копирование. См. раздел 4.6.1.
5.2. Обзор реализации репликации Репликация MySQL основывается на том, что главный сервер записывает все изменения базы данных (обновления, удаления и так далее) в бинарном журнале. Поэтому, чтобы использовать репликацию, вы должны включить бинарную регистрацию на главном сервере (см. раздел 4.8.4). Каждый подчиненный сервер принимает от главного сохраненные изменения, которые тот записал в свой бинарный журнал; таким образом, подчиненный сервер может провести те же изменения в своей копии данных. Очень важно понимать, что бинарный журнал - это просто запись, начатая от фиксированного момента времени, когда была запущена бинарная регистрация. Любые подчиненные серверы, которые вы устанавливаете, нуждаются в копии данных главного сервера в том виде, в каком они пребывали на момент начала регистрации. Если запустить подчиненный сервер с базами данных, отличными от тех, что были на главном сервере при старте регистрации, подчиненный сервер может аварийно завершиться. Единственный способ скопировать данные главного сервера на подчиненные предполагает применение команды LOAD DATA FROM MASTER. Помните, что LOAD DATA FROM MASTER доступна, начиная с версии MySQL 4.0.0, и в настоящее время работает, только если все таблицы принадлежат к типу My ISAM. К тому же этот оператор требует глобальной блокировки по чтению, поэтому никакие обновления данных на главном сервере невозможны, пока данные передаются на подчиненный сервер. Когда мы, наконец, реализуем свободное от блокировок резервное копирование таблиц (в MySQL 5.0), такая глобальная блокировка будет не нужна. Из-за этих ограничений мы рекомендуем, чтобы на данный момент вы использовали LOAD DATA FROM MASTER только в случаях, когда объем данных относительно невелик, либо допустим длительный простой главного сервера. Так как реальная скорость выполнения LOAD DATA FROM MASTER может варьироваться от системы к системе, хорошим правилом определения временных затрат будет предположение, что понадобится 1 секунда на 1 Мбайт данных. Это только грубое приближение, но оно близко к реальности, если и главный и подчиненный серверы - одинаковые машины на базе, скажем, процессора Pentium с частотой 700 МГц, соединенные через сеть 100 Мбит/с.
5.3. Детали реализации процесса репликации
367
После того, как подчиненный сервер получит копию данных главного сервера, он просто подключается к нему и ожидает обновлений, которые нужно обработать. Если главный сервер отключится, либо пропадет связь, он будет повторять периодические попытки подключиться снова до тех пор, пока ему это не удастся, и он не продолжит прослушивать изменения. Интервал повторения попыток управляется опцией —master-connect-retry. По умолчанию он составляет 60 секунд. Каждый подчиненный сервер запоминает, на каком этапе он утратил связь. Главный сервер не имеет понятия о том, сколько подчиненных серверов к нему подключено, и какие из них хранят актуальную информацию в любой момент времени.
5.3. Детали реализации процесса репликации Средство репликации MySQL реализовано с использованием трех потоков (один на главном сервере и два - на подчиненном). После выдачи команды START SLAVE подчиненный сервер создает поток ввода-вывода. Этот поток подключается к главному серверу и запрашивает у него операторы, записанные в его бинарных журналах. Главный сервер создает поток для отправки содержимого бинарного журнала подчиненному серверу. Этот поток можно идентифицировать как Binlog Dump в выводе команды SHOW PROCESSLIST на главном сервере. Поток ввода-вывода получает то, что отсылает Binlog Dump, и просто копирует в локальные файлы каталога данных, называемые трансляционными журналами (relay logs). Третий поток - это поток SQL, который создает подчиненный сервер для чтения трансляционных журналов и выполнения хранящихся в них обновлений. Из предыдущего описания следует, что создается три потока на каждый подчиненный сервер. На главном сервере, у которого таких подчиненных серверов несколько, создается один поток для каждого подключенного подчиненного сервера, а каждый из них, в свою очередь, запускает свой собственный поток ввода-вывода и поток SQL. В версиях MySQL, предшествующих 4.0.2, в процессе репликации создавались только два потока (один - на главном сервере и один - на подчиненном). Потоки, занимающиеся вводом-выводом и отработкой SQL-операторов, были скомбинированы в один, и никаких трансляционных журналов не использовалось. Выгода от использования двух потоков на подчиненном сервере состоит в том, что чтение операторов и их выполнение разделены на две независимых задачи. Задача чтения операторов не замедляется, если замедлено их выполнение. Например, если подчиненный сервер не запускался долгое время, при старте его поток ввода-вывода быстро получит все содержимое бинарного журнала от главного сервера, даже если поток обработки SQL будет отставать, и ему потребуются многие часы для того, чтобы догнать. Если подчиненный сервер остановится до того, как поток SQL обработает все полученные операторы, по крайней мере, поток ввода-вывода уже получит все, поэтому безопасная копия операторов уже будет локально сохранена в трансляционных журналах подчиненного сервера для последующего выполнения, когда он будет запущен снова. Это позволит очистить бинарный журнал главного сервера, поскольку ему больше не нужно ждать подчиненного сервера, чтобы передать содержимое этого журнала. Оператор SHOW PROCESSLIST предоставляет информацию о том, какие действия, связанные с репликацией, происходят на главном и подчиненном серверах. Следующий пример иллюстрирует, как эти три потока отображает SHOW PROCESSLIST. Представленный формат вывода характерен для SHOW PROCESSLIST в версии MySQL
368
Глава 5. Репликация в MySQL
4.0.15, когда содержимое столбца State изменилось, чтобы быть более информативным, чем в ранних версиях. На главном сервере вывод SHOW PROCESSLIST выглядит так: mysql> SHOW PROCESSLIST\G *************************** Id: 2
2. row ***************************
User: Host: db: Command: Time: State:
root localhost:32931 NULL Binlog Dump 94 Has sent all binlog to slave; waiting for binlog to be updated Info: NULL
Здесь поток с идентификатором 2 - это поток репликации, созданный для подключенного подчиненного сервера. Из информации следует, что все необработанные изменения данных отправлены подчиненному серверу, и что главный ожидает поступления новых изменений. Н а подчиненном сервере вывод SHOW PROCESSLIST выглядит, как показано ниже: mysql> SHOW PROCESSLIST\G *************************** 2. row *************************** Id: 10 User: system user Host: db: NULL Command: Connect Time: 11 State: Waiting for master to send event Info: NULL Id: User: Host: db: Command: Time: State:
11 system user
NULL Connect 11 Has read all relay log; waiting for the slave I/O thread to update it Info: NULL
Эта информация говорит о том, что поток с идентификатором 10 - это поток вводавывода, который взаимодействует с ведущим сервером, а поток с идентификатором 11 поток SQL, обрабатывающий изменения, сохраненные в трансляционном журнале. В настоящий момент оба потока простаивают, ожидая будущих изменений. Следует отметить, что значение столбца Time отображает, насколько давно подчиненный сервер сравнивался с главным. См. раздел 5.9.
5.3. Детали реализации процесса репликации
369
5.3.1. Состояние потока репликации главного сервера В следующем списке перечислены наиболее общие состояния потока Binlog Dump главного сервера, которые могут появляться в столбце State. Если вы не наблюдаете каких-либо потоков Binlog Dump на главном сервере, значит, репликация не выполняется. То есть в данный момент ни один подчиненный сервер не подключен. •
Sending binlog event to slave (Событие отправки бинарного журнала подчиненному серверу). Бинарный журнал содержит события; событие - это обычно оператор обновления данных, плюс некоторая добавочная информация. Поток считывает события из журнала и отправляет их подчиненному серверу.
• Finished reading one binlog; switching to next binlog (Завершение чтения очередного бинарного журнала; переключение на следующий бинарный журнал). Поток завершил чтение файла бинарного журнала и открывает следующий такой файл, чтобы отправить его подчиненному серверу. • Has sent a l l binlog to slave; waiting for binlog to be updated (Все бинарные журналы отправлены подчиненному серверу; ожидание бинарного журнала для обновления). Поток прочитал все отложенные изменения из бинарных журналов и отправил их подчиненному серверу. Это состояние простоя, с ожиданием появления новых событий в бинарном журнале, появляющихся в результате выполнения операторов изменения данных, которые выполняются на главном сервере. • Waiting to finalize termination (Ожидание звершения). Очень кратковременное состояние, которое случается при останове потока.
5.3.2. Состояние потока репликации ввода/вывода подчиненного сервера В следующем списке перечислены наиболее общие состояния, которые можно увидеть в столбце State для потока ввода/вывода подчиненного сервера. Начиная с версии MySQL 4.1.1, это состояние также может присутствовать и в столбце Slave_IO_State, отображаемом оператором SHOW SLAVE STATUS. To есть теперь вы можете получить хороший обзор того, что происходит, используя только SHOW SLAVE STATUS. • Connecting to master (Соединение с главным сервером). Поток пытается подключиться к главному серверу. • Checking master version (Проверка версии главного сервера). Очень кратковременное состояние, в котором поток пребывает непосредственно после того, как подключение установлено. • Registering slave on master (Регистрация подчиненного сервера на главном сервере). Также очень кратковременное состояние после установления соединения. • Requesting binlog dump (Запрос дампа бинарного журнала). Кратковременное состояние, возникающее после установления соединения. Поток посылает главному серверу запрос содержимого бинарного журнала, начиная с заданного имени файла журнала и позиции в нем.
370
Глава 5. Репликация в MySQL
• Waiting to reconnect after a failed binlog dump request (Ожидание повторного соединения после сбоя запроса дампа бинарного журнала). Если запрос выдал сбой (из-за разрыва соединения), поток переходит в это состояние, при котором находится в спящем режиме, периодически пытаясь восстановить соединение. Интервал между попытками может быть указан опцией —master-connect-retry. • Reconnecting after a failed binlog dump request (Повторное соединение после сбоя запроса дампа бинарного журнала). Поток пытается восстановить соединение с главным сервером. • Waiting for master to send event (Ожидание событий от главного сервера). Поток подключился к главному серверу и ожидает появления событий из бинарного журнала. В этом состоянии он может находиться длительное время, если главный сервер простаивает. Если ожидание длится slave_read_timeout секунд, происходит таймаут. В этом случае поток предполагает, что соединение разорвано и предпринимает попытки повторного подключения. • Queueing master event to the relay log (Запрос события главного сервера для журнала ретрансляции). Поток прочитал событие и копирует его в журнал ретрансляции, чтобы поток SQL мог его обработать. • Waiting to reconnect after a failed master event read (Ожидание повторного соединения после сбоя в чтении события главного сервера). Произошла ошибка при чтении (по причине отключения). Поток переходит в режим ожидания на master-connect-retry секунд и затем повторяет попытку подключения. • Reconnecting after a failed master event read (Повторное соединение после сбоя в чтении события главного сервера). Поток пытается восстановить соединение с главным сервером. Когда соединение устанавливается, поток переходит в состояние Waiting for master to send event. • Waiting for the slave SQL thread to free enough relay log space (Ожидание, пока поток SQL подчиненного сервера освободит достаточно места в журнале ретрансляции). Вы используете ненулевое значение лимита relay_log__space_limit, и журналы ретрансляции выросли настолько, что их общий размер превысил это значение. Поток ввода-вывода ожидает, пока поток SQL не освободит достаточно места, обработав накопившиеся в журналах ретрансляции события, чтобы иметь возможность удалить часть из них. • Waiting for slave mutex on exit (Ожидание семафора завершения от подчиненного сервера). Очень кратковременное состояние при останове потока.
5.3. Детали реализации процесса репликации
371
5.3.3. Состояние потока SQL репликации подчиненного сервера В следующем списке перечислены наиболее общие состояния, которые можно увидеть в столбце State для потока SQL подчиненного сервера: •
Reading event from the relay log (Чтение события из журнала ретрансляции). Поток читает событие из журнала ретрансляции перед началом его обработки. • Has read a l l relay log; waiting for the slave I/O thread to update i t (Прочитаны весь журнал ретрансляции; ожидание, пока поток ввода-вывода не обновит журнал). Поток обработал все события из файлов журнала ретрансляции и ждет, когда поток ввода-вывода запишет туда новые события. • Waiting for slave mutex on exit (Ожидание семафора завершения от подчиненного сервера). Очень кратковременное состояние при останове потока. Столбец State для потока SQL может также показывать текст оператора. Это означает, что он прочитал событие из журнала ретрансляции, извлек из него оператор и запустил его на выполнение.
5.3.4. Журнал ретрансляции и файлы состояния По умолчанию журналы ретрансляции используют имена файлов в форме имя хоста-relay-bin. ллл, где имя_хоста — это имя подчиненного сервера, а ллл — последовательный номер. Последовательные файлы журналов ретрансляции используют последовательные номера, начиная с 001. Подчиненный сервер учитывает текущие используемые журналы в файле индекса. Имя файла индекса по умолчанию формируется как имя_хоста-re laybin, index. По умолчанию все эти файлы создаются в каталоге данных подчиненного сервера. Имена файлов по умолчанию могут быть изменены с помощью опций сервера —relay-log и —relay-log-lindex. См. раздел 5.8. Файлы журналов ретрансляции имеют тот же формат, что и бинарные журналы, поэтому для их чтения вы можете использовать mysqlbinlog. Журналы ретрансляции автоматически удаляются потоком SQL немедленно после того, как он выполнит все записанные в журналах события и больше в них не нуждается. Не существует никакого явного механизма удаления журналов ретрансляции, поскольку поток SQL заботится об этом. Однако, начиная с MySQL 4.0.14, команда FLUSH LOGS осуществляет ротацию этих журналов, что влияет на момент удаления их потоком SQL. Новый журнал ретрансляции создается при следующих условиях: • Когда поток ввода-вывода запускается первый раз после старта подчиненного сервера (В MySQL 5.0 новый журнал ретрансляции создается при каждом старте потока ввода-вывода, а не только первый раз.) • Когда журналы сбрасываются, например, командой FLUSH LOGS или mysqladmin flash-logs. (Это приводит к созданию нового журнала ретрансляции только в версии MySQL 4.0.14.)
372
Глава 5. Репликация в MySQL
• Когда размер текущего журнала ретрансляции становится слишком большим. Значение "слишком большой" определяется следующим образом: • max_relay_log_size, если max_relay_log_size > 0. • max_binlog_size, если max_relay_log_size = 0, или версия MySQL, предшествующая 4.0.14. Подчиненный сервер репликации создает два дополнительных маленьких файла в каталоге данных. Это файлы состояния, и по умолчанию они называются roaster.info и relay-log.info. Эти файлы содержат информацию, подобную той, что выводит команда SHOW SLAVE STATUS. Как дисковые файлы, они переживают останов подчиненного сервера и при следующем запуске предоставляют ему информацию о том, на каком месте остановилось чтение бинарных журналов главного сервера и на каком - обработка его собственных журналов ретрансляции. Файл master.info обновляется потоком ввода-вывода. До MySQL 4.1 соответствие между строками в файле и столбцами, которые выводит SHOW SLAVE STATUS, было таким: Строка
Описание
1 2 3 4
Master_Log__File Read_Master_Log_Pos Master_Host Master_User
5
Пароль (не выводится командой SHOW SLAVE STATUS)
6 7
Master_Port Connect__Retry
Начиная с MySQL 4.1, файл включает количество строк и информацию об опциях SSL: Строка
Описание
1 2 3 4 5 6 7 8 9 10 11 12 13 14
Количество строк в файле Master_Log_File Read_Master_Log_Pos Master_Host MasterJJser Пароль (не выводится командой SHOW SLAVE STATUS) Master_Port Connect_Retry Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key
Файл relay-log.info обновляется потоком SQL. Соответствие между строками в файле и столбцами, выводимыми командой SHOW SLAVE STATUS, выглядит следующим образом:
5.4. Настройка репликации Строка
Описание
1 2 3 4
Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Exec_Master_Log_Pos
373
Когда выполняется резервное копирование данных подчиненного сервера, содержимое этих файлов также нужно копировать вместе с файлами журналов ретрансляции. После восстановления из резервной копии эти файлы понадобятся для продолжения репликации. Если вы потеряете файлы журналов ретрансляции, но у вас останется файл relay-log.info, вы можете определить по нему, насколько далеко продвинулся поток SQL в чтении и выполнении обновлений бинарного журнала главного сервера. Затем МОЖНО выдать CHANGE MASTER ТО вместе С опциями MASTER_LOG_FILE и MASTER_LOG_POS, чтобы заставить подчиненный сервер перечитать бинарный журнал главного сервера, начиная с заданного места. Это требует, чтобы бинарный журнал на главном сервере все еще существовал. Если вашему подчиненному серверу приходится реплицировать операторы LOAD DATA INFILE, вы должны будете также создать резервные копии всех файлов SQL_LOAD-*, находящиеся в каталоге, который подчиненный сервер использует для этих целей. Эти файлы понадобятся ему для продолжения репликации прерванных операторов LOAD DATA INFILE. Местоположение каталога задается опцией —slave-load-tmpdir. Если каталог не указан, по умолчанию им будет значение переменной tmpdir.
5.4 Настройка репликации Здесь представлено краткое описание настройки полной репликации вашего текущего сервера MySQL. Предполагается, что вам нужно реплицировать все базы данных, и вы никогда ранее не выполняли конфигурирование репликации. Вам придется ненадолго остановить главный сервер, чтобы выполнить шаги, описанные ниже. Процедура описана для случая настройки единственного подчиненного сервера, однако она применима и для настройки множества подчиненных серверов. Хотя этот метод и самый простой для настройки подчиненного сервера, однако, не единственный. Например, если у вас уже есть снимок данных главного сервера, главный сервер имеет набор серверных идентификаторов и бинарная регистрация на нем включена, вы можете настроить подчиненный сервер без останова главного сервера, и даже без блокировки обновлений на нем. Более подробная информация по этому поводу представлена в разделе 5.9. Если вы собираетесь администрировать процесс репликации MySQL, рекомендуем тщательно прочитать всю настоящую главу и попробовать выполнить все инструкции. Вы также должны ознакомиться со всеми опциями запуска репликации, описанными в разделе 5.8. Помните, что эта процедура и некоторые SQL-операторы, упоминаемые далее, ссылаются на привилегию SUPER. До версии MySQL 4.0.2 вместо нее использовалась привилегия PROCESS. 1. Убедитесь, что у вас установлены последние версии MySQL на главном и подчиненном серверах, и что эти версии совместимы, воспользовавшись таблицей из раздела 5.5. Не присылайте нам сообщений об ошибках до тех пор, пока не убедитесь в наличии проблемы в самом последнем выпуске.
374
Глава 5. Репликация в MySQL
2. Настройте пользовательскую учетную запись на главном сервере, которую сможет использовать подчиненный сервер для подключения. Этой учетной записи должна быть предоставлена привилегия REPLICATION SLAVE. Если упомянутая учетная запись будет применяться только для репликации (что рекомендуется), вы не должны выдавать ей никаких дополнительных привилегий. Предположим, что ваш домен называется mydomain.com, и вы хотите создать учетную запись с именем r e p l , чтобы подчиненные серверы смогли ее использовать для доступа к главному серверу с любого хоста вашего домена, указывая в качестве пароля s l a v e p a s s . Чтобы создя-^ учетную запись, выполните следующий оператор GRANT: mysql> GRANT REPLICATION SLAVE ON * . * -> TO f repl'@'%.mydomain.com 1 IDENTIFIED BY ' s l a v e p a s s 1 ; В версии MySQL, предшествующей 4.0.2, привилегии REPLICATION SLAVE не существовало. В место нее нужно было выдавать привилегию FILE: mysql> GRANT FILE ON * . * -> TO 'repl'@'%.mydomain.com'
IDENTIFIED BY ' s l a v e p a s s ' ;
Если вы планируете использовать операторы LOAD TABLE FROM MASTER и LOAD DATA FROM MASTER с хоста подчиненного сервера, то этой учетной записи потребуется выдать дополнительные привилегии: •
Глобальные привилегии SUPER и RELOAD.
•
Привилегию SELECT на все таблицы, которые вы хотите загружать. Любые таблицы главного сервера, на которых учетная запись не сможет выполнить оператор SELECT, будут проигнорированы оператором LOAD DATA FROM MASTER.
3. Если вы применяете только таблицы My ISAM, сбросьте все таблицы и установите блокировку на запись, выполнив команду FLUSH TABLES WITH READ LOCK: mysql> FLUSH TABLES WITH READ LOCK; Оставьте работать клиентскую программу, из которой была выдана команда FLUSH TABLES, чтобы блокировка по чтению осталась в силе. (Если вы выйдете из клиентской программы, блокировка будет снята.) Затем подготовьте снимок данных с главного сервера. Самый простой способ сделать снимок - воспользоваться программой архивации и создать бинарную резервную копию базы данных в каталоге данных главного сервера. Сгодится, например, t a r в среде Unix или же PowerArchiver, WinRAR, WinZIP или подобная в среде Windows. Чтобы с помощью tar создать архив, включающий все базы данных, перейдите в каталог данных главного сервера, после чего выполните следующую команду: shell> tar -cvf /tmp/mysql-snapshot.tar . Если вы хотите, чтобы в архив была включена только база данных t h i s d b , выполните вместо приведенной выше такую команду: shell> tar -cvf /tmp/mysql-snapshot.tar ./this_db Затем скопируйте архивный файл в каталог /tmp на хосте подчиненного сервера. На этой машине перейдите в каталог данных подчиненного сервера и распакуйте архив следующей командой:
5.4. Настройка репликации
375
shell> tar -xvf /trap/mysql-snapshot.tar Возможно, вы не захотите реплицировать базу данных mysql, если подчиненный сервер имеет другой набор пользовательских учетных записей, чем тот, что есть у главного сервера. В этом случае вы должны исключить его из архива. Также вам незачем включать в архив файлы журналов, а также master.info или relay-log.info. Пока действует блокировка по чтению, установленная командой FLUSH TABLES WITH READ LOCK, прочитайте значение имени текущего бинарного журнала и смещения на главном сервере: m y s q l > SHOW MASTER STATUS; + + + + + I File I Position | Binlog_Do_DB | Binlog_Ignore_DB | + + + + + I mysql-bin.003 | 73 | test | manual,mysql | + + + + + В столбце File представлено имя файла журнала, а в столбце Position - смещение. В данном примере показано имя mysql-bin.003 и смещение 73. Запишите эти значения. Они понадобятся позже, при настройке подчиненного сервера. Эти значения представляют собой координаты репликации, с которых подчиненный сервер должен начать обработку новых изменений, полученных от главного сервера. После того, как вы получите снимок и зафиксируете имя журнала и смещение, можно снять блокировку и разрешить проведение изменений: m y s q l > UNLOCK TABLES; Если вы применяете таблицы InnoDB, то в идеальном случае должны использовать инструмент InnoDB Hot Backup. Он делает полный снимок, не требуя установки каких-либо блокировок на главном сервере, и записывает имя журнала и смещение, соответствующие снимку, который будет использоваться позже на подчиненном сервере. InnoDB Hot Backup - это дополнительный коммерческий (платный) инструмент, который не входит в состав стандартного дистрибутива MySQL. С детальной информацией и снимками экранов этого инструмента можно ознакомиться на его домашней странице h t t p : / /www. innodb. com/manual. php. Если не использовать InnoDB Hot Backup, то самый быстрый способ получения бинарного снимка таблиц InnoDB предполагает останов главного сервера и копирование файлов данных InnoDB, журнальных файлов и файлов определения таблиц (.frm). Чтобы записать имя текущего журнала и значение смещения, выполните следующие команды перед остановкой сервера: m y s q l > FLUSH TABLES WITH READ LOCK; m y s q l > SHOW MASTER STATUS; Записи имени и смещения, полученные командой SHOW MASTER STATUS, будут выглядеть так же, как было показано выше. После этого остановите сервер без снятия блокировки таблиц, чтобы гарантировать, что сервер был остановлен в состоянии, соответствующем записанным значениям имени журнала и смещения: shell> mysqladmin -u root shutdown Альтернативный способ, который работает как для MylSAM-, так и для innoDBтаблиц, предусматривает использование SQL-дампа главного сервера вместо би-
376
Глава 5. Репликация в MySQL нарной копии, как было описано выше. Для этого выполните команду mysqldump —master-data на главном сервере, а позже загрузите файл SQL-дампа в базу данных подчиненного сервера. Однако этот способ медленнее, чем в случае бинарных данных. Если главный сервер ранее был запущен без включенной опции —log-bin, имя журнала и позиция смещения, показанная командой SHOW MASTER STATUS или mysqldump, будут пустыми. В этом случае значениями, которые вам понадобятся позже при настройке репликации на подчиненном сервере, будут пустая строка (")и4.
4. Убедитесь, что раздел [mysqld] в файле my.cnf на хосте главного сервера включает опцию log-bin. Там же должна быть указана опция зегчег-1с!=идентификатор главного сервера, где идентификатор_главного_сервера — положительное целое число от 1 до 2 3 2 - 1. Например: [mysqld] log-bin server-id=l Если эти опции не указаны, добавьте их и перезапустите сервер. 5. Остановите сервер, который предполагается сделать подчиненным, и добавьте в его файл my. cnf следующие строки: [mysqld] server-i 6.=идентифика тор_подчиненного_ серв ера Значение идентификатор_подчиненного_сервера, как и идентификатор_главного_сервера, должно быть положительным целым числом из диапазона от 1 до 2 3 2 - 1. Вдобавок очень важно, чтобы идентификатор подчиненного сервера отличался от идентификатора главного сервера, например: [mysqld] server-id=2 Если вы настраиваете несколько подчиненных серверов, каждый из них должен иметь уникальное значение serverid, отличающееся от того, что указано для главного, и тех, что указаны для остальных подчиненных серверов. Воспринимайте эти идентификаторы как нечто, подобное IP-адресам. Они уникальным образом идентифицируют каждый сервер в рамках сообщества партнеров репликации. Если вы не укажете значение server_id, оно будет установлено равным 1, если не определен master-host, и 2 - в противном случае. Заметьте, что в случае, если server_id будет пропущено, главный сервер будет отвергать попытки подключения от всех подчиненных серверов, и подчиненные серверы не смогут соединиться с ним. Поэтому пропускать server-id будет правильно только в случае резервного копирования с бинарными журналами. 6. Если вы выполняете бинарное резервное копирование данных главного сервера, переместите эти копии в каталог данных подчиненного сервера до его запуска. Убедитесь в корректности набора привилегий доступа к файлам и каталогам. Пользователь подчиненного сервера, от имени которого запускается сервер MySQL, должен иметь права на чтение и запись файлов, так же, как и пользователь главного.
5.4. Настройка репликации
377
Если вы выполняете резервное копирование с помощью mysqldump, запускайте подчиненный сервер первым (см. следующий шаг). 7. Запустите подчиненный сервер. Если ранее репликация на него выполнялась, запустите его с опцией — s k i p - s l a v e - s t a r t , чтобы он не предпринимал немедленных попыток соединения с главным сервером. Возможно, имеет смысл запустить подчиненный сервер с опцией —log-warnings, чтобы можно было получать более подробные сообщения о возникающих проблемах (например, связанных с сетью или подключением). 8. Если вы выполнили бинарное резервное копирование данных главного сервера с помощью mysqldump, загрузите файл дампа на подчиненный сервер: s h e l l > mysql -u r o o t -p < dump_file.sql 9. Выполните следующие операции на подчиненном сервере, указав конкретные значения опций для своей системы: mysql> CHANGE MASTER TO -> MASTER_HOST=' имя_хоста_главного_сервера', -> MASTER_USER='имя_пользователя_репликации', -> MASTER_PASSWORD='лароль_релликации ' ,
-> MASTER_LOG_FILE= * имя_файла_записанного_журнала%, -> MASTER_LOG_POS=лозиция_в_залисаняом_журнале; Ниже показаны максимальные длины строковых опций: MASTERJiOST 60 MASTERJJSER 16 MASTER_PASSWORD 32 MASTER_LOG_FILE 255
10. Запустите потоки репликации подчиненного сервера: mysql> START SLAVE; После выполнения этой процедуры подчиненный сервер должен подключиться к главному и захватить все изменения, которые произошли с момента получения первоначального снимка данных. Если вы забудете установить на главном сервере значение server-id, подчиненные серверы не смогут к нему подключиться. Если вы забудете установить на подчиненном сервере значение server-id, то получите следующее сообщение об ошибке в его журнале ошибок:
Warning: You should set server_id to a non-0 value if master_host is set; We force the server id to 2, but this MySQL server will not act as a slave. Предупреждение: Вы должны установить server_id в ненулевое значение, если установлен master_host; server_id принудительно установлен в 2, однако этот сервер MySQL не будет действовать в качестве подчиненного. Там же вы найдете сообщения об ошибках, если подчиненный сервер не сможет подключиться к подчиненному по каким-то другим причинам. Как только подчиненный сервер начинает репликацию, в его каталоге данных появляются два файла - один с именем m a s t e r . i n f o , а другой - с именем r e l a y - l o g . i n f o . Подчиненный сервер использует эти файлы для отслеживания, какую часть бинарного журнала главного сервера он успел обработать. Не удаляйте и не редактируйте эти файлы за исключением ситуаций, когда вы точно знаете, что делаете, и понимаете воз-
378
Глава 5. Репликация в MySQL
можные последствия своих действий. И даже в этом случае предпочтительно использовать команду CHANGE MASTER TO. На заметку! Й, Содержимое файла master. i n f o перекрывает значение некоторых опций, указанных в командр ной строке или в файле my. cnf (см. раздел 5.8). Как только вы получите снимок, можете использовать его для настройки других подчиненных серверов, выполнив соответствующую часть только что описанной процедуры. Нет необходимости готовить другой снимок данных главного сервера, можно использовать один и тот же для всех подчиненных серверов.
5.5. Совместимость репликации между версиями MySQL Оригинальный формат бинарных журналов был разработан в версии MySQL 3.23. Он изменялся в версии MySQL 4.0, а затем - в версии MySQL 5.0. Это имеет некоторые последствия, если вы обновляете серверы, участвующие в репликации, как описано в разделе 5.6. В том, что касается репликации, любые выпуски MySQL 4.1.x и MySQL 4.0.x идентичны, так как они имеют одинаковый формат бинарных журналов. Таким образом, любые серверы этих версий совместимы, и репликация между ними должна работать без проблем. Исключением из этого правила является то, что выпуски MySQL от 4.0.0 до 4.0.2 были ранними, "сырыми", и поэтому использоваться не должны. (Такими были альфа-версии серии выпусков 4.0. Их совместимость описана в документации, поставляемой с дистрибутивами.) В табл. 5.1 описывается совместимость репликации главный/подчиненный между различными версиями MySQL. Таблица 5.1. Совместимость репликации в различных версиях MySQL
Подчиненный сервер версии 3.23.33 и выше Подчиненный сервер версии 4.0.3 и выше Подчиненный сервер версии 5.0.0
Главный сервер версии 3.23.33 и выше
Главный сервер версии 4.0.3 и выше или любой версии 4.1 .х
Главный сервер версии 5.0
Да
Нет
Нет
Да
Да
Нет
Да
Да
Да
В качестве основного правила, мы рекомендуем использовать последние версии MySQL, поскольку средства репликации постоянно развиваются. Также мы рекомендуем устанавливать MySQL одной и той же версии на главном и на подчиненных серверах.
5.6. Модернизация установок репликации Когда вы модернизируете серверы, участвующие в репликации, процедура обновления зависит от текущих версий сервера и версий, до которых происходит обновление.
5.6. Модернизация установок репликации
379
5.6.1. Модернизация репликации до версии 4.0 или 4.1 Этот раздел посвящен модернизации репликации от MySQL 3.23 до MySQL 4.0 или 4.1. Сервер версии 4.0 должен иметь номер выпуска не ниже 4.0.3, как было описано в разделе 5.5. При выполнении модернизации главного сервера от версии MySQL 3.23 до версии 4.0 или 4.1, первым делом следует убедиться, что все подчиненные серверы уже модернизированы до версии 4.0 или 4.1. Если это еще не сделано, обновите сначала подчиненные серверы. Остановите каждый из них, выполните модернизацию, перезапустите сами серверы и перезапустите репликацию. Модернизацию можно провести безопасно в соответствии с описанной ниже процедурой, при этом предполагается, что на главном сервере установлена версия MySQL 3.23, а на всех подчиненных серверах - версия MySQL 4.0 или 4.1. Имейте в виду, что после того, как главный сервер будет модернизирован, вы не должны перезапускать репликацию, используя старые бинарные журналы из версии 3.23, поскольку это может вызвать сбои на подчиненных серверах версий 4.0 и 4.1. 1. Заблокируйте все обновления на главном сервере с помощью команды FLUSH TABLES WITH READ LOCK.
2. Подождите, пока подчиненные серверы обработают все накопившиеся изменения, полученные от главного сервера. Используйте команду SHOW MASTER STATUS на главном сервере для получения информации о его текущем бинарном журнале и позиции в нем. Затем для каждого подчиненного сервера используйте полученные значения в команде SELECT MASTER_POS_WAIT(). Это заблокирует подчиненный сервер до тех пор, пока он не освободится. После этого выдайте команду STOP SLAVE на подчиненном сервере. 3. Остановите главный сервер и модернизируйте его до версии MySQL 4.0 или 4.1. 4. Перезапустите главный сервер и запишите имя вновь созданного им файла бинарного журнала. Вы можете получить это имя с помощью команды SHOW MASTER STATUS на главном сервере. Затем выполните следующие команды на каждом из подчиненных серверов: mysql> CHANGE MASTER TO MASTER_LOG_FILE=' имя_бинарного_журнала', -> MASTERJLOG_POS=4; mysql> START SLAVE;
5.6.2. Модернизация репликации до версии 5.0 Этот раздел посвящен модернизации репликации от версии MySQL 3.23, 4.0 или 4.1 до версии 5.0.0. Сервер MySQL 4.0 должен иметь номер выпуска не ниже 4.0.3, как описывалось в разделе 5.5. Первое, что следует иметь в виду - MySQL 5.0.0 является альфа-выпуском. Он предназначен для того, чтобы работать лучше предшествующих версий (проще выполнять модернизацию, осуществлять репликацию некоторых важных переменных сеанса, например, sqljnode). Однако он пока еще недостаточно хорошо протестирован. Как и в отношении любого альфа-выпуска, мы пока не рекомендуем использовать его в ответственной производственной среде. При выполнении модернизации главного сервера от MySQL 3.23, 4.0 или 4.1 до версии 5.0.0, первым делом следует убедиться, что все подчиненные уже модернизированы
380
Глава 5. Репликация в MySQL
до версии MySQL 5.O.O. Если это еще не сделано, обновите сначала подчиненные серверы. Остановите каждый из них, проведите модернизацию, перезапустите сами серверы и перезапустите репликацию. Подчиненные серверы 5.0.0 могут читать старые бинарные журналы, которые были записаны до обновления, и обрабатывать их содержимое. Файлы журналов ретрансляции на подчиненных серверах будут иметь формат 5.0.0. После модернизации подчиненных серверов остановите главный сервер, обновите его до версии 5.0.0 и затем перезапустите. MySQL 5.0.0 может читать старые бинарные журналы, которые были записаны до обновления, и отправлять их подчиненным серверам MySQL 5.O.O. Подчиненные серверы распознают старый формат и корректно его обработают. Бинарные журналы, записанные главным сервером после обновления, будут иметь правильный формат 5.0.0, и подчиненные серверы также его правильно обработают. Другими словами, не нужно принимать каких-то особых мер при модернизации до версии 5.0.0, кроме того, что подчиненные серверы должны быть обновлены раньше главного. Имейте в виду, что возврат к версии, предшествующей 5.0.0, не будет столь простым. Вы должны будете убедиться, что все бинарные и журналы ретрансляции полностью обработаны, и вы можете их удалить прежде, чем начнете возврат к старой версии.
5.7. Возможности репликации и известные проблемы В приведенном ниже списке перечислены поддерживаемые и неподдерживаемые на сегодняшний день функции. Дополнительная информация о репликации, касающаяся InnoDB, содержится в разделе 9.7.5. • Репликация
корректно
выполняется
со
значениями AUTO_INCREMENT,
LAST_INSERT_ID() И TIMESTAMP.
• Функции USER(), UUIDO и LOAD_FILE() реплицируются без изменений, и поэтому на подчиненном сервере работают ненадежно. Это также верно для CONNECTION_ID() на подчиненных серверах до версии 4.1.1. Новая функция PASSWORD () хорошо реплицируется на главных серверах версии 4.1.1 и выше, подчиненные также должны быть версии 4.1.1 и выше, чтобы принимать ее. Если используются более старые подчиненные серверы, и есть необходимость выпонять репликацию PASSWORD () с главного сервера версии 4.1.x, вы должны запустить главный сервер с опцией --old-password, чтобы он использовал старую реализацию функции PASSWORD(). (Имейте в виду, что реализация PASSWORD() в MySQL 4.1.0 отличается от всех других версий MySQL. В средах с репликацией применения версии MySQL 4.1.0 лучше избегать.) • Переменная FOREIGNKEYCHECKS реплицируется, начиная с MySQL 4.0.14. Переменные sqljnode, UNIQUE_CHECKS и SQL_AUTO_IS_NULL реплицируются, начиная с версии 5.0.0. Переменные SQL_SELECT_LIMIT и table_type пока не реплицируются. • Необходимо использовать одинаковые наборы символов (—default-character-set) на главном и подчиненном серверах. В противном случае вы можете получить ошибку дублирования ключа на подчиненном сервере, поскольку ключ, являющийся уникальным в одном наборе символов, может таковым не оказаться в другом. Наборы символов будут реплицироваться в версии 5.0.x.
5.7. Возможности репликации и известные проблемы
381
•
Есть возможность реплицировать транзакционные таблицы на главном сервере, используя нетранзакционные на подчиненном сервере. Например, вы можете реплицировать главную таблицу InnoDB как подчиненную MylSAM. Однако если делать это, то можно столкнуться с проблемой, если подчиненный сервер остановится во время выполнения блока BEGIN/COMMIT, так как подчиненный сервер будет стартовать с начала блока BEGIN. Эта ошибка находится в нашем списке TODO и будет исправлена в ближайшее время.
•
Операторы обновления, которые ссылаются на пользовательские переменные (переменные в форме @имя_леремеяяой), плохо реплицируются в версиях 3.23 и 4.0. В версии 4.1 этот недостаток исправлен. Помните, что имена пользовательских переменных нечувствительны к регистру, начиная с MySQL 5.0. Это нужно принимать во внимание при настройке репликации между версией 5.0 и предшествующими версиями.
•
Подчиненный сервер может подключаться к главному, используя SSL, если оба они имеют версию 4.1.1 или выше.
•
Если в операторе CREATE TABLE на главном сервере применяются конструкции DATA DIRECTORY или INDEX DIRECTORY, те же конструкции применяются на подчиненном сервере. Это может вызвать проблемы, если соответствующий каталог отсутствует в файловой системе хоста подчиненного сервера, или же он есть, но недоступен подчиненному серверу. Начиная с MySQL 4.0.15, введена опция sqljnode под названием NO_DIR_IN_CREATE. Если подчиненный сервер работает в SQL-режиме, включающем эту опцию, он будет просто игнорировать эти конструкции перед репликацией оператора CREATE TABLE. В результате файлы данных и индексов My ISAM создаются в каталоге таблиц базы данных.
•
Хотя мы никогда не слышали о том, чтобы такое случалось, существует теоретическая возможность появления расхождений в данных на главном и подчиненном серверах, если запрос спроектирован таким образом, что модификация данных недетерминирована и отдается на усмотрение оптимизатора запросов (это в любом случае плохая практика, даже вне контекста репликации). Детальное объяснение этой ситуации можно найти в разделе 1.8.7.3.
•
До версии M y S Q L 4.1.1 Операторы FLUSH, ANALYZE TABLE, OPTIMIZE TABLE И REPAIR TABLE не записывались в бинарный журнал, а потому не реплицировались на подчиненные серверы. Обычно это не является проблемой, потому что эти операторы не модифицируют данные в таблицах. Однако, в некоторых случаях, это может приводить к сложностям. Если вы реплицируете таблицы привилегий из базы данных mysql и обновляете эти таблицы непосредственно, без операторов GRANT, то должны следом давать команду FLUSH PRIVILEGES, чтобы измененные привилегии пользователей вступили в силу. Также, если вы используете FLUSH TABLES, когда переименовываете таблицу My ISAM, являющуюся частью MERGEтаблицы, то должны вручную выдать команду FLUSH TABLES на подчиненных серверах. Начиная с MySQL 4.1.1, эти операторы фиксируются в бинарном журнале (если только не будет указан NO_WRITE_TO_BINLOG или его псевдоним LOCAL). Исключения составляют FLUSH LOGS, FLUSH MASTER, FLUSH SLAVE И FLUSH TABLES WITH READ LOCK, которые не регистрируются в журнале в любом случае. (Каждый из упомянутых операторов может привести к проблемам, если их реплицировать на подчиненный сервер.)
382
Глава 5. Репликация в MySQL
• MySQL поддерживает только один главный сервер и множество подчиненных. Позже мы планируем добавить алгоритм голосования для автоматической смены главного сервера, если с текущим что-то неладно. Мы также собираемся представить процессы "агентов", помогающие балансировать нагрузку путем отправки операторов SELECT другим подчиненным серверам. • Когда сервер останавливается и перезапускается, его таблица MEMORY (HEAP) становится пустой. Начиная с MySQL 4.0.18, главный сервер реплицирует этот эффект следующим образом: первый раз, когда главный сервер использует таблицу MEMORY после запуска, он уведомляет подчиненные серверы о том, что таблица должна быть очищена, записывая в бинарный журнал оператор DELETE FROM для этой таблицы. Более детальную информацию можно найти в разделе 8.3. • Временные таблицы реплицируются за исключением случаев, когда вы останавливаете подчиненный сервер (а не только потоки репликации подчиненного сервера), и у вас есть некоторые реплицированные временные таблицы, которые используются в операторах обновления, еще не обработанных на подчиненном сервере. Если вы остановите подчиненный сервер, временные таблицы, которые нужны этим операторам, станут недоступными после следующего запуска. Чтобы избежать этой проблемы, не останавливайте подчиненный сервер, пока на нем есть открытые временные таблицы. Вместо этого используйте следующую процедуру: 1. Введите команду STOP SLAVE. 2. С помощью SHOW STATUS просмотрите значение переменной lave_open_temp_tables. 3. Если ее значение равно 0, выполните команду mysqladmin shutdown для остановки подчиненного сервера. 4. Если ее значение не равно 0, перезапустите потоки репликации подчиненного сервера командой START SLAVE. 5. Повторите процедуру позже, в надежде на большее везение. Мы планируем решить эту проблему в ближайшем будущем. • Безопасно соединять сервера в циклические отношения главный/подчиненный с помощью опции --log-slave-updates. Помните, однако, что при таком варианте настройки многие операторы не будут работать корректно, если только ваш клиентский код не написан так, чтобы позаботиться о потенциальных проблемах, которые могут возникнуть из-за обновлений данных в разном порядке на разных серверах. Это означает, что вы можете настроить цепочку репликации таким образом: А ->
В ->
С ->
А
Идентификаторы сервера закодированы в бинарном журнале, поэтому сервер А будет знать, что событие, которое он прочитает, изначально было порождено им, и не станет его обрабатывать. Поэтому бесконечных циклов не будет. Однако эта циклическая настройка будет работать только тогда, когда вы не производите конфликтующих между собой обновлений таблиц. Другими словами, если вы вносите данные и на А, и на С, вы не должны никогда вставлять строку на А, ключ которой может конфликтовать со строкой, вставленной на С. Также вы не должны обновлять одни и те же строки на двух серверах, если порядок их обновления имеет значение.
5.7. Возможности репликации и известные проблемы
383
• Если оператор, выполняющийся на подчиненном сервере, приводит к ошибке, поток SQL прерывается и в журнал ошибок записывается сообщение. Вы должны затем подключиться к подчиненному серверу вручную, исправить проблему (например, отсутствующая таблица) и затем запустить START SLAVE. • Совершенно безопасно останавливать главный сервер и перезапускать его позже. Если подчиненный сервер теряет соединение с главным, он немедленно пытается его восстановить. Если ему это не удается, он повторяет попытки периодически (по умолчанию - каждые 60 секунд; это значение можно изменить с помощью опции —master-connect-retry). Подчиненный сервер также справляется с проблемами пропадания сети. Однако он известит о проблемах с сетью только в случае, если не получит от главного никаких данных в течение slave_net_timeout секунд. Если такие отказы кратковременны, вы можете уменьшить значение slave_net_timeout (см. раздел 4.2.3). • Остановка подчиненного сервера (штатная) также безопасна, поскольку он отслеживает позицию, на которой останавливает работу. Аварийные остановки могут привести к проблемам, особенно, если дисковый кэш не был сброшен, прежде чем система остановилась. Устойчивость ваших систем к отказам может быть значительно повышена, если вы применяете качественные источники бесперебойного питания. • Из-за нетранзакционной природы таблиц My ISAM существует возможность иметь оператор, который только частично обновил таблицу и возвратил код ошибки. Это может случиться, например, при многострочной вставке, когда одна их строк нарушила ограничение уникальности ключа, либо когда долго выполняющаяся операция обновления была прервана после того, как обновила только часть строк. Если подобное случается на главном сервере, поток подчиненного сервера останавливается и ожидает решения администратора базы данных о том, что с этим делать, если только не окажется, что код ошибки вполне легитимный и выполнение оператора на подчиненном сервере приведет к тому же коду ошибки. Если поведение, основанное на проверке кода ошибки, нежелательно, некоторые или все ошибки могут быть маскированы (проигнорированы) с помощью опции —slave-skip-errors. Эта опция появилась в MySQL 3.23.47. • Если вы обновляете транзакционные таблицы из нетранзакционных внутри сегмента BEGIN/COMMIT, записи бинарного журнала могут оказаться несинхронизированными, если какой-нибудь поток изменит нетранзакционную таблицу до завершения транзакции. Это объясняется тем, что транзакция записывается в бинарный журнал только при ее фиксации. • До версии 4.0.15 любое обновление нетранзакционной таблицы записывалось в бинарный журнал немедленно после его проведения, в то время как транзакционные обновления записывались после COMMIT, либо не записывались вовсе, если применялся ROLLBACK. Вы должны принимать это во внимание, когда обновляете и транзакционные, и нетранзакционные таблицы в пределах одной транзакции (это имеет значение не только для репликации, но также и в случае, если бинарная регистрация применяется для резервных копий). В версии 4.0.15 было изменено поведение бинарных журналов транзакций, в которых участвуют таблицы разных типов, что решило проблему (последовательность операторов в бинарном журнале записывается правильно, даже если применяется ROLLBACK). Проблема, которая
384
Глава 5. Репликация в MySQL осталась, состоит в том, что когда второй сеанс обновляет нетранзакционную таблицу в то время, когда в первом сеансе не окончена транзакция, то порядок операторов все еще может оказаться неверным, потому что обновление второго сеанса регистрируется в журнале немедленно после выполнения.
В следующем списке перечислены проблемы репликации в версии MySQL 3.23, которые были успешно решены в MySQL 4.O. •
LOAD DATA INFILE обрабатывается правильно до тех пор, пока файл данных находится на главном сервере во время репликации.
•
LOAD DATA LOCAL INFILE более не пропускается на подчиненном сервере, как это было в версии 3.23.
•
В версии 3.23 функция RANDO в операторах обновления данных реплицировалась неправильно. Используйте RAND {некоторое_неслучайное_выражение), если вы реплицируете обновления с вызовом RAND (). Например, в качестве аргумента RAND () можно использовать UNIX_TIMESTAMP ().
5.8. Опции запуска репликации И на главном, и на подчиненном серверах вы должны использовать опцию server-id для установки уникального идентификатора репликации. Для каждого главного и подчиненного серверов потребуется указать уникальное положительное число в пределах от 1 до 2 3 2 - 1, например, server-id=3. Опции, которые можно использовать на главном сервере для управления бинарной регистрацией, описаны в разделе 4.8.4. Ниже описаны опции, которые можно применять на подчиненном сервере репликации. Их можно указывать в командной строке или конфигурационном файле. Некоторые опции репликации подчиненного сервера обрабатываются специальным образом, в том смысле, что они игнорируются, если на момент старта сервера уже существует файл master.info, содержащий собственные значения. Подобным образом обрабатываются следующие опции: • —master-host • —master-user • —master-password • —master-port • —master-connect-retry Начиная с MySQL 4.1.1, следующие опции также обрабатываются специальным образом: • —master-ssl • —master-ssl-ca • —master-ssl-capath • —master-ssl-cert • —master-ssl-cipher • —master-ssl-key Формат файла master.info в MySQL 4.1.1 изменился, и теперь включает значения, соответствующие опциям SSL. Вдобавок, формат этого файла предусматривает, что в
5.8. Опции запуска репликации
385
первой строке указывается общее количество строк в нем. Если вы обновляете старый сервер до версии 4.1.1, он автоматически обновит файл master.info в соответствии с новым форматом. Однако если вы возвращаетесь от версии 4.1.1 к более старой, вам придется вручную убрать первую строку этого файла перед первым запуском сервера. Помните также, что после возврата к старой версии сервер не сможет больше использовать SSL-соединения для подключения к главному серверу. Если файл master.info не существует на момент запуска подчиненного сервера, для этих опций он использует те значения, которые указаны в командной строке или конфигурационном файле. Это случается, когда вы самый первый раз запускаете сервер в качестве подчиненного в процессе репликации, либо после того, как вы даете команду RESET SLAVE, останавливаете и перезапускаете подчиненный сервер. Если файл master.info существует на момент старта подчиненного сервера, переданные значения этих опций игнорируются. Вместо них используются значения, прочитанные из файла master. info. Если вы перезапускаете подчиненный сервер с другими значениями опций, которые соответствуют указанным в master.info, эти новые значения не имеют эффекта, поскольку сервер продолжает использовать файл master.info. Чтобы использовать новые значения, вы должны либо перезапустить сервер снова, удалив файл master.info, или (что предпочтительнее) с помощью команды CHANGE MASTER TO сбросить значения прямо в процессе работы подчиненного сервера. Предположим, что вы указали следующую опцию в файле my. cnf: [mysqld] master-host=HeKOTopNH_xocT
Первый раз, когда вы запускаете сервер как подчиненный в репликации, он читает и использует значение этой опции из файла my.cnf. Затем он записывает это значение в файл master.info. При следующем старте он читает имя хоста главного сервера только из файла master. info и игнорирует значение, заданное в конфигурационном файле. Если вы модифицируете файл my.cnf, чтобы изменить имя хоста главного сервера на другой_хост, это изменение не возымеет никакого эффекта. Вместо этого следует воспользоваться оператором CHANGE MASTER TO. Поскольку сервер отдает предпочтение существующему файлу master.info при чтении описанных опций запуска, возможно, вы предпочтете вообще их не использовать, а вместо этого указывать их с помощью оператора CHANGE MASTER TO. В следующем примере продемонстрировано более продуманное применение опций запуска для конфигурирования подчиненного сервера: [mysqld] server-id=2 master-host=db-master.mycompany.com master-port=3306 master-user=pertinax master-password=freitag master-connect-retry=60 report-host=db-slave.mycompany.com В следующем перечне описаны опции запуска для управления репликацией. Многие из них могут быть сброшены в процессе работы сервера с помощью команды CHANGE
386
Глава 5. Репликация в MySQL
MASTER TO. Другие, такие как опции —replicate-*, могут быть установлены только при запуске подчиненного сервера. Мы планируем исправить это. •
—log-slave-updates. Обычно изменения, полученные подчиненным сервером от главного, не записываются в его бинарный журнал. Эта опция указывает подчиненному серверу, что изменения, которые проводит его поток SQL репликации, должны регистрироваться в журнале. Чтобы эта опция возымела эффект, подчиненный сервер должен быть запущен с опцией —bin-log, включающей бинарную регистрацию. —log-slave-updates применяется в случаях, когда нужно построить цепочку реплицируемых серверов, например, по такой схеме: А -> В -> С
То есть А служит главным для подчиненного В, а В служит главным для С. Чтобы эта схема работала, В должен быть одновременно и главным, и подчиненным. Вы должны запускать и А, и В с опцией --bin-log, чтобы разрешить бинарную регистрацию, а В еще и с опцией —log-slave-updates. •
—log-warnings. Заставляет подчиненный сервер печатать больше сообщений о том, что он делает. Например, он известит вас об успешном восстановлении соединения после сбоя сети и сообщит о том, как стартовал каждый из потоков, обслуживающих репликацию. Эта опция касается не только репликации. Она заставляет генерировать сообщения о многих аспектах активности сервера.
•
--master-connect-retry=ceKyjwi. Период времени в секундах, в течение которого сервер ожидает перед повторными попытками подключиться в случае остановки главного сервера или отказа сети. Значение, указанное в master.info, имеет приоритет, если оно может быть прочитано. Если не установлено явно, принимается равным 60 секундам.
•
—master-host=xocT. Имя хоста или IP-адрес главного сервера репликации. Если эта опция не указана, потоки репликации подчиненного сервера не запускаются. Значение, указанное в master. info, имеет приоритет, если может быть прочитано.
•
—master-info-f Пе=имя_файла. Имя файла, в который подчиненный сервер записывает информацию о главном сервере. Значение по умолчанию - mysql.info, размещенный в каталоге данных.
•
—master-password=napcitfb. Пароль пользовательской учетной записи, которую поток подчиненного сервера использует при подключении к главному серверу. Значение, указанное в master. info, имеет приоритет, если может быть прочитано. Если пароль не установлен, он считается пустым.
•
—master-port=HOMep_nopTa. Порт TCP/IP, который использует главный сервер для прослушивания соединений. Значение, указанное в master.info, имеет приоритет, если может быть прочитано. Если не установлено, во внимание принимается жестко закодированное в сервере. Если вы не указали другое для configure при сборке сервера, то оно равно 3306. • —master-ssl —master-ssl-capath=имя_кaтaлoгa —master-ssl-cert=H^3^aj^7a —master-ssl-cipher=cnHCOK_iuH$poB
5.8. Опции запуска репликации
387
Эти опции используются для настройки защищенного соединения с главным сервером через SSL. Их значения такие же, как и у соответствующих опций --ssl, —ssl-ca, —ssl-capath, —ssl-cert, —ssl-cipher и —ssl-key, которые описаны в разделе 4.5.8.5. Значения, указанные в master.info, имеют приоритет, если могут быть прочитаны. Эти опции работают, начиная с MySQL 4.1.1. —таз1ег-изег=имя_пользователя. Имя пользовательской учетной записи, которую поток подчиненного сервера использует при подключении к главному. Учетная запись должна иметь привилегию REPLICATION SLAVE. (До MySQL 4.0.2 вместо этого она должна была иметь привилегию FILE.) Значение, указанное в master .info, имеет приоритет, если может быть прочитано. Если имя пользователя не указано, предполагается по умолчанию test. —max-relay-log-size=#. Для автоматической ротации журналов ретрансляции (см. раздел 4.2.3). Эта опция действительна, начиная с MySQL 4.0.14. —read-only. Эта опция запрещает какие-либо изменения данных, кроме тех, что выполняет поток репликации или пользователь с привилегией SUPER. Может оказаться полезным, если необходимо гарантировать, чтобы подчиненный сервер не допускал никаких обновлений данных от клиентов. Эта опция действительна, начиная с MySQL 4.0.14. —ге1ау-1од=имя_файла. Имя журнала ретрансляции. По умолчанию принимается равным имя_хоста-ге1ау-Ып.ллл, где имя_хоста - имя хоста подчиненного сервера, а ллл означает, что файлы журнала ретрансляции создаются в числовой последовательности. Вы можете указать эту опцию, чтобы использовать имена журналов, не зависящие от имени хоста; если файлы журналов получаются слишком большим (и вы не хотите уменьшать max_relay_log_size), и необходимо поместить их в месте, отличном от каталога данных; если требуется увеличить скорость за счет распределения нагрузки между дисками. —ге1ау-1од-1пс1ех=имя_файла. Указывает местоположение и имя файла индекса журнала ретрансляции. Значение по умолчанию - имя_хоста-ге1ау-Ып. index, где имя_хоста - имя хоста подчиненного сервера. —relay-log-infо-И1е=имя_файла. Имя файла, в который подчиненный сервер записывает информацию о журналах ретрансляции. По умолчанию это relaylog, info, размещенный в каталоге данных. —relay-log-purge={0 11}. Включает и отключает автоматическую очистку журналов ретрансляции, как только они становятся не нужны. Значение по умолчанию - 1 (включено). Это глобальная переменная, которую можно изменить установкой SET GLOBAL relay_log_purge. Эта опция действительна, начиная с MySQL 4.1.1. --relay-log-space-limit=#. Устанавливает верхний предел общего размера всех журналов ретрансляции на подчиненном сервере (значение 0 означает "не ограничено"). Это удобно для хостов подчиненного сервера, у которых ограничено дисковое пространство. Когда предел достигнут, поток ввода-вывода приостанавливает чтение событий из бинарного журнала главного сервера до тех пор, пока поток SQL не обработает и не удалит некоторые из неиспользуемых файлов жур-
388
Глава 5. Репликация в MySQL налов ретрансляции. Имейте в виду, что этот предел не абсолютен. Существуют случаи, когда потоку SQL требуется больше событий, прежде чем он очистит журналы ретрансляции. В этом случае поток ввода-вывода превысит ограничение до тех пор, пока поток SQL не сможет их очистить. Если этого не делать, можно получить взаимную блокировку (что и случалось в версиях MySQL, предшествующих 4.0.13). Вы не должны устанавливать значение —relay-log-space-limit меньше, чем двойное значение —max-relay-log-size (или —max-bin-log-size, если --max-relay-log-size равно 0). В этом случае существует вероятность, что поток ввода-вывода будет ждать свободного пространства, поскольку —relay-log-space-limit превышен, а поток SQL не будет иметь файлов журналов ретрансляции, которые нужно удалить, и не сможет удовлетворить ожиданий потока ввода-вывода. Это заставляет поток ввода-вывода временно игнорировать —relay-log-space-limit.
•
—герИсаЬе-' является управляющим в вашей командной оболочке, заключите значение опции в кавычки, папример: shell> mysqld ~replicate-rewrite-db= lt cтapaяБД->яoвaяБЛ м
•
—report-host=xocT. Имя хоста или IP-адрес подчиненного сервера, который передается главному серверу при регистрации. Это значение появляется в выводе команды SHOW SLAVE HOSTS на главном сервере. Если вы не хотите, чтобы подчиненный сервер регистрировался на главном, не устанавливайте это значение. Помните, что для главного сервера недостаточно просто прочитать IP-адрес подчиненного сервера из сокета TCP/IP после его подключения. Из-за трансляции сетевых адресов (NAT) или других обстоятельств, связанных с маршрутизацией, этот IP-адрес может оказаться некорректным для подключения к подчиненному серверу с главного сервера или с других хостов. Эта опция действительна, начиная с MySQL 4.O.O.
•
—report-port=HOMep_nopTa. Порт TCP/IP для подключения к подчиненному серверу, который передается главному серверу во время регистрации. Устанавливайте эту опцию, если подчиненный прослушивает нестандартный порт, или если у вас настроен какой-нибудь специальный туннель от главного или от других клиентов к подчиненному. Если вы не уверены, не указывайте эту опцию. Эта опция действительна, начиная с MySQL 4.O.O.
•
—skip-slave-start. Предписывает подчиненному серверу не запускать при старте потоки, обслуживающие репликацию. Чтобы запустить их позже, воспользуйтесь оператором START SLAVE.
•
—slave_compressed_protocol={0,1}. Если эта опция установлена в I, используется сжатие протокола взаимодействия между главным и подчиненным серверами, если они оба поддерживают такое сжатие.
5.8. Опции запуска репликации
391
•
—slave-load-tmpdir=HMH^a^a. Имя каталога, в котором подчиненный сервер создает временные файлы. Эта опция по умолчанию содержит значение, хранящееся в системной переменной tmpdir. Когда поток SQL подчиненного сервера реплицирует оператор LOAD DATA INFILE, он извлекает файл, предназначенный для загрузки, из журнала ретрансляции в каталог временных файлов, затем загружает его в таблицу. Если файл, загруженный в базу данных на главном сервере, был очень большим, временный файл на подчиненном тоже будет большим. Поэтому можно посоветовать использовать эту опцию, чтобы подчиненный сервер размещал временные файлы в каталоге, находящемся в файловой системе, в которой много свободного места. В этом случае вы также можете использовать опцию —relay-log, чтобы разместить журналы ретрансляции в той же файловой системе, потому что журналы ретрансляции также будут огромными. --slave-load-tmpdir должна указывать на каталог в дисковой системе, а не в памяти. Подчиненный сервер нуждается во временных файлах для репликации оператора LOAD DATA INFILE, чтобы пережить перезапуск машины. Этот каталог также не должен очищаться автоматически при перезапуске системы.
•
—slave-net-timeout=ceKyH^ Время ожидания данных от главного сервера, которое выдерживает подчиненный сервер перед тем, как прервать чтение из-за разрыва соединения и попробовать подключиться повторно. Первая попытка предпринимается немедленно после истечения тайм-аута. Интервал между попытками устанавливается с помощью опции --master-connect-retry.
•
—slave-skip-errors= [код_ошибки1,код_ошибки2,... | a l l ] . Обычно репликация останавливается, когда возникает ошибка, что дает возможность вручную устранить несогласованность данных. Эта опция предписывает потоку SQL подчиненного сервера продолжать репликацию, когда оператор возвращает одну из перечисленных в значении опции ошибок. Не используйте эту опцию, если только полностью не понимаете причин возникновения ошибок. Если нет ошибок в настройках репликации, в клиентских программах и в самом MySQL, ошибки, останавливающие репликацию, никогда не должны возникать. Неразборчивое применение этой опции может привести к тому, что произойдет полная рассинхронизация данных на подчиненном и главном серверах, и вы не будете иметь понятия почему. Для указания кодов ошибок нужно использовать числа, сопровождающие сообщения в журнале ошибок подчиненного сервера и в выводе команды SHOW SLAVE STATUS.
Вы можете (но не должны) также использовать крайне не рекомендуемое значение a l l , которое заставит подчиненный сервер игнорировать все ошибки и продолжать работу, независимо от того, что происходит. Нет необходимости говорить, что если вы используете это значение, то никто не сможет дать никаких гарантий целостности ваших данных. Не стоит жаловаться, если ваши данные на подчиненном сервере даже близко не будут похожи на те, что хранятся на главном. В общем, вас предупредили. Примеры: —slave-skip-errors=1062,1053 —slave-skip-errors=all
392
Глава 5. Репликация в MySQL
Правила репликации —replicate-* для определения того, будет ли оператор выполнен на подчиненном сервере или же проигнорирован, оцениваются следующим образом: 1. Есть ли какие-то правила —replicate-do-db или — replicate-ignore-db? • Да. Проверьте их как — binlog-do-db и —binlog-ignore-db (см. раздел 4.8.4). Каков результат проверки? • Игнорировать оператор. Проигнорировать и выйти. • Выполнить оператор. Не выполнять немедленно, отложить решение, перейти к следующему шагу. • Нет. Перейти к следующему шагу. 2. Есть ли какие-то правила --replicate-*-table? • Нет. Выполнить запрос и выйти. • Да. Перейти к следующему шагу. Только таблицы, которые должны обновляться, сравниваются с правилами (INSERT INTO sales SELECT * FROM prices: только sales будет сравниваться с правилом). Если несколько таблиц должны обновляться (многотабличный оператор), первая подходящая таблица (подходящая в смысле "do" или "ignore") побеждает. Таким образом, первая таблица проверяется на соответствие правилу. Далее, если решение не принято, на предмет соответствия правилам проверяется вторая таблица и так далее. 3. Есть ли какие-то правила —replicate-do-table? • Да. Соответствует ли таблица любому из них? • Да. Выполнить запрос и выйти. • Нет. Перейти к следующему шагу. • Нет. Перейти к следующему шагу. 4. Есть ли какие-то правила —replicate-ignore-table? • Да. Соответствует ли таблица любому из них? • Да. Игнорировать запрос и выйти. • Нет. Перейти к следующему шагу. • Нет. Перейти к следующему шагу. 5. Есть ли какие-то правила —replicate-wild-do-table? • Да. Соответствует ли таблица любому из них? • Да. Выполнить запрос и выйти. • Нет. Перейти к следующему шагу. • Нет. Перейти к следующему шагу. 6. Есть ли какие-то правила —-replicate-wild-ignore-table? • Да. Соответствует ли таблица любому из них? • Да. Игнорировать запрос и выйти. • Нет. Перейти к следующему шагу. • Нет. Перейти к следующему шагу. 7. Никаких правил —replicate-* не найдено. Есть ли следующая таблица, которую нужно проверить на предмет соответствия правилам?
5.9. Часто задаваемые вопросы по репликации
393
• Да. Цикл. • Нет. Проверены все таблицы, которые нужно обновлять, и соответствия правилам не найдены. Есть ли правила --replicate-do-table или —replicatewild-do-table? • Да. Игнорировать запрос и выйти. • Нет. Выполнить запрос и выйти.
5.9. Часто задаваемые вопросы по репликации Вопрос. Как настроить подчиненный сервер, если главный уже запущен, и нет желания его останавливать? Ответ. Существует несколько вариантов. Если у вас есть резервная копия данных главного сервера на какой-то момент и записано имя файла бинарного журнала и позиция смещения в нем (на основе вывода команды SHOW MASTER STATUS), соответствующие этому снимку, выполните следующую процедуру: 1. Убедитесь, что подчиненному серверу назначен уникальный идентификатор. 2. Выполните следующие команды на подчиненном сервере, заполнив нужными значениями каждую из опций: m y s q l > CHANGE MASTER TO -> MASTER_HOST=' имя_хоста_главного_сервера', -> MASTER_USER=' имя_пользователя_репликации*, -> MASTER_PASSWORD=% пароль_репликацш ', -> MASTER_LOG_FILE=' имя_файла_записанного_журнала', -> MASTERJL0G_P0S=no3Han#_B_3a лисаяном^куряале ; 3. Выполните START SLAVE на подчиненном сервере. Если у вас нет резервной копии данных главного сервера, ниже представлена краткая процедура ее создания. Все шаги выполняются на главном сервере. 1. Выполните оператор: m y s q l > FLUSH TABLES WITH READ LOCK; 2. He снимая блокировки, выполните следующую команду (или ее вариацию): shell> tar zcf /tmp/backup.tar.gz /var/lib/mysql 3. Выполните следующий оператор и запишите его вывод, который понадобится позже: mysql> SHOW MASTER STATUS; 4. Снимите блокировку: m y s q l > UNLOCK TABLES; В качестве альтернативного варианта можно загрузить SQL-дамп с главного сервера вместо бинарной копии, как было описано выше. Чтобы это сделать, можно воспользоваться mysqldump —master-date на главном сервере и позже загрузить его на подчиненный. Однако это медленнее, чем в случае бинарной копии. Независимо от того, какой из двух способов вы выберете, после этого следуйте инструкциям, составленным для случая наличия снимка данных, имени бинарного журнала и смещения в нем. Вы можете использовать один и тот же снимок для настройки несколь-
394
Глава 5. Репликация в MySQL
ких подчиненных серверов. Если только вы получили снимок данных главного сервера, вы можете подождать с настройкой подчиненных до тех пор, пока бинарные журналы главного сервера находятся в целости. Два практических ограничения, накладываемых на время от выгрузки снимка до настройки подчиненных - это объем дискового пространства для хранения растущих файлов бинарного журнала и время, необходимое подчиненным серверам, чтобы провести репликацию накопившихся изменений. Вы также можете использовать LOAD DATA FROM MASTER. Это удобный оператор, переносящий снимок данных на подчиненный сервер и одновременно настраивающий имя журнала и смещение. В будущем применение оператора LOAD DATA FROM MASTER будет рекомендовано для первоначальной настройки подчиненного сервера. Помните, однако, что он работает только с таблицами My ISAM и может долгое время удерживать блокировку по чтению. Пока еще он не реализован настолько эффективно, как нам бы хотелось. Если у вас большие таблицы, предпочтительным способом на сегодняшний день является создание бинарного снимка данных главного сервера после выполнения оператора FLUSH TABLES WITH READ LOCK.
Вопрос. Должен ли подчиненный сервер все время быть подключенным к главному? Ответ. Нет. Подчиненный сервер может оставаться выключенным в течение часов и даже дней, затем повторно подключиться и захватить накопившиеся изменения. Например, вы можете установить между серверами отношение главный/подчиненный по коммутируемой линии, которая работает только эпизодически и в течение кратких периодов времени. Следствием этого будет то, что не гарантируется синхронность данных между главным и подчиненным серверами в любой момент времени, если только вы не предусмотрите каких-то специальных мер. В будущем мы предусмотрим возможность блокировать главный сервер до тех пор, пока хотя бы один из подчиненных не синхронизирован. Вопрос. Как узнать, когда данные подчиненного сервера сравнивались с данными главного? Другими словами, как узнать дату последней репликации? Ответ. Если подчиненный сервер имеет номер версии 4.1.1 или выше, читайте значение в столбце Seconds_Behind_Master в выводе команды SHOW SLAVE STATUS. Для более старых версий подходит следующий способ. Это возможно, только если SHOW PROCESSLIST на подчиненном сервере показывает, что работает поток SQL (или, для MySQL 3.23, что работает поток подчиненного сервера), и что он обработал хотя бы одно событие, полученное от главного. См. раздел 5.3. Когда поток SQL обрабатывает событие, прочитанное с главного, он модифицирует свое собственное время по временной метке события (вот почему TIMESTAMP правильно реплицируются). В столбце Time вывода команды SHOW PROCESSLIST количество секунд, отображаемое для потока SQL, представляет собой разность времени между меткой последнего обработанного события и реальным временем машины подчиненного сервера. Вы можете использовать его для определения даты последнего реплицированного события. Следует заметить, что если ваш подчиненный сервер был отключен от главного в течение одного часа, а затем подключился заново, вы можете немедленно увидеть значение наподобие 3600 в столбце Time вывода команды SHOW PROCESSLIST. Это объясняется тем, что подчиненный сервер выполняет оператор, которому исполнился один час. Вопрос. Как заставить главный сервер блокировать изменения до тех пор, пока подчиненный не догонит его? Ответ. Воспользуйтесь следующей процедурой:
5.9. Часто задаваемые вопросы по репликации
395
1. На главном сервере выполните следующие операторы: mysql> FLUSH TABLES WITH READ LOCK; mysql> SHOW MASTER STATUS;
Запишите имя журнала и смещение, которые покажет команда SHOW. Это - координаты репликации. 2. На подчиненном сервере выполните следующие операторы, где аргументами функции MASTER_POS_WAIT() будут координаты репликации, полученные на предыдущем шаге: mysql> SELECT MASTER_POS_WAIT('имя_журнала', смещение); Оператор SELECT заблокирует базу до тех пор, пока подчиненный сервер не достигнет указанных координат репликации. К этому моменту данные двух серверов будут синхронизированы, и оператор SELECT возвратит управление. 3. На главном сервере выдайте следующую команду, чтобы снова разрешить ему принимать запросы на изменение данных от клиентов: mysql> UNLOCK TABLES;
Вопрос. Что надо знать при настройке двусторонней репликации? Ответ. Репликация в MySQL на данный момент не поддерживает никакого журнала блокировок между главным и подчиненным серверами, чтобы гарантировать атомарность распределенного (межсерверного) обновления данных. Другими словами, имеется возможность для клиента А провести изменения на главном сервере 1, а в это время, прежде чем изменение распространится на главный сервер 2, клиент В может провести такое изменение на главном сервере 2, которое заставит изменение от клиента А работать иначе, чем оно было сделано на главном сервере 1. Таким образом, когда изменение от клиента А поступит на главный сервер 2, оно породит таблицу, другую, чем мы имеем на главном сервере 1, даже после того, как все изменения от главного сервера 2 распространятся. Это означает, что нельзя связать два сервера отношением двусторонней репликации, если только вы не уверены в том, что ваши изменения данных могут происходить безопасно в любом порядке, либо вы каким-то образом позаботитесь об этих беспорядочных изменениях в коде клиента. Кроме того, нужно представлять, что двусторонняя репликация не повысит производительности значительно (если вообще повысит), поскольку изменения данных будут связанными. Оба сервера должны будут выполнять одинаковое количество изменений, которые в обычном случае приходится делать одному. Единственным отличием могло быть то, что было бы немного меньше соперничества в блокировках, поскольку изменения, порожденные на другом сервере, становились бы последовательными в одном подчиненном потоке. Но даже этот минимальный выигрыш мог быть нейтрализован задержками в сети. Вопрос. Как можно использовать репликацию для повышения производительности системы? Ответ. Вы должны настроить один сервер как главный и направить все операции записи на него. Затем настройте столько подчиненных серверов, сколько позволяет бюджет и площади помещений, и настройте их так, чтобы операции чтения распределялись между ними равномерно. Вы также можете запустить подчиненные серверы с опциями —skip-innodb, —skip-bdb, —low-priority-updates и —delay-key-write=ALL, чтобы добиться повышения скорости на подчиненных серверах. В этом случае подчиненные
396
Глава 5. Репликация в MySQL
серверы будут использовать нетранзакционные таблицы MylSAM вместо таблиц InnoDB и BDB, что увеличивает производительность. Вопрос. Что нужно сделать, чтобы подготовить код клиентских приложений для использования репликации, повышающей производительность? Ответ. Если часть вашего кода, отвечающая за доступ к базе данных, хорошо абстрагирована и является модульной, адаптация такого кода к работе со средой репликации будет легкой и гладкой. Просто измените реализацию доступа к данным таким образом, чтобы все операции записи обращались к главному серверу, а запросы чтения - как к главному, так и к подчиненным серверам. Если ваш код не имеет такого уровня абстракции, настройка системы репликации даст возможность и мотивацию его создать. Начать стоит с создания библиотеки или модуля оболочки, включающего следующие функции: • safe_writer_connect() • safe_reader_connect() • safe_reader_statement() • safe_writer_statement() Префикс saf е_ в именах функций означает, что каждая из них сама заботится об обработке ошибочных условий. Вы можете использовать разные имена для функций. Важно лишь обеспечить унифицированный интерфейс подключений для чтения, подключений для записи, выполнения чтения и выполнения записи. Затем потребуется преобразовать код для использования этой библиотеки. Поначалу это может показаться болезненным и трудным процессом, однако все усилия окупятся при длительной эксплуатации. Все приложения, использующие такой подход, смогут воспользоваться в полной мере выгодами, приносящими конфигурацией "главный/подчиненный", в том числе при использовании множества подчиненных серверов. Такой код будет гораздо проще сопровождать, и добавление опций поиска и устранения неисправностей окажется тривиальным. То есть вам придется модифицировать одну или две функции, например, чтобы добавить регистрацию в журнале времени выполнения каждого оператора, или для выявления одного из тысяч обрабатываемых запросов, который является причиной ошибок. Если у вас уже написаны огромные объемы кода, вы можете захотеть автоматизировать задачу преобразования, используя утилиту replace, поставляемую в стандартном дистрибутиве MySQL, или же, написав собственный сценарий преобразования. В идеале ваш код уже использует соглашения последовательного и непротиворечивого стиля программирования. Если нет, то вам в любом случае лучше переписать его, или, по крайней мере, пересмотреть и вручную внести изменения, приводящие его в более стройное состояние. Вопрос. Когда и насколько репликация MySQL повысит производительность системы? Ответ. Репликация MySQL наиболее выгодна для систем с частым чтением и редкой записью. Теоретически, используя схему с одним главным и несколькими подчиненными серверами, вы можете ее масштабировать, добавляя подчиненные серверы до тех пор, пока или не достигнете ограничения, налагаемого пропускной способностью сети, или не вырастет до предела загрузка главного сервера, связанная с обновлением данных. Для того чтобы определить, сколько подчиненных серверов можно добавить до того момента, когда выигрыш от этого начнет снижаться, и насколько вообще можно повысить производительность системы, вы должны знать шаблоны ваших запросов, и с помощью тестов эмпирически определить соотношение между пропускной способностью
5.9. Часто задаваемые вопросы по репликации
397
операций чтения (чтений в секунду, или maxjreads) и записи (max_writes) на типичном главном и типичном подчиненном серверах. Приведенный ниже пример показывает довольно упрощенный расчет того, что можно получить от репликации на некоторой гипотетической системе. Представим, что загрузка системы состоит на 10% из записи и на 90% из чтения, и мы определили с помощью тестирования, что max_reads равно 1200 - 2 * max__writes. Другими словами, система может выполнить 1200 чтений в секунду без записи, среднее время записи вдвое больше, чем среднее время чтения, и зависимость линейная. Предположим, что главный и подчиненные серверы имеют одинаковую мощность, и что мы имеем один главный сервер и N подчиненных серверов. Тогда мы получаем для каждого сервера (главного или подчиненного): reads = 1200 - 2 * writes reads = 9 * writes / (N + 1) (чтения разделены, но запись выполняется на всех серверах) 9 * writes / (AT + 1) + 2 * writes = 1200 writes = 1200 / (2 + 9/(tf + 1)) Последнее уравнение означает, что максимальное количество чтений для N подчиненных дает максимальную производительность 1200 чтений в минуту и соотношение 9 чтений на одну запись. Анализ позволяет сделать следующие выводы: • Если N = 0 (это означает, что репликация не используется), то наша система может выполнить около 1200 /11 = 109 записей в секунду. • Если N = 1, мы имеем 184 записи в секунду. • Если N=8, мы имеем 400 записей в секунду. • Если N=11, мы имеем 480 записей в секунду. • В конечном итоге, когда N приближается к бесконечности (а бюджет - к минус бесконечности), мы можем получить около 600 записей в секунду, повысив производительность системы в 5,5 раза. Однако уже всего с восемью серверами мы достигаем роста производительности в 4 раза. Помните, что эти вычисления предполагают наличие бесконечной пропускной способности сети и не учитывают ряд других факторов, которые могут ощутимо повлиять на вашу систему. Во многих случаях вы не сможете выполнить расчеты, подобные приведенным выше, которые бы позволили точно предсказать, что случится с вашей системой, если вы добавите N подчиненных серверов репликации. Однако ответы на следующие вопросы помогут решить, как и насколько репликация может повысить производительность вашей системы: • Каково отношение количества операций чтения к операциям записи в вашей системе? • Какую загрузку по записи может выдержать один сервер, если уменьшить количество чтений? • Сколько подчиненных серверов позволит подключить ваша сеть? Вопрос. Как использовать репликацию для обеспечения избыточной и высокой доступности? Ответ. При имеющихся доступных средствах вы можете настроить главный и подчиненный серверы (либо несколько подчиненных), и написать сценарий, который будет
398
Глава 5. Репликация в MySQL
выполнять мониторинг главного сервера, проверяя его готовность. Затем потребуется проинструктировать ваши приложения и подчиненные серверы о том, как менять главный сервер в случае его отказа. Ниже представлены некоторые советы. •
Чтобы дать команду подчиненному серверу сменить главныйсервер, используйте оператор CHANGE MASTER TO.
•
Хороший способ информировать приложения о местонахождении главного сервера - это использовать для него динамический адрес DNS. С помощью bind вы можете применять nsupdate для динамического обновления DNS.
•
Вы должны запускать подчиненные серверы с опцией —log-bin и без опции --log-slave-updates. Таким способом вы обеспечите готовность главного сервера стать подчиненным, как только вы выполните команды STOP SLAVE, RESET MASTER и CHANGE MASTER TO на других подчиненных серверах. Например, предположим, что имеется следующая конфигурация:
WC \ v WC
>М
/ I \ I \ v v v SI S2 S3 М означает главный (master) сервер, S - подчиненный (slave) сервера, WC - клиенты, присылающие запросы на чтение и запись. Клиенты, которым нужен доступ только по чтению, не представлены, поскольку в переключении они не нуждаются. /
S I , S2 и S3 - это подчиненные серверы, запущенные с опцией — l o g - b i n и без опции — l o g - s l a v e - u p d a t e s . Поскольку изменения данных, принимаемые подчиненными серверами от главного, не записываются в бинарный журнал, если не указана опция — l o g - s l a v e - u p d a t e s , бинарный журнал на каждом подчиненном сервере пуст. Если по какой-то причине М станет недоступным, вы можете выбрать один из подчиненных серверов и сделать его главным. Например, выберем S1. Все WC должны быть перенаправлены на S I , a S2 и S3 должны реплицироваться с S1. Убедитесь в том, что все подчиненные серверы обработали операторы, находящиеся в их журналах ретрансляции. На каждом подчиненном сервере выполните команду STOP SLAVE IO_THREAD, затем проверяйте вывод SHOW PROCESSLIST до тех пор, пока не увидите сообщения "Has read a l l r e l a y l o g s " ("Прочитаны все журналы ретрансляции"). Когда это произойдет на всех подчиненных серверах, их можно будет перенастроить на новую конфигурацию. На S1, выбранном для того, чтобы стать новым главным сервером, выполните STOP SLAVE и RESET MASTER. На других подчиненных серверах - S2 и S3 - используйте STOP SLAVE и CHANGE MASTER TO MASTER_HOST='S1' (где f S l ' представляет реальное имя хоста S1). Чтобы сменить главный сервер, добавьте всю информацию о том, как подключаться к S1 с S2 и S3 (имя пользователя, пароль, номер порта). В CHANGE MASTER нет необходимости указывать имя бинарного журнала S1 и смещение в нем. Мы знаем, что это бу-
5.10. Поиск неисправностей в системе репликации
399
дет первый бинарный журнал с позицией 4, что является значениями по умолчанию для команды CHANGE MASTER. И, наконец, запустите START SLAVE на S2 и S3. Затем проинструктируйте все WC, чтобы они направляли свои запросы на S1. С этого момента все изменения данных, присланные WC на S1, будут записываться в бинарный журнал на S1, который будет содержать абсолютно все операторы обновления данных, присланные на S1 с момента выхода из строя М. В результате получаем следующую конфигурацию: WC
WC
/ I | М(недоступен)
\I \ I VV
SK--S2 S3
I
Когда М будет доступен вновь, вам нужно будет только выполнить на нем команду CHANGE MASTER, такую же, как вы давали на S2 и S3, таким образом, сделав М подчиненным для S1 и проведя на нем все изменения, пропущенные с момента его выхода из строя. Теперь, чтобы его опять сделать главным сервером (например, по той причине, что это наиболее мощная машина), повторите описанную процедуру, как если бы S1 стал недоступен, а М должен стать новым главным сервером. Не забудьте запустить RESET MASTER на М, прежде чем настраивать S1, S2 и S3, как его подчиненные серверы. В противном случае можно потерять старые записи WC до момента его выхода из строя. В настоящее время мы работаем над системой интеграции автоматического выбора главного сервера в MySQL, но пока она не готова, вам придется создавать собственные средства мониторинга.
5.10. Поиск неисправностей в системе репликации Если вы следовали инструкциям, но ваша настройка репликации не работает, сначала проверьте следующие моменты: • Проверьте сообщения в журнале ошибок. Многие теряют время, не делая этого. • Выполняется ли бинарная регистрация на главном сервере? Проверьте с помощью команды SHOW MASTER STATUS. Если да, столбец Position будет иметь ненулевое значение. Если нет, убедитесь, что вы запускаете главный сервер с опциями —log-bin и —server-id. • Запущена ли репликация на подчиненном сервере? Используйте SHOW SLAVE STATUS для проверки того, что переменные Slave_IO_Running и Slave_SQL_Running имеют значения Yes. Если нет, проверьте, с какими опциями запускается подчиненный сервер. • Если подчиненный сервер запущен, установил ли он связь с главным сервером? Воспользуйтесь SHOW PROCESSLIST, чтобы найти потоки репликации ввода-вывода
400
Глава 5. Репликация в MySQL
и SQL и проверить значение их столбца State. См. раздел 5.3. Если значение State для потока ввода-вывода равно Connecting to master (Подключение к главному серверу), проверьте привилегии пользователя репликации на главном сервере, его имя хоста, ваши настройки DNS, работает ли главный сервер в данный момент и доступен ли он с подчиненного сервера. • Если подчиненный сервер работал ранее, а теперь остановлен, причина обычно состоит в том, что некий оператор, успешно выполненный на главном сервере, не прошел на подчиненном. Это никогда не должно случаться, если у вас был корректный первоначальный снимок данных главного сервера, и данные подчиненного не модифицировались вне его потоков репликации. Если это так, то, вероятно, это ошибка, либо вы столкнулись с одним из известных ограничений репликации, описанных в разделе 5.7. Если это ошибка, в разделе 5.11 можно найти инструкции о том, как сообщать об ошибках. • Если оператор, выполненный успешно на главном сервере, отвергнут подчиненным, и нет реальной возможности осуществить полную ресинхронизацию (то есть, удалить базу данных подчиненного и скопировать новый снимок с главного), попробуйте выполнить следующие действия: 1. Определите, чем отличается таблица на подчиненном сервере от той же таблицы на главном. Попытайтесь разобраться, как это получилось. Затем приведите таблицу на подчиненном сервере в состояние, эквивалентное ее состоянию на главном сервере, и выполните START SLAVE. 2. Если предыдущий шаг не работает или невозможен, попробуйте разобраться, нельзя ли провести обновление вручную (при необходимости), а затем проигнорировать следующий оператор с главного сервера. 3. Если вы решите, что следующий оператор с главного сервера можно пропустить, выполните следующие операторы: mysql> SET GLOBAL SQL_SLAVE_SKIP_COUNTER = л; raysql> START SLAVE; Значение л должно быть равно 1, если следующий оператор с главного сервера не использует AUTO_INCREMENT или LAST_INSERT_ID(). В противном случае значение должно быть равно 2. Причина указания значения 2 для операторов, ИСПОЛЬЗУЮЩИХ AUTO_INCREMENT ИЛИ LAST_INSERT_ID ( ) , СОСТОИТ В ТОМ, ЧТО ОНИ
берут два события в бинарном журнале главного сервера. 4. Если вы уверены, что подчиненный сервер стартовал, будучи идеально синхронизированным с главным, и никто не вносил изменений в данные подчиненного сервера вне системы репликации, значит, предположительно, расхождения объясняются ошибкой кода сервера. Если вы работаете с самой последней версией, сообщите нам о проблеме. Если у вас более старая версия MySQL, попробуйте ее обновить.
5.11. Сообщения об ошибках репликации Если вы убедились, что не было никаких пользовательских ошибок, а репликация либо не работает, либо функционирует нестабильно, значит, наступило время сообщать об ошибке. Мы хотели бы получать как можно больше информации от вас, чтобы разо-
5.11. Сообщения об ошибках репликации
401
браться в причинах проблемы. Потратьте некоторое время и усилия, чтобы подготовить хороший отчет об ошибке. Если у вас есть воспроизводимый тестовый случай, демонстрирующий ошибку, внесите его в нашу базу ошибок на http://bugs.mysql.com/. Если ваша проблема носит фантомный характер (то есть ее невозможно воспроизвести по желанию), выполните следующую процедуру: 1. Убедитесь, что не было никаких пользовательских ошибок. Например, если вы обновляете данные на подчиненном сервере непосредственно, вне системы репликации, данные рассинхронизируются, и вы можете получить ошибки нарушения уникальности при обновлении данных. В этом случае потоки подчиненного сервера, обслуживающие репликацию, останавливаются и ожидают, когда вы вручную приведете данные в синхронное состояние. Это не проблема репликации. Это проблема внешнего влияния, которое приводит к сбою репликации. 2. Запустите подчиненный сервер с опциями —log-slave-updates и —log-bin. Это вынудит его записывать все операторы, которые приходят от главного сервера, в собственный бинарный журнал. 3. Сохраните все симптомы проблем перед сбросом состояния репликации. Если у нас нет информации, или она имеет беглый, неполный характер, это затрудняет или делает невозможным разобраться в причинах проблемы. Свидетельства проблемы, которые вы должны собрать: • Все бинарные журналы главного сервера. • Все бинарные журналы подчиненного сервера. • Вывод SHOW MASTER STATUS с главного сервера, полученный в момент обнаружения проблемы. • Вывод SHOW SLAVE STATUS с подчиненного сервера, полученный в момент обнаружения проблемы. • Журналы ошибок с главного и подчиненного серверов. 4. Воспользуйтесь mysqlbinlog для проверки бинарных журналов. Следующая команда должна помочь в поиске проблемного запроса, например: shell> mysqlbinlog -j no3nu,MR_B_slave_status \ /путь/к/журнал_из_з1ауе_зЬаЬиз | head Как только вы соберете все свидетельства фантомной проблемы, попробуйте ее изолировать в отдельном тестовом случае. Затем внесите проблему в нашу базу ошибок на h t t p : //bugs .mysql. com/, сопроводив ее как можно более подробной информацией.
6
Оптимизация MySQL
О
птимизация - это комплексная задача, поскольку в конечном итоге она требует понимания всей системы, в которой выполняется. Несмотря на то что можно выполнить некоторую локальную оптимизацию, обладая минимальными знаниями системы или приложения, однако, чем более оптимальная система необходима, тем больше о ней следует знать. В этой главе объясняются различные способы оптимизации MySQL и приводятся некоторые характерные примеры. Помните, однако, что всегда есть дополнительные пути сделать вашу систему еще быстрее, хотя это и потребует приложить дополнительные усилия.
6.1. Обзор оптимизации Самый важный фактор в достижении высокой производительности системы - это ее базовая конструкция. Вы также должны представлять, какие типы задач будет выполнять ваша система, и где у нее могут быть узкие места. Основные узкие места системы таковы: • Поиск информации на диске. Диску требуется определенное время, чтобы найти какую-то часть данных. У современных дисков среднее время доступа обычно меньше 10 миллисекунд, то есть теоретически можно говорить о 100 операциях поиска в секунду. Этот показатель у новых дисков постепенно растет, но его чрезвычайно трудно оптимизировать для доступа к отдельной таблице. Способ оптимизировать время доступа диска заключается в распределении данных на более чем одном диске. • Чтение и запись на диск. Когда головки диска находится в правильной позиции, необходимо прочесть данные. Современные диски обеспечивают пропускную способность данных при чтении и записи, как минимум, в пределах 10-20 Мбайт в секунду. Это легче оптимизировать, чем время поиска, потому что можно организовать параллельное чтение с нескольких дисков. • Циклы центрального процессора. Когда данные поступают в основную память (или уже находятся там), их нужно обработать, чтобы получить какой-то результат. Маленькие таблицы, объем которых сравним с объемом памяти - самый общий ограничивающий фактор. Но при маленьких таблицах обычно скорость не является проблемой.
6.1. Обзор оптимизации
403
• Пропускная способность памяти. Когда центральный процессор нуждается в большем количестве данных, чем помещается в его кэш, пропускная способность памяти становится узким местом. Это не слишком существенное узкое место для большинства систем, но одно из тех, о которых нужно помнить.
6.1.1. Ограничения и компромиссы конструкции MySQL При использовании механизма хранения My ISAM MySQL использует чрезвычайно быструю систему блокировки таблиц, которая позволяет параллельно выполнять множество чтений или одну запись. Самая большая проблема с этим механизмом хранения проявляется тогда, когда идет устойчивый поток смешанных операторов обновления и медленных запросов к одной и той же таблице. Если это становится проблемой для определенных таблиц, вы можете выбрать для них другие типы (см. главу 8). MySQL может работать как с транзакционными, так и с нетранзакционными таблицами. Чтобы работать гладко с нетранзакционными таблицами (которые невозможно откатить, если что-то пошло не так), MySQL следует определенным правилам: • Все столбцы имеют значения по умолчанию. • Если вы вставляете "неверное" значение в столбец, такое как слишком больше число в числовой столбец, MySQL устанавливает для него "наилучшее возможное значение" вместо того, чтобы выдать ошибку. Для числовых столбцов таким значением является 0, наименьшее возможное, или наибольшее возможное значение. Для строк - это либо пустая строка, либо самая длинная возможная строка, которая помещается в столбец. • Все вычисляемые выражения возвращают значение, которое можно использовать, вместо выдачи сигнала об ошибочном условии. Например, 1/0 возвращает NULL. Следствием этих правил является то, что вы не должны использовать MySQL для проверки содержимого столбцов. Вместо этого вы должны проверять значения в приложении прежде, чем помещать их в базу данных.
6.1.2. Проектирование переносимых приложений Поскольку все серверы SQL реализуют разные части стандарта SQL, написание переносимого приложения требует определенных усилий. Очень легко добиться переносимости для простейших запросов и вставок, но становится намного сложнее, если вам требуется использовать больше возможностей. Если вам нужно приложение, которое работает быстро на разных базах данных, это становится еще труднее! Чтобы обеспечить переносимость сложного приложения, потребуется определить, с какими серверами SQL оно должно работать, а затем выяснить, какие средства эти серверы поддерживают. Все системы управления базами данных (СУБД) имеют определенные слабые места. То есть они имеют определенные компромиссы в конструкции, которые приводят к различному поведению в сходных ситуациях. С помощью MySQL-программы crash-me можно найти функции, типы и ограничения, которые должны учитываться при выборе сервера баз данных, crash-me не проверяет все возможные средства, но она достаточно исчерпывающая, поскольку выполняет около 450 тестов.
404
Глава 6. Оптимизация MySQL
Примером типа информации, которую может предоставить crash-me, может быть то, что вы не должны использовать имена столбцов длиннее 18 символов, если собираетесь взаимодействовать с Informix или DB2. Программа crash-me и тесты производительности MySQL мало зависят от конкретной СУБД. Взглянув на то, как они написаны, вы можете получить представление о том, как ваши собственные программы сделать независимыми от СУБД. Эти программы находятся в каталоге sql-bench исходного дистрибутива MySQL. Они реализованы на языке Perl и используют интерфейс баз данных DBI. Применение DBI само по себе решает проблемы переносимости, поскольку он предлагает независимые от СУБД методы доступа. За результатами crash-me обращайтесь по адресу http://dev.mysql.com/techresources/crash-me.php. Результаты тестов производительности можно увидеть по адресу http://dev.mysql.com/tech-resources/benchmarks/. Если вы стремитесь к независимости от СУБД, вы должны получить хорошее представление об узких местах каждого из серверов SQL. Например, MySQL очень быстро работает при извлечении и обновлении записей в таблицах My ISAM, но имеет проблемы при смешанном применении медленного чтения и записи на одной и той же таблице. С другой стороны, Oracle имеет большие проблемы при попытке получить доступ к строкам, которые только что обновлены (пока они не сброшены на диск). Транзакционные базы данных вообще не очень хороши для генерации отчетных таблиц из таблиц журналов, поскольку в этом случае блокировка строк практически бесполезна. Чтобы сделать ваши приложения действительно независимыми от СУБД, вы должны определить легко расширяемый интерфейс, посредством которого можно манипулировать данными. Так как язык C++ доступен в большинстве систем, имеет смысл использовать интерфейс доступа к базам данных, основанный на классах C++. Если вы применяете средства, специфичные для конкретной СУБД (такие как оператор REPLACE, который есть в MySQL), вы должны реализовать такие же средства для других серверов SQL, закодировав их альтернативным методом. Несмотря на то что он может оказаться медленнее, такой подход позволит выполнять те же задачи на других серверах. В MySQL вы можете использовать синтаксис /*! */ для добавления к запросам ключевых слов, специфичных для MySQL. Код внутри /* */ рассматривается как комментарий (и игнорируется) большинством других SQL-серверов. Если высокая производительность более важна, чем точность данных, как это бывает в некоторых Web-приложениях, появляется возможность создать уровень приложения, который кэширует результаты для повышения производительности. Позволяя старым результатам запросов исчезать со временем, вы можете поддерживать кэш в достаточно актуальном состоянии. Это является хорошим способом справиться с пиковыми нагрузками, в случае которых можно динамически увеличивать размер кэша и устанавливать таймаут "устаревания" данных в нем большим до тех пор, пока нагрузка не вернется в норму. В этом случае информация о создании таблицы должна включать информацию о начальном размере кэша и периоде его обновления. Альтернативой кэшу уровня приложений является использование кэша запросов MySQL. При включенном кэше запросов сервер сам принимает решения о том, когда результаты запросов могут быть использованы повторно. Это позволяет упростить приложения. См. 4.10.
6.1. Обзор оптимизации
405
6.1.3. Для чего мы использовали MySQL В настоящем разделе описываются ранние приложения MySQL. Во время первоначального создания MySQL его средства разрабатывались под нужды нашего крупнейшего заказчика, который управлял хранилищем данных для группы больших розничных торговых компаний Швеции. Мы получали еженедельные итоги по всем транзакциям, касающимся бонус-карт, и должны были предоставлять владельцам магазинов полезную информацию, призванную помочь им оценить, насколько проводимые ими рекламные кампании влияли на их собственных клиентов. Объем данных был достаточно велик (около 7 миллионов суммарных транзакций в месяц), и мы располагали данными за 4-10 лет, которые необходимо было предоставлять пользователям. Мы получали еженедельные запросы от наших клиентов, которые хотели иметь прямой доступ к новым отчетам по этим данным. Мы решили упомянутую проблему, поместив всю информацию за месяц в сжатые таблицы транзакций. У нас был набор простых макросов, которые генерировали итоговые таблицы, группируя данные по разным критериям (продуктовая группа, идентификатор клиента и так далее) из таблиц, в которых хранилась информация о торговых транзакциях. Отчеты представляли собой Web-страницы, динамически сгенерированные небольшим сценарием на Perl. Этот сценарий анализировал Web-страницу, выполнял SQLоператоры, находящиеся на ней, и помещал на их место результаты. Мы бы использовали вместо этого РНР или modperl, однако они были на то время недоступны. Для представления данных в графической форме мы написали простой инструмент на языке С, который мог обрабатывать результаты SQL-запросов и генерировать GIFизображения на базе их результатов. Этот инструмент также динамически вызывался из Perl-сценария, который обрабатывал Web-страницы. В большинстве случаев новый отчет мог быть создан простым копированием существующего сценария с модификацией SQL-запроса в нем. В некоторых случаях нам нужно было добавить больше столбцов к итоговой таблице, или сгенерировать новую, но это также было достаточно просто, потому что мы сохраняли все таблицы с торговыми транзакциями на диске (использовалось около 50 Гбайт под таблицу транзакций и 200 Гбайт - под другие пользовательские данные). Мы также предоставляли заказчикам непосредственный доступ к итоговым таблицам через ODBC, чтобы опытные пользователи могли самостоятельно экспериментировать с данными. Система работала хорошо, и у нас не было проблем с управлением данными на сравнительно скромном оборудовании - Sun Ultra SPARCstation (2 х 200 Мгц). Со временем система была перенесена под Linux.
6.1.4. Набор тестов производительности MySQL В этом разделе должно находиться техническое описание набора тестов производительности MySQL (benchmark suite) и crash-me, однако само описание еще не готово. В настоящее время вы можете получить представление о тестах производительности, ознакомившись с кодом и результатами тестов в каталоге sql-bench любого дистрибутива MySQL. Набор тестов производительности предназначен для того, чтобы продемонстрировать, какие операции данная реализация SQL выполняет хорошо или плохо.
406
Глава 6. Оптимизация MySQL
Помните, что все эти тесты однопоточные, поэтому замеряют минимальное время выполнения операций. В будущем мы планируем добавить многопоточные тесты. Для использования набора тестов производительности необходимо удовлетворить следующим требованиям: • Тесты производительности предоставляются исходным дистрибутивом MySQL. Вы можете либо загрузить такой дистрибутив с http://dev.mysql.com/downloads/, либо использовать текущее дерево разработки исходных текстов (см. раздел 2.3.3). • Тестовые сценарии написаны на Perl и используют модуль Perl DBI для доступа к серверам баз данных, полому DBI должен быть установлен. Вам также понадобятся специфичные для сервера драйверы DBD - по одному для каждого сервера, который необходимо протестировать. Например, чтобы протестировать MySQL, PostgreSQL и DB2, вы должны иметь установленные модули DBD: :mysql, DBD: :Pg и DBD:: DB2. См. раздел 2.7. После того, как вы получите исходный дистрибутив MySQL, вы найдете набор тестов производительности в его подкаталоге sql-bench. Чтобы запустить их, выполните сборку MySQL, затем перейдите в подкаталог sql-bench и выполните сценарий run-all-tests: shell> cd sql-bench shell> perl run-all-tests
—server-имя^сервера
имя_сервера - это один из поддерживаемых серверов. Для получения списка опций и поддерживаемых серверов воспользуйтесь командой: shell> perl run-all-tests —help Сценарий crash-me также находится в каталоге sql-bench. Этот сценарий пытается определить, какие средства база данных поддерживает и какие у нее возможности и ограничения для выполнения запросов. В частности, сценарий определяет: • Какие поддерживаются типы столбцов. • Сколько поддерживается индексов. • Какие поддерживаются функции. • Насколько большим может быть запрос. • Насколько большими могут быть столбцы типа VARCHAR. Вы можете найти результаты crash-me для многих различных серверов баз данных по адресу http: //dev.mysql ..com/tech-resources/crash-me.php. Более подробная информация о результатах тестов производительности доступна по адресу http://dev.mysql.com/tech-resources/benchmarks.
6.1.5. Использование собственных тестов производительности Для того чтобы найти узкие места в своих приложениях и базах данных, их потребуется обстоятельно протестировать на предмет производительности. Найдя одно из них (и заменив на "модуль-заглушку"), вы можете легко идентифицировать следующее. Даже если общая производительность вашего приложения приемлема, вы должны, по крайней мере, составить план узких мест и решить, как избавляться от них, когда понадобится искать резервы производительности.
6.2. Оптимизация операторов SELECT и других запросов
407
В качестве примера переносимых тестовых программ ознакомьтесь с набором тестов производительности MySQL (см. раздел 6.1.4). Вы можете взять любую из программ этого набора и модифицировать по собственному усмотрению. Сделав это, вы можете попробовать различные решения вашей проблемы и определить, какое из них самое быстрое. Другой бесплатный набор тестов производительности, Open Source Database Benchmark, можно найти на сайте http://osdb.sourceforge.net/. Очень часто проблемы проявляются тогда, когда система сильно загружена. У нас было много заказчиков, которые связывались с нами, когда во время эксплуатации протестированных систем сталкивались с проблемами высокой нагрузки. В большинстве случаев причина проблем производительности своими корнями уходит в базовую конструкцию СУБД (например, сканирование таблиц работает неважно при высоких нагрузках), либо связана с проблемами операционной системы или библиотек. Как правило, такие проблемы намного проще решать, когда система еще не запущена в производственную эксплуатацию. Во избежание подобных проблем, вы должны приложить некоторые усилия, чтобы протестировать общую производительность приложения под максимально возможной нагрузкой. Для этого можете воспользоваться инструмент Super Smack, который доступен по адресу http://jeremy.zawodny.com/mysql/super-sraack/. Упомянутый инструмент может поставить систему "на колени", поэтому используйте его только в системах, предназначенных для разработчиков.
6.2. Оптимизация операторов SELECT и других запросов Первое, что затрагивает все операторы: чем более сложна ваша настройка системы доступа, тем большую нагрузку вы получите. Использование более простых прав доступа, которые устанавливаются с помощью оператора GRANT, позволяет MySQL снизить нагрузку, связанную с их проверкой. Например, если вы не определяете никаких привилегий уровня таблицы или уровня столбца, то серверу не придется обращаться к таблицам tables_priv и columns_priv. Аналогично, если ни для каких пользовательских учетных записей не задаются ограничения на доступ к ресурсам, серверу не придется вести учет этих ресурсов. Если у вас очень высокий объем запросов, может быть, стоит потратить время на упрощение структуры привилегий, дабы снизить нагрузку сервера, связанную с их проверкой. Если проблема связана с некоторыми специфичными выражениями и функциями MySQL, можете с помощью функции BENCHMARK () в клиентской программе выполнить замеры времени. Синтаксис это функции таков: BENCHMARK {количество__циклов, выражение). Например: | BENCHMARK(1000000,1+1) +
I + 1 row in s e t
| +
0| + (0.32
sec)
408
Глава 6. Оптимизация MySQL
Эти результаты были получены в системе с процессором Pentium II400 Мгц. Они показывают, что MySQL может выполнить в этой системе 1 000 000 простых выражений суммирования за 0,32 секунды. Все функции MySQL должны быть очень хорошо оптимизированы, однако существуют и некоторые исключения. BENCHMARK () - отличный инструмент для определения, связана ли проблема с запросами.
6.2.1. Синтаксис оператора EXPLAIN (получение информации о SELECT) EXPLAIN
имя_таблицы
или EXPLAIN SELECT
onu,MM_select
Оператор EXPLAIN, как и его синоним DESCRIBE, может использоваться для получения информации о том, как MySQL будет выполнять оператор SELECT: •
Синтаксис EXPLAIN имя_таблицы - это синоним для DESCRIBE имя_таблицы или SHOW COLUMNS FROM имя_таблицы.
•
Когда вы предваряете оператор SELECT ключевым словом EXPLAIN, MySQL объясняет, как он будет обрабатывать SELECT, предоставляя информацию о том, как объединяются таблицы и в каком порядке.
Этот раздел посвящен второму применению EXPLAIN. С помощью EXPLAIN вы можете увидеть, когда к таблицам нужно добавить индексы, чтобы получить более быстрый SELECT, который будет использовать индексы для поиска записей. Вы должны периодически запускать ANALYZE TABLE для обновления статистики таблиц, такой как распределение значений ключей, которое может повлиять на принятие решений оптимизатором. Вы также можете увидеть, в правильном ли порядке оптимизатор выполняет соединение таблиц. Чтобы заставить оптимизатор использовать порядок соединения таблиц в соответствии с тем, который указан в операторе SELECT, этот оператор должен начинаться С SELECT STRAIGHT_JOIN вместо просто SELECT. EXPLAIN возвращает строку информации для каждой таблицы, используемой в операторе SELECT. Таблицы перечисляются в том порядке, в котором MySQL читает их при обработке запроса. MySQL разбирает все соединения, используя однопроходный многосвязный (single-sweep multi-join) метод. Это означает, что MySQL читает строку из первой таблицы, затем находит соответствующую строку во второй таблице, затем в третьей и так далее. Когда все таблицы обработаны, он выводит выбранные столбцы и выполняет обратный обход в списке таблиц до тех пор, пока не найдет таблицу, в которой есть еще подходящие строки. Следующая строка читается из этой таблицы, и процесс продолжается со следующей таблицей. В MySQL 4.1 формат вывода EXPLAIN был изменен, чтобы лучше работать с такими конструкциями, как UNION, подзапросами и производными таблицами. Наиболее значительным нововведением является добавление новых столбцов: i d и s e l e c t _ t y p e . Вы не увидите этих столбцов, если работаете с серверами более старыми, чем MySQL 4.1.
6.2. Оптимизация операторов SELECT и других запросов
409
Каждая строка вывода EXPLAIN представляет информацию об одной таблице и состоит из следующих столбцов: •
id. Идентификатор SELECT. Это порядковый номер оператора SELECT в запросе.
•
s e l e c t _ t y p e . Тип оператора SELECT, который может быть одним из следующих: •
SIMPLE. Простой оператор SELECT (не использующий UNION или SUBQUERY).
•
PRIMARY. Внешний оператор SELECT.
•
UNION. Второй или последний оператор SELECT в UNION.
•
DEPENDENT UNION. Второй или последний оператор SELECT в UNION, зависящий от внешнего подзапроса.
•
SUBQUERY. Первый оператор SELECT в подзапросе.
•
DEPENDENT SUBQUERY. Первый оператор SELECT в подзапросе, зависящий от внешнего подзапроса.
•
DERIVED. Оператор SELECT на порожденной таблице (подзапрос в конструкции FROM).
•
t a b l e . Таблица, на которую ссылается строка вывода.
•
type. Тип соединения. Различные типы соединений перечислены ниже, от лучшего к худшему: •
system. Таблица имеет только одну строку (= системная таблица). Это специальный случай типа соединения const.
•
const. Таблица имеет только максимум одну подходящую строку, которая будет прочитана в начале выполнения запроса. Поскольку строка только одна, значения ее столбцов могут быть приняты оптимизатором для дальнейшей обработки в качестве констант. Таблицы const очень быстрые, поскольку считываются только однажды. const применяются, когда вы сравниваете все части индекса PRIMARY KEY или UNIQUE с константными значениями. В следующих запросах таблица имя_ та блицы может быть использована как const-таблица: SELECT * FROM имя_таблицы WHERE первичный_ключ=1 SELECT * FROM имя_таблицы
;
WHERE первичный_ключ_часть1=1 AND первичный_ключ_часть2=2; •
eq_ref. Одна строка данной таблицы будет прочитана для каждой комбинации строк предыдущих таблиц. Это лучший из возможных тип соединения, если не считать const. Он применяется, когда все части индекса используются соединением, а индекс является PRIMARY KEY или UNIQUE. e q r e f может быть использован для индексированных столбцов, которые сравниваются с помощью операции =. Сравниваемое значение может быть константой или выражением, которое использует столбцы из таблиц, прочитанных перед данной таблицей. В следующих примерах MySQL может использовать соединение eq_ref для обработки таблицы таблица_ссылок: SELECT * FROM таблица_ссылок,другая_таблица WHERE таблица ссылок.ключевой столбец^ другая_таблица.столбец;
410
Глава 6. Оптимизация MySQL SELECT * FROM таблица_ссылок, другая__таблица WHERE та блица_ ссылок. ключев ой_столбец_ часть 1 =другая^ та блица. столбец AND таблица_ссылок. ключевой__столбец_часть2=1; •
ref. Все строки с подходящим значением индекса будут прочитаны из таблицы для каждой комбинации строк предыдущих таблиц, ref применяется, если соединения использует только левую часть ключа, или же ключ не является индексом PRIMARY KEY или UNIQUE (другими словами, если соединение не может извлечь единственную строку на основании значения ключа). Если используемый ключ соответствует только нескольким строкам, это хороший тип соединения. ref может быть использован для индексированных столбцов, которые сравниваются с помощью операции =. В следующих примерах MySQL может использовать соединение ref для обработки таблицы таблица_ссылок: SELECT * FROM таблица_ссылок WHERE ключевой_столбец=выражение; SELECT * FROM таблица_ссылок,другая_таблица WHERE та блица_ссылок. ключев ой_столбец=другая^ та блица. столбец; SELECT * FROM таблица^ссылок, другая_таблица WHERE та блица_ ссылок. ключев ой_столбец_ ча сть 1 =другая_ та блица. столбец AND таблица_ссылок. ключевой_столбец_часть2=1;
•
r e f o r n u l l . Тип соединения, подобный ref, но с тем отличием, что MySQL будет выполнять дополнительный поиск строк, содержащих значения NULL. Оптимизация этого типа соединений является новой в MySQL 4.1.1, и в основном применяется для разрешения подзапросов. В следующих примерах MySQL может использовать соединение r e f o r n u l l для обработки таблицы таблица_ссылок: SELECT * FROM таблица_ссылок WHERE ключевой_столбец=выражение OR ключевой_столбец IS NULL;
•
•
См. раздел 6.2.6. indexmerge. Этот тип означает, что применяется оптимизация соединения индексов (index Merge). В данном случае ключевой столбец содержит список используемых индексов, a key_len — список самых длинных частей ключа для используемых индексов. Более подробную информацию можно найти в разделе 6.2.5. uniquesubquery. Этот тип заменяет ref в некоторых подзапросах IN следующего вида: значение IN (SELECT первичный_ключ FROM таблица WHERE выражение) uniquesubquery - это просто функция поиска по индексу, которая для большей эффективности полностью заменяет подзапрос.
•
index_subquery. Этот тип соединения похож на unique_subquery. Он заменяет подзапросы IN, но работает с неуникальными индексами в подзапросах следующего вида: значение
IN (SELECT ключевой^столбец FROM таблица WHERE выражение)
6.2. Оптимизация операторов SELECT и других запросов •
411
range. Извлекаются строки только из заданного диапазона с использованием индекса для их выбора. Столбец key показывает, какой индекс используется. k e y l e n содержит самую длинную используемую часть индекса. Столбец ref для этого типа будет NULL. range может применяться, когда ключевой столбец сравнивается с константой, используя любую из операций: =, о , >, >=, ALTER TABLE t t MODIFY AssignedPC VARCHAR(15), -> MODIFY C l i e n t I D VARCHAR(15); Теперь EXPLAIN выдает следующую информацию: table type et ALL
possible_keys key PRIMARY NULL
key len ref NULL NULL
rows Extra 74
6.2. Оптимизация операторов SELECT и других запросов tt
ref
AssignedPC, ClientID, ActualPC et 1 eq ref PRIMARY do eq ref PRIMARY
415
ActualPC
15
et .EMPLOYID
PRIMARY PRIMARY
15 15
tt .AssignedPC 1 tt .ClientID 1
52
Using where
Это практически идеально. Осталась еще одна проблема, которая заключается в том, что по умолчанию MySQL предполагает, что значения столбца tt.ActualPC распределены равномерно, но для таблицы t t на самом деле это не так. К счастью, легко заставить MySQL проанализировать реальное распределение значений: mysql> ANALYZE TABLE tt; Теперь соединение просто блестяще и EXPLAIN выдает такой результат: table type tt ALL
possible_keys AssignedPC ClientID, ActualPC et eq ref PRIMARY et 1 eq_ref PRIMARY do eq ref PRIMARY
key NULL
key_len reJ NULL NULL
PRIMARY 15 PRIMARY 15 PRIMARY 15
rows Extra 3872 Using where
1 tt..ActualPC tt..AssignedPC 1 tt,.ClientID 1
Имейте в виду, что значение в столбце rows в выводе EXPLAIN является квалифицированным предположением оптимизатора MySQL. Вы должны проверить, близки ли эти цифры к реальным. Если нет, можно получить более высокую производительность, используя STRAIGHT_JOIN в операторе SELECT, и попробовать перечислить таблицы в конструкции FROM в другом порядке.
6.2.2. Ожидаемая производительность запросов В большинстве случаев можно оценить производительность, посчитав обращения к диску. Для маленьких таблиц, как правило, вы можете найти строку за одно обращение к диску (поскольку, вероятно, индекс кэширован). Для таблиц побольше вы можете оценить, что при использовании индексов в виде бинарных деревьев понадобится следующее количество операций доступа к диску: l o g {количество_строк) I l o g {длина_индексного_блока / 3 * 2 / [длина_индекса + длина_указателя__данных)) +1 В MySQL индексный блок обычно имеет размер 1024 байта, а указатель на данные как правило, 4 байта. Для таблицы в 500 000 строк с длиной ключа индекса в 3 байта (среднее целое), формула дает log (500,000) /log (1024/3*2/ (3+4)) + 1 = 4 обращения к диску. Упомянутый индекс потребует для своего хранения около 500000 * 7 * 3/2 = 5,2 Мбайт (предполагая, что типичное наполнение индексного буфера составляет 2/3), поэтому вероятно, большая часть индекса будет находиться в памяти и понадобится только один или два вызова, чтобы прочитать данные при поиске строки. Для записи, однако, понадобится четыре обращения к диску, чтобы найти место, куда поместить новый ключ индекса, и обычно два обращения, чтобы обновить индекс и записать строку. Имейте в виду, что предыдущие расчеты вовсе не означают, что производительность вашего приложения будет медленно снижаться по закону log N. До тех пор, пока все кэ-
416
Глава 6. Оптимизация MySQL
шируется операционной системой или SQL-сервером, с ростом таблиц эти вещи будут замедляться только в малой степени. После того, как объем данных станет слишком большим, чтобы поддаваться кэшированию, все станет работать значительно медленнее, до тех пор, пока ваше приложение ограничивается только количеством обращений к диску (которое растет по закону log N). Чтобы избежать этого, с ростом объема данных увеличивайте размер кэша ключей. Для таблиц MylSAM размер кэша ключей управляется системной переменной keyjouf f er_size. См. раздел 6.5.2.
6.2.3. Скорость выполнения запросов SELECT Обычно, когда вы хотите, чтобы медленный запрос SELECT.. .WHERE работал быстрее, первое, что потребуется сделать - это проверить, нельзя ли добавить индекс. Все ссылки между разными таблицами обычно должны использовать индексы. Вы можете потом с помощью EXPLAIN проверить, какие индексы использует SELECT. См. разделы 6.4.5 и 6.2.1. Ниже представлены некоторые общие советы по повышению скорости запросов к таблицам My ISAM: • Чтобы помочь оптимизатору MySQL выполнять запросы быстрее, запустите ANALYZE TABLE или myisamchk —analyze для таблицы после того, как в нее будут загружены данные. Это обновит те части индексов, которые хранят информацию о среднем количестве строк с одинаковыми значениями ключа (для уникальных индексов это всегда 1). MySQL будет использовать это для принятия решения, какой индекс выбрать при соединении таблиц на базе неконстантных выражений. Вы можете увидеть результат проведенного анализа таблиц с помощью SHOW INDEX FROM имя_таблицы, просмотрев там значение Cardinality, myisamchk —description --verbose показывает информацию о распределении индекса. • Чтобы отсортировать индекс и данные на основе индекса, используйте myisamchk --sort-index —sort-records=l (если вы хотите сортировать по индексу 1). Это хороший способ ускорить запросы, если имеется уникальный индекс, из которого вы хотите извлекать все записи в порядке, соответствующем индексу. Заметьте, что в первый раз, когда вы сортируете большую таблицу подобным способом, это может занять длительное время.
6.2.4. Как MySQL оптимизирует конструкцию WHERE В этом разделе обсуждаются оптимизации, которые можно сделать для обработки конструкций WHERE. В примере рассматривается оператор SELECT, но то же самое касается и конструкции WHERE в операторах DELETE и UPDATE. Помните, что работа над оптимизатором MySQL продолжается, поэтому настоящий раздел далеко не полон. MySQL выполняет разнообразную оптимизацию, и не вся она здесь документирована. Некоторые виды оптимизации, выполняемые MySQL, перечислены ниже. • Удаление лишних скобок: ((a AND b) AND с OR ( ( ( a AND b) AND (с AND d ) ) ) ) -> (a AND b AND c) OR (a AND b AND с AND d) • Подстановка констант: (a b>5 AND b=c AND a=5
6.2. Оптимизация операторов SELECT и других запросов
417
• Удаление константных условий (необходимо из-за подстановки констант): (В>=5 AND B=5) OR (B=6 AND 5=5) OR (B=7 AND 5=6) -> В=5 OR В=б
• Константные выражения в индексах вычисляются только один раз. •
COUNT (*) по одной таблице, без условия WHERE, выбирается непосредственно из информации о таблице My ISAM и HEAP. Это также делается для любых выражений NOT NULL, когда применяется только с одной таблицей.
• Раннее обнаружение неверных константных выражений. MySQL быстро определяет, что определенный оператор SELECT невозможен и не возвращает строк. •
HAVING объединяется с WHERE, если не используется GROUP BY или групповые функции (COUNT (), MIN () и так далее).
• Для каждой таблицы в соединении конструируется упрощенное условие WHERE для быстрого вычисления и пропуска лишних строк на как можно более раннем этапе. • Все константные таблицы читаются первыми, до остальных таблиц в запросе. Константными считаются следующие таблицы: • Пустые таблицы или таблицы с одной строкой. •
Таблицы, используемые в конструкции WHERE на индексе PRIMARY KEY или UNIQUE, где все части индекса сравниваются с константными выражениями и объявлены как NOT NULL. Все следующие таблицы используются как константные: SELECT * FROM t WHERE первичный_ключ=1; SELECT * FROM t l , t 2 WHERE tl.первичный_ключ =1 AND t2.первичный_ключ=Ь1.id; • Лучшая комбинация соединения таблиц находится после выбора из всех возможных. Если все столбцы в конструкциях ORDER BY и GROUP BY поступают из одной таблицы, этой таблице отдается предпочтение в качестве первой в соединении. • Если есть конструкция ORDER BY и другая конструкция GROUP BY, или же если ORDER BY или GROUP BY содержат столбцы из таблиц, отличных от первой таблицы в объединенном запросе, создается временная таблица. • Если вы используете SQL_SMALL_RESULT, MySQL применяет временные таблицы, размещенные в памяти. • Опрашивается каждый индекс таблицы, и лучший из них используется, если только оптимизатор не считает, что полное сканирование таблицы более эффективно. Ранее сканирование таблицы применялось на основании того, что индекс покрывал более 30% таблицы. Теперь оптимизатор стал более сложным, и основывает свою оценку на добавочных факторах, таких как размер таблицы, количество строк, размер блока ввода-вывода. То есть фиксированный процент не определяет более выбора между использованием индекса и полным сканированием. • В некоторых случаях MySQL может читать строки из индекса, даже не заглядывая в файл данных. Если все столбцы, используемые в индексе, являются числовыми, для разбора запроса используется только дерево индекса.
418
Глава 6. Оптимизация MySQL
•
Прежде чем каждая запись будет выведена, записи, которые не удовлетворяют условию HAVING, пропускаются.
Вот некоторые примеры запросов, выполняющихся очень быстро: SELECT COUNT (*) FROM
имя__таблицы;
SELECT MIN (часть_ключа1), MAX (часть_ключа1) FROM имя_таблицы; SELECT МАХ{часть__ключа2) FROM t b l имя__таблицы WHERE часть_ключа2=константа; SELECT . . . FROM имя_таблицы ORDER BY часть_ключа1, часть_ключа2, . . . LIMIT 1 0 ; SELECT . . . FROM имя__таблицы ORDER BY часть_ключа1 DESC, часть_ключа2 DESC, . . . LIMIT 1 0 ;
Следующие запросы разбираются только на основании дерева индекса, предполагая, что индексные столбцы являются числовыми: SELECT часть_ключа1, часть__ключа2 WHERE часть_ключа1-значение;
SELECT COUNT(*) FROM
FROM
имя_таблицы
имя_таблицы
WHERE часть_ключа1=значение! AND часть_ключа2~значение2; SELECT часть_ключа2 FROM имя_таблицы GROUP BY часть__ключа1;
Приведенные ниже запросы используют индексацию для извлечения строк в отсортированном порядке без дополнительного прохода: SELECT . . . FROM
имя_таблицы
ORDER BY часть_ключа1,
часть_ключа2,
... ;
SELECT . . . FROM имя_таблицы ORDER BY часть_ключа1 DESC, часть_ключа2
DESC,
... ;
6.2.5. Как MySQL оптимизирует выражения OR Метод соединения индексов (Index Merge) применяется для извлечения строк с несколькими сканированиями ref, ref_or_null или range и слияния результатов в один. Этот метод применяется, когда условие выбора в таблице является дизъюнкцией условий, для которых ref, ref_or_null или range могут использоваться с различными ключами. Этот тип оптимизации, связанный с соединением, является новым в MySQL 5.0.0; он представляет ощутимые изменения в поведении, связанном с применением индексов, поскольку старое правило заключалось в том, что сервер был в состоянии использовать максимум один индекс для каждой упоминаемой в запросе таблицы. В выводе команды EXPLAIN этот метод появляется как index_merge в столбце type. В этом случае столбец key содержит список применяемых индексов, a key_len - список самых длинных частей ключа этих индексов. Вот примеры: SELECT * SELECT * WHERE SELECT * WHERE AND SELECT * WHERE
FROM имя_таблицы WHERE часть_ключа1 = 10 OR часть_ключа2 = 20; FROM имя_таблицы {часть_ключа! = 10 OR часть__ключа2 = 20) AND неключевая_часть = 30; FROM t l , t 2 ( t l . к л ю ч 1 IN ( 1 , 2 ) OR t l . к л ю ч 2 LIKE 'значение*') Ь2.ключ1=Ь1.столбец; FROM t l , t 2 tl.ключ1=1
AND ( t 2 . k e y l = t l . с т о л б е ц OR t 2 . k e y 2 = t l . д р у г о й
столбец);
6.2. Оптимизация операторов SELECT и других запросов
419
6.2.6. Как MySQL оптимизирует IS NULL MySQL может выполнять такую же оптимизацию выражения имя_столбца IS NULL, как он делает с имя__столбца = константное_значение. Например, MySQL может использовать индексы и диапазоны для поиска NULL с IS NULL. SELECT * FROM имя_таблицы WHERE ключевой_столбец SELECT * FROM имя_таблицы WHERE ключевой_столбец SELECT * FROM имя_таблицы
I S NULL; NULL;
WHERE ключевой_столбец= константа 1 OR ключевой__столбец=константа2 OR ключевой_столбец IS NULL; Если конструкция WHERE содержит условие имя_столбца IS NULL для столбца, объявленного как NOT NULL, это выражение будет исключено оптимизатором. Однако такая оптимизация не производится в случае, когда эта столбец все-таки может иметь значение NULL, например, если он поступает из таблицы, находящейся справа от LEFT JOIN. MySQL 4.1.1 и выше может дополнительно оптимизировать комбинацию имя_столбца = выражение AND имя_столбца IS NULL - форму, часто встречающуюся в подзапросах. EXPLAIN отобразит ref_or_null, когда такая оптимизация выполняется. Оптимизация может обрабатывать одно условие IS NULL для любой части ключа. Вот некоторые примеры оптимизированных запросов с предположением, что существует индекс на столбцах а и b таблицы t2: SELECT * FROM t l WHERE t l . a = e x p r OR t l . a I S NULL; SELECT * FROM t l , t 2 WHERE t l . a = t 2 . a OR t 2 . a I S NULL; SELECT * FROM t l , t 2 WHERE ( t l . a = t 2 . a OR t 2 . a I S NULL) AND t 2 . b = t l . b ; SELECT * FROM t l , t 2 WHERE t l . a = t 2 . a AND ( t 2 . b = t l . b OR t 2 . b I S N U L L ) ; SELECT * FROM t l , t 2 WHERE ( t l . a = t 2 . a AND t 2 . a I S NULL AND . . . ) OR ( t l . a = t 2 . a AND t 2 . a I S NULL AND . . . ) ; ref_or_null работает, вначале выполняя чтение по указанному ключу, а затем осуществляя отдельный поиск строк со значением ключа NULL. Учтите, что оптимизатор может справиться только с одним уровнем IS NULL. В следующем запросе MySQL применяет поиск ключа только в выражении ( t l . a = t 2 . a AND t2. a IS NULL) и не сможет использовать ключевую часть на Ь: SELECT * FROM t l , t 2 WHERE ( t l . a = t 2 . a AND t 2 . a I S NULL) OR ( t l . b = t 2 . b AND t 2 . b I S NULL);
6.2.7. Как MySQL оптимизирует DISTINCT DISTINCT в комбинации с ORDER BY во многих случаях нуждается в создании временной таблицы. Помните, что поскольку DISTINCT может использовать GROUP BY, вы должны представлять, как MySQL работает со столбцами в конструкциях ORDER BY или HAVING, которые не являются частью списка выбираемых столбцов. MySQL расширяет применение GROUP BY так, что вы можете использовать столбцы и вычисления в списке столбцов SELECT, которые не появляются в конструкции GROUP BY.
420
Глава 6. Оптимизация MySQL
Это стоит за любым возможным значением для данной группы. Вы можете применять это для достижения более высокой производительности, избегая сортировки и группирования по ненужным элементам. Например, вам не нужно группировать по customer.name в следующем запросе: mysql> SELECT o r d e r . c u s t i d , customer.name, MAX(payments) -> FROM order,customer -> WHERE o r d e r . c u s t i d = customer.custid -> GROUP BY order.custid;
В стандартном SQL вам пришлось бы добавлять customer.name в конструкцию GROUP BY. В MySQL это имя излишне, если только вы не работаете в режиме ANSI. Не применяйте это средство, если столбцы, которые вы пропускаете в GROUP BY, не являются уникальными в группе. Вы получите непредсказуемые результаты. В некоторых случаях вы можете использовать MIN () и МАХ () для получения специфического значения столбца, даже если оно не уникально. Следующее выражение возвращает значение column из строки, содержащей самое маленькое значение столбца sort: SUBSTR(MIN(CONCAT(RPAD(sort,6,' '),column)),7) При комбинации LIMIT колмчество_строк с DISTINCT сервер MySQL остановится, как только найдет количество_строк уникальных строк. Если вы не извлекаете столбцы из всех таблиц, участвующих в запросе, MySQL останавливает сканирование неиспользуемых таблиц, как только найдет первое попадание. В следующем примере, предполагая, что t l используется перед t2 (это можно проверить с помощью EXPLAIN), MySQL останавливает чтение из t2 (для любой отдельной строки из t l ) , как только будет найдена первая строка t2: SELECT DISTINCT t l . a FROM t l , t 2 where t l . a = t 2 . a ;
6.2.8. Как MySQL оптимизирует LEFT JOIN и RIGHT JOIN LEFT JOIN В условие_соединения реализовано в MySQL следующим образом: • Таблица В устанавливается как зависимая от таблицы А и всех таблиц, от которых зависит А. • Таблица А устанавливается как зависимая от всех таблиц (кроме В), которые используются В УСЛОВИИ LEFT JOIN. • Условие LEFT JOIN используется для принятия решений о том, как извлекать строки из таблицы В. (Другими словами, никакие условия в конструкции WHERE не применяются). • Выполняется вся стандартная оптимизация соединений, за исключением того, что таблица читается всегда после всех таблиц, от которых она зависит. Если имеются циклические зависимости, MySQL выдает ошибку. • Выполняется вся стандартная оптимизация WHERE. • Если в А существует строка, соответствующая условию WHERE, но нет строк в В, соответствующих условию ON, генерируются дополнительные строки В со всеми столбцами, установленными в NULL. • Если вы используете LEFT JOIN, чтобы найти строки, которые не существуют в некоторой таблице, и указано условие имя_столбца IS NULL в части WHERE, где
6.2. Оптимизация операторов SELECT и других запросов
421
имя_столбца - это столбец, объявленный как NOT NULL, MySQL останавливает поиск строк (для отдельной комбинации ключей) после того, как найдет одну строку, соответствующую условию LEFT JOIN. RIGHT JOIN реализован аналогично, со сменой ролей связанных таблиц. Оптимизатор соединений вычисляет порядок, в котором должны объединяться таблицы. Порядок чтения таблиц обусловлен LEFT JOIN, и STRAIGHT_JOIN помогает оптимизатору выполнять его работу намного быстрее, поскольку ему не приходится сравнивать различные перестановки таблиц. Помните, что это означает, что если выполняется запрос показанного ниже типа, MySQL выполнит полное сканирование Ь, потому что LEFT JOIN указывает читать ее перед d: SELECT * FROM a,b LEFT JOIN с ON (c.key=a.key) LEFT JOIN d ON (d.key=a.key) WHERE b.key=d.key; Чтобы исправить это, в данном случае нужно переписать запрос следующим образом: SELECT * FROM b , a LEFT JOIN с ON ( с . k e y = a . k e y ) WHERE b . k e y = d . k e y ;
LEFT JOIN d ON ( d . k e y = a . k e y )
Начиная с версии 4.0.14, MySQL выполняет следующую оптимизацию LEFT JOIN: если условие WHERE всегда возвращает false для сгенерированной строки NULL, LEFT JOIN заменяется обычным соединением. Например, если столбец t2.columnl будет равен NULL, то в следующем запросе конструкция WHERE будет возвращать false: SELECT * FROM t l LEFT JOIN t2 ON (columnl) WHERE t2.column2=5; Поэтому его можно преобразовать к нормальному соединению: SELECT * FROM t l , t 2 WHERE t2.column2=5 AND tl.columnl=t2.columnl; Такой запрос может быть выполнен быстрее, так как MySQL теперь может использовать таблицу t2 перед таблицей t l . Чтобы жестко задать порядок таблиц, применяйте STRAIGHT_JOIN.
6.2.9. Как MySQL оптимизирует ORDER BY В некоторых случаях MySQL может использовать индексы, чтобы удовлетворить требованиям конструкций ORDER BY и GROUP BY, не выполняя дополнительную сортировку. Индекс может использоваться даже в тех случаях, когда ORDER BY не полностью соответствует ключу индекса до тех пор, пока все неиспользуемые части индекса и все дополнительные столбцы ORDER BY являются константами в конструкции WHERE. Следующие запросы будут использовать индекс для разрешения частей ORDER BY и GROUP BY: SELECT * SELECT * SELECT * SELECT * SELECT * WHERE
FROM FROM FROM FROM FROM часть
t l ORDER t l WHERE t l WHERE t l ORDER tl ключа2=1
BY часть_ключа!,часть_ключа2, ... ; часть_ключа1=константа ORDER BY часть_ключа2; часть_ключа1=константа GROUP BY часть_ключа2; BY часть_ключа1 DESC, часть_ключа2 DESC; ORDER BY часть
ключа!
DESC, часть ключа2
DESC;
422
Глава 6. Оптимизация MySQL
В некоторых случаях MySQL не может использовать индексы для разрешения конструкций ORDER BY и GROUP BY несмотря на то, что он по-прежнему применяет индексы для поиска строк, удовлетворяющих условию WHERE. Эти случаи включают следующие: • Используется ORDER BY на разных ключах: SELECT * FROM t l ORDER BY ключ1, ключ2; • Используется ORDER BY на непоследовательных частях ключа: SELECT * FROM t l WHERE часть_ключа2=константа ORDER BY часть_ключа2; • Используется смесь из ASC и DESC: SELECT * FROM t l ORDER BY часть_ключа1 DESC, часть_ключа2 ASC; •
Ключ, применяемый для извлечения строк, не совпадает с тем, который используется В ORDER BY: SELECT * FROM t l WHERE ключ2=константa ORDER BY ключ1;
• Связывается множество таблиц, и столбцы в ORDER BY - не все из первой неконстантной таблицы, которая используется для извлечения строк. (Это первая таблица в списке, выводимом EXPLAIN, которая не имеет типа соединения const.) •
Применяются разные выражения ORDER BY и GROUP BY.
• Тип используемого индекса таблицы не сохраняет строки в определенном порядке. Например, это касается HASH-индексов для НЕАР-таблиц. В тех случаях, когда MySQL должен сортировать результаты, он применяет следующий алгоритм: 1. Читает все строки по ключу или путем сканирования таблицы. Строки, не соответствующие условию WHERE, пропускаются. 2. Сохраняет ключ сортировки в буфере. Размер буфера задается системной переменной sort_buffer_size. 3. Когда буфер наполняется, запускает qsort (quicksort) на нем и сохраняет результат во временном файле. Сохраняет указатель на отсортированный блок. (Если все строки попадают в буфер, временный файл не создается.) 4. Повторяет предыдущие шаги до тех пор, пока все строки не будут прочитаны. 5. Выполняет множественное слияние вплоть до MERGEBUFF (7) областей в один блок в другом временном файле. Повторяет до тех пор, пока все блоки из первого файла не оказываются во втором файле. 6. Повторяет последующие шаги до тех пор, пока не останется блоков меньше, чем MERGEBUFF2 (15). 7. В последней операции множественного слияния в результирующий файл записывается только указатель на строку (последняя часть ключа сортировки). 8. Читает строки в порядке сортировки, используя указатели на строки в результирующем файле. Чтобы оптимизировать это, выполняется чтение в большой блок указателей строк, его сортировка и затем использование этого блока для чтения строк в сортированном виде в буфер строк. Размер этого буфера задается системной переменной read_rnd_buffer_size. Код, реализующий данный шаг, находится в исходном файле sql/records. ее.
6.2. Оптимизация операторов SELECT и других запросов
423
Может ли MySQL использовать индексы для выполнения запроса, легко проверить с помощью EXPLAIN SELECT.. .ORDER BY. Если вы видите Using f i l e s o r t в столбце Extra, это значит, что использовать индексы MySQL не может. См. раздел 6.2.1. Если вы хотите увеличить скорость ORDER BY, сначала посмотрите, можно ли заставить MySQL использовать индексы вместо дополнительной фазы сортировки. Если нельзя, можно попробовать следующие стратегии: • Увеличить размер переменной sort_buf fer_size. • Увеличить размер переменной read_rnd_buf fer_size. • Изменить tmpdir, чтобы он указывал на каталог в файловой системе с большим объемом свободного пространства. Если вы работаете с версией MySQL 4.1 или более новой, эта опция допускает указание нескольких путей, используемых в циклическом порядке. Пути должный быть разделены символом ' : ' в Unix или ' ; ' в Windows, NetWare и OS/2. Вы можете использовать это средство для распределения нагрузки по нескольким каталогам. На заметку! :;!; Пути должны указывать на каталоги, расположенные на разных физических дисках, а не раздеЛ л ах одного и того же диска.
По умолчанию MySQL сортирует запросы GROUP BY столбец!, столбец2,... так, как если бы в запросе было бы также указано ORDER BY столбец1, столбец2, . . . Если конструкция ORDER BY явно включена в запрос и содержит тот же список столбцов, MySQL во время оптимизации убирает его, безо всякого ущерба для скорости, даже несмотря на то, что происходит сортировка. Если запрос включает в себя GROUP BY, но вы хотите избежать избыточной нагрузки за счет сортировки результатов, то сортировку можно подавить, добавив ORDER BY NULL, например: INSERT INTO foo SELECT a, COUNT(*) FROM bar GROUP BY a ORDER BY NULL;
6.2.10. Как MySQL оптимизирует LIMIT В некоторых случаях MySQL обрабатывает запросы по-разному, когда применяется LIMIT количество_строк и не используется HAVING: • Если вы выбираете только несколько строк с LIMIT, MySQL использует индексы в некоторых случаях, когда обычно более предпочтительно полное сканирование таблицы. • Если вы применяете LIMIT количество_строк с ORDER BY, MySQL прекращает сортировку сразу, как только найдет первые количество_строк строк вместо того, чтобы сортировать всю таблицу. • При комбинации LIMIT количество_строк с DISTINCT, MySQL останавливается, как только найдет количество_строк уникальных строк. • В некоторых случаях конструкция GROUP BY может быть разрешена чтением ключа по порядку (или выполнением сортировки по ключу) с последующим вычислением итогов до тех пор, пока ключ не изменится. В этом случае LIMIT количество_строк не будет вычислять никаких ненужных значений GROUP BY.
424
Глава 6. Оптимизация MySQL
• Как только MySQL отправляет заказанное число строк клиенту, он прерывает выполнение запроса, если только вы не используете SQL_CALC_FOUND_ROWS. • LIMIT 0 всегда быстро возвращает пустой набор. Это полезно для проверки запроса или для получения типов результирующих столбцов. • Когда сервер использует временные таблицы для обработки запроса, LIMIT количество_строк применяется для вычисления необходимого объема дискового пространства.
6.2.11. Как избежать сканирования таблиц EXPLAIN показывает значение ALL в столбце type, когда MySQL осуществляет полное сканирование таблицы при выполнении запроса. Обычно это случается при следующих условиях: • Таблица настолько мала, что быстрее выполнить полное сканирование, чем поиск по ключу. Это обычный случай для таблиц, в которых меньше 10 строк и небольшая длина строки. • Не указаны ограничения в конструкциях ON или WHERE для индексированных столбцов. • Индексированные столбцы сравниваются с константными значениями, и MySQL (на основе индексного дерева) вычисляет, что константа покрывает значительную часть таблицы и поэтому полное сканирование должно быть быстрее. См. раздел 6.2.4. • Вы используете ключ с малым количеством возможных значений (значению ключа соответствует много строк) среди других столбцов. В этом случае MySQL предполагает, что применение ключа приведет к большому количеству поисков по ключу и поэтому сканирование таблицы будет выполнено быстрее. Для небольших таблиц сканирование часто подходит. Для больших таблиц попробуйте следующую технику минимизации ошибочного выбора оптимизатором полного сканирования: • Используйте ANALYZE TABLE имя_таблицы с целью обновления информации о распределении значений ключей индексов для сканируемых таблиц. • Используйте FORCE INDEX для сканируемых таблиц, чтобы указать MySQL, что сканирование таблицы обойдется дороже, чем доступ с использованием индекса. SELECT * FROM t l , t2 FORCE INDEX (индекс_для_столбца) WHERE 11. имя_столбца^2 . имя_стрлбца; • Запускайте mysqld с опцией —max-seeks-for-key=1000 либо применяйте SET max_seeks_for_key=1000, чтобы указать оптимизатору, что никакие сканирования ключей не потребуют более 1000 чтений. См. раздел 4.2.3.
6.2.12. Скорость выполнения запросов INSERT Время на вставку записи определяется следующими факторами, где числа показывают предположительные пропорции: • Подключение: (3) • Отправка запроса серверу: (2)
6.2. Оптимизация операторов SELECT и других запросов •
Разбор запроса: (2)
•
Вставка записи: (1 х размер записи)
•
Вставка индекса: (1 х количество записей)
•
Закрытие: (1)
425
Здесь не принимаются во внимание затраты на открытие таблиц, которые выполняются однажды для каждого параллельного выполняющегося запроса. Размер таблицы замедляет вставку индексов по закону log N, предполагая, что речь идет об индексах на основе бинарных деревьев. Для ускорения вставки можно применить следующие методы: •
Если вы вставляете много строк с одного клиента в одно и то же время, применяйте операторы INSERT с множеством списков VALUES, чтобы добавлять сразу несколько строк. Это значительно быстрее (в некоторых случаях во много раз), чем использовать отдельные однострочные операторы INSERT. Если вы добавляете данные в непустую таблицу, можете настроить переменную bulk_insert_buffer_size, чтобы это делалось еще быстрее (см. раздел 4.2.3).
•
Если вы вставляете множество строк с разных клиентов, то можете получить более высокую скорость, применяя оператор INSERT DELAYED.
•
В таблицы My ISAM можно вставлять строки одновременно с выполнением запросов SELECT, если только в таблице нет удаленных строк.
•
При загрузке таблицы из текстового файла применяйте LOAD DATA INFILE. Обычно это работает в 20 раз быстрее, чем при использовании множества операторов INSERT.
•
Потратив незначительные дополнительные усилия, можно добиться того, что LOAD DATA INFILE будет работать даже еще быстрее. Для этого выполните следующую процедуру: 1. Необязательно создайте таблицу с помощью CREATE TABLE. 2. Выполните оператор FLUSH TABLES или команду mysqladmin
flush-tables.
3. Используйте myisamchk —keys-used=O -rq /путь/к/базе_данных/имя_таблицы. Это отключит использование всех индексов таблицы при загрузке. 4. Вставьте данные в таблицу с помощью LOAD DATA INFILE. Это не будет обновлять индексы, поэтому выполнится очень быстро. 5. Если предполагается, что в будущем таблица будет служить только для чтения, с помощью myisampack уменьшите ее размер (см. раздел 8.1.3.3). 6. Пересоздайте индексы с помощью команды myisamchk -r -q /путь/к/базе_данных/имя_таблицы. Это создаст дерево индекса в памяти, прежде чем записать его на диск, что гораздо быстрее, так как позволяет избежать множества операций доступа к диску. Результирующее дерево индекса к тому же лучше сбалансировано. 7. Выполните оператор FLUSH TABLES или команду mysqladmin
flush-tables.
Имейте в виду, что LOAD DATA INFILE также выполняет предварительную оптимизацию, если вставка выполняется в пустую таблицу My ISAM. Главное отличие состоит в том, что вы можете позволить myisamchk выделить гораздо больше вре-
426
Глава 6. Оптимизация MySQL менной памяти для создания индексов, чем это делает сервер при пересоздании индексов, когда он выполняет LOAD DATA INFILE. Начиная с MySQL 4.0, можно использовать также ALTER TABLE имя_таблицы DISABLE KEYS вместо myisamchk --keys-used=O -rq /путь/к/базе_данных/ имя_таблицы и ALTER TABLE имя_таблицы ENABLE KEYS вместо myisamchk -r -q /путь/к/базе_данных/имя_таблицы. При этом шаг FLUSH TABLES можно пропустить. • Вы можете увеличить скорость операции вставки, которая выполняется несколькими операторами, если заблокируете таблицы: LOCK TABLES a WRITE; INSERT INTO a VALUES (1,23), (2,34), (4,33); INSERT INTO a VALUES (8, 26), (6,29) ; UNLOCK TABLES; Выигрыш в производительности появляется за счет того, что индексный буфер сбрасывается на диск только один раз, после того, как завершатся все операторы INSERT. Явные операторы блокировки не требуются, если вы можете вставить все строки одним оператором. Для транзакционных таблиц, чтобы поднять скорость, нужно использовать блоки BEGIN/COMMIT в м е с т о LOCK TABLES.
Блокировка также снижает общее время выполнения тестов со многими соединениями, несмотря на то что максимальное время ожидания индивидуальных соединений может возрасти, поскольку они ожидают снятия блокировок. Например: Connection I does 1000 inserts Connections 2, 3, and 4 do 1 insert Connection 5 does 1000 inserts Если вы не применяете блокировки, соединения 2, 3 и 4 завершатся перед соединениями 1 и 5. Если же они используются, возможно, что соединения 2, 3 и 4 не завершатся перед соединениями 1 и 5, однако общая скорость будет на 40% выше. Операции INSERT, UPDATE и DELETE в MySQL выполняются очень быстро, но вы получите лучшую общую производительность, добавив блокировки вокруг всего, что делает больше, чем 5 вставок или обновлений строк. Если вы делаете очень много вставок, то можете выполнять LOCK TABLE с последующим UNLOCK TABLE периодически (с интервалом в 1000 строк), чтобы позволить другим пользователям иметь доступ к таблице. Это также даст хороший выигрыш в производительности. INSERT все еще работает значительно медленнее при загрузке данных, чем LOAD DATA INFILE, даже если используются описанные выше стратегии. • Чтобы получить еще некоторое приращение скорости для таблиц My ISAM как при использовании INSERT, так и при LOAD DATA INFILE, можно увеличить значение системной переменной key_buffer_size. См. раздел 6.5.2.
6.2.13. Скорость выполнения запросов UPDATE Запросы на обновление оптимизируются как запрос SELECT с дополнительной нагрузкой в виде записи. Скорость записи зависит от объема данных, которые нужно обновить, и количества обновляемых индексов. Индексы, которые не изменяются, обновляться не будут.
6.2. Оптимизация операторов SELECT и других запросов
427
Другой способ получить быстрые обновления - это отложить их и позже сделать множество обновлений сразу. Выполнение групповых обновлений происходит значительно быстрее, чем по одному, если заблокировать таблицу. Следует отметить, что для таблиц My ISAM, которые используют динамический формат записей, обновление записи с увеличением ее общей длины может разделить запись. Если вы делаете это часто, очень важно периодически выполнять OPTIMIZE TABLE.
6.2.14. Скорость выполнения запросов DELETE Время на удаление отдельных записей прямо пропорционально количеству индексов. Чтобы удалять записи быстрее, можно увеличить размер кэша ключей. См. раздел 6.5.2. Если вы хотите удалить все строки в таблице, лучше применяйте TRUNCATE TABLE имя_таблицы, чем DELETE FROM имя__таблицы.
6.2.15. Другие советы по оптимизации В этом разделе представлены разнообразные советы по увеличению скорости выполнения запросов: • Используйте постоянные соединения, чтобы исключить затраты на подключения. Если вы не можете применять постоянные соединения и инициируете множество подключений к базе данных, можно изменить переменную thread_cache_size (см. раздел 6.5.2). • Всегда проверяйте все выдаваемые запросы - действительно ли они используют созданные вами индексы таблиц. В MySQL это можно сделать с помощью оператора EXPLAIN (см. раздел 6.2.1). • Старайтесь не применять сложных запросов SELECT к таблицам My ISAM, которые часто обновляются, чтобы избежать проблем с блокировками, обусловленными конкуренцией между чтением и записью. • В таблицы My ISAM, в которых нет удаленных строк, можно выполнять вставку новых строк в конец таблицы одновременно с выполнением запросов на чтение. Если для вас это важно, вам стоит рассмотреть возможность такого применения этих таблиц, которое исключает удаление строк. Другая возможность - это запускать OPTIMIZE TABLE после удаления большого количества строк. • Используйте ALTER TABLE... ORDER BY выражение lf выражение 2, . .., если вы в основном извлекаете строки в порядке выражение 1, выражение2, . . . Применяя это средство после проведения интенсивных изменений в таблице, вы можете получить более высокую производительность. • В некоторых случаях имеет смысл представить столбец, как "хешируемый" на основе информации из других столбцов. Если столбец короткий и в достаточной степени уникальный, это может работать значительно быстрее, чем большой составной индекс по многим столбцам. В MySQL очень просто использовать такой добавочный столбец: SELECT * FROM имя_таблицы WHERE хешируеьшй_столбеигШЬ (CONCAT {столбец!, AND coll='константа* AND co!2='константа';
столбец2))
428
Глава 6. Оптимизация MySQL
• В интенсивно изменяемых таблицах My ISAM нужно стараться избегать применения столбцов переменной длины (VARCHAR, BLOB и TEXT). Даже если таблица включает в себя всего один такой столбец, она будет использовать динамический формат записей. См. главу 8. • Обычно не стоит разделять одну таблицу на две или несколько только из-за того, что строки стали "большими". При обращении к строке, прежде всего на производительность влияет время доступа к диску - время поиска первого байта строки. После того, как первый байт найден, большинство современных дисков могут прочесть всю строку достаточно быстро для большинства приложений. Единственный случай, когда действительно имеет смысл разбить таблицу - это если речь идет о таблице My ISAM с динамическим форматом записи (см. выше), которую вы можете привести к формату фиксированного размера строки, или же вам очень часто нужно выполнять ее полное сканирование, при этом не нуждаясь в большинстве столбцов. См. главу 8. • Если часто требуется вычислять результаты, подобные счетчику итоговых значений, на основании множества строк, возможно, будет гораздо лучше ввести новую таблицу и обновлять счетчик в реальном времени. Обновление следующего типа работает очень быстро: UPDATE имя таблицы SET столбец_счетчика~столбец WHERE ключевой_столбец=константа ;
счетчика+1
Это действительно важно, когда вы применяете механизмы хранения MySQL, такие как My ISAM и ISAM, у которых есть только блокировка уровня таблицы (множество чтений/одна запись). Но это также повысит производительность и в большинстве других баз данных, поскольку диспетчеру блокировок строк в этом случае придется выполнять меньше работы. • Если вам нужно собирать статистику из больших таблиц протоколов, применяйте итоговые таблицы вместо регулярного сканирования этих больших таблиц. Поддержка таблиц итогов значительно проще, чем вычисление итогов "вживую". Гораздо быстрее регенерировать новые итоговые таблицы, когда что-то изменяется в зависимости от бизнес-решений, чем вносить эти изменения в работающие приложения. • Если возможно, вы должны разделить отчеты на "живые" и "статистические", при этом данные, необходимые для статистических отчетов, выбираются только из итоговых таблиц, которые генерируются периодически из живых данных. • Воспользуйтесь преимуществом того факта, что столбцы имеют значения по умолчанию. Вносите явно только те данные, что отличаются от значений по умолчанию. Это сократит затраты времени MySQL на разбор SQL-операторов и повысит скорость вставки. • В некоторых случаях удобно упаковывать данные и сохранять их в столбцы типа BLOB. Конечно, при этом придется добавлять дополнительный код в приложения, чтобы упаковывать и распаковывать информацию из значений BLOB, но на определенном этапе это может помочь сэкономить на чтении. Это достаточно практично, когда характер данных не приспособлен к хранению в табличной структуре типа "строка-столбец".
6.2. Оптимизация операторов SELECT и других запросов
429
• Обычно вы должны стараться избегать избыточности данных (что в теории реляционных баз данных называется "третьей нормальной формой"). Однако не бойтесь дублировать информацию или создавать итоговые таблицы, если необходимо добиться более высокой скорости. • Хранимые процедуры и функции, определяемые пользователем (User-Defined Functions - UDF) могут оказаться хорошим способом повышения производительности для некоторых задач. Однако если вы работаете с базой данных, которая не поддерживает этих средств, у вас должен быть другой способ выполнения тех же задач, даже если этот другой способ медленнее. • Вы всегда можете выиграть что-то, кэшируя запросы или ответы на уровне ваших приложений с последующим выполнением всех вставок и обновлений вместе. Если ваша база данных поддерживает блокировку таблиц (как MySQL и Oracle), это поможет гарантировать, что кэш индекса будет сброшен только однажды, после всех изменений. • Используйте INSERT DELAYED, если вам не обязательно знать, когда записаны ваши данные. Это повышает скорость, потому что множество строк могут быть записаны на диск в один прием. • Используйте INSERT LOW_PRIORITY, когда хотите дать операторам SELECT более высокий приоритет, чем операторам вставки строк. • Используйте SELECT LOWPRIORITY, когда нужно, чтобы запрос "перепрыгивал" очередь. То есть, SELECT будет выполняться, даже если другой клиент ожидает возможности выполнить запись. • Используйте многострочные операторы INSERT, чтобы сохранять много строк одним оператором (многие SQL-серверы поддерживают это). • Используйте LOAD DATA INFILE для загрузки больших объемов данных. Это быстрее, чем применение операторов INSERT. • Используйте столбцы AUTOINCREMENT для генерации уникальных значений. • Используйте OPTIMIZE TABLE от случая к случаю, чтобы избежать фрагментации таблиц MylSAM, когда применяется формат динамических таблиц. См. раздел 8.1.3. • Когда это возможно, используйте НЕАР-таблицы, чтобы получить высокую скорость. См. главу 8. • Когда применяется нормальная настройка Web-сервера, графические изображения должны храниться в виде файлов. Поэтому храните в базе данных только ссылки. Главная причина состоит в том, что Web-серверы гораздо лучше кэшируют файлы, чем содержимое баз данных, поэтому намного легче получить быструю систему, применяя файлы. • Используйте таблицы в памяти для некритичных данных, к которым обращаются часто, таких как информация о последнем рекламном баннере, показанном пользователю, который отключил cookie в своем браузере. • Столбцы с идентичной информацией в разных таблицах должны быть объявлены с одинаковыми типами данных. В противном случае до версии MySQL 3.23 соединения работали медленно.
430
Глава 6. Оптимизация MySQL
• Старайтесь использовать простые имена столбцов. Например, в таблице customer используйте имя столбца name вместо customer_name. Чтобы сделать имена переносимыми на другие SQL-серверы, их длина не должна превышать 18 символов. • Если вам нужна действительно высокая скорость, стоит обратить внимание на низкоуровневые интерфейсы доступа к данным, которые поддерживают различные SQL-серверы. Например, работая напрямую с механизмом хранения MySAM в MySQL, вы можете добиться от двукратного до четырехкратного повышения скорости по сравнению с SQL-интерфейсом. Чтобы иметь возможность сделать это, данные должны находиться на том же сервере, что и приложения, и обычно они должны быть доступны только одному процессу (поскольку внешняя блокировка файлов действительно медленна). Это проблему можно было бы решить вводом низкоуровневых команд на сервере MySQL (и это был бы простой путь для получения высокой производительности). При тщательной разработке конструкции интерфейса баз данных было бы достаточно просто поддерживать такой тип оптимизации. • Если вы работаете с числовыми данными, во многих случаях быстрее иметь доступ к данным в базе (при живом соединении), чем в текстовом файле. Информация в базе, скорее всего, будет храниться в более компактном формате, чем в текстовом файле, поэтому обращение к ней требует меньших затрат на чтение с диска. Вы также экономите на коде приложений, так как нет необходимости выполнять разбор текстовых файлов, чтобы найти строку и границы столбцы. • Для некоторых операций выигрыш в производительности может обеспечить репликация. Вы можете распределять клиентские запросы по реплицируемым серверам, таким образом, балансируя нагрузку. Чтобы избежать замедления работы главного сервера во время создания резервных копий, это можно поручить подчиненным серверам. См. главу 5. • Объявление таблицы MylSAM с табличной опцией DELAY_KEY_WRITE=1 ускоряет обновление индексов, поскольку они не сбрасываются на диск вплоть до закрытия таблицы. Недостаток такого подхода состоит в том, что если после открытия таблиц сервер выходит из строя, обязательно потребуется выполнить проверку таблиц, запустив сервер с опцией —my is am-re cove r или воспользовавшись программой myisamchk. Только после выполнения проверки можно будет нормально запустить сервер. (Следует заметить, однако, что вы ничего не потеряете, используя DELAY_KEY_WRITE, поскольку ключи всегда могут генерироваться на основе строк данных.)
6.3. Вопросы блокировки 6.3.1. Методы блокировки В настоящий момент MySQL поддерживает блокировку на уровне таблицы для таблиц ISAM, My ISAM и MEMORY (HEAP), блокировку уровня страницы для таблиц BDB и блокировку уровня строки - для таблиц InnoDB. Во многих случаях вы можете сделать квалифицированные предположения о том, какой тип блокировки лучший для приложения, но, в общем, очень трудно принять решение в пользу того или иного типа блокировки. Все зависит от приложений, и разные части одного и того же приложения могут требовать блокировок различных типов.
6.3. Вопросы блокировки
431
Чтобы решить, хотите ли вы использовать механизм хранения с блокировками уровня строки, нужно посмотреть, что делает ваше приложение и в какой пропорции оно использует запросы на выборку данных и на их обновление. Например, большинство Web-приложений выполняют множество выборок, очень мало удалений, обновления основаны в основном на значениях ключей, а вставки - только в некоторые специфические таблицы. Базовый тип таблиц MySQL - MylSAM - очень хорошо подходит для такого режима работы. Система блокировки уровня таблиц в MySQL свободна от взаимных блокировок (deadlock) в тех механизмах хранения, которые ее поддерживают. Избежание взаимных блокировок осуществляется тем, что всегда запрашиваются все необходимые блокировки в начале запроса и таблицы блокируются в одном и том же порядке. Метод блокировки таблиц при записи MySQL работает следующим образом: • Если в данный момент на таблице нет блокировок, поставить блокировку записи. • В противном случае поставить запрос на блокировку в очередь запросов блокировок записи. Метод блокировки таблиц при чтении MySQL работает следующим образом: • Если в данный момент на таблице нет блокировок записи, поставить блокировку чтения. • В противном случае поставить запрос на блокировку в очередь запросов блокировок чтения. Когда блокировка снята, возможность установки следующей предоставляется потокам, ожидающим в очереди блокировок записи, а затем - ожидающим в очереди блокировок чтения. Это означает, что если в таблице проводится много обновлений, то операторы SELECT будут ожидать, пока все они не выполнятся. Начиная с версии MySQL 3.23.33, вы можете анализировать состояние конкурирующих блокировок в системе, проверяя состояние переменных Table_locks_waited и Table_locks_immediate: mysql> SHOW STATUS LIKE 'Table%f; + + + | Variablename | Value | I Table_locks_immediate I 1151552 | I Table_locks_waited | 15324 | + + + Что касается MySQL 3.23.7 (3.23.5 для Windows), при работе с таблицами MylSAM вы можете свободно смешивать параллельные операторы INSERT и SELECT без блокировок, если только операторы INSERT не конкурируют между собой. То есть можно вставлять строки в таблицы MylSAM, в то время как другой клиент осуществляет чтение из них. Никаких конфликтов не возникает, если файл данных не содержит свободных блоков в середине, так как в этом случае записи всегда вставляются в конец файла. (Пустоты могут образоваться в результате удаления или обновления строк, находящихся в средине таблицы.) Если есть пустоты, параллельные вставки будут включены автоматически, когда они все будут заполнены новыми данными. Если вы хотите выполнять множество операторов INSERT и SELECT на таблице в момент, когда параллельные вставки невозможны, вы можете вставлять строки во времен-
432
Глава 6. Оптимизация MySQL
ный файл и обновлять реальную таблицу записями из этого временного файла периодически. Это можно сделать с помощью следующего кода: mysql> LOCK TABLES real_table WRITE, insert_table WRITE; mysql> INSERT INTO real_table SELECT * FROM insert_table; mysql> TRUNCATE TABLE insert_table; mysql> UNLOCK TABLES; InnoDB использует блокировки строк, a BDB - блокировки страниц. Для механизмов хранения InnoDB и BDB взаимные блокировки возможны. Это объясняется тем, что InnoDB автоматически вызывает блокировки строк, a BDB - блокировки страниц при выполнении SQL-операторов, а не в начале транзакции. Преимущества блокировки строк таковы: • Меньше блокировок конфликтуют между собой, когда разные потоки работают с разными строками. • Меньше изменений для отката. • Есть возможность держать блокировку отдельной строки в течение длительного времени. Ниже представлены недостатки блокировки строк: • Требуется больше памяти, чем при блокировке на уровне таблиц или на уровне страниц. • Медленнее работает, чем блокировка уровня страниц или уровня таблиц, особенно когда применяется к значительной части таблицы, поскольку нужно выполнить намного больше индивидуальных блокировок. • Определенно гораздо хуже, чем другие типы блокировок, если вы часто выполняете операции GROUP BY на значительной части данных, или если вы часто должны сканировать всю таблицу. • При высокоуровневом блокировании гораздо проще поддерживать блокировки других типов для настройки приложения, потому что у них нагрузка, связанная с блокировками, меньше, чем при блокировках уровня строки. Блокировки таблиц превосходят блокировки уровня страниц или уровня строк в следующих случаях: • Большинство операторов, выполняемых в таблице, связано с чтением. • Чтения и обновления по строгим ключам, когда вы модифицируете или удаляете строку, которая может быть извлечена единственным чтением ключа: UPDATE имя_таблицы SET столбец=значение WHERE столбец_уникального_ключа=зна чение_ключа ; DELETE FROM имя_таблицы WHERE столбец_уникального_ключа=значение_ключа; • Операторы SELECT комбинируются с операторами INSERT и очень малым количеством операторов UPDATE И DELETE. • Выполняется много полных сканирований таблиц и операций GROUP BY без необходимости записи. Ниже указаны альтернативы блокировкам строк и страниц. Управление версиями (такое, как мы используем в MySQL для параллельных вставок), когда вы можете иметь одну операцию записи одновременно со многими опера-
6.3. Вопросы блокировки
433
циями чтения. Это означает, что база/таблица поддерживают разные взгляды на данные в зависимости от того, когда вы начинаете доступ к ним. Другие названия для этого: перемещение во времени, копирование по записи или копирование по требованию. Копирование по требованию во многих случаях гораздо лучше, чем блокировка уровня страницы или уровня строки. Однако в худшем случае использует больше памяти, чем когда применяется нормальная блокировка. Вместо применения блокировок уровня строки можно использовать блокировки уровня приложения, такие как GETLOCKO и RELEASE_LOCK () в MySQL. Это экспертные блокировки, поэтому они работают только в хорошо работающих приложениях.
6.3.2. Вопросы блокировки таблиц Для достижения очень высокой скорости MySQL использует блокировки таблиц (вместо блокировок страниц, строк или столбцов) во всех механизмах хранения, кроме InnoDB и BDB. Для InnoDB и BDB MySQL применяет блокировку таблиц, только если это сделано явно с помощью вызова LOCK TABLES. Для этих типов таблиц мы вообще не рекомендуем использовать LOCK TABLES, поскольку таблицы InnoDB используют автоматическую блокировку строк, a BDB - блокировку страниц, чтобы гарантировать изоляцию транзакций. В больших таблицах для большинства приложений блокировка уровня таблицы гораздо лучше, чем блокировка уровня строки, однако, существуют некоторые подводные камни. Блокировка таблицы позволяет многим потокам читать данные из таблицы одновременно, но если поток собирается записывать в таблицу, он должен сначала получить эксклюзивный доступ. В процессе обновления данных все остальные потоки, которым нужен доступ к таблице, вынуждены ожидать, пока обновление не завершится. Обновления таблиц обычно рассматриваются как более важная операция, чем извлечение данных, поэтому им присваивается более высокий приоритет. Это должно гарантировать, что обновления таблицы не "истощатся", даже если в среде высока активность запросов SELECT. Блокировка таблиц вызывает проблемы в случаях, подобных тому, когда поток ожидает, поскольку диск переполнен и требуется дополнительно свободное пространство, чтобы поток продолжил работу. В этом случае все потоки, которым нужен доступ к проблемной таблице, также будут находиться в состоянии ожидания до тех пор, пока не будет выделено это свободное пространство. Табличная блокировка также невыгодна при следующем сценарии событий: • Клиент выдает оператор SELECT, который долго выполняется. • Другой клиент следом запускает оператор UPDATE для той же таблицы. Этому клиенту придется ждать, пока не завершится первый SELECT. • Другой клиент выдает другой оператор SELECT для той же таблицы. Поскольку UPDATE имеет более высокий приоритет, чем SELECT, последнему SELECT придется ждать, пока не завершится UPDATE. Он также будет ждать завершения первого SELECT!
В следующем списке представлены некоторые способы минимизации противоречий, связанных с блокировкой таблиц. • Постарайтесь добиться, чтобы SELECT выполнялся быстрее. Чтобы это сделать, можно создать итоговые таблицы.
434
Глава 6. Оптимизация MySQL
• Запустите mysqld с опцией —low-priority-updates. Это назначит всем операторам, модифицирующим данные, более низкий приоритет, чем операторам SELECT. В этом случае следующий оператор SELECT из предыдущего сценария будет выполнен перед оператором UPDATE и ему не придется ожидать завершения первого SELECT.
• Можно указать, что все обновления, исходящие из определенного клиентского соединения, должны выполняться с пониженным приоритетом, дав команду SET LOW_PRIORITY_UPDATES=1. • Можно назначить конкретному оператору INSERT, UPDATE или DELETE пониженный приоритет с помощью атрибута LOW_PRIORITY. • Можно назначить конкретному оператору SELECT повышенный приоритет, применив атрибут HIGH_PRIORITY. • Начиная с MySQL 3.23.7, можно запускать mysqld с низким значением системной переменной max_write_lock_count, чтобы заставить MySQL временно повышать приоритет всех операторов SELECT, которые находятся в состоянии ожидания, после того, как произойдет заданное количество операций вставки. Это позволяет установить блокировку READ после некоторого количества блокировок WRITE. • Если у вас возникают проблемы с INSERT в комбинации с SELECT, переключитесь на использование таблиц My ISAM, которые поддерживают параллельную работу SELECT И INSERT.
• Если вы смешиваете вставки и удаления в одной и той же таблице, очень поможет INSERT DELAYED.
• Если у вас возникают проблемы с SELECT в комбинации с DELETE, может помочь опция LIMIT для оператора DELETE. • Применение SQL_BUFFER_RESULTS с операторами SELECT может уменьшить продолжительность времени блокировки таблицы. • Можно внести изменение в программный код блокировки в mysys/thr_lock. с для использования единственной очереди. В этом случае блокировки записи и блокировки чтения будут иметь одинаковые приоритеты, что может помочь в некоторых приложениях. Вот некоторые советы по использовании блокировок таблиц в MySQL: • Конкуренция пользователей не является проблемой, если вы не смешиваете обновления с выборками, которые имеют дело с большим количеством строк. • Для ускорения вы можете использовать LOCK TABLES (много обновлений внутри одной блокировки работают гораздо быстрее, чем обновления без явных блокировок). Разнесение содержимого одной таблицы по нескольким таблицам также может помочь. • Если вы столкнулись с проблемой скорости при блокировке таблиц MySQL, вы можете повысить производительность, преобразовав некоторые из таблиц в формат innoDB или BDB. См. главу 9 и раздел 8.4.
6.4. Оптимизация структуры базы данных
435
6.4. Оптимизация структуры базы данных 6.4.1. Конструкторские решения MySQL содержит данные строк и данные индексов в отдельных файлах. Многие (почти все) другие базы данных смешивают информацию строк и индексную информацию в одной таблице. Мы верим, что вариант, реализованный в MySQL, лучше для очень широкого диапазона современных систем. Другой способ предусматривает хранение информации каждого столбца в отдельной области (примерами могут служить SDBM и Focus). Это наносит ущерб производительности при каждом запросе, который обращается более чем одному столбцу. Поскольку это происходит очень часто, мы уверены, что такая модель не особенно хороша для баз данных общего назначения. Более общий случай - это когда данные и индексы хранятся вместе (как у Oracle, Sybase и других). В этом случае информация строк таблицы находится на конечных страницах (листьях) индексов (верно лишь отчасти, если речь идет о кластерных индексах Sybase -прим. перев.). Преимущество такого варианта заключается в том, что если индекс хорошо кэширован, экономятся обращения к диску. Недостатки же следующие: • Сканирование таблиц значительно медленнее, поскольку нужно читать индексы для того, чтобы получить данные (это не совсем верно, по крайней мере, в Oracle не требуется читать индекс, если оптимизатор решает его не использовать - прим. перев.). • Невозможно использовать только индексные таблицы, чтобы извлечь данные для запроса (это не совсем верно, так как и в Oracle, и в Sybase при извлечении столбцов, участвующих в ключе индекса, используется только индекс, а доступ к самой таблице не требуется - прим. перев.). • Вы теряете большой объем пространства, поскольку вынуждены дублировать индексы из узлов (поскольку не в состоянии хранить строки в узлах (это не касается кластерных индексов Sybase - прим. перев.)). • Удаления приводят к деградации таблиц со временем, поскольку индексы в узлах обычно не обновляются при удалении (опять неверно! По крайней мере, принцип разделения табличного пространства на сегменты и экстенты в Oracle с возможностью указания предельных процентных значений их наполнения снимает эту проблему - прим. перев.)). • Труднее кэшировать только индексные данные.
6.4.2. Делайте объем данных как можно меньше Один из основных принципов оптимизации заключается в том, что нужно проектировать таблицы так, чтобы они занимали как можно меньше места на диске. Это может дать огромный выигрыш производительности, поскольку чтения диска выполняются быстрее и маленькие таблицы обычно требуют меньше основной памяти, в то время как ее содержимое интенсивнее используется при выполнении запросов. Индексация также в меньшей степени обременяет систему, если выполняется на маленьких столбцах. MySQL поддерживает множество разных типов таблиц и форматов строк. Для каждой таблицы вы можете принимать решения, какие методы хранения/индексации применять. Выбор правильного формата таблиц для вашего приложения может дать большой выигрыш производительности. См. главу 8.
436
Глава 6. Оптимизация MySQL
Вы можете добиться лучшей производительности и минимизировать место, необходимое для хранения данных, используя описанные ниже приемы. • Применяйте самые эффективные (компактные) из возможных типы данных. MySQL поддерживает много специализированных типов, которые экономят дисковое пространство и память. • Применяйте более компактные целочисленные типы, чтобы сделать таблицы меньше. Например, MEDIUMINT обычно лучше, чем INT. • Если возможно, объявляйте столбцы как NOT NULL. Это делает все быстрее и экономит один бит на столбец. Если вам действительно требуется NULL в ваших приложениях, вы, конечно, можете его применять. Просто избегайте того, чтобы это было свойством всех столбцов по умолчанию. • Для таблиц MylSAM, если в них нет столбцов переменной длины (VARCHAR, TEXT или BLOB), применяется формат записей с постоянной длиной. Это работает быстрее, но, к сожалению, приводит к расходу дискового пространства. См. раздел 8.1.3. • Первичный индекс таблицы должен быть коротким, насколько возможно. Это обеспечивает простую и эффективную идентификацию каждой строки. • Создавайте только те индексы, в которых действительно нуждаетесь. Индексы хороши для извлечения данных, но плохи, если вы хотите, чтобы сохранение данных было быстрым. Если вы в основном осуществляете доступ к таблице поиском по комбинации столбцов, создайте индекс по ним. Первой частью ключа индекса должна быть наиболее используемая столбец. Если вы всегда используете много столбцов, то должны использовать столбец с большим количеством дубликатов первым, чтобы получить лучшее сжатие индекса. • Весьма вероятно, что столбец имеет уникальный префикс в первых нескольких символах, тогда имеет смысл создать индекс по этому префиксу. MySQL поддерживает индексы по левой части символьных столбцов. Более короткие индексы быстрее не только потому, что занимают меньше места на диске, но и потому, что дают больше попаданий при обращении к индексному кэшу, а потому требуют меньше обращений к диску. См. раздел 6.5.2. • В некоторых обстоятельствах может оказаться выгодным разделение таблицы, которая сканируется наиболее часто, на две.
6.4.3. Индексы столбцов Все типы столбцов в MySQL могут быть индексированы. Применение индексов на соответствующих столбцах - лучший способ повысить производительность операций SELECT.
Максимальное количество индексов на таблицу и максимальная длина ключа индекса для каждого механизма хранения имеет свои значения (см. главу 8). Все механизмы хранения поддерживают, как минимум, 16 индексов на таблицу и общую длину ключа индекса, как минимум, в 256 байт. У большинства механизмов хранения значения этих ограничений выше. Используя синтаксис имя_столбца {длина) в спецификации индекса, можно создать индекс, ключом которого служат только первые длина символов столбца типа CHAR или VARCHAR. Индексируя подобным образом только префикс значений столбца, можно создать гораздо меньший по размеру индексный файл.
6.4. Оптимизация структуры базы данных
437
Механизмы хранения MylSAM и (начиная с MySQL 4.0.14) innoDB, также поддерживают индексацию столбцов типа TEXT и BLOB. При индексации этих столбцов вы должны указать длину префикса, используемую в ключе индекса, например: CREATE TABLE t e s t (blob_col BLOB, INDEX(blob_col(10))); Длина префикса может быть до 255 байтов (или 1000 байтов для таблиц MylSAM и InnoDB, как в версии MySQL 4.1.2). Обратите внимание, что ограничение длины префикса измеряется в байтах, в то время как длина префикса в операторе CREATE TABLE интерпретируется как количество символов. Имейте это в виду, когда указываете длину префикса для столбца, использующего многобайтный набор символов. Начиная с MySQL 3.23.23, вы можете также создавать индексы FULLTEXT. Они используются для полнотекстового поиска. Индексы FULLTEXT поддерживаются только таблицами типа MylSAM, и только для столбцов типа CHAR, VARCHAR и TEXT. Индексация в них всегда выполняется по всей столбце, а индексы, основанные на части столбцы (префиксные) не поддерживаются Начиная с MySQL 4.1.0, можно создавать индексы на пространственных (spatial) типах столбцов. В настоящее время пространственные типы поддерживаются только механизмом хранения MylSAM. Пространственные индексы используют R-деревья. Механизм хранения таблиц MEMORY (HEAP) поддерживает хеш-индексы. Начиная с MySQL 4.1.0, этот механизм также поддерживает индексы на основе В-деревьев (бинарных деревьев).
6.4.4. Составные индексы MySQL может создавать индексы с ключом, состоящим из нескольких столбцов. Индекс может состоять максимум из 15 столбцов. Для некоторых типов столбцов можно индексировать префиксы значений столбцов (см. раздел 6.4.3). Составные индексы можно рассматривать как отсортированные массивы, которые содержат значения, составленные из нескольких индексированных столбцов. MySQL использует составные индексы таким образом, что выполнение запросов ускоряется, когда вы указываете известное количество первых столбцов ключа индекса в конструкции WHERE, даже если не указываете значений других столбцов. Предположим, что таблица имеет следующее определение: CREATE TABLE t e s t ( i d INT NOT NULL, l a s t _ n a m e CHAR(30) NOT NULL, f i r s t _ n a m e CHAR(30) NOT NULL, PRIMARY KEY ( i d ) , INDEX name ( l a s t _ n a m e , f i r s t _ n a m e ) ) ;
Индекс name построен на основе значений столбцов last_name и first_name. Этот индекс может быть использован при выполнении запросов, для которых указаны значения lastname в заданном диапазоне, или значения обеих столбцов - и first_name, и last name. Таким образом, индекс name будет задействован при выполнении следующих запросов: SELECT * FROM t e s t WHERE last_name='Widenius'; SELECT * FROM t e s t WHERE l a s t name='Widenius' AND f i r s t name='Michael';
438
Глава 6. Оптимизация MySQL
SELECT * FROM test WHERE last_name='Widenius' AND (first_name='Michael' OR first_name='Monty1); SELECT * FROM test WHERE last_name='Widenius' AND first_name >='M' AND first_name < 'N f ; Однако индекс name не будет использован при выполнении таких запросов: SELECT * FROM test WHERE first_name='Michael•; SELECT * FROM test WHERE last_name='Widenius' OR first_name='Michael'; Манера, в которой MySQL использует индексы для повышения производительности запросов, обсуждается в следующем разделе.
6.4.5. Как MySQL использует индексы Индексы предназначены для быстрого поиска строк с определенным значением столбцов. Без индексов при поиске MySQL должен начать с первой записи и затем читать полностью всю таблицу, чтобы найти записи, удовлетворяющие запросу. Чем больше таблица, тем дороже это обходится. Если у таблицы есть индекс для столбца, указанного в запросе, MySQL может быстро определить позицию местонахождения нужной записи в середине файла данных, без необходимости просматривать все данные подряд. Если таблица содержит 1000 записей, то поиск по индексу будет, по крайней мере, в 100 раз быстрее, чем последовательное чтение. Имейте в виду, что если вам нужно просмотреть почти все 1000 строк, то лучше читать их последовательно, потому что это минимизирует количество обращений к диску. Большинство индексов MySQL (PRIMARY KEY, UNIQUE, INDEX и FULLTEXT) хранятся в В-деревьях. Исключение составляют индексы на столбцах пространственных типов, использующие R-деревья, и хеш-индексы таблиц типа MEMORY (HEAP). Строки автоматически сжимаются удалением ведущих и завершающих пробелов. Обычно индексы используются так, как описано выше. Специфичные для хешиндексов характеристики описаны в конце настоящего раздела. Итак, индексы используются для того, чтобы: • Быстро находить строки, удовлетворяющие условию WHERE. • Исключать из рассмотрения лишние строки. Если существует выбор между несколькими индексами, MySQL использует тот, что находит минимальное количество строк. • Извлекать строки из других таблиц при выполнении соединений. • Находить значения MIN () и МАХ () для специфичного проиндексированного столбца ключевой_столбец. Это оптимизируется препроцессором, проверяющим, используется ли в конструкции WHERE выражение часть_ключа#=константа по всем частям индекса, предшествующим ключевой_столбец в индексе. В этом случае MySQL выполняет один поиск ключа для каждого выражения MIN () и МАХ () и заменяет их константами. Если все выражения заменены константами, запрос возвратит управление сразу, например: SELECT MIN (часть_ключа2), МАХ (часть_ключа2) FROM имя таблицы WHERE часть ключа 1-10;
6.4. Оптимизация структуры базы данных
439
•
Сортировать группу в таблице, если сортировка или группировка выполняется по левому префиксу используемого ключа (например, ORDER BY часть ключа 1, часть_ключа2). Если все части ключа имеют следующее за ними слово DESC, ключ читается в обратном порядке. См. раздел 6.2.9.
•
В некоторых случаях запрос может быть оптимизирован так, чтобы извлекать значения, не обращаясь к строкам данных. Если запрос использует только числовые столбцы, которые формируют левый префикс некоторого ключа, извлекаемые значения могут быть получены для повышения скорости только из дерева индекса: SELECT часть_ключаЗ FROM имя_таблицы WHERE часть_ключа!=1
Предположим, что вводится следующий оператор SELECT: mysql> SELECT * FROM имя_таблицы WHERE столбец1=значение1
AND
столбец2=значение2;
Если существует составной индекс по столбец! и столбец2, соответствующие строки могут быть извлечены непосредственно. Если существуют отдельные индексы по столбцам столбец1 и столбец2, оптимизатор пытается найти самый узко ограничивающий индекс, принимая решение на основании того, какой из них возвратит меньше строк, и использует его. Если таблица имеет составной индекс, любой левосторонний префикс ключа может быть использован оптимизатором для поиска строк. Например, если существует индекс с ключом, составленным из трех столбцов (столбец!, столбец2, столбецЗ), то индексный поиск может выполняться по (столбец!), (столбец!, столбец2) или же по (столбец!, столбец2, столбецЗ). MySQL не может использовать индекс, если поисковые столбцы не составляют левую часть списка столбцов составного индекса. Предположим, у вас есть следующие операторы SELECT: SELECT * FROM имя_таблицы WHERE столбец!^значение!; SELECT * FROM имя_таблицы WHERE столбец2=значение2; SELECT * FROM имя_таблицы WHERE столбец2=значение2 AND столбецЗ=значениеЗ; Если существует индекс на (столбец!, столбец2, столбецЗ), только первый из приведенных запросов сможет его использовать для поиска. Второй и третий запросы в конструкции WHERE содержат входящие в индекс столбцы, но они не являются левосторонним префиксом списка столбцов, образующих этот ключ. Индекс используется для столбцов, которые сравниваются с помощью операций =, >, >=, CACHE INDEX t l , t 2 , t3 IN hot_cache;
I Table
| Op + + I test.tl | assign_to_keycache I test.t2 | assign_to_keycache I test.t3 | assign_to_keycache + +
I Msg_type + | status | status | status +
| Msg_text + | OK | OK | OK +
| + | | | +
На заметку! Если сборка сервера выполнялась с включенным механизмом хранения ISAM, то таблицы ISAM используют механизм кэша ключей. Однако индексы ISAM используют только кэш ключей по умолчанию и не могут быть переназначены на использование другого кэша.
6.4. Оптимизация структуры базы данных
443
Кэш ключей, указываемый в операторе CACHE INDEX, может быть создан путем установки его размера в параметре SET GLOBAL или с помощью опций запуска сервера. Например: mysql> SET GLOBAL keycachel.keyjDuffer_size=128*1024; Чтобы уничтожить кэш ключей, установите его размер в 0: mysql> SET GLOBAL
keycachel.key_buffer_size=O;
Переменные кэшей ключей - это структурные системные переменные, которые имеют имя и компоненты. Для keycachel.key_buffer_size, keycachel - имя переменной кэша, a key_buf fer_size - компонент кэша. По умолчанию индексы таблиц назначаются главному (по умолчанию) кэшу, который создается при запуске сервера. Когда какой-то кэш ключей разрушен, все назначенные ему индексы переназначаются на главный кэш. Для нагруженного сервера мы рекомендуем стратегию с использованием трех кэшей ключей: • "Горячий" (hot) кэш ключей, который занимает до 20% пространства, отведенного всем кэшам ключей. Он используется для таблиц, которые интенсивно задействуются для поиска, но редко обновляются. • "Холодный" (cold) кэш ключей, который занимает до 20% пространства, отведенного всем кэшам ключей. Используется для интенсивно обновляемых таблиц средних размеров, таких как временные таблицы. • "Теплый" (warm) кэш ключей, который занимает до 60% пространства, отведенного всем кэшам ключей. Это кэш ключей, используемый по умолчанию всеми остальными таблицами. Одной из причин для применения трех кэшей ключей является выгода от того, что обращение к одной структуре кэша не блокирует доступа к другим. Очереди, работающие с таблицами, назначенными одному кэшу ключей, не конкурируют с очередями, работающими с таблицами, назначенными другому кэшу. Выигрыш в производительности связан и с другими причинами: • Горячий кэш используется только для запросов чтения, поэтому его содержимое никогда не модифицируется. Следовательно, всякий раз, когда нужно получить индексный блок с диска, содержимое блока кэша, выбранного для замены, не нужно сбрасывать на диск. • Для индексов, назначенных этому кэшу, если нет запросов, требующих сканирования индекса, существует высокая вероятность того, что индексные блоки, соответствующие промежуточным узлам индексного В-дерева, останутся в кэше. • Операции обновления, в основном проводимые во временных таблицах, выполняются гораздо быстрее, если обновляемый узел уже находится в кэше и не требуется его считывать с диска. Если размер индексов временных таблиц сопоставим с размером холодного кэша ключей, очень высока вероятность того, что обновляемый узел уже находится в кэше. 6.4.6.3. Стратегия центральной точки По умолчанию система управления кэшами ключей MySQL 4.1 использует стратегию LRU для выбора блока кэша, подлежащего вытеснению, но она также поддерживает и более изощренный метод, называемый "стратегией центральной точки".
Глава 6. Оптимизация MySQL
444
Когда используется эта стратегия, цепочка LRU делится на две части: "горячую" подцепочку и "теплую" подцепочку. Точка раздела между ними не фиксирована, система управления кэшем ключей заботится о том, чтобы "теплая" часть не становилась слишком короткой, а всегда содержала как минимум key_cache_division_limit процентов блоков. key_cache_division_limit - это компонент структурированной переменной кэша ключей, поэтому его значение - это параметр, который устанавливается для каждого кэша. Когда индексный блок читается из таблицы в кэш ключей, он помещается в конец "теплой" подцепочки. После определенного количества попаданий (доступов к блоку) он перемещается в "горячую" подцепочку. В настоящее время количество попаданий, необходимых для этого, одинаково для всех индексных блоков. В будущем мы сделаем счетчик попаданий зависимым от уровня узла соответствующего блока в В-дереве индекса. Для узлов, находящихся ближе к корню дерева, потребуется меньше попаданий, чем для узлов-листьев. Блок, выбранный для переноса в "горячую" подцепочку, помещается в ее конец. Этот блок затем циркулирует внутри подцепочки. Если блок остается в начале подцепочки в течение достаточно длительного времени, он вытесняется в "теплую" часть. Время, необходимое для этого, определяется компонентом key_cache_age_threshold кэша ключей. Пороговое значение, предписывающее это, вычисляется так: для кэша ключей, содержащего N блоков, блок, находящийся в начале "горячей" подцепочки, к которому не осуществлялся доступ в течение N*key_cache_age_threshold/100 попаданий, должен быть перемещен в начало "теплой" подцепочки. Затем он становится первым кандидатом на вытеснение, потому что блоки, подлежащие замене, всегда выбираются в начале "теплой" подцепочки кэша. Стратегия центральной точки помогает увеличить производительность при выполнении запроса, который требует сканирования индексов и эффективно вытесняет из кэша все индексные блоки, содержащие высокоуровневые узлы В-дерева. Чтобы избежать этого, нужно использовать стратегию вставки центральной точки со значением key_cache_division_limit, установленным менее 100. Полезные узлы с частыми попаданиями будут сохранены в "горячей" подцепочке при сканировании индексов. 6.4.6.4. Предварительная загрузка индексов Если в кэше ключей достаточно блоков, чтобы поместить туда весь индекс целиком, или хотя бы блоки, представляющие нелистовые узлы, имеет смысл загрузить его предварительно в кэш ключей, прежде чем начать использовать. Предварительная загрузка позволит вам поместить индексные блоки в кэш наиболее эффективным способом: последовательным чтением индексных блоков. Без предварительной загрузки блоки также будут помещаться в кэш ключей, как это потребуется запросам. Но, несмотря на то, что блоки будут оставаться в кэше, так как там достаточно места для них всех, все же они будут извлекаться из индекса в случайном порядке, а не последовательно. Чтобы предварительно загрузить индекс в кэш, используйте оператор LOAD INDEX INTO CACHE. Например, следующий оператор предварительно загружает узлы (блоки) индексов таблиц t l и t2: mysql> LOAD INDEX INTO CACHE t l , t2 IGNORE LEAVES; Table
| Op
| Msg_type | Msg text
6.4. Оптимизация структуры базы данных
I test.tl I preload_keys | status I test.t2 I preload_keys | status + + +
445
| OK | OK +
| | +
Модификатор IGNORE LEAVES вынуждает предварительно загружать только блоки индекса, не являющиеся листьями. Поэтому приведенный выше оператор загружает все блоки индексов t l , но только нелистовые блоки t2. Если индекс назначается кэшу ключей с помощью оператора CACHE INDEX, предварительная загрузка помещает блоки индекса в этот кэш. Иначе индекс загружается в кэш по умолчанию. 6.4.6.5. Размер блока кэша ключей В MySQL 4.1 введена новая переменная key_cache_block_size, своя для каждого кэша. Она определяет размер блоков буферов кэша ключей, и предназначена для настройки производительности операций ввода-вывода для индексных файлов. Наилучшая производительность операций ввода-вывода достигается, когда размер буферов чтения равен размеру буферов ввода-вывода операционной системы. Однако установка размера ключевых узлов равной размеру буфера ввода-вывода не всегда гарантирует наилучшую производительность в итоге. При чтении больших узлов-листьев сервер вытаскивает много ненужных данных, эффективно препятствуя чтению других узлов. В настоящий момент вы не можете управлять размером индексных блоков таблицы. Этот размер устанавливается сервером при создании индексного файла .MYI, в зависимости от размера ключа индекса, заданного в определении таблицы. В большинстве случаев он устанавливается равным размеру буфера ввода-вывода. В будущем это будет изменено, и переменная key_cache_block_size будет полностью задействована. 6.4.6.6. Реструктуризация кэша ключей Кэш ключей может быть реструктурирован в любой момент путем обновления его параметров, например: mysql> SET GLOBAL cold__cache.key__buffer_size=4*1024*1024; Если присвоить новое значение компонентам кэша key_buffer_size или key_cache_block_size, то сервер разрушит старую структуру кэша ключей и создаст новую - на базе новых значений параметров. Если кэш содержит "измененные" блоки, сервер сохранит их на диске прежде, чем разрушить и пересоздать кэш. Реструктуризация не производится при изменении других параметров кэша. При реструктуризации кэша ключей сервер первым делом сбрасывает содержимое "измененных" блоков на диск. После этого содержимое кэша становится недоступным. Однако при этом не блокируются запросы, которым нужны индексы, назначенные кэшу. Вместо этого сервер напрямую обращается к табличным индексам, используя только встроенное кэширование файловой системы. Кэширование файловой системы не настолько эффективно, как кэши ключей, поэтому, хотя запросы и выполняются, может ощущаться замедление. Как только кэш реструктурирован, он снова становится доступным, и запросы снова используют его вместо механизма кэширования файловой системы.
446
Глава 6. Оптимизация MySQL
6.4.7. Как MySQL подсчитывает открытые таблицы Когда вы запускаете команду mysqladmin status, то видите нечто вроде следующего: Uptime: 426 Running threads: 1 Questions: 11082 Reloads: 1 Open tables: 12 Значение Open tables (Отрытые таблицы), равное 12, может несколько озадачить, если у вас всего шесть таблиц. MySQL - система многопоточная, поэтому может оказаться, что множество клиентов выполняют запросы к одной и той же таблице параллельно. Чтобы минимизировать проблемы со многими клиентскими потоками, имеющими разное состояние в одном и том же файле, таблица открывается независимо каждым параллельным потоком. Это требует некоторых затрат памяти, но обычно увеличивает производительность. Для таблиц My ISAM необходим один дополнительный файловый дескриптор на файл данных для каждого клиента, который его открывает. (В отличие от этого, дескриптор индексного файла совместно используется несколькими потоками.) Механизм хранения ISAM работает так же. Более подробно об этом можно прочитать в следующем разделе.
6.4.8. Как MySQL открывает и закрывает таблицы Системные переменные table_cache, max_connections и max_tmp_tables влияют на максимальное количество файлов, которые сервер может держать открытыми. Если вы увеличите одно или более из этих значений, то можете столкнуться с ограничением, накладываемым операционной системой на количество дескрипторов файлов, которые может открывать один процесс. Многие операционные системы позволяют увеличивать лимит открытых файлов, хотя способы могут варьироваться от системы к системе. Обратитесь к документации по операционной системе, чтобы узнать, можно ли увеличить этот предел, и как это сделать. table_cache связано с max_connections. Например, при 200 активных параллельных соединениях вам нужно иметь табличный кэш размером, по меньшей мере, 200 * А/, где N - максимальное количество таблиц в соединении. Также нужно зарезервировать некоторое число файловых дескрипторов для временных таблиц и файлов. Убедитесь, что ваша операционная система может обслуживать достаточное количество открытых файловых дескрипторов, указанное в установке table_cache. Если установлено слишком большое значение table_cache, MySQL может превысить максимально возможное количество дескрипторов и отвергать соединения, отказывать в обслуживании запросов и работать весьма ненадежно. Надо также принять во внимание, что механизм хранения My ISAM нуждается в дополнительных двух дескрипторах для каждой уникальной открытой таблицы. Вы можете увеличить количество доступных файловых дескрипторов для MySQL, с помощью опции запуска mysqld —open-files-limit. См. раздел А.2.17. Кэш открытых таблиц будет сохраняться на уровне table_cache позиций. Значение по умолчанию равно 64 и может быть изменено опцией mysqld —table_cache. Помните, что MySQL может открывать даже больше таблиц для обслуживания запросов. Неиспользуемые таблицы закрываются и удаляются из табличного кэша при следующих условиях:
6.4. Оптимизация структуры базы данных
447
• Когда кэш полон и поток пытается открыть таблицу, которая еще не содержится в кэше. • Когда кэш содержит больше, чем table_cache позиций, и поток больше не использует таблицу. • Когда выполняется операция сброса таблицы. Это происходит, если кто-то выполняет оператор FLUSH TABLES либо выдает команду mysqladmin flush-tables или mysqladmin refresh. Когда табличный кэш наполняется, сервер использует следующую процедуру, чтобы найти позицию в кэше для использования: • Таблицы, которые в данный момент не используются, освобождаются в порядке последнего обращения. • Если требуется открыть новую таблицу, но кэш полон и никакая из таблиц не может быть освобождена, кэш временно расширяется. Когда кэш временно расширен, и таблица переходит в состояние неиспользуемой, она закрывается и освобождается из кэша. Таблица открывается для каждого параллельного доступа. Это означает, что она должна быть открыта дважды, если потоки обращаются к одной и той же таблице, или один поток обращается к таблице дважды в одном запросе (например, выполняя соединение таблицы с нею самой). Каждое конкурирующее открытие требует позиции в табличном кэше. Первое открытие любой таблицы занимает два файловых дескриптора: один для файла данных и один для индексного файла. Каждое дополнительное использование таблицы требует только одного файлового дескриптора - для файла данных. Дескриптор индексного файла используется потоками совместно. Если вы открываете таблицу оператором HANDLER имя_таблицы OPEN, то выделенный табличный объект распределяется для потока. Этот табличный объект не разделяется другими потоками и не закрывается до тех пор, пока поток не выполнит оператор HANDLER имя_таблицы CLOSE, или же его выполнение прервется. Когда это случится, таблица перемещается назад в табличном кэше (если он не полон). Вы можете определить, что ваш табличный кэш маловат, проверив переменную состояния mysqld с именем Opened_tables: mysql> SHOW STATUS LIKE 'Opened_tables';
| Variable_name | Value | + + + | Opened_tables | 2741 | + + + Если значение достаточно велико, даже если вы не выполняли FLUSH TABLES, вам стоит увеличить размер табличного кэша. См. разделы 4.2.3 и 4.2.4.
6.49. Недостатки создания множества таблиц в одной базе данных Если у вас много таблиц My ISAM или ISAM в каталоге базы данных, то операции создания, открытия и закрытия таблиц могут быть медленными. Если вы выполняете оператор SELECT на множестве различных таблиц, будут иметь место некоторые накладные расходы, когда табличный кэш полон, потому что для каждой таблицы, которая должна
448
Глава 6. Оптимизация MySQL
быть открыта, другая должна быть закрыта. Вы можете снизить эти накладные расходы, увеличив размер табличного кэша.
6.5. Оптимизация сервера MySQL 6.5.1. Настройка параметров системы и запуска Начнем с факторов уровня системы, поскольку некоторые из этих решений могут быть приняты на ранних этапах, чтобы достичь существенного выигрыша в производительности. В других случаях беглого просмотра настоящего раздела может быть достаточно. Однако все же неплохо знать, что можно выиграть за счет изменений, вносимых в настройки на этом уровне. Выбор операционной системы, используемой по умолчанию, чрезвычайно важен! Чтобы наилучшим образом использовать многопроцессорные машины, вы должны использовать Solaris (потому что реализация потоков в ней работает действительно хорошо) или Linux (поскольку ядро 2.2 обладает хорошей поддержкой симметричных многопроцессорных вычислений). Помните, что старые ядра Linux имели ограничение на размер файла в 2 Гбайт по умолчанию. Если у вас такое ядро и есть настоятельная необходимость работать с файлами больше 2 Гбайт, вам следует установить исправление Large File Support (LFS) для файловой системы ext2. Другие файловые системы, такие как ReiserFS или XFS, не имеют ограничений в 2 Гбайт. Прежде чем вводить MySQL в производственную эксплуатацию, мы советуем протестировать существующую платформу. Ниже представлены другие советы. • Если у вас достаточно оперативной памяти, можете удалить все устройства подкачки. Некоторые операционные системы используют устройства подкачки в некоторых контекстах, даже если оперативной памяти достаточно. • Используйте опцию MySQL —skip-external-locking для исключения внешних блокировок. Эта опция в MySQL 4.0 включена по умолчанию. Для предшествующих версий она выключалась по умолчанию только с MIT-pthreads, потому что вызов flock () не полностью поддерживается пакетом MIT-pthreads на всех платформах. Это также включено по умолчанию в Linux, так как файловая блокировка Linux пока недостаточно безопасна. Имейте в виду, что опция —skip-externallocking не затрагивает функциональности MySQL до тех пор, пока вы запускаете на машине только один сервер. Просто помните, что надо остановить сервер (или заблокировать и сбросить соответствующие таблицы) перед запуском myisamchk. На некоторых системах эта опция обязательна, поскольку внешняя блокировка в любом случае не работает. Единственный случай, когда вы не можете использовать —skip-externallocking, это если вы запускаете несколько экземпляров сервера MySQL (а не клиента) для работы с одними и теми же данными, или если вы запускаете myisamchk для проверки (но не восстановления) таблицы, не указывая серверу предварительно сбросить и заблокировать эту таблицу. Вы можете по-прежнему применять LOCK TABLES/UNLOCK TABLES, даже если используется —skip-external-locking.
449
6.5. Оптимизация сервера MySQL
6.5.2. Настройка параметров сервера Вы можете определить размеры буферов по умолчанию, которые будет использовать сервер mysqld, следующей командой (для версий до MySQL 4.1 опустите —verbose): shell> mysqld —verbose --help Эта команда генерирует список всех опций mysqld и конфигурируемых системных переменных. Этот список включает также значения по умолчанию и выглядит примерно так: back log bdb_cache_size binlog_cache_size connect timeout delayed insert limit delayed insert timeout delayed_queue_size flush time interactive timeout join buffer size key buffer size long_query_time lower case table names max_allowed_packet max binlog cache size max connect errors max connections max delayed threads max heap table size max join size max_sort_length max tmp tables max write lock count myisam sort buffer size net buffer length net read timeout net retry count net write timeout read_buffer_size read_rnd_buffer_size slow launch time sort buffer table cache thread concurrency thread stack tmp table size wait timeout
current current current current current current current current current current current current current current current current current current current current current current current current current current current current current current current current current current current current current
value: value: value: value: value: value: value: value: value: value: value: value: value: value: value: value: value: value: value: value: value: value: value: value: value: value: value: value: value: value: value: value: value: value: value: value: value:
5 1048540 32768 5 100 300 1000 0 28800 131072 1048540 10 0 1048576 4294967295 10 100 20 16777216 4294967295 1024 32 4294967295 8388608 16384 30 10 60 131072 262144 2 2097116 64 10 131072 1048576 28800
Если в настоящий момент есть запущенный сервер mysqld, вы можете увидеть, какие значения системных переменных в нем установлены, подключившись к нему и выполнив оператор: mysql> SHOW VARIABLES;
450
Глава 6. Оптимизация MySQL
Вы также можете увидеть некоторые статистические и относящиеся к состоянию показатели работающего сервера, выполнив следующее: mysql> SHOW STATUS; Системные переменные и информацию о состоянии можно также получить, используя mysqladmin: shell> mysqladmin variables shell> mysqladmin extended-status Полное описание всех системных переменных и переменных состояния приведено в разделах 4.2.3 и 4.2.4. MySQL использует алгоритмы, которые очень хорошо масштабируются, поэтому вы обычно можете запускать его, имея очень мало памяти. Однако, обычно, более высокая производительность MySQL достигается предоставлением ему большего объема памяти. При настройке сервера MySQL две наиболее важные переменные - это k e y b u f f e r s i z e и tablecache. Прежде чем пытаться изменять значение других переменных, вы должны быть уверены в том, что значение этих двух установлено правильно. Следующие примеры показывают некоторые типичные значения переменных для различных конфигураций времени исполнения. В этих примерах используется сценарий mysqld_safe и синтаксис —имя_переменной= значение для установки значения переменной имя_переменной в значение значение. Этот синтаксис принят в MySQL, начиная с версии 4.0. При использовании более старых версий, примите во внимание следующие моменты: •
Используйте safejnysqld вместо raysqld_safe.
• Устанавливайте переменные с использованием синтаксиса --set-variable= имя_переменной= значение или -0 имя_переменной= значение. •
Переменные, у которых имя оканчивается на _size, возможно, придется специфицировать без _size. Например, старое имя sort__buffer_size выглядело как sort_buffer. Старым именем для read_buffer_size было sort_buffer. Чтобы увидеть, какие имена переменных распознает ваш сервер, выдайте команду mysqld —help.
Если у вас есть, как минимум, 256 Мбайт памяти, много таблиц, и вы хотите получить максимум производительности при небольшом количестве клиентов, вы должны использовать примерно следующее: shell> mysqld_safe —key_buffer_size=64M —table_cache=256 \ --sort_buffer_size=4M — read_buffer_size=lM & Если у вас только 128 Мбайт памяти и всего несколько таблиц, но вам требуется выполнять большие объемы сортировки, можно использовать что-то вроде этого: shell> mysqld_safe —key_buffer_size=16M —sort_buffer_size=lM Если выполняется очень много одновременных подключений, проблемы подкачки могут возникнуть независимо от того, что mysqld был сконфигурирован на использование малого объема памяти для каждого соединения, mysqld работает лучше, если у вас достаточно памяти для всех соединений. Когда мало памяти и много соединений, попробуйте что-то вроде этого: shell> mysqld_safe --key_buffer_size=512K —sort_buffer_size=100K \ —read buffer size=100K &
6.5. Оптимизация сервера MySQL
451
или даже этого: shell> mysqldjsafe --key_buffer_size=512K —sortJbuffer_size=16K \ —table_cache=32 —read_buffer_size=8K \ —netJbuffer_length=lK & Если вы выполняете операции GROUP BY или ORDER BY на таблицах, размер которых значительно превышает объем доступной памяти, то должны увеличить значение read_rnd_buf f e r s i z e для повышения скорости чтения строк после операций сортировки. После установки MySQL в каталоге support-files содержатся некоторые примеры файла my.cnf, а именно: my-huge.cnf, my-large.cnf, my-medium.cnf и my-small.cnf. Вы можете использовать эти файлы в качестве базы при оптимизации вашей системы. Имейте в виду, что если опции указываются в командной строке mysqld или mysqld_safe, они остаются в силе только на текущий запуск сервера. Чтобы использовать опции при каждом запуске, поместите их в файл настроек. Чтобы увидеть эффект от изменения параметров, выполните следующую команду (для версий, предшествующих MySQL 4.1, не указывайте —verbose): shell> mysqld —keyJbuffer_size=32M —verbose —help Значения переменных перечислены в конце вывода. Убедитесь, что опции —verbose и —help идут последними. В противном случае все опции, указанные после них, не окажут влияния на вывод. Информацию о настройке механизма хранения InnoDB можно найти в разделе 9.12.
6.5.3. Как компиляция и компоновка влияют на скорость MySQL Большинство следующих тестов производительности выполнялись под Linux, но они должны дать определенное представление о работе и в других операционных системах и рабочих окружениях. Самые быстрые исполняемые программы получаются, если применять статическую компоновку, указывая - s t a t i c . В Linux вы получите самый быстрый код, если скомпилируете с помощью рдсс и -03. Понадобится около 200 Мбайт памяти для компиляции с этой опцией файла sql_yacc. ее, потому что для gcc/pgcc требуется много памяти, чтобы сделать все функции встроенными. Вы также должны установить СХХ=дсс перед компиляцией MySQL, чтобы избежать включения библиотеки libstdc++, которая не нужна. Помните, что с некоторыми версиями рдсс результирующий код будет работать только с истинными процессорами Pentium, даже если вы используете опции компилятора, указывающие на необходимость генерации кода, совместимого со всеми процессорами семейства х586 (такими как AMD). Используя лучший компилятор и лучший набор опций, вы можете получить 10-30 % рост производительности приложения. В частности, это так же верно при компиляции самого сервера MySQL. Мы тестировали компиляторы Су gnus CodeFusion и Fujitsu, но когда мы это делали, ни один из них не был настолько свободен от ошибок, чтобы позволить скомпилировать MySQL с включенной оптимизацией. Стандартные бинарные дистрибутивы MySQL компилируются с поддержкой всех наборов символов. Когда вы компилируете его самостоятельно, вы можете включить
452
Глава 6. Оптимизация MySQL
поддержку только необходимых вам наборов символов. Это управляется опцией —withcharset сценария configure. Ниже приведен список некоторых замеров, которые мы сделали: • Если применяется компилятор рдсс и все компилируется с опцией -Об, mysqld работает на 1% быстрее, чем при использовании дсс 2.95.2. • Если применяется динамическая компоновка (без -static), результат под Linux на 13% медленнее. Помните, что вы можете использовать динамические библиотеки MySQL для клиентских приложений. Вышесказанное касается сервера, для которого производительность критична. • Если вы удаляете отладочную информацию из бинарного кода командой s t r i p mysqld, результирующий код может стать на 4% быстрее. • Для подключения клиента к серверу, запущенному на том же хосте, если вы подключаетесь по TCP/IP вместо сокетов Unix, производительность получается на 7,5% медленнее. (В Unix, если вы подключаетесь, указывая имя хоста localhost, MySQL использует файлы сокетов по умолчанию). • Подключение по TCP/IP к удаленному серверу, находящемуся на другом хосте, на 8-11% медленнее, чем подключение к локальному серверу, на том же хосте, даже если применяется сетевой интерфейс Ethernet 100 Мбит/с. • При запуске нашего набора тестов производительности по защищенному соединению (когда все данные шифруются внутренней поддержкой SSL), производительность получается на 55% ниже, чем по незащищенному соединению. • Если вы компилируете с —with-debug=full, большинство запросов будут выполняться на 20% медленнее. Некоторые запросы могут потребовать значительно большего времени. Например, тесты производительности MySQL выполняются на 35% медленнее. Если вы используете —with-debug (без =full), замедление составит только 15%. Для версии mysqld, скомпилированной с —with-debug=full, вы можете выключить проверку памяти во время выполнения, запустив его с опцией —skip-safemalloc. Конечный результат в этом случае будет близким к тому, что получается при конфигурировании компиляции с --with-debug. • На машине Sun UltraSPARC-lie сервер, скомпилированный Forte 5.0, работает на 4% быстрее, чем собранный с помощью gcc 3.2. • На Sun UltraSPARC-He сервер, скомпилированный Forte 5.0, работает на 4% быстрее в 32-разрядном режиме, чем в 64-разрядном. • Компиляция с помощью дсс 2.95.2 для UltraSPARC с опциями -mcpu=v8 -Wa, -xarch=v8plusa дает на 4% более высокую производительность. • В Solaris 2.5.1 на однопроцессорной машине с пакетом MIT-pthreads MySQL работает на 8-12% медленнее, чем со встроенной поддержкой потоков Solaris. При большей загрузке процессора разница будет еще больше. • Компиляция в Linux-x86 с использованием компилятора дсс без указателей фреймов (-fomit-frame-pointer или -fomit-frame-pointer -ffixed-ebp) делает mysqld на 1-4% быстрее. Бинарный дистрибутив MySQL для Linux, который поставляется компанией MySQL АВ, скомпилирован рдсс. Мы собираемся вернуться обратно к дсс из-за ошибки в рдсс,
6.5. Оптимизация сервера MySQL
453
которая приводит к невозможности генерации кода для процессоров AMD. Мы продолжим использовать дсс до тех пор, пока ошибка не будет устранена. Между тем, если у вас машина с процессором, отличным от AMD, вы можете получить более быстрый код, компилируя с помощью рдсс. Стандартный бинарный дистрибутив MySQL для Linux компонуется статически, чтобы сделать его быстрее и более переносимым.
6.5.4. Как MySQL использует память В следующем списке представлены способы, по которым сервер mysqld использует память. Где это применимо, имя системной переменной существенно для использования памяти, которого она касается. •
Буфер ключей (переменная key_buffer_size) раздельно используется всеми потоками, другие буферы, используемые сервером, выделяются по мере необходимости. См. раздел 6.5.2.
• Каждое подключение использует некоторое специфичное для потока пространство: •
Стек (по умолчанию 64 Кбайт, переменная thread_stack).
•
Буфер подключения (переменная net_buf f er_length).
• Буфер результата (переменная result_buf fer_length). Буфер подключения и буфер результата динамически увеличиваются при необходимости, вплоть до max_allowed_packet. Пока выполняется запрос, копия текущей строки запроса также распределяется в памяти. • Все потоки разделяют одну базовую память. • Только сжатые таблицы ISAM и MylSAM отображаются в память. Это связано с тем, что 32-разрядное пространство памяти в 4 Гбайт недостаточно для большинства крупных таблиц. Когда системы с 64-разрядным адресным пространством станут более распространенными, возможно, мы добавим общую поддержку отображения памяти. • Каждый запрос, который выполняет последовательное сканирование таблицы, распределяет буфер чтения (переменная read_rnd_buf fer_size). • Все соединения выполняются за один проход, и большинство соединений могут быть сделаны даже без использования временной таблицы. Большинство временных таблиц размещаются в памяти (memory-based, HEАР-tables). Временные таблицы с большой длинной записи (вычисляемой как сумма длин столбцов) либо содержащие столбцы типа BLOB сохраняются на диске. Одна проблема, которая имела место до MySQL 3.23.2, состояла в том, что внутренние таблицы, размещенные в памяти, превышали по размеру tmp_table_size, что приводило к ошибке "The t a b l e имя^таблицы is f u l l " ("Таблица имя_пгаблщы переполнена"). Начиная с версии 3.23.2, эта ситуация обрабатывается автоматически, путем замены таблицы в памяти на таблицу My ISAM на диске. Для того чтобы обойти эту проблему в более старых версиях сервера, можно увеличить размер временной таблицы, установив опцию tmp_table_size для mysqld или установив SQL-опцию SQLBIGTABLES в клиентской программе. В MySQL 3.20 максимальный размер временной таблицы определяется как record_buffer * 16. Если вы используете эту версию, то должны увеличить значение record_buffer. Вы также можете запустить mysqld с опцией —big-tables,
454
Глава 6. Оптимизация MySQL
чтобы всегда сохранять временные таблицы на диске. Однако это скажется на скорости многих сложных запросов. • Большинство запросов, выполняющих сортировку, размещают буфер сортировки и от нуля до двух временных файлов, в зависимости от размера результирующего набора. См. раздел А.4.4. • Почти все анализы и вычисления выполняются в локальной памяти. Для мелких элементов каких-либо накладных расходов, связанных с памятью, не возникает, поэтому удается избежать обычного медленного выделения и освобождения памяти. Память выделяется только для неожиданно больших строк. Это делается вызовами malloc () и free (). • Для каждой открываемой таблицы My ISAM и ISAM индексный файл открывается один раз, а файл данных - один раз для каждого из параллельных потоков, которые обслуживают клиентские соединения. Для каждого параллельного потока выделяется память под структуру таблицы, структуры каждой из столбцов и буфер размером 2 * N (где N - максимальная длина строки, не считая столбцов BLOB). Столбец типа BLOB требует от пяти до восьми байт, плюс длина данных BLOB. Механизмы хранения ISAM и My ISAM поддерживают один дополнительный буфер строки для внутреннего использования. • Для каждой таблицы, содержащей столбец BLOB, буфер увеличивается динамически, чтобы читать большие значения BLOB. Если вы сканируете таблицу, размер буфера будет настолько большим, чтобы поместилось наибольшее значение BLOB. • Управляющие структуры для всех находящихся в использовании таблиц сохраняются в кэше и обрабатываются по алгоритму FIFO. По умолчанию кэш имеет 64 позиции. Если таблица используется двумя работающими потоками одновременно, кэш содержит две позиции для этой таблицы. См. раздел 6.4.8. • Оператор FLUSH TABLES или команда mysqladmin flush-tables закрывают все таблицы, которые не используются, и помечают к закрытию все используемые таблицы, когда работающие в настоящий момент потоки завершатся. Это эффективно освобождает большую часть используемой памяти. Программа ps и другие, показывающие состояние системы, могут сообщать, что mysqld использует много памяти. Это может быть вызвано стеками потоков на разных адресах памяти. Например, версия ps от Solaris считает неиспользуемую память между стеками как используемую. В этом можно убедиться, проверив размер доступного файла подкачки с помощью команды swap -s. Мы тестировали mysqld с использованием различных детекторов утечки памяти (как коммерческих, так и с открытым исходным кодом), поэтому утечек памяти там быть не должно.
6.5.5. Как MySQL использует DNS Когда новый клиент подключается к mysqld, он порождает новый поток, чтобы обслужить запрос. Этот поток первым делом проверяет, находится ли имя хоста в кэше имен хостов. Если нет, он пытается преобразовать имя хоста: • Если операционная система поддерживает безопасные к потокам вызовы gethostbyaddr_r () и gethostbyname_r (), то поток использует их для преобразования имени хоста.
6.6. Вопросы использования дисков
455
• Если эти вызовы не поддерживаются, поток блокирует семафор и вызывает вместо них gethostbyaddr () и gethostbyname (). В этом случае никакой другой поток не может преобразовывать имена хостов до тех пор, пока первый поток не разблокирует семафор. Вы можете отключить поиск имен хостов DNS, запустив сервер с опцией —skiphost-cache. Однако в этом случае вы сможете использовать только IP-адреса в таблицах привилегий MySQL. Если система DNS очень медленная, а хостов много, более высокой производительности можно добиться либо отключением поиска в DNS с помощью опции —skip-name-resolve, либо увеличением значения HOST_CACHE_SIZE (по умолчанию 128) и перекомпиляцией mysqld. Можно отключить кэш имен хостов, запустив сервер с опцией —skip-host-cache. Чтобы очистить кэш имен хостов, выполните оператор FLUSH HOSTS или команду mysqladmin flush-hosts. Если вы хотите полностью запретить подключения по TCP/IP, запустите mysqld с опцией —skip-networking.
6.6. Вопросы использования дисков • Доступ к диску - это серьезное узкое место в контексте производительности. Эта проблема становится более ощутимой по мере того, как объемы хранимых данных начинают расти, что приводит к тому, что становится невозможным эффективное кэширование. Для больших баз данных, в которых доступ осуществляется болееменее случайно, вы можете быть уверены, что вам нужна, по крайней мере, одна операция доступа к диску для чтения и несколько - для записи. Чтобы минимизировать эту проблему, используйте диски с малым временем доступа. • Увеличивайте количество доступных физических дисков (и, таким образом, снижайте нагрузку, связанную с позиционированием), либо вводя символические ссылки на файлы на других дисках, либо за счет применения чередования (разбиения на полосы) дисков: • Использование символических ссылок. Это означает, что для таблиц My ISAM файлы данных и/или индексов перемещаются на другой диск, а в каталоге их обычного расположения создаются символические ссылки, указывающие на их новое местоположение. Это улучшает время доступа и чтения, предполагая, что диск не используется для других целей. См. раздел 6.6.1. •
Чередование (разбиение на полосы). Чередование означает, что вы имеете много дисков и помещаете первый блок на первый диск, второй блок - на второй диск и N-H блок на N-й диск (N- общее количество дисков). Это означает, что если ваш нормальный размер данных меньше, чем размер полосы чередования (или абсолютно совпадает), то вы получите гораздо лучшую производительность. Этот метод очень зависит от операционной системы и ширины полосы чередования, поэтому протестируйте свое приложение с разными значениями ширины. См. раздел 6.1.5. Разница в скорости при чередовании очень зависит от параметров. В зависимости от того, как вы установите параметры чередования и количество дисков, вы можете получить сильно отличающиеся результаты. Для оптимизации вам нужно выбирать между случайным и последовательным доступом.
456
Глава 6. Оптимизация MySQL
• Для целей надежности может возникнуть желание использовать массив RAID 0+1 (чередование плюс зеркальное отображение), но в этом случае вам понадобится 2*N физических устройств, чтобы иметь N устройств для данных. Это, вероятно, наилучший выбор, если вы располагаете соответствующими финансовыми средствами. Однако вы можете также инвестировать их в программное обеспечение управления дисковыми томами, для повышения эффективности. • Хорошее решение - варьировать уровень RAID в соответствии с тем, насколько критичны данные. Например, разместите маловажные данные, которые можно регенерировать, на диск RAID 0, но сохраните действительно важные данные, такие как информация хоста и протоколы, на диске RAID 0+1 или RAID N. Применение RAID N может стать проблемой, если у вас много операций записи, из-за времени, необходимого для обновления битов четности. • В Linux вы можете получить намного более высокую производительность, используя hdparm для конфигурирования вашего дискового интерфейса (До 100% под нагрузкой не является чем-то необычным.) Следующие параметры hdparm должны быть достаточно хороши для MySQL и, предположительно, для многих других приложений: hdparm -m 16 -d 1 Помните, что производительность и надежность при использовании этой команды зависит от существующего оборудования, поэтому мы настоятельно советуем всесторонне протестировать систему после применения команды hdparm. Ознакомьтесь с man-страницами, посвященными hdparm, чтобы получить более подробную информацию. Если hdparm применять неосмотрительно, результатом может быть повреждение файловой системы, поэтому сделайте резервные копии перед тем, как будете экспериментировать! • Вы также можете установить параметры файловой системы, которую использует база данных: Если вам не нужно знать, когда осуществлялся доступ к файлам в последний раз (что на самом деле не очень-то нужно для сервера баз данных), вы можете смонтировать файловую систему с опцией -о noatime. Это позволит пропускать обновления последнего времени доступа в узлах inode файловой системы, что сократит количество обращений к диску. На многих операционных системах вы можете настроить асинхронное обновление файловой системы, монтируя ее с опцией -о async. Если ваш компьютер достаточно стабилен, это даст более высокую производительность, без необходимости приносить в жертву надежность. (Этот флаг в Linux применяется по умолчанию.)
6.6.1. Использование символических ссылок Вы можете перемещать таблицы и базы данных из каталога данных в другие места и заменять их символическими ссылками, указывающими на их новое местоположение. Потребность в этом может возникнуть, например, если необходимо переместить базу данных в файловую систему, в которой больше свободного места, или повысить скорость за счет разнесения таблиц по разным дискам. Рекомендуемый способ сделать это - просто установить символическую ссылку на базу данных на другом диске. Устанавливать символические ссылки на отдельные таблицы имеет смысл только в крайних случаях.
б.б. Вопросы использования дисков
457
6.6.1.1. Использование символических ссылок на базы данных в Unix В Unix для установки символической ссылки на базу данных первым делом надо создать каталог на некотором диске, где вы имеете достаточно свободного пространства, после чего создать символическую ссылку на этот каталог из каталога данных MySQL. shell> xnkdir /drl/databases/test shell> In -s /drl/databases/test /путь/к/'каталогу_данных MySQL не поддерживает ссылки одного каталога сразу на множество баз данных. Замена каталога данных на символическую ссылку работает хорошо до тех пор, пока вы не создаете ссылок между базами. Предположим, что у вас есть база данных dbl в каталоге данных MySQL, и вы создаете символическую ссылку db2, которая указывает на dbl: shell> cd /путь/к/'каталогу_данных shell> In -s dbl db2 Теперь для каждой таблицы t b l a в базе данных dbl появляется соответствующая таблица tbl_a в базе данных db2. Если один клиент обновляет dbl.tbl_a, а другой db2. tbl_a, возникнут проблемы. Если вам действительно нужно так сделать, вы можете изменить один из исходных файлов. Файл, который необходимо модифицировать, зависит от вашей версии MySQL. Для MySQL 4.0 и выше обратите внимание на следующий фрагмент кода в файле mysys/my_symlink.c: if (!(MyFlags & MY_RESOLVE_LINK) | | (ilstat(filename,&stat_buff) && S_ISLNK(stat_buff.stjnode))) Для версий MySQL, предшествующих 4.0, найдите в файле mysys/mf_format.c следующий фрагмент: if
(flag & 32 | |
(Ilstat(to,&stat_buff)
&& S_ISLNK(stat_buff.stjnode)))
В обоих случаях замените это на такой код: if (1) В Windows можно использовать внутренние символические ссылки на каталоги, скомпилировав MySQL с ключом -DUSESYMDIR. Это позволит размещать разные базы данных на разных дисках. См. раздел 6.6.3.1. 6.6.1.2. Использование символических ссылок на таблицы в Unix До версии MySQL 4.0 не рекомендовалось применять символические ссылки на таблицы, если только вы не проявляли исключительную аккуратность в отношении к ним. Проблема состояла в том, что если вы запускали ALTER TABLE, REPAIR TABLE или OIPTIMIZE TABLE на таблицах, доступ к которым осуществлялся через символические ссылки, эти ссылки удалялись и заменялись исходными файлами. Это происходило потому, что эти операторы работают, создавая временные файлы в каталоге данных и затем заменяя исходные файлы этими временными файлами по окончании работы. Вы не должны символически связывать таблицы в системах, которые не поддерживают полноценно работающего вызова realpath (). (По крайней мере, Linux и Solaris поддерживают realpath ().) Вы можете проверить, поддерживает ли ваша система символические ссылки, выполнив оператор SHOW VARIABLES LIKE 'have_symlink'. В версии MySQL 4.0 символические ссылки полноценно поддерживаются только для таблиц My ISAM. Для других типов таблиц вы, возможно, столкнетесь со странными про-
458
Глава 6. Оптимизация MySQL
блемами, если попытаетесь использовать символические ссылки на файлы в операционной системе с любым из приведенных ранее операторов. Управление символическими ссылками для таблиц My ISAM осуществляется следующим образом: • В каталоге данных у вас всегда есть файл определения таблиц, файл данных и индексный файл. Файл данных и индексный файл можно перемещать куда угодно и в каталоге данных подменять символическими ссылками. С другой стороны, файл определений - нельзя. • Вы можете устанавливать символические ссылки на файл данных и индексный файл в разные каталоги независимо друг от друга. • Установка символических ссылок может выполняться вручную из командной строки командой In -s, если mysqld не запущен. Посредством SQL вы можете известить сервер о необходимости установки символической ссылки, используя опции DATA DIRECTORY И INDEX DIRECTORY оператора CREATE TABLE. • myisamchk не заменяет символическую ссылку файлом данных или файлом индекса. Она работает непосредственно с файлом, на который указывает ссылка. Все временные файлы создаются в каталоге, где находятся файл данных или индексный файл. • Когда вы удаляете таблицу, которая использует символическую ссылку, уничтожается как ссылка, так и сам файл. Это серьезная причина для того, чтобы не запускать mysqld от имени root, или предоставлять пользователям право записи в каталоги данных MySQL. • Если вы переименовываете таблицу с помощью оператора ALTER TABLE... RENAME и не перемещаете таблицу в другой каталог, символические ссылки в каталоге данных переименовываются, а сами файлы данных и индексов переименовываются соответственно. • Если вы применяете ALTER TABLE... RENAME для перемещения таблицы в другую базу данных, таблица перемещается в другой каталог данных. Старые символические ссылки и файлы, на которые они указывают, удаляются. Другими словами, новая таблица не будет связана символической ссылкой. • Если вы не пользуетесь символическими ссылками, то должны применять опцию —skip-symbolic-links с mysqld, дабы гарантировать, что никто не сможет использовать mysqld для удаления или переименования файла вне каталога данных. Оператор SHOW CREATE TABLE не сообщал о том, что таблица имела символические ссылки, вплоть до версии MySQL 4.0.15. Это также верно для утилиты mysqldump, которая использовала SHOW CREATE TABLE для генерации оператора CREATE TABLE. Ниже перечислены операции над символическими ссылками таблиц, которые пока не поддерживаются: • ALTER TABLE игнорирует ОПЦИИ DATA DIRECTORY И INDEX DIRECTORY. • BACKUP TABLE и RESTORE TABLE не воспринимают символические ссылки. • Файл . f rm никогда не должен быть символической ссылкой (как уже упоминалось, только файлы данных и индексов могут быть символическими ссылками). Попытки сделать это (например, чтобы создать синонимы) приведет к некорректным результатам. Предположим, что у вас есть база dbl в каталоге данных
6.6. Вопросы использования дисков
459
MySQL, таблица t b l l в этой базе, а в каталоге dbl вы создаете символическую ссылку tbl2, указывающую на t b l l : shell> shell> shell> shell>
cd In In In
/путь/к/каталогу_данных/6Ы -s tbll.frm tbl2.frm -s tbll.MYD tbl2.MYD -s tbll.MYI tbl2.MYI
Если один поток читает d b l . t b l l , а другой обновляет dbl.tbl2, возникнут проблемы: • Кэш запросов будет сбит с толку (он будет считать, что таблица t b l l не обновлялась, поэтому вернет устаревший результат). • Операторы ALTER на таблице tbl2 также завершатся неудачей. 6.6.1.3. Использование символических ссылок на базы данных в Windows Начиная с MySQL 3.23.16, серверы mysqld-max и mysqld-max-nt для Windows компилируются с опцией -DUSESYMDIR. Это позволяет поместить каталог данных на другой диск, установив символическую ссылку на него. Это похоже на символические ссылки в Unix, хотя процедура их определения отличается. Начиная с версии MySQL 4.0, символические ссылки по умолчанию разрешены. Если они не нужны, можете отключить их поддержку в конфигурационном файле через опцию skip-symbolic-links: [mysqld] skip-symbolic-links До версии MySQL 4.0 символические ссылки были выключены по умолчанию. Чтобы включить их, потребуется поместить в конфигурационный файл my.cnf или my.ini следующие строки: [mysqld] symbolic-links В среде Windows вы создаете символическую ссылку на базу данных MySQL, создавая файл в каталоге данных, содержащий путь на целевой каталог. Этот файл должен называться имя_базы^_данных. sym, где имя_базы_данных — имя базы данных. Предположим, что каталог данных MySQL находится в C:\mysql\data, и вы хотите иметь базу данных foo, расположенную в D: \data\foo. Создайте символическую ссылку следующим образом: 1. Убедитесь, что каталог D:\data\foo существует или при необходимости создайте его. Если у вас уже есть подкаталог базы данных foo в каталоге данных, вы должны переместить его в D:\data. В противном случае символическая ссылка будет недействительной. Во избежание проблем, при перемещении этого каталога сервер не должен функционировать. 2. Создайте файл С: \mysql\data\foo. sym, который содержит путь D: \data\foo\. После этого все таблицы, созданные в базе данных foo, будут созданы в каталоге D:\data\foo\. Имейте в виду, что символическая ссылка не будет использоваться, если каталог с именем этой базы данных существует в каталоге данных MySQL.
7
Клиентские программы и утилиты MySQL
С
уществует множество различных клиентских программ MySQL, предназначенных для подключения к серверу, доступа к базам данных и выполнения административных задач. Доступны также другие утилиты, которые не взаимодействуют с сервером, но выполняют операции, имеющие отношение к MySQL. В этой главе приводится краткий обзор этих программ вместе с детальными описаниями каждой из них. Рассказывается, как запускать эти программы, и какие опции они понимают. В главе 3 можно найти общую информацию о запуске программ и передаче им необходимых опций.
7.1. Обзор сценариев иутилит клиентской стороны В следующем списке кратко представлены клиентские программы и утилиты MySQL: • myisampack. Утилита сжатия таблиц MylSAM для создания более компактных таблиц, доступных только по чтению. См. раздел 7.2. • mysql. Инструмент командной строки для интерактивного ввода SQL-операторов или выполнения их из файла в пакетном режиме. См. раздел 7.3. • mysqlaccess. Сценарий, проверяющий права доступа пользователя к хосту и базе данных. • mysqladmin. Клиентская программа, выполняющая административные операции, такие как создание и уничтожение баз данных, перезагрузка таблиц грантов, выгрузка таблиц на диск и повторное открытие журнальных файлов. См. раздел 7.4. • mysqlbinlog. Утилита чтения операторов из бинарного журнала. Список выполняемых операторов, содержащийся в бинарном журнале, может быть использован для восстановления после аварий. См. раздел 7.5. • mysqlcc. Клиент, предоставляющий графический интерфейс для взаимодействия с сервером. См. раздел 7.6. • mysql check. Клиент обслуживания таблиц, предназначенный для проверки, восстановления, анализа и оптимизации таблиц. См. раздел 7.7.
7.2. myisampack — генератор сжатых таблиц MySQL, доступных только для чтения
461
•
mysqldump. Клиентская программа для экспорта дампа базы данных MySQL в файл в виде SQL-операторов или текстового файла с разделителями-табуляциями. Усовершенствованная свободно распространяемая программа Игоря Романенко (Igor Romanenko). См. раздел 7.8.
•
mysqlhotcopy. Утилита, выполняющая быстрое резервное копирование таблиц My ISAM или ISAM при работающем сервере. См. раздел 7.9.
•
mysqlimport. Клиентская программа, импортирующая текстовые файлы в соответствующие таблицы с применением LOAD DATA INFILE. См. раздел 7.10.
•
mysqlshow. Клиентская программа, выводящая информацию о базах данных, таблицах, столбцах и индексах. См. раздел 7.11.
•
p e r r o r . Утилита, отображающая описание кодов системных ошибок или ошибок MySQL. См. раздел 7.12.
•
r e p l a c e . Утилита замены строк в файлах или в стандартном потоке ввода. См. раздел 7.13.
Каждая программа MySQL принимает множество различных опций. Однако все программы распознают опцию - - h e l p , которую можно использовать для получения полного описания всех опций программы. Для примера попробуйте ввести mysql — h e l p . Клиентские программы MySQL, которые взаимодействуют с сервером, используя библиотеку m y s q l c l i e n t , имеют дело со следующими переменными окружения: MYSQL_UNIX_PORT
Значение по умолчанию имени файла сокета Unix; используется для подключения локальных клиентов.
MYSQL_TCP_PORT
Значение по умолчанию номера порта TCP/IP.
MYSQL_PWD
Пароль по умолчанию.
MYSQL_DEBUG
Опции трассировки во время отладки.
TMPDIR
Каталог временных файлов.
П р и м е н е н и е MYSQL_PWD небезопасно. С м . раздел 4.5.6. В ы м о ж е т е переопределить значения о п ц и й п о у м о л ч а н и ю и л и опций, у к а з а н н ы х в п е р е м е н н ы х окружения д л я всех с т а н д а р т н ы х п р о г р а м м , задав и х в ф а й л е к о н ф и г у р а ц и и или в к о м а н д н о й строке. С м . раздел 3.3.
7.2. myisampack — генератор сжатых таблиц MySQL, доступных только для чтения Утилита myisampack сжимает таблицы MylSAM. Она работает, сжимая каждый столбец таблицы по отдельности. Обычно myisampack сжимает файлы данных на 40-70%. Когда таблица используется позже, информация, необходимая для распаковки столбцов, считывается в память. Это существенно увеличивает производительность при доступе к отдельным записям, поскольку приходится распаковывать только одну запись, а не значительно больший дисковый блок, как это делает Stacker в среде MS-DOS. MySQL использует функцию mmap (), где это возможно, чтобы выполнить отображение в память сжатых таблиц. Если mmap () не работает, MySQL возвращается обратно к нормальным файловым операциям чтения/записи.
462
Глава 7. Клиентские программы и утилиты MySQL
Похожая утилита, pack_isam, сжимает таблицы ISAM. Поскольку формат таблиц ISAM считается устаревшим, в этом разделе описывается только myisampack, но основные приемы работы с myisampack подходят также и для packisam, если иное не оговорено специально. Следует отметить такие моменты: • Если сервер mysqld был запущен с опцией —skip-external-locking, не стоит запускать myisampack в отношении таблицы, которую сервер может обновлять одновременно с процессом упаковки. • После упаковки таблицы она становится доступной только для чтения. В общем, так и было задумано (например, для работы со сжатыми таблицами на компактдиске). Обеспечение возможности записи в сжатые таблицы есть в наших планах, но имеет низкий приоритет. • myisampack может сжимать столбцы типа TEXT и BLOB. Старая утилита pack_isam делать это не может. Запуск myisampack выглядит следующим образом: shell> myisampack [опции] имя_файла . . . Каждое имя файла должно быть именем индексного файла (.MYI). Если вы находитесь не в каталоге базы данных, потребуется указать полный путь к файлу. Допускается не указывать расширение .MYI. myisampack поддерживает следующие опции: •
—help, -?. Выводит страницу справки и завершает работу.
•
--backup, -b. Создает резервную копию данных таблицы под именем имя_таблицы. OLD.
•
—debug [=опции_отладки], -# [опции_отладки]. Записывает журнал отладки. Обычно строка опции_отладки имеет формат ' d: t :о,имя_файла'.
•
—force, -f. Создает упакованную таблицу, даже если она получается больше, чем исходная, или же найден временный файл, оставшийся от предыдущего запуска myisampack. (myisampack создает временный файл с именем имя_таблицы.ИШ во время сжатия таблицы. Если прервать работу myisampack, временный файл может остаться на диске.) Обычно myisampack завершается с сообщением об ошибке, если обнаруживает, что файл имя_таблицы.TMD не удален. С опцией —force упаковка выполняется в любом случае.
•
—-}о±п=имя_болыпой_таблицы, -j имя_большой_таблицы. Соединяет все таблицы, перечисленные в командной строке, в одну таблицу имя_болыпой_таблицы. Все таблицы, которые нужно соединить таким образом, должны иметь идентичную структуру (одинаковые имена и типы столбцов, одинаковые индексы и так далее).
•
—packlength=#, -р #. Указывает длину адреса записи в байтах. Значением должно быть 1, 2 или 3. myisampack сохраняет все записи с длиной указателей в 1, 2 или 3 байта. В большинстве нормальных случаев myisampack может определить правильное значение длины до начала упаковки файла, но в процессе может обнаружить, что допустимо использовать меньшее значение. В этом случае myisampack выводит сообщение об этом, чтобы следующий раз, когда вы будете упаковывать этот файл, вы смогли использовать более короткую длину указателя.
7.2. myisampack — генератор сжатых таблиц MySQL, доступных только для чтения
463
•
—silent, -s. Режим минимального количества сообщений. Выводит в выходной поток только сообщения об ошибках, если они возникают.
•
—test, -t. He выполняет упаковку таблицы, а только тестирует ее.
•
—tmp_diг=луть, -Т путь. Использует указанный каталог как местонахождение для временных файлов.
•
—verbose, -v. Режим расширенных сообщений. Выводит информацию о ходе операции упаковки и ее результатах.
•
--version, -V. Выводит информацию о версии и завершает работу.
•
—wait, -W. Ждет и повторяет попытки обработать таблицу, которая в данный момент занята. Если сервер mysqld был запущен с опцией —skip-external-locking, не стоит запускать myisampack для таблицы, которая может обновляться сервером.
Представленная ниже последовательность упаковки таблиц. shell> Is -I station.* -rw-rw-r— 1 monty my 994128 Apr -rw-rw-r— 1 monty my 53248 Apr -rw-rw-r— 1 monty my 5767 Apr
команд иллюстрирует типичный сеанс
17 19:00 station.MYD 17 19:00 station.MYI 17 19:00 station.frm
shell> myisamchk - d w station MylSAM file: station Isam-version: 2 Creation time: 1996-03-13 10:08:58 Recover time: 1997-02-02 3:06:43 Data records: 1192 Deleted blocks: 0 Datafile parts: 1192 Deleted data: 0 Datafile pointer (bytes): 2 Keyfile pointer (bytes): 2 Max datafile length: 54657023 Max keyfile length: 33554431 Recordlength: 834 Record format: Fixed length table description: Key Start Len Index Type 1 2 4 unique unsigned long 2 32 30 multip. text Field 1 2 3 4 5 6 7 8 9 10 11 12 13
Start 1 2 6 10 11 31 32 62 97 132 167 171 187
Length Type 1 4 4 1 20 1 30 35 35 35 4 16 35
Root Blocksize 1024 1024 10240 1024
Rec/key 1 1
464 14
15 16 17 18 19 20 21 22 23 24
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
Глава 7. Клиентские программы и утилиты MySQL 222 226 242 262 282 302 332 336 340 341 349 357 365 367 369 373 377 378 380 388 392 396 400 404 405 409 413 417 421 425 429 449 479 480 481 560 639 718 797 805 806 807 827 831
4 16 20 20 20 30 4 4 1 8 8 8 2 2
4 4 1 2 8 4 4 4 4 1 4 4 4 4 4 4 20 30 1 1 79 79 79 79 8 1 1 20 4 4
shell> myisampack station.MYI Compressing station.MYI: (1192 records) - Calculating statistics normal: 20 empty-space: 16 empty-zero: 12 empty-fill: 11 pre-space: 0 end-space: 12 table-lookups: 5 zero: 7 Original trees: 57 After join: 17 - Compressing file
7.2. myisampack - генератор сжатых таблиц MySQL, доступных только для чтения 87.14% Remember to run myisamchk -rq on compressed tables shell> Is -1 station.* -rw-rw-r— 1 monty my 127874 Apr 17 19:00 station.MYD -rw-rw-r— 1 monty my 55296 Apr 17 19:04 station.MYI -rw-rw-r— 1 monty my 5767 Apr 17 19:00 station.frm shell> myisamchk - d w station MylSAM file: station Isam-version: 2 Creation time 1996-03-13 10:08:58 Recover time: 1997-04-17 19:04:26 Data records: 1192 Deleted blocks: 0 Datafile parts: 1192 Deleted data: 0 Datafile pointer (bytes): 3 Keyfile pointer (bytes): 1 Max datafile length: 16777215 Max keyfile length: 131071 Recordlength: 834 Record format: Compressed table description: Key Start Len Index Type Root Blocksize Rec/key 1 2 4 unique unsigned long 10240 1024 1 54272 1024 1 2 32 30 multip.text Field 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
Start 1 2 6 10 11 31 32 62 97 132 167 171 187 222 226 242 262 282 302 332 336 340 341 349 357 365 367 369
Length 1 4 4 1 20 1 30 35 35 35 4 16 35 4 16 20 20 20 30 4 4 1 8 8 8 2 2 4
Type constant zerofill(l) no zeros, zerofill(l) table-lookup no endspace, no endspace, no empty no endspace, zerofill(l) no endspace, no endspace, zerofill(l) no endspace, no endspace, no endspace, no endspace, no endspace, always zero always zero
not always not always, no empty not always, no empty not_always, no empty not always, no empty not_always, no empty not always no empty no empty no empty
table-lookup table-lookup always zero no zeros, zerofill(l) no zeros, zerofill(l)
Huff tree Bits 1 0 2 9 2 9 3 9 4 0 3 9 5 9 6 9 7 9 6 9 2 9 5 9 6 9 2 9 5 9 8 9 8 9 5 9 6 9 2 9 2 9 3 9 0 9 10 0 2 9 2 9 2 9 2 9
465
466
Глава 7. Клиентские программы и утилиты MySQL 4 1 2 8 4 4 4 4 1 4 4 4 4 4 4 20 30 1 1 79 79 79 79 8 1 1 20 4 4
table-lookup no zeros, zerofill(l) no zeros always zero table-lookup no zeros, zerofill(l) no zeros, zerofill(l)
11 3 2 2 2 12 13 2
no zeros always zero no zeros always zero no zeros always zero no empty no empty no no no no no
endspace, no empty empty empty endspace empty
no empty no zeros, zerofill(2) no zeros, zerofill(l)
2 2 2 2 2 2 3 3 14 14 15 2 2 16 2 17 3 3 2 Csl
373 377 378 380 388 392 396 400 404 405 409 413 417 421 425 429 449 479 480 481 560 639 718 797 805 806 807 827 831
Csl
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
0 9 9 9 9 0 9 9 9 9 9 9 9 9 9 9 9 4 4 9 9 9 9 9 1 9 9 9 9
myisampack выводит информацию следующего рода: • normal. Количество столбцов, для которых не выполняется никакой дополнительной упаковки. • empty-space. Количество столбцов, содержащих только пробелы; это занимает 1 бит. • empty-zero. Количество столбцов, содержащих только двоичные нули; это занимает 1 бит. • empty-fill. Количество целочисленных столбцов, которые не занимают диапазон байтов, отведенных их типу; они сужаются до более компактного типа. Например, столбец BIGINT (восемь байт) может храниться как TINYINT (один байт), если все хранящиеся в ней значения находятся в диапазоне от-128 до 127. • pre-space. Количество десятичных столбцов, которые хранятся с ведущими пробелами. В этом случае каждое значение будет содержать информацию о количестве ведущих пробелов. • end-space. Количество столбцов, имеющих завершающие пробелы. В этом случае каждое значение будет хранить информацию о количестве таких пробелов. • table-lookup. Столбцы, содержащие только небольшое количество уникальных значений. Перед сжатием Хаффмана (Huffman) преобразуются к типу ENUM. •
zero. Количество столбцов, в которых все значения равны нулю.
7.3. Инструмент командной строки mysql
467
• Original trees. Начальное количество деревьев Хаффмана. • After join. Количество уникальных деревьев Хаффмана, оставшееся после объединения деревьев для экономии места заголовков. После того, как таблица была сжата, myisamchk -dvv выводит дополнительную информацию о каждом столбце: • Туре. Тип столбца. Может принимать одно их следующих значений:
•
•
constant. Все строки имеют одинаковые значения.
•
no endspace. He хранить завершающие пробелы.
•
no endspace, not_always. He хранить завершающие пробелы и не выполнять сжатие завершающих пробелов для всех значений.
•
no endspace, no empty. He хранить завершающие пробелы. Не хранить пустые значения.
•
table-lookup. Столбцы были преобразованы к типу ENUM.
•
z e r o f i l l ^ ) . Самые старшие л байт в значениях равны нулю и не сохраняются.
•
no zeroes. He хранить нули.
•
always zero. Нулевые значения хранятся, занимая один бит.
Huff tree. Количество деревьев Хаффмана, ассоциируемых со столбцом.
• Bits. Количество бит, используемых деревом Хаффмана. После того, как вы запустили myisampack, вы должны запустить myisamchk, чтобы пересоздать индексы. Одновременно вы можете отсортировать блоки индексов и собрать статистику, необходимую оптимизатору MySQL для более эффективной работы: shell> myisamchk -rq —sort-index —analyze имя_та блицы. MYI Похожая процедура предусмотрена и для таблиц ISAM. После использования packJLsam перестройте индексы с помощью isamchk: shell> isamchk -rq —sort-index —analyze имя_таблицы. ISM После установки упакованной таблицы в каталог данных MySQL потребуется выполнить mysqladmin flush-tables, чтобы заставить mysqld начать работать с этой таблицей. Чтобы распаковать ранее сжатую таблицу, используйте опцию —unpack программы myisamchk или isamchk.
7.3. Инструмент командной строки mysql mysql - это простая SQL-оболочка (снабженная средствами GNU readline). Она поддерживает интерактивный и не интерактивный режимы работы. Когда используется интерактивно, результаты запросов представляются в формате ASCII-таблицы. При работе в неинтерактивном режиме (например, в качестве фильтра), результат имеет формат, разделенный знаком табуляции. Формат вывода может быть изменен с помощью опций командной строки. Если у вас возникают проблемы, вызванные недостатком памяти при размещении больших результирующих наборов, используйте опцию —quick. Это заставит mysql извлекать результаты от сервера по одной строке, вместо того, чтобы получить ответ сразу
468
Глава 7. Клиентские программы и утилиты MySQL
весь и буферизировать его перед выводом. Для получения результата необходимо будет вызывать mysql_use_result () вместо mysql_store_result (). Использование mysql очень просто. Вызовите его из командной оболочки, как показано ниже: s h e l l > mysql имя_базы__данных или s h e l l > mysql —\1зег=имя_пользователя —password=napojib имя__базы_данных Затем вводите операторы SQL, завершая каждый символом ' ; ' , \д или \G и нажимая клавишу <Enter>. Вы также можете запускать сценарии следующим образом: s h e l l > mysql имя_базы__данных < s c r i p t . s q l > output.tab mysql поддерживает следующие опции: •
— h e l p , - ? . Выводит страницу справки и завершает работу.
•
—batch, -В. Печатает результаты, используя символ табуляции в качестве разделителя столбцов; каждая запись таблицы находится в отдельной строке. С этой опцией mysql не использует файл хронологии.
•
— c h a r a c t e r - s e t s - d i r = n y T b . Каталог, в котором установлен символьный набор. См. раздел 4.7.1.
•
—compress, -С. Сжимает всю информацию, пересылаемую между клиентом и сервером, если оба поддерживают сжатие.
•
—databaзе=имя_базы_данных, -D имя_базы_данных. База данных, с которой нужно работать. Обычно указывается в конфигурационном файле.
•
—debug [=опции_отладш], Обычно строка опции_отладки
-#
[опции_отладки].
Записывает журнал отладки.
имеет формат ' d : t : o , и м я _ ф а й л а \ П о умолчанию
'd:t:o,/tmp/mysql.trace 1 . •
—debug-info, -T. Печатает некоторую отладочную информацию при завершении работы программы.
•
—default-character-set=Ha6op. Использует набор в качестве набора символов по умолчанию. См. раздел 4.7.1.
•
—execute=onepaTop, -e оператор. Выполняет оператор и завершает работу. Формат по умолчанию такой же, как при использовании — b a t c h .
•
— f o r c e , -f. Продолжает работу, даже если возникнет ошибка SQL.
•
—host=H/wi_xocTa, -h имя_хоста. Подключается к серверу MySQL на указанном хосте.
•
--html, -H. Генерирует вывод в формате HTML.
•
--ignore-space, - i . Игнорирует пробелы после имен функций. Эффект от этой опции описывается в ходе обсуждения IGNORE_SPACE в разделе 4.2.2.
•
— l o c a l - i n f i l e [ = {0 11} ]. Включает и выключает свойство LOCAL для LOAD DATA INFILE. Если ничего не указано, опция включает LOCAL. Для явного включения и выключения следует использовать --local-infile=0 или ~ l o c a l - i n f i l e = l . Включение LOCAL не имеет эффекта, если сервер его не поддерживает.
7.3. Инструмент командной строки mysql
469
•
—named-commands, -G. Именованные команды включены. Длинный формат команд разрешен, равно как и сокращенный, подобный \*. Например, распознается как quit, так и /q.
•
—no-auto-rehash, -А. Автоматическое повторное хеширование не используется. Эта опция заставляет mysql стартовать быстрее, но вы должны будете выдавать команду rehash, если хотите использовать завершение имен таблиц и столбцов.
•
—no-beep, -b. He выдает звуковой сигнал при возникновении ошибки.
•
—no-named-commands, -g. Именованные команды отключены. Используется только форма \* либо именованные команды должны указываться только в начале строки, завершающейся точкой с запятой (;). Начиная с MySQL 3.23.22, mysql запускается с этой опцией, включенной по умолчанию. Однако даже в этом случае длинноформатные команды по-прежнему работают с первой строки.
•
—no-pager. He использует программу разбиения на страницы для просмотра ответа на запрос. Разбиение вывода на страницы обсуждается далее, в разделе 7.3.1.
•
—no-tee. He копировать вывод в файл. Файлы вывода обсуждаются в разделе 7.3.1.
•
—one-database, -0. Игнорирует все операторы кроме тех, что имеют отношение к базе данных по умолчанию, указанной в командной строке. Это удобно для того, чтобы пропускать изменения в других базах, зафиксированные в бинарном журнале.
•
--pager[^команда]. Использует указанную команду для постраничного просмотра ответа на запрос. Если команда не указана, ее имя берется из переменной окружения PAGER. Допустимыми программами разбиения на страницы могут быть less, more, cat [> filename] и так далее. Эта опция работает только в Unix. Она не работает в пакетном режиме. Файлы вывода обсуждаются в разделе 7.3.1.
•
— pas sword [^пароль], -р [пароль]. При подключении к серверу использовать указанный пароль. Имейте в виду, что если вы пользуетесь краткой формой этой опции (-р), то не должны оставлять пробел между флажком опции и паролем. Если в командной строке пароль не указан, он будет запрошен интерактивно.
•
—ро г Ь=номер_порта, -Р номер_ пор та. Номер порта TCP/IP для подключения.
•
—prompt^ строка_формата. Устанавливает формат приглашения. По умолчанию используется mysql>. Специальные символьные последовательности, которые можно использовать, описаны в разделе 7.3.1.
•
— protocol={TCP I SOCKET | PIPE | MEMORY}. Сетевой протокол для подключения к серверу. Эта опция появилась в MySQL 4.1.
•
--quick, -q. He кэширует каждый результат запроса, печатает каждую строку по мере получения. Это может вызвать задержки в работе сервера, если вывод приостанавливать. С этой опцией mysql не использует файл хронологии.
•
—raw, -r. Выводит значения столбцов без преобразования управляющих символов. Обычно используется с опцией —batch.
•
—reconnect. Если связь с сервером разорвана, автоматически пытается ее восстановить. Одна попытка восстановления подключения предпринимается каждый раз после потери связи. Чтобы подавить эти попытки, нужно использовать опцию —skip-reconnect. Введено в MySQL 4.1.0.
470
Глава 7. Клиентские программы и утилиты MySQL
•
—safe-updates, — i-am-a-dummy, -U. Разрешает только такие операторы UPDATE и DELETE, в которых указаны строки, подвергаемые изменению с использованием значений ключей. Если эта опция указана в конфигурационном файле, ее можно перекрыть, задав —safe-updates в командной строке. Более подробная информация об этой опции представлена в разделе 7.3.3.
•
—silent, -s. Режим минимального количества сообщений. Генерирует минимум выходной информации. Эту опцию можно указать несколько раз, чтобы еще больше ограничить объем вывода.
•
—skip-column-names, -N. Не выводить имена столбцов в результате.
•
—skip-line-numbers, -L. Не указывать номера строк для ошибок. Применимо в случаях, когда вы хотите сравнить результирующие файлы, в которых включены сообщения об ошибках.
•
—socket=nyTb, -S путь. Файл сокета, используемый для подключения.
•
—table, - t . Выводит результат в табличном формате. Этот формат используется по умолчанию при интерактивном режиме, но может быть применен и в пакетном режиме.
•
—tee=HM#_файла. Добавляет копию выходного потока в указанный файл. Эта опция не работает в пакетном режиме. Файлы вывода обсуждаются в разделе 7.3.1.
•
--unbuffered, -n. Сбрасывает содержимое буфера после каждого запроса.
•
—изег=имя_пользователя, -и имя_пользователя. Указывает имя пользователя MySQL для подключения к серверу.
•
--verbose, -v. Режим расширенных сообщений. Генерирует более подробный вывод. Эту опцию можно указать несколько раз, что приводит к большему и большему объему вывода. (Например, -v -v -v приводит к табличному формату вывода даже в пакетном режиме).
•
—version, -V. Выводит информацию о версии и завершает работу.
•
—vertical, -E. Печатает строки вывода вертикально. Без этой опции вы можете указать необходимость вертикального вывода для отдельных операторов, завершая их символами \G.
•
—wait, -w. Если соединение не может быть установлено, ожидать и повторять попытки, а не прерывать работу.
•
—xml, -X. Генерировать вывод в формате XML.
Можно также установить значения следующих переменных, используя опцию —имя__ переменной^ зна чение: •
connect_timeout. Таймаут подключения в секундах (по умолчанию 0).
•
maxallowedpacket. Максимальная длина пакета для отправки или приема с сервера (по умолчанию 16 Мбайт).
•
m a x j o i n s i z e . Автоматический предел на количество строк в соединении при использовании —safe-updates (по умолчанию 1 000 000).
•
n e t b u f f e r l e n g t h . Размер буфера для подключений через TCP/IP и сокеты (по умолчанию 16 Кбайт).
7.3. Инструмент командной строки mysql •
471
s e l e c t l i m i t . Автоматический предел для оператора SELECT при использовании —safe-updates (go умолчанию 1 000).
Существует возможность устанавливать переменные, используя синтаксис --set-уаг1аЫе=имя_леременяой5= значение или -0 имя_переменной= значение. Однако, начиная с версии MySQL 4.0, этот синтаксис считается устаревшим. В Unix клиентская программа mysql записывает исполняемые операторы в файл хронологии. По умолчанию он называется .mysql J i i s t o r y и находится в домашнем каталоге пользователя. Чтобы указать другой файл, установите значение переменной окружения MYSQL_HISTFILE. Если вы не хотите поддерживать файл хронологии, сначала удалите файл ,mysql_history, если он существует, и затем воспользуйтесь любой из следующих процедур: • Установите значение переменной MYSQLJilSTFILE равным /dev/null. Чтобы эта установка выполнялась автоматически при каждом входе в систему, внесите соответствующую строку в один из ваших сценариев запуска. • Создайте символическую ссылку ,mysql_history, указывающую на /dev/null: shell> In -s /dev/null $HOME/.mysql_history Это нужно сделать только однажды.
7.3.1. Команды mysql mysql посылает вводимые вами SQL-операторы для выполнения на сервер. Но существует также набор команд, которые mysql интерпретирует самостоятельно. Чтобы получить список этих команд, введите help или \h в приглашении командной строки mysql: mysql> help MySQL commands: (\h) clear (\c) connect (\r) delimiter edit ego
(\d) (\e) (\G)
exit go help nopager notee pager
(\q) (\g) (\h) (\n) (\t) (\P)
print prompt quit rehash source
(\p) (\R) (\q) (\#) (\.)
Synonym for 4help'. Clear command. Reconnect to the server. Optional arguments are db and host. Set query delimiter. Edit command with $EDITOR. Send command to mysql server, display result vertically. Exit mysql. Same as quit. Send command to mysql server. Display this help. Disable pager, print to stdout. Don't write into outfile. Set PAGER [to__pager] . Print the query results via PAGER. Print current command. Change your mysql prompt. Quit mysql. Rebuild completion hash. Execute an SQL script file.
Глава 7. Клиентские программы и утилиты MySQL
472
status system tee
(\s) (\!) (\T)
use
(\u)
Команды MySQL: •p (\h) clear (\c) connect (\r) delimiter edit ego
(\d) (\e) (\G)
exit go help nopager notee pager
(\q) (\g). (\h) (\n) (\t) (\P)
print prompt quit rehash source
(\p) (\R) (\q) (\#) (\.)
status system tee
(\s) (\!) (\T)
use
(\u)
Takes a f i l e name as an argument. Get status information from the server. Execute a system shell command. Set outfile [to__outfile] . Append everything into given outfile. Use another database. Takes database name as argument. Синоним для ' h e l p ' . Команда очистки. Повторно подключиться к серверу. Необязательными аргументами являются db и host. Установить разделитель запросов. Редактировать с помощью $EDITOR. Послать команду серверу mysql, отобразить результат вертикально. Завершить mysql. To же, что и quit. Послать команду серверу mysql. Вывести эту справку. Отключить разбиение на страницы, выводить в stdout. Не записывать вывод в файл. Установить PAGER [to_pager]. Печатать результаты запроса через PAGER. •Печатать текущую команду. Изменить формат приглашения mysql. Завершить mysql. Перестроить хеш завершения. Выполнить файл сценария SQL. Принимает в качестве аргумента имя файла. Получить информацию о состоянии из сервера. Выполнить команду системной оболочки. Установить файл вывода [to_outfile]. Дописывать все в конец заданного файла вывода. Использовать другую базу данных. Принимает в качестве аргумента имя базы данных.
Команды edit, nopager, pager и system работают только под Unix. Команда status выводит некоторую информацию о подключении и сервере, который вы используете. Если вы работаете в режиме —safe-updates, status также печатает значения переменных mysql, которые затрагивают ваши запросы. Чтобы регистрировать запросы и их результаты, используйте команду tee. Вся информация, выводимая на экран, будет дублироваться в заданном файле. Это может весьма пригодиться во время отладки. Вы можете включать это средство в командной строке с помощью опции —tee или интерактивно, вводя команду tee. Отключить действие команды можно командой notee. Повторный ввод tee возобновляет регистрацию в журнале. Если ввести tee без параметра, будет использоваться предыдущий файл. Имейте в виду, что tee сбрасывает результаты запроса в файл после каждого оператора, перед тем как mysql выведет очередное приглашение на ввод. Просмотр и поиск в результатах запроса в интерактивном режиме с помощью внешних программ Unix, подобных less, more, теперь возможен с опцией —pager. Если не
7.3. Инструмент командной строки mysql
473
указывать никакого значения этой опции, mysql проверяет значение переменной окружения PAGER и использует его в качестве имени программы просмотра. Постраничный просмотр вывода можно включать интерактивно командой pager и отключать командой nopager. Эта команда принимает необязательный аргумент. Если он есть, устанавливается указанная им программа просмотра. Если аргумента нет, выбирается программа, переданная в опции командной строки, а если не указана и там, то для просмотра результатов запросов используется стандартный вывод stdout. Постраничный просмотр работает только в средах Unix, так как для него применяется функция рореп (), которая в Windows отсутствует. Для Windows вместо этого можно использовать команду tee, которая сохранит весь вывод запроса в файле, несмотря на то что в ряде случаев для просмотра результатов это не так удобно, как применение pager. Вот несколько советов относительно команды pager: • Вы можете использовать эту команду для вывода в файл, при этом результаты поступят только в файл: mysql> pager cat > /tmp/log.txt Вы можете также передавать любые опции программе, используемой для постраничного просмотра: mysql> pager less -n -i -S • В предыдущем примере обратите внимание на опцию -S. Это удобно для просмотра очень широких результатов запроса. Иногда такие результирующие наборы очень трудно читать на экране. Опция -S программы less может помочь в подобной ситуации, поскольку позволит выполнять горизонтальную прокрутку широкого текста с помощью клавиш со стрелками вправо и влево. Вы можете использовать -S интерактивно внутри less, чтобы включать и отключать режим горизонтальной прокрутки. Более подробную информацию можно получить из руководства по less: shell> man less • Есть возможность задавать очень сложные команды постраничного просмотра для работы с результатами запросов:
mysql> pager cat | tee /drl/tmp/res.txt \ | tee /dr2/tmp/res2.txt | less -n -i -S В этом примере команда будет отправлять результат запроса в два файла, которые хранятся в двух разных каталогах на двух разных файловых системах, смонтированных на /drl и /dr2, вдобавок отображая его на экране командой less. Вы можете комбинировать функции tee и pager. Имея включенным tee и pager, установленным в less, вы сможете просматривать результат в less и одновременно сохранять вывод в файле. Разница между Unix-командой tee, применяемой с командой pager, и встроенной в mysql командой tee состоит в том, что встроенная команда tee работает, даже если соответствующая команда Unix недоступна. Встроенная команда tee регистрирует в журнале все, что выводится на экран, в то время как Unix-команда tee, применяемая совместно с pager, записывает не все. Кроме того, регистрацию в журнале встроенной командой tee можно включать и отключать интерактивно внутри mysql. Это удобно, если вы хотите регистрировать только некоторые запросы, но не все.
474
Глава 7. Клиентские программы и утилиты MySQL
Начиная с MySQL 4.0.2, приглашение по умолчанию mysql> можно изменить. Строка, определяющая приглашение, может включать следующие специальные последовательности: Опция
Описание
\v
Версия сервера.
\d
Текущая база данных.
\h
Хост сервера.
\р
Текущий хост TCP/IP.
\и
Ваше имя пользователя.
\U
Полное имя учетной записи пользователя u s e r_n ame @ h о s t _ n ame.
\\
Литеральный символ'V.
\п
Символ перевода строки.
\t
Символ табуляции.
\
Пробел (следует за обратной косой чертой).
\_
Пробел.
\R
Текущее время в 24-часовом формате.
\г
Текущее время в стандартном 12-часовом формате.
\т
Минуты текущего времени.
\у
Текущий год, двузначное число.
\Y
Текущий год, четырехзначное число.
\D
Полная текущая дата.
\s
Секунды текущего времени.
\w
Текущий день недели в трехсимвольном формате (Моп, Tue,...).
\Р
am/pm.
\о
Текущий месяц в числовом формате.
\0
Текущий месяц в трехсимвольном формате (Jan, Feb,...).
\с
Счетчик, увеличивающийся с каждым введенным оператором.
Символ ' \ ' с последующей любой буквой просто представляет эту букву. Если вы вводите команду prompt без аргументов, mysql возвращает приглашение к значению по умолчанию - mysql>. Приглашение можно установить разными способами: •
Используя переменную окружения. Вы можете в переменной окружения установить строку приглашения mysql, например: shell> export MYSQLJ>S1=" (\u@\h) [\d]> "
•
Используя конфигурационный файл. Вы можете установить форму приглашения в группе [mysql] конфигурационного файла MySQL - /etc/my.cnf или .my. cnf в домашнем каталоге. Например: [mysql] prompt=(\\u@\\h) [\\d]>\\_
7.3. Инструмент командной строки mysql
475
Обратите внимание, что в этом примере обратные косые черты дублируются. Если вы установите приглашение, используя опцию prompt в конфигурационном файле, желательно дублировать обратные косые черты, когда используются специальные параметры приглашения. Набор допустимых параметров приглашения частично переопределяется со специальными управляющими последовательностями, которые распознаются в конфигурационных файлах. (Эти последовательности перечислены в разделе 3.3.2.) Это переопределение может привести к проблемам, если использовать одинарные обратные косые черты. Например, \s будет интерпретироваться как пробел вместо того, чтобы означать секунды текущего времени. В следующем примере показано, как определить приглашение в конфигурационном файле, чтобы включить в него текущее время в формате ЧЧ:ММ:СС>: [mysql] prompt="\\r:\\m:\\s> " • Используя опцию командной строки. Можно установить приглашение в опции —prompt командной строки mysql, например: shell> mysql --prompt=" (\u@\h) [\d]> " {пользователь®хост) [база__данных] > • Интерактивно. Изменить форму приглашения можно также интерактивно, используя команду prompt (или \R), например: mysql> prompt (\u@\h) [\d]>\_ PROMPT set to '(\u@\h) [\d]>\_' {пользователь®хост) [база^данных]> {пользователь®хост) [база_данных]> prompt Returning to default PROMPT of mysql> mysql>
7.3.2. Запуск SQL-операторов из текстового файла Клиентская программа mysql обычно используется интерактивно: shell> mysql имя_базы_данных Однако существует возможность поместить SQL-операторы в файл с тем, чтобы mysql прочитал их оттуда и выполнил. Чтобы сделать это, создайте текстовый файл текстовый_файл, содержащий требуемые операторы. Затем запустите mysql, как показано ниже: shell> mysql имя_базы_данных < текстовый_файл Вы можете также поместить в начало файла оператор USE имя_базы_данных. В этом случае нет необходимости указывать базу данных в командной строке: shell> mysql < текстовый^файл Если mysql уже запущен, вы можете выполнить файл SQL-сценария, используя либо команду source, либо \.: mysql> source имя_файла; mysql> \. имя_файла
Глава 7. Клиентские программы и утилиты MySQL
476
7.3.3. Советы по mysql В этом разделе описаны некоторые приемы, позволяющие использовать mysql более эффективно. 7.3.3.1. Вертикальный вывод результатов запроса Некоторые результаты запросов гораздо лучше воспринимаются, если их выводить вертикально, вместо обычного горизонтального табличного формата. Например, длинные текстовые значения, которые включают в себя переводы строк, часто гораздо легче читать в вертикальном формате: m y s q l > SELECT * FROM m a i l s WHERE LENGTH(txt) < 300 LIMIT 300,1\G *************************** i# r o w ***************************
msg_nro: date: time_zone: mail_from: reply: mail_to: sbj: txt:
3068 2000-03-01 23:29:50 +0200 Monty
[email protected] "Thimble Smith" UTF-8 > » » "Thimble" == Thimble Smith writes:
Thimble> Hi. I think this is a good idea. Is anyone familiar Thimble> with UTF-8 or Unicode? Otherwise, I'll put this on my Thimble> TODO list and see what happens. Yes, please do that. Regards, Monty file: inbox-jani-1 hash: 190402944 1 row in set (0.09 sec) 7.3.3.2. Применение опции - -safe-updates Опция --safe-updates (или —i-am-a-dummy) удобна для начинающих пользователей. Эта опция была введена в MySQL 3.23.11. Она полезна в случаях, когда вы непреднамеренно вводите оператор DELETE FROM имя__таблицы без конструкции WHERE. Обычно такой оператор удаляет все строки в таблице. С опцией --safe-updates строки будут удалены только в случае указания ключевых значений, которые их идентифицируют. Это позволяет предотвратить крупные неприятности. Когда вы используете опцию --safe-updates, mysql при подключении отправляет на сервер следующий оператор: SET SQL_SAFE_UPDATES=l,SQL_SELECT_LIMIT=1000,
SQL_MAX_JOIN_SIZE=1000000;
Этот оператор SET приводит к следующим эффектам: • Вы не имеете возможности выполнять операторы UPDATE и DELETE, если только не укажете ключевое условие в конструкции WHERE либо не добавите конструкцию LIMIT (либо то и другое). Например: UPDATE имя_таблицы SET not_key_column=# WHERE key_column=#; UPDATE имя_таблицы SET not_key_column=# LIMIT 1;
7.4. Программа администрирования MySQL-сервера mysqladmin
477
• Все большие результаты запросов SELECT ограничиваются 1000 строк, если только не включают конструкцию LIMIT. • Многотабличные операторы SELECT, которые предположительно должны проверить более 1 000 000 комбинаций строк, прерываются. Чтобы указать ограничения, отличные от 1000 и 1000000, вы можете переопределить умолчания, используя опции —select_limit и —max_join_size: shell> mysql --safe-updates --select_limit=500 --max_join_size=10000
7.3.3.3. Отключение автоматического восстановления соединений mysql Если программа mysql теряет соединение с сервером в процессе выполнения запроса, она немедленно автоматически пытается восстановить это соединение и отправить запрос снова. Однако даже если mysql удастся это сделать, ваше первое соединение прервется, и все ваши предыдущие установки и объекты сеанса будут потеряны: временные таблицы, режим автоматической фиксации транзакций, пользовательские и системные переменные. Такое поведение может оказаться довольно-таки опасным, как в следующем примере, где сервер был остановлен и перезапущен без вашего ведома: mysql> SET @a=l; Query OK, 0 rows affected (0.05 sec) mysql> INSERT INTO t VALUES(@a); ERROR 2006: MySQL server has gone away No connection. Trying to reconnect... Connection id: 1 Current database: test Query OK, 1 row affected (1.30 sec) mysql> SELECT * FROM t; I a | + + | NULL |
1 row in set (0.05 sec) Пользовательская переменная @а была утеряна вместе с соединением, а после его восстановления стала неопределенной. Если важно, чтобы клиентская программа mysql была прервана с сообщением об ошибке при утере соединения, вы можете запустить ее с опцией —skip-reconnection.
7.4. Программа администрирования MySQL-сервера mysqladmin mysqladmin - это клиентская программа, предназначенная для выполнения операций администрирования. Вы можете использовать ее для проверки конфигурации и текущего состояния сервера, создания и удаления баз данных, и многого другого. Запуск выглядит mysqladmin так: s h e l l > mysqladmin
[опции]
команда
[опции-команды]
mysqladmin поддерживает следующие команды:
команда
...
478
Глава 7. Клиентские программы и утилиты MySQL
•
create имя__базы_данных. Создать новую базу данных.
•
drop имя_базы_данных. Удалить базу данных и все ее таблицы.
•
extended-status. Вывести переменные состояния сервера и их значения.
•
flush-hosts. Сбросить всю информацию из кэша хостов.
•
flush-logs. Сбросить все журналы.
•
flush-privileges. Перезагрузить таблицы привилегий (то же, что и reload).
•
flush-status. Очистить переменные состояния.
•
flush-tables. Сбросить буферы таблиц.
•
flush-threads. Сбросить кэш потоков (добавлена в MySQL 3.23.16).
•
k i l l идентификатор, идентификатор,.... Прервать потоки сервера.
•
password новый-пароль. Назначить новый пароль. Это изменяет пароль на новыйпароль для учетной записи, под которой вы подключились к серверу программой mysqladmin.
•
ping. Проверить, работает ли сервер.
•
processlist. Вывести список активных серверных потоков. Это то же самое, что и вывод оператора SHOW PROCESSLIST. Если указана опция —verbose, вывод будет подобен выводу оператора SHOW FULL PROCESSLIST.
•
reload. Перезагрузить таблицы привилегий (то же, что и flush-privileges).
•
refresh. Сбросить буферы всех таблиц, закрыть и открыть файлы журналов.
•
shutdown. Остановить сервер.
•
s t a r t - s l a v e . Запустить репликацию на подчиненном сервере (добавлена в MySQL 3.23.16).
•
status. Вывести краткое сообщение о состоянии сервера.
•
stop-slave. Остановить репликацию на подчиненном сервере (добавлена в MySQL 3.23.16).
•
variables. Вывести системные переменные сервера и их значения.
•
version. Показать номер версии сервера.
Все команды могут быть сокращены до любого уникального префикса. Например: shell> mysqladmin proc stat + + + + + + + + + I Id | User | Host | db | Command | Time | State I Info | I 6 | monty | localhost I I Processlist | 0 | + + + + + + + Uptime: 10077 Threads: 1 Questions: 9 Slow queries: 0 Opens: 6 Flush tables: 1 Open tables: 2 Memory in use: 1092K Max memory used: 1116K Команда status в mysqladmin выводит следующие значения: •
Uptime. Длительность работы сервера в секундах.
•
Threads. Количество активных потоков (клиентов).
I +
| +
7.4. Программа администрирования MySQL-сервера mysqladmin
479
• Questions. Количество клиентских запросов с момента старта сервера. • Slow queries. Количество запросов, на выполнение которых потребовалось более long_query_time секунд. • Opens. Количество таблиц, открытых сервером. • Flush tables. Количество выполненных сервером команд flush . . . , refresh и reload. • Open tables. Количество таблиц, открытых в данный момент. • Memory in use. Общий объем памяти, распределенный непосредственно кодом mysqld. Это значение отображается, только если MySQL был скомпилирован с опцией --with-debug-full. • Maximum memory used. Максимальный объем памяти, распределенный непосредственно кодом mysqld. Это значение отображается, только если MySQL был скомпилирован с опцией —with-debug-full. Если вы выполняете mysqladmin shutdown, подключившись к локальному серверу с использованием файла сокета Unix, mysqladmin ожидает, пока файл идентификатора процесса сервера будет удален, чтобы гарантировать, что сервер был остановлен правильно. mysqladmin поддерживает следующие опции: • —help, -?. Выводит страницу справки и завершает работу. • —character-sets-dir=nyTb. Каталог, в котором установлен символьный набор. См. раздел 4.7.1. • —compress, -С. Сживает всю информацию, передаваемую между клиентом и сервером, если оба они поддерживают сжатие. • —count=#, -с #. Количество итераций, которые необходимо выполнить. Работает только с опцией —sleep (-i). •
— debug[=опции__отладки], -# [опции^отладки]. Записывает журнал отладки. Обычно строка опции_отладки представляется в формате 'd:t:o,имя_файла*. По умолчанию 'd:t:о,/tmp/mysqladmin.trace'.
•
—force, -f. He запрашивает подтверждения команды drop database. В случае набора команд продолжает работу даже при возникновении ошибок.
• —host=HM#_xocTa, -h опции__отладки. Подключается к серверу MySQL на указанном хосте. • —password[=лароль], -р[пароль]. При подключении к серверу использует указанный пароль. Имейте в виду, что если вы применяете краткую форму этой опции (-р), то не должны оставлять пробел между названием опции и паролем. Если в командной строке пароль не указан, он будет запрошен интерактивно. • — рог t=HOMep_nopTaf -Р номерпорта. Номер порта TCP/IP для подключения. • —protocol={TCP I SOCKET I PIPE | MEMORY}. Сетевой протокол для подключения к серверу. Эта опция была введена в MySQL 4.1. • — r e l a t i v e , -г. Показывает разницу между текущим и предыдущим значением, когда применяется вместе с -i. В настоящее время эта опция работает только с
командой extended-status.
480
Глава 7. Клиентские программы и утилиты MySQL
•
—silent, -s. Завершает работу молча, если невозможно установить подключение к серверу.
•
—si 1р=задержка, - i задержка. Повторяет выполнение команды с задержкой задержка между попытками.
•
— socket=nyTb, -S путь. Файл сокета, используемый для подключения.
•
—изег=имя_пользователя, -и имя_пользователя. Указывает имя пользователя MySQL для подключения к серверу.
•
—verbose, -v. Режим расширенных сообщений. Генерирует более подробный вывод.
•
—version, -V. Выводит информацию о версии и завершает работу.
•
—vertical, -E. Печатает строки вывода вертикально. Похоже на —relative, но печатает вывод вертикально.
•
—wait [=#], -w [#]. Если соединение не может быть установлено, ожидает и повторяет попытки вместо того, чтобы прерывать работу. Если значение опции указано, оно задает количество повторных попыток (по умолчанию 1).
Можно также установить следующие переменные с помощью опции —имя_переменной= значение: •
connect __timeout. Количество секунд таймаута подключения (по умолчанию 0).
•
shutdown_timeout. Задержка при останове сервера в секундах (по умолчанию 0).
Вы можете также установить значения переменных, используя синтаксис —set-variable= имя_переменной= значение или -0 имя_переменной=значение. Однако, начиная с версии MySQL 4.0, этот синтаксис считается устаревшим.
7.5. Утилита работы с бинарными журналами mysqlbinlog Файлы бинарных журналов, которые генерирует сервер, записываются в двоичном формате. Для просмотра их содержимого в текстовом виде служит утилита mysqlbinlog. Она доступна, начиная с версии MySQL 3.23.14. Вызов mysqlbinlog выглядит следующим образом: shell> mysqlbinlog [опции] файл-журнала . . . Например, чтобы отобразить содержимое бинарного журнала воспользуйтесь командой: shell> mysqlbinlog binlog.0000003
binlog.000003,
Вывод этой команды включает все операторы, содержащиеся в binlog.000003, вместе с дополнительной информацией, такой как время выполнения каждого оператора, идентификатор потока клиента, который его вызвал, временная метка и так далее. Обычно mysqlbinlog используется для непосредственного чтения файлов бинарных журналов и применения на локальном сервере MySQL. Существует также возможность читать бинарные журналы с удаленного сервера, если использовать опцию —read-f romremote-server. Однако эта практика считается устаревшей, поскольку вместо этого мы, прежде всего, стараемся упростить работу с бинарными журналами на локальном сервере.
7.5. Утилита работы с бинарными журналами mysqlbinlog
481
Когда бинарный журнал читается с удаленного сервера, опции параметров соединения могут указывать, как подключаться к серверу, но они игнорируются, если не указана опция —read-from-remote-server. Опции параметров подключения таковы: —host, —password, —port, —protocol, —socket и —user. mysqlbinlog можно также использовать для чтения журналов, которые пишет подчиненный сервер при репликации. Журналы ретрансляции имеют тот же формат, что и обычные бинарные журналы. Бинарные журналы подробно описываются в разделе 4.8.4. mysqlbinlog поддерживает следующие опции: • —help, -?. Выводит страницу справки и завершает работу. • —databaэе=:имя_базы_данных, -d имя_базы_данных. Выводит информацию, касающуюся указанной базы данных (только для локальных журналов). • —force-read, -f. Принудительное чтение неизвестных событий в бинарном журнале. • —host=HM#_xocTa, -h имя_хоста. Читает бинарный журнал с сервера MySQL на указанном хосте. • — local-load=nyTb, -1 путь. Подготавливает локальные временные файлы в указанном каталоге для LOAD DATA INFILE. •
—of f set=N, -o N. Пропускает первые N позиций.
• —pas sword [=пароль], -р[пароль]. При подключении к серверу использует указанный пароль. Имейте в виду, что если вы применяете краткую форму этой опции (-р), то не должны оставлять пробел между названием опции и паролем. Если в командной строке пароль не указан, он будет запрошен интерактивно. • —port=HOMep_nopTa, -P номер_порта. Номер порта TCP/IP для подключения. • —position=N, - j N. Начинает читать бинарный журнал с позиции N. • —protocol={TCP I SOCKET | PIPE I MEMORY}. Сетевой протокол для подключения к серверу. Эта опция появилась в MySQL 4.1. • —read-from-remote-server, -R. Читает бинарный журнал с сервера MySQL. Любые параметры подключения игнорируются, если не указана эта опция. Параметры подключения задаются опциями —host, —password, —port, —protocol, —socket и —user. •
— r e s u l t - f Пе-пате=имя, -г имя. Направляет вывод в указанный файл.
• —short-form, -s. Выводит только операторы, содержащиеся в журнале, без дополнительной информации. • --socket=nyTb, -S путь. Файл сокета, используемый для подключения. • —иБег-имя_пользователя9 -и имя_пользователя. Указывает имя пользователя MySQL для подключения к серверу. • —version, -V. Выводит информацию о версии и завершает работу. Можно также установить следующие переменные с помощью опции —имя_переменной= значение: • open_files_limit. Указывает количество открытых файловых дескрипторов для резервирования.
482
Глава 7. Клиентские программы и утилиты MySQL
Можно перенаправить вывод программы mysqlbinlog на вход клиента mysql, чтобы выполнить операторы, содержащиеся в бинарном журнале. Это используется при восстановлении после аварий, если доступна старая резервная копия (см. раздел 4.6.1): shell> mysqlbinlog имя^хоста-Ып. 000001 | mysql или shell> mysqlbinlog имя_хоста-Ып. [0-9]* | mysql Вместо этого можно перенаправить вывод mysqlbinlog в текстовый файл, если необходимо перед выполнением модифицировать некоторые операторы (например, удалить некоторые операторы, которые вы не хотите исполнять по каким-то причинам). После редактирования файла можно выполнить содержащиеся в нем операторы, используя его в качестве входа для mysql. У mysqlbinlog есть опция --position, которая заставляет его печатать только те операторы, смещение которых от начала бинарного журнала больше или равно указанному значению. Если у вас есть более одного бинарного журнала, которые нужно выполнить на сервере MySQL, безопасный метод сделать это заключается в том, чтобы обработать их, используя единственное подключение к серверу. Приведем пример, демонстрирующий, что может оказаться небезопасным: shell> mysqlbinlog имя_хоста-Ып.000001 | mysql # ОПАСНО!! shell> mysqlbinlog имя_хоста-Ып.000002 | mysql # ОПАСНО!! Обработка бинарных журналов, использующих разные подключения к серверу, может вызвать проблемы, если первый из них содержит оператор CREATE TEMPORARY TABLE, а второй - оператор, который обращается к этой временной таблице. Когда выполнение первого процесса mysql завершится, сервер удалит временную таблицу. И когда второй процесс попытается обратиться к этой таблице, сервер сообщит об ошибке типа "неизвестная таблица". Чтобы избежать проблем подобного рода, используйте одно подключение для обработки содержимого всех необходимых бинарных журналов. Вот один из способов сделать это: shell> mysqlbinlog имя__хоста-Ып. 000001 имя^хоста-Ып. 000002 | mysql А вот другой подход: shell> mysqlbinlog имя_хоста-bin.000001 > /tmp/statements.sql shell> mysqlbinlog имя_хоста-Ып.000002 » /tmp/statements.sql shell> mysql -e "source /tmp/statements.sql" В MySQL 3.23 бинарный журнал не содержал данных для загрузки с помощью оператора LOAD DATA INFILE. Для выполнения этого оператора из файла бинарного журнала требовался исходный файл данных. Начиная с MySQL 4.0.14, бинарный журнал содержит эти данные, поэтому mysqlbinlog может генерировать вывод, который воспроизводит операцию LOAD DATA INFILE, без необходимости в исходном файле данных. mysqlbinlog копирует данные во временный файл и выдает оператор LOAD DATA INFILE, который ссылается на этот файл. Каталог по умолчанию, куда помещается этот файл, зависит от системы. Чтобы явно указать каталог, используйте опцию —local-load.
7.6. Центр управления MySQL — mysqlcc
483
Поскольку mysqlbinlog преобразует операторы LOAD DATA INFILE В LOAD DATA LOCAL INFILE (то есть, добавляет LOCAL), и клиент, и сервер, которые используются для обработки этих операторов, должны быть настроены так, чтобы разрешать LOCAL. |
Внимание!
Щ Щ Ш §и Щ
Временные файлы, которые создаются для LOAD DATA INFILE, не удаляются автоматически, поскольку они нужны д о т е х пор, пока в действительности не будут выполнены эти операторы. Вы должны удалить их самостоятельно после того, как отпадет необходимость в журнале. Э т и файлы можно найти в каталоге временных файлов под именами вроде оригинальное_имя__ фа ила - # - #.
В будущем мы решим эту проблему, позволив mysqlbinlog подключаться непосредственно к серверу mysqld. Тогда будет можно автоматически безопасно удалять файлы журналов немедленно после выполнения операторов LOAD DATA INFILE. До версии MySQL 4.1 утилита mysqlbinlog не могла готовить вывод, подходящий для mysql, если бинарный журнал содержал смешанные операторы, полученные от разных клиентов, которые использовали одноименные временные таблицы. В MySQL 4.1 это исправлено.
7.6. Центр управления MySQL — mysqlcc Центр управления MySQL, mysqlcc, - это не зависящая от платформы клиентская программа, представляющая графический интерфейс пользователя к серверу базы данных MySQL. Она поддерживает интерактивную работу, включая выделение цветом синтаксических конструкций и табуляцию. Обеспечивает управление базами данных и таблицами, а также задачи администрирования сервера. mysqlcc не входит в состав стандартного дистрибутива MySQL, но может быть загружена отдельно с http://dev.mysql.com/downloads/. В настоящее время mysqlcc работает на платформах Windows и Linux. Запустите mysqlcc, дважды щелкнув на ее пиктограмме в графической среде. Для запуска из командной строки введите следующую команду: shell> mysqlcc [опции] mysqlcc поддерживает следующие опции: •
--help, -?. Выводит справочное сообщение и завершает работу.
•
—blocking-queries, -b. Использует блокирующие запросы.
•
—compress, -С. Сжимает всю информацию, пересылаемую между клиентом и сервером, если оба поддерживают сжатие. • —connection-name=HM#, -с имя. Синоним опции —server. •
—databaзе=имя_базы_данных, -d имя_базы_данных. База данных для использования. В основном применяется в файле конфигурации.
•
--history-size=#, -H #. Длина списка хронологии в окне запросов.
•
--host=HM#_xocTa, -h имя_базы_данных. Подключается к серверу MySQL на указанном хосте. • —local-infile[ = {0|l}]. Включает и отключает свойство LOCAL для LOAD DATA INFILE. Если ничего не указано, опция включает LOCAL. Для явного включения и
484
Глава 7. Клиентские программы и утилиты MySQL отключения следует использовать —local-infile=0 или —local-infile=l. Включение LOCAL не имеет эффекта, если сервер не поддерживает его.
• —pass word [-пароль], -р[пароль]. При подключении к серверу использует указанный пароль. Имейте в виду, что если вы указываете краткую форму этой опции (-р), то не должны оставлять пробел между названием опции и паролем. Если в командной строке пароль не указан, он будет запрошен интерактивно. • —plugins_path=MM#, -g имя. Указывает путь к каталогу, в котором содержатся подключаемые модули центра управления MySQL. • —port=HOMep_nopTa, -P номер^порта. Номер порта TCP/IP для подключения. • —query, -q. Открывает при запуске окно запросов. • —register, -r. Открывает при запуске диалог Register Server (Регистрация сервера). • — server=HM*, -s имя. Имя подключения центра управления MySQL. • —socket=nyTb, -S путь. Файл сокета, используемый для подключения. • —syntax, -у. Включает выделение цветом синтаксиса и автоматическое завершение. • —syntax_f Пе=имя, -Y имя. Файл синтаксиса для автоматического завершения. • —translationj?ath=HM#, -T имя. Указывает путь к каталогу, в котором находятся файлы переводов центра управления MySQL. •
—изег=имя__пользователя, -и имя_пользователя. Указывает имя пользователя MySQL для подключения к серверу.
• —version, -V. Выводит информацию о версии и завершает работу. Можно также установить следующие переменные с помощью опции —имя_переменной= значение: • connect_timeout. Таймаут подключения в секундах (по умолчанию 0). • max_allowed_packet. Максимальная длина пакета для отправки или приема с сервера (по умолчанию 16 Мбайт). • max_join_size. Автоматический предел на количество строк в объединении при использовании --safe-updates (по умолчанию 1 000 000). • net_buffer_length. Размер буфера для подключений через TCP/IP и сокеты (по умолчанию 16 Кбайт). • select_limit. Автоматический предел для оператора SELECT при использовании —safe-updates (по умолчанию 1 000). Существует возможность устанавливать переменные, используя синтаксис —set-variable=имя_переменной=значение или -0 имя_переменной=значение. Однако, начиная с MySQL 4.0, этот синтаксис считается устаревшим.
7.7. Программа обслуживания и восстановления таблиц mysqlcheck
485
7.7. Программа обслуживания и восстановления таблиц mysqlcheck Клиентская программа mysqlcheck проверяет и восстанавливает таблицы MylSAM. Она также может оптимизировать и анализировать таблицы, mysqlcheck доступна, начиная с MySQL 3.23.38. mysqlcheck по функциональному назначению похожа на myisamchk, но работает иначе. Основное отличие состоит в том, что mysqlcheck должна использоваться при запущенном сервере mysqld, в то время как myisamchk - нет. Выгода от применения mysqlcheck в том, что для проверки и восстановления таблиц не надо останавливать сервер. mysqlcheck использует SQL-операторы CHECK TABLE, REPAIR TABLE, ANALYZE TABLE и OPTIMIZE TABLE удобным для пользователя способом. Она определяет, какой оператор необходимо применять для выполнения нужной операции, затем отправляет его серверу на исполнение. Существуют три основных способа запуска mysqlcheck: shell> mysqlcheck [опции] имя_6азы_датшх [таблицы] shell> raysqlcheck [опции] —databases база_данных1 [база__данных2 база_данныхЗ...] shell> mysqlcheck [опции] —all-databases Если вы не указываете никаких таблиц или используете опции --databases либо —all-databases, будут проверены все базы данных. mysqlcheck имеет некоторые свойства, отличающие ее от других клиентов. Поведение проверки таблиц по умолчанию (—check) может быть изменено переименованием самой программы. Если вам нужен инструмент, который будет по умолчанию восстанавливать таблицы, то вы можете просто скопировать программу mysqlcheck под именем mysqlrepair или создать символическую ссылку с именем mysqlrepair, указывающую на mysqlcheck. Если вы запустите mysqlrepair, она будет по умолчанию восстанавливать таблицы. Следующие имена можно использовать для изменения поведения mysqlcheck по умолчанию: mysqlrepair По умолчанию используется опция —repair, mysqlanalyze По умолчанию используется опция —analyze, mysqloptimize По умолчанию используется опция —optimize. mysqlcheck поддерживает следующие опции: •
—help, -?. Выводит справочное сообщение и завершает работу.
•
—all-databases, -А. Проверяет все таблицы во всех базах данных.
•
—all-in-1, - 1 . Вместо того, чтобы выполнять операторы для каждой таблицы, выполняет отдельный оператор для каждой базы данных, в которой нужно проверить все таблицы.
• —analyze, -а. Анализирует таблицы. • --auto-repair. Если проверяемая таблица повреждена, автоматически восстанавливает ее. Все необходимые операции по восстановлению выполняются после того, как все таблицы будут проверены. •
—character-sets-dir=nyTb. Каталог, в котором установлен символьный набор. См. раздел 4.7.1.
486
Глава 7. Клиентские программы и утилиты MySQL
•
--check, -с. Проверяет таблицы на предмет ошибок.
•
—check-only-changed, -С. Проверяет только те таблицы, которые изменялись с момента последней проверки или не были корректно закрыты.
•
—compress. Сжимает всю информацию, пересылаемую между клиентом и сервером, если оба поддерживают сжатие.
•
—databases, -В. Обрабатывает все таблицы в указанных базах данных. С этой опцией все аргументы рассматриваются как имена баз данных, а не таблиц.
•
—debug[=опции_отладки], -# [опции_отладки]. Записывает журнал отладки. Обычно строка опции_отладки имеет формат ' d: t : о, имя_файла'.
•
—default-character-set=Ha6op. Использует набор в качестве набора символов по умолчанию. См. раздел 4.7.1.
•
—extended, -e. Если использовать эту опцию при проверке таблиц, это гарантирует, что они будут на 100% исправны и непротиворечивы, но проверка потребует длительного времени. Если использовать эту опцию при восстановлении таблиц, будет выполняться расширенное восстановление, которое не только потребует длительного времени, но и может сгенерировать огромное количество "мусорных" строк.
•
--fast, -F. Проверяет только те таблицы, которые не были корректно закрыты.
•
—force, -f. Продолжает работу даже после возникновения ошибок SQL.
•
—host=HM*_xocTa, -h имя_хоста. Подключается к серверу MySQL на указанном хосте.
•
—medium-check, -m. Выполнить проверку, которая быстрее, чем при операции —extended. При этом находятся 99,99% всех ошибок, что может быть достаточно хорошо в большинстве случаев.
•
—optimize, -о. Оптимизировать таблицы.
•
--password[^пароль], -р[пароль]. При подключении к серверу использует указанный пароль. Имейте в виду, что если вы указываете краткую форму этой опции (-р), то не должны оставлять пробел между названием опции и паролем. Если в командной строке пароль не указан, он будет запрошен интерактивно.
•
—port=номер_порта, -Р номер_порта. Номер порта TCP/IP для подключения.
•
—protocol={TCP | SOCKET | PIPE | MEMORY}. Сетевой протокол для подключения к серверу. Эта опция введена в MySQL 4.1.
•
—quick, -q. Если использовать эту опцию при проверке таблиц, это предотвращает сканирование строк для поиска неправильных ссылок. Это наиболее быстрый способ проверки. Если использовать эту опцию при восстановлении таблиц, программа пытается восстанавливать только индексное дерево. Самый быстрый способ восстановления.
•
—repair, -r. Выполняет восстановление, которое может исправить почти все, кроме уникальных ключей, которые по каким-то причинам оказались неуникальными.
•
—silent, -s. Режим минимального количества сообщений. Выдает в выходной поток только сообщения об ошибках, если они случаются.
7.8. Программа резервного копирования баз данных mysqldump
487
•
—socket=nyTb, -S путь. Файл сокета, используемый для подключения.
•
—tables. Перекрывает опцию --databases или -В. Все аргументы трактуются как имена таблиц.
•
—useг=имя_лользователя, -и имя_пользователя. Указывает имя пользователя MySQL для подключения к серверу.
•
—verbose, -v. Режим расширенных сообщений. Выводит информацию о стадиях функционирования программы.
•
--version, -V. Выводит информацию о версии и завершает работу.
7.8. Программа резервного копирования баз данных mysqldump Клиентская программа mysqldump может использоваться для выгрузки дампа базы данных или набора баз данных с целью получения резервной копии или для переноса данных на другой SQL-сервер (не обязательно MySQL). Дамп содержит SQL-операторы, необходимые для создания таблиц и/или наполнения их данными. Если вы создаете резервную копию на сервере, то вам стоит рассмотреть вопрос применения mysqlhotcopy вместо mysqldump. См. раздел 7.9. Существует три основных способа запуска mysqldump: s h e l l > mysqldump [опции] имя_базы_данных [таблицы] shell> mysqldurap [опции] —databases база_данных1 [база_данных2 база_данныхЗ...] shell> mysqldurap [опции] —all-databases Если не указывать имен таблиц либо использовать опцию —databases или — a l l databases, будет выгружен полный дамп базы данных. Чтобы получить полный список опций, которые поддерживает ваша версия mysqldump, запустите mysqldump —help. Если вы запускаете mysqldump без опций —quick или —opt, mysqldump полностью загружает в память результирующий набор, прежде чем выгружать его в дамп. Это может стать причиной проблем, если выгружается большая база данных. Начиная с MySQL 4.1, опция —opt включена по умолчанию, но может быть отключена с помощью --skip-opt. Если вы пользуетесь последней копией программы mysqldump и собираетесь генерировать дамп, который должен будет загружаться на очень старый сервер MySQL, указывать опции —opt и -е не следует. Числовые значения, выходящие за пределы допустимых, такие как inf и -inf, равно как и NaN (not-a-number), выгружаются программой mysqldump как NULL. Вы можете увидеть это, воспользовавшись следующей простой таблицей: mysql> mysql> mysql> mysql>
inf -inf
CREATE TABLE t (f DOUBLE); INSERT INTO t VALUES(le+111111111111111111111); INSERT INTO t V A L U E S ( - l e l l l l l l l l l l l l l l l l l l l l l ) ; SELECT f FROM t ;
Глава 7. Клиентские программы и утилиты MySQL Для этой таблицы mysqldump генерирует следующий вывод: — Дамп данных таблицы Ч % INSERT INTO t VALUES (NULL); INSERT INTO t VALUES (NULL); Такое поведение приводит к тому, что если выгрузить в дамп и затем восстановить эту таблицу, то содержимое новой таблицы будет отличаться от содержимого оригинальной таблицы. mysqldump поддерживает следующие опции: •
—help, -?. Выводит справочное сообщение и завершает работу.
•
—add-drop-table. Перед каждым оператором CREATE TABLE добавляется DROP TABLE.
•
—add-locks. Окружает дамп каждой таблицы операторами LOCK TABLE и UNLOCK TABLE. Это ускоряет вставку строк, когда дамп загружается в базу. См. раздел 6.2.12.
•
--all-databases, -А. Выгружает все таблицы из всех баз данных. Это то же самое, что применение опции —databases с указанием имен всех баз данных в командной строке.
•
—all-keywords. Позволяет создавать имена столбцов, совпадающие с ключевыми словами. Это работает, если каждое такое наименование столбцы сопровождать префиксом - именем таблицы.
•
—comments [ = {011} ]. Если установлено в 0, то дополнительная информация в дампе подавляется. Это касается номера версии программы, версии сервера, имени хоста. Опция --skip-comments дает тот же эффект, что и --comments=0. Значение по умолчанию равно 1, что означает не подавлять дополнительную информацию. Опция появилась в MySQL 4.0.17.
•
—compatible-name=HM*. Генерирует вывод, который совместим с другими системами управления базами данных или более старыми версиями сервера MySQL. Значением аргумента имя может быть mysql323, mysql40, postgresql, oracle, mssql, db2, sapdb, no_key_options, no_table_options или no_field_options. Чтобы использовать несколько значений, разделяйте их запятыми. Значение этих опций имеет тот же смысл, как и соответствующие опции, устанавливающие SQLрежим сервера. См. раздел 4.2.2. Эта опция требует сервера версии MySQL 4.1.0 или выше. В более старых версиях она не делает ничего.
•
—complete-insert, -с. Использует полные операторы INSERT, включающие имена столбцов.
•
—compress, -С. Сжимает всю информацию, пересылаемую между клиентом и сервером, если оба поддерживают сжатие.
•
—create-options. Включает все специфичные для MySQL опции оператора CREATE TABLE. До версии MySQL 4.1.2 вместо этой опции использовалась —all.
7.8. Программа резервного копирования баз данных mysqldump
489
• --databases, -В. Для выгрузки определенных баз данных. Обратите внимание на отличия в применении. В этом случае никакие таблицы не указываются. Все аргументы командной строки трактуются как имена баз данных. Оператор USE имя_базы_данных включается в вывод перед каждой новой базой данных. • —debug [=опции_отладки], -# [опции_отладки]. Записывает журнал отладки. Обычно строка опции_отладки имеет формат ' d: t : о, имя_файла'. • —default-character-set=Ha6op. Использует набор в качестве набора символов по умолчанию. См. раздел 4.7.1. Если не указан конкретный набор, начиная с MySQL 4.1.2, используется utf 8; в более старых версиях применялся lati.nl. •
—delayed. Вставляет строки, используя оператор INSERT DELAYED.
• —delete-master-logs. На главном сервере репликации удаляет файлы бинарных журналов после выполнения операции выгрузки дампа. Опция автоматически включает — f i r s t - s l a v e . Была добавлена в MySQL 3.23.57 (для MySQL 3.23) и в MySQL 4.0.13 (для MySQL 4.0). • —disable-keys, -К. Для каждой таблицы окружить оператор INSERT фрагментами / * ! 40000 ALTER TABLE имя^таблицы DISABLE KEYS */ и / * ! 40000 ALTER TABLE
имя_таблицы ENABLE KEYS */. Это ускоряет загрузку данных из дампа на сервер MySQL, так как в этом случае индексы создаются после загрузки всех данных. Эффективно только для таблиц My ISAM. —extended-insert, -e. Использует многострочный синтаксис INSERT, включающий несколько списков VALUES. Это уменьшает размер дампа и ускоряет последующую загрузку. • —fields-terminates-by=... —fields-enclosed-by=... —fields-optionally-enclosed-by=... —fields-escaped-by=... —fields~terminated-by=... Эта опция применяется совместно с опцией -т и имеет то же значение, что и соответствующие КОНСТРУКЦИИ В LOAD DATA INFILE.
•
•
— f i r s t - s l a v e , -x. Блокирует все таблицы во всех базах данных.
• —flush-logs, -F. Сбрасывает буферы журналов сервера перед началом выгрузки дампа. Следует иметь в виду, что если эта опция применяется совместно с — a l l databases (или -А), буферы журналов сбрасываются для каждой из выгружаемых баз данных. •
—force, -f. Продолжает работу, даже если в процессе выгрузки произошла ошибка SQL.
• —host=HM*_xocTa, -h имя_хоста. Выгружает дамп с сервера MySQL, находящегося на указанном хосте (по умолчанию localhost). • —lock-tables, -1. Блокирует все таблицы перед началом выгрузки дампа. Таблицы блокируются с помощью READ LOCK, чтобы разрешить параллельные вставки в случае таблиц My ISAM. Обратите внимание, что при выгрузке нескольких баз данных блокируются таблицы для каждой базы по отдельности. Поэтому использование этой опции не гарантирует,
490
Глава 7. Клиентские программы и утилиты MySQL что таблицы в файле дампа будут логически согласованы между базами данных. Таблицы разных баз могут быть выгружены полностью в разном состоянии.
•
—master-data. Эта опция подобна —first-slave, но также генерирует оператор CHANGE MASTER TO, который заставит подчиненный сервер репликации начинать с правильной позиции в бинарном журнале главного сервера, если вы используете этот SQL-дамп главного сервера для настройки подчиненного.
•
—no-create-db, -п. Эта опция подавляет операторы CREATE DATABASE /* 132312 IF NOT EXISTS*/ имя_базы_данных, которые в противном случае включаются в дамп, если были указаны опции —databases или —all-databases.
•
—no-create-info, -t. He пишет в дамп операторы CREATE TABLE, которые пересоздают каждую выгружаемую таблицу.
•
—no-data, -d. He выводит никакой информации из строк таблицы. Это полезно, если необходимо получить дамп структур таблиц.
•
—opt. Эта опция является сокращением; она имеет тот же смысл, что и сочетание —quick —add-drop-table —add-locks —create-options —disable-keys —extended-insert --lock-tables. Опция позволяет выполнить операцию выгрузки дампа быстро и сгенерирует файл, который может быть быстро загружен на сервер MySQL. Начиная с MySQL 4.1, --opt используется по умолчанию, но может быть отключена с помощью —skip-opt. Чтобы отключить только некоторые из опций, включаемых —opt, нужно использовать соответствующую форму —skip. Например, —skip-add-drop-table или —skip-quick.
•
— password [^пароль], -р[пароль]. При подключении к серверу использует указанный пароль. Имейте в виду, что если вы указываете краткую форму этой опции (-р), то не должны оставлять пробел между названием опции и паролем. Если в командной строке пароль не указан, он будет запрошен интерактивно.
•
—рогt=HOMep_nopта, -Р номер__порта. Номер порта TCP/IP для подключения.
•
—protocol={TCP I SOCKET | PIPE | MEMORY}. Сетевой протокол для подключения к серверу. Эта опция введена в MySQL 4.1.
•
—quick, -q. Эта опция применима для выгрузки больших таблиц. Она заставляет mysqldump извлекать строки для дампа по одной, вместо того чтобы извлечь сразу весь результирующий набор и поместить его в буфер в памяти перед записью в дамп.
•
--quote-names, -Q. Помещает имена баз данных, таблиц и столбцов в кавычки ' N '. Если SQL-режим сервера включает опцию ANSI_QUOTES, имена помещаются в двойные кавычки. Начиная с MySQL 4.1.1, опция —quote-names включена по умолчанию.
•
—result-file=$awi, -r файл. Направляет вывод в указанный файл. Эта опция должна использоваться в Windows, поскольку она предохраняет символ новой строки с \п' от преобразования в '\г\п' (перевод строки, возврат каретки).
•
—single-transaction. Эта опция выдает SQL-оператор BEGIN перед выгрузкой данных с сервера в дамп. В основном она применима с таблицами innoDB и уровнем изоляции транзакций READ COMMITED, так как в этом режиме она выгружает базу данных в непротиворечивом состоянии, в котором база была на момент BEGIN, без блокировки других приложений.
7.8. Программа резервного копирования баз данных mysqldump
491
При использовании этой опции вы должны помнить, что только транзакционные таблицы будут выгружены в согласованном состоянии. Например, все таблицы MylSAM или HEAP в процессе выгрузки с этой опцией могут изменять свое состояние. Опция —single-transaction была добавлена в версии MySQL 4.O.2. Эта опция и —lock-tables являются взаимоисключающими, поскольку LOCK TABLES подразумевает неявную фиксацию всех незавершенных транзакций.
i
•
—socket=nyTb, -S путь. Файл сокета, используемый для подключения к localhost (хост по умолчанию).
•
—tab=nyrb, -T путь. Генерирует файл данных с разделителями-табуляциями. Для каждой выгружаемой в дамп таблицы mysqldump создает файл имя_таблицы. sql, который содержит оператор CREATE TABLE, и файл имя_таблицы. txt, который содержит данные. Значение опции - это имя каталога, в который должны сохраняться эти файлы. По умолчанию файлы данных .txt форматируются с использованием символа табуляции для разделения столбцов и символа новой строки для разделения строк таблицы. Формат может быть переопределен явно с помощью опций —f ieldsххх и —lines-xxx.
На заметку!
j? Эта опция может использоваться, только если mysqldump запускается на той же машине, на коЩ торой работает mysqld. Вы должны использовать учетную запись MySQL с привилегией FILE, a Ж сервер должен иметь право записи в каталог, указанный в значении опции.
•
--tables. Перекрывает опцию --databases или -В. Все аргументы, следующие за этой опцией, трактуются как имена таблиц.
•
—изег=имя_пользователя, -и имя__пользователя. Указывает имя пользователя MySQL для подключения к серверу.
•
--verbose, -v. Режим расширенных сообщений. Выводит информацию о ходе работы программы.
•
—version, -V. Выводит информацию о версии и завершает работу.
•
—where='условие_т*/пеге', -w у условие_where*. Выгружает только те строки, которые удовлетворяют заданному условию WHERE. Имейте в виду, что кавычки вокруг аргумента обязательны, если он включает в себя пробелы и символы, воспринимаемые вашим командным интерпретатором как специальные. Примеры: "—where=user='jimf'" "-wuserid>l" "-wuserickl"
•
—xml, -X. Записывает дамп в виде правильного XML-кода.
Можно также установить следующие переменные с помощью опции —имя_переменноРг= значение: • max_allowed_packet. Максимальный размер буфера для клиент-серверных коммуникаций. Значение переменной могло составлять до 16 Мбайт в версиях MySQL до 4.0 и до 1 Гбайт - в версиях от 4.0 и выше.
492
Глава 7. Клиентские программы и утилиты MySQL При генерации многострочных операторов вставки (при указании опции --extended-insert или --opt), mysqldump создает строки длиной до max_allowed_packet. Если вы увеличиваете значение этой переменной, то должны убедиться, что переменная max_allowed_packet на сервере имеет, по меньшей мере, такое же значение.
• n e t b u f fer_length. Начальный размер буфера для клиент-серверных коммуникаций. Существует также возможность установки значений переменных с использованием синтаксиса —set-var 1аЫе=имя__переменной=значение или -О имя_переменной= значение. Однако, начиная с версии MySQL 4.0, этот синтаксис считается устаревшим. Вероятно, наиболее часто mysqldump применяется для полной выгрузки всех баз данных: shell> mysqldump —opt имя__бавыжданных > backup-file. sql Загрузить дамп обратно на сервер можно так: shell> mysql имя_базы_данных < backup-file.sql или shell> mysql -e "source /путь-к-резервяым-колиям/backup-file. sql" имя_базы__данных mysqldump также очень удобен для наполнения базы данными посредством копирования данных с одного сервера MySQL на другой: shell> mysqldump —opt имя_базы_данных | mysql —hosЬ=удаленный-хост -С \ имя_ б а зы__да иных
Можно выгрузить дамп нескольких баз одной командой: shell> mysqldump —databases имя_базы_данных1 [имя_базы_данных2 . . . ] > \ my__databases. sql Если вы хотите выгрузить все базы данных, укажите опцию —all-databases: shell> mysqldump —all-databases > all_databases.sql Дополнительную информацию о создании резервных копий можно найти в разделе 4.6.1.
7.9. Программа резервного копирования базы данных mysqhotcopy mysqhotcopy - это сценарий на языке Perl, который использует LOCK TABLES, FLUSH TABLES и ср либо scp для быстрого создания резервной копии базы данных. Это самый быстрый способ получить копию базы данных или отдельных таблиц, однако он может применяться только на той же машине, где расположены каталоги баз данных. mysqhotcopy работает только для резервного копирования таблиц My ISAM и ISAM в среде Unix и, начиная с MySQL 4.0.18, в среде NetWare. shell> mysqlhotcopy имя_базы_данных [/путь/к/новому_каталогу) shell> mysqlhotcopy имя_базы_данных_1...имя_базы_данных_п /путь/к/новому_каталогу shell> mysqlhotcopy имя_базы_данных./регулярное_выражение/ mysqhotcopy поддерживает следующие опции:
7.10. Программа импорта данных mysqlimport
493
•
— h e l p , - ? . Выводит справочное сообщение и завершает работу.
•
—allowold. He прерывает работу, если целевой файл уже существует (переименовывается с добавлением суффикса _old).
•
—сЬескро1^=имя_базы_даняых.имя_таблицы. Вставляет контрольные точки в указанной таблице имя_базы_данных. имя_таблицы.
•
—debug. Разрешает вывод отладочной информации.
•
—dryrun, -n. Сообщает о действиях без их выполнения.
•
— f l u s h l o g . Сбрасывает буферы журналов после того, как все таблицы заблокированы.
•
—keepold. He удаляет предыдущий (переименованный) целевой файл после окончания работы.
•
—method=#. Метод копирования (ср или scp).
•
— n o i n d i c e s . He включает в резервную копию индексные файлы. Это делает ее меньше и быстрее. Индексы могут быть пересозданы позже с помощью myisamchk - r q или isamchk -rq.
•
—password[=лароль], -р[пароль]. При подключении к серверу использует указанный пароль. Имейте в виду, что в отличие от других клиентов MySQL, эта опция должна быть указана обязательно.
•
—port=HOMep_nopra, -P номер_ пор та. Номер порта TCP/IP для подключения.
•
— q u i e t , -q. Молчаливый вывод, за исключением случаев возникновения ошибок.
•
--гедехр=выражеяие. Копирует все базы данных с именами, соответствующими регулярному выражению выражение.
•
—socket=nyTb, -S путь. Файл сокета Unix, используемый для подключения.
•
—suf f ±х=строка. Суффикс имен копируемых баз данных.
•
— tmpdir=nyTb. Каталог временных файлов (вместо /tmp).
•
—изег=имя_пользователя, -и имя__пользователя. Указывает имя пользователя MySQL для подключения к серверу.
mysqhotcopy читает группы опций [ c l i e n t ] и [mysqhotcopy] из конфигурационных файлов. Чтобы выполнить mysqhotcopy, вы должны иметь доступ к файлам таблиц, которые собираетесь копировать, привилегию SELECT для этих таблиц и привилегию RELOAD (чтобы иметь возможность выполнить FLUSH TABLES). Воспользуйтесь p e r l d o c для просмотра дополнительной документации по mysqhotcopy:
shell> perldoc mysqlhotcopy
7.10. Программа импорта данных mysqlimport Клиентская программа mysqlimport предоставляет интерфейс командной строки для SQL-оператора LOAD DATA INFILE. Большинство опций mysqlimport непосредственно отображаются на конструкции оператора LOAD DATA INFILE.
494
Глава 7. Клиентские программы и утилиты MySQL
Вызов mysqlimport выглядит следующим образом: shell> mysqlimport [опции] жя_базы_данных текстовый^файл! [текстовый_файл2...] Для каждого текстового файла, перечисленного в командной строке, mysqlimport удаляет расширение и использует результат для определения имени таблицы, в которую нужно импортировать его содержимое. Например, файлы с именами p a t i e n t . t x t , p a t i e n t . t e x t и p a t i e n t все будут импортированы в таблицу p a t i e n t , mysqlimport поддерживает следующие опции: •
— h e l p , - ? . Выводит справочное сообщение и завершает работу.
•
—colитпэ=список_столбцов, -с список^столбцов. Задает список столбцов, разделенных запятыми. Порядок имен столбцов определяет соответствие между столбцами файла данных и столбцами таблицы.
•
—compress, -С. Сжимает всю информацию, пересылаемую между клиентом и сервером, если оба поддерживают сжатие.
•
—debug [=опции_отладки], -# [опции__отладки]. Записывает журнал отладки. Обычно строка опции_отладки имеет формат ' d: t : о, имя_файла'.
•
— d e l e t e , -D. Очищает таблицу перед импортом данных.
•
—fields-terminates-by=... —fields-enclosed-by=... —fields-optionally-enclosed-by=... —fields-escaped-by=... —fields-terminated-by=... Эта опция применяется совместно с опцией -т и имеет то же значение, что и соответствующие конструкции В LOAD DATA INFILE.
•
— f o r c e , -f. Игнорирует ошибки. Например, если таблица для отдельного текстового файла не существует, продолжает обрабатывать остальные файлы. Без этой опции при возникновении ошибки работа немедленно завершается.
•
—host=HM#_xoccra, -h имя_хоста. Импортирует данные на сервер MySQL на указанном хосте (по умолчанию l o c a l h o s t ) .
•
— i g n o r e , - i . См. описание опции — r e p l a c e .
•
— i g n o r e - l i n e s = n . Игнорирует первые л строк файла данных.
•
— l o c a l , -L. Читает входные файлы с клиента. По умолчанию предполагается, что текстовые файлы находятся на сервере, если вы подключаетесь к l o c a l h o s t (хост по умолчанию).
•
- - l o c k - t a b l e s , - 1 . Блокирует по записи все таблицы перед обработкой текстовых файлов. Это гарантирует, что все таблицы будут синхронизированы на сервере.
•
—password[=пароль], -р[пароль]. При подключении к серверу использует указанный пароль. Имейте в виду, что если вы указываете краткую форму этой опции (-р), то не должны оставлять пробел между названием опции и паролем. Если в командной строке пароль не указан, он будет запрошен интерактивно.
•
— рог1=номер_портаг -Р номер_порта. Номер порта TCP/IP для подключения.
•
—protocol={TCP I SOCKET | PIPE | MEMORY}. Сетевой протокол для подключения к серверу. Эта опция введена в MySQL 4.1.
7.11.
Программа просмотра баз данных, таблиц и столбцов mysqlshow
495
•
--replace, -г. Опции —replace и —ignore управляют поведением при загрузке записей, которые дублируют существующие в таблице по значению уникальных ключей. Если указать --replace, новые строки заменяют существующие с тем же значением уникального ключа. Если указать —ignore, дублированные строки пропускаются. Если не указывать ни одну из этих опций, то при возникновении ошибки, связанной с обнаружением дублированного значения уникального ключа, остаток файла игнорируется.
•
—silent, -s. Режим минимального количества сообщений. Генерирует вывод только при возникновении ошибок.
•
—socket=nyrb, -S путь. Файл сокета, используемый для подключения.
•
—изег=имя_пользователя, -и имя__пользователя. Указывает имя пользователя MySQL для подключения к серверу.
•
—verbose, -v. Режим расширенных сообщений. Выводит информацию о ходе работы программы.
•
—version, -V. Выводит информацию о версии и завершает работу.
Ниже представлен пример сеанса работы mysqlimport: shell> mysql -e 'CREATE TABLE imptest(id INT, n VARCHAR(30))' shell> ed a 100 Max Sydow 101 Count Dracula
test
w imptest.txt 32 q shell> od -c imptest.txt 0000000 0000020 0000040
1 0 0 \ t M 1 \ t C o u n
a t
x
S D
y r
d
o a
w c
u
l
\ n1 0 a \ n
shell> mysqlimport —local test imptest.txt test.imptest: Records: 2 Deleted: 0 Skipped: 0 Warnings: 0 shell> mysql -e 'SELECT * FROM imptesf test I id + I 100 I 101 +
7.11.
|n I + + | Max Sydow | | Count Dracula | + +
Программа просмотра баз данных, таблиц и столбцов mysqlshow
Клиентская программа mysqlshow может использоваться для быстрого просмотра имеющихся на сервере баз данных, их таблиц, столбцов таблиц и индексов. mysqlshow предоставляет интерфейс командной строки к некоторым SQL-операторам SHOW. Та же информация может быть получена непосредственным вызовом этих операторов, например, из программы mysql.
496
Глава 7. Клиентские программы и утилиты MySQL
Вызов mysqlshow выглядит следующим образом: shell> mysqlshow [опции] [имя_базы_данных [имя_таблицы [имя_столбца]]] • Если не указана ни одна база данных, показываются все. • Если не указана ни одна таблица, показываются все таблицы в базе данных. • Если не указан ни один столбец, показываются все соответствующие столбцы таблицы вместе с их типами. Имейте в виду, что в новейших версиях MySQL вы увидите только те базы, таблицы или столбцы, для доступа к которым у вас имеются соответствующие привилегии. Если последний аргумент содержит шаблонные символы SQL или командной оболочки ('*','?','%' или '_'), показываются только те имена, которые соответствуют шаблону. Если имя базы данных содержит знаки подчеркивания, перед ними должны помещаться обратные косые черты (некоторые оболочки Unix также требуют этого), чтобы получить правильный список таблиц и столбцов. Символы '*' и '?' преобразуются в шаблонные символы SQL '%' и '_'. Это может привести к некоторым недоразумениям, если вы захотите вывести столбцы таблиц с символом '_' в имени, поскольку в этом случае mysqlshow покажет только имена таблиц, соответствующие шаблону. Это легко исправить, добавив дополнительный символ '%' в конец командной строки как отдельный аргумент. mysqlshow поддерживает следующие опции: •
--help, -?. Выводит справочное сообщение и завершает работу.
•
—character-sets-dir=nyTb. Каталог, в котором установлен символьный набор. См. раздел 4.7.1. • —compress, -С. Сжимает всю информацию, пересылаемую между клиентом и сервером, если оба поддерживают сжатие. • —debug [=опции_отладки], -# [опции_отладки]. Записывает журнал отладки. Обычно строка опции_отладкиимеет формат 'd: t:о,имя_файла'. •
—default-character-set=на б ор. Использует набор в качестве набора символов по умолчанию. См. раздел 4.7.1. • ~host=MM£_xocTa, -h имя_хоста. Подключается к серверу MySQL на указанном хосте. •
—keys, -к. Показывает индексы таблиц.
•
--password[=пароль], -р[ пароль]. При подключении к серверу использует указанный пароль. Имейте в виду, что если вы указываете краткую форму этой опции (-р), то не должны оставлять пробел между названием опции и паролем. Если в командной строке пароль не указан, он будет запрошен интерактивно. • —port=HOMep_nopra, -P номер_порта. Номер порта TCP/IP для подключения. •
--protocol={TCP | SOCKET | PIPE | MEMORY}. Сетевой протокол для подключения к серверу. Эта опция введена в MySQL 4.1. • —socket=nyib, -S путь. Файл сокета, используемый для подключения. • •
—status, -i. Показывает дополнительную информацию о каждой таблице.
—изег=имя_пользователя, -и имя_пользователя. Указывает имя пользователя MySQL для подключения к серверу. • —verbose, -v. Режим расширенных сообщений. Выводит информацию о ходе работы программы. Эту опцию можно указать несколько раз, что приводит к большему и большему объему вывода.
7.13. Утилита замены строк replace •
497
—version, -V. Выводит информацию о версии и завершает работу.
7.12. Утилита объяснения кодов ошибок perror Для большинства системных ошибок в дополнение к внутреннему сообщению MySQL показывает системный код ошибки в одном из следующих стилей: сообщение ... (errno: #) сообщение ... (Errcode: #) Узнать, что означает код ошибки можно либо заглянув в документацию по системе, либо воспользовавшись утилитой perror. perror печатает описание кода системной ошибки или кода ошибки механизма хранения. Вызов perror осуществляется следующим образом: s h e l l > perror [опции] код_ошибки . . .
Пример: shell> perror 13 64 Error code 13: Permission denied Error code 64: Machine is not on the network Имейте в виду, что значение сообщений о системных ошибках может зависеть от вашей операционной системы. Данный код ошибки может означать разные вещи в различных операционных системах.
7.13. Утилита замены строк replace Утилита replace заменяет строки в файлах или в стандартном потоке ввода. Она использует механизм конечного автомата для поиска самой длинной подходящей строки. Эту утилиту можно использовать для того, чтобы менять местами фрагменты строк. Например, следующая команда меняет местами а и b в заданных файлах f i l e l и f ile2: shell> replace a b b a — f i l e l f i l e 2 ... Используйте опцию — для того, чтобы отметить, где завершается список заменяемых строк и начинается список файлов. Любой файл, указанный в командной строке, модифицируется на месте, поэтому вам может понадобиться создать копию исходного файла, прежде чем преобразовывать его. Если никаких файлов в командной строке не указано, replace читает из стандартного ввода и пишет в стандартный вывод. В этом случае опция — не нужна. Утилита replace используется в msql2mysql и поддерживает следующие опции: •
-?, - I . Выводит справочное сообщение и завершает работу.
•
-# опции_отладки. Записывает журнал отладки. Обычно строка опции_отладки имеет формат ' d: t : о, имя_файла'.
•
-s. Режим минимального количества сообщений. Печатает минимум информации о том, что делает программа.
•
-v. Режим расширенных сообщений. Печатает больший объем информации о том, что делает программа.
•
-V. Выводит информацию о версии и завершает работу.
8
Механизмы хранения и типы таблиц в MySQL
M
ySQL поддерживает несколько механизмов хранения, посредством которых осуществляется управление таблицами различных типов. Механизмы хранения данных в MySQL могут выполнять обработку как транзакционных таблиц, так и таблиц без транзакций: • Первоначальным механизмом хранения был ISAM, посредством которого осуществлялась обработка нетранзакционных таблиц. Впоследствии он был заменен механизмом My ISAM и со временем должен вообще выйти из употребления. В версии MySQL 4.1 его использование было сведено к минимуму, а в версии MySQL 5.0 он будет исключен полностью. • В версии MySQL 3.23.0 были введены механизмы хранения данных MylSAM и HEAP. Механизм MylSAM представляет собой усовершенствованный вариант механизма ISAM. Механизм HEAP работает с так называемыми "таблицами в памяти" (in-memory table). В версии MySQL 3.23.25 был представлен механизм MERGE, который позволяет работать с совокупностью идентичных таблиц MylSAM как с одной целой таблицей. Каждый из этих трех механизмом хранения работает с нетранзакционными таблицами и включен в MySQL по умолчанию. В настоящее время механизм HEAP имеет название MEMORY. • Механизмы хранения innoDB и BDB, осуществляющие обработку транзакционных таблиц, появились в версиях MySQL 3.23. Оба механизма доступны в исходном дистрибутиве MySQL 3.23.34а. Механизм BDB включен в бинарные дистрибутивы MySQL-Max для тех операционных систем, которые его поддерживают. Механизм InnoDB также входит в состав бинарных дистрибутивов MySQL-Max для MySQL 3.23. Начиная с версии MySQL 4.0, механизм InnoDB включен во все бинарные дистрибутивы. В исходных дистрибутивах вы можете включить или отключить любой механизм, конфигурируя MySQL так, как это необходимо. В настоящей главе вы сможете найти описание каждого механизма хранения MySQL, кроме InnoDB, которому посвящена вся глава 9. При создании новой таблицы вы можете сообщить MySQL о том, какой тип таблицы должен быть выбран. Для этого в операторе CREATE TABLE необходимо добавить опцию ENGINE ИЛИ TYPE:
8.1. Механизм хранения MylSAM
499
CREATE TABLE t (i INT) ENGINE = INNODB; CREATE TABLE t (i INT) TYPE = MEMORY; Опция ENGINE более предпочтительна, однако ее нельзя использовать в версиях MySQL, предшествующих 4.0.18. Опцию TYPE можно использовать в любой версии, начиная с MySQL 3.23.0 - первой версии MySQL, в которой появилась возможность работать с несколькими механизмами хранения. Если опустить опцию ENGINE или TYPE, по умолчанию будет выбрана таблица My ISAM. Таблицу, которая будет использоваться по умолчанию, можно указать в системной переменной table_type. Чтобы преобразовать таблицу одного типа в другой используется оператор ALTER TABLE, который позволяет определить новый тип таблицы: ALTER TABLE t ENGINE = MYISAM; ALTER TABLE t TYPE = BDB;
Если вы попытаетесь использовать ^скомпилированный или скомпилированный, но не активизированный механизм хранения, MySQL выберет вместо него My ISAM. Это будет удобно в том случае, если вам понадобится копировать таблицы между серверами MySQL, которые поддерживают различные механизмы хранения данных. (Например, во время настройки репликации главный сервер будет поддерживать транзакционные механизмы для безопасного хранения данных, а подчиненный сервер - нетранзакционные механизмы хранения в целях повышения скорости работы.) Следует отметить, что автоматическая замена таблицы на My ISAM может сбить с толку начинающих пользователей MySQL. В версии MySQL 4.1 и выше при автоматическом изменении типа таблицы генерируется предупреждающее сообщение. MySQL всегда создает файл формата . f rm, в котором содержится описание таблицы и столбцов. Индексы таблиц и данные могут храниться в одном или нескольких других файлах, что зависит от типа таблицы. Сервер создает файл . f rm над уровнем механизма хранения. Каждый механизм хранения данных создает дополнительные файлы, необходимые для таблиц, с которыми они работают. База данных (БД) может содержать таблицы различных типов. Если провести сравнение между таблицами без транзакций (Non-Transaction-Safe Table - NTST) и транзакционными таблицами (Transaction-Safe Table - TST), то можно выявить некоторые преимущества последних: • Более безопасные. Даже при аварийном отказе MySQL или возникновении серьезных проблем с оборудованием вы сможете восстановить свои данные либо из резервной копии и журнала транзакций, либо с помощью автоматического восстановления. • Допускается комбинирование нескольких операторов и принятие их с помощью одного оператора COMMIT (при условии, что режим автоматической фиксации отключен). • Допускается выполнение оператора ROLLBACK для отмены произведенных изменений (при условии, что режим автоматической фиксации отключен). • Если произошел сбой при обновлении, вы сможете восстановить все произведенные изменения. (В таблицах без транзакций произведенные изменения не могут быть отменены.) • Механизмы хранения с транзакциями лучше справляются с параллельной обработкой таблиц, в которых одновременно с чтением выполняется обновление данных.
500
Глава 8. Механизмы хранения и типы таблиц в MySQL
Учтите, что для того чтобы использовать механизм хранения innoDB в MySQL 3.23, потребуется сконфигурировать, по крайней мере, опцию запуска innodb_data_file_path. В версии 4.0, а также в более новых версиях механизм хранения InnoDB использует опции конфигурации, принятые по умолчанию (если только вы не определите свои опции). См. раздел 9.4. Таблицы без транзакций обладают своими преимуществами, что объясняется именно отсутствием транзакций: • Более высокая скорость работы. • Меньшие требования к дисковому пространству. • Для выполнения обновлений требуется меньше памяти. В одних и тех же операторах можно комбинировать таблицы с транзакциями и таблицы без транзакций, что дает возможность пользоваться преимуществами таблиц обеих типов. Однако если для транзакции отключить режим автоматической фиксации, то изменения в таблицах без транзакций все равно будут мгновенно фиксироваться, без возможности выполнения отката.
8.1. Механизм хранения MylSAM В версии MySQL 3.23 механизм хранения My ISAM используется по умолчанию. Он был создан на основе кода ISAM со множеством полезных расширений. Каждая таблица My ISAM хранится на диске в трех файлах, имена которых начинаются с имени таблицы, а расширения указывают на тип файла. В файле . f rm хранится описание таблицы, данные содержатся в файле с расширением .MYD (MYData), а индексный файл имеет расширение .MYI (MYIndex). Чтобы указать явным образом, что вам необходима таблица My ISAM, используйте опцию ENGINE ИЛИ TYPE: CREATE TABLE t (i INT) ENGINE = MYISAM; CREATE TABLE t (i INT) TYPE = MYISAM; Обычно эти опции не являются необходимыми. Механизм My ISAM используется по умолчанию, что можно изменить в соответствующих настройках. Выполнить проверку или восстановить таблицу My ISAM можно с помощью утилиты myisamchk (см. раздел 4.6.2.7). Утилита myisampack позволяет сжать таблицу MylSAM, уменьшая ее размеры (см. раздел 7.2). По сравнению со старым механизмом хранения ISAM механизм MylSAM обладает целым рядом усовершенствований: • Все значения сохраняются с первым младшим байтом, в результате чего данные не зависят от используемой операционной системы и компьютера. Чтобы данные можно было переносить в двоичном формате, компьютер должен уметь оперировать с числами со знаками, представленными в дополнительном двоичном коде (как и во всех компьютерах, выпущенных в течение последних двадцати лет), и должен поддерживать формат с плавающей запятой IEEE (этот формат также используется в подавляющем большинстве выпускаемых ныне серийных компьютеров). Следует иметь в виду, что двоичную совместимость могут не поддерживать лишь встроенные системы со специфическими процессорами.
8.1. Механизм хранения MylSAM
501
Хранение данных с первым младшим байтом не приводит к существенному снижению скорости работы; байты в строках таблицы обычно не выровнены, и на чтение такого байта в прямой и обратной последовательности потребуется одинаковый объем вычислительной работы. Кроме этого, чтобы извлечь значение из столбца, потребуется не больше времени, чем на выполнение какой-нибудь другой операции. •
Поддерживаются файлы, имеющие большой размер (вплоть до файлов с 63разрядной длиной); это относится к тем файловым и операционным системам, которые поддерживают файлы большого размера.
• При одновременном удалении, обновлении и вставке данных строки с динамически изменяющимся размером будут менее фрагментированными. Это объясняется автоматическим комбинированием смежных удаленных блоков и расширением блоков при удалении смежного блока. • Максимальное количество индексов в таблице составляет 64 (до выхода версии MySQL 4.1.2 их было 32). Количество индексов можно изменить путем повторной компиляции. Максимальное количество столбцов в индексе равно 16. • Максимальная длина ключа составляет 1000 байт (до выхода версии MySQL 4.1.2 она равнялась 500). Длину ключа можно изменить путем повторной компиляции. В случае если длина ключа превышает 250 байт, используется больший размер блока ключа (более 1024 байт). • Допускается индексирование столбцов BLOB и TEXT. • В индексированных столбцах допускается хранение значений NULL. В каждом ключе для этого отводится 0-1 байт. •
Значения цифровых ключей хранятся с первым старшим байтом, благодаря чему возможно более эффективное сжатие индексов.
• Индексные файлы в My ISAM имеют обычно меньший размер, чем в ISAM. Таким образом, в общем случае My ISAM будет использовать меньший объем системных ресурсов, нежели ISAM, хотя при добавлении данных в сжатый индекс механизме My ISAM понадобится больше процессорного времени. • Во время вставки записей в сортированном порядке (как в случае использования столбца AUTOINCREMENT) дерево индексов разбивается таким образом, чтобы верхний узел содержал всего лишь один ключ. За счет этого достигается более эффективное использование пространства в дереве индексов. •
В пределах одной таблицы обрабатывается один столбец AUTO_INCREMENT. Этот столбец механизм My ISAM автоматически обновляет при выполнении операторов INSERT/UPDATE, В результате чего работа со столбцом AUTO_INCREMENT происходит быстрее (как минимум на 10%). Удаленные из вершины последовательности значения повторно не используются, как это происходит в механизме ISAM. (Удаленные значения могут быть использованы повторно, если столбец AUTO_INCREMENT будет определен как последний столбец.) Значение AUTO_INCREMENT можно обнулить С ПОМОЩЬЮ ALTER TABLE ИЛИ myisamchk.
• Если в таблице нет свободных блоков в средней части файла данных, вы можете добавить новые строки с помощью оператора INSERT одновременно с тем, как другие потоки будут производить считывание данных из таблицы. (Такое добав-
Глава 8. Механизмы хранения и типы таблиц в MySQL
502
ление новых строк называется параллельной вставкой.) При удалении строки или обновлении строки с динамически изменяющейся длиной большим количеством данных может возникнуть свободный блок. Если будут заняты (заполнены) все свободные блоки, все последующие вставки вновь будут параллельными. • Файл данных и индексный файл можно сохранять в различных каталогах, что способствует повышению скорости работы (опции DATA DIRECTORY и INDEX DIRECTORY ДЛЯ CREATE
TABLE).
• В версии MySQL 4.1 каждый столбец символов может содержать символы в различных кодировках. • Индексный файл My ISAM имеет флаг, который указывает на то, правильно ли была закрыта таблица. Если для запуска использовать команду mysqld с опцией --myisam-recover, тогда при открытии таблиц MylSAM будет выполняться автоматическая проверка (и восстановление в случае необходимости), если они не были закрыты должным образом. • Утилита myisamchk будет отмечать таблицы как проверенные, если использовать опцию —update-state. Если указать опцию —fast, проверку пройдут только те таблицы, которые не имеют такой пометки. • С помощью опции —analyze утилита myisamchk будет сохранять статистические данные по частям ключа, а не по всему ключу в целом, как в ISAM. • Утилита myisamchk способна упаковывать столбцы BLOB и VARCHAR; утилита pack_isam- нет. Механизм хранения данных My ISAM обладает также рядом других возможностей, воспользоваться которыми в MySQL можно будет в обозримом будущем: • Поддержка типа VARCHAR; столбец VARCHAR начинается со значения длины, занимающего два байта. • Таблицы с VARCHAR могут иметь как фиксированную, так и динамически изменяющуюся длину записи. • Столбцы VARCHAR и CHAR могут быть длиной до 64 Кбайт. • Для UNIQUE может использоваться вычисленный хешированный индекс. Благодаря этому вы сможете работать с UNIQUE в любой комбинации столбцов в таблице. (С другой стороны, вы не сможете производить поиск по вычисленному индексу UNIQUE.)
8.1.1. Опции запуска MylSAM Для изменения поведения таблиц MylSAM используются следующие опции mysqld:
|
•
—my is am- re cove г=режим. Режим автоматического восстановления поврежденных таблиц MylSAM.
•
—delay-key-write=ALL. Ключевые буферы не будут сбрасываться на диск между записями для любой таблицы MylSAM.
На заметку!
Ь В этом случае не следует использовать таблицы MylSAM из других программ (например, из дру% гого сервера MySQL или в утилите myisamchk) в процессе работы с таблицей. В противном слуf; чае произойдет искажение индекса.
8.1. Механизм хранения MylSAM
503
Опция —external-locking бесполезна для таблиц, в которых используется опция —delay-key-write. См. раздел 4.2.1. На поведение таблиц My ISAM влияют следующие системные переменные: • bulk_insert_buffer__size. Размер кэша дерева, используемого при оптимизации групповой вставки. р
На заметку!
Ц
Это ограничение распространяется на поток*
• myisam_max_extra_sort_file_size. Используется, чтобы помочь MySQL принять решение относительно того, когда использовать медленный, но безопасный метод создания индекса кэша ключей. |
На заметку!
& Ц
До версии MySQL 4.0.3 значение этой переменной указывалось в мегабайтах, а начиная с этой версии - в байтах.
• m y i s a m m a x s o r t f i l e s i z e . Для создания индекса не будет использоваться метод быстрой сортировки, если временный файл будет иметь размер больше, чем размер, указанный в этой переменной. Щ На заметку! */* До версии MySQL 4.0.3 значение этой переменной указывалось в мегабайтах, а начиная с этой |% версии - в байтах.
• myisam_sort_buf fer_size. Устанавливает размер буфера, используемого при восстановлении таблиц. См. раздел 4.2.3. Автоматическое восстановление таблиц инициируется при запуске команды raysqld с опцией —myisam-recover. В этом случае, когда сервер открывает таблицу MylSAM, он проверяет, помечена ли данная таблица как поврежденная, отлично ли от нуля значение переменной счетчика открытий и не производится ли запуск сервера с опцией —skipexternal-locking. Если одно из этих условий будет выполнено, произойдет следующее: • Будет выполнена проверка таблицы на наличие ошибок. • Если сервер обнаружит ошибку, он попытается выполнить быстрое восстановление таблицы (включая сортировку, но без повторного создания файла данных). • Если восстановить таблицу не удалось вследствие ошибки в файле данных (например, из-за ошибки дублирования ключей), сервер еще раз попытается восстановить таблицу, однако на этот раз уже с повторным созданием файла данных. • Если восстановить таблицу не удалось, сервер попытается сделать это еще раз с помощью старого способа восстановления (выполняя построчную запись без сортировки). Этот способ позволяет исправить ошибку любого рода и не требует большого объема дискового пространства. Если в процессе восстановления не удалось восстановить все строки из предыдущего выполненного оператора, и в команде --myisam-recover не была указана опция FORCE, в журнале ошибок появится следующее сообщение: Error: Couldn't repair table: test.gOOpages
504
Глава 8. Механизмы хранения и типы таблиц в MySQL
Ошибка: Невозможно восстановить таблицу: test.gOOpages Если указывалась опция FORCE, это сообщение будет выглядеть следующим образом: Warning: Found 344 of 354 rows when repairing ./test/gOOpages Предупреждение: найдено 344 из 354 строк во время восстановления ./test/gOOpages Имейте в виду, что если для автоматического восстановления использовать опцию BACKUP, то в процессе восстановления будут создаваться файлы, с именами в виде имя_таблицы-дата-время .ВАК. Для автоматического переноса созданных файлов из каталогов базы данных на резервный носитель следует использовать сценарий сгоп.
8.1.2. Пространство, необходимое для ключей В таблицах My ISAM используются индексы в форме В-деревьев. Приближенно оценить размер индексного файла можно по формуле [длина_ключа+4) /0.67, просуммированной по всем ключам. Эта формула используется при наиболее неблагоприятном варианте, когда все ключи вставлены в отсортированном порядке и таблица не имеет сжатых ключей. В индексах строк сжаты пробелы. Если строкой является первая часть индекса, префикс также будет сжат* Сжимая пробелы, можно добиться еще большего сокращения размеров индексного файла, чем с помощью приведенной выше формулы, если столбец строки будет содержать множество пробелов в конце текстовой строки или будет являться столбцом VARCHAR, который не всегда используется в полную длину. Сжатие префикса полезно выполнять, если множество строк будут содержать одинаковый префикс. Числа в таблицах MylSAM могут быть сжаты в префиксах. Для этого при создании таблицы необходимо указать PACK_KEYS=1. Это будет полезно при наличии множества целочисленных ключей с одинаковыми префиксами, когда числа хранятся с первым старшим байтом.
8.1.3. Форматы хранения данных в таблицах MylSAM My ISAM поддерживает три различных формата хранения данных. Два из них (фиксированный и динамический формат) выбираются автоматически в зависимости от типа используемых столбцов. Третий формат, называемый сжатым форматом, можно создать только с помощью утилиты myisampack. Выполняя операторы CREATE или ALTER над таблицами, в которых отсутствуют столбцы BLOB или TEXT, с помощью опции ROW_FORMAT можно указать формат таблицы FIXED или DYNAMIC. В результате столбцы CHAR и VARCHAR станут столбцами CHAR для формата FIXED или VARCHAR для формата DYNAMIC. В дальнейшем можно будет сжимать или разворачивать таблицы, указывая для команды ALTER TABLE ОПЦИЮ ROW_FORMAT={COMPRESSED | DEFAULT}. 8.1.3.1. Характеристики статической таблицы (таблицы с фиксированной длиной) Статический формат в таблицах MylSAM является форматом по умолчанию. Он используется в тех случаях, когда таблица не содержит столбцов переменной длины (столбцы VARCHAR, BLOB или TEXT). Каждая строка сохраняется с фиксированным количеством байт.
8.1. Механизм хранения MylSAM
505
Среди трех форматов хранения данных в механизме My ISAM статический формат является самым простым и наиболее безопасным (данные в таблицах этого формата менее всего подвержены искажению). Также он является наиболее быстрым среди форматов, работающих с дисками. Повышение скорости работы достигается за счет простоты алгоритма поиска строк в файле данных, хранящемся на диске: для поиска строки в индексе ее номер умножается на длину строки. Кроме того, при сканировании таблицы очень просто считывать постоянное число записей при каждой операции чтения с диска. Безопасность таблицы можно будет оценить, если произойдет сбой в работе компьютера во время записи сервером MySQL файла My ISAM фиксированной длины. В этом случае утилита myisamchk сможет без труда определить начало и окончание каждой строки, поэтому обычно с ее помощью можно восстановить все записи за исключением частично перезаписанных. Имейте в виду, что индексы таблицы My ISAM всегда можно реконструировать на основе строк данных. К характеристикам таблиц статического формата можно отнести следующие: • Все столбцы CHAR, NUMERIC и DECIMAL заполняются пробелами по всей ширине столбца. • Высокая скорость работы. • Простота кэширования. • Простота восстановления данных после сбоя (благодаря тому, что записи располагаются в фиксированных позициях). • Не нуждаются в реорганизации данных кроме тех случаев, когда вы удаляете большое число записей и хотите передать освобожденное пространство диска операционной системе. Для этого используется OPTIMIZE TABLE или myisamchk -r. • Обычно требуют больше пространства на диске, чем таблицы динамического формата. 8.1.3.2. Характеристики динамических таблиц Динамический формат хранения используется в том случае, если таблица My ISAM содержит столбцы переменной длины (VARCHAR, BLOB или TEXT) или если таблица была создана с использованием опции ROW_FORMAT=DYNAMIC. Этот формат немного сложнее, поскольку каждая строка имеет заголовок, в котором указывается ее длина. Кроме того, одна запись может заканчиваться в нескольких позициях, если длина строки увеличится в процессе обновления. Для дефрагментации таблицы используется команда OPTIMIZE TABLE или утилита myisamchk. Если имеются столбцы с фиксированной длиной, к которым вы часто обращаетесь или которые часто изменяете в таблице, содержащей несколько столбцов переменной длины, то чтобы предотвратить фрагментацию столбцов переменной длины их следует переместить в другие таблицы. К характеристикам таблиц динамического формата относятся следующие: • Все столбцы со строками являются динамическими за исключением столбцов, имеющих длину менее 4. • Каждой записи предшествует битовая карта, указывающая на то, в каких столбцах содержатся пустые строки (для столбцов со строками) или нули (для столбцов с числами). Следует учесть, что это не относится к столбцам, содержащим значения NULL. Если столбец со строками будет иметь нулевую длину после удаления про-
Глава 8. Механизмы хранения и типы таблиц в MySQL
506
белов в конце строки, или если столбец с числами будет иметь нулевое значение, он будет отмечен в битовой карте и не будет сохранен на диск. Строка с содержимым сохраняется в виде байта длины и ее содержимого. • Для динамических таблиц обычно требуется меньше дискового пространства, чем для таблиц статического формата. • Каждая запись занимает столько пространства, сколько это необходимо. Однако если запись становится большей, она разделяется на требуемое количество частей, что в результате приводит к фрагментации записи. Так, если вы обновите строку информацией, которая заполнит всю длину строки, строка окажется фрагментированной. В этом случае вам придется периодически выполнять команду OPTIMIZE TABLE или запускать утилиту myisamchk с опцией -г, чтобы добиться более высокой производительности. Статистику по таблице можно получить с помощью утилиты myisamchk с опцией -ei. • Восстанавливать таблицы динамического формата после сбоев труднее, чем статические таблицы, поскольку запись может оказаться фрагментированной и быть разделена на множество частей; кроме этого, может отсутствовать ссылка (или фрагмент). • Длину строки для динамически изменяющихся записей можно приблизительно оценить следующим образом: 3 + + + + +
{количество столбцов + 7) / 8 {количество столбцов с символами) {упакованный размер столбцов с числами) {длина строк) {количество столбцов со значением NULL + 7) / 8
На каждую ссылку добавляется по 6 байт. Динамические записи связываются при каждом увеличении записи в момент ее обновления. Каждая новая ссылка будет иметь размер как минимум 20 байт, поэтому следующее увеличение можно будет произвести по той же ссылке. В противном случае будет использоваться другая ссылка. Количество ссылок можно узнать с помощью команды myisamchk -ed. Удалить ссылки можно с помощью команды myisamchk -r. 8.1.3.3. Характеристики сжатых таблиц Таблицы сжатого формата предназначены только для чтения и генерируются с помощью инструмента myisampack. Начиная с версии 3.23.19, дистрибутивы MySQL содержат инструмент myisampack. (Эта версия MySQL регламентируется лицензией GPL.) В более ранних версиях инструмент myisampack поставлялся только по лицензионному соглашению или соглашению о поддержке; несмотря на это, сервер способен читать таблицы, сжатые с помощью myisampack. Распаковать сжатые таблицы можно с помощью утилиты myisamchk. (В механизме хранения данных ISAM сжатые таблицы можно создавать с помощью утилиты pack_isam и распаковывать с помощью isamchk.) Сжатые таблицы обладают следующими характеристиками: • Занимают очень мало дискового пространства. Это позволяет сократить использование диска, что будет полезно при работе с низкоскоростными дисками (такими, как приводы компакт-дисков).
8.1. Механизм хранения MylSAM
507
• Каждая запись сжимается отдельно, поэтому издержки при доступе сводятся к минимуму. Заголовок для записи является фиксированным (1-3 байта), в зависимости от размера самой большой записи в таблице. Сжатие каждого столбца производится по-разному. Обычно для каждого столбца используется отдельное дерево Хаффмана. Существует несколько типов сжатия: • • • •
Сжатие пробелов суффикса. Сжатие пробелов префикса. Для хранения чисел с нулевым значением используется один бит. Если значения в столбце целых чисел представлены в небольшом диапазоне, столбец сохраняется с использованием наименьшего по размерам типа. Например, столбец BIGINT (восемь байт) можно хранить как столбец TINYINT (один байт), если все его значения будут находиться в диапазоне от-128 до 127.
•
Если столбец имеет только небольшую совокупность возможных значений, тип столбца преобразовывается в ENUM.
• В столбце может использоваться сочетание вышеуказанных сжатий. • Возможна обработка записей фиксированной и динамически изменяющейся длины.
8.1-4. Проблемы, связанные с таблицами MylSAM Формат файлов, который MySQL использует для хранения данных, тестировался самым тщательным образом, однако всегда существуют обстоятельства, которые могут привести к искажению данных в таблицах базы. 8.1.4.1. Повреждения таблиц MylSAM Несмотря на всю надежность формата таблиц MylSAM (все изменения в таблице, произведенные с помощью оператора SQL, записываются до того, как оператор вернет значение), существует вероятность искажения данных в таблицах. Это может произойти в следующих случаях: • В процессе записи был уничтожен процесс mysqld. • Произошло неожиданное отключение питания компьютера. • Возникли ошибки оборудования. • Для работы с таблицей, которая на данный момент модифицировалась сервером, применялась внешняя программа (например, myisamchk). • Возникла программная ошибка в коде MySQL или MylSAM. Ниже представлены наиболее распространенные признаки повреждения таблицы: • Во время извлечения данных из таблицы вы получили следующее сообщение об ошибке: Incorrect key f i l e for table: ' . . . ' . Try to repair i t Неверный файл ключей для таблицы: ' . . . ' . Попытайтесь восстановить его • Произведенные запросы не находят строки в таблице или возвращают неполные данные. Проверить состояние таблицы можно с помощью оператора CHECK TABLE. Восстановление поврежденной таблицы MylSAM выполняется командой REPAIR TABLE. Если про-
508
Глава 8. Механизмы хранения и типы таблиц в MySQL
цесс mysqld не запущен, вы можете также проверить или восстановить таблицу с помощью myisamchk. См. раздел 4.6.2.1. Если повреждение таблиц происходит слишком часто, попытайтесь установить причину этого. Прежде всего, необходимо выяснить, связано ли повреждение таблиц со сбоем на сервере. Просмотрите журнал ошибок: он должен содержать новое сообщение restarted mysqld, свидетельствующее о том, что повреждение таблицы произошло вследствие сбоя на сервере. Повреждение таблицы может произойти также во время выполнения обычной операции, что свидетельствует о программной ошибке. В этом случае желательно создать тестовый случай, с помощью которого можно было бы установить причину неприятностей. См. раздел А.4.2. 8.1.4.2. Проблемы, связанные с неправильно закрытыми таблицами Каждый индексный файл My ISAM (.MY I) имеет в своем заголовке счетчик, который может быть использован для проверки правильности закрытия таблицы. Если при выполнении команды CHECK TABLE или myisamchk вы получили следующее сообщение: clients are using or haven't closed the table properly клиенты неправильно используют таблицу или не закрыли ее соответствующим образом значит, произошло нарушение синхронности счетчика. Это сообщение не обязательно свидетельствует о повреждении таблицы, однако вам все равно придется проверить таблицу, чтобы убедиться в ее целостности. Счетчик работает следующим образом: • Во время первого обновления таблицы в MySQL значение счетчика в заголовках индексных файлов увеличивается. • При последующих обновлениях значение счетчика не изменяется. • После того как будет закрыт последний экземпляр таблицы (после выполнения операции FLUSH TABLES или по причине отсутствия места в кэше таблицы), значение счетчика уменьшится, если в таблицу были внесены изменения. • Если в процессе восстановления таблицы или в ходе ее проверки оказалось, что таблица не содержит никаких ошибок, значение счетчика обнуляется. • Чтобы избежать проблем с взаимодействием с другими процессами, которые могут проверять таблицу, значение счетчика при закрытии таблицы не уменьшается, если оно было равно нулю. Другими словами, синхронность счетчика может быть нарушена в следующих случаях: • Таблицы My ISAM копируются без выполнения команд LOCK TABLES и FLUSH TABLES. • Произошел сбой MySQL между обновлением и последним закрытием. (Имейте в виду, что таблица может сохранять свою целостность, поскольку MySQL всегда регистрирует изменения, произошедшие между выполнением операторов.) • Таблица была модифицирована с помощью команд myisamchk --recover или myisamchk --update-state в тот момент, когда она использовалась mysqld. • Таблицу используют несколько серверов mysqld; один из серверов выполнил в отношении таблицы команду REPAIR TABLE или CHECK TABLE, причем таблица в этот момент использовалась другим сервером. В этом случае лучше всего выполнить команду CHECK TABLE, даже если вы можете получить предупреждающее со-
8.2. Механизм хранения MERGE
509
общение от других серверов. Не следует применять команду REPAIR TABLE, поскольку о замене файла данных остальным серверам не будет известно. Вообще говоря, лучше всего избегать общего использования каталога данных несколькими серверами. Более подробно об этом вопросе рассказывалось в разделе 4.9.
8.2. Механизм хранения MERGE Механизм хранения MERGE был впервые представлен в версии MySQL 3.23.25. Он известен также как механизм MRG__MyISAM. В настоящее время его код является достаточно стабильным. Таблица MERGE представляет собой совокупность таблиц, идентичных таблицам My ISAM, которые могут использоваться как одна таблица. Здесь под "идентичными" таблицами подразумеваются таблицы, имеющие одинаковую структуру и ключи. Вам не удастся объединить таблицы, в которых по-разному упакованы столбцы, которые не имеют одинаковых столбцов или имеют индексы различного порядка. Однако любую из таких таблиц можно сжать с помощью утилиты myisampack. См. раздел 7.2. В процессе создания таблицы MERGE MySQL создает на диске два файла. Имя файла начинается с имени таблицы и имеет расширение, указывающее на тип файла. В файле . frm хранится описание таблицы, а файл .MRG содержит имена таблиц, которые будут использоваться как одна таблица. (Первоначально все используемые таблицы должны были находиться в той же базе данных, что и таблица MERGE. Это ограничение было снято в версии MySQL 4.1.1.) Для таблиц, входящих в таблицу MERGE, можно использовать команды SELECT, DELETE, UPDATE и (в версии MySQL 4.0) INSERT. Чтобы использовать возможности этих команд, необходимо располагать соответствующими привилегиями на их выполнение в таблицах, входящих в таблицу MERGE. Если вы примените к таблице MERGE команду DROP, вы удалите только определение MERGE. Таблицы, входящие в состав MERGE, останутся нетронутыми. При создании таблицы MERGE необходимо задать оператор UN ION=( список- та блиц), в котором указывается, какие таблицы будут использоваться как одна. Если необходимо, чтобы вставка в таблицу MERGE осуществлялась в первой или последней таблице списка UNION, с помощью опции INSERT_METHOD можно указать метод вставки. Если не указать эту опцию или не присвоить ей значение N0, то при попытке вставить записи в таблицу MERGE возникнет ошибка. В следующем примере показан пример создания таблицы MERGE: mysql> CREATE TABLE t l ( -> ->
a INT NOT NULL AUTO_INCREMENT PRIMARY KEY, m e s s a g e CHAR(20));
mysql> CREATE TABLE t 2 ( -> ->
a INT NOT NULL AUTO_INCREMENT PRIMARY KEY, m e s s a g e CHAR(20));
mysql> INSERT INTO t l (message) VALUES ( ' T e s t i n g ' ) , ( ' t a b l e ' ) , ( ' t l • ) ; mysql> INSERT INTO t2 (message) VALUES ('Testing•),('table'),('t2'); mysql> CREATE TABLE t o t a l ( -> a INT NOT NULL AUTO_INCREMENT, -> m e s s a g e CHAR(20), INDEX(a)) -> TYPE=MERGE U N I O N = ( t l , t 2 ) INSERT METHOD=LAST;
510
Глава 8. Механизмы хранения и типы таблиц в MySQL
Обратите внимание на то, что в таблице MERGE столбец а имеет индекс, хотя и не объявлен как PRIMARY KEY, подобно остальным таблицам My ISAM. Это объясняется тем, что таблица MERGE не может обеспечить уникальность каждой таблицы, входящей в данную совокупность. После того как будет создана таблица MERGE, можно выполнить следующее действие: mysql> SELECT * FROM total; +—+ + I a | message | +—+ + 1 | Testing | 2 | table | 3 I tl | 1 | Testing | 2 | table | 3 I t2 I + + + Обратите внимание на то, что манипулировать файлом .MRG можно и за пределами сервера MySQL: shell> cd /каталог_данных_тузд1/текущая_база_данных shell> Is -1 tl t2 > total.MRG shell> mysqladmin flush-tables Чтобы создать новую совокупность таблиц My ISAM в таблице MERGE, необходимо выполнить следующие действия: • Выполните команду DROP и повторно создайте таблицу. • С помощью команды ALTER TABLE имя_таблицы UNION= (...) измените список таблиц, входящих в совокупность. • Измените файл . MRG и выполните оператор FLUSH TABLE для таблицы MERGE и всех ее таблиц, чтобы механизм хранения мог прочитать новый файл описания. Ниже представлены возможности таблиц MERGE: • Довольно простое управление совокупностью журнальных таблиц. Так, например, можно ввести данные по различным месяцам в различные таблицы, сжать некоторые из них с помощью утилиты myisampack и затем создать таблицу MERGE, чтобы использовать их как одну. • Более высокая скорость работы. Можно разделить по некоторым критериям большие таблицы формата только для чтения и сохранить получившиеся отдельные таблицы на различных дисках. С такой таблицей MERGE можно будет работать гораздо быстрее, чем с действительно одной большой таблицей. (Аналогичные преимущества можно получить, используя дисковый массив RAID.) • Более эффективный поиск данных. Если вы точно знаете, что ищете, тогда поиск можно сделать по некоторым запросам в одной таблице, входящей в совокупность, а таблицу MERGE использовать для других запросов. Можно работать также с множеством различных таблиц MERGE с перекрывающимися совокупностями таблиц.
8.2. Механизм хранения MERGE •
511
Эффективное восстановление поврежденных таблиц. Гораздо легче восстановить одну таблицу, входящую в состав MERGE, нежели восстанавливать одну действительно большую таблицу.
• Мгновенное формирование нескольких таблиц в виде одной. Для таблицы MERGE не нужно поддерживать индекс, поскольку она работает с индексами каждой отдельной таблицы. Как результат, можно очень быстро сформировать или переформировать совокупности таблиц MERGE. (Учтите, что при формировании таблицы MERGE необходимо давать определение индексов, даже если ни один из них не будет создан.) •
Если имеется совокупность таблиц, которые вы намерены объединить по требованию или во время формирования в одну большую таблицу, то лучше всего создать на их основе таблицу MERGE по требованию. Сделать это будет гораздо быстрее и, кроме того, вы сможете сэкономить довольно большую часть дискового пространства.
• Таблицы MERGE позволяют обойти ограничение на размер файлов в данной операционной системе. Это ограничение распространяется на индивидуальную таблицу My ISAM, а на совокупность таблиц My ISAM - нет. • Для таблицы My ISAM можно создать псевдоним или синоним, определяя таблицу MERGE, которая будет отображена для данной одиночной таблицы. Причем это практически не скажется на производительности (добавится только пара непрямых вызовов и вызовы memcpy () при каждом считывании). А вот недостатки таблиц MERGE: • Для формирования таблицы MERGE можно использовать только идентичные таблицы My ISAM. •
Таблицы MERGE используют большее количество описаний файлов. Если 10 клиентов используют таблицу MERGE, объединяющую 10 таблиц, то сервер будет иметь дело с (10* 10)+10 файловыми дескрипторами. (10 дескрипторов файлов данных для каждого из 10 клиентов и 10 дескрипторов индексных файлов, являющихся для клиентов общими.)
• Медленное чтение ключей. При считывании ключа механизм хранения MERGE должен произвести чтение во всех таблицах, чтобы выяснить, какая из них наиболее всего совпадает с данным ключом. Если затем попытаться выполнить чтение следующего ключа, механизму MERGE придется просмотреть буферы чтения, чтобы найти следующий ключ. Только после завершения просмотра одного буфера механизм перейдет к просмотру следующего блока ключей. Вследствие этого работа с ключами MERGE осуществляется гораздо медленнее при поисках eq_ref, но не очень медленно при поисках ref. Дополнительно о eq_ref и ref можно почитать в разделе 6.2.1.
8.2.1. Проблемы, связанные с таблицами MERGE При работе с таблицами MERGE могут возникать следующие проблемы: •
Если вы используете команду ALTER TABLE для преобразования таблицы MERGE в таблицу другого типа, то отображение ее таблиц будет утрачено. Строки из ее таблиц My ISAM будут скопированы в измененную таблицу, которой затем будет присвоен новый тип.
512
Глава 8. Механизмы хранения и типы таблиц в MySQL
• До выхода версии MySQL 4.1.1 таблица MERGE и все ее таблицы должны были храниться в одной и той же базе данных. •
Оператор REPLACE не работает.
• Нельзя выполнять операторы DROP TABLE, ALTER TABLE или DELETE FROM без конструкции WHERE, a REPAIR TABLE, TRUNCATE TABLE, OPTIMIZE TABLE ИЛИ ANALYZE TABLE для любой таблицы, входящей в состав таблицы MERGE, которая, в свою очередь, является "открытой". Если вы попытаетесь выполнить один из упомянутых операторов, таблица MERGE, вероятно, все еще будет ссылаться на исходную таблицу, и вы получите непредсказуемые результаты. Самый простой способ решения этой проблемы заключается в выполнении оператора FLUSH TABLES, который позволит проверить наличие "открытых" таблиц MERGE. •
Таблица MERGE не может поддерживать ограничения UNIQUE для всех своих таблиц. При выполнении команды INSERT данные переносятся в первую или последнюю таблицу My ISAM (в зависимости от значения, присвоенного опцией INSERTMETHOD). MySQL гарантирует, что уникальные значения ключей остаются уникальными в пределах данной таблицы My ISAM, но не во всех таблицах, входящих в совокупность.
• До версии MySQL 3.23.49 оператор DELETE FROM таблица^тегде без конструкции WHERE очищал только отображение для таблицы. Другими словами, вместо удаления записей из отображенных таблиц она некорректно освобождала файл .MRG. •
Применение оператора RENAME TABLE к активной таблице MERGE может привести к повреждению данных в таблице. Эта проблема будет решена в версии MySQL 4.1.x.
• Когда вы создаете таблицу MERGE, не выполняется проверка существования таблиц, входящих в совокупность, и идентичности их структуры. Когда используется таблица MERGE, MySQL быстро проверяет, равна ли длина записей во всех отображенных таблицах, что, однако, не очень надежно. Если вы попытаетесь сформировать таблицу MERGE на основе разнородных таблиц My ISAM, вы наверняка столкнетесь с проблемами. • Порядок индексов в таблице MERGE и в ее таблицах должен быть одинаковым. Если вы используете ALTER TABLE для добавления индекса UNIQUE в таблицу, входящую в состав таблицы MERGE, и затем будете использовать ALTER TABLE для добавления неуникального индекса в таблицу MERGE, то порядок индексов в таблицах окажется различным, если в таблице, входящей в состав таблицы MERGE, оставался старый неуникальный индекс. (Это происходит из-за того, что оператор ALTER TABLE ставит индексы UNIQUE перед неуникальными индексами, чтобы можно было выявлять дублированные ключи на самой ранней стадии их появления.) Поэтому запросы могут вернуть неожиданные результаты. • Оператор DROP TABLE, выполненный над таблицей, входящей в состав таблицы MERGE, не работает в среде Windows, поскольку механизм MERGE скрывает отображение таблиц от верхнего уровня MySQL. Так как в Windows не разрешается удалять открытые файлы, то сначала необходимо будет сбросить на диск все таблицы MERGE (с помощью FLUSH TABLES) или удалить таблицу MERGE, прежде чем удалить таблицу. Эту ошибку мы планируем исправить с введением представлений.
8.3. Механизм хранения данных MEMORY (HEAP)
513
8.3. Механизм хранения данных MEMORY (HEAP) Механизм хранения данных MEMORY создает таблицы с содержимым, которые хранятся в памяти компьютера. Начиная с версии MySQL 4.1, синонимом таблиц MEMORY является HEAP, однако более предпочтительным считается термин MEMORY. Каждая таблица MEMORY связана с одним дисковым файлом. Имя файла начинается с имени таблицы и имеет расширение . f rm, указывающее на то, что в этом файле хранится описание таблицы. Чтобы указать явным образом, что вам необходима таблица MEMORY, используйте опцию ENGINE или TYPE: CREATE TABLE t (i INT) ENGINE = MEMORY; CREATE TABLE t (i INT) TYPE = HEAP; Таблицы MEMORY хранятся в памяти компьютера и используют хешированные индексы. Благодаря этому работа с ними производится очень быстро и их очень удобно применять для создания временных таблиц. Однако существует и негативная сторона - в случае сбоя в работе сервера все данные, хранящиеся в таблице MEMORY, будут утеряны. Таблицы существуют благодаря их описаниям, хранящимся в файлах . f rm на диске, однако после перезапуска сервера такие таблицы оказываются пустыми. Ниже представлен пример создания, использования и удаления таблицы MEMORY: mysql> CREATE TABLE t e s t TYPE=MEMORY -> SELECT ip,SUM(downloads) AS down -> FROM log_table GROUP BY ip; mysql> SELECT COUNT(ip),AVG(down) FROM t e s t ; mysql> DROP TABLE t e s t ; Таблицы MEMORY обладают следующими характеристиками: • Пространство для таблиц MEMORY распределяется по блокам небольшого размера. Таблицы используют 100%-ное динамическое хеширование (при операциях вставки). Для таблиц MEMORY не нужны области переполнения или дополнительное пространство для ключей. Дополнительное пространство также не требуется и для свободных списков. Удаленные строки помещаются в связанный список и повторно используются при вставке в таблицу новых данных. Таблицы MEMORY также не имеют проблем с одновременным удалением и вставкой, что часто случается в хешированных таблицах. • В таблице MEMORY может быть до 32 индексов в таблице, 16 столбцов в индексе, а максимальная длина ключа может составлять 500 байт. • До выхода версии MySQL 4.1 механизм хранения MEMORY реализовывал только хешированные индексы. Начиная с версии MySQL 4.1, хешированные индексы используются по умолчанию, однако с помощью конструкции USING вы можете явно указать, что индексом таблицы MEMORY должен быть HASH или BTREE: CREATE TABLE (id
INT,
lookup INDEX USING HASH
(id))
ENGINE = MEMORY; CREATE (id
TABLE INT,
lookup INDEX USING BTREE
ENGINE = MEMORY;
(id))
514
Глава 8. Механизмы хранения и типы таблиц в MySQL Общие характеристики индексов на основе В-деревьев и хеширования, описаны в разделе 6.4.5.
• В таблице MEMORY могут содержаться неуникальные ключи (что не является нормой для хешированных таблиц). • Если в таблице MEMORY с высокой степенью дублирования ключей (несколько статей индекса с одним и тем же значением) имеется хешированный индекс, то процессы обновления таблицы, влияющие на значения ключей, и удаления будут происходить очень медленно. Степень замедления работы пропорциональна степени дублирования (или обратно пропорциональна количеству индексов). Для решения этой проблемы можно использовать индекс BTREE. • Таблицы MEMORY используют формат с фиксированной длиной записи. • Таблицы MEMORY не поддерживают столбцы BLOB или TEXT. •
Таблицы MEMORY не поддерживают столбцы AUTO_INCREMENT.
• До выхода версии MySQL 4.0.2 таблицы MEMORY не поддерживали индексы в столбцах, которые содержали значения NULL. •
Таблицы MEMORY используются совместно всеми клиентами (подобно любой другой таблице).
• Свойство таблицы MEMORY, вследствие которого содержимое таблицы хранится в памяти, позволяет внутренним таблицам, которые сервер создает оперативно в процессе обработки запросов, совместно работать с ней. Однако внутренние таблицы обладают свойством, благодаря которому сервер автоматически преобразовывает их в "таблицы на диске" (on-disk table), если их размер становится чересчур большим. Предельно допустимый размер определяется значением системной переменной tmp_table_size. Таблицы MEMORY не преобразовываются в дисковые таблицы. Чтобы обеспечить защиту от случайных неквалифицированных действий, можно присвоить системной переменной tmp_table_size значение, соответствующее максимальному размеру таблиц MEMORY. Для индивидуальных таблиц можно также задать опция MAX_ROWS В операторе CREATE TABLE. • Чтобы поддерживать все одновременно используемые таблицы MEMORY, серверу необходима дополнительная память достаточного объема. • Чтобы освободить память, занимаемую таблицей MEMORY, содержимое которой вам больше не нужно, потребуется выполнить оператор DELETE или TRUNCATE_TABLE, или же удалить таблицу с помощью DROP TABLE. •
Если необходимо заполнить таблицу MEMORY данными во время запуска сервера MySQL, то для этого можно использовать опцию — i n i t - f i l e . Например, в файл для загрузки таблицы из постоянного источника данных можно поместить оператор INSERT INTO. . .SELECT ИЛИ LOAD DATA INFILE. См. раздел 4.2.1.
• Если использовать репликацию, то таблицы MEMORY, хранящиеся на главном сервере, будут становиться пустыми после его выключения и перезапуска. Однако подчиненному серверу не известно, являются ли эти таблицы пустыми, поэтому при попытке извлечь из них данные вам будет возвращено устаревшее содержимое. Начиная с версии MySQL 4.0.18, когда таблица MEMORY использовалась на
8.4. Механизм хранения данных BDB (BerkleyDB)
515
главном сервере впервые с момента его запуска, оператор DELETE FROM регистрировался в бинарном журнале главного сервера автоматически, синхронизируя подчиненный и главный серверы. Обратите внимание на то, что даже с учетом упомянутой стратегии подчиненный сервер все равно будет хранить устаревшие данные в таблице в промежутке времени между перезапуском главного сервера и первым его обращением к таблице. Однако если для заполнения таблицы MEMORY во время запуска главного сервера указать опцию — i n i t - f i l e , интервал простоя будет равен нулю. • Объем памяти, необходимый для одной строки в таблице MEMORY, можно вычислить следующим образом: SUM_OVER_ALL_KEYS(max_length_of_key + sizeof(char*) * 2) + ALIGN(length_of_row+l, sizeof(char*)) ALIGN () соответствует коэффициенту округления, благодаря которому длина строки будет кратна размеру указателя char. Величина sizeof (char*) равна 4 на 32-разрядных компьютерах и 8 на 64-разрядных.
8.4. Механизм хранения данных BDB (BerkleyDB) Компания Sleepycat Software разработала для MySQL механизм хранения Berkley DB, который обычно называют BDB для краткости. Поддержка таблиц этого типа включена в исходный дистрибутив MySQL, начиная с версии 3.23.34а, а также присутсвует в бинарных дистрибутивах MySQl-Max. Таблицы BDB имеют больше всего шансов оставаться целыми после сбоев. Над этими таблицами могут быть выполнены операции COMMIT и ROLLBACK для транзакций. Дистрибутив MySQL поставляется вместе с дистрибутивом BDB, в котором было сделано несколько исправлений, позволивших устранить некоторые проблемы при работе с MySQL. Использование версии BDB без исправлений в MySQL невозможно. Разработчики компании MySQL AB работают в тесном сотрудничестве с компанией Sleepycat, что дает возможность постоянно поддерживать на высоком уровне качество интерфейса MySQL/BDB. (Несмотря на надежность и тщательную проверку Berkley DB, интерфейс MySQL по-прежнему не отвечает самым высоким требованиям, поэтому работы над его улучшением и оптимизацией продолжаются.) Что касается поддержки таблиц BDB, то мы оказываем всяческую помощь нашим пользователям в выявлении проблем и создании воспроизводимых тестовых случаев. Каждый тестовый случай передается в Sleepycat, которая, в свою очередь, помогает выявлять и исправлять ошибки. Поскольку эта операция проходит в два этапа, то на решение проблем с таблицами BDB может быть потрачено больше времени, чем на решение похожих проблем с другими таблицами. Однако мы считаем, что эта процедура не должна вызывать каких-либо серьезных затруднений, поскольку код Berkley DB используется во многих приложениях, отличных от MySQL. См. раздел 1.4.1. Сведения о деятельности компании Berkley DB можно получить на сайте Sleepycat по адресу http://www.sleepycat.com.
Глава 8. Механизмы хранения и типы таблиц в MySQL
516
8.4.1. Операционные системы, поддерживающие BDB В настоящее время механизм хранения BDB может работать под управлением следующих операционных систем: • Linux 2.x Intel •
Sun Solaris (SPARC и х86)
• FreeBSD4.x/5.x(x86, sparc64) • IBM AIX 4.3.x •
SCO OpenServer
•
SCO UnixWare 7.1.x
Под управлением перечисленных ниже операционных систем механизм хранения BDB не работает: • Linux 2.x Alpha • Linux 2.x AMD64 • Linux 2.x IA-64 •
Linux 2.x s390
• Mac OS X
]*; На зметку! f*
%\ Представленные списки не являются полными. Мы обновим их, как только получим более деУ'. тальную информацию.
В случае выполнения сборки MySQL на основе исходного кода с поддержкой таблиц BDB, если при запуске mysqld возникает приведенная ниже ошибка, это означает, что механизм BDB существующей архитектурой не поддерживается: bdb: architecture lacks fast mutexes: applications cannot be threaded Can't i n i t databases bdb: в архитектуре отсутствуют быстрые семафоры: приложения не могут быть разбиты на потоки Невозможно инициализировать базы данных В этом случае потребуется пересобрать MySQL без поддержки таблиц BDB или запустить сервер с опцией —skip-bdb.
8.4.2. Установка BDB Если вы располагаете загруженной бинарной версией MySQL, которая включает поддержку Berkley DB, достаточно будет выполнить обычные инструкции по установке бинарного дистрибутива. (Дистрибутивы MySQl-Max включают поддержку BDB.) Если вы собираете MySQL на основе исходного кода, можно включить поддержку BDB, выполнив команду configure с опцией —with-berkley-db в дополнение к остальным обычно используемым опциям. Загрузите дистрибутив MySQl 3.23.34 или более новой версии, перейдите в каталог верхнего уровня и выполните следующую команду: shell> ./configure —with-berkeley-db [другие-опции] Более подробные сведения можно найти в разделах 2.2.5, 4.1.2 и 2.3.
8.4. Механизм хранения данных BDB (BerkleyDB)
517
8.4.3. Опции запуска BDB Для изменения поведения механизма хранения BDB служат следующие опции команды mysqld: •
--bdb-home=путь. Базовый каталог для таблиц BDB. Это должен быть тот же каталог, что и каталог для —datadir.
•
—bdb-lock-detect=Mero4. Способ обнаружения блокировки BDB. Опция может принимать одно из значений DEFAULT, OLDEST, RANDOM или YOUNGEST.
•
—bdb-logdir=путь. Каталог журнальных файлов BDB.
•
—bdb-no-recover. He запускать Berkley DB в режиме восстановления данных.
•
—bdb-no-sync. He сбрасывать синхронно на диск журналы BDB.
•
—bdb-shared-data. Запустить Berkley DB в режиме параллельной обработки. (Не используйте DBPRIVATE при инициализации Berkley DB.)
•
—bdb-tmpdir=nyrb. Каталог временных файлов BDB.
•
—skip-bdb. He использовать таблицы BDB.
См. раздел 4.2.1. Следующая системная переменная влияет на поведение таблиц BDB: • bdbmaxlock. Максимальное количество возможных блокировок, которые могут оставаться активными в таблице BDB. См. раздел 4.2.3. Если указать опцию --skip-bdb, MySQL не будет инициализировать библиотеку Berkley DB, что позволит сэкономить довольно-таки большой объем памяти. Однако в этом случае вы не сможете пользоваться таблицами BDB. Если вы попытаетесь создать таблицу BDB, MySQL создаст вместо нее таблицу My ISAM. Обычно, если вы не намерены использовать таблицы BDB, следует запускать mysqld без опции --bdb-no-recover. Однако если вы попытаетесь запустить mysqld при поврежденных журнальных файлах BDB, могут возникнуть проблемы. См. раздел 2.4.4. С помощью переменной bdb_max_lock можно задать максимальное количество блокировок, которые могут быть установлены на таблицу BDB. По умолчанию их количество составляет 10 000. Это значение следует увеличить, если при выполнении продолжительных транзакций, а также когда mysqld для выполнения запроса необходимо проверить множество строк, встречаются ошибки следующего рода: bdb: Lock table is out of available locks Got error 12 from . . . Можно также изменить переменные binlog_cache_size и max_binlog_cache_size, если будут применяться продолжительные транзакции с множеством операторов. См. раздел 4.8.4.
8.4.4. Характеристики таблиц BDB Каждая таблица BDB хранится на диске в виде двух файлов. Имя файла начинается с имени таблицы, а расширение указывает на тип файла. В файле . f rm хранится определение таблицы, а в файле . db - данные таблицы и индексы.
518
Глава 8. Механизмы хранения и типы таблиц в MySQL
Чтобы указать явно, что вы хотите работать с таблицей BDB, воспользуйтесь табличной опцией ENGINE или TYPE: CREATE TABLE t (i INT) ENGINE = BDB; CREATE TABLE t (i INT) TYPE = BDB; В опциях ENGINE и TYPE BerkleyDB является синонимом BDB. Механизм хранения BDB работает с транзакционными таблицами. Варианты использования этих таблиц зависят от режима автоматической фиксации: • Если вы работаете с включенной автоматической фиксацией (она включена по умолчанию), изменения в таблицах BDB будут незамедлительно фиксироваться, и не могут быть возвращены. • Если вы работаете с отключенной автоматической фиксацией, изменения не будут фиксироваться до тех пор, пока вы не выполните команду COMMIT. Вместо фиксации можно выполнить команду ROLLBACK, чтобы отменить внесенные изменения. Можно запустить транзакцию с помощью оператора BEGIN WORK, чтобы приостановить автоматическую фиксацию, или SET AUTOCOMMIT=0, чтобы запретить ее явным образом. Ниже представлены характеристики механизма хранения BDB. • Таблицы BDB могут иметь 31 индекс в таблице, 16 столбцов в индексе, а максимальный размер ключа может составлять 1024 байт (до выхода версии MySQL 4.0 этот размер составлял 500 байт). • Чтобы можно было уникальным образом идентифицировать каждую строку, в каждой таблице BDB должен присутствовать первичный ключ (PRIMARY KEY). Если вы сами не создадите его явным образом, MySQL создаст и будет поддерживать для вас скрытый первичный ключ. Скрытый ключ имеет длину 5 байт, и будет увеличиваться с каждой попыткой вставки данных. • Первичный ключ (PRIMARY KEY) будет работать гораздо быстрее, чем любой другой индекс, поскольку он хранится вместе с данными строки. Остальные индексы хранятся как данные ключа плюс первичный ключ, поэтому лучше всего работать с наименее коротким первичным ключом, что позволит увеличить скорость работы и сэкономить пространство на диске. Это же касается и таблиц InnoDB, в которых короткие первичные ключи позволяют экономить пространство диска не только в первичном, но и во вторичных индексах. • Если все столбцы, к которым вы производите обращение в таблице BDB, являются частью одного индекса или одного первичного ключа, MySQL может выполнить запрос, не обращаясь к самой строке. В таблице MylSAM это можно сделать только в том случае, если ее столбцы являются частью одного индекса. • Последовательное сканирование выполняется медленнее, чем в таблицах My ISAM, поскольку данные в таблицах BDB хранятся в В-деревьях, а не в отдельном файле данных. • Значения ключей не сжимаются в префиксах или суффиксах, как в таблицах My ISAM. Другими словами, информация о ключе в таблицах BDB занимает чуть больше места, чем в таблицах My ISAM.
8.4. Механизм хранения данных BDB (BerkleyDB)
519
• В таблице BDB имеются промежутки, в которые можно вставлять новые строки в середине индексного дерева. Как следствие, размер таблиц BDB превышает размер таблиц My IS AM. • Поскольку в таблицах BDB не поддерживаются счетчики строк, оператор SELECT COUNT (*) FROM имя_таблицы выполняется медленнее. • Оптимизатору необходимо знать приблизительное количество строк в таблице. MySQL определяет это значение, подсчитывая вставки и поддерживая его в отдельном сегменте в каждой таблице BDB. Если было выполнено всего несколько операторов DELETE или ROLLBACK, этого значения должно быть достаточно для оптимизатора MySQL. Однако MySQL сохраняет его только при закрытии, поэтому данное значение может оказаться ошибочным, если сервер вдруг прекратит свою работу. Следует иметь в виду, что если это значение не будет точным, ошибки все равно не произойдет. Значение счетчика строк можно будет обновить с помощью ANALYZE TABLE ИЛИ OPTIMIZE TABLE.
• Внутренняя блокировка в таблицах BDB выполняется на уровне страниц. • Оператор LOCK TABLES работает с таблицами BDB точно так же, как и с другими таблицами. Если LOCK TABLES не используется, MySQL устанавливает для данной таблицы внутреннюю блокировку множественной записи (благодаря которой не будут блокироваться другие потоки, осуществляющие запись). В результате, если другой поток установит блокировку таблицы, она заблокируется корректно. • Чтобы иметь возможность выполнять откаты транзакций, механизм хранения BDB поддерживает журнальные файлы. Для достижения максимальной производительности используется опция —bdb-logdir. В этой опции можно указать другой диск, на котором будут размещены журналы BDB (а не диск, на котором размещена сама база данных). • Когда начинается новый файл журнала BDB, MySQL выполняет контрольную проверку и удаляет любые журналы, не используемые для текущих транзакций. Выполнить контрольную проверку таблиц BDB в любое время можно с помощью оператора FLUSH LOGS. Чтобы выполнить восстановление после сбоя, необходимо использовать резервные копии таблиц и бинарный журнал MySQL. См. раздел 4.6.1. р
Внимание!
!| Если вы удалите старые журнальные файлы, которые все еще используются, BDB не сможет выff полнить восстановление, и в случае сбоя вы можете потерять данные.
• Приложения всегда должны быть готовы к обработке ситуаций, при которых всякое изменение в таблице BDB может вызвать автоматический откат, а всякое чтение может привести к взаимной блокировке. • Если таблица BDB заполняет все пространство на диске, выводится сообщение об ошибке (возможно, ошибка 28) и выполняется откат транзакции. В этом заключается отличие этих таблиц от таблиц My ISAM и ISAM, для которых mysqld будет ожидать появления достаточного объема дискового пространства, прежде чем продолжить работу.
520
Глава 8. Механизмы хранения и типы таблиц в MySQL
8.4.5. Что должно быть исправлено в механизме хранения BDB • Процесс одновременного открытия нескольких таблиц BDB происходит слишком долго. Для работы с таблицами BDB не нужно иметь слишком большой кэш таблицы (например, больше 256 Кбайт), и для клиента mysqld необходимо указывать опцию --no-auto-rehash. Мы планируем частично исправить это в версии MySQL 4.O. •
SHOW TABLE STATUS до сих пор не предоставляет достаточный объем информации по таблицам BDB.
• Необходимо оптимизировать производительность. • При сканировании таблиц необходимо отказаться от использования блокировок страниц.
8.4.6. Ограничения при использовании таблиц BDB Ниже приведен список ограничений, с которыми необходимо ознакомиться перед тем, как приступить к использованию таблиц BDB. • В файле .db содержится информация о том, где будет храниться создаваемый файл. Это необходимо для того, чтобы можно было обнаружить блокировки в многопользовательской среде, в которой поддерживаются символические ссылки. По причине этого файлы таблиц BDB нельзя перемещать из одного каталога базы данных в другой. • При создании резервных копий таблиц BDB вы должны либо использовать mysqldump, либо создавать резервную копию с файлами для каждой таблицы BDB (файлы .frm и .db) и журнальными файлами BDB. Механизм хранения BDB хранит незавершенные транзакции в своих журнальных файлах в каталоге данных; файлам присваиваются имена в виде log.XXXXXXXXXX (десять цифр). • Если столбец, в котором могут храниться значения NULL, имеет уникальный индекс, то в нем можно хранить только одно значение NULL. Это одно из отличий BDB от остальных механизмов хранения.
8.4.7. Ошибки, которые могут возникать при использовании таблиц BDB • Если при запуске mysqld возникает следующая ошибка, это означает, что новая версия BDB не поддерживает старый формат журнального файла: bdb: Ignoring log file: .../log.XXXXXXXXXX: unsupported log version # В этом случае потребуется удалить журналы BDB из каталога данных (файлы с именами в формате log.XXXXXXXXXX) и перезапустить mysqld. Мы рекомендуем также использовать mysqldump —opt, чтобы сохранить таблицы BDB, удалить старые файлы таблиц и восстановить данные из сохраненного файла. • Если при отключенном режиме автоматической фиксации удалить таблицу BDB, которая ссылается на другую транзакцию, в журнале ошибок MySQL может появиться следующие сообщения об ошибках:
8.5. Механизм хранения ISAM 001119 23:43:56 001119 23:43:56
bdb: bdb:
521 Missing log f i l e i d entry txn_abort: Log undo failed for LSN: 1 3644744: Invalid
Эти ошибки не являются фатальными, однако до тех пор, пока эта проблема не будет решена, мы рекомендуем не удалять таблицы BDB при включенном режиме автоматической фиксации. (Эта проблема является достаточно сложной.)
8.5. Механизм хранения ISAM Самым первым механизмом хранения в MySQL был ISAM. До выхода версии MySQL 3.23, в которой был представлен механизм MylSAM, это был единственный доступный механизм хранения. В настоящее время механизм ISAM используется очень редко. В версии MySQL 4.1 он включен в исходный код, однако не входит в состав бинарных дистрибутивов. Из версии MySQL 5.0 он будет полностью изъят. Встроенные версии сервера MySQL по умолчанию не поддерживают таблицы ISAM. Поскольку механизм ISAM используется крайне редко, а также по причине явного превосходства механизма My ISAM, мы рекомендуем преобразовать существующие таблицы ISAM в таблицы My ISAM с помощью оператора ALTER TABLE: mysql> ALTER TABLE имя_таблицы TYPE = MYISAM; Дополнительную информацию по MylSAM можно найти в разделе 8.1. Каждая таблица ISAM хранится на диске в виде трех файлов. Имя файла начинается с имени таблицы, а расширение указывает на тип файла. В файле . f rm содержится описание таблицы, файл данных имеет расширение .ISD, а индексный файл - расширение .ISM. В механизме ISAM применяются индексы в виде В-деревьев. Проверка или восстановление таблиц ISAM осуществляется с помощью утилиты isamchk. См. раздел 4.6.2.7. Таблица ISAM обладает следующими свойствами: • Сжатые ключи фиксированной длины. • Фиксированная и динамическая длина записи. •
16 индексов в таблице с 16 частями в каждом ключе.
• Максимальная длина ключа составляет 256 байт (по умолчанию). • Значения данных хранятся в машинном формате; это повышает скорость работы с данными, хотя и возникает зависимость от компьютера и операционной системы. Многие свойства таблиц MylSAM характерны и для таблиц ISAM. Однако между ними существует немало отличий, среди которых следует упомянуть такие: • Таблицы ISAM нельзя переносить между операционными системами и платформами в двоичном виде. • Не допускается работа с таблицами, размер которых превышает 4 Гбайт. • В строках поддерживается только сжатие префикса. • Ограничения по маленьким ключам (более строгие). • Динамические таблицы становятся более фрагментированными. • Не поддерживаются таблицы MERGE.
522
Глава 8. Механизмы хранения и типы таблиц в MySQL
• Проверка и восстановление поврежденных таблиц осуществляется с помощью утилиты isamchk, а не myisamchk. • Сжатие таблиц производится посредством утилиты pack_isam, а не myisampack. • Нельзя использовать операторы создания резервных копий BACKUP TABLE или RESTORE TABLE. • Нельзя использовать операторы обслуживания таблиц CHECK TABLE, REPAIR TABLE, OPTIMIZE
TABLE ИЛИ ANALYZE TABLE.
• He поддерживается полнотекстовый поиск и пространственные типы данных. • Таблицы не поддерживают множественные символьные наборы. • Индексы не могут присваиваться кэшам определенных ключей.
9 Механизм хранения InnoDB 9.1. Обзор InnoDB InnoDB является транзакционным (совместимым с ACID) механизмом хранения MySQL, который позволяет фиксировать транзакции, выполнять их откат, а также восстанавливать данные после сбоя. Для таблиц InnoDB доступна блокировка на уровне строки и используется метод согласованного чтения без блокировок в операторах SELECT (так же, как в Oracle). Эти функции улучшают параллелизм и повышают производительность в многопользовательском режиме. Для InnoDB не требуется расширение блокировки, поскольку блокировки на уровне строки в этих таблицах занимают очень мало места. Для таблиц InnoDB поддерживаются ограничения FOREIGN KEY. В запросах SQL вы можете свободно сочетать таблицы типа InnoDB с таблицами другого типа MySQL, даже в одном и том же запросе. Механизм хранения данных InnoDB разрабатывалась с той целью, чтобы обеспечить максимальную производительность при обработке больших объемов данных. По эффективности использования процессора ей нет равных среди других моделей реляционных баз данных с сохранением на диске. Будучи полностью интегрированным в сервер MySQL, механизм InnoDB поддерживает свой собственный буферный пул для кэширования данных и индексов в основной памяти. InnoDB хранит свои таблицы и индексы в пространстве памяти, которое может состоять из нескольких файлов (или низкоуровневых разделов диска). В этом заключается отличие InnoDB от, например, механизма My ISAM, в котором каждая таблица хранится в отдельном файле. Таблицы InnoDB могут иметь любой размер даже в тех операционных системах, в которых он ограничен 2 Гбайт. Начиная с версии MySQL 4.0, InnoDB входит в состав бинарного дистрибутива. Дополнительную информацию о поддержке таблиц InnoDB в MySQL 3.23 можно найти в разделе 9.3. Таблицы InnoDB применяются в многочисленных крупных сайтах, взаимодействующих с базами данных и, соответственно, требующих высокой производительности. Так, например, механизм InnoDB используется на популярном сайте новостей Slashdot.org. Формат InnoDB применяется для хранения более 1 Тбайт данных в компании Mytrix, Inc., а еще на одном сайте механизм InnoDB позволяет справляться с нагрузкой, исчисляемой в среднем 800 вставками/обновлениями в секунду.
524
Глава 9. Механизм хранения InnoDB
InnoDB распространяется на условиях общедоступной лицензии GNU GPL версии 2 (с июня 1991 года). Если вы занимаетесь распространением MySQL/InnoDB и ваше приложение не отвечает требованиям лицензионного соглашения GPL, вам следует приобрести коммерческую лицензию MySQL Pro на сайте: https://order.mysql.com/?sub=pg&pg_no=l
9.2. Контактная информация, касающаяся InnoDB Ниже представлена контактная информация Innobase Oy, производителя механизма хранения InnoDB: Web-сайт: http://www.InnoDB.com/ Электронная почта:
[email protected] Телефон: +358-9-6969 3250 (офис) +358-40-5617367 (мобильный) Innobase Oy Inc. World Trade Center Helsinki Aleksanterinkatu 17 P.O. Box 800 00101 Helsinki Finland
9.3. Таблицы InnoDB в MySQL 3.23 Начиная с версии MySQL 4.0, таблицы InnoDB доступны по умолчанию, поэтому представленная ниже информация касается только MySQL 3.23. Начиная с версии MySQL 3.23.34а, таблицы InnoDB входят в состав исходного дистрибутива MySQL и задействованы в бинарных файлах MySQL-Max серии 3.23. Для Windows бинарные файлы MySQL-Max включены в стандартный дистрибутив. Если вы загрузили бинарную версию MySQL, которая включает поддержку InnoDB, вам будет достаточно выполнить инструкции руководства по установке бинарной версии MySQL. Если у вас уже установлена MySQL 3.23, тогда самый простой способ установки MySQL-Max будет заключаться лишь в том, чтобы заменить исполняемый файл mysqld соответствующим файлом из дистрибутива MySQL-Max. MySQL и MySQL-Max отличаются только исполняемыми файлами сервера. См. разделы 2.2.5 и 4.1.2. Чтобы скомпилировать MySQL с поддержкой InnoDB, загрузите версию MySQL 3.23.34а или более новую версию с сайта http://www.mysql.com/ и сконфигурируйте MySQL с опцией —with-InnoDB. См. раздел 2.3. Чтобы использовать таблицы InnoDB в MySQL 3.23, необходимо указать конфигурационные параметры InnoDB в разделе [mysqld] файла my.cnf. В Windows для этого используется файл my.ini. Если не сконфигурировать InnoDB в файле опций, механизм InnoDB запустить не удастся. (Начиная с версии MySQL 4.0, если вы не указываете свои параметры, в InnoDB используются параметры, принятые по умолчанию. Чтобы достичь наиболее высокой производительности, рекомендуется выбирать значения параметров в соответствии с требованиями вашей системы; об этом говорится в разделе 9.4.)
9.4. Конфигурация InnoDB
525
Минимальным требованием конфигурирования файлов данных InnoDB в версии MySQL 3.23 является установка значения innodb_data_file_path. Например, чтобы сконфигурировать InnoDB для использования одного автоматически расширяющегося файла данных размером 10 Мбайт, в раздел [mysqld] файла опций необходимо поместить следующие строки: [mysqld] innodb_data_file_path=ibdata:ЮМ:autoextend По умолчанию InnoDB создает файл ibdatal в каталоге данных MySQL. Для явного указания местоположения файла служит параметр innodb_data_home_dir. См. раздел 9.4.
9.4. Конфигурация InnoDB Вопросам использования таблиц InnoDB в MySQL 3.23 посвящен раздел 9.3. Начиная с версии MySQL 4.0, InnoDB используется по умолчанию. Если вас не интересуют таблицы InnoDB, в файле опций MySQL добавьте опцию skip-InnoDB. InnoDB управляет двумя дисковыми ресурсами - файлами данных табличного пространства и файлами журналов. Если вы не укажете параметры конфигурации InnoDB, в MySQL 4.0 и выше будет создан автоматически расширяющийся файл размером 10 Мбайт с именем ibdatal и два файла журналов размером по 5 Мбайт каждый с именами ib_logfileO и ib_logfilel в каталоге данных MySQL (в MySQL 4.0.0 и 4.0.1 размер файла данных составляет 64 Мбайт, причем он не является автоматически расширяющимся). В MySQL 3.23 InnoDB без параметров конфигурации запускать нельзя. На заметку! Чтобы достичь высокой производительности, необходимо явным образом задать параметры InnoDB, представленные в следующих примерах. Естественно, вы будете иметь дело с собственными значениями параметров, которые соответствуют существующему оборудованию и удовлетворяют конкретным требованиям.
Для настройки файлов табличного пространства InnoDB применяется опция innodb_data_file_path в разделе [mysqld] файла my.cnf. В среде Windows используется файл my.ini. В качестве значения innodb_data_file_path необходимо указать перечень спецификаций одного или нескольких файлов данных. Если вы перечисляете несколько файлов данных, для их разделения следует использовать точку с запятой: innodb_data_file_path= спецификация_файла_данных1 [; спецификация_файла_данных2) . . .
Далее показан пример параметра настройки, явным образом создающего табличное пространство, которое имеет те же характеристики, что и характеристики, используемые по умолчанию в MySQL 4.0: [mysqld] innodb_data_file_path=ibdatal:ЮМ:autoextend В данном примере указываются параметры одиночного автоматически расширяющегося файла размером 10 Мбайт с именем ibdatal. Размещение этого файла не указано, поэтому по умолчанию он попадет в каталог данных MySQL. Размеры файла указываются с помощью суффиксов М и G, соответственно для Мбайт и Гбайт.
526
Глава 9. Механизм хранения InnoDB
Табличное пространство, содержащее файл данных ibdatal с фиксированным размером 50 Мбайт и автоматически расширяющийся файл ibdata2 размером 50 Мбайт в каталоге данных можно сконфигурировать следующим образом: [mysqld] innodb_data_file_path=ibdatal:50М;ibdata2:50M:autoextend Полный синтаксис спецификации файла данных включает имя файла, его размер и несколько необязательных атрибутов: имя файла:размер_файла (: autoextend (: max:максимальный_размер_файла))
Атрибут autoextend, а также последующие атрибуты, могут использоваться только для последнего файла данных в строке innodb_data_file_path. Атрибут autoextend доступен, начиная с версий MySQL 3.23.50 и 4.0.2. Если атрибут autoextend задать для последнего файла данных, то InnoDB увеличит размер файла данных после того, как он займет все свободное место в табличной области. С каждым новым увеличением файл будет получать дополнительные 8 Мбайт. Если текущий диск окажется заполненным, можно будет добавить еще один файл данных, но уже на другом диске. Инструкции по перестройке существующего табличного пространства представлены в разделе 9.8. Механизму InnoDB не известно о максимально возможном размере файла, поэтому следует быть внимательным при работе с файловыми системами, в которых размер файла ограничен 2 Гбайт. Чтобы задать максимальный размер для автоматически расширяющегося файла данных, используйте атрибут max. Ниже показан пример того, как можно увеличить предельно допустимый размер файла ibdatal до 500 Мбайт: [mysqld] innodb_data_file_path=ibdatal:10M:autoextend:max:500M По умолчанию InnoDB создает файлы табличного пространства в каталоге данных MySQL. Чтобы явным образом указать местоположение файлов, воспользуйтесь опцией innodb_data_home_dir. Например, чтобы использовать два файла с именами ibdatal и ibdata2 в каталоге /ibdata, необходимо сконфигурировать InnoDB следующим образом: [mysqld] innodb_data_home_dir=/ibdata innodb_data_file_path=/ibdatal:50M;ibdata2:50M:autoextend
II На заметку! ы InnoDB не создает каталоги, поэтому перед запуском сервера потребуется проверить, существуЬ ет ли каталог / i b d a t a . Это справедливо также и для конфигурируемых вами каталогов жур|; нальных файлов. Для создания каталога выполните команду mkdir в Unix или DOS.
InnoDB формирует путь к каталогу для каждого файла данных, присоединяя innodb_data_home_dir к имени файла данных, при необходимости добавляя прямую или обратную косую черту. Если параметр innodb_data_home_dir вообще не указан в файле my.cnf, то по умолчанию будет использоваться каталог "точка" ./, который обозначает каталог данных MySQL. Если определить параметр innodb_data_home_dir как пустую строку, тогда можно будет указать абсолютные пути к файлам данных, перечисленных в списке innodb_data_f ilejpath. Следующий пример аналогичен предыдущему:
9.4. Конфигурация InnoDB
527
[mysqld] innodb_data_home_dir=innodb_data_file_path= ibdata/ibdatal:50M/ibdata/ibdata2:50M:autoextend Простой пример файла my.cnf Предположим, что у вас есть компьютер с ОЗУ объемом 128 Мбайт и одним жестким диском. В предложенном ниже примере показаны возможные конфигурационные параметры в файле my.cnf или my.ini для InnoDB. Предполагается, что у вас установлена версия MySQL-Max 3.23.50 и выше или MySQL 4.0.2 и выше, поскольку в этом примере используется параметр autoextend. Этот пример будет интересен тем пользователям Unix и Windows, которые не хотят размещать свои файлы данных и файлы журналов на различных дисках. Здесь создается автоматически расширяющийся файл ibdatal и два файла журналов ib_logfileO и ib_logfilel в каталоге данных MySQL. Кроме этого, в этом каталоге находится небольшой автоматически создаваемый InnoDB архивный файл журнала ib_arch_log_0000000000: [mysqld] # Сюда можно добавить другие параметры сервера MySQL # ... # Файлы данных должны иметь достаточный размер для # для хранения ваших данных и индексов. # Убедитесь что у вас достаточно # свободного места на диске. innodb_data_file_path = ibdatal:10M:autoextend # # Размер буферного пула должен составлять # от 50 до 80% памяти вашего компьютера, set-variable = innodb_buffer_pool_size=70M set-variable = innodb_additional_mem_pool_size=10M # # Размер журнального файла должен составлять # около 25% от размера буферного пула, set-variable = innodb_log_file_size=20M set-variable = innodb_log_buffer_size=8M # innodb_flush_log_at_trx_commit=l Убедитесь в том, что сервер MySQL имеет права на создание файлов в каталоге данных. Как правило, сервер должен иметь права доступа к любому каталогу, в котором ему необходимо создать файлы данных и файлы журналов. Не забывайте, что в некоторых файловых системах размер файла не должен превышать 2 Гбайт. Общий размер файлов журналов должен быть менее 4 Гбайт, а общий размер файлов данных - как минимум 10 Мбайт. Когда вы впервые создаете табличное пространство InnoDB, лучше всего запустить сервер MySQL из командной строки. Тогда на экран будет выводиться информация о создании базы данных, и вы сможете следить за происходящими событиями. Например, если в системе Windows mysqld-max расположен в каталоге C:\mysql\bin, его можно запустить следующим образом: С:\> С:\mysql\bin\mysqld-max
—console
Глава 9. Механизм хранения InnoDB
528
Если вы не направляете вывод сервера на экран, просмотрите журнал регистрации ошибок сервера, чтобы узнать, какую информацию выводит InnoDB во время запуска. В разделе 9.6 можно найти пример информации, выводимой InnoDB. Где указывать параметры в Windows? Для Windows существуют следующие правила: • Должен быть создан только один файл - my. cnf или ту. ini. • Файл ту. cnf должен находиться в корневом каталоге диска С:. • Файл my.ini должен находиться в каталоге WINDIR; например, в C:\WINDOWS или C:\WINNT. Для просмотра значения WINDIR воспользуйтесь командой SET в командной строке: С:\> SET WINDIR Windir=C:\WINNT • Если в компьютере используется начальный загрузчик, в котором диск С: не является загрузочным, необходимо использовать файл my. ini. Где указываются параметры в Unix? В Unix mysqld считывает параметры из следующих файлов, если они существуют, в таком порядке: •
/etc/my, cnf. Общие параметры.
•
КАТАЛОГ_ДАННЫХ/my.cnf. Параметры сервера.
• defaults-extra-file. Файл, указанный в параметре —defaults-extra-file. •
~/.my. cnf. Параметры пользователя.
КАТАЛОГ_ДАННЫХ обозначает каталог данных MySQL, который был определен в качестве опции для configure при компиляции mysqld (обычно /usr/local/mysql/data для установки исполняемых файлов или /usr/local/var для установки исходного кода). Если вы хотите убедиться в том, что mysqld считывает параметры только из определенного файла, то при запуске сервера можно указать --defaults-option как первую опцию в командной строке: mysqld —defaults-file=Bam_nyTb_K_my_cnf Расширенный пример файла my.cnf Предположим, что у вас есть компьютер, работающий под управлением Linux, с ОЗУ 2 Гбайт и тремя жесткими дисками по 60 Гбайт (с путями к каталогам /, /dr2 и /dr3). В приведенном ниже примере показаны вероятные параметры конфигурации в файле my. cnf для InnoDB. [mysqld] # Здесь вы можете задать другие параметры сервера MySQL # ... innodb_data_home_dir = # # Файлы данных должны иметь достаточный размер для # хранения ваших данных и индексов. # Введите полное значение innodb__data_file_path в одной строке. innodb_data_file_path=/ibdata/ibdatal:2000M;
9.4. Конфигурация InnoDB
529
/dr2/ibdata/ibdata2:2000M:autoextend # # Размер буферного пула должен составлять # от 50 до 80% памяти вашего компьютера; # пользователям Linux x86 следует убедиться, что # общая занимаемая память не превышает 2 Гб. set-variable = innodb_buffer_pool_size=lG set-variable = innodb_additional_mem_pool_size=20M innodb_logjgroup_home_dir = /dr3/iblogs # # innodb_log_arch_dir должен быть таким же, # как и innodb_log_group_home_dir # (начиная с версии 4.0.6, этот параметр можно опустить). innodb_log_arch_dir = /dr3/iblogs set-variable = innodb_log_files_in_group=2 # # Размер файла журнала должен составлять # около 15% от размера буферного пула, set-variable = innodb_log_file_size=250M set-variable = innodb_log_buffer_size=8M # innodb_flush_log_at_trx_commit=l set-variable = innodb_lock_wait_timeout=50 # # Уберите комментарий со следующих строк, если # они должны использоваться. #innodb_flush_method=fdatasync #set-variable = innodb_thread_concurrency=5 Обратите внимание на то, что два файла данных размещены на разных дисках. InnoDB будет заполнять табличное пространство, начиная с первого файла данных. В некоторых случаях это позволяет повысить производительность базы данных, если не все данные размещены на одном физическом диске. Размещение файлов журналов на другом диске зачастую способствует повышению производительности. Для файлов данных InnoDB можно также использовать низкоуровневые разделы диска (низкоуровневые устройства), что может позволить ускорить процессы ввода-вывода. См. раздел 9.15.2. % Внимание! Ъ i; 5 ъ,
В GNU/Linux x86 нельзя устанавливать слишком большой процент используемой памяти. g l i b c позволит разрастись куче процесса и превысить стеки потоков, что приведет к сбою сервера. Степень риска будет гораздо выше, если эта величина приблизится или превысит значение 2 Гбайт:
Н/ innodb_buffer_pool_size i + key_buffer \ |; + max__connections * (sort_buffer_size+read_buffer_size+binlog__cache__size) y: + max_connections * 2 Мб Каждый поток будет использовать стек (обычно 2 Мбайт, а в бинарных дистрибутивах от компании MySQL AB только 256 Кбайт) и, в худшем случае, также дополнительную память, равную sort_buf fer_size + read_buf fer_size.
Глава 9. Механизм хранения InnoDB
530
Начиная с версии MySQL 4.1, вы можете использовать до 64 Гбайт памяти в 32разрядной операционной системе Windows. См. описание innodb_buf fer_pool_awe_mem_mb в разделе 9.5. Как настроить другие параметры сервера mysqld? Для большинства пользователей подойдут следующие стандартные значения: [mysqld] skip-external-locking set-variable = max_connections=200 set-variable = read__buffer_size=lM set-variable = sort_buffer=lM # # Размер key_buffer должен составлять # 5-50% вашего ОЗУ, в зависимости # от частоты использования # таблицы MylSAM, a key_buffer_size + # размер буферного пула InnoDB не должен # превышать 80% вашего ОЗУ. set-variable = key_buffer size=...
9.5. Опции запуска InnoDB В этом разделе описаны серверные опции, связанные с InnoDB. В версии MySQL 4.0 и выше их можно определить в виде —имя_опции= значение в командной строке или файлах опций. До выхода версии MySQL 4.0 числовые опции должны были указываться с использованием синтаксиса —set-va.riable=HMH_onu,HH= значение или -0 имя_опции= значение. •
innodb_additional_mem_pool_size. Размер пула памяти, который InnoDB использует для хранения информации словаря данных и других внутренних структур данных. Чем больше таблиц имеется в вашем приложении, тем больше информации нужно будет разместить в этом пуле. Если памяти в этом пуле окажется мало, для InnoDB будет выделена память операционной системы, а в журнал регистрации ошибок MySQL будут записываться предупреждающие сообщения. Значение по умолчанию - 1 Мбайт. • innodb_buf fer_pool_awe_mem_mb. Размер буферного пула (в мегабайтах), если он установлен в памяти AWE 32-разрядной Windows. Доступен, начиная с версии MySQL 4.1.0, и действителен только в среде 32-разрядной Windows. Если ваша 32-разрядная Windows поддерживает более 4 Гбайт памяти (так называемые адресные расширения Address Windowing Extentions, AWE), то с помощью этого параметра вы сможете разместить буферный пул InnoDB в физической памяти AWE. Максимально возможное значение для этого параметра составляет 64000. Если этот параметр указан, innodb_buffer_pool_size будет соответствовать окну в 32-разрядном адресном пространстве mysqld, в котором InnoDB будет отображать память AWE. Наиболее предпочтительным значением для innodb_buffer_pool_size является 500 Мбайт. •
innodb_buf fer_pool_size. Размер буфера памяти, который InnoDB использует для занесения данных и индексов своих таблиц в кэш. Чем больше это значение, тем меньше будет происходить обращений к диску для извлечения данных из таблиц.
9.5. Опции запуска InnoDB
531
На выделенном сервере баз данных этому параметру можно присвоить значение, равное примерно 80% физической памяти компьютера. Однако присваивать слишком большое значение не рекомендуется, так как при недостатке физической памяти операционная система будет вынуждена сбрасывать часть информации на диск. •
innodb_data__f ile_path. Пути к отдельным файлам данных и их размеры. Полный путь к каталогу каждого файла данных можно получить посредством объединения innodb__data_home_dir с путем, который указанным в данном параметре. Размеры файлов указываются в мегабайтах или гигабайтах (1 Гбайт = 1024 Мбайт) путем добавления к величине размера суффикса М или G. Совокупный размер файлов должен составлять как минимум 10 Мбайт. В некоторых операционных системах файлы должны иметь размер меньше 2 Гбайт. Если вы не укажете параметр innodb_data_filejpath, то в этом случае будет создан автоматически расширяющийся файл данных размером 10 Мбайт с именем ibdatal (справедливо для версии MySQL 4.0 и выше). Начиная с версии 3.23.44, в операционных системах, поддерживающих файлы большого размера, можно задавать файл, размер которого будет превышать 4 Гбайт. Вы можете также использовать низкоуровневые разделы диска. См. раздел 9.15.2.
•
innodb_data_home_dir. Общая часть пути к каталогу всех файлов данных InnoDB. Если этот параметр не указывать, то по умолчанию для него будет использоваться каталог данных MySQL. Если задать этот параметр как пустую строку, тогда в параметре innodb_data__file__path можно будет использовать абсолютные пути к файлам.
•
innodb_fast_shutdown. По умолчанию перед закрытием InnoDB выполняет полную чистку и слияние буфера вставок. На это уходит несколько минут, а то и часов. Если этому параметру присвоить значение 1, то при закрытии InnoDB пропустит упомянутую операцию. Этот параметр доступен, начиная с версий MySQL 3.23.44 и 4.0.1. Значение по умолчанию 1 используется, начиная с версии 3.23.50.
•
innodb_file_to_threads. Количество потоков ввода-вывода в InnoDB. Обычно этому параметру присваивается значение 4. Однако если в Windows этому параметру присвоить большее значение, тогда можно будет добиться сокращения количества обращений к диску. В Unix увеличение этого значения не будет иметь никакого эффекта. InnoDB всегда использует значение, принятое по умолчанию. Этот параметр доступен, начиная с версии MySQL 3.23.37.
•
innodb_file_per_table. Благодаря этой опции, InnoDB создает каждую новую таблицу с помощью своего собственного файла . ibd (а не совместно используемого табличного пространства), в котором сохраняются данные и индексы. См. раздел 9.7.6. Эта опция доступна, начиная с версии MySQL 4.1.1. • innodb_flush_log_at_trx_commit. Обычно этой опции присваивается значение 1, в результате чего после фиксации транзакции информация журнала записывается на диск, и фиксируются изменения, внесенные транзакцией. Это позволяет сохранить данные в случае повреждения базы данных. Если у вас выполняются небольшие транзакции, и вы готовы пожертвовать такой безопасностью, то этой опции можно присвоить значение 0 или 2, что позволит снизить количество обращений к диску. При нулевом значении запись сохраняется в журнальном файле,
Глава 9. Механизм хранения InnoDB
532
который сбрасывается на диск примерно один раз в секунду. Если присвоить значение 2, тогда запись в журнальный файл будет производиться во время выполнения каждой транзакции. По умолчанию используется значение 1 (до выхода версии MySQL 4.0.13 по умолчанию использовалось нулевое значение). •
innodb_f lushjnethod. Эта опция работает только в системах Unix. Если установить для нее значение fdatasync, то InnoDB будет использовать функцию fsyncO для сброса файлов данных и файлов журналов. Если присвоить значение O_DSYNC, тогда InnoDB будет применять 0_SYNC для открытия и сброса файлов журналов, а f sync () - для сброса файлов данных. Если указать 0_DIRECT (это значение доступно в некоторых версиях GNU/Linux, начиная с версии MySQL 4.0.14), тогда InnoDB будет использовать его для открытия файлов данных, a fsyncO - для сброса файлов данных и файлов журналов. Следует отметить, что InnoDB не использует f datasynk или O_DSYNK по умолчанию, поскольку во многих операционных системах семейства Unix они не работают. Этот параметр доступен, начиная с версии MySQL 3.23.40. • innodb_force_recovery
|! Внимание! || || || lm
Эта опция используется только в крайних случаях для сброса таблиц из поврежденной базы данных! Допустимыми значениями являются 1-6 (каждое из них описано в разделе 9.9.1). В целях безопасности InnoDB запрещает пользователю изменять данные, когда значение этого napaметра больше 0. Параметр доступен, начиная с версии MySQL 3.23.44.
• innodb_lock_wait_timeout. Время тайм-аута (в секундах), на протяжении которого транзакция InnoDB может ожидать блокировку до того, как будет произведен ее откат. InnoDB автоматически обнаруживает взаимные блокировки транзакций в своей таблице блокировок и выполняет их откат. Если вы используете LOCK TABLES или работаете с другими механизмами хранения с транзакциями, отличными от InnoDB, то в случае взаимной блокировки InnoDB не сможет его обнаружить. В подобных ситуациях устранить проблему поможет тайм-аут. По умолчанию время тайм-аута составляет 50 секунд. •
innodb_log_archjdir. Каталог, в который будут записываться заархивированные заполненные файлы журналов (при условии, что используется функция архивирования журналов). Значение этой опции на настоящий момент должно быть таким же, как и для опции innodb_log_group_home_dir. Начиная с версии 4.0.6, эту опцию можно опускать.
•
innodb_log_archive. На данный момент этому параметру необходимо присваивать нулевое значение. Поскольку восстановление из резервной копии MySQL осуществляет с помощью своих собственных файлов журналов, архивировать файлы журналов InnoDB не нужно. По умолчанию используется нулевое значение.
•
innodb_log_buffer_size. Размер буфера, который используется в InnoDB для записи журнальных файлов на диск. Лучше всего устанавливать размер в пределах 1-8 Мбайт. По умолчанию устанавливается размер 1 Мбайт. Большой буфер журналов позволяет выполнять большие транзакции, не записывая журнал на диск до завершения выполнения транзакции. Поэтому если вы работаете с большими транзакциями, увеличение размера буфера журналов приведет к сокращению количества дисковых операций ввода-вывода.
9.5. Опции запуска InnoDB •
533
innodb_log_file__size. Размер каждого журнального файла в группе журналов. Общий размер журнальных файлов на 32-разрядных компьютерах не должен превышать 4 Гбайт. По умолчанию принимается размер 5 Мбайт. Размер лучше всего подбирать таким, чтобы он составлял от 1 Мбайт до Ш от размера буферного пула, где N- это количество файлов журналов в группе. Чем больше это значение, тем меньше придется выполнять контрольных сбросов содержимого на диск из буферного пула, что приведет к сокращению количества дисковых операций ввода-вывода. Однако в этом есть и негативный момент: в случае сбоя на восстановление файлов больших размеров потребуется гораздо больше времени.
• innodb_log__f iles_in_group. Количество журнальных файлов в группе журналов. InnoDB выполняет запись в файлы циклически. Этой опции рекомендуется присваивать значение 2. •
innodb_log_group_home_dir. Путь к каталогу журнальных файлов InnoDB. Эта опция должна иметь то же значение, что и опция innodb_log_arch_dir. Если вы не укажете параметры журнала InnoDB, то в каталоге данных MySQL по умолчанию будут созданы два файла размером по 5 Мбайт с именами ib__logfileO и ib_logfilel.
•
innodb_max_dirty_pages_pct. Целое число в диапазоне от 0 до 100. По умолчанию используется 90. Главный поток в InnoDB пытается сбросить страницы из буферного пула, поэтому практически все эти страницы в определенный момент времени нельзя будет сбросить. Опция доступна, начиная с версий 4.0.13 и 4.1.1. Если вы имеете права суперпользователя (SUPER), то сможете изменять величину этого процента во время работы сервера. Это можно сделать следующим образом: SET GLOBAL innodb_max_dirty_pages_pct=3HaveHne;
•
innodb_mirrored_log_groups. Количество идентичных копий групп журналов, которые хранятся для базы данных. На текущий момент этому параметру должно быть присвоено значение 1. • innodb_open_files. Этот параметр используется только в том случае, когда в InnoDB задействовано множество табличных пространств. В нем указывается максимальное количество файлов . ibd, которые InnoDB может одновременно держать открытыми. Минимальное значение - 10. По умолчанию этому параметру присваивается значение 300. Параметр доступен, начиная с версии MySQL 4.1.1. Файловые дескрипторы, используемые для файлов .ibd, предназначены только для InnoDB. Они не зависят от параметра сервера --open-files-limit и не влияют на работу кэша таблиц. • innodb_thread_concurrency. InnoDB пытается работать параллельно с несколькими потоками операционной системы внутри InnoDB, причем их количество должно быть меньше или равно предельному значению, указанному в этой опции. По умолчанию опции присваивается значение 8. Если показатели производительности невысокие, а команда SHOW INNODB STATUS выявила множество потоков, ожидающих семафоры, это означает, что вы столкнулись с явлением, называемым "пробуксовкой" потоков (thread thrashing). В подобных ситуациях необходимо присвоить этому параметру меньшее или большее значение. Если вы работаете на компьютере с большим количеством процессоров и дисков, этому параметру можно присвоить более высокое значение, что позволит повысить степень ис-
534
Глава 9. Механизм хранения InnoDB пользования ресурсов компьютера. Рекомендуется, чтобы это значение было равно сумме количества процессоров и дисков вашей системы. Если значение будет равно 500 или больше, вы не сможете выполнять проверку параллельного выполнения операций. Параметр доступен, начиная с версий MySQL 3.23.44 и 4.0.1.
9.6. Создание табличного пространства InnoDB Предположим, что вы установили MySQL и внесли в файл my.cnf необходимые конфигурационные параметры InnoDB, Прежде чем запустить MySQL, необходимо убедиться, что указанные каталоги для файлов данных и журналов InnoDB существуют, и что сервер MySQL имеет права для доступа к этим каталогам. InnoDB может создавать только файлы, но не каталоги. Проверьте также, имеется ли достаточно свободного дискового пространства для файлов данных и журналов. Лучше всего запускать сервер MySQL из командной строки во время создания базы данных InnoDB, а не из оболочки mysqldsafe или в качестве службы Windows. Так вы сможете наблюдать за происходящим и просматривать выходную информацию mysqld. Если вы работаете в среде Unix, необходимо запустить демон mysqld. В Windows потребуется указать опцию --console. Теперь, после того как механизм InnoDB первоначально сконфигурирован с помощью файла опций, InnoDB создаст ваши файлы данных и файлы журналов. При этом будет выведена примерно такая информация: InnoDB: The f i r s t specified datafile /home/heikki/data/ibdatal did not e x i s t : InnoDB: a new database to be created! InnoDB: Setting file /home/heikki/data/ibdatal size to 134217728 InnoDB: Database physically writes the file full: wait... InnoDB: datafile /home/heikki/data/ibdata2 did not exist: new to be created InnoDB: Setting file /home/heikki/data/ibdata2 size to 262144000 InnoDB: Database physically writes the file full: wait... InnoDB: Log file /home/heikki/data/logs/ib_logfileO did not exist: new to be created InnoDB: Setting log file /home/heikki/data/logs/ib_logfileO size to 5242880 InnoDB: Log file /home/heikki/data/logs/ib_logfilel did not exist: new to be created InnoDB: Setting log file /home/heikki/data/logs/ib_logfilel size to 5242880 InnoDB: Log file /home/heikki/data/logs/ib_logfile2 did not exist: new to be created InnoDB: Setting log file /home/heikki/data/logs/ib_logfile2 size to 5242880 InnoDB: Started MySQLd: ready for connections Здесь была создана новая база данных InnoDB. К серверу MySQL можно подключиться посредством обычных клиентских программ MySQL, подобных mysql. Если работу сервера MySQL завершить с помощью команды mysqladmin shutdown, будет выведена следующая информация: 010321 18:33:34 mysqld: Normal shutdown 010321 18:33:34 mysqld: Shutdown Complete InnoDB: Starting shutdown... InnoDB: Shutdown completed
9.7. Создание таблиц InnoDB
535
Теперь можно просмотреть каталоги файлов данных и журналов, чтобы увидеть созданные файлы. Каталог журналов будет содержать небольшой файл ib_arch_log_0000000000. Этот файл появляется в результате создания базы данных, после чего InnoDB отключает архивирование журналов. Когда MySQL будет запущена вновь, файлы данных и файлы журналов уже будут созданы, поэтому выводимая информация будет гораздо короче: InnoDB: Started mysqld: ready for connections
9.6.1. Проблемы, связанные с инициализацией InnoDB Если при работе с файлом InnoDB выдает ошибку операционной системы, вероятно, причиной может быть одна из перечисленных ниже: • Вы не создали каталоги для файлов данных или журналов InnoDB. • У mysqld нет прав для создания файлов в этих каталогах. • mysqld не прочитал нужный файл my.cnf или my.ini и, соответственно, не получил указанные вами опции. • Диск переполнен или превышена квота использования диска. • Вы создали подкаталог, имя которого совпадает с указанным файлом данных. • Синтаксическая ошибка в параметре innodb_data_home_dir или innodb_data_file_path. Если в тот момент, когда InnoDB пытается инициализировать свое табличное пространство или свои журнальные файлы что-то происходит не так, необходимо удалить все файлы, созданные InnoDB. К ним относятся все файлы данных, все файлы журналов и небольшой заархивированный журнальный файл. Если вы уже создали какие-то таблицы InnoDB, вам придется удалить файлы . f rm этих таблиц (и любые файлы . ibd, если вы работаете с множеством табличных пространств), которые находятся в каталогах баз данных MySQL. После этого можно попробовать создать базе данных InnoDB еще раз. Лучше всего запускать сервер MySQL из командной строки, дабы иметь возможность наблюдать за происходящим.
9.7. Создание таблиц InnoDB Предположим, что вы запустили клиент MySQL с помощью команды mysql t e s t . Чтобы создать таблицу в формате InnoDB, в SQL-операторе создания таблицы потребуется указать опцию ENGINE = InnoDB или TYPE = InnoDB: CREATE TABLE customers (a INT, b CHAR (20), INDEX (a)) ENGINE=InnoDB; CREATE TABLE customers (a INT, b CHAR (20), INDEX (a)) TYPE=InnoDB; SQL-оператор создает таблицу и индекс по столбцу а табличного пространства InnoDB, которое состоит из файлов данных, указанных в файле my.cnf. Кроме этого, в подкаталоге t e s t каталога баз данных MySQL создается файл customers.frm. В свой собственный словарь данных InnoDB добавляет запись для таблицы ' t e s t / c u s t o m e r s ' . Эта запись означает, что вы можете создать таблицу с таким же именем customers в другой базе данных, и это не приведет к возникновению конфликта имен таблиц в рамках InnoDB.
536
Глава 9. Механизм хранения InnoDB
С помощью команды SHOW TABLE STATUS для любой таблицы InnoDB можно запросить количество свободного пространства в табличном пространстве InnoDB. Количество свободного пространства будет выводиться в разделе Comment выходной информации команды SHOW TABLE STATUS, например: SHOW TABLE STATUS FROM t e s t LIKE ' c u s t o m e r s ' Обратите внимание, что статистические данные, которые команда SHOW выдает по таблицам InnoDB, являются приблизительными. Они используются в целях оптимизации SQL. А вот точными являются зарезервированные размеры таблиц и индексов, значения которых указываются в байтах.
9.7.1. Как использовать транзакции InnoDB в разных API-интерфейсах По умолчанию каждый клиент, соединяющийся с сервером MySQL, начинает работу в режиме автоматической фиксации, при котором каждый SQL-оператор выполняется автоматически. Чтобы использовать транзакции с несколькими операторами, можно выключить автоматическую фиксацию с помощью SQL-оператора SET AUTOCOMMIT=0 и использовать COMMIT и ROLLBACK для фиксации или отката транзакции. Если вы хотите оставить активным режим автоматической фиксации, можно поместить транзакции между START TRANSACTION и COMMIT или ROLLBACK. До выхода версии MySQL 4.0.11 вместо START TRANSACTION нужно было использовать ключевое слово BEGIN. В следующем примере показаны две транзакции. Первая транзакция фиксируется, а выполнение второй отменяется. s h e l l > mysql t e s t Welcome t o t h e MySQL monitor. Commands end with ; or \g. Your MySQL connection i d i s 5 t o s e r v e r v e r s i o n : 3.23.50-log Type ' h e l p ; ' o r ' \ h ' f o r h e l p . Type ' \ c ' t o c l e a r t h e b u f f e r . m y s q l > CREATE TABLE CUSTOMER (A I N T , В CHAR ( 2 0 ) , INDEX ( A ) ) - > TYPE=InnoDB; Query OK, 0 rows a f f e c t e d ( 0 . 0 0 s e c ) mysql> BEGIN; Query OK, 0 rows a f f e c t e d ( 0 . 0 0 s e c ) mysql> INSERT INTO CUSTOMER VALUES ( 1 0 , ' H e i k k i ' ) ; Query OK, 1 row a f f e c t e d ( 0 . 0 0 s e c ) mysql> COMMIT; Query OK, 0 rows a f f e c t e d ( 0 . 0 0 s e c ) mysql> SET AUTOCOMMIT=0; Query OK, 0 rows a f f e c t e d ( 0 . 0 0 s e c ) mysql> INSERT INTO CUSTOMER VALUES ( 1 5 , ' J o h n ' ) ; Query OK, 1 row a f f e c t e d ( 0 . 0 0 s e c ) mysql> ROLLBACK; Query OK, 0 rows a f f e c t e d ( 0 . 0 0 s e c ) mysql> SELECT * FROM CUSTOMER; + 4+ I A | B | + 4+ I 10 | Heikki | +
+
+
1 row in set (0.00 sec) mysql>
9.7. Создание таблиц InnoDB
537
В таких API-интерфейсах, как PHP, Perl DBI/DBD, JDBC, ODBC или С, вы можете посылать команды управления транзакциями (подобные COMMIT) серверу MySQL в виде строк, подобно тому, как это делают и любые другие SQL-команды, например SELECT или INSERT. В некоторых API-интерфейсах также предлагается разделять специальные функции или методы фиксации и отката транзакций.
9.7.2. Преобразование таблиц MylSAM в формат InnoDB Очень важно отметить, что преобразовывать системные таблицы MySQL в базе данных mysql (например, user или host) в тип InnoDB не следует. Системные таблицы должны всегда оставаться таблицами типа My ISAM. Если вы хотите, чтобы все ваши таблицы (не системные) создавались как таблицы InnoDB, в раздел [mysqld] файла my.cnf или my.ini потребуется (начиная с версии MySQL 3.23.43) добавить строку def ault-table-type=InnoDB. В отличие от MylSAM, в InnoDB нет возможности оптимизировать создание отдельных индексов, поэтому в этом формате не предусматривается выполнение операций экспортирования и импортирования таблиц с последующим созданием индексов. Самый быстрый способ преобразовать таблицу в формат InnoDB - это напрямую вставить данные в таблицу InnoDB, воспользовавшись оператором ALTER TABLE.. .TYPE=INNODB; можно также создать пустую таблицу InnoDB с такой же структурой, и вставить строки с помощью INSERT INTO...SELECT * FROM... Если у вас имеются ограничения UNIQUE на вторичных ключах, то, начиная с версий MySQL 3.23.52, ускорить процесс импортирования таблиц можно, если временно отключить проверку на уникальность на время выполнения операций: SET UNIQUE_CHECKS=O. При работе с большими таблицами это позволит существенно сократить количество дисковых операций ввода-вывода, поскольку InnoDB будет использовать свой буфер вставки для ввода записей вторичного индекса в группу. Чтобы контролировать процесс вставки, большие таблицы желательно вставлять по частям: INSERT INTO новая_таблица SELECT * FROM старая_таблица WHERE ваш__ключ > значение AND ваш^ключ SHOW CREATE TABLE i b t e s t l l c \ G *************************** im r o w
***************************
Table: ibtestllc Create Table: CREATE TABLE ч ibtestllc v ( Ч Ч А int(ll) NOT NULL auto_increment, 4 4 D int(ll) NOT NULL default '0', 4 V B varchar(200) NOT NULL default ", N 4 C varchar(175) default NULL, PRIMARY KEY ( 4 A\V D \ * B 4 ) , KEY 4 B N ( 4 B\4 C N ) , KEY Ч Г ( % C % ), CONSTRAINT ^ 0 _ 3 8 7 7 5 4 FOREIGN KEY ( V A \ 4 D 4 ) REFERENCES 4 i b t e s t l l a N f A \ 4 D 4 ) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT N 0 _ 3 8 7 7 6 4 FOREIGN KEY ( 4 B \ ^ C ) 4 4 N REFERENCES 4 b t e s t l l a f B \ C ) ON DELETE CASCADE ON UPDATE CASCADE ) TYPE=InnoDB C H A R S E T = l a t i n l 1 rowi n s e t (0.01 s e c ) mysql> ALTER TABLE i b t e s t l l c DROP FOREIGN KEY
0_38775;
Начиная с версии MySQL 3.23.50, синтаксический анализатор InnoDB позволяет использовать обратные кавычки ( ) , обрамляющие имена таблиц и столбцов в конструкции FOREIGN KEY.. .REFERENCES... Начиная с версии MySQL 4.0.5, синтаксический анализатор InnoDB способен учитывать параметры системной переменной lower_case_table_names. До выхода версии MySQL 3.23.50 команды ALTER TABLE и CREATE INDEX не использовались для тех таблиц, в которых были установлены ограничения внешнего ключа или на которые имелись ссылки в ограничениях внешних ключей: команда ALTER TABLE удаляет все ограничения внешних ключей, определенные в таблице. Команду ALTER TABLE не следует применять в отношении тех таблиц, на которые имеются ссылки. Чтобы изменить логическую структуру, вместо этой команды необходимо использовать DROP
542
Глава 9. Механизм хранения InnoDB
TABLE и CREATE TABLE. При выполнении команды ALTER TABLE MySQL может использовать команду RENAME TABLE, что может привести к нарушению ограничений внешнего ключа, ссылающегося на таблицу. Оператор CREATE INDEX в MySQL обрабатывается так же, как и ALTER TABLE, поэтому приведенные выше ограничения действительны и для него. Начиная с версии MySQL 3.23.50, InnoDB возвращает определения внешнего ключа таблицы в виде части выходных данных оператора SHOW CREATE TABLE: SHOW CREATE TABLE имя_таблицы; В этой версии mysql dump также генерирует корректные определения таблиц для файла дампа и не забывает о внешних ключах. Вывести ограничения внешнего ключа для таблицы можно следующим образом: SHOW TABLE STATUS FROM имя_базы_данных LIKE 'имя_таблицы* Ограничения внешнего ключа выводятся в виде списка в столбце Comment (комментарий) вывода. При проверке внешних ключей InnoDB устанавливает совместно используемые блокировки на уровне строки на родительских или дочерних записях, подлежащих проверке. Проверка ограничений внешнего ключа для таблиц InnoDB осуществляется немедленно и не откладывается до фиксации транзакции. Чтобы облегчить повторную загрузку файлов дампа для таблиц, имеющих отношение к внешнему ключу, mysql dump автоматически включает в вывод дампа оператор для присвоения параметру FOREIGN_KEY_CHECKS значения 0 (как в версии MySQL 4.1.1). Это позволяет избежать возникновения проблем с таблицами, которые должны индивидуально повторно перезагружаться во время повторной загрузки дампа. В более ранних версиях переменную можно было отключить вручную непосредственно в mysql в процессе загрузки файла данных, как показано далее: mysql> SET FOREIGN_KEY_CHECKS = 0; mysql> SOURCE имя_файла_дампа; mysql> SET FOREIGN_KEY_CHECKS = 1; Подобным образом вы сможете импортировать таблицы в любом порядке, если в файле дампа будут содержаться таблицы, неупорядоченные для внешних ключей. Это позволит повысить скорость выполнения импорта. Параметр FORE IGN_KEY_CHECKS доступен, начиная с версии MySQL 3.23.52. и MySQL 4.O.3. Присвоение параметру FOREIGN_KEY_CHECKS нулевого значения будет полезно для того, чтобы игнорировать ограничения внешнего ключа во время выполнения операции LOAD DATA.
InnoDB позволяет удалять любую таблицу, даже если это приведет к нарушению ограничений внешнего ключа, ссылающегося на таблицу. При удалении таблицы удаляются и ограничения, описанные в операторе, с помощью которого она была создана. Если удаленная таблица создается повторно, ее описание должно согласоваться с ограничениями внешнего ключа, который на нее ссылается. В этой таблице необходимо правильно задать имена и типы столбцов; она должна также иметь индексы ключей, на которые производится ссылка, о чем было сказано выше. Если эти условия не будут удовлетворены, MySQL выдаст ошибку с номером 1005 и ссылку на ошибку с номером 150 в строке сообщения об ошибке.
9.7. Создание таблиц InnoDB
543
9.7.5. InnoDB и репликация в MySQL Репликация в MySQL для InnoDB работает также, как и в таблицах MylSAM. Ее можно использовать и несколько иначе: когда тип подчиненной таблицы отличается от исходного типа главной таблицы. Например, можно реплицировать модификации главной таблицы InnoDB в подчиненную таблицу My ISAM. Чтобы установить новую подчиненную таблицу для главной таблицы, необходимо сделать копию табличного пространства InnoDB и файлов журналов, а так же файлов .frm и таблиц InnoDB, и переместить копии в подчиненную таблицу. Чтобы безошибочно проделать эту процедуру, изучите материалы раздела 9.10. Если вы можете закрыть главную или существующую подчиненную таблицу, вы можете сформировать холодную резервную копию табличного пространства InnoDB и файлов журналов, и использовать ее для настройки подчиненной таблицы. Чтобы иметь возможность создавать новые подчиненные таблицы, не отключая серверы, можно использовать коммерческий инструмент InnoDB Hot Backup. На репликацию InnoDB распространяются некоторые несущественные ограничения: •
LOAD TABLE FROM MASTER не работает для таблиц типа InnoDB. С этим можно справиться двумя способами: 1) выполняя дамп таблицы на главном сервере и импортируя файл дампа на подчиненный сервер; 2) используя команду ALTER TABLE имя_таблицы TYPE=MyISAM на главном сервере перед настройкой репликации с помощью LOAD TABLE имя_таблицы FROM MASTER, а затем используя ALTER TABLE ДЛЯ последующего преобразования главной таблицы обратно к типу InnoDB.
• До выхода версии MySQL 4.0.6 команда SLAVE STOP не распознавала границы транзакции с несколькими операторами. Незавершенная транзакция будет отклонена, и следующая команда SLAVE START выполнит только оставшуюся часть транзакции. Это приведет к неудачному выполнению репликации. • До выхода версии MySQL 4.0.6 аварийный отказ подчиненного сервера во время выполнения транзакции с несколькими операторами приводил к возникновению тех же проблем, что и при выполнении команды SLAVE STOP. • До выхода версии MySQL 4.0.11 репликация оператора SET FOREIGN_KEY_CHECKS=0 работала некорректно. Большинство этих ограничений можно обойти, если использовать более новые версии сервера, к которым упомянутые ограничения не применимы. Неудачно выполненные на главном сервере транзакции вообще не влияют на репликацию. Репликация MySQL основана на бинарном журнале, в котором MySQL записывает SQL-операторы, модифицирующие данные. Подчиненная таблица считывает бинарный журнал главной таблицы и выполняет те же SQL-операторы. Однако операторы, выполняющиеся во время транзакции, не записываются в бинарный журнал до завершения выполнения транзакции. После завершения ее выполнения в бинарный журнал заносятся сразу все операторы. Например, если оператор был выполнен неудачно вследствие искажения внешнего ключа или по причине отката транзакции, то ни один SQLоператор не будет записан в бинарный журнал, и на подчиненном сервере транзакция вообще не будет выполнена.
Глава 9. Механизм хранения InnoDB
544
9.7.6. Использование табличного пространства для каждой таблицы Начиная с версии MySQL 4.1.1, каждую таблицу InnoDB и ее индексы можно сохранять в своем собственном файле. Эта возможность называется "множественными табличными пространствами", поскольку каждая таблица обладает своим собственным табличным пространством. f
На заметку!
'i Если вы используете MySQL 4.1.1 или выше, вам будет довольно трудно вернуться к ранним 'if версиям 4.0. или 4.1.0! Это связано с тем, что в ранних версиях поддержка множественных табj£ личныъ пространств для InnoDB отсутствует.
Если вам нужно будет перейти к версии 4.0, то в этом случае вам придется извлечь дампы таблиц и повторно создать все табличное пространство InnoDB. Если у вас нет созданных новых таблиц InnoDB для MySQL 4.1.1 и выше, и требуется быстро перейти к ранним версиям, можно просто вернуться к версии MySQL 4.0.18 или более поздней в линейке 4.0. Прежде чем перейти к версии в линейке 4.О., необходимо закрыть все клиентские соединения с сервером mysqld, который должен быть понижен в версии, и позволить ему осуществить очистку и операции слияния буферных вставок. После этого команда SHOW INNODB STATUS покажет, что основной поток находится в состоянии waiting for server activity. Затем можно будет завершить работу mysqld и запустить версию 4.0.18 или более позднюю в линейке 4.0. Тем не менее, мы не рекомендуем переходить напрямую к более ранней версии, поскольку такой переход еще не изучен в достаточной мере. Активизировать множество табличных пространств можно, если в раздел [mysqld] файла my. cnf добавить следующую строку: [mysqld] innodb_file_per_table После перезапуска сервера InnoDB будет сохранять каждую вновь созданную таблицу в ее собственном файле имя_таблицы.ibd, который будет расположен в каталоге баз данных, куда принадлежит таблица. Подобное происходит и в механизме хранения MylSAM, однако MylSAM делит таблицу на файл данных имя_таблицы.ЖЪ и файл индекса имя_таблицы.MYI. В InnoDB данные и индексы сохраняются в файле .ibd. Файл имя_таблицы. f rm создается так же, как и обычно. Если удалить строку innodb_file_per_table из файла my.cnf и перезапустить сервер, то InnoDB снова создаст таблицы внутри файлов совместно используемого табличного пространства. innodb_f ile_per__table оказывает влияние только на создание таблиц. Если запустить сервер без этой опции, новые таблицы хотя и будут созданы в файлах . idb, однако вы все равно сможете обращаться к таблицам, существующим в табличном пространстве общего использования. Если удалить этот параметр, то новые таблицы будут созданы в табличном пространстве общего использования, однако вы все равно сможете обращаться к любой таблице, созданной с применением множественного табличного пространства. Для InnoDB всегда необходимо табличное пространство общего использования. Для работы InnoDB недостаточно одних лишь файлов .idb. В табличном пространстве общего использования содержатся файлы ibdata, в которые InnoDB заносит свой внутренний словарь данных и журналы отмены выполненных действий.
9.7. Создание таблиц InnoDB
545
Нельзя свободно перемещать файлы .ibd между каталогами баз данных, как это можно сделать с файлами таблиц MylSAM. На то есть два объяснения: 1) описание таблицы хранится в табличном пространстве общего использования InnoDB; 2) механизм InnoDB должен сохранять последовательность идентификаторов транзакций и порядок номеров в журналах. В пределах установленной копии MySQL можно перемещать файл . ibd и связанную с ним таблицу из одной базы данных в другую с помощью знакомого вам оператора RENAME TABLE: RENAME TABLE старое_имя_базы_данных.имя_таблицы TO новое_имя_базы_данных. имя_та блицы; Если у вас имеется чистая резервная копия файла . ibd, этот файл можно восстановить в MySQL: 1. Выполните оператор ALTER TABLE: ALTER TABLE имя_таблицы DISCARD TABLESPACE; Внимание! Текущий файл . ibd будет удален. 2. Переместите резервную копию файла .ibd обратно в соответствующий каталог базы данных. 3. Выполните оператор ALTER TABLE: ALTER TABLE имя_таблицы IMPORT TABLESPACE; В данном контексте чистая резервная копия файла . idb означает, что: •
В этом файле не существует незафиксированных модификаций, выполненных транзакциями.
•
В этом файле не существуют несоединенные записи буфера вставок.
•
Во время чистки из него были удалены все индексные записи, обозначенные для удаления.
•
mysqld сбросил все модифицированные станицы файла . ibd из буферного пула в файл.
Чистую резервную копию файла . ibd можно подготовить следующим образом: 1. Остановите работу сервера mysqld и зафиксируйте все транзакции. 2. Подождите, пока после выполнения команды SHOW INNODB STATUS не будет показано, что в базе данных отсутствуют активные транзакции, и что основной поток InnoDB пребывает в состоянии Waiting for server a c t i v i t y . После этого вы сможете сделать копию . ibd файла. Другой способ создания чистой резервной копии файла . ibd заключается в использовании коммерческого инструмента InnoDB HOT Backup: 1. Воспользуйтесь InnoDB HOT Backup для резервного копирования InnoDB. 2. Запустите второй сервер mysqld для резервной копии, чтобы осуществить чистку файлов . ibd в резервной копии. В нашем списке TODO запланировано позволить перемещать чистые файлы . ibd в другую установленную копию MySQL. Для этого потребуется перенастроить идентификаторы транзакций и проверить последовательность номеров журналов в файле . ibd.
546
Глава 9. Механизм хранения lnnoDB
9.8. Добавление и удаление файлов данных и файлов журналов InnoDB В этом разделе показано, что можно сделать, если табличное пространство lnnoDB оказалось заполненным или если вы хотите изменить размер файлов журналов. Начиная с версий MySQL 3.23.50 и MySQL 4.0.2, самый простой способ увеличения размера табличного пространства InnoDB состоит в том, чтобы придать ему статус автоматически расширяющегося. Для последнего файла данных в описании табличного пространства можно указать параметр autoextend. Когда будет занято все пространство, InnoDB увеличит размер файла автоматически на 8 Мбайт. Можно поступить иначе, а именно - увеличить размер табличного пространства, добавив еще один файл данных. Для этого потребуется завершить сервер MySQL, изменить файл my.cnf, добавив новый файл данных в конце строки innodb_data_file_path, и запустить сервер снова. Если последний файл данных уже имеет ключевое слово autoextend, в файле my.cnf должен учитываться новый размер последнего файла данных. Узнайте, какой размер должен иметь файл, округлите эту величину (1024*1024 байт = 1 Мбайт) и укажите ее в параметре innodb_data_file_path. Затем вы сможете добавить другой файл данных. Помните, что только последний файл данных в innodb_data_f ile_path может быть указан как автоматически расширяющийся. Для примера предположим, что табличное пространство имеет только один автоматически расширяющийся файл данных ibdatal: innodb_data_home_dir = innodb_data_file_path =
/ibdata/ibdatal:ЮМ:autoextend
Допустим, что с течением времени размер этого файла данных увеличился до 988 Мбайт. Далее показана строка конфигурации после добавления другого автоматически расширяющегося файла данных. innodb_data__home_dir = innodb_data_file_path = /ibdata/ibdatal:988M;/disk2/ibdata2:50M:autoextend При добавлении нового файла в табличное пространство необходимо убедиться в том, что он не существует. InnoDB создаст и инициализирует этот файл после перезапуска сервера. На данный момент удалить файл данных из табличного пространства нельзя. Чтобы уменьшить размер табличного пространства, выполните следующие действия: 1. С помощью mysqldump подготовьте дамп всех таблиц InnoDB. 2. Остановите сервер. 3. Удалите из табличного пространства все существующие файлы. 4. Сконфигурируйте новое табличное пространство. 5. Перезапустите сервер. 6. Импортируйте файлы дампа. Если вам потребуется изменить количество или размер файлов журналов InnoDB, для этого будет необходимо остановить работу сервера MySQL и удостовериться, что сервер завершился без каких-либо ошибок. Затем нужно скопировать старые файлы журналов в безопасное место - на случай, если по завершении работы будут выявлены ошибки и
9.9. Создание резервных копий и восстановление базы данных InnoDB
547
если они вам понадобятся для восстановления табличного пространства. Затем следует удалить старые файлы журналов из их каталога, внести изменения в файл my. cnf и снова запустить MySQL. Теперь во время запуска raysqld увидит, что ни один файл журнала не существует, и выдаст сообщение о создании новых файлов журналов.
9.9. Создание резервных копий и восстановление базы данных InnoDB Чтобы обеспечить безопасное управление базами данных, необходимо регулярно создавать резервные копии. Существует интерактивный инструмент создания резервных копий InnoDB Hot Backup, который можно использовать для резервного копирования своей базы данных InnoDB во время ее работы. InnoDB Hot Backup не требует закрывать базу данных или устанавливать блокировки, то есть обычное функционирование базы данных не нарушается. InnoDB Hot Backup является дополнительным коммерческим инструментом, лицензия которого в расчете на один компьютер с сервером MySQL стоит 390 евро. Чтобы получить дополнительную информацию и просмотреть экранные снимки экрана, посетите домашнюю страницу InnoDB Hot Backup по адресу: http://www.InnoDB.com/order.html Если есть возможность остановить сервер MySQL, а затем создать бинарную резервную копию своей базы данных, выполните следующие действия: 1. Завершите сервер MySQL и удостоверьтесь, что он завершился без ошибок. 2. Скопируйте все свои файлы данных в безопасное место. 3. Скопируйте все свои файлы журналов InnoDB в безопасное место. 4. Скопируйте свой файл конфигурации my. cnf в безопасное место. 5. Скопируйте все файлы . f rm ваших таблиц InnoDB в безопасное место. Таблицы типа InnoDB поддерживают репликацию, поэтому ее возможностями можно воспользоваться для создания и хранения копий базы данных на площадках, обслуживающих базы данных, на которых требуется поддерживать высокую скорость доступа. Кроме создания бинарных резервных копий необходимо также регулярно выполнять дамп своих таблиц с помощью mysqldump. Дело в том, что повреждение бинарного файла для пользователя происходит практически незаметно. Таблицы, перенесенные в дамп, сохраняются в текстовых файлах, поэтому обнаружить ошибку в данных будет гораздо проще. Кроме этого, поскольку они представлены в довольно простом формате, вероятность серьезного повреждения данных будет меньше, mysqldump принимает опцию — single-transsaction, которая позволяет извлекать непротиворечивый снимок данных, не блокируя при этом других клиентов. Чтобы восстановить базу данных InnoDB из описанной выше бинарной резервной копии, потребуется запустить сервер MySQL с включенной функцией бинарной регистрации. Впоследствии, в процессе восстановления, вы сможете использовать бинарный журнал для мгновенного получения резервной копии базы данных: mysqlbinlog имя_хоста-Ып. 123 | mysql Чтобы восстановить работу сервера MySQL после сбоя, достаточно просто перезапустить его. InnoDB автоматически произведет проверку журналов и восстановит базу
548
Глава 9. Механизм хранения InnoDB
данных с повтором всех завершенных на данный момент транзакций. Кроме этого, InnoDB автоматически отклонит незавершенные на момент сбоя транзакции. Во время процесса восстановления InnoDB будет выводить примерно следующую информацию: InnoDB: InnoDB: InnoDB: InnoDB: InnoDB: InnoDB: InnoDB: InnoDB:
Database was not shut down normally. Starting recovery from log files... Starting log scan based on checkpoint at log sequence number 0 13674004 Doing recovery: scanned up to log sequence Doing recovery: scanned up to log sequence Doing recovery: scanned up to log sequence Doing recovery: scanned up to log sequence
InnoDB: InnoDB: InnoDB: InnoDB: InnoDB: InnoDB: InnoDB: InnoDB: InnoDB: InnoDB: InnoDB: mysqld:
Doing recovery: scanned up to log sequence number 0 20555264 Doing recovery: scanned up to log sequence number 0 20620800 Doing recovery: scanned up to log sequence number 0 20664 692 1 uncommitted transaction(s) which must be rolled back Starting rollback of uncommitted transactions Rolling back trx no 16745 Rolling back of trx no 16745 completed Rollback of uncommitted transactions completed Starting an apply batch of log records to the database... Apply batch completed Started ready for connections
number number number number
0 0 0 0
13739520 13805056 13870592 13936128
Если ваша база данных оказалась повреждена или произошел сбой диска, вам потребуется восстановить ее из резервной копии. В случае повреждения базы данных сначала необходимо найти неповрежденную резервную копию. Затем, после восстановления базы данных из резервной копии, следует восстановить бинарные журналы. В некоторых случаях при повреждении базы данных бывает достаточно подготовить дамп, удалить и создать повторно одну или несколько поврежденных таблиц. Для проверки целостности таблиц используется SQL-оператор CHECK TABLE, хотя сам по себе он не в состоянии обнаружить все возможные разновидности повреждений. Для проверки целостности табличного пространства применяется innodb_tablespace_monitor. В некоторых случаях видимые повреждения страниц базы данных возникают вследствие того, что в операционной системе оказывается поврежденным кэш файлов, при этом данные на диске остаются незатронутыми. В таких ситуациях лучше всего попытаться перезапустить компьютер. При перезапуске можно будет устранить ошибки, которые потенциально могли бы повредить страницу базы данных.
9.9.1. Принудительное восстановление Предположим, что у вас произошло повреждение страниц базы данных, и вы пришли к выводу, что решить проблему можно с помощью дампа таблиц базы данных и команды SELECT INTO OUTFILE. Как правило, большая часть данных окажется неповрежденной и корректной. Однако повреждение может привести к неправильному выполнению операции SELECT * FROM имя_ та блицы или фоновых операций InnoDB, либо даже к корректному выполнению восстановления InnoDB с повтором всех завершенных транзакций. В версии MySQL 3.23.44 была введена переменная, которую можно использовать для запуска механизма InnoDB; можно также запретить выполнение фоновых операций, что
9.9. Создание резервных копий и восстановление базы данных InnoDB
549
позволит выполнять дамп таблиц. Например, перед перезапуском сервера в разделе [mysqld] файла опций можно добавить следующую строку: [mysqld] innodb_force_recovery
=4
До MySQL 4.0 применялся следующий синтаксис: [mysqld] set-variable = innodb_force_recovery=4 Параметру innodb_force_recovery присваиваются положительные значения. Большое значение сочетает все меры предосторожности меньших значений. Если вы можете выполнить дамп таблиц, присвоив этому параметру значение менее 4, то в отдельных поврежденных страницах могут быть утрачены всего лишь некоторые данные. Если присвоить значение 6, то страницы базы данных останутся в прежнем состоянии, что, в свою очередь, может привести к повреждению В-деревьев и других структур базы данных. •
1 (SRV_FORCE_IGNORE_CORRUPT). ПОЗВОЛИТЬ серверу работать даже в случае обнаружения поврежденных страниц; попытаться пропустить выполнение команды SELECT * FROM имя_таблицы для поврежденных записей индекса и страниц, что поможет подготовить дамп таблиц.
•
2 (SRVFORCENOBACKGROUND). Предотвратить выполнение главного потока. Если сбой произойдет во время выполнения очистки, она будет защищена.
•
3 (SRV_FORCE_NO_TRX_UNDO). He выполнять откат транзакций после восстановления.
•
4 (sRVFORCENOIBUFMERGE). Предотвратить выполнение операций слияния буфера вставок. Если они могут привести к возникновению аварийной ситуации, лучше всего не выполнять их; не выполнять вычисление статистики по таблице.
•
5 (SRV_FORCE_NO_UNDO_LOG_SCAN). He просматривать журналы отмены выполненных операций во время запуска базы данных: InnoDB будет трактовать незавершенные транзакции как завершенные.
•
б (SRV_FORCE_NO_LOG_RED0)- He регистрировать восстановление с повтором всех завершенных транзакций.
Любое другое использование этих параметров в базе данных исключено. В качестве меры безопасности InnoDB запрещает пользователям выполнять операции INSERT, UPDATE и DELETE, когда параметру innodb_f orce_recovery присвоено значение больше нуля. Начиная с версий MySQL 3.23.53 и 4.0.4, разрешается выполнение команд DROP и CREATE над таблицами даже при принудительном восстановлении. Если вы уверены в том, что определенная таблица стала причиной сбоя при выполнении отката, ее можно удалить. Этот параметр можно использовать также и для останова неконтролируемого отката, вызванного сбоем при массовом импортировании или выполнении ALTER TABLE. Можно уничтожить процесс mysqld и присвоить параметру innodb_f orce_recovery значение 3, чтобы остановить работу базы данных без отката. Затем с помощью команды DROP потребуется удалить таблицу, вызвавшую откат.
550
Глава 9. Механизм хранения InnoDB
9.9.2. Контрольные точки В InnoDB реализован механизм установки контрольных точек, называемый "нечеткой контрольной точкой" (fuzzy checkpoint). InnoDB сбрасывает измененные страницы базы данных из буферного пула на диск небольшими частями. Сбрасывать содержимое буферного пула в одном большом пакете нет необходимости, поскольку это может привести к останову обработки SQL-операторов, выданных пользователями. При восстановлении InnoDB производит поиск меток контрольных точек, записанных в журнальных файлах. Известно, что все изменения базы данных, внесенные перед меткой, уже представлены в дисковом образе базы данных. Затем InnoDB приступает к сканированию файлов журналов от контрольной точки и вносит зарегистрированные изменения в базу данных. Регистрация в журналах в InnoDB осуществляется циклически. Все внесенные изменения, после которых страницы базы данных в буфере становятся отличными от образа на диске, должны быть доступны в журнальных файлах. Это необходимо для тех случаев, когда InnoDB придется производить восстановление. Это означает, что когда механизм InnoDB начинает повторно использовать файл журнала, он проверяет, содержат ли образы страниц базы данных на диске изменения, зарегистрированные в журнале. Другими словами, необходимость поставить контрольную точку зачастую приводит к тому, что InnoDB сбрасывает измененные страницы базы данных на диск. Из сказанного выше становится понятно, почему при больших файлах журналов сокращается количество дисковых операций ввода-вывода в случае установки контрольных точек. Иногда имеет смысл задавать общий размер файлов журналов таким, чтобы он был равен буферному пулу или даже больше. Недостаток больших журнальных файлов заключается в том, что восстановление после сбоя может длиться дольше, поскольку базе данных приходится учитывать больше информации из журнала.
9.10. Перенос базы данных InnoDB на другой компьютер В среде Windows механизм хранения InnoDB всегда хранит имена баз данных и таблиц в нижнем регистре. Чтобы перенести базу данных в двоичном формате из платформы Unix на платформу Windows или наоборот, необходимо, чтобы все имена были представлены в нижнем регистре. В Unix это можно сделать следующим образом. Прежде чем приступить к созданию баз данных и таблиц, в разделе [mysqld] файла опций my. cnf добавьте следующую строку: [mysqld] set-variable = lower_case_table_names=l В Windows опция lower_case_table_names по умолчанию имеет значение 1. Как и файлы данных MylSAM, файлы данных и файлы журналов InnoDB на двоичном уровне совместимы на всех платформах, если на компьютерах совпадает формат чисел с плавающей запятой. Базу данных InnoDB можно перенести без особого труда, скопировав все связанные с ней файлы (список которых был приведен в разделе 9.9). Если компьютеры имеют различные форматы чисел с плавающей запятой, а типы данных FLOAT или DOUBLE в ваших таблицах не используются, последовательность действий остается прежней: нужно просто скопировать все файлы, связанные с базой данных. Если же на
9.11. Транзакционная модель InnoDB и блокирование
551
ваших машинах поддерживаются различные форматы, а в таблицах содержатся данные с плавающей запятой, то чтобы перенести такие таблицы, необходимо сначала с помощью mysqldump подготовить дамп таблиц на одной машине, а затем перенести файлы дампа на другую машину. Чтобы увеличить скорость обработки, можно отключить режим автоматической фиксации транзакций во время импорта данных в базу, при условии, что ваше табличное пространство способно принять большой сегмент отката, который будет сгенерирован большой транзакцией импорта. Фиксацию нужно будет выполнить только после импорта всей таблицы или ее сегмента.
9.11. Транзакционная модель InnoDB и блокирование Транзакционная модель InnoDB призвана комбинировать лучшие возможности многовариантных баз данных и традиционного двухфазного блокирования. Механизм InnoDB устанавливает блокировки на уровне строки и по умолчанию выполняет запросы в форме согласованных считываний без блокировок, как это реализовано в Oracle. Хранение таблицы блокировок в InnoDB организовано настолько экономно, что отпадает необходимость в расширении блокировки: обычно нескольким пользователям одновременно разрешается блокировать каждую строку или любой произвольный набор строк в базе данных, не занимая всю память, доступную для InnoDB.
9.11.1. InnoDB и режим автоматической фиксации AUTOCOMMIT В InnoDB все действия пользователей выполняются внутри транзакции. Если режим автоматической фиксации включен, то каждый SQL-оператор формирует свою собственную транзакцию. Новое соединение в MySQL всегда начинается в режиме автоматической фиксации. Если режим автоматической фиксации отключен с помощью оператора SET AUTOCOMMIT=0, можно считать, что у пользователя всегда имеется открытая транзакция. SQL-операторы COMMIT и ROLLBACK завершают выполнение текущей транзакции и начинают новую. Оба оператора снимают все блокировки InnoDB, которые были приняты во время выполнения текущей транзакции. Если использовать оператор COMMIT, то все изменения, выполненные в период текущей транзакции, будут сохранены и видимы для других пользователей. Если применить оператор ROLLBACK, все изменения, произведенные в период текущей транзакции, будут отменены. Если соединение было установлено при включенном режиме автоматической фиксации, пользователь может продолжить выполнение транзакции с несколькими операторами посредством одного из операторов START TRANSACTION и BEGIN и завершить ее с ПОМОЩЬЮ COMMIT ИЛИ ROLLBACK.
9.11.2. InnoDB и уровень изоляции транзакций (TRANSACTION ISOLATION LEVEL) В терминах описания уровней изоляции транзакций SQL: 1992 в InnoDB по умолчанию применяется повторяющееся чтение (REPEATABLE READ). Начиная с версии MySQL
552
Глава 9. Механизм хранения InnoDB
4.0.5, в InnoDB предлагается четыре различных уровня изоляции транзакций, описанные в стандарте SQL. С помощью опции —transaction-isolation командной строки или в файлах опций можно установить уровень изоляции, который будет использоваться по умолчанию для всех соединений. Например, в разделе [raysqld] файла my.cnf этот параметр можно установить следующим образом: [mysqld] transaction-isolation = {READ-UNCOMMITTED | READ-COMMITTED | REPEATABLE-READ | SERIALIZABLE} Пользователь может изменить уровень изоляции транзакций для отдельно взятого сеанса или нового соединения следующим образом: SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED I REPEATABLE READ | SERIALIZABLE} Обратите внимание на то, что в опции --transaction-isolation имена уровней изоляции пишутся через дефис, а в операторе SET TRANSACTION - нет. Поведение по умолчанию определяет выбор уровня изоляции для следующей (а не для выполняющейся) транзакции. Если указать ключевое слово GLOBAL, то указанное выше выражение будет определять глобальный уровень изоляции, принимаемый по умолчанию для всех новых соединений (но не для существующих соединений). Для этого вам понадобится привилегия суперпользователя (SUPER). Если указать ключевое слово SESSION, то это выражение будет определять уровень изоляции, принимаемый по умолчанию для всех транзакций, которые будут выполняться во время данного соединения. Каждый клиент может изменить уровень изоляции для своего сеанса (даже внутри самой транзакции) или уровень изоляции для следующей транзакции. До выхода версии MySQL 3.23.50 оператор SET TRANSACTION не работал с таблицами InnoDB. До версии 4.0.5 были доступны только операторы REPEATABLE READ и SERIALIZABLE. Запросить глобальные и сеансовые уровни изоляции транзакций можно с помощью следующих операторов: SELECT @@global.tx_isolation; SELECT @@tx_isolation; В блокировке уровня строки InnoDB использует так называемую "блокировку следующего ключа" (next-key locking). Она означает, что помимо индексных записей InnoDB может блокировать также и "интервал" (gap) перед индексной записью, что позволяет блокировать вставки другими пользователями непосредственно перед индексной записью. Блокирование следующего ключа означает блокирование индексной записи и интервала перед ней. Блокирование интервала означает блокирование только интервала перед некоторыми индексными записями. Далее следует подробное описание каждого уровня изоляции в InnoDB: • READ UNCOMMITTED. Операторы SELECT выполняются без блокирования с возможным использованием более ранних версий записи. Таким образом, используя уровень изоляции, такие считывания не являются "согласованными" (другое название - "недействительные чтения"). В остальных случаях этот уровень работает так же, как и READ COMMITTED.
9.11. Транзакционная модель InnoDB и блокирование
553
• READ COMMITTED. Подобен уровню изоляции в Oracle. Все операторы SELECT... FOR UPDATE и SELECT.. .LOCK IN SHARE MODE блокируют только индексные записи, оставляя нетронутыми интервалы перед ними. Таким образом, они позволяют свободно добавлять новые записи после заблокированных записей. Операторы UPDATE и DELETE, которые используют уникальный индекс и уникальные условия поиска, блокируют только обнаруженную индексную запись, оставляя нетронутым интервал перед ней. В операторах диапазонного типа UPDATE и DELETE механизм InnoDB должен установить блокировку следующего ключа или блокировку интервалов и заблокировать вставки другими пользователями в интервалах, попадающих в диапазон. Это необходимо для того, чтобы гарантировать успешное выполнение репликации и восстановления в MySQL, заблокировав так называемые "фантомные строки" (phantom row). Согласованные чтения работают так же, как и в Oracle: каждое согласованное чтение, даже внутри одной и той же транзакции, устанавливает и читает свой собственный последний снимок. См. раздел 9.11.3. •
REPEATABLE READ. Этот уровень изоляции используется в InnoDB по умолчанию. Операторы SELECT... FOR UPDATE, SELECT. . .LOCK IN SHARE MODE, UPDATE И DELETE, которые используют уникальные индексы и уникальное условие поиска, блокируют только обнаруженную индексную запись, оставляя нетронутым интервал перед ней. При остальных условиях поиска в этих операциях используется блокировка следующего ключа, блокировка диапазона индексов, сканированных посредством блокировки следующего ключа или интервалов, и блокировка новых вставок другими пользователями. В согласованных чтениях есть важное отличие от предыдущего уровня изоляции: на этом уровне все согласованные чтения внутри одной и той же транзакции читают тот же снимок, который был сделан при первом чтении. А это значит, что если внутри одной и той же транзакции вы выполните несколько простых выборок (с помощью оператора SELECT), эти выборки будут соответствовать друг другу. См. раздел 9.11.3.
•
SERIALIZABLE. Этот уровень подобен уровню REPEATABLE READ, однако все простые операторы SELECT просто преобразуются в SELECT... LOCK IN SHARE MODE.
9.11.3. Согласованное чтение без блокировки Согласованное чтение означает, что InnoDB использует многовариантные таблицы для предоставления запросу мгновенного снимка базы данных на конкретный момент времени. Запросу будут доступны лишь те изменения, которые были произведены транзакциями, зафиксированными до этого момента времени, и недоступны изменения, вносимые незафиксированными или выполненными позже транзакциями. Исключение могут составить лишь те изменения, которые были произведены транзакцией, сформировавшей текущий запрос. Если вы используете уровень изоляции REPEATABLE READ, принятый по умолчанию, то все согласованные чтения из одной транзакции будут считывать мгновенный снимок, полученный при первом таком чтении в текущей транзакции. Можно получить и более свежую копию для своих запросов - для этого потребуется зафиксировать текущую транзакцию и выдать новые запросы.
554
Глава 9. Механизм хранения InnoDB
Режим согласованного чтения используется по умолчанию. В этом режиме InnoDB выполняет обработку операторов SELECT при уровнях изоляции READ COMMITTED или REPEATABLE READ. Во время согласованного чтения не устанавливаются блокировки на таблицы, к которым обращается запрос, и поэтому остальные пользователи могут вносить изменения в эти таблицы одновременно с согласованным чтением таблиц.
9.11.4. Чтения с блокировкой: SELECT... FOR UPDATE и SELECT... LOCK IN SHARE MODE В некоторых ситуациях согласованное чтение не подходит для решения данной задачи. Предположим, что вам необходимо добавить новую строку в таблицу child, предварительно убедившись, что в таблице parent для нее существует родительская строка. Далее следует пример, демонстрирующий способ реализации ссылочной целостности в коде вашего приложения. Допустим, что для чтения таблицы parent вы используете согласованное чтение, и что в этой таблице действительно была обнаружена родительская строка. Сможете ли вы сейчас добавить дочернюю строку в таблицу child, не беспокоясь о негативных последствиях? Нет, потому что в это время другой пользователь мог без вашего ведома удалить родительскую строку из таблицы parent. В подобных ситуациях необходимо произвести извлечение (SELECT) в режиме блокировки, ИСПОЛЬЗуя LOCK IN SHARE MODE: SELECT
* FROM PARENT WHERE NAME = ' J o n e s '
LOCK IN SHARE MODE;
При выполнении чтения в режиме совместного использования будут считываться самые новые доступные данные и будут заблокированы читаемые строки в режиме совместного использования. При блокировке в режиме совместного использования другие пользователи не смогут обновить или удалить читаемую строку. Кроме этого, если эти новые данные принадлежат еще не зафиксированной транзакции, будет ожидаться ее завершение. После того как указанный выше запрос вернет родительскую строку 'Jones', мы сможем безопасно добавить дочернюю строку в таблицу child и зафиксировать транзакцию. Рассмотрим еще один пример. Пусть имеется поле целочисленного счетчика в таблице child_codes, которое применяется для присвоения уникального идентификатора каждой дочерней записи, добавляемой к таблице child. Очевидно, что для получения текущего значения счетчика использовать согласованное чтение или чтение в режиме совместного доступа нельзя, поскольку два пользователя базы данных могут получить одно и то же значение счетчика; кроме того, у обоих пользователей возникнет ошибка дублированного ключа, если они попытаются добавить в таблицу дочерние записи с одинаковым идентификатором. Применять LOCK IN SHARE MODE нецелесообразно: если два пользователя одновременно попытаются получить значение счетчика, то, как минимум, у одного пользователя произойдет сбой при попытке обновить счетчик. На этот случай наиболее оптимальными представляются два способа чтения и увеличения значения счетчика: (1) нужно обновить значение счетчика, увеличив его на 1, и после этого прочитать его, или (2) сначала прочитать счетчик в режиме блокировки FOR UPDATE, а затем увеличить его значение. Второй способ можно реализовать следующим образом:
9.11. Транзакционная модель InnoDB и блокирование
555
SELECT counter_field FROM child_codes FOR UPDATE; UPDATE child_codes SET counter_field = counter_field + 1; Оператор SELECT...FOR UPDATE производит чтение последних доступных данных, блокируя по отдельности каждую считываемую строку. Он устанавливает блокировки на строки точно так же, как и при поиске с помощью SQL-оператора UPDATE. Заметьте, что приведенный пример касается работы оператора SELECT.. .FOR UPDATE. В MySQL специфическую задачу генерирования уникального идентификатора на самом деле можно выполнить с помощью всего лишь одного обращения к таблице: UPDATE child_codes SET counter_field = LAST_INSERT_ID(counter_field + DESELECT LAST_INSERT_ID(); Оператор SELECT просто получает информацию об идентификаторе (специфическую информацию для данного соединения). Он не обращается ни к одной таблице.
9.11.5. Блокировка следующего ключа: устранение "проблемы с фантомом" При блокировке на уровне строк в InnoDB используется алгоритм, называемый "блокировкой следующего ключа" (next-key locking). Блокировка на уровне строк осуществляется таким образом, что во время поиска или сканирования индекса таблицы устанавливается совместно используемая или эксклюзивная блокировка обрабатываемых записей индексов. Поэтому блокировки на уровне строк на самом деле являются блокировками записей индексов. Блокировки, которые в InnoDB устанавливаются на индексные записи, распространяются также и на интервал перед данной индексной записью. Если пользователь установил совместно используемую или эксклюзивную блокировку записи R в индексе, то другой пользователь не сможет вставить новую индексную запись непосредственно перед записью R в порядке следования индексов. Такая блокировка интервалов реализуется для того, чтобы не допустить возникновения так называемой "проблемы с фантомом" ("phantom problem"). Предположим, что в таблице child необходимо прочитать и заблокировать все дочерние записи с идентификатором, значение которого превышает 100, и затем в выбранных строках обновить некоторые поля: SELECT * FROM c h i l d WHERE i d > 100 FOR UPDATE;
Допустим, что по столбцу id создан индекс. При запросе будет произведено сканирование этого индекса, начиная с первой записи, в которой id больше 100. Далее, если установленные на записях индекса блокировки не заблокируют вставки в интервалы, то за это время в таблицу может быть вставлена новая строка. Если сейчас выполнить эту же команду SELECT в этой же транзакции, то после выполнения запроса вы сможете увидеть новую строку. Это противоречит принципу изоляции транзакции: транзакция должна выполняться таким образом, чтобы считываемые ею данные не изменялись во время выполнения транзакции. Если набор строк считать элементом данных, то новый дочерняя "фантомная запись" нарушит этот принцип изоляции. Когда InnoDB сканирует индекс, она может также заблокировать интервалы после последней записи в индексе. Именно это и было продемонстрировано в предыдущем примере: блокировка, установленная InnoDB, запрещает вставку в таблицу, если id будет больше 100.
556
Глава 9. Механизм хранения InnoDB
Блокировку следующего ключа можно использовать для того, чтобы проверить уникальность значений в своем приложении. Если данные считываются в режиме совместного доступа, и отсутствует дубликат строки, которую необходимо вставить, то можно безопасно вставлять свою строку и быть уверенным, что благодаря блокировке следующего ключа, установленной на предшествующей строке во время чтения, будет запрещена вставка дублированной строки. Таким образом, блокировка следующего ключа позволяет "заблокировать" отсутствие чего-либо в таблице.
9.11.6. Пример работы согласованного чтения в InnoDB Предположим, что вы используете уровень изоляции, установленный по умолчанию - REPEATABLE READ. При выполнении согласованного чтения (то есть обычного оператора SELECT) InnoDB определяет для транзакции момент времени, когда запросу будет предоставлена информация из базы данных. Поэтому если во время транзакции будет удалена строка и это изменение будет зафиксировано после указанного момента времени, вы не увидите, что строка была удалена. Это справедливо также для вставок и обновлений. Чтобы такой момент времени сдвинуть как можно дальше, нужно зафиксировать транзакцию и выполнить новый оператор SELECT. Этот прием называется многовариантным контролем совпадений (multi-versioned concurrency control). User A SET AUTOCOMMIT=0; time | SELECT * FROM t ; I empty s e t |
User В SET AUTOCOMMIT=0;
INSERT INTO t VALUES ( 1 ,
2);
I v
SELECT * FROM t ; empty s e t COMMIT; SELECT * FROM t ; empty s e t COMMIT; SELECT * FROM t ;
1 row in set В этом примере пользователь А увидит строку, вставленную пользователем В, только после того, как пользователь В зафиксирует вставку, а пользователь А зафиксирует свою собственную транзакцию, чтобы момент времени сдвинулся на позицию после фиксации, которую выполнил пользователь В. Чтобы увидеть "наиболее актуальное" состояние базы данных, необходимо воспользоваться чтением с блокировкой: SELECT * FROM t LOCK IN SHARE MODE;
9.11. Транзакционная модель InnoDB и блокирование
557
9.11.7. Блокировка, устанавливаемая различными SQL-операторами в InnoDB Чтения с блокировкой, команды UPDATE или DELETE устанавливают блокировки записей на каждой индексной записи, сканируемой в процессе выполнения SQL-запроса. Не имеет значения, присутствуют ли в запросе условия WHERE, которые исключат строку из полученного набора по запросу. InnoDB не запоминает точное условие WHERE, а знает только о том, какие индексные диапазоны были отсканированы. Блокировки записей обычно являются блокировками следующего ключа, которые также блокируют вставки в интервал непосредственно перед записью. Если блокировки являются эксклюзивными, InnoDB всегда будет получать также и кластеризованную индексную запись, устанавливая на ней блокировку. Если индексы, подходящие для вашего запроса, отсутствуют, и MySQL пришлось сканировать всю таблицу, чтобы обработать запрос, то каждая строка таблицы будет заблокированной. В свою очередь, это приведет к блокировке всех вставок в таблицу, выполняемых другими пользователями. Здесь важно создать правильно подобранные индексы, которые позволят сократить время поиска за счет сканирования меньшего количества строк. • SELECT... FROM осуществляет согласованное чтение снимка базы данных без блокировок, пока уровнем изоляции транзакции не является SERIALIZABLE. Для уровня SERIALIZABLE будет установлены совместно используемые блокировки следующего ключа на все считываемые индексные записи. •
SELECT.. .FROM.. .LOCK IN SHARE MODE устанавливает совместно используемые блокировки следующего ключа на все считываемые индексные записи.
•
SELECT.. .FROM.. .FOR UPDATE устанавливает эксклюзивную блокировку следующего ключа на все считываемые индексные записи.
•
INSERT INTO.. .VALUES (...) устанавливает эксклюзивную блокировку на вставленную строку. Заметьте, что эта блокировка не является блокировкой следующего ключа и не запрещает вставку записей другими пользователями в интервале перед вставленной строкой. Если произойдет ошибка дублирования ключа, оператор установит блокировку совместного использования на запись дублированного индекса.
• Во время инициализации предварительно описанного столбца AUTO_INCRESEMENT в таблице механизм InnoDB устанавливает эксклюзивную блокировку в конце индекса, связанного со столбцом AUTOINCREMENT. Для доступа к счетчику с автоматическим приращением InnoDB использует специальный режим блокировки таблицы AUTO-INC, при котором блокировка продолжается только до завершения выполнения текущего SQL-оператора, а не до завершения выполнения всей транзакции. См. раздел 9.11.1. До выхода версии MySQL 3.23.50 команда SHOW TABLE STATUS, выполненная над таблицей со столбцом AUTOINCRESEMENT, устанавливала эксклюзивную блокировку на уровне строк до конца индекса AUTO_INCREMENT. Это означает также, что команда SHOW TABLE STATUS может вызвать взаимную блокировку транзакций, приводя в замешательство пользователей. Начиная с версии MySQL 3.23.50, InnoDB выбирает значение предварительно инициализированного столбца AUTO_INCRESEMENT, не устанавливая какие-либо блокировки.
558 •
Глава 9. Механизм хранения InnoDB INSERT INTO T SELECT... FROM S WHERE... устанавливает эксклюзивную (не следующего ключа) блокировку на каждую вставляемую в таблицу Т строку. Осуществляет поиск в таблице S в виде согласованного чтения, однако если будет включен режим бинарной регистрации, то в таблице S будут установлены совместно используемые блокировки следующего ключа. В последнем случае InnoDB должна устанавливать блокировки, поскольку при восстановлении с повтором всех завершенных транзакций из резервной копии каждый SQL-оператор потребуется выполнить точно так таким же образом, как и изначально.
• CREATE TABLE... SELECT... выполняет SELECT в виде согласованного чтения или с блокировками совместного использования, как в предыдущем пункте. • REPLACE выполняется так же, как и вставка, при отсутствии конфликтов уникальных ключей. В противном случае на строке, подлежащей обновлению, будет установлена эксклюзивная блокировка следующего ключа. •
UPDATE.. .WHERE... устанавливает эксклюзивную блокировку следующего ключа на каждой записи, обнаруженной в процессе поиска.
•
DELETE FROM.. .WHERE... устанавливает эксклюзивную блокировку следующего ключа на каждой записи, обнаруженной во время поиска. • Если для таблицы определены ограничения FOREIGN KEY, то для любой вставки, обновления или удаления, для которых потребуется проверка условий ограничения, будет установлена совместная блокировка на уровне записей, которые просматриваются во время проверки ограничения. В InnoDB эти блокировки устанавливаются также при нарушении ограничения. •
LOCK TABLES... устанавливает блокировку таблицы. Эта блокировка производится кодом на уровне MySQL. Механизм автоматического обнаружения взаимных блокировок InnoDB не позволяет обнаруживать взаимные блокировки, в которых участвуют подобные блокировки таблиц. См. раздел 9.11.9. Кроме того, поскольку MySQL известно о блокировке на уровне строки, можно установить блокировку таблицы, в которой на данный момент какой-нибудь другой пользователь заблокировал строки. Это, однако, никоим образом не влияет на целостность транзакции. См. раздел 9.17.
9.11.8. В каких случаях MySQL явно выполняет фиксацию или откат транзакции По умолчанию MySQL устанавливает соединение с каждым клиентом в режиме автоматической фиксации. Если этот режим включен, MySQL выполняет фиксацию после каждого SQL-оператора, если в результате его выполнения не была возвращена ошибка. Если режим автоматической фиксации выключен, и соединение закрывается без выполнения явной фиксации вашей транзакции, MySQL выполнит откат транзакции. Если SQL-оператор возвращает ошибку, поведение фиксации/отката будет зависеть от возникшей ошибки. См. раздел 9.16. Следующие SQL-операторы инициируют явную фиксацию текущей транзакции в MySQL:
9.11. Транзакционная модель InnoDB и блокирование •
559
ALTER TABLE, BEGIN, CREATE INDEX, DROP DATABASE, DROP INDEX, DROP TABLE, LOAD MASTER DATA, LOCK TABLES, RENAME TABLE, SET AUTOCOMMIT=1, START TRANSACTION, TRUNCATE, UNLOCK TABLES.
• CREATE TABLES (фиксация производится только в том случае, если в версиях MySQL, предшествующих 4.0.13, используется бинарная регистрация). • Оператор CREATE TABLE в InnoDB обрабатывается как одна транзакция. Это означает, что команда ROLLBACK, инициированная пользователем, не приведет к отмене выполнения операторов CREATE TABLE, выданных пользователем во время данной транзакции.
9.11.9. Обнаружение взаимных блокировок и откат Механизм InnoDB автоматически обнаруживает взаимную блокировку транзакций и с целью предотвращения подобного рода блокировок выполняет откат одной или нескольких транзакций. Начиная с версии MySQL 4.0.5, InnoDB пытается выбирать для отката небольшие транзакции. Размер транзакции определяется количеством строк, которые должны быть вставлены, обновлены или удалены. До версии MySQL 4.0.5 механизм InnoDB производил откат той транзакции, чей запрос на блокировку был последним, вызвавшим взаимную блокировку, то есть, приводил к возникновению замкнутого цикла в графике ожиданий транзакций. Механизм InnoDB не способен обнаруживать взаимные блокировки, в которых блокировка таблицы была осуществлена с помощью MySQL-оператора LOCK TABLES или другим механизмом хранения, отличным от InnoDB. В ситуациях подобного рода необходимо присвоить определенное значение системной переменной innodb_lock_wait_timeout. Когда InnoDB выполняет откат транзакции, снимаются все блокировки транзакции. Тем не менее, если в результате ошибки произошел откат только одного SQL-оператора, некоторые блокировки, установленные SQL-оператором, могут сохраниться. Это происходит потому, что InnoDB хранит блокировку строк в формате, который впоследствии не позволяет определить, каким конкретно SQL-оператором устанавливалась блокировка.
9.11.10. Как справляться с взаимными блокировками Взаимные блокировки являются классической проблемой транзакционных баз данных. Они не опасны до тех пор, пока не начинают возникать настолько часто, что вы вообще оказываетесь не в состоянии запустить некоторые транзакции. Обычно вы должны разрабатывать свои приложения так, чтобы они всегда были подготовлены к повторному выполнению транзакции в случае отката, вызванного возникновением взаимной блокировки. InnoDB использует автоматическую блокировку на уровне строки. Столкнуться с взаимной блокировкой вы можете даже тогда, когда в транзакциях выполнятся вставка или удаление одной строки. Это происходит из-за того, что в действительности эти операции не являются атомарными; они автоматически блокируют индексные записи добавляемых или удаляемых строк (возможно, даже несколько записей). Справиться с взаимными блокировками или снизить вероятность их появления можно следующими способами: • Чтобы установить причину возникновения последней взаимной блокировки, используйте команду SHOW INNODB STATUS. Вы сможете соответствующим образом
560
Глава 9. Механизм хранения InnoDB настроить свое приложение и избежать возникновения взаимных блокировок. Этот способ можно реализовать в версиях MySQL 3.23.52 и MySQL 4.0.3, в зависимости от линейки MySQL.
• Всегда будьте готовы к повторному выполнению транзакции, если ее сбой был вызван взаимной блокировкой. Взаимные блокировки не являются опасным явлением, поэтому попытайтесь выполнить транзакцию снова. • Чаще фиксируйте свои транзакции. Небольшие транзакции менее часто становятся причиной возникновения конфликтов. • Если вы используете чтение с блокировкой (SELECT.. .FOR UPDATE или .. .LOCK IN SHARE MODE), попытайтесь использовать более низкий уровень изоляции, например READ COMMITTED. •
Старайтесь придерживаться фиксированного порядка обращения к своим таблицам и строкам, что позволит формировать согласованную очередность выполнения транзакций, не давая повода для возникновения взаимных блокировок.
•
Старайтесь использовать в своих таблицах тщательно подобранные индексы. Тогда ваши запросы будут сканировать меньшее количество индексных записей и, соответственно, будет установлено меньшее количество блокировок. Используйте EXPLAIN SELECT, чтобы узнать, какие индексы сервер MySQL считает наиболее подходящими для выполнения ваших запросов.
• Используйте как можно меньшее количество блокировок: если вы можете допустить, чтобы команда SELECT вернула данные из старого снимка, не добавляйте к ней конструкцию FOR UPDATE или LOCK IN SHARE MODE. Используйте уровень изоляции READ COMMITTED, который больше всего подходит для данной ситуации при каждом согласованном чтении внутри одной и той же транзакции будет прочитан свой собственный актуальный снимок. • Если ничего не помогло, выполните последовательно свои транзакции с блокировкой на уровне таблицы. Например, если вам нужно записать таблицу t i n прочитать таблицу t2, можете выдать следующие операторы: LOCK TABLES t l WRITE, t2 READ, . . . ; [do something with tables t l and t2 h e r e ] ; UNLOCK TABLES; Блокировки на уровне таблиц выстраивают ваши транзакции в очередь, что позволяет избежать возникновения взаимных блокировок. Заметьте, что LOCK TABLES неявно начинает транзакцию, подобно оператору BEGIN, a UNLOCK TABLES неявно завершает ее, подобно COMMIT. •
Еще один способ организации последовательного выполнения транзакций заключается в создании вспомогательной "семафорной" таблицы, содержащей одну строку. Каждая транзакция будет обновлять эту строку, прежде чем обращаться к другой таблице. В этом случае все транзакции выполняются последовательно. Обратите внимание на то, что таким же образом в настоящий момент работает и алгоритм обнаружения взаимных блокировок, поскольку последовательная блокировка представляет собой блокировку на уровне строки. Для устранения взаимных блокировок на уровне таблицы в MySQL необходимо использовать метод тайм-аута.
9.12. Советы по настройке производительности InnoDB
561
9.12. Советы по настройке производительности InnoDB • Если инструмент top в Unix или Task Manager (Диспетчер задач) в Windows показывают, что процент рабочей нагрузки процессора меньше 70%, это значит, что рабочая нагрузка связана, в основном, с обращениями к диску. Вероятно, вы слишком часто фиксируете транзакции или слишком мал размер вашего буферного пула. В этом случае можно увеличить размер буферного пула, но не более чем до 80% от физической памяти. • За одну транзакцию следует вносить несколько изменений. Механизм InnoDB должен сбрасывать журнал на диск после каждой фиксации транзакции, если эта транзакция внесла изменения в базу данных. Поскольку скорость вращения диска обычно не превышает 167 оборотов в секунду, то количество фиксаций ограничено 167 фиксациями в секунду, если, конечно, диск не "обманывает" операционную систему. • Если вы можете позволить себе терять последние зафиксированные транзакции, тогда в файле my.cnf присвойте опции innodb_flush_log_at_trx_commit нулевое значение. В любом случае, каждую секунду InnoDB будет пытаться сбросить журнал, причем положительный результат этой операции не гарантируется. • Увеличьте размеры журнальных файлов, пусть даже до размера буферного пула. Когда механизм InnoDB заполняет файлы журналов, он должен сохранять измененное содержимое буферного пула на диске в контрольной точке. Имейте в виду, что при работе с журналами небольших размеров может быть вызвано множество ненужных записей на диск, а для больших журналов понадобится большее время на восстановление после сбоя. • Можно увеличить размер буфера журнала, например до 8 Мбайт. • Вместо CHAR в качестве типа столбца используйте VARCHAR, если вы сохраняете строки разной длины или если столбец содержит нулевые значения. Для хранения данных столбец CHAR всегда занимает N байт, даже если строка короче или ее значением является NULL. Таблицы меньшего размера более всего подходят для буферного пула и сокращают количество дисковых операций ввода-вывода. • (Актуально для версии MySQL 3.23.39 и выше.) В некоторых версиях операционных систем Linux и Unix запись файлов на диск с помощью команды f datasync и других подобных методов выполняется на удивление медленно. По умолчанию в InnoDB используется функция fdatasync. Если скорость записи в базу данных является достаточно низкой, в файле my.cnf можно попробовать присвоить опции innodb_f lushjnethod значение O_DSYNC, хотя во многих механизмах это не приводит к увеличению производительности. • При импорте данных в InnoDB необходимо, чтобы в MySQL не был включен режим автоматической фиксации, поскольку для каждой вставки потребуется сбрасывать журналы на диск. Чтобы отключить режим автоматической фиксации во время выполнения операции импортирования, поместите блок импортирования между операторами SET AUTOCOMMIT и COMMIT: SET AUTOCOMMIT=0; /* SQL-операторы импортирования ... */ COMMIT;
562
Глава 9. Механизм хранения InnoDB Если указать опцию —opt для mysqldump, вы получите файлы, которые будут достаточно быстро импортироваться в таблицу InnoDB, даже если и не использовать вышеуказанные операторы SET AUTOCOMMIT и COMMIT.
• Осторожно относитесь к большому количеству откатов массовых вставок: InnoDB использует буфер вставок для того, чтобы сократить количество дисковых операций ввода-вывода, однако для соответствующего отката транзакции подобный механизм не предусмотрен. Ограниченный физическими параметрами диска откат может занять в 30 раз больше времени, чем вставка. Удаление процесса базы данных не поможет, поскольку после запуска базы данных снова начнется откат. Во избежание подобного отката можно увеличить размер буферного пула настолько, чтобы скорость выполнения отката зависела только от производительности центрального процессора, либо предусмотреть для этого специальную процедуру. См. раздел 9.9.1. • Следует также осторожно относиться к операциям со значительными объемами данных, которые зависят от производительности диска. Чтобы очистить таблицу, применяйте операторы DROP TABLE или TRUNCATE (начиная с версии MySQL 4.0 и выше), но не DELETE FROM имя_таблицы. • Если вам нужно вставить большое количество строк, используйте синтаксис оператора INSERT с несколькими строками, что позволит сократить нагрузку на связь между клиентом и сервером: INSERT INTO имя_таблицы VALUES (1,2), (5,5), ...; Этот совет подходит для вставок в таблицы любого типа, а не только для InnoDB. • Если у вас имеются ограничения UNIQUE для вторичных ключей, то, начиная с версий MySQL 3.23.52 и MySQL 4.0.3, можно ускорить импортирование таблиц, если отключить на время проверки на уникальность: SET UNIQUE_CHECKS=O; При работе с крупными таблицами можно будет существенно сократить количество дисковых операций ввода-вывода, поскольку InnoDB сможет использовать свой буфер вставки для групповой регистрации записей вторичных индексов. • Если в ваших таблицах имеются ограничения внешнего ключа FOREIGN KEY, то, начиная с версии MySQL 3.23.52 и MySQL 4.0.3, вы можете увеличить скорость выполнения вставок в таблицу, отключив на время проверку внешних ключей: SET FOREIGN_KEY_CHECKS=0;
Для больших таблиц это позволит сократить количество дисковых операций ввода-вывода. • Если вы часто обращаетесь к редко обновляемым таблицам, используйте кэш запросов, доступный в MySQL 4.0: [mysqld] query_cache_type = ON query_cache__size = 10M В MySQL 4.0 кэш запросов доступен только для режима автоматической фиксации. В версии MySQL 4.1.1 это ограничение было снято.
9.12. Советы по настройке производительности InnoDB
563
9.12.1. SHOW INNODB STATUS и мониторы InnoDB Начиная с версии MySQL 3.23.41, в состав InnoDB входят мониторы InnoDB, которые выводят информацию о внутреннем состоянии InnoDB. Начиная с версий MySQL 3.23.52 и MySQL 4.0.3, с помощью SQL-onepaTopf SHOW INNODB STATUS можно передавать выходные данные стандартного монитора InnoDB вашему клиенту SQL. Эту информацию полезно использовать для настройки производительности. Если вы пользуетесь интерактивным клиентом mysql, то выходную информацию будет более удобно читать, если заменить точку с запятой на \G: mysql> SHOW INNODB STATUS\G Другой способ использования мониторов InnoDB - позволить им непрерывно записывать данные на стандартный вывод сервера mysqld. В этом случае информация не будет пересылаться клиентам. В рабочем режиме мониторы InnoDB выводят данные примерно каждые 15 секунд. Выходные данные сервера обычно направляются для регистрации в журнал .err, который хранится в каталоге данных MySQL. Эти данные могут оказаться полезными для настройки производительности. В среде Windows необходимо запустить сервер из командной строки с опцией —console, если вы хотите направлять выходные данные в окно, а не в журнал регистрации ошибок. Монитор выводит следующую информацию: • По блокировкам записей и таблиц, которые выполняются в каждой транзакции. • По блокировкам, которые ожидают транзакции. • • • •
По семафорам, которые ожидают потоки. По файлам, которые ожидают ответ на запросы ввода-вывода. По статистике буферного пула. По активности буферов удаления и вставок в основном потоке InnoDB.
Чтобы стандартный монитор InnoDB выводил информацию в стандартный вывод mysqld, применяйте следующий SQL-оператор: CREATE TABLE innodbjnonitor(a INT) TYPE=InnoDB; Остановить монитор можно с помощью такого оператора: DROP TABLE innodbjnonitor; Синтаксис оператора CREATE TABLE предназначен только для передачи команды в механизм InnoDB через синтаксический анализатор SQL: здесь играет роль только имя таблицы innodbjnonitor и таблица InnoDB. Для монитора InnoDB структура таблицы значения не имеет. Если вы останавливаете функционирование сервера во время работы монитора и хотите запустить монитор повторно, вам придется сначала удалить таблицу, и уже затем выдать оператор CREATE TABLE для запуска монитора. В следующей версии этот синтаксис может быть изменен. Подобным образом можно запустить innodb_lock_monitor, который подобен innodbjnonitor, но выводит большой объем информации о блокировках. Отдельный монитор innodb_tablespace_monitor выводит перечень созданных сегментов файлов, существующих в табличном пространстве, и проверяет правильность размещения структур данных в табличном пространстве. В версии MySQL 3.23.44 появился монитор innodb_table_monitor, который выводит содержимое внутреннего словаря данных InnoDB.
564
Глава 9. Механизм хранения InnoDB
Ниже представлен пример информации, выводимой монитором InnoDB: mysql> SHOW INNODB STATUS\G *************************** im Status:
r o w
***************************
030709 13:00:59 INNODB MONITOR OUTPUT Per second averages calculated from the last 18 seconds SEMAPHORES OS WAIT ARRAY INFO: reservation count 413452, signal count 378357 --Thread 32782 has waited at btrOsea.c line 1477 for 0.00 seconds the semaphore: X-lock on RW-latch at 41a28668 created in file btrOsea.c line 135 a writer (thread id 32782) has reserved it in mode wait exclusive number of readers 1, waiters flag 1 Last time read locked in file btrOsea.c line 731 Last time write locked in file btrOsea.c line 1347 Mutex spin waits 0, rounds 0, OS waits 0 RW-shared spins 108462, OS waits 37964; RW-excl spins 681824, OS waits 375485 LATEST FOREIGN KEY ERROR 030709 13:00:59 Transaction: TRANSACTION 0 290328284, ACTIVE 0 sec, process no 3195, OS thread id 34831 inserting 15 lock struct (s), heap size 2496, undo log entries 9 MySQL thread id 25, query id 4668733 localhost heikki update insert into ibtestlla (D, В, С) values (5, 'khDk' ,'khDk1) Foreign key constraint fails for table test/ibtestlla: v
4
4
4
4
V
4
S
CONSTRAINT 0_219242 FOREIGN KEY f A \ D ) REFERENCES 4btestllb ( A\ D ) ON DELETE CASCADE ON UPDATE CASCADE Trying to add in child table, in index PRIMARY tuple: 0: len 4; hex 80000101; asc ;; 1: len 4; hex 80000005; asc ;; 2: len 4; hex 6b68446b; asc khDk;; 3: len 6; hex 0000114e0edc; asc ...N..;; 4: len 7; hex 00000000c3e0a7; asc ;; 5: len 4; hex 6b68446b; asc khDk;; But in parent table test/ibtestllb, in index PRIMARY, the closest match we can find is record: RECORD: info bits 0 0: len 4; hex 8000015b; asc ...[;; 1: len 4; hex 80000005; a sc ;; 2: len 3; hex 6b6864; asc khd;; 3: len 6; hex 0000111ef3eb; asc ;; 4: len 7; hex 800001001e0084; asc ;; 5: len 3; hex 6b6864; asc khd;; LATEST DETECTED DEADLOCK 030709 12:59:58 *** (1) TRANSACTION: TRANSACTION 0 290252780, ACTIVE 1 sec, process no 3185, OS thread id 30733 inserting LOCK WAIT 3 lock struct(s), heap size 320, undo log entries 146
9.12. Советы по настройке производительности InnoDB
565
MySQL thread id 21, query id 4553379 localhost heikki update INSERT INTO alexl VALUES(86, 86, 1 f ! 794,'aA35818','bb ,'c79166\'d4766t , el87358f l l ,'g84586', h794',date_format( 2001-04-03 12:54:22','%Y-%m-%d %H:%i'),7 *** (1) WAITING FOR THIS LOCK TO BE GRANTED: RECORD LOCKS space id 0 page no 48310 n bits 568 table test/alexl index symbole trx id 0 290252780 lock mode S waiting Record lock, heap no 324 RECORD: info bits 0 0: len 7; hex 61613335383138; asc a a35818;; 1: *** (2) TRANSACTION: TRANSACTION 0 290251546, ACTIVE 2 sec, process no 3190, OS thread id 32782 inserting 130 lock struct(s), heap size 11584, undo log entries 437 MySQL thread id 23, query id 4554396 localhost heikki update REPLACE INTO alexl VALUES(NULL, 32, NULL,!aa3572','','c3572','d6012t', " , NULL,fh396', NULL, NULL, 7.31,7.31,7.31,200) *** (2) HOLDS THE LOCK(S): RECORD LOCKS space id 0 page no 48310 n bits 568 table test/alexl index symbole trx id 0 290251546 lockjnode X locks rec but not gap Record lock, heap no 324 RECORD: info bits 0 0: len 7; hex 61613335383138; asc a a35818;; 1: *** (2) WAITING FOR THIS LOCK TO BE GRANTED: RECORD LOCKS space id 0 page no 48310 n bits 568 table test/alexl index symbole trx id 0 290251546 lockjnode X locks gap before rec insert intention waiting Record lock, heap no 82 RECORD: info bits 0 0: len 7; hex 61613335373230; asc aa 35720;; 1: *** WE ROLL BACK TRANSACTION (1) TRANSACTIONS Trx id counter 0 290328385 Purge done for trx's n:o < 0 290315608 undo n:o < 0 17 Total number of lock structs in row lock hash table 70 LIST OF TRANSACTIONS FOR EACH SESSION: -—TRANSACTION 0 0, not started, process no 3491, OS thread id 42002 MySQL thread id 32, query id 4668737 localhost heikki show innodb status —TRANSACTION 0 290328384, ACTIVE 0 sec, process no 3205, OS thread id 38929 inserting 1 lock struct(s), heap size 320 MySQL thread id 29, query id 4668736 localhost heikki update insert into speedc values (1519229,1, 'hgjhjgghggjgjgjgjgjggjgjgjgjgjgggjgjgjlhh gghggggghhjhghgggggghjhghghghghghhhhghghghj hhj ghj ghj kghj ghj ghj ghj fhj fh —TRANSACTION 0 290328383, ACTIVE 0 sec, process no 3180, OS thread id 28684 committing 1 lock struct(s), heap size 320, undo log entries 1 MySQL thread id 19, query id 4668734 localhost heikki update insert into speedcm values (1603393,1, 'hgjhjgghggjgjgjgjgjggjgjgjgjgjgggjgjgjlh hgghggggghhj hghgggggghj hghghghghghhhhghghghj hhj ghj ghj kghj ghj ghj ghj fhj f
566
Глава 9. Механизм хранения InnoDB
—-TRANSACTION 0 290328327, ACTIVE 0 sec, process no 3200, OS thread id 36880 starting index read LOCK WAIT 2 lock struct(s), heap size 320 MySQL thread id 27, query id 4668644 localhost heikki Searching rows for update update ibtestlla set В = 'kHdkkkk' where A = 89572 TRX HAS BEEN WAITING 0 SEC FOR THIS LOCK TO BE GRANTED: RECORD LOCKS space id 0 page no 65556 n bits 232 table test/ibtestlla index PRIM ARY trx id 0 290328327 lockjnode X waiting Record lock, heap no 1 RECORD: info bits 0 0: len 9; hex 73757072656d756d00; asc supremum.;; —TRANSACTION 0 290328284, ACTIVE 0 sec, process no 3195, OS thread id 34831 rollback of SQL statement ROLLING BACK 14 lock struct(s), heap size 2496, undo log entries 9 MySQL thread id 25, query id 4668733 localhost heikki update insert into ibtestlla (D, В, С) values (5, 'khDk' ,'khDk1) —TRANSACTION 0 290327208, ACTIVE 1 sec, process no 3190, OS thread id 32782 58 lock struct (s), heap size 5504, undo log entries 159 MySQL thread id 23, query id 4668732 localhost heikki update REPLACE INTO alexl VALUES(86, 46, 538, f aa95666 f , f bb', ! c95666 f , f d9486t l , f e200498f ',fg86814\
f
h538',date_format('2001-04-03 12:54:22','%Y-%m-%d
%H:%i»),
-—TRANSACTION 0 290323325, ACTIVE 3 sec, process no 3185, OS thread id 30733 inserting 4 lock struct (s), heap size 1024, undo log entries 165 MySQL thread id 21, query id 4668735 localhost heikki update INSERT INTO alexl VALUES(NULL, 49, NULL,faa42837', " ,•c56319','dl719t','', NULL,г п32Г, NULL, NULL, 7.31,7.31,7.31,200) FILE I/O I/O thread 0 state: waiting for i/o request (insert buffer thread) I/O thread 1 state: waiting for i/o request (log thread) I/O thread 2 state: waiting for i/o request (read thread) I/O thread 3 state: waiting for i/o request (write thread) Pending normal aio reads: 0, aio writes: 0, ibuf aio reads: 0, log i/o's: 0, sync i/o's: 0 Pending flushes (fsync) log: 0; buffer pool: 0 151671 OS file reads, 94747 OS file writes, 8750 OS fsyncs 25.44 reads/s, 18494 avg bytes/read, 17.55 writes/s, 2.33 fsyncs/s INSERT BUFFER AND ADAPTIVE HASH INDEX Ibuf for space 0: size 1, free list len 19, seg size 21, 85004 inserts, 85004 merged recs, 26669 merges Hash table size 207619, used cells 14461, node heap has 16 buffer (s) 1877.67 hash searches/s, 5121.10 non-hash searches/s LOG Log sequence number 18 1212842764
9.12. Советы по настройке производительности InnoDB
567
Log flushed up to 18 1212665295 Last checkpoint at 18 1135877290 0 pending log writes, 0 pending chkp writes 4341 log i/o's done, 1.22 log i/o's/second BUFFER POOL AND MEMORY Total memory allocated 84966343; in additional pool allocated 1402624 Buffer pool size 3200 Free buffers 110 Database pages 3074 Modified db pages 2674 Pending reads 0 Pending writes: LRU 0, flush list 0, single page 0 Pages read 171380, created 51968, written 194688 28.72 reads/s, 20.72 creates/s, 47.55 writes/s Buffer pool hit rate 999 / 1000 ROW OPERATIONS 0 queries inside InnoDB, 0 queries in queue Main thread process no. 3004, id 7176, state: purging Number of rows inserted 3738558, updated 127415, deleted 33707, read 755779 1586.13 inserts/s, 50.89 updates/s, 28.44 deletes/s, 107.88 reads/s END OF INNODB MONITOR OUTPUT 1 row in set (0.05 sec) Далее вы найдете некоторые примечания по выводу. • Если раздел TRANSACTIONS содержит информацию по ожидаемым блокировкам, то в вашем приложении может возникнуть конфликт блокировок. Выходные данные также могут помочь при отслеживании причин возникновения взаимных блокировок. • Раздел SEMAPHORES содержит информацию о потоках, ожидающих семафор, а также статистические данные по количеству повторных циклов или ожиданий, выполненных потоками для семафоров или блокировок чтения/записи. Большое количество потоков, ожидающих семафоры, может возникнуть в результате частого выполнения дисковых операций ввода-вывода, а также может быть обусловлено конфликтными ситуациями внутри самого механизма InnoDB. Конфликты могут иметь место при большом количестве параллельных запросов или в случае проблем с планированием потоков в операционной системе. В подобных ситуациях рекомендуется присвоить опции innodb_thread_concurrency значение меньше 8. • В разделе BUFFER POOL AND MEMORY содержится статистическая информация по записываемым и считываемым страницам. На основании этих сведений можно вычислить количество выполняемых операций ввода-вывода для файла данных, осуществляемых на данный момент в вашем запросе. • Раздел ROW OPERATION показывает, что делает главный поток.
568
Глава 9. Механизм хранения InnoDB
9.13. Реализация многовариантности Поскольку InnoDB является многовариантной базой данных, информация по старым версиям строк хранится в табличном пространстве. Эта информация содержится в структуре данных, которая по аналогии со структурой данных в Oracle называется сегментом отката (rollback segment). К каждой строке, хранящейся в базе данных, InnoDB добавляет по два поля. В 6байтовом поле хранится идентификатор последней транзакции, которая производила вставку или обновление строки. Удаление также рассматривается как обновление, при котором соответствующим образом помечается специальный бит удаления строки. Каждая строка содержит также 7-байтовое поле, которое называется указателем отката (roll pointer). Указатель отката указывает на запись в журнале отмены выполненных действий, занесенную в сегмент отката. Если строка была обновлена, запись в этом журнале будет содержать информацию, необходимую для восстановления содержимого строки до обновления. Информация из сегмента отката в базе данных InnoDB используется для отмены операций, которая необходима для отката транзакции. Она также используется при создании предыдущих версий строки для согласованного чтения. Журналы отмены выполненных действий в сегменте отката разделяются на журналы отмены вставок и журналы отмены обновлений. Журналы отмены вставок необходимы только для отката транзакций и могут быть удалены сразу после фиксации транзакции. Журналы отмены обновлений используются для согласованного чтения; их можно удалять только после того, как не останется ни одной транзакции, которой InnoDB присваивает копию, создающую при согласованном чтении раннюю версию строки на основе информации из журнала отмены обновлений. Не следует забывать о регулярной фиксации своих транзакций, включая те транзакции, в которых применяется согласованное чтение. В противном случае InnoDB не сможет удалить данные из журналов отмены обновлений, что приведет к увеличению размеров сегмента отката, который может занять все ваше табличное пространство. Физический размер записи журнала отмены в сегменте отката обычно меньше соответствующей вставленной или обновленной строки. Эту информацию можно использовать для вычисления размера пространства, необходимого для сегмента отката. В многовариантной схеме InnoDB строка физически не удаляется из базы данных после того, как она удаляется посредством SQL-оператора. Только после того, как InnoDB сможет удалить запись в журнале отмены обновлений, занесенную для удаления, соответствующая строка и ее индексная запись из базы данных могут быть удалены физически. Эта операция удаления называется чисткой (purge). Она производится достаточно быстро - на нее уходит столько же времени, сколько и на выполнение оператора SQLудаления.
9.14. Структуры таблиц и индексов MySQL хранит информацию своего словаря данных для таблиц в файлах . f rm, расположенных в каталогах базы данных. Однако для каждой таблицы InnoDB имеются также свои записи во внутренних словарях данных InnoDB в табличном пространстве. Когда MySQL удаляет таблицу или базу данных, необходимо удалить как файлы . f rm, так и соответствующие записи в словаре данных InnoDB. Именно поэтому нельзя пере-
9.14. Структуры таблиц и индексов
569
мещать таблицы innoDB между базами данных путем простого перемещения файлов . f rm. По той же причине команда DROP DATABASE не работала для таблиц InnoDB в версиях, предшествующих MySQL 3.23.43. Для всех таблиц InnoDB имеется специальный индекс, в котором хранятся данные строк - он называется кластеризованным индексом (clustered index). Если в таблице определить первичный ключ (PRIMARY KEY), то индекс первичного ключа будет кластеризованным индексом. Если первичный ключ для таблицы не был определен, MySQL будет использовать первый индекс UNIQUE, который имеют только столбцы NOT NULL, в качестве первичного ключа, и InnoDB рассматривает его как кластеризованный индекс. Если такого индекса в таблице нет, то InnoDB самостоятельно создаст кластеризованный индекс, в котором строки будут упорядочены по идентификаторам, присвоенным механизмом InnoDB строкам этой таблицы. Идентификатор строки представляет собой 6-байтовое поле, значение которого постоянно увеличивается при вставке новых строк. Таким образом, сортировка по идентификатору строки фактически представляет собой сортировку по последовательности вставки. Доступ к строке через кластеризованный индекс осуществляется достаточно быстро, поскольку данные строки находятся в той же странице, в которой производится поиск по индексу. При больших размерах таблицы архитектура кластеризованных индексов зачастую позволяет сократить количество дисковых операций ввода-вывода, если сравнивать ее с традиционными решениями. Записи в некластеризованных индексах (которые называются вторичными индексами) в InnoDB содержат значение первичного ключа для строки. InnoDB использует это значение первичного ключа для поиска строки в кластеризованном индексе. Следует иметь в виду, что если первичный ключ будет достаточно велик, вторичные индексы займут больше места. InnoDB сравнивает потоки CHAR и VARCHAR разной длины таким образом, что оставшаяся длина в более короткой строке будет рассматриваться как строка, содержащая пробелы.
9.14.1. Физическая структура индекса Все индексы в InnoDB являются В-деревьями, в которых запись индекса сохраняется в листовых страницах дерева. По умолчанию страница имеет размер 16 Кбайт. При вставке новых записей InnoDB пытается оставить свободной 1/16 страницы для будущих вставок и обновлений записей индекса. Если записи индекса вставлены в последовательном порядке (восходящем или нисходящем), то страница будет заполнена на 15/16. Если записи вставлены в случайном порядке, страницы будут заполнены от 1/2 до 15/16. Если коэффициент заполнения страницы будет меньше 1/2, InnoDB попытается сократить дерево индекса, чтобы освободить страницу.
9.14.2. Буферизация вставок Нередко в программах для работы с базами данных первичный ключ является уникальным идентификатором, и новые строки вставляются в порядке возрастания первичного ключа. Таким образом, для вставки в кластеризованный индекс нет необходимости проводить случайные считывания с диска.
570
Глава 9. Механизм хранения InnoDB
С другой стороны, вторичные индексы обычно не являются уникальными, поэтому вставки во вторичные индексы производятся в относительно случайном порядке. Это приводит к выполнению большого количества случайных дисковых операций вводавывода, если не используется специальный механизм, применяемый в InnoDB. Если требуется вставить запись индекса во вторичный индекс, который не является уникальным, InnoDB проверяет, находится ли страница вторичного индекса в буферном пуле. Если она там есть, InnoDB произведет вставку непосредственно в страницу индекса. Однако если страница индекса не будет найдена в буферном пуле, InnoDB вставит запись в специальную структуру буфера вставок. Буфер вставок имеет настолько небольшой размер, что может полностью поместиться в буферном пуле, и вставки в него могут производиться очень быстро. Буфер вставок периодически объединяется с деревьями вторичных индексов в базе данных. Часто за счет объединения нескольких вставок на одной странице индексного дерева можно сократить количество дисковых операций ввода-вывода. Использование буфера вставки может ускорить процессы вставки в таблицу в 15 раз.
9.14.3. Адаптивный хешированный индекс Если база данных практически вся умещается в основной памяти, то самым быстрым способом выполнения запросов по этой базе данных является использование хешированных индексов. В InnoDB существует автоматический механизм, который отслеживает поиски по индексу, которые осуществляются по индексам, определенным для таблицы. Если InnoDB посчитает, что запросы выиграют от создания хешированного индекса, такой индекс будет создан автоматически. Следует, однако, иметь в виду, что хешированный индекс всегда создается на основе существующего индекса В-дерева таблицы. InnoDB может создать хешированный индекс на префиксах любой длины ключа, определенного для В-дерева, в зависимости от того, по какой схеме поиска InnoDB просматривается индекс В-дерева. Хешированный индекс может быть частичным: не обязательно кэшировать в буферном пуле весь индекс Вдерева. InnoDB будет создавать хешированные индексы по запросу для тех страниц индекса, к которым часто производится доступ. Хотя механизм адаптивного хешированного индекса InnoDB приспосабливается к большому объему основной памяти, он больше подходит для архитектуры баз данных в основной памяти.
9.14.4. Физическая структура записи Записи в таблицах InnoDB имеют следующие характеристики: •
У всех записей индекса в InnoDB имеется заголовок, состоящий из 6 байт. Этот заголовок используется для связывания вместе последовательных записей, а также при блокировке на уровне строк.
• Записи в кластеризованном индексе содержат поля для всех столбцов, определенных пользователем. Кроме этого, имеется поле в 6 байтов для идентификатора транзакции и поле в 7 байт для указателя строки. • Если пользователь не определил для таблицы первичный ключ, то в каждой записи кластеризованного индекса также содержится 6-байтовое поле идентификатора строки.
9.15. Управление файловым пространством и дисковый ввод-вывод
571
• Каждая запись вторичного индекса содержит все поля, определенные для ключа кластеризованного индекса. • Запись содержит указатель на каждое поле записи. Если общая длина полей в записи будет меньше 128 байт, то указатель будет иметь размер в 1 байт, в противном случае - 2 байта. • InnoDB сохраняет столбцы фиксированной длины, такие как CHAR (10), в формате фиксированной длины. InnoDB усекает завершающие пробелы в столбцах VARCHAR. Учтите, что InnoDB может преобразовывать столбцы CHAR в VARCHAR. •
SQL-значение NULL занимает 0 байт при сохранении в столбце переменной длины. В столбце фиксированной длины резервируется фиксированная длина. Необходимость резервирования фиксированного пространства для значения NULL объясняется тем, что замена значения NULL на другое отличное от него значение осуществляется на месте и не приводит к фрагментации индексной страницы.
9.15. Управление файловым пространством и дисковый ввод-вывод 9.15.1. Дисковый ввод-вывод В операциях дискового ввода-вывода для таблиц InnoDB используется асинхронный ввод-вывод. InnoDB создает определенное количество потоков ввода-вывода, что позволяет обеспечить выполнение таких операций ввода-вывода, как опережающее чтение. В InnoDB используются два эвристических подхода к реализации опережающего чтения: • При последовательном опережающем чтении InnoDB, определив, что схема доступа к сегменту в табличном пространстве является последовательной, будет заранее направлять механизму ввода-вывода пакет считываний страниц базы данных. • При случайном опережающем чтении InnoDB, определив, что некоторые части табличного пространства полностью считываются в буферный пул, направляет оставшиеся считывания механизму ввода-вывода. Начиная с версии MySQL 3.23.41, в InnoDB используется новый способ сброса файлов на диск, который получил название двойной записи (doublewrite). Он обеспечивает высокую степень защиты при восстановлении после сбоя или отключении питания и позволяет увеличить производительность в большинстве версий Unix за счет уменьшения количества операций fsync (). Двойная запись означает, что InnoDB перед записью страниц в файл данных сначала записывает их в смежный участок табличного пространства, называемый буфером двойной записи (doublewrite buffer). Запись страниц в предназначенные для них места в файле данных выполняется только после завершения записи и сброса буфера двойной записи на диск. Если во время записи страницы произошел сбой, то во время восстановления InnoDB найдет в буфере двойной записи подходящую копию страницы.
572
Глава 9. Механизм хранения InnoDB
9.15.2. Использование низкоуровневых устройств для табличного пространства Начиная с версии MySQL 3.23.41, в качестве файлов данных табличного пространства можно также использовать низкоуровневые диски. Используя низкоуровневый диск, в Windows и в некоторых системах семейства Unix вы можете организовать ввод-вывод без участия буфера, не перегружая файловую систему. Это позволяет улучшить показатели производительности. При создании нового файла данных непосредственно за размером файла данных в опции innodb_data_f ile_path необходимо указать ключевое слово newraw. Раздел диска должен быть больше указанного размера или равен ему. Обратите внимание: 1 Мбайт в InnoDB - это 1024*1024 байт, тогда как в характеристиках диска 1 Мбайт обычно соответствует 1 000 000 байт. [mysqld] innodb_data_home_dir= innodb_data_filejpath=/dev/hddl:3Gnewraw;/dev/hdd2:2Gnewraw При новом запуске сервера InnoDB обнаруживает ключевое слово newraw и инициализирует новый раздел. Однако пока не создавайте и не изменяйте таблицы InnoDB, поскольку после перезапуска сервера InnoDB повторно инициализирует раздел и внесенные изменения будут утеряны. (Начиная с версий 3.23.44, в качестве меры предосторожности InnoDB запрещает изменять данные, если раздел указан как newraw.) После того как InnoDB инициализирует новый раздел, необходимо остановить сервер и заменить ключевое слово newraw на raw: [mysqld] i n n о db__da t a_h ome_d i r= innodb_data_file_path=/dev/hddl:5Graw;/dev/hdd2:2Graw Затем перезапустите сервер, теперь InnoDB разрешает производить изменения. В Windows, начиная с версии MySQL 4.1.1, можно размещать раздел диска в виде файла данных, как показано далее: [mysqld] innodb_data_home_dir= innodb_data_file_path=//./D::10Gnewraw Последовательность //./ соответствует синтаксису \\.\ в Windows, которые применяется для доступа к физическим дискам. С низкоуровневыми разделами диска должны быть связаны права доступа, имеющие дело с учетными записями, которые используются при работе сервера MySQL.
9.15.3. Управление файловым пространством Табличное пространство InnoDB составляют файлы данных, определенные в файле конфигурации. Файлы попросту присоединяются друг к другу, что и приводит к формированию табличного пространства. Разделение данных на полосы в них не производится. На данный момент невозможно непосредственно указать, где именно в табличном пространстве должны размещаться таблицы. Однако во вновь созданном табличном пространстве InnoDB распределяет пространство, начиная с первого файла данных.
9.15. Управление файловым пространством и дисковый ввод-вывод
573
Табличное пространство состоит из страниц базы данных, размер которых по умолчанию составляет 16 Кбайт. Эти страницы группируются в блоки, или экстенты (extent), состоящие из 64 последовательно расположенных страниц. "Файлы" внутри табличного пространства InnoDB называются "сегментами". Термин "сегмент отката" несколько не соответствует действительности, поскольку на самом деле в нем содержится множество сегментов табличного пространства. Для каждого индекса в InnoDB выделяется два сегмента: один - для конечных узлов В-дерева, а другой - для остальных узлов. Идея состоит в том, чтобы достичь более организованного расположения конечных узлов, в которых содержатся данные. Когда сегмент внутри табличного пространства возрастает, то специально для него InnoDB выделяет первые 32 страницы. После этого InnoDB начинает выделять для этого сегмента целые области расширения. Чтобы обеспечить хорошую организацию данных, InnoDB может добавить к большому сегменту до 4 областей расширения за один раз. Некоторые страницы табличного пространства содержат битовые образы других страниц, поэтому несколько экстентов в табличном пространстве InnoDB могут быть выделены не для целых сегментов, а только для отдельных страниц. После выдачи команды SHOW TABLE STATUS для получения информации о доступном свободном пространстве в табличном пространстве InnoDB выводит отчет о свободных экстентах. InnoDB всегда резервирует некоторые экстенты для выполнения очистки и других внутренних операций. Зарезервированные экстенты в объем свободного пространства не включаются. Если из таблицы удаляются данные, InnoDB объединяет соответствующие индексы Вдерева. В зависимости от схемы удалений, когда освобождаются отдельные страницы или экстенты табличного пространства, высвобожденная область становится доступной другим пользователям. Удаление таблицы или удаление всех ее строк гарантированно освободит пространство для других пользователей, но при этом не следует забывать, что физически строки удаляются только после проведения очистки, после чего они становятся ненужными при откате транзакций или согласованном чтении.
9.15.4. Дефрагментация таблицы Если в индексы таблицы выполнялись случайные вставки или удаления, индексы могут оказаться фрагментированными. Под фрагментацией понимается то, что физическое расположение индексных страниц на диске существенно отличается от алфавитного порядка страниц, или что в 64-страничных блоках, отведенных для индекса, присутствует множество пустых страниц. Скорость сканирования индекса можно увеличить с помощью команды ALTER TABLE: ALTER TABLE шя_таблицы TYPE=InnoDB При этом MySQL перестраивает таблицу. Существует еще один способ выполнить дефрагментацию - воспользоваться командой mysqldump для копирования дампа таблицы в текстовый файл, записи диска на диск и повторной загрузки таблицы из дампа. Если вставки в индекс всегда производятся последовательно, а удаления - только с конца, то алгоритм управления файловым пространством InnoDB гарантирует отсутствие фрагментации индекса.
574
Глава 9. Механизм хранения InnoDB
9.16. Обработка ошибок Обработка ошибок в innoDB не всегда соответствует спецификациям стандарта SQL. В соответствии со стандартом, любая ошибка, которая возникла во время выполнения SQL-оператора, должна приводить к откату оператора. Иногда InnoDB реализует откат только части оператора или целой транзакции. Ниже описаны особенности обработки ошибок в InnoDB: • Если свободное место в табличном пространстве закончилось, выдается сообщение MySQL об ошибке Table is full (Таблица переполнена), и InnoDB выполняет откат SQL-оператора. • Взаимная блокировка транзакции или истечение времени ожидания при блокировке приводят к откату целой транзакции. • Ошибка дублирования ключей приводит к откату вставки только данной определенной строки, даже в операторе INSERT INTO.. .SELECT. Этот алгоритм, возможно, будет изменен, чтобы можно было выполнять откат всего SQL-оператора, если для него не указана опция IGNORE. • Ошибка "row too long" ("слишком длинная строка") вызывает откат SQLоператора. • Большинство остальных ошибок обнаруживается на уровне кода MySQL (выше уровня механизма хранения InnoDB), и в случае их возникновения выполняется откат соответствующего SQL-оператора.
9.16.1. Коды ошибок InnoDB Ниже представлен перечень наиболее распространенных ошибок InnoDB, с которыми вы можете столкнуться, а также сведения о том, почему они возникают и советы по решению проблем. •
1005 (ER_CANT_CREATE_TABLE). Невозможно создать таблицу. Если уведомление об ошибке ссылается на ошибку с номером 150, это означает, что создать таблицу не удалось, поскольку ограничения внешнего ключа не были правильно сформулированы.
•
1016 (ER_CANT_OPEN_FILE). Невозможно найти таблицу InnoDB из файлов данных InnoDB в файле . f rm для существующей таблицы. См. раздел 9.18.1.
•
1114 (ER_RECORD_FILE_FULL). Механизм InnoDB исчерпал свободное место в табличном пространстве. Чтобы добавить новый файл данных, потребуется заново конфигурировать табличное пространство.
•
1205 (ER_LOCK_WAIT_TIMEOUT). Время ожидания блокировки истекло. Произошел откат транзакции.
•
1213 (ER_LOCK_DEADLOCK). Взаимная блокировка транзакции. Необходимо повторно запустить транзакцию.
•
1216 (ER_NO_REFERENCED_ROW). Попытка добавления строки при отсутствии родительской строки; сбой ограничения внешнего ключа. Необходимо добавить сначала родительскую строку.
•
1217 (ER_ROW_IS_REFERENCED). Попытка удалить родительскую строку, имеющую дочерние строки; сбой ограничения внешнего ключа. Необходимо удалить сначала дочерний ряд.
9.16. Обработка ошибок
575
9.16.2. Коды ошибок операционной системы Для вывода содержания ошибки операционной системы служит программа perror, входящая в состав дистрибутива MySQL. Ниже представлен список некоторых распространенных кодов ошибок системы Linux. Более подробно о них можно узнать в исходном коде Linux (http://www.iglu.org.i1/lxr/source/include/asrai386/errno.h). • 1 (EPERM). Запрет на выполнение операции. • 2 (ENOENT). Такой файл или каталог отсутствует. • 3 (ESRCH). Такой процесс отсутствует. • 4 (EINTR). Прерванный системный вызов. • 5 (ЕЮ). Ошибка ввода-вывода. • 6 (ENXIO). Такое устройство или адрес отсутствует. • 7 (E2BIG). Слишком большой список аргументов. • 8 (ENOEXEC). Ошибка формата исполняемого файла. • 9 (EBADF). Неверный номер файла. • 10 (ECHILD). Отсутствуют дочерние процессы. • 11 (EAGAIN). Попытайтесь повторить операцию. • 12 (ENOMEM). Недостаточно памяти. • 13 (EACCES). В доступе отказано. •
14 (EFAULT). Неверный адрес.
• 15 (ENOTBLK). Требуется блокировка устройства. • 16 (EBUSY). Занято устройство или ресурс. • 17 (EEXIST). Файл существует. • 18 (EXDEV). Ссылки между устройствами. • 19 (ENODEV). Такое устройство отсутствует. • 20 (ENOTDIR). Это не каталог. •
21 (EISDIR). Это каталог.
•
22 (EINVAL). Неверный аргумент.
• 23 (ENFILE). Переполнение таблицы файлов. • 24 (EMFILE). Слишком много открытых файлов. • 25 (ENOTTY). Несоответствующий i o c t l для устройства. • 26 (ETXTBSY). Текстовый файл занят. • 27 (EFBIG). Слишком большой файл. • 28 (ENOSPC). Свободное место на устройстве отсутствует. • 29 (ESPIPE). Неразрешенный поиск. • 3 0 (EROFS). Файловая система только для чтения. • 31 (EMLINK). Слишком много ссылок.
576
Глава 9. Механизм хранения InnoDB
Далее следует перечень некоторых распространенных кодов ошибок системы Windows. Более подробно о них можно узнать на сайте Microsoft по адресу: http://msdn.microsoft.com/library/default.asp?url=/library/ en-us/debug/base/system_error_codes.asp •
1 (ERROR_INVALID_FUNCTION). Недопустимая функция.
•
2 (ERROR_FILE_NOT_FOUND). Система не может найти указанный файл.
•
3 (ERROR_PATH_NOT_FOUND). Система не может найти указанный путь.
•
4 (ERROR_TOO_MANY_OPEN_FILES). Система не может открыть файл.
•
5 (ERROR_ACCESS_DENIED). В доступе отказано.
•
б (ERROR_INVALID_HANDLE). Недопустимый дескриптор.
•
7 (ERROR_ARENA__TRASHED). Блоки управления памятью разрушены.
•
8 (ERROR_NOT_ENOUGH_MEMORY). Недостаточно памяти для выполнения команды.
•
9 (ERROR_INVALID_BLOCK). Недопустимый адрес блока управления памятью.
•
10 (ERRORJBAD_ENVIRONMENT). Недопустимая среда.
•
11 (ERROR_BAD_FORMAT). Попытка загрузить программу с недопустимым форматом.
•
12 (ERROR_INVALID_ACCESS). Неверный код доступа.
•
13 (ERROR_INVALID_DATA). Недопустимые данные.
•
14 (ERROR_OUTOFMEMORY). Недостаточно памяти для завершения этой операции.
•
15 (ERROR_INVALID_DRIVE). Система не может найти указанное устройство.
•
16 (ERROR_CURRENT_DIRECTORY). Этот каталог не может быть удален.
•
17 (ERROR_NOT_SAME_DEVICE). Система не может переместить файл на другое дисковое устройство.
•
18 (ERROR_NO_MORE_FILES). Файлов больше нет.
•
19 (ERROR_WRITE_PROTECT). Носитель защищен от записи.
•
20 (ERROR_BAD_UNIT). Система не может найти указанное устройство.
•
21 (ERROR_NOT_READY). Устройство не готово.
•
22 (ERROR_BAD_COMMAND). Устройство не распознает команду.
•
23 (ERROR_CRC). Ошибка в данных (циклический код с избыточностью).
•
24 (ERROR_BAD_LENGTH). Программа выдала команду с недопустимой длиной.
•
25 (ERROR_SEEK). Дисковое устройство не может обнаружить указанную область или дорожку.
•
26 (ERROR_NOT_DOS__DISK). Нет доступа к указанному диску или дискете.
•
27 (ERROR_SECTOR_NOT_FOUND). Дисковое устройство не может обнаружить запрошенный сектор.
•
28 (ERROR_OUT_OF_PAPER). В принтере закончилась бумага.
•
29 (ERROR_WRITE_FAULT). Система не может выполнить запись на указанное устройство.
•
30 (ERRORREADFAULT) .Система не может выполнить чтение с указанного устройства.
9.17. Ограничения таблиц InnoDB
577
•
31 (ERROR_GEN_FAILURE). Устройство, подключенное к системе, не работает.
•
32 (ERROR_SHARING_VIOLATION). Процесс не имеет доступа к файлу, поскольку файл используется другим процессом.
•
33 (ERROR_LOCK_VIOLATION). Процесс не имеет доступа к файлу, поскольку другой процесс заблокировал часть файла.
•
34 (ERROR_WRONG_DISK). Вставьте другую дискету. Вставьте %2 (серийный номер тома: %3) в дисковод % 1 .
•
36
(ERROR_SHARING_BUFFER_EXCEEDED). СЛИШКОМ МНОГО фаЙЛОВ ОТКрЫТО ДЛЯ СО-
вместного использования. •
38 (ERROR_HANDLE_EOF). Достигнут конец файла.
•
39 (ERRORJiANDLE_DlSK_FULL). Отсутствует место на диске.
• •
112 (ERROR_DISK_FULL). Отсутствует место на диске. 123 (ERROR_INVALID_NAME). Неверный синтаксис имени файла, каталога или метки тома.
•
1450 (ERROR_NO__SYSTEM_RESOURCES). Недостаточно системных ресурсов для завершения затребованной службы.
9.17. Ограничения таблиц InnoDB
| Щ Ж | fj
•
Таблица не может содержать более 1000 столбцов.
•
Максимальная длина ключа составляет 1024 байта.
•
Максимальная длина строки, за исключением столбцов BLOB и TEXT, чуть меньше половины страницы базы данных; то есть, максимальная длина строки составляет приблизительно 8000 байт. Длина столбцов LONGBLOB и LONGTEXT должна быть менее 4 Гбайт, а общая длина строки, включая столбцы BLOB и TEXT, - менее 4 Гбайт. InnoDB сохраняет первые 512 байт столбца BLOB и TEXT в строке, а остальные переносит на отдельные страницы.
•
В некоторых операционных системах файлы данных должны иметь размер до 2 Гбайт.
•
Комбинированный размер файлов журналов InnoDB должен быть менее 4 Гбайт.
•
Минимальный размер табличного пространства составляет 10 Мбайт. Максимальный размер табличного пространства составляет 4 триллиона страниц базы данных (64 Тбайт), что является также максимальным размером таблицы.
•
Таблицы InnoDB не поддерживают индексы FULLTEXT.
•
В среде Windows механизм InnoDB всегда хранит имена баз данных и таблиц в нижнем регистре. Чтобы перенести базы данных в двоичном формате из Unix в Windows или наоборот, необходимо, чтобы имена всех баз данных и таблиц были представлены буквами нижнего регистра.
Предупреждение Не преобразовывайте системные таблицы MySQL в базе данных mysql из My ISAM в InnoDB! Эта операция не поддерживается. Если вы это сделаете, MySQL не будет запускаться до тех пор, пока вы не восстановите старые системные таблицы из резервной копии или не сгенерируете их с помощью сценария mysql_install_db.
578
Глава 9. Механизм хранения InnoDB
•
InnoDB не выполняет внутренний подсчет строк в таблице. (Это слишком сложно по причине поддержки многовариантности.) Чтобы обработать оператор SELECT COUNT(*) FROM T, механизм InnoDB должен сканировать индекс таблицы, на что потребуется некоторое время, если не вся таблица находится в буферном пуле. Для быстрого подсчета лучше пользоваться счетчиком таблицы, который вы должны создать сами, и позволить вашему приложению обновляться в соответствии с операциями вставки и удаления. Если ваша таблица изменяется редко, тогда лучше всего использовать кэш запросов MySQL. Можно выдавать также и команду SHOW TABLE STATUS, если интересует только приблизительный подсчет строк. См. раздел 9.12.
• Для столбца AUTOINCREMENT всегда следует указывать индекс для таблицы. Этот индекс должен содержать только столбец AUTOINCREMENT. В таблицах My ISAM столбец AUTOINCREMENT может быть частью индекса с множеством столбцов. •
InnoDB не использует параметр таблицы AUTO_INCREMENT для настройки значения первоначальной последовательности в операторе CREATE TABLE или ALTER TABLE. Чтобы настроить значение с помощью InnoDB, вставьте фиктивную строку с меньшим значением и удалите эту фиктивную строку, либо вставьте первую строку с явно указанным значением.
•
Во время перезапуска сервера MySQL InnoDB может вновь использовать старое значение для столбца AUTOINCREMENT (то есть, значение, которое было присвоено отклоненной старой транзакции).
•
Когда в столбце AUTOINCREMENT количество возможных значений превышает норму, InnoDB присваивает BIGINT значение -9223372036854775808, a BIGINT UNSIGNED - значение 1. Для значений BIGINT используется 64 бита, поэтому имейте в виду, что если вы выполняли вставку одного миллиона строк в секунду, пройдет около миллиона лет, прежде чем BIGINT достигнет своей верхней границы. Во всех других столбцах целочисленного типа возникнет ошибка дублирования ключей. То же самое характерно и для механизма MylSAM - это обычное поведение MySQL, а не какого-то механизма хранения.
•
Оператор DELETE FROM имя_таблицыне генерирует таблицу, а удаляет все строки, одну за другой.
•
TRUNCATE имя_ та блицы соответствует DELETE FROM имя__таблицы в InnoDB и не обнуляет счетчик AUTO__INCREMENT.
•
Команда SHOW TABLE STATUS не выдает точную статистику по таблицам InnoDB, за исключением физического размера, зарезервированного таблицей. Счетчик строк используется только для приближенной оценки для оптимизации SQL.
•
Если вы попытаетесь создать уникальный индекс в префиксе столбца, будет сгенерирована ошибка: CREATE TABLE T (A CHAR(20), В INT, UNIQUE (A(5))) TYPE = InnoDB; Если вы создаете неуникальный индекс в префиксе столбца, InnoDB создаст индекс по всему столбцу. В версиях MySQL 4.0.14 и 4.1.1 эти ограничения сняты.
•
Команда INSERT DELAYED для таблиц InnoDB не поддерживается.
9.18. Поиск и устранение неполадок в InnoDB
579
• Операции MySQL LOCK TABLES ничего не известно о блокировках на уровне строк в InnoDB, установленных уже выполненными SQL-операторами. Это означает, что таблица может оказаться заблокированной даже при существующих транзакциях других пользователей, у которых в данной таблице установлены блокировки на уровне строк. Таким образом, выполнение ваших операций над таблицей может быть отложено, если они столкнутся с блокировками, установленными другими пользователями. Возможно также появление взаимных блокировок. Однако это не означает, что целостность транзакций может быть нарушена, поскольку блокировки на уровне строк, устанавливаемые InnoDB, всегда отслеживают целостность. Кроме того, если таблица будет заблокирована, то транзакции не смогут установить в ней большее количество блокировок на уровне строки (в режиме конфликтующих блокировок). • До выхода версии MySQL 3.23.52 репликация всегда выполнялась в режиме автоматической фиксации. Поэтому процессам согласованного чтения на подчиненном сервере также могли быть видимы частично обработанные транзакции, поэтому чтение на подчиненном сервере не было действительно согласованным. Это ограничение было снято в MySQL 3.23.52. • Оператор LOAD TABLE FROM MASTER для настройки репликации на подчиненных серверах пока что не работает. В качестве альтернативы на главном сервере можно изменить формат таблицы на My ISAM, выполнить загрузку, а затем изменить формат главной таблицы снова на InnoDB. • По умолчанию размер страницы базы данных в InnoDB составляет 16 Кбайт. После повторной компиляции можно установить другой размер в диапазоне от 8 Кбайт до 64 Кбайт. Потребуется обновить значения UNIV_PAGE_SIZE и UNIV_PAGE_SIZE_SHIFT в файле исходного кода univ.i.
9.18. Поиск и устранение неполадок в InnoDB • Существует общее правило: когда происходит сбой при выполнении какой-то операции, или если вы подозреваете о существовании программной ошибки, необходимо просмотреть журнал ошибок сервера MySQL, который обычно имеет имя наподобие имя_хоста. err или mysql. err в Windows. • При поиске неполадок лучше всего запустить сервер MySQL из командной строки, а не с помощью оболочки mysqld_safe или как службу Windows. Вы сможете следить за информацией, выводимой mysqld в окне командной строки, и будете осведомлены о происходящих событиях. В Windows сервер должен быть запущен с опцией —console, в результате чего выходная информация будет направляться в окно консоли. • Чтобы получить сведения о возникшей проблеме, используйте мониторы InnoDB. Если проблема связана со снижением показателей производительности, или если ваш сервер зависает, попробуйте воспользоваться монитором innodbmonitor, который выводит информацию о внутреннем состоянии InnoDB. Если эта проблема связана с блокировками, используйте монитор innodb_lock_monitor. Если проблема связана с созданием таблиц или с другими операциями словаря данных, используйте монитор innodb_table_monitor, который выводит информацию о содержимом внутреннего словаря данных InnoDB.
580
Глава 9. Механизм хранения InnoDB
• Если вы подозреваете, что таблицы повреждена, запустите для нее команду CHECK TABLE.
9.18.1. Поиск и устранение неполадок в операциях словаря данных InnoDB Особенность таблиц заключается в том, что сервер MySQL хранит информацию словаря данных в файлах . f rm, которые расположены в каталогах баз данных, в то время как InnoDB хранит информацию в своем собственном словаре данных в файлах табличного пространства. Если вы перемещаете файлы . frm или используете команду DROP DATABASE в версиях MySQL, предшествующих 3.23.44, или если происходит сбой сервера во время выполнения операций со словарем данных, файлы . frm могут рассинхронизироваться со словарем данных InnoDB. Признаком нарушения синхронизации словаря данных является сбой при работе оператора CREATE TABLE. Если это произошло, просмотрите журнал ошибок сервера. Если в этом журнале вы найдете запись о том, что таблица уже существует внутри словаря данных InnoDB, значит, вы имеете дело с "висячей" таблицей в файлах табличного пространства InnoDB, для которой отсутствует соответствующий файл .frm. Сообщение об ошибке выглядит следующим образом: InnoDB: Error: table test/parent already exists in InnoDB internal InnoDB: data dictionary. Have you deleted the .frm file InnoDB: and not used DROP TABLE? Have you used DROP DATABASE InnoDB: for InnoDB tables in MySQL version mysqladmin -h чhostname4 version • Кто-то мог удалить файл Unix-сокета, который использует mysqld (по умолчанию это /tmp/mysql. sock). Например, у вас может работать задание сгоп, которое удаляет старые файлы из каталога /tmp. Вы всегда должны запускать команду mysqladmin version, чтобы проверить, действительно ли существует файл сокета, который mysqladmin будет использовать. Решение в этом случае сводится к изменению задания сгоп таким образом, чтобы оно не удаляло mysql.sock, или к размещению упомянутого файла где-нибудь в другом месте. См. раздел А.4.5. • Вы запустили mysqld с опцией —socket=/path/to/socket, но забыли указать клиентским программам новое имя файла сокета. Если вы изменяете путь к файлу сокета для сервера, вы также должны известить об этом клиентов MySQL. Это можно сделать той же опцией —socket при запуске клиентской программы. См. также раздел А.4.5. • Вы работаете под Linux, и один их потоков сервера прерван по ошибке (со сбросом дампа памяти). В этом случае нужно прервать все остальные потоки mysqld (например, командой k i l l или сценарием mysqlzap) прежде, чем перезапускать сервер mysqld. См. раздел А.4.2. • Сервер или клиентская программа могут не иметь необходимых прав доступа к каталогу, в котором находится файл Unix-сокета, или же к самому файлу сокета. В этом случае вы должны либо изменить права доступа к каталогу или файлу сокета таким образом, чтобы сервер и клиенты могли иметь к ним доступ, либо перезапустить mysqld с опцией --socket, указывающей имя файла сокета, находящегося в каталоге, в котором сервер сможет создать его и клиент будет иметь к нему доступ. Если вы получаете сообщение об ошибке Can' t connect to MySQL server on хост (Невозможно подключиться к серверу MySQL на хост), можете попробовать проделать следующие вещи, чтобы найти, в чем проблема:
592
Приложение А. Поиск и устранение неполадок в программах MySQL
• Проверьте, запущен ли сервер на хосте, выполнив команду t e l n e t хост 3306 и несколько раз нажав клавишу <Enter>. (3306 - это порт по умолчанию, который использует MySQL. Измените это значение, если ваш сервер прослушивает другой порт.) Если сервер MySQL работает и использует этот порт, то вы должны получить ответ, который включает номер версии сервера. Если вы получите ошибку вроде такой: t e l n e t : Unable to connect to remote host: Connection refused (telnet: Невозможно подключиться к удаленному хосту: Подключение отклонено), то это означает, что на этом порте нет работающего сервера. • Если сервер запущен на локальном хосте, попробуйте подключиться через файл Unix-сокета с помощью команды mysqladmin -h localhost variables. Проверьте номер порта TCP/IP, на который настроен сервер (это значение переменной port). •
Убедитесь, что ваш сервер mysqld не был запущен с опцией --skip-nrtworkingservice. Если эта опция использовалась, вы не сможете подключиться через TCP/IP.
А.2.3. Клиент не поддерживает протокол аутентификации MySQL 4.1 и выше, поддерживает протокол аутентификации, основанный на алгоритме хеширования паролей, который не совместим с тем, что используют старые клиентские программы. Если вы обновили сервер до версии 4.1, то попытка подключения к нему более старыми клиентами может провалиться с выдачей следующего сообщения: shell> mysql Client does not support authentication protocol requested by server; consider upgrading MySQL client Для решения этой проблемы воспользуйтесь одним из следующих подходов: • Обновите все клиентские программы, чтобы они использовали клиентскую библиотеку от версии 4.1.1 или более новую. • При подключении к серверу клиентскими программами более старых версий, используйте учетную запись, для которой установлен пароль в формате старых версий. • Переустановите пароли для всех пользователей, которым нужно работать со старыми клиентскими программами таким образом, чтобы они были в старом формате. Это можно сделать с помощью оператора SET PASSWORD и функции OLD_PASSWORD():
mysql> SET PASSWORD FOR ->
' пользователь'
@ ' хост'
= OLD_J?ASSWORD (' новый_пароль')
;
В качестве альтернативного варианта используйте UPDATE и FLUSH PRIVILEGES: mysql> UPDATE m y s q l . u s e r SET Password = OLD_PASSWORD('новый_пароль') -> WHERE Host = 'хост* AND U s e r = 'пользователь1; mysql> FLUSH PRIVILEGES;
Подставьте вместо новый^пароль новый пароль. MySQL не может сообщить вам, какой пароль был установлен ранее, поэтому вам придется указать новый. •
Укажите серверу использовать старый алгоритм хеширования паролей:
А.2. Наиболее общие ошибки при работе с программами MySQL
593
1. Запустите mysqld с опцией --old-password. 2. Установите пароль в старом формате каждой учетной записи, пароль которой был изменен под длинный формат 4.1. Вы можете идентифицировать эти учетные записи с помощью следующего запроса: mysql> SELECT Host, User, Password FROM mysql.user -> WHERE LENGTH(Password) > 16; Для каждой учетной записи, возвращенной этим запросом, используя значения User и Host, присвойте пароль функцией OLDPASSWORDO вместе с оператором SET PASSWORD или UPDATE, как было показано выше. Дополнительные сведения о хешировании паролей и аутентификации можно найти в разделе 4.4.9.
А.2.4. Пароль не принимается при интерактивном вводе Клиентские программы MySQL выдают приглашение на ввод пароля, когда запускаются с опциями —password или -р, после которых пароль не указавается: shell> mysql -u имя_пользователя -р Enter password: В некоторых системах вы можете обнаружить, что пароль работает, когда он указан в файле опций, или в командной строке, но не работает, когда вы вводите его интерактивно по приглашению Enter password:. Это случается, когда библиотека, представляемая системой для чтения паролей, ограничивает при вводе его длину меньшим количеством символов (обычно восемью). Это проблема системной библиотеки, а не MySQL. Чтобы обойти это, измените пароли MySQL, чтобы они не превышали по длине 8 символов, или же указывайте пароли в файле опций.
А.2.5. Хост йимя__хоста заблокирован Если вы получаете приведенное ниже сообщение об ошибке, это означает, что mysqld получил много запросов на подключение от хоста ' имя_хоста', которые были прерваны: Host 'имя_хоста1 is blocked because of many connection errors. Unblock with 'mysqladmin flush-hosts' Хост 'имя хоста* заблокирован по причине множества ошибок подключений. Разблокируйте хост с помощью 'mysqladmin flush-hosts' Максимальное количество прерванных запросов на подключение определяется значением системной переменной max_connect_errors. После того, как max_connect_errors попыток подключения проваливаются, сервер предполагает, что что-то не так (например, что кто-то пытается его взломать), и блокирует все дальнейшие подключения до тех пор, пока вы не выполните команду mysqladmin flush-hosts или оператор FLUSH HOSTS. См. раздел 4.2.3. По умолчанию mysqld блокирует хост после 10 ошибок подключения. Это можно изменить, запустив его следующим образом: shell> mysqld_safe —max_connect_errors=10000 & Если вы получаете это сообщение об ошибке для конкретного хоста, вам следует проверить, все ли в порядке с подключением через TCP/IP с этого хоста. Если у вас
594
Приложение А. Поиск и устранение неполадок в программах MySQL
проблема с сетью, будет не слишком хорошо увеличивать значение переменной max_connect_errors.
А.2.6. Слишком много подключений Если при попытке подключения к mysqld вы получаете ошибку Too many connections (Слишком много подключений), это означает, что все возможные подключения уже заняты другими клиентами. Количество допустимых подключений управляется системной переменной maxconnections. Ее значение по умолчанию равно 100. Если вам нужно поддерживать больше подключений, перезапустите mysqld, указав большее значение этой переменной. mysqld в настоящее время разрешает подключиться max_connections+l клиенту. Дополнительное подключение зарезервировано для пользователя с привилегией SUPER. Выдавая привилегию SUPER только администраторам, а не обычным пользователям (которым она и не нужна), администратор всегда сможет подключиться к серверу и воспользоваться SHOW PROCESSLIST для диагностики проблем, даже если максимальное количество непривилегированных пользователей уже подключены. Максимальное количество подключений, которое может поддерживать MySQL, зависит от качества библиотеки поддержки потоков на данной платформе. Linux или Solaris в состоянии обеспечить 500-1000 параллельных подключений, в зависимости от того, сколько памяти доступно в системе, и какую работу выполняют клиенты.
А.2.7. Недостаточно памяти Если вы отправляете запрос, используя клиентскую программу mysql, и получаете ошибку вроде приведенной ниже, это означает, что mysql не хватает памяти, чтобы сохранить весь результат запроса: mysql: Out of memory at line 42, 'malloc.c 1 mysql: needed 8136 byte (8k), memory in use: 12481367 bytes (12189k) ERROR 2008: MySQL client ran out of memory Чтобы исправить положение, сначала убедитесь в корректности выданного запроса. Имеет ли смысл то, что он возвращает настолько много строк? Если нет, исправьте запрос и попробуйте запустить его снова. Иначе можете вызвать mysql с опцией —quick. Это заставит его использовать функцию С API mysql_use_result(), чтобы получать больший по объему результат, который меньше нагружает клиента (но больше - сервер).
А.2.8. Сервер MySQL потерян Этот раздел также касается ошибки Lost connection t o s e r v e r during query (Потеряно соединение с сервером при обработке запроса). Наиболее общая причина ошибки MySQL s e r v e r has gone away (Сервер MySQL потерян) связана с тем, что сервер закрывает соединения по тайм-ауту. В этом случае вы получите один из следующих кодов ошибки (какой именно - зависит от операционной системы): Код ошибки
Описание
CR_SERVER_GONE_ERROR
Клиент не смог отправить запрос серверу.
CR_SERVER_LOST
Клиент не получил ошибку при записи на сервер, но и не получил полного ответа (или ни одного ответа) на запрос.
А.2. Наиболее общие ошибки при работе с программами MySQL
595
По умолчанию сервер закрывает соединение после восьми часов простоя. Вы можете изменить этот предел, установив нужное значение переменной wait_timeout при запуске mysqld. См. раздел 4.2.3. Если у вас есть сценарий, вам достаточно просто повторить запрос, чтобы произошло автоматическое повторного подключение. Эта ошибка также появиться в случае, если кто-то прервал поток, обслуживающий соединение, с помощью оператора KILL или команды mysqladmin k i l l . Другая общая причина появления ошибки MySQL server has gone away во время выполнения клиентской программы состоит в том, что вы пытаетесь выполнить запрос после того, как закрыли соединение. Это свидетельствует о логической ошибке в программе, которую потребуется исправить. Вы можете проверить, не был ли сервер остановлен и перезапущен, выполнив команду mysqladmin version и проверив время работы сервера. Если клиентское соединение было прервано из-за того, что mysqld был прерван по ошибке и перезапущен, вам нужно сосредоточиться на поиске причины останова mysqld. Начните с проверки того, не приводит ли ваш запрос к аварийному останову сервера. См. раздел А.4.2. Эту ошибку можно также получить, прислав серверу неправильный или слишком большой запрос. Если mysqld получает пакет, который слишком велик, или приходит не в том порядке, он предполагает, что что-то идет неправильно и разрывает соединение. Если вам нужно выполнять большие запросы (например, если вы работаете со столбцами типа BLOB), можете увеличить предел запроса, установив новое значение серверной переменной maxallowedpacket, которое по умолчанию составляет 1 Мбайт. Возможно, вам придется также увеличить максимальный размер пакета на клиентской стороне. Дополнительную информацию по установке размера пакета можно найти в разделе А.2.9. Вы также получите разрыв подключения, если пошлете пакет размером в 16 Мбайт или больше, если версия вашего клиента - ниже 4.0.8, а версия сервера - 4.0.8 или выше. Если вы хотите составить отчет об ошибке, связанной с этой проблемой, не забудьте включить в него следующую информацию: • Укажите, прервалась ли работа сервера MySQL. Информацию об этом можно найти в журнале ошибок сервера. См. раздел А.4.2. • Если определенный запрос приводит к аварийному завершению mysqld и удалению таблиц, которые проверялись непосредственно перед запросом с помощью оператора CHECK TABLE, можете ли вы предоставить воспроизводимый тестовый случай? • Каково значение системной переменной wait_timeout? (Эту информацию выдаст команда mysqladmin variables.) • Пытались ли вы запускать mysqld с опцией —log, чтобы проверить, не появляется ли проблемный запрос в журнале? См. раздел 1.7.1.2.
А.2.9. Слишком большой пакет Коммуникационный пакет - это отдельный SQL-оператор, отправленный серверу MySQL, или отдельная строка, отправленная клиенту. В MySQL 3.23 максимальный размер пакеты составлял 16 Мбайт, из-за ограничений, накладываемых клиент-серверным протоколом. Начиная с MySQL 4.0.1, этот предел составляет 1 Гбайт.
596
Приложение А. Поиск и устранение неполадок в программах MySQL
Когда клиент MySQL или сервер mysqld получает пакет размером больше, чем max_allowedj?acket байт, он выдает ошибку Packet too large (Слишком большой пакет) и закрывает соединение. В некоторых клиентах в этом случае вы также можете получить сообщение об ошибке Lost connection to MySQL server during query (Потеря соединения с сервером MySQL во время выполнения запроса). И клиент, и сервер имеют свою собственную переменную max_allowed_packet, поэтому если вы хотите работать с большими пакетами, то должны увеличить ее значение как на клиенте, так и на сервере. Если вы применяете клиентскую программу mysql, в ней по умолчанию max_allowed_packet равно 16 Мбайт. Это также максимальное значение этой переменной, которое допускалось в версиях MySQL до 4.0. Чтобы установить большее значение в версии 4.0 и выше, запускайте mysql следующим образом: mysql> mysql —max_allowed_packet=32M Это установит максимальный размер пакета в 32 Мбайт. Значение по умолчанию max_allowed_packet для сервера равно 1 Мбайт. Вы можете увеличить его, если серверу необходимо работать с большими запросами (например, если вы работаете со столбцами BLOB). Например, чтобы установить значение переменной для сервера в 16 Мбайт, запускайте сервер так: mysql> mysqld —max_allowedjpacket=16M До версии MySQL 4.0 синтаксис был иной: mysql> mysqld —set-variable=max_allowedjpacket=16M Для установки значения max_allowed_packet можно также использовать файл опций. Например, чтобы установить это значение в 16 Мбайт, добавьте в файл опций следующие строки: [mysqld] max_allowed_packet=16M До MySQL версии 4.0 синтаксис выглядел по-другому: [mysqld] set-variable = max_allowed_packet=16M Увеличивать значение этой переменной вполне безопасно, потому что дополнительная память выделяется только по необходимости. Например, mysqld выделяет дополнительную память, только когда получает длинный запрос, или когда должен вернуть большую строку результата. Небольшое значение по умолчанию для этой переменной простая предосторожность, предусмотренная, чтобы перехватывать некорректные пакеты между клиентом и сервером, а также гарантировать, что не будет превышен размер доступной памяти, если неожиданно будет переслан большой пакет. Вы можете также столкнуться со странными проблемами больших пакетов, если используете большие значения BLOB, но не предоставляете mysqld памяти достаточного объема для обработки этих запросов. Если вы предполагаете, что причина в этом, попробуйте добавить ulimit -d 256000 в начало сценария mysqld_safe и перезапустите сервер.
А.2. Наиболее общие ошибки при работе с программами MySQL
597
А.2.10. Ошибки связи и прерванные соединения Журнал ошибок сервера - это полезный источник информации о проблемах подключений (см. раздел 4.8.1). Начиная с версии MySQL 3.23.40, если вы запускаете сервер с опцией —warnings (или —log-warnings, начиная с MySQL 4.0.3), то вы можете найти в журнале ошибок следующие сообщения: 010301 14:38:23 Aborted connection 854 to db: 'users' user: 'josh' Если сообщение Aborted connection (Прерванное соединение) появляется в журнале ошибок, причиной может быть одна из следующих: • Клиентская программа не вызвала mysql_close () перед завершением. • Клиент находился в неактивном состоянии дольше, чем wait_timeout или interactive_timeout секунд, не передавая никаких запросов к серверу. См. раздел 4.2.3. • Клиентская программа прервалась внезапно, во время передачи данных. Когда любое из этих событий происходит, сервер увеличивает значение переменной состояния Aborted_clients. Сервер увеличивает значение переменной Aborted_clients также в следующих случаях: • У клиента нет прав подключения к базе данных. • Клиент указал неверный пароль. • Коммуникационный пакет содержит неверную информацию. • Получение пакета заняло больше, чем connect_timeout секунд времени. См. раздел 4.2.3. Если происходит что-то из упомянутого выше, возможно, кто-то пытается взломать ваш сервер! Ниже представлены другие причины проблем, связанных с прерванными клиентами и прерванными соединениями: • Используется Ethernet-протокол в Linux, как полудуплексный, так и полнодуплексный. Многие драйверы Ethernet в Linux содержат эту ошибку. Вы можете протестировать эту ошибку, пересылая огромный файл по FTP между клиентской и серверной машинами. Если передача идет в режиме "рывок-пауза-рывок-пауза", значит, вы столкнулись с синдромом дуплекса Linux. Единственным решением будет переключение режима обеих сетевых плат, а также сетевых концентраторов/коммутаторов в полнодуплексный режим, либо в полудуплексный, с последующим тестированием результата, чтобы найти наилучшие установки. • Возникла какая-то проблема с библиотекой поддержки потоков, которая является причиной прерывания чтения. • Неудачно настроен протокол TCP/IP. • Повреждены сетевые платы, концентраторы, коммутаторы, кабели или тому подобное. Это можно проверить, только заменив сетевое оборудование. • Значение переменной max_allowed_packet слишком мало, либо запросы требуют больше памяти, чем отведено mysqld. См. раздел А.2.9.
598
Приложение А. Поиск и устранение неполадок в программах MySQL
А.2.11. Переполнение таблицы Существует несколько причин появления ошибки переполнения таблиц: • Вы работаете с сервером MySQL версии, более старой, чем 3.23 и временная таблица, размещенная в памяти, разрослась до более чем tmp__table_size байт. Чтобы избежать этой проблемы, можете указать опцию -0 tmp_table_size=#, чтобы заставить mysqld увеличить размер временной таблицы, или использовать SQLоператор SQL_BIG_TABLES перед отправкой проблематичного запроса. Вы также можете запускать mysqld с опцией —big-tables. Это абсолютно то же самое, что и применение SQL_BIG_TABLES для всех запросов. Начиная с MySQL 3.23, эта проблема возникать не должна. Если размещаемая в памяти временная таблица становится больше tmp_table_size байт, сервер автоматически преобразует ее в таблицу My ISAM, размещаемую на диске. • Вы применяете таблицы InnoDB и превысили объем места, отведенного в табличном пространстве InnoDB. См. раздел 9.8. • Вы используете таблицы ISAM или My ISAM под управлением операционной системы, которая поддерживает файлы размером не более 2 Гбайт, и достигли этого предела в каком-то из файлов индекса или данных. • Вы применяете таблицы My ISAM, и пространство, необходимое для хранения ее данных, превысило разрешенное размером внутреннего указателя. (Если вы не задаете опцию MAX_ROWS при создании таблицы, MySQL использует системную переменную myisam_data_pointer_size. Ее значения по умолчанию в 4 байта достаточно для работы с таблицами размером только в 4 Гбайт.) См. раздел 4.2.3. Максимально допустимый размер файла данных или индекса можно проверить с помощью следующего оператора: SHOW TABLE STATUS FROM database LIKE 'имя_таблицы'; Вы также можете использовать myisamchk -dv /путь/к/файлу-индекса-таблицы. Если размер указателя слишком мал, проблему можно решить с помощью ALTER TABLE: ALTER TABLE имя_таблицы MAX_ROWS=1000000000 AVG_ROW Вы должны указывать AVGROWLENGTH только для таблиц со столбцами типа TEXT или BLOB. В этом случае MySQL не может оптимизировать необходимое пространство, основываясь только на количестве строк.
А.2.12. Невозможно создать/записать файл Если при выполнении некоторых запросов вы сталкиваетесь со следующим типом ошибки, это означает, что MySQL не может создать временный файл для размещения результирующего набора во временном каталоге: Can't create/write to file !\\sqla3fe_0.ism'. Это сообщение об ошибке типично для Windows, сообщение в Unix выглядит похоже. Для исправления запустите mysqld с опцией —tmpdir, или добавьте эту опцию в раздел [mysqld] файла опций. Например, для указания каталога C:\temp используются следующие строки:
А.2. Наиболее общие ошибки при работе с программами MySQL
599
[mysqld] tmpdir=C:/temp Каталог С: /temp должен уже существовать. См. раздел 3.3.2. Проверяйте также код получаемой ошибки с помощью perror. Одной из причин, по которой сервер не может записывать в таблицу, может быть переполнение файловой системы: shell> perror 28 Error code 28: No space left on device
A.2.13. Команды не синхронизированы Если вы получаете сообщение об ошибке Commands out of sync; you can't run t h i s command now (Команды не синхронизированы; вы не можете выполнить эту команду сейчас) в клиентском коде, это означает, что клиентские функции вызывались в неверном порядке. Это может случиться, например, если вы используете mysql_use_result () и пытаетесь выполнить новый запрос до вызова mysql_free_result (). Это также может произойти, если вы пытаетесь выполнить два запроса, возвращающие данные, без вызова между ними mysql_use_result () или mysql_store_result ().
А.2.14. Игнорируется пользователь Если вы получаете следующую ошибку, это означает, что когда mysqld запускается или перезагружает таблицы привилегий, он находит в таблице user пользовательскую учетную запись с неверным паролем: Found wrong password for user: 'some_user'@'some_hostf; ignoring user В следующем списке перечислены возможные причины и способы решения этой проблемы: • Возможно, вы запустили новую версию mysqld со старой таблицей user. Это можно проверить, выполнив команду mysqlshow mysql user и проверив длину столбца Password; она должны быть не меньше 16 символов. Если она короче, нужно это исправить, запустив сценарий scripts/add_long_password. • Учетная запись имеет старый пароль (длиной до 8 символов), a mysqld был запущен без опции --old-protocol. Обновите пользовательскую учетную запись в таблице user, присвоив ей новый пароль, или перезапустите mysqld с опцией —old-protocol. • Вы указали пароль в таблице user, не применяя функцию PASSWORD (). Используйте mysql для обновления пароля учетной записи в таблице user, не забыв применить функцию PASSWORD (): x
х
mysql> UPDATE user SET Password=PASSWORD( новый_пароль ) -> WHERE User='пользователь* AND Host='хост 1 ;
A.2.15. Таблица ' имя таблицы не существует Если вы получаете любую из приведенных ниже ошибок, обычно это означает, что таблица с указанным именем не существует в текущей базе данных:
600
Приложение А. Поиск и устранение неполадок в программах MySQL
Table 'имя^таблицы* doesn't exist Can't find f i l e : 'имя_таблицы} (errno: 2) В некоторых случаях это может означать, что таблица существует, но вы обращаетесь к ней некорректно: • Поскольку MySQL использует каталоги и файлы для хранения баз данных и таблиц, имена баз и таблиц чувствительны к регистру, если они располагаются в файловых системах с зависящими от регистра именами файлов. • Даже для файловых систем, в которых имена не зависят от регистра, таких как Windows, все ссылки на данную таблицу в пределах запроса должны указываться в одном регистре. Для проверки, какие таблицы содержатся в текущей базе данных, используйте SHOW TABLES.
А.2.16. Невозможно инициализировать набор символов При возникновении проблема с набором символов вы можете получить такое сообщение об ошибке: MySQL Connection Failed: Can't i n i t i a l i z e character set имя_набора Эта ошибка может возникать по следующим причинам: • Набор символов является многобайтным, а поддержка этого набора на клиенте отсутствует. В этом случае необходимо перекомпилировать клиенты, запустив configure с опцией —with-charзеЬ=имя_набора или —with-extra-charsets= имя_набора. См. раздел 2.3.2. Все стандартные программы MySQL компилируются с —with-extra-charsets= complex, что включает поддержку всех многобайтных символьных наборов. См. раздел 4.7.1. • Данный набор символов является простым, но не скомпилирован в mysqld, и файлы определения наборов символов не найдены там, где клиент ожидал их найти. В этом случае решить проблему можно одним из следующих способов: • Перекомпилировать клиент с поддержкой требуемого набора символов. См. раздел 2.3.2. • Указать клиенту каталог, в котором находятся файлы определения символьных наборов. Для большинства клиентов это можно сделать с помощью опции —character-set-dir.
А.2.17. Файл не найден Если вы получаете от MySQL сообщение ERROR ' . . . ' not found (errno: 23), Can't open f i l e : . . . (errno: 24), или любую другую ошибку с кодом errno 23 или errno 24, это означает, что MySQL не хватает файловых дескрипторов. Можно воспользоваться perror, чтобы получить описание ошибки по ее номеру:
shell> perror 23 File table overflow Переполнение таблицы файлов
А.З. Вопросы, связанные с установкой
601
shell> perror 24 Too many open f i l e s Слишком много открытых файлов
shell> perror 11 Resource temporarily unavailable Ресурс временно не доступен Проблема заключается в том, что mysqld пытается открыть слишком много файлов одновременно. Вы можете либо указать mysqld, чтобы он не открывал такого количества файлов сразу, либо увеличить количество доступных ему файловых дескрипторов. Чтобы указать mysqld, чтобы он не открывал одновременно так много файлов, можно уменьшить размер табличного кэша, для этого уменьшив значение системной переменной table_cache (ее значение по умолчанию равно 64). Уменьшение значения переменной max_connections также уменьшит количество открытых файлов (по умолчанию - 100). Для изменения количества доступных серверу файловых дескрипторов можно воспользоваться опцией —open-files-limit mysqld_safe, или же (начиная с MySQL 3.23.30) установить системную переменную open_files_limit. См. раздел 4.2.3. Самый простой способ установить эти значения - добавить их в файл опций. См. раздел 3.3.2. Если у вас старая версия mysqld, которая не поддерживают установку предельного числа открытых файлов, вы можете отредактировать сценарий mysqld_safe. В нем есть закомментированная строка ulimit -n 256. Вы можете удалить символ '#', сняв тем самым комментарий, и изменить число 256, указав необходимое число файловых дескрипторов, доступных mysqld. —open-files-limit и ulimit могут увеличить количество файловых дескрипторов, но только в пределах, установленных операционной системой. Существует также "жесткий" лимит, который можно превысить, только если вы запустите mysqld_safe или mysqld от имени пользователя root (только помните, что вам также нужно будет при запуске сервера указывать опцию —user, чтобы он не продолжал работать от имени root после своего запуска). Если вам понадобится увеличить лимит доступных каждому процессу файловых дескрипторов, установленный операционной системой, проконсультируйтесь с документацией по системе. ^
На заметку!
r
rl Если вы работаете с оболочкой t c s h , u l i m i t работать не будет! Эта оболочка также даст не|| корректный результат, если вы запросите текущие значения лимитов. В этом случае вам следует Ц запускать mysqld_saf e из sh.
А.З. Вопросы, связанные с установкой А.3.1. Проблемы компоновки клиентской библиотеки MySQL Во время компоновки прикладной программы с клиентской библиотекой MySQL вы можете получить ошибки неразрешенных ссылок для символов, начинающихся с mysql_, подобные приведенным ниже: /tmp/ccFKsdPa.o: In function N main f : /tmp/ccFKsdPa.o(.text+Oxb): undefined reference to 4 mysql_init f /tmp/ccFKsdPa.o(.text+0x31): undefined reference to 4 mysql_real_connect'
602
Приложение А. Поиск и устранение неполадок в программах MySQL
/tmp/ccFKsdPa.o (,t.ext+0x57) : undefined reference to N mysql_real_connect' /tmp/ccFKsdPa.o(.text+0x69): undefined reference to 4 mysql_error' /tmp/ccFKsdPa.o(.text+0x9a): undefined reference to 4 mysql_close' Решить эту проблему можно, добавив -Ькаталог -Imysqlclient в конец команды компоновки, где каталог представляет путь к каталогу, в котором находится клиентская библиотека. Чтобы определить правильное значение пути, попробуйте такую команду: shell> mysql_config —libs Вывод mysqi__config может включать другие библиотеки, которые также должны быть указаны в команде компоновки. Если вы получаете сообщения undefined reference, касающиеся функций uncompress или compress, добавьте в конец команды компоновки опцию -lz и попробуйте выдать ее заново. Если вы получаете сообщения undefined reference о функциях, которые должны присутствовать в вашей системе, таких как connect, просмотрите страницы руководства по функциям, чтобы найти, какие библиотеки должны быть включены во время компоновки. Вы можете получить ошибки undefined reference для функций, которые отсутствуют в вашей системе: mf_format.о(.text+0x201) : undefined reference to ч l x s t a t 1 Обычно это означает, что ваша клиентская библиотека MySQL была скомпилирована в системе, которая не на 100% совместима с вашей. В этом случае вам потребуется загрузить самый последний исходный дистрибутив MySQL и скомпилировать его самостоятельно. См. раздел 2.3. Вы можете получить ошибки неразрешенных ссылок во время выполнения, когда попытаетесь запустить программу MySQL. Если эти ошибки указывают на символы, начинающиеся с mysql_, или же сообщают о том, что не может быть найдена библиотека mysqlclient, это означает, что ваша система не может найти библиотеку общего использования libmysqlclient.so. Чтобы исправить это, нужно указать системе, где конкретно искать эту библиотеку. Воспользуйтесь любым из приведенных ниже методов, который наиболее точно соответствует ситуации в вашей системе: • Добавьте путь к каталогу, в котором находится libmysqlclient.so, в системную переменную LD_LIBRARY_PATH. • Добавьте путь к каталогу, в котором находится libmysqlclient.so, в системную переменную LD_LIBRARY. • Скопируйте libmysqlclient.so в один из каталогов, в которых система выполняет поиск, такой как /lib, и обновите информацию о разделяемых библиотеках, выполнив команду ldconf ig. Другой способ решения этой проблемы сводится к статической компоновке либо к удалению динамических библиотек перед началом компоновки вашего кода. Прежде чем использовать второй вариант, вы должны убедиться, что никакие другие программы не используют динамические библиотеки.
А.З. Вопросы, связанные с установкой
603
А.3.2. Как запускать MySQL от имени обычного пользователя Начиная с версий MySQL 4.0.17 и 4.1.2, в Windows можно запускать сервер в виде системной службы от имени обычной пользовательской учетной записи. (Более старые версии требовали наличия прав администратора. Это была ошибка, обнаруженная в MySQL 3.23.54.) В среде Unix MySQL-сервер mysqld может быть запущен любым пользователем. Однако, из соображений безопасности, вы должны избегать запуска сервера от имени пользователя Unix root. Для того чтобы запускать mysqld от обычного непривилегированного пользователя имя_пользователя, потребуется предпринять следующие действия: 1. Если сервер работает, остановите его (с помощью mysqladmin shutdown). 2. Измените каталоги и файлы базы данных таким образом, чтобы учетная запись имя_пользователя имела права чтения и записи в них (возможно, это придется сделать от имени root): shell> chown -R имя^пользователя /'путь/к/mysql/'каталог_данных Если этого не сделать, сервер не сможет получить доступ к базе данных и ее таблицам, если будет запущен от имени имя_пользователя. Если каталоги или файлы внутри каталога данных MySQL являются символическими ссылками, те же изменения потребуется выполнить по отношению к каталогам и файлам, на которые они указывают, chown -R может не следовать за символическими ссылками. 3. Запустите сервер от имени имя_пользователя. Если вы работаете в версии MySQL 3.22 или более поздней, альтернативой может быть запуск от имени root, но с опцией —изег=имя_пользователя. Сервер mysqld стартует, а затем, прежде чем принимать клиентские соединения, переключится на работу от имени имя_полъзователя. 4. Чтобы запустить сервер автоматически во время запуска системы от имени заданного пользователя, укажите имя пользователя, добавив опцию user в группу [mysqld] файла опций /etc/my.cnf или файла my.cnf в каталоге данных сервера. Например: [mysqld] мвет-имя_пользователя Если ваша Unix-машина сама по себе недостаточно защищена, вы должны назначить пароль учетной записи MySQL с именем root в таблицах привилегий. В противном случае любой пользователь, зарегистрированный в системе, сможет запускать клиентскую программу mysql с опцией —user=root и выполнять любые операции. (Присвоить пароли всем пользователям MySQL - в любом случае хорошая идея, но особенно это важно, если на хосте сервера зарегистрированы другие пользователи.) См. раздел 2.4.
А.3.3. Проблемы с правами доступа к файлам Если у вас возникли проблемы с правами доступа к файлам, вероятно, переменная окружения UMASK была установлена неправильно, когда стартовал сервер mysqld. Например, MySQL может выдавать следующее сообщение, когда вы пытаетесь создать новую таблицу:
604
Приложение А. Поиск и устранение неполадок в программах MySQL
ERROR: Can't find f i l e : 'путь/к/имя_файла.frm'
(Errcode: 13)
Значение UMASK по умолчанию равно 0660. Это можно изменить, запуская mysqld_safe следующим образом: shell> UMASK=384 # = 600 восьмеричное shell> export UMASK shell> mysqld_safe & По умолчанию MySQL создает базы данных и RAID-каталоги со значением прав доступа 0700. Подобное поведение можно изменить с помощью переменной UMASK_DIR. Если это сделать, новые каталоги создаются с правами, устанавливаемыми комбинацией переменных UMASK и UMASK_DIR. Например, если вы хотите предоставить групповой доступ ко всем новым каталогам, то можете поступить так: shell> UMASK_DIR=504 # = 770 восьмеричное shell> export UMASKJHR shell> mysqld__safe & В MySQL 3.23.25 и выше сервер предполагает, что значения UMASK и UMASK_DIR указаны в восьмеричной форме, если они начинаются с нуля. См. приложение Б.
А.4. Вопросы, касающиеся администрирования А.4.1. Как сбросить пароль для root Если вы не устанавливали пароль для root в MySQL, сервер вообще не будет запрашивать пароль при подключении от имени пользователя root. Однако настоятельно рекомендуется устанавливать пароли каждой пользовательской учетной записи (см. раздел 4.3.1). Если вы использовали пароль root ранее, но забыли его, можете установить новый пароль. Следующая процедура описывает этот процесс для среды Windows. Процедуру для Unix можно найти далее в настоящем разделе. Процедура для Windows. 1. Войдите в систему как Administrator (Администратор). 2. Остановите сервер MySQL, если он работает. Для сервера, запущенного как системная служба Windows, активизируйте диспетчер служб (Service manager): S t a r t s Control Panel^AdministratJve Tools^Services (Пуск^ Панель управления^ Администрирование •=> Службы). Затем найдите службу MySQL и остановите ее. Если сервер запущен не в виде системной службы, можно воспользоваться диспетчером задач, чтобы его остановить. 3. Откройте окно консоли: c c c c Start >Run t>cmd(Пycк >Bыпoлнить >cmd). 4. Предполагается, что MySQL установлен в каталоге С: \mysql. Если вы установили его в другой каталог, внесите соответствующие изменения. В командной строке DOS выполните команду: С:\> C:\mysql\bin\mysqld-nt --skip-grant-tables
А.4. Вопросы, касающиеся администрирования
605
Это запустит сервер в специальном режиме, который не проверяет таблицы привилегий для управления доступом. 5. Оставив первое окно консоли открытым, откройте второе окно консоли и выполните в нем следующие команды (вводя каждую в отдельной строке): С:\> C:\mysql\bin\mysqladmin -u root flush-privileges password "новый_пароль" С:\> C:\mysql\bin\mysqladmin -и root -р shutdown Замените 'новый_пароль* реальным паролем, который хотите использовать. Вторая команда выдаст приглашение на ввод нового пароля. Введите тот же пароль, который был указан в первой команде. 6. Остановите сервер MySQL, затем перезапустите его в нормальном режиме. Если вы запускаете сервер как системную службу, запустите его из окна Windows Services (Службы Windows). Если вы запускаете сервер вручную, используйте команды, с помощью которых обычно это делаете. 7. Теперь вы должны быть готовы подключаться с новым паролем. В среде Unix процедура переустановки пароля для root выглядит следующим образом: 1. Войдите в систему как пользователь root или же пользователь, от имени которого запускается сервер mysqld. 2. Найдите файл .pid, который содержит идентификатор процесса сервера. Точное местоположение и имя этого файла зависит от вашего дистрибутива, имени хоста и конфигурации. Обычно он находится в /var/lib/mysql/, /var/run/mysqld/ или /usr/local/mysql/data/. Как правило, расширением этого файла является .pid, a имя начинается либо с mysql, либо с имени вашего хоста. Теперь вы можете остановить сервер MySQL, послав сигнал командой k i l l (но не k i l l -9) процессу mysqld, используя путь файла .pid, в следующей команде: shell> k i l l "cat /каталог-данных-тузд1/имя_хоста. mysqld_safe —skip-grant-tables & 4. Установите новый пароль для учетной записи MySQL root@localhost: shell> mysqladmin -u root flush-privileges password " новый_пароль" Замените "новый_пароль " реальным паролем, который хотите использовать. 5. Остановите сервер MySQL, затем перезапустите его в нормальном режиме. 6. Теперь вы должны быть готовы подключаться с новым паролем. В качестве альтернативы на любой платформе вы можете установить новый пароль, с помощью клиентской программы mysql: 1. Остановите mysqld и перезапустите его с опцией —skip-grant-tables, как описано выше. 2. Подключитесь к серверу по команде: shell> mysql -u root
606
Приложение А. Поиск и устранение неполадок в программах MySQL
3. Выполните следующий оператор внутри клиента mysql: mysql> UPDATE mysql.user SET Password=PASSWORD ('новый_пароль') -> WHERE U s e r = ' r o o t ' ; mysql> FLUSH PRIVILEGES;
Замените 'новый_пароль реальным паролем, который хотите использовать. 4. Остановите сервер MySQL, затем перезапустите его в нормальном режиме. 5. Теперь вы должны быть готовы подключаться с новым паролем.
А.4.2. Что делать, если MySQL терпит крах Каждая версия MySQL перед выходом тестируется на множестве платформ. Это не гарантирует полного отсутствия ошибок, но если ошибки есть, то очень немного, и их довольно-таки трудно найти. Если вы столкнулись с проблемой, то всегда полезно разобраться, что именно привело вашу систему к краху, поскольку в этом случае вы имеете гораздо лучшие шансы быстро получить решение проблемы. Первое, что следует сделать - разобраться, завершается ли аварийно сервер mysqld, или проблема связана с клиентом. Вы можете проверить, насколько долго работает сервер mysqld, с помощью команды mysqladmin version. Если mysqld аварийно прекратил работу и был перезапущен, то имеет смысл поискать причину в журнале ошибок сервера (см. раздел 4.8.1). В некоторых системах в журнале ошибок можно найти трассировку стека на момент аварийного завершения mysqld и его можно проанализировать программой resolve_stack_dump. Имейте в виду, что значения переменных, зафиксированные в журнале ошибок, могут быть не на 100% верными. Многие случаи краха сервера вызваны повреждением файлов данных или индексных файлов. MySQL обновляет файлы на диске системным вызовом write () после каждого SQL-оператора и перед тем, как известить клиента о результате. (Это не так, если вы работаете с опцией —delay-key-write; в этом случае данные сразу записываются, а индексные файлы нет.) Это означает, что содержимое файлов данных будет в безопасности, даже если mysqld потерпит крах, потому что операционная система гарантирует, что все несброшенные данные будут записаны на диск. Вы можете заставить MySQL сбрасывать на диск данные после каждого SQL-оператора, запустив mysqld с опцией — flush. Исходя из вышесказанного, можно сделать вывод, что вы никогда не получите поврежденных таблиц, если только не случится что-то из следующего: • Сервер MySQL или хост сервера был прерван в процессе обновления данных. • Вы нашли ошибку в mysqld, которая приводит к его аварийному завершению в процессе обновления данных. • Некая внешняя программа манипулировала файлами данных или индексными файлами одновременно с mysqld, не устанавливая правильно блокировки таблиц. • Вы запустили несколько серверов mysqld, используя один и тот же каталог данных в системе, которая не поддерживает качетсвенных блокировок файловой системы (обычно управляемых диспетчером блокировок lockd), или же вы запустили несколько серверов mysqld с опцией —skip-external-locking.
А.4. Вопросы, касающиеся администрирования
607
•
У вас есть запорченный файл данных или индексный файл, который содержит поврежденные данные, которые сбивают с толку mysqld.
•
Вы нашли ошибку в коде сохранения данных. Такое маловероятно, но это последнее, что можно предположить. В этом случае вы можете попробовать изменить тип таблиц для использования другого механизма хранения, выполнив оператор ALTER TABLE на восстановленной копии таблицы.
Поскольку иногда очень трудно понять причину краха, прежде всего проверьте, есть ли вещи, которые работают у других, но приводят к краху вашу систему. Пожалуйста, попробуйте следующее: •
Остановите mysqld командой mysqladmin shutdown, запустите myisamchk —silent — force */* .MY I из каталога данных, чтобы проверить все таблицы My ISAM, и перезапустите mysqld. Это гарантирует, что вы начинаете из чистого состояния. См. главу 4.
•
Запустите mysqld с опцией --log и попробуйте среди информации, записанной в журнале, найти конкретный запрос, который приводит к аварии сервера. Около 95% всех ошибок связаны с конкретным запросом. Обычно это будет один из последних запросов в файле протокола - непосредственно перед перезапуском сервера. См. раздел 4.8.2. Если один и тот же запрос повторно прерывает работу сервера, даже если вы проверили все занятые в нем таблицы непосредственно перед его выполнением, вы сможете найти ошибку и составить отчет о ней. См. раздел 1.7.1.3.
•
Попытайтесь составить тестовый случай, которым мы сможем воспользоваться для воспроизведения проблемы.
•
Попробуйте запустить тесты из каталога mysql-test. Они достаточно хорошо тестируют функционирование MySQL. Вы можете добавить код в тесты производительности, который будет эмулировать ваше приложение. Тесты производительности можно найти в каталоге sql-bench исходного дистрибутива, или, для бинарного дистрибутива - в каталоге sql-bench вашей установки MySQL.
•
Попробуйте запустить сценарий fork_big.pl (он находится в каталоге t e s t s исходного дистрибутива).
•
Если вы настроили MySQL для отладки, будет гораздо легче собрать информацию о возможных ошибках, если что-то идет не так. Настройка MySQL для отладки включает безопасный распределитель памяти, который может найти некоторые ошибки. Это также приводит к генерации большого объема выходной информации о том, что происходит. Переконфигурируйте MySQL с помощью опций —with-debug или —with-debug=full сценария configure и затем перекомпилируйте MySQL.
•
Проверьте, установлены ли все последние исправления для операционной системы.
•
Используйте опцию —skip-external-locking с mysqld. В некоторых системах диспетчер блокировок lockd работает некорректно. Опция —skip-externallocking указывает mysqld не использовать внешнюю блокировку. (Это означает, что вы не можете запустить два и более экземпляра mysqld на одном и том же каталоге данных, и что нужно быть осторожным при использовании myisamchk. Несмотря на это, может быть поучительно попробовать эту опцию в качестве теста.)
608
Приложение А. Поиск и устранение неполадок в программах MySQL
•
Пробовали ли вы mysqladmin -u root processlist, когда случилось так, что mysqld работает, но не отвечает на запросы? Иногда mysqld вовсе не находится в "коматозном" состоянии, даже если вам может так показаться. Проблема может быть в том, что все соединения заняты, или могут возникнуть некоторые проблемы внутренних блокировок, mysqladmin -u root processlist обычно в СОСТОЯНИИ установить соединения даже в подобных случаях и предоставить полезную информацию о количестве текущих подключений и их состоянии.
• В отдельном окне запустите команду mysqladmin -i 5 status или mysqladmin -i 5 -r status, чтобы получить статистическую информацию, пока работают другие запросы. • Попробуйте предпринять следующие действия: 1. Запустите mysqld из gdb (или другого отладчика). 2. Запустите ваши тестовые сценарии. 3. Распечатайте трассировку вызовов и состояния локальных переменных на трех самых низких уровнях. В gdb это можно сделать с помощью приведенных ниже команд, когда mysqld потерпит крах внутри gdb: backtrace info local up info local up info local С помощью gdb можно также проверить, какие существуют потоки, командой info threads и переключиться на конкретный поток посредством команды thread #, где # - идентификатор потока. • Попытайтесь смоделировать приложение с помощью Perl-сценария, чтобы привести mysqld к краху или неправильному поведению. • Пришлите нормальный отчет об ошибке (см. раздел 1.7.1.3). Опишите ситуацию даже более детально, нежели обычно. Поскольку MySQL работает у многих пользователей, причиной краха может быть нечто такое, что есть только на вашем компьютере (например, ошибка, связанная с вашими специфическими системными библиотеками). • Если вы имеете проблемы с таблицами, содержащими строки динамической длины, и пользуетесь только столбцами VARCHAR (не BLOB и не TEXT), то можете попробовать сменить тип этих столбцов с VARCHAR на CHAR с помощью оператора ALTER TABLE. Это заставит MySQL использовать строки фиксированной длины. Такие строки занимают немного больше места, но гораздо более устойчивы к повреждениям. Используемый в настоящее время код, работающий с динамическими строками, применяется компанией MySQL AB в течение нескольких лет с очень небольшим количеством проблем, однако строки динамической длины по своей природе в большей степени подвержены ошибкам, поэтому имеет смысл попробовать такую стратегию и посмотреть, поможет ли это.
А.4. Вопросы, касающиеся администрирования
609
А.4.3. Как MySQL обрабатывает переполнение диска Когда случается переполнение диска, MySQL работает так: •
Проверяет ежеминутно, не появилось ли свободное пространство, чтобы записать текущую строку; если место появляется, продолжает работу так, будто ничего не случилось.
•
Каждые шесть минут записывает в файл протокола сообщение о переполнении диска.
Чтобы облегчить последствия проблемы, вы можете предпринять следующие шаги: • Для продолжения работы потребуется только освободить достаточное пространство на диске, чтобы вставить все строки. •
Чтобы прервать исполнение потока, необходимо использовать mysqladmin k i l l . Поток будет остановлен в тот момент, когда следующий раз проверит наличие места на диске (в пределах одной минуты).
•
Остальные потоки могут пребывать в состоянии ожидания таблицы, которая привела к переполнению диска. Если у вас несколько "заблокированных" потоков, прерывание одного из них, который ожидает освобождения места на диске, может позволить остальным продолжить работу.
Исключениями из описанного могут быть случаи, когда вы применяете REPAIR TABLE или OPTIMIZE TABLE, или когда индексы создаются в пакетном режиме после выполнения операторов LOAD DATA INFILE или ALTER TABLE. Все эти операторы могут создавать огромные временные файлы, и если их предоставить самим себе, то они могут стать причиной крупных проблем для всей остальной системы. Если диск переполняется в то время, когда MySQL выполняет одну их этих операций, он удалит временный файл и пометит таблицу как поврежденную. Исключением является только оператор ALTER TABLE, который оставит старую таблицу без изменений.
А.4.4. Где MySQL хранит временные файлы MySQL читает значение переменной окружения TMPDIR и трактует его как путь к каталогу, в котором следует создавать временные файлы. Если переменная TMPDIR не установлена, MySQL использует каталоги по умолчанию операционной системы. Обычно это /tmp, /var/tmp или /usr/tmp. Если каталог ваших временных файлов слишком мал, вы можете воспользоваться опцией mysqld — tmpdir, чтобы указать каталог в вашей файловой системе с достаточным свободным местом. Начиная с MySQL 4.1, эта опция может включать в себя список нескольких путей, используемых в циклическом порядке. Пути должны разделяться символом " : " в Unix или " ; " в Windows, NetWare или OS/2. S На заметку! Ji Q
Чтобы разделить эффективно нагрузку, эти пути должны указывать на каталоги, расположенные на разных физических дисках, а не в разделах одного и того же диска.
Если сервер MySQL функционирует в качестве подчиненного в системе репликации, вы не должны устанавливать опцию --tmpdir так, чтобы она указывала на каталог файловой системы, находящейся в памяти, либо на каталог, который автоматически очищается при перезапуске компьютера. Подчиненный сервер репликации нуждается во вре-
610
Приложение А. Поиск и устранение неполадок в программах MySQL
менных файлах для обслуживания перезапуска таким образом, чтобы иметь возможность реплицировать временные таблицы или операции LOAD DATA INFILE. Если содержимое каталога временных файлов будет потеряно при перезапуске сервера, репликация перестанет работать. Все временные файлы MySQL создает как скрытые. Это гарантирует, что они будут удалены, если работу mysqld будет прервана. Неудобство в применении скрытых файлов заключается в том, что вы не увидите большого временного файла, который переполнит файловую систему в каталоге, в котором он расположен. При выполнении сортировок (ORDER BY или GROUP BY) MySQL обычно использует один или два временных файла. Максимально необходимый объем дискового пространства в этом случае вычисляется по следующему выражению: (длина сортируемых строк + sizeof{указатель на строку)) * количество совпадающих строк *2 Размер указателя на строку обычно составляет 4 байта, но в будущем может вырасти для работы с очень большими таблицами. Для некоторых операторов SELECT MySQL также создает временные таблицы. Они не скрыты и получают имена SQL_*. ALTER TABLE создает временную таблицу в том же каталоге, где находится исходная таблица.
А.4.5. Как защитить или изменить файл сокета MySQL /tmp/mysql.sock По умолчанию файл сокета Unix, который используется сервером при взаимодействии с локальными клиентами, расположен в /tmp/mysql.sock. Это может стать причиной проблем, поскольку в некоторых версиях Unix удалять файлы из каталога tmp разрешено всем. В большинстве версий Unix, однако, удалить временный файл в каталоге /tmp может только тот, кто его создал, либо пользователь root. Чтобы включить это, установите бит sticky для каталога /tmp, войдя в систему как root и выдав следующую команду: shell> chmod +t /tmp Вы можете проверить, установлен ли этот бит, с помощью команды Is -Id /tmp. Если последним символом в правах доступа является t, значит бит установлен. Другой подход предполагает изменение каталога, в котором сервер создает файл Unix-сокета. Если вы сделаете это, то должны будет известить об этом все клиентские программы. Местоположение этого файла можно указать разными способами: • Указать путь в глобальном или локальном конфигурационном файле. Например, поместите в /etc/my.cnf следующие строки: [mysqld] socket=/path/to/socket [client] socket=/path/to/socket • Указывайте опцию —socket в командной строке mysqldsaf e, а также при запуске клиентских программ.
А.4. Вопросы, касающиеся администрирования
611
• Установите в переменной окружения MYSQL_UNIX_PORT путь к файлу Unix-сокета. • Перекомпилируйте MySQL из исходных текстов, чтобы использовать другое местоположение файла сокета по умолчанию. Определите путь в опции —withunix-socket-path во время запуска сценария configure. См. раздел 2.3.2. Чтобы проверить, работает ли файл сокета в новом месте, попытайтесь подключиться к серверу с использованием команды: shell> mysqladmin —soctet=/путь/к/фаРшу_сокетa
version
А.4.6. Проблемы с временными зонами Если у вас возникла проблема с SELECT NOW (), возвращающим время GMT, а не ваше локальное время, вам следует известить сервер о конкретной временной зоне. То же самое касается случая, когда UNIX_TIMESTAMP() возвращает неверное значение. Это должно быть сделано в окружении, в котором запущен сервер, например, в mysqldsafe или mysql. server. См. приложение Б. Установить временную зону для сервера можно с помощью опции —timezone= имя_временной_зоны сценария mysqldsafe. Также ее можно задать в переменной окружения TZ перед запуском mysqld. Допустимые значения опции и переменной окружения зависят от системы. Проконсультируйтесь с документацией по операционной системе, чтобы узнать, какие значения допускаются.
Б Переменные окружения
В
настоящем приложении перечислены переменные окружения, которые явно или неявно используются MySQL. Большинство из них упоминается в других разделах настоящего руководства. Следует отметить, что любые опции командной строки всегда имеют преимущество перед значениями, указанными в переменных окружения. Опции, заданные в конфигурационных файлах, также имеют преимущество перед значениями этих переменных. Во многих случаях для изменения поведения MySQL предпочтительнее использовать файлы опций вместо переменных окружения. См. раздел 3.3.2. Таблица Б.1. Переменные окружения Переменная
Описание
схх ее
Имя компилятора C++ (для запуска configure).
CFLAGS
Флаги компилятора С (для запуска configure).
CXXFLAGS
Флаги компилятора C++ (для запуска configure).
DBIJJSER
Имя пользователя по умолчанию для Perl DBI.
Имя компилятора С (для запуска configure).
DBI_TRACE
Опции трассировки для Perl DBI.
НОМЕ
Путь по умолчанию к файлу хронологии mysql указывается как $НОМЕ/.mysql_history. Используется для указания местоположения библиотеки libmysqlclient.so.
LD_RUN_PATH MYSQL_DEBUG MYSQLJilSTFILE MYSQL_HOST MYSQL PS1
Опции трассировки во время отладки. Путь к файлу хронологии mysql; переназначает путь по умолчанию $НОМЕ/.mysql_history. Имя хоста по умолчанию, используемое клиентской программой командной строки mysql. Приглашение командной строки в клиентской программе mysql.
613
Приложение Б. Переменные окружения
Окончание табл. Б. 1
Переменная
Описание
MYSQL_ PWD
Пароль по умрлчанию для подключения к серверу raysqld. Имейте в виду, что его использование небезопасно! См. раздел 4.5.6.
MYSQL_ TCP_PORT
Значение по умолчанию номера порта TCP/IP.
MYSQL_UNIX_PORT
Значение по умолчанию имени файла сокета Unix; используется для подключения локальных клиентов.
PATH
Используется оболочкой для поиска программ MySQL.
TMPDIR
Каталог временных файлов.
TZ
Наименование локальной временной зоны. См. А.4.6.
UMASK_ DIR
Маска прав доступа к пользовательским каталогам; используется при их создании.
UMASK
Маска прав доступа к пользовательским файлам.
USER
Имя пользователя по умолчанию в Windows и NetWare? применяемое для подключения к серверу raysqld.
Предметный указатель API-интерфейс, 19; 20; 31; 68; 158; 163; 165; 268; 536; 537 G GnuPG, 90-92 GPL, См. Лицензия GNU General Public License, 18; 29; 32-34; 36; 39; 56; 141; 506; 524;582 innodb_additional_mem_pool_size, 236; 527; 529; 530 innodb_buffer_pool_awe memmb, 530 innodb_buffer_pool_size, 236; 527; 529; 530 innodb_data_file_path, 215; 236; 500; 525-528; 531; 535; 546; 572 innodb_data_home_dir, 236; 525-528; 531; 535;546;572 innodbfastshutdown, 236; 531 innodb_file_per_table, 531; 544 innodbfiletothreads, 531 innodb_flush_log_at_trx_cornrnit, 236; 527; 529; 531; 561 innodb_flush_method, 236; 529; 532; 561 innodb_force_recovery, 236; 532; 549 innodb_lock_wait_timeout, 236; 529; 532; 559 innodb_log_arch_dir, 236; 529; 532; 533 innodblogarchive, 236; 532 innodb_log_buffer_size, 236; 527; 529; 532 innodbjog_file_size, 236; 527; 529; 533 innodblogfilesingroup, 236; 529; 533 innodb_log_group_home_dir, 236; 529; 532; 533 innodb_max_dirty_pages_pct, 533 innodbmirroredloggroups, 236; 533 innodbopenfiles, 533 innodbthreadconcurrency, 236; 529; 533; 567
s
SMP, См. Симметричная многопроцессорная система, 78; 170; 172; 175; 177 -temp-pool, 161; 230
Атомарная операция, 62
Б Библиотека readline,32; 104; 107; 132; 190; 191; 467 regexp, 32; 45; 493
В Взаимная блокировка, 47; 70; 388; 432; 532; 557-560
Д
Двойная лицензия, 15
ж Журнал бинарный, 345; 348 запросов, 345 медленных запросов, 345; 351 обновлений, 226; 345; 347 ошибок, 100; 101; 103; 148; 345; 346; 597 таблиц ISAM, 345
К Ключ внешний, 29; 37; 38; 43; 65; 66; 68; 100; 539; 541; 542; 562 Код ошибки 1005 (ER_CANT_CREATE_TABLE), 574 1016 (ER_CANT_OPEN_FILE), 574 1114 (ER_RECORD_FILE_FULL), 574 1205 (ER_LOCK_WAIT_TIMEOUT), 574 1213 (ER_LOCK_DEADLOCK), 574 1216 (ER_NO_REFERENCED_ROW), 574 1217 (ER_ROW_IS_REFERENCED), 574 Компания MySQL AB http://www.mysql.com, 15 коммерческая лицензия, 29; 30 поддержка, 21; 24; 28; 31; 40 сертификация, 28 Компилятор аСС,87;88; 188 СС,88 сс/схх, 89 сс-5.0, 86 ссс, 85; 177 есс, 85 egcs,89; 118; 122; 178; 179; 183; 189; 190
Предметный указатель gcc, 85-90; 118; 122; 123; 127-131; 173; 176-190; 192-196; 199; 200;451 pgcc,82; 122; 451; 452 xlC_r,87; 188 Конструкция CHANGE имястолбца, 59 DELAYED, 46; 59; 63; 71; 164; 172; 224; 241; 246; 262; 425; 429; 434; 489; 578 DROP INDEX, 59; 165; 559; 585 DROP имястолбца, 59 IF EXISTS, 17; 25; 59 IGNORE, 44; 58; 59; 68; 72; 162; 232; 233; 411; 444; 445; 468; 549; 574; 586 LIMIT, 39; 46; 47; 59; 158; 380; 418; 420; 423; 424; 434; 440; 476; 477; 586 LOW_PRIORITY, 59; 161; 227; 429; 434 ORDER BY, 21; 46; 59; 72-74; 162; 165; 166; 250; 251; 263; 327; 340; 412; 417419; 421-423; 427; 439; 440; 451; 610 SQL_SMALL_RESULT, 59; 417 WHERE, 20; 21; 58; 61; 64; 66; 70; 74; 75; 151; 152; 157; 247; 267; 269; 307; 309; 347; 348; 362; 409-413; 416-422; 424; 427; 428; 432; 437-440; 476; 491; 512; 537; 554; 555; 557; 558; 586; 592; 593; 599; 606 Контрольная сумма MD5, 61; 90; 91; 93; 266; 301; 427 Курсор, 42
л Лицензия GNU General Public License, 15; 18; 32; 582
M Механизм хранения BDB, 23; 62; 71; 98; 126; 147-149; 155; 214; 215; 223; 228; 238; 239; 242; 252; 350; 396; 411; 430; 432-434; 498; 499; 515521 HEAP, 40; 70; 73; 246; 382; 417; 422; 429; 430; 437; 438; 453; 491; 498; 513 InnoDB, 23; 24; 29; 37; 38; 43; 62; 64; 65; 68; 72; 97; 98; 100; 103; 120; 126; 147; 156; 161; 214; 215; 223; 229; 238; 242; 243; 252; 318; 319; 350; 361; 375; 380; 381; 396; 430; 432; 433; 434; 437; 451; 490; 498;500; 518; 523-564; 567-574; 577581;598 MEMORY, 42; 246; 358; 382; 430; 437; 438; 440; 469; 479; 481; 486; 490; 494; 496; 498; 499; 513-515; 567; 576
615 MERGE, 25; 42; 72; 75; 105; 361; 381; 498; 509; 510-512; 521; 549 MylSAM, 20; 22-25; 37; 38; 40; 42; 45; 46; 59; 62; 64; 65; 68; 72; 153; 159; 160; 161; 163-165; 168; 213; 215; 218; 223-227; 229; 230; 239-241; 243; 247; 248; 250; 252; 318-322; 324; 326; 329; 330; 333338; 345; 366; 374; 375; 381; 383; 394; 396; 403; 404; 411; 416; 417; 425^31; 434; 436; 437; 440; 441; 446; 447; 453455; 457; 458; 460; 461; 463; 465; 485; 489; 491; 492; 498-505; 507-512; 517519; 521; 523; 530; 537; 543-545; 550; 577-579; 598; 607 Монитор InnoDB, 563; 579
H Недействительный результат чтения, 63
о Оболочка bash, 112; 185; 186; 203; 210; 389 Bourne, 17; 210 sh, 16; 126; 145; 146; 185; 186; 191; 203; 210; 601 tcsh, 17; 112; 203; 210; 601 zsh,210 Оператор ALTER TABLE, 24; 45; 46; 59; 71; 75; 105; 156; 159; 163-165; 246; 248; 279; 324; 331; 361; 414; 426; 427; 457; 458; 489; 499; 501; 504; 510-512; 521; 537; 539541; 543; 545; 549; 559; 573; 578; 581; 598;607-610 ANALYZE TABLE, 59; 71; 72; 321; 324; 381; 408; 411; 415; 416; 424; 485; 512; 519; 522;587 CHECK TABLE, 55; 59; 113; 164; 165; 229; 321; 322; 330; 333; 485; 507; 508; 522; 548; 580; 585; 595 CREATE DATABASE, 59; 389; 390; 490; 585 CREATE TABLE, 24; 25; 40; 45; 53; 59; 61; 65; 71; 105; 155; 156; 230; 233; 240; 246; 247; 279; 280; 331; 381; 425; 437; 458; 487; 488; 490; 491; 495; 498-500; 502; 509; 513; 514; 518; 535; 536; 539-542; 558; 559; 563; 578; 580; 581 AVG_ROW_LENGTH, 24; 96; 331; 598 MAX_ROWS, 24; 96; 246; 247; 331; 514; 598 DROP DATABASE, 59; 105; 162; 164; 267; 361; 389; 390; 559; 569; 580 EXPLAIN, 21; 52; 53; 59; 408; 409; 411; 413416; 418-420; 422-424; 427; 560; 585
616 EXPLAIN SELECT, 52; 53; 59; 408; 413; 423; 560 FLUSH, 53; 59; 71; 75; 105; 151; 152; 229; 246; 252; 262; 269; 271; 277; 289; 294; 304; 306-309; 318; 320; 322; 345-348; 352; 364; 371; 374; 375; 379; 381; 393395; 425; 426; 447; 454; 455; 492; 493; 508; 510; 512; 519; 592; 593; 606 GRANT, 139; 140; 152; 160; 165; 221; 228; 266; 270; 271; 273; 277-280; 282; 283; 286; 288; 289; 292; 296; 298-300; 302310; 317; 374; 381; 407 LOAD DATA INFILE, 44; 47; 59; 72; 105; 106; 224; 231; 239; 244; 248; 253; 273; 279; 294; 319; 320; 373; 384; 391; 425; 426; 429; 461; 468; 481-483; 489; 493; 494; 514; 609; 610 LOCK TABLES, 63; 64; 243; 278; 280; 318; 426; 432-434; 448; 491; 492; 508; 519; 532;558-560; 579 OPTIMIZE TABLE, 59; 71; 72; 164; 321; 324; 333; 334; 381; 427; 429; 485; 505; 506; 512; 519; 522; 609 RENAME DATABASE, 43 RENAME TABLE', 42; 59; 512; 542; 545; 559 REPAIR TABLE, 55; 59; 71; 72; 113; 157; 162; 163; 229; 241; 242; 248; 319; 321; 324; 330; 333; 381; 457; 485; 507; 508; 512; 522; 609 REPLACE, 21; 44; 59; 70; 72; 227; 320; 404; 512; 558; 565;566; 587 RESET, 17; 59; 349; 364; 385; 398; 399 SHOW INDEX, 162; 411; 416 SHOW MASTER STATUS, 161; 280; 375; 376; 379; 393; 395; 399; 401 SHOW OPEN TABLES, 162 SHOW SLAVE STATUS, 162; 280; 369; 372; 391; 394; 399; 401 UNLOCK TABLES, 63; 320; 375; 393; 395; 426; 432; 448; 559; 560 Операционная система AIX, 77; 86;87;90;188-190; 214; 516 Amiga, 77 BSDI,77;90; 185; 186 FreeBSD, 77; 88; 89; 130; 131; 145; 183; 184; 248; 516 HP-UX, 77; 87; 187; 188; 214 Linux, 24; 77; 78; 81; 85; 86; 89; 91; 92; 94; 107; 109; 122; 127; 131; 133; 135; 138; 145; 161; 170-174; 176-178; 184; 197; 199; 213; 214; 216; 218; 225; 228; 230; 268; 290; 293; 351; 360; 405; 448; 451; 452; 456; 457; 483; 516; 528; 529; 532; 561; 575; 591; 594; 597
Предметный указатель Mac OS, 77; 81; 88; 109-111; 114; 117; 138; 144; 179; 214; 218; 245;516 NetBSD,77;185 Novell NetWare, 77; 112 OpenBSD, 77; 185 OS/2 Warp, 77; 196 SCO OpenServer, 77; 194; 516 SCO UnixWare, 78; 196; 516 SGI Irix, 78; 89; 193 Solaris, 24; 77; 78; 86; 127; 130-132; 179183; 214; 218; 224; 227; 252; 448; 452; 454; 457; 516; 594 SunOS, 78; 89; 131; 190 Tru64Unix,78 UNIX, 16; 21; 22; 38; 77; 141; 144; 194; 358; 359; 361; 384; 461; 611; 613 Windows, 15; 16; 21; 22; 38; 49; 51; 52; 55; 56; 78; 91; 93;95-99; 101-107; 133-138; 144; 148-154; 156; 159; 167; 168; 197; 198; 203; 206; 208-210; 213; 214;224; 225; 229; 230; 241; 245; 248; 251; 253; 272; 281; 282; 290; 293; 302; 311; 318; 327; 346; 347; 352-355; 357; 359; 374; 423; 431; 457; 459; 473; 483; 490; 512; 524; 525; 527; 528; 530; 531; 534; 550; 561; 563; 572; 576; 577; 579; 583; 590; 591; 598; 600; 603-605; 609; 613 Опция -analyze, 327; 333; 411; 416; 485; 502 ~ansi,57;223;238 AVG_ROW_LENGTH, 24; 96; 331; 598 -backup, 325; 462 -basedir, 216; 224; 354 -big-tables, 224; 453; 598 —bind-address, 224 bulk_insert_buffer_size, 161; 235; 239; 257; 425; 503 -character-sets-dir, 224; 325; 341; 345; 468; 479; 485; 496 -character-sets-dir, 224; 325; 468; 479; 485; 496 -check, 93; 325; 485; 486; 493 —check-only-changed, 325; 486 -chroot, 224 -config-file, 220 -console, 100; 101; 224; 346; 527; 534; 563; 579 -core-file, 176; 216; 224 —core-file-size, 216 —correct-checksum, 325 -datadir,216;224;353;358 -data-file-length, 325 -debug, 101; 136; 149; 224; 295; 323; 462; 468; 479; 486; 489; 493; 494; 496
Предметный указатель -default-character-set, 224; 340; 380; 468; 486; 489; 496 -default-collation, 224; 340 -defaults-extra-file, 207; 209; 216 -defaults-file, 209; 216; 359 -default-storage-engine, 224 -default-table-type, 224; 252 -delay-key-write, 224; 225; 229; 395; 502; 503; 606 -delay-key-write-for-all-tables, 225 -description, 327; 416 -des-key-file, 225 -enable-locking, 161; 225 -enable-named-pipe, 225; 590 -err-log, 216 -example, 220 -exit-info, 225 -extend-check, 323; 325 -external-locking, 132; 161; 225; 241; 503 -fast, 322; 325; 334; 486; 502 -flush, 225; 241; 489; 493; 606 -force, 171; 322; 325; 326; 462; 468; 479; 481; 486; 489; 494; 607 -help, 16; 22; 101; 119; 121; 136; 140; 141; 147; 168; 203; 204; 207; 212; 220; 223; 277; 321-323; 406; 450; 451; 461; 462; 468; 479; 481; 483; 485; 487; 488; 493; 494; 496 -information, 325 -init-file, 225; 243; 514; 515 -keys-used, 326; 425; 426 -language, 225; 341 --ledir, 217 -log, 72; 74; 141; 161; 216; 217; 220; 224; 226; 227; 239; 245; 319; 346-349; 351353; 376; 377; 382; 386; 398; 399; 401; 595; 597; 607 -log-bin, 72; 226; 239; 319; 346; 348; 349; 352; 353; 376; 398; 399; 401 -log-bin-index, 226; 349 -log-error, 161; 216; 217; 224; 226; 346; 353 -log-isam, 226; 353 —log-long-format, 226; 351 -log-queries-not-using-indexes, 226 -log-short-format, 226 -log-slave-updates, 382; 386; 398; 401 -log-slow-queries, 226; 245; 351; 352 -log-update, 226; 347; 352; 353 log-warnings, 161; 227 -log-warnings, 227; 377; 386; 597 -low-priority-updates, 227; 395; 434 -master-connect-retry, 367; 370; 383; 384; 386;391
617 -master-host, 384; 386 -master-info-file, 386 —master-password, 384; 386 -master-port, 384; 386 -master-ssl, 384; 386; 387 -master-ssl-ca, 384; 386 -master-ssl-capath, 384; 386 —master-ssl-cert, 384; 386 -master-ssl-cipher, 384; 386 -master-ssl-key, 384; 387 -master-user, 384; 387 MAX_ROWS, 24; 96; 246; 247; 331; 514; 598 -max-relay-log-size, 387; 388 -medium-check, 325; 486 -memlock, 227; 244 -myisam-recover, 227; 241; 248; 334; 430; 502; 503 —mysqladmin, 220 -mysqld,217;220 -mysqld-version, 217 -new, 155; 157; 208; 228 -nice, 217 -no-defaults, 209; 217; 291 -no-log, 220 —no-symlinks, 326 -old-passwords, 159; 298-300 -old-protocol, 166; 228; 599 -one-thread, 228 -open-files-limit, 184; 185; 217; 228; 446; 533;601 -pager, 469; 472 -parallel-recover, 326 -password, 220; 281; 295; 310 -pid-file, 217; 221; 228; 249; 353 -port, 149; 209; 217; 228; 249; 290; 352; 354; 355; 358; 359; 469; 479; 481; 484; 486; 490; 493; 494; 496; 590 -print-defaults, 154; 209 query_cache_type, 161; 237; 249; 259; 264; 362;363;562 -quick, 169; 207; 326; 328; 329; 467; 469; 486; 487; 490; 594 read_buffer_size, 161; 237; 250; 259; 323; 449; 450; 451; 529; 530 read_rnd_buffer_size, 161; 237; 250; 259; 422; 423; 449; 451; 453 -read-only, 325; 387 -recover, 323; 324; 326; 328; 508 -relay-log, 371; 387; 391 -relay-log-index, 387 -relay-log-info-file, 387 —relay-log-purge, 387 —relay-log-space-limit, 387
618 -replicate-do-db, 388; 392 --replicate-do-table, 388; 392; 393 -replicate-ignore-db, 388; 389; 392 --replicate-ignore-table, 389; 392 --replicate-rewrite-db, 390 -replicate-wild-do-table, 388; 389; 392; 393 -replicate-wild-ignore-table, 389; 390; 392 -report-host, 390 -report-port, 390 -safe-mode, 228 -safe-recover, 323; 326; 328; 332 -safe-show-database, 160; 228; 271 -safe-user-create, 228; 271 -secure-auth, 228; 250; 271 -set-auto-increment, 327 -set-character-set, 124; 153; 326; 340 -silent, 136; 322; 323; 329; 333; 334; 463; 470; 480; 486; 495; 607 -skip-bdb, 215; 228; 238; 242; 395; 516; 517 —skip-concurrent-insert, 229 —skip-delay-key-write, 229 -skip-external-locking, 113; 161; 227; 229; 323; 325; 328; 329; 448; 462; 463; 503; 606;607 -skip-grant-tables, 140; 229; 271; 291; 295; 604; 605 -skip-host-cache, 229; 293; 455 -skip-innodb, 161; 215; 229; 242; 395 —skip-isam, 229; 242 -skip-locking, 161; 229 -skip-name-resolve, 104; 184; 229; 271; 293; 455 —skip-networking, 229; 271; 455 -skip-new, 229; 240 -skip-safemalloc, 230; 452 -skip-show-database, 230; 271; 280 -skip-slave-start, 377; 390 -skip-stack-trace, 230 -skip-symbolic-links, 229; 458 -skip-thread-priority, 186; 230 —slave_compressed_protocol, 390 -slave-load-tmpdir, 319; 373; 391 —slave-net-timeout, 391 -slave-skip-errors, 383; 391 -socket, 104; 209; 217; 230; 352; 354; 358; 359; 470; 480; 481; 484; 487; 491; 493; 495; 496; 590; 591; 610; 611 sort_buffer_size, 161; 234; 237; 251; 254; 259; 264; 323; 324; 332; 334; 422; 423; 450; 451; 529 -sort-index, 327; 333; 334; 416; 467 -sort-records, 327; 333; 416 -sort-recover, 324; 326; 328
Предметный указатель -sql-mode, 57; 58; 158; 162; 223; 230; 232; 238 -symbolic-links, 229 ~tcp-ip, 220 -temp-pool, 161; 230 —timezone, 217 "tmpdir, 230; 327; 328; 353; 493; 598; 609 -transaction-isolation, 58; 158; 230; 552 -unpack, 327; 467 -update-state, 322; 325; 331; 502; 508 -user, 106; 115-117; 119-121; 139-141; 144; 146; 171; 182; 185; 203; 217; 220; 221; 224; 231; 269; 281; 302-305; 468; 470; 480; 481; 484; 487; 491; 493; 495; 496; 601; 603 -verbose, 147; 205; 223; 323; 327; 330; 416; 449; 451; 463; 470; 478; 480; 487; 491; 495; 496 -version, 205; 220; 231; 323; 463; 470; 480; 481; 484; 487; 491; 495; 497 -wait, 323; 463; 470; 480 -with-berkleydb, 82 -with-debug, 82; 90; 124; 131; 189; 224; 230; 452; 479; 607 -with-innodb, 82; 85-89; 194; 214 -with-libwrap, 82; 194 -with-names-z-libs, 82 —without-innodb, 161 -with-raid, 82
П Пакет RPM, 90; 107; 108; 109; 145; 203; 213; 218; 219 Переменная серверная autocommit, 257 backjog, 182; 235; 238; 449 basedir, 98; 134; 146; 147; 235; 238; 354; 356;357 bdb_cache_size, 235; 238; 449 bdbjiome, 235; 238 bdb_log_buffer_size, 235; 238 bdbjogdir, 235; 238 bdb_max_lock, 235; 238; 239; 517 bdb_shared_data, 235; 239 bdbjmpdir, 235; 239 bdb_version, 235; 239 bigjables, 257; 259 binlog_cache_size, 235; 239; 245; 257; 262; 350; 351; 449; 517; 529 bulk_insert_buffer_size, 161; 235; 239; 257; 425; 503 character_set, 235; 239; 240; 257 character_sets, 235; 240 concurrent_insert, 235; 240; 257
Предметный указатель connecttimeout, 209; 235; 240; 257; 449; 470;480; 484; 597 convert_character_set, 235; 257 datadir, 97; 98; 134; 140; 146; 147; 207; 218; 222; 235; 238; 240; 355; 358; 517 default_week_format, 235; 240; 257 delay_key_write, 235; 240; 257 delayed_insert_limit, 235; 241; 257; 449 delayed_insert_timeout, 235; 241; 257; 449 delayed_queue_size, 235; 241; 257; 449 flush, 71; 140; 229; 235; 241; 257; 271; 277; 279; 289; 293-295; 304; 328; 329; 345; 347; 348; 350; 352; 425; 447; 449; 454; 455; 467; 478; 479; 510; 567; 593; 605 flushjime, 235; 241; 257; 449 ft_boolean_syntax, 235; 241; 258 ft_max_word_len, 235; 241; 323; 324 ft_min_word_len, 235; 242; 323; 324 ft_query_expansion_limit, 235; 242 ft_stopword_fiie, 235; 242; 324 have_bdb,215;235;242 have_innodb,215;235;242 have_isam,215;236;242 have_openssl, 215; 236; 242; 313 have_query_cache, 215; 236; 362; 364 have_raid,215;236;242 have_symlink, 215; 236; 457 init_file, 236; 243 innodb_additional_mem_pool_size, 236; 527; 529; 530 innodb_buffer_pool_size, 236; 527; 529; 530 innodb_data_file_path, 215; 236; 500; 525528;531;535;546; 572 innodb_data_home_dir, 236; 525-528; 531; 535; 546;572 innodb_fast_shutdown, 236; 531 mnodb_file_io_threads, 236 innodb_flush_log_at_trx_commit, 236; 527; 529;531; 561 innodb_flush_method, 236; 529; 532; 561 innodb_force_recovery, 236; 532; 549 innodbjock_wait_timeout, 236; 529; 532; 559 innodb_log_arch_dir, 236; 529; 532; 533 innodb_log_archive, 236; 532 innodb_log_buffer_size, 236; 527; 529; 532 innodb_log_file_size, 236; 527; 529; 533 innodb_log_files_in_group, 236; 529; 533 innodb_log_group_home_dir, 236; 529; 532; 533 innodb_mirrored_log_groups, 236; 533 innodb_thread_concurrency, 236; 529; 533; 567 interactive_timeout, 236; 243; 253; 258; 449; 597 join_buffer_size, 236; 243; 449
619 key_buffer_size, 72; 166; 208; 231; 234; 236; 243; 244; 255-258; 263; 323-326; 332; 416; 426; 441; 443; 445; 449-451; 453; 530 key__cache__age_threshold, 236; 244; 255; 444 key_cache_block_size, 236; 244; 255; 256; 445 key_cache_division_limit, 236; 244; 255; 444 language, 222; 236; 244 large_files_support, 236 locaUnfiie, 236; 244; 258 locked_in_memory, 236; 244 log, 47; 71; 74; 100; 120; 129; 141; 148; 155; 161; 182; 226; 227; 236; 238; 244-247; 258; 259; 293; 319; 346; 347; 351; 352; 368; 370-373; 375-377; 386-388; 398; 415; 425; 473; 493; 513; 520; 521; 527; 534-536; 548; 564-567; 589 log_bin, 236; 244; 259 log_slave_updates, 236; 244 log_slow_queries, 236; 245 log_update, 236; 245; 259 log_warnings, 236; 258 long_query_time, 45; 226; 236; 245; 258; 264; 345;351;449; 479 low_priority_updates, 236; 245; 258; 259 lower_case_table_names, 55; 236; 245; 449; 541;550 max_allowed_packet, 208; 210; 211; 236; 245; 248; 258; 449; 453; 470; 484; 491; 492;595;596;597 max_binlog_cache_size, 236; 245; 258; 351; 449; 517 max_binlog_size, 236; 246; 258; 348; 372 max_connect_errors, 236; 246; 258; 449; 593;594 max_connections, 174; 228; 236; 246; 258; 274; 307; 446; 449; 529; 530; 594; 601 max_delayed_threads, 236; 246; 258; 449 maxerrorcount, 237; 246; 258 max_heap_table_size, 237; 246; 258; 449 maxjoin_size, 237; 246; 247; 258; 259; 413; 449; 470; 477; 484 max_relay_log_size, 237; 246; 247; 258; 372;387 max_sort_length, 73; 237; 247; 258; 449 maxjmpjables, 237; 247; 258; 446; 449 max_user_connections, 237; 247; 258; 270; 307 max_write_lock_count, 237; 247; 258; 434; 449 myisam_max_extra_sort_file_size, 161; 237; 248; 258; 503 myisam_max_sort_file_size, 237; 248; 258; 503
620
Предметный указатель myisam_recover_options, 237; 248 myisam_repair_threads, 237; 248; 258 myisam_sort_buffer_size, 237; 248; 258; 449; 503 net_buffer_length, 237; 245; 248; 258; 449; 451; 453; 470; 484; 492 net_read_timeout, 237; 248; 258; 449 net_retry_count, 237; 248; 258; 449 net_write_timeout, 237; 249; 258; 449 openjilesjimit, 237; 249; 481; 601 pid_file, 237; 249 port, 100; 126; 141; 143; 146; 149; 208; 222; 237; 249; 268; 318; 354-359; 385; 592 protocol_version, 237; 249 query_cache_limit, 237; 249; 259; 363 query_cache_size, 231; 235; 237; 249; 259; 360; 362; 562 query_cache_type, 161; 237; 249; 259; 264; 362;363; 562 read_buffer_size, 161; 237; 250; 259; 323; 449-451; 529; 530 read_md_buffer_size, 161; 237; 250; 259; 422; 423; 449; 451; 453 rpl_recovery_rank, 237; 259 serverjd, 237; 251; 259; 376; 377 skip_external_locking, 237; 251 skip_networking, 237; 251 skip_show_database, 237; 250; 251 slavejiettimeout, 237; 248; 251; 259; 383 slowjaunchjime, 237; 251; 259; 264; 449 socket, 100; 122; 126; 141; 143; 146; 149; 186; 208; 222; 237; 251; 290; 354-359; 590; 591; 610; 611 sort_buffer_size, 161; 234; 237; 251; 254; 259; 264; 323; 324; 332; 334;422; 423; 450;451;529 sql_mode, 57; 58; 158; 232; 237; 252; 379; 380; 381 table_cache, 228; 237; 252; 259; 263; 446; 447; 449; 450; 451; 601 tablejype, 237; 252; 259; 380; 499 thread_cache_size, 237; 252; 259; 265; 427 thread_stack, 176; 237; 252; 449; 453 timezone, 237; 252; 611 tmp_table_size, 237; 252; 259; 262; 449; 453; 514; 598 tmpdir, 230; 237; 239; 252; 253; 319; 327; 353; 373; 391; 423; 517; 599 tx_isolation, 237; 253; 260; 552 version, 52; 54; 103; 132; 141; 182; 195; 216; 217; 237; 253; 272; 291;335;337; 369; 463; 465; 478; 520; 536; 580; 590; 591; 595; 606; 611 waitjimeout, 184; 237; 243; 253; 260; 449; 595;597 warning_count, 260
состояния Aborted_clients, 260; 261; 597 Abortedconnects, 260; 261 Bytes_received, 260; 262 Bytes_sent, 260; 262 Connections, 252; 260; 262; 265; 426 Created_tmp_disk_tables, 260; 262 Createdjmp_files, 260; 262 Created_tmp_tables, 260; 262 Delayed_errors, 260; 262 Delayedinsertthreads, 260; 262 Delayedwrites, 260; 262 Flushcommands, 260; 262 Handler_delete, 260; 262 Handler_read_first, 260; 262 Handler_read_key, 260; 262 Handler_read_next, 260; 263 Handler_read_prev, 260; 263 Handlerreadrnd, 260; 263 Handler_read__rnd_next, 260; 263 Handlerupdate, 260; 263 Handlerwrite, 260; 263 Key_blocks_used, 244; 260; 263 Key_read_requests, 243; 260; 263 Key_reads,243;261;263 Key_write_requests, 243; 261; 263 Key_writes,243;261;263 Max_used_connections, 261; 263 Not_flushed_delayed_rows, 261; 263 Not_flushed_key_blocks, 261; 263 Open_files,261;263 Open_streams, 261; 263 Open_tables,261;263 Openedjables, 252; 261; 263; 447 Qcachejree_blocks, 261; 263; 363; 364 Qcachejfree_memory, 261; 264; 364 Qcachejiits, 261; 264; 361; 364 Qcachejnserts, 261; 264; 364 Qcache_lowmem_prunes, 261; 264; 363; 364 Qcache_not_cached, 261; 264; 364 Qcache_queries_in_cache, 261; 264; 364 Qcachejotal_blocks, 261; 264; 363; 364 Questions, 141; 261; 264; 446; 478; 479 Select_fulljoin,261;264 Select_full_rangejoin, 261; 264 Select_range, 261; 264 Select_range_check, 261; 264 Select_scan, 261; 264 Slave_open_temp_tables, 261; 264 Slave_running, 261; 264 Slowjaunchjhreads, 261; 264 Slow_queries, 245; 261; 264 Sort_merge_passes, 261; 264 Sort_range, 261; 264 Sort_rows,261;265 Sort_scan, 261 Table_locks_immediate, 261; 265; 431
621
Предметный указатель Table_locks_waited, 261; 265; 431 Threads_cached, 261; 265 Threads_connected, 261; 265 Threads_created, 252; 261; 265 Threads_running, 261; 265 Uptime, 141; 261; 265; 446; 478 Подзапрос, 39; 61; 66; 410 Полнотекстовый поиск, 23 Потоки MIT-pthreads, 47; 73; 127; 131; 132; 149; 179; 183; 184; 190; 271; 292; 448; 452; 591 Представление, 37; 43; 66 Привилегия CREATE TEMPORARY TABLES, 160 EXECUTE, 160; 278 FILE, 160 LOCK TABLES, 160 REPLICATION CLIENT, 160; 278; 280 REPLICATION SLAVE, 160; 278; 280; 374; 387 SHOW DATABASES, 160; 177; 228; 230; 250; 251; 271; 278; 280 SUPER, 160; 234; 250; 253; 255; 270; 278280; 350; 373; 374; 387; 533; 552; 594 Программа mysql, 15-18; 21; 25; 26; 28-34; 36; 37; 39; 41-46; 48; 50; 51; 53-56; 58; 60; 61; 64; 67; 68; 71; 72; 74; 80; 81; 83-123; 125127; 131-146; 148-155; 157-160; 163; 165-169; 171-173; 175; 177; 178; 179189; 191-203; 205-211; 213-215; 217219; 221-223; 228; 230; 232; 234-237; 243; 253; 254; 256; 257; 260; 266-273; 277-283; 286; 290-300; 302-310; 312; 313; 317; 320; 332; 340; 341; 345-347; 350-352; 354-358; 360-364; 368; 374; 375; 377; 379; 381; 386; 393; 395; 400; 401; 404; 406; 407; 414; 415; 420; 431; 432; 439; 442-445; 447; 449; 450; 459461; 467-469; 471-477; 482; 483; 487; 492; 495; 509; 510; 513; 521; 524; 527; 528; 534-537; 541; 542; 547; 563; 564; 577; 579; 584; 589; 59(Г-594; 596; 597; 599; 601-607; 610-612 mysqladmin, 16; 46; 52-54; 74; 96; 101-103; 105-107; 110; 112; 113; 132; 139-141; 145; 148; 151; 152; 167; 169; 186; 190; 193; 202; 203; 206; 220; 222; 229; 270; 271; 277; 279; 287; 289; 291-293; 295; 304; 308-310; 328; 329; 331; 345; 347; 348; 350; 352; 355; 358; 371; 375; 382; 425; 446; 447; 450; 454; 455; 460; 467; 477-479; 510; 534; 589-593; 595; 603; 605-609; 611
mysqlc, 104 mysqlcc, 127; 202; 206; 460; 483 mysqlcheck, 22; 202; 206; 321; 460; 485 mysqld, 38; 43; 46; 47; 53; 54; 55;^57; 71; 74; 82; 85; 86; 89; 93; 94; 96; 98-104; Г06; 109-111; 113-123; 129-132; 134; 135; 140; 141; 143-149; 153-155; 158; 160167; 170-178; 180-186; 190-193; 195; 197; 202; 206-208; 212- 232; 234; 238240; 242-244; 246; 249; 251-253; 256; 262; 269-272; 277; 289; 291-293; 295; 312; 316; 319; 322-325; 328; 329; 331; 334; 341; 345-352; 354-360; 362; 376; 385; 390; 424; 434; 446; 447; 449-455; 458; 459; 462; 463; 467; 479; 483; 485; 491; 502; 503; 507; 508; 516; 517; 519; 520; 524-528; 530; 534; 535; 537; 544; 545; 547-550; 552; 562; 563; 572; 579; 589-601; 603-611; 613 --ansi, 57; 223; 238 -sql-mode, 57; 58; 158; 162; 223; 230; 232; 238 mysqldhow, 107 mysqld-max, 82; 96; 98; 99; 212; 213; 216; 217; 225; 354; 355; 459; 527 mysqld-max-nt, 98; 99; 225; 355; 459 mysqld-nt, 98; 99; 106; 225; 355-357; 604 mysqld-opt, 98; 99 mysqldump, 53; 54; 65; 66; 107; 153; 155157; 160; 164; 168; 169; 202; 203; 206; 208; 232; 295; 319; 376; 377; 393; 458; 461; 487; 488; 490-492; 520; 542; 546; 547; 551; 562; 573; 584 mysqlhotcopy, 202; 206; 209; 319; 461; 487; 492; 493 mysqlimport, 169; 202; 206; 272; 461; 493495;584 mysqlshow, 103; 137; 141; 202; 203; 206; 461; 495; 496; 599 WinMySQLAdmin, 96; 98; 167 Протокол клиент-серверный, 43; 242; 249
p Режим ANSI, 18; 47; 56-58; 61; 87; 118; 188; 232; 233; 420; 490 ANSI_QUOTES, 58; 232; 233; 490 DB2, 233; 404; 406; 582 IGNORE_SPACE, 58; 232; 233; 468 MAXDB, 233 MSSQL, 233 MYSQL323, 233 MYSQL40, 233
Предметный указатель
622 NO_AUTO_VALUE_ON_ZERO, 232 NO_DIR_IN_CREATE, 233; 381 NO_FIELD_OPTIONS, 233 NO_KEY_OPTIONS, 233 NO_TABLE_OPTIONS, 233 NO_UNSIGNED_SUBTRACTION, 233 ONLY_FULL_GROUP_BY, 58; 233 ORACLE, 233 PIPES_AS_CONCAT, 58; 233 POSTGRESQL, 233 REAL_AS_FLOAT, 58; 233 Репликация, 23; 40; 71; 365; 366; 380; 395; 396; 543;584 --log-slave-updates, 382; 386; 398; 401 --log-warnings, 227; 377; 386; 597 —master-connect-retry, 367; 370; 383; 384; 386;391 -master-host, 384; 386 —master-info-file, 386 -master-password, 384; 386 -master-port, 384; 386 -master-ssl, 384; 386; 387 —master-ssl-ca, 384; 386 -master-ssl-capath, 384; 386 —master-ssl-cert, 384; 386
-master-ssl-cipher, 384; 386 -master-ssl-key, 384; 387 -master-user, 384; 387 —max-relay-log-size, 387; 388 -read-only, 325; 387 -relay-log, 371; 387; 391 -relay-log-index, 387
—relay-log-info-file, 387 -relay-log-purge, 387 -relay-log-space-limit, 387 -replicate-do-db, 388; 392 ~replicate-do-table, 388; 392; 393 -replicate-ignore-db, 388; 389; 392 -replicate-ignore-table, 389; 392 —replicate-rewrite-db, 390 -replicate-wild-do-table, 388; 389; 392; 393 -replicate-wild-ignore-table, 389; 390; 392 -report-host, 390 -report-port, 390 -skip-slave-start, 377; 390 —slave_compressed_protocol, 390 -slave-load-tmpdir, 319; 373; 391 —slave-net-timeout, 391 -slave-skip-errors, 383; 391 Репозиторий BitKeeper, 39; 41; 42; 79; 80; 82; 83; 124; 125; 127; 133; 135; 136
Семафор, 46; 47; 78; 104; 172; 370; 371; 455; 516; 533; 567 Сервер баз данных, 18 встроенный, 39; 223 Симметричная многопроцессорная система, 78; 170 Система управления базами данных, 18 Список рассылки MySQL, 48 anounce, 48 benchmarks, 49; 175; 404; 406 benchmarks-digest, 49 bugs, 48; 50; 51; 53; 54; 84; 126; 213; 401 bugs-digest, 48 gui-tools, 49 gui-tools-digest, 49 internals, 48; 90; 127; 172; 343 internals-digest, 48 Java, 49 java-digest, 49 msql-mysql-modules, 50 msql-mysql-modules-digest, 50 myodbc, 49 myodbc-digest, 49 mysql, 48 mysql-digest, 48 mysqldoc, 49; 127 mysqldoc-digest, 49 packagers, 49 packagers-digest, 49 plusplus, 49; 50 plusplus-digest, 50 Win32, 49; 133 win32-digest, 49 Стандарт SQL 1999, 18;56 2003, 18; 42; 56 SQL-92, 18; 56 СУБД, См. Система управления базами данных, 18; 19; 28; 29; 31; 33; 35; 36; 39; 47; 49; 56; 60; 62; 63; 67; 68; 79; 81; 150; 231; 403; 404; 407 Сценарий bin/mysqlbug, 85 Build-tools/Do-compile, 85 configure, 46; 54; 85-90; 118; 119; 121-124; 126-131; 161; 164; 173; 176-196; 312; 340; 342; 343; 358; 360; 386; 452; 516; 528; 600; 607; 611; 612
623
Предметный указатель mysql.server, 116; 120; 144-146; 173; 181; 202; 206; 213; 218; 219; 223; 270; 346; 611 mysql_fix_privilege_tables, 154; 158; 159; 165; 168; 213; 290; 297; 298 mysql_install_db, 94; ПО; 115; 116; 118; 120; 138; 139; 140; 142-144; 149; 171; 184; 191; 202; 213; 290; 304; 358; 577 mysql_multi, 202; 213; 219; 220-222; 359 mysqlaccess, 54; 117; 277; 289; 295; 460 mysqld_safe, 47; 74; 110; 111; 114; 115; 117; 119; 121; 140; 141; 144-147; 153; 160; 161; 174-176; 184; 185; 190; 191; 195; 202; 206; 213; 215-218; 220-224; 228; 252; 270; 334; 346; 354; 358; 359; 450; 451; 534; 579; 593; 596; 601; 604; 605; 610; 611 scripts/make_binary_distribution, 85; 95
т Тип BIT, 43; 61 DATE, 20; 25; 45; 46; 69; 157; 165; 166; 361; 585;587 DATETIME, 20; 25; 44; 46; 69; 157; 158; 166 SET, 20; 44; 46; 57-60; 64; 67; 69; 73-75; 124; 150-152; 155; 156; 158; 161; 196; 210; 227; 231; 232; 234; 235; 242; 243; 253; 254; 256; 257; 269; 270; 276; 289; 291; 292; 296; 298-300; 304; 305; 309; 332; 349; 350; 363; 387-389; 400; 424; 428; 432; 434; 443; 445; 476; 477; 518; 528; 533;536;537; 539-543; 551; 552; 555; 556; 559; 561; 562; 592; 593; 599; 606 TIMESTAMP, 20; 25; 26; 44; 46; 157; 166; 228; 361; 380; 384; 394; 587; 611 TINYINT,43;466;507;585 Триггер, 37; 65
У Уровень изоляции транзакций, 551; 552 READ COMMITTED, 230; 237; 552 READ UNCOMMITTED, 230; 552 REPEATABLE READ, 230; 552 SERIALIZABLE, 58; 158; 230; 552; 553; 557
Утилита gunzip, 114-119; 169; 198 myisamchk, 22; 24; 55; 113; 124; 153; 157; 163; 165; 203; 206; 213; 229; 319-340; 345; 411; 416; 425; 426; 430; 448; 458; 463; 465; 467; 485; 493; 500-502; SOSSOS; 522;598; 607 myisampack, 24; 45; 203; 206; 327; 339; 425; 460-464; 466; 467; 500; 504; 506; 509; 510; 522 mysqlaccess, 54; 117; 277; 289; 295; 460 mysqlbinlog, 72; 106; 203; 206; 320; 350; 371; 401; 460;480-483;547 mysqlhotcopy, 202; 206; 209; 319; 461; 487; 492; 493 perror, 203; 330; 461; 497; 575; 599-601 replace, 67; 193; 313; 316; 396; 461; 494; 495; 497 tar, 54; 81; 85; 91; 92; 94; 109; 110; 114-119; 131; 136; 171; 178; 179; 194; 195; 198; 354; 374; 375; 393
Ф Файл my.cnf, 97; 98; 106; 113; 118; 120; 134; 145147; 154; 167; 174; 206; 207; 209; 218220; 222; 231; 269; 311; 316; 317; 356; 359; 360; 376; 378; 385; 451; 459; 474; 524-528; 534; 535; 537; 544; 546; 547; 550; 552; 561; 603; 610 my.ini, 97; 98; 134; 206; 459; 524; 525; 527; 528; 535; 537 Файловая система ext2, 24; 448 ReiserFS, 24; 78; 448 Функция ADD_TO_SET, 44 ANY(), 45 EVERY(), 45 REMOVE_FROM_SET, 44 SOME(), 45 X Хранимая процедура, 37; 42; 65; 429
Научно-популярное издание Компания MySQL AB
MySQL. Руководство администратора Верстка Т.Н. Артеменко Художественный редактор ВТ. Павлютин
Издательский дом "Вильяме". 101509, Москва, ул. Лесная, д. 43, стр. 1. Подписано в печать 31.03.2005. Формат 70X100/16. Гарнитура Times. Печать офсетная. Усл. печ. л. 50,31. Уч.-изд. л. 39,64. Тираж 3000 экз. Заказ № 1384.
Отпечатано с диапозитивов в ФГУП "Печатный двор" Министерства РФ по делам печати, телерадиовещания и средств массовых коммуникаций. 197110, Санкт-Петербург, Чкаловский пр., 15.