ИНТЕРНЕТ УНИВЕРСИТЕТ ИНФОРМАЦИОННЫХ ТЕХНОЛОГИЙ Курс лекций АДМИНИСТРИРОВАНИЕ MySQL Кривой Рог 2010 СОДЕРЖАНИЕ ЛЕКЦИЯ 1. Введение в администрирование MySQL ЛЕКЦИЯ 2. Общее администрирование MySQL ЛЕКЦИЯ 3. Управление пользовательскими учетными записями ЛЕКЦИЯ 4. Проверка и восстановление таблиц ЛЕКЦИЯ 5. Сценарии и утилиты MySQL ЛЕКЦИЯ 6. Виды таблиц и способ их хранения ЛЕКЦИЯ 7. Каталог данных MySQL ЛЕКЦИЯ 8. Файлы журналов MySQL ЛЕКЦИЯ 9. Резервирование и копирование баз данных ЛЕКЦИЯ 10. Оптимизация ЛЕКЦИЯ 11. Безопасность ЛЕКЦИЯ 12. Концепции распределенных баз данных ЛЕКЦИЯ 13. Расширение возможностей 3 7 15 23 31 54 65 80 86 93 106 123 134 2 ЛЕКЦИЯ 1. Введение в администрирование MySQL Описание: Эта лекция является вводной. В ней представлено описание всех основных вопросов,которыми необходимо владеть для успешного выполнения задач по администрированию инсталляцией MySQL. Она же включает краткий обзор всех обязанностей администратора С развитием систем баз данных процедуры инсталляции и использования MySQL становятся все проще. Судя по всему, именно простота работы с MySQL стала основной причиной широкой ее популярности среди пользователей. Особенно это относится к тем из них, которые не являются, да и не желают быть программистами. Безусловно, знания компьютерного профессионала могут оказаться весьма полезными, но для успешного использования MySQL быть опытным программистом вовсе не обязательно. Однако и полностью без управления MySQL работать также не может. Администратор должен хотя бы иногда проверять согласованность и эффективность ее работы и знать, что делать при возникновении проблем. Вся эта информация представлена далее Этот курс посвящен рассмотрению различных аспектов администрирования MySQL. В этой лекции представлено описание всех основных вопросов, которыми необходимо владеть для успешного выполнения задач по администрированию инсталляцией MySQL. Она же включает краткий обзор всех обязанностей администратора. Инструкции по их выполнению рассматриваются в следующих лекциях. Представленный далее в этой лекции длинный список обязанностей может не на шутку напугать начинающего или неопытного администратора. Каждая указанная в списке задача действительно очень важна, однако не стоит пробовать освоить их все сразу. Гораздо лучше использовать лекции этого курса в качестве справочного руководства, которое всегда под рукой и в которое при необходимости можно заглянуть. Уже имеющие опыт работы администраторы могут заметить, что администрирование MySQLподобно администрированию других систем управления базами данных. Опыт администрирования других систем просто неоценим. В то же время, администрирование MySQL имеет свои уникальные особенности, которые и описываются в этом курсе. Обзор задач администрирования СУБД MySQL состоит из нескольких основных компонентов. Знание их сути и предназначения поможет лучше понять природу управляемой системы и принципы работы различных ее средств. Настоятельно рекомендуется потратить немного времени, чтобы хорошенько разобраться в представленном далее материале. Это значительно упростит дальнейшую работу. В частности, необходимо вникнуть в следующие аспекты работы MySQL. Сервер MySQL. Сервер mysqld выполняет все операции с базами данных и таблицами. Для запуска сервера, мониторинга его работы и перезапуска в случае сбоя применяется программа safe_mysqld (демон) Клиентские программы и утилиты MySQL. Для взаимодействия с сервером и выполнения ряда административных задач используются различные программы MySQL, наиболее важными среди которых являются следующие: o mysql. Интерактивная программа, позволяющая отправлять SQL-запросы на сервер и просматривать результаты их выполнения. 3 o o o mysqladmin. Административная программа, позволяющая выполнять такие операции, как завершение работы сервера, создание и удаление баз данных. Эту же программу можно применять для проверки состояния сервера, если что-то в его работе не так. isamchk или myisamchk. Утилиты, предназначенные для анализа и оптимизации таблиц, а также восстановления их в случае повреждения. mysqldump. Средство резервирования баз данных или их копирования на другой сервер. SQL - язык сервера. Некоторые задачи администрирования можно выполнить только с помощью утилиты командной строкиmysqladmin. Иногда гораздо эффективней справиться с задачей может администратор, который может "общаться" с сервером на его языке. Предположим, что необходимо проверить, почему привилегии пользователя работают вовсе не так, как ожидается. Напрямую "поговорить" с сервером на человеческом языке, к сожалению, нельзя. Зато можно воспользоваться программой-клиентом mysql и послать SQL-запрос для анализа таблиц разрешений. Незнакомым с операторами SQL пользователям следует разобраться по крайней мере в базовых принципах их работы. Незнание SQL - достаточно серьезное препятствие, и время, затраченное на изучение этого языка, окупится очень быстро. Конечно, чтобы стать настоящим "знатоком SQL", придется напряженно учиться и достаточно долго практиковаться. Познакомиться же с основами этого языка можно за весьма короткий промежуток времени. Более детально о языке SQL и использовании клиентской программы, работающей с командной строкой, рассказывается в курсе "Введение в MySQL". Каталог данных MySQL. Каталог данных используется сервером для хранения баз данных и файлов состояния. Важно понимать структуру и содержимое каталога данных, чтобы знать, как сервер представляет свои базы данных и таблицы в файловой системе, где хранятся различные файлы (например, регистрационные) и что в них содержится. Необходимо также уметь управлять распределением дискового пространства, чтобы избежать переполнения раздела с каталогом данных. Общее администрирование Общее администрирование включает в себя в основном работу с демоном mysqld, сервером MySQL и обеспечение доступа пользователей. К наиболее важным задачам общего администрирования относятся следующие. Запуск и остановка сервера. Администратор должен уметь запускать и останавливать сервер вручную из командной строки и настраивать автоматический запуск и завершение работы. Важно также знать, как восстановить работу сервера в случае сбоя или некорректного функционирования. Поддержка учетных записей пользователей. Администратор должен отчетливо понимать разницу между пользователями MySQL и пользователями UNIX и Windows, а также уметь настраивать учетные записи пользователей MySQL. Такая настройка зачастую заключается в определении, какие пользователи и с какого компьютера смогут подключаться к серверу. Новым пользователям необходимо, кроме всего прочего, сообщить свои параметры подключения, чтобы успешно настроить обмен данными с сервером. Настройка учетных записей — это задача администратора, а не пользователей! Поддержка регистрационных файлов. Администратор должен знать, регистрационные файлы каких типов необходимо проверять и поддерживать, а также каким образом и когда 4 выполнять эти операции. Последовательный просмотр и замена регистрационных журналов позволит избежать переполнения ими используемых дисков. Резервирование и копирование баз данных. Резервирование баз данных — исключительно важная операция, позволяющая в случае необходимости восстановить работу системы после сбоя. Желательно, конечно, чтобы имелась возможность восстановить базы данных до того состояния, в котором они находились перед сбоем. В этом случае потеря данных будет минимальной. Заметьте, однако, что резервирование баз данных отличается от резервирования информации всей системы, выполняемой, например, с помощью UNIXпрограммы dump. В процессе активной работы сервера файлы таблиц базы данных, как правило, подвергаются изменениям. Восстановление файлов, зарезервированных в какой-то определенный момент времени, не позволит в полной мере восстановить базу данных, т.е. потеря определенной части данных неизбежна. Более полезными для восстановления базы данных являются файлы, сгенерированные программой mysqldump. С ее помощью можно выполнять резервирование без предварительного завершения работы сервера. Иногда возникает необходимость в запуске СУБД на более быстродействующем главном компьютере или в создании копии базы данных. В этом случае все содержимое ее каталога можно скопировать на другой компьютер. Администратор должен уметь выполнять и эту процедуру. Файлы баз данных могут зависеть от конфигурации конкретной системы, поэтому простое копирование файлов не сможет дать достаточно удовлетворительных результатов. Настройка сервера. Пользователи всегда хотят, чтобы сервер работал максимально быстро. Самый быстрый и неэкономный метод повышения производительности сервера — приобретение и установка большего объема памяти и более быстрых дисков. Разбираться в работе сервера при применении подобных методов вовсе необязательно. Администратору необходимо знать, какие параметры применяются для настройки работы сервера и как их значения повлияют на ситуацию. Одни клиенты пользуются запросами в основном для выборки необходимой информации из баз данных, другие — в основном для добавления и обновления информации. Поэтому решение об изменении значений тех или иных параметров зачастую определяется типом запросов, отправляемых к узлу. Установка нескольких серверов. В некоторых случаях возникает необходимость в запуске сразу нескольких серверов. Она может определяться желанием протестировать работу новой версии MySQL перед полным переходом на нее или обеспечить более высокий уровень защиты для отдельных групп и пользователей. (Последний вариант, в частности, относится к провайдерам интернет-услуг.) В таких ситуациях администратор должен знать, как установить и настроить несколько одновременно работающих инсталляций. Обновление MySQL. Новые версии MySQL появляются достаточно часто. Администратор должен знать, как обновить старую версию для устранения найденных ошибок программного кода и добавления новых возможностей. Следует также понимать, что иногда имеет смысл воздержаться от обновления, а также уметь выбирать между официальными (стабильными) и тестовыми версиями этого программного продукта. Безопасность В процессе инсталляции MySQL важно также обеспечить надежную защиту хранимых данных. Администратор MySQL полностью отвечает за предоставление доступа к каталогам данных и серверу и должен разбираться в следующих вопросах. Защита файловой системы. В ОС UNIX могут поддерживаться несколько учетных записей пользователей, не обладающих полномочиями администратора MySQL. Необходимо проверить, чтобы эти пользователи не имели доступа к каталогам данных. Это позволит защититься от несанкционированного копирования или удаления таблиц баз данных либо 5 чтения регистрационных файлов с критически важной информацией. Администратор должен знать, как настроить учетные записи пользователей UNIX для сервера MySQL, как сделать каталог данных доступным только для владельца и как определить привилегии пользователей сервера. Защита сервера. Знание принципов работы системы безопасности MySQL поможет правильно настроить пользовательские учетные записи и полномочия доступа. Подключающиеся через сеть к серверу пользователи должны обладать правами доступа только к самой необходимой информации. Полное игнорирование системы безопасности может обернуться предоставлением прав администратора анонимному пользователю. Отладка и поддержка баз данных В душе каждый администратор MySQL надеется избежать повреждения или полного разрушения таблиц баз данных. Однако одних надежд мало. Выполнение определенных процедур позволит минимизировать риск сбоя и оказаться более подготовленным к негативному развитию событий. Восстановление после сбоя. Сбой может разрушить результаты даже самых успешных действий, поэтому администратор должен обязательно знать, как отладить и восстановить таблицы баз данных. Восстановление после сбоя — это процесс, выполняемый весьма редко. Однако он очень неприятен и, как правило, сопровождается пребыванием администратора в стрессовом состоянии (которое может еще более усугубляться постоянными звонками и стуком в дверь.) Для восстановления применяются средства проверки и восстановления isamchk и myisamchk. Необходимо обязательно научиться восстанавливать информацию из резервных файлов и использовать записи регистрационных журналов для восстановления всех изменений, внесенных с момента последнего резервирования. Превентивная поддержка. Для снижения вероятности повреждения или разрушения баз данных следует постоянно применять программы превентивной поддержки. Необходимо также выполнять и резервирование, хотя, конечно, выполнение мер превентивной поддержки снижает возможность их использования. Итак, мы рассмотрели краткое описание всех основных обязанностей администратора MySQL. В следующих лекциях эти задачи изучаются более детально, а также описываются процедуры эффективного их выполнения. Однако сначала рассматривается каталог данных MySQL. Ведь администратору необходимо четко понимать структуру и содержимое ресурса, на который направлены все операции поддержки. Ниже будут рассмотрены все общие административные задачи, система безопасности MySQL, поддержка работы СУБД и методы устранения всевозможных проблем. 6 ЛЕКЦИЯ 2. Общее администрирование MySQL Описание: В лекции рассмотрены общие задачи администратора, инсталляция MySql, методы и параметры запуска и завершения работы сервера MySql. Эта лекция посвящена рассмотрению задач администратора MySQL, точное выполнение которых позволит обеспечить согласованную и эффективную работу сервера MySQL. К задачам подобного рода относится проверка работоспособности сервера, достижение максимально возможной производительности, настройка пользовательских учетных записей для обеспечения клиентского доступа к серверу, поддержка журналов и резервирование баз данных. В некоторых случаях, когда на одном компьютере запускается несколько серверов, администратору для достижения максимальной производительности работы приходится также изменять операционные параметры работы сервера. Стремительное развитие возможностей MySQL вынуждает администратора пристально следить за новинками и вовремя обновлять свою систему MySQL посредством инсталляции новых версий. Кроме того, существуют и другие задачи администрирования, однако о них речь пойдет в других лекциях. В этой и следующих лекциях описывается несколько программ, исключительно полезных для выполнения задач администрирования MySQL. Утилита mysqladmin позволяет выполнять всевозможные административные функции. Сценарии safemysqld и mysqlserver применяются для запуска MySQL-сервера mysqld. Программа mysqldump используется для резервирования и копирования баз данных. Утилиты myisamchk и isamchk применяются для проверки целостности данных таблиц и операций отладки. Защита новой инсталляции MySQL На этапе инсталляции MySQL необходимо обязательно установить пароль для MySQLпользователя root, поскольку сразу после установки права сервера не защищены. Предполагается, что каталог данных и база данных mysql с таблицей разрешений уже инициализированы. На компьютерах с UNIX для их инициализации достаточно запустить сценарий mysql_install_db. На компьютерах, работающих под управлением Windows, каталог данных и база данных mysql инициализируются посредством запуска программы Setup в дистрибутиве сервера. Итак, каталог и основная база данных пронициализированы, и сервер запущен. Сразу после первой инсталляции MySQL на компьютере привилегии в таблице разрешений базы данных mysql устанавливаются следующим образом. Авторизоваться в качестве основного пользователя root с локального компьютера можно без пароля. Пользователь rootобладает всеми возможными правами (включая административные), может выполнять любые операции. (Кстати, совпадение имен суперпользователей MySQL и UNIX не является закономерностью Они никак друг на друга не влияют.) Права анонимного доступа предоставляются всем пользователям, подключающимся с локального компьютера к базе данныхtest или любой другой базе данных, имя которой начинается со слова test. Анонимные пользователи могут выполнять любые операции с такими таблицами, но не обладают привилегиями администратора. Для подключения к серверу с локального компьютера можно определить как имя главного компьютера localhost, так и его реальное имя. Например, если сервер размещается на компьютере pitviper.snake.net, 7 клиент этого компьютера может подключиться без пароля к серверу для работы с базой данных test с помощью одной из двух следующих команд: % mysql -h localhost test % mysql -h pit-viper.snake.net test На полное отсутствие защиты исходной инсталляции указывает тот факт, что подключиться к серверу MySQL можно в качестве пользователя root абсолютно без пароля. Именно поэтому одна из первых задач администратора MySQL заключается в установке пароля для пользователя root. Затем, в зависимости от метода установки пароля, возможно, еще придется указать серверу перезагрузить таблицы разрешений, чтобы загрузить в память все сделанные изменения. (В процессе запуска сервер загружает таблицы в память и может не заметить внесенные впоследствии изменения. В таком случае следует явным образом указать ему на необходимость повторного считывания таблиц.) В версиях MySQL 3.22 и выше установить пароль можно с помощью команды mysqladmin. Для этого достаточно ввести следующую команду, заменив ее часть "my password" реальным паролем: mysqladmin -u root password "my password" Во всех остальных версиях MySQL для этих целей можно воспользоваться программой mysql и непосредственно обновить таблицу разрешений grant в базе данных mysql: mysql> -u root mysql mysql> UPDATE user SET Password=PASSWORD("my password") WHERE User="root"; Команда mysql и оператор update применяется в старых версиях MySQL, а также во всех бесплатно распространяемых версиях под Windows. После установки пароля необходимо определиться, следует ли задавать серверу перезагрузку таблицы разрешений. Для этого запустите следующую команду: % mysqladmin -u root status Если сервер все еще позволяет подключаться в качестве пользователя root без пароля, укажите ему перезагрузить таблицы, введя следующую команду: % mysqladmin -u root reload После определения пароля пользователя root (и перезагрузки таблиц разрешений) самое время приступать к определению нового пароля для администратора. Настройка процедур запуска и завершения работы сервера MySQL Одна из основных обязанностей администратора MySQL — обеспечить согласованную и длительную работу сервера, что даст возможность пользователям получать доступ к нему в любое удобное время. Иногда, однако, возникает необходимость и во временной приостановке работы сервера. (Так, например, при перемещении базы данных необходимо убедиться, что сервер в это же время не обновляет ее таблицы.) Эти лекции не помогут разрешить компромисс между необходимостью постоянной работы сервера и желанием иногда временно приостановить его работу, поскольку зачастую решение этого компромисса зависит от конкретной ситуации. По крайней мере, читатели смогут узнать, как запустить и завершить работу сервера. 8 Все приведенные в этой лекции инструкции применимы только к операционным системам UNIX. Запуск представленных команд В большинстве примеров этой лекции такие программы, как mysqladmin, mysqldump и им подобные, для краткости представлены без опций -h, -u и -р. Предполагается, что пользователи будут правильно вызывать эти программы, используя в случае необходимости подключения к серверу соответствующие параметры. В версии MySQL 3.22.11 и выше перезагрузить таблицы можно с помощью командыmysqladmin flush-privileges и SQL-оператора FLUSH PRIVILEGES. Запуск сервера MySQL непривилегированным пользователем Прежде чем приступить к рассмотрению процедуры запуска сервера, давайте обсудим, какие пользователи могут выполнить подобный запуск. Сервер может запускаться вручную или автоматически. В первом случае сервер запускается в качестве пользователя, под именем которого зарегистрирован администратор, запускающий сервер (или другой сотрудник). Другими словами, если администратор зарегистрирован под именем пользователя paul и запускает сервер, то сервер будет работать с правами пользователяpaul. Если затем администратор с помощью команды su авторизуется в качестве пользователя root и запустит сервер, сервер будет работать с правами пользователя root. Однако всегда запускать сервер вручную весьма неудобно. Лучше всего настроить его на автоматический запуск во время загрузки системы. На UNIX-компьютерах процедура запуска выполняется системой с помощью UNIX-пользователя root, соответственно, все процессы, запускаемые во время этой процедуры, работают впоследствии с привилегиями пользователя root. Администратору следует помнить о двух целях, преследуемых при настройке процедуры запуска сервера MySQL. Желательно, чтобы сервер не обладал привилегиями пользователя root. В большинстве случаев рекомендуется ограничивать возможности всех процессов, не требующих прав доступа root. He нужны эти права и демону mysqld. Желательно, чтобы сервер все время работал под именем одного и того же пользователя. Весьма нелогично запускать сервер в разное время под именами разных пользователей, поскольку в этом случае файлы и каталоги с данными будут создаваться разными владельцами. В определенный момент времени это может привести к невозможности получения доступа к базам данных или таблицам. Постоянный запуск сервера от имени одного пользователя позволит избежать этой проблемы. Для запуска сервера под обычным пользователем, не обладающим широкими правами, выполните следующие действия. Выберите учетную запись, предназначенную для запуска сервера. Демон mysqld может работать от имени любого пользователя, однако лучше создать для него отдельную учетную запись. Можно также создать специальную группу для работы с MySQL. Предположим, что такой пользователь и группа уже созданы и имеют имена mysqladm и mysqlgrp. Пользователям, определившим другие имена для этих целей, придется подставлять их далее в примерах кода вместоmysqladm и mysqlgrp. 9 Если же MySQL был установлен под каким-либо пользователем, не обладающим специальными правами администратора, сервер наверняка будет запускаться под собственным именем этого пользователя. В этом случае необходимо заменить mysqladm иmysqlgrp соответствующим регистрационным именем и именем группы. Если же система MySQL инсталлировалась под управлением ОС Linux Red Hat с помощью RPMфайла, в процессе установки автоматически создается учетная запись с именем mysql. Ее в последующих примерах этой лекции нужно применять вместоmysqladm. Создайте, если необходимо, учетную запись сервера, используя обычную процедуру создания учетных записей системы. Для этого необходимо сначала авторизоваться в качестве пользователя root. Завершите работу сервера, если он работает. Измените права доступом к каталогу данных, а также всех его подкаталогов и файлов, чтобы новым владельцем этих элементов оказался пользователь mysqladm. Например, чтобы сделать пользователя mysqladm владельцем каталога данных/usr/local/var, необходимо ввести следующие команды (авторизовавшись в качестве пользователя root). # cd /usr/local/var. Переход в каталог данных. # chown -R mysqladm.mysqlgrp. Установка прав доступа для всех каталогов и файлов. Измените полномочия доступа к каталогу данных и всем его подкаталогам и файлам, чтобы работать с ними мог только пользователь mysqladm. Запретите доступ к данным всем остальным пользователям — это самая эффективная мера предосторожности. Если каталог данных размешается в директории /usr/local/var, определить права доступа на него для пользователя mysqladm можно с помощью следующих команд (авторизовавшись в качестве пользователя root). # cd /usr/local/var. Переход в каталог данных. # chmod -R go-rwx. Все элементы будут доступны только для пользователя mysqladm. Устанавливая права доступа и режим для каталога данных и его содержимого, не забудьте просмотреть символические связи. Нужно обязательно переместиться в каталоги, на которые эти связи указывают, и изменить права доступа для их содержимого. На этом этапе могут возникнуть проблемы, если содержащий все связанные файлы каталог не принадлежит владельцу каталога данных. Единственный способ решения таких проблем — авторизоваться в качестве пользователя root. По завершении вышеприведенной процедуры следует убедиться в нормальном запуске сервера, предварительно авторизовавшись в качестве пользователя mysqladm или root. В последнем случае обязательно нужно определить опцию --user=mysqladm, чтобы пользователь мог переключить IDномер своего компьютера на mysqladm (что также реализуется в процессе запуска системы). Опция --user была добавлена в mysql в версии MySQL 3.22. В более ранних версиях для этих же целей можно использовать команду su, которая указывает системе, работающей под управлением пользователя root, что запускать сервер необходимо с учетной записью другого пользователя. Настоятельно рекомендуется заглянуть в справочное руководство и ознакомиться с синтаксисом команды su, поскольку он может видоизменяться для отдельных пользователей. 10 Методы запуска сервера После определения учетной записи, которая будет применяться для работы сервера, можно приступать к выбору способа запуска. Сервер можно запускать вручную из командной строки или автоматически в процессе загрузки системы. Существуют три основных метода запуска сервера. Непосредственный вызов mysqld. Это, возможно, самый распространенный метод. Поэтому подробно рассматриваться далее он не будет. Достаточно лишь заметить, что в случае необходимости можно использовать команду mysqld --help для определения опций с другими методами запуска. Вызов сценария safemysqld. Этот сценарий в процессе своей работы пытается определить местоположение программы сервера и каталога данных, а затем запускает сервер с соответствующими опциями. Сценарий safemysqld записывает все сообщения об ошибках сервера в специальный файл ошибок, расположенный в каталоге данных. Кроме того, safemysqld следит за нормальной работой сервера и в случае сбоя перезагружает его. Этот сценарий наиболее часто применяется в BSD-версиях UNIX. Вызов сценария mysql.server. Этот сценарий запускает сервер посредством запуска сценария safemysqld. Сценарий mysql.server предназначен для использования на компьютерах с системой запуска/завершения работы System V. Данная система включает несколько каталогов со сценариями, вызываемыми при входе или выходе с определенного уровня работы. С помощью соответствующих аргументов start и stopможно определить, что делать дальше: запустить сервер или остановить его работу. Сценарий safemysqld располагается в подкаталоге bin каталога инсталляции MySQL. Его же можно найти в каталоге scripts дистрибутива MySQL. Сценарий mysql.server можно отыскать в подкаталоге share/mysql каталога инсталляции или каталоге support-files исходной дистрибуции MySQL. Для использования эти сценарии необходимо скопировать в соответствующие каталоги запуска. В ОС BSD-UNIX довольно часто используются несколько специальных файлов, которые располагаются в каталоге /etc и инициируют службы во время запуска. Как правило, имена таких файлов начинаются с приставки "rc". Файл rc.local (или имеющий подобное название), например, предназначен специально для запуска локальных служб. Для запуска сервера в подобных системах необходимо добавить в файл rc.local следующие строки (подставив правильный путь к сценариюsafe_mysqld): if [ -x /usr/local/bin/safe_mysqld ]; then /usr/local/bin/safe_mysqld & fi В системах System V для инсталляции сценария mysql.server достаточно разместить его в подкаталоге /etc каталога запуска. Это наверняка уже сделано, если Linux или MySQL инсталлировались с помощью RPM-файла. Если нет, инсталлируйте сценарий в основной каталог сценариев запуска и установите связи с ним в каталогах уровней запуска. Можно также сделать так, чтобы сценарии запускались только пользователем root. Структура каталогов с файлами запуска может изменяться от системы к системе, поэтому рекомендуется внимательно просмотреть, как эти файлы организованы в используемом компьютере. Например, в системе LinuxPPC для запуска применяются каталоги /etc/rc.d/init.d и etc/rc.d/rc3.d. Соответственно, инсталляция сценария выполняется с помощью следующих команд: # ср mysql.server /etc/rc.d/init.d 11 # cd /etc/init.d # chmod 500 mysql.server # cd /etc/rc.d/rc3.d # ln -s ../init.d/mysql.server S99mysql В ОС Solaris основной каталог сценариев — /etc/init.d, а каталог уровня запуска — /etc/rc2.d, поэтому набор команд инсталляции выглядит следующим образом: # ср mysql.server /etc/init.d # cd /etc/init.d # chmod 500 mysql.server # cd /etc/rc2.d # ln -s ../init.d/mysql.server S99mysql Эти команды обеспечивают автоматический запуск сценария S99mysql с аргументом start в процессе загрузки системы. Если имеется возможность использования команды chkconfig (часто применяемой под управлением Linux), ее также можно применить для инсталляции сценария mysql.server. В этом случае от ручного ввода приведенных выше команд можно отказаться. Определение опций запуска Существует два способа определения дополнительных опций запуска, которые применяются при загрузке сервера. Во-первых, можно изменить используемый сценарий запуска (safemysqld или mysql.server) и задать параметры непосредственно в строке вызова сервера. Вовторых, можно определить параметры собственно в конфигурационном файле. Профессионалы рекомендуют по возможности использовать для этих целей глобальные конфигурационные файлы. В системах UNIX и Windows этими файлами обычно являются /etc/my.cnf. Однако есть информация, которую невозможно задать в конфигурационных файлах. Для ее определения необходимо изменить сценарий safemysqld. Так, например, если сервер неправильно считал установки временного пояса и возвращает значения времени в формате GMT (времени по Гринвичу), можно для подсказки установить переменную среды TZ. Если сервер запускается с помощью сценария safemysqld или mysql.server, установку временного пояса можно добавить в safemysqld. Отыщите строку запуска сервера и перед ней добавьте следующие команды: TZ=US/Central export TZ Эти команды устанавливают часовой пояс центральной части Соединенных Штатов. Пользователям же необходимо аналогичным образом задать свой часовой пояс. Подобный синтаксис для переменной TZ применяется в системе Solaris. В других системах он может быть другим, например, таким: TZ=CST6CDT export TZ 12 Следует помнить, что после повторной инсталляции MySQL (например, при обновлении версии) все внесенные в сценарий запуска изменения будут потеряны. В таком случае необходимо сперва скопировать сценарий в другую папку, а после инсталляции сравнить оба сценария (старый и вновь инсталлированный) и добавить отсутствующие параметры. Проверка таблиц во время запуска Помимо настройки автоматического запуска сервера в процессе загрузки системы, можно также инсталлировать сценарий, который будет запускать утилиты myisamchk и isamchk. Это позволит проверять таблицы перед запуском сервера. В некоторых случаях перезагрузка сервера выполняется после сбоя, в результате которого таблицы могут оказаться поврежденными. Проверка таблиц перед запуском сервера — отличный способ предотвратить будущие проблемы. Завершение работы сервера Для самостоятельного завершения работы сервера применяется команда mysqladmin: % mysqladmin shutdown Автоматическое завершение работы сервера также не требует выполнения каких-либо специальных действий. В UNIX BSD работа служб обычно завершается посредством отправки процессам сигнала TERM. Службы либо соответствующим образом на него отвечают, либо просто закрываются. Сервер mysqld, например, на получение такого сигнала реагирует закрытием. В системах System V, запуск сервера в которых производится с помощью сценария mysql.server, процедура завершения работы реализуется посредством вызова этого же сценария, но с аргументом stop. При этом, конечно же, предполагается, что сценарий mysql.server инсталлирован. Когда нельзя подключиться к серверу В некоторых случаях возникает необходимость в самостоятельной перезагрузке сервера из-за невозможности подключения к нему. Честно говоря, получается какой-то парадокс, поскольку обычно для завершения работы сервера необходимо сначала подключиться к нему, а затем дать указание на остановку. Как же может возникнуть подобная ситуация? Во-первых, администратор может не знать пароля MySQL-пользователя root. Иногда это случается, когда при изменении пароля случайно введен лишний символ или пароль просто забыт. Во-вторых, подключение к компьютеру localhost обычно осуществляется через сокет ОС UNIX, которым, как правило, является/tmp/mysql.sock. Удаление этого файла делает невозможным подключение клиентов. Такая ситуация, в свою очередь, может возникнуть после запуска процесса сron, который удаляет временные файлы из каталога /tmp. Если подключиться нельзя из-за отсутствия файла разъема, проблему можно легко решить посредством простой перезагрузки сервера. В процессе запуска он пересоздаст этот файл. Проблема заключается в том, что использовать этот разъем для установления соединения с сервером нельзя. Для этого необходимо установить соединение TCP/IP. Например, если сервер запускается на компьютере с адресом viper.snake.net, подключиться к нему можно с помощью следующей команды: % mysqladmin -p -u root -h pit-viper.snake.net shutdown 13 Если файл разъема удален в результате работы задания программы остановки, проблема может возникнуть снова. Чтобы избежать этого, настройте программу остановки на использование другого файла разъема. Это можно осуществить с помощью глобального конфигурационного файла. Так, например, если /usr/local/var — каталог данных, для перемещения в него файла разъема достаточно добавить следующие строки в файл /etc/my.cnf: [mysqld] socket=/usr/local/var/mysql.sock [client] socket=/usr/local/var/mysql.sock Как видите, имя файла и путь к нему одинаковы как для сервера, так и для клиентских программ, в результате чего все они используют один файл разъема. Можно определить новый путь только для сервера, благодаря чему клиентские программы будут искать этот файл по старому адресу. Перезапустите сервер после внесения изменений, чтобы создать файл разъема в новой позиции. Иногда администратор не может подключиться к серверу из-за того, что забыл пароль пользователя root или в процессе изменения случайно присвоил ему не то значение, которое предполагал. В этом случае необходимо восстановить контроль над сервером, чтобы заново установить пароль. Это можно сделать следующим образом. Завершите работу сервера. Авторизовавшись как пользователь root на компьютере с сервером, администратор может завершить работу сервера с помощью команды kill. Используя команду ps, можно отыскать ID-номер процесса сервера. С этой же целью можно просмотреть PlD-файл, который обычно располагается в каталоге данных. Лучше сначала попытаться завершить работу сервера с помощью обычной команды kill, чем сразу посылать серверу сигналterm и проверять, правильно ли он отреагировал на нее, завершив работу. В этом случае все таблицы и журналы будут обработаны и закрыты корректно. Если в работе сервера не все нормально и он не отвечает на сигнал завершения работы, можно воспользоваться командой kill -9 для принудительного закрытия. Однако к ее помощи следует прибегать в самую последнюю очередь, поскольку в этом случае существует риск оставить таблицы поврежденными. Если работа сервера все же была завершена с помощью команды kill -9, настоятельно рекомендуется перед следующим запуском сервера проверить таблицы с помощью команд myisamchk и isamchk. Перезапустите сервер с помощью параметра --skip-grant-tables. Это укажет серверу не использовать таблицы разрешений для проверки соединений и позволит подключиться с полномочиями пользователя root без пароля. После удачного подключения измените пароль пользователя root без пароля. Используя команду mysqladmin flush-privileges, укажите серверу снова перезагрузиться, но с применением таблиц разрешений. Если используемая версия mysqladmin не поддерживает опцию flush-privileges, попробуйте воспользоваться командой reload. 14 ЛЕКЦИЯ 3. Управление пользовательскими учетными записями Описание: В этой лекции рассказывается, как создавать учетные записи пользователей MySQL, присваивать или удалять их привилегии, а также полностью удалять пользователей из таблиц разрешений. В обязанности администратора MySQL входит также создание и настройка учетных записейпользователей MySQL. В процессе этой настройки необходимо определить, какие пользователи будут иметь возможность подключения к серверу, откуда они смогут подключиться и что смогут делать после подключения. Два появившихся в MySQL 3.22.11 оператора упрощают эту задачу. Оператор GRANTсоздает пользователей MySQL и позволяет настроить их привилегии. Оператор REVOKE удаляет привилегии. Эти два оператора являются своего рода внешним интерфейсом для таблиц разрешений базы данных mysql и обеспечивают альтернативу непосредственному редактированию содержимого этих таблиц. Операторы grant иrevoke работают с четырьмя следующими таблицами. Таблица разрешений user db tables_priv columns_priv Содержимое Подключающиеся к серверу пользователи и все их глобальные привилегии Привилегии уровня базы данных Привилегии уровня таблицы Привилегии уровня столбца Существует еще одна, пятая таблица разрешений (host), однако операторы grant и revoke не в состоянии ее обрабатывать. Если оператор GRANT запускается для определенного пользователя, в таблице user для него создается новая запись. Если оператор определяет для пользователя какие-либо глобальные привилегии (привилегии администратора или привилегии, применяемые сразу ко всем базам данных), они также записываются в таблицу user. Права обработки базы данных, таблицы или столбца записываются соответственно в таблицы db, tables_priv и column_priv. Применять операторы grant и revoke проще, чем непосредственно редактировать таблицы разрешений. Однако для более полного понимания представленного здесь материала рекомендуется также прочитать лекцию 11, "Безопасность", в которой детально описываются таблицы разрешений. Роль этих таблиц действительно велика, и администратор должен понимать, каким образом их обрабатывают операторы GRANT иREVOKE. Далее в этой лекции рассказывается, как создавать учетные записи пользователей MySQL, присваивать или удалять их привилегии, а также полностью удалять пользователей из таблиц разрешений. В конце лекции описана также одна связанная с привилегиями "головоломка", которая может завести в тупик многих начинающих администраторов MySQL. Некоторые пользователи захотят также познакомиться со сценариями mysqlaccess и mysql_setpermission, которые являются частью дистрибуции MySQL. Они представляют собой Perl-сценарии и обеспечивают альтернативу оператору grant, поскольку применяются для установки пользовательских учетных записей. Для использования сценария mysql_setpermission требуется инсталляция поддержки DBI. Создание новых пользователей и предоставление привилегий 15 Оператор GRANT имеет следующий синтаксис: GRANT privileges (columns) ON what TO user IDENTIFIED BY "password" WITH GRANT OPTION Для успешного его выполнения обязательно нужно правильно определить следующую информацию: privileges (привилегии). Привилегии присваиваются определенному пользователю. Используемые в операторе grant спецификаторы привилегий описаны в представленной ниже таблице. Спецификатор привилегий user alter create delete drop index insert references select update file process reload shutdown all usage Разрешенная операция Подключающиеся к серверу пользователи и все их глобальные привилегии Изменение таблиц и индексов Создание баз данных и таблиц Удаление существующих записей из таблиц Удаление баз данных и таблиц Создание и удаление индексов Вставка новых записей в таблицы He используется Извлечение существующих записей из таблиц Изменение существующих записей таблиц Чтение и запись файлов сервера Просмотр информации о внутренних потоках сервера и их удаление Перезагрузка таблиц разрешений или обновление журналов, кэша компьютера или кэша таблицы Завершение работы сервера Все операции. Аналог — all privileges Полное отсутствие привилегий Спецификаторы привилегий, входящие в первую группу этой таблицы, применяются к базам данных, таблицам и столбцам. Спецификаторы второй группы определяют административные привилегии. Как правило, они применяются довольно редко, поскольку позволяют пользователю влиять на работу сервера. (Не каждому пользователю, например, необходима привилегияshutdown.) В третью группу входят два отдельных спецификатора: спецификатор ALL предоставляет "все привилегии", a USAGEозначает "полное отсутствие привилегий". В последнем случае создается новый пользователь, не обладающий никакими правами; columns (столбцы). Столбцы, к которым применяются определенные привилегии. Этот параметр необязателен и используется только при установке привилегий для столбцов. Имена нескольких столбцов отделяются друг от друга запятыми; what (что). Уровень применения привилегий. Привилегии могут быть глобальными (применяемыми ко всем базам данных и их таблицам), уровня баз данных (применяемыми 16 ко всем таблицам определенной базы данных) или уровня таблицы. Используя оператор columns, можно определить также привилегии уровня столбца; user (пользователь). Пользователь, которому присваиваются привилегии. В некоторых версиях MySQL необходимо указывать как имя пользователя, так и компьютер, с которого он сможет подключаться. Такой способ задания легко позволяет определить двух пользователей с одинаковым именем, но подключающихся с разных компьютеров. Возможности MySQL позволяют их различать и наделять различными правами. Имя пользователя в некоторых версиях MySQL представляет собой имя, используемое при подключении к серверу. Оно вовсе не обязательно должно быть связано с именем регистрации в ОС UNIX или Windows. Если имя пользователя MySQLне определено явным образом, клиентские программы по умолчанию применяют его в качестве регистрационного имени, однако это необязательно. Не существует также каких-либо особых требований, чтобы суперпользователь MySQL, обладающий максимальными правами, имел имя root. По желанию его можно изменить в таблицах разрешений на nobody, если для выполнения определенных операций требуются его полномочия; password (пароль). Присвоенный пользователю пароль, который не является обязательным. Если для нового пользователя опустить выражение IDENTIFIED BY, пароль ему присвоен не будет (что не совсем разумно с точки зрения безопасности). Если же этот оператор задается для уже существующего пользователя, введенный пароль заменит используемый до настоящего момента. Старый пароль останется неизменным, если новый не будет определен. Строка пароля, задаваемая с помощью выражения IDENTIFIEDBY, должна представлять собой буквенную строку, которую при записи зашифрует операторgrant. Поэтому не следует применять функцию password(), применяемую с оператором SET password. Оператор with grant option является необязательным. С его помощью можно предоставить пользователю все привилегии, определенные оператором GRANT для других пользователей. Этот оператор можно использовать для делегирования возможностей определенных категорий другим пользователям. В именах пользователей, баз данных, таблиц и паролях, записываемых в таблицу разрешений, строчные буквы отличаются от заглавных. Регистр в именах компьютеров и столбцов таблиц не учитывается. Чтобы определиться, какую же форму оператора GRANT применить, достаточно ответить на следующие вопросы. Кто и откуда может подключаться к серверу? Какой уровень привилегий должен иметь пользователь и на доступ к чему эти привилегии предоставляются? Необходимо ли пользователю предоставлять административные привилегии? Давайте попробуем ответить на эти вопросы и рассмотрим примеры оператора grant для создания учетных записей пользователей MySQL. Кто и откуда может подключаться к серверу Администратор может разрешить пользователю подключаться как с определенного компьютера, так и с различных компьютеров. В первом случае, если точно известно, что пользователи будут подключаться только со своих компьютеров, можно предоставить им такой доступ с помощью следующих операторов: 17 GRANT ALL ON samp_db.* TO boris@localhost IDENTIFIED BY "ruby" GRANT ALL ON samp_db.* TO [email protected] IDENTIFIED BY "quartz" GRANT ALL ON samp_db.* TO max@% IDENTIFIED BY "diamond" Символ "%" заменяет все возможные значения адресов и выполняет те же функции, что и при сравнении с помощью оператора LIKE. В предыдущем примере его можно условно заменить фразой "любой компьютер". Установка символа "%" аналогична простому опусканию части, задающей компьютер. Другими словами, эквивалентными в данном примере выступят записи max и mах@%. Это самый простой и, в то же время, самый незащищенный способ создать пользователя. В случае необходимости можно также разрешить пользователю подключаться с ограниченного числа компьютеров. Так, чтобы пользователь mаrу мог подключаться с компьютеров домена snake.net, достаточно воспользоваться спецификатором %.snake.net: GRANT ALL ON samp_db.* TO mary@%.snake.net IDENTIFIED BY "topaz" Для определения компьютера можно применять не только имена, но и IP-адреса. Эти адреса можно задавать явно либо с помощью вспомогательных символов. Кроме того, в версии MySQL 3.23 появилась возможность определять IP-адреса, задавая маску сети, устанавливая число разрядов в сетевом номере: GRANT ALL ON samp_db.* TO [email protected] IDENTIFIED BY "water" GRANT ALL ON samp_db.* TO [email protected].% IDENTIFIED BY "snow" GRANT ALL ON samp_db.* TO [email protected] .128.0/17 IDENTIFIED BY "ice" Первый оператор определяет только один компьютер, с которого может подключиться пользователь joe. Второй определяет набор IP-адресов для подсети класса С 192.168.128. В третьем операторе часть 192.168.128.0/17 определяет 17-разрядный сетевой номер и соответствует любому компьютеру с адресом 192.168.128 в первых 17 разрядах IP-адреса. Если MySQL отказывается принимать определенные пользовательские значения, попробуйте заключить их в кавычки (необходимо отдельно заключать в кавычки имя пользователя и компьютера): GRANT ALL ON samp_db.president TO "my_friend"@"boa.snake.net" Какой уровень привилегий должен иметь пользователь и на доступ к чему эти привилегии предоставляются Администратор может предоставлять пользователям привилегии разных уровней. Наиболее мощными являются глобальные привилегии, применяемые ко всем базам данных. Так, например, чтобы предоставить пользователю ethel права суперпользователя, который может делать все, в том числе и предоставлять привилегии другим пользователям, необходимо запустить следующий оператор: GRANT ALL ON *.* ТО ethel@localhost IDENTIFIED BY "coffee" WITH GRANT OPTION 18 Спецификатор *. * в предложении ON можно условно заменить фразой "все базы данных и все таблицы". Для повышения безопасности подключаться пользователю ethel разрешено только с одного локального компьютера. Ограничение компьютеров, с которых может подключаться к серверу обладающий широкими правами пользователь, — весьма мудрое решение. В этом случае ограничивается и число компьютеров, с которых могут быть предприняты попытки взлома пароля. Некоторые привилегии (FILE, process, reload и shutdown) являются административными и могут присваиваться только с помощью спецификатора глобальных привилегий ON *.*. В случае необходимости их можно присваивать без предоставления привилегий на уровне базы данных. Так, например, приведенный ниже оператор создает пользователя flush, который обладает возможностью только выполнять операторы FLUSH. Это может оказаться полезным в административных сценариях, когда необходимо выполнить обновление журналов: GRANT RELOAD ON *.* ТО flush@localhost IDENTIFIED BY "flushpass" В общем, как уже отмечалось ранее, административные привилегии присваиваются довольно редко, поскольку наделенные ими пользователи могут влиять на работу сервера. Привилегии уровня базы данных применяются ко всем таблицам определенной базы. Такие привилегии присваиваются с помощью предложения ON db name: GRANT ALL ON samp_db.* TO [email protected] IDENTIFIED BY "rock" GRANT SELECT ON menagerie.* TO ro_user@% IDENTIFIED BY "dirt" Первый из указанных операторов предоставляет пользователю bill все права для работы со всеми таблицами базы данныхsampdb. Второй оператор создает пользователя rouser с ограниченными правами (только чтение), который может получать доступ к любой таблице базы данных menagerie, однако только для чтения. Другими словами, этот пользователь имеет возможность запускать только оператор select. Как определить имя локального компьютера в таблице разрешений Довольно часто пользователи не могут подключиться к серверу с основного компьютера (на котором инсталлирован сервер) из-за того, что вместо имени localhost указывают имя сервера. Эта проблема возникает по причине использования разных способов определения имен, записанных в таблицах разрешений и выдаваемых программам. Если процедура сервера выдает неполное имя, например, pit-viper, а в таблицах разрешений записано полное имя pit-viper.snake.net (или наоборот), то подключение становится невозможным. Чтобы определить, существует ли такая проблема на используемом компьютере, попытайтесь подключиться к локальному серверу с помощью опции -h, устанавливающей имя компьютера. Затем загляните в общий учетный файл сервера. Какое имя компьютера в нем записано, полное или неполное? Неважно, какая форма применяется. Важно использовать для определения имени компьютера в операторе grant именно это имя. При задании оператора GRANT можно задавать сразу несколько привилегий одновременно. Так, например, если необходимо предоставить пользователю возможность считывать и изменять 19 содержимое существующих таблиц, но запретить создавать новые таблицы или удалять уже существующие, это можно сделать следующим образом: GRANT SELECT, INSERT, DELETE, UPDATE ON samp_db.* TO jennie@% IDENTIFIED BY "boron" Для еще более детального управления доступом можно предоставлять привилегии отдельным таблицам или даже отдельным их столбцам. Привилегии столбцам оказываются особенно полезными, если определенную часть таблицы необходимо скрыть от пользователя либо предоставить возможность изменения только заданных столбцов. Предположим, что какая-то фирма нанимает на определенный период времени сотрудника, который будет выполнять роль секретаря. Администратор решает предоставить новому сотруднику права доступа только для чтения таблицы member, содержащей информацию о действующих членах общества, и привилегию update столбцу expiration(срок окончания членства) этой таблицы. При таком доступе новый секретарь вполне сможет изменять даты окончания членства организаций-участников, если они продолжают свое членство. Для создания такого пользователя MySQL можно использовать следующие операторы: GRANT SELECT ON samp_db.member TO assistant@localhost IDENTIFIED BY "officehelp" GRANT UPDATE (expiration) ON samp_db.member TO assistant@localhost Первый оператор предоставляет права на чтение всей таблицы member и определяет пароль. Второй оператор добавляет привилегию update, но только для столбца expiration. Поскольку пароль устанавливается первым оператором, во втором его определять повторно вовсе не обязательно. Если необходимо присвоить привилегии для работы с несколькими столбцами, их имена следует разделить запятыми. Так, например, чтобы добавить привилегии UPDATE для полей адресов таблицы member для пользователя assistant, используется приведенный ниже оператор. При его выполнении новые привилегии будут добавлены к уже существующим привилегиям пользователя: GRANT UPDATE (street,city,state,zip) ON samp_db.member TO assistant@localhost Как правило, пользователю не предоставляются большие привилегии, чем это нужно для работы. Иногда, тем не менее, возникает необходимость в предоставлении пользователям возможности создавать таблицы, чтобы заносить в них промежуточные результаты. Желательно, чтобы эти таблицы создавались не в рабочей базе данных, поскольку пользователи могут случайно изменить ее содержимое. Эту задачу можно решить посредством создания отдельной базы данных (назовем ее tmp) и предоставлению пользователям всех возможных привилегий для работы с ней. Чтобы разрешить всем пользователям домена mars.net использовать базу данных tmp, достаточно ввести следующий операторgrant: GRANT ALL ON tmp.* TO "@%.mars.net После его выполнения пользователи смогут создавать и ссылаться на таблицы базы данных tmp с помощью имен типаtmp.tbl_name. 20 Нужны ли пользователю административные привилегии Администратор может предоставить владельцу базы данных возможность управления доступом, предоставив ему все привилегии базы данных и определив опцию WITH GRANT OPTION. Например, чтобы разрешить пользователю alicia подключаться с любого компьютера домена bigcorp.com и предоставить ему административные привилегии для работы со всеми таблицами базы данныхsales, необходимо использовать оператор grant следующего вида: GRANT ALL ON sales.* TO alicia@%.big-corp.com IDENTIFIED BY "applejuice" WITH GRANT OPTION Фактически, предложение with grant OPTION позволяет администратору делегировать права разрешения доступа другому пользователю. Однако следует проявлять осторожность, поскольку два пользователя с привилегиями grant могут предоставлять другим пользователям свои права. Если предоставить одному пользователю только привилегию SELECT, а второму, помимоselect, привилегию GRANT, второй пользователь легко может сделать первого "более сильным". Отмена привилегий и удаление пользователей Для отмены привилегий пользователя применяется оператор revoke. Его синтаксис очень похож на синтаксис оператора GRANT с той лишь разницей, что предложение ТО заменено на предложение FROM, а предложения IDENTIFIED BY и WITH GRANT OPTION отсутствуют вовсе: REVOKE privileges (columns) ON what FROM user Часть user этого оператора должна соответствовать части user исходного оператора GRANTдля пользователя, привилегии которого отменяются. Часть privileges необязательно должна соответствовать ранее определенным привилегиям. Пользуясь оператором revoke, можно отменить только некоторые из привилегий, предоставленные оператором GRANT. Оператор revoke применяется для отмены привилегий, но не для удаления пользователей. В таблице user все равно остается запись для пользователя, даже если все привилегии для него сняты. Это означает, что пользователь все еще имеет возможность подключаться к серверу. Для полного удаления пользователя необходимо явным образом удалить его запись из таблицы user. Для этих целей применяется оператор DELETE: % mysql -u root mysql mysql> DELETE FROM user WHERE User = "user_name" and Host = "host_name"; mysql> FLUSH PRIVILEGES; Оператор delete удаляет запись пользователя, а оператор FLUSH указывает серверу перезагрузить таблицы разрешений. (Таблицы перезагружаются автоматически при использовании операторов GRANT и revoke. Однако этого не происходит при непосредственном изменении таблиц разрешений.) Из описанной в следующем разделе ситуации вы узнаете, почему иногда лучше отказаться от удаления записей таблицы user. Головоломка с привилегиями 21 Довольно часто начинающие администраторы MySQL попадают в следующую весьма запутанную ситуацию. Пытаясь добавить в таблицу разрешений запись для пользователей, они используют в части имени компьютера общий формат, например: GRANT ALL ON samp_db.* TO fred@%snake.net IDENTIFIED BY "cocoa" Назначение этого оператора — разрешить пользователю fred подключаться к серверу с любого компьютера домена snake.net и предоставить ему все привилегии для работы с базой данных samp_db. В результате пользователь fred получает возможность подключиться с любого компьютера, кроме сервера. Попытка подключиться с сервера завершается выводом сообщения об отклонении доступа даже при предоставлении правильного пароля. Такая ситуация возникает, если в таблице разрешений содержатся записи, по умолчанию инсталлированные сценарием инициализации mysql_install_db. Причина ее возникновения в том, что при попытке подключения пользователя fred к серверу большим приоритетом перед записью этого пользователя обладает одна из записей анонимного пользователя. Согласно этой записи, для подключения пароль не нужен, однако пользователь fred пытается его ввести. Важно заметить, что для устранения этой проблемы достаточно удалить запись анонимного пользователя из таблицы user. Оператор revoke для этих целей не подходит, поскольку он отменяет только привилегии. Удаление записи выполняется с помощью следующих команд: % mysql -u root mysql mysql> DELETE FROM user where User=""; mysql> FLUSH PRIVILEGES; Сразу после удаления пользователь fred сможет успешно подключиться с локального компьютера. 22 ЛЕКЦИЯ 4. Проверка и восстановление таблиц Описание: В этой лекции рассказывается о том, как предотвратить катастрофу и как устранить ее последствия, если все же случилось непоправимое. Рассматриваются вопросы поиска повреждений в таблицах и их восстановления, а также методы создания резервных копий и последующей работы с ними. Если база данных хранит важную информацию, опробуйте описанные в этой лекции методики до того, как в них возникнет необходимость. Лучше подготовиться заранее, чем быть захваченным врасплох. Проверка и восстановление таблиц Повреждения в таблицах MyISAM происходят вследствие событий, которые невозможно избежать. Различные аппаратные сбои могут оказать самое непредсказуемое влияние на базу данных. Например, если жесткий диск выйдет из строя, данные окажутся полностью потерянными. Неожиданное выключение системы из-за сбоя питания может привести к тому, что изменения в таблицу будут внесены не полностью. Даже если уничтожить серверный процесс по команде kill, у него не будет возможности корректно завершить свою работу. Если найдена поврежденная таблица, потратьте время на выяснение причин, вызвавших повреждение. Вообще говоря, в MySQL таблицы редко оказываются поврежденными. Существуют два способа проверки и восстановления таблиц. Первый — с помощью специальных инструкций, второй — с помощью утилиты myisamchk. Соответствующие инструкции называются CHECK TABLE, REPAIR TABLE и OPTIMIZE TABLE. Они достаточно удобны, поскольку выполняются в рамках серверного процесса. В этом смысле они ничем не отличаются, к примеру, от инструкции SELECT. Утилита myisamchk обладает рядом дополнительных возможностей, которые в ряде ситуаций оказываются весьма удобными. Необходимость проверки таблицы может быть вызвана тем, что утилиты, обращающиеся к таблице, начинают себя странно вести. Например, вводимые запросы не завершаются или выдаются неожиданные сообщения об ошибках. Если при обращении к таблице возвращается номер ошибки, воспользуйтесь утилитой perror, которая отображает поясняющее сообщение, соответствующее данному номеру. Частота проверок базы данных зависит от степени доверия к серверу. Разработчики MySQL рекомендуют делать это хотя бы раз в неделю, но если есть возможность выполнять процедуру проверки каждую ночь, то шансы на заблаговременное обнаружение ошибки возрастают. С помощью демона cron или программы-планировщика можно составить график проверок таким образом, чтобы они запускались в часы наименьшей активности системы. Сохраняйте результаты проверок в журнальном файле или направляйте их самому себе по электронной почте. Возможно, имеет смысл изменить сценарий safe_mysql таким образом, чтобы при запуске сервера выполнялись инструкции проверки таблиц. Файл, содержащий такие инструкции, задается с помощью опции --init-file. Если повреждения произошли из-за того, что сервер внезапно прекратил работу, они будут немедленно исправлены. Обработчики таблиц, для которых поддерживаются транзакции, содержат код, позволяющий им восстанавливать таблицы на основании журнальных файлов при запуске сервера. Если возникает сомнение в целостности таблицы, необходимо остановить и повторно запустить сервер. 23 Таблицы снабжены флагом, указывающим, изменилось ли содержимое таблицы с момента последней проверки. Инструкция CHECK TABLE пропустит неизмененные таблицы при наличии ключевого слова CHANGED. В утилите myisamchk соответствующий режим включается с помощью опции --check-only-changed. Особым образом помечаются также неправильно закрытые таблицы. Чтобы проверить только их, укажите флаг FAST (инструкция CHECK TABLE) или опцию --fast (утилита myisamchk). По умолчанию утилита myisamchk ищет повреждения только в индексных файлах. В инструкции CHECK TABLE этот режим включается с помощью флага QUICK. Сама инструкция CHECK TABLE по умолчанию проверяет не только индексы, но и неправильные ссылки на удаленные записи. В утилите myisamchk этот режим включается с помощью опции -medium-check. Расширенный режим проверки задается флагом EXTEND и опцией --extended-check. В этом случае будут проверяться все индексируемые значения. Табличные проверки занимают много времени в случае крупных таблиц, особенно если у них много ключей. Стандартные режимы проверки в обоих методах обеспечивают вполне приемлемую производительность. Более быстрые проверки удобны, когда их нужно запускать регулярно, например по ночам. Расширенные проверки приходят на помощь, если повреждение таблицы очевидно, но обычные проверки его все равно не находят. В листинге 4.1 иллюстрируется процедура проверки и восстановления таблицы. В данном случае была создана небольшая таблица и сымитировано в ней повреждение, отредактировав табличные файлы в редакторе. Как видите, таблицу удалось восстановить. mysql>CHECK TABLE courses; +--------------+-------+-----------+---------------------------------------------+ | Table | Op | Msg_type | Msg_text | +--------------+-------+-----------+---------------------------------------------+ | courses | check | error | Size of indexfile is: 1924 Should be: 2048 | | test.courses | check | error | corrupt | +--------------+-------+-----------+---------------------------------------------+ 2 rows in set (0.00 sec) mysql>REPAIR TABLE courses; +--------------+--------+-----------+----------+ | Table | Op | Msg_type | Msg_text | +--------------+--------+-----------+----------+ | test.courses | repair | status | ok | +--------------+--------+-----------+----------+ 1 row in set (0.08 sec) Листинг 4.1. (html, txt) Таблицы можно проверять, когда сервер запущен. Программа MySQL не будет пытаться их восстановить. Но если обнаруживается поврежденная таблица, программа запрещает потокам обращаться к ней до тех пор, пока таблица не будет восстановлена. Для восстановления требуется получить монопольный доступ к таблице. В этой ситуации служебными инструкциями пользоваться удобнее, чем утилитой myisamchk, так как MySQL сможет заблокировать другие потоки на время восстановления таблицы. Утилитаmyisamchk может работать таким образом, только если операционная система поддерживает блокировку файлов. В Linux соответствующих функций нет, поэтому перед восстановлением таблиц нужно останавливать сервер. 24 Инструкция REPAIR TABLE устраняет повреждения в таблице. То же самое делает утилита myisamchk, при наличии опции --recover. Программа MySQL поддерживает три типа процедур восстановления: быструю, обычную и безопасную. В первом случае устраняются лишь проблемы с индексами. Во втором случае исправляется также большинство ошибок в табличном файле. В безопасном режиме таблица проверяется строка за строкой, а индексный файл создается заново. Это наиболее длительная процедура. При удалении записей из таблицы программа MySQL сохраняет в ней пустые участки, которые повторно задействуются при последующем выполнении инструкций INSERT. Если таблица содержит пустые участки, то перед вставкой записей ее нужно заблокировать. Правда, когда записи вставляются в конец файла данных, программа разрешает другим потокам параллельно осуществлять чтение таблицы. Таблицы с записями переменной длины неизбежно оказываются фрагментированными. Это происходит, когда обновляемая запись не помещается в отведенном для нее пространстве. В результате снижается производительность операций выборки, поскольку программа вынуждена искать запись в двух и более точках файла. Инструкция OPTIMIZE TABLE удаляет из таблицы пустые участки и осуществляет пересортировку записей. Аналогичные действия выполняет утилита myisamchk при наличии опции--analyze. Инструкция OPTIMIZE TABLE также сортирует индексы (соответствующая опция утилиты myisamchk называется --sort-index). Резервное копирование и восстановление Резервная копия — это образ базы данных в конкретный момент времени. К этому образу можно вернуться в случае непредвиденной потери данных. Резервные копии можно создавать сколь угодно часто. Нужно лишь помнить о том, что это достаточно трудоемкий процесс, продолжительность которого зависит от размера базы данных и скоростных характеристик оборудования. Создание резервных копий требует от сервера значительных затрат ресурсов, вплоть до того, что работать с другими базами данных станет невозможно. Нужно спланировать этот процесс таким образом, чтобы он приходился на периоды минимальной загруженности сервера. Если используется репликация, то резервные копии лучше создавать на подчиненном сервере. Если резервная копия была создана в полночь, а сбой базы данных произошел в полдень, половина дневных изменений окажется утерянной. В таком случае может помочь двоичный журнал. В нем фиксируются все изменения базы данных. С помощью утилиты mysqlbinlogможно преобразовать содержимое этого файла в запросы к восстановленной базе данных, которые позволят воссоздать ее состояние на момент сбоя. Таким образом, планируя схему резервного копирования, не забудьте учесть ротацию и архивирование двоичных журналов, чтобы они были синхронизированы с копиями базы данных. Помните общие правила обращения с резервными копиями. Если они хранятся в той же файловой системе, что и сама база данных, то данные не защищены от сбоев файловой системы. Отсюда правило: копии должны находиться на отдельном носителе. Храните их на перезаписываемом компакт-диске, магнитной ленте или другом жестком диске. Резервные копии могут храниться дома у начальника или администратора компании. Их можно также пересылать по сети в другую систему. С помощью Internet это делать не сложно. В процессе планирования необходимо предусмотреть тестирование копий и проверку возможности их восстановления на практике. Не ждите, пока случится катастрофа и вам придется учиться восстанавливать архивы. Создайте тестовую среду и потренируйтесь на ней. Можно попробовать 25 восстановить архив во временную пустую базу данных или же воспользоваться более сложной методикой — например, запустить еще один сервер MySQL на другом порту либо на другом компьютере. В MySQL существуют три основных способа архивирования данных. Первый — это копирование табличных файлов, второй — создание SQL-образов таблиц, третий — создание форматированных текстовых файлов. Первый способ является самым экономным и быстродействующим. Но для таблиц тех типов, которые поддерживают транзакции, последние два способа являются более гибкими. Например, все таблицы InnoDB хранятся в группе больших файлов, поэтому архивы нельзя будет сгруппировать по базам данных или таблицам. Какой бы метод ни был выбран, не забудьте защитить таблицы от изменений на время резервного копирования. Если копируются табличные файлы, следует остановить сервер. В остальных случаях достаточно поставить блокировки чтения с помощью инструкции LOCK TABLES и выполнить инструкцию FLUSH TABLES. Последняя необходима для того, чтобы все изменения индексов были записаны в таблицы. Наличие блокировок чтения позволит другим потокам параллельно обращаться к таблицам с запросами на выборку. Инструкции BACKUP TABLE и RESTORE TABLE копируют табличные файлы в указанный каталог. Естественно, серверный процесс должен иметь право записи в этот каталог. Программа MySQL копирует туда файлы с расширениями .frm и .MUD. Индексный файл (.MYI) можно воссоздать на основании первых двух, что позволит сэкономить место в архиве. В листинге 4.2 показан пример архивирования таблицы. mysql>BACKUP TABLE dictionary TO '/tm/backup'; +-----------------+--------+-----------+------------------------+ | Table | Op | Msg_type | Msg_text | +-----------------+--------+-----------+------------------------+ | test.dictionary | backup | status | ok | +-----------------+--------+-----------+------------------------+ 1 rows in set (0.27 sec) Листинг 4.2. (html, txt) Функции копирования файлов предоставляются операционной системой, поэтому данный способ создания резервных копий является самым быстрым. Таблица dictionary, скопированная в листинге 4.2, содержит более 100000 записей, а файл данных занимает почти 3 Мбайт. Как видите, процедура архивирования такой таблицы заняла менее секунды. Инструкция BACKUP TABLE самостоятельно заботится о блокировании таблиц и очистке табличных буферов. Это означает, что, в отличие от других методов резервного копирования, дополнительные инструкции не нужны. Инструкция RESTORE TABLE копирует архивные файлы в каталог базы данных и перестраивает индексы. Таблица не должна существовать на момент восстановления. В случае необходимости можно удалить ее с помощью инструкции DROP TABLE или же вручную удалить табличные файлы. В листинге 4.3 показаны результаты восстановления таблицы dictionary, резервная копия которой была создана в листинге 4.2. Обратите внимание на то, что процесс восстановления длился гораздо дольше, чем архивирование. Причина в том, что на перестройку индексов уходит много времени. 26 mysql> RESTORE TABLE dictionary FROM '/tmp/backup'; +-----------------+---------+-----------+--------------------------+ | Table | Op | Msg_type | Msg_text | +-----------------+---------+-----------+--------------------------+ | test.dictionary | restore | status | ok | +-----------------+---------+-----------+--------------------------+ 1 rows in set (1 min 22.24 sec) Листинг 4.3. (html, txt) Если резервные копии создаются вручную, то в архив можно также включить индексный файл. В этом случае в процессе восстановления таблицы индексный файл будет просто скопирован в каталог базы данных. Тем не менее его всегда можно воссоздать с помощью инструкции REPAIR TABLE. Предположим, таблица dictionary была полностью утеряна. Процесс ее восстановления начнем с копирования frm-файла обратно в каталог базы данных. Создать пустые файлы данных и индексов можно с помощью инструкции TRUNCATE TABLE. Затем необходимо скопировать старый файл данных поверх нового. После этого вводится инструкция REPAIR TABLE. В листинге 4.4 показано, как программа MySQL обнаруживает расхождение в количестве записей и перестраивает индексы. mysql> REPAIR TABLE dictionary; +-----------------+---------+-----------+-----------------------------------------+ | Table | Op | Msg_type | Msg_text | +-----------------+---------+-----------+-----------------------------------------+ | state | repair | warning | number of rows changed from 0 to 104237 | | test.state | repair | status | ok | +-----------------+---------+-----------+-----------------------------------------+ 2 rows in set (1 min 25.12 sec) Листинг 4.4. (html, txt) Для безопасного создания резервных копий лучше пользоваться специальной программой, чем делать все вручную. С этой целью в дистрибутив MySQL входит Perl-сценарий mysqlhotcopy. В листинге 4.5 показано, как с его помощью создаются копии таблиц привилегий. Команда ls позволяет убедиться, что все файлы, в том числе индексные, на месте. # mysqlhotcopy mysql /trap/hc Locked 6 tables in 0 seconds. Flushed tables(mysql.columns_priv, mysql.db, mysql.func, mysql.host, mysql.tables_priv, mysql.user) in 0 seconds. Copying 18 files… Copying indices for 0 files… Unlocked tables. Mysqlhotcopy copied 6 tables |(18 files) in 1 second (1 seconds overall). # ls /tmp/hc/mysql columns_priv.MYD db.MYD func.MYD host.MYD tables_priv.MYD user.MYD columns_priv.MYI db.MYI func.MYI host.MYI tables_priv.MYI user.MYI columns_priv.frm db.frm func.frm host.frm tables_priv.frm user.frm Листинг 4.5. (html, txt) 27 Сценарий mysqlhotcopy блокирует одновременно все таблицы базы данных, после чего очищает табличные буферы и копирует файлы. Сценарий можно запускать во время работы сервера, даже если в этот момент пользователи делают запросы к базе данных. Естественно, пока происходит копирование таблиц, пользователям будет запрещено вносить в них изменения. Формат табличных файлов понятен только программе MySQL. Если же создать SQL-образы таблиц, то их можно будет перенести в другие СУБД. Кроме того, в некоторых ситуациях полезно просматривать такие SQL-инструкции. Предположим, к примеру, что потеря данных оставалась незамеченной на протяжении нескольких месяцев. Возможно, пользователи удалили какие-то записи и лишь позднее обнаружили, что это было сделано неправильно. Нужно восстановить только удаленные записи, но не известно, когда точно они были удалены. Если резервные копии хранятся в формате SQL, можно просмотреть архивы и поискать, когда последний раз встречались требуемые записи. Недостатком такого способа резервного копирования является то, что процедура восстановления занимает много времени, поскольку программа MySQL вынуждена выполнять каждую инструкцию из архива. Для создания sql-образа таблицы предназначена утилита mysqldump. Она записывает текст инструкций в поток stdout, поэтому нужно перенаправить результаты ее работы в файл. Влистинге 4.6 показан созданный этой утилитой образ таблицы db из базы данных mysql. Утилита была запущена с опцией --opt которая включает режим оптимальных установок. # MySQL dump # # Host: localhost Database: mysql # # Server version 4.12.25-log # # Table structure for table 'db' # DROP TABLE IF EXISTS db; CREATE TABLE db ( Host char(60) binary NOT NULL default '', Db char(64) binary NOT NULL default '', User char(16) binary NOT NULL default '', Select_priv enum('N', 'Y') NOT NULL default 'N', Insert_priv enum('N', 'Y') NOT NULL default 'N', Update_priv enum('N', 'Y') NOT NULL default 'N', Delete_priv enum('N', 'Y') NOT NULL default 'N', Create_priv enum('N', 'Y') NOT NULL default 'N', Drop_priv enum('N', 'Y') NOT NULL default 'N', Grant_priv enum('N', 'Y') NOT NULL default 'N', References_priv enum('N', 'Y') NOT NULL default 'N', Index_priv enum('N', 'Y') NOT NULL default 'N', Alter_priv enum('N', 'Y') NOT NULL default 'N', PRIMARY KEY (Host, Db, User), KEY User (User) )TYPE=MyISAM COMMENT = 'Database privileges'; tt # Dumping data for table 'db' # 28 LOCK TABLES db WRITE; INSERT INTO db VALUES ('%', 'test', '', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'N', 'Y', 'Y', 'Y'), ('%', 'test\\_%', '', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'N', 'Y', 'Y', 'Y'), ('Localhost', 'freetime', 'httpd', 'Y', 'Y', 'Y', 'Y', 'N', 'N', 'N', 'N', 'N', 'N'); UNLOCK TABLES; Листинг 4.6. (html, txt) He забудьте заблокировать все таблицы для чтения, прежде чем запускать утилиту mysqldump. В противном случае целостность результатов не гарантируется. Предположим, имеется приложение, которое хранит информацию о клиентах и их электронных адресах. Создание учетной записи нового клиента включает добавление записи в таблицу client и последующую вставку одной или нескольких записей в таблицу email_address. Если параллельно с этим создавать резервную копию базы данных, то может оказаться, что в промежутке между созданием образов таблиц client и email_address приложение попытается обновить обе эти таблицы. Доступ к первой таблице будет запрещен, а ко второй — нет. В результате в архиве появятся адреса, не соответствующие ни одной записи таблицы клиентов. Чтобы восстановить данные из такого архива, достаточно выполнить SQL-сценарий в интерпретаторе mysql. Можно просто перенаправить сценарий на вход этой утилиты или же воспользоваться ее командой source. Интерпретатор выполнит все инструкции сценария так, как если бы они были введены в командной строке. Утилита mysqldump имеет режим создания текстового образа таблицы. В этом режиме для каждой архивируемой таблицы создаются два файла. Один из них имеет расширение .sql и содержит соответствующую инструкцию CREATE TABLE. Второй файл имеет расширение .txt и содержит записи таблицы, причем для разделения полей применяются символы табуляции. В листинге 4.7 показана команда, создающая текстовый образ таблицы dictionary в каталоге /tmp. [/tmp]# mysqldump --verbose --tab=/tmp test dictionary # Connecting to localhost... # Retrieving table structure for table dictionary... # Sending SELECT query... # Disconnecting from localhost... Листинг 4.7. (html, txt) Для восстановления данных из такого архива необходимо сначала создать таблицу, а затем выполнить инструкцию LOAD DATA INFILE, которая вставит записи в таблицу. Стандартный формат файла, создаваемого утилитой mysqldump, соответствует тому формату, который по умолчанию распознается инструкцией LOAD DATA INFILE. В листинге 4.8 демонстрируется загрузка данных в таблицу dictionary в среде mysql. mysql> source /tmp/dictionary.sql Query OK, 0 rows affected (0.00 sec) mysql> LOAD DATA INFILE '/tmp/dictionary.txt' INTO TABLE dictionary; Query OK, 104237 rows affected (1 min 27.70 sec) Records: 104237 Deleted: 0 Skipped: 0 Warnings: 0 Листинг 4.8. (html, txt) 29 Создать файл, понимаемый инструкцией LOAD DATA INFILE, позволяет также инструкция SELECT с предложением INTO (листинг 4.9). Схему таблицы необходимо получить другим путем, например с помощью инструкции SHOW CREATE TABLE. mysql> SELECT * FROM dictionary INTO OUTFILE 'tmp/dictionary.txt'; Query OK, 104237 rows affected (6.42 sec) Листинг 4.9. (html, txt) Один из способов восстановления таблиц заключается в использовании двоичного журнала. Достаточно преобразовать его содержимое в SQL-инструкции и выполнить их. Предварительно необходимо заблокировать все таблицы для записи или отключить всех клиентов от сервера. Преобразование двоичного журнала осуществляется с помощью утилиты mysqlbinlog (листинг 4.10). Результаты ее работы нужно направить в файл или интерпретатору mysql. Обратите внимание: инструкция SET меняет метку текущего времени сеанса, чтобы дата создания таблицы осталась неизменной. # mysqlbinlog --offset=1 --short-form red-bin.001 use freetime; SET TIMESTAMP=991767105; UPDATE session SET LastAction = now() WHERE ID='fNbbnOLBYYlqesqa'; use freetime; SET TIMESTAMP=991767134; UPDATE session SET LastAction = now() WHERE ID='fNbbnOLBYYlqesqa'; use freetime; SET TIMESTAMP=991767134; DELETE FROM project_view WHERE Project=2 AND User=2; use freetime; SET TIMESTAMP=991767135; INSERT INTO project_view VALUES (2, 2, now()); Листинг 4.10. (html, txt) 30 ЛЕКЦИЯ 5. Сценарии и утилиты MySQL Описание: В этой лекции дается представление о стандартной модели взаимодействия открытых систем OSI, уровнях функций, выполняемых при взаимодействии по сети, возможностях сетевых адаптеров и промежуточных сетевых устройств. Обзор серверных сценариев и утилит Все программы MySQL имеют множество различных опций. При этом каждая программа MySQL поддерживает опцию -help, которую можно использовать для получения полного описания различных опций программы. Например, попробуйте выполнить mysql -help. Заданные по умолчанию опции для всех стандартных программ можно переопределять при помощи файла опций. В следующем списке приводятся краткие описания серверных программ MySQL. myisamchk Утилита, применяемая для описания, проверки, оптимизации и восстановления таблиц MySQL. Поскольку утилита myisamchk имеет много функций, она описывается отдельно. make_binary_distribution Создает бинарную поставку откомпилированного кода MySQL. Эту версию при помощи FTP можно передать на сайт support.mysql.com в директорию /pub/mysql/Incoming, чтобы ею могли воспользоваться и другие пользователи MySQL. mysqlbug Сценарий, составляющий отчет о возникшей в MySQL неполадке. Этот сценарий должен всегда использоваться для составления отчета для почтового списка рассылки MySQL. mysqld Сам сервер MySQL, демон. Он должен работать постоянно. mysql_install_db Создает таблицы привилегий MySQL с заданными по умолчанию привилегиями. Это обычно делается только один раз, при первой инсталляции MySQL в системе. safe_mysqld, оболочка mysqld В MySQL 4.0 safe_mysqld был переименован в mysqld_safe. safe_mysqld — это сценарий, с помощью которого рекомендуется запускать демон mysqld на Unix. safe_mysqld служит для реализации неких дополнительных функций безопасности для mysqld, таких, как возможность перезапуска сервера при обнаружении ошибки и записи в журнал информации о процессе работы mysqld. 31 Если не указаны опции -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]. Обратите внимание: все опции, которые вводятся в командной строке для safe_mysqld, передаются mysqld. Если требуется применить в safe_mysqld какие-либо опции, которые mysqld не поддерживает, эти опции нужно определить в файле опций. Большинство опций safe_mysqld - те же, что и у mysqld. Safe_mysqld поддерживает следующие опции: -ledir=path -log-error=path -datadir=path, -defaults-extrafile=path, -defaults-file=path, -log=path, -pid-file=path -no-defaults -open-files-limit=# Путь к mysqld Записывать журнал ошибок в указанный файл Служебные пути для mysqld Максимальное количество файлов, которые могут быть открыты mysqld. Значение передаетсяulimit -n. Обратите внимание: чтобы эта опция работала корректно, необходимо запуститьsafe_mysqld от пользователя root! -port=# Номер порта для сетевой связи -socket=path Сокет для связи -timezone=# Устанавливает переменную часового пояса (TZ) в значение, передаваемое в этом параметре -core-file-size=# Размер файла, который mysqld должен быть способен создать. Используйте ulimit -c -mysqld=mysqld- Имя версии mysqld в каталоге ledir version -user=# Имя пользователя Сценарий safe_mysqld написан таким образом, чтобы можно было запустить сервер, инсталлированный как из исходного кода, так и из бинарной поставки MySQL, даже если компоненты сервера, в зависимости от используемой инсталляции, будут размещены несколько подругому. Для safe_mysqld требуется выполнение одного из следующих условий. Сервер и базы данных можно обнаружить относительно каталога, в котором вызывается safe_mysqld. safe_mysqld ищет в своей рабочей директории bin и data (для бинарных дистрибутивов) или libexec и var (для дистрибутивов с исходным кодом). Это 32 условие должно выполняться, если 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 будет записана поверх старой, поэтому нужно сделать копию отредактированной версии, которую вы сможете затем установить повторно. Mysqld_multi, программа для управления множеством серверов MySQL Программа mysqld_multi предназначена для управления несколькими процессами mysqld, работающих на различных сокетах Unix и портах TCP/IP. Программа будет искать группу(группы) [mysqld#] в my.cnf (или заданных при помощи -configfile=... файлах), где # — любое положительное число, начиная с 1. Мы говорим про этот номер далее как про номер группы опций, или GNR. Номера групп различают группы опций одну от другой и используются как аргумент при запуске mysqld_multi чтобы указать, какие серверы вы хотите запустить, остановить или получить статус. Эти группы должны быть такими же, как и обычная группа [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 не должно быть никаких пропусков (пробелов, символов табуляции или пустых строк). Любые данные после пропуска будут игнорироваться. 33 mysqld_multi поддерживает следующие опции: -configfile=... -example -log=... Альтернативный файл конфигурации (config file). Примечание: данный файл не влияет на собственные опции этой программы (группа [mysqld_multi]), а только на группы [mysqld#]. Без этой опции поиск всех данных будет осуществляться только в обычном файле my.cnf Представляет пример файла конфигурации Файл журнала. Имя файла журнала и полный путь к нему. Примечание: если файл существует, записи будут добавляться в конец файла Исполняемый файл 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 Вывод номера версии и завершение работы myisampack, MySQL-генератор сжатых таблиц (только для чтения) Утилита myisampack используется для сжатия таблиц MyISAM, а утилита pack_isam — для сжатия таблиц ISAM. Поскольку таблицы ISAM являются устаревшими, здесь будет рассматриваться только myisampack. myisampack сжимает каждый столбец в таблице по отдельности. Информация, необходимая для декомпрессии столбцов, считывается в память при открытии таблицы. В результате обеспечивается более высокая производительность при доступе к отдельным записям, поскольку нужно распаковывать только одну запись, а не значительно больший по размеру дисковый блок, как при использовании программы Stacker в MS DOS. В среднем myisampackсжимает файл данных на 40%70%. MySQL использует отображение в памяти (mmap()) для сжатых таблиц, а если mmap() не работает, возвращается назад к нормальному режиму чтения/записи. Обратите внимание на следующее: После сжатия таблица доступна в режиме только для чтения. Это удобно, скажем, для записи на CD. myisampack может также сжимать столбцы c типами BLOB или TEXT. Утилиту myisampack можно запустить следующим образом: shell> myisampack [options] filename ... 34 Каждое имя файла (filename) должно быть именем индексного файла (.MYI). Если вы не находитесь в директории базы данных, необходимо указать полный путь к файлу. Допускается опускать расширение .MYI. myisampack поддерживает следующие опции: -b, -backup -#, Создает резервную копию таблицы, присваивая ей имя tbl_name.OLD Выводить журнал отладки. Строка debug_options часто принимает значение d:t:o,filename debug=debug_options -f, Сжатие таблицы происходит, даже если она увеличивается или если существует временный файл. Во время сжатия таблицы myisampack создает -force временный файл tbl_name.TMD. Если вы вручную прекратите выполнение myisampack, может оказаться, что файл tbl_name.TMD не будет удален. Обычно если myisampack обнаруживает существующий tbl_name.TMD, она прекращает работу и выдает ошибку. При указании опции -force myisampack сжимает таблицу в любом случае -j big_tbl_name, Соединяет все таблицы, указанные в командной строке, в одну таблицу big_tbl_name. Все таблицы, подлежащие объединению, должны быть -join=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 -w, Если таблица уже используется, подождать повторить попытку. Если сервер mysqld был вызван с опцией -skip-external-locking, то не самая лучшая -wait идея — вызывать myisampack, если таблица может модифицироваться во время процесса сжатия Последовательность приведенных ниже команд иллюстрирует типичный сеанс сжатия таблицы: shell> ls -l station.* -rw-rw-r-- 1 monty my 994128 Apr 17 19:00 station.MYD 35 -rw-rw-r-- 1 monty my -rw-rw-r-- 1 monty my 53248 Apr 17 19:00 station.MYI 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 1 2 4 unique unsigned long 2 32 30 multip. text Root Blocksize Rec/key 1024 1024 1 10240 1024 1 Field Start Length Type 1 1 1 2 2 4 ... ... ... ... ... ... ... ... 56 57 827 4 831 4 shell> myisampack station.MYI Compressing station.MYI: (1192 records) - Calculating statistics normal: 20 empty-space: 16 empty-zero: pre-space: 0 end-space: 12 table-lookups: Original trees: 57 After join: 17 - Compressing file 87.14% shell> ls -l station.* -rw-rw-r-- 1 monty my -rw-rw-r-- 1 monty my -rw-rw-r-- 1 monty my 12 empty-fill: 11 5 zero: 7 127874 Apr 17 19:00 station.MYD 55296 Apr 17 19:04 station.MYI 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 36 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 1 2 4 unique unsigned long 2 32 30 multip. text Root Blocksize Rec/key 10240 1024 1 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 ... ... ... ... ... ... ... ... 53 805 1 54 806 1 55 807 20 no empty 56 827 4 no zeros, zerofill(2) 57 831 4 no zeros, zerofill(1) Листинг 5.1. (html, txt) 17 3 1 9 3 9 2 2 9 9 Ниже приведено описание вывода myisampack: normal emptyspace emptyzero empty-fill Количество столбцов, для которых не используется никакого дополнительного сжатия Количество столбцов, содержащих пустые значения; они занимают по 1 биту Количество целочисленных столбцов, в которых содержатся только двоичные нули (ascii 0); каждый из них будет занимать 1 бит Количество целочисленных столбцов, значения которых не полностью занимают отведенную для них разрядность в байтах; тип этих столбцов изменяется на тип с меньшей разрядностью (например, столбецINTEGER может быть изменен на MEDIUMINT) pre-space Количество десятичных столбцов, которые хранятся с начальными пробелами. В этом случае каждое значение будет содержать число ведущих пробелов end-space Количество столбцов, имеющих много оконечных пробелов. В этом случае каждое значение будет содержать число таких пробелов tableСтолбец имеет только небольшое количество различающихся значений, которые перед lookup сжатием Хаффмана (Huffman) конвертируются в ENUM zero Количество столбцов, все значения которых являются нулями Original Начальное количество деревьев Хаффмана 37 trees After join Количество различных деревьев Хаффмана, оставленных после соединения деревьев для сохранения небольшого пространства в заголовках После сжатия таблицы myisamchk -dvv выводит дополнительную информацию по каждому полю. Type Тип поля может содержать следующие дескрипторы: constant no endspace no endspace, not_always no endspace, no empty table-lookup zerofill(n) no zeros always zero Все строки содержат одинаковое значение Не сохраняются замыкающие пробелы Не сохраняются замыкающие пробелы и не производится сжатие за счет замыкающих пробелов для всех значений Не сохраняются замыкающие пробелы. Не сохраняются пустые значения Столбец был преобразован к ENUM В значении n главных байтов всегда являются 0 и не сохранены. Не сохраняются нули. Значения 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. Обзор клиентских сценариев и утилит Все клиенты MySQL, которые взаимодействуют с сервером с помощью библиотеки mysqlclient, используют следующие переменные окружения: Имя Описание MYSQL_UNIX_PORT Сокет, используемый по умолчанию для локальных подсоединений 38 MYSQL_TCP_PORT MYSQL_PWD MYSQL_DEBUG TMPDIR Устанавливаемый по умолчанию порт TCP/IP Устанавливаемый по умолчанию пароль Опции пошаговой отладки программ Каталог для создания временных таблиц/файлов Клиент mysql использует файл, указанный в переменной окружения MYSQL_HISTFILE, для хранения истории командной строки. Значение по умолчанию для этого файла истории — $HOME/.mysql_history, где $HOME — значение переменной окружения HOME. Все программы MySQL принимают множество различных опций. Для всех стандартных клиентских программ можно переопределить значения опций по умолчанию, задействуя файл опций. В приведенном ниже списке дано краткое описание клиентских программ MySQL. msql2mysql Сценарий оболочки операционной системы, преобразующий программы базы данных mSQL к виду, приемлемому для MySQL. Он не обрабатывает всех случаев, но с него хорошо начинать такое преобразование mysqlaccess Сценарий, который проверяет привилегии доступа для комбинации значений хоста, пользователя и базы данных mysqladmin Утилита для выполнения административных функций, таких, как создание или удаление баз данных, перезагрузка таблиц привилегий, запись на диск содержимого таблиц, находящегося в буфере, повторное открытие файлов журналов. Утилита mysqladmin может также использоваться для получения информации с сервера о номере версии, процессах и состоянии сервера mysqldump Выводит содержимое базы данных MySQL в виде файла с SQL-операторами или в виде текстовых файлов с символом табуляции в качестве разделителя mysqlimport Импортирует текстовые файлы в соответствующие таблицы, используя команду LOAD DATA INFILE >mysqlshow Отображает информацию о существующих базах данных, таблицах, полях и индексах replace Служебная программа, использующаяся в сценарии msql2mysql, но имеющая также более широкое применение. Утилита replace изменяет строки, находящиеся в файлах или в стандартных входных данных. Использует принцип конечного автомата, чтобы в первую очередь найти соответствие длинных строк. Может применяться для замены строк Утилита командной строки mysql Утилита командной строки mysql является простой SQL-оболочкой (с возможностями библиотеки readline проекта GNU). Она поддерживает интерактивный и неинтерактивный режимы. В интерактивном режиме результаты запроса представляются в ASCII-формате. При использовании в неинтерактивном режиме (например, в качестве фильтра) результат представляется в текстовом формате с символом табуляции в качестве разделителя (выходной формат можно изменить при помощи параметров командной строки). Сценарии можно запускать, как показано ниже: shell> mysql database < script.sql > output.tab 39 Если возникают проблемы из-за недостатка памяти на данном клиенте, применяйте параметр quick! Это заставит mysql использовать функцию mysql_use_result() вместо функции mysql_store_result() для получения результирующей выборки данных. Использовать mysql очень легко. Запустите mysql database или mysql -user=user_name password=your_password database. Наберите SQL-команду прямо в командной строке, завершив ее одним из символов: ';', '\g' или '\G', и нажмите клавишу "Ввод". Утилита командной строки mysql поддерживает следующие параметры. -?, -help Вывод справочной информации об использовании программы и выход из нее -A, -no-auto-rehash Отключает автоматическое рехеширование. Rehash следует использовать для получения хеша таблиц и полей. Это обеспечивает более быстрый старт mysql -prompt=... Устанавливает приглашение на ввод команд в заданном формате -b, -no-beep Выключает звуковой сигнал об ошибке -B, -batch Выводит результаты в пакетном режиме с символом табуляции в качестве разделителя, каждая строка с новой строки. Файл истории не используется -character-setsДиректория, где находятся наборы символов dir=... -C, -compress Использовать сжатие данных в протоколе сервер/клиент -#, -debug[=...] Журнал отладки. Значение по умолчанию —'d:t:o,/tmp/mysql.trace' -D, -database=... Имя используемой базы данных. Большей частью применяется в конфигурационном файле my.cnf -default-character- Установить набор символов по умолчанию set=... -e, -execute=... Выполнить команду и завершить программу (вывод результата как и для -batch) -E, -vertical Вывести результаты запроса (строки) по вертикали. Можно произвести вывод подобным образом и без данного параметра, завершая команды символами\G -f, -force Продолжать обработку даже при обнаружении ошибки SQL -g, -no-namedВыключает именованные команды. Следует использовать только команды commands вида \* либо применять именованные команды только в начале строки, заканчивающейся символом ';' -i, -ignore-space Игнорировать пробел после имен функций -h, -host=... Подсоединиться к базе данных на указанном хосте -H, -html Вывести выходные данные в виде HTML -X, -xml Вывести выходные данные в виде XML -L, -skip-lineНе указывать номера строк для ошибок. Полезно для сравнения numbers результирующих файлов, включающих сообщения об ошибках -no-pager Блокирует пейджер (программа постраничного вывода) и выводит результат в стандартный выводstdout (в Unix) -no-tee Блокирует выходной файл. Смотрите также команду\h (интерактивная помощь) -n, -unbuffered Очищать буфер после каждого запроса -N, -skip-column- Не указывать имена столбцов в результатах names -o, -one-database Обновить только базу данных, установленную по умолчанию. Позволяет пропускать обновления другой базы данных в журнале обновления 40 Устанавливает тип данных вывода. По умолчанию это переменная окружения PAGER. Ее возможные значения - less, more, cat [> имя файла], и т.д. -p[password], Пароль, используемый при подсоединении к серверу баз данных. Если в password[=...] командной строке пароль не указан, то он запрашивается у пользователя. При использовании краткой формы -p не оставляйте пробел между параметром и значением пароля -P порт, -port=порт Номер порта TCP/IP, используемый для подсоединения -q, -quick Не кэшировать результат. Выводить его строка за строкой так, как он приходит от сервера. Это может замедлить скорость работы сервера, если вывод результата будет приостановлен. Файл истории не используется -s, -silent Режим молчания. Выводить только сообщения об ошибках -S -socket=... Файл сокета, используемый для подсоединения -t -table Выводить результат в табличном формате. Установлено по умолчанию для непакетного режима -tee=... Присоединить что-либо к выходному файлу. Смотрите также команду \h (интерактивная помощь). Этот параметр не работает в пакетном режиме -u, -user=# Имя пользователя MySQL, если этот пользователь не является активным в данное время -pager[=...] mysqladmin, администрирование MySQL-сервера. Утилита для выполнения административных операций. Ее синтаксис: shell> mysqladmin [ПАРАМЕТРЫ] command [command-option] command ... Список опций, поддерживаемых вашей конкретной версией mysqladmin, можно получить, выполнив команду mysqladmin -help. Текущая версия mysqladmin поддерживает следующие команды: create databasename Создать новую базу данных. drop databasename Удалить базу данных и все ее таблицы. extended-status Выдает расширенный отчет о состоянии сервера (более полный, чем при командеstatus ). flush-hosts Сбросить и перезагрузить хосты. flush-logs Сбросить на диск и переоткрыть все журналы. 41 flush-tables Закрыть все открытые таблицы. flush-privileges Перечитать таблицы привилегий. kill id,id,... Завершить потоки mysql с указанными thread-id. password Установить новый пароль для сервера баз данных. Изменить старый пароль на новый. ping Проверить, работает ли сервер mysqld. processlist Показать список активных потоков на сервере. reload Перезагрузить таблицы привилегий. refresh Выполнить все табличные операции, находящиеся в буфере, закрыть и открыть заново все системные журналы. shutdown Завершить работу сервера баз данных. slave-start Запустить подчиненный дублирующий поток. slave-stop Остановить подчиненный дублирующий поток. status Выдает краткий отчет о состоянии сервера. variables Вывести доступные для использования переменные. 42 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 Threads Questions Slow queries Описание Количество секунд с момента запуска MySQL-сервера Количество активных потоков (клиентов) Количество вопросов от клиентов с момента запуска программы mysqld Количество запросов, потребовавших большее количество секунд, чем установлено в конфигурации ключомlong_query_time Opens Количество таблиц, открытых программой mysqld Flush table Количество выполненных команд flush ..., refresh, reload Open tables Количество таблиц, открытых в данное время Memory in Память, используемая непосредственно программой mysqld (доступно только в случае use компиляции MySQL с установленным значением -with-debug=full) Max Максимальный объем памяти, использованный непосредственно программой mysqld memory (доступно только в случае компиляции MySQL с установленным значением -withused debug=full) При выполнении mysqladmin shutdown через сокет (другими словами, через компьютер с запущенным mysqld) mysqladmin будет ожидать, пока на сервере MySQL не будет удален файл pidfile (в котором содержится идентификатор процесса pid запущенного сервера), чтобы убедиться, что сервер остановлен должным образом. Использование mysqlcheck для сопровождения и аварийного восстановления таблиц. Начиная с версии MySQL 3.23.38, можно применять новый инструмент для проверки и восстановления MyISAM-таблиц. Отличие mysqlcheck от myisamchk состоит в том, что утилита mysqlcheck должна использоваться при работающем сервере mysqld, в то время как myisamchk — при остановленном. Преимущество же заключается в том, что теперь не нужно останавливать сервер для проверки или восстановления таблиц. Утилита mysqlcheck использует соответствующие команды MySQLсервера CHECK, REPAIR,ANALYZE и OPTIMIZE удобным для пользователя образом. 43 Существует три альтернативных способа запуска mysqlcheck: shell> mysqlcheck [OPTIONS] database [tables] shell> mysqlcheck [OPTIONS] -databases DB1 [DB2 DB3...] shell> mysqlcheck [OPTIONS] -all-databases Таким образом, утилита может использоваться подобно mysqldump по отношению к выбранным базам данных и таблицам. В сравнении с другими клиентами утилита mysqlcheck имеет следующую отличительную особенность: установка поведения по умолчанию (проверка таблиц, -с) может быть изменена путем переименования исполняемого файла утилиты. Итак, чтобы получить инструмент, восстанавливающий таблицы по умолчанию, просто скопируйтеmysqlcheck с новым именем, mysqlrepair, или, наоборот, сделайте символьную ссылку на mysqlcheck и обозначьте ее какmysqlrepair. Если теперь запустить mysqlrepair, то утилита по умолчанию будет восстанавливать таблицы. mysqldump, получение дампов данных и структуры таблицы Данная утилита позволяет получить дамп ("моментальный снимок") содержимого базы данных или совокупности баз для создания резервной копии или пересылки данных на другой SQL-сервер баз данных (не обязательно MySQL-сервер). Дамп будет содержать набор команд SQL для создания и/или заполнения таблиц. Если же резервная копия создается на сервере, то вместо описываемой утилиты следует использовать mysqlhotcopy. 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). 44 -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=... , 45 -fields-escaped-by=... , -lines-terminated-by=... Эти опции используются совместно с параметром -T и имеют то же самое значение, что и соответствующие операторы дляLOAD DATA INFILE. -F, -flush-logs Записать на диск данные системного журнала из буфера MySQL-сервера перед началом выполнения дампа. -f, -force, Продолжать даже при получении ошибки SQL при выполнении дампа таблицы. -h, -host=.. Выполнить дамп данных MySQL сервера на указанном хосте. Значение хоста по умолчанию — localhost. -l, -lock-tables. Заблокировать все таблицы перед началом выполнения дампа. Таблицы блокируются оператором READ LOCAL, чтобы разрешить параллельные записи для MyISAM-таблиц. Следует отметить, что при выполнении дампа совокупности баз данных опция -locktables блокирует таблицы каждой базы по отдельности. Таким образом, использование этого параметра не гарантирует, что таблицы будут логически непротиворечивы в пределах этих баз данных. В различных базах данных при выполнении дампа таблицы могут находиться в совершенно разных состояниях. -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 46 То же, что и -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 47 Перекрывает параметр -databases (-B). -T, -tab=path-to-some-directory Для каждой заданной таблицы создает файл table_name.sql, содержащий SQL CREATE команды для создания таблицы, и файл table_name.txt с данными таблицы. Файл .txt имеет формат в соответствии с параметрами -fields-xxx и -linesxxx. Примечание: этот параметр работает только при условии, что утилита 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 При создании многострочных операторов ввода (как и в случаях применения параметров -extendedinsert или -opt) утилита mysqldump будет создавать строки длиной вплоть до указанной в net_buffer_length. При увеличении значения этой переменной необходимо также убедиться в том, что в MySQL-сервере для переменной max_allowed_packet указано значение, большее, чем величина net_buffer_length. Чаще всего утилита mysqldump используется для получения резервной копии всех баз данных. 48 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 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 поддерживает следующие опции: -u, -user=# Имя пользователя для входа в базу данных. -p, -password=# Используемый пароль при подсоединении к серверу. -P, -port=# Номер порта, используемого для подсоединения к локальному серверу. -S, -socket=# Номер сокета, используемого для подсоединения к локальному серверу. 49 -keepold Не удалять предыдущий результат (только что переименованный) после выполнения команды. -q, -quiet Выводить только сообщения об ошибках. -debug Разрешить отладку. -n, -dryrun Сообщать о действиях без их выполнения. -regexp=# Копировать все базы данных с именами, встречающимися в функции regexp. -checkpoint=# Внести проверочную запись в предусмотренную таблицу базы данных. -flushlog Записать на диск данные журналов из буфера, как только все таблицы заблокируются. -tmpdir=# Временная директория (вместо /tmp). А также некоторые другие. Более полное описание данного сценария можно посмотреть в документации по языку программирования Perl. Сценарий mysqlhotcopy берет информацию для групп [client] и [mysqlhotcopy] из файлов опций. Для выполнения программы mysqlhotcopy необходимы доступ для записи в директорию, куда будет помещена копия, и привилегия выполнения команды SELECT для копируемых таблиц и команды RELOAD для MySQL-сервера (чтобы выполнить FLUSH TABLES). mysqlimport, импорт данных из текстовых файлов Утилита mysqlimport обеспечивает интерфейс командной строки для SQL-оператора LOAD DATA INFILE. Большинство параметров mysqlimport полностью соответствует аналогичным параметрам для оператора LOAD DATA INFILE. Утилита mysqlimport вызывается следующим образом: shell> mysqlimport [параметры] database textfile1 [textfile2 ...] 50 Для каждого текстового файла, указанного в командной строке, mysqlimport удаляет расширение в каждом имени файла и использует его, чтобы определить, в какую таблицу занести содержимое. Например, файлы с именами patient.txt, patient.text и patientдолжны быть все занесены в таблицу с именем patient. Утилита mysqlimport поддерживает следующие опции: -c, -columns=... Эта опция принимает в качестве аргумента список разделенных запятыми имен полей. Данный список полей используется для создания соответствующей команды LOAD DATA INFILE, которая затем посылается в MySQL. -C, -compress Использовать компрессию в связи между клиентом и сервером, если они оба поддерживают сжатие. -#, -debug[=option_string] Отслеживать прохождение программы (для отладки). -d, -delete Удалить данные из таблицы перед импортированием текстового файла. -f, -force Игнорировать ошибки. Например, если таблица для текстового файла не существует, продолжать обработку остающихся файлов. Без параметра force утилита mysqlimport прекращает работу при отсутствии таблицы. -h host_name, -host=host_name Импортировать данные в MySQL-сервер на указанном хосте. Значение хоста по умолчанию — localhost. -l, -lock-tables Заблокировать все таблицы для записи перед обработкой любых текстовых файлов. Это обеспечивает синхронизацию всех таблиц на сервере. -L, -local Читать входящие файлы из клиента. По умолчанию предполагается, что текстовые файлы расположены на сервере при подсоединении к localhost (значение хоста по умолчанию). -pyour_pass, -password[=your_pass] Используемый пароль при подключении к серверу. Если аргумент =your_pass не введен, mysqlimport предложит ввести пароль. 51 -P port_num, -port=port_num Номер порта TCP/IP, используемого для подсоединения к хосту. -r, -replace Опции -replace и -ignore управляют обработкой поступающих на вход записей, которые дублируют имеющиеся записи по значениям уникальных ключей. Если задано значение replace, новые строки заменяют существующие с тем же самым значением уникального ключа. Если задано значение -ignore, входные строки, которые дублируют существующую строку по значению уникального ключа, пропускаются. Если же ни одна из опций не задана, то при обнаружении ключа-дубликата возникает ошибка и остаток текстового файла игнорируется. -s, -silent Режим молчания. Выводить только сообщения об ошибках. -u user_name, -user=user_name Имя пользователя MySQL-сервера, используемое при подсоединении к серверу. Значением по умолчанию является имя для входа в Unix. mysqlshow, просмотр баз данных, таблиц и столбцов Утилита mysqlshow позволяет кратко ознакомиться с существующими базами данных, их таблицами и столбцами таблиц. Аналогичную информацию можно получить с помощью программы mysql, используя команду SHOW. Утилита mysqlshow вызывается следующим образом: shell> mysqlshow [ПАРАМЕТРЫ] [database [table [column]]] Если имя базы данных не указано, то выдается список всех существующих баз данных. Если не указана таблица — показываются все таблицы, найденные в этой базе данных. Если не задан столбец — показываются все найденные в таблице столбцы и представленные в виде столбцов данные. Следует отметить, что в более новых версиях MySQL пользователь может просмотреть только те базы/таблицы/столбцы, для которых у него имеются соответствующие привилегии. Если последний аргумент содержит в себе шаблонные символы (*, ?, % или _) процессора или SQL, то будут представлены только данные, совпадающие с шаблоном. Если имя базы данных содержит подчеркивание, то оно должно быть экранировано обратным слешем (некоторые оболочки в Unix востребуют два обратных слеша) для того, чтобы получить корректные имена. '*'конвертируются в '%' и '?' - в '_'. Это может вызвать путаницу при попытке просмотреть столбцы таблицы с символом _, так как в таком случае mysqlshow покажет только имена таблиц, совпадающие с шаблоном. Ситуацию можно 52 легко исправить добавлением дополнительного символа % в конец командной строки (как отдельного аргумента). 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: Компьютер не находится в сети Следует учитывать, что сообщения об ошибках в большинстве своем являются системнозависимыми! Запуск 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; 53 ЛЕКЦИЯ 6. Виды таблиц и способ их хранения Описание: В этой лекции рассказывается о том, какие виды таблиц существуют в MySQL и как организуется физическое хранение данных и способ представления этих таблиц на жестком диске. Способ хранения таблиц и баз данных В MySQL таблице соответствует несколько файлов. Их имена совпадают с именем таблицы, а расширение определяет назначение файла. К примеру, файл с расширением .frm содержит описание структуры таблицы. Что касается баз данных, то они являются подкаталогами основного каталога данных (по умолчанию это/usr/local/var). Имя подкаталога соответствует имени базы данных. Это означает, что имена баз данных и таблиц отвечают тем же требованиям, которые предъявляются к именам файлов в данной системе. Скажем, файловая система ext2 в Linux чувствительна к регистру символов, a FAT32 в Windows — нет. Операционные системы налагают свои ограничения на максимальный размер файла. Обычно он составляет от 2 до 4 Гбайт. Для таблиц типа MyISAM, описываемого ниже, все данные сохраняются в одном файле, следовательно, максимальный размер файла одновременно является максимальным размером таблицы. MySQL позволяет разбивать табличные данные на несколько файлов при наличии опцииRAID_TYPE в инструкции CREATE TABLE. Тогда максимальный размер таблицы возрастет во столько раз, сколько файлов для нее создается. Можно даже разместить эти файлы на разных физических дисках, чтобы повысить производительность базы данных. Выделенные разделы В некоторых СУБД поддерживаются выделенные файловые системы. Такая файловая система инсталлируется в собственный дисковый раздел, и лишь СУБД знает, как ее использовать. Сервер берет на себя выполнение всех функций файловой системы, тогда как обычно они предоставляются самой операционной системой. Теоретически это способствует повышению производительности. Тем не менее, MySQL не позволяет записывать базы данных в выделенные разделы, так как изоляция от операционной системы не стоит незначительного выигрыша производительности. Современные операционные системы обладают гораздо большей производительностью, чем раньше, в основном из-за того, что они способны кэшировать дисковые блоки в оперативной памяти. Если бы программе MySQL пришлось выполнять эти функции в обход операционной системы, то тогда память, используемая для кэширования, тоже стала бы выделенной, а объем общедоступной оперативной памяти уменьшился бы. Управление файлами в рамках операционной системы имеет свои преимущества. Во-первых, разработчики системы проделывают огромную работу по отладке соответствующих функций, а вовторых, появляется возможность пользоваться стандартными утилитами обработки файлов. Создать резервную копию базы данных MySQL можно с помощью обычной утилиты tar, а не специализированной программы. Выделенные файловые системы требуют целого набора управляющих утилит, в частности для проверки и восстановления файлов. Всего этого нет в MySQL. Типы таблиц Начиная с версии 3.23.37 в В MySQL поддерживаются семь типов таблиц. Три из них – Berkley DB, Gemini и Inno DB ориентированы на транзакции, а четыре — Heap, ISAM, Merge и MyIsam — 54 нет. Транзакции являются относительно новым понятием в MySQL, но соответствующие функции для таблиц Berkeley DB и InnoDB существуют уже достаточно давно, что позволило включить их в стандартные бинарные дистрибутивы. Стандартным типом таблиц в MySQL является тип MyISAM. Он возник на основе более старого типа ISAM, который все еще существует, хотя использовать его не рекомендуется. Переопределить установку по умолчанию позволяет опция TYPE инструкцийCREATE TABLE и ALTER TABLE Berkeley DB Проект Berkeley DB начался в Калифорнийском университете в Беркли. Впоследствии его авторы сформировали компанию Sleepycat Software (www.sleepycat.com) и занялись распространением коммерческой версии СУБД. Многие утилиты до сих пор работают со старыми версиями BDB (1.85 и 1.86), в то время как компания Sleepycat Software предлагает уже семейство версий 3.x и 4.x. Эта СУБД свободно распространяется с исходными кодами, и ею можно пользоваться бесплатно, за исключением случаев, когда на ее основе планируется создавать приложения, не распространяемые на условиях открытой лицензии. BDB — это простая файловая СУБД, поддерживающая транзакции, но не располагающая какимлибо языком запросов. В MySQL эта СУБД нужна для того, чтобы можно было работать с таблицами в режиме транзакций. С Web-узла MySQL можно загрузить скомпилированную версию программы, в которую встроена поддержка BDB. Если впоследствии потребуется отключить эту поддержку, достаточно будет запустить демон mysql с опцией –skip-bdb. На этапе компиляции MySQL поддержка BDB включается с помощью опции –with-berkeley-db. Для MySQL нужна исправленная версия BDB, которая входит в исходный дистрибутив MySQL. Разработчики MySQL тесно сотрудничают с программистами компании Sleepycat, чтобы гарантировать максимальную эффективность использования библиотеки BDB. Вообще-то, поддержка BDB в MySQL появилась не так давно (в версии 3.23.24), но, учитывая высокую стабильность обоих продуктов, их интеграция не привела к возникновению каких-либо трудностей для пользователей. Разработчики MySQL планируют и дальше улучшать поддержку BDB. С функциональной точки зрения таблицы BDB ведут себя аналогично таблицам MyISAM. Нет никаких ограничений на число столбцов или индексов, как в случае резидентных таблиц. Единственное условие: для таблиц BDB обязательно наличие первичного ключа. Если он не задан, MySQL самостоятельно создаст внутренний первичный ключ, охватывающий первые пять байтов каждой записи. К таблицам BDB можно применять инструкцию LOCK TABLES, но при частой работе с ними лучше пользоваться преимуществами транзакций. Сами транзакции реализуются посредством журнальных файлов, куда записываются сведения об изменении табличных данных. Когда происходит отмена транзакции, функции библиотеки BDB читают журнальные файлы и делают "обратные" исправления. Журнальные файлы носят имена вида log.0000000001 и располагаются в каталоге данных, хотя эту установку можно изменить с помощью опции, указываемой при запуске сервера. MySQL пытается очищать журнальные файлы BDB в момент создания нового журнального файла. При этом удаляются ненужные файлы. Если не хотите ждать, воспользуйтесь инструкцией FLUSH LOGS. 55 В BDB таблицы блокируются на уровне страниц. Страница — это совокупность последовательно расположенных записей таблицы. Страничные блокировки необходимы, когда MySQL сканирует таблицу, а также при удалении, вставке и обновлении записей. В отличие от таблиц MyISAM, блокировки таблиц BDB могут приводить к возникновению тупиков, т.е. взаимоблокировок. В подобной ситуации одна или несколько транзакций отменяется. Это следует учитывать при написании приложений. Инструкция, которая приводит к автоматической отмене транзакции, возвращает сообщение об ошибке. Транзакции отменяются также в случае нехватки места в файловой системе. СУБД BDB не ведет подсчет записей в таблицах, но MySQL хранит собственный счетчик. Он используется модулем оптимизации объединений при выборе индексов. Значение счетчика может быть неточным, если произошел сбой базы данных, но счетчик можно сбросить с помощью инструкции ANALYZE TABLE или OPTIMIZE TABLE. Ведение счетчика записей немного замедляет работу с таблицами BDB. Табличные данные хранятся в виде двоичного дерева. Это более медленный метод, чем тот, который применяется для таблицMyISAM. СУБД BDB оставляет в дереве пустые позиции, чтобы операции вставки выполнялись быстрее. В результате размер файла становится большим, чем нужно. В отличие от таблиц MyISAM, индексы в таблицах BDB не сжимаются, т.е. они занимают больше места. Если в запросе участвуют столбцы одного индекса, обращение к табличным данным не производится, так как в этом нет необходимости. С этой целью BDB позволяет объединять первичный ключ со столбцами другого индекса (для таблиц MyISAM такая возможность не поддерживается). Gemini Функции работы с таблицами Gemini реализовали программисты компании NuSphere (www.nusphere.com). Эта компания обеспечивает поддержку и обучение пользователей MySQL. В этих таблицах отсутствуют столбцы типа BLOB и TEXT. Количество пользователей, которые могут одновременно работать с таблицами, по умолчанию равно 100. Данную установку можно изменить с помощью серверной переменной gemini_connection_limit. Таблицы Gemini блокируются на уровне записей, так как это выгоднее с точки зрения многопользовательской работы. Если заблокировать всю таблицу, другие потоки вынуждены будут встать в очередь на доступ к таблице. Блокировки записей предотвращают доступ к единичным записям, позволяя нескольким потокам работать с одной таблицей, но в разных ее "участках". Как и в случае таблиц MyISAM, доступ к файлу данных таблицы Gemini не требуется, если в запросе участвуют столбцы одного индекса. Для этих таблиц также ведется счетчик записей, используемый модулем оптимизации объединений. Heap MySQL хранит таблицы типа Heap в памяти, а не в файловой системе. Следовательно, доступ к ним осуществляется чрезвычайно быстро. Для поиска записей применяется хэш-таблица, но проблем со вставкой или с удалением записей не возникает, в отличие от других реализаций резидентных таблиц. Резидентные таблицы не располагают многими возможностями обычных таблиц. Они не могут иметь столбцы типа BLOB или TEXT. Нельзя использовать флаг AUTO_INCREMENT. Можно 56 создавать индексы, но нельзя индексировать столбцы, допускающие значения NULL. Индексы используются только в операциях = и <=> . Записи резидентных таблиц имеют фиксированную длину. Для столбцов типа VARCHAR сразу выделяется максимальное число байтов. Поскольку память — ограниченный ресурс, можно задать предельное количество записей в резидентной таблице. Для этого предназначена опция max_rows инструкции CREATE TABLE. Серверная переменная max_heap_table_size задает максимальный объем памяти, занимаемой всеми резидентными таблицами. Доступ к резидентным таблицам имеют все пользователи. Эти таблицы уничтожаются при выключении сервера. InnoDB СУБД InnoDB была разработана Хейкки Туури (Heikki Tuuri) из компании Innobase — финского производителя программного обеспечения, специализирующегося на технологии реляционных баз данных. InnoDB представляет собой результат исследований, проводимых Хейкки в университете Хельсинки. Поддержка InnoDB появилась в MySQL версии 3.23. Сама СУБД доступна на условиях открытой лицензии. На Web-узле InnoDB можно найти массу информации о деталях работы ядра этой СУБД. Ядро не существует само по себе, а является дополнением к MySQL. С Web-узла MySQL можно загрузить скомпилированную версию программы, в которую встроена поддержка InnoDB. Если впоследствии потребуется отключить эту поддержку, достаточно будет запустить демон mysql с опцией –skipinnodb. На этапе компиляции MySQL поддержка InnoDB включается с помощью опции –withinnodb. Исходные кодыInnoDB входят в исходный дистрибутив MySQL. В отличие от таблиц MyISAM, где для каждой таблицы создается один файл данных, данные InnoDB хранятся в больших совместно используемых файлах. Можно создать произвольное число файлов данных, но их нельзя будет удалить. Размер файлов определяется в конфигурационном файле. Если нужно уменьшить объем дискового пространства, занимаемого таблицами InnoDB, создайте резервные копии таблиц, после чего удалите все файлы InnoDB и позвольте программе MySQL восстановить их в соответствии с новыми установками конфигурационного файла. Журнальные файлы InnoDB можно безопасно удалить после остановки сервера. При повторном запуске сервера программа MySQL создаст журнальные файлы заново. В листинге 6.1 приведен пример опций, которые необходимо добавить в конфигурационный файл в группу [mysql] чтобы активизировать таблицы InnoDB. Размер файлов здесь задан относительно небольшим, что вполне подходит для целей эксперимента. На практике используются файлы гораздо большего размера. innodb_data_home_dir = /usr/local/var/innodb/ innodb_data_file_path = ibdata1/ibdata1:100M; ibdata2/ibdata2:100M set-variable = innodb_mirrored_log_groups = 1 innodb_log_group_home_dir = /disk2/innodb/log set-variable = innodb_log_files_in_group = 3 set-variable = innodb_log_file_size = 16M set-variable = innodb_log_buffer_size = 8M innodb_flush_log_at_trx_commit = 1 innodb_log_arch_dir = /disk2/innodb/log 57 innodb_log_archive = 0 set_variable = innodb_buffer_pool_size = 25M set_variable = innodb_additional_mem_pool_size = 5M set_variable = innodb_file_io_threads = 4 set_variable = innodb_lock_wait_timeout = 50 Листинг 6.1. (html, txt) После добавления опций в конфигурационный файл необходимо перезапустить сервер MySQL. Все необходимые файлы будут созданы автоматически. На это может уйти некоторое время, в зависимости от размера файлов и скорости жесткого диска. Таблицы InnoDB блокируются на уровне записей. Это происходит без участия пользователей по мере выполнения инструкций в рамках транзакций. Инструкция LOCK TABLE может конфликтовать с блокировками InnoDB. В отличие от таблиц MyISAM, блокировки таблиц InnoDB способны приводить к возникновению тупиков, т.е. взаимоблокировок. В подобной ситуации одна или несколько транзакций отменяется. Это следует учитывать при написании приложений. Инструкция, которая приводит к автоматической отмене транзакции, возвращает сообщение об ошибке. Транзакции отменяются также в случае нехватки места в файловой системе. На случай отмены транзакций ведется журнал транзакций. Он подвержен внутренней ротации, т.е. когда заполняются все записи, самые старые из них начинают удаляться. На момент создания этого курса существовало несколько ограничений таблиц InnoDB. Самое существенное из них заключалось в способе отслеживания таблиц. В InnoDB ведётся каталог таблиц, который не поддерживается инструкцией DROP TABLE, поэтому каждую таблицу приходится удалять отдельно. Не разрешается индексировать префикс столбца, а также индексировать столбцы типа BLOB и TEXT. Максимальное количество столбцов в таблице — 1000. Флаг DELAYED в инструкции INSERT не поддерживается. ISAM До версии 3.23 стандартным типом таблиц в MySQL был тип ISAM. Он не обладает такими возможностями, как более новый типMyISAM, поэтому в современных версиях MySQL использовать его не рекомендуется. Merge В таблице типа Merge группируется несколько таблиц MyISAM одинаковой структуры. Программа MySQL создает файл с расширением .MRG, в котором содержится список таблиц. При доступе к объединенной таблице программа обращается к каждой таблице из списка. Если в списке всего одна таблица, то создается только ее псевдоним. Если же таблиц две или более, их записи трактуются так, будто они находятся в одной таблице. С функциональной точки зрения объединенная таблица обладает всеми свойствами обычной таблицы. Объединенная таблица создается очень быстро, так как требуется всего лишь сформировать список имен исходных таблиц. В случае уничтожения такой таблицы удаляется лишь MRG-файл, но не исходные таблицы. У объединенных таблиц есть ряд недостатков. В них нельзя вставлять записи, поскольку программа MySQL не имеет возможности определить, в какую из исходных таблиц они должны быть помещены. Кроме того, при работе с такими таблицами задействуется большее число файловых дескрипторов, так как программе приходится открывать каждую исходную таблицу в отдельности. 58 Следовательно, извлечение данных из объединенных таблиц осуществляется медленнее, чем из таблиц других типов. Даже если дескрипторы индексных файлов совместно используются несколькими потоками, все равно приходится читать индексный файл каждой исходной таблицы. Несмотря на упомянутые ограничения, у объединенных таблиц есть и несомненные преимущества. Они позволяют интерпретировать группу таблиц как единое целое и в то же время продолжать работать с отдельными ее компонентами. Это идеальное решение для крупных таблиц, которые легко разбиваются на фрагменты. Например, журнальные файлы Web-сервера можно группировать в месячные таблицы. Если одна из таблиц повреждается, необходимо восстанавливать только ее, а не всю группу. Кроме того, исходные таблицы можно хранить на разных физических дисках, что способствует повышению производительности. MyISAM MyISAM – это стандартный тип таблиц в MySQL, если только в конфигурационном файле не задано иное. Для таблиц этого типа создан ряд специализированных утилит, позволяющих манипулировать табличными файлами. Сюда входят утилита myisamchk для проверки и восстановления таблиц и утилита myisampack для создания сжатых таблиц. Таблицы MylSAM являются платформо-независимыми. Табличные файлы можно перемещать между компьютерами разных архитектур и разными операционными системами без всякого преобразования. Для этого MySQL хранит все числа с плавающей запятой в формате IEEE, а все целые числа — в формате с прямым порядком следования байтов. С точки зрения производительности это совершенно непринципиально. MySQL хранит счетчик подключений к таблице MylSAM. Когда таблица закрывается, счетчик сбрасывается в нуль. Если сервер неожиданно завершает работу, счетчик остается положительным числом. В таком случае в процессе перезапуска сервер обнаружит проблему. Это не означает, что таблица непременно повреждена, но подобная возможность существует. Следует немедленно выполнить инструкцию CHECK TABLE или вызвать утилитуmyisamchk. Можно также запустить демон mysql с опцией –myisam-recover, чтобы заставить его восстанавливать все таблицы MyISAM с ненулевым значением счетчика. Для таблиц MyISAM разрешены одновременные операции вставки и выборки, если только в таблице нет пустых участков. Такие участки создаются инструкциями DELETE и могут быть заполнены последующими инструкциями INSERT. MySQL блокирует таблицу MyISAM, пока инструкция INSERT заполняет пустой участок. Для автоинкрементных столбцов таблиц MyISAM программа MySQL ведет внутренний счетчик, а не просто добавляет единицу к наибольшему значению столбца. Это дает небольшой выигрыш производительности при операциях вставки, но также означает, что значения столбца никогда не используются повторно. В таблицах других типов при удалении строки с наибольшим значением счетчика и последующей вставке новой строки ей будет присвоен тот же самый идентификатор. Индексные файлы имеют расширение .MYI. Файлы с расширением .MYD содержат данные, а с расширением .frm – схему таблицы. Если индексный файл по какой-то причине теряется, программа перестраивает индексы, используя информацию из frm-файла. По умолчанию в каждой таблице может быть не более тридцати двух индексов, но это значение можно повысить до шестидесяти четырех. Индексы создаются в виде двоичных деревьев. Разрешается индексировать столбцы типа BLOB и TEXT, а также столбцы, допускающие значения NULL. 59 В таблицах MyISAM могут быть фиксированные, динамические либо сжатые записи. Выбор между фиксированным и динамическим форматом диктуется определениями столбцов. Для создания сжатых таблиц предназначена утилита myisampack. Таблица будет иметь записи фиксированной длины, если в ней нет столбцов типа VARCHAR, BLOB или TEXT. Одинаковая длина записей имеет свои преимущества. Утилите myisampack будет проще восстанавливать поврежденные записи, если она знает их точную длину. Такие записи никогда не приходится разбивать на части при наличии в таблице пустых промежутков, что ускоряет операции чтения. Правда, записи фиксированной длины обычно занимают больше места на диске. Все записи таблицы будут динамическими, если в ней есть столбцы типа VARCHAR, BLOB или TEXT. Возможно также приведение столбцов типа CHAR к типу VARCHAR, если их длина больше четырех символов. Длина каждой записи отслеживается по специальному заголовку. В нем указана длина текущего сегмента записи. Поскольку при повреждении таблицы связи между фрагментами могут теряться, корректное восстановление записи не всегда возможно. Динамические записи часто требуют дефрагментации. При их удалении возникают пустые участки, которые не всегда в точности заполняются вставляемыми записями. Более того, из-за операций обновления длина записи может увеличиваться или уменьшаться. Если запись не помещается в отведенном для нее месте, она разбивается на два или более сегмента. По мере распределения записей по файлу время поиска данных возрастает. Устранить фрагментацию можно с помощью инструкцииOPTIMIZE TABLES. Сжатые таблицы занимают гораздо меньше места, чем таблицы с фиксированными или динамическими записями. Их удобно создавать в медленных файловых системах, например в тех, которые используются в компакт-дисках. Каждая запись сжимается отдельно с применением отдельной хэш-таблицы для каждого столбца. Сжатая таблица создается утилитой myisampack. С помощью утилиты myisamchk можно преобразовать сжатую таблицу обратно в фиксированный или динамический формат. Если таблица MyISAM находится на переполненном диске и в нее добавляется запись, программа MySQL перейдет в бесконечный цикл, ожидая освобождения места на диске. Столбцы В табл. 6.1 указаны размерности стандартных типов данных MySQL. Значения некоторых типов всегда занимают фиксированный объем памяти. Например, размерность столбцов типа INTEGER всегда составляет 4 байта. Столбцы типа CHAR могут иметь размерность от 0 до 255, но в момент создания таблицы под них отводится фиксированный объем памяти. Существуют также столбцы переменной размерности. Например, столбцы типа VARCHAR и BLOB интерпретируются в соответствии с их содержимым. Тип BIGINT BLOB, TEXT CHAR DATE Таблица 6.1. Размерности стандартных типов данных. Размерность 8 байтов длина содержимого + 2 байта указанное число байтов 3 байта 60 DATETIME DECIMAL (длина, точность) DOUBLE DOUBLE PRECISION ENUM FLOAT FLOAT (длина) INT INTEGER LONGBLOB, LONGTEXT MEDIUMBLOB, MEDIUMTEXT MEDIUMINT NUMERIC (длина, точность) REAL SET SMALLINT TIME TIMESTAMP TINYBLOB, TINYTEXT TINYINT VARCHAR (длина) YEAR 8 байтов длина + 1 байт, если точность равна 0; в противном случае — длина + 2 байта 8 байтов 8 байтов 1 байт, если в перечислении менее 255 элементов; в противном случае — 2 байта 4 байта 4 байта, если длина <= 24; в противном случае — 8 байтов 4 байта 4 байта длина + 2 байта длина + 2 байта 3 байта длина + 1 байт, если точность равна 0; в противном случае – длина + 2 байта 8 байтов 1, 2, 3, 4 или 8 байтов, в зависимости от количества элементов множества 2 байта 3 байта 4 байта длина + 2 байта 1 байт длина содержимого + 1 байт 1 байт Как указывалось выше, таблицы MYISAM содержат записи фиксированной либо переменной длины. Переход во второй режим осуществляется при наличии столбцов переменной размерности. Значения столбцов типа DECIMAL и NUMERIC хранятся в строковом виде, что позволяет обеспечить точность представления десятичных чисел. Каждой цифре соответствует один символ, еще по одному символу отводится на знаковый разряд и десятичную точку. Блокировки таблиц В MySQL разрешается явно блокировать таблицы с помощью инструкции LOCK TABLES. Тем не менее, не рекомендуется делать это для таблиц тех типов, которые поддерживают транзакции. Блокировки и транзакции — это два разных способа решения проблемы одновременного доступа к таблице, поэтому нужно сделать выбор в пользу одного из них. В зависимости от инструкции могут также применяться неявные блокировки. Например, инструкция UPDATE способна немедленно заблокировать таблицу, запретив доступ к ней другим потокам. Блокировки обоих типов защищены от возникновения тупиковых ситуаций, так что можно не волноваться по поводу отмены той или иной инструкции. 61 Можно заблокировать таблицу таким образом, чтобы разрешить другим потокам обращаться к ней для чтения. Это называется блокировкой чтения. Блокировка записи гарантирует текущему потоку монопольный доступ к таблице. Запросы на чтение откладываются до тех пор, пока не будут сняты все блокировки записи. Эту установку можно изменить с помощью флагов инструкций либо путем задания специальных серверных переменных. Для SQL-инструкций создаются две очереди. Чтобы программа MySQL начала извлекать инструкции из очереди на чтение, очередь на запись должна быть пуста. При наличии флагаLOW_PRIORITY инструкции DELETE, INSERT и UPDATE помещаются в очередь на чтение, т.е. они получают такой же приоритет, что и инструкции SELECT. Флаг HIGH_PRIORITY переводит инструкцию SELECT в очередь на запись. Индексы В MySQL индексы хранятся в виде двоичных деревьев. Деревья перестраиваются по мере вставки записей. Это означает, что каждый индекс вызывает небольшое снижение производительности. Как правило, индексы повышают скорость операций выборки за счет снижения скорости операций записи. Тем не менее, наличие индекса еще не гарантирует никакого ускорения. Нужно соотносить их с теми запросами, которые планируется выполнять. Чтобы понять, насколько эффективным окажется тот или иной индекс, пользуйтесь инструкцией EXPLAIN. Определения индексов хранятся в frm-файле а сами индексируемые значения — в файле с расширением .MYI. Если индексный файл отсутствует на момент запуска сервера, он будет автоматически воссоздан. Таким образом, при создании резервных копий можно не заботиться об индексах в целях экономии места. Позднее, в процессе восстановления базы данных, программа MySQL создаст индексы заново на основании схемы таблицы. Индексы способны повысить производительность инструкций, связанных с поиском записей. Они ускоряют процесс сравнения столбцов при выполнении операций объединения. Кроме того, они помогают находить минимальное и максимальное значения столбца и ускоряют выполнение инструкций SELECT с предложением ORDER BY. Чтобы индекс был задействован, он должен быть указан во всех частях предложения WHERE. Если используется лишь часть индекса, то должен соблюдаться порядок обращения к индексируемым столбцам: слева направо. Для примера рассмотрим таблицу, определение которой приведено в листинге 6.2. CREATE TABLE car ( Make CHAR(32) NOT NULL, Model CHAR(32) NOT NULL, Introduced YEAR, PRIMARY KEY (MAKE,Model) ); Листинг 6.2. (html, txt) У таблицы car имеется составной первичный ключ. В запросе, который показан в листинге 6.3, индекс будет использован, так как столбец Make является самым левым компонентом индекса. SELECT * FROM car WHERE Make='Ford'; Листинг 6.3. (html, txt) А вот в следующем запросе (листинг 6.4) этого не произойдет, поскольку правило очередности столбцов не соблюдается. 62 SELECT * FROM car WHERE Model='Pinto'; Листинг 6.4. (html, txt) В листинге 6.5 индекс также не используется, из-за того, что самый левый компонент индекса нельзя применить к каждой записи. Если бы в предложении WHERE стоял оператор AND, а не OR, все было бы наоборот. SELECT * FROM car WHERE Make='Ford' OR Model='Impala'; Листинг 6.5. (html, txt) Следующий запрос (листинг 6.6) является правильным с точки зрения использования индекса. В данном случае просмотр значений столбца осуществляется слева направо. SELECT * FROM car WHERE Make LIKE 'F%'; Листинг 6.6. (html, txt) В листинге 6.7 индекс не используется, потому что просмотр значений столбца осуществляется справа налево (метасимвол % стоит вначале). SELECT * FROM car WHERE Make LIKE '%d'; Листинг 6.7. (html, txt) Дескрипторы файлов Сервер MySQL представляет собой один процесс со множеством потоков. Для каждого сеанса подключения к серверу создается свой поток. Каждому потоку требуется один или несколько дескрипторов файлов, чтобы он мог осуществлять чтение и запись таблиц. Операционная система ограничивает количество файловых дескрипторов, доступных процессу. Это число может быть самым разным. Например, в AIX оно равно 2000 по умолчанию, а в Solaris — всего лишь 64. В Linux лимит по умолчанию составляет 1024 дескриптора. В Windows NT и 2000 видимый предел отсутствует. Чтобы не исчерпать лимит ресурсов, MySQL хранит кэш файловых дескрипторов всех соединений. По умолчанию размер кэша составляет 64 позиции. В случае переполнения кэша MySQL закрывает самый старый дескриптор, освобождая место для нового. В периоды высокой активности пользователей работа программы может замедляться из-за необходимости часто закрывать и открывать файлы. Пока сервер не прекратит работу или буфер не будет принудительно очищен, файловые дескрипторы остаются открытыми. Если активность настолько высока, что все дескрипторы, находящиеся в кэше, открыты, программа временно увеличивает размер кэша. Размер кэша дескрипторов можно задать другим, но не забывайте об ограничении, которое накладывается операционной системой. Правда, ее собственный лимит тоже можно изменить. Для этого существует, например, команда unlimit. Еще один способ — перекомпиляция ядра. Чтобы получить доступ к таблице, поток должен иметь в своем распоряжении дескриптор ее файла данных. Все потоки совместно владеют дескриптором индексного файла. Таким образом, когда три потока одновременно извлекают данные из таблицы, используются четыре дескриптора. Если таблица дважды указана в предложении FROM, например в случае операции самообъединения, программа MySQL вынуждена открывать отдельный дескриптор для каждой ссылки на таблицу. Открытие файла подразумевает его поиск в каталоге, поэтому чем больше файлов в каталоге, тем больше времени уходит на поиск файла. В MySQL таблицы хранятся в виде файлов, следовательно, 63 чем больше таблиц в базе данных, тем дольше открывается новый дескриптор. Эта зависимость ослабевает благодаря кэшу дескрипторов, поскольку дескрипторы долгое время остаются открытыми. Системная память В MySQL специальные буферы и кэши применяются для самых разных целей. Их размеры можно задавать в конфигурационном файле или в командной строке запуска сервера. У каждого потока есть свой стек, буфер приема входных данных от клиента и буфер результатов запроса. Размер стека задается серверной переменной thread_stack, а размеры обоих буферов — переменной net_buffer_length. Последняя определяет начальные размеры буферов, так как они могут увеличиваться в случае необходимости, например, при обработке столбцов типа BLOB или TEXT. Все потоки совместно используют индексный буфер. Его размер определяется переменной key_buffer_size. В операциях объединения, проходящих без участия индексных столбцов, используется отдельный буфер (переменная join_buffer_size), как и в операциях сканирования таблиц (переменная record_buffer). Если для выполнения операции объединения требуется временная таблица, она создается как резидентная (тип Heap). Максимальный размер таких таблиц определяется переменной tmp_table_size. После превышения этого предела таблица преобразуется в формат MyISAM. В любом случае временные таблицы удаляются по окончании операции. 64 ЛЕКЦИЯ 7. Каталог данных MySQL Описание: Лекция рассматривает вопросы управления размещением дискового пространства системы. Концептуальные принципы построения большинства систем управления реляционными базами данных одинаковы: все они состоят из набора баз данных, каждая из которых, в свою очередь, включает набор таблиц. Однако каждая система по-своему организует управляемые данные. Не является исключением в этом отношении и MySQL. По умолчанию вся информация, управляемая сервером mysqld, содержится в так называемом каталоге данных MySQL (MySQL data directory). В нем хранятся все базы данных и файлы состояния с информацией о функционировании сервера. Пользователь, выполняющий функции администратора MySQL, должен знать структуру этого каталога и уметь использовать его в своей повседневной работе. В этой лекции даются исчерпывающие ответы на следующие вопросы. Как определить месторасположение каталога данных. Это необходимо для эффективного управления его содержимым. Как организуется и обеспечивается доступ к базам данных и таблицам сервера. Эта информация необходима для создания расписания операций превентивной поддержки и восстановления поврежденных таблиц после сбоя. Где размещаются сгенерированные сервером файлы состояния и что они содержат. Эти файлы содержат информацию о работе сервера, которая может быть очень полезна для устранения всевозможных проблем. Как изменить месторасположение каталога данных по умолчанию или отдельных баз данных. Знание этих вопросов важно для управления размещением дискового пространства системы. Это может быть необходимо для распределения данных по физическим дискам или перемещения данных в файловых системах с целью освобождения пространства на одном из дисков. Данная информация пригодится и при планировании размещения новых баз данных. Значительную пользу от чтения этой лекции получат даже те пользователи, которые не занимаются администрированием MySQL. Дополнительные знания о принципах работы сервера никогда не будут лишними. Размещение каталога данных По умолчанию местоположение для каталога данных устанавливается при компиляции сервера. Обычно при инсталляции с исходной дистрибуции устанавливается каталог /usr/local/var, при инсталляции из двоичной дистрибуции —/usr/local/mysql/data, а при инсталляции из файла RPM -- /var/lib/mysql. Размещение каталога данных можно задать и явным образом при запуске сервера. Для этих целей применяется опция --datadir= /path/to/dir. Она оказывается весьма кстати, если каталог данных необходимо разместить в месте, отличном от того, которое указывается по умолчанию. Администратор MySQL обязательно должен знать, где находится каталог данных. При запуске нескольких серверов следует записать местоположение всех каталогов данных. Если же размещение каталога неизвестно (например, из-за того, что предыдущий администратор плохо вел свои записи), его можно определить несколькими методами. 65 Воспользоваться командой mysqladmin variables для получения пути к каталогу данных непосредственно с сервера. На компьютере, работающем под управлением ОС UNIX, результат ее ввода будет выглядеть примерно так: % mysqladmin variables +-------------------+-----------------+ | Variable name | Value | +-------------------+-----------------+ | back log | 5 | | connect timeout | 5 | | basedir | /var/local/ | | datadir | /usr/local/var/ | ... Из приведенных выше результатов видно, что каталог данных размещается в каталоге /usr/local/var/ сервера. На компьютере, работающем под управлением ОС Windows, результаты ввода этой же команды будут выглядеть следующим образом. % mysqladmin variables +-------------------+-----------------+ | Variable name | Value | +-------------------+-----------------+ | back log | 5 | | connect timeout | 5 | | basedir | c: \mysql\ | | datadir | c: \mysql\data\ | ... Если на компьютере запущено несколько серверов, каждый из них использует свой порт TCP/IP и разъем. Чтобы получить информацию о каталоге данных от каждого сервера, достаточно подключиться с помощью опций --port и --socket к соответствующему порту и разъему. % mysqladmin --port=port_num variables % mysqladmin --socket=/path/to/socket variables Команду mysqladmin можно запускать на любом компьютере, который подключен к серверу. Для подключения к серверу с удаленного компьютера применяется опция -host=host_name. % mysqladmin --host=host_name variables С компьютера, работающего под ОС Windows, можно подключиться к работающему через именованный канал серверу Windows NT с помощью опции --pipe, активизирующей соединение по именованному каналу, и опции --socket=pipe_name, определяющей имя канала. С:\> mysqladmin --pipe --socket=pipe_name variables 66 Воспользоваться командой ps для вывода командной строки исполняемого процесса mysql. Попробуйте одну из указанных ниже команд (в зависимости от версии ps, поддерживаемой системой) и поищите переменную --datadir в выводимых результатах. % ps axww | grep mysql % ps -ef | grep mysql ps BSD—UNIX ps системы System V Команда ps особенно полезна при запуске на одном компьютере нескольких серверов, поскольку позволяет узнать месторасположение сразу всех каталогов данных. Недостаток этого метода заключается в том, что команду ps обязательно нужно запускать на главном компьютере. Кроме того, она будет бесполезна, если переменная --datadir не описана явным образом в командной строке mysql. Если MySQL инсталлировалась из исходной дистрибуции, месторасположение каталога данных можно получить из информации о конфигурации. Так, например, месторасположение каталога указывается в элементе верхнего уровняMakefile. Однако будьте осторожны, поскольку позиция каталога является в Makefile значением переменнойlocalstatedir, а не datadir, как ожидают многие. Кроме того, если дистрибуция размещается на смонтированной сетевой файловой системе NFS и используется для установки MySQL на несколько компьютеров, в информации конфигурации отражаются данные только для компьютера, на котором система устанавливалась последней. Вполне возможно, что им окажется не тот компьютер, для которого необходимы данные. Если все предыдущие методы вам не подходят, можно воспользоваться командой find для поиска файлов базы данных. Приведенная ниже команда ищет все файлы .frm (описания), являющиеся частью инсталляций MySQL: % find / -name "*.frm" -print Во всех примерах этой лекции в качестве каталога данных MySQL определен каталог datadir. Вполне возможно, что на других компьютерах для этих целей может применяться другой каталог. Структура каталога данных Каталог данных MySQL содержит все управляемые сервером базы данных и таблицы. Они организованы в структуру простого дерева, что позволяет, в свою очередь, воспользоваться преимуществами иерархической структуры файловых систем ОС UNIX и Windows. Каждой базе данных соответствует подкаталог, расположенный внутри каталога данных. Таблицам базы данных соответствуют файлы, размещенные внутри каталога базы данных. Каталог данных содержит также создаваемые сервером файлы состояния, такие, например, как журналы. Они обеспечивают важную информацию о функционировании сервера и просто незаменимы для администратора, особенно когда сервер начинает сбоить и нужно найти источник проблемы. Если неправильно сформированный запрос приводит к сбою в работе сервера, с помощью журналов можно вычислить "виновника". Как обеспечивается доступ к данным сервера MySQL 67 Каждый элемент внутри каталога данных находится под управлением MySQL-сервера mysqld. Клиентские программы никогда не обращаются к данным напрямую. Точку взаимодействия, с помощью которой осуществляется доступ к базам данным, обеспечивает сервер, работающий в качестве промежуточного звена между клиентскими программами и данными (рис. 7.1). Рис. 7.1. Сервер является промежуточным звеном между клиентскими программами и данными В процессе запуска сервер открывает регистрационные файлы (если таковые запрашиваются) и предоставляет сетевой интерфейс к каталогу данных, прослушивая сетевые соединения. Для получения доступа к данным клиентская программа устанавливает соединение с сервером и посылает SQL-запрос на выполнение определенных операций (например, создание таблицы, извлечение или обновление записей). Сервер выполняет все операции и результаты отправляет обратно клиенту. Сервер представляет собой мультипотоковый механизм, поэтому может обслуживать несколько клиентских соединений одновременно. Однако так как две и более операции обновления не могут выполняться в один момент, на практике происходит разделение запросов по наборам, чтобы исключить одновременную попытку двух клиентов изменить одну запись. В обычных условиях использование сервера как единственной точки доступа к базе данных обеспечивает защиту от всякого рода недоразумений, связанных с одновременным доступом нескольких процессов к таблицам базы данных. Администраторы, однако, должны знать, что в некоторых случаях серверы не обладают эксклюзивным контролем над каталогом данных. В одном каталоге данных запущено несколько серверов. Как правило, для управления всеми базами данных используется один сервер, хотя можно запустить сразу несколько серверов. Если это делается для обеспечения доступа к нескольким отдельным каталогам данных, то проблем с взаимодействием различных серверов не возникает. Можно задать нескольким серверам один каталог данных (хотя удачным такое решение назвать сложно). В таком случае необходимо обязательно убедиться, что системы обеспечивают надежную блокировку файлов друг от друга. Иначе серверы начнут взаимодействовать 68 некорректно. Кроме того, при одновременном запуске нескольких серверов в одном каталоге регистрационные файлы будут содержать беспорядочные данные, а не ценную информацию. Запущены утилиты isamchk и myisamchk. Эти утилиты используются для поддержки таблиц, устранения проблем и отладки баз данных. Поскольку они обладают возможностью изменения содержимого таблиц, то могут получать доступ к данным одновременно с сервером. Это может стать источником повреждений данных. Администратор должен понимать, как ограничить подобный совместный доступ, чтобы снизить вероятность разрушения таблиц. Представление баз данных Каждая управляемая сервером MySQL база данных имеет свой собственный каталог. Он представлен в виде подкаталога каталога данных и имеет такое же название, как и собственно база. Так, например, базе данных my_db будет соответствовать каталог базы данных DATADIR/my_db. Такое представление значительно упрощает понимание предназначения и принципов работы некоторых операторов обработки баз данных. Так, оператор create database db_name создает пустой подкаталог db_name в каталоге данных, устанавливая права владения и режим, которые обеспечивают доступ только для пользователя сервера MySQL (UNIX-пользователя, работающего на сервере). Аналогичных результатов создания базы данных пользователь сервера может добиться и вручную, введя следующие команды. % mkdir DATADIR/db_name % chmod 700 DATADIR/db_name сервера MySQL Создает каталог базы данных Делает его доступным только для пользователя Такой подход, заключающийся в создании новой базы данных посредством создания пустого каталога, противоречит принципам, принятым в некоторых других СУБД, которые создают большое количество управляющих и системных файлов даже для "пустой" базы данных. Также легко можно реализовать и команду DROP database. Команда drop database db_name удаляет из каталога данных подкаталог db_name вместе со всеми расположенными в нем файлами. Тех же результатов можно достичь с помощью команды: % rm -rf DATADIR/db_name (Разница между этими двумя командами заключается в том, что сервер удалит лишь файлы, расширение которых отвечает табличным файлам. Если же в каталоге базы данных были созданы также какие-либо другие файлы, они останутся нетронутыми и каталог удален не будет.) Команда show databases на самом деле выводит список названий подкаталогов каталога данных. Некоторые системы управления базами данных поддерживают специальную таблицу со списком всех баз данных. В MySQL такой таблицы нет. Благодаря простоте структуры список баз является списком подкаталогов каталога данных. Следовательно, и необходимость в подобной таблице отсутствует. Представление таблиц баз данных Каждая таблица представлена в каталоге базы данных в виде трех файлов: файла формы (описания), файла данных и файла индексов. Основное имя файла соответствует названию таблицы, а его расширение отражает тип файла. Краткое описание расширений представлено в табл. 7.1. По расширениям файлов данных и индексов можно определить, используется ли в таблице старый формат ISAM или новый MyISAM. 69 Таблица 7.1. Типы файлов MySQL Расширение имение Тип файла файла frm Файл формы Содержимое файла Описывает структуру таблицы (столбцы, типы столбцов, индексы и т.п.) Файл данных ISD (ISAM)или MYD (MyISAM) Содержит данные таблицы, т.е. его строки Файл индексов ISM (ISAM)или MYI (MyISAM) Содержит дерево индексов для каждого файла данных. Этот файл существует независимо от того, имеются в таблице индексы или нет При выполнении оператора CREATE TABLE tblname, определяющего структуру таблицы, сервер создает файл tblname.frm с внутренней кодировкой структуры. Кроме того, создаются также файлы данных и индексов с информацией об отсутствии записей и индексов. (Если оператор create table включает спецификации индексов, в файле индексов они отражаются соответствующим образом.) Параметры владельца и режима файлов таблицы устанавливаются такими, чтобы обеспечить доступ только пользователю сервера MySQL. При исполнении оператора alter table расшифровывает файл tbl_name.frm и изменяет файлы данных и индексов с учетом определенных оператором структурных изменений. Такие же операции имеют место и при выполнении операторов create indexи drop index, поскольку они рассматриваются сервером как эквивалентные оператору ALTER table. В процессе выполнения оператора drop table из каталога базы данных удаляются все три представляющих таблицу файла. Пользователь не может вручную создать или изменить таблицу, хотя имеется возможность удалить ее — для этого достаточно удалить три соответствующих файла. Так, например, эквивалентом оператора drop table my_tbl для текущей базы данныхmy_tbl может быть команда: % rm -f DATADIR/my_db/my_tbl. * Вывод оператора SHOW tables mydb представляет собой простой список имен (без расширений) FRM-файлов каталога базы данных my_db. Как уже отмечалось ранее, некоторые СУБД поддерживают специальный реестр со списком всех таблиц баз данных. В MySQL такой реестр не нужен, поскольку список таблиц легко определяется благодаря структуре каталога данных. Ограничения операционной системы на имена баз данных и таблиц В MySQL устанавливается несколько основных правил присвоения имен базам данных и таблицам. Имена могут включать буквы и цифры текущего набора символов, а также символы подчеркивания и доллара ("_" и "$"). Длина имен не может превышать 64 символа. Однако так как именам баз данных и таблиц соответствуют названия каталогов и файлов, операционная система, под управлением которой работает сервер, может накладывать дополнительные ограничения. Во-первых, в именах баз данных и таблиц можно использовать только разрешенные для имен файлов символы. Так, например, символ "$" разрешается правилами MySQL, однако в некоторых операционных системах его нельзя применять в именах файлов. Такого рода ограничения 70 отсутствует в ОС UNIX и Windows. Наиболее значительные проблемы могут возникнуть в момент ссылки на имена баз данных при выполнении задач администрирования непосредственно из оболочки. Предположим, например, что база данных имеет имя $my_db. В этом случае всякая ссылка на имя базы может интерпретироваться как ссылка на переменную: % Is $my_db my_db: Undefined variable. Чтобы избежать возможных недоразумений, нужно либо вообще избегать использования символа "$", либо использовать кавычки, подтверждая его специальное значение: % Is my_db % Is '$my_db' Необходимо использовать одинарные кавычки, поскольку двойные кавычки не отражают специального значения символов имени. Во-вторых, несмотря на то, что MySQL разрешает задавать для баз данных и таблиц имена длиной до 64 символов, на самом деле их длина ограничивается максимально возможной длиной имен файлов. В большинстве случаев эта проблема как таковая отсутствует, хотя в некоторых UNIX-системах System V все еще существует старое ограничение в 14 символов. В таком случае имя таблицы должно содержать не более 10 символов, поскольку четыре остальных позиции отводится под точку и трехсимвольное расширение. В-третьих, на присвоение имен базам данных и таблицам оказывает влияние также чувствительность используемой файловой системы к регистру символов. Если буквы нижнего и верхнего регистров операционной системой воспринимаются по-разному (как, например, в ОС UNIX), имена my_tbl и My_tbl будут указывать на разные таблицы. Если же регистр не играет никакой роли (как, например, в Windows), my_tbl и My_tbl окажутся разными названиями одной и той же таблицы. Об этом следует помнить при разработке базы данных, которую впоследствии планируется перенести на другую платформу. Влияние структуры каталога данных на производительность системы Построение структуры каталогов данных на основании иерархической структуры файловой системы делает структуру каталога данных понятной для пользователей. В то же время, эта структура оказывает определенное влияние на производительность системы. Особенно это справедливо в отношении операций открытия файлов таблиц баз данных. Поскольку в структуре каталога данных таблица представляется несколькими файлами, для открытия каждой таблицы требуется не один, а сразу несколько дескрипторов файлов. Сервер весьма эффективно кэширует дескрипторы, однако загруженному серверу для обслуживания множества одновременных клиентских соединений и обработки сложных запросов к нескольким таблицам потребуется большое количество дескрипторов. Дескрипторы файлов — весьма ограниченный ресурс во многих системах, особенно в тех из них, в которых по умолчанию установлен низкий лимит. В лекции 2, "Общее администрирование MySQL", рассказывалось, как рассчитывать необходимое число дескрипторов и настроить конфигурацию сервера или операционной системы. Еще один негативный момент, связанный с представлением одной таблицы в виде нескольких файлов, заключается в том, что с увеличением таблиц увеличивается и время их открытия. Операции открытия таблиц целиком и полностью базируются на системных операциях открытия файлов, а следовательно, зависят от эффективности работы механизмов поиска файлов операционной системы. Как правило, эта проблема несущественна, хотя о ней все же стоит помнить при создании базы данных с большим количеством таблиц. 71 Так, например, каталог базы данных, включающей 10000 таблиц, содержит 30000 файлов. При открытии большого количества таблиц замедление выполнения операций открытия становится достаточно заметным. (Особенно это относится к файловым системам Linux ext2 и Solaris.) Если же эта проблема приобретает действительно угрожающие масштабы, возможно, имеет смысл пересмотреть структуру своих таблиц в соответствии со спецификой работы приложений и соответствующим образом их реорганизовать. Тщательно подумайте, действительно ли необходимо такое большое число таблиц. Иногда приложения генерируют их безо всякой на то необходимости. Много таблиц с аналогичными структурами могут генерироваться приложениями, которые создают отдельную таблицу для каждого пользователя. Чтобы объединить такие таблицы в одну, достаточно добавить столбец, который идентифицирует пользователя владельца строки. Если в результате таких действий число таблиц значительно уменьшится, производительность приложения возрастет. Всегда при проектировании базы данных следует анализировать, подходит ли для данного приложения та или иная стратегия. Однако существуют также причины, не позволяющие объединять таблицы описанным выше способом. Основными среди них являются следующие. Ограничение дискового пространства. Объединение таблиц приводит к уменьшению их числа (уменьшая, в свою очередь, время открытия), но сопровождается добавлением дополнительных столбцов (занимая дополнительное дисковое пространство). В результате складывается достаточно распространенный компромисс между временем обработки и свободным пространством, и администратор должен решить, какой фактор более важен. Если на первом плане стоит скорость, возможно, придется пожертвовать дополнительным дисковым пространством. Если же объемы дисков сильно ограничены, придется использовать большее количество таблиц и немного дольше ждать при открытии. Вопросы безопасности. Эта причина также может в значительной степени ограничить возможности и желание объединить таблицы. Основная цель использования отдельных таблиц для каждого пользователя — открытие доступа к данным таблицы только пользователям, обладающим соответствующими привилегиями. На самом деле права пользователей определяются полномочиями на уровне таблицы. После объединения данные всех пользователей окажутся в одной таблице. Возможности MySQL не позволяют ограничить для определенного пользователя доступ к определенным строкам таблиц. Соответственно, нельзя объединить таблицы, не потеряв контроля над доступом. Однако если доступ к данным контролируется приложением (пользователи не подключаются непосредственно к базе данных), можно спокойно объединить таблицы и для определения прав доступа воспользоваться соответствующими средствами приложения. MySQL накладывает внутреннее ограничение на размеры таблицы, однако, поскольку таблицы представляются в виде файлов, учитывать следует также и максимальный размер файла, разрешаемый операционной системой. Другими словами, максимально возможный размер таблицы определяется наиболее жестким ограничением среди ограничений MySQL и операционной системы. В последнее время намечается тенденция к ослаблению ограничений на размеры таблиц. Так, например, если в ОС IBM AIX 4.1 существовало ограничение на размер файла 2 Гбайта, то в ОС IBM AIX 4.2 оно увеличилось до приблизительно 64 Гбайт. Внутренний лимит на размер таблицы в MySQL в новых версиях также увеличивается. Так, если во всех предшествующих версии 3.23 системах он составляет 4 Гбайта, то в 3.23 был поднят до приблизительно 9 миллионов терабайт. Данные табл. 7.2позволяют оценить, как внутренний лимит на размер таблицы в MySQL сопоставляется с ограничением файловой системы AIX. Подобные сопоставления можно применять и для других операционных систем. Таблица 7.2. Сопоставление ограничений MySQL и операционной системы Версия MySQL Версия AIX Максимальный размер таблицы Ограничивающий фактор 72 MySQL 3 22 22 AIX 4 1 2 Гбайт Максимальный размер файла AIX 2 Гбайта MySQL 3 22 22 AIX 4 2 4 Гбайт Максимальный размер таблицы MySQL — 4 Гбайта MySQL 3 23 AIX 4.1 2 Гбайт Максимальный размер файла AIX 2 Гбайта MySQL 3 23 11 AIX 4 2 64 Гбайт Максимальный размер таблицы MySQL — 64 Гбайта Файлы состояния MySQL Помимо подкаталогов баз данных, каталог данных MySQL содержит множество файлов состояния. Краткий обзор этих файлов представлен в табл. 7.3, а детальное их описание следует далее. По умолчанию основная часть имени этих файлов содержит имя главного компьютера. В таблице это имя заменено словом HOSTNAME. Сервер записывает ID-номер своего процесса (Process ID — PID) в PID- файл при запуске и удаляет этот файл при завершении работы. Именно с помощью PID-файла сервер позволяет находить себя работающим процессам. Так, например, если во время завершения работы системы запустить сценарий mysql.server для завершения работы и сервера MySQL, данный сценарий обратится к PID-файлу. Это обращение позволит определить, какому процессу отправить команду на завершение работы. Таблица 7.3. Имя по Тип файла Содержимое файла умолчанию ID-номер процесса HOSTNAME, pid ID-номер процесса сервера HOSTNAME, err События запуска и завершения работы, а также записи об Журнал ошибок ошибках HOSTNAME, log События подключения /отключения и информация о Общий журнал запросах HOSTNAME, nnn Текст всех запросов, изменяющих содержимое или структуру Журнал обновлений таблицы Журнал ошибок создается сценарием safe_mysqld. Впоследствии именно в этот журнал перенаправляются все стандартные сообщения об ошибках сервера. Другими словами, журнал содержит все сообщения, записываемые сервером в stderr, и существует, только если сервер запускается с помощью вызова сценария safe_mysqld. (Это более предпочтительный метод запуска сервера, поскольку safe_mysqld перезапускает сервер при сбое в работе из-за ошибки.) Общий журнал и журнал обновления являются необязательными. Используя опции --log и -log-update, можно задать регистрацию только необходимой информации. Общий журнал предоставляет информацию о функционировании сервера: кто и с какого компьютера подключился и какие запросы присылает. Журнал обновлений также содержит информацию о запросах, однако только о тех из них, которые связаны с изменением содержимого баз данных. Содержимое же журнала обновлений представляется в виде операторов SQL. Впоследствии их можно выполнить, представив в виде ввода для клиента mysql. Журналы обновлений оказываются особенно полезными в случае сбоя, когда необходимо отследить все изменения, внесенные с момента последнего резервирования базы данных. Их использование позволяет восстановить базы данных до состояния, в котором они находились перед самым сбоем. 73 Ниже представлены данные, которые заносятся в общий журнал в течение короткой клиентской сессии. На протяжении работы клиент создает таблицу в базе данных test, вставляет в нее строку и затем удаляет всю таблицу. 990509 7:34:09 990509 990509 990509 990509 7:34:22 7:34:34 7:34:38 7:34:40 492 Connect 492 Query 492 Query 492 Field List 492 Field List 492 Query 492 Query 492 Query 492 Quit paul@localhost on test show databases show tables tbl_l tbl 2 CREATE TABLE my_tbl (val INT) INSERT INTO my_tbl VALUE(A) DROP TABLE my tbl Отдельные столбцы общего журнала отражают дату и время события, ID-номер сервера, тип события и относящуюся к нему специальную информацию Тот же сеанс в журнале обновлений отобразится следующим образом: use test; CREATE TABLE my_tbl (val INT); INSERT INTO my_tbl VALUE(A); DROP TABLE my_tbl; Для получения расширенной формы журнала обновлений используется опция --log-longformat. В расширенном журнале предоставляется информация также об отправителе и времени поступления запроса. Эти данные занимают, конечно, больше места на диске, однако позволяют узнать, кто и что пытался сделать. Сопоставлять информацию о событиях в общем журнале и журнале обновлений для этого не нужно. Для уже описанной выше сессии расширенный журнал обновлений будет выглядеть таким образом: # Time: 9905097:43:42 # User@Host: paul [paul] @ localhost [] use test; CREATE TABLE my_tbl (val INT); # User@Host: paul [paul] @ localhost {] INSERT INTO my_tbl VALUE(A); # Time: 9905097:43:43 # User@Host: paul [paul] 0 localhost П DROP TABLE my_tbl; Администратору настоятельно рекомендуется убедиться, что файлы журналов защищены от просмотра случайными пользователями. Как общий журнал, так и журнал обновлений могут содержать такую критически важную информацию, как пароли: ведь они включают текст отправляемых запросов. Ниже представлен пример одной записи журнала, которую вряд ли даже начинающий администратор захочет показать другому пользователю, поскольку она содержит пароль пользователя. 990509 7:47:24 4 Query UPDATE user SET Password=PASSWORD("secret") WHERE user="root" Детально о проверке и настройке полномочий на доступ к каталогу данных рассказывается в лекции 11, "Безопасность". Для защиты каталога данных можно воспользоваться простой командой: % chmod 700 DATADIR Запустите эту команду, зарегистрировавшись в качестве пользователя-владельца каталога данных. Не забудьте также зарегистрироваться под именем этого пользователя на сервере, иначе команда не только запретит другим пользователям доступ к каталогу данных (что и 74 требуется), но также закроет базы данных для сервера (чего допустить ни в коем случае нельзя). Файлы состояния размещаются на верхнем уровне каталога данных вместе с каталогами баз данных. Поэтому иногда пользователи беспокоятся, что имена файлов состояния могут конфликтовать с именами баз данных (например, при выполнении сервером оператора SHOW databases). Этого бояться не стоит. Информация о событиях и состояниях хранится в файлах, а базы данных записаны в каталогах, что позволяет исполняемым программам легко отличить их, вызвав команду stat(). (Именно таким образом их различает сервер.) Просматривая каталог данных с помощью опции ls -1, пользователь может отличить файлы состояния от каталогов баз данных, определив первую букву данных в режиме: ' - ' или ' d': % ls –l DATADIR total 31 drwxrwx-- 1 mysqladm drwxrwx-- 2 mysqladm -rw-rw--- 1 mysqladm -rw-rw-r- 1 mysqladm -rw-rw--- 1 mysqladm -rw-rw-r- 1 mysqladm drwxrwx-- 7 mysqladm drwxrwx-- 2 mysqladm mysqlgrp 1024 May 8 13:22 mysqlgrp 1024 Dec 15 22:34 mysqlgrp 64 May 9 20:11 mysqlgrp 24168 May 9 20:11 mysqlgrp 4376 May 9 20:11 mysqlgrp 5 May 9 20:11 mysqlgrp 512 Sep 10 1998 mysqlgrp 512 May 9 07:34 blgdb mysql pit-vlper. pit-vlper. pit-vlper. pit-vlper. sql-bench test 001 err log pld Можно также просто просмотреть список имен, ведь имена всех файлов состояния включают точку, а в именах баз данных она не используется (более того, запрещена). Более детально о поддержке файлов регистрации и способах работы с ними рассказывалось в лекции 2 "Общее администрирование MySQL". Перемещение содержимого каталога данных В предыдущем разделе описывалась структура каталога данных, создаваемая сервером по умолчанию. Этот каталог содержит все рабочие базы данных и файлы состояния. Иногда возникает необходимость в определении специального места для хранения содержимого каталога данных. В этой части лекции рассказывается, зачем может потребоваться перемещать отдельные части каталога данных (и даже сам каталог), какие его компоненты можно перемещать и как такое перемещение осуществить. Возможности MySQL позволяют администратору перемещать каталог данных или его внутренние элементы на другое место. Необходимость в этом может быть вызвана следующими причинами. Каталог данных можно разместить на диске большего размера, чем используется в настоящий момент. Если каталог данных располагается на часто используемом диске, перемещение его на другой диск позволит уровнять загрузку среди физических дисков. В этом случае можно разместить файлы баз данных и журналов на отдельном диске или распределить их по нескольким дискам сразу. Каждый из одновременно запущенных серверов можно разместить в своем каталоге данных. Такой подход является одним из способов обойти ограничения на файловые дескрипторы, особенно если эти ограничения нельзя устранить посредством настройки ядра системы. Некоторые операционные системы хранят PID-файлы сервера в отдельном каталоге, например /var/run. Возможно, для большей согласованности работы системы администратор пожелает разместить в этой папке и PID-файлы MySQL. Методы перемещения 75 Существует два способа перемещения компонентов каталога данных. Определение опции загрузки сервера с помощью командной строки или в группе [mysqld] конфигурационного файла. Перемещение элементов и создание в исходном каталоге символической связи (symbolic link), указывающей на новое местоположение. Ни один из приведенных методов не является универсальным для переноса информации. В табл. 7.4 отмечается, какие компоненты каталога данных можно перемещать и какой метод следует для этого использовать. Если применяется первый метод, можно задать опции в глобальном конфигурационном файле /etc/my.cnf (C:\my.cnf на компьютерах, работающих под управлением ОС Windows). В последних версиях ОС Windows этот файл может располагаться в системной папке (С:\Windows). Таблица 7.4. Обзор методов перемещения Перемещаемый компонент Целый каталог данных Применяемый метод перемещения Опция запуска или символическая связь Каталоги отдельных баз данных Символическая связь Отдельные таблицы баз данных Символическая связь PID-файл Опция запуска Файл общего журнала Опция запуска Файл журнала обновлений Опция запуска Для перемещения можно также применить файл my.cnf, расположенный в каталоге данных по умолчанию, однако делать это не рекомендуется. Если ваша цель — переместить весь каталог данных, необходимо оставить этот каталог нетронутым на старой позиции, чтобы разместить в нем конфигурационный файл со ссылкой на "реальный" каталог данных. Это может привести к путанице. Для определения опций сервера лучше воспользоваться конфигурационным файлом /etc/my.cnf. Определение эффекта перемещения Прежде чем приступать к перемещению каких-либо компонентов, настоятельно рекомендуется убедиться, что эта операция приведет к желаемому эффекту. Для получения информации о пространстве диска некоторые пользователи предпочитают использовать команды du, df и Is I, хотя этот выбор, в первую очередь, определяется правильным пониманием структуры используемой файловой системы. В приведенном ниже примере существует едва заметная ловушка, в которую можно попасться при перемещении каталога данных. Предположим, что каталог данных/usr/local/var планируется переместить в каталог /var/mysql, поскольку согласно выводу команды df файловая система /var содержит больше свободного пространства. % df /usr/var Filesystem 1k-blocks /dev/wd0s3e 396895 /dev/wd0s3f 1189359 Used 292126 1111924 Avail 73018 162287 Capacity 80% 15% Mounted on /usr /var Сколько же пространства освободится в файловой системе /usr в результате перемещения каталога данных? Чтобы вычислить этот объем, воспользуемся командой du -s и посмотрим, сколько этот каталог занимает: % cd /usr/local/var % du -s 133426 76 Как видно, этот каталог занимает чуть более 130 Мбайт, которые можно освободить в /usr. Однако можно ли этот прием реализовать на самом деле? Запустите команду df в каталоге данных: % df /usr/local/var Filesystem 1k-blocks /dev/wd0s3f 1189359 Used 1111924 Avail 162287 Capacity 15% Mounted on /var Что же получается? При запросе объема свободного пространства в файловой системе, содержащей каталог /usr/local/var, команда df отображает свободный объем в /var. Почему так? Ответ на этот вопрос дает команда Is -1: % is -l /usr/local lrwxrwxr 1 root wheel 10 Dec 11 23:46 var -> /var/mysql Из результатов выполнения этой команды видно, что /usr/local/var является символической связью с /var/mysql. Другими словами, каталог данных уже перемещен в файловую систему /var и включает указывающую на нее символическую связь. Соответственно, никакой выгоды перемещение каталога данных из /usr в /var не принесет. Суть этого примера состоит в том, что несколько действий по определению эффекта перемещения могут показать нецелесообразность подобного перемещения. Такая предосторожность позволяет вовремя остановиться и не тратить уйму времени на перемещение только для того, чтобы затем понять, что достичь нужной цели невозможно. Перемещение каталога данных Для перемещения каталога данных необходимо завершить работу сервера и только после этого перенести каталог на новую позицию. Затем необходимо удалить данные исходного каталога и заменить его символической связью, указывающей на новую позицию, либо перезапустить сервер с опцией, определяющей новое местоположение. Синтаксис командной строки и конфигурационного файла представлен в табл. 7.5. Таблица 7.5. Синтаксис перемещения каталога данных Метод Командная строка Синтаксис --datadir=/path/to/dir Конфигурационный файл опций [mysqld] datadir=/path/to/dir Перемещение баз данных Базы данных можно перемещать только с помощью метода символической связи. Для этого необходимо завершить работу сервера, перенести каталог базы данных, затем удалить этот каталог и заменить его символической связью, указывающей на новую позицию. После этого можно перезапустить сервер. Так, например, перемещение базы данных bigdb на другое место выполняется с помощью следующих команд. % mysqladmin -u root -p shutdown Enter password: ******** % cd DATADIR % tar cf - bigdb | (cd /var/db; tar xf -) % mv bigdb bigdb.orig % ln -s /var/db/bigdb . % safe_mysqld & 77 Меры предосторожности при перемещении Необходимо завершить работу сервера перед выполнением операции перемещения и запустить его снова впоследствии. При перемещении некоторых компонентов (например, каталога базы данных) можно, хотя и не рекомендуется, оставить сервер в рабочем состоянии. В этом случае следует убедиться, что сервер не обращается к перемещаемой базе данных. Не забудьте также выполнить оператор flush tables перед перемещением базы данных, чтобы сервер закрыл все открытые файлы таблиц. Игнорирование этих моментов может привести к повреждению таблиц. Для выполнения всех этих команд необходимо зарегистрироваться в качестве владельца каталога данных. Как видите, исходный каталог данных переименовывается для безопасности в bigdb.orig. После проверки правильности работы сервера с перемещенной базой данных его можно удалить: % rm -rf bigdb.orig Перемещение таблиц баз данных Перемещение отдельных таблиц баз данных — далеко не самая лучшая идея. В случае необходимости эту операцию можно реализовать посредством переноса файлов таблиц на новую позицию и установки символических связей в исходном каталоге данных, указывающих на новое местоположение. Однако если впоследствии выполнить операторы alter table или optimize table, изменения внесены не будут. В процессе выполнения каждого такого оператора в каталоге базы данных сначала создается временная таблица, которая и поддается изменению или оптимизации. Сразу после этого исходная таблица удаляется, а ее имя присваивается временной таблице. В результате этой процедуры символические связи будут удалены, а новая измененная таблица окажется записанной в том же каталоге данных, откуда ранее была перемещена исходная таблица. В конечном итоге, старые перемещенные ранее файлы таблиц оказываются на новой позиции. В большинстве случаев пользователи о них забывают, что способствует неэффективному использованию дискового пространства. Кроме того, в процессе изменения удаляются символические связи, из-за чего впоследствии оказывается довольно трудно вспомнить, куда были перемещены файлы таблиц. Поскольку практически невозможно гарантировать, что обладающие соответствующими полномочиями пользователи не будут пытаться изменить или оптимизировать таблицы (таким образом, сводя на нет все усилия по их перемещению), лучше оставить файлы таблиц размещенными в каталоге базы данных. Перемещение файлов состояния Перемещение PlD-файла, общего журнала и журнала обновлений осуществляется с помощью символических связей. Как уже отмечалось ранее, журнал ошибок создается сценарием safemysqld и поэтому не может перемещаться куда-либо (если, конечно, для этого не прибегнуть к редактированию safemysqld). Для записи файла состояния в новую позицию завершите работу сервера и перезапустите его, точно определив посредством соответствующей опции новое местоположение. Синтаксис командной строки и файла опций для каждого файла состояния представлен в табл. 7.6. Таблица 7.6. Синтаксис перемещения файлов состояния Метод Командная строка Синтаксис -pid-file=pidfile -log=logfile -log-update=updatefile 78 Файл опций [mysqld] pid-file=pidfilee log=logfile log-update=updatefile Удаление перемещенной базы данных Удалить базу данных можно с помощью оператора drop database, хотя в старых версиях MySQL с удалением перемещенной базы данных могут возникнуть проблемы. Таблицы такой базы данных будут удалены правильно. Ошибка возникает при попытке сервера удалить каталог базы данных поскольку он является лишь символической связью, а не реальным каталогом. Администратор MySQL должен самостоятельно удалить каталог базы данных и указывающую на него связь. Эта проблема устранена в MySQL версии 3 23 и выше. Если определить имя файла состояния, указав полный путь, то файл будет создан в определенной этим путем позиции. Во всех остальных случаях файл создается в каталоге данных. Так, например, при определении опции --pid-file=/var/run/mysqld.pidPIDфайл mysqld.pid будет создан в каталоге /var/run. Если же определена опция --pidfile=mysqld.pid, этим файлом окажется файл DATADIR/mysqld.pid. При определении имени журнала обновлений без расширения MySQL будет создавать последовательные имена каждый раз при открытии этого журнала. Эти имена будут дополняться расширением nnn, где nnn — следующий не используемый существующим файлом журнала обновлений номер (например, update.001, update.002 и тп). Чтобы избежать создания подобных имен сервером, достаточно определить имя с явным расширением. 79 ЛЕКЦИЯ 8. Файлы журналов MySQL Описание: В этой лекции рассматриваются вопросы аудита работы системы MySql. В MySQL имеется несколько журналов, позволяющих узнать, что происходит внутри mysqld: Журнал Описание Журнал ошибок В нем хранятся ошибки запуска, работы или завершения работыmysqld Журнал isam В нем хранится информация обо всех изменениях таблиц ISAM. Используется только при отладке кода isam Общий журнал запросов В нем хранится информация об установленных соединениях и выполненных запросах Журнал обновлений log В нем хранятся все команды, меняющие данные; в скором времени выйдет из употребления Бинарный журнал В нем хранятся все меняющие что-либо команды. Используется для обновлений репликации Журнал медленных запросов В нем хранятся все запросы, на выполнение которых ушло больше времени, чем указано в переменнойlong_query_time (или запросы, не использовавшие индексов) Все файлы журналов хранятся в каталоге с данными mysqld. С помощью команды FLUSH LOGS можно заставить mysqld открыть файлы журналов снова (или — в некоторых случаях — переключиться на новый файл). Журнал ошибок Журнал ошибок содержит информацию о том, когда запускается и останавливается mysqld, а также все критические ошибки, обнаруженные в процессе работы. В нем содержится информация о запуске и завершении работы mysqld, а также обо всех серьезных ошибках, возникших во время работы. Если произойдет неожиданное аварийное завершение работы и safe_mysqld придется перезапустить mysqld,safe_mysqld внесет в этот файл соответствующую запись. Кроме того, в этот журнал заносится предупреждение в том случае, если mysqld обнаружит таблицу, нуждающуюся в автоматической проверке или исправлении. Все ошибки mysqld записывает в stderr, который сценарий safe_mysqld перенаправляет в файл с именем 'hostname'.err (в Windows mysqld сохраняет его в каталоге \mysql\data\mysql.err). В некоторых ОС в журнал включается распечатка части стека погибшего mysqld. С помощью этой информации можно определить причину сбоя. Начиная с 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. 80 Если вы не указываете -log-error или используете опцию -console, то ошибки будут выводиться на stderr (на терминал). В Windows вывод всегда пишется в .err-файл, если -console не была указана. Общий журнал запросов Если вы хотите знать обо всем, что происходит с mysqld, нужно запустить систему с ключом log[=file]. После этого информация обо всех соединениях и запросах будет записываться в файл журнала (по умолчанию ему дается имя'hostname'.log). Этот журнал может оказаться полезным, если вы подозреваете наличие ошибки в клиентском ПО и хотите выяснить, что, по мнению mysqld, клиент передал базе. Старые версии скрипта mysql.server (с MySQL 3.23.4 по 3.23.8) передавали safe_mysqld опцию -log (включить общий журнал запросов). Если вам нужна большая производительность при запуске MySQL в промышленной эксплуатации, вы можете удалить опцию -log из mysql.server или поменять ее на -log-bin.. Записи в журнал заносятся по мере получения mysqld запросов. Порядок их занесения может быть иным, чем порядок выполнения команд. В этом и заключается основное отличие данного журнала от журналов обновлений и бинарных журналов, в которые информация заносится по мере выполнения запросов, но до отмены блокировок. Журнал обновлений (update) Обратите внимание: журнал обновлений (update) применялся в старых версиях и сейчас заменен бинарным журналом (binary). С этим журналом можно производить те же операции, что и с журналом обновлений. При запуске с ключом -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, присваивающие столбцам те же значения, которые у них были до "обновления". 81 Запись в журнал осуществляется сразу по завершении работы запроса, но до того, как будут сняты блокировки. Таким образом обеспечивается уверенность в том, что журнал ведется именно в порядке выполнения запросов. При желании обновить базу в соответствии с данными журналов обновлений можно воспользоваться следующей командой (при условии, что имена файлов журналов соответствуют форме file_name.###): shell> ls -l -t -r file_name.[0-9]* | xargs cat | mysql ls расставляет все файлы журналов в правильном порядке. Эта возможность может пригодиться в случае, если возникнет необходимость (в результате серьезного сбоя) привести базу в соответствие с резервной копией и затем повторить все обновления, произошедшие с момента создания копии и до сбоя. Бинарный журнал обновлений Бинарный журнал содержит всю информацию, имеющуюся в журнале обновлений, в более эффективном формате. В нем имеется информация и о времени выполнения каждого обновляющего базу запроса. В нем не содержится информации о запросах, которые не изменяют данные. Если вам нужно журналировать все запросы (например для выявления проблемного запроса), следует использовать общий журнал запросов. Бинарный журнал применяется и при репликации подчиненного сервера (slave) с головного (master). При запуске с ключом -log-bin[=file_name] mysqld создает файл журнала, в который вносятся данные обо всех обновляющих данные командах SQL. Если имя файла не задано, по умолчанию ему дается имя хоста с окончанием -bin. Если файлу присвоено имя, не содержащее пути доступа к нему, этот файл сохраняется в каталоге данных. При вводе расширения в имя файла (например: -log-bin=filename.extension) это расширение удаляется без предупреждения. К имени файла бинарного журнала программа mysqld прибавляет специальное расширение — номер, увеличивающийся при каждом выполнении команд mysqladmin refresh, mysqladmin flushlogs, FLUSH LOGS или перезапуске сервера. При достижении файлом журнала максимального размера, заданного в параметре max_binlog_size, автоматически создается новый. Все неактивные файлы бинарных журналов можно удалить командой RESET MASTER. На выбор данных, записываемых в журнал, влияют следующие настройки mysqld: Опция Описание binlog-dodb=database_name Указывает головному серверу что он должен журналировать обновления в двоичный журнал если текущая (т.е. выбранная) база данных — это 'database_name'. Остальные базы данных, особо не отмеченные, игнорируются. Имейте в виду, что если вы используете эту опцию, то вам следует делать обновления только в этой базе данных. (пример: binlog-do-db=some_database) binlog-ignoredb=database_name 82 Заставляет отказаться от занесения в журнал обновлений определенной базы данных (пример: 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 для резервного копирования нужно использовать бинарный журнал, а не старый журнал обновлений. Занесение данных в бинарный журнал происходит сразу по завершении исполнения запроса, но до снятия блокировок. Таким образом обеспечивается уверенность в том, что журнал ведется именно в порядке выполнения запросов. Обновления нетранзакционных таблиц сохраняются в двоичном журнале немедленно после выполнения. Все обновления (UPDATE, DELETE или INSERT), изменяющие данные в транзакционных таблицах (например, BDB-таблицу), находятся в кэше до вызова COMMIT. В этот момент mysqld пишет всю транзакцию целиком в двоичный журнал перед тем, как выполнить COMMIT. Каждый поток при запуске будет создавать буфер размером binlog_cache_size для буферизации запросов. Если запрос превышает этот размер, тогда поток откроет временный файл для сохранения транзакции. Временный файл будет удален при выходе потока. При запуске каждого потока создается буфер запросов, объем которого соответствует значению параметра binlog_cache_size. Если запрос не помещается в буфере, поток создаст временный файл для кэша. Временный файл удаляется по завершении работы потока. Параметр max_binlog_cache_size (по умолчанию 4Гб) позволяет ограничить общий объем памяти, используемой для кэширования мультитранзакционного запроса. Если транзакция больше этого — будет произведен откат. При использовании журнала обновлений или бинарного журнала параллельные операции вставки будут преобразованы в нормальные операции вставки в командах CREATE ... SELECT и INSERT ... SELECT. Это сделано специально — для того, чтобы обеспечить возможность создания точной копии таблиц путем объединения резервной копии с журналом. Журнал медленных запросов 83 При запуске с параметром -log-slow-queries[=file_name] mysqld создает файл журнала, в котором сохраняются данные обо всех командах SQL, на выполнение которых ушло больше времени, чем указано в значении параметра long_query_time. Время, уходящее на первоначальную блокировку таблиц, не входит во время исполнения запроса. Занесение данных в журнал происходит сразу по завершении исполнения запроса и снятия блокировок. Таким образом, порядок расположения записей может отличаться от порядка выполнения запросов. Если имя файла не задано, по умолчанию ему дается имя хоста с окончанием -slow.log. Если файлу присвоено имя, не содержащее пути доступа к нему, этот файл сохраняется в каталоге с данными. Этот журнал позволяет определить запросы, на выполнение которых ушло слишком много времени, — а, значит, и обнаружить основных кандидатов на оптимизацию. Конечно, при достижении журналом значительного объема эта задача усложняется. В таком случае журнал можно пропустить через команду mysqldumpslow и получить краткий отчет о запросах, попавших в список. При использовании ключа -log-long-format на экран выводятся и запросы, не работающие с индексами. Обслуживание файлов журналов В MySQL предусмотрено наличие нескольких файлов журналов, позволяющих следить за всеми аспектами работы системы. Правда, иногда приходится проверять, не занимают ли журналы лишнего места, и удалять ненужные. При работе с журналами MySQL, вам, вероятнее всего, понадобится удалять их или создавать их резервные копии, и указывать MySQL записывать данные журналов в новые файлы. В системе 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), файл журнала закрывается, после чего создается новый файл с большим номером. При использовании одного журнала обновлений нужно очистить журналы и перенести их старые файлы в резервную копию. При использовании обычной процедуры ведения журналов для этого нужно выполнить примерно следующую последовательность команд: 84 shell> cd mysql-data-directory shell> mv mysql.log mysql.old shell> mysqladmin flush-logs а затем сделать резервную копию файла mysql.old и удалить его. 85 ЛЕКЦИЯ 9. Резервирование и копирование баз данных Описание: В этой лекции рассматриваются вопросы создания резервных копий баз данных и аспекты восстановления баз из резервных копий. Администратор должен обязательно резервировать базы данных на случай повреждения или потери данных. Только благодаря резервированию все таблицы могут быть восстановлены до прежнего состояния в случае сбоя в работе системы. Кроме того, не исключен вариант, когда резервирование может оказаться единственным путем отступления, если какой-либо неопытный пользователь случайно выполнит операторы DROP database или drop table. Иногда сбой может произойти по вине собственно администратора MySQL. Так, автору этих лекций известны случаи, когда администраторы разрушали файлы таблиц, пытаясь изменить их с помощью таких редакторов, как vi или emacs. Это далеко не самый лучший способ отредактировать таблицы. Существует два основных способа резервирования баз данных: использование программыmysqldump и непосредственное копирование файлов базы данных (с помощью команд ср, tar или cpio). Каждый метод имеет свои преимущества и недостатки. Программа mysqldump тесно взаимодействует с сервером MySQL. Методы непосредственного копирования являются внешними по отношению к серверу и требуют проверки, чтобы клиенты не пытались изменить таблицы баз данных в процессе копирования. Эта же проблема возникает при использовании для резервирования баз данных средств резервирования файловой системы. Если в процессе резервирования кто-то из пользователей изменяет таблицы, их файлы окажутся несовместимыми и не подлежащими восстановлению. Разница между резервированием файловой системы и непосредственным копированием файлов заключается в том, что в первом случае имеется возможность управлять расписанием резервирования. Программа mysqldump медленней резервирует данные, чем методы непосредственного копирования. Программа mysqldump создает простые текстовые файлы, которые можно легко переносить на другие компьютеры, даже с другой аппаратной архитектурой. Копируемые вручную файлы не могут переноситься на другие компьютеры, если, конечно, не используется специальный формат хранения MylSAM. ISAM-таблицы могут копироваться только между компьютерами с подобной архитектурой. Так, например, копирование файлов из системы Solaris на компьютере с процессором SPARC в систему Solaris на компьютер с процессором SPARC будет успешным, чего нельзя сказать о копировании файлов из системы Solaris на компьютере с процессором SPARC в систему Solaris на компьютер с процессором Intel. Впервые появившийся в версии MySQL 3.23 формат хранения MylSAM решает эту проблему, поскольку является независимым от архитектуры компьютера. Соответственно, скопированные файлы можно легко переносить на другой компьютер с любой архитектурой в одном из двух случаев: на втором компьютере также запущена СУБД MySQL версии 3.23 и более поздней либо файлы таблиц представлены в формате MylSAM, а не ISAM. Независимо от выбранного метода резервирования существуют определенные принципы, которым необходимо следовать для достижения эффективных результатов. Регулярно выполняйте резервирование. На этапе планирования разработайте расписание и четко его придерживайтесь. Обязательно активизируйте регистрацию обновлений (как это сделать, рассказывается в лекции "Ведение файлов журналов"). Журналы обновлений помогут восстановить базу данных после сбоя, вернее, после восстановления заархивированных файлов дадут возможность вернуть ее в состояние, в котором база данных находилась непосредственно 86 перед сбоем. Для этого необходимо заново внести все изменения, сделанные с момента последнего резервирования, просто запустив запросы журнала обновлений. Согласно терминологии резервирования, заархивированные файлы баз данных представляют полный архив, а журналы обновлений — дополнительный. Используйте постоянную и легко понятную схему присвоения имен файлам архива. Имена типа backupl, backup2 и т.д. не несут никакой смысловой нагрузки, и когда приходит время восстанавливать информацию, много времени тратится на изучение их содержимого. Гораздо эффективней присваивать архивным файлам имена баз данных и дат резервирования. Например: % mysqldump samp_db > /usr/archives/mysql/samp_db.1999-10-02 % mysqldump menagerie > /usr/archives/mysql/menagerie.1999-10-02 Иногда сразу после создания файлы архивов лучше сжать, ведь они занимают много места. Время от времени рекомендуется также удалять ненужные файлы архивов, так же как и файлы журналов, чтобы не заполнять жесткий диск ненужной информацией. Более детально эта процедура рассматривается в лекции "Ведение файлов журналов". Описанные в ней способы можно применять и к файлам архивов. Резервируйте впоследствии архивные файлы MySQL с помощью средств резервирования файловой системы. В случае фатального сбоя операционной системы потерянным может оказаться не только каталог данных, но и вся остальная информация, находящаяся на жестком диске. Поэтому для большей надежности необходимо резервировать также файлы архивов и журналов обновлений. Размещайте файлы архивов на отдельном диске. Это снизит вероятность переполнения этими файлами диска, содержащего каталог данных. Описанные выше методы резервирования баз данных оказываются эффективными и для копирования этих баз на другой сервер. Наиболее часто база данных переносится на другой сервер, работающий на отдельном компьютере, однако можно перенести ее в отдельный каталог для другого сервера, работающего на этом же локальном компьютере. Необходимость в этом может возникнуть после выхода новой версии MySQL, когда администратор захочет протестировать ее работу перед полным переходом, либо при установке нового более производительного компьютера, на который со временем планируется перенести все базы данных. Резервирование и копирование баз данных с помощью программы mysqldump При резервировании базы данных с помощью программы mysqldump создается файл, который состоит из создающих таблицы операторов create table и операторов insert с данными строк таблиц. Другими словами, в процессе работы программа mysqldump создает набор операторов, которые впоследствии можно отправить серверу mysql для воссоздания базы данных. Для резервирования целой базы данных в одном текстовом файле достаточно запустить следующую команду: % mysqldump samp_db > /usr/archives/mysql/samp_db.1999-10-02 В результате ее выполнения будет создан файл, начинающийся следующим образом: # MySQL dump 6.0 87 # # Host: localhost Database: samp db # -------------------------------------------# Server version 3.23.2-alpha-log # # Table structure for table ‘adsence’ # CREATE TABLE adsence { student id int (10) unsigned DEFAULT ‘0’ NOT NULL, date date DEFAULT ‘0000-00-00’ NOT NULL, PRIMARY KEY (student id, date) }; # # Dumpling data for table ‘adsence’ # INSERT INTO adsence VALUES (3, ‘1999-09-03’); INSERT INTO adsence VALUES (5, ‘1999-09-03’); INSERT INTO adsence VALUES (10, ‘1999-09-06’); Остальная часть файла также состоит из операторов CREATE TABLE и INSERT. Чтобы сразу после создания сжать файл архива, необходимо ввести вместо представленной выше следующую команду: % mysqldump samp_db | gzip > /usr/archives/mysql/samp_db.1999-10-02.gz Результатом резервирования большой базы данных станет создание большого файла архива, с которым трудно работать. В таком случае можно зарезервировать отдельные таблицы, указав их имена после имени базы данных в строке команды mysqldump. Это приведет к созданию меньших, а следовательно, и более удобных для обработки файлов. Резервирование отдельных таблиц базы данных sampdb можно выполнить с помощью следующих команд: % mysqldump samp_db student score event adsence > gradebook.sql % mysqldump samp_db member president > hist-league.sql Если создаваемые файлы архивов планируется использовать для периодического обновления содержимого другой базы данных, можно добавить в командную строку mysqldump опцию -adddrop-table. В этом случае в файл архива будут заноситься операторы drop table if EXISTS. При загрузке файла архива с этими операторами в другой базе данных сообщения о существовании таблиц появляться не будут. Администраторы, управляющие двумя серверами, могут применять этот способ для периодической загрузки данных из баз данных одного сервера в базы другого. Для переноса содержимого базы данных на другой сервер вовсе необязательно создавать файлы архива. Достаточно убедиться в существовании этой базы данных на другом компьютере, а затем создать канал (pipe), чтобы mysql смог напрямую считывать вывод команды mysqldump. Так, например, копирование базы данных с компьютера pit-viper.snake.net на boa.snake.netлегко выполняется с помощью следующих команд: % mysqladmin -h boa.snake.net create samp db % mysqldump samp_db | mysql -h boa.snake.net samp_db 88 Чтобы впоследствии обновить информацию базы данных на компьютере boa.snake.net, запустите только вторую команду, добавив опцию -add-drop-table во избежание ошибок записи в уже существующие таблицы: % mysqldump -add-drop-table samp_db | mysql -h boa.snake.net samp_db В строке команды mysqladmin можно использовать и другие полезные опции. Комбинация опций -flush-logs и —lock-tables полезна для контроля состояния базы данных. Первая опция закрывает и повторно открывает файлы журналов обновлений, а вторая — блокирует все резервируемые таблицы. Если сервер создает журналы обновлений с порядковыми именами, каждый новый журнал будет содержать все запросы на изменение базы данных с момента ее последнего резервирования. (Блокировка таблиц закрывает доступ к базе данных пользователям, пытающимся внести изменения.) Если опция -flush-logs применяется для согласования времени создания журнала обновлений и времени резервирования, лучше архивировать сразу всю базу данных. При резервировании отдельных таблиц довольно трудно синхронизировать журналы обновлений с файлами архивов. В процессе восстановления содержимое журнала обновлений обычно извлекается для каждой базы данных отдельно. Невозможно рассортировать эту информацию еще и по таблицам, поэтому администратору это придется делать самостоятельно. Команда mysqldump по умолчанию перед записью таблицы в архив считывает ее всю в память. В этом, однако, нет необходимости. Более того, подобная обработка больших таблиц вообще может привести к сбою. Поэтому администратор может воспользоваться опцией — quick, определяющей построчное считывание и запись информации. Чтобы еще больше оптимизировать процесс резервирования, вместо опции —quick можно применить опцию — opt. Она, в свою очередь, активизирует все остальные опции, ускоряющие считывание и резервирование данных. Выполнение резервирования с помощью опции —opt — наиболее распространенный (благодаря скорости) метод выполнения. Однако следует проявлять осторожность, поскольку опция —opt оптимизирует процедуру резервирования, закрывая на время доступ к базе данных. Она блокирует все таблицы сразу, запрещая внесение каких-либо изменений. Эффект от применения этой опции заметить очень легко. Попробуйте запустить команду резервирования с этой опцией днем, во время наиболее частого использования базы данных. Пользователи не заставят себя долго ждать, и скоро телефон администратора начнет звонить не переставая. Эффекта, прямо противоположного результатам опции —opt, можно достичь с помощью опции —delayed. Эта опция заставляет команду mysqldump записывать в файл архива операторы INSERT DELAYED вместо операторов INSERT. Опция —delayed оказывается весьма полезной, если при загрузке файла архива в другую базу данных администратор желает уменьшить влияние этой операции на выполнение текущих запросов. Для уменьшения передаваемого объема информации при копировании базы данных с одного компьютера на другой весьма эффективной является опция —compress. Однако эта опция предназначается для программ, взаимодействующих с сервером удаленного, а не локального компьютера: % mysqldump --opt samp_db | mysql --compress -h boa.snake.net samp_db Команда mysqldump имеет и множество других опций. 89 Использование методов прямого копирования Второй метод резервирования баз данных и таблиц заключается в непосредственном копировании файлов таблиц. Как правило, эта процедура выполняется с помощью таких утилит, как ср, tar или cpio. В примерах этой лекции используется программа ср. Как уже отмечалось, применяя методы прямого копирования, обязательно нужно убедиться, что таблицы в процессе резервирования не используются другими пользователями. Если сервер изменяет какую-либо таблицу во время копирования, ее копия окажется искаженной. Лучший способ обеспечить целостность копий — временно приостановить работу сервера, скопировать файлы и затем снова запустить сервер. Итак, предположим, что работа сервера временно приостановлена либо подлежащие копированию таблицы защищены от изменения. В таком случае резервирование всей базы данных samp_db в каталог резервирования (DATADIR в этом примере — каталог данных сервера) выполняется посредством следующих команд: % cd DATADIR % cp -r samp_db /usr/archive/mysql Для резервирования отдельных таблиц введите следующие команды: % cd DATADIR/samp_db % ср member.* /usr/archive/mysql/samp_db % ср score.* /usr/archive/mysql/samp_db По завершению процедуры резервирования можно перезапустить сервер (если его работа была приостановлена) или снять блокировку с таблиц (если сервер все же работал). Для переноса зарезервированных методом прямого копирования файлов на другой компьютер достаточно еще раз скопировать их в соответствующий каталог базы данных другого компьютера. Однако прежде необходимо убедиться, что файлы соответствуют MyISAM-таблицам и оба компьютера имеют одинаковую аппаратную архитектуру. Иначе содержимое таблицы на втором компьютере может выглядеть очень странно. Следует также проверить, что в процессе инсталляции файлов на другой компьютер пользователи сервера не пытались получить к ним доступ. Репликация баз данных Термин "репликация" может означать как простое копирование базы данных на другой компьютер, так и интерактивное обновление подобной второй базы данных при внесении изменений в основную базу данных. Если необходимо простоскопировать базу данных на другой компьютер, можно воспользоваться одним из описанных выше методов. Первые признаки возможностей интерактивного обновления появились только в версии MySQL 3.23. Пока они находятся на стадии разработки, поэтому заинтересованным администраторам следует внимательно следить за будущими версиями, чтобы не пропустить новые версии. Восстановление данных из архивов 90 Повреждение данных может происходить по самым разным причинам и значительно варьироваться по масштабам. В наилучшем случае поврежденными оказываются одна-две таблицы (например, если работа компьютера была внезапно завершена из-за отключения электричества). В наихудшем — придется восстанавливать весь каталог данных (например, если сломался и не подлежит ремонту жесткий диск). Восстановление данных может потребоваться и в некоторых других ситуациях, например, когда пользователи случайно удалят базы данных или таблицы либо сотрут их содержимое. Независимо от причин повреждения, администратору немедленно нужно выполнить процедуру восстановления. Если таблицы не утеряны, а лишь повреждены, попытайтесь отладить их с помощью командmyisamchk и issamchk. Вполне вероятно, что проблему можно решить с их помощью, и необходимость в восстановлении файлов архивов отпадет. Процедура отладки таблиц описывается в лекции 4, "Поддержка и восстановление баз данных". Если же таблицы потеряны или не подлежат отладке, самое время приступить к их восстановлению. Для восстановления используются два источника информации: файлы архива и журналы обновлений. Первые позволяют восстановить таблицы до состояния, в котором они были в момент выполнения резервирования. Однако зачастую таблицы значительно изменяются пользователями между моментами резервирования и сбоя. В такой ситуации эффективными оказываются журналы обновлений, содержащие все последние запросы на внесение изменений. Чтобы восстановить все эти изменения, достаточно запустить запросы журнала обновлений в mysql. (Именно по этой причине администратор должен обязательно включить регистрацию обновлений. Если она не активизирована, немедленно включите ее, и прежде чем читать далее, создайте новый архив базы данных.) Процедура восстановления может видоизменяться в зависимости от объема информации, подлежащей воссозданию. Фактически, легче восстановить всю базу данных, чем одну таблицу, поскольку в журнал обновлений заносятся запросы на изменение именно баз данных, а не таблицы. Восстановление базы данных Сначала, если речь идет о восстановлении базы данных mysql с таблицами разрешений, необходимо запустить сервер с опцией —skip-grant-tables. Иначе сервер выдаст сообщение о невозможности поиска таблиц разрешений. После восстановления таблиц разрешений выполните команду mysqladmin flush-privileges, чтобы заставить сервер загрузить и использовать таблицы разрешений. Скопируйте содержимое каталога базы данных в другое место. Оно может потребоваться в будущем для изучения оставшихся данных поврежденных таблиц. Загрузите базу данных, используя файлы самых последних архивов. Если эти файлы были созданы программой mysqldump, используйте их в качестве ввода в mysql. Если же восстановление информации выполняется из файлов, непосредственно скопированных из каталога базы данных (например, с помощью команд tar или ср), скопируйте их обратно в каталог данных. В последнем случае перед копированием файлов необходимо временно приостановить работу сервера, а по завершении переноса — снова запустить. Используя журналы обновлений, повторно запустите все запросы на изменение базы данных, которые были исполнены с момента последнего резервирования. Для этого содержимое журнала обновлений можно представить в качестве ввода для mysql. Если необходимо, определите опцию —one-database, чтобы сервер mysql исполнил запросы только к той базе данных, которая представляет интерес. Если для восстановления информации необходимо использовать все журналы обновлений, запустите в каталоге с этими журналами следующую команду: %ls -t -r -l update.[0-9]*|xargs cat|mysq| —one-database db_name 91 Команда Is воспроизводит список файлов журналов обновлений, отсортированный сервером в порядке создания. (Об этом следует помнить, поскольку неаккуратное изменение имен файлов журналов может привести к восстановлению их запросов в неправильном порядке.) В большинстве же случаев используются не все, а только часть журналов обновлений. Например, если запросы к базе данных, выполненные после последнего резервирования, хранятся в файлах с именами update.392, update.393 и т.д., повторно запустить их можно с помощью следующих команд: % mysql —one-database db_name < update.392 % mysql -one-database db_name < update.393 Если процедура восстановления применяется для устранения результатов случайного выполнения операторов DROP database, drop table или delete, не забудьте перед запуском команды удалить эти операторы из журнала! Восстановление отдельных таблиц Восстанавливать отдельные таблицы сложней. Если для восстановления применяется файл архива, созданный утилитойmysqldump и содержащий данные для множества таблиц, администратору придется извлечь из него строки, соответствующие требуемой таблице, и использовать их в качестве ввода для mysql. Это самая легкая часть процедуры восстановления. После нее необходимо из журнала обновлений извлечь записи, соответствующие требуемой таблице. Для выполнения этой процедуры весьма полезной может оказаться утилита mysqlfindrows, возможности которой позволяют извлекать многострочные запросы из журнала обновлений. Еще один вариант — восстановить всю базу данных на другом сервере, а затем скопировать нужную таблицу в исходную базу данных. Эта процедура гораздо проще! Необходимо лишь убедиться, что работа сервера с исходной базой данных приостановлена в процессе копирования файлов в исходную базу. 92 ЛЕКЦИЯ 10. Оптимизация Описание: В лекции объясняется, когда и как нужно оптимизировать базы данных. Кроме того, затрагиваются проблемы перекомпиляцииядра MySql. Оптимизация — это процесс тонкой настройки системы, направленный на повышение скорости ее работы или сокращение объема используемой памяти. В первой части лекции объясняется, когда и как нужно оптимизировать базы данных. Бинарные дистрибутивы, доступные на Web-узле MySQL, оптимизированы для общего применения. Чтобы адаптировать программу к каким-то специфическим требованиям, ее необходимо перекомпилировать. Об этом и пойдет речь в конце лекции. Предварительные действия Перед началом проектирования базы данных поставьте себе задачу добиться максимальной ясности спецификации, даже если на это уйдет больше времени. Помните о том, что услуги программистов стоят дорого, особенно если им приходится разбираться с малопонятным проектом. Простое решение обычно является наилучшим. Перенося базу данных в производственную среду, позаботьтесь о том, чтобы производительность базы данных была адекватной. Если к проекту прилагается формальная спецификация требований, просмотрите, указываются ли в ней какие-либо ограничения производительности. Для приложений, работающих с базами данных, нередко задается максимальное время выполнения запросов. Продолжительность времени между вводом инструкции и получением результатов запроса зависит от многих факторов. Необходимо заранее учесть те факторы, которые впоследствии нельзя будет контролировать. Если обнаруживается, что система требует оптимизации, в первую очередь подумайте об обновлении аппаратной части. Это может оказаться самым дешевым вариантом. В 1965 г. Гордон Мур (Gordon Moore) установил, что вычислительные мощности удваиваются каждые 18 месяцев. Данное правило называют законом Мура. Но, несмотря на столь стремительный рост производительности, удельная стоимость вычислительных средств неуклонно снижается. Например, центральные процессоры за полтора года удвоят тактовую частоту, хотя стоить будут так же, как и полтора года назад. Таким образом, обновление компьютера может обойтись дешевле, чем оптимизация проекта. Во вторую очередь стоит подумать об обновлении программного обеспечения. Основной программный компонент— это операционная система. Известно, что Linux и BSD UNIX позволяют повысить производительность старых компьютеров, превосходя в этом отношении коммерческие операционные системы, такие, как Windows, особенно если бессбойная работа сервера очень важна. Обновляется и сама программа MySQL. Когда появится новая версия, ее производительность будет повышена в сравнении с текущей. Но и в текущую версию регулярно вносят мелкие исправления, так что желательно идти в ногу со временем. Основная причина оптимизации — желание сэкономить деньги (оставим в стороне личное удовлетворение и другие причины). Не забывайте об этом в своих попытках повысить производительность программы. Нет смысла затрачивать на оптимизацию больше денег, чем она способна принести. Стоит потрудиться над такой программой, с которой работает множество людей, особенно если это коммерческое приложение. Что касается программ с открытыми кодами, то важность оптимизации здесь трудно определить. Лично я рассматриваю работу над такими проектами как хобби. Чтобы процесс оптимизации был максимально эффективным, сосредоточьте усилия на самой медленной части программы, улучшение которой обеспечит наибольшую отдачу. Обычно 93 пытаются найти более быстрые альтернативы применяемым алгоритмам. В вычислительной технике относительная эффективность алгоритма записывается в нотации "большого О". Например, запись О(n) означает, что время выполнения алгоритма пропорционально числу обрабатываемых элементов п. Алгоритм типа О(n) является очень медленным. Проанализируйте используемые в программе алгоритмы и подумайте, что можно сделать для их улучшения. Тесты производительности Прежде чем приступать к оптимизации, нужно вооружиться средствами измерения производительности. Предусмотрительные разработчики MySQL написали группу Perl сценариев, предназначенных для тестирования производительности MySQL и других СУБД. Эти сценарии расположены в каталоге sql-bench исходного дистрибутива. В подкаталоге Results находятся результаты множества тестов существующих систем, которые можно сравнить с собственными оценками. В сценариях используется демонстрационная база данных, в которой выполняется восемь различных тестов. Эта база данных называется test и инсталлируется вместе с MySQL. Сценарий run_all_tests запускает все тесты последовательно. При наличии опции -log результаты работы сценария будут сохранены в каталоге output для последующего просмотра. Ниже приведена команда, запускающая тесты из каталога sqlbench. #./run-all-tests –user=leon –password=secret --leon Для работы этого сценария необходимо наличие в системе интерпретатора Perl и модуля DBI. Для экспериментов я использую старый компьютер Pentium с частотой 100 МГц, работающий под управлением RedHat Linux. Несмотря на слабую вычислительную мощность, программа MySQL демонстрирует на нем вполне приемлемую производительность. Кроме того, ограниченные возможности системы позволяют быстро выявлять неэффективные программные решения. Результаты тестов, полученные на этом компьютере, показаны в листинге 10.1. Несложно убедиться, что моя система работает примерно в 10 раз медленнее, чем самая медленная из систем, результаты тестов которых имеются в каталоге Results. Если бы такую производительность продемонстрировал рабочий сервер, нужно было бы немедленно обновить его аппаратную часть. The result logs which were found and the options: 1 mysql-linux 2.2.16_22_i586 MySQL 3.23.39 =============================================================== Operation | 1| | mysql-l| ----------------------------------------------------------Results per test in seconds: | | ----------------------------------------------------------ATIS | 549.00| Alter-table | 4836.00| Big-tables | 270.00| Connect | 607.00| Create | 2027.00| Insert | +88846.00| Select | +18339.00| wisconsin | 135.00| ----------------------------------------------------------Листинг 10.1. (html, txt) 94 The results per operation: -------------------------------------------------------alter table add (992) | 2670.00| alter table drop (496) | 2066.00| connect (10000) | 95.00| connect select 1 row (10000) | 115.00| connect select simple (10000) | 106.00| count (100) | 364.00| count distinct (1000) | +779.00| count distinct 2 (1000) | +605.00| count distinct big (120) | 1185.00| count distinct group (1000) | +726.00| count distinct group on key (1000) | +716.00| count distinct group on key parts (1) | +708.00| count distinct key prefix (1000) | +671.00| count group on key parts (1000) | 706.00| count on key (50100) | +7005.00| create + drop (10000) | 109.00| create MANY tables (10000) | 1196.00| create index (8) | 52.00| create key drop (10000) | 115.00| create table (31) | 0.00| delete all (12) | 219.00| delete all many keys (1) | 8960.00| delete big (1) | 5.00| delete big many keys (128) | 8956.00| delete key (10000) | 145.00| drop index (8) | 47.00| drop table (28) | 0.00| drop table when MANY tables (10000) | 105.00| insert (350768) | 1044.00| insert duplicate (100000) | 211.00| insert (100000) | 17849.00| insert many fields (2000) | 97.00| insert select 1 key (1) | 102.00| insert select 2 keys (1) | 125.00| min max (60) | 301.00| min max on key (85000) | +2627.00| multiple value insert (100000) | 102.00| order by big (10) | 560.00| order by big key (10) | 503.00| order by big key2 (10) | 479.00| order by big key desc (10) | 531.00| order by big key diff (10) | 586.00| order by big key prefix (10) | 487.00| order by key2 diff (500) | 57.00| order by key prefix (500) | 31.00| outer join (10) | 989.00| outer join found (10) | 918.00| outer join not found (500) | +36000.00| outer join on key (10) | 810.00| 95 select 1 row (10000) | 17.00| select 2 rows (10000) | 23.00| select big (10080) | 700.00| select column + column (10000) | 24.00| select diff key (500) | +1470.00| select distinct (800) | 145.00| select group (2925) | +896.00| select group when MANY tables (10000) | 502.00| select join (100) | 25.00| select key (200000) | +1123.00| select key2 (200000) | +1213.00| select key2 return key (200000) | +1174.00| select key2 return prim (200000) | +1197.00| select key prefix (200000) | +1245.00| select key prefix join (100) | 197.00| select key return key (200000) | +1106.00| select key many fields (2000) | 172.00| select query cache (10000) | 1075.00| select query cache2 (10000) | 1075.00| select range (410) | +1812.00| select range key2 (25010) | 185.00| select range prefix (25010) | 197.00| select simple (10000) | 11.00| select simple join (500) | 20.00| update big (10) | 440.00| update of key (40000) | 627.00| update of key big (501) | 351.00| update of primary key many keys(256) | 3290.00| update with key (300000) | 1011.00| update with key prefix (100000) | 290.00| wisc benchmark (114) | 44.00| -------------------------------------------------------TOTALS | +124540.00| -------------------------------------------------------Листинг 10.2. (html, txt) Сценарий compare results суммирует и сравнивает результаты тестов. В листинге 10.1приведен лишь один набор результатов. В действительности я немного сократил выходные данные, удалив ряд малозначащих пояснений. В первом блоке чисел указано время выполнения каждого из восьми тестов в секундах. Во втором блоке отображается статистика отдельных операций по всем тестам. Числа со знаком "плюс" — это приблизительные оценки, полученные для тестов, время выполнения которых превысило максимум. Результаты тестов, предоставляемые разработчиками MySQL, можно использовать для выбора аппаратной платформы и операционной системы. На Web узле MySQL (http://www.mysql.com) постоянно публикуются обновляемые результаты и графики сравнения показателей MySQL с показателями других СУБД, работающих на идентичном оборудовании. Приводятся также данные, касающиеся работы MySQL на разных платформах. Конечно, все эти тесты отражают лишь относительную производительность сервера. С их помощью можно узнать, насколько возрастет скорость его работы при изменении тех или иных настроек, но тесты не могут помочь в оптимизации базы данных. Для оценки производительности запросов 96 необходимо воспользоваться инструкцией EXPLAIN. Эта инструкция, помимо всего прочего, сообщает о том, сколько записей будет прочитано при выполнении заданной инструкции SELECT. Каждая строка результатов соответствует одной исходной таблице, а порядок строк совпадает с порядком обращения к таблицам. Сообщаемое число записей может быть приблизительным, но погрешность очень мала. Произведение счетчиков записей является грубым критерием производительности запроса. Чем меньше это произведение, тем быстрее выполняется запрос. Представим себе, к примеру, объединение таблицы, содержащей 15000 слов, с таблицей, содержащей 100000 слов. В худшем случае программе MySQL придется просмотреть все записи обеих таблиц. Сначала выбирается первая запись первой таблицы, а затем начинается просмотр записей второй таблицы до тех пор, пока не будет найдено совпадение. Умножив 15000 на 100000, получим 1,5 миллиарда операций чтения. На практике это число оказывается немного меньшим, но и его достаточно, чтобы получить представление о скорости запроса. Далее будет рассказываться о том, как с помощью индексов уменьшить количество записей, читаемых в процессе объединения таблиц. С помощью журнала медленных запросов, описанного в лекции 8, можно легко найти наименее эффективные запросы. В дистрибутив MySQL входит сценарий mysqldumpslow предназначенный для упорядочения записей этого журнала по указанному в них времени выполнения запроса. Оптимизация проекта Давайте вспомним некоторые теоретические аспекты. Нормализация — это такой метод оптимизации базы данных, при котором избыточность хранящейся в ней информации оказывается минимальной. Следовательно, уменьшается время, затрачиваемое приложением на поддержание целостности базы данных. Нормализация достигается за счет повышения объема работы, выполняемой сервером, так как увеличивается число таблиц и серверу приходится чаще создавать их объединения. В процессе денормализации в базу данных вносят некоторую избыточность, чтобы сократить объем работы по извлечению информации. Наиболее эффективный тип денормализации включает создание итоговых данных. Под этим может подразумеваться добавление к таблице столбца, хранящего результаты вычислений по другим столбцам. Например, если в таблице накапливаются данные о прохождении грузов, то в ней будут столбцы с указанием времени прибытия и отбытия груза. Чтобы не вычислять каждый раз время стоянки, можно посчитать его один раз и занести результат в отдельный столбец. Управлять подобной избыточностью несложно. Иногда создают не просто итоговые столбцы, а целые таблицы. Например, можно сохранять результаты ключевых запросов в таблице, которая обновляется раз в день. Это избавит сервер от необходимости все время выполнять одни и те же трудоемкие запросы, хотя и повысит риск получения пользователями неактуальных данных. Если таблицы содержат часто изменяемую информацию, лучше делать их резидентными. Такие таблицы хранятся в памяти и уничтожаются при перезагрузке сервера. Приложение должно быть готово к возможному отсутствию таблицы и должно уметь воссоздавать ее в случае необходимости. Хороший пример — Web-приложение, хранящее параметры сеанса в базе данных. Реляционные базы данных хорошо работают с типизированными значениями фиксированного размера. В MySQL поддерживаются типы переменной длины, например BLOB и TEXT, но управлять ими сложнее. Такого рода информацию лучше хранить в файлах, а в базе данных достаточно запоминать путевые имена этих файлов в столбцах типа CHAR. Если база данных используется в Web-приложениях, помните о том, что у Web-сервера есть кеш-буфер загружаемых 97 файлов изображений и аудиоклипов, поэтому он будет работать с такими файлами быстрее, чем MySQL. Еще одна причина избегать столбцов подобного типа заключается в появлении записей переменной длины со всеми вытекающими отсюда последствиями. При внесении изменений такая таблица становится дефрагментированной что приводит к замедлению доступа к ней. Для извлечения динамической строки может потребоваться несколько операций чтения, что также не способствует повышению производительности. О форматах хранения табличных данных рассказывалось в лекции 7, "Физическое хранение данных". Иногда возникает проблема — определить, когда стоит использовать столбцы типа CHAR, а когда VARCHAR. Если в таблице есть столбцы типа BLOB или TEXT, то предпочтение отдается типу VARCHAR, потому что все записи таблицы будут динамическими. То же самое справедливо для случая, когда средняя размерность значений столбца не превышает половины его размерности. Например, столбец типа VARCHAR (80) средняя размерность которого равна 10 символам, определен правильно. Если же средняя размерность превышает 40 символов, нужно поменять тип столбца на CHAR (80) Данное правило направлено на оптимизациюскорости работы с таблицами. Когда более важным фактором является экономия дискового пространства, то в большинстве случаев следует пользоваться типом VARCHAR. Для таблиц MyISAM поддерживается опция DELAY_KEY_WRITE. Она заставляет программу хранить изменения табличных индексов в памяти, пока таблица не будет закрыта. Это сокращает время записи на диск измененных табличных данных, но также повышает риск повреждения таблицы в случае сбоя сервера. Если используется данная опция, то при каждом перезапуске сервера необходимо проверять таблицы на предмет повреждений. Процедура analyse() представляет собой удобное средство проверки таблицы после вставки данных, так как она определяет диапазон значений каждого столбца в полученном наборе записей. Ее нужно применять в инструкции SELECT, которая извлекает все записи отдельной таблицы. На основании анализа таблицы процедура analyse() предложит оптимальный тип данных для каждого столбца. В некоторых случаях процедура analyse() сообщает о том, что вместо типа CHAR должен применяться тип ENUM. Это происходит, когда столбец содержит небольшое число повторяющихся значений. Столбец типа ENUM занимает гораздо меньше места, поскольку в действительности он хранит лишь номера элементов перечисления. Многие типы данных допускают регулирование своей размерности. Например, в столбце типа CHAR может храниться столько уникальных значений, что приводить его к типу ENUM нет никакого смысла, и все равно формальная размерность оказывается избыточной. То же самое касается типа INT, у которого существуют более "короткие" эквиваленты: MEDIUMINT, SMALLINT и TINYINT. Но не забудьте учесть будущее пополнение таблицы. Например, если в таблице 16000 записей, то для первичного ключа вполне подойдет тип SMALLINT. Если же предполагается, что в таблице будет более 65535 записей, следует остановиться на типе INT. Обратите внимание на столбцы, в которых не могут присутствовать значения NULL. Для экономии места такие столбцы нужно объявлять со спецификатором NOT NULL. Числовые столбцы, в которых не могут храниться отрицательные числа, должны иметь спецификатор UNSIGNED. Оптимизация приложений Подключение к базе данных MySQL происходит относительно быстро в сравнении с другими СУБД, но это время можно еще уменьшить за счет кэширования соединений. Требуется лишь прикладная среда, позволяющая хранить идентификаторы соединений в памяти во время работы сервера. Например, модуль РНР непрерывно работает на Web-сервере. Он поддерживает функцию 98 mysql pconnect(), которая создает постоянные соединения. Получив запрос на подключение к серверу, модуль РНР попытается использовать существующее соединение, если это возможно. В протоколах JDBC и ODBC тоже применяется технология кэширования соединений. Она особенно удобна, когда приложение создает большое число соединений за короткий промежуток времени. К примеру, если приложение вставляет данные в таблицу, можно предварительно помещать данные в буфер, с тем чтобы позднее занести их в таблицу в пакетном режиме. В этом случае лучше сразу же заблокировать таблицу, чтобы не пришлось многократно обновлять табличные индексы. Приложение может дотировать информацию, извлекаемую из базы данных. Это выгодно, если данные меняются нечасто. Когда изменение данных все же происходит, приложение запрашивает принудительную очистку буфера. Предположим, что в Internet магазине имеется каталог продаваемых товаров. Этот каталог пополняется или обновляется раз в неделю, а то и меньше. Когда приложение отправляет клиенту html-страницу с описанием товара, оно вполне может взять информацию из кэша. Если администратор захочет воспользоваться приложением для обновления цены товара, он должен будет очистить кэш. То же самое применимо и к программным блокам. Если нужно узнать название, цену и категорию товара, введите один запрос и сохраните полученные значения в программных переменных. Основная работа по выборке данных заключается в поиске нужной записи. Не имеет особого значения, 100 или 1000 байтов извлекаются из нее. Оптимизация запросов Незаметно для пользователей программа MySQL оптимизирует предложения WHEREинструкции SELECT. Обычно не нужно заботиться о том, сколько скобок указано в выражении или каков порядок таблиц в объединении. Вместо этого сосредоточьтесь на индексах. Они позволяют ускорить операции выборки данных за счет замедления операций записи. Конечно, индексы занимают дополнительное место на диске, но они незаменимы с точки зрения эффективной организации таблиц. Когда программа MySQL извлекает данные из таблицы, ей достаточно просмотреть один индексный столбец, чтобы найти нужные записи и не сканировать всю таблицу. Если к объединенной таблице применимы два индекса, программа выбирает из них тот который позволит прочесть меньшее число записей. Разрешается создавать индекс, охватывающий несколько столбцов. Программа MySQL может работать с частями индекса, но они должны просматриваться строго слева направо. Например, если индекс включает столбцы имени и фамилии, то при обращении к первому столбцу индекс будет использован, а ко второму — нет (при условии, что перед этим не было обращения к первому столбцу). Это правило применимо и к символам индексируемого столбца, содержащего текстовые данные (тип CHAR, VARCHAR или BLOB). Когда в предложении WHERE присутствует оператор LIKE, индекс задействуется лишь в том случае, если шаблон сравнения содержит все литеральные символы слева, а метасимволы — справа. Так, шаблон ‘abc %’ разрешает использование индекса, а шаблон ‘abc % xyz’ — нет. В листинге 10.2 приведены инструкции, создающие две таблицы. Таблица word будет содержать 14346 записей, а таблица dictionary — 104237. В первую таблицу слова заносятся пользователями, а вторая таблица содержит список известных программе слов. Пользователи часто вводят несуществующие слова. Запрос, анализируемый в листинге 10.3, предназначен для выяснения количества распознанных слов. Условию отбора соответствуют 911 записей. mysql> EXPLAIN SELECT word.word, dictionary.word 99 -> FROM word LEFT JOIN dictionary -> ON word.word=dictionary.word -> WHERE word.class = '_VERBO' \G *************************** 1.row *************************** table: word type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 14346 Extra: where used table: dictionary type: ALL possible_keys: NULL key: NULL key_len: NULL Листинг 10.3. (html, txt) В запросе участвуют три столбца: столбцы word и class таблицы word и столбец word таблицы dictionary. Известно, что тестовому условию отбора соответствуют 911 записей таблицы word, поэтому наша задача состоит в том, чтобы сократить диапазон сканирования первой таблицы до соответствующего уровня. Для этого необходимо создать индекс по столбцу class. Сначала я планировал включить в индекс только упомянутый столбец, но потом подумал о других запросах, которые приходится направлять таким таблицам. Я, например, часто создаю отчет, в который включается все содержимое таблицы, отсортированное сначала по классам, а затем — по словам. Разумнее будет включить в индекс сразу два столбца (листинг 10.4). ALTER TABLE word ADD INDEX (class, word) Листинг 10.4. (html, txt) Теперь инструкция EXPLAIN выдает другие результаты (листинг 10.5). В поле Key len сообщается о том, что индекс охватывает 16 символов столбца class. По оценке программы MySQL, ей придется просмотреть 1517 записей, хотя мы знаем, что их всего 911 Mysql > EXPLAIN SELECT word. word, dictionary. Word -> FROM word LEFT JOIN dictionary -> ON word. Word = dictionary. Word -> WHERE word. Class = "_VERBO" \G table: word type: ref possible keys: class key: class key len: 16 ref: const rows: 1517 Extra: where used; Using index table: dictionary type: ALL 100 possible keys: NULL key: NULL key len: NULL ref: NULL rows: 104237 Extra: 2 rows in set (0.00 sec) Листинг 10.5. (html, txt) Итак, появление индекса привело к сокращению диапазона сканирования в 15 раз, но инструкция все же вынуждена просматривать 45 миллионов записей. Осталось еще учесть столбцы word в обеих таблицах. Разберемся сначала с таблицейword. В процессе объединения таблиц программа MySQL использует не более одного индекса от каждой таблицы. Если появляются варианты, то выбирается индекс с более узким диапазоном. Созданный нами индекс уже охватывает столбец word, к тому же, как видно из листинга 10.5, диапазон поиска существенно сузился. Теперь перейдем к таблице dictionary. Пока что инструкция SELECT вынуждена сканировать ее целиком. Добавление индекса к столбцу word позволит программе сразу же находить нужную запись (листинг 10.6). ALTER TABLE dictionary ADD INDEX (word) Листинг 10.6. (html, txt) Эффект этого действия продемонстрирован в листинге 10.7. Как видите, количество просматриваемых записей таблицыdictionary сократилось до одной! Mysql > EXPLAIN SELECT word. word, dictionary. Word -> FROM word LEFT JOIN dictionary -> ON word. Word = dictionary. Word -> WHERE word. Class = "_VERBO" \G *********************** 1. row ******************** table: word type: ref possible keys: class key: class key len: 16 ref: const rows: 1517 Extra: where used; Using index table: dictionary type: ref possible keys: word key: word key len: 64 ref: word. word rows: 1 Extra: Using index 2 rows in set (0.26 sec) Листинг 10.7. (html, txt) Оптимизация инструкций 101 От оптимизации больше всего выигрывают запросы на выборку, но существуют также методики повышения эффективности других инструкций, в частности INSERT. Можно избежать затрат времени на анализ инструкции, если воспользоваться преимуществами значений по умолчанию. Вместо того чтобы указывать значения всех столбцов, задайте лишь те из них, которые отличаются от стандартных установок, а остальное пусть сделает MySQL. Сказанное иллюстрирует листинг 10.8, в котором показаны определение таблицы и инструкция INSERT CREATE TABLE address { ID int (11) NOT NULL AUTO INCREMENT, Name Prefix CHAR (16) default NULL, Name First CHAR (32) default NULL, Name Middle CHAR (32) default NULL, Name Last CHAR (64) NOT NULL default, Name Suffix CHAR (16) default NULL, Company CHAR (64) default NULL, Street1 CHAR (64) default NULL, Street2 CHAR (64) default NULL, Street3 CHAR (64) default NULL, City CHAR NOT NULL default ‘’, State Prov CHAR (64) NOT NULL default, Postal Code CHAR (16) NOT NULL default, Country Code CHAR (2) default NULL, Phone1 CHAR (32) default NULL, Phone2 CHAR (32) default NULL, Fax CHAR (32) default NULL, Email CHAR (64) NOT NULL default ‘’, PRIMARY KEY (ID) }; INSERT INTO address (Name First, Name Last) VALUES (‘Leon’, ‘Atkinson’); Листинг 10.8. (html, txt) По умолчанию операции записи имеют приоритет над операциями чтения, но программа MySQL не прервет выполнение инструкции SELECT, если в очереди вдруг появится инструкция INSERT. Последняя окажется заблокированной до тех пор, пока инструкция SELECT не завершится. У инструкции INSERT есть также специальный флаг DELAYED, при наличии которого инструкция помещается в очередь без блокирования клиентского приложения, что повышает его оперативность. Если есть несколько записей, предназначенных для вставки в таблицу, воспользуйтесь многострочной инструкцией INSERT. Еще быстрее работает инструкция LOAD DATA INFILE. Для полной очистки таблицы лучше вызывать инструкцию TRUNCATE TABLE, а неDELETE. В этом случае программа MySQL удалит и снова создаст табличный файл, вместо того чтобы удалять записи одна за другой. Если в состав инструкции входит сложное выражение, замените его пользовательской функцией. Естественно, это имеет смысл делать только тогда, когда предполагается многократно вызывать инструкцию. О создании собственных функций рассказывается в лекции 13, "Расширение возможностей MySQL". Обслуживание таблиц 102 Можно ускорить выполнение запросов, если хранить таблицы и индексы в упорядоченном виде. Инструкция OPTIMIZE TABLE улучшает таблицу тремя способами. Во-первых, она устраняет пустые промежутки, оставшиеся после удаления записей. Для таблиц MyISAM это означает возможность одновременного выполнения инструкций INSERT и SELECT. Во-вторых, она соединяет распределенные фрагменты таблиц с динамическими записями. И, наконец, она сортирует индексы. Инструкция ALTER TABLE позволяет отсортировать записи таблицы. Это тоже способствует ускорению некоторых запросов, хотя и не устраняет потребность в индексах. Если таблица меняется редко, а дисковое пространство ограничено, имеет смысл сжать таблицу с помощью утилиты myismpack. После этого таблица будет доступна только для чтения. Ее индексы необходимо перестроить, вызвав утилиту myismchk. Данная методика позволяет уменьшить размер таблицы на 40-70%, в зависимости от формата ее содержимого. Влистинге 10.9 показан процесс сжатия таблицы, содержащей названия штатов США. # myisampack. exe state Compressing state. MYD: (50 records) - Calculating statistic - Compressing file 32.42% Remember to run myisamchk – rq on compressing tables # myisamchk – rq state - check key delete - chain - check records delete – chain - recovering (with sort) MyISAM – table ‘state.MYI’ Data records: 50 - Fixing index 1 - Fixing index 2 Листинг 10.9. (html, txt) Настройка конфигурации сервера Когда речь заходит об объеме оперативной памяти сервера, совет всегда один: чем больше — тем лучше. Увеличение объема памяти способствует ускорению работы программы MySQL, так как в оперативной памяти она хранит свои временные таблицы и буферы записей. В подкаталоге support files дистрибутива содержатся образцы конфигурационных файлов с различными вариантами настроек, касающихся использования памяти. Выберите тот вариант, который соответствует исходным параметрам сервера. Поработав с сервером какое-то время, можно будет оценить, какие из настроек требуют корректировки. В листинге 10.10 показана конфигурация сервера, располагающего как минимум 1 Гбайт ОЗУ, четырьмя жесткими дисками и четырьмя центральными процессорами. Обратите внимание на важность индексного буфера. В данной конфигурации предполагается, что сервер хранит табличные данные на первом диске, а временные файлы — на втором. Таблицы InnoDB находятся на третьем диске, а журналы InnoDB — на четвертом. [mysqld] set – variable = key buffer = 384M set – variable = max allowed packet = 1M set – variable = table cache = 512 set – variable = sort buffer = 2M set – variable = record buffer = 2M 103 set – variable = thread cache size = 8 set – variable = thread concurrency = 8 set – variable = myisam sort buffer size = 64M log – bin = server – id = 1 tmpdir = /disk2/tmp/ # Таблицы BDB set – variable = bdb cache size = 384M set – variable = bdb max lock = 100000 # Таблицы InnoDB innodb data home dir = /disk3/ innodb log group home dir = /gisk4/ innodb log arch dir = /disk4/ innodb data file path = ibdata1: 250M; ibdata2: 500M; ibdata3: 1000M set – variable = innodb mirrored log groups = 1 set – variable = innodb log files in groups = 3 set – variable = innodb log files size = 5M set – variable = innodb log buffer size = 8M innodb flush log at trx commit = 1 innodb log archive = 0 set – variable = innodb buffer pool size = 16M set – variable = innodb additional mem pool size = 2M set – variable = innodb file io threads = 4 set – variable = innodb lock wait timeout = 50 Листинг 10.10. (html, txt) Когда сервер проработает какое-то время, выполните инструкцию SHOW STATUS, чтобы узнать его производительность. Сравните значения показателей Key reads и Key_read_requests. Их соотношение будет очень низким, если программа MySQL часто пользуется индексным буфером. В случае необходимости попытайтесь повысить размер буфера. Проследите изменение показателя Open tables, сравнивая его со значением серверной переменной table cache, которое можно узнать с помощью инструкции SHOW VARIABLES. Когда табличный буфер заполняется, программа MySQL вынуждена закрывать одни таблицы, чтобы открывать другие. Показатель Opened tables отражает число таблиц, открывавшихся с момента запуска сервера. Сравните его с общим числом запросов (показатель Questions). Чем больше будет размер табличного буфера, тем реже придется открывать и закрывать таблицы. Серверная переменная thread_cache_size задает размер кэша потоков. Как правило, на каждый процессор должно приходиться два потока. Сравните показатели Threads_created и Connections, чтобы определить, как часто серверу приходилось повторно использовать потоки. Просмотрите еще раз список переменных демона mysqld. Есть много разных буферов и кэшей, увеличение размера которых способно повысить производительность сервера. После изменения конфигурации обязательно проведите повторные замеры. Перекомпиляция MySQL Команда разработчиков MySQL прилагает огромные усилия для оптимизации исполняемых файлов программы. Лучше всего пользоваться бинарными дистрибутивами, которые доступны на Web-узле 104 MySQL. Вряд ли вам удастся получить более качественный исполняемый файл. Например, в дистрибутивы Linux зачастую включаются нестабильные версии компиляторов и библиотек. Разработчики MySQL всегда применяют самые стабильные версии в сочетании с оптимальными опциями компиляции. Необходимость в компиляции возникает, когда для данной платформы невозможно найти скомпилированную версию программы, хотя эта ситуация маловероятна. Еще одна причина — желание поэкспериментировать с различными библиотеками. Но подобными экспериментами не стоит слишком увлекаться, так как в результате можно получить нестабильно работающий исполняемый файл. На Web-узле MySQL приведена информация о том, как компилировать программу на различных платформах. Не поленитесь просмотреть рекомендации специалистов, поскольку здесь есть много "подводных камней", особенно в случае старых операционных систем. Перед началом компиляции убедитесь в наличии утилит qzip и qnutar Они необходимы для извлечения файлов из tar-архива. Учтите, что версия утилиты tar для Solaris содержит ошибку, которая не позволяет распаковывать некоторые архивы, поэтому желательно иметь GNU-версию утилиты. Нужен также компилятор языка C++. Вполне подойдет eqcs. He забудьте и об утилите make. Те, кто имеют опыт компиляции программ с открытыми кодами, должны быть знакомы со сценариями конфигурации, создаваемыми утилитой autoconf. Саму ее запускать не нужно. Файл Makefile создается сценарием configure. В листинге 10.11 показан вызов этого сценария с установками, которые рекомендованы разработчиками MySQL. Сценарий configure должен запускаться из каталога, содержащего исходные коды программы. CFLAGS = "-03" \ CXX = gcc \ CXXFLAGS = "-03 –felide–constructors–fno–exceptions–fno-rtti" \ ./configure –prefix = /usr/local/mysql \ --enable-assembler \\ --with-mysql-ldflags=-all-atatic Листинг 10.11. (html, txt) Параметры сценария configure можно получить, вызвав сценарий с опцией –help. Если нужно включить поддержку таблиц Berkeley DB или InnoDB, не забудьте указать соответствующие опции. В исходные дистрибутивы MySQL входят все необходимые для этого файлы, по этому путь к библиотекам Berkeley DB задается только в том случае, когда требуется использовать их альтернативные версии. 105 ЛЕКЦИЯ 11. Безопасность Описание: В этой лекции основное внимание уделяется действиям администратора, направленным на поддержание безопасности и целостности инсталляции MySQL В лекции 2, "Общее администрирование MySQL", уже были затронуты такие важные аспекты безопасности, как установка пароля основного MySQL-пользователя root и настройка учетных записей пользователей. В этой лекции детально описываются следующие моменты. Почему безопасность так важна и от каких видов атак следует защищаться в первую очередь. Какой риск несет в себе подключение пользователей локального компьютера (внутренняя безопасность) и как его минимизировать. Какой риск несет в себе подключение пользователей к серверу через сеть (внешняя безопасность) и как его минимизировать. Администратор MySQL полностью отвечает за безопасность содержимого баз данных, поэтому должен позаботиться о том, чтобы доступ к их записям пользователи получали только после жесткой авторизации. Необходимо обеспечить как внутреннюю, так и внешнюю безопасность. Внутренняя безопасность связана с выполнением действий на уровне файловой системы. Она обеспечивает защиту каталога данных MySQL от атак пользователей, работающих на том же компьютере, на котором запущен сервер. Нет смысла долго настраивать таблицы разрешений, контролирующие доступ клиентов через сеть, если из-за неправильно установленных полномочий каталога данных любой локальный пользователь может заменить файлы этих таблиц. Внешняя безопасность предназначена для управления внешними клиентскими соединениями и соответственно, необходима для защиты доступа к серверу MySQL через сетевые соединения. Таблицы разрешений MySQL должны быть настроены таким образом, чтобы доступ к базам данных предоставлялся только после правильного ввода имени и пароля. В этой лекции рассматриваются все описанные выше вопросы, а также приведены инструкции, выполнение которых позволит заблокировать неавторизированный доступ как изнутри, так и извне системы. Внутренняя безопасность: защита доступа к каталогу данных Сервер MySQL включает гибкую систему привилегий, реализованную через таблицы разрешений базы данных mysql. Изменяя содержимое этих таблиц, можно предоставлять или запрещать доступ определенным клиентам. Именно таким образом обеспечивается защита от неавторизированного сетевого доступа к данным. Однако нет смысла тратить много времени и усилий на обеспечение надежной защиты баз данных от доступа сетевых пользователей, если локальный пользователь, работающий на компьютере с сервером наряду с администратором, сможет легко просматривать и изменять содержимое каталога данных. Этот вид защиты можно проигнорировать, лишь будучи полностью уверенным, что никто другой не сможет зарегистрироваться и работать на компьютере, используемом для запуска сервера MySQL Максимальную защиту необходимо обеспечить следующим категориям. Файлы базы данных. Очевидно, что необходимо постоянно поддерживать закрытость баз данных сервера. Владельцы баз данных обычно вполне обоснованно полагают, что содержимое их баз данных закрыто для других пользователей. Даже если они так не считают, все равно не стоит выставлять информацию на всеобщее обозрение или делать ее открытой из-за плохой защиты каталога данных. 106 Учетные файлы. Файлы общего журнала и журнала обновлений также должны быть надежно защищены, поскольку они включают тексты запросов. Ведь любой пользователь, обладающий доступом к файлам журналов, сможет легко отследить все транзакции с базами данных. Важность подобной защиты еще более подчеркивается тем фактом, что в файлах журналов регистрируются даже запросы с операторами grant и SET password, включающие пароли. (Вообще-то, в MySQL используется шифрование паролей, однако оно применяется только после установления соединения с предварительной проверкой пароля. Процесс же установки пароля включает выполнение таких операторов, как GRANT, INSERT и SET PASSWORD. В файлы журналов они заносятся в обычной текстовой форме.) Взломщику, получившему доступ к файлам журналов, достаточно запустить команду grep, чтобы раскрыть важную информацию операторов grant и password. Не следует предоставлять пользователям компьютера, на котором установлен сервер, права чтения для файлов каталога данных, поскольку они могут легко повредить файлы состояния и таблицы баз данных. Не менее опасен и доступ с правами чтения. Обладая возможностью чтения файлов таблицы, очень легко "украсть" эти файлы и позволить другому серверу MySQL самому показать содержимое таблицы в виде простого текста. Как? Да очень просто. 1. Проинсталлируйте собственную версию MySQL на компьютере с сервером, установив отдельные значения порта, разъема и каталога данных. 2. Запустите сценарий mysql_install_db для инициализации каталога данных. Это позволит получить доступ к серверу в качестве MySQL-пользователя root, получив полный контроль над механизмом доступа. Параллельно будет создана база данных test. 3. Скопируйте файлы, соответствующие "украденной" таблице или таблицам в подкаталог test каталога данных сервера. 4. Запустите второй сервер. Вот те на! Доступ к таблицам открыт. Оператор show tables from test указывает на наличие копий "украденных" таблиц, а с помощью оператора SELECT * можно увидеть их содержимое. 5. Очень "злые" пользователи могут изменить полномочия учетной записи анонимного пользователя сервера, в результате чего к серверу для доступа к базе данных test сможет подключиться любой. В результате этих нехитрых действий содержимое украденных таблиц становится открытым для всех. Задумайтесь об этом. Вне всяких сомнений, ни один администратор не захочет столкнуться с такой ситуацией. Для определения, расположены ли в каталоге данных какие-либо незащищенные файлы и подкаталоги, достаточно запустить в нем команду ls -1. Найдите все файлы и каталоги, для которых активизированы "групповые" или "другие" полномочия. Вот для примера краткий список незащищенных элементов каталога данных, среди которых встречаются и подкаталоги баз данных. % ls -1 total 10148 drwxrwxr-x 11 mysqladm wheel 1024 May 8 12:20 . drwxr-xr-x 22 root wheel 512 May 8 13:31 .. drwx------ 2 mysqladm mysqlgrp 512 Apr 16 15:57 menagerle drwxrwxr-x 2 mysqladm wheel 512 Jan 25 20:43 mysql drwxrwxr-x 7 mysqladm wheel 512 Aug 31 1998 sql-bench drwxrwxr-x 2 mysqladm wheel 1536 May 6 06:11 test drwx------ 2 mysqladm wheel 1024 May 8 18:43 tmp 107 Как видите, для доступа к одним каталогам используются правильные полномочия, для других — нет. Такая ситуация стала результатом использования сервера в течение долгого периода времени. Менее ограничивающие полномочия созданы более старыми версиями серверов, которые были менее жестки в отношении прав доступа, чем новые. (Обратите внимание, что наиболее ограничивающие доступ каталоги menagerie и tmp имеют более позднее время создания.) Последние версии MySQL обязательно проверят, чтобы эти файлы смогли прочитать только пользователи, под именем которых работает сервер. Давайте попробуем настроить эти полномочия, чтобы доступ к файлам мог получить только пользователь сервера. Для этого можно воспользоваться средствами защиты файловой системы UNIX и определить права владения и режим данных файлов и каталогов. Выполните следующие действия. 1. Перейдите в каталог данных: 2. % cd DATADIR 3. Присвойте права владения всеми файлами каталога данных одной учетной записи, под управлением которой запускается сервер. (Эту операцию необходимо выполнить, зарегистрировавшись в качестве пользователя root.) В данном пособии для такой учетной записи используются имя пользователя mysqladm и группы mysqlgrp. Изменить права владения можно с помощью одной из следующих команд: 4. # chown -R mysqladm.mysqlgrp . 5. # find . -follow -type d -print|xargs chown mysqladm.mysqlgrp 6. Измените режим доступа к каталогу данных и каталогам баз данных, чтобы прочитать их смог только пользовательmysqladm. В результате этого доступ к каталогу данных не смогут получить другие пользователи. Изменить режим можно с помощью одной из приведенных ниже команд, зарегистрировавшись в качестве пользователя root или mysqladm(последнее предпочтительней, поскольку позволяет минимизировать число команд, запущенных пользователем root): 7. % chmod -R go-rwx 8. % find . -follow -type d -print | xargs chmod go-rwx 9. Теперь права владения и режим содержимого каталога данных присвоены пользователю mysqladm. Осталось убедиться, что сервер отныне будет запускаться в качестве пользователя mysqladm, поскольку только этот пользователь имеет доступ к каталогу данных. Процедура запуска сервера в качестве нового пользователя (не root) детально описана в лекции 2,"Общее администрирование MySQL". После выполнения всех описанных выше действий остается лишь убедиться в правильности установки полномочий для доступа к каталогу данных. % ls -1 total 10148 drwxrwxr-x 11 mysqladm wheel 1024 May 8 12:20 . drwxr-xr-x 22 root wheel 512 May 8 13:31 .. drwx------ 2 mysqladm mysqlgrp 512 Apr 16 15:57 menagerle drwxrwxr-x 2 mysqladm wheel 512 Jan 25 20:43 mysql drwxrwxr-x 7 mysqladm wheel 512 Aug 31 1998 sql-bench drwxrwxr-x 2 mysqladm wheel 1536 May 6 06:11 test drwx------ 2 mysqladm wheel 1024 May 8 18:43 tmp ... Внешняя безопасность: защита сетевого доступа 108 Система безопасности MySQL достаточно гибка, поскольку позволяет настроить привилегии доступа пользователей множеством различных способов. Как правило, установка привилегий реализуется с помощью операторов GRANT и revoke, которые изменяют таблицы разрешений, управляющие клиентским доступом. Некоторые администраторы, тем не менее, все еще используют старые версии MySQL, которые не поддерживают эти операторы (до версии MySQL 3.22.11). Иногда также администраторы замечают, что при установке с помощью операторов GRANT и REVOKE привилегии функционируют не так, как хотелось бы. В подобных ситуациях весьма полезным может оказаться знание таблиц разрешений MySQL и принципов использования их сервером для определения полномочий. Владеющий подобными знаниями администратор может добавлять, удалять или изменять привилегии пользователей посредством изменения собственно таблиц разрешений. Более того, исследование таблиц позволяет гораздо быстрей диагностировать проблемы, связанные с доступом. Автор предполагает, что читатель уже ознакомился с материалом лекции 3 "Управление пользовательскими учетными записями", лекции 2 "Общее администрирование MySQL" и разобрался в принципах работы операторов grant и revoke. Их применение — удобный способ установки пользовательских учетных записей MySQL и связанных с ними привилегий. Но эти операторы являют собой лишь оболочку. Реальные действия выполняются в таблицах разрешений сервера MySQL. Структура и содержимое таблиц разрешений MySQL Управление доступом к базам данных MySQL для клиентов, подключившихся к серверу через сеть, осуществляется с помощью содержимого таблиц разрешений. Эти таблицы входят в состав базы данных mysql и инициализируются в процессе инсталляции MySQL на компьютере. В табл. 1 и 2 представлено краткое описание структур пяти таблиц разрешений: user, db, host, tables_priv И columns_priv. Таблица 1. Структура таблиц разрешений user, dbи host Столбцы области доступа user db host host host host user db db password user Столбцы привилегий базы данных / таблицы Alter priv Alter priv Alter priv Create priv Create priv Create priv Delete priv Delete priv Delete priv Drop priv Drop priv Drop priv Index priv Index priv Index priv Insert priv Insert priv Insert priv References priv References priv References priv Select priv Select priv Select priv Update priv Update priv Update priv Столбцы административных привилегий File priv Grant priv Grant priv 109 Grant priv Process priv Reload priv Shutdown priv Таблица 2. Структура таблиц привилегий tables privt и columns privt Столбцы области доступа Tables priv columns priv Host Host Db Db User User Table name Table name Column name Столбец привилегий Table priv Column priv Таблицы разрешений содержат следующую информацию. user. Таблица user содержит список всех пользователей, которые могут подключаться к серверу, а также их пароли и все глобальные привилегии, если таковые применяются. Все указанные в этой таблице привилегии являются глобальными и применимы ко всем базам данных. Так, например, если активизировать в этой таблице привилегию delete, соответствующий пользователь сможет удалить записи из любой таблицы. Следовательно, необходимо тщательно все обдумать, прежде чем присваивать такую привилегию. db. Таблица db содержит список всех баз данных и пользователей, обладающих полномочиями на доступ к ним. Определенные в этой таблице привилегии применимы ко всем таблицам соответствующей базы данных. host. Таблица host применяется вместе с таблицей db и определяет привилегии доступа к базам данных определенного компьютера. Уровень этого контроля более высокий, чем при использовании одной лишь таблицы db. Операторы GRANT иREVOKE не могут изменять содержимое этой таблицы, поэтому на некоторых компьютерах она вообще не используется. tables_priv. Таблица tables_priv определяет привилегии доступа к таблицам. Эти привилегии применимы ко всем столбцам определенной таблицы. columns_priv. Таблица columns_priv определяет привилегии доступа к столбцам. Эти привилегии применимы к отдельным столбцам соответствующей таблицы. В расположенном далее пункте "Установка пользователей без помощи оператора GRANT" рассказывается, как оператор grant изменяет информацию этих таблиц и как с помощью непосредственного редактирования аналогичных результатов может достичь администратор. Таблицы tablespriv и columspriv впервые появились в MySQL версии 3.22.11 (вместе с оператором grant). Поэтому администраторы старых версий MySQL могут найти в базе данных mysql своего сервера только таблицы user, db и host. Если же эти таблицы не появляются даже после обновления до версии 3.22.11 или более поздней, запустите для их создания сценарийmysql_fix_privileges_tables. Отсутствие таблицы rowpriv объясняется невозможностью предоставления в MySQL привилегий на уровне строк. Нельзя, например, предоставить пользователю доступ только к отдельным строкам таблицы. Обеспечить подобную возможность реально можно только посредством написания 110 соответствующей программы. Для блокировки данных на уровне записей можно использовать функцию get_lock(). Таблицы разрешений содержат столбцы двух видов: столбцы области, определяющие область применения записи, и столбцы привилегий, определяющие присваиваемые привилегии. (Некоторые таблицы разрешений включают и другого рода столбцы, однако здесь они не рассматриваются.) Столбцы области применения таблицы разрешений Столбцы области применения таблицы разрешений определяют, когда же применяются записи таблиц. Каждый элемент таблицы разрешений включает значения столбцов User и Host. Эти значения определяют, что данный элемент применяется при подключении определенного пользователя (User) к конкретному компьютеру (Host). (Таблица Host является исключением в этом отношении. Она используется особым способом, который в данной лекции не рассматривается.) Кроме того, другие таблицы могут содержать дополнительные столбцы. Таблица db, например, включает также столбец Db, определяющий базу данных, к которой применяется запись. Аналогичным образом таблицы tables_priv и columns_priv содержат поля области, которые ограничивают область применения записи до отдельной таблицы базы данных или отдельного столбца таблицы. Столбцы привилегий таблицы разрешений Таблицы разрешений включают также столбцы привилегий. Именно они определяют, какие привилегии предоставляются описанному в столбцах области пользователю. Поддерживаемые сервером MySQL привилегии приведены в списке, представленном ниже. В этом списке указываются названия привилегий, используемые в строке оператора GRANT. В большинстве случаев названия столбцов привилегий таблиц user, db и host сходны (по очевидным причинам) с названиями привилегий. Столбец Select_priv, например, соответствует привилегии SELECT. Привилегии баз данных и таблиц Для работы с базами данных и таблицами применяются следующие привилегии. ALTER. Позволяет использовать оператор alter table. Вообще, ALTER — это привилегия первого уровня. Для обработки таблиц необходимо предоставить дополнительные привилегии в зависимости от того, какие операции необходимо выполнять. create. Позволяет создавать базы данных и таблицы, но не индексы. DELETE. Позволяет удалять записи из таблиц. DROP. Позволяет удалять таблицы и базы данных, но не индексы. INDEX. Позволяет создавать и удалять индексы в таблице. INSERT. Позволяет вставлять новые записи в таблицы. REFERENCES. В настоящее время не используется. SELECT. Позволяет извлекать данные из таблиц с помощью операторов select. Эту привилегию необязательно присваивать для исполнения операторов select, не связанных с таблицами, например, SELECT NOW() ИЛИ SELECT 4/2 UPDATE. Позволяет изменять записи таблицы. Административные привилегии 111 Следующие привилегии позволяют выполнять административные операции, управляющие функционированием сервера или дающие возможность присваивать привилегии другим пользователям. FILE. Позволяет давать серверу задание на считывание или запись файлов. Эту привилегию рекомендуется присваивать лишь в особых случаях. Поэтому сервер также предпринимает определенные меры предосторожности, позволяющие установить границы применения этой привилегии. Так, пользователи могут считывать файлы, которые доступны для чтения во всей системе. Невозможно записать файл, который уже существует на диске. Это позволяет избегать путаницы с критически важными файлами сервера, например /etc/passwd, или файлами чужих баз данных. Отсутствие подобного ограничения может привести к полной замене содержимого таблиц разрешений базы данных mysql. Присваивая привилегию file, следует обязательно убедиться, что запущенный сервер не обладает правами UNIX-пользователя root, который может создавать новые файлы в любом каталоге файловой системы. При запуске сервера под управлением учетной записи пользователя без особых привилегий создавать файлы можно будет только в доступных для такого пользователя каталогах. GRANT. Позволяет предоставить другому пользователю привилегии, имеющиеся у администратора, включая саму возможность присвоения привилегий. PROCESS. Позволяет просматривать информацию о выполняемых внутри сервера нитях (процессах) с помощью оператора SHOW PROCESSLIST или команды mysqladmin processlist. Эта же привилегия позволяет завершить выполнение процесса с помощью оператора KILL или команды mysqladmin kill. Наличие этой привилегии позволяет пользователям просматривать и завершать выполнение любых процессов, включая свои собственные. reload. Позволяет выполнять множество операций администрирования сервера, например запускать SQL-оператор FLUSHили выполнять такие mysqladmin-команды, как reload, refresh, flush-hosts, flush-logs, flush-privileges и flush-tables. Даже несмотря на административные функции, эта привилегия не является опасной. shutdown. Позволяет завершать работу сервера с помощью команды mysqladmin shutdown. В таблицах user, db и host каждая привилегия определена в отдельном столбце. Все эти столбцы описаны типом ENUMC"N", "Y", и по умолчанию каждая привилегия имеет значение "n" (отключена). Привилегии таблиц tables_priv и column_privпредставлены с помощью типа set, благодаря чему привилегии могут определяться различными комбинациями в одном столбце. Более эффективное представление привилегий в последних двух таблицах объясняется тем, что они появились гогораздо позже, чем первые три. (Вполне возможно, что в будущем таблицы user, db и host будут реорганизованы и привилегии в них будут задаваться с помощью типа set.) Например, столбец Table_priv таблицы tables_priv определяется следующим образом: SET('Select','Insert','Update','Delete','Create', 'Drop','Grant', 'Reference','Index','Alter') Столбец Column_priv таблицы column_priv определяется так: SET ('Select' , 'Insert','Update','Reference') 112 Привилегий столбцов гораздо меньше, чем привилегий таблиц, поскольку на уровне столбца можно выполнить гораздо меньше операций. Так, например, можно создать новую таблицу, но невозможно создать отдельный столбец. Таблица user, помимо всего прочего, содержит несколько привилегий, которые отсутствуют во всех других таблицах разрешений:File priv, Process priv, Reload_priv и Shutdown_priv. Эти привилегии применяются к выполняемым сервером операциям, не связанным с отдельной базой данных или таблицей. Ведь при необходимости завершения работы сервера вовсе не обязательно проверять, над какой базой данных в настоящее время ведется работа. Как сервер управляет доступом клиентов Сервер MySQL выполняет контроль за доступом клиентов в два этапа. Первый этап происходит при попытке подключения, когда сервер "заглядывает" в таблицу user и ищет все соответствующие этому имени записи, например, название компьютера, с которого можно подключаться, и пароль. Если ни одна запись с аналогичными значениями не найдена, пользователю отказывается в подключении. Если же вся предоставленная пользователем информация соответствует информации, записанной в таблице, соединение устанавливается и сервер переходит ко второму этапу. В процессе этого этапа каждый раз при получении от пользователя запроса сервер обращается к таблицам разрешений и проверяет, обладает ли пользователь достаточными привилегиями для выполнения того или иного запроса. Второй этап продолжается до завершения сеанса работы с сервером. Далее рассмотрим описание правил, используемых сервером MySQL для проверки соответствия записей таблиц разрешений с входящими запросами клиента. Описываются типы значений, применяемые в столбцах области таблиц разрешений, способы комбинирования информации; рассказывается о привилегиях в таблицах разрешений и порядке проверки записей таблицы. Содержимое столбцов области доступа В некоторых столбцах области необходимо вводить буквенные значения, однако в большинстве из них можно использовать также специальные символы. Host. Значение столбца Host может представлять собой имя компьютера или его IP-адрес. Значение localhost соответствует локальному компьютеру, однако рекомендуется использовать его только в том случае, если данный компьютер действительно имеет имяlocalhost. Представим ситуацию, когда локальный компьютер имеет имя pit.viper.snakeи для одного пользователя имеется две записи в таблице user. Одна запись в столбце Hostимеет значение localhost, а вторая — pitviper.snake.net. Первая запись будет использоваться только при подключении к компьютеру localhost, а вторая — к компьютеруpit-viper.snake.net. Если необходимо, чтобы пользователи имели возможность подключиться с помощью любого из этих способов, следует оставить обе эти записи в таблице user. Значения столбца Host также можно задать с помощью шаблона. Так, можно использовать распространенные в SQL символы "%" и "_", имеющие такое же значение, как и в строке запроса с оператором like. (REGEX-шаблоны для этих целей неприменимы.) Символы шаблона SQL можно применять при определении как имен, так и IP-адресов. Строке%.wisc.edu, например, соответствуют все компьютеры домена wisc.edu, а строке %.edu — компьютеры всех подключенных к сети организаций системы образования. Аналогичным образом, строка 192.168.% описывает все компьютеры подсети класса В 192.168, а строка 192.168.3.% — все компьютеры подсети класса С 192.168.3. 113 Значение "%" определяет все компьютеры и дает возможность пользователю подключиться из любой точки. Пустое значение столбца Host аналогично значению "!". (Исключение: в таблице db пустое значение столбца Host указывает на необходимость проверки таблицы host для получения более детальной информации) В версиях MySQL серии 3.23 можно также определить числа IP-адресов с помощью маски сети, отражающей разрядность сетевого номера. Строка 192.168.128.0/17, например, определяет 17 разрядный сетевой номер. Ей соответствует любой компьютер, первые 17 разрядов IP-адреса которого аналогичны разрядам адреса 192 .168 .128. User. Имена пользователей могут задаваться буквенными или пустыми значениями. В последнем случае сможет подключиться любой пользователь. Значение "%" и пустое значение в столбце User — это не одно и то же. Оно соответствует пользователю с именем "%". Надо признать, такое имя встречается довольно редко. Если при проверке входящего соединения пользователю соответствует в таблице User запись с пустым значением столбцаUser, данный клиент рассматривается как анонимный. Password. Значения этого столбца могут быть либо пустыми, либо буквенными. Специальные символы в них использовать нельзя. Пустое значение не является аналогией "любого пароля". Когда в таблице определено пустое значение столбцаPassword, пользователь не должен определять пароль вовсе. Значения паролей хранятся в зашифрованном, а не в обычном текстовом виде. Пользователи не смогут подключиться к серверу, если в столбец Password записываются обычные текстовые значения! Оператор GRANT и команда mysqladmin password автоматически шифруют пароль. Поэтому при непосредственной записи паролей с помощью команд INSERT, replace, update и set password следует зашифровать их значения с помощью команды PASSWORD("new_password") . Db. Значения столбца Db в таблицах columns_priv и tables_priv обязательно должны представлять собой текстовые имена баз данных. Использование специальных символов и пустых значений запрещается. В таблицах db и host эти значения можно определить как в виде текстовых значений, так и с помощью SQL-символов "%" и "_". Пустое значение и значение %позволяют получить доступ к любой базе данных. Table_name, Column_name. Значения этих столбцов представляют собой текстовые записи имен таблиц и столбцов. Использование специальных символов и пустых значений запрещается. Регистр символов в некоторых столбцах области играет важное значение, а в остальных столбцах значения могут быть записаны как строчными, так и прописными буквами. Регистры символов в таких столбцах воспринимаются сервером по-разному. Это показано в табл. 3. Необходимо заметить, что регистр значений столбца Table_name всегда имеет значение, хотя учет регистра в именах таблиц в запросах зависит от файловой системы, под управлением которой работает сервер (под управлением UNIX выбор регистра важен, а под управлением Windows — нет). Таблица 3. Учет регистра в столбцах области таблиц разрешений Столбец Учет регистра Host нет User да 114 Password Db Table name Column name да да да нет Проверка запроса Каждый раз при получении запроса сервер проверяет в таблицах разрешений, обладает ли отправивший запрос пользователь достаточными полномочиями для его исполнения. Для этих целей таблицы user, db, tables_priv и column_priv просматриваются в установленном порядке до тех пор, пока не будет определено, что доступ разрешен, либо не будут проверены все таблицы разрешений. Более подробно этот процесс выглядит следующим образом. 1. При первоначальном подключении сервер проверяет записи таблицы user, пытаясь определить глобальные привилегии подключающегося пользователя. Если таковые имеются и, более того, являются достаточными для выполнения запроса, сервер обрабатывает запрос. 2. Если имеющихся глобальных привилегий недостаточно, сервер ищет дополнительные привилегии в таблице db. Если найденные привилегии позволяют выполнить запрос, сервер его обрабатывает. Как хранятся пароли в таблице user Пароли представлены в этой таблице в виде зашифрованных строк, поэтому узнать их не может даже пользователь, имеющий права доступа к этой таблице. Довольно широко распространено мнение, что функция password () применяет методы кодирования, используемые и для шифрования паролей UNIX, однако оно ошибочно. Эти два способа кодирования действительно подобны в том отношении, что являются односторонними, т.е. необратимыми. Однако сервер MySQL использует иной алгоритм шифрования, чем UNIX. Это означает, что даже если UNIX-пароль является одновременно и паролем MySQL, зашифрованные строки пароля совпадать не будут. Чтобы использовать для приложения средства шифрования UNIX, вместо password запустите функцию CRYPT() . 1. Если набора глобальных привилегий и привилегий баз данных недостаточно, сервер продолжает поиск сначала в таблицеtables_priv, a потом и в columns_priv. 2. Если после проверки всех таблиц разрешений достаточных полномочий не найдено, сервер отклоняет попытку выполнения запроса. Говоря на языке булевой алгебры, привилегии таблиц разрешений используются сервером следующим образом: user OR db OR tables_priv OR columns_priv Некоторые читатели уже, возможно, задаются вопросом, почему в этой записи указывается четыре таблицы разрешений, хотя на самом деле их пять. Совершенно верно. Правильней было бы переписать ее следующим образом: user OR (db AND host) OR tables_pnv OR columns_priv Упрощенный вариант был представлен исключительно для того, чтобы показать, что таблица host не подвержена влиянию операторов grant и REVOKE. Администраторы, управляющие привилегиями пользователей с помощью операторов grant и revoke, могут забыть о таблице host по следующим причинам. 115 Проверяя привилегии уровня базы данных, сервер ищет запись для клиента в таблице db. Пустое значение столбца Host означает примерно следующее: проверьте таблицу host, чтобы определить, какие компьютеры могут получать доступ к базе данных. Сервер ищет в таблице host записи с таким же значением столбца Db, как и в записи таблицы db. Если компьютер подключающегося клиента не указан ни в одной записи таблицы host, то, следовательно, привилегии для работы с таблицами этому пользователю не предоставлены. Если значение столбца Host хотя бы одной записи этой таблицы соответствует компьютеру подключающегося пользователя, записи таблиц db и host объединяются, что приводит к определению реальных привилегий уровня баз данных клиента. Привилегии объединяются посредством логического оператора and. Это означает, что пользователь будет иметь привилегии только в том случае, когда записи о нем будут представлены в обеих таблицах. Таким образом, пользователю может присваиваться базовый набор привилегий в записи таблицы db. Согласно записям таблицы host, получить их можно будет только с определенных компьютеров. Так, например, можно предоставить доступ к базам данных со всех компьютеров домена, но убрать эти привилегии для пользователей компьютеров, расположенных в менее защищенной области. Из всего этого можно сделать вывод, что проверка привилегий — достаточно сложный процесс, особенно если учесть, что сервер проверяет привилегии при каждом получении запроса. Однако, на самом деле реализуется он весьма быстро, поскольку сервер не ищет информацию в таблицах разрешений для каждого запроса. Вместо этого содержимое таблиц записывается в память при загрузке, а данные затем быстро проверяются с помощью занесенных в память копий. Такая организация работы повышает производительность операций проверки доступа, хотя имеет и обратную сторону "медали" — сервер не замечает изменения привилегий при непосредственном изменении таблиц разрешений. Например, если новый пользователь создается администратором путем добавления новой записи в таблицу user с помощью оператора insert, он не сможет сразу же подключиться к серверу. Начинающих администраторов (а иногда и вполне опытных) это зачастую весьма сильно раздражает, хотя решение этой проблемы предельно просто: достаточно указать серверу перезагрузить таблицы разрешений сразу после внесения изменений. Это можно осуществить с помощью оператора FLUSH PRIVILEGES или команды mysqladmin flushprivileges (либо mysqladmin reload, если используется более старая версия, не поддерживающая flush-privileges). Порядок сравнения столбцов Сервер MySQL сортирует записи таблиц разрешений в определенном порядке, а затем, согласно этому порядку, ищет соответствующие соединениям данные. Важно понимать, в каком порядке записи располагаются сервером MySQL, особенно в таблице user. Считывая содержимое таблицы user, сервер сортирует ее записи, согласно значениям столбцов Host и User. Доминирующую роль здесь играет значение столбца Host (т.е. записи с одинаковыми значениями столбца Host размещаются рядом, а затем упорядочиваются по значению User). Однако выполняемая сортировка не является лексикографической, или, скорее, является таковой лишь частично. Основной принцип — более высокий приоритет символьных значений по сравнению со специальными символами. Это означает, что если пользователь подключается к компьютеру boa.snake.net, а в таблице имеются записи со значениями boa.snake.net и %.snake.net, то будет выбрана именно первая запись. Аналогичным образом, значение %.snake.net имеет больший приоритет, чем %.net, которое, в свою очередь, более 116 приоритетно, чем %. Точно так же обрабатываются и IP-адреса. Порядок приоритетности значений для пользователя, подключающегося с компьютера с IP-адресом 192.168.3.14, будет выглядеть следующим образом: 192.168.3.14, 192.168.3.%, 192.168.%, 192.% и %. Как минимизировать риск при работе с таблицами разрешений Ниже приведены некоторые рекомендации, которые следует учитывать при присвоении привилегий, а также описываются проблемы, связанные с неправильным выбором администратора. Для начала необходимо весьма аккуратно присваивать глобальные привилегии суперпользователей. Другими словами, не следует активизировать привилегии в записях таблицы user. Используйте с этой целью другие таблицы, чтобы ограничить область применения привилегий отдельными базами данных, таблицами и столбцами. Привилегии таблицы user позволяют воздействовать на функционирование всего сервера и получать доступ ко всем таблицам любой базы данных Не предоставляйте никаких привилегий для доступа к базе данных mysql. Ведь пользователь, обладающий привилегиями доступа к базе данных с таблицами разрешений, может легко изменить свои привилегии и получить таким образом доступ и к другим базам данных. Присвоение пользователю достаточных привилегий для изменения таблиц базы данных mysql дает такому пользователю и привилегию GRANT. Возможность непосредственного изменения таблицы практически равноценна возможности запуска оператора grant. Привилегию FILE также рекомендуется присваивать с большой осторожностью. Так, обладающий этой привилегией пользователь может запросто выполнить следующие операторы: CREATE TABLE etc_passwd (pwd_entry TEXT); LOAD DATA INFILE "/etc/passwd" INTO TABLE etc_passwd; SELECT * FROM etc_passwd; Выполнив эти операторы, пользователь получит содержимое файла паролей. Фактически, наличие привилегии FILE дает возможность пользователю раскрыть содержимое любого читаемого файла сервера, даже работая через сеть. Кроме того, привилегия FILE может использоваться для повреждения баз данных в системах, работающих с недостаточными файловыми правами. Именно поэтому администратор должен сделать содержимое каталога данных читаемым только для сервера. Если файлы таблиц баз данных открыты для всеобщего обзора, прочитать их сможет не только пользователь учетной записи сервера, но и любой другой пользователь, обладающий привилегией FILE и подключающийся к серверу через сеть. Как это реализуется, показано на следующем примере. Создайте таблицу со столбцом LONGBLOB. USE test CREATE TABLE tmp (b LONGBLOB) Используйте таблицу для записи содержимого файла всех нужных таблиц, а затем запишите это содержимое в файл своей базы данных. LOAD DATA INFILE "./other_db/x.frm" INTO TABLE tmp FIELDS ESCAPED BY " LINES TERMINATED BY " SELECT * FROM tmp INTO OUTFILE "y.frm" FIELDS ESCAPED BY " LINES TERMINATED BY " DELETE FROM tmp LOAD DATA INFILE "./other_db/x.ISD" INTO TABLE tmp FIELDS ESCAPED BY " LINES TERMINATED BY " SELECT * FROM tmp INTO OUTFILE "y.ISD" 117 FIELDS ESCAPED BY " LINES TERMINATED BY " DELETE FROM tmp LOAD DATA INFILE "./other_db/x.ISM" INTO TABLE tmp FIELDS ESCAPED BY " LINES TERMINATED BY " SELECT * FROM tmp INTO OUTFILE "y.ISM" FIELDS ESCAPED BY " LINES TERMINATED BY " В результате создана новая таблица, содержащая информацию таблицы other_db.x, к которой имеется полный доступ. Чтобы избежать подобных атак, установите права доступа к содержимому каталога данных в соответствии с инструкциями, представленными в пункте "Внутренняя безопасность: защита доступа к каталогу данных". Можно также при запуске сервера использовать опцию —skip-showdatabase. Это запретит пользователям запускать операторы SHOW database и show tables для баз данных, к которым им запрещен доступ, и не позволит пользователям случайно найти базу данных или таблицу, доступ к которым им не должен предоставляться. Иногда и привилегия ALTER используется таким образом, о котором даже и не подозревают администраторы. Предположим, например, что администратор желает предоставить пользователю userl доступ к таблице tablel, но не к таблице table2. Обладающий привилегией alter пользователь может легко обойти это ограничение, переименовав с помощью оператора ALTER TABLE таблицу table2 в tablel. Проявляйте осторожность и с привилегией GRANT. Два пользователя, обладающие разными привилегиями, могут легко расширить круг возможностей друг друга. Установка пользователей без помощи оператора grant Администраторы MySQL, работающие с версиями до 3.22.11, не могут использовать операторы GRANT (или revoke) для создания пользователей и настройки привилегий доступа. Для достижения тех же целей они могут непосредственно изменять содержимоетаблиц разрешений. Гораздо проще это сделать тем администраторам, которые знают, каким образом оператор GRANT изменяет таблицы разрешений. По сути, те же операции можно выполнять и самостоятельно, применяя операторы insert. (Другое дело, что оператор INSERT может быть достаточно неудобным и трудно используемым. Именно этим и объясняется зачастую упрощенное применение grant.) В строке оператора grant определяется имя пользователя, имя компьютера и иногда пароль. В таблице user для пользователя создается запись и соответствующие значения записываются в столбцы User. Host и Password. Если администратор определяет какие-либо глобальные привилегии в операторе GRANT, они записываются в столбец привилегий записи. Однако следует помнить, что оператор grant шифрует записываемый пароль, а оператор insert — нет. Поэтому при настройке пользователей с помощью операторовinsert необходимо применять функцию password (). При определении привилегий уровня базы данных имя пользователя и компьютера заносятся соответственно в столбцы User и Host таблицы db. Имя таблицы, к которой предоставляются привилегии, записывается в столбец Db, а сами привилегии — в столбец привилегий. Подобные операции выполняются и при определении полномочий уровня таблиц и столбцов. Для записи имени пользователя, компьютера, названия базы данных и, если необходимо, имени таблицы или столбца заносятся соответствующие значения в поля таблиц tables__priv и columns_priv. Присваиваемые привилегии записываются в столбцы привилегий. 118 Все описанные выше операции можно выполнить и не прибегая к помощи оператора GRANT. He забывайте также, что после непосредственного изменения таблиц разрешений необходимо указать серверу перезагрузить их. Иначе изменения окажутся незамеченными. Для повторной загрузки можно запустить команду mysqladmin flush-privileges или mysqladmin reload. Представленный ниже оператор GRANT создает суперпользователя со всеми привилегиями, включая возможность наделения привилегиями других пользователей: GRANT ALL ON *.* ТО ethel@localhost IDENTIFIED BY "coffee" WITH GRANT OPTION Этот оператор создает запись для компьютера ethel@localhost в таблице user и активизирует для нее все привилегии. Те же привилегии можно присвоить и с помощью оператора insert: INSERT INTO user VALUES ("localhost","ethel", PASSWORD("coffee"), "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y") И это только один оператор insert! Более того, в зависимости от используемой версии MySQL, он может еще и не работать. Если структура таблиц разрешений была случайно изменена, число столбцов привилегий может не равняться четырнадцати. Чтобы проверить количество столбцов в каждой таблице разрешений, воспользуйтесь оператором SHOW COLUMNS, а затем соответствующим образом измените операторы insert. Следующий оператор GRANT также создает пользователя со статусом суперпользователей, однако только для одной привилегии: GRANT RELOAD ON *.* ТО flush@localhost IDENTIFIED BY "flushpass" Этот оператор уже рассматривался в лекции 2, "Общее администрирование MySQL", когда речь шла о создании пользователяflush. Равноценный предыдущей строке оператор insert в этом примере не такой сложный, как в предыдущем. Ведь гораздо проще указать имена столбцов и определить значение только в одном столбце привилегий. Во всех других столбцах по умолчанию будет установлено значение "n": INSERT INTO user (Host, User, Password, Reload priv) VALUES("localhost", "flush", PASSWORD("flushpass") , "Y") Привилегии уровня базы данных присваиваются с помощью предложения ON db_name, а не ON *.*: GRANT ALL ON samp_db.* TO boris@localhost IDENTIFIED BY "ruby" Эти привилегии не являются глобальными, поэтому их не следует записывать в таблицу user. Запись в этой таблице создать нужно (чтобы пользователь смог подключиться), однако для определения привилегий доступа к базе данных необходимо создать запись также и в таблице db: INSERT INTO user (Host, User, Password) VALUES("localhost", "boris", PASSWORD("ruby")) INSERT INTO db VALUES("localhost", "samp_db", "boris", "Y","Y","Y","Y","Y","Y","N","Y","Y", "Y" 119 Столбец со значением "N" соответствует привилегии GRANT. Для оператора grant уровня базы данных с окончанием WITH GRANT option в этом столбце можно установить значение "у". Настройка привилегий уровня таблицы и столбца осуществляется посредством выполнения оператора INSERT для таблиц tables priv и columnspriv. Безусловно, если версия MySQL не включает оператор GRANT, то она не включает и эти таблицы, поскольку появились они одновременно. Если же администратор по определенным причинам желает манипулировать данными таблицtables priv и columns priv без помощи оператора grant, он должен проявлять осторожность, поскольку невозможно активизировать привилегии в отдельных столбцах. Необходимо установить в одном из столбцов tables priv. Tables priv илиcolumns priv. Column_priv значение SET, состоящее из активизируемых привилегий. Например, чтобы предоставить пользователю привилегии SELECT и INSERT для таблицы, установите в столбце Table priv соответствующей записи таблицыtables priv значение "Select, Insert". Для изменения привилегий пользователей, уже имеющих учетную запись MySQL вместо insert, используется команда update. Ее можно применять как для добавления, так и для удаления привилегий. Для полного удаления пользователя и всех его привилегий удалите с помощью команды DELETE его записи изо всех таблиц разрешений. Если администратор желает избежать непосредственного изменении таблиц разрешений, можно воспользоваться сценариямиmysqlaccess и mysql setpermissions, входящими в состав дистрибуции MySQL. Головоломка с привилегиями (продолжение) В лекции "Ведение файлов журналов" была рассмотрена ситуация, когда присвоенные администратором привилегии не позволяли достигать желаемого уровня доступа. Если помните, проблема возникала с новой инсталляцией MySQL, администратор которой добавлял запись для пользователя, тем самым разрешая ему подключаться к серверу с нескольких компьютеров. Очевидный способ определить подобный доступ — воспользоваться спецификатором имени компьютера с символом "%". Следовательно, администратор создает учетную запись пользователя с помощью следующего оператора: GRANT ALL ON samp db.* TO fred@%.snake .net IDENTIFIED BY "cocoa" Если пользователь f red имеет ученую запись на компьютере с сервером, то он попытается подключиться с него и получит следующий ответ: % mysql -u fred -pcocoa samp_db ERROR 1045: Access denied for user: 'fred@localhost' (Using password: YES) Почему же так происходит? Чтобы понять это, необходимо разобраться, как сценарий mysqlinstall db создает исходные таблицы разрешений и как сервер проверяет соответствие данных клиентских соединений и записей таблицы user. При инициализации баз данных в процессе работы mysql install db создает записи в таблице user со следующим значениями таблиц Host и User. +---------------------+------+ | Host | User | +---------------------+------+ | Localhost | root | | pit-viper.snake.net | root | 120 | localhost | | | pit-viper.snake.net | | +---------------------+------+ Первые две записи позволяют пользователю root подключиться к локальному компьютеру, определив либо localhost, либо собственно имя компьютера. Вторые две записи разрешают анонимное соединение с локальным компьютером. При добавлении записи для пользователя fred таблица принимает следующий вид: +---------------------+------+ | Host | User | +---------------------+------+ | Localhost | root | | pit-viper.snake.net | root | | localhost | | | pit-viper.snake.net | | | %.snake.net | fred | +---------------------+------+ В процессе запуска сервер считывает эти записи и сортирует их (сначала по имени компьютера, а затем по пользователям). В результате более определенные значения оказываются первыми, а менее определенные — последними. +---------------------+------+ | Host | User | +---------------------+------+ | Localhost | root | | localhost | | | pit-viper.snake.net | root | | pit-viper.snake.net | | | %.snake.net | fred | +---------------------+------+ Две записи для компьютера localhost располагаются рядом. Запись для пользователя root размещается первой, поскольку она является более полной. Аналогичным образом и в таком же порядке размещаются и записи компьютера pit-viper.snake.net. Все эти записи имеют в столбце Host буквенные значения безо всяких специальных символов, поэтому и располагаются перед записью для пользователя fred, включающей один специальный символ. Соответственно, записи анонимных пользователей имеют приоритет перед записью пользователя fred. Когда пользователь fred предпринимает попытку подключиться к серверу с локального компьютера, его данным соответствует запись с пустым именем пользователя, которая в порядке сортировки располагается перед записью с %.snake.net. Поскольку анонимные пользователи не применяют пароли, то и эта запись включает пустое значение пароля. Поскольку fred вводит пароль при подключении, возникает несоответствие, и соединение не устанавливается. Важно всегда помнить, что, хотя определять с помощью специальных символов имена компьютеров весьма удобно, с подключением с локального компьютера всегда будут возникать проблемы, если в таблице user будут размещаться записи для анонимных пользователей. 121 В большинстве случаев эти записи рекомендуется просто удалить, что значительно упростит дальнейшую работу администратора. Для этого можно воспользоваться следующим оператором: mysql> DELETE FROM user WHERE User = "; Чтобы быть полностью уверенным, что такая коллизия не произойдет в будущем, удалите записи анонимных пользователей и из всех других таблиц разрешений. Подобные записи имеются в таблицах db, tables_priv и columns_priv Хотя представленный в этой лекции материал описывает одну специфическую ситуацию, он позволяет сделать следующие общие выводы. Если присвоенные пользователям привилегии функционируют не так, как того ожидает администратор, необходимо заглянуть в таблицы разрешений и посмотреть, нет ли в них записей, значения столбца Host которых являются более определенными, чем введенные администратором. Именно в этом зачастую и кроется причина проблемы. Это свидетельствует также и о том, что администраторам необходимо более точно определять записи пользователей (добавляя новые записи для каждого конкретного уровня доступа). 122 ЛЕКЦИЯ 12. Концепции распределенных баз данных Описание: В этой лекции рассматриваются концепции распределенных баз данных, вопросы репликации данных и синхронизации баз. Также здесь рассказывается о том, как запустить несколько серверов MySQL на одном компьютере. Обычный сервер хранит у себя все данные и обслуживает все клиентские запросы. Схема взаимодействия между сервером и клиентами изображена на рис 12.1. Серверные данные располагаются на одном или нескольких физических дисках. Чтобы сделать запрос, клиент устанавливает соединение с сервером. Сервер анализирует инструкции, выполняет их, извлекает данные и возвращает результаты запроса. По мере возрастания нагрузки производительность сервера снижается. Чтобы избежать этого, задействуют дополнительные ресурсы, например, наращивают память, ставят дополнительные процессоры и даже сетевые платы. Эта стратегия эффективна, если клиенты расположены в непосредственной близости от сервера, — например, несколько серверов приложений взаимодействуют с одной СУБД. Но в тех архитектурах, где сервер и клиенты удалены друг от друга, производительность обратно пропорциональна расстоянию. Рис. 12.1. Обычный сервер баз данных Решением этой проблемы являются распределенные базы данных (РБД), которые сегментируют хранимую информацию и перемещают отдельные ее блоки ближе к нужным клиентам. Способов организации таких баз данных много. Можно разместить таблицы на разных компьютерах или использовать несколько идентичных хранилищ. Во втором случае серверы взаимодействуют друг с другом для поддержания синхронизации. Если на одном из серверов происходит обновление данных, оно распространяется и на все остальные серверы. К недостаткам распределенных баз данных можно отнести то, что возрастает сложность управления ими. Но преимуществ все же больше. Главное из них — повышение производительности. Данные быстрее обрабатываются несколькими серверами, а кроме того, данные располагаются ближе к тем пользователям, которые чаще с ними работают. Система становится более устойчивой, если она способна выдержать сбой одного из своих компонентов. В распределенной базе данных с симметричной схемой хранения исчезновение одного из серверов приводит к замедлению работы пользователей, находящихся ближе к этому серверу, но в целом система остается работоспособной. К тому же, она легко масштабируется, так как ее не нужно останавливать при добавлении еще одного сервера. В несимметричной системе можно оптимизировать схему расположения данных. Чем ближе пользователи находятся к нужным им данным, тем меньше на их работу влияют сетевые задержки. В результате серверам приходится обрабатывать меньшие объемы данных. Это также способствует повышению безопасности данных, поскольку их можно физически хранить в тех системах, где пользователи имеют право работать с соответствующими данными. В целом, однако, применение 123 распределенных баз данных связано с достаточно высоким риском. Требуется обеспечить соблюдение мер безопасности сразу на нескольких узлах, что не так-то просто реализовать. Распределенные базы данных трудно проектировать и обслуживать. Порядок работы в системе может со временем поменяться что повлечет за собой изменение схемы хранения данных. Как клиенты, так и серверы должны уметь обрабатывать запросы к данным, которые не расположены в ближайшей системе. Плохо спроектированная РБД может демонстрировать меньшую производительность, чем одиночный сервер. РБД состоит из трех основных частей: клиентов, модуля обработки транзакций и хранилища данных. Сервер обычно берет на себя задачи обработки транзакций и хранения данных, хотя в полностью распределенной базе данных за решение этих задач отвечают разные аппаратные компоненты. Обратимся к рис 12.2. Здесь три клиента взаимодействуют с двумя модулями обработки транзакций, которые, в свою очередь, работают с двумя хранилищами. Клиенты посылают свои запросы модулям, а те определяют, в каком из хранилищ находятся требуемые данные. Рис. 12.2. Распределенные серверы В идеальном случае, клиенты не знают, является система распределенной или нет. Они лишь посылают ей запросы, а система возвращает клиентам результаты этих запросов. Как она это делает, клиентов не интересует. На практике распределенные базы данных проявляют разную "прозрачность". В крайнем случае РБД хранится на нескольких независимых серверах, а клиентскому приложению приходится выбирать сервер в зависимости от того, какую информацию требуется получить. Это подразумевает, что таблицы, находящиеся на разных серверах, не имеют никаких внутренних связей. Естественно, такая организация РБД лишь изредка оказывается полезной. Система управления распределенными базами данных, или РСУБД, предоставляет клиентам унифицированный интерфейс доступа к данным, благодаря которому возникает иллюзия единого сервера. Если данные находятся в разных местах, РСУБД посылает запросы и обновления в соответствующие хранилища. В зависимости от того, с каким хранилищем ведется работа, производительность системы может оказаться разной, но, по крайней мере, клиентам не приходится самим заниматься выбором сервера. Если данные реплицируются между несколькими серверами, клиент в общем случае может предпочесть тот или иной сервер. В подобной схеме все серверы хранят одни и те же данные. Специальный модуль может помогать клиентам в выборе серверов, осуществляя выравнивание 124 нагрузки. РСУБД отвечает за выполнение транзакций в многосерверной среде, но в любой момент времени два сервера не могут быть синхронизированы между собой. В РБД применяется несколько схем распределения данных. В случае репликации каждый сервер хранит весь объем данных. Для этого требуется, чтобы РСУБД дублировала транзакции, позволяя всем клиентам видеть согласованный образ базы данных. В случае несимметричного разделения данных выбирается уровень сегментации. На самом высоком уровне расщеплению подвергаются отдельные базы данных, но не таблицы. Каждая таблица целиком находится в каком-то одном месте. На более низком уровне таблицы расщепляются по строкам или столбцам. Например, при горизонтальном расщеплении отдельные подмножества записей помещаются в разные хранилища, а при вертикальном расщеплении подмножества формируются на основании столбцов. Отложенная синхронизация Создать точную копию базы данных MySQL довольно просто. Способы резервного копирования баз данных описывались в лекции "Устранение последствий катастроф". Что касается восстановления данных, то это можно сделать на любом сервере. Располагая такими средствами, несложно реализовать распределенную базу данных, которая синхронизируется через достаточно большие промежутки времени, например, раз в день. Рассмотрим проблему обновления данных. Если обновления происходят сразу на двух серверах, их нужно согласовывать. Чтобы не возникали неразрешимые ситуации, необходимо позволить вносить изменения только на одном сервере. Тогда синхронизация будет заключаться в дублировании содержимого сервера, доступного для записи, на все остальные серверы. Их полезность зависит от того, насколько важна актуальность данных. Во многих случаях база данных, содержащая все записи, кроме тех, которые были созданы за последние 24 часа, вполне приемлема. Методика отложенной синхронизации идеально подходит для баз данных, содержащих результаты ночных отчетов. Например, Web-узел, предоставляющий доступ к МР3-файлам, может регистрировать названия запрашиваемых песен и составлять рейтинги популярности. Раз в день все серверы посылают свои журнальные главному серверу, который корректирует рейтинги согласно новой статистике. Схема такой базы данных приведена влистинге 12.1. /* Каталог МР3-файлов. */ CREATE TABLE song ( ID INT NOT NULL AUTO INCREMENT, Name CHAR(40) NOT NULL, Artist CHAR(16) NOT NULL, Filename CHAR(80) NOT NULL, PRIMARY KEY(ID), INDEX (Name), INDEX (Artist) ); /* Журнал запрашиваемых файлов. */ CREATE TABLE log ( Server TINYINT UNSIGNED NOT NULL, Song INT NOT NULL, DownloadTime DATETIME NOT NULL ); 125 Листинг 12.1. Схема распределений (html, txt) Каждый сервер хранит информацию о доступных песнях в таблице song. В таблицу log заносится запись всякий раз, когда кто-то загружает очередной МР3-файл. У этой таблицы нет первичного ключа, так как в обычном режиме она используется лишь для вставки записей. Наличие индекса только замедлит работу с таблицей. Раз в день таблицы log всех серверов объединяются по следующему сценарию. Один из серверов прекращает обслуживать запросы Web-приложений. Остальные серверы создают копии таблицы log, извлекают из них последние записи и посылают их серверу, генерирующему отчет. На время этой процедуры каждый сервер должен заблокировать свою таблицу log. Чтобы слишком много пользовательских запросов не оказалось заблокировано, процедуру желательно выполнять в период минимальной активности сервера. Сервер, генерирующий отчет, загружает полученные данные в свою таблицу log, после чего выполняет сценарий, показанный влистинге 12.2. В этом сценарии создаются два рейтинга популярности: по всем песням и за последние 24 часа. Временный индекс таблицы log ускоряет ее просмотр. /* Создание индекса. */ CREATE INDEX song ON log (Song); /* Определение рейтинга всех песен. */ DROP TABLE IF EXISTS popular alltime; CREATE TABLE popular alltime ( Rank INT NOT NULL, Song INT NOT NULL, Hits INT NOT NULL, ); SET @id = 0; INSERT INTO popular alltime SELECT (@id := @id+1), song, COUNT (*) FROM Log GROUP BY 2 ORDER BY 3 DESC; ALTER TABLE popular alltime ADD PRIMARY KEY (Rank); /* Определение рейтинга песен за последние 24 часа. */ DROP TABLE IF EXISTS popular last24; CREATE TABLE popular last24 ( Rank INT NOT NULL, Song INT NOT NULL, Hits INT NOT NULL, ); SET @id = 0; INSERT INTO popular last24 SELECT (@id := @id+1), song, COUNT (*) FROM Log WHERE DownloadTime > DATE SUB (NOW(), INTERVAL 24 HOUR) GROUP BY 2 126 ORDER BY 3 DESC; ALTER TABLE popular last24 ADD PRIMARY KEY (Rank); /* Удаление индекса */ DROP INDEX song ON log; Листинг 12.2. (html, txt) Таблицы рейтингов не содержат поле-счетчик: вместо него используется инкрементная переменная. Будучи созданной, рейтинговая таблица уже не меняется. Сценарий удаляет существующие таблицы и формирует их заново. Имеет смысл сжимать такие таблицы с помощью утилиты myisampack (см. лекцию "Утилиты командной строки"). Созданные таблицы загружаются остальными серверами, где они заменяют старые рейтинги. Изменения в таблицу song должны вноситься на одном сервере. Тогда исчезают проблемы, связанные с дублированием песен и первичных ключей. Главный сервер публикует новую редакцию каталога песен либо после каждого изменения, либо по определенному графику. Отложенная синхронизация удобна там, где пользователям не нужны отчеты в реальном времени. В приведенном выше примере число операций записи в журнальную таблицу превышает число обращений к рейтингам, если учесть, что пользователь, просматривающий список десяти лучших песен, наверняка захочет загрузить хотя бы одну из них. Методика срабатывает, поскольку информация, представленная в рейтинге, не имеет непосредственной ценности. В описанной схеме требуется, чтобы приложения знали архитектуру всей системы. Эта система не является монолитной и легко справляется со сбоями отдельных компонентов. Каждый из составляющих ее серверов хранит идентичную информацию. Репликация в MySQL Программа MySQL реализует функции автоматической репликации данных между главным и подчиненными серверами. Главный сервер ведет журнал изменений, который делается доступным для одного или нескольких подчиненных серверов. Простейшая схемарепликации с участием одного главного и двух подчиненных серверов изображена на рис 12.3. Рис. 12.3. Схема репликации с одним сервером для записи и двумя серверами для чтения Все серверы работают под управлением MySQL на разных компьютерах подключенных к сети. В целях синхронизации подчиненные серверы регулярно связываются с главным сервером. 127 Последний фиксирует каждое изменение в двоичном журнале (см. лекцию "Физическое хранение данных"). Если не считать короткие промежутки времени, в течение которых происходит синхронизация, подчиненные серверы содержат зеркальные копии базы данных. Клиенты могут посылать запросы на выборку как главному, так и любому подчиненному серверу. Запись данных должна происходить только на главном сервере, иначе изменения останутся локальными. В схеме на рис 12.3 запросы на выборку направляются только подчиненным серверам, что позволяет главному серверу сосредоточиться на обновлениях. На подчиненном сервере запускается отдельный поток, который периодически опрашивает главный сервер на предмет наличия изменений. Однако бывает так, что сервер одновременно является и главным, и подчиненным. Тогда становится возможной схема репликации, изображенная на рис 12.4. Здесь есть четыре сервера, каждый из которых играет двойную роль. Приложение направляет "своему" серверу запросы как на выборку, так и на обновление данных. Обновление, произошедшее на одном сервере, передается по цепочке остальным серверам. Рис. 12.4. Круговая репликация Приложение должно предотвращать несогласованные обновления. Рассмотрим такой случай. Серверы А и Б являются друг для друга главным и подчиненным сервером. Оба используют таблицу сообщений с первичным ключом-счетчиком. В определенный момент два пользователя одновременно создают новые сообщения, по одному на каждом сервере. Если таблицы раньше были синхронизированы, то теперь в каждой из них будет новая запись с идентификатором, совпадающим с идентификатором другой записи на другом сервере. Можно избежать этой неприятности, используя внешний генератор идентификаторов, при условии, что он будет однопотоковым. В схеме на рис 12.4 каждое приложение взаимодействует с одним сервером, хотя это необязательно. Если серверы расположены рядом, можно формировать пул серверов. Тогда при выборе сервера приложение сможет учитывать возможность сбоя или применять алгоритм выравнивания нагрузки. 128 Подчиненный сервер контролирует, какое изменение было получено от главного сервера последним. По умолчанию сведения об этом находятся в файле master info. Если обновление приводит к появлению ошибки, то поток, управляющий синхронизацией, останавливается. В этом случае сервер записывает сообщение в журнал ошибок. В MySQL версии 3.23.39 механизм репликации имеет ряд ограничений. В основном все они связаны с тем, что изменения фиксируются только в двоичном журнале. Функция RAND() по умолчанию инициализирует генератор псевдослучайных чисел значением системных часов, но это значение не сохраняется в двоичном журнале. В подобной ситуации можно инициализировать генератор самостоятельно с помощью функции UNIX TIMESTAMP(). Вспомните, что изменения таблиц привилегий в базе данных mysql не вступят в силу, пока не будут очищены буферы привилегий. Но дело в том, что в двоичном журнале не отслеживаются инструкции FLUSH, поэтому старайтесь не менять таблицы напрямую, а пользуйтесь инструкциями GRANT и REVOKE. Значения переменных не реплицируются. Если в обновлении строки участвовала переменная, то на подчиненном сервере будет использовано локальное, а не реальное значение этой переменной. Чтобы включить функции репликации, нужно отредактировать конфигурационные файлы сервера. Ниже перечислены опции демона mysqld, имеющие отношение к репликации. Все они были описаны в лекции "Утилиты командной строки". --binlog-do-db=база данных --binlog-ignore-db=база данных --log-bin-index=каталог --log-bin[=каталог] --log-slave-updates --master-connect-retry=секунды --master-host=узел --master-info-file=файл --master-password=пароль --master-port=порт --master-user=пользователь --replicate-do-db=база данных --replicate-do-table=база данных.таблица --replicate-ignore-db=база данных --replicate-ignore-table= база данных.таблица --replicate-rewrite-db=главный->подчиненный --replicate-wind-do-table=шаблон --replicate-wind-ignore-table=шаблон --server-id=идентификатор Прежде чем редактировать конфигурационные файлы, создайте на главном сервере учетную запись, чтобы подчиненный сервер мог получать обновления. В листинге 12.3 показана инструкция, создающая пользователя user с привилегией FILE. Никакие другие привилегии подчиненному серверу не нужны. В данном примере пользователь может посылать запросы с любого узла, но на практике обычно указывают конкретное доменное имя. GRANT FILE ON *.* ТО slave IDENTIFIED BY ‘password’ Листинг 12.3. (html, txt) 129 Теперь нужно остановить главный сервер или заблокировать все таблицы, подлежащие репликации. Создайте точные копии реплицируемых баз данных и лишь затем редактируйте конфигурационные файлы. Вспомните, что таблицы MySQL имеют системно независимый формат. Это позволяет копировать и перемещать файлы, не меняя их формат. В листинге 12.4 создается tar архив одной базы данных. Можно также выполнить на подчиненном сервере инструкцию LOAD TABLE, чтобы получить точную копию нужной таблицы. [/usr/local/var]# tar cvfz freetimedb.tar.gz. /freetime/ Листинг 12.4. (html, txt) Далее требуется включить двоичный журнал на главном сервере, внеся изменения в конфигурационный файл /etc/my.cnfСоответствующая опция называется log bin. С помощью опции server id серверу присваивается уникальный идентификатор. Влистинге 12.5 показаны две строки, которые добавляются в раздел [mysqld] конфигурационного файла. После внесения изменений нужно перезапустить главный сервер. log-bin server_id=1 Листинг 12.5. (html, txt) Скопируйте на подчиненный сервер созданную выше копию базы данных и отредактируйте его конфигурационный файл. Добавляемые в него опции перечислены в листинге 12.6. Поскольку реплицируется лишь одна база данных, с помощью опции replicate-do-dbзадается конкретное имя: freetime. Данному подчиненному серверу присваивается идентификатор 2. Master-host=192.168.123.194 Master-user=slave Master-password=password Master-port=3306 Replicate-do-db=freetime Server-id=2 Листинг 12.6. (html, txt) После изменения конфигурации запустите подчиненный сервер. Он свяжется с главным севером и проверит, изменилась ли база данных freetime с момента получения ее последней копии. Пока подчиненный сервер работает, он регулярно получает интересующие его изменения. Задержка обновления зависит от контекста, но обычно она составляет несколько секунд. В листинге 12.7 перечислены инструкции, используемые в процессе репликации. Инструкция CHANGE MASTER приводит к временной смене главного сервера. mysql> SHOW MASTER STATUS; +------------+----------+--------------+------------------+ |File | Position | Binlog do db | Binlog ignore db | +------------+----------+--------------+------------------+ |red-bin.002 | 312 | | | +------------+----------+--------------+------------------+ 1 row in set (0.00 sec) mysql> SHOW MASTER STATUS \G *************************************************************** Master Host: 192.168.123.194 130 Master User: slave Master Port: 3306 Connect retry: 60 Log file: red-bin.002 Pos: 312 Slave running: Yes Replicate do db: freetime Replicate ignore db: Last errno: 0 Last error: Skip connect: 0 1 row in set (0.00 sec) Листинг 12.7. (html, txt) Репликация пока еще является относительно новым механизмом в MySQL, хотя и хорошо работающим. По крайней мере, функциирепликации легко конфигурировать. В MySQL версии 4.0 будут внесены многочисленные улучшения, в том числе направленные на устранение ограничений репликации. В настоящее время репликация лучше всего реализуется в виде синхронизированных резервных копий. Все подчиненные серверы постоянно поддерживают свои данные в синхронизированном состоянии, поэтому при сбое главного сервера нужно лишь переключить приложения на новый сервер. Если репликация применяется для улучшения производительности работы в организации, следуйте схеме, представленной на рис 12.3. Приложение должно взять на себя заботу о том, чтобы изменения делались лишь на главном сервере. Во всем остальномрепликация должна быть абсолютно прозрачной. Если серверы, на которых хранится распределенная база данных, находятся на большом расстоянии друг от друга, попытайтесь внедрить схему круговой репликации. Например, можно закрепить за каждым сервером свой набор таблиц и позволить обновлять их только на одном сервере. Каждый узел в схеме круговой репликации важен для нормальной работы системы. Чтобы свести к минимуму потери от сбоев, создайте дополнительные подчиненные серверы, не входящие в "цепочку". Они предназначены для экстренной замены вышедшего из строя главного сервера. Запуск нескольких серверов Обычно сценарий safe mysqld запускает сервер MySQL от имени специального пользователя. Но на самом деле любой пользователь системы может запустить свой сервер параллельно с другими серверами, при условии, что все они будут работать с разными портами или сокетами. Таким способом часто обеспечивается повышенный уровень безопасности. К примеру, провайдеры Internet продают дисковое пространство Web-серверов множеству пользователей. В такой открытой среде нельзя рассчитывать на то, что пользователи не будут злоупотреблять своими привилегиями, имея доступ к общим ресурсам. Вместо того чтобы предоставлять каждому пользователю отдельную базу данных и заниматься администрированием всего множества баз данных, провайдеры создают для каждого пользователя свой сервер. Это позволяет пользователям самостоятельно заниматься администрированием, не мешая остальным. Неудобством такого подхода является то, что приложения должны подключаться к серверам, используя нестандартные установки. Все их нужно свести в персональный конфигурационный файл ~/my.cnf. 131 Нестандартные значения номера порта или имени сокета, с которыми работает сервер, тоже нужно вынести в отдельный конфигурационный файл, который передается демону mysqld при запуске. Каждому серверу необходим и свой каталог данных. Все это можно сделать вручную, но лучше воспользоваться специально предназначенным для этих целей сценарием mysqld multi. Данный сценарий работает с одним конфигурационным файлом, в котором у каждого сервера есть своя группа опций, объединенных под общим заголовком. В группу [mysqld multi] входят опции самого сценария, а названия остальных групп состоят из имени сервера и его номера, например [mysqld 13]. Опции каждой группы передаются соответствующему демонуmysqld при его запуске. Сценарий mysqld multi может запускать и останавливать любой сервер, указанный по номеру, но для этого сценарий должен иметь привилегию SHUTDOWN. Ею не должен владеть кто угодно, поэтому нужно создать специальную учетную запись на каждом сервере, где подобные действия разрешены (листинг 12.10). Имя пользователя и пароль должны быть везде одинаковыми. Поместите их в группу [mysqld multi] как показано в листинге 12.11. GRANT SHUTDOWN ON *.* TOmulti admin@localhost IDENTIFIED BY ‘password’ Листинг 12.10. (html, txt) У каждого сервера должна быть своя группа опций. В названии группы нужно указать положительное целое число, уникальное в пределах файла. Группы не обязаны располагаться по порядку. Для каждого сервера нужно задать файл сокета номер порта и каталог данных. Что касается имени пользователя, то разрешается, чтобы один и тот же пользователь запускал несколько серверов. В листинге 12.11 создаются три сервера для трех пользователей. [mysqld multi] mysqld = /usr/local/libexec/mysqld mysqladmin = /usr/local/bin/mysqladmin user = multi admin password = password log = /usr/local/var/multi.1og [mysqd1] socket = /tmp/mysql.sock port = 3306 pid-file = /usr/local/mysql/var/mysqld1/myserver.pid datadir = /usr/local/mysql/var/mysqld1/ user = jgalt [mysqd2] socket = /tmp/mysq2.sock port = 3307 pid-file = /usr/local/mysql/var/mysqld2/myserver.pid datadir = /usr/local/mysql/var/mysqld2/ user = dtaggart [mysqd3] socket = /tmp/mysq3.sock port = 3308 132 pid-file = /usr/local/mysql/var/mysqld3/myserver.pid datadir = /usr/local/mysql/var/mysqld3/ user = hreardon Листинг 12.11. (html, txt) 133 ЛЕКЦИЯ 13. Расширение возможностей Описание: В этой лекции рассматриваются способы расширения функциональных возможностей сервера MySQL. Сюда входит написание собственных функций и процедур, а также создание наборов символов. Описываются также средства отладки, имеющиеся в MySQL. Библиотека функций отладки В MySQL входит библиотека функций отладки, первоначально созданная Фредом Фишем (Fred Fish). Чтобы разрешить ее использование, нужно на этапе компиляции программы вызвать сценарийconfigure с опцией –with_debug. Если в распоряжении имеется бинарный дистрибутив, проверьте версию какого либо исполняемого файла. Программы, скомпилированные с поддержкой отладки, имеют суффикс –debug. Библиотека функций отладки является частью библиотеки mysqlclient. Макросы библиотеки объявлены в файле dbug.h. Названия всех макросов начинаются с префикса DBUG_ (табл. 13.1). Если нужно отключить отладку, определите макроконстанту DBUG_OFF. При ее наличии все остальные макросы игнорируются. Таблица 13.1. Макрос Описание DBUG ENTER Этот макрос принимает имя функции, в которую входит программа. Его (функция) нужно указывать после объявления локальных переменных, но перед вызовом каких либо инструкций. Например: DBUG ENTER ("main") DBUG EXECUTE Этот макрос помечает указанную инструкцию меткой. Например: DBUG (ключевое слово) EXECUTE ("where", print where(tmp,"cache")); DBUG FILE Эта макроконстанта инкапсулирует дескриптор выходного файла, в который записывается отладочная информация. Например: sprintf (DBUG FILE, "\nWHERE:(%s)" , info); DBUG LONGJMP Если в программе используется функция LONGJMP(), замените ее данным (среда, значение) макросом. DBUG POP () Этот макрос восстанавливает предыдущее состояние отладки. DBUG POP (); DBUG_PRINT Этот макрос записывает отладочную информацию в файловый поток, как (ключевое слово, если бы была вызвана функция fprintf с константой DBUG_FILE в качестве формат, [аргументы]) дескриптора. Первый это ключевое слово которое можно использовать с описанным ниже флагом d. Второй аргумент — это набор параметров, передаваемый функции fprintf. Например: DBUG_PRINT ("mfunkt" , ("name: "%s"" , name)); DBUG PROCESS Этот макрос задает имя текущего процесса. Например: DBUG PROCESS (имя) (argv [0] ); DBUG PUSH Этот макрос задает новые параметры для текущего сеанса отладки. Все они (формат) помещаются в стек, поэтому можно восстанавливать предыдущие состояния с помощью макроса DBUG POP (). Например: DBUG PUSH (" d:t "); DBUG RETURN Этот макрос заменяет инструкцию return. Если функция нечего не (значение) возвращает, пользуйтесь макросом DBUG VOID RETURN (). DBUG SET JMP Этот макрос заменяет функцию setjmp (). (среда) DBUG VOID Этот макрос указывает на то, что функция не возвращает никаких значений RETURN 134 Отладка функции начинается с того, что в ее начало помещается макрос DBUG ENTER(). Затем все вызовы инструкции returnзаменяются либо макросом DBUG ENTER(), либо DBUG VOID RETURN. Это позволяет отладчику определять, когда управление передается той или иной функции. Макрос DBUG EXECUTE() помечает отдельную строку кода ключевым словом. Макрос DBUG PRINT записывает сообщение в отладочный файл. Можно напрямую работать с этим файлом благодаря макроконстанте DBUG FILE, в которой хранится его дескриптор. В листинге показан пример отладки функции, которая вычисляет факториал заданного целого числа. ttinclude <dbug.h> int factorial (register int value) { DBUG ENTR ("factorial"); DBUG PRINT ("find", ("find %d factorial", value)); if (value > 1) { value *= factorial (value - 1); } DBUG ENTR ("result", ("result %d", value)); DBUG RETURN (value); } Листинг 13.1. (html, txt) Программа, работающая с библиотекой функций отладки, обычно начинает отладку, вызывая макрос DBUG PUSH(). Утилиты MySQL включают отладку, если получен соответствующий аргумент командной строки или если установлена специальная переменная среды. В табл. 13.2 перечислены флаги, понимаемые отладчиком и передаваемые макросу DBUG PUSH (). Они определяют, какая информация должна быть представлена в выходных данных. Строка формата выглядит как последовательность флагов, разделенных двоеточиями. Некоторые флаги требуют наличия параметров. Например, флаг d принимает список ключевых слов, разделенных запятыми. Таблица 13.2. Флаг Описание d [, Этот флаг разрешает выводить информацию макросам с именами ключевые вида DBUG ключевое слово. Если список ключевых слов не указан, то слова] подразумеваются все макросы. Ключевые слова должны задаваться без префикса DBUG. D [,время] Этот флаг свидетельствует о том, что вывод отладочной информации должен быть задержан на указанное число десятых долей секунды. Например, флаг D, 25 означает, что при выводе каждой строки будет выдерживаться пауза длительностью 2,5 секунды. f [,функции] Этот флаг разрешает выводить отладочную информацию только из указанных функций. Например, флаг f mainозначает, что будут включены макросы, находящиеся в теле функции main (). F Этот флаг указывает на то, что каждую строку отладочной информации необходимо сопровождать именем исходного файла. 135 Этот флаг включает режим профилирования. В результате будет создан файл dbugmon.out. В качестве аргумента может быть указан список функций, для которых выполняется профилирование. В противном случае подразумеваются все функции. Более подробную информацию об этом можно найти в файле dbug/readme.prof дистрибутива MySQL i Этот флаг указывает на то, что каждую строку отладочной информации необходимо сопровождать идентификатором процесса или потока, в зависимости от контекста. L Этот флаг указывает на то, что каждую строку отладочной информации необходимо сопровождать номером строки исходного файла. n Этот флаг указывает на то, что каждую строку отладочной информации необходимо сопровождать информацией о глубине вызова текущей функции. N Этот флаг включает нумерацию строк в файле отладки. о [, файл] Этот флаг говорит о том, что отладочная информация должна направляться в указанный файл. По умолчанию эта информация отображается на экране, но многие клиентские программы изменяют данную установку, создавая в каталоге /tmp файл с именем программы и расширением .Trace. О [, файл] Этот флаг аналогичен флагу o, но после каждой записи в файл будет очищаться файловый буфер P [, Этот флаг разрешает выводить отладочную информацию только указанным процессы] процессам. Имя процесса должно быть задано с помощью макроса DBUG_PROCESS Р Этот флаг указывает на то, что каждую строку отладочной информации необходимо сопровождать именем процесса r Этот флаг заставляет выравнивать выводимую информацию по левому краю экрана после вызова макроса DBUG PUSH (). S При наличии этого флага отладчик будет вызывать функцию sanity(file, line) для каждой отлаживаемой функции, пока первая не вернет значение, отличное от нуля t [, уровень] Этот макрос включает вывод строк, помечающих точки вызова и завершения функций. Через запятую может быть указан максимальный уровень трассировки, по достижении которого отладочная и трассировочная информация перестает выводиться. g Исходная документация, написанная Фредом Фишем, находится в файле dbug/user.r в исходном каталоге MySQL. С помощью утилиты nroff этот файл можно преобразовать в формат Postscript или в текстовый формат. Создание наборов символов Допускается включать в программу MySQL новые наборы символов. Для простого, однобайтового набора требуется лишь один файл с четырьмя таблицами преобразований. В случае сложного набора необходимо также написать функцию, выполняющую сортировку строк. # конфигурационный файл для набора символов latinl. # массив ctype{} (должен содержать 257 элементов). 00 20 20 20 20 20 20 20 20 20 28 28 28 28 28 28 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 ... ... ... ... 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 136 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 # Массив to lower (должен содержать 256 элементов). 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F ... ... ... ... E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF # Массив to upper (должен содержать 256 элементов). 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F ... ... ... ... E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF D0 D1 D2 D3 D4 D5 D6 F7 D8 D9 DA DB DC DD DE FF # Массив sort order (должен содержать 256 элементов). 00 01 02 10 11 12 ... ... ... ... 41 41 41 44 4E 4F 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 41 5C 5B 5C 43 45 45 45 45 49 49 49 49 4F 4F 4F 5D F7 D8 55 55 55 59 59 DE FF Десятичное значение 1 2 4 8 16 32 символ 64 128 цифра Листинг 13.2. (html, txt) Шестнадцатеричное значение Описание 0х01 0х02 0х04 0х08 0х10 0х20 прописная буква строчная буква цифра символ пробела знак пунктуации управляющий 0х40 0х80 пусто шестнадцатеричная Вторая группа значений представляет собой таблицу ASCII, предназначенную для перевода символов в нижний регистр. Например, символ в позиции 0x41 — это прописная буква "A", но ей соответствует значение 0x61, т.е. строчная "a". Третья группа значений определяет таблицу ASCII для перевода символов в верхний регистр. Последняя таблица задает порядок сортировки и обычно совпадает с третьей таблицей. Если истинный порядок сортировки невозможно отразить в столь простой таблице, то необходимо написать специальные функции сортировки. Для этого нужно создать файл в каталоге strings дерева MySQL. Здесь же находятся файлы всех остальных наборов символов, например, ctype_big5.c. Программа MySQL ищет в этом файле пять функций и четыре массива. Имена всех функций и массивов включают стандартный префикс и название набора. В листинге 13.3 показаны прототипы функций и определения массивов для набора символов big5. 137 uchar NEAR ctype big5{257} uchar NEAR to lower big5{} uchar NEAR to upper{257} uchar NEAR sort order big5{257} my bool my like range big5( const char *ptr, uint ptr length, pchar escape, uint ers length, char *min str, char *max str, uint *min length, uint *max length) int my strcoll big5( const uchar * s1, const uchar * s2) int my strnncoll big5( const uchar * s1, int len1, const uchar * s2 int len2) int my strnxfrm big5( uchar * dest, uchar * src, int len, int srclen) int my strxfrm big5( uchar * dest, uchar * src, int len) Листинг 13.3. (html, txt) Четыре функции осуществляют сравнение строк. Функция с префиксом my like range находит наименьшую и наибольшую строки (с учетом реестра), соответствующие выражению в операторе LIKE. Само выражение передается в аргументе ptr. Аргумент ptr length определяет длину выражения. Содержимое наименьшей и наибольшей строк заносится в аргументы min str и max strсоответственно. Функции с префиксами my strcoll и my strncoll служат аналогами обычных функций strcoll() и strncoll() языка С, которые, в свою очередь, являются версиями функций strcmp и strncmp, учитывающими региональные установки. Функции с префиксами my strxfrn и my strnxfrn эмулируют стандартные функции strxfrn() и strnxfrn(). Получить о них более подробную информацию можно в man файлах UNIX. В начало файла нужно добавить комментарий, подобный тому, что показан в листинге 13.4. На основании строк, приведенных в комментарии, сценарий configure включает набор символов в клиентскую библиотеку. Переменная strxfrn multiply набор задается в том случае, когда у набора 138 символов есть свои функции сортировки строк. Она определяет максимальный коэффициент удлинения строки при ее прохождении через функцию с префиксом my strxfrm. Как следует из листинга, строки в кодировке big5 не растягиваются. Если в набор входят многобайтовые символы, потребуется определить переменную mbmaxlen набор. Она задает максимально возможное число байтов в представлении символа. Например, в набор big5 входят двухбайтовые символы. /* Эти строки анализируются сценарием configure при создании файла ctype.c, поэтому не меняйте их без веских оснований. .configure. strxfrm multiply big5=1 .configure. mbmaxlen big5=2 /* Листинг 13.4. (html, txt) Все, что осталось теперь сделать, — это добавить имя набора в списки CHARSETS AVAILABLE и COMPILED CHARSETS в файлеconfigure.ini и перекомпилировать программу. Активизировать доступные наборы символов можно с помощью опций командной строки, конфигурационного файла или SQL инструкций. Создание функций В программу MySQL можно добавить новые функции, которые будут использоваться точно так же, как и встроенные функции. Существуют два способа создания таких функций. Первый — это включение функции непосредственно в исходный код MySQL, второй — определение функции в формате UDF (User Definable Function — пользовательская функция). Второй способ подходит, когда функцию требуется хранить и отлаживать отдельно от утилит MySQL. Код функции компилируется в виде библиотечного модуля, который загружается с помощью инструкции CREATE FUNCTION. Первый способ менее удобен, поскольку приходится останавливать сервер и заменять его исполняемый файл. Так обычно поступают с функциями, которые планируется сделать частью проекта MySQL. Ниже будет рассмотрен второй подход. В дистрибутив MySQL входит пример UDF-функций Он находится в файле sql/udf example.cc. В этом файле содержатся определения шести функций. Я скопировал из него строку, используемую утилитой make для правильного вызова компилятора языка С. В комментариях к файлу рекомендуется выполнить команду make udf example.cc, чтобы посмотреть параметры компиляции статического объектного файла, а затем заменить аргумент – с аргументом – shared – о udf example. so. В листинге 13.5 показана строка компиляции файла в моей системе RedHat в каталоге sql программы MySQL. c++ \ -DMYSQL SERVER \ -DDEFAUT MYSQL HOME="\"/usr/local\"" \ -DDATADIR="\"/usr/local/share/var\"" \ -DSHAREDIR="\"/usr/local/share/mysql\"" \ -DHAVE CONFIG H \ -DDBUG OFF \ -I../bdb/build unix \ -I../innobase/include \ -I./../include \ 139 -I./../regex \ -I. \ -I../include \ -I.. \ -03 \ -fno-implicit-templates \ -shared \ -o udf example.cc Листинг 13.5. (html, txt) После компиляции совместно используемой библиотеки нужно скопировать ее в один из каталогов, перечисленных в/etc/ld.so.conf файле. Если каталог будет другим, укажите его имя в переменной среды LD LIBRARY PATH. Для активизации функции нужно выполнить инструкцию CREATE FUNCTION. В листинге 13.6 демонстрируется загрузка функцийMETAPHON и AVGCOST из библиотеки udf example. В результате в таблице mysql.func будут созданы две новые записи, и пока инструкция DROP FUNCTION их не удалит, функции останутся доступны всем пользователям даже в случае перезапуска сервера. CREATE FUNCTION METAPHON RETURNS STRING SONAME "udf example.so"; CREATE AGGREGATE FUNCTION AVGCOST RETURNS REAL SONAME "udf example.so"; Листинг 13.6. (html, txt) В библиотечном файле может содержаться одна или несколько функций. Язык реализации — С или C++. Каждой SQL-функции в этом файле соответствует как минимум одна функция с аналогичным именем. Кроме того, могут быть созданы функции с суффиксами init и deinit. Например, в файле udf example.сс содержатся определения функций metaphon (), metaphon init () и metaphon deinit (). Когда вводится инструкция, содержащая вызов, сначала происходит обращение к функции с суффиксом init. Затем для каждой записи выполняется основная функция. В конце вызывается функция с суффиксом deinit. Все три функции должны быть безопасны для потоков. Это означает, что в них нельзя использовать глобальные переменные, меняющие свои значения. Функция с суффиксом _init предназначена для динамического выделения памяти, а функция с суфиксом deinit освобождает выделенную память. Основная функция может возвращать значение с плавающей запятой, целое число или строку. В первом случае тип результата должен быть double, во втором — long, a в третьем — char *. В листинге 13.7 показано несколько прототипов функций. Char *metaphon( UDF INIT *initid, UDF ARGS *args, char *result, unsigned long *length, char *is null, char *error); long long sequence( UDF INIT *initid, UDF ARGS *args char *is null, char *error); 140 double myfunc double( UDF INIT *initid, UDF ARGS *args char *is null, char *error); my bool metaphon init( UDF INIT *initid, UDF ARGS *args char *message); void metaphon deinit( UDF INIT *initid); Листинг 13.7. (html, txt) Числовые значения возвращаются непосредственно, а строковые — через указатели. Программа MySQL резервирует 255 — символьный буфер для аргумента result. В аргументе length должен быть указан размер возвращаемого значения. Если размер превышает 255 байтов, нужно создать собственный буфер в инициализирующей функции и передать указатель на него в поле ptrструктуры UDF_INIT. Описание полей структуры приведено в табл. 13.4. Поле my bool maybe null unsigned int decimals unsigned int max length char *ptr Таблица 13.4. Описание Указывает на то, может ли функция возвращать пустое значение. Если один из аргументов функции может быть пустым, в это поле будет записана единица Содержит количество цифр после запятой, если функция возвращает числовое значение. Будет указана максимальная точность среди всех аргументов Определяет максимальную длину возвращаемой строки С помощью этого указателя осуществляется обмен данными между инициализирующей функцией и другими двумя функциями. Например, можно выделить блок памяти и записать сюда адрес этого блока Если функция возвращает пустое значение, аргумент is_null должен быть равен 1. В случае ошибки в аргумент error записывается значение 1. В результате текущая запись и все последующие станут пустыми. Описание структуры UDF_ARGS приведено в табл. 13.5. Через эту структуру программа MySQL передает аргументы функции. unsigned int arg_count enum Item_result *arg_type char **args Таблица 13.5. Содержит число аргументов функции. Если это значение фиксировано, проверьте его в инициализирующей функции Содержит массив типов аргументов. Возможные значения массива таковы: INT_RESULT, REAL RESULT и STRING RESULT. Можно осуществлять проверку типов и в случае несовпадения либо возвращать признак ошибки, либо корректировать содержимое массива, приводя аргументы к нужному типу Содержит массив значений аргументов. Если аргумент является строкой, в массиве будет храниться указатель на строку. Длины строковых аргументов приведены в 141 массиве lengths. Если аргумент представляет собой целое число или число с плавающей запятой, приведите значение к типу long или double соответственно unsigned long Содержит массив длин аргументов. В инициализирующей функции эти значения *lengths устанавливаются по максимуму на основании определений столбцов. В основной функции длины строковых аргументов являются точными Создание процедур Процедуры MySQL выполняют операции над результатами запросов. Процедура активизируется при наличии в конце инструкцииSELECT ключевого слова PROCEDURE. В настоящий момент в MySQL входит единственная процедура analyse(). Разрешается создавать собственные процедуры, включая их в программу на этапе компиляции. Процедуры появились в MySQL версии 3.21, но пока что не вызвали особого энтузиазма. Писать их оказалось слишком сложно для большинства пользователей. Например, для создания процедуры на C++ требуется определить класс, производный от классаProcedure. Код последнего находится в файлах sql / procedure.h и sql / procedure c.c. Процедура analyse реализована в файле sql/sql_analyse_c.c. С другой стороны можно воспользоваться библиотекой mylua (www.fastflow.it/ mylua) которая позволяет динамически загружать процедуры, написанные на языке LUA (www.lua.org). Для запуска сценария LUA в MySQL нужно вызвать функцию LUA() указав ей имя исходного файла, где содержится определение процедуры. 142