Справочное руководство по MySQL версии 5.0.0-alpha. - Table of Contents

Справочное руководство по MySQL версии 5.0.0-alpha.

  • 1 Общая информация
    • 1.1 Об этом руководстве
    • 1.2 Соглашения, используемые в данном руководстве
    • 1.3 О русском переводе руководства
      • 1.3.1 Список терминов, принятых в русском переводе
    • 1.4 Что представляет собой MySQL?
      • 1.4.1 История MySQL
      • 1.4.2 Основные возможности MySQL
      • 1.4.3 Насколько стабильным является MySQL?
      • 1.4.4 Насколько большими могут быть таблицы в MySQL?
      • 1.4.5 Вопросы, связанные с Проблемой-2000
    • 1.5 Что представляет собой компания MySQL AB?
      • 1.5.1 Бизнес-модель и услуги, оказываемые компанией MySQL AB
        • 1.5.1.1 Поддержка
        • 1.5.1.2 Обучение и сертификация
        • 1.5.1.3 Консультации
        • 1.5.1.4 Коммерческие лицензии
        • 1.5.1.5 О нашей программе партнерства
        • 1.5.1.6 О рекламе
      • 1.5.2 Как с нами связаться
    • 1.6 Лицензии и поддержка MySQL
      • 1.6.1 Поддержка, предлагаемая компанией MySQL AB
      • 1.6.2 Авторские права и лицензии на MySQL
      • 1.6.3 Лицензии на ПО MySQL
        • 1.6.3.1 Использование ПО MySQL под коммерческой лицензией
        • 1.6.3.2 Бесплатное использование ПО MySQL по лицензии GPL
      • 1.6.4 Логотипы и торговые марки MySQL AB
        • 1.6.4.1 Оригинальный логотип MySQL
        • 1.6.4.2 Логотипы MySQL, которые могут использоваться без письменного разрешения
        • 1.6.4.3 В каком случае для использования логотипов необходимо письменное разрешение?
        • 1.6.4.4 Партнерские логотипы MySQL AB
        • 1.6.4.5 Использование слова MySQL в текстовых документах и презентациях
        • 1.6.4.6 Использование слова MySQL в названиях компаний и продуктов
    • 1.7 Кратко о MySQL 4.x
      • 1.7.1 Поэтапный выпуск
      • 1.7.2 Можно использовать уже прямо сейчас
      • 1.7.3 Встроенный MySQL
      • 1.7.4 Другие функции, доступные в MySQL 4.0
      • 1.7.5 Функции MySQL 4.x, которые будут добавлены в будущем
      • 1.7.6 MySQL 4.1, следующая ветка в разработке
    • 1.8 Источники информации по MySQL
      • 1.8.1 Списки рассылки MySQL
        • 1.8.1.1 Списки рассылки MySQL
        • 1.8.1.2 Как задавать вопросы и направлять сообщения об ошибках
        • 1.8.1.3 Как отправлять отчеты об ошибках или проблемах
        • 1.8.1.4 Рекомендации по ответам на вопросы, направляемые в список рассылки
      • 1.8.2 Пользователи MySQL на IRC
    • 1.9 Насколько MySQL соответствует стандартам?
      • 1.9.1 Каким стандартам соответствует MySQL ?
      • 1.9.2 Запуск MySQL в режиме ANSI
      • 1.9.3 Расширения MySQL к ANSI SQL92
      • 1.9.4 Отличия MySQL от ANSI SQL92
        • 1.9.4.1 Вложенные SELECTы
        • 1.9.4.2 Оператор SELECT INTO TABLE
        • 1.9.4.3 Транзакции и атомарные операции
        • 1.9.4.4 Хранимые процедуры и триггеры
        • 1.9.4.5 Внешние ключи
        • 1.9.4.6 Представления
        • 1.9.4.7 Символы `--' как начало комментария
      • 1.9.5 Известные ошибки и недостатки проектирования в MySQL
        • 1.9.5.1 Ошибки, известные в 3.23 и исправленные в более поздних версиях MySQL
        • 1.9.5.2 Открытые ошибки / особенности строения MySQL
    • 1.10 MySQL и будущее (что предстоит сделать)
      • 1.10.1 Что планируется реализовать в версии в 4.0
      • 1.10.2 Что планируется реализовать в версии 4.1
      • 1.10.3 Что планируется реализовать в версии 5.0
      • 1.10.4 Что должно быть сделано в ближайшем будущем
      • 1.10.5 То, что надо сделать когда-нибудь
      • 1.10.6 То, чего не планируется делать
    • 1.11 Сравнение MySQL с другими СУБД
      • 1.11.1 Сравнение MySQL и mSQL
        • 1.11.1.1 Как конвертировать инструментальные средства mSQL в MySQL
        • 1.11.1.2 Различия в клиент-серверных коммуникационных протоколах mSQL и MySQL
        • 1.11.1.3 Различия в синтаксисе SQL между mSQL 2.0 и MySQL
      • 1.11.2 Сравнение MySQL c PostgreSQL
        • 1.11.2.1 Стратегии развития MySQL и PostgreSQL
        • 1.11.2.2 Сравнение возможностей MySQL и PostgreSQL
        • 1.11.2.3 Тестирование скорости работы MySQL и PostgreSQL
  • 2 Установка MySQL
    • 2.1 Быстрая стандартная установка MySQL
      • 2.1.1 Установка MySQL на Linux
      • 2.1.2 Установка MySQL на Windows
        • 2.1.2.1 Установка бинарного кода
        • 2.1.2.2 Подготовка конфигурации MySQL для Windows
        • 2.1.2.3 Первый запуск сервера
      • 2.1.3 Установка MySQL на MacOS X
    • 2.2 Общие вопросы инсталляции
      • 2.2.1 Как получить MySQL
      • 2.2.2 Проверка целостности пакетов с помощью MD5 Checksums или GnuPG
      • 2.2.5 Операционные системы, поддерживаемые MySQL
      • 2.2.6 Какую версию MySQL использовать
      • 2.2.7 Схемы установки
      • 2.2.8 Как и когда выпускаются обновления
      • 2.2.9 Бинарные коды MySQL, скомпилированные в MySQL AB
      • 2.2.10 Установка бинарного дистрибутива MySQL
    • 2.3 Установка исходного дистрибутива MySQL
      • 2.3.1 Обзор быстрой установки
      • 2.3.2 Применение патчей
      • 2.3.3 Типичные опции configure
      • 2.3.4 Установка из экспериментального набора исходных кодов
      • 2.3.5 Проблемы с компиляцией?
      • 2.3.6 Замечания по потокам MIT-pthreads
      • 2.3.7 Дистрибутив исходного кода для Windows
    • 2.4 Послеустановочные настройка и тестирование
      • 2.4.1 Проблемы при запуске mysql_install_db
      • 2.4.2 Проблемы при запуске сервера MySQL
      • 2.4.3 Автоматический запуск и остановка MySQL
    • 2.5 Апгрейд/даунгрейд MySQL
      • 2.5.1 Модернизация с версии 4.0
      • 2.5.2 Модернизация с версии 3.23 до версии 4.0
      • 2.5.3 Модернизация с версии 3.22 до версии 3.23
      • 2.5.4 Модернизация с версии 3.21 до версии 3.22
      • 2.5.5 Модернизация с версии 3.20 до версии 3.21
      • 2.5.6 Модернизация к иной архитектуре
    • 2.6 Заметки по операционным системам
      • 2.6.1 Примечания к Linux (Все версии Linux)
        • 2.6.1.1 Примечания к бинарным дистрибутивам Linux
        • 2.6.1.2 Заметки по поводу Linux x86
        • 2.6.1.3 Примечания к Linux SPARC
        • 2.6.1.4 Примечания к Linux Alpha
        • 2.6.1.5 Примечания к Linux PowerPC
        • 2.6.1.6 Примечания к Linux MIPS
        • 2.6.1.7 Примечания к Linux IA64
      • 2.6.2 Примечания к Windows
        • 2.6.2.1 Запуск MySQL на Windows 95, 98 или Me
        • 2.6.2.2 Запуск MySQL на Windows NT, 2000 или XP
        • 2.6.2.3 Работа MySQL в среде Windows
        • 2.6.2.4 Соединение с MySQL на удаленной машине под Windows с использованием SSH
        • 2.6.2.5 Распределение данных в Windows между несколькими различными дисками
        • 2.6.2.6 Компиляция MySQL-клиентов в среде Windows
        • 2.6.2.7 Сравнительные характеристики MySQL под Windows и под Unix
      • 2.6.3 Примечания к Solaris
        • 2.6.3.1 Примечания к Solaris 2.7/2.8
        • 2.6.3.2 Примечания к Solaris x86
      • 2.6.4 Примечания к BSD
        • 2.6.4.1 Примечания к FreeBSD
        • 2.6.4.2 Примечания к NetBSD
        • 2.6.4.3 Примечания к OpenBSD 2.5
        • 2.6.4.4 Примечания к OpenBSD 2.8
        • 2.6.4.5 Примечания к BSD/OS версий 2.x
        • 2.6.4.6 Примечания к BSD/OS версий 3.x
        • 2.6.4.7 Примечания к BSD/OS версий 4.x
      • 2.6.5 Примечания к Mac OS X
        • 2.6.5.1 Mac OS X 10.x
        • 2.6.5.2 Mac OS X Server 1.2 (Rhapsody)
      • 2.6.6 Примечания к другим Unix-системам
        • 2.6.6.1 Примечания к бинарному дистрибутиву HP-UX
        • 2.6.6.2 Примечания к HP-UX версии 10.20
        • 2.6.6.3 Примечания к HP-UX версий 11.x
        • 2.6.6.4 Примечания к IBM-AIX
        • 2.6.6.5 Примечания к SunOS 4
        • 2.6.6.6 Примечания к Alpha-DEC-UNIX (Tru64)
        • 2.6.6.7 Примечания к Alpha-DEC-OSF/1
        • 2.6.6.8 Примечания к SGI Irix
        • 2.6.6.9 Примечания к Caldera (SCO)
        • 2.6.6.10 Примечания к Caldera (SCO) Unixware Version 7.0
      • 2.6.7 Примечания к OS/2
      • 2.6.8 Примечания к BeOS
      • 2.6.9 Примечания к Novell NetWare
    • 2.7 Замечания по установке Perl
      • 2.7.1 Установка Perl на Unix
      • 2.7.2 Установка ActiveState Perl на Windows
      • 2.7.3 Установка дистрибутива Perl для MySQL на Windows
      • 2.7.4 Проблемы использования интерфейса Perl DBI/DBD
  • 3 Учебное пособие по MySQL
    • 3.1 Подсоединение к серверу и отсоединение от него
    • 3.2 Ввод запросов
    • 3.3 Создание и использование базы данных
      • 3.3.1 Создание и выбор базы данных
      • 3.3.2 Создание таблицы
      • 3.3.3 Загрузка данных в таблицу
      • 3.3.4 Выборка информации из таблицы
        • 3.3.4.1 Выборка всех данных
        • 3.3.4.2 Выборка определенных строк
        • 3.3.4.3 Выборка определенных столбцов
        • 3.3.4.4 Сортировка строк
        • 3.3.4.5 Вычисление дат
        • 3.3.4.6 Работа с значениями NULL
        • 3.3.4.7 Сравнение по шаблонам
        • 3.3.4.8 Подсчет строк
        • 3.3.4.9 Использование нескольких таблиц
    • 3.4 Получение информации о базах данных и таблицах
    • 3.5 Примеры стандартных запросов
      • 3.5.1 Максимальное значение столбца
      • 3.5.2 Строка, содержащая максимальное значение некоторого столбца
      • 3.5.3 Максимальное значение столбца для группы
      • 3.5.4 Строка, содержащая максимальное значение некоторого столбца
      • 3.5.5 Использование пользовательских переменных
      • 3.5.6 Использование внешних ключей
      • 3.5.7 Поиск по двум ключам
      • 3.5.8 Подсчет посещений за день
      • 3.5.9 Использование атрибута AUTO_INCREMENT
    • 3.6 Использование mysql в пакетном режиме
    • 3.7 Запросы проекта "Близнецы" (Twin Project)
      • 3.7.1 Поиск нераспределенных близнецов
      • 3.7.2 Вывод таблицы состояний пар близнецов
    • 3.8 Использование MySQL совместно с Apache
  • 4 Администрирование баз данных
    • 4.1 Конфигурирование MySQL
      • 4.1.1 Параметры командной строки mysqld
      • 4.1.2 Файлы параметров `my.cnf'
      • 4.1.3 Установка нескольких серверов на один компьютер
      • 4.1.4 Запуск нескольких серверов MySQL на одном компьютере
    • 4.2 Общие проблемы безопасности и система привилегий доступа MySQL
      • 4.2.1 Общие принципы обеспечения безопасности
      • 4.2.2 Как обезопасить MySQL от хакеров
      • 4.2.3 Опции запуска mysqld, относящиеся к безопасности
      • 4.2.4 Вопросы безопасности, относящиеся к команде LOAD DATA LOCAL
      • 4.2.5 Функции, выполняемые системой привилегий
      • 4.2.6 Как работает система привилегий
      • 4.2.7 Привилегии, предоставляемые MySQL
      • 4.2.8 Соединение с сервером MySQL
      • 4.2.9 Управление доступом, этап 1: верификация подсоединения
      • 4.2.10 Управление доступом, этап 2: верификация запросов
      • 4.2.11 Причины появления ошибок Access denied ("в доступе отказано")
    • 4.3 Управление учетными записями пользователей MySQL
      • 4.3.1 Синтаксис команд GRANT и REVOKE
      • 4.3.2 Имена пользователей MySQL и пароли
      • 4.3.3 Когда изменения в привилегиях вступают в силу
      • 4.3.4 Задание изначальных привилегий MySQL
      • 4.3.5 Добавление новых пользователей в MySQL
      • 4.3.6 Ограничение ресурсов пользователя
      • 4.3.7 Задание паролей
      • 4.3.8 Обеспечение безопасности своего пароля
      • 4.3.9 Использование безопасных соединений
        • 4.3.9.1 Основные сведения
        • 4.3.9.2 Требования
        • 4.3.9.3 Создание SSL-сертификатов
        • 4.3.9.4 Параметры команды GRANT
    • 4.4 Предотвращение катастроф и восстановление
      • 4.4.1 Резервное копирование баз данных
      • 4.4.2 Синтаксис BACKUP TABLE
      • 4.4.3 Синтаксис RESTORE TABLE
      • 4.4.4 Синтаксис CHECK TABLE
      • 4.4.5 Синтаксис REPAIR TABLE
      • 4.4.6 Использование myisamchk для профилактики таблиц и послеаварийного
        • 4.4.6.1 Синтаксис запуска myisamchk
        • 4.4.6.2 Общие опции для myisamchk
        • 4.4.6.3 Проверочные опции для myisamchk
        • 4.4.6.4 Опции исправления для myisamchk
        • 4.4.6.5 Другие опции для myisamchk
        • 4.4.6.6 Использование памяти утилитой myisamchk
        • 4.4.6.7 Использование myisamchk для послеаварийного восстановления
        • 4.4.6.8 Как проверять таблицы на ошибки
        • 4.4.6.9 Как ремонтировать таблицы
        • 4.4.6.10 Оптимизация таблиц
      • 4.4.7 Настройка режима профилактики таблиц
      • 4.4.8 Получение информации о таблице
    • 4.5 Справочник по языку администрирования баз данных
      • 4.5.1 Синтаксис команды OPTIMIZE TABLE
      • 4.5.2 Синтаксис команды ANALYZE TABLE
      • 4.5.3 Синтаксис команды FLUSH
      • 4.5.4 Синтаксис команды RESET
      • 4.5.5 Синтаксис команды KILL
      • 4.5.6 Синтаксис команды SHOW
        • 4.5.6.1 Получение информации по базам данных, таблицам, столбцам и индексам
        • 4.5.6.2 SHOW TABLE STATUS
        • 4.5.6.3 SHOW STATUS
        • 4.5.6.4 SHOW VARIABLES
        • 4.5.6.5 SHOW LOGS
        • 4.5.6.6 SHOW PROCESSLIST
        • 4.5.6.7 SHOW GRANTS
        • 4.5.6.8 SHOW CREATE TABLE
        • 4.5.6.9 SHOW WARNINGS | ERRORS
        • 4.5.6.10 SHOW TABLE TYPES
        • 4.5.6.11 SHOW PRIVILEGES
    • 4.6 Локализация MySQL и использование национальных алфавитов
      • 4.6.1 Набор символов, применяющийся для записи данных и сортировки
        • 4.6.1.1 Набор символов немецкого алфавита
      • 4.6.2 Сообщения об ошибках на языках, отличных от английского
      • 4.6.3 Добавление набора символов
      • 4.6.4 Массивы определения символов
      • 4.6.5 Поддержка упорядочивания строк
      • 4.6.6 Поддержка многобайтовых символов
      • 4.6.7 Проблемы с наборами символов
    • 4.7 Серверные сценарии и утилиты MySQL
      • 4.7.1 Обзор серверных сценариев и утилит
      • 4.7.2 safe_mysqld, оболочка mysqld
      • 4.7.3 Mysqld_multi, программа для управления множеством серверов MySQL
      • 4.7.4 myisampack, MySQL-генератор сжатых таблиц (только для чтения)
      • 4.7.5 mysqld-max, расширенный сервер mysqld
    • 4.8 Клиентские сценарии и утилиты MySQL
      • 4.8.1 Обзор клиентских сценариев и утилит
      • 4.8.2 mysql, Утилита командной строки
      • 4.8.3 mysqladmin, Администрирование MySQL-сервера.
      • 4.8.4 Использование mysqlcheck для сопровождения и аварийного восстановления таблиц.
      • 4.8.5 mysqldump, Получение дампов данных и структуры таблицы
      • 4.8.6 mysqlhotcopy, Копирование баз данных и таблиц MySQL
      • 4.8.7 mysqlimport, импорт данных из текстовых файлов
      • 4.8.8 mysqlshow, просмотр баз данных, таблиц и столбцов
      • 4.8.9 mysql_config, Получение опций компиляции для компиляции клиентских программ
      • 4.8.10 perror, разъяснение кодов ошибок
      • 4.8.11 Как запускать SQL-команды из текстового файла
    • 4.9 Файлы журналов MySQL
      • 4.9.1 Журнал ошибок
      • 4.9.2 Общий журнал запросов
      • 4.9.3 Журнал обновлений (update)
      • 4.9.4 Бинарный журнал обновлений
      • 4.9.5 Журнал медленных запросов
      • 4.9.6 Обслуживание файлов журналов
    • 4.10 Репликация в MySQL
      • 4.10.1 Введение
      • 4.10.2 Как реализована репликация: обзор
      • 4.10.3 Как настроить репликацию
      • 4.10.4 Возможности репликации и известные проблемы
      • 4.10.5 Опции репликации в файле `my.cnf'
      • 4.10.6 SQL-команды, относящиеся к репликации
      • 4.10.7 Часто задаваемые вопросы по репликации
      • 4.10.8 Поиск неисправностей репликации
  • 5 Оптимизация в MySQL
    • 5.1 Oбзор оптимизации
      • 5.1.1 Конструктивные ограничения MySQL/компромиссы
      • 5.1.2 Вопросы переносимости
      • 5.1.3 Для чего мы использовали MySQL?
      • 5.1.4 Набор тестов MySQL (The MySQL Benchmark Suite)
      • 5.1.5 Использование собственных тестов
    • 5.2 Оптимизация SELECT и других запросов
      • 5.2.1 Синтаксис оператора EXPLAIN (получение информации о SELECT)
      • 5.2.2 Оценка производительности запроса
      • 5.2.3 Скорость выполнения запросов SELECT
      • 5.2.4 Как MySQL оптимизирует выражения WHERE
      • 5.2.5 Как MySQL оптимизирует DISTINCT
      • 5.2.6 Как MySQL оптимизирует LEFT JOIN и RIGHT JOIN
      • 5.2.7 Как MySQL оптимизирует ORDER BY
      • 5.2.8 Как MySQL оптимизирует LIMIT
      • 5.2.9 Скорость выполнения запросов INSERT
      • 5.2.10 Скорость выполнения запросов UPDATE
      • 5.2.11 Скорость выполнения запросов DELETE
      • 5.2.12 Другие советы по оптимизации
    • 5.3 Вопросы блокировок
      • 5.3.1 Как MySQL блокирует таблицы
      • 5.3.2 Вопросы блокирования таблиц
    • 5.4 Оптимизация структуры базы данных
      • 5.4.1 Конструктивные особенности MySQL
      • 5.4.2 Сделайте объем данных как можно меньше
      • 5.4.3 Использование индексов в MySQL
      • 5.4.4 Индексы столбцов
      • 5.4.5 Многостолбцовые индексы
      • 5.4.6 Почему так много открытых таблиц?
      • 5.4.7 Открытие и закрытие таблиц в MySQL
      • 5.4.8 Недостатки создания множества таблиц в одной базе данных
    • 5.5 Оптимизация сервера MySQL
      • 5.5.1 Настройка параметров системы, компляции и запуска
      • 5.5.2 Настройка параметров сервера
      • 5.5.3 Как компиляция и линкование влияет на скорость MySQL
      • 5.5.4 Как MySQL использует память
      • 5.5.5 Как MySQL использует DNS
      • 5.5.6 Синтаксис команды SET
    • 5.6 Вопросы, относящиеся к диску
      • 5.6.1 Использование символических ссылок
        • 5.6.1.1 Использование символических ссылок для баз данных
        • 5.6.1.2 Использование символических ссылок для таблиц
  • 6 Справочник по языку MySQL
    • 6.1 Структура языка
      • 6.1.1 Литералы: представление строк и чисел
        • 6.1.1.1 Cтроки
        • 6.1.1.2 Числа
        • 6.1.1.3 Шестнадцатеричные величины
        • 6.1.1.4 Значения NULL
      • 6.1.2 Имена баз данных, таблиц, столбцов, индексы псевдонимы
      • 6.1.3 Чувствительность имен к регистру
      • 6.1.4 Переменные пользователя
      • 6.1.5 Системные переменные
      • 6.1.6 Синтаксис комментариев
      • 6.1.7 ``Придирчив'' ли MySQL к зарезервированным словам?
    • 6.2 Типы данных столбцов
      • 6.2.1 Числовые типы данных
      • 6.2.2 Типы данных даты и времени
        • 6.2.2.1 Проблема 2000 года и типы данных
        • 6.2.2.2 Типы данных DATETIME, DATE и TIMESTAMP
        • 6.2.2.3 Тип данных TIME
        • 6.2.2.4 Тип данных YEAR
      • 6.2.3 Символьные типы данных
        • 6.2.3.1 Типы данных CHAR и VARCHAR
        • 6.2.3.2 Типы данных BLOB и TEXT
        • 6.2.3.3 Тип перечисления ENUM
        • 6.2.3.4 Тип множества SET
      • 6.2.4 Выбор правильного типа данных в столбце
      • 6.2.5 Использование типов столбцов из других баз данных
      • 6.2.6 Требования к памяти для различных типов столбцов
    • 6.3 Функции, используемые в операторах SELECT и WHERE
      • 6.3.1 Операторы и функции общего назначения
        • 6.3.1.1 Круглые скобки
        • 6.3.1.2 Операторы сравнения
        • 6.3.1.3 Логические операторы
        • 6.3.1.4 Функции потока управления программой
      • 6.3.2 Строковые функции
        • 6.3.2.1 Функции сравнения строк
        • 6.3.2.2 Чувствительность к регистру
      • 6.3.3 Числовые функции
        • 6.3.3.1 Арифметические операции
        • 6.3.3.2 Математические функции
      • 6.3.4 Функции даты и времени
      • 6.3.5 Функции приведения типов
      • 6.3.6 Другие функции
        • 6.3.6.1 Битовые функции
        • 6.3.6.2 Разные функции
      • 6.3.7 Функции, используемые в операторах GROUP BY
    • 6.4 Обработка данных: SELECT, INSERT, UPDATE, DELETE
      • 6.4.1 Синтаксис оператора SELECT
        • 6.4.1.1 Синтаксис оператора JOIN
        • 6.4.1.2 Синтаксис оператора UNION
      • 6.4.2 Синтаксис оператора HANDLER
      • 6.4.3 Синтаксис оператора INSERT
        • 6.4.3.1 Синтаксис оператора INSERT ... SELECT
      • 6.4.4 Синтаксис оператора INSERT DELAYED
      • 6.4.5 Синтаксис оператора UPDATE
      • 6.4.6 Синтаксис оператора DELETE
      • 6.4.7 Синтаксис оператора TRUNCATE
      • 6.4.8 Синтаксис оператора REPLACE
      • 6.4.9 Синтаксис оператора LOAD DATA INFILE
      • 6.4.10 Синтаксис оператора DO
    • 6.5 Определение данных: CREATE, DROP, ALTER
      • 6.5.1 Синтаксис оператора CREATE DATABASE
      • 6.5.2 Синтаксис оператора DROP DATABASE
      • 6.5.3 Синтаксис оператора CREATE TABLE
        • 6.5.3.1 Молчаливые изменения определений столбцов
      • 6.5.4 Синтаксис оператора ALTER TABLE
      • 6.5.5 Синтаксис оператора RENAME TABLE
      • 6.5.6 Синтаксис оператора DROP TABLE
      • 6.5.7 Синтаксис оператора CREATE INDEX
      • 6.5.8 Синтаксис оператора DROP INDEX
    • 6.6 Основные команды пользовательских программ MySQL
      • 6.6.1 Синтаксис команды USE
      • 6.6.2 Синтаксис команды DESCRIBE (Получение информации о столбцах)
    • 6.7 Команды управления транзакциями и блокировками в MySQL
      • 6.7.1 Синтаксис команд BEGIN/COMMIT/ROLLBACK
      • 6.7.2 Синтаксис команд LOCK TABLES/UNLOCK TABLES
      • 6.7.3 Синтаксис команды SET TRANSACTION
    • 6.8 Полнотекстовый поиск в MySQL
      • 6.8.1 Ограничения для полнотекстового поиска
      • 6.8.2 Тонкая настройка полнотекстового поиска в MySQL
      • 6.8.3 Предстоящие доработки по полнотекстовому поиску
    • 6.9 Кэш запросов в MySQL
      • 6.9.1 Как работает кэширование запросов
      • 6.9.2 Конфигурация кэша запросов
      • 6.9.3 Параметры кэша запросов в запросе SELECT
      • 6.9.4 Статус и поддержка кэша запросов
  • 7 Типы таблиц MySQL
    • 7.1 Таблицы MyISAM
      • 7.1.1 Пространство, необходимое для ключей
      • 7.1.2 Форматы таблиц MyISAM
        • 7.1.2.1 Характеристики статических таблиц (с фиксированной длиной)
        • 7.1.2.2 Характеристики динамических таблиц
        • 7.1.2.3 Характеристики сжатых таблиц
      • 7.1.3 Проблемы с таблицами MyISAM.
        • 7.1.3.1 Повреждения таблиц MyISAM
        • 7.1.3.2 Clients is using or hasn't closed the table properly
    • 7.2 Таблицы MERGE
      • 7.2.1 Проблемы при работе с таблицами MERGE
    • 7.3 Таблицы ISAM
    • 7.4 Таблицы HEAP
    • 7.5 Таблицы InnoDB
      • 7.5.1 Обзор таблиц InnoDB
      • 7.5.2 Параметры запуска InnoDB
      • 7.5.3 Создание табличной области InnoDB
        • 7.5.3.1 Если во время создания базы данных что-то происходит не так
      • 7.5.4 Создание таблиц InnoDB
        • 7.5.4.1 Преобразование таблиц MyISAM в формат InnoDB
        • 7.5.4.2 Ограничения внешнего ключа
      • 7.5.5 Добавление и удаление файлов данных и журналов InnoDB
      • 7.5.6 Создание резервных копий и восстановление баз данных InnoDB
        • 7.5.6.1 Контрольные точки
      • 7.5.7 Перенесение базы данных InnoDB на другой компьютер
      • 7.5.8 Транзакционная модель InnoDB
        • 7.5.8.1 Согласованное чтение
        • 7.5.8.2 Чтение с блокировкой
        • 7.5.8.3 Блокировка следующего ключа: устранение проблемы с фантомом
        • 7.5.8.4 Блокировка, осуществляемая различными операторами SQL в InnoDB
        • 7.5.8.5 Обнаружение и откат взаимоблокировки (deadlock)
        • 7.5.8.6 Пример работы согласованного чтения в InnoDB
        • 7.5.8.7 Каким образом избежать взаимоблокировок (deadlock)?
        • 7.5.8.8 Рекомендации по увеличению производительности
        • 7.5.8.9 InnoDB Monitor
      • 7.5.9 Реализация многовариантности
      • 7.5.10 Структуры таблиц и индексов
        • 7.5.10.1 Физическая структура индекса
        • 7.5.10.2 Буферизация вставок
        • 7.5.10.3 Адаптивный хешированный индекс
        • 7.5.10.4 Физическая структура записи
        • 7.5.10.5 Как работают автоинкрементные столбцы в InnoDB
      • 7.5.11 Управление файловым пространством и дисковый ввод/вывод
        • 7.5.11.1 Дисковый ввод/вывод
        • 7.5.11.2 Управление файловым пространством
        • 7.5.11.3 Дефрагментация таблицы
      • 7.5.12 Обработка ошибок
      • 7.5.13 Ограничения для таблиц InnoDB
      • 7.5.14 История изменений InnoDB
      • 7.5.15 Контактная информация для получения данных по InnoDB
    • 7.6 Таблицы BDB или BerkeleyDB
      • 7.6.1 Обзор таблиц BDB
      • 7.6.2 Установка BDB
      • 7.6.3 Параметры запуска BDB
      • 7.6.4 Характеристики таблиц BDB
      • 7.6.5 Что нам нужно исправить в BDB в ближайшем будущем:
      • 7.6.6 Операционные системы, поддерживаемые BDB
      • 7.6.7 Ограничения таблиц BDB
      • 7.6.8 Ошибки, которые могут возникнуть при использовании таблиц BDB
  • 8 Интерфейсы для MySQL
    • 8.1 Интерфейс PHP API для MySQL
      • 8.1.1 Общие проблемы MySQL и PHP
    • 8.2 Интерфейс Perl API для MySQL
      • 8.2.1 DBI с помощью DBD::mysql
      • 8.2.2 Интерфейс DBI
      • 8.2.3 Больше информации по DBI/DBD
    • 8.3 Поддержка ODBC в MySQL
      • 8.3.1 Как установить MyODBC
      • 8.3.2 Как заполнять различные поля в Администраторе ODBC
      • 8.3.3 Параметры подключения для MyODBC
      • 8.3.4 Как сообщать о проблемах с MyODBC
      • 8.3.5 Программы, работающие с MyODBC
      • 8.3.6 Как получить значение столбца AUTO_INCREMENT в ODBC
      • 8.3.7 Составление отчетов о проблемах с MyODBC
    • 8.4 Интерфейс C для MySQL
      • 8.4.1 Типы данных C API
      • 8.4.2 Обзор функций интерфейса C
      • 8.4.3 Описание функций интерфейса C
        • 8.4.3.1 mysql_affected_rows()
        • 8.4.3.2 mysql_change_user()
        • 8.4.3.3 mysql_character_set_name()
        • 8.4.3.4 mysql_close()
        • 8.4.3.5 mysql_connect()
        • 8.4.3.6 mysql_create_db()
        • 8.4.3.7 mysql_data_seek()
        • 8.4.3.8 mysql_debug()
        • 8.4.3.9 mysql_drop_db()
        • 8.4.3.10 mysql_dump_debug_info()
        • 8.4.3.11 mysql_eof()
        • 8.4.3.12 mysql_errno()
        • 8.4.3.13 mysql_error()
        • 8.4.3.14 mysql_escape_string()
        • 8.4.3.15 mysql_fetch_field()
        • 8.4.3.16 mysql_fetch_field_direct()
        • 8.4.3.17 mysql_fetch_fields()
        • 8.4.3.18 mysql_fetch_lengths()
        • 8.4.3.19 mysql_fetch_row()
        • 8.4.3.20 mysql_field_count()
        • 8.4.3.21 mysql_field_seek()
        • 8.4.3.22 mysql_field_tell()
        • 8.4.3.23 mysql_free_result()
        • 8.4.3.24 mysql_get_client_info()
        • 8.4.3.25 mysql_get_server_version()
        • 8.4.3.26 mysql_get_host_info()
        • 8.4.3.27 mysql_get_proto_info()
        • 8.4.3.28 mysql_get_server_info()
        • 8.4.3.29 mysql_info()
        • 8.4.3.30 mysql_init()
        • 8.4.3.31 mysql_insert_id()
        • 8.4.3.32 mysql_kill()
        • 8.4.3.33 mysql_list_dbs()
        • 8.4.3.34 mysql_list_fields()
        • 8.4.3.35 mysql_list_processes()
        • 8.4.3.36 mysql_list_tables()
        • 8.4.3.37 mysql_num_fields()
        • 8.4.3.38 mysql_num_rows()
        • 8.4.3.39 mysql_options()
        • 8.4.3.40 mysql_ping()
        • 8.4.3.41 mysql_query()
        • 8.4.3.42 mysql_real_connect()
        • 8.4.3.43 mysql_real_escape_string()
        • 8.4.3.44 mysql_real_query()
        • 8.4.3.45 mysql_reload()
        • 8.4.3.46 mysql_row_seek()
        • 8.4.3.47 mysql_row_tell()
        • 8.4.3.48 mysql_select_db()
        • 8.4.3.49 mysql_shutdown()
        • 8.4.3.50 mysql_stat()
        • 8.4.3.51 mysql_store_result()
        • 8.4.3.52 mysql_thread_id()
        • 8.4.3.53 mysql_use_result()
      • 8.4.4 Описания функций C, связанных с потоками
        • 8.4.4.1 my_init()
        • 8.4.4.2 mysql_thread_init()
        • 8.4.4.3 mysql_thread_end()
        • 8.4.4.4 mysql_thread_safe()
      • 8.4.5 Описания функций C, доступных во встраиваемом сервере
        • 8.4.5.1 mysql_server_init()
        • 8.4.5.2 mysql_server_end()
      • 8.4.6 Основные вопросы и проблемы в использовании интерфейса C
        • 8.4.6.1 Почему после успешных возвратов функции mysql_query() функция mysql_store_result() иногда возвращает NULL?
        • 8.4.6.2 Какие результаты можно получить из запроса?
        • 8.4.6.3 Как получить уникальный идентификатор для последней внесенной строки?
        • 8.4.6.4 Проблемы линкования с интерфейсом C
      • 8.4.7 Сборка клиентских программ
      • 8.4.8 Как создать клиентскую программу с потоками
      • 8.4.9 libmysqld, встраиваемая библиотека сервера MySQL
        • 8.4.9.1 Обзор библиотеки встраиваемого сервера MySQL
        • 8.4.9.2 Компиляция программ с libmysqld
        • 8.4.9.3 Ограничения при использовании встраиваемого сервера MySQL
        • 8.4.9.4 Использование файлов опций с встраиваемым сервером
        • 8.4.9.5 Что осталось сделать по встраиваемомуому серверу (TODO)
        • 8.4.9.6 Пример простого встраиваемого сервера
        • 8.4.9.7 Лицензирование встраиваемого сервера
    • 8.5 Интерфейсы C++
      • 8.5.1 Интерфейс Borland C++
    • 8.6 Взаимодействие MySQL и Java (JDBC)
    • 8.7 Интерфейсы Python API для MySQL
    • 8.8 Интерфейсы Tcl API для MySQL
    • 8.9 Оболочка Eiffel для MySQL
  • 9 Расширение MySQL
    • 9.1 Внутреннее устройство MySQL
      • 9.1.1 Потоки MySQL
      • 9.1.2 Пакет тестирования MySQL
        • 9.1.2.1 Выполнение тестового пакета MySQL
        • 9.1.2.2 Расширение тестового пакета MySQL
        • 9.1.2.3 Отчет об ошибках в тестовом пакете MySQL
    • 9.2 Добавление новых функций в MySQL
      • 9.2.1 Синтаксис CREATE FUNCTION/DROP FUNCTION
      • 9.2.2 Добавление новой определяемой пользователем функции
        • 9.2.2.1 Последовательность вызова UDF для простых функций
        • 9.2.2.2 Последовательность вызова UDF для агрегатных функций
        • 9.2.2.3 Обработка аргументов
        • 9.2.2.4 Возвращаемые значения и обработка ошибок
        • 9.2.2.5 Компиляция и установка определяемых пользователем функций
      • 9.2.3 Добавление новых родных функции
    • 9.3 Добавление новой процедуры в MySQL
      • 9.3.1 Процедура Analyse
      • 9.3.2 Написание процедуры
  • A Проблемы и распространенные ошибки
    • A.1 Как определить, чем вызваны проблемы
    • A.2 Распространенные ошибки при использовании MySQL
      • A.2.1 Ошибка Access denied
      • A.2.2 Ошибка MySQL server has gone away
      • A.2.3 Ошибка Can't connect to [local] MySQL server
      • A.2.4 Ошибка Host '...' is blocked
      • A.2.5 Ошибка Too many connections
      • A.2.6 Ошибка Some non-transactional changed tables couldn't be rolled back
      • A.2.7 Ошибка Out of memory
      • A.2.8 Ошибка Packet too large
      • A.2.9 Коммуникационные ошибки / Оборванные соединения
      • A.2.10 Ошибка The table is full
      • A.2.11 Ошибка Can't create/write to file
      • A.2.12 Ошибка в клиенте Commands out of sync
      • A.2.13 Ошибка Ignoring user
      • A.2.14 Ошибка Table 'xxx' doesn't exist
      • A.2.15 Ошибка Can't initialize character set xxx
      • A.2.16 Не найден файл (File not found)
    • A.3 Вопросы, связанные с инсталляцией
      • A.3.1 Проблемы при линковании с клиентской библиотекой MySQL
      • A.3.2 Запуск MySQL от обычного пользователя
      • A.3.3 Проблемы с правами доступа к файлам
    • A.4 Вопросы, связанные с администрированием
      • A.4.1 Что делать, если работа MySQL сопровождается постоянными сбоями
      • A.4.2 Как переустановить забытый пароль пользователя root
      • A.4.3 Как MySQL реагирует на переполнение диска
      • A.4.4 Где MySQL хранит временные файлы
      • A.4.5 Как защитить или изменить сокет-файл MySQL `/tmp/mysql.sock'
      • A.4.6 Проблемы с часовыми поясами
    • A.5 Проблемы, относящиеся к запросам
      • A.5.1 Чувствительность к регистру при поиске
      • A.5.2 Проблемы с использованием столбцов типа DATE
      • A.5.3 Проблемы со значением NULL
      • A.5.4 Проблемы с alias
      • A.5.5 Удаление строк из взаимосвязанных таблиц
      • A.5.6 Решение проблем с отсутствием строк, удовлетворяющих условиям поиска
      • A.5.7 Проблемы со сравнением чисел с плавающей точкой
    • A.6 Вопросы, связанные с определением таблиц
      • A.6.1 Проблемы с ALTER TABLE
      • A.6.2 Как изменить порядок столбцов в таблице
      • A.6.3 Проблемы, относящиеся к временным (TEMPORARY) таблицам
  • B Благодарности
    • B.1 Разработчики MySQL AB
    • B.2 Наши помощники, которые сделали вклад в развитие MySQL
    • B.3 Спонсоры MySQL
  • C История изменений и обновлений MySQL
    • C.1 Изменения в версии 4.1.x (Alpha)
      • C.1.1 Изменения в версии 4.1.0
    • C.2 Изменения в версии 4.0.x (В разработке; Альфа)
      • C.2.1 Изменения в версии 4.0.2
      • C.2.2 Изменения в версии 4.0.1 (23 Дек 2001)
      • C.2.3 Изменения в версии 4.0.0 (Окт 2001: Альфа)
    • C.3 Изменения в версии 3.23.x (Стабильная)
      • C.3.1 Изменения в версии 3.23.52
      • C.3.2 Изменения в версии 3.23.51 (31 Май 2002)
      • C.3.3 Изменения в версии 3.23.50 (21 Апр 2002)
      • C.3.4 Изменения в версии 3.23.49
      • C.3.5 Изменения в версии 3.23.48 (07 Фев 2002)
      • C.3.6 Изменения в версии 3.23.47 (27 Дек 2001)
      • C.3.7 Изменения в версии 3.23.46 (29 Ноя 2001)
      • C.3.8 Изменения в версии 3.23.45 (22 Ноя 2001)
      • C.3.9 Изменения в версии 3.23.44 (31 Окт 2001)
      • C.3.10 Изменения в версии 3.23.43
      • C.3.11 Изменения в версии 3.23.42 (08 Сен 2001)
      • C.3.12 Изменения в версии 3.23.41 (11 Авг 2001)
      • C.3.13 Изменения в версии 3.23.40
      • C.3.14 Изменения в версии 3.23.39 (12 Июн 2001)
      • C.3.15 Изменения в версии 3.23.38 (09 Май 2001)
      • C.3.16 Изменения в версии 3.23.37 (17 Апр 2001)
      • C.3.17 Изменения в версии 3.23.36 (27 Мар 2001)
      • C.3.18 Изменения в версии 3.23.35 (15 Мар 2001)
      • C.3.19 Изменения в версии 3.23.34a
      • C.3.20 Изменения в версии 3.23.34 (10 Мар 2001)
      • C.3.21 Изменения в версии 3.23.33 (09 Фев 2001)
      • C.3.22 Изменения в версии 3.23.32 (22 Янв 2001: Стабильная)
      • C.3.23 Изменения в версии 3.23.31 (17 Янв 2001)
      • C.3.24 Изменения в версии 3.23.30 (04 Янв 2001)
      • C.3.25 Изменения в версии 3.23.29 (16 Дек 2000)
      • C.3.26 Изменения в версии 3.23.28 (22 Ноя 2000: Гамма)
      • C.3.27 Изменения в версии 3.23.27 (24 Окт 2000)
      • C.3.28 Изменения в версии 3.23.26
      • C.3.29 Изменения в версии 3.23.25
      • C.3.30 Изменения в версии 3.23.24 (08 Сен 2000)
      • C.3.31 Изменения в версии 3.23.23
      • C.3.32 Изменения в версии 3.23.22 (31 Июл 2000)
      • C.3.33 Изменения в версии 3.23.21
      • C.3.34 Изменения в версии 3.23.20
      • C.3.35 Изменения в версии 3.23.19
      • C.3.36 Изменения в версии 3.23.18
      • C.3.37 Изменения в версии 3.23.17
      • C.3.38 Изменения в версии 3.23.16
      • C.3.39 Изменения в версии 3.23.15 (Май 2000: Бета)
      • C.3.40 Изменения в версии 3.23.14
      • C.3.41 Изменения в версии 3.23.13
      • C.3.42 Изменения в версии 3.23.12
      • C.3.43 Изменения в версии 3.23.11
      • C.3.44 Изменения в версии 3.23.10
      • C.3.45 Изменения в версии 3.23.9
      • C.3.46 Изменения в версии 3.23.8
      • C.3.47 Изменения в версии 3.23.7
      • C.3.48 Изменения в версии 3.23.6
      • C.3.49 Изменения в версии 3.23.5
      • C.3.50 Изменения в версии 3.23.4
      • C.3.51 Изменения в версии 3.23.3
      • C.3.52 Изменения в версии 3.23.2
      • C.3.53 Изменения в версии 3.23.1
      • C.3.54 Изменения в версии 3.23.0 (Сен 1999: Альфа)
    • C.4 Изменения в версии 3.22.x (Старая; все еще поддерживается)
      • C.4.1 Изменения в версии 3.22.35
      • C.4.2 Изменения в версии 3.22.34
      • C.4.3 Изменения в версии 3.22.33
      • C.4.4 Изменения в версии 3.22.32
      • C.4.5 Изменения в версии 3.22.31
      • C.4.6 Изменения в версии 3.22.30
      • C.4.7 Изменения в версии 3.22.29
      • C.4.8 Изменения в версии 3.22.28
      • C.4.9 Изменения в версии 3.22.27
      • C.4.10 Изменения в версии 3.22.26
      • C.4.11 Изменения в версии 3.22.25
      • C.4.12 Изменения в версии 3.22.24
      • C.4.13 Изменения в версии 3.22.23
      • C.4.14 Изменения в версии 3.22.22
      • C.4.15 Изменения в версии 3.22.21
      • C.4.16 Изменения в версии 3.22.20
      • C.4.17 Изменения в версии 3.22.19 (Мар 1999: Стабильная)
      • C.4.18 Изменения в версии 3.22.18
      • C.4.19 Изменения в версии 3.22.17
      • C.4.20 Изменения в версии 3.22.16 (Фев 1999: Гамма)
      • C.4.21 Изменения в версии 3.22.15
      • C.4.22 Изменения в версии 3.22.14
      • C.4.23 Изменения в версии 3.22.13
      • C.4.24 Изменения в версии 3.22.12
      • C.4.25 Изменения в версии 3.22.11
      • C.4.26 Изменения в версии 3.22.10
      • C.4.27 Изменения в версии 3.22.9
      • C.4.28 Изменения в версии 3.22.8
      • C.4.29 Изменения в версии 3.22.7 (Сен 1998: Бета)
      • C.4.30 Изменения в версии 3.22.6
      • C.4.31 Изменения в версии 3.22.5
      • C.4.32 Изменения в версии 3.22.4
      • C.4.33 Изменения в версии 3.22.3
      • C.4.34 Изменения в версии 3.22.2
      • C.4.35 Изменения в версии 3.22.1 (Июн 1998: Альфа)
      • C.4.36 Изменения в версии 3.22.0
    • C.5 Изменения в версии 3.21.x
      • C.5.1 Изменения в версии 3.21.33
      • C.5.2 Изменения в версии 3.21.32
      • C.5.3 Изменения в версии 3.21.31
      • C.5.4 Изменения в версии 3.21.30
      • C.5.5 Изменения в версии 3.21.29
      • C.5.6 Изменения в версии 3.21.28
      • C.5.7 Изменения в версии 3.21.27
      • C.5.8 Изменения в версии 3.21.26
      • C.5.9 Изменения в версии 3.21.25
      • C.5.10 Изменения в версии 3.21.24
      • C.5.11 Изменения в версии 3.21.23
      • C.5.12 Изменения в версии 3.21.22
      • C.5.13 Изменения в версии 3.21.21a
      • C.5.14 Изменения в версии 3.21.21
      • C.5.15 Изменения в версии 3.21.20
      • C.5.16 Изменения в версии 3.21.19
      • C.5.17 Изменения в версии 3.21.18
      • C.5.18 Изменения в версии 3.21.17
      • C.5.19 Изменения в версии 3.21.16
      • C.5.20 Изменения в версии 3.21.15
      • C.5.21 Изменения в версии 3.21.14b
      • C.5.22 Изменения в версии 3.21.14a
      • C.5.23 Изменения в версии 3.21.13
      • C.5.24 Изменения в версии 3.21.12
      • C.5.25 Изменения в версии 3.21.11
      • C.5.26 Изменения в версии 3.21.10
      • C.5.27 Изменения в версии 3.21.9
      • C.5.28 Изменения в версии 3.21.8
      • C.5.29 Изменения в версии 3.21.7
      • C.5.30 Изменения в версии 3.21.6
      • C.5.31 Изменения в версии 3.21.5
      • C.5.32 Изменения в версии 3.21.4
      • C.5.33 Изменения в версии 3.21.3
      • C.5.34 Изменения в версии 3.21.2
      • C.5.35 Изменения в версии 3.21.0
    • C.6 Изменения в версии 3.20.x
      • C.6.1 Изменения в версии 3.20.18
      • C.6.2 Изменения в версии 3.20.17
      • C.6.3 Изменения в версии 3.20.16
      • C.6.4 Изменения в версии 3.20.15
      • C.6.5 Изменения в версии 3.20.14
      • C.6.6 Изменения в версии 3.20.13
      • C.6.7 Изменения в версии 3.20.11
      • C.6.8 Изменения в версии 3.20.10
      • C.6.9 Изменения в версии 3.20.9
      • C.6.10 Изменения в версии 3.20.8
      • C.6.11 Изменения в версии 3.20.7
      • C.6.12 Изменения в версии 3.20.6
      • C.6.13 Изменения в версии 3.20.3
      • C.6.14 Изменения в версии 3.20.0
    • C.7 Изменения в версии 3.19.x
      • C.7.1 Изменения в версии 3.19.5
      • C.7.2 Изменения в версии 3.19.4
      • C.7.3 Изменения в версии 3.19.3
  • D Перенос на другие системы
    • D.1 Отладка сервера MySQL
      • D.1.1 Компиляция MySQL для отладки
      • D.1.2 Создание трассировочных файлов
      • D.1.3 Отладка mysqld при помощи gdb
      • D.1.4 Использование трассировки стека
      • D.1.5 Использование журналов для определения причин ошибок в mysqld
      • D.1.6 Создание контрольного примера при повреждении таблиц
    • D.2 Отладка клиента MySQL
    • D.3 Пакет DBUG
    • D.4 Методы блокировки
    • D.5 Замечания по потокам RTS
    • D.6 Различия между разными потоковыми пакетами
  • E Переменные окружения
  • F Регулярные выражения в MySQL
  • G GNU General Public License
    • 9.4 Preamble
  • H GNU Lesser General Public License
  • Команды SQL, функциональное оглавление
  • Концептуальное оглавление


Справочное руководство по MySQL версии 5.0.0-alpha. - 1 Общая информация

 Go to the first, previous, next, last section, table of contents.

1 Общая информация

Программное обеспечение MySQL (TM) представляет собой очень быстрый многопоточный, многопользовательский надежный SQL-сервер баз данных (SQL - язык структурированных запросов). Сервер MySQL предназначен как для критических по задачам производственных систем с большой нагрузкой, так и для встраивания в программное обеспечение массового распространения.

MySQL - это торговая марка MySQL АВ.

Программное обеспечение MySQL имеет двойное лицензирование. Это означает, что пользователи могут выбирать, использовать ли ПО MySQL бесплатно по общедоступной лицензии GNU General Public License (GPL) или приобрести одну из стандартных коммерческих лицензий MySQL AB. (http://www.gnu.org/licenses/).

Для получения самой свежей информации о программном обеспечении MySQL обращайтесь на веб-сайт MySQL (http://www.mysql.com/).

Ниже перечислены наиболее интересные разделы данного руководства.

  • Информация о компании, которая занимается разработкой и распространением ПО MySQL, находится в разделе section 1.5 Что представляет собой компания MySQL AB?.
  • Основные возможности сервера MySQL рассматриваются в разделе section 1.4.2 Основные возможности MySQL.
  • Инструкции по инсталляции приведены в разделе section 2 Установка MySQL.
  • Советы по переносу на другие архитектуры и операционные системы вы найдете в разделе section D Перенос на другие системы.
  • Информация по апгрейду с версии 3.23 находится в разделе section 2.5.2 Модернизация с версии 3.23 до версии 4.0
  • Информация по апгрейду с версии 3.22 находится в разделе section 2.5.3 Модернизация с версии 3.22 до версии 3.23
  • Введение в обучающий курс по серверу MySQL см. в разделе section 3 Учебное пособие по MySQL.
  • Примеры по SQL и данные по тестам производительности находятся в директории тестов производительности (`sql-bench' в дистрибутиве).
  • Информацию о новых возможностях и об исправлениях ошибок см. в разделе section C История изменений и обновлений MySQL.
  • Список известных на сегодняшний день ошибок и конструктивных дефектов см. в разделе section 1.9.5 Известные ошибки и недостатки проектирования в MySQL.
  • Планы развития MySQL см. в разделе section 1.10 MySQL и будущее (что предстоит сделать).
  • Полный список тех людей, которые сделали вклад в наш проект, вы найдете в разделе section B Благодарности.

Что важно:

Отчеты об ошибках (bugs), а также вопросы и комментарии следует посылать по адресу mysql@lists.mysql.com. See section 1.8.1.3 Как отправлять отчеты об ошибках или проблемах. Для составления отчетов об ошибках следует использовать сценарий mysqlbug. В поставках исходного текста сценарий mysqlbug находится в директории scripts. Если у вас бинарная поставка, то сценарий mysqlbug следует искать в директории `bin'.

Если вы обнаружите существенную ошибку, относящуюся к безопасности в сервере MySQL, следует сообщить об этом по адресу: security@mysql.com.

1.1 Об этом руководстве

Это - справочное руководство по MySQL; оно представляет собой документацию по MySQL версии 5.0.0-alpha. Функциональные изменения отмечены номером версии, в которой они произведены, поэтому это руководство будет полезно при освоении также и более старых версий MySQL.

Поскольку данный материал носит чисто справочный характер, в нем не содержится основных положений SQL или сведений по реляционным базам данных.

Руководство часто обновляется, поскольку ПО СУБД MySQL находится в состоянии постоянного развития. Самая последняя версия данного руководства доступна по адресу http://www.mysql.com/documentation/ в различных форматах, включая HTML, PDF и Windows HLP.

Исходным документом для всех версий документации является файл Texinfo. HTML-версия генерируется автоматически модифицированной версией texi2html. Текстовая и Info-версии генерируются при помощи makeinfo, PostScript-версия создается texi2dvi и dvips. PDF-версия генерируется с помощью pdftex.

Если найти нужную информацию в руководстве не удается, можно прибегнуть к помощи версии руководства с функцией поиска, находящейся по адресу http://www.mysql.com/doc/.

Группа, работающая над документацией, рассмотрит любые предложения по дополнению или исправлению данного руководства. Их следует отправлять по адресу docs@mysql.com.

Данное руководство было изначально написано Дэвидом Аксмарком (David Axmark) и Майклом (Монти) Видениусом (Michael (Monty) Widenius). Сейчас это руководство поддерживается Майклом (Монти) Видениусом, Полом Дюбуа (Paul DuBois), Арйен Ленц (Arjen Lentz). Остальные разработчики упомянуты в разделе section B Благодарности.

Авторское право (2003) на данное руководство принадлежит шведской компании MySQL AB. See section 1.6.2 Авторские права и лицензии на MySQL.

1.2 Соглашения, используемые в данном руководстве

В данном руководстве используются следующие обозначения:

Моноширинный
Для имен команд и опций; SQL-операторов; имен баз данных, таблиц, столбцов; кода на C и Perl, переменных окружения применяется моноширинный шрифт. Например: ''Чтобы увидеть, как работает mysqladmin, запустите его с опцией --help.''
`filename'
Моноширинный шрифт и кавычки используются для имен файлов и путей. Например: "Дистрибутив устанавливается в каталог `/usr/local/'".
`c'
Для представления последовательности символов используется моноширинный шрифт, а сама последовательность символов заключается в кавычки. Например: "Для задания шаблонного символа используется символ `%'".
Курсив
Курсив используется для выделения текста, подобно данному.
полужирный шрифт
Полужирный шрифт используется для заголовков таблиц и для того, чтобы особо выделить фрагмент текста.

Если нужно показать, что приведенная команда должна выполняться определенной программой, она предваряется подсказкой с именем этой программы. Например, shell> указывает, что команда будет выполняться вашей оболочкой, а mysql> означает, что команда будет выполняться клиентской программой mysql:

shell> набирайте команды оболочки здесь
mysql> набирайте SQL-операторы здесь

Для представления команд оболочки в данном руководстве применяется синтаксис оболочки Bourne. Если у вас используется csh-оболочка, синтаксис для нее будет несколько отличаться. Например, последовательность команд для установки переменной окружения и запуска команды в синтаксисе оболочки Bourne выглядит следующим образом:

shell> ПЕРЕМЕННАЯ=значение некая_команда

В случае csh-оболочки для выполнения тех же действий вам потребуются следующие команды:

shell> setenv ПЕРЕМЕННАЯ значение
shell> некая_команда

Часто в командах имена баз данных, таблиц, столбцов следует заменять конкретными значениями. Чтобы показать необходимость такой замены, в данном руководстве используются выражения типа db_name (имя базы данных), table_name (имя таблицы) и col_name (имя столбца). Например, в тексте руководства может встретиться оператор, подобный следующему:

mysql> SELECT col_name FROM db_name.table_name;

Это означает, что при вводе такого оператора вам необходимо будет указать собственную базу данных, имя таблицы и имя столбца, например:

mysql> SELECT author_name FROM biblio_db.author_list;

Ключевые слова SQL являются нечувствительными к регистру, поэтому их можно записывать, используя как прописные, так и строчные буквы. В данном руководстве используется регистр прописных букв.

Для представления необязательных слов и выражений в синтаксических описаниях используются квадратные скобки (`[' и `]'). Например, в приведенном ниже операторе выражение IF EXISTS является необязательным:

DROP TABLE [IF EXISTS] имя_таблицы

Если элемент синтаксиса состоит из ряда альтернативных элементов, последние отделяются друг от друга вертикальными чертами (`|' ). В случае, когда может быть выбран один элемент из такого ряда, альтернативные элементы заключаются в квадратные скобки (`[' и `]'):

TRIM([[BOTH | LEADING | TRAILING] [remstr] FROM] str)

В случае, когда должен быть выбран один элемент из такого ряда, альтернативные элементы заключаются в фигурные скобки (`{' и `}'):

{DESCRIBE | DESC } имя_таблицы {имя_столбца | wild}

1.3 О русском переводе руководства

Русский перевод документации на ПО СУБД MySQL выполнен в 2002-2003гг. компанией Ensita.NET (http://www.ensita.net/).

Переводчики: (в алфавитном порядке) Василюк Елена, Добродеев Сергей, Закиянов Денис, Коротун Юрий, Пономарев Алексей, Ченцов Алексей; а также Жданов Сергей (раздел "Интерфейс DBI").

Научная редакция: Егор Егоров, Людмила Мезенко, Виктория Резниченко.

Литературный редактор: Людмила Мезенко (the best!)

Главный редактор перевода: Егор Егоров

Все замечания по русской документации направляйте по адресу docs-team@ensita.net.

* * * * *

Компания Ensita.NET (http://www.ensita.net/), являясь официальным партнером MySQL AB с января 2002г. консультирует пользователей ПО СУБД MySQL по всему миру, поддерживая список рассылки mysql@lists.mysql.com (see section 1.8.1.1 Списки рассылки MySQL).

Ensita.NET с 1999г. занимается разработкой программного обеспечения для веб-сайтов, обслуживанием СУБД и консалтингом.

1.3.1 Список терминов, принятых в русском переводе

Редакционная коллегия при подготовке этого перевода старалась как можно адекватнее перевести специфические термины с английского языка на русский. Нами была поставлена цель создать справочное руководство на живом и понятном языке, но в то же время не переходить на чистый сленг. Поэтому терминология, принятая в этом переводе, возможно, не полностью соответствует четким терминам, принятым в русскоязычной литературе на "около-реляционную" тему.

Для ясности понимания мы включаем в документацию список принятых в этом переводе терминов.

Термин | Значение
account | аккаунт, учетная запись
ACL | списки контроля доступа
banner | баннер
benchmark page | страничка тестов производительности
Berkeley-style copyright | лицензия наподобие Berkeley
binary release, binary distribution | бинарная поставка, двоичная поставка
cache | кэш
case sensitive | чувствительный к регистру, регистро-зависимый
change history | история изменений
charset | набор символов, кодировка
client/server | клиент-серверный
command-line tool | утилита командной строки
commit | принять; commit transaction - принять транзакцию
communication protocol | коммуникационный протокол
contact form | форма. fill in the contact form - заполните форму
data dir | каталог с данными
datadir, data dir | каталог datadir, каталог данных
date type | тип даты
DBA | администратор (физическое лицо)
dbms | см. rdbms
ddos | distributed dos - распределенная атака создания отказа в обслуживании
denial of service | отказ в обслуживании
deployment | распространение
distribution | поставка, дистрибутив
distributor | производитель
dos | см. denial of service
embedded | встраиваемый. Не "встроенный"
environment variables | переменные окружения
escape chars | символы экранирования
escaped chars | экранированные символы
extended regular expression | расширенное регулярное выражение
fail-safe | отказобезопасный
feature | возможность, особенность
firewall | брандмауэр
flush | сброс, очистка, перегрузка
foreign key constraint | ограничения внешних ключей
full precision | полная точность
full-text | полнотекстовый
grant tables | таблицы привилегий
grants | привилегии
group | группа, группировка
group functions | групповые функции, операции группировки данных, операции над групповыми данными
host | удаленный компьютер
inserting data | добавление, вставка данных
join | связь
join optimizer | оптимизатор связей
key cache | кэш ключей
large-scale | широкомасштабный
license | лицензция
link | линкование (в контексте линкования компиляции программ)
localhost, local host | локальный хост, локальный компьютер
locking | блокировка
log | журнал
log position | точка положения в журнале репликации
login | см. account
login shell | первая оболочка входа (login shell)
master | (репликация) головной сервер
miscellaneous | разнообразный
multi-byte | мультибайтный
multi-layered | многоуровневый
multithread | многопоточный
mysql server | MySQL или сервер
mysql user | пользователь MySQL
non-updating queries | запросы, не изменяющие информацию
null | null
open source | система с открытым кодом (open source)
optional | опциональный
parser | синтаксический анализатор
patch | патч
port listening | слушание порта, слушать порт, ожидать соединение на порту
privacy | конфиденциальность
privilege | привилегии
qualifier | определитель
qualify | определять
rdbms | система управления реляционными базами данных
reference manual | справочник, руководство
regular client | обычный клиент
regular expression | регулярное выражение; extended - расширенное р.в.
released under gpl | выпущено под лицензией GPL
replica (server) | сервер с копиями
robustness | надежность, отказоустойчивость
rollback | откат
rotation | ротация
row-level locking | строчная блокировка
scope | контекст
script | сценарий, скрипт
security | безопасность
security issues | вопросы безопасности
SET | множество
silent | молчаливо
slave | (репликация) подчиненный сервер
snapshop | образ, снимок
socket | сокет
ssh port-forwarding | пересылка по SSH (SSH port-forwarding)
SSL connections | SSL-соединения
sticky | прилипчив
superuser | суперпользователь
symbol table | см. charset
symbol value | строкое значение
symlink | символическая ссылка
table handler | обработчик таблиц
thread | поток
time stamp | временная метка
timestamp | тип данных временной метки
TODO-list | список задач к выполнению
track | последовательность, протокол
transactional | транзакционный
trick | трюк, хитрость
unix socket, unix domain socket | unix-сокет
up-to-date | своевременный
utilities | инструментальные программы
vendor | поставщик
verbose | расширенный режим вывода сообщений
voting algorithm | алгоритм голосования
warning | предупреждение
wildcard | шаблон, шаблонные символы
wrapper | оболочка

1.4 Что представляет собой MySQL?

Разработку и сопровождение MySQL, самой популярной SQL-базы данных с открытым кодом, осуществляет компания MySQL AB. MySQL AB - коммерческая компания, основанная разработчиками MySQL, строящая свой бизнес, предоставляя различные сервисы для СУБД MySQL. See section 1.5 Что представляет собой компания MySQL AB?.

На веб-сайте MySQL (http://www.mysql.com/) представлена самая свежая информация о программном обеспечении MySQL и о компании MySQL AB.

MySQL - это система управления базами данных.
База данных представляет собой структурированную совокупность данных. Эти данные могут быть любыми - от простого списка предстоящих покупок до перечня экспонатов картинной галереи или огромного количества информации в корпоративной сети. Для записи, выборки и обработки данных, хранящихся в компьютерной базе данных, необходима система управления базой данных, каковой и является ПО MySQL. Поскольку компьютеры замечательно справляются с обработкой больших объемов данных, управление базами данных играет центральную роль в вычислениях. Реализовано такое управление может быть по-разному - как в виде отдельных утилит, так и в виде кода, входящего в состав других приложений.
MySQL - это система управления реляционными базами данных.
В реляционной базе данных данные хранятся не все скопом, а в отдельных таблицах, благодаря чему достигается выигрыш в скорости и гибкости. Таблицы связываются между собой при помощи отношений, благодаря чему обеспечивается возможность объединять при выполнении запроса данные из нескольких таблиц. SQL как часть системы MySQL можно охарактеризовать как язык структурированных запросов плюс наиболее распространенный стандартный язык, используемый для доступа к базам данных.
Программное обеспечение MySQL - это ПО с открытым кодом.
ПО с открытым кодом означает, что применять и модифицировать его может любой желающий. Такое ПО можно получать по Internet и использовать бесплатно. При этом каждый пользователь может изучить исходный код и изменить его в соответствии со своими потребностями. Использование программного обеспечения MySQL регламентируется лицензией GPL (GNU General Public License), http://www.gnu.org/licenses/, в которой указано, что можно и чего нельзя делать с этим программным обеспечением в различных ситуациях. Если работа в рамках GPL вас не устраивает или планируется встраивание MySQL-кода в коммерческое приложение, есть возможность купить коммерческую лицензированную версию у компании MySQL AB. See section 1.6.3 Лицензии на ПО MySQL.
В каких случаях следует отдавать предпочтение СУБД MySQL?
MySQL является очень быстрым, надежным и легким в использовании. Если вам требуются именно эти качества, попробуйте поработать с данным сервером. MySQL обладает также рядом удобных возможностей, разработанных в тесном контакте с пользователями. Сравнительные характеристики MySQL и других средств управления базами данных приведены на нашей странице тестов производительности (see section 5.1.4 Набор тестов MySQL (The MySQL Benchmark Suite)). Первоначально сервер MySQL разрабатывался для управления большими базами данных с целью обеспечить более высокую скорость работы по сравнению с существующими на тот момент аналогами. И вот уже в течение нескольких лет данный сервер успешно используется в условиях промышленной эксплуатации с высокими требованиями. Несмотря на то что MySQL постоянно совершенствуется, он уже сегодня обеспечивает широкий спектр полезных функций. Благодаря своей доступности, скорости и безопасности MySQL очень хорошо подходит для доступа к базам данных по Internet.
Технические возможности СУБД MySQL
Более детальную информацию по техническим возможностям MySQL можно получить в разделе section 6 Справочник по языку MySQL. ПО MySQL является системой клиент-сервер, которая содержит многопоточный SQL-сервер, обеспечивающий поддержку различных вычислительных машин баз данных, а также несколько различных клиентских программ и библиотек, средства администрирования и широкий спектр программных интерфейсов (API). Мы также поставляем сервер MySQL в виде многопоточной библиотеки, которую можно подключить к пользовательскому приложению и получить компактный, более быстрый и легкий в управлении продукт.
Доступно также большое количество программного обеспечения MySQL,
разработанного сторонними разработчиками. Вполне возможно, что СУБД MySQL уже поддерживается вашим любимым приложением или языком.

MySQL правильно произносится как ''Май Эс Кью Эль'' (а не ''майсиквел''), хотя никто не запрещает вам произносить эту аббревиатуру как ``майсиквел'' или еще каким-либо образом.

1.4.1 История MySQL

В один прекрасный день мы решили применить mSQL для доступа к нашим таблицам, для которых использовались собственные быстрые (ISAM) подпрограммы низкого уровня. Однако после тестирования мы пришли к заключению, что для наших целей скорость и гибкость mSQL недостаточны. В результате для базы данных был разработан новый SQL-интерфейс, но почти с тем же API-интерфейсом, что и mSQL. Этот API мы выбрали, чтобы упростить перенос на код сторонних разработчиков.

Происхождение имени MySQL не совсем ясно. Уже около 10 лет наша основная директория и большое количество библиотек и инструментария имеют префикс `my'. Более того, дочь Монти (она несколькими годами моложе) тоже получила имя My! Что из этих двух факторов повлияло на имя - до сих пор остается загадкой, даже для разработчиков.

1.4.2 Основные возможности MySQL

Ниже приведено описание важных характеристик программного обеспечения MySQL. See section 1.7 Кратко о MySQL 4.x.

Внутренние характеристики и переносимость
  • Написан на C и C++. Протестирован на множестве различных компиляторов.
  • Работает на различных платформах. See section 2.2.5 Операционные системы, поддерживаемые MySQL.
  • Для обеспечения переносимости используется GNU Automake, Autoconf и Libtool.
  • API для C, C++, Eiffel, Java, Perl, PHP, Python, Ruby и Tcl. See section 8 Интерфейсы для MySQL.
  • Полностью многопоточный с использованием потоков ядра. Это означает, что, если такая возможность обеспечивается, можно легко организовать работу с несколькими процессорами.
  • Очень быстрые дисковые таблицы на основе В-деревьев со сжатием индексов.
  • Очень быстрая базирующаяся на потоках система распределения памяти.
  • Очень быстрые соединения, использующие оптимизированный метод однопроходного мультисоединения (one-sweep multi-join).
  • Хеш-таблицы в памяти, используемые как временные таблицы.
  • SQL-функции реализованы при помощи хорошо оптимизированной библиотеки классов, поэтому они выполняются настолько быстро, насколько это возможно. Обычно после инициализации запроса распределения памяти не происходит вообще.
  • MySQL- код протестирован с использованием Purify (коммерческий детектор утечки памяти), а также Valgrind, одного из GPL-инструментов (http://developer.kde.org/~sewardj/
Типы столбцов
  • Большое количество: целочисленные со знаком/беззнаковые, длиной в 1, 2, 3, 4 и 8 байтов, FLOAT, DOUBLE, CHAR, VARCHAR, TEXT, BLOB, DATE, TIME, DATETIME, TIMESTAMP, YEAR, SET и ENUM. See section 6.2 Типы данных столбцов.
  • С записями фиксированной и переменной длины.
  • Все столбцы имеют значения по умолчанию. С помощью INSERT можно вставить подмножество столбцов таблицы; столбцы, для которых явно не заданы значения, устанавливаются в значения по умолчанию.
Команды и функции
  • Полная поддержка операторов и функций в SELECT- и WHERE- частях запросов. Например:
    mysql> SELECT CONCAT(first_name, " ", last_name)
    -> FROM tbl_name
    -> WHERE income/dependents > 10000 AND age > 30;
  • Полная поддержка для операторов SQL GROUP BY и ORDER BY с выражениями SQL. Поддержка групповых функций (COUNT(), COUNT(DISTINCT ...), AVG(), STD(), SUM(), MAX() и MIN()).
  • Поддержка LEFT OUTER JOIN и RIGHT OUTER JOIN с синтаксисом ANSI SQL и ODBC.
  • Разрешены псевдонимы для таблиц и столбцов в соответствии со стандартом SQL92.
  • DELETE, INSERT, REPLACE, and UPDATE возвращают число строк, которые были изменены. Вместо этого можно задать возвращение совпавших строк. Для этого следует установить флаг при соединении с сервером.
  • Команду SHOW, которая является специфической для MySQL, можно использовать для получения информации о базах данных, таблицах и индексах. Чтобы выяснить, как оптимизатор выполняет запрос, можно применять команду EXPLAIN.
  • Имена функций не конфликтуют с именами таблиц и столбцов. Например, ABS является корректным именем столбца. Для вызова функции существует только одно ограничение: между именем функции и следующей за ним открывающей скобкой `(' не должно быть пробелов. See section 6.1.7 ``Придирчив'' ли MySQL к зарезервированным словам?.
  • В одном и том же запросе могут указываться таблицы из различных баз данных (с версии 3.22).
Безопасность
  • Система, основанная на привилегиях и паролях, за счет чего обеспечивается гибкость и безопасность, и с возможностью верификации с удаленного компьютера. Пароли защищены, т.к. они при передаче по сети при соединении с сервером шифруются.
Масштабируемость и ограничения
  • Управляет очень большими базами данных. Компания MySQL AB. использует MySQL для работы с несколькими базами данных, которые содержат 50 миллионов записей, кроме того, нам известны пользователи, использующие MySQL для работы с 60000 таблицами, включающими около 5000000000 строк.
  • Для каждой таблицы разрешается иметь до 32 индексов. Каждый индекс может содержать от 1 до 16 столбцов или частей столбцов. Максимальная ширина индекса 500 бит (это значение может быть изменено при компиляции MySQL). Для индекса может использоваться префикс поля CHAR или VARCHAR.
Установка соединений
  • Клиенты могут соединяться с MySQL, используя сокеты TCP/IP, сокеты Unix или именованные каналы (named pipes, под NT).
  • Поддержка ODBC (Open-DataBase-Connectivity) для Win32 (с исходным кодом). Все функции ODBC 2.5 и многие другие. Например, для соединения с MySQL можно использовать MS Access. See section 8.3 Поддержка ODBC в MySQL.
Локализация
  • Сервер может обеспечивать сообщения об ошибках для клиентов на различных языках. See section 4.6.2 Сообщения об ошибках на языках, отличных от английского.
  • Полная поддержка нескольких различных кодировок, включая ISO-8859-1 (Latin1), немецкий, big5, ujis и многие другие. Например, скандинавские символы разрешены в именах таблиц и столбцов.
  • Для хранения всех данных используется выбранный набор символов. Все сравнения для столбцов с нормальными строками проводятся с учетом регистра символов.
  • Сортировка производится согласно выбранному алфавиту (по умолчанию используется шведский). Эту установку можно изменить при запуске сервера MySQL. Чтобы ознакомиться с примером очень грамотной сортировки, можно обратиться к коду сортировки для чешского языка. MySQL поддерживает много различных кодировок, которые можно задавать во время компиляции и в процессе работы.
Клиенты и инструментарий
  • Включает myisamchk, очень быструю утилиту для проверки, оптимизации и восстановления таблиц. Все функциональные возможности myisamchk также доступны через SQL-интерфейс. See section 4 Администрирование баз данных.
  • Все MySQL-программы можно запускать с опциями --help или -? для получения помощи.

1.4.3 Насколько стабильным является MySQL?

Этот раздел дает ответ на следующие вопросы ''Насколько стабильным является MySQL?'' и ''Могу ли я положиться на MySQL в своем проекте?'' Мы попытаемся внести ясность в эти проблемы, а также ответить на некоторые важные вопросы, которые имеют значение для многих потенциальных пользователей. Информация данного раздела базируется на данных из списка рассылки, - наши пользователи очень активно сообщают нам о выявленных проблемах и о своем опыте использования нашего ПО.

Самые первые версии кода были созданы в начале 80-х. Это был устойчивый код с форматом таблиц ISAM, обеспечивающим обратную совместимость с предыдущими версиями. Во времена компании TcX, предшественника MySQL AB, с середины 1986 года код MySQL работал в проектах без каких-либо проблем. Но когда сервер MySQL был выпущен для широкого использования, оказалось, что существует несколько фрагментов ``непротестированного кода''. Эти фрагменты были быстро обнаружены новыми пользователями, которые составляли запросы в несколько ином виде, чем мы.

С каждым новым релизом количество проблем, связанных с переносимостью, уменьшалось (несмотря на то, что в каждом выпуске появлялось множество новых возможностей).

Каждый релиз MySQL был рабочим, проблемы возникали только при использовании кода из ``серых зон''. Естественно, что новые пользователи не знают о том, где находятся такие ``серые зоны''; в данном разделе сделана попытка описать те из них, которые известны на данный момент. Большая часть описания относится к версии 3.23 MySQL-сервера. В самой последней версии все известные ошибки устранены, за исключением тех, которые перечислены в разделе ошибок, а также конструктивных дефектов. See section 1.9.5 Известные ошибки и недостатки проектирования в MySQL.

Структура ПО MySQL является многоуровневой с независимыми модулями. Некоторые из новейших модулей перечислены ниже, причем по каждому дается информация о том, насколько хорошо он протестирован.

Репликация - Gamma
Большие серверные кластеры, в которых применяется репликация, находятся в промышленной эксплуатации и показывают хорошие результаты. Работа над средствами репликации в MySQL 4.x продолжается.
InnoDB-таблицы - стабильно (в 3.23 с 3.23.49)
Обработчик транзакционных InnoDB-таблиц объявлен в настоящее время стабильными в дереве MySQL 3.23, начиная с версии 3.23.49. InnoDB используется в больших промышленных системах с большой нагрузкой.
BDB-таблицы - Gamma
Код Berkeley DB очень устойчив, но на настоящий момент продолжается усовершенствование интерфейса обработчика транзакционных BDB-таблиц с MySQL, поэтому должно пройти некоторое время, пока он будет так же хорошо протестирован, как и таблицы других типов.
Полнотекстовый поиск - Beta
Полнотекстовый поиск работает, но широко не используется. В версии MySQL 4.0 реализованы существенные улучшения данной возможности.
MyODBC 2.50 (использующий ODBC SDK 2.5) - Gamma
Чрезвычайно широко используется. Как оказалось, некоторые из возникших проблем являются зависящими от приложения, а не от ODBC-драйвера или сервера баз данных.
Aвтоматическое восстановление MyISAM-таблиц - Gamma
Статус Gamma относится только к новому коду в обработчике таблиц, который проверяет правильность закрытия таблицы после ее открытия и выполняет автоматическую проверку/восстановление незакрытой таблицы.
Вставка больших объемов данных - Alpha
Новая возможность в MyISAM-таблицах в MySQL 4.0 для быстрой вставки большого количества строк.
Блокировка - Gamma
В большой степени зависит от системы. В некоторых системах возникают большие проблемы с использованием стандартной для ОС блокировки (fcntl()). В таких случаях следует запустить демон mysqld с флагом --skip-external-locking. Известно, что проблемы имеют место в некоторых системах Linux и в SunOS, когда используются NFS-монтированные файловые системы.

Несмотря на то, что высококвалифицированную поддержку MySQL AB обеспечивает за плату, в списке рассылки MySQL обычно можно получить ответы на часто возникающие вопросы. Ошибки обычно ликвидируются сразу же при помощи патчей, а серьезные дефекты почти всегда устраняются в новом выпуске.

1.4.4 Насколько большими могут быть таблицы в MySQL?

MySQL версии 3.22 имеет предел по размеру таблиц 4 Гб. В MySQL версии 3.23, где используется новый тип таблиц, максимальный размер таблицы доведен до 8 миллионов терабайтов (2 ^ 63 bytes).

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

Операционная система | Ограничения на размеры файла
32-разрядная Linux-Intel | 2Гб, 4Гб и более, в зависимости от версии Linux
Linux-Alpha | 8T (?)
Solaris 2.5.1 | 2 Гб (с патчем возможно 4Гб)
Solaris 2.6 | 4Гб (может быть изменено при помощи указания флага)
Solaris 2.7 Intel | 4 Гб
Solaris 2.7 UltraSPARC | 512 Гб

В Linux 2.2 существует возможность создавать таблицы с размерами более 2 Гб, используя патч LFS для файловой системы ext2. Существуют также патчи, обеспечивающие поддержку больших файлов для ReiserFS в Linux 2.4.

Как можно видеть, размер таблицы в базе данных MySQL обычно лимитируется операционной системой.

По умолчанию MySQL-таблицы имеют максимальный размер около 4 Гб. Для любой таблицы можно проверить/определить ее максимальный размер с помощью команд SHOW TABLE STATUS или myisamchk -dv table_name. See section 4.5.6 Синтаксис команды SHOW.

Если необходимы таблицы большего размера, чем 4 Гб (и используемая операционная система ``не возражает''), следует при создании такой таблицы задать параметры AVG_ROW_LENGTH и MAX_ROWS (see section 6.5.3 Синтаксис оператора CREATE TABLE). Эти параметры можно задать и позже - с помощью ALTER TABLE (see section 6.5.4 Синтаксис оператора ALTER TABLE).

Если большая таблица предназначена только для чтения, можно воспользоваться myisampack, чтобы слить несколько таблиц в одну и сжать ее. Обычно myisampack ужимает таблицу по крайней мере на 50%, поэтому в результате можно получить очень большие таблицы (see section 4.7.4 myisampack, MySQL-генератор сжатых таблиц (только для чтения)).

Есть еще одна возможность обойти ограничения операционной системы на размеры файлов данных MyISAM, - это делается при помощи опции RAID (see section 6.5.3 Синтаксис оператора CREATE TABLE).

Еще одним решением может быть использование функции MERGE, которая обеспечивает возможность обрабатывать набор идентичных таблиц как одну таблицу (see section 7.2 Таблицы MERGE).

1.4.5 Вопросы, связанные с Проблемой-2000

Сам MySQL не имеет проблем, связанных с Проблемой-2000 (Y2K):

  • В MySQL используются функции времени Unix, поэтому проблемы с датами, вплоть до 2069, исключены. Принимается, что все двузначные значения годов находятся в диапазоне с 1970 по 2069, поэтому число 01 в столбце с типом year MySQL обрабатывает как 2001.
  • Все MySQL-функции, обрабатывающие даты, хранятся в одном файле `sql/time.cc'. Их код был написан очень тщательно, чтобы застраховаться от проблем, связанных с 2000-м годом.
  • В версиях MySQL 3.22 и более поздних в столбцах с новым типом YEAR, который обеспечивает хранение нулевого 0 года и значений лет от 1901 до 2155 в одном байте, а также отображение дат при помощи 2 или 4 знаков.

Проблемы, связанные с 2000-м годом, могут возникнуть в приложениях, которые используют MySQL так, что это может оказаться небезопасным с точки зрения Y2K. Например, во многих старых приложениях для хранения и обработки значений годов используются 2-значные величины (которые можно трактовать неоднозначно), а не 4-значные. Эта проблема может быть урегулирована при помощи приложений, которые используют 00 или 99 как ``отсутствующие'' индикаторы значений.

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

Приведенный ниже код является наглядной демонстрацией того, что в MySQL Server проблемы с датами вплоть до 2030 года отсутствуют.

mysql> DROP TABLE IF EXISTS y2k;
Query OK, 0 rows affected (0.01 sec)

mysql> CREATE TABLE y2k (date DATE,
    -> date_time DATETIME,
    -> time_stamp TIMESTAMP);
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO y2k VALUES
    -> ("1998-12-31","1998-12-31 23:59:59",19981231235959),
    -> ("1999-01-01","1999-01-01 00:00:00",19990101000000),
    -> ("1999-09-09","1999-09-09 23:59:59",19990909235959),
    -> ("2000-01-01","2000-01-01 00:00:00",20000101000000),
    -> ("2000-02-28","2000-02-28 00:00:00",20000228000000),
    -> ("2000-02-29","2000-02-29 00:00:00",20000229000000),
    -> ("2000-03-01","2000-03-01 00:00:00",20000301000000),
    -> ("2000-12-31","2000-12-31 23:59:59",20001231235959),
    -> ("2001-01-01","2001-01-01 00:00:00",20010101000000),
    -> ("2004-12-31","2004-12-31 23:59:59",20041231235959),
    -> ("2005-01-01","2005-01-01 00:00:00",20050101000000),
    -> ("2030-01-01","2030-01-01 00:00:00",20300101000000),
    -> ("2050-01-01","2050-01-01 00:00:00",20500101000000);
Query OK, 13 rows affected (0.01 sec)
Records: 13 Duplicates: 0 Warnings: 0

mysql> SELECT * FROM y2k;
+------------+---------------------+----------------+
| date | date_time | time_stamp |
+------------+---------------------+----------------+
| 1998-12-31 | 1998-12-31 23:59:59 | 19981231235959 |
| 1999-01-01 | 1999-01-01 00:00:00 | 19990101000000 |
| 1999-09-09 | 1999-09-09 23:59:59 | 19990909235959 |
| 2000-01-01 | 2000-01-01 00:00:00 | 20000101000000 |
| 2000-02-28 | 2000-02-28 00:00:00 | 20000228000000 |
| 2000-02-29 | 2000-02-29 00:00:00 | 20000229000000 |
| 2000-03-01 | 2000-03-01 00:00:00 | 20000301000000 |
| 2000-12-31 | 2000-12-31 23:59:59 | 20001231235959 |
| 2001-01-01 | 2001-01-01 00:00:00 | 20010101000000 |
| 2004-12-31 | 2004-12-31 23:59:59 | 20041231235959 |
| 2005-01-01 | 2005-01-01 00:00:00 | 20050101000000 |
| 2030-01-01 | 2030-01-01 00:00:00 | 20300101000000 |
| 2050-01-01 | 2050-01-01 00:00:00 | 00000000000000 |
+------------+---------------------+----------------+
13 rows in set (0.00 sec)

Можно видеть, что при использовании типов DATE и DATETIME проблем с датами будущего не возникнет (эти типы ``справляются'' с датами вплоть до 9999 года).

Тип TIMESTAMP, который используется для сохранения текущего времени, имеет диапазон только до 2030-01-01. В 32-разрядных машинах TIMESTAMP тип имеет диапазон от 1970 до 2030 (значение со знаком). В 64-разрядных машинах этот тип ``справляется'' со значениями времени до 2106 года (значение без знака).

Таким образом, даже несмотря на то, что MySQL является Y2K-совместимым, ответственность за однозначную интерпретацию значений даты ложится на плечи пользователя. See section 6.2.2.1 Проблема 2000 года и типы данных, где приведены правила по работе MySQL с входными данными, которые имеют неоднозначные значения даты (данные, содержащие 2-значные значения года).

1.5 Что представляет собой компания MySQL AB?

MySQL AB - компания, в состав которой входят основатели MySQL и основные разработчики. MySQL AB создана в Швеции Дэвидом Аксмарком (David Axmark), Аланом Ларссом (Allan Larsson) и Майклом Монти Видениусом (Michael Monty Widenius).

Все разработчики сервера MySQL - штатные сотрудники компании. MySQL AB - виртуальная компания, состоящая из сотрудников, живущих в десятках стран по всему миру. Мы каждый день общаемся по Сети друг с другом, а также с нашими партнерами и пользователями.

Наша компания занимается разработкой и распространением СУБД MySQL и сопутствующего ПО. MySQL AB владеет всеми правами на исходный код MySQL, на логотип и торговую марку MySQL, а также на данное руководство (see section 1.4 Что представляет собой MySQL?).

Наши основные ценности - это то, что наша деятельность посвящена MySQL и идеям Open Source, открытого программного обеспечения.

Мы хотим, чтобы сервер MySQL соответствовал следующим критериям:

  • Лучший и популярнейший сервер СУБД в мире
  • Доступный всем
  • Простой в эксплуатации
  • Постоянно развивающийся не в ущерб скорости и безопасности
  • Работающий надежно
  • Удобный для использования и усовершенствования

MySQL AB и люди, работающие в MySQL AB:

  • Продвигают философию Open Source и поддерживают пользователей Open Source
  • Хорошие граждане
  • С удовольствием работают с партнерами, разделяющими нашу точку зрения и ценности
  • Отвечают на электронную почту и предоставляют поддержку пользователям
  • Является виртуальной командой, взаимодействующей через Internet
  • Работают ``против'' патентованного ПО

Свежая информация о MySQL и MySQL AB находится на сайте MySQL (http://www.mysql.com/).

1.5.1 Бизнес-модель и услуги, оказываемые компанией MySQL AB

Очень часто нам задают такой вопрос: ''Как вам удается зарабатывать на жизнь, ведь вы все раздаете бесплатно?''

Компания MySQL AB получает плату за поддержку, услуги, коммерческие лицензии и лицензионные платежи. Эти доходы вкладываются в разработку продукта и расширение бизнеса нашей компании.

Компания является прибыльной с момента своего основания. В октябре 2001 ряд ведущих скандинавских инвесторов и небольшая группа меценатов предоставили нам венчурный кредит. Эти капиталовложения идут на укрепление нашей бизнес-модели и создают основу устойчивого роста бизнеса компании.

1.5.1.1 Поддержка

Владельцами и руководителями компании MySQL AB являются ее основатели и ведущие разработчики ПО баз данных MySQL. В задачи разработчиков входит предоставление поддержки клиентам и другим пользователям, что обеспечивает нам возможность всегда быть в курсе их потребностей и проблем. Вся наша поддержка осуществляется квалифицированными разработчиками. Ответы на самые каверзные вопросы дает

Майкл Монти Вайдиниус (Michael Monty Widenius), главный автор MySQL Server. See section 1.6.1 Поддержка, предлагаемая компанией MySQL AB.

Для более подробной информации и заказа различных уровней поддержки обратитесь на веб-сайт https://order.mysql.com/ или свяжитесь с нашим отделом сбыта по адресу sales@mysql.com.

1.5.1.2 Обучение и сертификация

Компания MySQL AB проводит обучение по MySQL и другим смежным продуктам по всему миру. Мы предлагаем как общедоступные, так и внутрифирменные курсы, подготовленные в соответствии с конкретными потребностями вашей компании. Обучение по MySQL проводят также наши партнеры - авторизованные центры обучения по MySQL.

В наших учебных материалах в качестве примеров используются те же базы данных, что и в нашей документации и типовых приложениях. Эти материалы постоянно дополняются, чтобы соответствовать последней версии MySQL. Наши инструкторы опираются на поддержку коллектива разработчиков, что гарантирует качество обучения и постоянное совершенствование учебного материала. Благодаря тесной связи с разработчиками вы можете быть уверены также и в том, что какой бы вопрос ни возник у вас в процессе обучения, на него всегда будет найден ответ.

Обучение на наших курсах позволит вам достичь целей, которые вы ставите перед собой при создании своих MySQL-приложений. Помимо этого вы:

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

Если предлагаемое нами обучение интересует вас как потенциального участника нашего проекта или партнера в реализации учебных курсов, посетите учебный раздел на нашем веб-сайте http://www.mysql.com/training/ или свяжитесь с нами по адресу: training@mysql.com.

Для более подробной информации о программе сертификации MySQL, см. http://www.mysql.com/certification/.

1.5.1.3 Консультации

Компания MySQL AB и ее авторизованные партнеры предлагают по всему миру консультационные услуги для пользователей MySQL а также для разработчиков, встраивающих MySQL в свое программное обеспечение.

Наши консультанты окажут вам помощь в таких вопросах, как проектирование и настройка баз данных, создание эффективных запросов, настройка используемой вами платформы для достижения оптимальной эффективности работы, решение проблем миграции, реализация тиражирования, создание устойчивых приложений диалоговой обработки запросов, а также во многих других. Кроме того, мы помогаем нашим клиентам встраивать MySQL в их продукты и приложения, предназначенные для широкомасштабного распространения.

Наши консультанты работают в тесном сотрудничестве с коллективом разработчиков компании, что обеспечивает высокий технический уровень предоставляемых ими профессиональных услуг. Мы предлагаем широкий диапазон форм консультационной поддержки - от двухдневных интенсивных курсов до проектов продолжительностью в недели и месяцы. Наши консультации охватывают не только MySQL, но и языки программирования и сценариев, например PHP, Perl и многое другое.

Заинтересованных в наших консультационных услугах, а также тех, кто хотели бы стать нашими партнерами в оказании таких услуг, приглашаем посетить консультационный раздел на нашем веб-сайте http://www.mysql.com/consulting/ или связаться с нашим консультационным отделом по адресу consulting@mysql.com.

1.5.1.4 Коммерческие лицензии

ПО баз данных MySQL выпускается по общедоступной лицензии GNU General Public License (GPL). Это означает, что при соблюдении условий GPL ПО MySQL можно пользоваться бесплатно. Если вы не хотите связывать себя лицензионными ограничениями GPL (например, вас не устраивает условие, что ваше собственное приложение также подпадает под действие GPL), есть возможность приобрести у компании MySQL AB на этот же продукт коммерческую лицензию.

См. https://order.mysql.com/).

Компания MySQL AB владеет авторскими правами на исходный код MySQL, поэтому мы вправе использовать двойное лицензирование, в соответствии с которым один и тот же продукт доступен как по лицензии GPL, так и по коммерческой лицензии, и это никоим образом не нарушает обязательств компании MySQL AB по предоставлению исходного кода. Более подробную информацию о том, в каких случаях необходимо приобретение коммерческой лицензии, вы найдете в разделе section 1.6.3 Лицензии на ПО MySQL.

Компания MySQL AB занимается также продажей коммерческих лицензий на ПО сторонних разработчиков, предоставляемое с открытым исходным кодом на условиях GPL. Это ПО расширяет возможности MySQL. Хороший пример - транзакционный обработчик таблиц InnoDB, обеспечивающий поддержку технологии ACID, строковую блокировку, восстановление системы после аварии, управление версиями, поддержку внешних ключей и многое другое (see section 7.5 Таблицы InnoDB).

1.5.1.5 О нашей программе партнерства

Компания MySQL AB реализует глобальную программу партнерства, которая охватывает учебные курсы, консультативные услуги и поддержку продукта, издательскую деятельность, а также продажу и распространение MySQL и смежных продуктов. Партнеры компании MySQL AB получают право быть представленными на веб-сайте http://www.mysql.com/ и использовать в маркировке своих продуктов специальные варианты торговой марки MySQL - с целью идентификации и продвижения этих продуктов на рынке.

Тех, кто заинтересован в получении статуса партнера MySQL, просим обращаться по адресу partner@mysql.com.

Название MySQL и логотип MySQL в виде дельфина являются торговыми марками компании MySQL AB (see section 1.6.4 Логотипы и торговые марки MySQL AB), принадлежащими компании MySQL AB. Узнаваемость этих торговых марок свидетельствует о том, что за годы своей работы основатели компании MySQL AB сумели добиться для своей компании заметного положения и признания в мире.

1.5.1.6 О рекламе

Веб-сайт компании MySQL (http://www.mysql.com/) пользуется популярностью среди разработчиков и пользователей. Например, в октябре 2001 г. мы обслужили 10 миллионов запросов на просмотр размещенных на нем страниц. Наши посетители относятся к категории лиц, принимающих решения и дающих рекомендации о покупке как программного, так и аппаратного обеспечения. 12% наших посетителей утверждают решения о приобретении, и только 9% наших посетителей совсем не имеют отношения к принятию подобных решений. Более 65% наших посетителей сделали в деловых целях как минимум одну покупку в Сети за последние полгода, а 70% - планируют совершить ее в ближайшие месяцы.

1.5.2 Как с нами связаться

Самая свежая информация о MySQL и нашей компании представлена на веб-сайте MySQL (http://www.mysql.com/).

По вопросам связи с прессой и темам, не затронутым в наших сообщениях для печати (http://www.mysql.com/news/), обращайтесь по адресу press@mysql.com.

Для получения своевременных и точных ответов на технические вопросы, касающиеся ПО MySQL, необходимо иметь действующий контракт с компанией MySQL AB по поддержке (за дополнительной информацией обращайтесь к разделу section 1.6.1 Поддержка, предлагаемая компанией MySQL AB). Чтобы заказать контракт по поддержке, следует обратиться на сайт https://order.mysql.com/ или направить сообщение по адресу sales@mysql.com.

Для получения информации об учебных курсах, которые проводит компания MySQL AB, посетите раздел по обучению на веб-сайте http://www.mysql.com/training/. Тех, кто имеет ограниченный доступ в Internet, просим связаться с учебным отделом компании MySQL AB по адресу training@mysql.com (see section 1.5.1.2 Обучение и сертификация).

Информацию о программе сертификации компании MySQL AB вы найдете на странице http://www.mysql.com/certification/index.html нашего веб-сайта. Если вы желаете быть в курсе текущего состояния программы сертификации по MySQL, просим сообщить об этом по адресу certification@mysql.com. See section 1.5.1.2 Обучение и сертификация.

Заинтересованных в получении консультаций приглашаем посетить раздел консультаций на веб-сайте http://www.mysql.com/consulting/. Тех, у кого имеется ограниченный доступ в Internet, просим связаться с консультационным отделом компании MySQL AB по адресу consulting@mysql.com. Обращайтесь к разделу section 1.5.1.3 Консультации.

Коммерческие лицензии можно приобрести по Сети, на веб-сайте https://order.mysql.com/. Здесь вы найдете также информацию о том, как передать в компанию MySQL AB свой заказ на покупку по факсу. Более подробная информация о лицензировании доступна на http://www.mysql.com/products/pricing.html.

Если у вас имеются вопросы, касающиеся лицензирования, или вы хотите знать расценки на лицензии в случае массового выпуска продукта, заполните форму на нашем веб-сайте (http://www.mysql.com/) или пошлите сообщение по электронной почте: вопросы, касающиеся лицензирования, направляйте по адресу licensing@mysql.com, а запросы на покупку - по адресу sales@mysql.com. Обращайтесь также к разделу section 1.6.3 Лицензии на ПО MySQL.

Если вы представляете деловые круги, заинтересованные в партнерских отношениях с компанией MySQL AB, напишите нам по адресу partner@mysql.com. Обращайтесь к разделу section 1.5.1.5 О нашей программе партнерства.

Для получения дополнительной информации о политике компании MySQL в отношении торговых марок обращайтесь на наш веб-сайт http://www.mysql.com/company/trademark.html или напишите письмо по адресу trademark@mysql.com. Обратитесь к разделу section 1.6.4 Логотипы и торговые марки MySQL AB.

Если вас заинтересовало какое-либо из предложений, перечисленных в нашем разделе предложений работы (http://www.mysql.com/company/jobs/), направляйте свои письма по адресу jobs@mysql.com. Просьба не оформлять свои личные данные в виде вложения в письмо: лучше добавьте эту информацию в виде обычного текста в конце своего сообщения.

Если вы желаете принять участие в общей дискуссии с нашими многочисленными пользователями, обращайтесь на соответствующий список рассылки (see section 1.8.1 Списки рассылки MySQL).

Сообщения об ошибках (или bugs), а также вопросы и комментарии следует направлять в список рассылки по адресу mysql@lists.mysql.com. При обнаружении в MySQL ошибок, влияющих на безопасность баз данных, просим сообщать об этом по адресу security@mysql.com. Обратитесь также к разделу section 1.8.1.3 Как отправлять отчеты об ошибках или проблемах.

Если у вас имеются сравнительные результаты тестирования, которые мы можем опубликовать, свяжитесь с нами по адресу benchmarks@mysql.com.

Предложения по внесению дополнений или исправлений в данное руководство пользователя следует направлять коллективу разработчиков руководства по адресу docs@mysql.com.

Вопросы и замечания по работе или содержанию веб-сайта MySQL (http://www.mysql.com/) направляйте по адресу webmaster@mysql.com.

Компания MySQL AB придерживается определенной политики относительно конфиденциальности информации. Об этом вы можете прочитать на странице http://www.mysql.com/company/privacy.html нашего веб-сайта. По вопросам этой политики просим обращаться по адресу privacy@mysql.com.

По всем другим вопросам обращайтесь по адресу info@mysql.com.

1.6 Лицензии и поддержка MySQL

В этом разделе описаны условия предоставления компанией MySQL AB лицензий и поддержки.

1.6.1 Поддержка, предлагаемая компанией MySQL AB

Что подразумевается под технической поддержкой компании MySQL AB? Это означает, что на каждый свой вопрос вы получите адресованный лично вам ответ непосредственно от программистов, пишущих программы баз данных MySQL.

Мы стараемся, чтобы наша техническая поддержка носила широкий и содержательный характер. Если вопрос, который вы задаете по MySQL, важен для вас, то, следовательно, он должен быть важен и для нас. Как правило, клиенты просят помочь разобраться в том, как работают те или иные команды или утилиты, как устранить ``узкие места'', мешающие эффективной работе системы, как восстановить систему в случае аварии, как влияет на работу MySQL та или иная операционная система или локальная сеть, какие технологии резервного копирования и восстановления данных лучше применять, как использовать API-интерфейсы и т.д. Наша поддержка охватывает вопросы, относящиеся только к серверу MySQL и нашим собственным утилитам, но не к продуктам сторонних разработчиков, которые обеспечивают доступ к серверу MySQL, хотя мы стараемся и в этих случаях оказывать посильную помощь.

Подробная информация о различных видах поддержки, которую предлагает компания, приведена на веб-сайте http://www.mysql.com/support/. Там же вы можете заказать по Сети контракты по поддержке. Те, кто имеет ограниченный доступ в Internet, могут связаться с нашим отделом сбыта по адресу sales@mysql.com.

Техническая поддержка - это своего рода страхование жизни. Без такой страховки можно успешно обходиться долгие годы, но наступит критический момент - и придется сожалеть о своей беспечности! Если вы используете сервер MySQL для важных приложений и внезапно сталкиваетесь с неполадками в их работе, может оказаться, что на самостоятельное выяснение ответов на все вопросы потребуется слишком много времени. В таких случаях не обойтись без срочной помощи самых опытных специалистов по устранению аварийных ситуаций в MySQL, а они работают именно в компании MySQL AB.

1.6.2 Авторские права и лицензии на MySQL

Компания MySQL AB является владельцем авторских прав на исходный код ПО MySQL, логотипы и торговые марки MySQL, а также на данное руководство пользователя. Обратитесь к разделу section 1.5 Что представляет собой компания MySQL AB? Распространение MySQL подпадает под действие нескольких различных лицензий:

  1. Весь код ПО сервера, специфичный только для MySQL, библиотека mysqlclient и клиентское ПО, а также библиотека GNU readline подпадают под действие общедоступной лицензиии GNU General Public License (see section G GNU General Public License). Текст этой лицензии имеется также в составе дистрибутива ПО, в файле `COPYING'.
  2. Библиотека GNU getopt подпадает под действие GNU Lesser General Public License (see section H GNU Lesser General Public License).
  3. Некоторые фрагменты исходного кода (библиотека regexp) подпадают под действие Berkeley-подобной лицензии.
  4. Старые версии MySQL (3.22 и более ранние) подпадают под действие более строгой лицензии (http://www.mysql.com/products/mypl.html). Информация об условиях лицензии имеется в документации на конкретную версию.
  5. Распространение руководства пользователя в данное время не подпадает под действие лицензии типа GPL. Его использование допускается на следующих условиях:
    • Допускается конвертирование в другие форматы, но внесение при этом каких-либо изменений или редактирование содержания не допускается.
    • Разрешается выпуск печатных копий руководства для личных целей.
    • Во всех остальных случаях, таких как продажа печатных изданий руководства или использование руководства (или его части) в других публикациях, требуется предварительно получить письменное согласие компании MySQL AB.
    Для получения дополнительной информации или в случае, если вы хотели бы принять участие в переводе руководства, обращайтесь по адресу docs@mysql.com.

Дополнительная информация о том, как практически осуществляется лицензирование MySQL, находится в разделе section 1.6.3 Лицензии на ПО MySQL. Обращайтесь также к разделу section 1.6.4 Логотипы и торговые марки MySQL AB.

1.6.3 Лицензии на ПО MySQL

ПО MySQL распространяется в соответствии с условиями общедоступной лицензии GNU General Public License (GPL), которая является одной из наиболее широко распространенных лицензий на ПО с открытым исходным кодом. Официальные условия лицензии GPL вы найдете на веб-сайте http://www.gnu.org/licenses/. Обратитесь также к http://www.gnu.org/licenses/gpl-faq.html и http://www.gnu.org/philosophy/enforcing-gpl.html.

Так как ПО MySQL выпускается по лицензии GPL, зачастую им можно пользоваться бесплатно, но в некоторых случаях желательно или необходимо приобрести коммерческую лицензию у компании MySQL AB (это можно сделать на веб-сайте https://order.mysql.com/).

См. http://www.mysql.com/products/licensing.html для получения более подробной информации.

Старые версии MySQL (3.22 и более ранние) подпадают под действие более строгой лицензии (http://www.mysql.com/products/mypl.html). Информацию об условиях лицензии вы найдете в документации на конкретную версию.

Обращаем ваше внимание на то, что использование ПО MySQL, подпадающего под коммерческую лицензию, лицензию GPL или старую лицензию MySQL, не означает, что вы автоматически получаете право на использование торговых марок, принадлежащих компании MySQL AB. Об этом читайте в разделе section 1.6.4 Логотипы и торговые марки MySQL AB.

1.6.3.1 Использование ПО MySQL под коммерческой лицензией

Лицензия GPL - в хорошем смысле - носит ``заразный'' характер. Это означает, что в случае линкования какой-либо программы с программой, выпущенной по данной лицензии, все части исходного кода получившегося продукта должны также выпускаться по лицензии GPL. В противном случае будут нарушены условия лицензии и вы вообще лишитесь права использовать программу, подпадающую под ее действие.

Коммерческая лицензия является необходимой в следующих случаях:

  • При линковании программы с любым GPL кодом из ПО MySQL, в тех случаях, когда вы не хотите, чтобы готовый продукт подпадал под действие GPL (например, продукт разрабатывается как коммерческий или существуют какие-либо другие причины не открывать добавленный программный код, который не подпадает под действие GPL). При покупке коммерческой лицензии вы не используете ПО MySQL под лицензией GPL, даже несмотря на то, что это один и тот же код.
  • В случае распространения приложения, не защищенного лицензией GPL, которое предназначено для работы исключительно с ПО MySQL и поставляется вместе с ним. Такой вариант решения в действительности считается связыванием, даже если оно осуществляется по сети.
  • В случае, когда вам требуется распространять ПО MySQL без предоставления исходного кода, как того требует лицензия GPL.
  • Если вы хотите сделать вклад в дальнейшее развитие технологии баз данных MySQL - в таких случаях коммерческая лицензия формально может и не требоваться. Еще одним хорошим способом оказать содействие развитию ПО MySQL является приобретение контракта по поддержке непосредственно у компании MySQL AB - это сразу же принесет пользу и вам (see section 1.6.1 Поддержка, предлагаемая компанией MySQL AB).

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

По поводу коммерческих лицензий, см. http://www.mysql.com/products/licensing.html. Для контрактов на поддержку, см. http://www.mysql.com/support/. Тех, для кого требуются особые условия лицензирования, а также тех, у кого имеется ограниченный доступ в Internet, просим связаться с нашим отделом сбыта по адресу sales@mysql.com.

1.6.3.2 Бесплатное использование ПО MySQL по лицензии GPL

По лицензии GPL допускается бесплатное использование ПО MySQL если вы согласны с условиями GPL. Подробнее по поводу лицензии GPL и освещение наиболее популярных вопросов вы найдете по адресу http://www.gnu.org/licenses/gpl-faq.html.

Некоторые общие примеры GPL-использования MySQL:

  • Если вы распространяете код вашего приложения и код MySQL под лицензией GPL и в исходных текстах.
  • При распространении исходного кода MySQL в комплекте с другими программами, не связанными с MySQL или не зависящими от него по своему функциональному назначению, даже в том случае, если они распространяются на коммерческой основе. Это называется mere aggregation в лицензии GPL.
  • Если вы не распространяете никаких частей кода MySQL - вы можете использовать MySQL бесплатно.
  • При использовании ПО MySQL сервис-провайдерами Internet (ISP), предлагающими своим клиентам веб-хостинг с серверами баз данных MySQL. С другой стороны, мы настоятельно рекомендуем пользователям обращаться только к тем сервис-провайдерам, которые имеют контракт на поддержку компании MySQL: только при наличии такого контракта можно иметь уверенность в том, что при возникновении проблем с инсталляцией MySQL сервис-провайдер будет способен оказать своим клиентам действенную помощь. Заметим, что даже те сервис-провайдеры, которые не имеют коммерческой лицензии на MySQL, должны, по крайней мере, предоставить своим клиентам доступ к чтению исходного кода инсталляции MySQL, чтобы они могли самостоятельно проверить корректность всех сделанных ими дополнений или изменений.
  • При использовании ПО баз данных MySQL совместно с веб-сервером коммерческой лицензии не требуется (если, конечно, это не есть продукт, который вы распространяете). Это разрешение остается в силе даже в том случае, если веб-сервер, использующий MySQL, - коммерческий, так как при этом продажи версии MySQL, заложенной в него, как таковой не происходит. Однако в таком случае желательно, чтобы владелец веб-сервера приобрел контракт на поддержку MySQL, поскольку ПО MySQL способствует успеху его предприятия.

В общем случае мы рекомендуем приобретать контракт на поддержку компании MySQL AB и тем, кому для использования ПО баз данных MySQL не требуется коммерческой лицензии: этим вы будете способствовать развитию технологии MySQL и заодно немедленно получите для себя дополнительные преимущества (see section 1.6.1 Поддержка, предлагаемая компанией MySQL AB).

В случае использования ПО баз данных MySQL в коммерческих целях, предполагающего получение прибыли, мы предлагаем приобретение поддержки того или иного уровня, что будет способствовать дальнейшему развитию ПО MySQL. Мы считаем, что, если база данных MySQL способствует вашему бизнесу, то резонно предложить и вам оказать содействие компании MySQL AB (иначе получается так, что, обращаясь в нашу службу поддержки с вопросом, вы не только бесплатно пользуетесь тем, во что мы вложили большое количество усилий, но к тому же и требуете от нас еще и бесплатной поддержки)

1.6.4 Логотипы и торговые марки MySQL AB

Многие пользователи СУБД MySQL выражают желание расположить логотип MySQL AB с изображением дельфина на своих веб-сайтах, книгах или коробках со своими программными продуктами. Мы приветствуем это желание, хотя и обязаны напомнить, что MySQL и логотип MySQL с изображением дельфина являются торговыми марками компании MySQL AB и могут применяться только в соответствии с нашими правилами использования торговых знаков, с которыми вы можете ознакомиться по адресу http://www.mysql.com/company/trademark.html.

1.6.4.1 Оригинальный логотип MySQL

Логотип MySQL с изображением дельфина был создан финским рекламным агентством Priority в 2001 году. Мы решили сделать эмблемой СУБД MySQL дельфина - умное, проворное и изящное животное, с удивительной легкостью плавающее в океане, так же как и наша СУБД - в океане данных. К тому же дельфины нам просто нравятся.

Оригинальный логотип MySQL может использоваться только представителями MySQL AB, а также лицами, получившими на то письменное разрешение.

1.6.4.2 Логотипы MySQL, которые могут использоваться без письменного разрешения

Мы разработали несколько специальных логотипов для договорного использования, которые можно загрузить с нашего сайта, расположенного по адресу http://www.mysql.com/press/logos.html и применять на сайтах третьих сторон без письменного разрешения MySQL AB. Возможности использования этих логотипов, как и следует из их названия, определенным образом ограничены: они регламентируются правилами применения наших торговых знаков (которые также приведены у нас на сайте). Если вы планируете использовать данные логотипы, необходимо ознакомиться с указанными правилами. Они в основном сводятся к следующим:

  • Нужный вам логотип вы можете использовать в том виде, в котором он приведен на сайте http://www.mysql.com/. Вы имеете право задать необходимые размеры логотипа, но не можете менять его цвета или вносить в изображение какие-либо другие изменения.
  • Должно быть явно указано, что именно вы, а не MySQL AB, являетесь создателем и владельцем сайта, на котором присутствует торговый знак MySQL.
  • Не разрешается использовать торговый знак в целях, которые могли бы принести вред MySQL AB или понизить ценность торговых знаков MySQL AB. Мы оставляем за собой право запретить использование торгового знака MySQL AB.
  • Помещая торговый знак на своем сайте, сделайте его гиперссылкой на сайт http://www.mysql.com/.
  • Если вы используете СУБД MySQL в своем приложении на условиях лицензии GPL, оно должно быть создано в соответствии с идеологией Open Source и снабжено способностью подсоединяться к серверу MySQL.

Связаться с нами с целью заключения соответствующих вашим потребностям соглашений можно по адресу trademark@mysql.com.

1.6.4.3 В каком случае для использования логотипов необходимо письменное разрешение?

Письменное разрешение MySQL AB для использования логотипов MySQL необходимо в следующих случаях:

  • При использовании логотипа MySQL AB где бы то ни было, кроме вашего веб-сайта.
  • При использовании любого логотипа MySQL AB, кроме вышеупомянутых специальных логотипов для договорного использования, на веб-сайтах или в любых других местах.

Исходя из юридических и коммерческих соображений, мы следим за использованием торговых знаков MySQL на различных продуктах, книгах и т.п. Обычно мы взимаем плату за помещение логотипов MySQL AB на коммерческих продуктах, так как считаем, что вполне справедливо, если часть полученных производителем прибылей идет таким образом на финансирование дальнейшего усовершенствования СУБД MySQL.

1.6.4.4 Партнерские логотипы MySQL AB

Партнерские логотипы MySQL могут использоваться только теми компаниями и частными лицами, которые подписали письменное соглашение о партнерстве с MySQL AB. В условия подписания такового соглашения входит сертификация в качестве преподавателя или консультанта MySQL. See section 1.5.1.5 О нашей программе партнерства.

1.6.4.5 Использование слова MySQL в текстовых документах и презентациях

MySQL AB приветствует упоминания о СУБД MySQL, но не следует забывать о том, что слово MySQL - торговая марка MySQL AB. Поэтому первое встречающееся в тексте слово MySQL следует снабдить символом, обозначающим торговую марку (TM), а также (по возможности) упомянуть о том, что MySQL является зарегистрированной торговой маркой компании MySQL AB. Дополнительную информацию вы сможете получить, ознакомившись с нашими правилами использования торговых знаков, расположенными по адресу http://www.mysql.com/company/trademark.html.

1.6.4.6 Использование слова MySQL в названиях компаний и продуктов

Использовать слово MySQL в названиях компаний, продуктов или в именах доменов без письменного разрешения MySQL AB запрещено.

1.7 Кратко о MySQL 4.x

Наконец-то появилась давно обещанная компанией MySQL AB бета-версия MySQL Server 4.0, которую так долго ждали пользователи. Ее можно загрузить с веб-сайта http://www.mysql.com/ или с наших зеркал.

Большинство новых функций MySQL 4.0 ориентированы на уже существующих пользователей MySQL уже существующих пользователей в общественной и деловой сфере. Эти функции позволяют усовершенствовать программное обеспечение базы данных MySQL, предоставляя решения для критически важных систем управления базами данных, работающих с большими объемами информации. Остальные новые функции предназначены для пользователей встроенных баз данных.

1.7.1 Поэтапный выпуск

Начиная с 4.0.6, MySQL имеет статус gamma, что означает что версии 4.0.x в течении более чем 2 месяцев (сначала в alpha-, затем и в beta-статусе) используются без каких-либо известных серьезных и сложных для исправления ошибок и готовы для промышленного использования.

Мы снимем префикс gamma, когда MySQL 4.0 будет в эксплуатации более чем один месяц без обнаруженных серьезных ошибок.

Все новые функции будут добавляться в версию MySQL 4.1, доступную сейчас из нашего репозитория bk, выпуск alpha-версии которой запланирован на первый квартал 2003. See section 2.3.4 Установка из экспериментального набора исходных кодов.

1.7.2 Можно использовать уже прямо сейчас

Все бинарные поставки проходят наши сложные тесты без каких-либо ошибок на всех платформах, на которых мы тестируем MySQL. MySQL 4.0 протестирован в реальных условиях огромным количеством пользователей и находится в промышленной эксплуатациями на нескольких крупных сайтах.

1.7.3 Встроенный MySQL

Библиотека libmysqld обеспечивает для MySQL возможность не отставать от прогресса в стремительно развивающемся мире приложений. Вариант MySQL в виде встроенной библиотеки позволяет встраивать MySQL в различные приложения и электронные устройства так, что конечный пользователь даже не будет знать о ``заложенной в их фундаменте'' базе данных. Встроенный MySQL идеально подходит для использования в интернет-приложениях, публичных киосках, в устройствах с сочетанием аппаратного и программного обеспечения, высокопроизводительных интернет-серверах, автономных базах данных, распространяемых на компакт-дисках, и так далее.

Большинство пользователей libmysqld оценят преимущество Двойной лицензии MySQL. Для тех, кто не хочет связывать себя условиями GPL лицензии, программное обеспечение доступно также на условиях коммерческой лицензии. Для встроенной библиотеки MySQL используется такой же интерфейс, как и для обычной клиентской библиотеки, поэтому ею удобно и легко пользоваться. See section 8.4.9 libmysqld, встраиваемая библиотека сервера MySQL.

1.7.4 Другие функции, доступные в MySQL 4.0

  • В версии 4.0 еще больше возросла скорость работы MySQL в нескольких областях, таких как множественные вставки (bulk INSERT) для большого количества данных, поиск в сжатых индексах, создание полнотекстовых индексов (FULLTEXT), а также COUNT(DISTINCT).
  • Обработчик таблиц InnoDB теперь входит в стандартный набор сервера MySQL, включая полную поддержку транзакций и блокировок уровня строки.
  • Немецкие, австрийские и швейцарские пользователи нашей программы обратят внимание, что мы добавили новый набор символов, latin1_de, который позволяет исправить порядок сортировки немецких символов, размещая немецкие умляуты в соответствии с телефонными книгами, используемыми в Германии.
  • Функции для упрощения преобразования из других систем баз данных в MySQL, включают TRUNCATE TABLE (как в Oracle) и IDENTITY, как синоним автоматически инкрементируемых ключей (как в Sybase). Многим пользователям также будет приятно узнать, что MySQL теперь поддерживает оператор UNION, долгожданную стандартную функцию SQL.
  • Создавая новые функции для новых пользователей, мы не забыли о запросах наших постоянных пользователей. У нас есть многотабличные операторы DELETE и UPDATE Добавив поддержку символических ссылок к MyISAM на уровне таблицы (а не только на уровне базы данных, как это было раньше), а также включив обработку таких ссылок как функцию, используемую в Windows по умолчанию, мы надеемся продемонстрировать, что серьезно относимся к предложениям по усовершенствованиям. Такие функции как SQL_CALC_FOUND_ROWS и FOUND_ROWS() позволяют узнать, сколько строк возвратит запрос без оператора LIMIT.

1.7.5 Функции MySQL 4.x, которые будут добавлены в будущем

В последующих версиях MySQL 4.x будут добавлены следующие функции, которые на данный момент находятся в стадии разработки:

  • Пользователи MySQL, работающие с критически важными системами и большими объемами данных, оценят дополнения к нашей системе репликации и удаленного резервного копирования. В более поздние версии 4.x будет включена отказобезопасная репликация; а к функциям уже существующей в версии 4.0 команды LOAD DATA FROM MASTER в скором времени будет добавлена автоматизация настройки подчиненных серверов. Удаленное резервное копирование обеспечит возможность легко добавлять новые подчиненные серверы, не отключая головной сервер, - это позволит практически избежать потерь в производительности при обновлении объемных систем.
  • Для администраторов баз данных удобным окажется еще одно новшество: в скором времени параметры mysqld (настройки запуска) можно будет изменять без выключения серверов.
  • Новые свойства поиска FULLTEXT в MySQL 4.0 позволяют использовать FULLTEXT-индексацию больших объемов текста при помощи как бинарной логики поиска, так и логики поиска естественного языка. Пользователи могут производить настройку минимальной длины слова и задавать свои списки недопустимых слов на любом естественном языке, благодаря чему появляется возможность создания новой группы программ на основе MySQL.
  • Производительность многих ``тяжеловесных'' приложений повысится благодаря еще более возросшей скорости заново переписанного ключевого кэша.
  • Большинству разработчиков также понравится встроенная в MySQL справка, которая вызывается из командной строки на клиенте.

1.7.6 MySQL 4.1, следующая ветка в разработке

MySQL 4.0 готовит базу для реализации новых возможностей в сервере MySQL 4.1 и более новых версиях. Имеются в виду такие возможности, как вложенные подзапросы (nested subqueries) (4.1), хранимые процедуры (5.0) и правила целостности ссылок (foreign key integrity rules) для MyISAM-таблиц (5.0).

Эти возможности возглавляют список наиболее востребованных нашими потребителями функций.

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

1.8 Источники информации по MySQL

1.8.1 Списки рассылки MySQL

В этом разделе представлены списки рассылки MySQL, а также даются некоторые указания по их использованию. Подписавшись на список рассылки, вы будете получать по электронной почте информацию из данного списка и сможете отправлять туда свои собственные вопросы и ответы.

1.8.1.1 Списки рассылки MySQL

Чтобы подписаться на главный список рассылки MySQL, следует отправить сообщение на адрес электронной почты mysql-subscribe@lists.mysql.com.

Чтобы отказаться от подписки на главный список рассылки MySQL, следует отправить сообщение на адрес электронной почты mysql-unsubscribe@lists.mysql.com.

В посылаемом сообщении роль играет только адрес, на который это сообщение отправляется. Тема и текст сообщения игнорируются.

Если адрес, с которого было отправлено ваше сообщение, не действителен, можно точно указать адрес для подписки или адрес, подписку для которого следует аннулировать. Для этого в указанных выше адресах электронной почты следует добавить дефис в конце командного слова, обозначающего подписку (subscribe) или отказ от нее (unsubscribe), а за ним - нужный адрес электронной почты, заменив в нем символ `@' на символ `='. Например, чтобы подписать адрес your_name@host.domain, необходимо отправить сообщение на mysql-subscribe-your_name=host.domain@lists.mysql.com.

Сообщения, посланные по адресам mysql-subscribe@lists.mysql.com или mysql-unsubscribe@lists.mysql.com, обрабатываются автоматически программой обслуживания списка рассылки ezmlm. Информация по программе ezmlm доступна на веб-узле ezmlm (http://www.ezmlm.org/).

Чтобы отправить сообщение в список рассылки, следует послать сообщение по адресу mysql@lists.mysql.com. Пожалуйста, не отправляйте сообщения о подписке или отказе от подписки на адрес mysql@lists.mysql.com, поскольку все сообщения, направленные на этот адрес, автоматически распространяются среди тысяч других подписчиков.

Если на вашем локальном веб-узле уже есть подписчики на mysql@lists.mysql.com, то на нем может существовать локальный список рассылки, поэтому сообщения, отправленные из lists.mysql.com на ваш веб-узел, будут также дублироваться в местный список. В таких случаях необходимо связаться со своим системным администратором, чтобы он добавил вас в местный список рассылки MySQL или исключил из него.

Если необходимо, чтобы сообщения, поступающие со списка рассылки, направлялись в отдельный почтовый ящик вашего почтового клиента, установите фильтр по заголовкам сообщений. Чтобы выделить сообщения из списка рассылки, можно использовать заголовки List-ID: или Delivered-To:.

Существуют следующие списки рассылки MySQL:

announce-subscribe@lists.mysql.com announce
Список для объявлений о выходах новых версий MySQL и относящихся к нему программ. Количество сообщений здесь небольшое, и на этот список желательно подписаться всем пользователям MySQL.
mysql-subscribe@lists.mysql.com mysql
Главный список для обсуждения общих вопросов по MySQL. Обратите внимание: некоторые темы лучше обсуждать в более специализированных списках. Если отправить сообщение не в тот список, то можно не получить ответа!
mysql-digest-subscribe@lists.mysql.com mysql-digest
Список mysql в виде сборника. Это означает, что вы получите все сообщения, отправленные за день, в виде одного большого почтового сообщения, которое отправляется раз в день.
bugs-subscribe@lists.mysql.com bugs
В этот список можно отправлять только подробные отчеты о повторяющихся ошибках, используя макропрограмму mysqlbug (если вы работаете в Windows, необходимо включить описание операционной системы и указать версию MySQL). Прежде чем отправлять отчет об ошибке, желательно проверить, при использовании какой версии MySQL данная ошибка возникает - последней окончательной или находящейся на стадии разработки! Чтобы любой желающий мог воспроизвести эту ошибку, желательно также включить в отчет контрольный тестовый пример, который можно было бы запустить при помощи mysql test < script. Все ошибки, сообщения о которых будут направлены в список рассылки, будут либо исправлены, либо включены в список ошибок в следующей версии MySQL! Если необходимо только небольшое изменение кода, мы также отправим исправляющую эту ошибку заплатку для программы.
bugs-digest-subscribe@lists.mysql.com bugs-digest
Список bugs в виде сборника.
internals-subscribe@lists.mysql.com internals
Список для тех, кто работает над кодом MySQL. В этом списке также можно обсуждать разработку MySQL и отправлять в него вставки в программу.
internals-digest-subscribe@lists.mysql.com internals-digest
Версия в виде сборника для списка internals.
java-subscribe@lists.mysql.com java
Обсуждение вопросов, связанных с MySQL и Java. В основном обсуждение по драйверам JDBC включая MySQL Connector/J.
java-digest-subscribe@lists.mysql.com java-digest
Версия в виде сборника для списка java.
win32-subscribe@lists.mysql.com win32
Все вопросы, касающиеся программного обеспечения MySQL в операционных системах Microsoft, таких как Windows 9x/Me/NT/2000/XP.
win32-digest-subscribe@lists.mysql.com win32-digest
Версия в виде сборника для списка win32.
myodbc-subscribe@lists.mysql.com myodbc
Все вопросы, касающиеся соединения MySQL через ODBC.
myodbc-digest-subscribe@lists.mysql.com myodbc-digest
Версия в виде сборника для списка myodbc.
mysqlcc-subscribe@lists.mysql.com mysqlcc
Все вопросы, касающиеся графического клиента MySQL Control Center (MyCC).
mysqlcc-digest-subscribe@lists.mysql.com mysqlcc-digest
Версия в виде сборника для списка mysqlcc.
plusplus-subscribe@lists.mysql.com plusplus
Все вопросы, касающиеся программирования на C++ API для MySQL.
plusplus-digest-subscribe@lists.mysql.com plusplus-digest
Версия в виде сборника для списка plusplus.
msql-mysql-modules-subscribe@lists.mysql.com msql-mysql-modules
Список по поддержке Perl для MySQL при помощи msql-mysql-modules.
msql-mysql-modules-digest-subscribe@lists.mysql.com msql-mysql-modules-digest
Версия в виде сборника для списка msql-mysql-modules.

Подписаться или отказаться от подписки на все списки рассылки можно способом, указанным выше. В своем сообщении о подписке или отказе от подписки вместо mysql просто укажите соответствующее название списка рассылки. Например, чтобы подписаться на список рассылки myodbc или отказаться от подписки на него, следует отправить сообщение по адресу myodbc-subscribe@lists.mysql.com или myodbc-unsubscribe@lists.mysql.com.

Если получить ответы на свои вопросы в списке рассылки не удалось, можно оплатить поддержку от MySQL AB - это позволит вам напрямую общаться с разработчиками MySQL. See section 1.6.1 Поддержка, предлагаемая компанией MySQL AB.

В приведенной ниже таблице указаны некоторые списки рассылки MySQL на языках, отличных от английского. Обратите внимание на то, что компания MySQL AB эти списки не контролирует, поэтому мы не можем гарантировать их качество.

mysql-france-subscribe@yahoogroups.com Французский список рассылки
list@tinc.net Корейский список рассылки
Чтобы подписаться на этот список рассылки, отправьте сообщение subscribe mysql your@e-mail.address.
mysql-de-request@lists.4t2.com Немецкий список рассылки
Чтобы подписаться на этот список рассылки, отправьте сообщение subscribe mysql-de your@e-mail.address. Информацию по этому списку рассылки можно найти на http://www.4t2.com/mysql/.
mysql-br-request@listas.linkway.com.br Португальский список рассылки
Чтобы подписаться на этот список рассылки, отправьте сообщение subscribe mysql-br your@e-mail.address.
mysql-alta@elistas.net Испанский список рассылки
Чтобы подписаться на этот список рассылки, отправьте сообщение subscribe mysql your@e-mail.address.

1.8.1.2 Как задавать вопросы и направлять сообщения об ошибках

Прежде чем отправлять отчет об ошибке, необходимо выполнить следующие действия:

  • Сначала проведите поиск в интерактивном руководстве по MySQL на: http://www.mysql.com/doc/ Мы стараемся постоянно обновлять данное руководство, добавляя информацию об исправлениях последних обнаруженных ошибок! Приложение, описывающее историю изменений (http://www.mysql.com/doc/en/News.html) также может быть полезным, т.к. вполне возможно, что именно в новой версии уже есть решение вашей проблемы.
  • Посмотрите в базе данных ошибок по адресу http://bugs.mysql.com. Может, известная ошибка уже сообщена и исправлена.
  • Просмотрите архивы списка рассылки MySQL: http://lists.mysql.com/
  • Можно также воспользоваться ссылкой http://www.mysql.com/search/, чтобы произвести поиск по всем веб-страницам (включая руководство), расположенным на веб-узле http://www.mysql.com/.

Если в руководстве или архивах не удалось найти ответ, обратитесь к локальному эксперту по MySQL. Если же и таким образом не удалось получить ответы на вопросы, переходите к следующему разделу, в котором описано, как отправлять почту на mysql@lists.mysql.com.

1.8.1.3 Как отправлять отчеты об ошибках или проблемах

Чтобы написать хороший отчет об ошибке, потребуется немало терпения. Однако лучше сделать все правильно с первой попытки - это сбережет и ваше, и наше время. Грамотно составленный отчет об ошибке, содержащий ее подробное описание, позволит нам исправить эту ошибку уже в следующей версии программы. Включенные в данный раздел рекомендации помогут вам правильно написать свой отчет, не тратя времени на описание того, что мало чем сможет нам помочь или не потребуется вовсе.

Мы рекомендуем для создания отчетов об ошибках (или отчетов о любых проблемах), всегда, если это возможно, использовать сценарий mysqlbug. mysqlbug можно найти в каталоге `scripts' раздела распространения исходных текстов, или в разделе распространения исполняемых программ, в каталоге `bin' инсталляционного каталога MySQL. Если же не удается воспользоваться mysqlbug, то все равно необходимо указать в своем отчете все данные, перечисленные ниже в этом разделе.

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

Обычно отчеты об ошибках и проблемах направляются в mysql@lists.mysql.com. Если же вы можете создать подробное описание, четко определяющее ошибку, его можно направить в список рассылки bugs@lists.mysql.com. Обратите внимание: в этот список рассылки можно посылать только полный отчет о повторяющейся ошибке, составленный при помощи сценария mysqlbug. Если вы работаете в Windows, необходимо включить описание операционной системы и версии MySQL. Прежде чем направлять отчет, желательно проверить, проявляется ли данная проблема при использовании последней окончательной или находящейся в стадии разработки версии MySQL! Чтобы любой желающий мог воспроизвести эту ошибку, желательно также включить в отчет контрольный тестовый пример, который можно было бы запустить при помощи ``mysql test < script'', либо Perl-сценарий или сценарий оболочки, которые можно запустить непосредственно. Все ошибки, сообщения о которых будут направлены в список рассылки, будут либо исправлены, либо включены в список ошибок в следующей версии MySQL! Если необходимо только небольшое изменение кода, мы также отправим исправляющий эту ошибку патч для программы.

Если вы нашли ошибку в системе безопасности MySQL, необходимо отправить сообщение по адресу security@mysql.com.

Не забывайте о том, что можно ответить на сообщение, в котором содержится слишком много информации, но нельзя ответить на сообщение, в котором информации недостаточно. Часто те, кто нам пишет, опускают некоторые факты: они считают, что им известна причина возникшей проблемы и поэтому, по их мнению, некоторые детали не имеют значения. Необходимо придерживаться следующего принципа: если возникают сомнения в отношении того, следует или нет приводить в отчете те или иные сведения, - включите их в отчет обязательно! Намного быстрее и проще написать несколько дополнительных строк в отчете, чем получать уточняющие вопросы и снова ждать ответа только потому, что в первый раз были указаны не все данные.

Чаще всего наши корреспонденты не указывают используемую версию MySQL или платформу, на которой установлен сервер MySQL (включая версию платформы). Это довольно существенная информация, и в 99 случаях из 100 отчет об ошибке без нее будет совершенно бесполезным! Очень часто бывает и так: мы получаем вопрос типа: ''Почему это у меня не работает?'', а потом оказывается, что указанная функция в данной версии MySQL отсутствует или что ошибка, описанная в отчете, уже была исправлена в более новой версии MySQL. Иногда ошибка зависит от используемой платформы. В таких случаях практически невозможно ничего исправить, не имея информации об операционной системе и о версии платформы.

Не забывайте указывать информацию о своем компиляторе - в тех случаях, когда это имеет отношение к возникшей проблеме. Ведь бывает и так: пользователь полагает, что проблема связана с MySQL, а на самом деле он нашел ошибку в компиляторе. Большинство компиляторов постоянно находятся в состоянии разработки и становятся лучше от версии к версии. Чтобы определить, зависит ли ваша проблема от компилятора, мы должны знать, какой именно используется компилятор. Обратите внимание на то, что все проблемы с компиляторами должны рассматриваться как ошибки и по ним должен составляться соответствующий отчет.

Вы окажете нам значительную помощь, включив в отчет об ошибке подробное описание проблемы. В качестве хорошего примера подобной информации можно привести описание всех действий, которые привели к возникновению проблемы и описание самой проблемы. Лучшие отчеты содержат подробные примеры, в которых показано, как можно воспроизвести ошибку или проблему. section D.1.6 Создание контрольного примера при повреждении таблиц.

Если программа выдает сообщение об ошибке, очень важно точно воспроизвести это сообщение в своем отчете! Возможно, нам придется производить поиск в архивах - лучше, чтобы указанное в отчете сообщение об ошибке точно совпадало с тем, которое выдает программа. Не следует пытаться запомнить сообщение об ошибке, имеет смысл просто скопировать его полностью и вставить в отчет!

Если возникли проблемы с MyODBC, необходимо попытаться создать файл трассировки MyODBC. See section 8.3.7 Составление отчетов о проблемах с MyODBC.

Не забывайте, что у большинства людей, которые будут читать ваш отчет, экраны дисплеев имеют ширину в 80 символов. При создании отчетов или примеров при помощи средств командной строки mysql необходимо использовать параметр --vertical (или терминатор оператора \G) для выходных данных, которые будут превышать ширину для таких дисплеев (пример для оператора EXPLAIN SELECT приведен ниже в данном разделе).

В свой отчет вам необходимо включить следующую информацию:

  • Версию используемого дистрибутива MySQL (например MySQL Version 3.22.22). Чтобы узнать, какая версия запущена, следует выполнить команду mysqladmin version. Программу mysqladmin можно найти в каталоге `bin' инсталляционного каталога MySQL.
  • Производителя и модель компьютера, на котором вы работаете.
  • Название и версию операционной системы. Для большинства операционных систем эту информацию можно получить, выполнив команду Unix uname -a.
  • Иногда важную роль играет количество памяти (реальной и виртуальной). Если у вас есть основания считать, что такая информация может оказаться полезной, включите в отчет эти значения.
  • Если используется дистрибутив в виде исходных текстов программного обеспечения MySQL, необходимо указать версию используемого компилятора. Если используется бинарный дистрибутив, необходимо указать имя дистрибутива.
  • Если проблема возникает во время компиляции, включите в отчет точное сообщение об ошибке (или ошибках), а также несколько строк до и после вызывающего ошибку кода в файле, вызвавшем проблему.
  • Если произошло аварийное завершение работы mysqld, необходимо сообщить о запросе, который привел к такому завершению. Это можно выяснить, запустив mysqld с включенной функцией ведения журнала. See section D.1.5 Использование журналов для определения причин ошибок в mysqld.
  • Если с программой связана какая-либо таблица базы данных, включите в отчет выходную информацию команды mysqldump --no-data db_name tbl_name1 tbl_name2 .... Выполняется это очень легко. Таким способом можно получить подробную информацию о таблице в базе данных, что поможет нам создать ситуацию, соответствующую той, в которой оказались вы.
  • Для ошибок, связанных со скоростью выполнения или проблемами с операторами SELECT, всегда необходимо включать в отчет выходную информацию команды EXPLAIN SELECT ... и, по крайней мере, количество строк, которые выдает оператор SELECT. Вы также должны включить вывода SHOW CREATE TABLE ... для каждой таблицы, задействованной в запросе. Чем больше информации будет предоставлено о сложившейся ситуации, тем больше шансов, что будет оказана надлежащая помощь! Например, ниже приведен образец очень хорошего отчета об ошибке (он, конечно, должен быть отправлен при помощи сценария mysqlbug): Пример запускается при помощи командной строки mysql (обратите внимание на применение терминатора операторов \G, который используется для операторов, если ширина выводимой ими информации превышает ширину строки 80-символьного дисплея):
    mysql> SHOW VARIABLES;
mysql> SHOW COLUMNS FROM ...\G
       <вывод SHOW COLUMNS>
mysql> EXPLAIN SELECT ...\G
       <вывод EXPLAIN>
mysql> FLUSH STATUS;
mysql> SELECT ...;
       <Корокая версия вывода SELECT, включая время,
        затраченное на обработку запроса>
mysql> SHOW STATUS;
       <вывод SHOW STATUS>
  • Если ошибка или проблема возникли во время работы mysqld, постарайтесь предоставить сценарий, который воспроизведет аномальное поведение программы. Сценарий должен включать все необходимые файлы данных. Чем точнее сценарий может воспроизвести сложившуюся ситуацию, тем лучше. Если вы можете создать воспроизводимый контрольный пример, его необходимо отправить на bugs@lists.mysql.com для немедленного рассмотрения! Если сценарий обеспечить нельзя, необходимо, по крайней мере, включить в свое сообщение выходную информацию команды mysqladmin variables extended-status processlist, чтобы предоставить данные о работе системы!
  • Если не удается создать контрольный пример в несколько строк, или если таблица тестирования слишком велика для отправления в список рассылки (более 10 строк), необходимо вывести содержимое таблиц при помощи команды mysqldump и создать файл `README' с описанием вашей проблемы. Запакуйте файлы при помощи tar и gzip или zip, и по ftp загрузите архив на ftp://support.mysql.com/pub/mysql/secret/. Затем отправьте краткое описание проблемы на bugs@lists.mysql.com.
  • Если MySQL на ваш запрос выдает странный, на ваш взгляд, результат, приведите в отчете не только сам результат, но также и ваше мнение о том, каким должен быть результат, и расчеты, подтверждающие это мнение.
  • Когда вы приводите пример ситуации, при которой возникает проблема, лучше сохранить действительные имена переменных, таблиц и т.п., вместо того, чтобы давать им новые имена. Иногда проблема может быть вызвана именем переменной или таблицы! Это довольно редкие случаи, но лучше, чтобы не терять времени, такую информацию отправить нам сразу. В конце концов, вам будет даже легче использовать данные, соответствующие реальной ситуации, и это во всех отношениях лучше для нас. Те же, кто не хотел бы показывать свои данные другим пользователям, могут загрузить файл по ftp на ftp://support.mysql.com/pub/mysql/secret/. Если данные действительно представляют собой секретную информацию, которую нельзя показывать даже нам, тогда можно привести пример, используя другие имена, но этот вариант следует оставить на крайний случай.
  • Включите в отчет все параметры, указанные для важных программ, если это возможно. Например, приведите параметры, которые вы используете как для запуска сервера mysqld, так и для запуска клиентских программ MySQL. Параметры таких программ как mysqld и mysql, а также сценарий configure часто содержат ответы на многие вопросы и очень важны! Включить их в отчет не помешает в любом случае! Если используются какие-либо модули, такие как Perl или PHP, также укажите их версии.
  • Если ваш вопрос относится к системе привилегий, укажите выходные данные команды mysqlaccess, выходные данные команды mysqladmin reload и все сообщения об ошибках, которые выдаются при попытке соединения! Во время проверки своих привилегий сначала необходимо выполнить команду mysqlaccess. После этого запустите mysqladmin reload version и попытайтесь соединиться с программой, которая вызывала проблемы. Программу mysqlaccess можно найти в каталоге `bin' установочного каталога MySQL.
  • Если у вас есть патч, который исправляет ошибку, - это хорошо. Но не думайте, что одного лишь патча для нас будет достаточно, или что мы будем ее использовать, если вы не предоставите необходимую информацию, такую как описание ошибки, которую исправляет ваш патч. Ведь мы можем найти проблемы в самом патче или попросту в нем не разобраться, что не даст нам возможности его применять. Если нам не удастся проверить, для чего именно служит этот патч, мы не станем его использовать. В таких случаях нам помогут контрольные примеры. Продемонстрируйте, что патч исправляет все проблемы, которые могут возникнуть в связи с этой ошибкой. Если мы найдем хотя бы один вариант, в котором патч не работает, то он может оказаться бесполезным.
  • Попытки угадать, что представляет собой ошибка, почему она возникает или от чего зависит, обычно не дают положительного результата. Даже члены команды MySQL не могут определить реальную причину ошибки без программы отладки.
  • Укажите в своем почтовом сообщении, что вы просмотрели справочное руководство и почтовый архив - тогда будет видно, как вы пытались решить эту проблему самостоятельно.
  • Если возникла синтаксическая ошибка, внимательно просмотрите свою программу! Если не удается найти никаких ошибок, может оказаться, что ваша версия MySQL не поддерживает используемый запрос. Если используется текущая версия в руководстве на http://www.mysql.com/doc/ не описан синтаксис, который вы используете, MySQL не поддерживает ваш запрос. В этом случае вы можете либо самостоятельно реализовать такой синтаксис, либо направить сообщение по адресу licensing@mysql.com и попросить либо предложить реализовать его! Если в руководстве описан используемый синтаксис, но у вас установлена более старая версия MySQL, необходимо проверить журнал изменений MySQL, чтобы узнать, когда был реализован данный синтаксис. В этом случае вы можете произвести обновление до более новой версии MySQL. See section C История изменений и обновлений MySQL.
  • Если в результате ошибки ваши данные оказываются поврежденными, или возникают ошибки при обращении к какой-либо определенной таблице, сначала необходимо проверить, а потом попытаться восстановить таблицы при помощи команды myisamchk или CHECK TABLE и REPAIR TABLE. See section 4 Администрирование баз данных.
  • Если повреждения ваших таблиц случаются часто, необходимо выяснить, когда и почему это происходит. В этом случае файл `mysql-data-directory/`hostname`.err' может содержать некоторую информацию о происходящем. See section 4.9.1 Журнал ошибок. Включите в отчет об ошибке всю важную информацию из этого файла. Обычно mysqld никогда не должна повреждать данные в таблицах, если не произошло никакого сбоя во время обновления! Если вам удалось найти причину ошибки в mysqld, нам будет гораздо проще оказать вам помощь в решении этой проблемы. See section A.1 Как определить, чем вызваны проблемы.
  • Если это возможно, загрузите и установите последнюю версию MySQL Server и проверьте, не решена ли в ней ваша проблема. Все версии программного обеспечения MySQL проходят тщательное тестирование и должны работать без проблем. Мы делаем все возможное, чтобы сохранить обратную совместимость, поэтому при переходе с одной версии MySQL на другую никаких проблем не должно возникать. See section 2.2.6 Какую версию MySQL использовать.

Если вы пользователь, пользующийся официальной поддержкой, направьте отчет об ошибке на mysql-support@mysql.com, чтобы его рассмотрели в первую очередь, а также в соответствующий список рассылки, чтобы узнать, сталкивался ли кто-нибудь еще с этой проблемой (и, возможно, нашел решение).

Чтобы получить информацию по отчетам об ошибках в MyODBC, See section 8.3.4 Как сообщать о проблемах с MyODBC.

Решения для наиболее часто встречающихся проблем можно найти в разделе section A Проблемы и распространенные ошибки.

Если ответы направляются к вам индивидуально, не попадая в список рассылки, хорошим тоном считается составить отчет по полученным ответам и отправить его в список рассылки, чтобы другие пользователи смогли получить информацию, которая помогла решить вашу проблему!

1.8.1.4 Рекомендации по ответам на вопросы, направляемые в список рассылки

Если вы считаете, что ваш ответ представляет интерес для большинства пользователей, то можете направить его прямо в список рассылки, вместо того, чтобы отвечать напрямую человеку, задавшему вопрос. Постарайтесь обобщить свой ответ таким образом, чтобы его смысл был понятен всем, а не только человеку, задавшему вопрос. При отправке сообщения в список рассылки убедитесь, что ваш ответ не является повторением предыдущего ответа.

Постарайтесь оставить главную часть вопроса в своем ответе, не стесняйтесь оставить все исходное сообщение в своем письме.

Не отправляйте сообщения из своего браузера с включенным режимом HTML! Многие пользователи не используют браузер для чтения почты!

1.8.2 Пользователи MySQL на IRC

В дополнение к спискам рассылки MySQL, вы можете найти поддержку у опытных пользователей MySQL в IRC.

Вот сети/каналы, известные нам на данный момент:

  • freenode (см. список серверов на http://www.freenode.net/ )
    • #mysql В основном обсуждение MySQL, но вопросы по другим СУБД приветствуются.
    • #mysqlphp Вопросы про популярную связку MySQL+PHP
  • EFnet (см. список серверов на http://www.efnet.org/)
    • #mysql Вопросы по MySQL.

Мы можем рекомендовать вам X-Chat для подключения к IRC-сети. X-Chat доступен как для Unix, так и для Windows по адресу: http://www.xchat.org/.

1.9 Насколько MySQL соответствует стандартам?

В этом разделе рассматривается соотношение между MySQL и стандартами ANSI SQL. Сервер MySQL имеет много расширений стандарта ANSI SQL; здесь вы найдете информацию о том, что представляют собой эти расширения и как их использовать. Помимо этого, в данном разделе содержится информация о том, какие функциональные возможности отсутствуют в сервере MySQL, а также дается описание способов обхода некоторых трудностей.

Мы не ставили перед собой цель ограничивать какую бы то ни было область применения сервера MySQL, если на то нет веских причин. И несмотря на то что у нас не хватает ресурсов выполнять разработку для каждого возможного применения сервера, мы всегда охотно окажем помощь и предложим советы тем, кто пытается расширять сферу использования MySQL.

Одним из главных направлений разработки данного продукта является продолжение работы в области соответствия его стандартам ANSI 99, но не за счет ущерба для скорости или надежности. Мы без опаски добавляем к серверу MySQL расширения к SQL или поддержку не предусмотренных в SQL возможностей, если это заметно увеличивает удобство его использования для значительной части наших пользователей (одним из примеров такой стратегии является новый интерфейс HANDLER в версии сервера MySQL 4.0; see section 6.4.2 Синтаксис оператора HANDLER).

В наших планах - продолжение поддержки баз данных с транзакциями и без транзакций, чтобы обеспечить как интенсивное применение для веб-регистрации, так и зависящее от целевого назначения использование в круглосуточном режиме 24/7.

С самого начала сервер MySQL был спроектирован для работы с базами данных среднего размера (10-100 миллионов строк или около 100 MB на таблицу) на малых вычислительных системах. Мы будем продолжать расширять сервер MySQL для работы с базами данных с размерами даже больше терабайта, и наряду с этим - предоставлять возможность компиляции упрощенной версии MySQL, которая больше подходит для портативных устройств и встраивания. Благодаря компоновочной схеме сервера MySQL оба эти направления возможны без каких-либо конфликтов в дереве исходных кодов.

В настоящее время мы не ставим перед собой задач поддержки работы в режиме реального времени или кластеризованных баз данных (хотя наши сервисы репликации уже обеспечивают многие из таких возможностей).

Мы не считаем, что для базы данных необходима поддержка чистого XML, но при этом будем добавлять на клиентской стороне поддержку XML-запросов наших пользователей. По нашему мнению, основной код сервера должен оставаться настолько ``скудным и чистым'', насколько возможно, а взамен следует разрабатывать библиотеки, которые ``взвалят на свои плечи'' все сложности на клиентской стороне. Эта концепция полностью соответствует упомянутой выше стратегии - не жертвовать скоростью или надежностью сервера.

1.9.1 Каким стандартам соответствует MySQL ?

Начальный уровень SQL92. Для ODBC уровни 0-3.51.

Мы стремимся к полной поддержке стандарта ANSI SQL99, но без ущерба для скорости и качества кода.

1.9.2 Запуск MySQL в режиме ANSI

При запуске mysqld с опцией --ansi поведение сервера MySQL изменяется следующим образом:

  • || представляет собой конкатенацию строк вместо ИЛИ (OR).
  • Допускается любое количество пробелов между именем функции и скобкой `('. Это заставляет MySQL интерпретировать все имена функций как зарезервированные слова.
  • `"' будет интерпретироваться как символ кавычки идентификатора (как символ кавычки ``' сервера MySQL), а не как символ кавычки строки.
  • REAL будет синонимом для FLOAT, а не для DOUBLE.
  • Уровнем изоляции транзакций по умолчанию является SERIALIZABLE (see section 6.7.3 Синтаксис команды SET TRANSACTION).
  • Вы можете использовать столбец/выражение в GROUP BY, которое не перечислено в списке столбцов.

Использование данной опции равносильно применению --sql-mode=REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES, IGNORE_SPACE,SERIALIZE,ONLY_FULL_GROUP_BY.

1.9.3 Расширения MySQL к ANSI SQL92

Сервер MySQL включает в себя ряд расширений, которые могут отсутствовать в других базах данных SQL. Если вы их используете, то следует иметь в виду, что такой код не будет переносимым на другие SQL-серверы. В некоторых случаях можно написать код, включающий расширения MySQL, но, тем не менее, являющийся переносимым, воспользовавшись комментариями вида /*! ... */. В этом случае сервер MySQL будет анализировать и выполнять данный код внутри этого комментария как обычную команду MySQL, в то время как другие SQL-серверы будут игнорировать данное расширение. Например:

SELECT /*! STRAIGHT_JOIN */ col_name FROM table1,table2 WHERE ...

При добавлении номера версии после '!' это выражение будет исполняться только в случае, если номер данной версии MySQL равен указанному номеру или больше:

CREATE /*!32302 TEMPORARY */ TABLE t (a int);

Это означает, что при наличии версии 3.23.02 или выше сервер MySQL будет использовать ключевое слово TEMPORARY.

Ниже приводится перечень расширений MySQL:

  • Типы полей MEDIUMINT, SET, ENUM и различные типы BLOB и TEXT.
  • Атрибуты полей AUTO_INCREMENT, BINARY, NULL, UNSIGNED и ZEROFILL.
  • Все сравнения строк по умолчанию являются независимыми от регистра символов с порядком сортировки, заданным текущей кодировкой (ISO-8859-1 Latin1 по умолчанию). Если вас это не устраивает, то можно объявить столбцы с атрибутом BINARY или использовать явное приведение типов BINARY, в результате чего сравнение будет выполняться в соответствии с порядком ASCII, используемом на хосте сервера MySQL.
  • Сервер MySQL сопоставляет каждую базу данных с подкаталогом в каталоге данных MySQL, а таблицы внутри базы данных - с именами файлов в этом подкаталоге базы данных. Это правило имеет несколько следствий:
    • В сервере MySQL, работающем под операционными системами с зависимыми от регистра символов именами файлов (таковыми являются большинство Unix-систем), имена баз данных и имена таблиц являются зависимыми от регистра символов (see section 6.1.3 Чувствительность имен к регистру).
    • Имена базы данных, таблицы, индекса, столбца или псевдонимы могут начинаться с цифры (но не должны содержать только цифры).
    • Можно использовать стандартную систему команд выполнения резервного копирования, переименования, перемещения, удаления и копирования таблиц. Например, для переименования таблицы необходимо переименовать соответствующие этой таблице файлы `.MYD', `.MYI' и `.frm'.
  • В командах SQL можно обращаться к таблицам из разных баз данных с помощью выражения db_name.tbl_name. В некоторых SQL-серверах обеспечивается точно такая же функциональная возможность, но она называется User space. Сервер MySQL не поддерживает табличные пространства (как в выражении: CREATE TABLE ralph.my_table...IN my_tablespace).
  • LIKE разрешается на числовых столбцах.
  • Использование INTO OUTFILE и STRAIGHT_JOIN в команде SELECT (see section 6.4.1 Синтаксис оператора SELECT).
  • Опция SQL_SMALL_RESULT в команде SELECT.
  • Использование EXPLAIN SELECT для получения описаний объединения таблиц.
  • Использование индексных имен, индексов на префиксах полей, а также INDEX или KEY в команде CREATE TABLE (see section 6.5.3 Синтаксис оператора CREATE TABLE).
  • Использование TEMPORARY или IF NOT EXISTS с CREATE TABLE.
  • Использование COUNT(DISTINCT list), где list представляет собой более чем один элемент.
  • Использование CHANGE col_name, DROP col_name или DROP INDEX, IGNORE или RENAME в команде ALTER TABLE (see section 6.5.4 Синтаксис оператора ALTER TABLE).
  • Использование RENAME TABLE. See section 6.5.5 Синтаксис оператора RENAME TABLE.
  • Использование нескольких выражений ADD, ALTER, DROP или CHANGE в команде ALTER TABLE.
  • Использование DROP TABLE с ключевыми словами IF EXISTS.
  • Возможность удаления нескольких таблиц одной командой DROP TABLE.
  • Условие LIMIT в команде DELETE.
  • Условие DELAYED в командах INSERT и REPLACE.
  • Условие LOW_PRIORITY в командах INSERT, REPLACE, DELETE и UPDATE.
  • Использование LOAD DATA INFILE. Во многих случаях этот синтаксис совместим с применяющимся в Oracle LOAD DATA INFILE (see section 6.4.9 Синтаксис оператора LOAD DATA INFILE).
  • Команды ANALYZE TABLE, CHECK TABLE, OPTIMIZE TABLE и REPAIR TABLE.
  • Команда SHOW (see section 4.5.6 Синтаксис команды SHOW).
  • Строки могут быть заключены в кавычки с помощью или `"', или `'', но не просто `''.
  • Использование символа экранирования `\'.
  • Команда SET (see section 5.5.6 Синтаксис команды SET).
  • Нет необходимости называть имена всех выбранных столбцов в части GROUP BY. Это дает лучшую производительность для некоторых очень специфических, но вполне нормальных запросов (see section 6.3.7 Функции, используемые в операторах GROUP BY).
  • Можно указывать ASC и DESC с GROUP BY.
  • Чтобы упростить работу для пользователей, привыкших к иным условиям среды SQL, в сервере MySQL поддерживаются псевдонимы для многих функций. Например, для всех строковых функций поддерживается синтаксис как ANSI SQL, так и ODBC.
  • Сервер MySQL понимает операторы || и && для обозначения логических ИЛИ (OR) и И (AND), как это принято в языке программирования C. В сервере MySQL || и ИЛИ (OR) являются синонимами, так же, как && и И (AND). Благодаря этому удобному синтаксису, в сервере MySQL не поддерживается оператор ANSI SQL || для конкатенации строк: вместо него используется функция CONCAT(). Поскольку функция CONCAT() принимает любое количество аргументов, то в сервере MySQL можно легко модифицировать использование оператора ||.
  • CREATE DATABASE или DROP DATABASE (see section 6.5.1 Синтаксис оператора CREATE DATABASE).
  • Оператор % является синонимом для MOD(). Т.е. N % M эквивалентно MOD(N,M). Оператор % поддерживается для программистов на C и для совместимости с PostgreSQL.
  • Операторы =, <>, <=,<, >=,>, <<, >>, <=>, AND, OR или LIKE могут использоваться при сравнении столбцов слева от FROM в командах SELECT. Например:
    mysql> SELECT col1=1 AND col2=2 FROM tbl_name;
  • Функция LAST_INSERT_ID() (see section 8.4.3.31 mysql_insert_id()).
  • Операторы REGEXP и NOT REGEXP расширенных регулярных выражений.
  • CONCAT() или CHAR() с одним аргументом или более чем с двумя аргументами (в сервере MySQL эти функции могут принимать любое количество аргументов).
  • Функции BIT_COUNT(), CASE, ELT(), FROM_DAYS(), FORMAT(), IF(), PASSWORD(), ENCRYPT(), MD5(), ENCODE(), DECODE(), PERIOD_ADD(), PERIOD_DIFF(), TO_DAYS() или WEEKDAY().
  • Использование функции TRIM() для усечения подстрок. В ANSI SQL поддерживается только удаление единичных символов.
  • Операция GROUP BY для функций STD(), BIT_OR() и BIT_AND().
  • Использование REPLACE вместо DELETE + INSERT (see section 6.4.8 Синтаксис оператора REPLACE).
  • Команды FLUSH, RESET и DO.
  • Возможность устанавливать переменные в команде с помощью :=:
    SELECT @a:=SUM(total),@b=COUNT(*),@a/@b AS avg FROM test_table;
SELECT @t1:=(@t2:=1)+@t3:=4,@t1,@t2,@t3;

1.9.4 Отличия MySQL от ANSI SQL92

Наши усилия направлены на то, чтобы сервер MySQL соответствовал стандартам ANSI SQL и ODBC SQL, но в некоторых случаях сервер MySQL функционирует по-другому. Ниже приведен перечень таких отличий:

  • Для столбцов VARCHAR при хранении величины концевые пробелы удаляются (see section 1.9.5 Известные ошибки и недостатки проектирования в MySQL).
  • В некоторых случаях столбцы CHAR без уведомления изменяются на столбцы VARCHAR (see section 6.5.3.1 Молчаливые изменения определений столбцов).
  • Привилегии для таблицы не аннулируются автоматически при удалении таблицы; чтобы удалить привилегии для таблицы, необходимо явно вызвать REVOKE (see section 4.3.1 Синтаксис команд GRANT и REVOKE).
  • NULL AND FALSE будет трактоваться как NULL, а не как FALSE. Причина здесь в том, что мы не считаем необходимым оценивать множество дополнительных условий для этого случая.

Если вас интересует, когда к серверу MySQL будут добавляться новые расширения, необходимо обратиться к онлайновому списку перспективных задач к выполнению, в котором дан их перечень в порядке приоритетности. Он находится по адресу http://www.mysql.com/doc/en/TODO.html. Это самая последняя версия списка задач к выполнению (TODO list) в данном руководстве (see section 1.10 MySQL и будущее (что предстоит сделать)).

1.9.4.1 Вложенные SELECTы

В сервер MySQL поддерживает вложенные запросы вида INSERT ... SELECT ... и REPLACE ... SELECT .... В других контекстах можно использовать и функцию IN().

Вложенные операции выборки реализованы в версии 4.1.

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

SELECT * FROM table1 WHERE id IN (SELECT id FROM table2);

можно переписать следующим образом:

SELECT table1.* FROM table1,table2 WHERE table1.id=table2.id;

Запросы:

SELECT * FROM table1 WHERE id NOT IN (SELECT id FROM table2);
SELECT * FROM table1 WHERE NOT EXISTS (SELECT id FROM table2
         WHERE table1.id=table2.id);

эквивалентны следующему:

SELECT table1.* FROM table1 LEFT JOIN table2 ON table1.id=table2.id
                WHERE table2.id IS NULL;

Для более сложных подзапросов часто можно создать временные таблицы, содержащие данный подзапрос. Иногда, однако, этот способ не годится, чаще всего для команд DELETE, для которых в стандарте SQL не поддерживаются объединения (за исключением вложенных выборок). В этой ситуации возможны два временных (пока вложенные запросы не поддерживаются сервером MySQL) варианта решения проблемы.

Первый вариант следующий: при помощи какого-либо процедурно-ориентированного языка программирования (такого как Perl или PHP) делается запрос SELECT для получения первичных ключей тех записей, которые должны быть удалены, а затем полученные величины используются для составления команды DELETE (DELETE FROM ... WHERE ... IN (key1, key2, ...)).

Второй вариант предполагает применение диалогового SQL для автоматического создания набора команд DELETE с использованием расширения MySQL CONCAT() (вместо стандартного оператора ||). Например:

SELECT CONCAT('DELETE FROM tab1 WHERE pkid = ', "'", tab1.pkid, "'", ';')
       FROM tab1, tab2
       WHERE tab1.col1 = tab2.col2;

Можно поместить этот запрос в файл скрипта, перенаправить стандартный вход клиента командной строки с этого файла, а стандартный выход - на еще один экземпляр клиента командной строки:

shell> mysql --skip-column-names mydb < myscript.sql | mysql mydb

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

1.9.4.2 Оператор SELECT INTO TABLE

Для сервера MySQL пока не реализована поддержка расширения Oracle SQL: SELECT ... INTO TABLE .... Вместо этого сервер MySQL поддерживает синтаксис ANSI SQL INSERT INTO ... SELECT ..., который, по существу, представляет собой то же самое (see section 6.4.3.1 Синтаксис оператора INSERT ... SELECT).

INSERT INTO tblTemp2 (fldID) SELECT tblTemp1.fldOrder_ID
       FROM tblTemp1 WHERE tblTemp1.fldOrder_ID > 100;

Можно также использовать выражения SELECT INTO OUTFILE... или CREATE TABLE ... SELECT.

1.9.4.3 Транзакции и атомарные операции

Поддержка транзакций в сервере MySQL реализуется при помощи обработчиков транзакционных таблиц типов InnoDB и BDB (see section 7 Типы таблиц MySQL). Таблицы InnoDB обеспечивают соответствие требованиям ACID.

Однако для таблиц нетранзакционных типов, таких как MyISAM, в MySQL используется иная парадигма обеспечения целостности данных, получившая название ``атомарные операции''. Атомарные операции в сравнении с транзакциями часто обеспечивают такую же или даже лучшую целостность при более высокой производительности. Поскольку сервер MySQL поддерживает обе парадигмы, пользователь может выбирать между скоростью, которую обеспечивают атомарные операции, и транзакционными возможностями для своих приложений. Такой выбор может быть сделан для каждой таблицы отдельно.

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

  1. Транзакционная парадигма обеспечивает следующие возможности: если приложения написаны таким образом, что в критических ситуациях зависят от вызова ROLLBACK вместо COMMIT, то транзакции предпочтительней атомарных операций. Транзакции также обеспечивают гарантию того, что незаконченные обновления или искаженные действия не будут фиксироваться в базе данных; серверу предоставляется возможность выполнить автоматический откат, и база данных будет сохранена. Почти во всех случаях при работе с сервером MySQL решить возможные проблемы можно путем включения простых проверок перед обновлениями и запуска простых скриптов, которые выполняют проверку баз данных на нарушение целостности с автоматическим исправлением повреждений или выдачей предупреждения, если такое нарушение возникает. Отметим, что полноценное выявление и устранение ошибок в таблицах без потери целостности данных можно обеспечить, просто используя системный журнал MySQL или добавив еще один дополнительный журнал.
  2. Во многих случаях транзакционные обновления можно переписать как атомарные. В общем случае все проблемы, которые решаются с помощью транзакций, можно решить с помощью LOCK TABLES или атомарных UPDATE, при гарантии того, что в базе данных никогда не произойдет автоматического прерывания (что является часто встречающейся проблемой для транзакционных баз данных).
  3. Даже в транзакционной системе возможна потеря данных в случае внезапной остановки сервера (если сервер ``упадет''). Разница между различными системами состоит только в том, насколько мал промежуток времени, в течение которого данные могут быть потеряны. Ни одна система не является надежной на 100%, только ``достаточно надежной''. Даже для сервера Oracle (эта база данных считается наиболее надежной транзакционной базой данных), по сообщениям, в подобных ситуациях иногда возможна потеря данных. Что же касается использования сервера MySQL, то в любом случае, независимо от того, применяются или нет транзакционные таблицы, для обеспечения безопасности необходимо только иметь резервные копии и включенную регистрацию обновлений. Благодаря этим мерам в MySQL, так же как и в других транзакционных базах данных, можно восстановить информацию в любой ситуации. Резервные копии вообще хорошо иметь всегда, независимо от того, какая база данных используется.

Транзакционная парадигма имеет свои достоинства и свои недостатки. Для многих пользователей и разработчиков приложений решающее значение имеет простота кодирования в проблемных ситуациях, в которых может произойти или неизбежно аварийное прерывание. Однако даже если парадигма атомарных операций для вас нова или вы привыкли к транзакциям, все же следует принимать во внимание выигрыш в скорости, который могут обеспечить нетранзакционные таблицы (порядка от трех до пяти раз по сравнению со скоростью наиболее быстрых и оптимально настроенных транзакционных таблиц).

В ситуациях, где целостность данных чрезвычайно важна, сервер MySQL обеспечивает даже для нетранзакционных таблиц надежность и целостность данных уровня транзакций или лучше. При блокировании таблиц с помощью LOCK TABLES все обновления останавливаются до тех пор, пока не будут выполнены все проверки на целостность. При наличии только блокировки чтения (в противоположность блокировке записи) операции чтения и вставки, тем не менее, производятся. Новые внесенные записи не будут видны никому из имеющих блокировку чтения клиентов до освобождения этих блокировок. С iомощью INSERT DELAYED вставки становятся в очередь и находятся там до тех пор, пока не будут сняты все блокировки. При этом клиент не вынужден ждать, пока отработает INSERT (see section 6.4.4 Синтаксис оператора INSERT DELAYED).

То, что мы подразумеваем под термином ``атомарные'', не означает ничего сверхъестественного. Имеется в виду лишь следующее: гарантируется, что при выполнении каждого конкретного обновления никакой другой пользователь не может повлиять на него и никогда не произойдет автоматического отката (который возможен на транзакционных таблицах, если не приняты должные меры предосторожности). Сервер MySQL также гарантирует, что не случится грязного чтения (dirty read)".

Ниже описаны некоторые технические приемы работы с нетранзакционными таблицами:

  • Циклы, для которых требуются транзакции, обычно могут кодироваться с помощью LOCK TABLES, причем нет необходимости в указателях при динамическом обновлении записей.
  • Чтобы избежать применения ROLLBACK, можно использовать следующую стратегию:
    • Применить LOCK TABLES ... для блокирования всех таблиц, к которым необходим доступ.
    • Проверить условия.
    • Обновить, если все в порядке.
    • Использовать UNLOCK TABLES для освобождения произведенных блокировок.
    Обычно этот метод обеспечивает намного более высокую скорость, чем использование транзакций с возможными откатами, хотя и не всегда. Это решение не годится только для одной ситуации - когда кто-либо уничтожает потоки посреди обновления. В этом случае все блокировки будут сняты, но некоторые обновления могут не выполниться.
  • Для обновления записей в рамках одиночной операции можно также использовать функции. Применяя приведенные ниже технические приемы, вы получите очень эффективное приложение:
    • Поля модифицируются относительно их текущей величины.
    • Обновляются только те поля, которые действительно изменились.
    Например, при выполнении обновлений информации некоторого заказчика мы обновляем только те данные этого заказчика, которые изменялись, и делаем проверку только на предмет того, модифицировались ли изменяемые данные или зависящие от них по сравнению с исходной строкой. Проверка на то, изменялись или нет данные, выполняется с помощью выражения WHERE в команде UPDATE. Если данную запись обновить не удалось, то клиент получает сообщение: "Некоторые данные, которые вы изменяли, были модифицированы другим пользователем". После этого в окне выводится старая версия, чтобы пользователь мог решить, какую версию записи заказчика он должен использовать. Такой алгоритм обеспечивает нечто похожее на блокирование столбцов, но реально он даже лучше, поскольку мы обновляем только часть столбцов, используя величины, соответствующие их текущим значениям. Это означает, что типичные команды UPDATE выглядят примерно как приведенные ниже:
    UPDATE tablename SET pay_back=pay_back+'relative change';
UPDATE customer
  SET
    customer_date='current_date',
    address='new address',
    phone='new phone',
    money_he_owes_us=money_he_owes_us+'new_money'
  WHERE
    customer_id=id AND address='old address' AND phone='old phone';
    Как можно видеть, этот способ очень эффективно и работает, даже если другой клиент изменит величины в столбцах pay_back или money_he_owes_us.
  • Во многих случаях пользователи хотят применять ROLLBACK и/или LOCK TABLES для управления уникальными идентификаторами для разных таблиц. Того же результата можно добиться намного более эффективно, используя столбец AUTO_INCREMENT и либо SQL-функцию LAST_INSERT_ID(), либо функцию C API mysql_insert_id() (see section 8.4.3.31 mysql_insert_id()). В общем случае можно написать код и для блокирования на уровне строк. Для некоторых ситуаций это действительно необходимо, но таких случаев очень мало. Блокировка на уровне строк поддерживается в таблицах InnoDB. Для типа MyISAM можно использовать флаговые столбцы в таблице и выполнять запросы, подобные следующему:
    UPDATE tbl_name SET row_flag=1 WHERE id=ID;
    MySQL возвращает 1 в качестве количества подвергнутых воздействию строк, если данная строка была найдена, а row_flag в исходной строке не был уже равен 1. Это можно себе представить так, как будто сервер MySQL изменяет предшествующий запрос на:
    UPDATE tbl_name SET row_flag=1 WHERE id=ID AND row_flag <> 1;

1.9.4.4 Хранимые процедуры и триггеры

Хранимые процедуры представляют собой набор команд SQL, которые могут компилироваться и храниться на сервере. Таким образом, вместо того, чтобы хранить часто используемый запрос, клиенты могут ссылаться на соответствующую хранимую процедуру. Это обеспечивает лучшую производительность, поскольку данный запрос должен анализироваться только однажды и уменьшается трафик между сервером и клиентом. Концептуальный уровень можно также повысить за счет создания на сервере библиотеки функций.

Триггер представляет собой хранимую процедуру, которая активизируется при наступлении определенного события. Например, можно задать хранимую процедуру, которая срабатывает каждый раз при удалении записи из транзакционной таблицы - таким образом обеспечивается автоматическое удаление соответствующего заказчика из таблицы заказчиков, когда все его транзакции удаляются.

Возможность работы с хранимыми процедурами будет обеспечивать планируемый язык обновлений. Наша цель - ввести хранимые процедуры приблизительно в версию сервера MySQL 5.0. Мы работаем также и над триггерами.

1.9.4.5 Внешние ключи

Следует учитывать, что в SQL внешние ключи используются не для объединения таблиц, а главным образом для проверки целостности ссылочных данных (ограничения внешних ключей). Если необходимо получить результаты из большого количества таблиц от команды SELECT, следует делать это через объединение таблиц:

SELECT * FROM table1,table2 WHERE table1.id = table2.id;

См. разделы section 6.4.1.1 Синтаксис оператора JOIN и See section 3.5.6 Использование внешних ключей.

В версии сервера MySQL 3.23.44 и выше таблицы InnoDB поддерживают проверку ограничений внешних ключей (see section 7.5 Таблицы InnoDB). Для таблиц других типов сервер MySQL производит анализ синтаксиса FOREIGN KEY в командах CREATE TABLE, но без выполнения дальнейших действий.

Синтаксис FOREIGN KEY без ON DELETE ... главным образом применяется для целей документирования. В некоторых ODBC-приложениях его можно использовать для автоматического создания выражений WHERE, но обычно это легко сделать вручную. FOREIGN KEY иногда используется в качестве проверки ограничений, но на практике такая проверка не является необходимой, если строки вносятся в таблицу в правильном порядке.

В сервере MySQL можно обойти проблему отсутствия реализации ON DELETE ... добавлением соответствующей команды DELETE в приложение, когда удаляются записи из таблицы, имеющей внешний ключ. На практике при этом достигается почти такая же скорость (в некоторых случаях еще быстрее), как и при использование внешних ключей, и намного большая переносимость.

В версии сервера MySQL 4.0 можно использовать многотабличное удаление, чтобы удалить строки из многих таблиц одной командой (see section 6.4.6 Синтаксис оператора DELETE).

В ближайшем будущем мы расширим реализацию FOREIGN KEY таким образом, что информация будет сохраняться в специальном файле таблицы и ее можно будет извлечь с помощью mysqldump и ODBC. На следующем этапе мы внедрим ограничения внешних ключей для приложений, в которых не так просто обойтись без них.

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

Некоторые преимущества внедрения внешних ключей:

  • При условии, что связи спроектированы правильно, ограничения внешних ключей сделают более сложным для программиста введение противоречивости в базу данных.
  • Использование каскадных обновлений и удалений может упростить код клиента.
  • Должным образом разработанные правила внешних ключей помогают в документировании отношений между таблицами.

Недостатки:

  • Ошибки, которые легко сделать в проектировании отношений ключей, могут вызывать сложные проблемы: например, зацикленные правила или ложные комбинации каскадных удалений.
  • Правильно написанное приложение будет само по себе обеспечивать отсутствие нарушения целостности ссылочных данных перед началом работы запроса. Таким образом, дополнительные проверки на уровне базы данных только понизят производительность для такого приложения.
  • Администраторы баз данных часто создают такую сложную топологию связей, при которой затруднительно, а зачастую и вовсе невозможно получить резервную копию или восстановить единичные таблицы.

1.9.4.6 Представления

Представления планируется реализовать примерно в версии сервера MySQL 5.0.

Представления полезны в основном для случая, когда требуется предоставлять пользователям доступ к набору связей как к одной таблице (только в режиме чтения). Во многих базах данных SQL не обеспечивается возможность обновлять какие-либо строки в представлении - такие обновления необходимо выполнять в отдельных таблицах.

Поскольку сервер MySQL применяется в основном в приложениях и веб-системах, где разработчик приложения имеет полный контроль над использованием базы данных, большинство из наших пользователей не считают представления достаточно важной функциональной возможностью (по крайней мере, никто не заинтересовался ими настолько, чтобы выразить готовность финансировать реализацию представлений).

Для сервера MySQL нет необходимости в применении представлений для ограничения доступа к столбцам, так как в нем реализована хорошо продуманная система привилегий (see section 4.2 Общие проблемы безопасности и система привилегий доступа MySQL).

1.9.4.7 Символы `--' как начало комментария

В некоторых отличных от MySQL базах данных SQL символы `--' используются как начальные символы комментариев. В сервере MySQL символом начала комментариев является `#'. Для сервера MySQL можно также использовать стиль комментирования из C: /* this is a comment */ (see section 6.1.6 Синтаксис комментариев).

В версии сервера MySQL 3.23.3 и выше поддерживается комментирование с помощью символов `--' - при условии, что за комментарием следует пробел. Это объясняется тем, что данный стиль комментирования вызвал много проблем при автоматической генерации SQL-запросов, в которых присутствовал код, подобный приведенному ниже (величина платежа вставляется в выражение !payment! автоматически):

UPDATE tbl_name SET credit=credit-!payment!

Давайте представим себе, что произойдет в случае, если величина payment окажется отрицательной. Поскольку выражение 1--1 в SQL является допустимым, то просто страшно себе вообразить последствия в случае, если будут разрешены комментарии, начинающиеся с `--',

Использование нашей реализации этого метода комментирования в версии сервера MySQL 3.23.3 и выше - в форме 1-- This is a comment - является действительно безопасным.

Существует еще один безопасный способ решения этой проблемы. Он заключается в том, что клиент командной строки mysql удаляет все строки, начинающиеся с `--'.

Приведенная ниже информация относится только к работе более ранних, чем 3.23.3, версий MySQL.

Если ваша SQL-программа представлена в виде текстового файла, содержащего комментарии `--', необходимо использовать:

shell> replace " --" " #" < text-file-with-funny-comments.sql \
    | mysql database

вместо обычного:

shell> mysql database < text-file-with-funny-comments.sql

Можно также отредактировать сам командный файл, заменив комментарии `--' комментариями `#':

shell> replace " --" " #" -- text-file-with-funny-comments.sql

Привести эти комментарии к первоначальному виду можно с помощью следующей команды:

shell> replace " #" " --" -- text-file-with-funny-comments.sql

1.9.5 Известные ошибки и недостатки проектирования в MySQL

1.9.5.1 Ошибки, известные в 3.23 и исправленные в более поздних версиях MySQL

Следующие ошибки не исправлены в MySQL 3.23, поскольку исправление их требует слишком значительных изменений кода, которые могут повлечь создание еще большего количества ошибок. Эти ошибки классифицированы как "не фатальные" и "переносимые".

  • Можно получить взаимоблокировку при помощи LOCK TABLE на множестве таблиц, а затем выполнив в том же соединениии DROP TABLE одной из таблиц, пока другой поток пытается получить блокировку на таблицу. Однако можно уничтожить (KILL) эти потоки с тем, чтобы ситуация была исправлена. Исправлено в 4.0.12.
  • SELECT MAX(key_column) FROM t1,t2,t3... где одна из таблиц является пустой не вернет NULL, но вместо этого вернет максимальное значение для столбца. Исправлено в 4.0.11.

1.9.5.2 Открытые ошибки / особенности строения MySQL

Устранение следующих из выявленных проблем относится к числу первоочередных задач:

  • ANALYZE TABLE на таблицах BDB в некоторых случаях может сделать таблицу недоступной для использования, пока не произойдет перезапуск mysqld. При этом в файле ошибок MySQL можно будет увидеть ошибки, подобные следующим:
    001207 22:07:56 bdb: log_flush: LSN past current end-of-log
  • Не следует выполнять ALTER TABLE на таблицах BDB, на которых осуществляются многокомандные транзакции, пока все эти транзакции не завершатся (возможно, данные транзакции будут проигнорированы).
  • ANALYZE TABLE, OPTIMIZE TABLE и REPAIR TABLE могут вызвать проблемы на таблицах, для которых используется INSERT DELAYED.
  • Выполнение LOCK TABLE ... и FLUSH TABLES ... не гарантирует, что на данной таблице нет исполняемых в текущий момент незаконченных транзакций.
  • Открытие таблиц BDB происходит несколько медленно. Если база данных содержит много таблиц BDB, то потребуется значительное время для использования клиента mysql на этой базе данных, если не применять опцию -A или если использовать rehash. Это особенно заметно при наличии большого табличного кэша.

Следующие проблемы также известны и будут устранены в свое время:

  • При использовании функции RPAD, или любой другой строковой функции, добавляющией пробелы в правую часть строки, в запросе, для которого MySQL будет создавать временные таблицы для его выполнения, все результирующие строки будут в результате обработаны RTRIM'ом (RTRIM'ed). Вот пример запроса: SELECT RPAD(t1.field1, 50, ' ') AS f2, RPAD(t2.field2, 50, ' ') AS f1 FROM table1 as t1 LEFT JOIN table2 AS t2 ON t1.record=t2.joinID ORDER BY t2.record; В результате невозможно получить пробелы в правой части результирующего столбца. Такое поведение присутствует во всех версиях MySQL. Причина заключается в том, что HEAP-таблицы, которые в первую очередь используются для временных таблиц, неспособны работать с VARCHAR-столбцами. Такое поведение будет исправлено в одной из версий 4.1.
  • При использовании SET CHARACTER SET нельзя использовать преобразованные символы в именах базы данных, таблицы и столбца.
  • Нельзя использовать _ или % с ESCAPE в LIKE ... ESCAPE.
  • Если в столбце DECIMAL число хранится в различных форматах (+01.00, 1.00, 01.00), то GROUP BY может рассматривать каждую величину как самостоятельную.
  • DELETE FROM merge_table при использовании без WHERE будет очищать только отображение для этой таблицы, а не удалять все данные в отображенных таблицах.
  • При использовании потоков MIT-pthreads нельзя расположить сервер в ином каталоге. Поскольку для решения данной проблемы требуются изменения для потоков MIT-pthreads, маловероятно, что мы ее устраним (see section 2.3.6 Замечания по потокам MIT-pthreads).
  • Не обеспечивается ``надежное'' применение величин BLOB в GROUP BY или ORDER BY или DISTINCT. В этих случаях при сравнении величин BLOB используются только первые max_sort_length байтов (по умолчанию 1024). Это можно изменить с помощью опции -O max_sort_length для mysqld. Обходной путь для большинства случаев заключается в использовании подстроки: SELECT DISTINCT LEFT(blob,2048) FROM tbl_name.
  • В сервере MySQL вычисления производятся в форматах типов BIGINT или DOUBLE (оба типа обычно имеют длину 64 бита). Это зависит от того, какую точность обеспечивает применяемая функция. Общее правило состоит в том, что битовые функции работают с точностью BIGINT, функции IF и ELT() - с точностью BIGINT или DOUBLE, а остальные - с точностью DOUBLE. Следует избегать применения беззнаковых величин двойной точности, если они могут превысить 63 бита (9223372036854775807), для каких-либо величин, кроме битовых полей! В версии сервера MySQL 4.0 реализована лучшая обработка BIGINT, чем в 3.23.
  • Во всех строковых столбцах, исключая BLOB и TEXT при извлечении данных автоматически удаляются все концевые пробелы. Для типов CHAR это хорошо и может рассматриваться как свойство, соответствующее ANSI SQL92. Ошибка заключается в том, что в сервере MySQL столбцы VARCHAR трактуются тем же самым образом.
  • В одной таблице может быть только до 255 столбцов типа ENUM и SET.
  • В MIN(), MAX() и других групповых функциях, MySQL сейчас сравнивает ENUM и SET-столбцы по их строковому значению, а не по относительной позиции строки в множестве.
  • При указании параметра safe_mysqld все сообщения из mysqld направляются в журнал данного потока mysqld. Одна из проблем заключается в том, что если вы исполняете mysqladmin refresh для того, чтобы закрыть и заново открыть журнал, то stdout и stderr будут все еще по-прежнему направлены в старый журнал. При активном использовании --log следует отредактировать safe_mysqld, чтобы записи велись в ``hostname`.err', а не в ``hostname`.log', с тем, чтобы вы могли очищать пространство, удаляя старые журналы и вызывая mysqladmin refresh.
  • При выполнении команды UPDATE столбцы обновляются слева направо. При ссылке на обновленный столбец вместо исходной величины будет получена обновленная величина. Например:
    mysql> UPDATE tbl_name SET KEY=KEY+1,KEY=KEY+1;
    Эта команда обновит KEY со значением 2 вместо значения 1.
  • В одном и том же запросе нельзя использовать временные таблицы более чем один раз. Например, следующая команда выполнена не будет:
    mysql> SELECT * FROM temporary_table, temporary_table AS t2;
  • RENAME не работает с временными таблицами или при использовании таблицы MERGE.
  • Оптимизатор может обрабатывать DISTINCT по-разному, в зависимости от того, используются или нет в объединении ``скрытые'' столбцы. В объединении скрытые столбцы считаются частью результата (даже если они не показываются), в то время как в обычных запросах скрытые столбцы не участвуют в сравнении DISTINCT. Возможно, в будущем мы изменим это правило таким образом, чтобы при выполнении DISTINCT скрытые столбцы никогда не сравнивались. Например:
    SELECT DISTINCT mp3id FROM band_downloads
       WHERE userid = 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, что не разрешается делать в ANSI SQL.
  • Поскольку сервер MySQL обеспечивает возможность работать с типами таблиц, которые не поддерживают транзакции и, следовательно, не допускают отката данных, то поведение сервера MySQL в некоторых аспектах отличается от других серверов SQL. Это делается, чтобы гарантировать, что сервер MySQL никогда не будет нуждаться в откате SQL-команд. Такое поведение временами может быть несколько неудобным, так как вследствие этого величины столбцов должны проверяться в приложении. Однако благодаря такому решению вы получаете действительно хорошее увеличение скорости, поскольку для сервера MySQL обеспечивается возможность производить определенные оптимизации, что в противном случае было бы очень трудно сделать. При попытке установить столбец в некорректную величину сервер MySQL вместо выполнения отката будет сохранять в данном столбце ``наиболее вероятную величину'':
    • При попытке сохранить в числовом столбце величину, выходящую за допустимые пределы, сервер MySQL вместо нее будет сохранять в этом столбце наименьшую или наибольшую допустимую величину.
    • При попытке сохранить в числовом столбце строку, которая начинается не с числа, сервер MySQL будет сохранять в нем 0.
    • При попытке сохранить NULL в числовом столбце, который не принимает значения величины NULL, сервер MySQL вместо NULL будет сохранять 0 или '' (пустая строка) (однако это поведение можно изменить с помощью опции компиляции -DDONT_USE_DEFAULT_FIELDS).
    • MySQL обеспечивает возможность сохранять некоторые ошибочные величины даты в столбцах DATE и DATETIME (такие как 2000-02-31 или 2000-02-00). Идея заключается в том, что задача проверки валидности даты не входит в круг обязанностей сервера баз данных. Если MySQL может сохранить и корректно воспроизвести какие-либо значение даты, пусть и неправильное - MySQL будет сохранять такое значение. Если дата полностью неправильна, сервер MySQL будет сохранять в этом столбце специальную величину даты 0000-00-00.
    • Если устанавливать столбец ENUM в неподдерживаемую величину, то он будет устанавливаться в значение ошибки empty string с числовым значением 0.
    • Если устанавливать столбец SET в неподдерживаемую величину, то эта величина будет игнорироваться.
  • При выполнении PROCEDURE на запросе, возвращающем пустой набор, в некоторых случаях PROCEDURE не будет преобразовывать столбцы.
  • При создании таблицы типа MERGE не происходит проверки, если лежащие в ее основе таблицы имеют совместимые типы.
  • Сервер MySQL пока еще не может обрабатывать величины NaN, -Inf и Inf с двойной точностью. Их использование вызовет проблемы при попытке экспорта или импорта данных. В качестве промежуточного решения мы должны изменить NaN на NULL (если возможно) и -Inf и Inf на минимальную или, соответственно, максимально возможную величину двойной точности.
  • LIMIT на отрицательных числах трактуются как большие положительные числа.
  • Если ALTER TABLE используется для того, чтобы сначала добавить индекс UNIQUE к таблице, которая входит в таблицу MERGE, а затем - чтобы добавить обычный индекс к таблице MERGE, то в случае, если существовал старый ключ, который не был уникальным в данной таблице, порядок ключей для таблиц будет различным. Это обусловлено тем, что ALTER TABLE помещает уникальные ключи перед обычными ключами, чтобы обеспечить возможность определять дублирующиеся ключи как можно раньше.

В более ранних версиях MySQL известны следующие ошибки:

  • Можно получить зависший поток при выполнении DROP TABLE на таблице, которая является одной из числа многих таблиц, заблокированных с помощью LOCK TABLES.
  • В следующем случае может произойти аварийное завершение процесса:
    • Обработчик задержанных вставок имеет незаконченные вставки в таблицу.
    • LOCK table с помощью WRITE.
    • FLUSH TABLES.
  • В версиях сервера MySQL до 3.23.2 команда UPDATE, которая обновляла ключ с помощью WHERE на тот же самый ключ, может оказаться неудачной, поскольку данный ключ использовался для поиска записей и одна и та же строка может быть найдена много раз:
    UPDATE tbl_name SET KEY=KEY+1 WHERE KEY > 100;
    Обходным решением является использование:
    mysql> UPDATE tbl_name SET KEY=KEY+1 WHERE KEY+0 > 100;
    Эта команда будет работать, поскольку сервер MySQL не будет использовать индекс на выражениях в утверждении WHERE.
  • До версии сервера MySQL 3.23 все числовые типы трактовались как поля с фиксированной точкой. Это означает, что необходимо было указывать, сколько десятичных знаков должно содержать поле с плавающей точкой. Все результаты возвращались с правильным количеством десятичных знаков.

В отношении ошибок, связанных со спецификой различных платформ, см. разделы о компилировании и переносе.

1.10 MySQL и будущее (что предстоит сделать)

В этом разделе приведен список возможностей, которые планируется реализовать в MySQL.

Разработка приведенных в списке пунктов будет проходить примерно в порядке их перечисления. Если вы считаете, что это порядок следует изменить, то, пожалуйста, зарегистрируйте лицензию или окажите поддержку MySQL АВ и сообщите нам, что желательно было бы разработать побыстрее. See section 1.6 Лицензии и поддержка MySQL.

Планируется, что в будущем стандарт ANSI SQL99 будет поддерживаться полностью, но с большим числом полезных расширений. Проблема заключается в том, чтобы сделать все намеченное, не жертвуя скоростью и без компромиссов при кодировании.

1.10.1 Что планируется реализовать в версии в 4.0

Уже все сделано. Сейчас мы только исправляем обнаруженные ошибки в MySQL 4.0. See section C.2 Изменения в версии 4.0.x (В разработке; Альфа). Сейчас ведется разработка версий 4.1 и 5.0.

1.10.2 Что планируется реализовать в версии 4.1

Следующие возможности планируются для реализации в MySQL 4.1. Список того, что уже сделано, можно найти в See section C.1 Изменения в версии 4.1.x (Alpha).

  • Стабильная поддержка OpenSSL (MySQL 4.0 поддерживает базовую, не 100%-протестированную поддержку OpenSSL).
  • Схема перекодировки и синтаксис для поддержки множества разных кодировок.
  • Встроенная помощь для всех команд из клиента командной строки.
  • Больше тестирования подготовленных выражений и множественных кодировок для одной таблицы.

1.10.3 Что планируется реализовать в версии 5.0

Перечисленные ниже функции планируется реализовать в MySQL 5.0.

Отметим также, что поскольку у нас над новыми проектами работает большое количество разработчиков, появятся и дополнительные возможности. Существует - хотя и очень небольшая - вероятность, что эти возможности будут введены уже в MySQL 4.1. Список того, что уже сделано в 4.1, можно найти в See section C.1 Изменения в версии 4.1.x (Alpha).

  • Хранимые процедуры
  • Поддержка внешних ключей для всех типов таблиц.
  • Новый текстовый формат файлов определения структуры таблиц (`.frm'-файлы) и табличный кэш для определений таблиц. Это позволит нам быстрее получать информацию о структуре таблиц и более качественно поддерживать внешние ключи.
  • SHOW COLUMNS FROM table_name (используемый клиентом mysql для получения информации о столбцах) не должен открывать таблицы, а только файл определения структуры. Это занимает меньше памяти и будет работать быстрее.
  • Отказобезопасная репликация.
  • Резервное копирование без остановки работы системы с очень малыми затратами на выполнение. Резервное копирование без остановки работы системы позволит добавлять новый подчиненный сервер репликации без демонтажа головного сервера.
  • ROLLUP и CUBE OLAP (Online Analytical Processing) опции группировки для приложения хранения данных (Data warehousing).
  • Обеспечить возможность для DELETE, работающей с MyISAM-таблицами, использовать кэш записей. Чтобы осуществить это, нам необходимо обновлять кэш записей потока при обновлении `.MYD'-файла.
  • При использовании SET CHARACTER SET мы должны преобразовать весь запрос целиком, а не только строки. Это позволит пользователям использовать сконвертированные символы в именах баз данных, таблиц и столбцов.
  • Решить проблему, заключающуюся в том, что оператор RENAME TABLE, использующийся для активной MERGE-таблицы, может повредить таблицу.
  • Добавить к клиент-серверному протоколу возможность получения информации о прогрессе выполнения для сложных и длительных запросов.
  • Реализовать RENAME DATABASE. Чтобы сделать эту команду безопасной для всех обработчиков таблиц, она будет работать следующим образом:
    • Создавать новую базу данных.
    • Переименовывать каждую таблицу, помещаемую в новую базу данных, как это обычно делается командой RENAME.
    • Удалять старую базу данных.
    • Добавить корректную поддержку VARCHAR (такая поддержка уже имеется для MyISAM).
  • Оптимизировать тип BIT, чтобы он занимал 1 бит (сейчас 1 символ).
  • Новое изменение внутреннего файлового интерфейса. Это позволит сделать обработку всех файлов более однотипной и упростит добавление такой функциональности, как RAID (текущая реализация - это просто хак).
  • Улучшенные таблицы в памяти (HEAP):
    • Записи динамического размера
    • Более быстрая обработка строк (сокращение операций копирования)

1.10.4 Что должно быть сделано в ближайшем будущем

  • Не разрешать более чем определенному количеству потоков одновременно заниматься восстановлением MyISAM-таблиц.
  • Изменение INSERT ... SELECT с целью оптимального использования одновременных вставок.
  • Возвращать истинные типы полей при выполнении SELECT MIN(столбец) GROUP BY.
  • Множественные результаты.
  • Сделать возможным задание long_query_time с градацией в микросекундах.
  • Cлинковать код myisampack прямо в сервер.
  • Перенос кода MySQL на QNX.
  • Перенос кода MySQL на BeOS.
  • Перенос MySQL-клиентов на LynxOS.
  • Добавление временного буферного кэша ключей во время выполнения INSERT/DELETE/UPDATE, чтобы обеспечить изящное восстановление в случае, если индексный файл окажется полностью заполненным.
  • Если выполняется работа ALTER TABLE над таблицей, которая имеет символическую ссылку на другой диск, создавать временные таблицы на этом диске.
  • Реализация типа DATE/DATETIME с корректной обработкой информации о временных зонах, чтобы упростить работу с форматом даты для различных временных зон.
  • FreeBSD и MIT-pthreads; отнимают ли спящие потоки время процессора?
  • Проверить, занимают ли блокированные потоки время процессора.
  • Исправить configure так, чтобы можно было компилировать все библиотеки (подобно MyISAM) без потоков.
  • Добавить опцию периодического сброса на диск страниц ключей для таблиц с запрещенными, в случае, если они некоторое время не использовались.
  • Возможность связывания по частям ключа (проблема оптимизации).
  • INSERT SQL_CONCURRENT и mysqld --concurrent-insert для выполнения одновременной вставки в конец файла, если файл закрыт для чтения.
  • Серверные курсоры.
  • Проверить, работает ли lockd с современными ядрами Linux; если нет, то внести исправления в lockd! Чтобы это протестировать, необходимо запустить mysqld с --enable-locking и выполнить различные наборы тестов на fork*. Они не должны выявить никаких ошибок, если lockd работает.
  • Возможность использования SQL-переменных в LIMIT, как, например, в LIMIT @a,@b.
  • Возможность обновления переменных в операторах UPDATE. Например: UPDATE TABLE foo SET @a=a+b,a=@a, b=@a+c.
  • Изменение: если пользовательские переменные обновляются, то сделать так, чтобы их можно было использовать с GROUP BY, как в следующем примере: SELECT id, @a:=COUNT(*), SUM(sum_col)/@a FROM table_name GROUP BY id.
  • Запретить автоматическое внесение DEFAULT-значений (значений по умолчанию) в столбцы. Выдавать ошибку в случае использования INSERT, не содержащего столбца, для которого не определено значение по умолчанию.
  • Исправить libmysql.c так, чтобы две команды mysql_query(), идущие подряд, могли работать без чтения результатов или с выдачей хорошего сообщения об ошибке, если это все-таки происходит.
  • Проверка, почему функция ctime() потоков MIT-pthreads не работает на некоторых FreeBSD системах.
  • Добавление опции IMAGE опции к LOAD DATA INFILE, чтобы не обновлять поля TIMESTAMP и AUTO_INCREMENT.
  • Добавляемый синтаксис LOAD DATE INFILE ... UPDATE.
  • Для таблиц с первичными ключами: если данные содержат первичный ключ, строки, соответствующие этому первичному ключу, обновляются остальными столбцами. Столбцы, которых нет во входных данных, остаются без изменений.
  • Для таблиц с первичными ключами, для которых отсутствует некоторая часть ключа во входном потоке данных или которые не имеют первичного ключа, входные данные интерпретируются сейчас как LOAD DATA INFILE ... REPLACE INTO.
  • Сделать понятный синтаксис LOAD DATA INFILE, подобно следующему:
    LOAD DATA INFILE 'file_name.txt' INTO TABLE tbl_name
     TEXT_FIELDS (text_field1, text_field2, text_field3)
     SET table_field1=CONCAT(text_field1, text_field2),
         table_field3=23
     IGNORE text_field3
    Такой синтаксис может быть использован для пропуска лишних столбцов в текстовом файле или для обновления столбцов на основе выражений, построенных по прочитанным данным.
  • LOAD DATA INFILE 'file_name' INTO TABLE 'table_name' ERRORS TO err_table_name. Этот оператор задает запись всех ошибок и предупреждений в таблицу err_table_name, которая будет иметь структуру, подобную следующей:
    line_number   - номер строки в файле данных
error_message - сообщение об ошибке/предупреждение
  и, возможно
data_line     - строка из файла данных
  • Автоматический вывод из mysql в Netscape.
  • LOCK DATABASES (с различными опциями.)
  • Функции: ADD_TO_SET(value,set) и REMOVE_FROM_SET(value,set).
  • Добавить использование t1 JOIN t2 ON ... и t1 JOIN t2 USING ... В данное время можно использовать этот синтаксис только с LEFT JOIN.
  • Намного большее количество переменных для SHOW STATUS. Фиксирование операций чтения и обновления. Выборки по 1 таблице и выборки по связям. Среднее число таблиц в выборке. Большое число запросов ORDER BY и GROUP BY.
  • Если вы прерываете выполнение запроса в середине, необходимо открыть другое соединение и убить старый выполнявшийся запрос. В свою очередь, сервер должен распознавать это на своей стороне.
  • Добавить интерфейс обработчика для табличных данных таким образом, чтобы была возможность использовать его как системную таблицу. Это будет работать несколько медленно в случае запрашивания информации обо всех таблицах, но очень гибко. Должен быть реализован SHOW INFO FROM tbl_name для основных данных о таблицах.
  • Сделать возможным SELECT a FROM crash_me LEFT JOIN crash_me2 USING (a); в данном случае подразумевается, что a будет браться из таблицы crash_me.
  • Oracle-подобный CONNECT BY PRIOR ... для изучения иерархических структур.
  • mysqladmin copy database new-database; требуется добавить команду COPY в mysqld.
  • Список процессов должен показывать количество запросов/потоков.
  • SHOW HOSTS для распечатки информации о кэше имен хостов.
  • Опции DELETE и REPLACE для оператора UPDATE (оператор с этими опциями будет удалять строки при получении ошибки дублирующихся ключей во время обновления).
  • Изменить формат DATETIME, чтобы сохранять порции в секундах.
  • Добавить все недостающие типы ANSI92 и ODBC 3.0.
  • Изменить имена таблиц с пустых строк на NULL для вычисляемых столбцов.
  • Не использовать Item_copy_string для числовых значений во избежание преобразований число->строка->число в случае: SELECT COUNT(*)*(id+0) FROM table_name GROUP BY id
  • Сделать возможным использование новой библиотеки GNU regexp вместо текущей (библиотека GNU должна быть намного быстрее, чем предыдущая).
  • Сделать так, чтобы ALTER TABLE не срывал работу INSERT DELAYED.
  • Сделать следующее исправление: если на столбцы есть ссылки в выражении UPDATE, они будут содержать значения, хранившиеся там до запуска процесса обновления.
  • Добавить эмуляцию pread()/pwrite() под Windows, чтобы сделать возможными одновременные вставки.
  • Разработать анализатор файла журнала для анализа и выдачи информации о том, какие таблицы используются наиболее часто, насколько часто выполняются мультитабличные связи и т.д. Это помогло бы пользователям выбирать такую конструкцию таблиц и областей, которая могла бы быть оптимизирована для выполнения наиболее эффективных запросов.
  • Добавить SUM(DISTINCT).
  • Добавить групповые функции ANY(), EVERY() и SOME(). В ANSI SQL эти функции работают только с булевыми столбцами, но мы можем расширить эти функции, чтобы они работали с любыми столбцами/выражениями, применив: value == 0 -> FALSE и value <> 0 -> TRUE.
  • Добиться, чтобы тип для MAX(column) был таким же как и тип столбцов:
    mysql> CREATE TABLE t1 (a DATE);
mysql> INSERT INTO t1 VALUES (NOW());
mysql> CREATE TABLE t2 SELECT MAX(a) FROM t1;
mysql> SHOW COLUMNS FROM t2;
  • Придумать хороший синтаксис для оператора, который будет выполнять UPDATE над строкой при наличии таковой, и INSERT новой строки, если строка отсутствует (подобно тому, как REPLACE работает с INSERT / DELETE).

1.10.5 То, что надо сделать когда-нибудь

  • Реализовать функцию: get_changed_tables(timeout,table1,table2,...).
  • Изменить чтение таблиц так, чтобы везде, где возможно. использовалась memmap. Сейчас memmap используется только для уплотненных таблиц.
  • Сделать лучше автоматический код временных меток (timestamp). Добавлять временные метки в журнал обновлений при помощи SET TIMESTAMP=#;.
  • Использовать в некоторых местах семафор чтения/записи для увеличения скорости.
  • Обеспечить полную поддержку внешних ключей в MyISAM-таблицах (возможно, после реализации хранимых процедур с триггерами).
  • Подготовить простые обзоры (сначала по одной таблице, позднее по любому выражению).
  • Реализовать автоматическое закрытие некоторых таблиц, если таблица, временная таблица или временные файлы получат ошибку 23 (недостаточно открытых файлов).
  • Если обнаружится поле=#, заменить все местонахождения поля на #. Сейчас такое делается только для некоторых простых случаев.
  • Заменить все константные выражения вычисляемыми, если возможно.
  • Реализовать оптимизацию ключ=выражение. К данному моменту делается оптимизация только для ключ=поле или ключ=константа.
  • Связывать некоторые функции копирования для улучшения кода.
  • Заменить sql_yacc.yy внутритекстовым синтаксическим анализатором, чтобы уменьшить ее размер и получать лучшие сообщения об ошибке (5 дней).
  • Изменить собственный синтаксический анализатор так, чтобы он использовал только одно правило для различного количества аргументов в функции.
  • Использовать полные вычисляемые имена в части сортировки (для ACCESS97).
  • MINUS, INTERSECT и FULL OUTER JOIN (в настоящее время поддерживаются UNION [в 4.0] и LEFT OUTER JOIN).
  • SQL_OPTION MAX_SELECT_TIME=#, чтобы устанавливать ограничения по времени для запроса.
  • Сделать так, чтобы обновляемый журнал записывался в базу данных..
  • Сделать добавления в LIMIT, чтобы можно было делать восстановление данных с конца результирующего набора.
  • Сигналы предупреждений для функций соединения/чтения/записи клиента.
  • Необходимо обратить внимание на изменения на safe_mysqld; согласно FSSTND (которому пытается следовать Debian) PID-файлы должны помещаться в `/var/run/<progname>.pid', a файлы журналов - в `/var/log'. Было бы хорошо, если бы было можно поместить "`DATADIR'" в первое объявление "`pidfile'" и "`log'", чтобы местоположение этих файлов можно было изменить одним оператором.
  • Разрешать клиенту запрашивать ведение журналов.
  • Добавить использование zlib() для gzip-файлов в LOAD DATA INFILE.
  • Исправить сортировку и группирование BLOB-столбцов (сейчас проблема частично решена).
  • Хранимые процедуры. Рассматриваются также триггеры.
  • Простой (атомарный) язык обновления, который может быть использован для написания циклов и т.п. в MySQL-сервере.
  • Произвести изменения для того, чтобы пользоваться семафорами при подсчете потоков. Но сначала нужно реализовать библиотеку семафоров для потоков MIT-pthreads.
  • Не устанавливать новое значение во время установки колонки в 0. вместо этого использовать NULL.
  • Добавить полную поддержку круглых скобок для JOIN.
  • В качестве альтернативы одному потоку/соединению управлять пулом потоков при обработке запросов.
  • Обеспечить возможность получать более чем одну блокировку при помощи GET_LOCK. Когда это будет реализовано, потребуется еще сделать обработку возможных тупиковых ситуаций, которые привнесет данное изменение.

Время отводится согласно объемам работ, а не реальному времени.

1.10.6 То, чего не планируется делать

  • Такого не существует; мы стремимся к полной совместимости с ANSI 92/ANSI 99.

1.11 Сравнение MySQL с другими СУБД

Наши пользователи провели исследование скорости работы нескольких обычных серверов баз данных и серверов баз данных с открытым кодом. Нам известно о проводившихся сравнениях MySQL с сервером Oracle, сервером DB/2, Microsoft SQL Server и другими коммерческими программными продуктами. Однако по причинам юридического характера опубликовать результаты некоторых из этих сравнений в документации не представляется возможным.

В данном разделе приведены результаты сравнения с mSQL (проводившегося по историческим причинам) и с PostgreSQL (так как эта СУБД также распространяется как ПО с открытым кодом). Если у вас имеются результаты подобного тестирования, которые мы могли бы опубликовать, просьба связаться с нами по адресу benchmarks@mysql.com.

Сравнения всех имеющихся функций и типов а также данные о пределах возможностей различных СУБД вы найдете на веб-странице crash-me, расположенной по адресу http://www.mysql.com/information/crash-me.php.

1.11.1 Сравнение MySQL и mSQL

Производительность
Точные результаты сравнения скорости работы можно найти в постоянно пополняющейся библиотеке проведенных тестов по MySQL (see section 5.1.4 Набор тестов MySQL (The MySQL Benchmark Suite)). СУБД mSQL, благодаря отсутствию затрат дополнительных ресурсов на создание потоков, а также за счет компактности синтаксического анализатора, небольшого количества функций и упрощенной системы безопасности, должна выигрывать в скорости выполнения:
  • тестов на выполнение циклов соединение-отсоединение, при каждом соединении выполняющих какой-нибудь простой запрос
  • операций INSERT над простыми таблицами, содержащими небольшое количество столбцов и ключей
  • CREATE TABLE и DROP TABLE
  • операций SELECT чего-нибудь, кроме индексов (очень просто выполняется просмотр таблицы)
Поскольку такие операции очень просты, при больших затратах ресурсов на начальном этапе выиграть в скорости их выполнения достаточно сложно. Поэтому лучшие результаты MySQL может показать лишь после установки соединения. С другой стороны, MySQL значительно превосходит mSQL (и большинство других реализаций SQL) при:
  • выполнении сложных операций SELECT.
  • загрузке объемных результатов (протокол, применяющийся в MySQL, превосходит другие по качеству, скорости и безопасности).
  • работе с таблицами, имеющими строки переменной длины, так как обработка данных в MySQL реализована более эффективно и в нем допускается создание индексов для столбцов с типом VARCHAR.
  • обработке таблиц, содержащих большое количество столбцов.
  • обработке таблиц с длинными записями.
  • выполнении операций SELECT с несколькими выражениями.
  • выполнении операций SELECT над объемными таблицами.
  • одновременной работе с несколькими соединениями. Архитектура MySQL Server является полностью многопоточной. Для каждого соединения создается отдельный поток и, таким образом, ни одному из них не приходится ожидать завершения другого (если, конечно, один из потоков не занимается изменением таблицы, доступ к которой требуется другому потоку). В mSQL же после установки одного соединения остальным приходится ожидать его завершения, вне зависимости от сложности и времени выполнения примененного в этом соединении запроса. По завершении первого соединения начинает обслуживаться второе, а все остальные снова ждут своей очереди.
  • связывании таблиц. При изменении порядка таблиц в вызове SELECT, скорость работы mSQL может упасть ниже всяких допустимых пределов. При выполнении комплекта тестов производительности выполнение такой операции заняло в 15000 раз больше времени, чем у MySQL. Причиной столь плачевно низкой производительности является отсутствие в mSQL оптимизатора связей, который обеспечивал бы оптимальность используемого порядка соединения таблиц. Однако если в mSQL2 расположить таблицы в правильном порядке, не перегружать оператор WHERE и использовать индексные столбцы, связывание будет выполнено относительно быстро! (see section 5.1.4 Набор тестов MySQL (The MySQL Benchmark Suite)).
  • ORDER BY и GROUP BY.
  • DISTINCT.
  • работе со столбцами с типами TEXT или BLOB.
Возможности SQL
  • GROUP BY и HAVING. В mSQL функция GROUP BY отсутствует вовсе. В MySQL Server же GROUP BY имеется и работает как с HAVING, так и со следующими функциями: COUNT(), AVG(), MIN(), MAX(), SUM()и STD(). Работа оператора COUNT(*) оптимизирована в расчете на быстрый возврат результатов, если оператор SELECT берет данные из одной таблицы, не используя никаких других столбцов и выражения WHERE. Функции MIN() и MAX() могут принимать строковые аргументы.
  • INSERT и UPDATE с вычислениями. MySQL может выполнять вычисления непосредственно в теле вызова INSERT или UPDATE. Вот пример:
    mysql> UPDATE SET x=x*10+y WHERE x<20;
  • Псевдонимы. В MySQL имеется возможность определения псевдонимов столбцов.
  • Квалификация имен столбцов. В MySQL, при условии уникальности имени столбца среди таблиц, использующихся при выполнении запроса, нет необходимости приводить его полный квалификатор.
  • SELECT с функциями. Функций в MySQL много (даже слишком много, чтобы их можно было перечислить здесь; see section 6.3 Функции, используемые в операторах SELECT и WHERE).
Эффективность использования дискового пространства
Можно ли уменьшить таблицы, и если да, то насколько? В MySQL имеются очень точные типы данных, а с их помощью можно создавать таблицы, занимающие минимум пространства. Примером чрезвычайно полезного типа данных MySQL может служить MEDIUMINT, длина значений которого составляет 3 байта. При наличии 100 миллионов записей значение экономии даже одного байта на каждой из них трудно переоценить. Выбор типов столбцов в mSQL2 значительно беднее, и поэтому снизить размеры таблиц заметно трудней.
Стабильность
Объективно оценить этот параметр трудно. Подробно вопрос стабильности MySQL рассмотрен в разделе section 1.4.3 Насколько стабильным является MySQL?. Данных и опыта, позволяющих судить о стабильности mSQL, у нас не имеется.
Стоимость
Цена лицензии является немаловажным фактором. По гибкости лицензии MySQL Server превосходит mSQL, да и стоит меньше. Вне зависимости от того, какой из продуктов вы выберете, не забудьте принять во внимание стоимость лицензии или технической поддержки по электронной почте.
Perl-интерфейсы
Perl-интерфейсы MySQL практически идентичны своим аналогам из mSQL, хотя и обладают некоторыми дополнительными возможностями.
JDBC (Java)
В настоящее время для MySQL разработано много разнообразных JDBC-драйверов:
  • MySQL Connector/J - родной драйвер для Java. Версия 3.x выпускается под двойным лицензированием (GPL и коммерческая лицензия).
  • Драйвер Resin: коммерческий JDBC-драйвер, распространяющийся как ПО с открытым кодом. http://www.caucho.com/projects/jdbc-mysql/index.xtp
  • Драйвер gwe: Java-интерфейс, разработанный компанией GWE technologies (более не поддерживается).
  • Драйвер jms: улучшенная версия драйвера gwe, разработанная Кельвином Заоку Жу (Xiaokun Kelvin ZHU, X.Zhu@brad.ac.uk) (более не поддерживается).
  • Драйвер twz: JDBC-драйвер типа 4, разработанный Терренсом В. Зеллерсом (Terrence W. Zellers zellert@voicenet.com). Это коммерческий продукт, но в частном порядке и для образовательных целей им можно пользоваться бесплатно (более не поддерживается).
Рекомендуется использование драйвера mm. Драйвер Resin тоже, возможно, неплох (по крайней мере, результаты тестов выглядят хорошо), но достаточного количества информации по нему у нас пока нет. Мы знаем, что в mSQL имеется JDBC-драйвер, но для сравнения у нас не хватает опыта работы с ним.
Скорость разработки
Основная команда разработчиков MySQL немногочисленна, но мы привыкли писать код на C и C++ очень быстро. Так как потоки, функции, оператор GROUP BY и т.п. в mSQL все еще не реализованы, этой системе еще долго придется догонять нас. Более точное представление о положении вещей вы сможете получить, прочитав файл `HISTORY' от mSQL за последний год, и сравнив его с разделом новостей (News) MySQL Reference Manual (see section C История изменений и обновлений MySQL). После этого сомнений относительно того, какая система развивалась быстрее, остаться не должно.
Инструментальные программы
Как для mSQL, так и для MySQL сторонними разработчиками было создано множество интересных инструментальных средств. Поскольку перенос программ из mSQL в MySQL сложностей не представляет, почти все интересные приложения, разработанные первоначально для mSQL,имеются и в вариантах для MySQL. В комплект поставки MySQL входит простая программа msql2mysql, исправляющая различия в написании наиболее популярных функций C API между mSQL и MySQL. Вызовы функции msqlConnect(), например, она заменяет на mysql_connect(). Обычно для перевода клиентской программы из mSQL в MySQL оказывается достаточно минимальных усилий.

1.11.1.1 Как конвертировать инструментальные средства mSQL в MySQL

Согласно нашему опыту, переделать такие инструментальные программы, как msql-tcl и msqljava, созданные на основе C API mSQL для работы с C API MySQL, несложно.

Сделать это можно так:

  1. Пропустите исходный файл через сценарий оболочки msql2mysql. Для этого необходима программа replace, распространяющаяся вместе с MySQL Server.
  2. Откомпилируйте.
  3. Исправьте все найденные компилятором ошибки.

Различия между реализациями C API в mSQL и MySQL заключаются в следующем:

  • В качестве типа в MySQL используется структура MYSQL (в mSQL в этом качестве применяется int).
  • Оператор mysql_connect() принимает в качестве параметра указатель на структуру MYSQL. Такую структуру можно легко объявить как глобальную или создать ее с помощью malloc(). Кроме того, mysql_connect() принимает еще два параметра, в которых указываются имя пользователя и его пароль. Для использования данной структуры по умолчанию этим параметрам нужно присвоить значения NULL, NULL.
  • mysql_error() принимает в качестве параметра структуру MYSQL. При переносе старого кода достаточно добавить параметр в вызов msql_error().
  • Для всех ошибок MySQL возвращает номер ошибки и текстовое сообщение. mSQL же возвращает только текстовое сообщение об ошибке.
  • Существует некоторая несовместимость, обусловленная тем, что в MySQL Server можно создавать несколько соединений с сервером из одного и того же процесса.

1.11.1.2 Различия в клиент-серверных коммуникационных протоколах mSQL и MySQL

Различий здесь имеется более чем достаточно для того, чтобы поддержку обоих протоколов одновременно обеспечить было невозможно (или, по меньшей мере, очень сложно).

Ниже приведены наиболее заметные различия между коммуникационными протоколами MySQL и mSQL:

  • В буфере сообщения может находиться несколько столбцов результатов.
  • Буферы сообщений динамически увеличиваются, если запрос или результат не умещаются в их текущем объеме, ограничение на объем буфера устанавливается сервером и клиентом.
  • Все пакеты нумеруются, что позволяет обнаружить среди них повторяющиеся или пропуски.
  • Все значения столбцов отправляются в виде ASCII. Длины строк и столбцов посылаются в упакованном виде в двоичном виде (1, 2 или 3 байта).
  • MySQL может считывать результаты без буферизации (без необходимости сохранения всех данных в клиенте).
  • Если одна операция считывания/записи занимает более 30 секунд, сервер закрывает соединение.
  • Если соединение бездействует в течение 8 часов, сервер его закрывает.

1.11.1.3 Различия в синтаксисе SQL между mSQL 2.0 и MySQL

Типы столбцов

MySQL
Имеются следующие дополнительные типы (не считая остальных; see section 6.5.3 Синтаксис оператора CREATE TABLE):
  • ENUM - тип для одного набора строк.
  • SET - тип для нескольких наборов строк.
  • BIGINT - тип для 64-битовых целых чисел.
Кроме того, MySQL поддерживает следующие атрибуты дополнительных типов:
  • UNSIGNED - опция для целочисленных столбцов и столбцов чисел с плавающей запятой.
  • ZEROFILL - опция для целочисленных столбцов.
  • AUTO_INCREMENT - опция для целочисленных столбцов, являющихся первичными ключами. See section 8.4.3.31 mysql_insert_id().
  • DEFAULT - значение для всех столбцов.
mSQL2
Типы столбцов в mSQL соответствуют приведенным в таблице типам MySQL:
Тип в mSQL | Соответствующий тип в MySQL
CHAR(len) | CHAR(len)
TEXT(len) | TEXT(len). len - максимальная длина. Работает LIKE.
INT | INT. Со множеством опций!
REAL | REAL. Или FLOAT. Имеются как 4-битовые, так и 8-битовые варианты.
UINT | INT UNSIGNED
DATE | DATE. Использует формат ANSI SQL, а не собственный формат mSQL.
TIME | TIME
MONEY | DECIMAL(12,2). Значение с фиксированной точкой и двумя знаками после нее.

Создание индексов

MySQL
Индексы могут указываться во время создания таблицы при помощи оператора CREATE TABLE.
mSQL
Индексы создаются после создания таблицы с помощью операторов CREATE INDEX.

Вставка уникального идентификатора в таблицу

MySQL
Для указания типа столбца достаточно использовать AUTO_INCREMENT. See section 8.4.3.31 mysql_insert_id().
mSQL
Необходимо создать в таблице SEQUENCE и выбрать столбец _seq.

Получение уникального идентификатора для строки

MySQL
Следует добавить к таблице первичный или уникальный ключ и использовать его. Новое в версии 3.23.11: если ключ PRIMARY или UNIQUE состоит только из одного целочисленного столбца, к нему можно обращаться и как к _rowid.
mSQL
Следует использовать столбец _rowid. Нельзя забывать о том, что _rowid может, в зависимости от множества факторов, со временем измениться.

Получение времени последнего изменения столбца

MySQL
Нужно вставить в таблицу столбец TIMESTAMP. Этому столбцу автоматически присваиваются текущая дата и время при вызове операторов INSERT или UPDATE, если ему не присвоить определенного значения или присвоить значение NULL.
mSQL
Следует использовать столбец _timestamp.

Сравнение значений NULL

MySQL
MySQL соответствует стандарту ANSI SQL, поэтому сравнение с NULL всегда возвращает результат NULL.
mSQL
В mSQL выражение NULL = NULL имеет значение TRUE. Поэтому при переводе старого кода из mSQL в MySQL =NULL необходимо заменить на IS NULL, а <>NULL - на IS NOT NULL.

Сравнение строк

MySQL
Обычно сравнение строк проводится без учета регистра символов, с порядком сортировки, который определяется текущим набором символов (ISO-8859-1 Latin1 по умолчанию). Если вам это не подходит, необходимо установить при объявлении столбцов атрибут BINARY, тогда сравнение будет проводиться в соответствии с ASCII-порядком, установленным на сервере MySQL.
mSQL
Все сравнения строк проводятся с учетом регистра символов в ASCII-порядке сортировки.

Поиск без учета регистра символов

MySQL
LIKE может быть как чувствительным, так и нечувствительным к регистру оператором, в зависимости от столбцов, к которым он применяется. По возможности MySQL использует индексы, если аргумент LIKE не начинается с шаблонного символа.
mSQL
Следует использовать CLIKE.

Обработка концевых пробелов

MySQL
Все пробелы в конце столбцов CHAR и VARCHAR удаляются. Если такое поведение нежелательно, используйте столбцы TEXT.
mSQL
Концевые пробелы сохраняются.

Операторы WHERE

MySQL
MySQL правильно определяет приоритеты действий (AND имеет приоритет перед OR). Заставить MySQL вести себя так, как mSQL, можно при помощи скобок (как можно видеть в соответствующем примере).
mSQL
Все действия производятся слева направо. А это значит, что некоторые логические вычисления, в которых наличествует более трех аргументов, не могут быть выполнены вообще. Кроме того, это означает, что при переносе в MySQL некоторые запросы необходимо менять. Это довольно просто сделать при помощи скобок. Возьмем, к примеру, следующий запрос mSQL:
mysql> SELECT * FROM table WHERE a=1 AND b=2 OR a=3 AND b=4;
Чтобы MySQL вычислил результат этого запроса так же, как это сделал бы mSQL, нужно расставить скобки:
mysql> SELECT * FROM table WHERE (a=1 AND (b=2 OR (a=3 AND (b=4))));

Ограничения доступа

MySQL
Для хранения привилегий для каждого пользователя, удаленного компьютера и базы имеются соответствующие таблицы. See section 4.2.6 Как работает система привилегий.
mSQL
Имеется файл `mSQL.acl', в котором можно определить привилегии чтения/записи для пользователей.

1.11.2 Сравнение MySQL c PostgreSQL

Читая этот раздел, помните о том, что оба программных продукта находятся в постоянном развитии. Мы (разработчики MySQL) и разработчики PostgreSQL постоянно заняты улучшением наших СУБД, поэтому обе системы являются серьезными альтернативами любым коммерческим СУБД.

Приведенное ниже сравнение проводилось в MySQL AB. Мы старались быть как можно более точными и объективными, однако, зная MySQL наизусть, мы не можем похвастаться таким же знанием возможностей PostgreSQL, поэтому в чем-то могли и ошибиться. Однако мы будем тут же исправлять все замеченные неточности.

Прежде всего хотелось бы отметить, что PostgreSQL и MySQL являются широко используемыми программными продуктами, которые разрабатывались с разными целями (хотя создатели обоих и стремятся довести их до полной совместимости со стандартом ANSI SQL). Это значит, что для решения одних задач больше подходит MySQL, для других же - PostgreSQL. Выбирая СУБД, проверьте, соответствуют ли ее возможности требованиям, предъявляемым решаемой задачей. Если требуется максимальная скорость работы, лучше всего, вероятно, будет остановить свой выбор на MySQL Server. Если же вам необходимы дополнительные возможности, имеющиеся только у PostgreSQL, этой СУБД и стоит пользоваться.

1.11.2.1 Стратегии развития MySQL и PostgreSQL

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

Мы считаем, что лучшим средством предоставления нашим пользователям новых возможностей является частый выпуск новых версий. Поэтому примерно раз в три недели у нас выходит несколько обновленная версия системы, а раз в год - полностью новая. Все версии проходят полное тестирование с помощью наших инструментальных средств на множестве платформ.

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

Еще одно значительное отличие MySQL от PostgreSQL заключается в том, что практически весь содержащийся в MySQL код создан разработчиками, работающими в MySQL AB и постоянно занятыми совершенствованием кода сервера. Исключением из этого правила являются системы транзакций и библиотека регулярных выражений regexp.

Большая же часть кода PostgreSQL написана множеством разработчиков, никак друг с другом не связанных. Не так давно разработчики PostgreSQL объявили о том, что у их команды наконец-то хватило времени на просмотр всего кода, вошедшего в состав очередной версии PostgreSQL.

У обоих вышеупомянутых методов разработки есть достоинства и недостатки. Мы, сотрудники MySQL AB, разумеется, считаем, что наша модель лучше, так как обеспечивает большую логичность кода, оптимальность и возможность его повторного использования, а также - меньшее количество ошибок. Будучи авторами кода сервера MySQL, мы с большим успехом можем координировать включение в систему новых возможностей и выход ее новых версий.

1.11.2.2 Сравнение возможностей MySQL и PostgreSQL

На странице crash-me (http://www.mysql.com/information/crash-me.php) приведен список ограничений и особенностей СУБД, которые могут быть обнаружены автоматически с помощью специальных программ. Однако не стоит забывать о том, что многие ограничения могут быть изменены настройкой соответствующих баз данных. Впрочем, эта web-страница оказывается очень кстати, если необходимо, чтобы создаваемое приложение нормально работало с несколькими СУБД или для перевода приложения с одной СУБД в другую.

MySQL обладает следующими преимуществами перед PostgreSQL:

  • MySQL обычно намного превосходит PostgreSQL по скорости работы. Кроме того, в MySQL 4.0 реализован кэш запросов. Он позволяет во много раз увеличить скорость обработки запросов для сайтов, на которых преобладают неоднократно повторяющиеся запросы на чтение.
  • По количеству пользователей MySQL также намного превосходит PostgreSQL. Поэтому код тестируется значительно более придирчиво и опытным путем доказана большая его надежность, нежели у PostgreSQL. MySQL чаще, чем PostgreSQL, используется на производстве, в основном потому, что компания MySQL AB (ранее - TCX DataKonsult AB) предоставляет высококачественную коммерческую техническую поддержку MySQL с момента появления этой системы на рынке, а у PostgreSQL до самого последнего времени никакой поддержки не было.
  • MySQL работает в среде Windows лучше, чем PostgreSQL. MySQL Server запускается как настоящее (родное) Windows-приложение (в NT/2000/XP - сервис), в то время как PostgreSQL запускается в среде эмуляции, Cygwin. Нам доводилось слышать о недостаточной стабильности работы PostgreSQL в среде Windows, но самостоятельно эти сведения до сих пор мы проверить не могли.
  • MySQL оснащен большим количеством API для других языков и поддерживается большим количеством существующих программ, нежели PostgreSQL.
  • MySQL работает на высоконадежных промышленных системах 24/7 (включенных 24 часа в сутки 7 дней в неделю). В большинстве случаев никаких ``чисток'' в MySQL производить не требуется. PostgreSQL же пока что не может работать в таких системах, так как иногда приходится запускать VACUUM для освобождения занятого последствиями работы команд UPDATE и DELETE пространства и проводить статистический анализ, необходимый для достижения максимальной производительности PostgreSQL. Запускать VACUUM необходимо и после каждого добавления к таблице нескольких столбцов. На напряженно работающих системах VACUUM нужно запускать более часто, в худших случаях - по несколько раз в день. А ведь во время работы VACUUM (а ее работа может продолжаться часы, если база данных достаточно велика) база практически ``мертва''. Впрочем, в PostgreSQL версии 7.2 выполнение основных функций этой программы больше не приводит к блокировке базы, и пользователи могут продолжать нормально работать с ней. Новая команда VACUUM FULL берется за дело более серьезно: она, как и в старых версиях, блокирует таблицу и сжимает копию таблицы на диске.
  • Репликация MySQL отлично протестирована и используется в таких сайтах, как:
    • Yahoo Finance (http://finance.yahoo.com/)
    • Mobile.de (http://www.mobile.de/)
    • Slashdot (http://www.slashdot.org/)
  • В комплект поставки MySQL входят два тестовых пакета, mysql-test-run и crash-me (http://www.mysql.com/information/crash-me.php), а также пакет для замеров производительности. Тестовая система постоянно обновляется, в нее добавляется код для тестирования всех новых возможностей и почти всех воспроизводимых ошибок, которые попали в поле нашего зрения. Перед выпуском каждой новой версии мы используем эти пакеты для тестирования MySQL на нескольких платформах. Наши тесты значительно превосходят по своим возможностям все существующие в PostgreSQL аналоги, и обеспечивают высокое качество кода MySQL.
  • Книг о MySQL вышло значительно больше, нежели о PostgreSQL. Книги о MySQL выпустили издательства O'Reilly, SAMS, Que и New Riders. Все возможности MySQL детально описаны в документации, так как это является обязательным условием включения новых возможностей в код.
  • MySQL поддерживает больше стандартных функций ODBC, чем PostgreSQL.
  • MySQL обладает значительно более мощной реализацией ALTER TABLE.
  • В MySQL предусмотрена возможность создания таблиц без транзакций, что необходимо приложениям, требующим максимально возможной скорости работы. Эти таблицы могут храниться в памяти, относиться к типу HEAP-таблиц или дисковых MyISAM. See section 7 Типы таблиц MySQL.
  • MySQL может работать с двумя поддерживающими транзакции обработчиками таблиц, а именно - InnoDB и BerkeleyDB. Так как все системы поддержки транзакций в разных условиях работают по-разному, это дает разработчику возможность найти наилучшее решение для условий, в которых будет работать его система. See section 7 Типы таблиц MySQL.
  • Команда слияния таблиц MERGE предоставляет в ваше распоряжение уникальную возможность создать представление нескольких идентичных таблиц и работать с ними как с одной. Это особенно удобно для работы с журналами, разбитыми, например, по месяцам. See section 7.2 Таблицы MERGE.
  • Возможность сжатия доступных только для чтения таблиц, не отменяющая прямого доступа к их записям, повышает производительность системы, снижая количество операций считывания с диска. Это особенно полезно при архивировании. See section 4.7.4 myisampack, MySQL-генератор сжатых таблиц (только для чтения).
  • В MySQL реализован полнотекстовый поиск. See section 6.8 Полнотекстовый поиск в MySQL.
  • Имеется возможность работы с несколькими базами через одно соединение (разумеется, в зависимости от привилегий пользователя).
  • Система MySQL с самого начала разрабатывалась в расчете на многопоточность, а PostgreSQL использует процессы. Переключение контекстов и доступ к общим данным несколькими потоками осуществляется значительно быстрее, нежели отдельными процессами. Таким образом MySQL Server в многопользовательских приложениях получает неплохое преимущество в производительности, а кроме того, таким образом MySQL Server удается значительно эффективней пользоваться преимуществами, предоставляемыми симметричными мультипроцессорными системами (SMP).
  • В MySQL реализована значительно более мощная система привилегий, нежели в PostgreSQL. В то время как PostgreSQL обеспечивает лишь привилегии INSERT, SELECT и UPDATE/DELETE над базой или таблицей, MySQL предоставляет возможность определения полного набора разнообразных привилегий на уровне базы, таблицы и столбца. Кроме того, MySQL позволяет задавать привилегии для комбинаций хост/пользователь. See section 4.3.1 Синтаксис команд GRANT и REVOKE.
  • В MySQL используется протокол связи между клиентом и сервером со сжатием данных, что увеличивает производительность системы в условиях низкоскоростных каналов связи.
  • Насколько нам известно, только в реляционной системе баз данных MySQL Server используется концепция ``обработчика таблиц''. Благодаря этому создается возможность работы с различными низкоуровневыми типами таблиц из ядра MySQL, причем каждая таблица может быть оптимизирована для различных характеристик производительности.
  • Все типы таблиц в MySQL (кроме InnoDB) реализованы в виде файлов (по одной таблице в файле), что значительно облегчает создание резервных копий, перенос, удаление и даже создание символьных ссылок между базами данных и таблицами, даже если сервер находится в нерабочем состоянии.
  • Наличие утилиты для восстановления и оптимизации таблиц MyISAM (наиболее распространенного типа таблиц в MySQL). Ее использование требуется только в случае физического повреждения файла данных (например, в результате аппаратного сбоя). Позволяет восстановить большую часть данных.
  • Обновление (апгрейд) MySQL проходит совершенно ``безболезненно''. При модернизации MySQL нет нужды в сохранении/восстановлении данных, что приходится делать при установке большинства обновлений PostgreSQL.

Недостатки MySQL по сравнению с PostgreSQL:

  • Поддержка транзакций в MySQL пока что не настолько хорошо проверена, как в системе PostgreSQL.
  • Так как MySQL основан на использовании потоков (threads), пока что еще не безошибочно работающих в некоторых ОС, для обеспечения стабильной работы приходится либо использовать один из откомпилированных пакетов, доступных по адресу http://www.mysql.com/downloads/, либо точно выполнять содержащиеся в section 2.3 Установка исходного дистрибутива MySQL инструкции.
  • Блокировка таблиц, применяющаяся в нетранзакционных таблицах MyISAM, во многих случаях работает быстрее, нежели блокировки на уровне страниц, строк или контроль версий. Недостаток этого подхода в том, что если не учитывать механизм работы блокирования таблиц, один длительный запрос может надолго заблокировать таблицу. Обычно этого эффекта можно избежать, приняв соответствующие меры при разработке приложения. Если это не удастся, всегда можно изменить тип таблицы и сделать ее транзакционной. See section 5.3.2 Вопросы блокирования таблиц.
  • При помощи UDF (user-defined functions, определяемые пользователем функции) возможности MySQL можно расширить и дополнить обычными SQL-функциями или их объединениями. Но это сделать не так просто, да и система не настолько гибка в этом отношении, как PostgreSQL. See section 9.2 Добавление новых функций в MySQL.
  • В MySQL сложнее организовывались обновления, затрагивающие несколько таблиц сразу. Впрочем, это было исправлено в MySQL 4.0.2 реализацией многотабличного UPDATE и в MySQL 4.1 - с помощью подзапросов. В MySQL 4.0 можно одновременно удалять данные из нескольких таблиц. See section 6.4.6 Синтаксис оператора DELETE.

Ниже перечислены преимущества PostgreSQL по сравнению с MySQL на сегодняшний день.

Так как нам известен план разработки новых версий MySQL, мы включили в приведенную ниже таблицу версии MySQL, в которых будет реализована поддержка соответствующих возможностей. К сожалению, в сопоставлении мы сделать этого не могли, так как план разработки PostgreSQL нам неизвестен.

Возможность | Версия MySQL
Подзапросы | 4.1
Внешние ключи | 5.0 (3.23 с InnoDB)
Представления | 5.0
Хранимые процедуры | 5.0
Триггеры | 5.0
Объединения | 4.0
Полные связи | 4.1
Ограничения | 4.1 или 5.0
Курсоры | 4.1 или 5.0
R-деревья | 4.1 (для таблиц MyISAM)
Наследование таблиц | Не планируется
Расширяемая система типов | Не планируется

Другие причины, по которым можно предпочесть PostgreSQL:

  • В некоторых случаях PostgreSQL оказывается ближе к ANSI SQL.
  • Работу PostgreSQL можно ускорить, выполняя код в виде хранимых процедур.
  • При хранении географических данных R-деревья дают PostgreSQL преимущество перед MySQL (примечание: в MySQL версии 4.1 для таблиц MyISAM реализована поддержка R-деревьев).
  • Оптимизатор PostgreSQL в некоторых случаях способен дать лучший в сравнении с существующим на сегодняшний день оптимизатором MySQL результат. Особенно это заметно при слиянии таблиц без соответствующих ключей или при слиянии с использованием разных ключей в сочетании с логическим оператором OR. Набор результатов тестов скорости MySQL, расположенный по адресу http://www.mysql.com/information/benchmarks.html покажет, каких конструкций следует избегать при работе с различными базами данных.
  • Команда разработчиков PostgreSQL, пишущих код для сервера, больше.

Недостатки PostgreSQL по сравнению с MySQL:

  • VACUUM затрудняет использование PostgreSQL в постоянно работающих системах.
  • Наличие только транзакционных таблиц.
  • Значительно более медленная работа команд INSERT, DELETE и UPDATE.

Полный список недостатков приведен в первой таблице настоящего раздела.

1.11.2.3 Тестирование скорости работы MySQL и PostgreSQL

Единственная тестовая система с открытым кодом, способная тестировать скорость работы как MySQL Server, так и PostgreSQL (а также других СУБД), о существовании которой нам известно, - наша собственная разработка. Ее можно найти по адресу http://www.mysql.com/information/benchmarks.html.

Мы много раз просили разработчиков PostgreSQL и некоторых пользователей PostgreSQL помочь нам расширить эту систему и превратить ее в совершенный инструмент тестирования скорости работы СУБД, но, к сожалению, безрезультатно.

По этой причине разработчики MySQL потратили много времени, пытаясь выжать (для тестирования) из PostgreSQL все возможное, но из-за недостаточно совершенного знания PostgreSQL мы наверняка что-то упустили. На страничке тестов производительности проведенное нами исследование полностью задокументировано, так что любой может легко повторить его и проверить результаты.

Обычно тесты запускаются без ключа --fast. При запуске с этим ключом используются все трюки, позволяющие заставить сервер работать как можно быстрее. Идея состоит в том, чтобы в обычном режиме тест показал, как сервер будет работать при настройках по умолчанию, в режиме --fast, - как производительность изменится, если разработчик приложения воспользуется расширениями сервера для ускорения его работы.

При тестировании PostgreSQL в режиме --fast мы запускаем VACUUM после каждой операции UPDATE и DROP TABLE, чтобы обеспечить отличное состояние базы для последующих операторов SELECT. Время, уходящее на работу VACUUM, измеряется отдельно.

Однако при тестировании PostgreSQL 7.1.1 мы не смогли запустить программу в режиме --fast, так как во время теста INSERT, postmaster (демон PostgreSQL) дал сбой и база данных была повреждена настолько, что перезапустить демон не удалось. Когда это случилось дважды, мы решили отложить тестирование в режиме --fast до выхода следующей версии PostgreSQL. Подробную информацию о компьютере, на котором выполнялись тесты, вы найдете на странице тестов.

Перед тем как переходить к описанию других известных нам тестов, мы дадим побольше информации о таких тестах вообще.

Нет ничего проще, чем написать тест, доказывающий, что любая СУБД является лучшей в мире, для этого достаточно ограничиться измерением результатов операций, с которыми эта СУБД справляется хорошо, и деликатно забыть об остальных. А если еще после этого выдать обобщенный график, то все становится еще проще.

Это то же самое, если бы мы решили сравнить скорость работы MySQL Server и PostgreSQL просто сравнив общие результаты тестов MySQL, приведенных на нашей странице. По таким результатам MySQL Server оказался бы более чем в 40 раз быстрее PostgreSQL, а это, конечно, неверно. Можно было бы подлить масла в огонь, избрав для тестирования PostgreSQL тесты, на которые эта система тратит больше всего времени, - и утверждать что MySQL Server более чем в 2000 раз быстрее PostgreSQL.

Дело тут в том, что MySQL оптимизирует многое из того, чего не оптимизирует PostgreSQL. И наоборот. SQL-оптимизатор вообще очень сложная штука, и можно потратить годы исключительно на его улучшение.

Исследуя результаты тестов, нужно искать задачи, которые должно выполнять ваше приложение, и результаты их выполнения использовать для принятия решения о выборе СУБД. Результаты тестов позволяют определить и задачи, с решением которых выбранная СУБД справляется не слишком хорошо, - таким образом можно определить, чего следует избегать и обходить в своих программах.

Нам известно о двух тестах, утверждающих, что PostgreSQL по производительности превосходит MySQL Server. Оба они - многопользовательские, а у сотрудников MySQL AB пока что не нашлось времени написать такой тест. Основная причина - довольно сложно сделать это так, чтобы не поставить ни одну из СУБД в заведомо проигрышное положение.

Один из этих тестов был заказан компанией Great Bridge, которая в течение 16 месяцев пыталась построить бизнес на основе PostgreSQL, но в конце концов прекратила свою деятельность. Вероятно, это худший из когда-либо проводившихся кем-либо тестов. Он не только принимает во внимание лишь те области, в которых PostgreSQL оказывается ``на коне'', но и ставит абсолютно все остальные СУБД в заведомо проигрышное положение.

Примечание: Нам стало известно о том, что даже некоторым ключевым разработчикам PostgreSQL отнюдь не понравилось то, как фирма Great Bridge проводила свое тестирование, так что команду разработчиков PostgreSQL мы в связи с этим тестом ни в чем не обвиняем.

Упомянутый тест осуждался во многих сообщениях и телеконференциях, так что мы просто коротко перечислим его недостатки.

  • Тесты выполнялись дорогой коммерческой программой, что сделало задачу проверки их результатов невыполнимой для Open Source-компании, каковой мы являемся; мы даже не можем выяснить, как же на самом деле проводились эти тесты. Причем сама программа, даже не является специализированной утилитой для тестирования производительности - она представляет из себя универсальный инструмент для настройки и тестирования приложений. Называть ее ``стандартным'' тестом - это уж слишком большая натяжка.
  • Компания Great Bridge признала, что база данных PostgreSQL была оптимизирована (а перед проведением теста была запущена программа VACUUM) и специально настроена для проведения тестов, чего не делалось ни для одной другой СУБД, участвовавшей в тестировании. Они заявили буквально следующее: ``Этот процесс оптимизирует индексы и высвобождает немного дискового пространства. Оптимизированные индексы в некоторой степени повышают производительность.'' Проведенные нами тесты недвусмысленно свидетельствуют о том, что разница в скорости выполнения большого количества выборок (SELECT'ов) из базы данных, прошедшей чистку VACUUM, и не прошедшей ее, может быть десятикратной.
  • Результаты тестов тоже вызывают сомнения. В тестовой документации AS3AP упоминается о том, что при тестировании выполняются ``выборки, простые связи, проекции, аггрегация, обновления с одним набором значений для атрибута и массовые обновления''. PostgreSQL отлично выполняет операции SELECT и JOIN (особенно после VACUUM), но отнюдь не здорово справляется с INSERT или UPDATE. А результаты показывают, что выполнялись только операции SELECT (или операций обновления выполнялось очень мало). Это правдоподобно объясняет отличные результаты, показанные PostgreSQL в данном тесте. А причина, по которой MySQL показал неважные результаты, станет понятной несколько ниже.
  • Так называемый тест запускался с компьютера, работающего под управлением Windows и связывавшегося с Linux через ODBC, а такая конфигурация никакому нормальному пользователю СУБД, особенно при работе с многопользовательским приложением, даже в голову не придет. В этом случае тестируется не СУБД, а ODBC-драйвер и Windows-протокол, связывающие клиентов.
  • При связи базы с Oracle и MS-SQL (Great Bridge косвенно указала на примененные в тесте СУБД) использовался не соответствующий им протокол, а ODBC. Любой, кто когда-либо имел дело с Oracle, знает, что во всех настоящих приложениях используется не ODBC, а ``родной'' интерфейс. Проводить тесты через ODBC и утверждать, что они имеют какое-либо отношение к использованию СУБД в реальной работе, попросту нечестно. Нужно было провести два теста, с ODBC и без него, чтобы получить истинные факты (причем все СУБД перед проведением тестов должны были бы настраиваться специалистами).
  • Представители компании постоянно говорят о TPC-C тестах, но нигде не упоминают о том, что проведенный ими тест вовсе не относился к TPC-C, а проводить TPC-C они просто не имели права. TPC-C может проводиться только по правилам, утвержденным комитетом TPC Council (http://www.tpc.org/). Great Bridge в комитет не обращалась. Не сделав этого, она не только вступила в конфликт с торговой маркой TPC, но и дискредитировала свои тесты. Установленные комитетом TPC Council правила очень строги, чтобы никто не мог выдавать ложных результатов или делать недоказуемые заявления. Очевидно, у Great Bridge не было желания следовать этим правилам.
  • После проведения первого теста мы связались с Great Bridge и сообщили ее представителям о наиболее очевидных из допущенных при тестировании MySQL Server ошибок:
    • Использование отладочной версии нашего ODBC-драйвера
    • Запуск сервера под управлением ОС Linux, не оптимизированной для работы с потоками.
    • Использование старой версии MySQL, хотя уже существовала более современная
    • Отказ от запуска MySQL Server с соответствующими настройками для работы с большим количеством пользователей (по умолчанию после установки MySQL Server настраивается для минимального использования ресурсов)
    Great Bridge провела новый тест, с нашим оптимизированным драйвером ODBC и лучшей настройкой MySQL Server, но отказалась применить обновленную библиотеку glibc или нашу стандартную бинарную поставку (ее используют 80% наших пользователей), которая была статически слинкована с конкретной glibc. Насколько нам известно, компания Great Bridge не сделала абсолютно ничего для правильной настройки других СУБД при тестировании. Впрочем, мы уверены, что в Oracle или Microsoft они за советом не обращались. ;)
  • Тестирование было оплачено Great Bridge, и эта компания решила опубликовать не все результаты, а только выборочно - те, что были ей выгодны.

Тим Пердью (Tim Perdue), преданный обожатель PostgreSQL и не слишком большой любитель MySQL, опубликовал свое сравнение на сайте PHPbuilder (http://www.phpbuilder.com/columns/tim20001112.php3).

Узнав об этом, мы связались с Тимом по телефону с тем, чтобы обсудить некоторые странности в полученных им результатах. Он, например, утверждал, что MySQL Server в его тестах с трудом справлялся с обслуживанием пяти пользователей, хотя нам были известны пользователи с примерно такими же, как у Тима, компьютерами, работающие с MySQL Server при 2000 активных соединениях, выдающих до 400 запросов в секунду (причем в данном случае производительность ограничивалась каналом связи с web, а не базой данных).

Похоже было, что Тим работал с ядром Linux, не умеющим нормально обрабатывать большое количество потоков, как, например, ядра до версии 2.4, у которых возникали серьезные проблемы с обработкой большого количества потоков на мультипроцессорных компьютерах. В настоящем руководстве мы описали решение этой проблемы, и Тим должен был об этом знать.

Существует еще одна возможная причина возникновения проблем: Тим мог воспользоваться старой библиотекой glibc или не загрузить откомпилированный исполняемый файл MySQL (слинкованный с исправленной библиотекой glibc) с нашего сайта, но скомпилировал его сам. В любом из этих случаев симптомы были бы именно такими, как описал Тим.

Мы спросили Тима, может ли он предоставить нам его данные с тем, чтобы мы могли повторить тест, а также попросили его проверить свою версию MySQL и сообщить нам. Пока что он этого не сделал.

Из за этого его тесту мы тоже не можем доверять. :(

Все течет, все изменяется, и старые тесты теряют актуальность. Теперь MySQL обзавелся парой новых обработчиков таблиц, которые обеспечивают совершенно разные характеристики в разрезе скорости/параллелизма. See section 7 Типы таблиц MySQL. Было бы интересно узнать, какие результаты показали бы вышеупомянутые тесты с разными типами транзакционных таблиц в MySQL. Конечно, в PostgreSQL с тех пор тоже появились новые возможности. Так как эти тесты недоступны общественности, выяснить, как СУБД показала бы себя в них сегодня, мы не можем.

Заключение:

Единственные существующие на сегодня тесты, позволяющие сравнить MySQL Server и PostgreSQL, которые любой может загрузить и запустить, - это тесты из комплекта MySQL. Мы, сотрудники MySQL AB, считаем, что Open Source-СУБД должны тестироваться при помощи Open Source-инструментов! Только так можно получить гарантии того, что никто не сможет провести невоспроизводимые тесты и на основе их результатов утверждать, что одна СУБД лучше другой. Не зная всех фактов, подтвердить или опровергнуть подобные утверждения просто невозможно.

Нам кажется странным, что невоспроизводимые тесты с участием PostgreSQL показывают преимущество этой системы, в то время как наши тесты, которые может повторить любой, четко доказывают обратное. Этим мы вовсе не хотим сказать, что PostgreSQL не годится для решения многих задач (еще как годится!) или что при определенных условиях эта система не обгонит MySQL Server. Но нам просто хотелось бы для разнообразия увидеть честный тест, в котором PostgreSQL покажет отличные результаты, - исключительно с целью поддержания товарищеской конкуренции!

Дополнительную информацию о нашей тестовой системе вы можете получить из раздела section 5.1.4 Набор тестов MySQL (The MySQL Benchmark Suite).

Мы занимаемся разработкой еще лучшего комплекса тестов, в состав которого будут включены многопользовательские тесты, а также более подробное описание того, что собственно делает каждый отдельный тест и как расширить комплекс.

Go to the first, previous, next, last section, table of contents.


Справочное руководство по MySQL версии 5.0.0-alpha. - 2 Установка MySQL

2 Установка MySQL

В этом разделе описаны получение и установка MySQL:

  • Список сайтов, с которых можно получить MySQL, See section 2.2.1 Как получить MySQL.
  • Чтобы узнать о поддерживаемых платформах, See section 2.2.5 Операционные системы, поддерживаемые MySQL. Необходимо иметь в виду, что не все поддерживаемые системы одинаково хорошо подходят для запуска MySQL: одни из них гораздо устойчивее и эффективнее, чем другие (за более подробной информацией следует обращаться к разделу section 2.2.5 Операционные системы, поддерживаемые MySQL).
  • Некоторые версии MySQL доступны как в виде бинарного дистрибутива, так и в виде дистрибутива исходного кода. Помимо этого, всем, кто желает ознакомиться с нашими последними разработками и помочь нам тестировать новый код, мы обеспечиваем открытый доступ к нашему текущему дереву исходных кодов. Чтобы определить, какую версию и тип дистрибутива вам следует использовать, See section 2.2.6 Какую версию MySQL использовать. Если вы сомневаетесь в том, какую версию выбрать, лучше предпочесть бинарный дистрибутив.
  • Инструкции по установке для бинарного дистрибутива и для дистрибутива исходного кода находятся в разделах section 2.2.10 Установка бинарного дистрибутива MySQL и See section 2.3 Установка исходного дистрибутива MySQL. В каждый набор инструкций включен раздел с описанием специфичных для различных операционных систем проблем, с которыми вы можете столкнуться.
  • Чтобы ознакомиться с послеустановочными процедурами, See section 2.4 Послеустановочные настройка и тестирование. Эти действия применимы при установке MySQL с использованием как бинарного дистрибутива, так и дистрибутива исходного кода.

2.1 Быстрая стандартная установка MySQL

2.1.1 Установка MySQL на Linux

Для установки MySQL на Linux рекомендуется применять пакеты RPM. В настоящее время RPM для MySQL создаются на операционной системе SuSE Linux 7.3, но они должны работать также и для других версий Linux, которые поддерживают rpm и используют glibc.

В случае возникновения проблем с файлом RPM (например, если вы получили ошибку ``Sorry, the host 'xxxx' could not be looked up''), обращайтесь к разделу See section 2.6.1.1 Примечания к бинарным дистрибутивам Linux.

Доступны для использования следующие RPM-файлы:

  • MySQL-server-VERSION.i386.rpm. Сервер MySQL. Если вам нужно только подключаться к серверу MySQL, запущенному на другом компьютере, этот файл не требуется. Обратите внимание, что выхода 4.0.10 этот пакет назывался MySQL-VERSION.i386.RPM.
  • MySQL-client-VERSION.i386.rpm. Стандартные клиентские программы MySQL. Установка этого пакета требуется всегда.
  • MySQL-bench-VERSION.i386.rpm. Тесты и контрольные задачи. Для файла требуется наличие модулей Perl и msql-mysql-modules.
  • MySQL-devel-VERSION.i386.rpm. Библиотеки и включаемые файлы, необходимые для компилирования других клиентов MySQL, таких как модули Perl.
  • MySQL-shared-VERSION.i386.rpm Этот пакет содержит динамические библиотеки (libmysqlclient.so*), нужные для некоторых языков программирования или приложений для того, чтобы работать с MySQL.
  • MySQL-embedded-VERSION.i386.rpm Встраиваемая библиотека сервера MySQL (MySQL 4.x и более новые).
  • MySQL-VERSION.src.rpm. Этот файл содержит исходный код для всех предыдущих пакетов. Файл также можно использовать для создания файлов RPM для других архитектур (например Alpha или SPARC).

Для просмотра всех файлов в пакете RPM выполните команду:

shell> rpm -qpl MySQL-VERSION.i386.rpm

Для выполнения стандартной минимальной установки запустите команду:

shell> rpm -i MySQL-server-VERSION.i386.rpm MySQL-client-VERSION.i386.rpm

Для установки только клиентского пакета выполните команду:

shell> rpm -i MySQL-client-VERSION.i386.rpm

RPM помещает данные в `/var/lib/mysql' и создает соответствующие вхождения в `/etc/init.d/' для автоматического запуска сервера во время начальной загрузки (в случае, если у вас имеется предыдущая инсталляция, можно создать копию ранее установленного файла запуска MySQL, чтобы изменения в нем не были утеряны.)

Если вы хотите установить MySQL RPM на старших версиях Linux, которые не поддерживают init-скрипты в `/etc/init.d' (непосредственно или посредством символической ссылки), вам следует создать символическую ссылку на старое расположение перед тем, как устанавливать RPM:

shell> cd /etc ; ln -s rc.d/init.d .

Однако, все современные поставки Linux должны поддерживать эту схему каталогов, т.к. это требование стандарта LSB (Linux Standard Base).

После установки RPM, mysqld должен заработать и вы можете сразу приступать к использованию MySQL.

See section 2.4 Послеустановочные настройка и тестирование.

Если при установке возникнут проблемы, то за более подробной информацией следует обращаться к главе, в которой описывается установка из бинарного дистрибутива. See section 2.2.10 Установка бинарного дистрибутива MySQL.

2.1.2 Установка MySQL на Windows

Имеются два следующих типа дистрибутивов сервера MySQL для Windows:

  1. Бинарный дистрибутив, в состав которого входит программа установки; она устанавливает все, что нужно, так что можно сразу же запускать сервер.
  2. Дистрибутив исходного кода, в котором содержится весь код и файлы поддержки для создания исполняемых файлов с использованием компилятора VC++ 6.0. See section 2.3.7 Дистрибутив исходного кода для Windows.

В общем случае следует отдавать предпочтение бинарному дистрибутиву.

Вам потребуется:

  • 32-разрядная операционная система Windows, такая как 9x, Me, NT, 2000 или XP. Под управлением семейства NT (NT, Windows 2000 и XP) сервер MySQL можно запускать как сервис. See section 2.6.2.2 Запуск MySQL на Windows NT, 2000 или XP. Если предполагается работать с таблицами размером более 4 Гб, необходимо установить MySQL на файловую систему NTFS или более новую. При создании таблиц не забывайте использовать MAX_ROWS и AVG_ROW_LENGTH. See section 6.5.3 Синтаксис оператора CREATE TABLE.
  • Поддержка протокола TCP/IP.
  • Копия бинарного кода MySQL или дистрибутив для Windows, который может быть загружен с http://www.mysql.com/downloads/. Примечание: дистрибутив поставляется в виде архивных файлов, сжатых архиватором ZIP. Во избежание повреждения файлов в процессе загрузки мы рекомендуем использовать адекватный клиент FTP с возможностью возобновления загрузки.
  • Архиватор ZIP для распаковки файла дистрибутива.
  • Достаточно места на жестком диске для распаковки, установки и создания баз данных в соответствии с вашими требованиями.
  • Если вы планируете подключаться к серверу MySQL через ODBC, то понадобится драйвер MyODBC. See section 8.3 Поддержка ODBC в MySQL.

2.1.2.1 Установка бинарного кода

  1. Если вы работаете на сервере NT/2000/XP, войдите в систему как пользователь с привилегиями администратора.
  2. Если вы производите модернизацию более ранней установки MySQL, то необходимо остановить сервер. Если сервер работает как сервис, то применяйте следующую команду:
    C:\> NET STOP MySQL
    В остальных случаях используйте:
    C:\mysql\bin> mysqladmin -u root shutdown
  3. Если вы хотите изменить исполняемый файл сервера (т.е. -max или -nt), необходимо также удалить сервис:
    C:\mysql\bin> mysqld-max-nt --remove
  4. Разархивируйте файл дистрибутива во временном каталоге.
  5. Запустите файл `setup.exe', чтобы начать процесс установки. Если вы хотите установить программу в иной каталог, чем заданный по умолчанию `c:\mysql', то используйте кнопку Browse для указания выбранного вами каталога.
  6. Завершите процесс установки.

2.1.2.2 Подготовка конфигурации MySQL для Windows

Начиная с версии MySQL 3.23.38, дистрибутив для Windows включает в себя как обычный бинарный код, так и бинарный код сервера MySQL-Max. Ниже приводится список различных серверов MySQL, которые можно использовать:

Бинарный код | Описание
mysqld | Скомпилирован с полным набором возможностей отладки и автоматической проверки выделения памяти, символических ссылок, таблиц InnoDB и BDB.
mysqld-opt | Оптимизированный бинарный код без поддержки транзакционных таблиц.
mysqld-nt | Оптимизированный бинарный код для NT/2000/XP с поддержкой именованных каналов. Можно запустить эту версию на Windows 9x/Me, но в этом случае не создаются именованные каналы и необходимо иметь установленный протокол TCP/IP.
mysqld-max | Оптимизированный бинарный код с поддержкой символических ссылок и таблиц InnoDB и BDB.
mysqld-max-nt | Подобен mysqld-max, но скомпилирован с поддержкой именованных каналов.

Начиная с версии 3.23.50, именованные каналы доступны только при запуске mysqld с --enable-named-pipe.

Все бинарные коды оптимизированы под процессор Pentium Pro, но должны работать на любом процессоре Intel >= i386.

При следующих обстоятельствах для того чтобы задать вашу конфигурацию MySQL будет необходимо использовать файл опций:

  • Если каталоги установки или данных отличаются от заданных по умолчанию местоположений (`c:\mysql' и `c:\mysql\data').
  • Если вы хотите использовать один из следующих серверов:
    • mysqld.exe
    • mysqld-max.exe
    • mysqld-max-nt.exe
  • Если вам требуется выполнить настройку установочных параметров сервера.

Обычно для редактирования файла опций `my.ini' можно использовать инструмент WinMySQLAdmin. В этом случае остальную часть данного раздела вы можете пропустить.

Существует два файла опций с одинаковыми функциями: `my.cnf' и `my.ini'. Однако во избежание недоразумений лучше всего использовать только один из них. Оба файла представляют собой простой текст. Если вы собираетесь использовать файл `my.cnf', то его следует создать в корневом каталоге диска C, если `my.ini' - то в системном каталоге Windows (это обычно что-либо вроде `C:\WINDOWS' или `C:\WINNT'; его точное местоположение можно определить по значению переменной окружения windir). MySQL сначала ищет файл `my.ini', а затем `my.cnf'.

Если на вашем компьютере используется начальный загрузчик, в котором диск C не является загрузочным диском, то следует работать только с файлом `my.ini'. Инструментальная программа WinMySQLAdmin, если она у вас применяется, также использует только файл `my.ini' (файл помощи с инструкциями по использованию этого инструмента находится в каталоге `\mysql\bin').

Используя notepad.exe, создайте файл опций и отредактируйте раздел [mysqld], указав значения параметров basedir и datadir:

[mysqld]
# set basedir to installation path, e.g., c:/mysql
basedir=the_install_path
# set datadir to location of data directory,
# e.g., c:/mysql/data or d:/mydata/data
datadir=the_data_path

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

Чтобы использовать каталог данных, отличный от заданного по умолчанию `c:\mysql\data', необходимо скопировать все содержимое каталога `c:\mysql\data' в новое местоположение.

Если вы хотите работать с транзакционными таблицами InnoDB, то необходимо вручную создать два новых каталога для хранения данных таблиц InnoDB и журнальных файлов - т.е. `c:\ibdata' и `c:\iblogs'. Помимо этого потребуется добавить несколько дополнительных строк в файле опций. См. раздел See section 7.5.2 Параметры запуска InnoDB.

Если же работу с таблицами InnoDB вы не планируете, следует в файле опций добавьте опцию skip-innodb.

Теперь вы готовы тестировать запуск сервера.

2.1.2.3 Первый запуск сервера

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

Убедитесь, что находитесь в каталоге, где расположен сервер, затем введите следующую команду:

C:\mysql\bin> mysqld-max --standalone

При запуске сервера вы должны увидеть следующие сообщения:

InnoDB: The first specified datafile c:\ibdata\ibdata1 did not exist:
InnoDB: a new database to be created!
InnoDB: Setting file c:\ibdata\ibdata1 size to 209715200
InnoDB: Database physically writes the file full: wait...
InnoDB: Log file c:\iblogs\ib_logfile0 did not exist: new to be created
InnoDB: Setting log file c:\iblogs\ib_logfile0 size to 31457280
InnoDB: Log file c:\iblogs\ib_logfile1 did not exist: new to be created
InnoDB: Setting log file c:\iblogs\ib_logfile1 size to 31457280
InnoDB: Log file c:\iblogs\ib_logfile2 did not exist: new to be created
InnoDB: Setting log file c:\iblogs\ib_logfile2 size to 31457280
InnoDB: Doublewrite buffer not found: creating new
InnoDB: Doublewrite buffer created
InnoDB: creating foreign key constraint system tables
InnoDB: foreign key constraint system tables created
011024 10:58:25 InnoDB: Started

Чтобы получить дальнейшую информацию о работе MySQL под Windows, обращайтесь к разделу See section 2.6.2 Примечания к Windows.

2.1.3 Установка MySQL на MacOS X

Начиная с MySQL 4.0.11, вы можете поставить MySQL на Mac OS X 10.2 ("Jaguar") используя родной формат пакетов PKG вместо бинарного tar-архива. Обратите внимание, что более старые версии Mac OS X (скажем, 10.1.x) не поддерживаются этим пакетом.

Пакет находится внутри файла образа диска (.dmg), который вам сначала следует смонтировать двойным щелчком мышки на его иконке в Finder. Образ должен быть смонтирован и вы увидите его содержимое.

Внимание: Перед тем как продолжить инсталляцию, убедитесь, что другие сервера MySQL не работают на этом компьютере!

Пожалуйста, остановите все запущенные копии MySQL перед тем, как продолжать. Для этого используйте или приложение MySQL Manager (на Mac OS X Server) или с помощью mysqladmin shutdown в командной строке.

Для того чтобы поставить MySQL PKG, дважды щелкните мышкой на иконке пакета. Это действие запустит инсталлятор пакетов Mac OS, который и проведет вас через процесс установки MySQL.

Пакет поставит себя в `/usr/local/mysql-<версия>' и также поставит символическую ссылку `/usr/local/mysql', указывающую на новое месторасположение. Если каталог с именем `/usr/local/mysql' уже существует, он будет вначале переименован в `/usr/local/mysql.bak'. Кроме того, будут установлены таблицы привилегий MySQL путем выполнения mysql_install_db после инсталляции.

Схема инсталляции похожа на ту, которая используется в бинарной поставке: все исполняемые файлы MySQL будут расположены по пути `/usr/local/mysql/bin', сокет будет расположен в `/etc/mysql.sock'. See section 2.2.7 Схемы установки.

Необходимо чтобы существовал пользователь с именем mysql (который должен существовать по умолчанию в каждой поставке Mac OS X 10.2 и выше).

Если вы используете Mac OS X Server, у вас уже есть работающая копия MySQL:

  • Mac OS X Server 10.2-10.2.2 идет с MySQL 3.23.51 в поставке
  • Mac OS X Server 10.2.3 и 10.2.4 поставляется с MySQL 3.23.53

Этот раздел руководства покрывает вопросы инсталляции только официального пакета PKG для Mac OS X. Сначала прочитайте руководство Apple по установке MySQL, пожалуйста (запустите приложение "Help View", выберите "Mac OS X Server", сделайте поиск слова "MySQL" и прочитайте раздел под названием "Installing MySQL").

Учтите, что преинсталлированные пакеты MySQL на Mac OS X Server запускаются с помощью команды safe_mysqld вместо mysqld_safe!

Если вы ранее использовали пакеты MySQL Марка Лиянажа (Marc Liyanage) с сайта http://www.entropy.ch, вы можете просто следовать инструкциям по обновлению пакетов используя схему расположения, как указано на его страничках.

Если вы обновляете MySQL с версии, собранной Марком или с предустановленной версии из поставки Mac OS X Server, на официальную сборку от MySQL - вам следует также преобразовать существующие таблицы привилегий MySQL. See section 2.5.2 Модернизация с версии 3.23 до версии 4.0.

После инсталляции вы можете запустить MySQL выполняя следующие команды в терминальном окне. Обратите внимание, что вам нужны привилегии администратора для выполнения этой задачи.

shell> cd /usr/local/mysql
shell> sudo ./bin/mysqld_safe
(Введите ваш пароль)
(Нажмите CTRL+Z)
shell> bg
(Нажмите CTRL+D для выхода из оболочки)

Теперь вы сможете подключиться к серверу MySQL, скажем, запустив `/usr/local/mysql/bin/mysql'.

Для того, чтобы MySQL автоматически запускался при загрузке, вы можете взять MySQL StartupItem Марка по этому адресу:

http://www2.entropy.ch/download/mysql-startupitem.pkg.tar.gz

Мы планируем в ближайшее время добавить StartupItem в официальный пакет MySQL в ближайшее время.

Заметьте, что инсталляция нового пакета MySQL не удаляет каталог более старой инсталляции. К сожалению, инсталлятор в Mac OS X еще не предоставляет нужной функциональности для того, чтобы корректно обновить существующие в системе пакеты.

После того, как вы скопировали файлы данных MySQL с предыдущего месторасположения, и успешно запустили новую версию, вы можете удалить старую инсталляцию. Кроме того, вы можете удалить старые каталоги Package Receipt, расположенные здесь: `/Library/Receipts/mysql-<version>.pkg'.

2.2 Общие вопросы инсталляции

2.2.1 Как получить MySQL

Информацию о текущей версии и инструкции по ее загрузке можно получить на домашней странице MySQL (http://www.mysql.com/).

Наш главный зеркальный сайт - http://mirrors.sunsite.dk/mysql/

Если вы заинтересованы в организации зеркального сайта MySQL, то можете анонимно зеркалировать нас программой rsync с адреса rsync://sunsite.dk/ftp/mirrors/mysql/. Просьба отправить нам письмо по адресу webmaster@mysql.com, чтобы уведомить нас о том, что ваш зеркальный сайт следует добавить в представленный ниже список.

Если возникнут проблемы с загрузкой с нашего главного сайта, пробуйте использовать один из следующих зеркальных сайтов.

О недействительных или устаревших зеркальных сайтах просьба сообщать по адресу webmaster@mysql.com.

For a complete upto-date list of MySQL web/download mirrors, see http://www.mysql.com/downloads/mirrors.html. There you will also find information about becoming a MySQL mirror site and how to report a bad or out-of-date mirror.

2.2.2 Проверка целостности пакетов с помощью MD5 Checksums или GnuPG

После того, как вы загрузили нужный вам пакет MySQL, и перед тем как вы будете его устанавливать, вам следует убедиться в том, что он в сохранности и не был кем-либо изменен.

MySQL AB предоставляет два способа проверить пакет: контрольная сумма MD5 и криптографическая подпись с использованиемп GnuPG, GNU Privacy Guard.

2.2.3 Проверка контрольной суммы MD5

После того как вы загрузили пакет, вы должны проверить, соответствует ли контрольная сумма MD5 загруженного пакета той, что указана на страничке загрузки пакетов. У каждого пакета своя контрольная сумма, которую вы можете проверить такой командой:

shell> md5sum <пакет>

Однако не все операционные системы поддерживают команду md5sum - на некоторых она просто называется md5, а в других она вовсе не поставляется. На Linux эта команда является частью GNU Text Utilities, которые доступны для множества разных платформ.

Вы можете загрузить исходный код по адресу http://www.gnu.org/software/textutils/. Если у вас уже установлен OpenSSL, вы также можете использовать команду openssl md5 <пакет>. Реализация md5 для DOS/Windows доступна по адресу http://www.fourmilab.ch/md5/.

Пример:

shell> md5sum mysql-standard-4.0.10-gamma-pc-linux-i686.tar.gz
155836a7ed8c93aee6728a827a6aa153
                mysql-standard-4.0.10-gamma-pc-linux-i686.tar.gz

Вы должны удостовериться, что результирующая контрольная сумма соответствует той, что указана на страничке загрузки возле соответствующего пакета.

Множество зеркальных сайтов также предоставляют файл с именем `MD5SUMS', который также содержит MD5 контрольные суммы всех файлов из каталога `Downloads'. Однако заметьте, что этот файл достаточно легко изменить и это не самый надежный метод проверки целостности пакета. Если вы в сомнениях, вы должны посмотреть на другие зеркала и сравнить увиденное.

2.2.4 Проверка подписи с использованием GnuPG

Гораздо более надежный метод проверки целостности пакета это использование криптографически сигнатур. MySQL AB использует ПО GNU Privacy Guard (GnuPG), открытая альтернатива весьма известному пакету Pretty Good Privacy (PGP) Фила Циммермана (Phil Zimmermann). См. http://www.gnupg.org/ и http://www.openpgp.org/ для более подробной информации про OpenPGP/GnuPG и как его получить и поставить на вашей системе. Большинство поставок Linux уже идут с GnuPG прямо в поставке.

Начиная с MySQL 4.0.10 (Февраль 2003), MySQL AB начала подписывать загружаемые пакеты с помощью GnuPG. Криптографические сигнатуры являются гораздо более надежным методом проверки целостности и аутентичности файла.

Для проверки подписи конкретного пакета, вам в первую очередь следует получить копию публичного ключа GPG build@mysql.com. Вы можете либо взять этот ключ прямо отсюда, либо взять его на http://www.keyserver.net/.

Key ID:
pub  1024D/5072E1F5 2003-02-03
     MySQL Package signing key (www.mysql.com) <build@mysql.com>
Fingerprint: A4A9 4068 76FC BD3C 4567  70C8 8C71 8D3B 5072 E1F5

Public Key (ASCII-armored):

-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.0.6 (GNU/Linux)
Comment: For info see http://www.gnupg.org

mQGiBD4+owwRBAC14GIfUfCyEDSIePvEW3SAFUdJBtoQHH/nJKZyQT7h9bPlUWC3
RODjQReyCITRrdwyrKUGku2FmeVGwn2u2WmDMNABLnpprWPkBdCk96+OmSLN9brZ
fw2vOUgCmYv2hW0hyDHuvYlQA/BThQoADgj8AW6/0Lo7V1W9/8VuHP0gQwCgvzV3
BqOxRznNCRCRxAuAuVztHRcEAJooQK1+iSiunZMYD1WufeXfshc57S/+yeJkegNW
hxwR9pRWVArNYJdDRT+rf2RUe3vpquKNQU/hnEIUHJRQqYHo8gTxvxXNQc7fJYLV
K2HtkrPbP72vwsEKMYhhr0eKCbtLGfls9krjJ6sBgACyP/Vb7hiPwxh6rDZ7ITnE
kYpXBACmWpP8NJTkamEnPCia2ZoOHODANwpUkP43I7jsDmgtobZX9qnrAXw+uNDI
QJEXM6FSbi0LLtZciNlYsafwAPEOMDKpMqAK6IyisNtPvaLd8lH0bPAnWqcyefep
rv0sxxqUEMcM3o7wwgfN83POkDasDbs3pjwPhxvhz6//62zQJ7Q7TXlTUUwgUGFj
a2FnZSBzaWduaW5nIGtleSAod3d3Lm15c3FsLmNvbSkgPGJ1aWxkQG15c3FsLmNv
bT6IXQQTEQIAHQUCPj6jDAUJCWYBgAULBwoDBAMVAwIDFgIBAheAAAoJEIxxjTtQ
cuH1cY4AnilUwTXn8MatQOiG0a/bPxrvK/gCAJ4oinSNZRYTnblChwFaazt7PF3q
zIhMBBMRAgAMBQI+PqPRBYMJZgC7AAoJEElQ4SqycpHyJOEAn1mxHijft00bKXvu
cSo/pECUmppiAJ41M9MRVj5VcdH/KN/KjRtW6tHFPYhMBBMRAgAMBQI+QoIDBYMJ
YiKJAAoJELb1zU3GuiQ/lpEAoIhpp6BozKI8p6eaabzF5MlJH58pAKCu/ROofK8J
Eg2aLos+5zEYrB/LsrkCDQQ+PqMdEAgA7+GJfxbMdY4wslPnjH9rF4N2qfWsEN/l
xaZoJYc3a6M02WCnHl6ahT2/tBK2w1QI4YFteR47gCvtgb6O1JHffOo2HfLmRDRi
Rjd1DTCHqeyX7CHhcghj/dNRlW2Z0l5QFEcmV9U0Vhp3aFfWC4Ujfs3LU+hkAWzE
7zaD5cH9J7yv/6xuZVw411x0h4UqsTcWMu0iM1BzELqX1DY7LwoPEb/O9Rkbf4fm
Le11EzIaCa4PqARXQZc4dhSinMt6K3X4BrRsKTfozBu74F47D8Ilbf5vSYHbuE5p
/1oIDznkg/p8kW+3FxuWrycciqFTcNz215yyX39LXFnlLzKUb/F5GwADBQf+Lwqq
a8CGrRfsOAJxim63CHfty5mUc5rUSnTslGYEIOCR1BeQauyPZbPDsDD9MZ1ZaSaf
anFvwFG6Llx9xkU7tzq+vKLoWkm4u5xf3vn55VjnSd1aQ9eQnUcXiL4cnBGoTbOW
I39EcyzgslzBdC++MPjcQTcA7p6JUVsP6oAB3FQWg54tuUo0Ec8bsM8b3Ev42Lmu
QT5NdKHGwHsXTPtl0klk4bQk4OajHsiy1BMahpT27jWjJlMiJc+IWJ0mghkKHt92
6s/ymfdf5HkdQ1cyvsz5tryVI3Fx78XeSYfQvuuwqp2H139pXGEkg0n6KdUOetdZ
Whe70YGNPw1yjWJT1IhMBBgRAgAMBQI+PqMdBQkJZgGAAAoJEIxxjTtQcuH17p4A
n3r1QpVC9yhnW2cSAjq+kr72GX0eAJ4295kl6NxYEuFApmr1+0uUq/SlsQ==
=YJkx
-----END PGP PUBLIC KEY BLOCK-----

Вы можете импортировать этот ключ в ваш публичный репозитарий ключей (public keyring) используя gpg --import. См. документацию на GPG для более подробной информации о том, как работать с публичными ключами.

После того, как вы загрузили и импортирлвали публичный ключ сборки, вы можете загрузить выбранный вами пакет MySQL и соответствующую подпись, доступную на той же страничке загрузки.

Файл сигнатуры имеет расширение `.asc'. Например, сигнатура для `mysql-standard-4.0.10-gamma-pc-linux-i686.tar.gz' будет `mysql-standard-4.0.10-gamma-pc-linux-i686.tar.gz.asc'. Удостоверьтесь, чтобы оба файла находятся в том же самом каталоге и затем запустите такую команду для проверки сигнатуры файла:

shell> gpg --verify <package>.asc

Example:

shell> gpg --verify mysql-standard-4.0.10-gamma-pc-linux-i686.tar.gz.asc
gpg: Warning: using insecure memory!
gpg: Signature made Mon 03 Feb 2003 08:50:39 PM MET using DSA key ID 5072E1F5
gpg: Good signature from
     "MySQL Package signing key (www.mysql.com) <build@mysql.com>"

Сообщение "Good signature" сообщает вам о том, что все в порядке.

Для пакетов RPM, отдельного файла подписи не предоставляется - пакеты RPM уже сами по себе имеют встроенную поддержку подписей GPG и контрольных сумм MD5. Вы можете проверить их такой командой:

shell> rpm --checksig <package>.rpm

Пример:

shell> 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) (даже несмотря на то, что вы импортировали ключ в ваш публичный репозиторий ключей GPG, keyring) - вам следует импортировать ключ в репозиторий ключей RPM. RPM 4.1 больше не использует ваш репозиторий ключей GPG (и GPG вообще), но поддерживает свой репозиторий, поскольку RPM - это общесистемная утилита, а репозиторий ключей GPG - это специфичный для пользователя файл). Чтобы импортировать публичный ключ MySQL в RPM, используйте вот такую команду:

shell> rpm --import <pubkey>

Пример:

shell> rpm --import mysql_pubkey.asc

Если вдруг вы заметите что контрольные суммы MD5 или подпись GPG не совпадают, попробуйте в первую очередь загрузить соответствующий пакет еще один раз, может быть, даже с другого сервера. Если вы не сможете успешно удостовериться в целостности пакета, пожалуйста, сообщите нам о подобных инцидентах, включая полное имя пакета и адрес сайта, с которого вы пытались загрузить пакет, на адрес webmaster@mysql.com или build@mysql.com.

2.2.5 Операционные системы, поддерживаемые MySQL

Мы применяем GNU Autoconf, что дает возможность переносить MySQL на все современные системы с работающими потоками Posix и компилятором C++ (чтобы скомпилировать только код клиента, требуется только компилятор C++ без использования потоков). Для себя мы используем и разрабатываем программное обеспечение в основном на Sun Solaris (версий 2.5 - 2.7) и SuSE Linux версии 7.x.

Следует учитывать, что для многих операционных систем поддержка собственных потоков работает только в самых последних версиях. Согласно полученным нами сообщениям, MySQL успешно компилируется на следующих комбинациях операционных систем и потоковых пакетов:

  • AIX 4.x, 5.x с собственными потоками. См.раздел See section 2.6.6.4 Примечания к IBM-AIX.
  • Amiga.
  • BSDI 2.x с пакетом MIT-pthreads. See section 2.6.4.5 Примечания к BSD/OS версий 2.x.
  • BSDI 3.0, 3.1 и 4.x с собственными потоками. See section 2.6.4.5 Примечания к BSD/OS версий 2.x.
  • DEC Unix 4.x с собственными потоками. See section 2.6.6.6 Примечания к Alpha-DEC-UNIX (Tru64).
  • FreeBSD 2.x с пакетом MIT-pthreads. See section 2.6.4.1 Примечания к FreeBSD.
  • FreeBSD 3.x и 4.x с собственными потоками. See section 2.6.4.1 Примечания к FreeBSD.
  • HP-UX 10.20 с пакетом MIT-pthreads или пакетом DCE-threads. See section 2.6.6.2 Примечания к HP-UX версии 10.20.
  • HP-UX 11.x с собственными потоками. See section 2.6.6.3 Примечания к HP-UX версий 11.x.
  • Linux 2.0+ с потоками LinuxThreads 0.7.1+ или glibc 2.0.7+. См. раздел See section 2.6.1 Примечания к Linux (Все версии Linux).
  • Mac OS X. See section 2.6.5 Примечания к Mac OS X.
  • NetBSD 1.3/1.4 Intel и NetBSD 1.3 Alpha (требует GNU make). See section 2.6.4.2 Примечания к NetBSD.
  • OpenBSD > 2.5 с собственными потоками. OpenBSD < 2.5 с пакетом MIT-pthreads. See section 2.6.4.3 Примечания к OpenBSD 2.5.
  • OS/2 Warp 3, FixPack 29 и OS/2 Warp 4, FixPack 4. See section 2.6.7 Примечания к OS/2.
  • SGI Irix 6.x с собственными потоками. See section 2.6.6.8 Примечания к SGI Irix.
  • Solaris 2.5 и выше с собственными потоками на SPARC и x86. See section 2.6.3 Примечания к Solaris.
  • SunOS 4.x с пакетом MIT-pthreads. See section 2.6.3 Примечания к Solaris.
  • Caldera (SCO) OpenServer с последним портом пакета FSU Pthreads. See section 2.6.6.9 Примечания к Caldera (SCO).
  • Caldera (SCO) UnixWare 7.0.1. See section 2.6.6.10 Примечания к Caldera (SCO) Unixware Version 7.0.
  • Tru64 Unix
  • Windows 9x, Me, NT, 2000 и XP. See section 2.6.2 Примечания к Windows.

Следует отметить, что не на всех платформах MySQL функционирует одинаково хорошо. Насколько подходит определенная платформа для высоконагружаемого многоцелевого сервера MySQL, определяется следующими факторами:

  • Общая стабильность потоковой библиотеки. Платформа может иметь отличную репутацию в других отношениях, но если в коде, который вызывается MySQL, потоковая библиотека нестабильна, то, даже если все остальное прекрасно, стабильность MySQL будет определяться стабильностью потоковой библиотеки.
  • Способность ядра и/или библиотеки потоков пользоваться преимуществом симметричной многопроцессорной обработки (SMP) на многопроцессорных системах. Другими словами, при создании процессом потока для этого потока должна быть возможность работать на ином центральном процессоре (CPU), чем исходный процесс.
  • Способность библиотеки ядра и/или потоков запускать много потоков, которые приобретают/освобождают синхронизирующий флаг в небольшой критической области, часто без излишних переключений контекста. Иными словами, если реализация pthread_mutex_lock() является очень ``уступающей'' время центрального процессора, это значительно вредит MySQL. Если не принять во внимание данное обстоятельство, то использование добавочных центральных процессоров сделает MySQL существенно медленнее.
  • Общая стабильность/производительность файловой системы.
  • Способность файловой системы работать с большими файлами вообще и работать с ними эффективно в случае больших таблиц.
  • Наш, т.е. разработчиков, уровень компетенции в том, что касается данной платформы. Для платформ, которые мы знаем хорошо, мы вводим в MySQL специфические для платформы оптимизации/исправления, доступные во время компиляции. Кроме того, мы можем также дать совет по оптимальной для MySQL конфигурации вашей системы.
  • Выполненный нами у себя объем тестирования подобных конфигураций.
  • Количество пользователей, успешно применяющих MySQL на данной платформе в подобных конфигурациях. Если это количество велико, то шансы получить некоторые специфические для данной платформы сюрпризы, намного меньше.

В соответствии с предыдущими критериями наилучшими платформами с этой точки зрения для функционирования MySQL являются: x86 под управлением SuSE Linux 7.1, с ядром 2.4 и ReiserFS (или любой подобный дистрибутив Linux) и SPARC под управлением Solaris 2.7 или 2.8. FreeBSD оказывается третьей, но мы в самом деле надеемся, что эта платформа войдет в число лучших, как только станет совершеннее потоковая библиотека. Мы также надеемся, что, с некоторого момента, мы сможем включить в высшую категорию все остальные платформы, на которых MySQL компилируется и функционирует нормально, но не с тем же уровнем стабильности и производительности. Это потребует некоторых усилий с нашей стороны в сотрудничестве с разработчиками компонентов операционных систем и библиотек, от которых зависит MySQL. Если вы заинтересованы в улучшении тех или иных компонентов, у вас есть возможность оказать влияние на их разработку и вы нуждаетесь в подробных инструкциях по поводу того, что нужно MySQL, чтобы работать лучше, пошлите письмо по адресу internals@lists.mysql.com.

Просьба к вам: на основании приведенных выше сравнительных характеристик не делать выводов о том, что какая-либо операционная система лучше или хуже другой в общем. Мы говорим о выборе определенной операционной системы для конкретной цели - для работы MySQL, и сравниваем платформы только в таком смысле. С этой точки зрения результат такого сравнения был бы другим, если бы мы включили в него больше пунктов. И в некоторых случаях причина того, что одна операционная система лучше, чем другая, может заключаться всего лишь в том, что в тестирование и оптимизацию этой конкретной платформы было вложено гораздо больше усилий. Мы просто констатируем наши наблюдения, чтобы помочь вам принять решение - на какой платформе использовать MySQL в вашей системе.

2.2.6 Какую версию MySQL использовать

Во-первых, нужно принять решение о том, что именно вам требуется - самый свежий экспериментальный выпуск или последняя устойчивая версия:

  • Если вы собираетесь использовать MySQL впервые или пытаетесь выполнить перенос MySQL на некоторую систему, для которой нет бинарного дистрибутива, то обычно мы рекомендуем начинать со стабильной версии (в настоящее время это версия 3.23). Следует иметь в виду, что все релизы MySQL проверяются с помощью тестов производительности MySQL и набора всесторонних тестов перед каждым выпуском (даже для экспериментальных выпусков).
  • Если же вы работаете со старой системой и желаете ее модернизировать, но хотите избежать возможных нестыковок при модернизации, то необходимо проводить замену на самую новую версию в той же ветви, которую вы используете (где только последний номер версии более новый, чем у вашей). В таких версиях мы стараемся исправлять только критические ошибки и делать только небольшие, относительно безопасные изменения.

Во-вторых, нужно принять решение, хотите ли вы использовать дистрибутив исходного кода или бинарный дистрибутив. В большинстве случаев лучше остановить свой выбор на бинарном дистрибутиве, если такой существует для вашей платформы, так как обычно его проще установить, чем дистрибутив исходного кода.

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

  • Если необходимо инсталлировать MySQL в некотором явно заданном местоположении (стандартные бинарные поставки являются ``готовыми к запуску'' в любом месте, но, возможно, вам потребуется еще большая гибкость).
  • Чтобы удовлетворить различные требования пользователей, мы поставляем две разных бинарных версии: одна скомпилирована с обработчиками нетранзакционных таблиц (небольшой, быстрый бинарный код), а вторая сконфигурирована с наиболее важными возможностями расширения, такими, как поддерживающие транзакции таблицы. Обе версии компилируются из одного и того же исходного кода. Все собственные клиенты MySQL могут подключаться к обеим версиям. Бинарный дистрибутив расширенной версии MySQL маркируется суффиксом -max и конфигурируется с теми же опциями, что и mysqld-max. See section 4.7.5 mysqld-max, расширенный сервер mysqld. Если вы хотите использовать пакет RPM MySQL-Max, то сначала следует установить стандартный пакет MySQL RPM.
  • Если вам нужно сконфигурировать mysqld с некоторыми дополнительными свойствами, которые отсутствуют в стандартных бинарных дистрибутивах. Ниже приводится список наиболее распространенных дополнительных опций, которые, возможно, вы захотите использовать:
    • --with-innodb
    • --with-berkeley-db
    • --with-raid
    • --with-libwrap
    • --with-named-z-lib (Это делается для некоторых бинарных дистрибутивов)
    • --with-debug[=full]
  • По умолчанию бинарный дистрибутив обычно компилируется с поддержкой всех кодировок и должен работать на различных процессорах из одного и того же семейства процессоров. Если требуется получить более быстрый сервер MySQL, то можно перекомпилировать его с поддержкой только одной необходимой вам кодировки, использовать лучший компилятор (наподобие pgcc) или воспользоваться опциями компилятора, которые лучше оптимизированы для вашего процессора.
  • Если вы нашли ошибку и сообщили о ней команде разработчиков MySQL, то вам должны выслать патч, который следует применить к дистрибутиву исходного кода для исправления ошибки.
  • Если вы хотите читать (и/или модифицировать) исходный код MySQL (на C и C++), необходимо иметь дистрибутив исходного кода. Исходный код - это всегда лучшая документация. Дистрибутивы исходного кода также содержат больше тестов и примеров, чем бинарные дистрибутивы.

В системе наименований в MySQL используются номера выпусков, состоящие из трех чисел и суффикса. Например, выпуск mysql-3.21.17-beta интерпретируется следующим образом:

  • Первое число (3) служит для описания формата файлов. Все выпуски версии 3 имеют один и тот же формат файлов.
  • Второе число (21) представляет собой уровень выпуска. Обычно существует выбор из двух возможностей. Одна представляет выпуск стабильной ветви (в настоящее время 23) и вторая - экспериментальную ветвь (в настоящее время 4.0). Обычно обе ветви стабильны, но экспериментальная версия может обладать некоторыми причудами, возможно отсутствие документации на новые свойства, либо она может не компилироваться на некоторых системах.
  • Третье число (17) является номером версии в пределах уровня выпуска. Это число увеличивается для каждого нового дистрибутива. Обычно имеет смысл предпочесть самую последнюю версию для выбранного уровня выпуска.
  • Суффикс (beta) указывает на уровень стабильности данного выпуска. Возможны следующие суффиксы:
    • alpha указывает, что выпуск содержит большие разделы нового кода, не протестированного на 100%. Обнаруженные ошибки (обычно их нет) должны быть задокументированы в разделе ``Новости'' (News). См. раздел See section C История изменений и обновлений MySQL. В большинстве выпусков alpha присутствуют также новые команды и расширения. При работе над alpha-выпуском может происходить активная разработка, включающая значительные изменения кода, но перед выпуском все тестируется. В любом выпуске MySQL не должно быть известных ошибок.
    • beta означает, что весь новый код протестирован. Не добавляются никакие новые свойства, которые могли бы вызвать повреждения старого кода. Не должно быть никаких известных ошибок. Версия изменяется с alpha на beta тогда, когда никаких сообщений о критических ошибках в alpha-версии не поступает по меньшей мере в течение месяца и мы не планируем добавлять какие- либо новые свойства, которые могли бы понизить надежность прежних команд.
    • gamma представляет собой версию beta, которая почти закончена и, похоже, работает хорошо. Добавляются только незначительные исправления. Это именно то, что во многих других компаниях называется релизом.
    • Если нет никакого суффикса, это означает, что данная версия запускалась на многих различных компьютерных системах без сообщений об ошибках, кроме ошибок, относящихся к специфике платформ; для нее допускается только исправление критических ошибок. Именно поэтому такой выпуск мы называем стабильным.

Все версии MySQL пропускаются через наши стандартные тесты и контрольные задачи, чтобы получить уверенность в том, что они надежны в применении. Так как стандартные тесты периодически дополняются, чтобы включить проверку обнаруженных новых ошибок и ситуаций, которые могут их вызвать, то набор тестов со временем становится лучше и лучше.

Отметим, что все выпуски протестированы по меньшей мере со следующими тестами:

Внутренний набор тестов
Набор является частью производственной системы для заказчика. Этот набор включает много таблиц с сотнями мегабайт данных.
Набор тестов производительности MySQL
Эти тесты работают с набором общеупотребительных запросов. Кроме того, они позволяют увидеть, действительно ли последний пакет оптимизаций делает код быстрее. See section 5.1.4 Набор тестов MySQL (The MySQL Benchmark Suite).
Тест crash-me
Тест пытается определить, какие функциональные возможности поддерживает база данных и каковы ее возможности и ограничения. See section 5.1.4 Набор тестов MySQL (The MySQL Benchmark Suite).

Существует еще один тест. Он заключается в том, что мы используем самую новую версию MySQL в нашей внутренней производственной среде по крайней мере на одной машине. Для работы с этой версией у нас есть более чем 100 гигабайт данных.

2.2.7 Схемы установки

В этом разделе описывается расположение каталогов, создаваемых по умолчанию при установке бинарного дистрибутива и дистрибутива исходного кода.

Бинарный дистрибутив устанавливается путем его распаковки в выбранном вами месте установки (обычно `/usr/local/mysql') и создает следующие каталоги:

Каталог | Содержание каталога
`bin' | Клиентские программы и сервер mysqld
`data' | Файлы журналов, базы данных
`include' | Включаемые (заголовочные) файлы
`lib' | Библиотеки
`scripts' | mysql_install_db
`share/mysql' | Файлы с текстами сообщений об ошибках
`sql-bench' | Тесты производительности

Дистрибутив исходного кода устанавливается после того, как вы сконфигурируете и скомпилируете его. По умолчанию на этапе установки файлы инсталлируются в каталог `/usr/local' в следующие подкаталоги:

Каталог | Содержание каталога
`bin' | Клиентские программы и скрипты
`include/mysql' | Включаемые (заголовочные) файлы
`info' | Документация в формате Info
`lib/mysql' | Библиотеки
`libexec' | Сервер mysqld
`share/mysql' | Файлы с текстами сообщений об ошибках
`sql-bench' | Тесты производительности и тест crash-me
`var' | Базы данных и файлы журналов

Внутри каталога установки схема расположения инсталляции исходного кода отличается от схемы установки бинарного дистрибутива в следующих отношениях:

  • Сервер mysqld устанавливается в каталог `libexec', а не в `bin'.
  • Каталогом данных является `var', а не `data'.
  • mysql_install_db устанавливается в каталоге `/usr/local/bin', а не в `/usr/local/mysql/scripts'.
  • Каталогами заголовочных файлов и библиотек являются `include/mysql' и `lib/mysql', а не `include' и `lib'.

Можно создать собственную бинарную установку из скомпилированного дистрибутива исходного кода. Для этого следует выполнить скрипт `scripts/make_binary_distribution'.

2.2.8 Как и когда выпускаются обновления

Развитие MySQL в MySQL AB происходит очень быстрыми темпами и мы стремимся к тому, чтобы результаты нашей работы стали доступны и другим пользователям MySQL. Мы стараемся сделать новый выпуск сразу же, как только в продукте появляются очень полезные свойства, которые, по нашему мнению, необходимы другим пользователям.

Помимо этого мы откликаемся на просьбы наших пользователей, если для этого требуется добавить в продукт легко реализуемые свойства. Мы принимаем во внимание пожелания наших пользователей, имеющих лицензии, а особенно - пожелания обширного круга пользователей, охваченных поддержкой при помощи электронной почты, и стараемся помочь им решить их проблемы.

Загружать новый выпуск не обязательно. Информацию о том, действительно ли новый выпуск представляет собой именно то, что вам требуется, вы почерпнете из раздела ``Новости'' (News). See section C История изменений и обновлений MySQL.

Наша политика в вопросах обновления MySQL заключается в следующем:

  • Для каждого небольшого обновления последняя цифра в строке версии увеличивается. При внесении существенно новых свойств или небольших несовместимостей с предыдущими версиями увеличивается второе число в строке версии. Если изменяется формат файлов, то увеличивается первая цифра.
  • Протестированные на устойчивость версии должны обычно появляться 1-2 раза в год, но если обнаруживаются небольшие ошибки, то выпускаются версии только с исправлениями ошибок.
  • Рабочие исправления к старым версиям должны появляться примерно каждые 1-8 недель.
  • Бинарные дистрибутивы для некоторых платформ мы будем делать для значительных выпусков. Бинарные дистрибутивы для других систем иногда создаются и другими людьми, но, как правило, не так часто.
  • Обычно мы делаем патчи доступными сразу же после локализации и исправления небольших ошибок. Они посылаются на bugs@lists.mysql.com и включаются в очередной выпуск.
  • Некритические, но досадные ошибки мы будем добавлять в репозиторий исходного кода MySQL и они будут исправляться в следующем выпуске.
  • Если по какой-либо случайности в выпуске окажется критическая ошибка, то мы сделаем новый выпуск как можно скорее. Мы хотели бы, чтобы нашему примеру и следовали и другие компании.

Текущим стабильным выпуском сейчас является версия 3.23; уже начата активную разработка версии 4.0. Ошибки в стабильной версии по-прежнему будут исправляться. Мы не верим в полное ``замораживание'', поскольку при этом упускаются исправления ошибок и вещи, которые ``должны быть сделаны''. ``Отчасти заморожено'' подразумевает, что мы можем добавить некоторые вещи, которые ``почти несомненно не окажут влияния ни на что из того, что уже работает''.

В MySQL применяется несколько отличающаяся от большинства других продуктов система именования. В общем случае достаточно надежно использовать любую версию, просуществовавшую в течение пары недель без замены ее новой версией. See section 2.2.6 Какую версию MySQL использовать.

2.2.9 Бинарные коды MySQL, скомпилированные в MySQL AB

Компания MySQL AB в качестве услуги предоставляет набор бинарных (скомпилированных) дистрибутивов MySQL - они скомпилированы на нашем оборудовании или на вычислительных системах, к которым нам любезно предоставили доступ заказчики.

Эти дистрибутивы сгенерированы скриптом Build-tools/Do-compile, который компилирует дерево исходных кодов, и создает архив .tar.gz используя scripts/make_binary_distribution

Эти бинарники сконфигурированы и собраны с помощью следующих компиляторов и опций.

Linux 2.4.xx i386 с gcc 2.95.3
CFLAGS="-O2 -mcpu=pentiumpro" CXX=gcc CXXFLAGS="-O2
-mcpu=pentiumpro -felide-constructors" ./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=-all-static
Linux 2.4.xx ia64 с ecc (Intel C++ Itanium Compiler 7.0)
CC=ecc CFLAGS=-tpp1 CXX=ecc CXXFLAGS=-tpp1 ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile
Linux 2.4.xx alpha с ccc (Compaq C 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-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --with-mysqld-ldflags=-non_shared --with-client-ldflags=-non_shared --disable-shared
Linux 2.2.xx sparc с egcs 1.1.2
CC=gcc CFLAGS="-O3 -fno-omit-frame-pointer" CXX=gcc CXXFLAGS="-O3 -fno-omit-frame-pointer -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --enable-assembler --disable-shared
Linux 2.4.xx s390 с gcc 2.95.3
CFLAGS="-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
Sun Solaris 2.8 sparc с gcc 3.2
CC=gcc CFLAGS="-O3 -fno-omit-frame-pointer" CXX=gcc CXXFLAGS="-O3 -fno-omit-frame-pointer -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --enable-assembler --with-named-z-libs=no --with-named-curses-libs=-lcurses --disable-shared
Sun Solaris 2.9 sparc с gcc 2.95.3
CC=gcc CFLAGS="-O3 -fno-omit-frame-pointer" CXX=gcc CXXFLAGS="-O3 -fno-omit-frame-pointer -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --enable-assembler --with-named-curses-libs=-lcurses --disable-shared
Sun Solaris 2.9 sparc с cc-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-safe-client --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.1
CFLAGS="-O2 -mcpu=powerpc -Wa,-many " CXX=gcc CXXFLAGS="-O2 -mcpu=powerpc -Wa,-many -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --with-named-z-libs=no --disable-shared
IBM AIX 5.1.0 ppc с gcc 3.2.1
CFLAGS="-O2 -mcpu=powerpc -Wa,-many" CXX=gcc CXXFLAGS="-O2 -mcpu=powerpc -Wa,-many -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --with-server-suffix="-pro" --enable-thread-safe-client --enable-local-infile --with-named-z-libs=no --disable-shared --with-innodb
HP-UX 10.20 pa-risc1.1 с gcc 3.1
CFLAGS="-DHPUX -I/opt/dce/include -O3 -fPIC" CXX=gcc CXXFLAGS="-DHPUX -I/opt/dce /include -felide-constructors -fno-exceptions -fno-rtti -O3 -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
HP-UX 11.11 pa-risc2.0 с aCC (HP ANSI 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
Apple MacOS X 10.2 powerpc с gcc 3.1
CC=gcc CFLAGS="-O3 -fno-omit-frame-pointer" CXX=gcc CXXFLAGS="-O3 -fno-omit-frame-pointer -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --disable-shared
FreeBSD 4.7 i386 с gcc 2.95.4
CFLAGS=-DHAVE_BROKEN_REALPATH ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --enable-assembler --with-named-z-libs=not-used --disable-shared

Следующие бинарные поставки собраны на системах, предоставленных MySQL AB пользователями. Заметьте, что эти бинарные поставки предоставляются исключительно для удобства. Поскольку у MySQL AB нет полного контроля над этими системами, мы только можем дать ограниченную поддержку этих бинарных поставок.

SCO Unix 3.2v5.0.6 i386 с gcc 2.95.3
CFLAGS="-O3 -mpentium" LDFLAGS=-static CXX=gcc CXXFLAGS="-O3 -mpentium -felide-constructors" ./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
Caldera Open Unix 8.0.0 i386 с CC 3.2
CC=cc CFLAGS="-O" CXX=CC ./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
Compaq Tru64 OSF/1 V5.1 732 alpha с cc/cxx (Compaq C V6.3-029i / DIGITAL C++ V6.1-027)
CC="cc -pthread" CFLAGS="-O4 -ansi_alias -ansi_args -fast -inline speed -speculate all" CXX="cxx -pthread" CXXFLAGS="-O4 -ansi_alias -fast -inline speed -speculate all -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 -lc" --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-frame-pointer -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --disable-shared

Такие опции компиляции использовались для бинарных поставок MySQL AB в прошлом. Такие бинарные поставки более не обновляются, но опции компиляции мы сохранили здесь как реферативную информацию.

Linux 2.2.x с x686 с gcc 2.95.2
CFLAGS="-O3 -mpentiumpro" CXX=gcc CXXFLAGS="-O3 -mpentiumpro
-felide-constructors -fno-exceptions -fno-rtti" ./configure
--prefix=/usr/local/mysql --enable-assembler
--with-mysqld-ldflags=-all-static --disable-shared
--with-extra-charsets=complex
SunOS 4.1.4 2 sun4c с gcc 2.7.2.1
CC=gcc CXX=gcc CXXFLAGS="-O3 -felide-constructors" ./configure
--prefix=/usr/local/mysql --disable-shared
--with-extra-charsets=complex --enable-assembler
SunOS 5.5.1 (and above) sun4u с egcs 1.0.3a or 2.90.27 or gcc 2.95.2 and newer
CC=gcc CFLAGS="-O3" CXX=gcc CXXFLAGS="-O3 -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --with-low-memory --with-extra-charsets=complex --enable-assembler
SunOS 5.6 i86pc с gcc 2.8.1
CC=gcc CXX=gcc CXXFLAGS=-O3 ./configure --prefix=/usr/local/mysql --with-low-memory --with-extra-charsets=complex
BSDI BSD/OS 3.1 i386 с gcc 2.7.2.1
CC=gcc CXX=gcc CXXFLAGS=-O ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex
BSDI BSD/OS 2.1 i386 с gcc 2.7.2
CC=gcc CXX=gcc CXXFLAGS=-O3 ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex
AIX 2 4 с gcc 2.7.2.2
CC=gcc CXX=gcc CXXFLAGS=-O3 ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex

Каждый, кто обладает более оптимальными опциями для любой из вышеперечисленных конфигураций, в любое время может выслать их в список рассылки разработчиков по адресу internals@lists.mysql.com.

Дистрибутивы RPM для версии MySQL до 3.22 создавались силами пользователей. Однако начиная с версии 3.22, пакеты RPM собираются у нас в MySQL AB.

Если вы хотите скомпилировать отладочную версию MySQL, то следует добавить --with-debug или --with-debug=full к предыдущим строкам конфигурации и удалить любые опции -fomit-frame-pointer.

По вопросам, относящимся к дистрибутиву для Windows, просьба обращаться к разделу See section 2.1.2 Установка MySQL на Windows.

2.2.10 Установка бинарного дистрибутива MySQL

См. также раздел See section 2.1.2.1 Установка бинарного кода, раздел section 2.1.1 Установка MySQL на Linux и раздел See section 8.4.7 Сборка клиентских программ.

Для установки бинарного дистрибутива MySQL необходимы следующие инструментальные средства:

  • GNU gunzip для разархивирования дистрибутива.
  • Подходящий tar для распаковки дистрибутива. GNU tar известен как работающий, а tar разработки Sun - как имеющий проблемы.

Для Linux существует альтернативный метод установки с использованием дистрибутива RPM (RedHat Package Manager, менеджер пакетов RedHat). См. раздел See section 2.1.1 Установка MySQL на Linux.

Если вам придется столкнуться с проблемами, то, пожалуйста, при отправке вопросов на mysql@lists.mysql.com всегда пользуйтесь mysqlbug. Даже если ваша проблема не относится к числу ошибок, mysqlbug соберет системную информацию, которая поможет решать такие проблемы и другим. Без mysqlbug вы уменьшаете вероятность получить решение своей проблемы! mysqlbug можно найти в каталоге `scripts' после распаковки дистрибутива. See section 1.8.1.3 Как отправлять отчеты об ошибках или проблемах.

Для установки бинарного дистрибутива MySQL необходимо выполнить следующие основные команды:

shell> groupadd mysql
shell> useradd -g mysql mysql
shell> cd /usr/local
shell> gunzip < /path/to/mysql-VERSION-OS.tar.gz | tar xvf -
shell> ln -s full-path-to-mysql-VERSION-OS mysql
shell> cd mysql
shell> scripts/mysql_install_db
shell> chown -R root .
shell> chown -R mysql data
shell> chgrp -R mysql .
shell> bin/safe_mysqld --user=mysql &

или

shell> bin/mysqld_safe --user=mysql &

если вы работаете с MySQL 4.x

Новых пользователей можно добавить, используя скрипт bin/mysql_setpermission, если установить модули Perl DBI и Msql-Mysql-modules.

Далее следует более детальное описание.

Для установки бинарного дистрибутива выполните приведенные ниже действия, а затем перейдите к разделу section 2.4 Послеустановочные настройка и тестирование для послеустановочной настройки и проверки:

  1. Выберите каталог, в котором вы хотите распаковать дистрибутив, и откройте его. В последующих примерах мы распаковываем дистрибутив под `/usr/local' и создаем каталог `/usr/local/mysql', в котором устанавливается MySQL. (Для выполнения дальнейших инструкций, следовательно, предполагается, что вы обладаете правами создания файлов в `/usr/local'. Если этот каталог защищен, то вы должны производить установку как пользователь root.)
  2. Получите файл дистрибутива с одного из сайтов, перечисленных в разделе See section 2.2.1 Как получить MySQL. Бинарные дистрибутивы MySQL поставляются как сжатые архивы tar с именами вроде `mysql-VERSION-OS.tar.gz', где VERSION представляет собой число (например 5.0.0-alpha), а OS указывает тип операционной системы, для которой предназначен данный дистрибутив (например pc-linux-gnu-i586).
  3. Если бинарный дистрибутив маркирован суффиксом -max, то это означает, что данный бинарный код поддерживает транзакционные таблицы и другие свойства. See section 4.7.5 mysqld-max, расширенный сервер mysqld. Отметим, что все бинарные дистрибутивы созданы из одного и того же дистрибутива исходного кода MySQL.
  4. Добавьте пользователя и группу для запуска mysqld как:
    shell> groupadd mysql
shell> useradd -g mysql mysql
    Приведенные команды добавляют группу mysql и пользователя mysql. Данный синтаксис для useradd и groupadd для различных версиях Unix может иметь некоторые различия. Эти команды могут также называться adduser и addgroup. При желании можно дать пользователю и группе вместо mysql другие имена.
  5. Задайте предназначенный для установки каталог:
    shell> cd /usr/local
  6. Распакуйте дистрибутив и создайте каталог установки:
    shell> gunzip < /path/to/mysql-VERSION-OS.tar.gz | tar xvf -
shell> ln -s full-path-to-mysql-VERSION-OS mysql
    Первая команда создает каталог с именем mysql-VERSION-OS, а вторая - устанавливает символическую ссылку на данный каталог. Это позволяет более просто ссылаться на каталог установки - как на `/usr/local/mysql'.
  7. Измените в каталоге установки:
    shell> cd mysql
    В каталоге mysql вы найдете несколько файлов и подкаталогов. Наиболее важными для целей установки являются подкаталоги `bin' и `scripts'.
    `bin'
    Этот каталог содержит клиентские программы и сервер. Необходимо добавить полный путь к этому каталогу в переменную окружения PATH, чтобы оболочка операционной системы правильно находила программы MySQL. See section E Переменные окружения.
    `scripts'
    Этот каталог содержит скрипт mysql_install_db, используемый для инициализации базы данных mysql, содержащей таблицы привилегий, в которых хранятся права доступа к серверу.
  8. Если вы предпочитаете использовать mysqlaccess и установить дистрибутив MySQL в каком-либо нестандартном месте, то необходимо изменить место, где mysqlaccess ожидает найти клиента mysql. Отредактируйте скрипт `bin/mysqlaccess' примерно на 18-й строке. Найдите строку, выглядящую примерно так:
    $MYSQL = '/usr/local/bin/mysql'; # путь к исполняемому клиенту mysql
    Измените путь для указания того места в системе, где действительно находится mysql. Если этого не сделать, то возникнет ошибка Broken pipe при запуске mysqlaccess.
  9. Создайте таблицы привилегий MySQL (необходимы только в том случае, если ранее MySQL не устанавливался):
    shell> scripts/mysql_install_db
    Отметим, что в версиях MySQL старше, чем 3.22.10, сервер MySQL запускался при запуске mysql_install_db. Сейчас это не так!
  10. Измените принадлежность бинарного кода пользователю root и принадлежность каталога данных пользователю, под которым будет запускаться mysqld, следующим образом:
    shell> chown -R root /usr/local/mysql/.
shell> chown -R mysql /usr/local/mysql/data
shell> chgrp -R mysql /usr/local/mysql/.
    Первая команда изменяет владельца данного файла на пользователя root, вторая - владельца каталога данных на пользователя mysql, а третья - группу на группу mysql.
  11. Если вы хотите установить поддержку интерфейса Perl DBI/DBD, See section 2.7 Замечания по установке Perl.
  12. Если вы хотели бы, чтобы работа MySQL начиналась автоматически при начальной загрузке компьютера, то можно скопировать `support-files/mysql.server' в то место, где находятся файлы запуска вашей системы. Более подробную информацию можно найти в самом скрипте `support-files/mysql.server' и в разделе See section 2.4.3 Автоматический запуск и остановка MySQL.

После того, как все это будет установлено, необходимо инициализировать и протестировать данный дистрибутив.

Запустить сервер MySQL можно с помощью следующей команды:

shell> bin/safe_mysqld --user=mysql &

А сейчас следует перейти к разделу section 4.7.2 safe_mysqld, оболочка mysqld и просмотреть раздел See section 2.4 Послеустановочные настройка и тестирование.

2.3 Установка исходного дистрибутива MySQL

Перед тем как приступить к установке исходного кода, вначале убедитесь, что наш бинарный дистрибутив подходит для вашей платформы и что он будет работать на вашей системе. Мы прилагаем много усилий для того, чтобы снабдить наши бинарные дистрибутивы наилучшими свойствами из возможных.

Для сборки и установки MySQL из исходного кода необходимы следующие инструменты:

  • GNU gunzip для разархивирования дистрибутива.
  • Подходящий tar для распаковки дистрибутива. Известно, что GNU tar является работоспособным, а tar разработки Sun имеет проблемы.
  • Работающий компилятор ANSI C++. К числу компиляторов, о которых известно, что они работают, относятся версии gcc >= 2.95.2, egcs >= 1.0.2 или egcs 2.91.66, SGI C++ и SunPro C++. При использовании gcc нет необходимости в libg++. Версия gcc 2.7.x имеет ошибку, из-за которой невозможна компиляция некоторых полностью допустимых файлов C++, таких как `sql/sql_base.cc'. Если у вас есть только gcc 2.7.x, то для того, чтобы можно было провести компиляцию MySQL, необходимо модернизировать gcc. Компилятор gcc 2.8.1, как известно, также имеет проблемы на некоторых платформах, так что его лучше не использовать, если для данной платформы существует новый компилятор. При компиляции версии MySQL 3.23.x рекомендуется gcc >= 2.95.2.
  • Хорошая программа make. Всегда рекомендуется (а иногда и необходимо) использовать GNU make. В случае возникновения проблем мы рекомендуем попробовать работать с версией GNU make 3.75 или более новой.

Очень важно, чтобы вы использовали последнюю версию gcc, достаточно новую, чтобы ``понимать'' опцию -fno-exceptions. В противном случае не исключена компиляция бинарного кода, который может неожиданно привести к отказу. Мы также рекомендуем использовать -felide-constructors и -fno-rtti вместе с -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

На большинстве операционных систем это даст быстрый и стабильный бинарный код.

Если вам придется столкнуться с проблемами, то при отправке вопросов на mysql@lists.mysql.com, пожалуйста, всегда используйте mysqlbug. Даже если ваша проблема не вызвана какой-либо ошибкой, mysqlbug соберет системную информацию, которая в поможет решении этой проблемы другим пользователям. Без mysqlbug уменьшается вероятность того, что вы получите решение своей проблемы! mysqlbug можно найти в каталоге `scripts' после распаковки дистрибутива. See section 1.8.1.3 Как отправлять отчеты об ошибках или проблемах.

2.3.1 Обзор быстрой установки

Для установки MySQL из исходного кода необходимо выполнить следующие основные команды:

shell> groupadd mysql
shell> useradd -g mysql mysql
shell> gunzip < mysql-VERSION.tar.gz | tar -xvf -
shell> cd mysql-VERSION
shell> ./configure --prefix=/usr/local/mysql
shell> make
shell> make install
shell> scripts/mysql_install_db
shell> chown -R root /usr/local/mysql
shell> chown -R mysql /usr/local/mysql/var
shell> chgrp -R mysql /usr/local/mysql
shell> cp support-files/my-medium.cnf /etc/my.cnf
shell> /usr/local/mysql/bin/safe_mysqld --user=mysql &
или
shell> /usr/local/mysql/bin/mysqld_safe --user=mysql &

если запускается версия MySQL 4.x.

Чтобы обеспечить поддержку таблиц InnoDB, следует отредактировать файл `/etc/my.cnf', удалив символ # перед теми параметрами, которые начинаются с innodb_.... See section 4.1.2 Файлы параметров `my.cnf'. See section 7.5.2 Параметры запуска InnoDB.

Если вы используете исходный код RPM, выполните следующую команду:

shell> rpm --rebuild --clean MySQL-VERSION.src.rpm

Эта команда создаст бинарный код RPM, который вы можете установить.

Новых пользователей можно добавить, используя скрипт bin/mysql_setpermission, если установить модули Perl DBI и Msql-Mysql-modules.

Ниже следует более подробное описание установки.

Для установки исходного кода нужно выполнить приведенные ниже действия, а затем перейти к разделу section 2.4 Послеустановочные настройка и тестирование для инициализации и послеустановочной проверки:

  1. Выберите каталог, в котором вы хотите распаковать дистрибутив, и откройте его. Получите файл дистрибутива с одного из сайтов, перечисленных в разделе See section 2.2.1 Как получить MySQL.
  2. Если вы заинтересованы в том, чтобы использовать с MySQL таблицы Berkeley DB, то необходимо получить версию исходного кода таблиц Berkeley DB с патчами. Кроме того, прежде чем предпринимать какие-либо действия, ознакомьтесь, пожалуйста, с разделом, посвященным таблицам Berkeley DB (see section 7.6 Таблицы BDB или BerkeleyDB). Дистрибутивы исходного кода MySQL поставляются в виде сжатых архивов tar с именами наподобие `mysql-VERSION.tar.gz', где VERSION представляет собой число.
  3. Добавьте пользователя и группу для запуска mysqld следующим образом:
    shell> groupadd mysql
shell> useradd -g mysql mysql
    Эти команды добавляют группу mysql и пользователя mysql. Данный синтаксис для useradd и groupadd в различных версиях Unix может иметь некоторые отличия. Приведенные выше команды могут также иметь другие названия - adduser и addgroup соответственно. Пользователю и группе можно назначить какие-нибудь иные, отличные от mysql имена.
  4. Распакуйте дистрибутив в текущем каталоге:
    shell> gunzip < /path/to/mysql-VERSION.tar.gz | tar xvf -
    Эта команда создает каталог с именем `mysql-VERSION'.
  5. Перейдите из каталога распакованного дистрибутива в каталог высшего уровня:
    shell> cd mysql-VERSION
    Учтите, что теперь необходимо конфигурировать и компоновать MySQL из этого каталога высшего уровня. Построить MySQL в другом каталоге нельзя.
  6. Сформируйте релиз и скомпилируйте весь код:
    shell> ./configure --prefix=/usr/local/mysql
shell> make
    При запуске configure вам, возможно, понадобится указать некоторые опции. Чтобы получить список опций, запустите ./configure --help. Некоторые наиболее полезные опции рассмотрены в разделе See section 2.3.3 Типичные опции configure. Если configure не работает и вы собираетесь посылать письмо с просьбой о помощи на mysql@lists.mysql.com, то просьба включить в него те строки из `config.log', которые, по вашему мнению, могут помочь решить данную проблему. Кроме того, если выполнение configure преждевременно прекращается, в письмо следует включить несколько последних строк вывода из configure. Для отсылки отчета об ошибке используйте скрипт mysqlbug (see section 1.8.1.3 Как отправлять отчеты об ошибках или проблемах). Если компиляция не выполняется, то обращайтесь к разделу See section 2.3.5 Проблемы с компиляцией?, в котором содержатся рекомендации по решению ряда часто встречающихся проблем.
  7. Установите весь код:
    shell> make install
    Возможно, необходимо запустить эту команду как root.
  8. Создайте таблицы привилегий MySQL (это необходимо только в случае, если нет ранее установленной версии MySQL ):
    shell> scripts/mysql_install_db
    Учтите, что в версиях MySQL до 3.22.10 работа сервера MySQL начиналась при запуске mysql_install_db. Сейчас это не так!
  9. Измените принадлежность бинарного кода root и принадлежность каталога данных, назначив их пользователю, под именем которого будет запускаться mysqld. Это делается следующим образом:
    shell> chown -R root /usr/local/mysql
shell> chown -R mysql /usr/local/mysql/var
shell> chgrp -R mysql /usr/local/mysql
    Первая команда изменяет атрибут owner данного файла на пользователя root, вторая - атрибут owner каталога данных на пользователя mysql, а третья - атрибут group на группу mysql.
  10. Если вы хотите установить поддержку интерфейса Perl DBI/DBD, обращайтесь к разделу See section 2.7 Замечания по установке Perl.
  11. Если вы хотели бы, чтобы работа MySQL начиналась автоматически при начальной загрузке компьютера, то можно скопировать `support-files/mysql.server' в то место, где находятся файлы запуска вашей системы. Более подробную информацию можно найти в самом скрипте `support-files/mysql.server' и в разделе See section 2.4.3 Автоматический запуск и остановка MySQL.

После завершения установки данный дистрибутив необходимо проинициализировать и протестировать:

shell> /usr/local/mysql/bin/safe_mysqld --user=mysql &

Если эта команда прекращает работу немедленно после останова демона mysqld, то некоторую информацию можно найти в файле `mysql-data-directory/'hostname'.err'. Причина, возможно, заключается в том, что уже запущен другой сервер mysqld (see section 4.1.4 Запуск нескольких серверов MySQL на одном компьютере).

Теперь приступайте к разделу See section 2.4 Послеустановочные настройка и тестирование.

2.3.2 Применение патчей

Патчи иногда присутствуют в списке рассылки или помещаются в папке патчей на веб-сайте MySQL (http://www.mysql.com/downloads/patches.html).

Для применения патча из списка рассылки сохраните сообщение, содержащее патч, в файле, поместите его в каталог высшего уровня, в котором находится дерево исходных кодов MySQL, и запустите следующие команды:

shell> patch -p1 < patch-file-name
shell> rm config.cache
shell> make clean

Патчи с FTP-сайта распространяются как файлы с простым текстом или как файлы, сжатые с помощью gzip. Патч в виде простого текста следует применять, как показано выше для патчей из списка рассылки. Чтобы применить сжатый патч, поместите его в каталог высшего уровня, в котором находится дерево исходных кодов MySQL, и запустите следующие команды:

shell> gunzip < patch-file-name.gz | patch -p1
shell> rm config.cache
shell> make clean

После применения патча следуйте инструкциям для обычной установки исходного кода, начиная с этапа ./configure. После запуска этапа make install перезапустите свой сервер MySQL.

Возможно, перед запуском make install потребуется остановить любые запущенные в это время серверы (используйте для этого mysqladmin shutdown). В некоторых системы не разрешается устанавливать новую версию какой-либо программы, если она замещает запущенную в данное время версию.

2.3.3 Типичные опции configure

Скрипт configure обеспечивает широкие возможности управления конфигурацией дистрибутива MySQL. Обычно такое управление осуществляется путем использования опций в командной строке configure. На работу configure можно также воздействовать при помощи соответствующих переменных окружения (see section E Переменные окружения). Чтобы получить список поддерживаемых configure опций, запустите следующую команду:

shell> ./configure --help

Ниже описаны некоторые из наиболее часто используемых опций configure:

  • Для компиляции только клиентских библиотек MySQL и клиентских программ (без серверной части) используйте опцию --without-server:
    shell> ./configure --without-server
    При отсутствии компилятора C++ не будет компилироваться mysql (именно для данной клиентской программы требуется C++). В этом случае можно удалить из configure код, который проверяет наличие компилятора C++, а затем запустить ./configure с опцией --without-server. На этапе компиляции и после этого будет предпринята попытка скомпилировать mysql, но любые предупреждения насчет `mysql.cc' можно игнорировать (если make остановится, попробуйте запустить make -k - чтобы компиляция остального кода продолжалась даже в случае возникновения ошибок).
  • Если необходимо получить встраиваемую библиотеку MySQL (`libmysqld.a'), используйте опцию --with-embedded-server.
  • Если вы не хотите, чтобы ваши системные журналы и каталоги баз данных располагались в каталоге `/usr/local/var', то используйте команду configure наподобие одной из приведенных ниже:
    shell> ./configure --prefix=/usr/local/mysql
shell> ./configure --prefix=/usr/local \
      --localstatedir=/usr/local/mysql/data
    Первая команда изменяет установочный префикс, в результате чего весь код будет установлен в каталоге `/usr/local/mysql' вместо принятого по умолчанию `/usr/local'. Вторая команда сохраняет принятый по умолчанию установочный префикс, но переопределяет принятое по умолчанию местоположение каталогов базы данных (обычно `/usr/local/var') и изменяет его на `/usr/local/mysql/data'. После завершения компиляции MySQL эти опции можно изменить с помощью файлов опций (see section 4.1.2 Файлы параметров `my.cnf')
  • Если вы работаете под Unix и хотите, чтобы сокет MySQL находился в каком-либо другом, отличном от принятого по умолчанию, месте (обычно по умолчанию задается каталог `/tmp' или `/var/run'), используйте команду configure, подобную следующей:
    shell> ./configure --with-unix-socket-path=/usr/local/mysql/tmp/mysql.sock
    Следует учитывать, что данный файл должен представлять собой полный путь к каталогу! Позже местоположение mysql.sock можно также изменить, используя файлы опций MySQL (see section A.4.5 Как защитить или изменить сокет-файл MySQL `/tmp/mysql.sock').
  • Если необходимо компилировать статически линкованные программы (например, чтобы создать бинарный дистрибутив, или чтобы повысить скорость, или чтобы обойти проблемы некоторых дистрибутивов RedHat 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.1 | CC=gcc CXX=gcc CXXFLAGS="-O3 -felide-constructors"
    egcs 1.0.3a | CC=gcc CXX=gcc CXXFLAGS="-O3 -felide-constructors -fno-exceptions -fno-rtti"
    gcc 2.95.2 | CFLAGS="-O3 -mpentiumpro" CXX=gcc CXXFLAGS="-O3 -mpentiumpro \ -felide-constructors -fno-exceptions -fno-rtti"
    pgcc 2.90.29 or newer | CFLAGS="-O3 -mpentiumpro -mstack-align-double" CXX=gcc \ CXXFLAGS="-O3 -mpentiumpro -mstack-align-double -felide-constructors \ -fno-exceptions -fno-rtti"
    В большинстве случаев можно получить достаточно оптимальный бинарный код MySQL путем использования опций предыдущей таблицы и добавления в командной строке следующих опций:
    --prefix=/usr/local/mysql --enable-assembler \
--with-mysqld-ldflags=-all-static
    Другими словами, полная строка конфигурации для всех последних версий gcc должна быть подобна приведенной ниже:
    CFLAGS="-O3 -mpentiumpro" CXX=gcc CXXFLAGS="-O3 -mpentiumpro \
-felide-constructors -fno-exceptions -fno-rtti" ./configure \
--prefix=/usr/local/mysql --enable-assembler \
--with-mysqld-ldflags=-all-static
    Все бинарные коды, которые мы поставляем с веб-сайта MySQL на http://www.mysql.com/, компилируются с максимальной оптимизацией и должны быть идеальными для большинства пользователей (see section 2.2.9 Бинарные коды MySQL, скомпилированные в MySQL AB). Существуют некоторые настройки, позволяющие сделать бинарный код даже еще быстрее, но их могут выполнять только опытные пользователи (see section 5.5.3 Как компиляция и линкование влияет на скорость MySQL). Если создать код не удается и при этом выдаются ошибки с указанием на компилятор или если компоновщик не в состоянии создать совместную библиотеку `libmysqlclient.so.#' (`#' представляет собой номер версии), то эту проблему можно обойти путем добавления к configure опции --disable-shared. В этом случае configure не будет создавать совместную библиотеку `libmysqlclient.so.#'.
  • Можно сконфигурировать MySQL таким образом, чтобы не использовать величины DEFAULT на столбцах не-NULL (т.е. на столбцах, которые не могут принимать значение NULL). При указании этой опции команды INSERT будут генерировать ошибку в случае, если явно не указаны величины для всех столбцов, которые не могут принимать значение NULL. Чтобы запретить использование величин по умолчанию, запустите configure, как показано ниже:
    shell> CXXFLAGS=-DDONT_USE_DEFAULT_FIELDS ./configure
  • По умолчанию в MySQL используется кодировка ISO-8859-1 (Latin1). Для изменения кодировки, принятой по умолчанию, следует применить опцию --with-charset:
    shell> ./configure --with-charset=CHARSET
    CHARSET может принимать одно из следующих значений: big5, cp1251, cp1257, czech, danish, dec8, dos, euc_kr, gb2312, gbk, german1, hebrew, hp8, hungarian, koi8_ru, koi8_ukr, latin1, latin2, sjis, swe7, tis620, ujis, usa7 или win1251ukr (see section 4.6.1 Набор символов, применяющийся для записи данных и сортировки). Если требуется преобразовывать символы между сервером и клиентом, следует рассмотреть команду SET CHARACTER SET (see section 5.5.6 Синтаксис команды SET). Предупреждение: если набор символов изменяется после создания таблиц, необходимо запустить myisamchk -r -q --set-characted-set=charset на каждой таблице. В противном случае индексы могут сортироваться неправильно (такое может случиться, если вы установите MySQL, создадите ряд таблиц, затем переконфигурируете MySQL с целью использования другого набора символов и заново установите MySQL). С помощью опции --with-extra-charsets=LIST можно определить, какие дополнительные кодировки необходимо скомпилировать в данном сервере. Здесь LIST либо представляет собой разделенный пробелами список кодировок, либо имеет значение complex для включения всех символов, которые не могут быть загружены динамически, либо имеет значение all для включения всех кодировок в бинарники.
  • Для конфигурации MySQL с кодом отладки используйте опцию --with-debug:
    shell> ./configure --with-debug
    Задание этой опции вызывает подключение надежного распределителя памяти, который может найти некоторые ошибки и обеспечить вывод информации о том, что происходит (see section D.1 Отладка сервера MySQL).
  • Если клиентские программы используют потоки, то необходимо также скомпилировать поддерживающую потоки версию клиентской библиотеки MySQL с опцией конфигурации --enable-thread-safe-client. При указании этой опции будет создана библиотека libmysqlclient_r, с которой следует линковать потоковые приложения (see section 8.4.8 Как создать клиентскую программу с потоками).
  • Опции, относящиеся к конкретным системам, можно найти в разделах данного руководства, в которых описываются особенности различных операционных систем (see section 2.6 Заметки по операционным системам).

2.3.4 Установка из экспериментального набора исходных кодов

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

Чтобы получить самый последний из разработанных наборов исходных кодов, используйте следующие инструкции:

  1. Загрузите программу BitKeeper с http://www.bitmover.com/cgi-bin/download.cgi. Для доступа к нашему хранилищу вам понадобится версия Bitkeeper 3.0 или более новая.
  2. Выполните инструкции по установке этой программы.
  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
    Чтобы клонировать ветку 4.1:
    shell> bk clone bk://mysql.bkbits.net/mysql-4.1 mysql-4.1
    В предыдущих примерах набор исходных кодов будет установлен в подкаталогах `mysql-3-23/', `mysql-4.0/' или `mysql-4.1/' вашего текущего каталога. Если вы находитесь за брендмауером, и можете только делать HTTP-запросы, вы можете также использовать BitKeeper по HTTP. Если вы используете прокси-сервер, просто установите переменную окружения http_proxy:
    shell> export http_proxy="http://your.proxy.server:8080/"
    И теперь просто замените bk:// на http:// когда будете делать клонирование. Например:
    shell> bk clone http://mysql.bkbits.net/mysql-4.1 mysql-4.1
    Первоначальная загрузка набора исходных кодов может потребовать времени в зависимости от скорости вашего соединения; будьте терпеливы.
  4. Чтобы запустить следующий набор команд, вам понадобятся программы GNU make, autoconf 2.53 (или новее), automake 1.5, libtool 1.4 и m4. Программа automake 1.7 (или новее) еще не работает. Если вы хотите настроить MySQL 4.1, вам также потребуется bison 1.75. Более старые версии bison могут давать такую ошибку: sql_yacc.yy:#####: fatal error: maximum table size (32767) exceeded. На самом деле максимальный размер таблиц не превышается, как утверждает это сообщение, но просто-напросто такое сообщение есть следствие ошибки в более ранних версиях bison. Типичные команды к выполнению в оболочке:
    cd mysql-4.0
bk -r get -Sq
aclocal; autoheader; autoconf; automake
(cd innobase ; aclocal; autoheader; autoconf; automake) # для InnoDB
(cd bdb/dist ; sh s_all ) # для Berkeley DB
./configure  # Ваши любимые опции здесь
make
    Если вы получаете некие странные сообщения на этом этапе - удостоверьтесь, что у вас действительно стоит libtool! Собрание наших стандартных конфигурационных скриптов находится в подкаталоге `BUILD/'. Если вы предпочитаете наиболее легкий путь, можно использовать скрипт `BUILD/compile-pentium-debug'. При компилировании с использованием другой архитектуры модифицируйте этот скрипт путем удаления флагов, относящихся к Pentium.
  5. После выполнения компиляции запустите make install. Следует проявлять осторожность при работе на машине, находящейся в эксплуатации; данная команда может выполнить установку поверх вашей существующей установленной версии. Если у вас уже установлена иная версия MySQL, мы рекомендуем запускать ./configure со значениями для опций prefix, with-tcp-port и unix-socket-path, отличными от тех, что были использованы для сервера, находящегося в эксплуатации.
  6. Усиленно нагружая свою новую инсталляцию, попытайтесь добиться отказа новых возможностей. Начинайте с запуска make test (see section 9.1.2 Пакет тестирования MySQL).
  7. Если вам удастся дойти до этапа make и дистрибутив не будет компилироваться, просьба сообщить нам об этом по адресу bugs@lists.mysql.com. Просьба информировать нас и в том случае, если вы установили последнюю версию требуемых инструментальных средств GNU и они терпят крах при попытке обработать наш конфигурационный файл. Однако если при выполнении aclocal вы получите ошибку command not found или возникнет аналогичная проблема, об этом сообщать не надо. В таком случае следует убедиться, что у вас установлены все необходимые инструментальные программы и что ваша переменная PATH указана правильно, чтобы оболочка могла найти их.
  8. Для того чтобы получить набор исходных кодов после начальной операции bk clone, необходимо периодически запускать bk pull для получения обновлений.
  9. Вы можете изучить историю изменений дерева исходных кодов, чтобы увидеть все отличия в них - для этого следует использовать bk sccstool. При обнаружении каких-либо отличий, которые покажутся вам странными, или кода, по которому возникают вопросы, не раздумывайте - посылайте письмо на internals@lists.mysql.com. Кроме того, если вы считаете, что у вас есть лучшие идеи по разработке, отправьте по тому же адресу сообщение со своим патчем. bk diffs создает патч после внесения изменений в исходный код. Если у вас нет времени написать код, реализующий вашу идею, просто пришлите ее описание.
  10. BitKeeper имеет хорошую вспомогательную программу, которая доступна посредством bk helptool.
  11. Внимание: любой commit (bk ci или bk citool) инициирует постинг сообщения с изменениями в наш внутренний список рассылки (internals). В общем случае, вам не нужно использовать commit (поскольку публично-доступное дерево не допустит bk push), но скорее, метод bk diffs, описанный ранее.

Вы также можете просматривать изменения, комментарии и исходный код в онлайн, например, по адресу http://mysql.bkbits.net:8080/mysql-4.1 для MySQL 4.1.

Руководство находится в отдельном дереве, которое можно клонировать так:

shell> bk clone bk://mysql.bkbits.net/mysqldoc mysqldoc

2.3.5 Проблемы с компиляцией?

На Solaris или Linux с использованием компилятора gcc все программы MySQL у нас компилируются чисто и без каких-либо предупреждений. В других системах могут возникать предупреждения из-за различий включаемых системных файлов (по поводу предупреждений, которые могут возникать при использовании потоков MIT-pthreads, обращайтесь к разделу see section 2.3.6 Замечания по потокам MIT-pthreads). Относительно других проблем сверьтесь с приведенным ниже списком.

Решение многих проблем предполагает выполнение переконфигурирования. В случаях, когда переконфигурирование действительно необходимо, следует учитывать следующее:

  • Если configure запускается после того, как эта команда уже запускалась, то можно использовать информацию, которая была собрана во время предыдущего вызова команды (такая информация хранится в `config.cache'). При запуске configure ищет данный файл и, если он существует, читает его содержимое, исходя из предположения, что данная информация все еще правильна. При выполнении переконфигурации это предположение является некорректным.
  • Каждый раз при запуске configure необходимо опять запускать make для перекомпилирования. Однако, возможно, вначале вам потребуется удалить старые объектные файлы из предыдущих компоновок, поскольку они были скомпилированы с использованием других опций конфигурации. Чтобы не допустить использования старой конфигурационной информации или объектных файлов, перед перезапуском configure запустите следующие команды:
    shell> rm config.cache
shell> make clean
    В качестве альтернативного варианта можно использовать команду make distclean. В следующем списке представлены некоторые проблемы компилирования MySQL, которые, как оказалось, возникают наиболее часто:
  • Если при компиляции `sql_yacc.cc' вы получаете ошибки, подобные представленным ниже, то, возможно, произошел выход за пределы памяти или пространства подкачки (свопинга):
    Internal compiler error: program cc1plus got fatal signal 11
или
Out of virtual memory
или
Virtual memory exhausted
    Проблема заключается в том, что для компиляции `sql_yacc.cc' со встраиваемыми функциями компилятору gcc требуется значительное количество памяти. Попробуйте произвести запуск configure с опцией --with-low-memory:
    shell> ./configure --with-low-memory
    Данная опция вызывает добавление -fno-inline к компилируемой строке для gcc и -O0 - при использовании какого-либо другого компилятора. Даже если у вас столько памяти и пространства для свопинга, что, по вашему мнению, невозможно выйти за их пределы, все же стоит попытаться использовать опцию with-low-memory. Эта проблема, по нашим наблюдениям, возникала даже на системах с аппаратными реализациями, обладающими широкими возможностями; обычно она устраняется с помощью опции --with-low-memory.
  • По умолчанию configure выбирает c++ как имя компилятора и GNU c++ линкуется с -lg++. При использовании gcc этот режим работы может вызывать такие проблемы в процессе конфигурации, как:
    configure: error: installation or configuration problem:
C++ compiler cannot create executables.
    Во время компиляции могут также возникать проблемы, относящиеся к g++, libg++ или libstdc++. Одна из причин их возникновения заключается в том, что, возможно, у вас нет g++ или есть g++, но нет библиотеки libg++ или libstdc++. Следует изучить файл `config.log' - по нему вы должны точно определить причину, по которой не работал компилятор c++ ! Чтобы обойти эти проблемы, можно в качестве компилятора C++ использовать gcc. Попробуйте установить переменную окружения CXX в gcc -O3. Например:
    shell> CXX="gcc -O3" ./configure
    Эта команда работает, поскольку gcc компилирует исходные коды C++ так же хорошо, как и g++, но по умолчанию не линкует libg++ или libstdc++. Есть, конечно, и другая возможность устранения этих проблем, которая заключается в установке g++, libg++ и libstdc++. Однако мы не рекомендовали бы использовать libg++ или libstdc++ с MySQL, поскольку это только увеличит размер бинарного кода mysqld без предоставления каких-либо преимуществ. Некоторые версии этих библиотек в прошлом также вызывали непонятные проблемы у пользователей MySQL.
  • Если процесс компиляции завершается аварийно и выводятся такие ошибки, как приведены ниже, то вам следует сделать апгрейд своей версии make до GNU 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
    Операционные системы Solaris и FreeBSD, как известно, имеют ненадежные программы make. Известно также, что версия GNU make 3.75 работает.
  • Если вы хотите определить флаги для использования их компиляторами C или C++, следует добавить флаги к переменным окружения CFLAGS и CXXFLAGS. Точно так же можно также указать имена компиляторов, используя CC и CXX. Например:
    shell> CC=gcc
shell> CFLAGS=-O3
shell> CXX=gcc
shell> CXXFLAGS=-O3
shell> export CC CFLAGS CXX CXXFLAGS
    В разделе section 2.2.9 Бинарные коды MySQL, скомпилированные в MySQL AB приведен список полезных для различных систем определений флагов.
  • При получении сообщения об ошибке, подобного приведенному ниже, необходимо модернизировать ваш компилятор gcc:
    client/libmysql.c:273: parse error before `__attribute__'
    Компилятор gcc 2.8.1 известен как работающий, но мы рекомендуем вместо него использовать gcc 2.95.2 или egcs 1.0.3a.
  • Если при компиляции mysqld вы получаете ошибки, подобные приведенным ниже, то это означает, что команда configure некорректно определила тип последнего аргумента в функциях accept(), getsockname() или getpeername():
    cxx: Error: mysqld.cc, line 645: In this statement, the referenced
type of the pointer value "&length" is "unsigned long", which
is not compatible with "int".
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 на size_t или int - в зависимости от своей операционной системы (учтите, что эти действия необходимо будет повторять каждый раз при запуске configure, поскольку configure восстанавливает файл `config.h').
  • Файл `sql_yacc.cc' генерируется из `sql_yacc.yy'. Обычно в процессе сборки не требуется создавать `sql_yacc.cc', поскольку MySQL поставляется с уже сгенерированной копией. Однако если действительно необходимо создать этот файл заново, то можно столкнуться со следующей ошибкой:
    "sql_yacc.yy", line xxx fatal: default action causes potential...
    Это признак того, что ваша версия yacc является неполной. Возможно, следует установить bison (GNU-версия yacc) и использовать вместо yacc.
  • При необходимости отладки mysqld или клиента MySQL запустите configure с опцией --with-debug, затем перекомпилируйте и слинкуйте эти программы с новой клиентской библиотекой (see section D.2 Отладка клиента MySQL).

2.3.6 Замечания по потокам MIT-pthreads

В этом разделе описываются некоторые аспекты использования потоков MIT-pthreads.

Следует иметь в виду, что под Linux использовать потоки MIT-pthreads нельзя, для этого необходимо установить LinuxThreads! See section 2.6.1 Примечания к Linux (Все версии Linux).

Если ваша система сама по себе не обеспечивает поддержку потоков, то необходимо скомпоновать MySQL, используя пакет поддержки MIT-pthreads. К таким системам относятся старые системы FreeBSD, SunOS 4.x, Solaris 2.4 и более ранние, а также некоторые другие (see section 2.2.5 Операционные системы, поддерживаемые MySQL).

Заметьте, с версии MySQL 4.0.2 потоки MIT более не присутствуют в поставке исходных текстов. Если вам действительно нужен этот пакет, вы можете его забрать с http://www.mysql.com/Downloads/Contrib/pthreads-1_60_beta6-mysql.tar.gz

После загрузки, распакуйте этот архив в каталог исходных текстов MySQL. Создастся новый каталог mit-pthreads.

  • Для большинства систем можно обеспечить использование потоков MIT-pthreads при помощи запуска configure с опцией --with-mit-threads:
    shell> ./configure --with-mit-threads
    При использовании потоков MIT-pthreads не поддерживается возможность сборки MySQL в каталоге, не содержащем исходный код, поскольку мы хотим минимизировать наши изменения в данном коде.
  • Проверки, определяющие, используются ли потоки MIT-pthreads, производятся только во время этапа конфигурационного процесса, относящегося к серверному коду. Если дистрибутив сконфигурирован с использованием --without-server для сборки только клиентского кода, то клиенты не будут знать, применяются ли потоки MIT-pthreads, и будут использовать подключения через сокеты Unix по умолчанию. Поскольку сокеты Unix не работают с потоками MIT-pthreads на некоторых платформах, то при запуске клиентских программ следует использовать -h или --host.
  • При компиляции MySQL с использованием потоков MIT-pthreads блокирование системы отключено по умолчанию из соображений производительности. Можно предписать серверу использовать системную блокировку с помощью опции --use-external-locking. Это только необходимо если вы собираетесь использовать два MySQL-сервера на одних и тех же файлах данных (не рекомендуется!).
  • Иногда потоковой команде bind() не удается подсоединить сокет без какого-либо сообщения об ошибке (по крайней мере, под Solaris). В результате все подключения к серверу обрываются. Например:
    shell> mysqladmin version
mysqladmin: connect to server at '' failed;
error: 'Can't connect to mysql server on localhost (146)'
    Для решения этой проблемы следует завершить выполнение сервера mysqld и перезапустить его. У нас это происходило только в тех случаях, когда мы прерывали работу сервера и сразу же снова его запускали.
  • При использовании потоков MIT-pthreads системный вызов функции sleep() не прерывается с помощью SIGINT (break). Это заметно только в том случае, если запускать mysqladmin --sleep. Следует ждать окончания работы sleep(), прежде чем прерывание будет обслужено и процесс завершит работу.
  • При линковании можно получить предупреждающие сообщения, подобные приведенным ниже (по крайней мере под Solaris); их можно игнорировать:
    ld: warning: symbol `_iob' has differing sizes:
    (file /my/local/pthreads/lib/libpthread.a(findfp.o) value=0x4;
file /usr/lib/libc.so value=0x140);
    /my/local/pthreads/lib/libpthread.a(findfp.o) definition taken
ld: warning: symbol `__iob' has differing sizes:
    (file /my/local/pthreads/lib/libpthread.a(findfp.o) value=0x4;
file /usr/lib/libc.so value=0x140);
    /my/local/pthreads/lib/libpthread.a(findfp.o) definition taken
  • Некоторые другие предупреждения также можно игнорировать:
    implicit declaration of function `int strtoll(...)'
implicit declaration of function `int strtoul(...)'
  • Нам не удалось добиться совместной работы readline с потоками MIT-pthreads (это не является необходимым, но для кого-то может представлять интерес).

2.3.7 Дистрибутив исходного кода для Windows

Вам потребуются следующие средства:

  • Компилятор VC++ 6.0 (усовершенствованный с помощью служебных пакетов 4 SP или 5 SP и пакета предварительной обработки) Пакет предварительной обработки необходим для макроассемблера. Более подробная информация находится на: http://msdn.microsoft.com/vstudio/sp/vs6sp5/faq.asp.
  • Дистрибутив исходного кода MySQL для Windows, который может быть загружен с http://www.mysql.com/downloads/.

Сборка MySQL

  1. Создайте рабочий каталог (т.е. workdir).
  2. Распакуйте дистрибутив исходного кода в вышеупомянутом каталоге.
  3. Запустите компилятор VC++ 6.0.
  4. В меню File выберите Open Workspace.
  5. Откройте рабочую область mysql.dsw, находящуюся в рабочем каталоге.
  6. В меню Build выберите подменю Set Active Configuration.
  7. Выберите в появившемся окне mysqld - Win32 Debug и нажмите OK.
  8. Нажмите клавишу F7, чтобы начать процесс построения отладочных версий сервера, библиотек и некоторых клиентских приложений.
  9. По окончании компиляции скопируйте библиотеки и исполняемые файлы в отдельный каталог.
  10. Тем же способом скомпилируйте рабочие версии (релизы), которые вам нужны.
  11. Создайте каталог для всего, что нужно MySQL, т.е. `c:\mysql'
  12. Из каталога workdir скопируйте в каталог `c:\mysql' следующие подкаталоги:
    • Data (данные)
    • Docs (документация)
    • Share (совместно используемые ресурсы)
  13. Создайте каталог `c:\mysql\bin' и скопируйте в него все скомпилированные перед этим серверы и клиенты.
  14. При желании можете также создать каталог `lib' и скопировать в него скомпилированные ранее библиотеки.
  15. Произведите очистку, используя Visual Studio. Установите и запустите сервер тем же способом, что и для бинарного дистрибутива для Windows (see section 2.1.2.2 Подготовка конфигурации MySQL для Windows).

2.4 Послеустановочные настройка и тестирование

После установки MySQL (из бинарного дистрибутива или исходного кода) необходимо проинициализировать таблицы привилегий, запустить сервер и убедиться, что сервер работает нормально. Можно также организовать автоматический запуск и остановку сервера, когда операционная система соответственно начинает и прекращает работу.

Обычно при установке из исходного кода для установки таблиц привилегий и запуска сервера нужно выполнить следующие команды:

shell> ./scripts/mysql_install_db
shell> cd mysql_installation_directory
shell> ./bin/safe_mysqld --user=mysql &

Для бинарного дистрибутива (но не для пакетов RPM или pkg) сделайте так:

shell> cd mysql_installation_directory
shell> ./scripts/mysql_install_db
shell> ./bin/safe_mysqld --user=mysql &

или

shell> ./bin/mysqld_safe --user=mysql &

Если вы используете MySQL 4.x.

Эти операции создают базу данных mysql, которая будет поддерживать все привилегии доступа к базе данных, базу данных test, которую можно использовать для тестирования MySQL, а также записи привилегий для пользователя, который запускает mysql_install_db и для пользователя root (без каких-либо паролей). При этом также запускается сервер mysqld.

mysql_install_db не перезаписывает старые таблицы привилегий, так что ее запуск будет безопасным в любом случае. Если вам не нужна база данных test, ее можно удалить с помощью mysqladmin -u root drop test.

Тестирование проще всего выполнить из каталога наивысшего уровня дистрибутива MySQL. Для бинарного дистрибутива таковым является ваш каталог инсталляции (обычно что-нибудь вроде `/usr/local/mysql'). Для дистрибутива в виде исходного кода это - главный каталог вашего набора исходных кодов MySQL.

В командах, представленных в настоящем разделе и последующих подразделах, BINDIR представляет собой путь к тому местоположению, где устанавливаются программы вроде mysqladmin и safe_mysqld. Для бинарного дистрибутива это каталог `bin' внутри дистрибутива. Для дистрибутива в виде исходного кода BINDIR может представлять собой `/usr/local/bin', если при запуске configure не указан иной, чем `/usr/local' инсталляционный каталог. EXECDIR - место, где устанавливается сервер mysqld. Для бинарного дистрибутива это то же самое, что и BINDIR. Для дистрибутива в виде исходного кода EXECDIR может представлять собой `/usr/local/libexec'.

Подробное описание тестирования:

  1. Если необходимо, запустите сервер mysqld и установите исходные таблицы привилегий MySQL, содержащие те привилегии, которые определяют, каким способом пользователям разрешено подключаться к серверу. Обычно это делается с помощью скрипта mysql_install_db:
    shell> scripts/mysql_install_db
    Как правило, mysql_install_db требует запуска только первый раз при установке MySQL. Таким образом, если производится модернизация существующей установки, то данный этап можно пропустить (однако скрипт mysql_install_db совершенно безопасен для использования и не обновляет никаких уже существующих таблицы; поэтому если у вас нет уверенности в том, как поступать, то всегда можно запустить mysql_install_db). Скрипт mysql_install_db создает шесть таблиц (user, db, host, tables_priv, columns_priv, and func) в базе данных mysql. Описание исходных привилегий дается в разделе See section 4.3.4 Задание изначальных привилегий MySQL. Если в двух словах, то эти привилегии позволяют пользователю root MySQL делать все, что угодно, и любому пользователю позволяют создавать или использовать базы данных с именем test или начинающимся с test_. Если таблицы привилегий не установлены, то в системном журнале при запуске сервера появится следующая ошибка:
    mysqld: Can't find file: 'host.frm'
    Такая ошибка может появиться и в случае бинарного дистрибутива MySQL, если вы не начали работу MySQL с точного выполнения команды `./bin/safe_mysqld'! See section 4.7.2 safe_mysqld, оболочка mysqld. Возможно, вам потребуется запускать mysql_install_db как root. Однако при желании вы можете запускать сервер MySQL как непривилегированный (не-root) пользователь, при условии, что этот пользователь может только читать файлы из каталога базы данных и записывать в него файлы. Инструкции по запуску MySQL в качестве непривилегированного пользователя даются в разделе See section A.3.2 Запуск MySQL от обычного пользователя. Если возникнут проблемы с mysql_install_db, обращайтесь к разделу See section 2.4.1 Проблемы при запуске mysql_install_db. Дистрибутив MySQL обеспечивает несколько вариантов запуска скрипта mysql_install_db:
    • Чтобы изменить исходные привилегии, которые устанавливаются в таблицах привилегий, вам, возможно, потребуется отредактировать mysql_install_db перед запуском. Это полезно, если нужно установить MySQL на нескольких машинах с одними и теми же привилегиями. В таком случае вам, возможно, потребуется только добавить несколько дополнительных команд INSERT к таблицам mysql.user и mysql.db!
    • Если необходимо изменить записи в таблицах привилегий после их установки, то можно запустить mysql_install_db, затем использовать mysql -u root mysql для доступа к таблицам привилегий как пользователь MySQL с привилегиями root и применять команды SQL для модификации таблиц привилегий напрямую.
    • Можно также создать таблицы привилегий полностью заново после того, как они были уже созданы. Это можно сделать после установки таблиц, а затем воссоздать после редактирования mysql_install_db.
    Более подробная информация о приведенных выше альтернативах находится в разделе See section 4.3.4 Задание изначальных привилегий MySQL.
  2. Запустите сервер MySQL как показано ниже:
    shell> cd mysql_installation_directory
shell> bin/safe_mysqld &
    Если возникнут проблемы с запуском сервера, See section 2.4.2 Проблемы при запуске сервера MySQL.
  3. Используйте mysqladmin для проверки, что сервер работает. Простую проверку того, что сервер функционирует и отвечает на подключения, обеспечивают следующие команды:
    shell> BINDIR/mysqladmin version
shell> BINDIR/mysqladmin variables
    Вывод из mysqladmin version будет иметь небольшие различия в зависимости от используемой платформы и версии MySQL, но должен быть похож на приведенный ниже:
    shell> BINDIR/mysqladmin version
mysqladmin  Ver 8.14 Distrib 3.23.32, 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          3.23.32-debug
Protocol version        10
Connection              Localhost via Unix socket
TCP port                3306
UNIX socket             /tmp/mysql.sock
Uptime:                 16 sec

Threads: 1  Questions: 9  Slow queries: 0
Opens: 7  Flush tables: 2  Open tables: 0
Queries per second avg: 0.000
Memory in use: 132K  Max memory used: 16773K
    Чтобы получить представление о том, что еще можно делать с помощью BINDIR/mysqladmin, запустите эту команду с опцией --help.
  4. Убедитесь, что можете остановить сервер:
    shell> BINDIR/mysqladmin -u root shutdown
  5. Убедитесь, что можете перезапустить сервер. Делайте это, используя safe_mysqld или путем прямого вызова mysqld. Например:
    shell> BINDIR/safe_mysqld --log &
    Если safe_mysqld терпит неудачу, попытайтесь запустить команду из каталога установки MySQL (если вы уже не там). Если команда по-прежнему не работает, см. раздел See section 2.4.2 Проблемы при запуске сервера MySQL.
  6. Запустите несколько простых тестов, чтобы убедиться, что сервер работает. Вывод должен быть похож на приведенный ниже:
    shell> BINDIR/mysqlshow
+-----------+
| Databases |
+-----------+
| mysql     |
+-----------+

shell> BINDIR/mysqlshow mysql
Database: mysql
+--------------+
|    Tables    |
+--------------+
| columns_priv |
| db           |
| func         |
| host         |
| tables_priv  |
| user         |
+--------------+

shell> BINDIR/mysql -e "SELECT host,db,user FROM db" mysql
+------+--------+------+
| host | db     | user |
+------+--------+------+
| %    | test   |      |
| %    | test_% |      |
+------+--------+------+
    В подкаталоге `sql-bench' каталога установки MySQL находится набор тестов производительности, который можно использовать для сравнения работы MySQL на различных платформах. Каталог `sql-bench/Results' содержит результаты большого количества запусков для различных баз данных и платформ. Чтобы запустить все тесты, выполните следующие команды:
    shell> cd sql-bench
shell> run-all-tests
    Если у вас отсутствует каталог `sql-bench', то, вероятно, вы работаете с пакетом RPM для бинарного дистрибутива (в пакеты RPM с дистрибутивами исходного кода включается каталог тестов производительности). В этом случае прежде чем использовать набор тестов производительности, необходимо его установить. Начиная с версии MySQL 3.22, существуют RPM-файлы тестов производительности, `mysql-bench-VERSION-i386.rpm', которые содержат код тестов производительности и данные. Имея дистрибутив исходного кода, можно также запустить эти тесты в подкаталоге `tests'. Например, чтобы запустить `auto_increment.tst', сделайте следующее:
    shell> BINDIR/mysql -vvf test < ./tests/auto_increment.tst
    Результаты будут выводиться в файл `./tests/auto_increment.res'.

2.4.1 Проблемы при запуске mysql_install_db

Скрипт mysql_install_db предназначен только для создания новых таблиц привилегий MySQL. Он не влияет ни на какие другие данные! А если таблицы привилегий MySQL уже установлены, этот скрипт ничего не будет делать!

Для того чтобы создать таблицы привилегий заново, необходимо остановить сервер mysqld, если он работает, и затем выполнить что-нибудь вроде:

mv mysql-data-directory/mysql mysql-data-directory/mysql-old
mysql_install_db

В этом разделе перечислены проблемы, с которыми можно столкнуться при запуске mysql_install_db:

mysql_install_db не устанавливает таблицы привилегий
Может оказаться, что mysql_install_db не в состоянии установить таблицы привилегий и заканчивает свою работу после вывода следующих сообщений:
starting mysqld daemon with databases from XXXXXX
mysql daemon ended
В таком случае необходимо очень тщательно изучить системный журнал! Этот журнал должен находиться в каталоге `XXXXXX', указанном в данном сообщении об ошибке. В нем содержится информация о том, почему не запустился mysqld. Если вам не удалось разобраться в том, что произошло, при посылке отчета об ошибке включите в него данный журнал, используя mysqlbug! См.раздел See section 1.8.1.3 Как отправлять отчеты об ошибках или проблемах.
Уже существует работающий демон mysqld
В таком случае вам вообще не следует запускать mysql_install_db. Скрипт mysql_install_db должен запускаться только однажды при установке MySQL первый раз.
При работающем демоне mysqld установка второго демона не работает
Это может случиться, когда уже существует установленный сервер MySQL, но вы хотите произвести новую инсталляцию в другом месте (например, для тестирования или, возможно, вам просто требуется запустить две инсталляции в одно и то же время). Вообще говоря, такая проблема, которая возникает при попытке запустить второй сервер, заключается в том, что второй сервер пытается использовать тот же сокет и порт, что и старый. В этом случае вы можете получить следующее сообщение об ошибке: Can't start server: Bind on TCP/IP port: Address already in use или Can't start server: Bind on unix socket.... See section 4.1.3 Установка нескольких серверов на один компьютер.
Нет доступа для записи в `/tmp'
Если у вас нет доступа для создания файла сокета в принятом по умолчанию месте (в `/tmp') или разрешения создавать временные файлы в каталоге `/tmp', то вы получите ошибку при запуске mysql_install_db или при запуске или использовании mysqld. Необходимо указать другой каталог для сокета и временных файлов следующим образом:
shell> TMPDIR=/some_tmp_dir/
shell> MYSQL_UNIX_PORT=/some_tmp_dir/mysqld.sock
shell> export TMPDIR MYSQL_UNIX_PORT
See section A.4.5 Как защитить или изменить сокет-файл MySQL `/tmp/mysql.sock'. Путь `some_tmp_dir' должен указывать на некоторый каталог, для которого у вас есть доступ для записи. See section E Переменные окружения. После этого у вас должна появиться возможность запустить mysql_install_db и начать работу сервера с помощью следующих команд:
shell> scripts/mysql_install_db
shell> BINDIR/safe_mysqld &
Немедленный аварийный отказ mysqld
Если вы работаете на версии RedHat 5.0 с версией glibc более старой, чем 2.0.7-5, следует позаботиться о том, чтобы установить все патчи для glibc! В архивах рассылки MySQL имеется большое количество писем об этом. Ссылки на архивы писем доступны в онлайновом режиме на http://lists.mysql.com/. Обращайтесь также к разделу See section 2.6.1 Примечания к Linux (Все версии Linux). Можно также запустить mysqld вручную, используя опцию --skip-grant-tables, и самостоятельно добавить информацию о привилегиях, при помощи mysql:
shell> BINDIR/safe_mysqld --skip-grant-tables &
shell> BINDIR/mysql -u root mysql
Из mysql в ручном режиме выполните команды SQL в mysql_install_db. Удостоверьтесь, что после этого вы запустили mysqladmin flush-privileges или mysqladmin reload, чтобы сервер перегрузил таблицы привилегий.

2.4.2 Проблемы при запуске сервера MySQL

Если вы собираетесь использовать таблицы, поддерживающие транзакции (InnoDB, BDB), следует прежде всего создать файл `my.cnf' и установить опции запуска для тех типов таблиц, с которыми планируется работать. See section 7 Типы таблиц MySQL.

В общем случае сервер mysqld запускается одним из следующих способов:

  • Вызовом mysql.server. Этот скрипт используется преимущественно для запуска и останова системы. Более подробно он описан в разделе See section 2.4.3 Автоматический запуск и остановка MySQL.
  • Вызовом команды safe_mysqld, которая определяет соответствующие опции для mysqld и затем запускает mysqld с этими опциями. See section 4.7.2 safe_mysqld, оболочка mysqld.
  • Относительно Windows NT/2000/XP просьба обращаться к разделу See section 2.6.2.2 Запуск MySQL на Windows NT, 2000 или XP.
  • Вызовом mysqld напрямую.

При своем запуске демон mysqld изменяет свой каталог на каталог данных (datadir). В нем он ожидает найти журнальные файлы, файлы pid (ID процессов) и собственно базы данных.

Местоположение каталога данных жестко устанавливается при компиляции дистрибутива. Однако если mysqld ожидает найти каталог данных где-либо в другом месте, а не там, где он действительно расположен в вашей системе, то демон mysqld не будет работать правильно. Если есть проблемы с неправильными путями, то, вызывая mysqld с опцией --help, вы можете найти информацию о том, что разрешают опции mysqld и какие установки путей приняты по умолчанию. Можно переопределить установки по умолчанию указанием правильных имен путей как аргументов mysqld в командной строке (эти опции также можно использовать с safe_mysqld).

Обычно требуется указывать mysqld только каталог, в котором устанавливается MySQL. Это можно сделать с помощью опции --basedir. Можно также использовать --help для проверки эффекта от изменения опций путей (учтите, что --help должна быть последней опцией в команде mysqld). Например:

shell> EXECDIR/mysqld --basedir=/usr/local --help

После определения требуемых установок путей запускайте сервер без опции --help.

Какой бы метод вы ни использовали для запуска сервера, если его неудачный запуск завершается корректно, то проверьте журнальный файл, чтобы узнать, почему запуск происходит неудачно. Журнальные файлы находятся в каталоге данных (обычно `/usr/local/mysql/data' для бинарного дистрибутива, `/usr/local/var' для дистрибутива исходного кода и `\mysql\data\mysql.err' под Windows). В каталоге данных следует искать файлы с именами в виде `host_name.err' и `host_name.log', где host_name - имя вашего серверного хоста. Затем проверьте последние несколько строк этих файлов:

shell> tail host_name.err
shell> tail host_name.log

В журнальном файле нужно искать что-нибудь похожее на следующее:

000729 14:50:10 bdb: Recovery function for LSN 1 27595 failed
000729 14:50:10 bdb: warning: ./test/t1.db: No such file or directory
000729 14:50:10 Can't init databases

Это означает, что вы не запустили mysqld с --bdb-no-recover и база данных Berkeley DB нашла что-то ошибочное в своих журнальных файлах при попытке восстановить ваши базы данных. Чтобы иметь возможность продолжить, необходимо переместить старый журнальный файл Berkeley DB из каталога баз данных в некоторое другое место, где позже можно будет изучить его. Журнальные файлы имеют имена `log.0000000001' и т.д.; номер возрастает при каждом запуске.

Если вы запускаете mysqld работает с поддержкой таблиц BDB и mysqld при старте выводит дамп оперативной памяти (coredump), то причиной этого это могут быть какие-либо проблемы с журналом восстановления BDB. В этом случае можно попробовать запуск mysqld с --bdb-no-recover. Если это помогает, то следует удалить все файлы `log.*' из каталога данных и попробовать запустить mysqld опять.

Если выдается приведенная ниже ошибка, то это означает, что некоторая другая программа (или другой сервер mysqld) уже использует данный TCP/IP порт или сокет, на которых mysqld пытается слушать:

Can't start server: Bind on TCP/IP port: Address already in use
или
Can't start server : Bind on unix socket...

Чтобы убедиться, что другого работающего сервера mysqld нет, используйте ps. Если другой работающий сервер не найден, то можно попробовать выполнить команду telnet your-host-name tcp-ip-port-number и нажать пару раз клавишу ``Enter''. Если вы не получаете сообщения об ошибке вроде следующего telnet: Unable to connect to remote host: Connection refused, значит, что порт TCP/IP порт, который mysqld пытается использовать, уже занят другой программой. section 2.4.1 Проблемы при запуске mysql_install_db и раздел See section 4.1.4 Запуск нескольких серверов MySQL на одном компьютере.

Если mysqld в настоящее время работает, то можно найти используемые им установки путей при помощи следующей команды:

shell> mysqladmin variables
или
shell> mysqladmin -h 'your-host-name' variables

Если при запуске mysqld вы получили ошибку Errcode 13, что значит Permission denied, это означает, что у вас не было прав читать/создавать файлы в базе данных MySQL или в журнальном каталоге. В таком случае вам следует либо запускать mysqld как пользователь root, либо изменить права доступа к упомянутым файлам и каталогам, чтобы иметь права использовать их.

Если safe_mysqld запускает сервер, но вы не можете подключиться к нему, то следует убедиться, что в `/etc/hosts' есть запись, которая выглядит примерно так:

127.0.0.1 localhost

Эта проблема возникает только в системах, не имеющих рабочей библиотеки потоков, и для которых MySQL следует конфигурировать для использования потоков MIT-pthreads.

Если вы не можете запустить mysqld, то можно попробовать создать трассировочный файл, чтобы обнаружить данную проблему. See section D.1.2 Создание трассировочных файлов.

При использовании таблиц InnoDB следует указывать опции запуска, специфические для InnoDB. See section 7.5.2 Параметры запуска InnoDB.

При использовании таблиц BDB (Berkeley DB) необходимо хорошо знать различные специфические для BDB опции запуска. See section 7.6.3 Параметры запуска BDB.

2.4.3 Автоматический запуск и остановка MySQL

Скрипты mysql.server и safe_mysqld могут применяться для автоматического запуска сервера во время загрузки операционной системы. Скрипт mysql.server можно также использовать для остановки сервера.

Чтобы применять скрипт mysql.server для запуска или остановки сервера, его следует вызывать с аргументами start или stop соответственно:

shell> mysql.server start
shell> mysql.server stop

mysql.server можно найти в подкаталоге `share/mysql' инсталляционного каталога MySQL или в каталоге `support-files' набора исходных кодов MySQL.

Перед тем как скрипт mysql.server запустит сервер, он изменяет данный каталог на инсталляционный каталог MySQL, затем вызывает safe_mysqld. Возможно, понадобится отредактировать скрипт mysql.server, если бинарный дистрибутив установлен вами не в стандартном месте. Модифицируйте его, указав cd в соответствующий каталог перед тем, как он запустит safe_mysqld. Если вы хотите запустить сервер от определенного пользователя, то добавьте соответствующую строку user к файлу `/etc/my.cnf' как показано далее в этом разделе.

mysql.server stop останавливает сервер путем посылки ему сигнала. Можно остановить сервер вручную - при помощи команды mysqladmin shutdown.

Вам следует добавить эти команды запуска и остановки в соответствующее место в файлах `/etc/rc*', если вы хотите автоматически запускать MySQL на вашем сервере.

На современных поставках Linux, достаточно скопировать файл mysql.server в каталог `/etc/init.d' (или `/etc/rc.d/init.d' на более старших системах Red Hat). После этого, выполните такую команду, чтобы включить автоматический запуск MySQL при загрузке системы:

shell> chkconfig --add mysql.server

В качестве альтернативы, в некоторых ОС также используются `/etc/rc.local' или `/etc/init.d/boot.local' для запуска дополнительных сервисов при загрузке. Для того, чтобы MySQL стартовал с использованием этого метода, вы можете добавить нечто вроде этого к указанным файлам:

/bin/sh -c 'cd /usr/local/mysql ; ./bin/safe_mysqld --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 понимает следующие опции: datadir, basedir и pid-file.

В таблице представлены группы опций, которые каждый из перечисленных запускающих скриптов читает из файлов опций:

Скрипт | Группы опций
mysqld | mysqld и server
mysql.server | mysql.server, mysqld, и server
safe_mysqld | mysql.server, mysqld, и server

See section 4.1.2 Файлы параметров `my.cnf'.

2.5 Апгрейд/даунгрейд MySQL

Файлы MySQL, содержащие структуру и данные, всегда можно перемещать между различными версиями одной и той же архитектуры, если используется одна и та же базовая версия MySQL. В настоящее время базовой является версия с номером 3. При изменении кодировки во время работы MySQL (при этом также может измениться порядок сортировки) необходимо запустить myisamchk -r -q --set-character-set=charset на всех таблицах. В противном случае индексы могут сортироваться неправильно.

В случае недоверия к новым версиям всегда можно переименовать старую версию mysqld, изменив ее имя на что-нибудь вроде mysqld-old-version-number. Если после этого mysqld новой версии начнет вести себя не так, как ожидалось, то можно просто прекратить работу новой версии и перезапустить старую!

И, разумеется, при модернизации следует также сделать резервную копию старых баз данных.

После модернизации у вас могут возникнуть проблемы с перекомпилированными клиентскими программами, такими как Commands out of sync, или произойти неожиданная смерть приложения (coredump). Причина может быть в том, что при компиляции программ были использованы старые заголовочные или библиотечные файлы. В этом случае следует проверить даты создания вашего файла `mysql.h' и библиотеки `libmysqlclient.a', чтобы убедиться, что они из нового дистрибутива MySQL. Если это не так, то программы нужно перекомпилировать!

Если возникнут проблемы с запуском нового сервера mysqld или трудности с подключением без пароля, то нужно убедиться, что вы не используете старый файл `my.cnf' из старой установки! Это можно проверить с помощью program-name --print-defaults. Если эта программа вместо имени программы выводит что-нибудь иное, то ваш файл `my.cnf' является активным и оказывает влияние на ход событий!

Каждый раз при установке нового релиза MySQL есть смысл создавать наново и переустанавливать дистрибутив Msql-Mysql-modules, особенно если вы замечаете симптомы того, что ваши скрипты DBI умирают после модернизации MySQL.

2.5.1 Модернизация с версии 4.0

В общем случае, чтобы выполнить апгрейд до версии 4.1 с более ранней:

  • Выполните скрипт mysql_fix_privilege_tables для создания новых столбцов с паролями. Это нужно для более безопасной работы с паролями.

Далее идет более подробный список вещей, на которые следует обратить внимание при апгрейде на 4.1:

  • Функции, что возвращают DATE, DATETIME или TIME теперь фиксируются при отдаче клиенту.
    mysql> SELECT cast("2001-1-1" as DATE)
    -> '2001-01-01'
  • Все столбцы и таблицы теперь имеют кодировку, которая показывается в выводе SHOW CREATE TABLE и mysqldump. (MySQL 4.0.6 и выше могут читать новые dump-файлы, но не прежние версии MySQL).
  • Временная метка (timestamp) теперь возвращается как строка вида 'YYYY-MM-DD HH:MM:DD'. Если вы хотите получить ее как число - вам следует добавить +0 к столбцу timestamp. Различные длины временных меток теперь не поддерживаются.
  • Если вы используете несколько серверов на одном и том же компьютере под управлением Windows, вам следует использовать различные опции --shared_memory_base_name.

Обратите внимание что формат определения таблиц (.frm) поменялся в 4.1. MySQL 4.0.11 может читать новый файл формата, но более старые версии не могут. Если вам нужно перемещать таблицы с 4.1 на более старшие версии MySQL, вам следует использовать mysqldump. See section 4.8.5 mysqldump, Получение дампов данных и структуры таблицы.

2.5.2 Модернизация с версии 3.23 до версии 4.0

В общем случае, вот что вам следует сделать для апгрейда к версии 4.0 с более старой:

  • Выполнить скрипт mysql_fix_privilege_tables чтобы добавить новые привилегии и возможности в таблицы привилегий MySQL.
  • Подредактировать скрипты запуска MySQL или конфигурационные файлы, чтобы не использовать устаревшие опции, описанные ниже.
  • Преобразовать ваши старые ISAM-файлы в формат MyISAM следующей командой: mysql_convert_table_format база данных. Обратите внимание, это нужно делать только если все таблицы в базе данных являются таблицами типа ISAM или MyISAM. Если это не тот случай, вам тогда следует выполнить ALTER TABLE имя_таблицы TYPE=MyISAM для всех ISAM-таблиц.
  • Удостоверьтесь, что у вас не используется никакие клиенты MySQL, что используют динамические библиотеки (например, Perl Msql-Mysql-modules). Если у вас есть такие, их следует перекомпилировать, т.к. структуры в `libmysqlclient.so' изменились.

MySQL 4.0 будет работать, даже если вы не выполните эти шагы, но у вас не будет возможности использовать новые привилегии, которые предоставляет MySQL 4.0, и у вас могут быть проблемы при дальнейшем апгрейде к 4.1 или более новым серверам. Формат ISAM в MySQL 4.0 все еще работает, но он уже морально устарел и будет исключен из версии MySQL 5.0.

Старые клиенты должны работать с версией 4.0 без каких-либо проблем.

И даже если вы выполните эти шаги, вы сможете произвести даунгрейд к MySQL 3.23.52 или более новой, если у вас возникнут проблемы с MySQL 4.0. В этом случае вам потребуется выполнить mysqldump на всех таблицах, использующих полнотекстовые индексы и восстановить dump на версии 3.23. Причина заключается в том, что MySQL 4.0 использует новый формат полнотекстовых индексов.

Вот подробный список того, на что следует обратить внимание при апгрейде к 4.0:

  • В MySQL 4.0 появилось большое количество новых привилегий в таблице mysql.user. See section 4.3.1 Синтаксис команд GRANT и REVOKE. Чтобы заставить эти новые привилегии работать, следует запустить скрипт mysql_fix_privilege_tables. До выполнения данного скрипта у всех пользователей будут привилегии SHOW DATABASES, CREATE TEMPORARY TABLES и LOCK TABLES. Значения для привилегий SUPER и EXECUTE берутся из PROCESS, для REPLICATION SLAVE и REPLICATION CLIENT - из FILE. Чтобы скрипты, создающие новых пользователей, могли использовать новые привилегии, их нужно модифицировать. Если в этих скриптах не используется команда GRANT, то сейчас самое время изменить их. В версии 4.0.2 опция --safe-show-database устарела и не рекомендуется (и она больше ничего не делает). See section 4.2.3 Опции запуска mysqld, относящиеся к безопасности. Если в версии 4.0.2 для новых пользователей возникают ошибки отказа в доступе, то следует проверить, не требуются ли вам некоторые новые привилегии, которые не были нужны раньше. В частности, для новых репликаций понадобится REPLICATION SLAVE (вместо FILE).
  • Параметры запуска myisam_max_extra_sort_file_size и myisam_max_extra_sort_file_size теперь указываются в байтах (до 4.0.3 указывались в мегабайтах). Внешняя блокировка файлов MyISAM/ISAM теперь выключена по умолчанию. Можно включить ее обратно опцией --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)
    Опции запуска record_buffer, sort_buffer и warnings все еще работают в MySQL 4.0, но считаются уже морально устаревшими.
  • Следующие SQL-переменные переименованы.
    Из | В.
    SQL_BIG_TABLES | BIG_TABLES
    SQL_LOW_PRIORITY_UPDATES | LOW_PRIORITY_UPDATES
    SQL_MAX_JOIN_SIZE | MAX_JOIN_SIZE
    QUERY_CACHE_TYPE | QUERY_CACHE_TYPE
    Старые имена в MySQL 4.0 работают, но уже не рекомендованы к использованию.
  • Вы должны использовать SET GLOBAL SQL_SLAVE_SKIP_COUNTER=# вместо SET SQL_SLAVE_SKIP_COUNTER=#.
  • Переименовали опцию запуска mysqld --skip-locking в --skip-external-locking и --enable-locking в --external-locking.
  • SHOW MASTER STATUS теперь возвращает пустой результат если двоичный журнал обновлений не включен.
  • SHOW SLAVE STATUS возвращает пустой результат если подчиненный сервер не инициализирован.
  • mysqld теперь обладает опцией --temp-pool включенной по умолчанию, т.к. это дает лучшую производительность на некоторых ОС (в основном, на Linux).
  • Столбцы DOUBLE и FLOAT теперь учитывают флаг UNSIGNED при хранении (раньше UNSIGNED игнорировался для этих столбцов).
  • ORDER BY столбец DESC теперь сортирует величины NULL в первую очередь; в 3.23 это было не всегда так. Внимание: в MySQL 4.0.11 восстановлено оригинальное поведение.
  • SHOW INDEX имеет на 2 столбца больше (Null и Index_type), чем в версии 3.23.
  • CHECK, SIGNED, LOCALTIME и LOCALTIMESTAMP теперь являются зарезервированными словами.
  • Результат работы всех поразрядных операторов |, &, <<, >> и ~ сейчас является беззнаковым. Это может вызвать проблемы при использовании их в контексте, где желателен результат со знаком. See section 6.3.5 Функции приведения типов.
  • Замечание: результат операции вычитания между целыми величинами, одна из которых имеет тип UNSIGNED, будет беззнаковым! Другими словами, перед модернизацией до MySQL 4.0 вы должны проверить свои приложения для случаев, где производится вычитание величины из беззнакового объекта и предполагается ответ с отрицательным знаком, или вычитание беззнаковой величины из целочисленного столбца. Данный режим можно заблокировать, используя опцию --sql-mode=NO_UNSIGNED_SUBTRACTION при запуске mysqld. See section 6.3.5 Функции приведения типов.
  • Для того чтобы использовать MATCH ... AGAINST (... IN BOOLEAN MODE) на таблицах, следует перестроить их заново при помощи REPAIR TABLE table_name USE_FRM.
  • LOCATE() и INSTR() чувствительны к регистру, если один из аргументов является двоичной строкой. В противном случае они не зависят от регистра.
  • STRCMP() при выполнении сравнений сейчас использует текущий набор символов; это означает, что операция сравнения по умолчанию начиная с данной версии является независимой от регистра.
  • HEX(string) сейчас возвращает символы строки, преобразованные в шестнадцатеричные. Если необходимо преобразовать число в шестнадцатеричное представление, убедитесь, что HEX() вызывается с числовым аргументом.
  • В версии 3.23 в команде INSERT INTO ... SELECT параметр IGNORE всегда был разрешен. В версии 4.0.1 MySQL остановится (и, возможно, произойдет откат) в случае ошибки, если IGNORE не задан явно.
  • Скрипт safe_mysqld переименован в mysqld_safe. Некоторое время мы будем включать safe_mysqld в дистрибутив как символическую ссылку на mysqld_safe.
  • Старые функции C API mysql_drop_db, mysql_create_db и mysql_connect больше не будут поддерживаться, если вы не скомпилируете MySQL с CFLAGS=-DUSE_OLD_FUNCTIONS). Вместо перекомпиляции лучше пересобрать клиента для использования нового 4.0 API.
  • В структуре MYSQL_FIELD величины length и max_length изменены с unsigned int на unsigned long. Это не должно вызывать проблем, за исключением того, что при использовании величин с такими типами в качестве аргументов в функциях класса printf() могут генерироваться предупреждающие сообщения.
  • Если необходимо удалить из таблицы все строки, но вам не нужно знать, сколько строк было удалено, следует использовать TRUNCATE TABLE при (поскольку TRUNCATE TABLE значительно быстрее, чем DELETE FROM table_name).
  • При попытке выполнить TRUNCATE TABLE или DROP DATABASE при наличии активной команды LOCK TABLES или транзакции вы получите ошибку.
  • Для хранения величин в столбцах BIGINT необходимо использовать целые числа (вместо строк, как было в MySQL 3.23). Возможность использования строк для данного случая пока еще работает, но применение целых чисел более эффективно.
  • Изменен формат SHOW OPEN TABLE.
  • Многопоточные клиенты должны использовать mysql_thread_init() и mysql_thread_end(). See section 8.4.8 Как создать клиентскую программу с потоками.
  • При желании перекомпилировать модуль Perl DBD::mysql необходимо получить версию Msql-Mysql-modules 1.2218 или более новую, поскольку в более старых модулях DBD использовался не поддерживаемый вызов функции drop_db().
  • В версии 4.0 RAND(seed) возвращает иные последовательности случайных чисел, чем в 3.23; это сделано для того, чтобы лучше различать RAND(seed) и RAND(seed+1).
  • Тип результата, возвращаемый IFNULL(A,B) теперь по умолчанию устанавливается более "общий" по отношению к типам A и B. Порядок выбора - STRING, REAL или INTEGER.

2.5.3 Модернизация с версии 3.22 до версии 3.23

В версии MySQL 3.23 поддерживаются таблицы нового типа MyISAM и старого типа ISAM. Старые таблицы не нуждаются в преобразовании для использования их в версии 3.23. По умолчанию все новые таблицы будут создаваться с типом MyISAM (если вы не запускаете mysqld с опцией --default-table-type=isam). Можно преобразовать таблицу ISAM в таблицу MyISAM при помощи команды ALTER TABLE table_name TYPE=MyISAM или при помощи Perl-скрипта mysql_convert_table_format.

Клиенты версий 3.22 и 3.21 должны работать с сервером версии 3.23 без каких-либо проблем.

Ниже перечислены моменты, на которые следует обратить внимание при модернизации до версии 3.23:

  • Все таблицы, в которых используется кодировка tis620, должны быть исправлены с помощью myisamchk -r или REPAIR TABLE.
  • При выполнении команды DROP DATABASE над базой данных, связанной символической ссылкой, удаляются как данная ссылка, так и исходная база данных (в 3.22 это было не так, поскольку программа configure не распознавала системный вызов readlink).
  • OPTIMIZE TABLE сейчас работает только с таблицами MyISAM. Для других типов таблиц можно использовать команду ALTER TABLE для оптимизации таблицы. Во время выполнения команды OPTIMIZE TABLE оптимизируемая таблица сейчас заблокирована для других потоков.
  • Клиент mysql сервера MySQL сейчас по умолчанию начинает свою работу с опцией --no-named-commands (-g). Данную опцию можно отключить с помощью --enable-named-commands (-G). В некоторых случаях это может вызывать проблемы несовместимости, например, в скриптах SQL, в которых названные команды используются без точки с запятой! Команды большого формата пока еще работают с начала строки.
  • Функции даты, работающие с частью представления даты (такие как MONTH()), сейчас будут возвращать 0 для даты 0000-00-00 (в версии MySQL 3.22 возвращалась величина NULL).
  • При использовании порядка сортировки символов german необходимо исправить все таблицы с помощью isamchk -r, так как в порядке сортировки произведены некоторые изменения!
  • Возвращаемый по умолчанию тип выражения IF теперь зависит от обоих аргументов, а не только от первого.
  • AUTO_INCREMENT теперь не будет работать с отрицательными числами; причина в том, что отрицательные числа вызывали проблемы при переходе от -1 к 0. Для таблиц MyISAM AUTO_INCREMENT не обрабатывается на более низком уровне и работает намного быстрее, чем раньше. Для таблиц MyISAM старые автоинкрементные номера также не используются повторно, даже при удалении из таблицы строк.
  • CASE, DELAYED, ELSE, END, FULLTEXT, INNER, RIGHT, THEN и WHEN сейчас являются зарезервированными словами.
  • FLOAT(X) сейчас является настоящим типом данных с плавающей точкой, а не величиной с фиксированным числом десятичных знаков.
  • При объявлении DECIMAL(length,dec) аргумент length больше не включает в себя место для знака или десятичной точки.
  • Строка TIME теперь должна представлять собой один из следующих форматов: [[[DAYS] [H]H:]MM:]SS[.fraction] или [[[[[H]H]H]H]MM]SS[.fraction].
  • LIKE сейчас сравнивает строки, используя те же правила сравнения символов, что и =. Если необходим старый режим работы, то можно скомпилировать MySQL с флагом CXXFLAGS=-DLIKE_CMP_TOUPPER.
  • Выражение REGEXP сейчас является независимым от регистра символов для нормальных (не двоичных) строк.
  • При проверке/исправлении таблиц необходимо использовать CHECK TABLE или myisamchk для таблиц MyISAM (`.MYI') и isamchk для таблиц ISAM (`.ISM').
  • Чтобы обеспечить совместимость файлов mysqldump между версией MySQL 3.22 и версией 3.23, не следует использовать опцию --opt или --all для mysqldump.
  • Проверьте все ваши вызовы функции DATE_FORMAT(), чтобы убедиться, что перед каждым символом формата имеется `%' (в версии MySQL 3.22 и более поздних этот синтаксис уже допускается).
  • mysql_fetch_fields_direct сейчас является функцией (был макрос) и возвращает указатель на MYSQL_FIELD вместо MYSQL_FIELD.
  • Функцию mysql_num_fields() больше нельзя использовать на объектах MYSQL* (сейчас это функция, принимающая MYSQL_RES* в качестве аргумента, так что вместо нее следует применять mysql_field_count()).
  • В версии MySQL 3.22 вывод SELECT DISTINCT ... почти всегда был отсортированным. Чтобы получить отсортированный вывод в версии 3.23, необходимо использовать GROUP BY или ORDER BY.
  • Функция SUM() сейчас возвращает NULL вместо 0 при отсутствии сопоставляемых строк: это сделано для соответствия с ANSI SQL.
  • Операторы AND или OR с величинами NULL теперь будут возвращать NULL вместо 0. В основном, это влияет на запросы, в которых используется NOT на выражениях AND/OR, так как NOT NULL = NULL. LPAD() и RPAD() будут укорачивать результирующую строку, если она длиннее, чем аргумент длины.

2.5.4 Модернизация с версии 3.21 до версии 3.22

В версии 3.21 по сравнению с 3.22 не было сделано никаких изменений, влияющих на совместимость. Единственный подводный камень - это то, что для новых таблиц, создающихся со столбцами типа DATE, будет применяться новый способ хранения даты. При использовании старой версии mysqld получить доступ к этим новым полям будет нельзя.

После установки версии MySQL 3.22 необходимо запустить новый сервер, а затем выполнить скрипт mysql_fix_privilege_tables. В результате будут добавлены новые привилегии, необходимые для использования команды GRANT. Если вы забудете выполнить эти действия, то получите Access denied при попытке использовать ALTER TABLE, CREATE INDEX или DROP INDEX. Если для вашего привилегированного (root) пользователя MySQL требуется пароль, то следует указать его как аргумент в mysql_fix_privilege_tables.

Изменен интерфейс C API к функции mysql_real_connect().Если вы располагаете старой клиентской программой, вызывающей данную функцию, то необходимо задать значение 0 для нового аргумента db (или перекодировать данный клиент, чтобы посылать значение элемента db для более быстрых подключений). Необходимо также вызывать mysql_init() перед вызовом функции mysql_real_connect()! Это изменение было проведено для того, чтобы дать возможность новой функции mysql_options() сохранять опции в структуре обработчика MYSQL.

Имя относящейся к mysqld переменной key_buffer изменено на key_buffer_size, однако старое имя можно использовать по-прежнему.

2.5.5 Модернизация с версии 3.20 до версии 3.21

Если вы работаете с версией выше, чем 3.20.28, и хотите перейти к 3.21, то необходимо сделать следующее:

Можно запустить сервер mysqld версии 3.21 с опцией safe_mysqld --old-protocol, чтобы использовать его с клиентами из дистрибутива версии 3.20. В этом случае функция mysql_errno() нового клиента не возвращает никаких серверных ошибок, кроме CR_UNKNOWN_ERROR (она предназначена для клиентских ошибок), при этом сервер использует не новую, а старую функцию проверки password().

Если вы не собираетесь использовать опцию --old-protocol к mysqld, то необходимо будет выполнить следующие изменения:

  • Весь клиентский код следует перекомпилировать. Для использования ODBC необходимо приобрести новый драйвер MyODBC 2.x.
  • Необходимо запустить скрипт `scripts/add_long_password' для преобразования поля Password в таблице mysql.user к CHAR(16).
  • Все пароли в таблице mysql.user должны быть переназначены (чтобы получить 62- разрядные пароли вместо 31- разрядных).
  • Формат таблиц не изменялся, следовательно, в преобразовании каких-либо таблиц необходимости нет.

Версия MySQL 3.20.28 и выше может обрабатывать новый формат таблиц user так, что это не отражается на клиентах. В более ранних, чем 3.20.28, версиях MySQL пароли больше не будут работать с клиентами, если таблица user преобразована. Для уверенности следует прежде провести апгрейд по меньшей мере до версии 3.20.28 и затем модернизировать до версии 3.21.

Новый код клиента работает с сервером mysqld версии 3.20.x, так что в случае каких-либо проблем с версией 3.21.x можно использовать старый сервер 3.20.x без необходимости повторной перекомпиляции клиентов.

Если не применить опцию --old-protocol для mysqld, то старые клиенты выдадут следующее сообщение об ошибке:

ERROR: Protocol mismatch. Server Version = 10 Client Version = 9

Новый интерфейс Perl DBI/DBD также поддерживает старый интерфейс mysqlperl. Единственное изменение, которое следует произвести при использовании mysqlperl, модифицировать аргументы в функции connect(). Новыми аргументами являются: host, database, user, и password (аргументы user и password поменялись местами). See section 8.2.2 Интерфейс DBI.

Ниже перечислены изменения, которые могут повлиять на запросы в старых приложениях:

  • HAVING теперь необходимо указывать перед любым выражением ORDER BY.
  • Произведена замена параметров в LOCATE().
  • Появилось несколько новых зарезервированных слов. Наиболее значимыми из них являются DATE, TIME и TIMESTAMP.

2.5.6 Модернизация к иной архитектуре

При использовании MySQL 3.23 можно копировать файлы `.frm', `.MYI' и `.MYD' между различными архитектурами, поддерживающими одинаковый формат чисел с плавающей точкой (все проблемы, связанные с перестановкой байтов, берет на себя MySQL).

Имеющиеся в MySQL файлы данных и индексные файлы типа ISAM (`.ISD' и `*.ISM' соответственно) являются архитектурно-независимыми, а в ряде случаев - зависимыми от операционной системы. Для переноса приложений на компьютер с архитектурой или операционной системой, которые отличаются от используемых на исходном компьютере, не следует пытаться перенести базу данных путем простого копирования файлов на другой компьютер. Используйте вместо этого mysqldump.

По умолчанию mysqldump создаст файл со всеми командами SQL. После этого данный файл можно перенести на другой компьютер и подать его на вход клиента mysql.

Используя mysqldump --help, просмотрите все доступные опции. При перемещении данных на более новую версию MySQL следует применять mysqldump --opt более новой версии, чтобы получить быструю и компактную копию.

Самый простой (хотя и не самый быстрый) способ перемещения базы данных с компьютера на компьютер - запустить на компьютере, где размещается исходная база данных, следующие команды:

shell> mysqladmin -h 'other hostname' create db_name
shell> mysqldump --opt db_name \
      | mysql -h 'other hostname' db_name

Если вы хотите скопировать базу данных с удаленного компьютера через медленную сеть, то можно использовать:

shell> mysqladmin create db_name
shell> mysqldump -h 'other hostname' --opt --compress db_name \
      | mysql db_name

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

shell> mysqldump --quick db_name | gzip > db_name.contents.gz

(Созданный в данном примере файл сжимается). Передайте этот файл с содержимым базы данных на требуемый компьютер и запустите там эти команды:

shell> mysqladmin create db_name
shell> gunzip < db_name.contents.gz | mysql db_name

Для выполнения передачи базы данных можно также использовать mysqldump и mysqlimport. В случае больших таблиц это намного более быстрый способ, чем простое применение mysqldump. В следующих командах DUMPDIR представляет собой полный путь к каталогу, используемому для хранения вывода из mysqldump.

Во-первых, создайте каталог для файлов вывода и дампа базы данных:

shell> mkdir DUMPDIR
shell> mysqldump --tab=DUMPDIR db_name

Затем передайте эти файлы в каталог DUMPDIR некоторого соответствующего каталога на требуемом компьютере и загрузите там данные файлы в MySQL:

shell> mysqladmin create db_name # создание  базы  данных
shell> cat DUMPDIR/*.sql | mysql db_name # создание  таблиц  в  базе данных
shell> mysqlimport db_name DUMPDIR/*.txt # загрузка  данных  в  таблицы

Помимо этого, не забудьте скопировать базу данных mysql, поскольку в ней хранятся таблицы привилегий (user, db, host). Возможно, на новом компьютере будет нужно запустить команды в качестве пользователя root MySQL, пока база данных mysql не займет свое место.

После импорта базы данных mysql на новый компьютер выполните mysqladmin flush-privileges, чтобы сервер перезагрузил информацию в таблицах привилегий.

2.6 Заметки по операционным системам

2.6.1 Примечания к Linux (Все версии Linux)

Приведенные ниже замечания о glibc будут полезны только для случая, когда вы собираете MySQL самостоятельно. Но обычно, если Linux работает на машине с архитектурой x86, гораздо лучше использовать наши бинарные файлы. Они линкуются с glibc, к которой применены наиболее удачные патчи, и с наиболее удачными опциями компилятора - все это сделано для того, чтобы программа была пригодной для работы на сильно нагруженном сервере. Поэтому если после прочтения данного раздела у вас возникнут сомнения относительно дальнейших действий, попробуйте сначала использовать бинарные файлы - возможно, они удовлетворят вашим требованиям. Если же окажется, что бинарные файлы вас не устраивают, то можно попробовать заняться собственноручной сборкой. Мы будем очень признательны за сообщение о том, почему вам пришлось отказаться от работы с нашими бинарниками, - это поможет нам в следующий раз собрать более удачную версию программы. Что же касается обычных пользователей, то для них даже при установке, рассчитанной на большое количество параллельных соединений и/или таблиц, превосходящих по объему ограничение в 2 Гб, наши бинарные файлы будут наилучшим вариантом выбора.

В операционной системе Linux MySQL использует LinuxThreads. Если у вас старая система Linux, в которой отсутствует glibc2, то прежде чем предпринимать попытку компиляции MySQL, необходимо установить LinuxThreads. Получить LinuxThreads можно по адресу http://www.mysql.com/downloads/os-linux.html.

Примечание: на Linux 2.2.14 и MySQL, установленных на многопроцессорных (SMP) системах, могут возникать некоторые непонятные проблемы. В таком случае мы рекомендуем как можно быстрее сделать апгрейд версии ядра до 2.4: оно станет гораздо более быстрым и устойчивым.

Необходимо отметить, что версии glibc до 2.1.1 включительно содержат фатальную ошибку в обработке pthread_mutex_timedwait, которая проявляется при использовании INSERT DELAYED. Поэтому мы рекомендуем не использовать INSERT DELAYED, пока не будет сделан апгрейд glibc.

Если планируется использовать более 1000 одновременных соединений, необходимо сделать некоторые изменения в LinuxThreads, пересобрать их и перелинковать MySQL с новой `libpthread.a'. Следует увеличить PTHREAD_THREADS_MAX в файле `sysdeps/unix/sysv/linux/bits/local_lim.h' до 4096 и уменьшить STACK_SIZE в `linuxthreads/internals.h' до 256 Kб.

Пути указаны относительно корневого каталога glibc. Заметим, что MySQL не будет устойчиво работать при 600-1000 соединениях, если размер STACK_SIZE останется по умолчанию 2 Mб.

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

В Linux 2.2 и более свежих версиях можно получить значение максимального количества файлов, которые можно открыть одновременно. Для этого необходимо выполнить:

cat /proc/sys/fs/file-max
cat /proc/sys/fs/dquot-max
cat /proc/sys/fs/super-max

В случае, если на машине установлено более 16 Mб памяти, к загрузочному скрипту (`/etc/init.d/boot.local' на SuSE) необходимо добавить записи наподобие следующих:

echo 65536 > /proc/sys/fs/file-max
echo 8192 > /proc/sys/fs/dquot-max
echo 1024 > /proc/sys/fs/super-max

Эти команды можно также запустить из командной строки от имени пользователя

root, но в таком случае при перезагрузке компьютера будут использоваться старые ограничения.

Альтернативно, вы можете установить эти параметры при загрузке, используя утилиту sysctl, которая используется во множестве поставок Linux (SuSE также добавила ее, начиная с SuSE 8.0). Просто напишите такие значения в файл `/etc/sysctl.conf':

# увеличить некоторые значения для MySQL
fs.file-max = 65536
fs.dquot-max = 8192
fs.super-max = 1024

Кроме того, необходимо добавить в `/etc/my.cnf':

[safe_mysqld]
open-files-limit=8192

Добавление такой записи позволит MySQL создавать до 8192 соединений и файлов.

Размером стеков потоков в адресном пространстве управляет константа STACK_SIZE в LinuxThreads. Ее значение должно быть достаточно большим, чтобы хватило места стеку каждого потока, но достаточно малым, чтобы предотвратить попадание стеков некоторых потоков в область общих данных mysqld. К сожалению, опытным путем нам удалось обнаружить, что реализация mmap() на Linux в случае поступления запроса на выделение адреса, который уже используется, вместо возвращения сообщения об ошибке успешно освобождает все ранее выделенные области и обнуляет данные на всей странице. Поэтому безопасность использования mysqld или любого другого потокового приложения зависит от "джентльменского" поведения кода, создающего потоки. Пользователь должен принять меры для обеспечения достаточно малого количества выполняемых потоков в любой момент времени, чтобы стеки потоков не пересекались с динамически выделяемой памятью. В случае mysqld необходимо навязать это "джентльменское" поведение установкой переменной max_connection в разумных пределах.

Если вы собираете MySQL самостоятельно и не хотите заниматься патчами LinuxThreads, то необходимо установить значение max_connections так, чтобы оно не превышало 500. Это значение должно быть еще меньше, если у вас достаточно велик буфер ключей, большая таблица динамически выделяемой памяти или имеются другие причины, по которым mysqld занимает большие объемы памяти, а также в случае, если вы используете ядро 2.2 с патчами для 2 Гб. Если используются наши бинарные файлы или RPM версии не старше 3.23.25, то можно безопасно устанавливать max_connections равным 1500 - при условии, что буфер ключей или таблицы динамически выделяемой памяти имеют небольшие размеры. Чем меньше STACK_SIZE в LinuxThreads, тем больше потоков можно безопасно создать. Рекомендуемая нами величина составляет от 128K до 256K.

При использовании множества одновременных соединений вы можете пострадать от одной "особенности" ядра 2.2. Данная особенность заключается в том, что процесс штрафуется за ветвление или порождение дочерних процессов - чтобы предотвратить атаки ветвлением. Это приводит к неудачному масштабированию MySQL при увеличении количества одновременных соединений. По нашим данным, на однопроцессорных машинах из-за данной особенности создание потоков происходит очень медленно, что может привести к большим затратам времени на соединение с MySQL (до 1 минуты), и столько же может занять завершение соединения. Что же касается многопроцессорных систем, то на них наблюдалось постепенное снижение скорости по мере роста числа клиентов. Пока мы пытались найти решение проблемы, один из пользователей прислал патч к ядру, утверждая, что патч заметно улучшил работу его сайта. Патч доступен по адресу http://www.mysql.com/Downloads/Patches/linux-fork.patch. Мы провели достаточно обширное тестирование этого патча как на развивающейся, так и на промышленной версиях системы. Применение патча заметно улучшило производительность MySQL, не вызвав при этом никаких проблем, поэтому теперь мы рекомендуем его пользователям, которые до сих пор используют ядро 2.2 на сильно нагруженных серверах. Кроме того, эта проблема была решена в ядре 2.4, поэтому если вас не устраивает производительность системы, то, по-видимому, проще сделать ее апгрейд до 2.4, чем использовать патчи к ядру 2.2. При обновлении системы, помимо исправления этой ошибки, вы также получите возможность воспользоваться преимуществами SMP.

При тестировании MySQL на двухпроцессорной машине с ядром 2.4 мы обнаружили, что MySQL масштабируется гораздо лучше - фактически отсутствовало замедление обработки запросов вплоть до 1000 соединений, а фактор масштабируемости MySQL (который вычисляется как отношение максимальной производительности к производительности при работе с одним клиентом) достигал 180%. Подобные результаты мы наблюдали на четырехпроцессорной системе - фактическое отсутствие замедления при росте количества соединений до 1000 при факторе масштабируемости в 300%. Поэтому для интенсивно нагруженных серверов мы настоятельно рекомендуем ядро 2.4. Оказалось также, что для достижения максимума производительности на ядре 2.4 весьма важно запускать mysqld с наибольшим возможным приоритетом. Для этого следует добавить в скрипт safe_mysqld команду renice -20 $$. В наших тестах на четырехпроцессорной машине увеличение приоритета привело к повышению производительности на 60% при работе 400 клиентов.

В дополнение к этому мы сейчас занимаемся сбором информации о производительности MySQL с ядром 2.4 на четырех- и восьмипроцессорных системах. Если у вас есть доступ к таким системам и вы тестировали их производительность, пожалуйста, отправьте сообщение с результатами по адресу docs@mysql.com - мы добавим эти результаты в документацию.

Существует еще один нюанс, заметно влияющий на производительность

MySQL, особенно на многопроцессорных системах. В LinuxThreads в glibc-2.1 очень плохо реализованы mutex'ы для программ со множеством потоков, в которых mutex хранится непродолжительное время. Парадоксально, но факт: в случае, если на многопроцессорных системах собрать MySQL с немодифицированными LinuxThreads, то при удалении процессора во много раз увеличивается производительность. Для решения этой проблемы мы предлагаем патч к glibc 2.1.3 http://www.mysql.com/Downloads/Linux/linuxthreads-2.1-patch.

В glibc-2.2.2 MySQL версии 3.23.36 использует адаптивный mutex, который гораздо лучше даже ``патченного'' в glibc-2.3.1. Однако предупреждаем, что при некоторых условиях код mutex'а в glibc-2.2.2 "закручивается" (overspin), а это ухудшает производительность MySQL. Шансы возникновения такого события можно понизить, если повысить приоритет выполнения mysqld. Можно также исправить "закручивание" с помощью патча, доступного по адресу http://www.mysql.com/Downloads/Linux/linuxthreads-2.2.2.patch. Он содержит в себе коррекцию "закручивания", максимальное количество потоков и размеры стека - все вместе. Необходимо применить его в каталоге linuxthreads командой patch -p0 </tmp/linuxthreads-2.2.2.patch. Мы надеемся, что данный патч будет в некотором виде включен в следующие выпуски glibc-2.2. В любом случае - если вы линкуете с использованием библиотеки glibc-2.2.2, то пока что необходимо исправлять STACK_SIZE и PTHREAD_THREADS_MAX. Мы не теряем надежду, что в будущем значения по умолчанию будут приведены к более приемлемым для сборки интенсивно нагруженного MySQL величинам, так что самостоятельная сборка сведется к выполнению ./configure; make; make install.

Вышеупомянутые патчи мы рекомендуем использовать только для создания специальной статической версии `libpthread.a', а последнюю - применять только для статического линкования MySQL. Мы уверены, что для MySQL эти патчи безопасны и заметно улучшают его производительность, но относительно других приложений данных нет. Линкуя другие приложения с ``патченной'' версией библиотеки или собирая ее динамическую версию и устанавливая ее на свою систему, вы осознанно идете на риск по отношению к другим приложениям, использующим LinuxThreads.

В случае, если вам придется столкнуться с непонятными проблемами при инсталляции MySQL или при работе утилит, то причина, вероятнее всего, связана с библиотеками или компилятором. В таком случае проблему должно решить использование наших бинарных файлов.

Существует одна известная проблема с бинарным дистрибутивом, касающаяся старых систем Linux, в которых используется libc (таких как RedHat 4.x или Slackware). Она проявляется в виде некоторых некритичных проблем с разрешением имен (see section 2.6.1.1 Примечания к бинарным дистрибутивам Linux).

При использовании LinuxThreads одновременно работают как минимум три процесса. По сути это потоки. Один поток управляет LinuxThreads, один - обрабатывает соединения и еще один - обрабатывает различные сигналы.

Заметим, что ядро Linux и библиотека LinuxThreads по умолчанию могут поддерживать только 1024 потока. Это значит, что может существовать не более 1021 соединения с MySQL на системе, к которой не применялись патчи. Информацию о том, как обойти это ограничение, можно найти на странице http://www.volano.com/linuxnotes.html.

Если по результату работы команды ps вы видите, что mysqld прекратил работу,

то обычно причиной этого является либо обнаружение ошибки в MySQL, либо испорченная таблица (see section A.4.1 Что делать, если работа MySQL сопровождается постоянными сбоями).

Если при получении сигнала SIGSEGV mysqld просто умирает, то для получения образа памяти (core dump) на Linux можно запустить mysqld с опцией --core-file. Заметим, что при этом вам, возможно, придется увеличить размер допустимого объема файла образа памяти путем добавления строки ulimit -c 1000000 в safe_mysqld или запуском safe_mysqld с опцией --core-file-size=1000000 (see section 4.7.2 safe_mysqld, оболочка mysqld).

Если при линковании собственного MySQL-клиента возникла ошибка:

ld.so.1: ./my: fatal: libmysqlclient.so.4:
open failed: No such file or directory

то проблему можно обойти одним из следующих способов:

  • линковать клиент с одним из флагов: -Wl,r/path-libmysqlclient.so. (вместо -Lpath);
  • скопировать `libmysqclient.so' в `/usr/lib';
  • добавить путь к каталогу, в котором находится `libmysqlclient.so', к переменной окружения LD_RUN_PATH перед запуском клиента.

Если вы используете компилятор Fujitsu (fcc / FCC), то возможны некоторые проблемы компиляции MySQL поскольку заголовки в Linux в значительной степени ориентированы на gcc.

Данная конфигурация должна работать с fcc/FCC:

CC=fcc CFLAGS="-O -K fast -K lib -K omitfp -Kpreex -D_GNU_SOURCE \
-DCONST=const -DNO_STRTOLL_PROTO" CXX=FCC CXXFLAGS="-O -K fast -K lib \
-K omitfp -K preex --no_exceptions --no_rtti -D_GNU_SOURCE -DCONST=const \
-Dalloca=__builtin_alloca -DNO_STRTOLL_PROTO \
'-D_EXTERN_INLINE=static __inline'" ./configure --prefix=/usr/local/mysql\
--enable-assembler --with-mysqld-ldflags=-all-static --disable-shared \
--with-low-memory

2.6.1.1 Примечания к бинарным дистрибутивам Linux

Для работы MySQL необходим Linux версии не ниже 2.0.

Предупреждение: По данным, полученным нами от некоторых пользователей MySQL, на Linux с ядром 2.2.14 имеются серьезные проблемы с устойчивостью работы MySQL. Если вы используете это ядро, необходимо обновить его до версии 2.2.19 или выше, либо до ядра версии 2.4. Аргументы в пользу 2.4 становятся еще более весомыми при использовании многопроцессорной системы, поскольку переход на эту версию ядра приводит к заметному увеличению скорости.

Как правило, бинарный дистрибутив линкуется с опцией -static, а это значит, что обычно нет необходимости беспокоиться о том, какая версия системных библиотек у вас установлена. Не требуется также устанавливать LinuxThreads. Размер программы, слинкованной с опцией -static, обычно больше в сравнении с версией, собранной динамически, однако скорость работы у нее выше (3-5%). Существует, однако, одна проблема. Она заключается в том, что со статически слинкованными программами невозможно использовать определяемые пользователем функции (user-definable function, UDF). Если вы собираетесь писать или использовать UDF'ы (это информация, касающаяся только программистов на C или C++), вам следует собственноручно собрать MySQL с использованием динамического линкования.

При использовании систем, базирующихся на libc (в отличие от glibc2-систем), могут возникать некоторые проблемы с разрешением имен удаленных компьютеров и использованием getpwnam() с бинарной версией (это происходит из-за того, что, к сожалению, glibc зависит от некоторых внешних библиотек при разрешении имен и использовании getpwent(), даже при сборке с опцией -static). В таком случае при запуске mysql_install_db возможно появление следующего сообщения об ошибке:

Sorry, the host 'xxxx' could not be looked up

Или же - при запуске mysqld с опцией --user - сообщение об ошибке может быть таким:

getpwnam: No such file or directory

Эту проблему можно решить одним из следующих способов:

  • загрузить и установить дистрибутив MySQL с исходными текстами (RPM или дистрибутив tar.gz).
  • Запустить mysql_install_db --force, чтобы избежать проверки resolveip в mysql_install_db. Оборотной стороной такого подхода является невозможность работать с именами машин в таблицах прав доступа - вместо них следует должны использовать IP-адреса (за исключением localhost). Если у вас старая поставка MySQL, которая не поддерживает ключ --force, то нужно просто удалить в редакторе проверку resolveip из mysql_install.
  • Запускать mysqld с помощью команды su вместо использования опции --user.

RPM и бинарные файлы MySQL для Linux на архитектуре Intel оптимизированы для достижения наибольшей возможной скорости работы. Мы всегда стараемся использовать компиляторы, которые дают наиболее быстрый и устойчивый код.

Поддержка Perl в MySQL требует Perl версии не ниже 5.004_03.

На некоторых Linux версии 2.2 при попытке создать большое количество новых соединений с сервером mysqld через TCP/IP вы можете получить сообщение об ошибке Resource temporarily unavailable (Ресурс временно недоступен).

Проблема заключается в задержке между закрытием сокета TCP/IP и реальным его освобождением системой в Linux. Поскольку существует ограниченное количество областей для поддержки TCP/IP, вы получите вышеназванную ошибку, если попытаетесь создать слишком много новых соединений TCP/IP на протяжении короткого отрезка времени (нечто подобное происходит при запуске теста на производительность MySQL `test-connect' поверх TCP/IP).

Об этой проблеме мы несколько раз сообщали в различные списки рассылки по Linux, однако удачного решения получить не удалось.

Единственное известное 'решение' данной проблемы заключается в том, что ваши клиенты должны работать с постоянными соединениями или использовать сокеты (в случае, если клиентская и серверная части находятся на одной машине). Остается надеяться, что эта проблема будет решена в ядре Linux 2.4.

2.6.1.2 Заметки по поводу Linux x86

Для MySQL необходимо наличие libc версии 5.4.12 или выше. Известно, что MySQL работает с libc 5.4.46, а также с glibc версии 2.0.6 и более новыми. Существуют некоторые проблемы с glibc из пакетов в RedHat, поэтому в случае возникновения проблем следует проверить, нет ли обновлений данной версии! Известно, что glibc из RPM версий 2.0.7-19 и 2.0.7-29 работоспособны.

Если вы используете Red Hat 8.0 или новую glibc 2.2.x вам следует запускать mysqld с опцией --thread-stack=192K. Если вы этого не сделаете, то mysqld будет умирать в gethostbyaddr() потому что новая glibc требует > 128Кбайт памяти стека для этого вызова. Такой размер стека установлен по умолчанию в MySQL 4.0.10 и более новых.

При использовании для сборки MySQL gcc 3.0 и выше библиотеку libstdc++v3 необходимо установить до сборки; если вы не сделаете этого, то получите сообщение об отсутствии символа __cxa_pure_virtual во время линкования!

На некоторых старых версиях Linux configure может приводить к ошибкам такого типа:

Syntax error in sched.h. Change _P to __P in the /usr/include/sched.h file.
See the Installation chapter in the Reference Manual.

Сделайте именно то, о чем говорится в сообщении об ошибке - добавьте дополнительный символ подчеркивания к имени макроса _P, которое имеет только один символ подчеркивания в начале, и попробуйте выполнить те же действия еще раз.

При компиляции могут выводиться некоторые предупреждения. Ниже приведены те из них, которые можно проигнорировать:

mysqld.cc -o objs-thread/mysqld.o
mysqld.cc: In function `void init_signals()':
mysqld.cc:315: warning: assignment of negative value `-1' to `long unsigned int'
mysqld.cc: In function `void * signal_hand(void *)':
mysqld.cc:346: warning: assignment of negative value `-1' to `long unsigned int'

mysql.server находится либо в каталоге `share/mysql' каталога инсталляции MySQL, либо в каталоге `support-files' каталога дерева исходных текстов MySQL.

Возникновение следующей ошибки при линковании mysqld говорит о некорректной установке libg++.a:

/usr/lib/libc.a(putc.o): In function `_IO_putc':
putc.o(.text+0x0): multiple definition of `_IO_putc'

Использования libg++.a можно избежать путем запуска configure следующим образом:

shell> CXX=gcc ./configure

2.6.1.3 Примечания к Linux SPARC

В некоторых версиях Linux SPARC испорчена функция readdir_r(). Это проявляется в том, что SHOW DATABASES всегда возвращает пустой набор. Проблема может быть решена удалением HAVE_READDIR_R из `config.h' - это нужно делать после конфигурирования, но до компиляции.

2.6.1.4 Примечания к Linux Alpha

MySQL версии 3.23.12 - первая версия MySQL, протестированная на Linux-Alpha. Поэтому если вы собираетесь использовать MySQL на Linux-Alpha, следует прежде всего убедиться, что вы используете либо эту версию, либо более свежую.

Мы тестировали MySQL на Alpha при помощи наших тестов на производительность и все работает превосходно.

При компиляции стандартных бинарных файлов MySQL мы использовали SuSE 7.0 для AXP с ядром 2.4.4-SMP, компилятор Compaq C (6.2-505) и компилятор Compaq C++ (6.3-006) на компьютере Compaq DS20 с процессором Alpha EV6.

Вышеупомянутый компилятор можно найти на http://www.support.compaq.com/alpha-tools/. Использование этого компилятора вместо gcc привело к улучшению производительности MySQL на 9-14%.

Отметим, что до версии MySQL 3.23.52 и 4.0.2 мы оптимизировали исполняемые файлы только для единственной модели процессора (используя опцию компиляции -fast); это означало что вы можете использовать наши двоичные файлы только если у вас процессор Alpha EV6.

Для всех следующих версий мы добавили флаг -arch generic к нашим опциям компиляции, что позволяет работать бинарному файлу на всех процессорах Alpha. Мы также собираем MySQL статически - во избежание проблем.

CC=ccc CFLAGS="-fast -arch generic" CXX=cxx \
CXXFLAGS="-fast -arch generic -noexceptions -nortti" \
./configure --prefix=/usr/local/mysql --disable-shared \
--with-extra-charsets=complex --enable-thread-safe-client \
--with-mysqld-ldflags=-non_shared --with-client-ldflags=-non_shared

Если вы хотите использовать egcs, то у нас применялась следующая командная строка конфигурирования:

CFLAGS="-O3 -fomit-frame-pointer" CXX=gcc \
CXXFLAGS="-O3 -fomit-frame-pointer -felide-constructors \
-fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql \
--disable-shared

Некоторые известные проблемы при запуске MySQL на Linux-Alpha:

  • отладка потоковых приложений, подобных MySQL, не работает с gdb 4.18. Вместо него необходимо установить и использовать gdb 5.1!
  • при попытке статического линкования mysqld с использованием gcc результирующий файл при попытке запуска сбрасывает образ памяти на диск (core dump) и умирает. Иными словами, не следует использовать с gcc опцию --with-mysqld-ldflags=-all-static.

2.6.1.5 Примечания к Linux PowerPC

MySQL должен работать на MkLinux при наличии самого свежего пакета glibc (проверено с glibc 2.0.7).

2.6.1.6 Примечания к Linux MIPS

Для того чтобы MySQL работал на Qube2 (Linux Mips), необходима самая свежая версия библиотеки glibc (известно, что MySQL работает с glibc-2.0.7-29C2). Помимо этого, следует использовать компилятор egcs C++ (egcs-1.0.2-9, gcc 2.95.2 или выше).

2.6.1.7 Примечания к Linux IA64

Для компиляции MySQL на Linux IA64 мы применяем следующую команду

конфигурирования: используется gcc-2.96:

CC=gcc CFLAGS="-O3 -fno-omit-frame-pointer" CXX=gcc \
CXXFLAGS="-O3 -fno-omit-frame-pointer -felide-constructors \
-fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql \
"--with-comment=Official MySQL binary" --with-extra-charsets=complex

На IA64 бинарные файлы MySQL-клиента используют динамические библиотеки. Это значит, что при установке нашего бинарного дистрибутива куда-либо, кроме `/usr/local/mysql', необходимо либо модифицировать `/etc/ld.so.conf', либо добавить путь к каталогу, в котором находится `libmysqlclient.so', к переменной окружения LD_LIBRARY_PATH.

See section A.3.1 Проблемы при линковании с клиентской библиотекой MySQL.

2.6.2 Примечания к Windows

В данном разделе описывается использование MySQL в среде Windows. Эта информация также находится в файле `README', поставляемом с дистрибутивом MySQL Windows. See section 2.1.2 Установка MySQL на Windows.

2.6.2.1 Запуск MySQL на Windows 95, 98 или Me

В MySQL для соединения клиента с сервером используется TCP/IP (это обеспечивает для любого компьютера в сети возможность соединиться с вашим MySQL-сервером). Поэтому TCP/IP необходимо установить на машине до запуска MySQL. TCP/IP, в частности, имеется на CD-диске с дистрибутивом Windows.

Обратите внимание: если вы используете один из старых выпусков Windows 95 (например OSR2), то вполне вероятно, что у вас установлен старый пакет Winsock; а для работы MySQL необходим Winsock 2! Самую свежую версию Winsock можно получить по адресу http://www.microsoft.com/. Windows 98 содержит новую библиотеку Winsock 2, поэтому данное замечание к ней не относится.

Для запуска mysqld необходимо открыть окно MS-DOS и выполнить:

C:\> C:\mysql\bin\mysqld

Это позволит запустить mysqld в фоновом режиме без окна.

Работу MySQL-сервера можно остановить командой:

C:\> C:\mysql\bin\mysqladmin -u root shutdown

Это вызов программы администрирования MySQL от имени пользователя root, который по умолчанию соответствует пользователю Administrator в системе привилегий MySQL. Обратите внимание: система привилегий MySQL абсолютно независима от каких-либо аккаунтов пользователей в среде Windows.

Заметим, что в Windows 95/98/Me не поддерживается создание именованных каналов. Таким образом, именованные каналы вы можете использовать для соединения с MySQL-сервером, работающем в системе Windows NT/2000/XP. (Разумеется, MySQL-сервер также должен поддерживать именованные каналы. Например, при работе mysqld-opt в системе NT/2000/XP нельзя создавать соединения с использованием именованных каналов; следует применять либо mysqld-nt, либо mysqld-max-nt.)

Если mysqld не запускается, следует проверить файл `\mysql\data\mysql.err', на предмет записей, сделанных сервером, - они содержат объяснения причин, вызвавших проблему. Можно также попробовать запустить сервер командой mysqld --standalone; в этом случае на экран будет выводиться некоторая полезная информация, которая может помочь решить проблему.

В качестве последней попытки можно попробовать запустить mysqld с флагами --standalone --debug. В этом случае mysqld будет помещать записи в файл отладки `C:\mysqld.trace'. Возможно, по содержимому этого файла вы сумеете определить причину, по которой не запускается mysqld. See section D.1.2 Создание трассировочных файлов.

Для вывода всех флагов, которые ``понимает'' mysqld, используйте команду mysqld --help.

2.6.2.2 Запуск MySQL на Windows NT, 2000 или XP

Для того чтобы MySQL работал с TCP/IP на Windows NT 4, необходимо установить Service Pack 3 (или выше)!

Обычно MySQL устанавливается на Windows NT/2000/XP как сервис. В случае, если сервер уже работает, необходимо сначала завершить его работу при помощи следующей команды:

C:\mysql\bin> mysqladmin -u root shutdown

Это вызов программы администрирования MySQL от имени пользователя root, который по умолчанию соответствует пользователю Administrator в системе привилегий MySQL. Обратите внимание: система привилегий MySQL абсолютно независима от каких-либо аккаунтов пользователей в системе Windows.

Теперь установим сервис сервера:

C:\mysql\bin> mysqld-max-nt --install

Если требуются какие-либо опции, они должны быть определены, как ``Start parameters'' в инструментальной программе Services системы Windows перед запуском сервиса MySQL.

Доступ к инструментальной программе Services (Windows Service Control Manager) можно получить в Control Panel (в Administrative Tools в Windows 2000). Рекомендуется закрывать Services при выполнении операций --instal или --remove - это предотвратит возникновение некоторых ошибок неизвестной природы.

За информацией о том, какие бинарные файлы следует использовать для запуска сервера, обращайтесь к разделу See section 2.1.2.2 Подготовка конфигурации MySQL для Windows.

Отметим, что начиная с версии 3.23.44 MySQL имеется возможность альтернативной установки сервиса - в режиме Manual (если вам не требуется автоматический запуск сервиса при загрузке операционной системы):

C:\mysql\bin> mysqld-max-nt --install-manual

Сервис устанавливается под именем MySQL. Сразу же после установки он может быть запущен при помощи инструментальной программы Services или командой NET START MySQL.

После запуска работа mysqld-max-nt может быть завершена при помощи mysqladmin из инструментальной программы Services или командой NET STOP MySQL.

Если MySQL функционирует в качестве сервиса, то операционная система автоматически завершает работу MySQL-сервиса при программном завершении работы компьютера. В версиях MySQL < 3.23.47 Windows ожидает всего лишь несколько секунд завершения остановки, после чего уничтожает процесс сервера базы данных, если превышено время ожидания (что может быть потенциальной причиной возникновения проблем). Например, при следующем запуске обработчик таблицы InnoDB должен выполнять восстановление после аварийного завершения. Начиная с MySQL версии 3.23.48, Windows ожидает завершения процесса MySQL-сервера дольше. Если вы считаете, что этого времени для вашей версии недостаточно, безопаснее запускать MySQL-сервер не как сервис, а из командной строки и завершать его работу командой mysqladmin shutdown.

В Windows NT (но не в Windows 2000/XP) существует проблема, которая заключается в том, что система по умолчанию ожидает окончания работы сервиса только 20 секунд, после чего уничтожает процесс сервиса. Это заданное по умолчанию значение можно увеличить с помощью редактора Registry (Реестра), запустив `\winnt\system32\regedt32.exe' и отредактировав значение WaitToKillServiceTimeout в записи HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control. Следует задать другое, большее значение в миллисекундах, например 120000, чтобы Windows NT ожидала 120 секунд.

Необходимо заметить, что при работе в качестве сервиса mysqld-max-nt не имеет доступа к консоли, а следовательно, невозможно увидеть его сообщения. Информация об ошибках находится в файле `c:\mysql\data\mysql.err'.

Если вы столкнулись с проблемами установки mysqld-max-nt в качестве сервиса, попробуйте запустить его с указанием полного пути:

C:\> C:\mysql\bin\mysqld-max-nt --install

Если это не поможет, можно принудить mysqld-max-nt стартовать соответствующим образом, исправив путь в Registry!

Если вы не хотите запускать mysqld-max-nt в качестве сервиса, его можно запустить следующим образом:

C:\> C:\mysql\bin\mysqld-max-nt --standalone
или
C:\> C:\mysql\bin\mysqld --standalone --debug

В случае последнего варианта вы получите отладочную информацию в `C:\mysqld.trace'. See section D.1.2 Создание трассировочных файлов.

2.6.2.3 Работа MySQL в среде Windows

MySQL поддерживает TCP/IP на всех Windows-системах и именованные каналы в среде NT/2000/XP. По умолчанию MySQL использует именованные каналы для соединений с локальной машиной в среде NT/2000/XP и TCP/IP - во всех остальных случаях, если на клиентской машине установлен TCP/IP. Имя машины определяет используемый протокол:

Имя машины | Протокол
NULL(отсутствует) | На NT/2000/XP пытается установить соединение через именованные каналы; если это не работает, используется TCP/IP. На 9x/Me используется TCP/IP.
. | Именованные каналы.
localhost | Соединение TCP/IP с локальной машиной
имя удаленной машины | TCP/IP

Чтобы заставить MySQL-клиента использовать именованные каналы, следует добавить опцию --pipe или задать . в качестве имени машины для соединения. Для определения имени канала используйте опцию --socket. В MySQL 4.1 вам следует использовать опцию --protocol=PIPE.

Отметим, что начиная с версии 3.23.50 именованные каналы применяются только в случае, если mysqld запущен с опцией --enable-named-pipe. Это вызвано тем, что у некоторых пользователей применение именованных каналов приводило к прекращению работы сервера MySQL.

Для проверки работоспособности MySQL нужно выполнить следующие команды:

C:\> C:\mysql\bin\mysqlshow
C:\> C:\mysql\bin\mysqlshow -u root mysql
C:\> C:\mysql\bin\mysqladmin version status proc
C:\> C:\mysql\bin\mysql test

Если при ответе mysqld на входящие соединения под Windows 9x/Me возникают задержки, то это, скорее всего, вызвано проблемами с вашим DNS. В таком случае следует запускать mysqld с опцией --skip-name-resolve и в таблицах привилегий MySQL использовать только localhost и IP-адреса. Избежать работы с DNS при соединении с MySQL-сервером mysqld-nt, работающим под NT/2000/XP, можно путем применения опции --pipe, которая задает использование именованных каналов. Сказанное выше справедливо для большинства клиентов MySQL.

Существует две версии программы работы с MySQL из командной строки:

Бинарный файл | Описание
mysql | Собран ``родными'' средствами Windows, обеспечивает весьма ограниченные возможности редактирования текста.
mysqlc | Собран с использованием компилятора и библиотек Cygnus GNU, которые обеспечивают редактор readline.

Если вы хотите использовать `mysqlc.exe', сначала необходимо скопировать `C:\mysql\lib\cygwinb19.dll' в системный каталог Windows (`\windows\system' или в другое аналогичное место).

По умолчанию всем пользователям Windows предоставляются полные права доступа ко всем базам данных без ввода пароля. Чтобы обеспечить большую безопасность MySQL, необходимо задать пароль для каждого пользователя и удалить запись в таблице mysql.user, содержащую Host='localhost' и User=' `.

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

C:\> C:\mysql\bin\mysql mysql
mysql> DELETE FROM user WHERE Host='localhost' AND User=' ';
mysql> QUIT
C:\> C:\mysql\bin\mysqladmin reload
C:\> C:\mysql\bin\mysqladmin -u root password your_password

Если вы хотите остановить сервер mysqld после того, как установлен пароль для пользователя root, нужно использовать команду:

C:\> mysqladmin --user=root --password=your_password shutdown

Если у вас работает старая испытательная версия MySQL 3.21 под Windows, вышеприведенная команда не выполнится и приведет к сообщению об ошибке: parse error near `SET password'. Для решения этой проблемы следует выполнить загрузку и обновление до последней доступной бесплатно версии MySQL.

В текущей версии MySQL вы можете легко добавлять новых пользователей и изменять их привилегии при помощи команд GRANT и REVOKE (see section 4.3.1 Синтаксис команд GRANT и REVOKE).

2.6.2.4 Соединение с MySQL на удаленной машине под Windows с использованием SSH

В этом разделе приведены замечания относительно получения безопасного соединения с удаленным MySQL-сервером с использованием SSH. Автором этих замечаний является Дэвид Карлсон (David Carlson) - dcarlson@mplcomm.com:

  • Установите 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/CryptographySSH/Clients/Windows/
  • Запустите Windows-клиент SSH. Установите Host_Name=адрес_своего_MySQL-сервера. Задайте userid=свой_userid для соединения со своим сервером (может отличатся от вашего имени пользователя/пароля для MySQL).
  • Задайте перенаправление портов или организуйте удаленный форвардинг (нужно сделать следующие установки: локальный порт - 3306, удаленный хост - адреса_вашего_mysql_сервера, удаленный порт - 3306) либо локальный форвардинг (порт - 3306, хост - localhost, удаленный порт - 3306).
  • Сохраните выполненные установки, иначе вам придется в следующий раз делать все заново.
  • Соединитесь со своим сервером, используя только что созданный вами SSH-сеанс.
  • Запустите в Windows какое-либо ODBC-приложение (например Access).
  • Создайте в Windows новый файл и ссылку на MySQL, используя ODBC-драйвер обычным образом, за исключением того, что вместо имени вашего MySQL-сервера следует указывать localhost, а не yourmysqlservername.

В результате этих действий вы должны получить ODBC-соединение со своим MySQL-сервером, защищенное при помощи SSH-кодирования.

2.6.2.5 Распределение данных в Windows между несколькими различными дисками

Начиная с MySQL версии 3.23.16 серверы mysqld-max и mysql-max-nt в дистрибутиве MySQL компилируются с флагом -DUSE_SYMDIR. Это обеспечивает возможность устанавливать базу данных на другом диске путем добавления символической ссылки на нее (подобно тому, как работают символические ссылки в Unix).

В Windows для создания символической ссылки на базу данных создается файл, содержащий путь к каталогу, на который указывает ссылка. Этот файл сохраняется в каталоге `mysql_data' под именем `database.sym'. Отметим, что такая символическая ссылка будет работать только в случае отсутствия каталога `mysql_data_dir\database'.

Например, если каталог данных MySQL находится в `C:\mysql\data', а вы хотите разместить базу данных foo в каталоге `D:\data\foo', необходимо создать файл `C:\mysql\data\foo.sym', содержащий текст `D:\data\foo\'. После этого все таблицы, создаваемые в базе данных foo, будут создаваться в `D:\data\foo'.

Отметим, что из-за потерь в скорости при открытии каждой таблицы в MySQL не включается использование символических ссылок по умолчанию, даже если вы собрали MySQL с поддержкой данной возможности. Чтобы обеспечить возможность разрешения символических ссылок, вы должны поместить в свой файл `my.cnf' или `my.ini' следующие строки:

[mysqld]
use-symbolic-links

В MySQL 4.0 использование символических ссылок по умолчанию будет включено. Если вы хотите запретить эту возможность, то для данной версии MySQL необходимо использовать опцию skip-symlink.

2.6.2.6 Компиляция MySQL-клиентов в среде Windows

В файлах исходных текстов следует перед `mysql.h' включить `windows.h':

#if defined(_WIN32) || defined(_WIN64)
#include <windows.h>
#endif
#include <mysql.h>

Линковать свою программу можно либо с использованием динамической библиотеки `libmysql.lib', которая является просто оболочкой для загрузки `libmysql.dll' по требованию, либо со статической библиотекой `mysqlclient.lib'.

Отметим, что поскольку библиотеки mysqlclient компилируются как потоковые библиотеки, следует скомпилировать вашу программу так, чтобы была разрешена многопочность!

2.6.2.7 Сравнительные характеристики MySQL под Windows и под Unix

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

Windows 95 и потоки
При создании каждого потока в Windows 95 теряется приблизительно 200 байтов основной памяти. А поскольку каждое соединение с MySQL создает новый поток, на Windows 95 не следует запускать mysqld на продолжительное время, если ваш сервер обрабатывает много соединений! Другие версии Windows не подвержены этой ошибке.
Параллельное чтение
Для обработки смешанных запросов SELECT и INSERT в MySQL используются функции pread() и pwrite(). В настоящее время для эмуляции pread()/pwrite() мы применяем mutex'ы. Однако в наши планы на будущее входит замена интерфейса файлового уровня виртуальным интерфейсом, чтобы иметь возможность использовать интерфейс readfile()/writefile() на NT/2000/XP - с целью ускорения работы. В текущей реализации число одновременно открытых в MySQL файлов не может быть больше 1024; это означает, что вы не сможете создать такое же количество одновременных соединений с MySQL в NT/2000/XP, как в Unix.
Чтение с блокировкой
В MySQL для каждого соединения используется чтение с блокировкой. Это означает, что:
  • Соединение не будет автоматически закрыто по истечении 8 часов, как в случае Unix-версии MySQL.
  • В случае ``зависания'' соединения невозможно оборвать его без остановки MySQL.
  • mysqladmin kill не работает для ``спящих'' соединений
  • mysqladmin shutdown не может отработать до тех пор, пока существуют ``спящие'' соединения.
Перечисленные проблемы мы планируем решить, когда наши разработчики под Windows придумают изящный способ их решения.
DROP DATABASE
Нельзя удалить базу данных, если она используется каким-либо потоком.
Остановка MySQL из диспетчера задач
В Windows 95 нельзя остановить MySQL из диспетчера задач или с помощью инструментальной программы shutdown; это можно сделать с помощью mysqladmin shutdown.
Имена, не зависящие от регистра символов
Имена файлов в Windows не зависят от регистра символов, поэтому имена таблиц и баз данных в MySQL под Windows также не зависимы от регистра. Единственное ограничение заключается в том, что имена баз данных и таблиц в пределах одного выражения должны задаваться с использованием одинакового регистра символов (see section 6.1.3 Чувствительность имен к регистру).
Символ каталогов `\'
Компоненты путей в Windows 95 разделяются символом `\', который также является символом экранирования в MySQL. Если вы используете LOAD DATA INFILE или SELECT ... INTO OUTFILE, символ `\' необходимо вводить дважды:
mysql> LOAD DATA INFILE "C:\\tmp\\skr.txt" INTO TABLE skr;
mysql> SELECT * INTO OUTFILE 'C:\\tmp\\skr.txt' FROM skr;
В качестве альтернативы можно использовать имена файлов Unix-стиля:
mysql> LOAD DATA INFILE "C:/tmp/skr.txt" INTO TABLE skr;
mysql> SELECT * INTO OUTFILE 'C:/tmp/skr.txt' FROM skr;
Ошибка can't open named pipe (невозможно открыть именованный канал)
При использовании MySQL версии 3.22 на NT с самым свежим клиентом mysql можно получить следующее сообщение об ошибке:
error 2017: can't open named pipe to host: . pipe...
Это происходит из-за того, что в данной версии MySQL на NT именованные каналы применяются по умолчанию. Чтобы избежать таких ошибок, следует использовать с новым клиентом MySQL флаг --host=localhost или создать файл флагов `C:\my.cnf', содержащий следующие строки:
[client]
host = localhost
Начиная с версии 3.23.50 именованные каналы используются только в случае, если mysqld запущен с флагом --enable-named-pipe.
Ошибка access denied for user (доступ пользователю запрещен)
Если вы получили сообщение об ошибке Access denied for user: `some-user@unknown' to database `mysql' при попытке доступа к MySQL-серверу, находящемуся на той же машине, с которой происходит доступ, это значит, что MySQL не может правильно определить адрес вашей машины. Для решения данной проблемы следует создать файл `\windows\hosts', содержащий:
127.0.0.1 localhost
ALTER TABLE
При выполнении оператора ALTER TABLE доступ к таблице для других потоков блокируется. Именно поэтому Windows не может удалить файл, который используется другим потоком (возможно, в будущем мы найдем какой-нибудь способ обойти эту проблему). Выполнение DROP TABLE над таблицей, входящей в состав сводной таблицы MERGE, не будет работать в Windows, так как отображение таблицы, которое выполняет обработчик MERGE, скрыто от верхнего уровня MySQL. Поскольку в Windows нельзя удалять открытые файлы, вначале следует сбросить все MERGE-таблицы (используя FLUSH TABLES) или удалить все MERGE-таблицы перед удалением таблицы. Мы исправим эту ошибку одновременно с введением оператора VIEW. Операторы DATA DIRECTORY и INDEX DIRECTORY в CREATE TABLE в Windows игнорируются, поскольку Windows не поддерживает символические ссылки.

Ниже приведены некоторые открытые вопросы для всех, кто захочет помочь нам в работе над выпусками под Windows:

  • Требуется создать однопользовательский сервер `MYSQL.DLL'. Он должен включать все возможности стандартного MySQL-сервера, за исключением потоков. Это заметно упростит использование MySQL в приложениях, которые не нуждаются в настоящем клиент-серверном взаимодействии и в доступе к базе с других машин.
  • Нужно было бы добавить в инсталляционный пакет нескольких симпатичных иконок для старта и остановки MySQL.
  • При регистрации mysqld в качестве сервиса с флагом --install (на NT) было бы неплохо иметь возможность добавлять флаги по умолчанию к командной строке. Сейчас эта проблема решается путем записи списка параметров в файл `C:\my.cnf'.
  • Было бы удобно останавливать mysqld из диспетчера задач. Сейчас для этого нужно применять mysqladmin shutdown.
  • Требуется перенести readline в Windows для использования с инструментальной программой, запускаемой из командной строки mysql.
  • GUI версия стандартных MySQL-клиентов (mysql, mysqlshow, mysqladmin и mysqldump) будет очень полезна.
  • Было бы хорошо, если бы чтение и запись сокетов из `net.c' можно было бы прерывать. Это позволило бы останавливать открытые потоки командой mysqladmin kill в Windows.
  • mysqld всегда стартует в местоположении "C", а не в местоположении, установленном по умолчанию. С благодарностью будет принято исправление, позволяющее использование программой mysqld текущего значения местоположения для порядка сортировки.
  • Требуется добавить макрос для ускорения безопасного для потоков метода инкремента/декремента, обеспечиваемого Windows.
  • Остальные, специфические для Windows вопросы, можно найти в файле README, который находится в поставке MySQL-Windows.

2.6.3 Примечания к Solaris

В системе Solaris проблемы подстерегают вас еще до распаковки дистрибутива MySQL! Программа tar в Solaris ``не умеет'' работать с длинными именами файлов, поэтому при попытке распаковать MySQL вы можете увидеть сообщение об ошибке, подобное следующему:

x mysql-3.22.12-beta/bench/Results/ATIS-mysql_odbc-NT_4.0-cmp-db2,\
informix,ms-sql,mysql,oracle,solid,sybase, 0 bytes, 0 tape blocks
tar: directory checksum error

В этом случае для распаковки дистрибутива необходимо использовать GNU-версию программы tar (gtar). Скомпилированную версию данной программы для Solaris можно загрузить с http://www.mysql.com/downloads/os-solaris.html.

Собственные потоки Sun работают только начиная с версии Solaris 2.5. Для версии 2.4 и более ранних MySQL автоматически использует MIT-pthreads (see section 2.3.6 Замечания по потокам MIT-pthreads).

Следующее сообщение об ошибке конфигурации:

checking for restartable system calls... configure: error can not run test
programs while cross compiling

означает, что имели место какие-то ошибки в установке компилятора! В этом случае необходимо обновить ваш компилятор до более свежей версии. Эту проблему можно также решить, вставив в файл `config.cache' следующую строку:

ac_cv_sys_restartable_syscalls=${ac_cv_sys_restartable_syscalls='no'}

При использовании Solaris на SPARC мы рекомендуем компилятор gcc 2.95.2. Его можно получить по адресу http://gcc.gnu.org/. Отметим, что egcs 1.1.1 и gcc 2.8.1 работают на SPARC ненадежно!

Рекомендуемая строка для configure при использовании gcc 2.95.2:

CC=gcc CFLAGS="-O3" \
CXX=gcc CXXFLAGS="-O3 -felide-constructors -fno-exceptions -fno-rtti" \
./configure --prefix=/usr/local/mysql --with-low-memory --enable-assembler

Если используется UltraSPARC, то при добавлении строки "-mcpu=v8 -Wa,-xarch=v8plusa" к переменным CFLAGS и CXXFLAGS можно получить повышение производительности на 4%.

При использовании компилятора Sun Fortre версии 5.0 (или выше) можно запускать configure следующим образом:

CC=cc CFLAGS="-Xa -fast -xO4 -native -xstrconst -mt" \
CXX=CC CXXFLAGS="-noex -xO4 -mt" \
./configure --prefix=/usr/local/mysql --enable-assembler

Можно создать 64-разрядный исполняемый код с помощью:

CC=cc CFLAGS="-Xa -fast -native -xstrconst -mt -xarch=v9" \
CXX=CC CXXFLAGS="-noex -mt -xarch=v9" ASFLAGS="-xarch=v9" \
./configure --prefix=/usr/local/mysql --enable-assembler

В тестах на производительность MySQL с Sun Fortre 5.0 мы получили 4%-ное ускорение на UltraSPARC по сравнению с gcc 3.2 с опцией -mcpu.

Если вы создаете 64-разрядный код, он на 4% медленнее чем 32-разрядный, но mysqld можно обслуживать больше потоков и использовать больше памяти.

В случае возникновения проблем с fdatasync или sched_yield их можно решить путем добавления LIBS=-lrt к командной строке запуска конфигурирования.

Последующий абзац относится только к более ранним, чем WorkShop 5.3, компиляторам:

Отредактировать скрипт configure можно, заменив строку:

#if !defined(__STDC__) || __STDC__ != 1

строкой:

#if !defined(__STDC__)

При включении __STDC__ с помощью опции -Xc компилятор Sun не сможет откомпилировать программу с файлом `pthread.h' из системы Solaris. Это ошибка Sun (испорченный компилятор или испорченный включаемый файл).

Если при запуске mysqld выдает приведенное ниже сообщение об ошибке:

libc internal error: _rmutex_unlock: rmutex not held

необходимо попробовать собрать MySQL, используя компилятор Sun с опцией запрещения многопоточности (-mt). Добавьте опцию -mt к CFLAGS и CXXFLAGS и попробуйте запустить mysqld еще раз.

При использовании SFW версии gcc (поставляемой с Solaris 8) необходимо к переменной окружения LD_LIBRARY_PATH перед конфигурированием добавить `/opt/sfw/lib'.

При работе с gcc от sunfreeware.com может возникнуть множество неприятностей. Во избежание проблем необходимо перекомпилировать gcc и бинарные инструментальные программы GNU в той системе, где вы собираетесь их использовать.

Получение нижеследующей ошибки при компиляции MySQL компилятором gcc означает, что gcc не сконфигурирован под вашу версию Solaris:

shell> gcc -O3 -g -O2 -DDBUG_OFF -o thr_alarm ...
./thr_alarm.c: In function `signal_hand':
./thr_alarm.c:556: too many arguments to function `sigwait'

В этом случае нужно взять самую свежую версию gcc и скомпилировать ее установленным gcc-компилятором! Почти все бинарные версии gcc (по крайней мере для Solaris 2.5) содержат старые, непригодные к использованию включаемые файлы, которые портят все программы, использующие потоки (а возможно, и другие программы)!

В Solaris не обеспечиваются статические версии всех системных библиотек (libpthreads и libdl), поэтому компилировать MySQL с опцией -static нельзя. При попытке такой компиляции вы получите одно из приведенных ниже сообщений об ошибке:

ld: fatal: library -ldl: not found
или
undefined reference to `dlopen'
или
cannot find -lrt

Если слишком много процессов одновременно пытаются установить соединение с mysqld, то в файле протокола MySQL появится следующее сообщение об ошибке:

Error in accept: Protocol error

Для решения этой проблемы можно попытаться запустить сервер с опцией --set-variable back_log=50. Внимание: --set-variable не используется в MySQL 4.0. Просто используйте --back_log=50. See section 4.1.1 Параметры командной строки mysqld.

Если вы линкуете собственный MySQL-клиент, то при попытке его запустить может выдаваться следующее сообщение об ошибке:

ld.so.1: ./my: fatal: libmysqlclient.so.#:
open failed: No such file or directory

Проблему можно решить одним из следующих способов:

  • Линковать клиент со следующими опциями (вместо -Lpath): -Wl,r/полный-путь-к-libmysqlclient.so.
  • Скопировать `libmysqclient.so' в `/usr/lib'.
  • Перед запуском своего клиента добавить путь к каталогу, в котором находится `libmysqclient.so', к переменной окружения LD_RUN_PATH.

Если вы столкнулись с проблемами конфигурирования, пытаясь линковать с опцией -lz и у вас не установлена zlib, существует два варианта:

  • Если вы хотите иметь возможность использовать протокол взаимодействия со сжатием, необходимо получить и установить zlib с ftp.gnu.org.
  • Сконфигурировать с --with-named-z-libs=no.

Если при использовании gcc вы столкнулись с проблемами загрузки UDF-функций в MySQL, попробуйте добавить -lgcc к строке, отвечающей за линкование UDF-функций.

Для того чтобы MySQL-сервер стартовал автоматически, можно скопировать `support-files/mysql.server' в `/etc/init.d' и создать на него символическую ссылку `/etc/rc3.d/S99mysql.server'.

Поскольку Solaris не поддерживает файлы образа памяти для приложений, использующих setuid(), невозможно получить файл образа памяти программы mysqld при использовании опции --user.

2.6.3.1 Примечания к Solaris 2.7/2.8

На Solaris 2.7 и 2.8 можно нормально использовать бинарные файлы для Solaris 2.6. Большинство вопросов по работе с Solaris 2.6 относятся также и к Solaris 2.7 и 2.8.

Необходимо отметить, что MySQL версии 3.23.4 и последующих может автоматически определять новые версии Solaris и избегать описанных ниже проблем!

В Solaris 2.7/2.8 имеются некоторые ошибки во включаемых файлах. При использовании gcc вы можете получить следующие сообщения об ошибках:

/usr/include/widec.h:42: warning: `getwc' redefined
/usr/include/wchar.h:326: warning: this is the location of the previous definition

В этом случае для исправления ошибки нужно выполнить следующие действия:

Скопируйте /usr/include/widec.h в .../lib/gcc-lib/os/gcc-version/include и измените строку с номером 41, содержащую:

#if !defined(lint) && !defined(__lint)

на

#if !defined(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.cc:50:
/usr/include/term.h:1060: syntax error before `,'
/usr/include/term.h:1081: syntax error before `;'

Решить эту проблему можно одним из способов:

  • Конфигурировать с CFLAGS=-DHAVE_CURSES_H CXXFLAGS=-DHAVE_CURSES_H ./configure (эта запись должна быть цельной строкой, без пробелов).
  • Отредактировать `/usr/include/widec.h', как описано выше, и перезапустить configure.
  • Удалить строку #define HAVE_TERM из `config.h' и запустить make повторно.

Если редактор связей не может обнаружить -lz при линковании вашей клиентской программы, то проблема, возможно, заключается в том, что файл `libz.so' установлен в `/usr/local/lib'. Данную проблему можно решить любым из приведенных выше способов:

  • Добавить `/usr/local/lib' к LD_LIBRARY_PATH.
  • Создать ссылку на `libz.so' из `/lib'.
  • Если используется Solaris 8, можно установить необязательную библиотеку zlib с CD-диска с дистрибутивом Solaris 8.
  • Конфигурировать MySQL с опцией --with-named-z-libs=no.

2.6.3.2 Примечания к Solaris x86

На Solaris 2.8 на x86-й архитектуре mysqld аварийно завершится с сохранением образа памяти на диске, если он обработан программой strip.

Если при использовании gcc или 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 (see section D.1.3 Отладка mysqld при помощи gdb).

2.6.4 Примечания к BSD

В этом разделе находится информация относительно различных BSD-систем, а также конкретных версий этих систем.

2.6.4.1 Примечания к FreeBSD

Для работы Mysql рекомендуется FreeBSD версий 3.x, поскольку версия с потоками является намного более интегрированной.

Простейшим, а поэтому и более предпочтительным способом установки является использование портов mysql-server и mysql-client из коллекции портов FreeBSD, которая доступна по адресу http://www.freebsd.org/.

Использование этих портов обеспечивает:

  • работоспособный MySQL со всеми возможностями оптимизации, доступными на данной версии FreeBSD;
  • автоматическую конфигурацию и сборку;
  • установку скриптов, запускающих MySQL, в `/usr/local/etc/rc.d';
  • возможность получения списка установленных файлов по команде pkg_info -L и удаления их при помощи команды pkg_delete в случае, если вы более не нуждаетесь в MySQL на данной машине.

Рекомендуется использовать MIT-pthreads на FreeBSD версий 2.x и собственные потоки для 3.x и более поздних версий FreeBSD. На некоторых последних версиях 2.2.x возможно применение собственных потоков, но при этом не исключены проблемы с остановкой mysqld.

Для сборки MySQL в соответствии с Makefile'ом необходима программа GNU make (gmake). Прежде чем выполнять сборку MySQL, следует установить GNU make.

Удостоверьтесь, что используемый вами сервер имен работает корректно. В противном случае возможны задержки или ошибки при соединении с mysqld.

Убедитесь в корректности записи localhost в файле `/etc/hosts' (при отсутствии или ошибочности этой записи возникнут проблемы соединения с базой). Файл `/etc/hosts' должен начинаться с записи:

127.0.0.1 localhost localhost.your.domain

Предлагаемый способ сборки и установки MySQL на FreeBSD с использованием gcc (версии 2.95.2 или более поздней):

CC=gcc CFLAGS="-O2 -fno-strength-reduce" \
CXX=gcc CXXFLAGS="-O2 -fno-rtti -fno-exceptions -felide-constructors \
-fno-strength-reduce" \
./configure --prefix=/usr/local/mysql --enable-assembler
gmake
gmake install
./scripts/mysql_install_db
cd /usr/local/mysql
./bin/mysqld_safe &

Если программа configure решила использовать MIT-pthreads, необходимо ознакомится с примечаниями по MIT-pthreads (see section 2.3.6 Замечания по потокам MIT-pthreads).

Если при выполнении make install возникла ошибка, сообщающая о невозможности нахождения `/usr/include/pthreads' (can't find `/usr/include/pthreads'), это значит, что configure не определил необходимость использования MIT-pthreads. Для исправления данной ошибки необходимо выполнить следующие команды:

shell> rm config.cache
shell> ./configure --with-mit-threads

Как известно, в FreeBSD по умолчанию установлено очень небольшое значение для количества одновременно открытых файлов (see section A.2.16 Не найден файл (File not found)). Чтобы исправить положение, следует раскомментировать секцию ulimit -n в скрипте safe_mysqld или повысить ограничение для пользователя mysqld в `/etc/login.conf' (не забудьте перестроить его командой cap_mkdb `/etc/login.conf'). Помимо этого, имеет смысл проверить установку подходящего класса для этого пользователя в файле паролей, если не используется значение по умолчанию (при помощи chpass mysqld-user-name). See section 4.7.2 safe_mysqld, оболочка mysqld.

При наличии значительного объема оперативной памяти можно рассмотреть вариант перестройки ядра, чтобы разрешить MySQL использовать более чем 512Mб оперативной памяти. Чтобы получить больше информации, обратитесь к option MAXDSIZ в конфигурационном файле LINT.

В случае возникновения проблем с текущей датой в MySQL ситуацию может исправить правильная установка переменной TZ. See section E Переменные окружения.

Для получения безопасной и устойчивой системы следует использовать только те ядра системы FreeBSD, которые обозначены как -RELEASE.

2.6.4.2 Примечания к NetBSD

Для компиляции на NetBSD необходимо, чтобы была установлена программа GNU make. В противном случае компиляция завершится аварийно при попытке make запустить lint на файлах 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 file descriptor или ошибки 9 при попытке открыть таблицу либо каталог означает, что вы не заказали достаточно дескрипторов файлов для MySQL.

В этом случае попробуйте запустить safe_mysqld от имени пользователя root с опциями:

--user=mysql --open-files-limit=2048

2.6.4.5 Примечания к BSD/OS версий 2.x

Получение приведенной ниже ошибки при компиляции MySQL означает, что установленное с помощью ulimit значение размера виртуальной памяти слишком мало:

item_func.h: In method `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.

Если вы используете gcc, то, возможно, необходимо добавить флаг --with-low-memory при запуске configure, чтобы обеспечить возможность компиляции `sql_yacc.cc'.

При возникновении проблем с текущей датой в MySQL может помочь установка переменной TZ (see section E Переменные окружения).

2.6.4.6 Примечания к BSD/OS версий 3.x

Для конфигурирования MySQL следует использовать следующую команду:

shell> env CXX=shlicc++ CC=shlicc2 \
       ./configure \
           --prefix=/usr/local/mysql \
       --localstatedir=/var/mysql \
       --without-perl \
       --with-unix-socket-path=/var/mysql/mysql.sock

Сработает и следующая командная строка:

shell> env CC=gcc CXX=gcc CXXFLAGS=-O3 \
       ./configure \
           --prefix=/usr/local/mysql \
       --with-unix-socket-path=/var/mysql/mysql.sock

При желании вы можете изменить местоположение каталогов или использовать значения по умолчанию, не определяя никаких путей.

Если возникнут проблемы с производительностью при большой нагрузке, попробуйте при запуске mysqld использовать опцию --skip-thread-priority! Применение данной опции приведет к тому, что все потоки будут работать с одинаковым приоритетом; на BSDI версии 3.1 это обеспечивало повышение производительности (по крайней мере, пока не был исправлен планировщик потоков).

В случае получения сообщения об ошибке 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 на этой системе, необходимо предварительно установить все патчи, относящиеся к реализации потоков. По крайней мере, должен быть установлен M400-023.

На некоторых системах BSDI версий 4.x вы можете столкнуться с проблемами при использовании динамических библиотек. Проявляется это как невозможность выполнить какую-либо клиентскую программу, например mysqladmin. В данном случае необходимо переконфигурировать MySQL с запретом использовать динамические библиотеки, указав для скрипта configure опцию --disable-shared.

Некоторые пользователи сообщали нам о проблемах на BSDI 4.0.1, которые проявляются в том, что через некоторое время после начала работы mysqld не может открыть таблицы. Это происходит потому, что из-за какой-то системной или библиотечной ошибки mysqld изменяет текущий каталог без какого-либо запроса!

Для решения проблемы необходимо либо обновить MySQL до версии 3.23.34, либо после запуска configure удалить строку #define HAVE_REALPATH из файла `config.h' перед запуском make.

Отметим, что вышеописанные действия приведут к невозможности создать символическую ссылку из одних каталогов базы данных на другой каталог базы данных или символическую ссылку на таблицу в другой базе данных на BSDI! (Создание символической ссылки на другой диск допускается.)

2.6.5 Примечания к Mac OS X

2.6.5.1 Mac OS X 10.x

На Mac OS X 10.x MySQL должен работать без каких-либо проблем. Для этой операционной системы нет необходимости в патчах к pthread!

Это также касается Mac OS X 10.x Server. Компиляция для серверной платформы ничем не отличается от компиляции для клиентской версии. Однако учтите, что Mac OS X Server поставляется с предустановленным MySQL.

See section 2.1.3 Установка MySQL на MacOS X.

2.6.5.2 Mac OS X Server 1.2 (Rhapsody)

Прежде чем попытаться отконфигурировать MySQL на сервере Mac OS X, необходимо установить пакет pthread, который находится по адресу http://www.prnet.de/RegEx/mysql.html.

Наши бинарные файлы для Mac OS X компилируются на Rhapsody 6.3 со следующими конфигурационными параметрами:

CC=gcc CFLAGS="-O3 -fno-omit-frame-pointer" CXX=gcc \
CXXFLAGS="-O3 -fno-omit-frame-pointer -felide-constructors \
-fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql \
--with-extra-charsets=complex --enable-thread-safe-client \
--enable-local-infile --disable-shared

Возможно, вам понадобится добавить псевдонимы в файл ресурсов оболочки - для доступа к mysql и mysqladmin из командной строки:

alias mysql '/usr/local/mysql/bin/mysql'
alias mysqladmin '/usr/local/mysql/bin/mysqladmin'

Или же вы можете просто добавить путь /usr/local/mysql/bin к переменной окружения PATH, скажем, путем добавления в файл `$HOME/.tcshrc':

setenv PATH $PATH:/usr/local/bin

2.6.6 Примечания к другим Unix-системам

2.6.6.1 Примечания к бинарному дистрибутиву HP-UX

Некоторые бинарные поставки MySQL для HP-UX распространяются как файлы HP depot и tar. Для использования файла depot у вас должна быть установлена версия HP-UX не выше 10.x - для того, чтобы обеспечить возможность работы с HP-инструментарием работы с depot-файлами.

Версия MySQL для HP была скомпилирована на сервере HP 9000/8xx в системе HP-UX 10.20 с использованием MIT-pthreads. Известно, что она хорошо работает в этой конфигурации. MySQL версии 3.22.26 и выше можно также собрать с использованием собственных потоков HP.

Другие конфигурации, на которых возможна работа MySQL:

  • HP 9000/7xx running HP-UX 10.20+
  • HP 9000/8xx running HP-UX 10.30

На следующих конфигурациях MySQL, скорее всего, работать не будет:

  • HP 9000/7xx or 8xx running HP-UX 10.x where x < 2
  • HP 9000/7xx or 8xx running HP-UX 9.x

Для установки дистрибутива используйте одну из представленных ниже команд; здесь /path/to/depot - полный путь к depot-файлу:

  • Для полной установки, включая сервер, клиент и инструментарий разработчика:
    shell> /usr/sbin/swinstall -s /path/to/depot mysql.full
  • Для установки только сервера:
    shell> /usr/sbin/swinstall -s /path/to/depot mysql.server
  • Для установки только клиентского пакета:
    shell> /usr/sbin/swinstall -s /path/to/depot mysql.client
  • Для установки только инструментария разработчика:
    shell> /usr/sbin/swinstall -s /path/to/depot mysql.developer

depot помещает бинарные исполняемые файлы и библиотеки в `/opt/mysql', а данные - в `/var/opt/mysql'. depot также создает соответствующие строки в `/etc/init.d' и `/etc/rc2.d' для автоматического запуска сервера при загрузке машины. Очевидно, что для установки необходимо обладать правами пользователя root.

Для установки на HP-UX дистрибутива tar.gz на машине должен быть установлен GNU tar.

2.6.6.2 Примечания к HP-UX версии 10.20

При компиляции MySQL на HP-UX существует пара небольших проблем. Мы рекомендуем применять вместо собственного компилятора HP-UX gcc, потому что код, созданный gcc, лучше!

Для HP-UX рекомендуется использование gcc 2.95. Не следует применять высокие уровни оптимизации (наподобие -O6), поскольку на HP-UX это может быть небезопасно.

Должна работать следующая строка конфигурации для gcc 2.95:

CFLAGS="-DHPUX -I/opt/dce/include -fpic" \
CXXFLAGS="-DHPUX -I/opt/dce/include -felide-constructors -fno-exceptions \
-fno-rtti" CXX=gcc ./configure --with-pthread \
--with-named-thread-libs='-ldce' --prefix=/usr/local/mysql
--disable-shared

Следующая строка конфигурации должна работать для gcc 3.1:

CFLAGS="-DHPUX -I/opt/dce/include -O3 -fPIC" CXX=gcc \
CXXFLAGS="-DHPUX -I/opt/dce/include -felide-constructors -fno-exceptions \
-fno-rtti -O3 -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.6.3 Примечания к HP-UX версий 11.x

Для HP-UX версий 11.x мы рекомендуем использовать MySQL не ниже 3.23.15.

Из-за некоторых критических ошибок в стандартных библиотеках HP-UX до попытки запуска MySQL на HP-UX 11.0 необходимо установить следующие патчи:

PHKL_22840 Streams cumulative
PHNE_22397 ARPA cumulative

Применение данных патчей решит проблему получения EWOULDBLOCK от recv() и EBADF от accept() в потоковых приложениях.

При использовании gcc 2.95.1 в системе, к которой не были применены патчи, возникнет ошибка:

In file included from /usr/include/unistd.h:11,
         from ../include/global.h:125,
         from mysql_priv.h:15,
         from item.cc:19:
/usr/include/sys/unistd.h:184: declaration of C function ...
/usr/include/sys/pthread.h:440: previous declaration ...
In file included from item.h:306,
         from mysql_priv.h:158,
         from item.cc:19:

Проблема заключается в том, что HP-UX существуют несовместимые определения функции pthreads_atfork(). Конфликтующие прототипы находятся в `/usr/include/sys/unistd.h':184 и в `/usr/include/sys/pthread.h':440 (подробности приведены ниже).

Одно из возможных решений заключается в том, чтобы скопировать `/usr/include/sys/unistd.h' в `mysql/include' и отредактировать `unistd.h' так, чтобы определение совпадало с определением из `pthread.h'. Ниже приведен результат работы diff:

183,184c183,184
<      extern int pthread_atfork(void (*prepare)(), void (*parent)(),
<                                                void (*child)());
---
>      extern int pthread_atfork(void (*prepare)(void), void (*parent)(void),
>                                                void (*child)(void));

После этого должна работать конфигурационная программа со следующими параметрами:

CFLAGS="-fomit-frame-pointer -O3 -fpic" CXX=gcc \
CXXFLAGS="-felide-constructors -fno-exceptions -fno-rtti -O3" \
./configure --prefix=/usr/local/mysql --disable-shared

Если вы используете MySQL 4.0.5 с компилятором HP-UX, то вам подойдет (проверено на cc B.11.11.04):

CC=cc CXX=aCC CFLAGS=+DD64 CXXFLAGS=+DD64 ./configure --with-extra-character-set=complex

Вы можете игнорировать ошибки, подобные этой:

aCC: warning 901: unknown option: `-3': use +help for online documentation

При получении следующего сообщения об ошибке при работе configure

checking for cc option to accept ANSI C... no
configure: error: MySQL requires a ANSI C compiler (and a C++ compiler).
Try gcc. See the Installation chapter in the Reference Manual.

следует удостовериться, что путь к компилятору K&R не указан раньше, чем путь к компиляторам HP-UX C и C++.

Еще одна причина, по которой вы не сможете скомпилировать MySQL, заключается в том, что вы забыли указать флаг +DD64, описанный выше.

2.6.6.4 Примечания к IBM-AIX

В Autoconf пропущено автоматическое определение xlC, поэтому при компиляции MySQL следует задавать команду configure наподобие следующей (в этом примере используется компилятор IBM):

export CC="xlc_r -ma -O3 -qstrict -qoptimize=3 -qmaxmem=8192 "
export CXX="xlC_r -ma -O3 -qstrict -qoptimize=3 -qmaxmem=8192"
export CFLAGS="-I /usr/local/include"
export LDFLAGS="-L /usr/local/lib"
export CPPFLAGS=$CFLAGS
export CXXFLAGS=$CFLAGS

./configure --prefix=/usr/local \
        --localstatedir=/var/mysql \
        --sysconfdir=/etc/mysql \
        --sbindir='/usr/local/bin' \
        --libexecdir='/usr/local/bin' \
        --enable-thread-safe-client \
        --enable-large-files

Здесь указаны опции, используемые для компиляции дистрибутива MySQL, который находится по адресу http://www-frec.bull.com/.

Если в приведенных выше строках конфигурации вы изменяете -O3 на -O2, следует также удалить опцию -qstrict (это ограничение компилятора IBM C).

При использовании gcc или egcs для компиляции MySQL следует применять флаг -fno-exceptions, потому что обработчик исключительных ситуаций в gcc/egcs не безопасен в реализации потоков! (Это проверено на egcs 1.1.) Существуют также некоторые известные проблемы с ассемблером IBM, которые могут привести к генерации неудачного кода при использовании его с gcc.

Для использования egcs или gcc 2.95 на AIX мы рекомендуем следующую строку конфигурирования:

CC="gcc -pipe -mcpu=power -Wa,-many" \
CXX="gcc -pipe -mcpu=power -Wa,-many" \
CXXFLAGS="-felide-constructors -fno-exceptions -fno-rtti" \
./configure --prefix=/usr/local/mysql --with-low-memory

Для того чтобы компиляция была успешной, здесь необходимо указывать ключи -Wa,-many. В IBM известно о существовании данной проблемы, но ее специалисты не торопятся исправлять ошибку, поскольку существует способ обхода. Нам неизвестно, необходимо ли использование -fno-exceptions с gcc 2.95, но поскольку в MySQL нет обработчика исключительных ситуаций, а эта опция способствует созданию более быстрого кода, мы рекомендуем всегда использовать ее с egcs/gcc.

В случае возникновения проблем в программах на ассемблере необходимо привести -mcpu=xxx в соответствие со своим процессором. Обычно достаточно использовать power2, power или powerpc, но, возможно, необходимо будет указать 604 или 604e. Хотя это и не приветствуется, но использование "power" будет безопасным почти всегда, даже на power2-машинах.

Если вы не знаете, какой у вас процессор, следует запустить uname -m. Данная команда возвращает строку наподобие "000514676700", формат которой xxyyyyyymmss, где xx и ss всегда 0, yyyyyy - уникальный идентификатор системы и mm - идентификатор процессора Planar. Карта этих значений находится по адресу http://publib.boulder.ibm.com/doc_link/en_US/a_doc_lib/cmds/aixcmds5/uname.htm.

В соответствии с данной картой можно узнать тип и модель машины, а уже по ним -определить тип процессора.

Возникновение проблем с сигналами (MySQL неожиданно умирает при большой нагрузке) может означать, что вы столкнулись с ошибкой операционной системы в работе с потоками и сигналами. В этом случае можно запретить MySQL использовать сигналы при помощи следующей строки конфигурации:

shell> 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

Это не повлияет на производительность MySQL, но приведет к побочному эффекту, состоящему в невозможности оборвать работу клиента со спящим соединением при помощи команд mysqladmin kill или mysqladmin shutdown. Вместо этого клиент завершит работу при попытке послать следующую команду.

На некоторых версиях AIX линкование с libbind.a приводит к тому, что getservbyname вызывает аварийную остановку программы с сохранением образа памяти на диск (core dump). Это ошибка AIX и о ней следует сообщить в IBM.

Для AIX 4.2.1 и gcc необходимо сделать следующие изменения:

После конфигурации следует отредактировать файлы `config.h' и `include/my_config.h', а также изменить строку, содержащую

#define HAVE_SNPRINTF 1

на

#undef HAVE_SNPRINTF

И напоследок необходимо в файле `mysqld.cc' добавить прототип функции initgoups.

#ifdef _AIX41
extern "C" int initgroups(const char *,int);
#endif

Если вам нужно выделить много памяти процессу mysqld, недостаточно указать ulimit -d unlimited. Вам также потребуется в mysqld_safe установить что-то вроде:

export LDR_CNTRL='MAXDATA=0x80000000'

Больше информации об использовании большого количества памяти - здесь: http://publib16.boulder.ibm.com/pseries/en_US/aixprggd/genprogc/lrg_prg_support.htm.

2.6.6.5 Примечания к SunOS 4

На SunOS 4 для компиляции MySQL необходимо использовать MIT-pthreads, что, в свою очередь, влечет за собой необходимость в GNU make.

На некоторых SunOS 4 возникают проблемы с динамическими библиотеками и libtool. Во избежание этих проблем можно использовать приведенную ниже строку configure:

shell> ./configure --disable-shared --with-mysqld-ldflags=-all-static

При компиляции readline могут выдаваться предупреждения о дублирующихся определениях. На них можно не обращать внимания.

При компиляции mysqld возникают предупреждения об implicit declaration of function. На них также можно не обращать внимания.

2.6.6.6 Примечания к Alpha-DEC-UNIX (Tru64)

При использовании egcs на Digital Unix необходимо обновить свою версию до gcc 2.95.2, поскольку известно о нескольких серьезных ошибках в egcs для DEC!

В документации рекомендуется для компиляции потоковых программ под Digital Unix использовать опцию -pthread для cc и cxx, а также библиотеки -lmach -lexc (в дополнение к -lpthread). Запускать configure нужно в следующей форме:

CC="cc -pthread" CXX="cxx -pthread -O" \
./configure --with-named-thread-libs="-lpthread -lmach -lexc -lc"

При компиляции mysqld может быть выдано несколько предупреждений наподобие следующих:

mysqld.cc: In function void handle_connections()':
mysqld.cc:626: passing long unsigned int *' as argument 3 of
accept(int,sockadddr *, int *)'

На них можно не обращать внимания. Они возникают из-за того, что configure может обнаруживать только ошибки, но не предупреждения.

При запуске сервера непосредственно из командной строки могут возникнуть проблемы с тем, что он прекращает работу при выходе из системы (при выходе из системы все процессы, запущенные вами во время работы, получают сигнал SIGHUP). Если такое происходит, следует запускать сервер командой:

shell> nohup mysqld [options] &

При указании nohup следующая за ней команда будет игнорировать все сигналы SIGHUP, посланные терминалом. В качестве альтернативного варианта можно запускать сервер командой safe_mysqld, которая при запуске mysqld выполнит вызов nohup вместо вас (see section 4.7.2 safe_mysqld, оболочка mysqld).

Если вы столкнулись с проблемами компиляции `mysys/get_opt.c', следует просто удалить строку #define _NO_PROTO в начале этого файла!

Для компилятора CC от Compaq используйте следующий код:

CC="cc -pthread"
CFLAGS="-O4 -ansi_alias -ansi_args -fast -inline speed all -arch host"
CXX="cxx -pthread"
CXXFLAGS="-O4 -ansi_alias -ansi_args -fast -inline speed all -arch host \
-noexceptions -nortti"
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 -lc"
gnumake

В случае возникновения проблем с libtool при компиляции с динамическими библиотеками (как показано выше), при линковании mysql вы можете избежать этих проблем с помощью:

cd mysql
/bin/sh ../libtool --mode=link cxx -pthread -O3 -DDBUG_OFF \
-O4 -ansi_alias -ansi_args -fast -inline speed \
-speculate all \ -arch host -DUNDEF_HAVE_GETHOSTBYNAME_R \
-o mysql mysql.o readline.o sql_string.o completion_hash.o \
../readline/libreadline.a -lcurses \
../libmysql/.libs/libmysqlclient.so -lm
cd ..
gnumake
gnumake install
scripts/mysql_install_db

2.6.6.7 Примечания к Alpha-DEC-OSF/1

В случае проблем компиляции при установленных DEC CC и gcc попробуйте запустить configure следующим образом:

CC=cc CFLAGS=-O CXX=gcc CXXFLAGS=-O3 \
./configure --prefix=/usr/local/mysql

Если возникнут проблемы с файлом `c_asm.h', можно создать и использовать ``фиктивный'' `c_asm.h' при помощи следующих команд:

touch include/c_asm.h
CC=gcc CFLAGS=-I./include \
CXX=gcc CXXFLAGS=-O3 \
./configure --prefix=/usr/local/mysql

Отметим, что перечисленные ниже проблемы с программой ld могут быть решены путем загрузки последнего набора патчей от DEC (Compaq) с http://ftp.support.compaq.com/public/unix/.

При использовании OSF/1 4.0D и компилятора DEC C V5.6-071 на Digital Unix V4.0 (Rev. 878) компилятор начинает вести себя странно (неопределенные asm-символы). Кроме того, /bin/ld также, похоже, содержит ошибки (проблемы с ошибками _exit undefined возникающими при линковании mysqld). На этих системах нам удалось организовать компиляцию MySQL с помощью следующей строки configure, заменив /bin/ld аналогичным файлом из версии OSF 4.0C:

CC=gcc CXX=gcc CXXFLAGS=-O3 ./configure --prefix=/usr/local/mysql

С Digital-компилятором "C++ V6.1-029" должно работать:

CC=cc -pthread
CFLAGS=-O4 -ansi_alias -ansi_args -fast -inline speed -speculate all \
       -arch host
CXX=cxx -pthread
CXXFLAGS=-O4 -ansi_alias -ansi_args -fast -inline speed -speculate all \
         -arch host -noexceptions -nortti
export CC CFLAGS CXX CXXFLAGS
./configure --prefix=/usr/mysql/mysql
        --with-mysqld-ldflags=-all-static \
            --disable-shared --with-named-thread-libs="-lmach -lexc -lc"

В некоторых версиях OSF/1 испорчена функция alloca(). Ситуацию можно поправить удалением из файла `config.h' строки, в которой определяется HAVE_ALLOCA.

Может также существовать некорректный прототип для функции alloca() в `/usr/include/alloca.h'. Предупреждение, вызванное этим, можно игнорировать.

configure будет автоматически использовать следующие потоковые библиотеки: --with-named-thread-libs="-lpthread -lmach -lexc -lc".

При использовании gcc можно попробовать запустить configure следующей строкой:

shell> CFLAGS=-D_PTHREAD_USE_D4 CXX=gcc CXXFLAGS=-O3 ./configure ...

Возникновение проблем с сигналами (MySQL неожиданно аварийно завершает работу при большой нагрузке), может означать, что вы обнаружили ошибку при работе операционной системы с потоками и сигналами. В данном случае можно запретить MySQL использовать сигналы путем конфигурации его следующим образом:

shell> CFLAGS=-DDONT_USE_THR_ALARM \
       CXXFLAGS=-DDONT_USE_THR_ALARM \
       ./configure ...

Это не повлияет на производительность MySQL, но приведет к побочному эффекту, который проявляется как невозможность оборвать работу клиента со спящим соединением командами mysqladmin kill или mysqladmin shutdown. Вместо этого клиент завершит работу при попытке послать следующую команду.

При использовании gcc 2.95.2 может возникать следующая ошибка компиляции:

sql_acl.cc:1456: Internal compiler error in `scan_region', at except.c:2566
Please submit a full bug report.

Чтобы выйти из положения в этом случае, следует перейти в каталог `sql' и выполнить последнюю строку gcc (просто выделите ее, например, мышкой и вставьте в терминал), изменив в ней -O3 на -O0 (или добавьте -O0 непосредственно после gcc, если у вас в строке компиляции отсутствует какая-либо опция -O). После выполнения указанных действий вернитесь в каталог верхнего уровня и запустите make повторно.

2.6.6.8 Примечания к SGI Irix

При использовании Irix 6.5.3 или выше mysqld может создавать потоки только в случае, если он запущен от имени пользователя с привилегиями CAP_SCHED_MGT (подобными тем, что у root) или если такие привилегии даются серверу mysqld следующей командой:

shell> chcap "CAP_SCHED_MGT+epi" /opt/mysql/libexec/mysqld

Возможно, вам придется убрать некоторые определения из `config.h'. Это делается после выполнения configure, но до компиляции.

В некоторых реализациях Irix неправильно реализована функция alloca(). Если сервер mysqld аварийно завершает работу при выполнении некоторых выражений SELECT, удалите из `config.h' строки, в которых определяются HAVE_ALLOC и HAVE_ALLOCA_H. Если не работает mysqladmin create, удалите из `config.h' строку, определяющую HAVE_READDIR_R. Можно также удалить строку, содержащую HAVE_TERM_H.

SGI рекомендует установить все патчи, как указано на странице

http://support.sgi.com/surfzone/patches/patchset/6.2_indigo.rps.html.

Вам следует, как минимум, установить последние обновления (rollup) ядра, последние обновления rld и последние обновления libc.

Для поддержки pthreads обязательно следует установить все патчи POSIX со страницы:

http://support.sgi.com/surfzone/patches/patchset/6.2_posix.rps.html

Если при компиляции `mysql.cc' вы получили сообщение об ошибке наподобие:

"/usr/include/curses.h", line 82: error(1084): invalid combination of type

то необходимо выполнить следующие команды в каталоге верхнего уровня дерева каталогов исходных текстов MySQL:

shell> extra/replace bool curses_bool < /usr/include/curses.h \
     > include/curses.h
shell> make

Мы получали также сообщения о проблемах управления. Если выполняется только один поток, то работа идет очень медленно. Однако если запустить еще одну программу-клиент, то можно получить ускорение в несколько раз (от двукратного до десятикратного соответственно) и для других потоков. Причины описанной проблемы с потоками в Irix пока неясны; возможно, вам удастся найти временное решение, пока она не будет решена.

При компиляции с помощью gcc можно использовать следующую команду configure:

CC=gcc CXX=gcc CXXFLAGS=-O3 \
./configure --prefix=/usr/local/mysql --enable-thread-safe-client \
--with-named-thread-libs=-lpthread

Сообщают, что для Irix 6.5.11 с собственными Irix C и C++ компиляторами версии 7.3.1.2, должно работать:

CC=cc CXX=CC CFLAGS='-O3 -n32 -TARG:platform=IP22 -I/usr/local/include \
-L/usr/local/lib' CXXFLAGS='-O3 -n32 -TARG:platform=IP22 \
-I/usr/local/include -L/usr/local/lib' ./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.6.9 Примечания к Caldera (SCO)

В настоящее время пакет тестировался только на системах ``sco3.2v5.0.4'' и ``sco3.2v5.0.5''. Заметный прогресс отмечается в отношении пакета на ``sco3.2v4.2''.

В настоящее время в качестве компилятора под OpenServer мы рекомендуем gcc 2.95.2. Используя его, можно скомпилировать MySQL при помощи следующей строки:

CC=gcc CXX=gcc ./configure ... (опции)
  1. На OpenServer 5.0.X необходимо использовать gcc-2.95.2p1 или более свежую версию от Skunkware - http://www.caldera.com/skunkware/ и выбрать пакет для OpenServer или получить его по ftp по адресу ftp2.caldera.com в каталоге pub/skunkware/osr5/devtools/gcc.
  2. Следует использовать портированную версию GCC 2.5.x для этого продукта и систему Development. Они необходимы для данной версии Caldera (SCO) Unix. Использовать просто систему GCC Dev нельзя.
  3. Необходимо загрузить пакет FSU Pthreads и установить его. Его можно найти по адресу http://www.cs.wustl.edu/~schmidt/ACE_wrappers/FSU-threads.tar.gz. Можно также получить уже скомпилированный пакет на http://www.mysql.com/Downloads/SCO/FSU-threads-3.5c.tar.gz.
  4. FSU Pthreads могут быть скомпилированы на Caldera (SCO) Unix 4.2 c tcpip. На OpenServer 3.0 или Open Desktop 3.0 (OS 3.0 ODT 3.0) с использованием Caldera (SCO) Development System вам понадобится хороший пакет GCC 2.5.x ODT или OS 3.0. Однако при отсутствии хорошо портированной версии возникнет масса проблем. Для портирования этой программы требуется система SCO Unix Development. Без нее у вас не будет необходимых библиотек и редактора связей.
  5. Для сборки FSU Pthreads в своей системе нужно выполнить следующие действия:
    1. Запустите ./configure в каталоге threads/src и выберите опцию SCO OpenServer. Эта команда скопирует Makefile.SCO5 в Makefile.
    2. Запустите make.
    3. Для установки в каталог по умолчанию - `/usr/include' войдите в систему с правами пользователя root, перейдите в каталог thread/src и запустите make install.
  6. Не забудьте использовать GNU make при сборке MySQL.
  7. При запуске safe_mysqld не с правами пользователя root вы получите разрешение открывать одновременно только 110 файлов на процесс (это значение установлено по умолчанию). mysqld сообщит об этом в файле протокола.
  8. На SCO 3.2V5.0.5 вы должны использовать FSU Pthreads версии 3.5c или выше, а также gcc 2.95.2 или более новую версию! Приведенная ниже команда configure должна выполняться корректно:
    shell> ./configure --prefix=/usr/local/mysql --disable-shared
  9. На SCO 3.2V4.2 следует использовать FSU Pthreads версии 3.5c или выше. Приведенная ниже команда configure должна выполняться корректно:
    shell> CFLAGS="-D_XOPEN_XPG4" CXX=gcc CXXFLAGS="-D_XOPEN_XPG4" \
       ./configure \
       --prefix=/usr/local/mysql \
       --with-named-thread-libs="-lgthreads -lsocket -lgen -lgthreads" \
       --with-named-curses-libs="-lcurses"
    У вас могут возникнуть проблемы с некоторыми включаемыми файлами. В таком случае новые, специфические для SCO включаемые файлы можно найти по адресу http://www.mysql.com/Downloads/SCO/SCO-3.2v4.2-includes.tar.gz. Этот архив следует распаковать в каталог дерева исходных текстов MySQL с именем include

Замечания по разработке под Caldera (SCO):

  • MySQL должен автоматически обнаруживать FSU Pthreads и линковать mysqld с использованием -lgthreads -lsocket -lgthreads.
  • Библиотеки разработки в Caldera (SCO) реентрантны в FSU Pthreads. Специалисты Caldera утверждают, что библиотечные функции Caldera реентрантны, поэтому они должны быть реентрантны с FSU Pthreads. FSU Pthreads на OpenServer пытаются использовать SCO-схему, чтобы создать реентрантные библиотеки.
  • FSU Pthreads (по крайней мере версия на http://www.mysql.com/) поставляется как линкованная с GNU malloc. При возникновении проблем с использованием памяти, убедитесь, что `gmalloc.o' включен в `libgthreads.a' и `libgthreads.so'.
  • В FSU Pthreads используют pthread следующие системные вызовы: read(), write(), getmsg(), connect(), accept(), select(), and wait().
  • CSSA-2001-SCO.35.2 (в списках заказов патч упоминается как патч по системе безопасности erg711905-dscr_remap) (версия 2.0.0) портит FSU-потоки и вызывает неустойчивую работу mysqld. Если вы собираетесь запускать mysqld на машине с установленным OpenServer 5.0.6, этот патч применять не следует.

Если необходимо установить DBI на Caldera (SCO), следует отредактировать Makefile в DBI-xxx и каждом подкаталоге.

Для приведенного ниже кода подразумевается использование gcc 2.95.2 или более новой версии:

СТАРЫЙ:                               НОВЫЙ:
CC = cc                               CC = gcc
CCCDLFLAGS = -KPIC -W1,-Bexport       CCCDLFLAGS = -fpic
CCDLFLAGS = -wl,-Bexport              CCDLFLAGS =

LD = ld                               LD = gcc -G -fpic
LDDLFLAGS = -G -L/usr/local/lib       LDDLFLAGS = -L/usr/local/lib
LDFLAGS = -belf -L/usr/local/lib      LDFLAGS = -L/usr/local/lib

LD = ld                               LD = gcc -G -fpic
OPTIMISE = -Od                        OPTIMISE = -O1

OLD:
CCCFLAGS = -belf -dy -w0 -U M_XENIX -DPERL_SCO5 -I/usr/local/include

НОВЫЙ:
CCFLAGS = -U M_XENIX -DPERL_SCO5 -I/usr/local/include

Это вызвано тем, что dynaloader из Perl не загружает DBI-модулей, если они скомпилированы компиляторами icc или cc.

Perl будет работать лучше, если его скомпилировать компилятором cc.

2.6.6.10 Примечания к Caldera (SCO) Unixware Version 7.0

Вы должны использовать MySQL версий не ниже 3.22.13, поскольку в этой версии исправлены некоторые проблемы, связанные с переносимостью под Unixware.

Нам удалось скомпилировать MySQL следующей командой configure на Unixware версии 7.0.1:

CC=cc CXX=CC ./configure --prefix=/usr/local/mysql

Если вы хотите использовать gcc, необходимо использовать gcc версии 2.95.2 или новее.

Caldera поставляет libsocket.so.2 с ftp://stage.caldera.com/pub/security/tools для исправлений безопасности в более ранних, чем OSR506, системах. Кроме того, исправление telnetd на ftp://stage.caldera.com/pub/security/openserver/CSSA-2001-SCO.10/ предназначено и для libsocket.so.2, и для libresolv.so.1. Там же находятся инструкции для установки на более ранние, чем OSR506, системы.

Устанавливать вышеупомянутые патчи лучше до попытки компиляции/использования MySQL.

2.6.7 Примечания к OS/2

В MySQL используется достаточно много открытых файлов. Поэтому в свой файл `CONFIG.SYS' вам нужно добавить код вроде приведенного ниже:

SET EMXOPT=-c -n -h1024

В противном случае вы можете столкнуться со следующей ошибкой:

File 'xxxx' not found (Errcode: 24)

При использовании MySQL с OS/2 Warp 3 требуется FixPack 29 или выше, а с OS/2 Warp 4 -FixPack 4 или выше. Это требуется для библиотеки Pthreads. MySQL может быть установлен на файловой системе, поддерживающей длинные имена, такой как HPFS, FAT32, и т.п.

Скрипт `INSTALL.CMD' должен запускаться из собственной оболочки OS/2 - `CMD.EXE'; и может не работать в заменяющих ее оболочках, таких как `4OS2.EXE'.

Скрипт `scripts/mysql-install-db' был переименован. Теперь он называется `install'.cmd и является REXX-скриптом, который задает установки безопасности MySQL по умолчанию и создает иконку WorkPlace Shell для MySQL.

Поддержка динамических модулей скомпилирована, но полностью не проверена. Динамические модули должны быть скомпилированы с использованием динамической библиотеки Pthreads.

gcc -Zdll -Zmt -Zcrtdll=pthrdrtl -I../include -I../regex -I.. \
    -o example udf_example.cc -L../lib -lmysqlclient udf_example.def
mv example.dll example.udf

Примечание: в соответствии с ограничениями OS/2 размер основной части имен модулей UDF не должен превышать 8-ми символов. Модули хранятся в каталоге `/mysql2/udf'; скрипт s`afe-mysqld.cmd' помещает путь к этому каталогу в переменную окружения BEGINLIBPATH. При использовании UDF-модулей определенные расширения игнорируются - они все принимаются как `.udf'. Например, в Unix динамический модуль может иметь имя `example.so' и функция из него будет загружаться следующим образом:

mysql> CREATE FUNCTION metaphon RETURNS STRING SONAME "example.so";

В OS/2 модуль будет иметь имя `example.udf', но вы не должны определять расширение модуля:

mysql> CREATE FUNCTION metaphon RETURNS STRING SONAME "example";

2.6.8 Примечания к BeOS

Мы заинтересованы в том, чтобы MySQL работал в BeOS, но, к сожалению, среди нас нет никого, кто знал бы BeOS или обладал временем для создания портированной версии.

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

У нас было предварительное общение с некоторыми разработчиками BeOS, утверждавших, что на 80% создана портированная версия MySQL под BeOS, однако уже на протяжении длительного времени мы не получали от них никаких известий.

2.6.9 Примечания к Novell NetWare

Мы заинтересованы в том, чтобы MySQL работал на Novell NetWare, но, к сожалению, среди нас нет никого, кто достаточно хорошо разбирался бы в NetWare или обладал временем для создания портированной версии.

Мы хотели бы найти желающих создать портированную версию и готовы помочь им в решении любых технических вопросов, которые могут возникнуть при работе над ней.

2.7 Замечания по установке Perl

2.7.1 Установка Perl на Unix

Поддержка Perl для MySQL обеспечивается средствами клиентского интерфейса DBI/DBD. See section 8.2 Интерфейс Perl API для MySQL. Для клиентского кода Perl DBD/DBI требуется версия Perl 5.004 или выше. При использовании более старой версии Perl данный интерфейс не будет работать.

Для поддержки Perl в MySQL также требуется, чтобы была установлена программная поддержка клиентов MySQL. Если вы установили MySQL из файлов RPM, то клиентские программы находятся в RPM-пакете MySQL-client, а их программная поддержка - в RPM-пакете MySQL-devel. Убедитесь, что у вас установлена последняя версия RPM.

С версии 3.22.8 поддержка Perl поставляется отдельно от основного дистрибутива MySQL. Если вы хотите установить поддержку Perl, то необходимые файлы можно получить с http://www.mysql.com/downloads/api-dbi.html.

Дистрибутивы Perl поставляются как сжатые tar-архивы с именами наподобие `MODULE-VERSION.tar.gz', где MODULE - имя модуля и VERSION - номер версии. Необходимо взять дистрибутивы Data-Dumper, DBI и Msql-Mysql-modules и установить их в указанном порядке. Процедура установки приведена ниже. Показанный пример приведен для модуля Data-Dumper, но сама процедура одинакова для всех трех дистрибутивов:

  1. Распакуйте дистрибутив в текущем каталоге:
    shell> gunzip < Data-Dumper-VERSION.tar.gz | tar xvf -
    Эта команда создает каталог с именем `Data-Dumper-VERSION'. Перейдите в каталог, куда распаковался дистрибутив:
    shell> cd Data-Dumper-VERSION
    Соберите дистрибутив и скомпилируйте:
    shell> perl Makefile.PL
shell> make
shell> make test
shell> make install

Команда make test является важной, поскольку она проверяет, работает ли модуль. Следует учитывать, что если эта команда выполняется во время установки Msql-Mysql-modules для проверки кода интерфейса, то сервер MySQL при этом должен работать, или же данный тест потерпит неудачу.

Каждый раз при установке нового выпуска MySQL полезно создать заново и переустановить дистрибутив Msql-Mysql-modules, особенно если замечаются такие симптомы, как смерть скриптов DBI после модернизации MySQL (имеется в виду coredump).

Если вы не обладаете правами установки модулей Perl в системном каталоге или локальных модулей Perl, то для вас окажется полезной следующая ссылка:

http://www.iserver.com/support/contrib/perl5/modules.html

Следует смотреть в рубрике Installing New Modules that Require Locally Installed Modules.

2.7.2 Установка ActiveState Perl на Windows

Для установки модуля DBD для MySQL под ActiveState Perl на Windows необходимо выполнить следующие действия:

  • Получить ActiveState Perl с http://www.activestate.com/Products/ActivePerl/ и установить его.
  • Открыть оболочку DOS.
  • Если это необходимо, то установить переменную HTTP_proxy. Например, можно попытаться сделать следующее:
    set HTTP_proxy=my.proxy.com:3128
  • Запустить программу PPM:
    C:\> c:\perl\bin\ppm.pl
  • Установить DBI, если этого еще не сделано:
    ppm> install DBI
  • Если все прошло успешно, то запустить следующую команду:
    install \
ftp://ftp.de.uu.net/pub/CPAN/authors/id/JWIED/DBD-mysql-1.2212.x86.ppd

Эти команды должны работать по крайней мере с версией ActiveState Perl 5.6.

Если приведенные выше команды у вас не работают, то вместо этого необходимо установить драйвер MyODBC и подключить сервер MySQL через ODBC:

use DBI;
$dbh= DBI->connect("DBI:ODBC:$dsn","$user","$password") ||
  die "Got error $DBI::errstr when connecting to $dsn\n";

2.7.3 Установка дистрибутива Perl для MySQL на Windows

Дистрибутив Perl для MySQL содержит DBI, DBD:MySQL и DBD:ODBC.

  • Загрузите дистрибутив Perl для Windows с http://www.mysql.com/downloads/os-win32.html.
  • Разархивируйте дистрибутив в C:, в результате чего вы получите каталог `C:\PERL'.
  • Добавьте в ваш путь каталог `C:\PERL\BIN'.
  • Добавьте в ваш путь каталог `C:\PERL\BIN\MSWIN32-x86-thread' или `C:\PERL\BIN\MSWIN32-x86'.
  • Протестируйте работу perl, выполнив команду perl -v в оболочке DOS.

2.7.4 Проблемы использования интерфейса Perl DBI/DBD

Если Perl сообщает, что не может найти модуль `../mysql/mysql.so', то проблема, возможно, заключается в том, что Perl не может найти динамическую библиотеку `libmysqlclient.so'.

Эту проблему можно устранить, используя любой из следующих методов:

  • Для сборки дистрибутива Msql-Mysql-modules используйте perl Makefile.PL -static -config вместо perl Makefile.PL.
  • Скопируйте `libmysqlclient.so' в каталог, где находятся другие динамические библиотеки (`/usr/lib' или `/lib').
  • Под Linux можно добавить путь к каталогу, где находится `libmysqlclient.so' в файл `/etc/ld.so.conf'.
  • Добавьте каталог, в котором находится `libmysqlclient.so', в переменную окружения LD_RUN_PATH.

Если вы получаете от DBD-mysql представленные ниже ошибки, то, скорее всего, у вас используется компилятор gcc (или старый бинарный код, скомпилированный с gcc):

/usr/bin/perl: can't resolve symbol '__moddi3'
/usr/bin/perl: can't resolve symbol '__divdi3'

Добавьте в команду линкования при сборке библиотеки `mysql.so', -L/usr/lib/gcc-lib/... -lgcc (нужно проверить вывод из make для `mysql.so' при компиляции клиента Perl). Опция -L должна указывать путь к каталогу, где находится `libgcc.a' в вашей системе.

Еще одна причина появления ошибок может заключаться в том, что оба модуля - Perl и MySQL не скомпилированы вместе компилятором gcc. В этом случае данное несоответствие можно устранить, скомпилировав оба модуля компилятором gcc.

Если при выполнении тестов вы получаете от модуля Msql-Mysql-modules следующие ошибки:

t/00base............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 и затем повторить процесс инсталляции сначала.

Если вы хотите использовать эти модули в системе, которая не поддерживает динамического линкования (вроде Caldera/SCO), то можно сгенерировать статическую версию Perl, включающую DBI и DBD-mysql. Она будет работать следующим образом: нужно создать версию Perl, слинкованную с кодом DBI, и установить ее поверх текущего Perl. Затем эта версия используется для сборки версии Perl, которая дополнительно включает слинкованный код DBD, и устанавливается уже она.

В операционной системе Caldera (SCO) необходимо иметь следующий набор переменных окружения:

shell> LD_LIBRARY_PATH=/lib:/usr/lib:/usr/local/lib:/usr/progressive/lib
или
shell> LD_LIBRARY_PATH=/usr/lib:/lib:/usr/local/lib:/usr/ccs/lib:\
       /usr/progressive/lib:/usr/skunk/lib
shell> LIBPATH=/usr/lib:/lib:/usr/local/lib:/usr/ccs/lib:\
       /usr/progressive/lib:/usr/skunk/lib
shell> MANPATH=scohelp:/usr/man:/usr/local1/man:/usr/local/man:\
       /usr/skunk/man:

Вначале следует создать модуль Perl, включающий статически слинкованный DBI. Это делается путем выполнения следующих команд в каталоге, где располагается дистрибутив DBI:

shell> perl Makefile.PL -static -config
shell> make
shell> make install
shell> make perl

Затем необходимо установить новый модуль Perl. Вывод команды make perl укажет точную команду make, которую необходимо будет выполнить для завершения установки. Для Caldera (SCO) это будет команда make -f Makefile.aperl inst_perl MAP_TARGET=perl.

Затем нужно использовать только что созданный модуль Perl для создания еще одного модуля Perl, который также включает в себя статически слинкованный модуль DBD::mysql. Это делается путем выполнения следующих команд в каталоге, где располагается дистрибутив Msql-Mysql-modules:

shell> perl Makefile.PL -static -config
shell> make
shell> make install
shell> make perl

И в завершение осталось установить этот новый модуль Perl. Какую команду для этого использовать, вы опять узнаете из вывода make perl.


Справочное руководство по MySQL версии 5.0.0-alpha. - 3 Учебное пособие по MySQL

3 Учебное пособие по MySQL

Эта глава представляет собой обучающий курс по MySQL: в ней демонстрируется использование клиентской программы mysql для создания несложной базы данных и работы с ней. Утилита mysql (иногда называемая также ``терминальным монитором'' или просто ``монитором'') представляет собой интерактивную программу, позволяющую подсоединяться к MySQL-серверу, запускать запросы, и просматривать результаты. Программа mysql может работать и в пакетном режиме: для этого необходимо записать все запросы в файл, а затем передать его содержимое на исполнение mysql. Ниже описаны оба способа использования mysql.

Увидеть список команд программы mysql можно, запустив ее с параметром --help:

shell> mysql --help

Текст главы построен с расчетом на то, что на вашем компьютере установлен mysql и существует связь с сервером MySQL. Если это не так, свяжитесь со своим администратором MySQL (если вы и есть администратор, обратитесь к другим разделам настоящего руководства).

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

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

3.1 Подсоединение к серверу и отсоединение от него

При подключении к серверу с помощью mysql обычно нужно ввести имя пользователя MySQL и, в большинстве случаев, пароль. Если сервер запущен не на том компьютере, с которого вы вошли в систему, необходимо также указать имя хоста. Параметры соединения (а именно - соответствующее имя хоста, пользователя и пароль) вы сможете узнать у администратора. Получив соответствующие параметры, подсоединиться к серверу можно следующим образом:

shell> mysql -h host -u user -p
Enter password: ********

Символы ******** обозначают ваш пароль; введите его, когда mysql выведет на экран запрос Enter password:.

Если все сработает, на экране должна появиться следующая информация и метка командной строки mysql>:

shell> mysql -h host -u user -p
Enter password: ********

Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 459 to server version: 3.22.20a-log

Type 'help' for help.

mysql>

Метка обозначает, что программа mysql готова к вводу команд.

В некоторых вариантах установки MySQL возможно подсоединение к запущенному на локальном хосте серверу без ввода имени пользователя (пользователь anonymous). Если ваша система настроена именно так, подсоединиться к серверу вы сможете, запустив mysql со следующими параметрами:

shell> mysql

После установки соединения можно в любой момент отключиться от сервера, набрав в командной строке mysql> команду QUIT:

mysql> QUIT
Bye

Отсоединиться от сервера можно и при помощи сочетания клавиш Control-D.

Большая часть приведенных ниже примеров построена с учетом того, что соединение с сервером уже установлено. Это видно по наличию в них командной строки mysql>.

3.2 Ввод запросов

Подсоединитесь к серверу, как было описано выше. Таким образом никакая база выбрана не будет, но это не страшно. На данном этапе нам гораздо важней разобраться с созданием запросов, нежели сразу усложнять себе жизнь созданием таблиц, загрузкой в них данных и извлечением их оттуда. В этом разделе разъясняются основные принципы ввода команд; на примере нескольких запросов вы можете поближе познакомиться с работой mysql.

Ниже приведена простая команда, запрашивающая у сервера информацию об его версии и текущей дате. Введите ее в командной строке mysql> и нажмите Enter:

mysql> SELECT VERSION(), CURRENT_DATE;

+--------------+--------------+
| VERSION()    | CURRENT_DATE |
+--------------+--------------+
| 3.22.20a-log | 1999-03-19   |
+--------------+--------------+
1 row in set (0.01 sec)
mysql>

Этот запрос иллюстрирует следующие особенности mysql:

  • Команда обычно состоит из SQL-выражения, за которым следует точка с запятой. (Из этого правила есть и исключения - команды без точки с запятой. Одним из них является упомянутая выше команда QUIT, остальные мы рассмотрим позднее.)
  • Когда пользователь вводит команду, mysql отправляет ее серверу для выполнения и выводит на экран сначала результаты, а затем - новую строку mysql>, что означает готовность к выполнению новых команд.
  • mysql выводит результаты работы запроса в виде таблицы (строк и столбцов). В первой строке этой таблицы содержатся заголовки столбцов, а в следующих строках - собственно результаты. Обычно заголовками столбцов становятся имена, полученные из таблиц базы. Если же извлекается не столбец таблицы, а значение выражения (как это происходит в приведенном выше примере), mysql дает столбцу имя запрашиваемого выражения.
  • mysql сообщает количество возвращаемых строк и время выполнения запроса, что позволяет в некоторой степени составить представление о производительности сервера. Эти значения обычно весьма впечатляют, так как представляют обычное (а не машинное время), кроме того, на них оказывает влияние загрузка сервера и скорость работы сети (для сокращения размеров листингов в остальных примерах этой главы строка "rows in set" удалена).

Для ввода ключевых слов можно использовать любой регистр символов. Приведенные ниже запросы абсолютно идентичны:

mysql> SELECT VERSION(), CURRENT_DATE;
mysql> select version(), current_date;
mysql> SeLeCt vErSiOn(), current_DATE;

А это - еще один запрос. В нем демонстрируется использование mysql в качестве несложного калькулятора:

mysql> SELECT SIN(PI()/4), (4+1)*5;
+-------------+---------+
| SIN(PI()/4) | (4+1)*5 |
+-------------+---------+
|    0.707107 |      25 |
+-------------+---------+

Все команды, представленные выше, были относительно короткими и состояли из одной строки. В одну строку можно поместить и несколько команд. Но каждая из них должна заканчиваться точкой с запятой:

mysql> SELECT VERSION(); SELECT NOW();
+--------------+
| VERSION()    |
+--------------+
| 3.22.20a-log |
+--------------+

+---------------------+
| NOW()               |
+---------------------+
| 1999-03-19 00:15:33 |
+---------------------+

Втискивать все команды в одну строку совсем не обязательно, так что создание длинных команд, занимающих несколько строк, никаких проблем не вызывает. Для mysql признаком завершения выражения является точка с запятой, а не конец строки (другими словами, mysql принимает команды без форматирования: строки с командами собираются, но не исполняются до тех пор, пока программа не обнаружит точку с запятой).

Вот пример несложного выражения, занимающего несколько строк:

mysql> SELECT
    -> USER()
    -> ,
    -> CURRENT_DATE;
+--------------------+--------------+
| USER()             | CURRENT_DATE |
+--------------------+--------------+
| joesmith@localhost | 1999-03-18   |
+--------------------+--------------+

Обратите внимание на то, как изменилась метка командной строки (с mysql> на ->) после ввода первой строки этого запроса. Таким образом программа mysql показывает, что завершенного выражения она пока что не получила и ожидает его полного ввода. Эта метка очень полезна, так как предоставляет весьма ценную информацию о состоянии программы. С ее помощью всегда можно узнать, чего ждет mysql.

Если вы решите отменить исполнение набираемой команды, наберите \c:

mysql> SELECT
    -> USER()
    -> \c
mysql>

Обратите внимание на метку: после ввода команды \c она снова принимает вид mysql>, показывая, что программа mysql перешла в режим ожидания указаний.

В этой таблице приведены все возможные варианта вида метки командной строки и соответствующие им состояния mysql:

Метка | Значение
mysql> | Ожидание новой команды.
-> | Ожидание следующей строки многострочной команды.
'> | Ожидание следующей строки, сбор строкового выражения, начинающегося с одиночной кавычки (`'').
"> | Ожидание следующей строки, сбор строкового выражения, начинающегося с двойной кавычки (`"').

Обычно многострочные команды получаются случайно, когда хочешь создать обычную команду, но забываешь поставить завершающую точку с запятой. В таком случае mysql ожидает продолжения:

mysql> SELECT USER()
    ->

Если с вами произошло подобное (вы думаете, что завершили команду, но программа выдает только метку ->), то mysql, вероятнее всего, ждет точки с запятой. Не обратив внимание на метку командной строки, можно довольно долго ждать выполнения команды, не понимая в чем дело. А достаточно лишь поставить точку с запятой, завершив команду, которую mysql и выполнит:

mysql> SELECT USER()
    -> ;
+--------------------+
| USER()             |
+--------------------+
| joesmith@localhost |
+--------------------+

Метки '> и "> используются при сборе строк. В MySQL строки можно заключать как в одинарные (`''), так и в двойные (`"') кавычки (можно, например, написать 'hello' или "goodbye"), к тому же, mysql позволяет вводить строковые выражения, состоящие из нескольких строчек текста. Метка '> или "> обозначает, что вы ввели строку, открывающуюся символом кавычек `'' или `"', но еще не ввели завершающую строковое выражение закрывающую кавычку.

Это, конечно, нормально, если вы собираетесь создать большое строковое выражение из нескольких строчек. Но это не слишком частый случай. Гораздо чаще оказывается, что вы просто забыли поставить закрывающую кавычку. Например:

mysql> SELECT * FROM my_table WHERE name = "Smith AND age < 30;
    ">

Если ввести такую команду SELECT, нажать Enter и подождать результатов, ничего не произойдет. Тут-то и нужно обратить внимание на метку командной строки, выглядящую вот так: ">. Это значит, что mysql ждет ввода завершающей части строки. (Теперь заметили ошибку в команде? В строке "Smith нет закрывающей кавычки.)

Что делать в этом случае? Проще всего было бы отменить команду. Однако теперь просто набрать \c нельзя, так как mysql примет эти символы за часть собираемой строки! Вместо этого нужно ввести закрывающие кавычки (тем самым дав mysql понять, что строка закончилась) и лишь затем набрать \c:

mysql> SELECT * FROM my_table WHERE name = "Smith AND age < 30;
    "> "\c
mysql>

Метка командной строки снова примет вид mysql>, показывая готовность mysql к выполнению команд.

Знать значение меток '> и "> необходимо, так как при вводе незавершенной строки все последующие строки будут игнорироваться mysql - включая строку с командой QUIT! Это может основательно сбить с толку, особенно если не знать, что для отмены команды перед соответствующей последовательностью символов необходимо поставить закрывающую кавычку.

3.3 Создание и использование базы данных

Теперь, когда вы знаете, как вводить команды, пора начать работу с базой данных.

Предположим, у вас дома (или в вольере) живет несколько домашних любимцев и вы хотите создать систему для хранения разнообразной информации о своем живом уголке. Для того чтобы это сделать, нужно просто создать таблицы и записать в них информацию. После этого любые данные можно будет получить, извлекая данные из таблиц. В этом разделе вы научитесь:

  • создавать базу данных
  • создавать таблицу
  • записывать в таблицу данные
  • извлекать данные из таблицы различными способами
  • работать с несколькими таблицами сразу

Наша база данных будет чрезвычайно проста (это мы сделали намеренно), но совсем несложно придумать реальные задачи, решение которых потребовало бы применения подобной базы данных. Такая база, например, может пригодиться скотоводу для хранения информации о поголовье или ветеринару - для учета пациентов. Готовая база данных menagerie, в которой содержатся некоторые из запросов и данные из приведенных ниже разделов, находится на web-сайте MySQL. Ее можно загрузить в виде сжатого tar-файла (http://www.mysql.com/Downloads/Contrib/Examples/menagerie.tar.gz) или Zip (http://www.mysql.com/Downloads/Contrib/Examples/menagerie.zip).

Узнать, какие базы существуют в настоящее время на сервере, можно при помощи команды SHOW:

mysql> SHOW DATABASES;
+----------+
| Database |
+----------+
| mysql    |
| test     |
| tmp      |
+----------+

На вашем компьютере список баз, вероятно, будет другим, но в нем все равно, скорее всего, будут присутствовать базы mysql и test. База данных mysql просто необходима, так как в ней она описываются пользовательские права доступа. База test часто применяется для экспериментов.

Впрочем, всех баз вы можете и не увидеть, если у вас нет привилегии SHOW DATABASES. See section 4.3.1 Синтаксис команд GRANT и REVOKE.

Если база данных test существует, попробуйте обратиться к ней:

mysql> USE test
Database changed

В команде USE, как и QUIT, точка с запятой не нужна (конечно, данные команды тоже можно завершать точкой с запятой - никакого вреда от этого не будет). Команда USE отличается от остальных и кое-чем еще: она должна задаваться одной строкой.

Базу данных test (если, конечно, у вас есть доступ к ней) можно использовать для работы с приведенными ниже примерами, но все созданное в ней может быть уничтожено любым другим пользователем, имеющим к ней доступ. Поэтому вам лучше попросить у своего администратора MySQL разрешение на создание собственной базы. Предположим, вы захотите назвать ее menagerie (``зверинец''). В таким случае администратору нужно будет набрать примерно такую команду:

mysql> GRANT ALL ON menagerie.* TO your_mysql_name;

где your_mysql_name - присвоенное вам имя MySQL.

3.3.1 Создание и выбор базы данных

Если администратор при выдаче разрешения создаст для вас базу, с ней можно сразу начинать работу. В противном случае вам придется создать ее самостоятельно:

mysql> CREATE DATABASE menagerie;

В Unix имеет значение регистр символов в именах баз данных (в отличие от ключевых слов SQL), так что в этой ОС вам всегда придется называть свою базу menagerie, а не Menagerie, MENAGERIE или еще как-нибудь. Это же правило распространяется и на имена таблиц (в Windows данное ограничение не действует, однако при обращении к базам и таблицам в пределах одного запроса, тем не менее, можно использовать только один регистр).

При создании базы данных она автоматически не выбирается; выбирать ее нужно отдельно. Сделать menagerie текущей базой можно с помощью следующей команды:

mysql> USE menagerie
Database changed

Создавать базу нужно только однажды, но выбирать ее приходится в каждом сеансе работы с mysql. Делать это можно с помощью команды USE, представленной выше. А можно выбирать базу и из командной строки при запуске mysql. Для этого достаточно лишь ввести ее имя после параметров соединения, которые нужно вводить в любом случае. Например:

shell> mysql -h host -u user -p menagerie
Enter password: ********

Обратите внимание: в вышеприведенной команде menagerie не является паролем. Ввести пароль в командной строке после параметра -p можно без пробела (например, -pmypassword, а не -p mypassword). Впрочем, пароль в командной строке все равно лучше не вводить, так как таким образом его могут и подсмотреть.

3.3.2 Создание таблицы

Как вы уже успели убедиться, создать базу данных было просто. Однако пока что в ней ничего нет - в этом можно удостовериться при помощи команды SHOW TABLES:

mysql> SHOW TABLES;
Empty set (0.00 sec)

Гораздо труднее определиться со структурой своей базы, т.е. с тем, какие могут понадобиться таблицы, и какие столбцы должны содержаться в каждой из них.

Вам обязательно будет нужна таблица, содержащая по записи на каждое из животных. Назвать ее можно pet, и храниться в ней будут, как минимум, имена. Но так как само по себе имя неинформативно, в таблице должны будут присутствовать и другие данные. Например, если домашние животные есть более чем у одного члена вашей семьи, в таблицу можно добавить и имя владельца каждого животного. Кроме того, в базу стоит внести и описательную информацию - например, вид и пол животного.

Но вот как быть с возрастом? Эта информация тоже может оказаться полезной, но хранить такие данные в базе неудобно. Возраст со временем меняется, а это значит, что придется довольно часто обновлять записи. Значительно удобнее хранить фиксированные значения - например, даты рождения. В таком случае возраст всегда можно получить, вычислив разницу между текущей датой и датой рождения. В MySQL есть функции для арифметических действий над данными, так что это совсем несложно. Хранение даты рождения имеет и другие преимущества:

  • Базу данных можно использовать для выдачи напоминаний о приближающихся днях рождения животных (не спешите улыбаться: та же задача может возникнуть и при работе с деловой базой данных, которая должна уметь напоминать о днях рождения клиентов, облегчая таким образом рассылку поздравлений).
  • Возраст можно подсчитывать относительно любой даты, а не только для текущей. Например, если записать в базу и дату смерти животного, всегда можно будет узнать, сколько лет ему было на момент смерти.

Можно было бы придумать и еще какие-нибудь данные, которые неплохо было бы хранить в таблице pet, но пока что мы ограничимся уже выбранными: именем (name), именем владельца (owner), видом (species), полом (sex), датой рождения (birth) и датой смерти (death).

При помощи команды CREATE TABLE определим структуру новой таблицы:

mysql> CREATE TABLE pet (name VARCHAR(20), owner VARCHAR(20),
    -> species VARCHAR(20), sex CHAR(1), birth DATE, death DATE);

Тип VARCHAR отлично подойдет для хранения имени животного, имени владельца и названия вида, так как длина данных этого типа может варьироваться. Конечно, длины таких столбцов вовсе не должны совпадать и не должны быть равны 20 - можно выбрать любое значение в пределах от 1 до 255 (если при выборе длины столбца вы ошибетесь, и при работе с базой окажется, что столбец маловат, можно будет исправить ошибку при помощи команды ALTER TABLE).

Пол животного можно обозначать несколькими способами, например буквами "m" и "f", или словами male (мужской) и female (женский). С буквами "m" и "f" будет проще.

Применение типа данных DATE для хранения дат рождения и смерти вполне очевидно.

Теперь, когда таблица создана, команда SHOW TABLES должна вывести следующее:

mysql> SHOW TABLES;
+---------------------+
| Tables in menagerie |
+---------------------+
| pet                 |
+---------------------+

Проверить, правильно была ли таблица создана в соответствии с планом, можно при помощи команды DESCRIBE:

mysql> DESCRIBE pet;
+---------+-------------+------+-----+---------+-------+
| Field   | Type        | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| name    | varchar(20) | YES  |     | NULL    |       |
| owner   | varchar(20) | YES  |     | NULL    |       |
| species | varchar(20) | YES  |     | NULL    |       |
| sex     | char(1)     | YES  |     | NULL    |       |
| birth   | date        | YES  |     | NULL    |       |
| death   | date        | YES  |     | NULL    |       |
+---------+-------------+------+-----+---------+-------+

Использовать команду DESCRIBE можно в любое время, например, если вы забудете имена столбцов или типы, к которым они относятся.

3.3.3 Загрузка данных в таблицу

Создав таблицу, нужно позаботиться об ее заполнении. Для этого предназначены команды LOAD DATA и INSERT.

Предположим, ваши записи соответствуют приведенным в этой таблице (обратите внимание: MySQL принимает даты в формате ГГГГ-ММ-ДД; возможно, к такой записи вы не привыкли).

name | owner | species | sex | birth | death
Fluffy | Harold | cat | f | 1993-02-04 |
Claws | Gwen | cat | m | 1994-03-17 |
Buffy | Harold | dog | f | 1989-05-13 |
Fang | Benny | dog | m | 1990-08-27 |
Bowser | Diane | dog | m | 1998-08-31 | 1995-07-29
Chirpy | Gwen | bird | f | 1998-09-11 |
Whistler | Gwen | bird |  | 1997-12-09 |
Slim | Benny | snake | m | 1996-04-29 |

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

Создайте текстовый файл с именем `pet.txt', содержащий по одной записи в каждой строке (значения столбцов должны быть разделены символами табуляции и даны в том порядке, который был определен командой CREATE TABLE). Незаполненным полям (например, неизвестный пол или даты смерти живых на сегодняшний день животных), можно присвоить значение NULL. В текстовом файле это значение представляется символами \N. Например, запись для птицы Whistler должна выглядеть примерно так (между значениями должны располагаться одиночные символы табуляции):

name | owner | species | sex | birth | death
Whistler | Gwen | bird | \N | 1997-12-09 | \N

Загрузить файл `pet.txt' в таблицу можно с помощью следующей команды:

mysql> LOAD DATA LOCAL INFILE "pet.txt" INTO TABLE pet;

Маркер конца строки и символ, разделяющий значения столбцов, можно специально задать в команде LOAD DATA, но по умолчанию используются символы табуляции и перевода строки. Воспринимая их, команда сможет корректно прочитать файл `pet.txt'.

При добавлении одиночных записей используется команда INSERT. В самом простом варианте ее применения необходимо задать значения каждого столбца, в том порядке, в каком они были перечислены в команде CREATE TABLE. Предположим, Диана (Diane) купила хомячка по имени Puffball. Соответствующую запись в таблицу с можно внести с помощью команды INSERT примерно так:

mysql> INSERT INTO pet
    -> VALUES ('Puffball','Diane','hamster','f','1999-03-30',NULL);

Обратите внимание на то, что здесь строковые выражения и даты представлены в виде ограниченных кавычками строк. Кроме того, в команде INSERT отсутствующие данные можно прямо заменять на NULL. Пользоваться эвфемизмом \N, как в команде LOAD DATA, нужды нет.

Этот пример наглядно показывает, что если бы с самого начала все данные вносились в базу при помощи нескольких команд INSERT, а не одной команды LOAD DATA, то набирать пришлось бы гораздо больше текста.

3.3.4 Выборка информации из таблицы

Информация извлекается из таблиц при помощи команды SELECT. Вызывается она так:

SELECT what_to_select
FROM which_table
WHERE conditions_to_satisfy

где what_to_select обозначает нужные данные. Это может быть список столбцов или символ * (``все столбцы''). which_table указывает таблицу, из которой должны быть извлечены данные. Условие WHERE использовать необязательно, но если оно все же присутствует в вызове команды, то параметр conditions_to_satisfy задает условия, которым должны соответствовать нужные строки.

3.3.4.1 Выборка всех данных

В самом простом варианте вызова SELECT из таблицы извлекаются сразу все данные:

mysql> SELECT * FROM pet;
+----------+--------+---------+------+------------+------------+
| name     | owner  | species | sex  | birth      | death      |
+----------+--------+---------+------+------------+------------+
| Fluffy   | Harold | cat     | f    | 1993-02-04 | NULL       |
| Claws    | Gwen   | cat     | m    | 1994-03-17 | NULL       |
| Buffy    | Harold | dog     | f    | 1989-05-13 | NULL       |
| Fang     | Benny  | dog     | m    | 1990-08-27 | NULL       |
| Bowser   | Diane  | dog     | m    | 1998-08-31 | 1995-07-29 |
| Chirpy   | Gwen   | bird    | f    | 1998-09-11 | NULL       |
| Whistler | Gwen   | bird    | NULL | 1997-12-09 | NULL       |
| Slim     | Benny  | snake   | m    | 1996-04-29 | NULL       |
| Puffball | Diane  | hamster | f    | 1999-03-30 | NULL       |
+----------+--------+---------+------+------------+------------+

Использовать SELECT таким образом удобно, когда нужно просмотреть всю таблицу, например, после того, как в нее была загружена первая порция данных. Как часто случается, в выведенных на экран данных сразу можно увидеть ошибку в таблице: Bowser, оказывается, успел умереть еще до того, как родился! Заглянув в его родословную обнаруживаем, что пес родился в 1989, а не в 1998 году.

Исправить ошибку можно как минимум двумя способами:

  • Отредактировать файл pet.txt, затем очистить таблицу и снова заполнить ее командами DELETE и LOAD DATA:
    mysql> SET AUTOCOMMIT=1;  # Used for quick re-create of the table
mysql> DELETE FROM pet;
mysql> LOAD DATA LOCAL INFILE "pet.txt" INTO TABLE pet;
    Однако в таком случае придется снова ввести запись о Puffball.
  • Исправить только ошибочно введенные данные при помощи команды UPDATE:
    mysql> UPDATE pet SET birth = "1989-08-31" WHERE name = "Bowser";

Как видно из приведенного выше примера, загрузить всю таблицу сразу очень просто. Но на практике обычно этого не требуется, особенно когда таблица достигает значительных размеров. Чаще всего нужно просто ответить на какой-нибудь вопрос, для чего необходимо ввести ограничения, указывающие, какая же информация вам нужна. Давайте рассмотрим несколько запросов с точки зрения вопросов, на которые они отвечают.

3.3.4.2 Выборка определенных строк

Из таблицы можно выбрать и только нужные строки. Например, если вы хотите проверить правильность внесенных в дату рождения собаки Bowser изменений, соответствующую запись можно получить следующим способом:

mysql> SELECT * FROM pet WHERE name = "Bowser";
+--------+-------+---------+------+------------+------------+
| name   | owner | species | sex  | birth      | death      |
+--------+-------+---------+------+------------+------------+
| Bowser | Diane | dog     | m    | 1989-08-31 | 1995-07-29 |
+--------+-------+---------+------+------------+------------+

Теперь видно, что год рождения теперь записан правильно -1989, а не 1998.

В операции сравнения строк обычно не учитывается регистр символов, так что имя можно записать как "bowser", "BOWSER" и т.п. Результаты запросов будут идентичными.

В условиях может указываться любой из столбцов, а не только name. Если, например, вам нужно узнать, какие их животных родились после 1998 года, в условие вводится значение столбца birth:

mysql> SELECT * FROM pet WHERE birth >= "1998-1-1";
+----------+-------+---------+------+------------+-------+
| name     | owner | species | sex  | birth      | death |
+----------+-------+---------+------+------------+-------+
| Chirpy   | Gwen  | bird    | f    | 1998-09-11 | NULL  |
| Puffball | Diane | hamster | f    | 1999-03-30 | NULL  |
+----------+-------+---------+------+------------+-------+

Условия можно и комбинировать, например для того, чтобы выделить всех собак женского пола:

mysql> SELECT * FROM pet WHERE species = "dog" AND sex = "f";
+-------+--------+---------+------+------------+-------+
| name  | owner  | species | sex  | birth      | death |
+-------+--------+---------+------+------------+-------+
| Buffy | Harold | dog     | f    | 1989-05-13 | NULL  |
+-------+--------+---------+------+------------+-------+

В предыдущем запросе использован оператор AND. Существует еще и оператор OR:

mysql> SELECT * FROM pet WHERE species = "snake" OR species = "bird";
+----------+-------+---------+------+------------+-------+
| name     | owner | species | sex  | birth      | death |
+----------+-------+---------+------+------------+-------+
| Chirpy   | Gwen  | bird    | f    | 1998-09-11 | NULL  |
| Whistler | Gwen  | bird    | NULL | 1997-12-09 | NULL  |
| Slim     | Benny | snake   | m    | 1996-04-29 | NULL  |
+----------+-------+---------+------+------------+-------+

Операторы AND и OR можно использовать совместно. В таком случае с помощью скобок можно указать порядок группировки условий:

mysql> SELECT * FROM pet WHERE (species = "cat" AND sex = "m")
    -> OR (species = "dog" AND sex = "f");
+-------+--------+---------+------+------------+-------+
| name  | owner  | species | sex  | birth      | death |
+-------+--------+---------+------+------------+-------+
| Claws | Gwen   | cat     | m    | 1994-03-17 | NULL  |
| Buffy | Harold | dog     | f    | 1989-05-13 | NULL  |
+-------+--------+---------+------+------------+-------+

3.3.4.3 Выборка определенных столбцов

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

mysql> SELECT name, birth FROM pet;
+----------+------------+
| name     | birth      |
+----------+------------+
| Fluffy   | 1993-02-04 |
| Claws    | 1994-03-17 |
| Buffy    | 1989-05-13 |
| Fang     | 1990-08-27 |
| Bowser   | 1989-08-31 |
| Chirpy   | 1998-09-11 |
| Whistler | 1997-12-09 |
| Slim     | 1996-04-29 |
| Puffball | 1999-03-30 |
+----------+------------+

Получить имена владельцев животных можно с помощью следующего запроса:

mysql> SELECT owner FROM pet;
+--------+
| owner  |
+--------+
| Harold |
| Gwen   |
| Harold |
| Benny  |
| Diane  |
| Gwen   |
| Gwen   |
| Benny  |
| Diane  |
+--------+

Однако этот запрос просто загружает поля с именем владельца из каждой записи, а некоторые имена встречаются более одного раза. Сократить количество выводимых строк можно, воспользовавшись ключевым словом DISTINCT - тогда будут выводиться только уникальные записи:

mysql> SELECT DISTINCT owner FROM pet;
+--------+
| owner  |
+--------+
| Benny  |
| Diane  |
| Gwen   |
| Harold |
+--------+

При помощи выражения WHERE можно комбинировать выбор строк и столбцов. Например для того, чтобы загрузить даты рождения только кошек и собак, можно воспользоваться следующим запросом:

mysql> SELECT name, species, birth FROM pet
    -> WHERE species = "dog" OR species = "cat";
+--------+---------+------------+
| name   | species | birth      |
+--------+---------+------------+
| Fluffy | cat     | 1993-02-04 |
| Claws  | cat     | 1994-03-17 |
| Buffy  | dog     | 1989-05-13 |
| Fang   | dog     | 1990-08-27 |
| Bowser | dog     | 1989-08-31 |
+--------+---------+------------+

3.3.4.4 Сортировка строк

Вы уже, наверное, заметили, что результаты, выдававшиеся запросами из предыдущих примеров, выводились без какой-либо сортировки. Но ведь часто разобраться в результатах легче, если они отсортированы. Для этого используется выражение ORDER BY.

Так выглядят даты рождения животных в отсортированном виде:

mysql> SELECT name, birth FROM pet ORDER BY birth;
+----------+------------+
| name     | birth      |
+----------+------------+
| Buffy    | 1989-05-13 |
| Bowser   | 1989-08-31 |
| Fang     | 1990-08-27 |
| Fluffy   | 1993-02-04 |
| Claws    | 1994-03-17 |
| Slim     | 1996-04-29 |
| Whistler | 1997-12-09 |
| Chirpy   | 1998-09-11 |
| Puffball | 1999-03-30 |
+----------+------------+

Над столбцами с символьными значениями операция сортировки - как и все другие операции сравнения - обычно проводится без учета регистра символов. Это значит, что порядок расположения столбцов, совпадающих во всем, кроме регистра символов, относительно друг друга будет не определен. Провести сортировку с учетом регистра символов можно при помощи команды BINARY: ORDER BY BINARY(поле).

Для сортировки в обратном порядке к имени столбца следует добавить ключевое слово DESC (по убыванию):

mysql> SELECT name, birth FROM pet ORDER BY birth DESC;
+----------+------------+
| name     | birth      |
+----------+------------+
| Puffball | 1999-03-30 |
| Chirpy   | 1998-09-11 |
| Whistler | 1997-12-09 |
| Slim     | 1996-04-29 |
| Claws    | 1994-03-17 |
| Fluffy   | 1993-02-04 |
| Fang     | 1990-08-27 |
| Bowser   | 1989-08-31 |
| Buffy    | 1989-05-13 |
+----------+------------+

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

mysql> SELECT name, species, birth FROM pet ORDER BY species, birth DESC;
+----------+---------+------------+
| name     | species | birth      |
+----------+---------+------------+
| Chirpy   | bird    | 1998-09-11 |
| Whistler | bird    | 1997-12-09 |
| Claws    | cat     | 1994-03-17 |
| Fluffy   | cat     | 1993-02-04 |
| Fang     | dog     | 1990-08-27 |
| Bowser   | dog     | 1989-08-31 |
| Buffy    | dog     | 1989-05-13 |
| Puffball | hamster | 1999-03-30 |
| Slim     | snake   | 1996-04-29 |
+----------+---------+------------+

Обратите внимание: действие ключевого слова DESC распространяется только на тот столбец, имя которого располагается в запросе прямо перед этим словом (в данном случае - birth); значения поля species по-прежнему отсортированы в возрастающем порядке.

3.3.4.5 Вычисление дат

В MySQL имеется несколько функций, реализующих арифметические операции над датами. Эти функции позволяют, например, вычислять возраст или получать части даты.

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

mysql> SELECT name, birth, CURRENT_DATE,
    -> (YEAR(CURRENT_DATE)-YEAR(birth))
    -> - (RIGHT(CURRENT_DATE,5)<RIGHT(birth,5))
    -> AS age
    -> FROM pet;
+----------+------------+--------------+------+
| name     | birth      | CURRENT_DATE | age  |
+----------+------------+--------------+------+
| Fluffy   | 1993-02-04 | 2001-08-29   |    8 |
| Claws    | 1994-03-17 | 2001-08-29   |    7 |
| Buffy    | 1989-05-13 | 2001-08-29   |   12 |
| Fang     | 1990-08-27 | 2001-08-29   |   11 |
| Bowser   | 1989-08-31 | 2001-08-29   |   11 |
| Chirpy   | 1998-09-11 | 2001-08-29   |    2 |
| Whistler | 1997-12-09 | 2001-08-29   |    3 |
| Slim     | 1996-04-29 | 2001-08-29   |    5 |
| Puffball | 1999-03-30 | 2001-08-29   |    2 |
+----------+------------+--------------+------+

В этом примере функция YEAR() выделяет из даты год, а RIGHT() - пять крайних справа символов, представляющих календарный день (MM-DD). Часть выражения, сравнивающая даты, выдает 1 или 0, что позволяет уменьшить результат на единицу, если текущий день (CURRENT_DATE) находится к началу календаря ближе, нежели день рождения животного. Все выражение смотрится несколько неуклюже, поэтому вместо него в заголовке соответствующего столбца результатов выводится псевдоним (age - "возраст").

Запрос неплохо работает, но разобраться в результатах было бы проще, если бы строки располагались в определенном порядке. Этого можно достичь, добавив в запрос выражение ORDER BY name и отсортировав таким образом результаты по имени:

mysql> SELECT name, birth, CURRENT_DATE,
    -> (YEAR(CURRENT_DATE)-YEAR(birth))
    -> - (RIGHT(CURRENT_DATE,5)<RIGHT(birth,5))
    -> AS age
    -> FROM pet ORDER BY name;
+----------+------------+--------------+------+
| name     | birth      | CURRENT_DATE | age  |
+----------+------------+--------------+------+
| Bowser   | 1989-08-31 | 2001-08-29   |   11 |
| Buffy    | 1989-05-13 | 2001-08-29   |   12 |
| Chirpy   | 1998-09-11 | 2001-08-29   |    2 |
| Claws    | 1994-03-17 | 2001-08-29   |    7 |
| Fang     | 1990-08-27 | 2001-08-29   |   11 |
| Fluffy   | 1993-02-04 | 2001-08-29   |    8 |
| Puffball | 1999-03-30 | 2001-08-29   |    2 |
| Slim     | 1996-04-29 | 2001-08-29   |    5 |
| Whistler | 1997-12-09 | 2001-08-29   |    3 |
+----------+------------+--------------+------+

Отсортировать результаты по возрасту также можно при помощи выражения ORDER BY:

mysql> SELECT name, birth, CURRENT_DATE,
    -> (YEAR(CURRENT_DATE)-YEAR(birth))
    -> - (RIGHT(CURRENT_DATE,5)<RIGHT(birth,5))
    -> AS age
    -> FROM pet ORDER BY age;
+----------+------------+--------------+------+
| name     | birth      | CURRENT_DATE | age  |
+----------+------------+--------------+------+
| Chirpy   | 1998-09-11 | 2001-08-29   |    2 |
| Puffball | 1999-03-30 | 2001-08-29   |    2 |
| Whistler | 1997-12-09 | 2001-08-29   |    3 |
| Slim     | 1996-04-29 | 2001-08-29   |    5 |
| Claws    | 1994-03-17 | 2001-08-29   |    7 |
| Fluffy   | 1993-02-04 | 2001-08-29   |    8 |
| Fang     | 1990-08-27 | 2001-08-29   |   11 |
| Bowser   | 1989-08-31 | 2001-08-29   |   11 |
| Buffy    | 1989-05-13 | 2001-08-29   |   12 |
+----------+------------+--------------+------+

подобный же запрос поможет определить возраст, которого достигли умершие животные на момент смерти. Выделить умерших животных можно, проверив значение поля death на предмет равенства NULL. Затем для записей, значения поля death которых не равно NULL, можно вычислить разницу между датами смерти и рождения:

mysql> SELECT name, birth, death,
    -> (YEAR(death)-YEAR(birth)) - (RIGHT(death,5)<RIGHT(birth,5))
    -> AS age
    -> FROM pet WHERE death IS NOT NULL ORDER BY age;
+--------+------------+------------+------+
| name   | birth      | death      | age  |
+--------+------------+------------+------+
| Bowser | 1989-08-31 | 1995-07-29 |    5 |
+--------+------------+------------+------+

В этом запросе используется выражение death IS NOT NULL, а не death <> NULL, так как NULL - особое значение (более подробные пояснения приведены в разделе see section 3.3.4.6 Работа с значениями NULL).

А как поступать, если потребуется определить, дни рождения каких животных наступят в следующем месяце? Для таких расчетов день и год значения не имеют; из столбца, содержащего дату рождения, нас интересует только месяц. В MySQL предусмотрено несколько функций для получения частей дат - YEAR(), MONTH(), и DAYOFMONTH(). В данном случае нам подойдет функция MONTH(). Увидеть работу этой функции можно с помощью простого запроса, выводящего дату рождения birth и MONTH(birth):

mysql> SELECT name, birth, MONTH(birth) FROM pet;
+----------+------------+--------------+
| name     | birth      | MONTH(birth) |
+----------+------------+--------------+
| Fluffy   | 1993-02-04 |            2 |
| Claws    | 1994-03-17 |            3 |
| Buffy    | 1989-05-13 |            5 |
| Fang     | 1990-08-27 |            8 |
| Bowser   | 1989-08-31 |            8 |
| Chirpy   | 1998-09-11 |            9 |
| Whistler | 1997-12-09 |           12 |
| Slim     | 1996-04-29 |            4 |
| Puffball | 1999-03-30 |            3 |
+----------+------------+--------------+

Найти животных, дни рождения которых наступят в следующем месяце, тоже несложно. Предположим, что сейчас на дворе апрель. Тогда номер текущего месяца - 4, а искать надо животных, родившихся в мае (5-м месяце), таким образом:

mysql> SELECT name, birth FROM pet WHERE MONTH(birth) = 5;
+-------+------------+
| name  | birth      |
+-------+------------+
| Buffy | 1989-05-13 |
+-------+------------+

Конечно, в декабре возникают некоторые осложнения. Если просто добавить единицу к номеру месяца (12) и поискать животных, родившихся в тринадцатом месяце, найти что-нибудь вряд ли удастся. Вместо этого нужно искать животных, родившихся в январе (1-м месяце).

Можно даже написать небольшой запрос, который будет работать вне зависимости от того, какой нынче месяц. Функция DATE_ADD() позволяет прибавить к дате некоторый интервал времени. Если добавить к значению, возвращаемому функцией NOW(), месяц, а затем извлечь из получившейся даты номер месяца при помощи функции MONTH(), мы получим именно тот месяц, который нам нужен:

mysql> SELECT name, birth FROM pet
    -> WHERE MONTH(birth) = MONTH(DATE_ADD(NOW(), INTERVAL 1 MONTH));

Ту же задачу можно решить и другим методом - для этого нужно прибавить единицу к номеру месяца, следующего за текущим (воспользовавшись функцией расчета по модулю (MOD) для перехода к 0, если номер текущего месяца равен 12):

mysql> SELECT name, birth FROM pet
    -> WHERE MONTH(birth) = MOD(MONTH(NOW()), 12) + 1;

Функция MONTH возвращает число от 1 до 12, а выражение MOD(число,12) - число от 0 до 11. Поэтому операцию сложения нужно проводить после MOD(), иначе результат перепрыгнет с ноября (11) сразу на январь (1).

3.3.4.6 Работа с значениями NULL

К NULL-значениям нужно привыкнуть. По идее, NULL обозначает отсутствующее или неизвестное значение и обрабатывается отличным от других значений образом. Проверить значение на равенство NULL с помощью обычных арифметических операторов сравнения (=, < или <>) нельзя. Это отлично иллюстрирует следующий запрос:

mysql> SELECT 1 = NULL, 1 <> NULL, 1 < NULL, 1 > NULL;
+----------+-----------+----------+----------+
| 1 = NULL | 1 <> NULL | 1 < NULL | 1 > NULL |
+----------+-----------+----------+----------+
|     NULL |      NULL |     NULL |     NULL |
+----------+-----------+----------+----------+

Очевидно, что от таких сравнений значащих результатов ожидать нечего. Вместо этого нужно пользоваться операторами IS NULL и IS NOT NULL:

mysql> SELECT 1 IS NULL, 1 IS NOT NULL;
+-----------+---------------+
| 1 IS NULL | 1 IS NOT NULL |
+-----------+---------------+
|         0 |             1 |
+-----------+---------------+

Отметим: в MySQL 0 или NULL приравнивается к логическому false, а все остальное - к true. По умолчанию значение "истина" для булевого оператора равно 1.

Именно из-за того, что при работе с NULL действуют особые правила, в предыдущем разделе для поиска умерших животных использовалось выражение death IS NOT NULL, а не death <> NULL.

Два NULL-значения считаются одинаковыми в GROUP BY.

При выполнении ORDER BY, NULL-значения идут в первую очередь если вы выполняете ORDER ... ASC и в последнюю - если ORDER BY ... DESC.

Обратите внимание, что в MySQL 4.0.2 - 4.0.10, NULL-значения всегда возвращались в первую очередь, вне зависимости от сортировки.

3.3.4.7 Сравнение по шаблонам

В MySQL реализовано стандартное для SQL сравнение по шаблонам, а также особый тип такого сравнения - он основан на использовании выражений, подобных применяющимся в служебных программах Unix (таких, как vi, grep и sed).

В SQL при сравнении по шаблону символ `_' обозначает любой одиночный символ, а `%' - определенное количество символов (включая ноль символов). В MySQL в SQL-шаблонах по умолчанию не учитывается регистр символов. При работе с шаблонами SQL использование операторов = или <> не допускается, вместо этого применяются операторы сравнения LIKE или NOT LIKE.

Найти все имена, начинающиеся с `b', можно следующим образом:

mysql> SELECT * FROM pet WHERE name LIKE "b%";
+--------+--------+---------+------+------------+------------+
| name   | owner  | species | sex  | birth      | death      |
+--------+--------+---------+------+------------+------------+
| Buffy  | Harold | dog     | f    | 1989-05-13 | NULL       |
| Bowser | Diane  | dog     | m    | 1989-08-31 | 1995-07-29 |
+--------+--------+---------+------+------------+------------+

Найти все имена, заканчивающиеся на `fy', можно следующим образом:

mysql> SELECT * FROM pet WHERE name LIKE "%fy";
+--------+--------+---------+------+------------+-------+
| name   | owner  | species | sex  | birth      | death |
+--------+--------+---------+------+------------+-------+
| Fluffy | Harold | cat     | f    | 1993-02-04 | NULL  |
| Buffy  | Harold | dog     | f    | 1989-05-13 | NULL  |
+--------+--------+---------+------+------------+-------+

Найти все имена, содержащие `w', можно следующим образом:

mysql> SELECT * FROM pet WHERE name LIKE "%w%";
+----------+-------+---------+------+------------+------------+
| name     | owner | species | sex  | birth      | death      |
+----------+-------+---------+------+------------+------------+
| Claws    | Gwen  | cat     | m    | 1994-03-17 | NULL       |
| Bowser   | Diane | dog     | m    | 1989-08-31 | 1995-07-29 |
| Whistler | Gwen  | bird    | NULL | 1997-12-09 | NULL       |
+----------+-------+---------+------+------------+------------+

Найти все имена, содержащие ровно пять символов, можно при помощи шаблонного символа `_':

mysql> SELECT * FROM pet WHERE name LIKE "_____";
+-------+--------+---------+------+------------+-------+
| name  | owner  | species | sex  | birth      | death |
+-------+--------+---------+------+------------+-------+
| Claws | Gwen   | cat     | m    | 1994-03-17 | NULL  |
| Buffy | Harold | dog     | f    | 1989-05-13 | NULL  |
+-------+--------+---------+------+------------+-------+

Во втором типе шаблонов, предусмотренных в MySQL, используются расширенные регулярные выражения. При поиске совпадений на основе такого шаблона шаблоном нужно пользоваться операторами REGEXP и NOT REGEXP (или их синонимами - RLIKE и NOT RLIKE).

Ниже приведены некоторые характеристики расширенных регулярных выражений:

  • `.' обозначает любой символ.
  • Класс символов `[...]' обозначает любой из символов в скобках. Например, `[abc]' обозначает `a', `b' или `c'. Набор символов можно обозначить с помощью дефиса. `[a-z]' обозначает любую букву нижнего регистра, а `[0-9]' - любую цифру.
  • `*' обозначает ноль или более экземпляров символа, стоящего перед ним. Например, `x*' обозначает любое количество символов `x', `[0-9]*' обозначает любое количество цифр, а `.*' - любое количество любых символов.
  • Для шаблона выдается совпадение, если поисковый контекст обнаружен в любой из частей значения, в котором производится поиск (для шаблонов SQL совпадение выдается только в случае, если совпадает все значение).
  • ``Закрепить'' шаблон так, чтобы проверять совпадения с началом или концом значения можно с помощью символов `^' (начало) или `$' (конец), которые располагаются в начале или в конце шаблона соответственно.

Чтобы продемонстрировать работу регулярных выражений, приведенные выше запросы LIKE здесь переписаны с использованием REGEXP.

Найти все имена, начинающиеся с `b', можно при помощи символа `^', привязывающего шаблон к началу имени:

mysql> SELECT * FROM pet WHERE name REGEXP "^b";
+--------+--------+---------+------+------------+------------+
| name   | owner  | species | sex  | birth      | death      |
+--------+--------+---------+------+------------+------------+
| Buffy  | Harold | dog     | f    | 1989-05-13 | NULL       |
| Bowser | Diane  | dog     | m    | 1989-08-31 | 1995-07-29 |
+--------+--------+---------+------+------------+------------+

В версиях MySQL до 3.23.4 REGEXP учитывает регистр символов, и приведенный запрос не возвратит никаких результатов. Для поиска символов `b' верхнего или нижнего регистра воспользуйтесь следующим запросом:

mysql> SELECT * FROM pet WHERE name REGEXP "^[bB]";

Начиная с версии MySQL 3.23.4, заставить REGEXP учитывать регистр символов можно с помощью ключевого слова BINARY. В этом запросе положительный результат поиска будет получен только при обнаружении символа 'b' нижнего регистра в начале имени:

mysql> SELECT * FROM pet WHERE name REGEXP BINARY "^b";

Найти все имена, заканчивающиеся на `fy', можно при помощи символа `$', привязывающего шаблон к концу имени:

mysql> SELECT * FROM pet WHERE name REGEXP "fy$";
+--------+--------+---------+------+------------+-------+
| name   | owner  | species | sex  | birth      | death |
+--------+--------+---------+------+------------+-------+
| Fluffy | Harold | cat     | f    | 1993-02-04 | NULL  |
| Buffy  | Harold | dog     | f    | 1989-05-13 | NULL  |
+--------+--------+---------+------+------------+-------+

Найти все имена, содержащие символ `w' любого регистра, можно так:

mysql> SELECT * FROM pet WHERE name REGEXP "w";
+----------+-------+---------+------+------------+------------+
| name     | owner | species | sex  | birth      | death      |
+----------+-------+---------+------+------------+------------+
| Claws    | Gwen  | cat     | m    | 1994-03-17 | NULL       |
| Bowser   | Diane | dog     | m    | 1989-08-31 | 1995-07-29 |
| Whistler | Gwen  | bird    | NULL | 1997-12-09 | NULL       |
+----------+-------+---------+------+------------+------------+

Поскольку регулярное выражение выдает положительный результат при совпадении шаблона с любым фрагментом значения, в приведенном выше примере привязывать поиск к любому из концов имени для сравнения полного значения с шаблоном, как это пришлось бы делать для шаблона SQL, не нужно.

Найти все имена, содержащие ровно пять символов, можно, если привязать поиск к началу и концу имени с помощью символов `^' и `$' и поставить пять символов `.' между ними:

mysql> SELECT * FROM pet WHERE name REGEXP "^.....$";
+-------+--------+---------+------+------------+-------+
| name  | owner  | species | sex  | birth      | death |
+-------+--------+---------+------+------------+-------+
| Claws | Gwen   | cat     | m    | 1994-03-17 | NULL  |
| Buffy | Harold | dog     | f    | 1989-05-13 | NULL  |
+-------+--------+---------+------+------------+-------+

Предыдущий запрос можно записать и при помощи оператора `{n}' (``повторить-n-раз''):

mysql> SELECT * FROM pet WHERE name REGEXP "^.{5}$";
+-------+--------+---------+------+------------+-------+
| name  | owner  | species | sex  | birth      | death |
+-------+--------+---------+------+------------+-------+
| Claws | Gwen   | cat     | m    | 1994-03-17 | NULL  |
| Buffy | Harold | dog     | f    | 1989-05-13 | NULL  |
+-------+--------+---------+------+------------+-------+

3.3.4.8 Подсчет строк

Базы данных часто используются для получения ответа на вопросы типа: ``как часто данные определенного типа встречаются в таблице?'' Вам, например, может понадобиться узнать общее количество животных, или то, сколько животных имеется у каждого из владельцев, или провести статистические исследования на базе хранящейся информации.

Процедура подсчета количества животных в сущности идентична подсчету количества строк в таблице, так как на каждое животное приходится по одной записи. Функция COUNT() подсчитает количество непустых результатов, и с ее помощью можно составить следующий запрос для определения числа животных:

mysql> SELECT COUNT(*) FROM pet;
+----------+
| COUNT(*) |
+----------+
|        9 |
+----------+

Ранее мы уже извлекали из таблицы имена владельцев животных. При помощи функции COUNT() можно узнать, сколько животных принадлежит каждому из владельцев:

mysql> SELECT owner, COUNT(*) FROM pet GROUP BY owner;
+--------+----------+
| owner  | COUNT(*) |
+--------+----------+
| Benny  |        2 |
| Diane  |        2 |
| Gwen   |        3 |
| Harold |        2 |
+--------+----------+

Обратите внимание на использование команды GROUP BY для объединения всех записей по каждому из владельцев. Без этой команды запрос выдал бы только сообщение об ошибке:

mysql> SELECT owner, COUNT(owner) FROM pet;
ERROR 1140 at line 1: Mixing of GROUP columns (MIN(),MAX(),COUNT()...)
with no GROUP columns is illegal if there is no GROUP BY clause

Команды COUNT() и GROUP BY очень помогают характеризовать данные различными способами. В примерах, приведенных ниже, вы увидите и другие способы проведения статистических подсчетов.

Количество животных каждого вида:

mysql> SELECT species, COUNT(*) FROM pet GROUP BY species;
+---------+----------+
| species | COUNT(*) |
+---------+----------+
| bird    |        2 |
| cat     |        2 |
| dog     |        3 |
| hamster |        1 |
| snake   |        1 |
+---------+----------+

Количество животных каждого пола:

mysql> SELECT sex, COUNT(*) FROM pet GROUP BY sex;
+------+----------+
| sex  | COUNT(*) |
+------+----------+
| NULL |        1 |
| f    |        4 |
| m    |        4 |
+------+----------+

(в этой таблице результатов NULL обозначает, что пол животного неизвестен)

Количество животных каждого вида с учетом пола:

mysql> SELECT species, sex, COUNT(*) FROM pet GROUP BY species, sex;
+---------+------+----------+
| species | sex  | COUNT(*) |
+---------+------+----------+
| bird    | NULL |        1 |
| bird    | f    |        1 |
| cat     | f    |        1 |
| cat     | m    |        1 |
| dog     | f    |        1 |
| dog     | m    |        2 |
| hamster | f    |        1 |
| snake   | m    |        1 |
+---------+------+----------+

При использовании функции COUNT() вовсе не обязательно загружать всю таблицу. Например, предыдущий запрос, в котором учитываются только кошки и собаки, выглядит следующим образом:

mysql> SELECT species, sex, COUNT(*) FROM pet
    -> WHERE species = "dog" OR species = "cat"
    -> GROUP BY species, sex;
+---------+------+----------+
| species | sex  | COUNT(*) |
+---------+------+----------+
| cat     | f    |        1 |
| cat     | m    |        1 |
| dog     | f    |        1 |
| dog     | m    |        2 |
+---------+------+----------+

Можно узнать и количество животных каждого пола с учетом только тех экземпляров, пол которых известен:

mysql> SELECT species, sex, COUNT(*) FROM pet
    -> WHERE sex IS NOT NULL
    -> GROUP BY species, sex;
+---------+------+----------+
| species | sex  | COUNT(*) |
+---------+------+----------+
| bird    | f    |        1 |
| cat     | f    |        1 |
| cat     | m    |        1 |
| dog     | f    |        1 |
| dog     | m    |        2 |
| hamster | f    |        1 |
| snake   | m    |        1 |
+---------+------+----------+

3.3.4.9 Использование нескольких таблиц

В таблице pet хранятся только основные данные о животных. Если же нужно держать в базе какую-либо дополнительную информацию о них (скажем, записи о событиях наподобие посещения ветеринара или рождения потомства), понадобится еще одна таблица. Давайте определимся с ее структурой. Эта таблица должна содержать:

  • имена животных, чтобы не путаться с тем, к какому животному относится какое событие
  • дата события
  • поле для описания события
  • поле, отражающее тип события, для того, чтобы можно было распределить их по категориям

С учетом всех приведенных выше требований можно составить примерно такую команду CREATE TABLE:

mysql> CREATE TABLE event (name VARCHAR(20), date DATE,
    -> type VARCHAR(15), remark VARCHAR(255));

Как и в случае с таблицей pet, начальные данные в таблицу проще всего загрузить, создав текстовый файл с информацией, разделенной символами табуляции:

name | date | type | remark
Fluffy | 1995-05-15 | litter | 4 kittens, 3 female, 1 male
Buffy | 1993-06-23 | litter | 5 puppies, 2 female, 3 male
Buffy | 1994-06-19 | litter | 3 puppies, 3 female
Chirpy | 1999-03-21 | vet | needed beak straightened
Slim | 1997-08-03 | vet | broken rib
Bowser | 1991-10-12 | kennel |
Fang | 1991-10-12 | kennel |
Fang | 1998-08-28 | birthday | Gave him a new chew toy
Claws | 1998-03-17 | birthday | Gave him a new flea collar
Whistler | 1998-12-09 | birthday | First birthday

Загрузите записи с помощью следующей команды:

mysql> LOAD DATA LOCAL INFILE "event.txt" INTO TABLE event;

Используя знания, усвоенные при работе с таблицей pet, вы сможете загружать данные из таблицы event; принципы здесь те же. Но что если самой по себе таблицы event перестанет хватать для получения нужных вам ответов?

Предположим, нужно узнать, в каком возрасте животные давали приплод. В таблице event указаны даты родов, но для того, чтобы рассчитать возраст матери, нужно знать и дату ее рождения. Так как даты рождения хранятся в таблице pet, в этом запросе нужно использовать обе таблицы:

mysql> SELECT pet.name,
    -> (TO_DAYS(date) - TO_DAYS(birth))/365 AS age,
    -> remark
    -> FROM pet, event
    -> WHERE pet.name = event.name AND type = "litter";
+--------+------+-----------------------------+
| name   | age  | remark                      |
+--------+------+-----------------------------+
| Fluffy | 2.27 | 4 kittens, 3 female, 1 male |
| Buffy  | 4.12 | 5 puppies, 2 female, 3 male |
| Buffy  | 5.10 | 3 puppies, 3 female         |
+--------+------+-----------------------------+

На некоторые аспекты этого запроса следует обратить особое внимание:

  • В выражении FROM указаны две таблицы, так как запрос будет получать информацию из обеих.
  • При комбинировании (объединении) информации из нескольких таблиц необходимо указать, как строки одной таблицы связываются с записями другой. Это просто, так как в обеих таблицах есть столбец с именами. В этом запросе выражение WHERE используется для сопоставления записей из двух таблиц по значениям имен.
  • Так как столбец name присутствует в обеих таблицах, нужно явно указать, какую именно таблицу вы имеете в виду, ссылаясь на данный столбец. Это можно сделать, связав имя таблицы с именем столбца.

Для объединения не обязательно иметь две отдельные таблицы; иногда можно объединить таблицу с самой собой - если нужно сравнить одни записи таблицы с другими записями той же таблицы. Например, для того, чтобы обнаружить среди животных ``семейные пары'', можно объединить таблицу pet с ней самой, составив пары животных разного пола, но одного вида:

mysql> SELECT p1.name, p1.sex, p2.name, p2.sex, p1.species
    -> FROM pet AS p1, pet AS p2
    -> WHERE p1.species = p2.species AND p1.sex = "f" AND p2.sex = "m";
+--------+------+--------+------+---------+
| name   | sex  | name   | sex  | species |
+--------+------+--------+------+---------+
| Fluffy | f    | Claws  | m    | cat     |
| Buffy  | f    | Fang   | m    | dog     |
| Buffy  | f    | Bowser | m    | dog     |
+--------+------+--------+------+---------+

В этом запросе мы указываем псевдонимы имен таблицы, для обращения к столбцам и определения, к какой из таблиц относится каждая ссылка на столбец.

3.4 Получение информации о базах данных и таблицах

Как быть, если вы забыли имя базы или таблицы, или структуру какой-либо из таблиц (например имена столбцов)? В MySQL эта проблема решается при помощи нескольких команд, выводящих информацию о базе данных и содержащихся в ней таблицах.

Вы уже познакомились с командой SHOW DATABASES, выводящей список управляемых сервером баз данных. Определить, какая из них выбрана в данный момент, можно с помощью функции DATABASE():

mysql> SELECT DATABASE();
+------------+
| DATABASE() |
+------------+
| menagerie  |
+------------+

Если ни одна из баз не выбрана, результат будет пуст.

Выяснить, какие таблицы содержит текущая база данных (что необходимо, если, например, никак не получается вспомнить имя нужной таблицы), можно при помощи следующей команды:

mysql> SHOW TABLES;
+---------------------+
| Tables in menagerie |
+---------------------+
| event               |
| pet                 |
+---------------------+

Узнать структуру таблицы можно при помощи команды DESCRIBE, которая выводит информацию о каждом из столбцов таблицы:

mysql> DESCRIBE pet;
+---------+-------------+------+-----+---------+-------+
| Field   | Type        | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| name    | varchar(20) | YES  |     | NULL    |       |
| owner   | varchar(20) | YES  |     | NULL    |       |
| species | varchar(20) | YES  |     | NULL    |       |
| sex     | char(1)     | YES  |     | NULL    |       |
| birth   | date        | YES  |     | NULL    |       |
| death   | date        | YES  |     | NULL    |       |
+---------+-------------+------+-----+---------+-------+

Field - имя столбца, Type - тип данных, к которому относится этот столбец, NULL указывает, может ли данный столбец содержать значения NULL, Key - является ли этот столбец индексным, и, наконец, Default указывает значение данного столбца по умолчанию.

Если для таблицы созданы индексы, информацию о них можно получить с помощью команды SHOW INDEX FROM tbl_name.

3.5 Примеры стандартных запросов

Здесь представлены примеры решения некоторых стандартных задач средствами MySQL.

В некоторых из примеров используется таблица shop (магазин), в которой содержатся цены по каждому изделию (item number)для определенных продавцов (dealer). Предположим, что каждый продавец имеет одну фиксированную цену для каждого изделия; тогда пара изделие-продавец (article, dealer) является первичным ключом для записей таблицы.

Запустите клиента mysql:

mysql имя-вашей-базы-данных

(Для большинства инсталляций MySQL можно использовать базу данных 'test'.)

Таблицу примера можно создать таким образом:

CREATE TABLE shop (
 article INT(4) UNSIGNED ZEROFILL DEFAULT '0000' NOT NULL,
 dealer  CHAR(20)                 DEFAULT ''     NOT NULL,
 price   DOUBLE(16,2)             DEFAULT '0.00' NOT NULL,
 PRIMARY KEY(article, dealer));

INSERT INTO shop VALUES
(1,'A',3.45),(1,'B',3.99),(2,'A',10.99),(3,'B',1.45),(3,'C',1.69),
(3,'D',1.25),(4,'D',19.95);

Ну и, скажем, данные для примера будут такими:

mysql> SELECT * FROM shop;

+---------+--------+-------+
| article | dealer | price |
+---------+--------+-------+
|    0001 | A      |  3.45 |
|    0001 | B      |  3.99 |
|    0002 | A      | 10.99 |
|    0003 | B      |  1.45 |
|    0003 | C      |  1.69 |
|    0003 | D      |  1.25 |
|    0004 | D      | 19.95 |
+---------+--------+-------+

3.5.1 Максимальное значение столбца

"Как определить наибольшее значение в столбце?"

SELECT MAX(article) AS article FROM shop

+---------+
| article |
+---------+
|       4 |
+---------+

3.5.2 Строка, содержащая максимальное значение некоторого столбца

"Как определить номер, дилера и цену самого дорогого изделия?"

В ANSI SQL (и MySQL 4.1) это легко делается при помощи вложенного запроса:

SELECT article, dealer, price
FROM   shop
WHERE  price=(SELECT MAX(price) FROM shop)

В версиях MySQL до 4.1 такая задача выполняется в два этапа:

  1. Следует получить максимальное значение цены из таблицы при помощи оператора SELECT.
  2. Используя это значение, необходимо составить следующий запрос:
    SELECT article, dealer, price
FROM   shop
WHERE  price=19.95

Существует еще одно решение: отсортировать все строки по убыванию цен и после этого получить первую строку, используя специальный оператор LIMIT:

SELECT article, dealer, price
FROM   shop
ORDER BY price DESC
LIMIT 1

Примечание: если существует несколько самых дорогих изделий (например, каждое из них стоит 19,95), запрос, использующий LIMIT, возвращает лишь одно из них!

3.5.3 Максимальное значение столбца для группы

"Как определить наибольшую цену по каждому изделию?"

SELECT article, MAX(price) AS price
FROM   shop
GROUP BY article

+---------+-------+
| article | price |
+---------+-------+
|    0001 |  3.99 |
|    0002 | 10.99 |
|    0003 |  1.69 |
|    0004 | 19.95 |
+---------+-------+

3.5.4 Строка, содержащая максимальное значение некоторого столбца

"Для каждого изделия, как определить дилер(ов) с самыми высокими ценами?"

В ANSI SQL (и MySQL 4.1) это легко делается при помощи вложенного запроса:

SELECT article, dealer, price
FROM   shop s1
WHERE  price=(SELECT MAX(s2.price)
              FROM shop s2
              WHERE s1.article = s2.article);

В MySQL до 4.1 такая задача выполняется в два этапа:

  1. Следует получить список (изделие, максимальная цена)
  2. Для каждого изделия, получить соответствующие записи, в которых цена соответствует максимальной.

Это легко делается с помощью временной таблицы:

CREATE TEMPORARY TABLE tmp (
        article INT(4) UNSIGNED ZEROFILL DEFAULT '0000' NOT NULL,
        price   DOUBLE(16,2)             DEFAULT '0.00' NOT NULL);

LOCK TABLES shop read;

INSERT INTO tmp SELECT article, MAX(price) FROM shop GROUP BY article;

SELECT shop.article, dealer, shop.price FROM shop, tmp
WHERE shop.article=tmp.article AND shop.price=tmp.price;

UNLOCK TABLES;

DROP TABLE tmp;

Если вы не используете ключевое слово TEMPORARY, вам также следует поставить блокировку на таблицу tmp.

"А можно ли это сделать одним запросом?"

Да, но только используя совершенно неэффективный трюк, который я называю "Трюк MAX-CONCAT":

SELECT article,
       SUBSTRING( MAX( CONCAT(LPAD(price,6,'0'),dealer) ), 7) AS dealer,
  0.00+LEFT(      MAX( CONCAT(LPAD(price,6,'0'),dealer) ), 6) AS price
FROM   shop
GROUP BY article;

+---------+--------+-------+
| article | dealer | price |
+---------+--------+-------+
|    0001 | B      |  3.99 |
|    0002 | A      | 10.99 |
|    0003 | C      |  1.69 |
|    0004 | D      | 19.95 |
+---------+--------+-------+

Разумеется, последний пример можно сделать чуть эффективнее, если разбиение катенизированной строки делать на стороне клиента.

3.5.5 Использование пользовательских переменных

В MySQL для хранения результатов, чтобы не держать их во временных переменных на клиенте, можно применять пользовательские переменные (see section 6.1.4 Переменные пользователя).

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

mysql> SELECT @min_price:=MIN(price),@max_price:=MAX(price) FROM shop;
mysql> SELECT * FROM shop WHERE price=@min_price OR price=@max_price;
+---------+--------+-------+
| article | dealer | price |
+---------+--------+-------+
|    0003 | D      |  1.25 |
|    0004 | D      | 19.95 |
+---------+--------+-------+

3.5.6 Использование внешних ключей

В MySQL 3.23.44 и выше в таблицах InnoDB осуществляется проверка ограничений целостности внешних ключей (обратитесь к разделам section 7.5 Таблицы InnoDB и section 1.9.4.5 Внешние ключи).

Фактически для соединения двух таблиц внешние ключи не нужны.

Единственное, что MySQL в настоящее время не осуществляет (в типах таблиц, отличных от InnoDB), это проверку (CHECK) что ключи, которые вы используете, действительно существуют в таблице(ах) на которые вы ссылаетесь, и не удаляет автоматически записи из таблиц с определением внешних ключей. Если же ключи используются обычным образом, все будет работать просто чудесно:

CREATE TABLE person (
    id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
    name CHAR(60) NOT NULL,
    PRIMARY KEY (id)
);

CREATE TABLE shirt (
    id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
    style ENUM('t-shirt', 'polo', 'dress') NOT NULL,
    color ENUM('red', 'blue', 'orange', 'white', 'black') NOT NULL,
    owner SMALLINT UNSIGNED NOT NULL REFERENCES person(id),
    PRIMARY KEY (id)
);

INSERT INTO person VALUES (NULL, 'Antonio Paz');

INSERT INTO shirt VALUES
(NULL, 'polo', 'blue', LAST_INSERT_ID()),
(NULL, 'dress', 'white', LAST_INSERT_ID()),
(NULL, 't-shirt', 'blue', LAST_INSERT_ID());

INSERT INTO person VALUES (NULL, 'Lilliana Angelovska');

INSERT INTO shirt VALUES
(NULL, 'dress', 'orange', LAST_INSERT_ID()),
(NULL, 'polo', 'red', LAST_INSERT_ID()),
(NULL, 'dress', 'blue', LAST_INSERT_ID()),
(NULL, 't-shirt', 'white', LAST_INSERT_ID());

SELECT * FROM person;
+----+---------------------+
| id | name                |
+----+---------------------+
|  1 | Antonio Paz         |
|  2 | Lilliana Angelovska |
+----+---------------------+

SELECT * FROM shirt;
+----+---------+--------+-------+
| id | style   | color  | owner |
+----+---------+--------+-------+
|  1 | polo    | blue   |     1 |
|  2 | dress   | white  |     1 |
|  3 | t-shirt | blue   |     1 |
|  4 | dress   | orange |     2 |
|  5 | polo    | red    |     2 |
|  6 | dress   | blue   |     2 |
|  7 | t-shirt | white  |     2 |
+----+---------+--------+-------+

SELECT s.* FROM person p, shirt s
 WHERE p.name LIKE 'Lilliana%'
   AND s.owner = p.id
   AND s.color <> 'white';

+----+-------+--------+-------+
| id | style | color  | owner |
+----+-------+--------+-------+
|  4 | dress | orange |     2 |
|  5 | polo  | red    |     2 |
|  6 | dress | blue   |     2 |
+----+-------+--------+-------+

3.5.7 Поиск по двум ключам

MySQL пока не осуществляет оптимизации, если поиск производится по двум различным ключам, которые связаны при помощи оператора OR (поиск по одному ключу с различными частями OR оптимизируется хорошо):

SELECT field1_index, field2_index FROM test_table WHERE field1_index = '1'
OR  field2_index = '1'

Причина заключается в том, что у нас не было времени, чтобы придумать эффективный способ обработки этого случая (сравните: обработка оператора AND теперь работает хорошо)

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

CREATE TEMPORARY TABLE tmp
SELECT field1_index, field2_index FROM test_table WHERE field1_index = '1';
INSERT INTO tmp
SELECT field1_index, field2_index FROM test_table WHERE field2_index = '1';
SELECT * from tmp;
DROP TABLE tmp;

Вышеупомянутый способ выполнения этого запроса - это фактически UNION (объединение) двух запросов. See section 6.4.1.2 Синтаксис оператора UNION.

3.5.8 Подсчет посещений за день

В этом разделе представлен пример использования групповых побитовых функций для вычисления дней месяца, когда пользователь заходил на веб-сайт.

CREATE TABLE t1 (year YEAR(4), month INT(2) UNSIGNED ZEROFILL,
             day INT(2) UNSIGNED ZEROFILL);
INSERT INTO t1 VALUES(2000,1,1),(2000,1,20),(2000,1,30),(2000,2,2),
            (2000,2,23),(2000,2,23);
SELECT year,month,BIT_COUNT(BIT_OR(1<<day)) AS days FROM t1
       GROUP BY year,month;

Which returns:

+------+-------+------+
| year | month | days |
+------+-------+------+
| 2000 |    01 |    3 |
| 2000 |    02 |    2 |
+------+-------+------+

Этот запрос подсчитывает, сколько различных дней входит в данную комбинацию год/месяц, автоматически исключая дублирующиеся значения.

3.5.9 Использование атрибута AUTO_INCREMENT

Атрибут AUTO_INCREMENT может использоваться для генерации уникального идентификатора для новых строк:

CREATE TABLE animals (
             id MEDIUMINT NOT NULL AUTO_INCREMENT,
             name CHAR(30) NOT NULL,
             PRIMARY KEY (id)
             );
INSERT INTO animals (name) VALUES ("dog"),("cat"),("penguin"),
                                  ("lax"),("whale");
SELECT * FROM animals;

Что вернет:

+----+---------+
| id | name    |
+----+---------+
|  1 | dog     |
|  2 | cat     |
|  3 | penguin |
|  4 | lax     |
|  5 | whale   |
+----+---------+

Вы можете получить AUTO_INCREMENT ключ с помощью функции SQL LAST_INSERT_ID() или с помощью функции mysql_insert_id() интерфейса C.

Для многострочной вставки, LAST_INSERT_ID()/mysql_insert_id() на самом деле вернут AUTO_INCREMENT значение для первой вставленной записи. Это сделано для того, чтобы многострочные вставки можно было повторить на других серверах.

В таблицах MyISAM и BDB можно определить AUTO_INCREMENT для вторичного столбца составного ключа. В этом случае значение, генерируемое для автоинкрементного столбца, вычисляется как MAX(auto_increment_column)+1) WHERE prefix=given-prefix. Столбец с атрибутом AUTO_INCREMENT удобно использовать, когда данные нужно помещать в упорядоченные группы.

CREATE TABLE animals (
             grp ENUM('fish','mammal','bird') NOT NULL,
             id MEDIUMINT NOT NULL AUTO_INCREMENT,
             name CHAR(30) NOT NULL,
             PRIMARY KEY (grp,id)
             );
INSERT INTO animals (grp,name) VALUES("mammal","dog"),("mammal","cat"),
                  ("bird","penguin"),("fish","lax"),("mammal","whale");
SELECT * FROM animals ORDER BY grp,id;

Что вернет:

+--------+----+---------+
| grp    | id | name    |
+--------+----+---------+
| fish   |  1 | lax     |
| mammal |  1 | dog     |
| mammal |  2 | cat     |
| mammal |  3 | whale   |
| bird   |  1 | penguin |
+--------+----+---------+

Обратите внимание, что в этом случае значение AUTO_INCREMENT будет использоваться повторно, если в какой-либо группе удаляется строка, содержащая наибольшее значение AUTO_INCREMENT.

3.6 Использование mysql в пакетном режиме

В предыдущих разделах было показано, как использовать mysql в интерактивном режиме, вводя запросы и тут же просматривая результаты. Запускать mysql можно и в пакетном режиме. Для этого нужно собрать все команды в один файл и передать его на исполнение mysql:

shell> mysql < batch-file

Если вы работаете с mysql в ОС Windows, и некоторые из специальных символов, содержащихся в пакетном файле, могут вызвать проблемы, воспользуйтесь следующей командой:

dos> mysql -e "source batch-file"

Если необходимо указать параметры соединения в командной строке, она может иметь следующий вид:

shell> mysql -h host -u user -p < batch-file
Enter password: ********

Работая с mysql таким образом, вы, в сущности, создаете сценарий и затем исполняете его.

Если нужно продолжать обработку сценария даже при обнаружении в нем ошибок, воспользуйтесь параметром командной строки --force.

Зачем вообще нужны сценарии? Причин тому несколько:

  • При необходимости частого (ежедневного или хотя бы еженедельного) запуска одного и того же запроса сценарий позволяет избавиться от многократного набора этого запроса.
  • Можно создавать новые запросы, подобные уже существующим, просто копируя и затем изменяя файлы сценариев.
  • Пакетный режим может пригодиться и при разработке особенно длинных запросов, а именно - многострочных команд или больших последовательностей команд. В таком деле одна допущенная ошибка может привести к необходимости повторного набора большого количества текста. Зато при работе со сценарием легко исправить ошибку и запустить запрос на повторное исполнение.
  • Если ваш запрос выводит на экран много текста, его можно просмотреть постранично, не мучаясь догадками относительно убежавшей за край экрана части результатов:
    shell> mysql < batch-file | more
  • Выводимые запросом результаты можно сохранить в файле для последующей обработки:
    shell> mysql < batch-file > mysql.out
  • Свой сценарий вы можете дать кому-нибудь еще, чтобы он тоже мог воспользоваться содержащимися в сценарии командами.
  • В некоторых случаях работать в интерактивном режиме просто не получается. И здесь без пакетного режима не обойтись.

По умолчанию при работе с mysql в пакетном режиме используется более сжатый формат вывода результатов, чем при интерактивной работе. В интерактивном режиме результаты работы запроса SELECT DISTINCT species FROM pet выглядят так:

+---------+
| species |
+---------+
| bird    |
| cat     |
| dog     |
| hamster |
| snake   |
+---------+

А в пакетном - вот так:

species
bird
cat
dog
hamster
snake

Если вам нужно, чтобы в пакетном режиме программа выводила данные так же, как и в интерактивном, воспользуйтесь ключом mysql -t. Включить "эхо" исполняемых команд можно с помощью ключа mysql -vvv.

В командную строку mysql можно включать и сценарии - при помощи команды source:

mysql> source filename;

3.7 Запросы проекта "Близнецы" (Twin Project)

В Analytikerna и Lentus мы проводили сбор и систематизацию данных в рамках крупного исследовательского проекта. Этот проект разрабатывается совместно Институтом экологической медицины Karolinska Institutet, Стокгольм и отделением клинических исследований в области старения и психологии университета Южной Калифорнии.

В проекте предусмотрен этап опросов, на котором происходит опрос по телефону всех проживающих в Швеции близнецов старше 65 лет. Близнецы, отвечающие критериям отбора, переходят на следующий этап. На этом этапе желающих участвовать в проекте близнецов посещает врач с медсестрой. Проводятся физические и нейропсихологические исследования, лабораторные анализы, неврологическое обследование, оценка психологического состояния, а также собираются данные по истории семьи. Кроме того, осуществляется сбор информации о медицинских и экологических факторах риска.

Дополнительную информацию о проекте вы можете получить по адресу: http://www.imm.ki.se/TWIN/TWINUKW.HTM

На поздних этапах администрирование проекта осуществляется с помощью web-интерфейса, написанного на Perl и MySQL.

Каждую ночь собранные во время интервью данные заносятся в базу данных MySQL.

3.7.1 Поиск нераспределенных близнецов

Этот запрос определяет, которые из близнецов переходят во второй этап проекта:

SELECT
        CONCAT(p1.id, p1.tvab) + 0 AS tvid,
        CONCAT(p1.christian_name, " ", p1.surname) AS Name,
        p1.postal_code AS Code,
        p1.city AS City,
        pg.abrev AS Area,
        IF(td.participation = "Aborted", "A", " ") AS A,
        p1.dead AS dead1,
        l.event AS event1,
        td.suspect AS tsuspect1,
        id.suspect AS isuspect1,
        td.severe AS tsevere1,
        id.severe AS isevere1,
        p2.dead AS dead2,
        l2.event AS event2,
        h2.nurse AS nurse2,
        h2.doctor AS doctor2,
        td2.suspect AS tsuspect2,
        id2.suspect AS isuspect2,
        td2.severe AS tsevere2,
        id2.severe AS isevere2,
        l.finish_date
FROM
        twin_project AS tp
        /* For Twin 1 */
        LEFT JOIN twin_data AS td ON tp.id = td.id
                  AND tp.tvab = td.tvab
        LEFT JOIN informant_data AS id ON tp.id = id.id
                  AND tp.tvab = id.tvab
        LEFT JOIN harmony AS h ON tp.id = h.id
                  AND tp.tvab = h.tvab
        LEFT JOIN lentus AS l ON tp.id = l.id
                  AND tp.tvab = l.tvab
        /* For Twin 2 */
        LEFT JOIN twin_data AS td2 ON p2.id = td2.id
                  AND p2.tvab = td2.tvab
        LEFT JOIN informant_data AS id2 ON p2.id = id2.id
                  AND p2.tvab = id2.tvab
        LEFT JOIN harmony AS h2 ON p2.id = h2.id
                  AND p2.tvab = h2.tvab
        LEFT JOIN lentus AS l2 ON p2.id = l2.id
                  AND p2.tvab = l2.tvab,
        person_data AS p1,
        person_data AS p2,
        postal_groups AS pg
WHERE
        /* p1 gets main twin and p2 gets his/her twin. */
        /* ptvab is a field inverted from tvab */
        p1.id = tp.id AND p1.tvab = tp.tvab AND
        p2.id = p1.id AND p2.ptvab = p1.tvab AND
        /* Just the sceening survey */
        tp.survey_no = 5 AND
        /* Skip if partner died before 65 but allow emigration (dead=9) */
        (p2.dead = 0 OR p2.dead = 9 OR
         (p2.dead = 1 AND
          (p2.death_date = 0 OR
           (((TO_DAYS(p2.death_date) - TO_DAYS(p2.birthday)) / 365)
            >= 65))))
        AND
        (
        /* Twin is suspect */
        (td.future_contact = 'Yes' AND td.suspect = 2) OR
        /* Twin is suspect - Informant is Blessed */
        (td.future_contact = 'Yes' AND td.suspect = 1
                                   AND id.suspect = 1) OR
        /* No twin - Informant is Blessed */
        (ISNULL(td.suspect) AND id.suspect = 1
                            AND id.future_contact = 'Yes') OR
        /* Twin broken off - Informant is Blessed */
        (td.participation = 'Aborted'
         AND id.suspect = 1 AND id.future_contact = 'Yes') OR
        /* Twin broken off - No inform - Have partner */
        (td.participation = 'Aborted' AND ISNULL(id.suspect)
                                      AND p2.dead = 0))
        AND
        l.event = 'Finished'
        /* Get at area code */
        AND SUBSTRING(p1.postal_code, 1, 2) = pg.code
        /* Not already distributed */
        AND (h.nurse IS NULL OR h.nurse=00 OR h.doctor=00)
        /* Has not refused or been aborted */
        AND NOT (h.status = 'Refused' OR h.status = 'Aborted'
        OR h.status = 'Died' OR h.status = 'Other')
ORDER BY
        tvid;

Дадим к этому запросу некоторые пояснения:

CONCAT(p1.id, p1.tvab) + 0 AS tvid
Сортируем по взаимосвязи id и tvab в числовом порядке. Прибавление нуля к результату заставляет MySQL обращаться с результатом как с числом.
column id
Определяет пару близнецов. Является ключевым полем всех таблиц.
column tvab
Определяет близнеца в паре. Принимает значение 1 или 2.
column ptvab
Отрицание tvab. Если значение tvab равно 1, значение этого поля - 2, и наоборот. Данное поле облегчает MySQL задачу оптимизации запроса и экономит время ввода данных.

Этот запрос иллюстрирует, помимо всего прочего, сравнение значений одной таблицы с помощью команды JOIN (p1 и p2). В этом примере таким образом проверяется, не умер ли один из близнецов до достижения им 65-летнего возраста. Если так и произошло, строка не попадает в список возвращаемых.

Все вышеприведенные поля имеются во всех таблицах, в которых хранится относящаяся к близнецам информация. Ключевыми полями для ускорения работы запросов назначены id,tvab (во всех таблицах), а также id,ptvab (person_data).

На нашем рабочем компьютере (200МГц UltraSPARC) этот запрос возвращает 150-200 строк, и его выполнение занимает менее секунды.

Текущее количество строк в таблицах, использовавшихся выше:
Таблица | Строки
person_data | 71074
lentus | 5291
twin_project | 5286
twin_data | 2012
informant_data | 663
harmony | 381
postal_groups | 100

3.7.2 Вывод таблицы состояний пар близнецов

Каждый опрос оканчивается кодом состояния, называющимся event (``событие''). Приведенный здесь запрос выводит данные обо всех парах близнецов, объединенные по полю event. Таблица наглядно показывает, с каким количеством пар близнецов работа полностью завершена, а в каком количестве пар работа с одним близнецом завершена, а с другим - нет и т.п.

SELECT
        t1.event,
        t2.event,
        COUNT(*)
FROM
        lentus AS t1,
        lentus AS t2,
        twin_project AS tp
WHERE
        /* We are looking at one pair at a time */
        t1.id = tp.id
        AND t1.tvab=tp.tvab
        AND t1.id = t2.id
        /* Just the sceening survey */
        AND tp.survey_no = 5
        /* This makes each pair only appear once */
        AND t1.tvab='1' AND t2.tvab='2'
GROUP BY
        t1.event, t2.event;

3.8 Использование MySQL совместно с Apache

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

Формат записи журналов Apache можно привести в легко понятную MySQL форму, введя в файл настроек Apache следующие строки:

LogFormat \
        "\"%h\",%{%Y%m%d%H%M%S}t,%>s,\"%b\",\"%{Content-Type}o\",  \
        \"%U\",\"%{Referer}i\",\"%{User-Agent}i\""

В MySQL же можно сделать примерно следующее:

LOAD DATA INFILE '/local/access_log' INTO TABLE table_name
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' ESCAPED BY '\\'


Справочное руководство по MySQL версии 5.0.0-alpha. - 4 Администрирование баз данных

4 Администрирование баз данных

4.1 Конфигурирование MySQL

4.1.1 Параметры командной строки mysqld

В большинстве случаев управление параметрами mysqld осуществляется при помощи файлов параметров (see section 4.1.2 Файлы параметров `my.cnf').

mysqld и mysqld.server считывают параметры из групп mysqld и server. mysqld_safe считывает параметры из групп mysqld, server, mysqld_safe и safe_mysqld. Встроенный сервер MySQL обычно считывает параметры из server, embedded и xxxxx_SERVER, где xxxxx - имя приложения.

mysqld принимает следующие параметры командной строки (для получения полного списка выполните mysqld --help):

--ansi
Использовать синтаксис ANSI SQL вместо синтаксиса MySQL (see section 1.9.2 Запуск MySQL в режиме ANSI).
-b, --basedir=path
Путь к каталогу установки. Все остальные пути обычно определяются относительно этого пути.
--big-tables
Позволяет использовать наборы результатов большого объема за счет сохранения всех временных файлов в одном. Данный параметр позволяет устранить большинство ошибок 'table full' (таблица переполнена), но замедляет обработку запросов, для которых было бы достаточно таблиц, расположенных в памяти. Начиная с версии 3.23.2 в MySQL эта проблема решается автоматически: память используется для небольших временных таблиц, а при необходимости происходит переключение на таблицы, расположенные на диске.
--bind-address=IP
IP-адрес, с которым необходимо установить связь.
--console
Писать журнал сообщений/ошибок в stderr/stdout даже если --log-error указана. На Windows mysqld просто не будет закрывать консольное окно если указана эта опция.
--character-sets-dir=path
Каталог, в котором расположены наборы символов (see section 4.6.1 Набор символов, применяющийся для записи данных и сортировки).
--chroot=path
Изменяет корневой каталог программы mysqld во время запуска. Рекомендуемая мера безопасности для MySQL 4.0 (MySQL 3.23 не вполне в состоянии предоставить 100% измененную среду запуска). Эта опция некоторым образом ограничивает использование функций LOAD DATA INFILE и SELECT ... INTO OUTFILE.
--core-file
Записывает файл ядра, если происходит аварийное прекращение работы mysqld. В некоторых системах также необходимо указать --core-file-size для safe_mysqld (see section 4.7.2 safe_mysqld, оболочка mysqld). Обратите внимание на то, что в некоторых системах, таких как Solaris, не удастся записать файл ядра, если используется параметр --user.
-h, --datadir=path
Путь к корневому каталогу базы данных.
--debug[...]=
Если MySQL настроен при помощи --with-debug, то этот параметр позволяет получить файл трассировки, в котором отражена работа mysqld (see section D.1.2 Создание трассировочных файлов).
--default-character-set=charset
Задает набор символов, принятый по умолчанию (see section 4.6.1 Набор символов, применяющийся для записи данных и сортировки).
--default-table-type=type
Задает тип таблиц, принятый по умолчанию (see section 7 Типы таблиц MySQL).
--delay-key-write[= OFF | ON | ALL]
Указывает, как на MyISAM DELAYED KEYS должен обрабатываться. See section 5.5.2 Настройка параметров сервера.
--delay-key-write-for-all-tables; В MySQL 4.0.3 следует использовать --delay-key-write=ALL.
Отмена сброса на диск ключевых буферов для всех таблиц MyISAM между записями. See section 5.5.2 Настройка параметров сервера.
--des-key-file=filename
Задает считывание из файла filename принятых по умолчанию ключей, которые используются для DES_ENCRYPT() и DES_DECRYPT().
--enable-external-locking (было --enable-locking)
Включает блокировку доступа к системе. Обратите внимание на то, что если этот параметр используется в системе, где функция lockd полностью не работает (например, в Linux), это может привести к зависанию mysqld.
--enable-named-pipe
Включает поддержку для именованных каналов (только в NT/Win2000/XP).
-T, --exit-info
Побитовое маскирование различных флагов, которое применяется для отладки сервера mysqld; не следует использовать этот параметр, если вы хорошо не разбираетесь в том, что именно он делает!
--flush
Задает сброс на диск всех изменений после каждой команды SQL. Обычно MySQL только направляет все изменения на диск после каждой команды SQL, делегируя управление синхронизацией записи на диск операционной системе (see section A.4.1 Что делать, если работа MySQL сопровождается постоянными сбоями).
-?, --help
Вывод сокращенной справки и завершение выполнения.
--init-file=file
Задает считывание команды SQL из файла file при запуске.
-L, --language=...
Вывод сообщений об ошибках клиента на указанном языке. Может быть задан в виде полного пути (see section 4.6.2 Сообщения об ошибках на языках, отличных от английского).
-l, --log[=file]
Задает занесение в файл журнала соединений и запросов (see section 4.9.2 Общий журнал запросов).
--log-bin=[file]
Двоичный журнал обновлений. Сохранение всех запросов, изменяющих данные, в файл. Используется для архивного копирования и репликации. See section 4.9.4 Бинарный журнал обновлений.
--log-bin-index[=file]
Имя индексного файла для двоичного журнала обновлений. See section 4.9.4 Бинарный журнал обновлений.
--log-error[=file]
Писать ошибки и сообщения в этот файл. See section 4.9.1 Журнал ошибок.
--log-isam[=file]
Заносит в файл журнала все изменения ISAM/MyISAM (используется только при отладке ISAM/MyISAM).
--log-slow-queries[=file]
Заносит в файл журнала все запросы, выполнение которых заняло больше, чем long_query_time секунд (see section 4.9.5 Журнал медленных запросов).
--log-update[=file]
Заносит в файл журнала обновления file.# где # представляет собой уникальный номер, если он не был задан (see section 4.9.3 Журнал обновлений (update)).
--log-long-format
Заносит в файл журнала обновлений некоторую дополнительную информацию. Если задано --log-slow-queries, то запросы, не использующие индексов, будут заноситься в журнал медленных запросов.
--low-priority-updates
Операциям по изменению таблиц (INSERT/DELETE/UPDATE) будет назначен более низкий приоритет, чем операциям выбора. Это также можно реализовать при помощи {INSERT | REPLACE | UPDATE | DELETE} LOW_PRIORITY ..., чтобы понизить приоритет только одного запроса, или через SET LOW_PRIORITY_UPDATES=1, чтобы изменить приоритет в одном потоке (see section 5.3.2 Вопросы блокирования таблиц).
--memlock
Фиксирует процесс mysqld в памяти. Этот параметр работает только в том случае, если ваша система поддерживает системный вызов mlockall(), например Solaris. Такая мера может быть полезной, если операционная система записывает mysqld в файл подкачки на диск.
--myisam-recover [=параметр[,параметр...]]]
Параметр - это любое сочетание DEFAULT, BACKUP, FORCE или QUICK. Если необходимо отключить данную функцию, укажите вместо набора параметров явно "". Если эта функция используется, mysqld проверит таблицу на предмет того, была ли она отмечена как сбойная или не была закрыта надлежащим образом (последний вариант действует только в том случае, если был включен параметр --skip-external-locking). В любом из этих случаев mysqld произведет полную проверку таблицы. Если таблица была повреждена, mysqld попытается ее восстановить. Приведенные ниже параметры влияют на работу процесса восстановления.
Параметр | Описание
DEFAULT | Аналогично отсутствию каких-либо параметров для функции --myisam-recover.
BACKUP | Если во время восстановления таблица данных была изменена, сохраняется резервная копия файла данных `table_name.MYD' под именем `table_name-datetime.BAK'.
FORCE | Запуск восстановления, даже если будет утрачено более одной строки из файла `.MYD'.
QUICK | Не проверять строки в таблице, в которых отсутствуют удаленные блоки.
Перед автоматическим восстановлением таблицы MySQL добавит запись об этом в журнал ошибок. Если необходимо, чтобы восстановление после большинства ошибок осуществлялось без вмешательства пользователя, следует установить параметры BACKUP и FORCE. Тогда восстановление будет производиться даже в случае, если некоторые строки будут удалены, но файл данных будет сохраняться в виде резервной копии, поэтому впоследствии всегда можно будет определить, что произошло.
--pid-file=path
Путь к pid-файлу используется функцией safe_mysqld.
-P, --port=...
Номер порта для прослушивания соединений TCP/IP.
-o, --old-protocol
Использовать протокол 3.20 для совместимости с некоторыми очень старыми клиентами (see section 2.5.5 Модернизация с версии 3.20 до версии 3.21).
--one-thread
Использовать только один поток (для отладки в системе Linux) (see section D.1 Отладка сервера MySQL).
-O, --set-variable var=option
Задает значение для переменной. --help - выводит список переменных. Подробное описание всех переменных можно найти в разделе SHOW VARIABLES этого руководства (see section 4.5.6.4 SHOW VARIABLES). Обратите внимание, --set-variable морально устарела с версии MySQL 4.0. Просто используйте --var=option. See section 5.5.2 Настройка параметров сервера. В MySQL 4.0.2 вы можете устанавливать переменную непосредственно с помощью --variable-name=option, и set-variable больше не нужна в файлах опций. Если вы хотите ограничить максимальное значение, в которое может быть установлена пемеременная при помощи SET, определите это значение с помощью опции --maximum-variable-name See section 5.5.6 Синтаксис команды SET. Когда переменная будет устанавливаться в какое-либо значение, MySQL автоматически будет корректировать его, чтобы оно оставалось в указананных рамках; также MySQL может немного корректировать установленное значение с тем, чтобы эффективнее использовались внутренние алгоритмы. Раздел по настройке параметров сервера включает информацию по их оптимизации (see section 5.5.2 Настройка параметров сервера).
--safe-mode
Пропуск некоторых этапов оптимизации.
--safe-show-database
При использовании этого параметра команда SHOW DATABASES выдает только те базы данных, для которых у пользователя есть какие-либо привилегии. Начиная с версии 4.0.2 этот параметр является недействительным и больше ни на что не влияет (его значение установлено по умолчанию), так как в новой версии появилась привилегия SHOW DATABASES (see section 4.3.1 Синтаксис команд GRANT и REVOKE).
--safe-user-create
Когда этот параметр включен, пользователь не может создавать новых пользователей при помощи команды GRANT, если он не имеет привилегии INSERT для таблицы mysql.user или для любого столбца этой таблицы.
--skip-bdb
Запретить использование таблиц BDB. Это сэкономит память и может ускорить работу.
--skip-concurrent-insert
Отключает возможность одновременного выбора и вставки данных для таблиц MyISAM (используется только в том случае, если в этой функции найдена ошибка).
--skip-delay-key-write; в MySQL 4.0.3 следует использовать --delay-key-write=OFF
Игнорирует параметр DELAY_KEY_WRITE для всех таблиц (see section 5.5.2 Настройка параметров сервера).
--skip-grant-tables
Включение данного параметра приводит к тому, что сервер совсем не использует систему привилегий - таким образом полный доступ ко всем базам данных получают все! (Можно дать серверу команду снова использовать таблицы доступа, запустив mysqladmin flush-privileges или mysqladmin reload.)
--skip-host-cache
Никогда не использовать кэш имени главного компьютера для быстрого разрешения соответствий имен и IP-адресов, а вместо этого всегда запрашивать DNS-сервер по каждому соединению (see section 5.5.5 Как MySQL использует DNS).
--skip-innodb
Запретить использование таблиц InnoDB. Это сэкономит память и может ускорить работу.
--skip-external-locking (было --skip-locking)
Не использовать средства системных блокировок. Чтобы воспользоваться функциями isamchk или myisamchk, необходимо выключить сервер (see section 1.4.3 Насколько стабильным является MySQL?). Обратите внимание на то, что в MySQL версии 3.23 для восстановления или проверки таблиц MyISAM можно использовать REPAIR и CHECK.
--skip-name-resolve
Не производится разрешения имен хостов. Все значения в столбце Host в таблицах привилегий должны быть IP-адресами или значениями localhost (see section 5.5.5 Как MySQL использует DNS).
--skip-networking
Прослушивание соединений TCP/IP не производится. Связь с mysqld должна осуществляться через сокеты Unix. Этот параметр рекомендуется для систем, в которых разрешены только локальные запросы (see section 5.5.5 Как MySQL использует DNS).
--skip-new
Не использовать новые (возможно, неправильные) операции.
--skip-symlink
Не удалять и не переименовывать файлы, на которые указывает файл symlinked в каталоге данных.
--skip-safemalloc
Если MySQL настроен при помощи --with-debug=full, все программы будут проверять память на наличие выхода за границы области памяти при каждом заполнении и освобождении памяти. Поскольку такая проверка осуществляется довольно медленно, от нее можно отказаться, воспользовавшись этим параметром.
--skip-show-database
Не позволяет использовать команду SHOW DATABASES, если пользователь не имеет привилегии SHOW DATABASES. Начиная с версии 4.0.2 этот параметр больше не нужен, поскольку доступ теперь может быть разрешен при помощи привилегии SHOW DATABASES.
--skip-stack-trace
Не записывать трассировку стеков. Этот параметр может оказаться полезным, когда mysqld запущен под отладчиком. В некоторых системах данный параметр также необходимо использовать для получения файла ядра (see section D.1 Отладка сервера MySQL).
--skip-thread-priority
Отключает использование приоритетов потока, чтобы уменьшить время ожидания ответа.
--socket=path
Файл канала, который используется для локального соединения вместо файла, принятого по умолчанию, /tmp/mysql.sock.
--sql-mode=параметр[,параметр[,параметр...]]
Параметр может представлять собой любое сочетание из: REAL_AS_FLOAT, PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, SERIALIZE, ONLY_FULL_GROUP_BY. Если нужно произвести сброс значения, параметр может быть пустым (""). Указание всех приведенных выше параметров аналогично использованию --ansi. При помощи этого параметра можно включать только необходимые режимы SQL (see section 1.9.2 Запуск MySQL в режиме ANSI).
--temp-pool
При указании данного параметра для создаваемых временных файлов будет использоваться ограниченный набор имен вместо создания уникального имени для каждого нового файла. Данная функция предназначена для устранения проблемы ядра Linux, возникающей при создании большого количества новых файлов с разными именами. По старой схеме в Linux как бы происходит 'утечка' памяти, так как она распределяется для кэша каталогов вместо дискового кэша.
--transaction-isolation= { READ-UNCOMMITTED | READ-COMMITTED |
REPEATABLE-READ | SERIALIZABLE } Задает принятый по умолчанию уровень изоляции транзакции (see section 6.7.3 Синтаксис команды SET TRANSACTION).
-t, --tmpdir=path
Путь для временных файлов. Может быть полезен, если принятый по умолчанию каталог /tmp расположен на слишком маленьком диске и не может вместить все временные таблицы. Начиная с MySQL 4.1, эта опция поддержает указание нескольких путей, разделенных двоеточием : (на Windows - точкой с запятой ;). Эти пути будут использованы в ротации.
-u, --user= [user_name | userid]
Запуск демона mysqld от имени пользователя user_name или userid (число). Этот параметр является обязательным при запуске mysqld в качестве главной программы. Начиная с MySQL 3.23.56 и 4.0.12: Для того, чтобы избежать возможного пробоя в безопасности когда пользователь добавляет опцию --user=root в один из файлов `my.cnf', mysqld лишь только будет использовать первую указанную опцию --user и давать предупреждение если указано множество таких опций. Имейте в виду, что `/etc/my.cnf' и `datadir/my.cnf' могут перекрыть опцию командной строки - таким образом, рекомендовано указывать эту опцию именно в `/etc/my.cnf'.
-V, --version
Вывод информации по версии программы и завершение выполнения.
-W, --log-warnings (было --warnings)
Задает запись таких предупреждений, как Aborted connection... в файл `.err' (see section A.2.9 Коммуникационные ошибки / Оборванные соединения.

Большая часть значений может быть изменена в процессе работы сервера с помощью команды SET. See section 5.5.6 Синтаксис команды SET.

4.1.2 Файлы параметров `my.cnf'

Начиная с версии 3.22 MySQL может считывать принятые по умолчанию параметры запуска для сервера и клиентов из файлов параметров.

В Unix считывание принятых по умолчанию параметров MySQL производится из следующих файлов:

Имя файла | Назначение
/etc/my.cnf | Общие параметры
DATADIR/my.cnf | Параметры для сервера
defaults-extra-file | Файл, указанный при помощи -defaults-extra-file=#
~/.my.cnf | Параметры для пользователя

DATADIR является каталогом данных MySQL (обычно `/usr/local/mysql/data' для бинарной установки или `/usr/local/var' для установки из исходных текстов). Обратите внимание, что это тот каталог, который был задан во время настройки, а не указанный при помощи --datadir при запуске mysqld! (--datadir не оказывает влияния на просмотр файлов параметров сервером, так как их просмотр происходит до обработки аргументов командной строки).

В Windows считывание принятых по умолчанию параметров MySQL производится из следующих файлов:

Имя файла | Назначение
windows-system-directory\my.ini | Общие параметры
C:\my.cnf | Общие параметры

Обратите внимание на то, что в Windows все пути необходимо указывать при помощи / вместо \. Если необходимо использовать \, то его нужно указать дважды, так как \ является знаком перехода в MySQL.

MySQL пытается прочитать файлы параметров в указанном выше порядке. Если существует несколько таких файлов, то параметр, указанный в файле, идущем позже, имеет преимущество над таким же параметром, указанным в файле, расположенном ранее. Параметры, указанные в командной строке, обладают более высоким приоритетом по отношению к параметрам, указанным в любом из файлов параметров. Некоторые параметры можно задавать при помощи переменных окружения. Параметры, указанные в командной строке или в файлах параметров, обладают преимуществом по отношению к переменным окружения (see section E Переменные окружения).

Приводим список программ, поддерживающих файлы параметров: mysql, mysqladmin, mysqld, mysqld_safe, mysql.server, mysqldump, mysqlimport, mysqlshow, mysqlcheck, myisamchk и myisampack.

Любой параметр, который может быть задан в командной строке при запуске программы MySQL, может быть также задан в файле параметров (без предваряющего двойного слэша). Чтобы получить список доступных параметров, следует запустить программу с параметром --help.

Файлы параметров могут содержать строки следующего вида:

#comment
Строки комментариев начинаются с символа `#' или `;'. Пустые строки игнорируются.
[group]
группа представляет собой имя программы или группы, для которой необходимо задать параметры. Любые параметры или строки, задающие значения переменных, которые указаны после строки группы, будут относиться к названной группе, пока не закончится файл параметров или же не будет указана другая строка группы.
option
Эквивалент --option в командной строке.
option=value
Эквивалент --option=value в командной строке.
set-variable = variable=value
Эквивалент --set-variable variable=value в командной строке. Данный синтаксис необходимо использовать для задания переменных mysqld. Заметьте, --set-variable не используется с MySQL 4.0. Просто используйте --variable=value.

Группа client обеспечивает возможность задавать параметры, относящиеся ко всем клиентам MySQL (кроме самого mysqld). Эта группа великолепно подходит для указания пароля, используемого при подсоединении к серверу (но при этом следует убедиться, что разрешение на чтение и запись этого файла есть только у вас).

Обратите внимание на то, что для параметров и значений все введенные перед ними и после них пробелы автоматически удаляются. В строках значений можно использовать такие экранирующие секвенции: `\b', `\t', `\n', `\r', `\\' и `\s' (`\s' - это пробел).

Пример типичного глобального файла параметров:

[client]
port=3306
socket=/tmp/mysql.sock

[mysqld]
port=3306
socket=/tmp/mysql.sock
set-variable = key_buffer_size=16M
set-variable = max_allowed_packet=1M

[mysqldump]
quick

Пример типичного файла параметров пользователя:

[client]
# Указанный пароль будет направлен всем стандартным клиентам MySQL
password=my_password

[mysql]
no-auto-rehash
set-variable = connect_timeout=2

[mysqlhotcopy]
interactive-timeout

Если у вас дистрибутив исходного кода, то примеры конфигурационных файлов с именами `my-xxxx.cnf' можно найти в каталоге `support-files'. В случае бинарного дистрибутива следует обратиться к каталогу `DIR/support-files', где DIR - имя каталога установки MySQL (обычно `/usr/local/mysql'). На данный момент там приведены примеры файлов конфигурации для малых, средних, больших и очень больших систем. Чтобы поэкспериментировать с файлом, можно скопировать `my-xxxx.cnf' в свой домашний каталог (переименуйте копию в `.my.cnf').

Все поддерживающие файлы параметров клиенты MySQL принимают следующие параметры:

Параметр | Описание
--no-defaults | Не читать информацию из файлов параметров.
--print-defaults | Вывести имя программы и все параметры, которые ей передаются.
--defaults-file=full-path-to-default-file | Использовать только указанный файл конфигурации.
--defaults-extra-file=full-path-to-default-file | Прочитать этот файл конфигурации после глобального файла конфигурации, но перед файлом конфигурации пользователя.

Обратите внимание на то, что указанные выше параметры должны идти первыми в командной строке! Однако параметр --print-defaults может использоваться сразу после команд --defaults-xxx-file.

Примечание для разработчиков: обработка файла параметров происходит следующим образом: все совпадающие параметры (т.е. параметры в соответствующих группах) обрабатываются перед любыми аргументами командной строки. Этот алгоритм хорошо подходит для программ, которые в случае, если один и тот же параметр указывается несколько раз, используют последний экземпляр параметра. Если же вы работаете со старой программой, которая считывает заданные несколько раз параметры указанным образом, но не читает файлы параметров, необходимо добавить только две строки, чтобы у нее появилась эта возможность. Чтобы увидеть, как это делается, достаточно ознакомиться с исходным кодом любого стандартного клиента MySQL.

В скриптах оболочки для анализа файлов config можно использовать команду `my_print_defaults':

shell> my_print_defaults client mysql
--port=3306
--socket=/tmp/mysql.sock
--no-auto-rehash

Приведенные выше выходные данные содержат все параметры для групп client и mysql.

4.1.3 Установка нескольких серверов на один компьютер

В некоторых случаях необходимо, чтобы на одном компьютере работало несколько различных серверов mysqld: например, если нужно запустить для тестирования новую версию MySQL совместно со старой версией, которая находится в работе, или когда разным пользователям нужно предоставить доступ к различным серверам mysqld, с которыми они умеют обращаться самостоятельно.

Один из способов запустить новый сервер -- указать ему другой канал и порт, например, таким образом:

shell> MYSQL_UNIX_PORT=/tmp/mysqld-new.sock
shell> MYSQL_TCP_PORT=3307
shell> export MYSQL_UNIX_PORT MYSQL_TCP_PORT
shell> scripts/mysql_install_db
shell> bin/safe_mysqld &

Приложение, в котором описаны переменные окружения, включает список других переменных окружения, которые можно использовать для управления mysqld (see section E Переменные окружения).

В приведенном выше примере представлен грубый быстрый метод, который обычно применяется для тестирования. Преимуществом данного метода является то, что все соединения, которые устанавливаются в указанной выше оболочке, автоматически направляются на новый запущенный сервер!

Если работать с несколькими серверами необходимо постоянно, то нужно создать файл параметров для каждого сервера (see section 4.1.2 Файлы параметров `my.cnf'). В скрипте запуска, который выполняется при каждой загрузке, следует указать оба сервера:

safe_mysqld --defaults-file=path-to-option-file

Для серверов должны быть различными по крайней мере следующие параметры:

  • port=#
  • socket=path
  • pid-file=path

Приведенные ниже параметры, если они используются, также должны различаться:

  • log=path
  • log-bin=path
  • log-update=path
  • log-isam=path
  • bdb-logdir=path
  • shared-memory-base-name (Новое в MySQL 4.1)

Если требуется увеличить производительность, необходимо также задать разные значения для следующих параметров:

  • tmpdir=path
  • bdb-tmpdir=path

See section 4.1.1 Параметры командной строки mysqld. Начиная с MySQL 4.1, в tmpdir могут быть указаны несколько путей, разделенных двоеточием : (точкой с запятой на Windows ;). Эти пути будут использованы в ротации. Эта функция может быть использована для того, чтобы распределить данные между разными физическими дисками.

Если производится установка бинарной версии MySQL (файлы .tar), которая запускается из ./bin/safe_mysqld, то в большинстве случаев единственными параметрами, которые необходимо добавить/изменить, являются аргументы socket и port для safe_mysqld.

See section 4.1.4 Запуск нескольких серверов MySQL на одном компьютере.

4.1.4 Запуск нескольких серверов MySQL на одном компьютере

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

Если необходимо запустить несколько серверов, то проще всего скомпилировать серверы с различными портами TCP/IP и файлами сокетов (see section 4.7.3 Mysqld_multi, программа для управления множеством серверов MySQL).

Предположим, что существующий сервер настроен на принятые по умолчанию номер порта и файл сокета. Настроим новый сервер при помощи команды configure следующим образом:

shell> ./configure --with-tcp-port=port_number \
             --with-unix-socket-path=file_name \
             --prefix=/usr/local/mysql-3.22.9

Здесь port_number и file_name должны отличаться от принятого по умолчанию номера порта и пути файла сокета, а значение --prefix должно указывать каталог установки, который отличается от того, в котором установлен текущий MySQL.

Проверить сокет, используемый установленным на данный момент сервером MySQL, можно при помощи следующей команды:

shell> mysqladmin -h hostname --port=port_number variables

Обратите внимание: если указать ``localhost'' как имя удаленного компьютера, mysqladmin по умолчанию будет использовать сокеты Unix вместо TCP/IP.

В MySQL 4.1 вы также можете указать протокол, который надлежит использовать с помощью опции --protocol=(TCP | SOCKET | PIPE | MEMORY).

Если на используемом порту находится сервер MySQL, то будет выдан список самых важных настраиваемых переменных в MySQL, включая имя сокета.

Повторно компилировать новый сервер MySQL нет необходимости, его просто нужно запустить с другими параметрами для порта и сокета. Используемые порт и сокет можно изменить, указав их как параметры запуска для safe_mysqld:

shell> /path/to/safe_mysqld --socket=file_name --port=port_number

Модуль mysqld_multi может также в качестве аргумента принимать safe_mysqld (или mysqld) и передавать параметры из файла конфигурации для safe_mysqld и дальше для mysqld.

Если новый сервер запускается на том же каталоге базы данных, что и другой сервер с включенной записью в журналы, необходимо также указать имена файлов журналов для safe_mysqld при помощи параметров --log, --log-update или --log-slow-queries. Иначе оба сервера могут попытаться осуществить запись в один и тот же файл журнала.

Предупреждение: обычно нельзя допускать, чтобы два сервера одновременно заносили данные в одну и ту же базу данных! Если ваша операционная система не поддерживает безотказную блокировку доступа, это может привести к возникновению неприятных сюрпризов!

Если для второго сервера понадобится использовать другой каталог базы данных, можно воспользоваться параметром --datadir=path для safe_mysqld.

Обратите внимание: запуск нескольких серверов MySQL (mysqlds) на различных компьютерах с доступом к одному каталогу данных через сетевую файловую систему обычно не приводит ни к чему хорошему! Проблема состоит в том, что сетевая файловая система становится узким местом для передачи данных. Она не предназначена для такого использования. И даже в этом случае придется искать решение, которое позволит обеспечить отсутствие конфликтов между двумя или более модулями mysqld. На данный момент не существует платформы, которая обеспечивает на 100% надежную блокировку доступа к файлам (обычно демон lockd) во всех возможных ситуациях. Кроме того, существует еще одна опасность при использовании сетевой файловой системы: эта система может еще больше усложнить работу программы lockd. Поэтому лучше смотреть на вещи проще и забыть об этой идее. Оптимальным решением будет использование одного компьютера с несколькими центральными процессорами и с операционной системой, которая эффективно управляет потоками.

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

  • Запустите клиент с параметрами --host 'hostname' --port=port_number, чтобы подсоединиться через TCP/IP, или [--host localhost --socket=file_name], чтобы подсоединиться через сокет Unix.
  • Запускайте ваш клиент с --protocol=tcp для подключения по TCP/IP и --protocol=socket для подключения через сокет Unix.
  • В своей программе на языке C или Perl можно задать аргументы порта или сокета при подсоединении к серверу MySQL.
  • При использовании модуля Perl DBD::mysql можно прочитать параметры из файлов параметров MySQL (see section 4.1.2 Файлы параметров `my.cnf').
    $dsn = "DBI:mysql:test;mysql_read_default_group=client;
mysql_read_default_file=/usr/local/mysql/data/my.cnf"
$dbh = DBI->connect($dsn, $user, $password);
  • Задайте переменные окружения MYSQL_UNIX_PORT и MYSQL_TCP_PORT, чтобы указать на сокет Unix и порт TCP/IP до запуска клиентов. Если обычно используются конкретные сокет или порт, команды для задания этих переменных окружения необходимо поместить в свой файл `.login' (see section E Переменные окружения).
  • Укажите принятые по умолчанию сокет и порт TCP/IP в файле `.my.cnf' в своем домашнем каталоге (see section 4.1.2 Файлы параметров `my.cnf').

4.2 Общие проблемы безопасности и система привилегий доступа MySQL

MySQL имеет развитую, но нестандартную систему обеспечения безопасности и привилегий доступа. В этом разделе дается описание ее работы.

4.2.1 Общие принципы обеспечения безопасности

С данным разделом должны ознакомиться все, кто использует MySQL на компьютерах, подключенных к Internet, - чтобы избежать наиболее распространенных ошибок, приводящих к нарушению безопасности системы.

При обсуждении вопросов безопасности мы акцентируем внимание на необходимости защиты всего серверного хоста (а не одного лишь сервера MySQL) от всех возможных типов атак: перехвата, внесения изменений, считывания и отказа в обслуживании. Данный раздел не охватывает всех аспектов готовности к работе и отказоустойчивости.

Используемая в MySQL система безопасности для всех подключений, запросов и иных операций, которые может пытаться выполнить пользователь, базируется на списках контроля доступа ACLs (Access Control Lists). Обеспечивается также некоторая поддержка SSL-соединений между клиентами и серверами MySQL. Многие из рассматриваемых здесь концепций не относятся исключительно к MySQL; те же общие соображения применимы практически ко всем приложениям.

При работе в MySQL старайтесь следовать приведенным ниже инструкциям:

  • Не предоставляйте никому (за исключением пользователя mysql под именем root) доступа к таблице user в базе данных mysql! Это чрезвычайно важно. В MySQL зашифрованный пароль является реальным паролем. Узнав пароль, занесенный в таблицу user, и имея доступ к удаленному компьютеру, занесенному в соответствующую учетную запись, войти в систему под именем зарегистрированного владельца пароля легко может кто угодно.
  • Изучите систему прав доступа MySQL. Для управления доступом к MySQL служат команды GRANT и REVOKE. Предоставляйте ровно столько прав, сколько необходимо, и не больше. Никогда не предоставляйте права всем хостам. Полезно проводить следующие контрольные проверки:
    • Выполните команду mysql -u root. Если удается успешно установить соединение с сервером без получения запроса пароля, значит, у вас имеются проблемы. Это означает, что кто угодно может подсоединиться к вашему серверу MySQL как клиент MySQL под именем root, получая таким образом право неограниченного доступа! Проанализируйте инструкцию по инсталляции MySQL, обращая особое внимание на ту часть, которая касается задания пароля пользователя root.
    • С помощью команды SHOW GRANTS проверьте, кто и к каким ресурсам имеет доступ. Воспользуйтесь командой REVOKE, отмените права доступа, которые не являются необходимыми.
  • Не храните в базе данных незашифрованных паролей. Если злоумышленнику удастся получить доступ на ваш компьютер, то в его руках окажется полный список паролей, которыми он может воспользоваться. Применяйте для шифрования MD5(), SHA1() или другие односторонние хеш-функции.
  • Не используйте в качестве пароля слова из словарей. Для взлома такого рода паролей имеются специальные программы. Даже слова типа ``xfish98'' - это очень плохие пароли. Куда лучше ``duag98'': здесь используется то же слово ``fish'', но при этом буквы в нем заменены ближайшими к ним слева буквами клавиатуры QWERTY. Еще один метод - составить парольное слово из первых букв слов какого либо словосочетания, например ``Mhall'' - по фразе ``Mary had a little lamb.'' Такой пароль легко запоминается и его легко вводить. А вот разгадать его тому, кто не знает ключевой фразы, будет непросто.
  • Приобретите брандмауэр. Эта мера обеспечит защиту как минимум от половины всех видов несанкционированного использования любого ПО, с которым вы работаете. Разместите MySQL за брандмауэром или в демилитаризованной зоне (demilitarised zone - DMZ). Полезно проводить следующие контрольные проверки:
  • Попробуйте просканировать ваши порты из Internet с помощью утилиты типа nmap. MySQL использует по умолчанию порт 3306. Этот порт должен быть недоступен с неблагонадежных компьютеров. Еще один простой способ проверить, открыт или нет ваш MySQL-порт, - попытаться выполнить с какой либо удаленной машины следующую команду, где server_host - имя хоста, на котором установлен ваш сервер MySQL:
    shell> telnet server_host 3306
    Если соединение будет установлено, и вы получите какие-либо бессмысленные символы, это будет означать, что порт открыт, и его нужно закрыть на брандмауэре или маршрутизаторе (если, конечно, нет действительно веских причин держать его открытым). Если же telnet просто зависнет или в подсоединении будет отказано, тогда все в порядке: порт заблокирован.
  • Не доверяйте никаким данным, которые вводят пользователи. Возможны попытки перехитрить вашу программу путем ввода последовательностей специальных или экранированных символов в веб-формы, URL-ы или любое приложение, созданное вами. Убедитесь, что защита вашего приложения не будет нарушена, если пользователь введет что-нибудь типа "'; DROP DATABASE mysql;''. Это крайний случай, но действия хакеров, использующих подобную технологию, могут привести к потере информации и появлению брешей в системе безопасности, если вы не готовы к ним. Не следует также забывать о необходимости проверки цифровых данных (распространенной ошибкой является защита только строк). Некоторые полагают, что если в базе данных хранятся только открытые данные, то в ее защите нет необходимости. Это неверно. Такие базы могут стать объектом успешных атак типа отказа от обслуживания. Простейший способ защиты от взломов такого типа - заключать числовые константы в кавычки: SELECT * FROM table WHERE ID='234', а не SELECT * FROM table WHERE ID=234. MySQL автоматически преобразует эту строку в число и выбросит из нее все нецифровые символы. Полезно проводить следующие контрольные проверки:
    • Для всех веб-приложений:
      • Попробуйте ввести во все ваши веб-формы одинарные и двойные кавычки - `'' и `"'. Если MySQL выдаст любое сообщение об ошибке, немедленно разберитесь, в чем дело.
      • Попробуйте видоизменять динамические URL, добавляя в них %22 (`"'), %23 (`#'), и %27 (`'').
      • Попробуйте модифицировать типы данных в динамических URL - замените числовые на символьные, используя символы из предыдущих примеров. Ваше приложение должно быть устойчиво к подобного рода атакам.
      • Попробуйте вводить в числовые поля вместо цифр буквы, пробелы и специальные символы. Ваше приложение должно либо удалять их до передачи в MySQL, либо выдавать сообщение об ошибке. Пропускать в MySQL значения без проверки очень опасно!
      • Проверяйте размер данных перед тем, как они будут переданы в MySQL.
      • При подключении приложения к базе данных лучше использовать имя пользователя, отличное от того, которое вы используете для целей администрирования. Не предоставляйте своим приложениям больше прав доступа, чем это необходимо.
    • Пользователям PHP:
      • Проверьте функцию addslashes(). Что касается PHP 4.0.3, то в нем имеется функция mysql_escape_string(), базирующаяся на функции с тем же именем из MySQL C API.
    • Пользователям MySQL C API:
      • Проверьте API-вызов mysql_real_escape_string().
    • Пользователям MySQL++:
      • Проверьте такие модификаторы, как escape и quote, - для потоков запросов.
    • Пользователям Perl DBI:
      • Проверьте метод quote() или используйте для проверки заполнители.
    • Пользователям Java JDBC:
      • Используйте для проверки объект PreparedStatement и символы-заполнители.
  • Не передавайте по Internet открытые (незашифрованные) данные. Они могут оказаться у кого угодно, имеющего достаточно времени и возможностей для того, чтобы перехватить их и использовать в своих целях. Используйте вместо этого протоколы с шифрованием данных, такие как SSL и SSH. MySQL, начиная с версии 4.0.0, поддерживает собственные SSL-соединения. Пересылка по SSH (SSH Port Forwarding) может быть использована для создания туннеля передачи данных с шифрованием и сжатием.
  • Научитесь пользоваться утилитами tcpdump и strings. В большинстве случаев проверить, являются ли потоки данных MySQL зашифрованными, можно с помощью команды, подобной той, которая приведена ниже:
    shell> tcpdump -l -i eth0 -w - src or dst port 3306 | strings
    (Она работает под Linux, и будет, с незначительными изменениями, работать под другими системами.) Предупреждение: если вы не видите данных, это еще не гарантирует того, что они зашифрованы. Если требуется высокий уровень безопасности, обратитесь к экспертам в этой области.

4.2.2 Как обезопасить MySQL от хакеров

При подключении к серверу MySQL используется, как правило, пароль. По линии связи пароль не передается в виде открытого текста, но алгоритм шифрования не очень сложный. Толковый хакер, если ему удастся перехватить трафик между клиентом и сервером, при определенной настойчивости может взломать пароль. Поэтому если связь между клиентом и сервером осуществляется по ненадежной сети, для шифрования связи следует использовать SSH-туннель.

Вся остальная информация передается в текстовом виде и может быть прочитана кем угодно, кто в состоянии отлеживать подключение. Если это вас беспокоит, можно воспользоваться протоколом со сжатием данных (в MySQL 3.22 и последующих версиях), что значительно затруднит подобные действия. Чтобы еще более повысить безопасность связи, следует использовать протокол ssh. Open source-клиент ssh доступен на веб-сайте http://www.openssh.org/, а коммерческий ssh-клиент можно получить на веб-сайте http://www.ssh.com/. С помощью такого протокола можно обеспечить зашифрованную связь по протоколу TCP/IP между сервером MySQL и клиентом MySQL.

Если вы используете MySQL 4.0, то можете также использовать предусмотренную в этой версии поддержку протокола OpenSSL. Обратитесь к разделу See section 4.3.9 Использование безопасных соединений.

Для обеспечения безопасности MySQL-системы необходимо строго придерживаться следующих рекомендаций:

  • У всех пользователей MySQL должны быть пароли. Для приложений клиент/сервер является общепринятым, что клиент может указывать любое имя пользователя, но если для other_user не задан пароль, то кто угодно может зайти под любым именем, просто введя mysql -u other_user db_name. Чтобы этого избежать, можно изменить пароль для всех пользователей, отредактировав скрипт mysql_install_db перед запуском приложения, или только пароль для root-пользователя MySQL, как это показано ниже:
    shell> mysql -u root mysql
mysql> UPDATE user SET Password=PASSWORD('new_password')
           WHERE user='root';
mysql> FLUSH PRIVILEGES;
  • Не запускайте демон MySQL от имени пользователя Unix root. Это очень опасно, потому что любой пользователь, имеющий привилегию FILE, будет в состоянии создавать файлы как пользователь root (например ~root/.bashrc). Чтобы предотвратить это, mysqld откажется запускаться от имени пользователя root, если это не будет задано напрямую с помощью опции --user=root. В то же время mysqld может быть запущена от имени обычного непривилегированного пользователя. Можно также, в целях еще большего укрепления безопасности, создать новый аккаунт Unix-пользователя mysql. При запуске mysqld от имени другого пользователя Unix у вас отпадает необходимость заменять имя пользователя root в таблице user, так как имена пользователя в MySQL не имеют ничего общего с аккаунтами пользователей Unix. Для запуска mysqld от имени другого пользователя Unix добавьте в группу [mysqld] файла опций `/etc/my.cnf' или файла опций `my.cnf', находящегося в каталоге данных сервера, строку user, задающую имя пользователя. Например:
    [mysqld]
user=mysql
    В результате сервер будет запущен от имени назначенного пользователя, независимо от того, производится запуск вручную или посредством safe_mysqld или mysql.server. Для получения дополнительной информации обратитесь к разделу See section A.3.2 Запуск MySQL от обычного пользователя.
  • Откажитесь от поддержки символических ссылок на таблицы (ее можно запретить с помощью опции --skip-symlink). Это особенно важно в том случае, если вы запускаете mysqld от имени пользователя root, поскольку у того, кто имеет право доступа для записи в каталоги данных mysqld, появляется возможность стереть любой файл в системе! Обратитесь к разделу See section 5.6.1.2 Использование символических ссылок для таблиц.
  • Удостоверьтесь, что пользователь Unix, от имени которого запускается mysqld, является единственным пользователем, имеющим привилегии чтения/записи в директории базы данных.
  • Не предоставляйте привилегии PROCESS всем пользователям. Команда mysqladmin processlist выводит текст запросов, обрабатываемых в данный момент. Следовательно, любой пользователь, имеющий право на выполнение этой команды, получает возможность прочитать, например, такой запрос другого пользователя, как UPDATE user SET password=PASSWORD('not_secure'). mysqld резервирует добавочное подключение для пользователей, имеющих привилегию PROCESS, так что пользователь MySQL под именем root может подключиться и осуществлять контроль даже в том случае, когда все обычные подключения заняты.
  • Не предоставляйте привилегии FILE всем пользователям. Любой пользователь, имеющий такую привилегию, может записать в любом месте файловой системы файл с привилегиями демона mysqld! Чтобы обеспечить здесь хоть минимальную защиту, все файлы создаваемые с помощью команды SELECT ... INTO OUTFILE, сделаны общедоступными для записи, но перезаписать существующие файлы нельзя. Привилегия FILE может быть также использована для чтения любого файла, доступного пользователю Unix, от имени которого запускается сервер. Можно также прочитать любой файл в текущую базу данных. Это может быть использовано в корыстных целях. Возможно, например, с помощью команды LOAD DATA загрузить `/etc/passwd' в таблицу и прочесть ее позже с помощью SELECT.
  • Если вы не доверяете своему DNS-серверу, используйте в таблицах привилегий вместо имен хостов IP-адреса. В любом случае следует очень осторожно относиться к внесению в таблицы привилегий записей, в которых значения имени хоста содержат шаблонные символы!
  • Чтобы ограничить число подключений, доступных для отдельного пользователя, можно в mysqld задать значение переменной max_user_connections.

4.2.3 Опции запуска mysqld, относящиеся к безопасности

К безопасности имеют отношение следующие опции mysqld:

--local-infile[=(0|1)]
При установке опции --local-infile=0 теряется возможность выполнять команду LOAD DATA LOCAL INFILE.
--safe-show-database
Если установлена эта опция, команда SHOW DATABASES возвращает только те базы данных, для которых пользователь имеет какую-либо привилегию. Начиная с версии 4.0.2 эта опция отменена и не служит ни для чего (она включена по умолчанию), т.к. сейчас у нас имеется привилегия SHOW DATABASES. Обратитесь к разделу See section 4.3.1 Синтаксис команд GRANT и REVOKE.
--safe-user-create
При установке этой опции пользователь не может создавать новых пользователей с помощью команды GRANT, если у него отсутствует привилегия INSERT для таблицы mysql.user. Чтобы предоставить пользователю доступ именно для создания новых пользователей с теми привилегиями, которые он имеет право предоставлять, для этого пользователя следует установить следующую привилегию:
mysql> GRANT INSERT(user) ON mysql.user TO 'user'&hacute;ostname';
Задание такой привилегии гарантирует, что этот пользователь не сможет непосредственно вносить изменения ни в одном из столбцов привилегий, а для предоставления привилегий другим пользователям должен будет использовать команду GRANT.
--skip-grant-tables
Установка этой опции запрещает серверу вообще использовать систему привилегий. Это открывает кому бы то ни было полный доступ ко всем базам данных! (После запуска сервера можно заставить его снова использовать таблицы привилегий с помощью команды mysqladmin flush-privileges или mysqladmin reload.)
--skip-name-resolve
При установке данной опции имена хостов не разрешены. Все значения в столбцах Host таблиц привилегий должны быть либо IP-адресами, либо localhost.
--skip-networking
Не разрешает осуществлять подсоединений по протоколу TCP/IP через сеть (данная опция запрещает такие подсоединения). Все подсоединения к mysqld должны осуществляться посредством сокетов Unix. Для MySQL старше 3.23.27 эта опция непригодна для систем, в которых используются MIT-потоки, так как MIT-потоки на тот момент не поддерживали сокеты Unix.
--skip-show-database
Разрешает выполнение команды SHOW DATABASES только в том случае, если пользователь имеет привилегию SHOW DATABASES. Начиная с версии 4.0.2 в этой опции больше нет необходимости, т.к. теперь доступ может предоставляться избирательно с помощью привилегии SHOW DATABASES.

4.2.4 Вопросы безопасности, относящиеся к команде LOAD DATA LOCAL

Чтобы решить проблемы безопасности, которые могут возникнуть при использовании команды LOAD DATA LOCAL,в MySQL 3.23.49 и MySQL 4.0.2 были добавлены новые опции.

При поддержке этой команды могут возникнуть две проблемы:

Первая: поскольку чтение файла инициируется сервером, теоретически имеется возможность создать ``доработанный'' при помощи патча сервер MySQL, способный читать любые файлы на клиентской машине, к которой текущий пользователь имеет доступ для чтения, в то время, когда клиент направляет запрос к таблице.

Вторая: в веб-среде, в которой подсоединение клиентов осуществляется с веб-сервера, пользователь может использовать команду LOAD DATA LOCAL для чтения любых файлов, к которым процесс веб-сервера имеет доступ для чтения (если предположить, что пользователь может выполнять на сервере SQL любые команды).

Эти проблемы решаются с помощью двух следующих исправлений:

Если вы конфигурируете MySQL без опции --enable-local-infile, то команда LOAD DATA LOCAL будет запрещена для всех клиентов, если, конечно, они не будут вызывать mysql_options (... MYSQL_OPT_LOCAL_INFILE, 0). Обратитесь к разделу See section 8.4.3.39 mysql_options().

В случае клиента mysql, LOAD DATA LOCAL может быть разблокирована заданием опции --local-infile[=1] или заблокирована с помощью опции --local-infile=0.

По умолчанию все MySQL-клиенты и библиотеки компилируются с опцией --enable-local-infile для обеспечения совместимости с MySQL 3.23.48 и более старыми версиями.

Блокировку всех команд LOAD DATA LOCAL на MySQL-сервере можно осуществить путем запуска mysqld с опцией --local-infile=0.

В случае, если команда LOAD DATA LOCAL INFILE заблокирована на сервере или клиенте, вы получите следующее сообщение об ошибке (1148):

The used command is not allowed with this MySQL version

4.2.5 Функции, выполняемые системой привилегий

Основной функцией системы привилегий MySQL является аутентификация пользователя, подключающегося с указанного хоста, и ассоциирование его с привилегиями базы данных, такими как SELECT, INSERT, UPDATE и DELETE.

К дополнительным функциональным возможностям системы привилегий относятся следующие: возможность обслуживания анонимного пользователя и предоставление привилегий для таких специфических для MySQL функций, как LOAD DATA INFILE и функции администрирования.

4.2.6 Как работает система привилегий

Система привилегий MySQL обеспечивает пользователям возможность выполнять только те действия, которые им разрешены в соответствии с их обязанностями. Когда вы подсоединяетесь к серверу MySQL, ваша личность устанавливается по имени хоста, с которого вы подсоединяетесь, и имени пользователя, которое вы указываете. Система предоставляет привилегии в соответствии с вашей личностью и тем, что вы хотите делать.

MySQL идентифицирует пользователя как по имени хоста, так и по имени пользователя, т.к. нет оснований полагать что данное имя пользователя принадлежит во всей Сети единственному человеку. Например, пользователь joe, устанавливающий соединение с office.com, вовсе не обязательно один и тот же человек, что и пользователь joe, подсоединяющийся с elsewhere.com. MySQL решает эту проблему, обеспечивая возможность различать пользователей, подсоединяющихся с различных хостов под одним и тем же именем пользователя: вы можете предоставлять joe один набор привилегий, если он подсоединяется с office.com, и другой набор привилегий, если joe подсоединяется с elsewhere.com.

Управление доступом в MySQL осуществляется в два этапа:

  • Этап 1: сервер проверяет, имеется ли у вас вообще разрешение на подсоединение. 2item Этап 2: если таковое имеется, сервер проверяет каждый из ваших запросов, чтобы убедиться в том, что у вас имеется достаточно привилегий для его выполнения. Например, если вы пытаетесь выбрать строки в таблице базы данных или удалить таблицу из базы данных, сервер в первом случае проверяет, имеется ли у вас для этой таблицы привилегия SELECT, а во втором - имеется ли у вас для этой базы данных привилегия DROP.

На обеих стадиях управления доступом сервер использует таблицы user, db и host из базы данных mysql. Ниже перечислены поля этих таблиц привилегий:

Имя таблицы | user | db | host
Поля контекста | Host | Host | Host
 | User | Db | Db
 | Password | User |
Поля привилегий | Select_priv | Select_priv | Select_priv
 | Insert_priv | Insert_priv | Insert_priv
 | Update_priv | Update_priv | Update_priv
 | Delete_priv | Delete_priv | Delete_priv
 | Index_priv | Index_priv | Index_priv
 | Alter_priv | Alter_priv | Alter_priv
 | Create_priv | Create_priv | Create_priv
 | Drop_priv | Drop_priv | Drop_priv
 | Grant_priv | Grant_priv | Grant_priv
 | References_priv |  |
 | Reload_priv |  |
 | Shutdown_priv |  |
 | Process_priv |  |
 | File_priv |  |

На втором этапе управления доступом (верификация запросов) сервер может (в случае, если запрос относится к таблицам базы данных) дополнительно обратиться к таблицам tables_priv и columns_priv. Поля этих таблиц привилегий перечислены ниже:

Имя таблицы | tables_priv | columns_priv
Поля контекста | Host | Host
 | Db | Db
 | User | User
 | Table_name | Table_name
 |  | Column_name
Поля привилегий | Table_priv | Column_priv
 | Column_priv |
Иные поля | Timestamp | Timestamp
 | Grantor |

Каждая таблица привилегий включает в себя поля контекста и поля привилегий.

Поля контекста определяют область действия каждой из записей в таблицах, т.е. контекст, к которому имеет отношение та или иная запись. Например, запись в таблице user, в полях Host и User которой указаны значения 'thomas.loc.gov' 'bob', предназначена для аутентификации подсоединений к серверу с хоста thomas.loc.gov под именем пользователя bob. Аналогично запись в таблице db, в полях Host, User и Db которой указаны значения 'thomas.loc.gov', 'bob' и 'reports', будет использоваться при попытке пользователя по именем bob подсоединиться с хоста thomas.loc.gov и получить доступ к базе данных reports. В полях контекста в таблицах tables_priv и columns_priv указаны таблицы или комбинации таблиц/столбцов, к которым применяется каждая запись.

При контроле доступа сравнение значений в полях Host осуществляется без учета регистра. Значения в полях User, Password, Db и Table_name также являются независимыми от регистра символов. Значения в поле Column_name являются независимыми от регистра символов, начиная с MySQL 3.22.12.

В полях привилегий указываются привилегии, предоставляемые записью в таблице, т.е. то, какие операции разрешено выполнять. Сервер формирует полное описание привилегий пользователя, комбинируя информацию, хранящуюся в разных таблицах привилегий. Это осуществляется по правилам, которые описаны в разделе See section 4.2.10 Управление доступом, этап 2: верификация запросов.

Поля контекста - это строковые значения, объявленные, как показано ниже; устанавливаемым по умолчанию значением для каждого из них является пустая строка:

Имя поля | Тип | Примечания
Host | CHAR(60) |
User | CHAR(16) |
Password | CHAR(16) |
Db | CHAR(64) | (CHAR(60) для таблиц tables_priv и columns_priv tables)
Table_name | CHAR(60) |
Column_name | CHAR(60) |

В таблицах user, db и host все поля привилегий имеют объявленный тип ENUM('N','Y'), т.е. возможно одно из двух значений - 'N' и 'Y', а устанавливаемым по умолчанию является 'N'.

В таблицах tables_priv and columns_priv поля привилегий объявляются как SET:

Имя таблицы | Имя поля | Допустимые элементы набора
tables_priv | Table_priv | 'Select', 'Insert', 'Update', 'Delete', 'Create', 'Drop', 'Grant', 'References', 'Index', 'Alter'
tables_priv | Column_priv | 'Select', 'Insert', 'Update', 'References'
columns_priv | Column_priv | 'Select', 'Insert', 'Update', 'References'

Если кратко, то сервер использует таблицы привилегий следующим образом:

  • Поля контекста таблицы user определяют, разрешить входящее подсоединение или отказать в нем. Для разрешенных подсоединений любые привилегии, предоставленные в таблице user, означают глобальные привилегии пользователя (привилегии суперпользователя). Эти привилегии распространяются на все базы данных, размещенные на сервере.
  • Таблицы db и host используются совместно:
    • Поля контекста таблицы db определяют, каким пользователям, при подсоединении с каких хостов разрешен доступ к каким базам данных. Поля привилегий определяют разрешенные операции.
    • Таблица host используется в качестве расширения таблицы db в случае, если необходимо применить некоторую запись из таблицы db к разным хостам. Например, если вы хотите предоставить пользователю возможность обращаться к базе данных с различных хостов сети, оставьте пустым поле в записи этого пользователя в таблице db, а затем внесите в таблицу host запись для каждого из этих хостов. Более подробно данный механизм описан в разделе See section 4.2.10 Управление доступом, этап 2: верификация запросов.
  • Таблицы tables_priv и columns_priv подобны таблице db, но областью их действия является уже уровень таблиц и столбцов, а не баз данных.

Заметим, что привилегии администрирования (RELOAD, SHUTDOWN и т.д..) задаются только в таблице user. Это связано с тем, что операции администрирования являются операциями над самим сервером, а не над базами данных, поэтому не смысла перечислять такие привилегии в других таблицах привилегий. Фактически для того, чтобы выяснить, имеете ли вы привилегии выполнять операции администрирования, достаточно обратиться только к таблице user.

Привилегия FILE также задается только в таблице user. Она не является привилегией администрирования как таковой, но возможность производить чтение или запись файлов на серверном хосте не связана с базой данных, к которой вы получаете доступ.

Сервер mysqld считывает содержимое таблиц привилегий единожды, при его запуске. О том, каким образом изменения, вносимые в таблицы привилегий, вступают в силу, рассказывается в разделе See section 4.3.3 Когда изменения в привилегиях вступают в силу.

При внесении изменений в таблицы привилегий стоит убедиться в том, что ваши изменения задают привилегии именно так, как задумано вами. Помощь по диагностике проблем вы найдете в разделе See section 4.2.11 Причины появления ошибок Access denied ("в доступе отказано"). По вопросам, связанным с безопасностью, следует обращаться к разделу See section 4.2.2 Как обезопасить MySQL от хакеров.

Полезным диагностическим инструментом является скрипт mysqlaccess, которым Ив Карлье (Yves Carlier) укомплектовал дистрибутив MySQL. Запустите mysqlaccess с опцией --help чтобы посмотреть, как он работает. Заметим, что mysqlaccess контролирует доступ, используя только таблицы user, db и host. Он не проверяет привилегии на уровне таблиц или столбцов.

4.2.7 Привилегии, предоставляемые MySQL

Информация о привилегиях пользователя хранится в таблицах user, db, host, tables_priv и columns_priv базы данных mysql (т.е. в базе данных с именем mysql). Сервер MySQL считывает содержимое этих таблиц во время запуска, и в случаях, указанных в разделе See section 4.3.3 Когда изменения в привилегиях вступают в силу.

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

Привилегия | Столбец | Контекст
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 TEMPORARY TABLES | Create_tmp_table_priv | администрирование сервера
EXECUTE | Execute_priv | администрирование сервера
FILE | File_priv | доступ к файлам на сервере
LOCK TABLES | Lock_tables_priv | администрирование сервера
PROCESS | Process_priv | администрирование сервера
RELOAD | Reload_priv | администрирование сервера
REPLICATION CLIENT | Repl_client_priv | администрирование сервера
REPLICATION SLAVE | Repl_slave_priv | администрирование сервера
SHOW DATABASES | Show_db_priv | администрирование сервера
SHUTDOWN | Shutdown_priv | администрирование сервера
SUPER | Super_priv | администрирование сервера

Привилегии SELECT, INSERT, UPDATE и DELETE позволяют выполнять операции над строками таблиц баз данных.

Для операторов SELECT привилегия SELECT требуется только в том случае, если они действительно извлекают строки из таблицы.. В ряде случае можно выполнять операторы SELECT, даже не имея разрешения на доступ ни к одной базе данных на сервере. Например: клиент mysql вы можете использовать в качестве обычного калькулятора:

mysql> SELECT 1+1;
mysql> SELECT PI()*2;

Привилегия INDEX позволяет создавать или уничтожать (удалять) индексы.

Привилегия ALTER позволяет использовать команду ALTER TABLE.

Привилегии CREATE и DROP позволяют создавать новые базы данных и таблицы или уничтожать (удалять) существующие базы данных и таблицы.

Заметим, что в случае, если пользователю предоставляется привилегия DROP по отношению к базе данных mysql, он может уничтожить базу данных, в которой хранятся привилегии доступа в MySQL!

Привилегия GRANT позволяет вам предоставлять другим пользователям привилегии, которыми обладаете вы сами.

Привилегия FILE дает вам право читать и записывать файлы на сервере с помощью операторов LOAD DATA INFILE и SELECT ... INTO OUTFILE. Любой пользователь, которому предоставлена такая привилегия, имеет право прочитать или записать любой файл, который может прочитать или записать сервер MySQL. Пользователь также может прочитать любой файл в каталоге текущей базы данных. Однако существующие файлы перезаписывать нельзя.

Остальные привилегии используются для операций администрирования, выполняемых с помощью программы mysqladmin. В таблице, приведенной ниже, для каждой из привилегий администрирования показано, какие команды mysqladmin она позволяет выполнять.

Привилегия | Команды, разрешенные обладателю привилегии
RELOAD | reload, refresh, flush-privileges, flush-hosts, flush-logs, and flush-tables
SHUTDOWN | shutdown
PROCESS | processlist
SUPER | kill

Команда reload заставляет сервер перечитать таблицы привилегий. Команда refresh очищает все таблицы, а также открывает и закрывает файлы журналов. flush-privileges является синонимом reload. Остальные команды flush-* выполняют функции, аналогичные функциям команды refresh, но с более узкой областью действия. В некоторых случаях такие команды могут оказаться более предпочтительными. Например, если вы хотите очистить только системные журналы, команда flush-logs лучше, чем refresh.

Команда shutdown завершает работу сервера.

Команда processlist выводит информацию о задачах, выполняющихся на сервере. Команда kill уничтожает серверные потоки. Собственные потоки всегда можно просмотреть или уничтожить, но для отображения потоков, запущенных другими пользователями, нужна привилегия PROCESS,а для уничтожения потоков, запущенных другими пользователями, потребуется привилегия SUPER. Обратитесь к разделу See section 4.5.5 Синтаксис команды KILL.

В общем случае идея предоставлять привилегии только тем пользователям, которым они необходимы, хорошая, но к предоставлению некоторых из них следует относиться особенно внимательно:

  • Привилегия GRANT позволяет пользователям передавать свои привилегии другим пользователям. Два пользователя с неодинаковыми привилегиями, имея привилегию GRANT, способны объединить свои привилегии.
  • Привилегия ALTER может быть использована для переименования таблиц и разрушения таким образом всей системы привилегий.
  • Привилегия FILE может использоваться злонамеренно для считывания любого доступного файла, хранящегося на сервере, или любого файла в каталоге текущей базы данных в таблицу, к содержимому которой можно затем получить доступ с помощью команды SELECT.
  • Привилегия SHUTDOWN может использоваться злонамеренно для полного прекращения работы сервера и, таким образом, полного запрещения обслуживания других пользователей.
  • Привилегия PROCESS может быть использована для просмотра открытого текста запросов выполняющихся в данный момент, включая запросы на установку или изменение паролей.
  • Привилегии доступа к базе данных mysql могут быть использованы для изменения паролей и другой информации, относящейся к привилегиям доступа. (Пароли хранятся в зашифрованном виде, поэтому злоумышленник не сможет просто прочесть их, чтобы получить пароли в виде обычного текста). Получив доступ к столбцу паролей mysql.user, любой пользователь может войти на сервер MySQL под именем другого пользователя (имея достаточные привилегии, тот же самый пользователь может заменить пароль на другой).

Есть вещи, которые система привилегий MySQL делать не может:

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

4.2.8 Соединение с сервером MySQL

Обычно для получения доступа к серверу MySQL необходимо сообщить клиентской программе параметры подсоединения: указать хост, с которым вы хотите соединиться, ваши имя пользователя и пароль. Например, клиент mysql можно запустить следующим образом (необязательные аргументы заключены в квадратные скобки `[' и `]'):

shell> mysql [-h host_name] [-u user_name] [-pyour_pass]

Альтернативной формой опций -h, -u, и -p являются --host=host_name, --user=user_name и --password=your_pass. Заметим, что между -p или --password= и следующим за ними паролем пробела нет.

Внимание: Указывать пароль в командной строке небезопасно! Любой пользователь в вашей системе может впоследствии отыскать ваш пароль, введя команду типа ps auxww. Обратитесь к разделу See section 4.1.2 Файлы параметров `my.cnf'.

В mysql используются следующие значения по умолчанию для параметров подсоединения, пропущенных в командной строке:

  • Значением по умолчанию для имени хоста является localhost.
  • Значением по умолчанию для имени пользователя является ваш Unix-аккаунт.
  • При отсутствии префикса -p никакого пароля не указывается.

Таким образом, для Unix-пользователя joe следующие команды являются эквивалентными:

shell> mysql -h localhost -u joe
shell> mysql -h localhost
shell> mysql -u joe
shell> mysql

Другие клиенты MySQL ведут себя подобным же образом.

В Unix-системах можно задавать различные значения по умолчанию, которые будут использоваться при соединении с сервером, чтобы избавиться от необходимости каждый раз при вызове клиентской программы вводить их в командной строке. Это можно сделать двумя способами:

  • Параметры подсоединения можно задать в разделе [client] файла конфигурации `my.cnf', который находится в вашей домашней директории. Соответствующий раздел этого файла может иметь следующий вид:
    [client]
host=host_name
user=user_name
password=your_pass
    Обратитесь к разделу See section 4.1.2 Файлы параметров `my.cnf'.
  • Параметры соединения можно задавать через переменные окружения. Для mysql можно задать хост при помощи MYSQL_HOST. Для задания имени пользователя для MySQL можно использовать USER (это относится только к ОС Windows). Пароль может быть задан с помощью MYSQL_PWD (но это небезопасно, см. следующий раздел). Обратитесь к разделу See section E Переменные окружения.

4.2.9 Управление доступом, этап 1: верификация подсоединения

При попытке соединения с сервером MySQL он либо устанавливает соединение, либо отказывает в нем - на основе данных о вашей личности и того, можете ли вы подтвердить их соответствующим паролем. Если нет, сервер полностью отказывает вам в доступе. В противном случае сервер устанавливает соединение, затем переходит ко второму этапу и ожидает запросов.

Личность задается двумя порциями информации:

  • хостом, с которого вы подсоединяетесь
  • вашим именем пользователя MySQL

Проверка личности осуществляется с помощью трех полей контекста таблицы user (Host, User и Password). Сервер устанавливает соединение только в том случае, если находит в таблице user запись, в которой имя хоста и имя пользователя совпадают с введенными вами, и вы указываете правильный пароль.

Значения в полях контекста таблицы user могут задаваться следующим образом:

  • В поле Host может указываться имя хоста, либо его IP-адрес, либо 'localhost' для обозначения локального хоста.
  • В поле Host разрешается использовать шаблонные символы `%' и `_'.
  • Значение '%' в поле Host означает любое имя хоста.
  • Пустое значение в поле Host означает, что к этой привилегии должна быть добавлена запись в таблице host, совпадающая с заданным именем хоста. Дополнительную информацию по данной теме вы найдете в следующем разделе.
  • Начиная с версии MySQL 3.23 для значений в поле в поле Host, определенных в виде IP-адресов, можно задавать сетевую маску, указывающую, сколько разрядов адреса будет использоваться для указания номера сети. Например:
    mysql> GRANT ALL PRIVILEGES ON db.*
    -> TO david&1acute;92.58.197.0/255.255.255.0';
    В этом случае все IP-адреса, для которых выполняется следующее условие:
    user_ip & netmask = host_ip.
    являются разрешенными для подсоединения. В предыдущем примере все IP-адреса в диапазоне от 192.58.197.0 до 192.58.197.255 являются разрешенными для подсоединения к серверу MySQL.
  • В поле User запрещено использовать шаблонные символы, но пустое значение разрешено, и оно соответствует любому имени. Если запись в таблице user, соответствующая входящему подсоединению, содержит пустое имя пользователя, данный пользователь считается анонимным пользователем (пользователем без имени), а заданное клиентом имя пользователя игнорируется. Это означает, что при всех последующих проверках доступа, осуществляемых на протяжении данного соединения (т.е. на этапе 2), будет использоваться пустое имя пользователя.
  • Поле Password может быть пустым. Это не означает, что в данном случае подходит любой пароль. Если поле пароля пусто, пользователь должен быть подсоединен без указания какого либо пароля.

Непустые значения в поле Password представляют собой зашифрованные пароли. В MySQL пароли не хранятся в виде открытого текста, который может прочитать кто угодно. Напротив, пароль, который вводится пользователем при попытке подсоединения, шифруется (с помощью функции PASSWORD()). В дальнейшем зашифрованный пароль используется клиентом/сервером в процессе проверки его правильности (это делается вообще без пересылки пароля во время подсоединения). Заметим, что с MySQL считает зашифрованный пароль РЕАЛЬНЫМ паролем, поэтому не следует допускать к нему кого бы то ни было! В частности, не разрешайте обычным пользователям доступ для чтения к таблицам в базе mysql!

Примеры, приведенные ниже, показывают, каким входящим подсоединениям соответствуют различные комбинации значений, указанных в полях Host и User таблицы user:

Значение в поле Host | Значение в поле User | Подсоединения, которым соответствует запись
'thomas.loc.gov' | 'fred' | fred, подключающийся с thomas.loc.gov
'thomas.loc.gov' | '' | Любой пользователь, подключающийся с thomas.loc.gov
'%' | 'fred' | fred, подключающийся с любого хоста
'%' | '' | Любой пользователь, подключающийся с любого хоста
'%.loc.gov' | 'fred' | fred, подключающийся с любого хоста, принадлежащего домену loc.gov
'x.y.%' | 'fred' | fred, подключающийся с x.y.net, x.y.com,x.y.edu, и т.д. (это, по-видимому, бесполезный вариант)
'144.155.166.177' | 'fred' | fred, подключающийся с хоста, имеющего IP-адрес 144.155.166.177
'144.155.166.%' | 'fred' | fred, подключающийся с любого хоста в подсети 144.155.166 класса C
'144.155.166.0/255.255.255.0' | 'fred' | То же самое, что и в предыдущем примере

Поскольку в IP-адресе, указываемом в поле Host, могут использоваться шаблонные символы (например '144.155.166.%' - данное значение соответствует всем без исключения хостам указанной подсети), возникает опасность, что кто-нибудь может попытаться воспользоваться этой возможностью, указав имя хоста, например, как 144.155.166.somewhere.com. Чтобы ``поставить заслон'' таким попыткам, в MySQL не разрешены имена хостов, начинающиеся с цифр и точки. Другими словами, имени хоста типа 1.2.foo.com, никогда не найдется соответствия в столбцах Host таблиц привилегий. IP-адресу с шаблонными символами может соответствовать только IP-адрес.

Входящее подсоединение может совпадать с несколькими записями в таблице user. Например, как было показано выше, подсоединению с thomas.loc.gov by fred могут подходить разные записи. Каким образом сервер определяет, какую из записей использовать, при совпадении с более чем одной из них? Для этого после считывания таблицы user во время запуска сервер производит ее сортировку, а затем, когда пользователь пытается установить соединение, записи таблицы просматриваются в порядке их упорядочения,. Используется первая подошедшая запись.

Сортировка таблицы user осуществляется следующим образом. Предположим, таблица user имеет следующий вид:

+-----------+----------+-
| Host      | User     | ...
+-----------+----------+-
| %         | root     | ...
| %         | jeffrey  | ...
| localhost | root     | ...
| localhost |          | ...
+-----------+----------+-

При считывании этой таблицы сервер упорядочивает записи, начиная с наиболее конкретных значений в столбце Host ('%' в столбце Host означает ``любой хост'' и является наименее конкретным). Записи с одинаковым значением в столбце Host упорядочиваются между собой начиная с наиболее конкретных значений в столбце User (пустое значение в столбце User означает ``любой пользователь'' и является наименее конкретным). Окончательно отсортированная таблица user имеет следующий вид:

+-----------+----------+-
| Host      | User     | ...
+-----------+----------+-
| localhost | root     | ...
| localhost |          | ...
| %         | jeffrey  | ...
| %         | root     | ...
+-----------+----------+-

При попытке подсоединения сервер просматривает отсортированные записи и использует первую подходящую запись. Для подсоединения с localhost пользователя jeffrey первыми подходящими записями являются записи со значением 'localhost' в столбце Host. Из них запись с пустым значением имени пользователя соответствует и имени подсоединяющегося хоста и имени пользователя. (запись '%'/'jeffrey' тоже подошла бы, но она -- не первая подходящая в этой таблице).

Рассмотрим другой пример. Пусть таблица user имеет вид:

+----------------+----------+-
| Host           | User     | ...
+----------------+----------+-
| %              | jeffrey  | ...
| thomas.loc.gov |          | ...
+----------------+----------+-

Отсортированная таблица выглядит следующим образом:

+----------------+----------+-
| Host           | User     | ...
+----------------+----------+-
| thomas.loc.gov |          | ...
| %              | jeffrey  | ...
+----------------+----------+-

Для подсоединения пользователя jeffrey с thomas.loc.gov подходит первая запись, в то время как для подсоединения jeffrey с whitehouse.gov - вторая.

Существует распространенное заблуждение: иногда думают, что при поиске записей для данного имени пользователя, соответствующих определенному подсоединению, сервер первыми будет использовать записи, в которых этот пользователь указан явно. Это абсолютно неверно, как и продемонстрировано в предыдущем примере: для подсоединения пользователя jeffrey с thomas.loc.gov первой подходящей записью является не запись, содержащая значение 'jeffrey' в поле User, а запись, не содержащая имени пользователя вовсе!

Если у вас возникают проблемы с подсоединением к серверу, выведите таблицу user и отсортируйте ее вручную, чтобы увидеть, где происходит первое совпадение.

Если соединение было успешно, но ваши привилегии - не те, что вы ожидали увижеть, вы можете использовать функцию CURRENT_USER() (новшество с MySQL 4.0.6) чтобы узнать, какой комбинации пользователь/компьютер ваше соединение соответствует. See section 6.3.6.2 Разные функции.

4.2.10 Управление доступом, этап 2: верификация запросов

После установления соединения сервер приступает к выполнению второго этапа. Для каждого поступающего запроса сервер проверяет, имеется ли у вас достаточно привилегий для его выполнения, основываясь при этом на типе операции, которую вы хотите выполнить. Теперь в действие вступают поля привилегий в таблицах привилегий. Информация о привилегиях может находиться в любой из таблиц привилегий - user, db, host, tables_priv или columns_priv. Обработка таблиц привилегий осуществляется с помощью команд GRANT и REVOKE. Обратитесь к разделу See section 4.3.1 Синтаксис команд GRANT и REVOKE. Интерес может представлять раздел See section 4.2.6 Как работает система привилегий, в котором перечислены поля, имеющиеся в каждой из таблиц привилегий.

Таблица user предоставляет привилегии глобального характера, и их применение не зависит от того, в какой базе вы работаете в данный момент. Например, если таблица user предоставляет пользователю привилегию DELETE, он может удалять строки из любой базы данных на серверном хосте! Иными словами, привилегии в таблице user - это привилегии суперпользователя. Поэтому целесообразно предоставлять привилегии в таблице user только суперпользователям, таким как администраторы сервера или администраторы баз данных. Что касается других пользователей, для их привилегий в таблице user следует установить значение 'N' и предоставлять им привилегии только на уровне баз данных, используя для этого таблицы db и host.

Таблицы db и host предоставляют привилегии на уровне базы данных. Значения в полях контекста могут задаваться следующим образом:

  • Шаблонные символы `%' и `_' могут использоваться в полях Host и Db любой таблицы. Если вы хотите использовать символ `_' как часть имени базы данных, укажите его как `\_' в операторе GRANT.
  • Значение '%' в колонке Host таблицы db означает ``любой хост''. Пустое значение в поле Host таблицы db означает ``за дополнительной информацией следует обратиться к таблице host''.
  • Значение '%' или пустое значение в поле Host таблицы host означает ``любой хост''.
  • Значение '%' или пустое значение в поле Db любой из таблиц означает ``любая база данных''.
  • Пустое значение в поле User любой из таблиц соответствует анонимному пользователю.

Таблицы db и host считываются и сортируются при запуске сервера (тогда же, когда он считывает таблицу user). Таблица db сортируется по полям контекста Host, Db и User, а таблица host - по полям контекста Host и Db. Как и в случае таблицы user, при сортировке первыми отбираются наиболее конкретные значения, а последними - наименее конкретные, а когда сервер производит поиск совпадающих записей, используется первая совпадающая запись, которую он находит.

Таблицы tables_priv и columns_priv предоставляют привилегии соответственно на уровне таблиц и столбцов. Значения в полях контекста задаются следующим образом:

  • В обеих таблицах в поле Host можно использовать шаблонные символы `%' и `_'.
  • В обеих таблицах '%' или пустое значение в поле Host означает ``любой хост''. В обеих таблицах в полях Db, Table_name и Column_name запрещено использовать шаблонные символы или пустое значение.

Таблицы_priv и columns_priv сортируются по полям Host, Db и User. Эта сортировка проводится так же, как и в таблице db, хотя в данном случае задача несколько упрощается, т.к. шаблонные символы могут встретиться только в поле Host.

Ниже описывается процесс верификации запроса. (Если вы хорошо знакомы с исходным кодом проверки доступа, то заметите некоторые отличия: приведенное здесь описание несколько упрощено, чтобы сделать его более понятным, однако оно соответствует тому, что в действительности делает код).

Для запросов на администрирование (SHUTDOWN, RELOAD, etc.) сервер проверяет запись только в таблице user, т.к. это единственная таблица, которая определяет привилегии администрирования. Доступ предоставляется при условии, что выбранная запись разрешает затребованные операции, и запрещается в противном случае. Например, вы хотите завершить работу mysql с помощью mysqladmin shutdown, но ваша запись в таблице user не предоставляет вам привилегию SHUTDOWN. В этом случае в доступе будет отказано без дальнейшей проверки таблицы db и host (поскольку в них отсутствует столбец Shutdown_priv, в такой проверке нет необходимости).

В случае запросов, относящихся к базам данных (INSERT, UPDATE и т.д.), сервер сначала проверяет глобальные привилегии пользователя (привилегии суперпользователя), просматривая запись в таблице user. Если эта запись разрешает затребованную операцию, доступ предоставляется. Если глобальные привилегии, указанные в таблице user, недостаточны, сервер проверяет таблицы db и host и определяет привилегии пользователя на уровне баз данных:

  1. Сервер просматривает таблицу db в поисках записи с подходящими значениями в полях Host, Db и User. Поля Host и User сравниваются с именем подключающегося хоста и именем пользователя MySQL. Поле Db сравнивается с именем базы данных, к которой пользователь хочет получить доступ. Если запись с подходящими значениями в полях Host и User отсутствует, в доступе будет отказано.
  2. Если же в таблице db имеется подходящая запись и значение в поле Host - не пустое, эта запись определяет привилегии пользователя, касающиеся базы данных.
  3. Если же в подходящей записи, выбранной в таблице db, значение в поле Host пустое, это означает, что перечень хостов, которым разрешен доступ к требуемой базе данных, приведен в таблице host. В этом случае дальнейший поиск производится в таблице host, где ищется запись с подходящими значениями в полях Host и Db. Если ни одной подходящей записи в таблице host нет, в доступе будет отказано. Если такая запись имеется, привилегии пользователя на уровне базы данных вычисляются путем логического умножения (не логического сложения!) привилегий, найденных в записях, которые выбраны в таблицах db и host. Другими словами, пользователю назначаются те привилегии, для которых в обеих записях установлено значение 'Y'. (Этот способ можно использовать следующим образом: предоставить всеобщие привилегии в записи, хранящейся в таблице db, а затем выборочно ограничить их отдельно по каждому хосту, используя для этого записи в таблице host.)

Определив привилегии на уровне базы данных, предоставляемые записями в таблицах db и host, сервер добавляет их к глобальным привилегиям, заданным в таблице user. Если в результате привилегий оказывается достаточно для выполнения затребованной операции, доступ предоставляется. В противном случае сервер проверяет по таблицам tables_priv и columns_priv привилегии пользователя на уровне таблиц и столбцов и добавляет их к уже имеющимся привилегиям. В зависимости от полученного результата доступ либо предоставляется, либо нет.

Если приведенное выше описание вычислений привилегий пользователя перевести на язык алгебры логики, используя логические операторы, то в результате получится примерно следующее:

global privileges
OR (database privileges AND host privileges)
OR table privileges
OR column privileges

Сам по себе алгоритм определения привилегий на первый взгляд может показаться неочевидным. И в самом деле, если первоначально глобальных привилегий, определяемых таблицей user, оказывается недостаточно для выполнения затребованной операции, то зачем впоследствии эти вроде бы бесполезные привилегии добавляются к привилегиям на уровне баз данных, таблиц и столбцов? Смысл такого добавления заключается в том, что для выполнения запроса может потребоваться не один, а несколько типов привилегий. Например, для выполнения оператора INSERT ... SELECT вам потребуется как привилегия INSERT, так и привилегия SELECT. Ваши привилегии могут быть таковы, что запись в таблице user предоставляет вам одну привилегию, а запись в таблице db - другую. Другими словами, привилегии, необходимые для выполнения запроса, у вас есть, но сервер не может выяснить при просмотре каждой таблицы в отдельности, и поэтому привилегии, предоставляемые записями из обеих таблиц, должны быть объединены.

Таблицу host можно использовать еще для одной цели - для поддержки списка надежных серверов.

В таблицах на TcX host содержит список всех машин локальной сети. Им предоставляются все привилегии.

Таблицу host можно также использовать для регистрации хостов, которые являются ненадежными. Предположим, одна из ваших машин - public.your.domain находится в общедоступной области, которую вы считаете незащищенной. В таком случае можно разрешить доступ всем хостам вашей сети, за исключением одной ``неблагонадежной'' машины, используя записи в таблице host, подобные приведенным ниже:

+--------------------+----+-
| Host               | Db | ...
+--------------------+----+-
| public.your.domain | %  | ... (для всех привилегий установлено значение 'N')
| %.your.domain      | %  | ... (для всех привилегий установлено значение 'Y')
+--------------------+----+-

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

4.2.11 Причины появления ошибок Access denied ("в доступе отказано")

Если при попытке подсоединения к серверу MySQL вы сталкиваетесь с ошибкой Access denied, то воспользуйтесь приведенным ниже списком. В нем перечислены меры, которые можно принять для решения этой проблемы:

  • Запускали ли вы после инсталляции MySQL скрипт mysql_install_db для установки начального содержимого таблиц привилегий? Если нет, сделайте это. Обратитесь к разделу See section 4.3.4 Задание изначальных привилегий MySQL. Проверьте первоначальные привилегии с помощью следующей команды:
    shell> mysql -u root test
    Подсоединение должно произойти без сбоя. Следует также убедиться, что в каталоге базы данных MySQL имеется файл `user.MYD'. Обычно он находится в директории `PATH/var/mysql/user.MYD', где PATH - путь к корневому каталогу инсталляции MySQL.
  • После новой инсталляции следует подсоединиться к серверу и создать пользователей, а также установить для них права доступа:
    shell> mysql -u root mysql
    Сервер разрешит подсоединение, т.к. пользователь MySQL с именем пользователя root исходно не имеет пароля. Но в этом заключается также и риск нарушения безопасности системы, поэтому при создании остальных пользователей MySQL, вам, помимо прочего, следует задать пароль для пользователя root. Если при попытке подсоединения от имени пользователя root вы получите следующую ошибку:
    Access denied for user: '@unknown' to database mysql
    это означает, что в таблице user отсутствует запись со значением 'root' в столбце User и mysqld не может определить имя хоста для вашего клиента. В этом случае необходимо перезапустить сервер с опцией --skip-grant-tables и отредактировать файл `/etc/hosts' или `\windows\hosts', добавив в него запись для вашего хоста.
  • Если вы столкнетесь с такой ошибкой, как:
    shell> mysqladmin -u root -pxxxx ver
Access denied for user: 'root@localhost' (Using password: YES)
    это означает, что используется неверный пароль. Обратитесь к разделу See section 4.3.7 Задание паролей. Если вы забыли пароль для пользователя root, то перезапустите mysqld с опцией --skip-grant-tables и измените пароль. Обратитесь к разделу See section A.4.2 Как переустановить забытый пароль пользователя root. Такая ошибка может появляться даже в том случае, если вы не задавали пароля вообще - это значит, что в каком-то файле `my.ini' имеется неверный пароль. Обратитесь к разделу See section 4.1.2 Файлы параметров `my.cnf'. Отменить использование файлов опций можно с помощью опции the --no-defaults, как показано ниже:
    shell> mysqladmin --no-defaults -u root ver
  • Запускали ли вы скрипт mysql_fix_privilege_tables при обновлении имеющейся инсталляции MySQL, если установленная версия - более ранняя, чем 3.22.11, а обновляется она до 3.22.11 или более поздней? Если нет, сделайте это. Начиная с MySQL 3.22.11, когда оператор GRANT стал функциональным, структура таблиц привилегий изменилась.
  • Если во время сеанса ваши привилегии изменились, то, возможно, их изменил суперпользователь. Перезагрузка таблиц привилегий отражается не только на новых подсоединениях клиентов, но также на уже имеющихся, как это показано в разделе See section 4.3.3 Когда изменения в привилегиях вступают в силу.
  • Если не удается добиться, чтобы пароль работал, помните, что функция PASSWORD() должна использоваться, если вы задаете пароль с помощью операторов INSERT, UPDATE или SET PASSWORD. Если же вы задаете пароль с помощью оператора GRANT ... INDENTIFIED BY или команды mysqladmin password, функция PASSWORD() не нужна. Обратитесь к разделу See section 4.3.7 Задание паролей.
  • localhost - это синоним имени вашего локального хоста, и, если хост явно не задан, также устанавливаемое по умолчанию имя хоста, к которому клиенты пытаются подключиться. Однако подсоединения к localhost не действуют, если в вашей рабочей системе используются MIT-потоки и MySQL старше версии 3.23.27 (подсоединения к localhost осуществляются с использованием сокетов Unix, а они не поддерживались тогда технологией MIT-потоков). Чтобы в таких системах эта проблема не возникала, следует явным образом задать имя серверного хоста с помощью опции --host. Таким образом будет установлено подсоединение к серверу mysqld по протоколу TCP/IP. В этом случае в записях таблицы user, хранящейся на серверном хосте, должно быть указано реальное имя хоста. (Это справедливо даже для тех случаев, когда клиентская программа и сервер запускаются на одном хосте).
  • Если при попытке подсоединения к базе данных с помощью команды mysql -u user_name db_name возникает ошибка Access denied, причина этого, возможно, кроется в таблице user. Чтобы проверить это, выполните команду mysql -u root mysql и введите следующий SQL-оператор:
    mysql> SELECT * FROM user;
    В результате будет выведена запись со столбцами Host и User, соответствующими имени вашего компьютера и вашему имени пользователя MySQL.
  • Сообщение об ошибке Access denied информирует вас о том, под каким именем вы пытаетесь войти в систему, об имени хоста, с которого вы пытаетесь установить соединение, и о том, использовали ли вы при этом пароль или нет. Как правило, в таблице user будет одна запись, точно соответствующая имени хоста и имени пользователя, указанным в сообщении об ошибке. Например, если вы получите сообщение об ошибке, в котором сказано Using password: NO, это означает, что вы пытались войти в систему, не указав пароль.
  • Если при попытке подсоединения не с того компьютера, на котором работает сервер MySQL, а с другого, вы получите сообщение об ошибке, приведенное ниже, то в таблице user отсутствует строка с таким именем хоста:
    Host ... is not allowed to connect to this MySQL server
    Чтобы исправить эту ошибку, с помощью утилиты командной строки mysql (на серверном хосте!) добавьте строку в таблицу user, db или host с комбинацией имени пользователя/хоста, соответствующей той, которую вы используете при попытке подсоединения. Затем выполните команду mysqladmin flush-privileges. Если вы используете MySQL версии, отличной от Version 3.22, и вам неизвестно имя хоста или IP-адрес компьютера, с которого вы подсоединяетесь, введите в таблицу user запись со значением '%' в поле Host и перезапустите mysqld на серверной машине с опцией --log. Когда соединение с клиентской машины будет установлено, вы найдете в журнале регистрации MySQL информацию об имени хоста, с которого вы подсоединились. (После этого следует заменить в записи таблицы user значение '%' настоящим именем хоста, из журнала регистрации. Иначе ваша система останется незащищенной.) В Linux причиной такой ошибки может быть то, что бинарная версия MySQL скомпилирована с версией glibc, отличной от используемой вами. В этом случае нужно будет либо обновить ОС/glibc, используемые вами, либо загрузить исходный код MySQL и скомпилировать сервер самостоятельно. Как правило, исходный RPM компилируется и инсталлируется элементарно, так что это не составит серьезной проблемы.
  • Если будет выдано сообщение об ошибке, в котором имя хоста не указано вообще или указан IP-адрес, хотя вы при попытке подсоединения указывали имя хоста:
    shell> mysqladmin -u root -pxxxx -h some-hostname ver
Access denied for user: 'root' (Using password: YES)
    то это означает, что ошибка возникает при попытке MySQL сопоставить IP-адрес с именем хоста. В этом случае вы можете выполнить команду mysqladmin flush-hosts, чтобы сбросить внутреннюю кэш-память DNS. Обратитесь к разделу See section 5.5.5 Как MySQL использует DNS. Вот некоторые способы решения этой проблемы:
    • Попробуйте выяснить, что не так с вашим сервером DNS, и устраните неисправность.
    • Задайте IP-адреса вместо имен хостов таблицах привилегий MySQL.
    • Запустите mysqld с опцией --skip-name-resolve.
    • Запустите mysqld с опцией --skip-host-cache.
    • Подключитесь к localhost если ваш сервер и клиент работают на одном и том же компьютере.
    • Поместите имена клиентских машин в каталог `/etc/hosts'.
  • Если команда mysql -u root test работает успешно, а команда mysql -h your_hostname -u root test приводит к ошибке Access denied, то, возможно, в таблице user имя вашего хоста указано неверно. Одна из распространенных проблем здесь заключается в том, что в поле Host записи, хранящейся в таблице user, задается только имя хоста, в то время как процедуры разрешения имен, используемые вашей системой, возвращают полностью определенное доменное имя (или наоборот). Например, если в таблице user имеется запись со значением 'tcx' в поле host, а DNS при этом сообщает MySQL, что имя хоста - 'tcx.subnet.se', эта запись действовать не будет. Попробуйте добавить в таблицу user запись, указав в колонке Host IP-адрес хоста. (В качестве альтернативы можно добавить в таблицу user запись со значением в поле Host, содержащим шаблонный символ, например 'tcx.%'. Но использовать имена хостов, оканчивающиеся на '%' - небезопасно и делать это не рекомендуется!)
  • Если команда mysql -u user_name test работает успешно, а команда mysql -u user_name other_db_name - нет, то в таблице db нет записи, соответствующей other_db_name.
  • Если команда mysql -u user_name db_name выполняется успешно на том компьютере, где установлен сервер, а mysql -u host_name -u user_name db_name не работает при выполнении ее на другой клиентской машине, то в таблицах user или db эта клиентская машина не зарегистрирована.
  • Если не удается выяснить причину ошибки Access denied, удалите из таблицы user все записи, в которых значение в поле Host включает шаблонные символы (записи, содержащие символы `'%'' или `'_''). Очень распространенной ошибкой является следующая: пользователь вставляет новую запись со значением '%' в поле Host и со значением 'some user' - в поле User, полагая, что после этого для подсоединения с той же самой машины он сможет использовать localhost. Такой расчет неверен, и причина здесь в том, что устанавливаемые по умолчанию привилегии включают запись со значением 'localhost' в поле Host и пустым полем User. И поскольку в этой записи значение 'localhost' более конкретно, чем '%', то именно она при подсоединении с localhost предшествует новой записи и, соответственно, будет выбрана и сработает! Правильным в этом случае будет вставить вторую запись со значением 'localhost' в поле Host и значением 'some_user' - в поле User или удалить запись со значением 'localhost' в поле Host и пустым полем User.
  • Если вы получите следующую ошибку, то эта проблема, возможно, связана с таблицей db или таблицей host:
    Access to database denied
    Если в записи, выбранной из таблицы db, столбец Host - пустой, удостоверьтесь, что в таблице host имеется по крайней мере одна соответствующая запись, указывающая, к каким хостам относится запись из таблицы db. Если ошибка возникает при выполнении SQL-команды SELECT ... INTO OUTFILE или LOAD DATA INFILE, то в вашей записи из таблицы user, вероятно, отсутствует разрешение на предоставление привилегии FILE.
  • Помните, что клиентские программы будут использовать параметры подсоединения, указанные файлах конфигурации или переменных окружения. Обратитесь к разделу See section E Переменные окружения. Если есть подозрение, что клиент отсылает неверные устанавливаемые по умолчанию параметры подсоединения, в случае, когда вы не задаете их в командной строке, проверьте ваше окружение и файл `my.cnf' в своей домашней директории. Можете также проверить конфигурационные файлы MySQL относящиеся ко все системе, хотя параметры клиентского подсоединения вряд ли указаны именно здесь. Обратитесь к разделу See section 4.1.2 Файлы параметров `my.cnf'. Если ошибка Access denied возникает при выполнении вашей клиентской программы без каких-либо опций, убедитесь, что ни в одном из ваших файлов опций не указан старый пароль! Обратитесь к разделу See section 4.1.2 Файлы параметров `my.cnf'.
  • Если вы вносите изменения в таблицы привилегий непосредственно (с помощью операторов INSERT или UPDATE), а ваши изменения, похоже, игнорируются, то следует выдать оператор FLUSH PRIVILEGES или выполнить команду mysqladmin flush-privileges - для того, чтобы заставить сервер перечитать таблицы привилегий. В противном случае ваши изменения вступят в силу лишь при последующем перезапуске сервера. Помните, что после того, как вы зададите пароль от имени пользователя, вам нужно будет указывать его только после сброса привилегий, т.к. серверу еще не будет известно о том, что вы изменили пароль!
  • При возникновении проблемы с доступом при использовании Perl-, PHP-, Python- или ODBC-программ, попробуйте установить соединение с сервером при помощи команды mysql -u user_name db_name или команды mysql -u user_name -pyour_pass db_name. Если ваш клиент mysql обеспечивает подсоединение, то проблема связана не с привилегиями доступа, а с вашей программой. (Заметим, что между -p и паролем пробела нет; для задания пароля можно также использовать синтаксическую структуру --password=your_pass. Если вы используете только саму опцию -p, MySQL запросит у вас пароль)
  • При тестировании запускайте демон mysqld с опцией --skip-grant-tables. Тогда вы сможете изменять таблицы привилегий MySQL и с помощью скрипта mysqlaccess проверять, произвели ли сделанные вами изменения желаемый эффект. Если результаты вас устраивают, выполните команду mysqladmin flush-privileges, чтобы приказать серверу mysqld приступить к использованию новых таблиц привилегий. Внимание: перезагрузка таблиц привилегий отменяет опцию --skip-grant-tables. Это позволяет заставить сервер приступить к использованию новых таблиц привилегий без завершения его работы и перезагрузки.
  • Если ничего не помогает, запустите демон mysqld daemon с опцией отладки (например --debug=d,general,query). В результате будет выведена информация о неудачных подсоединениях, с указанием хоста и пользователя, а также обо всех обработанных командах. Обратитесь к разделу See section D.1.2 Создание трассировочных файлов.
  • Если у вас имеется какая-либо проблема с таблицами привилегий MySQL и вы полагаете, что необходимо сообщить о ней в список рассылки, нужно обязательно приложить к своему отчету распечатку таблиц привилегий MySQL. Это можно сделать с помощью команды mysqldump mysql. Отчет о проблеме, как и в других случаях, отправляется с помощью скрипта mysqlbug. Обратитесь к разделу See section 1.8.1.3 Как отправлять отчеты об ошибках или проблемах. В некоторых случаях для выполнения скрипта mysqldump возможно, потребуется перезапустить mysqld с опцией --skip-grant-tables.

4.3 Управление учетными записями пользователей MySQL

4.3.1 Синтаксис команд GRANT и REVOKE

GRANT priv_type [(column_list)] [, priv_type [(column_list)] ...]
    ON {tbl_name | * | *.* | db_name.*}
    TO user_name [IDENTIFIED BY [PASSWORD] 'password']
        [, user_name [IDENTIFIED BY 'password'] ...]
    [REQUIRE
    NONE |
        [{SSL| X509}]
        [CIPHER cipher [AND]]
        [ISSUER issuer [AND]]
        [SUBJECT subject]]
    [WITH [GRANT OPTION | MAX_QUERIES_PER_HOUR # |
                          MAX_UPDATES_PER_HOUR # |
                          MAX_CONNECTIONS_PER_HOUR #]]

REVOKE priv_type [(column_list)] [, priv_type [(column_list)] ...]
    ON {tbl_name | * | *.* | db_name.*}
    FROM user_name [, user_name ...]

GRANT включен в MySQL начиная с версии 3.22.11 и выше. В более ранних версиях MySQL оператор GRANT ничего не выполняет.

Команды GRANT и REVOKE позволяют системным администраторам создавать пользователей MySQL, а также предоставлять права пользователям или лишать их прав на четырех уровнях привилегий:

Глобальный уровень
Глобальные привилегии применяются ко всем базам данных на указанном сервере. Эти привилегии хранятся в таблице mysql.user.
Уровень базы данных
Привилегии базы данных применяются ко всем таблицам указанной базы данных. Эти привилегии хранятся в таблицах mysql.db и mysql.host.
Уровень таблицы
Привилегии таблицы применяются ко всем столбцам указанной таблицы. Эти привилегии хранятся в таблице mysql.tables_priv.
Уровень столбца
Привилегии столбца применяются к отдельным столбцам указанной таблицы. Эти привилегии хранятся в таблице mysql.columns_priv.

Если привилегии предоставляются пользователю, которого не существует, то этот пользователь создается. Чтобы просмотреть примеры работы команды GRANT, см. раздел section 4.3.5 Добавление новых пользователей в MySQL.

В таблице приведен список возможных значений параметра priv_type для операторов GRANT и REVOKE:

ALL [PRIVILEGES] | Задает все простые привилегии, кроме WITH GRANT OPTION
ALTER | Разрешает использование ALTER TABLE
CREATE | Разрешает использование CREATE TABLE
CREATE TEMPORARY TABLES | Разрешает использование CREATE TEMPORARY TABLE
DELETE | Разрешает использование DELETE
DROP | Разрешает использование DROP TABLE
EXECUTE | Разрешает пользователю запускать хранимые процедуры (для MySQL 5.0)
FILE | Разрешает использование SELECT ... INTO OUTFILE и LOAD DATA INFILE
INDEX | Разрешает использование CREATE INDEX and DROP INDEX
INSERT | Разрешает использование INSERT
LOCK TABLES | Разрешает использование LOCK TABLES на таблицах, для которых есть привилегия SELECT
PROCESS | Разрешает использование SHOW FULL PROCESSLIST
REFERENCES | Зарезервировано для использования в будущем
RELOAD | Разрешает использование FLUSH
REPLICATION CLIENT | Предоставляет пользователю право запрашивать местонахождение головного и подчиненных серверов
REPLICATION SLAVE | Необходимо для подчиненных серверов при репликации (для чтения информации из бинарных журналов головного сервера)
SELECT | Разрешает использование SELECT
SHOW DATABASES | SHOW DATABASES выводит все базы данных
SHUTDOWN | Разрешает использование mysqladmin shutdown
SUPER | Позволяет установить одно соединение (один раз), даже если достигнуто значение max_connections, и запускать команды CHANGE MASTER, KILL thread, mysqladmin debug, PURGE MASTER LOGS и SET GLOBAL
UPDATE | Разрешает использование UPDATE
USAGE | Синоним для ``без привилегий''
GRANT OPTION | Синоним для WITH GRANT OPTION

Значение USAGE можно задавать, если необходимо создать пользователя без привилегий.

Привилегии CREATE TEMPORARY TABLES, EXECUTE, LOCK TABLES, REPLICATION ..., SHOW DATABASES и SUPER являются новыми для версии 4.0.2. Чтобы воспользоваться этими новыми привилегиями после обновления до версии 4.0.2, необходимо запустить скрипт mysql_fix_privilege_tables.

В боле старых версиях MySQL привилегия PROCESS предоставляет такие же права, как и новая привилегия SUPER.

Чтобы лишить пользователя привилегий, предоставленных командой GRANT, воспользуйтесь значением priv_type в GRANT OPTION:

mysql> REVOKE GRANT OPTION ON ... FROM ...;

Для таблицы можно указать только следующие значения priv_type: SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, GRANT OPTION, INDEX и ALTER.

Для столбца можно указать только следующие значения priv_type (при использовании оператора column_list): SELECT, INSERT и UPDATE.

Глобальные привилегии можно задать, воспользовавшись синтаксисом ON *.*, а привилегии базы данных - при помощи синтаксиса ON db_name.*. Если указать ON * при открытой текущей базе данных, то привилегии будут заданы для этой базы данных. (Предупреждение: если указать ON * при отсутствии открытой текущей базы данных, это повлияет на глобальные привилегии!)

Заметьте: шаблонные символы `_' и `%' не допускаются в определении имени баз данных в операторе GRANT. Это означает, что если вы хотите использовать, скажем, символ `_' в имени базы данных, то вы должны указать его как `\_' в GRANT, чтобы пользователь не имел возможности получить доступ к другим базам данных, соответствующих шаблону: GRANT ... ON `foo\_bar`.* TO ....

С тем, чтобы можно было определять права пользователям с конкретных компьютеров, в MySQL обеспечивается возможность указывать имя пользователя (user_name) в форме user@host. Если необходимо указать строку user, в которой содержатся специальные символы (такие как `-') или строку host, в которой содержатся специальные или групповые символы (такие как `%'), можно заключить имя удаленного компьютера или пользователя в кавычки (например, 'test-user'@'test-hostname').

В имени удаленного компьютера также можно указывать групповые символы. Например, user@'%.loc.gov' относится к user всех удаленных компьютеров домена loc.gov, а user@'144.155.166.%' относится к user всех удаленных компьютеров подсети 144.155.166 класс C.

Простая форма user является синонимом для user@"%".

В MySQL не поддерживаются групповые символы в именах пользователей. Анонимные пользователи определяются вставкой записей User='' в таблицу mysql.user или созданием пользователя с пустым именем при помощи команды GRANT.

Примечание: если анонимным пользователям разрешается подсоединяться к серверу MySQL, необходимо также предоставить привилегии всем локальным пользователям как user@localhost, поскольку в противном случае при попытке пользователя зайти в MySQL с локального компьютера в таблице mysql.user будет использоваться вход для анонимного пользователя!

Чтобы проверить, происходит ли подобное на вашем компьютере, выполните следующий запрос:

mysql> SELECT Host,User FROM mysql.user WHERE User='';

На данный момент команда GRANT поддерживает имена удаленных компьютеров, таблиц, баз данных и столбцов длиной не более 60 символов. Имя пользователя должно содержать не более 16 символов.

Привилегии для таблицы или столбца формируются при помощи логического оператора OR из привилегий каждого из четырех уровней. Например, если в таблице mysql.user указано, что у пользователя есть глобальная привилегия SELECT, эта привилегия не отменяется на уровне базы данных, таблицы или столбца.

Привилегии для столбца могут быть вычислены следующим образом:

глобальные привилегии
OR (привилегии базы данных AND привилегии удаленного компьютера)
OR привилегии таблицы
OR привилегии столбца

В большинстве случаев права пользователя определяются только на одном уровне привилегий, поэтому обычно эта процедура не настолько сложна, как описано выше. Подробная информация о последовательности действий проверки привилегий представлена в разделе section 4.2 Общие проблемы безопасности и система привилегий доступа MySQL.

Если привилегии предоставляются сочетанию пользователь/удаленный компьютер, которое отсутствует в таблице mysql.user, то в последнюю добавляется запись, которая остается в таблице до тех пор, пока не будет удалена при помощи команды DELETE. Иначе говоря, команда GRANT может создавать записи user в таблице, но команда REVOKE не может их удалить. Это необходимо делать при помощи команды DELETE.

Если в MySQL версий 3.22.12 и выше создан новый пользователь или предоставлены глобальные привилегии, пароль пользователя будет назначаться оператором IDENTIFIED BY, если он указан. Если у пользователя уже есть пароль, то этот пароль будет заменен новым.

Если вы не хотите отправлять пароль открытым текстом, можно воспользоваться параметром PASSWORD с зашифрованным паролем, полученным при помощи функции SQL PASSWORD() или функции C API make_scrambled_password(char *to, const char *password).

Предупреждение: если при создании нового пользователя не указать оператор IDENTIFIED BY, будет создан пользователь без пароля. Это ненадежно с точки зрения безопасности.

Пароли также можно задавать при помощи команды SET PASSWORD. See section 6.2.3.4 Тип множества SET.

Если у вас привилегии для базы данных, то при необходимости в таблице mysql.db создается запись. Данная запись удаляется после удаления всех привилегий для этой базы данных командой REVOKE.

Если у пользователя нет никаких привилегий для таблицы, то таблица не отображается, когда пользователь запрашивает список таблиц (например, при помощи оператора SHOW TABLES).

Оператор WITH GRANT OPTION предоставляет пользователю возможность наделять других пользователей любыми привилегиями, которые он сам имеет на указанном уровне привилегий. При предоставлении привилегии GRANT необходимо проявлять осмотрительность, так как два пользователя с разными привилегиями могут объединить свои привилегии!

Параметры MAX_QUERIES_PER_HOUR #, MAX_UPDATES_PER_HOUR # и MAX_CONNECTIONS_PER_HOUR # являются новыми в MySQL версии 4.0.2. Эти параметры ограничивают количество запросов, обновлений и входов, которые пользователь может осуществить в течение одного часа. Если установлено значение 0 (принято по умолчанию), то это означает, что для данного пользователя нет ограничений. See section 4.3.6 Ограничение ресурсов пользователя.

Внимание: чтобы указать любую из этих опция для существующего пользователя, но не давать никаких дополнительных привилегий, используйте GRANT USAGE ... WITH MAX_....

Нельзя предоставить другому пользователю привилегию, которой нет у вас самого. Привилегия GRANT позволяет предоставлять только те привилегии, которыми вы обладаете.

Учтите, что если пользователю назначена привилегия GRANT на определенном уровне привилегий, то все привилегии, которыми этот пользователь уже обладает (или которые будут ему назначены в будущем!) на этом уровне, также могут назначаться этим пользователем. Предположим, пользователю назначена привилегия INSERT в базе данных. Если потом в базе данных назначить привилегию SELECT и указать WITH GRANT OPTION, пользователь сможет назначать не только привилегию SELECT, но также и INSERT. Если затем в базе данных предоставить пользователю привилегию UPDATE, пользователь сможет после этого назначать INSERT, SELECT и UPDATE.

Не следует назначать привилегии ALTER обычным пользователям. Это дает пользователю возможность разрушить систему привилегий путем переименования таблиц!

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

При запуске mysqld все привилегии считываются в память. Привилегии базы данных, таблицы и столбца вступают в силу немедленно, а привилегии уровня пользователя - при следующем подсоединении пользователя. Изменения в таблицах назначения привилегий, которые осуществляются при помощи команд GRANT и REVOKE, обрабатываются сервером немедленно. Если изменять таблицы назначения привилегий вручную (используя команды INSERT, UPDATE и т.д.), необходимо запустить оператор FLUSH PRIVILEGES или mysqladmin flush-privileges, чтобы указать серверу на необходимость перезагрузки таблиц назначения привилегий. See section 4.3.3 Когда изменения в привилегиях вступают в силу.

Наиболее значительные отличия команды GRANT версий ANSI SQL и MySQL следующие:

  • В MySQL привилегии назначаются для сочетания имя пользователя + удаленный компьютер, а не только для имени пользователя.
  • В ANSI SQL отсутствуют глобальные привилегии и привилегии уровня базы данных, и ANSI SQL поддерживает не все типы привилегий MySQL. В свою очередь, в MySQL отсутствует поддержка привилегий ANSI SQL TRIGGER, UNDER.
  • Структура привилегий ANSI SQL является иерархической. Если удалить пользователя, то все назначенные этому пользователелю привилегии будут отменены. В MySQL назначенные привилегии не отменяются автоматически, их при необходимости требуется удалять самостоятельно.
  • В MySQL пользователь может применять к таблице оператор INSERT при наличии у него привилегии INSERT только для нескольких столбцов в этой таблице. Столбцы, для которых отсутствует привилегия INSERT, будут установлены в свои значения, принятые по умолчанию. В ANSI SQL требуется наличие привилегии INSERT для всех столбцов.
  • При удалении таблицы в ANSI SQL все привилегии для этой таблицы будут отменены. Если отменить привилегию в ANSI SQL, то все привилегии, которые были назначены на основе этой привилегии, также будут отменены. В MySQL привилегии могут удаляться только при помощи команды REVOKE или путем изменения таблиц назначения привилегий MySQL.

Чтобы ознакомиться с описанием использования REQUIRE, см. раздел See section 4.3.9 Использование безопасных соединений.

4.3.2 Имена пользователей MySQL и пароли

Между MySQL и Unix или Windows существует несколько различий в использовании имен пользователей и паролей:

  • Имена пользователей, которые применяются в MySQL для авторизации, не имеют ничего общего с именами пользователей Unix (аккаунты Unix) или именами пользователей Windows. Большинство клиентов MySQL по умолчанию пытаются войти в систему, используя текущее имя пользователя Unix в качестве имени пользователя MySQL, но это сделано только для удобства. Программы клиентов позволяют указывать различные имена при помощи параметров -u или --user. Это означает, что невозможно обеспечить безопасность базы данных, если не все имена пользователей MySQL снабжены паролями: ведь можно попытаться подсоединиться к серверу, используя любое имя, а если воспользоваться именем, которому не назначен пароль, то удастся войти в систему.
  • Имена пользователей MySQL могут содержать до 16 символов. Имена пользователей Unix обычно ограничены 8 символами.
  • Пароли MySQL не имеют никакого отношения к паролям Unix. Не существует связи между паролем, который используется для входа в Unix, и паролем, необходимым для доступа к базе данных.
  • MySQL шифрует пароли при помощи своего алгоритма, который отличается от алгоритма Unix, используемого во время входа в систему. Описание функций PASSWORD() и ENCRYPT() можно найти в разделе See section 6.3.6.2 Разные функции. Обратите внимание: даже если ваш пароль хранится в 'зашифрованном виде', то знания этого 'зашифрованного' пароля будет достаточно, чтобы подсоединиться к серверу MySQL!

Пользователи MySQL и их привилегии обычно создаются при помощи команды GRANT. See section 4.3.1 Синтаксис команд GRANT и REVOKE.

Если подсоединение к серверу MySQL осуществляется с клиента командной строки, необходимо указать пароль при помощи параметра --password=your-password. See section 4.2.8 Соединение с сервером MySQL.

mysql --user=monty --password=guess database_name

Если необходимо, чтобы клиент запрашивал пароль, то следует указать --password без каких-либо аргументов

mysql --user=monty --password database_name

или сокращенный вариант этого параметра:

mysql -u monty -p database_name

Обратите внимание на то, что в последнем примере database_name не является паролем.

Если необходимо указать пароль при помощи параметра -p, то следует поступить следующим образом:

mysql -u monty -pguess database_name

В некоторых системах вызов библиотеки, который MySQL использует для запроса пароля, автоматически обрезает пароль до 8 символов. В самом MySQL не существует никаких ограничений на длину пароля.

4.3.3 Когда изменения в привилегиях вступают в силу

При запуске mysqld все таблицы назначения привилегий загружаются в память и с этого момента привилегии вступают в силу.

Изменения, которые вносятся в таблицы назначения привилегий при помощи команд GRANT, REVOKE или SET PASSWORD, учитываются сервером немедленно.

Если вносить изменения в таблицы назначения привилегий вручную (при помощи команд INSERT, UPDATE и т.д.), необходимо запускать оператор FLUSH PRIVILEGES, mysqladmin flush-privileges или mysqladmin reload, чтобы указать серверу на необходимость перезагрузить эти таблицы. В противном случае изменения не вступят в силу, пока сервер не будет перезагружен. Если внести изменения вручную, но не перезагрузить таблицы назначения привилегий, то останется только удивляться, почему внесенные изменения не действуют!

Когда сервер замечает, что были внесены изменения в таблицы назначения привилегий, он обрабатывает установленные соединения клиентов следующим образом:

  • Изменения привилегий таблиц и столбцов вступают в силу при следующем запросе клиента
  • Изменения привилегий баз данных вступают в силу при следующем использовании команды USE db_name
  • Изменения глобальных привилегий и изменения пароля вступают в силу при следующем подсоединении пользователя.

4.3.4 Задание изначальных привилегий MySQL

После установки MySQL изначальные привилегии доступа задаются при помощи `scripts/mysql_install_db'. See section 2.3.1 Обзор быстрой установки. Скрипт mysql_install_db запускает сервер mysqld, а затем инициализирует таблицы предоставления привилегий со следующим набором привилегий:

  • В качестве суперпользователя создается MySQL root который может делать все, что угодно. Соединения должны устанавливаться с локального компьютера. Примечание: Изначально пароль root пуст, поэтому кто угодно может подсоединиться в качестве root без пароля и получить все привилегии.
  • Создается анонимный пользователь, который может выполнять любые операции над базами данных с именами test или начинающимися с test_. Соединения должны устанавливаться с локального компьютера. Это означает, что любой локальный пользователь может подключиться без пароля и будет воспринят сервером как анонимный пользователь.
  • Остальные привилегии запрещены. Например, обычный пользователь не может использовать команды mysqladmin shutdown или mysqladmin processlist.

Примечание: В Windows принятые по умолчанию привилегии отличаются от указанных. See section 2.6.2.3 Работа MySQL в среде Windows.

Поскольку сразу после установки программа совершенно не защищена, первым делом необходимо задать пароль для пользователя MySQL root. Это можно сделать следующим образом (обратите внимание, что пароль указывается при помощи функции PASSWORD()):

shell> mysql -u root mysql
mysql> SET PASSWORD FOR root@localhost=PASSWORD('new_password');

Опытные пользователи могут работать непосредственно с таблицами назначения привилегий:

shell> mysql -u root mysql
mysql> UPDATE user SET Password=PASSWORD('new_password')
    ->     WHERE user='root';
mysql> FLUSH PRIVILEGES;

Еще один способ задать пароль - воспользоваться командой mysqladmin:

shell> mysqladmin -u root password new_password

Изменять пароли других пользователей могут только пользователи с правом записи/обновления базы данных mysql. Все обычные пользователи (не анонимные) могут модифицировать только свой собственный пароль при помощи указанных выше команд или команды SET PASSWORD=PASSWORD('new_password').

Обратите внимание на то, что если пароль в таблице user обновляется напрямую при помощи первого метода, требуется указать серверу на необходимость перезагрузки таблиц привилегий (при помощи команды FLUSH PRIVILEGES), иначе изменения не будут учтены.

После того, как был задан пароль root, этот пароль необходимо будет вводить, подсоединяясь к серверу как root.

Можно оставить пароль root пустым, тогда не придется его указывать во время проведения дополнительных установок и тестирования. Тем не менее, обязательно укажите его, прежде чем использовать сервер для любой реальной работы.

Ознакомьтесь со скриптом `scripts/mysql_install_db', чтобы увидеть, как задавать привилегии по умолчанию. Данный скрипт можно использовать как основу для добавления других пользователей.

Если необходимо, чтобы изначальные привилегии отличались от указанных выше, можно изменить базу mysql_install_db еще до ее запуска.

Чтобы полностью заново создать таблицы предоставления привилегий, удалите все файлы с расширениями `.frm', `.MYI' и `.MYD' в каталоге, где находится база данных mysql (это каталог с именем mysql в каталоге базы данных, который выводится на экран при запуске команды mysqld --help). Затем запустите скрипт mysql_install_db (возможно, после добавления в него необходимых привилегий).

Примечание: в более старых, чем 3.22.10, версиях MySQL файлы с расширением `.frm' удалять не следует. Если же случайно они были удалены, их следует восстановить, скопировав из дистрибутива MySQL до запуска mysql_install_db.

4.3.5 Добавление новых пользователей в MySQL

Пользователей можно добавлять двумя различными способами - при помощи команды GRANT или напрямую в таблицы назначения привилегий MySQL. Предпочтительнее использовать команду GRANT - этот способ проще и дает меньше ошибок. See section 4.3.1 Синтаксис команд GRANT и REVOKE.

Существует также большое количество программ (таких как phpmyadmin), которые служат для создания и администрирования пользователей.

В приведенных ниже примерах демонстрируется, как использовать клиент mysql для задания новых пользователей. В примерах предполагается, что привилегии установлены в соответствии с принятыми по умолчанию значениями, описанными в предыдущем разделе. Это означает, что для внесения изменений на том же компьютере, где запущен mysqld, необходимо подсоединиться к серверу как пользователь MySQL root, и у пользователя root должна быть привилегия INSERT для базы данных mysql, а также административная привилегия RELOAD. Кроме того, если был изменен пароль пользователя root, его необходимо указать здесь для команды mysql.

Новых пользователей можно добавлять, используя команду GRANT:

shell> mysql --user=root mysql
mysql> GRANT ALL PRIVILEGES ON *.* TO monty@localhost
    ->     IDENTIFIED BY 'some_pass' WITH GRANT OPTION;
mysql> GRANT ALL PRIVILEGES ON *.* TO monty@"%"
        -> IDENTIFIED BY 'some_pass' WITH GRANT OPTION;
mysql> GRANT RELOAD,PROCESS ON *.* TO admin@localhost;
mysql> GRANT USAGE ON *.* TO dummy@localhost;

Эти команды GRANT создают трех новых пользователей:

monty
Полноценный суперпользователь - он может подсоединяться к серверу откуда угодно, но должен использовать для этого пароль some_pass. Обратите внимание на то, что мы должны применить операторы GRANT как для monty@localhost, так и для monty@"%". Если не добавить запись с localhost, запись анонимного пользователя для localhost, которая создается при помощи mysql_install_db, будет иметь преимущество при подсоединении с локального компьютера, так как в ней указано более определенное значение для поля Host, и она расположена раньше в таблице user.
admin
Пользователь, который может подсоединяться с localhost без пароля; ему назначены административные привилегии RELOAD и PROCESS. Эти привилегии позволяют пользователю запускать команды mysqladmin reload, mysqladmin refresh и mysqladmin flush-*, а также mysqladmin processlist. Ему не назначено никаких привилегий, относящихся к базам данных (их можно назначить позже, дополнительно применив оператор GRANT).
dummy
Пользователь, который может подсоединяться к серверу без пароля, но только с локального компьютера. Все глобальные привилегии установлены в значение 'N'-тип привилегии USAGE, который позволяет создавать пользователей без привилегий. Предполагается, что относящиеся к базам данных привилегии будут назначены позже.

Можно напрямую добавить точно такую же информацию о пользователе при помощи оператора INSERT, а затем дать серверу команду перезагрузить таблицы назначения привилегий:

shell> mysql --user=root mysql
mysql> INSERT INTO user VALUES('localhost','monty',PASSWORD('some_pass'),
    ->		'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y');
mysql> INSERT INTO user VALUES('%','monty',PASSWORD('some_pass'),
    ->		'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y');
mysql> INSERT INTO user SET Host='localhost',User='admin',
    ->		 Reload_priv='Y', Process_priv='Y';
mysql> INSERT INTO user (Host,User,Password)
    ->		 VALUES('localhost','dummy','');
mysql> FLUSH PRIVILEGES;

В зависимости от версии MySQL в примере, приведенном выше, может указываться различное количество значений 'Y' (в версиях до Version 3.22.11 было меньше столбцов привилегий). Для пользователя admin используется более удобочитаемый расширенный синтаксис команды INSERT, который доступен начиная с версии 3.22.11.

Обратите внимание: чтобы создать суперпользователя, необходимо создать запись таблицы user с полями привилегий, установленными в значение 'Y'. Нет необходимости задавать значения в записях таблиц db или host.

Столбцы привилегий в таблице user в последнем операторе INSERT (для пользователя dummy) не были заданы явно, поэтому данным столбцам был присвоено принятое по умолчанию значение 'N'. Точно так же действует команда GRANT USAGE.

В приведенном ниже примере добавляется пользователь custom, который может подсоединяться с компьютеров localhost, server.domain и whitehouse.gov. Он хочет получать доступ к базе данных bankaccount только с компьютера localhost, к базе данных expenses - только с whitehouse.gov, и к базе данных customer - со всех трех компьютеров, а также использовать пароль stupid при подсоединении со всех трех компьютеров.

Чтобы задать эти привилегии пользователя при помощи оператора GRANT, выполните следующие команды:

shell> mysql --user=root mysql
mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
    -> 	   ON bankaccount.*
    -> 	   TO custom@localhost
    ->     IDENTIFIED BY 'stupid';
mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
    ->     ON expenses.*
    ->     TO custom@whitehouse.gov
    ->     IDENTIFIED BY 'stupid';
mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
    ->     ON customer.*
    ->     TO custom@'%'
    ->     IDENTIFIED BY 'stupid';

Привилегии для пользователя custom мы назначаем потому, что этот пользователь хочет получать доступ к MySQL как с локального компьютера через сокеты Unix, так и с удаленного компьютера whitehouse.gov через протокол TCP/IP.

Чтобы задать привилегии пользователя путем непосредственного внесения изменений в таблицы назначения привилегий, выполните следующие команды (обратите внимание на команду FLUSH PRIVILEGES в конце примера):

shell> mysql --user=root mysql
mysql> INSERT INTO user (Host,User,Password)
    -> VALUES('localhost','custom',PASSWORD('stupid'));
mysql> INSERT INTO user (Host,User,Password)
    -> VALUES('server.domain','custom',PASSWORD('stupid'));
mysql> INSERT INTO user (Host,User,Password)
    -> VALUES('whitehouse.gov','custom',PASSWORD('stupid'));
mysql> INSERT INTO db
    -> (Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv,
    -> Create_priv,Drop_priv)
    -> VALUES
    -> ('localhost','bankaccount','custom','Y','Y','Y','Y','Y','Y');
mysql> INSERT INTO db
    -> (Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv,
    -> Create_priv,Drop_priv)
    -> VALUES
    -> ('whitehouse.gov','expenses','custom','Y','Y','Y','Y','Y','Y');
mysql> INSERT INTO db
    -> (Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv,
    -> Create_priv,Drop_priv)
    -> VALUES('%','customer','custom','Y','Y','Y','Y','Y','Y');
mysql> FLUSH PRIVILEGES;

Первые три оператора INSERT добавляют в таблицу user записи, которые позволят пользователю custom подключаться с различных компьютеров с указанным паролем, но не дают ему никаких привилегий (все привилегии установлены в принятое по умолчанию значение 'N'). Следующие три оператора INSERT добавляют записи в таблицу db, в которой назначаются привилегии для пользователя custom по отношению к базам данных bankaccount, expenses и customer, но только если доступ осуществляется с определенных компьютеров. Как обычно, после внесения изменений непосредственно в таблицы назначения привилегий серверу необходимо дать команду на перезагрузку этих таблиц (при помощи FLUSH PRIVILEGES), чтобы внесенные изменения вступили в силу.

Если необходимо предоставить определенному пользователю доступ с любого компьютера к определенному домену, можно воспользоваться оператором GRANT следующим образом:

mysql> GRANT ...
    ->	   ON *.*
    ->     TO myusername@"%.mydomainname.com"
    ->     IDENTIFIED BY 'mypassword';

Чтобы сделать то же самое путем непосредственного внесения изменений в таблицы назначения привилегий, выполните следующие действия:

mysql> INSERT INTO user VALUES ('%.mydomainname.com', 'myusername',
    ->		   PASSWORD('mypassword'),...);
mysql> FLUSH PRIVILEGES;

4.3.6 Ограничение ресурсов пользователя

Начиная с MySQL версии 4.0.2 можно ограничивать определенные ресурсы, выделяемые пользователям.

До этой версии единственным возможным методом ограничения использования ресурсов сервера MySQL была установка переменной запуска max_user_connections в значение, отличное от нуля. Но этот метод действует только на глобальном уровне и не позволяет управлять отдельными пользователями. Он может представлять определенный интерес только для провайдеров услуг Internet.

На уровне отдельного пользователя теперь введено управление следующими тремя ресурсами:

  • Количество всех запросов в час: все команды, которые может запускать пользователь.
  • Количество всех обновлений в час: любая команда, которая изменяет таблицу или базу данных.
  • Количество соединений, сделанных за час: новые соединения, открытые за час.

Пользователь в упомянутом выше контексте представляет собой отдельную запись в таблице user, которая уникальным образом идентифицируется своими столбцами user и host.

По умолчанию все пользователи не ограничены в использовании указанных выше ресурсов только в случае, только если эти ограничения не наложены на них. Данные ограничения могут быть наложены только при помощи глобальной команды GRANT (*.*) с использованием следующего синтаксиса:

GRANT ... WITH MAX_QUERIES_PER_HOUR N1
           MAX_UPDATES_PER_HOUR N2
           MAX_CONNECTIONS_PER_HOUR N3;

Можно указать любое сочетание приведенных выше ресурсов. N1, N2 и N3 являются целыми числами, представляющими собой значения количеств запросов/обновлений/соединений в час.

Если пользователь в течение часа достигает предела любого из вышеуказанных значений, его соединение будет прервано с выдачей соответствующего сообщения об ошибке.

Текущие значения для определенного пользователя могут быть сброшены (установлены в нуль), если воспользоваться оператором GRANT с любым из приведенных выше пунктов, включая оператор GRANT с текущими значениями.

Кроме того, текущие значения для всех пользователей сбрасываются, если производится перезагрузка привилегий (на сервере или при использовании команды mysqladmin reload) или если выполняется команда FLUSH USER_RESOURCES.

Эта функция включается сразу после того, как на пользователя будут наложены ограничения при помощи команды GRANT.

Необходимым условием для включения данной функции является наличие в таблице user базы данных mysql дополнительного столбца, как это определено в скриптах создания таблиц mysql_install_db и mysql_install_db.sh в подкаталоге `scripts'.

4.3.7 Задание паролей

В большинстве случаев для задания пользователей и их паролей следует пользоваться командой GRANT, поэтому приведенная ниже информация предназначена для опытных пользователей. See section 4.3.1 Синтаксис команд GRANT и REVOKE.

В примерах, приведенных в предыдущих разделах, демонстрируется важный принцип, который заключается в следующем: при сохранении непустых паролей с использованием операторов INSERT или UPDATE для их шифрования должна применяться функция PASSWORD(). Это делается потому, что в таблице user пароли хранятся в зашифрованном виде, а не как простой текст. Предположим, что мы упустили это из виду и задали пароли следующим образом:

shell> mysql -u root mysql
mysql> INSERT INTO user (Host,User,Password)
    -> VALUES('%','jeffrey','biscuit');
mysql> FLUSH PRIVILEGES;

В результате выполнения этих команд в таблице user будет сохранено значение пароля biscuit в виде простого текста. Когда пользователь jeffrey попытается подсоединиться к серверу, используя этот пароль, клиент mysql зашифрует его при помощи функции PASSWORD(), сгенерирует вектор аутентификации, основанный на зашифрованном пароле и случайно выбранном числе, полученном от сервера, и направит результат на сервер. Сервер использует значение password из таблицы user (в данном случае, это незашифрованное значение biscuit), чтобы осуществить точно такие же вычисления, и сравнит результаты. Результаты не совпадут, и сервер не позволит установить соединение:

shell> mysql -u jeffrey -pbiscuit test
Access denied

Перед занесением в таблицу user пароли необходимо зашифровывать, поэтому оператор INSERT должен использоваться следующим образом:

mysql> INSERT INTO user (Host,User,Password)
    -> VALUES('%','jeffrey',PASSWORD('biscuit'));

При использовании оператора SET PASSWORD также необходимо применять функцию PASSWORD():

mysql> SET PASSWORD FOR jeffrey@"%" = PASSWORD('biscuit');

Если пароль задается при помощи оператора GRANT ... IDENTIFIED BY или команды mysqladmin password, нет необходимости использовать функцию PASSWORD(). Обе эти команды самостоятельно производят шифровку пароля, поэтому пароль следует указывать как biscuit, например, таким образом:

mysql> GRANT USAGE ON *.* TO jeffrey@"%" IDENTIFIED BY 'biscuit';

или

shell> mysqladmin -u jeffrey password biscuit

Примечание: Функция PASSWORD() шифрует пароли отличным от Unix образом. Не следует полагать, что если ваши пароли для Unix и для MySQL совпадают, то функция PASSWORD() выдаст точно такой же результат шифрования, как и файл паролей Unix. See section 4.3.2 Имена пользователей MySQL и пароли.

4.3.8 Обеспечение безопасности своего пароля

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

  • Никогда не заносите пароль обычного доступа в таблицу mysql.user. Зная даже зашифрованный пароль пользователя, можно войти в систему под именем этого пользователя. Пароли шифруются только для того, чтобы нельзя было увидеть, какой именно пароль используется (если вы используете один и тот же пароль для разных приложений).
  • Использование параметров -pyour_pass или --password=your_pass в командной строке удобно, но не очень безопасно, так как ваш пароль становится видимым для системных статусных утилит (таких как ps), и другие пользователи могут просмотреть командные строки (во время запуска клиенты MySQL обычно перезаписывают аргументы командной строки нулями, но существует небольшой промежуток времени, на протяжении которого значение остается видимым).
  • Используйте параметр -p или --password (без указания значения your_pass). В этом случае программа клиента запрашивает пароль с терминала:
    shell> mysql -u user_name -p
Enter password: ********
    Ваш пароль будет представлен символами `*'. Вводить пароль таким образом намного безопаснее, чем из командной строки, поскольку он невидим для остальных пользователей. Тем не менее, этот метод подходит только для тех программ, которые вы запускаете самостоятельно. Если клиент требуется запустить из скрипта, то возможности ввести пароль с терминала не будет. В некоторых системах первая строка скрипта считывается и неправильно распознается как ваш пароль!
  • Храните свой файл в файле конфигурации. Например, можно записать свои пароли в разделе [client] файла `.my.cnf' в своем каталоге:
    [client]
password=your_pass
    Если пароль хранится в `.my.cnf', файл не должен быть доступен для чтения или записи для всех или для отдельных групп пользователей. Убедитесь, что права доступа к файлу установлены в 400 или 600.
  • Можно хранить свой пароль в переменной окружения MYSQL_PWD, но этот метод считается очень небезопасным и не должен использоваться. В некоторые версии ps включена возможность отображать переменные окружения работающего процесса. Поэтому если задать свой пароль при помощи MYSQL_PWD, он будет виден для всех,. Даже в системах без такой версии ps, неразумно предполагать, что не существует другого метода получить информацию по переменным окружения. See section E Переменные окружения.

Исходя из всего сказанного выше, самыми безопасными методами указания пароля являются запрос программы клиента на ввод пароля с терминала или указание пароля в защищенном надлежащим образом файле `.my.cnf'.

4.3.9 Использование безопасных соединений

4.3.9.1 Основные сведения

MySQL поддерживает шифрованные SSL-соединения. Для лучшего понимания того, как в MySQL используется SSL, мы приводим здесь основные сведения по SSL и X509. Пользователи, которые уже знакомы с данным протоколом и стандартом, эту часть могут пропустить.

По умолчанию в MySQL используются незашифрованные соединения между клиентом и сервером. Это означает, что просматривать все данные, передаваемые между клиентом и сервером, может кто угодно. На практике можно даже изменять данные во время передачи их от клиента к серверу и наоборот. Помимо того, иногда возникает необходимость передать действительно секретные данные через общедоступную сеть - в таких случаях использование незашифрованных соединений просто неприемлемо.

В протоколе SSL используются различные алгоритмы шифрования, обеспечивающие безопасность для данных, передаваемых через общедоступные сети. Этот протокол содержит средства, позволяющие обнаруживать любые изменения, потери и повторы данных. В протоколе SSL также применяются алгоритмы для проведения идентификации при помощи стандарта X509.

Шифровка - это метод, позволяющий сделать прочтение любых данных невозможным. Фактически при современном положении дел для алгоритмов шифрования требуется использование дополнительных элементов безопасности. Они должны обеспечивать противодействие многим видам известных на настоящий момент атак, таких как изменение порядка зашифрованных сообщений или повторение данных.

Стандарт X509 позволяет производить идентификацию в Internet. Чаще всего он используется в приложениях электронной коммерции. Упрощенно схема его применения выглядит следующим образом: существует некая организация под названием "Certificate Authority" (можно перевести как ``Сертификационное Бюро''. - Прим. пер.), которая назначает электронные сертификаты всем, кому они нужны. Сертификаты основываются на асимметричных алгоритмах шифрования, содержащих два ключа - публичный и секретный. Владелец сертификата может подтвердить свою личность, предъявив свой сертификат другой стороне. Сертификат состоит из публичного ключа владельца. Любые данные, зашифрованные при помощи этого публичного ключа могут быть расшифрованы только при помощи соответствующего секретного ключа, который находится у владельца сертификата.

В MySQL по умолчанию не используется шифрование при соединениях, так как это значительно замедляет обмен данными между клиентом и сервером. Любые дополнительные функции приводят к дополнительной нагрузке для компьютера, а шифрование данных требует интенсивной работы процессора, что может вызвать задержку выполнения основных задач MySQL. По умолчанию MySQL настроен на максимально быструю работу.

Если вы хотите получить дополнительную информацию о SSL/X509/шифровании, необходимо воспользоваться своим любимым поисковым сервером Internet и произвести поиск по словам, которые вас интересуют.

4.3.9.2 Требования

Для того чтобы SSL-соединения могли работать с MySQL, необходимо выполнить следующие действия:

  1. Установите библиотеку OpenSSL. Тестирование MySQL производилось с библиотекой OpenSSL 0.9.6. http://www.openssl.org/.
  2. Выполните настройку компиляции MySQL (configure) при помощи параметров --with-vio --with-openssl.
  3. Если используется старая версия MySQL, то необходимо обновить таблицу mysql.user путем добавления в нее определенных новых столбцов. Это можно сделать, запустив скрипт mysql_fix_privilege_tables.sh.
  4. Проверить, скомпилирована ли в запущенном сервере mysqld библиотека OpenSSL можно, убедившись, что SHOW VARIABLES LIKE 'have_openssl' показывает YES.

4.3.9.3 Создание SSL-сертификатов

Вот пример, как создаются SSL-сертификаты для MySQL:

DIR=`pwd`/openssl
PRIV=$DIR/private

mkdir $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

# Пример вывода:
# Using configuration from /home/monty/openssl/openssl.cnf
# Generating a 1024 bit RSA private key
# ................++++++
# .........++++++
# writing new private key to '/home/monty/openssl/private/cakey.pem'
# Enter PEM pass phrase:
# Verifying password - Enter PEM pass phrase:
# -----
# You are about to be asked to enter information that will be incorporated
# into your certificate request.
# What you are about to enter is what is called a Distinguished Name or a DN.
# There are quite a few fields but you can leave some blank
# For some fields there will be a default value,
# If you enter '.', the field will be left blank.
# -----
# Country Name (2 letter code) [AU]:FI
# State or Province Name (full name) [Some-State]:.
# Locality Name (eg, city) []:
# Organization Name (eg, company) [Internet Widgits Pty Ltd]:MySQL AB
# Organizational Unit Name (eg, section) []:
# Common Name (eg, YOUR name) []:MySQL admin
# Email Address []:

#
# Создаем server-request и ключ
#
openssl req -new -keyout $DIR/server-key.pem -out \
    $DIR/server-req.pem -days 3600 -config $DIR/openssl.cnf

# Пример вывода:
# Using configuration from /home/monty/openssl/openssl.cnf
# Generating a 1024 bit RSA private key
# ..++++++
# ..........++++++
# writing new private key to '/home/monty/openssl/server-key.pem'
# Enter PEM pass phrase:
# Verifying password - Enter PEM pass phrase:
# -----
# You are about to be asked to enter information that will be incorporated
# into your certificate request.
# What you are about to enter is what is called a Distinguished Name or a DN.
# There are quite a few fields but you can leave some blank
# For some fields there will be a default value,
# If you enter '.', the field will be left blank.
# -----
# Country Name (2 letter code) [AU]:FI
# State or Province Name (full name) [Some-State]:.
# Locality Name (eg, city) []:
# Organization Name (eg, company) [Internet Widgits Pty Ltd]:MySQL AB
# Organizational Unit Name (eg, section) []:
# Common Name (eg, YOUR name) []:MySQL server
# Email Address []:
#
# Please enter the following 'extra' attributes
# to be sent with your certificate request
# A challenge password []:
# An optional company name []:

#
# Удаляем парольную фразу из ключа (опционально)
#

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

# Пример вывода:
# Using configuration from /home/monty/openssl/openssl.cnf
# Enter PEM pass phrase:
# Check that the request matches the signature
# Signature ok
# The Subjects Distinguished Name is as follows
# countryName           :PRINTABLE:'FI'
# organizationName      :PRINTABLE:'MySQL AB'
# commonName            :PRINTABLE:'MySQL admin'
# Certificate is to be certified until Sep 13 14:22:46 2003 GMT (365 days)
# Sign the certificate? [y/n]:y
#
#
# 1 out of 1 certificate requests certified, commit? [y/n]y
# Write out database with 1 new entries
# Data Base Updated

#
# Создаем client request и ключ
#
openssl req -new -keyout $DIR/client-key.pem -out \
    $DIR/client-req.pem -days 3600 -config $DIR/openssl.cnf

# Пример вывода:
# Using configuration from /home/monty/openssl/openssl.cnf
# Generating a 1024 bit RSA private key
# .....................................++++++
# .............................................++++++
# writing new private key to '/home/monty/openssl/client-key.pem'
# Enter PEM pass phrase:
# Verifying password - Enter PEM pass phrase:
# -----
# You are about to be asked to enter information that will be incorporated
# into your certificate request.
# What you are about to enter is what is called a Distinguished Name or a DN.
# There are quite a few fields but you can leave some blank
# For some fields there will be a default value,
# If you enter '.', the field will be left blank.
# -----
# Country Name (2 letter code) [AU]:FI
# State or Province Name (full name) [Some-State]:.
# Locality Name (eg, city) []:
# Organization Name (eg, company) [Internet Widgits Pty Ltd]:MySQL AB
# Organizational Unit Name (eg, section) []:
# Common Name (eg, YOUR name) []:MySQL user
# Email Address []:
#
# Please enter the following 'extra' attributes
# to be sent with your certificate request
# A challenge password []:
# An optional company name []:

#
# Удаляем парольную фразу из ключа (опционально)
#
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

# Пример вывода:
# Using configuration from /home/monty/openssl/openssl.cnf
# Enter PEM pass phrase:
# Check that the request matches the signature
# Signature ok
# The Subjects Distinguished Name is as follows
# countryName           :PRINTABLE:'FI'
# organizationName      :PRINTABLE:'MySQL AB'
# commonName            :PRINTABLE:'MySQL user'
# Certificate is to be certified until Sep 13 16:45:17 2003 GMT (365 days)
# Sign the certificate? [y/n]:y
#
#
# 1 out of 1 certificate requests certified, commit? [y/n]y
# Write out database with 1 new entries
# Data Base Updated

#
# Создаем такой 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

#
# Тестируем MySQL

mysqld --defaults-file=$DIR/my.cnf &

mysql --defaults-file=$DIR/my.cnf

Вы также можете тестировать сертификаты путем модификации my.cnf таким образом, чтобы использовать демонстрационные сертификаты в каталоге mysql-source-dist/SSL.

4.3.9.4 Параметры команды GRANT

В дополнение к обычной схеме имя пользователя/пароль MySQL может производить проверку атрибутов сертификата X509. Для этого необходимы также все обычные параметры (имя пользователя, пароль, маска IP-адреса, имя базы данных/таблицы).

Существует несколько возможностей ограничить соединения:

  • Если не указано никаких параметров SSL/X509, а имя пользователя и пароль указаны правильно, то разрешены все виды шифрованных и нешифрованных соединений.
  • Параметр REQUIRE SSL позволяет серверу устанавливать только зашифрованные при помощи протокола SSL соединения. Обратите внимание, что этот параметр может быть неприемлемым, если существуют записи ACL, разрешающие не-SSL соединения.
    mysql> GRANT ALL PRIVILEGES ON test.* TO root@localhost
    -> IDENTIFIED BY "goodsecret" REQUIRE SSL;
  • REQUIRE X509 означает, что у клиента должен быть действительный сертификат, но мы не требуем наличия определенного сертификата, сертификата определенной фирмы или темы. Единственное ограничение - подпись должна поддаваться проверке при помощи одного из сертификатов бюро сертификации.
    mysql> GRANT ALL PRIVILEGES ON test.* TO root@localhost
    -> IDENTIFIED BY "goodsecret" REQUIRE X509;
  • REQUIRE ISSUER "issuer" делает требования по соединению более определенными: теперь клиент должен предоставить действительный сертификат X509, выданный бюро сертификации (CA) "issuer". Использование сертификатов X509 всегда означает применение шифрования, поэтому параметр SSL больше не нужен.
    mysql> GRANT ALL PRIVILEGES ON test.* TO root@localhost
    -> IDENTIFIED BY "goodsecret"
    -> REQUIRE ISSUER "C=FI, ST=Some-State, L=Helsinki,
    "> O=MySQL Finland AB, CN=Tonu Samuel/Email=tonu@mysql.com";
  • REQUIRE SUBJECT "subject" требует наличия у клиента действительного сертификата X509 с содержащейся в нем темой "subject". Если у клиента есть действительный сертификат, но другой "subject", то соединение не будет установлено.
    mysql> GRANT ALL PRIVILEGES ON test.* TO root@localhost
    -> IDENTIFIED BY "goodsecret"
    -> REQUIRE SUBJECT "C=EE, ST=Some-State, L=Tallinn,
    "> O=MySQL demo client certificate,
    "> CN=Tonu Samuel/Email=tonu@mysql.com";
  • REQUIRE CIPHER "cipher" требуется для обеспечения достаточно сложных шифра и длины ключа. Протокол SSL сам по себе может быть ненадежным из-за использования старых алгоритмов с короткими ключами шифрования. Воспользовавшись этим параметром, мы можем указать определенный метод шифрования, разрешающий соединение.
    mysql> GRANT ALL PRIVILEGES ON test.* TO root@localhost
    -> IDENTIFIED BY "goodsecret"
    -> REQUIRE CIPHER "EDH-RSA-DES-CBC3-SHA";
    Разрешается также сочетать SUBJECT, ISSUER, CIPHER в REQUIRE, например, так:
    mysql> GRANT ALL PRIVILEGES ON test.* TO root@localhost
    -> IDENTIFIED BY "goodsecret"
    -> REQUIRE SUBJECT "C=EE, ST=Some-State, L=Tallinn,
    "> O=MySQL demo client certificate,
    "> CN=Tonu Samuel/Email=tonu@mysql.com"
    -> AND ISSUER "C=FI, ST=Some-State, L=Helsinki,
    "> O=MySQL Finland AB, CN=Tonu Samuel/Email=tonu@mysql.com"
    -> AND CIPHER "EDH-RSA-DES-CBC3-SHA";
    Начиная с MySQL 4.0.4, слово AND необязательно в опциях REQUIRE. Порядок опций не имеет значения, но ни одна опция не может быть указана дважды.

4.4 Предотвращение катастроф и восстановление

4.4.1 Резервное копирование баз данных

Поскольку таблицы MySQL хранятся в виде файлов, то резервное копирование выполняется легко. Чтобы резервная копия была согласованной, выполните на выбранных таблицах LOCK TABLES, а затем FLUSH TABLES для этих таблиц (см. разделы section 6.7.2 Синтаксис команд LOCK TABLES/UNLOCK TABLES и see section 4.5.3 Синтаксис команды FLUSH). При этом требуется блокировка только на чтение; поэтому другие потоки смогут продолжать запросы на таблицах в то время, пока будут создаваться копии файлов из каталога базы данных. Команда FLUSH TABLE обеспечивает гарантию того, что все активные индексные страницы будут записаны на диск прежде, чем начнется резервное копирование.

Начиная с 3.23.56 и 4.0.12 BACKUP TABLE не позволит вам перезаписать существующие файлы, так как это создает потенциальные проблемы в безопасности.

Если есть необходимость провести резервное копирование на уровне SQL, то можно воспользоваться SELECT INTO OUTFILE или BACKUP TABLE (см. разделы section 6.4.1 Синтаксис оператора SELECT и see section 4.4.2 Синтаксис BACKUP TABLE).

Существует еще один способ создать резервную копию базы данных - использовать программу mysqldump или сценарий mysqlhotcopy (см. разделы section 4.8.5 mysqldump, Получение дампов данных и структуры таблицы и see section 4.8.6 mysqlhotcopy, Копирование баз данных и таблиц MySQL). Для этого нужно выполнить следующие действия:

  1. Сделать полное резервное копирование баз данных:
    shell> mysqldump --tab=/path/to/some/dir --opt --all

или

shell> mysqlhotcopy database /path/to/some/dir
    Можно также просто скопировать табличные файлы (файлы `*.frm', `*.MYD' и `*.MYI') в тот момент, когда сервер не проводит никаких обновлений. Этот метод используется в сценарии mysqlhotcopy.
  2. Если mysqld выполняется, остановить его, и затем запустить с опцией --log-update[=file_name] (see section 4.9.3 Журнал обновлений (update)). В файлах журнала обновлений находится информация, необходимая для того, чтобы повторить в базе данных последовательность изменений, внесенных с момента выполнения mysqldump.

Если дело дошло до восстановления, сначала надо попробовать восстановить таблицы с помощью REPAIR TABLE или myisamchk -r - это должно сработать в 99,9% случаев. Если myisamchk не даст результата, попробуйте применить следующую процедуру (эти действия применимы только в случае, если MySQL запускался с --log-update (see section 4.9.3 Журнал обновлений (update))):

  1. Восстановите исходный вариант по копии, сделанной в mysqldump.
  2. Выполните следующую команду, чтобы повторить обновления из бинарного журнала:
    shell> mysqlbinlog hostname-bin.[0-9]* | mysql
    Если используется журнал обновлений, то можно применить:
    shell> ls -1 -t -r hostname.[0-9]* | xargs cat | mysql

ls используется для того, чтобы расположить все файлы журнала обновлений в правильном порядке.

Можно проводить избирательное резервное копирование посредством SELECT * INTO OUTFILE 'file_name' FROM tbl_name, а восстановление - при помощи LOAD DATA INFILE 'file_name' REPLACE ... Чтобы избежать повторения записей, в таблице должен быть первичный или уникальный ключ. Ключевое слово REPLACE задает замену старых записей новыми в случае, когда новая запись в значении уникального ключа повторяет старую.

Если в системе, где выполняется резервное копирование, возникают проблемы с производительностью, то решить их можно, установив репликацию и выполняя резервное копирование на подчиненном сервере вместо головного (see section 4.10.1 Введение).

Пользователи файловой системы Veritas могут поступить следующим образом:

  1. Из клиента (или Perl) выполнить: FLUSH TABLES WITH READ LOCK.
  2. Из другого shell выполнить: mount vxfs snapshot.
  3. Из первого клиента выполнить: UNLOCK TABLES.
  4. Скопировать файлы из образа.
  5. Демонтировать образ.

4.4.2 Синтаксис BACKUP TABLE

BACKUP TABLE tbl_name[,tbl_name...] TO '/path/to/backup/directory'

Копирует в каталог резервного копирования тот минимум табличных файлов, который достаточен для восстановления таблицы, после сброса на диск всех изменений. На данный момент работает только для таблиц MyISAM. Для таблиц MyISAM копирует файлы `.frm' (определений) и `.MYD' (данных). Индексные файлы могут быть реконструированы по этим двум.

Перед использованием этой команды, пожалуйста, ознакомьтесь с разделом See section 4.4.1 Резервное копирование баз данных.

В процессе резервного копирования будет установлена блокировка чтения отдельно для каждой таблицы на время ее копирования. Если необходимо сделать резервное копирование в виде мгновенного образа нескольких таблиц, необходимо сначала запросить LOCK TABLES установки блокировки чтения для каждой таблицы в группе.

Команда возвращает таблицу со следующими столбцами:

Столбец | Значение
Table | Имя таблицы
Op | Всегда ``backup''
Msg_type | Одно из значений status, error, info или warning.
Msg_text | Само сообщение.

Заметим, что BACKUP TABLE доступна только в версии MySQL 3.23.25 и выше.

4.4.3 Синтаксис RESTORE TABLE

RESTORE TABLE tbl_name[,tbl_name...] FROM '/path/to/backup/directory'

Восстанавливает таблицу(ы) из резервной копии, созданной с помощью BACKUP TABLE. Существующие таблицы не перезаписываются: при попытке восстановления поверх существующей таблицы будет выдана ошибка. Восстановление занимает больше времени, нежели BACKUP - из-за необходимости повторного построения индекса. Чем больше в таблице будет ключей, тем больше времени заберет реконструкция. Эта команда, так же как и BACKUP TABLE, в настоящее время работает только для таблиц MyISAM.

Команда возвращает таблицу со следующими столбцами:

Столбец | Значение
Table | Имя таблицы
Op | Всегда ``restore''
Msg_type | Одно из значений status, error, info или warning.
Msg_text | Само сообщение.

4.4.4 Синтаксис CHECK TABLE

CHECK TABLE tbl_name[,tbl_name...] [option [option...]]

option = QUICK | FAST | MEDIUM | EXTENDED | CHANGED

CHECK TABLE работает только на таблицах MyISAM и InnoDB. На таблицах типа MyISAM команда эквивалентна запуску на таблице myisamchk -m table_name.

Если опция не указана, используется MEDIUM.

Проверяет таблицу(ы) на наличие ошибок. Для таблиц MyISAM обновляется статистика ключей. Команда возвращает таблицу со следующими столбцами:

Столбец | Значение
Table | Имя таблицы.
Op | Всегда ``check''.
Msg_type | Одно из значений status, error, info, или warning.
Msg_text | Само сообщение.

Заметим, что по каждой проверяемой таблице может быть выдано много строк информации. Последняя строка будет представлять Msg_type status и, как правило, должна содержать OK. Если выдается что-либо отличное от OK и Not checked, то обычно следует провести ремонт таблицы (see section 4.4.6 Использование myisamchk для профилактики таблиц и послеаварийного). Table already up to date свидетельствует о том, что указанный для таблицы тип (TYPE) вернул информацию о том, что таблица не нуждается в проверке.

Различные типы проверки означают следующее:

Тип | Действия
QUICK | Не сканировать строки для проверки на неправильные связи.
FAST | Проверять только таблицы, которые не были корректно закрыты.
CHANGED | Проверять только таблицы, которые изменились со времени последней проверки или не были закрыты корректно.
MEDIUM | Сканировать строки для проверки того, что уничтоженные связи в порядке. При этом также подсчитывается ключевая контрольная сумма для строки и сравнивается с подсчитанной контрольной суммой для ключей.
EXTENDED | Выполнить полный просмотр ключа для всех ключей для каждой строки. Успех такой проверки гарантирует 100%-ное отсутствие противоречий в таблице, но на проверку уйдет немало времени!

Для таблиц MyISAM с динамическими размерами при запуске проверки всегда выполняется проверка MEDIUM. Для строк со статическими размерами мы пропускаем сканирование строк для QUICK и FAST, поскольку повреждение строк происходит крайне редко.

Проверочные опции можно сочетать:

CHECK TABLE test_table FAST QUICK;

Эта команда просто вызовет быструю проверку таблицы для выявления того, была ли она закрыта корректно.

Примечание: в некоторых случаях CHECK TABLE изменяет таблицу! Это происходит, если таблица помечена как 'поврежденная/corrupted' или 'не закрытая корректно/not closed properly', а CHECK TABLE не находит никаких проблем в таблице. В этом случае CHECK TABLE отметит в таблице, что с ней все нормально.

Если таблица повреждена, то, скорее всего, проблема в индексах, а не в данных. Проверки всех типов обеспечивают всестороннюю проверку индексов и тем самым должны обнаруживать большинство ошибок.

Если проверяется таблица, с которой предположительно все нормально, то можно опустить проверочные опции или указать опцию QUICK. Последнюю возможность следует использовать в случае ограничений по времени и тогда, когда можно пойти на риск (очень незначительный), что QUICK пропустит ошибку в файле данных. (В большинстве случаев MySQL должен найти - при нормальной работе - любые ошибки в файле с данными. Если ошибки найдены, то таблица будет отмечена как 'поврежденная/corrupted', и в таком случае ее нельзя будет использовать, пока она не будет исправлена.)

FAST и CHANGED главным образом предназначены для использования в сценариях (например, для запуска из cron), если необходимо время от времени проверять таблицы. В большинстве случаев следует отдавать предпочтение FAST перед CHANGED (иначе надо поступать только в случае, когда возникает подозрение, что найдена ошибка в самом коде MyISAM).

Прибегать к EXTENDED следует только тогда, когда после выполнения нормальной проверки для таблицы по-прежнему выдаются странные ошибки при попытке MySQL обновить строку или найти строку по ключу (что очень маловероятно в случае успеха нормальной проверки!).

Некоторые проблемы, о которых сообщается при проверке таблицы, нельзя исправить автоматически:

  • Found row where the auto_increment column has the value 0. Это означает, что в таблице есть строка, где индексированный столбец AUTO_INCREMENT содержит значение 0 (строку, в которой столбец AUTO_INCREMENT имеет значение 0, можно создать, явно установив столбец в 0 командой UPDATE). Это само по себе не является ошибкой, но может вызвать неприятности, если понадобится сделать дамп таблицы или восстановить ее или выполнить над ней ALTER TABLE. В этом случае столбец с атрибутом AUTO_INCREMENT изменит значение в соответствии с правилами для столбцов AUTO_INCREMENT, что может вызвать проблемы, подобные ошибке дублирования ключа. Чтобы избавиться от предупреждения, просто выполните команду UPDATE для установки в столбце значения, отличного от 0.

4.4.5 Синтаксис REPAIR TABLE

REPAIR TABLE tbl_name[,tbl_name...] [QUICK] [EXTENDED] [USE_FRM]

REPAIR TABLE работает только на таблицах типа MyISAM и эквивалентна выполнению на таблице myisamchk -r table_name.

При обыкновенной работе запускать эту команду не приходится, но если случится катастрофа, то с помощью REPAIR TABLE практически наверняка удастся вернуть все данные из таблицы MyISAM. Если таблицы сильно повреждены, то следует постараться выяснить, что послужило этому причиной! Обращайтесь к разделам section A.4.1 Что делать, если работа MySQL сопровождается постоянными сбоями и See section 7.1.3 Проблемы с таблицами MyISAM..

REPAIR TABLE ремонтирует таблицу, которая, возможно, повреждена. Команда возвращает таблицу со следующими столбцами:
Столбец | Значение
Table | Имя таблицы
Op | Всегда ``repair''
Msg_type | Одно из значений status, error, info или warning.
Msg_text | Само сообщение.

Заметим, что по каждой ремонтируемой таблице может быть выдано много строк информации. Последняя строка будет представлять Msg_type status и, как правило, должна содержать OK. Если выдается что-либо отличное от OK, то следует попробовать исправить таблицу с помощью myisamchk -o, поскольку в REPAIR TABLE пока реализованы не все опции myisamchk. В скором будущем мы сделаем команду более гибкой.

Если указан QUICK, то MySQL будет пытаться сделать REPAIR только индексного дерева.

Если используется EXTENDED, то MySQL будет создавать индекс строка за строкой вместо создания по одному индексу единоразово с помощью сортировки; такая техника может работать лучше сортировки для ключей фиксированной длины, если речь идет о хорошо сжимаемых ключах типа CHAR большой длины. Это такой же ремонт, как делается с помощью myisamchk --safe-recover.

Что касается MySQL 4.0.2, то тут для REPAIR существует режим USE_FRM. Используйте его, если отсутствует файл `.MYI' или поврежден его заголовок. В этом режиме MySQL воссоздаст таблицу, используя информацию из файла `.frm'. Этот вид исправления в myisamchk недоступен.

4.4.6 Использование myisamchk для профилактики таблиц и послеаварийного

восстановления

Начиная с версии MySQL 3.23.13 таблицы MyISAM можно проверять с помощью команды CHECK TABLE (see section 4.4.4 Синтаксис CHECK TABLE). Для исправления таблиц используется команда REPAIR TABLE (see section 4.4.5 Синтаксис REPAIR TABLE).

Для проверки/ремонта таблиц типа MyISAM (`.MYI' и `.MYD') следует использовать утилиту myisamchk, а для ISAM (`.ISM' и `.ISD'') - утилиту isamchk (see section 7 Типы таблиц MySQL).

Ниже мы будем говорить о myisamchk, но все сказанное справедливо также и для более старой isamchk.

Утилиту myisamchk можно использовать для получения информации о таблицах рабочей базы данных, для их проверки и исправления или же оптимизации. В следующих разделах описывается, как запускать myisamchk (включая описание ее опций), как настроить график профилактики таблицы и как использовать myisamchk для выполнения различных функций.

В большинстве случаев для оптимизации и исправления таблиц можно также использовать команду OPTIMIZE TABLES, но этот вариант не такой быстрый и не такой надежный (в случае действительно фатальных ошибок), как myisamchk. С другой стороны, OPTIMIZE TABLE проще в использовании и освобождает от забот со сбросом таблиц на диск (see section 4.5.1 Синтаксис команды OPTIMIZE TABLE).

Хотя исправление при помощи myisamchk и достаточно безопасно, никогда не будет лишним сделать резервную копию прежде, чем выполнять ремонт (или любые другие действия, которые могут привнести в таблицу значительные изменения)

4.4.6.1 Синтаксис запуска myisamchk

myisamchk запускается следующим образом:

shell> myisamchk [options] tbl_name

Опции options определяют, что должна сделать myisamchk. В данном разделе дается описание этих опций (список опций можно также получить, запустив myisamchk --help). Если опции не указаны, myisamchk просто проверяет таблицу. Чтобы получить дополнительную информацию или указать myisamchk выполнить корректирующие действия, надо задать опции, как это описано в этом и в следующих разделах.

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

При желании в командной строке myisamchk можно перечислить имена нескольких таблиц. В качестве имени можно также указать имя индексного файла (с суффиксом `.MYI'), что позволит задавать все таблицы в каталоге при помощи шаблона `*.MYI'. Например, находясь в каталоге базы данных, можно проверить все таблицы этого каталога следующим образом:

shell> myisamchk *.MYI

Если каталог базы данных не является текущим, то все таблицы каталога можно проверить, указав к нему путь:

shell> myisamchk /path/to/database_dir/*.MYI

Можно даже проверить все таблицы во всех базах данных, если задать шаблон вместе с путем к каталогу данных MySQL:

shell> myisamchk /path/to/datadir/*/*.MYI

Быстро проверять все таблицы рекомендуется следующим образом:

myisamchk --silent --fast /path/to/datadir/*/*.MYI
isamchk --silent /path/to/datadir/*/*.ISM

Если необходимо проверить все таблицы и исправить все поврежденные из них, можно использовать следующую строку:

myisamchk --silent --force --fast --update-state -O key_buffer=64M \
      -O sort_buffer=64M -O read_buffer=1M -O write_buffer=1M \
      /path/to/datadir/*/*.MYI
isamchk --silent --force -O key_buffer=64M -O sort_buffer=64M \
    -O read_buffer=1M -O write_buffer=1M /path/to/datadir/*/*.ISM

Эти команды предполагают, что имеется более чем 64 Mб свободного пространства.

Следует отметить, что если выдается ошибка, подобная следующей:

myisamchk: warning: 1 clients is using or hasn't closed the table properly

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

Если mysqld запущен, то необходимо принудительно вызвать синхронизацию/закрытие всех таблиц с помощью FLUSH TABLES и обеспечить, чтобы никто не использовал таблиц, пока выполняется myisamchk. В версии MySQL 3.23 самый простой способ избежать этой проблемы заключается в применении для проверки таблиц команды CHECK TABLE вместо myisamchk.

4.4.6.2 Общие опции для myisamchk

myisamchk поддерживает следующие опции.

-# или --debug=debug_options
Вывод отладочной информации. Часто строка debug_options имеет следующий вид d:t:o,filename.
-? или --help
Отображение справочного сообщения с завершением работы.
-O var=option, --set-variable var=option
Устанавливает значение переменной. Внимание: --set-variable морально устарела в MySQL 4.0, просто используйте --var=option. Вывести список допустимых переменных и их значений по умолчанию для myisamchk можно с помощью myisamchk --help:
Переменная | Значение
key_buffer_size | 523264
read_buffer_size | 262136
write_buffer_size | 262136
sort_buffer_size | 2097144
sort_key_blocks | 16
decode_bits | 9
sort_buffer_size применяется, когда ключи исправляются посредством сортировки ключей (обычный случай при указании --recover), а key_buffer_size - если таблица проверяется с --extended-check или если ключи исправляются посредством вставки ключей в таблицу построчно (как при выполнении обычных вставок). Исправление через ключевой буфер применяется в следующих случаях:
  • Если используется --safe-recover.
  • Если размер требуемых для сортировки временных файлов будет более чем вдвое превышать объем, требующийся при создании ключевого файла непосредственно. Так часто обстоит дело, когда присутствуют большие ключи типов CHAR, VARCHAR или TEXT, поскольку при сортировке необходимо сохранять ключи целиком. Имея временное пространство на диске в избытке, можно заставить myisamchk делать исправления посредством сортировки, задав опцию --sort-recover.
Ремонт посредством ключевого буфера требует значительно меньше пространства, чем при использовании сортировки, однако выполняется значительно медленнее. Когда желательно ускорить выполнение ремонта/исправления, переменные нужно установить равными приблизительно 1/4 доступной памяти. Можно для обеих переменных задавать большие значения, поскольку всякий раз будет использоваться только один из рассматриваемых буферов.
-s или --silent
Молчаливый режим. Выдавать сообщения только при возникновении ошибок. Можно использовать -s дважды (-ss), чтобы предельно ограничить выдачу сообщений утилитой myisamchk.
-v или --verbose
Расширенный режим вывода. Выдается больше информации. Можно использовать с -d и -e. Можно использовать -v многократно (-vv, -vvv) - чтобы еще более расширить сводку!
-V или --version
Отображение версии myisamchk и завершение работы.
-w или, --wait
Если таблица заблокирована, то не выдавать ошибки, а, дождавшись снятия блокировки с таблицы, продолжить выполнение. Заметим, что если mysqld выполняется на таблице с --skip-external-locking, то таблица может быть заблокирована только другой командой myisamchk.

4.4.6.3 Проверочные опции для myisamchk

-c или --check
Проверить таблицы на ошибки. Является операцией по умолчанию, если myisamchk не передаются другие опции, меняющие это поведение.
-e или --extend-check
Проверить таблицу очень тщательно (выполняется достаточно медленно в случае большого количества индексов). Эту опцию следует использовать в экстремальных ситуациях. В большинстве случаев myisamchk или myisamchk --medium-check вполне достаточно для выявления ошибок в таблице. Если используется --extended-check и система располагает приличным объемом памяти, то следует значительно увеличить значение key_buffer_size!
-F или --fast
Проверять только таблицы, которые не были корректно закрыты.
-C или --check-only-changed
Проверять только таблицы, изменившиеся с момента последней проверки.
-f или --force
Выполнять перезапуск myisamchk с -r (исправить) на таблице, если myisamchk найдет в ней хоть одну ошибку.
-i или --information
Выдавать статистическую информацию о проверяемой таблице.
-m или --medium-check
Быстрее, чем расширенная проверка (extended-check), но при этом обнаруживается только 99,99% из общего числа ошибок (чего, однако, в большинстве случаев вполне достаточно).
-U или --update-state
Отмечать в файле `.MYI' факт проверки таблицы и наличие повреждений. Опцию следует использовать для получения максимального эффекта от опции --check-only-changed, однако ее применение недопустимо, если mysqld работает с таблицей и был запущен с опцией --skip-external-locking.
-T или --read-only
Не отмечать таблицу как проверенную. Это может пригодиться, когда myisamchk используется для проверки таблиц, используемых каким-то другим приложением, и это приложение не выполняет блокировку (как mysqld --skip-external-locking).

4.4.6.4 Опции исправления для myisamchk

Следующие опции используются, если myisamchk запускается с -r или -o:

-D # или --data-file-length=# Максимальная длина файла данных (когда файл данных пересоздается при его ``переполнении'').
-e или --extend-check Пробовать исправлять каждую возможную строку из файла данных. Обычно при этом обнаруживается масса замусоренных строк. Использовать эту опцию следует только в самом крайнем случае, когда больше ничего не остается.
-f или --force Писать поверх старых временных файлов (`table_name.TMD') вместо аварийного прекращения.
-k # или keys-used=# Если используется ISAM, то данный параметр предписывает обработчику таблиц ISAM на необходимость обновить только первые # индексов. Если используется MyISAM, то определяет, какие ключи использовать, при этом каждый двоичный бит соответствует одному ключу (первый ключ - это бит 0). Может использоваться для ускорения вставок! Отключенные индексы можно снова активизировать с помощью myisamchk -r. keys.
-l или --no-symlinks Не рассматривать символические ссылки. Обычно myisamchk исправляет таблицы, на которые указывают символические ссылки. Данная опция отсутствует в MySQL 4.0, в связи с тем, что MySQL 4.0 не удаляет символические ссылки во время восстановления.
-r или --recover При указании этой опции можно исправить практически все, кроме уникальных ключей, в которых есть повторения (ошибка, вероятность которой мизерна для таблиц ISAM/MyISAM). Если необходимо восстановить таблицу, то начинать надо с этой опции. Только если myisamchk сообщит, что таблица не может быть восстановлена с помощью -r, тогда следует пытаться применять -o (отметим, что в тех маловероятных случаях, когда -r не срабатывает, файл данных остается неизменным), В случае большого объема памяти следует увеличить размер sort_buffer_size!
-o или --safe-recover
Используется старый метод восстановления (читаются подряд все строки и обновляются все деревья индексов на основе найденных строк); такой алгоритм работает на порядок медленнее -r, но метод справляется с несколькими редкими случаями, непосильными для -r. При этом методе восстановления также используется значительно меньше дискового пространства, нежели в случае -r. Обычно всегда следует начинать с исправления посредством -r, и только если результат не будет достигнут, использовать -o. Для систем с большим объемом памяти следует увеличить размер key_buffer_size!
-n или --sort-recover
Заставляет myisamchk использовать сортировку при разрешении ключей, даже если это потребует временных файлов очень большого размера.
--character-sets-dir=...
Каталог, где хранятся кодировки.
--set-character-set=name
Изменить используемую для индекса кодировку
-t или --tmpdir=path
Путь для хранения временных файлов. Если не задан, myisamchk использует для пути переменную окружения TMPDIR. Начиная с MySQL 4.1, в TMPDIR могут быть указаны несколько путей, разделенных двоеточием : (точкой с запятой на Windows ;). Эти пути будут использованы в ротации. Это используется для того, чтобы распределить данные между разными физическими дисками.
-q или --quick
Быстрый ремонт без изменения файла данных. Можно добавить вторую -q, чтобы дать myisamchk санкцию на изменение исходного файла данных в случае дублирования ключей
-u или --unpack
Распаковать файл, упакованный в myisampack.

4.4.6.5 Другие опции для myisamchk

Кроме ремонта и проверки таблиц, myisamchk может выполнять другие операции:

-a или --analyze
Анализировать распределение ключей. Улучшает эффективность операции связывания за счет включения оптимизатора связей. Он обеспечивает лучший порядок связывания таблиц и определяет, какие ключи при этом следует использовать: myisamchk --describe --verbose table_name или посредством SHOW KEYS в MySQL.
-d или --description
Отображает некоторую информацию о таблице.
-A или --set-auto-increment[=value]
Предписывает, чтобы отсчет значений AUTO_INCREMENT начинался с value или большего значения. Если значение не указано, то в качестве следующего значения AUTO_INCREMENT берется наибольшее использованное значение для автоинкрементного ключа + 1.
-S или --sort-index
Сортировать блоки индексного дерева в порядке от больших к меньшим (high-low). Этим оптимизируются операции поиска и повышается скорость сканирования по ключу.
-R или --sort-records=#
Сортирует записи в соответствии с индексом. Это значительно повышает локализацию данных и может ускорить операции SELECT и ORDER BY, которые выполняются по индексу и выбирают данные по какому-либо интервалу. (Возможно, что первая сортировка будет выполняться очень медленно!) Чтобы узнать номера индексов таблицы, нужно использовать команду SHOW INDEX, показывающую индексы таблицы в том же порядке, в каком их видит myisamchk. Индексы нумеруются начиная с 1.

4.4.6.6 Использование памяти утилитой myisamchk

При работе myisamchk очень важно распределение памяти. Объем используемой myisamchk памяти не превышает количества, указанного с помощью опций -O. Когда речь идет о применении myisamchk на очень больших файлах, следует сначала принять решение о том, какое количество памяти будет при этом использоваться. По умолчанию для целей исправления ошибок отводится только около 3Mб. Применяя большие величины, можно достичь большей скорости работы myisamchk. К примеру, если имеется более 32Mб оперативной памяти, то можно задать следующие опции (в дополнение к любым другим указанным опциям):

shell> myisamchk -O sort=16M -O key=16M -O read=1M -O write=1M ...

В большинстве случаев достаточно использовать -O sort=16M.

Важно понимать, что myisamchk использует временные файлы, для указания на которые служит TMPDIR. Если TMPDIR указывает на файловую систему с размещением в памяти, то велика вероятность ошибок нехватки памяти (out of memory). Если такое произойдет, то в TMPDIR следует поместить имя некоторого другого каталога с большим пространством и перезапустить myisamchk.

При выполнении ремонта myisamchk также понадобится большое количество дискового пространства; :

  • Потребуется пространство порядка удвоенного размера файла - для оригинала и копии файла данных. В этом пространстве нет необходимости, когда исправление выполняется с --quick, поскольку в этом случае повторно создается только индексный файл. Дополнительное место необходимо на том же диске, где находится оригинальный файл записи!
  • Необходимо место для нового индексного файла, заменяющего старый. В начальной фазе выполнения старый индексный файл усекается, поэтому обычно данный объем можно не учитывать. Место должно обеспечиваться на диске, содержащем оригинальный индексный файл!
  • При указании --recover или --sort-recover (но не в случае использования --safe-recover) потребуется место для буфера сортировки: (largest_key + row_pointer_length)*number_of_rows * 2. Можно узнать длину ключей и row_pointer_length с помощью myisamchk -dv table. Это пространство выделяется на временном диске (который определяется при помощи TMPDIR либо --tmpdir=#).

Если возникнут проблемы в связи с нехваткой дискового пространства во время исправления, можно попробовать использовать --safe-recover вместо --recover.

4.4.6.7 Использование myisamchk для послеаварийного восстановления

При выполнении mysqld со --skip-external-locking (установка по умолчанию в некоторых системах, подобных Linux) применение myisamchk для проверки таблицы, когда она используется mysqld, не совсем безопасно. Если есть уверенность, что никто не обратится к таблицам через mysqld во время выполнения myisamchk, то достаточно до начала проверки таблиц выполнить mysqladmin flush-tables, если нет - то на время проверки таблиц необходимо приостановить mysqld. При запуске myisamchk в то время, когда mysqld обновляет таблицы, может быть выдано предупреждение о повреждении таблицы - даже в случае, если этого не произошло.

Если --skip-external-locking не используется, то проверять таблицы с помощью myisamchk можно в любое время. Во время проверки все пытающиеся обновить таблицу клиенты получат возможность сделать это, только дождавшись готовности myisamchk.

Если myisamchk применяется для ремонта или оптимизации таблиц, то всегда необходимо обеспечить отсутствие обращений сервера mysqld к таблице (это также относится к случаю использования --skip-external-locking). Если mysqld не может быть приостановлен, то до myisamchk, как минимум, надо выполнить mysqladmin flush-tables. Таблицы могут быть повреждены, если сервер и myisamchk обратятся к таблицам одновременно.

В данном разделе описывается, как выявлять повреждения данных в базах данных MySQL и что делать с повреждениями дальше. Если таблица повреждается часто, то надо постараться отыскать причину этих повреждений! Обращайтесь к разделу See section A.4.1 Что делать, если работа MySQL сопровождается постоянными сбоями.

Причины повреждения таблиц рассматриваются также в разделе по таблицам MyISAM. Обращайтесь к разделу See section 7.1.3 Проблемы с таблицами MyISAM..

При выполнении послеаварийного восстановления важно понимать, что каждой таблице tbl_name в базе данных соответствуют три файла в каталоге базы данных:

Файл | Назначение
`tbl_name.frm' | Файл определения таблицы (формы)
`tbl_name.MYD' | Файл данных
`tbl_name.MYI' | Индексный файл

Каждый из этих трех типов файлов ``имеет'' свои виды повреждений, но наиболее часто проблемы возникают с файлами данных и индексными файлами.

Во время своей работы myisamchk построчно создает копию файла (данных) `.MYD'. Стадия исправления завершается тем, что программа удаляет старый файл `.MYD' и переименовывает новый путем присвоения ему имени исходного. Если используется --quick, myisamchk не создает временного файла `.MYD', а, исходя из предположения, что файл `.MYD' правилен, только формирует новый индексный файл, никак не меняя файл `.MYD'. Это безопасно, поскольку myisamchk автоматически распознает, что файл `.MYD' запорчен, и в этом случае прерывает исправление. Можно также задавать для myisamchk две опции --quick. В этом случае myisamchk не прерывается аварийно по некоторым ошибкам (таким как дублирование ключа), а пытается исправить их путем модификации файла `.MYD'. Обычно использование двух опций --quick имеет смысл только в случае, если свободного места на диске недостаточно для выполнения нормального исправления. Тогда перед запуском myisamchk следует по крайней мере выполнить резервное копирование.

4.4.6.8 Как проверять таблицы на ошибки

Для проверки таблицы MyISAM используются следующие команды:

myisamchk tbl_name
Находит 99,99% всех ошибок. Не в состоянии отыскать повреждений, затрагивающих только файл данных (которые весьма необычны). Если необходимо только проверить таблицу, то обычно следует выполнить myisamchk без опций либо с одной из опций -s или --silent.
myisamchk -m tbl_name
Находит 99,999% всех ошибок. Сначала на ошибки проверяются все индексные элементы, а затем читаются все строки подряд. Программа вычисляет контрольную сумму для всех ключей в строке и проверяет, совпадает ли она с контрольной суммой в индексном дереве.
myisamchk -e tbl_name
В этом случае выполняется полная и тщательная проверка всех данных (-e означает ``расширенная проверка''). Происходит тестовое чтение каждого ключа для каждой строки с целью контроля того, что ключи указывают на нужные строки. Для большой таблицы с множеством ключей на это может потребоваться много времени. myisamchk обычно останавливается после обнаружения первой ошибки, но если желательно получить более подробную информацию, можно добавить опцию --verbose (-v) - таким образом выполнение myisamchk будет продолжаться вплоть до максимума в 20 ошибок. При нормальной работе достаточно просто запустить myisamchk (без аргументов за исключением имени таблицы).
myisamchk -e -i tbl_name
Аналогична предыдущей команде, но опция -i указывает myisamchk дополнительно отображать некоторую статистическую информацию.

4.4.6.9 Как ремонтировать таблицы

В данном разделе рассматривается только использование myisamchk на таблицах MyISAM (расширения `.MYI' и `.MYD'). Если же в системе применяются таблицы ISAM (расширения `.ISM' и `.ISD'), то следует пользоваться isamchk.

Начиная с версии MySQL 3.23.14 можно ремонтировать таблицы MyISAM при помощи команды REPAIR TABLE (see section 4.4.5 Синтаксис REPAIR TABLE).

К симптомам повреждения таблицы относятся неожиданные прерывания выполнения запросов и появление следующих ошибок:

  • `tbl_name.frm' is locked against change (Файл заблокирован для изменений)
  • Can't find file `tbl_name.MYI' (Errcode: ###) (Не могу найти файл `tbl_name.MYI' (Ошибка: ###))
  • Unexpected end of file (Неожиданно наступил конец)
  • Record file is crashed (Файл записей испорчен)
  • Got error ### from table handler (Получена ошибка ### от дескриптора таблицы). Для получения более подробной информации об ошибке можно выполнить perror ###. Чаще всего о проблемах с таблицей свидетельствуют следующие ошибки:
    shell> perror 126 127 132 134 135 136 141 144 145
126 = Index file is crashed / Wrong file format
127 = Record-file is crashed
132 = Old database file
134 = Record was already deleted (or record file crashed)
135 = No more room in record file
136 = No more room in index file
141 = Duplicate unique key or constraint on write or update
144 = Table is crashed and last repair failed
145 = Table was marked as crashed and should be repaired
    Заметим, что ошибка 135 - 'no more room in record file' ('не осталось места в файле записей'), не может быть исправлена просто выполнением ремонта. В этом случае необходимо использовать следующую команду:
    ALTER TABLE table MAX_ROWS=xxx AVG_ROW_LENGTH=yyy;

В других случаях следует выполнять ремонт таблиц. myisamchk обычно может обнаружить и исправить большинство неполадок.

Процесс ремонтирования включает до четырех описанных здесь стадий. Перед тем как приступить к ремонту, необходимо выполнить `cd' в каталог базы данных и проверить права доступа к табличным файлам. Файлы должны быть доступны для чтения Unix-пользователю, от имени которого выполняется mysqld, (а также выполняющему ремонт, поскольку ему приходится обращаться к проверяемым файлам). Если появится необходимость изменять файлы, то проверяющий также должен иметь доступ для записи.

Если используется версия MySQL 3.23.16 и выше, то для проверки и ремонта таблиц MyISAM можно (и нужно) использовать команды CHECK и REPAIR (section 4.4.4 Синтаксис CHECK TABLE и see section 4.4.5 Синтаксис REPAIR TABLE).

Раздел руководства, посвященный сопровождению таблиц, содержит опции к isamchk/myisamchk (see section 4.4.6 Использование myisamchk для профилактики таблиц и послеаварийного).

Случаи, когда упомянутые команды не дают результата или желательно использовать расширенные возможности, представленные в isamchk/myisamchk, рассматриваются в следующем разделе.

Если ремонт таблицы планируется выполнять из командной строки то сначала требуется остановить сервер. Следует отметить, что при выполнении mysqladmin shutdown с удаленного сервера mysqld все еще будет некоторое время работать после завершения mysqladmin, пока не будут остановлены все запросы и сброшены на диск все ключи.

Стадия 1: проверка таблиц

Выполните myisamchk *.MYI или, если вы располагаете временем, myisamchk -e *.MYI. Используйте опцию -s (молчаливый режим) для подавления ненужной информации.

Если mysqld остановлен, то следует использовать опцию --update-state для указания myisamchk отмечать таблицы как 'проверенные'(checked).

Ремонтировать следует только те таблицы, для которых myisamchk выдала ошибки. Для таких таблиц следует перейти к стадии 2.

Если во время проверки будут получены странные ошибки (подобные out of memory), или myisamchk завершится аварийно, то перейдите к стадии 3.

Стадия 2: легкий безопасный ремонт

Примечание: если есть желание ускорить ремонт, рекомендуется добавить: -O sort_buffer=# -O key_buffer=# (где # примерно 1/4 от имеющейся памяти) во всех командах isamchk/myisamchk.

Сначала надо попробовать запустить myisamchk -r -q tbl_name (-r -q означает "режим быстрого восстановления"). При этом будет сделана попытка исправить индексный файл без изменения файла данных. Если в файле данных содержится все необходимое, а удаленные связи указывают на правильные позиции в файле данных, то команда должна дать результат и таблица будет исправлена. Перейдите к ремонту следующей таблицы. В противном случае следует выполнить следующие действия:

  1. Сделать резервную копию файла данных.
  2. Использовать myisamchk -r tbl_name (-r означает "режим восстановления"). При этом из файла данных будут удалены некорректные и уничтоженные записи, и будет заново создан индексный файл.
  3. Если на предыдущем шаге проблему решить не удастся, то используйте myisamchk --safe-recover tbl_name. В режиме безопасного восстановления используется старый метод восстановления, справляющийся с некоторыми случаями, которые оказываются не под силу для режима обычного исправления (но работает этот метод медленнее).

Если во время проверки будут получены странные ошибки (подобные out of memory) или myisamchk аварийно завершается, то перейдите к стадии 3.

Стадия 3: сложный ремонт

До этой стадии дело доходит, только если первый 16-килобайтный блок в индексном файле разрушен или содержит неверную информацию, либо когда индексный файл отсутствует. В этом случае необходимо создать новый индексный файл. Необходимо выполнить следующие действия:

  1. Переместить файл данных в какое-нибудь безопасное место.
  2. Использовать файл описания таблицы для создания новых (пустых) файлов - данных и индексного:
    shell> mysql db_name
mysql> SET AUTOCOMMIT=1;
mysql> TRUNCATE TABLE table_name;
mysql> quit
    Если используемая версия SQL не располагает TRUNCATE TABLE, то взамен используется DELETE FROM table_name.
  3. Скопируйте старый файл данных на место недавно созданного (делать перемещение старого файла обратно на место нового нецелесообразно, поскольку в старом файле может снова возникнуть потребность, если что-то пойдет не так).

Вернитесь к стадии 2. myisamchk -r -q теперь должна сработать (но бесконечно повторять стадии не следует).

Что касается MySQL 4.0.2, то тут можно воспользоваться REPAIR ... USE_FRM, выполняющей всю эту процедуру автоматически.

Стадия 4: очень сложный ремонт

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

  1. Восстановите файл описания из резервной копии и перейдите к стадии 3. Можно также восстановить индексный файл и вернуться к стадии 2. Во втором случае начинать надо с myisamchk -r.
  2. Если резервной копии нет, но точно известно, как таблица создавалась, то создается копия таблицы в другой базе данных. Новый файл данных удаляется, затем файл описания с индексным файлом перемещаются из другой базы данных в поврежденную. Таким образом вы получаете новый файл описания и индексный файл, не затрагивая при этом файла данных. Делается возврат к стадии 2 с попыткой воссоздать индексный файл.

4.4.6.10 Оптимизация таблиц

Чтобы объединить фрагментированные записи и избавиться от потерь пространства, происходящих из-за удаления и обновления записей, нужно запустить myisamchk в режиме восстановления:

shell> myisamchk -r tbl_name

Такую же оптимизацию таблицы можно произвести, используя команду SQL OPTIMIZE TABLE. OPTIMIZE TABLE выполняет ремонт таблицы и анализ ключей, а также сортирует дерево индексов для ускорения поиска ключей. Вдобавок сводится на нет нежелательное взаимодействие между утилитой и сервером, поскольку при использовании OPTIMIZE TABLE работу выполняет сам сервер. Обращайтесь к разделу See section 4.5.1 Синтаксис команды OPTIMIZE TABLE.

myisamchk также располагает рядом других опций, которые можно использовать для повышения производительности таблицы:

  • -S, --sort-index
  • -R index_num, --sort-records=index_num
  • -a, --analyze

Полное описание опций можно найти в разделе See section 4.4.6.1 Синтаксис запуска myisamchk.

4.4.7 Настройка режима профилактики таблиц

Начиная с версии MySQL 3.23.13 можно проверять таблицы типа MyISAM с помощью команды CHECK TABLE (see section 4.4.4 Синтаксис CHECK TABLE). Для ремонта таблиц можно использовать команду REPAIR TABLE (see section 4.4.5 Синтаксис REPAIR TABLE).

Целесообразно выполнять регулярные проверки таблиц, не дожидаясь появления проблем. В целях профилактики для проверки таблиц можно использовать myisamchk -s. Опция -s (сокращение для --silent) задает выполнение myisamchk в молчаливом режиме с выдачей сообщений только при возникновении ошибок.

Не стоит сбрасывать со счетов и выполнение проверки таблиц при запуске сервера. Например, всякий раз, когда во время обновления происходит перезагрузка, необходима проверка всех таблиц, которые могли при этом пострадать (назовем их "потенциально поврежденными таблицами"). В safe_mysqld можно добавить тест, запускающий myisamchk для проверки всех таблиц, измененных за последние 24 часа, в случае, если после перезагрузки остался старый файл `.pid' (ID процесса) (mysqld создает `.pid'-файл во время запуска и удаляет его при нормальном завершении; наличие `.pid'-файла во время запуска системы свидетельствует о том, что mysqld не завершился нормально).

Можно сделать даже более надежный тест - выполнить проверку таблиц с более поздней, чем у `.pid'-файла, датой последней модификации.

Таблицы также следует регулярно проверять в ходе нормального функционирования системы. У себя в MySQL AB мы запускаем задачи по cron для проверки всех наших важных таблиц раз в неделю, используя следующую строку в файле crontab:

35 0 * * 0 /path/to/myisamchk --fast --silent /path/to/datadir/*/*.MYI

Такая команда отображает информацию о поврежденных таблицах, и мы при надобности можем их исследовать и исправить.

Поскольку за последние пару лет у нас (на самом деле) не было неожиданно поврежденных таблиц (таблиц, получивших повреждение по причинам, отличным от неисправностей оборудования), то для нас проверки один раз в неделю более чем достаточно.

Мы рекомендуем для начала выполнять myisamchk -s еженощно на всех таблицах, обновленных на протяжении последних 24 часов, пока вы не станете доверять MySQL настолько, насколько доверяем мы.

Обычно в таком контроле над таблицами MySQL необходимости нет. При изменении таблиц с динамическим размером строк (таблиц со столбцами типов VARCHAR, BLOB или TEXT) или при наличии таблиц с большим числом удаленных строк может потребоваться время от времени (где-то раз в месяц) дефрагментировать таблицы.

Это можно сделать, используя OPTIMIZE TABLE на аналогичных таблицах, или, если есть возможность приостановить mysqld, выполняя:

isamchk -r --silent --sort-index -O sort_buffer_size=16M */*.ISM
myisamchk -r --silent --sort-index -O sort_buffer_size=16M */*.MYI

4.4.8 Получение информации о таблице

Команды, представленные в этом разделе, используются для получения описания таблицы или статистики по таблице. Более подробное выборочное разъяснение вывода этих команд будет приведено ниже:

  • myisamchk -d tbl_name Выполняет myisamchk в "описательном режиме" для вывода описания таблицы. Если MySQL использует опцию --skip-external-locking, то myisamchk может сообщить об ошибке для таблицы, обновляемой во время исполнения утилиты. Однако поскольку myisamchk не меняет таблицы в описательном режиме, то никакого риска разрушения данных нет.
  • myisamchk -d -v tbl_name Для выдачи дополнительной информации по действиям, выполняемым утилитой myisamchk, добавляется -v для указания расширенного режима вывода сообщений.
  • myisamchk -eis tbl_name Отображается только наиболее важная информация из таблицы. Работает медленно вследствие того, что приходится считывать всю таблицу.
  • myisamchk -eiv tbl_name То же, что и -eis, но с сообщением о выполняемых действиях.

Пример вывода myisamchk -d:

MyISAM 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:

MyISAM file:         company
Record format:       Fixed length
File-version:        1
Creation time:       1999-10-30 12:12:51
Recover time:        1999-10-31 19:13:01
Status:              checked
Data records:           1403698  Deleted blocks:              0
Datafile parts:         1403698  Deleted data:                0
Datafilepointer (bytes):      3  Keyfile pointer (bytes):     3
Max datafile length: 3791650815  Max keyfile length: 4294967294
Recordlength:               226

table description:
Key Start Len Index   Type                  Rec/key     Root Blocksize
1   2     8   unique  double                      1 15845376      1024
2   15    10  multip. text packed stripped        2 25062400      1024
3   219   8   multip. double                     73 40907776      1024
4   63    10  multip. text packed stripped        5 48097280      1024
5   167   2   multip. unsigned short           4840 55200768      1024
6   177   4   multip. unsigned long            1346 65145856      1024
7   155   4   multip. text                     4995 75090944      1024
8   138   4   multip. unsigned long              87 85036032      1024
9   177   4   multip. unsigned long             178 96481280      1024
    193   1           text

Пример вывода myisamchk -eis:

Checking MyISAM 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 MyISAM file: company
Data records: 1403698   Deleted blocks:       0
- check file-size
- check delete-chain
block_size 1024:
index  1:
index  2:
index  3:
index  4:
index  5:
index  6:
index  7:
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
[кое-что опущено для краткости]

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

Для использованной в предыдущих примерах таблицы размеры файла данных и индексного файла были следующими:

-rw-rw-r-- 1 monty tcx 317235748 Jan 12 17:30 company.MYD
-rw-rw-r-- 1 davida tcx 96482304 Jan 12 18:35 company.MYM

Ниже приводятся пояснения по различным типам выдаваемой myisamchk информации. ``keyfile'' означает индексный файл. ``Record'' (запись) и ``row'' (строка) являются синонимами:

  • ISAM file - Имя (индексного) файла ISAM.
  • Isam-version - Версия формата ISAM. На данный момент всегда 2.
  • Creation time - Время создания файла данных.
  • Recover time - Дата последнего восстановления индексного файла/файла данных.
  • Data records - Количество записей в таблице.
  • Deleted blocks - Количество удаленных блоков, пространство для которых все еще зарезервировано. Таблицу можно оптимизировать для сведения к минимуму этого пространства (see section 4.4.6.10 Оптимизация таблиц).
  • Datafile parts - Для динамического формата записей показывает количество блоков данных. Для оптимизированной таблицы без фрагментированных записей совпадает с Data records.
  • Deleted data - Количество байтов удаленных данных, которые не были затребованы. Можно оптимизировать таблицу, чтобы сделать этот объем минимальным (see section 4.4.6.10 Оптимизация таблиц).
  • Data file pointer - Размер указателя в файле данных (в байтах). Обычно это 2, 3, 4 или 5 байтов. Для большинства таблиц достаточно 2 байтов, но назначение размера пока невозможно контролировать из MySQL. Для фиксированных таблиц указатель - это адрес записи, а для динамических - адрес байта.
  • Keyfile pointer - Размер указателя индексного файла в байтах. Обычно составляет 1, 2 или 3 байта. Для большинства таблиц хватает 2 байтов, но размер автоматически вычисляется MySQL. Указатель всегда является адресом блока.
  • Max datafile length - Максимальный размер файла данных таблицы (`.MYD'-файл) в байтах.
  • Max keyfile length - Максимальный размер индексного файла таблицы (`.MYI-файла') в байтах.
  • Recordlength - Размер отдельной записи в байтах.
  • Record format - Формат, используемый для хранения строк таблицы. В примерах, приведенных выше, использовался формат Fixed length. Другие возможные значения: Compressed и Packed.
  • table description - Список всех ключей в таблице. Для каждого ключа представляется некоторая низкоуровневая информация:
    • Key Номер данного ключа.
    • Start Место в записи, где начинается данная часть индекса.
    • Len Длина данной части индекса. Для упакованных чисел длина всегда должна равняться полной длине для столбца. Для строк длина может быть меньше полной длины индексированной колонки, поскольку допускается индексирование префикса столбца со значениями строками.
    • Индекс unique или multip. (multiple - повторяющийся/многократный) Показывает, может ли одно значение встречаться в индексе многократно.
    • Type Тип данных данной части индекса. Это тип данных ISAM с возможными вариантами - packed, stripped и empty.
    • Root Адрес корневого индексного блока.
    • Blocksize Размер каждого индексного блока. По умолчанию равен 1024, но значение можно изменить во время компиляции.
    • Rec/key Статистическое значение, используемое оптимизатором. Оно показывает, сколько записей приходится на одно значение для данного ключа. Для уникального ключа это соотношение всегда 1. Значение может быть обновлено после загрузки таблицы (или значительного ее изменения) посредством myisamchk -a. Если соотношение совсем не обновляется, то по умолчанию принимается значение 30.
  • В первом из приведенных примеров 9-й ключ является составным с двумя частями.
  • Keyblocks used - Процент использованных блоков ключей. Поскольку для примера была взята таблица, совсем недавно реорганизованная при помощи myisamchk, то значения очень высоки (очень близки к теоретическому максимуму).
  • Packed - MySQL пытается упаковывать ключи с общим суффиксом. Это может быть использовано только для ключей типа CHAR/VARCHAR/DECIMAL. Для длинных строк, таких как имена, при помощи упаковки можно значительно уменьшить занимаемое ими место. В третьем из приведенных примеров 4-й ключ состоит из 10 символов и для него достигнуто 60%-е уменьшение в объеме.
  • Max levels - Глубина B-дерева для данного ключа. В больших таблицах с длинными ключами значение является большим.
  • Records Количество строк в таблице.
  • M.recordlength - Средняя длина записи. Для таблиц с фиксированной длиной записи равняется точной длине записи.
  • Packed - MySQL отбрасывает пробелы в конце строк. Значение Packed указывает на процент достигнутой этим экономии.
  • Recordspace used - Процент использования файла данных.
  • Empty space - На сколько процентов файл данных не использован.
  • Blocks/Record - Среднее число блоков на запись (т.е. из какого числа связей состоит фрагментированная запись). Отношение всегда 1,0 для таблиц фиксированного формата. Важно, чтобы это значение было как можно ближе к 1,0. Если значение становится слишком большим, можно реорганизовать таблицу с помощью myisamchk. Обращайтесь к разделу See section 4.4.6.10 Оптимизация таблиц.
  • Recordblocks - Количество использованных блоков (связей). Для фиксированного формата совпадает с количеством записей.
  • Deleteblocks - Количество удаленных блоков (связей).
  • Recorddata - Количество использованных байтов в файле данных.
  • Deleted data - Количество удаленных (неиспользуемых) байтов в файле данных.
  • Lost space - Если запись при обновлении уменьшается, то теряется некоторое пространство. Данное значение является суммой всех таких потерь в байтах.
  • Linkdata - При использовании динамического формата таблиц фрагменты записи связываются с помощью указателей (каждый от 4 до 7 байтов). Linkdata - общий объем памяти, занимаемый всеми такими указателями.

Если таблица была сжата при помощи myisampack, то myisamchk -d выдает дополнительную информацию о каждом столбце в таблице. Обращайтесь к разделу See section 4.7.4 myisampack, MySQL-генератор сжатых таблиц (только для чтения), где приведен пример такой информации и пояснение к ней.

4.5 Справочник по языку администрирования баз данных

4.5.1 Синтаксис команды OPTIMIZE TABLE

OPTIMIZE TABLE tbl_name[,tbl_name]...

Команда OPTIMIZE TABLE должна использоваться после удаления большей части таблицы или если в таблице было внесено много изменений в строки переменной длины (таблицы, в которых есть столбцы VARCHAR, BLOB или TEXT). Удаленные записи поддерживаются при помощи связного списка, и последующие операции INSERT повторно используют позиции старых записей. Чтобы перераспределить неиспользуемое пространство и дефрагментировать файл данных, можно воспользоваться командой OPTIMIZE TABLE.

На данный момент команда OPTIMIZE TABLE работает только с таблицами MyISAM и BDB. Для таблиц BDB команда OPTIMIZE TABLE выполняет ANALYZE TABLE. См. раздел See section 4.5.2 Синтаксис команды ANALYZE TABLE.

Можно применить OPTIMIZE TABLE к таблицам других типов, запустив mysqld с параметром --skip-new или --safe-mode, но в этом случае OPTIMIZE TABLE лишь только выполняет ALTER TABLE.

Команда OPTIMIZE TABLE работает следующим образом:

  • Если в таблице есть удаленные или разделенные строки, восстанавливает таблицу.
  • Если индексные страницы не отсортированы - сортирует их.
  • Если статистические данные не обновлены (и восстановление нельзя осуществить путем сортировки индексов), обновляет их.

Команда OPTIMIZE TABLE для MyISAM представляет собой эквивалент выполнения myisamchk --quick --check-only-changed --sort-index --analyze над таблицей.

Обратите внимание: во время работы OPTIMIZE TABLE таблица заблокирована!

4.5.2 Синтаксис команды ANALYZE TABLE

ANALYZE TABLE tbl_name[,tbl_name...]

Анализирует и сохраняет распределение ключей для таблицы. Во время проведения анализа таблица заблокирована для чтения. Эта функция работает для таблиц MyISAM и BDB.

Данная команда является эквивалентом выполнения myisamchk -a для таблицы.

Сохраненное распределение ключей в MySQL используется для принятия решения о том, в каком порядке следует связывать таблицы, когда для связывания используются не константы, а другая база.

Эта команда выдает таблицу со следующими столбцами:

Столбец | Значение
Table | Имя таблицы
Op | Всегда ``analyze''
Msg_type | Одно из значений status, error, info или warning.
Msg_text | Сообщение.

Просмотреть сохраненное распределение ключей можно при помощи команды SHOW INDEX. See section 4.5.6.1 Получение информации по базам данных, таблицам, столбцам и индексам.

Если таблица не изменялась с момента предыдущего запуска команды ANALYZE TABLE, повторный анализ таблицы проводиться не будет.

4.5.3 Синтаксис команды FLUSH

FLUSH flush_option [,flush_option] ...

Команда FLUSH применяется для очистки части кэша, используемого MySQL. Для запуска FLUSH необходимо обладать привилегиями RELOAD.

Параметр flush_option может быть одним из следующих:

Параметр | Описание
HOSTS | Производится очистка таблиц кэша удаленных компьютеров. Сброс таблиц удаленного компьютера следует производить, если один из удаленных компьютеров изменил IP-адрес или если было получено сообщение об ошибке Host ... is blocked. Если во время соединения с сервером MySQL происходит больше ошибок подряд, чем указано в max_connect_errors для определенного удаленного компьютера, то MySQL предполагает, что что-то не в порядке, и блокирует последующие попытки установления соединения со стороны этого удаленного компьютера. Сброс таблиц удаленного компьютера позволяет снова попытаться установить соединение. See section A.2.4 Ошибка Host '...' is blocked. Чтобы это сообщение об ошибке не появлялось, запустите mysqld с параметром -O max_connect_errors=999999999.
DES_KEY_FILE | Производится перезагрузка ключей DES из файла, указанного параметром --des-key-file, при запуске сервера.
LOGS | Закрываются и повторно открывается все файлы журналов. Если файл журнала обновлений или файл бинарного журнала был указан без расширения, номер расширения файла журнала будет увеличен на единицу относительно предыдущего файла. Если в имени файла было указано расширение, MySQL закроет и повторно откроет файл журнала обновлений. See section 4.9.3 Журнал обновлений (update). Эти действия аналогичны отправке сигнала SIGHUP на сервер mysqld.
PRIVILEGES | Производится перезагрузка привилегий из таблиц привилегий в базе данных mysql.
QUERY CACHE | Производится дефрагментация кэша запросов, чтобы эффективнее использовать его память. Эта команда не удаляет запросы из кэша, как команда RESET QUERY CACHE.
TABLES | Закрываются все открытые таблицы и принудительно закрываются все используемые таблицы. Также сбрасывается кэш запросов.
[TABLE | TABLES] tbl_name [,tbl_name...] | Производится сброс только указанных таблиц.
TABLES WITH READ LOCK | Закрываются все открытые таблицы и блокируется доступ для чтения всех таблиц для всех баз данных, пока не будет запущена команда UNLOCK TABLES. Это очень удобный способ создавать резервные копии, если у вас файловая система наподобие Veritas, которая может обеспечить моментальные снимки данных в режиме реального времени.
STATUS | Большинство переменных состояния сбрасываются в нуль. Эту команду необходимо использовать при отладке запроса.
USER_RESOURCES | Все ресурсы пользователя сбрасываются в нулевое значение. Это позволяет заблокированному пользователю подсоединиться еще раз. See section 4.3.6 Ограничение ресурсов пользователя.

Ко всем приведенным выше командам можно получить доступ при помощи утилиты mysqladmin, используя команды flush-hosts, flush-logs, reload или flush-tables.

Рекомендуется также ознакомиться с командой RESET, которая применяется с репликацией. See section 4.5.4 Синтаксис команды RESET.

4.5.4 Синтаксис команды RESET

RESET reset_option [,reset_option] ...

Команда RESET используется для очистки. Кроме того, она также действует как более сильная версия команды FLUSH. See section 4.5.3 Синтаксис команды FLUSH.

Чтобы запустить команду RESET, необходимо обладать привилегиями RELOAD.

Параметр | Описание
MASTER | Удаляет все бинарные журналы, перечисленные в индексном файле, обнуляет значения индексного файла binlog. В версиях до 3.23.26 - FLUSH MASTER (Master)
SLAVE | Сбрасывает положение репликации подчиненного компьютера в журналах головного компьютера. В версиях до 3.23.26 эта команда называлась FLUSH SLAVE (Slave)
QUERY CACHE | Удаляет все результаты запросов из кэша запросов.

4.5.5 Синтаксис команды KILL

KILL thread_id

Каждое соединение с mysqld запускается в отдельном потоке. При помощи команды SHOW PROCESSLIST можно просмотреть список запущенных потоков, а при помощи команды KILL thread_id - удалить поток.

Если у вас есть привилегия PROCESS, можно просмотреть все потоки. Обладая привилегией SUPER, можно удалять любые потоки. В противном случае можно просматривать и удалять только свои собственные потоки.

Для просмотра и удаления потоков можно также применять команды mysqladmin processlist и mysqladmin kill.

При использовании команды KILL для потока устанавливается специальный флаг kill flag.

В большинстве случаев удаление потока занимает некоторое время, поскольку этот флаг проверяется с определенным интервалом.

  • В циклах SELECT, ORDER BY и GROUP BY флаг проверяется только после считывания блока строк. Если установлен флаг удаления, то выполнение оператора будет отменено.
  • При выполнении команды ALTER TABLE флаг удаления проверяется перед считыванием каждого блока строк из исходной таблицы. Если флаг установлен, то выполнение команды отменяется и временная таблица удаляется. При выполнении команд UPDATE и DELETE флаг удаления проверяется после каждого считывания блока, а также после каждого обновления или удаления строки. Если флаг удаления установлен, то выполнение оператора отменяется. Обратите внимание: если не используются транзакции, то отменить изменения будет невозможно!
  • GET_LOCK() будет отменен при помощи NULL.
  • Поток INSERT DELAYED быстро сбросит все строки, которые он содержит в памяти и будет удален.
  • Если поток находится в заблокированной таблице (состояние: Locked), то блокировка таблицы будет быстро отменена.
  • Если поток ожидает освобождения дискового пространства в запросе write, запись будет отменена с выдачей сообщения о переполнении диска.

4.5.6 Синтаксис команды SHOW

SHOW DATABASES [LIKE wild]
или SHOW [OPEN] TABLES [FROM db_name] [LIKE wild]
или SHOW [FULL] COLUMNS FROM tbl_name [FROM db_name] [LIKE wild]
или SHOW INDEX FROM tbl_name [FROM db_name]
или SHOW TABLE STATUS [FROM db_name] [LIKE wild]
или SHOW STATUS [LIKE wild]
или SHOW VARIABLES [LIKE wild]
или SHOW LOGS
или SHOW [FULL] PROCESSLIST
или SHOW GRANTS FOR user
или SHOW CREATE TABLE table_name
или SHOW MASTER STATUS
или SHOW MASTER LOGS
или SHOW SLAVE STATUS
или SHOW WARNINGS [LIMIT #]
или SHOW ERRORS [LIMIT #]
или SHOW TABLE TYPES

Команда SHOW предоставляет информацию по базам данных, таблицам, столбцам или о состоянии сервера. Если используется LIKE wild, то строка wild может содержать в себе шаблонные символы SQL `%' и `_'.

4.5.6.1 Получение информации по базам данных, таблицам, столбцам и индексам

Можно использовать два альтернативных синтаксиса - tbl_name FROM db_name и db_name.tbl_name. Приведенные ниже два оператора эквивалентны:

mysql> SHOW INDEX FROM mytable FROM mydb;
mysql> SHOW INDEX FROM mydb.mytable;

Команда SHOW DATABASES выдает список баз данных на компьютере, где установлен сервер MySQL. Этот список можно также получить, воспользовавшись инструментом командной строки mysqlshow. В версии 4.0.2 можно увидеть только те базы данных, для которых у вас есть какие-либо привилегии, если вы не имеете глобальной привилегии SHOW DATABASES.

Команда SHOW TABLES выводит список таблиц в указанной базе данных. Этот список также можно получить, используя команду mysqlshow db_name.

Примечание: если у пользователя нет никаких привилегий для таблицы, таблица не будет показана в результатах команды SHOW TABLES или mysqlshow db_name.

Команда SHOW OPEN TABLES выводит список таблиц, которые в настоящий момент открыты в кэше таблицы. See section 5.4.7 Открытие и закрытие таблиц в MySQL. В поле Comment указывается, сколько раз таблица кэшировалась (cached) и сколько раз использовалась (in_use).

Команда SHOW COLUMNS выводит список столбцов в заданной таблице. Если указать параметр FULL, то будут показаны также ваши привилегии для каждого столбца. Если типы столбцов отличаются от заданных в параметрах оператора CREATE TABLE, учтите, что MySQL иногда изменяет типы столбцов. See section 6.5.3.1 Молчаливые изменения определений столбцов.

Оператор DESCRIBE предоставляет почти такую же информацию, что и SHOW COLUMNS. See section 6.6.2 Синтаксис команды DESCRIBE (Получение информации о столбцах).

Команда SHOW FIELDS является синонимом команды SHOW COLUMNS, а команда SHOW KEYS - синонимом SHOW INDEX. Список столбцов или индексов таблицы можно также вывести при помощи команды mysqlshow db_name tbl_name или mysqlshow -k db_name tbl_name.

Команда SHOW INDEX выводит информацию по индексу в формате, подобном формату вывода запроса SQLStatistics в ODBC. Выводятся следующие столбцы:

Столбец | Значение
Table | Имя таблицы.
Non_unique | 0 если индекс не может содержать дублирующихся значений.
Key_name | Имя индекса.
Seq_in_index | Порядковый номер столбца в индексе, начиная с 1.
Column_name | Имя столбца.
Collation | Как столбцы отсортированы в индексе. В MySQL в данном столбце могут присутствовать значения 'A' (в порядке возрастания) или NULL (не отсортирован).
Cardinality | Количество уникальных значений в индексе. Обновляется путем запуска isamchk -a.
Sub_part Количество индексированных символов, если столбец индексируется частично. Если проиндексирован весь ключ, то будет содержаться значение NULL.
Null | Содержит значение 'YES', если столбец может содержать NULL.
Index_type Используемый метод индексирования.
Comment | Различные примечания. На данный момент в версиях MySQL < 4.0.2 выдается, является индекс FULLTEXT или нет.

Обратите внимание на то, что значение Cardinality подсчитывается по результатам статистики, сохраняющейся в виде целых чисел, которые недостаточно точны для небольших таблиц.

Столбцы Null и Index_type были добавлены начиная с версии MySQL 4.0.2.

4.5.6.2 SHOW TABLE STATUS

SHOW TABLE STATUS [FROM db_name] [LIKE wild]

Команда SHOW TABLE STATUS (новшество версии 3.23) работает как SHOW STATUS, но предоставляет большое количество информации по каждой таблице. Приведенный ниже список также можно получить, используя команду mysqlshow --status db_name. Выводятся следующие столбцы:

Столбец | Значение
Name | Имя таблицы.
Type | Тип таблицы. See section 7 Типы таблиц MySQL.
Row_format | Формат хранения строк (Fixed, Dynamic, или Compressed).
Rows | Количество строк.
Avg_row_length | Средняя длина строки.
Data_length | Размер файла данных.
Max_data_length | Максимальная длина файла данных.
Index_length | Длина индексного файла.
Data_free | Количество распределенных, но не используемых байтов.
Auto_increment | Следующее значение автоинкремента.
Create_time | Время создания таблицы.
Update_time | Время последнего обновления файла данных.
Check_time | Время последней проверки таблицы.
Create_options | Дополнительные параметры, использовавшиеся для команды CREATE TABLE.
Comment | Примечания, внесенные при создании таблицы (или информация о причинах, почему MySQL не может получить доступ к данным в таблицах).

В таблицах InnoDB информация о свободном дисковом пространстве в таблице заносится в ячейки примечаний к таблице.

4.5.6.3 SHOW STATUS

Команда SHOW STATUS предоставляет информацию по состоянию сервера (как mysqladmin extended-status). Пример выходных данных приведен ниже (формат и числа могут иметь некоторые отличия):

+--------------------------+------------+
| Variable_name            | Value      |
+--------------------------+------------+
| Aborted_clients          | 0          |
| Aborted_connects         | 0          |
| Bytes_received           | 155372598  |
| Bytes_sent               | 1176560426 |
| Connections              | 30023      |
| Created_tmp_disk_tables  | 0          |
| Created_tmp_tables       | 8340       |
| Created_tmp_files        | 60         |
| Delayed_insert_threads   | 0          |
| Delayed_writes           | 0          |
| Delayed_errors           | 0          |
| Flush_commands           | 1          |
| Handler_delete           | 462604     |
| Handler_read_first       | 105881     |
| Handler_read_key         | 27820558   |
| Handler_read_next        | 390681754  |
| Handler_read_prev        | 6022500    |
| Handler_read_rnd         | 30546748   |
| Handler_read_rnd_next    | 246216530  |
| Handler_update           | 16945404   |
| Handler_write            | 60356676   |
| Key_blocks_used          | 14955      |
| Key_read_requests        | 96854827   |
| Key_reads                | 162040     |
| Key_write_requests       | 7589728    |
| Key_writes               | 3813196    |
| Max_used_connections     | 0          |
| Not_flushed_key_blocks   | 0          |
| Not_flushed_delayed_rows | 0          |
| Open_tables              | 1          |
| Open_files               | 2          |
| Open_streams             | 0          |
| Opened_tables            | 44600      |
| Questions                | 2026873    |
| Select_full_join         | 0          |
| Select_full_range_join   | 0          |
| Select_range             | 99646      |
| Select_range_check       | 0          |
| Select_scan              | 30802      |
| Slave_running            | OFF        |
| Slave_open_temp_tables   | 0          |
| Slow_launch_threads      | 0          |
| Slow_queries             | 0          |
| Sort_merge_passes        | 30         |
| Sort_range               | 500        |
| Sort_rows                | 30296250   |
| Sort_scan                | 4650       |
| Table_locks_immediate    | 1920382    |
| Table_locks_waited       | 0          |
| Threads_cached           | 0          |
| Threads_created          | 30022      |
| Threads_connected        | 1          |
| Threads_running          | 1          |
| Uptime                   | 80380      |
+--------------------------+------------+

Приведенные выше переменные состояния имеют следующие значения:

Переменная | Значение
Aborted_clients | Количество соединений, отмененных по причине отключения клиента без надлежащего закрытия соединения. See section A.2.9 Коммуникационные ошибки / Оборванные соединения.
Aborted_connects | Количество неудачных попыток подсоединения к серверу MySQL. See section A.2.9 Коммуникационные ошибки / Оборванные соединения.
Bytes_received | Количество байтов, полученных от всех клиентов.
Bytes_sent | Количество байтов, отправленных всем клиентам.
Com_xxx | Количество запусков каждой команды xxx.
Connections | Количество попыток подсоединения к серверу MySQL.
Created_tmp_tables | Количество неявных временных таблиц на диске, созданных во время выполнения операторов.
Created_tmp_tables | Количество неявных временных таблиц в памяти, созданных во время выполнения операторов.
Created_tmp_files | Количество созданных временных файлов mysqld.
Delayed_insert_threads | Количество используемых потоков вставки данных в режиме insert delayed.
Delayed_writes | Количество строк, вставленных при помощи команды INSERT DELAYED.
Delayed_errors | Количество записанных при помощи команды INSERT DELAYED строк, в которых произошли какие-либо ошибки (возможно, duplicate key).
Flush_commands | Количество запущенных команд FLUSH.
Handler_commit | Количество внутренних команд COMMIT.
Handler_delete | Количество удалений строки из таблицы.
Handler_read_first | Количество считываний из индекса первой записи. Если это значение высокое, то, по всей вероятности, сервер осуществляет много полных индексных сканирований, например, SELECT col1 FROM foo, предполагая, что col1 проиндексирован.
Handler_read_key | Количество запросов на чтение строки, основанных на ключе. Высокое значение переменной говорит о том, что ваши запросы и таблицы проиндексированы надлежащим образом.
Handler_read_next | Количество запросов на чтение следующей строки в порядке расположения ключей. Это значение будет увеличиваться, если производится запрос индексного столбца с ограничением по размеру. Значение также увеличивается во время проведения индексного сканирования.
Handler_read_prev | Количество запросов на чтение предыдущей строки в порядке расположения ключей. В большинстве случаев используется для оптимизации ORDER BY ... DESC.
Handler_read_rnd | Количество запросов на чтение строки, основанных на фиксированной позиции. Значение будет высоким, если выполняется много запросов, требующих сортировки результатов.
Handler_read_rnd_next | Количество запросов на чтение следующей строки из файла данных. Данное значение будет высоким, если производится много сканирований таблиц. Обычно это означает, что ваши таблицы не проиндексированы надлежащим образом или ваши запросы не используют преимущества индексов.
Handler_rollback | Количество внутренних команд ROLLBACK.
Handler_update | Количество запросов на обновление строки в таблице.
Handler_write | Количество запросов на вставку строки в таблицу.
Key_blocks_used | Количество используемых блоков в кэше ключей.
Key_read_requests | Количество запросов на чтение блока ключей из кэша.
Key_reads | Количество физических считываний блока ключей с диска.
Key_write_requests | Количество запросов на запись блока ключей в кэш.
Key_writes | Количество физических записей блоков ключей на диск.
Max_used_connections | Максимальное количество одновременно используемых соединений.
Not_flushed_key_blocks | Блоки ключей в кэше ключей, которые были изменены, но еще не записаны на диск.
Not_flushed_delayed_rows | Количество строк, стоящих в очереди на запись в запросах INSERT DELAY.
Open_tables | Количество открытых таблиц.
Open_files | Количество открытых файлов.
Open_streams | Количество открытых потоков (в основном используется для журналирования).
Opened_tables | Количество открывавшихся таблиц.
Rpl_status | Статус отказобезопасной репликации (еще не используется).
Select_full_join | Количество соединений без ключей (если это значение равно 0, необходимо внимательно проверить индексы своих таблиц).
Select_full_range_join | Количество соединений, где был использован поиск по диапазону в справочной таблице.
Select_range | Количество соединений, в которых использовались диапазоны в первой таблице. (Обычно это значение не критично, даже если оно велико)
Select_scan | Количество соединений, в которых проводилось первое сканирование первой таблицы.
Select_range_check | Количество соединений без ключей, в которых проверка использования ключей производится после каждой строки (если это значение равно 0, необходимо внимательно проверить индексы своих таблиц).
Questions | Количество запросов, направленных на сервер.
Slave_open_temp_tables | Количество временных таблиц, открытых в настоящий момент потоком подчиненного компьютера.
Slave_running | Содержит значение ON, если это подчиненный компьютер, подключенный к головному компьютеру.
Slow_launch_threads | Количество потоков, создание которых заняло больше, чем указано в slow_launch_time.
Slow_queries | Количество запросов, обработка которых заняла больше времени, чем long_query_time. See section 4.9.5 Журнал медленных запросов.
Sort_merge_passes | Количество объединений, осуществленных алгоритмом сортировки. Если это значение велико, следует увеличить sort_buffer_size.
Sort_range | Количество сортировок, которые осуществлялись в диапазонах.
Sort_rows | Количество отсортированных строк.
Sort_scan | Количество сортировок, осуществленных путем сканирования таблицы.
ssl_xxx | Переменные, используемые SSL; еще не реализовано.
Table_locks_immediate | Количество запросов на немедленную блокировку таблицы. Доступно начиная с версии 3.23.33.
Table_locks_waited | Количество запросов, когда немедленная блокировка не могла быть осуществлена и требовалось время на ожидание. Если это значение велико, и у вас есть проблемы с производительностью, сначала необходимо оптимизировать свои запросы, а затем либо разделить таблицы, либо использовать репликацию. Доступно начиная с версии 3.23.33.
Threads_cached | Количество потоков в кэше потоков.
Threads_connected | Количество открытых в настоящий момент соединений.
Threads_created | Количество потоков, созданных для управления соединениями.
Threads_running | Количество не простаивающих потоков.
Uptime | Время в секундах, в течение которого сервер находится в работе.

Некоторые примечания к приведенной выше информации:

  • Если значение Opened_tables велико, возможно, что значение переменной table_cache слишком мало.
  • Если значение Key_reads велико, возможно, что значение переменной key_buffer_size слишком мало. Частоту неуспешных обращений к кэшу можно вычислить так: Key_reads/Key_read_requests.
  • Если значение Handler_read_rnd велико, возможно, поступает слишком много запросов, требующих от MySQL полного сканирования таблиц или у вас есть соединения, которые не используют ключи надлежащим образом.
  • Если значение Threads_created велико, возможно, необходимо увеличить значение переменной thread_cache_size. Частоту успешных обращений к кэшу можно вычислить при помощи Threads_created/Connections.
  • Если значение Created_tmp_disk_tables велико, возможно, необходимо увеличить значение переменной tmp_table_size, чтобы временные таблицы располагались в памяти, а не на жестком диске.

4.5.6.4 SHOW VARIABLES

SHOW [GLOBAL | SESSION] VARIABLES [LIKE wild]

Команда SHOW VARIABLES отображает значения некоторых системных переменных MySQL. Такую же информацию можно получить и при помощи команды mysqladmin variables. Если установленные по умолчанию значения вам не подходят, большинство из этих переменных можно задать, используя параметры командной строки при запуске mysqld. See section 4.1.1 Параметры командной строки mysqld.

Опции GLOBAL и SESSION новы с версии MySQL 4.0.3. С помощью GLOBAL вы получите значения, использующиеся для новых подключений к MySQL. С помощью SESSION вы получите значения, которые действуют прямо сейчас в текущем соединении. Если вы не указываете эти опции, подразумевается SESSION.

Вы можете изменить большинство параметров с помощью команды SET. See section 5.5.6 Синтаксис команды SET.

Ниже приведен пример выходных данных; формат и числа могут иметь некоторые отличия:

+---------------------------------+------------------------------+
| Variable_name                   | Value                        |
+---------------------------------+------------------------------|
| back_log                        | 50                           |
| basedir                         | /usr/local/mysql             |
| bdb_cache_size                  | 8388572                      |
| bdb_log_buffer_size             | 32768                        |
| bdb_home                        | /usr/local/mysql             |
| bdb_max_lock                    | 10000                        |
| bdb_logdir                      |                              |
| bdb_shared_data                 | OFF                          |
| bdb_tmpdir                      | /tmp/                        |
| bdb_version                     | Sleepycat Software: ...	 |
| binlog_cache_size               | 32768                        |
| bulk_insert_buffer_size         | 8388608                      |
| character_set                   | latin1                       |
| character_sets                  | latin1 big5 czech euc_kr	 |
| concurrent_insert               | ON                           |
| connect_timeout                 | 5                            |
| convert_character_set           |                              |
| datadir                         | /usr/local/mysql/data/       |
| delay_key_write                 | ON                           |
| delayed_insert_limit            | 100                          |
| delayed_insert_timeout          | 300                          |
| delayed_queue_size              | 1000                         |
| flush                           | OFF                          |
| flush_time                      | 0                            |
| ft_boolean_syntax               | + -><()~*:""&|               |
| ft_min_word_len                 | 4                            |
| ft_max_word_len                 | 254                          |
| ft_max_word_len_for_sort        | 20                           |
| ft_stopword_file                | (built-in)                   |
| have_bdb                        | YES                          |
| have_innodb                     | YES                          |
| have_isam                       | YES                          |
| have_raid                       | NO                           |
| have_symlink                    | DISABLED                     |
| have_openssl                    | YES                          |
| have_query_cache                | YES                          |
| init_file                       |                              |
| innodb_additional_mem_pool_size | 1048576                      |
| innodb_buffer_pool_size         | 8388608                      |
| innodb_data_file_path           | ibdata1:10M:autoextend       |
| innodb_data_home_dir            |                              |
| innodb_file_io_threads          | 4                            |
| innodb_force_recovery           | 0                            |
| innodb_thread_concurrency       | 8                            |
| innodb_flush_log_at_trx_commit  | 0                            |
| innodb_fast_shutdown            | ON                           |
| innodb_flush_method             |                              |
| innodb_lock_wait_timeout        | 50                           |
| innodb_log_arch_dir             |                              |
| innodb_log_archive              | OFF                          |
| innodb_log_buffer_size          | 1048576                      |
| innodb_log_file_size            | 5242880                      |
| innodb_log_files_in_group       | 2                            |
| innodb_log_group_home_dir       | ./                           |
| innodb_mirrored_log_groups      | 1                            |
| interactive_timeout             | 28800                        |
| join_buffer_size                | 131072                       |
| key_buffer_size                 | 16773120                     |
| language                        | /usr/local/mysql/share/...   |
| large_files_support             | ON                           |
| local_infile                    | ON                           |
| locked_in_memory                | OFF                          |
| log                             | OFF                          |
| log_update                      | OFF                          |
| log_bin                         | OFF                          |
| log_slave_updates               | OFF                          |
| log_slow_queries                | OFF                          |
| log_warnings                    | OFF                          |
| long_query_time                 | 10                           |
| low_priority_updates            | OFF                          |
| lower_case_table_names          | OFF                          |
| max_allowed_packet              | 1047552                      |
| max_binlog_cache_size           | 4294967295                   |
| max_binlog_size                 | 1073741824                   |
| max_connections                 | 100                          |
| max_connect_errors              | 10                           |
| max_delayed_threads             | 20                           |
| max_heap_table_size             | 16777216                     |
| max_join_size                   | 4294967295                   |
| max_sort_length                 | 1024                         |
| max_user_connections            | 0                            |
| max_tmp_tables                  | 32                           |
| max_write_lock_count            | 4294967295                   |
| myisam_max_extra_sort_file_size | 268435456                    |
| myisam_max_sort_file_size       | 2147483647                   |
| myisam_recover_options          | force                        |
| myisam_sort_buffer_size         | 8388608                      |
| net_buffer_length               | 16384                        |
| net_read_timeout                | 30                           |
| net_retry_count                 | 10                           |
| net_write_timeout               | 60                           |
| open_files_limit                | 0                            |
| pid_file                        | /usr/local/mysql/name.pid    |
| port                            | 3306                         |
| protocol_version                | 10                           |
| read_buffer_size                | 131072                       |
| read_rnd_buffer_size            | 262144                       |
| rpl_recovery_rank               | 0                            |
| query_cache_limit               | 1048576                      |
| query_cache_size                | 0                            |
| query_cache_type                | ON                           |
| safe_show_database              | OFF                          |
| server_id                       | 0                            |
| slave_net_timeout               | 3600                         |
| skip_external_locking           | ON                           |
| skip_networking                 | OFF                          |
| skip_show_database              | OFF                          |
| slow_launch_time                | 2                            |
| socket                          | /tmp/mysql.sock              |
| sort_buffer_size                | 2097116                      |
| sql_mode                        | 0                            |
| table_cache                     | 64                           |
| table_type                      | MYISAM                       |
| thread_cache_size               | 3                            |
| thread_stack                    | 131072                       |
| tx_isolation                    | READ-COMMITTED               |
| timezone                        | EEST                         |
| tmp_table_size                  | 33554432                     |
| tmpdir                          | /tmp/:/mnt/hd2/tmp/          |
| version                         | 4.0.4-beta                   |
| wait_timeout                    | 28800                        |
+---------------------------------+------------------------------+

Ниже описаны все параметры. Значения размеров буферов, длины и размеры стеков приведены в байтах. Значения можно указать с суффиксом 'K' или 'M', чтобы обозначить килобайты или мегабайты. Например, 16M означает 16 мегабайт. Регистр буквы суффикса не имеет значения, 16M и 16m обозначают одно и то же:

  • ansi_mode. Имеет значение ON, если mysqld был запущен с параметром --ansi. See section 1.9.2 Запуск MySQL в режиме ANSI.
  • back_log Количество поддерживаемых MySQL запросов на соединение, находящихся в очереди. Этот параметр начинает играть роль, когда главный поток MySQL получает очень много запросов на соединение за короткий промежуток времени. У главного потока уходит некоторое время (хотя очень небольшое) на проверку соединения и запуск нового потока. Значение back_log показывает, сколько запросов может находиться в очереди на этом коротком промежутке времени, прежде чем MySQL прекратит отвечать на новые запросы. Данное значение необходимо увеличить только в том случае, если ожидается большое количество соединений на протяжении короткого промежутка времени. Иначе говоря, это значение является размером очереди ожидания входящих соединений TCP/IP. У вашей операционной системы есть свое собственное ограничение на размер этой очереди. За более подробной информацией обращайтесь на страницу руководства ОС Unix по системному вызову listen(2). Чтобы узнать максимальное значение для этой переменной, обратитесь к документации по своей операционной системе. Попытка установить значение back_log выше, чем допускается в вашей операционной системе, не принесет положительного результата.
  • basedir Значение параметра --basedir.
  • bdb_cache_size Буфер, выделенный для индекса кэша и строк таблиц BDB. Если таблицы BDB не используются, необходимо запустить mysqld с параметром --skip-bdb, чтобы не расходовать память на этот кэш.
  • bdb_log_buffer_size Буфер, выделенный для индекса кэша и строк таблиц BDB. Если таблицы BDB не используются, его значение необходимо установить в 0 или запустить mysqld с параметром --skip-bdb, чтобы не расходовать память на этот кэш.
  • bdb_home Значение параметра --bdb-home.
  • bdb_max_lock Максимальное количество блокировок (по умолчанию 10000), которые можно установить на таблицу BDB. Этот параметр необходимо увеличить, если возникают ошибки типа bdb: Lock table is out of available locks или Got error 12 from ... при выполнении длинных транзакций или когда mysqld должен просмотреть много строк для вычисления запроса.
  • bdb_logdir Значение параметра --bdb-logdir.
  • bdb_shared_data Содержит значение ON, если используется параметр --bdb-shared-data.
  • bdb_tmpdir Значение параметра --bdb-tmpdir.
  • binlog_cache_size. Размер кэша для хранения операторов бинарного журнала SQL во время транзакции. Если часто используются большие транзакции со значительным количеством операторов, то в целях повышения производительности значение этого параметра можно увеличить. See section 6.7.1 Синтаксис команд BEGIN/COMMIT/ROLLBACK.
  • bulk_insert_buffer_size (был myisam_bulk_insert_tree_size) MyISAM использует специальный древо-подобный кэш чтобы ускорить многострочные вставки (которые INSERT ... SELECT, INSERT ... VALUES (...), (...), ..., и LOAD DATA INFILE). Эта переменная ограничивает размер такого кэша в каждом потоке (указывается в байтах). Установка в 0 запретит такую оптимизацию. Внимание: этот кэш работает только тогда, когда делается вставка в непустую таблицу. Значение по умолчанию: 8 Мб.
  • character_set Принятый по умолчанию набор символов.
  • character_sets Поддерживаемые наборы символов.
  • concurrent_inserts Если установлено значение ON (принятое по умолчанию), MySQL обеспечивает возможность использовать команду INSERT на таблицах MyISAM одновременно с выполнением над этими же таблицами запросов SELECT. Этот параметр можно отключить, запустив mysqld с параметром --safe или --skip-new.
  • connect_timeout Количество времени в секундах, на протяжении которого сервер mysqld ожидает поступления пакета соединения, после чего генерирует Bad handshake.
  • datadir Значение параметра --datadir.
  • delay_key_write Опция для таблиц MyISAM. Может принимать одно из следующих значений:
    OFF | Все CREATE TABLE ... DELAYED_KEY_WRITES игнорируются.
    ON | (по умолчанию) MySQL будет учитывать опцию DELAY_KEY_WRITE в CREATE TABLE.
    ALL | Все вновь открытые таблицы обслуживаются так, будто бы они были созданы с опцией DELAY_KEY_WRITE.
    Если DELAY_KEY_WRITE включен, это означает что ключевой буфер для таблиц с этой опцией не будет сбрасываться на диск при каждом обновлении индексов, но только тогда, когда таблица закрывается. Это весьма ускорит записи ключей, но вы должны обязательно реализовать автоматическую проверку всех таких таблиц с помощью myisamchk --fast --force если вы хотите использовать эту опцию.
  • delay_key_write Если включен (по умолчанию - включен), MySQL будет учитывать параметр DELAY_KEY_WRITE для команды CREATE TABLE. Это означает, что ключевой буфер таблиц с данным параметром будет сбрасываться на диск не при каждом обновлении индексов, а только при закрытии таблицы. Такой режим работы значительно ускоряет запись ключей, однако в случае использования данного параметра необходимо будет также добавить автоматическую проверку всех таблиц при помощи myisamchk --fast --force. Обратите внимание: если запустить mysqld с параметром --delay-key-write-for-all-tables, то все таблицы будут обрабатываться таким образом, как будто они были созданы с применением параметра delay_key_write. Этот флаг можно снять, запустив mysqld с параметром --skip-new или --safe-mode.
  • delayed_insert_limit После вставки строк delayed_insert_limit обработчик INSERT DELAYED проверит, остались ли незавершенные операторы SELECT. Если да, то перед тем, как приступить к выполнению следующих действий, они будут выполнены.
  • delayed_insert_timeout Временной промежуток, в течение которого процесс INSERT DELAYED должен ожидать операторов INSERT до прекращения выполнения задачи.
  • delayed_queue_size Размер очереди (в строках), который должен быть назначен для обработки команды INSERT DELAYED. При переполнении очереди все клиенты, выполняющие команду INSERT DELAYED, будут ожидать, пока в очереди снова появится свободное место.
  • flush Значение этой переменной будет ON, если вы запустили MySQL с параметром --flush.
  • flush_time Если значение этой переменной отличается от нуля, то каждые flush_time секунд все таблицы будут закрываться (чтобы освободить ресурсы и записать информацию на диск). Мы рекомендуем использовать этот параметр только для Windows 9x/Me или на системах с ограниченным количеством ресурсов.
  • ft_boolean_syntax Список операторов, поддерживаемых MATCH ... AGAINST(... IN BOOLEAN MODE). See section 6.8 Полнотекстовый поиск в MySQL.
  • ft_min_word_len Минимальная длина слова, включаемого в индекс FULLTEXT. Примечание: индексы FULLTEXT после изменения этой переменной должны быть скомпонованы заново (это новый параметр в MySQL 4.0).
  • ft_max_word_len Максимальная длина слова, включаемого в индекс FULLTEXT. Примечание: индексы FULLTEXT после изменения этой переменной должны быть скомпонованы заново (это новый параметр в MySQL 4.0).
  • ft_max_word_len_for_sort Максимальная длина слова в индексе FULLTEXT; эта длина будет использоваться для метода быстрого восстановления индекса в командах REPAIR, CREATE INDEX или ALTER TABLE. Более длинные слова вставляются дольше. При увеличении значения ft_max_word_len_for_sort MySQL будет создавать временные файлы большего размера (таким образом будет замедляться работа из-за возрастания нагрузки на порт ввода/вывода диска), а также будет помещать меньше ключей в один блок сортировки (что, опять же, способствует снижению производительности). Если значение переменной ft_max_word_len_for_sort слишком мало, MySQL будет вставлять большое количество слов достаточно медленно, но короткие слова будут вставляться очень быстро.
  • ft_stopword_file Из этого файла читается список стоп-слов для полнотекстового поиска. Все слова из этого файла будут использованы, комментарии в этом файле недопустимы. По умолчанию используется встроенный список стоп-слов (определен в файле `myisam/ft_static.c'). Установка этого параметра в пустое значение ("") выключает фильтрацию по стоп-словам. Внимание: FULLTEXT индексы должны быть перестроены после того, как эта переменная изменена. (Эта опция нова в MySQL 4.0.10)
  • have_innodb Значение YES, если mysqld поддерживает таблицы InnoDB. Значение DISABLED, если используется параметр --skip-innodb.
  • have_bdb Значение YES, если mysqld поддерживает таблицы Berkeley DB. Значение DISABLED, если используется параметр --skip-bdb.
  • have_raid Значение YES, если mysqld поддерживает параметр RAID.
  • have_openssl Значение YES, если mysqld поддерживает SSL (шифрование) в протоколе клиент/сервер.
  • init_file Имя файла, указанного при помощи параметра --init-file при запуске сервера. Это файл операторов SQL, которые сервер должен выполнить при запуске.
  • interactive_timeout Количество времени в секундах, на протяжении которого сервер ожидает активности со стороны интерактивного соединения, прежде чем закрыть его. Интерактивный клиент - это клиент, который использует параметр CLIENT_INTERACTIVE для mysql_real_connect(). См. также информацию по wait_timeout.
  • join_buffer_size Размер буфера, используемого для полных объединений (объединения, в которых не применяются индексы). Буфер выделяется один раз для каждого полного объединения двух таблиц. Если нужно ускорить полное объединение и невозможно добавить индексы, следует увеличить это значение (обычно добавление индексов является лучшим способом добиться быстрых объединений).
  • key_buffer_size Блоки индексов буферизированы и доступ к ним разрешен всем потокам. key_buffer_size - размер буфера, используемого для блоков индексов. Чтобы улучшить обработку индексов (для всех операций чтения и записи нескольких элементов), необходимо увеличить это значение настолько, насколько возможно. Размер 64 Мб для компьютера с 256 Мб (именно такой компьютер в основном используется для работы с MySQL) - довольно распространенная конфигурация. Тем не менее, если задать слишком большое значение (например, больше 50% от общего количества памяти), система может начать сохранять временные файлы на диске, что значительно снизит производительность. Помните, что, поскольку MySQL не производит кэширования считываемых данных, нужно оставлять определенное пространство для кэша файловой системы операционной системы. Производительность буфера ключей можно проверить, выполнив команду SHOW STATUS и проверив значения переменных Key_read_requests, Key_reads, Key_write_requests и Key_writes. Отношение значений Key_reads/Key_read_request обычно должно быть < 0,01. Отношение Key_write/Key_write_requests примерно равно 1, если в основном используются обновления/удаления, но может быть и меньше, если чаще используются обновления сразу многих элементов или если DELAY_KEY_WRITE. See section 4.5.6 Синтаксис команды SHOW. Чтобы еще больше увеличить скорость при одновременной записи большого количества строк, используйте команду LOCK TABLES. See section 6.7.2 Синтаксис команд LOCK TABLES/UNLOCK TABLES.
  • language Язык, используемый для вывода сообщений об ошибках.
  • large_file_support Если mysqld был откомпилирован с параметрами для поддержки больших файлов.
  • locked_in_memory Если mysqld был заблокирован в памяти при помощи --memlock
  • log Если включено занесение в журнал всех запросов.
  • log_update Если включен журнал обновлений.
  • log_bin Если включен бинарный журнал.
  • log_slave_updates Если обновления от подчиненного компьютера должны заноситься в журнал.
  • long_query_time Если обработка запроса отнимает больше указанного промежутка времени (в секундах), значение счетчика Slow_queries будет увеличено. Если используется параметр --log-slow-queries, запрос будет записан в журнал медленных запросов. Это значение указывается в единицах реального времени, а не времени занятости процессора (CPU time). Таким образом, некий запрос, который выполняется быстрее указываемого времени на слегка загруженном сервере может выполняться больше указанного времени на более загруженном компьютере. See section 4.9.5 Журнал медленных запросов.
  • lower_case_table_names Если установлено значение 1, имена таблиц будут сохранятся на диск с использованием строчных букв, а имена таблиц не будут чувствительны к регистру. С версии MySQL 4.0.2 это также касается и имен баз данных. See section 6.1.3 Чувствительность имен к регистру.
  • max_allowed_packet Максимальный размер одного пакета. Изначально размер буфера сообщений устанавливается в net_buffer_length байтов, но при необходимости может возрасти до max_allowed_packet байтов. Это значение по умолчанию не настолько велико, чтобы отсеивать большие (возможно ошибочные) пакеты. Если используются большие столбцы BLOB, его необходимо увеличить. Значение должно быть не меньше самого большого BLOB, который будет использоваться. Ограничение протокола для max_allowed_packet составляет 16 Мб в MySQL 3.23 и 1Гб в MySQL 4.0.
  • max_binlog_cache_size Если для транзакции с большим количеством операторов потребуется большее количество памяти, чем указано этим параметром, будет выдано сообщение об ошибке "Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage" (для транзакции с большим количеством операторов требуется больше, чем 'max_binlog_cache_size' байтов для хранения).
  • max_binlog_size Доступно после версии 3.23.33. Если запись в бинарный журнал (репликация) превысит данное значение, производится ротация журнала. Нельзя установить значение, меньшее, чем 1024 байта или большее, чем 1 Гб. По умолчанию установлено значение 1 Гб.
  • max_connections Разрешенное количество одновременно подсоединенных клиентов. Увеличение этого значения увеличивает количество дескрипторов файлов, необходимых для mysqld. Ниже приведены примечания по ограничениям для дескрипторов. See section A.2.5 Ошибка Too many connections.
  • max_connect_errors Если количество прерванных соединений с удаленным компьютером превышает это число, дальнейшие попытки удаленного компьютера установить соединение будут заблокированы. Блокировку с удаленного компьютера можно снять при помощи команды FLUSH HOSTS.
  • max_delayed_threads Не запускайте больше потоков, чем указано здесь, для обработки операторов INSERT DELAYED. Если попытаться вставить данные в новую таблицу, когда все потоки INSERT DELAYED заняты, строка будет вставлена таким образом, как будто атрибут DELAYED не был указан.
  • max_heap_table_size Не позволяет создавать динамические таблицы, размер которых превышает указанное значение.
  • max_join_size Объединения, которые потенциально могут считывать более max_join_size записей, будут возвращать ошибку. Это значение нужно задавать, если ваши пользователи осуществляют объединения, которым недостает оператора WHERE, - такие объединения занимают много времени, а затем возвращают миллионы строк.
  • max_sort_length Параметр определяет, сколько байтов следует использовать при сортировке значений BLOB или TEXT (обрабатываются только первые max_sort_length байтов каждого значения, остальные игнорируются).
  • max_user_connections Максимальное количество активных соединений для одного пользователя (0 = без ограничений).
  • max_tmp_tables (Этот параметр пока ни на что не влияет.) Максимальное количество временных таблиц, которые клиент может открывать одновременно.
  • max_write_lock_count После данного количества блокирования записей разрешается выполнить между ними несколько блокировок чтения.
  • myisam_recover_options Значение параметра --myisam-recover.
  • myisam_sort_buffer_size Буфер, который выделяется для сортировки индексов при выполнении команды REPAIR или для создания индексов при помощи команд CREATE INDEX или ALTER TABLE.
  • myisam_max_extra_sort_file_size. Если размер временного файла, используемого для быстрого создания индексов, превышает на указанный здесь объем используемый кэш ключей, то лучше отдать предпочтение методу кэша ключей. Такой метод применяется для того, чтобы для больших ключей символов в больших таблицах использовался более медленный метод кэширования ключей при создании таблиц. Обратите внимание: значение этого параметра в байтах, начиная с 4.0.3 (до 4.0.3 параметр указывался в мегабайтах).
  • myisam_max_sort_file_size Максимальный размер временного файла, который в MySQL может использоваться при восстановлении индекса (во время работы команд REPAIR, ALTER TABLE или LOAD DATA INFILE). Для файлов, размер которых превышает указанное значение, индекс будет создаваться при помощи кэша ключей (такой алгоритм работает несколько медленнее). Обратите внимание: значение этого параметра в байтах, начиная с 4.0.3 (до 4.0.3 параметр указывался в мегабайтах).
  • net_buffer_length В данное значение устанавливается в промежутках между запросами буфер соединения. Обычно это значение не изменяется, но если у вас очень мало памяти, можно установить его по размеру ожидаемого запроса (т.е. равным предполагаемой длине операторов SQL, отправляемых клиентами; если оператор превысит указанную длину, буфер будет автоматически увеличен как максимум до max_allowed_packet байтов).
  • net_read_timeout Количество времени в секундах, на протяжении которого ожидаются дополнительные данные от соединения, пока не будет отменено чтение. Обратите внимание, что мы не ожидаем поступления данных от соединения, время ожидания определяется по write_timeout. Также см. slave_net_timeout.
  • net_retry_count Если чтение из порта связи было прервано, будет предпринято указанное количество попыток повторного чтения. Это значение должно быть достаточно высоким на FreeBSD, так как внутренние прерывания направляются на все потоки.
  • net_write_timeout Время ожидания записи блока через соединение, пока запись не будет прервана (в секундах).
  • open_files_limit Если это значение отлично от 0, то mysqld будет применять его для резервных дескрипторов файлов, используемых с setrlimit(). Если это значение равно 0, то mysqld будет резервировать max_connections*5 или max_connections + table_cache*2 (в зависимости от того, какое число больше) файлов. Если mysqld выдает ошибку 'Too many open files' (слишком много открытых файлов), данное значение необходимо увеличить.
  • pid_file Значение параметра --pid-file.
  • port Значение параметра --port.
  • protocol_version Версия протокола, используемого сервером MySQL.
  • read_buffer_size (было record_buffer) Каждый поток, осуществляющий последовательное сканирование, выделяет буфер указанного размера для каждой сканируемой таблицы. Если проводится много последовательных сканирований, это значение можно увеличить.
  • record_rnd_buffer_size При считывании строк после проведения сортировки в отсортированном порядке строки считываются через буфер, чтобы избежать операций поиска по диску. Это может улучшить выполнение ORDER BY весьма и весьма, если параметр установлен в большое значение. Т.к. эта переменная имеет отношение к потоку, то не устанавливайте слишком большое значение глобально, но просто меняйте его при выполнении некоторых больших запросов.
  • query_cache_limit Результаты, превышающие это значение, не кэшируются (по умолчанию - 1Мб).
  • query_cache_size Память, выделенная для хранения результатов старых запросов. Если значение установлено в 0, кэш запросов отключен (принято по умолчанию).
  • query_cache_type Могут быть заданы следующие значения (только числовые):
    Значение | Объяснение | Примечание
    0 | OFF | Не кэширует и не извлекает результаты.
    1 | ON | Кэширует все результаты, кроме запросов SELECT SQL_NO_CACHE ....
    2 | DEMAND | Кэширует только запросы SELECT SQL_CACHE ....
  • safe_show_database Не отображаются базы данных, для которых у пользователя нет каких-либо привилегий по базам данных или таблицам. Таким образом можно увеличить степень безопасности, если вы не хотите предоставлять посторонним лицам возможность получать информацию о том, какие базы данных есть у других пользователей. Также см. skip_show_database.
  • server_id Значение параметра --server-id.
  • skip_locking Установлено в значение OFF, если mysqld использует внешнюю блокировку.
  • skip_networking Установлено в значение ON, если разрешаются только локальные соединения (через сокет).
  • skip_show_database Эта переменная не позволяет выполнять команду SHOW DATABASES, если у пользователя нет привилегии PROCESS. Таким образом можно увеличить степень безопасности, если вы не хотите предоставлять посторонним лицам возможность получать информацию о том, какие базы данных есть у других пользователей. Также см. safe_show_database.
  • slave_net_timeout Количество времени в секундах, в течение которого ожидаются дополнительные данные от подсоединенного головного или подчиненного компьютера прежде, чем будет отменено чтение.
  • slow_launch_time Если создание потока занимает больше, чем указанное значение (в секундах), значение счетчика Slow_launch_threads будет увеличено.
  • socket Сокет Unix, используемый сервером.
  • sort_buffer_size Каждый поток, которому необходимо произвести сортировку, выделяет буфер данного размера. Увеличение данного значения позволит ускорить выполнение операторов ORDER BY или GROUP BY. See section A.4.4 Где MySQL хранит временные файлы.
  • table_cache Количество открытых таблиц для всех потоков. С увеличением этого значения увеличивается количество дескрипторов файлов, необходимых для mysqld. Чтобы узнать, необходимо ли изменять значение кэша таблиц, следует проверить значение переменной Opened_tables. См. раздел See section A.4.4 Где MySQL хранит временные файлы. Если у этой переменной большое значение, а команда FLUSH TABLES (которая закрывает все таблицы, а потом открывает их повторно) используется не часто, то необходимо увеличить ее значение. Чтобы получить дополнительную информацию по кэшу таблиц, см. раздел See section 5.4.7 Открытие и закрытие таблиц в MySQL.
  • table_type Принятый по умолчанию тип таблиц.
  • thread_cache_size Определяет, сколько потоков должно сохраняться в кэше для повторного использования. После отключения клиента потоки клиента помещаются в кэш, если там не больше потоков, чем thread_cache_size. Все новые потоки сначала берутся из кэша, и только когда кэш становится пустым, создаются новые потоки. Значение этой переменной можно увеличить, чтобы повысить производительность, если создается много новых соединений (если потоки у вас хорошо организованы, обычно заметного улучшения производительности не наблюдается). Насколько эффективен текущий кэш потоков, можно определить по разнице между Connections и Threads_created.
  • thread_concurrency В системе Solaris mysqld вызывает функцию thr_setconcurrency() с этим значением. thr_setconcurrency() позволяет приложению дать системе потоков подсказку по необходимому количеству потоков, которые должны быть запущены в одно и то же время.
  • thread_stack Размер стека для каждого потока. От данного значения зависит большое количество ограничений, обнаруживаемых при помощи теста crash-me. По умолчанию этот размер достаточен для нормальной работы. See section 5.1.4 Набор тестов MySQL (The MySQL Benchmark Suite).
  • timezone Часовой пояс, в котором находится сервер.
  • tmp_table_size Если находящаяся в памяти временная таблица превысит этот размер, MySQL автоматически преобразует ее в дисковую таблицу MyISAM. Значение tmp_table_size следует увеличить, если выполняется много расширенных запросов GROUP BY и в вашей системе установлено значительное количество оперативной памяти.
  • tmpdir Каталог, используемый для временных файлов и временных таблиц. Начиная с MySQL 4.1, в tmpdir могут быть указаны несколько путей, разделенных двоеточием : (точкой с запятой на Windows ;). Эти пути будут использованы в ротации.
  • version Номер версии сервера.
  • wait_timeout Время в секундах, на протяжении которого сервер наблюдает неактивность в неинтерактивном соединения прежде, чем закрыть его. Когда запускается поток, SESSION.WAIT_TIMEOUT инициализируется исходя из GLOBAL.WAIT_TIMEOUT или GLOBAL.INTERACTIVE_TIMEOUT, в зависимости от типа клиента (как определяется в CLIENT_INTERACTIVE опции соединения). См. также interactive_timeout.

Раздел руководства, в котором описывается настройка MySQL содержит некоторую информацию по настройке приведенных выше переменных. See section 5.5.2 Настройка параметров сервера.

4.5.6.5 SHOW LOGS

SHOW LOGS отображает информацию по состоянию существующих файлов журналов. На данный момент выводится информация только по файлам журналов Berkeley DB.

  • File отображает полный путь к файлу журнала
  • Type отображает тип файла журнала (BDB для файлов журналов Berkeley DB)
  • Status отображает состояние файла журнала (FREE - если файл может быть удален, или IN USE, если файл необходим подсистеме транзакций).

4.5.6.6 SHOW PROCESSLIST

Команда SHOW [FULL] PROCESSLIST показывает, какие потоки запущены в настоящий момент. Эту информацию также можно получить при помощи команды mysqladmin processlist. Если у вас привилегия SUPER, можно просматривать все потоки, в противном случае - только свои потоки. See section 4.5.5 Синтаксис команды KILL. Если не используется параметр FULL, будут показаны только первые 100 символов каждого запроса.

Начиная с 4.0.12, MySQL сообщает имя хоста для TCP/IP соединений как имя_хоста:клиентский_порт с тем, чтобы было проще понять, какой клиент чем занят.

Эта команда очень полезна, если выдается сообщение об ошибке 'too many connections' (слишком много соединений) и необходимо выяснить, что происходит. MySQL резервирует одно дополнительное соединение для клиента с привилегией SUPER, чтобы у вас всегда была возможность войти в систему и произвести проверку (предполагается, что вы не станете раздавать эту привилегию всем своим пользователям).

Некоторые состояния обычно можно увидеть в mysqladmin processlist.

  • Checking table Поток осуществляет [автоматическую] проверку таблицы.
  • Closing tables Означает, что поток записывает измененные данные таблиц на диск и закрывает использующиеся таблицы. Выполнение этой операции должно произойти быстро. Если на нее уходит значительное время, убедитесь, что диск не переполнен или что диск не используется слишком интенсивно.
  • Connect Out Подчиненный компьютер, подсоединенный к головному компьютеру.
  • Copying to tmp table on disk Набор временных результатов превысил tmp_table_size, и теперь поток изменяет таблицу временных данных, расположенную в памяти, на дисковую таблицу, чтобы сохранить память.
  • Creating tmp table Поток создает временную таблицу, чтобы хранить часть результатов для запроса.
  • deleting from main table При запуске первой части удаления нескольких таблиц удаление производится только начиная с первой таблицы.
  • deleting from reference tables При запуске второй части удаления нескольких таблиц удаляются совпадающие строки из других таблиц.
  • Flushing tables Поток запускает команду FLUSH TABLES и ожидает, пока все потоки закроют свои таблицы.
  • Killed Кто-то направил команду на закрытие потока, и поток будет закрыт при следующей проверке флага закрытия. Флаг проверяется при каждом основном цикле в MySQL, но в некоторых случаях закрытие потока может занять некоторое время. Если поток заблокирован другим потоком, закрытие будет произведено сразу после того, как другой поток снимет блокировку.
  • Sending data Поток обрабатывает строки для оператора SELECT, а также направляет данные клиенту.
  • Sorting for group Поток осуществляет сортировку в соответствии с GROUP BY.
  • Sorting for order Поток осуществляет сортировку в соответствии с ORDER BY.
  • Opening tables Это просто означает, что поток пытается открыть таблицу. Такая процедура осуществляется довольно быстро, если что-либо не мешает открытию. Например, команды ALTER TABLE или LOCK TABLE могут помешать открытию таблицы, пока выполнение команды не будет завершено.
  • Removing duplicates Запрос использовал команду SELECT DISTINCT таким образом, что MySQL не смог произвести оптимизацию на начальном этапе. Поэтому MySQL перед отправкой результатов клиенту должен выполнить дополнительное удаление всех дублирующихся строк.
  • Reopen table Поток заблокировал таблицу, но обнаружил, что после блокировки структура таблицы изменилась. Он снял блокировку, закрыл таблицу и теперь пытается повторно ее открыть.
  • Repair by sorting Код восстановления использует сортировку для создания индексов.
  • Repair with keycache Код восстановления использует создание ключей один за другим, через кэш ключей. Это намного медленнее, чем Repair by sorting.
  • Searching rows for update Поток осуществляет первую фазу - производит поиск всех совпадающих строк, чтобы затем обновить их. Это действие необходимо выполнить, если команда UPDATE изменяет индекс, который используется для поиска указанных строк.
  • Sleeping Поток ожидает, когда клиент направит ему новую команду.
  • System lock Поток ожидает получения внешней системной блокировки таблицы. Если не используется несколько серверов mysqld, которые получают доступ к одним и тем же таблицам, системную блокировку можно отключить при помощи параметра --skip-external-locking.
  • Upgrading lock Обработчик INSERT DELAYED пытается заблокировать таблицу, чтобы вставить строки.
  • Updating Поток производит поиск строк, которые необходимо обновить, и обновляет их.
  • User Lock Поток ожидает GET_LOCK().
  • Waiting for tables Поток получил уведомление, что структура таблицы изменилась, и ему необходимо повторно открыть таблицу, чтобы получить новую структуру. Чтобы повторно открыть таблицу, он должен подождать, пока ее не закроют все остальные потоки. Это уведомление выдается, если другой поток воспользовался командой FLUSH TABLES или к таблице была применена одна из следующих команд: FLUSH TABLES table_name, ALTER TABLE, RENAME TABLE, REPAIR TABLE, ANALYZE TABLE или OPTIMIZE TABLE. Обработчик INSERT DELAYED завершил работу со всеми вставками и ожидает новые.

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

Существует еще несколько состояний, не упомянутых выше, но большинство из них полезны только для поиска ошибок в mysqld.

4.5.6.7 SHOW GRANTS

SHOW GRANTS FOR user выводит список команд назначения привилегий, которые нужны при дублировании привилегий для пользователя.

mysql> SHOW GRANTS FOR root@localhost;
+---------------------------------------------------------------------+
| Grants for root@localhost                                          |
+---------------------------------------------------------------------+
| GRANT ALL PRIVILEGES ON *.* TO 'root'&lacute;ocalhost' WITH GRANT OPTION |
+---------------------------------------------------------------------+

Для получения информации по привилегии в текущей сессии можно использовать функцию CURRENT_USER() (новшество в версии 4.0.6) для того, чтобы выяснить, по какому пользователю в действительности аутентифицировалась сессия. See section 6.3.6.2 Разные функции.

4.5.6.8 SHOW CREATE TABLE

Показывает оператор CREATE TABLE, который будет создавать данную таблицу:

mysql> SHOW CREATE TABLE t\G
*************************** 1. row ***************************
Table: t
Create Table: CREATE TABLE t (
id int(11) default NULL auto_increment,
s char(60) default NULL,
PRIMARY KEY (id)
) TYPE=MyISAM

Команда SHOW CREATE TABLE будет выдавать таблицу и названия столбцов в соответствии с параметром SQL_QUOTE_SHOW_CREATE. See section 5.5.6 Синтаксис команды SET.

4.5.6.9 SHOW WARNINGS | ERRORS

SHOW WARNINGS [LIMIT #]
SHOW ERRORS [LIMIT #]

Эта команда реализована в версии MySQL 4.1.0.

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

Сервер MySQL возвращает общее количество сообщений и ошибок, которые вы получили для последней команды. Это количество можно получить вызовом mysql_warning_count().

Максимум max_error_count сообщений сохраняется (переменная глобальная и специфичная для потока).

Вы можете получить количество ошибок из @error_count и количество предупреждений из @warning_count.

SHOW WARNINGS сообщает все ошибки, предупреждения и заметки, которые вы получили для последней команды, в то время как SHOW ERRORS даешь лишь только информацию по ошибкам.

mysql> DROP TABLE IF EXISTS нет_такой_таблицы;
mysql> SHOW WARNINGS;

+-------+------+-----------------------------------+
| Level | Code | Message                           |
+-------+------+-----------------------------------+
| Note  | 1051 | Unknown table 'нет_такой_таблицы' |
+-------+------+-----------------------------------+

4.5.6.10 SHOW TABLE TYPES

SHOW TABLE TYPES

Эта команда реализована в 4.1.0.

SHOW TABLE TYPES дает статусную информацию про типы таблиц. Эта информация полезна, например, для проверки, поддерживается ли определенный тип таблицы или для того чтобы узнать, какой тип таблиц используется по умолчанию.

mysql> SHOW TABLE TYPES;

+--------+---------+----------------------------------------------------------------+
| Type   | Support | Comment                                                        |
+--------+---------+----------------------------------------------------------------+
| MyISAM | DEFAULT | Основной тип для 3.23 с отличной производительностью           |
| HEAP   | YES     | Хеш-тип, хранится только в памяти, полезен для временных таблиц|
| MERGE  | YES     | Набор идентичных MyISAM-таблиц                                 |
| ISAM   | YES     | Старый тип; замещен MyISAM                                     |
| InnoDB | YES     | Поддерживает транзакции, строчную блокировку и внешние ключи   |
| BDB    | NO      | Поддерживает транзакции и страничную блокировку                |
+--------+---------+----------------------------------------------------------------+
6 rows in set (0.00 sec)

Опция DEFAULT в столбце Support указывает, что данный конкретный тип таблицы поддерживается и является принятым по умолчанию. Если сервер был запущен с --default-table-type=InnoDB, тогда для InnoDB столбец Support примет значение DEFAULT.

4.5.6.11 SHOW PRIVILEGES

SHOW PRIVILEGES

Эта команда реализована в MySQL 4.1.0.

SHOW PRIVILEGES показывает список системных привилегий, которые поддерживаются сервером MySQL.

mysql> show privileges;
+------------+--------------------------+-------------------------------------------------------+
| Privilege  | Context                  | Comment                                               |
+------------+--------------------------+-------------------------------------------------------+
| Select     | Tables                   | To retrieve rows from table                           |
| Insert     | Tables                   | To insert data into tables                            |
| Update     | Tables                   | To update existing rows                               |
| Delete     | Tables                   | To delete existing rows                               |
| Index      | Tables                   | To create or drop indexes                             |
| Alter      | Tables                   | To alter the table                                    |
| Create     | Databases,Tables,Indexes | To create new databases and tables                    |
| Drop       | Databases,Tables         | To drop databases and tables                          |
| Grant      | Databases,Tables         | To give to other users those privileges you possess   |
| References | Databases,Tables         | To have references on tables                          |
| Reload     | Server Admin             | To reload or refresh tables, logs and privileges      |
| Shutdown   | Server Admin             | To shutdown the server                                |
| Process    | Server Admin             | To view the plain text of currently executing queries |
| File       | File access on server    | To read and write files on the server                 |
+------------+--------------------------+-------------------------------------------------------+
14 rows in set (0.00 sec)

Этот же пример в переводе на русский язык:

mysql> show privileges;
+------------+--------------------------+-------------------------------------------------------+
| Привилегия | Контекст                 | Описание                                              |
+------------+--------------------------+-------------------------------------------------------+
| Select     | Таблица                  | Для выборки строк из таблицы                          |
| Insert     | Таблица                  | Для вставки данных в таблицы                          |
| Update     | Таблица                  | Для обновления существующих записей                   |
| Delete     | Таблица                  | Для удаления существующих записей                     |
| Index      | Таблица                  | Для создания или удаления индексов                    |
| Alter      | Таблица                  | Для изменения таблиц                                  |
| Create     | База,Таблица,Индекс      | Для создания новых баз данных и таблиц                |
| Drop       | База,Таблица             | Для удаления баз данных и таблиц                      |
| Grant      | База,Таблица             | Для раздачи другим пользователям имеющихся у вас прав |
| References | База,Таблица             | Для обладания ссылок на таблицы                       |
| Reload     | Администрирование        | Для обновления таблиц, журналов и привилегий          |
| Shutdown   | Администрирование        | Для остановки сервера                                 |
| Process    | Администрирование        | Для просмотра текста выполняющихся запросов           |
| File       | Доступ к файлам          | Для чтения и записи файлов на сервере                 |
+------------+--------------------------+-------------------------------------------------------+
14 rows in set (0.00 sec)

4.6 Локализация MySQL и использование национальных алфавитов

4.6.1 Набор символов, применяющийся для записи данных и сортировки

По умолчанию в MySQL используется набор символов ISO-8859-1 (Latin1) с сортировкой согласно шведским/финским правилам. Этот набор символов также подходит для использования в США и Западной Европе.

Все стандартные исполняемые файлы MySQL компилируются с настройкой --with-extra-charsets=complex. Таким образом в файл помещается код, позволяющий всем стандартным программам работать с набором символов latin1, а также многобайтовыми наборами символов. Другие наборы символов могут загружаться из соответствующих файлов определений по необходимости.

Набор определяет, какие символы могут использоваться в именах, а также способ сортировки значений в операторах ORDER BY и GROUP BY команды SELECT.

При запуске сервера можно изменить набор символов при помощи параметра --default-character-set. Выбрать доступные наборы символов можно при помощи параметров --with-charset=charset и --with-extra-charsets= список-кодировок | complex | all, и файлов наборов символов, перечисленных в SHAREDIR/charsets/Index. See section 2.3.3 Типичные опции configure.

При смене набора символов во время работы MySQL (что может одновременно изменить и порядок сортировки) необходимо запустить команду myisamchk -r -q --set-character-set=charset для всех таблиц. В противном случае индексы могут быть созданы в неправильном порядке.

При подключении клиента к серверу MySQL сервер отправляет ему используемый по умолчанию набор символов. На время соединения клиент переключается на использование этого набора.

Для экранирования строк в SQL-запросе необходимо пользоваться функцией mysql_real_escape_string(). mysql_real_escape_string() идентична старой функции mysql_escape_string() - во всем, кроме одного: в качестве первого параметра она принимает дескриптор соединения MYSQL.

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

Сделать это можно путем внесения в файл настроек MySQL следующей строки:

[client]
character-sets-dir=/usr/local/mysql/share/mysql/charsets

путь в ней указывает на каталог, в котором хранятся динамические наборы символов MySQL.

Заставить клиента использовать определенный набор символов можно следующим образом:

[client]
default-character-set=character-set-name

но обычно этого не требуется.

4.6.1.1 Набор символов немецкого алфавита

Для задания порядка сортировки в соответствии с немецким алфавитом нужно запустить mysqld с параметром --default-character-set=latin1_de.

При сортировке и сравнении строк осуществляется следующая подстановка:

Д  ->  ae
Ж  ->  oe
Э  ->  ue
ъ  ->  ss

Все символы с диакритическими знаками заменяются их аналогами из верхнего регистра и без ударения. Все буквы переводятся в верхний регистр.

При сравнении строк с помощью команды LIKE, подстановки двух символов вместо одного не происходит. Все буквы переводятся в верхний регистр. Диакритические знаки снимаются со всех букв, кроме: э, Э, ж, Ж, д и Д.

4.6.2 Сообщения об ошибках на языках, отличных от английского

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

При запуске mysqld выбрать определенный язык можно при помощи настройки --language=язык или -L язык. Например:

shell> mysqld --language=swedish
или:
shell> mysqld --language=/usr/local/share/swedish

Обратите внимание: названия языков вводятся в нижнем регистре.

Файлы языков по умолчанию располагаются в папке `mysql_base_dir/share/LANGUAGE/'.

Для того чтобы изменить тексты сообщений об ошибках, нужно отредактировать файл `errmsg.txt' и запустить следующую команду для генерации нового файла `errmsg.sys':

shell> comp_err errmsg.txt errmsg.sys

Установив новую версию MySQL, не забудьте внести те же изменения в новый файл `errmsg.txt'.

4.6.3 Добавление набора символов

Снабдить MySQL новым набором символов можно следующим образом.

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

Например, наборы latin1 и danish - простые, а big5 и czech - сложные.

Для всех приведенных ниже примеров предполагается, что используемый набор символов называется MYSET.

Для создания простого набора достаточно сделать следующее:

  1. Вставьте имя MYSET в конец файла `sql/share/charsets/Index' и присвойте этому набору символов уникальный номер.
  2. Создайте файл `sql/share/charsets/MYSET.conf'. (в качестве основы можно использовать файл `sql/share/charsets/latin1.conf'). Правила составления этого файла очень просты:
    • Комментарием считается целая строка, начинающаяся с символа `#'.
    • Слова разделяются любым количеством непечатаемых символов.
    • При определении набора символов каждое слово должно представлять собой число в шестнадцатеричной системе счисления.
    • Массив ctype занимает первых 257 слов. За ним следуют массивы to_lower, to_upper[] и sort_order[], каждый из которых занимает 256 слов.
    See section 4.6.4 Массивы определения символов.
  3. Добавьте имя набора символов в списки CHARSETS_AVAILABLE и COMPILED_CHARSETS файла `configure.in'.
  4. Перенастройте, перекомпилируйте и протестируйте систему.

Для создания сложного набора необходимо выполнить следующие действия:

  1. Создайте файл strings/ctype-MYSET.c в исходном дистрибутиве MySQL.
  2. Вставьте имя MYSET в конец файла sql/share/charsets/Index и присвойте этому набору символов уникальный номер.
  3. Просмотрите один из существующих файлов ctype-*.c (например strings/ctype-big5.c) и узнайте, что нужно определить. Не забывайте, что имена массивов в вашем файле должны быть похожи на следующие: ctype_MYSET, to_lower_MYSET и т.п. Эти имена соответствуют именам массивов из простого набора символов (see section 4.6.4 Массивы определения символов).
  4. В начале файла целесообразно поместить комментарий наподобие следующего:
    /*
этот комментарий разбирается configure для создания ctype.c,
поэтому не меняйте его, если не уверены в правильности своих действий.
*
.configure. number_MYSET=MYNUMBER
.configure. strxfrm_multiply_MYSET=N
.configure. mbmaxlen_MYSET=N
*/
    Программа configure использует этот комментарий для линкования набора символов с библиотекой MySQL. Значение строк strxfrm_multiply и mbmaxlen будет разъяснено ниже. Использовать их нужно только в том случае, если вам нужны функции для сортировки строк или работы с многобайтовыми наборами символов соответственно.
  5. После этого нужно создать некоторые из следующих функций:
    • my_strncoll_MYSET()
    • my_strcoll_MYSET()
    • my_strxfrm_MYSET()
    • my_like_range_MYSET()
    See section 4.6.5 Поддержка упорядочивания строк.
  6. Добавьте имя набора символов в списки CHARSETS_AVAILABLE и COMPILED_CHARSETS файла `configure.in'.
  7. Перенастройте, перекомпилируйте и протестируйте систему.

Более подробные инструкции приведены в файле `sql/share/charsets/README'.

Если вы хотите, чтобы ваш набор символов был включен в комплект поставки MySQL, вышлите патч с ним по адресу internals@lists.mysql.com.

4.6.4 Массивы определения символов

Простые массивы to_lower[] и to_upper[] содержат символы верхнего и нижнего регистров, соответствующие каждому из символов набора. Например:

to_lower['A'] should contain 'a'
to_upper['a'] should contain 'A'

sort_order[] - карта, устанавливающая правила упорядочивания символов для сравнения и сортировки. Во многих наборах символов эта таблица совпадает с to_upper[] (благодаря чему при сортировке регистр символов не учитывается). MySQL сортирует символы в соответствии со значением sort_order[символ]. Более сложные правила упорядочивания строк разъясняются ниже. See section 4.6.5 Поддержка упорядочивания строк.

ctype[] представляет собой массив битов, по одному элементу на каждый из символов. (Массивы to_lower[], to_upper[], и sort_order[] индексируются по значению символа, а ctype[] - по значению символа + 1. Это позволяет обрабатывать символы EOF).

В файле `m_ctype.h' приведены следующие определения битовых масок:

#define _U 01 /* верхний регистр */
#define _L 02 /* нижний регистр */
#define _N 04 /* число (цифра) */
#define _S 010 /* символ пробела */
#define _P 020 /* знак пунктуации */
#define _C 040 /* управляющий символ */
#define _B 0100 /* пустой символ */
#define _X 0200 /* шестнадцатеричная цифра */

Значение ctype[] для каждого из символов должно представлять собой объединение значений битовых масок, описывающих символ. Например, 'A' представят собой символ верхнего регистра (_U) а также шестнадцатеричную цифру (_X), поэтому элемент ['A'+1] должен содержать значение:

_U + _X = 01 + 0200 = 0201

4.6.5 Поддержка упорядочивания строк

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

В настоящее время лучшим справочным пособием по этому вопросу являются уже реализованные наборы символов. Примером такой реализации могут служить наборы big5, czech, gbk, sjis и tis160.

В начале файла в особом комментарии необходимо указать значение strxfrm_multiply_MYSET=N. Значение N представляет собой максимальный прирост объема строк во время my_strxfrm_MYSET (т.е. положительное целое число).

4.6.6 Поддержка многобайтовых символов

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

В настоящее время лучшим справочным пособием по этому вопросу являются уже реализованные наборы символов. Примером такой реализации могут служить наборы euc_kr, gb2312, gbk, sjis и ujis. Они реализованы в файлах `ctype-'charset'.c', расположенных в папке `strings'.

В начале файла в особом комментарии необходимо указать значение strxfrm_multiply_MYSET=N. Значение N должно содержать объем самого ``большого'' символа набора в байтах.

4.6.7 Проблемы с наборами символов

При попытке воспользоваться набором символов, не включенным в исполняемый файл, можно столкнуться со следующими неприятностями:

  • В программе задан неверный путь к каталогу, в котором хранятся наборы символов (по умолчанию это `/usr/local/mysql/share/mysql/charsets'). Данную проблему можно решить с помощью настройки --character-sets-dir.
  • Набор символов является многобайтовым и не может быть загружен динамически. В таком случае нужно перекомпилировать программу и включить в нее поддержку нужного набора.
  • Набор символов может быть загружен динамически, но конфигурационного файла для него нет. В таком случае нужно скопировать файл для этого набора из нового дистрибутива MySQL.
  • В файле `Index' нет имени набора символов.
    ERROR 1105: File '/usr/local/share/mysql/charsets/?.conf' not found (Errcode: 2)
    В таком случае нужно либо установить новый файл `Index' или вручную внести в него недостающие имена наборов.

Узнать имя набора символов таблиц MyISAM можно с помощью команды myisamchk -dvv table_name.

4.7 Серверные сценарии и утилиты MySQL

4.7.1 Обзор серверных сценариев и утилит

Все программы MySQL имеют множество различных опций. При этом каждая программа MySQL поддерживает опцию --help, которую можно использовать для получения полного описания различных опций программы. Например, попробуйте выполнить mysql --help.

Заданные по умолчанию опции для всех стандартных программ можно переопределять при помощи файла опций. See section 4.1.2 Файлы параметров `my.cnf'.

В следующем списке приводятся краткие описания серверных программ MySQL:

myisamchk
Утилита, используемая для описания, проверки, оптимизации и восстановления таблиц MySQL. Поскольку утилита myisamchk имеет много функций, она описывается в отдельном разделе. See section 4 Администрирование баз данных.
make_binary_distribution
Создает бинарную поставку откомпилированного кода MySQL. Эту версию при помощи FTP можно передать на сайт support.mysql.com в директорию `/pub/mysql/Incoming', чтобы ею могли воспользоваться и другие пользователи MySQL.
mysqlbug
Сценарий, составляющий отчет о возникшей в MySQL неполадке. Этот сценарий должен всегда использоваться для составления отчета для почтового списка рассылки MySQL.
mysqld
Сам сервер MySQL, демон. Он должен работать постоянно.
mysql_install_db
Создает таблицы привилегий MySQL с заданными по умолчанию привилегиями. Это обычно делается только один раз, при первой инсталляции MySQL в системе.

4.7.2 safe_mysqld, оболочка mysqld

В MySQL 4.0 safe_mysqld был переименован в mysqld_safe.

safe_mysqld - это сценарий, с помощью которого рекомендуется запускать демон mysqld на Unix. safe_mysqld служит для реализации неких дополнительных функций безопасности для mysqld, таких как возможность перезапуска сервера при обнаружении ошибки и записи в журнал информации о процессе работы mysqld.

Если не указаны опции --mysqld=# или --mysqld-version=#, safe_mysqld будет использовать исполняемый файл mysqld-max, если последний существует. Если mysqld-max не существует, safe_mysqld запустит mysqld. Это позволяет легко выяснить, что даст использование mysqld-max вместо mysqld: просто скопируйте mysqld-max поверх mysqld, и он будет работать.

Как правило, редактировать сценарий safe_mysqld не следует, однако можно указать опции для safe_mysqld, поместив их в раздел [safe_mysqld] файла `my.cnf'. safe_mysqld будет считывать все опции из разделов файлов опций [mysqld], [server] и [safe_mysqld]. See section 4.1.2 Файлы параметров `my.cnf'.

Обратите внимание: все опции, которые вводятся в командной строке для safe_mysqld, передаются mysqld. Если требуется применить в safe_mysqld какие-либо опции, которые mysqld не поддерживает, эти опции нужно определить в файле опций.

Большинство опций safe_mysqld - те же, что и у mysqld. See section 4.1.1 Параметры командной строки mysqld.

Safe_mysqld поддерживает следующие опции:

--basedir=path
--core-file-size=#
Размер core-файла который может быть создан mysqld. Значение передается ulimit -c
--datadir=path
--defaults-extra-file=path
--defaults-file=path
--err-log=path (устарело в 4.0; Используйте --log-error вместо)
--log-error=path
Писать журнал ошибок в указанный файл. See section 4.9.1 Журнал ошибок.
--ledir=path
Путь к mysqld
--log=path
--mysqld=mysqld-version
Имя версии mysqld, которую вы хотите запустить в директории `ledir'
--mysqld-version=version
То же, что и --mysqld=, но в этой опции задается только суффикс для mysqld. Например, если используется --mysqld-version=max, safe_mysqld запустит версию ledir/mysqld-max. Если задать --mysqld-version без аргумента, будет использоваться ledir/mysqld.
--no-defaults
--open-files-limit=#
Максимальное количество файлов, которые могут быть открыты mysqld. Значение передается ulimit -n. Обратите внимание: чтобы эта опция работала корректно, необходимо запустить safe_mysqld от пользователя root!
--pid-file=path
--port=#
--socket=path
--timezone=#
Устанавливает переменную часового пояса (TZ) в значение, передаваемое в этом параметре.
--user=#

Сценарий safe_mysqld написан таким образом, чтобы можно было запустить сервер, инсталлированный как из исходного кода, так и из бинарной поставки MySQL, даже если компоненты сервера, в зависимости от используемой инсталляции, будут размещены несколько по-другому. Для safe_mysqld требуется выполнение одного из следующих условий:

  • Сервер и базы данных можно обнаружить относительно каталога, в котором вызывается safe_mysqld. safe_mysqld ищет в своей рабочей директории `bin' и `data' (для бинарных дистрибутивов) или `libexec' и `var' (для дистрибутивов с исходным кодом). Это условие должно выполняться, если safe_mysqld запускается из директории, в которую инсталлирован MySQL (например `/usr/local/mysql' для бинарного дистрибутива).
  • Если сервер и базы данных не могут быть найдены относительно рабочей директории, safe_mysqld пытается найти их по абсолютным путям. Типичные местоположения - `/usr/local/libexec' и `/usr/local/var'. Действительные местоположения определяются при создании дистрибутива, из которого запускается safe_mysqld. Они должны быть корректными, если MySQL был инсталлирован в стандартное местоположение.

Поскольку safe_mysqld будет пытаться найти сервер и базы данных относительно собственной рабочей директории, можно инсталлировать двоичный дистрибутив MySQL куда угодно, при условии, что safe_mysqld будет запускаться из директории, в которой установлен MySQL:

shell> cd mysql_installation_directory
shell> bin/safe_mysqld &

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

4.7.3 Mysqld_multi, программа для управления множеством серверов MySQL

Программа mysqld_multi предназначена для управления несколькими процессами mysqld, работающих на различных сокетах Unix и портах TCP/IP.

Программа будет искать группу(группы) [mysqld#] в `my.cnf' (или заданных при помощи --config-file=... файлах), где # - любое положительное число, начиная с 1. Мы говорим про этот номер далее как про номер группы опций, или GNR. Номера групп различают группы опций одну от другой и используются как аргумент при запуске mysqld_multi чтобы указать, какие сервера вы хотите запустить, остановить или получить статус об. Эти группы должны быть такими же, как и обычная группа [mysqld] (например содержать опции для mysqld; см. в руководстве более подробную информацию), но с такими портом, сокетом и т.д., которые требуются для каждого отдельного процесса mysqld.

mysqld_multi запускается в таком синтаксисе:

Использование: mysqld_multi [OPTIONS] {start|stop|report} [GNR,GNR,GNR...]
или            mysqld_multi [OPTIONS] {start|stop|report} [GNR-GNR,GNR,GNR-GNR,...]

GNR здесь означает номер группы. Можно запускать, останавливать или создавать отчеты о любом GNR, или о нескольких из них одновременно. Получить пример о том, как бы вы могли настроить файл опций, можно так:

shell> mysqld_multi --example

В качестве разделителей в списке GNR применяются запятые, комбинации создаются при помощи тире. Последнее означает, что будут задействованы все номера GNR из диапазона GNR1-GNR2. Если не задан аргумент GNR, то все группы будут либо запущены, либо остановлены, либо будет выведен отчет об этих группах. Обратите внимание, что в списке GNR не должно быть никаких пропусков (пробелов, символов табуляции или пустых строк). Любые данные после пропуска будут игнорироваться.

mysqld_multi поддерживает следующие опции:

--config-file=...
Альтернативный файл конфигурации (config file). Примечание: данный файл не влияет на собственные опции этой программы (группа [mysqld_multi]), а только на группы [mysqld#]. Без этой опции поиск всех данных будет осуществляться только в обычном файле `my.cnf'.
--example
Представляет пример файла конфигурации.
--help
Выводит справочную информацию и завершает работу.
--log=...
Файл журнала. Имя файла журнала и полный путь к нему. Примечание: если файл существует, записи будут добавляться в конец файла.
--mysqladmin=...
Исполняемый файл mysqladmin, используемый для завершения работы сервера.
--mysqld=...
Исполняемый файл mysqld, который будет использоваться. Обратите внимание: в этой опции можно также указывать safe_mysqld. Опции передаются mysqld. Необходимо только удостовериться, что в переменной окружения PATH имеется mysqld или что установлен safe_mysqld.
--no-log
Вывод в stdout вместо журнала. По умолчанию журналы включены.
--password=...
Пароль пользователя для доступа к mysqladmin.
--tcp-ip
Подсоединение к серверу(ам) MySQL по TCP/IP вместо Unix-сокетов. Данная опция влияет на завершение работы сервера и создание отчетов. Если файл сокета отсутствует, сервер будет работать, но к нему можно будет обращаться только через порт TCP/IP. По умолчанию соединение осуществляется через сокет Unix.
--user=...
Имя пользователя MySQL для mysqladmin.
--version
Вывод номера версии и завершение работы.

Некоторые примечания относительно mysqld_multi:

  • Удостоверьтесь, что пользователь MySQL, останавливающий mysqld (например, при помощи mysqladmin), имеет один пароль и имя пользователя для всех директорий данных, к которым производится доступ (имеется в виду - к базе данных mysql). Убедитесь также, что пользователь имеет привилегию Shutdown_priv! Если имеется несколько директорий с данными и несколько различных баз данных mysql с различными паролями для пользователя root в MySQL, можно создать некоего общего пользователя multi_admin для всех, с одинаковым паролем (см. ниже). Сделать это можно так:
    shell> mysql -u root -S /tmp/mysql.sock -proot_password -e
"GRANT SHUTDOWN ON *.* TO multi_admin@localhost IDENTIFIED BY
    See section 4.2.6 Как работает система привилегий. Эти действия нужно выполнять для каждого mysqld для каждой имеющейся директории данных (для этого нужно выбрать другой сокет -S=...).
  • `pid-файл' играет очень важную роль, если для запуска mysqld используется сценарий safe_mysqld (например, --mysqld=safe_mysqld). Преимущество использования safe_mysqld вместо mysqld заключается в том, что safe_mysqld ``бережет'' каждый процесс mysqld и перезапустит его, если mysqld-процесс умрет по сигналу 9 или подобному (например, в случае ошибки сегментации - хотя, конечно, уж этой ошибки MySQL в принципе совершать не должен;). Пожалуйста, обратите внимание: может оказаться, что сценарий safe_mysqld требуется запускать из определенного каталога. Это означает, что прежде чем запустить mysqld_multi, прийдется перейти в нужный каталог. Если при запуске возникнут проблемы, пожалуйста, просмотрите сценарий safe_mysqld. Обратите внимание на следующие строки:
    --------------------------------------------------------------------------
MY_PWD=`pwd` Check if we are starting this relative (for the binary
release) if test -d /data/mysql -a -f ./share/mysql/english/errmsg.sys
-a -x ./bin/mysqld
--------------------------------------------------------------------------

See section 4.7.2  safe_mysqld, оболочка mysqld.
    Этот тест может пройти успешно, однако возможны и проблемы.
  • Не запускайте несколько демонов mysqld с одной и тожй же директорией данных. Используйте различные директории с данными, если Вы четко не уверены в своих действиях!
  • Файл сокета и порт TCP/IP должны быть различными для каждого демона mysqld.
  • Первая и пятая группы mysqld были преднамеренно не включены в пример. В файле конфигурации могут быть ``промежутки'' - это увеличивает гибкость. Порядок, в котором запускаются или завершают работу демоны mysqld, зависит от порядка, в котором они указаны в файле конфигурации.
  • Когда нужно обратиться к некоторой группе (GNR) в этой программе, просто используйте номер в конце имени группы. Например, GNR для группы [mysqld17] - 17.
  • Для mysqld можно использовать опцию --user, но для этого сценарий mysqld_multi должен быть запущен от root. Наличие опции в файле конфигурации не имеет значения; вы получите предупреждение только в случаях, если не являетесь суперпользователем и демон mysqlds запущен под вашим аккаунтом Unix. Важно: удостоверьтесь, что для pid-файла и директории с данными имеется доступ для чтения+записи(+выполнения - для директории с данными) для того пользователя Unix, который запускает определенный процесс mysqld. Не используйте для этого аккаунт root в Unix, если Вы не уверены в своих действиях!
  • Очень важно: удостоверьтесь, что вы понимаете значения опций, которые передаются демонам mysqld, и что осознаете то, почему могут быть нужны отдельные процессы mysqld. Запуск нескольких демонов mysqld с одной директорией данных не увеличит производительность в многопоточной системе!

See section 4.1.4 Запуск нескольких серверов MySQL на одном компьютере.

Пример файла конфигурации для mysqld_multi.

# Этот файл может находиться в вашей домашней директории (~/.my.cnf) или
/etc/my.cnf
# Version 2.1 by Jani Tolonen

[mysqld_multi]
mysqld = /usr/local/bin/safe_mysqld
mysqladmin = /usr/local/bin/mysqladmin
user = multi_admin
password = multipass

[mysqld2]
socket = /tmp/mysql.sock2
port = 3307
pid-file = /usr/local/mysql/var2/hostname.pid2
datadir = /usr/local/mysql/var2
language = /usr/local/share/mysql/english
user = john

[mysqld3]
socket = /tmp/mysql.sock3
port = 3308
pid-file = /usr/local/mysql/var3/hostname.pid3
datadir = /usr/local/mysql/var3
language = /usr/local/share/mysql/swedish
user = monty

[mysqld4]
socket = /tmp/mysql.sock4
port = 3309
pid-file = /usr/local/mysql/var4/hostname.pid4
datadir = /usr/local/mysql/var4
language = /usr/local/share/mysql/estonia
user = tonu

[mysqld6]
socket = /tmp/mysql.sock6
port = 3311
pid-file = /usr/local/mysql/var6/hostname.pid6
datadir = /usr/local/mysql/var6
language = /usr/local/share/mysql/japanese
user = jani

See section 4.1.2 Файлы параметров `my.cnf'.

4.7.4 myisampack, MySQL-генератор сжатых таблиц (только для чтения)

Утилита myisampack используется для сжатия таблиц MyISAM, а утилита pack_isam - для сжатия таблиц ISAM. Поскольку таблицы ISAM являются устаревшими, здесь будет рассматриваться только myisampack, но все, сказанное относительно myisampack, справедливо также и для pack_isam.

myisampack сжимает каждый столбец в таблице по отдельности. Информация, необходимая для декомпрессии столбцов, считывается в память при открытии таблицы. В результате обеспечивается более высокая производительность при доступе к отдельным записям, поскольку нужно распаковывать только одну запись, а не значительно больший по размеру дисковый блок, как при использовании программы Stacker в MS DOS. В среднем myisampack сжимает файл данных на 40%-70%.

(MySQL использует отображение в памяти (mmap()) для сжатых таблиц

а если mmap() не работает, возвращается назад к нормальному режиму чтения/записи.

Обратите внимание на следующее:

  • После сжатия таблица доступна в режиме только для чтения. Это удобно, скажем, для записи на CD. Реализация возможности записи в сжатые таблицы находится в нашем списке задач к выполнению, но имеет низкий приоритет.
  • myisampack может также сжимать столбцы c типами BLOB или TEXT. В предыдущей версии pack_isam (для таблиц ISAM) данной функции не было.

Утилиту myisampack можно запустить следующим образом:

shell> myisampack [options] filename ...

Каждое имя файла (filename) должно быть именем индексного файла (`.MYI'). Если вы не находитесь в директории базы данных, необходимо указать полный путь к файлу. Допускается опускать расширение `.MYI'.

myisampack поддерживает следующие опции:

-b, --backup
Создает резервную копию таблицы, присваивая ей имя `tbl_name.OLD'.
-#, --debug=debug_options
Выводить журнал отладки. Строка debug_options часто принимает значение d:t:o,filename
-f, --force
Сжатие таблицы происходит, даже если она увеличивается или если существует временный файл. Во время сжатия таблицы myisampack создает временный файл `tbl_name.TMD'. Если вы вручную прекратите выполнение myisampack, может оказаться так, что файл `tbl_name.TMD' не будет удален. Обычно если myisampack обнаруживает существующий `tbl_name.TMD', она прекращает работу и выдает ошибку. При указании опции --force myisampack сжимает таблицу в любом случае.
-?, --help
Выдает справочную информацию и завершает работу.
-j big_tbl_name, --join=big_tbl_name
Соединяет все таблицы, указанные в командной строке, в одну таблицу big_tbl_name. Все таблицы, подлежащие объединению, должны быть идентичными (одинаковые имена и типы столбцов, одинаковые индексы и т.д.).
-p #, --packlength=#
Определяет разрядность поля, хранящего длину строки, в байтах. Может принимать значения 1, 2 или 3. (myisampack хранит все строки с указателями длины размером в 1, 2, или 3 байта. В большинстве случаев myisampack способна определить правильное значение длины перед началом сжатия файла, но во время сжатия она может обнаружить, что может быть использована более короткая длина. В этом случае myisampack выведет сообщение о том, что в следующий раз при сжатии данного файла можно использовать более короткую длину записи.)
-s, --silent
Молчаливый режим. Сообщения выводятся только при возникновении ошибок.
-t, --test
Сжатие таблицы не выполняется, происходит только проверка процедуры сжатия.
-T dir_name, --tmp_dir=dir_name
Указанная директория используется как местоположение для создания временной таблицы.
-v, --verbose
Расширенный режим вывода сообщений. Выводится информация о состоянии процесса и результаты сжатия.
-V, --version
Отображает информацию о версии и завершает работу.
-w, --wait
Если таблица уже используется, подождать повторить попытку. Если сервер mysqld был вызван с опцией --skip-external-locking, то не самая лучшая идея - вызывать myisampack, если таблица может модифицироваться во время процесса сжатия.

Последовательность приведенных ниже команд иллюстрирует типичный сеанс сжатия таблицы:

shell> ls -l station.*
-rw-rw-r--   1 monty    my         994128 Apr 17 19:00 station.MYD
-rw-rw-r--   1 monty    my          53248 Apr 17 19:00 station.MYI
-rw-rw-r--   1 monty    my           5767 Apr 17 19:00 station.frm

shell> myisamchk -dvv station

MyISAM 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                       Root  Blocksize    Rec/key
1   2     4   unique  unsigned long              1024       1024          1
2   32    30  multip. text                      10240       1024          1

Field Start Length Type
1     1     1
2     2     4
3     6     4
4     10    1
5     11    20
6     31    1
7     32    30
8     62    35
9     97    35
10    132   35
11    167   4
12    171   16
13    187   35
14    222   4
15    226   16
16    242   20
17    262   20
18    282   20
19    302   30
20    332   4
21    336   4
22    340   1
23    341   8
24    349   8
25    357   8
26    365   2
27    367   2
28    369   4
29    373   4
30    377   1
31    378   2
32    380   8
33    388   4
34    392   4
35    396   4
36    400   4
37    404   1
38    405   4
39    409   4
40    413   4
41    417   4
42    421   4
43    425   4
44    429   20
45    449   30
46    479   1
47    480   1
48    481   79
49    560   79
50    639   79
51    718   79
52    797   8
53    805   1
54    806   1
55    807   20
56    827   4
57    831   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
87.14%

shell> ls -l 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 -dvv station

MyISAM 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
Datafilepointer (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
2   32    30  multip. text                      54272       1024          1

Field Start Length Type                         Huff tree  Bits
1     1     1      constant                             1     0
2     2     4      zerofill(1)                          2     9
3     6     4      no zeros, zerofill(1)                2     9
4     10    1                                           3     9
5     11    20     table-lookup                         4     0
6     31    1                                           3     9
7     32    30     no endspace, not_always              5     9
8     62    35     no endspace, not_always, no empty    6     9
9     97    35     no empty                             7     9
10    132   35     no endspace, not_always, no empty    6     9
11    167   4      zerofill(1)                          2     9
12    171   16     no endspace, not_always, no empty    5     9
13    187   35     no endspace, not_always, no empty    6     9
14    222   4      zerofill(1)                          2     9
15    226   16     no endspace, not_always, no empty    5     9
16    242   20     no endspace, not_always              8     9
17    262   20     no endspace, no empty                8     9
18    282   20     no endspace, no empty                5     9
19    302   30     no endspace, no empty                6     9
20    332   4      always zero                          2     9
21    336   4      always zero                          2     9
22    340   1                                           3     9
23    341   8      table-lookup                         9     0
24    349   8      table-lookup                        10     0
25    357   8      always zero                          2     9
26    365   2                                           2     9
27    367   2      no zeros, zerofill(1)                2     9
28    369   4      no zeros, zerofill(1)                2     9
29    373   4      table-lookup                        11     0
30    377   1                                           3     9
31    378   2      no zeros, zerofill(1)                2     9
32    380   8      no zeros                             2     9
33    388   4      always zero                          2     9
34    392   4      table-lookup                        12     0
35    396   4      no zeros, zerofill(1)               13     9
36    400   4      no zeros, zerofill(1)                2     9
37    404   1                                           2     9
38    405   4      no zeros                             2     9
39    409   4      always zero                          2     9
40    413   4      no zeros                             2     9
41    417   4      always zero                          2     9
42    421   4      no zeros                             2     9
43    425   4      always zero                          2     9
44    429   20     no empty                             3     9
45    449   30     no empty                             3     9
46    479   1                                          14     4
47    480   1                                          14     4
48    481   79     no endspace, no empty               15     9
49    560   79     no empty                             2     9
50    639   79     no empty                             2     9
51    718   79     no endspace                         16     9
52    797   8      no empty                             2     9
53    805   1                                          17     1
54    806   1                                           3     9
55    807   20     no empty                             3     9
56    827   4      no zeros, zerofill(2)                2     9
57    831   4      no zeros, zerofill(1)                2     9

Ниже приведено описание вывода myisampack:

normal
Количество столбцов, для которых не используется никакого дополнительного сжатия.
empty-space
Количество столбцов, содержащих пустые значения; эти занимают по 1 биту.
empty-zero
Количество целочисленных столбцов, в которых содержатся только двоичные нули (ascii 0); каждый из них будет занимать 1 бит
empty-fill
Количество целочисленных столбцов, значения которых не полностью занимают отведенную для них разрядность в байтах; тип этих столбцов изменяется на тип с меньшей разрядностью(например, столбец INTEGER может быть изменен на MEDIUMINT).
pre-space
Количество десятичных столбцов, которые хранятся с начальными пробелами. В этом случае каждое значение будет содержать число ведущих пробелов.
end-space
Количество столбцов, имеющих много оконечных пробелов. В этом случае каждое значение будет содержать число таких пробелов.
table-lookup
Столбец имеет только небольшое количество различающихся значений, которые перед сжатием Хаффмана (Huffman) конвертируются в ENUM.
zero
Количество столбцов, все значения которых являются нулями.
Original trees
Начальное количество деревьев Хаффмана.
After join
Количество различных деревьев Хаффмана, оставленных после соединения деревьев для сохранения немного пространства в заголовках.

После сжатия таблицы myisamchk -dvv выводит дополнительную информацию по каждому полю:

Type
Тип поля может содержать следующие дескрипторы:
constant
Все строки содержат одинаковое значение.
no endspace
Не сохраняются замыкающие пробелы.
no endspace, not_always
Не сохраняются замыкающие пробелы и не производится сжатие за счет замыкающих пробелов для всех значений.
no endspace, no empty
Не сохраняются замыкающие пробелы. Не сохраняются пустые значения.
table-lookup
Столбец был преобразован к ENUM.
zerofill(n)
В значении n главных байтов всегда являются 0 и не сохранены.
no zeros
Не сохраняются нули.
always zero
Значения 0 хранятся в 1 бите.
Huff tree
Дерево Хаффмана, связанное с полем.
Bits
Количество битов, используемых в дереве Хаффмана.

После запуска pack_isam/myisampack нужно запустить isamchk/myisamchk для повторного создания индекса. В это время можно также отсортировать индексные блоки и создать статистику, необходимую для более эффективной работы оптимизатора MySQL:

myisamchk -rq --analyze --sort-index table_name.MYI
isamchk -rq --analyze --sort-index table_name.ISM

После установки сжатой таблицы в директорию базы данных MySQL нужно проделать операцию mysqladmin flush-tables, чтобы сервер mysqld начал использовать новую таблицу.

Для распаковки сжатой таблицы можно использовать опцию --unpack isamchk или myisamchk.

4.7.5 mysqld-max, расширенный сервер mysqld

mysqld-max - это сервер MySQL (mysqld), скомпилированный со следующими конфигурационными опциями:

Опция | Описание
--with-server-suffix=-max | Добавляет суффикс к версии mysqld.
--with-innodb | Поддержка таблиц InnoDB.
--with-bdb | Поддержка таблиц Беркли DB (BDB)
CFLAGS=-DUSE_SYMDIR | Символические ссылки для Windows.

Бинарную версию MySQL-max можно найти по адресу http://www.mysql.com/downloads/mysql-max-3.23.html.

Бинарные дистрибутивы Windows MySQL включают стандартный двоичный файл mysqld.exe а также двоичный файл mysqld-max.exe. http://www.mysql.com/downloads/mysql-3.23.html. See section 2.1.2 Установка MySQL на Windows.

Обратите внимание: поскольку таблицы InnoDB и Berkeley DB доступны не для всех платформ, некоторые из двоичных дистрибутивов могут не поддерживать оба этих типа таблиц. Проверить, какие типы таблиц поддерживаются, можно при помощи следующего запроса:

mysql> SHOW VARIABLES LIKE "have_%";
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| have_bdb | YES |
| have_innodb | NO |
| have_isam | YES |
| have_raid | NO |
| have_openssl | NO |
+---------------+-------+

Значения имеют следующий смысл:

Значение | Описание
YES | Опция активизирована.
NO | MySQL не поддерживает эту опцию.
DISABLED | Опция xxxx заблокирована, потому что mysqld был запущен с параметром --skip-xxxx или потому, что mysqld был запущен не со всеми опциями, необходимыми для того, чтобы использование данной опции было возможным. В этом случае файл `hostname.err' будет содержать причину, по которой опция заблокирована.

Примечание: чтобы получить возможность создавать таблицы InnoDB, вы должны отредактировать опции, включив по меньшей мере опцию innodb_data_file_path. See section 7.5.2 Параметры запуска InnoDB.

Чтобы улучшить производительность таблиц BDB, для них нужно также добавить некоторые конфигурационные опции. See section 7.6.3 Параметры запуска BDB.

safe_mysqld будет автоматически пытаться запустить двоичный mysqld с суффиксом -max. Таким образом можно просто осуществлять тестирование свежесобранного бинарного mysqld в существующей инсталляции. Для этого нужно выполнить configure с требуемыми опциями, собрать, и затем установить новый mysqld как mysqld-max в тот же самый каталог, где находится ``старый'' бинарный mysqld. See section 4.7.2 safe_mysqld, оболочка mysqld.

mysqld-max RPM использует вышеупомянутую возможность safe_mysqld. Он только устанавливает исполняемый mysqld-max, и safe_mysqld будет автоматически использовать его после перезапуска safe_mysqld.

В следующей таблице показаны типы таблиц, поддерживаемые двоичным MySQL-Max:

System | BDB | InnoDB
AIX 4.3 | Нет | Да
HP-UX 11.0 | Нет | Да
Linux-Alpha | Нет | Да
Linux-Intel | Да | Да
Linux-IA64 | Нет | Да
Solaris-Intel | Нет | Да
Solaris-SPARC | Да | Да
Caldera (SCO) OSR5 | Да | Да
UnixWare | Да | Да
Windows/NT | Да | Да

4.8 Клиентские сценарии и утилиты MySQL

4.8.1 Обзор клиентских сценариев и утилит

Все клиенты MySQL, которые взаимодействуют с сервером с помощью библиотеки mysqlclient, используют следующие переменные окружения:

Имя | Описание
MYSQL_UNIX_PORT | Сокет, используемый по умолчанию для локальных подсоединений
MYSQL_TCP_PORT | Устанавливаемый по умолчанию порт TCP/IP
MYSQL_PWD | Устанавливаемый по умолчанию пароль
MYSQL_DEBUG | Опции пошаговой отладки программ
TMPDIR | Каталог для создания временных таблиц/файлов

Использование MYSQL_PWD небезопасно. See section 4.2.8 Соединение с сервером MySQL.

Клиент mysql использует файл, указанный в переменной окружения MYSQL_HISTFILE, для хранения истории командной строки. Значение по умолчанию для этого файла истории - $HOME/.mysql_history, где $HOME - значение переменной окружения HOME. See section E Переменные окружения.

Все программы MySQL принимают множество различных опций. При этом каждая программа MySQL поддерживает опцию --help, которую можно использовать для получения полного описания различных опций программы. Например, попробуйте запустить mysql --help.

Для всех стандартных клиентских программ можно переопределить значения опций по умолчанию, используя файл опций. See section 4.1.2 Файлы параметров `my.cnf'.

В приведенном ниже списке дано краткое описание клиентских программ MySQL:

msql2mysql
Сценарий оболочки операционной системы, преобразующий программы базы данных mSQL к виду, приемлемому для MySQL. Он не обрабатывает всех случаев, но с него хорошо начинать такое преобразование.
mysqlaccess
Сценарий, который проверяет привилегии доступа для комбинации значений хоста, пользователя и базы данных.
mysqladmin
Утилита для выполнения административных функций, таких как создание или удаление баз данных, перезагрузка таблиц привилегий, запись на диск содержимого таблиц, находящегося в буфере, повторное открытие файлов журналов. Утилита mysqladmin может также использоваться для получения информации с сервера о номере версии, процессах и состоянии сервера. См. раздел See section 4.8.3 mysqladmin, Администрирование MySQL-сервера..
mysqldump
Выводит содержимое базы данных MySQL в виде файла с SQL-операторами или в виде текстовых файлов с символом табуляции в качестве разделителя. Усовершенствованная свободно распространяемая утилита, автором которой является Игорь Романенко. See section 4.8.5 mysqldump, Получение дампов данных и структуры таблицы.
mysqlimport
Импортирует текстовые файлы в соответствующие таблицы, используя команду LOAD DATA INFILE. See section 4.8.7 mysqlimport, импорт данных из текстовых файлов.
mysqlshow
Отображает информацию о существующих базах данных, таблицах, полях и индексах.
replace
Служебная программа, использующаяся в сценарии msql2mysql, но имеющая также более широкое применение. Утилита replace изменяет строки, находящиеся в файлах или в стандартных входных данных. Использует принцип конечного автомата, чтобы в первую очередь найти соответствие длинных строк. Может применяться для замены строк. Например, эта команда меняет местами a и b в данных файлах:
shell> replace a b b a -- file1 file2 ...

4.8.2 mysql, Утилита командной строки

Утилита командной строки mysql является простой SQL-оболочкой (с возможностями библиотеки readline проекта GNU). Она поддерживает интерактивный и неинтерактивный режимы. В интерактивном режиме результаты запроса представляются в ASCII-формате. При использовании в неинтерактивном режиме (например, в качестве фильтра) результат представляется в текстовом формате с символом табуляции в качестве разделителя (выходной формат можно изменить при помощи параметров командной строки). Сценарии можно запускать, как показано ниже:

shell> mysql database < script.sql > output.tab

Если возникают проблемы из-за недостатка памяти на данном клиенте, применяйте параметр --quick! Это заставит mysql использовать функцию mysql_use_result() вместо функции mysql_store_result() для получения результирующей выборки данных.

Использовать mysql очень легко. Запустите mysql database или mysql --user=user_name --password=your_password database. Наберите SQL-команду прямо в командной строке, завершив ее одним из символов: `;', `\g' или `\G', и нажмите клавишу ``Ввод''.

Утилита командной строки mysql поддерживает следующие параметры:

-?, --help
Вывод справочной информации об использовании программы и выход из нее.
-A, --no-auto-rehash
Отключает автоматическое рехеширование. rehash следует использовать для получения хеша таблиц и полей. Это обеспечивает более быстрый старт mysql.
--prompt=...
Устанавливает приглашение на ввод команд в заданном формате.
-b, --no-beep
Выключает звуковой сигнал об ошибке.
-B, --batch
Выводит результаты в пакетном режиме с символом табуляции в качестве разделителя, каждая строка с новой строки. Файл истории не используется.
--character-sets-dir=...
Директория, где находятся наборы символов.
-C, --compress
Использовать сжатие данных в протоколе сервер/клиент.
-#, --debug[=...]
Журнал отладки. Значение по умолчанию - 'd:t:o,/tmp/mysql.trace'.
-D, --database=...
Имя используемой базы данных. Большей частью применяется в конфигурационном файле `my.cnf'.
--default-character-set=...
Установить набор символов по умолчанию.
-e, --execute=...
Выполнить команду и завершить программу (вывод результата как и для --batch).
-E, --vertical
Вывести результаты запроса (строки) по вертикали. Можно произвести вывод подобным образом и без данного параметра, завершая команды символами \G.
-f, --force
Продолжать обработку даже при обнаружении ошибки SQL.
-g, --no-named-commands
Выключает именованные команды. Следует использовать только команды вида \* либо применять именованные команды только в начале строки, заканчивающейся символом `;'. Начиная с версии 10.9 клиент запускается с этой опцией, включенной по умолчанию! С опцией -g, однако, длинные команды все еще работают с первой строки.
-G, --enable-named-commands
Разрешает именованные команды. Допускаются длинные команды, а также укороченные команды вида \*.
-i, --ignore-space
Игнорировать пробел после имен функций.
-h, --host=...
Подсоединиться к базе данных на указанном хосте.
-H, --html
Вывести выходные данные в виде HTML.
-X, --xml
Вывести выходные данные в виде XML.
-L, --skip-line-numbers
Не указывать номера строк для ошибок. Полезно для сравнения результирующих файлов, включающих сообщения об ошибках.
--no-pager
Блокирует пейджер (программа постраничного вывода) и выводит результат в стандартный вывод stdout (в Unix). Смотрите также команду \h (интерактивная помощь).
--no-tee
Блокирует выходной файл. Смотрите также команду \h (интерактивная помощь).
-n, --unbuffered
Очищать буфер после каждого запроса.
-N, --skip-column-names
Не указывать имена столбцов в результатах.
-O, --set-variable var=option
Установить значение переменной. Список используемых переменных выводится через --help. Обратите внимание, что --set-variable не используется в MySQL 4.0. Просто используйте --var=option.
-o, --one-database
Обновить только базу данных, установленную по умолчанию. Позволяет пропускать обновления другой базы данных в журнале обновления.
--pager[=...]
Устанавливает тип данных вывода. По умолчанию это переменная окружения PAGER. Ее возможные значения - less, more, cat [> имя файла], и т.д. См. также команду \h (интерактивная помощь). Этот параметр не работает в пакетном (batch) режиме. Пейджер работает только под Unix.
-p[password], --password[=...]
Пароль, используемый при подсоединении к серверу баз данных. Если в командной строке пароль не указан, то он запрашивается у пользователя. При использовании краткой формы -p не оставляйте пробел между параметром и значением пароля.
-P порт, --port=порт
Номер порта TCP/IP, используемый для подсоединения.
--protocol=(TCP | SOCKET | PIPE | MEMORY)
Для указания протокола соединения, который надлежит использовать. Новшество в MySQL 4.1.0.
-q, --quick
Не кэшировать результат. Выводить его строка за строкой так, как он приходит от сервера. Это может замедлить скорость работы сервера, если вывод результата будет приостановлен. Файл истории не используется.
-r, --raw
Показывать значения столбцов без какого-либо преобразования. Используется с --batch.
-s, --silent
Режим молчания. Выводить только сообщения об ошибках.
-S --socket=...
Файл сокета, используемый для подсоединения.
-t --table
Выводить результат в табличном формате. Установлено по умолчанию для непакетного режима.
-T, --debug-info
Выводить некоторые отладочные данные при выходе из программы.
--tee=...
Присоединить что-либо к выходному файлу. Смотрите также команду \h (интерактивная помощь). Этот параметр не работает в пакетном режиме.
-u, --user=#
Имя пользователя MySQL, если этот пользователь не является активным в данное время.
-U, --safe-updates[=#], --i-am-a-dummy[=#]
Разрешает выполнять только операции UPDATE и DELETE, используя ключи. Более полная информация об этом параметре приведена ниже. Можно сбросить данный параметр, установив в конфигурационном файле `my.cnf' значение аргумента --safe-updates=0.
-v, --verbose
Более расширенный режим вывода результатов (-v -v -v дает формат вывода таблицы).
-V, --version
Вывод информации о версии и выход из программы.
-w, --wait
Если соединение с сервером упало, подождать и попытаться восстановить его, вместо того, чтобы прервать работу.

Через параметры командной строки -O или --set-variable (в MySQL 4.0 используйте просто --var=option) можно также установить следующие переменные:

Имя переменной | По умолчанию | Описание
connect_timeout | 0 | Число секунд до истечения времени ожидания соединения
max_allowed_packet | 16777216 | Максимальная величина пакета, посылаемого/принимаемого с сервера
net_buffer_length | 16384 | Размер буфера для TCP/IP и сокетного соединения
select_limit | 1000 | Автоматическое ограничение количества команд SELECT при использовании --i-am-a-dummy
max_join_size | 1000000 | Автоматическое ограничение количества связанных строк при использовании --i-am-a-dummy.

Если ввести в командной строке help, программа mysql выведет список поддерживаемых ею команд:

mysql> help

Команды MySQL
help (\h)	Выводит данный текст.
? (\h)		Синоним для help.
clear (\c)	Команда очистки.
connect (\r)	Снова подключиться к серверу.
        Дополнительные аргументы - db и host.
edit (\e)	Редактировать текущую команду с помощью $EDITOR.
ego (\G)	Послать текущую команду MySQL серверу
        и вывести результат по вертикали.
exit (\q)	Выйти из программы. То же что и quit.
go (\g)		Послать текущую команду MySQL серверу.
nopager (\n)	Блокировать пейджер, выводить через stdout.
notee (\t)	Не добавлять записи в выходной файл outfile.
pager (\P)	Установить PAGER [to_pager].
        Выводить результаты запроса через PAGER.
print (\p)	Вывести текущую команду.
prompt (\R)	Изменить формат приглашения на ввод команд mysql.
quit (\q)	Выйти из программы.
rehash (\#)	Восстановить таблицу хэшей.
source (\.)	Запустить на выполнение файл с SQL-сценарием.
        Указать имя файла в качестве аргумента.
status (\s)	Получить информацию о статусе сервера.
tee (\T)	Установить параметр outfile [to_outfile].
        Присоединить что-либо к данному выходному файлу.
use (\u)	Использовать другую базу данных.
        Указать имя базы данных в качестве аргумента.

Команда pager работает только под Unix.

Команда status дает информацию о текущем соединении и используемом сервере. Если вы работаете в режиме --safe-updates, команда status также выведет значения переменных для mysql, которые влияют на ваши запросы.

Для начинающих рекомендуется пользоваться программой mysql с установленным параметром (введен в MySQL 3.23.11) --safe-updates (или --i-am-a-dummy для пользователей, выполнивших DELETE FROM table_name, но забывших указать аргументы в WHERE). В этом случае mysql при установлении соединения посылает следующую команду MySQL-серверу:

SET SQL_SAFE_UPDATES=1,SQL_SELECT_LIMIT=#select_limit#,
    SQL_MAX_JOIN_SIZE=#max_join_size#"

где #select_limit# и #max_join_size# - переменные, которые можно установить из командной строки mysql. See section 5.5.6 Синтаксис команды SET.

Результат этого следующий:

  • Не разрешено выполнять команды UPDATE или DELETE, если не указаны ограничения по ключам в секции WHERE. Однако можно заставить выполняться команды UPDATE/DELETE, используя оператор LIMIT:
    UPDATE table_name SET not_key_column=# WHERE not_key_column=# LIMIT 1;
  • Все слишком большие результаты ограничены строками #select_limit#.
  • SELECTы, которые могут потребовать для исполнения количество комбинаций строк более, чем #max_join_size#, будут прерваны.

Несколько полезных советов по использованию клиента mysql:

Некоторые данные более удобочитаемы при выводе их по вертикали вместо обычно используемого горизонтального окна вывода. Например, текст, который больше по длине, чем по ширине, и содержит в себе много новых строк, часто намного легче читать в вертикальном представлении.

mysql> SELECT * FROM mails WHERE LENGTH(txt) < 300 lIMIT 300,1\G
*************************** 1. row ***************************
  msg_nro: 3068
     date: 2000-03-01 23:29:50
time_zone: +0200
mail_from: Monty
    reply: monty@no.spam.com
  mail_to: "Thimble Smith" <tim@no.spam.com>
      sbj: UTF-8
      txt: >>>>> "Thimble" == Thimble Smith writes:
Thimble> Hi.  I think this is a good idea.  Is anyone familiar with UTF-8
Thimble> or Unicode? Otherwise, I'll put this on my TODO list and see what
Thimble> happens.

Yes, please do that.
Regards,
Monty
     file: inbox-jani-1
     hash: 190402944
1 row in set (0.09 sec)

Для журналирования можно использовать опции команды tee. Она может быть запущена с помощью параметра --tee=... для mysql или интерактивно из командной строки вводом команды tee. Все представляемые на экране данные будут также добавлены к заданному файлу. Это может быть очень полезно для целей отладки программы. Утилиту tee можно блокировать из командной строки командой notee. Повторный запуск команды tee снова включит журналирование. Если при этом параметр для команды tee не указан, то будет использоваться предыдущий файл. Следует учесть, что команда tee будет записывать результаты в файл после каждой выполненной команды, как раз перед появлением командной строки для ввода очередной команды.

При помощи опции --pager[=...] стал возможным просмотр или поиск результатов в интерактивном режиме с помощью Unix-программ less, more или иных подобных. Если явно не указать аргумент в этом параметре, клиент mysql будет искать переменную окружения PAGER и установит значение pager. Программу pager также можно запустить из интерактивной командной строки командой pager и остановить командой nopager. Команда может принимать аргумент, который является необязательным; pager будет установлена в значение этого аргумента.. Команда pager может быть вызвана и без аргумента, но это требует использования опции --pager или соответствующей установки по умолчанию стандартного вывода stdout. Команда pager работает только в Unix, поскольку использует функцию popen(), отсутствующую в Windows. Вместо этого в Windows можно использовать параметр tee, хотя в ряде ситуаций это менее удобно, чем применение команды pager.

Несколько советов касательно команды pager:

  • Ее можно использовать для записи в файл:
    mysql> pager cat > /tmp/log.txt
    и результаты будут направлены только в файл. Вызываемые командой pager программы могут принимать любые допустимые опции:
    mysql> pager less -n -i -S
  • Обратите особое внимание на опцию -S в вышеприведенном примере. Она может быть очень полезна при просмотре результатов. Попробуйте применить ее с горизонтальным выводом (завершайте команды символами '\g', or ';') и с вертикальным (в конце команд - '\G'). Очень громоздкие результаты вывода иногда трудно бывает прочесть с экрана, в этом случае команда less с опцией -S позволит просмотреть результаты в интерактивном режиме слева направо, при этом при появлении строк с длиной больше, чем ширина экрана, их вывод будет продолжен вывод с новой строки. Вывод данных в таких случаях получается более удобочитаемым. При интерактивном вызове команды less с опцией '-S' можно переключать режим ее работы (включено/выключено) из командной строки. Чтобы получить дополнительную информацию относительно less, обращайтесь к описанию команды 'h'.
  • В заключение отметим (если вы этого еще не поняли из предыдущих примеров :), что существует возможность комбинировать очень сложные способы обработки результатов. Так, в следующем примере результаты будут посланы в два различных каталога, смонтированных на двух различных жестких дисках в /dr1 and /dr2, и, несмотря на это, результаты можно увидеть на экране посредством команды less:
    mysql> pager cat | tee /dr1/tmp/res.txt | \
       tee /dr2/tmp/res2.txt | less -n -i -S

Приведенные выше функции можно тоже комбинировать: запустив tee и установив pager в less, можно просматривать результаты с помощью Unix-команды less и при этом одновременно производить запись в файл. Разница между служебной Unix-утилитой tee, используемой в программе pager, и встроенной в клиент mysql командой tee заключается в том, что встроенная команда tee работает даже в том случае, если в Unix утилита tee недоступна. Встроенная команда tee также ведет запись всего, что выводится на экран, тогда как утилита Unix tee, используемая с pager, не делает этого в достаточном объеме. Последнее, но тем не менее важное обстоятельство состоит в том, что интерактивная команда tee более удобна для переключения режимов работы включено/выключено, если при записи в файл иногда возникает необходимость отключить эту функцию.

Начиная с версии MySQL 4.0.2 можно изменить формат приглашения в командной строке клиента mysql.

Возможны следующие опции приглашения:
Опция | Описание
\v | версия mysqld
\d | имя используемой базы данных
\h | имя хоста, к которому производится подсоединение
\p | номер порта, через который производится подсоединение
\u | имя пользователя
\U | полный адрес username@host
\\ | обратный слэш `\'
\n | символ новой строки
\t | табуляция
\ | пробел
\_ | пробел с подчеркиванием
\R | время по военному часовому поясу (0-23)
\r | время по стандартному часовому поясу (1-12)
\m | минуты
\y | два разряда года
\Y | четыре разряда года
\D | полный формат даты
\s | секунды
\w | день недели в трехбуквенном формате (Mon, Tue, ...)
\P | Время до полудня/после полудня (am/pm)
\o | месяц в числовом формате
\O | месяц в трехбуквенном формате (Jan, Feb, ...)
\c | Счетчик, подсчитывающий количество вводимых команд

Символ `\' за которым следует любая другая буква, просто дополняет эту букву.

Установить параметры приглашения можно следующими способами:

В переменных окружения
Можно установить переменную окружения MYSQL_PS1 для строки приглашения. Например:
shell> export MYSQL_PS1="(\u@\h) [\d]> "
`my.cnf'
`.my.cnf'
Можно установить опцию prompt в любом конфигурационном файле MySQL в группе mysql. Например:
[mysql]
prompt=(\u@\h) [\d]>\_
В командной строке
Можно установить опцию --prompt из командной строки утилиты mysql. Например:
shell> mysql --prompt="(\u@\h) [\d]> "
(user@host) [database]>
В интерактивном режиме
Можно также использовать команду prompt (или \R) для изменения настроек приглашения в интерактивном режиме. Например:
mysql> prompt (\u@\h) [\d]>\_
PROMPT set to '(\u@\h) [\d]>\_'

(user@host) [database]>
(user@host) [database]> prompt
Возвращение к исходным (по умолчанию) настройкам PROMPT в утилите mysql>
mysql>

4.8.3 mysqladmin, Администрирование MySQL-сервера.

Утилита для выполнения административных операций. Ее синтаксис:

shell> mysqladmin [ПАРАМЕТРЫ] command [command-option] command ...

Список опций, поддерживаемых вашей конкретной версией mysqladmin, можно получить, выполнив команду mysqladmin --help.

Текущая версия mysqladmin поддерживает следующие команды:

create databasename
Создать новую базу данных.
drop databasename
Удалить базу данных и все ее таблицы.
extended-status
Выдает расширенный отчет о состоянии сервера (более полный, чем при команде status )
flush-hosts
Сбросить и перезагрузить хосты.
flush-logs
Сбросить на диск и переоткрыть все журналы.
flush-tables
Закрыть все открытые таблицы.
flush-privileges
Перечитать таблицы привилегий.
kill id,id,...
Завершить потоки mysql с указанными thread-id.
password
Установить новый пароль для сервера баз данных. Изменить старый пароль на новый.
ping
Проверить, работает ли сервер mysqld.
processlist
Показать список активных потоков на сервере.
reload
Перезагрузить таблицы привилегий.
refresh
Выполнить все табличные операции, находящиеся в буфере, закрыть и открыть заново все системные журналы.
shutdown
Завершить работу сервера баз данных.
slave-start
Запустить подчиненный дублирующий поток.
slave-stop
Остановить подчиненный дублирующий поток.
status
Выдает краткий отчет о состоянии сервера.
variables
Вывести доступные для использования переменные.
version
Вывести данные о версии сервера.

Все команды могут сокращаться до их уникальных префиксов. Например:

shell> mysqladmin proc stat
+----+-------+-----------+----+-------------+------+-------+------+
| Id | User  | Host      | db | Command     | Time | State | Info |
+----+-------+-----------+----+-------------+------+-------+------+
| 6  | monty | localhost |    | 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

Результат команды mysqladmin status выводится в виде следующих столбцов:

Столбец | Описание
Uptime | Количество секунд с момента запуска MySQL-сервера.
Threads | Количество активных потоков (клиентов).
Questions | Количество вопросов от клиентов с момента запуска программы mysqld.
Slow queries | Количество запросов, потребовавших большее количество секунд, чем установлено в конфигурации ключом long_query_time. See section 4.9.5 Журнал медленных запросов.
Opens | Количество таблиц, открытых программой mysqld.
Flush table | Количество выполненных команд flush ..., refresh, reload.
Open tables | Количество таблиц, открытых в данное время.
Memory in use | Память, используемая непосредственно программой mysqld (доступно только в случае компиляции MySQL с установленным значением --with-debug=full).
Max memory used | Максимальный объем памяти, использованный непосредственно программой mysqld (доступно только в случае компиляции MySQL с установленным значением --with-debug=full).

При выполнении mysqladmin shutdown через сокет (другими словами, через компьютер с запущенным mysqld) mysqladmin будет ожидать, пока на сервере MySQL не будет удален файл pid-file (в котором содержится идентификатор процесса `pid' запущенного сервера) чтобы убедиться, что сервер остановлен должным образом.

4.8.4 Использование mysqlcheck для сопровождения и аварийного восстановления таблиц.

Начиная с версии MySQL 3.23.38 можно применять новый инструмент для проверки и восстановления MyISAM-таблиц. Отличие mysqlcheck от myisamchk состоит в том, что утилита mysqlcheck должна использоваться при работающем сервере mysqld, в то время как myisamchk - при остановленном. Преимущество же заключается в том, что теперь не нужно останавливать сервер для проверки или восстановления таблиц.

Утилита mysqlcheck использует соответствующие команды MySQL-сервера CHECK, REPAIR, ANALYZE и OPTIMIZE удобным для пользователя образом.

Существует три альтернативных способа запуска mysqlcheck:

shell> mysqlcheck [OPTIONS] database [tables]
shell> mysqlcheck [OPTIONS] --databases DB1 [DB2 DB3...]
shell> mysqlcheck [OPTIONS] --all-databases

Таким образом, утилита может использоваться подобно mysqldump по отношению к выбранным базам данных и таблицам.

В сравнении с другими клиентами утилита mysqlcheck имеет следующую отличительную особенность: установка поведения по умолчанию, (проверка таблиц, -с), может быть изменена путем переименования исполняемого файла утилиты. Итак, чтобы получить инструмент, восстанавливающий таблицы по умолчанию, просто скопируйте mysqlcheck с новым именем, mysqlrepair, или, наоборот, сделайте символьную ссылку на mysqlrepair и обозначьте ее как mysqlrepair. Если теперь запустить mysqlrepair, то утилита по умолчанию будет восстанавливать таблицы.

Для изменения поведения mysqlcheck по умолчанию можно использовать следующие обозначения:

mysqlrepair: Значение по умолчанию будет -r
mysqlanalyze: Значение по умолчанию будет -a
mysqloptimize: Значение по умолчанию будет -o

Ниже приведены возможные опции для mysqlcheck. Какие из них поддерживает ваша версия, можно проверить с помощью команды mysqlcheck --help.

-A, --all-databases
Проверить все базы данных. Аналогична опции --databases, если указать все базы данных.
-1, --all-in-1
Вместо выполнения запросов для каждой таблицы в отдельности выполнить все запросы в одном отдельно для каждой таблицы. Имена таблиц будут представлены в виде списка имен, разделенных запятой.
-a, --analyze
Анализировать данные таблицы.
--auto-repair
Если проверенная таблица повреждена, автоматически восстановить ее. Исправления будут произведены после проверки всех таблиц, если были обнаружены повреждения.
-#, --debug=...
Выводит информацию журнала отладки. Часто используется следующий набор параметров: 'd:t:o,filename'
--character-sets-dir=...
Директория, где находятся установки символов.
-c, --check
Проверить таблицу на наличие ошибок.
-C, --check-only-changed
Проверить только таблицы, измененные со времени последней проверки или некорректно закрытые.
--compress
Использовать сжатие данных в протоколе сервер/клиент.
-?, --help
Вывести данную вспомогательную информацию и выйти из программы.
-B, --databases
Проверить несколько баз данных. Обратите внимание на разницу в использовании: в этом случае таблицы не указываются. Все имена аргументов рассматриваются как имена баз данных.
--default-character-set=...
Установить набор символов по умолчанию.
-F, --fast
Проверить только базы данных, которые не были закрыты должным образом.
-f, --force
Продолжать даже при получении ошибки SQL.
-e, --extended
При использовании данного параметра совместно с CHECK TABLE можно быть на 100 процентов быть уверенным в целостности таблицы, хотя это и займет много времени. Если же использовать этот параметр с REPAIR TABLE, запустится расширенное восстановление таблицы, которое может потребовать не только длительного времени выполнения, но и привнесет также массу ненужных строк!
-h, --host=...
Подключиться к хосту.
-m, --medium-check
Быстрее, чем --extended-check, но находит только 99,99 процентов всех ошибок. Для большинства случаев этот вариант вполне подходит.
-o, --optimize
Оптимизировать таблицу.
-p, --password[=...]
Используемый пароль при подключении к серверу. Если пароль не указан, у пользователя запрашивается пароль с терминала.
-P, --port=...
Номер порта, используемого для подключения по TCP/IP.
--protocol=(TCP | SOCKET | PIPE | MEMORY)
Для указания протокола соединения, который надлежит использовать. Новшество в MySQL 4.1.0.
-q, --quick
При использовании данной опции совместно с CHECK TABLE предотвращается сканирование строк для корректировки неправильных связей. Это наиболее быстрый метод проверки. Если же использовать этот параметр с REPAIR TABLE, программа попытается восстановить только систему индексов. Это наиболее быстрый метод восстановления таблицы.
-r, --repair
Может исправить почти все, за исключением уникальных ключей, имеющих дубликаты.
-s, --silent
Выводить только сообщения об ошибках.
-S, --socket=...
Файл сокета, используемый для подсоединения.
--tables
Перекрывает опцию --databases (-B).
-u, --user=#
Имя пользователя MySQL, если этот пользователь в данное время не является активным.
-v, --verbose
Вывести информацию о различных этапах.
-V, --version
Вывести информацию о версии и выйти из программы.

4.8.5 mysqldump, Получение дампов данных и структуры таблицы

Данная утилита позволяет получить дамп (``моментальный снимок'') содержимого базы данных или совокупности баз для создания резервной копии или пересылки данных на другой SQL-сервер баз данных (не обязательно MySQL-сервер). Дамп будет содержать набор команд SQL для создания и/или заполнения таблиц.

Если же резервная копия создается на сервере, то вместо описываемой утилиты следует использовать mysqlhotcopy. См.раздел See section 4.8.6 mysqlhotcopy, Копирование баз данных и таблиц MySQL.

shell> mysqldump [OPTIONS] database [tables]
или  mysqldump [OPTIONS] --databases [OPTIONS] DB1 [DB2 DB3...]
или  mysqldump [OPTIONS] --all-databases [OPTIONS]

Если не указывать имена таблиц или использовать параметры --databases или --all-databases, то будет получен дамп базы данных в целом (соответственно - всех баз данных).

Перечень опций, поддерживаемых вашей конкретной версией утилиты mysqldump, можно получить, выполнив команду mysqldump --help.

Следует иметь в виду, что утилита mysqldump, используемая без опций --quick или --opt, перед тем, как сделать дамп результата выборки информации, загрузит весь результат в память. Это может создать проблемы при получении дампа большой базы данных.

Учтите, что не следует применять параметры --opt или -e, если вы собираетесь использовать для получения дампа новую копию программы mysqldump, а затем воспроизводить его на очень старом MySQL-сервере.

Утилита mysqldump поддерживает следующие опции:

--add-locks
Добавить команды LOCK TABLES перед выполнением и UNLOCK TABLE после выполнения каждого дампа таблицы (для ускорения доступа к MySQL).
--add-drop-table
Добавить команду DROP TABLE перед каждой командой CREATE TABLE.
-A, --all-databases
Произвести дамп всех баз данных. Аналогично опции --databases с указанием всех баз данных.
-a, --all
Включить все опции создания объектов, специфичные для MySQL.
--allow-keywords
Разрешить создавать имена столбцов, которые совпадают с ключевыми словами. Отсутствие конфликтов обеспечивается прибавлением имени таблицы в качестве префикса к имени каждого столбца.
-c, --complete-insert
Использовать полные команды INSERT (с именами столбцов).
-C, --compress
Использовать сжатие всей информации между клиентом и сервером, если они оба поддерживают сжатие.
-B, --databases
Выполнить дамп нескольких баз данных. Обратите внимание на разницу в использовании: в этом случае таблицы не указываются. Все имена аргументов рассматриваются как имена баз данных. Оператор USE db_name; включается в вывод перед каждой новой базой данных.
--delayed
Использовать команду INSERT DELAYED при вставке строк.
-e, --extended-insert
Использовать команду INSERT с новым многострочным синтаксисом (повышает компактность и быстродействие операторов ввода).
-#, --debug[=option_string]
Отслеживать прохождение программы (для отладки).
--help
Вывести справочную информацию и выйти из программы.
--fields-terminated-by=...
--fields-enclosed-by=...
--fields-optionally-enclosed-by=...
--fields-escaped-by=...
--lines-terminated-by=...
Эти опции используются совместно с параметром -T и имеют то же самое значение, что и соответствующие операторы для LOAD DATA INFILE. См. раздел See section 6.4.9 Синтаксис оператора LOAD DATA INFILE.
-F, --flush-logs
Записать на диск данные системного журнала из буфера MySQL-сервера перед началом выполнения дампа.
-f, --force,
Продолжать даже при получении ошибки SQL при выполнении дампа таблицы.
-h, --host=..
Выполнить дамп данных MySQL сервера на указанном хосте. Значение хоста по умолчанию - localhost.
-l, --lock-tables.
Заблокировать все таблицы перед началом выполнения дампа. Таблицы блокируются оператором READ LOCAL, чтобы разрешить параллельные записи для MyISAM-таблиц. Следует отметить, что при выполнении дампа совокупности баз данных опция --lock-tables блокирует таблицы каждой базы по отдельности. Таким образом, использование этого параметра не гарантирует, что таблицы будут логически непротиворечивы в пределах этих баз данных. В различных базах данных при выполнении дампа таблицы могут находиться в совершенно разных состояниях.
-K, --disable-keys
Добавляет выражение /*!40000 ALTER TABLE tb_name DISABLE KEYS */; и /*!40000 ALTER TABLE tb_name ENABLE KEYS */; в выводе результата. Это ускорит загрузку данных на сервер MySQL 4.0, так как индексы создаются после внесения всех данных.
-n, --no-create-db
В выводе результата выражение CREATE DATABASE /*!32312 IF NOT EXISTS*/ db_name; будет отсутствовать. Данная строка будет добавлена в любом случае при использовании опций --databases или --all-databases.
-t, --no-create-info
Не записывать информацию о создании таблицы (команда CREATE TABLE).
-d, --no-data
Не записывать информацию из строк таблицы. Это очень полезно для получения дампа структуры таблицы!
--opt
То же, что и --quick --add-drop-table --add-locks --extended-insert --lock-tables. Должно дать наиболее быстрый дамп для чтения на MySQL-сервере.
-pyour_pass, --password[=your_pass]
Используемый пароль при подключении к серверу. Если аргумент =your_pass не введен, mysqldump предложит ввести пароль.
-P port_num, --port=port_num
Номер порта TCP/IP, используемого для подключения к хосту.
--protocol=(TCP | SOCKET | PIPE | MEMORY)
Для указания протокола соединения, который надлежит использовать. Новшество в MySQL 4.1.0.
-q, --quick
Выводить дамп непосредственно на стандартный вывод stdout без буферизации запроса. Для этого используется функция mysql_use_result().
-Q, --quote-names
Взять в кавычки имена таблиц и столбцов без символов ``'.
-r, --result-file=...
Прямой вывод указанного файла. Этот опцию следует использовать в MS DOS, так как она предотвращает преобразование символа новой строки '\n' в последовательность '\n\r' (новая строка + возврат каретки).
--single-transaction
Данная опция выдает SQL-команду BEGIN перед выполнением дампа данных с сервера. Наиболее часто используется с InnoDB-таблицамии и уровнем изоляции транзакций READ_COMMITTED, так как именно в этом режиме можно получить дамп с непротиворечивым состоянием базы данных после выполнения команды BEGIN без блокирования каких-либо приложений. Используя эту опцию, необходимо помнить, что при выполнении дампа только транзакционные таблицы будут находиться в непротиворечивом состоянии, т.е. некоторые MyISAM- или HEAP-таблицы при использовании данной опции могут все же изменить свое состояние. Опция --single-transaction добавлена в версии 4.0.2. Она является взаимоисключающей по отношению к опции --lock-tables, так как команда LOCK TABLES уже принимает открытую транзакцию.
-S /path/to/socket, --socket=/path/to/socket
Файл сокета для подсоединения к localhost (значение хоста по умолчанию).
--tables
Перекрывает параметр --databases (-B).
-T, --tab=path-to-some-directory
Для каждой заданной таблицы создает файл a `table_name.sql', содержащий SQL CREATE команды для создания таблицы, и файл `table_name.txt' с данными таблицы. Файл `.txt' имеет формат в соответствии с параметрами --fields-xxx и --lines--xxx. Примечание: Этот параметр работает только при условии, что утилита mysqldump запущена на том же компьютере, что и демон mysqld, причем пользователь/группа, запустившие данный поток mysqld (обычно это пользователь mysql и группа mysql), должны иметь право создавать/записывать файл по указанному адресу.
-u user_name, --user=user_name
Имя пользователя MySQL-сервера, используемое при подключении к серверу. Значением по умолчанию является имя пользователя Unix.
-O var=option, --set-variable var=option
Установить значения переменных. Доступные для использования переменные перечислены ниже. В MySQL 4.0 просто используйте --var=option.
-v, --verbose
Расширенный режим вывода. Вывод более детальной информации о работе программы.
-V, --version
Вывести информацию о версии и выйти из программы.
-w, --where='where-condition'
Выполнить дамп только выбранных записей. Обратите внимание, что кавычки обязательны.
"--where=user='jimf'" "-wuserid>1" "-wuserid<1"
-X, --xml
Представляет дамп базы данных в виде XML.
-x, --first-slave
Блокирует все таблицы во всех базах данных.
-O net_buffer_length=#, where # < 16M
При создании многострочных операторов ввода (как и в случаях применения параметров --extended-insert или --opt) утилита mysqldump будет создавать строки длиной вплоть до указанной в net_buffer_length. При увеличении значения этой переменной необходимо также убедиться в том, что в MySQL-сервере для переменной max_allowed_packet указано значение больше, чем величина net_buffer_length.

Чаще всего утилита mysqldump используется для получения резервной копии всех баз данных. See section 4.4.1 Резервное копирование баз данных.

mysqldump --opt database > backup-file.sql

Можно, наоборот, прочитать этот файл на MySQL-сервере посредством команды:

mysql database < backup-file.sql

или

mysql -e "source /patch-to-backup/backup-file.sql" database

Данная утилита достаточно часто используется и для переноса информации из базы данных на другой MySQL-сервер:

mysqldump --opt database | mysql --host=remote-host -C database

Вполне возможно получить дамп нескольких баз данных с помощью одной команды:

mysqldump --databases database1 [database2 ...] > my_databases.sql

Если необходим дамп всех баз данных, можно использовать:

mysqldump --all-databases > all_databases.sql

4.8.6 mysqlhotcopy, Копирование баз данных и таблиц MySQL

Утилита mysqlhotcopy представляет собой Perl-сценарий, использующий SQL-команды LOCK TABLES, FLUSH TABLES и Unix-утилиты cp или scp для быстрого получения резервной копии базы данных. Пожалуй, это наиболее быстрый способ копирования баз данных или таблиц, но он может работать только на том же компьютере, где расположены каталоги копируемой базы данных.

mysqlhotcopy db_name [/path/to/new_directory]
mysqlhotcopy db_name_1 ... db_name_n /path/to/new_directory
mysqlhotcopy db_name./regex/

Утилита mysqlhotcopy поддерживает следующие опции:

-?, --help
Показать окно справки и выйти из программы.
-u, --user=#
Имя пользователя для входа в базу данных.
-p, --password=#
Используемый пароль при подсоединении к серверу.
-P, --port=#
Номер порта, используемого для подсоединения к локальному серверу.
-S, --socket=#
Номер сокета, используемого для подсоединения к локальному серверу.
--allowold
Не делать прерывания, если объект уже существует (переименовать в it_old).
--keepold
Не удалять предыдущий результат (только что переименованный) после выполнения команды.
--noindices
Не включать обширные индексные файлы в копию, чтобы сделать дубликат меньше по размеру и более быстрым. Индексы можно реконструировать позже с помощью команды myisamchk -rq.
--method=#
Метод копирования (cp или scp).
-q, --quiet
Выводить только сообщения об ошибках.
--debug
Разрешить отладку.
-n, --dryrun
Сообщать о действиях без их выполнения.
--regexp=#
Копировать все базы данных с именами, встречающимися в функции regexp.
--suffix=#
Суффикс для имен скопированных баз данных.
--checkpoint=#
Внести проверочную запись в предусмотренную таблицу базы данных.
--flushlog
Записать на диск данные журналов из буфера, как только все таблицы заблокируются.
--tmpdir=#
Временная директория (вместо `/tmp').

Более полное описание данного сценария можно посмотреть в документации по языку программирования Perl.

Сценарий mysqlhotcopy берет информацию для групп [client] и [mysqlhotcopy] из файлов опций.

Для выполнения программы mysqlhotcopy необходимы доступ для записи в директорию, куда будет помещена копия, и привилегия выполнения команды SELECT для копируемых таблиц и команды RELOAD для MySQL-сервера (чтобы выполнить FLUSH TABLES).

4.8.7 mysqlimport, импорт данных из текстовых файлов

Утилита mysqlimport обеспечивает интерфейс командной строки для SQL-оператора LOAD DATA INFILE. Большинство параметров mysqlimport полностью соответствует аналогичным параметрам для оператора LOAD DATA INFILE. See section 6.4.9 Синтаксис оператора LOAD DATA INFILE.

Утилита mysqlimport вызывается следующим образом:

shell> mysqlimport [параметры] database textfile1 [textfile2 ...]

Для каждого текстового файла, указанного в командной строке, mysqlimport удаляет расширение в каждом имени файла и использует его, чтобы определить, в какую таблицу занести содержимое. Например, файлы с именами `patient.txt', `patient.text' и `patient' должны быть все занесены в таблицу с именем `patient'.

Утилита mysqlimport поддерживает следующие опции:

-c, --columns=...
Эта опция принимает в качестве аргумента список разделенных запятыми имен полей. Данный список полей используется для создания соответствующей команды LOAD DATA INFILE, которая затем посылается в MySQL. See section 6.4.9 Синтаксис оператора LOAD DATA INFILE.
-C, --compress
Использовать компрессию в связи между клиентом и сервером, если они оба поддерживают сжатие.
-#, --debug[=option_string]
Отслеживать прохождение программы (для отладки).
-d, --delete
Удалить данные из таблицы перед импортированием текстового файла.
--fields-terminated-by=...
--fields-enclosed-by=...
--fields-optionally-enclosed-by=...
--fields-escaped-by=...
--lines-terminated-by=...
Эти опции аналогичны соответствующим операторам для LOAD DATA INFILE. See section 6.4.9 Синтаксис оператора LOAD DATA INFILE.
-f, --force
Игнорировать ошибки. Например, если таблица для текстового файла не существует, продолжать обработку остающихся файлов. Без параметра --force утилита mysqlimport прекращает работу при отсутствии таблицы.
--help
Вывести справочную информацию и выйти из программы.
-h host_name, --host=host_name
Импортировать данные в MySQL-сервер на указанном хосте. Значение хоста по умолчанию - localhost.
-i, --ignore
См. описание для параметра --replace.
-l, --lock-tables
Заблокировать все таблицы для записи перед обработкой любых текстовых файлов. Это обеспечивает синхронизацию всех таблиц на сервере.
-L, --local
Читать входящие файлы из клиента. По умолчанию предполагается, что текстовые файлы расположены на сервере при подсоединении к localhost (значение хоста по умолчанию).
-pyour_pass, --password[=your_pass]
Используемый пароль при подключении к серверу. Если аргумент =your_pass не введен, mysqlimport предложит ввести пароль.
-P port_num, --port=port_num
Номер порта TCP/IP, используемого для подсоединения к хосту.
--protocol=(TCP | SOCKET | PIPE | MEMORY)
Для указания протокола соединения, который надлежит использовать. Новшество в MySQL 4.1.0.
-r, --replace
Опции --replace и --ignore управляют обработкой поступающих на вход записей, которые дублируют имеющиеся записи по значениям уникальных ключей. Если задано значение --replace, новые строки заменяют существующие с тем же самым значением уникального ключа. Если задано значение --ignore, входные строки, которые дублируют существующую строку по значению уникального ключа, пропускаются. Если же ни одна из опций не задана, то при обнаружении ключа-дубликата возникает ошибка и остаток текстового файла игнорируется.
-s, --silent
Режим молчания. Выводить только сообщения об ошибках.
-S /path/to/socket, --socket=/path/to/socket
Файл сокета для подсоединения к localhost (значение хоста по умолчанию).
-u user_name, --user=user_name
Имя пользователя MySQL-сервера, используемое при подсоединении к серверу. Значением по умолчанию является имя для входа в Unix.
-v, --verbose
Расширенный режим вывода. Вывод более детальной информации о работе программы.
-V, --version
Вывести информацию о версии и выйти из программы.

Ниже приведен пример листинга программы, использующей утилиту mysqlimport:

$ mysql --version
mysql  Ver 9.33 Distrib 3.22.25, for pc-linux-gnu (i686)
$ uname -a
Linux xxx.com 2.2.5-15 #1 Mon Apr 19 22:21:09 EDT 1999 i586 unknown
$ mysql -e 'CREATE TABLE imptest(id INT, n VARCHAR(30))' test
$ ed
a
100     Max Sydow
101     Count Dracula
.
w imptest.txt
32
q
$ od -c imptest.txt
0000000   1   0   0  \t   M   a   x       S   y   d   o   w  \n   1   0
0000020   1  \t   C   o   u   n   t       D   r   a   c   u   l   a  \n
0000040
$ mysqlimport --local test imptest.txt
test.imptest: Records: 2  Deleted: 0  Skipped: 0  Warnings: 0
$ mysql -e 'SELECT * FROM imptest' test
+------+---------------+
| id   | n             |
+------+---------------+
|  100 | Max Sydow     |
|  101 | Count Dracula |
+------+---------------+

4.8.8 mysqlshow, просмотр баз данных, таблиц и столбцов

Утилита mysqlshow позволяет кратко ознакомиться с существующими базами данных, их таблицами и столбцами таблиц.

Аналогичную информацию можно получить с помощью программы mysql, используя команду SHOW. See section 4.5.6 Синтаксис команды SHOW.

Утилита mysqlshow вызывается следующим образом:

shell> mysqlshow [ПАРАМЕТРЫ] [database [table [column]]]
  • Если имя базы данных не указано, то выдается список всех существующих баз данных.
  • Если не указана таблица - показываются все таблицы, найденные в этой базе данных
  • Если не задан столбец - показываются все найденные в таблице столбцы и представленные в виде столбцов данные.

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

Если последний аргумент содержит в себе шаблонные символы (*, ?, % или _) процессора или SQL, то будут представлены только данные, совпадающие с шаблоном. Если имя базы данных содержит подчеркивание, то оно должно быть экранировано обратным слешом (некоторые оболочки в Unix востребуют два обратных слеша) для того, чтобы получить корректные имена. `*' корвертируются в `%' и `?' - в `_'.

Это может вызвать путаницу при попытке просмотреть столбцы таблицы с символом _, так как в таком случае mysqlshow покажет только имена таблиц, совпадающие с шаблоном. Ситуацию можно легко исправить добавлением дополнительного символа % в конец командной строки (как отдельного аргумента).

4.8.9 mysql_config, Получение опций компиляции для компиляции клиентских программ

mysql_config дает полезную информацию о том, как компилировать ваши клиентские программы.

mysql_config поддерживает такие опции:

--cflags
Опции компилятора для поиска включаемых файлов
--libs
Библиотеки и опции, необходимые для линкования с клиентской библиотекой.
--socket
Имя сокета по умолчанию, определенное, когда конфигурировался MySQL.
--port
Номер порта по умолчанию, определенный, когда конфигурировался MySQL.
--version
Номер версии и версия для поставки MySQL.
--libmysqld-libs
Библиотеки и опции, необходимые для линкования с библиотекой встраиваемого сервера.

Если вы выполняете mysql_config без каких-либо параметров, вы получите все опции, которые он поддерживает плюс значение этих опций:

shell> mysql_config
sage: /usr/local/mysql/bin/mysql_config [OPTIONS]
Options:
        --cflags         [-I'/usr/local/mysql/include/mysql']
        --libs           [-L'/usr/local/mysql/lib/mysql' -lmysqlclient -lz -lcrypt -lnsl -lm -L/usr/lib -lssl -lcrypto]
        --socket         [/tmp/mysql.sock]
        --port           [3306]
        --version        [4.0.8-gamma]
        --libmysqld-libs [ -L'/usr/local/mysql/lib/mysql' -lmysqld -lpthread -lz -lcrypt -lnsl -lm  -lpthread  -lrt]

Вы можете это использовать, чтобы скопмилировать клиента MySQL таким образом:

CFG=/usr/local/mysql/bin/mysql_config
sh -c "gcc -o progname `$CFG --cflags` progname.c `$CFG --libs`"

4.8.10 perror, разъяснение кодов ошибок

Для большинства системных ошибок, помимо внутреннего текстового сообщения MySQL, можно также выводить номер кода системной ошибки в одном из следующих стилей: message ... (errno: #) или message ... (Errcode: #).

Выяснить, что данный код ошибки означает, можно либо путем изучения документации на данную систему, либо воспользовавшись возможностями утилиты perror.

perror выводит описание кода системной ошибки или код ошибки обработчика таблиц MyISAM/ISAM.

perror вызывается следующим образом:

shell> perror [ПАРАМЕТРЫ] [ERRORCODE [ERRORCODE...]]

Пример:

shell> perror 13 64
Error code 13: Доступ запрещен
Error code 64: Компьютер не находится в сети

Следует учитывать, что сообщения об ошибках в большинстве своем являются системно-зависимыми!

4.8.11 Как запускать SQL-команды из текстового файла

Обычно клиент mysql используется в интерактивном режиме, например, следующим образом:

shell> mysql database

Однако вполне можно поместить SQL команды в текстовый файл и указать mysql считывать входные данные из этого файла. Для этого необходимо создать текстовый файл text_file, содержащий команды, которые предстоит выполнить. Затем запускаем mysql как показано ниже:

shell> mysql database < text_file

Можно также запустить текстовый файл с командой USE db_name. В этом случае указывать имя базы данных в командной строке не обязательно:

shell> mysql < text_file

Если программа mysql уже работает, можно запустить файл с SQL-сценарием, используя команду source:

mysql> source filename;

Более подробная информация по пакетному режиму работы находится в разделе See section 3.6 Использование mysql в пакетном режиме.

4.9 Файлы журналов MySQL

В MySQL имеется несколько журналов, позволяющих узнать, что происходит внутри mysqld:

Журнал | Описание
Журнал ошибок | В нем хранятся ошибки запуска, работы или завершения работы mysqld.
Журнал isam | В нем хранится информация обо всех изменениях таблиц ISAM. Используется только при отладке кода isam.
Общий журнал запросов | В нем хранится информация об установленных соединениях и выполненных запросах.
Журнал обновлений log | В нем хранятся все команды, меняющие данные; в скором времени выйдет из употребления
Бинарный журнал обновлений | В нем хранятся все меняющие что-либо команды. Используется для репликации
Журнал медленных запросов | В нем хранятся все запросы, на выполнение которых ушло больше времени, чем указано в переменной long_query_time (или запросы, не использовавшие индексов).

Все файлы журналов хранятся в каталоге с данными mysqld. С помощью команды FLUSH LOGS можно заставить mysqld открыть файлы журналов снова (или - в некоторых случаях - переключиться на новый файл). See section 4.5.3 Синтаксис команды FLUSH.

4.9.1 Журнал ошибок

Журнал ошибок содержит информацию о том, когда запускается и останавливается mysqld, а также все критические ошибки, обнаруженные в процессе работы.

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

Все ошибки mysqld записывает в stderr, который сценарий safe_mysqld перенаправляет в файл с именем 'hostname'.err (в Windows mysqld сохраняет его в каталоге `\mysql\data\mysql.err').

В некоторых ОС в журнал включается распечатка части стека погибшего mysqld. С помощью этой информации можно определить причину сбоя (see section D.1.4 Использование трассировки стека).

Начиная с MySQL 4.0.10 можно указать, где именно mysqld должен сохранять журнал ошибок, с помощью опции --log-error[=filename]. Если имя файла не задается, то тогда mysqld будет использовать mysql-data-dir/'hostname'.err на Unix и `\mysql\data\mysql.err' на windows.

Если вы выполняете FLUSH LOGS старый файл будет сохранен с префиксом --old и mysqld создаст новый пустой журнал.

На старых версиях MySQL журнал ошибок велся скриптом mysqld_safe, который перенаправлял вывод в файл 'hostname'.err. В старых версиях можно было изменить имя этого файла опцией --err-log=filename.

Если вы не указываете --log-error или используете опцию --console, то ошибки будут выводиться на stderr (на терминал).

На Windows вывод всегда пишется в .err-файл если --console не была указана.

4.9.2 Общий журнал запросов

Если вы хотите знать обо всем, что происходит с mysqld, нужно запустить систему с ключом --log[=file]. После этого информация обо всех соединениях и запросах будет записываться в файл журнала (по умолчанию ему дается имя 'hostname'.log). Этот журнал может оказаться полезным, если вы подозреваете наличие ошибки в клиентском ПО и хотите выяснить, что, по мнению mysqld, клиент передал базе.

Старые версии скрипта mysql.server (с MySQL 3.23.4 по 3.23.8) передавали safe_mysqld опцию --log (включить общий журнал запросов). Если вам нужна большая производительность при запуске MySQL в промышленной эксплуатации, вы можете удалить опцию --log из mysql.server или поменять ее на --log-bin. See section 4.9.4 Бинарный журнал обновлений.

Записи в журнал заносятся по мере получения mysqld запросов. Порядок их занесения может отличаться от порядка выполнения команд. В этом и заключается основное отличие данного журнала от журналов обновлений и бинарных журналов, в которые информация заносится по мере выполнения запросов, но до отмены блокировок.

4.9.3 Журнал обновлений (update)

Обратите внимание: журнал обновлений (update) заменен бинарным журналом (binary) (see section 4.9.4 Бинарный журнал обновлений. С этим журналом можно производить те же операции, что и с журналом обновлений.

При запуске с ключом --log-update[=file_name] mysqld создает журнал, в который заносятся все команды SQL, обновляющие данные. Если имя файла не задано, по умолчанию ему присваивается имя хоста. Если файлу присвоено имя, не содержащее пути доступа к нему, этот файл сохраняется в каталоге с данными. Если у имени `file_name' нет расширения, mysqld даст файлу примерно такое имя: `file_name.###', где ### - номер, увеличивающийся при каждом выполнении команд mysqladmin refresh, mysqladmin flush-logs, FLUSH LOGS или при перезапуске сервера.

Обратите внимание: чтобы вышеописанная схема могла работать, нельзя самостоятельно создавать файлы с тем же именем, что и у журнала обновлений, а также с некоторыми расширениями, которые могут быть восприняты как номер, в каталоге, использующемся для хранения этого журнала!

При запуске с ключами --log или -l mysqld создает общий журнал в файле с именем `hostname.log', причем перезапуски и обновления не приводят к созданию нового файла журнала (хотя существующий при таких операциях закрывается и затем открывается вновь). В таком случае скопировать его (в Unix) можно так:

mv hostname.log hostname-old.log
mysqladmin flush-logs
cp hostname-old.log to-backup-directory
rm hostname-old.log

Журнал обновлений работает избирательно - в него попадают только те команды, которые действительно обновляют данные. Команда UPDATE или DELETE, выражение WHERE которой не находит совпадающих строк, в журнал не заносится - как и команды UPDATE, присваивающие столбцам те же значения, которые у них были до ``обновления''.

Запись в журнал осуществляется сразу по завершении работы запроса, но до того, как будут сняты блокировки. Таким образом обеспечивается уверенность в том, что журнал ведется именно в порядке выполнения запросов.

При желании обновить базу в соответствии с данными журналов обновлений можно воспользоваться следующей командой (при условии, что имена файлов журналов соответствуют форме `file_name.###'):

shell> ls -1 -t -r file_name.[0-9]* | xargs cat | mysql

ls расставляет все файлы журналов в правильном порядке.

Эта возможность может пригодиться в случае, если возникнет необходимость (в результате серьезного сбоя) привести базу в соответствие с резервной копией и затем повторить все обновления, произошедшие с момента создания копии и до сбоя.

4.9.4 Бинарный журнал обновлений

Бинарный журнал обновлений в скором времени должен полностью заменить журнал обновлений, так что мы рекомендуем вам как можно скорее перейти на его использование!

Бинарный журнал содержит всю информацию, имеющуюся в журнале обновлений, в более эффективном формате. В нем имеется информация и о времени выполнения каждого обновляющего базу запроса. В нем не содержится информации о запросах, которые не изменяют данные. Если вам нужно журналировать все запросы (например для выявления проблемного запроса), вам следует использовать общий журнал запросов. See section 4.9.2 Общий журнал запросов.

Бинарный журнал используется и при репликации подчиненного сервера (slave) с головного (master) (see section 4.10 Репликация в MySQL).

При запуске с ключом --log-bin[=file_name] mysqld создает файл журнала, в который вносятся данные обо всех обновляющих данные командах SQL. Если имя файла не задано, по умолчанию ему дается имя хоста с окончанием -bin. Если файлу присвоено имя, не содержащее пути доступа к нему, этот файл сохраняется в каталоге данных.

При вводе расширения в имя файла (например: --log-bin=filename.extension) это расширение удаляется без предупреждения.

К имени файла бинарного журнала программа mysqld прибавляет специальное расширение - номер, увеличивающийся при каждом выполнении команд mysqladmin refresh, mysqladmin flush-logs, FLUSH LOGS или перезапуске сервера. При достижении файлом журнала максимального размера, заданного в параметре max_binlog_size, автоматически создается новый. Все неактивные файлы бинарных журналов можно удалить командой RESET MASTER (see section 4.5.4 Синтаксис команды RESET.

На выбор данных, записываемых в журнал, влияют следующие настройки mysqld:

Опция | Описание
binlog-do-db=database_name | Указывает головному серверу что он должен журналировать обновления в двоичный журнал если текущая (т.е. выбранная) база данных - это 'database_name'. Остальные базы данных, особо не отмеченные, игнорируются. Имейте в виду, что если вы используете эту опцию, то вам следует делать обновления только в этой базе данных. (пример: binlog-do-db=some_database)
binlog-ignore-db=database_name | Заставляет master отказаться от занесения в журнал обновлений определенной базы данных (пример: binlog-ignore-db=some_database)

Чтобы была возможность определить, какие файлы журналов используются в данный момент, mysqld создает и индексный файл, содержащий имена всех находящихся в работе файлов. По умолчанию ему присваивается то же имя, что и файлу журнала, но с расширением .index. Имя этого файла можно изменить с помощью параметра --log-bin-index=[filename].

При использовании репликации удалять старые файлы журналов не стоит до тех пор, пока вы не будете уверены в том, что они никогда не понадобятся ни одной зависимой базе. Добиться такого результата можно, запуская команду mysqladmin flush-logs раз в день и затем удаляя все журналы, созданные более 3 дней назад.

Работать с файлами бинарного журнала можно с помощью программы mysqlbinlog. Обновить MySQL в соответствии с записями в журнале можно так:

shell> mysqlbinlog log-file | mysql -h server_name

С помощью программы mysqlbinlog можно даже считывать файлы журнала прямо с удаленного сервера MySQL!

При запуске mysqlbinlog с ключом --help на экран выводится дополнительная информация по работе с этой программой.

При работе с настройками BEGIN [WORK] или SET AUTOCOMMIT=0 для резервного копирования нужно использовать бинарный журнал, а не старый журнал обновлений.

Занесение данных в бинарный журнал происходит сразу по завершении исполнения запроса, но до снятия блокировок. Таким образом обеспечивается уверенность в том, что журнал ведется именно в порядке выполнения запросов.

Updates to non-transactional tables are stored in the binary log immediately after execution.

Обновления нетранзакционных таблиц сохраняются в двоичном журнале немедленно после выполнения. Все обновления (UPDATE, DELETE или INSERT), изменяющие данные в транзакционных таблицах (например, BDB-таблицу) находятся в кэше до вызова COMMIT. В этот момент mysqld пишет всю транзакцию целиком в двоичный журнал перед тем, как выполнить COMMIT. Каждый поток при запуске будет создавать буффер размером binlog_cache_size для буферизации запросов. Если запрос превышает этот размер, тогда поток откроет временный файл для сохранения транзакции. Временный файл будет удален при выходе потока.

При запуске каждого потока создается буфер запросов, объем которого соответствует значению параметра binlog_cache_size. Если запрос не помещается в буфере, поток создаст временный файл для кэша. Временный файл удаляется по завершении работы потока.

Параметр max_binlog_cache_size (по умолчанию 4Гб) позволяет ограничить общий объем памяти, используемой для кэширования мультитранзакционного запроса. Если транзакция больше этого - будет произведен откат.

При использовании журнала обновлений или бинарного журнала параллельные операции вставки будут преобразованы в нормальные операции вставки в командах CREATE ... SELECT и INSERT ... SELECT. Это сделано специально - для того, чтобы обеспечить возможность создания точной копии таблиц путем объединения резервной копии с журналом.

4.9.5 Журнал медленных запросов

При запуске с параметром --log-slow-queries[=file_name] mysqld создает файл журнала, в котором сохраняются данные обо всех командах SQL, на выполнение которых ушло больше времени, чем указано в значении параметра long_query_time. Время, уходящее на первоначальную блокировку таблиц, не включается во время исполнения запроса.

Занесение данных в журнал происходит сразу по завершении исполнения запроса и снятия блокировок. Таким образом, порядок расположения записей может отличаться от порядка выполнения запросов.

Если имя файла не задано, по умолчанию ему дается имя хоста с окончанием -slow.log. Если файлу присвоено имя, не содержащее пути доступа к нему, этот файл сохраняется в каталоге с данными.

Этот журнал позволяет определить запросы, на выполнение которых ушло слишком много времени, а, значит, и обнаружить основных кандидатов на оптимизацию. Конечно, при достижении журналом значительного объема эта задача усложняется. В таком случае журнал можно пропустить через команду mysqldumpslow и получить краткий отчет о запросах, попавших в список.

При использовании ключа --log-long-format на экран выводятся и запросы, не работающие с индексами (see section 4.1.1 Параметры командной строки mysqld).

4.9.6 Обслуживание файлов журналов

В MySQL предусмотрено наличие нескольких файлов журналов, позволяющих следить за всеми аспектами работы системы (see section 4.9 Файлы журналов MySQL). Правда, иногда приходится проверять, не занимают ли журналы лишнего места, и удалять ненужные.

При работе с журналами MySQL, вам, вероятнее всего, понадобится удалять их или создавать их резервные копии, и указывать MySQL записывать данные журналов в новые файлы (see section 4.4.1 Резервное копирование баз данных).

В системе Linux (Red Hat) для этого можно использовать сценарий mysql-log-rotate. При установке MySQL с дистрибутива RPM этот сценарий устанавливается автоматически. Обратите внимание: использовать журнал для репликации необходимо с максимальной аккуратностью!

В других ОС вы можете самостоятельно создать небольшой сценарий для обработки журналов, запускаемый из cron.

Заставить MySQL создать новый файл журнала можно с помощью команды mysqladmin flush-logs или SQL-команды FLUSH LOGS. При работе с MySQL версии 3.21 пользоваться можно только командой mysqladmin refresh.

Эта команда выполняет следующие действия:

  • Если используется стандартный журнал (--log) или журнал медленных запросов (--log-slow-queries), файл журнала (mysql.log и `hostname`-slow.log по умолчанию) закрывается и открывается вновь.
  • Если используется журнал обновлений (--log-update), файл журнала закрывается, после чего создается новый файл с большим номером.

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

shell> cd mysql-data-directory
shell> mv mysql.log mysql.old
shell> mysqladmin flush-logs

а затем сделать резервную копию файла mysql.old и удалить его.

4.10 Репликация в MySQL

В этом разделе описаны различные функциональные возможности репликации в MySQL. Он может служить справочником по опциям, используемым при репликации. Здесь будет описан механизм репликации и показано, как реализовывать репликации. В конце раздела мы дадим ответы на некоторые часто задаваемые вопросы, а также описания проблем и способы их решения.

Рекомендуем регулярно посещать наш web-сайт по адресу http://www.mysql.com/ для ознакомления с обновлениями, произошедшими в этом разделе. Механизм репликации постоянно улучшается, и руководство постоянно дополняется самой свежей информацией.

4.10.1 Введение

К числу преимуществ, которые обеспечивает репликация, относится повышение скорости и надежности. Чтобы обеспечить надежность, можно установить две системы и при возникновении проблем с головным сервером переключаться на резервную копию. Для увеличения скорости можно перенаправлять те запросы, которые не обновляют данные, на сервер с копиями. Разумеется, это даст эффект лишь в том случае, если запросы, не обновляющие данные, преобладают, но, как правило, чаще всего так и бывает.

MySQL, начиная с версии 3.23.15, поддерживает односторонний внутренний механизм репликации. Один сервер действует как головной, а другие - как подчиненные. Обратите внимание: один сервер может играть роль головного в одной паре и подчиненного - в другой. Головной сервер содержит двоичный журнал обновлений (see section 4.9.4 Бинарный журнал обновлений) и индексный файл двоичных журналов для протоколирования ротации двоичных журналов. Подчиненный сервер при соединении уведомляет головной о том, в каком состоянии он находится, начиная от последнего обновления, которое было успешно опубликовано на подчиненный сервер. После этого подчиненный сервер принимает обновления, а затем блокируется и ждет, пока головной сервер не сообщит о новых обновлениях.

Обратите внимание: при реплицировании базы данных все обновления этой базы данных должны производиться через головной сервер!

Еще одно преимущество использования механизма репликации заключается в том, что можно иметь "живую" резервную копию системы, выполняя резервное копирование не на головном, а на подчиненном сервере (see section 4.4.1 Резервное копирование баз данных).

4.10.2 Как реализована репликация: обзор

Репликация в MySQL основывается на том, что все изменения базы данных (обновления, удаления и т.д.) протоколируются в двоичном журнале на сервере (see section 4.9.4 Бинарный журнал обновлений), а подчиненный сервер читает сохраненные запросы из двоичного журнала головного сервера и выполняет эти запросы на своей копии данных.

Очень важно понимать, что двоичный журнал - это просто запись, начатая с фиксированного момента времени (с момента, когда вы включаете ведение записей в двоичном журнале). При установке каждого из подчиненных серверов нужно будет скопировать с головного сервера все данные, существовавшие на нем к моменту начала ведения записей в двоичном журнале. Если подчиненный сервер будет запущен с данными, не соответствующими тем, которые содержались на головном сервере к моменту запуска двоичного журнала, на подчиненном сервере может произойти сбой.

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

 |  | Головной | Головной | Головной | Головной
 |  | 3.23.33 и новее | 4.0.0 | 4.0.1 | 4.0.3 и новее
Подчиненный | 3.23.33 и новее | да | нет | нет | нет
Подчиненный | 4.0.0 | нет | да | нет | нет
Подчиненный | 4.0.1 | да | нет | да | нет
Подчиненный | 4.0.3 и новее | да | нет | нет | да

Note: MySQL 4.0.2 не рекомендован для репликации.

Начиная с версии 4.0.0 для записи данных на подчиненный сервер можно использовать команду LOAD DATA FROM MASTER. Учтите, что команда LOAD DATA FROM MASTER в настоящее время работает только если все таблицы на головном сервере имеют тип MyISAM, и для них будет установлена глобальная блокировка чтения, чтобы не допустить никаких записей во время передачи таблиц от головного сервера к подчиненному. Данное ограничение носит временный характер. Оно обусловлено тем, что мы еще не реализовали горячее резервное копирование таблиц без блокировок. Это ограничение мы снимем для следующих ветвей версии 4.0 - как только будет реализовано горячее резервное копирование, которое позволит команде LOAD DATA FROM MASTER работать без блокирования обновлений на головном сервере.

Из-за вышеупомянутого ограничения рекомендуется использовать команду LOAD DATA FROM MASTER только в тех случаях, если набор данных на головном сервере относительно невелик или если для головного сервера допустима длительная блокировка чтения. Скорость выполнения команды LOAD DATA FROM MASTER для разных систем может быть различной, поэтому для грубой оценки времени выполнения команды можно считать, что для передачи 1 Мб данных требуется 1 секунда. Это приблизительно соответствует случаю, когда и головной, и подчиненный серверы эквивалентны Pentium с тактовой частотой 700 МГц и связаны сетью с пропускной способностью 100 Мбит/с, а размер индексного файла равен примерно половине размера файла данных. Разумеется, такая прикидка дает лишь грубую приближенную оценку и в случае каждой конкретной системы потребуются свои допущения.

После того как подчиненный сервер будут правильно сконфигурирован и запущен, он должен легко соединиться с головным сервером и ожидать обработки обновлений. Если головной сервер завершит работу или подчиненный сервер потеряет связь с головным, подчиненный сервер будет пытаться установить соединение каждый раз по истечении интервала времени, указанного в опции master-connect-retry (в секундах) до тех пор, пока не установится подсоединение и не продолжится прослушивание обновлений.

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

В следующем разделе процесс установки головного/подчиненного серверов рассматривается более подробно.

4.10.3 Как настроить репликацию

Здесь кратко описано как настроить полную репликацию вашего MySQL-сервера. Предполагается, что реплицироваться будут все базы данных и репликация ранее не настраивалась. Для того чтобы выполнить указанные здесь действия, вам придется на короткое время остановить головной сервер.

Это самый простой способ установки подчиненного сервера, однако он не единственный. Например, если уже имеется образ головного сервера, на головном сервере уже установлен ID сервера и производятся записи в журнал, подчиненный сервер можно установить, не останавливая головной сервер и даже не устанавливая блокировки обновлений (за дополнительной информацией обращайтесь к разделу See section 4.10.7 Часто задаваемые вопросы по репликации.

Чтобы стать настоящим гуру по репликации в MySQL, советуем сначала изучить, осмыслить и опробовать все команды, упомянутые в разделе See section 4.10.6 SQL-команды, относящиеся к репликации. Необходимо также ознакомиться с опциями запуска репликации из файла `my.cnf' в разделе See section 4.10.5 Опции репликации в файле `my.cnf'.

  1. Удостоверьтесь, что на головном и подчиненном(ых) серверах установлена свежая версия MySQL. Используйте версию 3.23.29 или выше. В предыдущих релизах применялся другой формат двоичного журнала и содержались ошибки, которые были исправлены в более новых релизах. Большая просьба: пожалуйста, не посылайте сообщения об ошибках, не проверив, присутствует ли эта ошибка в последнем релизе.
  2. Установите на головном сервере отдельного пользователя для репликации с привилегией FILE (в версиях MySQL ниже 4.0.2) или REPLICATION SLAVE в более новых версиях MySQL. У этого пользователя должно быть также разрешение подсоединяться со всех подчиненных серверов. Если пользователь будет выполнять только репликацию (рекомендуется), то ему не нужно предоставлять какие-либо дополнительные привилегии. Например, чтобы создать пользователя с именем repl, который может иметь доступ к головному серверу с любого хоста, можно использовать такую команду:
    mysql> GRANT FILE ON *.* TO repl@"%" IDENTIFIED BY '<password>'; # головной < 4.0.2

    mysql> GRANT REPLICATION SLAVE ON *.* TO repl@"%" IDENTIFIED BY '<password>'; # головной >= 4.0.2
    Если вы планируете использовать LOAD TABLE FROM MASTER или LOAD DATA FROM MASTER (доступные с версии 4.0.0), вам также надо выделить привилегии RELOAD и SUPER на головном сервере для вышеуказанного пользователя.
  3. Если вы используете MyISAM-таблицы, сохраните содержимое и заблокируйте модифицирующие запросы командой FLUSH TABLES WITH READ LOCK.
    mysql> FLUSH TABLES WITH READ LOCK;
    и после этого - снимите образ данных на вашем головном сервере. Легче всего сделать это (на Unix), создав при помощи tar архив всей своей директории данных. Точное местоположение директории данных зависит от вашей инсталляции.
    tar -cvf /tmp/mysql-snapshot.tar /path/to/data-dir
    Пользователи Windows для создания архива каталога данных могут использовать WinZIP или другую подобную программу. После того как снимок будет или прямо во время этого процесса, узнайте значения: имя текущего двоичного журнала и позицию на головном сервере:
    mysql > SHOW MASTER STATUS;
+---------------+----------+--------------+-------------------------------+
| File          | Position | Binlog_do_db | Binlog_ignore_db              |
+---------------+----------+--------------+-------------------------------+
| mysql-bin.003 | 73       | test,bar     | foo,manual,sasha_likes_to_run |
+---------------+----------+--------------+-------------------------------+
1 row in set (0.06 sec)
    Столбец File дает имя журнала, Position дает информацию о смещении в журнале (позиции). В этом примере имя журнала - mysql-bin.003 и смещение - 73. Запишите эти значения - они вам понадобятся чуть позже, когда будете настраивать подчиненный сервер. Когда вы получили образ и сохранили указанную информацию, вы можете снова разрешить запись в таблицы на головном сервере:
    mysql> UNLOCK TABLES;
    Если вы используете таблицы InnoDB, то в идеале было бы хорошо, чтобы вы использовали ПО InnoDB Hot Backup. Она берет целостный снимок без установки каких-либо блокировок на головном сервере, и сохраняет имя журнала и позицию непосредственно в снимке, что позволит в дальнейшем использовать эту информацию на подчиненном сервере. Более подробная информация об этой программе доступна на http://www.innodb.com/hotbackup.html. Без использования этой утилиты, наиболее быстрый способ получить снимок таблиц InnoDB - это остановить головной сервер и скопировать файлы данных, журналы, и файлы определений формата таблицы (`.frm'). Для сохранения текущего имени файла журнала и смещения, вам следует выполнить следующее перед остановкой сервера:
    mysql> FLUSH TABLES WITH READ LOCK;
mysql> SHOW MASTER STATUS;
    И затем сохраните имя журнала и смещение из вывода команды SHOW MASTER STATUS так, как было показано выше. После этого остановите сервер без снятия блокировок с таблиц. Это нужно сделать именно так, чтобы быть уверенным, что сервер остановится именно с тем снимком, который мы сделали:
    shell> mysqladmin -uroot shutdown
    Если головной сервер был ранее запущен без опции log-bin, то значения имени файла журнала и позиции будут пустыми в выводе SHOW MASTER STATUS. В этом случае, сохраните пустую строку ('') как имя файла журнала и 4 как позицию.
  4. В `my.cnf' на головном сервере добавьте к разделу [mysqld] записи log-bin и server-id=уникальный номер и перезапустите сервер. Очень важно, чтобы номер подчиненного сервера отличался от номера головного сервера. Можно считать, что server-id играет роль IP-адреса - он уникально идентифицирует сервер среди участников репликации.
    [mysqld]
log-bin
server-id=1
  5. Добавьте в my.cnf на подчиненном сервере(ах) следующий фрагмент:
    server-id=<некоторое уникальное число между 2 и 2^32-1>
    заменяя значения в <> значениями, соответствующими вашей системе. Значения server-id должны быть различными на каждом сервере, участвующем в репликации. Если значение server-id не определено, оно будет установлено в 1, если также не определено значение master-host, оно будет установлено в 2. Обратите внимание, что если значение server-id опущено, то головной сервер будет отказывать в соединении всем подчиненным серверам, а подчиненный сервер - отказывать в соединении головному серверу. Таким образом, опускать установку значения server-id можно лишь в случае резервного копирования с использованием двоичного журнала.
  6. Когда подчиненный сервер будет работать, заставьте его забыть старую конфигурацию репликации, если он использовался в репликации раньше:
    mysql> RESET SLAVE;
  7. Скопируйте данные снимка в директорию данных на подчиненном сервере (ах). Удостоверьтесь в правильности привилегий для файлов и каталогов. Пользователь, от имени которого запускается MySQL, должен иметь возможность читать и записывать данные в них так же, как и на головном сервере.
  8. Перезапустите подчиненный(ые) сервер(ы).
  9. Когда подчиненные сервера запустятся, выполните:
    mysql> CHANGE MASTER TO MASTER_HOST='<имя хоста головного сервера>',
 MASTER_USER='<имя пользователя репликации>',
 MASTER_PASSWORD='<пароль репликации>',
 MASTER_LOG_FILE='<записанное вами имя журнала>',
 MASTER_LOG_POS=<записанная вами позиция>;
    заменяя значения в <> значениями, соответствующими вашей системе.
  10. Запустите поток подчиненного сервера:
    mysql> SLAVE START;

После выполнения указанных действий подчиненный(ые) сервер(ы) должен(ы) подсоединиться к головному серверу и подгонять свои данные под любые изменения, произошедшие на головном сервере после принятия образа.

Если не установлен идентификатор server-id для подчиненного сервера, в журнальный файл регистрации ошибок будет внесена следующая ошибка:

Warning: one should set server_id to a non-0 value if master_host is set.
The server will not act as a slave.

(Предупреждение: если задан master_host, следует установить server_id в
ненулевое значение.
Сервер не будет работать как подчиненный сервер.)

Если не установлен идентификатор головного сервера, подчиненные серверы не смогут подключиться к головному серверу.

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

После того как подчиненный сервер начнет выполнять репликацию, в той же директории, где находится журнал регистрации ошибок, появится файл `master.info'. Файл `master.info' используется подчиненным сервером для отслеживания того, какие записи двоичных журналов головного сервера обработаны. Не удаляйте и не редактируйте этот файл, если не уверены в том, что это необходимо. Даже если такая уверенность есть, все равно лучше использовать команду CHANGE MASTER TO.

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

4.10.4 Возможности репликации и известные проблемы

Ниже приводится список поддерживаемых и не поддерживаемых при репликации функций:

  • Реплицирование будет выполнено правильно при использовании значений AUTO_INCREMENT, LAST_INSERT_ID() и TIMESTAMP.
  • Если в обновлениях присутствует функция RAND(), реплицирование будет выполнено некорректно. При реплицировании обновлений с функцией RAND() применяйте RAND(some_non_rand_expr). В качестве аргумента (some_non_rand_expr - некоторое не случайное выражение) для функции RAND() можно, например, использовать функцию UNIX_TIMESTAMP().
  • На головном и подчиненном серверах следует использовать одинаковый набор символов (--default-character-set). В противном случае могут возникать ошибки дублирующихся ключей на подчиненном сервере, поскольку ключ, который считается уникальным на головном сервере, может не быть таковым при использовании другого набора символов.
  • В MySQL 3.23 команда LOAD DATA INFILE будет выполнена корректно, если файл во время выполнения обновления будет находиться на головном сервере. Команда LOAD LOCAL DATA INFILE будет проигнорирована. В MySQL 4.0 это ограничение не присутствует - все разновидности команды LOAD DATA INFILE реплицируются правильно.
  • Запросы на обновление, в которых используются пользовательские переменные, являются не безопасными для репликации (пока).
  • Команды FLUSH не записываются в двоичный журнал и поэтому не копируются на подчиненный сервер. Проблем при этом не возникает, поскольку команды FLUSH ничего не изменяют. Однако это означает, что при непосредственном, без использования оператора GRANT, обновлении таблиц привилегий MySQL и при последующем реплицировании базы данных привилегий mysql нужно выполнить команду FLUSH PRIVILEGES на подчиненных серверах, чтобы новые привилегии вступили в силу.
  • Временные таблицы, начиная с версии 3.23.29, реплицируются корректно, за исключением случая, когда при прекращении работы подчиненного сервера (не только потока подчиненного сервера) некоторые временные таблицы остаются открытыми и используются в последующих обновлениях. Для решения этой проблемы перед прекращением работы подчиненного сервера выполните команду SLAVE STOP, проверьте, чтобы переменная Slave_open_temp_tables содержала значение 0, затем выполните mysqladmin shutdown. Если значение переменной Slave_open_temp_tables не 0, перезапустите поток подчиненного сервера при помощи команды SLAVE START и проверьте, не улучшилась ли ситуация теперь. Эта проблема будет решаться более изящно, но придется подождать MySQL 4.0. В более ранних версиях при использовании временных таблиц репликации не выполняются должным образом - в таких случаях мы рекомендуем либо обновить версию MySQL, либо перед выполнением запросов, использующих временные таблицы, выполнить команду SET SQL_LOG_BIN=0 на своих клиентах.
  • MySQL поддерживает лишь один головной и много подчиненных серверов. В 4.x будет добавлен алгоритм голосования, обеспечивающий автоматическое изменение головного сервера, если что-либо будет выполняться неправильно при текущем головном сервере. Будут также введены процессы 'агента', которые помогут выполнять распределение нагрузки путем посылки запросов на выборки различным подчиненным серверам.
  • Начиная с версии 3.23.26 стало безопасно соединять серверы циклическими соединениями головной-подчиненный с включенной опцией log-slave-updates. Однако обратите внимание: при таком способе установки многие запросы не будут выполняться корректно, если только в коде вашего клиента не предусмотрена обработка потенциальных проблем, которые могут случаться при обновлениях, происходящих в различной последовательности на различных серверах. Это означает, что если вы сделаете установку следующим образом:
    A - > B > - C - > A
    то такая установка будет работать только в том случае, если выполняются непротиворечивые обновления между таблицами. Другими словами, при вставке данных на серверах A и C нельзя вставлять на сервере A строку, которая может иметь ключ, противоречащий строке, вставляемой на сервере C. Также нельзя обновлять одинаковые строки на двух серверах, если имеет значение порядок обновлений. Обратите внимание: в версии 3.23.26 изменился формат журнала. Таким образом, если версия подчиненного сервера меньше 3.23.26, сервер не сможет считывать записи из журнала.
  • Если запрос на подчиненном сервере вызывает ошибку, поток подчиненного сервера завершится, и в файле `.err' появится соответствующее сообщение. После этого нужно будет вручную установить соединение с подчиненным сервером, исправить причину ошибки (например обращение к несуществующей таблице) и затем выполнять SQL-команду SLAVE START (доступна в версии 3.23.16). При использовании версии 3.23.15 потребуется перезапустить сервер.
  • Если соединение с головным сервером прервется, подчиненный сервер попытается сразу же восстановить его, и затем в случае неудачи будет повторять попытки через установленное в опции master-connect-retry количество секунд (по умолчанию 60). По этой причине безопасно выключить головной сервер и после этого перезапустить его через некоторое время. Подчиненный сервер будет также разрешать проблемы, возникающие при аварийных отключениях электричества в узлах сети.
  • Завершение работы подчиненного сервера (корректное) также является безопасным, поскольку при этом отслеживаются события начиная от момента остановки сервера. Но в случае некорректного отключения сервера могут возникать проблемы, особенно, если дисковый кэш не был синхронизирован перед ``смертью'' системы. Для того чтобы значительно повысить эффективность своей системы обеспечения отказоустойчивости, целесообразно приобрести хороший UPS (источник бесперебойного питания).
  • Если головной сервер слушает нестандартный порт, это нужно будет указать также в параметре master-port в файле `my.cnf'.
  • В версии 3.23.15 все таблицы и базы данных могут быть реплицированы. Начиная с версии 3.23.16 появилась возможность ограничить репликацию набором баз данных при помощи директив replicate-do-db в файле `my.cnf'; можно также исключить набор баз данных из репликации при помощи директив replicate-ignore-db. Обратите внимание,: в версиях MySQL до 3.23.23, имелась ошибка, из-за которой команда LOAD DATA INFILE выполнялась некорректно, если она применялась к базе данных, исключенной из репликации.
  • Начиная с версии 3.23.16 команда SET SQL_LOG_BIN = 0 будет выключать ведение записей о репликации в журналах (двоичных) на головном сервере, а команда SET SQL_LOG_BIN = 1 - включать такое ведение записей. Для выполнения этих команд нужно иметь привилегию SUPER (в MySQL 4.0.2 и выше) или PROCESS (в более ранних версиях MySQL).
  • Начиная с версии 3.23.19 можно убрать мусор, оставшийся после неоконченной репликации (если ее выполнение пошло не должным образом), и начать все сначала, используя команды FLUSH MASTER и FLUSH SLAVE. В версии 3.23.26 эти команды переименованы в RESET MASTER и RESET SLAVE соответственно - чтобы сделать понятным их назначение. Тем не менее, старые варианты FLUSH все еще работают - для обеспечения совместимости.
  • Начиная с версии 3.23.23 можно заменять головные серверы и корректировать точку положения в журнале репликации при помощи команды CHANGE MASTER TO.
  • Начиная с версии 3.23.23 можно при помощи опции binlog-ignore-db уведомлять головной сервер о том, что обновления в некоторых базах данных не должны отражаться в двоичном журнале.
  • Начиная с версии 3.23.26, можно использовать опцию replicate-rewrite-db для уведомления подчиненного сервера о том, что он должен применить обновления базы данных на головном сервере к базе данных с другим именем на подчиненном сервере.
  • Начиная с версии 3.23.28 можно использовать команду PURGE MASTER LOGS TO 'имя-журнала', чтобы избавиться от старых журналов без завершения работы подчиненного сервера. Это удалит все журналы до, но не включая log-name.
  • Из-за того, что по своей природе таблицы MyISAM являются нетранзакционными, может случиться так, что запрос обновит таблицу только частично и возвратит код ошибки. Это может произойти, например, при вставке нескольких строк, одна из которых нарушает ограничение ключа, или в случае, когда длинный запрос обновления ``убивается'' после обновления некоторых строк. Если такое случится на головном сервере, поток подчиненного сервера завершит работу и будет ждать, пока администратор базы данных не примет решение о том, что делать в этом случае (если только код ошибки не является легитимным и в результате выполнения запроса не будет сгенерирована ошибка с тем же кодом). Если такой способ проверки правильности кода ошибки нежелателен, начиная с версии 3.23.47, некоторые (или все) ошибки могут быть замаскированы при помощи опции slave-skip-errors.
  • Отдельные таблицы могут исключаться из репликации при помощи опции replicate-do-table/replicate-ignore-tab или опции replicate-wild-do-table/replicate-wild-ignore-table. Однако в настоящее время наличие определенных конструктивных неточностей в некоторых довольно редких случаях может приводить к неожиданным результатам. Протокол репликации явно не уведомляет подчиненный сервер о том, какие таблицы должны быть изменены запросом, поэтому подчиненному серверу требуется анализировать запрос, чтобы узнать это. Чтобы избежать лишнего синтаксического анализа, для которого требуется прерывать выполнение запросов, исключение таблицы в настоящее время реализуется путем посылки запроса к стандартному анализатору MySQL для упрощенного синтаксического анализа. Если анализатор обнаружит, что таблица должна игнорироваться, выполнение запроса будет остановлено и выдано сообщение об успехе. Этот подход несколько неэффективен, при его применении чаще возникают ошибки и, кроме того, имеются две известные ошибки в версии 3.23.49. Первая может возникнуть из-за того, что поскольку анализатор автоматически открывает таблицу при анализе некоторых запросов, игнорируемая таблица должна существовать на подчиненном сервере. Другая ошибка заключается в том, что при частичном обновлении игнорируемой таблицы поток подчиненного сервера не заметит, что таблица должна игнорироваться, и приостановит процесс репликации. Несмотря на то что вышеупомянутые ошибки концептуально очень просто исправить, для этого придется изменить достаточно много кода, что поставит под угрозу состояние стабильности ветви 3.23. Если описанные случаи непосредственно имеют отношение к вашему приложению (а это довольно редкий случай) - используйте опцию slave-skip-errors, чтобы дать указание серверу продолжать репликации, игнорируя эти ошибки.

4.10.5 Опции репликации в файле `my.cnf'

Для использования репликации рекомендуется MySQL 3.23.33 или выше. С более ранними версиями тоже можно работать, но в них имеются ошибки и отсутствуют некоторые возможности. Если у вас не самая последняя версия MySQL, то в ней может не оказаться некоторых из упомянутых в данном разделе опций. Все опции, появившиеся в ветви 4.0, сопровождаются примечанием, в котором это указано. В противном случае, если интересующая вас опция не присутствует в версии 3.23, но действительно необходима, пожалуйста, замените версию на самую новую ветвь 3.23.

Не следует забывать о том, что ветвь 4.0 все еще находится в стадии альфа-разработки, поэтому некоторые функции могут работать не так гладко, как хотелось бы. Новые возможности, появившиеся в 4.0, рекомендуется использовать так, чтобы в случае возникновения проблемы не нарушилась работа приложения.

Как на головном, так и на подчиненном серверах нужно использовать опцию server-id. Она устанавливает уникальный идентификатор репликации. Нужно выбрать уникальное значение из диапазона от 1 до 2^32-1 для каждого головного и подчиненного сервера, например: server-id=3

В следующей таблице представлены опции, которые можно использовать для головного сервера.

Опция | Описание
log-bin=filename | Указывает местоположение двоичного журнала обновлений, в котором будут вестись записи. Обратите внимание: если передаваемый параметр имеет расширение (например log-bin=/mysql/logs/replication.log), то в случае вызова команды FLUSH LOGS версии MySQL ниже 3.23.24 не будут правильно работать во время репликации. Эта проблема устранена в версии 3.23.25. Теперь, если используется такой способ определения имени журнала, команда FLUSH LOGS для двоичных журналов будет игнорироваться. Для очистки журнала выполните команду FLUSH MASTER и не забудьте запустить команду FLUSH SLAVE на всех подчиненных серверах. В версии 3.23.26 или выше нужно использовать для этого команды RESET MASTER и RESET SLAVE Вы можете использовать эту опци. если вы хотите иметь имя, которое будет независимо от имени хоста (может быть полезно, скажем, если вы переименуете ваш сервер в один прекрасный день).
log-bin-index=filename | Так как пользователь может выполнять команду FLUSH LOG, нужно знать, какой журнал является активным в настоящее время, а также какие журналы использовались ранее и в какой последовательности они сменялись. Эта информация сохранена в индексном файле двоичного журнала, имя которого по умолчанию `имя_хоста.index'. Имя и содержимое данного файла не следует изменять. Пример: log-bin-index=db.index
sql-bin-update-same | Если включена данная опция, то при установке значения переменной SQL_LOG_BIN это же значение будет автоматически установлено и для переменной SQL_LOG_UPDATE, и наоборот.
binlog-do-db=database_name | Указывает головному серверу, что он должен вести записи об обновлениях в двоичном журнале, если текущая база данных - database_name. Все другие базы данных игнорируются. Обратите внимание: при использовании этой опции вы должны быть уверены, что обновления будут производиться только в текущей базе данных. Пример: binlog-do-db=sales
binlog-ignore-db=database_name | Указывает головному серверу, что если текущая база данных - database_name, то записи об обновлениях не должны вестись в двоичном журнале. Обратите внимание: при использовании этой опции вы должны быть уверены, что обновления будут производиться только в текущей базе данных. Пример: binlog-ignore-db=accounting

В следующей таблице представлены опции, которые можно использовать для подчиненного сервера:

Опция | Описание
master-host=host | Имя хоста головного сервера или IP-адрес для репликации. Если значение этой опции не установлено, поток подчиненного сервера не будет запущен. Обратите внимание: установка master-host будет игнорироваться, если существует корректный файл `master.info'. Возможно, лучше было бы назвать эти опции как-нибудь иначе, что-то вроде bootstrap-master-host, но менять их имена уже поздно. Пример: master-host=db-master.mycompany.com
master-user=username | Имя пользователя, которое подчиненный сервер будет использовать для аутентификации при подсоединении к головному серверу. Пользователь должен иметь привилегию FILE. Если пользователь головного сервера не установлен, будет использовано имя пользователя test. Если удастся считать значение из файла `master.info', то оно будет иметь больший приоритет. Пример: master-user=scott
master-password=password | Пароль, который будет использоваться при подсоединении подчиненного сервера к головному серверу. Если этот пароль не установлен, будет использоваться пустой пароль. Если удастся считать значение из файла `master.info,' то оно будет иметь больший приоритет. Пример: master-password=tiger
master-port=portnumber | Порт, который слушает головной сервер. Если не он не установлен, используется откомпилированная установка MYSQL_PORT. Это должно быть значение 3306, если оно не было изменено при помощи опций configure. Если удастся считать значение из файла `master.info', то оно будет иметь больший приоритет Пример: master-port=3306
master-connect-retry=seconds | Время ожидания в секундах для потока подчиненного сервера перед повторением попытки установить связь с головным сервером в случае прекращения работы головного сервера или потери связи. По умолчанию - 60. Пример: master-connect-retry=60
master-ssl | Доступна для версий выше 4.0.0. Включает SSL для репликации. Это относительно новая опция, поэтому применять ее следует осторожно. Пример: master-ssl
master-ssl-key | Доступна для версий выше 4.0.0. Имя файла-ключа SSL на головном сервере. Используется только в том случае, если включена опция master-ssl. Пример: master-ssl-key=SSL/master-key.pem
master-ssl-cert | Доступна для версий выше 4.0.0. Имя файла-сертификата SSL. Используется только в том случае, если включена опция master-ssl. Пример: master-ssl-key=SSL/master-cert.pem
master-info-file=filename | Местоположение файла, в который записывается информация о том, где на головном сервере произошла остановка во время выполнения репликации. По умолчанию это файл `master.info' в директории данных. Изменять это местоположение нет необходимости. Пример: master-info-file=master.info
report-host | Доступна для версий выше 4.0.0. Имя хоста или IP-адрес подчиненного сервера, который передается головному серверу во время регистрации подчиненного сервера. Может быть выведен командой SHOW SLAVE HOSTS. Не устанавливайте эту опцию, если не хотите, чтобы подчиненный сервер регистрировался на головном сервере. Обратите внимание: для того, чтобы головной сервер установил соединение с подчиненным сервером, ему недостаточно просто получить IP-адрес подчиненного сервера из соединения. Из-за NAT и других проблем маршрутизации IP-адрес может быть недопустимым для подсоединения головного сервера или других хостов к подчиненному серверу. Пример: report-host=slave1.mycompany.com
report-port | Доступна для версий выше 4.0.0. Порт для соединения с подчиненным сервером, имя хоста или IP-адрес которого были переданы головному серверу при регистрации подчиненного сервера. Порт нужно устанавливать лишь в том случае, когда подчиненный сервер слушает порт, который задан не по умолчанию, или если имеется специальный тоннель от головного сервера или других клиентов к подчиненному серверу. Не используйте эту опцию, если не уверены в своих действиях.
replicate-do-table=db_name.table_name | Сообщает подчиненному серверу, что он должен реплицировать только указанную таблицу. Для указания более чем одной таблицы директиву следует использовать несколько раз, по одному разу для каждой таблицы. В отличие от replicate-do-db, данную опцию можно применять для обновлений, в которых используется несколько баз данных. Пример: replicate-do-table=some_db.some_table
replicate-ignore-table=db_name.table_name | Указывает подчиненному серверу, что команды, обновляющие эту таблицу, не должны реплицироваться. Для указания более чем одной таблицы директиву следует задавать несколько раз, по одному разу для каждой таблицы. В отличие от replicate-do-db, данную опцию можно применять для обновлений, в которых используется несколько баз данных. Пример: replicate-ignore-table=db_name.some_table
replicate-wild-do-table=db_name.table_name | Указывает подчиненному серверу, что должны реплицироваться только те запросы, где хоть одна из таблиц удовлетворяет указанном шаблону. Для указания более чем одной таблицы директиву следует задавать несколько раз, по одному разу для каждой таблицы. Данную опцию можно применять для обновлений, в которых используется несколько баз данных. Пример: при использовании replicate-wild-do-table=foo%.bar% будут реплицироваться обновления только таблиц с именами, начинающимися с ``bar'', которые находятся в базах данных, с именами, начинаются с ``foo''. Заметьте, что если вы используете replicate-wild-do-table=foo%.% тогда это правило также распространяется и на CREATE DATABASE и на DROP DATABASE, т.е. эти два выражения также будут реплицированы если имя базы данных совпадет с шаблоном ('foo%' в этом примере; это получается из-за того, что символ % становится шаблонным).
replicate-wild-ignore-table=db_name.table_name | Указывает подчиненному серверу, запросы, где используется одна из перечисленных здесь таблиц, реплицироваться не должны. Для указания более чем одной подлежащей игнорированию таблицы директиву следует задавать несколько раз, по одному разу для каждой таблицы. Данную опцию можно применять для обновлений, в которых используется несколько баз данных. Например, при использовании replicate-wild-do-table=foo%.bar% не будут реплицироваться обновления всех таблиц, начинающихся на ``bar'', в базах данных, имена которых начинаются на ``foo''.
replicate-ignore-db=database_name | Сообщает подчиненному серверу, что не следует реплицировать ни один запрос, в котором текущая база данных - database_name. Чтобы указать более одной базы данных, директиву следует использовать несколько раз, по одному разу для каждой базы данных. Вы не должны использовать эту директиву, если вы используете кросс-табличные обновления, и не хотите чтобы эти обновления реплицировались. Основная причина такого поведения заключается в том, что очень трудно из самой команды понять, должен ли этот запрос реплицироваться или нет. Например, если вы используете многотабличное удаление или многотабличное обновление в MySQL 4.x, которое охватывает более чем одну базу данных. Кроме того, достаточно быстро можно проверить, является ли текущая база данных соответствующей, т.к. эта проверка выполняется только на момент соединения или смены базы данных. Если такие обновления необходимо производить, убедитесь, что у вас установлена версия MySQL 3.23.28 или выше и используйте replicate-ignore-db=db_name.%. Пример: replicate-ignore-db=some_db
replicate-do-db=database_name | Сообщает подчиненному серверу, что реплицироваться должна только указанная база данных. Чтобы указать более одной базы данных, директиву следует использовать несколько раз, по одному разу для каждой базы данных. Заметьте, что не будут реплицироваться обновления, охватывающие несколько баз данных, такие как UPDATE some_db.some_table SET foo='bar' при том, что выбрана другая база данных или не выбрана вовсе. Если такие обновления необходимо производить, убедитесь, что у вас установлена версия MySQL 3.23.28 или выше и используйте replicate-wild-do-table=db_name.%. Пример: replicate-do-db=some_db
log-slave-updates | Указывает подчиненному серверу, чтобы тот вел записи об обновлениях, происходящих на подчиненном сервере, в двоичном журнале. По умолчанию эта опция выключена. Ее следует включить, если требуется организовать подчиненные серверы в гирляндную цепь.
replicate-rewrite-db=from_name->to_name | Обновления производятся не в подлинную базу данных, а в базу данных с именем, указанным в опции. Пример: replicate-rewrite-db=master_db_name->slave_db_name
slave-skip-errors= [err_code1,err_code2,... | all] | Доступна только в версии 3.23.47 и выше. Сообщает потоку подчиненного сервера, что он должен продолжать репликацию, если запрос возвращает ошибку, указанную в списке. Обычно при возникновении ошибки выполнение реплицирование прекращается, чтобы пользователь мог вручную исправить несоответствия в данных. Не используйте данную опцию, если вы до конца не разобрались в причинах возникновения ошибок. Если не было допущено ошибок при установке репликации, нет ошибок в клиентских программах и нет никаких ошибок непосредственно в MySQL, то прекращения работы из-за ошибки происходить не должно. Неразборчивое применение данной опции может привести к тому, что подчиненный сервер окажется безнадежно не синхронизированным с головным сервером, и вы будете тщетно ломать себе голову над тем, каким образом это случилось. Код ошибок можно получить в сообщениях об ошибках в журнале ошибок и в выводе команды SHOW SLAVE STATUS. Полный список сообщений об ошибках можно найти в файле исходного дистрибутива `Docs/mysqld_error.txt'. Можно также (но не нужно) использовать значение all (хотя этого делать настоятельно не рекомендуется) - тогда будут игнорироваться все сообщения об ошибках и за процессом переброски данных наблюдения не будет. Само собой разумеется, при использовании этой опции целостность данных ставится под угрозу. В этом случае просьба не жаловаться, если данные на подчиненном сервере не будут соответствовать данным на головном сервере, - вас предупреждали. Пример: slave-skip-errors=1062,1053 или slave-skip-errors=all
skip-slave-start | Указывает компьютеру, на котором установлен подчиненный сервер, что при его запуске не должен запускаться подчиненный сервер. Пользователь может запустить его позже при помощи команды SLAVE START.
slave_compressed_protocol=# | Если 1, то использовать сжание в клиент/серверном протоколе связи, если оба, и сервер и клиент, поддерживают сжатие.
slave_net_timeout=# | Время ожидания (в секундах) дополнительных данных от головного сервера, после чего чтение будет прервано.

4.10.6 SQL-команды, относящиеся к репликации

Управление репликацией производится командами SQL. Ниже приводится краткое описание команд:

Команда | Описание
SLAVE START | Запускает поток подчиненного сервера (подчиненный сервер)
SLAVE STOP | Завершает поток подчиненного сервера. Также как и SLAVE START, этот оператор можно использовать с опциями IO_THREAD и SQL_THREAD. (подчиненный сервер)
SET SQL_LOG_BIN=0 | Блокирует ведение записей в журналах обновлений, если пользователь имеет привилегию SUPER. В противном случае ничего не выполняет (головной сервер)
SET SQL_LOG_BIN=1 | Отменяет блокировку ведения записей в журналах обновлений, если пользователь имеет привилегию SUPER. В противном случае ничего не выполняет (головной сервер)
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=n | Пропускает последующие n событий на головном сервере. Опция допустима, если поток подчиненного сервера не запущен, в противном случае будет выдана ошибка. Полезна для восстановления после сбоев репликации.
RESET MASTER | Удаляет все двоичные журналы, перечисленные в индексном файле, и делает индексный файл двоичных журналов пустым. Для версий ниже 3.23.26 используйте команду FLUSH SLAVE (головной сервер)
RESET SLAVE | Заставляет подчиненный сервер "забыть" свою точку положения репликации в журналах головного сервера. Для версий ниже 3.23.26 эта команда называется FLUSH SLAVE (подчиненный сервер)
LOAD TABLE tblname FROM MASTER | Загружает копию таблицы из головного на подчиненный сервер. Используется главным образом для отладки команды LOAD DATA FROM MASTER, но некоторые "пользователи-гурманы" могут найти ей и другие применения. Если вы относите себя к числу обычных, не отягощенных хакерскими амбициями пользователей, данную опцию применять не стоит. Требуется, чтобы у пользователя репликации, использущегося в соединении с головным сервером, присутствовали привилегии RELOAD и SUPER на головном сервере. (подчиненный сервер).
LOAD DATA FROM MASTER | Присутствует в версиях выше 4.0.0. Создает образ головного сервера и копирует его на подчиненный сервер. Требуется, чтобы у пользователя репликации, использущегося в соединении с головным сервером, присутствовали привилегии RELOAD и SUPER на головном сервере. Обновляет значения MASTER_LOG_FILE и MASTER_LOG_POS таким образом, чтобы подчиненный сервер начинал репликацию из конкретной позиции. Будет обрабатывать ограничения таблиц и баз данных, указанные в опциях replicate-*. При этом, пока происходит создание образа, могут использоваться лишь таблицы MyISAM и требуется глобальная блокировка чтения на головном сервере. В будущем планируется обеспечить работу этой команды с таблицами InnoDB и устранить необходимость глобальной блокировки чтения при помощи интерактивного резервного копирования, не требующего блокировки. Заметьте, LOAD DATA FROM MASTER НЕ копирует ни одну таблицу в базе данных mysql. Это сделано для того, чтобы было легко управлять разными пользователями на головном и подчиненном серверах.
CHANGE MASTER TO master_def_list Заменяет параметры головного сервера значениями, заданными в списке master_def_list, и перезапускает поток подчиненного сервера. master_def_list - это список с разделителем-запятой, содержащий значения master_def, где master_def - одно из следующих значений: MASTER_HOST, MASTER_USER, MASTER_PASSWORD, MASTER_PORT, MASTER_CONNECT_RETRY, MASTER_LOG_FILE, MASTER_LOG_POS. Например:
CHANGE MASTER TO
   MASTER_HOST='master2.mycompany.com',
   MASTER_USER='replication',
   MASTER_PASSWORD='bigs3cret',
   MASTER_PORT=3306,
   MASTER_LOG_FILE='master2-bin.001',
   MASTER_LOG_POS=4;
Следует указывать только те значения, которые подлежат изменению. Не указанные значения останутся неизменными, за исключением тех случаев, когда изменяется хост или порт. В этом случае подчиненный сервер считает, что поскольку изменяется хост или порт, головной сервер становится другим. Следовательно, старые значения и точки положения в журнале будут автоматически заменены на значение пустой строки и 0 соответственно (начальные значения). Обратите внимание: если подчиненный сервер перезапускается, он сохраняет "память" о своем последнем головном сервере. Если это нежелательно, можно перед перезапуском удалить файл `master.info' - тогда подчиненный сервер будет считывать информацию о своем головном сервере из файла `my.cnf' или из командной строки. Эта команда используется для настройки подчиненного сервера при наличии образа головного сервера, а также записей из журнала и сдвига головного сервера, которые соответствуют образу. Можно выполнить команду
CHANGE MASTER TO
   MASTER_LOG_FILE='log_name_on_master',
   MASTER_LOG_POS=log_offset_on_master
на подчиненном сервере после восстановления образа (подчиненный сервер)
SHOW MASTER STATUS | Выводит информацию о состоянии головного сервера, исходя из информации в двоичных журналах (головной сервер)
SHOW SLAVE HOSTS | Присутствует в версии 4.0.0 и выше. Выводит список подчиненных серверов, связанных в текущее время с головным сервером (подчиненный сервер)
SHOW SLAVE STATUS | Выводит информацию о состоянии существенных параметров потока подчиненного сервера (головной сервер)
SHOW MASTER LOGS | Присутствует только начиная с версии 3.23.28. Выводит список двоичных журналов головного сервера. Эту команду следует использовать перед вызовом команды PURGE MASTER LOGS TO для определения того, какие из журналов можно удалить (головной сервер)
SHOW BINLOG EVENTS [ IN 'logname' ] [ FROM pos ] [LIMIT [offset,] rows ] @tab Показывает события в двоичном журнале обновлений. Преимущественно применяется для тестирования/отладки, но может также использоваться и для обычных клиентов, по какой-либо причине нуждающихся в чтении содержимого двоичных журналов (головной сервер).
SHOW NEW MASTER FOR SLAVE
WITH
MASTER_LOG_FILE='logfile'
AND MASTER_LOG_POS=pos AND
MASTER_LOG_SEQ=log_seq AND
MASTER_SERVER_ID=server_id
         Эта команда используется, когда подчиненному серверу, связанному с головным сервером, который, возможно, является "мертвым" или недоступным, нужно отключить репликации на другом подчиненном сервере, связанном с тем же головным сервером. Команда возвратит пересчитанные координаты репликации (имя файла журнала и позицию в нем), и вывод этой команды может использоваться в последующей команде CHANGE MASTER TO. Обычным пользователям данная команда, как правило, никогда не понадобится: она главным образом служит для внутреннего использования в отказобезопасном репликационном коде. В будущем возможны изменения синтаксиса опции, если будет найден более интуитивно понятный способ описания этой операции.
PURGE MASTER LOGS TO 'logname' Присутствует начиная с версии 3.23.28. Удаляет все журналы репликации, которые перечислены в индексном файле журналов до передаваемого журнала, и удаляет их из индексного файла журналов. Таким образом передаваемый журнал становится первым в индексном файле журналов. Пример:
PURGE MASTER LOGS TO 'mysql-bin.010'
Эта команда не выполнит никаких действий и возвратит ошибку, если имеется активный подчиненный сервер, который в текущее время читает данные из одного из журналов, который должен быть удален. Однако если имеется бездействующий подчиненный сервер и происходит удаление одного из журналов, который он хочет прочитать, то после того, как подчиненный сервер "поднимется", он станет неспособным к репликации. Команда может быть безопасно выполнена на подчиненных серверах во время процесса репликации - не нужно останавливать процесс. Сначала необходимо проверить все подчиненные серверы при помощи команды SHOW SLAVE STATUS, чтобы увидеть, какой журнал используется, затем вывести список журналов головного сервера при помощи команды SHOW MASTER LOGS, найти самый ранний журнал среди всех подчиненных серверов (если все подчиненные серверы получили последние обновления, это будет последний журнал в списке), сделать резервные копии всех журналов, которые должны быть удалены (необязательно), и очистить все до целевого журнала.

4.10.7 Часто задаваемые вопросы по репликации

Вопрос: Как сконфигурировать подчиненный сервер, если головной сервер уже запущен, и я не хочу его останавливать?

Ответ: Есть несколько возможностей. Если имеется резервная копия головного сервера в некоторой точке, имя двоичного журнала и сдвиг (от вывода SHOW MASTER STATUS), соответствующий образу, выполните следующие действия:

  • Удостоверьтесь, что подчиненному серверу назначен уникальный идентификатор.
  • Выполните  команды  CHANGE MASTER TO MASTER_HOST='master-host-name',
MASTER_USER='master-user-name', MASTER_PASSWORD='master-pass',
MASTER_LOG_FILE='recorded-log-name', MASTER_LOG_POS=recorded_log_pos
  • Выполните команду SLAVE START

Если нет резервной копии головного сервера, существует быстрый способ создать ее в той же последовательности действий:

    FLUSH TABLES WITH READ LOCK
  • gtar zcf /tmp/backup.tar.gz /var/lib/mysql (или разновидность данной команды)
  • SHOW MASTER STATUS - удостоверьтесь в том что вывод этой команды сохранен - он пригодится позже
  • UNLOCK TABLES

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

В версии 4.0.0 и выше можно также использовать команду LOAD DATA FROM MASTER. Это удобная команда, которая создает образ, восстанавливает его на подчиненном сервере и сразу же корректирует имя журнала и сдвиг на подчиненном сервере. Именно команду LOAD DATA FROM MASTER можно рекомендовать как способ установки подчиненного сервера. Имейте в виду, однако, что при использовании данной команды чтение может быть блокировано на долгое время. В настоящее время эта команда еще не реализована настолько эффективно, как бы нам хотелось. Если имеются большие таблицы, пока лучше использовать локальный архив tar после выполнения команды FLUSH TABLES WITH READ LOCK.

В: Должен ли подчиненный сервер постоянно быть подсоединен к головному серверу?

О: Нет, не должен. Можно прекращать работу подчиненного сервера или оставлять его отсоединенным на несколько часов или даже дней, затем повторно подгонять подчиненный сервер к произошедшим обновлениям, и затем снова отсоединять или останавливать его на некоторое время. Таким образом можно, например, использовать установку "головной-подчиненный" через коммутационную связь, работающую в течение коротких периодов времени. При такой реализации, однако, нельзя гарантировать, что в какое-либо заданное время подчиненный сервер будет синхронизирован с головным сервером, если вы для этого не примете специальных мер. В будущем будет добавлена опция для блокировки головного сервера до тех пор, пока хотя бы один подчиненный сервер находится в синхронизации с ним.

В: Как заставить головной сервер блокировать обновления, пока происходит соединение с подчиненным сервером?

О: Выполните следующие команды:

  • Головной сервер: FLUSH TABLES WITH READ LOCK
  • Головной сервер: SHOW MASTER STATUS - запомните имя журнала и сдвиг
  • Подчиненный сервер: SELECT MASTER_POS_WAIT('recorded_log_name', recorded_log_offset) После выполнения этой команды подчиненный сервер будет синхронизирован с головным сервером
  • Головной сервер: UNLOCK TABLES - теперь головной сервер может продолжить обновления.

В: Почему иногда после перезапуска подчиненного сервера я вижу более одного потока Binlog_Dump на головном сервере?

О: Поток Binlog_Dump является непрерывным процессом, который обрабатывается сервером следующим способом:

  • Осуществляется захват обновлений.
  • Если не остается больше обновлений, входит в число pthread_cond_wait(), откуда его можно "пробудить", выполнив следующее обновление, или уничтожить.
  • После пробуждения проверяется причина пробуждения. Если нет причины прекращения цикла, цикл Binlog_dump продолжается.
  • При возникновении какой-либо фатальной ошибки, такой как обнаружение "мертвого" клиента, цикл прекращается.

Таким образом, если поток подчиненного сервера прекратится на подчиненном сервере, соответствующий поток Binlog_Dump на головном сервере не будет замечать этого, пока не произойдет по крайней мере одного обновления на головном сервере (или уничтожения потока), которое необходимо, чтобы пробудить его из числа pthread_cond_wait(). Тем временем подчиненный сервер может открыть другое соединение, результатом которого будет другой поток Binlog_Dump.

Эта проблема не должна присутствовать в версии 3.23.26 и более поздних версиях. В версии 3.23.26 для каждого репликационного сервера добавляется идентификатор server-id, и теперь все старые процессы-зомби на головном сервере уничтожаются при присоединении нового репликационного потока из того же самого подчиненного сервера.

В: Как прокручивать журналы репликации?

О: В версии 3.23.28 нужно использовать команду PURGE MASTER LOGS TO после определения тех журналов, которые должны быть удалены, и выборочно сделать резервные копии этих журналов. В более ранних версиях этот процесс намного более трудоемкий, и не может быть безопасно выполнен без остановки всех подчиненных серверов, если планируется повторное использование имен журналов. Нужно будет остановить потоки подчиненного сервера, отредактировать индексный файл двоичного журнала, удалить все старые журналы, перезапустить головной сервер, запустить потоки подчиненного сервера и затем удалить файлы старых журналов.

В: Как сделать апгрейд сервера во время репликации?

О: Если модернизируемая версия ниже 3.23.26, нужно лишь блокировать таблицы головного сервера, позволить подчиненному серверу подогнать обновления, затем выполнить команду FLUSH MASTER на головном сервере и команду FLUSH SLAVE на подчиненном сервере, чтобы очистить журналы, затем перезапустить новые версии на головном и подчиненном серверах. Обратите внимание: подчиненный сервер может останавливаться на некоторое время - пока головной сервер записывает в журнал все обновления, подчиненный сервер будет способен подогнать обновления как только сможет начать работу и подсоединиться к головному серверу.

В версиях выше 3.23.26 осуществляется блокировка протокола репликации для обновлений. Таким образом можно делать апгрейд до более свежей версии 3.23 головного и подчиненного серверов динамически. Помимо этого, на головном и подчиненном серверах могут быть запущены различающиеся версии MySQL, если обе версии выше 3.23.26.

Q: Какие проблемы могут возникать при установке двухсторонней репликации?

A: В настоящее время для репликаций MySQL не поддерживается никакого протокола блокировки между головным и подчиненным сервером, который обеспечивал бы неделимость распределенных (междусерверных) обновлений. Другими словами, клиент A может делать обновления на головном сервере 1, и в это же время, перед тем, как эти обновления скопируются на головной сервер 2, клиент B может делать обновления на головном сервере 2, из-за которых обновления клиента A будут выполняться не так, как на головном сервере 1 компании. Таким образом, когда обновления, сделанные клиентом A, будут перенесены на головной сервер 2, таблицы, полученные в результате, будут отличаться от таблиц на головном сервере 1. В этом случае таблицы на двух серверах будут разными, даже если обновления, произошедшие на головном сервере 2, также будут скопированы на головной сервер 1. Отсюда следует, что не стоит соединять в цепочку два сервера двусторонней репликационной связью, если вы не уверены, что обновления будут безопасно выполняться в любом порядке, или если вы не обрабатываете каким-либо образом такие неупорядоченные обновления где-либо в клиентском коде.

Важно понять также и то, что если двухсторонний механизм репликации и повышает производительность, то не настолько, что это могло бы отразиться на обновлениях. Каждый из серверов должен выполнять такое же количество обновлений, как и один сервер, разве что уменьшатся конфликты при блокировках, потому что обновления, происходящие на другом сервере, будут сериализованы в одном потоке подчиненного сервера. Эта выгода, тем не менее, может быть компенсирована задержками в сети.

Q: Как использовать репликацию для повышения производительности системы?

A: Установите один сервер как головной и направляйте все записи к нему, а также сконфигурируйте такое количество подчиненных серверов, на какое у вас хватит средств и дискового пространства, и распределите чтение между головным сервером и подчиненными серверами. Можно также запустить подчиненные серверы с опциями --skip-bdb, --low-priority-updates и --delay-key-write=ALL, чтобы получить увеличение скорости на подчиненном сервере. В данном случае подчиненный сервер для повышения скорости будет использовать нетранзакционные таблицы MyISAM вместо таблиц BDB.

Q: Что нужно сделать, чтобы подготовить свой клиентский код для использования репликации, повышающей производительность?

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

  • Safe_writer_connect()
  • Safe_reader_connect()
  • Safe_reader_query()
  • Safe_writer_query()

Префикс safe_ означает, что функция будет нести ответственность за обработку всех возникающих ошибок.

После этого нужно преобразовать клиентский код так, чтобы он использовал библиотеку оболочки. Вначале все это покажется лишней головной болью, но в конечном счете ваши усилия окупятся. Все приложения, построенные в соответствии с приведенной выше схемой, смогут "приобщиться" к преимуществам решения один головной/много подчиненных. Код будет гораздо легче поддерживать, а добавление опций поиска неисправностей станет тривиальным. К примеру, если вам захочется узнать, какой запрос среди многих тысяч возвращает ошибку или реализовать регистрацию продолжительности выполнения каждого запроса, то понадобится изменить всего пару функций. Если у вас уже написано много кода, то для автоматизации задачи его преобразования можно использовать написанную Монти утилиту replace, которая имеется в стандартном дистрибутиве MySQL, или написать собственный сценарий на Perl. Остается надеяться, что ваш код удовлетворяет некоторой распознаваемой схеме. В противном случае будет лучше переписать его каким-либо образом, или, по крайней мере, вручную подогнать его под схему.

Обратите внимание: имена функций, конечно же, можно использовать любые. Важно иметь унифицированный интерфейс для подключения для чтения, подсоединения для записи, выполнения чтения и выполнения записи.

Q: В каких случаях репликация MySQL может улучшить производительность системы, и насколько?

A: Механизм репликации MySQL наиболее эффективен для системы, где чтение производится часто, а запись - редко. Теоретически, используя установку один головной/много подчиненных, можно наращивать ее, добавляя подчиненные серверы, пока не исчерпается пропускная способность сети или количество обновлений не вырастет настолько, что головной сервер не сможет обрабатывать их.

Чтобы определить какое количество подчиненных серверов можно установить, прежде чем выгоды от дополнительных ресурсов не перестанут оправдывать затраты, и насколько увеличится производительность вашего сайта, нужно знать структуру запросов и опытным путем (тестированием) определить связь между производительностью чтения (количество считываний за секунду, или max_reads) и записи (max_writes) на типовом головном сервере и типовом подчиненном сервере. В приведенном примере показан достаточно упрощенный подсчет того, что можно получить, используя механизм репликации для предполагаемой системы.

Предположим, что загрузка системы состоит из 10% операций записи и 90% операций чтения, и известно что max_reads = 1200 - 2 * max_writes, или другими словами, наша система, не делая записей, может делать 1200 операций чтения за секунду, средняя скорость записи вдвое ниже, чем средняя скорость чтения, а зависимость между этими величинами линейная. Предположим, что головной сервер и подчиненный сервер имеют одинаковую мощность, и имеется N подчиненных серверов и 1 головной. Тогда для каждого сервера (головного или подчиненного) имеем:

reads = 1200 - 2 * writes (по результатам тестирования)

reads = 9 * writes / (N + 1) (операции чтения распределяются по серверам, но запись выполняются на всех серверах)

9 * writes/(N+1) + 2 * writes = 1200

writes = 1200/(2 + 9/(N+1)

Таким образом, если N = 0, что означает отсутствие репликации, система может обрабатывать 1200/11, т.е. около 109 записей в секунду (а число операций чтения, в соответствии с нашими допущениями для данной системы, будет в 9 раз больше, чем число операций записи).

Если N = 1, можно получить 184 операций записи в секунду.

Если N = 8, можно получить до 400 операций записи в секунду.

Если N = 17, то - 480 операций записи в секунду.

В конечном счете, если N приближается к бесконечности (а бюджет к минус бесконечности), можно получить около 600 записей в секунду, при этом производительность системы увеличится приблизительно в 5,5 раз. Однако при использовании лишь 8 серверов производительность уже увеличивается почти в 4 раза.

Обратите внимание: в приведенных вычислениях мы принимали, что сеть имеет неограниченную пропускную способность, и пренебрегали некоторыми другими факторами, которые могут оказаться существенными для системы. Во многих случаях такие подсчеты могут и не дать точного прогноза того, как отразится на системе добавление N подчиненных серверов. Однако определить, улучшат ли репликации производительность вашей системы, а если да, то насколько, вам помогут ответы на следующие вопросы:

  • Каково отношение числа операций чтения к числу операций записи в вашей системе?
  • Насколько увеличится количество записей, которые сможет обрабатывать один сервер, при уменьшении количества операций чтения?
  • Сколько подчиненных серверов можно установить при текущей пропускной способности сети?

Q: Как использовать репликацию для обеспечения избыточности и хорошей доступности?

A: С учетом сегодняшних возможностей репликации нужно будет установить головной сервер и подчиненный сервер (или несколько подчиненных серверов), и написать сценарий для мониторинга головного сервера - для определения, включен ли он, и уведомления приложения и подчиненных серверов об изменениях головного сервера в случае ошибки. Ниже приведено несколько советов:

  • Для уведомления подчиненного сервера об изменениях головного сервера используйте команду CHANGE MASTER TO.
  • Хороший способ информирования приложений о местоположении головного сервера - иметь на головном сервере динамической компонент DNS. При использовании bind для динамического обновления DNS можно применять nsupdate.
  • Запустите подчиненные серверы с опцией log-bin, но без log-slave-updates. Таким образом подчиненный сервер будет готов стать головным сервером после выполнения команд STOP SLAVE; RESET MASTER и CHANGE MASTER TO на других подчиненных серверах. Указание этой опции обеспечит также возможность перехвата ложных обновлений, которые могут происходить из-за ошибочной конфигурации подчиненного сервера (в идеале можно настроить права доступа таким образом, чтобы никакой клиент не мог производить обновления на подчиненном сервере иначе, чем через поток подчиненного сервера) в сочетании с ошибками в клиентских программах (они никогда не должны производить обновления на подчиненном сервере непосредственно).

В настоящее время мы работаем над интеграцией системы автоматического выбора головного сервера в MySQL, но пока эта функция не будет готова, придется создавать собственные средства контроля.

Q: Каким образом подчиненный сервер сохраняет информацию о том, где он находится на головном сервер?

A: Подчиненный сервер использует файл в каталоге данных, определенный в опции master-info-file=filename. В этом файле находится вся информация, необходимая подчиненному сервер для запроса новых обновлений. Этот файл содержит следующую информацию:

Номер строки | Описание
1 | Имя файла двоичного журнала
2 | Позиция в файле журнала
3 | Удаленный компьютер (головной сервер)
4 | Пользователь
5 | Пароль
6 | Порт
7 | Интервал в секундах между соединениями

4.10.8 Поиск неисправностей репликации

Если вы следовали инструкциям, но установленный механизм репликации не работает, прежде всего следует искать пользовательские ошибки. Выполните следующие проверки:

  • Производит ли головной сервер записи в двоичный журнал? Проверьте это при помощи команды SHOW MASTER STATUS. Если да, значение Position будет отличным от нуля. Если нет, проверьте, запущен ли головной сервер с опцией log-bin и установлен ли server-id.
  • Запущен ли подчиненный сервер? Проверьте это при помощи команды SHOW SLAVE STATUS. Ответ находится в столбце Slave_running. Если нет, проверьте опции подчиненного сервера и просмотрите сообщения в журнале ошибок.
  • Если подчиненный сервер запущен, установил ли он соединение с головным сервером? Выполните команду SHOW PROCESSLIST, найдите поток, которому соответствует значение system user в столбце User и none в столбце Host, и проверьте столбец State. Если в нем находится значение connecting to master, проверьте привилегии для пользователя репликации на головном сервере, имя хоста головного сервера, установку DNS, посмотрите, запущен ли головной сервер в текущее время, доступен ли он для подчиненного сервера. После этого, если все окажется в порядке, просмотрите журналы ошибок.
  • Если подчиненный сервер был запущен, но затем остановился, посмотрите на вывод команды SHOW SLAVE STATUS и проверьте журналы ошибок. Такое обычно случается, когда некоторый запрос, успешно выполняющийся на головном сервере, не выполняется на подчиненном. Если создан корректный образ головного сервера и данные на подчиненном сервере обновлялись только через поток подчиненного сервера, этого происходить не должно. Но если все же такое случилось - значит, имеет место ошибка; как сообщить о ней, читайте ниже.
  • Если запрос, успешно выполняемый на головном сервере, не выполняется на подчиненном, и нельзя выполнить полную ресинхронизацию базы данных (ее стоит выполнить), попробуйте сделать следующее:
    • Сначала проверьте: возможно где-либо случайно оказалась ненужная запись. Разберитесь, как она оказалась там, затем удалите ее, и выполните команду SLAVE START.
    • Если вы проделали все, о чем написано выше, и ничего не помогло или этого сделать нельзя, попытайтесь понять, будет ли безопасно выполнить обновления вручную (если необходимо) и после этого игнорировать следующий запрос от головного сервера.
    • Если вы решили пропустить следующий запрос, выполните команды SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; SLAVE START; чтобы пропустить запрос, не использующий функции AUTO_INCREMENT или LAST_INSERT_ID(). В противном случае выполните команды SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; SLAVE START. Причина того, что запросы, использующие функции AUTO_INCREMENT или LAST_INSERT_ID(), обрабатываются по-другому, заключается в том, что они создают два события в двоичном журнале головного сервера.
    • Если вы уверены, что подчиненный сервер был успешно запущен и синхронизирован с головным сервером, а также что обновления таблиц не производились вне потока подчиненного сервера, пришлите нам отчет об ошибке, и вам не потребуется опять повторять описанные выше уловки.
  • Удостоверьтесь, что вы не внесли старой ошибки при апгрейде MySQL до более новой версии.
  • Если ничего не помогает, просмотрите журналы ошибок. Если журналы большие, выполните команду grep -i slave /path/to/your-log.err на подчиненном сервере. Искать ошибку на головном сервере - не лучшая идея, поскольку в его журналах находятся лишь системные ошибки общего характера; если это возможно, он посылает ошибку на подчиненный сервер, когда что-либо происходит не так, как надо.

Если вы убедились, что пользовательская ошибка здесь ни при чем, однако механизм репликации по-прежнему не работает или работает нестабильно, пришло время начать работу над отчетом об ошибке. Вы должны предоставить нам столько информации, сколько нужно, чтобы отследить ошибку. Пожалуйста, уделите отчету об ошибке нужное количество времени и усилий, чтобы сделать его хорошо. В идеале мы хотели бы иметь контрольный пример в формате, который находится в каталоге `mysql-test/t/rpl*' исходного дерева. Отослав такой контрольный пример, в большинстве случаев можно рассчитывать на получение патча в течение одного-двух дней, хотя, конечно, это время может варьироваться в зависимости от множества факторов.

Еще один хороший способ проинформировать нас об ошибке - написать простую программу с легко конфигурируемыми параметрами соединения для головного и подчиненного серверов, в которой будет продемонстрирована проблема наших систем. Программа может быть написана на Perl или на C, в зависимости от того, какой язык вы знаете лучше.

Подготовив информацию об ошибке одним из двух способов, используйте утилиту mysqlbug, чтобы создать отчет об ошибке, и пошлите его по адресу bugs@lists.mysql.com. Если же вы имеете дело с фантомом - проблемой, которая имеет место, но вы по какой-либо причине не можете ее воспроизвести по желанию:

  • Убедитесь, что эта проблема не вызвана пользовательской ошибкой. Например, при обновлении подчиненного сервера вне потока подчиненного сервера данные будут не синхронизированы, и могут быть нарушения уникальных ключей при обновлениях. В этом случае поток подчиненного сервера остановится и будет ждать, пока таблицы не будут очищены вручную, для приведения их в синхронизированный режим.
  • Запустите подчиненный сервер с опциями log-slave-updates и log-bin - при этом в журнал будет заноситься информация обо всех обновлениях, происходящих на подчиненном сервере.
  • Сохраните все доказательства наличия ошибки перед сбросом репликации. Если у нас нет информации о проблеме, или имеется только отрывочная информация, потребуется время, чтобы найти источник проблемы. Вы должны собрать следующие "свидетельства":
    • Все двоичные журналы головного сервера
    • Весь двоичный журнал подчиненного сервера
    • Вывод команды SHOW MASTER STATUS на головном сервере во время обнаружения проблемы
    • Вывод команды SHOW SLAVE STATUS на головном сервере во время обнаружения проблемы
    • Журналы ошибок головного сервера и подчиненного сервера
  • Для изучения двоичных журналов используйте утилиту mysqlbinlog. Таким образом можно находить проблемные запросы, например:
    mysqlbinlog -j pos_from_slave_status /path/to/log_from_slave_status | head

Собрав "свидетельства" о проблеме-фантоме, попробуйте сначала организовать их в отдельный контрольный пример. После этого сообщите о проблеме по адресу bugs@lists.mysql.com, описав эту проблему во всех подробностях.


Справочное руководство по MySQL версии 5.0.0-alpha. - 5 Оптимизация в MySQL

5 Оптимизация в MySQL

Оптимизация - сложная задача, потому что она, в конечном счете, требует понимания системы в целом. В отдельных случаях для выполнения локальной оптимизации достаточно знать систему или приложение не в полном объеме, однако чтобы сделать систему более оптимальной, нужно разбираться в том, как она устроена.

В этой главе будут рассмотрены различные способы оптимизации MySQL и представлены некоторые примеры ее выполнения. Не следует забывать, однако, что всегда можно найти некоторые дополнительные возможности сделать систему еще быстрее (хотя каждый следующий шаг в этом направлении будет даваться все труднее и труднее).

5.1 Oбзор оптимизации

Чтобы увеличить скорость системы, необходимо, разумеется, прежде всего разбираться в ее конструкции. Кроме того, нужно знать, какие функции будет выполнять система и какие "узкие места" в ней имеются.

Ниже приведен список наиболее часто встречающихся "узких мест":

  • Поиск данных на диске. Чтобы найти на диске какой-то фрагмент данных, требуется некоторое время. Для устройств выпуска 1999 года среднее время поиска составляет менее 10мс, так что теоретически можно выполнять приблизительно 100 операций поиска в секунду. Это время можно ненамного уменьшить, заменив диски более новыми. Для одной таблицы поиск на диске оптимизировать очень сложно. Такую оптимизацию можно выполнить путем распределения данных по нескольким дискам.
  • Дисковое чтение/запись. После выполнения поиска, когда найдена соответствующая позиция на диске, мы можем считать данные. Для устройств выпуска 1999 года производительность одного диска составляет около 10-20Мб/с. Дисковое чтение/запись легче оптимизировать, чем дисковый поиск, поэтому читать можно параллельно с нескольких дисков.
  • Циклы процессора. Когда мы помещаем данные в основную память (или если они уже находятся там), мы должны обработать их, чтобы получить результат. Наличие маленьких по сравнению с объемом ОЗУ таблиц - наиболее часто встречающийся лимитирующий фактор. Но в этом случае, в общем-то, скорость обработки маленьких таблиц значения не имеет.
  • Пропускная способность ОЗУ (memory bandwidth). Когда процессору требуется больше данных, чем может вместить его кэш, узким местом становится пропускная способность памяти. В большинстве систем это узкое место встречается редко, однако о нем нужно знать.

5.1.1 Конструктивные ограничения MySQL/компромиссы

При использовании обработчика таблиц MyISAM MySQL применяет очень быструю блокировку таблиц (несколько потоков чтения/один поток записи). Самая большая проблема при использовании этого типа таблиц возникает в случае непрерывного потока обновлений в сочетании с медленными выборками из одной и той же таблицы. Если эта проблема касается лишь некоторых таблиц, можно использовать вместо них таблицы другого типа. See section 7 Типы таблиц MySQL.

MySQL может работать как с транзакционными так и с нетранзакционными таблицами. Чтобы обеспечить возможность нормальной работы с нетранзакционными таблицами (для которых невозможен откат, если что-нибудь произойдет не так, как надо), в MySQL существуют следующие правила:

  • Все столбцы имеют значения по умолчанию.
  • Если в столбец вставляется "неправильное" значение (например, NULL в столбец NOT NULL или слишком большое числовое значение - в числовой столбец), MySQL не будет выводить сообщение об ошибке, а просто поместит в столбец "наиболее подходящее возможное значение". Для числовых значений это 0, наименьшие возможные значения или наибольшее возможное значение. Для строк это либо пустая строка, либо самая длинная строка, которая может быть в столбце.
  • Все вычисляемые выражения возвращают значение, которое можно использовать вместо того, чтобы сигнализировать об ошибке. Например, выражение 1/0 возвратит NULL

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

Отсюда следует, что MySQL нельзя использовать для проверки содержимого полей. Это нужно делать в приложении.

5.1.2 Вопросы переносимости

Поскольку все SQL-серверы поддерживают разные части стандарта SQL, то разработка переносимых SQL-приложений занимает время. Для очень простых запросов/вставок это достаточно просто, однако чем сложнее становится ваше приложение, тем сложнее делать запросы переносимыми. Если вы хотите чтобы ваше приложение работало максимально быстро с разными серверами SQL, задача еще более усложняется.

Чтобы сделать сложное приложение переносимым в области SQL, вам следует выбрать те SQL-серверы, с которыми оно должно работать.

Чтобы узнать, какие функции, типы и ограничения существуют в выбранных вами серверах, можно воспользоваться приложением MySQL crash-me. crash-me пока еще далека от того, чтобы тестировать все, что возможно, но тем не менее, является достаточно качественным сравнительным тестом по более чем 450 характеристикам.

Например, если вы хотите использовать Informix или DB2, имена полей не должны быть длиннее 18 символов.

И тесты MySQL (MySQL benchmarks), и программа crash-me являются достаточно независимыми от конкретной СУБД. Ознакомившись с тем, как мы решили этот вопрос, вы можете получить представление о том, как следует писать переносимые программы для работы с базами данных. Тесты можно найти в каталоге `sql-bench' в поставке исходных текстов MySQL. Они написаны на Perl с использованием интерфейса DBI (который, кстати, уже решает проблему получения доступа к разным базам данных).

См. http://www.mysql.com/information/benchmarks.html - там находятся результаты тестов.

Как можно видеть по этим результатам, у каждой СУБД есть свои слабые стороны. Все они построены по-разному и спроектированы с учетом различных компромиссов, что приводит к различиям в поведении этих систем.

Если независимость от СУБД для вас очень важна, вам нужно хорошо ощущать, где находятся слабые места в каждом сервере. MySQL - очень быстрый сервер, если речь идет о выборках/вставках, но у нас все еще есть проблемы, когда с одной таблицей в смешанном режиме работают медленные клиенты, делающие выборки и обновления. С другой стороны, при работе в Oracle возникают большие проблемы, когда вы хотите получить доступ к строке, которую только что обновили (до тех пор, пока она не будет сохранена на диске). Транзакционные базы данных обычно не очень подходят для генерации отчетов по файлам журналов, так как в этом случае блокировки совершенно бесполезны.

Чтобы сделать свое приложение действительно не зависящим от СУБД, вам следует создать некий быстро расширяемый интерфейс, через который происходит обработка данных. Поскольку C++ доступен на большинстве систем, имеет смысл создать соответствующие классы-интерфейсы к базам данных.

Если вы используете некоторые специфические функции СУБД (скажем, REPLACE в MySQL), вам следует написать код, реализующий этот метод для других серверов SQL. С MySQL вы можете использовать такой синтаксис для того, чтобы добавить некоторые специфические для MySQL ключевые слова в запрос: /*! */. Код внутри /* */ будет проигнорирован как комментарий большинством других SQL-серверов.

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

В этом случае структура таблицы должна содержать информацию об изначальном размере кэша и то, как часто таблица должна быть обновлена в общем случае.

5.1.3 Для чего мы использовали MySQL?

На первых этапах развития MySQL его функциональные возможности разрабатывались под потребности самого крупного из наших заказчиков. Это делалось для обслуживания больших хранилищ данных для пары самых крупных продавцов в Швеции.

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

Объем этих данных весьма значителен (в сумме приблизительно 7 миллионов транзакций в месяц), и, кроме того, мы должны предоставлять пользователям данные за периоды от 4 до 10 лет. Каждую неделю мы получаем от клиентов просьбы предоставить "мгновенный" доступ к новым отчетам на основе этих данных.

Эта проблема была решена следующим образом. Мы сохраняем всю информацию за месяц в сжатых таблицах "транзакций". У нас есть набор простых макросов (сценарий), генерирующий итоговые таблицы, сгруппированные по различным критериям (группа изделий, идентификатор заказчика, хранилище...) из таблиц транзакций. Отчеты - это веб-страницы, динамически генерирующиеся небольшим сценарием на Perl, который просматривает веб-страницу, выполняет SQL-операторы, содержащиеся в ней и вставляет результаты. Для этих целей можно было бы использовать PHP или модуль mod_perl, но в то время этих средств еще не существовало.

Для графических данных мы написали простой инструмент на C, который может создавать GIF-файлы на основе результата SQL-запроса (определенным образом обработав результат). Это также динамически выполняется из создаваемой Perl'ом странички.

В большинстве случаев новый отчет может быть создан просто путем копирования существующего сценария и модифицирования SQL-запроса в нем. Иногда требуется дополнительно добавить поля в существующую итоговую таблицу или сгенерировать новую таблицу, но это также делается очень просто, поскольку у нас все транзакционные таблицы хранятся на диске (в настоящее время у нас имеется меньшей мере 50Гб транзакционных таблиц и 200Гб других клиентских данных.)

Кроме того, мы обеспечиваем для наших клиентов возможность обращаться к итоговым таблицам непосредственно через интерфейс ODBC; таким образом, продвинутые пользователи могут самостоятельно экспериментировать с данными.

У нас не было каких-либо проблем при обработке этих данных на весьма скромном Sun Ultra SPARCstation (2x200 МГц). Недавно мы заменили один из наших серверов на двухпроцессорный UltraSPARC с тактовой частотой 400 МГц и теперь планируем начать обрабатывать транзакции на уровне продукта, что будет означать десятикратное увеличение объема данных. Мы полагаем, что сможем справиться с этим объемом лишь только добавлением соответствующего количества дисков.

Помимо этого мы экспериментируем с Intel-Linux, чтобы получить больше производительности по низшей цене. Теперь, имея бинарно-переносимый формат базы данных (появившийся в версии 3.23), мы начнем использовать его для некоторых частей приложения.

Наша интуиция подсказывает, что у Linux производительность значительно выше при низкой и средней загрузке, а у Solaris - когда высокая загрузка начнет возникать из-за критического дискового ввода-вывода. Но у нас нет пока никаких выводов по этому поводу. После обсуждения с разработчиками ядра Linux мы выяснили, что в это может быть побочным эффектом работы ядра: когда Linux дает слишком много ресурсов пакетным заданиям, задачи взаимодействия начинают замедляться. Из-за этого машина работает очень медленно и не реагирует ни на что, пока обрабатываются большие пакеты. Надеемся, что в последующих ядрах Linux этот вопрос найдет свое решение.

5.1.4 Набор тестов MySQL (The MySQL Benchmark Suite)

В данном разделе будет находиться техническое описание набора эталонных тестов MySQL (и crash-me), но оно пока еще не написано. В настоящее время можно получить хорошее представление об эталонном тесте, глядя на код и результаты в каталоге `sql-bench' любого исходного дистрибутива MySQL.

Данный набор эталонных создан с целью обеспечить эталонный тест, который будет информировать любого пользователя о том, что в данной реализации SQL выполняется хорошо, а что плохо.

Обратите внимание: этот эталонный тест - однопоточный, так что в нем измеряется минимальное время выполнения операций. В будущем мы планируем добавить в данный набор большое количество многопоточных тестов.

Например (выполнено на одной машине под NT 4.0):

Чтение 2000000 строк по индексу | Секунды | Секунды
mysql | 367 | 249
mysql_odbc | 464 |
db2_odbc | 1206 |
informix_odbc | 121126 |
ms-sql_odbc | 1634 |
oracle_odbc | 20800 |
solid_odbc | 877 |
sybase_odbc | 17614 |
Вставка 350768 строк | Секунды | Секунды
mysql | 381 | 206
mysql_odbc | 619 |
db2_odbc | 3460 |
informix_odbc | 2692 |
ms-sql_odbc | 4012 |
oracle_odbc | 11291 |
solid_odbc | 1801 |
sybase_odbc | 4802 |

В предыдущем тесте MySQL запускался с 8-мегабайтным индексным кэшем.

Гораздо больше результатов тестов вы сможете найти по адресу http://www.mysql.com/information/benchmarks.html.

Обратите внимание: данные об Oracle отсутствуют - по просьбе компании Oracle вся информация по их продукту была удалена. Все эталонные тесты для Oracle должны быть пропущены через компанию Oracle! Мы считаем, однако, что при таком способе тестирования результаты эталонных тестов для Oracle будут в очень высокой степени различаться, поскольку приведенные на сайте результаты призваны показывать на что способна стандартная инсталляция для одного клиента.

Чтобы выполнить набор эталонных тестов, необходимо загрузить исходный дистрибутив MySQL, установить драйвер perl DBI, драйвер perl DBD для той базы данных, которую нужно проверить, а затем выполнить:

cd sql-bench
perl run-all-tests --server=#

где # - один из поддерживаемых серверов. Список всех опций и поддерживаемых серверов можно получить, выполнив run-all-tests --help.

Программа crash-me пытается определить, какие функции поддерживаются СУБД, и какие возможности и ограничения имеют эти функции при выполнении запросов. Например, она определяет следующее:

  • какие типы столбцов поддерживаются
  • сколько индексов поддерживается
  • какие функции поддерживаются
  • насколько большим может быть запрос
  • насколько большим может быть столбец VARCHAR

Результат, полученные crash-me для большого количества различных СУБД, можно найти по адресу: http://www.mysql.com/information/crash-me.php.

5.1.5 Использование собственных тестов

Чтобы найти "узкие места" в своем приложении и базе данных, вы должны их тщательно протестировать. После устранения "узкого места" (или после замены его некой заглушкой) можно легко идентифицировать следующее "узкое место" (и так далее). Даже если общая производительность приложения достаточна, нужно по крайней мере выявить все "узкие места" и определиться с тем, как их устранять, - на будущее, если когда-нибудь потребуется дополнительная производительность.

Примеры переносимых программ программы для эталонного тестирования можно найти в наборе тестов MySQL. See section 5.1.4 Набор тестов MySQL (The MySQL Benchmark Suite). Можно взять любую программу из этого набора и модифицировать ее для своих потребностей. Таким образом можно испытывать различные решения проблемы и проверять, которое из них самое быстрое.

Зачастую некоторые проблемы проявляются только тогда, когда система очень сильно загружена. К нам часто обращаются клиенты, которые, запустив (протестированную) систему в производство, сталкиваются с проблемами, связанными с нагрузкой. На сегодня причиной каждого из этих случаев были либо проблемы, связанные с базовой конструкцией (при высокой нагрузке нехорошо выполняется сканирование таблиц), либо проблемы ОС/библиотек. И большинство таких проблем было бы намного легче устранить до начала промышленной эксплуатации систем.

Чтобы избежать подобных проблем, нужно постараться выполнить эталонное тестирование всего приложения при самой плохой возможной нагрузке! Для этого можно использовать программу Super Smack, которая доступна по адресу: http://www.mysql.com/Downloads/super-smack/super-smack-1.0.tar.gz. Эта программа, как следует из ее имени (smack - шлепок - прим. пер.), способна поставить систему на колени, так что используйте её только на разрабатываемых системах (проще говоря, в девелопменте).

5.2 Оптимизация SELECT и других запросов

Сначала приведем одно правило, касающееся всех запросов: Чем сложнее ваша система привилений, тем больше издержек.

Если не было выполнено никаких операторов GRANT, MySQL каким-то образом будет оптимизировать проверку полномочий. Таким образом при наличии очень большого объема данных лучше, наверное, будет работать без привилегий. В противном случае при большом количестве полномочий проверка результатов будет происходить с увеличенными издержками.

Если проблема состоит в некоторой явной функции MySQL, всегда можно протестировать ее в клиенте:

mysql> SELECT BENCHMARK(1000000,1+1);
+------------------------+
| BENCHMARK(1000000,1+1) |
+------------------------+
|                      0 |
+------------------------+
1 row in set (0.32 sec)

Из приведенного выше примера видно, что MySQL может выполнять более 1000000 операций сложения за 0,32 секунды на PentiumII 400MHz.

Все функции MySQL достаточно хорошо оптимизированы, но могут попадаться некоторые исключения, и функция BENCHMARK(число_циклов,выражение) - хороший инструмент для выяснения, присутствует ли проблема в запросе.

5.2.1 Синтаксис оператора EXPLAIN (получение информации о SELECT)

    EXPLAIN имя_таблицы
или EXPLAIN SELECT опции_выборки

EXPLAIN имя_таблицы является синонимом операторов DESCRIBE имя_таблицы и SHOW COLUMNS FROM имя_таблицы.

Если оператор SELECT предваряется ключевым словом EXPLAIN, MySQL сообщит о том, как будет производиться обработка SELECT, и предоставит информацию о порядке и методе связывания таблиц.

При помощи EXPLAIN можно выяснить, когда стоит снабдить таблицы индексами, чтобы получить более быструю выборку, использующую индексы для поиска записей.

Вы должны почаще запускать ANALYZE TABLE с тем, чтобы обновлялась статистика по таблицам, такая как кардинальность ключей, которые могут повлиять на выбор оптимизатора. See section 4.5.2 Синтаксис команды ANALYZE TABLE.

Можно проверить, насколько удачный порядок связывания таблиц был выбран оптимизатором. Заставить оптимизатор связывать таблицы в заданном порядке можно при помощи указания STRAIGHT_JOIN.

Для непростых соединений EXPLAIN возвращает строку информации о каждой из использованных в работе оператора SELECT таблиц. Таблицы перечисляются в том порядке, в котором они будут считываться. MySQL выполняет все связывания за один проход (метод называется "single-sweep multi-join"). Делается это так: MySQL читает строку из первой таблицы, находит совпадающую строку во второй таблице, затем - в третьей, и так далее. Когда обработка всех таблиц завершается, MySQL выдает выбранные столбцы и обходит в обратном порядке список таблиц до тех пор, пока не будет найдена таблица с наибольшим совпадением строк. Следующая строка считывается из этой таблицы и процесс продолжается в следующей таблице.

В MySQL 4.1, вывод EXPLAIN был изменен с тем, чтобы работать лучше с конструкциями типа UNION, подзапросами, и наследованными (вторичными, derived) таблицами. Наиболее заметным изменением стало введение двух новых столбцов: id и select_type.

Вывод команды EXPLAIN включает следующие столбцы:

id
Идентификатор SELECT, последовательный номер этого конкретного SELECT в запросе.
select_type
Тип оператора SELECT, который может быть один из следующих:
SIMPLE
Простая выборка (SELECT без UNION или подзапросов).
PRIMARY
Крайний SELECT.
UNION
Второй и дальнейшие UNION SELECT.
DEPENDENT UNION
Второй и дальнейшие UNION SELECT, зависящие от внешнего подзапроса.
SUBSELECT
Первый SELECT в подзапросе.
DEPENDENT SUBSELECT
Первый SELECT, зависящий от внешнего подзапроса.
DERIVED
Наследованная (вторичная) таблица SELECT.
table
Таблица, к которой относится выводимая строка.
type
Тип связывания. Ниже перечислены различные типы связывания, упорядоченные от лучшего к худшему:
system
Таблица содержит только одну строку (= системная таблица). Это - частный случай типа связывания const.
const
Таблица содержит не более одной соответствующей строки, которая будет считываться в начале запроса. Поскольку имеется только одна строка, оптимизатор в дальнейшем может расценивать значения этой строки в столбце как константы. Таблицы const являются очень быстрыми, поскольку они читаются только однажды!
eq_ref
Для каждой комбинации строк из предыдущих таблиц будет cчитываться одна строка из этой таблицы. Это наилучший возможный тип связывания среди типов, отличных от const. Данный тип применяется, когда все части индекса используются для связывания, а сам индекс - UNIQUE или PRIMARY KEY.
ref
Из этой таблицы будут считываться все строки с совпадающими значениями индексов для каждой комбинации строк из предыдущих таблиц. Тип ref применяется, если для связывания используется только крайний левый префикс ключа, или если ключ не является UNIQUE или PRIMARY KEY (другими словами, если на основании значения ключа для связывания не может быть выбрана одна строка). Этот тип связывания хорошо работает, если используемый ключ соответствует только нескольким строкам.
range
При помощи индекса для выборки строк будут извлечены только строки, находящиеся в заданном диапазоне. Используемый индекс указывается в столбце key. Столбец key_len содержит самую длинную часть ключа, которая была использована. Столбец ref будет содержать значения NULL для этого типа.
index
Данный тип аналогичен ALL, за исключением того, что просматривается только дерево индексов. Этот тип обычно более быстрый чем ALL, поскольку индексный файл, как правило, меньше файла данных.
ALL
Для каждой комбинации строк из предыдущих таблиц будет производиться полный просмотр этой таблицы. Это обычно плохо, если таблица - первая из не отмеченных как const, и очень плохо во всех остальных случаях. Как правило, можно избегать типа связывания ALL - путем добавления большего количества индексов таким образом, чтобы строка могла быть найдена при помощи константных значений или значений столбца из предыдущих таблиц.
possible_keys
Столбец possible_keys служит для указания индексов, которые может использовать MySQL для нахождения строк в этой таблице. Обратите внимание: этот столбец полностью независим от порядка таблиц. Это означает, что на практике некоторые ключи в столбце possible_keys могут не годиться для сгенерированного порядка таблиц. Если данный столбец пуст, то никаких подходящих индексов не имеется. В этом случае для увеличения производительности следует исследовать выражение WHERE, чтобы увидеть, есть ли в нем ссылки на какой-либо столбец (столбцы), которые подходили бы для индексации. Если да, создайте соответствующий индекс и снова проверьте запрос при помощи оператора EXPLAIN. See section 6.5.4 Синтаксис оператора ALTER TABLE. Чтобы увидеть, какие индексы есть в таблице, используйте команду SHOW INDEX FROM имя_таблицы.
key
Столбец key содержит ключ (индекс), который MySQL решил использовать в действительности. Если никакой индекс не был выбран, ключ будет иметь значение NULL. Чтобы заставить MySQL применить индекс из possible_keys, следует использовать оператор USE INDEX/IGNORE INDEX в запросе. See section 6.4.1 Синтаксис оператора SELECT. Также, выполнение myisamchk --analyze (see section 4.4.6.1 Синтаксис запуска myisamchk) или ANALYZE TABLE (see section 4.5.2 Синтаксис команды ANALYZE TABLE) по таблицам даст возможность оптимизатору принимать более правильные решения.
key_len
Столбец key_len содержит длину ключа, которую решил использовать MySQL. Если key имеет значение NULL, то длина ключа (key_len) тоже NULL. Обратите внимание: по значению длины ключа можно определить, сколько частей составного ключа в действительности будет использовать MySQL.
ref
Столбец ref показывает, какие столбцы или константы используются с ключом, указанным в key, для выборки строк из таблицы.
rows
В столбце rows указывается число строк, которые MySQL считает нужным проанализировать для выполнения запроса.
Extra
Этот столбец содержит дополнительную информацию о том, как MySQL будет выполнять запрос. Ниже объясняется значение каждой из текстовых строк, которые могут находиться в этом столбце:
Distinct
После нахождения первой совпадающей строки MySQL не будет продолжать поиск строк для текущей комбинации строк.
Not exists
MySQL смог осуществить оптимизацию LEFT JOIN для запроса и после нахождения одной строки, соответствующей критерию LEFT JOIN, не будет искать в этой таблице последующие строки для предыдущей комбинации строк. Например:
SELECT * FROM t1 LEFT JOIN t2 ON t1.id=t2.id WHERE t2.id IS NULL;
Предположим, что столбец t2.id определен как NOT NULL. В этом случае MySQL просмотрит таблицу t1 и будет искать строки в t2 соответствующие t1.id. Если MySQL находит в t2 нужную строку, он знает, что t2.id никогда не может иметь значение NULL, и не будет искать в t2 оставшуюся часть строк, имеющих тот же самый id. Другими словами, для каждой строки в t1 MySQL должен выполнить только один поиск в t2, независимо от того, сколько совпадающих строк содержится в t2.
range checked for each record (index map: #)
MySQL не нашел достаточно хорошего индекса для использования. Вместо этого для каждой комбинации строк в предшествующих таблицах он будет проверять, какой индекс следует использовать (если есть какой-либо индекс), и применять его для поиска строк в таблице. Это делается не очень быстро, но таким образом таблицы связываются быстрее, чем без индекса.
Using filesort
MySQL должен будет сделать дополнительный проход, чтобы выяснить, как извлечь строки в порядке сортировки. Для выполнения сортировки выполняется просмотр всех строк согласно типу связывания (join type) и сохраняются ключ сортировки плюс указатель на строку для всех строк, удовлетворяющих выражению WHERE. После этого ключи сортируются и строки извлекаются в порядке сортировки.
Using index
Для извлечения данных из столбца используется только информация дерева индексов; при этом нет необходимости производить собственно чтение записи. Это применимо для случаев, когда все используемые столбцы таблицы являются частью одного индекса.
Using temporary
Чтобы выполнить запрос, MySQL должен будет создать временную таблицу для хранения результата. Это обычно происходит, если предложение ORDER BY выполняется для набора столбцов, отличного от того, который используется в предложении GROUP BY.
Using where
Выражение WHERE будет использоваться для выделения тех строк, которые будут сопоставляться со следующей таблицей или тех, которые будут посланы клиенту. Если этой информации нет, а таблица имеет тип ALL или index, то, значит, в вашем запросе есть какая-то ошибка (если вы не собираетесь делать выборку/тестирование всех строк таблицы).
Если нужно, чтобы запросы выполнялись настолько быстро, насколько это возможно, посмотрите, есть ли строки упоминания Using filesort и Using temporary.

Существует неплохой способ определить, насколько хорошим является тип связывания. Для этого нужно перемножить все значения столбца rows, выводимого командой EXPLAIN. Результатом будет грубая оценка того, сколько строк должен просмотреть MySQL для выполнения запроса. Это же число используется для ограничения запросов в переменной max_join_size. See section 5.5.2 Настройка параметров сервера.

В следующем примере показано, как можно постепенно оптимизировать JOIN при помощи информации, выводимой оператором EXPLAIN.

Предположим, что имеется представленный ниже оператор SELECT, который нужно исследовать при помощи команды EXPLAIN:

EXPLAIN SELECT tt.TicketNumber, tt.TimeIn,
            tt.ProjectReference, tt.EstimatedShipDate,
            tt.ActualShipDate, tt.ClientID,
            tt.ServiceCodes, tt.RepetitiveID,
            tt.CurrentProcess, tt.CurrentDPPerson,
            tt.RecordVolume, tt.DPPrinted, et.COUNTRY,
            et_1.COUNTRY, do.CUSTNAME
        FROM tt, et, et AS et_1, do
        WHERE tt.SubmitTime IS NULL
            AND tt.ActualPC = et.EMPLOYID
            AND tt.AssignedPC = et_1.EMPLOYID
            AND tt.ClientID = do.CUSTNMBR;

Для этого примера принимается, что:

  • Сравниваемые столбцы были объявлены следующим образом:
    Таблица | Столбец | Тип столбца
    tt | ActualPC | CHAR(10)
    tt | AssignedPC | CHAR(10)
    tt | ClientID | CHAR(10)
    et | EMPLOYID | CHAR(15)
    do | CUSTNMBR | CHAR(15)
  • Таблицы проиндексированы следующим образом:
    Таблица | Индекс
    tt | ActualPC
    tt | AssignedPC
    tt | ClientID
    et | EMPLOYID (primary key)
    do | CUSTNMBR (primary key)
  • Значения tt.ActualPC распределены не равномерно.

На начальном этапе перед выполнением какой-либо оптимизации оператор EXPLAIN выведет следующую информацию:

table type possible_keys                key  key_len ref  rows  Extra
et    ALL  PRIMARY                      NULL NULL    NULL 74
do    ALL  PRIMARY                      NULL NULL    NULL 2135
et_1  ALL  PRIMARY                      NULL NULL    NULL 74
tt    ALL  AssignedPC,ClientID,ActualPC NULL NULL    NULL 3872
      range checked for each record (key map: 35)

Поскольку каждая таблица имеет тип (type) ALL, из приведенного выше вывода видно, что MySQL будет делать полное связывание всех таблиц! Это займет долгое время, поскольку для выполнения такого связывания должно быть рассмотрено произведение числа строк в каждой таблице! Для нашего случая такое произведение - 74 * 2135 * 74 * 3872 = 45268558720 строк. Если таблицы большие, трудно даже представить себе, как долго они будут связываться.

Одна проблема здесь состоит в том, что MySQL не может (пока еще) эффективно применять индексы к столбцам, если они объявлены по-разному. В этом контексте тип VARCHAR и тип CHAR - одинаковы, если они не объявлены с различной длиной. Поскольку столбец tt.ActualPC объявлен как CHAR(10), а et.EMPLOYID - как CHAR(15), имеется несоответствие по длине значений.

Чтобы устранить это несоответствие между длинами столбцов, следует использовать команду ALTER TABLE для удлинения столбца ActualPC от 10 символов до 15 символов:

mysql> ALTER TABLE tt MODIFY ActualPC VARCHAR(15);

Теперь оба столбца tt.ActualPC и et.EMPLOYID имеют тип VARCHAR(15). При повторном выполнении оператора EXPLAIN будет выведен следующий результат:

table type   possible_keys   key     key_len ref         rows    Extra
tt    ALL    AssignedPC,ClientID,ActualPC NULL NULL NULL 3872    Using where
do    ALL    PRIMARY         NULL    NULL    NULL        2135
      range checked for each record (key map: 1)
et_1  ALL    PRIMARY         NULL    NULL    NULL        74
      range checked for each record (key map: 1)
et    eq_ref PRIMARY         PRIMARY 15      tt.ActualPC 1

Это не идеально, но уже намного лучше (произведение значений строк (rows) теперь уменьшилось в 74 раза). Такое связывание выполнится за пару секунд.

Можно сделать еще одно изменение - чтобы устранить несоответствие длин столбцов для сравнений tt.AssignedPC = et_1.EMPLOYID и tt.ClientID = do.CUSTNMBR.

mysql> ALTER TABLE tt MODIFY AssignedPC VARCHAR(15),
    ->                MODIFY ClientID   VARCHAR(15);

Теперь оператор EXPLAIN будет выводить такую информацию:

table type   possible_keys   key      key_len ref           rows Extra
et    ALL    PRIMARY         NULL     NULL    NULL          74
tt    ref    AssignedPC,     ActualPC 15      et.EMPLOYID   52   Using where
             ClientID,
             ActualPC
et_1  eq_ref PRIMARY         PRIMARY  15      tt.AssignedPC 1
do    eq_ref PRIMARY         PRIMARY  15      tt.ClientID   1

Это почти идеально.

Осталась еще одна проблема. Она заключается в том, что по умолчанию MySQL принимает, что значения в столбце tt.ActualPC распределены равномерно, но в таблице tt это не так. К счастью, проинформировать MySQL об этом можно очень просто:

shell> myisamchk --analyze PATH_TO_MYSQL_DATABASE/tt
shell> mysqladmin refresh

Теперь связывание совершенно, и оператор EXPLAIN выведет такой результат:

table type   possible_keys key     key_len ref           rows Extra
tt    ALL    AssignedPC    NULL    NULL    NULL          3872 Using where
             ClientID,
             ActualPC
et    eq_ref PRIMARY       PRIMARY 15      tt.ActualPC   1
et_1  eq_ref PRIMARY       PRIMARY 15      tt.AssignedPC 1
do    eq_ref PRIMARY       PRIMARY 15      tt.ClientID   1

Обратите внимание: столбец rows в выводе оператора EXPLAIN - опытное предположение оптимизатора связей MySQL. Чтобы оптимизировать запрос, нужно проверить, являются ли числа близкими к действительным. Если нет, можно получить лучшую производительность, используя в операторе SELECT соединение STRAIGHT_JOIN и попытаться задать другой порядок таблиц в выражении FROM.

5.2.2 Оценка производительности запроса

В большинстве случаев можно оценивать производительность путем подсчета дисковых операций. Для маленьких таблиц можно обычно принимать 1 строку за 1 операцию дискового поиска (поскольку индекс, скорее всего, в кэше). Для больших таблиц можно считать, что (при использовании индексов типа B++ деревьев) для нахождения строки потребуется

log(количество_строк) / log(длина_индексного_блока / 3 * 2 / (длина_индекса + длина_указателя_на_данные)) + 1

дисковая операция для получения строки.

Обычно в MySQL индексный блок занимает 1024 байта, а указательн - 4 байта. Для таблицы, содержащей 500000 строк и имеющей длину индекса 3 (medium integer) потребуется log(500,000)/log(1024/3*2/(3+4)) + 1 = 4 дисковых операции поиска.

Поскольку вышеупомянутый индекс будет занимать приблизительно 500000 * 7 * 3/2 = 5,2Mб (если учитывать, что индексные буфера обычно заполняются на 2/3), большая часть индекса, скорее всего, окажется в памяти, и для того, чтобы найти строку, потребуется лишь 1-2 обращения к ОС для чтения.

Для записи, однако, потребуется 4 дисковых запроса (таких, какие рассматривались выше) чтобы найти место для помещения нового индекса, и обычно 2 дисковых операции, чтобы обновить индекс и вставить строку.

Обратите внимание: сказанное выше не означает, что производительность приложения будет ухудшаться в log N раз! Поскольку все кэшируется в OС или на SQL-сервере, замедление работы при увеличении таблицы будет незначительным. И лишь после того, как данных станет так много, что они перестанут помещаться в кэш, замедление работы там, где работа приложения сводится только к операциям дискового поиска (количество которых растет в log N), станет гораздо ощутимей. Чтобы избежать этого, следует увеличить индексный кэш так, чтобы он вмещал возросшее количество данных. See section 5.5.2 Настройка параметров сервера.

5.2.3 Скорость выполнения запросов SELECT

В общем случае для того, чтобы заставить медленный SELECT ... WHERE работать быстрее, прежде всего нужно выяснить, можно ли добавить индекс. Для всех ссылок между различными таблицами должны, как правило, применяться индексы. Чтобы определить, какие индексы используются для выборки SELECT, можно использовать EXPLAIN. See section 5.2.1 Синтаксис оператора EXPLAIN (получение информации о SELECT).

Вот несколько общих советов:

  • Чтобы MySQL лучше оптимизировал запросы, можно выполнить myisamchk --analyze для таблицы после того, как она загружена соответствующими данными. Таким образом для каждой части индекса будет обновлено значение, указывающее среднее число строк, имеющих одинаковые значения (для уникальных индексов это всегда 1, разумеется). MySQL будет использовать это число, чтобы решить, какой индекс следует выбрать для связывания двух таблиц при помощи "неконстантного выражения". Результат работы analyze можно увидеть в столбце Cardinality после выполнения команды SHOW INDEX FROM имя_таблицы.
  • Чтобы отсортировать индекс и данные в соответствии с индексом, используйте myisamchk --sort-index --sort-records=1 (если нужно отсортировать по индексу 1). Если имеется уникальный индекс, по которому вы хотите считывать все записи в порядке, соответствующем данному индексу, это - хороший способ ускорить считывание записей. Обратите внимание, однако, что эта сортировка написана не оптимально и для большой таблицы будет выполняться долго!

5.2.4 Как MySQL оптимизирует выражения WHERE

Описание оптимизации выражений WHERE помещено в раздел, посвященный SELECT, потому что они главным образом используются в запросах SELECT, но для выражений WHERE в операторах DELETE и UPDATE используются те же способы оптимизации.

Отметим также, что данный раздел неполон. В MySQL реализовано много возможностей оптимизации, и у нас не было времени, чтобы задокументировать их все.

Ниже перечислены некоторые из оптимизации, выполняемых MySQL:

  • Удаляются ненужные скобки:
       ((a AND b) AND c OR (((a AND b) AND (c AND d))))
-> (a AND b AND c) OR (a AND b AND c AND d)
  • Константы заменяются значениями:
       (a<b AND b=c) AND a=5
-> b>5 AND b=c AND a=5
  • Удаляются условия для констант (требуется при замене констант значением):
       (B>=5 AND B=5) OR (B=6 AND 5=5) OR (B=7 AND 5=6)
-> B=5 OR B=6
  • Константные выражения, используемые индексами, оцениваются только один раз.
  • Для таблиц HEAP и MyISAM функция COUNT(*), которая вызывается для одной таблицы и не содержит предложения WHERE, берется непосредственно из табличной информации. Это делается также для любого выражения NOT NULL, в котором используется только одна таблица.
  • Недопустимые константные выражения выявляются на ранних этапах. MySQL быстро обнаруживает, что некоторые операторы SELECT неосуществимы и не возвращают строк.
  • Выполняется слияние выражения HAVING с WHERE, если не используется предложение GROUP BY или групповые функции (COUNT(), MIN()...).
  • Для каждого подчиненного связывания создается более простое предложение WHERE, чтобы ускорить оценку WHERE для каждого подчиненного связывания а также чтобы пропустить записи как можно быстрее.
  • Все константные таблицы считываются в первую очередь, перед любыми другими таблицами в запросе. К константным таблицам относятся следующие:
    • Пустая таблица или таблица с 1 строкой.
    • Таблица, которая используется с выражением WHERE для индекса UNIQUE, или PRIMARY KEY, где все части индекса используются с константными выражениями и части индекса определены как NOT NULL.
    Все эти таблицы используются как константные таблицы:
    mysql> SELECT * FROM t WHERE primary_key=1;
mysql> SELECT * FROM t1,t2
    ->          WHERE t1.primary_key=1 AND t2.primary_key=t1.id;
  • Лучшая комбинацию связывания для связывания таблиц находится путем испытания всех возможных вариантов. Если все столбцы в предложениях ORDER BY и GROUP BY принадлежат одной таблице, эта таблица рассматривается первой при связывании.
  • Если имеется выражение ORDER BY и отличное от него выражение GROUP BY, или если выражения ORDER BY или GROUP BY содержат столбцы не только из первой таблицы в очереди на связывание, но и из других таблиц, то тогда создается временная таблица.
  • Если используется SQL_SMALL_RESULT, MySQL будет применять временную таблицу, которую разместит в памяти.
  • Запрашивается каждый индекс таблицы, и используется лучший, охватывающий менее 30% строк. Если такой индекс найти нельзя, используется быстрое сканирование таблицы.
  • В некоторых случаях MySQL может читать данные из индекса даже без обращения к файлу данных. Если все столбцы, используемые в индексе, числовые, то для выполнения запроса будет использоваться только индексное дерево.
  • Перед выводом каждой записи пропускаются те, которые не соответствуют выражению HAVING.

Вот некоторые примеры очень быстрых запросов:

mysql> SELECT COUNT(*) FROM tbl_name;
mysql> SELECT MIN(key_part1),MAX(key_part1) FROM tbl_name;
mysql> SELECT MAX(key_part2) FROM tbl_name
    ->        WHERE key_part_1=constant;
mysql> SELECT ... FROM tbl_name
    ->        ORDER BY key_part1,key_part2,... LIMIT 10;
mysql> SELECT ... FROM tbl_name
    ->        ORDER BY key_part1 DESC,key_part2 DESC,... LIMIT 10;

Для выполнения следующих запросов используется только индексное дерево (предполагается, что индексированные столбцы числовые):

mysql> SELECT key_part1,key_part2 FROM tbl_name WHERE key_part1=val;
mysql> SELECT COUNT(*) FROM tbl_name
    ->        WHERE key_part1=val1 AND key_part2=val2;
mysql> SELECT key_part2 FROM tbl_name GROUP BY key_part1;

Следующие запросы используют индексацию, чтобы получить отсортированные строки без дополнительного прохода для сортировки:

mysql> SELECT ... FROM tbl_name
    ->            ORDER BY key_part1,key_part2,... ;
mysql> SELECT ... FROM tbl_name
    ->            ORDER BY key_part1 DESC,key_part2 DESC,... ;

5.2.5 Как MySQL оптимизирует DISTINCT

DISTINCT преобразовывается к GROUP BY для всех столбцов, для DISTINCT в сочетании с ORDER BY, помимо этого, во многих случаях также требуется временная таблица.

Если LIMIT # указывается совместно с DISTINCT, MySQL остановится, как только найдет # уникальных строк.

Если не все столбцы и не во всех таблицах используются, MySQL прекратит сканирование неиспользуемых таблиц, как только найдет первое совпадение.

SELECT DISTINCT t1.a FROM t1,t2 where t1.a=t2.a;

В случае, если, предположим, таблица t1 используется перед t2 (это проверяется при помощи EXPLAIN), MySQL прекратит чтение в t2 (для каждой отдельной строки из t1), после того как найдет первую строку в t2.

5.2.6 Как MySQL оптимизирует LEFT JOIN и RIGHT JOIN

Выражение "A LEFT JOIN B" в MySQL реализовано следующим образом:

  • Таблица B устанавливается как зависимая от таблицы A и от всех таблиц, от которых зависит A.
  • Таблица A устанавливается как зависимая ото всех таблиц (кроме B), которые используются в условии LEFT JOIN.
  • Все условия LEFT JOIN перемещаются в предложение WHERE.
  • Выполняются все стандартные способы оптимизации соединения, за исключением того, что таблица всегда читается после всех таблиц, от которых она зависит. Если имеется циклическая зависимость, MySQL выдаст ошибку.
  • Выполняются все стандартные способы оптимизации WHERE.
  • Если в таблице A имеется строка, соответствующая выражению WHERE, но в таблице B ни одна строка не удовлетворяет условию LEFT JOIN, генерируется дополнительная строка B, в которой все значения столбцов устанавливаются в NULL.
  • Если LEFT JOIN используется для поиска тех строк, которые отсутствуют в некоторой таблице, и в предложении WHERE выполняется следующая проверка: column_name IS NULL, где column_name - столбец, который объявлен как NOT NULL, MySQL пререстанет искать строки (для отдельной комбинации ключа) после того, как найдет строку, соответствующую условию LEFT JOIN.

RIGHT JOIN реализован аналогично LEFT JOIN.

При указании жесткого порядка чтения таблиц в LEFT JOIN и STRAIGHT JOIN оптимизатор связей (который определяет, в каком порядке таблицы должны быть связаны) будет выполнять работу намного быстрее, так как ему потребуется проверять меньшее количество перестановок таблиц.

Обратите внимание: отсюда следует, что если выполняется запрос типа

SELECT * FROM a,b LEFT JOIN c ON (c.key=a.key) LEFT JOIN d (d.key=a.key)
         WHERE b.key=d.key

MySQL будет делать полный просмотр таблицы b, поскольку LEFT JOIN заставит его читать эту таблицу перед d.

В этом случае, чтобы предотвратить полный просмотр таблицы b, нужно изменить запрос таким образом:

SELECT * FROM b,a LEFT JOIN c ON (c.key=a.key) LEFT JOIN d (d.key=a.key)
         WHERE b.key=d.key

5.2.7 Как MySQL оптимизирует ORDER BY

В некоторых случаях MySQL может использовать индекс, чтобы выполнить запрос ORDER BY или GROUP BY без выполнения дополнительной сортировки.

Индекс может также использоваться и тогда, когда предложение ORDER BY не соответствует индексу в точности, если все неиспользуемые части индекса и все столбцы, не указанные в ORDER BY - константы в выражении WHERE. Следующие запросы будут использовать индекс, чтобы выполнить ORDER BY / GROUP BY.

SELECT * FROM t1 ORDER BY key_part1,key_part2,...
SELECT * FROM t1 WHERE key_part1=constant ORDER BY key_part2
SELECT * FROM t1 WHERE key_part1=constant GROUP BY key_part2
SELECT * FROM t1 ORDER BY key_part1 DESC,key_part2 DESC
SELECT * FROM t1 WHERE key_part1=1 ORDER BY key_part1 DESC,key_part2 DESC

Ниже приведены некоторые случаи, когда MySQL не может использовать индексы, чтобы выполнить ORDER BY (обратите внимание, что MySQL тем не менее будет использовать индексы, чтобы найти строки, соответствующие выражению WHERE):

  • Сортировка ORDER BY делается по нескольким ключам: SELECT * FROM t1 ORDER BY key1,key2
  • Сортировка ORDER BY делается, при использовании непоследовательных частей ключа: SELECT * FROM t1 WHERE key2=constant ORDER BY key_part2
  • Смешиваются ASC и DESC. SELECT * FROM t1 ORDER BY key_part1 DESC,key_part2 ASC
  • Для выборки строк и для сортировки ORDER BY используются разные ключи: SELECT * FROM t1 WHERE key2=constant ORDER BY key1
  • Связываются несколько таблиц, и столбцы, по которым делается сортировка ORDER BY, относятся не только к первой неконстантной (const) таблице, используемой для выборки строк (это первая таблица в выводе EXPLAIN, в которой не используется константный, const, метод выборки строк).
  • Имеются различные выражения ORDER BY и GROUP BY.
  • Используемый индекс таблицы имеет такой тип, который не обеспечивает сортированного хранения строк (как индекс HASH в таблицах HEAP).

В тех случаях, когда MySQL должен сортировать результат, он использует следующий алгоритм:

  • Считываются все строки согласно ключу или путем сканирования таблицы. Строки, которые не соответствует предложению WHERE, пропускаются.
  • Ключ сортировки сохраняется в буфере сортировки (размера sort_buffer)
  • Когда буфер заполняется, содержимое буфера сортируется алгоритмом qsort, результаты сохраняются во временном файле. Сохраняется указатель на отсортированный блок (в том случае, когда все строки умещаются в буфере сортировки, временный файл не создается).
  • Вышеупомянутое действие повторяется, пока не будут считаны все строки.
  • Делается мультислияние до MERGEBUFF (7) областей в один блок в другом временном файле. Это действие повторяется, пока все блоки из первого файла не окажутся во втором файле.
  • Предыдущий пункт повторяется, пока не останется менее MERGEBUFF2 (15) блоков.
  • При последнем мультислиянии в результирующий файл записывается только указатель на строку (последняя часть ключа сортировки).
  • Теперь код в файле `sql/records.cc' будет использоваться для чтения данных в отсортированном порядке, с использованием указателей на строки из результирующего файла. Чтобы оптимизировать этот процесс, мы считываем большой блок указателей на строки, сортируем их, и затем считываем строки в отсортированном порядке в буфер строк (record_rnd_buffer).

При помощи команды EXPLAIN SELECT ... ORDER BY можно проверить, может ли MySQL использовать индексы для выполнения запроса. Если в столбце extra содержится значение Using filesort, то MySQL не может использовать индексы для выполнения сортировки ORDER BY. See section 5.2.1 Синтаксис оператора EXPLAIN (получение информации о SELECT).

Чтобы сортировка ORDER BY выполнялась с большей скоростью, нужно сначала посмотреть, можно ли заставить MySQL использовать индексы взамен дополнительной фазы сортировки. Если это невозможно, то можно сделать следующее:

  • Увеличить значение переменной sort_buffer.
  • Увеличить значение переменной record_rnd_buffer.
  • Изменить переменную tmpdir, чтобы она указывала на выделенный диск с большим количеством свободного пространства. Начиная с MySQL 4.1, в tmpdir могут быть указаны несколько путей, разделенных двоеточием : (точкой с запятой на Windows ;). Эти пути будут использованы в ротации. Внимание: Эти пути должны находится на разных физических дисках, не на разных разделах одного и того же диска.

MySQL по умолчанию сортирует все GROUP BY x,y[,...] запросы так, как если бы вы указали ORDER BY x,y[,...]. MySQL будет оптимизировать любой ORDER BY как сказано выше, без всяких потерь производительности. Если, как в некоторых случаях, вы не хотите иметь результат отсортированным, вы можете указать ORDER BY NULL:

INSERT INTO foo SELECT a,COUNT(*) FROM bar GROUP BY a ORDER BY NULL;

5.2.8 Как MySQL оптимизирует LIMIT

В некоторых случаях, когда используется LIMIT # и не используется HAVING, MySQL будет выполнять запрос несколько иначе:

  • Если при помощи LIMIT выбираются только несколько строк, MySQL будет использовать индексы в тех некоторых случаях, когда он обычно предпочел бы делать полное сканирование таблицы.
  • Если LIMIT # используется с ORDER BY, MySQL закончит сортировку, как только найдет первые # строк, вместо того, чтобы сортировать всю таблицу.
  • При сочетании LIMIT # с DISTINCT MySQL остановится, как только найдет # уникальных строк.
  • В некоторых случаях группировка GROUP BY может быть выполнена путем упорядоченного считывания ключа (или путем выполнения сортировки по ключу) и последующего вычисления итогового результата пока не изменится значение ключа. В этом случае LIMIT # не будет вычислять какие-либо ненужные предложения GROUP BY.
  • После того как MySQL пошлет первые # строк клиенту, он прервет выполнение запроса (если не используется SQL_CALC_FOUND_ROWS).
  • LIMIT 0 всегда будет быстро возвращать пустую выборку. Эта команда полезна для проверки запроса и получения типов столбцов результата.
  • Если сервер для выполнения запроса использует временные таблицы, LIMIT # применяется для вычисления того, сколько для них потребуется места.

5.2.9 Скорость выполнения запросов INSERT

Время, необходимое для вставки записи, можно грубо разделить на такие промежутки:

  • Подсоединение: (3)
  • Посылка запроса на сервер: (2)
  • Синтаксический анализ запроса: (2)
  • Вставка записи: (1 * размер записи)
  • Вставка индексов: (1 * число индексов)
  • Закрытие: (1)

где числа в скобках пропорциональны полному времени. При этом не учитывается время в начале вставки, требующееся для открытия таблиц (таблицы открываются один раз для каждого конкурентно выполняющегося запроса).

Размер таблицы замедляет вставку индексов в log N раз (B-деревья).

Некоторые способы ускорения вставки:

  • Если с одного клиента одновременно вставляется большое количество строк, используйте операторы INSERT в форме, содержащей множество записей. При этом вставка будет происходить намного быстрее (в некоторых случаях в несколько раз), чем при использовании отдельных операторов INSERT. При добавлении данных в непустую таблицу можно настроить переменную bulk_insert_buffer_size так, чтобы это делалось еще быстрее. See section 4.5.6.4 SHOW VARIABLES.
  • При вставке нескольких строк с различных клиентов можно повысить скорость, используя оператор INSERT DELAYED. See section 6.4.3 Синтаксис оператора INSERT.
  • Обратите внимание: при использовании таблиц MyISAM можно вставлять строки во время выполнения операторов SELECT, если в таблицах нет удаленных строк.
  • При загрузке таблицы из текстового файла используйте команду LOAD DATA INFILE. При этом обычно вставка будет происходить в 20 раз быстрее, чем при использовании соответствующего количества операторов INSERT. See section 6.4.9 Синтаксис оператора LOAD DATA INFILE.
  • Если таблица имеет много индексов, можно проделать некоторую дополнительную работу, чтобы команда LOAD DATA INFILE выполнялась еще быстрее. Используйте следующую процедуру:
    1. При необходимости создайте таблицу при помощи оператора CREATE TABLE (например, используя mysql или Perl-DBI).
    2. Выполните оператор FLUSH TABLES или команду оболочки: mysqladmin flush-tables.
    3. Используйте myisamchk --keys-used=0 -rq /path/to/db/tbl_name. После этого индексы не будут использоваться для данной таблицы.
    4. Вставьте данные в таблицу при помощи LOAD DATA INFILE. При этом никакие индексы обновляться не будут и, следовательно, скорость будет высокой весьма.
    5. Если вы собираетесь в будущем только лишь читать таблицу, выполните myisampack для этой таблицы, чтобы уменьшить ее размер. See section 4.7.4 myisampack, MySQL-генератор сжатых таблиц (только для чтения).
    6. Воссоздайте индексы при помощи команды myisamchk -r -q /path/to/db/tbl_name. Эта процедура создает индексное дерево в памяти, перед тем как записать его на диск, что гораздо быстрее за счет исключения большого количества дисковых операций. Индексное дерево, получившееся в результате, к тому же отлично сбалансировано.
    7. Выполните оператор FLUSH TABLES или команду оболочки: mysqladmin flush-tables.
    Обратите внимание: команда LOAD DATA INFILE также выполняет вышеупомянутую оптимизацию при вставках в пустую таблицу. Главное отличие этой команды от вышеупомянутой процедуры заключается в том, что при помощи myisamchk можно выделить намного больше временной памяти для создания индекса, чем MySQL, по вашему мнению, должен выделять для каждого воссоздания индексов. Начиная с MySQL 4.0 можно также использовать команду ALTER TABLE tbl_name DISABLE KEYS вместо myisamchk --keys-used=0 -rq /path/to/db/tbl_name и ALTER TABLE tbl_name ENABLE KEYS вместо myisamchk -r -q /path/to/db/tbl_name. Таким образом можно также пропускать шаги FLUSH TABLES.
  • Можно ускорять операции вставки, выполняемые несколькими операторами, путем установки блокировки таблиц:
    mysql> LOCK TABLES a WRITE;
mysql> INSERT INTO a VALUES (1,23),(2,34),(4,33);
mysql> INSERT INTO a VALUES (8,26),(6,29);
mysql> UNLOCK TABLES;
    Главный фактор, влияющий на скорость, - то, что буфер индексов сбрасывается на диск только один раз, после завершения всех операторов INSERT. Обычно содержимое индексных буферов сбрасывалось бы на диск столько раз, сколько имеется различных операторов INSERT. Блокировка не нужна, если можно вставить все строки при помощи одного оператора. Для транзакционных таблиц, чтобы повысить скорость, следует использовать BEGIN/COMMIT вместо LOCK TABLES. Блокировка также понизит полное время проверки подсоединений (multi-connection tests), но максимальное время ожидания для некоторых потоков повысится (потому что они ожидают снятия блокировки). Например:
    поток 1 делает 1000 вставок
потоки 2, 3 и 4 делают 1 вставку
поток 5 делает 1000 вставок
    Если блокировка не используется, 2, 3, и 4 завершат выполнение раньше, чем 1 и 5. Если блокировка используется, 2, 3 и 4, видимо, не закончат выполнение раньше, чем 1 или 5, но общее время должно приблизительно уменьшиться на 40%. Так как в MySQL операции INSERT, UPDATE и DELETE очень быстрые, общая производительность будет улучшаться, если добавлять блокировки ко всем командам, делающим более 5 вставок или обновлений подряд. Если делается очень много вставок строк, можно время от времени сопровождать команду LOCK TABLES командой UNLOCK TABLES (после каждых 1000 строк), чтобы позволить другим потокам обращаться к таблице. Результатом всего этого будет получение хорошей производительности. Конечно, для загрузки данных намного более быстрой является команда LOAD DATA INFILE.

Чтобы дополнительно повысить скорость выполнения команд LOAD DATA INFILE и INSERT, увеличьте буфер ключа (key buffer). See section 5.5.2 Настройка параметров сервера.

5.2.10 Скорость выполнения запросов UPDATE

Запросы UPDATE оптимизируются как запрос SELECT с дополнительными издержками на запись. Скорость записи зависит от размера обновляемых данных и количества обновляемых индексов. Индексы, которые не были изменены, обновлены не будут.

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

Обратите внимание: при использовании динамического формата записи, если запись обновляется более длинной, может произойти "расслоение" записи. Таким образом, если вы делаете это часто, очень важно время от времени выполнять команду OPTIMIZE TABLE. See section 4.5.1 Синтаксис команды OPTIMIZE TABLE.

5.2.11 Скорость выполнения запросов DELETE

Чтобы удалить все строки в таблице, нужно использовать команду TRUNCATE TABLE table_name. See section 6.4.7 Синтаксис оператора TRUNCATE.

Время, необходимое для удаления записи, прямо пропорционально числу индексов. Чтобы записи удалялись быстрее, можно увеличить размер индексного кэша. See section 5.5.2 Настройка параметров сервера.

5.2.12 Другие советы по оптимизации

Несортированные советы для повышения скорости систем:

  • Используйте постоянные соединения с базой данных, чтобы избежать издержек на подключения. Если невозможно использовать постоянные соединения и осуществляется большое количество новых подключений к базе данных, то можно изменить значение переменной thread_cache_size. See section 5.5.2 Настройка параметров сервера.
  • Всегда проверяйте, чтобы все ваши запросы действительно использовали созданные вами в таблицах индексы. В MySQL это можно сделать с помощью команды EXPLAIN. See section 5.2.1 Синтаксис оператора EXPLAIN (получение информации о SELECT).
  • Старайтесь избегать сложных запросов SELECT на часто обновляемых таблицах типа MyISAM. Это помогает избежать проблем с блокировкой таблиц.
  • Новые таблицы MyISAM могут вносить записи в таблицу без удаляемых записей, которые в то же самое время читает иная таблица. Если это имеет для вас значение, то следует рассмотреть методы, не требующие удаления записей или запускать OPTIMIZE TABLE после удаления большого количества строк.
  • Используйте ALTER TABLE ... ORDER BY expr1,expr2... если вы большей частью извлекаете записи в порядке expr1,expr2... Можно получить более высокую производительность, используя эту опцию после больших преобразований в таблице.
  • В некоторых случаях может оказаться целесообразным введение столбца, базирующегося на "хэшированной" информации из других столбцов. Если этот столбец невелик и достаточно уникален, то он может быть намного быстрее, чем большой индекс на многих столбцах. В MySQL очень просто использовать подобный дополнительный столбец: SELECT * FROM table_name WHERE hash=MD5(CONCAT(col1,col2)) AND col_1='constant' AND col_2='constant'
  • Для часто изменяющихся таблиц следует избегать типов VARCHAR или BLOB для всех столбцов. При использовании единичного столбца VARCHAR или BLOB вы получите динамическую длину строки. See section 7 Типы таблиц MySQL.
  • Разделение таблицы на несколько различных таблиц просто потому, что строки получаются "большими", обычно не приносит пользы. Чтобы получить доступ к строке, наиболее трудоемким оказывается поиск по диску для нахождения первого байта этой строки. После нахождения этих данных большинство новых дисков могут прочесть всю строку достаточно быстро для большинства приложений. Разделение таблицы имеет значение только в следующих случаях: когда это таблица с динамическим размером строки (смотрите выше), которую можно изменить на строку фиксированного размера, или когда необходимо просматривать таблицу очень часто и нет необходимости в большинстве столбцов. See section 7 Типы таблиц MySQL.
  • Если очень часто приходится производить вычисления, базирующиеся на информации из большого количества строк (такие как подсчет предметов), то, вероятно, намного лучше ввести новую таблицу и обновлять счетчик в режиме реального времени. Обновление вида UPDATE table SET count=count+1 WHERE index_column=constant является очень быстрым! Это действительно важно при использовании типов таблиц MySQL, вроде MyISAM или ISAM, имеющих только блокирование таблиц (многочисленные читающие/единственный записывающий). Для многих баз данных это обеспечит также более высокую производительность, поскольку программа управления блокировкой строк в этом случае будет иметь меньше работы.
  • Если необходимо собирать статистические данные из больших журнальных таблиц, то используйте сводные таблицы вместо сканирования целой таблицы. Поддерживать сводные таблицы должно быть намного быстрее, чем пытаться сделать ``живую'' статистику. Намного быстрее воспроизвести новые сводные таблицы из журналов, когда что-либо изменяется (в зависимости от деловых решений), чем изменять работающее приложение!
  • Если возможно, необходимо классифицировать отчеты как "реальные" или "статистические", где данные, необходимые для статистических отчетов, генерируются только на основе сводных таблиц, которые формируются из реальных данных.
  • Воспользуйтесь преимуществом того факта, что столбцы имеют значения по умолчанию. Вносите величины явно только тогда, когда значения вносимых величин отличаются от установленных по умолчанию. Это уменьшает объем анализа, который необходимо произвести в MySQL, и улучшает скорость внесения.
  • В некоторых случаях удобно упаковывать и хранить данные в столбцах BLOB. В этом случае необходимо добавить дополнительный код для запаковывания в BLOB и распаковывания обратно, но на некотором этапе это может сэкономить много обращений. Это практично, когда ваши данные не согласуются со структурой статической таблицы.
  • Обычно следует стремиться сохранять все данные в безизбыточной форме (которая называется 3-й нормальной формой в теории баз данных), но не следует опасаться дублирования данных или создания сводных таблиц, если это необходимо для достижения большей скорости.
  • Хранимые процедуры или UDF (функции, определяемые пользователем) могут быть хорошим способом получить большую производительность. В этом случае, однако, следует иметь в запасе некоторый иной (более медленный) путь, если используемая вами база данных не поддерживает этих возможностей.
  • Вы всегда можете кое-чего достичь путем кэширования запросов/ответов в своем приложении и стараясь выполнить много вставок/обновлений в одно и то же время. Если ваша база данных поддерживает блокировку таблиц (как MySQL и Oracle), то это должно помочь гарантировать, что кэш индексов сбрасывается только однажды после всех обновлений.
  • Используйте INSERT /*! DELAYED */, если нет необходимости знать, когда ваши данные записываются. Это повысит скорость работы, поскольку многие табличные записи могут быть внесены с помощью одной дисковой записи.
  • Используйте INSERT /*! LOW_PRIORITY */, если хотите сделать ваши выборки более важными.
  • Используйте SELECT /*! HIGH_PRIORITY */, чтобы получить выборки, которые перепрыгивают очередь. То есть, выборка выполняется, даже если кто-либо ожидает, чтобы сделать запись.
  • Используйте многострочную команду INSERT для хранения многих строк в одной SQL-команде (многие SQL-серверы поддерживают это).
  • Используйте LOAD DATA INFILE для загрузки больших количеств данных. Это быстрее, чем обычные вставки и будет еще быстрее при интеграции myisamchk в mysqld.
  • Используйте столбцы AUTO_INCREMENT, чтобы сделать величины уникальными.
  • Используйте время от времени OPTIMIZE TABLE, чтобы избежать фрагментации при использовании динамического табличного формата. See section 4.5.1 Синтаксис команды OPTIMIZE TABLE.
  • Используйте таблицы HEAP, чтобы получить более высокую скорость, когда это возможно. See section 7 Типы таблиц MySQL.
  • При использовании нормальной установки веб-сервера рисунки должны храниться как файлы. То есть, храните в базе данных только ссылку на файл. Главная причина этого состоит в том, что обычный веб-сервер намного лучше кэширует файлы, чем содержание базы данных. Таким образом, при использовании файлов намного легче получить быструю систему.
  • Используйте в памяти таблицы для неответственных данных, к которым часто обращаются (таким, как информация о последнем показанном баннере для пользователей, не имеющих cookies).
  • Столбцы с идентичной информацией в различных таблицах должны объявляться одинаково и иметь одинаковые имена. До версии 3.23 в противном случае получались медленные соединения (slow joins). Старайтесь сохранять имена простыми (используйте name вместо customer_name в таблице customer). Чтобы ваши имена были переносимыми на другие SQL-серверы, они должны быть короче, чем 18 символов.
  • Если вам действительно нужна высокая скорость, вы должны взглянуть на интерфейсы нижнего уровня для хранения данных, поддерживаемые различными SQL-серверами! Например, обращаясь к таблицам MyISAM в MySQL напрямую, можно было бы получить увеличение скорости в 2-5 раз по сравнению с использованием интерфейса SQL. Для возможности сделать это, данные должны находиться на том же самом сервере, что и приложение, и, обычно, должны иметь доступ только в одном процессе обработки (поскольку внешняя файловая блокировка действительно медленна). Можно было бы избавиться от вышеуказанных проблем введением низко-уровневых команд MyISAM в сервере MySQL (это был бы один из простых путей получить большую производительность, если необходимо). Путем тщательного проектирования интерфейса базы данных было бы достаточно просто поддерживать этот тип оптимизации.
  • Во многих случаях быстрее получить доступ к данным из базы данных (используя действующее соединение), чем обращаться к текстовому файлу, просто из-за того, что база данных, вероятно, более компактна, чем текстовый файл (если вы используете числовые данные), и это приведет к меньшему количеству обращений к диску. Вы также сэкономите на коде, поскольку не должны анализировать текстовые файлы, чтобы найти границы строк и столбцов.
  • Для увеличения скорости можно также использовать репликацию. See section 4.10 Репликация в MySQL.
  • Объявление таблицы с DELAY_KEY_WRITE=1 сделает обновление индексов более быстрым, так как они не записываются на диск, пока файл закрыт. Обратная сторона этого заключается в том, что необходимо запускать myisamchk на этих таблицах перед началом работы mysqld, для уверенности, что все в порядке, если что-либо уничтожит mysqld в середине работы. Поскольку ключевая информация всегда может быть воспроизведена из данных, то вы не должны что-либо потерять при использовании DELAY_KEY_WRITE.

5.3 Вопросы блокировок

5.3.1 Как MySQL блокирует таблицы

Описание различных методов блокировки дается в приложении, в разделе section D.4 Методы блокировки.

В MySQL все блокировки, кроме блокировок таблиц типов InnoDB и BDB, не создают тупиковых ситуаций. Это обеспечивается за счет того, что все необходимые блокировки всегда запрашиваются единожды в начале запроса и блокировка таблиц всегда происходит в одном и том же порядке.

В таблицах типа InnoDB устанавливается блокировка строк, а в таблицах типа BDB - блокировка страниц в процессе выполнения SQL-команд, а не в начале транзакции.

Метод блокирования, используемый в MySQL для блокировок записи (WRITE), работает следующим образом:

  • Если на данной таблице нет никаких блокировок, то на нее накладывается блокировка записи.
  • В противном случае запрос на данную блокировку ставится в очередь блокировок записи.

Метод блокирования, используемый в MySQL для блокировок чтения (READ), работает следующим образом:

  • Если на данной таблице нет блокировок записи, то на нее накладывается блокировка чтения.
  • В противном случае запрос на данную блокировку ставится в очередь блокировок чтения.

При освобождении текущей блокировки становится возможной следующая блокировка для потоков из очереди блокировок записи, затем для потоков из очереди блокировок чтения.

Это означает, что, если таблица подвергается многочисленным обновлениям, то команды SELECT будут ожидать, пока обновления не закончатся.

Чтобы обойти это в случае, когда для таблицы требуется выполнить много операций INSERT и SELECT, можно внести строки во временную таблицу и время от времени обновлять реальную таблицу записями из временной.

Для этого можно применить следующий код:

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;

В некоторых случаях, когда необходимо установить приоритеты извлечения данных, для команд INSERT, UPDATE или DELETE можно указывать опцию LOW_PRIORITY, а для команды SELECT - HIGH_PRIORITY. Тот же результат можно получить, запустив mysqld с --low-priority-updates.

Использование SQL_BUFFER_RESULT тоже способствует уменьшению времени блокировок таблиц. See section 6.4.1 Синтаксис оператора SELECT.

Можно также изменить блокировочный код в `mysys/thr_lock.c' - чтобы использовать только одну очередь блокировок. В этом случае блокировки записи и чтения будут иметь одинаковый приоритет, что может оказаться полезным для некоторых приложений.

5.3.2 Вопросы блокирования таблиц

Код блокирования таблиц в MySQL не создает тупиковых ситуаций.

Чтобы получить высокую скорость блокирования, в MySQL на таблицах всех типов, кроме InnoDB и BDB,используется табличная блокировка (вместо блокирования строк или столбцов). Если таблицы большие, то для большинства приложений табличная блокировка намного лучше, чем строковая, но существуют, конечно, и определенные подводные камни.

Для таблиц типов InnoDB и BDB в MySQL табличная блокировка используется только в случае, если данная таблица явно блокируется командой LOCK TABLES. Мы вообще не рекомендуем применять LOCK TABLES для упомянутых типов таблиц, поскольку для таблицы InnoDB используется автоматическая блокировка строкового уровня, а для таблиц BDB - блокировка страничного уровня. Это делается, чтобы гарантировать изоляцию транзакций.

В версии MySQL 3.23.7 и выше можно вставлять строки в таблицы MyISAM в то время, когда другие потоки производят чтение из этой таблицы. Следует учитывать, что в настоящее время эта функция работает только при условии, что в таблице в момент вставки отсутствуют какие-либо пустые пространства, оставшиеся после удаленных из нее записей. Как только все пустые места будут заполнены новыми данными, автоматически будет восстановлена возможность делать одновременные вставки.

Табличная блокировка обеспечивает возможность одновременного выполнения чтения из таблицы несколькими потоками, но если какой-нибудь поток попробует произвести запись в таблицу, то вначале он должен получить исключительный доступ. Во время обновления таблицы все другие потоки, стремящиеся получить доступ к этой конкретной таблице, будут ожидать, пока данное обновление не будет завершено.

Поскольку обновление обычно считается более важной операцией, чем SELECT, то все команды, производящие обновления таблицы, имеют более высокий приоритет, чем команды извлечения данных. Такой алгоритм гарантирует, что обновления не зависнут в случае, если для некоторой таблицы выполняется большое количество тяжелых запросов (этот порядок действий можно изменить, используя LOW_PRIORITY с командой обновления или HIGH_PRIORITY с командой SELECT).

Начиная с версии MySQL 3.23.7 можно использовать переменную max_write_lock_count, чтобы заставить MySQL временно предоставить всем командам SELECT, ожидающим доступ к таблице, более высокий приоритет после заданного числа вставок в таблицу.

Табличную блокировку, однако, нецелесообразно использовать в случае следующего сценария:

  • Клиент запускает SELECT, требующий длительного времени для выполнения.
  • Затем другой клиент запускает команду UPDATE на используемой таблице. Этот клиент будет ожидать, пока SELECT не закончит свою работу.
  • Другой клиент запускает еще одну команду SELECT на той же таблице. Поскольку UPDATE имеет более высокий приоритет, чем SELECT, то эта команда SELECT будет ждать, пока UPDATE не закончит свою работу. Кроме того, вторая команда SELECT будет также ждать, пока не завершится первая команда SELECT!
  • Поток ждет ситуации заполненного диска. В таком случае все потоки, которые хотят получить доступ к проблемной таблице, будут переведены в состояние ожидания до тех пор, пока не освободится немного дискового пространства.

Ниже представлены некоторые возможные решения данной проблемы:

  • Постарайтесь заставить команды SELECT выполняться быстрее. Возможно, для этого необходимо будет создать сводные таблицы.
  • Запустите mysqld с --low-priority-updates. Этим вы назначите всем командам обновления таблицы более низкий приоритет, чем у команды SELECT. Тогда последняя команда SELECT в предыдущем сценарии будет выполняться перед командой INSERT.
  • Конкретным командам INSERT, UPDATE или DELETE можно назначить более низкий приоритет с помощью атрибута LOW_PRIORITY.
  • Запустите mysqld с небольшим значением max_write_lock_count, чтобы разрешить блокировки чтения (READ) после определенного количества блокировок записи (WRITE).
  • SQL-командой: SET LOW_PRIORITY_UPDATES=1 можно указать, что все обновления из конкретного потока должны выполняться с низким приоритетом. See section 5.5.6 Синтаксис команды SET.
  • Можно указать, что команда SELECT является очень важной, - с помощью атрибута HIGH_PRIORITY. See section 6.4.1 Синтаксис оператора SELECT.
  • Если имеются проблемы при выполнении команд INSERT совместно с SELECT, перейдите на новые таблицы MyISAM, которые поддерживают одновременное выполнение команд SELECT и INSERT.
  • Если совместно выполняются преимущественно команды INSERT и SELECT, то решить возникающие при этом проблемы иногда помогает атрибут DELAYED для INSERT. See section 6.4.3 Синтаксис оператора INSERT.
  • Если имеются проблемы с командами SELECT и DELETE, то может помочь опция LIMIT для DELETE. See section 6.4.6 Синтаксис оператора DELETE.

5.4 Оптимизация структуры базы данных

5.4.1 Конструктивные особенности MySQL

В MySQL данные и индексы хранятся отдельно, в разных файлах, в то время как во многих (практически во всех) базах данных данные и индексы помещаются вместе в одном и том же файле. Мы полагаем, что конструкция MySQL лучше подходит для очень широкого диапазона современных систем.

Существует еще один способ хранения исходных данных - когда данные для каждого столбца содержатся в отдельной области (примерами являются SDBM и Focus). При такой организации данных неизбежно снижение производительности для каждого запроса, затрагивающего более, чем один столбец. Поскольку при доступе к более чем одному столбцу ситуация очень быстро начинает ухудшаться, то мы полагаем, что эта модель не вполне годится для баз данных общего назначения.

Модель, когда индексы и данные хранятся вместе (как в Oracle/Sybase и других), встречается чаще. В этом случае запись будет находиться в странице соответствующего индекса. Преимущества такой схемы во многих случаях заключаются в том, что считывание с диска получается более экономным - в зависимости от того, насколько хорошо кэшируется индекс. Недостатки же здесь следующие:

  • Сканирование таблиц выполняется намного медленнее, поскольку необходимо прочитать индексы, чтобы добраться до данных.
  • Нельзя использовать только таблицу индексов для извлечения данных по запросу.
  • Теряется много дискового пространства, поскольку необходимо дублировать индексы из узлов (так как нельзя хранить строку в узлах)
  • Удаления со временем приводят к вырождению таблицы (так как индексы в узлах обычно не обновляются при операции удаления).
  • Более сложно выполняется кэширование только данных об индексах.

5.4.2 Сделайте объем данных как можно меньше

Одна из основных задач оптимизации заключается в том, чтобы данные (и индексы) занимали как можно меньше места на диске (и в памяти). Это дает значительные преимущества в работе, поскольку ускоряется чтение диска, а оперативная память, как правило, используется меньше. Индексирование также требует меньших ресурсов, если оно выполняется на меньших столбцах.

MySQL поддерживает большое количество различных типов таблиц и форматов строк. Значительный выигрыш в производительности можно получить за счет правильного выбора формата таблицы (see section 7 Типы таблиц MySQL).

Чтобы увеличить производительность работы с таблицей и минимизировать требуемое пространство памяти, можно применять перечисленные ниже технические приемы:

  • Используйте по возможности наиболее эффективные (наименьшие по объему) типы данных. В MySQL имеется много специализированных типов данных, применение которых позволяет экономить пространство на диске и в памяти.
  • Используйте, если это возможно, целочисленные типы меньшей длины, чтобы получить таблицы меньшего размера. Например, MEDIUMINT часто лучше, чем INT.
  • Объявляйте везде, где возможно, столбцы как NOT NULL. Это позволяет ускорить все операции и сэкономить по одному биту для каждого столбца. Однако если для данного приложения действительно нужен NULL, то вы все-таки его (NULL) используйте. Нужно просто избегать наличия NULL во всех столбцах по умолчанию.
  • Если отсутствуют какие-либо столбцы переменной длины (столбцы типов VARCHAR, TEXT или BLOB), то нужно применять формат записи фиксированного размера. Такой метод дает увеличение скорости, но при этом, к сожалению, может потребоваться лишнее место на диске. See section 7.1.2 Форматы таблиц MyISAM.
  • Первичные индексы в таблице должны быть как можно короче. Это делает идентификацию конкретной записи простой и эффективной.
  • Метод хранения/индексации нужно выбрать для каждой таблицы. See section 7 Типы таблиц MySQL.
  • Создавайте только те индексы, которые действительно необходимы. Индексы хороши для извлечения данных, но плохи при необходимости быстрого сохранения информации. Если работа с таблицей большей частью сводится к поиску на некотором сочетании столбцов, то следует сделать по ним индекс. Первая часть этого индекса должна представлять собой наиболее используемый столбец. Если всегда задействовано много столбцов, то следует первым использовать столбец с большим количеством повторений, чтобы получить лучшее сжатие этого индекса.
  • Если в столбце с большой степенью вероятности в начальной части символов присутствует уникальный префикс, то лучше индексировать только этот префикс. MySQL поддерживает индекс по части символов столбца. Более короткие индексы работают быстрее не только за счет того, что они занимают меньше дискового пространства, но также и потому, что они обеспечивают больше попаданий в кэш индексов, благодаря чему уменьшается количество операций поиска на диске. See section 5.5.2 Настройка параметров сервера.
  • Иногда целесообразно разбить очень часто просматриваемую таблицу на две, особенно если таблица имеет динамический формат и при просмотре данной таблицы для поиска соответствующих строк можно использовать таблицу с меньшим статическим форматом.

5.4.3 Использование индексов в MySQL

Индексы применяются для быстрого поиска строк с указанным значением одного столбца. Без индекса чтение таблицы осуществляется по всей таблице начиная с первой записи, пока не будут найдены соответствующие строки. Чем больше таблица, тем больше накладные расходы. Если же таблица содержит индекс по рассматриваемым столбцам, то MySQL может быстро определить позицию для поиска в середине файла данных без просмотра всех данных. Для таблицы, содержащей 1000 строк, это будет как минимум в 100 раз быстрее по сравнению с последовательным перебором всех записей. Однако в случае, когда необходим доступ почти ко всем 1000 строкам, быстрее будет последовательное чтение, так как при этом не требуется операций поиска по диску.

Все индексы MySQL (PRIMARY, UNIQUE, и INDEX) хранятся в виде B-деревьев. Строки автоматически сжимаются с удалением пробелов в префиксах и оконечных пробелов (see section 6.5.7 Синтаксис оператора CREATE INDEX).

Индексы используются для того, чтобы:

  • Быстро найти строки, соответствующие выражению WHERE.
  • Извлечь строки из других таблиц при выполнении объединений.
  • Найти величины MAX() или MIN() для заданного индексированного столбца. Эта операция оптимизируется препроцессором, который проверяет, не используете ли вы WHERE key_part_4 = константа, по всем частям составного ключа < N. В этом случае MySQL сделает один просмотр ключа и заменит выражение константой MIN(). Если все выражения заменяются константой, запрос моментально вернет результат:
    SELECT MIN(key_part2),MAX(key_part2) FROM table_name where key_part1=10
  • Производить сортировку или группирование в таблице, если эти операции делаются на крайнем слева префиксе используемого ключа (например ORDER BY key_part_1,key_part_2). Если за всеми частями ключа следует DESC, то данный ключ читается в обратном порядке (see section 5.2.7 Как MySQL оптимизирует ORDER BY).
  • В некоторых случаях запрос можно оптимизировать для извлечения величин без обращения к файлу данных. Если все используемые столбцы в некоторой таблице являются числовыми и образуют крайний слева префикс для некоторого ключа, то чтобы обеспечить большую скорость, искомые величины могут быть извлечены непосредственно из индексного дерева:
    SELECT key_part3 FROM table_name WHERE key_part1=1

Предположим, что вызывается следующий оператор SELECT:

mysql> SELECT * FROM tbl_name WHERE col1=val1 AND col2=val2;

Если по столбцам col1 и col2 существует многостолбцовый индекс, то соответствующие строки могут выбираться напрямую. В случае, когда по столбцам col1 и col2 существуют раздельные индексы, оптимизатор пытается найти наиболее ограничивающий индекс путем определения, какой индекс найдет меньше строк, и использует данный индекс для выборки этих строк.

Если данная таблица имеет многостолбцовый индекс, то любой крайний слева префикс этого индекса может использоваться оптимизатором для нахождения строк. Например, если имеется индекс по трем столбцам (col1,col2,col3), то существует потенциальная возможность индексированного поиска по (col1), (col1,col2) и (col1,col2,col3).

В MySQL нельзя использовать частичный индекс, если столбцы не образуют крайний слева префикс этого индекса. Предположим, что имеются команды SELECT, показанные ниже:

mysql> SELECT * FROM tbl_name WHERE col1=val1;
mysql> SELECT * FROM tbl_name WHERE col2=val2;
mysql> SELECT * FROM tbl_name WHERE col2=val2 AND col3=val3;

Если индекс существует по (col1,col2,col3), то только первый показанный выше запрос использует данный индекс. Второй и третий запросы действительно включают индексированные столбцы, но (col2) и (col2,col3) не являются крайней слева частью префиксов (col1,col2,col3).

MySQL применяет индексы также для сравнений LIKE, если аргумент в выражении LIKE представляет собой постоянную строку, не начинающуюся с символа-шаблона. Например, следующие команды SELECT используют индексы:

mysql> SELECT * FROM tbl_name WHERE key_col LIKE "Patrick%";
mysql> SELECT * FROM tbl_name WHERE key_col LIKE "Pat%_ck%";

В первой команде рассматриваются только строки с "Patrick" <= key_col < "Patricl", а во второй - только строки с "Pat" <= key_col < "Pau".

Следующие команды SELECT не будут использовать индексы:

mysql> SELECT * FROM tbl_name WHERE key_col LIKE "%Patrick%";
mysql> SELECT * FROM tbl_name WHERE key_col LIKE other_col;

В первой команде величина LIKE начинается с шаблонного символа. Во второй команде величина LIKE не является константой.

В версии MySQL 4.0 производится другая оптимизация на выражении LIKE. Если используется выражение ... LIKE "%string%" и длина строки (string) больше, чем 3 символа, то MySQL будет применять алгоритм Турбо Бойера-Мура для инициализации шаблона для строки и затем использовать этот шаблон, чтобы выполнить поиск быстрее.

При поиске с использованием column_name IS NULL будут использоваться индексы, если column_name является индексом.

MySQL обычно использует тот индекс, который находит наименьшее количество строк. Индекс применяется для столбцов, которые сравниваются с помощью следующих операторов: =, >, >=, <, <=, BETWEEN и LIKE с префиксом, не содержащим шаблонного символа, такого как something%.

Если индекс не охватывает все уровни AND в выражении WHERE, то он не применяется для оптимизации данного запроса. Другими словами: чтобы индекс можно было использовать, префикс этого индекса должен входить в каждую группу AND.

Следующие выражения WHERE используют индексы:

... WHERE index_part1=1 AND index_part2=2 AND other_column=3
... WHERE index=1 OR A=10 AND index=2 /* индекс = 1 ИЛИ индекс = 2 */
... WHERE index_part1='hello' AND index_part_3=5

/* оптимизировано как "index_part1='hello'" */

... WHERE index1=1 and index2=2 or index1=3 and index3=3;

/* Можно использовать индекс по index1, но не по index2 или index 3 */

Следующие выражения WHERE не используют индексы:

... WHERE index_part2=1 AND index_part3=2
/* index_part_1 не используется */

... WHERE index=1 OR A=10
/* Индекс не используется в обеих частях AND */

... WHERE index_part1=1 OR index_part2=10
/* Нет индекса, покрывающего все строки*/

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

  • Если использование индекса требует от MySQL прохода более чем по 30% строк в данной таблице (в таких случаях просмотр таблицы, по всей видимости, окажется намного быстрее, так как потребуется выполнить меньше операций поиска). Следует учитывать, что если подобный запрос использует LIMIT по отношению только к извлекаемой части строк, то MySQL будет применять индекс в любом случае, так как небольшое количество строк можно найти намного быстрее, чтобы вернуть результат.

5.4.4 Индексы столбцов

В MySQL могут быть проиндексированы столбцы всех типов. Использование индексов на соответствующих столбцах представляет собой хороший способ ускорения выполнения операций SELECT.

Максимальное количество ключей и максимальная длина индексов определяется обработчиком таблиц (see section 7 Типы таблиц MySQL). Можно иметь по меньшей мере 16 ключей на всех обработчиках таблиц и общую длину индексов по меньшей мере 256 байтов.

Для столбцов типов CHAR и VARCHAR можно индексировать префикс столбца. Это намного быстрее и требует меньше дискового пространства, чем индексация всего столбца. Используемый в команде CREATE TABLE синтаксис для индексации префикса столбца выглядит примерно так:

KEY index_name (col_name(length))

В следующем примере создается индекс для первых 10 символов в столбце name:

mysql> CREATE TABLE test (
    ->        name CHAR(200) NOT NULL,
    ->        KEY index_name (name(10)));

Для столбцов типа BLOB и TEXT индексировать необходимо префикс столбца. Нельзя индексировать столбец целиком.

В версии MySQL 3.23.23 и более поздних можно также создавать специальные индексы FULLTEXT. Они используются для полнотекстового поиска. Полнотекстовые индексы FULLTEXT поддерживают только таблицы типа MyISAM. Они могут создаваться только по столбцам VARCHAR и TEXT. Индексация всегда производится для целого столбца, а частичная индексация не поддерживается. See section 6.8 Полнотекстовый поиск в MySQL.

5.4.5 Многостолбцовые индексы

MySQL может создавать индексы по нескольким столбцам. Индекс может включать в себя до 15 столбцов (на столбцах CHAR и VARCHAR можно также использовать префикс столбца в качестве части индекса)

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

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

Предположим, создается следующая таблица:

mysql> CREATE TABLE test (
    ->       id INT NOT NULL,
    ->       last_name CHAR(30) NOT NULL,
    ->       first_name CHAR(30) NOT NULL,
    ->       PRIMARY KEY (id),
    ->       INDEX name (last_name,first_name));

Индекс name является индексом по столбцам last_name и first_name. Этот индекс будет применяться для запросов, указывающих величины в известной области для last_name или для обоих столбцов last_name и first_name. Таким образом, индекс name будет использоваться в следующих запросах:

mysql> SELECT * FROM test WHERE last_name="Widenius";

mysql> SELECT * FROM test WHERE last_name="Widenius"
    ->                    AND first_name="Michael";

mysql> SELECT * FROM test WHERE last_name="Widenius"
    ->                    AND (first_name="Michael" OR first_name="Monty");

mysql> SELECT * FROM test WHERE last_name="Widenius"
    ->                    AND first_name >="M" AND first_name < "N";

Чтобы получить более подробную информацию о том, как в MySQL используются индексы для улучшения работы запросов, See section 5.4.3 Использование индексов в MySQL.

5.4.6 Почему так много открытых таблиц?

При запуске mysqladmin status можно увидеть что-нибудь вроде этого:

Uptime: 426 Running threads: 1 Questions: 11082 Reloads: 1 Open tables: 12

В чем же дело, ведь у вас всего 6 таблиц?

MySQL является многопоточной базой данных, поэтому для одной и той же таблицы могут одновременно присутствовать несколько запросов. Чтобы минимизировать эту проблему для двух потоков, имеющих различный статус на одном и том же файле, таблица открывается независимо каждым конкурирующим потоком. Это требует дополнительной памяти, но, как правило, повышает производительность. Кроме того, для таблиц типа ISAM и MyISAM требуется дополнительный дескриптор для файла данных. В таблицах этого типа дескриптор индексного файла используется совместно всеми потоками.

В следующем разделе вы найдете более подробную информацию по этой теме (see section 5.4.7 Открытие и закрытие таблиц в MySQL).

5.4.7 Открытие и закрытие таблиц в MySQL

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

Значения table_cache и max_connections взаимосвязаны. Например, для 200 одновременно работающих соединений необходимо иметь кэш для таблиц размером по меньшей мере 200 * n, где n - максимальное количество связанных таблиц. Необходимо также зарезервировать несколько дополнительных файловых дескрипторов для временных таблиц и файлов.

Следует удостовериться, что ваша операционная система способна обрабатывать такое количество открытых файловых дескрипторов, какое предполагает данная установка table_cache. Если устанавливается слишком высокое значение table_cache, то MySQL может выйти за пределы допустимого количества файловых дескрипторов, прервать соединение, не выполнять запросы и стать очень ненадежным. Необходимо также принять во внимание, что для обработчика таблиц MyISAM требуется по два файловых дескриптора для каждой уникальной открытой таблицы. Допустимое для MySQL количество файловых дескрипторов можно увеличить с помощью опции запуска --open-files-limit=# (see section A.2.16 Не найден файл (File not found)).

Максимальное количество таблиц в кэше открытых таблиц будет равно количеству, указанному в table_cache (по умолчанию - 64; это число можно изменить с помощью опции -O table_cache=# для mysqld). Следует учитывать, что для выполнения запросов MySQL может временно открыть и больше таблиц.

Неиспользуемая таблица закрывается и удаляется из кэша таблиц в следующих ситуациях:

  • Когда кэш заполнен и поток старается открыть таблицу, отсутствующую в этом кэше.
  • Когда кэш содержит более, чем table_cache входных величин, и поток больше не использует таблицу.
  • Когда кто-либо выполняет mysqladmin refresh или mysqladmin flush-tables.
  • Когда кто-либо выполняет FLUSH TABLES.

Когда табличный кэш заполняется, сервер использует следующую процедуру размещения входных данных кэша для их использования:

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

Таблица открывается для каждого одновременного доступа. Это означает, что, если существуют два потока, получающие доступ к одной и той же таблице, или происходит обращение к этой таблице дважды в одном и том же запросе (с помощью AS), то данная таблица должна быть открыта дважды. Для первого открытия любой таблицы требуется два файловых дескриптора; для каждого дополнительного использования - только один. Дополнительный дескриптор для первого открытия используется для индексного файла; этот дескриптор используется совместно всеми потоками.

При открытии таблицы командой HANDLER table_name OPEN создается выделенный табличный объект для данного потока. Этот табличный объект недоступен для других потоков и не будет закрыт, пока данный поток не вызовет команду HANDLER table_name CLOSE или сам поток не уничтожится (see section 6.4.2 Синтаксис оператора HANDLER). Если это произойдет, то данная таблица помещается обратно в кэш таблиц (если он не заполнен).

Чтобы узнать, не слишком ли мал кэш таблиц, следует проверить переменную Opened_tables. Если ее значение достаточно велико, даже если вы не выполняли слишком часто команду FLUSH TABLES, то необходимо увеличить данный кэш таблиц (see section 4.5.6.3 SHOW STATUS).

5.4.8 Недостатки создания множества таблиц в одной базе данных

Если в каталоге присутствует большое количество файлов, то операции открытия, закрытия и создания будут медленными. Выполнение значительного количества команд SELECT на большом количестве разных таблиц приводит к небольшим непроизводительным затратам при заполненном табличном кэше, поскольку для открытия одной таблицы требуется закрыть другую. Чтобы сократить эту перегрузку, следует увеличить табличный кэш.

5.5 Оптимизация сервера MySQL

5.5.1 Настройка параметров системы, компляции и запуска

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

Используемая по умолчанию операционная система имеет действительно большое значение! Чтобы получить максимальную выгоду от применения многопроцессорных компьютеров, следует применять Solaris (так как под этой ОС потоки работают в самом деле хорошо) или Linux (поскольку ядро 2.2 обеспечивает действительно хорошую поддержку SMP). Однако на 32-разрядных компьютерах Linux по умолчанию имеет ограничение размера файлов в 2 Гб. Будем надеяться, что это ограничение в скором времени будет снято при выпуске новых файловых систем (XFS/Reiserfs). Но если вам действительно не обойтись без файлов с размерами более чем 2 Гб на 32-разрядном ПК с Linux-intel, то следует использовать патч LFS для файловой системы ext2.

На многих платформах MySQL еще не находился в промышленной эксплуатации, поэтому мы рекомендуем прежде, чем остановить свой выбор на какой-либо платформе, сначала ее протестировать.

Другие советы:

  • Если оперативной памяти достаточно, то можно было бы удалить все внешние запоминающие устройства. Существуют операционные системы, которые при некоторых обстоятельствах будут использовать внешние запоминающие устройства даже при наличии свободной памяти.
  • Чтобы избежать внешнего блокирования, используйте опцию MySQL --skip-external-locking. Следует учитывать, что пока работает только один сервер, это не будет оказывать большого влияния на функциональные возможности MySQL. Только не забудьте остановить сервер (или блокировать соответствующие части) перед запуском myisamchk. В некоторых системах такое переключение обязательно, поскольку внешнее блокирование не работает в любом случае. Опция --skip-external-locking включена по умолчанию при компилировании с потоками MIT-pthreads, поскольку функция flock() не полностью поддерживается потоками MIT-pthreads на всех платформах. Для Linux также подразумевается, что блокирование файлов пока еще ненадежно. Нельзя использовать --skip-external-locking только в одном случае - при запуске нескольких серверов (не клиентов) MySQL на одних и тех же данных, или при запуске myisamchk на таблице без предварительного сбрасывания на диск и блокирования демона mysqld для сервера, содержащего эти таблицы. Можно также применять команду LOCK TABLES/UNLOCK TABLES даже при использовании --skip-external-locking.

5.5.2 Настройка параметров сервера

Размеры буферов, используемые по умолчанию сервером mysqld, можно узнать с помощью следующей команды:

shell> mysqld --help

Эта команда выдает список всех опций mysqld и конфигурируемых переменных. Вывод включает в себя величины по умолчанию и выглядит примерно следующим образом:

Possible variables for option --set-variable (-O) are:
back_log                 current value: 5
bdb_cache_size           current value: 1048540
binlog_cache_size        current value: 32768
connect_timeout          current value: 5
delayed_insert_timeout   current value: 300
delayed_insert_limit     current value: 100
delayed_queue_size       current value: 1000
flush_time               current value: 0
interactive_timeout      current value: 28800
join_buffer_size         current value: 131072
key_buffer_size          current value: 1048540
lower_case_table_names   current value: 0
long_query_time          current value: 10
max_allowed_packet       current value: 1048576
max_binlog_cache_size    current value: 4294967295
max_connections          current value: 100
max_connect_errors       current value: 10
max_delayed_threads      current value: 20
max_heap_table_size      current value: 16777216
max_join_size            current value: 4294967295
max_sort_length          current value: 1024
max_tmp_tables           current value: 32
max_write_lock_count     current value: 4294967295
myisam_sort_buffer_size  current value: 8388608
net_buffer_length        current value: 16384
net_retry_count          current value: 10
net_read_timeout         current value: 30
net_write_timeout        current value: 60
read_buffer_size         current value: 131072
record_rnd_buffer_size   current value: 131072
slow_launch_time         current value: 2
sort_buffer              current value: 2097116
table_cache              current value: 64
thread_concurrency       current value: 10
tmp_table_size           current value: 1048576
thread_stack             current value: 131072
wait_timeout             current value: 28800

Не забывайте, что --set-variable не используется в MySQL 4.0. Просто указывайте --var=option.

Если сервер mysqld в настоящее время работает, то для того, чтобы увидеть, какие величины реально используются для переменных, необходимо выполнить следующую команду:

shell> mysqladmin variables

Полное описание всех переменных можно найти в разделе SHOW VARIABLES этого руководства (see section 4.5.6.4 SHOW VARIABLES).

Некоторые статистические данные по работающему серверу можно также просмотреть с помощью команды SHOW STATUS (see section 4.5.6.3 SHOW STATUS).

В MySQL используются алгоритмы, масштабируемые в широких пределах, так что обычно можно работать с очень небольшой памятью. Однако если выделить для MySQL больше памяти, то и производительность, как правило, будет выше.

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

Если имеется большая память (>=256 Mб) и много таблиц, то для обеспечения максимальной производительности путем регулирования количества клиентов следует использовать что-нибудь вроде этого:

shell> safe_mysqld -O key_buffer=64M -O table_cache=256 \
                   -O sort_buffer=4M -O read_buffer_size=1M &

Если память составляет только 128 Mб и количество таблиц невелико, но тем не менее, выполняется много сортировок, то можно использовать что-нибудь вроде:

shell> safe_mysqld -O key_buffer=16M -O sort_buffer=1M

При малой памяти и большом количестве соединений следует использовать что-нибудь вроде следующего:

shell> safe_mysqld -O key_buffer=512k -O sort_buffer=100k \
                   -O read_buffer_size=100k &

или даже:

shell> safe_mysqld -O key_buffer=512k -O sort_buffer=16k \
                   -O table_cache=32 -O read_buffer_size=8k \
                   -O net_buffer_length=1K &

Если выполняются операции GROUP BY или ORDER BY на файлах, которые намного больше, чем доступная память, то следует увеличить величину record_rnd_buffer для ускорения чтения строк после выполнения сортировки.

После установки MySQL каталог `support-files' будет содержать несколько различных файлов-примеров `my.cnf', а именно: `my-huge.cnf', `my-large.cnf', `my-medium.cnf' и `my-small.cnf', которые можно использовать как основу для оптимизации вашей системы.

Если демон mysqld не отконфигурирован для использования очень малой памяти для каждого соединения, то в условиях очень большого количества соединений могут возникнуть проблемы с подкачкой виртуальной памяти. При наличии достаточной памяти для всех соединений mysqld, конечно, будет функционировать лучше.

Следует учитывать, что при изменении какой-либо опции для mysqld это изменение действительно только для данного экземпляра сервера.

Чтобы увидеть воздействие изменения параметра, нужно выполнить что-нибудь вроде этого:

shell> mysqld -O key_buffer=32m --help

Следует удостовериться, что опция --help расположена последней; в противном случае влияние любой опции, следующей после нее в командной строке, в данном выводе отражено не будет.

5.5.3 Как компиляция и линкование влияет на скорость MySQL

Большинство из последующих тестов выполняются под Linux с использованием тестов производительности MySQL, но они должны дать некоторое представление и для других операционных систем и рабочих нагрузок.

Самый быстрый исполняемый код получается при линковании с помощью -static.

Под Linux наиболее быстрый код можно получить при компилировании pgcc с опицей -O3. Чтобы скомпилировать sql_yacc.cc с этой опцией, требуется около 200 Mб памяти, поскольку компилятор gcc/pgcc забирает много памяти. При конфигурировании MySQL следует также установить CXX=gcc - чтобы не линковалась библиотека libstdc++ (в этом нет необходимости). Следует учитывать, что при некоторых версиях компилятора pgcc результирующий код будет работать только на настоящих процессорах Pentium, даже если использовать возможность компилятора выдавать результирующий код, работоспособный на всех процессорах типа x586 (например AMD).

Используя просто лучший компилятор и/или лучшую опцию компилятора, можно получить для приложения увеличение скорости на 10-30%. Это особенно важно, если вы компилируете сервер SQL самостоятельно!

Мы протестировали такие компиляторы как Cygnus CodeFusion и Fujitsu, но ни тот, ни другой не были достаточно свободны от ошибок, чтобы можно было скомпилировать MySQL с оптимизирующими параметрами.

При компилировании MySQL необходимо включать только наборы кодировок, которые вы собираетесь использовать (опция --with-charset=xxx). Стандартная поставка MySQL скомпилирована с поддержкой всех кодировок.

Ниже приводится обзор некоторых действий, которые мы предпринимали для ускорения работы:

  • При использовании pgcc и компиляции всего кода с -O6 сервер mysqld на 1% быстрее, чем при gcc 2.95.2.
  • При динамическом связывании (без опции -static) результирующий исполняемый файл сервера будет на 13% медленнее работать под управлением Linux. Обратите внимание: вы спокойно можете использовать динамическую библиотеку MySQL. Это касается только сервера и актуально только там, где нужна высокая производительность.
  • При сокращении двоичного кода mysqld с помощью strip libexec/mysqld можно получить прирост скорости результирующего двоичного кода до 4%.
  • При соединении с использованием протокола TCP/IP, а не сокетов Unix работа будет на 7,5% медленнее на том же самом компьютере (при подключении к localhost MySQL по умолчанию будет использовать сокеты).
  • При соединении с использованием протокола TCP/IP с другим компьютером по сети Ethernet с пропускной способностью 100Mбит/сек скорость будет на 8-11% ниже.
  • При запуске наших тестов производительности с использованием безопасных соединений (все данные зашифрованы с поддержкой протокола SSL) скорость была на 55% ниже.
  • Если код компилируется с параметром --with-debug=full, то для большинства запросов потери в производительности будут составлять до 20%, но некоторые запросы могут выполняться значительно дольше (тесты производительности MySQL работают на 35% медленнее). При использовании опции --with-debug теряется только 15% производительности. При запуске mysqld, откомпилированного с --with-debug=full и --skip-safemalloc, результат должен почти таким же, как и при компиляции с --with-debug.
  • На компьютере Sun UltraSPARC-IIe, Forte 5.0 дает на 4% более быстрый код чем gcc 3.2
  • На компьютере Sun UltraSPARC-IIe, Forte 5.0 дает на 4% более быстрый код в 32-разрядном режиме чем в 64-разрядном.
  • Компилирование посредством gcc 2.95.2 для UltraSPARC с опцией -mcpu=v8 -Wa,-xarch=v8plusa дает прирост производительности на 4%.
  • Под операционной системой Solaris 2.5.1 потоки MIT-pthreads на 8-12% медленнее, чем собственные потоки Solaris для единичного процессора. При возрастании нагрузки на процессоры разница должна получиться больше.
  • Запуск с --log-bin делает mysqld на 1% медленнее.
  • Компилирование под Linux-x86 с использованием gcc без указателей фреймов -fomit-frame-pointer или -fomit-frame-pointer -ffixed-ebp делает mysqld на 1-4% быстрее.

Поставка MySQL под Linux, которую предоставляет MySQL AB, обычно компилировалась с pgcc, но мы должны были вернуться к обычному компилятору gcc из-за ошибок в pgcc, которая могут генерировать код, не исполняемый на AMD. Пока эти ошибки не будут устранены, мы будем продолжать использовать gcc, однако если ваш компьютер не относится к типу AMD, то можно получить более быстрый двоичный код, компилируя его с pgcc. Стандартный двоичный код MySQL для Linux слинкован статически, чтобы сделать его более быстрым и более переносимым.

5.5.4 Как MySQL использует память

В следующем перечне дано описание некоторых аспектов использования памяти сервером mysqld. Там, где это возможно, приводятся имена серверных переменных, относящихся к использованию памяти:

  • Буфер ключей (переменная key_buffer_size) используется совместно всеми потоками; другие буферы, используемые данным сервером, выделяются при необходимости (see section 5.5.2 Настройка параметров сервера).
  • Каждое соединение использует определенное пространство в памяти для конкретного потока: стек (по умолчанию 64Kб, переменная thread_stack), буфер соединения (переменная net_buffer_length) и буфер результата (переменная net_buffer_length). Буфер соединения и буфер результата при необходимости динамически расширяются вплоть до max_allowed_packet. При выполнении запроса также выделяется память для копии строки данного текущего запроса.
  • Все потоки совместно используют одну и туже базовую память. Только сжатые таблицы типа ISAM/MyISAM имеют распределенную память. Это объясняется тем, что 4 Гб памяти (адресуемой в рамках 32-битной разрядности) мало для достаточно больших таблиц. Когда системы с 64-разрядными адресным пространством получат более широкое распространение, мы сможем добавить в сервер общую поддержку для распределения памяти.
  • Каждый запрос, выполняющий последовательный просмотр таблицы, размещается в буфере чтения (переменная record_buffer).
  • При чтении строк в "случайном" порядке (например, после сортировки) выделяется буфер "случайного чтения", чтобы избежать поиска по диску (переменная record_rnd_buffer).
  • Все объединения выполняются за одну операцию, и большинство объединений может производиться даже без временных таблиц. Большинство временных таблиц располагаются в оперативной памяти (в динамически выделяемой области HEAP). Временные таблицы с записями большой длины (вычисляемой как сумма длин всех столбцов) или таблицы, содержащие столбцы BLOB, хранятся на диске. В версиях MySQL до 3.23.2 существует проблема, заключающаяся в том, что если таблицы HEAP в динамически выделяемой области превышают размер tmp_table_size, то возникает ошибка The table tbl_name is full. В более новых версиях эта проблема при необходимости решается путем автоматического преобразования хранящихся в оперативной памяти HEAP-таблиц в таблицы MyISAM, расположенные на диске. Чтобы обойти эту проблему, можно увеличить размер временных таблиц установкой опции tmp_table_size в mysqld или установкой SQL-опции SQL_BIG_TABLES в клиентской программе (see section 5.5.6 Синтаксис команды SET). В версии MySQL 3.20 максимальный размер временной таблицы был равен record_buffer*16, так что при использовании данной версии необходимо увеличить значение record_buffer. Можно также запустить mysqld с опцией --big-tables - для того, чтобы всегда хранить временные таблицы на диске. Однако это будет влиять на скорость многих сложных запросов.
  • Большинство запросов, выполняющих сортировку, размещаются в буфере сортировки и в 0-2 временных файлах, в зависимости от размера результирующего набора данных (see section A.4.4 Где MySQL хранит временные файлы).
  • Почти все операции, связанные с анализом и вычислениями, выполняются в пространстве локальной памяти. Для небольших задач не требуется никаких дополнительных затрат памяти и удается избежать обычно медленных процессов выделения и освобождения памяти. Память выделяется только для непредвиденно больших строк (это делается с помощью функций malloc() и free()).
  • Каждый файл индексов и файл данных открываются сразу для каждого параллельно работающего потока. Для каждого параллельного потока выделяется место в памяти для структуры таблицы, структур столбцов для каждого столбца и буфер размером 3 * n (где n представляет максимальную длину строки без учета столбцов BLOB). Для столбца BLOB используется от 5 до 8 байтов плюс длина данных BLOB. Обработчики таблиц ISAM/MyISAM будут использовать один дополнительный буфер строки для внутреннего представления.
  • Для каждой таблицы, имеющей столбцы BLOB, буфер динамически увеличивается при чтении больших величин BLOB. При просмотре таблицы выделяется буфер с размером, равным наибольшей величине BLOB.
  • Обработчики всех находящихся в употреблении таблиц хранятся в кэше и обрабатываются в порядке их поступления (режим FIFO). Обычно этот кэш содержит 64 элемента. Если данная таблица была использована двумя работающими потоками в одно и то же время, то кэш содержит два элемента для такой таблицы (see section 5.4.7 Открытие и закрытие таблиц в MySQL).
  • Команда mysqladmin flush-tables закрывает все неиспользуемые таблицы и отмечает все используемые таблицы, которые необходимо закрыть после окончания выполнения текущего потока. Такой алгоритм позволяет эффективно освобождать большое количество используемой памяти.

Программа ps и другие программы контроля состояния системы могут сообщать, что mysqld использует слишком много памяти. Это может быть вызвано расположением стеков памяти потоков по различным адресам в памяти. Например, версия программы ps для Solaris интерпретирует неиспользуемую память между стеками как используемую. Это можно проверить путем выполнения допустимой перестановки с помощью swap -s. Мы тестировали mysqld при помощи коммерческих детекторов утечки памяти, так что никаких потерь памяти быть не должно.

5.5.5 Как MySQL использует DNS

Когда к mysqld подключается новый клиент, mysqld выделяет новый поток для обработки данного запроса. Этот поток вначале проверяет, имеется ли в кэше имен хостов имя требуемого хоста. Если нет, то поток вызовет функции gethostbyaddr_r() и gethostbyname_r(), чтобы определить имя хоста.

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

Можно заблокировать поиск DNS хоста, запустив mysqld с параметром --skip-name-resolve. В этом случае, однако, в таблицах привилегий MySQL можно использовать только IP-адреса.

Если процесс установления DNS очень медленный и хостов очень много, то можно получить более высокую производительность либо путем блокировки поиска DNS при помощи --skip-name-resolve, либо увеличив размер определения HOST_CACHE_SIZE (по умолчанию: 128) и перекомпилировав mysqld.

Заблокировать кэш имен хостов можно с помощью --skip-host-cache. Можно также очистить этот кэш с помощью команды FLUSH HOSTS или mysqladmin flush-hosts.

Можно запретить соединения по протоколу TCP/IP, запустив mysqld с опцией --skip-networking.

5.5.6 Синтаксис команды SET

SET [GLOBAL | SESSION] sql_variable=expression, [[GLOBAL | SESSION] sql_variable=expression...]

Команда SET устанавливает различные опции, влияющие на работу сервера или клиента.

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

В старых версиях MySQL мы допускали использование SET OPTION, но этот синтакс теперь считается морально устаревшим.

В MySQL 4.0.3 мы также добавили режимы GLOBAL и SESSION и реализовали доступ к наиболее важным переменным запуска.

LOCAL может использоваться как синоним для SESSION.

Если вы устанавливаете несколько переменных в одной команде, то последний указанный режим GLOBAL | SESSION будет использован.

SET sort_buffer_size=10000;
SET @@local.sort_buffer_size=10000;
SET GLOBAL sort_buffer_size=1000000, SESSION sort_buffer_size=1000000;
SET @@sort_buffer_size=1000000;
SET @@global.sort_buffer_size=1000000, @@local.sort_buffer_size=1000000;

Синтаксис @@variable_name поддерживается с тем, чтобы сделать MySQL более совместимым с другими СУБД.

Различные системные переменные, которые вы можете установить, описаниы в этом руководстве. See section 6.1.5 Системные переменные.

Если вы используете режим SESSION (по умолчанию), то значения переменных, которые вы устанавливаете, остаются в в действии до тех пор, пока текущая сессия не будет завершена, или до тех пор, пока вы не установите переменные в другое значение. Если вы используете GLOBAL, который требует привилегии SUPER, это значение запоминается и используется для всех новых соединений до тех пор, пока сервер не будет перезагружен. Если вы хотите сделать какое-либо значение перманентным, то вам следует указать его в одном из файлов конфигураций MySQL. See section 4.1.2 Файлы параметров `my.cnf'.

Чтобы избежать неправильного использования, MySQL будет сообщать об ошибке, если вы будете выполнять SET GLOBAL на переменной, которую только можно изменять в SET SESSION или если вы не выбираете режим GLOBAL для глобальной переменной.

Если вы хотите установить сессионную (SESSION) переменную в значение глобальной (GLOBAL) или просто в значение по умолчанию - вы можете установить это значение в DEFAULT.

SET max_join_size=DEFAULT;

Это аналогично:

SET @@session.max_join_size=@@global.max_join_size;

Если вам необходимо ограничить максимальное значение, которое может принимать стартовая переменная с помощью SET, вы можете указать это с помощью использования опции командной строки --maximum-variable-name. See section 4.1.1 Параметры командной строки mysqld.

Список большинства переменных можно получить с помощью SHOW VARIABLES. See section 4.5.6.4 SHOW VARIABLES. Вы можете получить конкретное значение с помощью синтаксиса @@[global.|local.]variable_name:

SHOW VARIABLES like "max_join_size";
SHOW GLOBAL VARIABLES like "max_join_size";
SELECT @@max_join_size, @@global.max_join_size;

Далее следует описание переменных, использующих нестандартный синтаксис SET и некоторых других. Описание других переменных можно найти в секции, описывающих системные переменные, вместе с описанием стартовых опций или в описании команды SHOW VARIABLES. See section 6.1.5 Системные переменные. See section 4.1.1 Параметры командной строки mysqld. See section 4.5.6.4 SHOW VARIABLES.

CHARACTER SET character_set_name | DEFAULT
Преобразует все строки, передающиеся от клиента, и строки передающиеся клиенту, в соответствии с заданным набором символов. В настоящее время единственной опцией для character_set_name является cp1251_koi8, но можно легко добавить новые наборы символов, отредактировав файл sql/convert.cc в дистрибутиве исходного кода MySQL. Чтобы восстановить установку по умолчанию, следует установить значение character_set_name в DEFAULT. Следует учитывать, что синтаксис установки опции CHARACTER SET отличается от синтаксиса установки других опций.
PASSWORD = PASSWORD('некий пароль')
Устанавливает пароль для текущего пользователя. Любой не анонимный пользователь может изменить свой собственный пароль!
PASSWORD FOR user = PASSWORD('некий пароль')
Устанавливает пароль для особого пользователя для текущего серверного хоста. Это может сделать только пользователь, имеющий доступ к базе данных mysql. Данный пользователь должен быть представлен в формате user@hostname, где user и hostname в точности соответствуют записям этих позиций в столбцах User и Host в таблице mysql.user. Например, если записи в полях User и Host соответственно были bob и %.loc.gov, то необходимо писать:
mysql> SET PASSWORD FOR bob@"%.loc.gov" = PASSWORD("newpass");
или
mysql> UPDATE mysql.user SET password=PASSWORD("newpass")
    ->                   WHERE user="bob" AND host="%.loc.gov";
SQL_AUTO_IS_NULL = 0 | 1
Если установить в 1 (значение по умолчанию), то можно найти последнюю внесенную строку для таблицы со столбцом AUTO_INCREMENT с помощью следующей конструкции: WHERE auto_increment_column IS NULL. Эта возможность используется некоторыми ODBC-программами, такими как Access.
AUTOCOMMIT = 0 | 1
Если установить в 1, то все изменения в таблицу будут вноситься немедленно. Чтобы открыть многокомандную транзакцию, необходимо использовать команду BEGIN (see section 6.7.1 Синтаксис команд BEGIN/COMMIT/ROLLBACK). Если установить данную опцию в 0, то необходимо использовать COMMIT / ROLLBACK для того, чтобы принять/отменить эту транзакцию (see section 6.7.1 Синтаксис команд BEGIN/COMMIT/ROLLBACK). Следует учитывать, что при переходе из режима работы без AUTOCOMMIT в режим AUTOCOMMIT MySQL автоматически выполнит COMMIT для любой открытой транзакции.
BIG_TABLES = 0 | 1
Если установить в 1, то предпочтительным местом хранения всех временных таблиц будет диск, а не оперативная память. Это вызовет некоторое замедление работы, зато для больших операций SELECT, требующих обширных временных таблиц, не будет выдаваться ошибка The table tbl_name is full. Для нового соединения значение этой величины по умолчанию равно 0 (т.е. использовать для временных таблиц оперативную память). Эта переменная раньше называлась SQL_BIG_TABLES.
SQL_BIG_SELECTS = 0 | 1
При установке в 0 MySQL будет прерывать выполнение запроса, если поступившая команда SELECT может потребовать слишком много времени для выполнения. Такая возможность полезна при нерационально написанном выражении WHERE. Запрос классифицируется как слишком большой, если оператору SELECT, видимо, пришлось бы обрабатывать больше строк, чем задано в max_join_size. Для нового соединения значение по умолчанию равно 1 (т.е. разрешаются любые команды SELECT).
SQL_BUFFER_RESULT = 0 | 1
SQL_BUFFER_RESULT будет заносить результат выполнения команд SELECT во временную таблицу. Это поможет MySQL раньше освободить блокировки таблиц и окажется полезным в случаях, когда требуется значительное время для пересылки результирующего набора данных клиенту.
LOW_PRIORITY_UPDATES = 0 | 1
При установке в 1 все команды INSERT, UPDATE, DELETE и LOCK TABLE WRITE будут ожидать, пока не будет ни одной ожидающей решения команды SELECT или LOCK TABLE READ на обрабатываемой таблице. Эта переменная раньше называлась SQL_LOW_PRIORITY_UPDATES.
MAX_JOIN_SIZE = значение | DEFAULT
Запрещает команды SELECT, которым, возможно, придется обрабатывать более, чем указанное значение комбинаций строк. Установив эту величину, можно определить команды SELECT, в которых ключи используются неправильно и которые, возможно, потребуют длительного времени для исполнения. При установке этой опции в величину, отличную от DEFAULT, сбрасывается флаг SQL_BIG_SELECTS. Если вновь установить флаг SQL_BIG_SELECTS, то переменная SQL_MAX_JOIN_SIZE будет игнорироваться. Значение по умолчанию для этой переменной можно установить, запустив mysqld с -O max_join_size=#. Эта переменная раньше называлась SQL_MAX_JOIN_SIZE. Следует учитывать, что если результат запроса всегда находится в кэше запросов, то упомянутая выше проверка выполняться не будет. Вместо этого MySQL будет отсылать результат клиенту, поскольку результат запроса уже вычислен и отсылка его клиенту не создаст нагрузки для сервера.
QUERY_CACHE_TYPE = OFF | ON | DEMAND
QUERY_CACHE_TYPE = 0 | 1 | 2
Определяет установку кэша запросов для данного потока.
Опция | Описание
0 or OFF | Не кэшировать или не извлекать результаты
1 or ON | Кэшировать все результаты за исключением запросов SELECT SQL_NO_CACHE ...
2 or DEMAND | Кэшировать только запросы SELECT SQL_CACHE ...
SQL_SAFE_UPDATES = 0 | 1
Если установить в 1, то MySQL будет прерывать выполнение поступивших команд UPDATE или DELETE, в которых не используется ключ или LIMIT в выражении WHERE. Это позволяет обнаружить ошибочные обновления при ручном создании команд SQL.
SQL_SELECT_LIMIT = value | DEFAULT
Максимальное количество записей, возвращаемых командой SELECT. Если SELECT содержит выражение LIMIT, то LIMIT превосходит по старшинству величину в SQL_SELECT_LIMIT. Для нового соединения значение по умолчанию равно "unlimited". Если предел был изменен, то его можно вернуть в значение по умолчанию указанием величины DEFAULT в выражении SQL_SELECT_LIMIT.
SQL_LOG_OFF = 0 | 1
При установке в 1 для данного клиента в стандартный журнал не будут заноситься никакие записи, если клиент имеет привилегии SUPER. Это не относится к журналу обновлений!
SQL_LOG_UPDATE = 0 | 1
При установке в 0 для данного клиента в журнал обновлений не будут заноситься никакие записи, если клиент имеет привилегии SUPER. Это не относится к стандартному журналу!
SQL_QUOTE_SHOW_CREATE = 0 | 1
При установке этой опции в 1 SHOW CREATE TABLE будет заключать в кавычки имена таблиц и столбцов. Имеет значение Включено по умолчанию, чтобы работала репликация таблиц с изощренными именами столбцов (see section 4.5.6.8 SHOW CREATE TABLE).
TIMESTAMP = timestamp_value | DEFAULT
Устанавливает время для данного клиента. Применяется для получения первоначальной временной метки при использовании журнала обновлений для восстановления строк. Переменная timestamp_value должна представлять системное время Unix, а не временную метку MySQL.
LAST_INSERT_ID = #
Устанавливает величину, возвращаемую функцией LAST_INSERT_ID(). Хранится в журнале обновлений при использовании функции LAST_INSERT_ID() в команде, обновляющей таблицу.
INSERT_ID = #
Устанавливает величину, которую следует использовать в следующей команде INSERT или ALTER TABLE при внесении величины AUTO_INCREMENT. В основном используется с журналом обновлений.

5.6 Вопросы, относящиеся к диску

  • Как уже упоминалось ранее, наиболее узким местом для производительности является поиск на диске. Эта проблема становится все более и более очевидной по мере того, как объем данных увеличивается настолько, что эффективное кэширование становится невозможным. Для крупных баз данных, где доступ к данным осуществляется более или менее случайным образом, можно с уверенностью сказать, что потребуется по меньшей мере один поиск по диску для чтения и пара поисков по диску для записи некоторой информации. Чтобы свести эту проблему к минимуму, следует использовать диски с малыми временами поиска.
  • Можно увеличить количество доступных дисковых "блоков" (и, таким образом, уменьшить нагрузку на диски). Это делается либо путем установления символических ссылок на разные диски, либо использованием RAID (stripe).
    Использование символических ссылок
    Это означает, что создаются символические ссылки индекса и/или файла/файлов данных из обычного каталога данных на иной диск (для которого, помимо этого, можно использовать RAID (stripe)). Применение символических ссылок улучшает как время поиска, так и время чтения (если эти диски не используются для других операций). See section 5.6.1 Использование символических ссылок.
    Использование RAID (stripe)
    Использование RAID (stripe) подразумевает, что при наличии нескольких дисков первый блок данных помещается на первом диске, второй блок - на втором диске, N-ный блок на диске с номером, равным остатку от целочисленного деления количества блоков N на число дисков, и т.д. При этом подразумевается, что если нормальный размер данных меньше, чем размер RAID-блока (или в точности равен ему), то производительность будет намного лучше. Следует учитывать, что процесс разделения дисков на RAID-блоки в значительной степени зависит от операционной системы и размера RAID-блока. Поэтому тесты производительности конкретного приложения необходимо производить для разных размеров RAID-блока (see section 5.1.5 Использование собственных тестов). Следует также учитывать, что разница в скорости при разделении дисков на RAID-блоки сильно зависит от заданных параметров. В зависимости от того, как установлены параметры разделения на RAID-блоки и каково количество дисков, можно получить величины с разницей в несколько порядков. Следует помнить, что необходимо выбрать оптимизацию отдельно для случайного и отдельно для последовательного доступа.
  • Для надежности можно использовать режим RAID 0+1 (разделение на RAID-блоки + зеркальное отображение), но в этом случае будет необходимо 2*N дисководов для хранения информации N дисководов данных. Если возможности позволяют, то такой вариант выбора - наилучший! Однако при этом могут понадобиться также инвестиции и в программное обеспечение для эффективного управления этим объемом оборудования.
  • Существует еще одна неплохая возможность: хранить не слишком важные данные (которые могут быть воспроизведены) на диске RAID 0, а действительно важные данные (такие как информация о хостах и журналы) - на диске RAID 0+1 или диске RAID N. Использование RAID N может оказаться проблемой, если у вас много операций записи, потому что обновление битов четности занимает время.
  • Можно также задать требуемые параметры для используемой базой данных файловой системы. Легко поддается изменению монтирование файловой системы с опцией noatime. Использование этой опции позволяет пропускать обновление при последнем обращении в данном режиме и тем самым избежать поиска по диску.
  • Под Linux можно получить намного большую производительность (под нагрузкой нередко вплоть до 100%), используя hdpram для конфигурации интерфейса диска! Приведенные ниже опции для hdparm зарекомендовали себя как очень полезные для MySQL (и, возможно, для многих других приложений):
    hdparm -m 16 -d 1
    Следует учитывать, что производительность/надежность при использовании приведенных выше рекомендаций зависит от конкретного оборудования, так что мы настоятельно рекомендуем вам основательно протестировать систему после использования hdparm! Для получения более подробной информации о применении hdparm, обращайтесь, пожалуйста, к соответствующей странице руководства! Некомпетентное применение hdparm может привести к разрушению файловой системы. Прежде чем экспериментировать, сделайте полную резервную копию!
  • Во многих операционных системах можно монтировать диски с флагом async - для того, чтобы данная файловая система могла обновляться асинхронно. Если ваш компьютер достаточно стабилен, это должно обеспечить повышение производительности без слишком большой потери надежности (под Linux этот флаг включен по умолчанию).
  • Если нет необходимости знать, к какому файлу было последнее обращение (что реально не используется на сервере баз данных), можно смонтировать файловые системы с флагом noatime.

5.6.1 Использование символических ссылок

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

Рекомендуется создавать символические ссылки на другой диск для баз данных, а символические ссылки для таблиц - только в крайних случаях.

5.6.1.1 Использование символических ссылок для баз данных

Для создания символической ссылки для базы данных вначале следует создать каталог на некотором диске, где имеется свободное место, а затем создать символическую ссылку на него из каталога баз данных MySQL.

shell> mkdir /dr1/databases/test
shell> ln -s /dr1/databases/test mysqld-datadir

MySQL не поддерживает ссылку из одного каталога на несколько баз данных. Замещение каталога базы данных символической ссылкой будет хорошо работать только в случае, если вы не создаете символическую ссылку между базами данных. Предположим, имеется база данных db1 в каталоге данных MySQL и создается символическая ссылка db2, указывающая на db1:

shell> cd /path/to/datadir
shell> ln -s db1 db2

Теперь для любой таблицы tbl_a в db1 должна существовать таблица tbl_a в db2. Если один поток обновляет db1.tbl_a, а другой поток - db2.tbl_a, то возникнут проблемы.

Если описанная выше возможность действительно необходима, то нужно изменить следующий код в mysys/mf_format.c:

if (flag & 32 || (!lstat(to,&stat_buff) && S_ISLNK(stat_buff.st_mode)))

на

if (1)

Под Windows можно использовать внутренние символические ссылки на каталоги (путем компиляции MySQL с -DUSE_SYMDIR). Это позволяет размещать различные базы данных на различных дисках (see section 2.6.2.5 Распределение данных в Windows между несколькими различными дисками).

5.6.1.2 Использование символических ссылок для таблиц

Не следует использовать символические ссылки для таблиц в версиях до MySQL 4.0, где при работе с ними требуется особая тщательность. Проблема заключается в том, что, если запускаются команды ALTER TABLE, REPAIR TABLE или OPTIMIZE TABLE на таблице, связанной символической ссылкой, то символические ссылки будут удалены и заменены исходными файлами. Это происходит потому, что любая вышеназванная команда работает путем создания временного файла в каталоге базы данных и по завершении команды происходит замещение исходного файла временным.

Не следует связывать символическими ссылками таблицы в системах, где вызов функции realpath() работает не полностью (по крайней мере, realpath() поддерживают Linux и Solaris).

В MySQL 4.0 символические ссылки полностью поддерживаются только для таблиц MyISAM. Для других типов таблиц при выполнении какой-либо из вышеупомянутых команд могут возникать непонятные проблемы.

Обработка символических ссылок в MySQL 4.0 происходит следующим образом (это в основном относится только к таблицам MyISAM).

  • В каталоге данных всегда будет находиться файл определения таблицы и файлы данных/индексов.
  • Можно связывать символическими ссылками файл индексов и файл данных с различными каталогами независимо друг от друга.
  • Связывание символическими ссылками можно выполнить из операционной системы (если не запущен mysqld) или с помощью команды INDEX/DATA DIRECTORY="path-to-dir" в CREATE TABLE (see section 6.5.3 Синтаксис оператора CREATE TABLE).
  • myisamchk не замещает символическую ссылку на индекс/файл, а работает напрямую с файлами, на которые указывает символическая ссылка. Все временные файлы будут создаваться в том же каталоге, где находится файл данных/индексов.
  • При удалении таблицы, в которой используются символические ссылки, как ссылка, так и файл, на который ссылка указывает, удаляются. Это веская причина для того, чтобы не запускать mysqld в качестве суперпользователя (root) и не позволять другим иметь доступ к записи в каталоги баз данных MySQL.
  • Если таблица переименовывается с помощью ALTER TABLE RENAME, и вы не переносите таблицу в другую базу данных, то данная символическая ссылка в каталоге базы данных будет переименована и файл данных/индексов соответственно будет переименован.
  • Если ALTER TABLE RENAME используется для переноса таблицы в другую базу данных, то эта таблица будет перенесена в другой каталог базы данных, а старые символические ссылки и файлы, на которые они указывают, будут удалены. Иными словами, новая таблица не будет ссылкой.
  • Если символические ссылки не применяются, то необходимо использовать опцию --skip-symlink в mysqld для уверенности, что никто не сможет удалить или переименовать файл вне каталога данных этого потока.

Возможности, которые пока еще не поддерживаются:

  • ALTER TABLE игнорирует все опции INDEX/DATA DIRECTORY="path".
  • CREATE TABLE не сообщает, что данная таблица имеет символические ссылки.
  • mysqldump не включает в вывод информацию о символических ссылках.
  • BACKUP TABLE и RESTORE TABLE не признают символические ссылки.


Справочное руководство по MySQL версии 5.0.0-alpha. - 6 Справочник по языку MySQL

6 Справочник по языку MySQL

MySQL имеет очень сложный, но интуитивно понятный и легкий в изучении интерфейс, основанный на SQL (структурированный язык запросов). В данном разделе описываются различные команды, типы данных и функции этого языка, которые необходимо знать, чтобы использовать MySQL рационально и эффективно. Данная глава служит также справочником по всем функциональным возможностям, реализованным в MySQL. Читатель найдет в этой главе ссылки на различные источники информации, которые, возможно, будут полезными для ее эффективного использования.

6.1 Структура языка

6.1.1 Литералы: представление строк и чисел

В этом разделе описываются различные способы представления строк и чисел в MySQL. Здесь затронуты также различные нюансы и особенности, с которыми могут столкнуться программисты при работе с этими базовыми типами данных в MySQL.

6.1.1.1 Cтроки

Строка представляет собой последовательность символов, заключенных либо в одинарные кавычки (`'') - апострофы, либо в двойные кавычки (`"'). При использовании диалекта ANSI SQL допустимы только одинарные кавычки. Например:

'a string'
"another string"

Внутри строки некоторые последовательности символов имеют специальное назначение. Каждая из этих последовательностей начинается обратным слешем (`\'), известным как escape-символ или символ перехода. MySQL распознает следующие escape-последовательности:

\0
Символ 0 (NUL) в ASCII коде.
\'
Символ одиночной кавычки (`'').
\"
Символ двойной кавычки (`"').
\b
Возврат на один символ.
\n
Символ новой строки (перевода строки).
\r
Символ перевода каретки.
\t
Символ табуляции.
\z
Символ (Control-Z) таблицы ASCII(26). Данный символ можно закодировать, чтобы обойти проблему, заключающуюся в том, что под Windows ASCII(26) означает конец файла (проблемы возникают при использовании ASCII(26) в выражении mysql database < filename).
\\
Символ обратного слеша.
\%
Символ процентов `%'. Используется для поиска копий литерала `%' в контекстах, где выражение `%' в противном случае интерпретировалось бы как групповой символ (see section 6.3.2.1 Функции сравнения строк).
\`_'
Символ подчеркивания `_'. Используется для поиска копий литерала `_' в контекстах, где выражение `_' в противном случае интерпретировалось бы как групповой символ (see section 6.3.2.1 Функции сравнения строк).

Обратите внимание на то, что при использовании `\%' или `\_' в контекстах некоторых строк будут возвращаться значения строк `\%' и `\_', а не `%' и `_'.

Существует несколько способов включить кавычки в строку:

  • Одиночная кавычка (апостроф) `'' внутри строки, заключенной в кавычки `'', может быть записана как `'''.
  • Двойная кавычка `"' внутри строки, заключенной в двойные кавычки `"', может быть записана как `""'.
  • Можно предварить символ кавычки символом экранирования (`\').
  • Для символа `'' внутри строки, заключенной в двойные кавычки, не требуется специальной обработки; его также не требуется дублировать или предварять обратным слешем. Точно так же не требует специальной обработки двойная кавычка `"' внутри строки, заключенной в одиночные кавычки `''.

Ниже показаны возможные варианты применения кавычек и escape-символа на примерах выполнения команды SELECT:

mysql> SELECT 'hello', '"hello"', '""hello""', 'hel''lo', '\'hello';
+-------+---------+-----------+--------+--------+
| hello | "hello" | ""hello"" | hel'lo | 'hello |
+-------+---------+-----------+--------+--------+

mysql> SELECT "hello", "'hello'", "''hello''", "hel""lo", "\"hello";
+-------+---------+-----------+--------+--------+
| hello | 'hello' | ''hello'' | hel"lo | "hello |
+-------+---------+-----------+--------+--------+

mysql> SELECT "This\nIs\nFour\nlines";
+--------------------+
| This
Is
Four
lines |
+--------------------+

Если необходимо вставить в строку двоичные данные (такие как BLOB), следующие символы должны быть представлены как escape-последовательности:

NUL
ASCII 0. Необходимо представлять в виде `\0' (обратный слеш и символ ASCII `0').
\
ASCII 92, обратный слеш. Представляется как `\\'.
'
ASCII 39, единичная кавычка. Представляется как `\''.
"
ASCII 34, двойная кавычка. Представляется как `\"'.

При написании программы на языке C для добавления символов экранирования в команде INSERT можно использовать функцию mysql_real_escape_string() из C API (see section 8.4.2 Обзор функций интерфейса C). При программировании на Perl можно использовать метод quote из пакета DBI для превращения специальных символов в соответствующие escape-последовательности (see section 8.2.2 Интерфейс DBI).

Не следует забывать, что указанное свойство escape-символа должно использоваться во всех строках, которые могут содержать любые специальные символы, перечисленные выше.

В качестве альтернативы многие интерфейсы прикладного программирования (API) для MySQL предоставляют определенную возможность использования символов-заменителей, что позволяет вносить специальные маркеры в строку запроса и затем связывать с ними значения данных при выдаче результатов запроса.

6.1.1.2 Числа

Целые числа представляются в виде последовательности цифр. Для чисел с плавающей точкой в качестве разделителя десятичных знаков используется символ `.'. Числа обоих типов могут предваряться символом `-', обозначающим отрицательную величину.

Примеры допустимых целых чисел:

1221
0
-32

Примеры допустимых чисел с плавающей запятой:

294.42
-32032.6809e+10
148.00

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

6.1.1.3 Шестнадцатеричные величины

MySQL поддерживает шестнадцатеричные величины. В числовом контексте такое число обладает всеми свойствами целого числа с 64-разрядной точностью. В строковом контексте шестнадцатеричная величина представляет собой двоичную строку, в которой каждая пара шестнадцатеричных разрядов конвертируется в символ:

mysql> SELECT x'4D7953514C';
         -> MySQL
mysql> SELECT 0xa+0;
         -> 10
mysql> SELECT 0x5061756c;
         -> Paul

Синтаксис выражений вида x'hexstring' (новшество в версии 4.0) базируется на ANSI SQL, а для обозначений вида 0x используется синтаксис ODBC. Шестнадцатеричные строки часто применяются в ODBC для представления двоичных типов данных вида BLOB. Для конвертирования строки или числа в шестнадцатеричный вид можно применять функцию HEX().

6.1.1.4 Значения NULL

Значение NULL означает ``отсутствие данных''. Они является отличным от значения 0 для числовых типов данных или пустой строки для строковых типов (see section A.5.3 Проблемы со значением NULL).

При использовании форматов импорта или экспорта текстовых файлов (LOAD DATA INFILE, SELECT ... INTO OUTFILE) NULL можно представить как \N (see section 6.4.9 Синтаксис оператора LOAD DATA INFILE).

6.1.2 Имена баз данных, таблиц, столбцов, индексы псевдонимы

Для всех имен баз данных, таблиц, столбцов, индексов и псевдонимов в MySQL приняты одни и те же правила.

Следует отметить, что эти правила были изменены, начиная с версии MySQL 3.23.6, когда было разрешено брать в одиночные скобки ``' идентификаторы (имена баз данных, таблиц и столбцов). Двойные скобки `"' тоже допустимы - при работе в режиме ANSI SQL (see section 1.9.2 Запуск MySQL в режиме ANSI).

Идентификатор | Максимальная длина строки | Допускаемые символы
База данных | 64 | Любой символ, допустимый в имени каталога, за исключением `/', `\' или `.'
Таблица | 64 | Любой символ, допустимый в имени файла, за исключением `/' или `.'
Столбец | 64 | Все символы
Псевдоним | 255 | Все символы

Необходимо также учитывать, что не следует использовать символы ASCII(0), ASCII(255) или кавычки в самом идентификаторе.

Кроме того, если имя идентификатора относится к служебным словам или содержит специальные символы, необходимо всегда заключать его в обратные кавычки ` при использовании в выражениях:

mysql> SELECT * FROM `select` WHERE `select`.id > 100;

See section 6.1.7 ``Придирчив'' ли MySQL к зарезервированным словам?.

В предыдущих версиях MySQL (до 3.23.6) для имен существовали следующие правила:

  • Имя может состоять из буквенно-цифровых символов установленного в данное время алфавита и символов `_' and `$'. Тип кодировки по умолчанию - ISO-8859-1 Latin1, он может быть изменен указанием иного типа в аргументе параметра --default-character-set mysqld (see section 4.6.1 Набор символов, применяющийся для записи данных и сортировки).
  • Имя может начинаться с любого допустимого символа, в частности, с цифры (в этом состоит отличие от правил, принятых во многих других базах данных). Однако имя не может состоять только из цифр.
  • Не допускается использование в именах символа `.', так как он применяется для расширения формата имени (посредством чего можно ссылаться на столбцы - см. в этом же разделе ниже).

Не рекомендуется использовать имена, подобные 1e, так как выражение вида 1e+1 является неоднозначным. Оно может интерпретироваться и как выражение 1e + 1, и как число 1e+1.

В MySQL разрешается делать ссылки на столбец, используя любую из следующих форм:

Ссылка на столбец | Значение
col_name | Столбец col_name из любой используемой в запросе таблицы содержит столбец с данным именем.
tbl_name.col_name | Столбец col_name из таблицы tbl_name текущей базы данных.
db_name.tbl_name.col_name | Столбец col_name из таблицы tbl_name базы данных db_name. Эта форма доступна в версии MySQL 3.22 или более поздних.
`column_name` | Имя столбца является ключевым словом или содержит специальные символы.

Нет необходимости указывать префикс tbl_name или db_name.tbl_name в ссылке на столбец в каком-либо утверждении, если эта ссылка не будет неоднозначной. Например, предположим, что каждая из таблиц t1 и t2 содержит столбец c, по которому производится выборка командой SELECT, использующей обе таблицы - и t1, и t2. В этом случае имя столбца c является неоднозначным, так как оно не уникально для таблиц, указанных в команде, поэтому необходимо уточнить, какая именно таблица имеется в виду, конкретизировав - t1.c или t2.c. Аналогично, при выборке данных из таблицы t в базе данных db1 и из таблицы t в базе данных db2 необходимо ссылаться на столбцы в этих таблицах как на db1.t.col_name и db2.t.col_name.

Выражение .tbl_name означает таблицу tbl_name в текущей базе данных. Данный синтаксис принят для совместимости с ODBC, так как некоторые программы ODBC ставят в начале имен таблиц в качестве префикса символ `.'.

6.1.3 Чувствительность имен к регистру

В MySQL имена баз данных и таблиц соответствуют директориям и файлам внутри директорий. Следовательно, чувствительность к регистру операционной системы, под которой работает MySQL, определяет чувствительность к регистру имен баз данных и таблиц. Это означает, что имена баз данных и таблиц нечувствительны к регистру под Windows, а под большинством версий Unix проявляют чувствительность к регистру. Одно большое исключение здесь это Mac OS X, когда файловая система по умолчанию HFS+ используется. Однако Mac OS X также поддерживает тома UFS, которые чувствительны к регистру под Mac OS X также как и на Unix. See section 1.9.3 Расширения MySQL к ANSI SQL92.

Примечание: хотя имена баз данных и таблиц нечувствительны к регистру под Windows, не следует ссылаться на конкретную базу данных или таблицу, используя различные регистры символов внутри одного и того же запроса. Приведенный ниже запрос не будет выполнен, поскольку в нем одна и та же таблица указана и как my_table, и как MY_TABLE:

mysql> SELECT * FROM my_table WHERE MY_TABLE.col=1;

Имена и псевдонимы столбцов нечувствительны к регистру во всех случаях.

Псевдонимы таблиц обладают чувствительностью к регистру. Приведенный ниже запрос не будет выполнен, поскольку он ссылается на псевдоним и как на a, и как на A:

mysql> SELECT col_name FROM tbl_name AS a
    -> WHERE a.col_name = 1 OR A.col_name = 2;

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

Одним из путей устранения этой проблемы является запуск демона mysqld с параметром -O lower_case_table_names=1. По умолчанию этот параметр имеет значение 1 для Windows и 0 для Unix.

Если значение параметра lower_case_table_names равно 1, MySQL при сохранении и поиске будет преобразовывать все имена таблиц к нижнему регистру. С версии 4.0.2 это также касается и имен баз данных. Обратите внимание на то, что при изменении этого параметра перед запуском mysqld необходимо прежде всего преобразовать имена всех старых таблиц к нижнему регистру.

При переносе MyISAM-файлов с Windows на диск в Unix в некоторых случаях будет полезна утилита mysql_fix_extensions для приведения в соответствие регистров расширений файлов в каждой указанной директории базы данных (нижний регистр `.frm', верхний регистр `.MYI' и `.MYD'). Утилиту mysql_fix_extensions можно найти в подкаталоге `scripts'.

6.1.4 Переменные пользователя

Для конкретного процесса пользователь может определить локальные переменные, которые в MySQL обозначаются как @variablename. Имя локальной переменной может состоять из буквенно-цифровых символов установленного в данное время алфавита и символов `_', `$', and `.'. Тип кодировки по умолчанию - ISO-8859-1 Latin1, он может быть изменен указанием иного типа в аргументе параметра --default-character-set mysqld (see section 4.6.1 Набор символов, применяющийся для записи данных и сортировки).

Локальные переменные не требуют инициализации. Они содержат значение NULL по умолчанию; в них могут храниться целые числа, вещественные числа или строковые величины. При запуске конкретного процесса все объявленные в нем локальные переменные автоматически активизируются.

Локальную переменную можно объявить, используя синтаксис команды SET:

SET @variable= { integer expression | real expression | string expression }
[,@variable= ...].

Можно также определить значение переменной иным способом, без команды SET. Однако в этом случае в качестве оператора присвоения более предпочтительно использовать оператор `:=', чем оператор `=', так как последний зарезервирован для сравнения выражений, не связанных с установкой переменных:

mysql> SELECT @t1:=(@t2:=1)+@t3:=4,@t1,@t2,@t3;
+----------------------+------+------+------+
| @t1:=(@t2:=1)+@t3:=4 | @t1  | @t2  | @t3  |
+----------------------+------+------+------+
|                    5 |    5 |    1 |    4 |
+----------------------+------+------+------+

Введенные пользователем переменные могут применяться только в составе выражений и там, где выражения допустимы. Заметим, что в область их применения в данное время не включается контекст, в котором явно требуется число, например, условие LIMIT в команде SELECT или выражение IGNORE number LINES в команде LOAD DATA.

Примечание: в команде SELECT каждое выражение оценивается только при отправлении клиенту. Это означает, что в условиях HAVING, GROUP BY, or ORDER BY не следует ссылаться на выражение, содержащее переменные, которые введены в части SELECT этой команды. Например, следующая команда НЕ будет выполняться так, как ожидалось:

mysql> SELECT (@aa:=id) AS a, (@aa+3) AS b FROM table_name HAVING b=5;

Причина в том, что переменная @aa не будет содержать значения текущей строки, в то время как значение id в предыдущем выражении является строкой.

Действует правило никогда не создавать и не использовать одну и ту же переменную в одном и том же выражении SQL.

6.1.5 Системные переменные

Начиная с MySQL 4.0.3 мы предоставляем лучший доступ к большинству системных переменных и переменных, относящихся к соединению. Можно менять теперь большую часть переменных без необходимости останавливать сервер.

Есть два типа системных переменных: специфичные для потока (или для соединения; мы их в дальнейшем называем потоковыми переменными для краткости), которые уникальны для данного соединения и глобальные перемененные, которые предназначаются для управления глобальными событиями. Глобальные переменные также используются для того, чтобы установить значения по умолчанию для соответствующих потоковых переменных для новых соединений.

Когда mysqld запускается, все глобальные переменные инициализируются из командной строки и файлов опций. Вы можете изменять значения с помощью SET GLOBAL. Когда новый поток создается, потоковые переменные инициализируются из глобальных и они не меняются даже если вы даете новую команду SET GLOBAL.

Для установки глобальной переменной, используйте один из таких синтаксисов: (Здесь используется sort_buffer_size в качестве примера)

SET GLOBAL sort_buffer_size=value;
SET @@global.sort_buffer_size=value;

Чтобы установить значение для потоковой переменной, используйте такие синтаксисы:

SET SESSION sort_buffer_size=value;
SET @@session.sort_buffer_size=value;
SET sort_buffer_size=value;

Если вы не указываете режим, то тогда подразумевается SESSION. See section 5.5.6 Синтаксис команды SET.

LOCAL - синоним для SESSION.

Для получения значения глобальной переменной используйте одну из этих команд:

SELECT @@global.sort_buffer_size;
SHOW GLOBAL VARIABLES like 'sort_buffer_size';

Для получения значения потоковой переменной используйте одну из этих команд:

SELECT @@session.sort_buffer_size;
SHOW SESSION VARIABLES like 'sort_buffer_size';

Когда вы запрашиваете значение переменной с помощью синтаксиса @@variable_name и не укзываете GLOBAL или SESSION, то тогда MySQL вернет потоковое значение этой переменное, если таковое существует. Если нет, то MySQL вернет глобальное значение.

Причина, по которой требуется указывать GLOBAL для установки только глобальных переменных но не для получения их значения, заключается в том, чтобы удостовериться, что если мы в будущем не будем иметь проблем, если добавим потоковую переменную с таким же именем или уберем некую потоковую переменную. В этом случае вы можете ненароком изменить состояние сервера в целом, а не исключительно вашего соединения.

Далее идет полный список всех переменных которые вы можете изменять и значения которых можете получать, а также информация о том, можете ли вы использовать SESSION или GLOBAL с ними.

Переменная | Тип значения | Тип
autocommit | булевое | SESSION
big_tables | булевое | SESSION
binlog_cache_size | число | GLOBAL
bulk_insert_buffer_size | число | GLOBAL | SESSION
concurrent_insert | булевое | GLOBAL
connect_timeout | число | GLOBAL
convert_character_set | строка | SESSION
delay_key_write | OFF | ON | ALL | GLOBAL
delayed_insert_limit | число | GLOBAL
delayed_insert_timeout | число | GLOBAL
delayed_queue_size | число | GLOBAL
error_count | число | LOCAL
flush | булевое | GLOBAL
flush_time | число | GLOBAL
foreign_key_checks | булевое | SESSION
identity | число | SESSION
insert_id | булевое | SESSION
interactive_timeout | число | GLOBAL | SESSION
join_buffer_size | число | GLOBAL | SESSION
key_buffer_size | число | GLOBAL
last_insert_id | булевое | SESSION
local_infile | булевое | GLOBAL
log_warnings | булевое | GLOBAL
long_query_time | число | GLOBAL | SESSION
low_priority_updates | булевое | GLOBAL | SESSION
max_allowed_packet | число | GLOBAL | SESSION
max_binlog_cache_size | число | GLOBAL
max_binlog_size | число | GLOBAL
max_connect_errors | число | GLOBAL
max_connections | число | GLOBAL
max_error_count | число | GLOBAL | SESSION
max_delayed_threads | число | GLOBAL
max_heap_table_size | число | GLOBAL | SESSION
max_join_size | число | GLOBAL | SESSION
max_sort_length | число | GLOBAL | SESSION
max_tmp_tables | число | GLOBAL
max_user_connections | число | GLOBAL
max_write_lock_count | число | GLOBAL
myisam_max_extra_sort_file_size | число | GLOBAL | SESSION
myisam_max_sort_file_size | число | GLOBAL | SESSION
myisam_sort_buffer_size | число | GLOBAL | SESSION
net_buffer_length | число | GLOBAL | SESSION
net_read_timeout | число | GLOBAL | SESSION
net_retry_count | число | GLOBAL | SESSION
net_write_timeout | число | GLOBAL | SESSION
query_cache_limit | число | GLOBAL
query_cache_size | число | GLOBAL
query_cache_type | enum | GLOBAL
read_buffer_size | число | GLOBAL | SESSION
read_rnd_buffer_size | число | GLOBAL | SESSION
rpl_recovery_rank | число | GLOBAL
safe_show_database | булевое | GLOBAL
server_id | число | GLOBAL
slave_compressed_protocol | булевое | GLOBAL
slave_net_timeout | число | GLOBAL
slow_launch_time | число | GLOBAL
sort_buffer_size | число | GLOBAL | SESSION
sql_auto_is_null | булевое | SESSION
sql_big_selects | булевое | SESSION
sql_big_tables | булевое | SESSION
sql_buffer_result | булевое | SESSION
sql_log_binlog | булевое | SESSION
sql_log_off | булевое | SESSION
sql_log_update | булевое | SESSION
sql_low_priority_updates | булевое | GLOBAL | SESSION
sql_max_join_size | число | GLOBAL | SESSION
sql_quote_show_create | булевое | SESSION
sql_safe_updates | булевое | SESSION
sql_select_limit | булевое | SESSION
sql_slave_skip_counter | число | GLOBAL
sql_warnings | булевое | SESSION
table_cache | число | GLOBAL
table_type | enum | GLOBAL | SESSION
thread_cache_size | число | GLOBAL
timestamp | булевое | SESSION
tmp_table_size | enum | GLOBAL | SESSION
tx_isolation | enum | GLOBAL | SESSION
version | строка | GLOBAL
wait_timeout | число | GLOBAL | SESSION
warning_count | число | LOCAL
unique_checks | булевое | SESSION

Переменные, помеченные как число могут иметь числовое значение. Переменные, помеченные как булевое могут быть установлены в 0, 1, ON или OFF. Переменные типа enum должны в общем случае быть установлены в одно из возможных значений для переменной, но также могут быть установлены в значение числа, соответствующего значению выбора enum. Первый элемент списка enum - номер 0.

Вот описание некоторых переменных:

Переменная | Описание
identity | Синоним для last_insert_id (совместимость с Sybase)
sql_low_priority_updates | Синоним для low_priority_updates
sql_max_join_size | Синоним для max_join_size
delay_key_write_for_all_tables | Если это и delay_key_write установлены, то тогда все вновь открываемые таблицы MyISAM открываются с задержкой записи ключей.
version | Синоним для VERSION() (совместимость (?) с Sybase)

Описания других переменных можно найти в описании переменных запуска mysql, в описании команды SHOW VARIABLES и в разделе SET. See section 4.1.1 Параметры командной строки mysqld. See section 4.5.6.4 SHOW VARIABLES. See section 5.5.6 Синтаксис команды SET.

6.1.6 Синтаксис комментариев

Сервер MySQL поддерживает следующие способы задания комментариев: с помощью символа `#', за которым следует текст комментария до конца строки; с помощью двух символов --, за которыми идет текст комментария до конца строки; и (для многострочных комментариев) с помощью символов /* (начало комментария) и */ (конец комментария):

mysql> SELECT 1+1;     # Этот комментарий продолжается до конца строки
mysql> SELECT 1+1;     -- Этот комментарий продолжается до конца строки
mysql> SELECT 1 /* Это комментарий в строке */ + 1;
mysql> SELECT 1+
/*
Это многострочный
комментарий
*/
1;

Обратите внимание: при использовании для комментирования способа с -- (двойное тире) требуется наличие хотя бы одного пробела после второго тире!

Хотя сервер ``понимает'' все описанные выше варианты комментирования, существует ряд ограничений на способ синтаксического анализа комментариев вида /* ... */ клиентом mysql:

  • Символы одинарной и двойной кавычек, даже внутри комментария, считаются началом заключенной в кавычки строки. Если внутри комментария не встречается вторая такая же кавычка, синтаксический анализатор не считает комментарий законченным. При работе с mysql в интерактивном режиме эта ошибка проявится в том, что окно запроса изменит свое состояние с mysql> на '> или ">.
  • Точка с запятой используется для обозначения окончания данной SQL-команды и что-либо, следующее за этим символом, указывает на начало следующего выражения.

Эти ограничения относятся как к интерактивному режиму работы mysql (из командной строки), так и к вызову команд из файла, читаемого с ввода командой mysql < some-file.

MySQL поддерживает принятый в ANSI SQL способ комментирования с помощью двойного тире `--' только в том случае, если после второго тире следует пробел (see section 1.9.4.7 Символы `--' как начало комментария).

6.1.7 ``Придирчив'' ли MySQL к зарезервированным словам?

Это общая проблема, возникающая при попытке создать таблицу с именами столбцов, использующих принятые в MySQL названия типов данных или функций, такие как TIMESTAMP или GROUP. Иногда это возможно (например, ABS является разрешенным именем для столбца), но не допускается пробел между именем функции и сразу же следующей за ним скобкой `(' при использовании имен функций, совпадающих с именами столбцов.

Следующие слова являются зарезервированными в MySQL. Большинство из них не допускаются в ANSI SQL92 как имена столбцов и/или таблиц (например GROUP). Некоторые зарезервированы для нужд MySQL и используются (в настоящее время) синтаксическим анализатором yacc:

Word | Word | Word
ADD | ALL | ALTER
ANALYZE | AND | AS
ASC | ASENSITIVE | AUTO_INCREMENT
BDB | BEFORE | BERKELEYDB
BETWEEN | BIGINT | BINARY
BLOB | BOTH | BY
CALL | CASCADE | CASE
CHANGE | CHAR | CHARACTER
CHECK | COLLATE | COLUMN
COLUMNS | CONDITION | CONNECTION
CONSTRAINT | CONTINUE | CREATE
CROSS | CURRENT_DATE | CURRENT_TIME
CURRENT_TIMESTAMP | CURSOR | DATABASE
DATABASES | DAY_HOUR | DAY_MICROSECOND
DAY_MINUTE | DAY_SECOND | DEC
DECIMAL | DECLARE | DEFAULT
DELAYED | DELETE | DESC
DESCRIBE | DETERMINISTIC | DISTINCT
DISTINCTROW | DIV | DOUBLE
DROP | ELSE | ELSEIF
ENCLOSED | ESCAPED | EXISTS
EXIT | EXPLAIN | FALSE
FETCH | FIELDS | FLOAT
FOR | FORCE | FOREIGN
FOUND | FRAC_SECOND | FROM
FULLTEXT | GRANT | GROUP
HAVING | HIGH_PRIORITY | HOUR_MICROSECOND
HOUR_MINUTE | HOUR_SECOND | IF
IGNORE | IN | INDEX
INFILE | INNER | INNODB
INOUT | INSENSITIVE | INSERT
INT | INTEGER | INTERVAL
INTO | IO_THREAD | IS
ITERATE | JOIN | KEY
KEYS | KILL | LEADING
LEAVE | LEFT | LIKE
LIMIT | LINES | LOAD
LOCALTIME | LOCALTIMESTAMP | LOCK
LONG | LONGBLOB | LONGTEXT
LOOP | LOW_PRIORITY | MASTER_SERVER_ID
MATCH | MEDIUMBLOB | MEDIUMINT
MEDIUMTEXT | MIDDLEINT | MINUTE_MICROSECOND
MINUTE_SECOND | MOD | NATURAL
NOT | NO_WRITE_TO_BINLOG | NULL
NUMERIC | ON | OPTIMIZE
OPTION | OPTIONALLY | OR
ORDER | OUT | OUTER
OUTFILE | PRECISION | PRIMARY
PRIVILEGES | PROCEDURE | PURGE
READ | REAL | REFERENCES
REGEXP | RENAME | REPEAT
REPLACE | REQUIRE | RESTRICT
RETURN | REVOKE | RIGHT
RLIKE | SECOND_MICROSECOND | SELECT
SENSITIVE | SEPARATOR | SET
SHOW | SMALLINT | SOME
SONAME | SPATIAL | SPECIFIC
SQL | SQLEXCEPTION | SQLSTATE
SQLWARNING | SQL_BIG_RESULT | SQL_CALC_FOUND_ROWS
SQL_SMALL_RESULT | SQL_TSI_DAY | SQL_TSI_FRAC_SECOND
SQL_TSI_HOUR | SQL_TSI_MINUTE | SQL_TSI_MONTH
SQL_TSI_QUARTER | SQL_TSI_SECOND | SQL_TSI_WEEK
SQL_TSI_YEAR | SSL | STARTING
STRAIGHT_JOIN | STRIPED | TABLE
TABLES | TERMINATED | THEN
TIMESTAMPADD | TIMESTAMPDIFF | TINYBLOB
TINYINT | TINYTEXT | TO
TRAILING | TRUE | UNDO
UNION | UNIQUE | UNLOCK
UNSIGNED | UPDATE | USAGE
USE | USER_RESOURCES | USING
UTC_DATE | UTC_TIME | UTC_TIMESTAMP
VALUES | VARBINARY | VARCHAR
VARCHARACTER | VARYING | WHEN
WHERE | WHILE | WITH
WRITE | XOR | YEAR_MONTH
ZEROFILL |  |

Следующие символы (из приведенной выше таблицы таблицы) не разрешены в ANSI SQL, но допускаются в MySQL как имена столбцов/таблиц. Это объясняется тем, что некоторые из этих имен являются словами естественного языка и уже использованы многими потребителями.

  • ACTION
  • BIT
  • DATE
  • ENUM
  • NO
  • TEXT
  • TIME
  • TIMESTAMP

6.2 Типы данных столбцов

MySQL поддерживает несколько типов столбцов, которые можно разделить на три категории: числовые типы данных, типы данных для хранения даты и времени и символьные (строковые) типы данных. В данном разделе вначале дается обзор всех возможных типов и приводятся требования по хранению для каждого типа столбца, затем свойства типов описываются более подробно по каждой категории. Мы намеренно сделали обзор кратким, поскольку более детальные описания требуют дополнительной информации о конкретных типах столбцов, например, о допустимых форматах представления величин.

Ниже перечислены типы столбцов, поддерживаемые MySQL. В описаниях используются следующие обозначения:

M
Указывает максимальный размер вывода. Максимально допустимый размер вывода составляет 255 символов.
D
Употребляется для типов данных с плавающей точкой и указывает количество разрядов, следующих за десятичной точкой. Максимально возможная величина составляет 30 разрядов, но не может быть больше, чем M-2.

Квадратные скобки (`[' и `]') указывают для типа данных группы необязательных признаков.

Заметьте, что если для столбца указать параметр ZEROFILL, то MySQL будет автоматически добавлять в этот столбец атрибут UNSIGNED.

Предупреждение: следует помнить, что при выполнении вычитания между числовыми величинами, одна из которых относится к типу UNSIGNED, результат будет беззнаковым! See section 6.3.5 Функции приведения типов.

TINYINT[(M)] [UNSIGNED] [ZEROFILL]
Очень малое целое число. Диапазон со знаком от -128 до 127. Диапазон без знака от 0 до 255.
BIT
BOOL
Являются синонимами для TINYINT(1).
SMALLINT[(M)] [UNSIGNED] [ZEROFILL]
Малое целое число. Диапазон со знаком от -32768 до 32767. Диапазон без знака от 0 до 65535.
MEDIUMINT[(M)] [UNSIGNED] [ZEROFILL]
Целое число среднего размера. Диапазон со знаком от -8388608 до 8388607. Диапазон без знака от 0 до 16777215.
INT[(M)] [UNSIGNED] [ZEROFILL]
Целое число нормального размера. Диапазон со знаком от -2147483648 до 2147483647. Диапазон без знака от 0 до 4294967295.
INTEGER[(M)] [UNSIGNED] [ZEROFILL]
Синоним для INT.
BIGINT[(M)] [UNSIGNED] [ZEROFILL]
Большое целое число. Диапазон со знаком от -9223372036854775808 до 9223372036854775807. Диапазон без знака от 0 до 18446744073709551615. Для столбцов типа BIGINT необходимо учитывать некоторые особенности:
  • Все арифметические операции выполняются с использованием значений BIGINT или DOUBLE со знаком, так что не следует использовать беззнаковые целые числа больше чем 9223372036854775807 (63 бита), кроме операций, выполняемых логическими функциями. В противном случае несколько последних разрядов результата могут оказаться ошибочными из-за ошибок округления при преобразовании BIGINT в DOUBLE. MySQL 4.0 может обрабатывать данные типа BIGINT в следующих случаях:
    • Использование целых чисел для хранения больших беззнаковых величин в столбце с типом BIGINT.
    • В случаях MIN(big_int_column) и MAX(big_int_column).
    • При использовании операторов (`+', `-', `*' и т.д.), когда оба операнда являются целыми числами.
  • Точное значение целого числа всегда можно хранить в столбце с типом BIGINT в виде строки. В этом случае MySQL выполнит преобразование строки в число без промежуточного преобразования.
  • Если оба аргумента являются целочисленными величинами, то при выполнении над ними операций `-', `+', и `*' будут использоваться правила BIGINT-арифметики. Это означает, что при умножении двух больших целых чисел (или результатов вычислений функций, возвращающих целые числа) результат операции может оказаться непредсказуемым, если он превосходит значение 9223372036854775807.
FLOAT(точность) [UNSIGNED] [ZEROFILL]
Число с плавающей точкой. Атрибут точности может иметь значение <=24 для числа с плавающей точкой обычной (одинарной) точности и между 25 и 53 - для числа с плавающей точкой удвоенной точности. Эти типы данных сходны с типами FLOAT и DOUBLE, описанными ниже. FLOAT(X) относится к тому же интервалу, что и соответствующие типы FLOAT и DOUBLE, но диапазон значений и количество десятичных знаков не определены. В версии MySQL 3.23 это истинная величина числа с плавающей точкой. В более ранних версиях MySQL тип данных FLOAT(точность) всегда имеет два десятичных знака. Следует отметить, что использование типа данных FLOAT может привести к неожиданным проблемам, так как все вычисления в MySQL выполняются с удвоенной точностью. See section A.5.6 Решение проблем с отсутствием строк, удовлетворяющих условиям поиска. Данный синтаксис обеспечивает совместимость с ODBC.
FLOAT[(M,D)] [UNSIGNED] [ZEROFILL]
Малое число с плавающей точкой обычной точности. Допустимые значения: от -3,402823466E+38 до -1,175494351E-38, 0, и от 1,175494351E-38 до 3,402823466E+38. Если указан атрибут UNSIGNED, отрицательные значения недопустимы. Атрибут M указывает количество выводимых пользователю знаков, а атрибут D - количество разрядов, следующих за десятичной точкой. Обозначение FLOAT без указания аргументов или запись вида FLOAT(X), где X <=24 справедливы для числа с плавающей точкой обычной точности.
DOUBLE[(M,D)] [UNSIGNED] [ZEROFILL]
Число с плавающей точкой удвоенной точности нормального размера. Допустимые значения: от -1,7976931348623157E+308 до -2,2250738585072014E-308, 0, и от 2,2250738585072014E-308 до 1,7976931348623157E+308. Если указан атрибут UNSIGNED, отрицательные значения недопустимы. Атрибут M указывает количество выводимых пользователю знаков, а атрибут D - количество разрядов, следующих за десятичной точкой. Обозначение DOUBLE без указания аргументов или запись вида FLOAT(X), где 25 <= X <= 53 справедливы для числа с плавающей точкой двойной точности.
DOUBLE PRECISION[(M,D)] [UNSIGNED] [ZEROFILL]
REAL[(M,D)] [UNSIGNED] [ZEROFILL]
Данные обозначения являются синонимами для DOUBLE.
DECIMAL[(M[,D])] [UNSIGNED] [ZEROFILL]
``Неупакованное'' число с плавающей точкой. Ведет себя подобно столбцу CHAR, содержащему цифровое значение. Термин ``неупакованное'' означает, что число хранится в виде строки и при этом для каждого десятичного знака используется один символ. Разделительный знак десятичных разрядов, а также знак `-' для отрицательных чисел не учитываются в M (но место для них зарезервировано). Если атрибут D равен 0, величины будут представлены без десятичного знака, т.е. без дробной части. Максимальный интервал значений типа DECIMAL тот же, что и для типа DOUBLE, но действительный интервал для конкретного столбца DECIMAL может быть ограничен выбором значений атрибутов M и D. Если указан атрибут UNSIGNED, отрицательные значения недопустимы. Если атрибут D не указан, его значение по умолчанию равно 0. Если не указан M, его значение по умолчанию равно 10. В более ранних, чем MySQL 3.23, версиях аргумент M должен содержать в себе место для знака числа и десятичного знака.
DEC[(M[,D])] [UNSIGNED] [ZEROFILL]
NUMERIC[(M[,D])] [UNSIGNED] [ZEROFILL]
Данные обозначения являются синонимами для DECIMAL.
DATE
Дата. Поддерживается интервал от '1000-01-01' до '9999-12-31'. MySQL выводит значения DATE в формате 'YYYY-MM-DD', но можно установить значения в столбец DATE, используя как строки, так и числа. See section 6.2.2.2 Типы данных DATETIME, DATE и TIMESTAMP.
DATETIME
Комбинация даты и времени. Поддерживается интервал от '1000-01-01 00:00:00' до '9999-12-31 23:59:59'. MySQL выводит значения DATETIME в формате 'YYYY-MM-DD HH:MM:SS', но можно устанавливать значения в столбце DATETIME, используя как строки, так и числа. See section 6.2.2.2 Типы данных DATETIME, DATE и TIMESTAMP.
TIMESTAMP[(M)]
Временная метка. Интервал от '1970-01-01 00:00:00' до некоторого значения времени в 2037 году. MySQL выводит значения TIMESTAMP в форматах YYYYMMDDHHMMSS, YYMMDDHHMMSS, YYYYMMDD или YYMMDD в зависимости от значений M: 14 (или отсутствующее), 12, 8, или 6; но можно также устанавливать значения в столбце TIMESTAMP, используя как строки, так и числа. Столбец TIMESTAMP полезен для записи даты и времени при выполнении операций INSERT или UPDATE, так как при этом автоматически вносятся значения даты и времени самой последней операции, если эти величины не введены программой. Можно также устанавливать текущее значение даты и времени, задавая значение NULL. See section 6.2.2 Типы данных даты и времени. Аргумент M влияет только на способ вывода столбца TIMESTAMP; для хранения его значений всегда используется 4 байта. Следует учитывать, что столбцы TIMESTAMP(M), где M равно 8 или 14, представляют собой числа, в то время, как столбцы TIMESTAMP(M) с иным значением аргумента M являются строками. Это убеждает, что можно надежно сделать дамп и восстановить таблицу с этими типами столбцов! See section 6.2.2.2 Типы данных DATETIME, DATE и TIMESTAMP.
TIME
Время. Интервал от '-838:59:59' до '838:59:59'. MySQL выводит значения TIME в формате 'HH:MM:SS', но можно устанавливать значения в столбце TIME, используя как строки, так и числа. See section 6.2.2.3 Тип данных TIME.
YEAR[(2|4)]
Год в двухзначном или четырехзначном форматах (по умолчанию формат четырехзначный). Допустимы следующие значения: с 1901 по 2155, 0000 для четырехзначного формата года и 1970-2069 при использовании двухзначного формата (70-69). MySQL выводит значения YEAR в формате YYYY, но можно задавать значения в столбце YEAR, используя как строки, так и числа (тип данных YEAR недоступен в версиях, предшествующих MySQL 3.22). See section 6.2.2.4 Тип данных YEAR.
[NATIONAL] CHAR(M) [BINARY]
Строка фиксированной длины, при хранении всегда дополняется пробелами в конце строки до заданного размера. Диапазон аргумента M составляет от 0 до 255 символов (от 1 до 255 в версиях, предшествующих MySQL 3.23). Концевые пробелы удаляются при выводе значения. Если не задан атрибут чувствительности к регистру BINARY, то величины CHAR сортируются и сравниваются как независимые от регистра в соответствии с установленным по умолчанию алфавитом. Атрибут NATIONAL CHAR (или его эквивалентная краткая форма NCHAR) представляет собой принятый в ANSI SQL способ указания, что в столбце CHAR должен использоваться установленный по умолчанию набор символов (CHARACTER). В MySQL это принято по умолчанию. CHAR является сокращением от CHARACTER. MySQL позволяет создавать столбец типа CHAR(0). В основном это полезно, если необходимо обеспечить совместимость с некоторыми старыми приложениями, которые зависят от наличия столбца, но реально эту величину не используют. Кроме того, такая возможность может очень пригодиться в случае, если необходим столбец, который может содержать только 2 значения, а именно CHAR(0) (т.е. столбец, который не определен как NOT NULL, занимает только один бит и принимает только 2 значения: NULL или ""). See section 6.2.3.1 Типы данных CHAR и VARCHAR.
CHAR
Это синоним для CHAR(1).
[NATIONAL] VARCHAR(M) [BINARY]
Строка переменной длины. Примечание: концевые пробелы удаляются при сохранении значения (в этом заключается отличие от спецификации ANSI SQL). Диапазон аргумента M составляет от 0 до 255 символов (от 1 до 255 в версиях, предшествующих MySQL Version 4.0.2). Если не задан атрибут чувствительности к регистру BINARY, то величины VARCHAR сортируются и сравниваются как независимые от регистра. See section 6.5.3.1 Молчаливые изменения определений столбцов. Термин VARCHAR является сокращением от CHARACTER VARYING. See section 6.2.3.1 Типы данных CHAR и VARCHAR.
TINYBLOB
TINYTEXT
Столбец типа BLOB или TEXT с максимальной длиной 255 (2^8 - 1) символов. See section 6.5.3.1 Молчаливые изменения определений столбцов. See section 6.2.3.2 Типы данных BLOB и TEXT.
BLOB
TEXT
Столбец типа BLOB или TEXT с максимальной длиной 65535 (2^16 - 1) символов. See section 6.5.3.1 Молчаливые изменения определений столбцов. See section 6.2.3.2 Типы данных BLOB и TEXT.
MEDIUMBLOB
MEDIUMTEXT
Столбец типа BLOB или TEXT с максимальной длиной 16777215 (2^24 - 1) символов. See section 6.5.3.1 Молчаливые изменения определений столбцов. See section 6.2.3.2 Типы данных BLOB и TEXT.
LONGBLOB
LONGTEXT
Столбец типа BLOB или TEXT с максимальной длиной 4294967295 (2^32 - 1) символов. See section 6.5.3.1 Молчаливые изменения определений столбцов. Следует учитывать, что в настоящее время протокол передачи данных сервер/клиент и таблицы MyISAM имеют ограничение 16 Мб на передаваемый пакет/строку таблицы, поэтому пока нельзя использовать этот тип данных в его полном диапазоне. See section 6.2.3.2 Типы данных BLOB и TEXT.
ENUM('значение1','значение2',...)
Перечисление. Перечисляемый тип данных. Объект строки может иметь только одно значение, выбранное из заданного списка величин 'значение1', 'значение2', ..., NULL или специальная величина ошибки "". Список ENUM может содержать максимум 65535 различных величин. See section 6.2.3.3 Тип перечисления ENUM.
SET('значение1','значение2',...)
Набор. Объект строки может иметь ноль или более значений, каждое из которых должно быть выбрано из заданного списка величин 'значение1', 'значение2', ... Список SET может содержать максимум 64 элемента. See section 6.2.3.4 Тип множества SET.

6.2.1 Числовые типы данных

MySQL поддерживает все числовые типы данных языка SQL92 по стандартам ANSI/ISO. Они включают в себя типы точных числовых данных (NUMERIC, DECIMAL, INTEGER и SMALLINT) и типы приближенных числовых данных (FLOAT, REAL и DOUBLE PRECISION). Ключевое слово INT является синонимом для INTEGER, а ключевое слово DEC - синонимом для DECIMAL.

Типы данных NUMERIC и DECIMAL реализованы в MySQL как один и тот же тип - это разрешается стандартом SQL92. Они используются для величин, для которых важно сохранить повышенную точность, например для денежных данных. Требуемая точность данных и масштаб могут задаваться (и обычно задаются) при объявлении столбца данных одного из этих типов, например:

    salary DECIMAL(5,2)

В этом примере - 5 (точность) представляет собой общее количество значащих десятичных знаков, с которыми будет храниться данная величина, а цифра 2 (масштаб) задает количество десятичных знаков после запятой. Следовательно, в этом случае интервал величин, которые могут храниться в столбце salary, составляет от -99,99 до 99,99 (в действительности для данного столбца MySQL обеспечивает возможность хранения чисел вплоть до 999,99, поскольку можно не хранить знак для положительных чисел).

В SQL92 по стандарту ANSI/ISO выражение DECIMAL(p) эквивалентно DECIMAL(p,0). Аналогично, выражение DECIMAL также эквивалентно DECIMAL(p,0), при этом предполагается, что величина p определяется конкретной реализацией. В настоящее время MySQL не поддерживает ни одну из рассматриваемых двух различных форм типов данных DECIMAL/NUMERIC. В общем случае это не является серьезной проблемой, так как основные преимущества данных типов состоят в возможности явно управлять как точностью, так и масштабом представления данных.

Величины типов DECIMAL и NUMERIC хранятся как строки, а не как двоичные числа с плавающей точкой, чтобы сохранить точность представления этих величин в десятичном виде. При этом используется по одному символу строки для каждого разряда хранимой величины, для десятичного знака (если масштаб > 0) и для знака `-' (для отрицательных чисел). Если параметр масштаба равен 0, то величины DECIMAL и NUMERIC не содержат десятичного знака или дробной части.

Максимальный интервал величин DECIMAL и NUMERIC тот же, что и для типа DOUBLE, но реальный интервал может быть ограничен выбором значений параметров точности или масштаба для данного столбца с типом данных DECIMAL или NUMERIC. Если конкретному столбцу присваивается значение, имеющее большее количество разрядов после десятичного знака, чем разрешено параметром масштаба, то данное значение округляется до количества разрядов, разрешенного масштаба. Если столбцу с типом DECIMAL или NUMERIC присваивается значение, выходящее за границы интервала, заданного значениями точности и масштаба (или принятого по умолчанию), то MySQL сохранит данную величину со значением соответствующей граничной точки данного интервала.

В качестве расширения стандарта ANSI/ISO SQL92 MySQL также поддерживает числовые типы представления данных TINYINT, MEDIUMINT и BIGINT, кратко описанные в таблице выше. Еще одно расширение указанного стандарта, поддерживаемое MySQL, позволяет при необходимости указывать количество показываемых пользователю символов целого числа в круглых скобках, следующих за базовым ключевым словом данного типа (например INT(4)). Это необязательное указание количества выводимых символов используется для дополнения слева выводимых значений, которые содержат символов меньше, чем заданная ширина столбца, однако не накладывает ограничений ни на диапазон величин, которые могут храниться в столбце, ни на количество разрядов, которые могут выводиться для величин, у которых количество символов превосходит ширину данного столбца. Если дополнительно указан необязательный атрибут ZEROFILL, свободные позиции по умолчанию заполняются нолями. Например, для столбца, объявленного как INT(5) ZEROFILL, величина 4 извлекается как 00004. Следует учитывать, что если в столбце для целых чисел хранится величина с количеством символов, превышающим заданную ширину столбца, могут возникнуть проблемы, когда MySQL будет генерировать временные таблицы для некоторых сложных связей, так как в подобных случаях MySQL полагает, что данные действительно поместились в столбец имеющейся ширины.

Все типы целочисленных данных могут иметь необязательный и не оговоренный в стандарте атрибут UNSIGNED. Беззнаковые величины можно использовать для разрешения записи в столбец только положительных чисел, если необходимо немного увеличить числовой интервал в столбце.

В версии MySQL 4.0.2 числовые типы данных с плавающей точкой также могут иметь параметр UNSIGNED. Как и в целочисленных типах, этот атрибут предотвращает хранение в отмеченном столбце отрицательных величин. Но, в отличие от целочисленных типов, максимальный интервал для величин столбца остается прежним.

Тип FLOAT обычно используется для представления приблизительных числовых типов данных. Стандарт ANSI/ISO SQL92 допускает факультативное указание точности (но не интервала порядка числа) в битах в круглых скобках, следующих за ключевым словом FLOAT. Реализация MySQL также поддерживает это факультативное указание точности. При этом если ключевое слово FLOAT в обозначении типа столбца используется без указания точности, MySQL выделяет 4 байта для хранения величин в этом столбце. Возможно также иное обозначение, с двумя числами в круглых скобках за ключевым словом FLOAT. В этом варианте первое число по-прежнему определяет требования к хранению величины в байтах, а второе число указывает количество разрядов после десятичной запятой, которые будут храниться и показываться (как для типов DECIMAL и NUMERIC). Если в столбец подобного типа попытаться записать число, содержащее больше десятичных знаков после запятой, чем указано для данного столбца, то значение величины при ее хранении в MySQL округляется для устранения излишних разрядов.

Для типов REAL и DOUBLE PRECISION не предусмотрены установки точности. MySQL воспринимает DOUBLE как синоним типа DOUBLE PRECISION - это еще одно расширение стандарта ANSI/ISO SQL92. Но, вопреки требованию стандарта, указывающему, что точность для REAL меньше, чем для DOUBLE PRECISION, в MySQL оба типа реализуются как 8-байтовые числа с плавающей точкой удвоенной точности (если не установлен ``ANSI-режим''). Чтобы обеспечить максимальную совместимость, в коде, требующем хранения приблизительных числовых величин, должны использоваться типы FLOAT или DOUBLE PRECISION без указаний точности или количества десятичных знаков.

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

Например, интервал столбца INT составляет от -2147483648 до 2147483647. Если попытаться записать в столбец INT число -9999999999, то оно будет усечено до нижней конечной точки интервала и вместо записываемого значения в столбце будет храниться величина -2147483648. Аналогично, если попытаться записать число 9999999999, то взамен запишется число 2147483647.

Если для столбца INT указан параметр UNSIGNED, то величина допустимого интервала для столбца останется той же, но его граничные точки сдвинутся к 0 и 4294967295. Если попытаться записать числа -9999999999 и 9999999999, то в столбце окажутся величины 0 и 4294967296.

Для команд ALTER TABLE, LOAD DATA INFILE, UPDATE и многострочной INSERT выводится предупреждение, если могут возникнуть преобразования данных вследствие вышеописанных усечений.

Тип | Байт | От | До
TINYINT | 1 | -128 | 127
SMALLINT | 2 | -32768 | 32767
MEDIUMINT | 3 | -8388608 | 8388607
INT | 4 | -2147483648 | 2147483647
BIGINT | 8 | -9223372036854775808 | 9223372036854775807

6.2.2 Типы данных даты и времени

Существуют следующие типы данных даты и времени: DATETIME, DATE, TIMESTAMP, TIME и YEAR. Каждый из них имеет интервал допустимых значений, а также значение ``ноль'', которое используется, когда пользователь вводит действительно недопустимое значение. Отметим, что MySQL позволяет хранить некоторые не вполне достоверные значения даты, например 1999-11-31. Причина в том, что, по нашему мнению, управление проверкой даты входит в обязанности конкретного приложения, а не SQL-серверов. Для ускорения проверки правильности даты MySQL только проверяет, находится ли месяц в интервале 0-12 и день в интервале 0-31. Данные интервалы начинаются с 0, это сделано для того, чтобы обеспечить для MySQL возможность хранить в столбцах DATE или DATETIME даты, в которых день или месяц равен нулю. Эта возможность особенно полезна для приложений, которые предполагают хранение даты рождения - здесь не всегда известен день или месяц рождения. В таких случаях дата хранится просто в виде 1999-00-00 или 1999-01-00 (при этом не следует рассчитывать на то, что для подобных дат функции DATE_SUB() или DATE_ADD дадут правильные значения).

Ниже приведены некоторые общие соображения, полезные при работе с типами данных даты и времени:

    MySQL извлекает значения для данного типа даты или времени только в стандартном формате, но в то же время пытается интерпретировать разнообразные форматы, которые могут поступать от пользователей (например, когда задается величина, которой следует присвоить тип даты или времени или сравнить со значением, имеющим один из этих типов). Тем не менее, поддерживаются только форматы, описанные в следующих разделах. Предполагается, что пользователь будет вводить допустимые значения величин, так как использование величин в других форматах может дать непредсказуемые результаты.
  • Хотя MySQL пытается интерпретировать значения в нескольких форматах, во всех случаях ожидается, что крайним слева будет раздел значения даты, содержащий год. Даты должны задаваться в порядке год-месяц-день (например, '98-09-04'), а не в порядке месяц-день-год или день-месяц-год, т.е. не так, как мы их обычно записываем (например '09-04-98', '04-09-98').
  • MySQL автоматически преобразует значение, имеющее тип даты или времени, в число, если данная величина используется в числовом контексте, и наоборот.
  • Значение, имеющее тип даты или времени, которое выходит за границы установленного интервала или является недопустимым для этого типа данных (см. начало раздела), преобразуется в значение ``ноль'' для данного типа. (Исключение составляют выходящие за границы установленного интервала величины типа TIME, которые усекаются до соответствующей граничной точки заданного интервала TIME). В следующей таблице представлены форматы значения ``ноль'' для каждого из типов столбцов:
    Тип столбца | Значение ``Ноль''
    DATETIME | '0000-00-00 00:00:00'
    DATE | '0000-00-00'
    TIMESTAMP | 00000000000000 (длина зависит от количества выводимых символов)
    TIME | '00:00:00'
    YEAR | 0000
  • Значения ``ноль'' - особые. Для их хранения или ссылок на них можно явно применять представленные в таблице значения, а можно использовать `0' или `0', что легче в написании.
  • Значения ``ноль'' даты или времени при использовании MyODBC автоматически конвертируются в NULL в версии MyODBC 2.50.12 и выше, так как ODBC не оперирует с подобными величинами.

6.2.2.1 Проблема 2000 года и типы данных

Ядро MySQL само по себе устойчиво к ``проблеме 2000 года'' (see section 1.4.5 Вопросы, связанные с Проблемой-2000), но некоторые представленные в MySQL входные величины могут являться источниками ошибок. Так, любое вводимое значение, содержащее двухразрядное значение года, является неоднозначным, поскольку неизвестно столетие. Подобные величины должны быть переведены в четырехразрядную форму, так как для внутреннего представления года в MySQL используется 4 разряда.

Для типов DATETIME, DATE, TIMESTAMP и YEAR даты с неоднозначным годом интерпретируются в MySQL по следующим правилам:

  • Величина года в интервале 00-69 конвертируется в 2000-2069.
  • Величина года в интервале 70-99 конвертируется в 1970-1999.

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

ORDER BY отсортирует двухразрядные YEAR/DATE/DATETIME типы корректно.

Необходимо также отметить, что некоторые функции, такие как MIN() и MAX() будут преобразовывать TIMESTAMP/DATE в число. Это означает, что столбец с данными типа TIMESTAMP, содержащими год в виде двух разрядов, не будет правильно работать с указанными функциями. Выход из этого положения состоит в преобразовании TIMESTAMP/DATE к четырехразрядному формату или использовании чего-нибудь вроде MIN(DATE_ADD(timestamp,INTERVAL 0 DAYS)).

6.2.2.2 Типы данных DATETIME, DATE и TIMESTAMP

Типы DATETIME, DATE и TIMESTAMP являются родственными типами данных. В данном разделе описаны их свойства, общие черты и различия.

Тип данных DATETIME используется для величин, содержащих информацию как о дате, так и о времени. MySQL извлекает и выводит величины DATETIME в формате 'YYYY-MM-DD HH:MM:SS'. Поддерживается диапазон величин от '1000-01-01 00:00:00' до '9999-12-31 23:59:59'. (''поддерживается'' означает, что хотя величины с более ранними временными значениями, возможно, тоже будут работать, но нет гарантии того, что они будут правильно храниться и отображаться).

Тип DATE используется для величин с информацией только о дате, без части, содержащей время. MySQL извлекает и выводит величины DATE в формате 'YYYY-MM-DD'. Поддерживается диапазон величин от '1000-01-01' до '9999-12-31'.

Тип столбца TIMESTAMP обеспечивает тип представления данных, который можно использовать для автоматической записи текущих даты и времени при выполнении операций INSERT или UPDATE. При наличии нескольких столбцов типа TIMESTAMP только первый из них обновляется автоматически.

Автоматическое обновление первого столбца с типом TIMESTAMP происходит при выполнении любого из следующих условий:

  • Столбец не указан явно в команде INSERT или LOAD DATA INFILE.
  • Столбец не указан явно в команде UPDATE, и при этом изменяется величина в некотором другом столбце (следует отметить, что команда UPDATE, устанавливающая столбец в то же самое значение, которое было до выполнения команды, не вызовет обновления столбца TIMESTAMP, поскольку в целях повышения производительности MySQL игнорирует подобные обновления при установке столбца в его текущее значение).
  • Величина в столбце TIMESTAMP явно установлена в NULL.

Для остальных (кроме первого) столбцов типа TIMESTAMP также можно задать установку в значение текущих даты и времени. Для этого необходимо просто установить столбец в NULL или в NOW().

Любой столбец типа TIMESTAMP (даже первый столбец данного типа) можно установить в значение, отличное от текущих даты и времени. Это делается путем явной установки его в желаемое значение. Данное свойство можно использовать, например, если необходимо установить столбец TIMESTAMP в значение текущих даты и времени при создании строки, а при последующем обновлении этой строки значение столбца не должно изменяться:

  • Пусть MySQL автоматически установит значение столбца с типом TIMESTAMP при создании данной строки. Столбец будет установлен в исходное состояние со значением текущих даты и времени.
  • При выполнении последующих обновлений других столбцов в данной строке необходимо явно установить столбец TIMESTAMP в его текущее значение.

Однако, с другой стороны, для этих целей, возможно, будет проще использовать столбец DATETIME. При создании строки его следует инициализировать функцией NOW() и оставить в покое при последующих обновлениях.

Величины типа TIMESTAMP могут принимать значения от начала 1970 года до некоторого значения в 2037 году с разрешением в одну секунду. Эти величины выводятся в виде числовых значений.

Формат данных, в котором MySQL извлекает и показывает величины TIMESTAMP, зависит от количества показываемых символов. Это проиллюстрировано в приведенной ниже таблице. Полный формат TIMESTAMP составляет 14 десятичных разрядов, но можно создавать столбцы типа TIMESTAMP и с более короткой строкой вывода:

Тип столбца | Формат вывода
TIMESTAMP(14) | YYYYMMDDHHMMSS
TIMESTAMP(12) | YYMMDDHHMMSS
TIMESTAMP(10) | YYMMDDHHMM
TIMESTAMP(8) | YYYYMMDD
TIMESTAMP(6) | YYMMDD
TIMESTAMP(4) | YYMM
TIMESTAMP(2) | YY

Независимо от размера выводимого значения размер данных, хранящихся в столбцах типа TIMESTAMP, всегда один и тот же. Чаще всего используется формат вывода с 6, 8, 12 или 14 десятичными знаками. При создании таблицы можно указать произвольный размер выводимых значений, однако если этот размер задать равным 0 или превышающим 14, то будет использоваться значение 14. Нечетные значения размеров в интервале от 1 до 13 будут приведены к ближайшему большему четному числу.

Величины DATETIME, DATE и TIMESTAMP могут быть заданы любым стандартным набором форматов:

  • Как строка в формате 'YYYY-MM-DD HH:MM:SS' или в формате 'YY-MM-DD HH:MM:SS'. Допускается ``облегченный'' синтаксис - можно использовать любой знак пунктуации в качестве разделительного между частями разделов даты или времени. Например, величины '98-12-31 11:30:45', '98.12.31 11+30+45', '98/12/31 11*30*45' и '98@12@31 11^30^45' являются эквивалентными.
  • Как строка в формате 'YYYY-MM-DD' или в формате 'YY-MM-DD'. Здесь также допустим ``облегченный'' синтаксис. Например, величины '98-12-31', '98.12.31', '98/12/31' и '98@12@31' являются эквивалентными.
  • Как строка без разделительных знаков в формате 'YYYYMMDDHHMMSS' или в формате 'YYMMDDHHMMSS', при условии, что строка понимается как дата. Например, величины '19970523091528' и '970523091528' можно интерпретировать как '1997-05-23 09:15:28', но величина '971122129015' является недопустимой (значение раздела минут является абсурдным) и преобразуется в '0000-00-00 00:00:00'.
  • Как строка без разделительных знаков в формате 'YYYYMMDD' или в формате 'YYMMDD', при условии, что строка интерпретируется как дата. Например, величины '19970523' и '970523' можно интерпретировать как '1997-05-23', но величина '971332' является недопустимой (значения разделов месяца и дня не имеют смысла) и преобразуется в '0000-00-00'.
  • Как число в формате YYYYMMDDHHMMSS или в формате YYMMDDHHMMSS, при условии, что число интерпретируется как дата. Например, величины 19830905132800 и 830905132800 интерпретируются как '1983-09-05 13:28:00'.
  • Как число в формате YYYYMMDD или в формате YYMMDD, при условии, что число интерпретируется как дата. Например, величины 19830905 и 830905 интерпретируются как '1983-09-05'.
  • Как результат выполнения функции, возвращающей величину, приемлемую в контекстах типов данных DATETIME, DATE или TIMESTAMP (например, функции NOW() или CURRENT_DATE().

Недопустимые значения величин DATETIME, DATE или TIMESTAMP преобразуются в значение ``ноль'' соответствующего типа величин ('0000-00-00 00:00:00', '0000-00-00', или 00000000000000).

Для величин, представленных как строки, содержащие разделительные знаки между частями даты, нет необходимости указывать два разряда для значений месяца или дня, меньших, чем 10. Так, величина '1979-6-9' эквивалентна величине '1979-06-09'. Аналогично, для величин, представленных как строки, содержащие разделительные знаки внутри обозначения времени, нет необходимости указывать два разряда для значений часов, минут или секунд, меньших, чем 10. Так,

Величины, определенные как числа, должны иметь 6, 8, 12, или 14 десятичных разрядов. Предполагается, что число, имеющее 8 или 14 разрядов, представлено в форматах YYYYMMDD или YYYYMMDDHHMMSS соответственно, причем год указан в первых четырех разрядах. Если же длина числа 6 или 12 разрядов, то предполагаются соответственно форматы YYMMDD или YYMMDDHHMMSS, где год указан в первых двух разрядах. Числа, длина которых не соответствует ни одному из описанных вариантов, интерпретируются как дополненные спереди нулями до ближайшей вышеуказанной длины.

Величины, представленные строками без разделительных знаков, интерпретируются с учетом их длины согласно приведенным далее правилам. Если длина строки равна 8 или 14 символам, то предполагается, что год задан первыми четырьмя символами. В противном случае предполагается, что год задан двумя первыми символами. Строка интерпретируется слева направо, при этом определяются значения для года, месяца, дня, часов, минут и секунд для всех представленных в строке разделов. Это означает, что строка с длиной меньше, чем 6 символов, не может быть использована. Например, если задать строку вида '9903', полагая, что это будет означать март 1999 года, то MySQL внесет в таблицу ``нулевую'' дату. Год и месяц в данной записи равны 99 и 03 соответственно, но раздел, представляющий день, пропущен (значение равно нулю), поэтому в целом данная величина не является достоверным значением даты.

При хранении допустимых величин в столбцах типа TIMESTAMP используется полная точность, указанная при их задании, независимо от количества выводимых символов. Это свойство имеет несколько следствий:

  • Необходимо всегда указывать год, месяц и день даже для типов TIMESTAMP(4) или TIMESTAMP(2). В противном случае задаваемая величина не будет допустимым значением даты и будет храниться как 0.
  • При увеличении ширины узкого столбца TIMESTAMP путем использования команды ALTER TABLE будет выводиться ранее ``скрытая'' информация.
  • И аналогично, при сужении столбца TIMESTAMP хранимая информация не будет потеряна, если не принимать во внимание, что при выводе информации будет выдаваться меньше.
  • Хотя величины TIMESTAMP хранятся с полной точностью, непосредственно может работать с этим исходным хранимым значением величины только функция UNIX_TIMESTAMP(). Остальные функции оперируют форматированными значениями извлеченной величины. Это означает, что нельзя использовать такие функции, как HOUR() или SECOND(), пока соответствующая часть величины TIMESTAMP не будет включена в ее форматированное значение. Например, раздел HH столбца TIMESTAMP не будет выводиться, пока количество выводимых символов не станет по меньшей мере равным 10, так что попытки использовать HOUR() для более коротких величин TIMESTAMP приведут к бессмысленным результатам.

Величины одного типа даты можно в ряде случаев присвоить объекту другого типа даты. Однако при этом возможны некоторое изменение величины или потеря информации:

  • Если присвоить значение типа DATE объекту DATETIME или TIMESTAMP, то в результирующей величине ``временная'' часть будет установлена в '00:00:00', так как величина DATE не содержит информации о времени.
  • Если присвоить значение типа DATE, DATETIME или TIMESTAMP объекту DATE, то ``временная'' часть в результирующей величине будет удалена, так как тип DATE не включает информацию о времени.
  • Несмотря на то что все величины DATETIME, DATE и TIMESTAMP могут быть указаны с использованием одного и того же набора форматов, следует помнить, что указанные типы имеют разные интервалы допустимых значений. Например, величины типа TIMESTAMP не могут иметь значения даты более ранние, чем относящиеся к 1970 году или более поздние, чем относящиеся к 2037 году. Это означает, что такая дата, как '1968-01-01', будучи разрешенной для величины типа DATETIME или DATE, недопустима для величины типа TIMESTAMP и будет преобразована в 0 при присвоении этому объекту.

Задавая величины даты, следует иметь в виду некоторые ``подводные камни'':

  • Упрощенный формат, который допускается для величин, заданных строками, может ввести в заблуждение. Например, такая величина, как '10:11:12', благодаря разделителю `:' могла бы оказаться величиной времени, но, используемая в контексте даты, она будет интерпретирована как год '2010-11-12'. В то же время величина '10:45:15' будет преобразована в '0000-00-00', так как для месяца значение '45' недопустимо.
  • Сервер MySQL выполняет только первичную проверку истинности даты: дни 00-31, месяцы 00-12, года 1000-9999. Любая дата вне этого диапазона преобразуется в 0000-00-00. Следует отметить, что, тем не менее, при этом не запрещается хранить неверные даты, такие как 2002-04-31. Это позволяет веб-приложениям сохранять данные форм без дополнительной проверки. Чтобы убедиться в достоверности даты, выполняется проверка в самом приложении.
  • Величины года, представленные двумя разрядами, допускают неоднозначное толкование, так как неизвестно столетие. MySQL интерпретирует двухразрядные величины года по следующим правилам:
    • Величины года в интервале 00-69 преобразуются в 2000-2069.
    • Величины года в интервале 70-99 преобразуются в 1970-1999.

6.2.2.3 Тип данных TIME

MySQL извлекает и выводит величины типа TIME в формате 'HH:MM:SS' (или в формате 'HHH:MM:SS' для больших значений часов). Величины TIME могут изменяться в пределах от '-838:59:59' до '838:59:59'. Причина того, что ``часовая'' часть величины может быть настолько большой, заключается в том, что тип TIME может использоваться не только для представления времени дня (которое должно быть меньше 24 часов), но также для представления общего истекшего времени или временного интервала между двумя событиями (который может быть значительно больше 24 часов или даже отрицательным).

Величины TIME могут быть заданы в различных форматах:

    Как строка в формате 'D HH:MM:SS.дробная часть' (следует учитывать, что MySQL пока не обеспечивает хранения дробной части величины в столбце рассматриваемого типа). Можно также использовать одно из следующих ``облегченных'' представлений: HH:MM:SS.дробная часть, HH:MM:SS, HH:MM, D HH:MM:SS, D HH:MM, D HH или SS. Здесь D - это дни из интервала значений 0-33.
  • Как строка без разделителей в формате 'HHMMSS', при условии, что строка интерпретируется как дата. Например, величина '101112' понимается как '10:11:12', но величина '109712' будет недопустимой (значение раздела минут является абсурдным) и преобразуется в '00:00:00'.
  • Как число в формате HHMMSS, при условии, что строка интерпретируется как дата. Например, величина 101112 понимается как '10:11:12'. MySQL понимает и следующие альтернативные форматы: SS, MMSS, HHMMSS, HHMMSS.дробная часть. При этом следует учитывать, что хранения дробной части MySQL пока не обеспечивает.
  • Как результат выполнения функции, возвращающей величину, приемлемую в контексте типа данных типа TIME (например, такой функции, как CURRENT_TIME).

Для величин типа TIME, представленных как строки, содержащие разделительные знаки между частями значения времени, нет необходимости указывать два разряда для значений часов, минут или секунд, меньших 10. Так, величина '8:3:2' эквивалентна величине '08:03:02'.

Будьте внимательны в отношении использования ``укороченных'' величин TIME в столбце типа TIME. MySQL интерпретирует выражения без разделительных двоеточий исходя из предположения, что крайние справа разряды представляют секунды (MySQL интерпретирует величины TIME как общее истекшее время, а не как время дня). Например, можно подразумевать, что величины '1112' и 1112 обозначают '11:12:00' (11 часов и 12 минут дня по показаниям часов), но MySQL понимает их как '00:11:12' (11 минут, 12 секунд). Подобно этому, '12' и 12 интерпретируются как '00:00:12'. Величины TIME с разделительными двоеточиями, наоборот, всегда трактуются как время дня. Т.е. выражение '11:12' будет пониматься как '11:12:00', а не '00:11:12'.

Величины, лежащие вне разрешенного интервала TIME, но во всем остальном представляющие собой допустимые значения, усекаются до соответствующей граничной точки данного интервала. Например, величины '-850:00:00' и '850:00:00' преобразуются соответственно в '-838:59:59' и '838:59:59'.

Недопустимые значения величин TIME преобразуются в значение '00:00:00'. Отметим, что поскольку выражение '00:00:00' само по себе представляет разрешенное значение величины TIME, то по хранящейся в таблице величине '00:00:00' невозможно определить, была ли эта величина изначально задана как '00:00:00' или является преобразованным значением недопустимой величины.

6.2.2.4 Тип данных YEAR

Тип YEAR - это однобайтный тип данных для представления значений года.

MySQL извлекает и выводит величины YEAR в формате YYYY. Диапазон возможных значений - от 1901 до 2155.

Величины типа YEAR могут быть заданы в различных форматах:

  • Как четырехзначная строка в интервале значений от '1901' до '2155'.
  • Как четырехзначное число в интервале значений от 1901 до 2155.
  • Как двухзначная строка в интервале значений от '00' до '99'. Величины в интервалах от '00' до '69' и от '70' до '99' при этом преобразуются в величины YEAR в интервалах от 2000 до 2069 и от 1970 до 1999 соответственно.
  • Как двухзначное число в интервале значений от 1 до 99. Величины в интервалах от 1 до 69 и от 70 до 99 при этом преобразуются в величины YEAR в интервалах от 2001 до 2069 и от 1970 до 1999 соответственно. Необходимо принять во внимание, что интервалы для двухзначных чисел и двухзначных строк несколько различаются, так как нельзя указать ``ноль'' непосредственно как число и интерпретировать его как 2000. Необходимо задать его как строку '0' или '00', или же оно будет интерпретировано как 0000.
  • Как результат выполнения функции, возвращающей величину, приемлемую в контексте типа данных YEAR (такой как NOW()).

Недопустимые величины YEAR преобразуются в 0000.

6.2.3 Символьные типы данных

Существуют следующие символьные типы данных: CHAR, VARCHAR, BLOB, TEXT, ENUM и SET. В данном разделе дается описание их работы, требований к их хранению и использования их в запросах.

Тип | Макс.размер | Байт
TINYTEXT или TINYBLOB | 2^8-1 | 255
TEXT или BLOB | 2^16-1 (64K-1) | 65535
MEDIUMTEXT или MEDIUMBLOB | 2^24-1 (16M-1) | 16777215
LONGBLOB | 2^32-1 (4G-1) | 4294967295

6.2.3.1 Типы данных CHAR и VARCHAR

Типы данных CHAR и VARCHAR очень схожи между собой, но различаются по способам их хранения и извлечения.

В столбце типа CHAR длина поля постоянна и задается при создании таблицы. Эта длина может принимать любое значение между 1 и 255 (что же касается версии MySQL 3.23, то в ней длина столбца CHAR может быть от 0 до 255). Величины типа CHAR при хранении дополняются справа пробелами до заданной длины. Эти концевые пробелы удаляются при извлечении хранимых величин.

Величины в столбцах VARCHAR представляют собой строки переменной длины. Так же как и для столбцов CHAR, можно задать столбец VARCHAR любой длины между 1 и 255. Однако, в противоположность CHAR, при хранении величин типа VARCHAR используется только то количество символов, которое необходимо, плюс один байт для записи длины. Хранимые величины пробелами не дополняются, наоборот, концевые пробелы при хранении удаляются (описанный процесс удаления пробелов отличается от предусмотренного спецификацией ANSI SQL).

Если задаваемая в столбце CHAR или VARCHAR величина превосходит максимально допустимую длину столбца, то эта величина соответствующим образом усекается.

Различие между этими двумя типами столбцов в представлении результата хранения величин с разной длиной строки в столбцах CHAR(4) и VARCHAR(4) проиллюстрировано следующей таблицей:

Величина | CHAR(4) | Требуемая память | VARCHAR(4) | Требуемая память
'' | ' ' | 4 байта | '' | 1 байт
'ab' | 'ab ' | 4 байта | 'ab' | 3 байта
'abcd' | 'abcd' | 4 байта | 'abcd' | 5 байтов
'abcdefgh' | 'abcd' | 4 байта | 'abcd' | 5 байтов

Извлеченные из столбцов CHAR(4) и VARCHAR(4) величины в каждом случае будут одними и теми же, поскольку при извлечении концевые пробелы из столбца CHAR удаляются.

Если при создании таблицы не был задан атрибут BINARY для столбцов, то величины в столбцах типа CHAR и VARCHAR сортируются и сравниваются без учета регистра. При задании атрибута BINARY величины в столбце сортируются и сравниваются с учетом регистра в соответствии с порядком таблицы ASCII на том компьютере, где работает сервер MySQL. Атрибут BINARY не влияет на процессы хранения или извлечения данных из столбца.

Атрибут BINARY является ``прилипчивым''. Это значит, что, если в каком-либо выражении использовать столбец, помеченный как BINARY, то сравнение всего выражения будет выполняться как сравнение величины типа BINARY.

MySQL может без предупреждения изменить тип столбца CHAR или VARCHAR во время создания таблицы. See section 6.5.3.1 Молчаливые изменения определений столбцов.

6.2.3.2 Типы данных BLOB и TEXT

Тип данных BLOB представляет собой двоичный объект большого размера, который может содержать переменное количество данных. Существуют 4 модификации этого типа - TINYBLOB, BLOB, MEDIUMBLOB и LONGBLOB, отличающиеся только максимальной длиной хранимых величин. See section 6.2.6 Требования к памяти для различных типов столбцов.

Тип данных TEXT также имеет 4 модификации - TINYTEXT, TEXT, MEDIUMTEXT и LONGTEXT, соответствующие упомянутым четырем типам BLOB и имеющие те же максимальную длину и требования к объему памяти. Единственное различие между типами BLOB и TEXT состоит в том, что сортировка и сравнение данных выполняются с учетом регистра для величин BLOB и без учета регистра для величин TEXT. Другими словами, TEXT - это независимый от регистра BLOB.

Если размер задаваемого в столбце BLOB или TEXT значения превосходит максимально допустимую длину столбца, то это значение соответствующим образом усекается.

В большинстве случаев столбец TEXT может рассматриваться как столбец VARCHAR неограниченного размера. И, аналогично, BLOB - как столбец типа VARCHAR BINARY. Различия при этом следующие:

  • Столбцы типов BLOB и TEXT могут индексироваться в версии MySQL 3.23.2 и более новых. Более старые версии MySQL не поддерживают индексацию этих столбцов.
  • В столбцах типов BLOB и TEXT не производится удаление концевых символов, как это делается для столбцов типа VARCHAR.
  • Для столбцов BLOB и TEXT не может быть задан атрибут DEFAULT - значения величин по умолчанию.

В MyODBC величины типа BLOB определяются как LONGVARBINARY и величины типа TEXT - как LONGVARCHAR.

Так как величины типов BLOB и TEXT могут быть чрезмерно большими, при их использовании целесообразно предусмотреть некоторые ограничения:

    Чтобы обеспечить возможность использования команд GROUP BY или ORDER BY в столбце типа BLOB или TEXT, необходимо преобразовать значение столбца в объект с фиксированной длиной. Обычно это делается с помощью функции SUBSTRING. Например:
    mysql> SELECT comment FROM tbl_name,SUBSTRING(comment,20) AS substr
    -> ORDER BY substr;
    Если этого не сделать, то операция сортировки в столбце будет выполнена только для первых байтов, количество которых задается параметром max_sort_length. Значение по умолчанию величины max_sort_length равно 1024; это значение можно изменить, используя параметр -O сервера mysqld при его запуске. Группировка выражения, включающего в себя величины BLOB или TEXT, возможна при указании позиции столбца или использовании псевдонима:
    mysql> SELECT id,SUBSTRING(blob_col,1,100) FROM tbl_name GROUP BY 2;
mysql> SELECT id,SUBSTRING(blob_col,1,100) AS b FROM tbl_name GROUP BY b;
  • Максимальный размер объекта типа BLOB или TEXT определяется его типом, но наибольшее значение, которое фактически может быть передано между клиентом и сервером, ограничено величиной доступной памяти и размером буферов связи. Можно изменить размер буфера блока передачи, но сделать это необходимо как на стороне сервера, так и на стороне клиента. See section 5.5.2 Настройка параметров сервера.

Следует учитывать, что внутренним представлением любой величины типа BLOB или TEXT является отдельно размещенный объект - в противоположность всем остальным типам столбцов, для которых память выделяется единовременно для столбца при открытии таблицы.

6.2.3.3 Тип перечисления ENUM

ENUM (перечисление) - это столбец, который может принимать значение из списка допустимых значений, явно перечисленных в спецификации столбца в момент создания таблицы.

Этим значением также может быть пустая строка ("") или NULL при определенных условиях:

  • Если делается всавка некорректного значения в столбец ENUM (т.е. вставка строки, не перечисленной в списке допустимых), то вставляется пустая строка, что является указанием на ошибочное значение. Эта строка отличается от "обычной" пустой строки по тому признаку, что она имеет цифровое значение, равное 0. Об этом чуть ниже.
  • Если ENUM определяется как NULL, то тогда NULL тоже является допустимым значением столбца и значение по умолчанию - NULL. Если ENUM определяется как NOT NULL, то значением по умолчанию является первый элемент из списка допустимых значений.

Каждая величина из допустимы имеет индекс:

  • Значение из списка допустимых величин, определенных при создании таблицы нумеруются, начиная с 1.
  • Индекс пустой ошибочной строки - 0. Это означает что вы можете использовать следующий SELECT для того, чтобы найти записи, в которые были вставлены некорректные значения ENUM:
    mysql> SELECT * FROM tbl_name WHERE enum_col=0;
  • Индекс значения NULL - NULL.

Например, столбец, определенный как ENUM("один", "два", "три") может иметь любую из перечисленных величин. Индекс каждой величины также известен:

Величина | Индекс
NULL | NULL
"" | 0
"один" | 1
"два" | 2
"три" | 3

Перечисление может иметь максимум 65535 элементов.

Начиная с 3.23.51, оконечные пробелы автоматически удаляются из величин этого столбца в момент создания таблицы.

Регистр не играет роли, когда вы делаете вставку в столбец ENUM. Однако регистр значений, получаемых из этого столбца, совпадает с регистром в написании соответствующего значения, заданного во время создания таблицы.

Если вы делаете выборку столбца ENUM в числовом контексте, возвращается индекс значения. Например, вы можете получить численное значение ENUM таким образом:

mysql> SELECT enum_col+0 FROM tbl_name;

Если вы вставляете число в столбец ENUM, это число воспринимается как индекс, и в таблицу записывается соответствующее этому индексу значение перечисления. (Однако, это не будет работать с LOAD DATA, который воспринимает все входящие данные как строки.) Не рекомендуется сохранять числа в перечислении, т.к. это может привести к излишней путаннице.

Значения перечисления сортируются в соответствии с порядком, в котором допустимые значения были заданы при создании таблицы. (Другими словами, значения ENUM сортируются в соответствии с ихними индексами.) Например, "a" в отсортированном выводе будет присутствовать раньше чем "b" для ENUM("a", "b"), но "b" появится раньше "a" для ENUM("b","a"). Пустые строки возвращаются перед непустыми строками, и NULL-значения будут выведены в самую первую очередь.

Для предотвращения неожиданностей, указывайте список ENUM в алфавитном порядке. Вы также можете использовать GROUP BY CONCAT(col) чтобы удостовериться, что столбец отсортирован в алфавитном порядке, а не по индексу.

Если вам нужно получить список возможных значения для столбца ENUM, вы должны вызвать SHOW COLUMNS FROM имя_таблицы LIKE имя_столбца_enum и проанализировать определение ENUM во втором столбце.

6.2.3.4 Тип множества SET

SET - это строковый тип, который может принимать ноль или более значений, каждое из которых должно быть выбрано из списка допустимых значений, определенных при создании таблицы. Элементы множества SET разделяются запятыми. Как следствие, сами элементы множества не могут содержать запятых.

Например, столбец, определенный как SET("один", "два") NOT NULL может принимать такие значения:

""
"один"
"два"
"один,два"

Множество SET может иметь максимум 64 различных элемента.

Начиная с 3.23.51, оконечные пробелы удаляются из значений множества SET в момент создания таблицы.

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

mysql> SELECT set_col+0 FROM tbl_name;

Если делается вставка в столбец SET, биты, установленные в двоичном представлении числа определяют элементы множества. Допустим, столбец определен как SET("a","b","c","d"). Тогда элементы имеют такие биты установленными:

SET элемент | числовое значение | двоичное значение
a | 1 | 0001
b | 2 | 0010
c | 4 | 0100
d | 8 | 1000

Если вы вставляет значение 9 в этот столбец, это соответствует 1001 в двоичном представлении, так что первый ("a") и четвертый ("d") элементы множества выбираются, что в результате дает "a,d".

Для значения, содержащего более чем один элемент множестве, не играет никакой роли, в каком порядке эти элементы перечисляются в момент вставки значения. Также не играет роли, как много раз то или иное значение перечислено. Когда позже это значение выбирается, каждый элемент будет присутствовать только единожды, и элементы будут перечислены в том порядке, в котором они перечисляются в определении таблицы. Например, если столбец определен как SET("a","b","c","d"), тогда "a,d", "d,a", и "d,a,a,d,d" будут представлены как "a,d".

Если вы вставляете в столбец SET некорректую величины, это значение будет проигнорировано.

SET-значения сортируются в соответствии с числовым представлением. NULL-значения идут в первую очередь.

Обычно, следует выполнять SELECT для SET-столбца, используя оператор LIKE или функцию FIND_IN_SET():

mysql> SELECT * FROM tbl_name WHERE set_col LIKE '%value%';
mysql> SELECT * FROM tbl_name WHERE FIND_IN_SET('value',set_col)>0;

Но и такая форма также работает:

mysql> SELECT * FROM tbl_name WHERE set_col = 'val1,val2';
mysql> SELECT * FROM tbl_name WHERE set_col & 1;

Первый оператор в каждом примере делает выборку точного значения. Второй оператор делает выборку значений, содержащих первого элемента множества.

Если вам нужно получить все возможные значения для столбца SET, вам следует вызвать SHOW COLUMNS FROM table_name LIKE set_column_name и проанализировать SET-определение во втором столбце.

6.2.4 Выбор правильного типа данных в столбце

Для того чтобы память использовалась наиболее эффективно, всегда следует стараться применять тип данных, обеспечивающий максимальную точность. Например, для величин в диапазоне между 1 и 99999 в целочисленном столбце наилучшим типом будет MEDIUMINT UNSIGNED.

Часто приходится сталкиваться с такой проблемой, как точное представление денежных величин. В MySQL для представления таких величин необходимо использовать тип данных DECIMAL. Поскольку данные этого типа хранятся в виде строки, потерь в точности не происходит. А в случаях, когда точность не имеет слишком большого значения, вполне подойдет и тип данных DOUBLE.

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

6.2.5 Использование типов столбцов из других баз данных

Чтобы облегчить использование SQL-кода, написанного для баз данных других поставщиков, в MySQL установлено соответствие типов столбцов, как показано в следующей таблице. Это соответствие упрощает применение описаний таблиц баз данных других поставщиков в MySQL:

Тип иного поставщика | Тип MySQL
BINARY(NUM) | CHAR(NUM) BINARY
CHAR VARYING(NUM) | VARCHAR(NUM)
FLOAT4 | FLOAT
FLOAT8 | DOUBLE
INT1 | TINYINT
INT2 | SMALLINT
INT3 | MEDIUMINT
INT4 | INT
INT8 | BIGINT
LONG VARBINARY | MEDIUMBLOB
LONG VARCHAR | MEDIUMTEXT
MIDDLEINT | MEDIUMINT
VARBINARY(NUM) | VARCHAR(NUM) BINARY

Соотнесение типов столбцов происходит во время создания таблицы. При создании таблицы с типами столбцов, которые используются другими поставщиками, после запуска команды DESCRIBE имя_таблицы выдается структура данной таблицы с применением принятых в MySQL эквивалентных типов.

6.2.6 Требования к памяти для различных типов столбцов

Требования к объему памяти для столбцов каждого типа, поддерживаемого MySQL, перечислены ниже по категориям.

Требования к памяти для числовых типов

Тип столбца | Требуемая память
TINYINT | 1 byte
SMALLINT | 2 байта
MEDIUMINT | 3 байта
INT | 4 байта
INTEGER | 4 байта
BIGINT | 8 байтов
FLOAT(X) | 4, если X <= 24 или 8, если 25 <= X <= 53
FLOAT | 4 байта
DOUBLE | 8 байтов
DOUBLE PRECISION | 8 байтов
REAL | 8 байтов
DECIMAL(M,D) | M+2 байт, если D > 0, M+1 байт, если D = 0 (D+2, если M < D)
NUMERIC(M,D) | M+2 байт, если D > 0, M+1 байт, если D = 0 (D+2, если M < D)

Требования к памяти для типов даты и времени

Тип столбца | Требуемая память
DATE | 3 байта
DATETIME | 8 байтов
TIMESTAMP | 4 байта
TIME | 3 байта
YEAR | 1 байт

Требования к памяти для символьных типов

Тип столбца | Требуемая память
CHAR(M) | M байт, 1 <= M <= 255
VARCHAR(M) | L+1 байт, где L <= M и 1 <= M <= 255
TINYBLOB, TINYTEXT | L+1 байт, где L < 2^8
BLOB, TEXT | L+2 байт, где L < 2^16
MEDIUMBLOB, MEDIUMTEXT | L+3 байт, где L < 2^24
LONGBLOB, LONGTEXT | L+4 байт, где L < 2^32
ENUM('value1','value2',...) | 1 или 2 байт, в зависимости от количества перечисляемых величин (максимум 65535)
SET('value1','value2',...) | 1, 2, 3, 4 или 8 байт, в зависимости от количества элементов множества (максимум 64)

VARCHAR, BLOB и TEXT являются типами данных с переменной длиной строки, для таких типов требования к памяти в общем случае определяются реальным размером величин в столбце (представлен символом L в приведенной выше таблице), а не максимально возможным для данного типа размером. Например, столбец VARCHAR(10) может содержать строку с максимальной длиной 10 символов. Реально требуемый объем памяти равен длине строки (L) плюс 1 байт для записи длины строки. Для строки 'abcd' L равно 4 и требуемый объем памяти равен 5 байтов.

В случае типов данных BLOB и TEXT требуется 1, 2, 3 или 4 байта для записи длины значения данного столбца в зависимости от максимально возможной длины для данного типа. See section 6.2.3.2 Типы данных BLOB и TEXT.

Если таблица включает в себя столбец какого-либо типа с переменной длиной строки, то формат записи также будет переменной длины. Следует учитывать, что при создании таблицы MySQL может при определенных условиях преобразовать тип столбца с переменной длиной в тип с постоянной длиной строки или наоборот. See section 6.5.3.1 Молчаливые изменения определений столбцов.

Размер объекта ENUM определяется количеством различных перечисляемых величин. Один байт используется для перечисления до 255 возможных величин. Используя два байта, можно перечислить до 65535 величин. See section 6.2.3.3 Тип перечисления ENUM.

Размер объекта SET определяется количеством различных элементов множества. Если это количество равно N, то размер объекта вычисляется по формуле (N+7)/8 и полученное число округляется до 1, 2, 3, 4 или 8 байтов. Множество SET может иметь максимум 64 элемента. See section 6.2.3.4 Тип множества SET.

Максимальный размер записи в MyISAM составляет 65534 байтов. Каждый BLOB или TEXT-столбец засчитывается здесь как 5-9 байтов.

6.3 Функции, используемые в операторах SELECT и WHERE

В команде SQL выражение SELECT или определение WHERE могут включать в себя любое выражение, в котором используются описанные ниже функции.

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

Примечание: между именем функции и следующими за ним скобками не должно быть пробелов. Это поможет синтаксическому анализатору MySQL отличать вызовы функций от ссылок на таблицы или столбцы, имена которых случайно окажутся теми же, что и у функций. Однако допускаются пробелы до или после аргументов.

Если нужно, чтобы в MySQL допускались пробелы после имени функции, следует запустить mysqld с параметром --ansi или использовать CLIENT_IGNORE_SPACE в mysql_connect(), но в этом случае все имена функций станут зарезервированными словами. See section 1.9.2 Запуск MySQL в режиме ANSI.

В целях упрощения в данной документации результат выполнения программы mysql в примерах представлен в сокращенной форме. Таким образом вывод:

mysql> SELECT MOD(29,9);
1 rows in set (0.00 sec)

+-----------+
| mod(29,9) |
+-----------+
|         2 |
+-----------+

будет представлен следующим образом:

mysql> SELECT MOD(29,9);
        -> 2

6.3.1 Операторы и функции общего назначения

6.3.1.1 Круглые скобки

( ... )

Круглые скобки используются для задания порядка вычислений в выражении. Например:

mysql> SELECT 1+2*3;
        -> 7
mysql> SELECT (1+2)*3;
        -> 9

6.3.1.2 Операторы сравнения

Операторы сравнения дают в результате величину 1 (истина, TRUE), 0 (ложь, FALSE) или NULL. Эти функции работают как с числами, так и со строками. Строки при необходимости автоматически преобразуются в числа, а числа - в строки (как в Perl).

Операции сравнения в MySQL выполняются по следующим правилам:

  • Если один или оба аргумента - NULL, то и результат сравнения будет NULL. Справедливо для всех операторов кроме <=>.
  • Если оба аргумента в операторе сравнения являются строками, то они сравниваются как строки.
  • Если оба аргумента - целые числа, то они сравниваются как целые числа.
  • Шестнадцатеричные величины, если они не сравниваются с числом, трактуются как строки с двоичными данными.
  • Если один из аргументов представляет собой столбец типа TIMESTAMP или DATETIME, а второй аргумент - константа, то константа перед выполнением сравнения преобразуется к типу TIMESTAMP. Это сделано для лучшей совместимости с ODBC.
  • Во всех других случаях аргументы сравниваются как действительные числа с плавающей точкой.

По умолчанию сравнение строк производится без учета регистра символов с использованием текущего набора символов (по умолчанию ISO-8859-1 Latin1, который, к тому же, прекрасно подходит для английского языка).

Ниже приведены примеры, иллюстрирующие преобразование строк в числа для операторов сравнения:

mysql> SELECT 1 > '6x';
         -> 0
mysql> SELECT 7 > '6x';
         -> 1
mysql> SELECT 0 > 'x6';
         -> 0
mysql> SELECT 0 = 'x6';
         -> 1
=
Равно:
mysql> SELECT 1 = 0;
        -> 0
mysql> SELECT '0' = 0;
        -> 1
mysql> SELECT '0.0' = 0;
        -> 1
mysql> SELECT '0.01' = 0;
        -> 0
mysql> SELECT '.01' = 0.01;
        -> 1
<>
!=
Не равно:
mysql> SELECT '.01' <> '0.01';
        -> 1
mysql> SELECT .01 <> '0.01';
        -> 0
mysql> SELECT 'zapp' <> 'zappp';
        -> 1
<=
Меньше или равно:
mysql> SELECT 0.1 <= 2;
        -> 1
<
Меньше чем:
mysql> SELECT 2 < 2;
        -> 0
>=
Больше или равно:
mysql> SELECT 2 >= 2;
        -> 1
>
Больше чем:
mysql> SELECT 2 > 2;
        -> 0
<=>
NULL-безопасное сравнение (равно):
mysql> SELECT 1 <=> 1, NULL <=> NULL, 1 <=> NULL;
        -> 1 1 0
IS NULL
IS NOT NULL
Тест для определения, является величина равной NULL или нет:
mysql> SELECT 1 IS NULL, 0 IS NULL, NULL IS NULL;
        -> 0 0 1
mysql> SELECT 1 IS NOT NULL, 0 IS NOT NULL, NULL IS NOT NULL;
        -> 1 1 0
Для того, чтобы MySQL хорошо работал с другими программами, обеспечивается поддержка следующих дополнительных возможностей для функции IS NULL:
  • Можно найти последнюю вставленную строку, используя выражение:
    SELECT * FROM tbl_name WHERE auto_col IS NULL
    Это свойство можно блокировать установкой SQL_AUTO_IS_NULL=0. See section 5.5.6 Синтаксис команды SET.
  • Для данных типа NOT NULL DATE и столбцов DATETIME можно найти особую дату 0000-00-00, используя выражение:
    SELECT * FROM tbl_name WHERE date_column IS NULL
    Это необходимо для работы некоторых приложений ODBC (так как ODBC не поддерживает значение даты 0000-00-00).
expr BETWEEN min AND max
Если величина выражения expr больше или равна заданному значению min и меньше или равна заданному значению max, то функция BETWEEN возвращает 1, в противном случае - 0. Это эквивалентно выражению (min <= expr AND expr <= max), в котором все аргументы представлены одним и тем же типом данных. В противном случае имеет место быть преобразование типов так, как сказано выше, но применительно ко всем трем аргументами. Внимание: до 4.0.5 аргументы приводились к типу expr.
mysql> SELECT 1 BETWEEN 2 AND 3;
        -> 0
mysql> SELECT 'b' BETWEEN 'a' AND 'c';
        -> 1
mysql> SELECT 2 BETWEEN 2 AND '3';
        -> 1
mysql> SELECT 2 BETWEEN 2 AND 'x-3';
        -> 0
expr NOT BETWEEN min AND max
То же справедливо и для функции NOT (expr BETWEEN min AND max).
expr IN (value,...)
Возвращает 1, если выражение expr равно любой величине из списка IN, иначе - 0. Если все величины - константы, то они оцениваются в соответствии с типом выражения expr и сортируются. Поиск элемента в этом случае производится методом логического поиска. Это означает, что функция IN является очень быстрой, если список значений IN состоит полностью из констант. Если expr является зависимым от регистра строковым выражением, то сравнение строк производится с учетом регистра:
mysql> SELECT 2 IN (0,3,5,'wefwf');
        -> 0
mysql> SELECT 'wefwf' IN (0,3,5,'wefwf');
        -> 1
Начиная с 4.1 (в соответствии со стандартом SQL-99), IN возвращает NULL не только если выражение в левой части является NULL, но также если не найдено соответствия в списке и одно из выражений в списке является величиной NULL.
expr NOT IN (value,...)
То же справедливо и для функции NOT (expr IN (value,...)).
ISNULL(expr)
Если expr равно NULL, то ISNULL() возвращает 1, в противном случае - 0:
mysql> SELECT ISNULL(1+1);
        -> 0
mysql> SELECT ISNULL(1/0);
        -> 1
Обратите внимание: при сравнении величин NULL с использованием оператора = всегда будет возвращаться значение FALSE!
COALESCE(list)
Возвращает первый в списке элемент со значением, не равным NULL:
mysql> SELECT COALESCE(NULL,1);
        -> 1
mysql> SELECT COALESCE(NULL,NULL,NULL);
        -> NULL
INTERVAL(N,N1,N2,N3,...)
Возвращает 0, если N < N1, и 1, если N < N2, и так далее. Все аргументы трактуются как целые числа. Для корректной работы этой функции необходимо условие N1 < N2 < N3 < ... < Nn. Это обусловлено тем, что используется логический поиск (очень быстрый):
mysql> SELECT INTERVAL(23, 1, 15, 17, 30, 44, 200);
        -> 3
mysql> SELECT INTERVAL(10, 1, 10, 100, 1000);
        -> 2
mysql> SELECT INTERVAL(22, 23, 30, 44, 200);
        -> 0

Если регистронезависимая строка сравнивается с помощью любого стандартного оператора (=, <>, ..., но не LIKE), то конечные пустые символы (т.е. пробелы, табуляторы и переводы строк) игнорируются: игнорируется.

mysql> SELECT "a" ="A \n";
        -> 1

6.3.1.3 Логические операторы

В SQL, все логические операторы возвращают TRUE (ИСТИНА), FALSE (ЛОЖЬ) или NULL (UNKNOWN, неизвестно). В MySQL это реализовано как 1 (TRUE, ИСТИНА), 0 (FALSE, ЛОЖЬ) или NULL. Это справедливо для большинства SQL СУБД, однако некоторые возвращают любое положительное значение как значение TRUE.

NOT
!
Логическое НЕ. Возвращает 1, если операнд равен 0, 0 если операнд - ненулевая величина, и NOT NULL возвращает NULL.
mysql> SELECT NOT 10;
        -> 0
mysql> SELECT NOT 0;
        -> 1
mysql> SELECT NOT NULL;
        -> NULL
mysql> SELECT ! (1+1);
        -> 0
mysql> SELECT ! 1+1;
        -> 1
Последний пример дает 1, поскольку данное выражение вычисляется тем же способом, что и (!1)+1.
AND
&&
Логическое И. Дает 1 если все операнды ненулевые и не NULL, 0 если один или более операндов равны 0, или NULL в остальных случаях.
mysql> SELECT 1 && 1;
        -> 1
mysql> SELECT 1 && 0;
        -> 0
mysql> SELECT 1 && NULL;
        -> NULL
mysql> SELECT 0 && NULL;
        -> 0
mysql> SELECT NULL && 0;
        -> 0
Обратите внимание, что версии MySQL до 4.0.5 прекращали вычисление, встретив первый NULL, вместо того, чтобы продолжать вычисление выражений с целью нахождения возможных значений 0. Это означает, что в этих версиях выражение SELECT (NULL AND 0) возвращает NULL вместо 0. В 4.0.5 код был переписан так, чтобы оптимизация сохранилась, но результат всегда был таков, как требует того ANSI.
OR
||
Логическое ИЛИ. Возвращает 1, если любой из операндов не 0, NULL если один из операндов NULL, в остальных случаях возвращает 0.
mysql> SELECT 1 || 1;
        -> 1
mysql> SELECT 1 || 0;
        -> 1
mysql> SELECT 0 || 0;
        -> 0
mysql> SELECT 0 || NULL;
        -> NULL
mysql> SELECT 1 || NULL;
        -> 1
XOR
Логический XOR (побитовое сложение по модулю 2) Возвращает NULL если любой из операндов - NULL. Для не-NULL операндов, возвращает 1 если нечетное количество операндов - не 0.
mysql> SELECT 1 XOR 1;
        -> 0
mysql> SELECT 1 XOR 0;
        -> 1
mysql> SELECT 1 XOR NULL;
        -> NULL
mysql> SELECT 1 XOR 1 XOR 1;
        -> 1
a XOR b математически эквалиентно (a AND (NOT b)) OR ((NOT a) and b). XOR был реализован в 4.0.2.

6.3.1.4 Функции потока управления программой

IFNULL(expr1,expr2)
Если expr1 не равно NULL, то функция IFNULL() возвращает значение expr1, в противном случае - expr2. В зависимости от контекста функция IFNULL() может возвращать либо числовое, либо строковое значение:
mysql> SELECT IFNULL(1,0);
        -> 1
mysql> SELECT IFNULL(NULL,10);
        -> 10
mysql> SELECT IFNULL(1/0,10);
        -> 10
mysql> SELECT IFNULL(1/0,'yes');
        -> 'yes'
В 4.0.6 и раньше по умолчанию возвращал для IFNULL(expr1,expr2) более "общее" из двух выражений в порядке STRING, REAL или INTEGER. Разница с более ранними версиями MySQL больше всего заметна тогда, когда вы создаете таблицу, основанную на выражении или MySQL внутренне сохраняет величину, основанную на выражении IFNULL() во временной таблице.
CREATE TABLE foo SELECT IFNULL(1,"test") as test;
В 4.0.6 тип для столбца "test" - CHAR(4) в то время как на более ранних типом был бы BIGINT.
NULLIF(expr1,expr2)
Если выражение expr1 = expr2 истинно, то возвращает NULL, в противном случае - expr1. Эквивалентна оператору CASE WHEN x = y THEN NULL ELSE x END:
mysql> SELECT NULLIF(1,1);
        -> NULL
mysql> SELECT NULLIF(1,2);
        -> 1
Отметим, что если аргументы не равны, то величина expr1 вычисляется в MySQL дважды.
IF(expr1,expr2,expr3)
Если expr1 равно значению ИСТИНА (expr1 <> 0 и expr1 <> NULL), то функция IF() возвращает expr2, в противном случае - expr3. В зависимости от контекста функция IF() может возвращать либо числовое, либо строковое значение:
mysql> SELECT IF(1>2,2,3);
        -> 3
mysql> SELECT IF(1<2,'yes','no');
        -> 'yes'
mysql> SELECT IF(STRCMP('test','test1'),'no','yes');
        -> 'no'
Если expr2 или expr3 являются NULL тогда результирующим типом IF() будет тип, который не есть NULL. Это нововведение в MySQL 4.0.3. expr1 вычисляется как целое число; это означает, что при исследовании чисел с плавающей точкой или строковых величин в этой функции необходимо использовать операцию сравнения:
mysql> SELECT IF(0.1,1,0);
        -> 0
mysql> SELECT IF(0.1<>0,1,0);
        -> 1
В первом случае из приведенных выше функция IF(0.1) возвращает 0, так как 0.1 преобразуется в целое число и в результате выполняется функция IF(0). Но это вовсе не то, что должно было бы получиться. Во втором случае исходная величина с плавающей точкой исследуется при помощи оператора сравнения, чтобы определить, является ли она ненулевой, и в качестве аргумента функции используется результат сравнения - целое число. В версии MySQL 3.23 возвращаемый по умолчанию тип функции IF() (это может иметь значение при сохранении его во временной таблице) вычисляется, как показано ниже:
Выражение | Возвращаемая величина
expr2 или expr3 возвращает строку | строка
expr2 or expr3 возвращает величину с плавающей точкой | с плавающей точкой
expr2 or expr3 возвращает целое число | целое число
Если expr2 и expr3 являются строками, и обе регистро-независимы, то и результат является регистро-независимым (начиная с 3.23.51).
CASE value WHEN [compare-value] THEN result [WHEN [compare-value] THEN result ...] [ELSE result] END
CASE WHEN [condition] THEN result [WHEN [condition] THEN result ...] [ELSE result] END
В первом варианте возвращается значение result, если value=compare-value. Во втором - результат для первого указанного условия condition, если оно истинно. Если соответствующая величина результата не определена, то возвращается значение result, указанное после оператора ELSE. Если часть ELSE в выражении отсутствует, возвращается NULL:
mysql> SELECT CASE 1 WHEN 1 THEN "one"
           WHEN 2 THEN "two" ELSE "more" END;
       -> "one"
mysql> SELECT CASE WHEN 1>0 THEN "true" ELSE "false" END;
       -> "true"
mysql> SELECT CASE BINARY "B" WHEN "a" THEN 1 WHEN "b" THEN 2 END;
       -> NULL

Тип возвращаемой величины будет такой же (INTEGER, DOUBLE или STRING), как и у первой возвращаемой величины (выражение после первого оператора THEN).

6.3.2 Строковые функции

Строковые функции возвращают NULL, если длина результата оказывается больше, чем указано в значении серверного параметра max_allowed_packet. See section 5.5.2 Настройка параметров сервера.

Для функций, работающих с позициями в строке, нумерация позиций начинается с 1.

Возвращает значение ASCII-кода крайнего слева символа строки str; 0 если str является пустой строкой; NULL, если str равна NULL:
mysql> SELECT ASCII('2');
        -> 50
mysql> SELECT ASCII(2);
        -> 50
mysql> SELECT ASCII('dx');
        -> 100
См. также функцию ORD().
ORD(str)
Если крайний слева символ строки str представляет собой многобайтный символ, то данная функция возвращает его код, который вычисляется на основе ASCII-кодов составляющих его символов по формуле: ((первый байт ASCII-кода)*256+(второй байт ASCII-кода))[*256+третий байт ASCII-кода...]. Если крайний слева символ не является многобайтным, то данная функция возвращает то же значение, что и ASCII():
mysql> SELECT ORD('2');
        -> 50
CONV(N,from_base,to_base)
Преобразует числа из одной системы счисления в другую. Возвращает строковое представление числа N, преобразованного из системы счисления с основой from_base в систему счисления с основой to_base. Если хотя бы один из аргументов равен NULL, то возвращается NULL. Аргумент N интерпретируется как целое число, но может быть задан как целое число или строка. Минимальное значение основы системы счисления равно 2, а максимальное - 36. Если аргумент to_base представлен отрицательным числом, то принимается, что N - число со знаком. В противном случае N трактуется как беззнаковое число. Функция CONV работает с 64-битовой точностью:
mysql> SELECT CONV("a",16,2);
        -> '1010'
mysql> SELECT CONV("6E",18,8);
        -> '172'
mysql> SELECT CONV(-17,10,-18);
        -> '-H'
mysql> SELECT CONV(10+"10"+'10'+0xa,10,10);
        -> '40'
BIN(N)
Возвращает строку, представляющую двоичную величину N, где N - целое число большого размера (BIGINT). Эквивалентна функции CONV(N,10,2). Если N равно NULL, возвращается NULL:
mysql> SELECT BIN(12);
        -> '1100'
OCT(N)
Возвращает строковое представление восьмеричного значения числа N, где N - целое число большого размера. Эквивалентно функции CONV(N,10,8). Если N равно NULL, возвращается NULL:
mysql> SELECT OCT(12);
        -> '14'
HEX(N_or_S)
Если N_OR_S - число, то возвращается строковое представление шестнадцатеричного числа N, где N - целое число большого размера (BIGINT). Эквивалентна функции CONV(N,10,16). Если N_OR_S - строка, то функция возвращает шестнадцатеричную строку N_OR_S, где каждый символ в N_OR_S конвертируется в 2 шестнадцатеричных числа. Является обратной по отношению к строкам 0xff.
mysql> SELECT HEX(255);
        -> 'FF'
mysql> SELECT HEX("abc");
        -> 616263
mysql> SELECT 0x616263;
        -> "abc"
CHAR(N,...)
CHAR() интерпретирует аргументы как целые числа и возвращает строку, состоящую из символов, соответствующих ASCII-коду этих чисел. Величины NULL пропускаются:
mysql> SELECT CHAR(77,121,83,81,'76');
        -> 'MySQL'
mysql> SELECT CHAR(77,77.3,'77.3');
        -> 'MMM'
CONCAT(str1,str2,...)
Возвращает строку, являющуюся результатом конкатенации аргументов. Если хотя бы один из аргументов равен NULL, возвращается NULL. Может принимать более 2 аргументов. Числовой аргумент преобразуется в эквивалентную строковую форму:
mysql> SELECT CONCAT('My', 'S', 'QL');
        -> 'MySQL'
mysql> SELECT CONCAT('My', NULL, 'QL');
        -> NULL
mysql> SELECT CONCAT(14.3);
        -> '14.3'
CONCAT_WS(separator, str1, str2,...)
Функция CONCAT_WS() обозначает CONCAT With Separator (конкатенация с разделителем) и представляет собой специальную форму функции CONCAT(). Первый аргумент является разделителем для остальных аргументов. Разделитель, так же как и остальные аргументы, может быть строкой. Если разделитель равен NULL, то результат будет NULL. Данная функция будет пропускать все величины NULL и пустые строки, расположенные после аргумента-разделителя. Разделитель будет добавляться между строками, подлежащими конкатенации:
mysql> SELECT CONCAT_WS(",","First name","Second name","Last Name");
        -> 'First name,Second name,Last Name'

mysql> SELECT CONCAT_WS(",","First name",NULL,"Last Name");
        -> 'First name,Last Name'
LENGTH(str)
OCTET_LENGTH(str)
CHAR_LENGTH(str)
CHARACTER_LENGTH(str)
Возвращает длину строки str:
mysql> SELECT LENGTH('text');
        -> 4

mysql> SELECT OCTET_LENGTH('text');
        -> 4
Обратите внимание: для CHAR_LENGTH() и CHARACTER_LENGTH() многобайтные символы учитываются только однажды.
BIT_LENGTH(str)
Возвращает длину строки str в битах:
mysql> SELECT BIT_LENGTH('text');
        -> 32
LOCATE(substr,str)
POSITION(substr IN str)
Возвращает позицию первого вхождения подстроки substr в строку str. Если подстрока substr в строке str отсутствует, возвращается 0:
mysql> SELECT LOCATE('bar', 'foobarbar');
        -> 4
mysql> SELECT LOCATE('xbar', 'foobar');
        -> 0
Данная функция поддерживает многобайтные величины. В MySQL 3.23 эта функция чувствительна к регистру, а в 4.0 она чувствительна к регистру только в случае, если хотя бы один из аргументов является строкой с двоичными данными.
LOCATE(substr,str,pos)
Возвращает позицию первого вхождения подстроки substr в строку str, начиная с позиции pos. Если подстрока substr в строке str отсутствует, возвращается 0:
mysql> SELECT LOCATE('bar', 'foobarbar',5);
        -> 7
Данная функция поддерживает многобайтные величины. В MySQL 3.23 эта функция чувствительна к регистру, а в 4.0 она чувствительна к регистру, только в случае, если хотя бы один из аргументов является строкой с двоичными данными.
INSTR(str,substr)
Возвращает позицию первого вхождения подстроки substr в строку str. То же, что и двухаргументная форма функции LOCATE(), за исключением перемены мест аргументов:
mysql> SELECT INSTR('foobarbar', 'bar');
        -> 4

mysql> SELECT INSTR('xbar', 'foobar');
        -> 0
Данная функция поддерживает многобайтные величины. В MySQL 3.23 эта функция чувствительна к регистру, а в 4.0 она чувствительна к регистру только в случае, если хотя бы один из аргументов является строкой с двоичными данными.
LPAD(str,len,padstr)
Возвращает строку str, которая дополняется слева строкой padstr, пока строка str не достигнет длины len символов. Если строка str длиннее, чем len, то она будет укорочена до len символов.
mysql> SELECT LPAD('hi',4,'??');
        -> '??hi'
RPAD(str,len,padstr)
Возвращает строку str, которая дополняется справа строкой padstr, пока строка str не достигнет длины len символов. Если строка str длиннее, чем len, то она будет укорочена до len символов.
mysql> SELECT RPAD('hi',5,'?');
        -> 'hi???'
LEFT(str,len)
Возвращает крайние слева len символов из строки str:
mysql> SELECT LEFT('foobarbar', 5);
        -> 'fooba'
Данная функция поддерживает многобайтные величины.
RIGHT(str,len)
Возвращает крайние справа len символов из строки str:
mysql> SELECT RIGHT('foobarbar', 4);
        -> 'rbar'
Данная функция поддерживает многобайтные величины.
SUBSTRING(str,pos,len)
SUBSTRING(str FROM pos FOR len)
MID(str,pos,len)
Возвращает подстроку длиной len символов из строки str, начиная от позиции pos. Существует форма с оператором FROM, для которой используется синтаксис ANSI SQL92:
mysql> SELECT SUBSTRING('Quadratically',5,6);
        -> 'ratica'
Данная функция поддерживает многобайтные величины.
SUBSTRING(str,pos)
SUBSTRING(str FROM pos)
Возвращает подстроку из строки str, начиная с позиции pos:
mysql> SELECT SUBSTRING('Quadratically',5);
        -> 'ratically'

mysql> SELECT SUBSTRING('foobarbar' FROM 4);
        -> 'barbar'
Данная функция поддерживает многобайтные величины.
SUBSTRING_INDEX(str,delim,count)
Возвращает подстроку из строки str перед появлениям count вхождений разделителя delim. Если count положителен, то возвращается все, что находится слева от последнего разделителя (считая слева). Если count отрицателен, то возвращается все, что находится справа от последнего разделителя (считая справа):
mysql> SELECT SUBSTRING_INDEX('www.mysql.com', '.', 2);
        -> 'www.mysql'

mysql> SELECT SUBSTRING_INDEX('www.mysql.com', '.', -2);
        -> 'mysql.com'
Данная функция поддерживает многобайтные величины.
LTRIM(str)
Возвращает строку str с удаленными начальными пробелами:
mysql> SELECT LTRIM(' barbar');
        -> 'barbar'
Данная функция поддерживает многобайтные величины.
RTRIM(str)
Возвращает строку str с удаленными конечными пробелами:
mysql> SELECT RTRIM('barbar ');
        -> 'barbar'
Данная функция поддерживает многобайтные величины.
TRIM([[BOTH | LEADING | TRAILING] [remstr] FROM] str)
Возвращает строку str с удаленными всеми префиксами и/или суффиксами, указанными в remstr. Если не указан ни один из спецификаторов BOTH, LEADING или TRAILING, то подразумевается BOTH. Если аргумент remstr не задан, то удаляются пробелы:
mysql> SELECT TRIM(' bar ');
        -> 'bar'

mysql> SELECT TRIM(LEADING 'x' FROM 'xxxbarxxx');
        -> 'barxxx'

mysql> SELECT TRIM(BOTH 'x' FROM 'xxxbarxxx');
        -> 'bar'

mysql> SELECT TRIM(TRAILING 'xyz' FROM 'barxxyz');
        -> 'barx'
Данная функция поддерживает многобайтные величины.
SOUNDEX(str)
Возвращает саундекс от str. Soundex - ``идентификатор звучания строки''. Словосочетания ``К скалам бурым'' и ``С каламбуроми'' должны давать одинаковый саундекс, т.к. на слух они звучат одинаково. Заметим, однако, что этой функции для русского языка не существует. MySQL нуждается в ней, и если кто-то может предоставить алгоритм саундекса на русском языке - свяжитесь с нами. - Прим. переводчика. Две созвучные строки, создающие впечатление почти одинаковых, могут иметь идентичные саундексы. Обычно стандартная саундекс-строка имеет длину 4 символа, но функция SOUNDEX() возвращает строку произвольной длины. Можно использовать функцию SUBSTRING() для извлечения стандартного саундекса строки из результата функции SOUNDEX(). В строке str игнорируются все символы, не являющиеся буквами или цифрами. Все международные буквенные символы, не входящие в диапазон A-Z, трактуются как гласные:
mysql> SELECT SOUNDEX('Hello');
        -> 'H400'

mysql> SELECT SOUNDEX('Quadratically');
        -> 'Q36324'
SPACE(N)
Возвращает строку, состоящую из N пробелов:
mysql> SELECT SPACE(6);
        -> ' '
REPLACE(str,from_str,to_str)
Возвращает строку str, в которой все вхождения строки from_str заменены на to_str:
mysql> SELECT REPLACE('www.mysql.com', 'w', 'Ww');
        -> 'WwWwWw.mysql.com'
Данная функция поддерживает многобайтные величины.
REPEAT(str,count)
Возвращает строку, состоящую из строки str, повторенной count раз. Если значение count <= 0, возвращает пустую строку. Возвращает NULL, если str или count равны NULL:
mysql> SELECT REPEAT('MySQL', 3);
        -> 'MySQLMySQLMySQL'
REVERSE(str)
Возвращает строку str с обратным порядком символов:
mysql> SELECT REVERSE('abc');
        -> 'cba'
Данная функция поддерживает многобайтные величины.
INSERT(str,pos,len,newstr)
Возвращает строку str, в которой подстрока начиная с позиции pos, имеющая длину len замещена на newstr:
mysql> SELECT INSERT('Quadratic', 3, 4, 'What');
        -> 'QuWhattic'
Данная функция поддерживает многобайтные величины.
ELT(N,str1,str2,str3,...)
Возвращает str1, если N = 1, str2, если N = 2, и так далее. Если N меньше, чем 1 или больше, чем число аргументов, возвращается NULL. Функция ELT() является дополненительной по отношению к функции FIELD():
mysql> SELECT ELT(1, 'ej', 'Heja', 'hej', 'foo');
        -> 'ej'

mysql> SELECT ELT(4, 'ej', 'Heja', 'hej', 'foo');
        -> 'foo'
FIELD(str,str1,str2,str3,...)
Возвращает индекс строки str в списке str1, str2, str3, .... Если строка str не найдена, возвращается 0. Функция FIELD() является дополнительной по отношению к функции ELT():
mysql> SELECT FIELD('ej', 'Hej', 'ej', 'Heja', 'hej', 'foo');
        -> 2

mysql> SELECT FIELD('fo', 'Hej', 'ej', 'Heja', 'hej', 'foo');
        -> 0
FIND_IN_SET(str,strlist)
Возвращает значение от 1 до N, если строка str присутствует в списке strlist, состоящем из N подстрок. Список строк представляет собой строку, состоящую из подстрок, разделенных символами `,'. Если первый аргумент представляет собой строку констант, а второй является столбцом типа SET, функция FIND_IN_SET() оптимизируется для использования двоичной арифметики! Возвращает 0, если str отсутствует в списке strlist или если strlist является пустой строкой. Если один из аргументов равен NULL, возвращается 0. Данная функция не будет корректно работать, если первый аргумент содержит символ `,':
mysql> SELECT FIND_IN_SET('b','a,b,c,d');
        -> 2
MAKE_SET(bits,str1,str2,...)
Возвращает множество (строку, содержащую подстроки, разделенные символами `,'), состоящее из строк, имеющих соответствующий бит в наборе bits. Аргумент str1 соответствует биту 0, str2 - биту 1, и так далее. Нулевые строки в наборах str1, str2, ... не прибавляются к результату:
mysql> SELECT MAKE_SET(1,'a','b','c');
        -> 'a'

mysql> SELECT MAKE_SET(1 | 4,'hello','nice','world');
        -> 'hello,world'

mysql> SELECT MAKE_SET(0,'a','b','c');
        -> ''
EXPORT_SET(bits,on,off,[separator,[number_of_bits]])
Возвращает строку, где для каждому установленному биту в аргументе bits соответствует строка on, а каждому сброшенному биту - off. Каждая строка отделена разделителем, указанным в параметре separator (по умолчанию - `,'), причем используется только количество битов, заданное аргументом number_of_bits (по умолчанию 64), из всего количества, указанного в bits:
mysql> SELECT EXPORT_SET(5,'Y','N',',',4)
        -> Y,N,Y,N
LCASE(str)
LOWER(str)
Возвращает строку str, в которой все символы переведены в нижний регистр в соответствии с текущей установкой набора символов (по умолчанию - ISO-8859-1 Latin1):
mysql> SELECT LCASE('QUADRATICALLY');
        -> 'quadratically'
Данная функция поддерживает многобайтные величины.
UCASE(str)
UPPER(str)
Возвращает строку str, в которой все символы переведены в верхний регистр в соответствии с текущей установкой набора символов (по умолчанию - ISO-8859-1 Latin1):
mysql> SELECT UCASE('Hej');
        -> 'HEJ'
Данная функция поддерживает многобайтные величины.
LOAD_FILE(file_name)
Читает заданный файл и возвращает его содержимое в виде строки. Данный файл должен находится на сервере, должен быть указан полный путь к этому файлу и пользователь должен обладать привилегией FILE. Размер данного файла должен быть меньше указанного в max_allowed_packet и файл должен быть открыт для чтения для всех. Если файл не существует или не может быть прочитан по одной из вышеупомянутых причин, то функция возвращает NULL:
mysql> UPDATE tbl_name
       SET blob_column=LOAD_FILE("/tmp/picture")
       WHERE id=1;
При использовании версии MySQL, отличной от 3.23, чтение файла необходимо выполнять внутри вашего приложения и использовать команду INSERT для внесения в базу данных информации, содержащейся в файле. Один из путей реализации этого с использованием библиотеки MySQL++ можно найти на http://www.mysql.com/documentation/mysql++/mysql++-examples.html.
QUOTE(str)
Экранирует строку с тем, чтобы получить корректное значение для SQL-выражения. Строка заключается в одинарные кавычки, и каждое вхождение одинарной кавычки (`''), обратного слеша (`\'), значения ASCII NUL и Control-Z экранируются обратным слешом. Если аргумент - NULL, то тогда результатом будет слово "NULL" без окружающих кавычек.
mysql> SELECT QUOTE("Don't");
        -> 'Don\'t!'
mysql> SELECT QUOTE(NULL);
        -> NULL

MySQL при необходимости автоматически конвертирует числа в строки и наоборот:

mysql> SELECT 1+"1";
        -> 2

mysql> SELECT CONCAT(2,' test');
        -> '2 test'

Для преобразования числа в строку явным образом, необходимо передать его в качестве аргумента функции CONCAT().

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

6.3.2.1 Функции сравнения строк

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

expr LIKE pat [ESCAPE 'escape-char']
Функция производит сравнение с шаблоном, используя операции сравнения простых регулярных выражений в SQL. Возвращает 1 (ИСТИНА) или 0 (ЛОЖЬ). Выражение LIKE предусматривает использование следующих двух шаблонных символов в pat:
Символ Описание
% Соответствует любому количеству символов, даже нулевых
_ Соответствует ровно одному символу
mysql> SELECT 'David!' LIKE 'David_';
        -> 1
mysql> SELECT 'David!' LIKE '%D%v%';
        -> 1
mysql> select TRUNCATE(-1.999,1);
        -> -1.9
Начиная с MySQL 3.23.51 все числа округляются к нулю. Если D является негативным, то тогда вся часть числа округляется к нулю.
mysql> select truncate(122,-2);
       -> 100
Если требуется исследовать литералы при помощи шаблонного символа, следует предварить шаблонный символ экранирующим символом. Если экранирующий символ конкретно не указывается, то подразумевается применение символа `\':
Строка Описание
\% Соответствует одному символу `%'
\_ Соответствует одному символу `_'
mysql> SELECT 'David!' LIKE 'David\_';
        -> 0

mysql> SELECT 'David_' LIKE 'David\_';
        -> 1
Для указания конкретного экранирующего символа используется выражение ESCAPE:
mysql> SELECT 'David_' LIKE 'David|_' ESCAPE '|';
        -> 1
В следующих двух примерах показано, что сравнение строк производится с учетом регистра, если ни один из операндов не является строкой с двоичными данными:
mysql> SELECT 'abc' LIKE 'ABC';
        -> 1
mysql> SELECT 'abc' LIKE BINARY 'ABC';
        -> 0
В функции LIKE допускаются даже числовые выражения! (Это расширение MySQL по сравнению с ANSI SQL LIKE.)
mysql> SELECT 10 LIKE '1%';
        -> 1
Примечание: поскольку в MySQL применяются правила экранирования в строках, применяемые в языке C (например, `\n'), необходимо дублировать все символы `\', используемые в строках функции LIKE. Например, для поиска сочетания символов `\n' его необходимо указать как `\\n'. Чтобы выполнить поиск символа `\', он должен быть указан как `\\\\' (обратные слеши удаляются дважды: сначала синтаксическим анализатором, а потом - при выполнении сравнения с шаблоном, таким образом остается только один обратный слеш, который и будет обрабатываться).
expr NOT LIKE pat [ESCAPE 'escape-char']
То же, что и NOT (expr LIKE pat [ESCAPE 'escape-char']).
expr SOUNDS LIKE expr
Тоже самое что и SOUNDEX(expr)=SOUNDEX(expr) (доступно в версии 4.1 или новее).
expr REGEXP pat
expr RLIKE pat
Выполняет сравнение строкового выражения expr с шаблоном pat. Шаблон может представлять собой расширенное регулярное выражение. See section F Регулярные выражения в MySQL. Возвращает 1, если expr соответствует pat, в противном случае - 0. Функция RLIKE является синонимом для REGEXP, она предусмотрена для совместимости с mSQL. Примечание: поскольку в MySQL используются правила экранирования в строках, применяемые в языке C (например, `\n'), необходимо дублировать все символы `\', используемые в строках функции REGEXP. Что касается версии MySQL 3.23.4, функция REGEXP является независимой от регистра для нормальных строк (т.е. строк не с двоичными данными):
mysql> SELECT 'Monty!' REGEXP 'm%y%%';
        -> 0

mysql> SELECT 'Monty!' REGEXP '.*';
        -> 1

mysql> SELECT 'new*\n*line' REGEXP 'new\\*.\\*line';
        -> 1

mysql> SELECT "a" REGEXP "A", "a" REGEXP BINARY "A";
        -> 1 0

mysql> SELECT "a" REGEXP "^[a-d]";
        -> 1
В REGEXP и RLIKE используется текущий набор символов (ISO-8859-1 Latin1 по умолчанию),
expr NOT REGEXP pat
expr NOT RLIKE pat
То же, что и NOT (expr REGEXP pat).
STRCMP(expr1,expr2)
Функция STRCMP() возвращает: 0, если строки идентичны, -1 - если первый аргумент меньше второго (в соответствии с имеющимся порядком сортировки), и 1 - в остальных случаях:
mysql> SELECT STRCMP('text', 'text2');
        -> -1

mysql> SELECT STRCMP('text2', 'text');
        -> 1

mysql> SELECT STRCMP('text', 'text');
        -> 0
MATCH (col1,col2,...) AGAINST (expr)
MATCH (col1,col2,...) AGAINST (expr IN BOOLEAN MODE)
Функция MATCH ... AGAINST() используется для полнотекстового поиска и возвращает величину релевантности - степень сходства между текстом в столбцах (col1,col2,...) и запросом expr. Величина релевантности представляет собой положительное число с плавающей точкой. Нулевая релевантность означает отсутствие сходства. Функция MATCH ... AGAINST() работает в версиях MySQL 3.23.23 или более поздних. Расширение IN BOOLEAN MODE было добавлено в версии 4.0.1. Более подробное описание и примеры использования приведены в разделе section 6.8 Полнотекстовый поиск в MySQL.

6.3.2.2 Чувствительность к регистру

BINARY
Оператор BINARY преобразует следующую за ним строку в строку с двоичными данными. Это простой способ обеспечить сравнение в столбце с учетом регистра, даже если данный столбец не определен как BINARY или BLOB:
mysql> SELECT "a" = "A";
        -> 1

mysql> SELECT BINARY "a" = "A";
        -> 0
BINARY string является сокращением для CAST(string AS BINARY). See section 6.3.5 Функции приведения типов. Оператор BINARY был введен в версии MySQL 3.23.0. Следует учитывать, что при приведении индексированного столбца к типу BINARY MySQL в некоторых случаях не сможет эффективно использовать индексы. Для сравнения двоичных данных типа BLOB без учета регистра данные с типом BLOB перед выполнением сравнения всегда можно конвертировать в верхний регистр:
SELECT 'A' LIKE UPPER(blob_col) FROM table_name;
В скором времени мы планируем ввести преобразование между различными кодировками, чтобы сделать сравнение строк еще более гибким.

6.3.3 Числовые функции

6.3.3.1 Арифметические операции

В MySQL можно применять обычные арифметические операторы. Следует иметь в виду, что если оба аргумента являются целыми числами, то при использовании операторов `-', `+' и `*' результат вычисляется с точностью BIGINT (64 бита). Если один из аргументов - беззнаковое целое число, а второй аргумент - также целое число, то результат будет беззнаковым целым числом. See section 6.3.5 Функции приведения типов.

+
Сложение:
mysql> SELECT 3+5;
        -> 8
-
Вычитание:
mysql> SELECT 3-5;
        -> -2
*
Умножение:
mysql> SELECT 3*5;
        -> 15

mysql> SELECT 18014398509481984*18014398509481984.0;
        -> 324518553658426726783156020576256.0

mysql> SELECT 18014398509481984*18014398509481984;
        -> 0
В последнем выражении мы получим неверный результат, так как произведение умножения целых чисел выходит за границы 64-битового диапазона для вычислений с точностью BIGINT.
/
Деление:
mysql> SELECT 3/5;
        -> 0.60
Деление на ноль приводит к результату NULL:
mysql> SELECT 102/(1-1);
        -> NULL
Деление будет выполняться по правилам BIGINT-арифметики только в случае, если эта операция представлена в контексте, где ее результат преобразуется в INTEGER!

6.3.3.2 Математические функции

Все математические функции в случае ошибки возвращают NULL.

-
Унарный минус. Изменяет знак аргумента:
mysql> SELECT - 2;
        -> -2
Необходимо учитывать, что если этот оператор используется с данными типа BIGINT, возвращаемое значение также будет иметь тип BIGINT! Это означает, что следует избегать использования оператора для целых чисел, которые могут иметь величину -2^63!
ABS(X)
Возвращает абсолютное значение величины X:
mysql> SELECT ABS(2);
        -> 2
mysql> SELECT ABS(-32);
        -> 32
Эту функцию можно уверенно применять для величин типа BIGINT.
SIGN(X)
Возвращает знак аргумента в виде -1, 0 или 1, в зависимости от того, является ли X отрицательным, нулем или положительным:
mysql> SELECT SIGN(-32);
        -> -1

mysql> SELECT SIGN(0);
        -> 0

mysql> SELECT SIGN(234);
        -> 1
MOD(N,M)
%
Значение по модулю (подобно оператору % в C). Возвращает остаток от деления N на M:
mysql> SELECT MOD(234, 10);
        -> 4

mysql> SELECT 253 % 7;
        -> 1

mysql> SELECT MOD(29,9);
        -> 2
Эту функцию можно уверенно применять для величин типа BIGINT.
FLOOR(X)
Возвращает наибольшее целое число, не превышающее X:
mysql> SELECT FLOOR(1.23);
        -> 1

mysql> SELECT FLOOR(-1.23);
        -> -2
Следует учитывать, что возвращаемая величина преобразуется в BIGINT!
CEILING(X)
Возвращает наименьшее целое число, не меньшее, чем X:
mysql> SELECT CEILING(1.23);
        -> 2

mysql> SELECT CEILING(-1.23);
        -> -1
Следует учитывать, что возвращаемая величина преобразуется в BIGINT!
ROUND(X)
Возвращает аргумент X, округленный до ближайшего целого числа:
mysql> SELECT ROUND(-1.23);
        -> -1

mysql> SELECT ROUND(-1.58);
        -> -2

mysql> SELECT ROUND(1.58);
        -> 2
Следует учитывать, что поведение функции ROUND() при значении аргумента, равном середине между двумя целыми числами, зависит от конкретной реализации библиотеки C. Округление может выполняться: к ближайшему четному числу, всегда к ближайшему большему, всегда к ближайшему меньшему, всегда быть направленным к нулю. Чтобы округление всегда происходило только в одном направлении, необходимо использовать вместо данной хорошо определенные функции, такие как TRUNCATE() или FLOOR().
ROUND(X,D)
Возвращает аргумент X, округленный до числа с D десятичными знаками. Если D равно 0, результат будет представлен без десятичного знака или дробной части:
mysql> SELECT ROUND(1.298, 1);
        -> 1.3

mysql> SELECT ROUND(1.298, 0);
        -> 1
EXP(X)
Возвращает значение e (основа натуральных логарифмов), возведенное в степень X:
mysql> SELECT EXP(2);
        -> 7.389056

mysql> SELECT EXP(-2);
        -> 0.135335
LN(X)
Возвращает натуральный логарифм числа X:
mysql> SELECT LN(2);
        -> 0.693147
mysql> SELECT LN(-2);
        -> NULL
Эта функция появилась в MySQL 4.0.3. Это синоним LOG(X).
LOG(B, X)
Если вызывается с одним параметром, возвращает натуральный логарифм числа X:
mysql> SELECT LOG(2);
        -> 0.693147

mysql> SELECT LOG(-2);
        -> NULL
Если вызывается с двумя параметрами, функция возвращает логарифм числа X по базе B:
mysql> SELECT LOG(2,65536);
        -> 16.000000
mysql> SELECT LOG(1,100);
        -> NULL
Опция указания базы логарифма появилась в MySQL 4.0.3. LOG(B,X) эквалиентно LOG(X)/LOG(B).
LOG2(X)
Возвращает логарифм числа X по базе 2:
mysql> SELECT LOG2(65536);
        -> 16.000000
mysql> SELECT LOG2(-100);
        -> NULL
Функция LOG2() полезна с тем, чтобы узнать, сколько бит число потребует для хранения. Эта функция добавлена в MySQL 4.0.3. В более старых версиях вызывайте вместо нее: LOG(X)/LOG(2)
LOG10(X)
Возвращает десятичный логарифм числа X:
mysql> SELECT LOG10(2);
        -> 0.301030

mysql> SELECT LOG10(100);
        -> 2.000000

mysql> SELECT LOG10(-100);
        -> NULL
POW(X,Y)
POWER(X,Y)
Возвращает значение аргумента X, возведенное в степень Y:
mysql> SELECT POW(2,2);
        -> 4.000000

mysql> SELECT POW(2,-2);
        -> 0.250000
SQRT(X)
Возвращает неотрицательный квадратный корень числа X:
mysql> SELECT SQRT(4);
        -> 2.000000

mysql> SELECT SQRT(20);
        -> 4.472136
PI()
Возвращает значение числа "пи". По умолчанию представлено 5 десятичных знаков, но в MySQL для представления числа "пи" при внутренних вычислениях используется полная двойная точность.
mysql> SELECT PI();
        -> 3.141593

mysql> SELECT PI()+0.000000000000000000;
        -> 3.141592653589793116
COS(X)
Возвращает косинус числа X, где X задается в радианах:
mysql> SELECT COS(PI());
        -> -1.000000
SIN(X)
Возвращает синус числа X, где X задается в радианах:
mysql> SELECT SIN(PI());
        -> 0.000000
TAN(X)
Возвращает тангенс числа X, где X задается в радианах:
mysql> SELECT TAN(PI()+1);
        -> 1.557408
ACOS(X)
Возвращает арккосинус числа X, т.е. величину, косинус которой равен X. Если X не находится в диапазоне от -1 до 1, возвращает NULL:
mysql> SELECT ACOS(1);
        -> 0.000000

mysql> SELECT ACOS(1.0001);
        -> NULL

mysql> SELECT ACOS(0);
        -> 1.570796
ASIN(X)
Возвращает арксинус числа X, т.е. величину, синус которой равен X. Если X не находится в диапазоне от -1 до 1, возвращает NULL:
mysql> SELECT ASIN(0.2);
        -> 0.201358

mysql> SELECT ASIN('foo');
        -> 0.000000
ATAN(X)
Возвращает арктангенс числа X, т.е. величину, тангенс которой равен X:
mysql> SELECT ATAN(2);
        -> 1.107149

mysql> SELECT ATAN(-2);
        -> -1.107149
ATAN(Y,X)
ATAN2(Y,X)
Возвращает арктангенс двух переменных X и Y. Вычисление производится так же, как и вычисление арктангенса Y / X, за исключением того, что знаки обоих аргументов используются для определения квадранта результата:
mysql> SELECT ATAN(-2,2);
        -> -0.785398

mysql> SELECT ATAN2(PI(),0);
        -> 1.570796
COT(X)
Возвращает котангенс числа X:
mysql> SELECT COT(12);
        -> -1.57267341

mysql> SELECT COT(0);
        -> NULL
RAND()
RAND(N)
Возвращает случайную величину с плавающей точкой в диапазоне от 0 до 1,0. Если целочисленный аргумент N указан, то он используется как начальное значение этой величины:
mysql> SELECT RAND();
        -> 0.9233482386203

mysql> SELECT RAND(20);
        -> 0.15888261251047

mysql> SELECT RAND(20);
        -> 0.15888261251047

mysql> SELECT RAND();
        -> 0.63553050033332

mysql> SELECT RAND();
        -> 0.70100469486881
В выражениях вида ORDER BY не следует использовать столбец с величинами RAND(), поскольку применение оператора ORDER BY приведет к многократным вычислениям в этом столбце. В версии MySQL 3.23 можно, однако, выполнить следующий оператор: SELECT * FROM table_name ORDER BY RAND(): он полезен для получения случайного экземпляра из множества SELECT * FROM table1,table2 WHERE a=b AND c<d ORDER BY RAND() LIMIT 1000. Следует учитывать, что оператор RAND() в выражении WHERE при выполнении выражения WHERE будет вычисляться каждый раз заново. Оператор RAND() не следует воспринимать как полноценный генератор случайных чисел: это просто быстрый способ динамической генерации случайных чисел, переносимых между платформами для одной и той же версии MySQL.
LEAST(X,Y,...)
Если задано два или более аргументов, возвращает наименьший (с минимальным значением) аргумент. Сравнение аргументов происходит по следующим правилам:
  • Если возвращаемая величина используется в целочисленном контексте (INTEGER), или все аргументы являются целочисленными, то они сравниваются как целые числа.
  • Если возвращаемая величина используется в контексте действительных чисел (REAL) или все аргументы являются действительными числами, то они сравниваются как числа типа REAL.
  • Если один из аргументов является зависимой от регистра строкой, то данные аргументы сравниваются с учетом регистра.
  • В остальных случаях аргументы сравниваются как строки, независимые от регистра.
mysql> SELECT LEAST(2,0);
        -> 0

mysql> SELECT LEAST(34.0,3.0,5.0,767.0);
        -> 3.0

mysql> SELECT LEAST("B","A","C");
        -> "A"
В версиях MySQL до 3.22.5 можно использовать MIN() вместо LEAST.
GREATEST(X,Y,...)
Возвращает наибольший (с максимальным значением) аргумент. Сравнение аргументов происходит по тем же правилам, что и для LEAST:
mysql> SELECT GREATEST(2,0);
        -> 2

mysql> SELECT GREATEST(34.0,3.0,5.0,767.0);
        -> 767.0

mysql> SELECT GREATEST("B","A","C");
        -> "C"
В версиях MySQL до 3.22.5 можно использовать MAX() вместо GREATEST.
DEGREES(X)
Возвращает аргумент X, преобразованный из радианов в градусы:
mysql> SELECT DEGREES(PI());
        -> 180.000000
RADIANS(X)
Возвращает аргумент X, преобразованный из градусов в радианы:
mysql> SELECT RADIANS(90);
        -> 1.570796
TRUNCATE(X,D)
Возвращает число X, усеченное до D десятичных знаков. Если D равно 0, результат будет представлен без десятичного знака или дробной части:
mysql> SELECT TRUNCATE(1.223,1);
        -> 1.2
mysql> SELECT TRUNCATE(1.999,1);
        -> 1.9
mysql> SELECT TRUNCATE(1.999,0);
        -> 1
mysql> SELECT TRUNCATE(-1.999,1);
        -> -1.9
Начиная с MySQL 3.23.51 все числа округляются к нулю. Если D - негативное, то тогда вся часть числа обнуляется:
mysql> SELECT TRUNCATE(122,-2);
       -> 100
Следует учитывать, что обычно в компьютерах десятичные числа хранятся не так, как целые, а как числа двойной точности с плавающим десятичным знаком (DOUBLE). Поэтому иногда результат может вводить в заблуждение, как в следующем примере:
mysql> SELECT TRUNCATE(10.28*100,0);
        -> 1027
Это происходит потому, что в действительности 10,28 хранится как нечто вроде 10,2799999999999999.

6.3.4 Функции даты и времени

Описание диапазона величин для каждого типа и возможные форматы представления даты и времени приведены в разделе section 6.2.2 Типы данных даты и времени.

Ниже представлен пример, в котором используются функции даты. Приведенный запрос выбирает все записи с величиной date_col в течение последних 30 дней:

mysql> SELECT something FROM tbl_name
        WHERE TO_DAYS(NOW()) - TO_DAYS(date_col) <= 30;
DAYOFWEEK(date)
Возвращает индекс дня недели для аргумента date (1 = воскресенье, 2 = понедельник, ... 7 = суббота). Эти индексные величины соответствуют стандарту ODBC.
mysql> SELECT DAYOFWEEK('1998-02-03');
        -> 3
WEEKDAY(date)
Возвращает индекс дня недели для аргумента date (0 =понедельник, 1 = вторник, ... 6 = воскресенье):
mysql> SELECT WEEKDAY('1998-02-03 22:23:00');
        -> 1
mysql> SELECT WEEKDAY('1997-11-05');
        -> 2
DAYOFMONTH(date)
Возвращает порядковый номер дня месяца для аргумента date в диапазоне от 1 до 31:
mysql> SELECT DAYOFMONTH('1998-02-03');
        -> 3
DAYOFYEAR(date)
Возвращает порядковый номер дня года для аргумента date в диапазоне от 1 до 366:
mysql> SELECT DAYOFYEAR('1998-02-03');
        -> 34
MONTH(date)
Возвращает порядковый номер месяца в году для аргумента date в диапазоне от 1 до 12:
mysql> SELECT MONTH('1998-02-03');
        -> 2
DAYNAME(date)
Возвращает название дня недели для аргумента date:
mysql> SELECT DAYNAME("1998-02-05");
        -> 'Thursday'
MONTHNAME(date)
Возвращает название месяца для аргумента date:
mysql> SELECT MONTHNAME("1998-02-05");
        -> 'February'
QUARTER(date)
Возвращает номер квартала года для аргумента date в диапазоне от 1 до 4:
mysql> SELECT QUARTER('98-04-01');
        -> 2
WEEK(date)
WEEK(date,first)
При наличии одного аргумента возвращает порядковый номер недели в году для date в диапазоне от 0 до 53 (да, возможно начало 53-й недели) для регионов, где воскресенье считается первым днем недели. Форма WEEK() с двумя аргументами позволяет уточнить, с какого дня начинается неделя - с воскресенья или с понедельника. Результат будет в пределах 0-53 или 1-52. Вот как работает второй аргумент:
Величина | Означает
0 | Неделя начинается с воскресенья; возвращаемое значение - в промежутке 0-53
1 | Неделя начинается с понедельника; возвращаемое значение - в промежутке 0-53
2 | Неделя начинается с воскресенья; возвращаемое значение - в промежутке 1-53
3 | Неделя начинается с понедельника; возвращаемое значение - в промежутке 1-53 (ISO 8601)
mysql> SELECT WEEK('1998-02-20');
        -> 7

mysql> SELECT WEEK('1998-02-20',0);
        -> 7

mysql> SELECT WEEK('1998-02-20',1);
        -> 8

mysql> SELECT WEEK('1998-12-31',1);
        -> 53
Примечание: в версии 4.0 функция WEEK(#,0) была изменена с целью соответствия календарю США. Заметьте, если неделя является последней неделей прошлого года, MySQL вернет 0 если вы не указали 2 или 3 как опциональный аргумент:
mysql> SELECT YEAR('2000-01-01'), WEEK('2000-01-01',0);
        -> 2000, 0
mysql> SELECT WEEK('2000-01-01',2);
        -> 52
Можно считать, что MySQL должен вернуть 52, так как данная дата и является 52-ой неделей года 1999. Мы решили возвращать 0, так как мы хотим, чтобы функция давала "номер недели в указанном году". Это делает функцию WEEK() более надежной при использовании совместно с другими функциями, которые вычисляют части дат. Если вам все же важно уточнить корректную неделю в году, тогда вы можете использовать 2 или 3 как опциональный аргумент или использовать YEARWEEK()
mysql> SELECT YEARWEEK('2000-01-01');
        -> 199952
mysql> SELECT MID(YEARWEEK('2000-01-01'),5,2);
        -> 52
YEAR(date)
Возвращает год для аргумента date в диапазоне от 1000 до 9999:
mysql> SELECT YEAR('98-02-03');
        -> 1998
YEARWEEK(date)
YEARWEEK(date,first)
Возвращает год и неделю для аргумента date. Второй аргумент в данной функции работает подобно второму аргументу в функции WEEK(). Следует учитывать, что год может отличаться от указанного в аргументе date для первой и последней недель года:
mysql> SELECT YEARWEEK('1987-01-01');
        -> 198653
Обратите внимание, что номер недели отличается от того, который возвращает функция WEEK() (0), будучи вызванной с опциональным аргументом 0 или 1. Это потому, что WEEK() возвращает номер недели именно в указанном году.
HOUR(time)
Возвращает час для аргумента time в диапазоне от 0 до 23:
mysql> SELECT HOUR('10:05:03');
        -> 10
MINUTE(time)
Возвращает количество минут для аргумента time в диапазоне от 0 до 59:
mysql> SELECT MINUTE('98-02-03 10:05:03');
        -> 5
SECOND(time)
Возвращает количество секунд для аргумента time в диапазоне от 0 до 59:
mysql> SELECT SECOND('10:05:03');
        -> 3
PERIOD_ADD(P,N)
Добавляет N месяцев к периоду P (в формате YYMM или YYYYMM). Возвращает величину в формате YYYYMM. Следует учитывать, что аргумент периода P не является значением даты:
mysql> SELECT PERIOD_ADD(9801,2);
        -> 199803
PERIOD_DIFF(P1,P2)
Возвращает количество месяцев между периодами P1 и P2. P1 и P2 должны быть в формате YYMM или YYYYMM. Следует учитывать, что аргументы периода P1 и P2 не являются значениями даты:
mysql> SELECT PERIOD_DIFF(9802,199703);
        -> 11
DATE_ADD(date,INTERVAL expr type)
DATE_SUB(date,INTERVAL expr type)
ADDDATE(date,INTERVAL expr type)
SUBDATE(date,INTERVAL expr type)
Данные функции производят арифметические действия над датами. Обе являются нововведением версии MySQL 3.22. Функции ADDDATE() и SUBDATE() - синонимы для DATE_ADD() и DATE_SUB(). В версии MySQL 3.23 вместо функций DATE_ADD() и DATE_SUB() можно использовать операторы + и -, если выражение с правой стороны представляет собой столбец типа DATE или DATETIME (см. пример ниже). Аргумент date является величиной типа DATETIME или DATE, задающей начальную дату. Выражение expr задает величину интервала, который следует добавить к начальной дате или вычесть из начальной даты. Выражение expr представляет собой строку, которая может начинаться с - для отрицательных значений интервалов. Ключевое слово type показывает, каким образом необходимо интерпретировать данное выражение. Вспомогательная функция EXTRACT(type FROM date) возвращает интервал указанного типа (type) из значения даты. В следующей таблице показана взаимосвязь аргументов type и expr:
Значение Type | Ожидаемый формат expr
SECOND | SECONDS
MINUTE | MINUTES
HOUR | HOURS
DAY | DAYS
MONTH | MONTHS
YEAR | YEARS
MINUTE_SECOND | "MINUTES:SECONDS"
HOUR_MINUTE | "HOURS:MINUTES"
DAY_HOUR | "DAYS HOURS"
YEAR_MONTH | "YEARS-MONTHS"
HOUR_SECOND | "HOURS:MINUTES:SECONDS"
DAY_MINUTE | "DAYS HOURS:MINUTES"
DAY_SECOND | "DAYS HOURS:MINUTES:SECONDS"
В MySQL формат выражения expr допускает любые разделительные знаки. Разделители, представленные в данной таблице, приведены в качестве примеров. Если аргумент date является величиной типа DATE и предполагаемые вычисления включают в себя только части YEAR, MONTH, и DAY (т.е. не содержат временной части TIME), то результат представляется величиной типа DATE. В других случаях результат представляет собой величину DATETIME:
mysql> SELECT "1997-12-31 23:59:59" + INTERVAL 1 SECOND;
        -> 1998-01-01 00:00:00
mysql> SELECT INTERVAL 1 DAY + "1997-12-31";
        -> 1998-01-01
mysql> SELECT "1998-01-01" - INTERVAL 1 SECOND;
        -> 1997-12-31 23:59:59
mysql> SELECT DATE_ADD("1997-12-31 23:59:59", INTERVAL 1 SECOND);
        -> 1998-01-01 00:00:00
mysql> SELECT DATE_ADD("1997-12-31 23:59:59", INTERVAL 1 DAY);
        -> 1998-01-01 23:59:59
mysql> SELECT DATE_ADD("1997-12-31 23:59:59", INTERVAL "1:1" MINUTE_SECOND);
        -> 1998-01-01 00:01:00
mysql> SELECT DATE_SUB("1998-01-01 00:00:00", INTERVAL "1 1:1:1" DAY_SECOND);
        -> 1997-12-30 22:58:59
mysql> SELECT DATE_ADD("1998-01-01 00:00:00", INTERVAL "-1 10" DAY_HOUR);
        -> 1997-12-30 14:00:00
mysql> SELECT DATE_SUB("1998-01-02", INTERVAL 31 DAY);
        -> 1997-12-02
Если указанный интервал слишком короткий (т.е. не включает все части интервала, ожидаемые при заданном ключевом слове type), то MySQL предполагает, что опущены крайние слева части интервала. Например, если указан аргумент type в виде DAY_SECOND, то ожидаемое выражение expr должно иметь следующие части: дни, часы, минуты и секунды. Если в этом случае указать значение интервала в виде "1:10", то MySQL предполагает, что опущены дни и часы, а данная величина включает только минуты и секунды. Другими словами, сочетание "1:10" DAY_SECOND интерпретируется как эквивалент "1:10" MINUTE_SECOND. Аналогичным образом в MySQL интерпретируются и значения TIME - скорее как представляющие прошедшее время, чем как время дня. Следует учитывать, что при операциях сложения или вычитания с участием величины DATE и выражения, содержащего временную часть, данная величина DATE будет автоматически конвертироваться в величину типа DATETIME:
mysql> SELECT DATE_ADD("1999-01-01", INTERVAL 1 DAY);
        -> 1999-01-02

mysql> SELECT DATE_ADD("1999-01-01", INTERVAL 1 HOUR);
        -> 1999-01-01 01:00:00
При использовании некорректных значений дат результат будет равен NULL. Если при суммировании MONTH, YEAR_MONTH или YEAR номер дня в результирующей дате превышает максимальное количество дней в новом месяце, то номер дня результирующей даты принимается равным последнему дню нового месяца:
mysql> SELECT DATE_ADD('1998-01-30', INTERVAL 1 MONTH);
        -> 1998-02-28
Из предыдущего примера видно, что слово INTERVAL и ключевое слово type не являются регистро-зависимыми.
EXTRACT(type FROM date)
Типы интервалов для функции EXTRACT() используются те же, что и для функций DATE_ADD() или DATE_SUB(), но EXTRACT() производит скорее извлечение части из значения даты, чем выполнение арифметических действий.
mysql> SELECT EXTRACT(YEAR FROM "1999-07-02");
        -> 1999

mysql> SELECT EXTRACT(YEAR_MONTH FROM "1999-07-02 01:02:03");
        -> 199907

mysql> SELECT EXTRACT(DAY_MINUTE FROM "1999-07-02 01:02:03");
        -> 20102
TO_DAYS(date)
функция возвращает номер дня для даты, указанной в аргументе date, (количество дней, прошедших с года 0):
mysql> SELECT TO_DAYS(950501);
        -> 728779

mysql> SELECT TO_DAYS('1997-10-07');
        -> 729669
Функция TO_DAYS() не предназначена для использования с величинами, предшествующими введению григорианского календаря (1582), поскольку не учитывает дни, утерянные при изменении календаря.
FROM_DAYS(N)
Возвращает величину DATE для заданного номера дня N:
mysql> SELECT FROM_DAYS(729669);
        -> '1997-10-07'
Функция FROM_DAYS() не предназначена для использования с величинами, предшествующими введению григорианского календаря (1582), поскольку она не учитывает дни, утерянные при изменении календаря.
DATE_FORMAT(date,format)
Форматирует величину date в соответствии со строкой format. В строке format могут использоваться следующие определители:
Определитель | Описание
%M | Название месяца (январь...декабрь)
%W | Название дня недели (воскресенье...суббота)
%D | День месяца с английским суффиксом (0st, 1st, 2nd, 3rd и т.д.)
%Y | Год, число, 4 разряда
%y | Год, число, 2 разряда
%X | Год для недели, где воскресенье считается первым днем недели, число, 4 разряда, используется с '%V'
%x | Год для недели, где воскресенье считается первым днем недели, число, 4 разряда, используется с '%v'
%a | Сокращенное наименование дня недели (Вс...Сб)
%d | День месяца, число (00..31)
%e | День месяца, число (0..31)
%m | Месяц, число (00..12)
%c | Месяц, число (0..12)
%b | Сокращенное наименование месяца (Янв...Дек)
%j | День года (001..366)
%H | Час (00..23)
%k | Час (0..23)
%h | Час (01..12)
%I | Час (01..12)
%l | Час (1..12)
%i | Минуты, число (00..59)
%r | Время, 12-часовой формат (hh:mm:ss [AP]M)
%T | Время, 24-часовой формат (hh:mm:ss)
%S | Секунды (00..59)
%s | Секунды (00..59)
%p | AM или PM
%w | День недели (0=воскресенье..6=суббота)
%U | Неделя (00..53), где воскресенье считается первым днем недели
%u | Неделя (00..53), где понедельник считается первым днем недели
%V | Неделя (01..53), где воскресенье считается первым днем недели. Используется с `%X'
%v | Неделя (01..53), где понедельник считается первым днем недели. Используется с `%x'
%% Литерал `%'.
Все другие символы просто копируются в результирующее выражение без интерпретации:
mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00', '%W %M %Y');
        -> 'Saturday October 1997'
mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00', '%H:%i:%s');
        -> '22:23:00'
mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00', '%D %y %a %d %m %b %j');
        -> '4th 97 Sat 04 10 Oct 277'
mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00', '%H %k %I %r %T %S %w');
        -> '22 22 10 10:23:00 PM 22:23:00 00 6'
mysql> SELECT DATE_FORMAT('1999-01-01', '%X %V');
        -> '1998 52'
В MySQL 3.23 символ `%' должен предшествовать символам определителя формата. В более ранних версиях MySQL символ `%' необязателен. Причина того, что промежутки для месяца и дня начинаются с нуля заключается в том, что MySQL позволяет использовать неполные даты, такие как '2004-00-00', начиная с MySQL 3.23.
TIME_FORMAT(time,format)
Данная функция используется аналогично описанной выше функции DATE_FORMAT(), но строка format может содержать только те определители формата, которые относятся к часам, минутам и секундам. При указании других определителей будет выдана величина NULL или 0.
CURDATE()
CURRENT_DATE
Возвращает сегодняшнюю дату как величину в формате YYYY-MM-DD или YYYYMMDD, в зависимости от того, в каком контексте используется функция - в строковом или числовом:
mysql> SELECT CURDATE();
        -> '1997-12-15'
mysql> SELECT CURDATE() + 0;
        -> 19971215
CURTIME()
CURRENT_TIME
Возвращает текущее время как величину в формате HH:MM:SS или HHMMS, в зависимости от того, в каком контексте используется функция - в строковом или числовом:
mysql> SELECT CURTIME();
        -> '23:50:26'
mysql> SELECT CURTIME() + 0;
        -> 235026
NOW()
SYSDATE()
CURRENT_TIMESTAMP
Возвращает текущую дату и время как величину в формате YYYY-MM-DD HH:MM:SS или YYYYMMDDHHMMSS, в зависимости от того, в каком контексте используется функция - в строковом или числовом:
mysql> SELECT NOW();
        -> '1997-12-15 23:50:26'
mysql> SELECT NOW() + 0;
        -> 19971215235026
Заметьте, что NOW() вычисляется только единожды для каждого запроса, а именно - в начале его выполнения. Это позволяет быть уверенным в том, что множественные ссылки на NOW() в рамках одного запроса дадут одно и то же значение.
UNIX_TIMESTAMP()
UNIX_TIMESTAMP(date)
При вызове данной функции без аргумента она возвращает временную метку UNIX_TIMESTAMP (секунды с 1970-01-01 00:00:00 GMT) как беззнаковое целое число. Если функция UNIX_TIMESTAMP() вызывается с аргументом date, она возвращает величину аргумента как количество секунд с 1970-01-01 00:00:00 GMT. Аргумент date может представлять собой строку типа DATE, строку DATETIME, величину типа TIMESTAMP или число в формате YYMMDD или YYYYMMDD местного времени:
mysql> SELECT UNIX_TIMESTAMP();
        -> 882226357

mysql> SELECT UNIX_TIMESTAMP('1997-10-04 22:23:00');
        -> 875996580
При использовании функции UNIX_TIMESTAMP в столбце TIMESTAMP эта функция будет возвращать величину внутренней временной метки непосредственно, без подразумеваемого преобразования строки во временную метку (``string-to-unix-timestamp'' ). Если заданная дата выходит за пределы допустимого диапазона, то функция UNIX_TIMESTAMP() возвратит 0, но следует учитывать, что выполняется только базовая проверка (год 1970-2037, месяц 01-12, день 01-31). Если необходимо выполнить вычитание столбцов UNIX_TIMESTAMP(), результат можно преобразовать к целым числам со знаком. See section 6.3.5 Функции приведения типов.
FROM_UNIXTIME(unix_timestamp)
Возвращает представление аргумента unix_timestamp как величину в формате YYYY-MM-DD HH:MM:SS или YYYYMMDDHHMMSS, в зависимости от того, в каком контексте используется функция - в строковом или числовом:
mysql> SELECT FROM_UNIXTIME(875996580);
        -> '1997-10-04 22:23:00'

mysql> SELECT FROM_UNIXTIME(875996580) + 0;
        -> 19971004222300
FROM_UNIXTIME(unix_timestamp,format)
Возвращает строковое представление аргумента unix_timestamp, отформатированное в соответствии со строкой format. Строка format может содержать те же определители, которые перечислены в описании для функции DATE_FORMAT():
mysql> SELECT FROM_UNIXTIME(UNIX_TIMESTAMP(), '%Y %D %M %h:%i:%s %x');
        -> '1997 23rd December 03:43:30 1997'
SEC_TO_TIME(seconds)
Возвращает аргумент seconds, преобразованный в часы, минуты и секунды, как величину в формате HH:MM:SS или HHMMSS, в зависимости от того, в каком контексте используется функция - в строковом или числовом:
mysql> SELECT SEC_TO_TIME(2378);
        -> '00:39:38'

mysql> SELECT SEC_TO_TIME(2378) + 0;
        -> 3938
TIME_TO_SEC(time)
Возвращает аргумент time, преобразованный в секунды:
mysql> SELECT TIME_TO_SEC('22:23:00');
        -> 80580

mysql> SELECT TIME_TO_SEC('00:39:38');
        -> 2378

6.3.5 Функции приведения типов

Функция CAST имеет следующий синтаксис:

CAST(expression AS type)

или

CONVERT(expression,type)

где аргумент type представляет один из типов:

  • BINARY
  • CHAR (Новшество в 4.0.6)
  • DATE
  • DATETIME
  • SIGNED {INTEGER}
  • TIME
  • UNSIGNED {INTEGER}

Функция CAST() соответствует синтаксису ANSI SQL99, а функция CONVERT() - синтаксису ODBC.

Данная функция приведения типов используется главным образом для создания столбца конкретного типа с помощью команды CREATE ... SELECT:

CREATE TABLE new_table SELECT CAST('2000-01-01' AS DATE);

Выражение CAST string AS BINARY эквивалентно BINARY string. CAST(expr AS CHAR считает что данное выражение есть строка в кодировке по умолчанию.

Для преобразования строки в числовую величину обычно не нужно ничего делать: просто используйте строку так, как будто это число:

mysql> SELECT 1+'1';
       -> 2

Если вы указываете номер в строковом контексте, номер будет автоматически преобразован к строке типа BINARY.

mysql> SELECT concat("hello you ",2);
       ->  "hello you 2"

MySQL поддерживает арифметические операции с 64-битовыми величинами - как со знаковыми, так и с беззнаковыми. Если используются числовые операции (такие как +) и один из операндов представлен в виде unsigned integer, то результат будет беззнаковым. Его можно переопределить, используя операторы приведения SIGNED и UNSIGNED, чтобы получить 64-битовое целое число со знаком или без знака соответственно.

mysql> SELECT CAST(1-2 AS UNSIGNED)
        -> 18446744073709551615

mysql> SELECT CAST(CAST(1-2 AS UNSIGNED) AS SIGNED);
        -> -1

Следует учитывать, что если один из операндов представлен величиной с плавающей точкой (в данном контексте DECIMAL() рассматривается как величина с плавающей точкой), результат также является величиной с плавающей точкой и не подчиняется вышеприведенному правилу приведения.

mysql> SELECT CAST(1 AS UNSIGNED) -2.0
        -> -1.0

Если в арифметической операции используется строка, то результат преобразуется в число с плавающей точкой.

Функции CAST() и CONVERT() были добавлены в MySQL 4.0.2.

В MySQL 4.0 была изменены правила обработки беззнаковых величин, чтобы обеспечить более полную поддержку величин типа BIGINT. Если код необходимо использовать и для MySQL 4.0, и для версии 3.23 (в которой функция CAST, скорее всего, не будет работать), то можно, применив следующий трюк, получить при вычитании двух беззнаковых целочисленных столбцов результат со знаком:

SELECT (unsigned_column_1+0.0)-(unsigned_column_2+0.0);

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

Если возникнут проблемы со столбцами типа UNSIGNED в старых приложениях MySQL при переносе их на MySQL 4.0, можно использовать параметр --sql-mode=NO_UNSIGNED_SUBTRACTION при запуске mysqld. Однако следует учитывать, что при этом теряется возможность эффективного использования столбцов типа UNSIGNED BIGINT.

6.3.6 Другие функции

6.3.6.1 Битовые функции

MySQL использует для двоичных операций 64-битовые величины BIGINT, следовательно, для двоичных операторов максимальный диапазон составляет 64 бита.

|
Побитовое ИЛИ
mysql> SELECT 29 | 15;
        -> 31
Результат является беззнаковым 64-битовым целым числом.
&
Побитовое И
mysql> SELECT 29 & 15;
        -> 13
Результат является беззнаковым 64-битовым целым числом.
^
Побитовый XOR (побитовое сложение по модулю 2)
mysql> SELECT 1 ^ 1;
        -> 0
mysql> SELECT 1 ^ 0;
        -> 1
mysql> SELECT 11 ^ 3;
        -> 8
Результат - беззнаковое 64-битное целое число. XOR был реализован в MySQL 4.0.2.
<<
Сдвиг числа двойной длины (BIGINT) влево:
mysql> SELECT 1 << 2;
        -> 4
Результат является беззнаковым 64-битовым целым числом.
>>
Сдвиг числа двойной длины (BIGINT) вправо:
mysql> SELECT 4 >> 2;
        -> 1
Результат является беззнаковым 64-битовым целым числом.
~
Инвертировать все биты:
mysql> SELECT 5 & ~1;
        -> 4
Результат является беззнаковым 64-битовым целым числом.
BIT_COUNT(N)
Возвращает число битов, указанное в аргументе N:
mysql> SELECT BIT_COUNT(29);
        -> 4

6.3.6.2 Разные функции

DATABASE()
Возвращает имя текущей базы данных:
mysql> SELECT DATABASE();
        -> 'test'
Если в данное время нет активной базы данных, то функция DATABASE() возвращает пустую строку.
USER()
SYSTEM_USER()
SESSION_USER()
Возвращает имя текущего активного пользователя MySQL:
mysql> SELECT USER();
        -> 'davida@localhost'
В версии MySQL 3.22.11 или более поздней данная функция включает в себя имя хоста клиента, а также имя пользователя. Можно извлечь часть, касающуюся только имени пользователя, приведенным ниже способом (проверяется, включает ли данная величина имя хоста):
mysql> SELECT SUBSTRING_INDEX(USER(),"@",1);
        -> 'davida'
CURRENT_USER()
Возвращает текущее имя пользователя, под которым пользователь аутентифицировался в текущей сессии:
mysql> SELECT USER();
        -> 'davida@localhost'
mysql> SELECT * FROM mysql.user;
        -> ERROR 1044: Access denied for user: '@localhost' to database 'mysql'
mysql> SELECT CURRENT_USER();
        -> '@localhost'
PASSWORD(str)
OLD_PASSWORD(str)
Создает строку "пароля" из простого текста в аргументе str. Именно эта функция используется в целях шифрования паролей MySQL для хранения в столбце Password в таблице привилегий user:
mysql> SELECT PASSWORD('badpwd');
        -> '7f84554057dd964b'
Шифрование, которое выполняет функция PASSWORD(), необратимо. Способ шифрования пароля, который используется функцией PASSWORD(), отличается от применяемого для шифрования паролей в Unix. Функция PASSWORD() используется в системе аутентификации в сервер MySQL, вам не следует использовать ее для ваших собственных приложений. С этой целью, лучше используйте функции MD5() и SHA1().
ENCRYPT(str[,salt])
Шифрует аргумент str, используя вызов системной функции кодирования crypt() из Unix. Аргумент salt должен быть строкой из двух символов (в версии MySQL 3.22.16 аргумент salt может содержать более двух символов):
mysql> SELECT ENCRYPT("hello");
        -> 'VxuFAJXVARROc'
Если функция crypt() в данной операционной системе недоступна, функция ENCRYPT() всегда возвращает NULL. Функция ENCRYPT() игнорирует все символы в аргументе str, за исключением первых восьми, по крайней мере в некоторых операционных системах - это определяется тем, как реализован системный вызов базовой функции crypt().
ENCODE(str,pass_str)
Шифрует str, используя аргумент pass_str как пароль. Для расшифровки результата следует использовать функцию DECODE(). Результат представляет собой двоичную строку той же длины, что и string. Для хранения результата в столбце следует использовать столбец типа BLOB.
DECODE(crypt_str,pass_str)
Расшифровывает зашифрованную строку crypt_str, используя аргумент pass_str как пароль. Аргумент crypt_str должен быть строкой, возвращаемой функцией ENCODE().
MD5(string)
Вычисляет 128-битовую контрольную сумму MD5 для аргумента string. Возвращаемая величина представляет собой 32-разрядное шестнадцатеричное число, которое может быть использовано, например, в качестве хеш-ключа:
mysql> SELECT MD5("testing");
        -> 'ae2b1fca515949e5d54fb22b8ed95575'
Это "RSA Data Security, Inc. MD5 Message-Digest Algorithm".
SHA1(string)
SHA(string)
Вычисляет 160-битовую контрольную сумму SHA1 для аргумента string, как описано в RFC 3174 (Secure Hash Algorithm). Возвращаемая величина представляет собой 40-разрядное шестнадцатеричное число или NULL (в том случае, если входной аргумент был равен NULL). Одно из возможных применений для этой функции - в качестве хеш-ключа. Можно ее использовать и как криптографически безопасную функцию для сохранения паролей.
mysql> SELECT SHA1("abc");
        -> 'a9993e364706816aba3e25717850c26c9cd0d89d'
Функция SHA1() была добавлена в версии 4.0.2, и может рассматриваться как более защищенный криптографически эквивалент функции MD5(). SHA() является синонимом для функции SHA1().
AES_ENCRYPT(string,key_string)
AES_DECRYPT(string,key_string)
Эти функции позволяют шифровать/дешифровать данные, используя официальный алгоритм AES (Advanced Encryption Standard) (предыдущее название - Rijndael). В нем применяется кодирование с 128-битовым ключом, однако при помощи патча к исходному коду длину ключа можно увеличить до 256 битов. В MySQL выбран 128-битовый ключ, поскольку он работает намного быстрее и обычно обеспечивает вполне достаточную защищенность. Входные аргументы могут быть любой длины. Если один из аргументов равен NULL, то результат этой функции также будет иметь значение NULL. Так как AES является алгоритмом блочного уровня, то для декодирования используется дополнение строк нечетной длины, так, чтобы длина результирующей строки могла вычисляться как выражение 16*(trunc(длина_строки/16)+1). Если AES_DECRYPT() обнаруживает некорректные данные или некорректное заполнение строки (имеет в виду padding - прим. пер.), функция вернет NULL. Однако AES_DECRYPT() вполне может вернуть не-NULL величину, или, возможно, просто мусор, если входные данных или ключ - некорректны. AES_DECRYPT() имеет также модификацию, возвращающую величину со значением, не равным NULL, даже при неправильном ключе. Функции AES можно использовать для хранения данных в зашифрованном виде путем модификации запросов:
INSERT INTO t VALUES (1,AES_ENCRYPT("text","password"));
Можно добиться еще более высокого уровня защищенности за счет исключения передачи ключа через соединение для каждого запроса - для этого ключ на время соединения должен сохраняться в переменной на сервере:
SELECT @password:="my password";
INSERT INTO t VALUES (1,AES_ENCRYPT("text",@password));
Функции AES_ENCRYPT() и AES_DECRYPT() были добавлены в версию 4.0.2 и могут рассматриваться как наиболее криптографически защищенные шифрующие функции, в настоящее время доступные в MySQL.
DES_ENCRYPT(string_to_encrypt [, (key_number | key_string) ] )
Шифрует строку с заданным ключом, используя алгоритм тройного DES. Следует учитывать, что эта функция работает только тогда, когда конфигурация MySQL поддерживает SSL. See section 4.3.9 Использование безопасных соединений. Ключ для использования при шифровании выбирается следующим образом:
Аргумент | Описание
Только один аргумент | Используется первый ключ из des-key-file
Номер ключа | Используется заданный ключ (0-9) из des-key-file
Строка | Для шифрования string_to_encrypt может использоваться ключ, заданный в key_string
Функция возвращает двоичную строку, в которой первый символ будет CHAR(128 | key_number). Число 128 добавлено для упрощения распознавания зашифрованного ключа. При использовании строкового ключа key_number будет равен 127. При ошибке эта функция возвращает NULL. Длина строки в результате будет равна new_length=org_length + (8-(org_length % 8))+1. Выражение des-key-file имеет следующий форматt:
key_number des_key_string
key_number des_key_string
Каждый элемент key_number должен быть числом от 0 до 9. Строки в данном файле могут располагаться в произвольном порядке. Выражение des_key_string представляет собой строку, которая будет использована при шифровании сообщения. Между числом и ключом должен быть по крайней мере один пробел. Первый ключ используется по умолчанию, если не задан какой-либо аргумент ключа в функции DES_ENCRYPT(). Существует возможность послать MySQL запрос на чтение новых значений ключей из файла ключей при помощи команды FLUSH DES_KEY_FILE. Эта операция требует наличия привилегии Reload_priv. Одно из преимуществ наличия набора ключей по умолчанию состоит в том, что приложения могут проверять существование зашифрованных величин в столбцах без предоставления конечному пользователю права расшифровки этих величин.
mysql> SELECT customer_address FROM customer_table WHERE
        crypted_credit_card = DES_ENCRYPT("credit_card_number");
DES_DECRYPT(string_to_decrypt [, key_string])
Дешифрует строку, зашифрованную с помощью функции DES_ENCRYPT(). Следует учитывать, что эта функция работает только тогда, когда конфигурация MySQL поддерживает SSL. See section 4.3.9 Использование безопасных соединений. Если аргумент key_string не задан, то функция DES_DECRYPT() проверяет первый байт зашифрованной строки для определения номера ключа алгоритма DES, использованного для шифрования исходной строки, Затем читает ключ из des-key-file для расшифровки сообщения. Чтобы выполнить это, пользователь должен обладать привилегией SUPER. При указании значения аргумента в key_string эта строка используется как ключ для дешифровки сообщения. Если строка string_to_decrypt не выглядит как зашифрованная, то MySQL вернет заданную строку string_to_decrypt. При ошибке эта функция возвращает NULL.
LAST_INSERT_ID([expr])
Возвращает последнюю автоматически сгенерированную величину, которая была внесена в столбец AUTO_INCREMENT. See section 8.4.3.31 mysql_insert_id().
mysql> SELECT LAST_INSERT_ID();
        -> 195
Значение последнего сгенерированного ID сохраняется на сервере для данного конкретного соединения и не будет изменено другим клиентом. Оно не будет изменено даже при обновлении другого столбца AUTO_INCREMENT конкретной величиной (то есть, которая не равна NULL и не равна 0). При внесении большого количества строк с помощью одной команды INSERT функция LAST_INSERT_ID() возвращает значение для первой внесенной строки. Причина этого заключается в том, что можно легко воспроизвести точно такую же команду INSERT на другом сервере. Если задано значение аргумента expr в функции LAST_INSERT_ID(), то величина аргумента возвращается функцией и устанавливается в качестве следующего значения, которое будет возвращено функцией LAST_INSERT_ID(). Это можно использовать для моделирования последовательностей: Вначале создается таблица:
mysql> CREATE TABLE sequence (id INT NOT NULL);
mysql> INSERT INTO sequence VALUES (0);
Затем данную таблицу можно использовать для генерации чисел последовательности как показано ниже:
mysql> UPDATE sequence SET id=LAST_INSERT_ID(id+1);
Можно генерировать последовательности без вызова LAST_INSERT_ID(): полезность применения данной функции состоит в том, что данное значение ID поддерживается на сервере как последняя автоматически сгенерированная величина (защищенная от других пользователей), и вы можете извлекать новый ID так же, как и любое другое нормальное значение AUTO_INCREMENT в MySQL. Например, функция LAST_INSERT_ID() (без аргумента) возвратит новое значение ID. Функцию C API mysql_insert_id() также можно использовать для получения этой величины. Следует учитывать, что, поскольку функция mysql_insert_id() обновляется только после команд INSERT и UPDATE, то нельзя использовать эту функцию C API для извлечения значения ID для LAST_INSERT_ID(expr) после выполнения других команд SQL, таких как SELECT или SET.
FORMAT(X,D)
Форматирует число X в формат вида '#,###,###.##' с округлением до D десятичных знаков. Если D равно 0, результат будет представлен без десятичной точки или дробной части:
mysql> SELECT FORMAT(12332.123456, 4);
        -> '12,332.1235'

mysql> SELECT FORMAT(12332.1,4);
        -> '12,332.1000'

mysql> SELECT FORMAT(12332.2,0);
        -> '12,332'
VERSION()
Возвращает строку с номером версии сервера MySQL:
mysql> SELECT VERSION();
        -> '3.23.13-log'
Следует учитывать, что если данная версия заканчивается с -log, то это означает, что включено ведение журналов.
CONNECTION_ID()
Возвращает идентификатор (thread_id) для данного соединения. Каждое соединение имеет свой собственный уникальный идентификатор:
mysql> SELECT CONNECTION_ID();
        -> 1
GET_LOCK(str,timeout)
Пытается осуществить блокировку по имени, которое заданно в строке str, с временем ожидания в секундах, указанном в аргументе timeout. Возвращает 1, если блокировка осуществлена успешно, 0 - если закончилось время ожидания для данной попытки, или NULL, если возникла ошибка (такая как отсутствие свободной памяти или уничтожение потока командой mysqladmin kill). Блокировка снимается при выполнении команды RELEASE_LOCK(), запуске новой команды GET_LOCK() или при завершении данного потока. Эту функцию можно использовать для осуществления блокировок уровня приложения или для моделирования блокировки записи. Функция блокирует запросы других клиентов на блокировку с тем же именем; клиенты, которые используют согласованные имена блокировок, могут применять эту функцию для выполнения совместного упредительного блокирования:
mysql> SELECT GET_LOCK("lock1",10);
        -> 1
mysql> SELECT IS_FREE_LOCK("lock2");
        -> 1
mysql> SELECT GET_LOCK("lock2",10);
        -> 1
mysql> SELECT RELEASE_LOCK("lock2");
        -> 1
mysql> SELECT RELEASE_LOCK("lock1");
        -> NULL
Обратите внимание: повторный вызов функции RELEASE_LOCK() возвращает NULL, поскольку блокировка lock1 была автоматически выполнена вторым вызовом функции GET_LOCK().
RELEASE_LOCK(str)
Снимает блокировку, указанную в строке str, полученной от функции GET_LOCK(). Возвращает 1 если блокировка была снята, 0 - если такая блокировка уже поставлена в другом соединении (в этом случае блокировка не снимается) и NULL, если блокировки с указанным именем не существует. Последнее может произойти в случае, когда вызов функции GET_LOCK() не привел к успешному результату или данная блокировка уже снята. Функцию RELEASE_LOCK() удобно использовать совместно с командой DO. See section 6.4.10 Синтаксис оператора DO.
IS_FREE_LOCK(str)
Проверяет, свободна ли блокировка по имени str (т.е. не установлена). Возвращает 1 если блокировка свободна (никто не поставил таковую). Возвращает 0 если блокировка установлена и NULL в случае ошибки (например, при неправильных аргументах).
BENCHMARK(count,expr)
Функция BENCHMARK() повторяет выполнение выражения expr заданное количество раз, указанное в аргументе count. Она может использоваться для определения того, насколько быстро MySQL обрабатывает данное выражение. Значение результата всегда равно 0. Функция предназначена для использования в клиенте mysql, который сообщает о времени выполнения запроса:
mysql> SELECT BENCHMARK(1000000,ENCODE("hello","goodbye"));
+----------------------------------------------+
| BENCHMARK(1000000,ENCODE("hello","goodbye")) |
+----------------------------------------------+
|                                            0 |
+----------------------------------------------+
1 row in set (4.74 sec)
Указанное в отчете время представляет собой время, подсчитанное на стороне клиента, а не время, затраченное центральным процессором (CPU time) на сервере. Может оказаться целесообразным выполнить BENCHMARK() несколько раз, чтобы выяснить, насколько интенсивно загружен серверный компьютер.
INET_NTOA(expr)
По заданному числовому адресу сети (4 или 8 байтов) возвращает представление указанного адреса в виде разделенных точками четырех октетов в виде строки:
mysql> SELECT INET_NTOA(3520061480);
        -> "209.207.224.40"
INET_ATON(expr)
По заданному представлению сетевого адреса в виде строки, содержащей разделенные точками четыре октета, функция возвращает целое число, представляющее собой числовое значение данного адреса. Адреса могут быть длиной 4 или 8 байтов:
mysql> SELECT INET_ATON("209.207.224.40");
        -> 3520061480
Результирующее число всегда генерируется в соответствии с порядком расположения октетов в сетевом адресе, например вышеприведенное число вычисляется как 209*256^3 + 207*256^2 + 224*256 +40.
MASTER_POS_WAIT(log_name, log_pos)
Блокируется, пока подчиненный сервер не достигнет определенной точки положения в журнале репликации головного сервера (т.е. не прочитает и не выполнит все операции до указанной позиции). Если информация головного сервера не инициализирована, или аргументы неправильны, то функция возвращает NULL. Если подчиненный сервер не работает, то функция блокируется и ожидает, пока сервер запустится и дойдет до указанной позиции или пройдет через нее. Если подчиненный сервер уже прошел указанную точку, то функция немедленно возвращает результат. Если timeout (новшество в 4.0.10) указан, то ожидание прекратится по прошествии timeout секунд. Таймаут должен быть больше 0. 0 или негативный таймаут означает тоже самое что и отсутствие таймаута. Возвращаемая величина представляет собой число событий в журнале, которые функция должна была ``переждать'', пока сервер дойдет до указанной точки, NULL в случае ошибки или -1 в случае, если истек таймаут.
FOUND_ROWS()
Возвращает количество строк, которые возвратила бы последняя команда SELECT SQL_CALC_FOUND_ROWS ... при отсутствии ограничения оператором LIMIT.
mysql> SELECT SQL_CALC_FOUND_ROWS * FROM tbl_name WHERE id > 100 LIMIT 10;
mysql> SELECT FOUND_ROWS();
Второй вызов команды SELECT возвратит количество строк, которые возвратила бы первая команда SELECT, если бы она была написана без выражения LIMIT. Отметим, что, хотя при использовании команды SELECT SQL_CALC_FOUND_ROWS ..., MySQL должен пересчитать все строки в наборе результатов, этот способ все равно быстрее, чем без LIMIT, так как не требуется посылать результат клиенту. Функция SQL_CALC_FOUND_ROWS появилась в MySQL 4.0.0.

6.3.7 Функции, используемые в операторах GROUP BY

Вызов групповых функций для SQL-команд, не содержащих GROUP BY, эквивалентен выполнению этих функций над всем набором возвращаемых данных.

COUNT(expr)
Возвращает количество величин со значением, не равным NULL, в строках, полученных при помощи команды SELECT:
mysql> SELECT student.student_name,COUNT(*) FROM student,course
        WHERE student.student_id=course.student_id
        GROUP BY student_name;
Функция COUNT(*) несколько отличается от описанной выше: она возвращает количество извлеченных строк, содержащих величины со значением NULL. COUNT(*) оптимизирована для очень быстрого возврата результата при условии, что команда SELECT извлекает данные из одной таблицы, никакие другие столбцы не обрабатываются и функция не содержит выражения WHERE. Например:
mysql> SELECT COUNT(*) FROM student;
COUNT(DISTINCT expr,[expr...])
Возвращает количество различающихся величин со значением, не равным NULL:
mysql> SELECT COUNT(DISTINCT results) FROM student;
В MySQL для того, чтобы получить количество различающихся комбинаций выражений, не содержащих NULL, нужно просто задать список этих выражений. В ANSI SQL необходимо провести конкатенацию всех выражений внутри COUNT(DISTINCT ...).
AVG(expr)
Возвращает среднее значение аргумента expr:
mysql> SELECT student_name, AVG(test_score)
        FROM student
        GROUP BY student_name;
MIN(expr)
MAX(expr)
Возвращает минимальную или максимальную величину аргумента expr. Функции MIN() и MAX() могут принимать строковый аргумент; в таких случаях они возвращают минимальную или максимальную строковую величину. See section 5.4.3 Использование индексов в MySQL.
mysql> SELECT student_name, MIN(test_score), MAX(test_score)
        FROM student
        GROUP BY student_name;
В MIN(), MAX() и других групповых фунциях MySQL сейчас сравнивает ENUM и SET-столбцы по ихнему строковому представлению а не по относительной позиции строки в множестве. Это будет исправлено.
SUM(expr)
Возвращает сумму величин в аргументе expr. Обратите внимание: если возвращаемый набор данных не содержит ни одной строки, то функция возвращает NULL!
VARIANCE(expr)
Возвращает вариант стандарта, которому соответствует expr. Это - расширение по сравнению с ANSI SQL, доступное только в 4.1 или более поздних версиях.
STD(expr)
STDDEV(expr)
Возвращает среднеквадратичное отклонение значения в аргументе expr. Эта функция является расширением ANSI SQL. Форма STDDEV() обеспечивает совместимость с Oracle.
BIT_OR(expr)
Возвращает побитовое ИЛИ для всех битов в expr. Вычисление производится с 64-битовой (BIGINT) точностью.
BIT_AND(expr)
Возвращает побитовое И для всех битов в expr. Вычисление производится с 64-битовой (BIGINT) точностью.

В MySQL расширены возможности использования оператора GROUP BY. Теперь в выражениях SELECT можно использовать столбцы или вычисления, которые не присутствуют в части GROUP BY. Это справедливо для любой возможной величины для этой группы. Данная возможность позволяет повысить производительность за счет исключения сортировки и группирования ненужных величин. Например, в следующем запросе нет необходимости в группировке customer.name:

mysql> SELECT order.custid,customer.name,MAX(payments)
        FROM order,customer
        WHERE order.custid = customer.custid
        GROUP BY order.custid;

В ANSI SQL к предложению GROUP BY необходимо добавлять customer.name. В MySQL, если работа происходит не в режиме ANSI, это имя избыточно.

Не используйте данное свойство, если столбцы, пропущенные в части GROUP BY, не являются уникальными в данной группе! Возможны непредсказуемые результаты.

В некоторых случаях можно применять функции MIN() и MAX() для получения указанной величины столбца, даже если он не является уникальным. В следующем примере выдается значение столбца column из строки, содержащей наименьшую величину в столбце sort:

SUBSTR(MIN(CONCAT(RPAD(sort,6,' '),column)),7)

See section 3.5.4 Строка, содержащая максимальное значение некоторого столбца.

Следует отметить, что в версии MySQL 3.22 (или более ранней) либо при попытке работы в рамках ANSI SQL применение выражений в предложениях GROUP BY или ORDER BY невозможно. Это ограничение можно обойти, используя для выражения псевдоним:

mysql> SELECT id,FLOOR(value/100) AS val FROM tbl_name
        GROUP BY id,val ORDER BY val;

В версии MySQL 3.23 можно также выполнить следующее:

mysql> SELECT id,FLOOR(value/100) FROM tbl_name ORDER BY RAND();

6.4 Обработка данных: SELECT, INSERT, UPDATE, DELETE

6.4.1 Синтаксис оператора SELECT

Оператор SELECT имеет следующую структуру:

SELECT [STRAIGHT_JOIN]
       [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]
       [SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS] [HIGH_PRIORITY]
       [DISTINCT | DISTINCTROW | ALL]
    select_expression,...
    [INTO {OUTFILE | DUMPFILE} 'file_name' export_options]
    [FROM table_references
      [WHERE where_definition]
      [GROUP BY {unsigned_integer | col_name | formula} [ASC | DESC], ...]
      [HAVING where_definition]
      [ORDER BY {unsigned_integer | col_name | formula} [ASC | DESC], ...]
      [LIMIT [offset,] rows | rows OFFSET offset]
      [PROCEDURE procedure_name(argument_list)]
      [FOR UPDATE | LOCK IN SHARE MODE]]

SELECT применяется для извлечения строк, выбранных из одной или нескольких таблиц. Выражение select_expression задает столбцы, в которых необходимо проводить выборку. Кроме того, оператор SELECT можно использовать для извлечения строк, вычисленных без ссылки на какую-либо таблицу. Например:

mysql> SELECT 1 + 1;
        -> 2

При указании ключевых слов следует точно соблюдать порядок, указанный выше. Например, выражение HAVING должно располагаться после всех выражений GROUP BY и перед всеми выражениями ORDER BY.

  • Используя ключевое слово AS, выражению в SELECT можно присвоить псевдоним. Псевдоним используется в качестве имени столбца в данном выражении и может применяться в ORDER BY или HAVING. Например:
    mysql> SELECT CONCAT(last_name,', ',first_name) AS full_name
        FROM mytable ORDER BY full_name;
  • Псевдонимы столбцов нельзя использовать в выражении WHERE, поскольку находящиеся в столбцах величины на момент выполнения WHERE могут быть еще не определены. See section A.5.4 Проблемы с alias.
  • Выражение FROM table_references задает таблицы, из которых надлежит извлекать строки. Если указано имя более чем одной таблицы, следует выполнить объединение. Информацию о синтаксисе объединения можно найти в разделе section 6.4.1.1 Синтаксис оператора JOIN. Для каждой заданной таблицы по желанию можно указать псевдоним.
    table_name [[AS] alias] [[USE INDEX (key_list)] | [IGNORE INDEX (key_list)] | FORCE INDEX (key_list)]]
    В версии MySQL 3.23.12 можно указывать, какие именно индексы (ключи) MySQL должен применять для извлечения информации из таблицы. Это полезно, если оператор EXPLAIN (выводящий информацию о структуре и порядке выполнения запроса SELECT), показывает, что MySQL из списка возможных индексов выбрал неправильный. Если нужно. чтобы для поиска записи в таблице применялся только один из возможных индексов, следует задать значение этого индекса в USE INDEX (key_list). Альтернативное выражение IGNORE INDEX (key_list) запрещает использование в MySQL данного конкретного индекса. В MySQL 4.0.9 можно также указывать FORCE INDEX. Это работает также, как и USE INDEX (key_list) но в дополнение дает понять серверу что полное сканирование таблицы будет ОЧЕНЬ дорогостоящей операцией. Другими словами, в этом случае сканирование таблицы будет использовано только тогда, когда не будет найдено другого способа использовать один из данных индексов для поиска записей в таблице. Выражения USE/IGNORE KEY являются синонимами для USE/IGNORE INDEX.
  • Ссылки на таблицы могут даваться как tbl_name (в рамках текущей базы данных), или как dbname.tbl_name с тем, чтобы четко указать базу данных. Ссылки на столбцы могут задаваться в виде col_name, tbl_name.col_name или db_name.tbl_name.col_name. В выражениях tbl_name или db_name.tbl_name нет необходимости указывать префикс для ссылок на столбцы в команде SELECT, если эти ссылки нельзя истолковать неоднозначно. See section 6.1.2 Имена баз данных, таблиц, столбцов, индексы псевдонимы, где приведены примеры неоднозначных случаев, для которых требуются более четкие определения ссылок на столбцы.
  • Ссылку на таблицу можно заменить псевдонимом, используя tbl_name [AS] alias_name:
    mysql> SELECT t1.name, t2.salary FROM employee AS t1, info AS t2
        WHERE t1.name = t2.name;

mysql> SELECT t1.name, t2.salary FROM employee t1, info t2
        WHERE t1.name = t2.name;
  • В выражениях ORDER BY и GROUP BY для ссылок на столбцы, выбранные для вывода информации, можно использовать либо имена столбцов, либо их псевдонимы, либо их позиции (местоположения). Нумерация позиций столбцов начинается с 1:
    mysql> SELECT college, region, seed FROM tournament
        ORDER BY region, seed;

mysql> SELECT college, region AS r, seed AS s FROM tournament
        ORDER BY r, s;

mysql> SELECT college, region, seed FROM tournament
        ORDER  BY 2, 3;
    Для того чтобы сортировка производилась в обратном порядке, в утверждении ORDER BY к имени заданного столбца, в котором производится сортировка, следует добавить ключевое слово DESC (убывающий). По умолчанию принята сортировка в возрастающем порядке, который можно задать явно при помощи ключевого слова ASC.
  • В выражении WHERE можно использовать любую из функций, которая поддерживается в MySQL. See section 6.3 Функции, используемые в операторах SELECT и WHERE. Выражение HAVING может ссылаться на любой столбец или псевдоним, упомянутый в выражении select_expression. HAVING отрабатывается последним, непосредственно перед отсылкой данных клиенту, и без какой бы то ни было оптимизации. Не используйте это выражение для определения того, что должно быть определено в WHERE. Например, нельзя задать следующий оператор:
    mysql> SELECT col_name FROM tbl_name HAVING col_name > 0;
    Вместо этого следует задавать:
    mysql> SELECT col_name FROM tbl_name WHERE col_name > 0;
    В версии MySQL 3.22.5 или более поздней можно также писать запросы, как показано ниже:
    mysql> SELECT user,MAX(salary) FROM users
        GROUP BY user HAVING MAX(salary)>10;
    В более старых версиях MySQL вместо этого можно указывать:
    mysql> SELECT user,MAX(salary) AS sum FROM users
        GROUP BY user HAVING sum>10;
  • Параметры (опции) DISTINCT, DISTINCTROW и ALL указывают, должны ли возвращаться дублирующиеся записи. По умолчанию установлен параметр (ALL), т.е. возвращаются все встречающиеся строки. DISTINCT и DISTINCTROW являются синонимами и указывают, что дублирующиеся строки в результирующем наборе данных должны быть удалены.
  • Все параметры, начинающиеся с SQL_, STRAIGHT_JOIN и HIGH_PRIORITY, представляют собой расширение MySQL для ANSI SQL.
  • При указании параметра HIGH_PRIORITY содержащий его оператор SELECT будет иметь более высокий приоритет, чем команда обновления таблицы. Нужно только использовать этот параметр с запросами, которые должны выполняться очень быстро и сразу. Если таблица заблокирована для чтения, то запрос SELECT HIGH_PRIORITY будет выполняться даже при наличии команды обновления, ожидающей, пока таблица освободится.
  • Параметр SQL_BIG_RESULT можно использовать с GROUP BY или DISTINCT, чтобы сообщить оптимизатору, что результат будет содержать большое количество строк. Если указан этот параметр, MySQL при необходимости будет непосредственно использовать временные таблицы на диске, однако предпочтение будет отдаваться не созданию временной таблицы с ключом по элементам GROUP BY, а сортировке данных.
  • При указании параметра SQL_BUFFER_RESULT MySQL будет заносить результат во временную таблицу. Таким образом MySQL получает возможность раньше снять блокировку таблицы; это полезно также для случаев, когда для посылки результата клиенту требуется значительное время.
  • Параметр SQL_SMALL_RESULT является опцией, специфической для MySQL. Данный параметр можно использовать с GROUP BY или DISTINCT, чтобы сообщить оптимизатору, что результирующий набор данных будет небольшим. В этом случае MySQL для хранения результирующей таблицы вместо сортировки будет использовать быстрые временные таблицы. В версии MySQL 3.23 указывать данный параметр обычно нет необходимости.
  • Параметр SQL_CALC_FOUND_ROWS (MySQL 4.0.0 и более новый) возвращает количество строк, которые вернул бы оператор SELECT, если бы не был указан LIMIT. Искомое количество строк можно получить при помощи SELECT FOUND_ROWS(). See section 6.3.6.2 Разные функции. Заметьте, что в версиях MySQL до 4.1.0 это не работает с LIMIT 0, который оптимизирован для того, чтобы немедленно вернуть нулевой результат. See section 5.2.8 Как MySQL оптимизирует LIMIT.
  • Параметр SQL_CACHE предписывает MySQL сохранять результат запроса в кэше запросов при использовании QUERY_CACHE_TYPE=2 (DEMAND). See section 6.9 Кэш запросов в MySQL.
  • Параметр SQL_NO_CACHE запрещает MySQL хранить результат запроса в кэше запросов. See section 6.9 Кэш запросов в MySQL.
  • При использовании выражения GROUP BY строки вывода будут сортироваться в соответствии с порядком, заданным в GROUP BY, - так, как если бы применялось выражение ORDER BY для всех полей, указанных в GROUP BY. В MySQL выражение GROUP BY расширено таким образом, что для него можно также указывать параметры ASC и DESC:
    SELECT a,COUNT(b) FROM test_table GROUP BY a DESC
  • Расширенный оператор GROUP BY в MySQL обеспечивает, в частности, возможность выбора полей, не упомянутых в выражении GROUP BY. Если ваш запрос не приносит ожидаемых результатов, прочтите, пожалуйста, описание GROUP BY. See section 6.3.7 Функции, используемые в операторах GROUP BY.
  • При указании параметра STRAIGHT_JOIN оптимизатор будет объединять таблицы в том порядке, в котором они перечислены в выражении FROM. Применение данного параметра позволяет увеличить скорость выполнения запроса, если оптимизатор производит объединение таблиц неоптимальным образом. See section 5.2.1 Синтаксис оператора EXPLAIN (получение информации о SELECT).
  • Выражение LIMIT может использоваться для ограничения количества строк, возвращенных командой SELECT. LIMIT принимает один или два числовых аргумента. Эти аргументы должны быть целочисленными константами. Если заданы два аргумента, то первый указывает на начало первой возвращаемой строки, а второй задает максимальное количество возвращаемых строк. При этом смещение начальной строки равно 0 (не 1): Для совместимости с PostgreSQL MySQL также поддерживает синтаксис LIMIT # OFFSET #.
    mysql> SELECT * FROM table LIMIT 5,10; # возвращает строки 6-15
    Для того, чтобы выбрать все строки с определенного смещения и до конца результата, вы можете использовать значение -1 в качестве второго параметра:
    mysql> SELECT * FROM table LIMIT 95,-1; # Retrieve rows 96-last.
    Если задан один аргумент, то он показывает максимальное количество возвращаемых строк:
    mysql> SELECT * FROM table LIMIT 5; # возвращает первых 5 строк
    Другими словами, LIMIT n эквивалентно LIMIT 0,n.
  • Оператор SELECT может быть представлен в форме SELECT ... INTO OUTFILE 'file_name'. Эта разновидность команды осуществляет запись выбранных строк в файл, указанный в file_name. Данный файл создается на сервере и до этого не должен существовать (таким образом, помимо прочего, предотвращается разрушение таблиц и файлов, таких как `/etc/passwd'). Для использования этой формы команды SELECT необходимы привилегии FILE. Форма SELECT ... INTO OUTFILE главным образом предназначена для выполнения очень быстрого дампа таблицы на серверном компьютере. Команду SELECT ... INTO OUTFILE нельзя применять, если необходимо создать результирующий файл на ином хосте, отличном от серверного. В таком случае для генерации нужного файла вместо этой команды следует использовать некоторую клиентскую программу наподобие mysqldump --tab или mysql -e "SELECT ..." > outfile. Команда SELECT ... INTO OUTFILE является дополнительной по отношению к LOAD DATA INFILE; синтаксис части export_options этой команды содержит те же выражения FIELDS и LINES, которые используются в команде LOAD DATA INFILE. See section 6.4.9 Синтаксис оператора LOAD DATA INFILE. Следует учитывать, что в результирующем текстовом файле оператор ESCAPED BY экранирует только следующие символы:
    • Символ оператора ESCAPED BY
    • Первый символ оператора FIELDS TERMINATED BY
    • Первый символ оператора LINES TERMINATED BY
    Помимо этого ASCII-символ 0 конвертируется в ESCAPED BY, за которым следует символ `0' (ASCII 48). Это делается потому, что необходимо экранировать любые символы операторов FIELDS TERMINATED BY, ESCAPED BY или LINES TERMINATED BY, чтобы иметь надежную возможность повторить чтение этого файла. ASCII 0 экранируется, чтобы облегчить просмотр файла с помощью программ вывода типа pager. Поскольку результирующий файл не должен удовлетворять синтаксису SQL, нет необходимости экранировать что-либо еще. Ниже приведен пример того, как получить файл в формате, который используется многими старыми программами.
    SELECT a,b,a+b INTO OUTFILE "/tmp/result.text"
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY "\n"
FROM test_table;
  • Если вместо INTO OUTFILE использовать INTO DUMPFILE, то MySQL запишет в файл только одну строку без символов завершения столбцов или строк и без какого бы то ни было экранирования. Это полезно для хранения данных типа BLOB в файле.
  • Следует учитывать, что любой файл, созданный с помощью INTO OUTFILE и INTO DUMPFILE, будет доступен для записи всем пользователям! Причина этого заключается в следующем: сервер MySQL не может создавать файл, принадлежащий только какому-либо текущему пользователю (вы никогда не можете запустить mysqld от пользователя root), соответственно, файл должен быть доступен для записи всем пользователям. При использовании FOR UPDATE с обработчиком таблиц, поддерживающим блокировку страниц/строк, выбранные строки будут заблокированы для записи.

6.4.1.1 Синтаксис оператора JOIN

MySQL поддерживает следующий синтаксис оператора JOIN при использовании в командах SELECT:

table_reference, table_reference
table_reference [CROSS] JOIN table_reference
table_reference INNER JOIN table_reference join_condition
table_reference STRAIGHT_JOIN table_reference
table_reference LEFT [OUTER] JOIN table_reference join_condition
table_reference LEFT [OUTER] JOIN table_reference
table_reference NATURAL [LEFT [OUTER]] JOIN table_reference
{ OJ table_reference LEFT OUTER JOIN table_reference ON conditional_expr }
table_reference RIGHT [OUTER] JOIN table_reference join_condition
table_reference RIGHT [OUTER] JOIN table_reference
table_reference NATURAL [RIGHT [OUTER]] JOIN table_reference

где table_reference определено, как:

table_name [[AS] alias] [[USE INDEX (key_list)] | [IGNORE INDEX (key_list)] | [FORCE INDEX (key_list)]]

и join_condition определено, как:

ON conditional_expr |
USING (column_list)

В большинстве случаев не следует указывать в части ON какие бы то ни было условия, накладывающие ограничения на строки в наборе результатов (из этого правила есть исключения). Если необходимо указать, какие строки должны присутствовать в результате, следует сделать это в выражении WHERE.

Необходимо учитывать, что в версиях до 3.23.17 оператор INNER JOIN не принимает параметр join_condition!

Наличие последней из приведенных выше конструкций выражения LEFT OUTER JOIN обусловлено только требованиями совместимости с ODBC:

  • Вместо ссылки на таблицу может использоваться псевдоним, который присваивается при помощи выражений tbl_name AS alias_name или tbl_name alias_name:
    mysql> SELECT t1.name, t2.salary FROM employee AS t1, info AS t2
        WHERE t1.name = t2.name;
  • Условный оператор ON представляет собой условие в любой форме из числа тех, которые можно использовать в выражении WHERE.
  • Если запись для правой таблицы в частях ON или USING в LEFT JOIN не найдена, то для данной таблицы используется строка, в которой все столбцы установлены в NULL. Эту возможность можно применять для нахождения результатов в таблице, не имеющей эквивалента в другой таблице:
    mysql> SELECT table1.* FROM table1
        LEFT JOIN table2 ON table1.id=table2.id
        WHERE table2.id IS NULL;
    Этот пример находит все строки в таблице table1 с величиной id, которая не присутствует в таблице table2 (т.е. все строки в table1, для которых нет соответствующих строк в table2). Конечно, это предполагает, что table2.id объявлен как NOT NULL. See section 5.2.6 Как MySQL оптимизирует LEFT JOIN и RIGHT JOIN.
  • USING (column_list) служит для указания списка столбцов, которые должны существовать в обеих таблицах. Такое выражение USING, как:
    A LEFT JOIN B USING (C1,C2,C3,...)
    семантически идентично выражению ON, например:
    A.C1=B.C1 AND A.C2=B.C2 AND A.C3=B.C3,...
  • Выражение NATURAL [LEFT] JOIN для двух таблиц определяется так, чтобы оно являлось семантическим эквивалентом INNER JOIN или LEFT JOIN с выражением USING, в котором указаны все столбцы, имеющиеся в обеих таблицах.
  • INNER JOIN и , (запятая) являются семантическими эквивалентами. Оба осуществляют полное объединение используемых таблиц. Способ связывания таблиц обычно задается в условии WHERE.
  • RIGHT JOIN работает аналогично LEFT JOIN. Для сохранения переносимости кода между различными базами данных рекомендуется вместо RIGHT JOIN использовать LEFT JOIN.
  • STRAIGHT_JOIN идентично JOIN, за исключением того, что левая таблица всегда читается раньше правой. Это выражение может использоваться для тех (немногих) случаев, когда оптимизатор объединения располагает таблицы в неправильном порядке.
  • Начиная с версии MySQL 3.23.12, можно давать MySQL указания о том, какой индекс должен использоваться при извлечении информации из таблицы. Эта возможность полезна, если оператор EXPLAIN показывает, что MySQL из всех возможных индексов использует ошибочный. Задавая значение индекса в USE INDEX (key_list), можно заставить MySQL применять для поиска записи только один из возможных индексов. Альтернативное выражение IGNORE INDEX (key_list) запрещает использование в MySQL данного конкретного индекса. Выражения USE/IGNORE KEY являются синонимами для USE/IGNORE INDEX. В MySQL 4.0.9 можно также указывать FORCE INDEX. Это работает также, как и USE INDEX (key_list) но в дополнение дает понять серверу что полное сканирование таблицы будет ОЧЕНЬ дорогостоящей операцией. Другими словами, в этом случае сканирование таблицы будет использовано только тогда, когда не будет найдено другого способа использовать один из данных индексов для поиска записей в таблице.

Несколько примеров:

mysql> SELECT * FROM table1,table2 WHERE table1.id=table2.id;
mysql> SELECT * FROM table1 LEFT JOIN table2 ON table1.id=table2.id;
mysql> SELECT * FROM table1 LEFT JOIN table2 USING (id);
mysql> SELECT * FROM table1 LEFT JOIN table2 ON table1.id=table2.id
       LEFT JOIN table3 ON table2.id=table3.id;
mysql> SELECT * FROM table1 USE INDEX (key1,key2)
       WHERE key1=1 AND key2=2 AND key3=3;
mysql> SELECT * FROM table1 IGNORE INDEX (key3)
       WHERE key1=1 AND key2=2 AND key3=3;

See section 5.2.6 Как MySQL оптимизирует LEFT JOIN и RIGHT JOIN.

6.4.1.2 Синтаксис оператора UNION

SELECT ...
UNION [ALL]
SELECT ...
  [UNION
   SELECT ...]

Оператор UNION реализован в MySQL 4.0.0.

UNION используется для объединения результатов работы нескольких команд SELECT в один набор результатов.

Столбцы, перечисленные в части select_expression должны быть одинакового типа. Имена столбцов, указанные в первом SELECT будут использованы как имена столбцов для всего результата.

Эти команды SELECT являются обычными командами выборки данных, но со следующим ограничением:

  • Только последняя команда SELECT может включать оператор INTO OUTFILE.

Если не используется ключевое слово ALL для UNION, все возвращенные строки будут уникальными, так как по умолчанию подразумевается DISTINCT для всего результирующего набора данных. Если указать ключевое слово ALL, то результат будет содержать все найденные строки из всех примененных команд SELECT.

Если для всего результата UNION необходимо применить оператор ORDER BY, следует использовать круглые скобки:

(SELECT a FROM table_name WHERE a=10 AND B=1 ORDER BY a LIMIT 10)
UNION
(SELECT a FROM table_name WHERE a=11 AND B=2 ORDER BY a LIMIT 10)
ORDER BY a;

6.4.2 Синтаксис оператора HANDLER

HANDLER tbl_name OPEN [ AS alias ]
HANDLER tbl_name READ index_name { = | >= | <= | < } (value1,value2,...)
    [ WHERE ... ] [LIMIT ... ]
HANDLER tbl_name READ index_name { FIRST | NEXT | PREV | LAST }
    [ WHERE ... ] [LIMIT ... ]
HANDLER tbl_name READ { FIRST | NEXT }
    [ WHERE ... ] [LIMIT ... ]
HANDLER tbl_name CLOSE

Оператор HANDLER обеспечивает прямой доступ к интерфейсу обработчика таблиц MyISAM.

Первая форма оператора HANDLER открывает таблицу, делая ее доступной для последовательности команд HANDLER ... READ. Этот объект недоступен другим потокам и не будет закрыт, пока данный поток не вызовет HANDLER tbl_name CLOSE или сам поток не будет уничтожен.

Вторая форма выбирает одну строку (или больше - в соответствии с установкой в выражении LIMIT), для которой(ых) указанный индекс соответствует заданному условию и условие в выражении WHERE также выполняется. Если индекс состоит из нескольких частей (охватывает несколько столбцов), то составляющие его величины указываются в виде разделенного запятыми списка. Обеспечиваются величины только для нескольких первых столбцов.

Третья форма выбирает одну строку (или больше - в соответствии с установкой в выражении LIMIT), из таблицы; в порядке указания индексов в соответствии с условием WHERE.

Четвертая форма (без указания индексов) выбирает одну строку (или больше - в соответствии с установкой в выражении LIMIT), из таблицы, используя естественный порядок строк (как они хранятся в файле данных), в соответствии с условием WHERE. Эта форма работает быстрее, чем HANDLER tbl_name READ index_name, в тех случаях, когда желателен просмотр всей таблицы.

Оператор HANDLER ... CLOSE закрывает таблицу, открытую оператором HANDLER ... OPEN.

Оператор HANDLER представляет собой что-то наподобие низкоуровневой команды. Например, он не обеспечивает целостности таблицы. Т.е. HANDLER ... OPEN НЕ делает моментального снимка таблицы и НЕ блокирует ее. Отсюда следует, что после вызова команды HANDLER ... OPEN данные таблицы могут быть модифицированы (этим или любым другим потоком), а сами модификации в просмотрах таблицы при помощи HANDLER ... NEXT или HANDLER ... PREV могут появляться только частично.

Вот причины, по которым вы можете предпочесть HANDLER вместо обычного SQL:

  • Он быстрее чем SELECT, потому что:
    • Выделенный код обработчика таблиц создается в потоке по вызову HANDLER open.
    • Меньше синтаксического анализа.
    • Нет нагрузки на оптимизацию и проверку.
    • Таблицу не нужно блокировать между запросами.
    • Этот интерфейс не обязан предоставлять целостный вид данных (скажем, грязное чтение допускается), что позволяет обработчику таблиц делать оптимизации которые SQL обычно не допускает.
  • Гораздо легче переносить на MySQL приложения, которые используют интерфейс, подобный ISAM.
  • Такой интерфейс позволяет просматривать базу данных способом, который не так легко (или в некоторых случаях и вовсе невозможно) реализовать с помощью SQL. Интерфейс HANDLER является более естественным способом получить данные, когда приходится иметь дело с интерактивными пользовательскими приложениями.

6.4.3 Синтаксис оператора INSERT

    INSERT [LOW_PRIORITY | DELAYED] [IGNORE]
        [INTO] tbl_name [(col_name,...)]
        VALUES (expression,...),(...),...
        [ ON DUPLICATE KEY UPDATE col_name=expression, ... ]
или INSERT [LOW_PRIORITY | DELAYED] [IGNORE]
        [INTO] tbl_name [(col_name,...)]
        SELECT ...
или INSERT [LOW_PRIORITY | DELAYED] [IGNORE]
        [INTO] tbl_name
        SET col_name=(expression | DEFAULT), ...
        [ ON DUPLICATE KEY UPDATE col_name=expression, ... ]

Оператор INSERT вставляет новые строки в существующую таблицу. Форма данной команды INSERT ... VALUES вставляет строки в соответствии с точно указанными в команде значениями. Форма INSERT ... SELECT вставляет строки, выбранные из другой таблицы или таблиц. Форма INSERT ... VALUES со списком из нескольких значений поддерживается в версии MySQL 3.22.5 и более поздних. Синтаксис выражения col_name=expression поддерживается в версии MySQL 3.22.10 и более поздних.

tbl_name задает таблицу, в которую должны быть внесены строки. Столбцы, для которых заданы величины в команде, указываются в списке имен столбцов или в части SET:

  • Если не указан список столбцов для INSERT ... VALUES или INSERT ... SELECT, то величины для всех столбцов должны быть определены в списке VALUES() или в результате работы SELECT. Если порядок столбцов в таблице неизвестен, для его получения можно использовать DESCRIBE tbl_name.
  • Любой столбец, для которого явно не указано значение, будет установлен в свое значение по умолчанию. Например, если в заданном списке столбцов не указаны все столбцы в данной таблице, то не упомянутые столбцы устанавливаются в свои значения по умолчанию. Установка значений по умолчанию описывается в разделе section 6.5.3 Синтаксис оператора CREATE TABLE. Вы также можете использовать ключевое слово DEFAULT для того, чтобы установить столбец в его значение по умолчанию (новшество в MySQL 4.0.3). Это облегчает написание INSERT, присвающим значения всем, за исключением одного-двух, столбцам, т.к. такой ситнаксис позволяет вам обойтись без указания списка столбцов, которые оператор INSERT должен обновить. В MySQL всегда предусмотрено значение по умолчанию для каждого поля. Это требование ``навязано'' MySQL, чтобы обеспечить возможность работы как с таблицами, поддерживающими транзакции, так и с таблицами, не поддерживающими их. Наша точка зрения (разработчиков) состоит в том, что проверка содержимого полей должна производиться приложением, а не сервером баз данных.
  • Выражение expression может относится к любому столбцу, который ранее был внесен в список значений. Например, можно указать следующее:
    mysql> INSERT INTO tbl_name (col1,col2) VALUES(15,col1*2);
    Но нельзя указать:
    mysql> INSERT INTO tbl_name (col1,col2) VALUES(col2*2,15);
  • Если указывается ключевое слово LOW_PRIORITY, то выполнение данной команды INSERT будет задержано до тех пор, пока другие клиенты не завершат чтение этой таблицы. В этом случае данный клиент должен ожидать, пока данная команда вставки не будет завершена, что в случае интенсивного использования таблицы может потребовать значительного времени. В противоположность этому команда INSERT DELAYED позволяет данному клиенту продолжать операцию сразу же. See section 6.4.4 Синтаксис оператора INSERT DELAYED. Следует отметить, что указатель LOW_PRIORITY обычно не используется с таблицами MyISAM, поскольку при его указании становятся невозможными параллельные вставки. See section 7.1 Таблицы MyISAM.
  • Если в команде INSERT со строками, имеющими много значений, указывается ключевое слово IGNORE, то все строки, имеющие дублирующиеся ключи PRIMARY или UNIQUE в этой таблице, будут проигнорированы и не будут внесены. Если не указывать IGNORE, то данная операция вставки прекращается при обнаружении строки, имеющей дублирующееся значение существующего ключа. Количество строк, внесенных в данную таблицу, можно определить при помощи функции C API mysql_info().
  • Если вы указываете ON DUPLICATE KEY UPDATE (новшество в MySQL 4.1.0), и производится вставка строки, которая вызывает ошибку дублирующегося первичного (PRIMARY) или уникального (UNIQUE) ключа, то вполняется UPDATE старой строки. Например:
    mysql> INSERT INTO table (a,b,c) VALUES (1,2,3)
   --> ON DUPLICATE KEY UPDATE c=c+1;
    Если a определяется как UNIQUE и уже содержит 1, то тогда вышеуказанная команда будет аналогична следующей:
    mysql> UPDATE table SET c=c+1 WHERE a=1;
    Внимание: если столбец b также является уникальным ключем, то UPDATE переписывается как:
    mysql> UPDATE table SET c=c+1 WHERE a=1 OR b=2 LIMIT 1;
    и если несколько записей соответствуют a=1 OR b=2 только одна запись будет обновлена! В общем случае, следует избегать использования ON DUPLICATE KEY на таблицах со множеством уникальных (UNIQUE) ключей. Когда используется ON DUPLICATE KEY UPDATE, опция DELAYED будет проигнорирована.
  • Если MySQL был сконфигурирован с использованием опции DONT_USE_DEFAULT_FIELDS, то команда INSERT будет генерировать ошибку, если явно не указать величины для всех столбцов, которые требуют значений не-NULL. See section 2.3.3 Типичные опции configure.
  • С помощью функции mysql_insert_id можно найти величину, использованную для столбца AUTO_INCREMENT. See section 8.4.3.31 mysql_insert_id().

Если задается команда INSERT ... SELECT или INSERT ... VALUES со списками из нескольких значений, то для получения информации о данном запросе можно использовать функцию C API mysql_info(). Формат этой информационной строки приведен ниже:

Records: 100 Duplicates: 0 Warnings: 0

Duplicates показывает число строк, которые не могли быть внесены, поскольку они дублировали бы значения некоторых существующих уникальных индексов. Указатель Warnings показывает число попыток внести величину в столбец, который по какой-либо причине оказался проблематичным. Предупреждения возникают при выполнении любого из следующих условий:

  • Внесение NULL в столбец, который был объявлен, как NOT NULL. Данный столбец устанавливается в значение, заданное по умолчанию.
  • Установка числового столбца в значение, лежащее за пределами его допустимого диапазона. Данная величина усекается до соответствующей конечной точки этого диапазона.
  • Занесение в числовой столбец такой величины, как '10.34 a'. Конечные данные удаляются и вносится только оставшаяся числовая часть. Если величина вовсе не имеет смысла как число, то столбец устанавливается в 0.
  • Внесение в столбцы типа CHAR, VARCHAR, TEXT или BLOB строки, превосходящей максимальную длину столбца. Данная величина усекается до максимальной длины столбца.
  • Внесение в столбец даты или времени строки, недопустимой для данного типа столбца. Этот столбец устанавливается в нулевую величину, соответствующую данному типу.

6.4.3.1 Синтаксис оператора INSERT ... SELECT

INSERT [LOW_PRIORITY] [IGNORE] [INTO] tbl_name [(column list)] SELECT ...

Команда INSERT ... SELECT обеспечивает возможность быстрого внесения большого количества строк в таблицу из одной или более таблиц.

INSERT INTO tblTemp2 (fldID) SELECT tblTemp1.fldOrder_ID
        FROM tblTemp1
        WHERE tblTemp1.fldOrder_ID > 100;

Для команды INSERT ... SELECT необходимо соблюдение следующих условий:

  • Целевая таблица команды INSERT не должна появляться в утверждении FROM части SELECT данного запроса, поскольку в ANSI SQL запрещено производить выборку из той же таблицы, в которую производится вставка. (Проблема заключается в том, что операция SELECT, возможно, найдет записи, которые были внесены ранее в течение того же самого прогона команды. При использовании команд, внутри которых содержатся многоступенчатые выборки, можно легко попасть в очень запутанную ситуацию!)
  • Столбцы AUTO_INCREMENT работают, как обычно.
  • Для получения информации о данном запросе можно использовать функцию C API mysql_info(). See section 6.4.3 Синтаксис оператора INSERT.
  • Чтобы гарантировать возможность использования журнала обновлений/двоичного журнала для восстановления исходного состояния таблиц, в MySQL во время выполнения команды INSERT ... SELECT параллельные вставки не разрешаются.

Разумеется, для перезаписи старых строк можно вместо INSERT использовать REPLACE.

6.4.4 Синтаксис оператора INSERT DELAYED

INSERT  DELAYED ...

Опция DELAYED для команды INSERT является специфической для MySQL возможностью, которая очень полезна, если клиент не может ждать завершения команды INSERT. Такая проблема встречается часто - она возникает, когда MySQL используется для ведения журналов (проще говоря, для логгинга) и при этом периодически запускаются команды SELECT и UPDATE, для выполнения которых требуется много времени. Оператор DELAYED был введен в версию MySQL 3.22.15. Он является расширением MySQL к ANSI SQL92.

INSERT DELAYED работает только с таблицами типа ISAM и MyISAM. Следует учитывать, что таблицы MyISAM поддерживают одновременное выполнение SELECT и INSERT, поэтому если нет свободных блоков в середине файла данных, то необходимость в применении INSERT DELAYED возникает очень редко. See section 7.1 Таблицы MyISAM.

При использовании оператора INSERT DELAYED клиент сразу же получает успешный ответ от сервера, а запись будет добавлена в таблицу сразу же после того, как эту таблицу перестанет использовать другой поток.

Еще одно существенное преимущество применения оператора INSERT DELAYED заключается в том, что данные от многих клиентов собираются вместе и записываются одним блоком. Это намного быстрее, чем несколько отдельных операций вставки.

Обратите внимание: в настоящее время все записи, поставленные в очередь на добавление, хранятся только в памяти до тех пор, пока они не будут записаны на диск. Отсюда следует, что если выполнение mysqld будет завершено принудительно (kill -9) или программа умрет, то все находящиеся в очереди данные, которые не записаны на диск, будут потеряны!.

Ниже детально описано, что происходит при использовании опции DELAYED в командах INSERT или REPLACE. В этом описании ``поток'' понимается как поток, принимающий команду INSERT DELAYED, а ``обработчик'' - это поток, который обрабатывает все команды INSERT DELAYED в конкретной таблице.

  • При выполнении потоком команды DELAYED для таблицы создается поток-обработчик для обработки всех команд DELAYED в данной таблице, если подобный обработчик уже не существует.
  • Данный поток проверяет, выполнил ли уже обработчик блокировку DELAYED; если нет, то он предписывает обработчику сделать это. Блокировка DELAYED может быть осуществлена даже в случае, если блокировки READ или WRITE на данной таблице уже выполнены другими потоками. Однако обработчик будет ожидать всех блокировок ALTER TABLE и завершения всех команд FLUSH TABLES, чтобы убедиться в том, что структура таблицы соответствует последнему обновлению.
  • Поток выполняет команду INSERT, но вместо записи строки в таблицу он ставит финальную копию этой строки в очередь, управляемую потоком-обработчиком. Поток отмечает все синтаксические ошибки и сообщает о них клиентской программе.
  • Клиент не может уведомить о количестве дубликатов или значении AUTO_INCREMENT для данной результирующей строки; он также не может получить эти данные с сервера, поскольку команда INSERT возвращает результат до полного завершения операции вставки. По той же причине ничего существенного не даст и использование функции C API mysql_info().
  • Обновление журнала обновлений производится потоком-обработчиком после вставки строки в таблицу. В случае многострочной вставки обновление журнала обновлений производится при записи первой строки.
  • После записи каждых delayed_insert_limit строк, обработчик проверяет, не находятся ли в ожидании выполнения какие-либо команды SELECT. Если да, то обработчик перед продолжением своей работы ``пропускает их вперед'' на выполнение.
  • Если очередь обработчика больше не содержит строк, то с данной таблицы будет снята блокировка. Если в течение delayed_insert_timeout секунд не поступят никакие новые команды INSERT DELAYED, то обработчик завершит свою работу.
  • Если более, чем delayed_queue_size строк уже ожидают в очереди обработчика, то поток, запрашивающий INSERT DELAYED, будет ждать, пока не освободится место в очереди. Таким образом можно иметь уверенность в том, что mysqld не займет всю память сервера для хранения запросов данной очереди.
  • Поток-обработчик будет наблюдаться в списке процессов MySQL со значением delayed_insert в столбце Command. Поток-обработчик можно уничтожить запуском команды FLUSH TABLES или командой KILL номер_потока. Однако перед своим завершением он вначале сохранит в таблице все поставленные в очередь строки. В процессе сохранения он не будет принимать никаких новых команд INSERT от иного потока. При выполнении после этого команды INSERT DELAYED будет создан новый поток-обработчик. Обратите внимание: отсюда следует, что команды INSERT DELAYED имеют более высокий приоритет, чем обычные команды INSERT, если уже существует запущенный обработчик INSERT DELAYED! Другие команды обновления должны ожидать, пока не опустеет очередь INSERT DELAYED или же пока кто-либо не прекратит выполнение потока-обработчика (с помощью KILL номер_потока) или не выполнит FLUSH TABLES.
  • Представленные в таблице переменные обеспечивают информацию об INSERT DELAYED:
    Переменная | Значение
    Delayed_insert_threads | Количество потоков-обработчиков
    Delayed_writes | Количество строк, записанных INSERT DELAYED
    Not_flushed_delayed_rows | Количество строк, ожидающих записи
  • Чтобы увидеть эти переменные, следует вызвать команду SHOW STATUS или выполнить команду mysqladmin extended-status.

Обратите внимание: если данная таблица не используется, то команда INSERT DELAYED работает медленнее, чем обычная команда INSERT. Кроме того, возникает дополнительная нагрузка на сервер, поскольку требуется управлять отдельным потоком для каждой таблицы, для которой используется INSERT DELAYED. Это означает, что команду INSERT DELAYED следует применять только тогда, когда в ней есть реальная необходимость!

6.4.5 Синтаксис оператора UPDATE

UPDATE [LOW_PRIORITY] [IGNORE] tbl_name
    SET col_name1=expr1 [, col_name2=expr2 ...]
    [WHERE where_definition]
    [ORDER BY ...]
    [LIMIT rows]

или

UPDATE [LOW_PRIORITY] [IGNORE] tbl_name [, tbl_name ...]
    SET col_name1=expr1 [, col_name2=expr2 ...]
    [WHERE where_definition]

Оператор UPDATE обновляет столбцы в соответствии с их новыми значениями в строках существующей таблицы. В выражении SET указывается, какие именно столбцы следует модифицировать и какие величины должны быть в них установлены. В выражении WHERE, если оно присутствует, задается, какие строки подлежат обновлению. В остальных случаях обновляются все строки. Если задано выражение ORDER BY, то строки будут обновляться в указанном в нем порядке.

Если указывается ключевое слово LOW_PRIORITY, то выполнение данной команды UPDATE задерживается до тех пор, пока другие клиенты не завершат чтение этой таблицы.

Если указывается ключевое слово IGNORE, то команда обновления не будет прервана, даже если при обновлении возникнет ошибка дублирования ключей. Строки, из-за которых возникают конфликтные ситуации, обновлены не будут.

Если доступ к столбцу из указанного выражения осуществляется по аргументу tbl_name, то команда UPDATE использует для этого столбца его текущее значение. Например, следующая команда устанавливает столбец age в значение, на единицу большее его текущей величины:

mysql> UPDATE persondata SET age=age+1;

Значения команда UPDATE присваивает слева направо. Например, следующая команда удваивает значение в столбце age, затем инкрементирует его:

mysql> UPDATE persondata SET age=age*2, age=age+1;

Если столбец устанавливается в его текущее значение, то MySQL замечает это и не обновляет его.

Команда UPDATE возвращает количество фактически измененных строк. В версии MySQL 3.22 и более поздних функция C API mysql_info() возвращает количество строк, которые были найдены и обновлены, и количество предупреждений, имевших место при выполнении UPDATE.

В версии MySQL 3.23 можно использовать LIMIT #, чтобы убедиться, что было изменено только заданное количество строк.

Начиная с версии MySQL 4.0.4 вы также можете выполнять UPDATE, охватывающий множество таблиц:

UPDATE items,month SET items.price=month.price
WHERE items.id=month.id;

Обратите внимание: вы не можете использовать ORDER BY или LIMIT для многотабличных обновлений.

6.4.6 Синтаксис оператора DELETE

DELETE [LOW_PRIORITY] [QUICK] FROM table_name
       [WHERE where_definition]
       [ORDER BY ...]
       [LIMIT rows]

или

DELETE [LOW_PRIORITY] [QUICK] table_name[.*] [, table_name[.*] ...]
       FROM table-references
       [WHERE where_definition]

или

DELETE [LOW_PRIORITY] [QUICK]
       FROM table_name[.*] [, table_name[.*] ...]
       USING table-references
       [WHERE where_definition]

Оператор DELETE удаляет из таблицы table_name строки, удовлетворяющие заданным в where_definition условиям, и возвращает число удаленных записей.

Если оператор DELETE запускается без определения WHERE, то удаляются все строки. При работе в режиме AUTOCOMMIT это будет аналогично использованию оператора TRUNCATE. See section 6.4.7 Синтаксис оператора TRUNCATE. В MySQL 3.23 оператор DELETE без определения WHERE возвратит ноль как число удаленных записей.

Если действительно необходимо знать число удаленных записей при удалении всех строк, и если допустимы потери в скорости, то можно использовать команду DELETE в следующей форме:

mysql> DELETE FROM table_name WHERE 1>0;

Следует учитывать, что эта форма работает намного медленнее, чем DELETE FROM table_name без выражения WHERE, поскольку строки удаляются поочередно по одной.

Если указано ключевое слово LOW_PRIORITY, выполнение данной команды DELETE будет задержано до тех пор, пока другие клиенты не завершат чтение этой таблицы.

Если задан параметр QUICK, то обработчик таблицы при выполнении удаления не будет объединять индексы - в некоторых случаях это может ускорить данную операцию.

В таблицах MyISAM удаленные записи сохраняются в связанном списке, а последующие операции INSERT повторно используют места, где располагались удаленные записи. Чтобы возвратить неиспользуемое пространство и уменьшить размер файлов, можно применить команду OPTIMIZE TABLE или утилиту myisamchk для реорганизации таблиц. Команда OPTIMIZE TABLE проще, но утилита myisamchk работает быстрее. See section 4.5.1 Синтаксис команды OPTIMIZE TABLE. See section 4.4.6.10 Оптимизация таблиц.

Первый из числа приведенных в начале данного раздела многотабличный формат команды DELETE поддерживается, начиная с MySQL 4.0.0. Второй многотабличный формат поддерживается, начиная с MySQL 4.0.2.

Идея заключается в том, что удаляются только совпадающие строки из таблиц, перечисленных перед выражениями FROM или USING. Это позволяет удалять единовременно строки из нескольких таблиц, а также использовать для поиска дополнительные таблицы.

Символы .* после имен таблиц требуются только для совместимости с Access:

DELETE t1,t2 FROM t1,t2,t3 WHERE t1.id=t2.id AND t2.id=t3.id

или

DELETE FROM t1,t2 USING t1,t2,t3 WHERE t1.id=t2.id AND t2.id=t3.id

В предыдущем случае просто удалены совпадающие строки из таблиц t1 и t2.

Если применяется выражение ORDER BY (доступно с версии MySQL 4.0), то строки будут удалены в указанном порядке. В действительности это выражение полезно только в сочетании с LIMIT. Например:

DELETE FROM somelog
        WHERE user = 'jcole'
        ORDER BY timestamp
        LIMIT 1

Данный оператор удалит самую старую запись (по timestamp), в которой строка соответствует указанной в выражении WHERE.

Специфическая для MySQL опция LIMIT для команды DELETE указывает серверу максимальное количество строк, которые следует удалить до возврата управления клиенту. Эта опция может использоваться для гарантии того, что данная команда DELETE не потребует слишком много времени для выполнения. Можно просто повторять команду DELETE до тех пор, пока количество удаленных строк меньше, чем величина LIMIT.

С MySQL 4.0 вы можете указать множество таблиц в DELETE чтобы удалить записи из одной таблицы, основываясь на условии по множеству таблиц. Однако, с такой формой оператора DELETE нельзя использовать ORDER BY или LIMIT.

6.4.7 Синтаксис оператора TRUNCATE

TRUNCATE TABLE table_name

В версии 3.23 TRUNCATE TABLE выполняет последовательность "COMMIT ; DELETE FROM table_name". See section 6.4.6 Синтаксис оператора DELETE.

TRUNCATE TABLE имеет следующие отличия от DELETE FROM ...:

  • Эта операция удаляет и воссоздает таблицу, что намного быстрее, чем поочередное удаление строк.
  • Операция является нетранзакционной; если одновременно выполняется транзакция или активная блокировка таблицы, то можно получить ошибку.
  • Не возвращает количество удаленных строк.
  • Пока существует корректный файл `table_name.frm', таблицу можно воссоздать с его с помощью, даже если файлы данных или индексов повреждены.

TRUNCATE является расширением Oracle SQL.

6.4.8 Синтаксис оператора REPLACE

    REPLACE [LOW_PRIORITY | DELAYED]
        [INTO] tbl_name [(col_name,...)]
        VALUES (expression,...),(...),...
или REPLACE [LOW_PRIORITY | DELAYED]
        [INTO] tbl_name [(col_name,...)]
        SELECT ...
или REPLACE [LOW_PRIORITY | DELAYED]
        [INTO] tbl_name
        SET col_name=expression, col_name=expression,...

Оператор REPLACE работает точно так же, как INSERT, за исключением того, что если старая запись в данной таблице имеет то же значение индекса UNIQUE или PRIMARY KEY, что и новая, то старая запись перед занесением новой будет удалена. See section 6.4.3 Синтаксис оператора INSERT.

Другими словами, команда REPLACE не предоставляет доступа к замещаемой записи. В некоторых старых версиях MySQL такой доступ иногда оказывался возможным, но это был дефект, который уже исправлен.

Для использования REPLACE у вас должны быть привилегии INSERT и DELETE для таблицы.

При использовании команды REPLACE функция mysql_affected_rows() вернет значение, равное 2, если старая строка была заменена новой. Объясняется это тем, что в таблицу вставляется строка после того, как удаляется дубликат.

Это позволяет легко определять, какое действие произвела команда REPLACE - добавление или замещение строки. Достаточно просто проверить, какое число вернула функция mysql_affected_rows() - 1 (строка добавлена) или 2 (замещена).

Следует учитывать, что, если не используются индексы UNIQUE или PRIMARY KEY, то применение команды REPLACE не имеет смысла, так как она работает просто как INSERT.

6.4.9 Синтаксис оператора LOAD DATA INFILE

LOAD DATA [LOW_PRIORITY | CONCURRENT] [LOCAL] INFILE 'file_name.txt'
    [REPLACE | IGNORE]
    INTO TABLE tbl_name
    [FIELDS
        [TERMINATED BY '\t']
        [[OPTIONALLY] ENCLOSED BY '']
        [ESCAPED BY '\\' ]
    ]
    [LINES TERMINATED BY '\n']
    [IGNORE number LINES]
    [(col_name,...)]

Команда LOAD DATA INFILE читает строки из текстового файла и вставляет их в таблицу с очень высокой скоростью. Если задано ключевое слово LOCAL, то файл читается с клиентского хоста. Если же LOCAL не указывается, то файл должен находиться на сервере. (Опция LOCAL доступна в версии MySQL 3.22.6 и более поздних.)

Если текстовые файлы, которые нужно прочитать, находятся на сервере, то из соображений безопасности эти файлы должны либо размещаться в директории базы данных, либо быть доступными для чтения всем пользователям. Кроме того, для применения команды LOAD DATA INFILE к серверным файлам необходимо обладать привилегиями FILE для серверного хоста. See section 4.2.7 Привилегии, предоставляемые MySQL.

В версиях MySQL 3.23.49 и MySQL 4.0.2 команда LOCAL не будет работать в случаях, если демон mysqld запущен с параметром --local-infile=0 или если для клиента не включена возможность поддержки LOCAL. See section 4.2.4 Вопросы безопасности, относящиеся к команде LOAD DATA LOCAL.

Если указывается ключевое слово LOW_PRIORITY, то выполнение данной команды LOAD DATA будет задержано до тех пор, пока другие клиенты не завершат чтение этой таблицы.

Если указывается ключевое слово CONCURRENT при работе с таблицами MyISAM, то другие потоки могут извлекать данные из таблицы во время выполнения команды LOAD DATA. Использование этой возможности, конечно, будет немного влиять на производительность выполнения LOAD DATA, даже если никакой другой поток не использует данную таблицу в это же время.

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

При использовании версий MySQL до 3.23.24 при помощи команды LOAD DATA INFILE нельзя выполнять чтение из FIFO. Если необходимо читать из FIFO (например, стандартный вывод gunzip), следует использовать LOAD DATA LOCAL INFILE.

Можно также загружать файлы данных, используя утилиту mysqlimport. Эта утилита выполняет загрузку файлов путем посылки на сервер команд LOAD DATA INFILE. Опция --local заставляет mysqlimport читать файлы данных с клиентского хоста. Можно указать параметр --compress, чтобы получить лучшую производительность при работе через медленные сети, если и клиент, и сервер поддерживают протокол сжатия данных.

В случаях, когда файлы находятся на сервере, последний действует по следующим правилам:

  • Если задан абсолютный (полный) путь к файлу, то сервер использует этот путь без изменений.
  • Если задан относительный путь к файлу с указанием одного или более начальных каталогов, то поиск файла будет осуществляться относительно указанных каталогов в каталоге данных сервера (datadir).
  • Если дается путь к файлу без указания начальных каталогов, то сервер ищет этот файл в директории используемой базы данных.

Отсюда следует, что файл, заданный как `./myfile.txt', читается из серверного каталога данных, в то время как файл, заданный как `myfile.txt', читается из каталога используемой базы данных. Например, следующая команда LOAD DATA читает файл data.txt в каталоге базы данных для db1, поскольку db1 является текущей базой данных, даже если эта команда явно содержит указание загрузить файл в таблицу базы данных db2:

mysql> USE db1;
mysql> LOAD DATA INFILE "data.txt" INTO TABLE db2.my_table;

Ключевые слова REPLACE и IGNORE управляют обработкой входных записей, которые дублируют существующие записи с теми же величинами уникальных ключей. Если указать REPLACE, то новые строки заменят существующие с таким же уникальным ключом. Если указать IGNORE, то входные строки, имеющие тот же уникальный ключ, что и существующие, будут пропускаться. Если не указан ни один из параметров, то при обнаружении дублирующегося значения ключа возникает ошибка и оставшаяся часть текстового файла игнорируется.

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

При использовании LOAD DATA INFILE на пустых таблицах MyISAM все неуникальные индексы создаются в отдельном пакете (как в REPAIR). Обычно это значительно ускоряет работу LOAD DATA INFILE в случае большого количества индексов.

Команда LOAD DATA INFILE является дополнительной к SELECT ... INTO OUTFILE. See section 6.4.1 Синтаксис оператора SELECT. Чтобы записать данные из базы данных в файл, используется SELECT ... INTO OUTFILE. Чтобы прочитать данные обратно в базу данных, используется LOAD DATA INFILE. Синтаксис FIELDS и LINES одинаков в обеих командах. Обе части являются необязательными, но если указаны оба, то FIELDS должно предшествовать LINES.

Если указывается FIELDS, то каждое из его подвыражений (TERMINATED BY, [OPTIONALLY] ENCLOSED BY, и ESCAPED BY) также является необязательным, однако необходимо указать по меньшей мере одно из них.

Если утверждение FIELDS не определено, то по умолчанию его параметры будут принимать следующие значения:

FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\'

Если утверждение LINES не определено, то по умолчанию оно имеет следующую структуру:

LINES TERMINATED BY '\n'

Иными словами, при установках по умолчанию команда LOAD DATA INFILE при чтении входных данных будет работать следующим образом:

  • Искать концы строк в виде символов `\n'
  • Разбивать строки на поля по символам табуляции.
  • Не ожидать, что поля могут быть заключены в символы цитирования.
  • Интерпретировать встречающиеся символы табуляции, новой строки или `\', предваренные `\', как литералы, являющиеся частью значения поля.

И, наоборот, если действуют установки по умолчанию при записи выходных данных, команда SELECT ... INTO OUTFILE будет работать следующим образом:

  • Вставлять символы табуляции между полями.
  • Не заключать поля в символы цитирования. Использовать символы `\' для экранирования экземпляров символов табуляции, новой строки или `\', которые появляются среди величин поля.
  • Вставлять символы новой строки в конце каждой записи.

Следует учитывать, что в записи FIELDS ESCAPED BY `\' необходимо указывать два обратных слеша для величины, которая должна читаться как один обратный слеш.

Опцию IGNORE number LINES можно применять для игнорирования заголовка имен столбцов в начале файла:

mysql> LOAD DATA INFILE "/tmp/file_name" INTO TABLE test IGNORE 1 LINES;

При использовании SELECT ... INTO OUTFILE совместно с LOAD DATA INFILE для того, чтобы данные из базы данных прочитать в файл, а затем - обратно из файла в базу данных, опции, обрабатывающие поля и строки, для обеих команд должны совпадать. В противном случае LOAD DATA INFILE не сможет интерпретировать содержимое данного файла правильно. Предположим, что команда SELECT ... INTO OUTFILE используется для записи в файл с полями, разделенными запятыми:

mysql> SELECT * INTO OUTFILE 'data.txt'
        FIELDS TERMINATED BY ','
        FROM ...;

Чтобы прочитать этот разделенный запятыми файл обратно в базу данных, корректная команда должна иметь вид:

mysql> LOAD DATA INFILE 'data.txt' INTO TABLE table2
        FIELDS TERMINATED BY ',';

Если вместо этого попытаться прочитать этот файл с помощью команды, представленной ниже, то она не будет работать, поскольку предписывает команде LOAD DATA INFILE искать символы табуляции между полями:

mysql> LOAD DATA INFILE 'data.txt' INTO TABLE table2
        FIELDS TERMINATED BY '\t';

Похожий результат получился бы, если бы каждая входная строка интерпретировалась как отдельное поле.

Команду LOAD DATA INFILE можно также использовать для чтения файлов, полученных из внешних источников. Например, поля в файле формата базе данных dBASE будут разделены запятыми и заключены в двойные кавычки. Если строки в данном файле заканчиваются символами новой строки, то для записи файла можно использовать приведенную ниже команду, в которой проиллюстрировано задание опций, обрабатывающих поля и строки:

mysql> LOAD DATA INFILE 'data.txt' INTO TABLE tbl_name
        FIELDS TERMINATED BY ',' ENCLOSED BY '"'
        LINES TERMINATED BY '\n';

Любая из опций, обрабатывающих поля и строки, может задавать пустую строку (''). Если строка не пустая, то величины опций FIELDS [OPTIONALLY] ENCLOSED BY и FIELDS ESCAPED BY должны содержать один символ. Величины опций FIELDS TERMINATED BY и LINES TERMINATED BY могут содержать более чем один символ. Например, чтобы записать строки, заканчивающиеся парами ``возврат каретки - перевод строки'' (как в текстовых файлах MS DOS или Windows), необходимо задать следующее выражение: LINES TERMINATED BY '\r\n'.

Например, чтобы прочитать файл `jokes', в котором строки разделены символами %%, в таблицу SQL, необходимо сделать следующее:

CREATE TABLE jokes (
        a INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
        joke TEXT NOT NULL);

LOAD DATA INFILE "/tmp/jokes.txt" INTO TABLE jokes FIELDS TERMINATED BY "";

LINES TERMINATED BY "\n%%\n" (joke);

Опция FIELDS [OPTIONALLY] ENCLOSED BY служит для управления полями, заключенными в заданные символы. Если параметр OPTIONALLY опущен, то в выводе (SELECT ... INTO OUTFILE) все поля будут заключены в символы, заданные в ENCLOSED BY. Пример такого вывода (в котором в качестве разделителя полей используется запятая) показан ниже:

"1","a string","100.20"
"2","a string containing a , comma","102.20"
"3","a string containing a \" quote","102.20"
"4","a string containing a \", quote and comma","102.20"

Если указан параметр OPTIONALLY, то заданным в ENCLOSED BY символом выделяются только поля типа CHAR и VARCHAR:

1,"a string",100.20
2,"a string containing a , comma",102.20
3,"a string containing a \" quote",102.20
4,"a string containing a \", quote and comma",102.20

Следует учитывать, что появление символов ENCLOSED BY внутри величины поля экранируется применением перед ними префикса из ESCAPED BY. Также следует учитывать, что если в ESCAPED BY указана пустая величина, то существует возможность создать вывод, который оператор LOAD DATA INFILE не сможет правильно прочитать. Например, если символ экранирования является пустой строкой, то вывод, представленный выше, окажется таким, как показано ниже. Обратите внимание: второе поле в четвертой строке содержит запятую, следующую за кавычкой, которая (ошибочно) появляется, чтобы ограничить данное поле:

1,"a string",100.20
2,"a string containing a , comma",102.20
3,"a string containing a " quote",102.20
4,"a string containing a ", quote and comma",102.20

Для ввода символ ENCLOSED BY, если он есть, удаляется из обоих концов величин полей. (Это справедливо независимо от того, указан или нет параметр OPTIONALLY: при работе с входными данными параметр OPTIONALLY не учитывается.) Если встречается символ ENCLOSED BY, которому предшествует символ ESCAPED BY, то он интерпретируется как часть текущей величины поля. Кроме того, двойные символы ENCLOSED BY, встречающиеся внутри поля, интерпретируются как одиночные символы ENCLOSED BY, если данное поле само начинается с этого символа. Например, если указывается ENCLOSED BY '"', то кавычки обрабатываются, как показано ниже:

"The ""BIG"" boss"  -> The "BIG" boss
The "BIG" boss      -> The "BIG" boss
The ""BIG"" boss    -> The ""BIG"" boss

Опция FIELDS ESCAPED BY служит для управления записью или чтением специальных символов. Если символ FIELDS ESCAPED BY не пустой, он используется в качестве префикса для следующих символов в выводе:

  • Символ FIELDS ESCAPED BY
  • Символ FIELDS [OPTIONALLY] ENCLOSED BY
  • Первый символ величин FIELDS TERMINATED BY и LINES TERMINATED BY
  • Символ ASCII 0 (в действительности после экранирующего символа пишется ASCII `0', а не байт с нулевой величиной)

Если символ FIELDS ESCAPED BY пустой, то никакие символы не экранируются. На самом деле указывать пустой экранирующий символ нет смысла, особенно если величины полей в обрабатываемых данных содержат какие-либо из символов, указанных в приведенном выше списке.

Если символ FIELDS ESCAPED BY не пуст, то в случае входных данных вхождения такого символа удаляются и следующий за таким вхождением символ принимается буквально как часть величины поля. Исключениями являются экранированные `0' или `N' (например, \0 или \N, если экранирующим символом является `\'). Эти последовательности интерпретируются как ASCII 0 (байт с нулевой величиной) и NULL. См. ниже правила обработки величины NULL.

Чтобы получить более полную информацию о синтаксисе экранирующего символа `\' см. раздел section 6.1.1 Литералы: представление строк и чисел.

В ряде случаев опции обработки полей и строк взаимодействуют:

  • Если LINES TERMINATED BY является пустой строкой и FIELDS TERMINATED BY является не пустой строкой, то строки также заканчиваются символами FIELDS TERMINATED BY.
  • Если обе величины FIELDS TERMINATED BY и FIELDS ENCLOSED BY являются пустыми (''), то применяется формат с фиксированной строкой (без разделителей). В формате с фиксированной строкой не предусмотрены никакие разделители между полями. Вместо этого при чтении и записи величин столбцов используется ширина ``вывода'' столбцов. Например, если столбец объявлен как INT(7), значения для этого столбца записываются с использованием полей шириной 7 символов. Входные значения для этого столбца получаются чтением 7 символов. Формат с фиксированной строкой влияет также на обработку величин NULL (см. ниже). Отметим, что формат с фиксированными размерами не будет работать при использовании мультибайтного набора символов.

Значения NULL в зависимости от используемых опций FIELDS и LINES будут обрабатываться по-разному:

  • Для установленных по умолчанию величин FIELDS и LINES NULL записывается как \N для вывода и \N читается как NULL для ввода (исходя из предположения, что символ ESCAPED BY равен `\').
  • Если FIELDS ENCLOSED BY не является пустым, то поле, значение которого представляет собой слово из букв NULL, читается как величина NULL (в отличие от слова NULL, заключенного между символами FIELDS ENCLOSED BY, которое читается как строка 'NULL').
  • Если FIELDS ESCAPED BY является пустым, NULL записывается как слово NULL.
  • В формате с фиксированной строкой (который имеет место, если оба спецификатора - FIELDS TERMINATED BY и FIELDS ENCLOSED BY - являются пустыми), NULL записывается как пустая строка. Отметим, что вследствие этого величина NULL и пустая строка в данной таблице будут неразличимы при записи в файл, поскольку они обе записываются как пустые строки. Если необходимо, чтобы эти величины были различными при обратном чтении файла, то не следует использовать формат с фиксированной строкой.

Некоторые случаи, не поддерживаемые оператором LOAD DATA INFILE:

  • Строки с фиксированным размером (обе опции FIELDS TERMINATED BY и FIELDS ENCLOSED BY пустые) и столбцы типа BLOB или TEXT.
  • Если указывается разделитель, совпадающий с другим или являющийся префиксом другого, то LOAD DATA INFILE не сможет интерпретировать ввод правильно. Например, следующее утверждение FIELDS вызовет проблемы:
    FIELDS TERMINATED BY '"' ENCLOSED BY '"'
  • Если опция FIELDS ESCAPED BY пустая, то содержащееся в значении поля вхождение символа FIELDS ENCLOSED BY или LINES TERMINATED BY, за которым следует символ FIELDS TERMINATED BY, приведет к преждевременному завершению чтения поля или строки командой LOAD DATA INFILE. Это происходит вследствие того, что LOAD DATA INFILE не может правильно определить, где заканчивается поле или строка.

Следующий пример загружает все столбцы таблицы persondata:

mysql> LOAD DATA INFILE 'persondata.txt' INTO TABLE persondata;

Список полей не указывается, следовательно, команда LOAD DATA INFILE ожидает входные строки для заполнения каждого столбца таблицы. При этом используются значения FIELDS и LINES по умолчанию.

Если требуется загрузить только некоторые из столбцов таблицы, необходимо задать список столбцов:

mysql> LOAD DATA INFILE 'persondata.txt'
        INTO TABLE persondata (col1,col2,...);

Список полей необходимо задавать и в случаях, если порядок следования полей во входном файле отличается от порядка столбцов в данной таблице. В противном случае MySQL не сможет установить соответствие вводимых полей и столбцов таблицы.

Если строка имеет слишком мало полей, то столбцы, для которых отсутствуют поля во входном файле, устанавливаются в свои значения по умолчанию. Назначение величин по умолчанию описывается в разделе section 6.5.3 Синтаксис оператора CREATE TABLE.

Значение пустого поля интерпретируется иначе, чем отсутствие значения:

  • Для строковых типов столбец устанавливается в пустую строку.
  • Для числовых типов столбец устанавливается в 0.
  • Для типов даты и времени столбец устанавливается в соответствующее этому типу значение ``ноль''. See section 6.2.2 Типы данных даты и времени.

Отметим, что это те же самые величины, которые окажутся в столбце в результате явного назначения пустой строки столбцам строкового, числового типов, либо типов даты или времени в команде INSERT или UPDATE.

Столбцы типа TIMESTAMP устанавливаются только в текущую дату или время в случаях, если для столбца назначено значение NULL или (только для первого столбца TIMESTAMP) если столбец TIMESTAMP находится вне списка полей, если такой список задан.

Если входная строка имеет слишком много полей, то лишние поля игнорируются и количество предупреждений увеличится.

Команда LOAD DATA INFILE интерпретирует все входные данные как строки, поэтому нельзя указывать числовые величины для столбцов ENUM или SET так же, как для команд INSERT. Все величины ENUM и SET должны быть заданы как строки!

При использовании C API можно получить информацию о запросе, вызвав функцию API mysql_info() по окончании запроса LOAD DATA INFILE. Ниже показан формат строки информации для этого случая:

Records: 1 Deleted: 0 Skipped: 0 Warnings: 0

Предостережения выдаются при тех же обстоятельствах, что и при записи величин командой INSERT (see section 6.4.3 Синтаксис оператора INSERT), за исключением того, что команда LOAD DATA INFILE дополнительно генерирует предупреждения, когда во входной строке слишком мало или слишком много полей. Предостережения нигде не хранятся; количество предупреждений может использоваться только для того, чтобы проверить, нормально ли выполнились указанные действия. Если необходимо точно знать причины предупреждений, то следует выполнить команду SELECT ... INTO OUTFILE в другой файл и сравнить результат с первоначальным входным файлом - это единственный способ получить такую информацию.

Если необходимо выполнить LOAD DATA для чтения из канала, можно применить следующий трюк:

mkfifo /mysql/db/x/x
chmod 666 /mysql/db/x/x
cat < /dev/tcp/10.1.1.12/4711 > /nt/mysql/db/x/x
mysql -e "LOAD DATA INFILE 'x' INTO TABLE x" x

При использовании версии MySQL старше, чем 3.23.25, вышеприведенное можно сделать только с LOAD DATA LOCAL INFILE.

Чтобы получить более подробную информацию об эффективности INSERT в сравнении с LOAD DATA INFILE и увеличении скорости LOAD DATA INFILE, см. раздел section 5.2.9 Скорость выполнения запросов INSERT.

6.4.10 Синтаксис оператора DO

DO expression, [expression, ...]

Выполняет данное выражение, но не возвращает какой-либо результат. Является сокращенной формой оператора SELECT expression, expression, но преимущество его заключается в том, что он работает немного быстрее, если нет необходимости в возвращении результата.

Оператор главным образом полезен при использовании с функциями, имеющими побочные эффекты, такими как RELEASE_LOCK.

6.5 Определение данных: CREATE, DROP, ALTER

6.5.1 Синтаксис оператора CREATE DATABASE

CREATE DATABASE [IF NOT EXISTS] db_name

Оператор CREATE DATABASE создает базу данных с указанным именем. Правила для допустимых имен базы данных приведены в разделе section 6.1.2 Имена баз данных, таблиц, столбцов, индексы псевдонимы. Если база данных уже существует и не указан ключевой параметр IF NOT EXISTS, то возникает ошибка выполнения команды.

Базы данных в MySQL реализуются как директории, содержащие файлы, которые соответствуют таблицам в базе данных. Поскольку при первоначальном создании база данных не содержит таблиц, то команда CREATE DATABASE создает только соответствующую поддиректорию в директории данных MySQL.

Базы данных можно также создавать с помощью утилиты mysqladmin. See section 4.8 Клиентские сценарии и утилиты MySQL.

6.5.2 Синтаксис оператора DROP DATABASE

DROP DATABASE [IF EXISTS] db_name

Оператор DROP DATABASE удаляет все таблицы в указанной базе данных и саму базу. Если вы выполняете DROP DATABASE на базе данных, символически связанной с другой, то удаляется как ссылка, так и оригинальная база данных. Будьте ОЧЕНЬ внимательны при работе с этой командой!

Оператор DROP DATABASE возвращает количество файлов, которые были удалены из директории базы данных. Как правило, это число равно количеству таблиц, умноженному на три, поскольку обычно каждая таблица представлена тремя файлами - `.MYD'-файлом, `MYI'-файлом и `.frm'-файлом.

Команда DROP DATABASE удаляет из директории указанной базы данных все файлы со следующими расширениями:

Расширение | Расширение | Расширение | Расширение
.BAK | .DAT | .HSH | .ISD
.ISM | .ISM | .MRG | .MYD
.MYI | .db | .frm |

Все поддиректории, имена которых состоят из двух цифр (RAID-директории), также удаляются.

В версии MySQL 3.22 и более поздних можно использовать ключевые слова IF EXISTS для предупреждения ошибки, если указанная база данных не существует.

Можно также удалять базы данных с помощью утилиты mysqladmin. See section 4.8 Клиентские сценарии и утилиты MySQL.

6.5.3 Синтаксис оператора CREATE TABLE

CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name [(create_definition,...)]
[table_options] [select_statement]

или

CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name LIKE old_table_name;

create_definition:
  col_name type [NOT NULL | NULL] [DEFAULT default_value] [AUTO_INCREMENT]
            [PRIMARY KEY] [reference_definition]
  или   PRIMARY KEY (index_col_name,...)
  или   KEY [index_name] (index_col_name,...)
  или   INDEX [index_name] (index_col_name,...)
  или   UNIQUE [INDEX] [index_name] (index_col_name,...)
  или   FULLTEXT [INDEX] [index_name] (index_col_name,...)
  или   [CONSTRAINT symbol] FOREIGN KEY [index_name] (index_col_name,...)
            [reference_definition]
  или   CHECK (expr)

type:
        TINYINT[(length)] [UNSIGNED] [ZEROFILL]
  или   SMALLINT[(length)] [UNSIGNED] [ZEROFILL]
  или   MEDIUMINT[(length)] [UNSIGNED] [ZEROFILL]
  или   INT[(length)] [UNSIGNED] [ZEROFILL]
  или   INTEGER[(length)] [UNSIGNED] [ZEROFILL]
  или   BIGINT[(length)] [UNSIGNED] [ZEROFILL]
  или   REAL[(length,decimals)] [UNSIGNED] [ZEROFILL]
  или   DOUBLE[(length,decimals)] [UNSIGNED] [ZEROFILL]
  или   FLOAT[(length,decimals)] [UNSIGNED] [ZEROFILL]
  или   DECIMAL(length,decimals) [UNSIGNED] [ZEROFILL]
  или   NUMERIC(length,decimals) [UNSIGNED] [ZEROFILL]
  или   CHAR(length) [BINARY]
  или   VARCHAR(length) [BINARY]
  или   DATE
  или   TIME
  или   TIMESTAMP
  или   DATETIME
  или   TINYBLOB
  или   BLOB
  или   MEDIUMBLOB
  или   LONGBLOB
  или   TINYTEXT
  или   TEXT
  или   MEDIUMTEXT
  или   LONGTEXT
  или   ENUM(value1,value2,value3,...)
  или   SET(value1,value2,value3,...)

index_col_name:
        col_name [(length)]

reference_definition:
        REFERENCES tbl_name [(index_col_name,...)]
                   [MATCH FULL | MATCH PARTIAL]
                   [ON DELETE reference_option]
                   [ON UPDATE reference_option]

reference_option:
        RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT

table_options:
        TYPE = {BDB | HEAP | ISAM | InnoDB | MERGE | MRG_MYISAM | MYISAM }
или     AUTO_INCREMENT = #
или     AVG_ROW_LENGTH = #
или     CHECKSUM = {0 | 1}
или     COMMENT = "string"
или     MAX_ROWS = #
или     MIN_ROWS = #
или     PACK_KEYS = {0 | 1 | DEFAULT}
или     PASSWORD = "string"
или     DELAY_KEY_WRITE = {0 | 1}
или     ROW_FORMAT= { default | dynamic | fixed | compressed }
или     RAID_TYPE= {1 | STRIPED | RAID0 } RAID_CHUNKS=#  RAID_CHUNKSIZE=#
или     UNION = (table_name,[table_name...])
или     INSERT_METHOD= {NO | FIRST | LAST }
или     DATA DIRECTORY="абсолютный путь к каталогу"
или     INDEX DIRECTORY="абсолютный путь к каталогу"

select_statement:
        [IGNORE | REPLACE] SELECT ...  (любое корректное выражение SELECT)

Оператор CREATE TABLE создает таблицу с заданным именем в текущей базе данных. Правила для допустимых имен таблицы приведены в разделе section 6.1.2 Имена баз данных, таблиц, столбцов, индексы псевдонимы. Если нет активной текущей базы данных или указанная таблица уже существует, то возникает ошибка выполнения команды.

В версии MySQL 3.22 и более поздних имя таблицы может быть указано как db_name.tbl_name. Эта форма записи работает независимо от того, является ли указанная база данных текущей.

Начиная с MySQL 3.23 при создании таблицы можно использовать ключевое слово TEMPORARY. Временная таблица автоматически удаляется по завершении соединения, а ее имя действительно только в течение данного соединения. Это означает, что в двух разных соединениях могут использоваться временные таблицы с одинаковыми именами без конфликта друг с другом или с существующей таблицей с тем же именем (существующая таблица скрыта, пока не удалена временная таблица). С версии MySQL 4.0.2 для создания временных таблиц необходимо иметь привилегии CREATE TEMPORARY TABLES.

В версии MySQL 3.23 и более поздних можно использовать ключевые слова IF NOT EXISTS для того, чтобы не возникала ошибка, если указанная таблица уже существует. Следует учитывать, что при этом не проверяется идентичность структур этих таблиц.

В MySQL 4.1 вы можете указать LIKE чтобы создавать таблицу, основываясь на определении другой, уже существующей, таблицы. В MySQL 4.1 также можете определять тип автоматически создаваемого столбца:

CREATE TABLE foo (a tinyint not null) SELECT b+1 AS 'a' FROM bar;

Каждая таблица tbl_name представлена определенными файлами в директории базы данных. В случае таблиц типа MyISAM это следующие файлы:

Файл | Назначение
tbl_name.frm | Файл определения таблицы
tbl_name.MYD | Файл данных
tbl_name.MYI | Файл индексов

Чтобы получить более полную информацию о свойствах различных типов столбцов, section 6.2 Типы данных столбцов:

  • Если не указывается ни NULL, ни NOT NULL, то столбец интерпретируется так, как будто указано NULL.
  • Целочисленный столбец может иметь дополнительный атрибут AUTO_INCREMENT. При записи величины NULL (рекомендуется) или 0 в столбец AUTO_INCREMENT данный столбец устанавливается в значение value+1, где value представляет собой наибольшее для этого столбца значение в таблице на момент записи. Последовательность AUTO_INCREMENT начинается с 1. See section 8.4.3.31 mysql_insert_id(). Если удалить строку, содержащую максимальную величину для столбца AUTO_INCREMENT, то в таблицах типа ISAM или BDB эта величина будет восстановлена, а в таблицах типа MyISAM или InnoDB - нет. Если удалить все строки в таблице командой DELETE FROM table_name (без выражения WHERE) в режиме AUTOCOMMIT, то для таблиц всех типов последовательность начнется заново. Примечание: в таблице может быть только один столбец AUTO_INCREMENT, и он должен быть индексирован. Кроме того, версия MySQL 3.23 будет правильно работать только с положительными величинами столбца AUTO_INCREMENT. В случае внесения отрицательного числа оно интерпретируется как очень большое положительное число. Это делается, чтобы избежать проблем с точностью, когда числа ``заворачиваются'' от положительного к отрицательному и, кроме того, для гарантии, что по ошибке не будет получен столбец AUTO_INCREMENT со значением 0. В таблицах MyISAM и BDB можно указать вторичный столбец AUTO_INCREMENT с многостолбцовым ключом. See section 3.5.9 Использование атрибута AUTO_INCREMENT. Последнюю внесенную строку можно найти с помощью следующего запроса (чтобы сделать MySQL совместимым с некоторыми ODBC-приложениями):
    SELECT * FROM tbl_name WHERE auto_col IS NULL
  • CREATE TABLE автоматически принимает текущую открытую транзакцию в InnoDB если в MySQL включен двоичный журнал.
  • Величины NULL для столбца типа TIMESTAMP обрабатываются иначе, чем для столбцов других типов. В столбце TIMESTAMP нельзя хранить литерал NULL; при установке данного столбца в NULL он будет установлен в текущее значение даты и времени. Поскольку столбцы TIMESTAMP ведут себя подобным образом, то атрибуты NULL и NOT NULL неприменимы в обычном режиме и игнорируются при их задании. С другой стороны, чтобы облегчить клиентам MySQL использование столбцов TIMESTAMP, сервер сообщает, что таким столбцам могут быть назначены величины NULL (что соответствует действительности), хотя реально TIMESTAMP никогда не будет содержать величины NULL. Это можно увидеть, применив DESCRIBE tbl_name для получения описания данной таблицы. Следует учитывать, что установка столбца TIMESTAMP в 0 не равнозначна установке его в NULL, поскольку 0 для TIMESTAMP является допустимой величиной.
  • Величина DEFAULT должна быть константой, она не может быть функцией или выражением. Если для данного столбца не задается никакой величины DEFAULT, то MySQL автоматически назначает ее. Если столбец может принимать NULL как допустимую величину, то по умолчанию присваивается значение NULL. Если столбец объявлен как NOT NULL, то значение по умолчанию зависит от типа столбца:
    • Для числовых типов, за исключением объявленных с атрибутом AUTO_INCREMENT, значение по умолчанию равно 0. Для столбца AUTO_INCREMENT значением по умолчанию является следующее значение в последовательности для этого столбца.
    • Для типов даты и времени, отличных от TIMESTAMP, значение по умолчанию равно соответствующей нулевой величине для данного типа. Для первого столбца TIMESTAMP в таблице значение по умолчанию представляет собой текущее значение даты и времени. See section 6.2.2 Типы данных даты и времени. Для типов даты и времени, отличных от TIMESTAMP, значение по умолчанию равно соответствующей нулевой величине для данного типа. Для первого столбца TIMESTAMP в таблице значение по умолчанию представляет собой текущее значение даты и времени. See section 6.2.2 Типы данных даты и времени.
    • Для строковых типов, кроме ENUM, значением по умолчанию является пустая строка. Для ENUM значение по умолчанию равно первой перечисляемой величине.
    Значения по умолчанию должны быть константами. Это означает, например, что нельзя установить для столбца даты в качестве значения по умолчанию величину функции, такой как NOW() или CURRENT_DATE.
  • KEY является синонимом для INDEX.
  • В MySQL ключ UNIQUE может иметь только различающиеся значения. При попытке добавить новую строку с ключом, совпадающим с существующей строкой, возникает ошибка выполнения команды.
  • PRIMARY KEY представляет собой уникальный ключ KEY с дополнительным ограничением, что все столбцы с данным ключом должны быть определены как NOT NULL. В MySQL этот ключ называется PRIMARY (первичный). Таблица может иметь только один первичный ключ PRIMARY KEY. Если PRIMARY KEY отсутствует в таблицах, а некоторое приложение запрашивает его, то MySQL может превратить в PRIMARY KEY первый ключ UNIQUE, не имеющий ни одного столбца NULL.
  • PRIMARY KEY может быть многостолбцовым индексом. Однако нельзя создать многостолбцовый индекс, используя в определении столбца атрибут ключа PRIMARY KEY. Именно таким образом только один столбец будет отмечен как первичный. Необходимо использовать синтаксис PRIMARY KEY(index_col_name, ...).
  • Если ключ PRIMARY или UNIQUE состоит только из одного столбца и он принадлежит к числовому типу, то на него можно сослаться также как на _rowid (новшество версии 3.23.11).
  • Если индексу не назначено имя, то ему будет присвоено первое имя в index_col_name, возможно, с суффиксами (_2, _3, ...), делающими это имя уникальным. Имена индексов для таблицы можно увидеть, используя SHOW INDEX FROM tbl_name. SHOW Syntax.
  • Только таблицы типов MyISAM, InnoDB и BDB поддерживают индексы столбцов, которые могут иметь величины NULL. В других случаях, во избежание ошибки, необходимо объявлять такие столбцы как NOT NULL.
  • С помощью выражения col_name(length) можно указать индекс, для которого используется только часть столбца CHAR или VARCHAR. Это поможет сделать файл индексов намного меньше. See section 5.4.4 Индексы столбцов.
  • Индексацию столбцов BLOB и TEXT поддерживают только таблицы с типом MyISAM. Назначая индекс столбцу с типом BLOB или TEXT, всегда НЕОБХОДИМО указывать длину этого индекса:
    CREATE TABLE test (blob_col BLOB, INDEX(blob_col(10)));
  • При использовании выражений ORDER BY или GROUP BY со столбцом типа TEXT или BLOB используются только первые max_sort_length байтов. See section 6.2.3.2 Типы данных BLOB и TEXT.
  • В версии MySQL 3.23.23 и более поздних можно создавать также специальные индексы FULLTEXT. Они применяются для полнотекстового поиска. Эти индексы поддерживаются только таблицами типа MyISAM и они могут быть созданы только из столбцов CHAR, VARCHAR и TEXT. Индексирование всегда выполняется для всего столбца целиком, частичная индексация не поддерживается. Более подробно эта операция описана в разделе MySQL section 6.8 Полнотекстовый поиск в MySQL.
  • Выражения FOREIGN KEY, CHECK и REFERENCES фактически ничего не делают. Они введены только из соображений совместимости, чтобы облегчить перенос кода с других SQL-серверов и запускать приложения, создающие таблицы со ссылками. See section 1.9.3 Расширения MySQL к ANSI SQL92.
  • В MySQL версии 3.23.44 или более поздней, таблицы InnoDB выполняют проверку ограничений внешнего ключа. See section 7.5 Таблицы InnoDB. Однако обратите внимание, что синтаксис FOREIGN KEY в InnoDB более строгий чем приведенный выше. InnoDB не допускает указания index_name. Также столбцы таблицы, на которую ссылаются, должны быть явно указаны. Начиная с 4.0.8 InnoDB поддерживает действия ON DELETE и ON UPDATE. Для уточнения синтаксиса см. документацию по InnoDB. See section 7.5 Таблицы InnoDB. Для остальных типов таблиц, MySQL делает синтаксической разбор указаний FOREIGN KEY, CHECK и REFERENCES в CREATE TABLE, но при этом успешно их игнорирует. See section 1.9.4.5 Внешние ключи.
  • Для каждого столбца NULL требуется один дополнительный бит, при этом величина столбца округляется в большую сторону до ближайшего байта.
  • Максимальную длину записи в байтах можно вычислить следующим образом:
    длина записи = 1
        + (сумма длин столбцов)
        + (количество столбцов с допустимым NULL + 7)/8
        + (количество столбцов с динамической длинной)
  • Опции table_options и SELECT реализованы только в версиях MySQL 3.23 и выше. Ниже представлены различные типы таблиц:
    Тип таблицы | Описание
    BDB или BerkeleyDB | Таблицы с поддержкой транзакций и блокировкой страниц. See section 7.6 Таблицы BDB или BerkeleyDB.
    HEAP | Данные для этой таблицы хранятся только в памяти. See section 7.4 Таблицы HEAP.
    ISAM | Оригинальный обработчик таблиц. See section 7.3 Таблицы ISAM.
    InnoDB | Таблицы с поддержкой транзакций и блокировкой строк. See section 7.5 Таблицы InnoDB.
    MERGE | Набор таблиц MyISAM, используемый как одна таблица. See section 7.2 Таблицы MERGE.
    MRG_MyISAM | Псевдоним для таблиц MERGE
    MyISAM | Новый обработчик, обеспечивающий переносимость таблиц в бинарном виде, который заменяет ISAM. See section 7.1 Таблицы MyISAM.
    See section 7 Типы таблиц MySQL. Если задается тип таблицы, который не поддерживается данной версией, то MySQL выберет из возможных типов ближайший к указанному. Например, если задается TYPE=BDB и данный дистрибутив MySQL не поддерживает таблиц BDB, то вместо этого будет создана таблица MyISAM. Другие табличные опции используются для оптимизации характеристик таблицы. Эти опции в большинстве случаев не требуют специальной установки. Данные опции работают с таблицами всех типов, если не указано иное:
    Опция | Описание
    AUTO_INCREMENT | Следующая величина AUTO_INCREMENT, которую следует установить для данной таблицы (MyISAM).
    AVG_ROW_LENGTH | Приближенное значение средней длины строки для данной таблицы. Имеет смысл устанавливать только для обширных таблиц с записями переменной длины.
    CHECKSUM | Следует установить в 1, чтобы в MySQL поддерживалась проверка контрольной суммы для всех строк (это делает таблицы немного более медленными при обновлении, но позволяет легче находить поврежденные таблицы) (MyISAM).
    COMMENT | Комментарий для данной таблицы длиной 60 символов.
    MAX_ROWS | Максимальное число строк, которые планируется хранить в данной таблице.
    MIN_ROWS | Минимальное число строк, которые планируется хранить в данной таблице.
    PACK_KEYS | Следует установить в 1 для получения меньшего индекса. Обычно это замедляет обновление и ускоряет чтение (MyISAM, ISAM). Установка в 0 отключит уплотнение ключей. При установке в DEFAULT (MySQL 4.0) обработчик таблиц будет уплотнять только длинные столбцы CHAR/VARCHAR.
    PASSWORD | Шифрует файл `.frm' с помощью пароля. Эта опция не функционирует в стандартной версии MySQL.
    DELAY_KEY_WRITE | Установка в 1 задерживает операции обновления таблицы ключей, пока не закроется указанная таблица (MyISAM).
    ROW_FORMAT | Определяет, каким образом должны храниться строки. В настоящее время эта опция работает только с таблицами MyISAM, которые поддерживают форматы строк DYNAMIC и FIXED. See section 7.1.2 Форматы таблиц MyISAM.
    При использовании таблиц MyISAM MySQL вычисляет выражение max_rows * avg_row_length, чтобы определить, насколько велика будет результирующая таблица. Если не задана ни одна из вышеупомянутых опций, то максимальный размер таблицы будет составлять 4Гб (или 2Гб если данная операционная система поддерживает только таблицы величиной до 2Гб). Это делается для того, чтобы, если нет реальной необходимости в больших файлах, ограничить размеры указателей, что позволит сделать индексы меньше и быстрее. Если опция PACK_KEYS не используется, то по умолчанию уплотняются только строки, но не числа. При использовании PACK_KEYS=1 числа тоже будут уплотняться. При уплотнении двоичных числовых ключей MySQL будет использовать сжатие префиксов. Это означает, что выгода от этого будет значительной только в случае большого количества одинаковых чисел. При сжатии префиксов для каждого ключа требуется один дополнительный байт, в котором указано, сколько байтов предыдущего ключа являются такими же, как и для следующего (следует учитывать, что указатель на строку хранится в порядке "старший-байт-в-начале" сразу после ключа - чтобы улучшить компрессию). Это означает, что при наличии нескольких одинаковых ключей в двух строках записи все последующие ``аналогичные'' ключи будут занимать только по 2 байта (включая указатель строки). Сравним: в обычном случае для хранения последующих ключей требуется размер_хранения_ключа + размер_указателя (обычно 4) байтов. С другой стороны, если все ключи абсолютно разные, каждый ключ будет занимать на 1 байт больше, если данный ключ не может иметь величину NULL (в этом случае уплотненный ключ будет храниться в том же байте, который используется для указания, что ключ равен NULL).
  • Если после команды CREATE указывается команда SELECT, то MySQL создаст новые поля для всех элементов в данной команде SELECT. Например:
    mysql> CREATE TABLE test (a INT NOT NULL AUTO_INCREMENT,
        PRIMARY KEY (a), KEY(b))
        TYPE=MyISAM SELECT b,c FROM test2;
    Эта команда создаст таблицу MyISAM с тремя столбцами a, b и c. Отметим, что столбцы из команды SELECT присоединяются к таблице справа, а не перекрывают ее. Рассмотрим следующий пример:
    mysql> SELECT * FROM foo;
+---+
| n |
+---+
| 1 |
+---+

mysql> CREATE TABLE bar (m INT) SELECT n FROM foo;
Query OK, 1 row affected (0.02 sec)
Records: 1 Duplicates: 0 Warnings: 0

mysql> SELECT * FROM bar;
+------+---+
| m    | n |
+------+---+
| NULL | 1 |
+------+---+
1 row in set (0.00 sec)
    Каждая строка в таблице foo вносится в таблицу bar со своим значением из foo, при этом в новые столбцы в таблице bar записываются величины, заданные по умолчанию. Команда CREATE TABLE ... SELECT не создает автоматически каких-либо индексов. Это сделано преднамеренно, чтобы команда была настолько гибкой, насколько возможно. Чтобы иметь индексы в созданной таблице, необходимо указать их перед данной командой SELECT:
    mysql> CREATE TABLE bar (UNIQUE (n)) SELECT n FROM foo;
    Если возникает ошибка при копировании данных в таблицу, то они будут автоматически удалены. Чтобы обеспечить возможность использовать для восстановления таблиц журнал обновлений/двоичный журнал, в MySQL во время выполнения команды CREATE TABLE ... SELECT не разрешены параллельные вставки.
  • Воспользовавшись опцией RAID_TYPE, можно разбить файл данных MyISAM на участки с тем, чтобы преодолеть 2Гб/4Гб лимит файловой системы под управлением ОС, не поддерживающих большие файлы. Разбиение не касается файла индексов. Следует учесть, что для файловых систем, которые поддерживают большие файлы, эта опция не рекомендуется! Для получения более высокой скорости ввода-вывода можно разместить RAID-директории на различных физических дисках. RAID_TYPE будет работать под любой операционной системой, если конфигурация MySQL выполнена с параметром --with-raid. В настоящее время для опции RAID_TYPE возможен только параметр STRIPED (1 и RAID0 являются псевдонимами для него). Если указывается RAID_TYPE=STRIPED для таблицы MyISAM, то MyISAM создаст поддиректории RAID_CHUNKS с именами `00', `01', `02' в директории базы данных. В каждой из этих директорий MyISAM создаст файл `table_name.MYD'. При записи данных в файл данных обработчик RAID установит соответствие первых RAID_CHUNKSIZE*1024 байтов первому упомянутому файлу, следующих RAID_CHUNKSIZE*1024 байтов - следующему файлу и так далее.
  • Опция UNION применяется, если необходимо использовать совокупность идентичных таблиц как одну таблицу. Она работает только с таблицами MERGE. See section 7.2 Таблицы MERGE. На данный момент для таблиц, сопоставляемых с таблицей MERGE, необходимо иметь привилегии SELECT, UPDATE и DELETE. Все сопоставляемые таблицы должны принадлежать той же базе данных, что и таблица MERGE.
  • Для внесения данных в таблицу MERGE необходимо указать с помощью INSERT_METHOD, в какую таблицу данная строка должна быть внесена. See section 7.2 Таблицы MERGE. Эта опция была введена в MySQL 4.0.0.
  • В созданной таблице ключ PRIMARY будет помещен первым, за ним все ключи UNIQUE и затем простые ключи. Это помогает оптимизатору MySQL определять приоритеты используемых ключей, а также более быстро определять сдублированные ключи UNIQUE.
  • Используя опции DATA DIRECTORY="каталог" или INDEX DIRECTORY="каталог", можно указать, где обработчик таблицы должен помещать свои табличные и индексные файлы. Следует учитывать, что указываемый параметр directory должен представлять собой полный путь к требуемому каталогу (а не относительный путь). Данные опции работают только для таблиц MyISAM в версии MySQL 4.0, если при этом не используется опция --skip-symlink. See section 5.6.1.2 Использование символических ссылок для таблиц.

6.5.3.1 Молчаливые изменения определений столбцов

В некоторых случаях MySQL без уведомления изменяет определение столбца, заданное командой CREATE TABLE (Это может осуществляться также для команды ALTER TABLE):

  • Столбец VARCHAR с длиной меньше, чем четыре, преобразуется в столбец CHAR.
  • Если некоторый столбец в таблице имеет переменную длину, то и вся строка в результате будет переменной длины. Следовательно, если таблица содержит любые столбцы переменной длины (VARCHAR, TEXT или BLOB), то все столбцы CHAR с длиной, превышающей три символа, преобразуются в столбцы VARCHAR. Это в любом случае не влияет на использование столбцов; в MySQL столбец VARCHAR представляет собой просто иной способ хранения символов. MySQL выполняет данное преобразование, поскольку оно позволяет сэкономить память и сделать табличные операции более быстрыми. See section 7 Типы таблиц MySQL.
  • Количество выводящихся символов столбца TIMESTAMP должно быть четным и находиться в диапазоне от 2 до 14. При задании размера вывода, равного 0 или превышающего 14, указанный размер приводится к 14. Нечетные величины размера вывода в пределах от 1 до 13 приводятся к следующему четному числу.
  • В столбце TIMESTAMP не может храниться литерал NULL; установка данного столбца в NULL устанавливает его в текущее значение даты и времени. Поскольку столбцы TIMESTAMP ведут себя подобным образом, то атрибуты NULL и NOT NULL неприменимы в обычном режиме и игнорируются при их задании. DESCRIBE tbl_name всегда сообщает, что столбцу TIMESTAMP могут быть присвоены величины NULL.
  • MySQL приводит в соответствие определенные типы столбцов, используемые другими производителями баз данных SQL, к типам, принятым в MySQL. See section 6.2.5 Использование типов столбцов из других баз данных.

Если необходимо увидеть, использует ли MySQL иной тип столбца, чем был первоначально задан, следует запустить команду DESCRIBE tbl_name после создания или изменения данной таблицы.

Некоторые другие изменения типов столбцов могут происходить при сжатии таблицы с использованием утилиты myisampack. See section 7.1.2.3 Характеристики сжатых таблиц.

6.5.4 Синтаксис оператора ALTER TABLE

ALTER [IGNORE] TABLE tbl_name alter_spec [, alter_spec ...]

alter_specification:
        ADD [COLUMN] create_definition [FIRST | AFTER column_name ]
  или   ADD [COLUMN] (create_definition, create_definition,...)
  или   ADD INDEX [index_name] (index_col_name,...)
  или   ADD PRIMARY KEY (index_col_name,...)
  или   ADD UNIQUE [index_name] (index_col_name,...)
  или   ADD FULLTEXT [index_name] (index_col_name,...)
  или   ADD [CONSTRAINT symbol] FOREIGN KEY [index_name] (index_col_name,...)
            [reference_definition]
  или   ALTER [COLUMN] col_name {SET DEFAULT literal | DROP DEFAULT}
  или   CHANGE [COLUMN] old_col_name create_definition
               [FIRST | AFTER column_name]
  или   MODIFY [COLUMN] create_definition [FIRST | AFTER column_name]
  или   DROP [COLUMN] col_name
  или   DROP PRIMARY KEY
  или   DROP INDEX index_name
  или   DISABLE KEYS
  или   ENABLE KEYS
  или   RENAME [TO] new_tbl_name
  или   ORDER BY col
  или   table_options

Оператор ALTER TABLE обеспечивает возможность изменять структуру существующей таблицы. Например, можно добавлять или удалять столбцы, создавать или уничтожать индексы или переименовывать столбцы либо саму таблицу. Можно также изменять комментарий для таблицы и ее тип. See section 6.5.3 Синтаксис оператора CREATE TABLE.

Если оператор ALTER TABLE используется для изменения определения типа столбца, но DESCRIBE tbl_name показывает, что столбец не изменился, то, возможно, MySQL игнорирует данную модификацию по одной из причин, описанных в разделе section 6.5.3.1 Молчаливые изменения определений столбцов. Например, при попытке изменить столбец VARCHAR на CHAR MySQL будет продолжать использовать VARCHAR, если данная таблица содержит другие столбцы с переменной длиной.

Оператор ALTER TABLE во время работы создает временную копию исходной таблицы. Требуемое изменение выполняется на копии, затем исходная таблица удаляется, а новая переименовывается. Так делается для того, чтобы в новую таблицу автоматически попадали все обновления кроме неудавшихся. Во время выполнения ALTER TABLE исходная таблица доступна для чтения другими клиентами. Операции обновления и записи в этой таблице приостанавливаются, пока не будет готова новая таблица.

Следует отметить, что при использовании любой другой опции для ALTER TABLE кроме RENAME, MySQL всегда будет создавать временную таблицу, даже если данные, строго говоря, и не нуждаются в копировании (например, при изменении имени столбца). Мы планируем исправить это в будущем, однако, поскольку ALTER TABLE выполняется не так часто, мы (разработчики MySQL) не считаем эту задачу первоочередной. Для таблиц MyISAM можно увеличить скорость воссоздания индексной части (что является наиболее медленной частью в процессе восстановления таблицы) путем установки переменной myisam_sort_buffer_size достаточно большого значения.

  • Для использования оператора ALTER TABLE необходимы привилегии ALTER, INSERT и CREATE для данной таблицы.
  • Опция IGNORE является расширением MySQL по отношению к ANSI SQL92. Она управляет работой ALTER TABLE при наличии дубликатов уникальных ключей в новой таблице. Если опция IGNORE не задана, то для данной копии процесс прерывается и происходит откат назад. Если IGNORE указывается, тогда для строк с дубликатами уникальных ключей только первая строка используется, а остальные удаляются.
  • Можно запустить несколько выражений ADD, ALTER, DROP и CHANGE в одной команде ALTER TABLE. Это является расширением MySQL по отношению к ANSI SQL92, где допускается только одно выражение из упомянутых в одной команде ALTER TABLE.
  • Опции CHANGE col_name, DROP col_name и DROP INDEX также являются расширениями MySQL по отношению к ANSI SQL92.
  • Опция MODIFY представляет собой расширение Oracle для команды ALTER TABLE.
  • Необязательное слово COLUMN представляет собой ``белый шум'' и может быть опущено.
  • При использовании ALTER TABLE имя_таблицы RENAME TO новое_имя без каких-либо других опций MySQL просто переименовывает файлы, соответствующие заданной таблице. В этом случае нет необходимости создавать временную таблицу. See section 6.5.5 Синтаксис оператора RENAME TABLE.
  • В выражении create_definition для ADD и CHANGE используется тот же синтаксис, что и для CREATE TABLE. Следует учитывать, что этот синтаксис включает имя столбца, а не просто его тип. See section 6.5.3 Синтаксис оператора CREATE TABLE.
  • Столбец можно переименовывать, используя выражение CHANGE имя_столбца create_definition. Чтобы сделать это, необходимо указать старое и новое имена столбца и его тип в настоящее время. Например, чтобы переименовать столбец INTEGER из a в b, можно сделать следующее:
    mysql> ALTER TABLE t1 CHANGE a b INTEGER;
    При изменении типа столбца, но не его имени синтаксис выражения CHANGE все равно требует указания обоих имен столбца, даже если они одинаковы. Например:
    mysql> ALTER TABLE t1 CHANGE b b BIGINT NOT NULL;
    Однако начиная с версии MySQL 3.22.16a можно также использовать выражение MODIFY для изменения типа столбца без переименовывания его:
    mysql> ALTER TABLE t1 MODIFY b BIGINT NOT NULL;
  • При использовании CHANGE или MODIFY для того, чтобы уменьшить длину столбца, по части которого построен индекс (например, индекс по первым 10 символам столбца VARCHAR), нельзя сделать столбец короче, чем число проиндексированных символов.
  • При изменении типа столбца с использованием CHANGE или MODIFY MySQL пытается преобразовать данные в новый тип как можно корректнее.
  • В версии MySQL 3.22 и более поздних можно использовать FIRST или ADD ... AFTER имя_столбца для добавления столбца на заданную позицию внутри табличной строки. По умолчанию столбец добавляется в конце. Начиная с версии MySQL 4.0.1, можно также использовать ключевые слова FIRST и AFTER в опциях CHANGE или MODIFY.
  • Опция ALTER COLUMN задает для столбца новое значение по умолчанию или удаляет старое. Если старое значение по умолчанию удаляется и данный столбец может принимать значение NULL, то новое значение по умолчанию будет NULL. Если столбец не может быть NULL, то MySQL назначает значение по умолчанию так, как описано в разделе section 6.5.3 Синтаксис оператора CREATE TABLE.
  • Опция DROP INDEX удаляет индекс. Это является расширением MySQL по отношению к ANSI SQL92. See section 6.5.8 Синтаксис оператора DROP INDEX.
  • Если столбцы удаляются из таблицы, то эти столбцы удаляются также и из любого индекса, в который они входят как часть. Если все столбцы, составляющие индекс, удаляются, то данный индекс также удаляется.
  • Если таблица содержит только один столбец, то этот столбец не может быть удален. Вместо этого можно удалить данную таблицу, используя команду DROP TABLE.
  • Опция DROP PRIMARY KEY удаляет первичный индекс. Если такого индекса в данной таблице не существует, то удаляется первый индекс UNIQUE в этой таблице. (MySQL отмечает первый уникальный ключ UNIQUE как первичный ключ PRIMARY KEY, если никакой другой первичный ключ PRIMARY KEY не был явно указан). При добавлении UNIQUE INDEX или PRIMARY KEY в таблицу они хранятся перед остальными неуникальными ключами, чтобы можно было определить дублирующиеся ключи как можно раньше.
  • Опция ORDER BY позволяет создавать новую таблицу со строками, размещенными в заданном порядке. Следует учитывать, что созданная таблица не будет сохранять этот порядок строк после операций вставки и удаления. В некоторых случаях такая возможность может облегчить операцию сортировки в MySQL, если таблица имеет такое расположение столбцов, которое вы хотели бы иметь в дальнейшем. Эта опция в основном полезна, если заранее известен определенный порядок, в котором преимущественно будут запрашиваться строки. Использование данной опции после значительных преобразований таблицы дает возможность получить более высокую производительность.
  • При использовании команды ALTER TABLE для таблиц MyISAM все неуникальные индексы создаются в отдельном пакете (подобно REPAIR). Благодаря этому команда ALTER TABLE при наличии нескольких индексов будет работать быстрее.
  • Начиная с MySQL 4.0, вышеуказанная возможность может быть активизирована явным образом. Команда ALTER TABLE ... DISABLE KEYS блокирует в MySQL обновление неуникальных индексов для таблиц MyISAM. После этого можно применить команду ALTER TABLE ... ENABLE KEYS для воссоздания недостающих индексов. Так как MySQL делает это с помощью специального алгоритма, который намного быстрее в сравнении со вставкой ключей один за другим, блокировка ключей может дать существенное ускорение на больших массивах вставок.
  • Применяя функцию C API mysql_info(), можно определить, сколько записей было скопировано, а также (при использовании IGNORE) - сколько записей было удалено из-за дублирования значений уникальных ключей.
  • Выражения FOREIGN KEY, CHECK и REFERENCES фактически ничего не делают во всех типах таблиц, кроме InnoDB. InnoDB поддерживает ADD CONSTRAINT FOREIGN KEY (...) REFERENCES ... (...). Заметьте, что InnoDB не допускает указания index_name. See section 7.5 Таблицы InnoDB. Поддержка синтаксиса FOREIGH KEY введена только из соображений совместимости, чтобы облегчить перенос кода с других серверов SQL и запуск приложений, создающих таблицы со ссылками. See section 1.9.4 Отличия MySQL от ANSI SQL92.

Ниже приводятся примеры, показывающие некоторые случаи употребления команды ALTER TABLE. Пример начинается с таблицы t1, которая создается следующим образом:

mysql> CREATE TABLE t1 (a INTEGER,b CHAR(10));

Для того чтобы переименовать таблицу из t1 в t2:

mysql> ALTER TABLE t1 RENAME t2;

Для того чтобы изменить тип столбца с INTEGER на TINYINT NOT NULL (оставляя имя прежним) и изменить тип столбца b с CHAR(10) на CHAR(20) с переименованием его с b на c:

mysql> ALTER TABLE t2 MODIFY a TINYINT NOT NULL, CHANGE b c CHAR(20);

Для того чтобы добавить новый столбец TIMESTAMP с именем d:

mysql> ALTER TABLE t2 ADD d TIMESTAMP;

Для того чтобы добавить индекс к столбцу d и сделать столбец a первичным ключом:

mysql> ALTER TABLE t2 ADD INDEX (d), ADD PRIMARY KEY (a);

Для того чтобы удалить столбец c:

mysql> ALTER TABLE t2 DROP COLUMN c;

Для того чтобы добавить новый числовой столбец AUTO_INCREMENT с именем c:

mysql> ALTER TABLE t2 ADD c INT UNSIGNED NOT NULL AUTO_INCREMENT,
        ADD INDEX (c);

Заметьте, что столбец c индексируется, так как столбцы AUTO_INCREMENT должны быть индексированы, кроме того, столбец c объявляется как NOT NULL, поскольку индексированные столбцы не могут быть NULL.

При добавлении столбца AUTO_INCREMENT значения этого столбца автоматически заполняются последовательными номерами (при добавлении записей). Первый номер последовательности можно установить путем выполнения команды SET INSERT_ID=# перед ALTER TABLE или использования табличной опции AUTO_INCREMENT = #. See section 5.5.6 Синтаксис команды SET.

Если столбец AUTO_INCREMENT для таблиц MyISAM, не изменяется, то номер последовательности остается прежним. При удалении столбца AUTO_INCREMENT и последующем добавлении другого столбца AUTO_INCREMENT номера будут начинаться снова с 1.

See section A.6.1 Проблемы с ALTER TABLE.

6.5.5 Синтаксис оператора RENAME TABLE

RENAME TABLE tbl_name TO new_tbl_name[, tbl_name2 TO new_tbl_name2,...]

Операция переименования должна осуществляться как атомарная, т.е. при выполнении переименования никакому другому потоку не разрешается доступ к указанным таблицам. Благодаря этому возможно замещение таблицы пустой таблицей:

CREATE TABLE new_table (...);
RENAME TABLE old_table TO backup_table, new_table TO old_table;

Переименование производится слева направо. Таким образом, для обмена именами между двумя таблицами необходимо выполнить следующие действия:

RENAME TABLE old_table TO backup_table,
        new_table TO old_table,
        backup_table TO new_table;

Для двух баз данных, находящихся на одном и том же диске, можно также осуществлять обмен именами:

RENAME TABLE current_db.tbl_name TO other_db.tbl_name;

При выполнении команды RENAME не должны иметь место заблокированные таблицы или активные транзакции. Необходимо также иметь привилегии ALTER и DROP для исходной таблицы и привилегии CREATE и INSERT - для новой.

Если MySQL сталкивается с какой-либо ошибкой при переименовании нескольких таблиц, то произойдет обратное переименование для всех переименованных таблиц, чтобы вернуть все в исходное состояние.

Оператор RENAME TABLE был добавлен в MySQL 3.23.23.

6.5.6 Синтаксис оператора DROP TABLE

DROP [TEMPORARY] TABLE [IF EXISTS] tbl_name [, tbl_name,...] [RESTRICT | CASCADE]

Оператор DROP TABLE удаляет одну или несколько таблиц. Все табличные данные и определения удаляются, так что будьте внимательны при работе с этой командой!

В версии MySQL 3.22 и более поздних можно использовать ключевые слова IF EXISTS, чтобы предупредить ошибку, если указанные таблицы не существуют.

В 4.1 будет получено замечание (NOTE) для всех несуществующих таблиц при использовании IF EXISTS. See section 4.5.6.9 SHOW WARNINGS | ERRORS.

Опции RESTRICT и CASCADE позволяют упростить перенос программы. В данный момент они не задействованы.

Примечание: DROP TABLE автоматически принимает текущую активную транзакцию (за исключением случаев, когда вы используетее 4.1 и указано ключевое слово TEMPORARY).

Опция TEMPORARY игнорируется в 4.0. В 4.1 эта опция работает следующим образом:

  • Только уничтожает временные таблицы.
  • Не закрывает открытую транзакцию.
  • Права доступа не проверяются.

Использование слова TEMPORARY - это хороший способ удостовериться что вы случайно не уничтожите настоящую таблицу.

6.5.7 Синтаксис оператора CREATE INDEX

CREATE [UNIQUE|FULLTEXT] INDEX index_name
        ON tbl_name (col_name[(length)],... )

Команда CREATE INDEX в версиях MySQL до 3.22 не выполняет никаких действий. В версии 3.22 и более поздних CREATE INDEX соответствует команде ALTER TABLE в части создания индексов. See section 6.5.4 Синтаксис оператора ALTER TABLE.

Обычно все индексы создаются в таблице во время создания самой таблицы командой CREATE TABLE. See section 6.5.3 Синтаксис оператора CREATE TABLE. CREATE INDEX дает возможность добавить индексы к существующим таблицам.

Список столбцов в форме (col1,col2,...) создает индекс для нескольких столбцов. Величины индексов формируются путем конкатенации величин указанных столбцов.

Для столбцов типов CHAR и VARCHAR с помощью параметра col_name(length) могут создаваться индексы, для которых используется только часть столбца (для столбцов BLOB и TEXT нужно указывать длину). Команда, приведенная ниже, создает индекс, используя первые 10 символов столбца name:

mysql> CREATE INDEX part_of_name ON customer (name(10));

Поскольку большинство имен обычно имеют отличия друг от друга в первых 10 символах, данный индекс не должен быть намного медленнее, чем созданный из столбца name целиком. Кроме того, используя неполные столбцы для индексов, можно сделать файл индексов намного меньше, а это позволяет сэкономить место на диске и к тому же повысить скорость операций INSERT!

Следует учитывать, что в версии MySQL 3.23.2 и более поздних для таблиц типа MyISAM можно добавлять индекс только для столбцов, которые могут принимать величины NULL или для столбцов BLOB/TEXT.

Чтобы получить более подробную информацию о том, как MySQL использует индексы, See section 5.4.3 Использование индексов в MySQL.

С помощью опции FULLTEXT можно индексировать только столбцы VARCHAR и TEXT и только в таблицах MyISAM. Эта возможность доступна только в версии MySQL 3.23.23 и выше. See section 6.8 Полнотекстовый поиск в MySQL.

6.5.8 Синтаксис оператора DROP INDEX

DROP INDEX index_name ON tbl_name

Оператор DROP INDEX удаляет индексы, указанные в index_name из таблицы tbl_name. DROP INDEX не выполняет никаких действий в версиях MySQL до 3.22. В версиях 3.22 и более поздних DROP INDEX соответствует команде ALTER TABLE в части удаления индексов. See section 6.5.4 Синтаксис оператора ALTER TABLE.

6.6 Основные команды пользовательских программ MySQL

6.6.1 Синтаксис команды USE

USE db_name

Команда USE db_name предписывает MySQL использовать базу данных с именем db_name в последующих запросах по умолчанию. Указанная база данных остается в этом состоянии до конца данного сеанса или пока не будет выдана еще одна команда USE:

mysql> USE db1;
mysql> SELECT COUNT(*) FROM mytable; # selects from db1.mytable
mysql> USE db2;
mysql> SELECT COUNT(*) FROM mytable; # selects from db2.mytable

То обстоятельство, что отдельная база данных посредством команды USE выбирается как используемая в текущий момент по умолчанию, не является препятствием для доступа к таблицам других баз данных. Следующий пример иллюстрирует получение доступа к таблице author базы данных db1 и к таблице editor базы данных db2:

mysql> USE db1;
mysql> SELECT author_name,editor_name FROM author,db2.editor
        WHERE author.editor_id = db2.editor.editor_id;

Наличие команды USE обеспечивает совместимость с Sybase.

6.6.2 Синтаксис команды DESCRIBE (Получение информации о столбцах)

{DESCRIBE | DESC} tbl_name [col_name | wild]

Команда DESCRIBE представляет собой сокращенный вариант команды SHOW COLUMNS FROM. See section 4.5.6.1 Получение информации по базам данных, таблицам, столбцам и индексам.

Команда DESCRIBE предоставляет информацию о столбцах таблицы. Параметр col_name может содержать имя столбца или строки, включающей такие групповые символы SQL, как `%' и `_' (шаблонные символы, позволяющие получить информацию о всех подходящих столбцах). В кавычки брать строку не нужно.

Следует отметить, что типы столбцов в полученном описании могут отличаться от ожидаемых, первоначально заданных командой CREATE TABLE при создании таблицы, поскольку MySQL иногда изменяет типы столбцов. See section 6.5.3.1 Молчаливые изменения определений столбцов.

Данная команда обеспечивает совместимость с Oracle.

Команда SHOW предоставляет аналогичную информацию. See section 4.5.6 Синтаксис команды SHOW.

6.7 Команды управления транзакциями и блокировками в MySQL

6.7.1 Синтаксис команд BEGIN/COMMIT/ROLLBACK

По умолчанию MySQL работает в режиме autocommit. Это означает, что при выполнении обновления данных MySQL будет сразу записывать обновленные данные на диск.

При использовании таблиц, поддерживающих транзакции (таких как InnoDB, BDB), в MySQL можно отключить режим autocommit при помощи следующей команды:

SET AUTOCOMMIT=0

После этого необходимо применить команду COMMIT для записи изменений на диск или команду ROLLBACK, которая позволяет игнорировать изменения, произведенные с начала данной транзакции.

Если необходимо переключиться из режима AUTOCOMMIT только для выполнения одной последовательности команд, то для этого можно использовать команду START TRANSACTION или BEGIN или BEGIN WORK:

START TRANSACTION;
SELECT @A:=SUM(salary) FROM table1 WHERE type=1;
UPDATE table2 SET summmary=@A WHERE type=1;
COMMIT;

START TRANSACTION была добавлена в MySQL 4.0.11. Это - рекомендованный способ открыть транзакцию, в соответствии с синтаксисом ANSI SQL.

Отметим, что при использовании таблиц, не поддерживающих транзакции, изменения будут записаны сразу же, независимо от статуса режима autocommit.

При выполнении команды ROLLBACK после обновления таблицы, не поддерживающей транзакции, пользователь получит ошибку (ER_WARNING_NOT_COMPLETE_ROLLBACK) в виде предупреждения. Все таблицы, поддерживающие транзакции, будут перезаписаны, но ни одна таблица, не поддерживающая транзакции, не будет изменена.

При выполнении команд START TRANSACTION или SET AUTOCOMMIT=0 необходимо использовать двоичный журнал MySQL для резервных копий вместо более старого журнала записи изменений. Транзакции сохраняются в двоичном системном журнале как одна порция данных (перед операцией COMMIT), чтобы гарантировать, что транзакции, по которым происходит откат, не записываются. See section 4.9.4 Бинарный журнал обновлений.

Следующие команды автоматически завершают транзакцию (как если бы перед выполнением данной команды была сделана операция COMMIT ):

Команда | Команда | Команда
ALTER TABLE | BEGIN | CREATE INDEX
DROP DATABASE | DROP TABLE | RENAME TABLE
TRUNCATE |  |

Уровень изоляции для транзакций можно изменить с помощью команды SET TRANSACTION ISOLATION LEVEL .... See section 6.7.3 Синтаксис команды SET TRANSACTION.

6.7.2 Синтаксис команд LOCK TABLES/UNLOCK TABLES

LOCK TABLES tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE}
            [, tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE} ...]
...
UNLOCK TABLES

Команда LOCK TABLES блокирует указанные в ней таблицы для данного потока. Команда UNLOCK TABLES снимает любые блокировки, удерживаемые данным потоком. Все таблицы, заблокированные текущим потоком, автоматически разблокируются при появлении в потоке иной команды LOCK TABLES или при прекращении соединения с сервером.

Чтобы использовать команду LOCK TABLES в MySQL 4.0.2, необходимо иметь глобальные привилегии LOCK TABLES и SELECT для заданных таблиц. В MySQL 3.23 для этого необходимы привилегии SELECT, INSERT, DELETE и UPDATE для рассматриваемых таблиц.

Основные преимущества использования команды LOCK TABLES состоят в том, что она позволяет осуществлять эмуляцию транзакций или получить более высокую скорость при обновлении таблиц. Ниже это разъясняется более подробно.

Если в потоке возникает блокировка операции READ для некоторой таблицы, то только этот поток (и все другие потоки) могут читать из данной таблицы. Если для некоторой таблицы в потоке существует блокировка WRITE, тогда только поток, содержащий блокировку, может осуществлять операции чтения (READ) и записи (WRITE) на данной таблице. Остальные потоки блокируются.

Различие между READ LOCAL и READ состоит в том, что READ LOCAL позволяет выполнять неконфликтующие команды INSERT во время существования блокировки. Однако эту команду нельзя использовать для работы с файлами базы данных вне сервера MySQL во время данной блокировки.

При использовании команды LOCK TABLES необходимо блокировать все таблицы, которые предполагается использовать в последующих запросах, употребляя при этом те же самые псевдонимы, которые будут в запросах! Если таблица упоминается в запросе несколько раз (с псевдонимами), необходимо заблокировать каждый псевдоним!

Блокировка WRITE обычно имеет более высокий приоритет, чем блокировка READ, чтобы гарантировать, что изменения обрабатываются так быстро, как возможно. Это означает, что если один поток получает блокировку READ и затем иной поток запрашивает блокировку WRITE, последующие запросы на блокировку READ будут ожидать, пока поток WRITE не получит блокировку и не снимет ее. Можно использовать блокировки LOW_PRIORITY WRITE, позволяющие другим потокам получать блокировки READ в то время, как основной поток находится в состоянии ожидания блокировки WRITE. Блокировки LOW_PRIORITY WRITE могут быть использованы только если есть уверенность, что в конечном итоге будет период времени, когда ни один из потоков не будет иметь блокировки READ.

Команда LOCK TABLES работает следующим образом:

  1. Сортирует все блокируемые таблицы в порядке, который задан внутренним образом, т.е. ``зашит'' (с точки зрения пользователя этот порядок не задан).
  2. Блокировка WRITE ставится перед блокировкой READ, если таблицы блокируются с блокировками READ и WRITE.
  3. Блокирует одну таблицу единовременно, пока поток не получит все блокировки.

Описанный порядок действий гарантирует, что блокирование таблицы не создает тупиковой ситуации. Однако есть и другие вещи, о которых необходимо отдавать себе отчет при работе по описанной схеме:

Использование для таблицы блокировки LOW_PRIORITY WRITE всего лишь означает, что MySQL будет выполнять данную конкретную блокировку, пока не появится поток, запрашивающий блокировку READ. Если поток получил блокировку WRITE и находится в ожидании блокировки следующей таблицы из списка блокируемых таблиц, то все остальные потоки будут ожидать, пока блокировка WRITE не будет снята. Если это представляет серьезную проблему для вашего приложения, то следует подумать о преобразовании имеющихся таблиц в таблицы иного вида, поддерживающие транзакции.

Поток, ожидающий блокировку таблицы, можно безопасно уничтожить с помощью команды KILL. See section 4.5.5 Синтаксис команды KILL.

Учтите, что нельзя блокировать любые таблицы, используемые совместно с оператором INSERT DELAYED, поскольку в этом случае команда INSERT выполняется как отдельный поток.

Обычно нет необходимости блокировать таблицы, поскольку все единичные команды UPDATE являются неделимыми; никакой другой поток не может взаимодействовать с какой-либо SQL-командой, выполняемой в данное время. Однако в некоторых случаях предпочтительно тем или иным образом осуществлять блокировку таблиц:

  • Если предполагается выполнить большое количество операций на группе взаимосвязанных таблиц, то быстрее всего это сделать, блокировав таблицы, которые вы собираетесь использовать. Конечно, это имеет свою обратную сторону, поскольку никакой другой поток управления не может обновить таблицу с блокировкой READ или прочитать таблицу с блокировкой WRITE. При блокировке LOCK TABLES операции выполняются быстрее потому, что в этом случае MySQL не производит запись на диск содержимого кэша ключей для заблокированных таблиц, пока не будет вызвана команда UNLOCK TABLES (обычно кэш ключей записывается на диск после каждой SQL-команды). Применение LOCK TABLES увеличивает скорость записи/обновления/удаления в таблицах типа MyISAM.
  • Если вы используете таблицы, не поддерживающие транзакций, то при использовании программы обработки таблиц необходимо применять команду LOCK TABLES для гарантии, что никакой другой поток не вклинился между операциями SELECT и UPDATE. Ниже показан пример, требующий использования LOCK TABLES для успешного выполнения операций:
    mysql> LOCK TABLES trans READ, customer WRITE;
mysql> SELECT SUM(value) FROM trans WHERE customer_id=some_id;
mysql> UPDATE customer SET total_value=sum_from_previous_statement
        WHERE customer_id=some_id;
mysql> UNLOCK TABLES;
    Без использования LOCK TABLES существует вероятность того, что какой-либо иной поток управления может вставить новую строку в таблицу trans между выполнением операций SELECT и UPDATE.

Используя пошаговые обновления (UPDATE customer SET value=value+new_value) или функцию LAST_INSERT_ID(), применения команды LOCK TABLES во многих случаях можно избежать.

Некоторые проблемы можно также решить путем применения блокирующих функций на уровне пользователя GET_LOCK() и RELEASE_LOCK(). Эти блоки хранятся в хэш-таблице на сервере и, чтобы обеспечить высокую скорость, реализованы в виде pthread_mutex_lock() и pthread_mutex_unlock(). See section 6.3.6.2 Разные функции.

Чтобы получить дополнительную информацию о механизме блокировки, обращайтесь к разделу section 5.3.1 Как MySQL блокирует таблицы.

Можно блокировать все таблицы во всех базах данных блокировкой READ с помощью команды FLUSH TABLES WITH READ LOCK. See section 4.5.3 Синтаксис команды FLUSH. Это очень удобно для получения резервной копии файловой системы, подобной Veritas, при работе в которой могут потребоваться заблаговременные копии памяти.

Примечание: Команда LOCK TABLES не сохраняет транзакции и автоматически фиксирует все активные транзакции перед попыткой блокировать таблицы.

6.7.3 Синтаксис команды SET TRANSACTION

SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL
{ READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE }

Устанавливает уровень изоляции транзакций.

По умолчанию уровень изоляции устанавливается для последующей (не начальной) транзакции. При использовании ключевого слова GLOBAL данная команда устанавливает уровень изоляции по умолчанию глобально для всех новых соединений, созданных от этого момента. Однако для того чтобы выполнить данную команду, необходима привилегия SUPER. При использовании ключевого слова SESSION устанавливается уровень изоляции по умолчанию для всех будущих транзакций, выполняемых в текущем соединении.

Установить глобальный уровень изоляции по умолчанию для утилиты mysqld можно с помощью опции --transaction-isolation=.... See section 4.1.1 Параметры командной строки mysqld.

6.8 Полнотекстовый поиск в MySQL

С 3.23.23 MySQL поддерживает полнотекстовый поиск и индексацию. Полнотекстовые индексы в MySQL обозначаются как индексы типа FULLTEXT. Эти индексы могут быть созданы в таблицах MyISAM в столбцах VARCHAR и TEXT во время создания таблицы командой CREATE TABLE или добавлены позже с помощью команд ALTER TABLE или CREATE INDEX. Загрузка больших массивов данных в таблицу будет происходить намного быстрее, если таблица не содержит индекс FULLTEXT, который затем создается командой ALTER TABLE (или CREATE INDEX). Загрузка данных в таблицу, уже имеющую индекс FULLTEXT, будет более медленной.

Полнотекстовый поиск выполняется с помощью функции MATCH().

mysql> CREATE TABLE articles (
        id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
        title VARCHAR(200),
        body TEXT,
        FULLTEXT (title,body)
        );
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO articles VALUES
    -> (NULL,'MySQL Tutorial', 'DBMS stands for DataBase ...'),
    -> (NULL,'How To Use MySQL Efficiently', 'After you went through a ...'),
    -> (NULL,'Optimising MySQL','In this tutorial we will show ...'),
    -> (NULL,'1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),
    -> (NULL,'MySQL vs. YourSQL', 'In the following database comparison ...'),
    -> (NULL,'MySQL Security', 'When configured properly, MySQL ...');
Query OK, 6 rows affected (0.00 sec)
Records: 6 Duplicates: 0 Warnings: 0

mysql> SELECT * FROM articles
        WHERE MATCH (title,body) AGAINST ('database');
+----+-------------------+------------------------------------------+
| id | title             | body                                     |
+----+-------------------+------------------------------------------+
|  5 | MySQL vs. YourSQL | In the following database comparison ... |
|  1 | MySQL Tutorial    | DBMS stands for DataBase ...             |
+----+-------------------+------------------------------------------+
2 rows in set (0.00 sec)

Функция MATCH() выполняет поиск в естественном языке, сравнивая строку с содержимым текста (совокупность одного или более столбцов, включенных в индекс FULLTEXT). Строка поиска задается как аргумент в выражении AGAINST(). Поиск выполняется без учета регистра символов. Для каждой строки столбца в заданной таблице команда MATCH() возвращает величину релевантности, т.е. степень сходства между строкой поиска и текстом, содержащимся в данной строке указанного в списке оператора MATCH() столбца.

Когда команда MATCH() используется в выражении WHERE (см. пример выше), возвращенные строки столбцов автоматически сортируются, начиная с наиболее релевантных. Величина релевантности представляет собой неотрицательное число с плавающей точкой. Релевантность вычисляется на основе количества слов в данной строке столбца, количества уникальных слов в этой строке, общего количества слов в тексте и числа документов (строк), содержащих отдельное слово.

Поиск возможен также в логическом режиме, это объясняется ниже в данном разделе.

Предыдущий пример представляет собой общую иллюстрацию использования функции MATCH(). Строки возвращаются в порядке уменьшения релевантности.

В следующем примере показано, как извлекать величины релевантности в явном виде. В случае отсутствия выражений WHERE и ORDER BY возвращаемые строки не упорядочиваются.

mysql> SELECT id,MATCH (title,body) AGAINST ('Tutorial') FROM articles;
+----+-----------------------------------------+
| id | MATCH (title,body) AGAINST ('Tutorial') |
+----+-----------------------------------------+
|  1 |                        0.64840710366884 |
|  2 |                                       0 |
|  3 |                        0.66266459031789 |
|  4 |                                       0 |
|  5 |                                       0 |
|  6 |                                       0 |
+----+-----------------------------------------+
6 rows in set (0.00 sec)

Следующий пример - более сложный. Запрос возвращает значение релевантности и, кроме того, сортирует строки в порядке убывания релевантности. Чтобы получить такой результат, необходимо указать MATCH() дважды. Это не приведет к дополнительным издержкам, так как оптимизатор MySQL учтет, что эти два вызова MATCH() идентичны, и запустит код полнотекстового поиска только однажды.

mysql> SELECT id, body, MATCH (title,body) AGAINST
    -> ('Security implications of running MySQL as root') AS score
    -> FROM articles WHERE MATCH (title,body) AGAINST
    -> ('Security implications of running MySQL as root');
+----+-------------------------------------+-----------------+
| id | body                                | score           |
+----+-------------------------------------+-----------------+
|  4 | 1. Never run mysqld as root. 2. ... | 1.5055546709332 |
|  6 | When configured properly, MySQL ... |   1.31140957288 |
+----+-------------------------------------+-----------------+
2 rows in set (0.00 sec)

Для разбивки текста на слова MySQL использует очень простой синтаксический анализатор. ``Словом'' является любая последовательность символов, состоящая из букв, чисел, знаков `'' и `_'. Любое ``слово'', присутствующее в стоп-списке (stopword) или просто слишком короткое (3 символа или меньше), игнорируется.

Каждое правильное слово в наборе проверяемых текстов и в данном запросе оценивается в соответствии с его важностью в этом запросе или наборе текстов. Таким образом, слово, присутствующее во многих документах, будет иметь меньший вес (и даже, возможно, нулевой), как имеющее более низкое смысловое значение в данном конкретном наборе текстов. С другой стороны, редко встречающееся слово получит более высокий вес. Затем полученные значения весов слов объединяются для вычисления релевантности данной строки столбца.

Описанная техника подсчета лучше всего работает для больших наборов текстов (фактически она именно для этого тщательно настраивалась). Для очень малых таблиц распределение слов не отражает адекватно их смысловое значение, и данная модель иногда может выдавать некорректные результаты.

mysql> SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('MySQL');
Empty set (0.00 sec)

Поиск по слову ``MySQL'' в предыдущем примере не приводит к каким-либо результатам, так как это слово присутствует более чем в половине строк. По существу, данное слово целесообразно трактовать как стоп-слово (т.е. слово с нулевой смысловой ценностью). Это наиболее приемлемое решение - запрос на естественном языке не должен возвращать каждую вторую строку из таблицы размером 1Гб.

Маловероятно, что слово, встречающееся в половине строк таблицы, определяет местонахождение релевантных документов. На самом деле, наиболее вероятно, что будет найдено много не относящихся к делу документов. Общеизвестно, что такое случается слишком часто при попытке найти что-либо в Интернет с помощью поисковых машин. Именно на этом основании подобным строкам должно быть назначено низкое смысловое значение в данном конкретном наборе данных.

В MySQL 4.0.1 возможен полнотекстовый поиск также и в логическом режиме с использованием модификатора IN BOOLEAN MODE.

mysql> SELECT * FROM articles WHERE MATCH (title,body)
    ->     AGAINST ('+MySQL -YourSQL' IN BOOLEAN MODE);
+----+------------------------------+-------------------------------------+
| id | title                        | body                                |
+----+------------------------------+-------------------------------------+
|  1 | MySQL Tutorial               | DBMS stands for DataBase ...        |
|  2 | How To Use MySQL Efficiently | After you went through a ...        |
|  3 | Optimising MySQL             | In this tutorial we will show ...   |
|  4 | 1001 MySQL Tricks            | 1. Never run mysqld as root. 2. ... |
|  6 | MySQL Security               | When configured properly, MySQL ... |
+----+------------------------------+-------------------------------------+

Данный запрос вывел все строки, содержащие слово ``MySQL'' (заметьте, 50-процентная пороговая величина здесь не используется), но эти строки не содержат слова ``YourSQL''. Следует отметить, что логический режим поиска не сортирует автоматически строки в порядке уменьшения релевантности. Это видно по результату предыдущего запроса, где строка с наиболее высокой релевантностью (содержащая слово ``MySQL'' дважды) помещена последней, а не первой. Логический режим полнотекстового поиска может работать даже без индекса FULLTEXT, хотя и очень медленно.

В логическом режиме полнотекстового поиска поддерживаются следующие операторы:

+
Предшествующий слову знак ``плюс'' показывает, что это слово должно присутствовать в каждой возвращенной строке.
-
Предшествующий слову знак ``минус'' означает, что это слово не должно присутствовать в какой-либо возвращенной строке.
По умолчанию (если ни плюс, ни минус не указаны) данное слово является не обязательным, но содержащие его строки будут оцениваться более высоко. Это имитирует поведение команды MATCH() ... AGAINST() без модификатора IN BOOLEAN MODE.
< >
Эти два оператора используются для того, чтобы изменить вклад слова в величину релевантности, которое приписывается строке. Оператор < уменьшает этот вклад, а оператор > - увеличивает его. См. пример ниже.
( )
Круглые скобки группируют слова в подвыражения.
~
Предшествующий слову знак ``тильда'' воздействует как оператор отрицания, обуславливая негативный вклад данного слова в релевантность строки. Им отмечают нежелательные слова. Строка, содержащая такое слово, будет оценена ниже других, но не будет исключена совершенно, как в случае оператора - ``минус''.
*
Звездочка является оператором усечения. В отличие от остальных операторов, она должна добавляться в конце слова, а не в начале.
"
Фраза, заключенная в двойные кавычки, соответствует только строкам, содержащим эту фразу, написанную буквально.

Ниже приведен ряд примеров:

apple banana
находит строки, содержащие по меньшей мере одно из этих слов.
+apple +juice
... оба слова.
+apple macintosh
... слово ``apple'', но ранг строки выше, если она также содержит слово ``macintosh''.
+apple -macintosh
... слово ``apple'', но не ``macintosh''.
+apple +(>pie <strudel)
... ``apple'' и ``pie'', или ``apple'' и ``strudel'' (в любом порядке), но ранг ``apple pie'' выше, чем ``apple strudel''.
apple*
... ``apple'', ``apples'', ``applesauce'', и ``applet''.
"some words"
... ``some words of wisdom'', но не ``some noise words''.

6.8.1 Ограничения для полнотекстового поиска

  • Все параметры функции MATCH() должны быть столбцами одной и той же таблицы, т.е. частью одного и того же индекса FULLTEXT, за исключением работы MATCH() в режиме IN BOOLEAN MODE.
  • Список столбцов в команде MATCH() должен точно соответствовать списку столбцов в определении индекса FULLTEXT для этой таблицы, за исключением работы данной функции MATCH() в режиме IN BOOLEAN MODE.
  • Аргумент в выражении AGAINST() должен быть неизменяемой строкой.

6.8.2 Тонкая настройка полнотекстового поиска в MySQL

К сожалению, полнотекстовый поиск имеет еще мало настраиваемых пользователем параметров, хотя для последующих модификаций добавление некоторого их количества является очень важной задачей (TODO). Однако при наличии исходного дистрибутива MySQL (see section 2.3 Установка исходного дистрибутива MySQL) имеется больше возможностей управлять полнотекстовым поиском.

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

    Минимальная длина подлежащих индексации слов определяется в MySQL переменной ft_min_word_len (see section 4.5.6.4 SHOW VARIABLES). Установите желаемую величину этой переменной и создайте заново индексы FULLTEXT (эта переменная доступна только в версии MySQL 4.0).
  • Список стоп-слов может быть загружен с файла, указанного в переменной ft_stopword_file. See section 4.5.6.4 SHOW VARIABLES. После модификации стоп-листа перестройте ваши полнотекствые индексы. (Эта переменная введена в MySQL 4.0.10)
  • 50-процентный порог определяется выбранной конкретной схемой присваивания весовых коэффициентов. Чтобы отменить ее, измените следующую строку в `myisam/ftdefs.h':
    #define GWS_IN_USE GWS_PROB
    на:
    #define GWS_IN_USE GWS_FREQ
    Затем перекомпилируйте MySQL. Создавать заново индексы в этом случае нет необходимости. Примечание: таким образом вы существенно ухудшите способность MySQL продуцировать адекватные величины релевантности для функции MATCH(). Если действительно необходим поиск для таких общеупотребительных слов, то было бы лучше использовать вместо этого поиск в режиме IN BOOLEAN MODE, при котором не предусмотрен 50-процентный порог.
  • Иногда отладчик поисковой машины желает изменить операторы, используемые для логического поиска по полному тексту. Эти операторы определяются переменной ft_boolean_syntax. See section 4.5.6.4 SHOW VARIABLES. Однако эта переменная доступна только для чтения, ее значение устанавливается в `myisam/ft_static.c'.

Наиболее простым способом перестроить полнотекстовый индекс в тех случаях, когда это нужно - это вот такая команда:

mysql> REPAIR TABLE tbl_name QUICK;

6.8.3 Предстоящие доработки по полнотекстовому поиску

  • Сделать все операции с индексом FULLTEXT более быстрыми.
  • Операторы схожести
  • Поддержка для слов, тождественных индексам, - чтобы словами могли быть любые строки, которые пользователь пожелает трактовать как слова, например "C++", "AS/400", "TCP/IP" и т.д.
  • Поддержка полнотекстового поиска в таблицах типа MERGE.
  • Поддержка многобайтовых наборов символов.
  • Сделать список стоп-слов (``stopword'') зависящим от языка данных.
  • Стемминг (в зависимости от языка данных, конечно).
  • Обобщенный синтаксический пре-анализатор с определяемым пользователем функциониями (UDF).
  • Сделать данную модель поиска более гибкой (путем добавления ряда регулируемых параметров к FULLTEXT в CREATE/ALTER TABLE).

6.9 Кэш запросов в MySQL

Начиная с версии 4.0.1 сервер MySQL снабжен кэшем запросов. В процессе работы кэш запросов хранит текст запроса SELECT вместе с соответствующим результатом, который посылался клиенту. При получении другого идентичного запроса сервер извлечет результаты из кэша запросов, а не анализировать и выполнять снова тот же самый запрос.

Кэш запросов особенно полезен в средах, где (некоторые) таблицы не обновляются слишком часто и присутствует много идентичных запросов. Эта ситуация типична для многих веб-серверов с обширным активным информационным наполнением.

Ниже приведены некоторые данные функционирования для кэша запросов (они получены во время работы тестового комплекта MySQL под Linux Alpha 2x500 МГц с 2Гб ОЗУ и 64-мегабайтным кэшем запросов):

  • Если все производимые запросы являются простыми (такими как выбор строки из таблицы с одной строкой), но различаются настолько, что не могут быть кэшированы, непроизводительные затраты при активном состоянии кэша запросов составляют 13%. Это можно было бы рассматривать как сценарий наиболее неблагоприятного варианта. Однако в реальной жизни запросы более сложны, чем приведенный простой пример, так что непроизводительные затраты обычно значительно ниже.
  • Поиск строки в таблице с одной строкой происходит на 238% быстрее. Можно рассматривать эту величину, как близкую к минимальному увеличению быстродействия, ожидаемого при кэшировании запроса.
  • Если вы хотите запретить кеш запросов, установите переменную query_cache_size в 0. Запрещение кеша запросов не создает лишних перегрузок для сервера. Вы можете целиком исключить код кеша запросов из сервера путем указания при компиляции опции --without-query-cache в configure.

6.9.1 Как работает кэширование запросов

Перед синтаксическим анализом запросы сравниваются, поэтому запросы

SELECT * FROM tbl_name

и

Select * from tbl_name

для кэша запросов рассматриваются как различные, поскольку они должны быть абсолютно одинаковыми (байт в байт), чтобы рассматриваться как идентичные. Помимо этого, запрос может трактоваться как отличающийся, если, например, какой-либо клиент использует протокол соединения нового формата или иной набор символов, чем другой клиент.

Запросы, использующие различные базы данных, различные версии протоколов или различные наборы символов по умолчанию, рассматриваются как различные и кэшируются раздельно.

Рассматриваемый кэш надежно работает для запросов вида SELECT CALC_ROWS ... и SELECT FOUND_ROWS() ..., так как число найденных строк всегда хранится в кэше.

Если результат запроса вернулся из кеша запросов, тогда статусная переменная Com_select не будет увеличена, но вместо нее будет увеличена Qcache_hits. See section 6.9.4 Статус и поддержка кэша запросов.

При изменениях таблицы (INSERT, UPDATE, DELETE, TRUNCATE, ALTER или DROP TABLE|DATABASE), все кэшированные запросы, использовавшие данную таблицу (возможно, через таблицу MRG_MyISAM!), становятся недействительными и удаляются из кэша.

Если изменения были произведены в поддерживающих транзакции таблицах вида InnoDB, то все кэшированные запросы становятся недействительными при выполнении команды COMMIT.

Запрос не будет кэширован, если содержит одну из приведенных ниже функций:

Функция | Функция | Функция
Определяемые пользователем функции (UDF) | CONNECTION_ID | FOUND_ROWS
GET_LOCK | RELEASE_LOCK | LOAD_FILE
MASTER_POS_WAIT | NOW | SYSDATE
CURRENT_TIMESTAMP | CURDATE | CURRENT_DATE
CURTIME | CURRENT_TIME | DATABASE
ENCRYPT (с одним параметром) | LAST_INSERT_ID | RAND
UNIX_TIMESTAMP (без параметров) | USER | BENCHMARK

Запрос также не будет кэширован, если он содержит переменные пользователя, работает с системными таблицами mysql, или выражен в форме SELECT ... IN SHARE MODE, SELECT ... INTO OUTFILE ..., SELECT ... INTO DUMPFILE ... или в форме SELECT * FROM AUTOINCREMENT_FIELD IS NULL (для получения последнего ID - это для ODBC).

Однако FOUND ROWS() возвратит правильную величину, даже если из кэша был выбран предыдущий запрос.

В случае если запрос не использует таблиц, или использует временные таблицы, или если пользователь обладает привилегиями уровня столбца на какую-либо из задействованных таблиц, запрос не будет кеширован.

Перед выборкой запроса из кэша запросов MySQL проверит, обладает ли пользователь привилегией SELECT для всех включенных баз данных и таблиц. Если это не так, то результат кэширования не используется.

6.9.2 Конфигурация кэша запросов

Для кэша запросов в MySQL добавляется несколько системных переменных для mysqld, которые могут быть установлены в конфигурационном файле или из командной строки при запуске mysqld.

  • query_cache_limit Не кэшировать результаты, большие, чем указано (по умолчанию 1Мб).
  • query_cache_size Память, выделенная для хранения результатов старых запросов. Если равно 0, то кэширование запроса блокируется (по умолчанию). Указывается в байтах.
  • query_cache_type Можно установить следующие (только числовые) значения:
    Опция | Описание
    0 | OFF (``ВЫКЛЮЧЕНО''), результаты не кэшировать и не извлекать
    1 | ON (``ВКЛЮЧЕНО''), кэшировать все результаты, за исключением запросов SELECT SQL_NO_CACHE ...
    2 | DEMAND (``ПО ТРЕБОВАНИЮ''), кэшировать только запросы SELECT SQL_CACHE ...

Внутри потока (соединения) можно изменить функционирование кэша запросов по сравнению с установленным по умолчанию. Синтаксис следующий:

QUERY_CACHE_TYPE = OFF | ON | DEMAND
QUERY_CACHE_TYPE = 0   | 1  | 2

Опция | Описание
0 или OFF | Результаты не кэшировать и не извлекать.
1 или ON | Кэшировать все результаты за исключением запросов SELECT SQL_NO_CACHE ...
2 или DEMAND | Кэшировать только запросы SELECT SQL_CACHE ...

6.9.3 Параметры кэша запросов в запросе SELECT

В запросе SELECT можно указывать две опции для кэша запросов:

Опция | Описание
SQL_CACHE | Если QUERY_CACHE_TYPE имеет опцию DEMAND, позволяет запросу кэшироваться. Если QUERY_CACHE_TYPE имеет опцию ON, является состоянием по умолчанию. Если QUERY_CACHE_TYPE имеет опцию OFF, ничего не делать.
SQL_NO_CACHE | Делает данный запрос некэшируемым, не разрешает хранить в кэше данный запрос.

6.9.4 Статус и поддержка кэша запросов

С помощью команды FLUSH QUERY CACHE можно дефрагментировать кэш запросов с целью лучшего использования его памяти. Эта команда не удалит ни одного запроса из кэша. Команда FLUSH TABLES также записывает на диск содержимое кэша запросов.

Команда RESET QUERY CACHE удаляет все результаты запросов из кэша запросов.

Можно контролировать функционирование кэша запросов в SHOW STATUS:

Переменная | Описание
Qcache_queries_in_cache | Количество запросов, зарегистрированных в кэше.
Qcache_inserts | Количество запросов, добавленных в кэш.
Qcache_hits | Количество результативных обращений в кэш.
Qcache_lowmem_prunes | Количество запросов, удаленных из кеша по причине недостаточного количества памяти.
Qcache_not_cached | Количество не кэшированных запросов (не подлежащих кэшированию или из-за установок QUERY_CACHE_TYPE).
Qcache_free_memory | Величина свободной памяти для кэша запросов.
Qcache_total_blocks | Общее количество блоков в кэше запросов.
Qcache_free_blocks | Количество свободных блоков памяти в кэше запросов.

Общее количество запросов = Qcache_inserts + Qcache_hits + Qcache_not_cached.

Кэш запросов использует блоки переменной длины, так что параметры Qcache_total_blocks и Qcache_free_blocks могут показывать фрагментацию памяти кэша запросов. После команды FLUSH QUERY CACHE остается только один (большой) свободный блок.

Примечание: каждый запрос нуждается как минимум в двух блоках (один для текста данного запроса и один или больше - для результатов запроса). Для каждой используемой в запросе таблицы также требуется один блок, но если два или более запросов используют одну и ту же таблицу, требуется выделение только одного блока.

Вы можете использовать переменную Qcache_lowmem_prunes для настройки размера кеша запросов. В ней подсчитывается количество запросов, которые были удалены из кеша для освобождения памяти под новые результаты запросов. Кеш запросов использует стратегию используется реже всего (least recently used, LRU) для принятия решений о о том, какие запросы удалить из кеша.


Справочное руководство по MySQL версии 5.0.0-alpha. - 7 Типы таблиц MySQL

7 Типы таблиц MySQL

В MySQL версии 3.23.6 можно было выбирать из трех основных форматов таблиц (ISAM, HEAP и MyISAM). Более новые версии MySQL могут поддерживать дополнительные типы таблиц (InnoDB или BDB) - в зависимости от варианта установки.

При создании новой таблицы можно указать MySQL, какой тип таблицы для нее использовать.

Для таблицы и определений столбцов MySQL всегда создает файл `.frm'. Индекс и данные хранятся в других файлах, в зависимости от типа таблиц.

Обратите внимание: если необходимо использовать таблицы InnoDB, при запуске следует указать параметр innodb_data_file_path. See section 7.5.2 Параметры запуска InnoDB.

Если попытаться воспользоваться таблицей, которая не была активизирована или добавлена при компиляции, MySQL вместо нее создаст таблицу типа MyISAM. Это очень полезная функция, когда необходимо произвести копирование таблиц с одного SQL-сервера на другой, а серверы поддерживают различные типы таблиц (например, при копировании таблиц на подчиненный компьютер, который оптимизирован для быстрой работы без использования транзакционных таблиц).

Тем не менее, такое автоматическое изменение таблиц может сбить с толку новых пользователей MySQL. Мы планируем устранить эту проблему путем введения предупреждений в новом клиент-серверном протоколе в MySQL 4.1, которые будут выводиться при автоматическом изменении типов таблиц.

Преобразовывать таблицы из одного типа в другой можно при помощи оператора ALTER TABLE. See section 6.5.4 Синтаксис оператора ALTER TABLE.

Обратите внимание на то, что MySQL поддерживает два различных типа таблиц: транзакционные (InnoDB и BDB) и без поддержки транзакций (HEAP, ISAM, MERGE и MyISAM).

Преимущества транзакционных таблиц (Transaction-safe tables, TST):

  • Надежность. Даже если произойдет сбой в работе MySQL или возникнут проблемы с оборудованием, свои данные вы сможете восстановить - либо методом автоматического восстановления, либо при помощи резервной копии и журнала транзакций.
  • Можно сочетать несколько операторов и принимать все эти операторы одной командой COMMIT.
  • Можно запустить команду ROLLBACK, чтобы отменить внесенные изменения (если работа не производится в режиме автоматической фиксации).
  • Если произойдет сбой во время обновления, все изменения будут восстановлены (в нетранзакционных таблицах все внесенные изменения не могут быть отменены).
  • Лучше обеспечивает параллелизм при одновременных обновлениях таблицы и чтении.

Обратите внимание, что для использования таблиц InnoDB вам как минимум следует указать опцию innodb_data_file_path. See section 7.5.2 Параметры запуска InnoDB.

Преимущества нетранзакционных таблиц (non-transaction-safe tables, NTST):

  • Работать с ними намного быстрее, так как не выполняются дополнительные транзакции.
  • Для них требуется меньше дискового пространства, так как не применяются дополнительные транзакции.
  • Для обновлений используется меньше памяти.

В операторах можно сочетать таблицы TST и NTST, чтобы взять лучшее от каждого типа.

7.1 Таблицы MyISAM

Тип таблиц MyISAM принят по умолчанию в MySQL версии 3.23. Он основывается на коде ISAM и обладает в сравнении с ним большим количеством полезных дополнений.

Индекс хранится в файле с расширением `.MYI' (MYIndex), а данные - в файле с расширением `.MYD' (MYData). Таблицы MyISAM можно проверять/восстанавливать при помощи утилиты myisamchk. See section 4.4.6.7 Использование myisamchk для послеаварийного восстановления. Таблицы MyISAM можно сжимать при помощи команды myisampack, после чего они будут занимать намного меньше места. See section 4.7.4 myisampack, MySQL-генератор сжатых таблиц (только для чтения).

Новшества, которыми обладает тип MyISAM:

  • Флаг в файле MyISAM, указывающий, правильно была закрыта таблица или нет. В случае запуска mysqld с параметром --myisam-recover таблицы MyISAM будут автоматически проверяться и/или восстанавливаться при открытии, если таблица была закрыта неправильно.
  • При помощи команды INSERT можно вставлять новые строки в таблицу, в середине файла данных которой нет свободных блоков, в то время как другие потоки считывают из таблицы информацию (совмещенная вставка). Свободный блок может быть получен при обновлении строки с динамической длиной, когда большее количество данных заменяется меньшим количеством или при удалении строк. Когда свободных блоков не остается, все последующие блоки снова будут вставляться как совмещенные.
  • Поддержка больших файлов (63 бита) в файловых/операционных системах, которые поддерживают большие файлы.
  • Хранение всех данных осуществляется с первым младшим байтом. Это делает данные независимыми от операционной системы. Единственное требование - в компьютере должны применяться дополненные до двух байтов целые числа со знаком (как и во всех компьютерах в последние 20 лет) и формат с плавающей единичной запятой IEEE (также использующийся в подавляющем большинстве серийных компьютеров). Единственными компьютерами, которые могут не поддерживать бинарную совместимость, являются встроенные системы (поскольку в них иногда применяются специальные процессоры). При хранении данных с первым младшим байтом не происходит снижения скорости. Обычно байты в строке таблицы не выровнены и нет большой разницы в том, как прочитать невыровненный байт - в прямой последовательности или в обратной. Фактическое время извлечения значения столбца также не критично по сравнению со временем выполнения остального кода.
  • Все ключи номеров хранятся с первым старшим байтом, чтобы сжатие индексов было более эффективным.
  • Внутренняя обработка столбца AUTO_INCREMENT. MyISAM автоматически обновляет его при выполнении команд INSERT/UPDATE. Значение AUTO_INCREMENT может быть обнулено оператором myisamchk. После этого столбец AUTO_INCREMENT будет быстрее (по крайней мере на 10%) и старые номера не будут повторно использоваться, как со старым ISAM. Обратите внимание: когда AUTO_INCREMENT задан в конце составного ключа, старое поведение все еще сохраняется.
  • При вставке в отсортированном порядке (как при использовании столбца AUTO_INCREMENT) дерево ключей будет разделено таким образом, чтобы верхний узел содержал только один ключ. При этом сокращается расход пространства памяти в дереве ключей.
  • Столбцы BLOB и TEXT могут быть проиндексированы.
  • В индексных столбцах разрешены значения NULL. Они занимают 0-1 байта на ключ.
  • По умолчанию максимальная длина ключа составляет 500 байтов (это значение может быть изменено при повторной компиляции). В случаях, когда ключи больше 250 байтов, для них используются большие размеры блока ключа, чем предусмотренные по умолчанию 1024 байта.
  • По умолчанию в таблице может быть не более 32 ключей. Это значение можно увеличить до 64 без повторной компиляции myisamchk.
  • myisamchk будет отмечать таблицы как проверенные, если они запускаются с параметром --update-state. myisamchk --fast будет проверять только те таблицы, в которых отсутствует данная пометка.
  • myisamchk -a сохраняет статистические данные по частям ключа (не только для ключей целиком, как в ISAM).
  • Строки с динамическим размером будут менее фрагментированными, чем при смешивании удалений с обновлениями и вставками. Это осуществляется путем автоматического сочетания удаленных смежных блоков и расширением блоков, если следующий блок удален.
  • myisampack может упаковывать столбцы BLOB и VARCHAR.
  • Можно поместить файл данных и файл индексов в разные каталоги, чтобы увеличить скорость (с параметром DATA/INDEX DIRECTORY="path" для CREATE TABLE). See section 6.5.3 Синтаксис оператора CREATE TABLE.

MyISAM также поддерживает следующие функции, которые можно будет использовать в MySQL в ближайшем будущем:

  • Поддержка типа VARCHAR; столбец VARCHAR начинается с длины, которая хранится в 2 байтах.
  • Таблицы с VARCHAR могут иметь фиксированную или динамическую длину записей.
  • VARCHAR и CHAR могут быть до 64 Кб длиной. У всех ключевых сегментов есть свои собственные определения языка. Это позволяет задавать в MySQL различные определения языка для каждого столбца.
  • Для UNIQUE может использоваться вычисленный хэш-индекс. Это позволяет использовать UNIQUE с любым сочетанием столбцов в таблице (тем не менее, нельзя производить поиск по вычисленному UNIQUE индексу).

Обратите внимание, что индексные файлы при использовании MyISAM обычно намного меньше в сравнении с ISAM. Это означает, что для MyISAM обычно задействуется меньше системных ресурсов, чем для ISAM, но больше загружается процессор при вставке данных в сжатый индекс.

Приведенные ниже параметры mysqld могут использоваться для изменения поведения таблиц MyISAM. See section 4.5.6.4 SHOW VARIABLES.

Параметр | Описание
--myisam-recover=# | Автоматическое восстановление таблиц после сбоя.
-O myisam_sort_buffer_size=# | При восстановлении таблиц используется буфер.
--delay-key-write=ALL | Не сбрасывать на диск ключевые буферы между записями для любых таблиц MyISAM
-O myisam_max_extra_sort_file_size=# | Используется, чтобы помочь MySQL выбрать, когда использовать медленный, но надежный метод создания индекса кэша ключей. Обратите внимание на то, что этот параметр задается в мегабайтах!
-O myisam_max_sort_file_size=# | Не использовать метод быстрой сортировки индекса для созданных индексов, если временный файл превысит этот размер. Обратите внимание на то, что этот параметр задается в мегабайтах!
-O bulk_insert_buffer_size=# Размер кэша дерева, используемого при оптимизации групповых вставок. Обратите внимание: это ограничение на поток!

Автоматическое восстановление активизируется при запуске mysqld с параметром --myisam-recover=# (see section 4.1.1 Параметры командной строки mysqld). Когда таблица открывается, производится проверка, не помечена ли она как сбойная, не равна ли переменная счетчика открытий таблицы нулю (0) и не производится ли запуск с параметром --skip-external-locking. Если хотя бы одно из этих условий выполняется, произойдет следующее:

  • Будет произведена проверка таблицы на наличие ошибок;
  • Если обнаружится ошибка, будет произведена попытка быстрого восстановления (с сортировкой и без повторного создания файла данных) таблицы;
  • Если восстановление не удалось из-за ошибки в файле данных (например, ошибка дублирующегося ключа), будет произведена вторая попытка, но на этот раз с повторным созданием файла данных.
  • Если восстановление не удастся, будет произведена еще одна попытка с применением старого метода восстановления (запись по строкам без сортировки), который обеспечивает устранение ошибок любого типа с использованием незначительных ресурсов диска.

Если не удается восстановить все строки из предыдущего выполненного оператора, и не был указан параметр FORCE для myisam-recover, автоматическое восстановление будет отменено со следующей ошибкой в файле ошибок:

Error: Couldn't repair table: test.g00pages

Если в этом случае был указан параметр FORCE, вместо вышеуказанного сообщения в файле ошибок будет присутствовать следующее предупреждение:

Warning: Found 344 of 354 rows when repairing ./test/g00pages

Обратите внимание: если запустить автоматическое восстановление с параметром BACKUP, необходимо установить скрипт cron, который автоматически перемещает файлы с именами `tablename-datetime.BAK' из каталогов базы данных на носитель резервного копирования.

See section 4.1.1 Параметры командной строки mysqld.

7.1.1 Пространство, необходимое для ключей

В MySQL могут поддерживаться различные типы индексов, однако обычно это тип ISAM или MyISAM. Для обоих типов используется индекс B-дерева, так что приблизительно вычислить размер индексного файла можно по формуле (длина ключа+4)/0.67, просуммированной по всем ключам (приведено значение для самого худшего случая, когда все ключи вставлены в порядке сортировки и сжатые ключи отсутствуют).

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

В таблицах MyISAM можно также сжимать числа в префиксах, указывая при создании таблицы PACK_KEYS=1. Это полезно в случае, когда имеется много целочисленных ключей с одинаковыми префиксами, а числа хранятся с первым старшим байтом.

7.1.2 Форматы таблиц MyISAM

В MyISAM поддерживается три различных типа таблиц. Два из них выбираются автоматически, в зависимости от типа используемых столбцов. Третий - сжатые таблицы - может быть создан только при помощи инструмента myisampack.

При использовании с таблицами команд CREATE или ALTER для таблиц, у которых нет форсированной настройки BLOB, можно задать формат DYNAMIC или FIXED с параметром таблицы ROW_FORMAT=#. В будущем можно будет сжимать/разжимать таблицы, указывая ROW_FORMAT=compressed | default для ALTER TABLE. See section 6.5.3 Синтаксис оператора CREATE TABLE.

7.1.2.1 Характеристики статических таблиц (с фиксированной длиной)

Это формат, принятый по умолчанию. Он используется, когда таблица не содержит столбцов VARCHAR, BLOB или TEXT.

Данный формат - самый простой и безопасный, а также наиболее быстрый при работе с дисками. Скорость достигается за счет простоты поиска информации на диске: в таблицах статического формата с индексом для этого достаточно всего лишь умножить номер строки на ее длину.

Кроме того, при сканировании таблицы очень просто считывать постоянное количество записей при каждом чтении с диска.

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

  • Все столбцы CHAR, NUMERIC и DECIMAL расширены пробелами до ширины столбца;
  • Очень быстрые;
  • Легко кэшируются;
  • Легко восстанавливаются после сбоя, так как записи расположены в фиксированных позициях;
  • Не нуждаются в реорганизации (при помощи myisamchk), кроме случаев, когда удаляется большое количество записей и необходимо вернуть дисковое пространство операционной системе.
  • Для них обычно используется больше дискового пространства, чем для динамических таблиц.

7.1.2.2 Характеристики динамических таблиц

Данный формат используется для таблиц, которые содержат столбцы VARCHAR, BLOB или TEXT, а также если таблица была создана с параметром ROW_FORMAT=dynamic.

Это несколько более сложный формат, так как у каждой строки есть заголовок, в котором указана ее длина. Одна запись может заканчиваться более чем в одном месте, если она была увеличена во время обновления.

Чтобы произвести дефрагментацию таблицы, можно воспользоваться командами OPTIMIZE table или myisamchk. Если у вас есть статические данные, которые часто считываются/изменяются в некоторых столбцах VARCHAR или BLOB одной и той же таблицы, во избежание фрагментации эти динамические столбцы лучше переместить в другие таблицы. Свойства динамических таблиц следующие:

  • Все столбцы со строками являются динамическими (кроме тех, у которых длина меньше 4).
  • Перед каждой записью помещается битовый массив, показывающий, какие столбцы пусты ('') для строковых столбцов, или ноль для числовых столбцов (это не то же самое, что столбцы, содержащие значение NULL). Если длина строкового столбца равна нулю после удаления пробелов в конце строки, или у числового столбца значение ноль, он отмечается в битовом массиве и не сохраняется на диск. Строки, содержащие значения, сохраняются в виде байта длины и строки содержимого.
  • Обычно такие таблицы занимают намного меньше дискового пространства, чем таблицы с фиксированной длиной.
  • Для всех записей используется ровно столько места, сколько необходимо. Если размер записи увеличивается, она разделяется на несколько частей - по мере необходимости. Это приводит к фрагментации записей.
  • Если в строку добавляется информация, превышающая длину строки, строка будет фрагментирована. В этом случае для увеличения производительности можно время от времени запускать команду myisamchk -r. Чтобы получить статистические данные, воспользуйтесь командой myisamchk -ei tbl_name.
  • Восстановление после сбоя для таких таблиц является более сложным процессом, так как запись может быть фрагментированной и состоять из нескольких частей, а ссылка (или фрагмент) могут отсутствовать.
  • Предполагаемая длина строки для динамических записей вычисляется следующим образом:
    3
+ (число столбцов+ 7) / 8
+ (число столбцов char)
+ размер числовых столбцов в упакованном виде
+ длина строк
+ (число столбцов NULL + 7) / 8
    На каждую ссылку добавляется по 6 байтов. Динамические записи связываются при каждом увеличении записи во время обновления. Каждая новая ссылка занимает по крайней мере 20 байтов, поэтому следующее увеличение может произойти либо по этой же ссылке; либо по другой, если не хватит места. Количество ссылок можно проверить при помощи команды myisamchk -ed. Все ссылки можно удалить при помощи команды myisamchk -r.

7.1.2.3 Характеристики сжатых таблиц

Таблицы этого тип предназначены только для чтения. Они генерируются при помощи дополнительного инструмента myisampack (pack_isam для таблиц ISAM):

  • Все дистрибутивы MySQL, даже выпущенные до предоставления общедоступной лицензии MySQL, могут читать таблицы, которые были сжаты при помощи myisampack.
  • Сжатые таблицы занимают очень мало дискового пространства; таким образом при применении данного типа значительно снижается использование дискового пространства. Это полезно при работе с медленными дисками (такими как компакт-диски).
  • Каждая запись сжимается отдельно (незначительные издержки при доступе). Заголовки у записей фиксированные (1-3 байта), в зависимости от самой большой записи в таблице. Все столбцы сжимаются по-разному. Ниже приведено описание некоторых типов сжатия:
    • Обычно для каждого столбца используются разные таблицы Хаффмана.
    • Сжимаются пробелы суффикса.
    • Сжимаются пробелы префикса.
    • Для хранения чисел со значением 0 отводится 1 бит.
    • Если у значений в целочисленном столбце небольшой диапазон, столбец сохраняется с использованием минимального по размерам возможного типа. Например, столбец BIGINT (8 байт) может быть сохранен как столбец TINYINT (1 байт) если все значения находятся в диапазоне от 0 до 255.
    • Если в столбце содержится небольшое множество возможных значений, тип столбца преобразовывается в ENUM.
    • Столбец может содержать сочетание указанных выше сжатий.
  • Для таблиц этого типа возможна обработка записей с фиксированной или динамической длиной.
  • Таблицы данного типа могут быть распакованы при помощи команды myisamchk.

7.1.3 Проблемы с таблицами MyISAM.

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

7.1.3.1 Повреждения таблиц MyISAM

Несмотря на то, что формат таблиц MyISAM очень надежен (все изменения в таблице записываются до возвращения значения оператора SQL), таблица, тем не менее, может быть повреждена. Такое происходит в следующих случаях:

  • Процесс mysqld уничтожен во время осуществления записи;
  • Неожиданное отключение компьютера (например, если выключилось электропитание);
  • Ошибка аппаратного обеспечения;
  • Использование внешней программы (например myisamchk) на открытой таблице.
  • Ошибка программного обеспечения в коде MySQL или MyISAM.

Типичные признаки поврежденной таблицы следующие:

  • Во время выбора данных из таблицы выдается ошибка Incorrect key file for table: '...'. Try to repair it.
  • Запросы не находят в таблице строки или выдают неполные данные.

Проверить состояние таблицы можно при помощи команды CHECK TABLE. См. раздел See section 4.4.4 Синтаксис CHECK TABLE.

Для восстановления поврежденного файла можно применить команду REPAIR TABLE. See section 4.4.5 Синтаксис REPAIR TABLE. Таблицу можно восстановить и в случае, когда не запущен mysqld, при помощи команды myisamchk. See section 4.4.6.1 Синтаксис запуска myisamchk.

Если таблицы повреждены значительно, необходимо выяснить причину произошедшего! See section A.4.1 Что делать, если работа MySQL сопровождается постоянными сбоями.

Сначала следует определить, послужил ли причиной повреждения таблицы сбой mysqld (это можно легко проверить, просмотрев последние строки restarted mysqld в файле ошибок mysqld). Если дело не в этом, то необходимо составить подробное описание произошедшего. See section D.1.6 Создание контрольного примера при повреждении таблиц.

7.1.3.2 Clients is using or hasn't closed the table properly

Клиенты неправильно используют таблицу или не закрыли ее надлежащим образом

В заголовке каждого файла MyISAM `.MYI' имеется счетчик, который может использоваться для проверки правильности закрытия таблицы.

Если при выполнении команд CHECK TABLE или myisamchk выдается следующая ошибка:

# clients is using or hasn't closed the table properly

значит, нарушена синхронность счетчика. Это не означает, что таблица повреждена, но необходимо произвести проверку и убедиться, что все в порядке.

Счетчик работает следующим образом:

  • Во время первого обновления таблицы в MySQL значение счетчика в заголовках индексных файлов увеличивается.
  • Во время следующих обновлений значение счетчика не изменяется.
  • После закрытия последней записи таблицы (после применения команды FLUSH или из-за отсутствия места в кэше таблицы) значение счетчика уменьшается, если в таблицу были внесены изменения.
  • Если производится проверка таблицы, или проверка показывает, что все в порядке, счетчик устанавливается в значение 0.
  • Чтобы избежать пересечения с другими процессами, которые могут проверять таблицу, при закрытии значение счетчика не уменьшается, если счетчик установлен в значение 0.

Иначе говоря, синхронность может быть нарушена следующим образом:

  • Таблицы MyISAM копируются без команд LOCK и FLUSH TABLES.
  • Между обновлением и последним закрытием произошел сбой MySQL (обратите внимание: с таблицей все может быть в порядке, так как MySQL документирует все изменения между выполнением каждого из операторов).
  • Кто-то применил команду myisamchk --recover или myisamchk --update-state к таблице, которая в данный момент использовалась mysqld.

Таблицу используют несколько серверов mysqld, и один из них выполнил команду REPAIR или CHECK по отношению к таблице, с которой работал другой сервер. В этом случае можно выполнить команду CHECK (даже если другие серверы выдают предупреждения), но команды REPAIR следует избегать, так как она заменяет файл данных новым, информация о котором не передается другим серверам.

7.2 Таблицы MERGE

Таблицы MERGE (объединение) являются новшеством версии MySQL 3.23.25. В настоящее время код находится еще на стадии разработки, но, тем не менее, должен быть достаточно стабилен.

Таблица MERGE (или таблица MRG_MyISAM) представляет собой совокупность идентичных таблиц MyISAM, которые могут использоваться как одна таблица. К совокупности таблиц можно применять только команды SELECT, DELETE и UPDATE. Если же попытаться применить к таблице MERGE команду DROP, она подействует только на определение MERGE.

Обратите внимание на то, что команда DELETE FROM merge_table без параметра WHERE очищает только распределение для таблицы, но ничего не удаляет из распределенных таблиц (мы планируем исправить это в версии 4.1).

Под идентичными таблицами подразумеваются таблицы, созданные с одинаковой структурой и ключами. Нельзя объединять таблицы, в которых столбцы сжаты разными методами или не совпадают, либо ключи расположены в другом порядке. Тем не менее, некоторые таблицы можно сжимать при помощи команды myisampack. See section 4.7.4 myisampack, MySQL-генератор сжатых таблиц (только для чтения).

При создании таблицы MERGE будут образованы файлы определений таблиц `.frm' и списка таблиц `.MRG'. Файл `.MRG' содержит список индексных файлов (файлы `.MYI'), работа с которыми должна осуществляться как с единым файлом. Все используемые таблицы должны размещаться в той же базе данных, что и таблица MERGE.

На данный момент по отношению к таблицам, которые необходимо преобразовать в таблицу MERGE,необходимо обладать привилегиями SELECT, UPDATE и DELETE.

Ниже перечислены возможности, которые обеспечивают таблицы MERGE:

  • Простое управление набором файлов журналов. Например, можно поместить данные за различные месяцы в отдельные файлы, сжать некоторые из них при помощи myisampack, а затем создать таблицу MERGE, чтобы использовать их как одну таблицу.
  • Увеличение скорости работы. Большую таблицу можно разделить по некоторому критерию, а затем поместить различные части таблицы на разные диски. В этом случае таблица MERGE может обрабатываться намного быстрее, чем обычная большая таблица (можно, конечно, воспользоваться дисковым массивом RAID, чтобы получить те же преимущества).
  • Более эффективный поиск. Если точно известно, что вы ищете, можно производить поиск по определенным запросам только в одной из составляющих таблицу MERGE таблиц, одновременно используя таблицу MERGE для других запросов. Можно даже иметь несколько активных таблиц MERGE (возможно, с перекрывающимися файлами).
  • Более простое восстановление. Гораздо легче восстановить отдельные файлы, которые преобразованы в файл MERGE, чем пытаться восстановить действительно большой файл.
  • Быстрая обработка большого количества файлов как одного. Для таблицы MERGE используются индексы отдельных таблиц; поддерживать для нее один большой индекс нет необходимости. Благодаря этому создание или изменение таблиц MERGE осуществляется ОЧЕНЬ быстро. Обратите внимание на то, что при создании таблицы MERGE необходимо указывать определения ключей!
  • Если требуется объединить несколько таблиц в одну большую таблицу по требованию или при формировании, лучше создать для них по требованию таблицу MERGE. Это намного быстрее и позволит сэкономить дисковое пространство.
  • Таблицы MERGE позволяют обходить ограничения на размер файлов в операционных системах.
  • Можно создать псевдоним/синоним для таблицы - для этого нужно просто применить MERGE к одной таблице. Заметного падения производительности при этом наблюдаться не будет (только пара непрямых вызовов и вызовы memcpy() при каждом чтении).

Недостатки таблиц MERGE:

  • Для создания таблицы MERGE можно использовать только идентичные таблицы MyISAM.
  • Не работает команда REPLACE.
  • Для таблиц MERGE используется больше дескрипторов файлов. Если применяется таблица MERGE, преобразованная из более чем 10 таблиц, к которым получают доступ 10 пользователей, то используется 10*10 + 10 дескрипторов файлов (10 файлов данных для 10 пользователей и 10 общих индексных файлов).
  • Ключи считываются медленнее. При чтении ключа обработчику MERGE необходимо прочитать все базовые таблицы, чтобы выяснить, какая из них больше всего соответствует указанному ключу. Если после этого выполнить команду ``читать следующий'', то обработчик объединенной таблицы должен будет просмотреть буферы чтения, чтобы найти следующий ключ. Только по завершении использования одного буфера ключей обработчику понадобится прочитать следующий блок ключей. В связи с этим ключи MERGE дают большое замедление при поиске eq_ref, однако не такое значительное при поиске ref. See section 5.2.1 Синтаксис оператора EXPLAIN (получение информации о SELECT).
  • Нельзя выполнять команды DROP TABLE, ALTER TABLE, DELETE FROM table_name без оператора WHERE REPAIR TABLE, TRUNCATE TABLE, OPTIMIZE TABLE, или ANALYZE TABLE по отношению к таблицам, которые размещены в таблице MERGE и открыты. Если это сделать, в таблице MERGE останутся ссылки на исходную таблицу, и полученные результаты будут совершенно непредсказуемыми. Самый легкий путь обойти эти трудности - выполнить комманду FLUSH TABLES. Это удостоверит, что ни одна таблица MERGE не будет открытой.

При создании таблицы MERGE необходимо указать при помощи UNION(list-of-tables), какие таблицы требуется использовать как одну. В случае необходимости, если требуется производить вставку в таблицу MERGE в первую или в последнюю таблицу в списке UNION, можно задать INSERT_METHOD. Если не указать INSERT_METHOD или выбрать NO, то все команды INSERT для таблицы MERGE будут выдавать ошибку.

В приведенном ниже примере показано, как использовать таблицы MERGE:

CREATE TABLE t1 (a INT AUTO_INCREMENT PRIMARY KEY, message CHAR(20));
CREATE TABLE t2 (a INT AUTO_INCREMENT PRIMARY KEY, message CHAR(20));
INSERT INTO t1 (message) VALUES ("Testing"),("table"),("t1");
INSERT INTO t2 (message) VALUES ("Testing"),("table"),("t2");
CREATE TABLE total (a INT AUTO_INCREMENT PRIMARY KEY, message CHAR(20))
TYPE=MERGE UNION=(t1,t2) INSERT_METHOD=LAST;

Кроме того, можно управлять файлом `.MRG', находясь за пределами сервера MySQL:

shell> cd /mysql-data-directory/current-database
shell> ls -1 t1.MYI t2.MYI > total.MRG
shell> mysqladmin flush-tables

Теперь можно выполнять следующие действия:

mysql> SELECT * FROM total;
+---+---------+
| a | message |
+---+---------+
| 1 | Testing |
| 2 | table   |
| 3 | t1      |
| 1 | Testing |
| 2 | table   |
| 3 | t2      |
+---+---------+

Обратите внимание на то, что столбец a, хотя и объявлен как PRIMARY KEY, не является уникальным, так как таблица MERGE не может обеспечивать уникальность для всех таблиц MyISAM.

Чтобы повторно преобразовать таблицу MERGE, можно выбрать один из следующих вариантов:

  • Применить к таблице команду DROP и создать ее повторно
  • Воспользоваться командой ALTER TABLE table_name UNION(...)
  • Изменить файл `.MRG' и выполнить команду FLUSH TABLE над таблицей MERGE и всеми базовыми таблицами, чтобы обработчик прочитал новый файл определения.

7.2.1 Проблемы при работе с таблицами MERGE

При работе с таблицами MERGE могут возникать следующие проблемы:

  • Для таблицы MERGE не могут поддерживаться ограничения UNIQUE по всей таблице. При выполнении команды INSERT данные помещаются в первую или последнюю таблицу (в соответствии с INSERT_METHOD=xxx) и для этой таблицы MyISAM обеспечивается однозначность данных, но ей ничего не известно об остальных таблицах MyISAM.
  • Команда DELETE FROM merge_table без оператора WHERE очищает только распределение для таблицы, ничего не удаляя из преобразованных таблиц.
  • Использование команды RENAME TABLE над активной таблицей MERGE может привести к повреждению таблицы. Эта ошибка будет исправлена в MySQL 4.0.x.
  • При создании таблицы типа MERGE не проверяется совместимость типов базовых таблиц. Создав таблицу MERGE на основе несовместимых типов, вы можете столкнуться с непредсказуемыми проблемами.
  • Если для первого добавления индекса UNIQUE в таблицу, преобразованную в MERGE, используется команда ALTER TABLE, а затем командой ALTER TABLE в таблицу MERGE добавляется нормальный индекс, порядок ключей для таблиц будет разным, если в таблице был старый не однозначный ключ. Это происходит потому, что команда ALTER TABLE помещает ключи UNIQUE перед нормальными ключами, чтобы как можно раньше обнаружить дублирующиеся ключи.
  • Оптимизатор диапазона пока не может эффективно использовать таблицу MERGE, в связи с чем иногда возникают неоптимальные соединения. Это будет исправлено в MySQL 4.0.x.

Команда DROP TABLE над таблицей, преобразованной в таблицу MERGE, не будет работать под Windows, так как обработчик MERGE скрывает распределение таблиц от верхнего уровня MySQL. Поскольку в Windows не разрешается удалять открытые файлы, сначала необходимо сбросить на диск все таблицы MERGE (при помощи команды FLUSH TABLES) или удалить таблицу MERGE перед тем, как удалить таблицу. Эту ошибку мы планируем исправить одновременно с введением VIEW.

7.3 Таблицы ISAM

В MySQL пока еще можно применять и устаревший тип таблиц ISAM. В ближайшем времени этот тип будет исключен (возможно, в MySQL 5.0), так как MyISAM является улучшенной реализацией тех же возможностей. В таблицах ISAM используется индекс B-tree. Индекс хранится в файле с расширением `.ISM', а данные - в файле с расширением `.ISD'. Таблицы ISAM можно проверять/восстанавливать при помощи утилиты isamchk (see section 7.1 Таблицы MyISAM).

Ниже перечислены свойства таблиц ISAM:

  • Ключи со сжатой и фиксированной длиной
  • Фиксированная и динамическая длина записи
  • 16 ключей с 16 частями ключей/ключами
  • Максимальная длина ключа 256 (по умолчанию)
  • Данные хранятся в машинном формате; благодаря этому обеспечивается скорость, но возникает зависимость от компьютера/ОС.

Большинство параметров таблиц MyISAM также соответствуют таблицам ISAM. See section 7.1 Таблицы MyISAM. Ниже перечислены основные отличия таблиц ISAM от MyISAM:

  • Таблицы ISAM не являются переносимыми в двоичном виде с одной ОС/платформы на другую;
  • Невозможна работа с таблицами > 4Гб.
  • В строках поддерживается только сжатие префикса.
  • Ограничения по маленьким ключам.
  • Динамические таблицы больше фрагментируются.
  • Таблицы сжимаются при помощи pack_isam, а не при помощи myisampack.

Если вы хотите преобразовать таблицу ISAM в таблицу MyISAM, чтобы иметь возможность работать с такими утилитами, как mysqlcheck, воспользуйтесь оператором ALTER TABLE:

mysql> ALTER TABLE tbl_name TYPE = MYISAM;

Встроенные версии MySQL не поддерживают таблицы ISAM.

7.4 Таблицы HEAP

Для HEAP-таблиц используются хэш-индексы; эти таблицы хранятся в памяти. Благодаря этому обработка их осуществляется очень быстро, однако в случае сбоя MySQL будут утрачены все данные, которые в них хранились. Тип HEAP очень хорошо подходит для временных таблиц!

Для внутренних HEAP-таблиц в MySQL используется 100%-ное динамическое хэширование без областей переполнения; дополнительное пространство для свободных списков не требуется. Отсутствуют при использовании HEAP-таблиц и проблемы с командами удаления и вставки, которые часто применяются в хэшированных таблицах:

mysql> CREATE TABLE test TYPE=HEAP SELECT ip,SUM(downloads) AS down
    -> FROM log_table GROUP BY ip;
mysql> SELECT COUNT(ip),AVG(down) FROM test;
mysql> DROP TABLE test;

При использовании HEAP-таблиц необходимо обращать внимание на следующие моменты:

  • Необходимо всегда указывать параметр MAX_ROWS в операторе CREATE, чтобы случайным образом не занять всю память.
  • Индексы будут использоваться только с = и <=> (но ОЧЕНЬ быстрые).
  • В HEAP-таблицах для поиска строки могут использоваться только полные ключи, в то время как для таблиц MyISAM при поиске строк может применяться любой префикс ключа.
  • Для HEAP-таблиц используется формат с фиксированной длиной записи.
  • Для HEAP-таблиц не поддерживаются столбцы формата BLOB/TEXT.
  • Для HEAP-таблиц не поддерживаются столбцы формата AUTO_INCREMENT.
  • До версии 4.0.2 для HEAP-таблиц не поддерживаются индексы в столбцах формата NULL.
  • В HEAP-таблицах могут встречаться совпадающие ключи (что не является нормой для хэшированных таблиц).
  • HEAP-таблицы используются совместно всеми клиентами (как и все другие таблицы).
  • Нельзя производить поиск следующей записи в порядке следования (т.е. использовать индекс в команде ORDER BY).
  • Данные HEAP-таблиц расположены в маленьких блоках. Таблицы на 100% являются динамическими (при вставке). Нет необходимости ни в областях переполнения, ни в дополнительных ключах. Удаленные строки помещаются в связанный список и используются при вставке в таблицу новых данных.
  • Следует позаботиться о том, чтобы имелось достаточное количество дополнительной памяти для всех HEAP-таблиц, которые будут использоваться одновременно,.
  • Чтобы освободить память, необходимо запустить команду DELETE FROM heap_table, TRUNCATE heap_table или DROP TABLE heap_table.
  • MySQL не может подсчитать, сколько строк находится между двумя значениями (используется оптимизатором диапазонов для выбора используемого индекса). Это может повлиять на некоторые запросы, если преобразовать таблицу MyISAM в формат HEAP.
  • При создании размер таблицы HEAP не может превышать max_heap_table_size; это сделано для того, чтобы обеспечить защиту от случайных неквалифицированных действий.

Количество памяти, необходимой для одной строки в HEAP-таблице, вычисляется следующим образом:

SUM_OVER_ALL_KEYS(max_length_of_key + sizeof(char*) * 2)
+ ALIGN(length_of_row+1, sizeof(char*))

sizeof(char*) составляет 4 на 32-разрядных компьютерах и 8 - на 64-разрядных.

7.5 Таблицы InnoDB

7.5.1 Обзор таблиц InnoDB

Таблицы InnoDB в MySQL снабжены обработчиком таблиц, обеспечивающим безопасные транзакции (уровня ACID) с возможностями фиксации транзакции, отката и восстановления после сбоя. Для таблиц InnoDB осуществляется блокировка на уровне строки, а также используется метод чтения без блокировок в команде SELECT (наподобие применяющегося в Oracle). Перечисленные функции позволяют улучшить взаимную совместимость и повысить производительность в многопользовательском режиме. В InnoDB нет необходимости в расширении блокировки, так как блоки строк в InnoDB занимают очень мало места. Для таблиц InnoDB поддерживаются ограничивающие условия FOREIGN KEY.

InnoDB предназначается для получения максимальной производительности при обработке больших объемов данных. По эффективности использования процессора этот тип намного превосходит другие модели реляционных баз данных с памятью на дисках.

Технически InnoDB является завершенной системой управления базой данных в рамках MySQL. В InnoDB есть свой собственный буферный пул для кэширования данных и индексов в основной памяти. Таблицы и индексы InnoDB хранятся в специальном пространстве памяти, которое может состоять из нескольких файлов. В этом заключается отличие InnoDB от, например, таблиц MyISAM: каждая таблица MyISAM хранится в отдельном файле. Таблицы InnoDB могут быть любого размера даже в тех операционных системах, где установлено ограничение файла в 2 Гб.

Свежую информацию по InnoDB можно найти на http://www.innodb.com/. Здесь же находится последняя версия руководства по InnoDB. Кроме того, можно заказать коммерческие лицензии и поддержку для InnoDB.

В настоящий момент (октябрь 2001 года) таблицы InnoDB применяются на нескольких больших сайтах баз данных, для которых важна высокая производительность. Так, таблицы InnoDB используются на популярном сайте новостей Slashdot.org. Формат InnoDB применяется для хранения более 1Тб данных компании Mytrix, Inc; можно привести пример еще одного сайта, где при помощи при помощи InnoDB обрабатывается средняя нагрузка объемом в 800 вставок/обновлений в секунду.

Таблицы InnoDB входят в дистрибутив исходных текстов MySQL, начиная с версии 3.23.34a; они активизированы в исполняемом коде MySQL -Max. Для Windows исполняемые коды -Max находятся в стандартном дистрибутиве.

Если вы загрузили исполняемую версию MySQL, которая включает поддержку InnoDB, следует просто выполнить инструкции руководства MySQL по установке исполняемой версии MySQL. В случае, если у вас уже установлен MySQL-3.23, проще всего установить MySQL -Max, чтобы заменить исполняемый файл `mysqld' соответствующим файлом из дистрибутива -Max. Различными в MySQL и MySQL -Max являются только исполняемые файлы сервера. См. разделы section 2.2.10 Установка бинарного дистрибутива MySQL и See section 4.7.5 mysqld-max, расширенный сервер mysqld.

Чтобы произвести компиляцию MySQL с поддержкой InnoDB, загрузите MySQL-3.23.34a или более новую версию с http://www.mysql.com/ и настройте MySQL при помощи параметра --with-innodb. См. раздел руководства MySQL по установке дистрибутива исходного кода MySQL, See section 2.3 Установка исходного дистрибутива MySQL.

cd /path/to/source/of/mysql-3.23.37
./configure --with-innodb

Чтобы использовать InnoDB, необходимо указать параметры запуска InnoDB в своем файле `my.cnf' или `my.ini'. Самый простой способ внести изменения - добавить в раздел [mysqld] строку

innodb_data_file_path=ibdata:30M

Однако чтобы добиться высокой скорости работы, лучше указать рекомендуемые параметры. See section 7.5.2 Параметры запуска InnoDB.

InnoDB распространяется на условиях общедоступной лицензии версии 2 (от июня 1991 года). В дистрибутиве исходного кода MySQL InnoDB находится в подкаталоге `innobase'.

7.5.2 Параметры запуска InnoDB

Чтобы использовать таблицы InnoDB в MySQL-Max-3.23, НЕОБХОДИМО задать параметры конфигурации в разделе [mysqld] файла конфигурации `my.cnf' или в файле параметров Windows `my.ini'.

В версии 3.23 как минимум необходимо указать имя и размер файлов данных в innodb_data_file_path. Если вы не указали innodb_data_home_dir в `my.cnf' по умолчанию эти файлы создаются в директории данных MySQL. Если вы указали innodb_data_home_dir как пустую строку, то вы должны указать полный путь к вашим файлам данным в innodb_data_file_path. В MySQL 4.0 не требуется задавать даже innodb_data_file_path: по умолчанию для него создается автоматически увеличивающийся файл размером в 10 Мб с именем `ibdata1' в каталоге `datadir' MySQL. (в MySQL-4.0.0 и 4.0.1 размер файла данных составляет 64 Мб и он не является автоматически увеличивающимся).

Если вы не хотите использовать InnoDB таблицы, вы можете добавить опцию skip-innodb в конфигурационный файл MySQL.

Однако для того, чтобы получить высокую производительность, НЕОБХОДИМО явно задать параметры InnoDB, перечисленные в следующих примерах.

Начиная с версий 3.23.50 и 4.0.2 для InnoDB имеется возможность задавать последний файл данных в innodb_data_file_path как автоматически увеличивающийся. В этом случае для innodb_data_file_path используется следующий синтаксис:

pathtodatafile:sizespecification;pathtodatafile:sizespecification;...
... ;pathtodatafile:sizespecification[:autoextend[:max:sizespecification]]

Если последний файл данных указан с параметром автоматического увеличения, то в случае нехватки места для табличной области InnoDB будет увеличивать последний файл данных; приращение файла каждый раз составляет 8 Мб. Например, синтаксис:

innodb_data_home_dir =
innodb_data_file_path = /ibdata/ibdata1:100M:autoextend

указывает InnoDB создать один файл данных с начальным размером 100 Мб, который будет увеличиваться на 8 Мб каждый раз, когда не будет хватать места. Если текущий диск окажется заполненным, можно, к примеру, добавить еще один файл данных на другой диск. При задании размера автоматически увеличивающегося файла `ibdata1' следует округлить его текущий размер до ближайшего числа, кратного 1024 * 1024 байтам (= 1 Мб), и явно указать округленный размер `ibdata1' в innodb_data_file_path. После этой записи можно добавить еще один файл данных:

innodb_data_home_dir =
innodb_data_file_path = /ibdata/ibdata1:988M;/disk2/ibdata2:50M:autoextend

Следует соблюдать осторожность при работе в файловых системах, в которых установлено ограничение на размер файла в 2 Гб! Максимальный для данной операционной системы размер файла InnoDB не известен. В таком случае желательно указать максимальный размер файла данных:

innodb_data_home_dir =
innodb_data_file_path = /ibdata/ibdata1:100M:autoextend:max:2000M

Простой пример файла `my.cnf'. Предположим, что у вас есть компьютер с 128 Мб ОЗУ и одним жестким диском. Ниже приведены примеры возможных параметров конфигурации в `my.cnf' или `my.ini' для InnoDB. Мы предполагаем что у вас запущен MySQL-Max-3.23.50 и выше или MySQL-4.0.2 и выше. Этот пример подходит для большинства пользователей работающих под Unix и Windows, которые не хотят располагать файлы данных и журнальные файлы на различных дисках. В этом примере создается автоматически увеличивающийся файл `ibdata1' и два журнальных файла `ib_logfile0' и `ib_logfile1' в в директории данных MySQL (обычно `/mysql/data'). Небольшой архивный журнальный файл InnoDB `ib_arch_log_0000000000' также располагается в каталоге datadir:

[mysqld]
# Сюда  можно  добавить  другие  опции MySQL
# ...
#
# Файлы  данных  должны  иметь  достаточно
# места  для  сохранения  ваших  данных  и
# индексов. Убедитесь что у вас достаточно
# свободного места на диске.
innodb_data_file_path = ibdata1: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
# Если  допустима  потеря  некоторых
# последних  транзакций, установите
# flush_log_в_trx_commit в 0
innodb_flush_log_at_trx_commit=1

Убедитесь, что MySQL server имеет права создавать файлы в datadir.

Не забывайте, что в некоторых файловых системах существует ограничение в 2 Гб на размер файла данных! Общий размер файлов журналов должен быть меньше 4 Гб, а общий размер файлов данных - больше или равен 10Мб.

При первом создании базы данных InnoDB лучше всего запустить сервер MySQL из командной строки. Тогда на экран будет выводиться информация о создании базы данных и вы сможете увидеть, что происходит. Смотрите следующий раздел, в котором описано, на что должна быть похожа выводимая информация. Например, в Windows можно запустить `mysqld-max.exe' с параметрами:

your-path-to-mysqld>mysqld-max --console

Где поместить файл `my.cnf' или `my.ini' в Windows? Для Windows существуют следующие правила:

  • Должен быть создан только один файл `my.cnf' или `my.ini'.
  • Файл `my.cnf' должен находиться в корневом каталоге диска `C:'.
  • Файл `my.ini' должен находиться в каталоге `WINDIR', например в `C:\WINDOWS' или `C:\WINNT'. Чтобы вывести значение `WINDIR', можно воспользоваться командой SET операционной системы MS-DOS.
  • Если на вашем компьютере применяется загрузчик операционной системы, в котором диск `C:' не является загрузочным, то необходимо использовать файл `my.ini'.

Где указываются параметры в Unix?

В Unix mysqld считывает параметры из следующих файлов, если они существуют, в таком порядке:

  • `/etc/my.cnf' - общие параметры.
  • `COMPILATION_DATADIR/my.cnf' -- параметры для сервера.
  • `defaults-extra-file' -- файл, указанный при помощи --defaults-extra-file=....
  • `~/.my.cnf' - параметры для пользователя.

COMPILATION_DATADIR представляет собой каталог данных MySQL, который был указан как параметр ./configure при компиляции mysqld (обычно `/usr/local/mysql/data' для установки исполняемых файлов или `/usr/local/var' для установки исходного кода).

Если точно не известно, откуда mysqld считывает свои файлы `my.cnf' или `my.ini', можно задать путь как первый параметр командной строки для сервера: mysqld --defaults-file=your_path_to_my_cnf.

InnoDB формирует полный путь к файлу данных путем соединения innodb_data_home_dir и имени файла данных или пути в innodb_data_file_path, добавляя при необходимости косую черту. Если ключевое слово innodb_data_home_dir не упоминается в `my.cnf' совсем, по умолчанию используется директория данных MySQL.

Пример расширенного файла `my.cnf'

Предположим, что у вас есть компьютер Linux с 2 Гб ОЗУ и тремя жесткими дисками по 60 Гб (с путями каталогов ``/'', ``/dr2'' and ``/dr3''). Ниже приведен пример возможных параметров конфигурации в `my.cnf' для InnoDB:

Учтите, что InnoDB не создает директории: вы должны создать их самостоятельно. Используйте комманду Unix или MS-DOS mkdir для создания домашней директории для InnoDB и домашней директории для группы журнальных файлов.

[mysqld]
# Здесь  вы  можете  задать  другие  опции  сервера MySQL
# ...
#
innodb_data_home_dir =
# Файлы  данных  должны  иметь  достаточно
# места  для  сохранения  ваших  данных  и
# индексов
innodb_data_file_path = /ibdata/ibdata1:2000M;/dr2/ibdata/ibdata2:2000M:autoextend
# Размер  буферного  пула  следует  задавать
# как 50 - 80% памяти  компьютера, но
# для Linux x86 следует  убедиться, что
# общий  расход  памяти  не  превышает 2 Гб
set-variable = innodb_buffer_pool_size=1G
set-variable = innodb_additional_mem_pool_size=20M
innodb_log_group_home_dir = /dr3/iblogs
# .._log_arch_dir должен  быть  такой
# же, как _log_group_home_dir
innodb_log_arch_dir = /dr3/iblogs
set-variable = innodb_log_files_in_group=3
# Размер  файла  журналов  должен  составлять
# около 15 % от  размера  буферного  пула
set-variable = innodb_log_file_size=150M
set-variable = innodb_log_buffer_size=8M
# Если  допустима  потеря  некоторых
# последних  транзакций, установите
# flush_log_в_trx_commit в 0
innodb_flush_log_at_trx_commit=1
set-variable = innodb_lock_wait_timeout=50
#innodb_flush_method=fdatasync
#set-variable = innodb_thread_concurrency=5

Обратите внимание на то, что два файла данных размещены на разных дисках. InnoDB будет заполнять табличное пространство, образованное файлами данных, снизу вверх. В некоторых случаях это позволяет увеличить производительность баз данных, если не все данные размещены на одном физическом диске. Размещение файлов журнала на другом диске очень часто позволяет повысить производительность. Для файлов данных можно также использовать разделы реального диска (реальные устройства): в некоторых версиях Unix это ускоряет операции ввода/вывода. Информацию по указанию параметров в `my.cnf' вы найдете в разделе руководства по управлению пространством файлов InnoDB.

Предупреждение: в Linux x86 необходимо соблюдать осторожность, чтобы не установить слишком высокое значение использования памяти. glibc может дать процессу разрастись и превысить стеки потоков, что приведет к сбою сервера. Степень риска значительно повышается, если значение

innodb_buffer_pool_size + key_buffer +
max_connections * (sort_buffer + read_buffer_size) + max_connections * 2 MB

приближается к значению 2 Гб или превышает его. Каждый поток будет использовать стек (обычно 2 Мб, но в бинарной поставке MySQL AB только 256 Кб) и в худшем случае также дополнительную память sort_buffer + read_buffer_size.

Как настроить другие параметры сервера mysqld? Для большинства пользователей подходят следующие стандартные значения:

skip-locking
set-variable = max_connections=200
set-variable = read_buffer_size=1M
set-variable = sort_buffer=1M
# Размер key_buffer следует  задавать  как
# 5%-50% от  вашего  ОЗУ, в  зависимости
# от  того, как  часто  у  вас  используются
# таблицы MyISAM, но key_buffer +
# размер  буферного  пула InnoDB не  должен
# превышать 80% вашего  ОЗУ
set-variable = key_buffer=...

Обратите внимание на то, что некоторые параметры представлены при помощи формата числового параметра `my.cnf': set-variable = innodb... = 123, а остальные (строчные и логические параметры) - при помощи другого формата: innodb_... = ....

Параметры настройки имеют следующие значения:

Параметр | Описание
innodb_data_home_dir | Общая часть пути к каталогу всех файлов данных InnoDB. Если вы не указали этот параметр в `my.cnf', то по умолчанию для этого параметра принято значение datadir MySQL. Если вы указали как пустою строку, то в этом случае вы можете использовать полный путь в innodb_data_file_path.
innodb_data_file_path | Пути к отдельным файлам данных и их размеры. Полный путь к каталогу каждого файла данных получается путем объединения innodb_data_home_dir с путем, который задается данным параметром. Размеры файлов указаны в мегабайтах. InnoDB также ``понимает'' сокращение 'G', 1 G означает 1024 М. Начиная с версии 3.23.44 в операционных системах, где поддерживаются большие файлы, можно задавать размер файла, превышающий 4 Гб. В некоторых операционных системах файлы должны быть < 2 Гб. Общий объем файлов должен быть как минимум 10 Мб.
innodb_mirrored_log_groups | Количество идентичных копий групп журналов, которые хранятся для базы данных. На данный момент этому параметру должно быть присвоено значение 1.
innodb_log_group_home_dir | Путь к каталогу файлов журналов InnoDB.
innodb_log_files_in_group | Количество файлов журналов в группе журналов. InnoDB производит запись в файлы по круговому способу. Для этого параметра рекомендуется установить значение "3".
innodb_log_file_size | Размер каждого файла журнала в группе журналов (указывается в мегабайтах). Разумный диапазон значений составляет от 1М до 1/N от размера буферного пула, приведенного ниже, где N - количество файлов журналов в группе. Чем больше это значение, тем меньше требуется сбросов на диск информации из буферного пула, что сокращает количество дисковых операций ввода/вывода. Однако в случае сбоя восстановление при больших размерах файлов журналов займет больше времени. Общий размер файлов журналов на 32-разрядных компьютерах должен быть < 4 Гб.
innodb_log_buffer_size | Размер буфера, который в InnoDB используется для записи информации файлов журналов на диск. Разумный диапазон значений составляет от 1М до 8М. Большой буфер журналов позволяет осуществлять объемные транзакции без записи журнала на диск до завершения транзакции. Поэтому если ваши транзакции отличаются значительными объемами, увеличение буфера журналов сократит количество операций ввода/вывода диска.
innodb_flush_log_at_trx_commit | Обычно этому параметру присваивается значение 1; при этом значении после завершения транзакции информация журнала записывается на диск и фиксируются изменения, внесенные транзакцией, благодаря чему данные сохраняются в случае сбоя базы данных. Если у вас выполняется большое количество маленьких транзакций и вы готовы пожертвовать такой возможностью, можно установить значение этого параметра в 0, чтобы снизить количество обращений к диску.
innodb_log_arch_dir | Каталог, в котором будут храниться заполненные файлы журналов, если включено архивирование журналов. Значение этого параметра на настоящий момент должно задаваться таким же, как и для innodb_log_group_home_dir.
innodb_log_archive | На данный момент значение этого параметра должно устанавливаться в 0. Поскольку восстановление из резервной копии MySQL осуществляет при помощи своих собственных файлов журналов, архивировать файлы журналов InnoDB нет необходимости.
innodb_buffer_pool_size | Размер буфера памяти, который InnoDB использует для кэширования данных и индексов своих таблиц. Чем больше это значение, тем меньше обращений к диску осуществляется при получении доступа к данным таблиц. На специально выделенном сервере баз данных этот параметр можно установить в значение до 80% физической памяти компьютера. Однако для этого параметра не следует задавать слишком большое значение, так как при недостатке физической памяти операционная система будет вынуждена сбрасывать часть информации на диск.
innodb_additional_mem_pool_size | Размер пула памяти, который InnoDB использует для хранения информации словаря данных и других внутренних структур данных. Разумным значением для этого параметра может быть 2М, но чем больше таблиц в вашем приложении, тем больше информации нужно будет разместить в этом пуле. Если памяти в этом пуле будет недостаточно для InnoDB, то будет выделятся память операционной системы, а в файл журнала MySQL будут записываться предупреждающие сообщения.
innodb_file_io_threads | Количество потоков ввода/вывода файлов в InnoDB. Обычно этому параметру присваивается значение 4, но в Windows при помощи увеличения данного значения можно сократить количество обращений к диску.
innodb_lock_wait_timeout | Время простоя (в секундах), на протяжении которого транзакция InnoDB может ожидать блокировки прежде, чем будет произведен откат. InnoDB автоматически обнаруживает зависшие транзакции в своей таблице блокировок и производит откат транзакций. Если в той же самой транзакции используется команда LOCK TABLES, или другие обработчики таблиц с безопасными транзакциями, отличными от InnoDB, то может возникнуть зависание, которое не будет обнаружено InnoDB. В таких ситуациях параметр времени простоя помогает устранить проблему.
innodb_flush_method (Доступен, начиная с версий 3.23.40 и выше). По умолчанию для этого параметра принято значение fdatasync. Другой возможный вариант - O_DSYNC.

7.5.3 Создание табличной области InnoDB

Предположим, что вы установили MySQL и внесли в файл `my.cnf' необходимые параметры настройки InnoDB. Прежде чем запустить MySQL, необходимо убедиться, что указанные каталоги для файлов данных и журналов InnoDB существуют, и что у вас есть право доступа к этим каталогам. InnoDB может создавать только файлы, но не каталоги. Проверьте также, достаточно ли у вас свободного дискового пространства для файлов данных и журналов.

Теперь при запуске MySQL InnoDB начнет создавать ваши файлы данных и файлы журналов. При этом будет выводиться примерно такая информация:

~/mysqlm/sql > mysqld
InnoDB: The first specified datafile /home/heikki/data/ibdata1
did not exist:
InnoDB: a new database to be created!
InnoDB: Setting file /home/heikki/data/ibdata1 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_logfile0 did not exist:
new to be created
InnoDB: Setting log file /home/heikki/data/logs/ib_logfile0 size to
5242880
InnoDB: Log file /home/heikki/data/logs/ib_logfile1 did not exist:
new to be created
InnoDB: Setting log file /home/heikki/data/logs/ib_logfile1 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, InnoDB выведет примерно следующее:

010321 18:33:34 mysqld: Normal shutdown
010321 18:33:34 mysqld: Shutdown Complete
InnoDB: Starting shutdown...
InnoDB: Shutdown completed

Теперь можно просмотреть каталоги файлов данных и журналов, чтобы увидеть, какие файлы были созданы. В каталоге журналов будет также находиться небольшой файл ib_arch_log_0000000000. Этот файл появляется в результате создания базы данных, после чего InnoDB отключает архивирование журналов. При новом запуске MySQL будет выведена примерно следующая информация:

~/mysqlm/sql > mysqld
InnoDB: Started
mysqld: ready for connections

7.5.3.1 Если во время создания базы данных что-то происходит не так

Если InnoDB выдает ошибку операционной системы во время операции с файлом, то причиной возникшей проблемы, как правило, является одна из следующих:

    Вы не создали каталоги для файлов данных или журналов InnoDB.
  • У mysqld нет прав на создание файлов в этих каталогах.
  • mysqld не считал нужный файл `my.cnf' или `my.ini' и, соответственно, не получил указанных вами параметров.
  • Диск переполнен или превышена квота использования диска.
  • Вы создали подкаталог, имя которого совпадает с указанным файлом данных.
  • Синтаксическая ошибка в innodb_data_home_dir или innodb_data_file_path.

Если что-то происходит не так во время создания базы данных InnoDB, необходимо удалить все файлы, созданные InnoDB. В их число входят все файлы данных, все файлы журналов, небольшой архивный файл журнала; если вы уже создали какие-либо таблицы InnoDB, то следует также удалить соответствующие им файлы `.frm', которые находятся в каталогах баз данных MySQL. После этого можно попробовать создать базу данные InnoDB еще раз.

7.5.4 Создание таблиц InnoDB

Предположим, что у вас запущен клиент MySQL при помощи команды mysql test. Чтобы создать таблицу в формате InnoDB, необходимо в команде создания таблицы SQL указать TYPE = InnoDB:

CREATE TABLE CUSTOMER (A INT, B CHAR (20), INDEX (A)) TYPE = InnoDB;

Эта команда SQL создаст таблицу и индекс в столбце A табличной области InnoDB. Кроме того, MySQL создаст файл `CUSTOMER.frm' каталоге баз данных MySQL с именем `test'. В свой собственный словарь данных InnoDB добавит запись для таблицы test/CUSTOMER. Таким образом, можно создать таблицу с таким же именем CUSTOMER в другой базе данных MySQL, и это не приведет к конфликту имен таблиц в рамках InnoDB.

Для любой таблицы, которая была создана с параметром TYPE = InnoDB, можно запросить количество свободного пространства в табличной области InnoDB. Для этого нужно выполнить команду запроса состояния таблицы. Количество свободного пространства будет выводиться в разделе примечаний к таблице в выходной информации команды SHOW.

Например:

SHOW TABLE STATUS FROM test LIKE 'CUSTOMER'

Обратите внимание на то, что статистические данные, которые команда SHOW выдает по таблицам InnoDB, являются приблизительными: они используются для оптимизации SQL. Точными являются зарезервированные размеры таблицы и индекса, значения которых выдаются в байтах.

7.5.4.1 Преобразование таблиц MyISAM в формат InnoDB

В InnoDB отсутствует специальная оптимизация создания отдельных индексов. Таким образом, этот формат не обеспечивает экспорта и импорта таблиц с последующим созданием индексов. Самый быстрый способ преобразовать таблицу в формат InnoDB - напрямую вставить данные в таблицу InnoDB, воспользовавшись командой ALTER TABLE ... TYPE=INNODB, или создать пустую таблицу InnoDB с такой же структурой и вставить строки при помощи команды INSERT INTO ... SELECT * FROM ....

Чтобы лучше контролировать процесс вставки, большие таблицы желательно вставлять по частям:

INSERT INTO newtable SELECT * FROM oldtable
   WHERE yourkey > something AND yourkey <= somethingelse;

После того, как все данные будут вставлены, таблицы можно будет переименовать.

Во время преобразования больших таблиц необходимо задать достаточно большой размер динамического буфера InnoDB, чтобы снизить количество дисковых операций ввода/вывода. Однако размер буфера не должен превышать 80% физической памяти компьютера. Следует установить большие размеры для файлов журналов InnoDB, а также большой размер буфера журналов.

Убедитесь, что у вас достаточно свободного пространства для табличной области: таблицы InnoDB занимают намного больше места, чем таблицы MyISAM. Если во время выполнения команды ALTER TABLE будет исчерпано свободное дисковое пространство, начнется выполнение отката, и это может занять несколько часов, если диск заполнен. Во время вставок для таблицы InnoDB используется буфер вставки, чтобы произвести объединение вторичных индексных записей с индексными таблицами при помощи групповых операций. Это позволяет значительно снизить интенсивность дисковых операций ввода/вывода. При откате такой механизм не используется, поэтому откат может занять в 30 раз больше времени, чем вставка.

В случае, если началось выполнение отката и база данных не содержит ценной информации, лучше прервать этот процесс и удалить все данные InnoDB, файлы журналов, а также все таблицы InnoDB (файлы с расширением `.frm'), и начать свою работу сначала, а не ждать завершения выполнения миллионов операций ввода/вывода диска.

7.5.4.2 Ограничения внешнего ключа

Начиная с версии 3.23.43b, в InnoDB включены ограничения внешних ключей. InnoDB - первый формат таблиц MySQL, который обеспечивает возможность задавать ограничения внешнего ключа, чтобы обеспечить целостность данных.

Синтаксис задания ограничения внешнего ключа в InnoDB следующий:

[CONSTRAINT symbol] FOREIGN KEY (index_col_name, ...)
                    REFERENCES table_name (index_col_name, ...)
                    [ON DELETE {CASCADE | SET NULL | NO ACTION
                                | RESTRICT}]
                    [ON UPDATE {CASCADE | SET NULL | NO ACTION
                                | RESTRICT}]

Обе таблицы должны быть InnoDB-типа; обязательно также наличие индекса, в котором внешний ключ и ссылочный ключ должны находиться в ПЕРВЫХ столбцах. Для таблиц InnoDB индексы по внешним ключам или ссылочным ключам не создаются автоматически: их создание требуется задавать явно.

Соответствующие столбцы внешнего и ссылочного ключей в таблице InnoDB должны содержать одинаковые типы данных, чтобы их можно было сравнивать без преобразования типов. Размер и знак целочисленных типов должны быть одинаковыми. Длины для строковых типов могут не совпадать.

Если вы указали действие SET NULL, убедитесь что вы не объявили столбец в дочерней таблице как NOT NULL.

Если оператор MySQL CREATE TABLE выдает ошибку с номером 1005, и в строке сообщения об ошибке присутствует ссылка на ошибку с номером 150, то произошел сбой создания таблицы из-за того, что ограничения внешнего ключа не были сформированы надлежащим образом. Аналогично и для оператора ALTER TABLE: если происходит ошибка при выполнении оператора и в сообщении присутствует ссылка на ошибку с номером 150, то определение внешнего ключа для преобразовываемой таблицы сформировано неправильно.

Начиная с версии 3.23.50 с ограничением внешнего ключа можно также связывать выражения ON DELETE CASCADE или ON DELETE SET NULL. Начиная с версии 4.0.8 вы можете это же использовать с ON UPDATE.

Если указано выражение ON DELETE CASCADE и строка в родительской таблице удалена, то в формате InnoDB все эти строки автоматически удаляются также и из дочерней таблицы, значения внешнего ключа которой равны значениям ссылочного ключа в строке родительской таблицы. Если указано выражение ON DELETE SET NULL, строки дочерней таблицы автоматически обновляются, поэтому столбцам во внешнем ключе также присваивается значение SQL NULL.

Начиная с версии 3.23.50 в InnoDB не осуществляется проверка ограничений внешних ключей на наличие значений внешних или родительских ключей, которые содержат столбец NULL.

Начиная с версии 3.23.50 синтаксический анализатор InnoDB обеспечивает возможность использовать обратные кавычки (`), ограничивающие имена таблиц и столбцов в FOREIGN KEY ... REFERENCES ..., однако синтаксический анализатор InnoDB еще ``не знает'' об опции lower_case_table_names, которая может быть задана в файле `my.cnf'.

Пример:

CREATE TABLE parent(id INT NOT NULL, PRIMARY KEY (id)) TYPE=INNODB;
CREATE TABLE child(id INT, parent_id INT, INDEX par_ind (parent_id),
         FOREIGN KEY (parent_id) REFERENCES parent(id)
         ON DELETE SET NULL
) TYPE=INNODB;

Начиная с версии 3.23.50, для таблиц InnoDB обеспечивается возможность добавлять новые ограничения внешних ключей для таблиц при помощи

ALTER TABLE yourtablename
  ADD [CONSTRAINT symbol] FOREIGN KEY (...) REFERENCES anothertablename(...)

Однако не следует забывать предварительно создавать необходимые индексы. В InnoDB версий < 3.23.50 команды ALTER TABLE или CREATE INDEX не должны использоваться совместно с таблицами, для которых установлены ограничения внешнего ключа или на которые есть ссылки в ограничениях внешних ключей: Команда ALTER TABLE удаляет все ограничения внешних ключей, определенные в таблице. Не следует использовать команду ALTER TABLE для таблиц, на которые есть ссылки; вместо этого необходимо применять команды DROP TABLE и CREATE TABLE, чтобы изменить логическую структуру. При выполнении команды ALTER TABLE MySQL может использовать команду RENAME TABLE, что нарушит ограничения внешнего ключа, относящиеся к таблице. Оператор CREATE INDEX в MySQL обрабатывается таким же образом, как и ALTER TABLE, поэтому приведенные выше ограничения распространяются и на этот оператор.

При проверке внешних ключей для таблиц InnoDB устанавливается совместно используемая блокировка строк на подлежащих просмотру родительских или дочерних записях. Проверка ограничений внешнего ключа для таблиц InnoDB производится немедленно и не откладывается до принятия транзакции.

Формат InnoDB обеспечивает возможность удалить любую таблицу, даже если это нарушит ограничения внешнего ключа, ссылающегося на таблицу. При удалении таблицы также удаляются ограничения, определенные оператором ее создания.

Если удаленная таблица создается повторно, ее определение должно быть согласовано с ограничениями внешнего ключа, который на нее ссылается. В этой таблице необходимо правильно задать имена и типы столбцов; в ней также должны присутствовать индексы ключей, на которые производится ссылка, как указано выше. Если эти условия не будут выполнены, MySQL выдаст ошибку с номером 1005 и ссылку на ошибку с номером 150 в строке сообщения об ошибке.

Начиная с версии 3.23.50 InnoDB возвращает определения внешних ключей таблицы, если вызвать

SHOW CREATE TABLE yourtablename

Помимо этого, mysqldump выводит корректные определения таблиц в файл дампа, ``не забывая'' о внешних ключах.

Список ограничений внешнего ключа таблицы T можно также вывести при помощи команды

SHOW TABLE STATUS FROM yourdatabasename LIKE 'T'

Ограничения внешнего ключа выводятся в комментариях к таблице.

7.5.5 Добавление и удаление файлов данных и журналов InnoDB

Начиная с версий 3.23.50 и 4.0.2, можно указать последний файл данных InnoDB как autoextend. Можно также увеличить табличную область, указав дополнительные файлы данных. Для этого необходимо остановить сервер MySQL, внести изменения в файл `my.cnf', добавив новый файл данных к innodb_data_file_path, а затем запустить сервер MySQL снова.

На данный момент нельзя удалить файл данных из InnoDB. Чтобы уменьшить размер своей базы данных, необходимо воспользоваться mysqldump, чтобы сделать дамп всех своих таблиц, создать новую базу данных и импортировать таблицы в новую базу данных.

Если необходимо изменить количество или размер файлов журналов InnoDB, необходимо остановить MySQL и убедиться, что работа была завершена без ошибок. После этого нужно скопировать старые файлы журналов в безопасное место - на случай, если завершение работы было произведено с ошибками и потребуется восстановление базы данных. Затем следует удалить старые файлы журналов из каталога файлов журналов, внести изменения в `my.cnf' и снова запустить MySQL. InnoDB при запуске сообщит о создании новых файлов журналов.

7.5.6 Создание резервных копий и восстановление баз данных InnoDB

Чтобы обеспечить безопасное управление базами данных, необходимо регулярно создавать резервные копии.

Существует интерактивный инструмент, который можно использовать для создания резервных копий своих баз данных InnoDB, когда они открыты, - InnoDB Hot Backup. Для своей работы InnoDB Hot Backup не требует закрытия базы данных, блокировки данных или нарушения обычного хода обработки базы данных. InnoDB Hot Backup является платным дополнительным инструментом, не входящим в стандартный дистрибутив MySQL. Чтобы получить дополнительную информацию о нем и просмотреть копии экрана, см. домашнюю страницу InnoDB Hot Backup http://www.innodb.com/hotbackup.html.

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

  • Закройте свою базу данных MySQL и убедитесь, что закрытие было произведено без ошибок.
  • Скопируйте все свои файлы данных в безопасное место.
  • Скопируйте все свои файлы журналов InnoDB в безопасное место.
  • Скопируйте свой файл конфигурации `my.cnf' в безопасное место.
  • Скопируйте все файлы `.frm' своих таблиц InnoDB в безопасное место.

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

Дампы лучше всего создавать одновременно с созданием двоичной резервной копии своей базы данных. Чтобы получить согласованную копию всех своих таблиц в дампах, необходимо запретить всем клиентам доступ к базе данных. Затем можно создать двоичную резервную копию и получить согласованные копии своей базы данных в двух форматах.

Чтобы восстановить исходное состояние своей базы данных InnoDB из описанной выше двоичной резервной копии, необходимо запустить свою базу данных MySQL с включенными общим журналом и архивацией журналов MySQL (здесь под общим журналом подразумевается механизм занесения записей в журнал сервера MySQL, независимый от журналов InnoDB).

Единственное, что нужно сделать для восстановления процесса MySQL после сбоя, - перезапустить его. InnoDB автоматически произведет проверку журналов и выполнит восстановление базы данных, а также автоматически произведет откат по незавершенным транзакциям, которые проводились на момент сбоя. Во время восстановления InnoDB будет выводить примерно следующую информацию:

~/mysqlm/sql > mysqld
InnoDB: Database was not shut down normally.
InnoDB: Starting recovery from log files...
InnoDB: Starting log scan based on checkpoint at
InnoDB: log sequence number 0 13674004
InnoDB: Doing recovery: scanned up to log sequence number 0 13739520
InnoDB: Doing recovery: scanned up to log sequence number 0 13805056
InnoDB: Doing recovery: scanned up to log sequence number 0 13870592
InnoDB: Doing recovery: scanned up to log sequence number 0 13936128
...
InnoDB: Doing recovery: scanned up to log sequence number 0 20555264
InnoDB: Doing recovery: scanned up to log sequence number 0 20620800
InnoDB: Doing recovery: scanned up to log sequence number 0 20664692
InnoDB: 1 uncommitted transaction(s) which must be rolled back
InnoDB: Starting rollback of uncommitted transactions
InnoDB: Rolling back trx no 16745
InnoDB: Rolling back of trx no 16745 completed
InnoDB: Rollback of uncommitted transactions completed
InnoDB: Starting an apply batch of log records to the database...
InnoDB: Apply batch completed
InnoDB: Started
mysqld: ready for connections

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

7.5.6.1 Контрольные точки

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

В случае восстановления после сбоя InnoDB производит поиск меток контрольных точек, записанных в файлы журналов. Известно, что все изменения базы данных, внесенные перед меткой, уже записаны в образ базы данных на диске. Затем InnoDB производит сканирование файлов журналов начиная от места контрольной точки, и вносит зафиксированные изменения в базу данных.

Запись в файлы журналов в InnoDB осуществляется по круговому методу. Все внесенные изменения, после которых страницы базы данных в буфере начинают отличаться от образа на диске, должны быть записаны в файлы журналов, на случай, если InnoDB понадобится произвести восстановление. Это означает, что когда InnoDB начинает повторно использовать файл журнала по круговому методу, производится проверка на наличие в образах страниц базы данных на диске изменений, зафиксированных в файле журнала, который InnoDB собирается повторно использовать. Иначе говоря, необходимость поставить контрольную точку зачастую приводит к тому, что InnoDB сбрасывает измененные страницы базы данных на диск.

Из сказанного выше становится понятно, почему при больших файлах журналов сокращается количество дисковых операций ввода/вывода при создании контрольных точек. Иногда имеет смысл задавать общий размер файлов журналов равным буферному пулу или даже больше. Недостатком больших файлов журналов является то, что восстановление после сбоя может длиться дольше, так как к базе данных придется применить больше информации из файла журнала.

7.5.7 Перенесение базы данных InnoDB на другой компьютер

Файлы данных и журналов InnoDB на двоичном уровне совместимы на всех платформах, если на компьютерах совпадает формат чисел с плавающей десятичной запятой. Базу данных InnoDB можно перенести, просто скопировав все относящиеся к ней файлы (список которых был приведен в предыдущем разделе, посвященном созданию резервных копий базы данных). Если компьютеры имеют различные форматы чисел с плавающей десятичной запятой, но типы данных FLOAT или DOUBLE в ваших таблицах не задействованы, последовательность действий остается точно такой же: нужно просто скопировать все относящиеся к базе данных файлы. Если же при наличии различных форматов в ваших таблицах содержатся данные с плавающей десятичной запятой, то для перемещения таких таблиц необходимо воспользоваться командами mysqldump и mysqlimport.

Чтобы увеличить скорость обработки, можно отключить автоматическую фиксацию транзакций при импортировании в свою базу данных, исходя из предположения, что ваша табличная область содержит достаточно пространства для отката большого сегмента на случай генерации большой транзакции импортирования. Фиксация производится только после импорта всей таблицы или сегмента таблицы.

7.5.8 Транзакционная модель InnoDB

Назначение транзакционной модели InnoDB заключается в том, чтобы совместить лучшие свойства многовариантной базы данных и традиционной двухфазной блокировки. Для таблиц InnoDB осуществляется блокировка на уровне строки и запросы по умолчанию запускаются как целостное считывание без блокировок, подобно тому, как это реализовано в Oracle. Хранение таблицы блокировок InnoDB организовано настолько экономично, что нет необходимости в расширении блокировки: обычно несколько пользователей могут блокировать любую строку или любой набор строк в базе данных, не занимая всю память, доступную для InnoDB.

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

Если режим автоматической фиксации отключен при помощи SET AUTOCOMMIT = 0, то мы предполагаем, что у пользователя постоянно имеется открытая транзакция. Если он выполняет оператор SQL COMMIT или ROLLBACK, которые завершают текущую транзакцию, сразу же запускается новая транзакция. Оба упомянутых оператора снимают все блокировки InnoDB, которые были установлены во время выполнения текущей транзакции. Оператор COMMIT означает, что изменения, внесенные во время выполнения текущей транзакции, принимаются и становятся видимыми для других пользователей. Оператор ROLLBACK отменяет все изменения, внесенные текущей транзакцией.

Если в соединении установлено AUTOCOMMIT = 1, то пользователь, тем не менее, может использовать транзакции, начиная их с BEGIN и заканчивая при помощи COMMIT или ROLLBACK.

В терминах описания уровней изоляции транзакций (SQL-1992), InnoDB по умолчанию использует REPEATABLE READ. Начиная с версии 4.0.5, InnoDB предлагает все 4 уровня изоляции описанные в стандарте SQL-1992. Вы можете установить уровень изоляции по умолчанию для всех соединений в секции [mysqld] файла `my.cnf':

transaction-isolation = {READ-UNCOMMITTED | READ-COMMITTED
                         | REPEATABLE-READ | SERIALIZABLE}

Пользователь может изменить уровень изоляции для отдельно взятой сессии или нового соединения таким образом:

SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL
                       {READ UNCOMMITTED | READ COMMITTED
                        | REPEATABLE READ | SERIALIZABLE}

Обратите внимания что названия уровней изоляции пишется без дефиса в SQL-выражении. Если вы указали ключевое слово GLOBAL в указанном выше выражении, оно будет определять уровень изоляции для новых соединений, но не будет иметь эффекта для старых соединений. Любой пользователь может изменить уровень изоляции для своей сессии, даже внутри самой транзакции. В версиях старше 3.23.50 SET TRANSACTION не оказывает эффекта на таблицы InnoDB. В версиях старше 4.0.5 вы можете использовать только REPEATABLE READ и SERIALIZABLE.

Вы можете получить информацию об уровне изоляции, глобальном или для текущего соединения:

SELECT @@global.tx_isolation;
SELECT @@tx_isolation;

В блокировке уровня строки InnoDB использует так называемую блокировку следующего ключа. Это означает, что кроме индексных записей InnoDB может также блокирует "интервал" перед индексной записью для блокировки вставок другими пользователями непосредственно перед индексной записью. Блокировка следующего ключа означает блокировку, которая ставится на индексную запись и интервал перед ней. Блокировка интервала означает только блокировку интервала перед некоторыми индексными записями.

Подробное описание каждого уровня изоляции в InnoDB:

  • READ UNCOMMITTED Также называется "грязным чтением": неблокирующиеся выборки (SELECT) выполняются таким образом, что мы не видим возможные ранние версии записи; таким образом они "несогласованно" читаются в этом уровне изоляции; в остальных случаях этот уровень работает также как и READ COMMITTED.
  • READ COMMITTED Нечто похожее на уровень изоляции Oracle. Все выражения SELECT ... FOR UPDATE и SELECT ... LOCK IN SHARE MODE блокируют только индексные записи и не блокируют интервал перед ними. Поэтому они позволяют свободно добавлять новые записи после заблокированных. UPDATE и DELETE, которые используют уникальный индекс и уникальные условия поиска, блокируют только найденную индексную запись, и не блокируют интервал перед ней. Но в UPDATE и DELETE диапазонного типа в InnoDB должны установить блокировку следующего ключа или интервальную блокировку и блокировать добавления другими пользователями в интервал, покрытый диапазоном. Это необходимо, т.к. "фантомные строки" должны быть блокированы для успешной работы репликации и восстановления в MySQL. Согласованное чтение работает как и в Oracle: каждое согласованное чтение, даже внутри одной транзакции, устанавливает и читает свой собственный снимок.
  • REPEATABLE READ Этот уровень изоляции используется в InnoDB по умолчанию. SELECT ... FOR UPDATE, SELECT ... LOCK IN SHARE MODE, UPDATE, и DELETE, которые используют уникальные индексы и уникальное условие поиска блокируют только найденную индексную запись и не блокируют интервал перед ней. В остальных случаях эта операция использует блокировку следующего ключа, блокирует диапазон индексов, просканированных блокировкой следующего ключа или интервальной, и блокирует новые добавления другими пользователями. В согласованном чтении есть важное отличие от предыдущего уровня изоляции: на этом уровне все согласованные чтения внутри той же самой транзакции читают снимок, сделанный для первого чтения. Это соглашение означает, что если вы выполните несколько простых выборок (SELECT) внутри той же самой транзакции, эти выборки будут целостными по отношению к друг другу.
  • SERIALIZABLE Этот уровень похож на предыдущий, но простые SELECT преобразовываются в SELECT ... LOCK IN SHARE MODE.

7.5.8.1 Согласованное чтение

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

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

Согласованное чтение является режимом по умолчанию, в котором в InnoDB обрабатываются операторы SELECT при READ COMMITTED или REPEATABLE READ уровнях изоляции. При согласованном чтении не устанавливаются блокировки на таблицы, к которым обращается запрос, и, таким образом, остальные пользователи могут вносить изменения в эти таблицы одновременно с согласованным чтением таблиц.

7.5.8.2 Чтение с блокировкой

В некоторых случаях использовать согласованное чтение нецелесообразно. Приведем пример. Допустим, что необходимо добавить новую строку в таблицу CHILD, предварительно убедившись, что для нее имеется родительская строка в таблице PARENT.

Предположим, что для чтения таблицы PARENT было использовано согласованное чтение, и в таблице была обнаружена родительская строка. Можно ли теперь безопасно добавить дочернюю строку в таблицу CHILD? Нет, потому что в это время другой пользователь мог без вашего ведома удалить родительскую строку из таблицы PARENT.

В данной ситуации необходимо выполнить операцию SELECT в режиме блокировки, LOCK IN SHARE MODE.

SELECT * FROM PARENT WHERE NAME = 'Jones' LOCK IN SHARE MODE;

Выполнение чтения в режиме совместного использования (share mode) означает, что считываются самые новые доступные данные и производится блокировка строк, чтение которых осуществляется. Если последние данные принадлежат еще не зафиксированной транзакции, мы ждем, пока транзакция не будет зафиксирована. Блокировка в режиме совместного использования не позволяет другим пользователям обновить или удалить читаемую строку. После того, как указанный выше запрос вернет родительскую строку 'Jones', мы можем безопасно добавить дочернюю строку в таблицу CHILD и зафиксировать транзакцию. В этом примере показано, как использовать целостность ссылочных данных в своей программе.

Рассмотрим еще один пример. Пусть у нас есть поле целочисленного счетчика в таблице CHILD_CODES, которое мы используем для назначения уникального идентификатора каждой дочерней записи, добавляемой к таблице CHILD. Очевидно, что использование согласованного чтения или чтения в режиме совместного доступа для получения текущего значения счетчика не подходит, так как два пользователя базы данных могут получить одно и то же значение счетчика и создать дублирующиеся ключи при добавлении двух дочерних записей в таблицу.

Для этого случая возможны два способа произвести чтение и увеличить значение счетчика: (1) сначала обновить значение счетчика, увеличив его на 1, и только после этого прочитать его или (2) сначала прочитать счетчик в режиме блокировки FOR UPDATE, а после этого увеличить его значение:

SELECT COUNTER_FIELD FROM CHILD_CODES FOR UPDATE;
UPDATE CHILD_CODES SET COUNTER_FIELD = COUNTER_FIELD + 1;

Оператор SELECT ... FOR UPDATE прочитает последние доступные данные с установкой отдельной блокировки на каждую считываемую строку. Таким образом, блокировка на строки устанавливается точно так же, как и в случае поиска по UPDATE.

7.5.8.3 Блокировка следующего ключа: устранение проблемы с фантомом

При блокировке на уровне строк в InnoDB используется алгоритм, который получил название блокировки следующего ключа. В InnoDB осуществляется блокировка на уровне строк, поэтому на время поиска или сканирования индекса таблицы устанавливается совместно используемая или эксклюзивная блокировка записей обрабатываемых индексов. Таким образом, более точно блокировку на уровне строк можно определить как блокировку индексных записей.

Блокировка, которая в InnoDB устанавливается на индексные записи, влияет также на интервал перед этой индексной записью. Если у пользователя имеется совместная или эксклюзивная блокировка записи R в индексе, то другой пользователь не может вставить новую индексную запись перед R в порядке следования индексов. Такая блокировка интервалов производится для предотвращения так называемой проблемы с фантомом. Предположим, что необходимо прочитать и заблокировать все дочерние записи с идентификатором, превышающим 100, из таблицы CHILD, и обновить некоторые поля в выбранных строках.

SELECT * FROM CHILD WHERE ID > 100 FOR UPDATE;

Допустим, что создан индекс таблицы CHILD по столбцу ID. Наш запрос произведет сканирование, начиная с первой записи, в которой ID больше 100. Теперь, если установленная на записи индекса блокировка не заблокирует вставки в интервалы, за это время в таблицу может быть вставлена новая дочерняя запись. Если теперь в транзакции запустить

SELECT * FROM CHILD WHERE ID > 100 FOR UPDATE;

еще раз, то в результате запроса будет выдана новая дочерняя запись. Это противоречит принципу изоляции транзакции: транзакция должна запускаться таким образом, чтобы считываемые ею данные не изменялись на протяжении выполнения транзакции. Если мы рассматриваем набор строк как элемент данных, то новая дочерняя ``запись-фантом'' нарушит этот принцип изоляции.

Когда InnoDB сканирует индекс, то возможна также блокировка интервалов после последних записей в индексе. Именно это иллюстрируется в предыдущем примере: блокировка, установленная InnoDB, предотвратит вставку в таблицу, если ID будет больше 100.

Блокировку следующего ключа можно использовать для того, чтобы провести проверку уникальности значений в своей программе. Если данные считываются в режиме совместного доступа и отсутствует дубликат строки, которую необходимо вставить, то можно безопасно вставлять свою строку и быть уверенным, что благодаря блокировке следующего ключа, установленной на предшествующей строке во время чтения, будет предотвращена вставка дублирующейся строки. Таким образом, блокировка следующего ключа позволяет ``заблокировать'' отсутствие чего-либо в таблице.

7.5.8.4 Блокировка, осуществляемая различными операторами SQL в InnoDB

  • SELECT ... FROM ...: согласованное чтение, которое производится из образа базы данных без блокировки.
  • SELECT ... FROM ... LOCK IN SHARE MODE: устанавливает совместно используемую блокировку следующего ключа на все считываемые индексные записи.
  • SELECT ... FROM ... FOR UPDATE: устанавливает эксклюзивную блокировку следующего ключа на все считываемые индексные записи.
  • INSERT INTO ... VALUES (...): устанавливает эксклюзивную блокировку на вставленную строку. Обратите внимание, что эта блокировка не является блокировкой следующего ключа и не предотвращает вставку другими пользователями записей в интервал перед вставленной строкой. Если произойдет ошибка дублирующегося ключа, оператор устанавливает блокировку совместного доступа на запись дублирующегося индекса.
  • INSERT INTO T SELECT ... FROM S WHERE ... устанавливает эксклюзивную (не следующего ключа) блокировку на каждую вставляемую в T строку. Осуществляет поиск по S как согласованное чтение, но устанавливает блокировки совместного доступа к следующему ключу на S, если включено ведение журнала MySQL. InnoDB в последнем случае должен устанавливать блокировки, так как при восстановлении работоспособности системы с повтором всех завершенных транзакций из резервной копии все операторы SQL должны запускаться точно таким же образом, как и изначально.
  • CREATE TABLE ... SELECT ... выполняет операцию SELECT как согласованное чтение или совместную блокировку, как и в предыдущем пункте.
  • REPLACE осуществляется так же, как и вставка, если нет конфликтов уникальных ключей. В противном случае эксклюзивная блокировка следующего ключа будет установлена на строку, которая должна быть обновлена.
  • UPDATE ... SET ... WHERE ...: устанавливает эксклюзивную блокировку следующего ключа для каждой записи, по которой производится поиск.
  • DELETE FROM ... WHERE ...: устанавливает эксклюзивную блокировку следующего ключа для каждой записи, по которой производится поиск.
  • Если для таблицы определены ограничения FOREIGN KEY, для любой вставки, обновления или удаления, для которых требуется проверка условий ограничения, устанавливается совместная блокировка на уровне записей, которые просматриваются для проверки ограничения. В InnoDB эти блокировки устанавливаются также в случае нарушения ограничения.
  • LOCK TABLES ...: устанавливает блокировку таблицы. Эта блокировка производится кодом уровня MySQL. Механизм автоматического обнаружения взаимоблокировок (deadlock) InnoDB не может детектировать взаимоблокировки, в которых участвуют такие блокировки таблиц (см. следующий раздел). Кроме того, поскольку MySQL ``знает'' о блокировке на уровне строки, возможно установление блокировки таблицы, в которой другой пользователь заблокировал строки. Но это не опасно для целостности транзакции. See section 7.5.13 Ограничения для таблиц InnoDB.

7.5.8.5 Обнаружение и откат взаимоблокировки (deadlock)

InnoDB автоматически обнаруживает взаимоблокировку транзакций и производит откат транзакции или транзакций для предотвращения взаимоблокировок. Начиная с версии 4.0.5 InnoDB будет пытаться выбрать меньшую транзакцию для отката. Размер транзакции определяется количеством строк, которые должны быть добавлены, обновлены или удалены. До версии 4.0.5 InnoDB всегда откатывал транзакцию, запрос на блокировку которой вызвал возникновение взаимоблокировки, то есть замкнутого цикла в графике ожиданий транзакций.

InnoDB не может обнаружить взаимоблокировку, установленную оператором MySQL LOCK TABLES, или блокировку, установленную отличным от InnoDB обработчиком таблиц. Такие ситуации необходимо исправлять при помощи параметра innodb_lock_wait_timeout, который задается в `my.cnf'.

Когда InnoDB выполняет полный откат транзакции, все блокировки, установленные транзакцией, снимаются. Тем не менее, если в результате ошибки производится откат только одного оператора SQL, некоторые блокировки, установленные оператором, могут остаться в силе. Это происходит потому, что InnoDB хранит блокировку строк в формате, по которому впоследствии нельзя определить, каким оператором SQL была установлена блокировка.

7.5.8.6 Пример работы согласованного чтения в InnoDB

Допустим, вы используете уровень изоляции, установленый по умолчанию - REPEATABLE READ. При выполнении согласованного чтения (т.е. обычного оператора SELECT) InnoDB определяет для транзакции момент времени, по состоянию на который запросу будет предоставляться информация из базы данных. Таким образом, если транзакция удаляет строку и фиксирует это изменение после назначенного момента времени, то вы не увидите, что строка была удалена. Это справедливо также для вставок и обновлений.

Чтобы такой момент времени ``передвинуть вперед'', нужно зафиксировать транзакцию, а затем выполнить новую команду SELECT.

Это называется многовариантным контролем совпадений.

         Пользователь A 	  Пользователь B

        SET AUTOCOMMIT=0;	SET AUTOCOMMIT=0;

время
| 		SELECT * FROM t;
|		пустой набор данных
|					INSERT INTO t VALUES (1, 2);
|
v 		SELECT * FROM t;
        пустой набор данных
                    COMMIT;
        SELECT * FROM t;
        пустой набор данных;

        COMMIT;

        SELECT * FROM t;
        ---------------------
        | 1 | 2 |
        ---------------------

Таким образом, пользователь A увидит строку, вставленную пользователем B только после того, как B зафиксирует вставку, и A зафиксирует свою собственную транзакцию, чтобы момент времени передвинулся на позицию, находящуюся после фиксации, произведенной пользователем B.

Чтобы увидеть ``самое свежее'' состояние базы данных, необходимо использовать чтение с блокировкой:

SELECT * FROM t LOCK IN SHARE MODE;

7.5.8.7 Каким образом избежать взаимоблокировок (deadlock)?

Взаимоблокировки - классическая проблема транзакционных баз данных. Они не опасны до тех пор пока не становятся настолько частыми, что вы вообще не можете запустить некоторые транзакции. Обычно вы можете написать свои приложения таким образом, что они всегда будут подготавливать перезапуск транзакции, если произошел откат из-за взаимоблокировок.

InnoDB использует автоматическую блокировку уровня строки. Вы можете создать взаимоблокировку даже в случае транзакций, которые всего лишь добавляют или удаляют единичную строку. Это происходит из-за того, что в действительности эти операции не являются "атомарными": они автоматически устанавливают блокировку на индексные записи добавляемых/удаляемых строк (или на несколько записей).

Вы можете избежать взаимоблокировок или уменьшить их количество, следуя следующим приемам:

  • Используйте SHOW INNODB STATUS в MySQL начиная с 3.23.52 и 4.0.3 для определения причины последней взаимоблокировки. Это поможет вам настроить ваше приложение, что бы избежать взаимоблокировок.
  • Всегда подготавливайте перезапуск транзакции, если произошел откат из-за взаимоблокировки. Взаимоблокировка не опасна: всего лишь попробуйте еще раз.
  • Чаще фиксируйте свои транзакии. Маленькие транзакции меньше склонны к противоречиям.
  • Если вы используете чтение с блокировкой SELECT ... FOR UPDATE или ... LOCK IN SHARE MODE, попробуйте использовать более низкий уровень изоляции READ COMMITTED.
  • Производите операции с вашими таблицам и строками в фиксированном порядке. Тогда транзакции будут формировать очередь и не будет происходить взаимоблокировка.
  • Добавьте хорошие индексы на ваши таблицы. Тогда ваши запросы будут сканировать меньше индексных записей и, соответственно, будут устанавливать меньше блокировок. Используйте EXPLAIN SELECT для того, чтобы узнать, выбирает ли MySQL соответствующий индекс для ваших запросов.
  • Используйте меньше блокировок: если вы можете допустить, чтобы SELECT возвращал данные из старого снимка, не добавляйте к выражению FOR UPDATE или LOCK IN SHARE MODE. Используйте уровень изоляции READ COMMITTED, который больше всего подходит для данной ситуации, так как каждое согласованное чтение внутри одной и той же транзакции читает свой собственный свежий снимок.
  • Если ничего не помогло, сериализируйте свои транзакции с блокировкой уровня таблиц: LOCK TABLES t1 WRITE, t2 READ, ... ; [здесь можете развлекаться с таблицами t1 и t2]; UNLOCK TABLES. Блокировка на уровне таблиц выстраивает ваши транзакции в очередь, и позволяет избежать взаимоблокировки. Заметьте, что LOCK TABLES неявным образом начинает транзакцию наподобие BEGIN, и UNLOCK TABLES неявным образом завершает ее в COMMIT.
  • Другое решение для сериализации транзакций - это создание вспомагательного "семафора" таблицы, где есть всего лишь одна строка. Каждая транзакция обновляет эту строку перед доступом к другой таблице. В этом случае все транзакции выполняются в виде очереди. Отметим что таким же образом в настоящий момент работает и алгоритм определения взаимоблокировок в InnoDB, так как блокировка сериализации - это блокировка уровня строки. При блокировке на уровне таблицы в MySQL мы используем метод таймаута для разрешения взаимоблокировки.

7.5.8.8 Рекомендации по увеличению производительности

1. Если top операционной системы Unix или Task Manager Windows показывают процент рабочей нагрузки процессора меньше 70%, это значит, что объем рабочей нагрузки в основном сводится к обращениям к диску. Возможно, слишком часто производится фиксация транзакций, или буферный пул слишком мал. Здесь может помочь увеличение размера буферного пула, но не следует устанавливать его значение большим, чем 80% физической памяти.

2. Несколько изменений следует вносить за одну транзакцию. InnoDB должен сбрасывать журнал на диск после каждой фиксации транзакции, если эта транзакция вносит изменения в базу данных. Поскольку скорость вращения диска обычно не превышает 167 оборотов в секунду, то количество фиксаций ограничено 167 фиксациями в секунду, если, конечно, диск не обманывает операционную систему.

3. Если вы можете позволить себе потерять последние зафиксированные транзакции, установите параметр innodb_flush_log_at_trx_commit в файле `my.cnf' в нулевое значение. Так или иначе InnoDB пытается сохранить журнал ежесекундно, и в этом случае сохранение не гарантируется.

4. Увеличьте размеры файлов журналов, доведите их даже до размера буферного пула. Когда InnoDB заполняет файлы журналов, он должен сохранить измененное содержимое буферного пула на диск в виде моментального снимка базы. Маленькие журналы будут вызывать множество ненужных записей на диск. Есть и оборотная сторона медали - если файлы журналов большие, то время восстановления транзакций (в случае сбоя) будет больше.

5. Кроме того, буфер журнала должен быть достаточно большим, например 8 Мб.

6. (Актуально для версии 3.23.39 и выше.) В некоторых версиях операционных систем Linux и Unix запись файлов на диск при помощи команды Unix fdatasync и других подобных методов производится на удивление медленно. Принятый по умолчанию метод InnoDB использует функцию fdatasync. Если скорость записи базы данных вас не устраивает, можно попробовать для параметра innodb_flush_method в файле `my.cnf' задать значение O_DSYNC, хотя на многих системах O_DSYNC обычно работает медленнее.

7. При импортировании данных в InnoDB убедитесь что в MySQL не установлено значение autocommit=1. Если оно установлено, то каждая вставка требует сохранения журналов на диске. Поместите прямо в начале вашего файла с данными:

SET AUTOCOMMIT=0;

и в конце

COMMIT;

Если используется параметр mysqldump --opt, то вы получите файлы, которые достаточно быстро импортируются в InnoDB, даже если их не окружить вышеуказанными командами SET AUTOCOMMIT=0; ... COMMIT;.

8. Осторожно относитесь к значительным откатам больших вставок InnoDB использует буфер вставок для того, чтобы меньше ``дергать'' диск на вставках, однако для соответствующего отката транзакции такой механизм не предусмотрен.. Ограниченный производительностью диска откат может занять в 30 раз больше времени, чем вставка. Удаление процесса базы данных не поможет, так как откат начнется снова после запуска базы данных. Единственный способ избежать такого отката - это увеличить буферный пул настолько, что откат станет зависеть только от производительности процессора, перестанет ``равняться'' по диску и отработается быстро. Есть еще один способ - это удаление базы данных InnoDB целиком.

9. Следует также осторожно относиться к операциям со значительными объемами данных, зависящим от производительности диска. Чтобы очистить таблицу, используйте команды DROP TABLE или TRUNCATE (начиная с версии MySQL-4.0 и выше), а не DELETE FROM yourtable.

10. Используйте множественные вставки для уменьшения нагрузки на коммуникации между клиентом и сервером, если вам нужно вставить множество записей:

INSERT INTO yourtable VALUES (1, 2), (5, 5);

Эта рекомендация подходит для вставок в таблицы любого типа, а не только InnoDB.

7.5.8.9 InnoDB Monitor

Начиная с версии 3.23.41 в состав InnoDB входит InnoDB Monitor, который выводит информацию по внутреннему состоянию InnoDB. Когда InnoDB Monitor включен, сервер MySQL mysqld выводит стандартный набор данных (обратите внимание: клиент MySQL ничего не выводит) примерно каждые 15 секунд. Эти данные могут пригодиться при настройке производительности. В операционной системе Windows необходимо запустить mysqld-max из командной строки MS-DOS с параметрами --standalone --console, чтобы направить выводимые данные в окно MS-DOS.

Существует отдельная функция innodb_lock_monitor, которая выводит такую же информацию как innodb_monitor, а также данные по блокировкам, установленным каждой транзакцией.

Выводящаяся информация включает следующие данные:

  • по блокировкам, ожидающим транзакций;
  • по семафорам, ожидающим потоков;
  • по файлам, ожидающим ответа на запрос ввода/вывода;
  • статистику буферного пула;
  • по активности буферов удаления и вставок в основном потоке InnoDB.

InnoDB Monitor можно запустить при помощи следующей команды SQL:

CREATE TABLE innodb_monitor(a int) type = innodb;

а остановить его при помощи:

DROP TABLE innodb_monitor;

Вызов команды CREATE TABLE является только способом передачи команды в InnoDB через программу синтаксического анализа SQL. Факт создания таблицы не играет никакой роли для InnoDB Monitor. Если вы останавливаете сервер, когда монитор работает, и хотите запустить монитор заново, следует уничтожить таблицу прежде, чем снова вызвать CREATE TABLE для запуска монитора. Синтаксис может измениться в будущих версиях.

Пример информации, выводимой InnoDB Monitor:

================================
010809 18:45:06 INNODB MONITOR OUTPUT
================================
--------------------------
LOCKS HELD BY TRANSACTIONS
--------------------------
LOCK INFO:
Number of locks in the record hash table 1294
LOCKS FOR TRANSACTION ID 0 579342744
TABLE LOCK table test/mytable trx id 0 582333343 lock_mode IX
RECORD LOCKS space id 0 page no 12758 n bits 104 table test/mytable index
PRIMARY trx id 0 582333343 lock_mode X
Record lock, heap no 2 PHYSICAL RECORD: n_fields 74; 1-byte offs FALSE;
info bits 0
0: len 4; hex 0001a801; asc ;; 1: len 6; hex 000022b5b39f; asc ";;
2: len 7; hex 000002001e03ec; asc ;; 3: len 4; hex 00000001;
...
-----------------------------------------------
CURRENT SEMAPHORES RESERVED AND SEMAPHORE WAITS
-----------------------------------------------
SYNC INFO:
Sorry, cannot give mutex list info in non-debug version!
Sorry, cannot give rw-lock list info in non-debug version!
-----------------------------------------------------
SYNC ARRAY INFO: reservation count 6041054, signal count 2913432
4a239430 waited for by thread 49627477 op. S-LOCK file NOT KNOWN line 0
Mut ex 0 sp 5530989 r 62038708 sys 2155035;
rws 0 8257574 8025336; rwx 0 1121090 1848344
-----------------------------------------------------
CURRENT PENDING FILE I/O'S
--------------------------
Pending normal aio reads:
Reserved slot, messages 40157658 4a4a40b8
Reserved slot, messages 40157658 4a477e28
...
Reserved slot, messages 40157658 4a4424a8
Reserved slot, messages 40157658 4a39ea38
Total of 36 reserved aio slots
Pending aio writes:
Total of 0 reserved aio slots
Pending insert buffer aio reads:
Total of 0 reserved aio slots
Pending log writes or reads:
Reserved slot, messages 40158c98 40157f98
Total of 1 reserved aio slots
Pending synchronous reads or writes:
Total of 0 reserved aio slots
-----------
BUFFER POOL
-----------
LRU list length 8034
Free list length 0
Flush list length 999
Buffer pool size in pages 8192
Pending reads 39
Pending writes: LRU 0, flush list 0, single page 0
Pages read 31383918, created 51310, written 2985115
----------------------------
END OF INNODB MONITOR OUTPUT
============================
010809 18:45:22 InnoDB starts purge
010809 18:45:22 InnoDB purged 0 pages

Некоторые примечания по выводу:

  • Если раздел LOCKS HELD BY TRANSACTIONS содержит информацию по ожидаемым блокировкам, то у вашей программы может быть конфликт блокировок. Выводимая информация также может оказать помощь в отслеживании причин возникновения взаимных блокировок.
  • Если InnoDB скомпилировать при помощи UNIV_SYNC_DEBUG в `univ.i', то раздел SYNC INFO будет содержать информацию по зарезервированным семафорам.
  • Раздел SYNC ARRAY INFO содержит информацию по потокам, ожидающим семафора, а также статистические данные по количеству повторных циклов или ожиданий, выполненных потоками для семафоров или блокировок чтения/записи. Большое количество потоков, ожидающих семафоров, может возникнуть в результате частого выполнения операций ввода/вывода диска, оно может быть также обусловлено конфликтами внутри самого InnoDB. Конфликты могут возникать при большом количестве параллельных запросов или в случае проблем операционной системы с планированием потоков.
  • В разделе CURRENT PENDING FILE I/O'S выводится список файлов, ожидающих ответа на запрос ввода/вывода. Большое количество таких файлов говорит о том, что рабочая нагрузка ограничена операциями ввода/вывода диска.
  • Раздел BUFFER POOL содержит статистическую информацию по записываемым и считываемым страницам. По этим данным можно вычислить, сколько запросов ввода/вывода по файлам данных выполняется на данный момент.

7.5.9 Реализация многовариантности

Поскольку InnoDB является многовариантной базой данных, информация по старым версиям строк в ней хранится в табличной области. Эта информация содержится в структуре данных, которую мы по аналогии со структурой данных в Oracle называем сегментом отката.

К каждому внутреннему представлению строки таблицы, хранящейся в базе данных InnoDB, добавляется по два поля. В 6-байтовом поле хранится идентификатор последней транзакции, которая производила вставку или обновление строки. Удаление рассматривается как обновление, при котором специальный бит удаления строки помечается соответствующим образом. Помимо этого, каждая строка содержит также 7-байтовое поле, которое называется указателем отката. Указатель отката указывает на запись журнала отмены, занесенную в сегмент отката. Если строка была обновлена, запись журнала отмены содержит необходимую информацию для восстановления содержимого строки до обновления.

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

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

Не забывайте регулярно фиксировать свои транзакции, включая транзакции, использующие согласованное чтение. В противном случае InnoDB не сможет удалить данные из журналов отмены обновления, что приведет к разрастанию сегмента отката, который может занять всю вашу табличную область.

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

В нашей многовариантной схеме строка физически не удаляется из базы данных немедленно после удаления ее при помощи оператора SQL. Только после того, как InnoDB сможет удалить запись журнала отмены обновления, занесенную для удаления, соответствующая строка и ее индексная запись из базы данных могут быть физически удалены. Эта операция удаления называется чисткой. Она производится достаточно быстро - на нее уходит столько же времени, как и на выполнение оператора удаления SQL.

7.5.10 Структуры таблиц и индексов

В MySQL информация словаря данных таблиц хранится в файлах `.frm', расположенных в каталогах баз данных. Но для каждой таблицы InnoDB имеются также свои записи во внутренних словарях данных InnoDB в табличной области. Когда MySQL удаляет таблицу или базу данных, необходимо удалить как файлы `.frm', так и соответствующие записи в словаре данных InnoDB. Именно поэтому нельзя перемещать таблицы InnoDB между базами данных путем простого перемещения файлов `.frm'. По этой же причине DROP DATABASE не работал для таблиц InnoDB в MySQL версий <= 3.23.43.

Для всех таблиц InnoDB есть специальный индекс, в котором хранятся данные строк - он называется кластеризованным индексом. Если в таблице определить PRIMARY KEY, то индекс первичного ключа будет кластеризированным индексом.

Если первичный ключ для таблицы не определен, то InnoDB самостоятельно создаст кластеризированный индекс; строки в этом индексе будут упорядочены по идентификатору строки, который InnoDB назначил строкам этой таблицы. Идентификатор строки представляет собой 6-байтовое поле, значение которого постоянно увеличивается при вставке новых строк. Таким образом, сортировка по идентификатору строки фактически представляет собой сортировку по последовательности вставки.

Доступ к строке через кластеризированный индекс осуществляется достаточно быстро, поскольку данные строки находятся на той же странице, к которой приводит поиск по индексу. Во многих базах данных информация и индексная запись традиционно хранятся на разных страницах. При больших размерах таблицы архитектура кластеризированных индексов часто позволяет сократить количество дисковых операций ввода/вывода по сравнению с традиционными решениями.

Записи в некластеризированных индексах (мы называем их также вторичными индексами), в InnoDB содержат значение первичного ключа для строки. InnoDB использует этот значение первичного ключа для поиска строки в кластеризированном индексе. Следует учитывать, что если первичный ключ достаточно велик, вторичные индексы будут занимать больше места.

7.5.10.1 Физическая структура индекса

Все индексы в InnoDB представляют собой B-деревья, в которых записи индексов хранятся в страницах ответвления дерева. По умолчанию размер индексной страницы составляет 16 Кб. При вставке новых записей InnoDB старается оставить 1 / 16 страницы свободной - для будущих вставок и обновлений индексных записей.

Если записи индекса вставлены в последовательном порядке (в порядке возрастания или убывания), то получившиеся индексные страницы будут заполнены примерно на 15/16. Для записей, которые вставляются в случайном порядке, эти значения составят от 1/2 до 15/16. Если коэффициент заполнения индексной страницы уменьшится и станет ниже 1/2, InnoDB попытается объединить записи индексного дерева, чтобы освободить страницу.

7.5.10.2 Буферизация вставок

Нередко в программах для работы с базами данных первичный ключ является уникальным идентификатором и новые строки вставляются в порядке возрастания первичного ключа. Таким образом, вставки в кластеризированный индекс не требуют проведения случайных считываний с диска.

Что же касается вторичных индексов, то они, напротив, обычно не являются уникальными, так что вставки во вторичные индексы производятся в относительно случайном порядке. Это приводит к выполнению большого количества случайных дисковых операций ввода/вывода диска, если не используется специальный механизм, применяемый в InnoDB.

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

Буфер вставок периодически объединяется с деревьями вторичных индексов в базе данных. Часто, объединив несколько вставок на одной странице индексного дерева, можно за счет этого сократить количество операций ввода/вывода диска. Использование буфера вставки может ускорить вставку в таблицу в 15 раз.

7.5.10.3 Адаптивный хешированный индекс

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

Но следует учитывать, что хешированный индекс всегда создается на основе существующего индекса B-дерева таблицы. InnoDB может создать хешированный индекс на префиксах любой длины ключа, определенного для B-дерева, в зависимости от того, по какой схеме поиска InnoDB производит обзор индекса the B-дерева. Хешированный индекс может быть частичным: не обязательно кэшировать в буферном пуле весь индекс B-дерева. InnoDB будет создавать хешированные индексы по запросу для тех страниц индекса, к которым часто производится доступ.

Хотя механизм адаптивного хешированного индекса InnoDB приспосабливается к большому количеству основной памяти, он больше подходит для архитектуры баз данных основной памяти.

7.5.10.4 Физическая структура записи

  • У всех записей индекса в InnoDB есть заголовок, состоящий из 6 байтов. Заголовок используется для связывания вместе последовательных записей, а также при блокировке на уровне строк.
  • Записи в кластеризированном индексе содержат поля для всех столбцов, определенных пользователем. Кроме того, имеется 6-байтовое поле для идентификатора транзакции и 7-байтовое поле для указателя строки.
  • Если пользователь не определил для таблицы первичный ключ, то в каждой записи кластеризированного индекса также содержится 6-байтовое поле идентификатора строки.
  • Все записи вторичного индекса содержат также все поля, определенные для ключа кластеризированного индекса.
  • Запись также содержит указатель на каждое поле записи. Если общая длина полей в записи меньше 128 байтов, то размер указателя будет 1 байт, в противном случае - 2 байта.

7.5.10.5 Как работают автоинкрементные столбцы в InnoDB

Когда пользователь после запуска базы данных осуществляет первую вставку в таблицу T, где определен автоинкрементный столбец, и пользователь не предоставляет конкретного значения для этого столбца, InnoDB выполняет SELECT MAX(auto-inc-column) FROM T, затем присваивает это значение, увеличенное на единицу, столбцу, и автоматически увеличивает счетчик таблицы. Эту последовательность действий мы называем инициализацией счетчика автоматического увеличения для таблицы T.

Ту же последовательность действий InnoDB выполняет и для инициализации автоинкрементного счетчика вновь созданной таблицы.

Обратите внимание: если пользователь указывает при вставке значение автоинкрементного столбца 0, то InnoDB обрабатывает строку так, как будто значение не было указано.

Если после инициализации автоматического увеличения счетчика пользователь вставляет строку, в которой он явно указывает значение столбца, и это значение превышает текущее значение счетчика, то счетчик устанавливается в указанное значение столбца. Если пользователь явно не указывает значение, то InnoDB увеличивает счетчик на единицу и присваивает столбцу это новое значение.

При присвоении значений из счетчика механизм автоматического увеличения обходит блокировку и управление транзакциями. Вследствие этого могут возникнуть пропуски в последовательности чисел в случае, если производится откат транзакций, которые получили номера из счетчика.

Для случаев, когда пользователь присваивает столбцу отрицательное значение или если значение превысит максимальное целое число, которое может храниться в переменной целочисленного типа, поведение механизма механического увеличения не определено.

7.5.11 Управление файловым пространством и дисковый ввод/вывод

7.5.11.1 Дисковый ввод/вывод

В операциях дискового ввода/вывода для таблиц InnoDB используется асинхронный ввод/вывод. В Windows NT применяется собственный асинхронный ввод/вывод, обеспечиваемый операционной системой, а в Unix - эмуляция асинхронного ввода/вывода, встроенная в InnoDB (InnoDB создает определенное количество потоков ввода/вывода, чтобы обеспечить операции ввода/вывода, такие как опережающее считывание). В будущей версии мы добавим поддержку эмуляции асинхронного ввода/вывода в Windows NT и собственного асинхронного ввода/вывода в тех версиях Unix, в которых он есть.

В Windows NT для таблиц InnoDB используется ввод/вывод без буферизации. Это означает, что страницы на диске, которые записывает или считывает InnoDB, не заносятся в файловый кэш операционной системы. При этом экономится некоторое количество памяти.

Начиная с версии 3.23.41 в InnoDB используется новая техника сбрасывания файлов на диск, которая получила название двойной записи. Она обеспечивает большую безопасность при восстановлении после сбоев (таких как, например, зависание операционной системы или отключение питания) и повышение производительности на большинстве версий Unix, так как снижается необходимость в операциях fsync.

``Двойная запись'' означает, что InnoDB перед записью страниц в файл данных сначала записывает их в смежный участок табличной области, который называется буфером двойной записи. Запись страниц в предназначенные для них места файла данных осуществляется только после завершения записи и сброса буфера двойной записи на диск. В случае сбоя системы во время записи страницы InnoDB во время восстановления найдет в буфере двойной записи пригодную копию страницы.

Начиная с версии 3.23.41 в качестве файла данных можно также использовать раздел реального диска, хотя тестирование этой возможности еще не проводилось. При создании нового файла данных в innodb_data_file_path сразу после размера файла данных необходимо ввести ключевое слово newraw. Раздел диска должен быть больше указанного размера или равен ему. Обратите внимание: 1 Мб в InnoDB -это 1024 x 1024 байт, тогда как в характеристиках диска 1 Мб обычно соответствует 1000 000 байт.

innodb_data_file_path=hdd1:5Gnewraw;hdd2:2Gnewraw

При новом запуске базы данных Вы должны изменить ключевое слово на raw. В противном случае InnoDB перезапишет ваш раздел!

innodb_data_file_path=hdd1:5Graw;hdd2:2Graw

Используя реальный диск, в некоторых версиях Unix можно производить небуферизованные операции ввода/вывода.

В InnoDB существует два эвристических метода опережающего считывания: последовательное опережающее считывание и случайное опережающее считывание. Метод последовательного опережающего считывания предусматривает, что InnoDB, определив, что схема доступа к сегменту в табличной области является последовательной, будет заранее направлять системе ввода/вывода пакет считываний страниц базы данных. Метод случайного опережающего считывания предполагает, что InnoDB, определив, что некоторые части табличной области полностью считываются в буферный пул, направляет оставшиеся считывания системе ввода/вывода.

7.5.11.2 Управление файловым пространством

Табличную область InnoDB составляют файлы данных, определенные в файле конфигурации. Файлы используются последовательно, распределения данных (striping ) по ним не производится. На данный момент вы не можете непосредственно указать, где должны быть размещены таблицы. Можно только воспользоваться знанием того факта, что для вновь созданной табличной области InnoDB будет распределяться место с начала памяти.

Табличная область состоит из страниц базы данных, принятый по умолчанию размер которых составляет 16 Кб. Эти страницы сгруппированы в блоки по 64 последовательных страницы. 'Файлы' внутри табличной области в InnoDB называются сегментами. Название 'сегмент отката' несколько не соответствует действительности, так как фактически в нем содержится много сегментов табличной области.

Для каждого индекса в InnoDB выделяется два сегмента: один - для конечных узлов B-дерева, а другой - для остальных узлов. Идея заключается в том, чтобы получить лучшее координирование конечных узлов, в которых содержатся данные.

Когда сегмент внутри табличной области возрастает, InnoDB выделяет первые 32 специально для этого сегмента. После этого InnoDB начинает выделять целые области для этого сегмента. Чтобы обеспечить хорошее координирование данных, InnoDB может единовременно добавить к большому сегменту до 4 областей,.

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

Когда вы запускаете запрос SHOW TABLE STATUS FROM ... LIKE ... для получения информации по доступному свободному пространству табличной области, InnoDB предоставит данные по свободным областям табличной области. InnoDB всегда резервирует области для очистки и других внутренних операций. Зарезервированные области не включаются в объем свободного пространства.

Если из таблицы удаляются данные, InnoDB объединяет соответствующие индексы B-дерева. В зависимости от схемы удалений, когда освобождаются отдельные страницы или области табличной области, это пространство становится доступным для других пользователей. Удаление таблицы или удаление всех ее строк гарантированно освободит пространство для других пользователей, но не следует забывать, что физически строки удаляются только после проведения чистки, после чего они больше не нужны при откате транзакций или согласованном чтении.

7.5.11.3 Дефрагментация таблицы

Если в индексной таблице производились случайные вставки или удаления, индекс может стать фрагментированным. Под фрагментацией мы подразумеваем то, что физическое расположение индексных страниц на диске значительно отличается от алфавитного порядка страниц, или что в 64-страничных блоках много пустых страниц, которые занесены в индекс.

Скорость сканирования индекса может возрасти, если периодически использовать команду mysqldump для копирования дампа таблицы в текстовый файл, записи диска на диск и повторного считывания таблицы из дампа. Есть еще один способ произвести дефрагментацию - преобразовать таблицу при помощи команды ALTER в тип MyISAM, а затем обратно в тип InnoDB. Обратите внимание на то, что таблица типа MyISAM должна помещаться в один файл в вашей операционной системе.

Если вставки в индекс всегда производятся последовательно, а удаления - только с конца, то алгоритм управления файловым пространством InnoDB гарантирует, что фрагментации индекса не возникнет.

7.5.12 Обработка ошибок

Обработка ошибок в InnoDB не всегда соответствует спецификациям, указанным в стандарте ANSI SQL. В соответствии со стандартом ANSI любая ошибка, произошедшая во время выполнения оператора SQL должна привести к откату оператора. InnoDB иногда осуществляет откат только части оператора или целой транзакции. Особенности обработки ошибок в InnoDB указаны в приведенном ниже списке.

  • Если закончилось свободное место в табличной области, будет выдано сообщение об ошибке MySQL 'Table is full' и InnoDB произведет откат оператора SQL.
  • Взаимоблокировка транзакции или истечение времени ожидания при блокировке приводят к откату целой транзакции в InnoDB.
  • Ошибка дублирующегося ключа приводит к откату вставки только этой определенной строки, даже в операторе INSERT INTO ... SELECT .... Этот алгоритм мы, возможно, изменим, с тем чтобы производился откат всего оператора SQL, если для него не указан параметр IGNORE.
  • Ошибка 'row too long' приводит к откату оператора SQL.
  • Большинство остальных ошибок обнаруживается на уровне кода MySQL, и производится откат соответствующего оператора SQL.

7.5.13 Ограничения для таблиц InnoDB

  • Предупреждение: НЕЛЬЗЯ преобразовывать системные таблицы MySQL из формата MyISAM в формат InnoDB! Эта операция не поддерживается, и если попытаться ее осуществить, MySQL не перезапустится, пока не будут восстановлены старые системные таблицы из резервной копии, или пока не будут созданы новые таблицы при помощи скрипта mysql_install_db.
  • Команда SHOW TABLE STATUS не выдает точных статистических данных по таблицам InnoDB, за исключением размера физического пространства, зарезервированного для таблицы. Подсчет строк производится приблизительно так, как в оптимизации SQL.
  • Если попытаться создать уникальный индекс на префиксе столбца, то будет выдана ошибка:
    CREATE TABLE T (A CHAR(20), B INT, UNIQUE (A(5))) TYPE = InnoDB;
    Если на префиксе столбца создать неуникальный индекс, InnoDB создаст индекс по всему столбцу.
  • Для таблиц InnoDB не поддерживается команда INSERT DELAYED.
  • Операция MySQL LOCK TABLES не знает про блокировки InnoDB на уровне строк в уже выполненном операторе SQL: это означает, что можно установить блокировку на таблицу, даже если существуют транзакции других пользователей, которые установили блокировку этой же таблицы на уровне строк. Таким образом, может оказаться, что ваши операции над таблицей будут вынуждены ожидать, если такая блокировка будет установлена другими пользователями: возможна также и взаимоблокировка. Тем не менее, это не угрожает целостности транзакций, так как при установке блокировки на таблицы InnoDB всегда соблюдается целостность. Кроме того, блокировка таблицы не позволяет другим транзакциям установить на таблицу дополнительные блокировки на уровне строки (в режиме несовместимости блокировок).
  • Нельзя установить ключ для столбцов типа BLOB или TEXT.
  • Таблица не может содержать больше 1000 столбцов.
  • Команда DELETE FROM TABLE не пересоздает таблицу, она удаляет все строки по одной, что осуществляется не очень быстро. В будущих версиях MySQL можно будет использовать команду TRUNCATE, которая намного быстрее.
  • Принятый по умолчанию размер страницы в InnoDB составляет 16 Кб. Повторно скомпилировав код, можно установить значение от 8 Кб до 64 Кб. В версиях <= 3.23.40 InnoDB максимальная длина строки несколько меньше половины размера страницы базы данных. Начиная с релиза исходного кода версии 3.23.41 столбцы типов BLOB и TEXT могут достигать 4 Гб, общая длина строк также не должна превышать 4 Гб. Поля с размером меньше или равным 128 байтам в InnoDB не хранятся на отдельных страницах. После того как InnoDB изменит строку, сохранив длинные поля на отдельных страницах, оставшаяся длина строки должна быть меньше половины страницы базы данных. Максимальная длина ключа - 7000 байтов.
  • В некоторых операционных системах файлы данных не должны превышать 2 Гб. Общий размер файлов журналов должен быть меньше 4 Гб.
  • Максимальный размер табличной области составляет 4 миллиарда страниц базы данных. Это также максимальный размер таблицы. Минимальный размер табличной области составляет 10 Мб.

7.5.14 История изменений InnoDB

Раздел в переводе.

7.5.15 Контактная информация для получения данных по InnoDB

Контактная информация компании Innobase Oy, которая создала модель InnoDB: веб-сайт: http://www.innodb.com/, e-mail: Heikki.Tuuri@innodb.com

Телефон: 358-9-6969 3250 (офис) 358-40-5617367 (мобильный)
Innobase Oy Inc.
World Trade Center Helsinki
Aleksanterinkatu 17
P.O.Box 800
00101 Helsinki
Finland

7.6 Таблицы BDB или BerkeleyDB

7.6.1 Обзор таблиц BDB

Поддержка таблиц BDB включена в дистрибутив исходного кода MySQL начиная с версии 3.23.34 и в бинарную версию MySQL-Max.

BerkeleyDB, доступный на веб-сайте http://www.sleepycat.com/, обеспечивает транзакционный обработчик таблиц для MySQL.

Использование BerkeleyDB повышает для ваших таблиц шансы уцелеть после сбоев, а также предоставляет возможность осуществлять операции COMMIT и ROLLBACK для транзакций. Дистрибутив исходного кода MySQL поставляется с дистрибутивом BDB, содержащим несколько небольших исправлений, которые позволяют устранить определенные проблемы при работе с MySQL. Неисправленные версии BDB при работе с MySQL использовать нельзя.

В целях поддержания высокого уровня и качества интерфейса MySQL/BDB компания MySQL AB тесно сотрудничает с компанией Sleepycat.

Что касается поддержки таблиц BDB, то мы взяли на себя обязательство оказывать помощь нашим пользователям в выявлении проблем и создании воспроизводимых контрольных примеров для любых ошибок, возникающих при использовании таблиц BDB. Все такие контрольные примеры направляются в компанию Sleepycat, которая, в свою очередь, помогает нам выявлять и исправлять ошибки. Поскольку эта операция состоит из двух этапов, решение проблем с таблицами BDB может отнять у нас больше времени, чем устранение ошибок других обработчиков таблиц. Тем не менее, поскольку помимо MySQL код BerkeleyDB использовался с большим количеством других приложений, мы не думаем, что с ним возникнут серьезные проблемы (see section 1.5.1.1 Поддержка).

7.6.2 Установка BDB

Если вы загрузили бинарную версию MySQL, которая включает поддержку BerkeleyDB, просто выполните инструкции по установке бинарной версии MySQL (см. разделы section 2.2.10 Установка бинарного дистрибутива MySQL и see section 4.7.5 mysqld-max, расширенный сервер mysqld).

Чтобы произвести компиляцию MySQL с поддержкой Berkeley DB, загрузите MySQL версии 3.23.34 или выше и выполните настройку MySQL при помощи параметра --with-berkeley-db (see section 2.3 Установка исходного дистрибутива MySQL).

cd /path/to/source/of/mysql-3.23.34
./configure --with-berkeley-db

Чтобы получить самую последнюю информацию, обращайтесь к руководству, которое поставляется с дистрибутивом BDB.

Хотя Berkeley DB детально протестирован и надежен, BDB-интерфейс MySQL пока еще является бета-версией. Мы совершенствуем и оптимизируем его, чтобы в скором времени добиться стабильной работы.

7.6.3 Параметры запуска BDB

Если запуск производился с параметром AUTOCOMMIT=0, то изменения, сделанные в в таблицах BDB, не вносятся, пока не будет выполнена команда COMMIT. Кроме операции фиксации, можно запустить команду ROLLBACK, чтобы отменить изменения (see section 6.7.1 Синтаксис команд BEGIN/COMMIT/ROLLBACK).

Если вы работаете с параметром AUTOCOMMIT=1 (значение по умолчанию), внесенные изменения будут фиксироваться немедленно. Можно выполнить расширенную транзакцию при помощи команды SQL BEGIN WORK, после которой изменения не будут зафиксированы до запуска команды COMMIT (или будут отменены при помощи команды ROLLBACK).

Чтобы изменить параметры таблиц BDB, можно воспользоваться следующими опциями mysqld:

Параметр | Описание
--bdb-home=directory | Базовый каталог для таблиц BDB. Это должен быть тот же каталог, что и для --datadir.
--bdb-lock-detect=# | Обнаружение блокировки Berkeley; одно из значений: DEFAULT, OLDEST, RANDOM или YOUNGEST
--bdb-logdir=directory | Каталог файла журнала Berkeley DB
--bdb-no-sync | Отмена синхронной записи журналов на диск
--bdb-no-recover | Отмена запуска Berkeley DB в режиме восстановления
--bdb-shared-data | Запуск Berkeley DB в режиме параллельной обработки (при инициализации Berkeley DB не следует использовать DB_PRIVATE)
--bdb-tmpdir=directory | Имя временной директории Berkeley DB
--skip-bdb | Отмена использования таблиц BDB
-O bdb_max_lock=1000 | Задает максимальное количество возможных блокировок (see section 4.5.6.4 SHOW VARIABLES).

Если используется параметр --skip-bdb, MySQL не будет инициализировать библиотеку Berkeley DB, что позволит сэкономить большое количество памяти. Разумеется, после включения этого параметра нельзя пользоваться таблицами BDB. если вы попытаетесь создать таблицу BDB, то в этом случае MySQL будет создавать таблицу MyISAM.

Обычно если предполагается использовать таблицы BDB, следует запускать mysqld без параметра --bdb-no-recover. Однако если файлы журналов BDB повреждены, то при попытке запуска mysqld могут возникнуть проблемы (see section 2.4.2 Проблемы при запуске сервера MySQL).

При помощи параметра bdb_max_lock задается максимальное количество блокировок (10000 по умолчанию), которые могут быть установлены на таблицу BDB. Это значение необходимо увеличить, если возникают ошибки bdb: Lock table is out of available locks или Got error 12 from ... при проведении длинных транзакций или когда mysqld должен просмотреть много строк, чтобы произвести необходимые вычисления для запроса.

Можно также изменить binlog_cache_size и max_binlog_cache_size, если используются большие многострочные транзакции (see section 6.7.1 Синтаксис команд BEGIN/COMMIT/ROLLBACK).

7.6.4 Характеристики таблиц BDB

  • Чтобы обеспечить возможность отката транзакций, для таблиц BDB поддерживается ведение файлов журналов. Для достижения максимальной производительности эти файлы необходимо разместить на разных с базой данных дисках, воспользовавшись параметром --bdb-logdir.
  • Каждый раз, когда создается новый файл журнала BDB, MySQL устанавливает контрольные точки и удаляет все файлы журналов, которые не нужны для текущих транзакций. Можно также в любое время запустить команду FLUSH LOGS, чтобы установить контрольную точку для таблиц Berkeley DB. Чтобы произвести восстановление после сбоя, необходимо воспользоваться резервными копиями таблицы, а также бинарным журналом MySQL (see section 4.4.1 Резервное копирование баз данных). Предупреждение: если удалить используемые старые файлы журналов, BDB не сможет осуществить восстановление, и в случае сбоя вы можете потерять данные.
  • В MySQL все таблицы BDB должны иметь первичные ключи, чтобы обеспечить возможность обращаться к ранее считанным строкам. Если первичный ключ не создан, MySQL создаст его и будет поддерживать скрытый первичный ключ. Длина скрытого ключа составляет 5 байтов, а его значение увеличивается при каждой попытке вставки.
  • Если все столбцы, к которым производится обращение в таблице BDB, являются частью одного индекса или одного первичного ключа, то MySQL может выполнить запрос, не обращаясь к самой строке. Для таблиц MyISAM это справедливо только если столбцы являются частью одного индекса.
  • Первичный ключ обеспечивает более быструю обработку, чем любой другой ключ, так как он хранится вместе с данными строки. Поскольку остальные ключи хранятся как данные ключа + PRIMARY KEY, очень важно иметь как можно более короткие первичные ключи, чтобы сэкономить дисковое пространство и увеличить производительность.
  • Команда LOCK TABLES работает с таблицами BDB точно так же, как и с другими таблицами. Если команда LOCK TABLE не используется, MySQL устанавливает на таблицу внутреннюю множественную блокировку записи, чтобы обеспечить правильную блокировку, если другой поток установит блокировку таблицы.
  • Внутренняя блокировка в таблицах BDB осуществляется на уровне страниц.
  • Команда SELECT COUNT(*) FROM table_name выполняется медленно, так как для таблиц BDB не поддерживается подсчет количества строк в таблице.
  • Сканирование осуществляется медленнее, чем в таблицах MyISAM, так как данные в таблицах BDB хранятся в B-деревьях, а не в отдельных файлах данных.
  • Приложение всегда должно быть готово к обработке ситуаций, в которых любые изменения таблицы BDB могут привести к автоматическому откату и любое считывание может вызвать сбой из-за возникновения взаимоблокировки.
  • Ключи не являются пакованными как в MyISAM. Иначе говоря, информация по ключам в таблицах BDB займет несколько больше места по сравнению с таблицами MyISAM.
  • В таблице BDB всегда имеются промежутки, благодаря чему можно вставлять новые строки в середину дерева ключа. Из-за этого таблицы BDB несколько больше, чем таблицы MyISAM.
  • Оптимизатору необходимо знать приблизительное количество строк в таблице. В MySQL этот вопрос решается путем подсчета количества вставок и поддержки этой информации в отдельном сегменте каждой таблицы BDB. Если операторов DELETE или ROLLBACK выполнялось не слишком много, это количество должно быть достаточно точным для оптимизатора MySQL, но MySQL сохраняет это число только при закрытии, и оно в случае аварийного завершения работы MySQL может оказаться неверным. Если число не соответствует действительности на 100% - ничего страшного в этом нет. Количество строк можно обновить, запустив команду ANALYZE TABLE или OPTIMIZE TABLE (см. разделы section 4.5.2 Синтаксис команды ANALYZE TABLE и see section 4.5.1 Синтаксис команды OPTIMIZE TABLE).
  • Если таблица BDB займет все пространство на диске, то будет выведено сообщение об ошибке (возможно, ошибка 28) и выполнен откат транзакции. В отличие от BDB, таблицы MyISAM и ISAM в mysqld будут ожидать, пока не появится свободное место, а потом продолжат работу.

7.6.5 Что нам нужно исправить в BDB в ближайшем будущем:

  • Процесс одновременного открытия многих таблиц BDB производится очень медленно. Если вы собираетесь применять таблицы BDB, не следует создавать очень большой кэш таблицы (например, больше 256 Кб) и необходимо использовать параметр --no-auto-rehash для клиента mysql. Мы планируем частично исправить это в версии 4.0.
  • Команда SHOW TABLE STATUS еще не предоставляет достаточного количества информации по таблицам BDB.
  • Оптимизация производительности.
  • Переход на запрет использования блокировок при сканировании таблиц.

7.6.6 Операционные системы, поддерживаемые BDB

На данный момент нам известно, что таблицы BDB работают со следующими операционными системами.

  • Linux 2.x Intel
  • Solaris SPARC
  • Caldera (SCO) OpenServer
  • Caldera (SCO) UnixWare 7.0.1

И не работают со следующими:

  • Linux 2.x Alpha
  • Max OS X

Этот список неполон. Мы будем обновлять его по мере поступления свежей информации.

Если вы собираете MySQL с поддержкой таблиц BDB и получаете вот такую ошибку в файле журнала при запуске mysqld:

bdb: architecture lacks fast mutexes: applications cannot be threaded
Can't init dtabases

То это означает, что таблицы BDB не поддерживаются на вашей платформе. В этом случае вам следует пересобрать MySQL без поддержки таблиц BDB.

7.6.7 Ограничения таблиц BDB

Ниже приведены ограничения при использовании таблиц BDB:

  • Таблицы BDB хранятся в файле `.db', который находится в том же каталоге, где был создан (это сделано для того, чтобы была возможность обнаруживать блокировки в многопользовательской среде с поддержкой символических ссылок). Но вследствие этого таблицы BDB нельзя перемещать между каталогами!
  • При создании резервных копий таблиц BDB необходимо использовать mysqldump или создать резервные копии всех файлов `table_name.db' и файлов журналов BDB. Файлы журналов BDB - это файлы в базовом каталоге донных с именами `log.XXXXXX' (6 цифр). Обработчик таблицы BDB хранит незавершенные транзакции в файлах журналов; их наличие требуется при запуске mysqld.

7.6.8 Ошибки, которые могут возникнуть при использовании таблиц BDB

  • Если в `hostname.err log' при запуске mysqld возникла следующая ошибка:
    bdb: Ignoring log file: .../log.XXXXXXXXXX: unsupported log version #
    это означает, что новая версия BDB не поддерживает старый формат файлов журналов. В этом случае необходимо удалить все файлы журналов BDB из каталога своей базы данных (файлы формата `log.XXXXXXXXXX' ) и перезапустить mysqld. Мы также рекомендуем сохранить содержимое BDB-баз данных в файл путем вызова mysqldump --opt, удалить старые файлы таблиц и восстановить базы данных из сохраненного файла.
  • Если запуск производится не в режиме auto_commit и происходит удаление таблицы, которая используется другим потоком, в файле ошибок MySQL могут появится следующие записи:
    001119 23:43:56 bdb: Missing log fileid entry
001119 23:43:56 bdb: txn_abort: Log undo failed for LSN:
1 3644744: Invalid
    Это не смертельно, но мы не рекомендуем удалять таблицы, если вы не находитесь в режиме auto_commit, пока эта проблема не будет решена (а решить ее вовсе не просто).


Справочное руководство по MySQL версии 5.0.0-alpha. - 8 Интерфейсы для MySQL

8 Интерфейсы для MySQL

Эта глава описывает доступные для MySQL интерфейсы, а также разъясняет, где их можно получить и как их использовать. Интерфейс C API охвачен наиболее широко, так как он был разработан командой MySQL и является базой для большинства других интерфейсов.

8.1 Интерфейс PHP API для MySQL

PHP представляет собой серверный язык программирования скриптов со встраиваемым кодом HTML, который может использоваться для создания динамических веб-страниц. Он содержит поддержку для доступа к нескольким базам данных, включая MySQL. PHP может запускаться как отдельная программа или компилироваться как модуль для использования с веб-сервером Apache.

Дистрибутив и документацию можно найти на веб-сайте PHP (http://www.php.net/).

8.1.1 Общие проблемы MySQL и PHP

  • Ошибка: "Максимальное время исполнения превышено" ("Maximum Execution Time Exceeded"). Это ограничение PHP; откройте файл `php3.ini' и измените максимальное время исполнения с 30 секунд на более высокую величину, такую, какая вам необходима. Есть еще один неплохой способ - удвоить разрешенный объем оперативной памяти с 8 Мб до 16 Мб на скрипт.
  • Ошибка: "Неисправимая ошибка: Вызов неподдерживаемой или неопределенной функции mysql_connect() в .." ("Fatal error: Call to unsupported or undefined function mysql_connect() in ..") Это означает, что ваша версия PHP не скомпилирована с поддержкой MySQL. Можно либо скомпилировать динамический модуль MySQL и загрузить его в PHP, либо перекомпилировать PHP со встроенной поддержкой MySQL. Это подробно описывается в руководстве по PHP.
  • Ошибка: "неопределенная ссылка на `uncompress' (несжатый) " ("undefined reference to `uncompress'"). Это означает, что данная клиентская библиотека скомпилирована с поддержкой сжатого клиент-серверного протокола. Устранение этой проблемы заключается в добавлении -lz в конце при линковании с -lmysqlclient.

8.2 Интерфейс Perl API для MySQL

Этот раздел снабжает документами для работы с интерфейсом Perl DBI. Более ранний интерфейс назывался mysqlperl. В настоящее время интерфейс DBI/DBD является рекомендуемым интерфейсом Perl, так что mysqlperl здесь не документируется как устаревший.

8.2.1 DBI с помощью DBD::mysql

DBI представляет собой общий интерфейс для многих баз данных. Это означает, что можно написать скрипт, работающий со многими различными процессорами баз данных без изменения. При этом для каждого типа базы данных необходим определенный драйвер (DBD - это абревиатура DataBase Driver). Для MySQL этот драйвер называется DBD::mysql.

Для более подробной информации об интерфейсе Perl5 DBI, пожалуйста, посетите веб-страницу DBI и прочитайте документацию:

http://dbi.perl.org/

Для более подробной информации об объектно ориентированном программировании (OOП), описанном в Perl5, смотрите веб-страницу Perl OOP:

http://language.perl.com/info/documentation.html

Следует учитывать, что, если вы хотите использовать транзакции с Perl, то необходимо иметь модуль Msql-Mysql-modules версии 1.2216 или новее.

Рекомендуемый модуль для Perl: DBD-mysql-2.1022 или новее.

Инструкции по установке поддержки Perl в MySQL даются в разделе See section 2.7 Замечания по установке Perl.

Если у вас уже установлены модули MySQL, то вы можете найти информацию о специфике функциональности MySQL при помощи одной из следующих команд:

shell> perldoc DBD/mysql
shell> perldoc mysql

8.2.2 Интерфейс DBI

Унифицированные методы DBI
Метод | Описание
connect | Создает соединение с сервером
disconnect | Разрывает соединение с сервером
prepare | Готовит SQL-запрос к выполнению
execute | Выполняет приготовленный запрос
do | Готовит и выполняет запрос
quote | Заключает в символы цитирования строки или BLOB-значения, которые вы собираетесь внести
fetchrow_array | Возвращает следующую запись как массив
fetchrow_arrayref | Возвращает следующую запись как ссылку на массив
fetchrow_hashref | Возвращает следующую запись как ссылку на хеш
fetchall_arrayref | Возвращает всю информацию как массив массивов
finish | Завершает выражение и освобождает системные ресурсы
rows | Возвращает количество измененных/удаленных строк
data_sources | Возвращает массив, список баз данных, доступных на сервере
ChopBlanks | Определяет, будут ли методы fetchrow_* убирать начальные и оконечные пробелы
NUM_OF_PARAMS | Количество символов-заполнителей в приготовленном выражении
NULLABLE | Возвращает ссылку на массив значений, которые определяют, могут ли столбцы содержать значения NULL. Возможные значения для каждого элемента массива: 0 или пустая строка, если столбец не может быть NULL, 1 - если может, и 2, если статус NULL для столбца неизвестен
trace | Производит трассировку для отладки

Методы, определенные только для MySQL

Метод | Описание
insrtid | Значение AUTO_INCREMENT, которое было присвоено последним
is_blob | Какие столбцы имеют тип BLOB
is_key | Какие столбцы являются ключами
is_num | Какие столбцы имеют числовой тип
is_pri_key | Какие столбцы являются первичными ключами
is_not_null | Столбцы, которые НЕ МОГУТ иметь значение NULL. См. NULLABLE
length | Максимально допустимые размеры содержимого столбцов
max_length | Максимальные размеры столбцов, присутствующих в результате
NAME | Имена столбцов
NUM_OF_FIELDS | Количество полей, возвращенных в результате операции
table | Имена таблиц в результате
type | Типы всех столбцов

Более детально методы Perl DBI описаны в следующих разделах. Возвращаемые переменные:

$dbh
Дескриптор базы данных
$sth
Дескриптор выражения
$rc
Код возврата (часто статус)
$rv
Возвращенное значение (часто количество строк)

Унифицированные методы DBI

connect($data_source, $username, $password)
Метод connect используется для подсоединения к источнику данных (СУБД). Строка $data_source должна начинаться с DBI:имя драйвера:. Примеры вызова connect с драйвером DBD::mysql:
$dbh = DBI->connect("DBI:mysql:$database", $user, $password);
$dbh = DBI->connect("DBI:mysql:$database:$hostname", $user,
        $password);
$dbh = DBI->connect("DBI:mysql:$database:$hostname:$port", $user,
        $password);
Если не определены имя пользователя либо пароль, DBI использует значения переменных окружения DBI_USER и DBI_PASS. Если не указано имя хоста, используется значение по умолчанию - localhost. Если не указан номер порта, также используется значение по умолчанию (3306). Начиная с Msql-Mysql-modules версии 1.2009, доступны следующие модификаторы $data_source:
mysql_read_default_file=file_name
Читать файл `file_name' как файл настроек. За более подробной информацией о файлах настройки обращайтесь к разделу See section 4.1.2 Файлы параметров `my.cnf'.
mysql_read_default_group=group_name
По умолчанию используется группа [client] файла настроек. Опцией mysql_read_default_group, группа по умолчанию устанавливается в [group_name].
mysql_compression=1
Использовать сжатие при обмене клиента и сервера (MySQL версий 3.22.3 и выше).
mysql_socket=/path/to/socket
Указывает путь к Unix-сокету, который будет использоваться для соединения с сервером. (MySQL версии 3.21.15 и более поздние).
Можно указывать не один модификатор, а несколько; при этом каждый должен предваряться точкой с запятой. Например, если вы не хотите явно указывать имя пользователя и пароль в программе, использующей DBI, можно внести эту информацию в файл `~/.my.cnf', написав вызов connect. Это делается следующим образом:
$dbh = DBI -> connect("DBI:mysql:$database",
          ";mysql_read_default_file=$ENV{HOME}/.my.cnf",
            $user, $password);
Данный пример считает настройки из группы [client] файла `~/.my.cnf'. Чтобы выполнить те же действия, но с настройками, взятыми из группы [perl], нужно использовать следующую форму записи:
$dbh = DBI -> connect("DBI:mysql:$database",
          ";mysql_read_default_file=$ENV{HOME}/.my.cnf"
          . ";mysql_read_default_group=perl",
          $user, $password);
disconnect
Метод disconnect разрывает соединение с базой данных. Это стоит делать перед выходом из программы. Пример:
$rc = $dbh->disconnect;
prepare($statement)
Подготавливает SQL-запрос $statement к исполнению сервером. Возвращает дескриптор выражения ($sth), который затем используется для вызова метода execute. Обычно работа с запросами типа SELECT (так же, как и аналогичными, такими как SHOW, DESCRIBE, EXPLAIN) сводится к вызову методов prepare и execute. Пример:
$sth = $dbh -> prepare($statement)
or die "Не  могу  подготовить $statement: $dbh -> errstr\n";
Если вы хотите считывать большие результаты вашим клиентом, вы можете указать использование mysql_use_result() в Perl:
my $sth = $dbh->prepare($statement { "mysql_use_result" => 1});
execute
Метод execute выполняет приготовленный запрос. Если запрос не SELECT, метод возвращает количество строк, которые были подверглись воздействию запроса. Если таковых нет, execute возвращает "0E0", что Perl интерпретирует как нуль, но воспринимает как значение ``истина'' (true). Если возникает ошибка, execute возвращает undef. Для запросов SELECT метод только инициирует выполнение запроса SQL-сервером и для получения данных необходимо использовать один из методов fetch_*. Пример:
$rv = $sth -> execute or die "Не могу выполнить: $sth -> errstr";
do($statement)
Метод do готовит SQL-запрос к выполнению, выполняет его и возвращает количество строк, подвергшихся воздействию. Если нет ни одной такой строки, как результат возвращается значение "0E0", что Perl интерпретирует как нуль, но воспринимает как значение ``истина'' (true).. Этот метод обычно используется для выражений, не являющихся операторами SELECT, которые не могут быть подготовлены заранее (из-за ограничений драйвера) или же выполняются только один раз (операции вставки, удаления и т.д.). Например:
$rv = $dbh->do($statement)
or die "Не могу выполнить: $sth -> errstr";
Обычно использование 'do' существенно быстрей (и предпочтительней) для запросов без параметров, чем пара prepare/execute.
quote($string)
Метод quote используется для экранирования специальных символов в запросе символами экранирования, а также заключения данных в необходимые внешние символы цитирования (например кавычки). Пример:
$sql = $dbh->quote($string)
fetchrow_array
Этот метод выбирает очередную строку данных и возвращает ее как массив значений полей. Пример:
while(@row = $sth -> fetchrow_array) {
print qw($row[0]\t$row[1]\t$row[2]\n);
}
fetchrow_arrayref
Этот метод выбирает очередную строку данных и возвращает ссылку на массив значений полей. Пример:
while($row_ref = $sth -> fetchrow_arrayref) {
print qw($row_ref -> [0]\t$row_ref -> [1]\t$row_ref ->
[2]\n);
}
fetchrow_hashref
Этот метод выбирает строку данных и возвращает ссылку на хеш, содержащий пары имя/значение. Данный метод намного менее эффективен, чем использование пописанных выше ссылок на массивы. Пример:
while($hash_ref = $sth -> fetchrow_hashref) {
print qw($hash_ref -> {firstname}\t$hash_ref ->
{lastname}\t$hash_ref ->{title}\n);
}
fetchall_arrayref
Этот метод выдает все данные (все строки), получаемые как результат SQL-запроса. Он возвращает ссылку на массив ссылок на массивы отдельных строк. Соответственно, для обращения к этим данным нужно использовать вложенный цикл. Пример:
my $table = $sth -> fetchall_arrayref
or die "$sth -> errstr\n";
my($i, $j);
for $i ( 0 .. $#{$table}} ) {
for $j ( 0 .. $#{$table -> [$i]} )  {
print "$table -> [$i][$j]\t";
}
print "\n";
}
finish
Указывает, что данные этого дескриптора запроса больше не нужны. После вызова этого метода программа освобождает дескриптор запроса и все системные ресурсы, которые используются для работы с ним. Пример:
$rc = $sth -> finish;
rows
Возвращает число измененных/удаленных последней командой (UPDATE, DELETE и т.д.) строк. Это обычно требуется после выполнения метода execute над запросами, не являющимися запросами SELECT. Например:
$rv = $sth -> rows;
NULLABLE
Возвращает ссылку на массив значений, которые указывают, может столбец принимать значения NULL или нет. Возможные значения для каждого элемента массива - это 0 или пустая строка, если столбец не может содержать значения NULL, 1 - если может и 2 - если статус столбца относительно значения NULL не определен. Например:
$null_possible = $sth -> {NULLABLE};
NUM_OF_FIELDS
Значение этого атрибута равно числу полей в результате запроса (SELECT или SHOW FIELDS). Его можно использовать его для проверки, возвращает ли запрос результат вообще: нулевое значение соответствует запросам типа INSERT, DELETE, UPDATE - т.е. всем, кроме SELECT. Например:
$nr_of_fields = $sth -> {NUM_OF_FIELDS};
data_sources($driver_name)
Этот метод возвращает массив с именами баз данных, доступных на локальном MySQL-сервере (на localhost). Пример:
@dbs = DBI->data_sources("mysql");
ChopBlanks
Этот атрибут определяет, будут ли методы fetchrow_* убирать начальные и оконечные пробелы из результатов. Пример:
$sth -> {'ChopBlanks'} = 1;
trace($trace_level)
trace($trace_level, $trace_filename)
Метод trace разрешает или запрещает трассировку. Если он вызывается как метод класса DBI, он влияет на разрешение трассировки всех дескрипторов. В случае же обращения к нему как к методу дескриптора запроса либо базы данных он разрешает/запрещает трассировку для этой базы данных или этого запроса (и всех будущих потомков). $trace_level указывает уровень детализации трассировочной информации, так установка $trace_level в 2 включает детализированную трассировку. Установка $trace_level в 0 запрещает трассировку. По умолчанию вывод трассировочной информации осуществляется на стандартное устройство вывода ошибок (stderr). Если указан параметр $trace_filename, его значение используется как имя файла, в который выводится трассировочная информация ВСЕХ дескрипторов, для которых разрешена трассировка. Пример:
DBI->trace(2);                # трассировка всего
DBI->trace(2,"/tmp/dbi.out"); # трассировка всего в /tmp/dbi.out
$dth->trace(2);               # трассировка всех запросов к этой базе
данных
$sth->trace(2);               # трассировка этого запроса
Трассировку DBI можно также включить при помощи переменной окружения DBI_TRACE. Присвоение числового значения эквивалентно вызову DBI->trace(значение). Строковое значение (имя файла) эквивалентно вызову DBI->trace(2,значение).

Методы, специфичные для MySQL

Описанные здесь методы специфичны для MySQL и не являются частью стандарта DBI. Сейчас считается, что часть из них использовать не стоит: is_blob, is_key, is_num, is_pri_key, is_not_null, length, max_length и table. Ниже указаны возможные стандартные альтернативы, если они существуют:

insertid
Если вы используете специфичную для MySQL функцию AUTO_INCREMENT, здесь будут сохраняться автоматически увеличенные значения. Пример:
$new_id = $sth->{insertid};
В качестве альтернативы можно использовать $dbh -> {'mysql_insertid'}.
is_blob
Возвращает ссылку на массив булевых значений; для каждого элемента массива значение ``истина'' указывает, что соответствующий столбец имеет тип BLOB. Например:
$keys = $sth -> {is_blob};
is_key
Возвращает ссылку на массив булевых значений; для каждого элемента массива значение ``истина'' указывает, что соответствующий столбец является ключом. Пример:
$keys = $sth -> {is_key};
is_num
Возвращает ссылку на массив булевых значений; для каждого элемента массива, значение ``истина'' указывает, что соответствующий столбец содержит числовые значения. Например:
$nums = $sth -> {is_num};
is_pri_key
Возвращает ссылку на массив булевых значений; для каждого элемента массива, значение ``истина'' указывает, что соответствующий столбец является первичным ключом. Пример:
$pri_keys = $sth -> {is_pri_key};
is_not_null
Возвращает ссылку на массив б булевых значений; для каждого элемента массива значение ``ложь'' указывает на то, что столбец может содержать значения NULL. Например:
$not_nulls = $sth -> {is_not_null};
is_not_null не рекомендуется к применению; предпочтительно использование NULLABLE (описан ранее), поскольку это стандартный для DBI метод.
length
max_length
Каждый из этих методов возвращает ссылку на массив размеров столбцов. Массив, соответствующий length, содержит максимальные допустимые размеры каждого столбца (из описания таблицы). Массив max_length содержит максимальные размеры элементов, присутствующих в результирующей таблице. Например:
$lengths = $sth -> {length};
$max_lengths = $sth -> {max_length};
NAME
Возвращает ссылку на массив имен столбцов. Например:
$names = $sth -> {NAME};
table
Возвращает ссылку на массив названий таблиц. Например:
$tables = $sth -> {table};
type
Возвращает ссылку на массив типов столбцов. Пример:
$types = $sth -> {type};

8.2.3 Больше информации по DBI/DBD

Вы можете использовать команду perldoc для получения больше информации по DBI.

perldoc DBI
perldoc DBI::FAQ
perldoc DBD::mysql

Конечно, вы можете использовать pod2man, pod2html и другие утилиты для трансляции в другие форматы.

Самая свежая информация по DBI живет на веб-сайте DBI: http://dbi.perl.org/.

8.3 Поддержка ODBC в MySQL

MySQL обеспечивает поддержку для ODBC посредством программы MyODBC. В этом разделе показано, как устанавливать и использовать MyODBC. Здесь также приведен список программ общего применения, о которых известно, что они работают с MyODBC.

8.3.1 Как установить MyODBC

MyODBC 2.50 представляет собой 32-разрядный драйвер ODBC спецификации уровня 0 (с возможностями уровней 1 и 2) для подсоединения совместимого с ODBC приложения к MySQL. MyODBC работает под Windows 9x/Me/NT/2000/XP и на большинстве платформ Unix.

MyODBC 3.51 это усовершенствованная версия ODBC со спецификационным уровнем 1 (полностью ядро API + уровень возможности 2).

MyODBC является свободно доступным. Самую свежую версию можно найти на http://www.mysql.com/downloads/api-myodbc.html.

Обратите внимание, что версии 2.50.х распространяются под LGPL лицензией, тогда как 3.51.х версии под лицензией GPL.

Если существуют проблемы с MyODBC, а программа также работает и с OLEDB, то следует попробовать работать с драйвером OLEDB.

Обычно установка MyODBC требуется только на компьютерах под Windows. Для Unix необходимость в MyODBC возникает только для программ, подобных ColdFusion, которые работают на Unix-машинах и используют ODBC для подключения к базам данных.

Для установки MyODBC на Unix-машину понадобится также программа управления ODBC. MyODBC, как известно, работает с большинством программ управления ODBC для Unix.

Для того чтобы установить MyODBC на Windows, необходимо загрузить соответствующий файл MyODBC `.zip', распаковать его с помощью WinZIP или другой подобной программы и выполнить исполняемый файл `SETUP.EXE'.

При попытке установить MyODBC под Windows/NT/XP можно получить следующую ошибку:

An error occurred while copying C:\WINDOWS\SYSTEM\MFC30.DLL. Restart
Windows and try installing again (before running any applications which
use  ODBC)

Проблема здесь заключается в том, что некоторая другая программа в это же время использует ODBC и из-за конструктивных особенностей Windows в данном случае может оказаться невозможным установить новый драйвер ODBC с помощью поставляемой Microsoft программы установки. В большинстве случаев можно продолжать установку, просто нажимая Ignore для копирования оставшихся файлов MyODBC, при этом заключительная установка должна работать. Если она не работает, то выход состоит в следующем: перезагрузите систему в безопасном режиме (safe mode) (для перехода в этот режим следует нажать F8 непосредственно перед тем, как компьютер начинает запускать Windows во время перезагрузки), установите MyODBC и перезагрузите Windows в обычном режиме.

  • Чтобы установить подсоединение к Unix-компьютеру от Windows-компьютера с помощью приложения ODBC (которое само по себе не поддерживает MySQL), необходимо вначале установить MyODBC на Windows-машине.
  • Данный пользователь и Windows-машина должны обладать привилегиями доступа к серверу MySQL на Unix-машине. Это устанавливается с помощью команды GRANT (see section 4.3.1 Синтаксис команд GRANT и REVOKE).
  • Необходимо создать новую запись DSN ODBC следующим образом:
  • Открыть Control Panel (Панель управления) на Windows-компьютере.
  • Выполнить двойной щелчок на пиктограмме ODBC Data Sources 32-bit (Источники данных ODBC (32бит)).
  • Щелкнуть на закладке User DSN (Пользовательский DSN).
  • Щелкнуть на кнопке Add (Добавить).
  • Выбрать MySQL в окне Create New Data Source (Создание нового источника данных) и щелкнуть на кнопке Finish (Готово).
  • Откроется окно конфигурации драйвера MySQL по умолчанию (see section 8.3.2 Как заполнять различные поля в Администраторе ODBC).
  • Теперь запустите свое приложение и выберите драйвер ODBC с помощью DSN, заданного вами в Администраторе источников данных ODBC.

Обратите внимание: существуют и другие возможности конфигурации в окне MySQL (трассировка, не подсказывать соединение и так далее), которые вы можете опробовать, если столкнетесь с какими-либо проблемами.

8.3.2 Как заполнять различные поля в Администраторе ODBC

Для Windows 95 существует три возможности задания имени сервера:

  • Использовать IP-адрес сервера.
  • Добавить файл \windows\lmhosts со следующей информацией:
    ip hostname
    Например:
    194.216.84.21 my_hostname
  • Сконфигурировать ПК для использования DNS.

Пример заполнения при установке ODBC:

Windows DSN name:   test
Description:        This is my test database
MySql Database:     test
Server:             194.216.84.21
User:               monty
Password:           my_password
Port:

Значением поля Windows DSN name может быть любое имя, уникальное для данной установки ODBC.

Не обязательно указывать значения для полей Server, User, Password или Port в окне установки ODBC. Однако если вы это сделали, данные величины в дальнейшем при установке соединения будут использованы как значения по умолчанию. Тогда же можно будет изменить эти значения.

Если номер порта не задан, то используется его значение по умолчанию (3306).

Если задается опция Read options from C:\my.cnf, то группы client и odbc будут читаться из файла `C:\my.cnf'. Можно применять все опции, используемые в mysql_options() (see section 8.4.3.39 mysql_options()).

8.3.3 Параметры подключения для MyODBC

Можно указать следующие параметры для MyODBC в разделе [Servername] файла `ODBC.INI' или через аргумент InConnectionString при вызове функции SQLDriverConnect().
Параметр | Величина по умолчанию | Комментарий
user | ODBC (под Windows)@tab Имя пользователя, используемое для подключения к MySQL.
server | localhost | Имя хоста сервера MySQL.
database@tab | База данных по умолчанию.
option | 0 | Целое число, с помощью которого можно указать, как должен работать драйвер MyODBC (см. ниже).
port | 3306 | Используемый порт TCP/IP, если значением server не является localhost.
stmt |  | Команда, которая будет выполняться при подключении к MySQL.
password@tab | Пароль для комбинации server user.
socket |  | Сокет или канал Windows для подключения.

Аргумент ``option'' используется для указания MyODBC, что данный клиент не на 100% соответствует ODBC. Под Windows обычно устанавливается флаг опций путем переключения различных опций в окне данного соединения, но можно также установить это в аргументе ``option''. Следующие опции перечислены в том же порядке, в котором они перечислены в окне подключения MyODBC:
Бит | Описание
1 | Данный клиент не может отследить, что драйвер MyODBC возвращает реальную ширину столбца.
2 | Данный клиент не может отследить, что драйвер MyODBC возвращает реальную величину подвергшихся воздействию строк. Если этот флаг установлен, то взамен MySQL возвращает ``найденные строки''. Необходима версия MySQL 3.21.14 или более новая, чтобы эта опция работала.
4 | Создает журнал отладки в c:\myodbc.log. Это то же самое, что задать MYSQL_DEBUG=d:t:O,c::\myodbc.log в `AUTOEXEC.BAT'
8 | Не устанавливать никаких пакетных ограничений для результатов и параметров.
16 | Не выводить подсказки для вопросов, даже если драйвер захотел бы предложить это
32 | Имитировать драйвер ODBC 1.0 в определенной ситуации.
64 | Игнорировать использование имени базы данных в database.table.column.
128 | Заставляет использовать указатели менеджера ODBC (экспериментальная).
256 | Отключить использование расширенной выборки (экспериментальная).
512 | Заполнить поля CHAR до полной длины столбца.
1024 | Функция SQLDescribeCol() будет возвращать полностью уточненные имена столбцов
2048 | Использовать сжатие в клиент-серверном протоколе
4096 | Предписывает серверу игнорировать пробел после имени функции и перед `(' (необходимо для PowerBuilder). Это сделает имена всех функций ключевыми словами!
8192 | Соединяет с именованными каналами сервер mysqld, работающий под NT.
16384 | Изменяет тип столбцов LONGLONG на INT (некоторые приложения не могут обрабатывать LONGLONG).
32768 | Возвращает параметр user как Table_qualifier и Table_owner из SQL-таблиц (экспериментальная)
65536 | Читает параметры из групп client и odbc из файла `my.cnf'
131072 | Добавляет некоторые дополнительные проверки безопасности (не должно понадобиться, но...)

Если необходимо иметь много опций, следует добавить вышеуказанные флаги! Например, установка опции в 12 (4+8) дает отладку без ограничений пакетов!

По умолчанию `MYODBC.DLL' компилируется для оптимальной производительности. Если необходимо отладить MyODBC (например, включить трассировку), следует вместо этого использовать `MYODBCD.DLL'. Для установки этого файла следует скопировать `MYODBCD.DLL' поверх установленного файла `MYODBC.DLL'.

8.3.4 Как сообщать о проблемах с MyODBC

Драйвер MyODBC был протестирован с Access, Admndemo.exe, C++-Builder, Borland Builder 4, Centura Team Developer (первоначально Gupta SQL/Windows), ColdFusion (под Solaris и NT с пакетом обновлений svc pack 5), Crystal Reports, DataJunction, Delphi, ERwin, Excel, iHTML, FileMaker Pro, FoxPro, Notes 4.5/4.6, SBSS, Perl DBD-ODBC, Paradox, Powerbuilder, 32-разрядным Powerdesigner, VC++ и Visual Basic.

Если вам известны какие- либо другие приложения, работающие с MyODBC, пожалуйста, пошлите сообщение об этом по адресу myodbc@lists.mysql.com!

При работе с некоторыми программами можно получить ошибку вроде: Another user has modifies the record that you have modified.

В большинстве случаев эту проблему можно устранить одним из следующих способов:

  • Добавить первичный ключ для данной таблицы, если он еще не создан.
  • Добавить столбец TIMESTAMP, если он еще не создан.
  • Использовать поля только с числами с плавающей запятой двойной точности. Некоторые программы могут не срабатывать при сравнении чисел с плавающей запятой одинарной точности.

Если перечисленные выше способы не помогают, необходимо сделать трассировочный файл MyODBC и попробовать определить, в чем дело.

8.3.5 Программы, работающие с MyODBC

Большинство программ должно работать с MyODBC, но для каждой из перечисленных ниже мы либо провели тестирование сами, либо получили подтверждение от пользователей, что она действительно работает:

Программа
Комментарий
Access
Чтобы заставить Access работать:
  • При использовании Access 2000 необходимо установить самую последнюю версию (2.6 или выше) Microsoft MDAC (Microsoft Data Access Components), которую можно найти на http://www.microsoft.com/data/. Это позволит устранить ошибку в Access, которая проявляется в том, что при экспорте данных в MySQL не указываются имена таблиц и столбцов. Еще один способ обойти эту ошибку заключается в модернизации MyODBC до версии 2.50.33 и MySQL до версии 3.23.x - оба апгрейда вместе обеспечивают обход данной ошибки! Необходимо также получить и использовать Microsoft Jet 4.0 Service Pack 5 (SP5), который можно найти на http://support.microsoft.com/support/kb/articles/Q 239/1/14.ASP. Это позволит исключить некоторые случаи, когда столбцы в Access отмечаются как #deleted#. Следует учитывать, что при использовании версии MySQL 3.22 необходимо применять патч для MDAC и использовать MyODBC 2.50.32 или 2.50.34 и выше, чтобы обойти эту проблему.
  • Для всех версий Access необходимо включить для MyODBC флаг опции Return matching rows. Для Access 2.0 следует дополнительно включить Simulate ODBC 1.0.
  • Все таблицы, в которых вы хотите иметь возможность обновления, должны содержать столбец типа TIMESTAMP для временных меток. Для максимальной переносимости рекомендуется TIMESTAMP(14) или просто TIMESTAMP вместо других вариантов TIMESTAMP(X).
  • Таблица должна иметь первичный ключ. Если не имеет, то новые или обновленные строки могут выводиться как #DELETED#.
  • Используйте поля с числами с плавающей запятой только двойной точности (типа DOUBLE). Access отказывается работать при сравнении чисел с плавающей запятой одинарной точности. Проявляется это обычно в том, что новые или обновленные строки могут выводиться как #DELETED# или в том, что вы не можете найти или обновить строки.
  • При связывании через MyODBC таблицы, один из столбцов которой имеет тип BIGINT, результат будет выводиться как #DELETED#. Обходное решение заключается в следующем:
    • Добавьте еще один пустой столбец с TIMESTAMP в качестве типа данных, предпочтительно TIMESTAMP(14).
    • Проверьте Change BIGINT columns to INT в диалоговом окне опций подключения в Администраторе источников данных ODBC DSN
    • Удалите данную табличную связь из Access и создайте ее вновь.
    После этого старые записи все равно будут представлены как #DELETED#, а заново добавленные/обновленные записи будут уже выводиться правильно.
  • Если после добавления столбца TIMESTAMP все еще появляется ошибка Another user has changed your data, то, возможно, поможет следующий трюк. Не используйте режим работы ``Таблица''. Вместо этого создайте форму с желаемыми полями и используйте режим работы ``Форма''. Следует установить свойство DefaultValue для столбца TIMESTAMP в NOW(). Возможно, было бы неплохо убрать столбец TIMESTAMP из поля зрения, чтобы не смущать пользователей.
  • В некоторых случаях Access может создавать недопустимые запросы SQL, которые MySQL не может понять. Это можно устранить путем выбора в меню Access опции Query|SQLSpecific|Pass-Through.
  • Access под NT будет сообщать о столбцах BLOB как об объектах OLE. Если вместо этого вы хотите иметь столбцы MEMO, то необходимо изменить тип столбца на TEXT с помощью ALTER TABLE.
  • Access не всегда может правильно обработать столбцы типа DATE. Если с ними возникают проблемы, следует изменить тип этих столбцов на DATETIME.
  • Если Access содержит столбец, определенный как BYTE, то Access будет пытаться экспортировать его как TINYINT вместо TINYINT UNSIGNED. Это будет вызывать проблемы, если величины в данном столбце превышают 127!
ADO
При написании программ с привлечением интерфейса ADO API и MyODBC необходимо обратить внимание на некоторые исходные свойства, которые не поддерживаются сервером MySQL. Например, использование свойства CursorLocation как adUseServer будет возвращать для свойства RecordCount результат -1. Чтобы получить правильную величину, необходимо установить данное свойство в adUseClient, как показано в коде VB ниже:
Dim myconn As New ADODB.Connection
Dim myrs As New Recordset
Dim mySQL As String
Dim myrows As Long

myconn.Open "DSN=MyODBCsample"
mySQL = "SELECT * from user"
myrs.Source = mySQL
Set myrs.ActiveConnection = myconn
myrs.CursorLocation = adUseClient
myrs.Open
myrows = myrs.RecordCount

myrs.Close
myconn.Close
Еще один обходной путь состоит в том, чтобы для такого запроса использовать команду SELECT COUNT(*), чтобы получить правильное количество строк.
Активные серверные страницы (ASP)
Необходимо использовать флаг опции Return matching rows.
BDE-приложения
Чтобы заставить их работать, следует установить флаги опций Don't optimize column widths и Return matching rows.
Borland Builder 4
При запуске запроса можно использовать свойство Active или метод Open. Следует учитывать, что Active будет начинать работу при автоматической выдаче запроса SELECT * FROM ..., что может оказаться не так уж и хорошо для больших таблиц!
ColdFusion (Под Unix)
Приведенные далее сведения взяты из документации по ColdFusion. Для применения драйвера unixODBC с источником данных MyODBC следует использовать следующую информацию. Корпорация Allaire подтвердила, что версия MyODBC 2.50.26 работает с версией MySQL 3.22.27 и ColdFusion для Linux (любая более новая версия также должна работать). Драйвер MyODBC можно загрузить с http://www.mysql.com/downloads/api-myodbc.html В версии ColdFusion 4.5.1 можно использовать Администратор источников данных ColdFusion для добавления источника данных MySQL. Однако данный драйвер не включен в версию ColdFusion 4.5.1. Чтобы драйвер MySQL появился в выпадающем списке источников данных ODBC, необходимо создать драйвер MyODBC и скопировать его в каталог `/opt/coldfusion/lib/libmyodbc.so'. Каталог `Contrib' содержит программу `mydsn-xxx.zip', которая позволяет создавать и удалять файл реестра DSN для драйвера MyODBC для приложений Coldfusion.
DataJunction
Необходимо изменить эту программу для вывода VARCHAR вместо ENUM, поскольку экспорт ENUM происходит таким образом, что вызывает неприятности в MySQL.
Excel
Работает. Несколько замечаний:
  • Если существуют проблемы с датами, попробуйте выбирать их как строки, используя функцию CONCAT(). Например:
    select CONCAT(rise_time), CONCAT(set_time)
    from sunrise_sunset;
    Величины, извлеченные как строки этим способом, должны корректно распознаваться программой Excel97 как значения времени. Назначение функции CONCAT() в этом примере состоит в том, чтобы ``обмануть'' ODBC, заставив интерпретировать столбец как столбец ``строкового типа''. Без функции CONCAT() ODBC будет считать, что это столбец временного типа, и Excel не распознает его. Следует заметить, что это является ошибкой Excel, поскольку он автоматически преобразует строку в значения времени. Это замечательно если источником является текстовый файл, но это глупо, когда источником является подключение ODBC, дающее точные типы данных для каждого столбца.
Word
Для извлечения данных из MySQL в документы Word/Excel следует использовать драйвер MyODBC и помощь встроенной программы Microsoft Query. Для создания, например, базы данных db с таблицей, содержащей 2 столбца с текстом, необходимо выполнить следующие действия:
  • Вставьте строки, используя командную строку клиента mysql.
  • Создайте файл DSN, используя менеджер ODBC, например, my для созданной выше базы данных db.
  • Откройте приложение Word.
  • Создайте новый пустой документ.
  • Используя панель инструментов вызванной базы данных, нажмите кнопку Insert database.
  • Нажмите кнопку Get Data.
  • В окне Get Data справа нажмите кнопку Ms Query.
  • В окне Ms Query создайте новый источник данных, используя файл DSN my.
  • Выберите новый запрос.
  • Выберите желаемый столбец.
  • Создайте фильтр (при желании).
  • Создайте сортировку (при желании).
  • Выберите Return Data to Microsoft Word.
  • Нажмите кнопку Finish.
  • Нажмите Insert data и выбирайте записи.
  • Нажмите Ok. Вы увидите выбранные строки в своем документе в Word.
odbcadmin
Тестовая программа для ODBC.
Delphi
Необходимо использовать версию BDE 3.2 или более новую. Установите поле опции Don't optimize column width при подключении к MySQL. Кроме того, ниже приводится потенциально полезный код Delphi, который устанавливает вхождения для драйвера MyODBC как в ODBC, так и в BDE. (Запись в BDE требует наличия редактора псевдонимов BDE Alias Editor, который доступен бесплатно на Delphi Super Page. Спасибо за это Брайену Брантону (Bryan Brunton bryan@flesherfab.com)):
fReg:= TRegistry.Create;
fReg.OpenKey('\Software\ODBC\ODBC.INI\DocumentsFab', True);
fReg.WriteString('Database', 'Documents');
fReg.WriteString('Description', ' ');
fReg.WriteString('Driver', 'C:\WINNT\System32\myodbc.dll');
fReg.WriteString('Flag', '1');
fReg.WriteString('Password', '');
fReg.WriteString('Port', ' ');
fReg.WriteString('Server', 'xmark');
fReg.WriteString('User', 'winuser');
fReg.OpenKey('\Software\ODBC\ODBC.INI\ODBC Data Sources', True);
fReg.WriteString('DocumentsFab', 'MySQL');
fReg.CloseKey;
fReg.Free;

Memo1.Lines.Add('DATABASE NAME=');
Memo1.Lines.Add('USER NAME=');
Memo1.Lines.Add('ODBC DSN=DocumentsFab');
Memo1.Lines.Add('OPEN MODE=READ/WRITE');
Memo1.Lines.Add('BATCH COUNT=200');
Memo1.Lines.Add('LANGDRIVER=');
Memo1.Lines.Add('MAX ROWS=-1');
Memo1.Lines.Add('SCHEMA CACHE DIR=');
Memo1.Lines.Add('SCHEMA CACHE SIZE=8');
Memo1.Lines.Add('SCHEMA CACHE TIME=-1');
Memo1.Lines.Add('SQLPASSTHRU MODE=SHARED AUTOCOMMIT');
Memo1.Lines.Add('SQLQRYMODE=');
Memo1.Lines.Add('ENABLE SCHEMA CACHE=FALSE');
Memo1.Lines.Add('ENABLE BCD=FALSE');
Memo1.Lines.Add('ROWSET SIZE=20');
Memo1.Lines.Add('BLOBS TO CACHE=64');
Memo1.Lines.Add('BLOB SIZE=32');
AliasEditor.Add('DocumentsFab','MySQL',Memo1.Lines);
C++ Builder
Проведено тестирование с версией BDE 3.0. Единственная обнаруженная проблема состоит в том, что при изменениях схемы таблиц не обновляются поля запросов. Хотя BDE не распознает первичных ключей, а только индекс PRIMARY, тем не менее, это не было проблемой.
Vision
Необходимо использовать флаг опции Return matching rows.
Visual Basic
Чтобы обеспечить возможность обновить таблицу, для нее необходимо определить первичный ключ. Visual Basic с ADO не обрабатывает больших целых чисел. Это означает, что некоторые запросы вроде SHOW PROCESSLIST не будут работать правильно. Для устранения данной проблемы нужно добавить опцию OPTION=16384 в строке подключения ODBC или установить опцию Change BIGINT columns to INT в окне подключения MyODBC. Можно также установить опцию Return matching rows.
VisualInterDev
Если возникает ошибка [Microsoft][ODBC Driver Manager] Driver does not support this parameter, то ее причина может заключаться в том, что результат содержит данные типа BIGINT. Попробуйте установить опцию Change BIGINT columns to INT в окне подключения MyODBC.
Visual Objects
Необходимо использовать флаг опции Don't optimize column widths.

8.3.6 Как получить значение столбца AUTO_INCREMENT в ODBC

Существует распространенная проблема, заключающаяся в том, как получить значение автоматически сгенерированного ID из INSERT. С помощью ODBC можно сделать что-то наподобие следующего (предполагается, что auto представляет собой поле AUTO_INCREMENT ):

INSERT INTO foo (auto,text) VALUES(NULL,'text');
SELECT LAST_INSERT_ID();

Или, если вы просто собираетесь вставить данный ID в другую таблицу, то можно сделать так:

INSERT INTO foo (auto,text) VALUES(NULL,'text');
INSERT INTO foo2 (id,text) VALUES(LAST_INSERT_ID(),'text');

See section 8.4.6.3 Как получить уникальный идентификатор для последней внесенной строки?.

Для некоторых приложений ODBC (по крайней мере, для Delphi и Access), чтобы найти недавно вставленную строку, можно использовать следующий запрос:

SELECT * FROM tbl_name WHERE auto IS NULL;

8.3.7 Составление отчетов о проблемах с MyODBC

Если встречаются трудности с применением MyODBC, то следует начинать с получения системного журнала менеджера ODBC (журнал, получаемый при затребовании записей в Администраторе ODBC) и журнала MyODBC.

Чтобы получить журнал MyODBC, необходимо выполнить следующие действия:

  1. Убедитесь, что вы используете `myodbcd.dll', а не `myodbc.dll'. Наиболее простой способ - получить файл `myodbcd.dll' из дистрибутива MyODBC и скопировать его поверх файла `myodbc.dll', который должен находиться в вашем каталоге `C:\windows\system32' или `C:\winnt\system32'. Однако после окончания тестирования целесообразно восстановить старый файл `myodbc.dll', поскольку он намного быстрее, чем `myodbcd.dll'.
  2. Включите опцию Trace MyODBC в окне подключения/конфигурации MyODBC. Информация будет записываться в файл `C:\myodbc.log'. Если опция трассировки не запоминается при возвращении к предыдущему окну, то это означает, что сейчас драйвер `myodbcd.dll' не используется (см. пункт выше).
  3. Запустите свое приложение и попытайтесь получить отказ в работе.

Проверьте трассировочный файл MyODBC, что бы попытаться выяснить, в чем дело. Можно также найти сделанные вами запросы в файле `myodbc.log' - поищите в нем строку >mysql_real_query.

Попробуйте также выполнить дублирование этих запросов с помощью монитора mysql или admndemo, чтобы определить, где возникает ошибка - в MyODBC или в MySQL.

Если вы обнаружите какую-либо ошибку, то присылайте, пожалуйста, только строки, имеющие отношение к ней (максимум 40 строк), по адресу myodbc@lists.mysql.com. Просьба никогда не присылать полностью весь системный журнал MyODBC или ODBC!

Если у вас нет возможности определить, что именно у вас не так, остается последняя возможность - создать архив (tar или zip), содержащий трассировочный файл MyODBC, системный журнал ODBC и файл README с описанием своей проблемы. Вы можете послать это по адресу ftp://support.mysql.com/pub/mysql/secret/. В MySQL AB только мы будем иметь доступ к присланным вами файлам. Гарантируем, что с ними мы будем обращаться очень осторожно!

Если вы можете создать программу для демонстрации данной проблемы, присылайте, пожалуйста, и ее тоже!

Если эта программа работает с некоторыми другими серверами SQL, следует сделать системный журнал ODBC, где вы делаете в точности то же самое в другом сервере SQL.

Помните, что чем больше информации вы нам предоставите, тем больше вероятность, что мы сможем решить данную проблему!

8.4 Интерфейс C для MySQL

Исходный код программного интерфейса (API) C распространяется вместе с MySQL. Он включает в себя библиотеку mysqlclient и обеспечивает возможность доступа к базе данных программам на С.

Многие клиенты исходного дистрибутива MySQL написаны на C. Они являются хорошими примерами для демонстрации использования интерфейса C. Их можно найти их в каталоге clients исходного дистрибутива MySQL.

Большинство других клиентских интерфейсов (за исключением Java) для соединения с сервером MySQL используют библиотеку mysqlclient. Это означает, что, например, можно извлечь определенную выгоду, используя те же переменные окружения, что и в других клиентских программах, поскольку на них есть ссылки из библиотеки (see section 4.8 Клиентские сценарии и утилиты MySQL, где приведен список этих переменных).

Клиент имеет максимальный размер буфера связи. Начальный размер этого буфера составляет 16 Kб и автоматически увеличивается до максимального значения 16 Mб. Поскольку размеры буфера увеличиваются только при подтверждении запроса на это, то просто увеличение максимального предела по умолчанию само по себе не обеспечит увеличения используемых ресурсов. Проверка этого размера в основном используется для ошибочных запросов и коммуникационных пакетов.

Буфер связи должен быть достаточно большим, чтобы вмещать целую SQL-команду (для потока клиент-сервер) и целую строку возвращенных данных (для потока сервер-клиент). Буфер связи для каждого из потоков динамически увеличивается до максимального значения, чтобы обработать любой запрос или строку. Например, для данных типа BLOB объемом до 16 Mб необходим предел буфера связи по меньшей мере в 16 Mб (как для сервера, так и для клиента). Максимальное значение по умолчанию для клиента составляет 16 Mб, а для сервера максимум по умолчанию равен 1Mб. Можно увеличить этот объем, изменив величину параметра max_allowed_packet при запуске сервера (see section 5.5.2 Настройка параметров сервера).

Сервер MySQL сжимает каждый буфер связи до величины net_buffer_length байтов после каждого запроса. Для клиентов размер буфера, связанного с соединением, не уменьшается, пока не будет закрыто данное соединение и при этом не будет освобождена выделенная клиенту память.

Программирование с учетом потоков описано в разделе See section 8.4.8 Как создать клиентскую программу с потоками. При создании автономного приложения, включающего и "сервер", и "клиент" в одной и той же программе (и не взаимодействующего с внешним сервером MySQL), обращайтесь к разделу See section 8.4.9 libmysqld, встраиваемая библиотека сервера MySQL.

8.4.1 Типы данных C API

MYSQL
Данная структура представляет дескриптор соединения с базой данных. Используется почти во всех функциях MySQL.
MYSQL_RES
Эта структура содержит результат запроса, возвратившего строки (SELECT, SHOW, DESCRIBE, EXPLAIN). Возвращенная из запроса информация далее в этом разделе называется результирующим набором данных.
MYSQL_ROW
Является ``типобезопасным'' представлением данных одной строки. В настоящее время этот тип реализован как массив строк с фиксированным количеством байтов (их нельзя трактовать как строки с нулевым символом в конце, если величины полей могут содержать двоичные данные, поскольку они могут содержать ноль байтов). Строки можно получить вызовом функции mysql_fetch_row().
MYSQL_FIELD
Данная структура содержит информацию об отдельном поле таблицы: имя поля, тип и его размер. Элементы данной структуры детально описаны в этом разделе ниже. Для каждого поля можно получить структуру MYSQL_FIELD, последовательно вызывая функцию mysql_fetch_field(). Величины полей не являются частью данной структуры, они содержатся в структуре MYSQL_ROW.
MYSQL_FIELD_OFFSET
``Типобезопасное'' представление позиции поля в списке полей MySQL. (используется функцией mysql_field_seek()). Позиции представляют собой номера полей внутри строки, причем нумерация начинается с нуля.
my_ulonglong
Данный тип используется для возврата количества строк, а также в функциях mysql_affected_rows(), mysql_num_rows() и mysql_insert_id(). Этот тип обеспечивает диапазон изменений величин от 0 до 1.84e19. Может не работать в некоторых системах при выводе величины типа my_ulonglong. Для вывода подобной величины следует преобразовать ее в тип unsigned long и использовать формат %lu. Пример:
printf (Количество  строк: %lu\n", (unsigned long) mysql_num_rows(result));

Структура MYSQL_FIELD содержит следующие перечисленные ниже элементы:

char * name
Имя данного поля, заданное строкой с нулевым символом в конце.
char * table
Имя таблицы, содержащей это поле, если оно невычисляемое. Для полей, получаемых в результате вычислений, величина table представляет собой пустую строку.
char * def
Значение по умолчанию этого поля, заданное строкой с нулевым символом в конце. Задается только при использовании функции mysql_list_fields().
enum enum_field_types type
Тип данного поля. Величина type может быть одной из следующих:
Тип величины | Описание типа
FIELD_TYPE_TINY | Поле TINYINT
FIELD_TYPE_SHORT | Поле SMALLINT
FIELD_TYPE_LONG | Поле INTEGER
FIELD_TYPE_INT24 | Поле MEDIUMINT
FIELD_TYPE_LONGLONG | Поле BIGINT
FIELD_TYPE_DECIMAL | Поле DECIMAL или NUMERIC
FIELD_TYPE_FLOAT | Поле FLOAT
FIELD_TYPE_DOUBLE | Поле DOUBLE или REAL
FIELD_TYPE_TIMESTAMP | Поле TIMESTAMP
FIELD_TYPE_DATE | Поле DATE
FIELD_TYPE_TIME | Поле TIME
FIELD_TYPE_DATETIME | Поле DATETIME
FIELD_TYPE_YEAR | Поле YEAR
FIELD_TYPE_STRING | Строка поля (CHAR или VARCHAR)
FIELD_TYPE_BLOB | BLOB или TEXT поле (используется max_length для определения максимальной длинны)
FIELD_TYPE_SET | Поле типа SET
FIELD_TYPE_ENUM | Поле типа ENUM
FIELD_TYPE_NULL | Поле типа NULL
FIELD_TYPE_CHAR | Не рекомендуется; лучше использовать FIELD_TYPE_TINY
Можно использовать макрос IS_NUM() для проверки, является ли тип поля числовым. В макросе IS_NUM() следует указать величину type и, если поле имеет числовой тип, будет возвращено значение TRUE:
if (IS_NUM(field->type))
   printf("Field is numeric\n");
unsigned int length
Размер данного поля в том виде, в каком он указан в определении таблицы.
unsigned int max_length
Максимальный размер данного поля в результирующем наборе данных (длина самой большой величины поля для строк в текущем результирующем наборе данных). При использовании mysql_store_result() или mysql_list_fields() данная переменная содержит максимальную длину для данного поля. При использовании mysql_use_result() значение этой переменной равно нулю.
unsigned int flags
Различные двоичные флаги для данного поля. Величина flags может иметь ноль или больше двоичных значений следующего набора флагов:
Значение флага | описание флага
NOT_NULL_FLAG | Поле не может содержать значение NULL
PRI_KEY_FLAG | Поле является частью первичного ключа
UNIQUE_KEY_FLAG | Поле является частью уникального ключа
MULTIPLE_KEY_FLAG | Поле является частью не уникального ключа
UNSIGNED_FLAG | Поле имеет атрибут UNSIGNED
ZEROFILL_FLAG | Поле имеет атрибут ZEROFILL
BINARY_FLAG | Поле имеет атрибут BINARY
AUTO_INCREMENT_FLAG | Поле имеет атрибут AUTO_INCREMENT
ENUM_FLAG | Поле имеет тип ENUM (не рекомендуется)
SET_FLAG | Поле имеет тип SET (не рекомендуется)
BLOB_FLAG | Поле имеет тип BLOB или TEXT (не рекомендуется)
TIMESTAMP_FLAG | Поле имеет тип TIMESTAMP (не рекомендуется)
Использование флагов BLOB_FLAG, ENUM_FLAG, SET_FLAG и TIMESTAMP_FLAG не рекомендуется, поскольку они указывают скорее тип поля, чем атрибут этого типа. Вместо этого более предпочтительно определять тип поля описанным выше способом field->type в отношении полей FIELD_TYPE_BLOB, FIELD_TYPE_ENUM, FIELD_TYPE_SET или FIELD_TYPE_TIMESTAMP. Следующий пример иллюстрирует типичное использование величины flags:
if (field->flags & NOT_NULL_FLAG)
   printf("Field can't be null\n");
Можно использовать следующие возможности макросов для определения булевого значения величины flags:
Статус флага | Описание
IS_NOT_NULL(flags) | Возвращает TRUE, если данное поле определено как NOT NULL
IS_PRI_KEY(flags) | Возвращает TRUE, если данное поле является первичным ключом
IS_BLOB(flags) | Возвращает TRUE, если данное поле имеет тип BLOB или TEXT (не рекомендуется; более предпочтительно field->type)
unsigned int decimals
Возвращает число десятичных знаков для числовых полей.

8.4.2 Обзор функций интерфейса C

В приведенной ниже таблице перечислены доступные в интерфейсе C функции. Более детально они описаны в следующем разделе (see section 8.4.3 Описание функций интерфейса C).
Функция | Описание
mysql_affected_rows() | Возвращает количество строк, измененных/удаленных/вставленных последним запросом UPDATE, DELETE или INSERT.
mysql_change_user() | Переключает пользователя и базу данных для открытого соединения.
mysql_character_set_name() | Возвращает название кодировки, установленной для данного соединения.
mysql_close() | Закрывает соединение с сервером.
mysql_connect() | Создает соединение с сервером баз данных MySQL. Данная функция не рекомендуется; вместо нее следует использовать функцию mysql_real_connect().
mysql_create_db() | Создает базу данных. Данная функция не рекомендуется; вместо нее следует использовать команду SQL CREATE DATABASE.
mysql_data_seek() | Ищет произвольную строку в результирующем наборе запроса.
mysql_debug() | Выполняет отладочные операции DBUG_PUSH с заданной строкой.
mysql_drop_db() | Удаляет базу данных. Эта функция не рекомендуется; вместо нее следует использовать команду SQL DROP DATABASE.
mysql_dump_debug_info() | Заставляет сервер записывать отладочную информацию в журнал.
mysql_eof() | Определяет, была ли данная строка последней из прочитанных в результирующем наборе данных. Эта функция не рекомендуется; mysql_errno() или mysql_error() могут быть использованы вместо нее.
mysql_errno() | Возвращает номер ошибки для последней запущенной функции MySQL.
mysql_error() | Возвращает сообщение об ошибке для последней запущенной функции MySQL.
mysql_escape_string() | Экранирует специальные символы в строке, чтобы ее было возможно использовать в команде SQL.
mysql_fetch_field() | Возвращает тип следующего поля таблицы.
mysql_fetch_field_direct() | Возвращает тип поля таблицы по заданному номеру поля.
mysql_fetch_fields() | Возвращает массив структур, содержащих информацию обо всех полях.
mysql_fetch_lengths() | Возвращает массив длин всех столбцов в текущей строке.
mysql_fetch_row() | Извлекает следующую строку из результирующего набора.
mysql_field_seek() | Устанавливает курсор столбцов на заданный столбец.
mysql_field_count() | Возвращает количество столбцов в результате для последнего запроса.
mysql_field_tell() | Возвращает значение положения курсора поля для последнего вызова mysql_fetch_field().
mysql_free_result() | Освобождает память, использованную для результирующего набора.
mysql_get_client_info() | Возвращает информацию о версии клиента.
mysql_get_host_info() | Возвращает строку, описывающую параметры текущего соединения.
mysql_get_server_version() | Возвращает номер версии сервера как целое число (новое с 4.1)
mysql_get_proto_info() | Возвращает версию протокола, используемого для данного соединения.
mysql_get_server_info() | Возвращает номер версии сервера баз данных.
mysql_info() | Возвращает информацию о последнем выполненном запросе.
mysql_init() | Выделяет или инициализирует какую-либо структуру MYSQL.
mysql_insert_id() | Возвращает идентификатор, сгенерированный для столбца AUTO_INCREMENT предыдущим запросом.
mysql_kill() | Уничтожает заданный поток.
mysql_list_dbs() | Возвращает имена баз данных, совпадающие с простым регулярным выражением.
mysql_list_fields() | Возвращает имена полей, совпадающих с простым регулярным выражением.
mysql_list_processes() | Возвращает список текущих потоков на сервере.
mysql_list_tables() | Возвращает имена таблиц, совпадающих с простым регулярным выражением.
mysql_num_fields() | Возвращает количество столбцов в результирующем наборе.
mysql_num_rows() | Возвращает количество строк в результирующем наборе.
mysql_options() | Устанавливает параметры соединения для mysql_connect().
mysql_ping() | Проверяет, работает ли данное соединение с сервером, и восстанавливает соединение при необходимости.
mysql_query() | Выполняет SQL-запрос, заданный в виде строки с нулевым символом в конце.
mysql_real_connect() | Создает соединение с сервером баз данных MySQL.
mysql_real_escape_string() | Экранирует специальные символы в строке, чтобы обеспечить возможность использования ее в команде SQL, с учетом установленной для данного соединения кодировки.
mysql_real_query() | Выполняет SQL-запрос, заданный в виде фиксированной строки.
mysql_reload() | Предписывает серверу перегрузить таблицы привилегий.
mysql_row_seek() Устанавливает курсор на заданную строку в результирующем наборе, используя величину, возвращенную из mysql_row_tell().
mysql_row_tell() | Возвращает положение курсора строки.
mysql_select_db() | Выбирает базу данных.
mysql_shutdown() | Останавливает сервер баз данных.
mysql_stat() | Возвращает информацию о текущем статусе сервера баз данных в виде строки.
mysql_store_result() | Извлекает полный результирующий набор для данного клиента.
mysql_thread_id() | Возвращает идентификатор текущего потока.
mysql_thread_safe() | Возвращает 1, если клиенты скомпилированы как поддерживающие потоки.
mysql_use_result() | Инициализирует построчное извлечение результирующего набора.

При подсоединения к серверу необходимо вызвать функцию mysql_init() для инициализации дескриптора соединения, затем с этим дескриптором вызвать функцию mysql_real_connect() (которая содержит такую информацию, как имя данного хоста, имя пользователя и пароль). После соединения функция mysql_real_connect() устанавливает флаг reconnect (часть данной структуры MYSQL) в значение 1. Этот флаг указывает, что в случае, если запрос не может быть выполнен из-за потери соединения, следует попытаться восстановить соединение с сервером до окончательного отказа от него. Для закрытия соединения вызывается функция mysql_close().

При активном соединении клиент может посылать SQL-запросы на сервер, используя функции mysql_query() или mysql_real_query(). Разница между этими двумя функциями состоит в том, что mysql_query() работает с запросом, представленным в виде строки с нулевыми окончаниями, в то время, как mysql_real_query() работает со строками фиксированной длины. Если данная строка содержит двоичные данные (которые могут состоять из нуля байтов), то необходимо использовать mysql_real_query().

Для каждого запроса без выборки данных (т.е. не вида SELECT, а, например, INSERT, UPDATE, DELETE) можно узнать количество измененных (затронутых) строк путем вызова функции mysql_affected_rows().

Для запросов SELECT можно извлечь выбранные строки как результирующий набор. (Следует учитывать, что некоторые команды сходны с SELECT в том смысле, что они тоже возвращают строки. Это команды SHOW, DESCRIBE и EXPLAIN. Они должны трактоваться тем же образом, что и команды SELECT.)

Для клиента существует два способа обработки результирующих наборов данных. Первый состоит в извлечении сразу всего результирующего набора целиком вызовом функции mysql_store_result(). Эта функция забирает с сервера все строки, возвращенные запросом, и хранит их в данном клиенте. Второй способ заключается в инициализации для клиента построчного извлечения результирующего набора путем вызова функции mysql_use_result(). Эта функция инициализирует указанное извлечение, но фактически не получает с сервера ни одной строки.

В обоих случаях доступ к строкам происходит с помощью функции mysql_fetch_row(). Совместно с mysql_store_result() mysql_fetch_row() осуществляет доступ к строкам, уже извлеченным с сервера. Совместно с mysql_use_result() mysql_fetch_row() реально получает данную строку с сервера. Информацию о размере данных в каждой строке можно получить вызовом функции mysql_fetch_lengths().

После выполнения операций с результирующим набором необходимо вызвать функцию mysql_free_result(), чтобы освободить использованную для этого память.

Два описанных выше механизма извлечения данных являются взаимодополняющими. Клиентские программы должны выбирать наиболее подходящий для их требований способ. На практике клиенты обычно стремятся использовать функцию mysql_store_result().

Преимущество функции mysql_store_result() состоит в том, что, поскольку все строки выбраны и находятся у клиента, то возможен не только последовательный доступ к строкам. В результирующем наборе данных можно перемещаться назад и вперед в, используя функции mysql_data_seek() или mysql_row_seek(), чтобы изменить положение текущей строки внутри результирующего набора. Можно также узнать количество находящихся в нем строк, вызвав функцию mysql_num_rows(). С другой стороны, для mysql_store_result() требования к памяти могут быть очень высокими для обширных результирующих наборов, что может привести к нехватке памяти.

Преимущество функции mysql_use_result() заключается в том, что клиент требует меньше памяти для результирующего набора, поскольку он сохраняет только одну строку единовременно (и, так как это меньше перегружает память, то функция mysql_use_result() может быть быстрее). Недостатками являются: необходимость обрабатывать каждую строку быстро, чтобы избежать связывания сервера, невозможность произвольного доступа к строкам внутри результирующего набора (возможен только последовательный доступ к строкам), невозможность узнать количество строк в результирующем наборе до его полного извлечения. Более того, необходимо извлекать все строки, даже если в середине извлечения станет ясно, что искомая информация найдена.

Благодаря интерфейсу клиенты получают возможность соответствующим образом реагировать на запросы (извлекать строки только при необходимости) без уточнения, являлся или нет данный запрос выборкой. Это можно делать, вызывая функцию mysql_store_result() после каждого вызова mysql_query() (или mysql_real_query()). Если вызов результирующего набора был успешным, то данный запрос принадлежал к виду SELECT и можно производить чтение строк. Если вызов результирующего набора не удался, можно вызвать функцию mysql_field_count() для определения, можно ли было действительно ожидать результат. Если mysql_field_count() возвращает нуль, то данный запрос не возвратил никаких данных (это указывает, что запрос был вида INSERT, UPDATE, DELETE и т.д.), и не следовало ожидать возвращенных строк. Если функция mysql_field_count() является ненулевой, данный запрос должен был возвратить результат, но не сделал этого. Это указывает, что данный запрос был типа SELECT, но его выполнение оказалось неуспешным (см. пример в описании функции mysql_field_count()).

Как mysql_store_result() так и mysql_use_result() позволяют получить информацию о полях, составляющих результирующий набор (количество полей, их имена и типы и т.д.). Можно получить последовательный доступ к информации о полях внутри строки путем повторного вызова функции mysql_fetch_field() или к номеру поля внутри строки с помощью функции mysql_fetch_field_direct(). Текущее положение курсора поля может быть изменено вызовом функции mysql_field_seek(). Установка курсора производится последующим вызовом функции mysql_fetch_field(). Можно также получить информацию для всех полей сразу с помощью функции mysql_fetch_fields().

Для обнаружения ошибок и сообщения о них MySQL обеспечивает доступ к информации об ошибках посредством функций mysql_errno() и mysql_error(). Они возвращают код ошибки или сообщение об ошибке для последней запущенной функции (которая может быть успешной или не выполниться), позволяя определить место возникновения и характер ошибки.

8.4.3 Описание функций интерфейса C

В приведенных здесь описаниях параметр или возвращаемая величина, обозначенная как NULL, означает NULL в терминах языка программирования C, а не величину NULL в MySQL.

Функции, возвращающие величину, обычно возвращают указатель или целое число. Если не указано иначе, то функции, возвращающие указатель, возвращают величину не-NULL при успешном выполнении или величину NULL, указывающую на ошибку, а функции, возвращающие целое число, возвращают нуль при успешном выполнении или ненулевую величину при возникновении ошибки. Следует учитывать, что термин ``ненулевая величина'' означает именно это. Если в описании функции не сказано иначе, то не следует пробовать интерпретировать эту величину иначе, чем нуль:

if (result)		 /* правильно */
   ... error ...
if (result < 0)		 /* неправильно */
   ... error ...
if (result == -1)	 /* неправильно */
   ... error ...

Если функция возвращает ошибку, то возможные типы ошибок представлены в ее описании в подраздел Ошибки. Вызвав функцию mysql_errno(), можно узнать, какие именно ошибки произошли. Строковое представление ошибки можно получить, вызывая функцию mysql_error().

8.4.3.1 mysql_affected_rows()

my_ulonglong mysql_affected_rows(MYSQL *mysql)

Описание

Возвращает количество строк, измененных последней командой UPDATE, удаленных последней командой DELETE или вставленных последней командой INSERT. Может быть вызвана немедленно после mysql_query() для команд UPDATE, DELETE или INSERT. Для команд SELECT mysql_affected_rows() работает аналогично mysql_num_rows().

Возвращаемые значения

Целое число больше нуля равно количеству строк, подвергшихся воздействию или извлеченных. Нуль указывает, что ни одна из записей не была обновлена для команды UPDATE, ни одна из строк не совпала с утверждением WHERE в данном запросе или что ни один запрос еще не был выполнен. Значение -1 показывает, что данный запрос возвратил ошибку или что для запроса SELECT функция mysql_affected_rows() была вызвана прежде вызова функции mysql_store_result().

Ошибки

Нет.

Пример

mysql_query(&mysql,"UPDATE products SET cost=cost*1.25 WHERE group=10");
printf("%ld products updated",(long) mysql_affected_rows(&mysql));

Если указывается флаг CLIENT_FOUND_ROWS при подключении к mysqld, то mysql_affected_rows() возвратит количество строк, соответствующих выражению WHERE для команд UPDATE.

Следует отметить, что при использовании команды REPLACE функция mysql_affected_rows() возвратит значение 2, если новая строка заменила старую. Это происходит по той причине, что в данном случае одна строка была внесена после того как дублирующая была удалена.

8.4.3.2 mysql_change_user()

my_bool mysql_change_user(MYSQL *mysql, const char *user, const char *password, const char *db)

Описание

Изменяет пользователя и устанавливает базу данных, указанную в аргументе db в качестве текущей по базы данных для соединения, заданного в аргументе mysql. В последующих запросах эта база данных является текущей по умолчанию для табличных ссылок, которые не содержат явного указателя базы данных.

Эта функция была введена в версию MySQL 3.23.3.

Функция mysql_change_user() не выполняется, если подключенный пользователь не может быть аутентифицирован или если он не имеет разрешения на использование этой базы данных. В таком случае данный пользователь и база данных не изменяются.

Параметр db может быть установлен в NULL, если база данных по умолчанию не нужна.

Начиная с версии 4.0.6 будет всегда производить откат любой начатой транзакции, закрывать все временные таблицы, снимать блокировку со всех заблокированных таблиц и переустанавливать состояние, если произошло новое соединение. Это будет происходить даже в том случае, если имя пользователя не изменится.

Возвращаемые значения

Нуль при успешном выполнении. Ненулевая величина, если возникла ошибка.

Ошибки

Те же, что и для mysql_real_connect().

CR_COMMANDS_OUT_OF_SYNC
Команды были выполнены в ненадлежащем порядке.
CR_SERVER_GONE_ERROR
Сервер MySQL неожиданно завершил работу.
CR_SERVER_LOST
Соединение с сервером прервалось в процессе данного запроса.
CR_UNKNOWN_ERROR
Произошла неизвестная ошибка.
ER_UNKNOWN_COM_ERROR
Сервер MySQL не обеспечивает выполнение этой команды (возможно, старая версия сервера)
ER_ACCESS_DENIED_ERROR
Пользователь или пароль ошибочны.
ER_BAD_DB_ERROR
Данная база данных не существует.
ER_DBACCESS_DENIED_ERROR
Данный пользователь не имеет прав доступа к этой базе данных.
ER_WRONG_DB_NAME
Имя базы данных было слишком длинным.

Пример

if (mysql_change_user(&mysql, "user", "password", "new_database"))
{
  fprintf(stderr, "Failed to change user. Error: %s\n",
  mysql_error(&mysql));
}

8.4.3.3 mysql_character_set_name()

const char *mysql_character_set_name(MYSQL *mysql)

Описание

Возвращает установленную кодировку для текущего подключения.

Возвращаемые значения

Кодировка, установленная по умолчанию.

Ошибки

Нет.

8.4.3.4 mysql_close()

void mysql_close(MYSQL *mysql)

Описание

Закрывает ранее открытое соединение. Функция mysql_close() также освобождает дескриптор данного соединения, указанный в mysql, если данный дескриптор был выделен автоматически функциями mysql_init() или mysql_connect().

Возвращаемые значения

Нет.

Ошибки

Нет.

8.4.3.5 mysql_connect()

MYSQL *mysql_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd)

Описание

Данная функция не рекомендуется. Вместо нее предпочтительно использовать функцию mysql_real_connect().

mysql_connect() пытается установить соединение с сервером баз данных MySQL , работающим на хосте host. До успешного завершения функции mysql_connect() нельзя выполнять никакие другие функции интерфейса, за исключением mysql_get_client_info().

Значения параметров являются теми же самыми, что и для соответствующих параметров функции mysql_real_connect(), с той разницей, что параметр соединения может быть NULL. В этом случае интерфейс C автоматически выделяет память для структуры соединения и освобождает ее при вызове функции mysql_close(). Недостаток данного подхода состоит в том, что при падении соединения нельзя получить сообщение об ошибке (чтобы получить информацию об ошибке из функций mysql_errno() или mysql_error(), необходимо обеспечить адекватный указатель структуры MYSQL).

Возвращаемые значения

Те же, что и для mysql_real_connect().

Ошибки

Те же, что и для mysql_real_connect().

8.4.3.6 mysql_create_db()

int mysql_create_db(MYSQL *mysql, const char *db)

Описание

Создает базу данных, указанную в параметре db.

Данная функция не рекомендуется. Вместо нее предпочтительно использовать функцию mysql_query() для выполнения SQL-команды CREATE DATABASE.

Возвращаемые значения

Нуль, если база данных создана успешно. Ненулевая величина, если произошла ошибка.

Ошибки

CR_COMMANDS_OUT_OF_SYNC
Команды были выполнены в ненадлежащем порядке.
CR_SERVER_GONE_ERROR
Сервер MySQL неожиданно завершил работу.
CR_SERVER_LOST
Соединение с сервером прервалось в процессе данного запроса.
CR_UNKNOWN_ERROR
Произошла неизвестная ошибка.

Пример

if(mysql_create_db(&mysql, "my_database"))
{
  fprintf(stderr, "Failed to create new database. Error: %s\n", mysql_error(&mysql));
}

8.4.3.7 mysql_data_seek()

void mysql_data_seek(MYSQL_RES *result, my_ulonglong offset)

Описание

Ищет произвольную строку в результирующем наборе запроса. Для этого требуется, чтобы структура результирующего набора содержала целиком весь результат данного запроса, поэтому mysql_data_seek() может использоваться только в сочетании с mysql_store_result(), но не с mysql_use_result().

Адрес смещения должен быть величиной в диапазоне от 0 до mysql_num_rows(result)-1.

Возвращаемые значения

Нет.

Ошибки

Нет.

8.4.3.8 mysql_debug()

void mysql_debug(const char *debug)

Описание

Выполняет отладочные операции DBUG_PUSH с заданной строкой. Функция mysql_debug() использует отладочную библиотеку Fred Fish debug. Для использования этой функции необходимо компилировать библиотеку клиента с поддержкой отладки (см. разделы section D.1 Отладка сервера MySQL и see section D.2 Отладка клиента MySQL).

Возвращаемые значения

Нет.

Ошибки

Нет.

Пример

Представленный здесь вызов функции заставляет библиотеку клиента генерировать трассировочный файл в каталоге `/tmp/client.trace' на клиентской машине:

mysql_debug("d:t:O,/tmp/client.trace");

8.4.3.9 mysql_drop_db()

int mysql_drop_db(MYSQL *mysql, const char *db)

Описание

Уничтожает базу данных, указанную в параметре db.

Данная функция не рекомендуется. Вместо нее предпочтительно использовать функцию mysql_query() для выполнения SQL-команды DROP DATABASE.

Возвращаемые значения

Нуль, если база данных удалена успешно. Ненулевая величина, если произошла ошибка.

Ошибки

CR_COMMANDS_OUT_OF_SYNC
Команды были выполнены в ненадлежащем порядке.
CR_SERVER_GONE_ERROR
Сервер MySQL неожиданно завершил работу.
CR_SERVER_LOST
Соединение с сервером прервалось в процессе данного запроса.
CR_UNKNOWN_ERROR
Произошла неизвестная ошибка.

Пример

if(mysql_drop_db(&mysql, "my_database"))
fprintf(stderr, "Failed to drop the database: Error: %s\n", mysql_error(&mysql));

8.4.3.10 mysql_dump_debug_info()

int mysql_dump_debug_info(MYSQL *mysql)

Описание

Предписывает серверу производить запись отладочной информации в журнал. Для работы функции необходимо, чтобы подключенный пользователь имел привилегию SUPER.

Возвращаемые значения

Нуль, если команда выполнена успешно. Ненулевая величина, если произошла ошибка.

Ошибки

CR_COMMANDS_OUT_OF_SYNC
Команды были выполнены в ненадлежащем порядке.
CR_SERVER_GONE_ERROR
Сервер MySQL неожиданно завершил работу.
CR_SERVER_LOST
Соединение с сервером прервалось в процессе данного запроса.
CR_UNKNOWN_ERROR
Произошла неизвестная ошибка.

8.4.3.11 mysql_eof()

my_bool mysql_eof(MYSQL_RES *result)

Описание

Данная функция не рекомендуется. Вместо нее можно использовать функции mysql_errno() или mysql_error().

Функция mysql_eof() определяет, была ли данная строка последней из прочитанных в результирующем наборе данных.

Если результирующий набор получен путем успешного вызова функции mysql_store_result(), то данный клиент получает полный набор данных за одну операцию. В этом случае возврат NULL из mysql_fetch_row() всегда означает, что достигнут конец результирующего набора и нет необходимости в вызове функции mysql_eof(). При использовании совместно с mysql_store_result() функция mysql_eof() всегда будет возвращать TRUE.

С другой стороны, при использовании mysql_use_result() для инициализации извлечения результирующего набора, клиент получает строки набора с сервера поочередно при повторных вызовах функции mysql_fetch_row(). Поскольку в этом процессе может возникнуть ошибка в соединении, NULL, полученный от mysql_fetch_row(), не всегда означает что конец результата был достигнут корректно. В этом случае вы можете использовать mysql_eof(), чтобы выяснить, что же случилось. mysql_eof() вернет ненулевую величину, если конец результирующего набора был достигнут, и нуль, если произошла ошибка.

Исторически сложилось так, что mysql_eof() по своим задачам сходна со стандартными функциями обработки ошибок MySQL mysql_errno() и mysql_error(). Поскольку эти функции дают одну и ту же информацию, их использование более предпочтительно чем mysql_eof(), которая сейчас выведена из употребления (в действительности они предоставляют еще больше информации, т.к. mysql_eof() возвращает только булево значение, в то время как функции обработки ошибок сообщают причину, по которой ошибка произошла).

Возвращаемые значения

Нуль, если ошибок не произошло. Ненулевая величина, если конец результирующего набора данных достигнут.

Ошибки

Никаких.

Пример

Следующий пример иллюстрирует применение mysql_eof():

mysql_query(&mysql,"SELECT * FROM some_table");
result = mysql_use_result(&mysql);
while((row = mysql_fetch_row(result)))
{
    // делаем что-то с данными
}
if(!mysql_eof(result)) // mysql_fetch_row() сбойнул из-за ошибки
{
    fprintf(stderr, "Error: %s\n", mysql_error(&mysql));
}

Того же эффекта вы можете достичь с помощью стандартных функций ошибок MySQL:

mysql_query(&mysql,"SELECT * FROM some_table");
result = mysql_use_result(&mysql);
while((row = mysql_fetch_row(result)))
{
    // что-то делаем с данными
}
if(mysql_errno(&mysql)) // mysql_fetch_row() сбойнул из-за ошибки
{
fprintf(stderr, "Error: %s\n", mysql_error(&mysql));
}

8.4.3.12 mysql_errno()

unsigned int mysql_errno(MYSQL *mysql)

Описание

Для соединения, указанного в mysql, функция mysql_errno() возвращает код ошибки для последней запущенной функции интерфейса, которая может быть успешной или не выполниться. Возвращение нулевой величины означает, что ошибка не возникала. Номера сообщений об ошибке для клиентов перечислены в заголовочном файле MySQL `errmsg.h'. Номера серверных сообщений об ошибке даны в файле `mysqld_error.h'. В исходном дистрибутиве MySQL можно найти полный список сообщений об ошибках и номеров ошибок в файле `Docs/mysqld_error.txt'.

Возвращаемые значения

Значение кода ошибки. Нуль, если ошибка не возникала.

Ошибки

Нет.

8.4.3.13 mysql_error()

char *mysql_error(MYSQL *mysql)

Описание

Для соединения, указанного в mysql, функция mysql_error() возвращает сообщение об ошибке для последней вызванной функции интерфейса, которая может быть успешной или не выполниться. Если ошибка не возникала, то возвращается пустая строка (""). Это означает, что следующие две проверки эквивалентны:

if(mysql_errno(&mysql))
{
    // ошибка  возникла
}
if(mysql_error(&mysql)[0] != '\0')
{
    // ошибка возникла
}

Язык клиентских сообщений об ошибке может быть изменен путем перекомпилирования клиентской библиотеки MySQL. В настоящее время можно выбирать для вывода сообщений об ошибке один из нескольких различных естественных языков (see section 4.6.2 Сообщения об ошибках на языках, отличных от английского).

Возвращаемые значения

Символьная строка с описанием ошибки. Пустая строка, если ошибка не возникала.

Ошибки

Нет.

8.4.3.14 mysql_escape_string()

Вместо этой функции следует использовать функцию mysql_real_escape_string()!

Данная функция идентична функции mysql_real_escape_string(), за исключением того, что mysql_real_escape_string() принимает дескриптор соединения в качестве своего первого аргумента и экранирует строку в соответствии с текущей кодировкой. Функция mysql_escape_string() не требует параметров соединения в качестве аргумента и не учитывает установки текущей кодировки.

8.4.3.15 mysql_fetch_field()

MYSQL_FIELD *mysql_fetch_field(MYSQL_RES *result)

Описание

Возвращает определение одного столбца из результирующего набора в виде структуры MYSQL_FIELD. Для извлечения информации обо всех столбцах в результирующем наборе следует вызывать эту функцию повторно. Если полей больше не остается, функция mysql_fetch_field() возвращает NULL.

Каждый раз при выполнении нового запроса SELECT функция mysql_fetch_field() сбрасывается в исходное состояние, чтобы возвращать информацию о первом поле. На поле, возвращенное функцией mysql_fetch_field(), также можно воздействовать, вызвав функцию mysql_field_seek().

Если вызвана функция mysql_query() для выполнения команды SELECT на таблице, но не вызвана функция mysql_store_result(), то MySQL возвращает установленную по умолчанию длину данных типа BLOB (8 Kб) при вызове функции mysql_fetch_field() для выяснения длины поля BLOB (Размер 8 Kб выбран потому, что MySQL в этом случае не знает максимальной длины для BLOB. Когда-нибудь эта конфигурация будет сделана перестраиваемой.) Поскольку результирующий набор извлечен, то выражение field->max_length содержит длину наибольшей величины для данного столбца в указанном запросе.

Возвращаемые значения

Структура MYSQL_FIELD для текущего столбца. NULL, если полей больше не остается.

Ошибки

Нет.

Пример

MYSQL_FIELD *field;
while((field = mysql_fetch_field(result)))
{
    printf("field name %s\n", field->name);
}

8.4.3.16 mysql_fetch_field_direct()

MYSQL_FIELD *mysql_fetch_field_direct(MYSQL_RES *result, unsigned int fieldnr)

Описание

По заданному номеру поля fieldnr для столбца внутри результирующего набора возвращает определение данного поля столбца как структуру MYSQL_FIELD. Эту функцию можно использовать для извлечения определения для произвольного столбца. Величина fieldnr должна находиться в диапазоне от 0 до mysql_num_fields(result)-1.

Возвращаемые значения

Структура MYSQL_FIELD для указанного столбца.

Ошибки

Нет.

Пример

unsigned int num_fields;
unsigned int i;
MYSQL_FIELD *field;
num_fields = mysql_num_fields(result);
for(i = 0; i < num_fields; i++)
{
    field = mysql_fetch_field_direct(result, i);
    printf("Field %u is %s\n", i, field->name);
}

8.4.3.17 mysql_fetch_fields()

MYSQL_FIELD *mysql_fetch_fields(MYSQL_RES *result)

Описание

Возвращает массив всех структур MYSQL_FIELD для результирующего набора данных. Каждая структура предоставляет определение данного поля в одном столбце результирующего набора.

Возвращаемые значения

Массив структур MYSQL_FIELD для всех столбцов результирующего набора.

Ошибки

Нет.

Пример

unsigned int num_fields;
unsigned int i;
MYSQL_FIELD *fields;

num_fields = mysql_num_fields(result);
fields = mysql_fetch_fields(result);
for(i = 0; i < num_fields; i++)
{
    printf("Field %u is %s\n", i, fields[i].name);
}

8.4.3.18 mysql_fetch_lengths()

unsigned long *mysql_fetch_lengths(MYSQL_RES *result)

Описание

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

Искомая длина для пустых столбцов и для столбцов, содержащих величины NULL, равна нулю. Чтобы увидеть, как следует различать эти два случая, см. описание для функции mysql_fetch_row().

Возвращаемые значения

Массив беззнаковых целых чисел, представляющий собой размер каждого столбца (не включая конечные нулевые символы). NULL если произошла ошибка.

Ошибки

Функция mysql_fetch_lengths() действительна только для данной текущей строки в результирующем наборе данных. Она возвращает NULL, если ее вызов происходит до вызова функции mysql_fetch_row() или после извлечения всех строк в результате.

Пример

MYSQL_ROW row;
unsigned long *lengths;
unsigned int num_fields;
unsigned int i;

row = mysql_fetch_row(result);
if (row)
{
    num_fields = mysql_num_fields(result);
    lengths = mysql_fetch_lengths(result);
    for(i = 0; i < num_fields; i++)
    {
        printf("Column %u is %lu bytes in length.\n", i, lengths[i]);
    }
}

8.4.3.19 mysql_fetch_row()

MYSQL_ROW mysql_fetch_row(MYSQL_RES *result)

Описание

Извлекает следующую строку в результирующем наборе данных. При использовании после функции mysql_store_result() функция mysql_fetch_row() возвращает NULL, если больше не осталось строк для извлечения. При использовании после функции mysql_use_result() функция mysql_fetch_row() возвращает NULL, если больше не осталось строк для извлечения или если произошла ошибка.

Количество величин в данной строке задается в mysql_num_fields(result). Если параметр row содержит возвращенные значения из вызова функции mysql_fetch_row(), то указатели на эти величины имеют значения от row[0] до row[mysql_num_fields(result)-1]. Величины NULL в данной строке отмечаются указателями NULL.

Размеры полей в данной строке можно получить, вызывая функцию mysql_fetch_lengths(). Пустые поля и поля, содержащие NULL, в обоих случаях имеют длину 0; их можно различить, проверив указатель для данной величины поля. Если указатель равен NULL, то данное поле содержит NULL; в противном случае, данное поле является пустым.

Возвращаемые значения

Структура MYSQL_ROW для следующей строки. NULL, если нет больше строк для извлечения или произошла ошибка.

Ошибки

CR_SERVER_LOST
Соединение с сервером прервалось в процессе данного запроса.
CR_UNKNOWN_ERROR
Произошла неизвестная ошибка.

Пример

MYSQL_ROW row;
unsigned int num_fields;
unsigned int i;

num_fields = mysql_num_fields(result);
while ((row = mysql_fetch_row(result)))
{
    unsigned long *lengths;
    lengths = mysql_fetch_lengths(result);
    for(i = 0; i < num_fields; i++)
    {
        printf("[%.*s] ", (int) lengths[i], row[i] ? row[i] : "NULL");
    }
    printf("\n");
}

8.4.3.20 mysql_field_count()

unsigned int mysql_field_count(MYSQL *mysql)

При использовании более ранней, чем 3.22.24, версии MySQL необходимо вместо этого выражения использовать следующее: unsigned int mysql_num_fields(MYSQL *mysql).

Описание

Возвращает количество столбцов для последнего запроса в данном соединении.

Обычно эту функцию используют в случае, когда функция mysql_store_result() возвращает NULL (и, следовательно, нет ни одного указателя для результирующего набора). В этом случае можно вызвать функцию mysql_field_count() для определения, может ли функция mysql_store_result() выдать непустой результат. Это дает возможность данной клиентской программе выполнить соответствующее действие без уточнения, был ли данный запрос командой вида SELECT (или похожей на SELECT). Приведенный ниже пример иллюстрирует, как это можно сделать.

See section 8.4.6.1 Почему после успешных возвратов функции mysql_query() функция mysql_store_result() иногда возвращает NULL?.

Возвращаемые значения

Беззнаковое целое число, представляющее количество полей в результирующем наборе.

Ошибки

Нет.

Пример

MYSQL_RES *result;
unsigned int num_fields;
unsigned int num_rows;

if (mysql_query(&mysql,query_string))
{
    // ошибка
}
else // запрос выполнен, обработка возвращенных им данных
{
    result = mysql_store_result(&mysql);
    if (result) // содержит строки
    {
        num_fields = mysql_num_fields(result);
        // извлечение строк, затем вызов mysql_free_result(result)
    }
    else // mysql_store_result() не вернула ничего; может ли что-либо вернуть?
    {
        if(mysql_field_count(&mysql) == 0)
        {
            // запрос не возвращает данные
            // (запрос не был вида SELECT)
            num_rows = mysql_affected_rows(&mysql);
        }
        else // mysql_store_result() должна была вернуть данные
        {
            fprintf(stderr, "Error: %s\n", mysql_error(&mysql));
        }
    }
}

Альтернатива состоит в замене вызова функции mysql_field_count(&mysql) вызовом функции mysql_errno(&mysql). В этом случае можно проверить, была ли данная команда вида SELECT, непосредственно по ошибке от mysql_store_result(), а не делать логический вывод по величине функции mysql_field_count().

8.4.3.21 mysql_field_seek()

MYSQL_FIELD_OFFSET mysql_field_seek(MYSQL_RES *result, MYSQL_FIELD_OFFSET offset)

Описание

Устанавливает курсор поля в заданную позицию. Дальнейший вызов функции mysql_fetch_field() будет извлекать определение данного поля в столбце, ассоциированном с данной позицией курсора.

Для поиска начала строки необходимо установить величину offset в нуль.

Возвращаемые значения

Предыдущая величина курсора поля.

Ошибки

Нет.

8.4.3.22 mysql_field_tell()

MYSQL_FIELD_OFFSET mysql_field_tell(MYSQL_RES *result)

Описание

Возвращает позицию курсора поля, использованную для последнего вызова функции mysql_fetch_field(). Эта величина может использоваться как аргумент в функции mysql_field_seek().

Возвращаемые значения

Текущая позиция курсора поля.

Ошибки

Нет.

8.4.3.23 mysql_free_result()

void mysql_free_result(MYSQL_RES *result)

Описание

Освобождает память, выделенную для результирующего набора данных функциями mysql_store_result(), mysql_use_result(), mysql_list_dbs() и т.д. После выполнения операций с результирующим набором необходимо освободить используемую под него память вызовом функции mysql_free_result().

Возвращаемые значения

Нет.

Ошибки

Нет.

8.4.3.24 mysql_get_client_info()

char *mysql_get_client_info(void)

Описание

Возвращает строку, представляющую версию библиотеки данного клиента.

Возвращаемые значения

Символьная строка, которая представляет версию библиотеки данного клиента MySQL.

Ошибки

Нет.

8.4.3.25 mysql_get_server_version()

unsigned long mysql_get_server_version(MYSQL *mysql)

Описание

Возвращает номер версии сервера как целое число (новое с 4.1)

Возвращаемые значения

Число, представляющее версию сервера MySQL, в следующем формате:

main_version*10000 + minor_version *100 + sub_version

Например, 4.1.0 будет возвращена как 40100.

Это полезно для быстрого определения версии сервера в клиентской программе для того, чтобы узнать, поддерживаются ли некоторые возможности.

Ошибки

Нет.

8.4.3.26 mysql_get_host_info()

char *mysql_get_host_info(MYSQL *mysql)

Описание

Возвращает строку, описывающую тип используемого соединения, включая имя серверного хоста.

Возвращаемые значения

Символьная строка, представляющая имя серверного хоста и тип данного соединения.

Ошибки

Нет.

8.4.3.27 mysql_get_proto_info()

unsigned int mysql_get_proto_info(MYSQL *mysql)

Описание

Возвращает версию протокола, используемую для текущего соединения.

Возвращаемые значения

Беззнаковое целое число, представляющее версию протокола, используемую для текущего соединения.

Ошибки

Нет.

8.4.3.28 mysql_get_server_info()

char *mysql_get_server_info(MYSQL *mysql)

Описание

Возвращает строку, представляющую номер версии сервера.

Возвращаемые значения

Символьная строка, представляющая номер версии сервера.

Ошибки

Нет.

8.4.3.29 mysql_info()

char *mysql_info(MYSQL *mysql)

Описание

Извлекает строку, представляющую информацию о последнем выполненном запросе, но только для команд, перечисленных ниже. Для других команд функция mysql_info() возвращает NULL. Строка имеет различный формат в зависимости от типа запроса, как описано ниже. Числа приведены только для иллюстрации; данная строка будет содержать величины, соответствующие конкретному запросу.

INSERT INTO ... SELECT ...
Формат строки: Records: 100 Duplicates: 0 Warnings: 0
INSERT INTO ... VALUES (...),(...),(...)...
Формат строки: Records: 3 Duplicates: 0 Warnings: 0
LOAD DATA INFILE ...
Формат строки: Records: 1 Deleted: 0 Skipped: 0 Warnings: 0
ALTER TABLE
Формат строки: Records: 3 Duplicates: 0 Warnings: 0
UPDATE
Формат строки: Rows matched: 40 Changed: 40 Warnings: 0

Следует учитывать, что функция mysql_info() возвращает величину не-NULL для команды INSERT ... VALUES, только если в данной команде заданы множественные списки величин.

Возвращаемые значения

Символьная строка, представляющая дополнительную информацию о последнем выполненном запросе. NULL, если нет никакой доступной информации по данному запросу.

Ошибки

Нет.

8.4.3.30 mysql_init()

MYSQL *mysql_init(MYSQL *mysql)

Описание

Выделяет или инициализирует объект MYSQL, подходящий для функции mysql_real_connect(). Если аргумент mysql представляет собой указатель NULL, то эта функция выделяет, инициализирует и возвращает новый объект. В противном случае инициализируется указанный объект и возвращается его адрес. Если функция mysql_init() выделяет новый объект, то он будет освобожден при вызове функции mysql_close(), чтобы закрыть данное соединение.

Возвращаемые значения

Инициализированный дескриптор MYSQL*. NULL при недостатке памяти для выделения нового объекта.

Ошибки

В случае нехватки памяти возвращается NULL.

8.4.3.31 mysql_insert_id()

my_ulonglong mysql_insert_id(MYSQL *mysql)

Описание

Возвращает идентификатор ID, сгенерированный для столбца AUTO_INCREMENT предыдущим запросом. Эту функцию следует использовать после выполнения запроса INSERT в таблице, содержащей поле AUTO_INCREMENT.

Следует учитывать, что функция mysql_insert_id() возвращает 0, если предыдущий запрос не сформировал величину AUTO_INCREMENT. Если необходимо сохранить эту величину в дальнейшем, то следует позаботиться о вызове функции mysql_insert_id() немедленно после запроса, который создает указанную величину.

Функция mysql_insert_id() обновляется после команд INSERT и UPDATE, которые генерируют величину AUTO_INCREMENT или устанавливают величину столбца в значение LAST_INSERT_ID(expr). See section 6.3.6.2 Разные функции.

Следует также иметь в виду, что величина SQL-функции LAST_INSERT_ID() всегда содержит самое последнее сгенерированное значение AUTO_INCREMENT и не обновляется между запросами, так как величина этой функции сохраняется сервером.

Возвращаемые значения

Величина поля AUTO_INCREMENT, обновленного предыдущим запросом. Возвращает нуль, если перед этим не было запроса в данном соединении или если данный запрос не обновил величину AUTO_INCREMENT.

Ошибки

Нет.

8.4.3.32 mysql_kill()

int mysql_kill(MYSQL *mysql, unsigned long pid)

Описание

Предписывает серверу уничтожить поток, указанный в аргументе pid.

Возвращаемые значения

Нуль при успешном выполнении. Отличная от нуля величина при ошибке.

Ошибки

CR_COMMANDS_OUT_OF_SYNC
Команды были выполнены в ненадлежащем порядке.
CR_SERVER_GONE_ERROR
Сервер MySQL неожиданно завершил работу.
CR_SERVER_LOST
Соединение с сервером прервалось в процессе данного запроса.
CR_UNKNOWN_ERROR
Произошла неизвестная ошибка.

8.4.3.33 mysql_list_dbs()

MYSQL_RES *mysql_list_dbs(MYSQL *mysql, const char *wild)

Описание

Возвращает результирующий набор, состоящий из имен баз данных на сервере, которые встречаются в простом регулярном выражении, указанном в параметре wild. Параметр wild может содержать шаблонные символы `%' или `_', а также может быть указателем NULL, что соответствует всем базам данных. Вызов функции mysql_list_dbs()аналогичен выполнению запроса SHOW databases [LIKE wild].

Результирующий набор необходимо освободить с помощью функции mysql_free_result().

Возвращаемые значения

Результирующий набор MYSQL_RES при успешном выполнении. NULL, если произошла ошибка.

Ошибки

CR_COMMANDS_OUT_OF_SYNC
Команды были выполнены в ненадлежащем порядке.
CR_OUT_OF_MEMORY
Нехватка памяти.
CR_SERVER_GONE_ERROR
Сервер MySQL неожиданно завершил работу.
CR_SERVER_LOST
Соединение с сервером прервалось в процессе данного запроса.
CR_UNKNOWN_ERROR
Произошла неизвестная ошибка.

8.4.3.34 mysql_list_fields()

MYSQL_RES *mysql_list_fields(MYSQL *mysql, const char *table, const char *wild)

Описание

Возвращает результирующий набор, состоящий из имен полей в заданной таблице, встречающихся в простом регулярном выражении, указанном в параметре wild. Параметр wild может содержать шаблонные символы `%' или `_', а также может быть указателем NULL, что соответствует всем полям. Вызов функции mysql_list_fields() аналогичен выполнению запроса SHOW COLUMNS FROM tbl_name [LIKE wild].

Следует учитывать, что рекомендуется использовать команду SHOW COLUMNS FROM tbl_name вместо функции mysql_list_fields().

Результирующий набор необходимо освободить с помощью функции mysql_free_result().

Возвращаемые значения

Результирующий набор MYSQL_RES при успешном выполнении. NULL, если произошла ошибка.

Ошибки

CR_COMMANDS_OUT_OF_SYNC
Команды были выполнены в ненадлежащем порядке.
CR_SERVER_GONE_ERROR
Сервер MySQL неожиданно завершил работу.
CR_SERVER_LOST
Соединение с сервером прервалось в процессе данного запроса.
CR_UNKNOWN_ERROR
Произошла неизвестная ошибка.

8.4.3.35 mysql_list_processes()

MYSQL_RES *mysql_list_processes(MYSQL *mysql)

Описание

Возвращает результирующий набор, описывающий текущие потоки на сервере. Предоставляет тот же тип информации, который выдается утилитой mysqladmin processlist или запросом SHOW PROCESSLIST.

Результирующий набор необходимо освободить с помощью функции mysql_free_result().

Возвращаемые значения

Результирующий набор MYSQL_RES при успешном выполнении. NULL, если произошла ошибка.

Ошибки

CR_COMMANDS_OUT_OF_SYNC
Команды были выполнены в ненадлежащем порядке.
CR_SERVER_GONE_ERROR
Сервер MySQL неожиданно завершил работу.
CR_SERVER_LOST
Соединение с сервером прервалось в процессе данного запроса.
CR_UNKNOWN_ERROR
Произошла неизвестная ошибка.

8.4.3.36 mysql_list_tables()

MYSQL_RES *mysql_list_tables(MYSQL *mysql, const char *wild)

Описание

Возвращает результирующий набор, состоящий из имен таблиц в текущей базе данных, которые встречаются в простом регулярном выражении, указанном в параметре wild. Параметр wild может содержать шаблонные символы `%' или `_', а также может быть указателем NULL, что соответствует всем таблицам. Вызов функции mysql_list_tables()аналогичен выполнению запроса SHOW tables [LIKE wild].

Результирующий набор необходимо освободить с помощью функции mysql_free_result().

Возвращаемые значения

Результирующий набор MYSQL_RES при успешном выполнении. NULL, если произошла ошибка.

Ошибки

CR_COMMANDS_OUT_OF_SYNC Команды были выполнены в ненадлежащем порядке. CR_SERVER_GONE_ERROR Сервер MySQL неожиданно завершил работу. CR_SERVER_LOST Соединение с сервером прервалось в процессе данного запроса. CR_UNKNOWN_ERROR Произошла неизвестная ошибка.

8.4.3.37 mysql_num_fields()

unsigned int mysql_num_fields(MYSQL_RES *result)

или

unsigned int mysql_num_fields(MYSQL *mysql)

Вторая форма не работает на версии MySQL 3.22.24 или более новой. Вместо аргумента в параметре MYSQL* необходимо использовать выражение unsigned int mysql_field_count(MYSQL *mysql)

Описание

Возвращает количество столбцов в результирующем наборе.

Следует отметить, что можно получить искомое количество столбцов с помощью указателя или на результирующий набор, или на дескриптор соединения. Дескриптор соединения необходимо использовать, если функции mysql_store_result() или mysql_use_result() возвратили NULL (и, следовательно, отсутствует указатель результирующего набора). В этом случае можно вызвать функцию mysql_field_count()для определения, может ли функция mysql_store_result()выдать непустой результат. Это дает возможность данной клиентской программе выполнить соответствующее действие без уточнения, был ли данный запрос командой вида SELECT (или похожей на SELECT). В приведенном ниже примере иллюстрируется, как это можно сделать.

See section 8.4.6.1 Почему после успешных возвратов функции mysql_query() функция mysql_store_result() иногда возвращает NULL?.

Возвращаемые значения

Беззнаковое целое число, представляющее количество полей в результирующем наборе.

Ошибки

Нет.

Пример

MYSQL_RES *result;
unsigned int num_fields;
unsigned int num_rows;

if (mysql_query(&mysql,query_string))
{
    // ошибка
}
else // запрос выполнен, обработка возвращенных им данных
{
    result = mysql_store_result(&mysql);
    if (result) // содержит строки {
        num_fields = mysql_num_fields(result);
        // извлечение строк, затем вызов mysql_free_result(result)
    }
    else // mysql_store_result()не вернула ничего; может ли что-либо вернуть?
    {
        if (mysql_errno(&mysql))
        {
            fprintf(stderr, "Error: %s\n", mysql_error(&mysql));
        }
        else if (mysql_field_count(&mysql) == 0)
        {
            // запрос не возвращает данные
            // (запрос не был вида SELECT)
            num_rows = mysql_affected_rows(&mysql);
        }
    }
}

Альтернатива (если известно, что данный запрос должен вернуть результирующий набор) состоит в замене вызова функции mysql_errno(&mysql) на проверку, равна ли 0 функция mysql_field_count(&mysql). Это может случиться, только если что-нибудь происходило не так.

8.4.3.38 mysql_num_rows()

my_ulonglong mysql_num_rows(MYSQL_RES *result)

Описание

Возвращает количество строк в результирующем наборе.

Использование функции mysql_num_rows() зависит от того, какая функция - mysql_store_result() или mysql_use_result() применяется для возвращения результирующего набора. Если используется mysql_store_result(), то функция mysql_num_rows() может вызываться немедленно. Если используется mysql_use_result(),то функция mysql_num_rows() не будет возвращать правильную величину до тех пор, пока все строки в результирующем наборе не будут извлечены.

Возвращаемые значения

Количество строк в результирующем наборе.

Ошибки

Нет.

8.4.3.39 mysql_options()

int mysql_options(MYSQL *mysql, enum mysql_option option, const char *arg)

Описание

Может использоваться для установки дополнительных опций соединения и влияет на режим работы соединения. Эта функция может вызываться многократно для установки нескольких опций.

Функция mysql_options() должна вызываться после функции mysql_init() и перед функцией mysql_connect() или mysql_real_connect().

Аргумент option представляет собой опцию, которую требуется установить; аргумент arg является величиной этой опции. Если данная опция является целым числом, то аргумент arg должен указывать на величину целого числа.

Возможные значения опций:

Опция | Тип аргумента | Функция
MYSQL_OPT_CONNECT_TIMEOUT | unsigned int * | Время ожидания для соединения в секундах.
MYSQL_OPT_COMPRESS | Не используется | Использовать сжатие в клиент-серверном протоколе.
MYSQL_OPT_LOCAL_INFILE | Опциональный указатель на uint | Если указатель не задан или указывает на unsigned int != 0 команда LOAD LOCAL INFILE разрешена.
MYSQL_OPT_NAMED_PIPE | Не используется | Использовать именованные каналы для соединения с сервером MySQL на NT.
MYSQL_INIT_COMMAND | char * | Команда для исполнения при подключении к серверу MySQL. При восстановлении соединения будет снова автоматически выполнена.
MYSQL_READ_DEFAULT_FILE | char * | Читать опции из указанного файла опций вместо чтения из файла `my.cnf'.
MYSQL_READ_DEFAULT_GROUP | char * | Читать опции из указанной группы из файла `my.cnf' или из файла заданного в MYSQL_READ_DEFAULT_FILE.

Следует помнить, что группа client читается всегда при использовании MYSQL_READ_DEFAULT_FILE или MYSQL_READ_DEFAULT_GROUP.

Упомянутая группа в файле опций может содержать следующие опции:

Опция | Описание
connect-timeout | Время ожидания для соединения в секундах. Для Linux это время ожидания используется также для ожидания первого ответа с сервера.
compress | Использовать сжатие в клиент-серверном протоколе.
database | Подключиться к этой базе данных, если никакая база данных не была указана в данной команде подключения.
debug | Опции отладки.
disable-local-infile | Блокировка использования LOAD DATA LOCAL.
host | Имя хоста по умолчанию.
init-command | Команда для исполнения при подключении к серверу MySQL. При восстановлении соединения будет снова автоматически выполнена.
interactive-timeout | Аналогично заданию CLIENT_INTERACTIVE в mysql_real_connect(). See section 8.4.3.42 mysql_real_connect().
local-infile[=(0|1)] | Если аргумент не задан или указан аргумент != 0, то разрешено использование LOAD DATA LOCAL.
max_allowed_packet | Максимальный размер пакета, который клиент может читать с сервера.
password | Пароль по умолчанию.
pipe | Использовать именованные каналы для соединения с сервером MySQL на NT.
protocol=(TCP | SOCKET | PIPE | MEMORY) | Какой протокол использовать для подключения к серверу (новшество 4.1.0).
port | Номер порта по умолчанию.
return-found-rows | Предписывает mysql_info() возвращать найденные строки вместо обновления их при выполнении UPDATE.
shared-memory-base-name=name | Имя блока общей памяти (shared memory name), которое следует использовать для подключения к серверу (по умолчанию "MySQL"). Новшество в MySQL 4.1.
socket | Номер сокета по умолчанию.
user | Пользователь по умолчанию.

Следует помнить, что timeout замещен на connect-timeout, но timeout временно еще работает.

Для более подробной информации о файлах опций см. раздел See section 4.1.2 Файлы параметров `my.cnf'.

Возвращаемые значения

Нуль при успешном выполнении. Величина, отличная от нуля, если используется неизвестная опция.

Пример

MYSQL mysql;

mysql_init(&mysql);
mysql_options(&mysql,MYSQL_OPT_COMPRESS,0);
mysql_options(&mysql,MYSQL_READ_DEFAULT_GROUP,"odbc");
if
(!mysql_real_connect(&mysql,"host","user","passwd","database",0,NULL,0))
{
    fprintf(stderr, "Failed to connect to database: Error: %s\n",
    mysql_error(&mysql));
}

Вышеприведенный пример запрашивает клиента использовать сжатый клиент-серверный протокол и читать дополнительные опции из секции odbc в файле `my.cnf'.

8.4.3.40 mysql_ping()

int mysql_ping(MYSQL *mysql)

Описание

Проверяет, работает ли данное соединение с сервером. Если соединение прервано, то пытается автоматически восстановить его.

Эта функция может использоваться клиентами, долгое время находящимися в состоянии простоя, для проверки, закрыл ли сервер данное соединение, и для восстановления соединения при необходимости.

Возвращаемые значения

Нуль, если сервер в активном состоянии. Величина, отличная от нуля, если произошла ошибка.

Ошибки

CR_COMMANDS_OUT_OF_SYNC
Команды были выполнены в ненадлежащем порядке.
CR_SERVER_GONE_ERROR
Сервер MySQL неожиданно завершил работу.
CR_UNKNOWN_ERROR
Произошла неизвестная ошибка.

8.4.3.41 mysql_query()

int mysql_query(MYSQL *mysql, const char *query)

Описание

Выполняет запрос SQL, указанный в аргументе query в виде строки с нулевыми окончаниями. Данный запрос должен состоять из одной команды SQL. Нельзя добавлять к этой команде в качестве завершающих элементов точку с запятой (`;') или \g.

Функция mysql_query() не может использоваться для запросов, содержащих двоичные данные; вместо этого необходимо использовать функцию mysql_real_query() (двоичные данные могут содержать символ `\0', который mysql_query() интерпретирует как окончание строки запроса).

Для проверки, вернул данный запрос результирующий набор или нет, можно использовать функцию mysql_field_count(). See section 8.4.3.20 mysql_field_count().

Возвращаемые значения

Нуль при успешном выполнении запроса. Величина, отличная от нуля, если произошла ошибка.

Ошибки

CR_COMMANDS_OUT_OF_SYNC
Команды были выполнены в ненадлежащем порядке.
CR_SERVER_GONE_ERROR
Сервер MySQL неожиданно завершил работу.
CR_SERVER_LOST
Соединение с сервером прервалось в процессе данного запроса.
CR_UNKNOWN_ERROR
Произошла неизвестная ошибка.

8.4.3.42 mysql_real_connect()

MYSQL *mysql_real_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd, const char *db, unsigned int port, const char *unix_socket, unsigned int client_flag)

Описание

Функция mysql_real_connect() пытается установить соединение с сервером баз данных MySQL, работающим на хосте host. До успешного завершения функции mysql_real_connect() нельзя выполнять никакие другие функции интерфейса, за исключением mysql_get_client_info().

Параметры этой функции указываются следующим образом:

  • Первым параметром должен быть указатель существующей структуры MYSQL. До вызова функции mysql_real_connect() необходимо вызвать функцию mysql_init() для инициализации данной структуры MYSQL. Вызов функции mysql_options() позволяет изменить многие опции данного соединения. See section 8.4.3.39 mysql_options().
  • host может быть как именем хоста, так и IP-адресом. Если host равен NULL или строке "localhost", то подразумевается соединение с локальным хостом. Если операционная система поддерживает сокеты (Unix) или именованные каналы (Windows), то они используются вместо протокола TCP/IP для соединения с сервером.
  • Параметр user содержит имя данного пользователя MySQL. Если параметр user равен NULL, то подразумевается текущий пользователь. Под операционной системой Unix, это будет текущее имя входа в систему. Под Windows ODBC имя пользователя должно быть указано явным образом. См. раздел See section 8.3.2 Как заполнять различные поля в Администраторе ODBC.
  • Параметр passwd содержит пароль для user. Если параметр passwd равен NULL, то только записи в таблице user для пользователя, имеющего чистое (пустое) поле пароля, будут проверяться на совпадение. Это дает возможность администратору базы данных устанавливать систему прав MySQL таким образом, что пользователи получают различные права, в зависимости от того, имеют они или нет установленный пароль. Замечание: не следует пытаться шифровать пароль перед вызовом функции mysql_real_connect(); шифрование пароля производится автоматически библиотекой.
  • Параметр db представляет собой имя базы данных. Если параметр db не равен NULL, то данное соединение установит эту величину в качестве базы данных по умолчанию.
  • Если параметр port не равен 0, то данная величина будет использована в качестве порта для соединения TCP/IP. Следует учитывать, что тип соединения определяется параметром host.
  • Если параметр unix_socket не равен NULL, то данная строка указывает сокет или именованный канал, который следует использовать. Следует учитывать, что тип соединения определяется параметром host.
  • Величина параметра client_flag обычно равна 0, но при особых обстоятельствах может быть установлена как комбинация следующих флагов:
    Имя флага | Описание флага
    CLIENT_COMPRESS | Использовать сжатие в протоколе.
    CLIENT_FOUND_ROWS | Возвращать количество найденных (совпавших) строк, а не количество строк, подвергшихся воздействию.
    CLIENT_IGNORE_SPACE | Допускать пробелы после имен функций. Сделать имена всех функций зарезервированными словами.
    CLIENT_INTERACTIVE | Допускать простой длительностью interactive_timeout секунд (вместо wait_timeout секунд) перед закрытием данного соединения.
    CLIENT_NO_SCHEMA | Запретить использование формы db_name.tbl_name.col_name. Это делается для ODBC и заставляет синтаксический анализатор генерировать ошибку при использовании данного синтаксиса, который полезен для выявления ошибок в некоторых программах ODBC.
    CLIENT_ODBC | Клиентом является клиент ODBC. Настраивает mysqld для большей совместимости с ODBC.
    CLIENT_SSL | Использовать SSL (протокол шифрования).

Возвращаемые значения

Дескриптор соединения MYSQL*, если соединение было успешным, NULL если соединение было неудачным. Для успешного соединения возвращаемая величина та же, что и величина первого параметра.

Ошибки

CR_CONN_HOST_ERROR
Не удалось соединиться с сервером MySQL.
CR_CONNECTION_ERROR
Не удалось соединиться с локальным сервером MySQL.
CR_IPSOCK_ERROR
Не удалось создать IP-сокет.
CR_OUT_OF_MEMORY
Недостаток памяти.
CR_SOCKET_CREATE_ERROR
Не удалось создать Unix сокет.
CR_UNKNOWN_HOST
Не удалось найти IP-адрес для данного имени хоста.
CR_VERSION_ERROR
Несоответствие протокола, что явилось результатом попытки соединения с сервером с клиентской библиотекой, использующей иную версию протокола. Это может произойти при использовании очень старой клиентской библиотеки для подключения к новому серверу, при запуске которого не была установлена опция --old-protocol.
CR_NAMEDPIPEOPEN_ERROR
Не удалось создать именованный канал на Windows.
CR_NAMEDPIPEWAIT_ERROR
Не удалось дождаться именованного канала на Windows.
CR_NAMEDPIPESETSTATE_ERROR
Не удалось получить обработчик канала на Windows.
CR_SERVER_LOST
Если connect_timeout > 0 и требовалось больше, чем connect_timeout секунд для соединения с сервером или если сервер прекратил работу во время выполнения init-command.

Пример

MYSQL mysql;

mysql_init(&mysql);
mysql_options(&mysql,MYSQL_READ_DEFAULT_GROUP,"your_prog_name");
if
(!mysql_real_connect(&mysql,"host","user","passwd","database",0,NULL,0))
{
    fprintf(stderr, "Failed to connect to database: Error: %s\n",
    mysql_error(&mysql));
}

Используя функцию mysql_options(), библиотека MySQL будет читать секции [client] и [your_prog_name] в конфигурационном файле `my.cnf', что будет гарантировать нормальную работу данной программы, даже если MySQL будет установлен нестандартным образом.

Следует заметить, что во время соединения функция mysql_real_connect() устанавливает флаг reconnect (часть данной структуры MYSQL) в значение, равное 1. Этот флаг показывает, что в случае, если запрос не может быть выполнен из-за потери соединения, то следует попытаться восстановить соединение прежде, чем отказаться от него.

8.4.3.43 mysql_real_escape_string()

unsigned long mysql_real_escape_string(MYSQL *mysql, char *to, const char *from, unsigned long length)

Описание

Эта функция используется для создания допустимой SQL- строки, которую можно использовать в команде SQL. See section 6.1.1.1 Cтроки.

Строка из секции from кодируется в экранированную SQL-строку, принимая во внимание текущую кодировку данного соединения. Результат помещается в секцию to с добавлением концевого нулевого байта. Кодируются следующие символы: NUL (ASCII 0), `\n', `\r', `\', `'', `"' и Ctrl-Z (see section 6.1.1 Литералы: представление строк и чисел). (Строго говоря, MySQL требует только чтобы обратная косая черта и кавычки, используемые для квотинга строк в запросе, были проэкранированы. Эта функция экранирует и другие символы, делая их более легкими для чтения в журнальных файлах.)

Строка, указанная в секции from, должна быть длиной length байтов. Необходимо выделить для секции to буфер величиной по меньшей мере length*2+1 байтов (в наихудшем случае каждый символ может потребовать кодировки с использованием двух байтов и, кроме того, необходимо место для концевого нулевого байта). При возврате функции mysql_real_escape_string() содержимое секции to будет представлять собой строку с нулевым окончанием. Возвращаемая величина представляет собой длину данной кодированной строки, не включая концевой нулевой символ.

Пример

char query[1000],*end;

end = strmov(query,"INSERT INTO test_table values(");
*end++ = '\'';
end += mysql_real_escape_string(&mysql, end,"What's this",11);
*end++ = '\'';
*end++ = ',';
*end++ = '\'';
end += mysql_real_escape_string(&mysql, end,"binary data: \0\r\n",16);
*end++ = '\'';
*end++ = ')';

if (mysql_real_query(&mysql,query,(unsigned int) (end - query)))
{
    fprintf(stderr, "Failed to insert row, Error: %s\n",
    mysql_error(&mysql));
}

Функция strmov(), использованная в этом примере, присутствует в библиотеке mysqlclient и работает подобно функции strcpy(), но возвращает указатель на концевой нуль первого параметра.

Возвращаемые значения

Длина величины, помещенной в секции to, не включая концевой нулевой символ.

Ошибки

Нет.

8.4.3.44 mysql_real_query()

int mysql_real_query(MYSQL *mysql, const char *query, unsigned long length)

Описание

Выполняет SQL-запрос, указанный в query, который должен быть строкой длиною length байтов. Данный запрос должен состоять из одной команды SQL. Нельзя добавлять к этой команде в качестве завершающих элементов точку с запятой (`;') или \g.

Необходимо использовать функцию mysql_real_query() вместо функции mysql_query()для запросов, содержащих двоичные данные, поскольку двоичные данные могут содержать символ `\0'. Кроме того, функция mysql_real_query() быстрее, чем mysql_query() так как она не вызывает функцию strlen() в строке запроса.

Для проверки того, вернул данный запрос результирующий набор или нет, можно использовать функцию mysql_field_count(). See section 8.4.3.20 mysql_field_count().

Возвращаемые значения

Нуль при успешном выполнении запроса. Величина, отличная от нуля, если произошла ошибка.

Ошибки

CR_COMMANDS_OUT_OF_SYNC
Команды были выполнены в ненадлежащем порядке.
CR_SERVER_GONE_ERROR
Сервер MySQL неожиданно завершил работу.
CR_SERVER_LOST
Соединение с сервером прервалось в процессе данного запроса.
CR_UNKNOWN_ERROR
Произошла неизвестная ошибка.

8.4.3.45 mysql_reload()

int mysql_reload(MYSQL *mysql)

Описание

Запрашивает сервер MySQL перегрузить таблицы привилегий. Подключенный пользователь должен обладать правом RELOAD.

Данная функция не рекомендуется. Вместо нее предпочтительно использовать функцию mysql_query() для вызова SQL-команды FLUSH PRIVILEGES.

Возвращаемые значения

Нуль при успешном выполнении запроса. Величина, отличная от нуля, если произошла ошибка.

Ошибки

CR_COMMANDS_OUT_OF_SYNC
Команды были выполнены в ненадлежащем порядке.
CR_SERVER_GONE_ERROR
Сервер MySQL неожиданно завершил работу.
CR_SERVER_LOST
Соединение с сервером прервалось в процессе данного запроса.
CR_UNKNOWN_ERROR
Произошла неизвестная ошибка.

8.4.3.46 mysql_row_seek()

MYSQL_ROW_OFFSET mysql_row_seek(MYSQL_RES *result, MYSQL_ROW_OFFSET offset)

Описание

Устанавливает курсор строки на произвольную заданную строку в результирующем наборе запроса. Это требует, чтобы структура результирующего набора содержала целиком весь результат данного запроса, поэтому функция mysql_row_seek() может использоваться только в соединении с mysql_store_result(), но не с mysql_use_result().

Адрес смещения должен быть величиной, возвращенной в результате вызова функций mysql_row_tell() или mysql_row_seek(). Эта величина не является номером строки, поэтому для проведения поиска строки внутри результирующего набора по номеру строки вместо данной функции следует использовать функцию mysql_data_seek().

Возвращаемые значения

Предыдущая позиция курсора строки. Эта величина может быть получена последовательным вызовом mysql_row_seek().

Ошибки

Нет.

8.4.3.47 mysql_row_tell()

MYSQL_ROW_OFFSET mysql_row_tell(MYSQL_RES *result)

Описание

Возвращает позицию курсора строки, использованную для последнего вызова функции mysql_fetch_row().Эта величина может использоваться как аргумент в функции mysql_row_seek().

Функцию mysql_row_tell() следует использовать только после функции mysql_store_result(), но не после mysql_use_result().

Возвращаемые значения

Текущая позиция курсора строки.

Ошибки

Нет.

8.4.3.48 mysql_select_db()

int mysql_select_db(MYSQL *mysql, const char *db)

Описание

Устанавливает базу данных, указанную в db, в качестве текущей базы данных по умолчанию для соединения, указанного в mysql. В последующих запросах эта база данных является текущей по умолчанию для табличных ссылок, которые не содержат явного указателя базы данных.

Функция mysql_select_db() не работает, пока подключенный пользователь не сможет быть аутентифицирован как имеющий право на использование запрашиваемой базы данных.

Возвращаемые значения

Нуль при успешном выполнении запроса. Величина, отличная от нуля, если произошла ошибка.

Ошибки

CR_COMMANDS_OUT_OF_SYNC
Команды были выполнены в ненадлежащем порядке.
CR_SERVER_GONE_ERROR
Сервер MySQL неожиданно завершил работу.
CR_SERVER_LOST
Соединение с сервером прервалось в процессе данного запроса.
CR_UNKNOWN_ERROR
Произошла неизвестная ошибка.

8.4.3.49 mysql_shutdown()

int mysql_shutdown(MYSQL *mysql)

Описание

Останавливает сервер баз данных. Подключенный пользователь должен иметь права SHUTDOWN.

Возвращаемые значения

Нуль при успешном выполнении запроса. Величина, отличная от нуля, если произошла ошибка.

Ошибки

CR_COMMANDS_OUT_OF_SYNC
Команды были выполнены в ненадлежащем порядке.
CR_SERVER_GONE_ERROR
Сервер MySQL неожиданно завершил работу.
CR_SERVER_LOST
Соединение с сервером прервалось в процессе данного запроса.
CR_UNKNOWN_ERROR
Произошла неизвестная ошибка.

8.4.3.50 mysql_stat()

char *mysql_stat(MYSQL *mysql)

Описание

Возвращает символьную строку, содержащую информацию, подобную предоставляемой командой mysqladmin status. Информация включает в себя время работы сервера в секундах, а также количество запущенных потоков, запросов, перегрузок и открытых таблиц.

Возвращаемые значения

Символьная строка с описанием статуса сервера. NULL, если возникла ошибка.

Ошибки

CR_COMMANDS_OUT_OF_SYNC
Команды были выполнены в ненадлежащем порядке.
CR_SERVER_GONE_ERROR
Сервер MySQL неожиданно завершил работу.
CR_SERVER_LOST
Соединение с сервером прервалось в процессе данного запроса.
CR_UNKNOWN_ERROR
Произошла неизвестная ошибка.

8.4.3.51 mysql_store_result()

MYSQL_RES *mysql_store_result(MYSQL *mysql)

Описание

Функцию mysql_store_result() или mysql_use_result() необходимо вызывать после каждого выполненного запроса, извлекающего данные (SELECT, SHOW, DESCRIBE, EXPLAIN).

Нет необходимости в вызове функции mysql_store_result() или mysql_use_result() для других запросов, но не будет никакого вреда или заметной потери производительности, если функция mysql_store_result() будет вызываться во всех случаях. Можно определить, вернул ли данный запрос результирующий набор, проверкой, возвращает ли 0 функция mysql_store_result() (более подробно об этом см. дальше).

Для проверки того, вернул данный запрос результирующий набор или нет, можно использовать функцию mysql_field_count(). See section 8.4.3.20 mysql_field_count().

Функция mysql_store_result() читает весь результат запроса данного клиента, выделяет структуру MYSQL_RES и помещает результат в эту структуру.

Функция mysql_store_result() возвращает нулевой указатель, если данный запрос не вернул результирующий набор (если этот запрос был, например, командой INSERT).

Функция mysql_store_result() также возвращает нулевой указатель, если чтение результирующего набора завершилось неудачно. Выяснить, произошла ли ошибка, можно следующим образом: если mysql_error() не возвращает нулевой указатель, если mysql_errno() возвращает величину <> 0 или если mysql_field_count()возвращает величину <> 0.

Пустой результирующий набор возвращается в случае, если нет ни одной возвращенной строки. (Пустой результирующий набор и нулевой указатель - разные вещи в контексте возвращаемых величин.)

Если была вызвана функция mysql_store_result() и полученный результат не является нулевым указателем, то можно вызвать функцию mysql_num_rows() для определения количества строк в результирующем наборе.

Можно вызвать функцию mysql_fetch_row() для выборки строк из результирующего набора или функции mysql_row_seek() и mysql_row_tell() для получения или установки положения текущей строки внутри данного результирующего набора.

Необходимо вызвать функцию mysql_free_result() сразу же после окончания действий с результирующим набором.

See section 8.4.6.1 Почему после успешных возвратов функции mysql_query() функция mysql_store_result() иногда возвращает NULL?.

Возвращаемые значения

Результирующая структура MYSQL_RES с результатами. NULL, если произошла ошибка.

Ошибки

CR_COMMANDS_OUT_OF_SYNC
Команды были выполнены в ненадлежащем порядке.
CR_OUT_OF_MEMORY
Нехватка памяти.
CR_SERVER_GONE_ERROR
Сервер MySQL неожиданно завершил работу.
CR_SERVER_LOST
Соединение с сервером прервалось в процессе данного запроса.
CR_UNKNOWN_ERROR
Произошла неизвестная ошибка.

8.4.3.52 mysql_thread_id()

unsigned long mysql_thread_id(MYSQL *mysql)

Описание

Возвращает идентификатор данного потока для текущего соединения. Эта величина может быть использована как аргумент для функции mysql_kill() для уничтожения данного потока.

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

Возвращаемые значения

Идентификатор данного потока для текущего соединения.

Ошибки

Нет.

8.4.3.53 mysql_use_result()

MYSQL_RES *mysql_use_result(MYSQL *mysql)

Описание

Функцию mysql_store_result() или mysql_use_result() необходимо вызывать после каждого выполненного запроса, извлекающего данные (SELECT, SHOW, DESCRIBE, EXPLAIN).

Функция mysql_use_result() инициализирует извлечение результирующего набора, но фактически не производит чтение в клиенте подобно тому, как это делает функция mysql_store_result(). Вместо этого каждая строка должна извлекаться индивидуально посредством вызова функции mysql_fetch_row(). При этом методе результат запроса читается непосредственно на сервере без промежуточного хранения его во временной таблице или локальном буфере, что быстрее и требует намного меньше памяти, чем использование функции mysql_store_result(). Клиент будет выделять память только для текущей строки и буфер связи может расти до величины max_allowed_packet байтов.

С другой стороны, функцию mysql_use_result() нельзя использовать, если выполняется много операций по обработке каждой строки на клиентской стороне, или если вывод делается на терминал, на котором пользователь может нажать ^S (остановить вывод).

Это будет ограничивать работу сервера и будет мешать другим потокам в обновлении таблиц, из которых выбираются данные.

При использовании mysql_use_result() необходимо выполнять mysql_fetch_row(), пока не возвратится величина NULL, в противном случае невыбранные строки данного запроса будут возвращены как часть результирующего набора для следующего запроса. Если вы забыли сделать это, то интерфейс C будет выдавать ошибку Commands out of sync; you can't run this command now!

Нельзя использовать функции mysql_data_seek(), mysql_row_seek(), mysql_row_tell(), mysql_num_rows() или mysql_affected_rows() для обработки результата, возвращенного функцией mysql_use_result(), а также нельзя запускать другие запросы, пока функция mysql_use_result() не завершится (однако после выборки всех строк функция mysql_num_rows() будет корректно возвращать количество выбранных строк).

Необходимо вызвать функцию mysql_free_result() сразу же после окончания действий с результирующим набором.

Возвращаемые значения

Результирующая структура MYSQL_RES с результатами. NULL, если произошла ошибка.

Ошибки

CR_COMMANDS_OUT_OF_SYNC
Команды были выполнены в ненадлежащем порядке.
CR_OUT_OF_MEMORY
Нехватка памяти.
CR_SERVER_GONE_ERROR
Сервер MySQL неожиданно завершил работу.
CR_SERVER_LOST
Соединение с сервером прервалось в процессе данного запроса.
CR_UNKNOWN_ERROR
Произошла неизвестная ошибка.

8.4.4 Описания функций C, связанных с потоками

Эти функции необходимо вызывать для сборки клиента с поддержкой потоков. See section 8.4.8 Как создать клиентскую программу с потоками.

8.4.4.1 my_init()

void my_init(void)

Описание

Данную функцию необходимо вызывать однажды во время запуска программы перед вызовом любой функции MySQL. Ее вызовом инициализируются необходимые для MySQL глобальные переменные. При использовании клиентской библиотеки, поддерживающей потоки, эта функция будет также вызывать функцию mysql_thread_init() для этого потока.

Данная функция вызывается автоматически функциями mysql_init(), mysql_server_init() и mysql_connect().

Возвращаемые величины

Нет.

8.4.4.2 mysql_thread_init()

my_bool mysql_thread_init(void)

Описание

Эту функцию необходимо вызывать для каждого созданного потока - для инициализации его специфических переменных.

Данная функция вызывается автоматически функциями my_init() и mysql_connect().

Возвращаемые величины

Нет.

8.4.4.3 mysql_thread_end()

void mysql_thread_end(void)

Описание

Данную функцию необходимо вызывать перед вызовом функции pthread_exit() для освобождения памяти, выделенной функцией mysql_thread_init().

Следует учитывать, что эта функция не вызывается автоматически клиентской библиотекой. Во избежание утечки памяти она должна вызываться явно.

Возвращаемые величины

Нет.

8.4.4.4 mysql_thread_safe()

unsigned int mysql_thread_safe(void)

Описание

Эта функция возвращает значение, показывающее, компилировался ли данный клиент как поддерживающий потоки.

Возвращаемые величины

1 - если данный клиент поддерживает потоки, 0 - в противном случае.

8.4.5 Описания функций C, доступных во встраиваемом сервере

Эти функции можно использовать при линковании с библиотекой встраиваемого сервера MySQL.

See section 8.4.9 libmysqld, встраиваемая библиотека сервера MySQL.

Если данная программа слинкована с -lmysqlclient, а не с -lmysqld, то эти функции не делают ничего. Это обеспечивает возможность выбора между встраиваемым сервером MySQL и автономным без какой-либо модификации кода.

8.4.5.1 mysql_server_init()

int mysql_server_init(int argc, char **argv, char **groups)

Описание

Данную функцию необходимо вызывать только один раз во время работы программы, использующей встроенный сервер. Это функцию следует вызвать перед вызовом любой другой функции MySQL. Она запускает сервер и инициализирует все подсистемы (mysys, InnoDB и т.д.), используемые сервером. Без вызова этой функции произойдет аварийное завершение данной программы. При использовании пакета DBUG, поставляемого вместе с MySQL, данную функцию следует вызывать после функции MY_INIT().

Аргументы argc и argv аналогичны аргументам в main(). Первый элемент аргумента argv игнорируется (обычно он содержит имя программы). Для удобства аргумент argc может быть равен 0 (нуль) - если не задано ни одного аргумента командной строки для данного сервера. mysql_server_init() делает копию аргументов, т.е. она безопастна для уничтожения argv или groups после вызова.

Аргумент groups представляет собой список строк, заканчивающийся NULL. Этот аргумент задает активные группы в файлах опций (see section 4.1.2 Файлы параметров `my.cnf'). Для удобства аргумент groups может быть равен NULL - в этом случае будут активны группы [server] и [emedded].

Пример

#include <mysql.h>
#include <stdlib.h>

static char *server_args[] = {
  "this_program", /* эта строка не используется */
  "--datadir=.",
  "--key_buffer_size=32M"
};

static char *server_groups[] = {
  "embedded",
  "server",
  "this_program_SERVER",
  (char *)NULL
};

int main(void) {
  mysql_server_init(sizeof(server_args) / sizeof(char *),
  server_args, server_groups);
  /* Здесь используются любые функции MySQL  API */
  mysql_server_end();
  return EXIT_SUCCESS;
}

Возвращаемые значения

0 - если все в порядке, 1 - если произошла ошибка.

8.4.5.2 mysql_server_end()

void mysql_server_end(void)

Описание

Эту функцию в программе необходимо вызывать только единожды, после всех остальных функций MySQL. Она останавливает libmysqld, встраиваемый сервер MySQL.

Возвращаемые значения

Нет.

8.4.6 Основные вопросы и проблемы в использовании интерфейса C

8.4.6.1 Почему после успешных возвратов функции mysql_query() функция mysql_store_result() иногда возвращает NULL?

Для функции mysql_store_result() после успешного вызова функции mysql_query() возможен возврат величины NULL. Это может означать следующее:

  • Произошел сбой в выполнении функции mallow() (например, если результирующий набор данных слишком велик).
  • Данные не могли быть прочитаны (возникла ошибка в соединении). Запрос не вернул никаких данных (например, это был запрос вида INSERT, UPDATE или DELETE).

Проверить, вернула ли данная команда не пустой результирующий набор, всегда можно с помощью вызова функции mysql_field_count(). Если функция mysql_field_count() возвращает нуль, то данный результирующий набор является пустым и последний запрос представлял собой команду, которая не возвращает результирующие величины (например, INSERT или DELETE). Если функция mysql_field_count() возвращает величину, отличную от нуля, то данная команда должна была вернуть не пустой результат (см. описание функции mysql_field_count()).

Можно протестировать описанные ситуации на ошибку, вызывая функции mysql_error() или mysql_errno().

8.4.6.2 Какие результаты можно получить из запроса?

В дополнение к возвращенному запросом результирующему набору данных можно также получить следующую информацию:

  • Функция mysql_affected_rows() возвращает количество строк, подвергшихся воздействию во время последнего запроса при выполнении INSERT, UPDATE или DELETE. Исключение составляет случай использования команды DELETE без выражения WHERE, когда таблица воссоздается как пустая, а это намного быстрее! В таком случае функция mysql_affected_rows() в качестве количества подвергшихся воздействию записей возвращает нуль.
  • Функция mysql_num_rows() возвращает количество строк в результирующем наборе данных. Функция mysql_num_rows() может вызываться сразу же после возвращения функции mysql_store_result(). Совместно с функцией mysql_use_result() функция mysql_num_rows() может вызываться только после того, как извлечены все строки с помощью функции mysql_fetch_row().
  • Функция mysql_insert_id() возвращает идентификатор, созданный последним запросом, внесшим строку в таблицу с автоинкрементным полем (AUTO_INCREMENT, mysql_insert_id()).
  • Некоторые запросы (LOAD DATA INFILE ..., INSERT INTO ... SELECT ..., UPDATE) возвращают дополнительную информацию. Ее можно получить с помощью функции mysql_info(). Описание формата возвращаемой строки смотрите в описании функции mysql_info(). Если дополнительная информация отсутствует, то функция mysql_info() возвращает указатель NULL.

8.4.6.3 Как получить уникальный идентификатор для последней внесенной строки?

При внесении записи в таблицу, содержащую столбец с атрибутом AUTO_INCREMENT, последний сгенерированный идентификатор можно получить, вызвав функцию mysql_insert_id().

Для извлечения этого id можно также использовать функцию LAST_INSERT_ID() в строке запроса, передаваемой в mysql_query().

Для проверки, используется или нет поле AUTO_INCREMENT, можно выполнить следующий код. Этот код также проверяет, был ли данный запрос вида INSERT с использованием AUTO_INCREMENT:

if (mysql_error(&mysql)[0] == 0 &&
mysql_num_fields(result) == 0 &&
mysql_insert_id(&mysql) != 0)
{
    used_id = mysql_insert_id(&mysql);
}

Самое последнее сгенерированное значение идентификатора сохраняется на сервере в течение времени жизни данного соединения. Это значение не может быть изменено другим клиентом, более того, оно не будет изменено даже при обновлении другого столбца AUTO_INCREMENT конкретной величиной (т.е. не NULL или 0).

Идентификатор, который был сгенерирован для одной таблицы, можно вставить в другую таблицу, используя команды SQL, как показано ниже:

INSERT INTO foo (auto,text)
    VALUES(NULL,'text'); # генерация ID вставкой NULL
INSERT INTO foo2 (id,text)
    VALUES(LAST_INSERT_ID(),'text'); # использование ID во второй таблице

8.4.6.4 Проблемы линкования с интерфейсом C

При линковании программы с клиентской библиотекой C в некоторых системах могут возникать следующие проблемы:

gcc -g -o client test.o -L/usr/local/lib/mysql -lmysqlclient -lsocket -lnsl

Undefined        first referenced
 symbol          in file
floor            /usr/local/lib/mysql/libmysqlclient.a(password.o)
ld: fatal: Symbol referencing errors. No output written to client

Если это случилось в вашей системе, то необходимо подключить математическую библиотеку путем добавления параметра -lm в конец строки компилирования/линкования.

8.4.7 Сборка клиентских программ

Клиенты MySQL, созданные собственноручно или полученные от сторонних фирм, при компилировании должны линковаться с использованием опций -lmysqlclient -lz в команде линкования. Возможно, потребуется задать опцию -L, чтобы указать компоновщику местоположение данной библиотеки. Например, если библиотека установлена в каталоге `/usr/local/mysql/lib', следует использовать в команде линкования выражение -L/usr/local/mysql/lib -lmysqlclient -lz.

Для клиентов, использующих файлы заголовков MySQL, при компиляции, возможно, потребуется задать опцию -I (например, -I/usr/local/mysql/include), чтобы компилятор мог найти требуемые файлы заголовков.

Для того что бы сделать вышеизложенное более простым под Unix мы предоставляем для вас скрипт mysql_config. See section 4.8.9 mysql_config, Получение опций компиляции для компиляции клиентских программ.

Вы можете использовать его, компилируя клиента MySQL следующим образом:

CFG=/usr/local/mysql/bin/mysql_config
sh -c "gcc -o progname `$CFG --cflags` progname.c `$CFG --libs`"

sh -c необходимо чтобы оболочка не воспринимала вывод mysql_config как одно слово.

8.4.8 Как создать клиентскую программу с потоками

Клиентская библиотека почти безопасна при использовании в мультипоточном режиме. Наибольшая проблема заключается в том, что функции в `net.c', читающие из сокетов, не поддерживают прерываний. Они были спроектированы исходя из предположения, что пользователь может захотеть иметь свой собственный аварийный сигнал, который способен прерывать слишком долгое чтение с сервера. При установке обработчиков прерываний для прерывания SIGPIPE управление сокетами должно быть поддерживающим потоки.

В более ранних бинарных поставках MySQL, которые мы (разработчики MySQL) распространяли с нашего веб-сайта (http://www.mysql.com/), клиентские библиотеки обычно не компилировались с возможностью поддержки потоков (бинарные поставки для Windows по умолчанию компилируются как поддерживающие потоки). Более новые бинарные поставки должны иметь как нормальную, так и поддерживающую потоки клиентскую библиотеку.

Чтобы получить поддерживающую потоки клиентскую программу с возможностью прерывать ее из других потоков и устанавливать блокировки по времени при соединении с сервером MySQL, необходимо использовать библиотеки -lmysys, -lmystrings и -ldbug libraries, а также код `net_serv.o', используемый данным сервером.

Если нет необходимости в прерываниях или временных блокировках, то можно просто скомпилировать поддерживающую потоки клиентскую библиотеку (mysqlclient_r) и использовать ее (see section 8.4 Интерфейс C для MySQL). В этом случае нет необходимости заботиться об объектном файле net_serv.o или других библиотеках MySQL.

Если необходимо применять временные блокировки и прерывания при использовании поддерживающего потоки клиента, то можно с успехом использовать подпрограммы из файла `thr_alarm.c'. При использовании подпрограмм из библиотеки mysys следует помнить только о том, что сначала следует вызвать функцию my_init()! See section 8.4.4 Описания функций C, связанных с потоками.

Все функции, за исключением mysql_real_connect(), по умолчанию являются поддерживающими потоки. Ниже приводятся рекомендации, как следует компилировать поддерживающую потоки клиентскую библиотеку и использовать ее в этом режиме (замечания по функции mysql_real_connect() справедливы также и для функции mysql_connect(), но поскольку функция mysql_connect() не рекомендуется, то в любом случае следует использовать функцию mysql_real_connect()).

Для того чтобы сделать функцию mysql_real_connect() поддерживающей потоки, необходимо перекомпилировать клиентскую библиотеку со следующей командой:

shell> ./configure --enable-thread-safe-client

Это создаст поддерживающую потоки клиентскую библиотеку libmysqlclient_r (предполагается, что данная операционная система включает поддерживающую потоки функцию gethostbyname_r()). Эта библиотека является поддерживающей потоки для данного соединения. Можно позволить двум потокам использовать одно и то же соединение со следующими оговорками:

  • Два потока не могут посылать запрос серверу MySQL в одно и то же время на одном и том же соединении. В особенности необходимо быть уверенным, что в промежутках между вызовом функций mysql_query() и mysql_store_result() никакой другой поток не использует это же соединение.
  • Многие потоки имеют доступ к различным результирующим наборам данных, извлекаемых функцией mysql_store_result().
  • При использовании функции mysql_use_result необходимо быть уверенным, что никакой другой поток не использует это же соединение, пока данный результирующий набор не будет обработан. Однако действительно наилучший вариант для потоковых клиентов, совместно использующих одно и то же соединение, - это применять функцию mysql_store_result().
  • Если необходимо использовать большое количество потоков на одном и том же соединении, то следует иметь синхронизирующую блокировку в отношении вызова комбинации функций mysql_query() и mysql_store_result(). Как только выполнение функции mysql_store_result() заканчивается, данная блокировка может сниматься и другие потоки могут запрашивать это же самое соединение.
  • Если вы программируете с использованием потоков POSIX, то можно использовать функции pthread_mutex_lock() и pthread_mutex_unlock() для установки и освобождения синхронизирующей блокировки.

Необходимо знать следующее: если имеется вызываемый функцией MySQL поток, который не создавал данное соединение с базой данных MySQL, то:

При вызове функций mysql_init() или mysql_connect() MySQL создаст специальные переменные для этого потока, которые (среди прочих применений) используются библиотекой отладки.

При вызове функции MySQL до того, как поток вызвал функции mysql_init() или mysql_connect(), данный поток в этом случае не будет иметь необходимых специальных переменных потока и, вероятно, программа рано или поздно умрет с дампом оперативной памяти.

Для более плавной работы программы необходимо выполнить следующие действия:

  1. Вызвать функцию my_init() при запуске данной программы, если она вызывает какую-либо другую функцию MySQL до вызова функции mysql_real_connect().
  2. Вызвать функцию mysql_thread_init() в обработчике потока до вызова иной функции MySQL.
  3. В данном потоке вызвать функцию mysql_thread_end() перед вызовом pthread_exit(). Это освободит память, занятую специальными переменными потока для MySQL.

Следует учитывать, что можно получить некоторые ошибки из-за наличия неопределенных символов при связывании клиента с библиотекой libmysqlclient_r. В большинстве случаев это происходит вследствие того, что в строку связывания/компилирования не включены библиотеки потока.

8.4.9 libmysqld, встраиваемая библиотека сервера MySQL

8.4.9.1 Обзор библиотеки встраиваемого сервера MySQL

Библиотека встраиваемого сервера MySQL обеспечивает возможность запуска полнофункционального сервера MySQL внутри клиентского приложения. Основные преимущества, которые дает ее использование, - увеличение скорости и более простое управление для встраиваемых приложений.

Интерфейсы API для встраиваемой версии MySQL и для версии клиент/сервер идентичны. Чтобы реализовать возможность использования встраиваемого сервера в старом приложении с потоками, обычно необходимо только добавить вызовы следующих функций:

Функция | Когда вызывается
mysql_server_init() | Должна вызываться перед любой другой функцией MySQL, предпочтительно раньше, чем функция main().
mysql_server_end() | Должна вызываться перед выходом из данной программы.
mysql_thread_init() | Должна вызываться в каждом создаваемом потоке, который будет работать с MySQL.
mysql_thread_end() | Должна вызываться перед вызовом pthread_exit()

После добавления функций необходимо связать данный код с библиотекой `libmysqld.a' вместо `libmysqlclient.a'.

Вышеприведенные функции типа mysql_server_xxx также включены в `libmysqlclient.a' - таким образом обеспечивается возможность переключаться между встраиваемой и клиент-серверной версиями просто линкованием конкретного приложения с соответствующей библиотекой. См.раздел See section 8.4.5.1 mysql_server_init().

8.4.9.2 Компиляция программ с libmysqld

Чтобы получить библиотеку libmysqld, необходимо сконфигурировать (при помощи configure) сборку MySQL с опцией --with-embedded-server.

При связывании программы с libmysqld необходимо также включать специфические для данной системы библиотеки pthread и другие библиотеки, используемые сервером MySQL. Полный список библиотек можно получить, выполнив mysql_config --libmysqld-libs.

Для компиляции и связывания должны использоваться флаги компиляции потоковой программы, даже если никакие потоковые функции в данном коде явно не вызываются.

8.4.9.3 Ограничения при использовании встраиваемого сервера MySQL

встраиваемый сервер имеет следующие ограничения:

  • Не поддерживает таблицы ISAM (это сделано главным образом для уменьшения размеров библиотеки)
  • Не поддерживает функции UDF (функции, определяемые пользователем).
  • Не отслеживаются стеки на дампе оперативной памяти.
  • Нет внутренней поддержки RAID (обычно этого не требуется, так как большинство операционных систем в настоящее время имеют поддержку для больших файлов).
  • встраиваемый сервер MySQL нельзя установить как головной или подчиненный сервер репликации
  • К встраиваемому серверу нельзя подсоединиться из внешнего процесса через сокеты или по протоколу TCP/IP.

Некоторые из этих ограничений могут быть изменены путем редактирования включаемого файла `mysql_embed.h' и перекомпилирования MySQL.

8.4.9.4 Использование файлов опций с встраиваемым сервером

Ниже приводятся рекомендации по использованию файлов опций для облегчения перехода между клиент-серверным приложением и приложением с встраиваемым MySQL (see section 4.1.2 Файлы параметров `my.cnf').

  • Следует помещать общие опции в раздел [server]. Они будут читаться обеими версиями MySQL.
  • Следует помещать специфические клиент-серверные опции в раздел [mysqld].
  • Следует помещать специфические опции встраиваемого MySQL в раздел [embedded].
  • Следует помещать специфические опции приложения в раздел [ApplicationName_SERVER].

8.4.9.5 Что осталось сделать по встраиваемомуому серверу (TODO)

  • Предполагается обеспечить возможность не включать некоторые части MySQL, чтобы сделать библиотеку меньше.
  • Многое еще нужно сделать для оптимизации скорости.
  • Ошибки записываются в stderr. Предполагается добавить возможность указывать для них имя файла.
  • Необходимо изменить InnoDB, чтобы вывод этого обработчика не был бы настолько подробным во встраиваемой версии.

8.4.9.6 Пример простого встраиваемого сервера

Этот пример программы и сборочного файла должен работать без каких-либо изменений под операционными системами Linux или FreeBSD. Для других операционных систем потребуются небольшие изменения. При разработке данного примера мы ставили перед собой цель предоставить достаточно информации для понимания рассматриваемой темы и в то же время не перегружать текст руководства лишними деталями, специфическими для реального приложения.

Чтобы запустить этот пример, создайте каталог `test_libmysqld' там же, где находится каталог исходного кода mysql-4.0. Сохраните исходный код `test_libmysqld.c' и `GNUmakefile' в данном каталоге и запустите GNU `make' в каталоге `test_libmysqld'.

`test_libmysqld.c'

/*
* Клиент простого примера с использованием библиотеки встраиваемого
сервера MySQL
*/
#include <mysql.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>

MYSQL *db_connect(const char *dbname);
void db_disconnect(MYSQL *db);
void db_do_query(MYSQL *db, const char *query);

const char *server_groups[] = {
    "test_libmysqld_SERVER", "embedded", "server", NULL
};

int
main(int argc, char **argv)
{
  MYSQL *one, *two;
  /* Функцию mysql_server_init() необходимо вызывать перед любыми другими *
  функциями mysql.
  * Можно задать mysql_server_init(0, NULL, NULL); тогда для
  * инициализации сервера будут использоваться группы "server",
  * "embedded", NULL
  *}.
  *
  * В файле $HOME/.my.cnf можно указать:

[test_libmysqld_SERVER]
language = /path/to/source/of/mysql/sql/share/english

* Можно было бы, конечно, модифицировать argc и argv непосредственно
  * перед передачей их в эту функцию или создать
  * новые аргументы - для этого годится любой выбранный вами способ.
  * Однако все аргументы в argv (кроме argv[0], который
  * представляет собой имя программы) должны быть допустимыми опциями
  * для сервера MySQL.
  *
  * Если данный клиент линкуется с нормальной библиотекой mysqlclient,
  * то эта функция является просто заглушкой, ничего не делающей.
  */

mysql_server_init(argc, argv, (char **)server_groups);
one = db_connect("test");
two = db_connect(NULL);
db_do_query(one, "SHOW TABLE STATUS");
db_do_query(two, "SHOW DATABASES");
mysql_close(two);
mysql_close(one);

/* Эта функция должна вызываться после всех других функций mysql */

mysql_server_end();
exit(EXIT_SUCCESS);

}

static void
die(MYSQL *db, char *fmt, ...)
{
  va_list ap;
  va_start(ap, fmt);
  vfprintf(stderr, fmt, ap);
  va_end(ap);
  (void)putc('\n', stderr);
  if (db)
  db_disconnect(db);
  exit(EXIT_FAILURE);
}

MYSQL *
db_connect(const char *dbname)
{
  MYSQL *db = mysql_init(NULL);
  if (!db)
  die(db, "mysql_init failed: no memory");

/*
* Обратите внимание: клиент и сервер используют разные имена групп.
* Это обязательное условие, поскольку сервер не должен использовать опции
* клиента и наоборот.
*/

mysql_options(db, MYSQL_READ_DEFAULT_GROUP, "test_libmysqld_CLIENT");
if (!mysql_real_connect(db, NULL, NULL, NULL, dbname, 0, NULL, 0))
die(db, "mysql_real_connect failed: %s", mysql_error(db));
return db;
}

void
db_disconnect(MYSQL *db)
{
  mysql_close(db);
}

void
db_do_query(MYSQL *db, const char *query)
{
  if (mysql_query(db, query) != 0)
  goto err;
  if (mysql_field_count(db) > 0)
  {
    MYSQL_RES *res;
    MYSQL_ROW row, end_row;
    int num_fields;
    if (!(res = mysql_store_result(db)))
    goto err;
    num_fields = mysql_num_fields(res);
    while ((row = mysql_fetch_row(res)))
    {
       (void)fputs(">> ", stdout);
       for (end_row = row + num_fields; row < end_row; ++row)
       (void)printf("%s\t", row ? (char*)*row : "NULL");
       (void)fputc('\n', stdout);
    }
    (void)fputc('\n', stdout);
}
else
(void)printf("Affected rows: %lld\n", mysql_affected_rows(db));
return;
err:
die(db, "db_do_query failed: %s [%s]", mysql_error(db), query);
}

`GNUmakefile'

# Предполагается, что программное обеспечение MySQL установлено в
#/usr/local/mysql

inc := /usr/local/mysql/include/mysql
lib := /usr/local/mysql/lib

# Если программное обеспечение MySQL еще не установлено, сделайте такую
замену:

#inc := $(HOME)/mysql-4.0/include
#lib := $(HOME)/mysql-4.0/libmysqld

CC := gcc
CPPFLAGS := -I$(inc) -D_THREAD_SAFE -D_REENTRANT
CFLAGS := -g -W -Wall
LDFLAGS := -static

# Можно изменить -lmysqld на -lmysqlclient для того, чтобы использовать
# обычную клиент-серверную библиотеку

LDLIBS = -L$(lib) -lmysqld -lz -lm -lcrypt
ifneq (,$(shell grep FreeBSD /COPYRIGHT 2>/dev/null))

# Для FreeBSD

LDFLAGS += -pthread
else

# Предполагается Linux

LDLIBS += -lpthread
endif

# Это работает для простых однофайловых тестовых программ

sources := $(wildcard *.c)
objects := $(patsubst %c,%o,$(sources))
targets := $(basename $(sources))
all: $(targets)
clean:
rm -f $(targets) $(objects) *.core

8.4.9.7 Лицензирование встраиваемого сервера

Исходный код MySQL подпадает под действие лицензии GNU GPL (see section G GNU General Public License). Одно из следствий этого заключается в том, что любая программа, включающая (посредством связывания с libmysqld) исходный код MySQL, должна выпускаться как открытое программное обеспечение (под лицензией, совместимой с GPL).

Мы стараемся всячески способствовать всем, кто распространяет открытое программное обеспечение, выпуская код под GPL или совместимой лицензией. Для тех же, кому эти условия не подходят, существует другая возможность - покупка коммерческой лицензии для кода MySQL у компании MySQL AB. Более подробная информация об этом находится в разделе See section 1.6.3 Лицензии на ПО MySQL.

8.5 Интерфейсы C++

MySQL Connector/C++ (или MySQL++) является официальным MySQL API для C++. Больше информации вы можете найти на http://www.mysql.com/products/mysql++/.

8.5.1 Интерфейс Borland C++

Исходный код MySQL можно скомпилировать под Windows с Borland C++ 5.02 (исходный код Windows включает в себя только проекты для Microsoft VC++, а для Borland C++ файлы проекта необходимо сделать самостоятельно).

Одна известная проблема, связанная с Borland C++, заключается в том, что в нем применяется иное, чем в VC++, упорядочивание структур. Это означает, что при попытке использовать имеющуюся по умолчанию библиотеку `libmysql.dll' (которая была скомпилирована с VC++) совместно с Borland C++ вы столкнетесь с проблемами. Избежать этих проблем можно одним из следующих способов.

  • Можно использовать статические библиотеки MySQL для Borland C++, которые находятся на http://www.mysql.com/downloads/os-win32.html.
  • Вызывать функцию mysql_init() только с аргументом NULL, не выделяя предварительно структуру MYSQL.

8.6 Взаимодействие MySQL и Java (JDBC)

Имеется два поддерживаемых драйвера JDBC для MySQL (драйвер Connector/J и драйвер Reisin JDBC). Копию драйвера Connector/J можно найти на http://www.mysql.com/products/connector-j/, а драйвера Reisin - на http://www.caucho.com/projects/jdbc-mysql/index.xtp. По вопросам, касающимся документации, обращайтесь к любой документации по JDBC, а по вопросам, касающимся присущих MySQL специфических особенностей, - к собственной документации по конкретному драйверу.

8.7 Интерфейсы Python API для MySQL

MySQLdb предоставляет поддержку MySQL для Python, в соответствии с интерфейсом баз данных, принятом в Python (Python DB API). Вы можете найти его здесь: http://sourceforge.net/projects/mysql-python/.

8.8 Интерфейсы Tcl API для MySQL

MySQLtcl - это простой API для доступа к базам данным MySQL при помощи Tcl. Вы можете найти его здесь: http://www.xdobry.de/mysqltcl/.

8.9 Оболочка Eiffel для MySQL

Eiffel MySQL - это интерфейс к базам данным MySQL для языка Eiffel, написанный Майклом Рэвитсом (Michael Ravits). Вы можете найти его здесь: http://efsa.sourceforge.net/archive/ravits/mysql.htm.


Справочное руководство по MySQL версии 5.0.0-alpha. - 9 Расширение MySQL

9 Расширение MySQL

9.1 Внутреннее устройство MySQL

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

оставаться в курсе процесса разработки, необходимо выполнять инструкции из раздела See section 2.3.4 Установка из экспериментального набора исходных кодов. Тем, кого интересует внутреннее устройство MySQL, следует подписаться на наш список рассылки internals. Активность этого списка сравнительно невысока. За подробностями относительно подписки, пожалуйста, обращайтесь к разделу See section 1.8.1.1 Списки рассылки MySQL. Все разработчики из MySQL AB участвуют в списке internals, помогая другим людям, работающим над кодом MySQL. Не стесняйтесь использовать этот список как для того, чтобы задавать вопросы по коду, так и для посылки патчей, которые вы бы хотели приобщить к проекту MySQL!

9.1.1 Потоки MySQL

Сервер создает следующие потоки:

  • Поток TCP/IP-соединений обрабатывает все запросы подключения и создает новые выделенные потоки для проведения аутентификации и обработки SQL запросов для каждого соединения.
  • В Windows NT есть поток обслуживания именованного канала, который выполняет ту же работу, что и поток TCP/IP-соединений, но только по запросам на соединение именованного канала.
  • Поток сигналов обрабатывает все сигналы. Обычно этот поток также обрабатывает сигналы таймера и обращается к process_alarm() для принудительного объявления таймаутов на соединениях, которые слишком долго простаивали.
  • Если mysqld скомпилирован с -DUSE_ALARM_THREAD, то создается выделенный поток, обрабатывающий сигналы таймера. Используется только в некоторых системах, в которых возникают проблемы с sigwait(), или если есть необходимость использовать код thr_alarm() в приложении без выделенного потока обработки сигналов.
  • Если применяется опция --flush_time=#, то создается выделенный поток для периодического сбрасывания на диск всех таблиц с заданным интервалом.
  • Каждое соединение имеет свой поток.
  • Каждая отдельная таблица, на которой используется INSERT DELAYED, получает свой отдельный поток.
  • Если применяется --master-host, то запускается поток репликации подчиненного сервера для чтения и применения обновлений от головного.

mysqladmin processlist выводит только потоки соединений, INSERT DELAYED и поток репликации.

9.1.2 Пакет тестирования MySQL

До последнего времени наш основной всесторонний пакет для тестирования основывался на конфиденциальных данных заказчиков и по этой причине не был общедоступным. Процесс тестирования был открытым только частично - доступными являлись тест crash-me, содержащийся в каталоге `sql-bench' код оценки производительности на Perl DBI/DBD, и различные тесты, расположенные в каталоге `tests'. Из-за отсутствия стандартизованного доступного пакета как нашим пользователям, так и разработчикам было сложно выполнять регрессионные тесты кода MySQL. Чтобы решить эту проблему, мы создали новую систему тестирования, которая включается в поставку исходного кода и в двоичную поставку начиная с версии 3.23.29.

При помощи текущего набора контрольных тестов нельзя выполнить всестороннюю проверку MySQL, однако он позволяет обнаружить большинство очевидных ошибок в коде обработки SQL, проблемы ОС/библиотек, а также достаточно полно протестировать репликацию. Нашей конечной целью является создание тестов, охватывающих 100% кода. Мы приветствуем разработки, дополняющие наш тестовый пакет. Пользователи должны быть заинтересованы в том, чтобы добавить к этому пакету тесты, исследующие критические для их систем функциональные возможности, поскольку это будет гарантировать работу всех будущих версий MySQL с их собственными приложениями.

9.1.2.1 Выполнение тестового пакета MySQL

Система тестирования включает в себя интерпретатор языка тестирования (mysqltest), shell-сценарий для выполнения всех тестов (mysql-test-run), сами контрольные тесты, написанные на специальном языке тестирования, и ожидаемые для них результаты. Чтобы запустить тестовый пакет в системе после сборки, необходимо, находясь в корне каталога исходных текстов, ввести make test или mysql-test/mysql-test-run. Если же у вас установлена бинарная поставка, то следует перейти при помощи cd в корень инсталляции (например /usr/local/mysql) и выполнить scripts/mysql-test-run. Все тесты должны пройти успешно. В противном случае следует попробовать отыскать причину неудачи и, если это ошибка MySQL, сообщить о ней. Обращайтесь к разделу See section 9.1.2.3 Отчет об ошибках в тестовом пакете MySQL.

Если на машине, которую необходимо протестировать, работает экземпляр mysqld, то останавливать его не обязательно, лишь бы он не использовал порты 9306 и 9307. Если один из этих портов занят, то нужно отредактировать mysql-test-run и изменить значения для порта головного и/или вспомогательного серверов на номер доступного порта.

Можно выполнить один отдельный контрольный тест посредством mysql-test/mysql-test-run test_name.

Если один из тестов окончился неуспешно, то чтобы узнать, как обстоит дело с оставшимися тестами, следует проводить тестирование, запуская mysql-test-run с опцией --force.

9.1.2.2 Расширение тестового пакета MySQL

Для создания собственных контрольных тестов можно использовать язык mysqltest. К сожалению, полная документация по языку пока еще не написана, но мы планируем в скором времени это сделать. Можно, однако, обратиться к имеющимся контрольным тестам и использовать их в качестве примера. В качестве отправных точек должны служить следующие моменты:

  • Тесты должны быть расположены в mysql-test/t/*.test
  • Контрольные тесты должны состоять из завершающихся точкой с запятой ; команд и должны соответствовать вводу для клиента командной строки mysql. Команда по умолчанию является запросом, который предназначен для посылки серверу MySQL, за исключением тех случаев, когда она распознается как внутренняя команда (напр. sleep).
  • Все запросы, выдающие результаты, - например SELECT, SHOW, EXPLAIN и т.д. должны предваряться @/path/to/result/file. Файл должен содержать ожидаемые результаты. Такой файл результатов можно легко сгенерировать, запустив mysqltest -r < t/test-case-name.test из каталога mysql-test, а затем при необходимости можно отредактировать сгенерированные файлы результатов для подгонки вывода к ожидаемому виду. В этом случае следует быть особенно внимательным, чтобы не добавить или удалить каких-либо невидимых символов - внимательно следите за тем, чтобы только изменялся текст и/или удалялись строки. Если необходимо вставить строку, то нужно следить за тем, чтобы поля были разделены символами жесткой табуляции, и такой же символ жесткой табуляции должен присутствовать в конце. Для проверки того, что текстовый редактор ничего не напутал в процессе редактирования, может пригодиться od -c. Мы, конечно, надеемся, что никому не придется редактировать вывод mysqltest -r, поскольку потребность в этом возникает только в случае обнаружения ошибки.
  • Чтобы получить соответствие нашей конфигурации, следует разместить файлы результатов в каталоге mysql-test/r и назвать их test_name.result. Если тест производит более одного результата, следует использовать test_name.a.result, test_name.b.result и т.д.
  • Если команда возвращает ошибку, то необходимо в предыдущей строке указать --error error-number. error-number может быть списком номеров возможных ошибок, разделенных ','.
  • При написании контрольного теста репликации необходимо в первой строке тестового файла поместить source include/master-slave.inc;. Для переключения между головным и подчиненным серверами используется connection master; и connection slave;. Если что-то требуется сделать на дополнительном соединении, то можно выполнить connection master1; для головного и connection slave1; для подчиненного.
  • Если необходимо что-либо выполнять в цикле, то можно использовать нечто в таком духе:
    let $1=1000;
while ($1)
{
    # здесь выполняются ваши запросы
    dec $1;
}
  • Для паузы между запросами используется команда sleep. Она поддерживает десятые доли секунды, таким образом можно, например, делать sleep 1.3; для временной задержки в 1,3 секунды.
  • Чтобы для определенного контрольного теста запускать подчиненный сервер с дополнительными опциями, нужно поместить эти опции в формате командной строки в mysql-test/t/test_name-slave.opt. Для головного сервера опции помещаются в mysql-test/t/test_name-master.opt.
  • Если у вас возникнут вопросы по тестовому пакету или если вы хотите добавить контрольный тест, шлите e-mail на internals@lists.mysql.com. Поскольку в списке не допускаются присоединенные файлы, все нужные файлы следует положить на: ftp://support.mysql.com/pub/mysql/Incoming/

9.1.2.3 Отчет об ошибках в тестовом пакете MySQL

Если используемая версия MySQL не проходит через тестовый пакет, следует поступать следующим образом:

  • Прежде всего, не отсылайте отчет об ошибке, пока не соберете максимального количества сведений по проблеме, с которой вы столкнулись! Большая просьба к вам - используйте для этого сценарий mysqlbug, чтобы мы имели возможность получить как можно больше информации о вашей системе и версии MySQL (see section 1.8.1.3 Как отправлять отчеты об ошибках или проблемах).
  • Проследите за тем, чтобы в отчет был включен вывод mysql-test-run, а также содержимое всех файлов .reject из каталога mysql-test/r.
  • Если тест из тестового пакета терпит неудачу, проверьте, будет ли он также неуспешным при выполнении его самого по себе:
    cd mysql-test
mysql-test-run --local test-name
    Если тест не проходит, то следует сконфигурировать MySQL с --with-debug и запустить mysql-test-run с опцией --debug. Если он не пройдет и в этом случае, следует положить трассировочный файл `var/tmp/master.trace' на ftp://support.mysql.com/pub/mysql/secret, чтобы мы могли его изучить. Пожалуйста, не забудьте также включить полное описание используемой системы, версию исполняемого файла mysqld и описание того, как он был скомпилирован.
  • Попробуйте также выполнить mysql-test-run с опцией --force, чтобы выяснить, есть ли еще тесты, которые система не проходит.
  • Если вы компилировали MySQL собственноручно, сверьтесь с нашим руководством в той его части, где дается описание компиляции MySQL на используемой платформе или (что более предпочтительно) используйте одну из откомпилированных нами для вас бинарных поставок http://www.mysql.com/downloads/. Все наши стандартные бинарные дистрибутивы должны проходить тестовый пакет!
  • Если получена ошибка, подобная Result length mismatch или Result content mismatch, то это означает, что нет точного совпадения между выходными данными теста и контрольными выходными данными. Это может говорить об ошибке в MySQL или о том, что при некоторых обстоятельствах используемая версия mysqld выдает слегка отличающиеся результаты. Результаты неудачных тестов помещаются в файл с тем же именем, что и у файла результатов, но с расширением .reject. Если контрольный тест терпит неудачу, то по этим двум файлам следует выполнить diff. Если не удается обнаружить, в чем их отличия, исследуйте оба файла с помощью od -c, а также проверьте их размеры.
  • Если тест полностью потерпел фиаско, то для выяснения причины неполадок следует обратиться к файлам журналов в каталоге mysql-test/var/log.
  • Если MySQL был скомпилирован в отладочном режиме, то можно попробовать выполнить отладку, запустив mysql-test-run с опциями --gdb и/или -debug (see section D.1.2 Создание трассировочных файлов). Если MySQL не был скомпилирован для отладки, то это стоит сделать - просто задайте опции --with-debug для configure! Обращайтесь к разделу See section 2.3 Установка исходного дистрибутива MySQL.

9.2 Добавление новых функций в MySQL

Существует два способа добавления функций в MySQL:

  • Можно добавить функцию посредством интерфейса определяемых пользователем функций (user-definable function - UDF). Определяемые пользователем функции добавляются и удаляются динамически с помощью команд CREATE FUNCTION и DROP FUNCTION (see section 9.2.1 Синтаксис CREATE FUNCTION/DROP FUNCTION).
  • Можно добавить функцию как ``родную'' (встроенную) функцию MySQL. ``Родные'' функции компилируются вместе с остальным кодом сервера mysqld и становятся постоянно доступными.

Каждый метод имеет преимущества и недостатки:

  • Если вы пишете определяемую пользователем функцию, то помимо сервера необходимо инсталлировать объектный файл. В этом нет необходимости при компиляции функции вместе с сервером.
  • UDFы можно добавить в бинарную поставку MySQL. Для ``родных'' функций необходимо изменять поставку исходного кода.
  • При обновлении поставки MySQL можно продолжать использовать ранее инсталлированные UDFы. Для ``родных функций нужно при каждом обновлении вносить изменения повторно.

Независимо от выбранного метода добавления новых функций, их можно использовать точно так же, как и встроенные функции, подобные ABS() или SOUNDEX().

9.2.1 Синтаксис CREATE FUNCTION/DROP FUNCTION

CREATE [AGGREGATE] FUNCTION function_name RETURNS {STRING|REAL|INTEGER}
       SONAME shared_library_name

DROP FUNCTION function_name

Определяемая пользователем функция (UDF) - это средство, позволяющее расширить MySQL за счет новой функции, которая работает подобно ``родным'' (встроенным) функциям MySQL, таким как ABS() и CONCAT().

AGGREGATE - новая опция для версии MySQL 3.23. AGGREGATE - функция работает точно так же, как и ``родные'' GROUP-функции MySQL GROUP вроде SUM или COUNT().

CREATE FUNCTION сохраняет имя, тип и имя разделяемой библиотеки функции в системной таблице mysql.func. Чтобы создавать и удалять функции, необходимо обладать привилегиями INSERT и DELETE для базы данных mysql.

Все активные функции подгружаются при каждом запуске сервера, за исключением случая, когда mysqld запускается с опцией --skip-grant-tables. Тогда инициализация UDF пропускается и UDFы недоступны (активная функция - это функция, которая была загружена посредством CREATE FUNCTION и не удалена с помощью DROP FUNCTION).

Инструкции по написанию определяемых пользователем функций находятся в разделе See section 9.2 Добавление новых функций в MySQL. Чтобы механизм UDF работал, функции должны быть написаны на C или C++, используемая операционная система должна поддерживать динамическую загрузку и mysqld должен быть скомпилирован динамически (а не статически).

Отметим, что для того, чтобы работала AGGREGATE, таблица mysql.func должна содержать столбец type. В противном случае следует запустить сценарий mysql_fix_privilege_tables, чтобы внести нужные исправления.

9.2.2 Добавление новой определяемой пользователем функции

Для того чтобы работал механизм UDF, функции должны быть написаны на C или на C++, а используемая операционная система должна поддерживать динамическую загрузку. В поставку исходного кода входит файл `sql/udf_example.cc', в котором определены пять новых функций. К этому файлу следует обращаться, если нужно узнать, как работает соглашение о вызовах UDF.

Чтобы mysqld имел возможность использовать UDF-функции, необходимо сконфигурировать MySQL с --with-mysqld-ldflags=-rdynamic. Причина здесь в том, что на многих платформах (включая Linux) можно загружать динамическую библиотеку (посредством dlopen()) из статически скомпонованной программы, получаемой при использовании --with-mysqld-ldflags=-all-static. Если есть потребность использовать UDF, которой нужно обращаться к символам из mysqld (как в примере функции methaphone из `sql/udf_example.cc', которая использует default_charset_info), то программу необходимо компоновать с -rdynamic (обращайтесь к man dlopen).

Для каждой функции, которую предполагается использовать в командах SQL, следует определять соответствующие функции C (или C++). В дальнейшем в качестве имени для примера функции мы будем использовать имя xxx. Чтобы различать применение в SQL и C/C++, для вызова SQL-функции мы будем использовать обозначение XXX() (прописными), а xxx() (строчными) - для вызова функции C/C++.

Для реализации интерфейса для XXX() требуются следующие функции C/C++:

xxx() (обязательная)
Главная функция. Она вычисляет результат функции. Соответствие между типами SQL и возвращаемым типом функции C/C++ показано в приведенной ниже таблице:
Тип SQL | Тип C/C++
STRING | char *
INTEGER | long long
REAL | double
xxx_init() (необязательная)
Функция инициализации для xxx(). Может быть использована:
  • для проверки количества аргументов к XXX();
  • для проверки того, что аргументы имеют требуемый тип или, в противном случае, для указания MySQL приводить аргументы к нужным типам при вызове главной функции;
  • для распределения всей памяти, требуемой основной функцией;
  • для задания максимальной длины результата;
  • для задания (для REAL-функций) максимального числа десятичных знаков после запятой;
  • для указания, может ли результатом быть NULL.
xxx_deinit() (необязательная)
Функция деинициализации для xxx(). Должна освобождать всю память, выделенную функцией инициализации.

При запуске SQL-команды XXX() MySQL вызывает функцию инициализации xxx_init(), чтобы дать ей возможность выполнить все необходимые установки, такие как проверка аргументов и распределение памяти. Если xxx_init() возвращает ошибку, то выполнение SQL-команды прерывается с сообщением об ошибке, а главная функция и функция деинициализации не вызываются. В противном случае для каждой строки вызывается главная функция xxx(). После того как будут обработаны все строки, вызывается функция деинициализации xxx_deinit(), чтобы выполнить необходимую очистку.

Для агрегатных функций (подобных SUM()) необходимо также подготовить следующие функции:

xxx_reset() (обязательная)
Сбрасывает сумму и обрабатывает аргумент как начальное значение для новой группы.
xxx_add() (обязательная)
Добавляет аргумент к имеющейся сумме.

При использовании агрегатных UDF-функций MySQL работает следующим образом:

  1. Вызывается xxx_init(), чтобы агрегатная функция могла распределить память, которая понадобится для хранения результатов.
  2. Таблица сортируется в соответствии с выражением GROUP BY.
  3. Для первой строки новой группы вызывается функция xxx_reset().
  4. Для каждой новой строки, принадлежащей к той же группе, вызывается функция xxx_add().
  5. Когда группа меняется, или после завершения обработки последней строки вызывается xxx() для получения итога.
  6. Повторяются шаги 3-5, пока не будут обработаны все строки.
  7. Вызывается xxx_deinit(), чтобы UDF могла освободить всю распределенную ею память.

Все функции должны поддерживать многопоточность (не только главная, но также и функции инициализации и деинициализации). Это означает, что непозволительно распределять какие-либо глобальные или статические переменные с изменяющимися значениями! Если требуется память, то ее следует распределять в xxx_init() и освобождать в xxx_deinit().

9.2.2.1 Последовательность вызова UDF для простых функций

Главная функция должна быть определена, как это показано здесь. Обратите внимание на то, что тип возвращаемого значения и параметры варьируются в зависимости от того, как определена SQL-функция XXX() в команде CREATE FUNCTION - как возвращающая STRING, INTEGER или REAL:

Для STRING-функций:

char *xxx(UDF_INIT *initid, UDF_ARGS *args,
      char *result, unsigned long *length,
      char *is_null, char *error);

Для INTEGER-функций:

long long xxx(UDF_INIT *initid, UDF_ARGS *args,
          char *is_null, char *error);

Для REAL-функций:

double xxx(UDF_INIT *initid, UDF_ARGS *args,
       char *is_null, char *error);

Функции инициализации и деинициализации объявляются следующим образом:

my_bool xxx_init(UDF_INIT *initid, UDF_ARGS *args, char *message);

void xxx_deinit(UDF_INIT *initid);

Параметр initid передается всем трем функциям. Он указывает на структуру UDF_INIT, используемую для передачи информации между функциями. Поля структуры UDF_INIT перечислены ниже. Функция инициализации должна заполнять все поля, которые ей следует изменить (чтобы использовать для поля значение по умолчанию, его необходимо оставить в неизменном виде):

my_bool maybe_null
xxx_init() должна устанавливать maybe_null в 1, если xxx() может возвращать NULL. Значение по умолчанию будет 1, если хоть один аргумент объявлен как maybe_null.
unsigned int decimals
Количество знаков после запятой. По умолчанию используется максимальное количество знаков для аргументов, переданных в основную функцию. (Например, если функции передаются 1,34, 1,345 и 1,3, то значением по умолчанию будет 3, поскольку 1,345 имеет 3 знака после запятой.
unsigned int max_length
Максимальная длина строкового результата. Значение по умолчанию зависит от типа результата функции. Для строковых функций по умолчанию используется размер наиболее длинного аргумента. Для целочисленных функций значение по умолчанию составляет 21 цифру. Для вещественных функций по умолчанию берется 13 плюс количество знаков после запятой, которое задается initid->decimals (для числовых функций длина включает знак и символ десятичной точки). Если требуется возвращать значение типа BLOB, то поле можно установить равным либо 65 Kб либо 16 Mб; эта память не распределяется, а применяется для определения того, какой использовать тип столбцов, если понадобится временно хранить данные.
char *ptr
Указатель, используемый функцией по своему усмотрению. Например, функции могут применять initid->ptr для передачи между функциями распределенной памяти. В xxx_init() память распределяется и назначается этому указателю:
initid->ptr = allocated_memory;
В xxx() и xxx_deinit() должны обращаться к initid->ptr для использования или освобождения памяти.

9.2.2.2 Последовательность вызова UDF для агрегатных функций

Ниже приведено описание функций, которые необходимо определить при создании агрегатной UDF-функции.

char *xxx_reset(UDF_INIT *initid, UDF_ARGS *args,
        char *is_null, char *error);

Эта функция вызывается, когда MySQL находит первую строку в новой группе. В функции необходимо сбросить все внутренние переменные, в которых накапливаются значения, и затем установить переданный аргумент как первый аргумент в группе.

Во многих случаях это реализуется путем сброса всех переменных и последующего вызова xxx_add().

char *xxx_add(UDF_INIT *initid, UDF_ARGS *args,
          char *is_null, char *error);

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

Функция xxx() должна быть объявлена точно так же, как это делается при определении простой UDF-функции (see section 9.2.2.1 Последовательность вызова UDF для простых функций).

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

Какая бы то ни было, обработка аргументов в xxx_reset() и xxx_add() должна проводиться точно так же, как для нормальных UDF-функций (see section 9.2.2.3 Обработка аргументов).

Организация возврата значений в xxx() эквивалентна используемой для нормальной UDF (see section 9.2.2.4 Возвращаемые значения и обработка ошибок).

Аргументы-указатели is_null и error одинаковы для всех вызовов xxx_reset(), xxx_add() и xxx(). Их можно использовать для запоминания того, что произошла ошибка, или когда функция xxx() должна возвращать NULL. Заметьте, что сохранять строку в *error нельзя! Это всего лишь 1-байтовый флаг!

is_null сбрасывается для каждой группы (перед вызовом xxx_reset()). error не сбрасывается никогда.

Если is_null или error окажется установленным после xxx(), MySQL вернет NULL в качестве результата групповой функции.

9.2.2.3 Обработка аргументов

Параметр args указывает на структуру UDF_ARGS, содержащую перечисленные ниже поля:

unsigned int arg_count
Количество аргументов. Это значение следует проверять в функции инициализации, если необходимо, чтобы функция вызывалась с определенным количеством аргументов. Например:
if (args->arg_count != 2)
{
    strcpy(message,"XXX() requires two arguments");
    return 1;
}
enum Item_result *arg_type
Тип для каждого аргумента. Возможные значения типа: STRING_RESULT, INT_RESULT и REAL_RESULT. Чтобы контролировать принадлежность аргументов к нужному типу и возвращать ошибку, если это не так, следует проверить массив arg_type в функции инициализации. Например:
if (args->arg_type[0] != STRING_RESULT ||
args->arg_type[1] != INT_RESULT)
{
    strcpy(message,"XXX() requires a string and an integer");
    return 1;
}
В качестве альтернативы требованию, чтобы аргументы были определенного типа, можно использовать функцию инициализации для назначения элементам arg_type выбранных типов. В этом случае MySQL будет приводить аргументы к этим типам для каждого вызова xxx(). Например, чтобы указать на приведение первых двух аргументов к строковому и целочисленному типам, выполните в xxx_init():
args->arg_type[0] = STRING_RESULT;
args->arg_type[1] = INT_RESULT;
char **args
args->args передает в функцию инициализации информацию общего характера об аргументах, с которыми была вызвана функция. Для константного аргумента i args->args[i] указывает на значение аргумента (ниже приведены инструкции о том, как правильно получать доступ к значениям). Для неконстантого аргумента args->args[i] есть 0. Константный аргумент - это выражение, в котором используются только константы, вроде 3 или 4*7-2 или SIN(3.14). Неконстантный аргумент - это выражение, ссылающееся на значения, которые могут изменяться от строки к строке, такие как имена столбцов или обращения к функциям с неконстантными аргументами. Для каждого вызова главной функции args->args содержит фактические аргументы, переданные для обрабатываемой в данный момент строки. Функции могут ссылаться на аргумент i следующим образом:
  • Аргумент типа STRING_RESULT передается в виде указателя на строку плюс длина, чтобы обеспечить обработку двоичных данных или данных произвольной длины. Содержимое строки доступно посредством args->args[i], а длина строки представляет собой args->lengths[i]. Не следует исходить из предположения, что символ \0 отмечает конец строки.
  • Для аргумента типа INT_RESULT необходимо привести args->args[i] к значению типа long long:
    long long int_val;
int_val = *((long long*) args->args[i]);
  • Для аргумента типа REAL_RESULT необходимо привести args->args[i] к значению типа double:
    double real_val;
real_val = *((double*) args->args[i]);
unsigned long *lengths
Для функции инициализации массив lengths указывает максимальную длину строки для каждого аргумента. Изменять этот массив нельзя. При каждом вызове главной функции lengths содержит фактические длины всех строковых аргументов, переданных для обрабатываемой в текущий момент строки. Для типов аргументов INT_RESULT или REAL_RESULT lengths также содержит максимальную длину аргумента (как для функции инициализации).

9.2.2.4 Возвращаемые значения и обработка ошибок

Функция инициализации должна возвращать 0, если ошибок нет, и 1 в противном случае. Если происходит ошибка, xxx_init() должна поместить сообщение об ошибке с завершающим '\0' в параметр message. Сообщение будет возвращено клиенту. Буфер сообщения имеет длину MYSQL_ERRMSG_SIZE символов, но надо стараться, чтобы сообщение не превышало 80 символов - для соответствия ширине стандартного экрана терминала.

Возвращаемое главной функцией xxx() значение является значением функции для функций long long и double. Строковые функции должны возвращать указатель на результат и помещать длину строки в аргумент length.

Эти величины следует устанавливать равными содержимому и длине возвращаемого значения. К примеру:

memcpy(result, "result string", 13);
*length = 13;

Размер буфера result, передаваемого вычислительной функции, составляет 255 байтов. Если этого достаточно для полученного результата, то о распределении памяти для результатов беспокоиться нечего.

Если строковая функция должна возвращать строку длиннее, чем 255 байтов, то для строки необходимо выделять память с помощью malloc() в функции xxx_init() или в функции xxx() и освобождать ее в функции xxx_deinit(). Указатель на распределенную память можно сохранить в поле ptr структуры UDF_INIT, чтобы в последующих вызовах xxx() использовать эту память повторно (see section 9.2.2.1 Последовательность вызова UDF для простых функций.

Чтобы указать в главной функции на возврат значения NULL, is_null устанавливается в 1:

*is_null = 1;

Чтобы указать в главной функции на возврат ошибки, в 1 устанавливается параметр error:

*error = 1;

Если xxx() устанавливает для какой-либо строки *error в 1, то значение функции будет NULL для этой и всех последующих строк, обрабатываемых командой, в которой вызывается XXX() (для последующих строк xxx() даже не будет вызываться). Примечание: в версиях MySQL до 3.22.10 было необходимо устанавливать как *error так и *is_null:

*error = 1;
*is_null = 1;

9.2.2.5 Компиляция и установка определяемых пользователем функций

Файлы, реализующие UDFы, должны компилироваться и устанавливаться на машине, где работает сервер. Эта процедура описана ниже для файла примеров UDF `udf_example.cc', входящего в поставку исходного кода MySQL. Данный файл содержит следующие функции:

  • metaphon() возвращает metaphon-строку для строкового аргумента. Эта строка в общем напоминает soundex-строку, но более приспособлена для английского языка.
  • myfunc_double() возвращает отношение суммы ASCII-значений символов своих аргументов к суммарной длине аргументов.
  • myfunc_int() возвращает суммарную длину своих аргументов.
  • sequence([const int]) возвращает последовательность, начиная с заданного номера, либо с 1, если номер не задан.
  • lookup() возвращает IP-адрес для имени удаленного компьютера.
  • reverse_lookup() возвращает имя удаленного компьютера для IP-адреса. Функция может вызываться для строки "xxx.xxx.xxx.xxx" либо для четырех чисел.

Динамически загружаемый файл должен компилироваться как разделяемый объектный файл с помощью команды следующего вида:

shell> gcc -shared -o udf_example.so myfunc.cc

Корректные опции компилятора для своей системы можно легко получить, запустив следующую команду в каталоге `sql' дерева исходных текстов MySQL:

shell> make udf_example.o

Следует выполнить команду компиляции, подобную приведенной выше make, с той разницей, что надо удалить опцию -c ближе к концу строки и добавить -o `udf_example.so' в конце строки (в некоторых системах, возможно, -c придется оставить в команде).

После компиляции разделяемого объектного файла, содержащего UDFы, следует установить его и дать о нем знать MySQL. В результате компиляции разделяемого объектного модуля из `udf_example.cc' получается файл с именем наподобие `udf_example.so' (точное имя может на разных платформах может быть различным). Скопируйте этот файл в какой-нибудь просматриваемый ld каталог, вроде `/usr/lib'. Во многих системах можно устанавливать переменную окружения LD_LIBRARY или LD_LIBRARY_PATH для указания каталога, в котором размещены файлы UDF-функций. В руководстве по dlopen указывается, какую переменную следует использовать в данной системе. Необходимо сделать соответствующие установки в скриптах запуска mysql.server или safe_mysqld и перезапустить mysqld.

После установки библиотеки следует уведомить mysqld о новых функциях следующими командами:

mysql> CREATE FUNCTION metaphon RETURNS STRING SONAME "udf_example.so";
mysql> CREATE FUNCTION myfunc_double RETURNS REAL SONAME "udf_example.so";
mysql> CREATE FUNCTION myfunc_int RETURNS INTEGER SONAME "udf_example.so";
mysql> CREATE FUNCTION lookup RETURNS STRING SONAME "udf_example.so";
mysql> CREATE FUNCTION reverse_lookup
    -> RETURNS STRING SONAME "udf_example.so";
mysql> CREATE AGGREGATE FUNCTION avgcost
    -> RETURNS REAL SONAME "udf_example.so";

Функции могут быть удалены с помощью DROP FUNCTION:

mysql> DROP FUNCTION metaphon;
mysql> DROP FUNCTION myfunc_double;
mysql> DROP FUNCTION myfunc_int;
mysql> DROP FUNCTION lookup;
mysql> DROP FUNCTION reverse_lookup;
mysql> DROP FUNCTION avgcost;

Команды CREATE FUNCTION и DROP FUNCTION обновляют системную таблицу func в базе данных mysql. В таблицу записываются имя функции, ее тип и имя разделяемой библиотеки. Для создания и удаления функций необходимо обладать привилегиями INSERT и DELETE для базы данных mysql.

Недопустимо использовать CREATE FUNCTION для добавления функции, которая уже была создана. Если необходимо переустановить функцию, ее следует удалить с помощью DROP FUNCTION и затем переустановить посредством CREATE FUNCTION. Эти действия приходится выполнять, например, когда компилируется новая версия данной функции, и надо, чтобы mysqld получил новую версию. Иначе сервер будет продолжать пользоваться старой версией.

Активные функции подгружаются при каждом запуске сервера, за исключением случая, когда mysqld запускается с опцией --skip-grant-tables. Тогда инициализация UDF пропускается и UDFы недоступны (активная функция - это функция, которая была загружена посредством CREATE FUNCTION и не удалена с помощью DROP FUNCTION).

9.2.3 Добавление новых родных функции

В этом разделе приведена процедура добавления новой ``родной'' функции. Следует учитывать, что в бинарную поставку ``родные'' функции добавить невозможно, поскольку эта процедура требует изменения исходного кода MySQL. Поэтому необходимо собственноручно компилировать MySQL из поставки исходного текста. Кроме того, при переходе на другую версию MySQL (например, при выпуске новой версии) все изменения придется повторить для этой новой версии.

Чтобы добавить новую ``родную'' функцию MySQL, необходимо выполнить следующие действия:

  1. Добавьте в `lex.h' одну строку, определяющую имя новой функции в массиве sql_functions[].
  2. Если прототип функции простой (вообще без аргументов или принимает один, два или три аргумента), то в `lex.h' вторым аргументом в массиве sql_functions[] следует указать SYM(FUNC_ARG#) (где # количество аргументов) и добавить в `item_create.cc' функцию, создающую объект функции. В качестве примеров можно рассмотреть ABS и create_funcs_abs(). Если прототип функции сложный (например, принимает переменное число аргументов), то следует добавить две строки в `sql_yacc.yy'. Одна строка служит для указания препроцессору, какой символ должен определить yacc (строку следует добавить в начало файла). Затем определяются параметры функции и правило разбора simple_expr пополняется "элементом" с этими параметрами. Чтобы получить представление о том, как это делается, в качестве примера просмотрите все вхождения ATAN в `sql_yacc.yy'.
  3. В `item_func.h' объявляется класс, наследуемый от Item_num_func или Item_str_func, в зависимости от того, какое значение возвращает функция - числовое или строковое.
  4. В `item_func.cc' добавьте одно из следующих объявлений, в зависимости от того, какая функция определяется - числовая или строковая:
    double Item_func_newname::val()
longlong Item_func_newname::val_int()
String *Item_func_newname::Str(String *str)
    Если объект наследуется от любого стандартного элемента (подобного Item_num_func), то, возможно, потребуется определить только одну из перечисленных выше функций и возложить на родительский объект заботу об остальных функциях. Например, класс Item_str_func определяет функцию val(), выполняющую atof() над значением, возвращенным ::str().
  5. Возможно, понадобится также определить следующую функцию объекта:
    void Item_func_newname::fix_length_and_dec()
    Эта функция должна как минимум вычислять max_length на основе переданных аргументов. max_length является максимальным количеством символов, которое может возвращать функция. Эта функция также должна устанавливать maybe_null = 0, если невозможно, чтобы главная функция возвратила значение NULL. Узнать, может ли какой-либо аргумент функции возвращать NULL, функция может путем проверки поля/переменной maybe_null аргумента. В качестве типичного примера того, как это делается, можно рассмотреть Item_func_mod::fix_length_and_dec.

Все функции должны поддерживать многопоточность (другими словами, непозволительно использовать какие-либо глобальные или статические переменные в функции без их защиты примитивами взаимного исключения).

Если желательно возвращать NULL, из ::val(), ::val_int() или ::str(), то необходимо устанавливать null_value в 1 и возвращать 0.

Для функции объекта ::str() существуют следующие дополнительные аспекты:

  • Аргумент String *str обеспечивает строковый буфер, который может быть использован для размещения результата (дополнительную информацию о типе String можно найти в файле `sql_string.h').
  • Функция ::str() должна возвращать строку, содержащую результат, или (char*) 0, если результат NULL.
  • На сегодняшний день при написании всех строковых функций принято избегать какого бы то ни было распределения памяти, за исключением случаев, когда это абсолютно необходимо!

9.3 Добавление новой процедуры в MySQL

В MySQL, можно определить процедуру на C++, которая обращается к данным в запросе и изменяет их до того, как они будут посланы клиенту. Изменение может быть выполнено на построчном уровне, либо на уровне GROUP BY.

Чтобы продемонстрировать то, как это можно сделать, мы создали пример процедуры в версии MySQL 3.23.

Дополнительно мы рекомендуем обратить внимание mylua. Располагая mylua, можно использовать язык LUA для загрузки процедуры в mysqld во время выполнения.

9.3.1 Процедура Analyse

analyse([max elements,[max memory]])

Эта процедура определена в `sql/sql_analyse.cc'. Она исследует результат запроса и возвращает анализ результатов:

  • max elements (по умолчанию 256) - максимальное число различных значений, которые analyse будет распознавать в столбце. Аргумент используется analyse для проверки того, является ли тип ENUM оптимальным типом столбца.
  • max memory (по умолчанию 8192) - максимальное количество памяти, которую должна выделять analyse для столбца в процессе поиска всех различных значений.
SELECT ... FROM ... WHERE ... PROCEDURE ANALYSE([max elements,[max memory]])

9.3.2 Написание процедуры

На данный момент единственной документацией по этой теме является исходный код.

Всю информацию о процедурах можно найти, изучив следующие файлы:

  • `sql/sql_analyse.cc'
  • `sql/procedure.h'
  • `sql/procedure.cc'
  • `sql/sql_select.cc'


Справочное руководство по MySQL версии 5.0.0-alpha. - A Проблемы и распространенные ошибки

A Проблемы и распространенные ошибки

В этой главе перечислены некоторые распространенные проблемы и сообщения об ошибках, с которыми приходится сталкиваться пользователям. Вы научитесь выяснять, в чем заключается проблема и что следует сделать для ее решения. Кроме того, здесь даны правильные решения некоторых распространенных проблем.

A.1 Как определить, чем вызваны проблемы

При возникновении проблемы прежде всего следует обнаружить ее источник - программу или элемент оборудования:

  • Если присутствует один из следующих симптомов, то проблема, скорее всего, связана с аппаратным обеспечением (с памятью, материнской платой, процессором или жестким диском) либо с ядром:
    • Не работает клавиатура. Обычно ее работоспособность можно проверить по реакции на нажатие Caps Lock. Если индикатор Caps Lock не меняется, то клавиатуру необходимо заменить (прежде чем это сделать, следует попробовать перезагрузить компьютер и проверить все кабели к клавиатуре).
    • Не перемещается курсор мыши.
    • Машина не отвечает на ping-запросы удаленной машины.
    • Различные не связанные между собой программы не работают, как надо.
    • Система неожиданно перезагрузилась (дефектная программа пользовательского уровня никогда не должна быть способна вызвать отказ системы).
    В этом случае необходимо начать с проверки всех кабелей и запуска диагностических средств для проверки аппаратуры! Следует также проверить, нет ли патчей, обновлений, сервисных пакетов (service pack) для используемой операционной системы, при помощи которых вы, возможно, могли бы решить проблемы. Кроме того, следует удостовериться, что у вас установлены достаточно свежие версии библиотек (таких как glibc). Для раннего обнаружения проблем хорошо использовать машину с ECC-памятью!
  • В случае блокировки клавиатуры положение можно исправить, если войти на свою машину с другой машины и выполнить на своей машине kbd_mode -a.
  • Исследуйте свой системный журнальный файл (`/var/log/messages' или т.п.) на предмет причин возникающих проблем. Если есть основания полагать, что проблема - в MySQL, то следует также изучить журнальные файлы MySQL (see section 4.9.3 Журнал обновлений (update)).
  • Если вы считаете, что аппаратные проблемы отсутствуют, следует попробовать обнаружить вызывающую проблемы программу. Попробуйте с помощью top, ps, taskmanager или подобной программы проверить, какая программа забирает все ресурсы процессора или блокирует машину.
  • Проверьте с помощью top, df или подобной программы, нет ли нехватки памяти, дискового пространства, дескрипторов для открытия файлов или каких-либо других критических ресурсов.
  • Если проблема связана с бесконтрольным процессом, то всегда можно попробовать уничтожить его. Если он не хочет уничтожаться, то, вероятно, существует ошибка в операционной системе.

Если после изучения всех возможных причин вы сделали вывод, что источником проблемы является именно MySQL-сервер или клиент, то следует сделать отчет об ошибке для нашего списка рассылки или команды поддержки. В отчете об ошибке постарайтесь дать очень подробное описание поведения системы и свое мнение по поводу происходящего. Следует также объяснить, почему вы считаете, что проблемы вызывает именно MySQL. Примите во внимание все ситуации, описанные в данном разделе. Опишите все проблемы в точности так, как они наблюдаются при исследовании системы. При помещении в отчет для всего вывода программ и/или их сообщений об ошибках и/или подобной информации из журнальных файлов используйте метод "вырезать и вставить"!

Просьба детально описать, какая именно программа не работает, и какие симптомы вы наблюдали! Нам доводилось получать много отчетов об ошибках, где просто утверждалось, что "система не работает", - такие отчеты не давали никакой информации о характере возможной проблемы.

Если программа сбоит, то всегда полезно выяснить:

  • Не вызвала ли данная программа ошибки сегментации (core dump)?
  • Не забирает ли программа все ресурсы процессора? Проверьте с помощью top. Дайте программе немного поработать - возможно, она занимается сложными вычислениями.
  • Если проблемы вызваны именно сервером mysqld, то можно ли выполнить mysqladmin -u root ping или mysqladmin -u root processlist?
  • Что сообщает клиентская программа (попробуйте поработать, например, с mysql) при попытке соединиться с MySQL? Происходит ли заклинивание клиента? Выдает ли программа какой-нибудь вывод?

При посылке отчета об ошибке необходимо придерживаться схемы, описанной в этом руководстве (see section 1.8.1.2 Как задавать вопросы и направлять сообщения об ошибках).

A.2 Распространенные ошибки при использовании MySQL

В этом разделе перечислены некоторые ошибки, с которыми часто приходится сталкиваться пользователям; дается описание этих ошибок и способы их исправления.

A.2.1 Ошибка Access denied

See section 4.2.11 Причины появления ошибок Access denied ("в доступе отказано"). See section 4.2.6 Как работает система привилегий.

A.2.2 Ошибка MySQL server has gone away

Все изложенное в данном разделе относится также и к родственной ошибке Lost connection to server during query.

Наиболее часто ошибка MySQL server has gone away возникает в результате тайм-аута соединения и его закрытия сервером. По умолчанию сервер закрывает соединение по прошествии 8 часов бездействия. Можно изменить лимит времени, установив при запуске mysqld переменную wait_timeout.

Другой распространенной причиной получения ошибки MySQL server has gone away является выдача команды "закрытия" на соединении MySQL с последующей попыткой выполнить запрос на закрытом соединении.

Если это получено в скрипте, то достаточно просто повторить запрос от клиента, чтобы соединение автоматически восстановилось.

Обычно в этом случае выдаются следующие коды ошибки (какой из них вы получите, зависит от ОС):

Код ошибки | Описание
CR_SERVER_GONE_ERROR | Клиент не может послать запрос серверу.
CR_SERVER_LOST | Клиент не получил ошибки при передаче запроса серверу, но он не получил также полного ответа (или хоть какого-то ответа) на запрос.

Ошибка будет также выдана, если кто-нибудь уничтожит выполняющийся поток посредством kill номерпотока.

Проверить, что MySQL на ходу, можно, запустив mysqladmin version и изучив время работы (uptime). Если проблема в аварийном завершении mysqld, то необходимо сосредоточиться на поиске причины аварии. В этом случае следует сначала проверить, не будет ли уничтожен MySQL снова при повторном задании запроса (see section A.4.1 Что делать, если работа MySQL сопровождается постоянными сбоями).

Эти ошибки будут также выдаваться при посылке серверу неверного или слишком длинного запроса. Если mysqld получает неправильный или слишком большой пакет, то сервер предполагает, что с клиентом что-то не так, и закрывает соединение. Если необходимо выполнять объемные запросы (например, при работе с большими столбцами типа BLOB), можно увеличить предельный размер запроса, запустив mysqld с опцией -O max_allowed_packet=# (по умолчанию 1 Mб). Дополнительная память выделяется по требованию, так что mysqld будет выделять больше памяти только в случае, когда выдан большой запрос или когда mysqld должен возвратить большую строку результата!

Вы также можете получить разрыв соединения, если вы отправили пакет больше 16Мб, если ваш клиент старше чем 4.0.8, а ваш сервер 4.0.8 или новее.

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

  • Информацию о том, упал MySQL или нет (это можно определить по файлу hostname.err (see section A.4.1 Что делать, если работа MySQL сопровождается постоянными сбоями).
  • Если определенный запрос уничтожает mysqld, а используемые в нем таблицы перед выполнением запроса проверялись с помощью CHECK TABLE, то желательно составить контрольный тест (see section D.1.6 Создание контрольного примера при повреждении таблиц).
  • Значение переменной wait_timeout в сервере (это значение выдает mysqladmin variables).
  • Информацию о том, пробовали ли вы запускать mysqld с --log и проверять, появляется ли выданный запрос в журнале.

Обращайтесь к разделу See section 1.8.1.2 Как задавать вопросы и направлять сообщения об ошибках.

A.2.3 Ошибка Can't connect to [local] MySQL server

Клиент MySQL на Unix может соединиться с сервером mysqld двумя различными способами: используя либо Unix-сокеты, когда соединение происходит через файл в файловой системе (по умолчанию `/tmp/mysqld.sock'), либо TCP/IP с соединением через номер порта. Unix-сокеты обеспечивают большую скорость, чем TCP/IP, но могут применяться только при соединении с сервером на том же компьютере. Unix-сокеты используются, если не задано имя хоста или если задано специальное имя localhost.

В Windows, если сервер mysqld выполняется в 9x/Me, возможно соединение только через TCP/IP. Если сервер работает на NT/2000/XP и mysqld запущен с --enable-named-pipe, то можно также устанавливать соединение с помощью именованных каналов. Имя именованного канала - MySQL. Если имя хоста не указано при соединении с mysqld, то клиент MySQL сначала попробует подключиться к именованному каналу, а если этого сделать не удастся, то к порту TCP/IP. Можно предписать использование именованных каналов в Windows, используя . в качестве имени хоста.

Ошибка (2002) Can't connect to ... обычно говорит о том, что MySQL не запущен на данной системе или что при попытке соединиться с сервером mysqld используется неверный сокет-файл или порт TCP/IP.

Для начала проверьте (с помощью ps или диспетчера задач в Windows), выполняется ли на сервере процесс с именем mysqld! Если процесса mysqld нет, то его необходимо запустить (see section 2.4.2 Проблемы при запуске сервера MySQL).

Если процесс mysqld выполняется, то можно проверить сервер, пробуя использовать следующие различные соединения (конечно, номер порта и путь сокета для вашей конфигурации могут быть другими):

shell> mysqladmin version
shell> mysqladmin variables
shell> mysqladmin -h `hostname` version variables
shell> mysqladmin -h `hostname` --port=3306 version
shell> mysqladmin -h 'ip for your host' version
shell> mysqladmin --protocol=socket --socket=/tmp/mysql.sock version

Обратите внимание на то, что для hostname используются обратные кавычки вместо прямых; это задает подстановку вывода hostname (т.е. текущего имени хоста) в команду mysqladmin.

Ниже приводится несколько причин, которые могут вызывать ошибку Can't connect to local MySQL server:

  • mysqld не выполняется.
  • Сервер запущен на системе, использующей MIT-потоки. При работе на системе, в которой отсутствуют "родные" потоки, mysqld использует пакет MIT-pthreads (see section 2.2.5 Операционные системы, поддерживаемые MySQL). Однако не во всех версиях MIT-потоков поддерживаются Unix-сокеты. В системе без поддержки сокетов при соединении с сервером всегда необходимо явно указывать имя хоста. Попробуйте проверить соединение с сервером с помощью следующей команды:
    shell> mysqladmin -h `hostname` version
  • Кто-либо удалил Unix-сокет, используемый mysqld (по умолчанию `/tmp/mysqld.sock'). Возможно, есть задание cron, которое удаляет сокет MySQL (например, задание, удаляющее старые файлы в каталоге `/tmp'). В таком случае всегда можно выполнить mysqladmin version и проверить, действительно ли существует сокет, который используется mysqladmin. Решение здесь заключается в следующем: можно либо изменить задание cron с тем, чтобы оно не удаляло `mysqld.sock', либо поместить сокет в каком-нибудь другом месте (see section A.4.5 Как защитить или изменить сокет-файл MySQL `/tmp/mysql.sock').
  • Сервер mysqld запущен с опцией --socket=/path/to/socket. Если путь к сокету для сервера был изменен, то необходимо уведомить о новом пути и клиентов MySQL. Это можно сделать, передав клиенту путь к сокету в качестве аргумента. see section A.4.5 Как защитить или изменить сокет-файл MySQL `/tmp/mysql.sock'.
  • Используется Linux, и один из потоков аварийно завершился (core dump). В этом случае, перед тем как заново запустить MySQL, необходимо уничтожить все остальные потоки mysqld (например, с помощью сценария mysql_zap). Обращайтесь к разделу See section A.4.1 Что делать, если работа MySQL сопровождается постоянными сбоями.
  • Возможно, пользователь, от которого запущен MySQL-сервер, не имеет привилегий чтения и записи для каталога, содержащего сокет-файл, либо для самого сокет-файла. В этом случае необходимо либо изменить привилегии для каталога/файла, либо перезапустить mysqld, так чтобы сервер использовал каталог, к которому пользователь имеет доступ.

Если получено сообщение об ошибке Can't connect to MySQL server on some_hostname, то чтобы выяснить, в чем проблема, можно попробовать выполнить следующие действия:

  • Проверить, запущен ли сервер, выполнив telnet your-host-name tcp-ip-port-number, и несколько раз нажать Enter. Если MySQL работает на этом порту, то должен быть получен ответ, включающий номер версии запущенного сервера. Если будет выдана ошибка вроде telnet: Unable to connect to remote host: Connection refused, то на указанном порту сервер не работает.
  • Попробуйте соединиться с демоном mysqld на локальной машине и проверьте с помощью mysqladmin variables, какой порт TCP/IP сконфигурирован для использования mysqld (переменная port).
  • Проверьте, не запускается ли сервер mysqld с опцией --skip-networking.

A.2.4 Ошибка Host '...' is blocked

Ошибка, подобная следующей:

Host 'hostname' is blocked because of many connection errors.
Unblock with 'mysqladmin flush-hosts'

говорит о том, что от хоста hostname имело место большое количество (max_connect_errors) прерванных посредине запросов на соединение к mysqld. После max_connect_errors неудачных запросов mysqld делает предположение, что что-то не так (может, атака от кракера), и блокирует последующие соединения с узла до того момента, пока кто-нибудь не выполнит команду mysqladmin flush-hosts.

По умолчанию mysqld блокирует хост после 10 ошибок соединения. Это значение можно легко отрегулировать, запустив сервер следующим образом:

shell> safe_mysqld -O max_connect_errors=10000 &

Заметим, что если для некоторого хоста получено это сообщение об ошибке, то следует сначала проверить, все ли в порядке с TCP/IP-соединениями от этого хоста. Если TCP/IP-соединения не работают, то увеличивать значение переменной max_connect_errors бесполезно!

A.2.5 Ошибка Too many connections

Получение ошибки Too many connections при попытке соединиться с MySQL означает, что уже есть max_connections клиентов, соединившихся с сервером mysqld.

Если есть потребность в большем количестве соединений, чем задано по умолчанию (100), то следует перезапустить mysqld с заданием большего значения для переменной max_connections.

Заметим, что фактически mysqld разрешает соединяться (max_connections+1) клиентам. Последнее соединение зарезервировано для пользователя с привилегией SUPER. Если не наделять этой привилегией обычных пользователей (они могут обойтись и без нее), то администратор, располагая этой привилегией, может войти и использовать SHOW PROCESSLIST для выяснения причин неполадок (see section 4.5.6.6 SHOW PROCESSLIST).

Максимальное число соединений MySQL зависит от того, насколько хорошей является библиотека потоков на данной платформе. Linux или Solaris должны быть в состоянии поддерживать 500-1000 одновременных соединений, в зависимости от количества имеющейся памяти и того, чем занимаются клиенты.

A.2.6 Ошибка Some non-transactional changed tables couldn't be rolled back

Получение ошибки/предупреждения: Warning: Some non-transactional changed tables couldn't be rolled back при попытке сделать ROLLBACK означает, что для некоторых использованных в транзакции таблиц не поддерживаются транзакции. Команда ROLLBACK на эти нетранзакционные таблицы не подействует.

Наиболее типичный случай возникновения такой ошибки связан с попыткой создать таблицу, тип которой не поддерживается бинарником mysqld. Если mysqld не поддерживает тип таблиц (или тип таблиц отключен опцией при запуске), то сервер создаст таблицу с типом, наиболее близким к запрошенному (скорее всего, MyISAM).

Чтобы проверить тип таблицы, следует выполнить:

SHOW TABLE STATUS LIKE 'table_name'. See section 4.5.6.2 SHOW TABLE STATUS.

Можно проверить, какие расширения поддерживает исполняемый файл mysqld, выполнив:

show variables like 'have_%'. See section 4.5.6.4 SHOW VARIABLES.

A.2.7 Ошибка Out of memory

По выданному запросу может быть получена ошибка следующего вида:

mysql: Out of memory at line 42, 'malloc.c'

mysql: needed 8136 byte (8k), memory in use: 12481367 bytes (12189k)

ERROR 2008: MySQL client ran out of memory

Как видим, в ней есть ссылка на MySQL-клиент mysql. Причина этой ошибки в том, что клиенту просто не хватает памяти для размещения всего результата.

Чтобы устранить данную проблему, сначала проверьте правильность запроса. Действительно ли есть необходимость в том, чтобы запрос возвращал так много строк? Если да, то можно использовать mysql --quick, где для извлечения результирующего множества применяется mysql_use_result(). При этом уменьшается загрузка клиента (но увеличивается загрузка сервера).

A.2.8 Ошибка Packet too large

Когда клиент MySQL или сервер mysqld получают пакет с размерами, превышающими max_allowed_packet байтов, программа выдает ошибку Packet too large и закрывает соединение.

В MySQL 3.23 размер самого большого возможного пакета составляет 16 Mб (из-за ограничений клиент-серверного протокола). В MySQL 4.0.1 и выше размер пакета ограничивается только количеством имеющейся на сервере памяти (вплоть до теоретического максимума в 2 Гб).

Коммуникационный пакет - это одна команда SQL, посылаемая серверу, или одна строка, посылаемая клиенту.

Когда клиент MySQL или сервер mysqld получают пакет, размеры которого превышают max_allowed_packet байтов, программа выдает ошибку Packet too large и закрывает соединение. Если коммуникационный пакет слишком велик, то в некоторых клиентах может быть выдана ошибка Lost connection to MySQL server during query.

Отметим, что и клиент, и сервер имеют свои собственные переменные max_allowed_packet. Если требуется обрабатывать большие пакеты, то эту переменную необходимо увеличить как для клиента, так и для сервера.

Увеличение переменной не опасно, поскольку память выделяется только при необходимости; эта переменная скорее является мерой предосторожности для "отлавливания" неправильных пакетов между клиентом и сервером, а также для того, чтобы предупредить ситуацию нехватки памяти, вследствие случайного использования больших пакетов.

Если используется клиент mysql, то можно задать больший буфер, запустив клиент посредством mysql --set-variable=max_allowed_packet=8M. Для других клиентов существуют собственные методы установки этой переменной. Обратите внимание, что начиная с 4.0 использование --set-variable не рекомендуется, используйте просто --max-allowed-packet=8M.

Для установки max_allowed_packet большего размера в mysqld можно также использовать файл опций. Например, если в таблице предполагается хранить значение типа MEDIUMBLOB максимальной длины, то нужно запускать сервер с опцией set-variable=max_allowed_packet=16M.

При использовании больших пакетов могут также возникать непредсказуемые проблемы, если вы работаете с большими значениями типа BLOB, и mysqld не был предоставлен доступ к достаточному объему памяти для обработки запроса. Если есть подозрение, что дело в этом, попробуйте добавить ulimit -d 256000 в начале скрипта safe_mysqld и перезапустить mysqld.

A.2.9 Коммуникационные ошибки / Оборванные соединения

Начиная с MySQL 3.23.40 ошибка Aborted connection выдается только в случае, если mysqld запущен с --warnings.

В журнале ошибок могут присутствовать ошибки наподобие этой:

010301 14:38:23 Aborted connection 854 to db: 'users' user: 'josh'

(see section 4.9.1 Журнал ошибок).

Такие ошибки сигнализируют об одной из следующих ситуаций:

  • Клиентская программа не выполнила mysql_close() перед выходом.
  • Клиент бездействовал на протяжении более чем wait_timeout или interactive_timeout (see section 4.5.6.4 SHOW VARIABLES).
  • Клиентская программа внезапно завершилась посреди передачи.

В подобных ситуациях увеличивается значение переменной сервера Aborted_clients.

Значение переменной сервера Aborted_connects увеличивается в следующих случаях:

  • Когда пакет соединения содержит неверную информацию.
  • Когда пользователь не имеет привилегий для соединения с базой данных.
  • Когда пользователь использует неверный пароль.
  • Когда на получение пакета соединения уходит более connect_timeout секунд. See section 4.5.6.4 SHOW VARIABLES.

Обратите внимание: все перечисленное выше может свидетельствовать о попытке взлома базы данных!

Ниже перечислены другие причины проблем, которые могут возникнуть с оборванными клиентами или разорванными соединениями.

  • Использование как полудуплексного, так и полного дуплексного Ethernet-протокола под Linux. Данная ошибка присутствует во многих Linux-драйверах Ethernet. Выполните тест на данную ошибку - для этого следует передать очень большой файл через ftp-соединение между этими двумя машинами. Если передача проходит в режиме всплеск-пауза-всплеск-пауза ..., то можно констатировать наличие дуплексного синдрома Linux. Единственное решение проблемы - отключить как полу-, так и полнодуплексную передачу на концентраторах и коммутаторах.
  • Некоторая проблема с библиотекой потоков, вызывающая прерывания при чтении.
  • "Криво" сконфигурированный TCP/IP.
  • Дефектные Ethernet-карты, концентраторы, коммутаторы или кабели... Такие проблемы можно как следует диагностировать только путем замены оборудования.
  • max_allowed_packet слишком мала, или запросам требуется памяти больше, чем было выделено для mysqld (see section A.2.8 Ошибка Packet too large).

A.2.10 Ошибка The table is full

Существует несколько случаев, когда выдается эта ошибка:

  • Используется старая версия MySQL (до 3.23.0), а размещенная в памяти временная таблица становится больше, чем tmp_table_size байтов. Для решения этой проблемы можно использовать опцию -O tmp_table_size=#, чтобы mysqld увеличил размер временных таблиц, или опцию SQL SQL_BIG_TABLES, перед тем как выдать сомнительный запрос (see section 5.5.6 Синтаксис команды SET). Можно также запускать mysqld с опцией --big-tables - эффект здесь будет таким же, как и от использования SQL_BIG_TABLES для всех запросов. В версии MySQL 3.23 размещенные в памяти временные таблицы после того, как размер таблицы превысит tmp_table_size, автоматически преобразуются в расположенные на диске таблицы типа MyISAM.
  • Используются таблицы InnoDB и исчерпалось место в табличном пространстве InnoDB. В таком случае следует увеличить табличное пространство InnoDB.
  • Используются таблицы ISAM или MyISAM в операционной системе, которая поддерживает файлы размером до 2 Гб, и файл данных или индексный файл достигли этого предела.
  • Используются таблицы MyISAM, и размер требуемых данных или индекса превышает тот, который предусматривался MySQL при выделении указателей (если MAX_ROWS не указано в CREATE TABLE, MySQL выделяет указатели, предусматривающие размещение только 4 Гб данных). Проверить максимальные размеры данных/индекса можно посредством
    SHOW TABLE STATUS FROM database LIKE 'table_name';
    или с помощью myisamchk -dv база_данных/таблица. Если проблема связана с указателями, то это можно исправить с помощью команды наподобие следующей:
    ALTER TABLE table_name MAX_ROWS=1000000000 AVG_ROW_LENGTH=nnn;
    Указывать AVG_ROW_LENGTH нужно только для таблиц с полями типа BLOB/TEXT, поскольку в этом случае MySQL не может оптимизировать требуемое пространство, исходя только из количества строк.

A.2.11 Ошибка Can't create/write to file

Получение для некоторых запросов ошибки вида:

Can't create/write to file '\\sqla3fe_0.ism'.

означает, что MySQL не может создать в заданном временном каталоге временный файл для результирующего набора (приведенное сообщение об ошибке типично для Windows, примерно такой же вид имеет сообщение об ошибке Unix). Чтобы решить проблему, запустите mysqld с --tmpdir=path или добавьте в своем файле опций:

[mysqld]
tmpdir=C:/temp

исходя из предположения, что каталог `c:\\temp' существует (see section 4.1.2 Файлы параметров `my.cnf').

Проверьте также код полученной ошибки с помощью perror. Одной из причин также может быть ошибка переполнения диска;

shell> perror 28
Error code 28: No space left on device

A.2.12 Ошибка в клиенте Commands out of sync

Если получена ошибка Commands out of sync; you can't run this command now в клиентском коде, то клиентские функции вызываются в неправильном порядке!

Это может произойти, например, если используется mysql_use_result() и делается попытка выполнить новый запрос до того, как вызвана mysql_free_result(), или если клиент пытается выполнить два возвращающих данные запроса без обращения к mysql_use_result() либо mysql_store_result() в промежутке между ними.

A.2.13 Ошибка Ignoring user

Получение следующей ошибки:

Found wrong password for user: 'some_user@some_host'; ignoring user

означает, что при запуске mysqld или при перезагрузке таблиц привилегий сервер нашел в таблице user запись с неправильным паролем и в результате запись просто игнорируется системой привилегий.

Причины проблемы и способы ее решения могут быть следующими:

  • Возможно, работает новая версия mysqld со старой таблицей user. Это можно проверить путем выполнения mysqlshow mysql user, чтобы посмотреть, короче ли поле пароля, чем 16 символов. Если это так, то положение можно исправить, запустив сценарий `scripts/add_long_password'.
  • У пользователя старый пароль (длиной в 8 символов), а mysqld запущен без опции --old-protocol. Обновите данные пользователя в таблице user, задав новый пароль, или перезапустите mysqld с --old-protocol.
  • Пароль был установлен в таблице user без применения функции PASSWORD(). Воспользуйтесь mysql для обновления пароля пользователя в таблице user. Позаботьтесь о том, чтобы была использована функция PASSWORD():
    mysql> UPDATE user SET password=PASSWORD('your password')
    ->             WHERE user='XXX';

A.2.14 Ошибка Table 'xxx' doesn't exist

Получение ошибки Table 'xxx' doesn't exist или Can't find file: 'xxx' (errno: 2), означает, что в текущей базе данных не существует таблицы с именем xxx.

Обратите внимание: поскольку в MySQL для хранения баз данных и таблиц используются каталоги и файлы, то имена баз данных и каталогов являются зависимыми от регистра символов! (Под Windows имена баз данных и таблиц не зависят от регистра символов, но для всех ссылок на заданную таблицу в пределах запроса должен использоваться одинаковый регистр!)

Проверить, какие таблицы имеются в текущей базе данных, можно с помощью SHOW TABLES. see section 4.5.6 Синтаксис команды SHOW.

A.2.15 Ошибка Can't initialize character set xxx

Получение ошибки наподобие:

MySQL Connection Failed: Can't initialize character set xxx

Означает, что имеется одна из следующих ситуаций:

  • Кодировка является многобайтовой и не поддерживается клиентом. В этом случае необходимо перекомпилировать клиент с --with-charset=xxx или с --with-extra-charsets=xxx (see section 2.3.3 Типичные опции configure). Весь стандартный бинарный код MySQL откомпилирован с --with-extra-character-sets=complex, что обеспечивает поддержку всех многобайтовых кодировок (see section 4.6.1 Набор символов, применяющийся для записи данных и сортировки).
  • Кодировка является простой кодировкой, не скомпилированной в mysqld, и файлы определения кодировки находятся не там, где рассчитывает их найти клиент. В этом случае необходимо:
    • Перекомпилировать клиент с поддержкой этой кодировки (see section 2.3.3 Типичные опции configure).
    • Указать клиенту, где расположены файлы определения кодировки. Для многих клиентов это можно сделать с помощью опции --character-sets-dir=path-to-charset-dir.
    • Скопировать файлы определения кодировки туда, где, по мнению клиента, они должны находиться.

A.2.16 Не найден файл (File not found)

Получение от MySQL ERROR '...' not found (errno: 23), Can't open file: ... (errno: 24), или любой другой ошибки с номером 23 или 24 означает, что для MySQL выделено недостаточно файловых дескрипторов. Можно использовать утилиту perror для получения описания ошибки с определенным номером:

shell> perror 23
File table overflow
shell> perror 24
Too many open files
shell> perror 11
Resource temporarily unavailable

Проблема здесь в том, что mysqld пытается одновременно держать открытыми слишком много файлов. Можно либо указать mysqld не открывать так много файлов одновременно, либо увеличить количество файловых дескрипторов, доступных mysqld.

Чтобы предписать mysqld держать одновременно открытыми меньше файлов, можно уменьшить табличный кэш, задав safe_mysqld опцию -O table_cache=32 (значение по умолчанию 64). Уменьшение значения max_connections также уменьшит количество открытых файлов (по умолчанию значение переменной 90).

Чтобы изменить число доступных mysqld файловых дескрипторов, можно использовать опцию --open-files-limit=# в safe_mysqld или опцию -O open-files-limit=# в mysqld (see section 4.5.6.4 SHOW VARIABLES). Проще всего это сделать путем добавления опции в файл опций (see section 4.1.2 Файлы параметров `my.cnf'). Если используется ранняя версия mysqld, не поддерживающая эту возможность, можно отредактировать скрипт safe_mysqld. В скрипте есть закомментированная строка ulimit -n 256; можно, убрав символ `#', раскомментировать эту строку и, заменив значение 256 другим, повлиять на количество доступных mysqld файловых дескрипторов.

При помощи ulimit (и open-files-limit) можно увеличить количество файловых дескрипторов только до предела, установленного в операционной системе. Существует также "жесткий" предел, который может быть переопределен только при запуске safe_mysqld или mysqld от имени пользователя root (но помните, что в этом случае также следует использовать опцию --user=...). Если необходимо увеличить предел ОС по количеству доступных отдельному процессу файловых дескрипторов, обращайтесь к документации по своей операционной системе.

Обратите внимание: при использовании tcsh ulimit работать не будет! Кроме того, tcsh будет сообщать неверные значения при запросе текущих пределов! В этом случае необходимо запускать safe_mysqld с использованием sh!

A.3 Вопросы, связанные с инсталляцией

A.3.1 Проблемы при линковании с клиентской библиотекой MySQL

Если при линковании программы получены ошибки неразрешенных ссылок на символы, имена которых начинаются с mysql_, подобные следующим:

/tmp/ccFKsdPa.o: In function `main':
/tmp/ccFKsdPa.o(.text+0xb): undefined reference to `mysql_init'
/tmp/ccFKsdPa.o(.text+0x31): undefined reference to `mysql_real_connect'
/tmp/ccFKsdPa.o(.text+0x57): undefined reference to `mysql_real_connect'
/tmp/ccFKsdPa.o(.text+0x69): undefined reference to `mysql_error'
/tmp/ccFKsdPa.o(.text+0x9a): undefined reference to `mysql_close'

то их можно устранить, добавив -Lpath-to-the-mysql-library -lmysqlclient в самом конце используемой команды линкования.

Если выдаются ошибки undefined reference для функции uncompress или compress, добавьте в самом конце команды линкования -lz и повторите попытку!

Если получены ошибки undefined reference для функций, которые должны присутствовать в системе, таких как connect, то сверьтесь по странице руководства для данной функции, какие библиотеки необходимо добавить в команде линкования!

Получение ошибок undefined reference для функций, отсутствующих в используемой системе, наподобие следующего:

mf_format.o(.text+0x201): undefined reference to `__lxstat'

обычно означает, что библиотека скомпилирована в системе, которая не на 100% совместима с системой пользователя. В этом случае необходимо загрузить последнюю поставку с исходными текстами MySQL и откомпилировать библиотеку самостоятельно (see section 2.3 Установка исходного дистрибутива MySQL).

Если при попытке выполнить программу выдаются ошибки о ненайденных символах, начинающихся с mysql_, или о том, что не удается найти библиотеку mysqlclient, то это означает, что система не может найти динамической библиотеки `libmysqlclient.so'.

Чтобы исправить это, необходимо предписать системе проводить поиск динамических библиотек в каталоге с клиентской библиотекой MySQL. Это можно сделать одним из следующих способов:

  • Добавить в переменную окружения LD_LIBRARY_PATH путь к каталогу, содержащему `libmysqlclient.so'.
  • Добавить в переменную окружения LD_LIBRARY путь к каталогу, содержащему `libmysqlclient.so'.
  • Скопировать `libmysqlclient.so' в каталог, просматриваемый системой при поиске библиотек, таких как `/lib', и обновить информацию о распределенных библиотеках, выполнив ldconfig.

Другой способ решения этой проблемы заключается в статическом линковании программы с использованием -static, или в удалении динамических библиотек MySQL до линкования своего кода. Во втором случае необходимо удостовериться, что динамические библиотеки не используются другими программами!

A.3.2 Запуск MySQL от обычного пользователя

Сервер mysqld может запускаться и работать от любого пользователя. Чтобы настроить mysqld для работы под Unix-пользователем user_name, необходимо выполнить следующие действия:

  1. Если сервер работает, остановите его (используйте mysqladmin shutdown).
  2. Измените каталоги и файлы баз данных так, чтобы user_name имел привилегии для чтения и записи файлов в этих каталогах (возможно, это нужно будет делать из Unix-аккаунта root):
    shell> chown -R user_name /path/to/mysql/datadir
    Если среди каталогов или файлов в каталоге данных MySQL присутствуют символические ссылки, то нужно будет также перейти по этим ссылкам и изменить каталоги и файлы, на которые они указывают. chown -R может не отработать символических ссылок.
  3. Запустите сервер из аккаунта user_name или, если у вас MySQL 3.22 и выше, запустите mysqld из Unix-аккаунта root и используйте опцию --user=user_name. mysqld переключится на выполнение в контексте Unix-пользователя user_name до того, как начнет обслуживать запросы на соединение.
  4. Чтобы запускать сервер от имени данного пользователя автоматически в ходе загрузки системы, добавьте строку user, указывающую имя пользователя, в группе [mysqld] файла опций `/etc/my.cnf' или файла опций `my.cnf' из каталога данных сервера. Например:
    [mysqld]
user=user_name

К этому моменту процесс mysqld должен без помех работать под Unix-пользователем user_name. Однако содержимое таблиц привилегий не изменяется. По умолчанию (сразу после выполнения скрипта инсталляции таблиц привилегий mysql_install_db) MySQL-пользователь root является единственным пользователем с правами на доступ к базе данных mysql, а также на создание и удаление баз данных. Если вы не меняли этих полномочий, они по-прежнему действительны. То, что вы вошли в систему как Unix-пользователь, отличный от root, не может вам помешать получить доступ к MySQL в качестве MySQL-пользователя root; просто задайте клиентской программе опцию -u root.

Отметим, что работа с MySQL в качестве MySQL-пользователя root посредством указания -u root в командной строке не имеет ничего общего с выполнением MySQL под Unix-пользователем root, или вообще под каким бы то ни было Unix-пользователем. Привилегии доступа и имена пользователей MySQL никак не связаны с именами Unix-пользователей. Единственная связь с именами Unix-пользователей заключается в том, что если при запуске клиентской программы не задана опция -u, то клиент попытается соединиться, используя в качестве имени MySQL-пользователя имя Unix-аккаунта.

Если Unix-сервер не слишком хорошо защищен или не нуждается в повышенных мерах безопасности, следует как минимум установить в таблицах привилегий пароль для MySQL-пользователя root. В противном случае любой пользователь с аккаунтом на данной машине сможет запустить mysql -u root db_name и делать в MySQL все, что ему заблагорассудится.

A.3.3 Проблемы с правами доступа к файлам

Если существуют проблемы с правами доступа к файлам, например, если mysql при создании таблицы выдает следующее сообщение об ошибке:

ERROR: Can't find file: 'path/with/filename.frm' (Errcode: 13)

то, возможно, при запуске сервера mysqld неправильно устанавливается переменная окружения UMASK. По умолчанию значение umask 0660. Его можно изменить, запуская safe_mysqld следующим образом:

shell> UMASK=384 # = 600 in octal
shell> export UMASK
shell> /path/to/safe_mysqld &

По умолчанию MySQL создает каталоги баз данных и RAID-каталоги с правами доступа 0700. Такое поведение можно изменить, установив переменную UMASK_DIR. Если установить эту переменную, то при создании новых каталогов используется комбинация UMASK и UMASK_DIR. Например, если требуется, чтобы доступ ко всем новым каталогам получала группа, то можно выполнить:

shell> UMASK_DIR=504 # = 770 in octal
shell> export UMASK_DIR
shell> /path/to/safe_mysqld &

В версии MySQL 3.23.25 и выше MySQL предполагает, что значения для UMASK и UMASK_DIR, начинающиеся с нуля, восьмеричные.

see section E Переменные окружения.

A.4 Вопросы, связанные с администрированием

A.4.1 Что делать, если работа MySQL сопровождается постоянными сбоями

Перед официальным выпуском все версии MySQL тестируются на многих платформах. Это не означает, что в MySQL совсем нет ошибок, но если они и есть, то мало, и их не так просто отыскать. В любом случае, столкнувшись с какой-либо проблемой, всегда полезно попытаться точно определить, что вызывает аварию системы, - тогда шансы, что проблема будет устранена в скором времени, станут значительно выше.

Сначала надо попробовать локализовать проблему. Определите, что происходит: то ли демон mysqld прекращает работу, то ли проблема связана с клиентом. Узнать, сколько времени сервер mysqld уже работает, можно, выполнив mysqladmin version. Если mysqld прекратил выполнение, то для выяснения причин можно изучить файл `mysql-data-directory/`hostname`.err' (see section 4.9.1 Журнал ошибок).

Причиной многих аварий MySQL являются поврежденные индексные файлы или файлы данных. MySQL обновляет данные на диске, используя системный вызов write(), после каждой команды SQL и до того, как клиент будет уведомлен о результате (однако при выполнении с delay_key_write это не так: записываются только данные). Отсюда следует, что данные не пострадают даже в случае аварийного завершения mysqld, поскольку ОС позаботится о том, чтобы те данные, которые не сброшены, были записаны на диск. Можно заставить MySQL сбрасывать все на диск после каждой SQL-команды, запустив mysqld с --flush.

Все это означает, что обычно таблицы не должны повреждаться; исключение составляют следующие случаи:

  • Кто-нибудь/что-нибудь убьет процесс mysqld или выключит машину посреди операции обновления.
  • Проявила себя ошибка в mysqld, вызывающая прекращение его выполнения посреди операции обновления.
  • Кто-нибудь работает с файлами данных или индексными файлами вне mysqld и при этом не делает блокировку таблиц как следует.
  • Если работает несколько серверов mysqld с одними данными на системе без пристойной поддержки блокировок файловой системы (обычно реализуется демоном lockd) или если выполняется несколько серверов со --skip-external-locking
  • Существует поврежденный индексный файл или файл данных, содержащий очень неправильные данные, которые вводят в заблуждение mysqld.
  • Проявила себя в коде записи данных. Это маловероятно, но в общем случае возможно. В этом случае можно попробовать изменить формат файла на соответствующий другому обработчику баз данных, используя ALTER TABLE на исправленной копии таблицы!

Поскольку найти причину сбоя всегда непросто, сначала можно попробовать выяснить, что из того, что работает у других, вызывает аварии у вас. Попытайтесь выполнить следующие действия:

  • Остановите демон mysqld с помощью mysqladmin shutdown, выполните myisamchk --silent --force */*.MYI на всех таблицах и перезапустите демон mysqld. Этим гарантируется безошибочность исходного состояния (see section 4 Администрирование баз данных).
  • Используйте mysqld --log и попытайтесь определить по информации в журналах, не вызвано ли прекращение работы сервера каким-либо специфическим запросом. Около 95% всех ошибок обусловлены конкретными запросами! Обычно это один из последних запросов в журнальном файле непосредственно до перезапуска MySQL (see section 4.9.2 Общий журнал запросов). Если вы сумеете повторно вызвать отказ MySQL при помощи одного из запросов, даже когда таблицы были проверены непосредственно перед выполнением запроса, то возможна локализация ошибки и подготовка отчета об ошибке! see section 1.8.1.3 Как отправлять отчеты об ошибках или проблемах.
  • Попробуйте сделать контрольный тест, который мы могли бы использовать, чтобы воспроизвести проблему (see section D.1.6 Создание контрольного примера при повреждении таблиц).
  • Попробуйте выполнить входящий в поставку тест mysql-test и тесты производительности MySQL (see section 9.1.2 Пакет тестирования MySQL). Эти тесты должны довольно хорошо протестировать MySQL. Вы можете также добавить в тесты производительности код для имитации своего приложения! Тесты производительности можно найти в каталоге bench в поставке с исходными кодами или, в случае бинарной поставки, в подкаталоге sql-bench своего каталога инсталляции MySQL.
  • Попробуйте fork_test.pl и fork2_test.pl.
  • Если что-то пойдет не так, то собирать информацию о возможных ошибках будет значительно проще, если MySQL сконфигурирован для отладки. Переконфигурируйте MySQL, применяя configure с опцией --with-debug или --with-debug=full, и затем перекомпилируйте (see section D.1 Отладка сервера MySQL).
  • Конфигурирование MySQL в отладочном режиме приводит к включению безопасного распределителя памяти, который может находить некоторые ошибки. Помимо этого, отладочная версия выдает большое количество информации о том, что происходит.
  • Выясните, применены ли последние патчи для используемой операционной системы.
  • Используйте опцию --skip-external-locking к mysqld. На некоторых системах менеджер блокировок lockd не работает как следует; опция --skip-external-locking указывает mysqld не применять внешнюю блокировку (это означает, что нельзя выполнять два сервера mysqld на одних данных и что необходимо быть осторожным при использовании myisamchk, однако применение этой опции может принести большую пользу для целей тестирования).
  • Если возникнет ситуация, когда кажется, что mysqld запущен, но не отвечает, стоит попробовать выполнить mysqladmin -u root processlist. Иногда mysqld не является зависшим, даже если кажется, что это так. Проблема может быть в том, что все соединения используются, или, возможно, имеется некая внутренняя проблема с блокировками. mysqladmin processlist обычно способна установить соединение даже в таких случаях и выдать полезную информацию о текущем количестве соединений и их состоянии.
  • Выполните команду в отдельном окне mysqladmin -i 5 status или mysqladmin -i 5 -r для вывода статистики, пока будут выполняться другие запросы.
  • Попробуйте выполнить следующие действия:
    1. Запустите mysqld в gdb (или в другом отладчике). See section D.1.3 Отладка mysqld при помощи gdb.
    2. Запустите тестовые скрипты.
    3. Отобразите стек (backtrace) и локальные переменные на трех нижних уровнях. В gdb это можно сделать следующими командами после аварийного завершения mysqld внутри gdb:
      backtrace
info local
up
info local
up
info local
      С помощью gdb можно также выяснить, какие имеются потоки (посредством info threads), и переключиться на определенный поток посредством thread #, где # - номер потока.
  • Попробуйте имитировать работу своего приложения с помощью Perl-скрипта, который бы вызвал аварийное завершение или неправильное функционирование MySQL.
  • Отправьте нам обычный отчет об ошибке (see section 1.8.1.3 Как отправлять отчеты об ошибках или проблемах). Любые подробности будут нелишними. Поскольку MySQL нормально эксплуатируется в очень многих местах, то, возможно, авария вызвана причиной, которая свойственна только вашему компьютеру (например, ошибка, связанная с вашими особенными системными библиотеками).
  • Если возникла проблема с таблицами, имеющими динамическую длину строк, и не используются столбцы типа BLOB/TEXT (а только столбцы типа VARCHAR), то можно попробовать изменить все VARCHAR на CHAR с помощью ALTER TABLE. Это заставит MySQL использовать строки фиксированного размера. Для строк фиксированного размера понадобится немного дополнительной памяти, однако они гораздо менее чувствительны к повреждениям! Сегодняшний код динамических строк без каких бы то ни было проблем эксплуатируется в MySQL AB по крайней мере 3 года, но в принципе строки динамической длины более подвержены ошибкам, поэтому данный рецепт, возможно, сможет вам чем-то помочь!

A.4.2 Как переустановить забытый пароль пользователя root

Если для MySQL пароль пользователя root никогда не устанавливался, то для соединения с сервером в качестве пользователя root пароль не потребуется. Рекомендуется всегда устанавливать пароль для каждого пользователя (see section 4.2.2 Как обезопасить MySQL от хакеров).

Если вы забыли установленный для root пароль, то новый пароль можно задать при помощи следующей процедуры:

  1. Остановите сервер mysqld; для этого нужно послать kill (но не kill -9) серверу mysqld. Номер процесса хранится в файле `.pid', обычно расположенном в каталоге баз данных MySQL:
    shell> kill `cat /mysql-data-directory/hostname.pid`
    Чтобы выполнить эту команду, необходимо быть либо Unix-пользователем root, либо пользователем, под которым работает mysqld.
  2. Перезапустите mysqld с опцией --skip-grant-tables.
  3. Установите новый пароль с помощью команды mysqladmin password:
    shell> mysqladmin -u root password 'mynewpassword'
  4. Теперь можно либо просто остановить mysqld и заново запустить его обычным способом, либо просто загрузить таблицы привилегий посредством:
    shell> mysqladmin -h hostname flush-privileges
  5. После этого можно будет соединяться, пользуясь новым паролем.

Есть и другой способ установки нового пароля - с помощью клиента mysql:

    Остановите mysqld и перезапустите его с опцией --skip-grant-tables, как было описано ранее.
  1. Соединитесь с сервером mysqld посредством:
    shell> mysql -u root mysql
  2. Выполните следующие команды из клиента mysql:
    mysql> UPDATE user SET Password=PASSWORD('mynewpassword')
    -> WHERE User='root';
mysql> FLUSH PRIVILEGES;
  3. После этого можно будет соединяться по новому паролю.
  4. Остановите mysqld и запустите его заново, как обычно.

A.4.3 Как MySQL реагирует на переполнение диска

Когда возникает ситуация переполнения диска, MySQL реагирует следующим образом:

    Один раз в минуту сервер проверяет, достаточно ли места для записи текущей строки. Если места достаточно, то сервер продолжает работу так, как будто ничего не произошло.
  • Каждые 6 минут сервер помещает в журнальный файл запись с предупреждением о ситуации переполнения диска.

Для снижения остроты проблемы можно принять следующие меры:

  • Чтобы продолжать работу, необходимо просто освободить на диске место, достаточное для вставки всех записей.
  • Чтобы прервать поток, необходимо послать потоку mysqladmin kill. Поток будет аварийно прекращен, когда он в следующий раз проверит диск (в течение 1 минуты).
  • Учтите, что таблицу, вызвавшую ситуацию переполнения диска, могут ожидать другие потоки. Если существует несколько "блокированных" потоков, то удаление одного потока, ожидающего по причине переполнения диска, позволит продолжаться другим.

Исключение составляет использование REPAIR или OPTIMIZE, а также случай, когда индексы создаются в пакете после команды LOAD DATA INFILE или ALTER TABLE.

Все упомянутые команды могут использовать большие временные файлы, которые, если их оставить без внимания, могут вызвать большие проблемы во всей системе. Если MySQL сталкивается с переполнением диска при выполнении одной из указанных операций, то сервер удаляет большие временные файлы и отмечает таблицу как поврежденную (за исключением ALTER TABLE, для которого старая таблица остается без изменений).

A.4.4 Где MySQL хранит временные файлы

Переменная окружения TMPDIR содержит полное имя каталога, в котором в MySQL хранит временные файлы. Если TMPDIR не установлена, то MySQL использует каталог, заданный в системе по умолчанию (обычно это `/tmp' или `/usr/tmp'). Если файловая система, в которой находится каталог временных файлов, слишком мала, то следует, отредактировав safe_mysqld, присвоить TMPDIR значение, указывающее на каталог в "более просторной" файловой системе! Временный каталог можно также задавать с помощью опции --tmpdir к mysqld.

Все временные файлы MySQL создает как скрытые; таким образом гарантируется, что временные файлы будут удалены, если mysqld умрет. Недостаток использования скрытых файлов в том, что не будут видны большие временные файлы, забирающие место в файловой системе, где расположен каталог временных файлов.

При сортировке (ORDER BY или GROUP BY) MySQL обычно использует один или два временных файла. Максимальный размер требующегося для этого пространства на диске составляет:

(размер сортируемых данных + sizeof(указатель базы данных))
* количество совпавших записей
* 2

sizeof(указатель базы данных) обычно равен 4, но со временем для очень больших таблиц может увеличиться.

Для некоторых запросов SELECT MySQL также создает временные SQL-таблицы. Они не скрытые и имеют имена вида `SQL_*'.

ALTER TABLE создает временную таблицу в одном каталоге с исходной таблицей.

Если вы используете версию 4.1 или более новую - вы можете распределять нагрузку между несколькими физическими дисками путем установления --tmpdir в список путей, разделенных двоеточием : (точкой с запятой ; - под Winodws). Они будут использоваться в ротации. Замечание: эти пути должны представлять различные физические диски, а не различные разделы одного и того же диска.

A.4.5 Как защитить или изменить сокет-файл MySQL `/tmp/mysql.sock'

Если возникают проблемы с тем, что кто угодно может удалить коммуникационный сокет MySQL `/tmp/mysql.sock', то в большинстве версий Unix можно защитить содержимое `/tmp', установив на каталоге ``липучий'' (sticky) бит. Войдите в систему как пользователь root и выполните следующую команду:

shell> chmod +t /tmp

Это защитит ваш каталог `/tmp': теперь удалять в нем файлы смогут только их владельцы или суперпользователь (root).

Проверить, установлен ли ``липучий'' (sticky) бит, можно, выполнив ls -ld /tmp. Если последним битом прав является t, то бит установлен.

Изменить путь к каталогу, где MySQL открывает сокет-файл, можно, воспользовавшись одним из следующих способов:

  • Укажите путь в глобальном или локальном файле опций. Например, поместите в `/etc/my.cnf':
    [client]
socket=path-for-socket-file

[mysqld]
socket=path-for-socket-file
    See section 4.1.2 Файлы параметров `my.cnf'.
  • Укажите, где расположен файл, в командной строке safe_mysqld и большинства клиентов с помощью опции --socket=путь-к-файлу-сокета.
  • Укажите путь к сокету в переменной окружения MYSQL_UNIX_PORT.
  • Определите путь с помощью опции конфигурирования --with-unix-socket-path=путь-к-файлу-сокета (see section 2.3.3 Типичные опции configure).

Проверить, работает ли сокет, можно следующей командой:

shell> mysqladmin --socket=/path/to/socket version

A.4.6 Проблемы с часовыми поясами

Если есть проблема с тем, что SELECT NOW() возвращает значения GMT, а не местное время, то необходимо установить переменную окружения TZ равной местному часовому поясу. Это должно быть сделано для окружения, в котором работает сервер, например, в safe_mysqld или mysql.server (see section E Переменные окружения).

A.5 Проблемы, относящиеся к запросам

A.5.1 Чувствительность к регистру при поиске

По умолчанию поиск в MySQL является независимым от регистра символов (хотя существуют некоторые кодировки, которые всегда чувствительны к регистру, такие как czech). Это означает, что при поиске с помощью col_name LIKE 'a%' будут выданы все значения столбца, начинающиеся на A или a. Если необходимо выполнить тот же поиск с учетом регистра, для проверки префикса следует использовать что-то вроде INSTR(col_name, "A")=1 или STRCMP(col_name, "A") = 0, если значение в столбце точно равно A.

Простые операции сравнения (>=, >, =, <, <=, сортировка и группировка) основываются на "сорте" каждого символа. Символы одного сорта (такие как E, e и E) обрабатываются как одинаковые символы!

В старых версиях MySQL сравнения по LIKE выполнялись над символами, переведенными в верхний регистр (E == e, но E <> E). В новых версиях MySQL LIKE работает точно так же, как другие операторы сравнения.

Если необходимо, чтобы столбец всегда обрабатывался в с учетом регистра, объявите его с типом BINARY (see section 6.5.3 Синтаксис оператора CREATE TABLE).

Если вы используете китайские данные в так называемой кодировке big5, то имеет смысл объявить все символьные столбцы как BINARY. Сортировка таких столбцов будет работать, поскольку порядок сортировки символов в кодировке big5 основывается на порядке кодов ASCII.

A.5.2 Проблемы с использованием столбцов типа DATE

Значения типа DATE имеют формат YYYY-MM-DD; согласно стандарту ANSI SQL, никакой другой формат не допускается. Пользователь должен применять этот формат в выражениях UPDATE и в определении WHERE операторов SELECT. Например:

mysql> SELECT * FROM tbl_name WHERE date >= '1997-05-05';

Из соображений удобства MySQL автоматически преобразовывает дату в число, если дата используется в числовом контексте (и наоборот). Благодаря своей ``разумности'' MySQL допускает также ``мягкую'' строковую форму при обновлении и в определении WHERE, сравнивающем дату со столбцом типа TIMESTAMP, DATE или DATETIME ("мягкая" форма означает, что для разделения составляющих даты можно использовать любой знак пунктуации; например, 1998-08-15 и 1998#08#15 эквивалентны). MySQL может также преобразовывать в даты строки, не содержащие разделителей (наподобие 19980815), при условии, что представляемая строкой дата не лишена смысла.

Специальная дата 0000-00-00 может записываться и извлекаться в виде 0000-00-00. При использовании даты 0000-00-00 из MyODBC она будет автоматически преобразована в NULL в версии MyODBC 2.50.12 и выше, так как ODBC не обеспечивает обработку такого рода дат.

Поскольку в MySQL выполняются описанные выше преобразования, следующие команды будут работать:

mysql> INSERT INTO tbl_name (idate) VALUES (19970505);
mysql> INSERT INTO tbl_name (idate) VALUES ('19970505');
mysql> INSERT INTO tbl_name (idate) VALUES ('97-05-05');
mysql> INSERT INTO tbl_name (idate) VALUES ('1997.05.05');
mysql> INSERT INTO tbl_name (idate) VALUES ('1997 05 05');
mysql> INSERT INTO tbl_name (idate) VALUES ('0000-00-00');
mysql> SELECT idate FROM tbl_name WHERE idate >= '1997-05-05';
mysql> SELECT idate FROM tbl_name WHERE idate >= 19970505;
mysql> SELECT MOD(idate,100) FROM tbl_name WHERE idate >= 19970505;
mysql> SELECT idate FROM tbl_name WHERE idate >= '19970505';

Однако приведенные ниже команды работать не будут:

mysql> SELECT idate FROM tbl_name WHERE STRCMP(idate,'19970505')=0;

STRCMP() - строковая функция, следовательно, она преобразует idate в строку и сравнивает строки. Функция не станет преобразовывать 19970505 в дату и сравнивать даты.

Заметим, что MySQL осуществляет очень ограниченную проверку правильности дат, поэтому такая некорректная дата, как 1998-2-31, будет занесена в базу.

Поскольку MySQL пакует даты для сохранения, он не может сохранить любую дату, так как она может не поместится в результирующий буфер. Правила принятия дат следующие:

  • Если MySQL может хранить и выбирать заданную дату, неправильная дата принимается для столбцов DATE и DATETIME.
  • Все значения дней между 0-31 принимаются для любой даты, это удобно для приложения, где вы запрашиваете год, месяц и день в 3х различных полях.
  • День или месяц могут быть нулем. Это удобно когда вы хотите хранить дату рождения в столбце DATE и знаете только часть ее.

Если же дату нельзя преобразовать в какое-нибудь разумное значение, в поле типа DATE заносится 0. Проверка правильности дат не делается - в основном из соображений, связанных со скоростью: мы считаем, что проверкой дат должно заниматься приложение, а не сервер.

A.5.3 Проблемы со значением NULL

Концепция NULL-значения часто вводит в заблуждение новичков в SQL, которые считают, что NULL - то же, что и пустая строка "". Это ошибка! Например, следующие команды совершенно различны:

mysql> INSERT INTO my_table (phone) VALUES (NULL);
mysql> INSERT INTO my_table (phone) VALUES ("");

Обе команды вставляют значение в столбец phone, но первая - значение NULL, а вторая - пустую строку. Смысл первого можно передать как ``номер телефона неизвестен'', смысл второго - ``у нее нет телефона''.

В SQL сравнение значения NULL с любым другим значением, даже со значением NULL, всегда ложно. Выражение, содержащее NULL, всегда дает значение NULL, за исключением случаев, специально оговоренных в документации по операторам и функциям, присутствующим в выражении. Все столбцы в следующем примере возвращают NULL:

mysql> SELECT NULL,1+NULL,CONCAT('Invisible',NULL);

Если в столбце нужно найти значения NULL, то нельзя использовать условие =NULL. Следующая команда не возвращает ни одной строки, поскольку для любого выражения expr = NULL ЛОЖНО:

mysql> SELECT * FROM my_table WHERE phone = NULL;

Для поиска значений NULL необходимо использовать проверку IS NULL. Ниже показано, как найти телефонный номер NULL и пустой телефонный номер:

mysql> SELECT * FROM my_table WHERE phone IS NULL;
mysql> SELECT * FROM my_table WHERE phone = "";

Заметим, что добавлять индекс по столбцу, в котором допускаются значения NULL, можно только в случае, если вы работаете с версией MySQL 3.23.2 или выше, а используемый тип таблиц - MyISAM или InnoDB. В более ранних версиях или для других типов таблиц необходимо объявлять такие столбцы с атрибутом NOT NULL. Это также подразумевает, что тогда нельзя вставлять NULL в индексированный столбец.

При чтении данных с помощью LOAD DATA INFILE пустые поля обновляются значениями ''. Если необходимо поместить в столбец значение NULL, то в текстовом файле следует использовать \N. Также при некоторых обстоятельствах можно использовать слово-литерал NULL (see section 6.4.9 Синтаксис оператора LOAD DATA INFILE).

При использовании ORDER BY значения NULL выдаются первыми. В версиях предшествующих 4.0.2, при сортировке в убывающем порядке при помощи DESC, значения NULL также выдаются последними. При использовании GROUP BY все значения NULL считаются равными.

Для обработки NULL предназначены операторы IS NULL и IS NOT NULL, а также функция IFNULL().

Для некоторых типов столбцов значения NULL обрабатываются специальным образом. Если NULL вставляется в первый в таблице столбец типа TIMESTAMP, то в него помещается значение текущей даты и времени. При вставке NULL в AUTO_INCREMENT-столбец вставляется следующее число последовательности.

A.5.4 Проблемы с alias

Псевдонимы можно использовать для ссылки на столбец в GROUP BY, ORDER BY или в части HAVING, а также для лучшего именования столбцов:

SELECT SQRT(a*b) as rt FROM table_name GROUP BY rt HAVING rt > 0;
SELECT id,COUNT(*) AS cnt FROM table_name GROUP BY id HAVING cnt > 0;
SELECT id AS "Customer identity" FROM table_name;

Заметим, что в ANSI SQL запрещено ссылаться на псевдоним в определении WHERE. Вызвано это тем, что при выполнении кода WHERE значение столбца может быть еще не определенным. Например, следующий запрос недопустим:

SELECT id,COUNT(*) AS cnt FROM table_name WHERE cnt > 0 GROUP BY id;

Выражение WHERE выполняется, чтобы определить, какие строки следует включить в часть GROUP BY, тогда как HAVING используется для тех строк из результирующего множества, которые должны использоваться.

A.5.5 Удаление строк из взаимосвязанных таблиц

Поскольку MySQL до 4.1.0 не поддерживает вложенных запросов, а также использование более одной таблицы в команде DELETE (до версии 4.0), то для удаления строк из 2 взаимосвязанных таблиц следует использовать следующий подход:

  1. Выполните в главной таблице SELECT строк на основе некоторого условия WHERE.
  2. Выполните DELETE строк главной таблицы на основе этого же условия.
  3. DELETE FROM related_table WHERE related_column IN (selected_rows).

где selected_rows - количество строк, выбранных по запросу в п.1.

Если общее количество символов в запросе с related_column больше 1048576 (значение max_allowed_packet по умолчанию), то следует разбить запрос на меньшие части и выполнить несколько команд DELETE. Если related_column является индексом/индексирован, то самый быстрый DELETE получится при удалении 100-1000 идентификаторов related_column за запрос. Если related_column не индекс, то скорость не зависит от количества аргументов в операторе IN.

A.5.6 Решение проблем с отсутствием строк, удовлетворяющих условиям поиска

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

  1. Проверьте запрос с помощью EXPLAIN и посмотрите, не присутствуют ли в нем явно неправильные записи (see section 5.2.1 Синтаксис оператора EXPLAIN (получение информации о SELECT)).
  2. Выберите только поля, используемые в выражении WHERE.
  3. По одной убирайте из запроса таблицы до тех пор, пока не станут возвращаться какие-нибудь строки. Если таблицы большие, то в запросе имеет смысл использовать LIMIT 10.
  4. Выполните SELECT для столбца, который должен был дать совпадение строки с последней исключенной из запроса таблицей.
  5. Если столбцы типа FLOAT или DOUBLE сравниваются с имеющими дробную часть числами, то нельзя использовать `='. Это распространенная проблема в большинстве компьютерных языков, поскольку значения с плавающей запятой не являются точными. В большинстве случаев проблему решает изменение FLOAT на DOUBLE. See section A.5.7 Проблемы со сравнением чисел с плавающей точкой.
  6. Если так и не удалось выяснить, в чем загвоздка, то для демонстрации возникших у вас проблем создайте минимальный тест, запускающийся при помощи mysql test < query.sql. Тестовый файл можно создать, воспользовавшись mysqldump --quick database tables > query.sql. Далее откройте файл в редакторе, удалите некоторые команды вставки (если их слишком много) и добавьте в конце файла свою команду выборки. Убедитесь, что проблема по-прежнему проявляется, посредством:
    shell> mysqladmin create test2
shell> mysql test2 < query.sql
    Используя mysqlbug, пошлите тестовый файл в список рассылки на mysql@lists.mysql.com.

A.5.7 Проблемы со сравнением чисел с плавающей точкой

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

Поля типов FLOAT, DOUBLE и DECIMAL следующие.

CREATE TABLE t1 (i INT, d1 DECIMAL(9,2), d2 DECIMAL(9,2));
INSERT INTO t1 VALUES (1, 101.40, 21.40), (1, -80.00, 0.00),
(2, 0.00, 0.00), (2, -13.20, 0.00), (2, 59.60, 46.40),
(2, 30.40, 30.40), (3, 37.00, 7.40), (3, -29.60, 0.00),
(4, 60.00, 15.40), (4, -10.60, 0.00), (4, -34.00, 0.00),
(5, 33.00, 0.00), (5, -25.80, 0.00), (5, 0.00, 7.20),
(6, 0.00, 0.00), (6, -51.40, 0.00);

mysql> SELECT i, SUM(d1) AS a, SUM(d2) AS b
    -> FROM t1 GROUP BY i HAVING a <> b;
+------+--------+-------+
| i    | a      | b     |
+------+--------+-------+
|    1 |  21.40 | 21.40 |
|    2 |  76.80 | 76.80 |
|    3 |   7.40 |  7.40 |
|    4 |  15.40 | 15.40 |
|    5 |   7.20 |  7.20 |
|    6 | -51.40 |  0.00 |
+------+--------+-------+

Результат правильный. Хотя кажется, что первые пять записей должны быть отброшены, не выдержав проверки на сравнение, тем не менее, они могут удовлетворить условиям по той причине, что в зависимости от архитектуры компьютера между числами проявляются отличия примерно на уровне десятого знака.

С помощью ROUND() (или подобной функции) проблема не может быть решена, поскольку результат все равно будет числом с плавающей запятой, например:

mysql> SELECT i, ROUND(SUM(d1), 2) AS a, ROUND(SUM(d2), 2) AS b
    -> FROM t1 GROUP BY i HAVING a <> b;
+------+--------+-------+
| i    | a      | b     |
+------+--------+-------+
|    1 |  21.40 | 21.40 |
|    2 |  76.80 | 76.80 |
|    3 |   7.40 |  7.40 |
|    4 |  15.40 | 15.40 |
|    5 |   7.20 |  7.20 |
|    6 | -51.40 |  0.00 |
+------+--------+-------+

Вот как выглядят числа в столбце 'a':

mysql> SELECT i, ROUND(SUM(d1), 2)*1.0000000000000000 AS a,
    -> ROUND(SUM(d2), 2) AS b FROM t1 GROUP BY i HAVING a <> b;
+------+----------------------+-------+
| i    | a                    | b     |
+------+----------------------+-------+
|    1 |  21.3999999999999986 | 21.40 |
|    2 |  76.7999999999999972 | 76.80 |
|    3 |   7.4000000000000004 |  7.40 |
|    4 |  15.4000000000000004 | 15.40 |
|    5 |   7.2000000000000002 |  7.20 |
|    6 | -51.3999999999999986 |  0.00 |
+------+----------------------+-------+

В вашей системе результаты могут либо такими, либо нет - это зависит от архитектуры компьютера. Каждый процессор выполняет вычисления с плавающей точкой по-своему. Например, на некоторых машинах можно получить ``правильные'' результаты, если умножить оба аргумента на 1 (см. пример ниже).

ПРЕДУПРЕЖДЕНИЕ: НИКОГДА НЕ ПОЛАГАЙТЕСЬ НА ДАННЫЙ МЕТОД В СВОЕМ ПРИЛОЖЕНИИ, ЭТО ПРИМЕР ТОГО, КАКИЕ МЕТОДЫ НЕ СЛЕДУЕТ ИСПОЛЬЗОВАТЬ!!!

mysql> SELECT i, ROUND(SUM(d1), 2)*1 AS a, ROUND(SUM(d2), 2)*1 AS b
    -> FROM t1 GROUP BY i HAVING a <> b;
+------+--------+------+
| i    | a      | b    |
+------+--------+------+
|    6 | -51.40 | 0.00 |
+------+--------+------+

Приведенный выше пример вроде бы работает. Но это случайность, поскольку именно на той конкретной машине, где выполнялась проверка, процессор выполняет арифметические операции с плавающей точкой таким образом, что числа округляются до одинаковых значений. Однако полагаться на то, что так будут работать все без исключения процессоры, нельзя.

Правильный способ сравнения чисел с плавающей запятой заключается в том, чтобы сначала определиться с допустимым отклонением одного числа от другого, а затем при сравнении учитывать этот допуск. Например, если мы договоримся, что числа должны считаться одинаковыми, если они равны с точностью до одной десятитысячной (0,0001), то сравнение должно проводиться следующим образом:

mysql> SELECT i, SUM(d1) AS a, SUM(d2) AS b FROM t1
    -> GROUP BY i HAVING ABS(a - b) > 0.0001;
+------+--------+------+
| i    | a      | b    |
+------+--------+------+
|    6 | -51.40 | 0.00 |
+------+--------+------+
1 row in set (0.00 sec)

И наоборот, если мы хотим оставить строки, в которых числа одинаковы, то проверка должна быть следующей:

mysql> SELECT i, SUM(d1) AS a, SUM(d2) AS b FROM t1
    -> GROUP BY i HAVING ABS(a - b) < 0.0001;
+------+-------+-------+
| i    | a     | b     |
+------+-------+-------+
|    1 | 21.40 | 21.40 |
|    2 | 76.80 | 76.80 |
|    3 |  7.40 |  7.40 |
|    4 | 15.40 | 15.40 |
|    5 |  7.20 |  7.20 |
+------+-------+-------+

A.6 Вопросы, связанные с определением таблиц

A.6.1 Проблемы с ALTER TABLE

ALTER TABLE изменяет таблицу в соответствии с текущей кодировкой. Если при выполнении ALTER TABLE выдается ошибка дублирующегося ключа, то причина либо в том, что новая кодировка отображает ключи в одинаковые значения, либо в том, что таблица повреждена. В последнем случае на таблице необходимо выполнить REPAIR TABLE.

Если работа ALTER TABLE прекращается с ошибкой, подобной приведенной ниже:

Error on rename of './database/name.frm' to './database/B-a.frm' (Errcode: 17)

то проблема может быть связана с тем, что MySQL аварийно завершился на предыдущей команде ALTER TABLE и осталась старая таблица с именем `A-что_нибудь' или `B-что_нибудь'. В этом случае перейдите в каталог данных MySQL и удалите все файлы, имена которых начинаются с A- или B- (их можно и не удалять, а куда-либо переместить).

ALTER TABLE работает следующим образом:

  • Создается новая таблица с именем `A-xxx' с заданными в запросе изменениями.
  • Все строки старой таблицы копируются в `A-xxx'.
  • Старая таблица переименовывается в `B-xxx'.
  • `A-xxx' переименовывается в имя старой таблицы.
  • Удаляется `B-xxx'.

Если что-то приключится при операции переименования, MySQL попытается отменить изменения. Если случится что-то серьезное (чего произойти, конечно, не должно), MySQL может оставить старую таблицу именованной как `B-xxx' - в этом случае, однако, для восстановления данных достаточно будет просто переименовать ее на системном уровне.

A.6.2 Как изменить порядок столбцов в таблице

Основная идея SQL заключается в том, чтобы разделить приложения и формат хранения данных. Всегда следует указывать порядок извлечения данных, например:

SELECT col_name1, col_name2, col_name3 FROM tbl_name;

возвратит столбцы в порядке col_name1, col_name2, col_name3, тогда как:

SELECT col_name1, col_name3, col_name2 FROM tbl_name;

возвратит столбцы в порядке col_name1, col_name3, col_name2.

В приложения никогда нельзя использовать SELECT * и извлекать столбцы, полагаясь на их позиции, поскольку порядок, в котором возвращаются столбцы, не может быть гарантирован. Простое изменение в базе данных может катастрофически сказаться на поведении приложения.

Если порядок столбцов все-таки требуется изменить, то сделать это можно следующим образом:

  1. Создайте новую таблицу со столбцами в правильном порядке.
  2. Выполните INSERT INTO new_table SELECT поля-в-желаемом-порядке FROM old_table.
  3. Удалите или переименуйте old_table.
  4. ALTER TABLE new_table RENAME old_table.

A.6.3 Проблемы, относящиеся к временным (TEMPORARY) таблицам

Ниже перечислены ограничения, относящиеся к временным таблицам.

  • Временной может быть только таблица типа HEAP, ISAM, MyISAM, MERGE или InnoDB.
  • Временная таблица не может использоваться в одном запросе более одного раза. Например, следующий запрос работать не будет.
    mysql> SELECT * FROM temporary_table, temporary_table AS t2;
  • Нельзя использовать RENAME на таблице с атрибутом TEMPORARY. Отметим, однако, что ALTER TABLE оригинальное_имя RENAME новое_имя работает!


Справочное руководство по MySQL версии 5.0.0-alpha. - B Благодарности

B Благодарности

В этом приложении перечисляются разработчики, помощники и спонсоры, которые помогли сделать MySQL таким, какой он есть сегодня.

B.1 Разработчики MySQL AB

Здесь представлен список разработчиков, занимающихся в настоящее разработкой программного обеспечения сервера баз данных MySQL в компании MySQL AB или занимавшихся этой разработкой ранее, приблизительно в том порядке, в котором они начинали работать с нами. После личных данных каждого разработчика следует небольшой список задач, за которые он отвечал, или выполненных им работ. Все разработчеки вовлечены в техническую поддержку.

Майкл (Монти) Видениус (Michael (Monty) Widenius)
  • Главный программист и главный автор MySQL сервера (mysqld).
  • Новые функции для строковой библиотеки.
  • Большая часть библиотеки mysys.
  • Библиотеки ISAM и MyISAM (обработчики индексного файла B-tree с уплотнением индексов и различными форматами записи).
  • Библиотека HEAP. Система таблиц памяти с разработанным нами превосходным полностью динамическим хешированием. В эксплуатации находится с 1981 года; опубликована приблизительно в 1984 году.
  • Программа replace (гляньте на нее, это КРУТО!).
  • MyODBC, драйвер ODBC для Windows95.
  • Устранение ошибок в потоках MIT-pthreads для обеспечения их работы в сервере MySQL. А также Unireg, прикладная среда с интерфейсом Curses со многими полезными утилитами.
  • Осуществил перенос из mSQL таких средств, как msqlperl, DBD/DBI и DB2mysql.
  • Большинство тестов crash-me и организация эталонных тестов для MySQL.
Дэвид Эксмарк (David Axmark)
  • Первый основной автор справочного руководства, включая модернизацию texi2html.
  • Автоматический веб-сайт, обновляющийся из данного руководства.
  • Первоначальная поддержка Autoconf, Automake и Libtool.
  • Лицензирование.
  • Участие в написании всех текстовых файлов (из них в настоящее время остался только файл `README': остальные вошли в состав руководства).
  • Большой объем работы по тестированию новых возможностей.
  • Наш домашний юрист по программному обеспечению с открытым кодом (Free Software).
  • Ответственный за поддержку списка рассылки (у которого никогда нет времени делать это как следует...).
  • Автор нашего оригинального кода, обеспечивающего переносимость (которому сейчас более 10 лет). В настоящее время от mysys остались только некоторые части.
  • А также человек, которому Монти всегда может позвонить среди ночи, когда только что заработало новое программное средство.
  • Старший специалист по открытому коду (связь с общественностью MySQL).
Яни Толонен (Jani Tolonen)
  • mysqlimport
  • Большое количество расширений для клиентов командной строки.
  • PROCEDURE ANALYSE()
Синиша Миливоевич (Sinisa Milivojevic)
  • Компрессия (с помощью zlib) в протоколе клиент-сервер.
  • Превосходное хеширование для фазы лексического анализатора.
  • Многострочная команда INSERT
  • Опция mysqldump -e
  • LOAD DATA LOCAL INFILE
  • Опция SQL_CALC_FOUND_ROWS для SELECT
  • Опция --max-user-connections=...
  • net_read и net_write_timeout
  • GRANT/REVOKE и SHOW GRANTS FOR
  • Новый клиент-серверный протокол для версии 4.0
  • UNION в 4.0.
  • Многотабличные команды DELETE/UPDATE
  • Вторичные таблицы в 4.1.
  • Управление пользовательскими ресурсами.
  • Первый автор MySQL++ C API и клиента MySQLGUI.
Тону Сэмюэл (Tonu Samuel) (разработчик в прошлом)
  • Интерфейс VIO (основы клиент-серверного протокола с шифрованием).
  • MySQL Filesystem (технология использования баз данных MySQL как файловой системы).
  • Выражение CASE.
  • Функции MD5() и COALESCE().
  • Поддержка RAID для таблиц MyISAM.
Саша Пачев (Sasha Pachev)
  • Начальная реализация репликации (до версии 4.0).
  • SHOW CREATE TABLE.
  • mysql-bench
Мэт Вагнер (Matt Wagner)
  • Набор тестов для MySQL
  • Веб-мастер (до 2002).
  • Координатор разработки.
Мигуэл Солорцано (Miguel Solorzano)
  • Разработка Win32 и выпуск бинарных версий.
  • Код сервера под Windows NT.
  • WinMySQLAdmin.
Тимоти Смит (Timothy Smith) (разработчик в прошлом)
  • Поддержка динамических символов (dynamic character).
  • configure, пакеты RPM и другие части сборочной системы.
  • Начальный разработчик libmysqld, встраиваемого сервера.
Сергей Голубчик (Sergei Golubchik)
  • Полнотекстовый поиск.
  • Добавление ключей к библиотеке MERGE.
Джереми Коул (Jeremy Cole)
  • Чтение корректуры и редактирование этого замечательного руководства на английском языке.
  • ALTER TABLE ... ORDER BY ....
  • UPDATE ... ORDER BY ....
  • DELETE ... ORDER BY ....
Индрек Сиитан (Indrek Siitan)
  • Разработка/программирование веб-интерфейса.
  • Автор нашей системы управления списком рассылки.
Джордж дел Конде (Jorge del Conde)
  • Центр Управления MySQL MyCC (MySQL Control Center).
  • Разработка Win32
  • Начальная реализация веб-портала.
Вену Аннуганти (Venu Anuganti)
  • MyODBC 3.51
  • Новый клиент/серверный протокол для 4.1 (для подготовленных выражений).
Арйен Ленц (Arjen Lentz)
  • Поддерживает справочное руководство по MySQL.
  • Подготовка печатного издания справочного руководства в издательстве O'Reilly.
Александр Барков (Alexander (Bar) Barkov), Алексей Бочков (Alexey (Holyfoot)
Botchkov), и Рамиль Калимуллин (Ramil Kalimullin)
  • Пространственные данные (GIS) и реализация R-Деревьев в 4.1
  • Unicode и набор символов в 4.1
Александр Белкин (Oleksandr (Sanja) Byelkin)
  • Кэш запросов в 4.0
  • Реализация вложенных запросов (4.1).
Алексей Кишкин (Aleksey (Walrus) Kishkin) и Алексей Строганов (Alexey (Ranger) Stroganov)
  • Разработка тестов скорости работы и анализ.
  • Поддержка набора тестов для MySQL.
Зэк Гринт (Zak Greant)
  • Адвокат по открытому коду, связь MySQL с общественностью.
Карстен Педерсен (Carsten Pedersen)
  • Сертификационная программа MySQL.
Ленц Гриммер (Lenz Grimmer)
  • Технология производства (сборка и выпуск).
Петр Зайцев (Peter Zaitsev)
  • SHA1(), AES_ENCRYPT() и AES_DECRYPT() функции.
  • Отладка, чистка различных возможностей.
Александр Керемидарский (Alexander (Salle) Keremidarski)
  • Документирование существующего кода и алгоритмов в MySQL.
  • Отладка.
Пер-Эрик Мартин (Per-Erik Martin)
  • Главный разработчик хранимых процедур и триггеров.
Джим Уинстед (Jim Winstead)
  • Главный веб-разработчик.
Марк Мэтьюз (Mark Matthews)
  • Драйвер Connector/J (Java).

B.2 Наши помощники, которые сделали вклад в развитие MySQL

В то время как MySQL AB обладает всеми авторскими правами на сервер MySQL и документацию по MySQL, мы хотим отдать дань уважения тем, кто в той или иной степени лично способствовал разработке MySQL. Ниже в произвольном порядке перечислены наши помощники, которые сделали вклад в развитие в MySQL:

Пол Дюбуа (Paul DuBois)
В настоящее время помощь в приведении данного справочного руководства (Reference Manual) к корректному и понятному виду. Другими словами, перевод текстов Монти и Дэвида с их собственного английского на английский, понятный другим людям.
Джанмассимо Вигаццола (Gianmassimo Vigazzola) qwerg@mbox.vol.it или
qwerg@tin.it Первоначальный перенос на Win32/NT.
Ким Олдэйл (Kim Aldale)
Помог переписать самые первые тексты Монти и Дэвида с их собственного английского на нормальный английский.
Пер Эрик Олссон (Per Eric Olsson)
Благодарность за более или менее конструктивную критику и первоклассное тестирование формата динамической записи.
Ирэна Панциров (Irena Pancirov) irena@mail.yacc.it
Перенос Win32 с помощью компилятора Borland. mysqlshutdown.exe и mysqlwatch.exe
Дэвид Дж. Хьюз (David J. Hughes)
Благодарность за вклад в создание SQL-базы данных, распространяемой по принципу shareware. Начав свою работу в компании TcX (предшественник MySQL AB) с mSQL, мы, однако, пришли к выводу, что эта база данных не удовлетворяет нашим требованиям. Поэтому вместо нее был написан интерфейс SQL к нашему компоновщику приложений Unireg. На программу mysqladmin и клиент mysql оказали значительное влияние их двойники в mSQL. Мы приложили много усилий, чтобы сделать синтаксис MySQL расширенным вариантом mSQL. Многие идеи API были заимствованы из mSQL, чтобы упростить перенос свободно распространяемых программ mSQL в MySQL API. Программное обеспечение MySQL не содержит никакого кода из mSQL. Два файла в дистрибутиве (`client/insert_test.c' и `client/select_test.c') базируются на соответствующих (не защищенных авторскими правами) файлах дистрибутива mSQL, но они модифицированы в примеры, показывающие, какие изменения необходимы для преобразования кода из mSQL в сервер MySQL. (авторское право на mSQL принадлежит Дэвиду Дж. Хьюзу (David J. Hughes.))
Фред Фиш (Fred Fish)
Благодарность за его великолепную отладку C и библиотеку трассировки. Монти сделал ряд небольших улучшений к этой библиотеке (скорость и другие возможности).
Ричард А. О'Кифи (Richard A. O'Keefe)
Благодарность за его общедоступную строковую библиотеку.
Генри Спенсер (Henry Spencer)
Благодарность за его библиотеку регулярных выражений, использованную в WHERE column REGEXP regexp.
Ассоциация Свободного ПО (Free Software Foundation)
От этой ассоциации мы получили прекрасный компилятор (gcc), библиотеку libc (из которой заимствовали `strto.c' для того, чтобы получить код, работающий под Linux) и библиотеку readline (для клиента mysql).
Ассоциация Свободного ПО (Free Software Foundation) и команда
разработчиков Xemacs (The XEmacs development team) Благодарность за действительно великолепный редактор/среду, который использовали практически все в MySQL AB/TcX/detron.
Патрик Линч (Patrick Lynch)
Благодарность за помощь в получении http://www.mysql.com/.
Фред Линдберг (Fred Lindberg)
Благодарность за установку qmail для управления списком рассылки MySQL и за неоценимую помощь, которую мы получили в управлении списком рассылки MySQL.
Игорь Романенко (Igor Romanenko) igor@frog.kiev.ua
mysqldump (ранее msqldump, Монти осуществил перенос этой утилиты и усовершенствовал ее).
Юрий Дарио (Yuri Dario)
Благодарность за поддержку и расширение переноса MySQL на OS/2.
Тим Банке (Tim Bunce, Alligator Descartes)
Благодарность за интерфейс DBD (Perl).
Тим Банке (Tim Bunce)
Автор mysqlhotcopy.
Эндриас Коуниг (Andreas Koenig) a.koenig@mind.de
Благодарность за интерфейс Perl для сервера MySQL.
Юджин Чан (Eugene Chan) eugene@acenet.com.sg
Благодарность за перенос PHP для сервера MySQL.
Майкл Дж. Миллер мл. (Michael J. Miller Jr.) mke@terrapin.turbolift.com
Благодарность за первое руководство по MySQL. И за большое количество орфографических и грамматических правок в разделе FAQ (который уже давно превратился в руководство по MySQL).
Ян Кайлин (Yan Cailin)
Первый перевод справочного руководства по MySQL на упрощенный китайский язык в начале 2000 года; на этом руководстве базировались версии, кодированные на Big5 и HK (http://mysql.hitstar.com/). Персональная домашняя страничка на linuxdb.yeah.net.
Джованни Маруцелли (Giovanni Maruzzelli) maruzz@matrice.it
Благодарность за перенос iODBC (Unix ODBC).
Крис Провензано (Chris Provenzano)
Переносимые потоки pthreads пользовательского уровня. Выдержка из документа по авторским правам на MySQL: "Этот продукт включает в себя программное обеспечение, разработанное Крисом Провензано, Калифорнийский университет, Беркли (Chris Provenzano, the University of California, Berkeley) и его помощниками". В настоящее время мы используем версию 1_60_beta6 с патчами Монти (см. `mit-pthreads/Changes-mysql').
Ксавьер Лерой (Xavier Leroy) Xavier.Leroy@inria.fr
Автор LinuxThreads (используемых сервером MySQL под Linux).
Зарко Мокник (Zarko Mocnik) zarko.mocnik@dem.si
Упорядочение для словенского языка и разработка модуля `cset.tar.gz', который облегчает добавление других кодировок.
"ТАМИТО" ("TAMITO") tommy@valley.ne.jp
Макрос кодировки _MB и наборы символов ujis и sjis.
Джошуа Чамас (Joshua Chamas) joshua@chamas.com
Основы для параллельной вставки, расширенный синтаксис даты, отладка под NT и ответы по списку рассылки MySQL.
Ив Карлиер (Yves Carlier) Yves.Carlier@rug.ac.be
mysqlaccess, программа, показывающая права доступа для пользователя.
Рис Джонс (Rhys Jones) rhys@wales.com (И GWE Technologies Limited)
Благодарность за JDBC, модуль для извлечения данных из базы данных MySQL при помощи помощью Java-клиента.
Др. Ксайэокун Келвин ZHU (Dr Xiaokun Kelvin ZHU) X.Zhu@brad.ac.uk
Дальнейшая разработка JDBC-драйвера и других относящихся к MySQL Java-программ.
Джеймс Купер (James Cooper) pixel@organic.com
Благодарность за установку архива списка рассылки с возможностью поиска на его сайте.
Рик Мехелик (Rick Mehalick) Rick_Mehalick@i-o.com
Благодарность за xmysql, графический X-клиент для сервера MySQL.
Дуг Сиск (Doug Sisk) sisk@wix.com
Благодарность за разработку пакетов RPM для MySQL под RedHat Linux.
Дайменд Александер В. (Diemand Alexander V.) axeld@vial.ethz.ch
Благодарность за разработку пакетов RPM для MySQL под RedHat Linux-Alpha.
Энтони Пеймес Олив (Antoni Pamies Olive) toni@readysoft.es
Благодарность за разработку пакетов RPM многих клиентов MySQL для Intel и SPARC.
Джей Бладвортс (Jay Bloodworth) jay@pathways.sde.state.sc.us
Благодарность за разработку пакетов RPM для версии MySQL 3.21.
Джошен Видманн (Jochen Wiedmann) wiedmann@neckar-alb.de
Благодарность за поддержку модуля Perl DBD::mysql.
Терьен Джилберт (Therrien Gilbert) gilbert@ican.net, Джин - Марк Поуйот
(Jean-Marc Pouyot) jmp@scalaire.fr Сообщения об ошибках на французском языке.
Петр Снайдр (Petr snajdr), snajdr@pvt.net
Сообщения об ошибках на чешском языке.
Ярослав Левандовски (Jaroslaw Lewandowski) jotel@itnet.com.pl
Сообщения об ошибках на польском языке.
Мигель Эйнджел Фернандес Роиз (Miguel Angel Fernandez Roiz)
Сообщения об ошибках на испанском языке.
Рой - Магн Моу (Roy-Magne Mo) rmo@www.hivolda.no
Сообщения об ошибках на норвежском языке и тестирование версии 3.21.#.
Тимур И. Бакеев (Timur I. Bakeyev) root@timur.tatarstan.ru
Сообщения об ошибках на русском языке.
brenno@dewinter.com и Филиппо Грасилли (& Filippo Grassilli)
phil@hyppo.com Сообщения об ошибках на итальянском языке.
Дирк Мюнцингер (Dirk Munzinger) dirk@trinity.saar.de
Сообщения об ошибках на немецком языке.
Биллик Стефан (Billik Stefan) billik@sun.uniag.sk
Сообщения об ошибках на словацком языке.
Стефан Сарою (Stefan Saroiu) tzoompy@cs.washington.edu
Сообщения об ошибках на румынском языке.
Петер Фехер (Peter Feher)
Сообщения об ошибках на венгерском языке.
Роберто М. Серкуейра (Roberto M. Serqueira)
Сообщения об ошибках на португальском языке.
Карстен Х. Педерсен (Carsten H. Pedersen)
Сообщения об ошибках на датском языке.
Арйен Дж. Ленц (Arjen G. Lentz)
Сооббщения об ошибках на немецком языке, завершение ранее начатого перевода.
Дэвид Сеседоут (David Sacerdote) davids@secnet.com
Идеи по проверке безопасности DNS-имен хостов.
Вэй-Джу Чен (Wei-Jou Chen) jou@nematic.ieo.nctu.edu.tw
Поддержка китайских символов (BIG5).
Вэй Хи (Wei He) hewei@mail.ied.ac.cn
Большое количество функциональных возможностей для китайской (GBK) кодировки.
Зеев Зураски (Zeev Suraski) bourbon@netvision.net.il
Форматирование значений времени в FROM_UNIXTIME(), функции ENCRYPT(); кроме того, он является консультантом по bison. Активный член списка рассылки.
Лук де Боуер (Luuk de Boer) luuk@wxs.nl
Перенос (и расширение) набора тестов производительности для DBI/DBD. Оказал большую помощь по тестам crash-me и тестам производительности. Некоторые новые функции даты. Скрипт mysql_setpermissions.
Джей Флагерти (Jay Flaherty) fty@mediapulse.com
Большая часть раздела DBI/DBD в этом руководстве.
Пол Саузвортс (Paul Southworth) pauls@etext.org, Рэй Лоуйзага (Ray
Loyzaga) yar@cs.su.oz.au Корректура данного справочного руководства на английском языке.
Алексей Михайлов (Alexis Mikhailov) root@medinf.chuvashia.su
Определяемые пользователем функции (UDF); функции CREATE и DROP.
Андреас Бобак (Andreas F. Bobak) bobak@relog.ch
Расширение AGGREGATE к функциям UDF.
Росс Уэйклин (Ross Wakelin) R.Wakelin@march.co.uk
Помощь в установке InstallShield для MySQL-Win32.
Джетро Райт III (Jethro Wright III) jetman@li.net
Библиотека `libmysql.dll'.
Джеймс Перейра (James Pereria) jpereira@iafrica.com
Mysqlmanager, Win32 GUI-программа для администрирования сервера MySQL.
Курт Сэмпсон (Curt Sampson) cjs@portal.ca
Перенос потоков MIT-pthreads на NetBSD/Alpha и NetBSD 1.3/i386.
Энтони Т. Куртис (Antony T. Curtis) antony.curtis@olcs.net
Перенос программного обеспечения базы данных MySQL на OS/2.
Мартин Рамш (Martin Ramsch) m.ramsch@computer.org
Примеры в учебнике MySQL.
Стив Харвей (Steve Harvey)
Благодарность за более безопасное выполнение mysqlaccess.
Конарк IA-64, Центр устойчивых систем, частная компания с ограниченной
ответственностью (Konark IA-64 Centre of Persistent Systems Private Limited) http://www.pspl.co.in/konark/. Помощь в переносе сервера MySQL на Win64.
Алберт Чин-Эй-Янг (Albert Chin-A-Young).
Конфигурирование обновлений для Tru64, поддержка больших файлов и улучшенная поддержка оболочек TCP.
Джон Бирел (John Birrell)
Эмуляция pthread_mutex() для OS/2.
Бенджамин Пфлюгманн (Benjamin Pflugmann)
Расширение таблиц MERGE для обработки запросов INSERT. Активный член списков рассылки MySQL.
Гильем Бишо (Guilhem Bichot)
Исправление трактовки показателя степени для DECIMAL. Автор mysql_tableinfo.
Джоселин Фурнье (Jocelyn Fournier)
Отличное исследование и описание бесчисленного количества ошибок (особенно в коде вложенных запросов в MySQL 4.1)
Джордж Ричтер (Georg Richter)
Тестирование и выявление ошибок в MySQL 4.1 Новое PHP 5.0 расширение mysqli (API) для использования с MySQL 4.1 и выше.
Марк Лиянаж (Marc Liyanage)
Поддерживает пакеты для Mac OS X и дает бесценную информацию о том, как создавать PKG для Mac OS X.

Другие помощники, те, кто нашел ошибки, и тестировщики: Джеймс Х. Томпсон (James H. Thompson), Морицио Менгини (Maurizio Menghini), Войцех Трик (Wojciech Tryc), Лука Берра (Luca Berra), Зарко Мокник (Zarko Mocnik), Уим Бонис (Wim Bonis), Элмар Хейнке (Elmar Haneke), jehamby@lightside, psmith@BayNetworks.com, duane@connect.com.au, Тед Депнер (Ted Deppner) ted@psyber.com, Майк Саймонс (Mike Simons), Джакко Хайватти (Jaakko Hyvatti).

Наша благодарность - за множество сообщений об ошибках и их исправлениях от участников списка рассылки.

Огромное уважение - тем, кто помогает нам отвечать на вопросы списка рассылки mysql@lists.mysql.com:

Дэниэл Кох (Daniel Koch) dkoch@amcity.com
Установка Irix.
Лук де Боуер (Luuk de Boer) luuk@wxs.nl
Вопросы по тестам производительности.
Тим Сэйлер (Tim Sailer) tps@users.buoy.com
Вопросы по DBD-mysql.
Бойд Лин Гербер (Boyd Lynn Gerber) gerberb@zenez.com
Вопросы, относящиеся к SCO.
Ричард Мехелик (Richard Mehalick) RM186061@shellus.com
Вопросы, относящиеся к xmysql, и вопросы базовой инсталляции.
Зеев Зураски (Zeev Suraski) bourbon@netvision.net.il
Вопросы по конфигурации модулей Apache (log & auth), вопросы, относящиеся к PHP, синтаксису SQL и другие общие вопросы.
Франциск Гуаш (Francesc Guasch) frankie@citel.upc.es
Общие вопросы.
Джонатан Дж Смит (Jonathan J Smith) jsmith@wtp.net
Вопросы, относящиеся к специфике операционных систем Linux, синтаксису SQL и другим вещам, которые могут понадобиться в работе.
Дэвид Склар (David Sklar) sklar@student.net
Использование MySQL совместно с PHP и Perl.
Элистер МакДоналд (Alistair MacDonald) A.MacDonald@uel.ac.uk
Пока не определился, легко переходит к новым темам, может справиться с Linux и, возможно, с HP-UX. Пытается заставить пользователей применять mysqlbug.
Джон Лайен (John Lyon) jlyon@imag.net
Вопросы по инсталляции MySQL на системах Linux с использованием либо файлов `.rpm', либо компиляции из исходного кода.
Лорвид Лтд. (Lorvid Ltd.) lorvid@WOLFENET.com
Простые вопросы выписки счетов, лицензии, поддержки, авторских прав.
Патрик Шерил (Patrick Sherrill) patrick@coconet.com
Вопросы по ODBC и интерфейсу VisualC++.
Рэнди Хармон (Randy Harmon) rjharmon@uptimecomputers.com
Вопросы по DBD, Linux, некоторые вопросы по синтаксису SQL.

B.3 Спонсоры MySQL

В то время как MySQL AB обладает всеми авторскими правами на сервер MySQL и документацию по MySQL, мы хотим отдать дань уважения следующим компаниям, оказывавшим нам финансовую помощь в разработке MySQL, такую как оплата разработки новых возможностей или снабжение техническими средствами.

VA Linux / Andover.net
Финансирование репликации.
NuSphere
Редактирование руководства по MySQL.
Студия Stork Design (Stork Design studio)
Веб-сайт MySQL, использовавшийся в 1998-2000гг.
Intel
Эта компания внесла вклад в разработку для платформ Windows и Linux.
Compaq
Эта компания внесла вклад в разработку для Linux/Alpha.
SWSoft
Разработка встроенной версии mysqld.
FutureQuest
--skip-show-databasea


Справочное руководство по MySQL версии 5.0.0-alpha. - C История изменений и обновлений MySQL

C История изменений и обновлений MySQL

Раздел в стадии перевода.

C.1 Изменения в версии 4.1.x (Alpha)

Раздел в стадии перевода.

C.1.1 Изменения в версии 4.1.0

Раздел в стадии перевода.

C.2 Изменения в версии 4.0.x (В разработке; Альфа)

Раздел в стадии перевода.

C.2.1 Изменения в версии 4.0.2

Раздел в стадии перевода.

C.2.2 Изменения в версии 4.0.1 (23 Дек 2001)

Раздел в стадии перевода.

C.2.3 Изменения в версии 4.0.0 (Окт 2001: Альфа)

Раздел в стадии перевода.

C.3 Изменения в версии 3.23.x (Стабильная)

Раздел в стадии перевода.

C.3.1 Изменения в версии 3.23.52

Раздел в стадии перевода.

C.3.2 Изменения в версии 3.23.51 (31 Май 2002)

Раздел в стадии перевода.

C.3.3 Изменения в версии 3.23.50 (21 Апр 2002)

Раздел в стадии перевода.

C.3.4 Изменения в версии 3.23.49

Раздел в стадии перевода.

C.3.5 Изменения в версии 3.23.48 (07 Фев 2002)

Раздел в стадии перевода.

C.3.6 Изменения в версии 3.23.47 (27 Дек 2001)

Раздел в стадии перевода.

C.3.7 Изменения в версии 3.23.46 (29 Ноя 2001)

Раздел в стадии перевода.

C.3.8 Изменения в версии 3.23.45 (22 Ноя 2001)

Раздел в стадии перевода.

C.3.9 Изменения в версии 3.23.44 (31 Окт 2001)

Раздел в стадии перевода.

C.3.10 Изменения в версии 3.23.43

Раздел в стадии перевода.

C.3.11 Изменения в версии 3.23.42 (08 Сен 2001)

Раздел в стадии перевода.

C.3.12 Изменения в версии 3.23.41 (11 Авг 2001)

Раздел в стадии перевода.

C.3.13 Изменения в версии 3.23.40

Раздел в стадии перевода.

C.3.14 Изменения в версии 3.23.39 (12 Июн 2001)

Раздел в стадии перевода.

C.3.15 Изменения в версии 3.23.38 (09 Май 2001)

Раздел в стадии перевода.

C.3.16 Изменения в версии 3.23.37 (17 Апр 2001)

Раздел в стадии перевода.

C.3.17 Изменения в версии 3.23.36 (27 Мар 2001)

Раздел в стадии перевода.

C.3.18 Изменения в версии 3.23.35 (15 Мар 2001)

Раздел в стадии перевода.

C.3.19 Изменения в версии 3.23.34a

Раздел в стадии перевода.

C.3.20 Изменения в версии 3.23.34 (10 Мар 2001)

Раздел в стадии перевода.

C.3.21 Изменения в версии 3.23.33 (09 Фев 2001)

Раздел в стадии перевода.

C.3.22 Изменения в версии 3.23.32 (22 Янв 2001: Стабильная)

Раздел в стадии перевода.

C.3.23 Изменения в версии 3.23.31 (17 Янв 2001)

Раздел в стадии перевода.

C.3.24 Изменения в версии 3.23.30 (04 Янв 2001)

Раздел в стадии перевода.

C.3.25 Изменения в версии 3.23.29 (16 Дек 2000)

Раздел в стадии перевода.

C.3.26 Изменения в версии 3.23.28 (22 Ноя 2000: Гамма)

Раздел в стадии перевода.

C.3.27 Изменения в версии 3.23.27 (24 Окт 2000)

Раздел в стадии перевода.

C.3.28 Изменения в версии 3.23.26

Раздел в стадии перевода.

C.3.29 Изменения в версии 3.23.25

Раздел в стадии перевода.

C.3.30 Изменения в версии 3.23.24 (08 Сен 2000)

Раздел в стадии перевода.

C.3.31 Изменения в версии 3.23.23

Раздел в стадии перевода.

C.3.32 Изменения в версии 3.23.22 (31 Июл 2000)

Раздел в стадии перевода.

C.3.33 Изменения в версии 3.23.21

Раздел в стадии перевода.

C.3.34 Изменения в версии 3.23.20

Раздел в стадии перевода.

C.3.35 Изменения в версии 3.23.19

Раздел в стадии перевода.

C.3.36 Изменения в версии 3.23.18

Раздел в стадии перевода.

C.3.37 Изменения в версии 3.23.17

Раздел в стадии перевода.

C.3.38 Изменения в версии 3.23.16

Раздел в стадии перевода.

C.3.39 Изменения в версии 3.23.15 (Май 2000: Бета)

Раздел в стадии перевода.

C.3.40 Изменения в версии 3.23.14

Раздел в стадии перевода.

C.3.41 Изменения в версии 3.23.13

Раздел в стадии перевода.

C.3.42 Изменения в версии 3.23.12

Раздел в стадии перевода.

C.3.43 Изменения в версии 3.23.11

Раздел в стадии перевода.

C.3.44 Изменения в версии 3.23.10

Раздел в стадии перевода.

C.3.45 Изменения в версии 3.23.9

Раздел в стадии перевода.

C.3.46 Изменения в версии 3.23.8

Раздел в стадии перевода.

C.3.47 Изменения в версии 3.23.7

Раздел в стадии перевода.

C.3.48 Изменения в версии 3.23.6

Раздел в стадии перевода.

C.3.49 Изменения в версии 3.23.5

Раздел в стадии перевода.

C.3.50 Изменения в версии 3.23.4

Раздел в стадии перевода.

C.3.51 Изменения в версии 3.23.3

Раздел в стадии перевода.

C.3.52 Изменения в версии 3.23.2

Раздел в стадии перевода.

C.3.53 Изменения в версии 3.23.1

Раздел в стадии перевода.

C.3.54 Изменения в версии 3.23.0 (Сен 1999: Альфа)

Раздел в стадии перевода.

C.4 Изменения в версии 3.22.x (Старая; все еще поддерживается)

Раздел в стадии перевода.

C.4.1 Изменения в версии 3.22.35

Раздел в стадии перевода.

C.4.2 Изменения в версии 3.22.34

Раздел в стадии перевода.

C.4.3 Изменения в версии 3.22.33

Раздел в стадии перевода.

C.4.4 Изменения в версии 3.22.32

Раздел в стадии перевода.

C.4.5 Изменения в версии 3.22.31

Раздел в стадии перевода.

C.4.6 Изменения в версии 3.22.30

Раздел в стадии перевода.

C.4.7 Изменения в версии 3.22.29

Раздел в стадии перевода.

C.4.8 Изменения в версии 3.22.28

Раздел в стадии перевода.

C.4.9 Изменения в версии 3.22.27

Раздел в стадии перевода.

C.4.10 Изменения в версии 3.22.26

Раздел в стадии перевода.

C.4.11 Изменения в версии 3.22.25

Раздел в стадии перевода.

C.4.12 Изменения в версии 3.22.24

Раздел в стадии перевода.

C.4.13 Изменения в версии 3.22.23

Раздел в стадии перевода.

C.4.14 Изменения в версии 3.22.22

Раздел в стадии перевода.

C.4.15 Изменения в версии 3.22.21

Раздел в стадии перевода.

C.4.16 Изменения в версии 3.22.20

Раздел в стадии перевода.

C.4.17 Изменения в версии 3.22.19 (Мар 1999: Стабильная)

Раздел в стадии перевода.

C.4.18 Изменения в версии 3.22.18

Раздел в стадии перевода.

C.4.19 Изменения в версии 3.22.17

Раздел в стадии перевода.

C.4.20 Изменения в версии 3.22.16 (Фев 1999: Гамма)

Раздел в стадии перевода.

C.4.21 Изменения в версии 3.22.15

Раздел в стадии перевода.

C.4.22 Изменения в версии 3.22.14

Раздел в стадии перевода.

C.4.23 Изменения в версии 3.22.13

Раздел в стадии перевода.

C.4.24 Изменения в версии 3.22.12

Раздел в стадии перевода.

C.4.25 Изменения в версии 3.22.11

Раздел в стадии перевода.

C.4.26 Изменения в версии 3.22.10

Раздел в стадии перевода.

C.4.27 Изменения в версии 3.22.9

Раздел в стадии перевода.

C.4.28 Изменения в версии 3.22.8

Раздел в стадии перевода.

C.4.29 Изменения в версии 3.22.7 (Сен 1998: Бета)

Раздел в стадии перевода.

C.4.30 Изменения в версии 3.22.6

Раздел в стадии перевода.

C.4.31 Изменения в версии 3.22.5

Раздел в стадии перевода.

C.4.32 Изменения в версии 3.22.4

Раздел в стадии перевода.

C.4.33 Изменения в версии 3.22.3

Раздел в стадии перевода.

C.4.34 Изменения в версии 3.22.2

Раздел в стадии перевода.

C.4.35 Изменения в версии 3.22.1 (Июн 1998: Альфа)

Раздел в стадии перевода.

C.4.36 Изменения в версии 3.22.0

Раздел в стадии перевода.

C.5 Изменения в версии 3.21.x

Раздел в стадии перевода.

C.5.1 Изменения в версии 3.21.33

Раздел в стадии перевода.

C.5.2 Изменения в версии 3.21.32

Раздел в стадии перевода.

C.5.3 Изменения в версии 3.21.31

Раздел в стадии перевода.

C.5.4 Изменения в версии 3.21.30

Раздел в стадии перевода.

C.5.5 Изменения в версии 3.21.29

Раздел в стадии перевода.

C.5.6 Изменения в версии 3.21.28

Раздел в стадии перевода.

C.5.7 Изменения в версии 3.21.27

Раздел в стадии перевода.

C.5.8 Изменения в версии 3.21.26

Раздел в стадии перевода.

C.5.9 Изменения в версии 3.21.25

Раздел в стадии перевода.

C.5.10 Изменения в версии 3.21.24

Раздел в стадии перевода.

C.5.11 Изменения в версии 3.21.23

Раздел в стадии перевода.

C.5.12 Изменения в версии 3.21.22

Раздел в стадии перевода.

C.5.13 Изменения в версии 3.21.21a

Раздел в стадии перевода.

C.5.14 Изменения в версии 3.21.21

Раздел в стадии перевода.

C.5.15 Изменения в версии 3.21.20

Раздел в стадии перевода.

C.5.16 Изменения в версии 3.21.19

Раздел в стадии перевода.

C.5.17 Изменения в версии 3.21.18

Раздел в стадии перевода.

C.5.18 Изменения в версии 3.21.17

Раздел в стадии перевода.

C.5.19 Изменения в версии 3.21.16

Раздел в стадии перевода.

C.5.20 Изменения в версии 3.21.15

Раздел в стадии перевода.

C.5.21 Изменения в версии 3.21.14b

Раздел в стадии перевода.

C.5.22 Изменения в версии 3.21.14a

Раздел в стадии перевода.

C.5.23 Изменения в версии 3.21.13

Раздел в стадии перевода.

C.5.24 Изменения в версии 3.21.12

Раздел в стадии перевода.

C.5.25 Изменения в версии 3.21.11

Раздел в стадии перевода.

C.5.26 Изменения в версии 3.21.10

Раздел в стадии перевода.

C.5.27 Изменения в версии 3.21.9

Раздел в стадии перевода.

C.5.28 Изменения в версии 3.21.8

Раздел в стадии перевода.

C.5.29 Изменения в версии 3.21.7

Раздел в стадии перевода.

C.5.30 Изменения в версии 3.21.6

Раздел в стадии перевода.

C.5.31 Изменения в версии 3.21.5

Раздел в стадии перевода.

C.5.32 Изменения в версии 3.21.4

Раздел в стадии перевода.

C.5.33 Изменения в версии 3.21.3

Раздел в стадии перевода.

C.5.34 Изменения в версии 3.21.2

Раздел в стадии перевода.

C.5.35 Изменения в версии 3.21.0

Раздел в стадии перевода.

C.6 Изменения в версии 3.20.x

Раздел в стадии перевода.

C.6.1 Изменения в версии 3.20.18

Раздел в стадии перевода.

C.6.2 Изменения в версии 3.20.17

Раздел в стадии перевода.

C.6.3 Изменения в версии 3.20.16

Раздел в стадии перевода.

C.6.4 Изменения в версии 3.20.15

Раздел в стадии перевода.

C.6.5 Изменения в версии 3.20.14

Раздел в стадии перевода.

C.6.6 Изменения в версии 3.20.13

Раздел в стадии перевода.

C.6.7 Изменения в версии 3.20.11

Раздел в стадии перевода.

C.6.8 Изменения в версии 3.20.10

Раздел в стадии перевода.

C.6.9 Изменения в версии 3.20.9

Раздел в стадии перевода.

C.6.10 Изменения в версии 3.20.8

Раздел в стадии перевода.

C.6.11 Изменения в версии 3.20.7

Раздел в стадии перевода.

C.6.12 Изменения в версии 3.20.6

Раздел в стадии перевода.

C.6.13 Изменения в версии 3.20.3

Раздел в стадии перевода.

C.6.14 Изменения в версии 3.20.0

Раздел в стадии перевода.

C.7 Изменения в версии 3.19.x

Раздел в стадии перевода.

C.7.1 Изменения в версии 3.19.5

Раздел в стадии перевода.

C.7.2 Изменения в версии 3.19.4

Раздел в стадии перевода.

C.7.3 Изменения в версии 3.19.3

Раздел в стадии перевода.


Справочное руководство по MySQL версии 5.0.0-alpha. - D Перенос на другие системы

D Перенос на другие системы

Цель данного раздела - обеспечить помощь в переносе MySQL на другие операционные системы. Но сначала необходимо ознакомиться со списком поддерживаемых в настоящее время операционных систем (see section 2.2.5 Операционные системы, поддерживаемые MySQL). Если вы создали новую версию переноса MySQL, пожалуйста, сообщите нам - тогда мы включим ее в настоящий список и в список на нашем веб-сайте (http://www.mysql.com/) и сможем рекомендовать ее другим пользователям.

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

Для сервера необходима рабочая библиотека Posix-потоков. Под операционной системой Solaris 2.5 мы используем потоки Sun PThreads ("родная" поддержка потоков в версии 2.4 и более ранних не является достаточно хорошей), а под Linux мы используем LinuxThreads, разработку Ксавье Лероя (Xavier Leroy, Xavier.Leroy@inria.fr).

При переносе на новый вариант Unix без хорошей поддержки собственных потоков наиболее трудной частью является перенос потоков MIT-pthreads. См. `mit-pthreads/README' и Programming POSIX Threads (Программирование POSIX-потоков) (http://www.humanfactor.com/pthreads/).

В состав поставки MySQL входит исправленная версия Pthreads Провензано (Provenzano) от MIT (см. веб-страницу MIT Pthreads на http://www.mit.edu:8001/people/proven/pthreads.html). Эту версию можно применять для операционных систем, не имеющих POSIX-потоков.

Можно использовать и другой пакет потоков пользовательского уровня - FSU Pthreads ( страница FSU Pthreads). Эта реализация применяется для переноса SCO.

Для ознакомления этими проблемами и анализа их следует изучить программы `thr_lock.c' и `thr_alarm.c' в каталоге `mysys'.

И сервер, и клиент нуждаются в работающем компиляторе C++ (мы используем gcc, испытывали также SPARCworks). Еще одним работающим компилятором является Irix cc.

Для компиляции только клиентской части используйте ./configure --without-server.

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

Если необходимо изменить любой `Makefile' или скрипт конфигурации, следует использовать Automake и Autoconf. Мы применяли версии automake-1.2 и autoconf-2.12.

Ниже перечислены действия, необходимые для того, чтобы собрать все заново из базовых файлов:

/bin/rm */.deps/*.P
/bin/rm -f config.cache
aclocal
autoheader
aclocal
automake
autoconf
./configure --with-debug=full --prefix='your installation directory'

# makefiles были сгенерированы для GNU make 3.75 или более новой,
# обозначенной как gmake строчкой ниже

gmake clean all install init-db

Если вы столкнетесь с проблемами новой версии переноса, то, возможно, потребуется произвести некоторую отладку MySQL! See section D.1 Отладка сервера MySQL.

Примечание: прежде чем запускать отладку mysqld, нужно добиться, чтобы заработала тестовая программа `mysys/thr_alarm' and `mysys/thr_lock', - тогда у вас появится хотя бы призрачный шанс получить рабочие потоки.

D.1 Отладка сервера MySQL

Если вы используете в MySQL совершенно новую функциональную возможность, то можно попробовать запустить mysqld с параметром --skip-new (при этом все новые, потенциально ненадежные функции будут заблокированы) или с параметром --safe-mode - он отключает ряд оптимизаций, которые могут вызвать проблемы. See section A.4.1 Что делать, если работа MySQL сопровождается постоянными сбоями.

Если mysqld не хочет стартовать, то необходимо посмотреть, не влияют ли на ваши настройки какие-либо конфигурационные файлы! Вы можете проверить аргументы файла `my.cnf' с помощью mysqld --print-defaults и, чтобы запретить их использование, стартовать mysqld с параметром --no-defaults ....

Если для запуска mysqld требуется большое количество ресурсов центрального процессора или памяти, а также в случае зависания программы можно использовать команду mysqladmin processlist status. Эта команда позволит определить, какой именно запрос требует столь длительного времени выполнения. При изучении проблем, связанных с производительностью или трудностями при подсоединении новых клиентов, иногда полезно запустить команду mysqladmin -i10 processlist status в другом окне.

Команда mysqladmin debug выводит в журнальный файл информацию о применяемых блокировках, используемой памяти и работе с запросами запросов - возможно, это поможет вам решить некоторые проблемы. Данная команда снабдит вас полезной информацией даже в том случае, если код MySQL не был скомпилирован для отладки!

Если проблема заключается в том, что некоторые таблицы справляются с работой все медленнее и медленнее, то такие таблицы необходимо попробовать оптимизировать с помощью команды OPTIMIZE TABLE или myisamchk. See section 4 Администрирование баз данных. Для проверки медленных запросов можно также использовать EXPLAIN.

Кроме того, чтобы решить уникальные для конкретных условий эксплуатации проблемы, необходимо изучить раздел данного руководства, в котором описывается специфика определенной операционной системы. See section 2.6 Заметки по операционным системам.

D.1.1 Компиляция MySQL для отладки

Иногда в случае каких-либо очень специфических проблем помогает отладка MySQL. Для этого необходимо сконфигурировать сборку MySQL с параметрами --with-debug или --with-debug=full. Чтобы проверить, был ли код MySQL скомпилирован с возможностью отладки, нужно запустить команду: mysqld --help. Если среди опций присутствует флаг --debug, то отладка доступна. Кроме того, если задана возможность отладки, команда mysqladmin ver выводит версию mysqld как mysql ... --debug.

При использовании компиляторов gcc или egcs рекомендуется следующая конфигурационная строка:

CC=gcc CFLAGS="-O2" CXX=gcc CXXFLAGS="-O2 -felide-constructors \
   -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql \
   --with-debug --with-extra-charsets=complex

Такая запись позволит избежать проблем с библиотекой libstdc++ и исключениями C++ (многие компиляторы имеют проблемы с исключениями C++ в кодах потоков) и скомпилировать версию MySQL с поддержкой всех кодировок.

Если есть подозрение, что может возникнуть ошибка переполнения памяти, то можно сконфигурировать MySQL с параметром --with-debug=full, чтобы установить программу контроля выделения памяти (SAFEMALLOC). Однако SAFEMALLOC замедляет работу системы, поэтому при возникновении проблем с производительностью необходимо запустить mysqld с опцией --skip-safemalloc. Эта опция заблокирует проверки переполнения памяти для каждого вызова malloc и free.

Если mysqld перестает падать в аварийном режиме при компиляции ее с параметром --with-debug, то, возможно, вы нашли ошибку в компиляторе или произошла ошибка синхронизации внутри MySQL. В этом случае можно попытаться добавить к переменным CFLAGS и CXXFLAGS в приведенной выше конфигурационной строке -g и не использовать параметр --with-debug. Если mysqld и после этого будет падать, то можно по меньшей мере подключить к ней отладчик gdb или использовать gdb для core-файла, чтобы выяснить, что происходит.

Если MySQL сконфигурирован для отладки, то автоматически становятся доступными множество дополнительных функций контроля надежности, которые отслеживают состояние mysqld. Если они обнаруживают что-либо "неожиданное", то информация об этом будет записана в поток вывода stderr, который safe_mysqld направит в журнал ошибок! Таким образом, если возникают какие-либо неожиданные проблемы с MySQL и при этом доступен исходный код дистрибутива, то первое, что необходимо сделать, - сконфигурировать MySQL для отладки! (А второе необходимое действие - это, конечно, послать письмо на mysql@lists.mysql.com и попросить помощи). Пожалуйста, для всех сообщений о сбоях или вопросов относительно используемой версии MySQL используйте скрипт mysqlbug!

В поставке MySQL для Windows файл mysqld.exe по умолчанию скомпилирован с поддержкой трассировочных файлов.

D.1.2 Создание трассировочных файлов

Если сервер mysqld не запускается или если вы можете вызвать его скорую аварийную остановку, то для выяснения причин неполадок можно попытаться создать трассировочный файл.

Для этого необходимо иметь mysqld, скомпилированный для отладки. Проверить, скомпилирован ли mysqld для отладки можно, выполнив mysqld -V. Если номер данной версии заканчивается на -debug, то она скомпилирована с поддержкой трассировочных файлов.

Запустите сервер mysqld с журналом трассировки в каталоге `/tmp/mysqld.trace' (или `C:\mysqld.trace' под Windows):

mysqld --debug

Под Windows необходимо также использовать флаг --standalone, чтобы mysqld не стартовал как сервис:

В окне DOS введите следующее:

mysqld --debug --standalone

После этого можно использовать клиента командной строки mysql.exe во втором окне DOS, чтобы воспроизвести проблему. Для остановки описанного выше сервера mysqld следует воспользоваться командой mysqladmin shutdown.

Следует учесть, что трассировочный файл получится очень большим! Чтобы получить трассировочный файл меньшего размера, можно использовать что-нибудь вроде:

mysqld --debug=d,info,error,query,general,where:O,/tmp/mysqld.trace

при этом в каталог `/tmp/mysqld.trace' будет выводиться только информация с наиболее интересными для вас признаками.

Если вы создаете отчет о подобных ошибках, то, пожалуйста, присылайте в соответствующий список рассылки только те строки из трассировочного файла, которые, по вашему мнению, имеют непосредственное отношение к ошибке! Те же, кто затрудняются определить место ошибки, могут загрузить на ftp трассировочный файл вместе с отчетом об ошибках по адресу ftp://support.mysql.com/pub/mysql/secret/, чтобы разработчики MySQL могли взглянуть на него.

Трассировочный файл создается с помощью пакета DBUG, автором которого является Фред Фиш (Fred Fish). See section D.3 Пакет DBUG.

D.1.3 Отладка mysqld при помощи gdb

В большинстве операционных систем можно запускать mysqld под отладчиком gdb - это позволяет получить больше информации при аварийных остановках mysqld,

С некоторыми более старыми версиями gdb под Linux, чтобы обеспечить возможность отладки потоков mysqld, необходимо использовать run --one-thread. В этом случае в каждый момент времени доступен для отладки только один поток. Нам остается только рекомендовать вам как можно быстрее заменить старые версии отладчика на версию gdb 5.1, поскольку отладка потоков в этой версии работает намного лучше!

При работе mysqld под отладчиком gdb необходимо заблокировать трассировку стеков при помощи --skip-stack-trace, что обеспечит возможность выявить ошибки сегмантацию внутри gdb.

Если постоянно подсоединяются новые пользователи, то отладка MySQL под gdb может оказаться достаточно сложным делом, поскольку gdb не освобождает память, занимаемую старыми потоками. Эту проблему можно устранить, запустив mysqld с параметрами -O thread_cache_size='max_connections+1'. В большинстве случаев даже простое использование -O thread_cache_size=5 может очень помочь!

Для получения дампа оперативной памяти под Linux, если mysqld падает по сигналу SIGSEGV, можно запустить mysqld с опцией --core-file. Этот файл оперативной памяти (core) можно использовать для обратной трассировки при выявлении причин останова mysqld:

shell> gdb mysqld core
gdb> backtrace full
gdb> exit

See section A.4.1 Что делать, если работа MySQL сопровождается постоянными сбоями.

При использовании версии gdb 4.17.x или выше под Linux необходимо установить в текущем каталоге файл `.gdb' со следующей информацией:

set print sevenbit off
handle SIGUSR1 nostop noprint
handle SIGUSR2 nostop noprint
handle SIGWAITING nostop noprint
handle SIGLWP nostop noprint
handle SIGPIPE nostop
handle SIGALRM nostop
handle SIGHUP nostop
handle SIGTERM nostop noprint

Если при отладке потоков с помощью gdb возникают проблемы, необходимо загрузить версию gdb 5.x и попробовать использовать ее вместо прежней. Новая версия отладчика gdb обеспечивает значительно улучшенную обработку потоков!

Ниже приводится пример отладки mysqld:

shell> gdb /usr/local/libexec/mysqld
gdb> run
...
backtrace full # Делайте это при аварийной остановке mysqld

Включите полученный вывод в письмо, сгенерированное с помощью mysqlbug, и пошлите это письмо по адресу mysql@lists.mysql.com.

Если mysqld зависает, можно попробовать использовать некоторые системные средства наподобие strace или /usr/proc/bin/pstack для выяснения, где именно произошло зависание mysqld.

strace /tmp/log libexec/mysqld

Если используется интерфейс Perl DBI, то можно получить отладочную информацию, используя метод trace или установив переменную окружения DBI_TRACE. See section 8.2.2 Интерфейс DBI.

D.1.4 Использование трассировки стека

В некоторых операционных системах журнал ошибок в случае смерти mysqld будет содержать трассировку стека. Эти данные можно использовать для выяснения, где (и, может быть, почему) умер mysqld (see section 4.9.1 Журнал ошибок). Для получения трассировки стека не следует компилировать mysqld с опцией -fomit-frame-pointer для gcc (see section D.1.1 Компиляция MySQL для отладки).

Если файл ошибок содержит что-нибудь похожее на следующее:

mysqld got signal 11;
The manual section 'Debugging a MySQL server' tells you how to use a
stack trace and/or the core file to produce a readable backtrace that may
help in finding out why mysqld died
Attemping backtrace. You can use the following information to find out
where mysqld died.  If you see no messages after this, something went
terribly wrong
stack range sanity check, ok, backtrace follows
0x40077552
0x81281a0
0x8128f47
0x8127be0
0x8127995
0x8104947
0x80ff28f
0x810131b
0x80ee4bc
0x80c3c91
0x80c6b43
0x80c1fd9
0x80c1686

то можно определить, где произошла остановка mysqld. Для этого нужно выполнить следующие действия:

  1. Скопируйте приведенные выше числовые значения в файл, например mysqld.stack.
  2. Создайте файл символов для сервера mysqld:
    nm -n libexec/mysqld > /tmp/mysqld.sym
    Следует учесть, что во многих бинарных поставках MySQL приведенный выше файл с именем `mysqld.sym.gz' уже имеется. В этом случае необходимо распаковать его следующим образом:
    gunzip < bin/mysqld.sym.gz > /tmp/mysqld.sym
  3. Выполните resolve_stack_dump -s /tmp/mysqld.sym -n mysqld.stack, чтобы вывести место остановки mysqld. Если и это не поможет определить причину останова mysqld, то следует сделать отчет об ошибке и включить в него данный вывод с комментарием. Следует учитывать, однако, что в большинстве случаев наличие лишь только трассировки стеков не поможет нам определить причину данной проблемы. Чтобы иметь возможность локализовать данный сбой или рекомендовать обходной путь, нам, как правило, необходимо знать, какой именно запрос привел к остановке mysqld и, желательно, иметь контрольный пример, чтобы мы могли воспроизвести данную проблему! See section 1.8.1.3 Как отправлять отчеты об ошибках или проблемах.

D.1.5 Использование журналов для определения причин ошибок в mysqld

Обратите внимание: перед запуском mysqld с --log необходимо проверить все используемые таблицы с помощью myisamchk (see section 4 Администрирование баз данных).

Если демон mysqld умрет или зависнет, следует запустить mysqld с опцией --log. Если аварийное завершение mysqld снова повторится, то можно исследовать часть журнала, относящуюся к запросу, убившему mysqld.

При использовании опции --log без имени файла данный журнал хранится в каталоге базе данных как ``hostname`.log'. В большинстве случаев именно последний запрос в системном журнале приводит к смерти mysqld, но при возможности лучше в этом убедиться: перезапустите mysqld и выполните найденный запрос из командной строки mysql. Если запрос выполняется, то следует протестировать все сложные запросы, которые не завершились.

Можно также попробовать выполнить команду EXPLAIN для всех выражений SELECT, которые занимают длительное время, чтобы убедиться, что mysqld правильно использует индексы. See section 5.2.1 Синтаксис оператора EXPLAIN (получение информации о SELECT).

Запросы, требующие слишком длительного времени для выполнения, можно выявить, запустив mysqld с параметром --log-slow-queries. See section 4.9.5 Журнал медленных запросов.

Если в журнале ошибок (обычно он имеет имя ``hostname`.err') присутствует запись "mysqld restarted", то у вас есть шанс найти запрос, вызывающий смерть mysqld. В этом случае необходимо проверить все таблицы с помощью команды myisamchk (see section 4 Администрирование баз данных) и проанализировать запросы в журналах MySQL, чтобы определить, какой из них не работает. Если такой запрос найден, прежде всего необходимо попытаться сделать апгрейд MySQL до новейшей версии. Если же это не помогает и нет ничего похожего в архиве списка рассылки mysql, пришлите отчет о данном сбое по адресу mysql@lists.mysql.com. Ссылки на архивы списка рассылки доступны по адресу http://lists.mysql.com/.

Если демон mysqld был запущен с параметром myisam-recover, то MySQL автоматически проверяет и пытается восстановить таблицы MyISAM (если они отмечены как "таблица не закрыта правильно" или "таблица повреждена"). В этом случае MySQL запишет в файл `hostname.err' предупреждение: "Warning: Checking table ...", за которым следует "Warning: Repairing table", если данную таблицу следует исправить. Если таких ошибок в журнале много, а mysqld перед этим не умирал со сбоем, то что-то работает неправильно и необходимы дальнейшие исследования. See section 4.1.1 Параметры командной строки mysqld.

Конечно, неожиданная смерть mysqld - событие малоприятное, но в этом случае следует не изучать сообщения "Checking table...", а попытаться найти причины остановки mysqld.

D.1.6 Создание контрольного примера при повреждении таблиц

Когда таблицы оказываются поврежденными или mysqld всегда дает сбой после некоторых команд, то можно провести испытания (если данный сбой воспроизводим). Для этого нужно выполнить следующие действия:

  • Остановите демон MySQL (с помощью команды mysqladmin shutdown).
  • Сделайте резервную копию таблиц (в качестве меры предосторожности на случай, если процесс исправления таблиц пройдет некорректно, хотя это и маловероятно).
  • Проверьте все таблицы с помощью команды myisamchk -s database/*.MYI. Исправьте некорректные таблицы с помощью команды myisamchk -r database/table.MYI.
  • Создайте еще раз резервные копии этих таблиц.
  • Переместите (или удалите совсем) все старые журнальные файлы из каталога данных MySQL, если нужно освободить больше места.
  • Запустите mysqld с --log-bin (see section 4.9.4 Бинарный журнал обновлений). Если вы хотите найти запрос, который приводит к сбою mysqld, то следует использовать --log --log-bin.
  • Когда таблица с искажениями будет получена, остановите сервер mysqld.
  • Восстановите систему из резервной копии.
  • Перезапустите сервер mysqld без --log-bin.
  • Выполните заново команды mysqlbinlog update-log-file | mysql. Обновленная запись в журнале сохраняется в каталоге баз данных MySQL с именем `hostname-bin.#'.
  • Если в результате вышеприведенной команды таблицы опять окажутся поврежденными или вы можете получить сбой в работе mysqld, то, значит, вы нашли повторяющуюся ошибку, которую можно исправить! Загрузите эти таблицы и запись из двоичного журнала по адресу ftp://support.mysql.com/pub/mysql/secret/ и пошлите письмо с описанием данной проблемы на bugs@lists.mysql.com или (если вы являетесь коммерческим пользователем) на support@mysql.com - и команда разработчиков MySQL устранит ошибку настолько быстро, насколько это возможно.

Для локализации проблемы можно также использовать скрипт mysql_find_rows, чтобы просто выполнить ряд обновляющих команд.

D.2 Отладка клиента MySQL

Чтобы иметь возможность отладки клиента MySQL с помощью встроенного отладчика, необходимо сконфигурировать сборку MySQL с --with-debug или --with-debug=full. See section 2.3.3 Типичные опции configure.

Перед запуском клиента следует установить переменную окружения MYSQL_DEBUG:

shell> MYSQL_DEBUG=d:t:O,/tmp/client.trace
shell> export MYSQL_DEBUG

Это заставит клиента генерировать трассировочный файл в `/tmp/client.trace'.

Если существуют проблемы с кодом конкретного клиента, необходимо попытаться соединиться с сервером и послать запрос, используя другой заведомо работоспособный клиент. Это следует делать при работе mysql в режиме отладки (предполагается, что данный экземпляр MySQL скомпилирован с возможностью отладки):

shell> mysql --debug=d:t:O,/tmp/client.trace

приведенный выше вызов снабдит вас полезной информацией для отчета об ошибках. See section 1.8.1.3 Как отправлять отчеты об ошибках или проблемах.

Если ваш клиент, имея "правильный" на первый взгляд код, отказывается устойчиво работать, необходимо проверить, соответствует ли включаемый файл `mysql.h' файлу вашей библиотеки mysql. Очень распространенная ошибка заключается в том, что используется старый файл `mysql.h' из MySQL старой установки с новой библиотекой MySQL.

D.3 Пакет DBUG

Сервер MySQL и большинство клиентов MySQL компилируются с пакетом DBUG, автором первой версии которого является Фред Фиш (Fred Fish). При конфигурации MySQL в отладочном режиме этот пакет дает возможность получить трассировочный файл для отладки программы. See section D.1.2 Создание трассировочных файлов.

Чтобы воспользоваться пакетом отладки, следует в вызове программы задать опцию --debug="..." или -#...

Большинство программ MySQL по умолчанию имеют отладочную строку, которая будет использована, если не задана опция --debug. По умолчанию трассировочный файл обычно находится в `/tmp/имя_программы.trace' под Unix и в `\имя_программы.trace' под Windows.

Строка управления отладкой представляет собой последовательность разделенных двоеточиями полей, как в следующем примере:

<field_1>:<field_2>:...:<field_N>

Каждое поле состоит из обязательного флагового символа, за которым следует необязательный символ "," и разделенный запятыми список модификаторов:

flag[,modifier,modifier,...,modifier]

В настоящее время распознаются следующие символы флагов:

Флаг | Описание
d | Разрешает вывод из макроса DBUG_<N> для текущего состояния. За этим флагом может следовать список ключевых слов. Если задан такой список, то из вывода макроса DBUG будет выбираться вывод только с данными ключевыми словами. Если задан пустой список ключевых слов, выбирается вывод всего макроса.
D | Задает задержку вывода после каждой строки отладчика. Аргумент представляет собой количество десятых долей секунд задержки в соответствии с возможностями машины. Т.е. D,20 означает задержку в две секунды.
f | Ограничивает отладку и/или трассировку и профайлинг только перечисленными в списке функциями. Обратите внимание: если задан нулевой список, то будут заблокированы все функции. Соответствующие флаги "d" или "t" должны также задаваться, данный флаг только ограничивает их действия, если они разрешены.
F | Идентифицирует имя исходного файла для каждой строки вывода отладки или трассировки.
i | Идентифицирует процесс указанием pid или идентификатором потока (thread id) в каждой строке вывода отладки или трассировки.
g | Разрешает профайлинг. Создает файл с именем `dbugmon.out', содержащий информацию, которую можно использовать для профайлинга программы. За этим флагом может следовать список ключевых слов; если такой список задан, то профайлинг будет применяться только для функций из этого списка. Если задан нулевой список ключевых слов, то профайлинг применяется ко всем функциям.
L | Идентифицирует номер строки исходного файла для каждой строки вывода отладки или трассировки.
n | Задает вывод глубины вложенности текущей функции для каждой строки вывода отладки или трассировки.
N | Задает нумерацию каждой строки в выводе dbug.
o | Переадресует выходной поток отладчика в указанный файл. По умолчанию вывод осуществляется в stderr.
O | То же, что и o, но указанный файл сбрасывается на диск каждый раз между операциями записи. При необходимости этот файл закрывается и снова открывается каждый раз между операциями записи.
p | Ограничивает действия отладчика указанным процессом. Процесс должен быть идентифицирован макросом DBUG_PROCESS и совпадать с указанным в списке для действий отладчика.
P | Выводит имя текущего процесса для каждой строки вывода отладки или трассировки.
r | Не наследовать уровень вложенности функции в предыдущем состоянии при переходе в новое состояние. Полезно, если вывод должен начинаться с левого поля.
S | Выполнять функцию _sanity(_file_,_line_) для каждой отлаженной функции, пока _sanity() не возвратит значение, отличное от 0. (Главным образом используется совместно с safemalloc для определения утечек памяти).
t | Разрешает трассировку вызовов функций/выход из функций. За этим параметром может следовать список (содержащий только один модификатор). Данный модификатор задает число - максимальный уровень вложения функций, ниже которого не производится вывод ни для отладочного, ни для трассировочного макросов. Параметр по умолчанию задается во время компиляции.

Ниже представлены некоторые примеры строк управления отладкой, которые можно применять в командной строке оболочки (символ "-#" обычно используется для внедрения управляющей строки в программу):

-#d:t
-#d:f,main,subr1:F:L:t,20
-#d,input,output,files:n
-#d:t:i:O,\\mysqld.trace

В MySQL обычно применяются следующие дескрипторы для вывода (совместно с опцией d): enter,exit,error,warning,info и loop.

D.4 Методы блокировки

В настоящее время MySQL поддерживает только табличную блокировку для таблиц типов ISAM/MyISAM и HEAP, страничную блокировку для таблиц BDB и строковую блокировку для таблиц InnoDB (see section 5.3.1 Как MySQL блокирует таблицы). Для таблиц MyISAM можно произвольным образом сочетать команды INSERT и SELECT без блокировок, поскольку поддерживается управление версиями (Versioning).

Начиная с версии 3.23.33 имеется возможность анализировать конфликты и конкуренцию блокировок таблиц в системе. Это делается путем проверки переменных Table_locks_waited и Table_locks_immediate.

Если вы хотите использовать тип таблиц с блокировкой уровня записи, то прежде, чем принимать такое решение, следует посмотреть, что делает данное приложение и какая принята модель выборки/обновления данных.

Аргументы в пользу строковой блокировки:

  • Меньше конфликтов блокировок при обращении к различным строкам из множества потоков.
  • Меньше изменений при откатах.
  • Возможна блокировка одной строки на длительное время.

Аргументы против строковой блокировки

  • Требуется больше памяти, чем при страничной или табличной блокировке.
  • При использовании большой части таблицы строковая блокировка работает медленнее в сравнении с блокировкой на уровне страниц или таблиц, поскольку требуется производить намного больше блокировок.
  • Определенно хуже других блокировок, если часто выполняется операция GROUP BY на значительной части данных или если приходится сканировать всю таблицу.
  • Для блокировок более высокого уровня также проще осуществить поддержку различных типов блокировок для настройки приложения, поскольку для них затраты на блокировку менее заметны, чем для строкового уровня блокировки.

Блокировки на уровне таблиц лучше, чем блокировки страничного/строкового уровня в следующих случаях:

  • Когда производится главным образом чтение.
  • При чтении и обновлении для строго заданных ключей; при обновлении или удалении строки, которая может быть извлечена чтением одного ключа:
    UPDATE table_name SET column=value WHERE unique_key#
DELETE FROM table_name WHERE unique_key=#
  • SELECT с INSERT (и очень мало операций UPDATE и DELETE).
  • Выполняется много операций просмотра и группировки GROUP BY на всей таблице без записи.

Другие возможности, кроме строчного/страничного уровня блокирования:

Управление версиями (Versioning), подобно тому, как это делается в MySQL для параллельных вставок. При этом один из пользователей может выполнять операцию записи в то же время, когда несколько пользователей производят чтение. Это означает, что данная база данных/таблица поддерживает различные представления для данных в зависимости от того, когда произошло обращение к ним. Существуют и другие названия этой возможности - перемещение по времени (time travel), метод копирования в момент записи (copy on write) или метод копирования по запросу (copy on demand).

Копирование по запросу во многих случаях значительно лучше, чем страничный или строковый уровень блокировки; однако в наиболее неблагоприятном варианте этот метод требует намного больше памяти, чем при использовании обычных блокировок.

Вместо использования блокировок строкового уровня можно применять блокировки уровня приложения (подобно get_lock/release_lock в MySQL). Конечно, такие блокировки годятся только для корректно работающих приложений.

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

Ниже приводится несколько советов по блокировкам в MySQL:

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

Одновременный доступ пользователей не представляет проблем, если не происходит смешивания обновлений и выборок, требующих проверки нескольких строк в одной и той же таблице.

В случае сочетания вставок и удалений в одной и той же таблице очень полезно применять INSERT DELAYED.

Для повышения скорости можно также использовать LOCK TABLES (несколько обновлений в рамках одной блокировки выполняются намного быстрее, чем обновления без блокировок). Целесообразно также распределять данные по различным таблицам.

Иногда проблемы со скоростью при блокировках таблиц в MySQL удается решить преобразованием ряда таблиц в таблицы типа InnoDB или BDB. See section 7.5 Таблицы InnoDB. See section 7.6 Таблицы BDB или BerkeleyDB.

Большое количество различных аспектов настройки приложения рассмотрено в разделе данного руководства, посвященном оптимизации (see section 5.2.12 Другие советы по оптимизации).

D.5 Замечания по потокам RTS

При попытке применить пакеты потоков RTS с MySQL автору пришлось столкнуться со следующими проблемами:

В этих пакетах используются старые версии большинства вызовов POSIX, поэтому очень утомительно создавать оболочки (wrapper) для всех функций. На мой взгляд, было бы легче изменить библиотеки этих потоков в соответствии с современной спецификацией POSIX.

Некоторые оболочки уже написаны (чтобы получить более подробную информацию, обращайтесь к `mysys/my_pthread.c').

Следует изменить, по меньшей мере, следующие аспекты:

В pthread_get_specific должен использоваться один аргумент, а в sigwait - два аргумента. Многие функции (по крайней мере, pthread_cond_wait, pthread_cond_timedwait) должны возвращать код ошибки или ошибку. Сейчас они возвращают -1 и устанавливают errno.

Еще одна проблема заключается в том, что потоки пользовательского уровня используют сигнал ALRM, преждевременно прекращающий работу многих функций (read, write, open...). MySQL должен повторять попытку выполнить такие вызовы в случае прерывания, но это не так легко проверить.

Наиболее значительная из нерешенных проблем заключается в следующем:

Чтобы получать alarm на уровне потока, я изменил mysys/thr_alarm.c - чтобы ожидать alarm с помощью функции pthread_cond_timedwait(). Однако оказалось, что это приводит к преждевременному прекращению работы с ошибкой EINTR. Чтобы понять, почему так получается, я пытался отладить библиотеку потока, но не смог найти никакого простого решения.

Для тех, кто хочет попробовать использовать MySQL с потоками RTS, я предлагаю следующее:

  • Измените функции, используемые MySQL из библиотеки потоков для POSIX. Это не должно занять много времени.
  • Скомпилируйте все библиотеки с -DHAVE_rts_threads.
  • Скомпилируйте thr_alarm.
  • Если существуют некоторые небольшие отличия в реализации, то они могут быть устранены изменением `my_pthread.h' и `my_pthread.c'.
  • Запустите thr_alarm. Если программа выполняется без каких-либо предупреждений, сообщений об ошибках или об аварийном выходе, значит, вы на правильном пути. Ниже приводится успешный прогон программы под Solaris:
    Main thread: 1
Thread 0 (5) started
Thread: 5  Waiting
process_alarm
Thread 1 (6) started
Thread: 6  Waiting
process_alarm
process_alarm
thread_alarm
Thread: 6  Slept for 1 (1) sec
Thread: 6  Waiting
process_alarm
process_alarm
thread_alarm
Thread: 6  Slept for 2 (2) sec
Thread: 6  Simulation of no alarm needed
Thread: 6  Slept for 0 (3) sec
Thread: 6  Waiting
process_alarm
process_alarm
thread_alarm
Thread: 6  Slept for 4 (4) sec
Thread: 6  Waiting
process_alarm
thread_alarm
Thread: 5  Slept for 10 (10) sec
Thread: 5  Waiting
process_alarm
process_alarm
thread_alarm
Thread: 6  Slept for 5 (5) sec
Thread: 6  Waiting
process_alarm
process_alarm

...
thread_alarm
Thread: 5  Slept for 0 (1) sec
end

D.6 Различия между разными потоковыми пакетами

Работа MySQL в значительной степени зависит от используемого потокового пакета. Таким образом, при выборе хорошей платформы для MySQL потоковый пакет играет очень важную роль.

Существуют по меньшей мере три типа потоковых пакетов:

  • Пользовательские потоки в одном процессе. Переключение потоков осуществляется сигналами (alarm) и библиотека потоков управляет всеми функциями, не поддерживающими потоки, с помощью блокировок. Операции чтения, записи и выборки обычно управляются программой выбора потоков, которая переключает их на другой поток, если текущий должен ожидать данные (речь идет о вызове select). Пакеты пользовательских потоков могут быть интегрированы в стандартные библиотеки (FreeBSD- и BSDI-потоки). Такие интегрированные пакеты требуют меньше затрат в сравнении с потоковыми пакетами, которые должны обрабатывать все ненадежные вызовы (MIT-pthreads, FSU Pthreads и потоки RTS). В некоторых средах (например SCO) все системные вызовы поддерживают потоки, так что обработка может быть выполнена очень просто (FSU Pthreads под SCO). Недостатки такого метода: поскольку все вызовы, для которых установлены соответствия, занимают мало времени, очень сложно контролировать обработку всех ситуаций. Обычно существуют также системные вызовы, не обрабатываемые потоковым пакетом (такие как MIT-pthreads и сокеты). Диспетчеризация потоков не всегда является оптимальной.
  • Пользовательские потоки в раздельных процессах. Переключение потоков производится ядром и все данные используются совместно всеми потоками. Потоковый пакет управляет стандартными вызовами потоков, чтобы обеспечить совместное использование данных этими потоками. Такой метод используется в LinuxThreads. Недостатки этого метода: масса процессов; медленное создание потока. Если один поток умирает, то остальные обычно зависают и необходимо их уничтожать перед перезапуском. Переключение потоков отчасти затратно.
  • Потоки ядра. Переключение потоков управляется потоковой библиотекой или ядром и происходит очень быстро. Все делается в одном процессе, но для некоторых систем ps может показывать разные потоки. Если один из потоков неожиданно умрет, то происходит аварийное прерывание всего процесса. Большинство системных вызовов поддерживают потоки и должны требовать очень небольших затрат. С потоками ядра работают Solaris, HP-UX, AIX и OSF/1.

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


Справочное руководство по MySQL версии 5.0.0-alpha. - E Переменные окружения

E Переменные окружения

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

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

Во многих случаях для изменения поведения MySQL более предпочтительно использовать конфигурационный файл. See section 4.1.2 Файлы параметров `my.cnf'.

Переменная | Описание
CCX | Устанавливается в компиляторе C++ при конфигурации.
CC | Устанавливается в компиляторе C при конфигурации.
CFLAGS | Флаги для компилятора C при конфигурации.
CXXFLAGS | Флаги для компилятора C++ при конфигурации.
DBI_USER | Имя пользователя по умолчанию для интерфейса Perl DBI.
DBI_TRACE | Используется при трассировке в Perl DBI.
HOME | Для файла истории mysql путь по умолчанию `$HOME/.mysql_history'.
LD_RUN_PATH | Используется для указания, где находится `libmysqlclient.so'.
MYSQL_DEBUG | Опции отладки-трассировки при отладке.
MYSQL_HISTFILE | Путь к файлу истории mysql.
MYSQL_HOST | Имя хоста по умолчанию, используемое для клиента командной строки mysql.
MYSQL_PS1 | Приглашение для использования в клиенте командной строки mysql. See section 4.8.2 mysql, Утилита командной строки.
MYSQL_PWD | Пароль по умолчанию при подключении к mysqld. Учтите, что использование этой переменной небезопасно!
MYSQL_TCP_PORT | Порт TCP/IP по умолчанию.
MYSQL_UNIX_PORT | Сокет по умолчанию; используется для подсоединений к локальной машине.
PATH | Используется оболочкой для поиска программ MySQL.
TMPDIR | Каталог, в котором создаются временные таблицы/файлы.
TZ | Должна быть установлена для локального часового пояса. See section A.4.6 Проблемы с часовыми поясами.
UMASK_DIR | Маска создания пользовательского каталога при создании каталогов. Учтите, что эта переменная дополняет UMASK!
UMASK | Маска создания пользовательского файла при создании файлов.
USER | Пользователь по умолчанию под Windows при подключении к mysqld.


Справочное руководство по MySQL версии 5.0.0-alpha. - F Регулярные выражения в MySQL

F Регулярные выражения в MySQL

Регулярные выражения (regex, regexp) представляют собой мощный способ выполнения сложного поиска.

В MySQL используется расширенная версия предложенной Генри Спенсером (Henry Spencer) реализации регулярных выражений, которая ориентирована на соответствие POSIX 1003.2.

В данном разделе приведен упрощенный справочник; подробности здесь опущены. Чтобы получить более точную информацию, обращайтесь к странице руководства Генри Спенсера regex(7), которая включена в дистрибутив исходного кода. See section B Благодарности.

Регулярное выражение описывает набор строк. Простейшее регулярное выражение не включает в себя специальных символов. Например, регулярное выражение hello означает совпадение с hello и ничего больше.

В нетривиальных регулярных выражениях используются определенные специальные конструкции - это обеспечивает возможность получать соответствие для более чем одной строки. Например, регулярное выражение hello|word соответствует как hello, так и word.

Можно привести и более сложный пример: регулярному выражению B[an]*s соответствует любая из строк: Bananas, Baaaaas, Bs, а также любая другая строка, начинающаяся с B, заканчивающаяся на s и содержащая любое количество символов a или n между ними.

В регулярном выражении могут использоваться любые специальные символы/структуры из числа приведенных ниже:

^
Соответствие началу строки.
mysql> SELECT "fo\nfo" REGEXP "^fo$"; 	-> 0
mysql> SELECT "fofo" REGEXP "^fo"; 	-> 1
$
Соответствие концу строки.
mysql> SELECT "fo\no" REGEXP "^fo\no$"; -> 1
mysql> SELECT "fo\no" REGEXP "^fo$"; 	-> 0
.
Соответствие любому символу (включая перевод строки).
mysql> SELECT "fofo" REGEXP "^f.*"; 	-> 1
mysql> SELECT "fo\nfo" REGEXP "^f.*"; 	-> 1
a*
Соответствие любой последовательности из нуля или более символов "a".
mysql> SELECT "Ban" REGEXP "^Ba*n"; 	-> 1
mysql> SELECT "Baaan" REGEXP "^Ba*n"; 	-> 1
mysql> SELECT "Bn" REGEXP "^Ba*n"; 	-> 1
a+
Соответствие любой последовательности из одного или более символов "a ".
mysql> SELECT "Ban" REGEXP "^Ba+n"; 	-> 1
mysql> SELECT "Bn" REGEXP "^Ba+n"; 	-> 0
a?
Соответствие как нулю, так и одному символу "a".
mysql> SELECT "Bn" REGEXP "^Ba?n"; 	-> 1
mysql> SELECT "Ban" REGEXP "^Ba?n"; 	-> 1
mysql> SELECT "Baan" REGEXP "^Ba?n"; 	-> 0
de|abc
Соответствие как последовательности de, так и последовательности abc.
mysql> SELECT "pi" REGEXP "pi|apa"; 		-> 1
mysql> SELECT "axe" REGEXP "pi|apa"; 		-> 0
mysql> SELECT "apa" REGEXP "pi|apa"; 		-> 1
mysql> SELECT "apa" REGEXP "^(pi|apa)$"; 	-> 1
mysql> SELECT "pi" REGEXP "^(pi|apa)$"; 	-> 1
mysql> SELECT "pix" REGEXP "^(pi|apa)$"; 	-> 0
(abc)*
Соответствие нулю или более вхождениям последовательности abc.
mysql> SELECT "pi" REGEXP "^(pi)*$"; 	-> 1
mysql> SELECT "pip" REGEXP "^(pi)*$"; 	-> 0
mysql> SELECT "pipi" REGEXP "^(pi)*$"; 	-> 1
{1}
{2,3}
Существует более общий способ написания регулярных выражений, позволяющий установить соответствия для нескольких вхождений предшествующего элемента.
a*
Можно записать как a{0,}.
a+
Можно записать как a{1,}.
a?
Можно записать как a{0,1}.
Точнее говоря, элемент, за которым следует ограничение, содержащее одно целое число i без запятой, соответствует последовательности, в точности состоящей из i вхождений данного элемента. Если за элементом следует ограничение, содержащее одно число i и запятую, то устанавливается соответствие для последовательности, содержащей i или более вхождений данного элемента. Если за элементом следует ограничение, содержащее два целых числа i и j, то устанавливается соответствие для последовательности от i до j (включительно) вхождений данного элемента. Оба аргумента должны находится в диапазоне от 0 до RE_DUP_MAX (по умолчанию 255) включительно. Если существуют оба аргумента, то второй должен быть больше первого или равен ему.
[a-dX]
[^a-dX]
Устанавливает соответствие для любого символа, являющегося (или не являющегося, если используется ^) символом a, b, c, d или X. Для литерального включения символа ] следует сразу же после него написать открывающую скобку [. Для литерального включения символа - он должен быть написан первым или последним. Таким образом, выражение [0-9] устанавливает соответствие для любой десятичной цифры. Любой символ, для которого не задано определенное значение внутри пары скобок [], не имеет специального значения и совпадает только с самим собой.
mysql> SELECT "aXbc" REGEXP "[a-dXYZ]"; 	-> 1
mysql> SELECT "aXbc" REGEXP "^[a-dXYZ]$"; 	-> 0
mysql> SELECT "aXbc" REGEXP "^[a-dXYZ]+$"; 	-> 1
mysql> SELECT "aXbc" REGEXP "^[^a-dXYZ]+$"; 	-> 0
mysql> SELECT "gheis" REGEXP "^[^a-dXYZ]+$"; 	-> 1
mysql> SELECT "gheisa" REGEXP "^[^a-dXYZ]+$"; 	-> 0
[[.characters.]]
Последовательность символов данного элемента сравнения. Эта последовательность представляет собой единственный элемент из списка в выражении в скобках. Выражение в скобках, содержащее многосимвольный сравнивающий элемент, может, следовательно, искать соответствие более, чем одного, например, если последовательность сравнения включает в себя элемент сравнения ch, то регулярное выражение [[.ch.]]*c устанавливает соответствие с первыми пятью символами выражения chchcc.
[=character_class=]
Класс эквивалентности, означающий, что последовательности символов всех элементов сравнения, включенных в данный класс, эквивалентны между собой. Например, если o и (+) являются членами класса эквивалентности, то последовательности [[=o=]], [[=(+)=]] и [o(+)] все являются синонимичными. Класс эквивалентности может не быть конечной точкой диапазона.
[:character_class:]
Имя класса символов, заключенное внутри выражения в скобках [: имя :], обозначает список всех символов, принадлежащих данному классу. Имена стандартных классов символов следующие:
Имя | Имя | Имя
alnum | digit | punct
alpha | graph | space
blank | lower | upper
cntrl | print | xdigit
Они обозначают классы символов, определенные на странице ctype(3). Локаль может предоставлять другие классы. Класс символов не может использоваться как конечная точка диапазона.
mysql> SELECT "justalnums" REGEXP "[[:alnum:]]+"; 	-> 1
mysql> SELECT "!!" REGEXP "[[:alnum:]]+"; 		-> 0
[[:<:]]
[[:>:]]
Эти выражения устанавливают соответствие с нулевой строкой в начале и в конце слова соответственно. Слово определяется как последовательность символов слова, которой не предшествуют и за которой не следуют символы слова. Под символом слова понимается любая буква или цифра (как определено в ctype(3)) или подчеркивание (_).
mysql> SELECT "a word a" REGEXP "[[:<:]]word[[:>:]]"; 		  -> 1
mysql> SELECT "a xword a" REGEXP "[[:<:]]word[[:>:]]"; 		  -> 0

mysql> SELECT "weeknights" REGEXP "^(wee|week)(knights|nights)$"; -> 1


Справочное руководство по MySQL версии 5.0.0-alpha. - G GNU General Public License

G GNU General Public License

Version 2, June 1991

Copyright © 1989, 1991 Free Software Foundation, Inc.
59 Temple Place - Suite 330, Boston, MA  02111-1307, USA

Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.

9.4 Preamble

The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too.

When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things.

To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it.

For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.

We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software.

Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations.

Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all.

The precise terms and conditions for copying, distribution and modification follow.

9.5 TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

  1. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The ``Program'', below, refers to any such program or work, and a ``work based on the Program'' means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term ``modification''.) Each licensee is addressed as ``you''. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does.
  2. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.
  3. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:
    1. You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change.
    2. You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License.
    3. If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.)
    These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.
  4. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following:
    1. Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
    2. Accompany it with a written offer, valid for at least three years, to give any third-party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
    3. Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.)
    The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code.
  5. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.
  6. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it.
  7. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License.
  8. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.
  9. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.
  10. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and ``any later version'', you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation.
  11. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.

    9.6 NO WARRANTY

  12. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM ``AS IS'' WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
  13. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

9.7 END OF TERMS AND CONDITIONS

9.8 How to Apply These Terms to Your New Programs

If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms.

To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the ``copyright'' line and a pointer to where the full notice is found.

one line to give the program's name and a brief idea of what it does.
Copyright (C) yyyy  name of author

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

Also add information on how to contact you by electronic and paper mail.

If the program is interactive, make it output a short notice like this when it starts in an interactive mode:

Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.

The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program.

You should also get your employer (if you work as a programmer) or your school, if any, to sign a ``copyright disclaimer'' for the program, if necessary. Here is a sample; alter the names:

Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.

signature of Ty Coon, 1 April 1989
Ty Coon, President of Vice

This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License.


Справочное руководство по MySQL версии 5.0.0-alpha. - H GNU Lesser General Public License

H GNU Lesser General Public License

Version 2.1, February 1999

Copyright © 1991, 1999 Free Software Foundation, Inc.
59 Temple Place -- Suite 330, Boston, MA 02111-1307, USA

Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.

[This is the first released version of the Lesser GPL.  It also counts
as the successor of the GNU Library Public License, version 2, hence the
version number 2.1.]

9.9 Preamble

The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users.

This license, the Lesser General Public License, applies to some specially designated software--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below.

When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things.

To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it.

For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights.

We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library.

To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others.

Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license.

Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs.

When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library.

We call this license the Lesser General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances.

For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License.

In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system.

Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library.

The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a ``work based on the library'' and a ``work that uses the library''. The former contains code derived from the library, whereas the latter must be combined with the library in order to run.

9.10 TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

  1. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called ``this License''). Each licensee is addressed as ``you''. A ``library'' means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The ``Library'', below, refers to any such software library or work which has been distributed under these terms. A ``work based on the Library'' means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term ``modification''.) ``Source code'' for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does.
  2. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.
  3. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:
    1. The modified work must itself be a software library.
    2. You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change.
    3. You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License.
    4. If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.)
    These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.
  4. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library.
  5. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code.
  6. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a ``work that uses the Library''. Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a ``work that uses the Library'' with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a ``work that uses the library''. The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a ``work that uses the Library'' uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether they are linked directly with the Library itself.
  7. As an exception to the Sections above, you may also combine or link a ``work that uses the Library'' with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things:
    1. Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable ``work that uses the Library'', as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.)
    2. Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at runtime a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with.
    3. Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution.
    4. If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place.
    5. Verify that the user has already received a copy of these materials or that you have already sent this user a copy.
    For an executable, the required form of the ``work that uses the Library'' must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute.
  8. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things:
    1. Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above.
    2. Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work.
  9. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.
  10. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it.
  11. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License.
  12. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.
  13. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.
  14. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and ``any later version'', you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation.
  15. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.

    9.11 NO WARRANTY

  16. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY ``AS IS'' WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
  17. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

9.12 END OF TERMS AND CONDITIONS

9.13 How to Apply These Terms to Your New Libraries

If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License).

To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the ``copyright'' line and a pointer to where the full notice is found.

one line to give the library's name and an idea of what it does.
Copyright (C) year  name of author

This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or (at
your option) any later version.

This library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
USA.

Also add information on how to contact you by electronic and paper mail.

You should also get your employer (if you work as a programmer) or your school, if any, to sign a ``copyright disclaimer'' for the library, if necessary. Here is a sample; alter the names:

Yoyodyne, Inc., hereby disclaims all copyright interest in the library
`Frob' (a library for tweaking knobs) written by James Random Hacker.

signature of Ty Coon, 1 April 1990
Ty Coon, President of Vice

That's all there is to it!


Справочное руководство по MySQL версии 5.0.0-alpha. - Команды SQL, функциональное оглавление

Команды SQL, функциональное оглавление

  • ! (логическое NOT)
  • != (не равно)
  • "
  • %, %
  • & (битовое AND)
  • && (логическое AND)
  • () (круглые скобки)
  • (Control-Z) \z
  • * (умножение)
  • + (сложение)
  • - (унарный минус)
  • - (вычитание)
  • .my.cnf файлы
  • / (деление)
  • /etc/passwd
  • < (меньше чем)
  • <<
  • << (левый сдвиг)
  • <= (меньше или равно)
  • <=> (равно)
  • <> (не равно)
  • = (равенство)
  • > (больше чем)
  • >= (больше или равно)
  • >> (правый сдвиг)
  • \" (двойная кавычка)
  • \' (одинарная кавычка)
  • \0 (ASCII 0)
  • \\
  • \b
  • \n
  • \r
  • \t (табуляция)
  • \z (Control-Z) ASCII(26)
  • ^ (побитовый XOR)
  • _
  • `

    • A

  • ABS()
  • ADDDATE()
  • AES_DECRYPT()
  • AES_ENCRYPT()
  • alias
  • ALTER COLUMN
  • ALTER TABLE, ALTER TABLE, ALTER TABLE
  • ANALYZE TABLE
  • AND, битовое
  • AND, логическое
  • AS, AS
  • ASCII()
  • ASIN()
  • ATAN(), ATAN()
  • ATAN2()
  • AUTO_INCREMENT, использование с DBI
  • AVG()

    • B

  • BACKUP TABLE
  • BEGIN
  • BENCHMARK()
  • BETWEEN ... AND
  • BIGINT
  • BIN()
  • BINARY
  • BIT
  • BIT_AND()
  • BIT_COUNT
  • BIT_COUNT()
  • BIT_LENGTH()
  • BIT_OR
  • BIT_OR()
  • BLOB, BLOB
  • BOOL

    • C

  • CASE
  • CAST
  • CC переменная окружения, CC переменная окружения
  • CC переменная окружения
  • CCX переменная окружения
  • CEILING()
  • CFLAGS переменная окружения, CFLAGS переменная окружения
  • CHAR, CHAR
  • CHAR VARYING
  • CHAR()
  • CHAR_LENGTH()
  • CHARACTER
  • CHARACTER VARYING
  • CHARACTER_LENGTH()
  • CHECK TABLE
  • COALESCE()
  • COMMIT, COMMIT
  • CONCAT()
  • CONCAT_WS()
  • CONNECTION_ID()
  • CONV()
  • CONVERT
  • COS()
  • COT()
  • COUNT()
  • COUNT(DISTINCT)
  • CREATE DATABASE
  • CREATE FUNCTION
  • CREATE TABLE
  • CROSS JOIN
  • CURDATE()
  • CURRENT_DATE
  • CURRENT_TIME
  • CURRENT_TIMESTAMP
  • CURRENT_USER()
  • CURTIME()
  • CXX переменная окружения
  • CXX переменная окружения, CXX переменная окружения, CXX переменная окружения
  • CXXFLAGS переменная окружения, CXXFLAGS переменная окружения, CXXFLAGS переменная окружения, CXXFLAGS переменная окружения

    • D

  • DATABASE()
  • DATE, DATE, DATE
  • DATE_ADD()
  • DATE_FORMAT()
  • DATE_SUB()
  • DATETIME, DATETIME
  • DAYNAME()
  • DAYOFMONTH()
  • DAYOFWEEK()
  • DAYOFYEAR()
  • DBI->ChopBlanks()
  • DBI->connect()
  • DBI->data_sources()
  • DBI->disconnect
  • DBI->do
  • DBI->execute
  • DBI->fetchall_arrayref()
  • DBI->fetchrow_array()
  • DBI->fetchrow_arrayref()
  • DBI->fetchrow_hashref()
  • DBI->finish()
  • DBI->prepare
  • DBI->quote()
  • DBI->rows()
  • DBI->trace()
  • DBI->{insertid}
  • DBI->{is_blob}
  • DBI->{is_key}
  • DBI->{is_not_null}
  • DBI->{is_num}
  • DBI->{is_pri_key}
  • DBI->{length}
  • DBI->{max_length}
  • DBI->{NAME}
  • DBI->{NULLABLE}
  • DBI->{NUM_OF_FIELDS}
  • DBI->{table}
  • DBI->{type}
  • DBI_TRACE переменная окружения
  • DBI_TRACE переменная окружения
  • DBI_USER переменная окружения
  • DEC
  • DECIMAL
  • DECODE()
  • DEGREES()
  • DELAYED
  • DELETE
  • DES_DECRYPT()
  • DES_ENCRYPT()
  • DESC
  • DESCRIBE, DESCRIBE
  • DISTINCT, DISTINCT, DISTINCT
  • DO
  • DOUBLE
  • DOUBLE PRECISION
  • DROP DATABASE
  • DROP FUNCTION
  • DROP INDEX, DROP INDEX
  • DROP TABLE
  • DUMPFILE

    • E

  • ELT()
  • ENCODE()
  • ENCRYPT()
  • ENUM
  • Environment variable, TZ
  • EXP()
  • EXPLAIN
  • EXPORT_SET()
  • EXTRACT()

    • F

  • FIELD()
  • FIND_IN_SET()
  • FLOAT, FLOAT
  • FLOAT(M,D)
  • FLOAT(точность), FLOAT(точность)
  • FLOOR()
  • FLUSH
  • FORCE INDEX, FORCE INDEX
  • FORMAT()
  • FOUND_ROWS()
  • FROM_DAYS()
  • FROM_UNIXTIME(), FROM_UNIXTIME()

    • G

  • GET_LOCK()
  • GRANT
  • GRANT statement
  • GRANTS
  • GREATEST()

    • H

  • HANDLER
  • HEX()
  • HOME переменная окружения
  • host.frm, проблемы поиска
  • HOUR()

    • I

  • IF()
  • IFNULL()
  • IGNORE INDEX, IGNORE INDEX
  • IGNORE KEY, IGNORE KEY
  • IN
  • INET_ATON()
  • INET_NTOA()
  • INNER JOIN
  • INSERT, INSERT
  • INSERT ... SELECT, INSERT ... SELECT
  • INSERT DELAYED
  • INSERT()
  • INSTR()
  • INT
  • INTEGER
  • INTERVAL()
  • IS NOT NULL
  • IS NULL
  • IS NULL, и индексы
  • IS_FREE_LOCK()
  • ISNULL()
  • ISOLATION LEVEL

    • J

  • JOIN

    • K

  • KILL

    • L

  • LAST_INSERT_ID(), LAST_INSERT_ID()
  • LCASE()
  • LD_RUN_PATH переменная окружения, LD_RUN_PATH переменная окружения, LD_RUN_PATH переменная окружения, LD_RUN_PATH переменная окружения
  • LEAST()
  • LEFT JOIN, LEFT JOIN
  • LEFT OUTER JOIN
  • LEFT()
  • LENGTH()
  • LIKE
  • LIKE, и индексы
  • LIKE, и шаблонные символы
  • LIMIT, LIMIT
  • LN()
  • LOAD DATA INFILE, LOAD DATA INFILE
  • LOAD_FILE()
  • LOCATE(), LOCATE()
  • LOCK TABLES
  • LOG()
  • LOG10()
  • LOG2()
  • LONGBLOB
  • LONGTEXT
  • LOWER()
  • LPAD()
  • LTRIM()

    • M

  • MAKE_SET()
  • MASTER_POS_WAIT()
  • MATCH ... AGAINST()
  • MAX()
  • MD5()
  • MEDIUMBLOB
  • MEDIUMINT
  • MEDIUMTEXT
  • MID()
  • MIN()
  • MINUTE()
  • MOD()
  • MONTH()
  • MONTHNAME()
  • my_init()
  • my_ulonglong значения, вывод
  • mysql_affected_rows()
  • mysql_change_user()
  • mysql_character_set_name()
  • mysql_close()
  • mysql_connect()
  • mysql_create_db()
  • mysql_data_seek()
  • MYSQL_DEBUG переменная окружения
  • MYSQL_DEBUG переменная окружения
  • mysql_debug()
  • mysql_drop_db()
  • mysql_dump_debug_info()
  • mysql_eof(), mysql_eof()
  • mysql_errno()
  • mysql_error()
  • mysql_escape_string()
  • mysql_fetch_field()
  • mysql_fetch_field_direct()
  • mysql_fetch_fields()
  • mysql_fetch_lengths()
  • mysql_fetch_row()
  • mysql_field_count(), mysql_field_count()
  • mysql_field_seek()
  • mysql_field_tell()
  • mysql_free_result()
  • mysql_get_client_info()
  • mysql_get_host_info()
  • mysql_get_proto_info()
  • mysql_get_server_info()
  • mysql_get_server_version()
  • MYSQL_HISTFILE переменная окружения
  • MYSQL_HOST переменная окружения
  • mysql_info()
  • mysql_info()
  • mysql_init()
  • mysql_insert_id()
  • mysql_insert_id()
  • mysql_kill()
  • mysql_list_dbs()
  • mysql_list_fields()
  • mysql_list_processes(), mysql_list_processes()
  • mysql_list_tables(), mysql_list_tables()
  • mysql_num_fields()
  • mysql_num_rows()
  • mysql_options()
  • mysql_ping()
  • MYSQL_PS1 переменная окружения
  • MYSQL_PWD переменная окружения
  • MYSQL_PWD переменная окружения
  • mysql_query(), mysql_query()
  • mysql_real_connect()
  • mysql_real_escape_string()
  • mysql_real_query()
  • mysql_reload()
  • mysql_row_seek()
  • mysql_row_tell()
  • mysql_select_db()
  • mysql_server_end()
  • mysql_server_init()
  • mysql_shutdown()
  • mysql_stat()
  • mysql_store_result(), mysql_store_result()
  • MYSQL_TCP_PORT переменная окружения
  • MYSQL_TCP_PORT переменная окружения
  • mysql_thread_end()
  • mysql_thread_id()
  • mysql_thread_init()
  • mysql_thread_safe()
  • MYSQL_UNIX_PORT переменная окружения, MYSQL_UNIX_PORT переменная окружения
  • MYSQL_UNIX_PORT переменная окружения
  • mysql_use_result()

    • N

  • NATIONAL CHAR
  • NATURAL LEFT JOIN
  • NATURAL LEFT OUTER JOIN
  • NATURAL RIGHT JOIN
  • NATURAL RIGHT OUTER JOIN
  • NCHAR
  • NOT BETWEEN
  • NOT IN
  • NOT LIKE
  • NOT REGEXP
  • NOT, логическое
  • NOW()
  • NULL, NULL, NULL
  • NULL value
  • NULLIF()
  • NUMERIC

    • O

  • OCT()
  • OCTET_LENGTH()
  • OLD_PASSWORD()
  • OPTIMIZE TABLE
  • OR, битовое
  • OR, логическое
  • ORD()
  • ORDER BY

    • P

  • PASSWORD(), PASSWORD(), PASSWORD()
  • PATH переменная окружения, PATH переменная окружения
  • PERIOD_ADD()
  • PERIOD_DIFF()
  • PI()
  • POSITION()
  • POW()
  • POWER()
  • PRIMARY KEY, PRIMARY KEY
  • PROCESSLIST

    • Q

  • QUARTER()
  • QUOTE()

    • R

  • RADIANS()
  • RAND()
  • REAL
  • REGEXP
  • RELEASE_LOCK()
  • RENAME TABLE
  • REPAIR TABLE
  • REPEAT()
  • REPLACE
  • REPLACE ... SELECT, REPLACE ... SELECT
  • REPLACE()
  • RESTORE TABLE
  • REVERSE()
  • REVOKE
  • RIGHT JOIN
  • RIGHT OUTER JOIN
  • RIGHT()
  • RLIKE
  • ROLLBACK, ROLLBACK
  • ROUND(), ROUND()
  • RPAD()
  • RTRIM()

    • S

  • SEC_TO_TIME()
  • SECOND()
  • SELECT
  • SELECT INTO TABLE
  • SELECT speed
  • SELECT, оптимизация
  • SESSION_USER()
  • SET, SET
  • SET OPTION
  • SET PASSWORD оператор
  • SET TRANSACTION
  • SHA()
  • SHA1()
  • SHOW COLUMNS
  • SHOW CREATE TABLE, SHOW CREATE TABLE
  • SHOW DATABASE INFO
  • SHOW DATABASES
  • SHOW FIELDS
  • SHOW GRANTS, SHOW GRANTS
  • SHOW INDEX
  • SHOW KEYS
  • SHOW MASTER LOGS
  • SHOW MASTER STATUS
  • SHOW PRIVILEGES
  • SHOW PROCESSLIST, SHOW PROCESSLIST
  • SHOW SLAVE STATUS
  • SHOW STATUS
  • SHOW TABLE STATUS
  • SHOW TABLE TYPES, SHOW TABLE TYPES
  • SHOW TABLES
  • SHOW VARIABLES
  • SHOW WARNINGS, SHOW WARNINGS
  • SIGN()
  • SIN()
  • SMALLINT
  • SOUNDEX()
  • SOUNDS LIKE
  • SPACE()
  • SQL_CACHE
  • SQL_NO_CACHE
  • START TRANSACTION
  • statements, GRANT
  • STD()
  • STDDEV()
  • STRAIGHT_JOIN
  • STRCMP()
  • SUBDATE()
  • SUBSTRING()
  • SUBSTRING_INDEX()
  • SUM()
  • SYSDATE()
  • SYSTEM_USER()

    • T

  • table_cache
  • TAN()
  • TEXT, TEXT
  • threads
  • TIME, TIME
  • TIME_FORMAT()
  • TIME_TO_SEC()
  • TIMESTAMP, TIMESTAMP
  • TINYBLOB
  • TINYINT
  • TINYTEXT
  • TMPDIR переменная окружения, TMPDIR переменная окружения
  • TO_DAYS()
  • TRIM()
  • TRUNCATE
  • TRUNCATE()
  • TZ environment variable
  • TZ переменная окружения

    • U

  • UCASE()
  • UDF функции
  • UMASK переменная окружения
  • UMASK_DIR переменная окружения
  • UNION, UNION
  • UNIQUE
  • UNIX_TIMESTAMP()
  • UNLOCK TABLES
  • UPDATE
  • UPPER()
  • USE
  • USE INDEX, USE INDEX
  • USE KEY, USE KEY
  • USER переменная окружения
  • USER()

    • V

  • VARCHAR, VARCHAR
  • VARIANCE()
  • VERSION()

    • W

  • WEEK()
  • WEEKDAY()
  • WHERE

    • X

  • XOR, логическое
  • XOR, побитовый

    • Y

  • YEAR, YEAR
  • YEAR()
  • YEARWEEK()

  • | (битовое OR)
  • || (логическое OR)
  • ~
  • арифметические функции
  • битовые функции
  • больше или равно (>=)
  • больше чем (>)
  • деление (/)
  • двойная кавычка (\"
  • файл .my.cnf, файл .my.cnf, файл .my.cnf, файл .my.cnf, файл .my.cnf
  • файл .mysql_history
  • файл .pid
  • функции даты и времени
  • функции потока управления
  • функции сравнения строк
  • функции, GROUP BY
  • функции, поток управления
  • функции, строки
  • идентивикаторы, квотинг
  • конвертирование
  • круглые скобки ( и )
  • квотинг идентификаторов
  • логические операторы
  • математические функции
  • меньше или равно (<=)
  • меньше чем (<)
  • метод DBI ChopBlanks()
  • метод DBI connect()
  • метод DBI data_sources()
  • метод DBI disconnect
  • метод DBI do
  • метод DBI execute
  • метод DBI fetchall_arrayref()
  • метод DBI fetchrow_array()
  • метод DBI fetchrow_arrayref()
  • метод DBI fetchrow_hashref()
  • метод DBI finish()
  • метод DBI insertid
  • метод DBI is_blob
  • метод DBI is_key
  • метод DBI is_not_null
  • метод DBI is_num
  • метод DBI is_pri_key
  • метод DBI length
  • метод DBI max_length
  • метод DBI NAME
  • метод DBI NULLABLE
  • метод DBI NUM_OF_FIELDS
  • метод DBI prepare
  • метод DBI quote()
  • метод DBI rows()
  • метод DBI table
  • метод DBI trace()
  • метод DBI type
  • минус, унарный (-)
  • не равно (!=)
  • не равно (<>)
  • одинарная кавычка (\')
  • опции configure, --with-charset
  • опции configure, --with-extra-charsets
  • опция -p
  • опция -password
  • опция without-server
  • оператор GRANT
  • оператор INSERT, назначить привилегии
  • операторы сравнения
  • операторы, INSERT
  • опреаторы, логические
  • определяемые пользователем функции
  • параметр -p
  • параметр -password
  • параметр REQUIRE GRANT
  • параметры командной строки
  • переменная окружения HOME
  • переменная окружения MYSQL_HISTFILE
  • переменная окружения MYSQL_HOST
  • переменная окружения MYSQL_PWD
  • переменная окружения MYSQL_TCP_PORT
  • переменная окружения MYSQL_TCP_PORT
  • переменная окружения MYSQL_UNIX_PORT
  • переменная окружения MYSQL_UNIX_PORT
  • переменная окружения UMASK
  • переменная окружения UMASK_DIR
  • переменная окружения USER
  • переменная окружения, CC
  • переменная окружения, CC, переменная окружения, CC
  • переменная окружения, CCX
  • переменная окружения, CFLAGS, переменная окружения, CFLAGS
  • переменная окружения, CXX
  • переменная окружения, CXX, переменная окружения, CXX, переменная окружения, CXX
  • переменная окружения, CXXFLAGS, переменная окружения, CXXFLAGS, переменная окружения, CXXFLAGS, переменная окружения, CXXFLAGS
  • переменная окружения, DBI_TRACE
  • переменная окружения, DBI_TRACE
  • переменная окружения, DBI_USER
  • переменная окружения, HOME
  • переменная окружения, HOME
  • переменная окружения, LD_RUN_PATH, переменная окружения, LD_RUN_PATH, переменная окружения, LD_RUN_PATH, переменная окружения, LD_RUN_PATH
  • переменная окружения, MYSQL_DEBUG
  • переменная окружения, MYSQL_DEBUG
  • переменная окружения, MYSQL_HISTFILE
  • переменная окружения, MYSQL_HISTFILE
  • переменная окружения, MYSQL_HOST
  • переменная окружения, MYSQL_HOST
  • переменная окружения, MYSQL_PS1
  • переменная окружения, MYSQL_PWD, переменная окружения, MYSQL_PWD
  • переменная окружения, MYSQL_PWD
  • переменная окружения, MYSQL_TCP_PORT, переменная окружения, MYSQL_TCP_PORT
  • переменная окружения, MYSQL_TCP_PORT, переменная окружения, MYSQL_TCP_PORT
  • переменная окружения, MYSQL_UNIX_PORT, переменная окружения, MYSQL_UNIX_PORT
  • переменная окружения, MYSQL_UNIX_PORT, переменная окружения, MYSQL_UNIX_PORT, переменная окружения, MYSQL_UNIX_PORT
  • переменная окружения, PATH, переменная окружения, PATH
  • переменная окружения, TMPDIR, переменная окружения, TMPDIR
  • переменная окружения, TZ
  • переменная окружения, UMASK, переменная окружения, UMASK
  • переменная окружения, UMASK_DIR, переменная окружения, UMASK_DIR
  • переменная окружения, USER
  • переменная окружения, USER
  • равенство (=)
  • разные функции
  • сложение (+)
  • сравнение строк, функции
  • строковые функции
  • табуляция (\t)
  • тип данных C my_ulonglong
  • тип данных C MYSQL
  • тип данных C MYSQL_FIELD
  • тип данных C MYSQL_FIELD_OFFSET
  • тип данных C MYSQL_RES
  • тип данных C MYSQL_ROW
  • умножение (*)
  • унарный минус (-)
  • вычитание (-)
  • шестнадцатиричные величины
  • Функции, определяемые пользователем
  • Типы

    • Go to the first, previous, next, last section, table of contents.


Справочное руководство по MySQL версии 5.0.0-alpha. - Концептуальное оглавление

Концептуальное оглавление

A

  • ACID
  • ACID
  • ACLs
  • ActiveState Perl
  • Apache
  • APIs
  • AUTO-INCREMENT, ODBC
  • AUTO_INCREMENT
  • AUTO_INCREMENT, и значения NULL

    • B

  • batch, опции mysql
  • Big5 китайский набор символов
  • bit_functions, пример
  • BLOB столбцы, индексация
  • BLOB столбцы, значения по умолчанию
  • BLOB, размер

    • C

  • C API
  • C API, функции
  • C++ Builder
  • C++ компилятор, gcc
  • cc1plus проблемы
  • character-sets-dir, опции mysql
  • ColdFusion
  • commands out of sync
  • compress, опции mysql
  • config.cache
  • connection, aborted
  • crash-me
  • cvs

    • D

  • database, опции mysql
  • DataJunction
  • DBI/DBD
  • debug-info, опции mysql
  • debug, опции mysql
  • default-character-set, опции mysql
  • delayed_insert_limit
  • Delphi
  • disk full
  • DNS

    • E

  • enable-named-commands, опции mysql
  • ENUM, размер
  • Errcode
  • errno
  • Excel
  • execute, опции mysql

    • F

  • fatal signal 11
  • force, опции mysql
  • foreign keys
  • FreeBSD, осторожно
  • full disk
  • FULLTEXT

    • G

  • gcc
  • General Public License
  • General Public License, MySQL
  • GPL, General Public License
  • GPL, GNU General Public License
  • GPL, MySQL
  • GROUP BY, псевдонимы в
  • GROUP BY, расширение к ANSI SQL

    • H

  • help, опции mysql
  • host, опции mysql
  • HP-UX, бинарная поставка
  • html, опции mysql

    • I

  • ignore-space, опции mysql
  • INSERT DELAYED
  • Internet Relay Chat
  • IRC

    • J

  • JDBC

    • L

  • LGPL, GNU Lesser General Public License
  • LGPL, GNU Library General Public License
  • LGPL, Lesser General Public License
  • LGPL, Library General Public License
  • libmysqld

    • M

  • Mac OS X, инсталяция
  • make_binary_distribution
  • max_allowed_packet
  • max_join_size
  • MIT-pthreads
  • MIT-потоки
  • mSQL и MySQL - различия в протоколе связи
  • mSQL совместимость
  • mSQL, MySQL и mSQL, обзор
  • msql2mysql
  • multi mysqld
  • multi-byte character sets
  • My, вариации
  • MyISAM, size
  • MyISAM, сжатые таблицы, MyISAM, сжатые таблицы
  • myisamchk, myisamchk
  • myisamchk, опции
  • myisamchk, параметры
  • myisamchk, пример вывода
  • myisampack, myisampack
  • MyODBC
  • MyODBC, сообщения о проблемах
  • mysql
  • MySQL и будущее
  • MySQL, определение
  • MySQL, произношение
  • MySQL, введение
  • mysql.sock, защита
  • mysql_fix_privilege_tables
  • mysql_install_db
  • mysqlaccess
  • mysqladmin, mysqladmin, mysqladmin, mysqladmin, mysqladmin, mysqladmin
  • mysqlbinlog, mysqlbinlog
  • mysqlbug
  • mysqlbug скрипт
  • mysqld
  • mysqld, запуск
  • mysqld-max
  • mysqld_multi
  • mysqld_safe
  • mysqldump, mysqldump
  • mysqlimport, mysqlimport, mysqlimport
  • mysqlshow
  • mysqltest, пакет тестирования MySQL

    • N

  • net_buffer_length
  • no-auto-rehash, опции mysql
  • no-beep, опции mysql
  • no-named-commands, опции mysql
  • no-pager, опции mysql
  • no-tee, опции mysql
  • Non-transactional tables
  • NULL значения, индексы
  • NULL, проверка на NULL, NULL, проверка на NULL
  • NULL, проверка на null, NULL, проверка на null

    • O

  • ODBC
  • ODBC совместимость, ODBC совместимость, ODBC совместимость, ODBC совместимость
  • ODBC, administrator
  • odbcadmin
  • one-database, опции mysql
  • OpenSSL
  • ORDER BY, псевдонимы в

    • P

  • pack_isam
  • pager, опции mysql
  • password, опции mysql
  • Perl DBI/DBD, проблемы инсталляции
  • Perl, инсталляция
  • Perl, инсталляция под Windows
  • perror
  • PHP API
  • PHP интерфейс
  • port, опции mysql
  • PostgreSQL и MySQL, сравнение
  • prompt, опции mysql
  • protocol, mysql option

    • Q

  • quick, опции mysql

    • R

  • raw, опции mysql
  • RedHat package manager
  • regex
  • regexp
  • replace
  • RPM, определение

    • S

  • safe-updates, опции mysql
  • safe_mysqld
  • SELECT, Кэш запросов
  • select_limit
  • SET, размер
  • set-variable var=option, опции mysql
  • silent, опции mysql
  • skip-column-names, опции mysql
  • skip-line-numbers, опции mysql
  • socket, опции mysql
  • Solaris, осторожно
  • SQL, определение
  • SSH
  • stripe
  • subSELECT

    • T

  • table cache
  • table is full
  • table, опции mysql
  • TCP/IP
  • tee, опции mysql
  • Texinfo
  • TEXT столбцы, индексация
  • TEXT столбцы, значения по умолчанию
  • TEXT, размер
  • TIMESTAMP, и значения NULL
  • TODO libmysqld

    • U

  • UDF, определение
  • UDF, возвращаемые значения
  • unbuffered, опции mysql
  • uptime
  • user, опции mysql

    • V

  • VARCHAR, размер
  • verbose, опции mysql
  • version, опции mysql
  • vertical, опции mysql
  • Visual Basic

    • W

  • wait, опции mysql
  • Windows
  • Windows против Unix
  • Windows, компиляция
  • Windows, вопросы открытости
  • Word

    • X

  • xml, опции mysql

    • Y

  • Y2K

  • администратор сервера
  • администратор, сервер
  • адрес электронной почты, коммерческая поддержка
  • анонимный пользоваетль
  • анонимный пользователь
  • апгрейд
  • апгрейд, 4.0 до 4.1
  • апгрейд, иные архитектуры
  • апгрейд, с 3.20 до 3.21
  • апгрейд, с 3.21 до 3.22
  • апгрейд, с 3.22 до 3.23
  • апгрейд, с 3.23 до 4.0
  • арифметические операторы
  • авария, восстановление
  • авторские права
  • база данных, определение
  • база данных, выбор
  • база данных, чувствительность к регистру
  • базы данных, MySQL и остальные
  • базы данных, дамп, базы данных, дамп
  • базы данных, имена
  • базы данных, использование
  • базы данных, получение информации
  • базы данных, просмотр
  • базы данных, резервное копирование
  • базы данных, символические ссылки
  • базы данных, создание
  • базы данных, замещение
  • бесплатное лицензирование
  • безопастность, от хакеров
  • библиотека mysqlclient
  • библиотека встраиваемого сервера
  • библиотека, mysqlclient
  • бинарная поставка, бинарная поставка
  • бинарная поставка, HP-UX
  • бинарная поставка, linux
  • бинарный дистрибутив
  • бинарный дистрибутив, установка
  • бинарный журнал обновлений
  • блокировка
  • блокировка на уровне строки
  • блокировка, таблицы
  • цели MySQL
  • целое число
  • цены, поддержка
  • цифры
  • дамп, базы данных, дамп, базы данных
  • данные, импорт
  • данные, кодировка
  • данные, набор символов
  • данные, размер
  • данные, выборка
  • данные, загрузка данных в таблицу
  • дата
  • дата, тип
  • даунгрейд
  • дерево BitKeeper
  • диск, распределение данных
  • добавить, кодировка
  • добавить, набор символов
  • добавить, привилегии, новый пользователь
  • добавление новых пользователей
  • добавление, новые функции
  • добавление, определяемых пользователем функций
  • добавление, процедуры
  • добавление, родных функции
  • допустимые имена
  • доступ для записи, `/tmp'
  • файл `config.cache'
  • файл `my.cnf'
  • файл mysql.sock, расположение
  • файл истории
  • файл скрипта
  • файл сокета, расположение
  • файл, лимиты размеров
  • файл, права доступа
  • файл, сообщение not found
  • файлы RPM
  • файлы параметров, файлы параметров
  • файлы журналов, файлы журналов
  • файлы журналов, обслуживание
  • файлы, `config.cache'
  • файлы, `my.cnf'
  • файлы, `tmp'
  • файлы, бинарный журнал
  • файлы, скрипт
  • файлы, сообщения об ошибках
  • файлы, текст
  • файлы, журнал медленных запросов
  • файлы, журнал обновлений
  • файлы, журнал запросов
  • файлы, журналы, файлы, журналы
  • файлы, восстановление
  • функции даты, год 2000
  • функции используемые для SELECT с WHERE
  • функции, группировка
  • функции, новые
  • функции, определяемые пользователем
  • функции, определяемые пользователем, определение
  • функция, удаление
  • глобальные привилегии
  • группировка, выражение
  • хакеры, обезопасить
  • хранилище данных
  • хранимые процедуры
  • хранимые процедуры и триггеры, определение
  • имена
  • имена баз данных, чувствительность к регистру
  • имена индексов
  • имена пользователей, и пароли
  • имена таблиц, чувствительность к регистру
  • имена, переменные
  • имена, чувствительность к регистру
  • именованные каналы
  • импорт, данные
  • имя MySQL
  • имя хоста по умолчанию
  • имя хоста, по умолчанию
  • имя псевдонима, чувствительность к регистру
  • имя столбца, чувствительность к регистру
  • имя таблицы, чувствительность к регистру
  • индекс, удаление, индекс, удаление
  • индексация, BLOB столбцы
  • индексация, TEXT столбцы
  • индексы
  • индексы, и IS NULL
  • индексы, и LIKE
  • индексы, использование
  • индексы, левый префикс
  • индексы, многостолбцовые
  • индексы, размер блока
  • индексы, составные
  • индексы, столбцы
  • информация о привилегиях, расположение
  • инсталляция, Perl
  • инсталляция, Perl на Windows
  • инсталляция, UDF
  • инсталляция, обзор
  • инсталляция, процедуры
  • инсталяция, Mac OS X PKG пакеты
  • интерфейс C
  • интерфейс C, функции
  • интерфейс C, проблемы с линкованием
  • интерфейс DBI
  • интерфейс Perl
  • интерфейсы
  • интерфейсы C++
  • интерфейсы Python
  • интерфейсы TCL
  • использование множества дисков для распределения данных
  • использование памяти, использование памяти
  • использование памяти, myisamchk
  • использование, MySQL
  • история MySQL
  • история командной строки
  • изменение поля
  • изменение привилегий
  • изменение расположения файла сокета `mysql.sock'
  • изменение столбца
  • изменение таблицы
  • изменение, таблица
  • изменения определений столбцов
  • изменения расположения файла сокета
  • изменить, порядок столбцов
  • изначальные, привелегии
  • известные проблемы
  • ключевое слово
  • ключевые слова
  • ключи
  • ключи, многостолбцовые
  • ключи, поиск по двум
  • ключи, внешние, ключи, внешние
  • клиент, поток
  • клиентские программы, линкование
  • клиентские утилиты
  • кодировка
  • кодировка, добавить
  • команда prompt
  • команда status, результаты
  • команды SQL, репликация
  • команды для установки бинарного дистрибутива
  • команды, репликация
  • комманда status
  • коммандная строка, ктилита
  • комманды, список
  • комментарии, добавление
  • комментарии, начало
  • коммерческая поддержка, адрес электронной почты
  • коммерческая поддержка, типы
  • коммуникационный протокол
  • компиляция, UDF
  • компиляция, на Windows
  • компиляция, оптимизация
  • компиляция, проблемы
  • компиляция, скорость
  • компиляция, статически
  • компилятор Borland C++
  • компилятор C++ не в состоянии создать исполняемый файл
  • компилятор, C++ gcc
  • консалтинг
  • консалтинг по MySQL
  • конструкция, ограничения
  • конструкция, особенность
  • консультации
  • консультации по MySQL
  • контактная информация
  • конвертация, утилиты MySQL
  • квадратные скобки
  • кэш, очиска
  • кэширование имен хостов
  • левый префикс индекса
  • лицензии
  • лицензирование
  • лицензирование, бесплатно
  • лицензирование, контактная информация
  • лицензирование, в примерах
  • лимиты, размер файла
  • линкование
  • линкование, проблемы
  • линкование, скорость
  • линкование, статически
  • линковка, ошибки
  • литералы
  • логотипы
  • максимальный объем памяти
  • медленные запросы
  • менеджер пакетов RedHat
  • место установки по умолчанию
  • многобайтовые символы
  • многостолбцовые индексы
  • модернизация, иные архитектуры
  • модули, список
  • модуль Perl DBI
  • монитор, терминал
  • набор символов
  • набор символов, кодировка
  • набор тестов
  • наименования, версий MySQL
  • настрйка, после установки
  • настройка master-slave
  • настройка головной сервер - подчиненный сервер
  • настройки, встраиваемый сервер
  • назначить, привилегии
  • начало комментария
  • нехватка виртуальной памяти при компиляции
  • несколько серверов
  • нобор символов, добавить
  • номера версий
  • обновление, таблицы
  • обновления версий MySQL
  • оборванные клиенты
  • оборванные соединения
  • обработка аргументов
  • обработка, ошибки
  • обработчик таблицы, выбор
  • обработчики таблиц MySQL
  • обслуживание, файлы журналов
  • обзор
  • обзор инсталляции
  • общая информация
  • оценка, производительность запросов
  • ограничения, конструкция
  • окрытый код, определение
  • опции
  • опции mysqld
  • опции mysqld
  • опции исправления, myisamchk
  • опции конфигурации
  • опции, configure
  • опции, myisamchk
  • опции, командная строка
  • опции, командная строка, mysql
  • опции, репликации
  • опция configure, --with-low-memory
  • операционные системы, Windows против Unix
  • операционные системы, файловый лимит
  • операционные системы, поддерживаемые
  • операторы конвертирования
  • операторы, арифметические
  • определение символов
  • определение, символов
  • определяемые пользователем функции, добавление, определяемые пользователем функции, добавление
  • оптимизация, оптимизация
  • оптимизация системы
  • оптимизация, DISTINCT
  • оптимизация, LEFT JOIN
  • оптимизация, LIMIT
  • оптимизация, советы
  • оптимизация, таблицы
  • основные возможности MySQL
  • основы SSL и X509
  • остановка сервера
  • остановка сервера, автоматическая
  • остановка, автоматическая
  • осторожно: FreeBSD
  • осторожно: Solaris
  • отказ от значений по умолчанию
  • открытие, таблицы
  • открытые таблицы, открытые таблицы
  • открытые, таблицы
  • отобрать, привилегии
  • отображение, статус таблиц
  • отрицательные значения
  • отсоединение, от сервера
  • отсутсвие строк, удовлетворяющих условиям поиска
  • ответы на вопросы, рекомендации
  • отчет об ошибке, критерии
  • отчет, ошибки
  • отчет, проблемы с MyODBC
  • ошибки access denied
  • ошибки округления
  • ошибки, access denied
  • ошибки, известные
  • ошибки, линковка
  • ошибки, обработка в UDF
  • ошибки, отчет
  • ошибки, отчеты, ошибки, отчеты
  • ошибки, проверка таблиц
  • ошибки, распространенные
  • ошибки, сообщения
  • ошибки, список
  • очистка, кэш
  • пакетный режим
  • параметр config-file
  • параметр example
  • параметр help
  • параметр log
  • параметр mysqladmin
  • параметр mysqld
  • параметр no-log
  • параметр password
  • параметр tcp-ip
  • параметр user
  • параметр version
  • параметры касающиеся SSL
  • параметры командной строки mysql
  • параметры командной строки, mysql
  • параметры по умолчанию
  • параметры запуска
  • параметры запуска, mysql
  • параметры запуска, настройка
  • параметры запуска, по умолчанию
  • параметры, myisamchk
  • параметры, сервер
  • пароли, безопастность
  • пароли, для пользователей
  • пароли, установка
  • пароль root
  • пароль, переустановить
  • пароль, пользователь root
  • пароль, установить, пароль, установить
  • пароль, забыт
  • партнерство с MySQL AB
  • патчи, применение
  • переконфигурация, переконфигурация
  • переменная connect_timeout
  • переменные окружения, переменные окружения, переменные окружения, переменные окружения
  • переменные пользователя
  • переменные, mysqld
  • переменные, пользователь
  • переменные, системные
  • переменные, статус
  • переменные, значения
  • переносимость
  • переполнение диска
  • пересоздать, таблицы привелегий
  • плавающая точка
  • поддержка
  • поддержка потоков
  • поддержка потоков, привнесенная
  • поддержка языков
  • поддержка, адрес электронной почты
  • поддержка, лицензирование
  • поддержка, операционные системы
  • поддержка, типы
  • подсчет, строки таблицы
  • подзапросы
  • поиск, два ключа
  • поиск, и чувствиетльность к регистру
  • поиск, полнотекстовый
  • поиск, веб странички MySQL
  • показ, информация по базам данным
  • поле, изменение
  • политика лицензирования
  • полнотекстовый поиск
  • получение MySQL
  • получение, информации, SHOW
  • пользователи, MySQL
  • пользователи, root
  • пользователи, добавление
  • пользователь root, переустановить пароль
  • помощники, сделавшие вклад в MySQL
  • порядок, столбцы
  • портативность, типы
  • после инсталяции, много серверов
  • после инсталяции, несколько серверов
  • последняя запись, уникальный ID
  • поставка исходных текстов
  • поставка исходных текстов, установка
  • потоки, потоки
  • потоки, клиенты
  • потоки, показывать
  • потоковый клиент
  • повторный запуск configure
  • повторый запуск сервера
  • права доступа
  • права пользователя, добавить
  • права, доступ
  • приглашение, значения
  • применение патчей
  • пример, сжатые таблицы
  • примеры
  • примеры, вывод myisamchk
  • примеры, запросы
  • привилегии доступа
  • привилегии, дать
  • привилегии, добавить
  • привилегии, доступ
  • привилегии, изменение
  • привилегии, изначальные
  • привилегии, отобрать
  • привилегии, показать
  • привилегии, посмотреть
  • проблема 2000 года
  • проблема-2000
  • проблемы инсталляции, Solaris
  • проблемы инсталляции, tar
  • проблемы инсталляции, контрольные суммы
  • проблемы при запуске сервера
  • проблемы с временными зонами
  • проблемы в `sql_yacc.cc'
  • проблемы, MyODBC
  • проблемы, блокировка таблиц
  • проблемы, инсталляция Perl
  • проблемы, инсталляция на IBM AIX
  • проблемы, известные
  • проблемы, компиляция
  • проблемы, линковка
  • проблемы, отчеты
  • проблемы, ошибки access denied
  • проблемы, распространенные ошибки
  • проблемы, сообщения
  • проблемы, столбец типа DATE
  • проблемы, временные зоны
  • проблемы, запуск сервера
  • проблемы, значение времени
  • процедуры, добавление
  • процессы, показывать
  • продажа продуктов
  • продукты, продажа
  • проектирование базы данных
  • профилактика, таблицы
  • программа crash-me, программа crash-me
  • программы для Access
  • программы для ADO
  • программы для Borland Builder 4
  • программы, crash-me
  • программы, клиенты
  • программы, список, программы, список
  • произношение, MySQL
  • производительность
  • производительность, оценка
  • производительность, тесты
  • производительность, улучшение
  • производительность, увеливечение
  • просмотр, информация по базам данным
  • пространство для ключей, MyISAM
  • протокол коммуникации
  • протокол связи
  • провайдеры услуг Internet
  • провайдеры услуг интернет
  • проверка прав, эффект на скорость
  • проверка, таблиц на ошибки
  • проверочные опции, myisamchk
  • псевдоним таблицы
  • псевдонимы в GROUP BY
  • псевдонимы выражений, псевдонимы выражений
  • псевдонимы, имена
  • псевдонимы, в ORDER BY
  • работа на MySQL
  • работа на веб-сервере
  • работа в режиме ANSI
  • работа, контактная информация
  • расположение руководства в сети
  • расширения по сравнению с ANSI SQL
  • расширения по сравнению с ANSI SQL92
  • размер буфера, сервер mysqld
  • размер ранилища, минимизция
  • размер таблиц
  • размер вывода
  • размеры буферов, клиент
  • разработчики, список
  • реклама, контактная информация
  • реляционная база данных, определение
  • ремонт, таблицы
  • репликация
  • репликация, команды
  • рестарт сервера
  • режим, пакетный
  • резервное копирование
  • резервное копирование, базы данных, резервное копирование, базы данных, резервное копирование, базы данных
  • родная поддержка потоков
  • родные функции, добавление
  • руководство, доступные форматы
  • руководство, онлайн
  • руководство, типографские соглашения
  • сбои, повторяющиеся
  • сборка, клиентские программы
  • сценарий mysql_install_db
  • сценарий mysqlbug, расположение
  • сертификация
  • сертификация MySQL
  • сервер mysqld, размер буфера
  • сервер, отсоединение
  • сервер, перезапуск
  • сервер, соединение, сервер, соединение
  • сервера, несколько
  • сервисы провайдеров
  • сервисы, провайдеры
  • сервисы, веб
  • сетевая маска, в таблице mysql.user
  • сетевой этикет, сетевой этикет
  • схемы установки
  • символические ссылки
  • символьные ссылки
  • символы экранирования
  • символы, многобайтовые
  • синтаксис команд
  • синтаксис оболочки
  • система безопастности
  • система привелегий, описание
  • система привилегий
  • система, безопастность
  • система, права
  • система, привилегии
  • системная таблица
  • системные переменные
  • скобки, квадратные
  • скорость, компиляция
  • скорость, линкование
  • скорость, увеличение
  • скорость, вставка
  • скорость, запросов, скорость, запросов
  • скрипт configure
  • скрипт mysql_install_db
  • скрипт mysqlbug
  • скрипты, скрипты, скрипты
  • соединение через SSH
  • соединение, проверка
  • соединение, с сервером, соединение, с сервером
  • соединение, верификация
  • соглашения, типографские
  • сообдения, языки
  • сообщение об ошибках, просмотр
  • сообщение об ошибке, can't find file
  • сообщения о, ошибки
  • сообщения об ошибках, адрес электронной почты
  • сообщения об ошибках, языки
  • соритровка, таблицы привелегий
  • сортировка, данные
  • сортировка, кодировка
  • сортировка, набор символов
  • сортировка, строки таблицы
  • сортировка, таблица привилегий
  • составной индекс
  • советы
  • советы, оптимизация
  • совместимость Oracle
  • совместимость с mSQL
  • совместимость с ODBC, совместимость с ODBC, совместимость с ODBC, совместимость с ODBC, совместимость с ODBC
  • совместимость с Oracle
  • совместимость с PostgreSQL
  • совместимость с Sybase
  • совместимость со стандартами
  • совместимость, между версиями MySQL, совместимость, между версиями MySQL, совместимость, между версиями MySQL, совместимость, между версиями MySQL
  • совместимость, с ANSI SQL
  • создание, базы данных
  • создание, параметры запуска по умолчанию
  • создание, таблицы
  • списки рассылки MySQL
  • списки рассылки, архивы
  • списки рассылки, рекомендации
  • список рассылки, список рассылки
  • список задач к выполнению
  • спонсоры MySQL
  • сравнение по шаблонам
  • сравнение строк, чувствительность к регистру
  • сравнение, MySQL и остальные
  • сравнение, шаблоны
  • ссылки
  • ссылки для загрузки MySQL
  • ссылки, символические
  • стабильность
  • старт и стоп
  • статус, таблицы
  • стоимость лицензирования
  • стоимость поддержки
  • стоимость, поддержка
  • столбцы, другие типы
  • столбцы, имена
  • столбцы, индексы
  • столбцы, изменить
  • столбцы, просмотр
  • столбцы, типы
  • столбцы, требования к памяти
  • столбцы, выборка
  • столбец типа DATE, проблемы
  • столбец, изменение
  • строка, блокировка
  • строки, определение
  • строки, подсчет
  • строки, сортировка
  • строки, типы
  • строки, удаление
  • строки, удовлетворять условиям поиска
  • строки, упорядочивание
  • строки, выборка
  • строки, экранируемые символы
  • строчная блокировка
  • структура каталогов, по умолчанию
  • суперпользователь
  • сжатые таблицы, сжатые таблицы
  • сьрос таблиц
  • таблица host
  • таблица user, сортировка
  • таблица, host
  • таблица, изменение
  • таблица, константа
  • таблица, удаление
  • таблица, выборка столбцов
  • таблицы BDB, таблицы BDB
  • таблицы BerkeleyDB
  • таблицы db, сортировка
  • таблицы HEAP
  • таблицы host, сортировка
  • таблицы InnoDB, таблицы InnoDB
  • таблицы ISAM
  • таблицы MERGE
  • таблицы MERGE, определение
  • таблицы MyISAM
  • таблицы привелегий, пересоздать
  • таблицы привелегий, сортировка
  • таблицы привилегий
  • таблицы привилегий, сортировка
  • таблицы, BDB
  • таблицы, Berkeley DB
  • таблицы, HEAP
  • таблицы, ISAM
  • таблицы, блокировка
  • таблицы, дамп, таблицы, дамп
  • таблицы, дефрагментация, таблицы, дефрагментация, таблицы, дефрагментация
  • таблицы, динамические
  • таблицы, фрагментация
  • таблицы, имена
  • таблицы, информация
  • таблицы, изменение
  • таблицы, изменение порядка столбцов
  • таблицы, максимальный размер
  • таблицы, настройка профилактики
  • таблицы, несколько
  • таблицы, объединение
  • таблицы, оптимизация
  • таблицы, открытие
  • таблицы, открытые
  • таблицы, поддерживающие транзакции
  • таблицы, подсчет строк
  • таблицы, получение информации
  • таблицы, права
  • таблицы, привелегии
  • таблицы, просмотр
  • таблицы, проверка
  • таблицы, проверка ошибок
  • таблицы, ремонт
  • таблицы, сброс
  • таблицы, символические ссылки
  • таблицы, система
  • таблицы, слишком много
  • таблицы, сортировка строк
  • таблицы, создание
  • таблицы, статус
  • таблицы, сжатие
  • таблицы, сжатый формат
  • таблицы, удаление строк
  • таблицы, улучшение производительности
  • таблицы, выборка данных
  • таблицы, выборка строк
  • таблицы, загрузка данных
  • таблицы, закрытие
  • таймаут
  • техническая поддержка, адрес электронной почты
  • техническая поддержка, лицензирование
  • текстовые файлы, импорт
  • терминальный монитор, определение
  • тестирование mysqld, mysqltest
  • тестирование сервера
  • тестирование, инсталляция
  • тестирование, послеустановочная настройка
  • тестирование, соединение с сервером
  • тестирование, выпуск MySQL
  • тесты
  • тип дата, Y2K проблема
  • тип даты
  • тип времени
  • типографские соглашения
  • типы данных
  • типы данных даты и времени
  • типы данных, C
  • типы конвертирования
  • типы поддержки
  • типы таблиц MySQL
  • типы таблиц, выбор
  • типы, дата и время
  • типы, портативность
  • типы, столбцы, типы, столбцы
  • типы, строки
  • типы, число
  • торговые марки
  • транзакции, поддержка, транзакции, поддержка
  • транзакционно-безопасные таблицы
  • транзакионно-безопасные таблицы
  • транзакионные таблицы
  • требования к памяти, типы столбцов
  • треды
  • тренинги
  • тренинги MySQL
  • триггеры
  • удаление базы данных
  • удаление индекса, удаление индекса
  • удаление таблицы
  • удаление, mysql.sock
  • удаление, функция
  • удаление, строки
  • уменьшение, размер данных
  • уникальное значение для последней записи
  • уникальный ID
  • упорядочивание строк
  • управление доступом
  • установить, пароль
  • установка бинарного дистрибутива
  • установка, обзор
  • установка, поставка исходных текстов
  • установка, схема
  • утилита коммандной строки
  • утилиты MySQL, конвертация
  • утилиты, mysqld_multi
  • утилиты, safe_mysqld
  • увеливение, производительность
  • увеличение, скорость
  • учебное пособие
  • учет регистра, проверка доступа
  • журнал медленных запросов
  • журнал обновлений
  • журнал запросов
  • журнальные файлы
  • вакансии на MySQL
  • веб-сервер, работа
  • версии и выпуски, именование номеров версий
  • версии, обновления
  • версия MySQL
  • версия, последняя
  • вложенные запросы
  • внешние ключи
  • внутренние ошибки компилятора
  • внутренности MySQL
  • внутреняя блокировка
  • вопросы дизайна
  • вопросы относящиеся к диску
  • восстановление, после аварии
  • возможности MySQL
  • возраст, вычисление
  • временные таблицы, проблемы
  • временный файл, доступ для записи
  • время, тип
  • вставка, скорость
  • ввод, запросов
  • выбор типов
  • выбор версии
  • выбор, база данных
  • выборка, данные из таблицы
  • выгрузка, таблицы
  • выходы обновлений
  • выкачка
  • выпуски, тестирование
  • выражение, расширенное
  • вывод, размер
  • вычисление данных
  • вычисление, данные
  • задавая вопросы
  • загрузка
  • загрузка, таблицы
  • заказчики, MySQL
  • закрытие, таблицы
  • запросы
  • запросы, оценка производительности
  • запросы, примеры
  • запросы, проект Близнецы
  • запросы, скорость
  • запросы, ввод
  • запуск сервера
  • запуск сервера, автоматический
  • запуск, mysqld
  • запуск, автоматический
  • запуск, несколько серверов
  • запуск, пакетный
  • запуск, запросов
  • зарезервированное слово
  • зарезервированные слова
  • зеркала сайта
  • значение NULL
  • значение NULL, и столбцы TIMESTAMP
  • значение времени, проблемы
  • значения NULL
  • значения NULL, и столбцы AUTO_INCREMENT
  • значения по умолчанию, значения по умолчанию, значения по умолчанию, значения по умолчанию
  • значения по умолчанию, BLOB и TEXT столбцы
  • значения по умолчанию, подавление
  • шаблонные символы, и LIKE
  • шаблонные символы, в таблице mysql.columns_priv
  • шаблонные символы, в таблице mysql.db
  • шаблонные символы, в таблице mysql.host
  • шаблонные символы, в таблице mysql.tables_priv
  • экранирование двоичных данных
  • экранирование строк
  • экспериментальное дерево исходных кодов
  • числа
  • число с плавающей точкой
  • число с плавающей запятой
  • числовые типы
  • чувствиетльность к регистру, в поиске
  • чувствительность к регистру, имена
  • чувствительность к регистру, имена баз данных
  • чувствительность к регистру, имена таблиц
  • чувствительность к регистру, сравнение строк
  • Анонимный пользователь, Анонимный пользователь
  • Близнецы, запросы
  • Год 2000, проблема
  • Характеристики динамических таблиц
  • Китайский
  • Кэш запросов
  • Оболочка Eiffel
  • Переменные окружения, список
  • Перенос, на другие системы
  • Порт, на другие системы
  • Портирование, на другие системы
  • Последовательность вызова UDF, агрегатные функции
  • Последовательность вызова UDF, простые функции
  • Послеустановочная настройка, тестирование
  • Представления
  • Проблемы инсталляции на Solaris
  • Регулярные выражения, MySQL
  • Регулярные выражения, определения
  • Скорость работы MySQL и PostgreSQL
  • Сравнение возможностей MySQL и PostgreSQL
  • Стратегии развития MySQL и PostgreSQL
  • Установка нескольких серверов
  • Внешние ключи
  • Взаимодействие с Java
  • Запуск нескольких серверов
  • Что есть MySQL AB, определение
  • Что такое X509/Сертификат?
  • Что такое фиврование

    • Go to the first, previous, next, last section, table of contents.