MySQL & mSQL

         

Что такое база данных?


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

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

У традиционных бумажных баз данных много недостатков. Им требуется огромное физическое пространство. Библиотеки занимают целые

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

MySQL и mSQL не являются базами данных. Фактически они являются компьютерными программами, позволяющими пользователю создавать, поддерживать базы данных и управлять ими. Такой тип программного обеспечения известен как Системы управления базами данных (СУБД). СУБД действует как посредник между физической базой данных и ее пользователями.

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



Что такое реляционная база данных?


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

Таблица 1-1. Таблица книг



ISBN

Название

Автор

0-446-67424-9

0-201-54239-Х

0-87685-086-7

0-941423-38-7

L.A. Confidential

An Introduction to Database Systems

Post Office

The Man with the Golden Arm

James Ellroy

C.J. Date

Charles Bukowski

Nelson Algren

В таблице 1-2 и таблице 1-3 показаны две таблицы, которые могут появиться в базе данных Национальной Баскетбольной Ассоциации.

Таблица 1-2. Таблица команд НБА

№ команды

Название

Тренер

1

Golden State Warriors

P.J. Carlesimo

2

Minnesota Timberwolves

Flip Saunders

3

L.A. Lakers

Kurt Rambis

4

Indiana Pacers

Larry Bird

Таблица 1-3. Таблица игроков НБА

Имя

Положение

№ команды

Rik Smits

Центровой

4

Kevin Garnett

Нападающий

2

Kobe Bryant

Защитник

3

Reggie Miller

Защитник

4

Stephen Marbury

Защитник

2

Shaquille O'Neal

Центровой

3

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

СУБД для реляционной базы данных часто называется Реляционной системой управления базами данных (РСУБД). MySQL и mSQL являются примерами РСУБД.

Какое отношение ко всему этому имеет SQL? Нам необходимо иметь некий способ взаимодействия с базой данных. Нужно определять таблицы, а также извлекать, добавлять, обновлять и удалять данные. SQL (Structured Query Language - язык структурированных запросов) является компьютерным языком, используемым для выражения операций с базой данных, организованной в реляционной форме (то есть в виде таблиц). SQL является принятым в отрасли стандартом языка, на котором говорит большинство программистов баз данных и который используется большинством пакетов РСУБД. Как следует из их названий, механизм работы с MySQL и mSQL основан на SQL. Из-за своей простоты, однако, они поддерживают лишь подмножество современного стандарта SQL - SQL2. Мы обсудим, в чем именно состоит отличие поддерживаемого MySQL и mSQL диалекта SQL от стандарта, в последующих главах.



в течение многих лет используют


Введение в реляционные базы данных


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

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

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

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

ном мире. Если у вас есть опыт работы с реляционными базами данных и их проектированием, вы можете сразу перейти к главе 4, «MySQL» или главе 5, «mSQL», где мы углубляемся в детали практической работы с MySQL и mSQL. Но, если вы собираетесь это сделать, обратите внимание, что в конце данной главы мы приводим краткое введение и сравнение основных возможностей этих продуктов. В оставшейся части книги в основном излагается применение MySQL и mSQL для создания и поддержки того типа приложений, которые важны для таких пользователей, как вы.



MySQL и mSQL


MySQL и mSQL - очень схожие, дешевые, компактные и быстрые базы данных. В этой книге описаны обе эти базы данных, что связано с их крайним сходством. Однако между ними есть и очень важные различия, о которых мы также обязательно расскажем. Обе системы поддерживают программирование на С, Perl, Java (через API Java DataBase Connectivity - JDBC) и Python. Благодаря инструментальным средствам, которые MySQL и mSQL предоставляют для этих языков, можно создавать полноценные клиент-серверные приложения и интегрированные с базами данных веб-сайты, не тратя на это состояния. Это приятное известие для маленьких фирм, публикующих данные в Интернет, и всех тех, кто разрабатывает небольшие клиент-серверные приложения и не может позволить себе приобрести коммерческие продукты.

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

История mSQL

До 1994 года вам не удалось бы обзавестись РСУБД с поддержкой SQL, не потратив при этом изрядной суммы денег. На рынке тогда доминировали Oracle, Sybase и Informix. Эти системы управления базами данных были разработаны для обработки огромных объемов данных с очень сложными взаимосвязями. Они были мощными, обладали множеством возможностей, а также требовали больших вычислительных ресурсов и были дороги. В те времена еще нельзя было за $2000 купить сервер с 200-MHz Pentium. Ресурсы, требуемые для этих СУБД, стоили десятки тысяч долларов.


У больших корпораций и крупных университетов не возникало проблем с тем, чтобы потратить за год несколько миллионов долларов на такие комплекты серверов и СУБД. Малым организациям и частным пользователям приходилось довольствоваться слабыми настольными приложениями. Несколько дешевых СУБД с архитектурой клиент/ сервер в то время существовало, но ни в одной из них не использовался SQL в качестве языка запросов. Наиболее примечательной из них была Postgres, имевшая общее происхождение с коммерческой базой данных Ingres. К несчастью, Postgres требовала примерно тех же ресурсов, что и ее коммерческие аналоги, не давая преимущества использования SQL в качестве языка запросов. В то время в Postgres использовалась разновидность языка QUEL, называвшаяся PostQUEL.

Дэвид Хьюз

Часть диссертации, которую Давид Хьюз (David Hughes) (известный также как Bamby) писал в Университете Бонд в Австралии, была посвящена разработке системы мониторинга и управления группой систем из одного или нескольких мест. Проект носил название Minerva Network Management System. Главным элементом Minerva была база данных для хранения данных обо всех компьютерах в сети. Будучи студентом университета и не имея доступа к серверам, на которых работали большие коммерческие базы данных, Хьюз решил, что Postgres - это очевидное решение, вполне отвечающее его потребностям.

Его коллеги предложили сделать SQL стандартным языком запросов для Minerva. В конце концов, SQL был и остается самым общепринятым стандартом языка запросов. Основываясь на SQL, Minerva могла бы использоваться в любой точке света, где установлена поддерживающая SQL СУБД. Иными словами, SQL предоставлял возможности Minerva гораздо более широкому кругу пользователей, нежели PostQUEL, ограничивавший его пользователями Postgres. В конечном итоге оказалось, что сегодня даже Postgres поддерживает SQL.

Желание пользоваться стандартом SQL, с одной стороны, и отсутствие доступа к базе данных, поддерживающей SQL, - с другой, поставили Хьюза в трудное положение. Если использовать в Minerva язык запросов, основанный на SQL, то не удастся найти СУБД с соответствующим механизмом работы. Не имея возможности приобрести дорогую РСУБД, Хьюз нашел творческое решение проблемы: выход в том, чтобы создать программу, «на лету» транслирующую запросы SQL в запросы PostQUEL. Такая программа должна была перехватывать все



посылаемые Minerva предложения SQL, преобразовывать их в PostQUEL и результат пересылать дальше в Postgres. Хьюз написал такую программу и назвал ее miniSQL, или mSQL.

От транслятора PostQUEL к РСУБД

В течение некоторого времени такая конфигурация удовлетворяла потребности Хьюза. Для Minerva было безразлично, какая СУБД используется, если только она понимает SQL, и она считала, что Postgres понимает SQL, поскольку в середине находился mSQL, производивший трансляцию в PostQUEL. К несчастью, по мере роста Minerva ее работа стала значительно замедляться. Стало ясно, что ни Postgres, ни другая большая РСУБД не смогут поддерживать тот небольшой набор возможностей, который требовался для Minerva, на тех ограниченных ресурсах, которые были ей доступны. Например, для Minerva требовалось одновременное подключение к нескольким базам данных. Для поддержки этого Postgres требовал одновременного запуска нескольких экземпляров* сервера базы данных. Кроме того, несколько потенциальных участников проекта не могли принять в нем участие, поскольку Postgres не поддерживал их системы, а они не могли позволить себе купить дорогую СУБД с поддержкой SQL.

Оказавшись перед лицом этих проблем, Хьюз пересмотрел свое отношение к Postgres. По своим размерам и сложности она, возможно, превышала потребности Minerva. Большинство запросов, генерируемых Minerva, представляли собой простые операторы INSERT, DELETE и SELECT. Все остальные возможности, имевшиеся в Postgres и снижавшие производительность, просто не требовались для Minerva.

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

История MySQL

Было бы ошибкой рассматривать MySQL просто как ответ на недостатки mSQL. Ее изобретатель Майкл Видениус (известный также как Monty) из шведской компании ТсХ работает с базами данных с 1979 г. До недавнего времени Видениус был в ТсХ только разработчиком. В 1979 г. он разработал для внутрифирменного использования средство управления базами данных под названием UNIREG. После 1979 года UNIREG была переписана на нескольких разных языках и расширена для поддержки больших баз данных.



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

В 1994 г. ТсХ стала разрабатывать приложения для WWW, используя для поддержки этого проекта UNIREG. К несчастью, UNIREG из-за больших накладных расходов не могла успешно использоваться для динамической генерации веб-страниц. И ТсХ начала присматриваться к SQL и mSQL. В то время, однако, mSQL существовала только в виде релизов 1.x. Как мы уже говорили, версии mSQL 1.x не поддерживали никаких индексов и поэтому по производительности уступали UNIREG.

Видениус связался с Хьюзом, автором mSQL, чтобы узнать, не заинтересуется ли тот подключением mSQL к обработчику В+ ISAM в UNIREG. Хьюз, однако, к тому времени уже далеко продвинулся на пути к mSQL 2 и создал средства для работы с индексами. ТсХ решила создать сервер баз данных, более соответствующий ее нуждам.

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

К маю 1995 г. у ТсХ имелась база данных, удовлетворявшая внутренние потребности компании, - MySQL 1.0. Бизнес-партнер фирмы Давид Аксмарк (David Axmark) из Detron HB стал убеждать ТсХ представить свой сервер в Интернет. Цель представления сервера в Интернет -использование бизнес-модели, пионером которой был Аладдин Петер Дейч (Aladdin Peter Deutsch). Результатом стали очень гибкие авторские права, которые делают MySQL «более бесплатной», чем mSQL.

Что касается названия, то Видениус говорит об этом так: «До конца не ясно, откуда идет название MySQL. В ТсХ базовый каталог, а также значительное число библиотек и утилит в течение десятка лет имели префикс «mу». Вместе с тем мою дочь (на несколько лет младше) тоже зовут Май (My). Поэтому остается тайной, какой из двух источников дал название MySQL».



С момента публикации MySQL в Интернет она перенесена на многие UNIX-системы, под Win32 и OS/2. ТсХ считает, что MySQL использует около 500 000 серверов.

Основные изменения, внесенные в текущую рекомендованную версию 3.22:

Усиленная защита.

Ускорение соединений, анализа запросов SQL и улучшенный оптимизатор запросов.

Поддержка большего числа операционных систем.

INSERT DELAYED.

Команды GRANT и REVOKE.

CREATE INDEX и DROP INDEX.

Уровни блокировки HIGH_PRIORITY и LOW_PRIORITY для операторов SELECT, INSERT, UPDATE и DELETE.

Новая команда FLUSH, применимая к TABLES, HOSTS, LOGS и PRIVILEGES.

Новая команда KILL в SQL, действующая, как kill в Unix или msqladmin.

Поддержка выражений в предложении НAVIN G.

Сжатие протокола клиент/сервер.

Сохранение параметров программы по умолчанию в файлах my.cnf. Основные изменения в разрабатываемой версии 3.23:

Таблицы, переносимые напрямую между различными ОС и ЦП.

Временные таблицы и таблицы HEAP, хранимые только в ОЗУ.

Поддержка больших файлов (63 бит) на операционных системах, которые их поддерживают.

Подлинные поля чисел с плавающей точкой.

Комментарии к таблицам.

Шаблон процедуры ANALYSE().

Функции, определяемые пользователем.

Значительное ускорение обработки SELECT DISTINCT.

COUNT(DISTINCT).

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

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

MySQL или mSQL?

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



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

Независимо от того, какую базу данных вы выберете, вы окажетесь в выигрыше. Обе эти базы данных обеспечат большее быстродействие, чем при любом другом выборе. Для объективного сравнения этих баз данных друг с другом и другими продуктами рекомендуем посетить страницу http://www.mysql.com/crash-me-choose.htmy. Она находится на домашней странице MySQL, но представленные на ней критерии можно свободно проверить, а сама страница сделана очень хорошо.


Приложения и базы данных


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

Базы данных существуют для того, чтобы люди могли с ними взаимодействовать. В случае электронных баз данных взаимодействие происходит не непосредственно с базой данных, а косвенно — с помощью программного обеспечения. До появления Всемирной паутины (World Wide Web) базы данных обычно использовались большими корпорациями для поддержки различных деловых функций - бухгалтерии и финансов, контроля поставок и складского учета, планирования производства, учета персонала и т. п. Интернет и более сложные задачи домашних вычислений содействовали перемещению потребностей в использовании баз данных за пределы больших корпораций.

Базы данных и WWW

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

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


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

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

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




Проектирование баз данных


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



Методология логического моделирования данных


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

Выявить и смоделировать сущности.

Выявить и смоделировать связи между сущностями.

Выявить и смоделировать атрибуты.

Указать уникальный идентификатор для каждой сущности.

Провести нормализацию.

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

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



Нормализация


Е. Ф. Кодд (Е. F. Codd), занимавшийся исследовательской работой в IBM, впервые представил концепцию нормализации в нескольких важных статьях, написанных в 1970-е годы. Задача нормализации остается той же самой и сегодня: устранить из базы данных некоторые нежелательные характеристики. В частности ставится задача устранить некоторые виды избыточности данных и благодаря этому избежать аномалий при изменении данных. Аномалии изменения данных - это сложности при операциях вставки, изменения и удаления данных, возникающие из-за структуры базы данных. Дополнительным результатом нормализации является конструкция, хорошо соответствующая реальному миру. Поэтому в результате нормализации модель данных становится более ясной.

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

Первая нормальная форма (1NF)

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

Вернувшись к нашей базе данных, мы обнаруживаем, что повторяющиеся значения есть в атрибуте Song (песня), поэтому очевидно, что база не находится в 1NF. Сущность с повторяющимися значениями указывает на то, что мы упустили еще по крайней мере одну сущность. Обнаружить другие сущности можно, взглянув на каждый атрибут и задавшись вопросом «что описывает эта вещь?»


Что описывает атрибут Song? Он перечисляет все песни на CD. Поэтому Song - это еще один объект, о котором мы собираем данные, и, возможно, он является сущностью. Мы добавим его в свою диаграмму и придадим атрибут Song Name (название песни). Чтобы покончить с сущностью Song, спросим себя, чем еще мы хотели бы ее охарактеризовать. Мы отметили ранее, что длительность песни мы также хотели бы сохранить. Новая модель данных показана на рис. 2-3.



Рис. 2-3. Модель данных с сущностями CD и Song

Теперь, когда Song Name и Song Length являются атрибутами сущности Song, мы имеем модель данных с двумя сущностями в 1NF. К сожалению, мы не указали никакого способа связать вместе CD и Song.

Уникальный идентификатор

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

Он уникален для каждого экземпляра сущности.

Для каждого экземпляра сущности он имеет значение, отличное от NULL в течение всего срока существования экземпляра.

В течение всего времени существования экземпляра его значение не меняется.

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

Новички в моделировании данных часто делают ошибку, выбирая в качестве ID неподходящие атрибуты. Если, к примеру, у вас есть сущность Person (человек, лицо), может возникнуть соблазн выбрать в качестве идентификатора Name (фамилию), поскольку она есть у каждого лица и не меняется. Но что если лицо вступает в брак или законным образом хочет изменить фамилию? Или вы допустили ошибку при первоначальном вводе фамилии? При каждом из этих событий нарушается третье правило для идентификаторов. Еще хуже то, что фамилия окажется не уникальной. Если вы не можете стопроцентно гарантировать, что атрибут Name уникален, вы нарушаете первое правило для идентификаторов. Наконец, вы считаете, что у каждого экземпляра Person фамилия отлична от NULL. Но вы уверены, что всякий раз, вводя первоначальные данные в базу, будете знать фамилию? Ваш процесс может быть организован так, что при начальном создании записи фамилия может быть неизвестна. Из этого следует извлечь тот урок, что при выборе неидентифицирующего атрибута в качестве идентификатора возникает много проблем.



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



Рис. 2-4. Сущности CD и Song со своими уникальными идентификаторами

Связи

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

У каждой стороны связи есть имя, описывающее связь. Возьмем две гипотетические сущности — Служащий и Отдел. Один вариант связи между ними состоит в том, что Служащий «приписан» к Отделу. Этот Отдел «отвечает» за Служащего. Таким образом, связь со стороны Служащий называется «приписан», а со стороны Отдел - «отвечает».

Степень, называемая также кардинальным числом, показывает, сколько экземпляров описывающей сущности должны описывать один экземпляр описываемой сущности. Степень выражается с помощью двух разных значений- «один-к-одному» (1) и «один-ко-многим» (М). Служащий приписан одновременно только к одному отделу, поэтому у сущности Служащий связь с сущностью Отдел «один-к-одному». В обратном направлении, отдел отвечает за многих служащих. Поэтому мы говорим, что у сущности Отдел связь с сущностью Служащий «один-ко-многим». В результате в Отделе может быть и только один Служащий.

Иногда полезно выразить связь словами. Один из способов - вставить разные составляющие направления связи в следующую формулу:



сущность1имеет [одну и только одну одну или много] сущностъ2

Согласно этой формуле связь между Служащим и Отделом можно выразить так:

Каждый Служащий должен быть приписан к одному и только одному

Отделу.

Каждый Отдел может отвечать одному или многим Служащим.



Рис. 2-5. Анатомия связи



Рис. 2-6. Связь CD-'Song

Можно использовать эту формулу для описания сущностей в нашей модели данных. В каждом CD содержится много или одна Song, и каждая Song содержится хотя бы в одном CD. В нашей модели данных эту связь можно показать, проведя линию между двумя сущностями. Степень обозначается прямой линией для связи «один и только один» и «птичьей лапой» для связи «один-ко-многим>>. На рис. 2-5 показаны эти обозначения.

Как это применимо к связи между Song и CD? На практике Song может содержаться на многих CD, но для нашего примера мы этим пренебрежем. На рис. 2-6 показана модель данных с обозначенными связями.

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

Вторая нормальная форма (2NF)

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



Рис. 2-7. Модель данных с новой сущностью Artist

В нашем примере «Herbie Hancock» является Band Name (названием ансамбля) для двух разных CD. Это показывает, что Band Name не полностью зависит от идентификатора CD ID. Это дублирование представляет собой проблему, поскольку если мы допустили ошибку при вводе «Herbie Hancock», придется исправлять значение в нескольких местах. Это указывает нам, что Band Name должно быть частью новой сущности, связанной с CD. Как и раньше, мы решаем эту задачу, задав вопрос: «Что описывает название ансамбля?» Оно описывает ансамбль, или, вообще говоря, исполнителя. Исполнитель - еще один объект, о котором мы собираем данные, и потому, возможно, является сущностью. Мы добавим его к нашей схеме с атрибутом Band Name. Поскольку исполнитель может не быть ансамблем, мы переименуем атрибут как Artist Name. На рис. 2-7 показано новое состояние модели.



Правда, не показаны связи для новой таблицы исполнителей. Ясно, что у каждого Artist может быть один или много CD. У каждого CD может быть один или несколько Artist. Это показано на рис. 2-8.



Рис. 2-8. Связи сущности Artist в модели данных

Вначале мы присвоили атрибут Band Name сущности CD. Поэтому было естественным установить прямую связь между Artist и CD. Но верно ли это? При ближайшем рассмотрении оказывается, что следует установить прямую связь между Artist и Song. У каждого Artist есть одна или много Song. Каждая Song исполняется одним и только одним Artist. Правильные связи показаны на рис. 2-9.

Это не только более разумно, чем связь между Artist и CD, но и решает проблему дисков-сборников.



Рис. 2-9. Подлинная связь между Artist и остальной частью модели данных

Виды связей

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

Если одна сторона имеет степень «один или много», а другая сторона имеет степень «один и только один», то это связь «один-ко-многим» или «1-к-М». Все связи в нашей модели - это связи «один-ко-многим». Этого можно было ожидать, поскольку связи «один-ко-многим» наиболее распространены.

И наконец, последний тип связей - когда обе стороны имеют степень «один-ко-многим». Такого типа связи называются «многие-ко-мно-гим», или «М-к-М». В предыдущей версии нашей модели данных связь Artist-CD имела тип «многие-ко-многим».

Уточнение.связей

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



Связи «многие-ко-многим» встречаются чаще, чем «один-к-одному». В этих связях часто есть некоторые данные, которыми мы хотим охарактеризовать связь. Взглянем, например, на предыдущую версию нашей модели данных на рис. 2-8, в которой была связь «многие-ко-многим» между Artist и CD. Artist имеет связь с CD, поскольку у исполнителя есть одна или несколько Song на этом CD. Модель данных на рис. 2-9 фактически является другим представлением этой связи «многие-ко-многим».

Все связи «многие-ко-многим» нужно разрешать с помощью следующей технологии:

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

Свяжите новую сущность с двумя исходными. Каждая из исходных сущностей должна иметь связь «один-ко-многим» с сущностью-связкой.

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

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



Рис. 2-10. Наша модель данных во второй нормальной форме

Еще о 2NF

Наша модель все еще не приобрела вторую нормальную форму. Значение атрибута Record Label (фирма звукозаписи) имеет только одно значение для каждого CD, но одно и то же значение его присутствует в нескольких СD. Ситуация сходна с той, которая была с атрибутом Band Name. И точно так же дублирование указывает на то, что Record Label должна быть частью отдельной сущности. Каждая Record Label выпускает один или много CD. Каждый CD выпускается одной и только одной Record Label. Модель этой связи представлена на рис. 2-10.



Третья нормальная форма (3NF)

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

Если бы мы пожелали отслеживать адрес Record Label, то столкнулись бы с проблемами для третьей нормальной формы. В сущности Record Label должны быть атрибуты State Name (название штата) и State Abbreviation (сокращенное название штата). Хотя для учета CD эти данные и не нужны, мы добавим их к нашей модели для иллюстрации проблемы. На рис. 2-11 показаны адресные данные в сущности Record Label.



Рис. 2-11. Адресная информация о фирме звукозаписи в нашей базе данных

Значения State Name и State Abbreviation удовлетворяют первой нормальной форме, поскольку имеют только одно значение в каждой записи сущности Record Label. Проблема в том, что State Name и State Abbreviation взаимозависимы. Иными словами, поменяв State Abbreviation для какой-либо Record Label, мы вынуждены будем также изменить State Name. Мы произведем нормализацию, создав сущность State с атрибутами State Name и State Abbreviation. На рис. 2-12 показано, как связать эту новую сущность с сущностью Record Label.

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



Рис. 2-12. Модель данных в третьей нормальной форме




Проектирование баз данных


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

Таблица 2-1. База данных CD, состоящая из одной таблицы

Band Name

CD Title

Record Label

Songs

Stevie Wonder Talking Book Motown You Are the Sunshine of My Life, Maybe Your Baby, Superstition, . . .

Miles Davis Quintet

Miles Smiles

Columbia

Orbits, Circle, . . .

Wayne Shorter

Speak No Evil

Blue Note

Witch Hunt, Fee-Fi-Fo-Fum

Herbie Hancock

Headhunters

Columbia

Chameleon, Watermelon Man, . . .

Herbie Hancock

Maiden Voyage

Blue Note

Maiden Voyage

(Для краткости мы опустили большую часть -песен.) На первый взгляд, эта таблица нам подходит, поскольку в ней есть все необходимые данные. При более близком рассмотрении, однако, мы сталкиваемся с некоторыми проблемами. Возьмем, к примеру, Herbie Hancock. Название ансамбля повторяется дважды - для каждого CD. Это повторение неприятно по нескольким причинам. Во-первых, при вводе данных нам приходится вводить одно и то же несколько раз. Во-вторых, что более важно, при изменении каких-либо данных приходится изменять их в нескольких местах. Что если, к примеру, в Herbie вкралась орфографическая ошибка? Пришлось бы исправлять данные в двух строках. Та же проблема возникнет, если имя Herbie Hancock в будущем изменится (а ля Jefferson Airplane или John Cougar). С добавлением к нашей коллекции новых дисков Herbie Hancock увеличивается объем работы, необходимой для поддержания непротиворечивости данных.


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

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

Сущности в базе данных

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

Атрибуты сущности

Атрибут описывает данные о сущности, которые нужно сохранить. У каждой сущности ноль или более атрибутов, описывающих ее, и каждый атрибут описывает в точности одну сущность. Каждый экземпляр сущности (строка таблицы) имеет в точности одно значение, возможно, равное NULL, для каждого из своих атрибутов. Значение атрибута может быть числом, строкой символов, датой, временем или другим базовым значением данных. На первом этапе проектирования базы данных, логическом моделировании, нас не заботит то, каким образом будут храниться данные.



NULL лежит в основе проблемы, связанной с отсутствующей информацией. Он специально используется тогда, когда какая-то часть данных отсутствует. Рассмотрим, к примеру, ситуацию, когда на CD нет данных о длительности каждой песни. У каждой песни есть длительность, но, глядя на коробку, вы не можете сказать, какова она. Хранить длительность как О нежелательно, поскольку это было бы неверно. Вместо этого вы записываете длительность как NULL. Если вы считаете, что можно сохранить ее как 0 и использовать 0 для обозначения «неизвестной длины», то можете попасть в одну из тех западней, которые привели к проблеме 2000-го года. В старых системах не только год хранится как две цифры, но и придается особое значение величине 9-9-99.

В нашем примере база данных ссылается на ряд объектов - CD, название CD, название ансамбля, песни и название фирмы звукозаписи. Какие из них являются сущностями, а какие - атрибутами?

Модель данных

Обратите внимание, что мы определяем несколько видов данных (название CD, название ансамбля и т. д.), относящихся к каждому CD, и без которых описать CD совершенно невозможно. Поэтому CD является одним из тех объектов, которые мы хотим описать, и, похоже, является сущностью. Начнем разработку модели данных с изображения CD как сущности. На рис. 2-1 показана наша единственная сущность в модели данных.



Рис. 2-1. Сущность «CD» в модели данных

По общепринятому соглашению об именовании сущностей имя сущности должно быть в единственном числе. Поэтому мы называем таблицу, в которой хранятся CD «CD», а не «CDs». Мы используем это соглашение, поскольку каждая сущность дает имя экземпляру. Например, «San Francisco 49ers» является экземпляром сущности «Футбольная команда», а не «Футбольные команды».

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

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



Рис. 2-2. Сущность «CD» с атрибутами




Проектирование физической базы данных


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

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

Объекты становятся таблицами в физической базе данных.

Атрибуты становятся колонками в физической базе данных. Для каждой колонки нужно выбрать подходящий тип данных.

Уникальные идентификаторы становятся колонками, не допускающими значение NULL. В физической базе данных они называются первичными ключами (primary keys). Вы можете также пожелать создать уникальный индекс по идентификатору, чтобы обеспечивать уникальность. Учтите, что в mSQL нет понятия первичного ключа, есть просто уникальные индексы. К MySQL это не относится.

Отношения моделируются в виде внешних ключей (foreign keys). Мы коснемся их позднее.

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

Таблица 2-2. Определения физических таблиц для базы, данных CD

Таблица

Колонка

Тип данных

Примечания

CD

CDId

INT

primary key


CDTitle

TEXT(50)


Artist

Artistld

INT

primary key


ArtistName

TEXT(50)


Song

Songld

INT

primary key


SongName

TEXT(50)


RecordLabel

RecordLabelld

INT

primary key


RecordLabelName

TEXT(50)

primary key

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


Для остальных колонок установлен тип TEXT с длиной 50. Такое определение годится и для MySQL, и для mSQL. Для MySQL, впрочем, лучше было бы выбрать VARCHAR, но это несущественно для нашего примера. Выбор правильного типа данных для колонок очень важен, но мы не будем сейчас на этом останавливаться, поскольку не касались еще типов данных, поддерживаемых MySQL и mSQL.

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

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

Чаще всего отношение имеет тип «1-к-М». Ему соответствует первичный ключ со стороны «1», помещенный в таблицу на стороне «многие». В нашем примере это означает, что нужно сделать следующее:

Поместить колонку RecordLabelId в таблицу CD.

Поместить колонку CDId в таблицу Song.

Поместить колонку Artistic! в таблицу Song. Полученная схема показана в таблице 2-3.

Таблица 2-3. Физическая модель данных для базы данных CD



Таблица



Колонка



Тип данных



Примечания



CD



Cdld



INT



primary key







CDTitle



TEXT(50)











RecordLabelld



INT



foreign key



Artist



Artistld



INT



primary key







ArtistName



TEXT(50)







Song



Songld



INT



primary key







SongName



TEXT(50)











Cdld



INT



foreign key







Artistld



INT



foreign key



RecordLabel



RecordLabelld



INT



primary key







RecordLabelName



TEXT(50)





<


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

Теперь у нас есть полная физическая схема базы данных. Осталось перевести эту схему на SQL. Для каждой таблицы в схеме вы пишете одну команду CREATE TABLE. Обычно для поддержки уникальности создается уникальный индекс по первичным ключам.

В некотором смысле мы сейчас забегаем вперед. Вы, возможно, не знакомы с SQL, а в задачи данной главы не входит знакомство с версиями SQL, поддерживаемыми MySQL и mSQL. Все же, вот два простых сценария для создания базы данных CD. Первый сценарий, пример 2-1, составлен для MySQL, пример 2-2 — для mSQL.

Пример 2-1. Сценарий создания базы данных CD в MySQL

CREATE TABLE CD (CDID INT NOT NULL,

RECORD_LABEL_I INT, CD_TITLE TEXT, PRIMARY KEY (CD_ID))

CREATE TABLE Artist (ARTIST_ID INT NOT NULL, ARTIST_NAMETEXT,

PRIMARY KEY (ARTIST_ID)) CREATE TABLE Song (SONG_ID INT NOT NULL, CD_ID INT, SONG_NAME TEXT, PRIMARY KEY (SONG_ID))

CREATE TABLE RecorLabel(RECORD LABEL_ID INT NOT NULL, RECORD_LABEL_NAME TEXT, PRIMARY KEY(RECORD_LABEL_ID))

Пример 2-2. Сценарий создания базы данных CD в mSQL

CREATE TABLE CD (CD_ID INT NOT NULL,

RECORD_LABEL_IDINT, CD_TITLE TEXT(50))

CREATE UNIQUE INDEX CD_IDX ON 0(DCD.ID)

CREATE TABLE ArtistARTIST_ID INT NO NULL,

ARTIST_NAMETEXT(50))

CREATE UNIQUE INDEX Artist_IDX ON Artist (ARTIST_ID)

CREATE TABLE Song (SONG_ID INT NOT NULL, CD_ID INT,

SONG_NAME TEXT(50))

CREATE UNIQUE INDEX Song_IDX ON Song (SONG_ID)

CREATE TABLE RecordLabel (RECORD_LABEL_IDINT NOT NULL,

RECORD_LABEL_NAMEEXT(50))

CREATE UNIQUE INDEX RecordLabel_IDX

ON RecordLabel(RECORD_LABEL_ID)

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


Установка


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



MSQL


Первым шагом в установке mSQL является получение дистрибутива исходного кода. На момент написания этой книги самые новые версии mSQL распределялись только с веб-страницы Hughes Technology на http://www.hughes.com.avl. Автор mSQL предпочел официально не распространять двоичные дистрибутивы mSQL. Если на вашей машине нет компилятора С, то вам следует либо установить его, либо скомпилировать на такой же машине с той же операционной системой и перенести результат.

Полученный дистрибутив с исходным кодом mSQL распакуйте командой:

gunzip - с msql-2.0.4.1.tar.gz | tar xvf -

В результате в рабочем каталоге будет образован каталог с именем msq 1-2.0.4.1. Перейдите в него.

Создайте на своей машине инсталляционный каталог командой:

make target

Теперь перейдите в каталог targets. В нем должен быть новый каталог с названием вашей операционной системы и платформы, например, Solaris-2.6-Spare или Linux-2.0. 33-1386. Перейдите в этот каталог.

В рабочем каталоге запустите сценарий setup. Лучше запустите его как . /setup, чтобы командный процессор не запустил программу setup из какого-нибудь другого каталога. Сценарий сконфигурирует исходный код для компиляции. После выполнения сценария рассмотрите файл site.mm и измените необходимые параметры для настройки своей локальной установки. В частности, вы, возможно, захотите изменить переменную INST_DIR, задающую каталог, в который устанавливается mSQL. Если конфигурация вас устраивает, для компиляции mSQL выполните команду:

make all

После компиляции установите mSQL в выбранный вами каталог с помощью команды:

make install

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

gzip - с msql-x.x.x.tar.gz tar xvf -

cd msql-x.x.x

make target

cd targets/myOS-mymachine

./setup

make all

make install



MySQL


Прежде чем начать установку MySQL, нужно ответить на пару вопросов.

Собираетесь ли вы устанавливать MySQL как пользователь root или какой-либо другой пользователь?

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

Будете ли вы устанавливать MySQL из исходного кода или откомпилированных модулей?

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

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

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

Таблица 3-1. Список серверов Интернета, с которых можно взять экземпляр исходного кода или двоичных файлов MySQL

Азия

Корея

KREONet

http://linux.kreonet.re.hr/mysql/

Япония

Soft Agency

http://www.softagency.co.jp/MySQL/


Nagoya Syouka University

http://mirror.nucba.ac.jp/mirror/mysql/


Nagoya Syouka University

ftp://mirror.nucba.ac.jp/mirror/ mysql/


HappySize

http://www.happysize.co.jp/mysql/


HappySize

ftp://ftp.happysize.co.jp/pub/mysql/

Сингапур

HJC

http://mysql.hjc.edu.sg/


HJC

ftp://ftp.hjc.edu.sg/mysql/

Тайвань

NCTU

http://mysql.taconet.com.tw/


TTN

http://mysql.ttn.net

Австралия

Австралия

AARNet/Queensland

http://mirror.aarnet.edu.au/mysql/


AARNet/Queensland

ftp://mirror.aarnet.edu.au/pub/ mysql/


Blue Planet/Melbourne

http://mysql.bluep.com


Blue Planet/Melbourne

ftp://mysql.bluep.com/pub/mirrorl/ mysql/


Tas

http://ftp.tas.gov.au/mysql/


Tas

ftp://ftp.tas.gov.au/pub/mysql/

Африка

Южная Африка

The Internet Solution/ Johannesburg

ftp://ftp.is.co.za/linux/mysql/

<


Европа



Австрия



University of Technology/Vienna



http://gd.tuwien.ac.at/db/mysql/







University of Technology/Vienna



ftp://gd.tuwien.ac.at/db/mysql/



Болгария



Naturella



ftp://ftp.ntrl.net/pub/mirror/mysql/



Дания



Ake



http://mysql.ake.dk







SunSITE



http://sunsite.auc.dk/mysql/







SunSITE



ftp://sunsite.auc.dk/pub/databases/ mysql/



Эстония



Tradenet



http://mysql.tradenet.ee



Финляндия



EUnet



http://mysql.eunet.fi



Франция



Minet



http://www.minet.net/devel/mysql/



Германия



Bonn University, Bonn



http://www.wipol.uni-bonn.de/ MySQL/







Bonn University, Bonn



http://www.wipol.uni-bonn.de/ MySQL/







Wolfenbuettel



http://www.fh-wolfenbuettel.de/ftp/ pub/database/ mysql/







Wolfenbuettel



ftp://ftp.fh-wolfenbuettel.de/pub/ database/ mysql/







Staufen



http://mysql.staufen.de



Греция



NTUA, Athens



http://www.ntua.gr/mysql/







NTUA, Athens



ftp://ftp.ntua.gr/pub/databases/



Венгрия



Xenia



http://xenia.sote.hu/ftp/mirrors/







Xenia



ftp://xenia.sote.hu/pub/mirrors/



Израиль



Netvision



http://mysql.netvision.net.il



Италия



Teta Srl



http://www.teta.it/mysql/



Польша



Sunsite



http://sunsite.icm.edu.pl/mysql/







Sunsite



ftp://sunsite.icm.edu.pl/pub/unix/



Португалия



lerianet



http://mysql.leirianet.pt







lerianet



ftp://ftp.leirianet.pt/pub/mysql/



Россия



DirectNet



http://mysql.directnet.ru







IZHCOM



http://mysql.udm.net







IZHCOM



http://mysql.udm.net



Румыния



Bucharest



http://www.lbi.ro/MySQL/







Bucharest



ftp://ftp.lbi.ro/mirrors/ftp.tcx.se







Timisoara



http://www.dnttm.ro/mysql/







Timisoara



ftp://ftp.dnttm.ro/pub/mysql



Швеция



Sunet



http://ftp.sunet.se/pub/unix/ databases/ relational/ my sql/







Sunet



ftp://ftp.dnttm.ro/pub/mysql







тcх



http://www.tcx.se







тcх



ftp://www.tcx.se







тcх



http://www.mysql.com (Primary Site)







тcх



ftp://ftp.mysql.com (Primary Site)



Англия



Omnipotent/UK



http://mysql.omnipotent.net







Omnipotent/UK



ftp://mysql.omnipotent.net







PHG/UK



http://ftp.plig.org/pub/mysql/







PliG/UK



ftp://ftp.plig.org/pub/mysql/



Украина



РАСО



http://mysql.paco.net.ua







РАСО



ftp://mysql.paco.net.ua



Северная Америка



Канада



Tryc



http://web.tryc.on.ca/mysql/



США



Circle Net/North Carolina



http://www.mysql.net







DIGEX



ftp://ftp.digex.net/pub/database/







Gina net/Florida



http://www.gina.net/mysql/







Hurricane Electric/San Jose



http://mysql.he.net







Netcasting/West Coast



ftp://ftp.netcasting.net/pub/mysql/







Phoenix



http://phoenix.acs.ttu.edu/mysql/







pingzero/Los Angeles



http://mysql.pingzero.net



Южная Америка



Чили



Amerikanclaris



http://www.labs.amerikanclaris.cl/







vision



http://mysql.vision.cl

<


Подключившись к серверу FTP, войдите в каталог Downloads. В нем будут перечислены несколько версий MySQL, например:

MySQL-3.21

MySQL-3.22

MySQL-3.23

Самый высокий номер версии соответствует нестабильному выпуску, в котором производится добавление и проверка новых характеристик. Отдельные подверсии его будут иметь пометки 'alpha', 'beta' или 'gamma'. Предыдущая версия является текущей стабильной версией. Эта версия тщательно проверена и считается свободной от ошибок. Доступны также более ранние архивные версии.

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

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

mysql-3.22.19-beta-sgi-irix6,4-mip.tgz

mysql-3.22.21a-beta-ibm-aix4.2.1.0-rs6000.tgz

mysql-3.22.31-pc-linux-gnu-i586.tgz

mysql-3.22.33-sun-solaris2.6-sparc.tgz

mysql-3.22.33.tar.gz

Файлы, имена которых включают названия машин и операционных систем, являются двоичными версиями для этих систем. Если название машины не указано, как в последней строке, то это исходный код. Если к файлу не присоединена метка 'alpha', 'beta' или 'gamma' - это стабильная версия. Что касается двух последних файлов списка, то первый - откомпилированная версия для Sun Solaris на машине Spare, а последний - исходный код. Прочие, более старые версии существуют, поскольку у команды разработчиков не всегда есть время и возможность откомпилировать каждую подверсию MySQL на каждой существующей операционной системе и аппаратной конфигурации. В действительности, большая часть прекомпилированных версий предоставлена обычными пользователями, которым удалось успешно откомпилировать последнюю версию на своей системе.



Зная это, вы можете теперь выбрать версию MySQL, которую хотите использовать, и загрузить исходный код, если собираетесь компилировать MySQL, или двоичный дистрибутив для вашей машины, если он существует. Когда отсутствует двоичный дистрибутив, точно соответствующий вашей конфигурации, проверьте, нет ли его для слегка отличной конфигурации. Например, mysql-3.22.32a-ibm-aix4.2.1.0-powerpc.tgz может работать также на версии AIX 4.1.4 на том же типе машин. Если вы не можете таким образом подобрать работающую версию, попробуйте поискать в более старых версиях MySQL. Если и это не удастся, придется компилировать исходный код. В случае успешной компиляции и запуска MySQL можно предоставить откомпилированные двоичные файлы команде разработчиков MySQL для включения в архив.

Установка из исходного кода

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

gunzip - с mysql-x.xx.xx.tar.gz | tar xvf -

где mysql-x. xx. xx . tar. gz - имя загруженного вами файла. В результате в рабочем каталоге будет создан каталог mysql-x. xx. xx. Перейдите в него. Запустите сценарий configure в рабочем каталоге. Вызовите его как . /configure, чтобы случайно не запустить программу с тем же именем, находящуюся где-либо в другом месте. Во многих случаях установка прекрасно проходит без задания каких-либо параметров, но при возникновении трудностей можно использовать многочисленные параметры, информацию о которых можно вывести на экран, задав ключ -help. Вот наиболее употребительные:

--without-server

В результате компилируются все имеющиеся клиенты MySQL, но не сервер.

-prefix

Устанавливается каталог инсталляции, отличный от каталога по умолчанию (/usr/ local/ ).

-with-low-memory

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

-localstatedir

Используется для назначения каталога для файлов базы данных, отличающегося от принятого по умолчанию (/usr/local/var).



-with-charset

Используется для выбора набора символов, отличного от принятого по умолчанию (lati.nl). На момент написания книги доступны наборы символов big5, danish, cp1251, cp1257, croat, czech, dec8, dos,

euc_kr, germanl, Hebrew, hp8, hungarian, koi8_ru, koi8_ukr, latin1, Iatin2, swe7, usa7, win1251, win1251u, kr, ujis, sjis, tis620.

После завершения выполнения сценария configure запустите make в рабочем каталоге. В результате будет произведена полная компиляция.

По завершении компиляции команда make install установит все в нужное место.

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

./scripts/mysql_install_db

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

./bin/mysqladmin version

На экран будет выведено что-то, близкое к следующему:

mysqladmin Ver 7.11 Distrib 3.22.23b, for linux on 1586

TCX Datakonsult AB, by Monty

Server version 3.22.23b-debug

Protocol version 10

Connection Localhost via UNIX socket

UNIX socket /tmp/mysql.sock

Uptime: 6 sec

Threads: 1 Questions: 1 Slow queries: 0 Opens: 6 Flush tables: 1 Open

tables: 2 Memory in use: 1093K Max memory used: 1093K

Итак, последовательность шагов установки такова:

gzip - с mysql-x.xx. xx. tar. gz | tar xvf -

cd mysql-x.xx.xx

./configure

make

make install

./scripts/mysql_install_db

./bin/mysqladmin version

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

Загрузив двоичный дистрибутив, вы должны выбрать каталог для установки файлов MySQL. Чаще всего выбирается /usr/local/mysql, но это в значительной мере зависит от потребностей ваших пользователей, и имеющихся у вас прав доступа.

Перейдите в каталог на уровень выше, чем тот, в котором вы хотите разместить дистрибутив MySQL. Например, если вы хотите использовать /usr/local/mysql, перейдите в /usr/local. Для распаковки дистрибутива выполните команду:



gunzip - с /tmp/mysql-x.xx.xx-fflymac/line. tgz | tar xvf -

Здесь /tmp - имя каталога, в который вы загрузили дистрибутив MySQL, a mysql-x.xx.xx-mymachine.tgz - имя загруженного файла.

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

In - s mysql-x.xx.xx mysql

Теперь проверьте, содержит ли двоичный пакет таблицы назначения прав доступа. Перейдите в каталог mysql/mysql. Если он не существует или пуст, вам придется создать таблицы самому. Вернитесь назад, на один уровень, в главный каталог установки mysql и выполните команду:

scripts/mysql_install_db

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

bin/safe_mysqld --log &

Чтобы убедиться, что демон правильно работает, введите:

bin/mysqladmin version

Ответ должен быть примерно таким:

Mysqladmin Ver 6.3 Distrib 3.21.33, for sun-solaris2.6 on spare

TCX Datakonsult AB, by Monty

Server version 3.21.17-alpha

Protocol version 10

Connection Localhost via UNIX socket

TCP Port 3333

UNIX socket /tmp/mysql.sock

Uptime: 13 sec

Running threads: 1 Questions: 20 Reloads: 2 Open Tables: 3




Администрирование базы данных


Теперь, когда у вас есть свежеустановленная и запущенная MySQL, нужно первым делом поменять пароль суперпользователя сервера, выполнив из каталога, в который установлена MySQL, команду:

./bin/mysqladmin -u root password 'mynewpasswd'

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

Утилита mysqladmin

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

Создание баз данных

Ваш сервер бесполезен, пока нет баз данных, которые он обслуживает. С помощью mysqladmin можно создавать новые базы данных:

mysqladmin -p create DATABASENAME

Параметр -р указывает, что вы хотите, чтобы было выдано приглашение для ввода пароля суперпользователя, который вы задали раньше. Если вы введете правильный пароль, то mysqladmin создаст новую пустую базу данных с именем, которое вы указали. Поскольку в MySQL база данных - это каталог с группой файлов, команда mysqladmin create создает новый каталог, который будет содержать файлы базы данных. Например, если вы создали базу данных с именем «mydata», в каталоге data, содержащемся в директории, в которую установлена MySQL, будет создан каталог mydata.

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

Удаление базы данных

В процессе разработки приложения вам, вероятно, потребуется создать несколько баз данных для поддержки процесса разработки. Например, обычной практикой в разработке приложений баз данных является создание отдельных баз данных для разработки, тестирования и работы. По завершении разработки следует избавиться от этих промежуточных баз данных. Утилита mysqladmin позволяет удалить базу данных с помощью параметра «drop»:


mysqladmin -p drop DATABASENAME

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

Переименование и копирование баз данных

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

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

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

Uptime: 395 Threads: 1 Questions: 14 Slow queries: 0

Opens: 10 Flush tables: 1 Open tables: 6

Выводимые величины означают следующее: Uptime

Число секунд, в течение которых сервер запущен и работает. Threads

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

Questions

Число запросов, переданных базе данных с момента запуска.



Slow queries

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

Opens

Число таблиц, открытых с момента запуска сервера.

Flush tables

Количество команд flush, refresh и reload.

Open tables

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

Если компиляция MySQL производилась с параметром --with-debug , то mysqladmin status показывает также текущую и максимальную величину используемой памяти.

Если вас интересует более общая статическая информация, то выполните команду mysqladmin version. Она выдает на экран следующее:

bin/mysqladmin Ver 7.8 Distrib 3.22.17, for sun-solaris2.6 on spare TCX Datakonsult AB, by Monty

Server version 3.22.17

Protocol version 10

Connection Localhost via Unix socket

Unix socket /tmp/;ny3ql. sock

Uptime: 23 mm 58 sec

Threads: 1 Questions: 15 Slow queries: 0 Opens: 10 Flush tables: 1 Open tables: 6

Последняя строка совпадает, конечно, с теми данными, которые показывает mysqladmin status. Остальные данные совершенно другие.

Server version

Версия запущенного сервера MySQL. Protocol version

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

Connection

Метод подключения к серверу. В нашем примере клиент общается с MySQL через сокет Unix. Если вы обращаетесь к удаленному серверу, в этой позиции будет имя машины, с которой вы подключились.

Unix socket

Имя файла сокета, который вы используете для обмена данными с сервером. Если вы связываетесь с MySQL через TCP/IP, вместо этого пункта будет указан пункт TCP port с номером порта MySQL.



Uptime

Суммарное время работы сервера.

Две другие команды, mysqladmin variables и mysqladmin extended-status, предлагают дополнительную информацию.

Поскольку MySQL многопоточна, отследить активность процесса с помощью команды Unix ps не просто. Несмотря на то что выполняется несколько потоков, в списке процессов будет указан только один процесс. MySQL позволяет справиться с этим с помощью команды mysqladmin processlist, которая перечисляет все активные потоки в виде чудесно представленной таблички:



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

Id

Внутренний идентификационный номер потока. Это значение не имеет отношения к каким-либо системным ID процессов. Вы можете использовать это число в команде mysqladmin kill, чтобы завершить поток.

User

Пользователь, подключенный к серверу через этот поток.

Host

Имя узла, с которого подключился пользователь.

db

База данных, к которой подключен пользователь.

Command

Тип команды, выполняемой потоком. Команда может иметь один из следующих типов:

Sleep

Поток ждет ввода пользователя. Большинство процессов должно находиться в этом состоянии.

Quit

Поток в процессе завершения.

Init DB

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

Query

Поток выполняет реальный запрос. Хотя наибольшая часть взаимодействия с базой данных происходит в виде запросов, эти команды производятся очень быстро и редко появляются в выдаче.

Field list

Поток создает список полей в таблице.

Create DB

Поток создает новую базу данных.

Drop DB

Поток удаляет базу данных.

Reload

Поток перезагружает таблицы доступа MySQL. После перезагрузки все новые потоки будут использовать обновленные таблицы доступа.

Shutdown

Поток находится в процессе завершения всех других потоков и закрытия сервера.

Statistics

Поток генерирует статистику.



Processes

Этот поток анализирует другие потоки. С этим значением будет показан поток, выполняющий данную команду.

Connect

Поток в процессе установления входящего соединения с клиентом.

Kill

Этот поток завершает другой поток.

Refresh

Поток очищает все буферы и сбрасывает журнальные файлы.

Файлы журналов MySQL дают еще один способ получения полезной информации для администрирования сервера. MySQL создает главный журнал, если mysqld запускается с параметром --log. Этот журнал ведется в файле /usr/local/var/HOSTNAME.log, где HOSTNAME - имя машины, на которой запущен MySQL. В этот журнал записываются подключения к серверу и команды, посылаемые ему клиентами.

Задав параметр -debug для mysqld (или safe_mysqld), вы заставите MySQL посылать в журнал дополнительную информацию. Пакет отладки, используемый MySQL, имеет десятки параметров, большинство из которых вы никогда не будете использовать. Наиболее часто используется установка -d:t:o,FILENAME, где FILENAME - имя журнала отладки, который вы хотите использовать. При задании этого параметра в журнал будут заноситься практически все действия сервера, шаг за шагом.

MySQL поддерживает еще один журнал, пригодный для чтения. Если запустить MySQL с параметром -log-update, будет создан файл с именем HOSTNAME. #, где HOSTNAME имя машины, a #- уникальное число. В этом журнале содержатся все изменения, вносимые в таблицы баз данных. Этот журнал создается в виде SQL, поэтому все операции можно воспроизвести на другом сервере баз данных.

Завершение работы сервера

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

mysqladmin -p shutdown

Эта команда - самый правильный способ завершения работы сервера. Если вы запустили MySQL с помощью safe_mysqld и пытаетесь закрыть сервер каким-либо другим способом, safe_mysqld просто запустит еще один экземпляр сервера. Можно также безопасно закрыть сервер традиционной Unix-командой kill, но никогда не пользуйтесь kill-9.

Параметры командной строки для mysqladmin



Утилита mysqladmin - очень богатый инструмент со множеством параметров командной строки. Общий ее формат

mysqladmin OPTIONS COMMAND1 COMMAND2 . . . COMMANDn

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

mysqladmin -p create silly drop silly

Эта команда одним махом создаст и уничтожит базу данных «silly». Вот перечень команд, которые можно передать mysqladmin:

create DATABASENAME

Создает новую базу данных с указанным именем.

drop DATABASENAME

Удаляет базу данных с указанным именем.

extended-status

Выдает расширенное сообщение о статусе сервера.

flush-hosts

Немедленно записывает все буферизованные изменения на удаленных компьютерах.

flush-logs

Немедленно записывает все буферизованные изменения в журналы.

flush-tables

Немедленно записывает все буферизованные изменения в таблицы.

flush-privileges

То же, что reload.

killID1,ID2.....IDn

Завершает потоки с заданными IDs.

password NEWPASSWORD

Заменяет пароль на новое значение.

ping

Проверяет, работает ли еще mysqld.

processlist

Выдает список активных потоков.

reload

Заново загружает все таблицы доступа.

refresh

Записывает буферизованные изменения во все таблицы и закрывает и открывает все журналы.

shutdown

Завершает работу сервера.

status

Выдает краткое сообщение о состоянии сервера.

variables

Выдает значения имеющихся переменных.

version

Выдает данные о версии сервера.

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

-# LOG

Выдача отладочной информации в журнал. Часто это 'd:t:o,FILENAME'.

-f

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

-? или --help

Выдача подсказки по использованию утилиты msqladmin.



Использовать сжатие в протоколе клиент/сервер.

-Н HOST

Подключиться к указанному компьютеру.

-р [PASSWORD]

Использовать указанный пароль для проверки прав пользователя.



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

-Р PORT

Использовать для подключения указанный порт.

-i SECONDS

Повторно выполнять команды через заданный промежуток времени.

-s

Выйти без сообщений, если соединение с сервером невозможно установить.

-S SOCKET

Файл для использования в качестве сокета Unix.

-t TIMEOUT

Тайм-аут для соединения.

-u USER

Имя для регистрации пользователя, если оно отлично от текущего.

-V

Выдать информацию о версии и завершить работу.

-w COUNT

Ждать и повторить попытку заданное число раз, если сервер в данный момент не готов.

Резервирование данных

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

В главе 5 «mSQL» приводится подробное изложение роли команды msqldump при резервировании данных mSQL. MySQL поддерживает почти идентичную функциональность в виде команды mysqldump. Мы рекомендуем изучить этот пункт, чтобы понять роль mysqldump при полном резервировании баз данных. В данном параграфе мы остановимся на следующем наиболее важном виде резервирования - инкре-ментном резервировании.

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

При использовании MySQL инкрементное резервирование можно производить, используя такую возможность сервера баз данных, как «update log» - журнал изменений MySQL. Если сервер баз данных mysqld запущен с параметром --log-update, то все изменения в базе данных будут сохраняться в файле в виде команд SQL. Изменения будут сохраняться в порядке их производства. В результате получается файл, который, будучи обработан монитором mysql, воспроизведет все действия, произведенные над базой данных. Если журнал хранится с самого образования базы данных, то будет восстановлен весь жизненный цикл базы данных, который приведет ее в текущее состояние.



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

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

Система безопасности

Вам не только нужно иметь надежный доступ к своим данным, но и быть уверенным, что у других нет никакого доступа к ним. MySQL использует собственный сервер баз данных для обеспечения безопасности. При первоначальной установке MySQL создается база данных под названием «mysql». В этой базе есть пять таблиц: db, host, user, tab-les_priv, и columns_priv . Более новые версии MySQL создают также базу данных с названием func, но она не имеет отношения к безопасности. MySQL использует эти таблицы для определения того, кому что позволено делать. Таблица user содержит данные по безопасности, относящиеся к серверу в целом. Таблица host содержит права доступа к серверу для удаленных компьютеров. И наконец, db, tables_priv и со-lumns_priv управляют доступом к отдельным базам данных, таблицам и колонкам.



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

Таблица user

Таблица user имеет вид, показанный в Таблице 4-1:

Таблица 4-1. Таблица user



Поле



Тип



Null



Ключ



Значение



Примеч.



















по умолчанию







Host



char(60)







PRI











User



char(16)







PRI













Поле



Тип



Null



Ключ



Значение



Примеч.



















по умолчанию







Password



char(16)



















Select_priv



enum('N','Y')











N





Insert priv enum('N','Y')   N  


Update_priv



enum('N','Y')











N







Delete_priv



enum('N','Y')











N







Create_priv



enum('N','Y')











N







Drop priv



enum('N','Y')











N







Reload priv



enum('N','Y')











N







Shutdown_priv



enum('N','Y')











N







Process_priv



enum('N','Y')











N







File_priv



enum('N','Y')











N







Grant_priv



enum('N','Y')











N







References_priv



enum('N','Y')











N







Index_priv



enum('N','Y')











N







Alter_priv



enum('N','Y')











N





В колонках Host и User можно использовать символ «% », заменяющий произвольную последовательность символов. Например, имя узла «chem%lab» включает в себя «chembiolab», «chemtestlab» и т. д. Специальное имя пользователя «nobody» действует как одиночный «% », то есть охватывает всех пользователей, не упомянутых где-либо в другом месте. Ниже разъясняется смысл различных прав доступа:

Select_priv

Возможность выполнять команды SELECT.

Insert__priv

Возможность выполнять команды INSERT.

Update_priv

Возможность выполнять команды UPDATE.

Delete_priv

Возможность выполнять команды DELETE.

Createjyriv

Возможность выполнять команды CREATE или создавать базы данных.



Drop_priv

Возможность выполнять команды DROP для удаления баз данных.

Reload_priv

Возможность перезагружать информацию о доступе с помощью mysqladmin reload.

Shutdown_priv

Возможность останавливать сервер через mysqladmin shutdown.

Process_priv

Возможность управлять процессами сервера.

File_priv

Возможность читать и записывать файлы с помощью команд типа SELECT INTO OUTFILE и LOAD DATA INFILE.

Grant_priv

Возможность давать привилегии другим пользователям.

Index_priv

Возможность создавать и уничтожать индексы.

Alter_priv

Возможность выполнять команду ALTER TABLE.

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

INSERT INTO user (Host, User, Password, Select_priv,

Insert_priv, Update_priv, Dclete_priv)

VALUES ('%', 'bob', password('mypass'), 'Y', 'Y', 'Y'.'Y')

INSERT INTO user (Host, User, Password, Select_priv)

VALUES ('athens.imaginary.com', 'jane', '', 'Y')

INSERT INTO user (Host, User, Password)

VALUES ('%', 'nobody', ")

INSERT INTO user (Host, User, Password, Select_pnv,

Insert_priv, Updatejriv, Delete_priv)

VALUES ('athens.imaginary.com', 'nobody',

password('thispass'), 'Y', 'Y', 'Y', 'Y')

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

Первый созданный нами пользователь, «bob», может подключаться к базе данных с любого компьютера и выполнять команды SELECT, INSERT, UPDATE и DELETE. Второй пользователь, «jane», может подключаться с «athens.imaginary.com», не имеет пароля и может выполнять только SELECT. Третий пользователь - «nobody» - с любой машины.'Этот пользователь вообще ничего не может делать. Последний пользователь -«nobody» - с машины «athens.imaginary.com», он может выполнять SELECT, INSERT, UPDATE и DELETE, как и пользователь «bob.»



Как MySQL производит сопоставление? Возможно, вы обратили внимание, что некоторое имя может соответствовать на деле нескольким записям. Например, «nobody@athens.imaginary.com» соответствует и «nobody@%», и «nobody@athens.imaginary.com». Прежде чем осуществлять поиск в таблице user, MySQL сортирует данные следующим образом:

Сначала ищется соответствие для узлов, не содержащих масок « % », при этом пустое поле Host трактуется как «% ».

Для одного и того же узла сначала проверяется соответствие имен, не содержащих масок. Пустое поле User трактуется как содержащее «%».

Первое найденное соответствие считается окончательным.

В предыдущем примере пользователь сначала будет сравниваться с «nobody» из «athens.imagmary.com», поскольку «athens.imaginary.com» в порядке сортировки стоит выше «% ». Поскольку имена компьютеров сортируются раньше имен пользователей, значения привилегий для компьютера, с которого вы подключаетесь, имеют приоритет перед любыми конкретными правами, которые у вас могут быть. Например, если таблица user содержит записи:



Host



User



%

athens .imaginary .com



jane

и jane подключается с «athens.imaginary.com», то MySQL будет использовать привилегии, данные «athens.imaginary.com».

Таблица db

Вы могли обратить внимание, что в таблице user не упоминаются конкретные базы данных и таблицы. Таблица user управляет сервером в целом. Однако на сервере обычно находится несколько баз данных, которые служат различным целям и, соответственно, обслуживают разные группы пользователей. Права доступа к отдельным базам данных хранятся в таблице db. Эта таблица имеет структуру, представленную в таблице 4-2:

Таблица 4-2. Таблица db



Поле



Тип



Null



Ключ



Значение по умолчанию



Примеч.



Host



char(60)







PRI











Db



char(32)







PRI











User



char(16)







PRI











Select priv



enum('N','Y')











N







Insert_priv



enum('N','Y')











N







Update_priv



enum('N','Y')











N







Delete priv



enum('N','Y')











N







Create_priv



enum('N','Y')











N







Drop_priv



enum('N','Y')











N







Referen-



enum('N','Y')











N







ces_priv























Index_priv



enum('N','Y')











N







Alter_priv



enum('N','Y')











N





<


Эта таблица во многом похожа на таблицу user. Основное отличие в том, что вместо колонки Password имеется колонка Db. Таблица управляет правами пользователей в отношении определенных баз данных. Поскольку привилегии, указанные в таблице user, относятся ко всему серверу в целом, права, присвоенные пользователю в таблице user, перекрывают права, присвоенные тому же пользователю в таблице db. Например, если пользователю в таблице user разрешают доступ типа INSERT, это право действует в отношении всех баз данных, вне зависимости от того, что указано в таблице db.

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

Те же правила, которые действуют в отношении колонок User и Host в таблице user, действуют и в таблице db, но с некоторой особенностью. Пустое поле Host вынуждает MySQL найти запись, соответствующую имени узла пользователя, в таблице host. Если такой записи не найдено, MySQL отказывает в доступе. Если соответствие найдено, MySQL определяет права как пересечение прав, определяемых таблицами host и db. Иными словами, в обеих записях разрешение должно иметь значение «Y», иначе в доступе отказывается.

Таблица host

Таблица host служит особой цели. Ее структура показана в таблице 4-3:

Таблица 4-3. Таблица Host



Поле



Тип



Null



Ключ



Значение по умолчанию



Примеч.



Host



char(60)







PRI











Db



char(32)







PRI











Select_priv



enum('N','Y')











N







Insert_priv



enum('N','Y')











N







Update_priv



enum('N','Y')











N







Delete_priv



enum('N','Y')











N







Create_priv



enum('N','Y')











N







Drop_priv



enum('N','Y')











N







Grant_priv



enum('N','Y')











N







Referen-



enum('NYY')











N







ces_priv























Index_priv



enum('N','Y')











N







Alter_priv



enum('N','Y')











N





<


Таблица host позволяет задать основные разрешения на межкомпьютерном уровне. При проверке прав доступа MySQL ищет в таблице db соответствие имени пользователя и его машине. Если он находит запись, соответствующую имени пользователя, поле host которой пусто, MySQL обращается к таблице host и использует пересечение обоих прав для определения окончательного права доступа. Например, у вас может быть группа серверов, которые вы считаете менее защищенными, чем остальная часть сети. Вы можете запретить для них все права записи. Если «bob» заходит с одной из таких машин, и его запись в таблице db содержит пустое поле host, ему будет запрещена операция записи, даже если она разрешена ему согласно таблице db.

Таблицы tables_priv и colums_priv

Эти две таблицы, по сути, уточняют данные, имеющиеся в таблице db. Именно, право на всякую операцию сначала проверяется по таблице db, затем по таблице tables_priv , затем по таблице columns_priv . Операция разрешается, если одна из них дает разрешение. С помощью этих таблиц можно сузить область действия разрешений до уровня таблиц и колонок. Управлять этими таблицами можно через команды SQL GRANT и REVOKE.

Последовательность контроля доступа

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

При подключении проводятся две проверки. Сначала MySQL проверяет, есть ли в таблице user запись, соответствующая имени пользователя и машины, с которой он подключается. Поиск соответствия основывается на правилах, которые мы обсудили раньше. Если соответствие не найдено, в доступе отказывается. В случае когда соответствующая запись найдена и имеет непустое поле Password , необходимо ввести правильный пароль. Неправильный пароль приводит к отклонению запроса на подключение.

Если соединение установлено, MySQL переходит к этапу верификации запроса. При этом сделанные вами запросы сопоставляются с вашими правами. Эти права MySQL проверяет по таблицам user, db, host, tables_priv и columns__priv . Как только найдено соответствие в таблице user с положительным разрешением, команда немедленно выполняется. В противном случае MySQL продолжает поиск в следующих таблицах в указанном порядке:



db

tables_priv

columns_priv

Если таблица db содержит разрешение, дальнейшая проверка прекращается и выполняется команда. Если нет, то MySQL ищет соответствие в таблице tables_priv . Если, к примеру, это команда SELECT, объединяющая две таблицы, то пользователь должен иметь разрешения для обеих этих таблиц. Если хотя бы одна из записей отказывает в доступе или отсутствует, MySQL точно таким же способом проверяет все колонки в таблице columns_priv .

Утилита mysqlaccess

Освоение системы защиты MySQL поначалу может показаться вам затруднительным. Несколько упрощает дело имеющаяся в MySQL утилита mysqlaccess. Эта команда является сценарием на языке Perl , который, исходя из имен машины, пользователя и базы данных, точно показывает, что данный пользователь может делать и почему. Например, команда mysqlaccess nobody isp.com mydata может вывести следующее:

Access-rights

for USER 'nobody', from HOST 'isp.com', to DB 'mydata'



BEWARE: Everybody can access your DB as user 'nobody'

: from host 'isp.com' WITHOUT supplying a password. : Be very careful about it!!

The following rules are used: db : 'isp.com','mydata','nobody','Y','Y','Y','Y','N',

'N','N','N','N','N'

host : 'Not processed: host-field is not empty in db-table.'

user : '%', 'nobody', ", 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N'

(Выводится, в частности, предупреждение о том, что база доступна любому, регистрирующемуся как «nobody» с машины «isp.com» без ввода пароля, в связи с чем нужно проявлять осторожность.)

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

Изменение прав доступа

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

По каким-то причинам в некоторых дистрибутивах MySQL сценарий mysqlaccess указывает на нестандартное расположение исполняемых файлов Perl. Если при попытке выполнить mysqlaccess вы получаете сообщение «command not found», то это, скорее всего, ваш случай. Вам необходимо изменить строку 1 сценария mysqlaccess, чтобы она указывала на правильный путь к Perl, обычно /usr/local/bin/perl.




MySQL является, возможно, самым ярким


MySQL

MySQL является, возможно, самым ярким программным проектом после выхода Linux. В то время как mSQL заслуживает уважения за то, что столкнула дело управления базами данных с мертвой точки, MySQL умело воспользовалась моментом. Сейчас она не больше и не меньше, как серьезный конкурент большим СУБД в области разработки баз данных малого и среднего масштаба. В самом начале MySQL просто стала заменой устаревающему ядру mSQL версии 1. Как отмечалось в Главе 1, признаки старения mSQL проявились в виде проблем со стабильностью и неспособностью удовлетворить растущие требования, которые обрушились на нее благодаря успеху. MySQL использовала основы проекта mSQL и теперь превосходит ее по набору характеристик и одновременно по производительности.



Настройка производительности


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

MySQL имеет три потенциальных «узких места» при любом подключении. Во-первых, это сетевое соединение клиента с сервером. Во-вторых, это время решения таких задач, как, скажем, построение индексов. И наконец, проблема может быть связана с дисковым вводом/выводом. MySQL предоставляет доступ к переменным, с помощью которых ее функционирование можно настроить в соответствии со средой приложения. Все эти переменные можно установить, используя параметр -О в команде mysqld. Например, переменная back_log принимает значение 15 в результате добавления к mysqld параметра -О backjtog=15. Ниже следует список полезных переменных.

bach_log

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

key_buffer

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

max Connections

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

table_cache

Буфер, используемый для хранения данных, к которым происходит частое обращение. Если выделить под них память, то резко сокращается объем обращений к диску. Отрицательный эффект - существенное увеличение расхода памяти.


Структура хранения данных в MySQL

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

-rw-rw-- - 1 root root 1034155 Jun 3 17:08 mytable.ISD

-rw-rw---- 1 root root 50176 Jun 3 17:08 mytable.ISM

-rw-rw-- - 1 root root 9114 Jun 3 14:24 mytable.frm

В файле ISD хранятся фактические данные. В файле ISM хранятся данные о ключах и прочие внутренние данные, необходимые MySQL для быстрого поиска данных в файле ISD. Файл f rm содержит структуру самой таблицы.

Файл ISM наиболее важен для функционирования MySQL. Он настолько важен, что ему посвящена целая утилита isamchk. Запуск isamchk -d выводит сведения о таблице:

# isamchk -d mytable

ISAM file: mytable

Data records: 1973 Deleted blocks: 0

Recordlength: 343

Record format: Packed

table description:

Key Start Len Index Type

1 2 50 unique text packed stripped

Важное поле, которое нужно отметить, это «Deleted blocks» (удаленные блоки). Если его значение слишком велико, то файл понапрасну занимает много лишнего места. К счастью, это пространство можно освободить. В результате выполнения следующей команды таблица будет просмотрена и создана заново, при этом будут в большинстве своем устранены ошибки и высвобождено свободное пространство:

isamchk -r mytable

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

Восстановление поврежденных таблиц

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

isamchk mytable

При запуске isamchk во время работы сервера может потребоваться выполнить mysqladmin reload, чтобы сервер «увидел» исправленную таблицу.

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



isamchk -rq mytable

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

isamchk -e mytable

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

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

Удаление и замена ключей

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

В этих случаях оказывается полезным временное удаление ключей из таблицы и воссоздание их после завершения опасной работы. Следующая команда удаляет ключи из таблицы:

isamchk -rq -k0

Если вы готовы снова вставить ключи, это можно сделать командой:

isamchk -rq

Прежде чем ввести команду isamchk с параметром -r, завершите работу сервера, иначе таблица может оказаться повреждений.

Команда isamchk предоставляет столько возможностей, что вам, вероятно, станет сложно разобраться во всех них. Следует, однако, руководствоваться следующими соображениями:

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



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

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

Устранение неполадок

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

Изменения в таблицах доступа не действуют.

Не забывайте выполнять команду mysqladmin reload после внесения изменений в таблицы доступа.

При высокой загрузке MySQL отказывает в подключении.

Сначала уточните число соединений, допускаемых сервером. Команда mysqladmin variables покажет его значение в поле max_connec-tions. Можно увеличить это число, запустив mysqld с параметром -О max_connections=###, где ### - предел, который вы хотите установить.

Можно также проверить значение back_log , которое определяет размер очереди, создаваемой MySQL для входящих соединений, равное 5 по умолчанию. Версии MySQL до 3.22 позволяли увеличить это значение до 64, но в более поздних версиях его можно увеличить до 1024. Однако оно может быть ограничено до 64 вашей операционной системой.

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



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

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

Число потоков начинает расти, и потоки не завершаются,

В некоторых системах с установленным NFS, а также в Linux, есть проблемы с механизмом блокировки файлов. Результатом может быть замораживание потоков. Команда mysqladmin processlist поможет выявить эту проблему. Если в поле «Command» против замороженных потоков стоит «System lock», запустите mysqld с параметром --skip_ locking.


Проект


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

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

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

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

Рис. 4-1. Клиент-серверная архитектура MySQL

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


MySQL фактически расширяет ANSI SQL несколькими новыми возможностями. В их числе новые функции (ENCRYPT, WEEKDAY, IF и другие), возможность инкрементирования полей (AUTO_INCREMENT и LAST_INSERT_ID), а также возможность различать верхний и нижний регистры.

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

С 1996 года ТсХ использует MySQL в среде, где имеется более 40 баз данных, содержащих 10 000 таблиц. Из этих 10 000 более 500 таблиц имеют, в свою очередь, более 7 миллионов записей - около 100 Гбайт данных.




Установка MySQL


Прежде чем использовать MySQL, ее необходимо установить. MySQL работает почти на любой известной Unix-платформе, а также под управлением Windows 9x, Windows NT и OS/2. Для Windows 9x и Windows NT требуется приобрести лицензию. Если вы хотите лишь протестировать работу этой СУБД, имеется более старая бесплатная версия.

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

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



Утилиты MySQL


ТсХ распространяет MySQL с большим набором вспомогательных утилит, однако набор утилит, предлагаемых сторонними разработчиками, еще богаче. В этом параграфе мы постараемся дать краткий обзор этих инструментов, отложив полное описание до главы 18 «Справочник по РНР и Lite».

Утилиты командной строки (Command Line Tools)

isamchk

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

isamlog

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

mysql

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

mysqlaccess

Модифицирует таблицы прав доступа MySQL и отображает их в

удобном для чтения виде. Использование этой утилиты — хороший способ изучения структуры таблиц доступа MySQL.

mysqladmin

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

mysqlbug

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

mysqldump

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

mysqlimport

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

mysqlshow

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


Утилиты сторонних разработчиков

Ни один поставщик или разработчик не может самостоятельно предоставить все необходимые для программного продукта средства поддержки. Продукты с открытым исходным кодом, такие как Linux, имели столь потрясающий успех не только благодаря проделанной Линусом Торвальдсом работе по созданию ядра Linux, но и благодаря сотням, если не тысячам, программ для Linux сторонних разработчиков. MySQL также значительно выиграл от работы подобных добровольцев. Хотелось бы перечислить все имеющиеся программы, но этот перечень ежедневно меняется. Ниже мы попытались составить представление о том, что имеется в наличии. За самым свежим списком обратитесь на домашнюю страницу MySQL: http://www.mysql.com/Contrib.

Утилиты преобразования баз данных

access_to_mysql

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

dbf2mysql

Конвертирует файлы dBASE (DBF) в таблицы MySQL. Хотя dBASE утратил популярность, формат DBF установился как наиболее распространенный для передачи данных между различными приложениями баз данных. Все главные настольные приложения баз данных могут читать и писать DBF-файлы. Это приложение полезно для экспорта/импорта данных в коммерческие настольные базы данных.

Export sql/Importsql

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

Интерфейсы CGI

РНР

Создает HTML-страницы с использованием специальных тегов, распознаваемых анализатором РНР. РНР имеет интерфейсы к большинству основных баз данных, включая MySQL и mSQL. Мы более подробно расскажем о РНР в главе 12 «РНР и другие средства поддержки управления HTML со стороны баз данных».

Mysql-webadmin

Осуществляет веб-администрирование баз данных MySQL. Используя это средство, можно просматривать таблицы и изменять их содержимое с помощью HTML-форм.



Mysqladm

Осуществляет веб- администрирование баз данных MySQL. Эта CGI-программа позволяет просматривать таблицы через WWW, добавлять таблицы и изменять их содержимое.

www-sql

Создает HTML-страницы из таблиц баз данных MySQL. Эта программа осуществляет разбор HTML-страниц в поисках специальных тегов и использует извлеченные данные для выполнения команд SQL на сервере MySQL.

Клиентские приложения

Mysqlwinadmn

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

xmysql

Обеспечивает полный доступ к таблицам баз данных MySQL для клиента X Window System. Поддерживает групповые вставки и удаления.

xmysqladmin

Позволяет осуществлять администрирование MySQL из X Window System. Это инструмент для графического интерфейса, позволяющий создавать и удалять базы данных и управлять таблицами. С его помощью можно также проверять, запущен ли сервер, перегружать таблицы доступа и управлять потоками.

Интерфейсы программирования

MyODBC

Реализует ODBC API к MySQL в Windows.

Db.py

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

Vdb-dflts

Реализует библиотеку Vdb для MySQL. Vdb - не зависящий от типа базы данных API для С, позволяющий единому клиенту иметь доступ к различным серверам баз данных. Клиенты Vdb могут использовать этот API для досупа к базам данных MySQL.

Delphi-interface

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

dump2h

Преобразует структуры таблиц MySQL в файлы заголовков С. Эта программа принимает обычный файл, создаваемый mysqldump и генерирует заголовочный файл С, описывающий таблицу в виде структуры (st ruct) на С.

mm.mysql.jdbc



Реализует стандартный API JDBC (Java Database Connectivity -доступ к базам данных из Java). В главе 14 «Java и JDBC» подробно обсуждается программирование на Java с использованием этого API, а в главе 22 «Справочник по JDBC» представлено полное справочное руководство по JDBC 2.0.

twzJdbcForMysql

Реализация JDBC API для Java.

Mysqltcl

Реализует интерфейс Tel к MySQL.

MySQLmodule

Реализует доступ к MySQL из Python.

Mysql-c++

Объектно-ориентированная оболочка MySQL С API для доступа из приложений на C++.

MySQL++

Обеспечивает объектно-ориентированный доступ к MySQL для приложений на C++,

Pike-mysql

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

Sqlscreens

Генерирует экраны баз данных на Tcl/Tk на основе баз данных MySQL. Позволяет разработчикам строить специализированные . GUI, привязанные к таблицам MySQL.

Squile

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

Wintcl

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

Разное

Emacs-sql-mode

Адаптирует стандартный режим SQL для Emacs для поддержки особенностей синтаксиса SQL в MySQL. Вводит отступы, выделяет синтаксис и довершает команды, что облегчает работу с SQL.

findres

Отыскивает в таблицах MySQL зарезервированные слова. Эта-программа ищет в таблицах MySQL зарезервированные слова SQL, которые могут нарушить правильную работу других баз данных, поддерживающих SQL.

Hyalog

Сохраняет в таблице MySQL исходящие факсимильные сообщения. Эта программа отслеживает факсы, отправляемые программой HylaFax, и сохраняет их копии в базе данных MySQL.

mod_auth_mysql

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



mod_log_mysql

Регистрирует трафик WWW, проходящий через сервер Apache, в базе данных MySQL.

mysqlpasswd

Обеспечивает добавление, удаление и изменение записей о пользователях, хранимых в MySQL модулем mod_auth_mysql из состава Apache.

Mysql_watchdog

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

Nsapi_auth_mysql

Аутентифицирует пользователей на веб-сервере Netscape.

Pam_mysql

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

Wuftpd-mysql

Позволяет регистрировать в базе данных MySQL трафик FTP через демон WuFTP.




Запуск MySQL


Как правило, сервер баз данных работает постоянно. В конце концов, какой смысл иметь базу данных, если нельзя получить данные. ТсХ создавала MySQL, имея это в виду, поэтому MySQL работает под Unix как демон, и как служба — под Windows NT. В Windows 95 есть только грубый аналог, реализуемый помещением ярлыка исполняемого приложения в папку Автозагрузка (StartUp). Важной особенностью работы под Windows 95 является то, что при создании каждого потока происходит утечка примерно 200 байт оперативной памяти. Поэтому под Windows 95 не следует надолго оставлять MySQL работающей. К Windows 98 и Windows NT это не относится.

Запуск MySQL осуществляется с помощью сценария safe_mysqld. Под Unix этот файл устанавливается по умолчанию как /usr/local/bin/ safe_mysqld. Это сценарий для командного процессора Борна, и вы можете редактировать его, чтобы изменять принятые по умолчанию параметры. Все параметры, которые вы зададите в safe_mysqld, будут переданы непосредственно демону MySQL.

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

/usr/local/mysql/bin/safe_mysqld &

Причина, по которой вы должны запускать safe_mysqld в фоновом режиме (и по которой нужно запускать именно safe_mysqld, а не mysqld) в том, что сценарий safe_mysqld запускает mysqld, а затем непрерывно проверяет, выполняется ли mysqld. Если выполнение MySQL неожиданно прекратится, safe_mysqld ее перезапустит.

Теперь, когда вы знаете, как запускать MySQL, нужно сделать так, чтобы MySQL стартовала и заканчивала работу вместе с компьютером, на котором она выполняется. Под Windows NT, конечно, достаточно установить MySQL как службу. Под Windows 9x нужно поместить ярлык сценария запуска MySQL в папку Startup. Под Unix, как и почти всегда бывает в этом мире, заставить MySQL стартовать и завершаться вместе с системой несколько сложнее. Unix-системы обычно ищут сценарии начального запуска где-то в каталоге /etc - в /etc/rc.d или /etc/ init.d. Вы должны узнать у системного администратора или в документации, куда именно нужно помещать сценарии запуска/завершения. Дистрибутив MySQL содержит в каталоге support_j'lies файл mysql.ser-ver. Этот сценарий и будет служить сценарием запуска/завершения.



Администрирование баз данных


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

Утилита msqladmin

Утилита msqladmin является вашим главным инструментом администрирования баз данных. Она поддерживает создание, удаление, копирование, переименование и исследование ваших баз данных mSQL. Если вы вернетесь к нашему обсуждению того, что такое база данных в главе 1, то вспомните, что mSQL сама по себе - не база данных. Ваши базы данных - это группы файлов в каждом подкаталоге каталога msqldb. mSQL - система управления этими базами. Одна СУБД одновременно может обслуживать много баз данных. Утилита msqladmin позволяет администрировать базы данных для выбранного сервера.

Создание баз данных

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

msqladmin create DATABASENAME

В этой команде DATABASENAME - имя новой базы данных, которую вы хотите создать. Команда создает новую пустую базу данных с указанным вами именем. Как мы говорили раньше, база данных в mSQL — просто каталог в каталоге msqldb в том месте, куда вы установили mSQL. mSQL помещает все данные, относящиеся к вашей новой базе данных, в файлы, находящиеся в этом каталоге. Например, если вы создаете базу данных с именем «mydata», используя установку mSQL по умолчанию, будет создан каталог /usr/local/Hughes/msqldb/mydata.

Удаление базы данных

Во время разработки нового приложения баз данных вы, вероятно, захотите создать несколько баз данных для поддержки процесса разработки. Например, в процессе разработки принято иметь различные базы данных для разработки, тестирования и окончательного результата. По завершении разработки можно освободиться от баз данных для разработки и тестирования. Утилита msqladmin имеет параметр «drop», позволяющий удалить базу данных:

msqladmin drop DATABASENAME

Как и в команде msqladmin create, DATABASENAME является именем базы данных, которую вы хотите уничтожить. mSQL не позволит вам случайно удалить базу данных. После ввода этой команды она предупредит вас, что удаление базы данных потенциально очень опасно и попросит вас подтвердить свое намерение. После удаления базы данных вы можете убедиться в том, что в каталоге msqldb больше нет каталога, служившего ранее этой базой данных.


Переименование и копирование баз данных

Удобной новой возможностью, включенной в mSQL 2, является возможность переименования и копирования баз данных.

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

msqladmin move OLDNAHE NEWNAME

Например, если вы создали базу данных «midata» с ошибкой в имени и хотите исправить ее, нужно выполнить команду:

msqladmin move midata mydata

Копирование столь же просто:

msqladmin copy mydata mynewdata

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

Если вы работали с MySQL, то обратите внимание, что контроль состояния сервера - область, в которой mSQL явно не силен. Утилита msqladmin служит вам интерфейсом к контролю состояния серверов. msqladmin stats в mSQL 2 выводит на экран следующее:

Server Statistics

-------------------------

Mini SQL Version 2.0.4.1 - Forge Alpha Build #9

Copyright (c) 1993-94 David J. Hughes

Copyright (c) 1995-98 Hughes Technologies Pty Ltd. All rights reserved.

Config file : c:\usr\local\hughes\msql.conf Max connections : 61 Cur connections : 1

Running as user : UID 500

Connection table :

Sock Username Hostname Database Connect Idle Queries,



Здесь требуется некоторое пояснение:

Max connections

Максимальное количество одновременных соединений, которое может обработать сервер.

Cur connections

Число подключений к серверу в данный момент. Sock

Номер сокета Интернет, используемый mSQL для идентификации каждого соединения.

Username

Имя пользователя, подключенного к серверу.

Hostname

Имя машины, подключенной к серверу. «Unix sock» указывает на локальное подключение через сокет Unix.

Database

Имя базы данных, к которой пользователь подключен в данный момент. «No DB» означает, что клиент не выбрал базу данных.

Connect



Общее время соединения клиента с сервером в часах и минутах.

Idle

Число минут, прошедших с момента последнего запроса пользователя.

Queries

Общее количество запросов, посланных клиентом через данное соединение.

Помимо команды msqladmin stats можно получить другую, более статичную информацию с помощью команды msqladmin version. Ее выдача может выглядеть так:

Version Details :-

msqladmin version 2.0.4,1 - Forge Alpha Build #9

mSQL server version 2.0.4,1 - Forge Alpha Build #9

mSQL protocol version23

mSQL connection 127.0.0.1 via TCP/IP

Target platform CYGWIN32_NT-4.0-1586

Configuration Details :-

Default config file c:\usr\local\hughes/msql.conf

TCP socket 1114

Unix socket c:\usr\local\Hughes\msql2.sock

mSQL user msql

Admin user root

Install directory c:\usr\local\Hughes

PID file location c:\usr\local\Hughes\msql2d.pid

Memory Sync Timer 30

Hostname Lookup False

Каждое значение, выводимое командой msqladmin version, может быть установлено в конфигурационном файле mSQL 2.

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

Завершение работы сервера

Ранее в этой главе в примере сценария запуска/остановки для Unix вы видели, как завершать работу сервера mSQL. Команда такая:

msqladmin shutdown

Эта команда осуществляет корректное завершение работы сервера mSQL.

Перезагрузка при изменении параметров сервера

Если вы производите изменения в ACL mSQL, нужно дать серверу команду на перезагрузку этих изменений. Для этого вводится команда:

msqladmin reload

Мы расскажем о mSQL ACL позднее в этой главе.

Параметры командной строки msqladmin

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



msqladmin [-h host] [-f conf] [-q] COMMAND

Параметры имеют следующее значение:

-h

Имя машины, на которой работает администрируемый сервер.

-f

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

-q.

Запуск в «тихом» режиме. При этом msqladmin не просит подтверждения команд. Этот параметр полезен при запуске утилиты из сценариев.

Резервирование данных

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

При использовании mSQL есть несколько методов резервирования. Как чаще всего бывает в mSQL, они небогаты украшениями, но дело свое делают. Чаще всего для создания резервных копий баз данных mSQL используется команда msqldump. Она делает полный стандартный дамп всей базы. Для каждой базы данных в системе нужно выполнить свою команду, например:

msqldump database1 > /usr/backups/database1.sql. daily

msqldump database2 > /usr/backups/database2.sql. daily

msqldump database3 > /usr/backups/database3.sql. daily

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

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



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

Восстановление данных из резервных копий производится столь же просто, как создание копий. Дампы, создаваемые msqldump, имеют стандартную форму SQL и могут быть обработаны монитором msql. Эти дампы содержат команды для создания как таблиц, так и данных, поэтому нужно либо удалить существующие таблицы, либо удалить из дампов команды CREATE TABLE. Если вы восстанавливаете только отдельные строки данных, можно просто скопировать их из дампа и подать на вход монитора msql.

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

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



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

Система безопасности

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

mSQL управляет безопасностью с помощью файла msql.acl, который находится в каталоге установки mSQL. Расширение .acl образовано от «Access Control List» - «Список контроля доступа» - очень гибкой системы авторизации, с некоторого времени используемой в ряде операционных систем и приложений. Формат файла msql.acl следующий:

database=mydata

read=*

write=*

host=*

access=local,remote

database=mynewdata read=*

wriite=admin,root host=* access=local

Для каждой базы данных есть ряд опций. Строки read и write указывают, каким пользователям вы хотите предоставить право чтения (SELECT) базы или записи (INSERT, UPDATE, DELETE) в базу данных. Строка host показывает, какие машины могут иметь удаленный доступ к базе. Если строка access содержит «local», значит, разрешены локальные подключения через сокеты Unix, а если содержит «remote», то разрешены удаленные подключения по TCP.

В файле ACL допустим символ-маска «*» в полях read, write и host. Поэтому можно иметь такой ACL:

database=mynewdata

read=*

write=msql*

host=*. client.com,"isp.com

access=local, remote

Этот ACL означает, что любой пользователь любой машины в client.com, а также любой пользователь любой машины в любом домене, оканчивающемся на isp.com - например, wisp.com или lisp.com, - может иметь подключение к базе данных. Эти пользователи могут осуществлять чтение данных, но только пользователи, чьи имена начинаются с «msql», могут вносить в нее изменения.



По умолчанию все права отсутствуют, поэтому если вы пропустите строку write, никто не сможет модифицировать базу данных. Отдельные пользователи и машины могут исключаться с помощью префикса «-» перед их именем. Рассмотрим пример:

dataoase=moredata

read=-bob,*

write=jane

host=-junk. isp.com,*, isp.com

access=local,remote

Этот ACL разрешает подключение всем хостам домена isp.com, за исключением junk.isp.com. Кроме того, чтение разрешено всем пользователям, кроме пользователя «bob». Только «jane» имеет право записи в базе данных. Поскольку по умолчанию установлен отказ в доступе, конкретно указывать, кому отказано в доступе, как «bob'y»» бессмысленно, если строка не содержит также символа «*».

mSQL действует согласно первому обнаруженному соответствию. Например, строка read=*,-bob дает пользователю «bob» право чтения.

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




Архитектура


Дэвид Хьюз преследовал три цели, создавая mSQL:

mSQL должна быть быстрой.

mSQL должна быть компактной.

mSQL должна обеспечивать множественность одновременных подключений.

Высокая скорость была главной целью mSQL. Поскольку в большинстве коммерческих SQL-серверов разработчики стараются реализовать полную спецификацию SQL2, а кроме того, и собственные расширения языка, им приходится расплачиваться производительностью и размерами. MSQL, напротив, жертвует некоторыми наиболее изощренными возможностями коммерческих серверов в пользу скорости. Для проекта Minerva требовалась возможность быстрого выполнения большого числа простых SQL-запросов. Именно это позволяет делать mSQL.

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

Скорости и размера, достигнутых в mSQL, было бы достаточно для того, чтобы успешно заменить Postgres в проекте Minerva. Хьюз, однако, хотел изменить и ту модель поведения, которая, собственно, заставила его искать альтернативу. Хьюз спроектировал mSQL так, чтобы та могла обрабатывать множественные одновременные подключения в рамках одного процесса. В результате получается маленький, быстрый, эффективный SQL-сервер, способный одновременно обрабатывать несколько запросов - локально или по сети.

Для реализации своих проектных целей Хьюзу пришлось ограничить функциональность сервера. Диалект SQL, поддерживаемый mSQL, является подмножеством стандарта ANSI SQL2, содержащим наиболее употребительные команды, такие как CREATE, INSERT, SELECT, UPDATE и DELETE. Хьюз отказался от ресурсоемких операций, вроде поддержки транзакций. В том типе приложений, которые используют mSQL, функциональность, опущенная Хьюзом, обычно не требуется.


mSQL является однопоточным сервером с очередью. Одновременно к серверу может подключиться любое число клиентов - до определенного предела. При отправке клиентом запроса к серверу mSQL ставит запрос в синхронную очередь и обрабатывает все запросы последовательно по одному. Эффективность такого решения зависит, таким образом, от способности сервера быстро обработать каждый запрос. Если запросы вовремя не обрабатывать, очередь будет расти, что в итоге приведет к краху сервера из-за превышения системных ограничений. Поэтому скорость является решающим фактором для успешной работы mSQL. На рис. 5-1 показана работа очереди mSQL и однопоточная работа.

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

mSQL поддерживает два типа соединений со стороны клиента. Удаленные клиенты подключаются к серверу через известный порт TCP/IP. Используя TCP/IP, база данных mSQL может предоставлять доступ любому компьютеру в мире через Интернет. Локальные соединения тоже могут производиться через TCP/IP, но лучшей производительности можно добиться, используя стандартный сокет Unix, что эффективнее примерно на 20%.



Рис. 5-1. Архитектура клиент,/сервер в mSQL

С mSQL связан набор программ, позволяющих осуществлять полный доступ к базе данных. Монитор msql позволяет пользователю непосредственно направлять запросы серверу. Хотя во время разработки этот инструмент полезен, большинству пользователей необходим какой-либо интерфейс для доступа к базе данных посредством какого-либо приложения. Для поддержки разработки приложений mSQL имеет встроенный API на языке С, позволяющий любой С-программе соединяться с сервером mSQL через TCP/IP или сокет Unix.

mSQL поддерживает также сетевой протокол, позволяющий подключаться к серверу по сети, используя другие языки, без С API. С помощью этих двух интерфейсов разработчики, использующие множество языков, разработали библиотеки для подключения к mSQL почти из любого известного языка. В данной книге рассказывается об использовании API для С, Perl, Java и Python.




mSQL


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

mSQL является реляционной системой управления базами данных (РСУБД), открывшей эру дешевых баз данных малого и среднего масштаба с поддержкой SQL. Малые размеры, впечатляющая производительность и простота изучения сделали ее предпочтительным выбором растущего числа разработчиков программ для Интернет, которым не достает времени, чтобы стать экспертами в области программирования баз данных. Автор mSQL намеренно стремился к достижению этих целей, приступая к созданию программного продукта, способного заполнить зияющий пробел в ряду РСУБД.



Установка mSQL


Первым шагом при работе с mSQL является, естественно, загрузка и установка. Как вы это сделаете, зависит от типа предполагаемой платформы. mSQL появилась как приложение для Linux, и это та платформа, которую поддерживает Хьюз. Если у вас работает какая-то разновидность Unix, mSQL, скорее всего, сможет на ней работать. Даже если нет, mSQL поставляется с исходным текстом, и опытный С-программист исправит места, создающие несовместимость. Дистрибутив для Unix находится по адресу http://www.hughes.com.au.

Если вы работаете под Windows или OS/2, для вас тоже не все потеряно: переложения для Win32 и OS/2 также активно поддерживаются. Последние версии mSQL для PC находятся по адресу http://blnet.com/ msqlpc/. Хотя эти приложения относительно новые, они всегда немного отстают от самых свежих версий, предоставляемых Хьюзом. В момент написания книги номер текущей версии для Unix был 2.0.7, текущей версии для Win32 - 2.0.4.1, и текущей версии для OS/2 - 2.06. Меньше повезло пользователям Мае. На Макинтош перенесены только клиентские средства для mSQL.

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



Утилиты mSQL


Об одной из поставляемых с mSQL утилит, msqladmin, мы уже рассказали. mSQL содержит семь основных утилит, составляющих основу взаимодействия с ней. В дополнение к этим основным утилитам mSQL

поддерживает облегченную утилиту обработки сценариев Lite и интерфейс к WWW под названием W3-mSQL. Помимо того, существуют многочисленные средства сторонних разработчиков. Сейчас мы подробно остановимся на базовых утилитах, поставляемых с mSQL, и пробежим по списку утилит «со стороны». К Lite и W3-mSQL мы обратимся позднее.

Утилиты командной строки

Каждая утилита командной строки имеет подробную подсказку, разъясняющую ее синтаксис. В основном этот синтаксис является копией команды msqladmln. Именно, параметр -h позволяет указать машину, а параметр -/ позволяет задать имя конкретного файла конфигурации.

msql

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

msqldump

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

msqlimport

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

relshow

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

msqlexport

Эта утилита выводит содержимое таблицы на стандартное устройство вывода в виде текстового файла с разделителями. Многие другие СУБД и приложения, такие как Microsoft Excel, могут читать этот файл и импортировать из него данные.

Поддержка сторонними разработчиками


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

сторонних разработчиков можно получить с веб-серверов Hughes и mSQL PC, о которых шла речь ранее в этой главе.

Утилиты преобразования баз данных

dbf2msql

Преобразует файлы DBF в таблицы mSQL. DBF - это формат файлов базы данных dBASE, бывшей когда-то ведущей настольной базой данных. Хотя dBASE утратил популярность, формат DBF установился как наиболее распространенный для передачи данных между различными приложениями баз данных. Все главные настольные приложения баз данных могут читать и писать DBF-файлы. Это приложение полезно для экспорта/импорта данных в коммерческие настольные базы данных.

mSQLpp

Конвертирует ESQL (Ingres Embedded SQL - встроенный SQL для Ingres) в SQL, доступный для mSQL. ESQL встраивается прямо в исходный код программ на С, чтобы облегчить доступ к базам данных из С. Эта программа конвертирует файл исходного кода С с ESQL в файл исходного кода С, использующий стандартный API mSQL.v Она предназначена для работы в качестве препроцессора и обычно позволяет с помощью фильтрации использовать ESQL-файлы с mSQL без всякой модификации.

Интерфейсы CGI

РНР

Создает HTML-страницы со специальными тегами, распознаваемыми анализатором РНР. РНР содержит интерфейсы к большинству основных баз данных, включая MySQL и mSQL. PHP более подробно освещается в главе 12 «РНР и другие средства поддержки HTML, управляемого базами данных».

dbadmln

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



Jate

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

mSQLCGI

Еще один CGI-интерфейс к таблицам mSQL. Эта программа позволяет просматривать и модифицировать таблицы mSQL через WWW с использованием форм HTML. Особенностью этого интерфейса является необходимость обработки каждой таблицы, которую вы хотите использовать, специальной прилагаемой программой, прежде чем к ней можно будет получить доступ через Web.

Клиентские приложения

dbview

Показывает структуру базы данных mSQL. Эта утилита сходна с relshow, но имеет некоторые дополнительные возможности. Например, dbview показывает количество записей в каждой таблице.

XfSQL

Обеспечивает полный доступ к данным таблиц mSQL в качестве клиента Xforms для X Window System. С помощью этого инструмента можно добавлять, удалять и просматривать данные таблиц в X Window System.

XmSQL

Обеспечивает полный доступ к данным таблиц mSQL как независимый от библиотеки клиент X Window System. Благодаря этому она будет компилироваться на любой системе X Window.

mSQLsql

Отображает форматированные таблицы. Используя эту утилиту, можно просматривать таблицу mSQL в различных видах, включая настраиваемые рамки и разделители для форматированных ASCII-таблиц. Можно также генерировать HTML-таблицы, используя заданные пользователем параметры.

mSQLwin-relshow

Аналог утилиты relshow для графического интерфейса Windows.

Интерфейсы программирования

ConNExS

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



mSQLBase

Предоставляет API SQLBase как С-оболочку для программ, работающих с mSQL. SQLBase API - это API доступа к базам данных независимого разработчика, поддерживающий несколько основных серверов SQL. Эта программа транслирует mSQL API в SQLBase API, в результате чего клиенты SQLBase могут работать с mSQL.

mSQLCLI

Инкапсулирует С API для mSQL таким образом, что клиенты ODBC под OS/2 могут работать с mSQL. ODBC - распространенный независимый от баз данных API, поддерживаемый большинством баз данных под OS/2 и Windows. Эта оболочка реализует стандартные средства ODBC, поддерживаемые mSQL, но только для операционной системы OS/2. Она содержит минимальный уровень функциональности ODBC.

msqldll

Упаковывает С API для mSQL в виде DLL для Windows. С помощью этой DLL можно создавать приложения для Windows, используя Visual Basic или другой инструмент для программирования в Windows, работающий с DLL.

MsqlJava

Создает оболочку сетевого протокола TCP/IP mSQL для Java API, напоминающую mSQL С API. Помогает быстро начать создавать приложения Java разработчикам, которые уже знают mSQL С API, но не знакомы со стандартом JDBC API. MsqlJava работает только с JDK 1.0.

mSQL-JDBC

Реализует стандарт Java Database Connectivity (JDBC) API поверх сетевого протокола TCP/IP mSQL. Этот пакет поддерживает максимальный уровень функциональности JDBC, возможный для mSQL в среде JDK 1.1 и JDK 1.2 (Java 2), включая стандарт JDBC 2.O. В главе 14 «Java и JDBC» подробно обсуждается программирование на Java с использованием этого API, а в главе 22 «Справочник по JDBC» представлено полное справочное руководство по JDBC 2.0.

MsqlODBC

Реализует ODBC API для mSQL 1 в Windows. Дэвид Хьюз в настоящее время работает над реализацией для mSQL 2.

mSQLPerl

Обеспечивает сценариям Perl доступ к базам данных mSQL. В главе 10 «Perl», подробно обсуждается программирование на Perl для MySQL и mSQL, а в главе 21 «Справочник по Perl», представлено полное справочное руководство по mSQLPerl.



mSQLPython

Обеспечивает сценариям Python доступ к базам данных mSQL. В главе 11 «Python», подробно обсуждается программирование на Python для MySQL и mSQL, а в главе 20 «Справочник по Python», представлено полное справочное руководство по mSQLPython.

mSQLRexx

Поддерживает доступ к mSQL из REXX, языка сценариев, наиболее часто используемого в OS/2.

mSQLTCL

Позволяет программам на Tel иметь доступ к базам данных mSQL. Поддержка включает многие расширения Tcl, в том числе Tcl/Tk и Expect.

mSQLVdb

Обеспечивает доступ к базам данных mSQL через библиотеку базы данных Vdb. Vdb - не зависящий от типа базы данных API для С, позволяющий единому клиенту иметь доступ к различным серверам баз данных. Клиенты Vdb могут использовать этот API для доступа к базам данных mSQL.

zmsql

Обеспечивает объектно-ориентированный доступ к базам данных mSQL для программ на C++.

Разное

mod_auth_msql

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

mSQLEmacs

Расширяет базовую поддержку режима SQL в Emacs, обеспечивая отступы и выделение цветом для mSQL-диалекта SQL.

msqlexpire

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

mSQLSSL

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

Sqs

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


Версии mSQL


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

Однако в наше время вычислительная среда долго не стоит на месте. С возникновением широкомасштабного сотрудничества через Интернет не стало проектов, недоступных для преданных им групп программистов. К 1996 году стали появляться другие недорогие реализации SQL, MySQL в их числе, и mSQL перестала существовать в одиночестве.

В продолжение 1990-х Хьюз разрабатывал и совершенствовал mSQL. Однако ядро базы данных в итоге достигло той точки, где дальнейшая разработка требовала глубокого пересмотра всего проекта. Такая большая работа потребовала бы много времени, поскольку новый проект влечет новые ошибки и промахи. Одновременно необходимо осуществлять и поддержку существующего продукта. Таким образом, mSQL 2 появилась как переработка ядра базы данных при продолжении одновременной поддержки существующего продукта - mSQL 1.

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

Основные изменения, произведенные в mSQL 2 в сравнении с mSQL 1, следующие:

Возросшие устойчивость и производительность


В первом выпуске mSQL 2 были решены все известные проблемы со стабильностью в mSQL 1. Были устранены утечки памяти, а код тщательно протестирован для выявления ошибок. Общая производительность выросла, несмотря на добавление новых характеристик.

Улучшенная поддержка индексов

В первой версии mSQL использовалась очень слабая схема индексирования. В каждой таблице можно было иметь только один индекс, состоящий только из одной колонки, - первичный ключ. В mSQL 2 индексирование полностью переработано с целью поддержки более сложных и часто встречающихся задач. Теперь можно иметь несколько индексов для каждой таблицы и составлять их более чем из одной колонки. Индексирование теперь поддерживает индексные файлы как в виде В-дерева, так и в стиле AVL.

Дополнительные типы данных

В mSQL 2 добавились многие типы данных, что приближает его к полной реализации спецификации ANSI SQL2. Наряду с MONEY, DATE и TIME mSQL 2 поддерживает теперь и тип TEXT. В первоначальной версии mSQL все поля были фиксированной длины, и поэтому текстовые поля типа CHAR имели предустановленный размер. Часто для поддержки таких атрибутов, как адреса электронной почты или названия книг, приходилось определять большое поле типа CHAR, что приводило к неоправданному расходу памяти. Например, для поля адреса электронной почты вы определили бы поле CHAR(35). Даже если адрес оказывался «xxx@imaginary.com», mSQL использовал все 35 символов поля. Еще хуже то, что если адрес оказывался длиннее 35 символов, вам сильно не повезло. Новый тип данных TEXT решает обе проблемы, позволяя вам задать среднюю длину поля. Все, превышающее этот размер, будет храниться в буфере переполнения. При меньшем размере лишние символы не будут записываться. К сожалению, поля типа TEXT имеют недостатки, не позволяющие использовать их в качестве индексов и употреблять в предложениях типа LIKE.

Улучшенный сервис и поддержка API

Стандартный инструментарий, поставляемый с mSQL, улучшен с целью поддержки всех новых характеристик. Хьюз добавил новые функции, такие как, например, копирование и переименование таблиц в msqladmin. Приложение W3-msql для взаимодействия с WWW существенно переделано и дополнено. Язык сценариев переработан в Lite - язык с прямой поддержкой взаимодействия WWW и баз данных.

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




Запуск mSQL


mSQL - это действительно единственное ядро базы данных типа «завел и поехал». Иными словами, можно установить mSQL, запустить сервер и сразу заняться делом. Серверный процесс mSQL называется msql2d (для серверов mSQL 1 он называется msqld). Этот исполняемый файл и все утилиты, поступающие с дистрибутивом mSQL, находятся в каталоге bin. Запустить экземпляр mSQL можно, просто введя msql2d без всяких параметров командной строки.

Такая реализация по умолчанию не всегда вас удовлетворит. В большинстве случаев потребуется отредактировать файл msql.conf в каталоге дистрибутива mSQL. Этот файл конфигурации mSQL 2 (в mSQL 1 он отсутствует) позволяет определить несколько часто используемых параметров. Его изменение обычно необходимо тогда, когда вы используете какой-нибудь прекомпилированный дистрибутив.

Демон mSQL - не ветвящийся процесс. Это означает, что запуск его из командной строки оставит процесс работать на терминале, пока вы явно не нажмете CTRL-C, чтобы прекратить его, или не переведете процесс в фоновый режим. Под Unix можно запустить сервер mSQL из командной строки в фоновом режиме, введя команду:

msqld2 &

Следующий сценарий запускает процесс сервера mSQL при запуске системы и корректно завершает его при остановке системы:

#!/bin/sh

if [ $1 - "start" ]; then

if [ -x /usr/local/Hughes/bin/msql2d ]; then

su msql -c '/usr/local/Hughes/bin/nisql2d &'

fi

else

if [ $1 = "stop" ]; then

if [ -x /usr/local/Hughes/bin/msqladmin ]; then

su msql -c '/usr/local/Hughes/bin/msqladmin shutdown'

fi

fi

fi

В этом сценарии предполагается, что вы запускаете mSQL в Unix с идентификатором пользователя msql. Разумеется, его нужно заменить конкретным ID пользователя, а также заменить /usr/'local/Hughes именем каталога, в который вы установили mSQL.

Поскольку версия для Win32 не работает пока как служба NT, можно запускать mSQL из папки Автозагрузка (StartUp), просто поместив ярлык для файла msql2d.exe в папку Автозагрузка (использование команды msqladmin мы опишем ниже в данной главе).


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

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

#!/bin/sh

# Извлечь ID процесса демона базы данных

# Это годится для mSQL 2; для mSQL 1

# Строка должна быть другой:

# PID='cat /usr/local/Minerva/msqld.pid' PID='cat /usr/local/Hughes/msq!2d.pid'

# Далее проверяется активность процесса сервера.

# Эта строка пригодна для систем BSD (Linux)

ALIVE='ps aux grep $PID | grep -v grep | awk '{print $2}"

# Для систем SysV (Solaris) раскомментируйте следующую строку

#ALIVE='ps -et grep $PID | grep -v grep | awk '{print $2}"

if [ $ALIVE ]

then

REALLY_ALIVE='msqladmin version' DATE='date'

#Если 'ERROR', или если

# выдачи вообще не было, msqladmin

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

if ! echo $REALLY_ALIVE | grep "^ERROR"

then

exit

fi

if [ ! $REALLY_ALIVE ]

then exit;

fi

else

# Для mSQL 1 должно быть /usr/local/Minerva/hin/msqld &

# for mSQL installations /usr/local/Hughes/bin/msql2d &

mail -s "mSQL daemon restarted" root@yourmachine.com <<EOM

The mSQL daemon died unexpectedly and was restarted on $DATE.

Sincerely,

The mSQL Watchdog

EOM

fi

После запуска mSQL может обмениваться данными с окружающим миром двумя способами. Связь с Интернетом происходит через порт TCP/IP. По умолчанию mSQL слушает порт 1112. mSQL2 слушает порт 1114. Вы можете при желании изменить номер порта либо во время компиляции (mSQL 1), либо через файл конфигурации (mSQL 2).

Локальная связь происходит через сокеты Unix. Сокеты Unix выглядят обычными файлами файловой системы Unix. От обычных файлов их можно отличить по символу, следующему за именем при использовании флага `F` в команде Is. mSQL использует файл /deu/msql, в то время как mSQL 2 использует файл /usr/local/Hughes/msql2.sock.



Запуск нескольких демонов

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

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

Чтобы установить для mSQL 2 второй каталог, используйте следующие команды:

mkdir -p /usr/local/second_database/msqldb/. tmp

ср /usr/local/Hughes/msql.conf /usr/local/Hughes/msql.acl\

/usr/local/second_database

chown -R msql /usr/local/second_database

Некоторые Unix-системы используют mkdirs вместо mkdir -p, в других же такая возможность может вообще отсутствовать, и тогда каждый каталог придется создавать отдельно. Вам придется также заменить идентификатор пользователя, под именем которого вы запускаете msql2d, если он отличен от «msql». В Windows и OS/2 процедура та же, за исключением названий команд и символа-разделителя пути.

Когда каталоги созданы и файлы скопированы, нужно отредактировать файл msql.conf из нового каталога, чтобы переменная Inst_Dir указывала на /usr/local/'second_database, а значение TCP_Port не конфликтовало с другими TCP-службами сервера. Значение Unix_Port можно не изменять, поскольку новый сокет будет образован в новом каталоге.



Для запуска нового демона введите ту же команду msql2d со следующими параметрами:

msql2d -f /usr/local/second_database/msql. conf

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

Файл конфигурации mSQL

Мы уже сталкивались с файлом конфигурации mSQL, но еще не вникали в мелкие подробности. В mSQL 1 все, кроме безопасности, определялось во время компиляции. В mSQL 2 есть файл конфигурации, позволяющий управлять поведением сервера mSQL во время работы. Ниже дан пример файла конфигурации.

[general]

Inst_Dir = c:\usr\local\Hughes

mSQL_User = msql

Admin_User = root

Pid_File = %I\msql2d.pid

TCP_Port = 1114

Unix_Port = %I\msql2.sock

[system]

Msync_Timer = 30

Host_Lookup = True

Read_0nly = False

Remote_Access = True

Local_Access = True

[w3-msql]

Auth_Host = NULL

Footer = True

Force_Private = False

Сценарий конфигурации разделен на секции, как ini-файл в Windows, состоящие из пар ключ-значение. Сейчас для нас представляет интерес только секция general.

Inst_Dir

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

mSQL_User

ID пользователя, от имени которого запускается процесс mSQL.

Admin_User

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

TCP_Port

Порт TCP/IP, который будет слушать сервер. В Unix номер порта, меньший 1024, можно выбрать, только если сервер mSQL запущен суперпользователем.

Unix_Port

Имя файла сокета Unix. В этом файле мы использовали переменную % 1% вместо Inst_Dir.




и mSQL используется структурированный язык


Диалект SQL, используемый в MySQL и mSQL

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

SQL является разновидностью «естественного языка». Иными словами, команда SQL должна читаться, по крайней мере на первый взгляд, как. предложение английского языка. У такого подхода есть как преимущества, так и недостатки, но факт заключается в том, что этот язык очень непохож на традиционные языки программирования, такие как С, Java или Perl.

В этой главе мы рассмотрим язык SQL, как он реализован в MySQL и mSQL. По большей части, диалект MySQL является надмножеством диалекта mSQL. Мы старательно отметим те случаи, где два диалекта расходятся. Однако в основном эта глава относится и к одной, и к другой СУБД.



Индексы


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

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

CREATE INDEX index_name ON tablename (column1,

column2,

columnN)

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

CREATE TABLE materials (id INT NOT NULL,

name CHAR(50) NOT NULL,

resistance INT,

melting_pt REAL,

INDEX indexl (id, name),

UNIQUE INDEX index2 (name))

В этом примере для таблицы создается два индекса. Первый индекс indexl состоит из полей id и name. Второй индекс включает в себя только поле name и указывает, что значения поля name должны быть уникальными. Если вы попытаетесь вставить в поле name значение, которое уже есть в этом поле в какой-либо строке, операция не будет осуществлена. Все поля, указанные в уникальном индексе, должны быть объявлены как NOT NULL .

Хотя мы создали отдельный индекс для поля name, отдельно для поля id мы не создавали индекса. Если такой индекс нам понадобится, создавать его не нужно - он уже есть. Когда индекс содержит более одной колонки (например, name, rank, nserial_number), MySQL читает колонки в порядке слева направо. Благодаря используемой MySQL структуре индекса всякое подмножество колонок с левого края автоматически становится индексом внутри «главного» индекса. Например, когда вы создаете индекс name, rank, serial_number, создаются также «свободные» индексы name и name вместе с rank. Однако индексы rank или name и seri-al_number не создаются, если не потребовать этого явно.


MySQL поддерживает также семантику ANSI SQL для особого индекса, называемого первичным ключом. В MySQL первичный ключ - это уникальный индекс с именем PRIMARY. Назначив при создании таблицы колонку первичным ключом, вы делаете ее уникальным индексом, который будет поддерживать объединения таблиц. В следующем примере создается таблица cities с первичным ключом id.

CREATE TABLE cities (id INT NOT NULL PRIMARY KEY,

name VARCHAR(100),

pop MEDIUMINT,

founded DATE)

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




Основы SQL


SQL «структурирован» в том отношении, что он следует определенному набору правил. Компьютерной программе легко разобрать на части сформулированный запрос SQL. Действительно, в книге издательства O'Reilly «lex & у асе», написанной Джоном Ливайном, Тони Мэйсоном и Дугом Брауном (John Levine, Tony Mason, Doug Brown), реализована грамматика SQL для демонстрации процесса создания программы, интерпретирующей язык! Запрос (query) - это полностью заданная команда, посылаемая серверу баз данных, который выполняет запрошенное действие. Ниже приведен пример SQL-запроса:

SELECT name FROM people WHERE name LIKE 'Stac%'

Как можно видеть, это предложение выглядит почти как фраза на ломаном английском языке: «Выбрать имена из список люди, где имена похожи на Stac». SQL в очень незначительной мере использует форматирование и специальные символы, обычно ассоциируемые с компьютерными языками. Сравните, к примеру, «$++;($*++/$|);$&$л„;$!» в Perl и «SELECT value FROM table» в SQL.

История SQL

В IBM изобрели SQL в начале 1970-х, вскоре после введения д-ром Е. Ф. Коддом (Е. F. Codd) понятия реляционной базы данных. С самого начала SQL был легким в изучении, но мощным языком. Он напоминает естественный язык, такой как английский, и поэтому не утомляет тех, кто не является техническим специалистом. В 1970-х это достоинство было еще более важным, чем сегодня.

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

SQL действительно был настолько популярен среди пользователей, для которых предназначался, что в 1980-х компания Oracle выпустила первую в мире общедоступную коммерческую SQL-систему. Oracle SQL был хитом сезона и породил вокруг SQL целую индустрию. Sybase, Informix, Microsoft и ряд других компаний вышли на рынок с собственными разработками реляционных систем управления базами данных (РСУБД), основанных на SQL.


В то время когда Oracle и ее конкуренты вышли на сцену, SQL был новинкой, и для него не существовало стандартов. Лишь в 1989 году комиссия по стандартам ANSI выпустила первый общедоступный стандарт SQL. Сегодня его называют SQL89. К несчастью, этот новый стандарт не слишком углублялся в определение технической структуры языка. Поэтому, хотя различные коммерческие реализации языка SQL сближались, различия в синтаксисе делали задачу перехода с одной реализации языка на другую нетривиальной. Только в 1992 году стандарт ANSI SQL вступил в свои права.

Произносится как «сиквел» или «эс-кю-эль». Некоторые люди относятся с благоговением к произношению SQL. He обращайте на них внимания. Однако нужно заметить, что в MySQL и mSQL правильное произношение -«эс-кю-эль».

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

SQL2 - не последнее слово в стандартах SQL. В связи с ростом популярности объектно-ориентированных СУБД (ООСУБД) и объектно-реляционных СУБД (ОРСУБД) возрастает давление с целью принятия объектно-ориентированного доступа к базам данных в качестве стандарта SQL. Ответом на эту проблему должен послужить SQL3. Он не является пока официальным стандартом, но в настоящее время вполне определился и может стать официальным стандартом где-то в 1999 году.



С появлением MySQL и mSQL проявился новый подход к разработке серверов баз данных. Вместо создания очередной гигантской РСУБД с риском не предложить ничего нового в сравнении с «большими парнями», были предложены небольшие и быстрые реализации наиболее часто используемых функций SQL.



Архитектура SQL

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

CREATE TABLE people (name CHAR(10))

глагол дополнение расширенное определение

INSERT INTO people VALUES('me')

глагол косвенное прямое

дополнение дополнение

SELECT name FROM people WHERE name LIKE '%e'

глагол прямое косвенное придаточное дополнение дополнение предложение

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

cREatE ТАblЕ people (name cHaR(10))

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

Первый элемент SQL-запроса - всегда глагол. Глагол выражает действие, которое должно выполнить ядро базы данных. Хотя остальная часть команды зависит от глагола, она всегда следует общему формату: указывается имя объекта, над которым осуществляется действие, а затем описываются используемые при действии данные. Например, в запросе CREATE TABLE people (char(10)) используется глагол CREATE, за которым следует дополнение (объект) TABLE .Оставшаяся часть запроса описывает таблицу, которую нужно создать.

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

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




Последовательности и автоинкрементирование


Лучше всего, когда первичный ключ не имеет в таблице никакого иного значения, кроме значения первичного ключа. Для достижения этого лучшим способом является создание числового первичного ключа, значение которого увеличивается при добавлении в таблицу новой строки. Если вернуться к примеру с таблицей cities, то первый введенный вами город должен иметь id, равный 1, второй - 2, третий - 3, и т. д. Чтобы успешно управлять такой последовательностью первичных ключей, нужно иметь какое-то средство, гарантирующее, что в данный конкретный момент только один клиент может прочесть число и увеличить его на единицу. В базе данных с транзакциями можно создать таблицу, скажем, с именем sequence , содержащую число, представляющее очередной id. Когда необходимо добавить новую строку в таблицу, вы читаете число из этой таблицы и вставляете число на единицу большее. Чтобы эта схема работала, нужно быть уверенным, что никто другой не сможет произвести чтение из таблицы, пока вы не ввели новое число. В противном случае два клиента могут прочесть одно и то же значение и попытаться использовать его в качестве значения первичного ключа в одной и той же таблице.

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

Последовательности в MySQL

При создании таблицы в MySQL можно одну из колонок специфицировать как AUTO_INCREMENT . В этом случае, при добавлении новой строки, имеющей значение NULL или 0 в данной колонке, автоматически будет происходить замена на значение на единицу больше, чем наибольшее текущее значение в колонке. Колонка с модификатором AUTO_INCREMENT должна быть индексирована. Ниже приведен пример использования поля типа AUTOJNCREMENT :

CREATE TABLE cities (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,


name VARCHAR(100),

pop MEDIUMINT,

founded DATE)

Когда вы первый раз добавляете строку, поле id получает значение 1, если в команде INSERT для него используется значение NULL или 0. Например, следующая команда использует возможность AUTO_INCREMENT:

INSERT INTO cities (id, name, pop)

VALUES (NULL, 'Houston', 3000000)

Если вы выполните эту команду, когда в таблице нет строк, поле id получит значение 1, а не NULL. В случае, когда в таблице уже есть строки, полю будет присвоено значение на 1 большее, чем наибольшее значение id в данный момент.

Другим способом реализации последовательностей является использование значения, возвращаемого функцией LAST_INSERT_ID :

UPDATE table SET id=LAST_INSERT_ID (id+1);

Последовательности в mSQL

Каждая таблица в mSQL может иметь одну связанную с ней последовательность. Синтаксис создания последовательности следующий:

CREATE SEQUENCE ON table_name [VALUE start STEP incr]

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

CREATE SEQUENCE ON mytable VALUE 100 STEP 5

Создается последовательность в таблице mytable, начальным значением которой будет 100, а при каждом обращении оно будет увеличиваться на 5. Вторым значением, следовательно, будет 105.

Для доступа к последовательности нужно выбрать из таблицы специальную колонку с именем _seq:

SELECT _seq FROM table_name

В результате вы получите очередное значение последовательности и инкрементируете его.




Расширения языка


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

Возможности MySQL

MySQL превосходит mSQL в поддержке SQL, предоставляя возможность работы с функциями и в некоторой мере — с внешними объединениями. Функции в SQL аналогичны функциям в других языках программирования, таких как С и Perl. Функция может принимать аргументы и возвращает некоторое значение. Например, функция SQRT(16) возвращает 4. В MySQL в команде SELECT функции могут использоваться в двух местах:

Как извлекаемая величина

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

# Выбрать название каждого события (event), а также его дату

# в удобном для чтения формате из всех событий, более свежих,

# чем указанная дата. Функция FROM_UnixTIME()

# преобразует стандартное значение времени Unix

# в читаемый вид.

SELECT name, FROM_UnixTIME(date)

FROM events

WHERE time > 90534323

# Выбрать заглавие статьи, полный текст ее,

# и длину (в байтах) полного текста для всех

# статей, автор которых Stacie Sheldon.

# Функция LENGTHO возвращает длину заданной

# строки в символах.

SELECT title, text, LENGTH(text)

FROM papers

WHERE author = 'Stacie Sheldon'

Как часть предложения WHERE

В этом виде функция заменяет место константы при вычислении в предложении WHERE. Значение функции используется при сравнении в каждой строке таблицы. Приведем пример.

# Случайным образом выбрать название объекта из общего числа 35.

# Функция RAND() генерирует случайное число

# между 0 и 1 (умножается на 34, чтобы сделать его между 0

# и 34, и увеличивается на 1 , чтобы сделать его между 1 и


# 35). Функция ROUND() возвращает данное число округленным

# до ближайшего целого, что приводит к целому числу

# между 1 и 35, которое должно соответствовать одному

# из чисел ID в таблице.

SELECT name

FROM entries

WHERE id = ROUND( (RAND()*34) + 1 )

# Можно использовать функции одновременно в списке значений

# и предложении WHERE. В этом примере выбираются имя и дата

# всех событий, происшедших более суток назад. Функция UNIX_TIMESTAMP()

# без аргументов возвращает текущее время

# в формате Unix.

SELECT name, FROM_UnixTIME(date)

FROM events

WHERE time > (Unix_TIMESTAMP() - (60 * 60 * 24) )

# Функция может использовать значение поля таблицы.

# В этом примере возвращаются имена всех,

# кто использовал свое имя в качестве пароля. Функция ENCRYPTO

# возвращает зашифрованную в стиле пароля Unix

# заданную строку, используя 2-символьный ключ.

# Функция LEFT() возвращает п самых левых символов

# переданной строки.

SELECT name

FROM people

WHERE password = ENCRYPT(name, LEFT(name, 2))

Наконец, MySQL поддерживает более сильный тип объединения, чем простое внутреннее объединение, которое мы до сих пор использовали. Именно, MySQL поддерживает так называемое левое внешнее объединение (известное также просто как внешнее объединение). Объединение этого типа похоже на внутреннее объединение, за исключением того, что в него включаются данные из левой колонки, которым нет соответствия в правой колонке. Если вы обратитесь к нашим таблицам с авторами и книгами, то вспомните, что в наше объединение не вошли авторы, у которых в базе данных не было книг. Часто вы можете пожелать вывести записи из одной таблицы, для которых нет соответствия в другой таблице, с которой производится объединение. Это можно сделать с помощью внешнего объединения:

SELECT book.title, author.name

FROM author

LEFT JOIN book ON book.author = author.id

Обратите внимание, что во внешнем объединении вместо WHERE используется ключевое слово ON. Результат нашего запроса будет выглядеть так:





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

SELECT my_prod.name

FROM my_prod

NATURAL LEFT JOIN their_prod

Особенности mSQL

В mSQL есть пять «системных переменных», которые можно включить в любой запрос. Об одной из этих переменных, _seq, мы уже говорили. Остальные переменные следующие:

_rowid

Уникальный идентификатор возвращенной строки данных. Для повышения производительности можно использовать эту переменную в командах UPDATE или DELETE. Однако такой подход нельзя рекомендовать определенно, поскольку разные клиенты могут помешать друг другу. Например, два клиента могут выбрать одну и ту же строку. Первый клиент удаляет ее, а затем третий клиент добавляет новую строку. Новая строка может получить то же значение _rowid, что и удаленная строка. Если теперь второй клиент попытается отредактировать или удалить строку, используя данное значение _rowid, то результат будет совсем не тот, на который он рассчитывал.

_timestamp

Время последней модификации строки. В текущей версии mSQL имеет стандартный формат времени Unix. В будущих версиях формат может измениться, поэтому использовать эту переменную следует только для сравнения временных меток разных строк.

_sysdate

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

_user

Содержит имя клиента текущего соединения. Как и _-sysdate, не зависит от таблицы, из которой выбирается.


Создание и удаление таблиц


Успешно установив MySQL или mSQL, вы можете приступить к созданию своей первой таблицы. Таблица, структурированное вместилище данных, является основным понятием реляционных баз. Прежде чем начать вводить данные в таблицу, вы должны определить ее структуру. Рассмотрим следующую раскладку:


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

Общий синтаксис для создания таблиц следующий:

CREATE TABLE table_name (colutnn_namel type [modifiers] [, column_name2 type [modifiers]] )

Какие идентификаторы - имена таблиц и колонок - являются допустимыми, зависит от конкретной СУБД. mSQL обеспечивает поддержку имен в объеме, близком к минимальному. В качестве идентификатора он допускает любую последовательность букв набора ISO 8859-1 (Latin 1), цифр и знака «-», длиной до 20 символов. Идентификатор должен начинаться с буквы. Проблемы вызывает ограничение на использование только ISO 8859-1. Для хорошей переносимости SQL нужно избегать имен, начинающихся не с допустимой буквы. MySQL предоставляет больше возможностей. Длина идентификатора может быть до 64 символов, допустим символ «$», и первым символом может быть цифра. Более важно, однако, что MySQL допускает использование любых символов из установленного в системе локального набора.

Колонка - это отдельная единица данных в таблице. В таблице может содержаться произвольное число колонок, но использование больших таблиц бывает неэффективным. Вот здесь правильное проектирование базы данных, обсуждавшееся в главе 2, начинает играть важную роль. Создав правильно нормализованные таблицы, можно объединять их («join») для осуществления поиска в данных, размещенных в нескольких таблицах. Механику объединения таблиц мы обсудим позднее в данной главе.


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

DROP TABLE Lable_name

Эта команда не оставит и следа от таблицы в базе данных. MySQL уничтожит все данные удаленной таблицы. Если у вас не осталось резервной копии, нет абсолютно никакого способа отменить действие данной операции. Мораль этой истории: всегда храните резервные копии и будьте очень внимательны при удалении таблиц. В один «прекрасный» день это вам пригодится.

В MySQL можно одной командой удалить несколько таблиц, разделяя их имена запятыми. Например, DROP TABLE people, animals, plants удалит эти три таблицы. Можно также использовать модификатор IF EXISTS для подавления ошибки в случае отсутствия удаляемой таблицы. Этот модификатор полезен в больших сценариях, предназначенных для создания базы данных и всех ее таблиц. Прежде чем создавать таблицу, выполните команду DROP TABLE table_name IF EXISTS.




Типы данных в SQL


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

В главе 15 «Справочник по SQL» дается полное справочное руководство по типам SQL, поддерживаемым MySQL и mSQL. В таблице 6-1 дан сокращенный список, состоящий из наиболее употребительных типов, поддерживаемых в обоих языках.

Таблица 6-1. Наиболее употребительные типы, данных, поддерживаемые как MySQL, так и mSQL

Тип данных

Описание

INT Целое число. В MySQL INT может быть со знаком или без знака, в то время как mSQL имеет отдельный тип UINT для беззнаковых целых.
REAL Число с плавающей запятой. Этот тип допускает больший диапазон значений, чем INT, но не обладает его точностью.
TEXT(length) Символьная величина переменной длины. В mSQL значение length используется как предположение о том, какой длины будут хранимые строки. Можно сохранять и строки большей длины, но ценой потери производительности. В MySQL TEXT - лишь один из нескольких типов данных переменного размера.
DATE Стандартное значение даты. Хотя формат хранения даты различен в MySQL и mSQL, оба ядра могут использовать тип DATE для хранения произвольных дат, относящихся к прошлому, настоящему и будущему. Оба ядра правильно решают «проблему 2000».
TIME

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

CHAR(length)

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

<


« MySQL поддерживает атрибут UNSIGNED для всех числовых типов. Этот модификатор позволяет вводить в колонку только положительные (беззнаковые) числа. Беззнаковые поля имеют верхний предел значений вдвое больший, чем у соответствующих знаковых типов. Беззнаковый TINYINT - однобайтовый числовой тип MySQL - имеет диапазон от 0 до 255, а не от -127 до 127, как у своего знакового аналога.

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

Числовые типы данных

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

Символьные типы

С символьными типами работать немного труднее. Вы должны подумать не только о максимальной и минимальной длине строки, но также о среднем размере, частоте отклонения от него и необходимости в индексировании. В данном контексте мы называем индексом поле или группу полей, в которых вы собираетесь осуществлять поиск — в основном, в предложении WHERE. Индексирование, однако, значительно сложнее, чем такое упрощенное определение, и мы займемся им далее в этой главе. Здесь важно лишь отметить, что индексирование по символьным полям происходит значительно быстрее, если они имеют фиксированную длину. В действительности, mSQL даже не позволяет индексировать поля переменной длины. Если длина строк не слишком колеблется или, что еще лучше, постоянна, то, вероятно, лучше выбрать для поля тип CHAR. Пример хорошего кандидата на тип CHAR — код страны. Стандартом ISO определены двухсимвольные коды для всех стран (US для США, FR для Франции и т. д.). Поскольку эти коды состоят ровно из двух символов, CHAR(2) будет правильным выбором для данного поля.



Чтобы подходить для типа CHAR, поле необязательно должно быть фиксированной длины, но длина не должна сильно колебаться. Телефонные номера, к примеру, можно смело хранить в поле CHAR(13), хотя длина номеров различна в разных странах. Просто различие не столь велико, поэтому нет смысла делать поле для номера телефона переменным по длине. В отношении поля типа CHAR важно помнить, что, вне зависимости от реальной длины хранимой строки, в поле будет ровно столько символов, сколько указано в его размере — не больше и не меньше. Разность в длине между размером сохраняемого текста и размером поля заполняется пробелами. Не стоит беспокоиться по поводу нескольких лишних символов при хранении телефонных номеров, но не хотелось бы тратить много места в некоторых других случаях. Для этого существуют текстовые поля переменной длины.

Хороший пример поля, для которого требуется тип данных с переменной длиной, дает URL Интернет. По большей части адреса Web занимают сравнительно немного места - http://www.ora.com, http:// www.hughes.com.au, http://www.mysql.com - и не представляют проблемы. Иногда, однако, можно наткнуться на адреса подобного вида: http://www.winespectator.com/Wine/Spectator/ _notes\5527293926834323221480431354? Xvl I =&Xr5=&Xvl =& type-region-search- code=&Xal 4=flora+springs&Xv4=.

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

Поля переменной длины в MySQL

Если вы используете только mSQL, этот раздел можно пропустить. Преимуществом текстовых полей переменной длины в MySQL является то, что они используют ровно столько места, сколько необходимо для хранения отдельной величины. Например, поле типа VARCHAR(255) , в котором хранится строка «hello, world», занимает только двенадцать байтов (по одному байту на каждый символ плюс еще один байт для хранения длины).



В отличие от стандарта ANSI, в MySQL поля типа VARCHAR не дополняются пробелами. Перед записью из строки удаляются лишние пробелы.



Сохранить строки, длина которых больше, чем заданный размер поля, нельзя. В поле VARCHAR(4) можно сохранить строку не длиннее 4 символов. Если вы попытаетесь сохранить строку «happy birthday», MySQL сократит ее до «happ». Недостатком подхода MySQL к хранению полей переменной длины, в сравнении с mSQL, является то, что не существует способа сохранить необычную строку, длина которой превосходит заданное вами значение. В таблице 6-2 показан размер пространства, необходимого для хранения 144-символьного URL, продемонстрированного выше, и обычного, 30-символьного URL,

Таблица 6-2. Пространство памяти, необходимое для различных символьных типов MySQL

Тип данных

Пространство для хранения строки из 144 символов

Пространство для хранения строки из 30 символов

Максимальная длина строки

СНАR(150)

150

150

255

VARCHAR(ISO)

145

31

255

TINYTEXT(ISO)

145

31

255

ТЕХТ(150)

146

32

65535

MEDIUM-ТЕХТ(150)

147

33

16777215

LONGTEXT(150)

148

34

4294967295

Если через годы работы со своей базой данных вы обнаружите, что мир изменился, и поле, уютно чувствовавшее себя в типе VARCHAR(25) , должно теперь вмещать строки длиной 30 символов, не все потеряно. В MySQL есть команда ALTER TABLE , позволяющая переопределить размер поля без потери данных.

ALTER TABLE mytable MODIFY tnycolumn LONGTEXT

Поля переменной длины в mSQL

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



Остановимся немного на последствиях различий в подходе. Чтобы сохранить все вышеперечисленные URL в поле типа CHAR, потребуется колонка типа CHAR(144). При таком развитии событий четыре упомянутые URL займут 576 байт (144 х 4), хотя фактически хранится только 216 байт данных. Остальные 360 байт- просто потерянное пространство. Если помножить эту цифру на тысячи и миллионы строк, то можно понять, что это представляет собой серьезную проблему. Если же использовать поле переменной длины типа ТЕХТ(30), то для хранения 216 байт данных требуется только 234 байта (30 X 3 + 144). Всего лишь 18 байт потеряно. Экономия составила 41%!

Двоичные типы данных

В mSQL нет поддержки двоичных данных. В MySQL, напротив, есть целый ряд двоичных типов данных, соответствующих своим символьным аналогам. Двоичными типами, поддерживаемыми MySQL, являются CHAR BINARY , VARCHAR BINARY , TINYBLOB, BLOB, MEDIUMBLOB и LONGBLOB. Практическое отличие между символьными типами и их двоичными аналогами основано на принципе кодировки. Двоичные данные просто являются куском данных, которые MySQL не пытается интерпретировать. Напротив, символьные данные предполагаются представляющими текстовые данные из используемых человеком алфавитов. Поэтому они кодируются и сортируются, основываясь на правилах, соответствующих рассматриваемому набору символов. Двоичные же данные MySQL сортирует в порядке ASCII без учета регистра.

Перечисления и множества

MySQL предоставляет еще два особых типа данных, не имеющих аналога в mSQL. Тип ENUM позволяет при создании таблицы указать список возможных значений некоторого поля. Например, если бы у вас была колонка с именем «фрукт», в которую вы разрешили бы помещать только значения «яблоко», «апельсин», «киви» и «банан», ей следовало бы присвоить тип ENUM:

CREATE TABLE meal(meal_id INT NOT NULL PRIMARY KEY,

фрукт ENUM('яблоко', 'апельсин', 'киви', 'банан'))

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



Тип MySQL SET работает аналогично, но позволяет одновременно хранить в поле несколько значений.

Другие типы данных

Любые мыслимые данные можно хранить с помощью числовых или символьных типов. В принципе, даже числа можно хранить в символьном виде. Однако то, что это можно сделать, не означает, что это нужно делать. Рассмотрим, к примеру, как хранить в базе данных денежные суммы. Можно делать это, используя INT или REAL. Хотя интуитивно REAL может показаться более подходящим - в конце концов, в денежных суммах нужны десятичные знаки, - на самом деле более правильно использовать INT. В полях, содержащих значения с плавающей запятой, таких как REAL, часто невозможно найти число с точным десятичным значением. Например, если вы вводите число 0.43, которое должно представлять сумму $0.43, MySQL и mSQL могут записать его как 0.42999998. Это небольшое отличие может вызвать проблемы при совершении большого числа математических операций. Сохраняя число как INT и устанавливая десятичную точку в нужное место, можно быть уверенным, что его значение представляет именно то, что вам требуется.

К чему такие хлопоты? Не лучше ли было бы, если бы MySQL и mSQL обеспечивали некий тип данных, специально предназначенный для денежных сумм? MySQL и в меньшей степени mSQL предоставляют специальные типы данных для таких случаев. Одним из них является тип MONEY, другим- DATE. Полное описание всех типов данных можно найти в главе 17 «Программы и утилиты для MySQL и mSQL».




Управление данными


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

Добавление данных

Добавление данных в таблицу является одной из наиболее простых операций SQL. Несколько примеров этого вы уже видели. Как MySQL, так и mSQL поддерживают стандартный синтаксис INSERT:

INSERT INTO table_name (columnl, column2, ..., columnN)

VALUES (value!, value2, .... valueN)

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

INSERT INTO addresses (name, address, city, state, phone, age)

VALUES( 'Irving Forbush', ' 123 Mockingbird Lane', 'Corbin', 'KY', '(800) 555-1234', 26)

Кроме того, управляющий символ - по умолчанию '\' — позволяет вводить в литералы одиночные кавычки и сам символ '\':

# Ввести данные в каталог Stacie's Directory, который находится

# в c:\Personal\Stacie

INSERT INTO files (description, location)

VALUES ('Stacie\'s Directory', 'C: \\Personal\\Stacie')

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

Более новые версии MySQL поддерживают нестандартный вызов INSERT для одновременной вставки сразу нескольких строк:

INSERT INTO foods VALUES (NULL, 'Oranges', 133, 0, 2, 39),

(HULL, 'Bananas', 122, 0, 4, 29), (NULL, 'Liver', 232, 3, 15, 10)

Хотя поддерживаемый MySQL нестандартный синтаксис удобно использовать для быстрого выполнения задач администрирования, не следует без крайней нужды пользоваться им при написании приложений. Как правило, следует придерживаться стандарта ANSI SQL2 настолько близко, насколько MySQL и mSQL это позволяют. Благодаря этому вы получаете возможность перейти в будущем на какую-нибудь другую базу данных. Переносимость особенно важна для тех, у кого потребности среднего масштаба, поскольку такие пользователи обычно предполагают когда-нибудь перейти на полномасштабную базу данных.


MySQL поддерживает синтаксис SQL2, позволяющий вводить в таблицу результаты запроса SELECT:

INSERT INTO foods (name, fat)

SELECT food_name, fat_grams FROM recipes

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

Изменение данных

Добавление новых строк в базу данных - лишь начало ее использования. Если ваша база не является базой данных «только для чтения», вам, вероятно, понадобится периодически изменять данные. Стандартная команда SQL для изменения данных выглядит так:

UPDATE table_name

SET column1=value1, column2=value2, ..., columnN=valueN

[WHERE clause]

В mSQL значение, присваиваемое колонке, должно быть литералом и иметь тот же тип, что и колонка. MySQL, напротив, позволяет вычислять присваиваемое значение. Можно даже вычислять значение, используя значение другой колонки:

UPDATE years

SET end_year - begin_year+5

В этой команде значение колонки end_year устанавливается равным значению колонки begin_year плюс 5 для каждой строки таблицы.

Предложение WHERE

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

UPDATE bands

SET lead_singer = 'Ian Anderson'

WHERE band_name = 'Jethro Tull'

Эта команда — UPDATE - указывает, что нужно изменить значение в колонке lead_singer для тех строк, в которых band_name совпадает с «Jethro Tull.» Если рассматриваемая колонка не является уникальным индексом, предложение WHERE может соответствовать нескольким строкам. Многие команды SQL используют предложение WHERE, чтобы отобрать строки, над которыми нужно совершить операции. Поскольку по колонкам, участвующим в предложении WHERE, осуществляется поиск, следует иметь индексы по тем их комбинациям, которые обычно используются.



Удаление

Удаление данных - очень простая операция. Вы просто указываете таблицу, из которой нужно удалить строки, и в предложении WHERE задаете строки, которые хотите удалить:

DELETE FROM table_name [WHERE clause]

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

Запросы

Самая часто используемая команда SQL - та, которая позволяет просматривать данные в базе: SELECT. Ввод и изменение данных производятся лишь от случая к случаю, и большинство баз данных в основном занято тем, что предоставляет данные для чтения. Общий вид команды SELECT следующий:

SELECT column1, column2, ..., columnN

FROM table1, table2, .... tableN

[WHERE clause]

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

В первой части команды SELECT перечисляются колонки, которые вы хотите извлечь. Можно задать «*», чтобы указать, что вы хотите извлечь все колонки. В предложении FROM указываются таблицы, в которых находятся эти колонки. Предложение WHERE указывает, какие именно строки должны использоваться, и позволяет определить, каким образом должны объединяться две таблицы.

Объединения

Объединения вносят «реляционность» в реляционные базы данных. Именно объединение позволяет сопоставить строке одной таблицы строку другой. Основным видом объединения является то, что иногда называют внутренним объединением. Объединение таблиц заключается в приравнивании колонок двух таблиц:

SELECT book, title, author, name

FROM author, book

WHERE book, author = author, id

Рассмотрим базу данных, в которой таблица book имеет вид, как в таблице 6-3.

Таблица 6-3. Таблица книг





ID



Title



Author



Pages



1



The Green Mile



4



894



2



Guards, Guards!



2



302



ID



Title



Author



Pages



3



Imzadi



3



354



4



Gold



1



405



5



Howling Mad



3



294

А таблица авторов author имеет вид таблицы 6-4.

Таблица 6-4. Таблица авторов



ID



Name



Citizen



1



Isaac Asimov



US



2



Terry Pratchet



UK



3



Peter David



us



4



Stephen King



us



5



Neil Gaiman



UK

В результате внутреннего объединения создается таблица, в которой объединяются поля обеих таблиц для строк, удовлетворяющих запросу в обеих таблицах. В нашем примере запрос указывает, что поле author в таблице book должно совпадать с полем id таблицы author. Результат выполнения этого запроса представлен в таблице 6-5.

Таблица 6-5. Результаты запроса с внутренним объединением



Book Title



Author Name



The Green Mile



Stephen King



Guards, Guards!



Terry Pratchet



Imzadi



Peter David



Gold



Isaac Asimov



Howling Mad



Peter David

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

Псевдонимы

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

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

# Псевдоним колонки

SELECT long_field_names_are_annoying AS myfield

FROM table_name



WHERE myfield = 'Joe'

# Псевдоним таблицы в MySQL

SELECT people.names, tests.score

FROM tests, really_long_people_table_name AS people

# Псевдоним таблицы в mSQL

SELECT people.names, tests.score

FROM tests, really_long_people_table_name=people

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

Группировка и упорядочение

По умолчанию порядок, в котором появляются результаты выборки, не определен. К счастью, SQL предоставляет некоторые средства наведения порядка в этой случайной последовательности. Первое средство -упорядочение - есть и в MySQL, и в mSQL. Вы можете потребовать от базы данных, чтобы выводимые результаты были упорядочены по некоторой колонке. Например, если вы укажете, что запрос должен упорядочить результаты по полю last_name , то результаты будут выведены в алфавитном порядке по значению поля last_name . Упорядочение осуществляется с помощью предложения ORDER BY:

SELECT last_name, first_name, age

FROM people

ORDER BY last_name, first_name

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

Группировка — это средство ANSI SQL, реализованное в MySQL, но не в mSQL. Поскольку в mSQL нет агрегатных функций, то группировка просто не имеет смысла. Как и предполагает название, группировка позволяет объединять в одну строки с аналогичными значениями с целью их совместной обработки. Обычно это делается для применения к результатам агрегатных функций. О функциях мы поговорим несколько позднее.

Рассмотрим пример:

mysql> SELECT name, rank, salary FROM people\g



5 rows in set (0.01 sec)

После группировки по званию (rank) выдача изменяется:

mysql> SELECT rank FROM people GROUP BY rank\g



3 rows in set (0.01 sec)

После применения группировки можно, наконец, найти среднюю зарплату (salary) для каждого звания. О функциях, используемых в этом примере, мы поговорим позднее.



mysql> SELECT rank, AVG(salary) FROM people GROUP BY rank\g



3 rows in set (0.04 sec)

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

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




Beagle


Beagle является бесплатным ядром баз данных SQL, разработанным и реализованным Робертом Клейном (Robert Klein). Как и GNU SQL, Beagle задуман как полностью SQL-совместимый сервер со всеми необходимыми функциями, включая объектно-реляционные расширения, впервые появившиеся в PostgreSQL. Как и GNU SQL, Beagle во многом не завершен. Ко времени печати этой книги он достиг того уровня развития, когда он надежен и может использоваться для тестирования и разработки. Для промышленного пользования этот продукт еще не готов.

Одной из наиболее интересных особенностей Beagle является то, что автор с самого начала проекта вел журнал разработки. Изучая этот журнал, вы можете проследить развитие SQL-сервера от простого тестового приложения, использующего TCP и архитектуру клиент/сервер, до почти полностью функционального SQL-сервера, каким он является сегодня. Домашняя страница Beagle расположена на http:// www.beaglesql.org.



Чего недостает MySQL и mSQL


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

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

Транзакции

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

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

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


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

# Снять $100 из $110 на сберегательном счете

UPDATE account

SET balance = 10.00

WHERE id = 1234

# Добавить $100 к $55 на чековом счете

UPDATE account

SET balance = 155.00

WHERE id = 5678

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

Объединяя эти две команды в транзакцию, вы говорите, что либо обе должны быть успешно выполнены, либо ни одна из них. Если первая команда пройдет, а вторая не сможет выполниться, то можно дать команду, называемую «откат»(«rollback»), которая вернет базу данных в состояние, предшествовавшее началу транзакции. Точно так же никому не разрешается трогать файлы, которые вы модифицируете, пока работа не будет завершена. MySQL частично позволяет эмулировать транзакции, используя команду LOCK TABLES. Блокировки помогают избежать нарушения целостности данных, но не дают возможности осуществления операции отката. В mSQL поддержка транзакций отсутствует.

Триггеры

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

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



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

В простейшем случае хранимые процедуры - это одна или несколько команд SQL, хранимых в базе данных под каким-либо простым именем и в совокупности выполняющих некую функцию. В примере с переводом денежных средств можно было бы просто сохранить эти две команды в одной хранимой процедуре с именем «transfer» (перевод). Ваше приложение передает хранимой процедуре два номера счета и сумму, и она выполняет две команды SQL в одной транзакции.

На более высоком уровне сложности хранимые процедуры могут расширять базовый синтаксис SQL, так что он становится похожим на традиционные языки программирования. Двумя примерами таких расширений являются Oracle PL/SQL и Sybase/ Microsoft Tran-sactSQL. Часто можно слышать, что использование хранимых процедур «помещает бизнес-логику в базу данных».

Вложенные запросы

Обычная команда SQL SELECT осуществляет полный доступ ко всем данным, хранимым в таблице, - если вы знаете, что ищете. Когда вы не стремитесь извлечь содержимое таблицы целиком, SELECT в своем основном виде требует ввести хотя бы часть данных, которые вы хотите извлечь. Например, SELECT name FROM friends WHERE name LIKE 'B%' требует знания хотя бы одной буквы имени, которое вы ищете. Что делать в случае, если вы хотите узнать, чей заработок был выше среднего? Запрос должен выглядеть примерно так:

SELECT name FROM people WHERE salary > ???

Больше чего? Вы понятия не имеете, каков средний заработок, пока не сделаете выборку по заработкам! Необходимо взять значение SELECT AVG(salary) FROM people и вставить его в предыдущий запрос. Вложенный запрос позволяет это сделать:

SELECT name

FROM people

WHERE salary > (SELECT AVG(salary) FROM people)

Объекты

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

В РСУБД все данные хранятся в виде таблиц, представляющих собой просто списки записей, в свою очередь, являющихся собранием битов, представляющих текст, числа и другие типы данных. В объектно-ориентированной системе управления базами данных (ООСУБД) базовой единицей хранения данных является объект. Объект может содержать не только данные тех же типов, что встречаются в реляционных базах данных, но также и другие объекты или многомерные данные, скажем, массивы, или даже выполняемые функции, в мире объектно-ориентированного программирования обычно называемые методами.




Что значит «бесплатный»?


Иногда можно слышать, как MySQL и mSQL называют «бесплатными» (free) продуктами. Когда сравнивают MySQL и mSQL, иногда даже говорят, что MySQL «более бесплатна», чем mSQL. Здравый смысл противится выражению «более бесплатный». Однако в мире программного обеспечения действительно изобретены «степени бесплатности».

До сих пор мы сознательно избегали обсуждения «бесплатности» MySQL и mSQL, поскольку термин «бесплатный» неоднозначен в мире программного обеспечения. На самом деле, лицензия как на один, так и на другой продукт может оказаться для вас не бесплатной, в зависимости от того, кем вы являетесь. По правилам, действовавшим в момент написания книги, университет не был обязан платить за лицензию ни на тот, ни на другой продукт. А коммерческий пользователь mSQL- обязан. Когда говорят, что MySQL «более бесплатна», чем mSQL, имеют в виду, что MySQL бесплатна для большего числа пользователей, чем mSQL.

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

В мире программирования возник новый термин, предназначенный для избавления от неоднозначности понятия «бесплатный». Он называется Open Source- Открытый код. Фактически, термин «Open Source» стал торговой маркой, обозначающей программный продукт, исходный код которого открыт вне зависимости от взимаемой за его использование платы. Linux, Netscape, FreeBSD, Perl, Apache, все продукты GNU и многие продукты, упоминаемые в этой книге, такие как MySQL, mSQL, mm.mysql.jdbc и mSQL-JDBC (мы перечислили лишь немногие), - все они являются Open Source-продуктами.

Другие базы данных, о которых мы говорим в этой главе, также относятся к Open Source. Open source имеет очень большое значение в мире пользователей среднего класса, поскольку «большие парни» склонны рассматривать этот рынок как не заслуживающий их внимания из-за ограниченности, а разработчики малого класса считают эти продукты слишком сложными для себя.



Другие СУБД среднего масштаба


Когда mSQL впервые вышла на сцену, это была единственная СУБД среднего масштаба с поддержкой SQL. Но она недолго оставалась в одиночестве. Конечно, вы уже знаете о другой такой базе данных: MySQL. За годы, прошедшие после появления mSQL, появилось и несколько СУБД среднего класса. Мы сосредоточились в этой книге на MySQL и mSQL из-за их очень большого сходства и громадной популярности. Было бы, однако, несправедливо не упомянуть о других базах данных.

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



MySQL & mSQL


Проект GNU для многих программистов является символом свободы. Официальная лицензия на продукты GNU гарантирует свободный доступ и полную свободу модификации исходного кода. Почти для всякой утилиты среды Unix можно найти версию GNU - включая редактор (Emacs), командный процессор (bash) и ядро операционной системы (Hurd). До недавнего времени зияющим пробелом было отсутствие СУБД.

Институт системного программирования Российской Академии наук работает над тем, чтобы изменить это положение. Пару лет назад он выпустил первую открытую бета-версию GNU SQL - полностью функциональную РСУБД с поддержкой SQL и лицензией GNU Public License (GPL). Ко времени печати этой книги текущая версия GNU SQL имела номер 0.7beta.

Когда задумывалась GNU SQL, спецификация SQL 2 была еще не окончательной, поэтому первые версии GNU SQL обеспечивали поддержку только функций SQL89, а возможности SQL2 добавлялись постепенно.

В настоящее время GNU SQL поддерживает многие развитые возможности - транзакции, вложенные запросы и курсоры. Поскольку это бета-версия, мы не рекомендовали бы ее для промышленного использования. По мере своего становления она, конечно, будет достойна внимания. Подробнее узнать о GNU SQL можно на http://www.ispras.ru/-kml/gss/index.html



PostgreSQL


Существующая в настоящее время реализация объектно-реляционной СУБД Postgres известна как PostgreSQL (или Postgres 6). Хотя Post-gres поддерживает SQL в течение всего трех лет, самой системе уже более десяти лет. В начале 1980-х д-р Майкл Стоунбрейкер (Michael Sto-nebreaker) из Калифорнийского Университета в Беркли разработал систему баз данных, которая предвосхитила многие концепции, реализованные в современных системах управления базами данных. Эта СУБД получила название Ingres (позднее University Ingres). Ingres была некоммерческим проектом, финансируемым университетом; проектом, быстро обретшим последователей среди специалистов по компьютерам во всем мире.

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

Через некоторое время д-р Стоунбреикер пошел в своих исследованиях дальше того, что предполагалось в начальных целях проекта Ingres. Он решил, что настало время разработать совершенно новую систему баз данных, развивавшую идеи, заложенные в Ingres, и отправился осваивать новую территорию. Эта система баз данных стала известна как Postgres, то есть после-Ingres.

Postgres, как и Ingres, была открытым для общественности проектом, который финансировался университетом. И так же, как в случае Ingres, коммерческий сектор обратил внимание и на Postgres, в результате чего появился коммерческий проект Illustra*. Бесплатная Postgres продолжила свое существование и сейчас соперничает в популярности с MySQL и mSQL среди серверов баз данных среднего масштаба.

В 1995 г. произошли два события, повлиявшие на судьбу Postgres. Во-первых, два студента д-ра Стоунбрейкера - Эндрю Ю (Andrew Yu) и Джолли Чен (Jolly Chen) - разработали SQL-интерфейс для Postgres.

Таким образом, через несколько лет после того, как Дэвид Хьюз впервые разработал MiniSQL для использования SQL в работе с Postgres, у последней появился настоящий SQL-интерфейс. Поддержка SQL вызвала рост популярности. Как и в случае с mSQL и MySQL, рост популярности привел к росту потребности в новых функциях. В результате появилась объектно-ориентированная СУБД среднего масштаба с поддержкой транзакций, триггеров и вложенных запросов. Подробнее узнать о PostgreSQL можно на http://www.postgresql.org.



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


Как и многие приложения, MySQL обладает набором тестов для проверки того, что заново откомпилированная система действительно поддерживает все возможности, которыми предположительно должна обладать. Для MySQL этот набор называется «crash-me», поскольку одной из его задач является попытка «завалить» сервер баз данных.

В какой-то момент обратили внимание на то, что «crash-me» является переносимой программой. Она может работать не только в различных операционных системах, но и использоваться для тестирования разных СУБД. С тех пор «crash-me» превратилась из простого набора тестов в программу, позволяющую производить сравнение характеристик. Тесты включают в себя стандартный SQL, а также расширения, предлагаемые многими серверами. Кроме того, программа проверяет надежность сервера при интенсивной нагрузке. Полный прогон тестов дает исчерпывающую характеристику возможностей сервера баз данных.

Можно использовать «crash-me» для сравнения двух или более серверов баз данных в активном режиме. Домашняя страница «crash-me» находится на http://www.mysql.com/crash-me-choose.htmy.



Архитектура клиент/сервер


В упрощенном виде архитектура клиент/сервер предполагает разделение происходящей в приложении обработки на две или более логически различные части. До сих пор в этой книге мы обсуждали базы данных так, будто они существуют в некоем безвоздушном пространстве. Однако они выполняют свое предназначение только тогда, когда используются какими-либо приложениями. Упрощая, можно сказать, Что база данных составляет одну часть архитектуры клиент/сервер. База данных является «сервером», а всякое использующее ее приложение является «клиентом». Часто клиент и сервер расположены на разных машинах; в большинстве случаев приложение клиента является дружественным интерфейсом к базе данных. На рис. 8-1 графически представлена простая система клиент/сервер.

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

Рис. 8-1. Архитектура клиент/сервер

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

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



Часть II.


Программирование баз данных

Мощь базы данных реализуется через инструменты, предназначенные для работы с ней. В этой части мы поговорим о том, как создавать такие инструменты, используя некоторые популярные сегодня языки программирования. На примере создания веб-приложений для бизнеса мы обсудим API и инструменты, необходимые для максимального использования потенциала MySQL и mSQL. Эта часть начинается с нескольких обзорных глав по архитектуре приложений для работы с базами данных и СGI-программированию. Однако основное содержание этой части посвящено программированию на различных языках для MySQL и mSQL.



в деталях разработки приложений для


Архитектуры приложений для работы с базами данных

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



Объектное/реляционное моделирование


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

Объекты не хранят только простые данные в своих атрибутах. Там могут храниться также коллекции и связи с другими объектами.

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

Практические правила для объектно-реляционного моделирования

У каждого сохраняемого класса в базе данных есть своя таблица.

Поля объектов с простыми типами данных (целые, символы, строки и т. д.) сопоставлены колонкам в соответствующей таблице базы данных.

Каждая строка таблицы базы данных cоответствует экземпляру соответствующего хранимого класса.

Каждая связь между объектами типа «многие-ко-многим» требует таблицы-связки, так же как это требуется для объектов базы данных типа «многие-ко-многим».

Наследование моделируется с помощью отношения «один-к-одному» между таблицами, соответствующими классу и подклассу.

Вспомните адресную книгу, о которой мы говорили ранее. Допустим, она имеет таблицы address и person, как на рис. 8-2.

Рис. 8-2. Модель данных простого приложения адресной книги

Есть весьма неочевидная проблема, с которой сталкиваются программисты. Основная задача объектно-ориентированного подхода к реляционным данным - это, получив эти данные, немедленно создать экземпляр объекта. Приложение должно работать с данными только через объекты. Большинство традиционных методов программирования, включая разработку на С, PowerBuilder и VisualBasic, требует, чтобы разработчик извлек из базы данные, а затем их обработал. Главное отличие состоит в том, что в объектно-ориентированном программировании баз данных вы имеете дело с объектами, а не данными.

Рис. 8-3 показывает объектную модель, соответствующую модели данных на рис. 8-2. Каждая строка базы данных преобразуется в программный объект. Таким образом, ваше приложение принимает результирующий набор и для каждой возвращаемой строки создает новый экземпляр Address или Person. Труднее всего справиться с проблемой, о которой уже говорилось: как в приложении установить связь между человеком и его адресом? Объект Person, конечно, имеет ссылку на объект Address, относящийся к этому человеку, но сохранить объект Address внутри таблицы person реляционной базы нельзя. Модель данных предполагает хранение связей между объектами с помощью внешних ключей, для чего в таблицу person заносится address_id.

Рис. 8-3. Объектная модель, поддерживающая простое приложение адресной книги

Самое незначительное усложнение объектной модели может вызвать бездну проблем при установлении соответствия наших объектов и модели данных. Допустим, что Person является потомком Entity и класс Company тоже является потомком Entity. Как отделить Entity от Person или Company? Приведенное выше правило фактически является скорее рекомендацией. В некоторых случаях базовый класс является чисто абстрактным и, следовательно, не имеет в базе связанных с ним данных. В таком случае для этого класса в базе данных не будет объекта.



Обработка данных


В части I «Введение в MySQL и mSQL» мы дали понятия управления транзакциями и результирующего набора. Приложение для работы с базой данных — всего лишь инструмент для управления транзакциями и обработки результирующих наборов. Например, если ваше приложение является адресной книгой, то обработка результирующих наборов заключается в том, чтобы извлечь из таблицы все строки и показать их пользователю. Управление транзакциями просто сводится к тому, чтобы изменения в таблицах address и person производились как единое целое.

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

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

«Уборка за собой» включает в себя правильную обработку ошибок. Хорошие языки программирования затрудняют пропуск обработчиков исключительных ситуаций (отказ сети, повторяющиеся ключи при добавлении, ошибки синтаксиса SQL и т. д.). Но независимо от того, какой язык вы избрали, вы обязаны знать, какие исключительные ситуации могут возникать при данном вызове API, и в каждой исключительной ситуации действовать надлежащим образом. С-библиотеки для MySQL и mSQL основываются на представлении базы данных в виде наборов строк. Мы хотим этим сказать, что библиотеки С позволяют непосредственно обращаться с данными в том виде, в каком они в принципе существуют в базе данных. Глава 13 «С и C++», раскрывает практические детали программирования в этой модели с использованием С API для MySQL и mSQL.

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