Справочное руководство по MySQL версии 4.1.1-alpha. - 4 Администрирование баз данных

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

# 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 E.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 E.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 E.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 F Переменные окружения).

Приводим список программ, поддерживающих файлы параметров: `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 F Переменные окружения).

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

Если работать с несколькими серверами необходимо постоянно, то нужно создать файл параметров для каждого сервера (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 F Переменные окружения).
- Укажите принятые по умолчанию сокет и порт 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=23`4. 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''hostname';

  Задание такой привилегии гарантирует, что этот пользователь не сможет непосредственно вносить изменения ни в одном из столбцов привилегий, а для предоставления привилегий другим пользователям должен будет использовать команду `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 F Переменные окружения.

### 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'192.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 tes`t приводит к ошибке `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_nam`e - нет, то в таблице `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 F Переменные окружения. Если есть подозрение, что клиент отсылает неверные устанавливаемые по умолчанию параметры подсоединения, в случае, когда вы не задаете их в командной строке, проверьте ваше окружение и файл ``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 E.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`, I`NDEX` и `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 F Переменные окружения.

Исходя из всего сказанного выше, самыми безопасными методами указания пароля являются запрос программы клиента на ввод пароля с терминала или указание пароля в защищенном надлежащим образом файле ``.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''localhost' 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 F Переменные окружения.

Все программы 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 databas`e. Наберите 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 E.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, описав эту проблему во всех подробностях.

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