Оглавление

Число страниц (страница равна 2000 символов) | Краткое описание главы
5 | Введение. Основные термины и соглашения, использованные в книге. Также обсуждает хронологию.
7 | Глава 1 Описание стандартов, принятых в MySQL.
35 | Глава 2 дает краткое введение в MySQL.
8 | Глава 3 имеет дело со структурой языка.
30 | Глава 4 рассматривает введение в администрирование.
25 | Глава 5 подробно рассматривает типы столбцов.
34 | Глава 6 рассматривает функции для использования в самых главных операторах языка: SELECT и WHERE
18 | Глава 7 описывает определение данных: вызовы CREATE, DROP и ALTER.
25 | Глава 8 объясняет манипуляции с данными: команды SELECT, INSERT, UPDATE и DELETE.
11 | Глава 9 охватывает обзор прочих инструментов языка MySQL.
33 | Глава 10 обсуждает общие проблемы защиты и систему привилегий доступа в MySQL.
27 | Глава 11 объясняет проблемы и общие ошибки.
19 | Глава 12 описывает клиентские скрипты и утилиты MySQL.
11 | Глава 13 охватывает поддержку MySQL ODBC.
75 | Глава 14 рассказывает об оптимизации запросов.
5 | Заключение. Ссылки на источники дополнительной информации по СУБД MySQL.
1 | Приложение 1. Здесь описан комплектный CD-ROM.
1 | Приложение 2. Переменные окружения.
1 | Приложение 3. Выяснение вопросов или сообщение об ошибках в пакете
 | Приложение 4. GNU GENERAL PUBLIC LICENSE.
 | Приложение 5. GNU LESSER GENERAL PUBLIC LICENSE.

Всего: 370 страниц в формате А4.


MySQL: руководство пользователя

Введение

За последнее время MySQL сильно продвинулась вперед. Уже сейчас эта СУБД стала фактическим стандартом для интернет-приложений (веб-магазины, сложные сайты, информационные порталы). Под открытыми системами (Linux, FreeBSD) и даже под закрытыми, где нет продукции Microsoft (Sun Solaris, разные коммерческие версии Unix), эта СУБД лидирует уже сейчас. Да оно и понятно: она обладает очень высоким быстродействием и надежностью (по некоторым параметрам поспорит даже с монстром от Oracle!).

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

Тут и возникает серьезная проблема: в России с литературой по открытым системам дело обстоит из рук вон плохо. То есть, хуже некуда. Представим такую ситуацию: на предприятии успешно идет внедрение корпоративной БД под MySQL (возможности этой СУБД легко позволяют управиться с потребностями довольно крупной компании, проверено лично). Есть много далеких от компьютерной техники людей (но все же не чайников), которые более-менее разбираются во всяких MS Windows и MS Office, но им теперь придется работать с клиентской частью MySQL (кстати, MySQL есть чуть ли не под любой ОС). Понятно, что необходимы знания о том, как это делается, особенно если учесть, что диалект языка SQL, реализованный в MySQL, имеет немало отличий от версии ANSI SQL93. Что делать администратору, на которого в ближайшее время обрушится шквал вопросов?

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

По меньшей мере странным выглядит то, что никто до сих пор не подумал о том, что литература по MySQL нужна и тем, кто с этой СУБД будет работать на уровне пользователя. Сложно поверить в то, что здесь все считается интуитивно понятным. Все же это очень сложный пакет, даже на пользовательском уровне нельзя просто взять и начать с ним работать, надо учиться. Почему-то принято считать, что всякий, кто работает с MySQL, является администратором системы, ему нужны подробные сведения по настройкам пакета, и ему совсем не к чему описывать простые понятия, вроде языка этого пакета. Такое мнение глубоко ошибочно! Язык у этого пакета изобилует всякими скрытыми возможностями, хитростями и неожиданностями. Далеко не всем нужно и администрироваине.

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

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

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

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

В этой книге рассмотрены следующие вопросы:

  • Соответствие MySQL отраслевым стандартам.
  • Структура языка SQL (вернее, его диалекта, принятого в MySQL), его основные понятия, примеры синтаксиса.
  • Введение в администрирование пакета (ограниченный обзор).
  • Язык SQL, реализованный в MySQL. Он рассмотрен в виде нескольких глав, каждая из которых охватывает свою часть языка, а именно:
    • Типы столбцов в таблицах.
    • Функции для использования в операторе SELECT.
    • Определение данных, создание, удаление и модификация таблиц.
    • Манипуляции с данными в таблицах.
    • Секреты и тонкости этой версии SQL.
  • Проблемы защиты и система привилегий пакета.
  • Рассмотрение общих ошибок при работе с пакетом и путей их обхода.
  • Взаимодействие с другими программами по протоколу ODBC.
  • Оптимизация запросов и работы с пакетом.

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

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

Благодарности

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

  • Паутову Надежду Константиновну за корректуру текста и помощь в работе над стилем изложения и терпение к моим ошибкам.
  • Филатову Августу Александровну за неоценимые консультации по русскому языку.
  • Дуванова Александра Александровича за техническую помощь в изготовлении сопроводительного CD-ROM.
  • Паутова Валентина Павловича за предоставленную техническую помощь.
А также всех тех, без чьей ценной помощи и поддержки создание этой работы было бы невозможным. СПАСИБО ВАМ!

Некоторые пользователи MySQL

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

Если Вы используете MySQL в уникальной среде или имеете память об успехе относительно того, как Вы применяли MySQL, Вы можете написать на docs@mysql.com с темой Success:.

  • Peter Zaitsev с Spylog.ru пишет: Я думаю, что Вы будете заинтересованы размером моей базы данных. Целая база данных в настоящее время хранится на 15 серверах, и я думаю, что это приблизительно 60000 таблиц, содержащих около 5000000000 строк. Мой обычно загруженный сервер в настоящее время хранит приблизительно 10000 таблиц с 1000000000 строк в них. Большие таблицы имеют приблизительно 50000000 строк, и это значение поднимется, как только я перейду на ядро 2.4 с большими файлами. В настоящее время я должен удалить многое из файлов регистрации для больших сайтов, чтобы размеры таблиц попали в 2Gb.
  • Texas Instruments использует MySQL для обработки ряда таблиц, которые содержат до 2000 миллионов строк в базе данных регрессов проверок правильности.

Сайты новостей

  • Yahoo!
  • Slashdot: Новости и обсуждения по Linux и технике, разные дискуссии
  • Все про Linux
  • Linuxtoday
  • 32Bits Online: все о вычислениях
  • Freshmeat: новости относительно новых версий программ и аппаратуры

Web-поисковики

  • AAA Matilda Web Search
  • What's New
  • Aladin
  • Columbus Finder
  • Spider
  • Blitzsuche
  • Indoseek Indonesia
  • Yaboo BOOkmarker
  • OzSearch Internet Guide
  • Splat! Search
  • The Open Source Digital Library System Project

Некоторые специализированные поисковики

  • SpyLOG: очень популярное место счетчиков для Web
  • TuCows Network; Архив Free Software
  • Jobvertise: Поиск работы
  • База данных музыки
  • Футбольный поисковик
  • TAKEDOWN: реслинг
  • Международная сеть лирики
  • Музыканты, ищущие других музыкантов (свободный сервис)
  • AddALL поиск книг и сравнение их цен
  • Оглавление Harvard's Gray Herbarium
  • Поисковик для авторов игр
  • Энциклопедия каникул и отпусков
  • База данных игр для Mac (применяет PHP и MySQL)
  • Публикации Monash University в Australia
  • Профессиональное здоровье и база данных по сайтам (проект ECC)
  • Биоинформационная база данных главной детской больницы в Монреале

Онлайновые магазины

  • Spoiler Webzine.Интерактивный журнал, охватывающий музыку, литературу, разные виды искусства.
  • Ежедневные новости относительно Linux на немецком языке
  • Betazine: интерактивный журнал испытателей бета-версий
  • Computer Currents

Если Вам понравилась эта работа, напишите: считаете ли Вы ее качественной или нет? Стоит ли издавать? Хорошо ли изложен материал?

Web-сайты, использующие MySQL для своей работы

  • NASA
  • NASA KIDS
  • Sience@NASA
  • handy.de
  • Репозитарий Qt Widget и Object
  • Бразильский сайт проекта samba
  • Польский общий социальный обзор
  • Expo2000 Международное распределение билетов для Expo2000 было выполнено, используя MySQL и tcl/tk. Более 5000 транспортных агентств во всем мире имеют доступ к этому.
  • FreeVote.com: свободное обслуживание голосований с миллионами пользователей.
  • Forza Motorsport
  • DreamHost Web-хостинг

Некоторые сервисы Domain/Internet/Web

  • Перечень Web-провайдеров, которые поддерживают MySQL
  • Динамические сервисы DNS
  • Динамические сервисы имен доменов
  • Open DNS Project; динамический сервис DNS
  • Hammernode; Публичные серверы DNS
  • Бесплатные домены третьего уровня
  • Online Database
  • Сервисы BigBiz Internet
  • Виртуальная газета
  • Global InfoNet Inc
  • WebHosters: энциклопедия WWW-провайдеров
  • Информационные сервер
  • Новостной сайт по технологиям
  • WorldNet Communications: интернет-провайдер
  • Netizen: Web в Австралии
  • Поисковый сайт по учебным курсам в Англии (UK)
  • Чат Gannon (лицензия GPL). Написан на языках Perl и Javascript
  • Справочник интернет-ссылок
  • Web-ориентированный сервис закладок с удобным управлением
  • Walnut Creek CDROM
  • WWWThreads: интерактивные дискуссионные форумы по разным вопросам
  • Итальянское хранилище данных по местной погоде
  • Аукцион "Person To Person"
  • Советы Web-разработчику
  • Mailfriends.com: свободный сервис для каждого, кто хочет найти друзей через internet.
  • Web-страница списка Telnet BBS
  • Цифровые открытки UniNova
  • Поисковик с комментариями по DSL-провайдерам в разных странах. Сделан на MySQL и Modperl, все страницы будут сгенерированы динамически из базы данных на MySQL

Web-сайты, применяющие в работе PHP и MySQL

  • Jgaa's Internet: официальный сайт поддержки
  • Ionline: публикации про MySQL, PHP, Java, Web-программирование, разработку DB
  • BaBoo (Browse and bookmark). Свободный Web-менеджер закладок с календарем
  • Система планирования курсов в Pensacola Junior College
  • Florida Community College в Jacksonville
  • 32bit.com: архив по shareware/freeware
  • Шутки 2000
  • Burken.NU Burken предлагает много скриптов для удаленных пользователей, подобно счетчикам, гостевым книгам, системам показа баннеров и прочему.
  • tips.pair.com Советы по html, javascript, 2d/3d-графике и PHP3/MySQL. Все страницы строятся из базы данных.
  • Softwarezrus.comСайт, который продает готовые компьютеры.

Консультанты по MySQL

  • Ayni AG
  • Online Database
  • DataGuard (использует MySQL и PHP)
  • WWITS (использует MySQL и PHP)
  • Чиповый замок Inc
  • Cybersource Pty. Ltd
  • Spring infotainment gmbh & co. kg
  • Разработка Web-сайтов с MySQL
  • Группа консультантов Berkeley
  • JAMM Consulting Inc.

Прочие страницы

  • Демонстрашки AZC.COM
  • Поиск учебных курсов
  • Онлайновый аукцион Northerbys
  • Амстердамский аэропорт
  • База данных по CD
  • Звуковая база данных
  • Музыкальные записи в нотах
  • Bagism: фаны Джона Леннона
  • US Folk брокер
  • Чтение почты через Web
  • Бесплатные домашние странички на www.somecoolname.mypage.org
  • Der Server f@"ur Schulen im Web (сайт на немецком языке)
  • Онлайновые сервисы Auldhaefen
  • Информационный центр CaryNET
  • Dataden Computer Systems
  • Andr'emuseet (на шведском языке)
  • HOMESITE Internet Marketing
  • Сетевые сервисы Jade-V
  • Weather World 2010 Technical Credits
  • Реестр присосок к Gimp
  • Архив технической информации и инструментов для Java (совместим с MySQL ANSI-92)
  • База данных по кодам к играм
  • Страничка "Powered By" (Kcilink)
  • Netcasting
  • NBL (Австралийская национальная баскетбольная лига)
  • Много CGI-скриптов
  • Whirlycott: дизайн Web-сайтов
  • Музей Tusculanum Press
  • Centro Siciliano di Documentazione
  • Статистика по Quake
  • Astroforum: все про астрологию (сайт только на немецком языке)
  • OpenDebate: интерактивные опросы и открытое обсуждение проблем
  • Дискуссии по химии (открытый сервер)
  • FreSch! Свободный сервис поиска учащихся и перспективных выпускников
  • Стокгольмский пинбол
  • HEK: конструкторская компания
  • Elsevier: бизнес-информация
  • Медицинские ссылки (применяет ColdFusion и MySQL)
  • Поиск работ и людей в JobLink-USA
  • Ассоциация по Skydiving
  • E-коммерция и внутренний учет
  • Ведущая деловая ежедневная газета Дании
  • База данных Internet NES
  • Транспортное агентство в Праге на 3 языках
  • Проект Linkstation
  • Интерактивная база данных с поиском по разным людям
  • Интерактивная база данных с поиском по классифицированным лошадям
  • Сайт Poot
  • "Playin' in the LAN": набор для контроля за сетью
  • Агентство для связи с общественностью армии США
  • Realestate handling in Yugoslavia
  • PIMS: Информационная система управления патентами
  • Pilkington Software Inc
  • Мемориал ветеранов Вьетнама
  • Объединение игроков, специализируется на работе с аукционами и скрытыми материалами
  • Ежедневный бюллетень института в Монтерее
  • Сайт, обслуживающий бизнесы и жителей Lake Washington's Eastside
  • Сайт французского боулинга

Посылайте обновления на webmaster@mysql.com.


Основная информация про MySQL

1 Основная информация про MySQL

MySQL очень быстрый, многопоточный, многопользовательский и поддерживающий SQL (Structured Query Language) сервер баз данных.

MySQL является free software. Он лицензируется по GNU GENERAL PUBLIC LICENSE http://www.gnu.org.

Сайт MySQL предоставляет последнюю информацию касательно MySQL.

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

  • Все о разработчиках MySQL можно узнать в разделе "1.1.2 Что такое MySQL AB".
  • Обсуждение основных возможностей MySQL приведено в разделе "1.1.4 Основные возможности MySQL".
  • Для новичков предусмотрен раздел "2 Введение в MySQL".
  • Примеры на SQL и информация по тестированию производительности есть в каталоге sql-bench дистрибутива.
  • Перечень известных на сегодняшний день проблем и дефектов приведен в разделе "1.2.7 Известные ошибки в MySQL".

ВАЖНО:

Сообщения об ошибках также как вопросы и комментарии, должны быть посланы списку рассылки mysql@lists.mysql.com. Подробности в разделе "Как сообщать о проблемах и сбоях". Скрипт mysqlbug должен использоваться, чтобы генерировать отчеты об ошибках. Для дистрибутивов исходных текстов скрипт mysqlbug может быть найден в каталоге scripts. Для двоичных дистрибутивов mysqlbug находится в каталоге bin. Если Вы нашли ошибку защиты в MySQL, Вы должны послать e-mail на security@mysql.com.

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

1.1 MySQL, MySQL AB и Open Source

1.1.1 Что такое MySQL

MySQL представляет собой очень популярную систему управления базами данных с открытыми исходными текстами, разрабатываемую MySQL AB. MySQL AB является коммерческой компанией, строящей свой бизнес на сервисах, сосредоточенных на базе данных MySQL. Подробности в разделе "1.1.2 Что такое MySQL AB".

MySQL представляет собой систему управления базами данных.
Базой данных называют структурированный набор данных. Это может быть чем угодно: от простого перечня покупок до галереи изображений. Чтобы добавлять, обращаться и обрабатывать данные, сохраненные в компьютерной базе данных, Вы нуждаетесь в системе управления базы данных, типа MySQL. Так как компьютеры очень хороши при обработке больших количеств данных, базы данных играют центральную роль в вычислениях, как автономные утилиты, или как части других пакетов прикладных программ.
MySQL является реляционной СУБД.
Реляционная база данных сохраняет данные в отдельных таблицах. Это добавляет быстродействие и гибкость. Таблицы связаны определенными отношениями, делающими возможным объединить данные из нескольких таблиц в одном запросе. SQL-часть MySQL ориентирована на Structured Query Language, наиболее общий стандартизированный язык, используемый, чтобы обратиться к компьютерным базам данных.
MySQL является Open Source Software.
Open Source означает, что тексты открыты для чтения и правки всем желающим. Любой может скачать MySQL из Internet и использовать его совершенно бесплатно. Любой желающий может изучать исходный текст и изменять его по своему усмотрению. MySQL использует лицензию GPL (GNU General Public License) http://www.gnu.org, чтобы определить то, что Вы можете делать с программным обеспечением в различных ситуациях. Если Вы считаете GPL неудобной или должны внедрить MySQL в коммерческую прикладную программу, Вы можете купить коммерчески запатентованную версию у авторов.
Почему используют MySQL?
MySQL очень быстр, надежен и легок в использовании. Если это то, что Вы ищете, Вы должны попробовать его. MySQL также имеет очень практичный набор свойств, разработанных в очень близком сотрудничестве с пользователями. Вы можете найти сравнение эффективности MySQL с некоторыми другими администраторами баз данных на странице эталонных тестов. Подробности в разделе "14.1.4 Пакет тестов MySQL Benchmark Suite". MySQL был первоначально разработан, чтобы обработать очень большие базы данных намного быстрее, чем существующие решения, и успешно использовался в высокотребовательных промышленных средах в течение нескольких лет. При постоянной разработке MySQL сегодня предлагает богатый и очень полезный набор функций. Связность, быстродействие и защита делают MySQL очень подходящим для обращения к базам данных из Internet.
Технические возможности MySQL.
За подробностями отсылаю Вас к разделу "9 Обзор языка MySQL". MySQL является системой "клиент-сервер", состоящей из многопоточного SQL-сервера, который поддерживает различные функции, нескольких различных клиентских программ и библиотек, административных инструментальных средств и нескольких интерфейсов программирования.
MySQL имеет много дополнительных программ.
Вероятно, Вы обнаружите, что Ваша любимая прикладная программа или язык программирования уже поддерживает MySQL.

Официально MySQL произносится как "Май-Эс-Ку-Эль", а не как MY-SEQUEL.

1.1.2 Что такое MySQL AB?

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

Авторы ищут партнеров, которые хотели бы поддерживать разработку MySQL так, чтобы они могли бы ускорить темп разработки. Если Вы заинтересованы в этом, напишите на e-mail partner@mysql.com!

MySQL AB имеет в настоящее время свыше 20 разработчиков ( http://www.mysql.com/development/team.html) в платежной ведомости, и это число возрастает быстро.

Основные источники дохода:

  • Коммерческая поддержка высокого качества для MySQL, обеспеченная разработчиками MySQL непосредственно. Если Вы заинтересованы в закупке контракта поддержки, пожалуйста, посетите https://order.mysql.com, чтобы рассмотреть параметры поддержки или собственно заказать поддержку.
  • Консультантские услуги. Фирма MySQL AB имеет разработчиков и консультантов в 12 странах и партнеров во многих других странах, которые могут помочь Вам почти с любой проблемой с MySQL. Если Вы нуждаетесь в консультантских услугах, пожалуйста, напишите по e-mail хорошее описание Ваших потребностей на info@mysql.com! Если авторы не смогут обработать это непосредственно, то они обычно могут найти партнера или разработчика, который может помочь Вам с Вашими проблемами.
  • Авторы продают лицензии на использование MySQL как встроенной базы данных. Если Вы имеете коммерческую программу, для которой Вам требуется база данных высоких качеств, но Вы не можете позволить себе открыть ее исходники, Вы можете купить право использовать сервер MySQL под нормальным коммерческим авторским правом. Если Вы заинтересованы этим, Вы можете купить лицензию прямо на сайте https://order.mysql.com или написать на licensing@mysql.com.
  • Реклама. Сайт http://www.mysql.com представаляет собой очень популярное место более, чем с 10000000 показами страницы в месяц (на январь 2001). Сами понимаете, что баннер на таком сайте гарантирует известность в среде Open source, Linux и баз данных. Если это Вам интересно и нужно, напишите на advertising@mysql.com.
  • Авторы пакета формируют программу партнеров, чтобы иметь возможность обеспечивать услуги MySQL в каждой стране. Если Вы заинтересованы в том, чтобы стать таким партнером, пишите на partner@mysql.com или посетите сайт программы партнерства http://www.mysql.com/information/partners.html.
  • Разработчики обеспечивают обучение MySQL через свои программы партнеров. Для получения большего количества информации, пожалуйста, пишите на info@mysql.com.
  • Если Вы заинтересованы использованием марки изготовителя MySQL в Вашем маркетинге, Вы можете написать об этом на e-mail info@mysql.com.

Авторы пакета хотят, чтобы MySQL всегда был:

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

MySQL AB и команда MySQL AB:

  • Продвигает в массы философию Open Source (открытых исходных текстов) и поддерживает все сообщество разработчиков Open Source Community.
  • Предпочитает партнеров, которые совместно используют знания.
  • Отвечают на почту и оказывает поддержку.
  • Является виртуальной компанией, работающей в основном по сети.
  • Выступает против программных патентов.

1.1.3 История MySQL

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

Название возникло из сокращения (а вернее, слияния) слов My SQL, что на английском языке значит "мой SQL". Названию около десяти лет, оно прижилось еще в те времена, когда пакет не был коммерческой разработкой.

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

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

  • Полностью многопоточное использование ядерных нитей. Это означает, что пакет может легко использовать много CPUs, если они есть.
  • Интерфейсы для языков C, C++, Eiffel, Java, Perl, PHP, Python и Tcl.
  • Работает на многих различных платформах.
  • Много типов столбцов: целые со знаком или без него длиной 1, 2, 3, 4 и 8 байт, FLOAT, DOUBLE, CHAR, VARCHAR, TEXT, BLOB, DATE, TIME, DATETIME, TIMESTAMP, YEAR, SET и ENUM. Подробности приведены в разделе "5 Типы столбцов". Там все рассказано.
  • Очень быстрые объединения, использующие оптимизированное однопроходное объединение многих таблиц.
  • Полная поддержка операторов и функций в частях запроса SELECT и WHERE. Например:
    mysql> SELECT CONCAT(first_name, " ", last_name) FROM tbl_name
                  WHERE income/dependents > 10000 AND age > 30;
  • SQL-функции выполнены через хорошо оптимизированную библиотеку классов и должны выполняться с такой скоростью, с какой только возможно! Обычно не имеется никакого распределения памяти вообще после инициализации запроса.
  • Полная поддержка предложений SQL GROUP BY и ORDER
BY. Поддержка групповых функций (COUNT(),
COUNT(DISTINCT ...), AVG(), STD(),
SUM(), MAX() и MIN()).
  • Поддержка LEFT OUTER JOIN и RIGHT OUTER JOIN с синтаксисами ANSI SQL и ODBC.
  • Вы можете смешивать таблицы из разных баз данных в одном запросе.
  • Привилегии и система паролей, которая является очень гибкой и безопасной, и позволяет проверку, основанную на имени хоста. Пароли безопасны потому, что вся передача пароля шифрована, когда Вы соединяетесь с сервером.
  • ODBC (Open-DataBase-Connectivity) поддерживается для Win32 (с исходниками). Все функции ODBC 2.5 и многие другие реализованы. Например, Вы можете использовать MS Access для связи с сервером MySQL. Подробности в разделе "13 Поддержка MySQL ODBC".
  • Очень быстрые дисковые таблицы B-tree с индексным сжатием.
  • Можно иметь до 32 индексов на таблицу. Каждый индекс может состоять от 1 до 16 столбцов или частей столбцов. Максимальная индексная длина 500 байт (это может быть изменено при компиляции MySQL). Индекс может использовать префикс поля CHAR или VARCHAR.
  • Записи фиксированной и переменной длины.
  • Таблицы в памяти, которые используются как временные таблицы.
  • Поддержка поистине огромных объемов данных. Известен случай использования MySQL на 60000 таблиц, хранящих около 5000000000 строк.
  • Все столбцы имеют значения по умолчанию. Вы можете использовать вызов INSERT, чтобы вставить подмножество столбцов таблицы. Те столбцы, которым явно не заданы значения, будут автоматически установлены к их значениям по умолчанию.
  • Для переносимости использованы GNU Automake, Autoconf и Libtool.
  • Пакет написан на C и C++. Оттестирован на всех распространенных компиляторах этих языков.
  • Очень быстрая поточно-безопасная система управления памятью.
  • Никаких утечек памяти. MySQL тестировался с помощью Purify, коммерческого детектора утечек памяти.
  • Есть myisamchk, очень быстрая утилита для проверки таблицы, оптимизации и ремонта. Все функциональные возможности myisamchk также доступны через интерфейс SQL.
  • Полная поддержка для нескольких различных наборов символов, включая ISO-8859-1 (Latin1), german, big5, ujis и много других. Например, скандинавские символы `@ringaccent{a}', `@"a' и `@"o' позволяются в именах столбцов и таблиц.
  • Все данные сохранены в выбранном наборе символов. Все сравнения для нормальных столбцов нечувствительны к регистру.
  • Сортировка выполнена согласно выбранному набору символов (шведский по умолчанию). Возможно изменить это, когда сервер MySQL работает. Чтобы увидеть пример очень продвинутой сортировки, рассмотрите сортировочный код для Czech. MySQL поддерживает много различных наборов символов, которые могут быть определены при компиляции или во время выполнения.
  • Псевдонимы на таблицах и именах столбцов доступны как в стандарте SQL92.
  • DELETE, INSERT, REPLACE и UPDATE возвращают число строк, которые были изменены (обработаны). Можно взамен вернуть число согласованных строк, устанавливая флажок при соединении с сервером.
  • Имена функции не сталкиваются с именами столбцов или таблиц. Например, ABS представляет собой имеющее силу имя столбца. Единственное ограничение: для обращения к функции никакие пробелы не позволяются между именем функции и символом скобки (`('), который следует за ним.
  • Все программы пакета MySQL понимают параметры командной строки --help или -? для выдачи справки о параметрах запуска конкретной программы.
  • Сервер умеет выдавать сообщения об ошибках и диагностику на разных языках.
  • Клиенты могут соединяться с сервером MySQL, используя все мыслимые способы, допустимые в сегодняшних сетях: сокеты TCP/IP, сокеты Unix (под Unix) или даже именованные каналы (под NT).
  • MySQL-специфичная команда SHOW может использоваться, чтобы получить информацию относительно баз данных, таблиц и индексов. Команда EXPLAIN может использоваться, чтобы определить, как именно оптимизатор решает запрос.

1.1.5 Насколько стабилен MySQL?

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

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

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

Каждый выпуск MySQL был пригоден для использования, и имелись проблемы только, когда пользователи начинали использовать код из серых зон. Естественно, пользователи снаружи не видят то, чем являются серые зоны, этот раздел пытается указать, которые зоны в настоящее время известны. Описания имеют дело с MySQL Version 3.23. Все известные и сообщенные ошибки выправлены в последней версии, за исключением ошибок, перечисленных в отдельном разделе, которые являются проблемами, связанными с проектом. Подробности в разделе "1.2.7 Известные ошибки и проблемы".

MySQL написан на нескольких уровнях и различных независимых модулях. Эти модули перечислены ниже с индикацией относительно того, как хорошо проверен каждый из них (сравните с MS SQL Server!):

Драйвер ISAM-таблиц: стабилен.
Это управляет хранением и поиском всех данных в MySQL Version 3.22 и ранее. Во всех выпусках MySQL не имелось сообщений об ошибках в этом коде. Единственный известный способ получить разрушенную таблицу состоит в том, чтобы уничтожить сервер в середине модификации. Даже это вряд ли уничтожит любые данные потому, что все данные сбрасываются на диск между запросами. Не было отчетов об ошибках относительно потерянных данных из-за ошибок в MySQL.
Драйвер MyISAM-таблиц: стабилен.
Это ноовведение MySQL Version 3.23. Это в значительной степени основано на коде ISAM-таблиц, но имеет много новых и очень полезных свойств.
Лексический анализатор и обработчик команд: стабильны.
Не было сообщений об ошибках в этой системе в течение длительного времени.
Клиентский код на C: стабилен.
Никаких известных проблем. До Version 3.20 имелись некоторые ограничения в размере буферов передачи/приема. Начиная с Version 3.21, буферный размер теперь динамически меняется до значения по умолчанию в 16M.
Стандартные клиентские программы: стабильны.
Это касается утилит mysql, mysqladmin, mysqlshow, mysqldump и mysqlimport.
Поддержка SQL: стабильна.
Базисная система функций SQL, классы строк и динамическая обработка памяти. Ни одной сообщенной ошибки в этой системе.
Оптимизатор запросов: стабилен.
Оптимизатор диапазонов: стабилен.
Оптимизатор объединений: стабилен.
Блокировки: пока Gamma.
Это очень зависит от системы. На некоторых системах имеются большие проблемы при использовании стандарта блокировки OS (fcntl()). В этих случаях Вы должны выполнить MySQL с опцией --skip-locking. Проблемы, как известно, происходят на некоторых Linux-системах и на SunOS при использовании файловых систем по NFS.
Linux threads: стабильно.
Главная найденная проблема была с обращением fcntl(), которое исправлено, используя опцию --skip-locking для mysqld. Некоторые пользователи сообщали о проблемах тупика в Version 0.5. LinuxThreads должен быть перетранслирован, если Вы планируете использовать свыше 1000 параллельных подключений. Хотя можно выполнить много подключений с LinuxThreads по умолчанию (однако, Вы никогда не будете иметь более, чем 1021 подключение), заданный по умолчанию лимит стека в 2 МБ делает прикладную программу ненадежной, и она способна свалиться в дамп ядра после создания 1021 неактивных подключений.
Solaris 2.5+ pthreads: стабильно.
Мы используем это для всей нашей промышленной работы.
MIT-pthreads (прочие системы): стабильно.
Не имелось никаких сообщенных ошибок, начиная с Version 3.20.15, и никаких известных авторам (почувствуйте разницу!) ошибок, начиная с Version 3.20.16. На некоторых системах имеется сильное замедление операций (до 1/20 секунды бездействия между каждыми двумя запросами). Конечно, MIT-pthreads может все немного замедлять, но индексные инструкции SELECT обычно выполняются в одном пакете.
Другие реализации потоков: Beta-Gamma.
Версии для других систем все еще очень новые и могут иметь ошибки, возможно, в MySQL, но наиболее часто непосредственно в реализации потоков.
LOAD DATA..., INSERT...SELECT: стабильно.
Некоторые люди думали, что они нашли ошибки здесь, но они обычно просто не поняли ситуацию. Пожалуйста, внимательно проверьте руководство перед тем, как сообщать о возникших проблемах!
ALTER TABLE: стабильно.
Маленькие изменения в Version 3.22.12.
DBD: стабильно.
Сейчас поддерживает Jochen Wiedmann (wiedmann@neckar-alb.de). Спасибо!
mysqlaccess: стабильно.
Написан и поддерживается Yves Carlier (Yves.Carlier@rug.ac.be). Спасибо!
GRANT: стабильно.
Большие изменения внесены в MySQL Version 3.22.12.
MyODBC (используется ODBC SDK 2.5): Gamma.
Это, кажется, уже работает хорошо с некоторыми программами.
Репликация: Beta/Gamma.
Авторы все еще работают над репликацией, так что не ожидайте, что это будет твердой скалой. С другой стороны, некоторые пользователи MySQL уже вовсю применяют это свойство с очень хорошими результатами.
Таблицы BDB: Beta.
Код Berkeley DB сам по себе очень устойчив, но разработчики пакета все еще улучшают интерфейс между MySQL и таблицами BDB, так что будет требоваться некоторое время прежде, чем все будет надежно.
Таблицы InnoDB: Beta.
Это недавнее добавление к MySQL. Они работают хорошо и могут использоваться после начального тестирования.
Автоматический ремонт таблиц MyISAM: Beta.
Это воздействует только на новый код, который проверяет, была ли таблица закрыта правильно, и выполняет автоматическую проверку/ремонт таблицы, если это не так.
Таблицы MERGE: Beta/Gamma.
Использование ключей на таблицах MERGE все еще не оттестировано как следует. Другая часть кода MERGE проверена.
FULLTEXT: Beta.
Текстовый поиск работает, но все еще не используется широко.

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

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

MySQL Version 3.22 имеет лимит в 4G на размер таблицы. С новым кодом MyISAM в MySQL Version 3.23 максимальный размер таблицы увеличен до 8 миллионов терабайт (2^63 байт).

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

Операционная система | Ограничение размера файла
Linux-Intel 32 bit | 2G, 4G или больше, зависит от версии Linux
Linux-Alpha | 8T (?)
Solaris 2.5.1 | 2G (возможно, до 4G с патчем)
Solaris 2.6 | 4G
Solaris 2.7 Intel | 4G
Solaris 2.7 ULTRA-SPARC | 8T (?)

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

Это означает, что размер таблицы для MySQL обычно ограничивается операционной системой, а не самим пакетом.

По умолчанию таблицы MySQL имеют максимальный размер около 4G. Вы можете проверять максимальный размер таблицы для каждой конкретной таблицы с помощью команды SHOW TABLE STATUS или утилитой myisamchk -dv table_name. Подробности приведены в разделе "4.10 Синтаксис вызова SHOW".

Если Вы нуждаетесь в таблицах, больших, чем 4G (и Ваша операционная система поддерживает это), Вы должны установить параметры AVG_ROW_LENGTH и MAX_ROWS, когда Вы создаете Вашу таблицу. Подробности в разделе "7.3 Синтаксис CREATE TABLE". Вы можете установить их и позже с помощью ALTER TABLE. Подробности в разделе "7.4 Синтаксис ALTER TABLE ".

Если Ваша большая таблица нужна только для чтения, Вы могли бы использовать myisampack, чтобы объединить и сжать много таблиц в одну. Утилита myisampack обычно сжимает таблицу по крайней мере на 50%, так что Вы можете иметь намного большие таблицы.

Вы можете обойти ограничения размера файла операционной системы для файлов данных MyISAM, используя опцию RAID. Подробности в разделе "7.3 Синтаксис CREATE TABLE".

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

1.1.7 Совместимость с проблемой 2000

MySQL непосредственно не имеет никаких трудностей с проблемой 2000 (Y2K):

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

Вы можете сталкиваться с проблемами в прикладных программах, которые используют MySQL, но сами несовместимы с проблемой Y2K. Например, много старых прикладных программ сохраняют или управляют значениями лет, используя числа с 2 цифрами (которые являются неоднозначными). Эта проблема также может быть составлена прикладными программами, которые используют 00 или 99 как значения для индикатора "пропустить". В свое время пришлось столкнуться с программой, которая помечала удаленные записи, выставляя им год 00...

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

Имеется простой пример, иллюстрирующий, что MySQL не имеет любых проблем с датами до года 2030:

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

mysql> CREATE TABLE y2k (date date, date_time datetime,
                             time_stamp timestamp);
Query OK, 0 rows affected (0.00 sec)

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

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

Это показывает, что типы DATE и DATETIME не будут давать никаких проблем с будущими датами (они легко обрабатывают даты вообще до 9999 года).

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

Даже при том, что MySQL Y2K-совместим, Вы отвечаете за то, чтобы обеспечить однозначный ввод. Подробности в разделе "5.2.1 Проблема Y2K и типы Date", там описаны правила MySQL для ввода дат с неоднозначными данными (данные, содержащие значения года с 2 цифрами).

1.2 MySQL и стандарты

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

1.2.1 MySQL-расширения для стандарта ANSI SQL92

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

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

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

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

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

MySQL-расширения перечислены ниже:

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

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

Авторы пробуют заставить MySQL следовать стандартам ANSI SQL и ODBC SQL, но в некоторых случаях MySQL обрабатывает некоторые дела по-другому:

  • -- является комментарием, только если сопровождается незаполненным пространством. Подробности чуть ниже.
  • Для столбцов VARCHAR конечные пробелы будут удалены, когда значение сохранено. Подробности в разделе "1.2.7 Известные ошибки и проблемы".
  • В ряде случаев столбцы типа CHAR тихо меняются на столбцы типа VARCHAR.
  • Привилегии для таблицы автоматически не отменяются, когда Вы удаляете таблицу. Вы должны явно выдать REVOKE, чтобы отменить все привилегии для таблицы.
  • NULL AND FALSE вернет NULL вместо FALSE, чтобы не возиться долго с оценкой выражений.

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

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

  • || является конкатенацией строк, а не OR.
  • Вы можете иметь любое число пробелов между именем функции и `('. Это вынуждает все имена функций обрабатываться как зарезервированные слова.
  • `"' будет цитировать идентификаторы (аналогично MySQL ``'), но не строки.
  • REAL превратится в синоним для FLOAT вместо синонима для DOUBLE.
  • Заданный по умолчанию уровень изоляции транзакции: SERIALIZABLE. Подробности в разделе "9.2.3 Синтаксис SET TRANSACTION".

Этого также можно достичь опцией --sql-mode=REAL_AS_FLOAT, PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,SERIALIZE,ONLY_FULL_GROUP_BY.

1.2.4 Функциональные возможности, отсутствующие в MySQL

Следующие функциональные возможности отсутствуют в текущей версии MySQL. Есть список, указывающий, когда новые расширения могут быть добавлены к MySQL (с их приоритетами), его можно посмотреть в Интернете по адресу http://www.mysql.com/documentation/manual.php?section=TODO.

1.2.4.1 Вложенные операторы select (sub-selects)

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

Во многих случаях Вы можете переписать запрос без sub-select:

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

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

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

Запросы:

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

Могут быть переделаны так:

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

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

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

Второе решение должно использовать интерактивный SQL для автопостроения набора инструкций DELETE при использовании MySQL-расширения CONCAT() (вместо стандартного оператора ||):

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

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

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

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

1.2.4.2 SELECT INTO TABLE

MySQL не поддерживает Oracle SQL-расширение SELECT ... INTO TABLE .... MySQL вместо него поддерживает синтаксис ANSI SQL INSERT INTO ... SELECT ..., который является в основном той же самой функциональностью. Подробности в разделе "8.3.1 Синтаксис INSERT ... SELECT ".

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

Альтернативно, Вы можете использовать SELECT INTO OUTFILE... или CREATE TABLE ... SELECT, чтобы решить Вашу проблему.

1.2.4.3 Транзации

Поскольку MySQL в настоящее время поддерживает транзакции, следующее обсуждение имеет силу, только если Вы используете не транзакционно-безопасные типы таблицы. Подробности в разделе "9.2.1 Синтаксис BEGIN/COMMIT/ROLLBACK".

Часто спрашивают, почему MySQL не транзационная база данных?

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

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

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

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

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

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

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

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

Наконец, в ситуациях, где целостность имеет самую высокую важность, текущие свойства MySQL учитывают уровень транзакции или лучшую надежность и целостность. Если Вы блокируете таблицы с помощью LOCK TABLES, все модификации остановятся, пока любые проверки целостности не будут сделаны. Если Вы только получаете блокировку чтения (в противоположность блокировке записи), то чтение и вставки продолжают работать. Новые вставленные записи не будут замечены клиентами, имеющими блокировку READ, пока они не освободят их блокировки чтения. С помощью INSERT DELAYED Вы можете поместить вставки в локальную очередь, где они останутся до тех пор, пока блокировки не будут освобождены. Таким образом, сервер не будет иметь пользователя, который ждет завершения вставки. Подробности в разделе "8.4 Синтаксис INSERT DELAYED".

"Атомная" означает, что Вы можете убедиться в том, что в то время как каждая специфическая модификация выполняется, никакой другой пользователь не может сталкиваться с ней, и никакой автоматической обратной перемотки не будет никогда (хотя это может случаться на транзакционных системах, если Вы не очень осторожны). MySQL также гарантирует, что не будет иметься лишних чтений. Вы можете найти пример того, как писать атомные модификации в разделе "1.2.6 Как справиться без COMMIT/ROLLBACK".

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

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

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

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

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

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

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

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

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

SELECT * from table1,table2 where table1.id = table2.id;

Подробности есть в разделах "8.1.1 Синтаксис JOIN" и "2.5.6 Использование внешних ключей".

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

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

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

1.2.4.6 Почему не реализована поддержка для Foreign Keys

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

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

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

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

Противопоказания:

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

1.2.4.7 Views

MySQL не поддерживает views, но это планируется исправить примерно к 4.1.

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

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

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

1.2.4.8 `--' как начало комментария

Некоторые базы данных SQL применяют -- как начало комментария. MySQL имеет # как символ начала комментария, даже если инструмент командной строки mysql удаляет все строки, начинающиеся с --. Вы можете также использовать стиль комментариев языка C (/* это комментарий */) в MySQL.

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

UPDATE tbl_name SET credit=credit-!payment!

Как Вы думаете, что случится, когда значение payment отрицательное? А вот что. Поскольку 1--1 допустимо в SQL, пакет думает, что начался комментарий типа --. Вряд ли это входит в Ваши планы...

В MySQL Version 3.23 Вы можете использовать: 1-- Это был комментарий

Следующее обсуждение касается Вас, только если Вы управляете MySQL Version 3.23 или ранее:

Если Вы имеете программу SQL в текстовом файле, который содержит комментарии --, Вы должны использовать:

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

Вместо обычного решения:

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

Вы можете также редактировать командный файл, чтобы сменить комментарии -- на #:

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

Замените их обратно этой командой:

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

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

Entry level SQL92. ODBC levels 0-2.

1.2.6 Как обойтись без COMMIT/ROLLBACK

Следующее обычно применяется только для таблиц ISAM, MyISAM и HEAP. Если Вы используете только транзакционно-безопасные таблицы (BDB или InnoDB) в модификации, Вы можете также делать COMMIT и ROLLBACK в MySQL. Подробности в разделе "9.2.1 Синтаксис BEGIN/COMMIT/ROLLBACK".

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

Текущей проблемой является ROLLBACK. Без ROLLBACK Вы можете делать любой вид COMMIT с помощью LOCK TABLES. Для поддержки ROLLBACK с вышеупомянутыми типами таблицы MySQL должен быть изменен так, чтобы сохранять все старые записи, которые модифицировались, и иметь возможность быстро вернуться к отправной точке, если была выдана команда ROLLBACK. Для простых случаев это довольно просто (можно приспособить сюда isamlog), но будет намного трудней выполнить ROLLBACK для ALTER/DROP/CREATE TABLE.

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

  1. Примените LOCK TABLES ..., чтобы блокировать все таблицы, к которым Вы хотите обращаться.
  2. Проверьте все условия.
  3. Модифицируйте, если все в порядке.
  4. Вызовите команду UNLOCK TABLES, чтобы снять блокировки.

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

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

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

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

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

UPDATE tablename SET pay_back=pay_back+'relative change';
UPDATE customer SET customer_date='current_date',
                    address='new address', phone='new phone',
                    money_he_owes_us=money_he_owes_us+'new_money'
       WHERE customer_id=id AND address='old address' AND phone='old phone';

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

Во многих случаях пользователи хотели использовать ROLLBACK и/или LOCK TABLES с целью управления уникальными идентификаторами для некоторых таблиц. Это может быть обработано намного более эффективно, используя столбец AUTO_INCREMENT и функцию SQL LAST_INSERT_ID() или функцию C API mysql_insert_id().

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

UPDATE tbl_name SET row_flag=1 WHERE id=ID;

MySQL вернет для числа обработанных строк, если строка была найдена, и row_flag не был 1 в первоначальной строке.

1.2.7 Известные ошибки и проблемы

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

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

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

  • MATCH работает только с инструкциями SELECT.
  • При использовании SET CHARACTER SET не могут быть применены транслируемые символы в базе данных, таблице и столбцах.
  • DELETE FROM merge_table, используемый без WHERE, только очистит отображение для таблицы, не удаляя ничего в самих отображенных таблицах.
  • Вы не можете формировать пакет в другом каталоге при использовании MIT-pthreads, поскольку это требует правки кода MIT-pthreads, мы вряд ли это свойство будем исправлять.
  • Значения BLOB не могут надежно использоваться в GROUP BY, ORDER BY или DISTINCT. Только первые max_sort_length байт (по умолчанию 1024) используются при сравнении BLOB в этих случаях. Это может быть изменено с помощью опции -O max_sort_length при запуске mysqld. Обход для большинства случаев должен использовать подстроку: SELECT DISTINCT LEFT(blob,2048) FROM tbl_name.
  • Вычисление выполнено с BIGINT или DOUBLE (оба обычно длиной в 64 бита). Это зависит от функции, которую обрабатывает пакет. Общее правило: битовые функции выполнены с точностью BIGINT, IF и ELT() с BIGINT или DOUBLE, а все прочие с DOUBLE. Нужно пробовать избегать использовать большие длинные значения без знака (9223372036854775807)!
  • Все строковые столбцы, кроме BLOB и TEXT, автоматически удаляют все конечные пробелы, когда сохраняются. Для типа CHAR это разрешено и может быть расценено как свойство согласно ANSI SQL92. Ошибка в том, что в MySQL столбцы VARCHAR обрабатываются тем же самым путем.
  • Вы можете иметь только до 255 столбцов типа ENUM и SET для каждой таблицы.
  • safe_mysqld переназначает все сообщения mysqld в файл регистрации mysqld. Одна проблема с этим состоит в том, что, если Вы выполняете mysqladmin refresh, чтобы закрыть и вновь открыть файл регистрации, stdout и stderr все еще переназначаются к старому файлу регистрации. Если Вы используете опцию --log, Вы должны редактировать safe_mysqld, чтобы регистрировать данные в файле 'hostname'.err вместо 'hostname'.log, чтобы у Вас не было крупных проблем с запуском и работой с mysqladmin refresh.
  • В инструкции UPDATE столбцы модифицируются слева направо. Если Вы обращаетесь к модифицируемому столбцу, Вы получите модифицируемое значение вместо первоначального значения. Например:
    mysql> UPDATE tbl_name SET KEY=KEY+1,KEY=KEY+1;
    Это модифицирует KEY с 2 вместо 1.
  • Вы не можете использовать временные таблицы больше, чем однажды в том же самом запросе. Например, следующее не будет работать:
    select * from temporary_table, temporary_table as t2;
  • RENAME не работает с таблицами TEMPORARY.
  • Оптимизатор может обрабатывать DISTINCT по-разному, если Вы используете скрытые столбцы в объединении или нет. В объединении скрытые столбцы рассчитаны как часть результата (даже если они не показаны) в то время, как в нормальном запросе они не участвуют в сравнении DISTINCT. Мы, вероятно, изменим это в будущем, чтобы никогда не сравнить скрытые столбцы при выполнении DISTINCT. Например:
    SELECT DISTINCT mp3id FROM band_downloads WHERE userid=9 ORDER BY id DESC;
    и
    SELECT DISTINCT band_downloads.mp3id, FROM band_downloads,band_mp3
       WHERE band_downloads.userid=9 AND band_mp3.id=band_downloads.mp3id
       ORDER BY band_downloads.id DESC;
    Во втором случае Вы можете в MySQL 3.23.x получить две идентичных строки в наборе результатов (потому, что скрытый столбец 'id' может отличаться). Обратите внимание, что это случается только для запросов, где Вы не имеете ORDER BY в результате, что вообще-то неправильно с точки зрения стандарта ANSI SQL.
  • Поскольку MySQL позволяет Вам работать с типами таблиц, которые не поддерживают транзакции (и таким образом не могут выполнить rollback), некоторые вещи ведут себя немного иначе, чем в других серверах SQL. Это только должно гарантировать, что MySQL никогда не должен делать обратную перемотку для команд SQL. Это может быть иногда немного неуклюже, поскольку значения столбца должны проверяться прикладной программой, но это фактически даст Вам хорошее увеличение быстродействия, поскольку это позволяет MySQL делать некоторые оптимизации, которые иначе были бы невозможны или очень трудны. Если Вы устанавливаете столбец к неправильному значению, MySQL будет, вместо того, чтобы делать обратную перемотку, сохранять самое лучшее возможное значение в столбце.
    • Если Вы пробуете сохранять значение вне диапазона в числовом столбце, MySQL взамен сохранит самое маленькое или самое большое возможное значение.
    • Если Вы пробуете сохранять строку, которая не начинается с числа, в числовой столбец, MySQL сохранит 0 в нем.
    • Если Вы пробуете сохранять NULL, который не берет значения NULL, MySQL сохранит 0 или '' (пустую строку). Это поведение может, однако, быть изменено с опцией компиляции -DDONT_USE_DEFAULT_FIELDS.
    • MySQL позволяет Вам сохранять некоторые неправильные значения даты в столбцы DATE и DATETIME. Например, 2000-02-31 или 2000-02-00. Если дата полностью неправильна, MySQL сохранит в столбце специальное значение даты 0000-00-00.
    • Если Вы устанавливаете enum к неподдерживаемому значению, это будет установлено к значению ошибки 'empty string' с числовым значением 0.
  • Если Вы выполняете PROCEDURE на запросе, который возвращает пустой набор, в некоторых случаях PROCEDURE не будет трансформировать столбцы.
  • Создание таблицы типа MERGE не проверяет, имеют ли основные таблицы совместимые типы.
  • MySQL не может все же обрабатывать значения NaN, -Inf и Inf в double. Использование их вызовет проблемы при попытке экспортировать и импортировать данные. Вы должны как промежуточное решение изменить NaN на NULL (если возможно), а -Inf и Inf соответственно к минимальному и максимальному возможным значениям double.
  • LIMIT на отрицательных числах превращается в очень большие положительные числа, что ошибочно.
  • Если Вы используете ALTER TABLE, чтобы сначала добавить индекс UNIQUE к таблице, используемой в таблице типа MERGE, и затем использовать ALTER TABLE, чтобы добавить нормальный индекс уже на таблице MERGE, порядок ключей будет иным для таблиц, если имелся старый не уникальный ключ в таблице. Это потому, что ALTER TABLE помещает ключи UNIQUE перед нормальными ключами, чтобы обнаружить двойные ключи как можно раньше.

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

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

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


Введение в MySQL

2 Введение в MySQL

Эта глава обеспечивает введение в MySQL, показывая, как использовать клиент mysql, чтобы создавать и использовать простую базу данных. mysql (иногда упоминаемый как "terminal monitor" или "monitor") представляет собой интерактивную программу, которая позволяет Вам соединяться с сервером MySQL, выполнять запросы и просматривать результаты. Она может также использоваться в пакетном режиме: Вы помещаете Ваши запросы в файл заранее, затем сообщаете, чтобы клиент mysql выполнил содержимое файла. Оба пути использования будут здесь рассмотрены.

Чтобы увидеть список параметров mysql, вызовите его с опцией --help:

shell> mysql --help

Эта глава предполагает, что mysql установлен на Вашей машине, и что сервер MySQL доступен.

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

2.1 Соединение с сервером

Чтобы соединяться с сервером, Вы обычно должны обеспечить имя пользователя, когда Вы вызываете mysql и, вероятно, пароль. Если сервер выполняется на другой машине, Вы будете также должны определить hostname. Войдите в контакт с Вашим администратором, чтобы выяснить, какие параметры соединения Вы должны использовать, чтобы подключиться (то есть, какой hostname, порт, имя пользователя и пароль). Как только Вы узнаете соответствующие параметры, Вы должны иметь возможность соединиться так:

shell> mysql -h host -u user -p
Enter password: ********

Здесь ******** представляет Ваш пароль. Введите его, когда mysql отобразит сообщение Enter password:.

Если это работает, Вы должны увидеть некоторую вводную информацию, сопровождаемую подсказкой mysql>:

shell> mysql -h host -u user -p
Enter password: ********
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 459 to server version: 3.22.20a-log

Type 'help' for help.

mysql>

Подсказка сообщает Вам, что mysql готов принять команды.

Некоторые инсталляции MySQL позволяют пользователям соединяться как анонимным (неназванным) пользователям с сервером на локальной машине. Если у Вас дело обстоит именно так, Вы можете соединиться с таким сервером, вызывая mysql без параметров:

shell> mysql

После того, как Вы успешно соединились, Вы можете разъединять соединение в любое время, набрав команду QUIT в ответ на подсказку mysql>:

mysql> QUIT
Bye

Вы можете также разъединять связь, нажимая Control-D.

Большинство примеров в следующих разделах считает, что Вы связаны с сервером. Они указывают это подсказкой mysql>.

2.2 Ввод запросов

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

Имеется простая команда, которая просит, чтобы сервер сообщил свою версию и текущую дату. Напечатайте это как показано ниже после подсказки mysql> и нажмите клавишу RETURN:

mysql> SELECT VERSION(), CURRENT_DATE;
+--------------+--------------+
| version()    | CURRENT_DATE |
+--------------+--------------+
| 3.22.20a-log | 1999-03-19   |
+--------------+--------------+
1 row in set (0.01 sec)
mysql>

Этот запрос иллюстрирует несколько вещей относительно mysql:

  • Команда обычно состоит из инструкции SQL, сопровождаемой точкой с запятой. Имеются некоторые исключительные ситуации, где точка с запятой не требуется, например, упомянутая выше команда QUIT. Мы доберемся до других позже.
  • Когда Вы выдаете команду, mysql посылает ее серверу для выполнения и отображает результаты, затем печатает другой запрос mysql>, чтобы указать, что готов для приема другой команды.
  • mysql отображает вывод запроса как таблицу (строки и столбцы). Первая строка содержит метки для столбцов. Следующие строки задают результаты запроса. Обычно, метки столбца представляют собой имена столбцов, которые Вы выбираете из таблиц базы данных. Если Вы получаете значение выражения, а не столбец таблицы, mysql маркирует столбец, используя выражение непосредственно.
  • mysql показывает, сколько строк было возвращено, и как долго обрабатывался запрос, что дает Вам грубые данные относительно эффективности сервера. Эти значения неточны потому, что они представляют не машинное время или затраты времени CPU, а рамки выполнения запроса. На эти данные действуют, например, задержки в сетевом канале. Для краткости строка ``rows in set'' не показывается в оставшихся примерах из этой главы.

Ключевые слова могут быть введены в любом регистре. Следующие запросы эквивалентны:

mysql> SELECT VERSION(), CURRENT_DATE;
mysql> select version(), current_date;
mysql> SeLeCt vErSiOn(), current_DATE;

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

mysql> SELECT SIN(PI()/4), (4+1)*5;
+-------------+---------+
| SIN(PI()/4) | (4+1)*5 |
+-------------+---------+
|    0.707107 |      25 |
+-------------+---------+

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

mysql> SELECT VERSION(); SELECT NOW();
+--------------+
| version()    |
+--------------+
| 3.22.20a-log |
+--------------+
+---------------------+
| NOW()               |
+---------------------+
| 1999-03-19 00:15:33 |
+---------------------+

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

Имеется простая инструкция с длинной строкой:

mysql> SELECT
    -> USER()
    -> ,
    -> CURRENT_DATE;
+--------------------+--------------+
| USER()             | CURRENT_DATE |
+--------------------+--------------+
| joesmith@localhost | 1999-03-18   |
+--------------------+--------------+

В этом примере обратите внимание, как подсказка изменяется с mysql> на -> после того, как Вы вводите первую строку запроса. Этим mysql указывает, что пока не видел полную инструкцию и ждет остальное. Подсказка Ваш друг потому, что обеспечивает ценную обратную связь. Если Вы используете эту обратную связь, Вы будете всегда знать, чего ждет от Вас mysql.

Если Вы решаете, что Вы не хотите выполнять команду, но находитесь в процессе ввода, отмените ее вводом \c:

mysql> SELECT
    -> USER()
    -> \c
mysql>

Здесь также обратите внимание на подсказку. Она переключилась назад в mysql> после ввода \c, обеспечивая обратную связь, чтобы указать, что mysql готов для новой команды.

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

Подсказка | Смысл
mysql> | Ожидание новой команды
-> | Ожидание следующей строки многострочной команды
'> | Ожидание следующей строки при сборе строки, которая начинается с одиночной кавычки (')
"> | Ожидание следующей строки при сборе строки, которая начинается с двойной кавычки (")

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

mysql> SELECT USER()
    ->

Если это случается с Вами (Вы думаете, что ввели оператор, но единственный ответ представляет собой подсказку ->), наиболее вероятно, что mysql ждет точку с запятой. Введите точку с запятой, чтобы завершить инструкцию, и mysql ее выполнит:

mysql> SELECT USER()
    -> ;
+--------------------+
| USER()             |
+--------------------+
| joesmith@localhost |
+--------------------+

Подсказки '> и "> появляются при работе со строкой в кавычках. В MySQL Вы можете писать строки в символах ' или " (например, 'hello' или "goodbye"), и mysql позволяет Вам вводить длинные строки в виде нескольких коротких строк. Когда Вы видите подсказку '> или ">, это означает, что Вы ввели строку, которая начинается с символа кавычки ' или ", но еще не ввели вторую кавычку, которая завершает эту строку. Это также может сообщать и об ошибке:

mysql> SELECT * FROM my_table WHERE name="Smith AND age < 30;
    ">

Если Вы вводите эту инструкцию SELECT, то нажатие RETURN ничего не вернет. Вместо того, чтобы задаваться вопросом, почему этот запрос так долго выполняется, обратите внимание на подсказку ">. Это сообщает Вам, что mysql ожидает увидеть остальную часть незавершенной строки. Вы видите ошибку в инструкции? Строка "Smith пропускает вторую кавычку.

Что делать? Самая простая вещь: отменить команду. Однако, Вы не можете в этом случае просто напечатать \c, так как mysql интерпретирует это как часть, которая вводится! Вместо этого, введите заключительный символ кавычки (чтобы mysql понял, что Вы закончили строку), а уж потом \c:

mysql> SELECT * FROM my_table WHERE name = "Smith AND age < 30;
    "> "\c
mysql>

Подсказка изменяется обратно на mysql>, указывая, что mysql готов для новой команды.

Важно знать, что сообщают подсказки '> и ">, так как если Вы по ошибке вводите незавершенную строку, любые дальнейшие строки, которые Вы введете, будут игнорироваться mysql, включая строку QUIT! Это может крепко запутать, особенно, если Вы не знаете, что должны ввести кавычку завершения прежде, чем Вы сможете отменить текущую команду.

2.3 Создание и использование баз данных

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

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

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

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

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

mysql> SHOW DATABASES;
+----------+
| Database |
+----------+
| mysql    |
| test     |
| tmp      |
+----------+

Список баз данных, вероятно, иной на Вашей машине, но базы с именами mysql и test, вероятно, будут среди них. База данных mysql вообще обязательна потому, что она описывает привилегии доступа пользователей. База данных test часто обеспечивается как рабочая область для начинающих пользователей (лягушатник). Именно там проводятся разные "опыты со взрывами".

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

mysql> USE test
Database changed

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

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

mysql> GRANT ALL ON menagerie.* TO your_mysql_name;

Здесь your_mysql_name представляет собой имя пользователя MySQL, назначенное Вам.

2.3.1 Создание и выбор баз данных

Если администратор создал базу данных для Вас и установил Ваши права доступа, Вы можете начинать использовать ее. Иначе, Вы должны создать базу данных самостоятельно. Например:

mysql> CREATE DATABASE menagerie;

Под Unix имена баз данных чувствительны к регистру (в отличие от ключевых слов SQL), так что Вы должны всегда обращаться к Вашей базе данных как к menagerie, но не как Menagerie, MENAGERIE или еще как-то. Это также верно для имен таблицы. Под Windows это ограничение не применяется, хотя Вы должны обращаться к базам данных и таблицам, используя тот же самый регистр символов в течение запроса.

Создание базы данных не выбирает ее для использования, Вы должны сделать это явно. Чтобы объявить menagerie текущей (актуальной) базой данных, используйте эту команду:

mysql> USE menagerie
Database changed

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

shell> mysql -h host -u user -p menagerie
Enter password: ********

Обратите внимание, что menagerie не Ваш пароль. Если Вы хотите указать пароль в командной строке после опции -p, Вы должны сделать это без пробела (например, как -pmypassword, но не как -p mypassword). Однако, помещение Вашего пароля в командную строку не рекомендуется потому, что это выставит его на всеобщее обозрение всем пользователям Вашей машины.

2.3.2 Создание таблицы

Создание базы данных дело простое, но сейчас база пустая, о чем и сообщает команда SHOW TABLES:

mysql> SHOW TABLES;
Empty set (0.00 sec)

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

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

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

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

Пока в таблице pet ограничимся данными об имени, владельце, разновидности, поле, рождении и гибели, если она произошла.

Используйте инструкцию CREATE TABLE, чтобы определить размещение Вашей таблицы:

mysql> CREATE TABLE pet (name VARCHAR(20), owner VARCHAR(20),
    -> species VARCHAR(20), sex CHAR(1), birth DATE, death DATE);

VARCHAR представляет собой хороший выбор для столбцов имени, владельца и разновидности потому, что значения столбца изменяются по длине. Длины столбцов name, owner и species не должны превышать 20 символов. Вообще-то, для этого типа столбцов Вы можете выбирать любую длину от 1 до 255, какая кажется наиболее приемлемой Вам. Если Вы делаете столбец недостаточных размеров, а позже окажется, что Вы нуждаетесь в более длинном поле, MySQL обеспечивает инструкцию ALTER TABLE.

Пол животных можно представить разными путями, например, "m" и "f" или словами "male" и "female". Самое простое: использовать одиночные символы "m" и "f".

Использование типа данных DATE для столбцов рождения и гибели (birth и death) явно довольно очевидный выбор.

Теперь, когда Вы создали таблицу, SHOW TABLES должен произвести некоторый вывод:

mysql> SHOW TABLES;
+---------------------+
| Tables in menagerie |
+---------------------+
| pet                 |
+---------------------+

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

mysql> DESCRIBE pet;
+---------+-------------+------+-----+---------+-------+
| Field   | Type        | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| name    | varchar(20) | YES  |     | NULL    |       |
| owner   | varchar(20) | YES  |     | NULL    |       |
| species | varchar(20) | YES  |     | NULL    |       |
| sex     | char(1)     | YES  |     | NULL    |       |
| birth   | date        | YES  |     | NULL    |       |
| death   | date        | YES  |     | NULL    |       |
+---------+-------------+------+-----+---------+-------+

Вы можете использовать DESCRIBE в любое время, например, если Вы забываете имена столбцов в Вашей таблице, или каких они типов.

2.3.3 Загрузка данных в таблицу

После создания Вашей таблицы Вы должны заполнить ее. Инструкции LOAD DATA и INSERT полезны для этого.

Предположим, что Ваши записи о живности могут быть описаны как показано ниже. Заметьте, что MySQL ожидает даты в формате YYYY-MM-DD, это может быть отлично от того, к чему Вы привыкли.

name | owner | species | sex | birth | death
Fluffy | Harold | кошка | f | 1993-02-04 |
Claws | Gwen | кошка | m | 1994-03-17 |
Buffy | Harold | собака | f | 1989-05-13 |
Fang | Benny | собака | m | 1990-08-27 |
Bowser | Diane | собака | m | 1989-08-31 | 1995-07-29
Chirpy | Gwen | птичка | f | 1998-09-11 |
Whistler | Gwen | птичка |  | 1997-12-09 |
Slim | Benny | змея | m | 1996-04-29 |

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

Вы могли бы создать текстовый файл pet.txt, содержащий одну запись на строку, со значениями, отделяемыми позициями табуляции, указанными в том порядке, в котором столбцы были перечислены в инструкции CREATE TABLE. Для отсутствующих значений (типа неизвестного пола или дат гибели для животных, которые все еще живут), Вы можете использовать значения NULL. Чтобы представить их в Вашем текстовом файле, используйте \N. Например, запись для птички Whistler выглядит примерно так (пробелом я обозначил табуляцию):

Whistler Gwen птичка \N 1997-12-09 \N

Чтобы загрузить текстовый файл pet.txt в таблицу pet, используйте эту команду:

mysql> LOAD DATA LOCAL INFILE "pet.txt" INTO TABLE pet;

Вы можете определять разделитель значений столбцов и маркер конца строки в инструкции явно LOAD DATA, если Вы желаете, но значениями по умолчанию являются табуляция и перевод строки. Они достаточны, чтобы правильно прочитать файл pet.txt.

Когда Вы хотите добавить новые записи по одной, полезна инструкция INSERT. В самой простой ее форме Вы обеспечиваете значения для каждого столбца в том порядке, в котором столбцы были перечислены в инструкции CREATE TABLE. Предположим, что Diane получила нового хомяка Puffball. Вы можете добавить новую запись, используя инструкцию INSERT, подобно этому:

mysql> INSERT INTO pet
    -> VALUES ('Puffball','Diane','hamster','f','1999-03-30',NULL);

Обратите внимание, что строка и значения даты определены как цитируемые строки. Вы можете вставлять NULL непосредственно, чтобы представить отсутствие значения.

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

2.3.4 Получение информации из таблицы

Инструкция SELECT используется, чтобы получить информацию из таблицы. Общая форма инструкции:

SELECT what_to_select FROM which_table WHERE conditions_to_satisfy

what_to_select указывает то, что Вы хотите увидеть. Это может быть список столбцов или *, чтобы указать все столбцы. which_table указывает таблицу, из которой Вы хотите получить данные. Предложение WHERE факультативно. Если оно представлено, conditions_to_satisfy определяет условия, которым должны удовлетворять искомые строки.

2.3.4.1 Выбор всех данных

Самая простая форма SELECT получает все из таблицы:

mysql> SELECT * FROM pet;
+----------+--------+---------+------+------------+------------+
| name     | owner  | species | sex  | birth      | death      |
+----------+--------+---------+------+------------+------------+
| Fluffy   | Harold | cat     | f    | 1993-02-04 | NULL       |
| Claws    | Gwen   | cat     | m    | 1994-03-17 | NULL       |
| Buffy    | Harold | dog     | f    | 1989-05-13 | NULL       |
| Fang     | Benny  | dog     | m    | 1990-08-27 | NULL       |
| Bowser   | Diane  | dog     | m    | 1998-08-31 | 1995-07-29 |
| Chirpy   | Gwen   | bird    | f    | 1998-09-11 | NULL       |
| Whistler | Gwen   | bird    | NULL | 1997-12-09 | NULL       |
| Slim     | Benny  | snake   | m    | 1996-04-29 | NULL       |
| Puffball | Diane  | hamster | f    | 1999-03-30 | NULL       |
+----------+--------+---------+------+------------+------------+

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

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

2.3.4.2 Выбор конкретных строк

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

mysql> SELECT * FROM pet WHERE name = "Bowser";
+--------+-------+---------+------+------------+------------+
| name   | owner | species | sex  | birth      | death      |
+--------+-------+---------+------+------------+------------+
| Bowser | Diane | dog     | m    | 1989-08-31 | 1995-07-29 |
+--------+-------+---------+------+------------+------------+

Вывод подтверждает, что год теперь правильно зарегистрирован как 1989, а не 1998.

Сравнения строк обычно не чувствительны к регистру, так что Вы можете определять имя как "bowser", "BOWSER" или как хотите. Результат запроса будет тот же самый.

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

mysql> SELECT * FROM pet WHERE birth >= "1998-1-1";
+----------+-------+---------+-----+------------+-------+
| name     | owner | species | sex | birth      | death |
+----------+-------+---------+-----+------------+-------+
| Chirpy   | Gwen  | bird    | f   | 1998-09-11 | NULL  |
| Puffball | Diane | hamster | f   | 1999-03-30 | NULL  |
+----------+-------+---------+-----+------------+-------+

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

mysql> SELECT * FROM pet WHERE species="dog" AND sex="f";
+-------+--------+---------+-----+------------+-------+
| name  | owner  | species | sex | birth      | death |
+-------+--------+---------+-----+------------+-------+
| Buffy | Harold | dog     | f   | 1989-05-13 | NULL  |
+-------+--------+---------+-----+------------+-------+

Предшествующий запрос использует логический оператор AND. Имеется также оператор OR:

mysql> SELECT * FROM pet WHERE species="snake" OR species="bird";
+----------+-------+---------+------+------------+-------+
| name     | owner | species | sex  | birth      | death |
+----------+-------+---------+------+------------+-------+
| Chirpy   | Gwen  | bird    | f    | 1998-09-11 | NULL  |
| Whistler | Gwen  | bird    | NULL | 1997-12-09 | NULL  |
| Slim     | Benny | snake   | m    | 1996-04-29 | NULL  |
+----------+-------+---------+------+------------+-------+

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

mysql> SELECT * FROM pet WHERE (species = "cat" AND sex = "m")
    -> OR (species = "dog" AND sex = "f");
+-------+--------+---------+------+------------+-------+
| name  | owner  | species | sex  | birth      | death |
+-------+--------+---------+------+------------+-------+
| Claws | Gwen   | cat     | m    | 1994-03-17 | NULL  |
| Buffy | Harold | dog     | f    | 1989-05-13 | NULL  |
+-------+--------+---------+------+------------+-------+

2.3.4.3 Выбор произвольных столбцов

Если Вы не хотите видеть все строки из Вашей таблицы, только укажите столбцы, в которых вы заинтересованы, отделяя их запятыми. Например, если Вы хотите знать, когда Ваши животные были рождены, выберите столбцы name и birth:

mysql> SELECT name, birth FROM pet;
+----------+------------+
| name     | birth      |
+----------+------------+
| Fluffy   | 1993-02-04 |
| Claws    | 1994-03-17 |
| Buffy    | 1989-05-13 |
| Fang     | 1990-08-27 |
| Bowser   | 1989-08-31 |
| Chirpy   | 1998-09-11 |
| Whistler | 1997-12-09 |
| Slim     | 1996-04-29 |
| Puffball | 1999-03-30 |
+----------+------------+

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

mysql> SELECT owner FROM pet;
+--------+
| owner  |
+--------+
| Harold |
| Gwen   |
| Harold |
| Benny  |
| Diane  |
| Gwen   |
| Gwen   |
| Benny  |
| Diane  |
+--------+

Однако, обратите внимание, что запрос просто находит поле owner из каждой записи, и некоторые из них появляются больше, чем однажды. Чтобы минимизировать вывод, получите каждую уникальную запись вывода только однажды, добавляя ключевое слово DISTINCT:

mysql> SELECT DISTINCT owner FROM pet;
+--------+
| owner  |
+--------+
| Benny  |
| Diane  |
| Gwen   |
| Harold |
+--------+

Вы можете использовать предложение WHERE, чтобы объединить выбор строки с выбором столбца. Например, чтобы получить даты рождения только для кошек и собак, используйте запрос:

mysql> SELECT name, species, birth FROM pet
    -> WHERE species = "dog" OR species = "cat";
+--------+---------+------------+
| name   | species | birth      |
+--------+---------+------------+
| Fluffy | cat     | 1993-02-04 |
| Claws  | cat     | 1994-03-17 |
| Buffy  | dog     | 1989-05-13 |
| Fang   | dog     | 1990-08-27 |
| Bowser | dog     | 1989-08-31 |
+--------+---------+------------+

2.3.4.4 Сортировка строк

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

Отсортируем дни рождения нашей живности:

mysql> SELECT name, birth FROM pet ORDER BY birth;
+----------+------------+
| name     | birth      |
+----------+------------+
| Buffy    | 1989-05-13 |
| Bowser   | 1989-08-31 |
| Fang     | 1990-08-27 |
| Fluffy   | 1993-02-04 |
| Claws    | 1994-03-17 |
| Slim     | 1996-04-29 |
| Whistler | 1997-12-09 |
| Chirpy   | 1998-09-11 |
| Puffball | 1999-03-30 |
+----------+------------+

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

mysql> SELECT name, birth FROM pet ORDER BY birth DESC;
+----------+------------+
| name     | birth      |
+----------+------------+
| Puffball | 1999-03-30 |
| Chirpy   | 1998-09-11 |
| Whistler | 1997-12-09 |
| Slim     | 1996-04-29 |
| Claws    | 1994-03-17 |
| Fluffy   | 1993-02-04 |
| Fang     | 1990-08-27 |
| Bowser   | 1989-08-31 |
| Buffy    | 1989-05-13 |
+----------+------------+

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

mysql> SELECT name, species, birth FROM pet ORDER BY species, birth DESC;
+----------+---------+------------+
| name     | species | birth      |
+----------+---------+------------+
| Chirpy   | bird    | 1998-09-11 |
| Whistler | bird    | 1997-12-09 |
| Claws    | cat     | 1994-03-17 |
| Fluffy   | cat     | 1993-02-04 |
| Fang     | dog     | 1990-08-27 |
| Bowser   | dog     | 1989-08-31 |
| Buffy    | dog     | 1989-05-13 |
| Puffball | hamster | 1999-03-30 |
| Slim     | snake   | 1996-04-29 |
+----------+---------+------------+

Обратите внимание, что ключевое слово DESC применяется только к имени столбца непосредственно перед ним (birth), а значения species сортируются в порядке возрастания.

2.3.4.5 Вычисление дат

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

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

mysql> SELECT name, birth, CURRENT_DATE,
    -> (YEAR(CURRENT_DATE)-YEAR(birth))
    -> -(RIGHT(CURRENT_DATE,5)<RIGHT(birth,5)) AS age FROM pet;
+----------+------------+--------------+------+
| name     | birth      | CURRENT_DATE | age  |
+----------+------------+--------------+------+
| Fluffy   | 1993-02-04 | 2001-08-29   |    8 |
| Claws    | 1994-03-17 | 2001-08-29   |    7 |
| Buffy    | 1989-05-13 | 2001-08-29   |   12 |
| Fang     | 1990-08-27 | 2001-08-29   |   11 |
| Bowser   | 1989-08-31 | 2001-08-29   |   11 |
| Chirpy   | 1998-09-11 | 2001-08-29   |    2 |
| Whistler | 1997-12-09 | 2001-08-29   |    3 |
| Slim     | 1996-04-29 | 2001-08-29   |    5 |
| Puffball | 1999-03-30 | 2001-08-29   |    2 |
+----------+------------+--------------+------+

Здесь YEAR() выделяет часть года даты, RIGHT() убирает пять символов, которые представляют часть MM-DD даты. Часть выражения, которое сравнивает значения MM-DD, выставляется в 1 или 0, что корректирует различие лет, если CURRENT_DATE стоит ранее в году, чем рождение (birth). Полное выражение несколько перегружено, так что псевдоним (age) используется, чтобы заставить столбец вывода обрести более читабельный заголовок.

Запрос работает, но результат мог бы быть просмотрен более легко, если строки были выведены в некотором порядке. Это может быть выполнено, добавляя предложение ORDER BY name, чтобы сортировать вывод:

mysql> SELECT name, birth, CURRENT_DATE,
    -> (YEAR(CURRENT_DATE)-YEAR(birth))
    -> -(RIGHT(CURRENT_DATE,5)<RIGHT(birth,5))
    -> AS age FROM pet ORDER BY name;
+----------+------------+--------------+------+
| name     | birth      | CURRENT_DATE | age  |
+----------+------------+--------------+------+
| Bowser   | 1989-08-31 | 2001-08-29   |   11 |
| Buffy    | 1989-05-13 | 2001-08-29   |   12 |
| Chirpy   | 1998-09-11 | 2001-08-29   |    2 |
| Claws    | 1994-03-17 | 2001-08-29   |    7 |
| Fang     | 1990-08-27 | 2001-08-29   |   11 |
| Fluffy   | 1993-02-04 | 2001-08-29   |    8 |
| Puffball | 1999-03-30 | 2001-08-29   |    2 |
| Slim     | 1996-04-29 | 2001-08-29   |    5 |
| Whistler | 1997-12-09 | 2001-08-29   |    3 |
+----------+------------+--------------+------+

Чтобы отсортировать вывод по возрасту (age), а не по имени (name), примените другое предложение ORDER BY:

mysql> SELECT name, birth, CURRENT_DATE,
    -> (YEAR(CURRENT_DATE)-YEAR(birth))
    -> -(RIGHT(CURRENT_DATE,5)<RIGHT(birth,5))
    -> AS age FROM pet ORDER BY age;
+----------+------------+--------------+------+
| name     | birth      | CURRENT_DATE | age  |
+----------+------------+--------------+------+
| Chirpy   | 1998-09-11 | 2001-08-29   |    2 |
| Puffball | 1999-03-30 | 2001-08-29   |    2 |
| Whistler | 1997-12-09 | 2001-08-29   |    3 |
| Slim     | 1996-04-29 | 2001-08-29   |    5 |
| Claws    | 1994-03-17 | 2001-08-29   |    7 |
| Fluffy   | 1993-02-04 | 2001-08-29   |    8 |
| Fang     | 1990-08-27 | 2001-08-29   |   11 |
| Bowser   | 1989-08-31 | 2001-08-29   |   11 |
| Buffy    | 1989-05-13 | 2001-08-29   |   12 |
+----------+------------+--------------+------+

Подобный запрос может использоваться, чтобы определить возраст для животных, которые умерли. Вы определяете такие случаи, проверяя, является или нет значение death равным NULL. Затем, для тех, которые не-NULL, вычислите разницу между death и birth:

mysql> SELECT name, birth, death,
    -> (YEAR(death)-YEAR(birth)) - (RIGHT(death,5)<RIGHT(birth,5))
    -> AS age
    -> FROM pet WHERE death IS NOT NULL ORDER BY age;
+--------+------------+------------+------+
| name   | birth      | death      | age  |
+--------+------------+------------+------+
| Bowser | 1989-08-31 | 1995-07-29 |    5 |
+--------+------------+------------+------+

Запрос использует death IS NOT NULL вместо death != NULL потому, что NULL специальное значение. Подробности в разделе "2.3.4.6 Работа со значениями NULL".

Что делать, если Вы хотите знать, какие животные имеют дни рождения в следующем месяце? Для этого типа вычисления, год и день не годятся. Вы просто хотите извлекать часть месяца из столбца birth. MySQL обеспечивает несколько функций извлечения частей даты, типа YEAR(), MONTH() и DAYOFMONTH(). Чтобы увидеть, как это работает, выполните простой запрос, который отображает значения birth и MONTH(birth):

mysql> SELECT name, birth, MONTH(birth) FROM pet;
+----------+------------+--------------+
| name     | birth      | MONTH(birth) |
+----------+------------+--------------+
| Fluffy   | 1993-02-04 |            2 |
| Claws    | 1994-03-17 |            3 |
| Buffy    | 1989-05-13 |            5 |
| Fang     | 1990-08-27 |            8 |
| Bowser   | 1989-08-31 |            8 |
| Chirpy   | 1998-09-11 |            9 |
| Whistler | 1997-12-09 |           12 |
| Slim     | 1996-04-29 |            4 |
| Puffball | 1999-03-30 |            3 |
+----------+------------+--------------+

Поиск животных с днями рождения в наступающем месяце прост. Предположим, что текущий месяц апрель. Значение month равно 4, и Вы ищете животных, рожденных в мае (month=5):

mysql> SELECT name, birth FROM pet WHERE MONTH(birth) = 5;
+-------+------------+
| name  | birth      |
+-------+------------+
| Buffy | 1989-05-13 |
+-------+------------+

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

Вы можете даже написать запрос так, чтобы это работало независимо от того, каков текущий месяц. DATE_ADD() позволяет Вам добавлять интервал времени к заданной дате. Если Вы добавляете месяц к значению NOW(), а затем извлекаете часть месяца с помощью MONTH(), результатом как раз и будет тот месяц, в котором надо искать дни рождения:

mysql> SELECT name, birth FROM pet
    -> WHERE MONTH(birth) = MONTH(DATE_ADD(NOW(), INTERVAL 1 MONTH));

2.3.4.6 Работа со значениями NULL

Значение NULL может удивлять, пока Вы не привыкнете к нему. Концептуально, NULL означает отсутствие средств для оценки или неизвестное значение, и это обрабатывается несколько по-другому, чем другие значения. Для проверки на NULL Вы не можете использовать арифметические операторы, например, =, < или !=. Чтобы показать это, попробуйте следующий запрос:

mysql> SELECT 1 = NULL, 1 != NULL, 1 < NULL, 1 > NULL;
+----------+-----------+----------+----------+
| 1 = NULL | 1 != NULL | 1 < NULL | 1 > NULL |
+----------+-----------+----------+----------+
|     NULL |      NULL |     NULL |     NULL |
+----------+-----------+----------+----------+

Очевидно, что никакого толка от таких сравнений нет и не будет. Используйте взамен операторы IS NULL и IS NOT NULL:

mysql> SELECT 1 IS NULL, 1 IS NOT NULL;
+-----------+---------------+
| 1 IS NULL | 1 IS NOT NULL |
+-----------+---------------+
|         0 |             1 |
+-----------+---------------+

В MySQL 0 или NULL означает false в логических операциях, а все остальное значит true. Заданное по умолчанию значение истины в булевых операциях равно 1.

Эта специальная обработка NULL является причиной того, почему в предыдущем разделе было необходимо определить, которые животные умерли, используя именно death IS NOT NULL вместо death!=NULL.

2.3.4.7 Сравнение по шаблону

MySQL обеспечивает стандартные шаблоны SQL, основанные на расширенных регулярных выражениях, подобных используемым Unix-приложениями, вроде vi, grep и sed.

SQL-шаблоны позволяют Вам использовать _, чтобы соответствовать любому одиночному символу и %, чтобы соответствовать произвольному числу символов (включая нулевое количество). В MySQL SQL-шаблоны по умолчанию не чувствительны к регистру. Некоторые примеры показываются ниже. Обратите внимание, что Вы не используете = или !=, когда Вы применяете образцы SQL; используйте операторы сравнения LIKE или NOT LIKE.

Чтобы найти имена, начинающиеся с `b', введите:

mysql> SELECT * FROM pet WHERE name LIKE "b%";
+--------+--------+---------+------+------------+------------+
| name   | owner  | species | sex  | birth      | death      |
+--------+--------+---------+------+------------+------------+
| Buffy  | Harold | dog     | f    | 1989-05-13 | NULL       |
| Bowser | Diane  | dog     | m    | 1989-08-31 | 1995-07-29 |
+--------+--------+---------+------+------------+------------+

Чтобы найти имена, заканчивающиеся на `fy', введите:

mysql> SELECT * FROM pet WHERE name LIKE "%fy";
+--------+--------+---------+------+------------+-------+
| name   | owner  | species | sex  | birth      | death |
+--------+--------+---------+------+------------+-------+
| Fluffy | Harold | cat     | f    | 1993-02-04 | NULL  |
| Buffy  | Harold | dog     | f    | 1989-05-13 | NULL  |
+--------+--------+---------+------+------------+-------+

Чтобы найти имена, содержащие `w', введите:

mysql> SELECT * FROM pet WHERE name LIKE "%w%";
+----------+-------+---------+------+------------+------------+
| name     | owner | species | sex  | birth      | death      |
+----------+-------+---------+------+------------+------------+
| Claws    | Gwen  | cat     | m    | 1994-03-17 | NULL       |
| Bowser   | Diane | dog     | m    | 1989-08-31 | 1995-07-29 |
| Whistler | Gwen  | bird    | NULL | 1997-12-09 | NULL       |
+----------+-------+---------+------+------------+------------+

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

mysql> SELECT * FROM pet WHERE name LIKE "_____";
+-------+--------+---------+------+------------+-------+
| name  | owner  | species | sex  | birth      | death |
+-------+--------+---------+------+------------+-------+
| Claws | Gwen   | cat     | m    | 1994-03-17 | NULL  |
| Buffy | Harold | dog     | f    | 1989-05-13 | NULL  |
+-------+--------+---------+------+------------+-------+

Другой тип образца, поддерживаемый MySQL, это расширенные регулярные выражения. Когда Вы проверяете соответствия для этого типа образца, используйте операторы REGEXP и NOT REGEXP (или RLIKE и NOT RLIKE, которые являются синонимами).

Некоторые характеристики расширенных регулярных выражений:

  • Точка (.) соответствует любому одиночному символу.
  • Символьный класс [...] соответствует любому символу внутри скобок. Например, [abc] соответствует a, b или c. Чтобы задать диапазон символов, используйте черточку. Например, [a-z] соответствует любому латинскому символу нижнего регистра в то время, как [0-9] определяет любую цифру.
  • Звездочка * соответствует нолю или большему количеству образцов предшествующих ей. Например, x* соответствует любому числу символов x, [0-9]* соответствует любому числу цифр, а .* соответствует любому количеству чего-нибудь.
  • Регулярные выражения чувствительны к регистру, но Вы можете использовать символьный класс, чтобы соответствовать обоим регистрам сразу. Например, [aA] соответствует символу a нижнего или верхнего регистра, а [a-zA-Z] соответствует любому символу.
  • Образец считается соответствующим, если соответствие происходит где-нибудь в проверяемом значении. SQL учитывает соответствие только, если оно удовлетворяет всему значению.
  • Чтобы закреплять образец так, чтобы он соответствовал началу или концу проверяемого значения, используется символ циркумфлекса (^) в начале или доллара ($) в конце образца.

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

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

mysql> SELECT * FROM pet WHERE name REGEXP "^b";
+--------+--------+---------+-----+------------+------------+
| name   | owner  | species | sex | birth      | death      |
+--------+--------+---------+-----+------------+------------+
| Buffy  | Harold | dog     | f   | 1989-05-13 | NULL       |
| Bowser | Diane  | dog     | m   | 1989-08-31 | 1995-07-29 |
+--------+--------+---------+-----+------------+------------+

До MySQL Version 3.23.4 REGEXP чувствителен к регистру, и предыдущий запрос не возвратит никаких строк. Чтобы соответствовать нижнему или верхнему регистру b, используйте этот запрос взамен:

mysql> SELECT * FROM pet WHERE name REGEXP "^[bB]";

В MySQL 3.23.4, чтобы вынудить сравнение REGEXP быть чувствительным к регистру, используют ключевое слово BINARY, чтобы сделать одну из строк двоичной. Этот запрос будет соответствовать только нижнему регистру b в начале имени:

mysql> SELECT * FROM pet WHERE name REGEXP BINARY "^b";

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

mysql> SELECT * FROM pet WHERE name REGEXP "fy$";
+--------+--------+---------+------+------------+-------+
| name   | owner  | species | sex  | birth      | death |
+--------+--------+---------+------+------------+-------+
| Fluffy | Harold | cat     | f    | 1993-02-04 | NULL  |
| Buffy  | Harold | dog     | f    | 1989-05-13 | NULL  |
+--------+--------+---------+------+------------+-------+

Чтобы находить имена, содержащие `w', неважно в каком регистре, используйте этот запрос:

mysql> SELECT * FROM pet WHERE name REGEXP "w";
+----------+-------+---------+------+------------+------------+
| name     | owner | species | sex  | birth      | death      |
+----------+-------+---------+------+------------+------------+
| Claws    | Gwen  | cat     | m    | 1994-03-17 | NULL       |
| Bowser   | Diane | dog     | m    | 1989-08-31 | 1995-07-29 |
| Whistler | Gwen  | bird    | NULL | 1997-12-09 | NULL       |
+----------+-------+---------+------+------------+------------+

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

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

mysql> SELECT * FROM pet WHERE name REGEXP "^.....$";
+-------+--------+---------+------+------------+-------+
| name  | owner  | species | sex  | birth      | death |
+-------+--------+---------+------+------------+-------+
| Claws | Gwen   | cat     | m    | 1994-03-17 | NULL  |
| Buffy | Harold | dog     | f    | 1989-05-13 | NULL  |
+-------+--------+---------+------+------------+-------+

Вы могли бы также переписать предыдущий запрос, используя {n} в операторе repeat-n-times:

mysql> SELECT * FROM pet WHERE name REGEXP "^.{5}$";
+-------+--------+---------+------+------------+-------+
| name  | owner  | species | sex  | birth      | death |
+-------+--------+---------+------+------------+-------+
| Claws | Gwen   | cat     | m    | 1994-03-17 | NULL  |
| Buffy | Harold | dog     | f    | 1989-05-13 | NULL  |
+-------+--------+---------+------+------------+-------+

2.3.4.8 Подсчет строк

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

Подсчет общего количества животных, которых Вы имеете, аналогичен вопросу о том, сколько строк находятся в таблице pet? Дело в том, что имеется одна запись на домашнее животное. Функция COUNT() считает число не-NULL результатов, так что запрос для подсчета животных выглядит следующим образом:

mysql> SELECT COUNT(*) FROM pet;
+----------+
| COUNT(*) |
+----------+
|        9 |
+----------+

Ранее Вы нашли имена людей, которые имели домашние животных. Вы можете использовать COUNT(), если хотите выяснить, сколько домашних животных имеет каждый владелец:

mysql> SELECT owner, COUNT(*) FROM pet GROUP BY owner;
+--------+----------+
| owner  | COUNT(*) |
+--------+----------+
| Benny  |        2 |
| Diane  |        2 |
| Gwen   |        3 |
| Harold |        2 |
+--------+----------+

Обратите внимание на использование ключевого слова GROUP BY, чтобы сгруппировать вместе все записи для каждого владельца (owner). Без него все, что Вы получите, это сообщение об ошибках:

mysql> SELECT owner, COUNT(owner) FROM pet;
ERROR 1140 at line 1: Mixing of GROUP columns (MIN(),MAX(),COUNT()...)
with no GROUP columns is illegal if there is no GROUP BY clause

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

Число животных на разновидность:

mysql> SELECT species, COUNT(*) FROM pet GROUP BY species;
+---------+----------+
| species | COUNT(*) |
+---------+----------+
| bird    |        2 |
| cat     |        2 |
| dog     |        3 |
| hamster |        1 |
| snake   |        1 |
+---------+----------+

Число животных на пол:

mysql> SELECT sex, COUNT(*) FROM pet GROUP BY sex;
+------+----------+
| sex  | COUNT(*) |
+------+----------+
| NULL |        1 |
| f    |        4 |
| m    |        4 |
+------+----------+

В этом выводе NULL указывает неизвестный пол.

Число животных на комбинацию разновидности и пола:

mysql> SELECT species, sex, COUNT(*) FROM pet GROUP BY species, sex;
+---------+------+----------+
| species | sex  | COUNT(*) |
+---------+------+----------+
| bird    | NULL |        1 |
| bird    | f    |        1 |
| cat     | f    |        1 |
| cat     | m    |        1 |
| dog     | f    |        1 |
| dog     | m    |        2 |
| hamster | f    |        1 |
| snake   | m    |        1 |
+---------+------+----------+

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

mysql> SELECT species, sex, COUNT(*) FROM pet
    -> WHERE species = "dog" OR species = "cat" GROUP BY species, sex;
+---------+------+----------+
| species | sex  | COUNT(*) |
+---------+------+----------+
| cat     | f    |        1 |
| cat     | m    |        1 |
| dog     | f    |        1 |
| dog     | m    |        2 |
+---------+------+----------+

Если Вы хотите получить число животных каждого пола (только для животных, пол которых известен):

mysql> SELECT species, sex, COUNT(*) FROM pet
    -> WHERE sex IS NOT NULL GROUP BY species, sex;
+---------+------+----------+
| species | sex  | COUNT(*) |
+---------+------+----------+
| bird    | f    |        1 |
| cat     | f    |        1 |
| cat     | m    |        1 |
| dog     | f    |        1 |
| dog     | m    |        2 |
| hamster | f    |        1 |
| snake   | m    |        1 |
+---------+------+----------+

2.3.4.9 Использование нескольких таблиц в одном запросе

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

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

Согласно этим данным инструкция CREATE TABLE для таблицы событий (event) могла бы выглядеть следующим образом:

mysql> CREATE TABLE event (name VARCHAR(20), date DATE,
    -> type VARCHAR(15), remark VARCHAR(255));

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

Fluffy | 1995-05-15 | Потомство | 4 котенка, 3 female, 1 male
Buffy | 1993-06-23 | Потомство | 5 щенков, 2 female, 3 male
Buffy | 1994-06-19 | Потомство | 3 щенка, 3 female
Chirpy | 1999-03-21 | Ветеринар | Необходимо выпрямление клюва
Slim | 1997-08-03 | Ветеринар | Сломано ребро
Bowser | 1991-10-12 | Конура
Fang | 1991-10-12 | Конура
Fang | 1998-08-28 | День рождения | Подарок: новая жевательная игрушка
Claws | 1998-03-17 | День рождения | Подарок: ошейник от блох
Whistler | 1998-12-09 | День рождения | Первый день рождения

Загрузите записи так:

mysql> LOAD DATA LOCAL INFILE "event.txt" INTO TABLE event;

Учитывая то, чему Вы научились (я очень надеюсь, что и правда чему-то научились) на запросах к таблице pet, Вы должны быть способны выполнить поиски на записях в таблице event, принципы те же самые. Но что делать, когда таблица event отдельно недостаточна, чтобы ответить на вопросы, которые Вы задаете?

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

mysql> SELECT pet.name, (TO_DAYS(date)-TO_DAYS(birth))/365 AS age,
    -> remark FROM pet, event WHERE pet.name=event.name
    -> AND type="litter";
+--------+------+-----------------------------+
| name   | age  | remark                      |
+--------+------+-----------------------------+
| Fluffy | 2.27 | 4 kittens, 3 female, 1 male |
| Buffy  | 4.12 | 5 puppies, 2 female, 3 male |
| Buffy  | 5.10 | 3 puppies, 3 female         |
+--------+------+-----------------------------+

Итак, что тут происходит?

  • Предложение FROM вносит в список две таблицы потому, что запрос должен получить информацию из обеих таблиц.
  • При объединении (joining) информации из многих таблиц, Вы должны определить, как записи в одной таблице могут быть согласованы с записями в другой. Это просто потому, что они обе имеют столбец name. Запрос использует предложение WHERE, чтобы заставить совпасть записи в двух таблицах, основываясь на значениях name.
  • Поскольку столбец name есть в обеих таблицах, Вы должны указать, относительно которой таблицы Вы его обозначаете. Это выполнено добавлением имени таблицы к имени столбца.

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

mysql> SELECT p1.name, p1.sex, p2.name, p2.sex, p1.species
    -> FROM pet AS p1, pet AS p2
    -> WHERE p1.species=p2.species AND p1.sex="f" AND p2.sex="m";
+--------+------+--------+------+---------+
| name   | sex  | name   | sex  | species |
+--------+------+--------+------+---------+
| Fluffy | f    | Claws  | m    | cat     |
| Buffy  | f    | Fang   | m    | dog     |
| Buffy  | f    | Bowser | m    | dog     |
+--------+------+--------+------+---------+

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

2.4 Получение информации о базах данных и таблицах

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

Вы уже видели вызов SHOW DATABASES, который вносит в список базы данных, управляемые сервером. Чтобы выяснять, которая база данных в настоящее время выбрана, используйте функцию DATABASE():

mysql> SELECT DATABASE();
+------------+
| DATABASE() |
+------------+
| menagerie  |
+------------+

Если Вы не выбрали базу данных, результат пуст.

Чтобы выяснять какие таблицы хранит текущая база данных (например, когда Вы не уверены относительно имени таблицы), используйте эту команду:

mysql> SHOW TABLES;
+---------------------+
| Tables in menagerie |
+---------------------+
| event               |
| pet                 |
+---------------------+

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

mysql> DESCRIBE pet;
+---------+-------------+------+-----+---------+-------+
| Field   | Type        | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| name    | varchar(20) | YES  |     | NULL    |       |
| owner   | varchar(20) | YES  |     | NULL    |       |
| species | varchar(20) | YES  |     | NULL    |       |
| sex     | char(1)     | YES  |     | NULL    |       |
| birth   | date        | YES  |     | NULL    |       |
| death   | date        | YES  |     | NULL    |       |
+---------+-------------+------+-----+---------+-------+

Field указывает имя столбца, Type тип данных для столбца, Null указывает, может или нет столбец содержать значения NULL, Key указывает, индексирован или нет столбец, а Default определяет значение столбца по умолчанию.

Если Вы имеете индексы на таблице, SHOW INDEX FROM tbl_name производит информацию относительно их.

2.5 Примеры общих запросов

Имеются примеры того, как решить некоторые общие проблемы с MySQL.

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

Запустите инструмент командной строки mysql и выберите базу данных:

mysql your-database-name

В большинстве инсталляций MySQL Вы можете использовать имя базы данных test.

Вы можете создать таблицу для примера так:

CREATE TABLE shop (article INT(4) UNSIGNED ZEROFILL DEFAULT '0000'
             NOT NULL, dealer CHAR(20) DEFAULT '' NOT NULL,
             price DOUBLE(16,2) DEFAULT '0.00' NOT NULL,
             PRIMARY KEY(article, dealer));
INSERT INTO shop VALUES
   (1,'A',3.45),(1,'B',3.99),(2,'A',10.99),
   (3,'B',1.45),(3,'C',1.69),(3,'D',1.25),(4,'D',19.95);

Посмотрим данные примера:

mysql> SELECT * FROM shop;
+---------+--------+-------+
| article | dealer | price |
+---------+--------+-------+
|    0001 | A      |  3.45 |
|    0001 | B      |  3.99 |
|    0002 | A      | 10.99 |
|    0003 | B      |  1.45 |
|    0003 | C      |  1.69 |
|    0003 | D      |  1.25 |
|    0004 | D      | 19.95 |
+---------+--------+-------+

2.5.1 Максимальное значение для столбца

Что является самым большим значением для элемента?

SELECT MAX(article) AS article FROM shop
+---------+
| article |
+---------+
|       4 |
+---------+

2.5.2 В какой строке хранится максимум некоего столбца?

Допустим, надо найти код, торговца и цену наиболее дорогого изделия.

В ANSI SQL это легко может быть выполнен подзапросом:

SELECT article, dealer, price FROM shop
       WHERE price=(SELECT MAX(price) FROM shop)

В MySQL (который еще не имеет поддержки вложенных запросов) это делается за два шага:

  1. Получите максимальное ценовое значение из таблицы с помощью SELECT.
  2. Используя это значение, надо создать фактический запрос:
    SELECT article, dealer, price FROM shop WHERE price=19.95

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

SELECT article, dealer, price FROM shop ORDER BY price DESC LIMIT 1

ОБРАТИТЕ ВНИМАНИЕ: Если имеется несколько изделий с одинаковой ценой (например, каждое по 19.95), то LIMIT показывает только одно из них.

2.5.3 Максимум столбца в группе

Что является самой высокой ценой на изделие?

SELECT article, MAX(price) AS price FROM shop GROUP BY article
+---------+-------+
| article | price |
+---------+-------+
|    0001 |  3.99 |
|    0002 | 10.99 |
|    0003 |  1.69 |
|    0004 | 19.95 |
+---------+-------+

2.5.4 В какой строке максимум по группе

Для каждого изделия, найдите торгового агента с наиболее высокой ценой.

В ANSI SQL я сделал бы это подзапросом:

SELECT article, dealer, price FROM shop s1
       WHERE price=(SELECT MAX(s2.price) FROM shop s2
             WHERE s1.article = s2.article);

В MySQL проще всего добиться такого эффекта так:

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

Это может быть легко выполнено через временную таблицу:

CREATE TEMPORARY TABLE tmp (article INT(4) UNSIGNED ZEROFILL
       DEFAULT '0000' NOT NULL, price DOUBLE(16,2) DEFAULT '0.00'
       NOT NULL);
LOCK TABLES shop read;
INSERT INTO tmp SELECT article, MAX(price) FROM shop GROUP BY article;
SELECT shop.article, dealer, shop.price FROM shop, tmp
       WHERE shop.article=tmp.article AND shop.price=tmp.price;
UNLOCK TABLES;
DROP TABLE tmp;

Если Вы не используете таблицу TEMPORARY, Вы должны также блокировать таблицу tmp.

Можно это сделать одиночным запросом?

Да, но только используя совершенно неэффективный прием MAX-CONCAT trick:

SELECT article, SUBSTRING(MAX(CONCAT(LPAD(price,6,'0'),dealer)), 7)
       AS dealer, 0.00+LEFT(MAX(CONCAT(LPAD(price,6,'0'),dealer)), 6)
       AS price FROM shop GROUP BY article;
+---------+--------+-------+
| article | dealer | price |
+---------+--------+-------+
|    0001 | B      |  3.99 |
|    0002 | A      | 10.99 |
|    0003 | C      |  1.69 |
|    0004 | D      | 19.95 |
+---------+--------+-------+

2.5.5 Применение переменных пользователя

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

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

select @min_price:=min(price),@max_price:=max(price) from shop;
select * from shop where price=@min_price or price=@max_price;
+---------+--------+-------+
| article | dealer | price |
+---------+--------+-------+
|    0003 | D      |  1.25 |
|    0004 | D      | 19.95 |
+---------+--------+-------+

2.5.6 Использование внешних ключей

Вы не нуждаетесь во внешних ключах, чтобы соединить 2 таблицы.

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

CREATE TABLE persons (id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
             name CHAR(60) NOT NULL, PRIMARY KEY (id));
CREATE TABLE shirts (id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
             style ENUM('t-shirt', 'polo', 'dress') NOT NULL,
             color ENUM('red', 'blue', 'orange', 'white', 'black')
             NOT NULL, owner SMALLINT UNSIGNED NOT NULL REFERENCES persons,
             PRIMARY KEY (id));
INSERT INTO persons VALUES (NULL, 'Antonio Paz');
INSERT INTO shirts VALUES (NULL, 'polo', 'blue', LAST_INSERT_ID()),
   (NULL, 'dress', 'white', LAST_INSERT_ID()),
   (NULL, 't-shirt', 'blue', LAST_INSERT_ID());
INSERT INTO persons VALUES (NULL, 'Lilliana Angelovska');
INSERT INTO shirts VALUES (NULL, 'dress', 'orange', LAST_INSERT_ID()),
   (NULL, 'polo', 'red', LAST_INSERT_ID()),
   (NULL, 'dress', 'blue', LAST_INSERT_ID()),
   (NULL, 't-shirt', 'white', LAST_INSERT_ID());
SELECT * FROM persons;
+----+---------------------+
| id | name                |
+----+---------------------+
|  1 | Antonio Paz         |
|  2 | Lilliana Angelovska |
+----+---------------------+
SELECT * FROM shirts;
+----+---------+--------+-------+
| id | style   | color  | owner |
+----+---------+--------+-------+
|  1 | polo    | blue   |     1 |
|  2 | dress   | white  |     1 |
|  3 | t-shirt | blue   |     1 |
|  4 | dress   | orange |     2 |
|  5 | polo    | red    |     2 |
|  6 | dress   | blue   |     2 |
|  7 | t-shirt | white  |     2 |
+----+---------+--------+-------+
SELECT s.* FROM persons p, shirts s WHERE p.name LIKE 'Lilliana%'
       AND s.owner = p.id AND s.color <> 'white';
+----+-------+--------+-------+
| id | style | color  | owner |
+----+-------+--------+-------+
|  4 | dress | orange |     2 |
|  5 | polo  | red    |     2 |
|  6 | dress | blue   |     2 |
+----+-------+--------+-------+

2.5.7 Поиск на двух ключах

MySQL не оптимизирует запрос, когда Вы ищете на двух различных ключах, объединенных с помощью OR. Поиск на одном ключе с OR оптимизирован хорошо.

SELECT field1_index, field2_index FROM test_table WHERE field1_index = '1'
       OR field2_index = '1'

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

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

CREATE TEMPORARY TABLE tmp
SELECT field1_index, field2_index FROM test_table
       WHERE field1_index = '1';
INSERT INTO tmp
SELECT field1_index, field2_index FROM test_table
       WHERE field2_index = '1';
SELECT * from tmp;
DROP TABLE tmp;

Вышеупомянутый способ выполнить этот запрос в действительности вызывает UNION для двух запросов.

2.5.8 Вычисление посещений за день

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

CREATE TABLE t1 (year YEAR(4), month INT(2) UNSIGNED ZEROFILL,
       day INT(2) UNSIGNED ZEROFILL);
INSERT INTO t1 VALUES(2000,1,1),(2000,1,20),(2000,1,30),
       (2000,2,2),(2000,2,23),(2000,2,23);
SELECT year,month,BIT_COUNT(BIT_OR(1<<day)) AS days
       FROM t1 GROUP BY year,month;
+------+-------+------+
| year | month | days |
+------+-------+------+
| 2000 |    01 |    3 |
| 2000 |    02 |    2 |
+------+-------+------+

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

2.6 Использование mysql в пакетном режиме

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

shell> mysql < batch-file

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

shell> mysql -h host -u user -p < batch-file
Enter password: ********

Когда Вы используете mysql этим способом, Вы создаете файл скрипта, а затем выполняете скрипт.

Почему использование скриптов удобно? Имеется несколько причин:

  • Если Вы выполняете запрос неоднократно (скажем, каждый день или каждую неделю), скрипт позволяет Вам избежать ввода запроса каждый раз, когда Вы его выполняете.
  • Вы можете генерировать новые запросы из похожих существующих, копируя и редактируя файлы скриптов.
  • Пакетный режим может также быть полезен в то время, когда Вы разрабатываете запрос, особенно для команд с многими строками или многооператорных последовательностей команд. Если Вы сделаете ошибку, Вы не должны повторно вводить все. Только отредактируйте скрипт, чтобы исправить ошибку, затем сообщите, чтобы mysql выполнил его снова.
  • Если Вы имеете запрос, который производит много вывода, Вы можете выполнять вывод через pager вместо того, чтобы мучаться с экраном:
    shell> mysql < batch-file|more
  • Вы можете захватывать вывод в файл для дальнейшей обработки:
    shell> mysql < batch-file > mysql.out
  • Вы можете передавать Ваш скрипт другим людям, так что они смогут выполнять команды так же.
  • Некоторые ситуации не учитывают интерактивное использование, например, когда Вы выполняете запрос из планировщика cron. В этом случае Вы должны использовать пакетный режим.

Заданный по умолчанию выходной формат несколько иной (более краткий), когда Вы выполняете mysql в пакетном режиме. Например, вывод SELECT DISTINCT species FROM pet напоминает этот образец, когда выполнен в интерактивном режиме:

+---------+
| species |
+---------+
| bird    |
| cat     |
| dog     |
| hamster |
| snake   |
+---------+

Но когда выполнен в пакетном режиме, он подобен этому:

species
bird
cat
dog
hamster
snake

Если Вы хотите получать интерактивный выходной формат в пакетном режиме, используйте mysql -t. Для добавления к выводу команд, которые были выполнены, используется mysql -vvv.

2.7 Запросы из двух проектов

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

http://www.imm.ki.se/TWIN/TWINUKW.HTM

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

Каждую ночь (исследования ведутся днем) все данные из интервью перемещаются в базу данных MySQL.

2.7.1 Поиск всех важных близнецов

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

select concat(p1.id, p1.tvab) + 0 as tvid,
       concat(p1.christian_name, " ", p1.surname) as Name,
       p1.postal_code as Code, p1.city as City, pg.abrev as Area,
       if(td.participation = "Aborted", "A", " ") as A,
       p1.dead as dead1, l.event as event1, td.suspect as tsuspect1,
       id.suspect as isuspect1, td.severe as tsevere1,
       id.severe as isevere1, p2.dead as dead2, l2.event as event2,
       h2.nurse as nurse2, h2.doctor as doctor2, td2.suspect as tsuspect2,
       id2.suspect as isuspect2, td2.severe as tsevere2,
       id2.severe as isevere2, l.finish_date from twin_project as tp
       left join twin_data as td on tp.id = td.id and tp.tvab = td.tvab
       left join informant_data as id on tp.id = id.id and tp.tvab=id.tvab
       left join harmony as h on tp.id = h.id and tp.tvab = h.tvab
       left join lentus as l on tp.id = l.id and tp.tvab = l.tvab
       left join twin_data as td2 on p2.id = td2.id and p2.tvab = td2.tvab
       left join informant_data as id2 on p2.id = id2.id and
       p2.tvab=id2.tvab left join harmony as h2 on p2.id = h2.id and
       p2.tvab = h2.tvab left join lentus as l2 on p2.id = l2.id and
       p2.tvab = l2.tvab, person_data as p1, person_data as p2,
       postal_groups as pg where p1.id = tp.id and p1.tvab = tp.tvab and
       p2.id = p1.id and p2.ptvab = p1.tvab and tp.survey_no = 5 and
       (p2.dead = 0 or p2.dead=9 or (p2.dead=1 and (p2.death_date=0 or
       (((to_days(p2.death_date)-to_days(p2.birthday))/365) >= 65))))
       and ((td.future_contact = 'Yes' and td.suspect = 2) or
       (td.future_contact = 'Yes' and td.suspect = 1 and id.suspect=1) or
       (ISNULL(td.suspect) and id.suspect=1 and id.future_contact='Yes') or
       (td.participation = 'Aborted' and id.suspect = 1 and
       id.future_contact = 'Yes') or (td.participation = 'Aborted' and
       ISNULL(id.suspect) and p2.dead = 0)) and l.event = 'Finished'
       and substring(p1.postal_code, 1, 2) = pg.code
       and (h.nurse is NULL or h.nurse=00 or h.doctor=00)
       and not (h.status = 'Refused' or h.status = 'Aborted'
       or h.status = 'Died' or h.status = 'Other') order by tvid;

Как Вам такой запрос? Даю некоторые объяснения:

concat(p1.id, p1.tvab) + 0 as tvid
Мы хотим сортировать на составном идентификаторе id и tvab в числовом порядке. Добавление 0 к результату заставляет MySQL обрабатывать его именно как число.
column id
Это идентифицирует пару близнецов. Это ключ во всех таблицах.
column tvab
Это идентифицирует близнецов в паре. Это имеет значение 1 или 2.
column ptvab
Это инверсия tvab. Когда tvab равно 1, ptvab принимает значение 2, и наоборот. Это существует, чтобы проще оптимизировать запрос.

Этот запрос показывает среди других вещей, как делать поиск на таблице из той же самой таблицы с объединением (p1 и p2). В примере это используется, чтобы проверить, умер ли партнер близнецов до 65 лет. Если так, строка не будет возвращена.

Все вышеприведенное существует во всех таблицах с информацией по близнецам. Мы имеем ключ на паре id,tvab (все таблицы) и другой паре id,ptvab (только в person_data), чтобы сделать запросы быстрее.

На нашей машине (200MHz UltraSPARC) этот запрос возвращает приблизительно 150-200 строк и требует времени меньше, чем одна секунда.

Текущее число записей в таблицах, используемых выше:
Таблица | Строк
person_data | 71074
lentus | 5291
twin_project | 5286
twin_data | 2012
informant_data | 663
harmony | 381
postal_groups | 100

2.7.2 Состояние пары

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

select t1.event, t2.event, count(*) from lentus as t1, lentus as t2,
       twin_project as tp where t1.id = tp.id and t1.tvab=tp.tvab
       and t1.id = t2.id and tp.survey_no = 5 and t1.tvab='1' and
       t2.tvab='2' group by t1.event, t2.event;


Структура языка

3 Структура языка

3.1 Литералы: как писать строки и числа

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

3.1.1 Строки

Строка представляет собой последовательность символов, окруженных одиночными кавычками (') или двойными кавычками ("). Допустима только одиночная кавычка, если Вы работаете в ANSI-режиме. Примеры:

'a string'
"another string"

Внутри строки некоторые последовательности имеют специальное значение. Каждая из этих последовательностей начинается с наклонной черты влево (\), известной как escape character. MySQL распознает следующие управляющие последовательности:

\0
Символ с кодом ASCII 0 (NUL).
\'
Символ одиночной кавычки (').
\"
Символ двойной кавычки (").
\b
Символ backspace.
\n
Символ newline.
\r
Символ возврата каретки.
\t
Символ табуляции.
\z
ASCII(26)=(Control-Z). Этот символ может быть закодирован, чтобы позволить Вам обойти проблему восприятия ASCII(26) как END-OF-FILE под Windows. ASCII(26) вызовет проблемы, если Вы попробуете использовать mysql database < filename.
\\
Символ backslash (\).
\%
Символ %. Это используется, чтобы искать литеральные образцы % в контекстах, где % иначе интерпретировался бы как групповой символ. Подробности в разделе "6.3.2.1 Функции сравнения строк".
\_
Символ _. Это используется, чтобы искать литеральные образцы _ в контекстах, где _ иначе интерпретировался бы как групповой символ. Подробности в разделе "6.3.2.1 Функции сравнения строк".

Обратите внимание, что, если Вы используете \% или \_ в некоторых контекстах, они возвратят строки \% и \_ вместо % и _.

Имеется несколько способов включить кавычки в строку:

  • ' внутри строки, цитируемой с ' может быть написано как ''.
  • `"' внутри строки, цитируемой с " может быть написано как "".
  • Вы можете предварить кавычку символом \.
  • ' внутри строки, цитируемой с " не требует специальной обработки или экранировки. Таким же образом, " внутри строки, цитируемой с ' этого тоже не требует.

Инструкции SELECT, приведенные ниже, показывают как работают цитирование и экранировка:

mysql> SELECT 'hello', '"hello"', '""hello""', 'hel''lo', '\'hello';
  +-------+---------+-----------+--------+--------+
  | hello | "hello" | ""hello"" | hel'lo | 'hello |
  +-------+---------+-----------+--------+--------+
mysql> SELECT "hello", "'hello'", "''hello''", "hel""lo", "\"hello";
  +-------+---------+-----------+--------+--------+
  | hello | 'hello' | ''hello'' | hel"lo | "hello |
  +-------+---------+-----------+--------+--------+
mysql> SELECT "This\nIs\nFour\nlines";
  +--------------------+
  | This
  Is
  Four
  lines |
  +--------------------+

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

NUL
ASCII 0. Вы должны представить это как \0.
\
ASCII 92, backslash. Представьте это как \\.
'
ASCII 39, одиночная кавычка. Представьте это как \'.
"
ASCII 34, двойная кавычка. Представьте это как \".

Если Вы пишете код на C, Вы можете использовать функцию C API mysql_escape_string() для инструкции INSERT. В языке Perl Вы можете использовать метод quote пакета DBI, чтобы преобразовать специальные символы в соответствующие управляющие последовательности.

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

3.1.2 Числа

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

Примеры имеющих силу целых чисел:

1221
0
-32

Примеры чисел с плавающей запятой:

294.42
-32032.6809e+10
148.00

Целое число может использоваться в контексте с плавающей запятой: это интерпретируется как эквивалентное число с плавающей запятой.

3.1.3 Шестнадцатеричные значения

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

mysql> SELECT x'FF'
       -> 255
mysql> SELECT 0xa+0;
       -> 10
mysql> select 0x5061756c;
       -> Paul

Синтаксис x'hexstring' (нововведение в версии 4.0) основан на ANSI SQL и синтаксисе 0x из ODBC. Шестнадцатеричные строки часто используются ODBC, чтобы задать значения для столбцов типа BLOB.

3.1.4 Значения NULL

Значение NULL не означает "никакие данные" и отличается от значений типа 0 для числовых типов или пустой строки для типов строковых. Подробности в разделе " 11.5.3 Проблемы со значениями NULL".

NULL может представляться как \N при использовании импортирования текстового файла или экспортных форматов (LOAD DATA INFILE, SELECT ... INTO OUTFILE). Подробности в разделе "8.4.9 Синтаксис LOAD DATA INFILE".

3.2 Имена баз данных, таблиц, индексов, столбцов и псевдонимов

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

Обратите внимание, что правила изменились, начиная с MySQL Version 3.23.6, когда авторы представили цитирование идентификаторов (имена баз данных, таблиц и столбцов) с помощью апострофа (`). Двойная кавычка (") также будет работать, чтобы цитировать идентификаторы, если Вы выполняетесь в ANSI-режиме. Подробности в разделе "1.4.3 Запуск MySQL в ANSI-режиме".

Идентификатор | Максимальная длина | Допустимые символы
База данных | 64 | Любые символы, допустимые в имени каталога, кроме / или ..
Таблица | 64 | Любые символы, допустимые в имени файла, кроме / или ..
Столбец | 64 | Все символы.
Псевдоним | 255 | Все символы.

Обратите внимание, что в дополнение к вышеупомянутому, Вы не можете иметь в идентификаторе символы цитирования, а также ASCII(0) или ASCII(255).

Обратите внимание, что, если идентификатор представляет собой ограниченное слово или содержит специальные символы, Вы должны всегда цитировать его с `:

SELECT * from `select` where `select`.id > 100;

В предыдущих версиях MySQL правила для имен были следующими:

  • Имя может состоять из алфавитно-цифровых символов текущего набора символов, а также из _ и $. Заданный по умолчанию набор символов: ISO-8859-1 Latin1, это может быть изменено опцией --default-character-set в mysqld.
  • Имя может начинаться с любого символа, который является допустимым в имени. В частности имя может начинаться с номера (это отличие от многих других систем управления базами данных!). Однако, имя не может состоять только из чисел.
  • Вы не можете использовать символ точки (.) в именах потому, что он используется, чтобы расширить формат, которым Вы можете обратиться к столбцам.

Рекомендуется, чтобы Вы не использовали имена, подобные 1e потому, что выражение вроде 1e+1 неоднозначно. Это может интерпретироваться как выражение 1e+1 или как число 1e+1.

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

Ссылка на столбец | Значение
col_name | Столбец col_name из любой таблицы, используемой в запросе, содержащем это имя.
tbl_name.col_name | Столбец col_name из таблицы tbl_name текущей базы данных.
db_name.tbl_name.col_name | Столбец col_name из таблицы tbl_name базы данных db_name. Эта форма доступна в MySQL Version 3.22 или позже.
`column_name` | Столбец, который является ключевым словом или содержит специальные символы.

Вы не должны определять префикс tbl_name или db_name.tbl_name для столбца в инструкции, если ссылка однозначна. Например, есть таблицы t1 и t2, каждая содержит столбец c, и Вы получаете c командой SELECT, которая использует t1 и t2. В этом случае c неоднозначен потому, что он не уникален среди таблиц, используемых в инструкции, так что Вы должны указать, что Вы имеете в виду: t1.c или t2.c. Точно так же, если Вы получаете данные из таблицы t в базе данных db1 и из таблицы t в базе данных db2, Вы должны обратиться к столбцам в тех таблицах как db1.t.col_name и db2.t.col_name.

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

3.3 Чувствительность к регистру в именах

В MySQL базы данных и таблицы соответствуют каталогам и файлам внутри тех каталогов. Следовательно, чувствительность операционной системы определяет чувствительность к регистру имен таблицы и базы данных. Это означает, что имена баз данных и таблиц чувствительны к регистру в Unix и нечувствительны в Windows. Подробности в разделе "1.4.1 MySQL-расширения для ANSI SQL92".

ОБРАТИТЕ ВНИМАНИЕ: Несмотря на отсутствие чувствительности к регистру имен баз данных и таблиц в Windows, СУБД все же такое различие делает. Так что в рамках одного запроса надо использовать одно и то же имя. Например, этот запрос не сработает из-за одновременного применения my_table и MY_TABLE:

mysql> SELECT * FROM my_table WHERE MY_TABLE.col=1;

Имена столбца нечувствительны к регистру символов во всех случаях.

Псевдонимы для таблиц чувствительны к регистру. Например, этот запрос не сработает из-за одновременного применения a и A:

mysql> SELECT col_name FROM tbl_name AS a
           WHERE a.col_name = 1 OR A.col_name = 2;

Псевдонимы для столбцов нечувствительны к регистру.

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

Один способ избежать этой проблемы состоит в том, чтобы запустить mysqld с опцией -O lower_case_table_names=1. По умолчанию эта опция установлена в 1 под Windows и в 0 под Unix.

Если lower_case_table_names равен 1, MySQL преобразует все имена таблицы в строчные буквы. Обратите внимание, что, если Вы изменяете эту опцию, Вы должны сначала преобразовать Ваши старые имена таблиц в строчные буквы перед запуском сервера mysqld.

3.4 Пользовательские переменные

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

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

Вы можете устанавливать переменную через вызов SET:

SET @variable = {integer expression|real expression|string expression}
                [,@variable= ...].

Вы можете также устанавливать переменную в выражении @variable:=expr:

select @t1:=(@t2:=1)+@t3:=4,@t1,@t2,@t3;
  +----------------------+------+------+------+
  | @t1:=(@t2:=1)+@t3:=4 | @t1  | @t2  | @t3  |
  +----------------------+------+------+------+
  |                    5 |    5 |    1 |    4 |
  +----------------------+------+------+------+

Здесь надо использовать синтаксис := потому, что = был зарезервирован для сравнений.

Переменные пользователя могут применяться там, где позволяются выражения. Обратите внимание, что это в настоящее время не включает использование в контекстах, где явно требуется число, например, в предложении LIMIT вызова SELECT, или в предложении IGNORE number LINES в инструкции LOAD DATA.

ОБРАТИТЕ ВНИМАНИЕ: В инструкции SELECT каждое выражение вычислено только тогда, когда оно послано пользователю. Это означает, что в HAVING, GROUP BY или ORDER BY Вы не можете обратиться к выражению, которое включает переменные, которые установлены в SELECT. Например, следующая инструкция НЕ будет работать как ожидается:

SELECT (@aa:=id) AS a, (@aa+3) AS b FROM table_name HAVING b=5;

Причина: @aa будет содержать не значение текущей строки, а значение id предыдущей принятой строки.

3.5 Комментарии

Сервер MySQL поддерживает стили комментариев # до конца строки, -- до конца строки и /* в строке или в нескольких строках */:

mysql> select 1+1;     # Этот комментарий продолжается до конца строки.
mysql> select 1+1;     -- Этот тоже.
mysql> select 1 /* это комментарий, встроенный в строку */ + 1;
mysql> select 1+
/*
Это комментарий,
занимающий несколько строк.
*/
1;

Обратите внимание, что стиль комментария -- требует, чтобы Вы имели по крайней мере один пробел после --!

Хотя сервер понимает синтаксис комментария, имеются некоторые ограничения на путь, которым клиент mysql анализирует комментарии /* ... */:

  • Символы в одиночных и двойных кавычках указывают начало цитируемой строки даже внутри комментария. Если кавычка не согласована с второй кавычкой внутри комментария, синтаксический анализатор не понимает, что комментарий уже закончился. Если Вы работаете с mysql в интерактивном режиме, Вы можете крепко запутаться с приглашением командной строки, которое меняется с mysql> на '> или на ">.
  • Точка с запятой указывает конец текущей инструкции SQL.

Эти ограничения применяются, когда Вы выполняете mysql в интерактивном режиме и тогда, когда Вы помещаете команды в файл и сообщаете, чтобы mysql читал ввод из этого файла командой mysql < some-file.

MySQL не поддерживает ANSI SQL стиль комментария `--'. Подробности в разделе "1.4.4.8 `--' как начало комментария".

3.6 Как MySQL работает с зарезервированными словами

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

Следующие слова явно зарезервированы в MySQL. Большинство их запрещается ANSI SQL92 для имен таблицы или столбца (например, group). Несколько слов зарезервированы потому, что MySQL нуждается в них и (в настоящее время) использует синтаксический анализатор yacc:
action | add | aggregate | all
alter | after | and | as
asc | avg | avg_row_length | auto_increment
between | bigint | bit | binary
blob | bool | both | by
cascade | case | char | character
change | check | checksum | column
columns | comment | constraint | create
cross | current_date | current_time | current_timestamp
data | database | databases | date
datetime | day | day_hour | day_minute
day_second | dayofmonth | dayofweek | dayofyear
dec | decimal | default | delayed
delay_key_write | delete | desc | describe
distinct | distinctrow | double | drop
end | else | escape | escaped
enclosed | enum | explain | exists
fields | file | first | float
float4 | float8 | flush | foreign
from | for | full | function
global | grant | grants | group
having | heap | high_priority | hour
hour_minute | hour_second | hosts | identified
ignore | in | index | infile
inner | insert | insert_id | int
integer | interval | int1 | int2
int3 | int4 | int8 | into
if | is | isam | join
key | keys | kill | last_insert_id
leading | left | length | like
lines | limit | load | local
lock | logs | long | longblob
longtext | low_priority | max | max_rows
match | mediumblob | mediumtext | mediumint
middleint | min_rows | minute | minute_second
modify | month | monthname | myisam
natural | numeric | no | not
null | on | optimize | option
optionally | or | order | outer
outfile | pack_keys | partial | password
precision | primary | procedure | process
processlist | privileges | read | real
references | reload | regexp | rename
replace | restrict | returns | revoke
rlike | row | rows | second
select | set | show | shutdown
smallint | soname | sql_big_tables | sql_big_selects
sql_low_priority_updates | sql_log_off | sql_log_update | sql_select_limit
sql_small_result | sql_big_result | sql_warnings | straight_join
starting | status | string | table
tables | temporary | terminated | text
then | time | timestamp | tinyblob
tinytext | tinyint | trailing | to
type | use | using | unique
unlock | unsigned | update | usage
values | varchar | variables | varying
varbinary | with | write | when
where | year | year_month | zerofill

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

  • ACTION
  • BIT
  • DATE
  • ENUM
  • NO
  • TEXT
  • TIME
  • TIMESTAMP


Введение в администрирование

4 Введение в администрирование

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

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

Поскольку таблицы MySQL сохранены как файлы, просто делайте копию. Чтобы получать непротиворечивую копию, скомандуйте LOCK TABLES на релевантных таблицах и дополните это командой FLUSH TABLES для них, дабы все данные были гарантированно сброшены на диск. Подробности по этим командам есть в разделах "9.7.2 Синтаксис LOCK TABLES/UNLOCK TABLES" и "4.8 Синтаксис FLUSH". Вам нужна только блокировка записи. Это позволяет другим потокам продолжать делать запросы к таблицам в то время, как Вы делаете копию файлов в каталоге баз данных. Команда FLUSH TABLE необходима, чтобы гарантировать, что все активные индексные страницы записаны на диск прежде, чем Вы запускаете процесс копирования.

Если Вы хотите делать копию уровня SQL из таблицы, Вы можете использовать SELECT INTO OUTFILE или BACKUP TABLE. Подробности в разделах "8.1 Синтаксис SELECT " и "4.2 Синтаксис BACKUP TABLE".

Другой способ поддержать базу данных состоит в том, чтобы использовать программу mysqldump или скрипт mysqlhotcopy. Подробности в разделах "12.5 mysqldump, Дамп структур таблиц и данных" и "12.6 mysqlhotcopy, Копирование баз данных и таблиц MySQL".

  1. Для полного резервирования баз данных надо скомандовать:
    shell> mysqldump --tab=/path/to/some/dir --opt --full
    или
    shell> mysqlhotcopy database /path/to/some/dir
    Вы можете также просто копировать все файлы таблицы (*.frm, *.MYD и *.MYI), пока сервер что-нибудь не модифицирует. Скрипт mysqlhotcopy использует этот метод.
  2. Если mysqld запущен, остановите его, а затем запустите с опцией --log-update[=file_name]. Подробнее об этой опции можно узнать в разделе "4.9.3 Файл регистрации модификаций". Файлы протоколов предоставляют Вам информацию относительно того, что изменилось со времени последнего вызова mysqldump.

Если Вы должны восстановить что-либо, попробуйте восстанавливать Ваши таблицы, используя REPAIR TABLE или myisamchk -r. Это эффективно в 99.9% случаев. Если myisamchk ничего хорошего не сделал, попробуйте следующую процедуру (это будет работать только, если Вы запустили MySQL с опцией --log-update):

  1. Восстановите оригинальную копию mysqldump.
  2. Выполните следующую команду, чтобы заново выполнить модификации в двоичном файле регистрации:
    shell> mysqlbinlog hostname-bin.[0-9]* | mysql
    Если Вы используете файл регистрации модификации, Вы можете использовать:
    shell> ls -1 -t -r hostname.[0-9]* | xargs cat | mysql

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

Вы можете также делать выборочные копии: SELECT * INTO OUTFILE file_name FROM tbl_name и восстанавливать их: LOAD DATA INFILE file_name REPLACE .... Чтобы избежать двойных записей, Вам нужен PRIMARY KEY или UNIQUE в таблице. Ключевое слово REPLACE заменяет старые записи на новые, когда новая запись дублирует старую запись на уникальном значении ключа.

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

Если Вы используете файловую систему Veritas, Вы можете делать следующее:

  1. Выполните в клиенте (perl?) FLUSH TABLES WITH READ LOCK
  2. Выполните в другом клиенте или в копии оболочки команду mount vxfs snapshot.
  3. Выполните в первом клиенте UNLOCK TABLES
  4. Копируйте файлы из snapshot
  5. Размонтируйте snapshot

4.2 Синтаксис BACKUP TABLE

BACKUP TABLE tbl_name[,tbl_name...] TO '/path/to/backup/directory'

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

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

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

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

Столбец | Значение
Table | Имя таблицы
Op | Обязательно ``backup''
Msg_type | Одно из status, error, info или warning.
Msg_text | Собственно сообщение.

Обратите внимание, что команда BACKUP TABLE доступна только в MySQL версии 3.23.25 и старше.

4.3 Синтаксис RESTORE TABLE

RESTORE TABLE tbl_name[,tbl_name...] FROM '/path/to/backup/directory'

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

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

Столбец | Значение
Table | Имя таблицы
Op | Обязательно ``restore''
Msg_type | Одно из status, error, info или warning.
Msg_text | Собственно сообщение.

4.4 Синтаксис CHECK TABLE

CHECK TABLE tbl_name[,tbl_name...] [option [option...]]
option = QUICK | FAST | MEDIUM | EXTENDED | CHANGED

CHECK TABLE работает только с таблицами типа MyISAM. На них данная команда эквивалентна myisamchk -m table_name.

Если Вы не определяете опций, используется MEDIUM.

Данная команда проверяет таблицу на ошибки. Для таблиц типа MyISAM модифицируется статистика ключа. Команда возвращает таблицу со следующими столбцами:

Столбец | Значение
Table | Имя таблицы.
Op | Обязательно ``check''.
Msg_type | Одно из status, error, info или warning.
Msg_text | Собственно сообщение.

Обратите внимание, что Вы можете получать много строк информации для каждой проверенной таблицы. Последняя строка будет иметь тип Msg_type status и значение OK, если все хорошо. Если ответов OK или Not checked нет, Вы должны выполнить ремонт таблицы. Сообщение Not checked говорит о том, что для данной таблицы TYPE сообщил MySQL, что там не было никакой потребности проверять таблицу.

Различные типы проверки:

Тип | Значение
QUICK | Не просматривать строки, чтобы проверить неправильные связи.
FAST | Проверить только те таблицы, которые не были закрыты правильно.
CHANGED | Проверить только те таблицы, которые не были закрыты правильно, и те, которые изменились со времен последней проверки.
MEDIUM | Сканировать строки для проверки правильности удаленных связей. Это также вычисляет контрольную сумму ключа для строк и проверяет ее правильность.
EXTENDED | Выполнить полную проверку всех ключей для всех строк в таблице. Это гарантирует, что таблица на 100% непротиворечива, но требует много времени!

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

Вы можете объединять параметры проверки:

CHECK TABLE test_table FAST QUICK;

Это предписывает провести быструю проверку на таблице, если она не была закрыта правильно.

ОБРАТИТЕ ВНИМАНИЕ: в ряде случаев CHECK TABLE изменяет таблицу! Это случается, если таблица отмечена как 'corrupted' (повреждена) или 'not closed properly' (не закрыта правильно), но команда CHECK TABLE не нашла проблем в таблице. В этой ситуации CHECK TABLE отметит таблицу как ok.

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

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

FAST и CHANGED обычно предназначены, чтобы использоваться из скрипта (например, из cron), если Вы хотите проверять таблицу время от времени. В большинстве случаев FAST имеет приоритет перед CHANGED.

EXTENDED должен использоваться после того, как Вы выполнили нормальную проверку, но все еще получаете странные ошибки из таблицы, когда MySQL пробует модифицировать строку или найти строку по ключу (это ОЧЕНЬ маловероятно, если нормальная проверка прошла спокойно!).

Некоторые вещи, сообщаемые проверкой таблиц, не могут быть исправлены в автоматическом режиме:

  • Найденная строка, где столбец auto_increment имеет значение 0 . Это означает, что Вы имеете в таблице строку, где столбец индекса auto_increment содержит значение 0. Можно создать такую конструкцию командой UPDATE. Это не ошибка само по себе, но может вызывать проблему, если Вы сбрасываете таблицу в дамп, а потом восстановите ее оттуда или скомандуете ALTER TABLE на таблице. В этом случае столбец auto_increment изменит значение, согласно правилам auto_increment, что может вызвать проблемы подобно ошибке дублирования ключа. Избавиться от предупреждения можно, только выполнив инструкцию UPDATE, чтобы установить столбец к некоторому другому значению (не 0).

4.5 Синтаксис REPAIR TABLE

REPAIR TABLE tbl_name[,tbl_name...] [QUICK] [EXTENDED]

REPAIR TABLE тоже работает только на таблицах типа MyISAM и аналогичен вызову myisamchk -r table_name.

Обычно Вам никогда не придется выполнять эту команду, но в случае ошибок Вы, очень вероятно, вернете все Ваши данные из таблицы MyISAM с помощью команды REPAIR TABLE. Если Ваши таблицы разрушаются, Вы должны попробовать нахйти причину этого! Подробности по этому вопросу есть в разделе "11.4.1 Что делать, если MySQL рухнул".

REPAIR TABLE восстанавливает разрушенную таблицу. Команда возвращает таблицу со следующими столбцами:

Столбец | Значение
Table | Имя таблицы
Op | Обязательно ``repair''
Msg_type | Одно из status, error, info или warning.
Msg_text | Собственно сообщение.

Обратите внимание, что Вы можете получать много строк информации для каждой восстановленной таблицы. Последняя будет иметь тип Msg_type status и значение OK, если все в порядке. Если значение OK так и не появилось, Вы должны попробовать восстанавливать таблицу с помощью myisamchk -o, поскольку REPAIR TABLE еще не выполняет все параметры myisamchk. В ближайшем будущем планируется сделать ее более гибкой.

Если задан QUICK, MySQL пробует делать REPAIR только для индексного дерева.

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

4.6 Синтаксис OPTIMIZE TABLE

OPTIMIZE TABLE tbl_name[,tbl_name]...

OPTIMIZE TABLE должен использоваться, если Вы удалили большую часть таблицы, или если Вы сделали много изменений для таблицы со строками переменных длин (таблицы, которые имеют VARCHAR, BLOB или TEXT). Удаленные записи поддерживаются в связанном списке, и при последующем использовании операций INSERT повторно применяются старые позиции записей. Вы можете использовать OPTIMIZE TABLE, чтобы освободить неиспользуемое место и дефрагментировать файл данных.

Сейчас OPTIMIZE TABLE применим только к таблицам типов MyISAM и BDB. Для таблиц типа BDB OPTIMIZE TABLE в настоящее время отображается на вызов ANALYZE TABLE. Подробности об этом вызове в разделе "4.7 Синтаксис ANALYZE TABLE ".

Вы можете оптимизировать и другие типы таблиц запуском mysqld с опциями --skip-new или --safe-mode, но в этом случае OPTIMIZE TABLE превратится в вызов ALTER TABLE.

OPTIMIZE TABLE работает следующим образом:

  • Если таблица имеет удаленные или порванные строки, ремонтирует таблицу.
  • Если индексные страницы не отсортированы, сортирует их.
  • Если статистика не современна (и ремонт не может быть выполнен с сортировкой индекса), модифицирует ее.

OPTIMIZE TABLE для таблиц типа MyISAM эквивалентен вызову myisamchk --quick --check-changed-tables --sort-index --analyze.

Обратите внимание, что таблица будет блокирована в течение всего времени работы команды OPTIMIZE TABLE!

4.7 Синтаксис ANALYZE TABLE

ANALYZE TABLE tbl_name[,tbl_name...]

Анализирует и сохраняет распределение ключей для таблицы. Во время процесса анализа таблица будет блокирована с доступом только на чтение. Это работает на таблицах типов MyISAM и BDB.

Это эквивалентно вызову myisamchk -a.

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

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

Столбец | Значение
Table | Имя таблицы
Op | Обязательно ``analyze''
Msg_type | Одно из status, error, info или warning.
Msg_text | Собственно сообщение.

Вы можете проверять сохраненное распределение ключей командой SHOW INDEX. Подробности в разделе "4.10.1 Получение информации о базах данных, таблицах, столбцах и индексах".

Если таблица не изменилась после последней команды ANALYZE TABLE, она не будет проанализирована снова.

4.8 Синтаксис FLUSH

FLUSH flush_option [,flush_option]

Вы должны использовать команду FLUSH, если Вы хотите очищать внутренние кэши MySQL. Для выполнения FLUSH Вы должны иметь право RELOAD.

flush_option может быть любой из следующего списка:

HOSTS | Освобождает ведущие таблицы кэша. Вы должны это сделать, если некоторые из Ваших хостов изменяют IP, или если Вы получили сообщение об ошибке "Host ... is blocked". Когда в строке для данного компьютера происходит больше, чем max_connect_errors ошибок за время связи с сервером, MySQL приходит к выводу, что что-то пошло неправильно, и блокирует компьютер. Подробности в разделе "11.2.4 Ошибка Host '...' is blocked. Вы можете запустить mysqld с опцией -O max_connection_errors=999999999, чтобы избежать этого сообщения об ошибке.
LOGS | Закрывает и вновь открывает все журналы. Если Вы определили журнал модификаций или двоичный журнал без расширения, номер расширения журнала будет увеличен на один относительно предыдущего файла. Если Вы использовали расширение в имени файла, MySQL закроет и вновь откроет журнал модификаций. Это эквивалентно посылке на сервер mysqld сигнала SIGHUP.
PRIVILEGES | Перезагружает привилегии из таблиц в базе данных mysql.
TABLES | Закрывает все открытые таблицы.
[TABLE|TABLES] table_name [,table_name...] | Применяет предыдущую команду только к заданным таблицам.
TABLES WITH READ LOCK | Закрывает все открытые таблицы и блокирует все таблицы для всех баз данных с доступом только на чтение, пока не будет выполнена команда UNLOCK TABLES. Это очень удобный способ получить резервную копию, если Вы имеете файловую систему, подобную Veritas.
STATUS | Сбрасывает большинство переменных состояния к нулю. Используется при отладке запроса.

Вы можете также обращаться к каждой из команд, показанных выше с помощью утилиты mysqladmin, используя команды flush-hosts, flush-logs, reload или flush-tables.

4.9 Синтаксис KILL

KILL thread_id

Каждое подключение к mysqld выполняется в отдельном процессе. Вы можете видеть запущенные процессы командой SHOW PROCESSLIST и уничтожать процесс командой KILL thread_id.

Если Вы имеете привилегию process, Вы можете видеть и уничтожать все процессы. Иначе Вы можете видеть и уничтожать только Ваши собственные процессы.

Вы можете также использовать команды mysqladmin processlist и mysqladmin kill, чтобы исследовать и уничтожать процессы.

При вызове KILL для процесса устанавливается флаг kill flag.

В большинстве случаев может требоваться некоторое время для того, чтобы процесс уничтожился, поскольку флаг kill flag может быть проверен только в специфических интервалах:

  • В циклах SELECT, ORDER BY и GROUP BY флажок будет проверен после чтения блока строк. Если он установлен, инструкция будет прервана.
  • При выполнении ALTER TABLE флаг будет проверен прежде, чем каждый блок строк считается из первоначальной таблицы. Если он установлен, команда будет прервана, а временная таблица удалена.
  • При выполнении UPDATE TABLE и DELETE TABLE, флажок будет проверен после каждого чтения блока и после каждого обновления или удаления строки. Если он установлен, инструкция будет прервана. Обратите внимание, что, если Вы не используете транзакции, сделанные в таблице изменения не будут отменены!
  • GET_LOCK() прервется с NULL.
  • Все процессы INSERT DELAYED быстренько сбросят на диск все строки, которые у них лежат в памяти и завершатся.
  • Если поток находится в драйвере блокировки таблицы (состояние: Locked), блокировка таблицы будет быстро прервана.
  • Если поток ждет свободное дисковое пространство в вызове write, запись немедленно прерывается с сообщением об ошибке переполнения диска.

4.10 Синтаксис SHOW

   SHOW DATABASES [LIKE wild]
   SHOW [OPEN] TABLES [FROM db_name] [LIKE wild]
   SHOW [FULL] COLUMNS FROM tbl_name [FROM db_name] [LIKE wild]
   SHOW INDEX FROM tbl_name [FROM db_name]
   SHOW TABLE STATUS [FROM db_name] [LIKE wild]
   SHOW STATUS [LIKE wild]
   SHOW VARIABLES [LIKE wild]
   SHOW LOGS
   SHOW [FULL] PROCESSLIST
   SHOW GRANTS FOR user
   SHOW CREATE TABLE table_name
   SHOW MASTER STATUS
   SHOW MASTER LOGS
   SHOW SLAVE STATUS

SHOW обеспечивает информацию относительно баз данных, таблиц, столбцов или информацию состояния сервера. Если используется часть LIKE wild, строка wild может быть строкой, которая использует групповые символы SQL % и _.

4.10.1 Получение информации о базе данных, таблицах, столбцах и индексах

Вы можете использовать db_name.tbl_name как вариант для tbl_name FROM db_name. Эти две инструкции эквивалентны:

mysql> SHOW INDEX FROM mytable FROM mydb;
mysql> SHOW INDEX FROM mydb.mytable;

SHOW DATABASES вносит в список базы данных на сервере MySQL. Вы можете также получать этот список, используя команду mysqlshow.

SHOW TABLES вносит в список таблицы в заданной базе данных. Вы можете также получать этот список, используя команду mysqlshow db_name.

ОБРАТИТЕ ВНИМАНИЕ: Если пользователь не имеет привилегий для таблицы, соответствующая таблица не будет обнаруживаться в выводе SHOW TABLES или mysqlshow db_name.

SHOW OPEN TABLES вносит в список таблицы, которые являются в настоящее время открытыми в кэше таблиц. Поле Comment сообщает сколько раз таблица кэшируется (cached) и используется (in_use).

SHOW COLUMNS вносит в список столбцы в данной таблице. Если Вы определяете опцию FULL, Вы также получите привилегии, которые Вы имеете для каждого столбца. Если типы столбцов отличны от ожидаемых, они будут основаны на инструкции CREATE TABLE, заметьте, что MySQL иногда сам изменяет типы столбца. Подробности в разделе "7.3.1 Тихие изменения спецификации столбца".

Инструкция DESCRIBE обеспечивает информацию, подобную SHOW COLUMNS. Подробности в разделе "9.1.2 Синтаксис DESCRIBE (получение информации о столбцах)".

SHOW FIELDS является синонимом для SHOW COLUMNS, а SHOW KEYS синонимом для SHOW INDEX. Вы можете также вносить в список столбцы таблицы или индексы с помощью команд mysqlshow db_name tbl_name или mysqlshow -k db_name tbl_name.

SHOW INDEX возвращает индексную информацию в формате, который очень походит на вызов SQLStatistics в ODBC. Следующие столбцы всегда будут возвращены:

Столбец | Назначение
Table | Имя таблицы.
Non_unique | 0, если индекс не может содержать дубликаты.
Key_name | Имя индекса.
Seq_in_index | Номер последовательности столбца в индексе, начиная с 1 (не с 0!).
Column_name | Имя столбца.
Collation | Как столбец сортируется в индексе. В MySQL это может иметь варианты `A' (по возрастанию) или NULL (не сортируемый).
Cardinality | Число уникальных значений в индексе. Это модифицируется запуском isamchk -a.
Sub_part | Число индексированных символов, если столбец только частично индексирован. NULL если весь ключ индексирован в полном объеме.
Comment | Различные замечания. Пока это сообщает, является ли индекс полнотекстовым (FULLTEXT) или нет.

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

4.10.2 Синтаксис SHOW TABLE STATUS

SHOW TABLE STATUS [FROM db_name] [LIKE wild]

SHOW TABLE STATUS (новинка в Version 3.23) работает подобно SHOW STATUS, но обеспечивает много информации относительно каждой таблицы. Вы можете также получать этот список, используя команду mysqlshow --status db_name. Следующие столбцы возвращены:

Столбец | Зачем он нужен
Name | Имя таблицы.
Type | Тип таблицы.
Row_format | Формат хранения строки (фиксированный, динамический или сжатый).
Rows | Число строк.
Avg_row_length | Средняя длина строки.
Data_length | Длина файла данных.
Max_data_length | Максимальная длина файла данных.
Index_length | Длина индексного файла.
Data_free | Число распределенных, но не используемых байт.
Auto_increment | Следующее значение auto_increment.
Create_time | Когда таблица была создана.
Update_time | Когда файл данных был в последний раз модифицирован.
Check_time | Когда таблица была в последний раз проверена на ошибки.
Create_options | Дополнительные параметры, используемые с CREATE TABLE.
Comment | Комментарий, используемый при создании таблицы (или информация о том, почему MySQL не может обращаться к информации по данной таблицы).

Таблицы InnoDB сообщат свободное пространство в ней через поле комментария таблицы.

4.10.3 Синтаксис SHOW STATUS

SHOW STATUS обеспечивает информацию состояния сервера (подобно mysqladmin extended-status). Вывод походит на показанное ниже, хотя формат и числа будут другими:

+--------------------------+------------+
| Variable_name            | Value      |
+--------------------------+------------+
| Aborted_clients          | 0          |
| Aborted_connects         | 0          |
| Bytes_received           | 155372598  |
| Bytes_sent               | 1176560426 |
| Connections              | 30023      |
| Created_tmp_disk_tables  | 0          |
| Created_tmp_tables       | 8340       |
| Created_tmp_files        | 60         |
| Delayed_insert_threads   | 0          |
| Delayed_writes           | 0          |
| Delayed_errors           | 0          |
| Flush_commands           | 1          |
| Handler_delete           | 462604     |
| Handler_read_first       | 105881     |
| Handler_read_key         | 27820558   |
| Handler_read_next        | 390681754  |
| Handler_read_prev        | 6022500    |
| Handler_read_rnd         | 30546748   |
| Handler_read_rnd_next    | 246216530  |
| Handler_update           | 16945404   |
| Handler_write            | 60356676   |
| Key_blocks_used          | 14955      |
| Key_read_requests        | 96854827   |
| Key_reads                | 162040     |
| Key_write_requests       | 7589728    |
| Key_writes               | 3813196    |
| Max_used_connections     | 0          |
| Not_flushed_key_blocks   | 0          |
| Not_flushed_delayed_rows | 0          |
| Open_tables              | 1          |
| Open_files               | 2          |
| Open_streams             | 0          |
| Opened_tables            | 44600      |
| Questions                | 2026873    |
| Select_full_join         | 0          |
| Select_full_range_join   | 0          |
| Select_range             | 99646      |
| Select_range_check       | 0          |
| Select_scan              | 30802      |
| Slave_running            | OFF        |
| Slave_open_temp_tables   | 0          |
| Slow_launch_threads      | 0          |
| Slow_queries             | 0          |
| Sort_merge_passes        | 30         |
| Sort_range               | 500        |
| Sort_rows                | 30296250   |
| Sort_scan                | 4650       |
| Table_locks_immediate    | 1920382    |
| Table_locks_waited       | 0          |
| Threads_cached           | 0          |
| Threads_created          | 30022      |
| Threads_connected        | 1          |
| Threads_running          | 1          |
| Uptime                   | 80380      |
+--------------------------+------------+

Переменные состояния, перечисленные выше, имеют следующие значения:

Переменная | Значение
Aborted_clients | Число подключений, прерванных потому, что клиент не закрыл подключение правильно. Подробности в разделе "11.2.9 Ошибки связи/прерванные соединения".
Aborted_connects | Число попыток соединиться с сервером MySQL, которые потерпели неудачу. Подробности в разделе "11.2.9 Ошибки связи/прерванные соединения".
Bytes_received | Число байт, полученных с клиентов.
Bytes_sent | Число байт, посланных клиентам.
Connections | Число попыток подключения к серверу MySQL.
Created_tmp_disk_tables | Число неявных временных таблиц на диске, созданных при выполнении инструкций.
Created_tmp_tables | Число неявных временных таблиц в памяти, созданных при выполнении инструкций.
Created_tmp_files | Сколько временных файлов создал mysqld.
Delayed_insert_threads | Число отсроченных потоков драйвера вставки в использовании.
Delayed_writes | Число строк, записанных со INSERT DELAYED.
Delayed_errors | Число строк, записанных со INSERT DELAYED, для которых произошла ошибка (вероятно, двойной ключ (duplicate key) был использован).
Flush_commands | Число выполненных команд FLUSH.
Handler_delete | Сколько раз строка была удалена из таблицы.
Handler_read_first | Сколько раз первая запись читалась из индекса. Если это значение высоко, предполагается, что сервер делал много полных просмотров индекса, например, SELECT col1 FROM foo, считая, что col1 индексирован.
Handler_read_key | Число запросов на чтение строки, основанных на ключе. Если это значение высоко, это значит, что Ваши запросы и таблицы были правильно индексированы.
Handler_read_next | Число запросов на чтение следующей строки в порядке ключа. Это значение будет увеличено, если Вы запрашиваете индексный столбец с ограничением диапазона. Это также будет увеличено, если Вы делаете индексный просмотр.
Handler_read_rnd | Число запросов на чтение строк, основанных на фиксированной позиции. Это значение будет высоким, если Вы делаете много запросов, которые требуют сортировки результата.
Handler_read_rnd_next | Число запросов на чтение следующей строки в файле данных. Это значение будет высоким, если Вы делаете много просмотров таблицы. Вообще это предполагает, что Ваши таблицы не были правильно индексированы, или что Ваши запросы не используют индексы.
Handler_update | Число запросов на модификацию строк в таблице.
Handler_write | Число запросов на вставку строки в таблицу.
Key_blocks_used | Число используемых блоков в кэше ключа.
Key_read_requests | Число запросов на чтение блока ключа из кэша.
Key_reads | Число физических чтений блока ключа с диска, а не из кэша.
Key_write_requests | Число запросов на запись блока ключа в кэш.
Key_writes | Число физических записей блока ключа на диск, а не в кэш.
Max_used_connections | Максимальное число подключений в использовании одновременно.
Not_flushed_key_blocks | Число блоков ключей в кэше ключа, которые изменились, но не сброшены на диск.
Not_flushed_delayed_rows | Число строк, ждущих записи в очередях запросов INSERT DELAY.
Open_tables | Число таблиц, которые являются открытыми.
Open_files | Число файлов, которые являются открытыми.
Open_streams | Число потоков, которые являются открытыми (используемыми, главным образом, для протоколирования).
Opened_tables | Число таблиц, которые были открыты.
Select_full_join | Число объединений без ключей (должно быть 0).
Select_full_range_join | Число объединений, где использовали поиск диапазона по таблице ссылок.
Select_range | Число объединений, где использовали диапазоны в первой таблице. Это обычно не критическое, даже если это большое.
Select_scan | Число объединений, где просмотрели первую таблицу.
Select_range_check | Число объединений без ключей, где проверяем использование ключа после каждой строки (должно быть 0).
Questions | Число запросов, посланных серверу.
Slave_open_temp_tables | Число временных таблиц, в настоящее время открытых подчиненным процессом.
Slow_launch_threads | Число потоков, которым понадобилось для установления соединения больше, чем slow_launch_time.
Slow_queries | Число запросов, которые заняли больше, чем long_query_time.
Sort_merge_passes | Число объединений, потребовавших сортировки. Если это значение большое, Вы должны рассмотреть увеличение sort_buffer.
Sort_range | Число сортировок с диапазонами.
Sort_rows | Число сортируемых строк.
Sort_scan | Число сортировок выполненных, просматривая таблицу.
Table_locks_immediate | Сколько раз блокировка таблицы применялась сразу. Доступно после версии 3.23.33.
Table_locks_waited | Сколько раз блокировка таблицы не могла быть применена сразу и пришлось ждать. Если это значение высоко, и Вы имеете проблемы с эффективностью, Вы должны сначала оптимизировать Ваши запросы, а затем или разделить таблицу, или использовать репликацию. Доступно после 3.23.33.
Threads_cached | Число потоков в кэше.
Threads_connected | Сколько в настоящее время открыто подключений.
Threads_created | Число потоков созданных, чтобы обработать подключения.
Threads_running | Число потоков, которые сейчас не бездействуют.
Uptime | Сколько секунд сервер уже работает.

Некоторые комментарии относительно вышеупомянутого:

  • Если Opened_tables велико, то переменная table_cache, вероятно, слишком маленькая.
  • Если key_reads велико, то переменная key_cache, вероятно, слишком маленькая. Коэффицент кэширования может быть вычислен по формуле: key_reads/key_read_requests.
  • Если Handler_read_rnd велико, то Вы, вероятно, имеете много запросов, которые требуют, чтобы MySQL просматривал целые таблицы, или Вы имеете объединения, которые не используют ключи правильно.
  • Если Threads_created велико, то следует увеличить переменную thread_cache_size.

4.10.4 Синтаксис SHOW VARIABLES

SHOW VARIABLES [LIKE wild]

SHOW VARIABLES показывает значения некоторых переменных системы MySQL. Вы можете также получить эту информацию, используя команду mysqladmin variables.

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

+-------------------------+---------------------------+
| Variable_name           | Value                     |
+-------------------------+---------------------------+
| ansi_mode               | OFF                       |
| back_log                | 50                        |
| basedir                 | /my/monty/                |
| bdb_cache_size          | 16777216                  |
| bdb_log_buffer_size     | 32768                     |
| bdb_home                | /my/monty/data/           |
| bdb_max_lock            | 10000                     |
| bdb_logdir              |                           |
| bdb_shared_data         | OFF                       |
| bdb_tmpdir              | /tmp/                     |
| binlog_cache_size       | 32768                     |
| concurrent_insert       | ON                        |
| connect_timeout         | 5                         |
| datadir                 | /my/monty/data/           |
| delay_key_write         | ON                        |
| delayed_insert_limit    | 100                       |
| delayed_insert_timeout  | 300                       |
| delayed_queue_size      | 1000                      |
| flush                   | OFF                       |
| flush_time              | 0                         |
| have_bdb                | YES                       |
| have_innodb             | YES                       |
| have_raid               | YES                       |
| have_ssl                | NO                        |
| init_file               |                           |
| interactive_timeout     | 28800                     |
| join_buffer_size        | 131072                    |
| key_buffer_size         | 16776192                  |
| language                | /my/monty/share/english/  |
| large_files_support     | ON                        |
| log                     | OFF                       |
| log_update              | OFF                       |
| log_bin                 | OFF                       |
| log_slave_updates       | OFF                       |
| long_query_time         | 10                        |
| low_priority_updates    | OFF                       |
| lower_case_table_names  | 0                         |
| max_allowed_packet      | 1048576                   |
| max_binlog_cache_size   | 4294967295                |
| max_connections         | 100                       |
| max_connect_errors      | 10                        |
| max_delayed_threads     | 20                        |
| max_heap_table_size     | 16777216                  |
| max_join_size           | 4294967295                |
| max_sort_length         | 1024                      |
| max_tmp_tables          | 32                        |
| max_write_lock_count    | 4294967295                |
| myisam_recover_options  | DEFAULT                   |
| myisam_sort_buffer_size | 8388608                   |
| net_buffer_length       | 16384                     |
| net_read_timeout        | 30                        |
| net_retry_count         | 10                        |
| net_write_timeout       | 60                        |
| open_files_limit        | 0                         |
| pid_file                | /my/monty/data/donna.pid  |
| port                    | 3306                      |
| protocol_version        | 10                        |
| record_buffer           | 131072                    |
| query_buffer_size       | 0                         |
| safe_show_database      | OFF                       |
| server_id               | 0                         |
| skip_locking            | ON                        |
| skip_networking         | OFF                       |
| skip_show_database      | OFF                       |
| slow_launch_time        | 2                         |
| socket                  | /tmp/mysql.sock           |
| sort_buffer             | 2097116                   |
| table_cache             | 64                        |
| table_type              | MYISAM                    |
| thread_cache_size       | 4                         |
| thread_stack            | 65536                     |
| tmp_table_size          | 1048576                   |
| tmpdir                  | /tmp/                     |
| version                 | 3.23.29a-gamma-debug      |
| wait_timeout            | 28800                     |
+-------------------------+---------------------------+

Каждая опция описана ниже. Значения для буферных размеров, длин и размеров стека даны в байтах. Вы можете определять значения с суффиксами `K' или `M', чтобы указать килобайты или мегабайты. Например, 16M указывает 16 мегабайтов. Регистр символов суффикса не имеет значения: 16M и 16m эквивалентны.

ansi_mode.
ON, если mysqld запущен с опцией --ansi. Подробности в разделе "1.4.3 Запуск MySQL в режиме ANSI".
back_log
Сколько ожидающих обработки подключений может иметь MySQL. Это важно, когда главный процесс MySQL получает ОЧЕНЬ много запросов подключения за очень короткое время. Затем требуется некоторое время (хотя очень немного) для основного процесса, чтобы проверить подключение и запустить новый поток. Значение back_log указывает, сколько запросов могут быть сложены в стек в течение этого короткого времени прежде, чем MySQL на мгновение остановит ответы на новые запросы. Вы должны увеличить это только, если Вы ожидаете большое количество подключений за короткий периоде времени (сервер работает интенсивно).

Другими словами, это значение задает размер слушающей очереди для входящих подключений TCP/IP. Ваша операционная система имеет собственное ограничение размера этой очереди. В Unix man-страница listen(2) должна иметь большее количество деталей. Проверьте документацию на Вашу ОС для выяснения максимального значения для этой переменной. Попытка устанавливать back_log выше, чем это ограничение операционной системы, будет неэффективна, хотя и безопасна.

basedir
Значение опции --basedir.
bdb_cache_size
Буфер, который распределен, чтобы кэшировать индекс и строки для BDB-таблиц. Если Вы не используете таблицы BDB, Вы должны запустить mysqld с опцией --skip-bdb, чтобы не тратить впустую память для этого кэша.
bdb_log_buffer_size
Буфер, который распределен, чтобы кэшировать протоколы для BDB-таблиц. Если Вы не используете таблицы BDB, Вы должны запустить mysqld с опцией --skip-bdb, чтобы не тратить впустую память для этого кэша.
bdb_home
Значение опции --bdb-home.
bdb_max_lock
Максимальное число блокировок (по умолчанию 1000), которые Вы можете иметь активным на BDB-таблице. Вы должны увеличить это значение, если Вы получаете ошибки типа bdb: Lock table is out of available locks или Got error 12 from ..., когда Вы делаете длинные транзакции, или когда mysqld должен исследовать много строк, чтобы вычислить и обработать запрос.
bdb_logdir
Значение опции --bdb-logdir.
bdb_shared_data
ON, если Вы используете --bdb-shared-data.
bdb_tmpdir
Значение опции --bdb-tmpdir.
binlog_cache_size.
Размер кэша, чтобы хранить инструкции SQL для двоичного файла регистрации в течение транзакции. Если Вы часто используете большие, многооператорные транзакции, Вы можете увеличить это значение, чтобы получить большую эффективность. Подробности в разделе "9.2.1 Синтаксис BEGIN/COMMIT/ROLLBACK".
character_set
Набор символов по умолчанию.
character_sets
Поддерживаемые наборы символов.
concurrent_inserts
Если ON (значение по умолчанию), MySQL позволит Вам использовать INSERT на таблицах системы MyISAM в то же самое время, когда Вы выполняете на них запросы SELECT. Вы можете выключить эту опцию запуском mysqld с параметрами --safe или --skip-new.
connect_timeout
Число секунд, которое сервер mysqld ждет подключения перед ответом Bad handshake.
datadir
Значение опции --datadir.
delay_key_write
Если включено (по умолчанию), MySQL учитывает опцию delay_key_write в CREATE TABLE. Это означает, что буфер ключей для таблиц с этой опцией не будет сбрасываться на каждой индексной модификации, а только когда таблица будет закрыта. Это ускорит работу по записи, но Вы должны добавить автоматическую проверку всех таблиц командой myisamchk --fast --force. Обратите внимание, что, если Вы запускаете mysqld с опцией --delay-key-write-for-all-tables, это означает, что все таблицы будут обрабатываться так, как будто они были созданы с опцией delay_key_write. Вы можете очищать этот флажок, запуская mysqld с параметрами --skip-new или --safe-mode.
delayed_insert_limit
После вставки delayed_insert_limit строк, драйвер INSERT DELAYED проверит, имеется ли любая задержка инструкций SELECT. Если так, это позволяет им выполниться перед продолжением работ с таблицей.
delayed_insert_timeout
Сколько времени поток INSERT DELAYED должен ждать инструкции INSERT перед своим завершением.
delayed_queue_size
Каких размеров (в строках) очередь должна быть распределена для обработки INSERT DELAYED. Если очередь заполняется, любой пользователь, который вызвал INSERT DELAYED, будет ждать до появления свободного места в очереди.
flush
ON, если MySQL был запущен с опцией --flush.
flush_time
Если это установлено в значение, отличное от нуля, то каждые flush_time секунд все таблицы будут закрыты (чтобы освободить ресурсы и сбросить данные на диск). Я рекомендую эту опцию только на Win95, Win98 или на системах, где Вы имеете очень небольшое количество ресурсов.
have_bdb
YES, если mysqld поддерживает таблицы Berkeley DB. DISABLED, если использован параметр --skip-bdb.
have_innodb
YES, если mysqld поддерживает таблицы InnoDB. DISABLED, если использован параметр --skip-innodb.
have_raid
YES, если mysqld поддерживает опцию RAID.
have_ssl
YES, если mysqld поддерживает SSL (шифрование) по протоколу клиент/сервер.
init_file
Имя файла, определенного в параметре --init-file при запуске сервера. Это файл инструкций SQL, которые Вы хотите всегда выполнять при каждом запуске сервера.
interactive_timeout
Число секунд, которое сервер ждет действий на активном подключении перед его закрытием. Интерактивный пользователь определен как пользователь, который применяет опцию CLIENT_INTERACTIVE для mysql_real_connect(). См. также wait_timeout.
join_buffer_size
Размер буфера, который используется для полных объединений (объединения, которые не используют индексы). Буфер будет распределен один раз для каждого полного объединения между двумя таблицами. Увеличьте это значение, чтобы ускорить полное объединение, если добавление индексов невозможно. Обычно самый лучший способ получать быстрые объединения состоит в том, чтобы добавить индексы таблицы.
key_buffer_size
Индексные блоки буферизированы и разделяются всеми потоками. key_buffer_size как раз и задает размер буфера, используемого для индексных блоков. Увеличьте это значение, чтобы улучшить индексную обработку. Но если Вы сделаете его слишком большим (больше, чем 50% общей памяти?), Ваша система может начать использовать своп и стать ДЕЙСТВИТЕЛЬНО медленной. Не забудьте, что поскольку MySQL не кэширует чтение данных, Вы должны оставить некоторый участок памяти для кэша файловой системы ОС.

Вы можете проверять эффективность буфера ключей выполнением show status и изучением переменных Key_read_requests, Key_reads, Key_write_requests и Key_writes. Коэффициент Key_reads/Key_read_request обычно должен быть < 0.01. Key_write/Key_write_requests обычно близко к 1, если Вы используете обычное обновление/удаление, но может быть намного меньше, если Вы имеете тенденцию делать модификации, которые воздействуют на много данных сразу, или если Вы используете delay_key_write. Подробности в разделе "4.10 Синтаксис SHOW".

Чтобы получить заметное ускорение при записи многих строк сразу, используйте LOCK TABLES. Подробности в разделе "9.2.2 Синтаксис LOCK TABLES/UNLOCK TABLES".

language
Язык, используемый для сообщений об ошибках.
large_file_support
Если mysqld компилировался с параметрами для поддержки больших файлов.
locked_in_memory
Если mysqld был блокирован в памяти опцией --memlock
log
Если включено протоколирование всех запросов.
log_update
Регистрации всех запросов допускается.
log_bin
Файл регистрации модификации включен.
log_slave_updates
Модификации с подчиненного регистрируются.
long_query_time
Если запрос занимает больше, чем заданное здесь время (в секундах), счетчик Slow_queries будет увеличен. Если Вы используете --log-slow-queries, запрос будут регистрироваться в файле регистрации медленных запросов.
lower_case_table_names
Если установлено в 1, имена таблиц будут сохранены на диске в нижнем регистре, и они не будут чувствительны к регистру. Подробности в разделе "3.3 Чувствительность к регистру символов в именах".
max_allowed_packet
Максимальный размер одного пакета. Буфер сообщений инициализирован для размера в net_buffer_length байт, но может вырасти до max_allowed_packet байт, когда необходимо. Это значение по умолчанию маленькое, но позволяет захватывать большие (возможно, неправильные) пакеты. Вы должны увеличить это значение, если используете большие столбцы BLOB. Он должно быть столь же большим как самый крупный BLOB, который Вы хотите использовать. Текущий протокол ограничивает max_allowed_packet размером 16M.
max_binlog_cache_size
Если многооператорная транзакция требует больше, чем этот объем памяти, выйдет ошибочка "Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage".
max_binlog_size
Доступно после версии 3.23.33. Если запись в двоичный файл регистрации (для репликации) превышает данное значение, выполняется ротация файлов. Вы не можете устанавливать это значение меньше, чем в 1024 байта, или больше, чем 1 GB. Значение по умолчанию 1 GB.
max_connections
Число одновременно допущенных клиентов. Увеличение этого значения увеличивает число описателей файла, которых требует mysqld. Подробности в разделе "11.2.5 Ошибка Too many connections".
max_connect_errors
Если имеется больше, чем это число, прерванных подключений с хоста, хост будет блокирован, и никакие подключения с него станут невозможными вообще. Вы можете снова открыть хост командой FLUSH HOSTS.
max_delayed_threads
Не запускать больше, чем это число потоков, чтобы обработать инструкции INSERT DELAYED. Если Вы попробуете вставлять данные в новую таблицу после того, как все потоки INSERT DELAYED будут заняты, строка будет вставлена, как будто атрибут DELAYED не был определен вовсе, то есть немедленно.
max_heap_table_size
Не позволять создание heap-таблиц больше этого числа.
max_join_size
Объединения, которые, вероятно, собираются читать больше, чем сказано в max_join_size, возвращают ошибку. Установите это значение, если Ваши пользователи имеют тенденцию выполнять объединения, которые испытывают недостаток предложения WHERE, занимают много времени или возвращают миллионы строк.
max_sort_length
Число байтов, чтобы использовать при сортировке значений BLOB или TEXT (только первые max_sort_length байтов из каждого значения реально используются, остальное игнорируется вообще).
max_user_connections
Максимальное число активных подключений для одного пользователя (0 = нет никаких ограничений).
max_tmp_tables
Максимальное число временных таблиц, которые пользователь может хранить открытыми в один момент времени.
max_write_lock_count
После этого количества блоикоровок записи допускается выполнение между делом блокировок чтения.
myisam_recover_options
Значение параметра --myisam-recover.
myisam_sort_buffer_size
Буфер, который распределен для сортировки индекса при выполнении REPAIR или при создании индексов с помощью CREATE INDEX или ALTER TABLE.
myisam_max_extra_sort_file_size.
Если создание временного файла для быстрой генерации индекса много больше, чем использование кэша ключей. то предпочтительнее метод кэша. Это значение используется, главным образом, чтобы вынудить длинные символьные ключи в больших таблицах использовать более медленный метод создания индекса. ОБРАТИТЕ ВНИМАНИЕ, что этот параметр задан в мегабайтах!
myisam_max_sort_file_size
Максимальный размер временного файла, который MySQL позволяет использовать при освежении индекса (в течение REPAIR, ALTER TABLE или LOAD DATA INFILE. Если размер файла больше, чем это значение, индекс будет создан через кэш ключа, который является более медленным. ОБРАТИТЕ ВНИМАНИЕ, что этот параметр задан в мегабайтах!
net_buffer_length
Буфер связи будет приведен к этому размеру между запросами. Это обычно не должно изменяться, но если Вы имеете очень мало памяти, Вы можете устанавливать это значение в ожидаемый размер запроса. То есть в ожидаемую длину инструкций SQL, посланных клиентами. Если запрос превышает эту длину, буфер будет автоматически расширен до max_allowed_packet байт.
net_read_timeout
Сколько секунд ждать данные из подключения перед прерыванием чтения. Обратите внимание, что, когда мы не ожидаем данные из подключения, время ожидания определено через write_timeout. См. также slave_read_timeout.
net_retry_count
Если чтение на коммуникационном порте прервано, оно повторится несколько раз перед отменой попыток связи. Это значение должно быть очень велико на FreeBSD, поскольку там внутренние прерывания посланы всем серверным процессам чтения.
net_write_timeout
Число секунд ожидания блока, который будет записан в подключение.
open_files_limit
Если это не 0, mysqld использует это значение, чтобы резервировать описатели файла для применения с setrlimit(). Если это значение = 0, mysqld резервирует max_connections*5 или max_connections+table_cache*2 (используется большее из этих значений) число файлов. Вы должны попробовать увеличивать это значение, если mysqld выдает Вам ошибку 'Too many open files'.
pid_file
Значение параметра --pid-file.
port
Значение параметра --port.
protocol_version
Версия протокола, используемого сервером MySQL.
record_buffer
Каждый поток, который делает последовательный просмотр, распределяет буфер этого размера для каждой таблицы, которую просматривает. Если Вы делаете много последовательных просмотров, стоит увеличить это значение.
record_rnd_buffer
При чтении строк в сортируемом порядке после сортировки, строки читаются через этот буфер, чтобы избежать дисковых поисков. Если не задан, берется значение из переменной record_buffer.
query_buffer_size
Начальное распределение буфера запросов. Если большинство Ваших запросов имеет большую длину, Вы должны увеличить это!
safe_show_databases
Не показывать базы данных, для которых пользователь не имеет привилегий базы данных или таблицы. Это может улучшать защиту. См. также skip_show_databases.
server_id
Значение опции --server-id.
skip_locking
Если OFF, mysqld использует внешнюю блокировку.
skip_networking
Если ON, допустимы только локальные (сокетные) подключения.
skip_show_databases
Это предотвращает выполнение SHOW DATABASES, если пользователь не имеет привилегии PROCESS_PRIV. Это может улучшить защиту. См. также safe_show_databases.
slave_read_timeout
Число секунд, которое надлежит ждать данные из главного/подчиненного подключения перед прерыванием чтения.
slow_launch_time
Если создание потока занимает больше времени, чем это значение (в секундах), счетчик Slow_launch_threads будет увеличен.
socket
Unix-сокет, используемый сервером.
sort_buffer
Каждый поток, который должен делать сортировку, распределяет буфер этого размера. Увеличьте это значение для ускорения операций ORDER BY или GROUP BY. Подробности в разделе "11.4.4 Где MySQL хранит временные файлы".
table_cache
Число открытых таблиц для всех потоков. Увеличение этого значения увеличивает число описателей файла, которых требует mysqld. MySQL нуждается в двух описателях файла для каждой уникальной открытой таблицы. Вы можете проверять, должны ли Вы увеличить кэш таблицы, анализируя переменную Opened_tables. Подробности в разделе "4.10 Синтаксис SHOW". Удостоверьтесь, что Ваша операционная система может обрабатывать число описателей файла, подразумеваемых установкой table_cache. Если table_cache слишком велико, MySQL может исчерпать описатели файла и начать сбоить.
table_type
Тип таблицы по умолчанию.
thread_cache_size
Сколько потоков мы должны хранить в кэше для повторного использования. Когда пользователь отсоединяется, потоки пользователя будут помещены в кэш, если нет больше, чем thread_cache_size потоков. Все новые потоки сначала принимаются из кэша и только, когда кэш пуст, создаются новые. Эта переменная может увеличиваться, чтобы улучшить эффективность, если Вы имеете много новых подключений.
thread_concurrency
На Solaris mysqld вызовет thr_setconcurrency() с этим значением. thr_setconcurrency() разрешает прикладной программе давать системе управления данные относительно желательного числа потоков, которые должны быть выполнены в одно и то же время.
thread_stack
Размер стека для каждого потока. Многие из ограничений, обнаруженных тестом crash-me, зависят от этого значения. Значение по умолчанию достаточно большое для нормальной работы.
timezone
Таймзона (часовой пояс) для сервера.
tmp_table_size
Если временная таблица в памяти превышает этот размер, MySQL автоматически преобразует ее в таблицу MyISAM на диске. Увеличьте значение tmp_table_size, если Вы делаете много продвинутых запросов GROUP BY, и Вы имеете много памяти.
tmpdir
Каталог, используемый для временных файлов и таблиц.
version
Код версии сервера.
wait_timeout
Число секунд, которое сервер ждет действий на подключении перед его закрытием. См. также interactive_timeout.

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

4.10.5 Синтаксис SHOW LOGS

SHOW LOGS показывает Вам информацию относительно состояния существующих журналов. В настоящее время этот вызов отображает только информацию относительно журналов Berkeley DB.

  • File показывает полный путь к журналу.
  • Type показывает тип журнала (BDB для журналов типа Berkeley DB).
  • Status показывает состояние журнала (FREE если файл может быть удален, или IN USE если файл необходим подсистеме транзакций).

4.10.6 Синтаксис SHOW PROCESSLIST

SHOW PROCESSLIST показывает Вам, которые процессы работают. Вы можете также получать эту информацию, используя команду mysqladmin processlist. Если Вы имеете привилегию process, Вы можете видеть все процессы. Иначе Вы можете видеть только Ваши собственные процессы. Если Вы не используете опцию FULL, то только первые 100 символов каждого запроса будут показаны. Подробности в разделе "4.9 Синтаксис KILL".

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

4.10.7 Синтаксис SHOW GRANTS

SHOW GRANTS FOR user вносит в список команды, который должны быть выданы, чтобы дублировать права пользователя. Например:

mysql> SHOW GRANTS FOR root@localhost;
+---------------------------------------------------------------------+
| Grants for root@localhost                                           |
+---------------------------------------------------------------------+
| GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION |
+---------------------------------------------------------------------+

4.10.8 Синтаксис SHOW CREATE TABLE

Показывает инструкцию CREATE TABLE, которая создаст данную таблицу. Например:

mysql> show create table t\G
*************************** 1. row ***************************
       Table: t
Create Table: CREATE TABLE t (
  id int(11) default NULL auto_increment,
  s char(60) default NULL,
  PRIMARY KEY (id)
) TYPE=MyISAM

4.11 Файл опций my.cnf

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

MySQL читает заданные по умолчанию параметры из следующих файлов (в Unix):

Имя файла | Зачем он нужен
/etc/my.cnf | Глобальные опции для всех
DATADIR/my.cnf | Опции для сервера
defaults-extra-file | Файл, определенный через --defaults-extra-file=#
~/.my.cnf | Специфические для пользователей опции

DATADIR представляет собой каталог данных MySQL (обычно /usr/local/mysql/data для бинарного дистрибутива или /usr/local/var для установки из исходников). Обратите внимание, что это тот каталог, который был определен в конфигурации, а не указан в опции --datadir при запуске mysqld! Параметр --datadir не имеет никакого эффекта в то время, когда сервер ищет файлы опций потому, что он их ищет прежде, чем обрабатывает любые параметры командной строки.

MySQL читает заданные по умолчанию параметры из следующих файлов (только в ОС Windows):

Имя файла | Зачем он нужен
windows-system-directory\my.ini | Глобальные опции
C:\my.cnf | Глобальные опции
C:\mysql\data\my.cnf | Опции для сервера

Обратите внимание, что в Windows Вы должны определить все пути с / вместо \. Если Вы используете \, Вы должны определить это дважды, поскольку \ символ ESC в MySQL.

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

Следующие программы поддерживают файлы опций: mysql, mysqladmin, mysqld, mysqldump, mysqlimport, mysql.server, myisamchk и myisampack.

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

Файл опций может содержать строки следующих форм:

#comment
Строки комментария начинаются с `#' или с `;'. Пустые строки игнорируются.
[group]
group представляет собой имя программы или группы, для которой Вы хотите устанавливать параметры. После строки группы любая строка option или set-variable обращается к именованной группе, пока не будет достигнут конец файла опций или другая строка группы.
option
Эквивалентно --option в командной строке.
option=value
Эквивалентно --option=value в командной строке.
set-variable = variable=value
Эквивалентно --set-variable variable=value в командной строке. Этот синтаксис должен использоваться, чтобы установить переменную mysqld.

Группа client позволяет Вам определять параметры, которые обращаются ко всей клиентуре MySQL (но не к mysqld). Это самая подходящая группа, чтобы определить в ней пароль, который Вы используете, чтобы соединиться с сервером. Но удостоверьтесь, что файл опций читаем и перезаписываем только Вами.

Обратите внимание, что для параметров и значений все конечные и начальные пробелы автоматически удалены. Вы можете использовать управляющие последовательности \b, \t, \n, \r, \\ и \s в Вашей строке (\s==пробел).

Имеется типичный глобальный файл опций:

[client]
port=3306
socket=/tmp/mysql.sock

[mysqld]
port=3306
socket=/tmp/mysql.sock
set-variable = key_buffer_size=16M
set-variable = max_allowed_packet=1M

[mysqldump]
quick

Имеется типичный файл опций пользователя:

[client]
# The following password will be sent to all standard MySQL clients
password=my_password

[mysql]
no-auto-rehash
set-variable=connect_timeout=2

[mysqlhotcopy]
interactive-timeout

Если Вы имеете дистрибутив с исходниками, Вы найдете, что типовые файлы конфигурации называются my-xxxx.cnf в каталоге support-files. А вот в двоичном дистрибутиве смотрите в каталоге DIR/support-files, где DIR задает имя пути к каталогу установки MySQL (обычно /usr/local/mysql). В настоящее время имеются типовые файлы конфигурации для маленькой, средней, большой и очень большой системы. Вы можете копировать my-xxxx.cnf в Ваш основной каталог (переименуйте копию в .my.cnf), чтобы экспериментировать.

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

--no-defaults | Не читать любые файлы опций.
--print-defaults | Печатать имя программы и все параметры, которые ей передаются.
--defaults-file=full-path-to-default-file | Использовать только данный файл конфигурации.
--defaults-extra-file=full-path-to-default-file | Читать этот файл конфигурации после глобального файла опций, но перед чтением файла настроек пользователя.

Обратите внимание, что вышеупомянутые параметры должны быть первыми в командной строке, чтобы они работали! Однако, --print-defaults может использоваться непосредственно после команды --defaults-xxx-file.

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

shell> my_print_defaults client mysql
--port=3306
--socket=/tmp/mysql.sock
--no-auto-rehash

Вышеупомянутый вывод содержит все параметры для групп client и mysql.


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

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

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

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

M
Указывает максимальный размер отображения. Максимальный допустимый размер отображения равен 255.
D
Применяется к типам с плавающей запятой и указывает число цифр после десятичной отметки. Максимальное возможное значение равно 30, но должно быть не больше, чем M-2.

Квадратные скобки ([ и ]) указывают части спецификаторов типа, которые являются факультативными.

Обратите внимание, что, если Вы определяете для столбца ZEROFILL, MySQL автоматически добавит к столбцу атрибут UNSIGNED.

TINYINT[(M)] [UNSIGNED] [ZEROFILL]
Очень маленькое целое число. Диапазон значений со знаком от -128 до 127. Диапазон значений без знака от 0 до 255.
SMALLINT[(M)] [UNSIGNED] [ZEROFILL]
Маленькое целое число. Диапазон со знаком от -32768 до 32767. Диапазон без знака от 0 до 65535.
MEDIUMINT[(M)] [UNSIGNED] [ZEROFILL]
Целое число средних размеров. Диапазон со знаком от -8388608 до 8388607. Диапазон значений без знака от 0 до 16777215.
INT[(M)] [UNSIGNED] [ZEROFILL]
Целое число нормального размера. Диапазон значений со знаком от -2147483648 до 2147483647. Диапазон значений без знака от 0 до 4294967295.
INTEGER[(M)] [UNSIGNED] [ZEROFILL]
Синоним для INT.
BIGINT[(M)] [UNSIGNED] [ZEROFILL]
Большое целое число. Диапазон значений со знаком от -9223372036854775808 до 9223372036854775807. Диапазон значений без знака от 0 до 18446744073709551615.

Некоторые вещи, которые Вы должны знать относительно столбцов типа BIGINT:

  • Поскольку вся арифметика выполнена, используя значения типов BIGINT или DOUBLE, Вы не должны использовать большие целые числа без знака, которые имеют значение по модулю большее, чем 9223372036854775807 (63 бита) за исключением битовых функций! Если Вы это сделаете, некоторые из последних цифр в результате могут быть ошибочными из-за округления при преобразовании BIGINT в DOUBLE.
  • Вы можете всегда сохранять точное целочисленное значение в столбце BIGINT, сохраняя его как строку, в этом случае не будет никакого промежуточного двойного представления.
  • В MySQL 4.0 Вы можете использовать целые числа, чтобы сохранить большие значения без знака в строках BIGINT.
  • -, + и * используют арифметику BIGINT, когда оба параметра представляют собой значения типа INTEGER. Это означает, что, если Вы умножаете два больших целых числа (или результаты функций, которые возвращают целые числа), Вы можете получить непредвиденные эффекты, когда результат больше, чем 9223372036854775807.
FLOAT(precision) [ZEROFILL]
Число с плавающей запятой. Не может быть без знака. Точность (precision) может быть в пределах <=24, для числа с одиночной точностью, или между 25 и 53, для числа двойной точности. Эти типы подобны FLOAT и DOUBLE, описанным ниже. FLOAT(X) имеет тот же самый диапазон, что и соответствующие типы FLOAT и DOUBLE, но размер отображения и число десятичных чисел неопределенны. В MySQL Version 3.23 это и есть истинное значение с плавающей запятой. В старых версиях MySQL FLOAT(precision) всегда имеет 2 десятичных числа. Обратите внимание, что использование типа FLOAT может создавать Вам некоторые непредвиденные проблемы, поскольку все вычисления в MySQL всегда выполнены с двойной точностью. Этот синтаксис предусмотрен для ODBC-совместимости.
FLOAT[(M,D)] [ZEROFILL]
Маленькое (с одиночной точностью) число с плавающей запятой. Не может быть без знака. Допустимые значения от -3.402823466E+38 до -1.175494351E-38, 0 и от 1.175494351E-38 до 3.402823466E+38. M задает размер отображения, а D число десятичных чисел. Соответствует FLOAT(X), где X <= 24.
DOUBLE[(M,D)] [ZEROFILL]
Число нормального размера (двойная точность) с плавающей запятой. Не может быть без знака. Допустимые значения от -1.7976931348623157E+308 до -2.2250738585072014E-308, 0 и от 2.2250738585072014E-308 до 1.7976931348623157E+308. M задает размер отображения, а D число десятичных чисел. Соответствует DOUBLE без параметра или FLOAT(X), где 25 <= X <= 53.
DOUBLE PRECISION[(M,D)] [ZEROFILL]
REAL[(M,D)] [ZEROFILL]
Синонимы для DOUBLE.
DECIMAL[(M[,D])] [ZEROFILL]
Распакованное число с плавающей запятой. Не может быть без знака. Ведет себя подобно столбцу CHAR: "распакованный" означает, что число сохранено как строка, используя один символ для каждой цифры значения. Десятичная отметка и, для отрицательных чисел, знак - не рассчитана в M (но пробел для них зарезервирован). Если D=0, значения не будут иметь никакой десятичной отметки или дробной части. Максимальный диапазон значений DECIMAL аналогичен DOUBLE, но фактический диапазон для данного столбца DECIMAL может быть задан через M и D. Если D не задано, оно будет установлено в 0. Если же не задано M, оно считается равным 10. Обратите внимание, что в MySQL Version 3.22 аргумент M должен включать пробел, необходимый для знака и десятичной отметки.
NUMERIC(M,D) [ZEROFILL]
Синоним для DECIMAL.
DATE
Дата. Поддерживаемый диапазон: от 1000-01-01 до 9999-12-31. MySQL отображает значения DATE в формате YYYY-MM-DD, но позволяет Вам назначать значения столбцам DATE используя строки или числа.
DATETIME
Комбинация даты и времени. Поддерживаемый диапазон: от 1000-01-01 00:00:00 до 9999-12-31 23:59:59. MySQL отображает значения типа DATETIME в формате YYYY-MM-DD HH:MM:SS, но позволяет Вам назначать значения столбцам DATETIME, используя строки или числа.
TIMESTAMP[(M)]
Метка времени. Поддерживаемый диапазон: от 1970-01-01 00:00:00 примерно до 2037. MySQL отображает значения типа TIMESTAMP в форматах YYYYMMDDHHMMSS, YYMMDDHHMMSS, YYYYMMDD или YYMMDD, в зависмости от значения M: 14 (или пропущено), 12, 8 или 6, но позволяет Вам задавать значения столбцам TIMESTAMP, используя строки или числа. Столбец TIMESTAMP полезен для записи даты и времени операции INSERT или UPDATE потому, что он будет автоматически установлен к дате и времени самой последней операции, если Вы не задаете значение самостоятельно. Вы можете также устанавливать его к текущей дате и времени, назначая значение NULL. TIMESTAMP всегда сохраняется в 4 байтах. Параметр M воздействует только на то, как отображается столбец TIMESTAMP. Обратите внимание, что столбцы TIMESTAMP(X) при X, равном 8 или 14, являются числами, в то время как другие столбцы TIMESTAMP(X) представляют собой строки! Это только должно гарантировать, что можно надежно сбросить таблицу в дамп, а потом восстанавливать ее с этими типами!
TIME
Время. Поддерживаемый диапазон: от -838:59:59 до 838:59:59. MySQL отображает значения типа TIME в формате HH:MM:SS, но позволяет Вам задавать значения столбцам TIME, используя строки или числа.
YEAR[(2|4)]
Год с двумя или четыремя цифрами (по умолчанию задано 4). Допустимые значения: от 1901 до 2155, 0000 в формате года с 4 цифрами, и 1970-2069, если Вы используете формат с 2 цифрами (70-69). MySQL отображают значения YEAR в формате YYYY, но позволяет Вам указывать значения столбцам типа YEAR, используя строки или числа. Впервые тип YEAR появился в MySQL Version 3.22.
[NATIONAL] CHAR(M) [BINARY]
Строка фиксированной длины, которая всегда дополняется справа пробелами до определенной длины. Диапазон M от 1 до 255 символов. Конечные пробелы будут удалены, когда значение извлекается из таблицы. Переменные CHAR сортируются и сравниваются без учета регистра согласно заданному по умолчанию набору символов, если не задано ключевое слово BINARY. NATIONAL CHAR (короткая форма NCHAR) представляет собой взятый из ANSI SQL способ определить, что столбец CHAR должен использовать заданный набор символов CHARACTER. Это значение по умолчанию в MySQL. CHAR является сокращением для CHARACTER. MySQL позволяет Вам создавать столбец типа CHAR(0). Это главным образом полезно, когда Вы должны обеспечить совместимость с некоторыми старыми прикладными программами, которые зависят от существования столбца, но фактически не использует значение. Это также очень удобно, когда Вы нуждаетесь в столбце, который может брать только 2 значения: CHAR(0), который не определен как NOT NULL, займет всего лишь один бит и может принимать только 2 значения: NULL или "".
[NATIONAL] VARCHAR(M) [BINARY]
Строка переменной длины. A variable-length string. ОБРАТИТЕ ВНИМАНИЕ: Конечные пробелы будут автоматически удалены, когда значение сохранено (это отличается от спецификаций ANSI SQL). Диапазон M от 1 до 255 символов. Значения типа VARCHAR сортируются и сравниваются без учета регистра согласно заданному по умолчанию набору символов, если не задано ключевое слово BINARY. VARCHAR является сокращением для CHARACTER VARYING.
TINYBLOB
TINYTEXT
Столбцы BLOB или TEXT имеют максимальную длину в 255 (2^8-1) символов.
BLOB
TEXT
Столбцы BLOB или TEXT имеют максимальную длину в 65535 (2^16-1) символов.
MEDIUMBLOB
MEDIUMTEXT
Столбцы MEDIUMBLOB или MEDIUMTEXT имеют максимальную длину в 16777215 (2^24-1) символов.
LONGBLOB
LONGTEXT
Столбцы LONGBLOB или LONGTEXT имеют максимальную длину в 4294967295 (2^32-1) символов. Обратите внимание, что поскольку протокол клиент-сервер и таблицы MyISAM имеет в настоящее время ограничение в 16M на пакет связи/строку таблицы, Вы не можете использовать весь диапазон этого типа.
ENUM('value1','value2',...)
Перечисление. Строковый объект, который может иметь только одно значение, выбранное из списка значений value1, value2, ..., NULL или специальное значение ошибки "". ENUM может иметь максимум 65535 разных значений.
SET('value1','value2',...)
Множество. Строковый объект, который может иметь ноль или больше значений, каждое из которых должно быть выбрано из списка значений value1, value2, .... SET может иметь максимум 64 члена.

5.1 Числовые типы

MySQL поддерживает все числовые типы ANSI/ISO SQL92. Эти типы включают точные числовые типы данных (NUMERIC, DECIMAL, INTEGER и SMALLINT), а также приблизительные числовые типы данных (FLOAT, REAL и DOUBLE PRECISION). Ключевое слово INT представляет собой синоним для INTEGER, а ключевое слово DEC является синонимом для DECIMAL.

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

   salary DECIMAL(9,2)

В этом примере 9 (точность, precision) представляет число значащих десятичных цифр, которые будут сохранены для значений, а 2 (масштаб, scale) представляет число цифр, которые будут сохранены после десятичной отметки. В этом случае, следовательно, диапазон значений, которые могут быть сохранены в столбце salary от -9999999.99 до 9999999.99. (MySQL может фактически сохранять числа до 9999999.99 в этом столбце потому, что не требуется сохранять знак для положительных чисел).

В ANSI/ISO SQL92 синтаксис DECIMAL(p) эквивалентен DECIMAL(p,0). Точно так же синтаксис DECIMAL является эквивалентным DECIMAL(p,0), где реализации позволяют менять значение p. MySQL в настоящее время не поддерживает никакую из этих различных форм типов данных DECIMAL/NUMERIC. Это не серьезная проблема, поскольку принципиальные выгоды этих типов происходят от способности управлять точностью и масштабом явно.

Значения типов DECIMAL и NUMERIC сохранены как строки, в не как двоичные числа с плавающей запятой, чтобы сохранить десятичную точность значений. Один символ используется для каждой цифры значения, десятичной отметки (если scale > 0) и знака - (для отрицательных чисел). Если scale равен 0, значения DECIMAL и NUMERIC не содержат никакой десятичной отметки или дробной части.

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

MySQL поддерживает как расширение стандарта ANSI/ISO SQL92 встроенные типы TINYINT, MEDIUMINT и BIGINT как перечислено в таблицах выше. Другое расширение поддержано MySQL для факультативного определения ширины отображения значения в круглых скобках после основного ключевого слова для типа (например, INT(4)). Эта факультативная спецификация ширины используется для вывода значений, чья ширина меньше, чем ширина, определенная для столбца, но не сдерживает диапазон значений, которые могут быть сохранены в столбце, или число цифр, которые будут отображаться для значений, чья ширина превышает заданную. Когда используется вместе с факультативным атрибутом расширения ZEROFILL, дополнение значения по умолчанию пробелами заменено на нули. Например, для столбца, объявленного как INT(5) ZEROFILL, значение 4 превратится в 00004. Обратите внимание, что, если Вы сохраняете значения большие, чем ширина отображения в целочисленном столбце, Вы можете испытывать проблемы, когда MySQL генерирует временные таблицы для некоторых сложных объединений, поскольку в этих случаях MySQL полагает, что данные вписывались в первоначальную ширину столбца.

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

Тип FLOAT используется, чтобы представить приблизительные числовые типы данных. Стандарт ANSI/ISO SQL92 позволяет факультативную спецификацию точности (но не диапазон образца) в битах после ключевого слова FLOAT в круглых скобках. MySQL-реализация также поддерживает эту факультативную спецификацию точности. Когда ключевое слово FLOAT используется для типа столбца без спецификации точности, MySQL применяет четыре байта, чтобы сохранить значения. Различный синтаксис также поддержан, с двумя числами, заданными в круглых скобках после ключевого слова FLOAT. С этой опцией первое число продолжает представлять требования к памяти для значения в байтах, а второе определяет число цифр, которые будут сохранены и отображаться после десятичной отметки (как с DECIMAL и NUMERIC). Когда MySQL нужно сохранить число для такого столбца с большим количеством цифр после десятичной отметки, чем определено для столбца, значение будет автоматически округлено, чтобы устранить лишние цифры.

Типы REAL и DOUBLE PRECISION не принимают спецификации точности. В качестве дополнения к стандарту ANSI/ISO SQL92 MySQL распознает DOUBLE как синоним для DOUBLE PRECISION. В отличие от требования стандарта, чтобы точность для REAL была меньшие, чем используемая для DOUBLE PRECISION, MySQL реализует то и другое как 8-байтные double-precision floating-point значения (при работе не в ANSI mode). Для максимальной мобильности код, требующий хранение приблизительных числовых значений данных должен использовать FLOAT или DOUBLE PRECISION без спецификации точности или количества чисел после десятичной точки.

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

Например, диапазон столбца INT от -2147483648 до 2147483647. Если Вы пробуете вставлять -9999999999 в столбец типа INT, значение будет усечено к нижей границе диапазона и сохранено -2147483648. Точно так же, если Вы пробуете вставлять 9999999999, вместо этого будет сохранено 2147483647.

Если столбец INT определен как UNSIGNED, размер диапазона столбца тот же самый, но произойдет сдвиг значений на 0 и 4294967295. Если Вы пробуете сохранять -9999999999 и 9999999999, значения, сохраненные в столбце, станут соответственно 0 и 4294967296.

Преобразования, которые происходят из-за усечения, сообщаются как ``warnings'' для инструкций ALTER TABLE, LOAD DATA INFILE, UPDATE и многострочного варианта INSERT.

5.2 Типы Date и Time

Типы даты и времени: DATETIME, DATE, TIMESTAMP, TIME и YEAR. Каждый из них имеет диапазон допустимых значений, также как и некий ноль, который используется, когда Вы определяете, действительно, запрещенное значение. Обратите внимание, что MySQL позволяет Вам сохранять некоторые недопустимые значения даты, например, 1999-11-31. Причина этого в том, что обрабатывать проверку даты ответственность прикладной программы, а не сервера SQL. Чтобы сделать проверку даты быстрой, MySQL проверяет только то, что месяц находится в диапазоне 0-12, и день находится в диапазоне 0-31. Вышеупомянутые диапазоны определены так потому, что MySQL позволяет Вам сохранять в столбцах DATE или DATETIME даты, где день или месяц нулевой. Это чрезвычайно полезно для прикладных программ, которые должны сохранить дату рождения, для которой Вы не знаете точную дату. В этом случае Вы просто сохраняете дату подобно 1999-00-00 или 1999-01-00. Вы, конечно, не можете получать правильное значение из функций, подобных DATE_SUB() или DATE_ADD, для таких неправильных дат.

Имеются некоторые общие вещи, которые стоит иметь в виду при работе с типами даты и времени:

  • MySQL возвращает значения для данного типа в стандартном формате, но пытается интерпретировать ряд форматов для значений, которые Вы обеспечиваете (например, когда Вы определяете значение, которое будет назначено переменной или сравниваться). Однако, поддержаны только форматы, описанные в следующих разделах. Ожидается, что Вы обеспечите допустимые значения, и непредсказуемые результаты могут быть получены, если Вы используете значения в других форматах.
  • Хотя MySQL пробует интерпретировать значения в нескольких форматах, он всегда ожидает, что часть, определяющая год, стоит на крайнем слева месте. Даты должны быть даны в порядке год-месяц-день (например, 98-09-04).
  • MySQL автоматически преобразует значения даты и времени в числа, если значение используется в числовом контексте, и наоборот.
  • Когда MySQL сталкивается со значением, которое находится вне диапазона или иначе запрещено для типа, он устанавливает значение в ноль для этого типа. Исключительная ситуация: вышедшие за границу диапазона значения TIME урезаются до соответствующей границы. Таблица ниже показывает нулевые значения каждого типа:
    Тип столбца | Нулевое значение
    DATETIME | '0000-00-00 00:00:00'
    DATE | '0000-00-00'
    TIMESTAMP | 00000000000000 (длина зависит от размера отображения)
    TIME | '00:00:00'
    YEAR | 0000
  • Нулевое значение специально, но Вы можете сохранять или обращаться к ним, явно используя значения, показанные в таблице. Вы можете также делать это, применяя значения '0' или 0.
  • Нулевые значения даты и времени, используемые через MyODBC, будут преобразованы автоматически в NULL в MyODBC Version 2.50.12 и выше потому, что ODBC не может обрабатывать такие значения.

5.2.1 Проблема Y2K и типы Date

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

Для типов DATETIME, DATE, TIMESTAMP и YEAR MySQL интерпретирует даты с неоднозначным годом так:

  • Значения года в диапазоне 00-69 будут преобразованы в 2000-2069.
  • Значения года в диапазоне 70-99 будут преобразованы в 1970-1999.

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

ORDER BY сортирует значения типов YEAR/DATE/DATETIME с 2 цифрами правильно.

Обратите внимание также, что некоторые функции, подобно MIN() и MAX(), преобразуют TIMESTAMP/DATE в число. Это означает, что timestamp с годом с 2 цифрами не будет работать правильно с этими функциями. Исправление в этом случае должно преобразовать TIMESTAMP/DATE к формату года с 4 цифрами или использовать нечто вроде MIN(DATE_ADD(timestamp,INTERVAL 0 DAYS)).

5.2.2 Типы DATETIME, DATE и TIMESTAMP

Типы DATETIME, DATE и TIMESTAMP связаны. Этот раздел описывает их характеристики и чем они отличаются.

Тип DATETIME используется, когда Вы нуждаетесь в значениях, которые содержат информацию о дате и времени. MySQL получает и отображает значения DATETIME в формате YYYY-MM-DD HH:MM:SS. Поддерживаемый диапазон от 1000-01-01 00:00:00 до 9999-12-31 23:59:59.

Тип DATE используется, когда Вы нуждаетесь только в значении даты, без части времени. MySQL получает и отображает значения DATE в формате YYYY-MM-DD. Поддерживаемый диапазон от 1000-01-01 до 9999-12-31.

Тип столбца TIMESTAMP обеспечивает тип, который Вы можете использовать, чтобы автоматически отметить операции INSERT или UPDATE текущей датой и временем. Если Вы имеете много столбцов типа TIMESTAMP, только первый модифицируется автоматически.

Автоматическое модифицирование первого столбца TIMESTAMP происходит при любом из условий:

  • Столбец не определен явно в инструкции INSERT или LOAD DATA INFILE.
  • Столбец не определен явно в инструкции UPDATE и некотором другом значении изменений столбца. Обратите внимание, что UPDATE, который устанавливает столбец к значению, которое тот уже имеет, не будет заставлять столбец типа TIMESTAMP модифицироваться потому, что, если Вы устанавливаете столбец к текущему значению, MySQL игнорирует модификацию для эффективности.
  • Вы явно устанавливаете столбец типа TIMESTAMP в NULL.

Второй и последующие столбцы типа TIMESTAMP также могут быть установлены к текущей дате и времени. Только установите столбец в NULL или в NOW().

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

  • Позвольте MySQL устанавливать столбец, когда строка создана. Это инициализирует переменную и установит ее в текущую дату и время.
  • Когда Вы выполняете последующие модификации к другим столбцам в строке, установите столбец TIMESTAMP явно в текущее значение.

Значения TIMESTAMP имеют точность в одну секунду. Значения отображаются как числа.

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

Тип столбца | Формат отображения
TIMESTAMP(14) | YYYYMMDDHHMMSS
TIMESTAMP(12) | YYMMDDHHMMSS
TIMESTAMP(10) | YYMMDDHHMM
TIMESTAMP(8) | YYYYMMDD
TIMESTAMP(6) | YYMMDD
TIMESTAMP(4) | YYMM
TIMESTAMP(2) | YY

Все столбцы типа TIMESTAMP имеют тот же самый размер памяти, независимо от размера отображения. Наиболее распространенные размеры: 6, 8, 12 и 14. Вы можете определять произвольный размер при создании таблицы, но значения 0 или больше, чем 14, будут установлены в 14. Нечетные размеры в диапазоне от 1 до 13 будут приведены к следующему четному числу.

Вы можете определять значения DATETIME, DATE и TIMESTAMP, использующие любой из общего набора форматов:

  • Строка в формате YYYY-MM-DD HH:MM:SS или YY-MM-DD HH:MM:SS. Облегченный синтаксис позволяется: любой символ пунктуации может использоваться как разделитель между частями даты или частями времени. Например, 98-12-31 11:30:45, 98.12.31 11+30+45, 98/12/31 11*30*45 и 98@12@31 11^30^45 равны.
  • Строка в формате YYYY-MM-DD или YY-MM-DD. Облегченный синтаксис позволяется и здесь: например, строки 98-12-31, 98.12.31, 98/12/31 и 98@12@31 являются эквивалентными.
  • Строка без разделителей в формате YYYYMMDDHHMMSS или YYMMDDHHMMSS, при условии, что строка имеет смысл как дата. Например, 19970523091528 и 970523091528 интерпретируются как 1997-05-23 09:15:28, но 971122129015 запрещен (это имеет неправильную минутную часть) и становится 0000-00-00 00:00:00.
  • Строка без разделителей в формате YYYYMMDD или YYMMDD, при условии, что строка имеет смысл как дата. Например, 19970523 и 970523 интерпретируются как 1997-05-23, но 971332 запрещен (это имеет неправильную часть месяца) и становится 0000-00-00.
  • Число в формате YYYYMMDDHHMMSS или YYMMDDHHMMSS, при условии, что число имеет смысл как дата. Например, 19830905132800 и 830905132800 интерпретируются как 1983-09-05 13:28:00.
  • Число в формате YYYYMMDD или YYMMDD при условии, что число имеет смысл как дата. Например, 19830905 и 830905 интерпретируются как 1983-09-05.
  • Результат функции, которая возвращает значение которое является приемлемым в контексте DATETIME, DATE или TIMESTAMP, типа NOW() или CURRENT_DATE.

Запрещенные значения DATETIME, DATE или TIMESTAMP преобразованы в нулевое значение соответствующего типа (0000-00-00 00:00:00, 0000-00-00 или 00000000000000).

Для значений, определенных как строки, которые включают разделители частей даты, не требуется определять две цифры для значений месяца или дня, которые являются меньше, чем 10. 1979-6-9 эквивалентно 1979-06-09. Точно так же для значений, определенных как строки, которые включают разделители части времени, необязательно определять две цифры для значений часа, минут или секунды, которые меньше, чем 10. 1979-10-30 1:2:3 то же самое, что и 1979-10-30 01:02:03.

Значения, определенные как числа, должны быть длиной в 6, 8, 12 или 14 цифр. Если число длиной в 8 или 14 цифр, считается, что оно в формате YYYYMMDD или YYYYMMDDHHMMSS, и что год задан первыми 4 цифрами. Если число длиной в 6 или 12 цифр, считается, что оно в формате YYMMDD или YYMMDDHHMMSS, и что год задан первыми 2 цифрами. Числа, которые не соответствуют этим длинам, дополняются нулями до самой близкой длины.

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

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

  • Всегда определяйте год, месяц и день, даже если Ваш тип столбца TIMESTAMP(4) или TIMESTAMP(2). Иначе, значение не будет допустимой датой, и будет сохранен 0.
  • Если Вы используете ALTER TABLE, чтобы расширить узкий столбец TIMESTAMP, будет отображаться та информация, которая раньше была скрыта.
  • Точно так же сужение столбца TIMESTAMP не уничтожит информацию, просто меньшее количество информации будет показываться, когда значения столбца отображаются.
  • Хотя значения TIMESTAMP сохранены в полной точности, единственная функция, которая функционирует непосредственно на основном сохраненном значении, это UNIX_TIMESTAMP(). Другие функции имеют дело с форматируемым значением. Вы не можете использовать функции типа HOUR() или SECOND(), если релевантная часть значения TIMESTAMP не включена в форматируемое значение. Например, часть HH столбца TIMESTAMP не отображается, если размер отображения меньше 10.

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

  • Если Вы назначаете значение DATE объекту DATETIME или TIMESTAMP, часть времени возникающего в результате значения будет установлена в 00:00:00 потому, что значение DATE не содержит информацию для времени.
  • Если Вы назначаете значение DATETIME или TIMESTAMP объекту a DATE, часть времени возникающего в результате значения удалена потому, что тип DATE не сохраняет информацию о времени.
  • Не забудьте, что, хотя DATETIME, DATE и TIMESTAMP могут быть определены, используя тот же самый набор форматов, они имеют разный диапазон значений. Например, TIMESTAMP не могут быть ранее, чем 1970, или позже, чем 2037. Это означает, что дата типа 1968-01-01, которая вполне нормальна для DATETIME или DATE, недопустима для переменной типа TIMESTAMP и превратится в 0.

Знайте некоторые ловушки при определении значений даты:

  • Ослабленный формат, позволенный для значений, определенных как строки, может обманывать. Например, значение типа 10:11:12 могло бы напоминать значение времени из-за разделителя :, но если оно используется в контексте даты будет интерпретироваться как год 2010-11-12. Значение 10:45:15 будет преобразовано в 0000-00-00 потому, что 45 недопустимый месяц.
  • Значения года, определенные как две цифры, неоднозначны потому, что столетие неизвестно. MySQL интерпретирует их так:
    • Значения года в диапазоне 00-69 преобразованы в 2000-2069.
    • Значения года в диапазоне 70-99 преобразованы в 1970-1999.

5.2.3 Тип TIME

MySQL получает и отображает значения TIME в формате HH:MM:SS (или HHH:MM:SS для больших значений часов). Значения TIME могут располагаться в диапазоне от -838:59:59 до 838:59:59. Причина того, что часть часов может быть настолько большой в том, что тип TIME может использоваться не только, чтобы представить время дня (которое должно быть меньше, чем 24 часа), но также и прошедшее время или интервал времени между двумя событиями (который может быть намного больше, чем 24 часа).

Вы можете определять значения TIME разными способами:

  • Как строку в формате D HH:MM:SS.fraction. Обратите внимание, что MySQL все же не сохраняет дробную часть для столбца времени. Можно также использовать один из следующих ослабленных синтаксисов: HH:MM:SS.fraction, HH:MM:SS, HH:MM, D HH:MM:SS, D HH:MM, D HH или SS. Здесь под D понимаются дни в пределах 0-33.
  • Как строку без разделителей в формате HHMMSS, при условии, что это имеет смысл как время. Например, 101112 допустимо и будет воспринято как 10:11:12, но 109712 из-за неправильной минутной части превратится в 00:00:00.
  • Как число в фромате HHMMSS, при условии, что это имеет смысл как время. Например, 101112 допустимо и будет воспринято как 10:11:12. Следующие альтернативные форматы также будут поняты: SS, MMSS, HHMMSS, HHMMSS.fraction. Обратите внимание, что MySQL все же не сохраняет дробную часть.
  • Как результат функции, которая возвращает значение, которое является приемлемым в контексте TIME, например, CURRENT_TIME.

Для значений TIME, определенных как строки, которые включают разделитель частей времени, необязательно задавать две цифры для часов, минут или секунд, которые меньше 10. Указание 8:3:2 аналогично 08:03:02.

Будьте внимательны относительно назначения коротких значений TIME. Без точки с запятой MySQL интерпретирует значения, используя предположение, что крайние справа цифры представляют секунды. MySQL интерпретирует значения TIME как прошедшее время, а не время дня. Например, Вы могли задавать 1112 и 1112 как 11:12:00, но MySQL поймет это как 00:11:12. Точно так же 12 и 12 интерпретируются как 00:00:12. Значения TIME с точкой с запятой вместо этого, всегда обрабатываются как время дня. Так 11:12 будет означать 11:12:00, но не 00:11:12.

Значения, которые находятся вне диапазона TIME, но допустимы во всем остальном, будут усечены до соответствующей границы диапазона. Например, -850:00:00 и 850:00:00 превратятся в -838:59:59 и 838:59:59.

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

5.2.4 Тип YEAR

Тип YEAR представляет собой тип с 1 байтом, используемый для представления лет.

MySQL получает и отображает значения типа YEAR в формате YYYY. Диапазон: от 1901 до 2155.

Вы можете определять значения YEAR в форматах:

  • Как строка с четырьмя цифрами в диапазоне от 1901 до 2155.
  • Как число с четырьмя цифрами в диапазоне от 1901 до 2155.
  • Как строка с двумя цифрами в диапазоне от 00 до 99. Значения в диапазонах от 00 до 69 и от 70 до 99 будут преобразованы в значения YEAR в диапазонах от 2000 до 2069 и от 1970 до 1999.
  • Как число с двумя цифрами в диапазоне от 1 до 99. Значения в диапазонах от 1 до 69 и от 70 до 99 будут преобразованы в значения YEAR в диапазонах от 2001 до 2069 и от 1970 до 1999. Обратите внимание, что диапазон для чисел с двумя цифрами немного иной, чем для строк с двумя цифрами потому, что Вы не можете определять ноль непосредственно как число. Вы должны определить это как строку 0 (или 00), или это будет интерпретироваться как 0000.
  • Как результат функции, возвращающей значение, которое является приемлемым в контексте YEAR, например, NOW().

Запрещенные значения YEAR будут преобразованы в 0000.

5.3 Строковые типы

Строковыми считаются типы: CHAR, VARCHAR, BLOB, TEXT, ENUM и SET. Этот раздел описывает как работу типов, их требования к памяти и как использовать их в Ваших запросах. Сразу следует отметить, что к строковым причислены типы, которые в разных языках программирования таковыми не являются, например, ENUM и SET.

5.3.1 Типы CHAR и VARCHAR

Типы CHAR и VARCHAR подобны, но отличаются способом их хранения и получения.

Длина столбца CHAR фиксирована и задается, когда Вы создаете таблицу. Длина может быть любым значением между 1 и 255. В MySQL Version 3.23 длина CHAR может быть от 0 до 255. Когда значения CHAR сохраняются в таблице, они дополняются справа пробелами до нужной длины. Когда значения CHAR получены, конечные пробелы будут автоматически удалены.

Значения в столбцах VARCHAR представляют собой строки переменной длины. Вы можете объявлять, что столбец VARCHAR будет любой длины между 1 и 255, точно как для столбцов типа CHAR. Однако, в отличие от CHAR, значения VARCHAR сохранены, используя ровно столько символов, сколько надо, плюс один байт, чтобы записать длину (аналог типа String в языке Pascal). Значения не дополняются, вместо этого конечные пробелы будут удалены, когда значения сохранены в таблице. Это удаление пробелов отличается от спецификации ANSI SQL, там они остаются.

Если Вы назначаете значение столбцу CHAR или VARCHAR, которое превышает максимальную длину столбца, значение будет усечено, чтобы поместиться в столбец.

Таблица ниже иллюстрирует различия между двумя типами столбцов, показывая результат сохранения различных значений в CHAR(4) и VARCHAR(4):

Значение | CHAR(4) | Для хранения надо | VARCHAR(4) | Для хранения надо
'' | ' ' | 4 байта | '' | 1 байт
'ab' | 'ab ' | 4 байта | 'ab' | 3 байта
'abcd' | 'abcd' | 4 байта | 'abcd' | 5 байт
'abcdefgh' | 'abcd' | 4 байта | 'abcd' | 5 байт

Значения, полученные из столбцов CHAR(4) и VARCHAR(4), будут те же самые в каждом случае потому, что конечные пробелы удалены из столбцов CHAR после поиска.

Значения в столбцах CHAR и VARCHAR сортируются и сравниваются без учета регистра, если атрибут BINARY не был определен, когда таблица была создана. Атрибут BINARY означает, что значения столбца сортируются и сравниваются с учетом регистра согласно порядку символов серверной (не клиентской!) машины MySQL. BINARY не воздействует на то, как столбец будет сохранен или получен.

Атрибут BINARY липкий. Это означает, что, если столбец, отмеченный как BINARY, используется в выражении, все выражение сравнивается как значение BINARY.

MySQL может тихо изменять тип столбца CHAR или VARCHAR при создании таблицы. Подробности в разделе "7.3.1 Тихие изменения спецификации столбца".

5.3.2 Типы BLOB и TEXT

BLOB представляет собой двоичный большой объект, который может хранить переменное количество данных. Есть четыре типа BLOB'ов: TINYBLOB, BLOB, MEDIUMBLOB и LONGBLOB, отличающиеся только по максимальной длине значений, которые они могут хранить.

Четыре типа TEXT: TINYTEXT, TEXT, MEDIUMTEXT и LONGTEXT соответствуют четырем типам BLOB и имеют те же самые максимальные длины и требования к памяти. Единственное различие между типами BLOB и TEXT в том, что сортировка выполняется с учетом регистра для значений типа BLOB и без учета регистра для TEXT.

Если Вы назначаете значение столбцу BLOB или TEXT, которое превышает максимальную длину для типа столбца, значение будет усечено, чтобы поместиться.

В большинстве случаев Вы можете расценивать столбец TEXT как VARCHAR, который может быть столь большим, как Вы хотите. Точно так же Вы можете расценивать столбец BLOB как VARCHAR BINARY. Различия в том, что:

  • Вы можете иметь индексы на столбцах BLOB и TEXT, начиная с MySQL Version 3.23.2 и выше. Старые версии MySQL не поддерживали это.
  • Не имеется никакого удаления пробелов для BLOB и TEXT, когда значения сохранены, в противоположность VARCHAR.
  • Столбцы типов BLOB и TEXT не могут иметь значений DEFAULT.

MyODBC определяет значения BLOB как LONGVARBINARY, а значения типа TEXT как LONGVARCHAR.

Поскольку значения BLOB и TEXT могут быть чрезвычайно длинными, Вы можете столкнуться с ограничениями при использовании:

  • Если Вы хотите использовать GROUP BY или ORDER BY на столбце типа BLOB или TEXT, Вы должны преобразовать значение столбца в объект фиксированной длины. Стандартный способ сделать это: функция SUBSTRING, например:
    mysql> select comment from tbl_name,substring(comment,20) as substr
                  ORDER BY substr;
    Если Вы не сделаете это, только первые max_sort_length байт столбца используются при сортировке. Значение по умолчанию для max_sort_length равно 1024, это значение может быть изменено, используя опцию -O при запуске сервера mysqld. Вы можете группировать на выражении, включающем значения BLOB или TEXT, определяя позицию столбца или используя псевдоним:
    mysql> select id,substring(blob_col,1,100) from tbl_name
           GROUP BY 2;
mysql> select id,substring(blob_col,1,100) as b from tbl_name
           GROUP BY b;
  • Максимальный размер объекта BLOB или TEXT определен типом, но самое большое значение, которое Вы можете фактически передать между клиентом и сервером, зависит от количества доступной памяти и размера буферов связей. Вы можете изменять размер буфера сообщения, но Вы должны сделать это на клиенте и на сервере.

Обратите внимание, что каждое значение BLOB или TEXT внутренне представляется отдельно распределенным объектом. Это отличие от всех других типов столбца, для которых память распределена один раз на столбец, когда таблица открывается.

5.3.3 Тип ENUM

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

Значение может также быть пустой строкой ("") или NULL при некоторых обстоятельствах:

  • Если Вы вставляете недопустимое значение в ENUM (то есть, строку, которая не указана в перечне допустимых значений), взамен будет вставлена пустая строка как специальное значение ошибки. Эта строка может отличаться от нормальной пустой строки тем фактом, что эта имеет числовое значение 0. Подробнее относительно этого позже...
  • Если ENUM объявлен как NULL, то NULL также допустимое значение для столбца, и значением по умолчанию как раз и будет именно NULL. Если ENUM объявлен как NOT NULL, значением по умолчанию будет первый элемент из списка дозволенных значений.

Каждое значение перечисления имеет индекс:

  • Значения из списка допустимых элементов в спецификации столбца пронумерованы, начиная с 1.
  • Индексное значение пустого значения ошибки 0. Это означает, что Вы можете использовать следующую инструкцию SELECT, чтобы найти строки, в которых были установлены недопустимые для ENUM значения:
    mysql> SELECT * FROM tbl_name WHERE enum_col=0;
  • Индексом значения NULL является само NULL.

Например, столбец, определенный как ENUM("one","two","three"), может иметь любое из значений, показанных ниже. Индекс каждого значения также показывается:

Значение | Индекс
NULL | NULL
"" | 0
"one" | 1
"two" | 2
"three" | 3

Перечисление может иметь максимум 65535 элементов.

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

Если Вы получаете ENUM в числовом контексте, будет возвращен индекс значения столбца. Например, Вы можете получать числовые значения из столбца ENUM подобно этому:

mysql> SELECT enum_col+0 FROM tbl_name;

Если Вы сохраняете число в ENUM, он обрабатывается как индекс, и сохраненное значение представляет собой член перечисления с этим индексом. Однако, это не будет работать с вызовом LOAD DATA, который обрабатывает весь свой ввод как строки.

Значения ENUM сортируются согласно порядку, в котором члены перечисления были указаны в спецификации столбца. Другими словами, значения ENUM сортируются согласно их индексным числам. Например, "a" окажется перед "b" для ENUM("a","b"), но "b" опередит "a" для ENUM("b", "a"). Пустые строки окажутся перед непустыми строками, а значения NULL перед всеми другими значениями перечисления.

Если Вы хотите получать все возможные значения для столбца ENUM, Вы должны использовать SHOW COLUMNS FROM table_name LIKE enum_column_name и анализировать определение ENUM во втором столбце вывода.

5.3.4 Тип SET

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

Например, столбец, определенный как SET("one","two") NOT NULL, может иметь любое из этих значений:

""
"one"
"two"
"one,two"

SET может иметь максимум 64 различных членов.

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

mysql> SELECT set_col+0 FROM tbl_name;

Если число сохранено в столбце SET, биты, которые установлены в двоичном представлении числа, определяют члены набора в значении столбца. Предположим, что столбец определен как SET("a","b","c","d"). Члены имеют следующие разрядные значения:

SET член множества | Десятичное значение | Двоичное значение
a | 1 | 0001
b | 2 | 0010
c | 4 | 0100
d | 8 | 1000

Если Вы назначаете число 9 этому столбцу (в двоичной системе это будет 1001), то первый и четвертый члены значения SET (то есть, "a" и "d") будут выбраны, и возникающим в результате значением будет "a,d".

Для значения, содержащего больше, чем один элемент SET, не имеет значения порядок элементов, в котором они перечислены, когда Вы вставляете значение. Также не важно, сколько раз данный элемент перечислен в значении. Когда значение потом будет получено из таблицы, каждый элемент в нем появится лишь однажды, причем элементы будут перечислены согласно порядку, в котором они были определены при создании таблицы. Например, если столбец определен как SET("a","b","c","d"), то "a,d", "d,a" и "d,a,a,d,d" будут появляться как "a,d" при получении данных из таблицы.

Значения SET сортируются в цифровой форме. NULL расположится перед другими значениями.

Обычно, Вы выполняете SELECT на столбце SET, применяя оператор LIKE или функцию FIND_IN_SET():

mysql> SELECT * FROM tbl_name WHERE set_col LIKE '%value%';
mysql> SELECT * FROM tbl_name WHERE FIND_IN_SET('value',set_col)>0;

Но следующее будет также работать:

mysql> SELECT * FROM tbl_name WHERE set_col = 'val1,val2';
mysql> SELECT * FROM tbl_name WHERE set_col & 1;

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

Если Вы хотите получать все возможные значения для столбца SET, Вы должны использовать: SHOW COLUMNS FROM table_name LIKE set_column_name и анализировать второй столбец определения.

5.4 Выбор правильного типа для столбца

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

Точное представление денежных величин обычно является проблемой. В MySQL Вы должны использовать тип DECIMAL. Это сохранено как строка, так что никакая потеря точности не должна произойти. Если точность не слишком важна, тип DOUBLE также может быть достаточен.

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

5.5 Использование типов столбцов из других СУБД

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

Чужой тип | Тип в MySQL
BINARY(NUM) | CHAR(NUM) BINARY
CHAR VARYING(NUM) | VARCHAR(NUM)
FLOAT4 | FLOAT
FLOAT8 | DOUBLE
INT1 | TINYINT
INT2 | SMALLINT
INT3 | MEDIUMINT
INT4 | INT
INT8 | BIGINT
LONG VARBINARY | MEDIUMBLOB
LONG VARCHAR | MEDIUMTEXT
MIDDLEINT | MEDIUMINT
VARBINARY(NUM) | VARCHAR(NUM) BINARY

Отображение типа столбца происходит при создании таблицы. Если Вы создаете таблицу с типами, используемыми другими авторами, а затем выдаете команду DESCRIBE tbl_name, MySQL сообщает структуру таблицы, использующую эквивалентные типы MySQL.

5.6 Требования столбцов к памяти

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

5.2.6.1 Требования к памяти для чисел

Тип столбца | Для хранения надо
TINYINT | 1 байт
SMALLINT | 2 байта
MEDIUMINT | 3 байта
INT | 4 байта
INTEGER | 4 байта
BIGINT | 8 байта
FLOAT(X) | 4, если X <= 24, или 8, если 25 <= X <= 53
FLOAT | 4 байта
DOUBLE | 8 байта
DOUBLE PRECISION | 8 байта
REAL | 8 байта
DECIMAL(M,D) | M+2 байт, если D > 0, M+1 байт, если D=0 (D+2, если M < D )
NUMERIC(M,D) | M+2 байт, если D > 0, M+1 байт, если D=0 (D+2, если M < D )

5.2.6.2 Требования к памяти для даты и времени

Тип столбца | Для хранения надо
DATE | 3 байта
DATETIME | 8 байта
TIMESTAMP | 4 байта
TIME | 3 байта
YEAR | 1 байт

5.2.6.3 Требования к памяти для строк

Тип столбца | Для хранения надо
CHAR(M) | M байт, 1 <= M <= 255
VARCHAR(M) | L+1 байт, где L <= M и 1 <= M <= 255
TINYBLOB, TINYTEXT | L+1 байт, где L < 2^8
BLOB, TEXT | L+2 байта, где L < 2^16
MEDIUMBLOB, MEDIUMTEXT | L+3 байта, где L < 2^24
LONGBLOB, LONGTEXT | L+4 байта, где L < 2^32
ENUM('value1','value2',...) | 1 или 2 байта, в зависимости от количества значений перечисления (максимум 65535 значений)
SET('value1','value2',...) | 1, 2, 3, 4 или 8 байт, в зависимости от числа членов набора (максимум 64 члена)

Типы VARCHAR, BLOB и TEXT представляют собой типы переменной длины, для которых требования к памяти зависят от фактической длины значения столбца (представлена как L в предшествующей таблице). Например, столбец VARCHAR(10) может хранить строку с максимальной длиной в 10 символов. Фактическая требуемая память равна длине строки (L) плюс 1 байт, чтобы записать длину строки. Для строки abcd, L равно 4, а требования к памяти равны 5 байтам.

Типы BLOB и TEXT требуют 1, 2, 3 или 4 байта, чтобы записать длину значения столбца, в зависимости от максимальной возможной длины типа.

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

Размер объекта ENUM определен числом различных значений перечисления. Один байт используется для перечислений до 255 возможных значений. Два байта используются для перечислений до 65535 значений. Подробности в разделе "5.3.3 Тип ENUM ".

Размер объекта SET определен числом различных членов набора. Если размер набора равен N, то объект занимает (N+7)/8 байт, округленных до 1, 2, 3, 4 или 8 байт. SET может иметь максимум до 64 членов. Подробности приведены в разделе "5.3.4 Тип SET".


Функции для использования в SELECT и WHERE

6 Функции для использования в SELECT и WHERE

select_expression или where_definition в инструкции SQL может состоять из любого выражения, использующего функции, описанные ниже.

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

ОБРАТИТЕ ВНИМАНИЕ: не должно быть никаких пробелов между именем функции и круглой скобкой после него. Это помогает синтаксическому анализатору MySQL различать обращения к функции и ссылки к таблицам или столбцам, которые, случается, имеют то же самое имя, что и функция. Пробелы вокруг параметров разрешаются.

Вы можете заставить MySQL принимать пробелы после имени функции, запуская mysqld с опцией --ansi или используя параметр CLIENT_IGNORE_SPACE в mysql_connect(), но в этом случае все имена функции станут зарезервированными словами. Подробности в разделе "1.4.3 Запуск MySQL в режиме ANSI ".

Ради краткости, примеры отображают вывод из программы mysql в сокращенной форме. Например:

mysql> select MOD(29,9);
1 rows in set (0.00 sec)
  +-----------+
  | mod(29,9) |
  +-----------+
  |         2 |
  +-----------+

Отображается подобно этому:

mysql> select MOD(29,9);
-> 2

6.1 Нетипизированные операторы и функции

6.1.1 Скобки

( ... )

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

mysql> select 1+2*3;
    -> 7
mysql> select (1+2)*3;
    -> 9

6.1.2 Операторы сравнения

Операторы сравнения возвращают значения 1 (TRUE), 0 (FALSE) или NULL. Эти функции работают для чисел и строк. Строки автоматически будут преобразованы в числа, а числа в строки, как необходимо (как в языке Perl).

MySQL выполняет все сравнения, использующие следующие правила:

  • Если одни или оба параметра равны NULL, результат сравнения также равен NULL, кроме операторов <=>.
  • Если оба параметра в операции сравнения представляют собой строки, они сравниваются как строки.
  • Если оба параметра представляют собой числа, они сравниваются как числа.
  • Шестнадцатеричные значения обрабатываются как двоичные строки, если не сравниваются с числом.
  • Если один из параметров представляет собой столбец типа TIMESTAMP или DATETIME, а другой параметр является константой, то она будет преобразована в timestamp прежде, чем сравнение выполняется. Это выполнено, чтобы быть более дружественным к ODBC.
  • Во всех других случаях параметры сравниваются как числа с плавающей запятой (реальные).

По умолчанию, сравнения строк выполнены независимо от регистра, используя текущий набор символов (по умолчанию это ISO-8859-1 Latin1, который работает превосходно для английского языка).

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

mysql> SELECT 1 > '6x';
     -> 0
mysql> SELECT 7 > '6x';
     -> 1
mysql> SELECT 0 > 'x6';
     -> 0
mysql> SELECT 0 = 'x6';
-> 1
=
Равны:
mysql> select 1 = 0;
    -> 0
mysql> select '0' = 0;
    -> 1
mysql> select '0.0' = 0;
    -> 1
mysql> select '0.01' = 0;
    -> 0
mysql> select '.01' = 0.01;
    -> 1
<>
!=
Не равны:
mysql> select '.01' <> '0.01';
    -> 1
mysql> select .01 <> '0.01';
    -> 0
mysql> select 'zapp' <> 'zappp';
    -> 1
<=
Меньше, чем или равны:
mysql> select 0.1 <= 2;
    -> 1
<
Строго мньше, чем:
mysql> select 2 < 2;
    -> 0
>=
Больше, чем или равны:
mysql> select 2 >= 2;
    -> 1
>
Строго больше, чем:
mysql> select 2 > 2;
    -> 0
<=>
Null равен:
mysql> select 1 <=> 1, NULL <=> NULL, 1 <=> NULL;
    -> 1 1 0
IS NULL
IS NOT NULL
Проверяет, является или нет значение NULL:
mysql> select 1 IS NULL, 0 IS NULL, NULL IS NULL;
    -> 0 0 1
mysql> select 1 IS NOT NULL, 0 IS NOT NULL, NULL IS NOT NULL;
    -> 1 1 0
expr BETWEEN min AND max
Если expr больше или равно min, и expr меньше или равно max, то BETWEEN вернет 1, иначе это возвращает 0. Это эквивалентно выражению (min <= expr AND expr <= max), если все параметры имеют тот же самый тип. Первый параметр (expr) определяет, как выполняется сравнение следующим образом:
  • Если expr представляет собой столбец типа TIMESTAMP, DATE или DATETIME, то MIN() и MAX() приводятся к тому же самому формату, если они константы.
  • Если expr представляет собой строку, нечувствительную к регистру, то сравнение выполняется без учета регистра.
  • Если expr представляет собой строку, чувствительную к регистру, то сравнение выполняется с учетом регистра символов.
  • Если expr представляет собой целочисленное выражение, будет выполнено целочисленное сравнение.
  • Иначе, будет выполнено сравнение чисел с плавающей запятой.
mysql> select 1 BETWEEN 2 AND 3;
    -> 0
mysql> select 'b' BETWEEN 'a' AND 'c';
    -> 1
mysql> select 2 BETWEEN 2 AND '3';
    -> 1
mysql> select 2 BETWEEN 2 AND 'x-3';
    -> 0
expr IN (value,...)
Возвращается 1, если expr представляет собой любое из значений в списке IN, иначе возвращается 0. Если все значения константы, то все значения оценены согласно типу expr и отсортированы. Поиск элемента затем будет выполнен, используя двоичный поиск. Это означает, что IN очень быстр, если список значений IN состоит полностью из констант. Если expr чувствительное к регистру строковое выражение, сравнение строк выполняется с учетом регистра:
mysql> select 2 IN (0,3,5,'wefwf');
    -> 0
mysql> select 'wefwf' IN (0,3,5,'wefwf');
    -> 1
expr NOT IN (value,...)
Аналогично NOT (expr IN (value,...)).
ISNULL(expr)
Если expr равен NULL, ISNULL() возвращает 1, иначе это возвращает 0:
mysql> select ISNULL(1+1);
    -> 0
mysql> select ISNULL(1/0);
    -> 1
Обратите внимание, что сравнение значений NULL, использующих = всегда будет равно false!
COALESCE(list)
Возвращает первый не-NULL элемент в списке:
mysql> select COALESCE(NULL,1);
    -> 1
mysql> select COALESCE(NULL,NULL,NULL);
    -> NULL
INTERVAL(N,N1,N2,N3,...)
Возвращает 0, если N < N1, 1, если N < N2 и так далее. Все параметры обрабатываются как целые числа. Это требует, чтобы выполнялось N1 < N2 < N3 < ... < Nn для этой функции, чтобы она могла работать правильно. Это потому, что при работе функции используется двоичный поиск (очень быстрый):
mysql> select INTERVAL(23, 1, 15, 17, 30, 44, 200);
    -> 3
mysql> select INTERVAL(10, 1, 10, 100, 1000);
    -> 2
mysql> select INTERVAL(22, 23, 30, 44, 200);
    -> 0

Если Вы сравниваете чувствительную к регистру строку любым из стандартных операторов (=, <>..., но не LIKE), конечный пробел будет игнорироваться.

mysql> select "a" ="A ";
    -> 1

6.1.3 Логические операторы

Все логические функции возвращают 1 (TRUE), 0 (FALSE) или NULL (неизвестное, которое находится в большинстве случаев также, как FALSE):

NOT
!
Логический NOT. Возвращает 1, если параметр 0, иначе возвращает 0. Исключительная ситуация: NOT NULL возвращает NULL:
mysql> select NOT 1;
    -> 0
mysql> select NOT NULL;
    -> NULL
mysql> select ! (1+1);
    -> 0
mysql> select ! 1+1;
    -> 1
Последний пример возвращает 1 потому, что выражение оценивается так же, как (!1)+1.
OR
||
Логический OR. Возвращает 1, если любой параметр не 0 и не NULL:
mysql> select 1 || 0;
    -> 1
mysql> select 0 || 0;
    -> 0
mysql> select 1 || NULL;
    -> 1
AND
&&
Логический AND. Возвращается 0, если параметр 0 или NULL, иначе возвращается 1:
mysql> select 1 && NULL;
    -> 0
mysql> select 1 && 0;
    -> 0

6.1.4 Функции ветвления

IFNULL(expr1,expr2)
Если expr1 не NULL, IFNULL() вернет expr1, иначе expr2. IFNULL() возвращает числовое или строковое значение в зависимости от контекста, в котором это используется:
mysql> select IFNULL(1,0);
    -> 1
mysql> select IFNULL(NULL,10);
    -> 10
mysql> select IFNULL(1/0,10);
    -> 10
mysql> select IFNULL(1/0,'yes');
    -> 'yes'
NULLIF(expr1,expr2)
Если expr1=expr2, вернет NULL, иначе возвращает expr1. Это работает также, как CASE WHEN x=y THEN NULL ELSE x END:
mysql> select NULLIF(1,1);
    -> NULL
mysql> select NULLIF(1,2);
    -> 1
Обратите внимание, что expr1 будет оценен дважды в MySQL, если параметры равны.
IF(expr1,expr2,expr3)
Если expr1 равно TRUE (expr1 <> 0 и expr1 <> NULL), то IF() вернет expr2, иначе вернет expr3. IF() возвращает числовое или строковое значение в зависимости от контекста, в котором это используется:
mysql> select IF(1>2,2,3);
    -> 3
mysql> select IF(1<2,'yes','no');
    -> 'yes'
mysql> select IF(strcmp('test','test1'),'no','yes');
    -> 'no'
expr1 будет оценен как целочисленное значение, это означает, что, если Вы проверяете выражение с плавающей запятой или строку, Вы должны сделать следующее для корректного использования операции сравнения:
mysql> select IF(0.1,1,0);
    -> 0
mysql> select IF(0.1<>0,1,0);
    -> 1
В первом случае выше IF(0.1) вернет 0 потому, что 0.1 преобразован в целочисленное значение, возникающее в результате в IF(0). Это не может быть тем, что Вы ожидаете. Во втором случае сравнение проверяет первоначальное значение с плавающей запятой, чтобы видеть,является ли это отличным от нуля. Результат сравнения используется как целое число. Заданный по умолчанию тип возврата IF() (который может иметь значение, когда это значение будет сохранено во временной таблице) вычислен в MySQL 3.23 следующим образом:
Выражение | Возвращаемое значение
expr2 или expr3 возвращает строку | Строка
expr2 или expr3 возвращает значение с плавающей запятой | Число с плавающей запятой
expr2 или expr3 возвращает целое число | Целое число
CASE value WHEN [compare-value] THEN result [WHEN [compare-value] THEN result ...] [ELSE result] END
CASE WHEN [condition] THEN result [WHEN [condition] THEN result ...] [ELSE result] END
Первая версия возвращает result, где value=compare-value. Вторая версия возвращает результат для первого условия, которое является истинным. Если не имелось никакого значения результата соответствия, то будет возвращен результат после ELSE. Если не имеется части ELSE, вернется NULL:
mysql> SELECT CASE 1 WHEN 1 THEN "one" WHEN 2 THEN "two"
           ELSE "more" END;
   -> "one"
mysql> SELECT CASE WHEN 1>0 THEN "true" ELSE "false" END;
   -> "true"
mysql> SELECT CASE BINARY "B" when "a" then 1 when "b" then 2 END;
   -> NULL

Тип значения возврата (INTEGER, DOUBLE или STRING) такое же, как и тип первого возвращенного значения (выражение после первого THEN).

6.2 Строковые функции

Строковые функции возвращают NULL, если длина результата большая, чем параметр сервера max_allowed_packet.

Для функций, которые оперируют позициями в строке, первая позиция всегда пронумерована как 1, а не 0.

ASCII(str)
Возвращает ASCII-код крайнего левого символа строки str. Вернет 0, если str пустая. Вернет NULL, если str равна NULL:
mysql> select ASCII('2');
    -> 50
mysql> select ASCII(2);
    -> 50
mysql> select ASCII('dx');
    -> 100
См. также описание функции ORD().
ORD(str)
Если крайний левый символ строки str представляет собой многобайтный символ, возвращает код символа, возвращая ASCII-значение кода символа в формате: ((первый байт ASCII-кода)*256+(второй байт ASCII-кода))[*256+ третий байт ASCII-кода...]. Если крайний левый символ не является многобайтным, действует аналогично функции ASCII():
mysql> select ORD('2');
    -> 50
CONV(N,from_base,to_base)
Преобразовывает числа между различными системами счисления. Возвращает строковое представление числа N, преобразованного из from_base в to_base. Вернет NULL, если любой параметр равен NULL. Параметр N интерпретируется как целое число, но может быть определен как целое число или строка. Минимальная система счисления 2, максимальная 36. Если to_base отрицательное значение, N расценено как число со знаком. Иначе, N обрабатывается как число без знака. Вызов CONV всегда работает с 64-разрядной точностью:
mysql> select CONV("a",16,2);
    -> '1010'
mysql> select CONV("6E",18,8);
    -> '172'
mysql> select CONV(-17,10,-18);
    -> '-H'
mysql> select CONV(10+"10"+'10'+0xa,10,10);
    -> '40'
BIN(N)
Возвращает строковое представление двоичного значения N, где N представляет собой число типа longlong (BIGINT). Это эквивалентно CONV(N,10,2). Возвращает NULL, если N равно NULL:
mysql> select BIN(12);
    -> '1100'
OCT(N)
Возвращает строковое представление восьмеричного значения N, где N представляет собой число типа longlong. Это эквивалентно CONV(N,10,8). Возвращает NULL, если N равно NULL:
mysql> select OCT(12);
    -> '14'
HEX(N)
Возвращает строковое представление шестнадцатеричного значения N, где N представляет собой число типа longlong. Это эквивалентно CONV(N,10,16). Возвращает NULL, если N равно NULL:
mysql> select HEX(255);
    -> 'FF'
CHAR(N,...)
CHAR() интерпретируют параметры как целые числа и возвращает строку состоящую из символов, заданных значениями ASCII-кодов из тех целых чисел. Значения NULL будут пропущены:
mysql> select CHAR(77,121,83,81,'76');
    -> 'MySQL'
mysql> select CHAR(77,77.3,'77.3');
    -> 'MMM'
CONCAT(str1,str2,...)
Возвращает строку, которая следует из связывания параметров. Возвращает NULL, если любой параметр NULL. Может иметь больше, чем 2 параметра. Числовой параметр будет автоматически преобразован в эквивалентную строковую форму:
mysql> select CONCAT('My', 'S', 'QL');
    -> 'MySQL'
mysql> select CONCAT('My', NULL, 'QL');
    -> NULL
mysql> select CONCAT(14.3);
    -> '14.3'
CONCAT_WS(separator, str1, str2,...)
CONCAT_WS() расшифровывается как CONCAT With Separator и представляет собой специальную форму функции CONCAT(). Первый параметр задает разделитель для остальной части параметров. Разделитель может быть строкой так же, как и остальная часть параметров. Если разделитель равен NULL, результат превратится в NULL. Разделитель будет добавлен между строками, которые нужно объединить в одну целую:
mysql> select CONCAT_WS(",","First name","Second name","Last Name");
   -> 'First name,Second name,Last Name'
mysql> select CONCAT_WS(",","First name",NULL,"Last Name");
   -> 'First name,Last Name'
LENGTH(str)
OCTET_LENGTH(str)
CHAR_LENGTH(str)
CHARACTER_LENGTH(str)
Возвращает длину строки str:
mysql> select LENGTH('text');
    -> 4
mysql> select OCTET_LENGTH('text');
    -> 4
Обратите внимание, что для CHAR_LENGTH() любой многобайтный символ считается одним.
LOCATE(substr,str)
POSITION(substr IN str)
Возвращает позицию первого местонахождения подстроки substr в строке str. Если не нашла substr в str, вернет 0:
mysql> select LOCATE('bar', 'foobarbar');
    -> 4
mysql> select LOCATE('xbar', 'foobar');
    -> 0
Поддерживаются многобайтные символы.
LOCATE(substr,str,pos)
Возвращает позицию первого местонахождения подстроки substr в строке str, после позиции pos. Если не нашла substr в str, вернет 0:
mysql> select LOCATE('bar', 'foobarbar',5);
    -> 7
Поддерживаются многобайтные символы.
INSTR(str,substr)
Аналог LOCATE(), но с переставленными параметрами:
mysql> select INSTR('foobarbar', 'bar');
    -> 4
mysql> select INSTR('xbar', 'foobar');
    -> 0
Поддерживаются многобайтные символы.
LPAD(str,len,padstr)
Возвращает строку str, дополненную слева строкой padstr. Максимальная длина str равна len символам. Если str длиннее, чем len, она будет урезана до len символов. Если str короче, чем len символов, padstr будет приписана несколько раз.
mysql> select LPAD('hi',4,'??');
    -> '??hi'
RPAD(str,len,padstr)
Аналогично LPAD(str,len,padstr), но строка padstr приписывается справа.
mysql> select RPAD('hi',5,'?');
    -> 'hi???'
LEFT(str,len)
Возвращает len крайних левых символов из строки str:
mysql> select LEFT('foobarbar', 5);
    -> 'fooba'
Поддерживаются многобайтные символы.
RIGHT(str,len)
Возвращает len крайних правых символов из строки str:
mysql> select RIGHT('foobarbar', 4);
    -> 'rbar'
Поддерживаются многобайтные символы.
SUBSTRING(str,pos,len)
SUBSTRING(str FROM pos FOR len)
MID(str,pos,len)
Возвращает подстроку длиной в len символов из строки str, начиная с позиции pos. Иная форма, которая использует синтаксис FROM из ANSI SQL92:
mysql> select SUBSTRING('Quadratically',5,6);
    -> 'ratica'
Поддерживаются многобайтные символы.
SUBSTRING(str,pos)
SUBSTRING(str FROM pos)
Возвращает подстроку из строки str. начиная с позиции pos:
mysql> select SUBSTRING('Quadratically',5);
    -> 'ratically'
mysql> select SUBSTRING('foobarbar' FROM 4);
    -> 'barbar'
Поддерживаются многобайтные символы.
SUBSTRING_INDEX(str,delim,count)
Возвращает подстроку из строки str, отступив count символов от разделителя delim. Если count положителен, вернется все левее разделителя. Если count отрицателен, вернется все правее заданного разделителя:
mysql> select SUBSTRING_INDEX('www.mysql.com', '.', 2);
    -> 'www.mysql'
mysql> select SUBSTRING_INDEX('www.mysql.com', '.', -2);
    -> 'mysql.com'
Поддерживаются многобайтные символы.
LTRIM(str)
Возвращает строку str с удаленными ведущими пробелами:
mysql> select LTRIM('  barbar');
    -> 'barbar'
RTRIM(str)
Возвращает строку str с удаленными конечными пробелами:
mysql> select RTRIM('barbar   ');
    -> 'barbar'
Поддерживаются многобайтные символы.
TRIM([[BOTH|LEADING|TRAILING] [remstr] FROM] str)
Возвращает строку str, из которой удалены все префиксы и суффиксы remstr. Если ни один из спецификаторов BOTH, LEADING или TRAILING не задан, принимается BOTH. Если не задан параметр remstr, будут удалены пробелы:
mysql> select TRIM('  bar   ');
    -> 'bar'
mysql> select TRIM(LEADING 'x' FROM 'xxxbarxxx');
    -> 'barxxx'
mysql> select TRIM(BOTH 'x' FROM 'xxxbarxxx');
    -> 'bar'
mysql> select TRIM(TRAILING 'xyz' FROM 'barxxyz');
    -> 'barx'
Поддерживаются многобайтные символы.
SOUNDEX(str)
Возвращает soundex-строку из строки str. Две строки, которые звучат почти одинаково, должны иметь идентичные soundex-строки. Стандартная soundex-строка длиной 4 символа, но функция SOUNDEX() возвращает произвольно длинную строку. Вы можете использовать SUBSTRING() на результате, чтобы получить стандартную soundex-строку. Все не алфавитно-цифровые символы игнорируются в данной строке. Все международные алфавитные символы вне диапазона A-Z обрабатываются как гласные:
mysql> select SOUNDEX('Hello');
    -> 'H400'
mysql> select SOUNDEX('Quadratically');
    -> 'Q36324'
SPACE(N)
Возвращает строку, состоящую из N пробелов:
mysql> select SPACE(6);
    -> '      '
REPLACE(str,from_str,to_str)
Возвращает строку str, где все вхождения подстроки from_str заменены на подстроку to_str:
mysql> select REPLACE('www.mysql.com', 'w', 'Ww');
    -> 'WwWwWw.mysql.com'
Поддерживаются многобайтные символы.
REPEAT(str,count)
Возвращает строку, состоящую из вводной строки str повторенной count раз. Если count <=0, возвращает пустую строку. Если str или count равны NULL, вернет NULL:
mysql> select REPEAT('MySQL', 3);
    -> 'MySQLMySQLMySQL'
REVERSE(str)
Возвращает строку str с обращенным порядком символов:
mysql> select REVERSE('abc');
    -> 'cba'
Поддерживаются многобайтные символы.
INSERT(str,pos,len,newstr)
Возвращает строку str с подстрокой, начинающейся в позиции pos и длиной в len символов, замененной на строку newstr:
mysql> select INSERT('Quadratic', 3, 4, 'What');
    -> 'QuWhattic'
Поддерживаются многобайтные символы.
ELT(N,str1,str2,str3,...)
Возвращает str1, если N=1, str2, если N=2 и так далее. Возвращает NULL, если N меньше, чем 1, или больше, чем число параметров. ELT() дополняет функцию FIELD():
mysql> select ELT(1, 'ej', 'Heja', 'hej', 'foo');
    -> 'ej'
mysql> select ELT(4, 'ej', 'Heja', 'hej', 'foo');
    -> 'foo'
FIELD(str,str1,str2,str3,...)
Возвращает индекс str в списке str1, str2, str3, .... Вернет 0, если str не найдена. FIELD() дополняет функцию ELT():
mysql> select FIELD('ej', 'Hej', 'ej', 'Heja', 'hej', 'foo');
    -> 2
mysql> select FIELD('fo', 'Hej', 'ej', 'Heja', 'hej', 'foo');
    -> 0
FIND_IN_SET(str,strlist)
Возвращает значение от 1 до N, если строка str находится в списке strlist, состоящем из N подстрок. Список строк представляет собой строку, составленную из подстрок, отделяемых символом запятой (,). Если первый параметр постоянная строка, а второй столбец типа SET, то функция FIND_IN_SET() оптимизирована, чтобы использовать разрядную арифметику. Возвращается 0, если str не в strlist или strlist является пустой строкой. Возвращает NULL, если любой параметр NULL. Эта функция не будет работать правильно, если первый параметр содержит запятую:
mysql> SELECT FIND_IN_SET('b','a,b,c,d');
    -> 2
MAKE_SET(bits,str1,str2,...)
Возвращает строку, содержащую подстроки, отделяемые запятой (,), состоящую из строк, которые имеют соответствующий бит в наборе bits. str1 соответствует биту 0, str2 биту 1 и так далее. NULL в str1, str2, ... не попадут в результат:
mysql> SELECT MAKE_SET(1,'a','b','c');
    -> 'a'
mysql> SELECT MAKE_SET(1 | 4,'hello','nice','world');
    -> 'hello,world'
mysql> SELECT MAKE_SET(0,'a','b','c');
    -> ''
EXPORT_SET(bits,on,off,[separator,[number_of_bits]])
Возвращает строку, где для каждого бита, установленного в наборе 'bit', Вы получите строку 'on', а для каждого неустановленного строку 'off'. Каждая отделяется от других разделителем (separator, по умолчанию запятая) и используется только 'number_of_bits' бит (по умолчанию 64):
mysql> select EXPORT_SET(5,'Y','N',',',4)
    -> Y,N,Y,N
LCASE(str)
LOWER(str)
Возвращает строку str со всеми символами, измененными на нижний регистр согласно текущему отображению набора символов (значение по умолчанию: ISO-8859-1 Latin1):
mysql> select LCASE('QUADRATICALLY');
    -> 'quadratically'
Поддерживаются многобайтные символы.
UCASE(str)
UPPER(str)
Возвращает строку str со всеми символами, измененными на верхний регистр согласно текущему отображению набора символов (значение по умолчанию: ISO-8859-1 Latin1):
mysql> select UCASE('Hej');
    -> 'HEJ'
Поддерживаются многобайтные символы.
LOAD_FILE(file_name)
Читает файл и возвращает содержание файла как строку. Файл должен быть на сервере, Вы должны определить полное имя файла и иметь привилегию file. Файл должен быть читаем всеми и быть меньше, чем max_allowed_packet. Если файл не существует или не может читаться из-за одной из вышеупомянутых причин, функция возвратит NULL:
mysql> UPDATE table_name
           SET blob_column=LOAD_FILE("/tmp/picture")
           WHERE id=1;

Если Вы не используете MySQL Version 3.23, Вы должны делать чтение файла внутри Вашей прикладной программы и создавать инструкцию INSERT, чтобы модифицировать базу данных с информацией из файла. Один способ сделать это, если Вы используете библиотеку MySQL++, есть на страничке http://www.mysql.com/documentation/mysql++/mysql++-examples.html.

MySQL по мере необходимости автоматически преобразует числа в строки и наоборот (как в Perl):

mysql> SELECT 1+"1";
    -> 2
mysql> SELECT CONCAT(2,' test');
    -> '2 test'

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

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

6.2.1 Функции сравнения строк

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

expr LIKE pat [ESCAPE 'escape-char']
Соответствие, использующее простое регулярное сравнение выражения SQL. Возвращает 1 (TRUE) или 0 (FALSE). С LIKE Вы можете использовать следующие два групповых символа в задаваемом образце:
% Соответствует любому числу символов.
_ Соответствует строго одному символу.
mysql> select 'David!' LIKE 'David_';
    -> 1
mysql> select 'David!' LIKE '%D%v%';
    -> 1
Чтобы проверять для литеральных образцов группового символа, экранируйте его символом escape. Если Вы не определяете символ ESCAPE, будет принято значение \:
\% Соответствует одному символу %.
\_ Соответствует одному символу _.
mysql> select 'David!' LIKE 'David\_';
    -> 0
mysql> select 'David_' LIKE 'David\_';
    -> 1
Чтобы определять иной символ escape, используйте предложение ESCAPE:
mysql> select 'David_' LIKE 'David|_' ESCAPE '|';
    -> 1
Следующие две инструкции иллюстрируют сравнения нечувствительных к регистру строк, если один из операндов не двоичная строка:
mysql> select 'abc' LIKE 'ABC';
    -> 1
mysql> SELECT 'abc' LIKE BINARY 'ABC';
    -> 0
LIKE позволяется на числовых выражениях! Это MySQL-расширение ANSI SQL LIKE.
mysql> select 10 LIKE '1%';
    -> 1
Обратите внимание: поскольку MySQL использует C-escape синтаксис в строках (например, \n), Вы должны удвоить любой символ \, который Вы используете в Вашем выражении LIKE. Например, чтобы искать \n, определите это как \\n. Чтобы искать \, определите это как \\\\ (наклонные черты влево будут удалены синтаксическим анализатором и повторно, когда соответствие образца выполнено, оставляя одиночную наклонную черту влево, которая будет согласована в данном выражении).
expr NOT LIKE pat [ESCAPE 'escape-char']
Это аналогично вызову NOT (expr LIKE pat [ESCAPE 'escape-char']).
expr REGEXP pat
expr RLIKE pat
Выполняет соответствие образца выражения строки expr для образца pat. Образец может быть расширенным регулярным выражением. Подробности в разделе "6.7 Описание синтаксиса регулярных выражений MySQL". Возвращает 1, если expr соответствует pat, иначе вернется 0. RLIKE представляет собой синоним для REGEXP, предусмотренный для совместимости с mSQL. Обратите внимание: поскольку MySQL использует C-escape синтаксис в строках (например, \n), Вы должны удвоить любой символ \, который Вы используете в Вашем выражении REGEXP. Например, чтобы искать \n, определите это как \\n. Начиная с MySQL Version 3.23.4, REGEXP нечувствителен к регистру для нормальных (не двоичных) строк:
mysql> select 'Monty!' REGEXP 'm%y%%';
    -> 0
mysql> select 'Monty!' REGEXP '.*';
    -> 1
mysql> select 'new*\n*line' REGEXP 'new\\*.\\*line';
    -> 1
mysql> select "a" REGEXP "A", "a" REGEXP BINARY "A";
    -> 1  0
mysql> select "a" REGEXP "^[a-d]";
    -> 1
REGEXP и RLIKE используют текущий набор символов (по умолчанию задан ISO-8859-1 Latin1).
expr NOT REGEXP pat
expr NOT RLIKE pat
Это аналогично вызову NOT (expr REGEXP pat).
STRCMP(expr1,expr2)
STRCMP() возвращает 0, если строки одинаковые, -1, если первый параметр меньше, чем второй согласно текущему порядку сортировки, или 1 в противном случае:
mysql> select STRCMP('text', 'text2');
    -> -1
mysql> select STRCMP('text2', 'text');
    -> 1
mysql> select STRCMP('text', 'text');
    -> 0
MATCH (col1,col2,...) AGAINST (expr)
MATCH ... AGAINST() используется для полнотекстового поиска и возвращает релевантность (она же уместность), меру подобия между текстом в столбцах (col1,col2,...) и запросе expr. Релевантность представляет собой положительное число с плавающей запятой. Нулевое значение данной величины означает отсутствие схожести. Для работы MATCH ... AGAINST() сначала должен быть создан индекс FULLTEXT. Подробности в разделе "7.3 Синтаксис CREATE TABLE ". MATCH ... AGAINST() доступен в MySQL Version 3.23.23 или более поздних. Подробности в разделе "9.4 Полнотекстовый поиск в MySQL".

6.2.2 Чувствительность к регистру символов

BINARY
Оператор BINARY приводит строку к двоичной форме. Это простой способ вынудить сравнение столбца быть чувствительным к регистру, даже если столбец не определен как BINARY или BLOB:
mysql> select "a" = "A";
    -> 1
mysql> select BINARY "a" = "A";
    -> 0
BINARY появился в MySQL Version 3.23.0. Обратите внимание, что в некотором контексте MySQL не будет способен использовать индекс эффективно, когда Вы приводите индексированный столбец к BINARY.

Если Вы хотите сравнивать нечувствительные к регистру объекты blob, Вы можете всегда преобразовывать blob в верхний регистр перед сравнением:

SELECT 'A' LIKE UPPER(blob_col) FROM table_name;

6.3 Числовые функции

6.3.1 Арифметические операторы

Обычные арифметические операторы доступны. Обратите внимание, что в случае `-', `+' и `*', результат вычислен с точностью BIGINT (64-bit), если оба параметра целые числа!

+
Сложение:
mysql> select 3+5;
    -> 8
-
Вычитание:
mysql> select 3-5;
    -> -2
*
Умножение:
mysql> select 3*5;
    -> 15
mysql> select 18014398509481984*18014398509481984.0;
    -> 324518553658426726783156020576256.0
mysql> select 18014398509481984*18014398509481984;
    -> 0
Результат последнего выражения ошибочен потому, что результат целочисленного умножения превышает 64-разрядный диапазон вычислений BIGINT.
/
Деление:
mysql> select 3/5;
    -> 0.60
Деление на ноль вернет NULL:
mysql> select 102/(1-1);
    -> NULL
Деление будет вычислено с арифметикой BIGINT только, если выполняется в контексте, где результат преобразован в целое число!

6.3.2 Математические функции

Все математические функции возвращают NULL в случае ошибки.

-
Унарный минус. Меняет знак аргумента:
mysql> select - 2;
    -> -2
Обратите внимание, что, если этот оператор используется с BIGINT, значение возврата будет типа BIGINT! Это означает, что Вы должны избегать использования - на целых числах, которые могут иметь значение -2^63!
ABS(X)
Возвращает абсолютное значение X:
mysql> select ABS(2);
    -> 2
mysql> select ABS(-32);
    -> 32
Эта функция безопасна, чтобы использовать со значениями BIGINT.
SIGN(X)
Возвращает знак параметра как -1, 0 или 1, в зависимости от того, является ли X отрицательным, нулевым или положительным:
mysql> select SIGN(-32);
    -> -1
mysql> select SIGN(0);
    -> 0
mysql> select SIGN(234);
    -> 1
MOD(N,M)
%
MOD (подобно оператору % в языке C). Возвращает остаток от деления N на M:
mysql> select MOD(234, 10);
    -> 4
mysql> select 253 % 7;
    -> 1
mysql> select MOD(29,9);
    -> 2
Эта функция безопасна, чтобы использовать со значениями BIGINT.
FLOOR(X)
Возвращает самое большое целочисленное значение не большее, чем X:
mysql> select FLOOR(1.23);
    -> 1
mysql> select FLOOR(-1.23);
    -> -2
Обратите внимание, что значение возврата преобразовано в BIGINT!
CEILING(X)
Возвращает самое маленькое целочисленное значение не меньше, чем X:
mysql> select CEILING(1.23);
    -> 2
mysql> select CEILING(-1.23);
    -> -1
Обратите внимание, что значение возврата преобразовано в BIGINT!
ROUND(X)
Возвращает параметр X, округленный к самому близкому целому:
mysql> select ROUND(-1.23);
    -> -1
mysql> select ROUND(-1.58);
    -> -2
mysql> select ROUND(1.58);
    -> 2
Обратите внимание, что поведение ROUND(), когда параметр расположен точно между двумя целыми числами, зависит от реализации библиотеки C. Некоторые версии всегда округляют к самому близкому четному числу, другие всегда к самому большому, самому меньшему или вообще возвращают ноль. Если Вы нуждаетесь в одном виде округления, Вы должны использовать четкую функцию, подобно TRUNCATE() или FLOOR().
ROUND(X,D)
Возвращает параметр X, округленный к числу с D десятичными цифрами. Если D равно 0, результат не будет иметь никакой десятичной отметки или дробной части:
mysql> select ROUND(1.298, 1);
    -> 1.3
mysql> select ROUND(1.298, 0);
    -> 1
EXP(X)
Возвращает значение e (основание натуральных логарифмов), предварительно возведенное в степень X:
mysql> select EXP(2);
    -> 7.389056
mysql> select EXP(-2);
    -> 0.135335
LOG(X)
Возвращает натуральный логарифм X:
mysql> select LOG(2);
    -> 0.693147
mysql> select LOG(-2);
    -> NULL
Для других логарифмов пользуйтесь формулой LOG(X)/LOG(B).
LOG10(X)
Возвращает десятичный логарифм X:
mysql> select LOG10(2);
    -> 0.301030
mysql> select LOG10(100);
    -> 2.000000
mysql> select LOG10(-100);
    -> NULL
POW(X,Y)
POWER(X,Y)
Возвращает значение X в степени Y:
mysql> select POW(2,2);
    -> 4.000000
mysql> select POW(2,-2);
    -> 0.250000
SQRT(X)
Возвращает неотрицательный квадратный корень X:
mysql> select SQRT(4);
    -> 2.000000
mysql> select SQRT(20);
    -> 4.472136
PI()
Возвращает значение PI. По умолчанию, показывается 5 десятичных чисел, но MySQL внутренне использует полный алгоритм расчета PI.
mysql> select PI();
    -> 3.141593
mysql> SELECT PI()+0.000000000000000000;
    -> 3.141592653589793116
COS(X)
Возвращает косинус X, где X задан в радианах:
mysql> select COS(PI());
    -> -1.000000
SIN(X)
Возвращает синус X, где X задан в радианах:
mysql> select SIN(PI());
    -> 0.000000
TAN(X)
Возвращает тангенс X, где X задан в радианах:
mysql> select TAN(PI()+1);
    -> 1.557408
ACOS(X)
Возвращает арккосинус X, то есть значение, чей косинус равен X. Вернет NULL, если X не в диапазоне от -1 до 1:
mysql> select ACOS(1);
    -> 0.000000
mysql> select ACOS(1.0001);
    -> NULL
mysql> select ACOS(0);
    -> 1.570796
ASIN(X)
Возвращает арксинус X, то есть значение, чей синус равен X. Вернет NULL, если X не в диапазоне от -1 до 1:
mysql> select ASIN(0.2);
    -> 0.201358
mysql> select ASIN('foo');
    -> 0.000000
ATAN(X)
Возвращает арктангенс X, то есть значение, чей тангенс равен X:
mysql> select ATAN(2);
    -> 1.107149
mysql> select ATAN(-2);
    -> -1.107149
ATAN2(Y,X)
Возвращает тангенс дуги из двух переменных X и Y. Это подобно вычислению тангенса дуги Y/X, за исключением того, что знаки обоих параметров используются, чтобы определить quadrant результата:
mysql> select ATAN(-2,2);
    -> -0.785398
mysql> select ATAN(PI(),0);
    -> 1.570796
COT(X)
Возвращает котангенс X:
mysql> select COT(12);
    -> -1.57267341
mysql> select COT(0);
    -> NULL
RAND()
RAND(N)
Возвращает произвольное значение с плавающей запятой в диапазоне от 0 до 1.0. Если целочисленный параметр N определен, он используется как значение инициализации:
mysql> select RAND();
    -> 0.5925
mysql> select RAND(20);
    -> 0.1811
mysql> select RAND(20);
    -> 0.1811
mysql> select RAND();
    -> 0.2079
mysql> select RAND();
    -> 0.7888
Вы не можете использовать столбец со значением RAND() в предложении ORDER BY потому, что ORDER BY вычисляется несколько раз. В MySQL Version 3.23, Вы, однако, это можете: SELECT * FROM table_name ORDER BY RAND() Это полезно, чтобы получить произвольную выборку SELECT * FROM table1,table2 WHERE a=b AND c<d ORDER BY RAND() LIMIT 1000. Обратите внимание, что RAND() в предложенииi WHERE будет переоценен каждый раз, когда выполняется WHERE.
LEAST(X,Y,...)
С двумя или больше параметрами, возвращает самый маленький параметр. Параметры сравниваются по следующим правилам:
  • Если значение возврата используется в контексте INTEGER, или все параметры целые числа, они сравниваются как целые числа.
  • Если значение возврата применяется в контексте REAL, или все параметры представляют собой числа real, они сравниваются как real.
  • Если любой параметр является чувствительной к регистру строкой, все параметры сравниваются именно как чувствительные к регистру строки.
  • Во всех других случаях параметры всегда сравниваются как нечувствительные к регистру обычные строки.
mysql> select LEAST(2,0);
    -> 0
mysql> select LEAST(34.0,3.0,5.0,767.0);
    -> 3.0
mysql> select LEAST("B","A","C");
    -> "A"
В MySQL до Version 3.22.5 Вы можете использовать MIN() вместо LEAST.
GREATEST(X,Y,...)
Возвращает самый большой параметр. Параметры сравниваются, используя те же самые правила, что касаются и вызова LEAST:
mysql> select GREATEST(2,0);
    -> 2
mysql> select GREATEST(34.0,3.0,5.0,767.0);
    -> 767.0
mysql> select GREATEST("B","A","C");
    -> "C"
В MySQL до Version 3.22.5 Вы можете использовать MAX() вместо GREATEST.
DEGREES(X)
Возвращает параметр X, преобразованный из радиан в градусы:
mysql> select DEGREES(PI());
    -> 180.000000
RADIANS(X)
Обратно вызову DEGREES(X):
mysql> select RADIANS(90);
    -> 1.570796
TRUNCATE(X,D)
Возвращает число X, усеченное до D десятичных чисел. Если D равно 0, результат не будет иметь никакой десятичной отметки или дробной части:
mysql> select TRUNCATE(1.223,1);
    -> 1.2
mysql> select TRUNCATE(1.999,1);
    -> 1.9
mysql> select TRUNCATE(1.999,0);
    -> 1
Обратите внимание, что, поскольку десятичные числа обычно сохраняются в компьютерах не как точные числа, а как двоичные значения, Вы можете быть введены в заблуждение следующим результатом:
mysql> select TRUNCATE(10.28*100,0);
   -> 1027
Вышеупомянутое случается потому, что число 10.28 фактически будет сохранено как нечто вроде 10.2799999999999999.

6.4 Функции для времени и даты

Обратитесь к разделу "5.2 Типы Date и Time" для описания диапазона значений, которые имеет каждый тип, и форматов, в которых значения даты и времени могут быть определены.

Имеется пример, который использует функции даты. Запрос ниже выбирает все записи со значением date_col в пределах последних 30 дней:

mysql> SELECT something FROM table
           WHERE TO_DAYS(NOW()) - TO_DAYS(date_col) <= 30;
DAYOFWEEK(date)
Возвращает номер дня недели для date (1=воскресенье, 2=понедельник, ..., 7=суббота). Эти индексные значения соответствуют стандарту ODBC:
mysql> select DAYOFWEEK('1998-02-03');
    -> 3
WEEKDAY(date)
Возвращает номер дня недели для date (0=понедельник, 1=вторник, ..., 6=воскресенье):
mysql> select WEEKDAY('1997-10-04 22:23:00');
    -> 5
mysql> select WEEKDAY('1997-11-05');
    -> 2
DAYOFMONTH(date)
Возвращает день месяца для date, в диапазоне от 1 до 31:
mysql> select DAYOFMONTH('1998-02-03');
    -> 3
DAYOFYEAR(date)
Возвращает день года для date, в диапазоне от 1 до 366:
mysql> select DAYOFYEAR('1998-02-03');
    -> 34
MONTH(date)
Возвращает месяц для date, в диапазоне от 1 до 12:
mysql> select MONTH('1998-02-03');
    -> 2
DAYNAME(date)
Возвращает имя дня недели для date:
mysql> select DAYNAME("1998-02-05");
    -> 'Thursday'
MONTHNAME(date)
Возвращает имя месяца для date:
mysql> select MONTHNAME("1998-02-05");
    -> 'February'
QUARTER(date)
Возвращает четверть года для date, в диапазоне от 1 до 4:
mysql> select QUARTER('98-04-01');
    -> 2
WEEK(date)
WEEK(date,first)
С одиночным параметром возвращает неделю для date, в диапазоне от 0 до 53 (да, могут иметься начала недели 53), для расположений, где воскресенье считается первым днем недели. Форма с двумя параметрами WEEK() позволяет Вам определять, начинается ли неделя в воскресенье или в понедельник. Неделя начинается в воскресенье, если второй параметр равен 0, или в понедельник, если он равен 1:
mysql> select WEEK('1998-02-20');
    -> 7
mysql> select WEEK('1998-02-20',0);
    -> 7
mysql> select WEEK('1998-02-20',1);
    -> 8
mysql> select WEEK('1998-12-31',1);
    -> 53
YEAR(date)
Возвращает год для date, в диапазоне от 1000 до 9999:
mysql> select YEAR('98-02-03');
    -> 1998
YEARWEEK(date)
YEARWEEK(date,first)
Возвращает год и неделю для date. Вторые параметры работают точно так же, как и второй параметр в вызове WEEK(). Обратите внимание, что год может отличаться от года в параметре для первой и последней недель:
mysql> select YEARWEEK('1987-01-01');
    -> 198653
HOUR(time)
Возвращает час для time, в диапазоне от 0 до 23:
mysql> select HOUR('10:05:03');
    -> 10
MINUTE(time)
Возвращает минуту для time, в диапазоне от 0 до 59:
mysql> select MINUTE('98-02-03 10:05:03');
    -> 5
SECOND(time)
Возвращает секунды для time, в диапазоне от 0 до 59:
mysql> select SECOND('10:05:03');
    -> 3
PERIOD_ADD(P,N)
Добавляет N месяцев к периоду P (в формате YYMM или YYYYMM). Возвращает значение в формате YYYYMM. Обратите внимание, что параметр P НЕ является датой:
mysql> select PERIOD_ADD(9801,2);
    -> 199803
PERIOD_DIFF(P1,P2)
Возвращает число месяцев между периодами P1 и P2. P1 и P2 должны быть в формате YYMM или YYYYMM. Обратите внимание, что параметры P1 и P2 НЕ являются датами:
mysql> select PERIOD_DIFF(9802,199703);
    -> 11
DATE_ADD(date,INTERVAL expr type)
DATE_SUB(date,INTERVAL expr type)
ADDDATE(date,INTERVAL expr type)
SUBDATE(date,INTERVAL expr type)
Эти функции выполняют арифметику даты. Они новы для MySQL Version 3.22. ADDDATE() и SUBDATE() представляют собой синонимы DATE_ADD() и DATE_SUB(). В MySQL Version 3.23 Вы можете использовать + и - вместо DATE_ADD() и DATE_SUB(), если выражение справа является столбом типа datetime или датой (пример ниже). date значение типа DATETIME или DATE, определяющее стартовую дату. expr задает выражение, определяющее значение интервала, которое будет добавлено или вычтено из стартовой даты. expr является строкой, оно может начинаться с `-' для отрицательных интервалов. type представляет собой ключевое слово, указывающее, как данное выражение должно интерпретироваться. Связанная функция EXTRACT(type FROM date) возвращает интервал 'type' даты. Следующая таблица показывает, как параметры type и expr связаны:
type значение | ожидаемый формат expr
SECOND | SECONDS
MINUTE | MINUTES
HOUR | HOURS
DAY | DAYS
MONTH | MONTHS
YEAR | YEARS
MINUTE_SECOND | "MINUTES:SECONDS"
HOUR_MINUTE | "HOURS:MINUTES"
DAY_HOUR | "DAYS HOURS"
YEAR_MONTH | "YEARS-MONTHS"
HOUR_SECOND | "HOURS:MINUTES:SECONDS"
DAY_MINUTE | "DAYS HOURS:MINUTES"
DAY_SECOND | "DAYS HOURS:MINUTES:SECONDS"
MySQL позволяет любой разделитель в формате expr. Показанные в таблице представляют собой предложенные разделители. Если параметр date значение типа DATE, и Ваши вычисления включают только части YEAR, MONTH и DAY, (то есть никаких частей времени), результат будет значением типа DATE. Иначе будет установлен тип DATETIME:
mysql> SELECT "1997-12-31 23:59:59" + INTERVAL 1 SECOND;
    -> 1998-01-01 00:00:00
mysql> SELECT INTERVAL 1 DAY + "1997-12-31";
    -> 1998-01-01
mysql> SELECT "1998-01-01" - INTERVAL 1 SECOND;
   -> 1997-12-31 23:59:59
mysql> SELECT DATE_ADD("1997-12-31 23:59:59",
                       INTERVAL 1 SECOND);
    -> 1998-01-01 00:00:00
mysql> SELECT DATE_ADD("1997-12-31 23:59:59",
                       INTERVAL 1 DAY);
    -> 1998-01-01 23:59:59
mysql> SELECT DATE_ADD("1997-12-31 23:59:59",
                       INTERVAL "1:1" MINUTE_SECOND);
    -> 1998-01-01 00:01:00
mysql> SELECT DATE_SUB("1998-01-01 00:00:00",
                       INTERVAL "1 1:1:1" DAY_SECOND);
    -> 1997-12-30 22:58:59
mysql> SELECT DATE_ADD("1998-01-01 00:00:00",
                       INTERVAL "-1 10" DAY_HOUR);
    -> 1997-12-30 14:00:00
mysql> SELECT DATE_SUB("1998-01-02", INTERVAL 31 DAY);
    -> 1997-12-02
Если Вы определяете значение интервала, которое является слишком коротким (не включает все части интервала, которые ожидались бы из ключевого слова type), MySQL считает, что Вы не учли крайние левые части значения интервала. Например, если Вы определяете type как DAY_SECOND, значение expr, как ожидается, будет иметь дни, часы, минуты и секунды. Если Вы определяете, что значение выглядит как "1:10", MySQL считает, что части дней и часов отсутствуют, а значение представляет минуты и секунды. Другими словами, "1:10" DAY_SECOND интерпретируется таким способом, которым это является эквивалентным "1:10" MINUTE_SECOND. Это аналогично пути, которым MySQL интерпретирует значения TIME как представление прошедшего времени, а не время дня. Обратите внимание, что, если Вы добавляете или вычитаете значение date, работая с частями времени, оно будет автоматически преобразовано в значение time:
mysql> select date_add("1999-01-01", interval 1 day);
    -> 1999-01-02
mysql> select date_add("1999-01-01", interval 1 hour);
    -> 1999-01-01 01:00:00
Если Вы используете, действительно, неправильные даты, результатом будет NULL. Если Вы добавляете MONTH, YEAR_MONTH или YEAR, и возникающая в результате дата имеет день, который является большим, чем максимальный день нового месяца, день откорректирован к максимальному дню в новом месяце:
mysql> select DATE_ADD('1998-01-30', Interval 1 month);
    -> 1998-02-28
Обратите внимание, что слово INTERVAL и ключевое слово type не чувствительны к регистру.
EXTRACT(type FROM date)
Функция EXTRACT() использует те же самые виды спецификаторов типа интервала, что и DATE_ADD() или DATE_SUB(), но извлекает части даты, а не проводит выполнение арифметики даты.
mysql> SELECT EXTRACT(YEAR FROM "1999-07-02");
    -> 1999
mysql> SELECT EXTRACT(YEAR_MONTH FROM "1999-07-02 01:02:03");
    -> 199907
mysql> SELECT EXTRACT(DAY_MINUTE FROM "1999-07-02 01:02:03");
    -> 20102
TO_DAYS(date)
Берет дату date, возвращает порядковый номер дня, считая с самого первого года:
mysql> select TO_DAYS(950501);
    -> 728779
mysql> select TO_DAYS('1997-10-07');
    -> 729669
TO_DAYS() не предназначена для использования со значениями, которые предшествуют появлению Грегорианского календаря (1582) потому, что эта функция не принимает во внимание дни, которые были потеряны, когда календарь был изменен.
FROM_DAYS(N)
Берет номер дня N, возвращает значение DATE:
mysql> select FROM_DAYS(729669);
    -> '1997-10-07'
FROM_DAYS() не предназначена для использования со значениями, которые предшествуют появлению Грегорианского календаря (1582) потому, что эта функция не принимает во внимание дни, которые были потеряны, когда календарь был изменен.
DATE_FORMAT(date,format)
Форматирует значение date согласно строке format. Следующие спецификаторы могут использоваться в формате:
%M | Имя месяца (январь..декабрь).
%W | День недели (воскресенье..суббота).
%D | День месяца с английским суффиксом (1st, 2nd, 3rd, ...).
%Y | Год, числовое представление, 4 цифры.
%y | Год, числовое представление, 2 цифры.
%X | Год для недель, где воскресенье первый день недели, числовое представление, 4 цифры, используемые с '%V'.
%x | Год для недель, где понедельник первый день недели, числовое представление, 4 цифры, используемые с '%v'.
%a | Краткая форма названия дня (Sun..Sat).
%d | День месяца, числовой (00..31).
%e | День месяца, числовой (0..31).
%m | Месяц, числовой (01..12).
%c | Месяц, числовой (1..12).
%b | Краткая форма названия месяца (Jan..Dec).
%j | День года (001..366).
%H | Час (00..23).
%k | Час (0..23).
%h | Час (01..12).
%I | Час (01..12).
%l | Час (1..12).
%i | Минуты, числовая форма (00..59).
%r | Время, 12-часовой формат (hh:mm:ss [AP]M).
%T | Время, 24-часовой формат (hh:mm:ss).
%S | Секунды (00..59).
%s | Секунды (00..59).
%p | AM или PM.
%w | День недели (0=воскресенье..6=суббота).
%U | Неделя (0..53), где воскресенье первый день недели.
%u | Неделя (0..53), где понедельник первый день недели.
%V | Неделя (1..53), где воскресенье первый день недели. Использован с '%X'.
%v | Неделя (1..53), где понедельник первый день недели. Использован с '%x'.
%% Знак процента (%).
Все другие символы будут только скопированы в результат без интерпретации:
mysql> select DATE_FORMAT('1997-10-04 22:23:00', '%W %M %Y');
    -> 'Saturday October 1997'
mysql> select DATE_FORMAT('1997-10-04 22:23:00', '%H:%i:%s');
    -> '22:23:00'
mysql> select DATE_FORMAT('1997-10-04 22:23:00',
                              '%D %y %a %d %m %b %j');
    -> '4th 97 Sat 04 10 Oct 277'
mysql> select DATE_FORMAT('1997-10-04 22:23:00',
                              '%H %k %I %r %T %S %w');
    -> '22 22 10 10:23:00 PM 22:23:00 00 6'
mysql> select DATE_FORMAT('1999-01-01', '%X %V');
    -> '1998 52'
Начиная с MySQL Version 3.23, символ % обязательно требуется указывать перед символами спецификатора формата. В более ранних версиях MySQL символ % был факультативным.
TIME_FORMAT(time,format)
Это используется подобно функции DATE_FORMAT(), но строка format может содержать только те спецификаторы формата, которые обрабатывают часы, минуты и секунды. Другие спецификаторы производят значения NULL или 0.
CURDATE()
CURRENT_DATE
Возвращает сегодняшнюю дату как значение в формате YYYY-MM-DD или YYYYMMDD, в зависимости от того, используется ли функция в контексте строки или числа:
mysql> select CURDATE();
    -> '1997-12-15'
mysql> select CURDATE() + 0;
    -> 19971215
CURTIME()
CURRENT_TIME
Возвращает текущее время как значение в формате HH:MM:SS или HHMMSS, в зависимости от того, используется ли функция в контексте строки или числа:
mysql> select CURTIME();
    -> '23:50:26'
mysql> select CURTIME() + 0;
    -> 235026
NOW()
SYSDATE()
CURRENT_TIMESTAMP
Возвращает текущую дату и время как значение в формате YYYY-MM-DD HH:MM:SS или YYYYMMDDHHMMSS в зависимости от того, используется ли функция в контексте строки или числа:
mysql> select NOW();
    -> '1997-12-15 23:50:26'
mysql> select NOW() + 0;
    -> 19971215235026
UNIX_TIMESTAMP()
UNIX_TIMESTAMP(date)
Если вызвано без параметра, возвращает Unix timestamp (секунды с момента 1970-01-01 00:00:00 GMT). Если UNIX_TIMESTAMP() вызван с параметром date, это возвращает значение параметра как секунды с момента 1970-01-01 00:00:00 GMT. date может быть строками типов DATE, DATETIME, TIMESTAMP или числом в форматах YYMMDD или YYYYMMDD в местном времени:
mysql> select UNIX_TIMESTAMP();
    -> 882226357
mysql> select UNIX_TIMESTAMP('1997-10-04 22:23:00');
    -> 875996580
Когда UNIX_TIMESTAMP используется на столбце типа TIMESTAMP, функция получит значение непосредственно, без неявного преобразования ``string-to-unix-timestamp''. Если Вы задаете UNIX_TIMESTAMP() неправильно, вернется 0.
FROM_UNIXTIME(unix_timestamp)
Возвращает представление параметра unix_timestamp как значение в формате YYYY-MM-DD HH:MM:SS или YYYYMMDDHHMMSS в зависимости от того, используется ли функция в контексте строки или числа:
mysql> select FROM_UNIXTIME(875996580);
    -> '1997-10-04 22:23:00'
mysql> select FROM_UNIXTIME(875996580) + 0;
    -> 19971004222300
FROM_UNIXTIME(unix_timestamp,format)
Возвращает представление параметра unix_timestamp как строку, форматируемую согласно строке format. Строка format может содержать те же самые спецификаторы, что и для функции DATE_FORMAT():
mysql> select FROM_UNIXTIME(UNIX_TIMESTAMP(),
                            '%Y %D %M %h:%i:%s %x');
    -> '1997 23rd December 03:43:30 x'
SEC_TO_TIME(seconds)
Возвращает параметр seconds, преобразованный в часы, минуты и секунды, как значение в формате HH:MM:SS или HHMMSS в зависимости от того, используется ли функция в контексте строки или числа:
mysql> select SEC_TO_TIME(2378);
    -> '00:39:38'
mysql> select SEC_TO_TIME(2378) + 0;
    -> 3938
TIME_TO_SEC(time)
Возвращает параметр time, преобразованный в секунды:
mysql> select TIME_TO_SEC('22:23:00');
    -> 80580
mysql> select TIME_TO_SEC('00:39:38');
    -> 2378

6.5 Прочие функции

6.5.1 Битовые функции

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

|
Побитовое OR:
mysql> select 29 | 15;
    -> 31
&
Побитовое AND:
mysql> select 29 & 15;
    -> 13
<<
Сдвигает число типа longlong (BIGINT) влево:
mysql> select 1 << 2;
    -> 4
>>
Сдвигает число типа longlong (BIGINT) вправо:
mysql> select 4 >> 2;
    -> 1
~
Инвертирует все биты:
mysql> select 5 & ~1;
    -> 4
BIT_COUNT(N)
Возвращает число битов, которые установлены в параметре N:
mysql> select BIT_COUNT(29);
    -> 4

6.5.2 Дополнительные функции

DATABASE()
Возвращает текущее имя базы данных:
mysql> select DATABASE();
    -> 'test'
Если не имеется никакой текущей базы данных, DATABASE() возвращает пустую строку.
USER()
SYSTEM_USER()
SESSION_USER()
Возвращает текущее имя пользователя MySQL:
mysql> select USER();
    -> 'davida@localhost'
В MySQL Version 3.22.11 и более поздних версиях это включает hostname пользователя, а не только имя пользователя. Вы можете извлекать только часть имени пользователя подобно этому:
mysql> select substring_index(USER(),"@",1);
    -> 'davida'
PASSWORD(str)
Вычисляет строку пароля из открытого текста str. Это функция, которая используется для шифрования паролей MySQL для хранения в столбце Password таблицы привилегий user:
mysql> select PASSWORD('badpwd');
    -> '7f84554057dd964b'
Шифрование PASSWORD() необратимо. PASSWORD() не выполняет шифрование пароля таким же образом, что и Unix. Вы не должны считать, что, если Ваши пароли для Unix и MySQL одинаковы, PASSWORD() выдаст то же самое шифрованное значение, какое сохранено в файле паролей Unix. См. функцию ENCRYPT().
ENCRYPT(str[,salt])
Шифрует str, используя системный вызов Unix crypt(). Параметр salt должен быть строкой с двумя символами. Начиная с MySQL Version 3.22.16, salt может быть длиннее, чем два символа:
mysql> select ENCRYPT("hello");
    -> 'VxuFAJXVARROc'
Если crypt() недоступен на Вашей системе, ENCRYPT() всегда возвращает NULL. ENCRYPT() игнорирует все, кроме первых 8 символов str, по крайней мере на некоторых системах. Это определено поведением системного вызова crypt().
ENCODE(str,pass_str)
Шифрует str, используя pass_str как пароль. Для дешифрования примените вызов DECODE(). Результат: двоичная строка string той же самой длины. Если Вы хотите сохранять это в столбце, используйте тип столбца BLOB.
DECODE(crypt_str,pass_str)
Дешифрует зашифрованную строку crypt_str, используя pass_str как пароль. crypt_str должна быть строкой, возвращенной из ENCODE().
MD5(string)
Вычисляет контрольную сумму MD5 для строки. Значение возвращено как 32 разрядное шестнадцатеричное число, которое может, например, использоваться как ключ хэширования:
mysql> select MD5("testing");
    -> 'ae2b1fca515949e5d54fb22b8ed95575'
Это "RSA Data Security, Inc. MD5 Message-Digest Algorithm".
LAST_INSERT_ID([expr])
Возвращает последнее автоматически сгенерированное значение, которое было вставлено в столбец с поддержкой AUTO_INCREMENT.
mysql> select LAST_INSERT_ID();
    -> 195
Последний ID, который был сгенерирован, поддерживается сервером на основании подключения. Это не будет изменено другим пользователем. Это не будет даже изменено, если Вы модифицируете другой столбец AUTO_INCREMENT с нормальным значением (то есть значением, которое не NULL и не 0). Если Вы вставляете много строк в то же самое время с инструкцией insert, LAST_INSERT_ID() возвращает значение для первой вставленной строки. Причина для этого в том, чтобы сделать возможным легкое воспроизведение той же самой инструкции на другом сервере. Если expr дан как параметр LAST_INSERT_ID(), то значение параметра возвращенного функцией, будет установлено в следующее значение, которое будет возвращено LAST_INSERT_ID() и будет использоваться как следующее значение auto_increment. Это может применяться, чтобы моделировать последовательности. Сначала создайте таблицу:
mysql> create table sequence (id int not null);
mysql> insert into sequence values (0);
Затем таблица может использоваться, чтобы генерировать числа последовательности подобно этому:
mysql> update sequence set id=LAST_INSERT_ID(id+1);
Вы можете генерировать последовательности без того, чтобы вызвать LAST_INSERT_ID(), но полезность использования функции состоит в том, что значение ID поддерживается сервером как последнее автоматически сгенерированное значение. Вы можете получить новый ID чтением любого нормального значения AUTO_INCREMENT в MySQL. Например, LAST_INSERT_ID() (без параметра) возвратит новый ID. Функция C API mysql_insert_id() может также использоваться, чтобы получить значение. Обратите внимание, что поскольку mysql_insert_id() модифицируется только после инструкций INSERT и UPDATE, Вы не можете использовать эту функцию, чтобы получать значение для LAST_INSERT_ID(expr) после выполнения других инструкций SQL подобно SELECT или SET.
FORMAT(X,D)
Форматирует число X к формату подобно #,###,###.##, округляя к D десятичным цифрам. Если D равен 0, результат не будет иметь никакой десятичной отметки или дробной части:
mysql> select FORMAT(12332.123456, 4);
    -> '12,332.1235'
mysql> select FORMAT(12332.1,4);
    -> '12,332.1000'
mysql> select FORMAT(12332.2,0);
    -> '12,332'
VERSION()
Возвращает строку, указывающую версию MySQL:
mysql> select VERSION();
    -> '3.23.13-log'
Обратите внимание, что, если Ваша версия заканчивается словом -log, это означает, что регистрация допускается.
CONNECTION_ID()
Возвращает идентификатор подключения (thread_id) для соединения. Каждое подключение имеет собственный уникальный идентификатор:
mysql> select CONNECTION_ID();
    -> 1
GET_LOCK(str,timeout)
Пробует получать блокировку с именем, заданным строкой str, со временем ожидания timeout секунд. Возвратит 1, если блокировка была получена успешно, 0 если попытка провалилась по тайм-ауту, или NULL если произошла ошибка (типа исчерпания памяти или уничтожения процесса командой mysqladmin kill). Блокировка будет снята, когда Вы выполняете RELEASE_LOCK(), новый вызов GET_LOCK() или процесс завершается. Эта функция может использоваться, чтобы выполнить блокировки прикладной программы или моделировать блокировки записи. Это блокирует запросы другой клиентуры для блокировок с тем же самым именем: клиентура, которая договаривается о данном имени блокировки, может использовать строку, чтобы выполнить совместную (кооперативную) консультативную блокировку:
mysql> select GET_LOCK("lock1",10);
    -> 1
mysql> select GET_LOCK("lock2",10);
    -> 1
mysql> select RELEASE_LOCK("lock2");
    -> 1
mysql> select RELEASE_LOCK("lock1");
    -> NULL
Обратите внимание, что второй вызов RELEASE_LOCK() вернет NULL потому, что блокировка lock1 была автоматически снята вторым вызовом GET_LOCK().
RELEASE_LOCK(str)
Снимает блокировку, именованную строкой str, которая была получена с GET_LOCK(). Возвратит 1, если блокировка была нормально снята, 0, если блокировка не была блокирована этим потоком (когда блокировка не снята), или NULL, если поименованная блокировка не существует. Блокировка не существует, если она никогда не была получена обращением к GET_LOCK() или уже снята.
BENCHMARK(count,expr)
Функция BENCHMARK() выполняет вычисление выражения expr count раз. Это может использоваться для измерения того, как быстро MySQL обрабатывает выражение. Значение результата всегда 0. Предназначено для использования клиентом mysql, который сообщает времена выполнения запроса:
mysql> select BENCHMARK(1000000,encode("hello","goodbye"));
  +----------------------------------------------+
  | BENCHMARK(1000000,encode("hello","goodbye")) |
  +----------------------------------------------+
  |                                            0 |
  +----------------------------------------------+
1 row in set (4.74 sec)
Сообщенное время представляет собой время, прошедшее на стороне клиента, а не CPU time на сервере! Может быть, желательно выполнить BENCHMARK() несколько раз, и интерпретировать результат с отношением к тому, как тяжело был загружен сервер.
INET_NTOA(expr)
Возвращает сетевой адрес (4 или 8 байт) для числового выражения:
mysql> select INET_NTOA(3520061480);
    -> "209.207.224.40"
INET_ATON(expr)
Возвращает целое число, которое представляет числовое значение для сетевого адреса. Адреса могут быть длиной в 4 или 8 байт:
mysql> select INET_ATON("209.207.224.40");
    -> 3520061480
Сгенерированное число всегда в порядке сетевых байт. Например, вышеупомянутое число вычислено как 209*255^3+207*255^2+224*255+40.
MASTER_POS_WAIT(log_name, log_pos)
Блокирует работу пока подчиненный сервер достигает определенной позиции в главном файле регистрации в течение репликации. Если главная информация не инициализирована, возвращает NULL. Если подчиненный не работает, блокирует работу и будет ждать, пока тот не запустится. Если подчиненный уже достиг определенной позиции, возврат управления произойдет немедленно. Значение возврата: число событий файла регистрации, которое следует пропустить, чтобы дойти до определенной позиции, или NULL в случае ошибки. Полезно для управления синхронизацией, но было первоначально написано для отладки.

6.6 Функции для применения в предложении GROUP BY

Если Вы используете функцию в инструкции, не содержащей предложение GROUP BY, это эквивалентно группировке на всех строках.

COUNT(expr)
Возвращает количество не-NULL (возможно, одинаковых) значений в строках, найденных SELECT:
mysql> select student.student_name,COUNT(*) from student,course
                  where student.student_id=course.student_id
                  GROUP BY student_name;
COUNT(*) оптимизирован, чтобы возвратить данные очень быстро, если SELECT получает данные из одной таблицы, никакие другие столбцы не задействованы, и в запросе не имеется никакого предложения WHERE. Например:
mysql> select COUNT(*) from student;
COUNT(DISTINCT expr,[expr...])
Возвращает число различных значений не-NULL:
mysql> select COUNT(DISTINCT results) from student;
В MySQL Вы можете получить число различных комбинаций выражений, которые не содержат NULL, задавая список выражений. В ANSI SQL Вы были бы должны сделать конкатенацию всех выражений внутри CODE(DISTINCT...).
AVG(expr)
Возвращает среднее значение expr:
mysql> select student_name, AVG(test_score)
                  from student
                  GROUP BY student_name;
MIN(expr)
MAX(expr)
Возвращает минимальное или максимальное значение expr. MIN() и MAX() может брать строковый параметр. В таких случаях они возвращают минимальное или максимальное значение строки.
mysql> select student_name, MIN(test_score), MAX(test_score)
                  from student
                  GROUP BY student_name;
SUM(expr)
Возвращает сумму expr. Обратите внимание, что, если набор возвратов не имеет никаких строк, это возвращает NULL!
STD(expr)
STDDEV(expr)
Возвращает стандартное отклонение expr. Это расширение ANSI SQL. Форма STDDEV() этой функции предусмотрена для совместимости с Oracle.
BIT_OR(expr)
Возвращается поразрядный OR всех битов в expr. Вычисление выполняется с 64-разрядной точностью (BIGINT).
BIT_AND(expr)
Возвращается поразрядный AND всех битов в expr. Вычисление выполняется с 64-разрядной точностью (BIGINT).

MySQL расширил использование GROUP BY. Вы можете использовать столбцы или вычисления в выражениях SELECT, которые не появляются в части GROUP BY. Это соответствует любому возможному значению для этой группы. Вы можете использовать это, чтобы получить лучшую эффективность, избегая сортировки и группировки на ненужных элементах. Например, Вы не должны группировать на customer.name в следующем запросе:

mysql> select order.custid,customer.name,max(payments)
                  from order,customer where order.custid=customer.custid
                  GROUP BY order.custid;

В ANSI SQL Вы были бы должны добавить customer.name к предложению GROUP BY. В MySQL имя избыточно, если Вы не выполняетесь в ANSI режиме.

Не используйте это свойство, если столбцы, которые Вы получаете из предложения GROUP BY не уникальны в группе! Вы получите непредсказуемые результаты.

В некоторых случаях Вы можете использовать MIN() и MAX() чтобы получить специфическое значение столбца, даже если оно неуникально. Следующее выдает значение column из строки, содержащей самое маленькое значение в столбце sort:

substr(MIN(concat(rpad(sort,6,' '),column)),7)

Подробности в разделе "3.5.4 В какой строке максимум по группе".

Обратите внимание, что, если Вы используете MySQL Version 3.22 (или ранее), или если Вы пробуете следовать ANSI SQL, Вы не можете использовать выражения в предложениях GROUP BY или ORDER BY. Вы можете обойти это ограничение, используя псевдоним для выражения:

mysql> SELECT id,FLOOR(value/100) AS val
                  FROM tbl_name
                  GROUP BY id,val ORDER BY val;

В MySQL Version 3.23 Вы можете сделать:

mysql> SELECT id,FLOOR(value/100) FROM tbl_name ORDER BY RAND();

6.7 Описание синтаксиса регулярных выражений MySQL

Регулярные выражения (они же regular expression или regex) представляют собой мощный путь для определения сложного поиска.

MySQL использует реализацию Henry Spencer's, которая нацелена на соответствие POSIX 1003.2. MySQL использует ее расширенную версию.

Это упрощенное описание, которое опускает ряд деталей. За подробной информацией отсылаю Вас к man-странице Henry Spencer's regex(7), которая включена в дистрибутив исходного кода.

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

Нетривиальные регулярные выражения используют некоторые специальные конструкции так, чтобы они могли соответствовать больше, чем одной строке. Например, regexp hello|word соответствует строке hello или word.

Как более сложный пример, regexp B[an]*s соответствует любой из строк Bananas, Baaaaas, Bs и любой другой строке, начинающейся с B, заканчивающейся на s и содержащей любое число символов в диапазоне от a до n между ними.

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

^
Соответствует началу строки.
mysql> select "fo\nfo" REGEXP "^fo$"; -> 0
mysql> select "fofo" REGEXP "^fo";    -> 1
$
Соответствует концу строки.
mysql> select "fo\no" REGEXP "^fo\no$"; -> 1
mysql> select "fo\no" REGEXP "^fo$";    -> 0
.
Соответствует любому символу (включая newline).
mysql> select "fofo" REGEXP "^f.*";   -> 1
mysql> select "fo\nfo" REGEXP "^f.*"; -> 1
a*
Соответствует любой последовательности из ноля или больше символов. a.
mysql> select "Ban" REGEXP "^Ba*n";   -> 1
mysql> select "Baaan" REGEXP "^Ba*n"; -> 1
mysql> select "Bn" REGEXP "^Ba*n";    -> 1
a+
Соответствует любой последовательности из одного или больше символов. a.
mysql> select "Ban" REGEXP "^Ba+n"; -> 1
mysql> select "Bn" REGEXP "^Ba+n";  -> 0
a?
Соответствует нолю или одному символу a.
mysql> select "Bn" REGEXP "^Ba?n";   -> 1
mysql> select "Ban" REGEXP "^Ba?n";  -> 1
mysql> select "Baan" REGEXP "^Ba?n"; -> 0
de|abc
Соответствует последовательностям de или abc.
mysql> select "pi" REGEXP "pi|apa";  -> 1
mysql> select "axe" REGEXP "pi|apa"; -> 0
mysql> select "apa" REGEXP "pi|apa"; -> 1
mysql> select "apa" REGEXP "^(pi|apa)$"; -> 1
mysql> select "pi" REGEXP "^(pi|apa)$";  -> 1
mysql> select "pix" REGEXP "^(pi|apa)$"; -> 0
(abc)*
Соответствует нолю или большему количеству образцов последовательности abc.
mysql> select "pi" REGEXP "^(pi)*$";   -> 1
mysql> select "pip" REGEXP "^(pi)*$";  -> 0
mysql> select "pipi" REGEXP "^(pi)*$"; -> 1
{1}
{2,3}
Более общий путь записи regexp, которые соответствуют нескольким местонахождениям предыдущего атома.
a*
Может быть написан как a{0,}.
a+
Может быть написан как a{1,}.
a?
Может быть написан как a{0,1}.
Чтобы быть более точным, атом, сопровождаемый одним целым числом i без запятой соответствует последовательности точно i вхождений атома. Атом, сопровождаемый одним числом с запятой, соответствует последовательности из одного или большего числа вхождений i. Атом, сопровождаемый двумя целыми числами i и j соответствует последовательности, включающей от i до j копий атома (границы диапазона входят в число). Оба аргумента должны быть в диапазоне от 0 до RE_DUP_MAX (по умолчанию 255), включая границы. Если заданы два аргумента, второй должен быть больше или равен первому, но не меньше его.
[a-dX]
[^a-dX]
Соответствует любому символу, который является (или не является, если используется ^) одним из: a, b, c, d или X. Чтобы включить литеральный символ ], он должен следовать сразу за открывающейся скобкой [. Чтобы включить символ -, он должен быть написан первым или последним. Так [0-9] соответствует любой десятичной цифре. Любой символ, который не имеет определенного значения внутри [], не имеет никакого специального значения.
mysql> select "aXbc" REGEXP "[a-dXYZ]";    -> 1
mysql> select "aXbc" REGEXP "^[a-dXYZ]$";  -> 0
mysql> select "aXbc" REGEXP "^[a-dXYZ]+$"; -> 1
mysql> select "aXbc" REGEXP "^[^a-dXYZ]+$";   -> 0
mysql> select "gheis" REGEXP "^[^a-dXYZ]+$";  -> 1
mysql> select "gheisa" REGEXP "^[^a-dXYZ]+$"; -> 0
[[.characters.]]
Последовательность символов. Последовательность представляет собой одиночный элемент из списка выражений в скобках. Выражение, содержащее много символов, может таким образом соответствовать больше, чем одному символу, например, если последовательность сопоставления включает элемент ch, то регулярное выражение [[.ch.]]*c соответствует первым пяти символам chchcc.
[=character_class=]
Класс эквивалентности, состоящий из последовательностей символов, включая себя. Например, если o и (+) члены класса эквивалентности, то [[=o=]], [[=(+)=]] и [o(+)] синонимы. Класс эквивалентности не может быть краем диапазона.
[:character_class:]
В выражении в скобках имя символьного класса, включенного в [: и :], представляет список всех символов, принадлежащих к классу. Стандартные символьные имена:
alnum | digit | punct
alpha | graph | space
blank | lower | upper
cntrl | print | xdigit
Это указано для символьных классов, определенных на man-странице ctype(3). Регион или язык может обеспечивать другие. Символьный класс не может использоваться как край диапазона.
mysql> select "justalnums" REGEXP "[[:alnum:]]+"; -> 1
mysql> select "!!" REGEXP "[[:alnum:]]+";         -> 0
[[:<:]]
[[:>:]]
Соответствуют нулевой (пустой) строке в начале и в конце слова соответственно. Слово определено как последовательность символов alnum (как определено в ctype(3)) или символов подчеркивания (_).
mysql> select "a word a" REGEXP "[[:<:]]word[[:>:]]";  -> 1
mysql> select "a xword a" REGEXP "[[:<:]]word[[:>:]]"; -> 0

mysql> select "weeknights" REGEXP "^(wee|week)(knights|nights)$"; -> 1


Определение данных: CREATE, DROP, ALTER

7 Определение данных: CREATE, DROP, ALTER

7.1 Синтаксис CREATE DATABASE

CREATE DATABASE [IF NOT EXISTS] db_name

CREATE DATABASE создает базу данных с указанным именем. Правила для допустимых имен баз данных приведены в разделе "3.2 Имена баз данных, таблиц, индексов, столбцов и псевдонимов". Ошибка происходит, если база данных уже существует, и Вы не определяли IF NOT EXISTS.

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

Вы можете также создавать базы данных с помощью программы mysqladmin. Подробности в разделе "12 Клиентские скрипты и утилиты MySQL".

7.2 Синтаксис DROP DATABASE

DROP DATABASE [IF EXISTS] db_name

DROP DATABASE удаляет все таблицы в базе данных и удаляет саму базу данных. Если выполнили DROP DATABASE на символически связанной базе данных, связь и первоначальная база данных будут удалены. Будьте ОЧЕНЬ осторожны с этой командой!

DROP DATABASE возвращает число файлов, которые были удалены из каталога баз данных. Обычно это кратное трем число потому, что каждая таблица соответствует файлам .MYD, .MYI и .frm.

Команда DROP DATABASE удаляет из заданного каталога базы данных все найденные файлы со следующими расширениями:

.BAK | .DAT | .HSH | .ISD
.ISM | .ISM | .MRG | .MYD
.MYI | .db | .frm

Все подкаталоги, имена которых состоят из 2 цифр (каталоги RAID), также будут удалены.

В MySQL Version 3.22 или позже Вы можете использовать ключевые слова IF EXISTS, чтобы предотвратить ошибку, если база данных не существует.

Вы можете также удалять базы данных с помощью команды mysqladmin. Подробности в разделе "12 Клиентские скрипты и утилиты MySQL".

7.3 Синтаксис CREATE TABLE

CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name [(create_definition,...)]
[table_options] [select_statement]

create_definition:
  col_name type [NOT NULL | NULL] [DEFAULT default_value] [AUTO_INCREMENT]
            [PRIMARY KEY] [reference_definition]
  or    PRIMARY KEY (index_col_name,...)
  or    KEY [index_name] (index_col_name,...)
  or    INDEX [index_name] (index_col_name,...)
  or    UNIQUE [INDEX] [index_name] (index_col_name,...)
  or    FULLTEXT [INDEX] [index_name] (index_col_name,...)
  or    [CONSTRAINT symbol] FOREIGN KEY index_name (index_col_name,...)
            [reference_definition]
  or    CHECK (expr)

type:
        TINYINT[(length)] [UNSIGNED] [ZEROFILL]
  or    SMALLINT[(length)] [UNSIGNED] [ZEROFILL]
  or    MEDIUMINT[(length)] [UNSIGNED] [ZEROFILL]
  or    INT[(length)] [UNSIGNED] [ZEROFILL]
  or    INTEGER[(length)] [UNSIGNED] [ZEROFILL]
  or    BIGINT[(length)] [UNSIGNED] [ZEROFILL]
  or    REAL[(length,decimals)] [UNSIGNED] [ZEROFILL]
  or    DOUBLE[(length,decimals)] [UNSIGNED] [ZEROFILL]
  or    FLOAT[(length,decimals)] [UNSIGNED] [ZEROFILL]
  or    DECIMAL(length,decimals) [UNSIGNED] [ZEROFILL]
  or    NUMERIC(length,decimals) [UNSIGNED] [ZEROFILL]
  or    CHAR(length) [BINARY]
  or    VARCHAR(length) [BINARY]
  or    DATE
  or    TIME
  or    TIMESTAMP
  or    DATETIME
  or    TINYBLOB
  or    BLOB
  or    MEDIUMBLOB
  or    LONGBLOB
  or    TINYTEXT
  or    TEXT
  or    MEDIUMTEXT
  or    LONGTEXT
  or    ENUM(value1,value2,value3,...)
  or    SET(value1,value2,value3,...)

index_col_name:
        col_name [(length)]

reference_definition:
        REFERENCES tbl_name [(index_col_name,...)]
                   [MATCH FULL | MATCH PARTIAL]
                   [ON DELETE reference_option]
                   [ON UPDATE reference_option]

reference_option:
        RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT

table_options:
        TYPE = {BDB | HEAP | ISAM | InnoDB | MERGE | MYISAM }
or      AUTO_INCREMENT = #
or      AVG_ROW_LENGTH = #
or      CHECKSUM = {0 | 1}
or      COMMENT = "string"
or      MAX_ROWS = #
or      MIN_ROWS = #
or      PACK_KEYS = {0 | 1}
or      PASSWORD = "string"
or      DELAY_KEY_WRITE = {0 | 1}
or      ROW_FORMAT= { default | dynamic | fixed | compressed }
or      RAID_TYPE= {1 | STRIPED | RAID0 } RAID_CHUNKS=#  RAID_CHUNKSIZE=#
or      UNION = (table_name,[table_name...])
or      DATA DIRECTORY="directory"
or      INDEX DIRECTORY="directory"

select_statement:
        [IGNORE | REPLACE] SELECT ...  (Some legal select statement)

CREATE TABLE создает таблицу с заданным именем в текущей базе данных. Правила для допустимых имен таблицы даны в разделе "3.2 Имена баз данных, таблиц, индексов, столбцов и псевдонимов". Ошибка происходит, если не имеется никакой текущей базы данных, или если таблица уже существует.

В MySQL Version 3.22 или позже имя таблицы может быть определено как db_name.tbl_name. Это работает независимо от того, имеется или нет текущая база данных.

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

В MySQL Version 3.23 или позже Вы можете использовать ключевые слова IF NOT EXISTS, чтобы ошибка не произошла, если таблица уже существует. Обратите внимание, что не имеется никакой проверки, что структуры таблиц идентичны.

Каждая таблица tbl_name представляется некоторыми файлами в каталоге баз данных. В случае таблиц MyISAM-типа Вы получите:

Файл | Назначение
tbl_name.frm | Определение таблицы (форма)
tbl_name.MYD | Данные таблицы
tbl_name.MYI | Индекс таблицы

Для получения большего количества информации относительно свойств различных типов столбцов обратитесь к разделу "5 Типы столбцов":

  • Если NULL или NOT NULL не определены, столбец обрабатывается, как если бы был определен NULL.
  • Целочисленный столбец может иметь дополнительный атрибут AUTO_INCREMENT. Когда Вы вставляете значение NULL (рекомендуется) или 0 в столбец с атрибутом AUTO_INCREMENT, столбец будет установлен в значение value+1, где value представляет собой самое большое значение для столбца в настоящее время в данной таблице. AUTO_INCREMENT-последовательности начинаются с 1. Если Вы удаляете строку, содержащую максимальное значение для столбца AUTO_INCREMENT, значение будет многократно использоваться для таблиц ISAM или BDB, но не для таблиц типов MyISAM или InnoDB. Если Вы удаляете все строки в таблице с помощью вызова DELETE FROM table_name (без WHERE) в режиме AUTOCOMMIT, последовательность начинается сначала для всех типов таблицы. ОБРАТИТЕ ВНИМАНИЕ: может иметься только один столбец AUTO_INCREMENT на таблицу, и он должен быть индексирован. MySQL Version 3.23 будет также работать правильно, только если столбец auto_increment имеет только положительные значения. Вставка отрицательного числа будет расценена как вставка очень большого положительного номера. Это выполнено, чтобы избежать проблем точности, когда числа переходят от положительного к отрицательному и также гарантировать, что случайно не получается столбец auto_increment, который содержит 0. Чтобы сделать MySQL совместимым с некоторыми прикладными программами ODBC, Вы можете находить последнюю вставленную строку следующим запросом:
    SELECT * FROM tbl_name WHERE auto_col IS NULL
  • Значения NULL для столбцов TIMESTAMP будут обработаны иначе, чем для других типов столбцов. Вы не можете сохранять литеральный NULL в столбце TIMESTAMP. Установка столбца в NULL приведет его к текущей (актуальной) дате и времени. Поскольку столбцы TIMESTAMP ведут себя именно так, атрибуты NULL и NOT NULL не применяются нормальным способом и игнорируются, если Вы определяете их. С другой стороны, чтобы сделать это проще для MySQL-клиентуры, сервер сообщает, что таким столбцам могут быть назначены значения NULL (это и правда так), даже при том, что TIMESTAMP никогда фактически не будет содержать значение NULL. Вы можете видеть это, когда Вы используете DESCRIBE tbl_name, чтобы получить описание Вашей таблицы. Обратите внимание, что установка столбца TIMESTAMP в 0 не устанавливает его в NULL, поскольку 0 имеющее силу значение TIMESTAMP.
  • Если никакое значение DEFAULT не определено для столбца, MySQL автоматически назначает его. Если столбец может брать как значение NULL, значением по умолчанию будет именно NULL. Если столбец объявлен как NOT NULL, значение по умолчанию зависит от типа столбца:
    • Для числовых типов, не объявленных с атрибутом AUTO_INCREMENT, значение по умолчанию 0. Для столбцов AUTO_INCREMENT значением по умолчанию будет следующее значение в последовательности.
    • Для типов даты и времени, но не для TIMESTAMP, значением по умолчанию будет соответствующее нулевое значение для типа. Для первого в таблице столбца TIMESTAMP значением по умолчанию будет текущая (актуальная) дата и время. Подробности в разделе "5.2 Типы Date и Time".
    • Для строк, но не для ENUM, значением по умолчанию является пустая строка. Для типа ENUM первое значение перечисления.
    Значения по умолчанию должны быть константами. Это означает, например, что Вы не можете устанавливать значение по умолчанию для столбца даты в виде значения функции, типа NOW() или CURRENT_DATE.
  • KEY представляет собой синоним для INDEX.
  • В MySQL ключ UNIQUE может иметь только различные значения. Ошибка происходит, если Вы пробуете добавлять новую строку с ключом, который соответствует существующей строке.
  • PRIMARY KEY является уникальным KEY, причем все столбцы ключа должны быть определены как NOT NULL. В MySQL такой ключ именован как PRIMARY. Таблица может иметь только один PRIMARY KEY. Если Вы не имеете PRIMARY KEY, а некоторые прикладные программы просят о PRIMARY KEY в Ваших таблицах, MySQL возвратит первый ключ UNIQUE, который не имеет столбцов NULL.
  • PRIMARY KEY может быть многостолбцовым индексом. Однако, Вы не можете создавать такой индекс, использующий атрибут PRIMARY KEY в спецификации столбца. Выполнение этого отметит только один столбец как первичный. Вы должны использовать вызов PRIMARY KEY(index_col_name, ...).
  • Если ключи PRIMARY или UNIQUE состоят только из одного столбца, и он имеет тип integer, Вы можете также обратиться к нему как _rowid (нововведение в Version 3.23.11).
  • Если Вы не назначаете имя индексу, будет назначено то же самое имя, какое имеет первый index_col_name, с факультативным суффиксом (_2, _3, ...): чтобы сделать его уникальным. Вы можете видеть индексные имена для таблицы, используя SHOW INDEX FROM tbl_name. Подробности в разделе "4.5.5 Синтаксис SHOW".
  • Только тип таблицы MyISAM поддерживает индексы на столбцах, которые могут иметь значения NULL. В других случаях Вы должны объявить такие столбцы как NOT NULL.
  • С помощью инструкции col_name(length) Вы можете определять индекс, который использует только часть столбца типа CHAR или VARCHAR. Это может сделать индексный файл намного меньше.
  • Только тип таблицы MyISAM поддерживает индексы на столбцах типов BLOB и TEXT. При помещении индекса на столбце BLOB или TEXT Вы ДОЛЖНЫ всегда определять длину индекса:
    CREATE TABLE test (blob_col BLOB, index(blob_col(10)));
  • Когда Вы используете ORDER BY или GROUP BY со столбцом TEXT или BLOB, используется только первые max_sort_length байт. Подробности в разделе "5.3.2 Типы BLOB и TEXT ".
  • В MySQL Version 3.23.23 или позже Вы можете также создавать специальные индексы FULLTEXT. Они используются для полнотекстового поиска. Только тип таблицы MyISAM поддерживает индексы FULLTEXT. Они могут быть созданы только из столбцов типов VARCHAR и TEXT. Индексация всегда выполняется над всем столбцом, частичная индексация пока не поддержана. Подробности в разделе "9.4 Полнотекстовый поиск в MySQL".
  • Определения FOREIGN KEY, CHECK и REFERENCES фактически не делают ничего. Синтаксис для них обеспечивается только для совместимости, чтобы сделать проще портирование кода из других SQL-серверов и выполнять прикладные программы, которые создают таблицы со ссылками. Подробности в разделе "1.4.4 Функциональные возможности, отсутствующие в MySQL".
  • Каждый столбец со значением NULL берет один бит, округляя занятое им место до самого близкого байта.
  • Максимальная длина записи в байтах может быть вычислена следующим образом:
    row length = 1+(sum of column lengths)+
             (number of NULL columns+7)/8+
             (number of variable-length columns)
  • Опции table_options и SELECT выполнены только в MySQL Version 3.23 и выше.

    Различные типы таблиц:
    BDB или Berkeley_db | Транзакционно-безопасные таблицы с блокировкой страниц.
    HEAP | Данные для этих таблиц сохранены только в памяти.
    ISAM | Первоначальный драйвер таблицы.
    InnoDB | Транзакционно-безопасные таблицы с блокировкой строки.
    MERGE | Совокупность таблиц MyISAM, используемых как одна.
    MyISAM | Новый двоично-независимый драйвер таблицы, который заменяет формат ISAM.
    Если тип таблицы определен, и этот специфический тип недоступен, MySQL выберет тип таблицы самый близкий к тому, который Вы определили. Например, если определен TYPE=BDB, но этот дистрибутив MySQL не поддерживает таблицы типа BDB, таблица будет создана как MyISAM. Другие параметры таблицы используются, чтобы оптимизировать поведение таблицы. В большинстве случаев, Вы не должны их определять. Параметры всегда работают для всех типов таблицы, если не оговорено обратное явно.
    AUTO_INCREMENT | Установить следующее значение auto_increment для Вашей таблицы (только MyISAM).
    AVG_ROW_LENGTH | Приближенное значение средней длины строки для Вашей таблицы. Вы должны установить это только для больших таблиц с записями переменного размера.
    CHECKSUM | Установите это в 1, если Вы хотите, чтобы MySQL поддержал контрольную сумму для всех строк (делает таблицу немного медленнее, чтобы модифицировать, но делает проще поиск повреждений таблицы, только для MyISAM).
    COMMENT | 60-символьный комментарий к таблице.
    MAX_ROWS | Максимальное число строк, которое Вы планируете сохранять в таблице.
    MIN_ROWS | Минимальное число строк, которое Вы планируете сохранять в таблице.
    PACK_KEYS | Установите это в 1, если Вы хотите иметь меньший индекс. Это обычно делает модификации медленнее, зато чтения быстрее (только для MyISAM и ISAM).
    PASSWORD | Зашифровать файл .frm паролем. Эта опция не делает ничего в стандартной версии MySQL.
    DELAY_KEY_WRITE | Установите это в 1, если Вы хотите задержать обновление ключей таблицы до ее закрытия (только MyISAM).
    ROW_FORMAT | Определяет, как строки должны быть сохранены. В настоящее время Вы можете использовать только опции DYNAMIC и STATIC для таблиц типа MyISAM.
    Когда Вы применяете таблицу MyISAM, MySQL использует результат max_rows*avg_row_length, чтобы решить насколько большой будет возникающая в результате таблица. Если Вы не определяете любые из вышеупомянутых параметров, максимальный размер для таблицы будет 4G (или 2G, если Ваша операционная система поддерживают только таблицы 2G). Причина для этого: надо уменьшить размеры указателя, чтобы сделать индекс меньше и быстрее, если Вы действительно не нуждаетесь в больших файлах. Если Вы не используете PACK_KEYS, по умолчанию будут упакованы только строки, но не числа. Если Вы используете PACK_KEYS=1, числа будут упакованы также. При упаковке двоичных цифровых ключей MySQL использует префиксное сжатие. Это означает, что Вы получите большую пользу от этого только, если Вы имеете много чисел, которые являются теми же самыми. Префиксное сжатие означает, что каждый ключ нуждается в одном байте дополнительного пространства, чтобы указать, сколько байтов предыдущего ключа совпадают с текущим. Обратите внимание, что указатель на строку сохранен в порядке со старшим первым байтом непосредственно после ключа, чтобы улучшить сжатие. Это означает, что, если Вы имеете много равных ключей в строке, все последующие те же самые ключи будет обычно только брать 2 байта (включая указатель на строку). Сравните это с обычным случаем, где следующие ключи будут брать storage_size_for_key+pointer_size (обычно 4) байта. С другой стороны, если все ключи полностью различны, Вы будете терять 1 байт на ключ, если он не может иметь значения NULL (в этом случае, упакованная длина ключа будет сохранена в том же самом байте, который используется, чтобы отметить, что этот ключ имеет значение NULL).

  • Если Вы определяете SELECT после инструкции CREATE, MySQL создаст новые поля для всех элементов в SELECT. Например:
    mysql> CREATE TABLE test (a int not null auto_increment,
           primary key (a), key(b))
           TYPE=MyISAM SELECT b,c from test2;
    Это создаст таблицу типа MyISAM с тремя столбцами: a, b и c. Обратите внимание, что столбцы из инструкции SELECT будут добавлены к правой стороне таблицы. Пример:
    mysql> select * from foo;
+---+
| n |
+---+
| 1 |
+---+

mysql> create table bar (m int) select n from foo;
Query OK, 1 row affected (0.02 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> select * from bar;
+------+---+
| m    | n |
+------+---+
| NULL | 1 |
+------+---+
1 row in set (0.00 sec)
    Для каждой строки в таблице foo, строка будет вставлена в область bar со значениями из foo и значениями по умолчанию для новых столбцов. CREATE TABLE ... SELECT автоматически не будет создавать никаких индексов для Вас. Это должно быть выполнено преднамеренно, чтобы сделать команду настолько гибкой, насколько это вообще возможно. Если Вы хотите иметь индексы в созданной таблице, Вы должны определить их перед инструкцией SELECT:
    mysql> create table bar (unique (n)) select n from foo;
    Если происходят ошибки при копировании данных в таблицу, они будут автоматически удалены. Чтобы гарантировать, что файл регистрации модификаций может использоваться, чтобы освежить первоначальные таблицы, MySQL не будет позволять параллельные вставки в течение выполнения CREATE TABLE .... SELECT.
  • Опция RAID_TYPE поможет Вам обойти 2G/4G ограничение для файла данных MyISAM (но не индексного файла) на операционных системах, которые не поддерживают большие файлы. Вы можете получать также большее быстродействие, помещая каталоги RAID на различных физических дисках. RAID_TYPE будет работать с любой OS, если Вы сконфигурировали MySQL с опцией --with-raid. Пока единственный позволенный RAID_TYPE называется STRIPED (псевдонимы для него: 1 и RAID0). Если Вы определяете RAID_TYPE=STRIPED для таблицы MyISAM, MyISAM создаст каталоги RAID_CHUNKS с именами 00, 01, 02 в каталоге базы данных. В каждом из этих каталогов MyISAM создаст файл table_name.MYD. При записи данных в файл данных, драйвер RAID отобразит первые RAID_CHUNKSIZE*1024 байт на первый файл, второй кусок длиной в RAID_CHUNKSIZE*1024 байт на второй и так далее.
  • UNION используется, когда Вы хотите использовать совокупность идентичных таблиц как одну целую. Это работает только с таблицами типа MERGE. Вы должны иметь привилегии SELECT, UPDATE и DELETE на таблицах, которые Вы отображаете к таблице MERGE. Все отображенные таблицы должны быть в той же самой базе данных, что и таблица MERGE.
  • В созданной таблице ключ PRIMARY будет помещен в начало, за ним расположатся ключи UNIQUE, а за ними нормальные ключи. Это помогает оптимизатору MySQL располагать по приоритетам, который ключ использовать, а также более быстро обнаруживает дублированные ключи UNIQUE.
  • Используя DATA DIRECTORY="directory" или INDEX DIRECTORY="directory" Вы можете определять, где драйвер таблицы должен поместить файлы таблицы и индекса. Это работает только для таблиц MyISAM в MySQL 4.0, когда Вы не используете опцию --skip-symlink.

7.3.1 Тихие изменения спецификации столбца

В некоторых случаях MySQL тихо изменяет спецификацию столбца, заданную в инструкции CREATE TABLE. Это может также происходить с ALTER TABLE:

  • VARCHAR-столбцы с длиной меньше, чем четыре, будут изменены на CHAR.
  • Если любой столбец в таблице имеет переменную длину, вся строка будет в результате переменной длины. Следовательно, если таблица содержит любые столбцы переменной длины (VARCHAR, TEXT или BLOB), все столбцы CHAR длиной более, чем три символа, будут изменены на VARCHAR. В MySQL VARCHAR всего лишь иной способ хранить символы. MySQL выполняет это преобразование потому, что оно экономит место и делает операции с таблицей быстрее.
  • TIMESTAMP должен быть четный и в диапазоне от 2 до 14. Если Вы определяете 0 или больше, чем 14, размер принудительно выставится в 14. Нечетно-оцененные размеры в диапазоне от 1 до 13 принудительно выставятся в следующее более высокое четное число.
  • Вы не можете сохранять литеральный NULL в столбце TIMESTAMP. Установка его в NULL реально устанавливает его к текущей (актуальной) дате и времени. Потому, что столбцы TIMESTAMP ведут себя именно так, атрибуты NULL и NOT NULL не применяются нормальным способом и игнорируются, если Вы определяете их. DESCRIBE tbl_name всегда сообщает, что столбцу TIMESTAMP может быть назначено значение NULL.
  • MySQL отображает некоторые типы столбца, используемые другими SQL-серверами баз данных к типам MySQL. Подробности в разделе "5.5 Использование типов столбцов из других баз данных".

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

Некоторые другие изменения типа столбца могут происходить, если Вы сжимаете таблицу, используя myisampack.

7.4 Синтаксис ALTER TABLE

ALTER [IGNORE] TABLE tbl_name alter_spec [, alter_spec ...]

alter_specification:
        ADD [COLUMN] create_definition [FIRST | AFTER column_name ]
        ADD [COLUMN] (create_definition, create_definition,...)
        ADD INDEX [index_name] (index_col_name,...)
        ADD PRIMARY KEY (index_col_name,...)
        ADD UNIQUE [index_name] (index_col_name,...)
        ADD FULLTEXT [index_name] (index_col_name,...)
        ADD [CONSTRAINT symbol] FOREIGN KEY index_name
            (index_col_name,...)
            [reference_definition]
        ALTER [COLUMN] col_name {SET DEFAULT literal|DROP DEFAULT}
        CHANGE [COLUMN] old_col_name create_definition
        MODIFY [COLUMN] create_definition
        DROP [COLUMN] col_name
        DROP PRIMARY KEY
        DROP INDEX index_name
        DISABLE KEYS
        ENABLE KEYS
        RENAME [TO] new_tbl_name
        ORDER BY col
        table_options

ALTER TABLE позволяет Вам изменять структуру существующей таблицы. Например, Вы можете добавлять или удалять столбцы, создавать или уничтожать индексы, изменять тип существующих столбцов, переименовывать столбцы или непосредственно таблицу. Вы можете также изменять комментарий для таблицы и тип таблицы. Подробности в разделе "7.3 Синтаксис CREATE TABLE ".

Если Вы используете ALTER TABLE, чтобы изменить спецификацию столбца, но DESCRIBE tbl_name указывает, что Ваш столбец не был изменен, возможно, что MySQL игнорировал Вашу модификацию по одной из причин, описанных в разделе "7.3.1 Тихие изменения спецификации столбца". Например, если Вы пробуете изменять столбец VARCHAR на CHAR, MySQL будет все же использовать именно VARCHAR, если таблица содержит другие столбцы переменной длины.

ALTER TABLE работает, делая временную копию первоначальной таблицы. Перенастройка выполняется на копии, затем первоначальная таблица будет удалена, а новая переименована в старую. Это выполнено таким способом, чтобы все модификации были автоматически переназначены к новой таблице. В то время, как выполняется ALTER TABLE, первоначальная таблица читаема другой клиентурой. Модификации и записи остановлены, пока новая таблица не будет готова.

Обратите внимание, что, если Вы используете любую другую опцию ALTER TABLE, чем RENAME, MySQL будет всегда создавать временную таблицу, даже если данные не должны быть строго скопированы (подобно тому, когда Вы изменяете имя столбца). Авторы планируют исправить это в будущем, но поскольку ALTER TABLE вызывается относительно редко, это не имеет высокого приоритета в TODO.

  • Чтобы использовать ALTER TABLE, Вы должны иметь привилегии ALTER, INSERT и CREATE на таблице.
  • IGNORE представляет собой MySQL-расширение ANSI SQL92. Это управляет тем, как работает ALTER TABLE, если имеются дубликаты на уникальных ключах в новой таблице. Если IGNORE не определен, копия прервана и прокручена обратно. Если IGNORE определен, то для строк с дубликатами на уникальном ключе используется только первая строка, другие удалены.
  • Вы можете выдавать несколько команд ADD, ALTER, DROP и CHANGE в одной инструкции ALTER TABLE. Это MySQL-расширение ANSI SQL92, который позволяет только одну команду на инструкцию ALTER TABLE.
  • CHANGE col_name, DROP col_name и DROP INDEX тоже MySQL-расширения ANSI SQL92.
  • MODIFY представляет собой Oracle-расширение ALTER TABLE.
  • Факультативное слово COLUMN реально не работает и может быть свободно пропущено.
  • Если Вы используете ALTER TABLE tbl_name RENAME TO new_name без любых других параметров, MySQL просто переименовывает файлы, которые соответствуют таблице tbl_name. Нет никакой потребности создавать временную таблицу. Подробности в разделе "7.5 Синтаксис RENAME TABLE ".
  • Начиная с MySQL 4.0 вышеупомянутое свойство может быть активизировано явно. ALTER TABLE ... DISABLE KEYS предписывает прекратить модифицировать неуникальные индексы для таблиц MyISAM. ALTER TABLE ... ENABLE KEYS затем должен использоваться, чтобы освежить отсутствующие индексы. MySQL делает это специальным алгоритмом, который намного быстрее, чем вставка ключей один за другим, блокировка обработки ключей может давать значительное ускорение работы системы на оптовых вставках.
  • Предложение create_definition используют тот же самый синтаксис для ADD и CHANGE, что и CREATE TABLE. Обратите внимание, что этот синтаксис включает имя столбца, а не только тип столбца. Подробности в разделе "7.3 Синтаксис CREATE TABLE ".
  • Вы можете переименовывать столбец, используя CHANGE old_col_name create_definition. Чтобы сделать так, определите старые и новые имена столбца и тип, который столбец в настоящее время имеет. Например, чтобы переименовать столбец типа INTEGER из a в b, Вы можете сделать:
    mysql> ALTER TABLE t1 CHANGE a b INTEGER;
    Если Вы хотите изменять тип столбца, но не имя, синтаксис CHANGE все еще требует имен двух столбцов, даже если это тот же самый столбец:
    mysql> ALTER TABLE t1 CHANGE b b BIGINT NOT NULL;
    Однако, начиная с MySQL Version 3.22.16a, Вы можете также использовать MODIFY, чтобы изменить тип столбца без переименования:
    mysql> ALTER TABLE t1 MODIFY b BIGINT NOT NULL;
  • Если Вы используете CHANGE или MODIFY, чтобы сократить столбец, для которого индекс существует как часть столбца (например, если Вы имеете индекс на первых 10 символах столбца VARCHAR), Вы не можете делать столбец короче, чем число символов, которые индексированы.
  • Когда Вы изменяете тип столбца, используя CHANGE или MODIFY, MySQL пробует преобразовывать данные к новому типу.
  • В MySQL Version 3.22 или позже Вы можете использовать FIRST или ADD ... AFTER col_name, чтобы добавить столбец в специфической позиции внутри строки таблиц. Значение по умолчанию должно добавить столбец в последнюю позицию.
  • ALTER COLUMN определяет новое значение по умолчанию для столбца или удаляет старое значение по умолчанию. Если старое значение по умолчанию удалено, и столбец может быть NULL, новое значение по умолчанию будет NULL. Если столбец не может быть NULL, MySQL назначает значение по умолчанию, как описано в разделе "7.3 Синтаксис CREATE TABLE ".
  • DROP INDEX удаляет индекс. Это расширение MySQL для ANSI SQL92. Подробности в разделе "7.8 Синтаксис DROP INDEX".
  • Если столбцы удалены из таблицы, столбцы будут также удалены из любого индекса, частью которого они являются. Если все столбцы, которые составляют индекс, удалены, то будет удален и сам индекс.
  • Если таблица содержит только один столбец, он не может быть удален.
  • DROP PRIMARY KEY удаляет первичный индекс. Если такой индекс не существует, это удаляет первый UNIQUE-индекс в таблице (MySQL отмечает первый ключ UNIQUE как PRIMARY KEY, если никакой PRIMARY KEY не был определен явно). Если Вы добавляете UNIQUE INDEX или PRIMARY KEY к таблице, он будет сохранен перед любым не-UNIQUE индексом так, чтобы MySQL мог обнаружить двойные ключи как можно раньше.
  • ORDER BY позволяет Вам создавать новую таблицу со строками в специфическом порядке. Обратите внимание, что таблица не будет оставаться в этом порядке после вставок и удалений. В некоторых случаях это может сделать сортировку проще для MySQL, если таблица сделана так, как Вы желаете упорядочить ее позже. Эта опция главным образом полезна, когда Вы знаете, что Вы обычно собираетесь сделать запрос строк в некотором порядке. Используя эту опцию после больших изменений для таблицы, Вы можете получить более высокую эффективность.
  • Если Вы используете ALTER TABLE на таблице MyISAM, все неуникальные индексы будут созданы в отдельном пакете (подобно тому, как это происходит в REPAIR). Это ускорит ALTER TABLE, когда Вы имеете много индексов.

Имеется пример, который показывает, некоторые из способов применения ALTER TABLE. Мы начинаем с таблицы t1, которая создана как показано ниже:

mysql> CREATE TABLE t1 (a INTEGER,b CHAR(10));

Чтобы переименовывать таблицу из t1 в t2, надо:

mysql> ALTER TABLE t1 RENAME t2;

Чтобы изменить столбец a с типа INTEGER на тип TINYINT NOT NULL (имя оставим прежнее), и столбец b переделать с типа CHAR(10) на CHAR(20) с одновременным переименованием b в c, надо сделать:

mysql> ALTER TABLE t2 MODIFY a TINYINT NOT NULL, CHANGE b c CHAR(20);

Чтобы добавить новый столбец типа TIMESTAMP с именем d, надо сделать:

mysql> ALTER TABLE t2 ADD d TIMESTAMP;

Чтобы добавить индекс на столбце d, и сделать столбец a первичным ключом, надо:

mysql> ALTER TABLE t2 ADD INDEX (d), ADD PRIMARY KEY (a);

Чтобы удалить столбец c:

mysql> ALTER TABLE t2 DROP COLUMN c;

Чтобы добавить новый целочисленный столбец c с поддержкой AUTO_INCREMENT, надо:

mysql> ALTER TABLE t2 ADD c INT UNSIGNED NOT NULL AUTO_INCREMENT,
           ADD INDEX (c);

Обратите внимание, что мы индексировали c потому, что столбец AUTO_INCREMENT должен быть индексирован, а также мы объявляем c как NOT NULL потому, что индексированные столбцы не могут быть NULL.

Когда Вы добавляете столбец AUTO_INCREMENT, значения столбца будут заполнены числами последовательности для Вас автоматически. Вы можете устанавливать первый номер последовательности, выполняя SET INSERT_ID=# перед ALTER TABLE или используя опцию AUTO_INCREMENT=#.

С таблицами MyISAM, если Вы не изменяете столбец на AUTO_INCREMENT, номер последовательности не будут изменен. Если Вы удаляете столбец с поддержкой AUTO_INCREMENT, а затем добавляете другой с AUTO_INCREMENT, числа снова начнутся с 1.

Подробности в разделе "11.6.1 Проблемы с ALTER TABLE".

7.5 Синтаксис RENAME TABLE

RENAME TABLE tbl_name TO new_table_name[, tbl_name2 TO new_table_name2,...]

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

CREATE TABLE new_table (...);
RENAME TABLE old_table TO backup_table, new_table TO old_table;

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

RENAME TABLE old_table    TO backup_table,
             new_table    TO old_table,
             backup_table TO new_table;

Таблицы можно не только переименовывать, но еще и перемещать между разными базами данных. Например:

RENAME TABLE current_database.table_name TO other_database.table_name;

Когда Вы выполняете RENAME, Вы не можете иметь блокированные таблицы или активные транзакции. Вы должны также иметь привилегии ALTER и DROP на первоначальной таблице и привилегии CREATE и INSERT на новой таблице.

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

7.6 Синтаксис DROP TABLE

DROP TABLE [IF EXISTS] tbl_name [, tbl_name,...] [RESTRICT | CASCADE]

DROP TABLE удаляет одну или большее количество таблиц. Все данные таблицы и определение таблицы будут удалены, так что будьте внимательны с этой командой!

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

RESTRICT и CASCADE ничего не делают и нужны лишь для совместимости с другими СУБД.

ОБРАТИТЕ ВНИМАНИЕ: DROP TABLE не транзакционно-безопасна и автоматически завершает любые активные транзакции.

7.7 Синтаксис CREATE INDEX

CREATE [UNIQUE|FULLTEXT] INDEX index_name ON tbl_name (col_name[(length)],... )

Инструкция CREATE INDEX ничего не делает до Version 3.22. В Version 3.22 или позже CREATE INDEX она отображена к инструкции ALTER TABLE, чтобы создать индексы. Подробности в разделе "7.4 Синтаксис ALTER TABLE ".

Обычно Вы создаете все индексы на таблице во время непосредственного создания таблицы с помощью вызова CREATE TABLE. Подробности в разделе "7.3 Синтаксис CREATE TABLE ". CREATE INDEX позволяет Вам добавлять индексы к существующим в базе таблицам.

Список столбцов в форме (col1,col2,...) создает индекс по многим столбцам. Индексные значения будут сформированы, связывая значения из заданных для индексации столбцов.

Для столбцов CHAR и VARCHAR индексы могут быть созданы с использованием только части столбца, применяя синтаксис col_name(length). На столбцах BLOB и TEXT длина требуется обязательно. Инструкция, показанная ниже, создает индекс с использованием первых 10 символов из столбца name:

mysql> CREATE INDEX part_of_name ON customer (name(10));

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

Обратите внимание, что Вы можете добавлять индекс на столбце, который может иметь значения NULL, и на столбцах типов BLOB и TEXT только, если Вы используете MySQL Version 3.23.2 или более новую и применяете тип таблицы MyISAM.

Индексы FULLTEXT могут индексировать только столбцы типов VARCHAR и TEXT в таблицах типа MyISAM. Индексы FULLTEXT доступны в MySQL Version 3.23.23 и более новых. Подробности в разделе "9.4 Полнотекстовый поиск в MySQL".

7.8 Синтаксис DROP INDEX

DROP INDEX index_name ON tbl_name

DROP INDEX удаляет индекс с именем index_name из таблицы tbl_name. DROP INDEX ничего не делает до версии Version 3.22, а начиная с нее, этот вызов перенацелен на соответствующий вызов ALTER TABLE для удаления индекса. Подробности в разделе "7.4 Синтаксис ALTER TABLE".


Манипуляции с данными: SELECT, INSERT, UPDATE, DELETE

8 Манипуляции с данными: SELECT, INSERT, UPDATE, DELETE

8.1 Синтаксис SELECT

SELECT [STRAIGHT_JOIN] [SQL_SMALL_RESULT] [SQL_BIG_RESULT]
       [SQL_BUFFER_RESULT] [HIGH_PRIORITY] [DISTINCT|DISTINCTROW|ALL]
       select_expression,...
       [INTO {OUTFILE|DUMPFILE} 'file_name' export_options]
       [FROM table_references [WHERE where_definition]
       [GROUP BY {unsigned_integer|col_name|formula} [ASC|DESC], ...]
       [HAVING where_definition]
       [ORDER BY {unsigned_integer|col_name|formula} [ASC|DESC] ,...]
       [LIMIT [offset,] rows] [PROCEDURE procedure_name]
       [FOR UPDATE|LOCK IN SHARE MODE]]

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

mysql> SELECT 1 + 1;
    -> 2

Все используемые ключевые слова должны быть даны точно в порядке, показанном выше. Например, предложение HAVING должно прийти после любого предложения GROUP BY и перед любым предложением ORDER BY.

  • Выражение SELECT может применять псевдоним, используя AS. Псевдоним используется при задании в выражении имени столбца и может быть указан с предложениями ORDER BY или HAVING. Пример:
    mysql> select concat(last_name,', ',first_name) AS full_name
                  from mytable ORDER BY full_name;
  • Предложение FROM table_references указывает таблицы, из которых надо отыскать строки. Если Вы называете больше, чем одну таблицу, Вы выполняете объединение. Для получения информации относительно синтаксиса объединения обратитесь к разделу "8.1.1 Синтаксис JOIN".
  • Вы можете обратиться к столбцу как col_name, tbl_name.col_name или db_name.tbl_name.col_name. Вы не должны определять префикс tbl_name или db_name.tbl_name для ссылки столбца в инструкции SELECT, если ссылка однозначна. Подробности в разделе "3.2 Имена баз данных, таблиц, индексов, столбцов и псевдонимов", там есть примеры неоднозначности, которые требуют более явных форм ссылки.
  • Ссылка таблицы может быть представлена псевдонимом tbl_name [AS] alias_name:
    mysql> select t1.name, t2.salary from employee AS t1, info AS t2
           where t1.name = t2.name;
mysql> select t1.name, t2.salary from employee t1, info t2
           where t1.name = t2.name;
  • Столбцы, выбранные для вывода, могут упоминаться в предложениях ORDER BY и GROUP BY использующими имена столбца, псевдонимы столбца или позицию столбца. Позиции столбца начинаются с 1:
    mysql> select college, region, seed from tournament
           ORDER BY region, seed;
mysql> select college, region AS r, seed AS s from tournament
           ORDER BY r, s;
mysql> select college, region, seed from tournament
           ORDER BY 2, 3;
    Чтобы сортировать в обратном порядке, добавьте к имени столбца в предложении ORDER BY, которым Вы сортируете, ключевое слово DESC. Значение по умолчанию: порядок возрастания, это может быть определено, явно используя ключевое слово ASC.
  • Вы можете в предложении WHERE использовать любую из функций MySQL. Подробности в разделе "6 Функции для использования в предложениях SELECT и WHERE".
  • Предложение HAVING может обратиться к любому столбцу или псевдониму, именованному в select_expression. Это применяется в последнюю очередь прежде, чем элементы будут посланы пользователю, без оптимизации. Не используйте HAVING для элементов, которые должны быть в предложении WHERE. Например, не пишите это:
    mysql> select col_name from tbl_name HAVING col_name > 0;
    Пишите это взамен:
    mysql> select col_name from tbl_name WHERE col_name > 0;
    В MySQL Version 3.22.5 или позже Вы можете также писать запросы подобно этому:
    mysql> select user,max(salary) from users
                  group by user HAVING max(salary)>10;
    В старых версиях MySQL Вы можете писать взамен это:
    mysql> select user,max(salary) AS sum from users
           group by user HAVING sum>10;
  • SQL_SMALL_RESULT, SQL_BIG_RESULT, SQL_BUFFER_RESULT, STRAIGHT_JOIN и HIGH_PRIORITY представляют собой MySQL-расширения ANSI SQL92.
  • HIGH_PRIORITY даст SELECT более высокий приоритет, чем инструкциям, которые модифицируют таблицу. Вы должны использовать это только для запросов, которые являются очень быстрыми и должны быть выполнены сразу. Запрос SELECT HIGH_PRIORITY выполнится, если таблица блокирована для чтения, даже если имеется инструкция модификации, которая ждет таблицу.
  • SQL_BIG_RESULT может использоваться с GROUP BY или DISTINCT, чтобы сообщить оптимизатору, что набор результатов будет иметь много строк. В этом случае MySQL использует дисковые временные таблицы если необходимо. MySQL будет также, в этом случае, предпочитать сортировку временной таблицы с ключом на элементах GROUP BY.
  • Если Вы используете GROUP BY, строки вывода будут сортироваться согласно GROUP BY, как будто Вы имели ORDER BY над всеми полями в GROUP BY. MySQL расширил GROUP BY так, что Вы можете также определять ASC и DESC для GROUP BY:
    SELECT a,COUNT(b) FROM test_table GROUP BY a DESC
  • MySQL расширил использование GROUP BY так, чтобы позволить Вам выбирать поля, которые не упомянуты в предложении GROUP BY. Если Вы не получаете те результаты, которых Вы ожидаете от Вашего запроса, пожалуйста, прочитайте описание на GROUP BY. Подробности в разделе "14 Функции для использования с предложением GROUP BY".
  • SQL_BUFFER_RESULT принудительно поместит результат во временную таблицу. Это поможет MySQL освободить блокированную таблицу пораньше и пригодится в случаях, где требуется длительное время, чтобы послать набор результатов пользователю.
  • SQL_SMALL_RESULT опция, специфичная для MySQL, может использоваться с GROUP BY или DISTINCT, чтобы сообщить оптимизатору, что набор результатов будет маленький. В этом случае MySQL использует быстрые временные таблицы, чтобы сохранить возникающую в результате таблицу вместо того, чтобы использовать сортировку.
  • STRAIGHT_JOIN заставляет оптимизатор соединять таблицы в том порядке, в котором они перечислены в предложении FROM. Вы можете использовать это, чтобы ускорить запрос, если оптимизатор соединяет таблицы в неоптимальном порядке.
  • Предложение LIMIT может использоваться, чтобы ограничить число строк, возвращенных инструкцией SELECT. LIMIT берет один или два числовых параметра. Если два параметра заданы, первый определяет смещение первой строки, которая будет возвращена, второй определяет максимальное число строк. Смещение начальной строки 0 (не 1!):
    mysql> select * from table LIMIT 5,10;  # Вернуть строки 6-15
    Если один параметр задан, он указывает максимальное число строк:
    mysql> select * from table LIMIT 5;     # Вернуть первые 5 строк
    Другими словами, LIMIT n эквивалентно LIMIT 0,n.
  • Форма SELECT ... INTO OUTFILE 'file_name' пишет выбранные строки в файл. Он будет создан на сервере и не может уже существовать (среди других полезных свойств, это защищает от разрушения некоторыми шутниками файлов типа /etc/passwd). Вы должны иметь привилегию file на сервере, чтобы использовать эту форму вызова SELECT. SELECT ... INTO OUTFILE главным образом предназначен для того, чтобы позволить Вам очень быстро сделать дамп таблицы на сервере. Если Вы хотите создавать возникающий в результате файл на некотором другом компьютере, Вы не можете использовать SELECT ... INTO OUTFILE. В этом случае Вы должны взамен использовать какую-нибудь программу-клиента, подобную mysqldump --tab или mysql -e "SELECT ..." > outfile, чтобы генерировать файл. SELECT ... INTO OUTFILE дополнение синтаксиса LOAD DATA INFILE. Синтаксис для части инструкции export_options состоит из тех же самых предложений FIELDS и LINES, которые используются с инструкцией LOAD DATA INFILE. Подробности в разделе "8.9 Синтаксис LOAD DATA INFILE". В возникающем в результате текстовом файле только следующие символы закодированы через символ ESCAPED BY:
    • Сам символ ESCAPED BY
    • Первый символ в FIELDS TERMINATED BY
    • Первый символ в LINES TERMINATED BY
    Дополнительно ASCII 0 будет преобразован в ESCAPED BY, сопровождаемый 0 (ASCII 48). Причина для вышеупомянутого в том, что Вы ДОЛЖНЫ выйти из любых символов FIELDS TERMINATED BY, ESCAPED BY или LINES TERMINATED BY, чтобы надежно читать файл обратно. ASCII 0 экранирован, чтобы сделать это проще. Поскольку возникающий в результате файл не должен соответствовать SQL-синтаксису, ничто иное не должно экранироваться. Пример получения файла в формате, используемом многими довольно старыми программами:
    SELECT a,b,a+b INTO OUTFILE "/tmp/result.text"
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY "\n"
FROM test_table;
  • Если Вы используете INTO DUMPFILE вместо INTO OUTFILE, MySQL будет только писать одну строку в файл, без любого выравнивания или экранировки управляющих символов. Это полезно, если Вы хотите сохранять blob в файле.
  • Обратите внимание, что любой файл, созданный INTO OUTFILE и INTO DUMPFILE будет читаемым для всех пользователей! Причина в том, что сервер MySQL не может создавать файл, который принадлежит кому-либо другому, а не пользователю, который запустил сервер. Вы не должны никогда выполнять mysqld как root!), файл должен быть доступен на чтение всем желающим, чтобы Вы могли получать из него строки.
  • Если Вы используете FOR UPDATE с драйвером таблиц, поддерживающем блокировки страницы/столбца, нужные столбцы будут заблокированы для записи.

8.1.1 Синтаксис JOIN

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

table_reference, table_reference
table_reference [CROSS] JOIN table_reference
table_reference INNER JOIN table_reference join_condition
table_reference STRAIGHT_JOIN table_reference
table_reference LEFT [OUTER] JOIN table_reference join_condition
table_reference LEFT [OUTER] JOIN table_reference
table_reference NATURAL [LEFT [OUTER]] JOIN table_reference
{ oj table_reference LEFT OUTER JOIN table_reference ON conditional_expr }
table_reference RIGHT [OUTER] JOIN table_reference join_condition
table_reference RIGHT [OUTER] JOIN table_reference
table_reference NATURAL [RIGHT [OUTER]] JOIN table_reference

Здесь table_reference определен как:

table_name [[AS] alias] [USE INDEX (key_list)] [IGNORE INDEX (key_list)]

а join_condition как:

ON conditional_expr |
USING (column_list)

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

Обратите внимание, что в версиях до Version 3.23.17 INNER JOIN не обрабатывал join_condition!

Последний синтаксис LEFT OUTER JOIN, показанный выше, существует только для совместимости с ODBC:

  • Ссылка таблицы может быть оснащена псевдонимом с использованием tbl_name AS alias_name или tbl_name alias_name:
    mysql> select t1.name, t2.salary from employee AS t1, info AS t2
           where t1.name = t2.name;
  • Условное выражение ON представляет собой любое условное выражение формы, которое может использоваться в предложении WHERE.
  • Если не имеется никакой записи соответствия для правой таблицы в части ON или USING в LEFT JOIN, используется строка со всем набором столбцов, выставленным в NULL. Вы можете использовать этот факт, чтобы найти записи в таблице, которые не имеют никакого дубликата в другой таблице:
    mysql> select table1.* from table1
           LEFT JOIN table2 ON table1.id=table2.id
           where table2.id is NULL;
    Этот пример находит все строки в table1 со значением идентификатора id, которое не представлено в table2 (то есть, все строки в table1 без соответствующей строки в table2). Это подразумевает, что table2.id объявлен как NOT NULL.
  • USING (column_list) объявляет список столбцов, которые должны существовать в обеих таблицах. Предложение типа USING:
    A LEFT JOIN B USING (C1,C2,C3,...)
    Определено, чтобы быть семантически идентичным выражению ON:
    A.C1=B.C1 AND A.C2=B.C2 AND A.C3=B.C3,...
  • NATURAL [LEFT] JOIN двух таблиц определено семантически эквивалентно INNER JOIN или LEFT JOIN с предложением USING с именами всех столбцов, которые существуют в обеих таблицах.
  • RIGHT JOIN работает аналогично LEFT JOIN. Чтобы сохранить код переносимым между базами данных, рекомендует использовать LEFT JOIN вместо RIGHT JOIN.
  • STRAIGHT_JOIN идентичен JOIN, за исключением того, что левая таблица всегда читается перед правой таблицей. Это может использоваться для тех немногих случаев, когда оптимизатор объединения помещает таблицы в неправильном порядке.
  • С MySQL Version 3.23.12 Вы можете давать советы относительно того, как MySQL должен использовать индекс при получении информации из таблицы. Это полезно, если EXPLAIN показывает, что MySQL использует неправильный индекс. Определяя USE INDEX (key_list), Вы можете сообщать, чтобы MySQL использовал только один из определенных индексов, чтобы найти строки в таблице. Альтернативный синтаксис IGNORE INDEX (key_list) может использоваться, чтобы сообщить, чтобы MySQL не использовал некоторый специфический индекс.

Вот некоторые примеры:

mysql> select * from table1,table2 where table1.id=table2.id;
mysql> select * from table1 LEFT JOIN table2 ON table1.id=table2.id;
mysql> select * from table1 LEFT JOIN table2 USING (id);
mysql> select * from table1 LEFT JOIN table2 ON table1.id=table2.id
           LEFT JOIN table3 ON table2.id=table3.id;
mysql> select * from table1 USE INDEX (key1,key2) WHERE key1=1 and
                    key2=2 AND key3=3;
mysql> select * from table1 IGNORE INDEX (key3) WHERE key1=1 and
                    key2=2 AND key3=3;

8.2 Синтаксис UNION

SELECT ....
UNION [ALL]
SELECT ....
  [UNION
   SELECT ...]

UNION реализован только в версии MySQL 4.0.0 и выше.

UNION используется, чтобы объединить результаты из многих инструкций SELECT в один набор результатов.

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

  • Только последняя команда SELECT может иметь INTO OUTFILE.
  • Только последняя команда SELECT может иметь ORDER BY.

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

8.3 Синтаксис INSERT

INSERT [LOW_PRIORITY | DELAYED] [IGNORE]
       [INTO] tbl_name [(col_name,...)]
       VALUES (expression,...),(...),...
INSERT [LOW_PRIORITY | DELAYED] [IGNORE]
       [INTO] tbl_name [(col_name,...)] SELECT ...
INSERT [LOW_PRIORITY | DELAYED] [IGNORE] [INTO] tbl_name
       SET col_name=expression, col_name=expression, ...

INSERT вставляет новые строки в существующую таблицу. Форма INSERT ... VALUES вставляет строки, основываясь на явно определенных значениях. INSERT ... SELECT вставляет строки, выбранные из другой таблицы или таблиц. Форма INSERT ... VALUES с несколькими списками значений поддержана в MySQL Version 3.22.5 или позже. Синтаксис col_name=expression введен, начиная с MySQL Version 3.22.10 или выше.

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

  • Если Вы не определяете никакого списка столбцов для INSERT ... VALUES или INSERT ... SELECT, значения для всех столбцов нужно обеспечить в списке VALUES() или через SELECT. Если Вы не знаете порядка столбцов в таблице, используйте DESCRIBE tbl_name, чтобы выяснить.
  • Любой столбец, для которого значение явно не задано, будет установлен в значение по умолчанию. Например, если Вы определяете список столбцов, который не называет все столбцы в таблице, неназванные столбцы будут установлены в их значения по умолчанию. Задание значений по умолчанию описано в разделе "7.3 Синтаксис CREATE TABLE ".
  • Выражение expression может обратиться к любому столбцу, который был установлен ранее в списке значения. Например, можно задать:
    mysql> INSERT INTO tbl_name (col1,col2) VALUES(15,col1*2);
    Но нельзя скомандовать:
    mysql> INSERT INTO tbl_name (col1,col2) VALUES(col2*2,15);
  • Если Вы определяете ключевое слово LOW_PRIORITY, выполнение INSERT будет отложено до тех пор, пока другая клиентура не прекратит читать из таблицы. В этом случае пользователь должен ждать, пока инструкция вставки не будет завершена, что может занять немало времени, если таблица находится в тяжелом использовании. Это отличие от INSERT DELAYED, которая позволяет пользователю продолжать работу сразу же. Подробности в разделе "8.4 Синтаксис INSERT DELAYED". Обратите внимание, что LOW_PRIORITY обычно не должен использоваться с таблицами MyISAM, поскольку это отключает параллельные вставки.
  • Если Вы определяете ключевое слово IGNORE в INSERT со многими строками значений, любые строки, которые дублируют существующий ключ PRIMARY или UNIQUE в таблице, игнорируются и не будут вставлены. Если Вы не определяете IGNORE, вставка будет прервана, если имеется любая строка, которая дублирует существующее значение ключа. Вы можете определять в функции C API mysql_info(), сколько строк были вставлены в таблицу.
  • Если MySQL был конфигурирован, используя опцию DONT_USE_DEFAULT_FIELDS, инструкции INSERT генерируют ошибку, если Вы явно не определяете значения для всех столбцов, которые требуют значения, отличного от NULL.

Если Вы используете INSERT ... SELECT или INSERT ... VALUES со многими списками значений, Вы можете использовать функцию C API mysql_info(), чтобы получить информацию относительно запроса. Формат информационной строки показан ниже:

Records: 100 Duplicates: 0 Warnings: 0

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

  • Вставка NULL в столбец, который был объявлен как NOT NULL. Столбец установлен в значение по умолчанию.
  • Установка числового столбца в значение, которое находится вне диапазона столбца. Значение отсечено к соответствующей границе диапазона.
  • Установка числового столбца к значению типа 10.34 a. Конечный будет мусор удален, и остающаяся числовая часть будет вставлена. Если значение не имеет смысла как число вообще, столбец установлен в 0.
  • Вставка строки, которая превышает максимальную длину столбца, в столбец типов CHAR, VARCHAR, TEXT или BLOB. Значение усечено к максимальной длине столбца.
  • Вставка значения, которое является запрещенным для этого типа столбца, в столбец даты или времени. Столбец установлен к соответствующему нулевому значению для типа.

8.3.1 Синтаксис INSERT ... SELECT

INSERT [LOW_PRIORITY] [IGNORE] [INTO] tbl_name [(column list)] SELECT ...

Командой INSERT ... SELECT Вы можете быстро вставлять много строк в таблицу из одной или нескольких таблиц.

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

Следующие условия работают для команды INSERT ... SELECT:

  • Целевая таблица инструкции INSERT не может появляться в предложении FROM части SELECT запроса потому, что в ANSI SQL запрещено выполнять SELECT над той же самой таблицей, в которую Вы вставляете. Проблема состоит в том, что SELECT, возможно, нашел бы записи, которые были вставлены ранее в течение той же самой операции. При использовании предложений sub-select, ситуация могла бы очень легко запутаться!
  • Столбцы AUTO_INCREMENT работают как обычной.
  • Вы можете использовать функцию C API mysql_info(), чтобы получить информацию относительно запроса. Подробности в разделе "8.3 Синтаксис INSERT".
  • Чтобы гарантировать, что модификации регистрируются и могут использоваться, чтобы пересоздать первоначальные таблицы, MySQL не будет позволять параллельные вставки в течение выполнения INSERT ... SELECT.

Вы можете, конечно, также использовать REPLACE вместо INSERT, чтобы перезаписать старые строки.

8.4 Синтаксис INSERT DELAYED

INSERT DELAYED ...

Опция DELAYED для инструкции INSERT специфична для MySQL и является очень полезной, если Вы имеете клиентуру, которая не может ждать завершения INSERT. Это общая проблема, когда Вы используете MySQL для регистрации и также периодически выполняете инструкции SELECT и UPDATE, которые занимают много времени. DELAYED введен в MySQL Version 3.22.15. Это MySQL-расширение для стандарта ANSI SQL92.

INSERT DELAYED работает только с таблицами ISAM и MyISAM. Обратите внимание, что таблицы MyISAM поддерживают параллельные SELECT и INSERT, если не имеется никаких свободных блоков в середине файла данных, Вы очень редко должны использовать INSERT DELAYED с таблицами типа MyISAM.

Когда Вы используете INSERT DELAYED, клиент получит сообщение OK сразу, а вот строка будет вставлена, когда таблица не будет использоваться любым другим потоком.

Другая польза от применения INSERT DELAYED в том, что вставки многих клиентов будут связаны вместе и записаны в одном блоке. Это намного быстрее, чем выполнение многих отдельных вставок.

Обратите внимание, что в настоящее время поставленные в очередь строки сохранены только в памяти, пока они не вставлены в таблицу. Это означает, что, если Вы уничтожаете mysqld крутыми мерами (kill -9), или если mysqld рухнет неожиданно, любые поставленные в очередь строки, которые не были записаны на диск, потеряются!

Следующее описывает подробно, что случается, когда Вы используете опцию DELAYED вместе с командами INSERT или REPLACE. В этом описании "поток" представляет собой поток, который получил команду INSERT DELAYED, и "драйвер" обозначает поток, который обрабатывает все инструкции INSERT DELAYED для специфической таблицы.

  • Когда поток выполняет инструкцию DELAYED для таблицы, будет создан драйвер: чтобы обработать все инструкции DELAYED для этой таблицы, если никакого такого драйвера еще не существует.
  • Поток проверяет, приобрел или нет драйвер блокировку DELAYED. Если нет, он сообщает, чтобы драйвер это сделал. Блокировка DELAYED может быть получена, даже если другие потоки имеют блокировку READ или WRITE на таблице. Однако, драйвер будет ждать ALTER TABLE или FLUSH TABLES, чтобы гарантировать, что текущая структура таблицы современна.
  • Поток выполняет инструкцию INSERT, но вместо того, чтобы записать строку в таблицу, он помещает копию конечной строки в очередь, которая управляется драйвером. Любые ошибки синтаксиса будут отмечены потоком и сообщены программе пользователя.
  • Пользователь не может сообщать число дубликатов или значения AUTO_INCREMENT для возникающей в результате строки. Он не может получить эти данные с сервера, поскольку возвраты INSERT перед операцией вставки был завершены.
  • Файл регистрации модификаций обновляется драйвером, когда строка будет реально вставлена в таблицу. В случае вставки нескольких строк файл регистрации модификаций меняется, когда вставлена первая строка.
  • После того, как каждые delayed_insert_limit строк написаны, драйвер проверяет, являются или нет любые инструкции SELECT ждущими своей очереди. Если это так, драйвер позволяет им выполниться перед продолжением своей работы.
  • Когда драйвер больше не имеет строк в очереди, он разблокирует таблицу. Если никакая новая команда INSERT DELAYED не появилась в течение последних delayed_insert_timeout секунд, драйвер завершается.
  • Если больше, чем delayed_queue_size строк, ждущих обработки, уже в специфической очереди драйверов, поток, запрашивающий INSERT DELAYED ждет до появления участка памяти в очереди. Это выполнено, чтобы гарантировать, что сервер mysqld не использует всю память для отсроченной очереди.
  • Поток драйвера обнаружится в списке процесса MySQL с меткой delayed_insert в столбце Command. Это будет уничтожаться, если Вы выполняете команду FLUSH TABLES или уничтожаете поток с помощью KILL thread_id. Однако, драйвер сначала сохранит все поставленные в очередь строки в таблицу перед выходом. В это время система не будет принимать никакие новые команды INSERT от других потоков. Если Вы выполняете команду INSERT DELAYED после того, как это было выполнено, новый поток драйвера будет создан.
  • Обратите внимание, что вышеупомянутое означает, что команды INSERT DELAYED имеют более высокий приоритет, чем нормальные команды INSERT, если уже имеется драйвер INSERT DELAYED! Другие команды модификации должны будут ждать до опустошения очереди INSERT DELAYED, уничтожения драйвера (через KILL thread_id) или выполнения FLUSH TABLES.
  • Следующие переменные состояния обеспечивают информацию относительно выполнения команд INSERT DELAYED:
    Переменная | Значение
    Delayed_insert_threads | Число обработчиков потоков
    Delayed_writes | Число строк, вставленных с помощью INSERT DELAYED
    Not_flushed_delayed_rows | Число строк, ждущих записи
    Вы можете рассматривать эти переменные, выдавая инструкцию SHOW STATUS или выполняя команду mysqladmin extended-status.

Обратите внимание, что INSERT DELAYED медленнее, чем нормальная INSERT, если таблица сейчас не используется. Имеется также дополнительная нагрузка для сервера, чтобы обработать отдельный поток для каждой таблицы, на которой Вы используете INSERT DELAYED. Это означает, что Вы должны использовать INSERT DELAYED только тогда, когда Вы, действительно, уверены, что нуждаетесь в этом!

8.5 Синтаксис UPDATE

UPDATE [LOW_PRIORITY] [IGNORE] tbl_name
       SET col_name1=expr1, [col_name2=expr2, ...]
       [WHERE where_definition] [LIMIT #]

UPDATE модифицирует столбцы в существующих строках таблиц с новыми значениями. Предложение SET указывает, какие столбцы изменять, и значения, которые им должны быть заданы. Предложение WHERE, если задано, определяет, какие строки должны модифицироваться. Иначе модифицируются все строки. Если определено предложение ORDER BY, строки будут модифицироваться в том порядке, который определен.

Если Вы определяете ключевое слово LOW_PRIORITY, выполнение UPDATE будет отсрочено до наступления момента, когда никакие клиенты не читают из таблицы.

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

Если Вы обращаетесь к столбцу из tbl_name в выражении, UPDATE использует текущее значение столбца. Например, следующая инструкция устанавливает столбец age к следующему за его текущим значением:

mysql> UPDATE persondata SET age=age+1;

Назначения UPDATE оценены слева направо. Например, следующая инструкция удваивает столбец age, затем увеличивает его на 1:

mysql> UPDATE persondata SET age=age*2, age=age+1;

Если Вы устанавливаете столбец к значению, которое он в настоящее время имеет, MySQL не обращает внимания на это и не модифицирует столбец!

UPDATE возвращает число строк, которые были фактически изменены. В MySQL Version 3.22 или позже функция C API mysql_info() возвращает число строк, которые были согласованы и модифицировались, и число предупреждений, которые произошли в течение UPDATE.

В MySQL Version 3.23 Вы можете использовать LIMIT #, чтобы гарантировать, что только заданное число строк будет изменено.

8.6 Синтаксис DELETE

DELETE [LOW_PRIORITY | QUICK] FROM table_name
       [WHERE where_definition]
       [ORDER BY ...] [LIMIT rows]
DELETE [LOW_PRIORITY | QUICK] table_name[.*] [table_name[.*] ...] FROM
       table-references [WHERE where_definition]

DELETE удаляет строки, которые удовлетворяют условию, заданному в where_definition из таблицы table_name и возвращает число удаленных записей.

Если Вы выдаете DELETE без предложения WHERE, все строки будут удалены. Если Вы делаете это в режиме AUTOCOMMIT, это сработает аналогично TRUNCATE. Подробности в разделе "8.7 Синтаксис TRUNCATE". В MySQL 3.23 DELETE без предложения WHERE возвратит ноль как число обработанных записей.

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

mysql> DELETE FROM table_name WHERE 1>0;

Обратите внимание, что это НАМНОГО медленнее, чем DELETE FROM table_name без предложения WHERE потому, что эта команда удаляет строки по одной.

Если Вы определяете ключевое слово LOW_PRIORITY, выполнение DELETE будет отсрочено до наступления момента, когда никакие клиенты не читают из таблицы.

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

В MyISAM-таблицах удаленные записи поддерживаются в связанном списке, и старые позиции записей повторно используются вызовом INSERT. Чтобы освободить неиспользуемое место и уменьшить размеры файла, используйте команду OPTIMIZE TABLE или утилиту myisamchk, чтобы реорганизовать таблицы. OPTIMIZE TABLE проще, но myisamchk быстрее. Подробности в разделе "4.6 Синтаксис OPTIMIZE TABLE".

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

Символ .* после имени таблицы появился для совместимости с Access:

DELETE t1,t2 FROM t1,t2,t3 WHERE t1.id=t2.id AND t2.id=t3.id

В вышеупомянутом случае мы удаляем строки соответствий только из таблиц t1 и t2.

ORDER BY и использование нескольких таблиц в DELETE реализовано, начиная с MySQL 4.0.

Если предложение ORDER BY используется, строки будут удалены в заданном порядке. Это удобно в сочетании с LIMIT. Например:

DELETE FROM somelog WHERE user='jcole' ORDER BY timestamp LIMIT 1

Это удалит самую старую запись (по timestamp), где строка соответствует предложению WHERE.

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

8.7 Синтаксис TRUNCATE

TRUNCATE TABLE table_name

В версии 3.23 TRUNCATE TABLE отображен на вызов COMMIT; DELETE FROM table_name. Подробности в разделе "8.6 Синтаксис DELETE".

Разница между TRUNCATE TABLE и DELETE FROM ..:

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

TRUNCATE представляет собой Oracle-расширение языка SQL.

8.8 Синтаксис REPLACE

REPLACE [LOW_PRIORITY | DELAYED]
        [INTO] tbl_name [(col_name,...)]
        VALUES (expression,...),(...),...
REPLACE [LOW_PRIORITY | DELAYED]
        [INTO] tbl_name [(col_name,...)] SELECT ...
REPLACE [LOW_PRIORITY | DELAYED] [INTO] tbl_name
        SET col_name=expression, col_name=expression,...

REPLACE работает в точности подобно INSERT, за исключением того, что, если старая запись в таблице имеет то же самое значение, что и новая запись на уникальном индексе, старая запись будет удалена прежде, чем новая запись вставлена в таблицу. Подробности в разделе "8.3 Синтаксис INSERT".

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

При использовании вызова REPLACE mysql_affected_rows() возвратит 2, если новая строка заменила старую. Это потому, что в этом случае одна строка была вставлена, а затем дубликат был удален.

8.9 Синтаксис LOAD DATA INFILE

LOAD DATA [LOW_PRIORITY | CONCURRENT] [LOCAL] INFILE 'file_name.txt'
          [REPLACE | IGNORE] INTO TABLE tbl_name
          [FIELDS
            [TERMINATED BY '\t']
            [[OPTIONALLY] ENCLOSED BY '']
            [ESCAPED BY '\\' ]
          ]
          [LINES TERMINATED BY '\n'] [IGNORE number LINES]
          [(col_name,...)]

Команда LOAD DATA INFILE читает строки из текстового файла в таблицу. Если ключевое слово LOCAL определено, файл читается с компьютера пользователя. Если LOCAL не определено, файл должен быть размещен на сервере. LOCAL доступен в MySQL Version 3.22.6 или более поздней.

По соображениям безопасности, при чтении текстовых файлов, размещенных на сервере, файлы должны находиться в каталоге баз данных или быть читаемыми всеми. Также, чтобы использовать LOAD DATA INFILE на файлах сервера, Вы должны иметь привилегию file. Подробности в разделе "10.6 Привилегии, предоставляемые MySQL".

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

Если Вы определяете ключевое слово CONCURRENT с таблицей типа MyISAM, то другие потоки могут получать данные из таблицы в то время, как выполняется LOAD DATA. Использование этой опции будет, конечно, воздействовать на эффективность LOAD DATA, даже если никакой другой поток не использует таблицу в то же самое время.

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

Если Вы используете MySQL ниже 3.23.24, Вы не можете читать из FIFO с помощью LOAD DATA INFILE. Если Вы должны читать из FIFO (например, вывод из gunzip), используйте вместо этого команду LOAD DATA LOCAL INFILE.

Вы можете также загружать файлы данных, используя полезность mysqlimport. Она функционирует, посылая команду LOAD DATA INFILE на сервер. Опция --local заставляет mysqlimport читать файлы данных с компьютера пользователя. Вы можете определять опцию --compress, чтобы получить лучшую эффективность при работе с медленными сетями, если пользователь и сервер поддерживают сжатый протокол.

При размещении файлов на компьютере сервера, он использует правила:

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

Обратите внимание, что эти правила означают, что файл, заданный как ./myfile.txt, читается из каталога данных сервера в то время, как файл myfile.txt читается из каталога текущей базы данных. Например, следующая инструкция LOAD DATA читает файл data.txt из каталога базы данных для db1 потому, что db1 текущая база данных, даже при том, что инструкция явно загружает файл в таблицу в базе данных db2:

mysql> USE db1;
mysql> LOAD DATA INFILE "data.txt" INTO TABLE db2.my_table;

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

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

Если Вы используете LOAD DATA INFILE на пустой таблице MyISAM, все неуникальные индексы будут созданы в отдельном пакете (подобно REPAIR). Это обычно делает LOAD DATA INFILE намного быстрее, когда Вы имеете много индексов.

LOAD DATA INFILE представляет собой дополнение к SELECT ... INTO OUTFILE. Подробности в разделе "8.1 Синтаксис SELECT". Чтобы писать данные из базы данных в файл, используйте SELECT ... INTO OUTFILE. Чтобы читать файл обратно в базу данных, используйте LOAD DATA INFILE. Синтаксис предложений FIELDS и LINES тот же самый для обеих команд. Оба предложения факультативные, но FIELDS должно предшествовать LINES, если оба определены.

Если Вы определяете предложение FIELDS, каждое из подпредложений (TERMINATED BY, [OPTIONALLY] ENCLOSED BY и ESCAPED BY) также факультативны за исключением того, что Вы должны определить по крайней мере одно из них.

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

FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\'

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

LINES TERMINATED BY '\n'

Другими словами, значения по умолчанию заставляют LOAD DATA INFILE действовать следующим образом при чтении ввода:

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

SELECT ... INTO OUTFILE по умолчанию должен действовать следующим образом при записи вывода:

  • Записать позиции табуляции между полями.
  • Не включать поля внутрь любых символов цитирования.
  • Использовать \, чтобы выйти из позиций табуляции, newline или символов \, которые происходят внутри значений поля.
  • Записать newlines в конце строк.

Обратите внимание, что, чтобы писать FIELDS ESCAPED BY '\\', Вы должны определить две наклонных черты влево для любого значения, которое нужно читать как одиночную наклонную черту влево.

Опция IGNORE number LINES может использоваться, чтобы игнорировать заголовок столбца в начале файла:

mysql> LOAD DATA INFILE "/tmp/file_name" into table
                            test IGNORE 1 LINES;

Когда Вы используете SELECT ... INTO OUTFILE в тандеме с LOAD DATA INFILE, чтобы записать данные из базы данных в файл, а затем читаете файл обратно в базу данных позже, параметры обработки поля и строк для обеих команд должны соответствовать. Иначе LOAD DATA INFILE не будут интерпретировать содержание файла правильно. Предположите, что Вы используете SELECT ... INTO OUTFILE, чтобы записать файл с полями, разграниченными запятыми:

mysql> SELECT * INTO OUTFILE 'data.txt'
           FIELDS TERMINATED BY ','
           FROM ...;

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

mysql> LOAD DATA INFILE 'data.txt' INTO TABLE table2
           FIELDS TERMINATED BY ',';

Если взамен Вы пробовали читать файл инструкцией, показанной ниже, это не будет работать потому, что это инструктирует LOAD DATA INFILE искать позиции табуляции между полями:

mysql> LOAD DATA INFILE 'data.txt' INTO TABLE table2
           FIELDS TERMINATED BY '\t';

Вероятный результат: каждая входная строка интерпретируется как одиночное поле без разделения на поля.

LOAD DATA INFILE может использоваться, чтобы читать файлы, полученные из внешних источников. Например, файл в формате dBASE будет иметь поля, разделяемые запятыми и заключенные в двойные кавычки. Если строки в файле завершены newlines, команда, показанная ниже, иллюстрирует параметры обработки, которые Вы использовали бы, чтобы загрузить файл:

mysql> LOAD DATA INFILE 'data.txt' INTO TABLE tbl_name
           FIELDS TERMINATED BY ',' ENCLOSED BY '"'
           LINES TERMINATED BY '\n';

Любое из поля или параметров обработки может определять пустую строку (''). Если она не пустая, значения FIELDS [OPTIONALLY] ENCLOSED BY и FIELDS ESCAPED BY должны быть одиночным символом. Значения FIELDS TERMINATED BY и LINES TERMINATED BY могут быть больше, чем одним символом. Например, чтобы писать строки, которые завершены парами carriage return-linefeed, или читать файл, содержащий такие строки, определите LINES TERMINATED BY '\r\n'.

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

create table jokes (a int not null auto_increment primary key,
                   joke text not null);
load data infile "/tmp/jokes.txt" into table jokes
          fields terminated by "" lines terminated by "\n%%\n" (joke);

FIELDS [OPTIONALLY] ENCLOSED BY управляет цитированием полей. Для вывода (SELECT ... INTO OUTFILE), если Вы опускаете слово OPTIONALLY, все поля включены символом ENCLOSED BY. Пример такого вывода (использование запятой как разделителя поля) ниже:

"1","a string","100.20"
"2","a string containing a , comma","102.20"
"3","a string containing a \" quote","102.20"
"4","a string containing a \", quote and comma","102.20"

Если Вы определяете OPTIONALLY, символ ENCLOSED BY используется только для того, чтобы включить поля типов CHAR и VARCHAR:

1,"a string",100.20
2,"a string containing a , comma",102.20
3,"a string containing a \" quote",102.20
4,"a string containing a \", quote and comma",102.20

Обратите внимание, что местонахождение символа ENCLOSED BY внутри значения поля экранируется приписыванием символа ESCAPED BY. Также обратите внимание, что, если Вы определяете пустое значение ESCAPED BY, возможно генерировать вывод, который не может читаться правильно средствами LOAD DATA INFILE. Например, вывод, показанный выше, появился бы как показано ниже, если бы символ ESC был пустым. Заметьте, что второе поле в четвертой строке содержит запятую после кавычки, которая ошибочно появляется и завершает поле:

1,"a string",100.20
2,"a string containing a , comma",102.20
3,"a string containing a " quote",102.20
4,"a string containing a ", quote and comma",102.20

Для ввода символ ENCLOSED BY, если он вообще задан, будет удален с концов значений поля. Это истинно, определен или нет OPTIONALLY. OPTIONALLY не имеет никакого эффекта на входной интерпретации. Местонахождения символа ENCLOSED BY, которому предшествует символ ESCAPED BY, интерпретируются как часть текущего значения поля. Кроме того, дублированные символы ENCLOSED BY, встречающиеся внутри полей, интерпретируются как одиночные символы ENCLOSED BY, если поле непосредственно начинается этим символом. Например, если определено ENCLOSED BY '"', кавычки будут обработаны как показано ниже:

"The ""BIG"" boss"  -> The "BIG" boss
The "BIG" boss      -> The "BIG" boss
The ""BIG"" boss    -> The ""BIG"" boss

FIELDS ESCAPED BY контролирует, как писать или читать специальные символы. Если символ FIELDS ESCAPED BY не пуст, он использует для префикса следующие символы на выводе:

  • Символ FIELDS ESCAPED BY.
  • Символ FIELDS [OPTIONALLY] ENCLOSED BY.
  • Первый символ значений FIELDS TERMINATED BY и LINES TERMINATED BY.
  • ASCII 0 (что фактически написано после символа ASCII 0, не нулевой байт).

Если символ FIELDS ESCAPED BY пуст, никакие символы не экранируются вовсе. Не стоит определять пустой символ ESC, особенно, если значения полей в Ваших данных содержат любой из символов в списке выше.

Для ввода, если символ FIELDS ESCAPED BY не пуст, местонахождения этого символа будут удалены, и следующий символ принимается буквально как часть значения поля. Исключительные ситуации: 0 или N (например, \0 или \N, если символ ESC задан как \). Эти последовательности интерпретируются как 0 и NULL соответственно. Ниже изложены правила для обработки NULL.

За подробностями относительно синтаксиса экранировки с символом \ отсылаю Вас к разделу "3.1 Литералы: как писать строки и числа".

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

  • Если LINES TERMINATED BY пустая строка, а FIELDS TERMINATED BY не пустая, строки также будут завершены FIELDS TERMINATED BY.
  • Если обе строки FIELDS TERMINATED BY и FIELDS ENCLOSED BY пусты (''), используется фиксированный формат. С этим форматом никакие разделители не используются между полями. Вместо этого, значения столбцов пишутся и читаются, используя "экранную" ширину. Например, если столбец объявлен как INT(7), значения для столбца будут написаны, используя 7-символьные поля. На вводе значения для столбца будут получены, читая 7 символов. Формат фиксированной строки также воздействует на обработку значений NULL (см. ниже). Обратите внимание, что этот формат не будет работать, если Вы используете многобайтный набор символов.

Обработка значений NULL изменяется, в зависимости от параметров FIELDS и LINES, которые Вы используете:

  • Для заданных по умолчанию значений FIELDS и LINES NULL будет написан как \N для вывода, а \N читается как NULL для ввода (подразумевается, что символ ESCAPED BY определен как \).
  • Если FIELDS ENCLOSED BY не пуст, поле, содержащее литеральное слово NULL, читается как значение NULL (это отличается от слова NULL, заключенного внутри символов FIELDS ENCLOSED BY, которое читается как строка 'NULL').
  • Если FIELDS ESCAPED BY пустое, NULL будет написан как слово NULL.
  • С форматом фиксированной строки (когда FIELDS TERMINATED BY и FIELDS ENCLOSED BY оба пусты), NULL будет записан как пустая строка. Обратите внимание, что это делает неразличимыми значения NULL и пустые строки в таблице, когда они записаны в файл потому, что и то и другое пишется как как пустые строки. Если Вы должны при чтении файла иметь возможность разобраться что есть что, не следует применять фиксированный формат строки.

Некоторые случаи не поддержаны LOAD DATA INFILE:

  • Строки фиксированной длины (FIELDS TERMINATED BY и FIELDS ENCLOSED BY вместе пустые) в сочетании со столбцами BLOB или TEXT.
  • Если Вы определяете один разделитель, который является префиксом другого, команда LOAD DATA INFILE не будет способна интерпретировать ввод правильно. Например, следующее предложение FIELDS проблемное:
    FIELDS TERMINATED BY '"' ENCLOSED BY '"'
  • Если параметр FIELDS ESCAPED BY пуст, значение поля, которое содержит FIELDS ENCLOSED BY или LINES TERMINATED BY, сопровождаемое значением FIELDS TERMINATED BY, заставит LOAD DATA INFILE перестать читать поле или строку слишком рано. Это случается потому, что LOAD DATA INFILE не может правильно определять, где заканчивается поле.

Следующий пример загружает все столбцы таблицы persondata:

mysql> LOAD DATA INFILE 'persondata.txt' INTO TABLE persondata;

Никакой список полей не определен, так что LOAD DATA INFILE ожидает строки, содержащие поле для каждого столбца таблицы. Используются заданные по умолчанию значения FIELDS и LINES.

Если Вы желаете загрузить только некоторые из столбцов таблицы, определите список полей:

mysql> LOAD DATA INFILE 'persondata.txt'
           INTO TABLE persondata (col1,col2,...);

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

Если строка имеет слишком мало полей, столбцы, для которых никакого входного поля не присутствует, будут установлены в значения по умолчанию. Задание этих значений по умолчанию подробно описано в разделе "7.3 Синтаксис CREATE TABLE ".

Пустое значение поля интерпретируется не так, как если бы оно отсутствовало вовсе, а именно:

  • Для строковых типов, столбец установлен в пустую строку.
  • Для числовых типов, столбец установлен в 0.
  • Для типов даты и времени, столбец установлен к соответствующему нулю для типа. Подробности в разделе "5.2 Типы Date и Time".

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

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

LOAD DATA INFILE расценивает весь ввод как строки, так что Вы не можете использовать числовые значения для столбцов типов ENUM или SET, как Вы можете это делать инструкциями INSERT. Все значения ENUM и SET должны быть определены как строки!

Если Вы используете C API, Вы можете получать информацию относительно запроса, вызывая функцию mysql_info() когда запрос LOAD DATA INFILE обработан. Формат информационной строки показывается ниже:

Records: 1  Deleted: 0  Skipped: 0  Warnings: 0

Предупреждения происходят при тех же самых обстоятельствах, что и с командой INSERT (подробности в разделе "8.3 Синтаксис INSERT"), за исключением того, что LOAD DATA INFILE также генерирует предупреждения, когда имеется слишком мало или слишком много полей во входной строке. Предупреждения не сохранены где-нибудь. Число предупреждений может использоваться только как индикация, если все пошло нормально. Если Вы получаете предупреждения и хотите знать точно, почему Вы их получили, один способ сделать это состоит в том, чтобы использовать SELECT ... INTO OUTFILE в другой файл и сравнить его с первоначальным входным файлом.

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

mkfifo /mysql/db/x/x
chmod 666 /mysql/db/x/x
cat < /dev/tcp/10.1.1.12/4711 > /nt/mysql/db/x/x
mysql -e "LOAD DATA INFILE 'x' INTO TABLE x" x

Если Вы используете версию MySQL до 3.23.25, Вы можете делать вышеупомянутое только с помощью LOAD DATA LOCAL INFILE.


Обзор языка MySQL

9 Обзор языка MySQL

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

9.1 Базисные команды клиента MySQL

9.1.1 Синтаксис USE

USE db_name

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

mysql> USE db1;
mysql> SELECT count(*) FROM mytable;      # selects from db1.mytable
mysql> USE db2;
mysql> SELECT count(*) FROM mytable;      # selects from db2.mytable

Создание специфической базы данных посредством инструкции USE не препятствует Вам обращаться к таблицам в других базах данных. Пример ниже обращается к таблице author из базы данных db1 и таблице editor из базы данных db2:

mysql> USE db1;
mysql> SELECT author_name,editor_name FROM author,db2.editor
           WHERE author.editor_id = db2.editor.editor_id;

Инструкция USE предусмотрена для совместимости с Sybase.

9.1.2 Синтаксис DESCRIBE (получение информации о столбцах)

{DESCRIBE | DESC} tbl_name {col_name | wild}

DESCRIBE представляет собой сокращение для вызова SHOW COLUMNS FROM. Подробности в разделе "4.10 Получение информации о базах данных, таблицах, столбцах и индексах".

DESCRIBE обеспечивает информацию относительно столбцов таблицы. col_name может быть именем столбца или строкой, содержащей групповые символы SQL `%' и `_'.

Если типы столбцов не те, которые Вы задавали в инструкции CREATE TABLE, обратите внимание, что MySQL иногда изменяет типы столбцов. Подробности в разделе "7.3.1 Тихие изменения спецификации столбца".

Эта инструкция предусмотрена для совместимости с Oracle.

Инструкция SHOW обеспечивает подобную информацию. Подробности в разделе "4.10 Синтаксис SHOW".

9.2 Команды транзакций и блокировок в MySQL

9.2.1 Синтаксис BEGIN/COMMIT/ROLLBACK

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

Если Вы используете транзакционно-безопасные таблицы (подобно BDB, InnoDB, Вы можете перевести MySQL в режим не-autocommit следующей командой:

SET AUTOCOMMIT=0

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

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

BEGIN;
SELECT @A:=SUM(salary) FROM table1 WHERE type=1;
UPDATE table2 SET summmary=@A WHERE type=1;
COMMIT;

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

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

Если Вы используете BEGIN или SET AUTOCOMMIT=0, Вы должны использовать двоичный файл регистрации MySQL для резервирования вместо старого файла регистрации модификаций. Транзакции сохранены в двоичном протоколе, запись для COMMIT может гарантировать, что транзакции, которые прокручены обратно, не сохранены.

Следующие команды автоматически заканчивают транзакцию (как будто Вы сделали COMMIT перед выполнением команды):

ALTER TABLE | BEGIN | CREATE INDEX
DROP DATABASE | DROP TABLE | RENAME TABLE
TRUNCATE

Вы можете изменять уровень изоляции для транзакций командой SET TRANSACTION ISOLATION LEVEL .... Подробности в разделе "9.2.3 Синтаксис SET TRANSACTION".

9.2.2 Синтаксис LOCK TABLES/UNLOCK TABLES

LOCK TABLES tbl_name [AS alias] {READ|[READ LOCAL]|[LOW_PRIORITY] WRITE}
            [, tbl_name {READ | [LOW_PRIORITY] WRITE} ...]
...
UNLOCK TABLES

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

Основные причины использовать LOCK TABLES: эмуляция транзакций или получение большего быстродействия при модифицировании таблиц. Это объясняется более подробно позже.

Если поток получает блокировку READ на таблице, он (и все остальные) могут только читать из таблицы. Если поток получает блокировку WRITE на таблице, то только он может читать или писать таблицу. Другие потоки блокированы.

Различие между READ LOCAL и READ в том, что READ LOCAL позволяет непротиворечивым инструкциям INSERT выполняться в то время, как установлена блокировка. Это не может использоваться, если Вы собираетесь управлять файлами базы данных снаружи MySQL в то время, как Вы поставили блокировку.

Когда Вы используете LOCK TABLES, Вы должны блокировать все таблицы, которые Вы собираетесь использовать, и использовать тот же самый псевдоним, который собираетесь применить в Ваших запросах! Если Вы используете таблицу в запросе несколько раз (с псевдонимами), Вы должны получить блокировку для каждого псевдонима!

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

LOCK TABLES работает так:

  1. Сортирует все таблицы, которые будут блокированы, во внутреннем определенном порядке (с точки зрения пользователя, порядок неопределен).
  2. Если таблица блокирована с помощью блокировок read и write, write всегда размещается перед read.
  3. Блокируется одна таблица за раз, пока поток не получает все блокировки.

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

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

Вы можете безопасно уничтожать поток, который ждет блокировку таблицы, с помощью команды KILL. Подробности в разделе "4.9 Синтаксис KILL".

Обратите внимание, что Вы НЕ должны блокировать таблицы, которые Вы используете с INSERT DELAYED. Это потому, что в этом случае INSERT выполняется отдельным потоком.

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

  • Если Вы собираетесь выполнять много операций на связке таблиц, намного быстрее блокировать таблицы, которые Вы собираетесь использовать. Конечно, никакой другой поток не может модифицировать блокированную на READ таблицу, и никакой поток не сможет читать блокированную на WRITE таблицу. Причина того, что некоторые вещи выполняются быстрее под LOCK TABLES в том, что MySQL не будет сбрасывать на диск кэш ключей для блокированных таблиц до вызова UNLOCK TABLES (обычно кэш ключей сбрасывается на диск после каждой инструкции SQL). Это ускоряет вставки, удаления и обновления на таблицах MyISAM.
  • Если Вы используете драйвер таблицы в MySQL, который не поддерживает транзакции, Вы должны использовать LOCK TABLES, если Вы хотите гарантировать, что никакой другой поток не обработается между SELECT и UPDATE. Пример, показанный ниже, требует LOCK TABLES, чтобы выполниться безопасно:
    mysql> LOCK TABLES trans READ, customer WRITE;
mysql> select sum(value) from trans where customer_id= some_id;
mysql> update customer set total_value=sum_from_previous_statement
                  where customer_id=some_id;
mysql> UNLOCK TABLES;
    Без LOCK TABLES имеется возможность, что другой поток может вставлять новую строку в таблице trans между выполнением инструкций SELECT и UPDATE.

Используя инкрементные модификации (UPDATE customer SET value=value+new_value) или функцию LAST_INSERT_ID(), Вы во многих случаях можете избежать использования LOCK TABLES.

Вы можете также решать некоторые проблемы, используя функции GET_LOCK() и RELEASE_LOCK(). Эти блокировки сохранены в таблице hash на сервере и выполнены через вызовы pthread_mutex_lock() и pthread_mutex_unlock() для ускорения работы. Подробности в разделе "6.5.2 Дополнительные функции ".

Вы можете блокировать все таблицы во всех базах данных с блокировками чтения командой FLUSH TABLES WITH READ LOCK. Подробности в разделе "4.8 Синтаксис FLUSH". Это очень удобный способ получать резервные копии, если Вы имеете файловую систему, подобную Veritas, которая может делать кадры состояния.

ОБРАТИТЕ ВНИМАНИЕ: LOCK TABLES не транзакционно-безопасна и автоматически завершает любые активные транзакции перед попыткой блокировать таблицы.

9.2.3 Синтаксис SET TRANSACTION

SET [GLOBAL|SESSION] TRANSACTION ISOLATION LEVEL
[READ UNCOMMITTED|READ COMMITTED|REPEATABLE READ|SERIALIZABLE]

Устанавливает уровень изоляции транзакции глобально, для целого сеанса или следующей транзакции.

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

Если Вы устанавливаете привилегию GLOBAL, это будет воздействовать на все новые созданные потоки. Вы будете нуждаться в привилегии PROCESS, чтобы сделать это.

Установка привилегии SESSION будет воздействовать на следующую и на все будущие транзакции.

9.3 Синтаксис HANDLER

HANDLER table OPEN [AS alias]
HANDLER table READ index {=|>=|<=|<} (value1, value2, ...)
                   [WHERE ...] [LIMIT ...]
HANDLER table READ index {FIRST|NEXT|PREV|LAST} [WHERE ...] [LIMIT ...]
HANDLER table READ {FIRST|NEXT} [WHERE ...] [LIMIT ...]
HANDLER table CLOSE

Команда HANDLER обеспечивает прямой доступ к интерфейсу таблиц MySQL, совершая обход SQL-оптимизатора. Таким образом, это работает быстрее, чем SELECT.

Первая форма инструкции HANDLER открывает таблицу, делая ее доступной через следующий вызов HANDLER ... READ.

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

Третья форма выбирает одну (или определенное предложением LIMIT число) строку в индексном порядке, соответствуя условиям определения WHERE запроса.

Четвертая форма (без индексной спецификации) выбирает одну (или определенное предложением LIMIT число) строку из таблицы в естественном порядке строк (как они сохранены в файле данных), соответствуя условиям определения WHERE запроса. Это быстрее, чем HANDLER table READ index, когда нужен полный просмотр таблицы.

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

HANDLER это инструкция низкого уровня, например, она не обеспечивает непротиворечивость. Вызов HANDLER ... OPEN НЕ блокирует таблицу. Так что другие потоки могут работать с таблицей и менять данные.

9.4 Полнотекстовый поиск в MySQL

Начиная с Version 3.23.23, MySQL имеет поддержку для полнотекстовой индексации и поиска. Полнотекстовые индексы в MySQL представляют собой индекс типа FULLTEXT. Индекс FULLTEXT может быть создан из столбцов VARCHAR и TEXT в вызове CREATE TABLE или добавлен позже через инструкции ALTER TABLE или CREATE INDEX. Для больших наборов данных, добавление индекса FULLTEXT через ALTER TABLE (или CREATE INDEX) намного быстрее, чем вставка строк в пустую таблицу с индексом.

Поиск выполняется с помощью функции MATCH.

mysql> CREATE TABLE articles (
    ->   id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
    ->   title VARCHAR(200),
    ->   body TEXT,
    ->   FULLTEXT (title,body)
    -> );
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO articles VALUES
    -> (0,'MySQL Tutorial', 'DBMS stands for DataBase Management ...'),
    -> (0,'How To Use MySQL Efficiently', 'After you went through a ...'),
    -> (0,'Optimizing MySQL','In this tutorial we will show how to ...'),
    -> (0,'1001 MySQL Trick','1. Never run mysqld as root. 2. Normalize ...'),
    -> (0,'MySQL vs. YourSQL', 'In the following database comparison we ...'),
    -> (0,'MySQL Security', 'When configured properly, MySQL could be ...');
Query OK, 5 rows affected (0.00 sec)
Records: 5  Duplicates: 0  Warnings: 0

mysql> SELECT * FROM articles WHERE MATCH (title,body)
                    AGAINST ('database');
+----+-------------------+---------------------------------------------+
| id | title             | body                                        |
+----+-------------------+---------------------------------------------+
|  5 | MySQL vs. YourSQL | In the following database comparison we ... |
|  1 | MySQL Tutorial    | DBMS stands for DataBase Management ...     |
+----+-------------------+---------------------------------------------+
2 rows in set (0.00 sec)

Функция MATCH соответствует запросу естественного языка для текстовой совокупности AGAINST, которая является просто набором столбцов, покрытых индексом FULLTEXT). Для каждой строки в таблице это возвращает релевантность: меру подобия между текстом в этой строке (в столбцах, которые являются частью совокупности) и запросом. Когда это используется в предложении WHERE (см. пример выше) возвращенные строки автоматически сортируются с уменьшением релевантности. Релевантность представлена неотрицательным числом с плавающей запятой. Нулевая релевантность означает, что нет никакого подобия.

Вышеупомянутое представляет собой базисный пример использования функции MATCH. Строки будут возвращены с уменьшением релевантности.

mysql> SELECT id,MATCH (title,body) AGAINST ('Tutorial') FROM articles;
+----+-----------------------------------------+
| id | MATCH (title,body) AGAINST ('Tutorial') |
+----+-----------------------------------------+
|  1 |                        0.64840710366884 |
|  2 |                                       0 |
|  3 |                        0.66266459031789 |
|  4 |                                       0 |
|  5 |                                       0 |
|  6 |                                       0 |
+----+-----------------------------------------+
5 rows in set (0.00 sec)

Этот пример показывает, как найти релевантность. Поскольку предложения WHERE или ORDER BY не присутствуют в запросе, возвращенные строки не упорядочиваются.

mysql> SELECT id, body, MATCH (title,body) AGAINST (
    -> 'Security implications of running MySQL as root') AS score
    -> FROM articles WHERE MATCH (title,body) AGAINST
    -> ('Security implications of running MySQL as root');
+----+-----------------------------------------------+-----------------+
| id | body                                          | score           |
+----+-----------------------------------------------+-----------------+
|  4 | 1. Never run mysqld as root. 2. Normalize ... | 1.5055546709332 |
|  6 | When configured properly, MySQL could be ...  |   1.31140957288 |
+----+-----------------------------------------------+-----------------+
2 rows in set (0.00 sec)

Это более сложный пример: запрос возвращает релевантность и дополнительно сортирует строки с ее уменьшением. Чтобы достичь этого, нужно определить MATCH дважды. Обратите внимание, что это не вызовет никакой перегрузки, так как оптимизатор MySQL обратит внимание, что эти два обращения MATCH идентичны, и вызовут код поиска только однажды.

MySQL использует очень простой синтаксический анализатор, чтобы расчленить текст на слова. Слово является любой последовательностью символов, чисел, знаков ' и _. Любое слово, которое присутствует в списке stopword или слишком короткое (3 символа или меньше), игнорируется.

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

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

mysql> SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('MySQL');
Empty set (0.00 sec)

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

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

9.4.1 Полнотекстовые ограничения

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

9.4.2 Подстройка полнотекстового поиска MySQL

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

  • Минимальная длина слова, которое будет индексировано определена в файле myisam/ftdefs.h строкой
    #define MIN_WORD_LEN 4
    Измените это на значение, которое Вы предпочитаете, перекомпилируйте MySQL и пересоздайте индексы FULLTEXT.
  • Список stopword определен в файле myisam/ft_static.c. Поменяйте его по своему вкусу, пересоберите MySQL и пересоздайте индексы FULLTEXT.
  • Порог в 50% задан в соответствии со специфической выбранной схемой надбавки. Чтобы отключить это, измените следующую строку в файле myisam/ftdefs.h:
    #define GWS_IN_USE GWS_PROB
    на
    #define GWS_IN_USE GWS_FREQ
    После этого пересоберите MySQL. Индексы в этом случае пересоздавать не надо.

9.4.3 Новые свойства в полнотекстовом поиске в MySQL 4.0

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

  • REPAIR TABLE и ALTER TABLE работают с индексами FULLTEXT, а OPTIMIZE TABLE с индексами FULLTEXT теперь работает в 100 раз быстрее.
  • MATCH ... AGAINST поддерживает следующие boolean operators:
    • +слово означает, что слово должно присутствовать в каждой возвращенной строке.
    • -слово означает, что слово не должно присутствовать в каждой возвращенной строке.
    • < и > могут использоваться, чтобы уменьшить и увеличить вес слова в запросе.
    • ~ может использоваться, чтобы назначить отрицательный вес слову.
    • * является оператором усечения.
    Булев поиск использует более упрощенный путь вычисления релевантности, который не имеет порога 50%.
  • Поиски теперь работают в 2 раза быстрее из-за оптимизированного алгоритма.
  • Утилита ft_dump добавлена для индексных операторов низкого уровня FULLTEXT (запросы, дампы, статистика).

9.9.4 Что еще надо сделать в полнотекстовом поиске

  • Ускорить все операции с индексами FULLTEXT.
  • Поддержка скобок () в булевом поиске.
  • Поиск фраз, операторы близости.
  • Булев поиск может работать без индекса FULLTEXT (но очень медленно).
  • Поддержка для "always-index words". Это такие строки, которые пользователь определяет как слова, например, "C++", "AS/400", "TCP/IP" и т.д.
  • Поддержка для поиска в таблицах типа MERGE.
  • Поддержка для многобайтных наборов символов.
  • Сделать список stopword зависимым от языка данных в таблице.
  • Происхождение (зависимое от языка данных, конечно).
  • Универсальный обработчик пользовательских UDF (?).
  • Сделать модель более гибкой (добавляя некоторые корректируемые параметры для FULLTEXT в вызов CREATE/ALTER TABLE).


Общие проблемы защиты и система привилегий доступа MySQL

10 Общие проблемы защиты и система привилегий доступа MySQL

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

10.1 Управление привилегиями

10.1.1 Синтаксис GRANT и REVOKE

GRANT priv_type [(column_list)] [, priv_type [(column_list)] ...]
      ON {tbl_name|*|*.*|db_name.*} TO user_name [IDENTIFIED BY 'password']
      [, user_name [IDENTIFIED BY 'password'] ...] [REQUIRE {SSL|X509}
      [ISSUER issuer] [SUBJECT subject]] [WITH GRANT OPTION]

REVOKE priv_type [(column_list)] [, priv_type [(column_list)] ...]
       ON {tbl_name|*| *.*|db_name.*}
       FROM user_name [, user_name ...]

GRANT реализован в MySQL Version 3.22.11 или позже. Для более ранних версий MySQL инструкция GRANT не делает ничего.

Команды GRANT и REVOKE позволяют администраторам системы создавать пользователей, предоставлять и отменять права на MySQL-пользователей в четырех уровнях привилегий:

Глобальный уровень (Global level)
Глобальные привилегии обращаются ко всем базам данных на данном сервере. Эти привилегии сохранены в таблице mysql.user.
Уровень баз данных (Database level)
Привилегии баз данных обращаются ко всем таблицам в данной базе данных. Эти привилегии сохранены в таблицах mysql.db и mysql.host.
Уровень таблиц (Table level)
Привилегии таблиц обращаются ко всем столбцам в данной таблице. Эти привилегии сохранены в таблице mysql.tables_priv.
Уровень столбцов (Column level)
Привилегии столбцов обращаются к одиночным столбцам в данной таблице. Эти привилегии сохранены в таблице mysql.columns_priv.

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

Для инструкций GRANT и REVOKE аргумент priv_type может быть определен как любой из следующего списка:

ALL PRIVILEGES   FILE         RELOAD     ALTER   INDEX     SELECT
CREATE           INSERT       SHUTDOWN   DELETE  PROCESS   UPDATE
DROP             REFERENCES   USAGE

ALL представляет собой синоним для ALL PRIVILEGES. REFERENCES пока не реализовано. USAGE в настоящее время представляет собой синоним для ``no privileges''. Это может быть применено, когда Вы хотите создать пользователя, который не имеет никаких привилегий.

Чтобы отменять привилегию предоставленную командой grant, используйте значение priv_type параметра GRANT OPTION:

REVOKE GRANT OPTION ON ... FROM ...;

Значения priv_type, которые Вы можете определять для таблицы: SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, GRANT, INDEX и ALTER.

Значения priv_type, которые Вы можете определять для столбца (то есть, когда Вы используете аргумент column_list): SELECT, INSERT и UPDATE.

Вы можете устанавливать глобальные привилегии, используя синтаксис ON *.*. Вы можете устанавливать привилегии базы данных, используя синтаксис ON db_name.*. Если Вы определяете ON *, и Вы имеете текущую базу данных, Вы установите привилегии именно для этой базы данных. ПРЕДУПРЕЖДЕНИЕ: Если Вы определяете ON *, и Вы не имеете текущей базы данных, Вы будете воздействовать на глобальные привилегии!

Чтобы приспосабливать предоставление прав на пользователей с произвольных компьютеров, MySQL поддерживает определение значения user_name в форме user@host. Если Вы хотите определять строку user или строку host, содержащую специальные или групповые символы (например, `-'), Вы можете цитировать имя пользователя или хоста (например, 'test-user'@'test-hostname').

Вы можете определять групповые символы в hostname. Например, user@"%.joker.botik.ru" применяется к user для любого компьютера в домене joker.botik.ru, а user@"144.155.166.%" будет применено к user с любой машины в сети 144.155.166 класса C.

Простая форма user представляет собой синоним для user@"%". ОБРАТИТЕ ВНИМАНИЕ: Если Вы позволяете анонимным пользователям соединяться с сервером MySQL (что является значением по умолчанию), Вы должны также добавить всех локальных пользователей как user@localhost потому, что иначе анонимная запись в таблице mysql.user будет применяться, когда пользователь попробует зарегистрироваться на сервере MySQL с локальной машины! Анонимные пользователи определены вставкой записей с User='' в таблицу mysql.user. Вы можете проверять, применяется ли это у Вас, выполняя такой запрос:

mysql> SELECT Host,User FROM mysql.user WHERE User='';

В настоящий момент GRANT поддерживает имена хоста, базы данных, таблицы и столбца длиной только до 60 символов. Имя пользователя может быть длиной до 16 символов.

Привилегии для таблицы или столбца сформированы из логического ИЛИ (OR) привилегий в каждом из четырех уровней привилегии. Например, если таблица mysql.user определяет, что пользователь имеет глобальную привилегию select, это не может быть отменено записью на других уровнях доступа!

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

global privileges OR
(database privileges AND host privileges) OR
table privileges OR column privileges

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

Если Вы предоставляете привилегии для комбинации user/hostname, которая не существует в таблице mysql.user, запись будет добавлена и останется там пока ее не удалят командой DELETE. Другими словами, GRANT может создавать записи в таблице user, но REVOKE не будет удалять их. Вы должны делать это явно, используя вызов DELETE.

В MySQL Version 3.22.12 или позже, если новый пользователь создан, или если Вы имеете глобальные привилегии, пароль пользователя будет установлен в пароль, определенный предложением IDENTIFIED BY, если оно задано. Если пользователь уже имел пароль, он будет заменен новым.

ПРЕДУПРЕЖДЕНИЕ: Если Вы создаете нового пользователя, но не определяете предложение IDENTIFIED BY, пользователь не имеет никакого пароля. Это опасно.

Пароли также могут быть установлены командой SET PASSWORD. Подробности в разделе "14.5.6 Синтаксис SET".

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

Если пользователь не имеет привилегий на таблице, данная таблица не отображается вообще, когда пользователь запрашивает список таблиц (например, инструкцией SHOW TABLES).

Предложение WITH GRANT OPTION дает пользователю способность передать другим пользователям любые привилегии, которые этот пользователь имеет в определенном уровне доступа. Вы должны быть внимательным к тому, кому Вы даете привилегию grant, поскольку два пользователя с различными привилегиями могут быть способны соединить свои привилегии!

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

Знайте, что, когда Вы предоставляете пользователю привилегию grant в специфическом уровне привилегии, любые привилегии, которые пользователь уже имеет (или получит в будущем!) в этом уровне также могут передаваться этим пользователем кому угодно. Предположите, что Вы предоставляете пользователю привилегию insert на базе данных. Если Вы затем предоставляете привилегию select на базе данных и определяете WITH GRANT OPTION, пользователь сможет передавать не только привилегию select, но и insert! Если Вы затем предоставляете ему еще и привилегию update на базе данных, этот пользователь сможет передавать insert, select и update.

Вы не должны предоставлять привилегию alter нормальному пользователю. Если Вы это сделаете, пользователь может попробовать разрушить систему привилегии, переименовывая таблицы!

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

Когда mysqld запускается, все привилегии читаются в память. Привилегии, связанные с базами данных, таблицами и столбцами начинают действовать сразу же, а связанные с пользователями сработают, когда пользователь соединится с сервером в следующий раз. Модификации к таблицам предоставления, которые Вы выполняете, используя GRANT или REVOKE воспринимаются сервером немедленно. Если Вы изменяете таблицы предоставления вручную (используя INSERT, UPDATE и т.д.), Вы должны выполнить инструкцию FLUSH PRIVILEGES или запустить команду mysqladmin flush-privileges, чтобы сервер перезагрузил все таблицы предоставления привилегий.

Самые большие различия между ANSI SQL и MySQL версиями оператора GRANT:

  • В MySQL привилегии даны для комбинаций username+hostname, а не только для одного username.
  • ANSI SQL не имеет привилегий глобального уровня и базы данных и не поддерживает все типы привилегии, которые предоставляет MySQL. Зато MySQL не поддерживает привилегии TRIGGER, EXECUTE и UNDER из ANSI SQL.
  • Привилегии ANSI SQL структурированы иерархически. Если Вы удаляете пользователя, все привилегии, которые этот пользователь предоставил, отменяются автоматически. В MySQL предоставленные привилегии автоматически не отменяются, Вы должны отменить их непосредственно, если это необходимо.
  • Если Вы в MySQL имеете предоставление INSERT только на части столбцов в таблице, Вы можете выполнять инструкции INSERT относительно таблицы: столбцы, для которых Вы не имеете привилегию INSERT будут установлены к их значениям по умолчанию. ANSI SQL требует, чтобы Вы имели привилегию INSERT на всех столбцах.
  • Когда Вы удаляете таблицу в ANSI SQL, все привилегии для таблицы отменяются. Если Вы отменяете привилегию в ANSI SQL, все привилегии, которые предоставлялись основанными на этой привилегии, также отменяются. В MySQL привилегии могут быть удалены только явным вызовом команды REVOKE или правкой таблиц предоставления привилегий MySQL.

10.1.2 Имена и пароли пользователей MySQL

Имеются несколько различий между использованием имен и паролей MySQL и Unix или Windows:

  • Имена пользователей, которые используются MySQL для опознавательных целей, не имеют никакого отношения к именам пользователей Unix или Windows. Большинство клиентов MySQL по умолчанию пробует войти, используя текущее имя пользователя Unix как имя пользователя MySQL, но это только для удобства. Программы-клиенты позволяют задавать различные имена опциями -u или --user. Это означает, что Вы не можете делать базу данных безопасной всегда, если все имена пользователей MySQL не имеют паролей. Любой может пытаться соединиться с сервером, используя любое имя, и это получиться, если использовано имя, которое не имеет пароля.
  • Имена пользователей MySQL могут быть длиной до 16 символов. В Unix обычно длина не превышает 8 символов.
  • Пароли MySQL тоже не имеют никакого отношения к паролям в Unix. Очень советую сделать их разными: тогда взлом пароля Unix не будет означать взлома пароля для доступа к базам данных и, наоборот.
  • MySQL шифрует пароли, используя алгоритм, отличный от алгоритма шифрования в Unix. За подробностями обратитесь к описаниям функций PASSWORD() и ENCRYPT() в разделе "6.5 Прочие функции". Обратите внимание, что, даже если пароль сохранен в зашифрованном виде, знания именно зашифрованного пароля вполне достаточно, чтобы соединиться с сервером MySQL!

Пользователи MySQL и их привилегии обычно создаются командой GRANT. Подробности в разделе "10.1 Синтаксис GRANT и REVOKE".

Когда Вы входите в систему на сервере MySQL с помощью клиента командной строки, Вы должны определить пароль с помощью опции --password=your-password. Подробности изложены в разделе "10.7 Связь с сервером MySQL":

mysql --user=monty --password=guess database_name

Если Вы хотите, чтобы Вас запросили относительно пароля, Вы должны использовать аргумент --password:

mysql --user=monty --password database_name

Или в кратком виде:

mysql -u monty -p database_name

Обратите внимание, что в последнем примере пароль НЕ database_name.

Если Вы хотите использовать опцию -p, чтобы задать пароль, сделайте это так:

mysql -u monty -pguess database_name

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

10.2 Общие принципы защиты

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

Очень важно уделить внимание проблемам безопасности всего сервера (а не только MySQL) и защите от всех типов атак.

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

При запуске MySQL следуйте этим руководящим принципам:

  • НИКТО И НИКОГДА (кроме пользователя MySQL ROOT) НЕ ДОЛЖЕН ИМЕТЬ ДОСТУП К ТАБЛИЦЕ user В БАЗЕ ДАННЫХ mysql!
  • Изучите систему привилегий доступа MySQL. Команды GRANT и REVOKE используются для управления доступом к MySQL. Не предоставляйте большие привилегии, чем необходимо. Никогда не предоставляйте привилегии всем хостам. Контрольный список:
    • Попробуйте mysql -u root. Если Вы способны соединиться успешно с сервером без запроса о пароле, Вы имеете проблемы. Любой может соединяться с Вашим сервером MySQL как MySQL пользователь root с полными привилегиями! Поставьте пароль пользователя.
    • Используйте команду SHOW GRANTS и проверьте, кто имеет доступ к какой базе данных. Удалите те привилегии, которые не являются необходимыми, с помощью команды REVOKE.
  • Не храните никакие пароли открытым текстом в Вашей базе данных. Взамен используйте MD5() или другую одностороннюю хеш-функцию.
  • Выбирайте хорошие пароли. По этому поводу написано и сказано уже столько, что я просто не вижу смысла повторять весь ужас паролей типа pupsik.
  • Поставьте firewall. Он защищает Вас от, по крайней мере, 50% всех типов дырок в любом программном обеспечении. Поместите MySQL за firewall или в демилитаризированной зоне (DMZ). Контрольный список:
    • Попробуйте просматривать Ваши порты из Internet, используя инструмент типа nmap. MySQL по умолчанию использует порт 3306. Этот порт должен быть недоступен кому попало. Другой простой способ проверить, является или нет Ваш порт MySQL открытым, состоит в том, чтобы попробовать следующую команду с некоторой удаленной машины, где server_host задает имя хоста Вашего сервера MySQL:
      shell> telnet server_host 3306
      Если Вы получаете подключение и некоторые символы, порт открыт, и должен быть закрыт на Вашем firewall или маршрутизаторе, если Вы не имеете причин хранить его открытым. Если telnet только висит или от подключения отказываются, все ХОРОШО; порт блокирован.
  • Не доверяйте никаким данным, введенным Вашими пользователями. Они могут подбросить Вам код-ловушку в виде Web forms, URL или каких-то приложений. Убедитесь, что ваша прикладная программа остается безопасной, даже если пользователь вводит нечто вроде: ``; DROP DATABASE mysql;''. Также не забудьте проверять числовые данные. Иногда помогает заключить все числовые значения в апострофы. Например: SELECT * FROM table WHERE ID='234' вместо SELECT * FROM table WHERE ID=234. MySQL автоматически преобразует эту строку в число и удаляет нечисловые символы из нее. Контрольный список:
    • Все Web-приложения.
      • Попробуйте ввод в Web-формах `'' и `"'. Если Вы получаете любой вид ошибки MySQL, исследуйте проблему сразу же.
      • Попробуйте изменить любой динамический URL добавляя %22 (`"'), %23 (`#') и %27 (`'').
      • Попробуйте менять типы данных в динамическом URL от числовых до символьных, содержащих символы из предыдущих примеров. Ваша прикладная программа должна быть безопасна!
      • Попробуйте ввести символы, пробелы и специальные символы вместо чисел в числовых полях. Ваша прикладная программа должна удалить их перед прохождением запроса к MySQL или сгенерировать ошибку. Прохождение значений без контроля типов к MySQL очень опасно!
      • Проверьте размеры данных перед прохождением их к MySQL.
      • Не давайте Вашим прикладным программам больше привилегий чем, они реально нуждаются. Проверьте, что эти программы соединяются с базой данных, используя не то имя пользователя, которое Вы используете для различных административных целей (и ни в коем случае не имя root!).
    • Пользователям языка PHP:
      • Поставьте патчи, исправляющие знаменитые ошибки переполнения буфера при обработке Web-форм!
      • Проверьте функцию addslashes(). Начиная с PHP 4.0.3, появилась функция mysql_escape_string(), которая основана на одноименной функции в MySQL C API.
    • Пользователям MySQL C API:
      • Проверьте функцию mysql_escape_string().
    • Пользователям пакета MySQL++:
      • Проверьте модификаторы escape и quote для потоков запроса.
    • Пользователям Perl DBI:
      • Проверьте метод quote().
    • Пользователям Java JDBC:
      • Используйте объект PreparedStatement.
  • Не передавайте нешифрованные данные через Internet. Эти данные доступны для каждого, кто имеет время и желание использовать их для собственных целей. Вместо этого, используйте шифрованный протокол типа SSL или SSH. MySQL поддерживает внутренние подключения SSL с версии 3.23.9. Пересылка порта SSH может использоваться, чтобы создать шифрованный и сжатый туннель для связи.
  • Обучитесь использовать утилиты tcpdump и strings. Для большинства случаев Вы можете проверять, шифрованы или нет потоки данных MySQL, выдавая команду:
    shell> tcpdump -l -i eth0 -w - src or dst port 3306|strings
    Это работает под Linux и должно работать с маленькими модификациями под другими системами. Если Вы не видите данные, это не всегда означает, что они фактически зашифрованы. Если Вы нуждаетесь в хорошей защите, Вы должны проконсультироваться с экспертом защиты.

10.2 Как защитить MySQL от хакеров

Когда Вы соединяетесь с сервером MySQL, Вы обычно должны использовать пароль. Он не передается открытым текстом, однако, алгоритм шифрования не очень силен, и с некоторым усилием умный нападаюший может расколоть пароль, если может перехватить трафик. Если подключение между пользователем и сервером проходит недоверенную сеть, Вы должны использовать SSH-туннель, чтобы шифровать связь. Увы, хакеры сделали шифрование совершенно мирной связи обычным делом. А думали ли мы все, что через три года будем совершенно спокойно воспринимать шифрование данных не в военных системах, а дома?

Вся другая информация будет перемещена как текст, который может читаться любым, кто способен наблюдать подключение. Если Вы обеспокоены относительно этого, Вы можете использовать сжатый протокол (в MySQL версии 3.22 и выше), чтобы делать такое чтение намного тяжелее. Чтобы сделать связь более безопасной, Вы должны использовать ssh. Вы можете скачать исходные тексты клиентской части ssh с http://www.openssh.org, коммерческая версия клиента ssh доступна на http://www.ssh.com. Теперь Вы можете получить шифрованное TCP/IP подключение к серверу MySQL.

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

  • Используйте пароли для всех пользователей MySQL. Не забудьте, что любой может войти, как любой другой пользователь, просто отдав команду mysql -u other_user db_name, если этот самый other_user не имеет никакого пароля. Это общее поведение при работе с прикладными программами клиент/сервер, где клиент может определять любое имя пользователя.
  • Не выполняйте MySQL daemon как Unix-пользователь root. Это очень опасно, потому что любой пользователь с привилегиями FILE будет способен создать файлы как root (например, ~root/.bashrc). Чтобы предотвращать это, mysqld откажется выполняться как root, если это не определено, непосредственно используя опцию --user=root. mysqld может быть выполнен как обычный непривилегированный пользователь. Вы можете также создать нового Unix-пользователя mysql, чтобы сделать все даже более безопасным. Если Вы выполняете mysqld как другой Unix-пользователь, Вы не должны изменять имя пользователя root в таблице user потому, что имена MySQL-пользователей не имеют никакого отношения к именам пользователей Unix. Чтобы запустить mysqld как другой пользователь Unix, добавьте строку user, которая определяет имя пользователя к группе [mysqld] в файле /etc/my.cnf или в файле my.cnf в каталоге данных сервера. Например:
    [mysqld]
user=mysql
    Это заставит сервер запускаться как обозначенный пользователь, неважно запускаете ли Вы его вручную, используя safe_mysqld или mysql.server. Подробности в разделе "11.3.2 Как выполнить MySQL как нормальный пользователь"..
  • Не поддерживайте ссылки на таблицы (это может быть заблокировано опцией --skip-symlink). Это особенно важно, если Вы выполняете mysqld как root, так как любой пользователь, который имеет доступ для записи к каталогам данных, может удалить любой файл в системе!
  • Проверьте, что Unix-пользователь, от имени коего выполняется mysqld является единственным, кому позволено чтение-запись в каталогах баз данных.
  • Не давайте привилегию process всем пользователям. Вывод mysqladmin processlist показывает текст в настоящее время выполняющихся запросов, так что любой пользователь, которому дозволено эту команду выдавать, мигом увидит, что кто-то выдает запрос типа UPDATE user SET password=PASSWORD('Ваш_надежный_пароль'). Я понимаю, что не все приходит в голову, но много систем взломали именно из-за таких неочевидных дыр в защите. mysqld резервирует подключение для пользователей, которые имеют привилегию process, чтобы MySQL-пользователь root мог войти и работать, даже если все нормальные подключения уже находятся в использовании.
  • Не давайте привилегию file всем пользователям. Любой пользователь, который имеет эту привилегию, может писать файл где-нибудь в файловой системе с привилегиями mysqld daemon! Чтобы сделать это немного более безопасным, все файлы, сгенерированные SELECT ... INTO OUTFILE читаются кем угодно, и Вы не можете записывать поверх существующих файлов. Привилегия file может также использоваться, чтобы читать любой файл, доступный для Unix-пользователя, от имени которого выполняется сервер. Это может быть злоупотреблено, например, используя LOAD DATA, чтобы загрузить /etc/passwd в таблицу, которая может затем читаться с помощью SELECT.
  • Если Вы хотите ограничить число подключений для одиночного пользователя, Вы можете сделать это, устанавливая переменную max_user_connections в mysqld.

10.3 Параметры запуска для mysqld, связанные с защитой

Следующие параметры mysqld воздействуют на защиту:

--safe-show-database
С этой опцией SHOW DATABASES возвращает только те базы данных, для которых пользователь имеет некоторую привилегию.
--safe-user-create
Если включено, пользователь не может создавать новых пользователей командой GRANT, если он не имеет права INSERT на таблице mysql.user. Если Вы хотите давать пользователю доступ к созданию новых пользователей с теми привилегиями, которые он имеет право предоставить, Вы должны дать ему следующую привилегию:
GRANT INSERT(user) on mysql.user to 'user''hostname';
Это гарантирует, что пользователь не может изменять любые столбцы привилегий непосредственно, а должен использовать команду GRANT, чтобы дать привилегии другим пользователям.
--skip-grant-tables
Эта опция заставляет сервер не использовать систему привилегий вообще. Это дает каждому полный доступ ко всем базам данных! Вы можете сообщить, чтобы сервер начал использовать таблицы привилегий снова, выполняя команду mysqladmin flush-privileges или mysqladmin reload.
--skip-name-resolve
Не преобразовывать имена. Все значения столбца Host в таблицах предоставления привилегий должны быть IP-адресами или localhost.
--skip-networking
Не слушать TCP/IP подключения вообще. Все взаимодействие с mysqld должно быть выполнено через сокеты Unix. Эта опция очень рекомендуется на системах, где позволяются только локальные запросы. Эта опция не подходит для систем, которые используют MIT-PTHREADS потому, что пакет MIT-PTHREADS не поддерживает Unix-сокеты.
--skip-show-database
Инструкция SHOW DATABASES не будет возвращать ничего.

10.4 Что делает система привилегий

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

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

10.5 Как работает система привилегий

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

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

Управление доступом MySQL включает две стадии:

  • Стадия 1: сервер проверяет, стоит ли ему с Вами связываться.
  • Стадия 2: разрешив Вам соединиться с сервером, он проверяет каждый запрос, который Вы выдаете, чтобы видеть, имеете или нет Вы достаточные привилегии, чтобы выполнить его. Например, если Вы пробуете выбирать строки из таблицы в базе данных или удалить таблицу из базы данных, сервер удостоверится, что Вы имеете привилегию select для таблицы или привилегию drop для базы данных.

Сервер использует таблицы user, db и host в базе данных mysql на обеих стадиях управления доступа. Поля в этих таблицах показаны ниже:

Имя таблицы | user | db | host
Поля контекста | Host | Host | Host
 | User | Db | Db
 | Password | User |
Поля привилегий | Select_priv | Select_priv | Select_priv
 | Insert_priv | Insert_priv | Insert_priv
 | Update_priv | Update_priv | Update_priv
 | Delete_priv | Delete_priv | Delete_priv
 | Index_priv | Index_priv | Index_priv
 | Alter_priv | Alter_priv | Alter_priv
 | Create_priv | Create_priv | Create_priv
 | Drop_priv | Drop_priv | Drop_priv
 | Grant_priv | Grant_priv | Grant_priv
 | References_priv |  |
 | Reload_priv |  |
 | Shutdown_priv |  |
 | Process_priv |  |
 | File_priv |  |

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

Имя таблицы | tables_priv | columns_priv
Поля контекста | Host | Host
 | Db | Db
 | User | User
 | Table_name | Table_name
 |  | Column_name
Поля привилегий | Table_priv | Column_priv
 | Column_priv |
Прочие поля | Timestamp | Timestamp
 | Grantor |

Каждая таблица содержит поля области (контекста) и поля привилегий.

Поля контекста определяют область (контекст) каждой записи в таблицах, то есть тот контекст, в котором применяется данная запись. Например, запись в таблице user со значениями Host и User 'thomas.joker.botik.ru' и 'bob' соответственно использовалась бы для подтверждения подключений, сделанных на сервер пользователем bob с компьютера thomas.joker.botik.ru. Точно так же запись таблицы db с полями Host, User и Db, выставленными соответственно в thomas.joker.botik.ru, bob и reports, использовалась бы, когда bob соединяется с компьютера thomas.joker.botik.ru, чтобы обратиться к базе данных отчетов (reports). Таблицы tables_priv и columns_priv хранят поля области (контекста), указывающие таблицы или комбинации таблицы/столбца, к которым применяется каждая запись.

Для целей проверки доступа значения Host нечувствительны к регистру. Зато User, Password, Db и значения Table_name еще как чувствительны! Column_name нечувствительны в MySQL версии 3.22.12 или позже.

Поля привилегий указывают привилегии, предоставленные записью таблицы, то есть какие операции могут выполняться. Сервер объединяет информацию из различных таблиц предоставления привилегий, чтобы сформировать полное описание прав данного пользователя. Правила, используемые, чтобы это сделать, подробно описаны в разделе "10.9 Контроль доступа, стадия 2: Проверка запросов".

Поля контекста представляют собой строки, объявленные как показано ниже. Значение по умолчанию для каждой: пустая строка:

Имя поля | Тип
Host | CHAR(60)
User | CHAR(16)
Password | CHAR(16)
Db | CHAR(64) | (CHAR(60) для таблиц tables_priv и columns_priv)
Table_name | CHAR(60)
Column_name | CHAR(60)

В таблицах user, db и host все поля привилегий объявлены как ENUM('N','Y'): каждое может иметь значение 'N' или 'Y', значение по умолчанию 'N'.

В таблицах tables_priv и columns_priv поля привилегий объявлены как поля SET:

Имя таблицы | Имя поля | Возможные элементы набора
tables_priv | Table_priv | 'Select', 'Insert', 'Update', 'Delete', 'Create', 'Drop', 'Grant', 'References', 'Index', 'Alter'
tables_priv | Column_priv | 'Select', 'Insert', 'Update', 'References'
columns_priv | Column_priv | 'Select', 'Insert', 'Update', 'References'

Сервер использует таблицы предоставления подобно этому алгоритму:

  • Поля области (контекста) из таблицы user определяют, позволять или отклонить входящие подключения. Для позволенных подключений любые привилегии, предоставленные в таблице user, указывают глобальные привилегии пользователя. Эти привилегии обращаются ко всем базам данных на сервере.
  • Таблицы db и host используются вместе:
    • Поля области (контекста) таблицы db определяют, которые пользователи к каким базам данных с каких компьютеров могут обращаться. Поля привилегий определяют, какие операции позволяются.
    • Таблица host используется как расширение таблицы db, когда Вы хотите использовать запись из таблицы db, чтобы обратиться к нескольким компьютерам. Например, если Вы хотите, чтобы пользователь мог работать с базой данных с нескольких компьютеров в Вашей сети, оставьте значение Host пустым в записи пользователя таблицы db, затем заполните таблицу host, создав в ней запись для каждого из компьютеров. Этот механизм описан более подробно в разделе "10.9 Контроль доступа, стадия 2: Проверка запросов".
  • Таблицы tables_priv и columns_priv подобны таблице db, но более точны: они применяются в уровнях столбца и таблицы, а не на уровне всей базы данных.

Обратите внимание, что административные привилегии (reload, shutdown и т.д.) определены только в таблице user. Это потому, что административные операции выполняются непосредственно на сервере и не специфические для базы данных, так что нет никакой причины внести в список такие привилегии в других таблицах. Фактически, только таблица user должна использоваться, чтобы определить, можете ли Вы выполнять административную операцию или нет.

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

Сервер mysqld читает содержание таблиц только один раз, при своем запуске. Изменения для таблиц предоставления привилегий вступают в силу как сказано в разделе "10.11 Когда изменения привилегий вступают в силу".

Когда Вы изменяете содержание таблиц предоставления, стоит удостовериться, что Ваши изменения установили привилегии так, как Вы хотите. Для справки в диагностировании проблем обратитесь в раздел "10.10 Причины ошибки Access denied. Проблемы с защитой подробно рассмотрены в разделе "10.2 Как защитить MySQL от хакеров".

Полезный диагностический инструмент: скрипт mysqlaccess, который Yves Carlier предоставил для дистрибутива MySQL. Вызовите mysqlaccess с опцией --help, чтобы выяснить, как это работает. Обратите внимание, что mysqlaccess проверяет доступ, используя только таблицы user, db и host. Это не проверяет привилегии уровня столбца или таблицы.

10.6 Привилегии, предоставляемые MySQL

Информация относительно привилегий пользователя сохранена в таблицах user, db, host, tables_priv и columns_priv в базе данных mysql. Сервер MySQL читает содержание этих таблиц при запуске и при обстоятельствах, перечисленных в разделе "10.11 Когда изменения привилегий вступают в силу".

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

Привилегия | Столбец | Контекст (поле) действия
select | Select_priv | таблицы
insert | Insert_priv | таблицы
update | Update_priv | таблицы
delete | Delete_priv | таблицы
index | Index_priv | таблицы
alter | Alter_priv | таблицы
create | Create_priv | базы данных, таблицы или индексы
drop | Drop_priv | базы данных или таблицы
grant | Grant_priv | базы данных или таблицы
references | References_priv | базы данных или таблицы
reload | Reload_priv | серверное администрирование
shutdown | Shutdown_priv | серверное администрирование
process | Process_priv | серверное администрирование
file | File_priv | доступ к файлам на сервере

Привилегии select, insert, update и delete позволяют Вам выполнять операции на строках в существующих таблицах в базе данных.

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

mysql> SELECT 1+1;
mysql> SELECT PI()*2;

Привилегия index позволяет создавать или удалять индексы.

Привилегия alter позволяет использовать ALTER TABLE.

Привилегии create и drop позволяют создавать новые базы данных и таблицы или удалять существующие.

Обратите внимание, что, если Вы предоставляете привилегию drop для базы данных mysql пользователю, он сможет удалить всю базу данных, в которой сохранены привилегии доступа MySQL!

Привилегия grant позволяет Вам давать другим пользователям те привилегии, которыми Вы непосредственно обладаете.

Привилегия file дает Вам разрешение читать и писать файлы на сервере, используя инструкции LOAD DATA INFILE и SELECT ... INTO OUTFILE. Любой пользователь, кому эта привилегия предоставляется, может читать или писать любой файл, который доступен на чтение или запись серверу MySQL.

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

Привилегия | Команды, разрешенные держателям данной привилегии
reload | reload, refresh, flush-privileges, flush-hosts, flush-logs и flush-tables
shutdown | shutdown
process | processlist, kill

Команда reload сообщает, что сервер должен заново прочитать таблицы предоставления привилегий. Команда refresh сбрасывает на диск все таблицы, закрывает и заново открывает журналы. Привилегия flush-privileges является синонимом для reload. Другие команды flush-* выполняют функции, подобные refresh, но в более ограниченном контексте, и могут быть предпочтительны в некоторых ситуациях. Например, если Вы хотите только сбросить на диск журналы, команда flush-logs представляет собой лучший выбор, чем refresh.

Команда shutdown выключает сервер.

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

Некоторые предосторожности при предоставлении привилегий:

  • Привилегия grant позволяет пользователям отдавать их привилегии другим пользователям. Два пользователя с различными привилегиями и с привилегией grant способны объединить свои привилегии!
  • Привилегия alter может использоваться, чтобы развалить систему привилегий, переименовывая таблицы.
  • Привилегия file может быть злоупотреблена, чтобы читать любой доступный всем на чтение файл на сервере в таблицу базы данных, к содержанию которой можно затем обращаться, используя SELECT. Это включает содержание всех баз данных на сервере!
  • Привилегия shutdown может быть злоупотреблена, чтобы лишить других пользователей доступа простым выключением сервера.
  • Привилегия process, чтобы рассмотреть текст выполняемых в настоящее время запросов, включая запросы, которые устанавливают или изменяют пароли пользователей.
  • Привилегии на базе данных mysql могут использоваться, чтобы изменить пароли и другую информацию привилегий доступа. Пароли сохранены зашифрованными, так что злонамеренный пользователь не сможет просто читать их, чтобы узнать простой текстовый пароль. Если пользователь может обращаться к столбцу пароля в mysql.user, он может использовать это, чтобы зарегистрировать нового пользователя на сервере MySQL.

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

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

10.7 Связь с сервером MySQL

Клиент MySQL требует, чтобы Вы определили параметры подключения, когда Вы хотите обратиться к серверу MySQL: компьютер, с которым надо связаться, Ваше имя пользователя и пароль. Например, клиент mysql может быть запущен примерно так (факультативные параметры заключены в `[' и `]'):

shell> mysql [-h host_name] [-u user_name] [-pyour_pass]

Альтернативные формы параметров -h, -u и -p: --host=host_name, --user=user_name и --password=your_pass. Обратите внимание, что не должно быть никаких пробелов вообще между -p или --password= и паролем.

ОБРАТИТЕ ВНИМАНИЕ: Определение пароля в командной строке далеко не безопасно! Любой пользователь в Вашей системе может выяснить Ваш пароль командой, наподобие ps auxww.

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

  • Имя хоста по умолчанию: localhost.
  • Заданное по умолчанию имя пользователя: Ваше Unix-имя входа в систему.
  • Никакой пароль не задан, если отсутствует -p.

Таким образом, для Unix-пользователя joe эквивалентно:

shell> mysql -h localhost -u joe
shell> mysql -h localhost
shell> mysql -u joe
shell> mysql

Другая MySQL-клиентура ведет себя аналогично.

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

  • Вы можете определять параметры подключения в разделе [client] файла конфигурации .my.cnf в Вашем основном (домашнем) каталоге системы. Релевантный раздел файла мог бы выглядеть следующим образом:
    [client]
host=host_name
user=user_name
password=your_pass
  • Вы можете определять параметры подключения, используя системные переменные. Компьютер назначения может быть определен для mysql в переменной MYSQL_HOST. Имя пользователя MySQL может быть определено, используя USER (это только для Windows). Пароль может быть определен, используя MYSQL_PWD (но это опасно! Подробности по этому вопросу чуть ниже).

    10.8 Контроль доступа, стадия 1: Проверка соединения

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

    Идентификация основана на двух частях информации:

    • Компьютер, с которого Вы соединяетесь
    • Ваше имя пользователя MySQL

    Проверка выполняется, используя три поля области (контекста) таблицы user (Host, User и Password). Сервер принимает подключение только, если запись таблицы user соответствует Вашему hostname и имени пользователя, и Вы вводите правильный пароль.

    Значения в полях области (контекста) таблицы user могут быть определены следующим образом:

    • Значение Host может быть hostname, IP-адресом или localhost, чтобы указать локальный компьютер.
    • Вы можете использовать групповые символы `%' и `_' в поле Host.
    • Значение '%' поля Host соответствует любому имени хоста (hostname).
    • Пустое значение Host означает, что привилегия должна быть получена методом операции логического AND с записью в таблице host, которая соответствует данному имени. Вы можете найти большее количество информации относительно этого в следующей главе.
    • Начиная с MySQL Version 3.23, для значений Host, определенных как IP, Вы можете определять netmask, указывая, сколько бит адреса использовать для сетевого адреса. Например:
      GRANT ALL PRIVILEGES on db.* to david@'192.58.197.0/255.255.255.0';
      Это позволит каждому желающему соединяться с IP, где следующее истинно:
      user_ip & netmask = host_ip.
      В вышеупомянутом примере все IP в интервале 192.58.197.0-192.58.197.255 могут соединяться с сервером MySQL.
    • Групповые символы не позволяются в поле User, но Вы можете определять пустое значение, которое соответствует любому имени. Если запись таблицы user, которое соответствует входящему подключению, имеет пустое имя пользователя, такой пользователь является анонимным (то есть, пользователем без имени), а не тем пользователем, имя которого по умолчанию указывает клиент. Это означает, что пустое имя пользователя применяется для всей дальнейшей проверки доступа (то есть в течение Стадии 2).
    • Поле Password может быть пусто. Это не означает, что любой пароль подойдет, это означает, что пользователь должен соединиться без того, чтобы определить пароль.

    Непустые значения Password представляют зашифрованные пароли. MySQL не сохраняет пароли в форме открытого текста. Пароли шифруются функцией PASSWORD(). Зашифрованный пароль затем используется, когда клиент/сервер проверяет, является ли пароль правильным (это будет выполнено без передачи зашифрованного пароля по сети). Обращаю внимание, что с точки зрения MySQL зашифрованный пароль представляет собой РЕАЛЬНЫЙ пароль, так что Вы не должны давать доступ к нему кому попало! В частности, не давайте нормальный доступ для чтения пользователям к таблицам в базе данных mysql!

    Примеры ниже показывают, как различные комбинации значений Host и User в записях таблицы user обращаются к входящим подключениям:

    Host значение | User значение | Подключения, согласованные записью
    'thomas.joker.botik.ru' | 'lnz' | lnz, связавшийся с машины thomas.joker.botik.ru
    'thomas.joker.botik.ru' '' Любой пользователь, связавшийся с машины thomas.joker.botik.ru
    '%' 'lnz' lnz, связавшийся с любой машины
    '%' '' Любой пользователь, связавшийся с любой машины
    '%.joker.botik.ru' | 'lnz' | lnz, связавшийся с любой машины в домене joker.botik.ru
    'x.y.%' | 'lnz' | lnz , связавшийся с x.y.net, x.y.com, x.y.edu и т.д.
    '144.155.166.177' | 'lnz' | lnz, связавшийся с машины с IP-адресом 144.155.166.177
    '144.155.166.%' | 'lnz' | lnz, связавшийся с любой машины в сети 144.155.166 коасса C
    '144.155.166.0/255.255.255.0' | 'lnz' | Аналогично предыдущему примеру

    Поскольку Вы можете использовать символы подстановки в IP-адресах в поле Host (например, 144.155.166.%, чтобы соответствовать каждому компьютеру в подсети), есть возможность, что кто-то может попробовать эксплуатировать это свойство, именуя свой компьютер 144.155.166.somewhere.com. Чтобы мешать таким попыткам, MySQL отвергает соответствие имен хостов, которые начинаются с цифр и точки. Таким образом, если Вы имеете компьютер с именем наподобие 3.6.foo.com, его имя никогда не будет соответствовать столбцу Host таблиц. Только IP-адрес может соответствовать символам подстановки в IP-адресе.

    Входящее подключение может быть согласовано более, чем с одной записью в таблице user. Например, подключение пользователя lnz с машины thomas.joker.botik.ru согласовано несколькими записями, показанными выше. Как сервер выбирает, которую запись использовать в данной ситуации? Он решает этот вопрос, сортируя таблицу user после ее чтения при запуске. Затем записи просматриваются в отсортированном порядке. Используется первое совпадение.

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

    +-----------+---------+-
| Host      | User    | ...
+-----------+---------+-
| %         | root    | ...
| %         | alexmv  | ...
| localhost | root    | ...
| localhost |         | ...
+-----------+---------+-

    Когда сервер читает таблицу, он располагает записи с наиболее специфическими значениями Host вначале ('%' в столбце Host означает любой компьютер, а, стало быть, наименее специфический). Записи с одинаковыми значениями Host упорядочиваются с наиболее специфическими значениями User (пустое значение User означает любого пользователя, и наименее специфическое). Возникающая в результате сортировки таблица user выглядит следующим образом:

    +-----------+---------+-
| Host      | User    | ...
+-----------+---------+-
| localhost | root    | ...
| localhost |         | ...
| %         | alexmv  | ...
| %         | root    | ...
+-----------+---------+-

    Когда предпринято подключение, сервер просматривает отсортированные записи и использует первое найденное соответствие. Для подключения пользователя alexmv с машины localhost записи со значением localhost в столбце Host окажутся первыми. Из них подходит запись с пустым именем пользователя. Запись '%'/alexmv тоже подходит, но она не первая.

    Имеется другой пример. Предположите, что таблица user выглядит следующим образом:

    +-----------------------+---------+-
| Host                  | User    | ...
+-----------------------+---------+-
| %                     | alexmv  | ...
| thomas.joker.botik.ru |         | ...
+-----------------------+---------+-

    Отсортированная таблица будет выглядеть так:

    +-----------------------+---------+-
| Host                  | User    | ...
+-----------------------+---------+-
| thomas.joker.botik.ru |         | ...
| %                     | alexmv  | ...
+-----------------------+---------+-

    Подключение пользователя alexmv с машины thomas.joker.botik.ru согласовано первой записью в то время, как подключение alexmv с машины rustex.botik.ru соответствует второй записи.

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

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

    10.9 Контроль доступа, стадия 2: Проверка запросов

    Как только Вы устанавливаете подключение, сервер вводит Стадию 2. Для каждого запроса, который входит на подключении, сервер проверяет, имеете ли Вы достаточные привилегии, чтобы выполнить его, основываясь на типе операции. Эти привилегии могут исходить из любой из таблиц: user, db, host, tables_priv или columns_priv. Таблицы предоставления привилегий управляются с помощью команд GRANT и REVOKE. Подробности в разделе "10.1 Синтаксис GRANT и REVOKE".

    Таблица user предоставляет привилегии, которые назначены Вам на глобальном основании, и это применяется независимо от того, какова текущая база данных. Например, если таблица user предоставляет Вам привилегию delete, Вы можете удалять строки из любой базы данных на сервере! Другими словами, привилегии таблицы user являются глобальными. Мудро предоставить привилегии в таблице user только суперпользователям типа администраторов базы данных или сервера в целом. Для других пользователей Вы должны оставить привилегии в таблице user в значении 'N' и давать их только при использовании таблиц db и host.

    Таблицы db и host предоставляют специфические для базы данных привилегии. Значения в полях области могут быть определены так:

    • Групповые символы `%' и `_' могут использоваться в полях Host и Db любой таблицы.
    • Значение '%' в поле Host таблицы db означает любой компьютер. Пустое значение Host в таблице db предписывает брать информацию из таблицы host.
    • '%' или пустое значение Host в таблице host означает любой компьютер.
    • '%' или пустое значение Db в любой таблице означает любую базу данных.
    • Пустое значение User в любой таблице соответствует анонимному пользователю.

    Таблицы db и host читаются и сортируются при запуске сервера по тем же правилам, что и таблица user.

    Таблицы tables_priv и columns_priv предоставляют специфические для таблицы и столбца привилегии. Значения в полях области (контекста) могут быть определены так:

    • Групповые символы `%' и `_' могут использоваться в поле Host любой таблицы.
    • '%' или пустое значение Host в любой таблице означает любой компьютер.
    • Поля Db, Table_name и Column_name не могут содержать групповые символы или быть пустыми в любой таблице.

    Таблицы tables_priv и columns_priv сортируются по полям Host, Db и User. Это подобно сортировке таблицы db, хотя сортировка более простая потому, что только поле Host может содержать групповые символы.

    Процесс проверки запроса описан ниже.

    Для административных запросов (shutdown, reload и т.д.), сервер проверяет только запись таблицы user потому, что это единственная таблица, которая определяет административные привилегии. Доступ предоставляется, если запись позволяет запрошенную операцию. Например, если Вы хотите выполнить mysqladmin shutdown, но Ваша запись в таблице user не предоставляет Вам привилегию shutdown, доступ будет отклонен без всякой проверки таблиц db или host.

    Для связанных с базой данных запросов (insert, update и т.д.), сервер сначала проверит глобальные привилегии (суперпользователя) по записям в таблице user. Если запись позволяет запрошенную операцию, доступ предоставляется. Если глобальные привилегии в таблице user недостаточны, сервер определяет специфические для базы данных привилегии пользователя, проверяя таблицы db и host:

    1. Сервер смотрит в таблице db соответствия полей Host, Db и User. Поля Host и User должны соответствовать hostname соединяющегося клиентского компьютера и MySQL-имени пользователя. Поле Db должно соответствовать базе данных, к которой пользователь хочет обращаться. Если не имеется никакой записи для Host и User, доступ будет отклонен.
    2. Если имеется соответствие записи в таблице db и ее поле Host не пустое, то данная запись определяет специфические для базы данных привилегии пользователя.
    3. Если в соответствующей записи таблицы db поле Host является пустым, это выражает, что таблица host перечисляет, какие именно компьютеры имеют доступ к базе данных. В этом случае дальнейшая поисковая работа ведется в таблице host, чтобы найти соответствие полей Host и Db. Если соответствий в таблице host нет, доступ будет отклонен. Если имеется соответствие, специфические для базы данных привилегии пользователя будут вычислены как пересечение (но не объединение!) привилегий в таблицах db и host, то есть, привилегий, которые являются 'Y', в обеих записях.

    После определения специфических для базы данных привилегий, предоставленных записями таблиц db и host, сервер добавляет их к глобальным привилегиям, предоставленным таблицей user. Если результат позволяет запрошенную операцию, доступ предоставляется. Иначе сервер проверяет пользовательские привилегии таблицы и столбца в таблицах tables_priv и columns_priv соответственно, добавляя их к привилегиям пользователя.

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

    global privileges
OR (database privileges AND host privileges)
OR table privileges OR column privileges

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

    Таблица host может использоваться, чтобы поддерживать список безопасных машин и серверов.

    В TcX таблица host хранит список всех машин в локальной сети. Им предоставляют все привилегии.

    Вы можете также использовать таблицу host, чтобы указать компьютеры, которые не безопасны. Предположите, что Вы имеете машину public.your.domain, которая размещена в общем домене, который Вы не рассматриваете как безопасный. Вы можете позволять доступ всем компьютерам в Вашей сети за исключением этой системы, используя записи в таблице host:

    +--------------------+----+-
| Host               | Db | ...
+--------------------+----+-
| public.your.domain | %  | ... (все привилегии установлены в 'N')
| %.your.domain      | %  | ... (все привилегии установлены в 'Y')
+--------------------+----+-

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

    10.10 Причины ошибки Access denied

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

    • Если Вы получаете такую ошибку:
      shell> mysqladmin -u username -pxxxx ver
Access denied for user: 'username@localhost' (Using password: YES)
      Это означает, что Вы используете неправильный пароль. Подробности в разделе "10.12 Установка паролей". Если Вы получаете вышеупомянутую ошибку, даже если Вы не определили пароль, это означает, что есть неправильный пароль в файле my.ini. Вы можете отказаться от использования файлов опций с помощью параметра командной строки --no-defaults:
      shell> mysqladmin --no-defaults -u username ver
    • Если Ваши привилегии изменяются в середине сеанса, может быть, суперпользователь изменил их. Перезагрузка таблиц предоставления воздействует на новые подключения пользователя, но это также воздействует и на существующие подключения, как обозначено в разделе "10.11 Когда изменения привилегий вступают в силу".
    • Если Вы не можете получать Ваш пароль, чтобы работать, помните, что Вы должны использовать функцию PASSWORD(), если Вы устанавливаете пароль инструкцией INSERT, UPDATE или SET PASSWORD. Функция PASSWORD() не нужна, если Вы определяете пароль, используя инструкцию GRANT ... INDENTIFIED BY или вызов команды mysqladmin password. Подробности в разделе "10.12 Установка паролей".
    • localhost представляет собой синоним для Вашего локального hostname, а также заданный по умолчанию компьютер, с которым клиент пробует соединяться, если Вы не определяете никакого компьютер явно. Однако, подключения с localhost не работают, если Вы работаете на системе, которая использует MIT-pthreads (подключения localhost сделаны, используя Unix-сокеты, которые не поддержаны MIT-pthreads). Чтобы избежать этой проблемы на таких системах, Вы должны использовать опцию --host, чтобы назвать компьютер сервера явно. Это будет делать TCP/IP-подключение (не через сокеты!) к серверу mysqld. В этом случае Вы должны иметь Ваш реальный hostname в записях таблицы user на компьютере сервера (даже если Вы запускаете клиент и сервер на одной физической машине).
    • Если Вы получаете ошибку Access denied при попытке соединиться с базой данных с помощью вызова mysql -u user_name db_name, Вы можете иметь проблему с таблицей user. Обратитесь к администратору.
    • Обычно Вы должны иметь одну запись в таблице user, которая точно соответствует hostname и имени пользователя, которые были даны в сообщении об ошибках. Например, если Вы получаете сообщение об ошибках, которое содержит строку Using password: NO, это означает, что Вы пробовали войти в систему без пароля.
    • Если Вы получаете сообщение об ошибках, где hostname не показывается, или где вместо hostname выводится IP-адрес, даже если Вы пробуете соединяться именно с реальным hostname:
      shell> mysqladmin -u root -pxxxx -h some-hostname ver
Access denied for user: 'root' (Using password: YES)
      Это означает, что MySQL получил некоторую ошибку при попытке преобразования между IP и hostname. Если Ваш клиент и сервер исполняются на одной машине, свяжитесь с localhost.
    • Если mysql -u user_name test корректно работает, а вот mysql -u user_name other_db_name работать и не думает, Вы не имеете записи для other_db_name, перечисленной в таблице db, обратитесь к администратору.
    • Если mysql -u user_name db_name корректно работает, когда выполнена на машине сервера, но mysql -u host_name -u user_name db_name не работает, когда выполнена на другой машине, Вы имеете машину пользователя, не перечисленную в таблицах user или db.
    • Если Вы получаете следующую ошибку, Вы можете иметь проблему с таблицами db или host:
      Access to database denied
      Если запись из таблицы db имеет пустое значение в столбце Host удостоверьтесь, что имеется одна или большее количество соответствующих записей в таблице host, определяющих, к которым компьютерам применяется запись таблицы db. Если Вы получаете ошибку при использование команд SQL SELECT ... INTO OUTFILE или LOAD DATA INFILE, Ваша запись в таблице user, вероятно, не имеет привилегию file.
    • Не забудьте, что программы пользователя используют параметры подключения, определенные в файлах конфигурации или системных переменных. Подробнее об этом можно прочитать в разделе " Приложение 2. Переменные окружения". Если пользователь посылает неправильные заданные по умолчанию параметры подключения, когда Вы не определяете их в командной строке, проверьте Вашу среду и файл .my.cnf в Вашем основном каталоге. Вы могли бы также проверять системные файлы конфигурации MySQL, хотя гораздо менее вероятно, что параметры подключения пользователя будут определены именно там. Если Вы получаете ошибку Access denied, когда Вы выполняете клиента без параметров вообще, удостоверьтесь, что Вы не определили старый пароль в любом из файлов опций!
    • Если Вы имеете проблемы доступа с Perl, PHP, Python или программой ODBC, попробуйте соединяться с сервером командой mysql -u user_name db_name или mysql -u user_name -pyour_pass db_name. Если Вы способны подключить использование mysql, имеется проблема с Вашей программой, а не с привилегиями доступа. Обратите внимание, что нет пробелов между -p и паролем. Вы можете также использовать синтаксис --password=your_pass, чтобы определить пароль. Если Вы используете единственную опцию -p, MySQL запросит Вас относительно ввода пароля.
    • Если Вы имеете любые другие проблемы с таблицами предоставления привилегий MySQL и чувствуете, что Вы должны сообщить проблему в список рассылки, всегда обеспечивайте дамп таблиц предоставления привилегий MySQL. Вы можете создать дамп таблицы командой mysqldump mysql. Как всегда регистрируйте Вашу проблему при помощи скрипта mysqlbug. Подробности в разделе "Как сообщать о сбоях и проблемах".

    10.11 Когда привилегии вступают в силу

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

    Модификации к таблицам предоставления, которые Вы выполняете используя GRANT, REVOKE или SET PASSWORD вступают в силу немедленно.

    Если Вы изменяете таблицы предоставления вручную (используя операторы INSERT, UPDATE), Вы должны выполнить инструкцию FLUSH PRIVILEGES или запустить mysqladmin flush-privileges, или mysqladmin reload, чтобы сообщить, что сервер должен перезагрузил таблицы предоставления. Иначе Ваши изменения не будут иметь никакого эффекта, пока Вы не перезапустите сервер. Если Вы изменяете таблицы предоставления вручную, но забываете перезагружать привилегии, Вы будете часто задаваться вопросом, почему Ваши изменения не делают вообще ничего!

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

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

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

    10.12 Установка паролей

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

    Примеры в предшествующих разделах иллюстрируют важный принцип: когда Вы сохраняете непустой пароль, используя инструкции INSERT или UPDATE, Вы должны использовать функцию PASSWORD() для его шифрования. Это потому, что таблица user хранит пароли в зашифрованной форме, а не как открытый текст. Если Вы забываете этот факт, Вы, вероятно, будет пытаться устанавливать пароли подобно этому примеру:

    shell> mysql -u root mysql
mysql> INSERT INTO user (Host,User,Password)
                  VALUES('%','alexmv','biscuit');
mysql> FLUSH PRIVILEGES;

    Результат: открытый текст 'biscuit' будет сохранен как пароль в таблице user. Когда пользователь alexmv попытается подключиться к серверу, клиент mysql шифрует его пароль с помощью вызова функции PASSWORD(), генерирует вектор аутентификации, основанный на зашифрованном пароле и произвольном числе, полученном с сервера, и посылает результат сервера. Он использует значение password в таблице user (а там не зашифрованное значение biscuit!), чтобы выполнить те же самые вычисления, и сравнивает результаты. Разумеется, они отличаются, и сервер отклоняет подключение (а Вы долго пытаетесь понять, почему ничего не работает):

    shell> mysql -u alexmv -pbiscuit test
Access denied

    Пароли должны быть зашифрованы, когда они вставлены в таблицу user, так что инструкция INSERT должна быть определена подобно этому:

    mysql> INSERT INTO user (Host,User,Password)
                  VALUES('%','alexmv',PASSWORD('biscuit'));

    Вы должны также использовать функцию PASSWORD(), когда Вы применяете инструкции SET PASSWORD:

    mysql> SET PASSWORD FOR alexmv@"%" = PASSWORD('biscuit');

    Если Вы устанавливаете пароли, используя инструкции GRANT ... IDENTIFIED BY или вызов команды mysqladmin password, функция PASSWORD() уже не нужна: там она вызывается автоматически, так что Вы должны определить пароль biscuit примерно так (вот что мешало не путать людей, а сделать единую процедуру настройки?!):

    mysql> GRANT USAGE ON *.* TO alexmv@"%" IDENTIFIED BY 'biscuit';

    или примерно так:

    shell> mysqladmin -u alexmv password biscuit

    ОБРАТИТЕ ВНИМАНИЕ: PASSWORD() не выполняет шифрование пароля так, как это делается в Unix.

    10.12.1 Хранение паролей в безопасности

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

    • Никогда не давайте нормальному пользователю доступ к таблице mysql.user. Знание зашифрованного пароля для пользователя делает возможным вход в систему под именем этого пользователя.
    • Используйте опции -pyour_pass или --password=your_pass в командной строке. Это удобно, но опасно потому, что Ваш пароль становится видимым программам состояния системы (например, ps), которые могут вызываться другими пользователями, чтобы отобразить командные строки. Клиенты MySQL обнуляют командные строки, чтобы их не было видно в процессе выполнения, но имеется краткий интервал, в течение которого значение является видимым.
    • Используйте опции -p или --password (без определенного значения your_pass). В этом случае программа-клиент запросит пароль с терминала:
      shell> mysql -u user_name -p
Enter password: ********
      Символы * представляют Ваш пароль. Это более безопасно, чем определить пароль прямо в командной строке потому, что это не видно другим пользователям. Однако, этот метод ввода пароля подходит только для программ, которые Вы выполняете в интерактивном режиме. Если Вы хотите вызывать клиента из скрипта, который выполняется не в интерактивном режиме, не имеется никакой возможности ввести пароль с терминала. На некоторых системах Вы можете даже обнаружить, что первая строка Вашего скрипта читается и неправильно интерпретируется как Ваш пароль!
    • Сохраните Ваш пароль в файле конфигурации. Например, Вы можете перечислить пароль в разделе [client] файла .my.cnf в Вашем основном каталоге:
      [client]
password=your_pass
      Если Вы сохраняете Ваш пароль в файле .my.cnf, не должен быть доступен на чтение (тем более на запись) никому, кроме Вас. Удостоверьтесь, что режим доступа файла 400 или 600.
    • Вы можете сохранять Ваш пароль в системной переменной MYSQL_PWD, но этот метод должен рассматриваться как чрезвычайно опасный и не должен использоваться. Некоторые версии ps включают опцию, чтобы отобразить среду управления процессами. Ваш пароль будет видим всем желающим использовать такую команду. Даже на системах без такой версии ps неблагоразумно считать, что не имеется никакого другого метода наблюдать среды процесса.

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


Проблемы и общие ошибки

11 Проблемы и общие ошибки

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

11.1 Как определять, что вызывает проблемы

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

  • Если Вы имеете один из следующих признаков, то это, вероятно, аппаратные средства (подобно памяти, системной плате, CPU или жесткому диску) или ядерная проблема:
    • Клавиатура не работает. Это может обычно проверяться, нажимая Caps Lock. Если индикатор Caps Lock не изменяется, Вы должны заменить Вашу клавиатуру. При выполнении этого, Вы должны попробовать перезагрузить Ваш компьютер и проверить все кабели, идущие на клавиатуру.
    • Указатель мышки не двигается.
    • Машина не отвечает на сетевые запросы с удаленной машины.
    • Различные, не связанные друг с другом, программы не ведут себя правильно.
    • Если Ваша система неожиданно перезагружена (дефектная программа уровня пользователя никогда не может этого сделать).
    В этом случае Вы должны начать с проверки всех Ваших кабелей и выполнить какую-нибудь диагностическую программу, чтобы проверить Ваши аппаратные средства! Вы должны также проверить, имеются ли любые заплаты, модификации или сервисные пакеты для Вашей операционной системы, которые могли бы, вероятно, решить эти проблемы. Проверьте также, что все Ваши библиотеки (подобно glibc) современны. Всегда хорошо использовать машину с памятью ECC, чтобы обнаружить проблемы памяти пораньше.
  • Если Ваша клавиатура блокирована, Вы можете быть способны исправить это, регистрируясь с другой машины и выполняя kbd_mode -a.
  • Пожалуйста, исследуйте Ваш журнал системы (нечто вроде /var/log/messages) для поиска причин Ваших проблем. Если Вы думаете, что проблема в MySQL, Вы должны также исследовать журналы MySQL.
  • Если Вы не думаете, что имеете аппаратные проблемы, Вы должны попробовать выяснить, которая программа вызывает проблемы. Попробуйте использовать top, ps, taskmanager или некоторую подобную программу, чтобы установить, которая программа занимает весь CPU или блокирует машину.
  • Проверьте с помощью top, df или подобной программы, не исчерпана ли память, место на диске или иной критический ресурс.
  • Если проблема в некотором процессе, вышедшем из-под контроля, Вы можете всегда попробовать уничтожить его.

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

Если сбоит программа, всегда полезно знать следующее:

  • Программа в запросе получила ошибку segmentation fault (core dumped)?
  • Программа захватывает CPU целиком и полностью? Проверьте через top. Позвольте программе поработать некоторое время, она может оценивать что-то тяжелое.
  • Если это сервер mysqld вызывает проблемы, Вы можете сделать mysqladmin -u root ping или mysqladmin -u root processlist?
  • Что говорит программа пользователя (попробуйте, например, mysql), когда Вы пробуете соединяться с сервером MySQL? Клиент зависает? Вы получаете любой вывод из программы?

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

11.2 Общие ошибки при использовании MySQL

Этот раздел перечисляет некоторые ошибки, с которыми пользователи часто сталкиваются. Здесь Вы найдете описания ошибок, и как решить проблему.

11.2.1 Ошибка Access denied

Обратитесь к разделам "10.5 Как работает система привилегий" и особенно "10.10 Причины ошибки Access denied".

11.2.2 Ошибка MySQL server has gone away

Наиболее общая причина для ошибки MySQL server has gone away состоит в том, что у сервера кончилось время ожидания, и он закрыл подключение. По умолчанию сервер закрывает подключение после 8 часов отсутствия активности. Вы можете изменять срок, устанавливая переменную wait_timeout, когда Вы запускаете mysqld

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

Вы можете проверять, что MySQL работает, выполняя mysqladmin version и исследуя uptime.

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

Вы обычно можете получать следующие коды ошибки в этом случае:

CR_SERVER_GONE_ERROR | Клиент не может послать запрос на сервер.
CR_SERVER_LOST | Клиент не получал ошибку при записи на сервер, но и не получил полный ответ (или любой ответ) на запрос.

Вы можете также получать эти ошибки, если Вы посылаете неправильной или слишком большой запрос серверу. Если mysqld получает пакет, который является слишком большим или вне правил, он считает, что что-то пошло неправильно с клиентом и закрывает подключение. Если Вы нуждаетесь в больших запросах (например, если Вы работаете с большими столбцами BLOB), Вы можете увеличить ограничение запроса, запуская mysqld с опцией -O max_allowed_packet=# (по умолчанию 1M). Память дополнительного пространства распределена по требованию, так что mysqld использует большее количество памяти только, когда Вы выдаете большой запрос, или когда mysqld должен возвратить большую строку результатов!

11.2.3 Ошибка Can't connect to [local] MySQL server

Клиент MySQL под ОС Unix может соединяться с сервером mysqld двумя различными способами: Unix-сокеты, которые подключают через файл в файловой системе (значение по умолчанию /tmp/mysqld.sock) или по протоколу TCP/IP, который соединяется через номер порта. Unix-сокеты быстрее, чем TCP/IP, но могут использоваться только при соединении с сервером на том же самом компьютере. Они применяются, если Вы не определяете hostname, или если Вы определяете специальное имя localhost.

Под Windows Вы можете соединяться только через TCP/IP, если сервер mysqld запущен под Win95/Win98. Если же использована NT, Вы можете также соединяться с именованными каналами. Имя такого именованного канала MySQL. Если Вы не задаете hostname при соединении с сервером, клиент сначала попробует соединяться с именованным каналом, и если это не работает, то соединится с TCP/IP портом. Вы можете заставить использовать именованный канал под Windows, указав точку (.) как hostname.

Сообщение error (2002) Can't connect to ... обычно означает, что не имеется сервера MySQL на системе, что Вы используете неправильный файл сокета или не тот TCP/IP порт при попытке соединиться с mysqld.

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

Если процесс mysqld работает, Вы можете проверять сервер, пробуя различные подключения (номер порта и имя пути сокета):

shell> mysqladmin version
shell> mysqladmin variables
shell> mysqladmin -h `hostname` version variables
shell> mysqladmin -h `hostname` --port=3306 version
shell> mysqladmin -h 'ip for your host' version
shell> mysqladmin --socket=/tmp/mysql.sock version

Обратите внимание на использование апострофов вместо кавычек с командой hostname: они заставляют вывод hostname (то есть, текущий hostname) вставиться в mysqladmin.

Имеются некоторые причины, по которым может происходить ошибка Can't connect to local MySQL server:

  • mysqld не запущен.
  • Вы работаете на системе, которая использует MIT-PTHREADS. Если Вы работаете на системе, которая не имеет местной поддержки потоков, mysqld использует пакет MIT-pthreads. Однако, все версии MIT-pthreads не поддерживают Unix-сокеты. На системе без поддержки сокетов Вы должны всегда определять hostname явно при соединении с сервером. Попробуйте использовать эту команду, чтобы Ваше проверить подключение:
    shell> mysqladmin -h `hostname` version
  • Кто-то удалил Unix-сокет, использовавшийся mysqld, (по умолчанию это /tmp/mysqld.sock). Вы могли бы иметь задачу для планировщика cron, которая удаляет старые файлы из каталога /tmp, и сокет вместе с ними). Вы можете всегда выполнять mysqladmin version и проверять, что каталог сокета в самом деле существует. Подробности в разделе "11.4.5 Как защитить или сменить файл сокета MySQL /tmp/mysql.sock".
  • Вы запустили mysqld с опцией --socket=/path/to/socket. Если Вы изменяете имя пути сокета для сервера, не забудьте поставить об этом в известность клиентов. Вы можете сделать это, обеспечивая путь к сокету как параметр клиента. Подробности в разделе "11.4.5 Как защитить файл сокета MySQL /tmp/mysql.sock".
  • Вы используете Linux, и один поток свалился (core dumped). В этом случае Вы должны уничтожить другие потоки mysqld (например, скриптом mysql_zap прежде, чем Вы сможете запустить новый сервер MySQL).
  • Вы, возможно, не имеете прав доступа на чтение и запись к каталогу, который хранит файл сокета, или соответствующую привилегию на доступ к файлу. В этом случае Вы должны изменить привилегию для каталога (файла) или перезапустить mysqld так, чтобы он использовал каталог, к которому Вы можете обращаться.

Если Вы получаете сообщение об ошибке Can't connect to MySQL server on some_hostname, Вы можете попробовать следующие вещи, чтобы выяснить, какова проблема:

  • Проверьте работоспособность сервера командой telnet your-host-name tcp-ip-port-number с двойным нажатием RETURN. Если имеется сервер MySQL, слушающий на этом порте, Вы должны получить ответ, который включает номер версии. Если Вы получаете ошибку подобно telnet: Unable to connect to remote host: Connection refused, стало быть там не имеется никакого сервера. Куда он делся? Это уже другой вопрос, ищите...
  • Попробуйте соединиться с mysqld на локальной машине и проверить TCP/IP порт, на который mysqld сконфигурирован (переменная port) с помощью mysqladmin variables.
  • Проверьте, что сервер mysqld не запущен с параметром --skip-networking.

11.2.4 Ошибка Host '...' is blocked

Если Вы получаете сообщение об ошибке:

Host 'hostname' is blocked because of many connection errors.
Unblock with 'mysqladmin flush-hosts'

Это означает, что mysqld получил много (max_connect_errors) запросов подключения с компьютера hostname, которые были прерваны в середине. После max_connect_errors потерпевших неудачу запросов mysqld считает, что что-то неправильно (подобно нападению хакеров) и блокирует дальнейшие соединения с этой машины, пока кто-то не выполняет команду mysqladmin flush-hosts.

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

shell> safe_mysqld -O max_connect_errors=10000 &

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

11.2.5 Ошибка Too many connections

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

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

Обратите внимание, что mysqld фактически позволяет (max_connections+1) подключений. Последнее подключение зарезервировано для пользователя с привилегией process. Не давая эту привилегию нормальным пользователям (они не должны нуждаться в ней), администратор с этой привилегией может войти и использовать SHOW PROCESSLIST, чтобы выяснить то, что могло бы быть неправильно. Подробности приведены в разделе " 4.10 Синтаксис команды SHOW".

Максимальное количество подключений зависит от того, как хороша библиотека потоков на данной платформе. Linux или Solaris могут поддерживать 500-1000 одновременных подключений в зависимости от того, сколько RAM Вы имеете, и что Ваша клиентура делает.

11.2.6 Ошибка Some non-transactional changed tables couldn't be rolled back

Если Вы получаете ошибку Warning: Some non-transactional changed tables couldn't be rolled back при попытке сделать ROLLBACK, это означает, что некоторые из таблиц, которые Вы использовали, не поддерживали транзакции. На эти таблицы не будет воздействовать инструкция ROLLBACK.

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

Вы можете проверять тип таблицы:

SHOW TABLE STATUS LIKE 'table_name'.
Подробности в разделе "4.10.2 SHOW TABLE STATUS".

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

show variables like 'have_%'. Подробности в разделе "4.10.4 SHOW VARIABLES ".

11.2.7 Ошибка Out of memory

Если Вы выдаете запрос и получаете нечто вроде следующей ошибки:

mysql: Out of memory at line 42, 'malloc.c'
mysql: needed 8136 byte (8k), memory in use: 12481367 bytes (12189k)
ERROR 2008: MySQL client ran out of memory

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

Чтобы выправить проблему, сначала проверьте, что Ваш запрос правилен. Является ли приемлемым, чтобы он возвратил так много строк? Если да, Вы можете использовать mysql --quick, который использует mysql_use_result(), чтобы получить набор результатов. Это помещает меньшее количество нагрузки на клиента (но больше на сервер).

11.2.8 Ошибка Packet too large

Когда клиент MySQL или сервер mysqld получает пакет больше, чем max_allowed_packet байт, он выдает ошибку Packet too large и закрывает подключение.

Если Вы используете клиента mysql, Вы можете определять больший буфер, запуская клиента командой mysql --set-variable=max_allowed_packet=8M.

Если Вы используете другую клиентуру, которая не позволяет Вам определять максимальный размер пакета (типа DBI), Вы должны установить размер пакета, когда Вы запускаете сервер. Вы используете опцию командной строки для mysqld, чтобы установить max_allowed_packet к большему размеру. Например, если Вы ожидаете сохранять полную длину BLOB в таблицу, Вы будете должны запустить сервер с опцией --set-variable=max_allowed_packet=16M.

Вы можете также получать странные проблемы с большими пакетами, если Вы используете большие blob'ы, но не дали mysqld доступ к достаточной памяти, чтобы обработать запрос. Если Вы подозреваете, что дело обстоит именно так, попробуйте добавить ulimit -d 256000 к скрипту safe_mysqld и перезапустить mysqld.

11.2.9 Ошибки связи и прерванные подключения

Начиная с MySQL 3.23.40 Вы получаете только ошибку Aborted connection при запуске mysqld с опцией --warnings.

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

010301 14:38:23  Aborted connection 854 to db: 'users' user: 'josh'

Это означает, что что-то из следующего случилось:

  • Программа пользователя не вызвала mysql_close() перед выходом.
  • Пользователь бездействовал больше, чем wait_timeout или interactive_timeout без того, чтобы делать любые запросы.
  • Программа пользователя была закончена резко в середине передачи.

Когда вышеупомянутое случается, переменная сервера Aborted_clients будет увеличена.

Переменная сервера Aborted_connects растет:

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

Обратите внимание, что вышеупомянутое может указывать, что кто-то пробует врываться в Вашу базу данных!

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

  • Использование дуплексного протокола Ethernet в половинном и полном режимах с Linux. Многие драйверы Ethernet для Linux имеют эту ошибку. Вы должны проверить ее наличие, пересылая огромный файл через ftp между двумя машинами. Если передача входит в режим "burst-pause-burst-pause ...", значит Вы испытываете дуплексный синдром Linux. Единственное решение для этой проблемы: правильно настроить драйвер.
  • Некоторые проблемы с библиотекой потоков, которая вызывает прерывания на разных вызовах чтения.
  • Неправильно настроен протокол TCP/IP.
  • Где-то накрылась сеть: кабель, коммутатор, концентратор...
  • max_allowed_packet слишком маленький, или запросы требуют большее количество памяти, чем Вы имеете для mysqld.

11.2.10 Ошибка The table is full

Эта ошибка происходит в старых версиях MySQL, когда расположенная в памяти временная таблица становится больше, чем tmp_table_size байт. Чтобы избежать этой проблемы, Вы можете использовать опцию -O tmp_table_size=#, чтобы увеличить размер временной таблицы или использовать опцию SQL_BIG_TABLES прежде, чем Вы выдаете проблематичный запрос.

Вы можете также запустить mysqld с опцией --big-tables. Это действует точно также, как использование для всех запросов SQL_BIG_TABLES.

В MySQL Version 3.23 временная таблица в памяти будет автоматически преобразована в дисковую MyISAM после того, как размер таблицы станет больше, чем tmp_table_size.

11.2.11 Ошибка Can't create/write to file

Если для некоторых запросов Вы получаете ошибку типа:

Can't create/write to file '\\sqla3fe_0.ism'.

Это означает, что MySQL не может создать временный файл для набора результатов в заданном временном каталоге. Для исправления запустите mysqld с опцией --tmpdir=path или добавьте к файлу опцией сервера следующее:

[mysqld]
tmpdir=C:/temp

Считается, что каталог c:\temp существует.

Проверьте также код ошибки, который Вы получаете через perror. Причиной может быть также полный диск;

shell> perror 28
Error code 28: No space left on device

11.2.12 Ошибка на клиенте Commands out of sync

Если Вы получаете Commands out of sync; You can't run this command now в Вашем коде пользователя, стало быть Вы вызываете функции пользователя в неправильном порядке!

Это может случаться, например, если Вы используете mysql_use_result() и пробуете выполнять новый запрос прежде, чем Вы вызвали mysql_free_result(). Это может также случаться, если Вы пробуете выполнять два запроса, которые возвращают данные, без обязательного вызова функции mysql_use_result() или mysql_store_result() между ними.

11.2.13 Ошибка Ignoring user

Если Вы получаете следующую ошибку:

Found wrong password for user: 'some_user@some_host'; Ignoring user

Это означает, что, когда mysqld запустился или перезагрузил таблицы привилегий, он нашел запись в таблице user с недопустимым паролем. В результате запись просто игнорируется системой.

Возможные причины для этой проблемы:

  • Вы можете управлять новой версией mysqld со старой таблицей user. Вы можете проверить это, выполняя mysqlshow mysql user, чтобы видеть, является ли поле пароля короче, чем 16 символов. Если это так, Вы можете исправлять это дело запуском скрипта scripts/add_long_password.
  • Пользователь имеет старый пароль (длиной 8 символов), и Вы не запускали mysqld с опцией --old-protocol. Модифицируйте пользователя в таблице user с новым паролем или перезапустите mysqld с опцией --old-protocol.
  • Вы определили пароль в таблице user без того, чтобы использовать функцию PASSWORD(). Примените mysql, чтобы модифицировать пользователя в таблице user с новым паролем. Удостоверьтесь, что вызвана функция PASSWORD():
    mysql> update user set password=PASSWORD('your password')
                       where user='XXX';

11.2.14 Ошибка Table 'xxx' doesn't exist

Если Вы получаете ошибку Table 'xxx' doesn't exist или Can't find file: 'xxx' (errno: 2), это означает, что таблица с именем xxx не существует в текущей (актуальной) базе данных.

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

Вы можете проверить, какие таблицы Вы имеете в текущей базе данных, через SHOW TABLES. Подробности в разделе " 4.10 Синтаксис SHOW".

11.2.15 Ошибка Can't initialize character set xxx

Если Вы получаете ошибку подобно:

MySQL Connection Failed: Can't initialize character set xxx

Это означает одно из следующего:

  • Набор символов многобайтный, а Вы не имеете поддержки для него на клиенте. В этом случае Вы должны перетранслировать клиента с опцией --with-charset=xxx или --with-extra-charsets=xxx. Все стандартные двоичные файлы MySQL компилируются с --with-extra-character-sets=complex, что допускает поддержку для всех многобайтных наборов символов.
  • Набор символов простой, но тот, который не компилируется в mysqld, и файлы определения набора символов не в том месте, где клиент ожидает находить их. В этом случае Вы должны:
    • Перетранслируйте клиента с поддержкой для набора символов.
    • Определите, где искать файлы определения набора символов. Для многих клиентов это делается через опцию --character-sets-dir=path-to-charset-dir.
    • Копируйте символьные файлы определения туда, где их ищет клиент.

11.2.16 Файл не найден

Если Вы получаете ERROR '...' not found (errno: 23), Can't open file: ... (errno: 24) или любую другую ошибку с errno 23 или errno 24 из MySQL, это означает, что Вы не распределили достаточно описателей файла для MySQL. Вы можете использовать утилитку perror, чтобы получить описание того, что код ошибки означает:

shell> perror 23
File table overflow
shell> perror 24
Too many open files
shell> perror 11
Resource temporarily unavailable

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

Чтобы сообщать, чтобы mysqld хранил открытым меньшее количество файлов одновременно, Вы можете сделать кэш таблицы меньшим, используя опцию -O table_cache=32 при вызове safe_mysqld (значение по умолчанию 64). Уменьшение значения max_connections также уменьшит число открытых файлов (значение по умолчанию: 90).

Чтобы изменять число описателей файла, доступных mysqld, Вы можете использовать опцию --open-files-limit=# при вызове safe_mysqld или -O open-files-limit=# при запуске mysqld. Самый простой способ сделать это состоит в том, чтобы добавить опцию к Вашему файлу опции. Если Вы имеете старую версию mysqld, которая не поддерживает это, Вы можете отредактировать скрипт safe_mysqld. Имеется прокомментированная строка ulimit -n 256 в скрипте. Вы можете удалять символ #, чтобы раскомментировать строку и изменить число 256, чтобы воздействовать на число описателей файла.

ulimit (и open-files-limit) может увеличивать число описателей файла, но только до ограничения, наложенного операционной системой. Имеется также жесткое ограничение, которое может быть перекрыто только, если Вы запускаете safe_mysqld или mysqld как root (только не забудьте, что Вы должны также использовать опцию --user=.. в этом случае). Если Вы должны увеличить ограничение OS на число описателей файла, доступных каждому процессу, консультируйтесь с документацией для Вашей операционной системы.

Обратите внимание, что, если Вы выполняете оболочку tcsh, ulimit не будет работать! tcsh также сообщит неправильные значения, когда Вы спросите о текущих ограничениях. В этом случае Вы должны запустить safe_mysqld из sh.

11.3 Проблемы при установке

11.3.1 Проблемы компоновки с библиотекой клиентов MySQL

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

/tmp/ccFKsdPa.o: In function `main':
/tmp/ccFKsdPa.o(.text+0xb): undefined reference to `mysql_init'
/tmp/ccFKsdPa.o(.text+0x31): undefined reference to `mysql_real_connect'
/tmp/ccFKsdPa.o(.text+0x57): undefined reference to `mysql_real_connect'
/tmp/ccFKsdPa.o(.text+0x69): undefined reference to `mysql_error'
/tmp/ccFKsdPa.o(.text+0x9a): undefined reference to `mysql_close'

Вы должны быть способны решить это, добавляя -Lpath-to-the-mysql-library -lmysqlclient В САМОМ КОНЦЕ строки для компоновщика.

Если Вы получаете ошибки undefined reference для функций uncompress или compress, добавьте -lz В САМОМ КОНЦЕ строки для компоновщика.

Если Вы получаете ошибки undefined reference для функций, которые должны существовать в Вашей системе, подобно connect, проверьте man-страницу для рассматриваемой функции, чтобы выяснить, какую библиотеку Вы должны добавить.

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

mf_format.o(.text+0x201): undefined reference to `__lxstat'

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

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

  • Добавьте путь к каталогу, где Вы имеете libmysqlclient.so, к системной переменной LD_LIBRARY_PATH.
  • Добавьте путь к каталогу, где Вы имеете libmysqlclient.so, к системной переменной LD_LIBRARY.
  • Копируйте libmysqlclient.so в место, где система ищет общие библиотеки, например, /lib, и модифицируйте общедоступную библиотечную информацию, выполняя ldconfig.

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

11.3.2 Как запустить MySQL от имени нормального пользователя

MySQL-сервер mysqld может быть запущен и выполняться любым пользователем. Чтобы mysqld работал как Unix-пользователь user_name, Вы должны сделать следующие шаги:

  1. Завершите сервер, если он запущен (mysqladmin shutdown).
  2. Измените каталоги баз данных и файлы так, чтобы user_name имел права на чтение и запись:
    shell> chown -R user_name /path/to/mysql/datadir
    Если каталоги или файлы внутри каталога данных MySQL представляют собой символические ссылки, Вы будете также должны следовать за теми связями и изменять каталоги и файлы, на которые они указывают. Увы, chown -R не может следовать за ссылками для Вас.
  3. Запустите сервер как пользователь user_name или, если Вы используете MySQL Version 3.22 или позже, как Unix-пользователь root с опцией --user=user_name. mysqld переключится на Unix-пользователя user_name перед принятием любых подключений.
  4. Чтобы запустить сервер как данное имя пользователя автоматически при запуске системы, добавьте строку user, которая определяет имя пользователя, к группе [mysqld] файла /etc/my.cnf (или my.cnf) в каталоге данных сервера. Например:
    [mysqld]
user=user_name

Обратите внимание, что доступ к MySQL как root указанием -u root в командной строке, не имеет никакого отношения к запуску MySQL как root. Права доступа и имена пользователей MySQL полностью независимы от имен в Unix. Единственное подключение с именем пользователя Unix происходит, если Вы не указали опцию -u, когда Вы вызываете программу пользователя. Клиент пробует подключиться, используя Ваше Unix-имя входа в систему как имя пользователя MySQL.

11.3.3 Проблемы с доступом к файлам

Если Вы имеете проблемы с правами доступа к файлам, например, если mysql выдает такое сообщение об ошибке, когда создаете таблицу:

ERROR: Can't find file: 'path/with/filename.frm' (Errcode: 13)

То системная переменная UMASK может быть установлена неправильно, когда запускается mysqld. Значение по умолчанию для umask: 0660. Вы можете изменять это поведение, запуская safe_mysqld так:

shell> UMASK=384  # = 600 in octal
shell> export UMASK
shell> /path/to/safe_mysqld &

По умолчанию MySQL создаст базу данных и каталоги RAID с правами доступа 0700. Вы можете изменять это поведение, устанавливая переменную UMASK_DIR. Если Вы устанавливаете ее, новые каталоги будут созданы с объединением UMASK и UMASK_DIR. Например, если Вы хотите давать группе доступ ко всем новым каталогам, Вы можете сделать:

shell> UMASK_DIR=504              # =770 в аосьмеричном формате.
shell> export UMASK_DIR
shell> /path/to/safe_mysqld &

В MySQL Version 3.23.25 и выше MySQL считает, что значения UMASK и UMASK_DIR заданы в восьмеричном формате, если они начинаются с ноля.

11.4 Проблемы, связанные с администрированием

11.4.1 Что делать, если MySQL падает

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

Сначала Вы должны пробовать выяснять, состоит ли проблема в том, что mysqld падает, или ее корень надо искать на клиенте. Вы можете проверять время работы сервера mysqld командой mysqladmin version. Если mysqld свалился, Вы можете находить причину этого в файле mysql-data-directory/hostname.err.

Много сбоев MySQL вызваны разрушенным индексом или файлами данных. MySQL модифицирует данные относительно диска через системный вызов write() после каждой инструкции SQL, но прежде, чем пользователю сообщают относительно результата. Это не так, если Вы работаете с опцией delayed_key_writes, когда только данные будут записаны. Это означает, что данные в безопасности, даже если сбоит mysqld, если ОС гарантируют, что данные будут сброшены из кэша на диск. Вы можете заставить MySQL сбрасывать кэш принудительно после каждой команды SQL, запуская mysqld с опцией --flush.

Вышеупомянутое означает, что обычно Вы не должны получить разрушенные таблицы и файлы, если:

  • Кто-то уничтожил mysqld в середине модификации.
  • Вы нашли неизвестную ошибку в mysqld, которая разрушила его в середине модификации.
  • Кто-то управляет файлами данных или индекса вне mysqld без того, чтобы блокировать таблицу.
  • Если Вы управляете несколькими серверами mysqld на тех же самых данных в системе, которая не поддерживает хорошие блокировки файловой системы (обычно обрабатываемые сервером lockd), или была указана опция --skip-locking при запуске сервера.
  • Вы имеете поврежденный файл индекса или данных, который содержит очень неправильные данные, в результате mysqld запутался.
  • Вы нашли ошибку в коде памяти. Это не очень вероятно, но это по крайней мере возможно. В этом случае Вы можете пробовать изменять файл к другому драйверу базы данных использованием ALTER TABLE на восстановленной копии таблицы.

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

  • Завершите mysqld с помощью mysqladmin shutdown, запустите myisamchk --silent --force */*.MYI на всех таблицах и перезапустите сервер mysqld. Это гарантирует, что Вы запустились с чистого состояния.
  • Используйте mysqld --log и попробуйте определить из информации в файле регистрации, уничтожает или нет некоторый специфический запрос сервер. Приблизительно 95% всех ошибок связаны со специфическим запросом! Обычно это один из последних запросов в журнале. Если Вы можете повторить процесс уничтожения MySQL одним из запросов даже, когда Вы проверили все таблицы перед выполнением запроса, то ошибка локализована. Готовьте отчет об ошибке. Подробности в разделе "Приложение 3. Как сообщать о проблемах и сбоях".
  • Попробуйте управлять включенным тестом mysql-test и эталонными тестами MySQL. Подробности в разделе "14.3.2 Набор тестов MySQL". Они должны проверить MySQL довольно хорошо. Вы можете также добавлять к эталонным тестам код, который моделирует Вашу прикладную программу. Эталонные тесты могут быть найдены в каталоге bench дистрибутива исходного кода или, для двоичных дистрибутивов, в каталоге sql-bench под Вашим каталогом установок MySQL.
  • Попробуйте выполнить fork_test.pl и fork2_test.pl.
  • Вы применили самые последние заплатки для Вашей операционной системы?
  • Используйте опцию --skip-locking для mysqld. На некоторых системах администратор блокировок lockd не работает правильно. Опция --skip-locking сообщает, чтобы mysqld не использовал внешнюю блокировку. Это означает, что Вы не сможете выполнять несколько серверов mysqld на тех же самых данных, и что Вы должны быть внимательны, если Вы используете myisamchk, но может быть поучительно опробовать опцию как тест.
  • Вы пробовали mysqladmin -u root processlist, когда mysqld работает, но не отвечает? Иногда mysqld не завис даже при том, что Вы могли бы думать именно так. Проблема может состоять в том, что все подключения находятся в использовании, или может иметься некоторая внутренняя проблема блокировки. Вызов mysqladmin processlist обычно будет способен делать подключение даже в этих случаях и может обеспечивать полезную информацию относительно текущего числа подключений и их состояния.
  • Выполните команду mysqladmin -i 5 status или mysqladmin -i 5 -r status, чтобы произвести статистику в то время, как Вы выполняете другие Ваши запросы.
  • Попытайтесь смоделировать Вашу прикладную программу скриптом на Perl, чтобы вынудить MySQL разрушаться или плохо себя вести.
  • Пошлите нормальный отчет об ошибке. Подробности в разделе "Как сообщать о проблемах и сбоях". Может быть аварийный отказ следует из чего-то такого, что существует только на Вашем компьютере (например, ошибка, которая связана с Вашими специфическими библиотеками системы).
  • Если Вы имеете проблему с таблицами со строками динамической длины, и Вы не используете столбцы BLOB/TEXT (только VARCHAR), Вы можете пробовать изменять все VARCHAR на CHAR с помощью команды ALTER TABLE. Это вынудит MySQL использовать строки фиксированных размеров. Они берут небольшое дополнительное пространство, но намного более терпимы к искажению! Текущий динамический код строки был в использовании в MySQL AB по крайней мере 3 года без всяких проблем, но строки динамической длины вообще более склонны к ошибкам, так что посмотрите, что получится.

11.4.2 Как сбрасывать забытый пароль

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

  1. Завершите сервер mysqld отправкой ему команды kill (но не kill -9!). Идентификатор процесса будет сохранен в .pid-файле, который обычно хранится в каталоге для баз данных MySQL:
    kill `cat /mysql-data-directory/hostname.pid`
    Вы должны быть Unix-пользователем root или тем пользователем, от имени которого выполняется сервер.
  2. Перезапустите mysqld с опцией --skip-grant-tables.
  3. Соединитесь с mysqld командой mysql -h hostname mysql и смените пароль командой GRANT. Подробности в разделе "10.1 Синтаксис GRANT и REVOKE". Вы можете также делать это с помощью команды mysqladmin -h hostname -u user password new_password.
  4. Загрузите таблицы предоставления привилегий: mysqladmin -h hostname flush-privileges или командой SQL FLUSH PRIVILEGES.

Обратите внимание, что после того, как Вы запустили mysqld с опцией --skip-grant-tables, любое использование команды GRANT даст Вам ошибку Unknown command, пока Вы не выполните FLUSH PRIVILEGES.

11.4.3 Как MySQL обрабатывает полный диск

Когда диск полностью заполнится, MySQL делает следующее:

  • Он проверяет раз в минуту, чтобы видеть, имеется или нет достаточно места, чтобы записать текущую строку. Если имеется достаточно места на диске, работа продолжается, как будто ничто не случилось.
  • Каждые 5-6 минут в журнал пишется предупреждение о полном диске.

Чтобы облегчить проблему, Вы можете предпринять следующие действия:

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

Исключительные ситуации: Вы используете REPAIR или OPTIMIZE, индексы созданы в пакете после LOAD DATA INFILE, или выполнена инструкция ALTER TABLE.

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

11.4.4 Где MySQL хранит временные файлы

MySQL использует значение системной переменной TMPDIR как имя пути каталога, чтобы сохранить временные файлы. Если Вы не имеете TMPDIR, MySQL использует системное значение по умолчанию, которое является обычно /tmp или /usr/tmp. Если файловая система, содержащая Ваш временный каталог слишком маленькая, Вы должны отредактировать скрипт safe_mysqld, чтобы установить TMPDIR так, чтобы указать на каталог в файловой системе, где Вы имеете достаточно места. Вы можете также устанавливать временный каталог, используя опцию --tmpdir при вызове mysqld.

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

При сортировке (ORDER BY или GROUP BY) MySQL обычно использует один или два временных файла. Максимальное дисковое пространство, необходимое для сортировки:

(Длина сортируемых данных+sizeof(database pointer))*
число совпадающих строк*2

Здесь sizeof(database pointer) обычно 4, но может расти в будущем для действительно больших таблиц.

Для некоторого запроса SELECT MySQL также создает временные SQL-таблицы. Они не скрыты и имеют имена формы SQL_*.

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

11.4.5 Как защитить или сменить файл сокета MySQL /tmp/mysql.sock

Если Вы имеете проблемы с тем фактом, что любой может удалять сокет MySQL /tmp/mysql.sock, Вы можете, на большинстве версий Unix, защитить Вашу файловую систему /tmp, устанавливая липкий бит на ней. Зайдите в систему как root и скомандуйте:

shell> chmod +t /tmp

Это защитит Вашу файловую систему /tmp так, чтобы файлы могли быть удалены только их владельцами или суперпользователем (root).

Вы можете проверять, установлен ли липкий бит, выполняя ls -ld /tmp. Если последний бит прав доступа равен t, липкий бит установлен.

Вы можете изменять место, где MySQL помещают файл сокета, так:

  • Определите путь в глобальном или локальном файле опций. Например, поместите в /etc/my.cnf:
    [client]
socket=path-for-socket-file

[mysqld]
socket=path-for-socket-file
  • Определите это в командной строке для safe_mysqld и для большинства клиентов опцией --socket=path-for-socket-file.
  • Определите путь на сокет в системной переменной MYSQL_UNIX_PORT.

Вы можете проверять, что сокет работает, с помощью команды:

shell> mysqladmin --socket=/path/to/socket version

11.4.6 Проблемы с временными зонами

Если Вы имеете проблему с SELECT NOW(), возвращающим значения в GMT, а не по Вашему местному времени, Вы должны установить системную переменную TZ к Вашему текущему часовому поясу. Это должно быть выполнено для среды, в которой выполняется сервер, например, в скрипте safe_mysqld или в mysql.server.

11.5 Проблемы с запросами

11.5.1 Чувствительность к регистру в поиске

По умолчанию поиск в MySQL нечувствителен к регистру (хотя имеются некоторые наборы символов, которые всегда чувствительны, например, czech). Это означает, что, если Вы ищете col_name LIKE 'a%', Вы получите все значения столбца, которые начинаются с A или a. Если Вы хотите сделать этот поиск с учетом регистра, используйте нечто подобное INSTR(col_name, "A")=1, чтобы проверить префикс. Или используйте STRCMP(col_name,"A")=0, если значение столбца было точно "A".

Простые операции сравнения (>=, >, =, < ,<=, сортировка и группировка) основаны на значении сорта каждого символа. Символы с тем же самым значением сорта обрабатываются как тот же самый символ.

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

Если Вы хотите, чтобы столбец всегда обработался в режиме чувствительности к регистру, объявите его как BINARY. Подробности в разделе "7.3 Синтаксис CREATE TABLE ".

Если Вы используете китайские данные в так называемом кодировании big5, Вы должны сделать все символьные столбцы BINARY. Это работает потому, что порядок сортировки символов кодирования big5 основан на порядке ASCII кодов.

11.5.2 Проблемы использования столбцов DATE

Формат значения DATE всегда YYYY-MM-DD. Согласно ANSI SQL, никакой другой формат не позволяется. Вы должны использовать этот формат в выражениях UPDATE и в предложении WHERE инструкций SELECT. Например:

mysql> SELECT * FROM tbl_name WHERE date >= '1997-05-05';

Как дополнительное удобство MySQL автоматически преобразовывает дату в число, если дата используется в числовом контексте (и наоборот). Также достаточно интеллектуально обрабатывается ослабленная форма строки при модифицировании и в предложении WHERE, которое сравнивает дату со столбцом TIMESTAMP, DATE или DATETIME. Ослабленная форма означает, что любой символ пунктуации может использоваться как разделитель между частями. Например, 1998-08-15 и 1998#08#15 являются эквивалентными. MySQL может также преобразовывать строку не содержащую никаких разделителей (типа 19980815), если она имеет смысл как дата.

Специальная дата 0000-00-00 может быть сохранена и получена как 0000-00-00. При использовании даты 0000-00-00 через MyODBC, это будет автоматически преобразовано в NULL в MyODBC Version 2.50.12 и выше потому, что ODBC не может обрабатывать этот вид даты.

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

mysql> INSERT INTO tbl_name (idate) VALUES (19970505);
mysql> INSERT INTO tbl_name (idate) VALUES ('19970505');
mysql> INSERT INTO tbl_name (idate) VALUES ('97-05-05');
mysql> INSERT INTO tbl_name (idate) VALUES ('1997.05.05');
mysql> INSERT INTO tbl_name (idate) VALUES ('1997 05 05');
mysql> INSERT INTO tbl_name (idate) VALUES ('0000-00-00');
mysql> SELECT idate FROM tbl_name WHERE idate >= '1997-05-05';
mysql> SELECT idate FROM tbl_name WHERE idate >= 19970505;
mysql> SELECT mod(idate,100) FROM tbl_name WHERE idate >= 19970505;
mysql> SELECT idate FROM tbl_name WHERE idate >= '19970505';

Однако, следующее работать не будет:

mysql> SELECT idate FROM tbl_name WHERE STRCMP(idate,'19970505')=0;

STRCMP() представляет собой строковую функцию, так что это преобразовывает idate в строку и выполняет сравнение строк. Но она не конвертирует 19970505 в дату и не сравнивает даты.

Обратите внимание, что MySQL не делает никакой проверки, является или нет дата правильной. Если Вы сохраняете неправильную дату, типа 1998-2-31, неправильная дата будет сохранена. Если дата не может быть преобразована в любое приемлемое значение, 0 будет сохранен в поле DATE. Это главным образом проблема быстродействия.

11.5.3 Проблемы со значениями NULL

Концепция значения NULL представляет собой общий источник беспорядка для новичков в SQL, которые часто думают, что NULL та же самая вещь, что и пустая строка ''. Дело обстоит не так! Например, следующие инструкции полностью различны:

mysql> INSERT INTO my_table (phone) VALUES (NULL);
mysql> INSERT INTO my_table (phone) VALUES ("");

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

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

mysql> SELECT NULL,1+NULL,CONCAT('Invisible',NULL);

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

mysql> SELECT * FROM my_table WHERE phone = NULL;

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

mysql> SELECT * FROM my_table WHERE phone IS NULL;
mysql> SELECT * FROM my_table WHERE phone = "";

В MySQL как и во многих других SQL-серверах, Вы не можете индексировать столбцы, которые могут иметь значения NULL. Вы должны объявить столбцы для индекса как NOT NULL. Наоборот, Вы не можете вставлять NULL в индексированный столбец.

При чтении данных через LOAD DATA INFILE, пустые столбцы модифицируются с ''. Если Вы хотите иметь в столбце значение NULL, Вы должны использовать \N в текстовом файле. Литеральное слово 'NULL' может также с успехом использоваться при некоторых обстоятельствах. Подробности есть в разделе "8.9 Синтаксис LOAD DATA INFILE".

При использовании ORDER BY значения NULL будут представлены первыми. Если Вы сортируете в порядке по убыванию, используя DESC, значения NULL, понятно, окажутся в хвосте. При использовании GROUP BY, все значения NULL будут расценены как равные.

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

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

11.5.4 Проблемы с alias

Вы можете использовать псевдоним, чтобы обратиться к столбцу в GROUP BY, ORDER BY или в части HAVING. Псевдонимы могут также использоваться, чтобы дать столбцам лучшие имена:

SELECT SQRT(a*b) as rt FROM table_name GROUP BY rt HAVING rt > 0;
SELECT id,COUNT(*) AS cnt FROM table_name GROUP BY id HAVING cnt > 0;
SELECT id AS "Customer identity" FROM table_name;

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

SELECT id,COUNT(*) AS cnt FROM table_name WHERE cnt > 0 GROUP BY id;

Инструкция WHERE выполнена, чтобы определить, которые строки должны быть включены в часть GROUP BY в то время, как HAVING используется, чтобы решить, которые строки из набора результатов должны использоваться.

11.5.5 Удаление строк из связанных таблиц

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

  1. SELECT строки, основываясь на некотором условии WHERE в основной таблице.
  2. DELETE строки в основной таблице, основываясь на том же самом условии.
  3. DELETE FROM связанная_таблица WHERE связанные_столбцы IN (выбранные_строки).

Если общее количество символов в запросе со связанными столбцами (related_column) больше, чем 1048576 (значение по умолчанию для max_allowed_packet), Вы должны расчленить его на меньшие части и выполнить много инструкций DELETE. Вы, вероятно, достигнете пика производительности при удалении 100-1000 related_column на запрос, если related_column является индексом. В противном случае быстродействие независимо от числа параметров в предложении IN.

11.5.6 Решение проблем с несоответствием строк

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

  1. Проверьте запрос с помощью EXPLAIN и выправьте его, если Вы можете найти что-то такое, что является очевидно неправильным. Подробности в разделе "14.2.1 Синтаксис EXPLAIN (получение информации о SELECT)".
  2. Выберите только те поля, которые используются в предложении WHERE.
  3. Удаляйте по одной таблице из запроса, пока он не будет возвращать строки. Если таблицы большие, хорошо использовать с запросом LIMIT 10.
  4. Сделайте SELECT для столбца, который должен был соответствовать в таблице, которая была последней удалена из запроса.
  5. Если Вы сравниваете столбцы FLOAT или DOUBLE с числовыми столбцами, которые имеют десятичные числа, Вы не можете использовать =. Эта проблема общая в большинстве компьютерных языков потому, что значения с плавающей запятой не точные значения:
    mysql> SELECT * FROM table_name WHERE float_column=3.5;
    ->
mysql> SELECT * FROM table_name WHERE float_column between 3.45 and 3.55;
    В большинстве случаев замена FLOAT на DOUBLE исправит это дело.
  6. Если Вы все еще не можете вычислить, что идет неправильно, создайте минимальный тест, который может быть выполнен с mysql test < query.sql, который показывает Ваши проблемы. Вы можете создавать файл теста с помощью mysqldump --quick database tables > query.sql. Откройте файл в редакторе, удалите некоторые строки и добавьте Вашу инструкцию выбора в конце файла. Проверьте, что Вы все еще имеете Вашу проблему:
    shell> mysqladmin create test2
shell> mysql test2 < query.sql
    Отправьте файл теста, используя mysqlbug на mysql@lists.mysql.com.

11.6 Проблемы с определениями таблиц

11.6.1 Проблемы с ALTER TABLE

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

Если ALTER TABLE падает с ошибкой подобно этой:

Error on rename of './database/name.frm' to
                   './database/B-a.frm' (Errcode: 17)

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

ALTER TABLE работает следующим образом:

  • Создает новую таблицу под именем A-xxx с нужными изменениями.
  • Все строки из старой таблицы копируются в A-xxx.
  • Старая таблица переименуется в B-xxx.
  • Таблица A-xxx переименуется в старую таблицу.
  • Таблица B-xxx удаляется.

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

11.6.2 Как менять порядок столбцов в таблице

Вы должны всегда определять порядок, в котором Вы желаете получить данные:

SELECT col_name1, col_name2, col_name3 FROM tbl_name;

Возвратит столбцы в порядке col_name1, col_name2, col_name3 в то время, как:

SELECT col_name1, col_name3, col_name2 FROM tbl_name;

Возвратит столбцы в порядке col_name1, col_name3, col_name2.

Вы не должны в прикладной программе использовать SELECT * и получать столбцы, основываясь на их позиции потому, что порядок, в котором столбцы возвращены, НЕЛЬЗЯ ГАРАНТИРОВАТЬ через какое-то время. Простое изменение Вашей базы данных может заставить Вашу прикладную программу развалиться полностью.

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

  1. Создайте новую таблицу со столбцами в правильном порядке.
  2. Выполните INSERT INTO new_table SELECT fields-in-new_table-order FROM old_table.
  3. Удалите или переименуйте old_table.
  4. Выполните ALTER TABLE new_table RENAME old_table.

11.6.3 Проблемы с TEMPORARY TABLE

Следующее представляет собой список всех ограничений, действительных для временных таблиц (TEMPORARY TABLES).

  • Временные таблицы могут быть только типов HEAP, ISAM или MyISAM.
  • Вы не можете использовать временные таблицы больше одного раза в запросе. Например, следующее работать не будет:
    select * from temporary_table, temporary_table as t2;
    Это планируется исправить в версии 4.0.
  • Вы не можете использовать RENAME для таблиц TEMPORARY. Обратите внимание, что ALTER TABLE org_name RENAME new_name тем не менее работает вполне корректно! Это планируется исправить в версии 4.0.


Клиентские скрипты и утилиты MySQL

12 Клиентские скрипты и утилиты MySQL

12.1 Обзор клиентских скриптов и утилит

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

Имя | Описание
MYSQL_UNIX_PORT | Сокет по умолчанию. Используется для связи с localhost
MYSQL_TCP_PORT | TCP/IP порт по умолчанию
MYSQL_PWD | Пароль по умолчанию
MYSQL_DEBUG | Опции для трассировки, если используется режим отладки
TMPDIR | Каталог для временных файлов и таблиц

Применение MYSQL_PWD опасно. Подробности в разделе "2.1 Соединение с сервером".

Клиент mysql использует файл, именованный в системной переменной MYSQL_HISTFILE, чтобы сохранить хронологию командной строки. Значение по умолчанию для файла хронологии: $HOME/.mysql_history, здесь $HOME представляет собой значение системной переменной HOME. Подробности в разделе "Приложение 2. Переменные окружения ".

Все программы MySQL имеют много различных параметров. Однако, каждая программа MySQL обеспечивает опцию --help, которую Вы можете использовать, чтобы получить полное описание различных параметров программы. Например, mysql --help.

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

Список ниже кратко описывает программы MySQL:

myisamchk
Утилита, чтобы описывать, проверять, оптимизировать и ремонтировать MySQL таблицы. Потому, что myisamchk имеет много функций, он описан в собственной главе. Подробности в разделе "4 Администрирование СУБД MySQL".
make_binary_distribution
Делает двоичный выпуск из откомпилированного MySQL. Готовая версия может быть выложена по FTP в каталог /pub/mysql/Incoming на машине support.mysql.com для удобства других пользователей MySQL.
msql2mysql
Скрипт оболочки, который преобразовывает программы mSQL в MySQL. Не обрабатывает все случаи, но дает хорошее начало при преобразовании.
mysqlaccess
Скрипт, который проверяет привилегии доступа для компьютера, пользователя и комбинации баз данных.
mysqladmin
Утилита для выполнения административных операций, типа создания или удаления баз данных, перезагрузки таблиц предоставления, сброса таблиц на диск и повторного открытия журналов. Программа mysqladmin может также использоваться, чтобы узнавать версию, данные о процессах и информацию о текущем состоянии сервера.
mysqlbug
Скрипт для сообщения об ошибках MySQL. Этот скрипт всегда должен использоваться, когда готовится сообщение об ошибке в список рассылки MySQL.
mysqld
Сервер SQL. Должен всегда работать.
mysqldump
Сбрасывает базы данных MySQL в файл как инструкции SQL или как отделяемые табуляцией текстовые файлы. Подробности в разделе "12.5 mysqldump, Сброс в дамп структур таблицы и ее данных".
mysqlimport
Импортирует текстовые файлы в соответствующие таблицы, используя LOAD DATA INFILE. Подробности в разделе "12.7 mysqlimport, импортирование данных из текстовых файлов".
mysqlshow
Отображает подробную сводную информацию относительно баз данных, таблиц, столбцов и их индексов.
mysql_install_db
Создает таблицы предоставления привилегий MySQL с заданными по умолчанию привилегиями. Это обычно выполняется только однажды, при первой установке MySQL на систему.
replace
Утилита, которая используется msql2mysql, но имеет более общую применимость. replace меняет строки в файлах или на стандартном вводе. Использует специальный алгоритм, чтобы сначала соответствовать более длинным строкам. Может использоваться, чтобы менять строки. Например, эта команда меняет a и b в файлах:
shell> replace a b b a -- file1 file2 ...

12.2 Инструмент командной строки

mysql простая SQL оболочка (с возможностями GNU readline). Это поддерживает интерактивное и не интерактивное использование. Когда используется в интерактивном режиме, результаты запроса будут представлены в формате ASCII-таблицы. Когда используется в не интерактивном режиме (например, как фильтр), результат будет выведен в разделяемом табуляциями формате. Выходной формат может быть изменен, используя параметры командной строки. Вы можете выполнять скрипты так:

shell> mysql database < script.sql > output.tab

Если Вы имеете проблемы из-за недостаточной памяти у клиента, используйте опцию --quick! Это вынуждает клиент mysql использовать mysql_use_result() вместо вызова mysql_store_result(), чтобы отыскать набор результатов.

Использование mysql очень просто. Только запустите его следующим образом: mysql database или mysql --user=user_name --password=your_password database. Напечатайте инструкцию SQL, закончите ее `;', `\g' или `\G' и нажмите RETURN/ENTER.

mysql поддерживает следующие параметры:

-?, --help
Отобразить справку и завершится.
-A, --no-auto-rehash
Никакого автоматического перехеширования. Каждый должен использовать 'rehash', чтобы получить завершение поля и таблицу. Это дает более быстрый запуск клиента mysql.
-B, --batch
Печатать результаты, используя табуляцию как разделитель, каждая строка таблицы начинается на новой строке вывода. Не использует файл хронологии.
--character-sets-dir=...
Каталог, где размещены наборы символов.
-C, --compress
Использовать сжатие в протоколе клиент-сервер.
-#, --debug[=...]
Файл регистрации отладки. Значение по умолчанию 'd:t:o,/tmp/mysql.trace'.
-D, --database=...
База данных, которую надлежит использовать. Это, главным образом, полезно в файле my.cnf.
--default-character-set=...
Заданный по умолчанию набор символов.
-e, --execute=...
Выполнить команду и завершиться. Вывод как в случае --batch.
-E, --vertical
Печатать вывод запроса (строки) вертикально. Без этой опции Вы можете также достичь такого вывода, заканчивая команду сочетанием \G.
-f, --force
Продолжить, даже если мы получаем ошибку SQL.
-g, --no-named-commands
Именованные команды заблокированы. Используйте форму только \*. Можно применять именованные команды только в начале строки, оканчивающейся точкой с запятой (;). Начиная с Version 10.9, клиент теперь запускается с этой опцией по умолчанию! С опцией -g, длинный формат команд, однако, все еще будет работать из первой строки.
-G, --enable-named-commands
Именованные команды допускаются. Длинный формат команд позволяются также как сокращение команд \*.
-i, --ignore-space
Игнорировать пробелы после имен функций.
-h, --host=...
Соединиться с данным компьютером.
-H, --html
Производить вывод HTML.
-L, --skip-line-numbers
Не писать номер строки для ошибок. Полезно, когда надо сравнить результирующие файлы с ошибками.
--no-pager
Отключить pager и выводить наstdout. Подробности в интерактивной справке (\h).
--no-tee
Отключить outfile. Подробности в интерактивной справке (\h).
-n, --unbuffered
Сбрасывать буфер после каждого запроса.
-N, --skip-column-names
Не писать имена столбцов в результатах.
-O, --set-variable var=option
Задать переменной значение. Список переменных доступен через --help.
-o, --one-database
Модифицировать только заданную по умолчанию базу данных. Это полезно для пропуска модификаций другой базы данных в файле регистрации модификации.
--pager[=...]
Тип вывода. Значение по умолчанию: Ваша переменная окружения PAGER. Допустимые значения: less, more, cat [> filename], etc. Подробности в интерактивной справке (\h). Эта опция не работает в пакетном режиме. Pager работает только в UNIX.
-p[password], --password[=...]
Пароль, чтобы использовать при соединении с сервером. Если пароль не задан в командной строке, Вы будете запрошены относительно него. Обратите внимание, что, если Вы используете короткую форму -p, Вы не можете иметь пробелов между этой опцией и паролем.
-P --port=...
TCP/IP порт, чтобы использовать для подключения.
-q, --quick
Не кэшировать результат, печатать его строка в строку. Это может замедлять сервер, если вывод приостановлен. Не использует файл хронологии.
-r, --raw
Писать значения столбца без преобразования управляющих символов. Использован в режиме --batch.
-s, --silent
Быть более тихим.
-S --socket=...
Файл сокета, который надо использовать для подключения.
-t --table
Вывод в формате таблицы. Это задано по умолчанию в не пакетном режиме.
-T, --debug-info
Печатать информацию отладки при выходе.
--tee=...
Добавить все в outfile. Не работает в пакетном режиме.
-u, --user=#
Пользователь для входа в систему, если не текущий пользователь.
-U, --safe-updates[=#], --i-am-a-dummy[=#]
Позволить только UPDATE и DELETE, которые используют ключи. Вы можете сбрасывать эту опцию, если Вы имеете ее в Вашем файле my.cnf, используя параметр --safe-updates=0.
-v, --verbose
Более подробный вывод (-v -v -v дает выходной формат таблицы).
-V, --version
Вывести информацию о версии и завершиться.
-w, --wait
Ждать и повторять попытки связаться, если подключение свалилось.

Вы можете также устанавливать следующие переменные через -O или --set-variable:

Имя переменной | Значение по умолчанию | Описание
connect_timeout | 0 | Число секунд перед завершением подключения по тайм-ауту.
max_allowed_packet | 16777216 | Максимальная длина пакетов для обмена с сервером.
net_buffer_length | 16384 | Буфер для связи через сокет или TCP/IP.
select_limit | 1000 | Автоматическое ограничение для SELECT при использовании --i-am-a-dummy
max_join_size | 1000000 | Автоматическое ограничение для строк в объединении при использовании --i-am-a-dummy.

Если Вы напечатаете 'help' в командной строке, mysql распечатает команды, которые он поддерживает:

mysql> help

MySQL commands:
help    (\h)    Display this text.
?       (\h)    Synonym for `help'.
clear   (\c)    Clear command.
connect (\r)    Reconnect to the server. Optional arguments are db and host.
edit    (\e)    Edit command with $EDITOR.
ego     (\G)    Send command to mysql server, display result vertically.
exit    (\q)    Exit mysql. Same as quit.
go      (\g)    Send command to mysql server.
nopager (\n)    Disable pager, print to stdout.
notee   (\t)    Don't write into outfile.
pager   (\P)    Set PAGER [to_pager]. Print the query results via PAGER.
print   (\p)    Print current command.
quit    (\q)    Quit mysql.
rehash  (\#)    Rebuild completion hash.
source  (\.)    Execute a SQL script file. Takes a file name as an argument.
status  (\s)    Get status information from the server.
tee     (\T)    Set outfile [to_outfile]. Append everything into given outfile.
use     (\u)    Use another database. Takes database name as argument.

Внимание: pager работает только в UNIX.

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

Полезная опция запуска для новичков (появилась в MySQL Version 3.23.11): --safe-updates (или --i-am-a-dummy для пользователей, которые скомандовали DELETE FROM table_name, но забыли указать предложение WHERE). При использовании этой опции, mysql посылает следующую команду серверу MySQL при открытии подключения:

SET SQL_SAFE_UPDATES=1,SQL_SELECT_LIMIT=#select_limit#,
    SQL_MAX_JOIN_SIZE=#max_join_size#"

Здесь #select_limit# и #max_join_size# являются переменными, которые могут быть заданы в командной строке mysql.

Эффект вышеупомянутой команды:

  • Вам не позволяют давать инструкции UPDATE или DELETE, если Вы не имеете ограничения ключа в части WHERE. Можно, однако, выполнить UPDATE/DELETE, используя слово LIMIT:
    UPDATE table_name SET not_key_column=# WHERE not_key_column=# LIMIT 1;
  • Все большие результаты автоматически ограничены строками #select_limit#.
  • SELECT, который, вероятно, должен будет исследовать больше, чем #max_join_size комбинаций строк, будет прерван.

Некоторые полезные советы относительно применения клиента mysql:

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

mysql> select * from mails where length(txt) < 300 limit 300,1\G
*************************** 1. row ***************************
  msg_nro: 3068
     date: 2000-03-01 23:29:50
time_zone: +0200
mail_from: Monty
    reply: monty@no.spam.com
  mail_to: "Thimble Smith" <tim@no.spam.com>
      sbj: UTF-8
      txt: >>>>> "Thimble" == Thimble Smith writes:

Thimble> Hi. I think this is a good idea. Is anyone familiar with
Thimble> UTF-8 or Unicode? Otherwise I'll put this on my TODO list
Thimble> and see what happens.

Yes, please do that.

Regards,
Monty
     file: inbox-jani-1
     hash: 190402944
1 row in set (0.09 sec)
  • Для регистрации Вы можете использовать опцию tee. Режим tee может быть начат с помощью опции --tee=... или из командной строки в интерактивном режиме с помощью команды tee. Все данные, отображаемые на экране, будут также добавляться в заданный файл. Это может быть очень полезно для отладки. Режим может быть заблокирован из командной строки командой notee. Выполнение tee второй раз снова начинает регистрировать вывод. Без параметра будет использоваться предыдущий файл. Обратите внимание, что tee сбрасывает результаты в файл после каждой команды прежде, чем появляется командная строка.
  • Просмотр или поиск результатов в интерактивном режиме в UNIX с помощью less, more или любой другой подобной программы, является теперь возможным с опцией --pager[=...]. Без параметра клиент mysql будет искать системную переменную PAGER и соответственно устанавливать свой параметр pager. Этот режим может быть запущен из интерактивной командной строки командой pager и заблокирован командой nopager. Команда факультативно берет параметр, и pager будет установлен в заданное им значение. Команда pager может быть вызвана без параметра, но это требует, чтобы использовалась опция --pager, или pager будет значением по умолчанию (stdout). pager работает только в UNIX, так как это использует функцию popen(), которая не существует в Windows. Под ОС Windows опция tee может использоваться вместо этого, хотя она не может быть столь же удобна, как pager в некоторых ситуациях.
  • Несколько советов относительно pager: Вы можете использовать его, чтобы писать в файл:
    mysql> pager cat > /tmp/log.txt
    И результаты будут переданы только в этот файл. Вы можете также передавать любые параметры для программ, которые Вы хотите использовать с pager:
    mysql> pager less -n -i -S
    Из вышеупомянутого обратите внимание на опцию '-S'. Вы можете посчитать ее очень полезной при просмотре результатов. Попробуйте опцию с горизонтальным выводом (команды заканчиваются на '\g' или ';') и с вертикальным выводом (команды заканчиваются на '\G'). Иногда очень широкий набор результатов должен быстро читаться с экрана, с опцией -S и программой less Вы сможете просмотреть результаты внутри интерактивного less слева направо без строк, более длинных, чем Ваш экран. Это может сделать результат намного более читаемым. Вы можете переключать режим внутри интерактивного less с помощью '-S'. Подробности в описании на 'h'.
  • Вы можете объединять очень сложные способы обрабки результатов, например, следующее пошлет результаты двум файлам в двух различных каталогах, на двух различных жестких дисках, /dr1 и /dr2, и на экран через less:
    mysql> pager cat|tee /dr1/tmp/res.txt|tee /dr2/tmp/res2.txt| \
                 less -n -i -S
  • Вы можете также объединять две функции: включить tee, pager установить на 'less', и Вы будете способны просмотреть результаты в unix 'less' и все еще копировать весь вывод в файл. Различие между UNIX tee, используемом с pager и клиентом mysql то, что встроенный режим tee работает, даже если Вы не имеете UNIX tee.

12.3 mysqladmin, Администрирование сервера MySQL

Утилита для выполнения административных операций. Синтаксис:

shell> mysqladmin [OPTIONS] command [command-option] command ...

Вы можете получить список параметров, которые Ваша версия mysqladmin поддерживает, выполняя mysqladmin --help.

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

create databasename
Создать новую базу данных.
drop databasename
Удалить базу данных и все таблицы.
extended-status
Дает расширенное сообщение состояния сервера.
flush-hosts
Сбрасывает все кэшируемые хосты.
flush-logs
Сбрасывает все протоколы.
flush-tables
Сбрасывает все таблицы на диск.
flush-privileges
Перезагружает таблицы предоставления привилегий (то же, что и reload).
kill id,id,...
Уничтожает поток mysql.
password
Устанавливает новый пароль. Изменяет старый пароль на новый.
ping
Проверяет, является ли mysqld действующим.
processlist
Показывает список активных потоков сервера.
reload
Перезагружает таблицы предоставления привилегий
refresh
Сбрасывает на диск все таблицы и открытые файлы протоколов.
shutdown
Завершает работу сервера.
slave-start
Запускает подчиненный процесс репликации.
slave-stop
Завершает подчиненный процесс репликации.
status
Дает короткое сообщение состояния сервера.
variables
Печатает доступные переменные.
version
Выдает краткую информацию о версии сервера.

Все команды могут быть сокращены к их уникальному префиксу. Например:

shell> mysqladmin proc stat
+----+-------+-----------+----+-------------+------+-------+------+
| Id | User  | Host      | db | Command     | Time | State | Info |
+----+-------+-----------+----+-------------+------+-------+------+
| 6  | monty | localhost |    | Processlist | 0    |       |      |
+----+-------+-----------+----+-------------+------+-------+------+
Uptime: 10077  Threads: 1  Questions: 9  Slow queries: 0  Opens: 6  Flush tables: 1  Open tables: 2  Memory in use: 1092K  Max memory used: 1116K

Результат команды mysqladmin status имеет следующие столбцы:

Uptime | Число секунд, которые прошли с момента запуска сервера
Threads | Число активных потоков (клиентов)
Questions | Число запросов от клиентуры с тех пор, как mysqld был запущен.
Slow queries | Запросы, которые заняли больше, чем long_query_time секунд.
Opens | Сколько таблиц открылись в mysqld.
Flush tables | Сколько выполнено команд flush ..., refresh и reload.
Open tables | Число таблиц, которые открыты СЕЙЧАС.
Memory in use | Память, распределенная непосредственно кодом mysqld (доступно только, когда MySQL компилируется с опцией --with-debug=full).
Max memory used | Максимальная память, распределенная непосредственно кодом mysqld (доступно только, когда MySQL компилируется с опцией --with-debug=full).

Если Вы делаете myslqadmin shutdown на сокете (другими словами, на компьютере, где запущен mysqld), mysqladmin будет ждать, пока не будет удален MySQL pid-file, чтобы гарантировать, что сервер mysqld был завершен правильно.

12.4 Использование mysqlcheck для поддержания таблиц и восстановления

Начиная с MySQL version 3.23.38, Вы можете использовать новый инструмент для проверки и ремонта таблиц MyISAM. Отличие от myisamchk в том, что mysqlcheck должен использоваться, когда сервер mysqld работает, а myisamchk работает только, когда сервер выключен.

mysqlcheck использует команды сервера MySQL CHECK, REPAIR, ANALYZE и OPTIMIZE удобным для пользователя способом.

Имеются три альтернативных способа вызвать mysqlcheck:

shell> mysqlcheck [OPTIONS] database [tables]
shell> mysqlcheck [OPTIONS] --databases DB1 [DB2 DB3...]
shell> mysqlcheck [OPTIONS] --all-databases

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

Имена, которые Вы можете использовать, чтобы изменить заданное по умолчанию поведение mysqlcheck:

mysqlrepair:   По умолчанию опция -r
mysqlanalyze:  По умолчанию опция -a
mysqloptimize: По умолчанию опция -o

Параметры, доступные для mysqlcheck, перечислены здесь, пожалуйста, проверьте, что Ваша версия поддерживает вызов mysqlcheck --help.

-A, --all-databases
Проверить все базы данных. Это будет то же самое, что и --databases с выбором всех баз данных.
-1, --all-in-1
Вместо того, чтобы делать один запрос для каждой таблицы, выполнить все запросы в одном запросе отдельно для каждой базы данных. Имена таблиц будут переданы в списке через запятую.
-a, --analyze
Анализировать данные таблицы.
--auto-repair
Если проверяемая таблица разрушена, автоматически исправить ее. Восстановление будет выполнено после того, как все таблицы проверятся.
-#, --debug=...
Файл регистрации отладки. Часто это 'd:t:o,filename'.
--character-sets-dir=...
Каталог, где искать наборы символов.
-c, --check
Проверить таблицу на ошибки.
-C, --check-only-changed
Проверить только те таблицы, которые изменились с последней проверки или не были закрыты правильно.
--compress
Использовать сжатие в протоколе клиент-сервер.
-?, --help
Отобразить сообщение справки.
-B, --databases
Проверять несколько баз данных. Обратите внимание на различие в использовании: в этом случае никакие таблицы не даны. Все параметры будут расценены как имена баз данных.
--default-character-set=...
Заданный по умолчанию набор символов.
-F, --fast
Проверить только те таблицы, которые не были закрыты правильно.
-f, --force
Продолжить, даже если мы получаем sql-ошибку.
-e, --extended
Если Вы используете эту опцию с CHECK TABLE, это гарантирует, что таблица на 100% непротиворечива, но займет длительное время. Если Вы используете эту опцию с REPAIR TABLE, она выполнит расширенный ремонт таблицы, который может занять немало времени и породить много строк мусора в таблице!
-h, --host=...
Связаться с указанным хостом.
-m, --medium-check
Быстрее, чем extended-check, но находит только 99.99% всех ошибок. Режим должен быть достаточно хорошим для большинства случаев.
-o, --optimize
Оптимизировать таблицу.
-p, --password[=...]
Пароль, чтобы использовать при соединении с сервером. Если пароль не задан, он будет запрошен.
-P, --port=...
Номер порта, который надлежит использовать для подключения.
-q, --quick
Если Вы используете эту опцию с CHECK TABLE, это не дает просматривать строки, чтобы проверить неправильные связи. Это самая быстрая проверка. Если Вы используете эту опцию с REPAIR TABLE, ремонту будет подвергнуто только индексное дерево. Это самый быстрый метод ремонта для таблицы.
-r, --repair
Может выправить почти все, что угодно, за исключением уникальных ключей, которые стали не уникальными.
-s, --silent
Выводить только сообщения об ошибках.
-S, --socket=...
Файл сокета, который надо использовать для подключения.
--tables
Отменяет опцию --databases (-B).
-u, --user=#
Пользователь для входа в систему, если не текущий пользователь.
-v, --verbose
Печатать информацию относительно различных стадий.
-V, --version
Вывести информацию о версии.

12.5 mysqldump, Сброс в дамп структуры таблицы и ее данных

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

Если Вы делаете копию на сервер, Вы должны рассмотреть использование вместо этой утилиты mysqlhotcopy. Подробности в разделе "12.6 mysqlhotcopy, копирование баз данных и таблиц MySQL".

shell> mysqldump [OPTIONS] database [tables]
           mysqldump [OPTIONS] --databases [OPTIONS] DB1 [DB2 DB3...]
           mysqldump [OPTIONS] --all-databases [OPTIONS]

Если Вы не задаете таблицы или используете --databases или --all-databases, целая база данных будет сброшена в дамп.

Вы можете получить список параметров, которые поддерживает Ваша версия mysqldump, выполняя mysqldump --help.

Обратите внимание, что, если Вы выполняете mysqldump без опций --quick или --opt, mysqldump загрузит целый набор результатов в память перед дампингом. Это будет, вероятно, проблемой, если Вы обрабатываете большую базу данных.

Обратите внимание, что, если Вы используете новую копию программы mysqldump и собираетесь делать дамп, который будет читаться очень старым сервером MySQL, Вы не должны использовать параметры --opt или -e.

mysqldump поддерживает следующие параметры:

--add-locks
Добавить LOCK TABLES перед и UNLOCK TABLE после каждого дампа таблицы, чтобы получить быстрые вставки в MySQL.
--add-drop-table
Добавить drop table перед каждой инстукцией создания.
-A, --all-databases
Дамп всех баз данных. Это будет то же самое, что и --databases со всеми выбранными базами данных.
-a, --all
Включить все MySQL-специфичные параметры create.
--allow-keywords
Позволить создание имен столбцов, которые являются ключевыми словами. Это реализовано путем приписывания имен столбцов к имени таблицы.
-c, --complete-insert
Использовать полный формат инструкций вставки (с именами столбца).
-C, --compress
Сжимать всю информацию, передаваемую между клиентом и сервером, если они оба поддерживают сжатие.
-B, --databases
Сбросить в дамп несколько баз данных. Обратите внимание на различие в использовании. В этом случае никакие таблицы не могут быть заданы. Все параметры имени будут расценены как имена базы данных. USE db_name; будет включен в вывод перед каждой новой базой данных.
--delayed
Вставлять строки командой INSERT DELAYED.
-e, --extended-insert
Использовать новый синтаксис INSERT. Дает более компактные и быстрые инструкции вставок.
-#, --debug[=option_string]
Использовать трассировку (для отладки).
--help
Отобразить справку о параметрах.
--fields-terminated-by=...
--fields-enclosed-by=...
--fields-optionally-enclosed-by=...
--fields-escaped-by=...
--lines-terminated-by=...
Эти параметры используются с опцией -T и имеют то же самое значение, что и соответствующие предложения для LOAD DATA INFILE. Подробности в разделе "8.9 Синтаксис LOAD DATA INFILE".
-F, --flush-logs
Сбросить файл протокола сервера MySQL на диск перед стартом дампа.
-f, --force,
Продолжать, даже если мы получаем SQL ошибку в течение дампа таблицы.
-h, --host=...
Сбросить данные в дамп с сервера MySQL на указанном хосте. Заданный по умолчанию хост: localhost.
-l, --lock-tables
Блокировать все таблицы перед стартом дампа. Таблицы будут заблокированы с опцией READ LOCAL, чтобы позволить параллельные вставки в случае таблиц MyISAM.
-n, --no-create-db
Запись 'CREATE DATABASE /*!32312 IF NOT EXISTS*/ db_name;' не будет помещена в вывод. Вышеупомянутая строка будет добавлена иначе, если была дана опция --databases или --all-databases.
-t, --no-create-info
Не писать информацию для создания таблицы (инструкция CREATE TABLE ).
-d, --no-data
Не писать любую информацию строк для таблицы. Это очень полезно, если Вы хотите получить только дамп структуры для таблицы!
--opt
То же самое, что и задать --quick --add-drop-table --add-locks --extended-insert --lock-tables. Опция должна дать Вам самый быстрый возможный дамп для чтения на сервере MySQL.
-pyour_pass, --password[=your_pass]
Пароль, чтобы использовать при соединении с сервером. Если Вы не определяете никакой части `=your_pass', Вы будете запрошены относительно ввода пароля.
-P port_num, --port=port_num
TCP/IP порт, чтобы использовать для соединения с удаленным компьютером. Это используется для подключений к системам, отличным от localhost, там применяются Unix-сокеты.
-q, --quick
Не буферизовать запрос, дамп непосредственно направляется на stdout. Для этого используется вызов mysql_use_result().
-r, --result-file=...
Прямой вывод в заданный файл. Эта опция должна использоваться в MSDOS, поскольку не превращает '\n' в '\n\r'.
-S /path/to/socket, --socket=/path/to/socket
Файл сокета, чтобы использовать при соединении с localhost. Он является заданным по умолчанию компьютером.
--tables
Отменяет опцию --databases (-B).
-T, --tab=path-to-some-directory
Создает файл table_name.sql, который содержит команды SQL CREATE, и файл table_name.txt, который содержит данные для каждой указанной таблицы. ОБРАТИТЕ ВНИМАНИЕ: Это работает только, если mysqldump выполнен на той же самой машине, что и сервер mysqld. Формат файла .txt соответствует опциям --fields-xxx и --lines--xxx.
-u user_name, --user=user_name
Пользователь MySQL, чтобы применить при соединении с сервером. Значение по умолчанию: Ваше Unix-имя входа в систему.
-O var=option, --set-variable var=option
Установить значение переменной. Возможные переменные перечислены ниже.
-v, --verbose
Подробный режим. Распечатать большее количество информации относительно того, что делает программа.
-V, --version
Вывести информацию о версии.
-w, --where='where-condition'
Дамп только выбранных записей. Обратите внимание, что КАВЫЧКИ обязательны:
"--where=user='jimf'" "-wuserid>1" "-wuserid<1"
-O net_buffer_length=#, where # < 16M
При создании мультистрочных инструкций (как с опцией --extended-insert или --opt), mysqldump создаст строки длины до net_buffer_length. Если Вы увеличиваете эту переменную, Вы должны также гарантировать, что переменная max_allowed_packet в сервере MySQL больше, чем net_buffer_length.

Наиболее нормальное использование mysqldump: создание копий целых баз данных. Подробности в разделе "4.1 Резервирование баз данных":

mysqldump --opt database > backup-file.sql

Вы можете прочитать этот файл обратно в MySQL:

mysql database < backup-file.sql

или:

mysql -e "source /patch-to-backup/backup-file.sql" database

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

mysqldump --opt database|mysql --host=remote-host -C database

Возможно выполнить дамп нескольких баз данных одной командой:

mysqldump --databases database1 [database2 database3...] > my_databases.sql

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

mysqldump --all-databases > all_databases.sql

12.6 mysqlhotcopy, копирование баз данных и таблиц MySQL

mysqlhotcopy представляет собой perl-скрипт, который использует LOCK TABLES, FLUSH TABLES и cp или scp, чтобы быстро сделать копию базы данных. Это самый быстрый способ сделать копию с базы данных или одиночной таблицы, но это может быть выполнено только на той же самой машине, где находятся каталоги баз данных.

mysqlhotcopy db_name [/path/to/new_directory]
mysqlhotcopy db_name_1 ... db_name_n /path/to/new_directory
mysqlhotcopy db_name./regex/

mysqlhotcopy поддерживает следующие параметры:

-?, --help
Отобразить экран справки.
-u, --user=#
Пользователь для входа в систему.
-p, --password=#
Пароль для входа в систему.
-P, --port=#
Порт, чтобы использовать при соединении с локальным сервером.
-S, --socket=#
Сокет, который надо использовать при соединении с локальным сервером.
--allowold
Не прерывать процесс копирования, если файл-адресат уже существует (переименовать его в его же имя с добавлением суффикса _old).
--keepold
Не удалять предыдущего (теперь переименованного) адресата, когда процесс копирования будет выполнен.
--noindices
Не включать полные индексные файлы в копию, чтобы сделать копию меньше. Индексы могут позже быть восстановлены с помощью myisamchk -rq.
--method=#
Метод для получения копии (cp или scp).
-q, --quiet
Сообщать только об ошибках.
--debug
Включить режим отладки.
-n, --dryrun
Только сообщать о действиях, но не выполнять их.
--regexp=#
Копировать все базы данных с именами, соответствующими regexp.
--suffix=#
Суффикс для добавления к именам скопированных баз данных.
--checkpoint=#
Вставить запись контрольной точки в определенный db.table.
--flushlog
Сбросить протоколы на диск при блокировке таблиц.
--tmpdir=#
Временный каталог (вместо /tmp).

Вы можете использовать perldoc mysqlhotcopy, чтобы получить более полную документацию для mysqlhotcopy.

mysqlhotcopy читает группы [client] и [mysqlhotcopy] из файлов опций.

Чтобы выполнить mysqlhotcopy, Вы нуждаетесь в доступе к резервному каталогу для записи, в привилегии SELECT для таблиц, которые Вы собираетесь копировать, и в привилегии MySQL Reload, чтобы выполнить команду FLUSH TABLES.

12.7 mysqlimport, импорт данных из текстовых файлов

mysqlimport интерфейс командной строки к инструкции SQL LOAD DATA INFILE. Большинство параметров mysqlimport непосредственно соответствует тем же самым параметрам LOAD DATA INFILE. Подробности в разделе "8.9 Синтаксис LOAD DATA INFILE ".

mysqlimport вызывается подобно этому:

shell> mysqlimport [options] database textfile1 [textfile2....]

Для каждого текстового файла, указанного в командной строке, mysqlimport отделяет любое расширение от имени файла и использует результат, чтобы определить, в которую таблицу импортировать содержание файла. Например, файлы с именами patient.txt, patient.text и patient будут все вместе импортированы в одну таблицу patient.

mysqlimport поддерживает следующие параметры:

-c, --columns=...
Эта опция берет разделяемый запятыми список имен полей как параметр. Он используется, чтобы создать соответствующую команду LOAD DATA INFILE, которая затем будет передана MySQL. Подробности в разделе "8.9 Синтаксис LOAD DATA INFILE ".
-C, --compress
Сжать всю информацию, передаваемую между клиентом и сервером.
-#, --debug[=option_string]
Использовать трассировку программы (для отладки).
-d, --delete
Очистить таблицу перед импортированием в нее текстового файла.
--fields-terminated-by=...
--fields-enclosed-by=...
--fields-optionally-enclosed-by=...
--fields-escaped-by=...
--lines-terminated-by=...
Эти параметры имеют то же самое значение, что и соответствующие предложения для LOAD DATA INFILE. Подробности в разделе "8.9 Синтаксис LOAD DATA INFILE ".
-f, --force
Игнорировать ошибки. Например, если таблица для текстового файла не существует, продолжить обрабатывать все оставшиеся файлы. Без --force mysqlimport прерывает работу, если нужная таблица не существует.
--help
Отобразить экран справки.
-h host_name, --host=host_name
Импортировать данные на сервер MySQL на указанном компьютере. Заданный по умолчанию компьютер: localhost.
-i, --ignore
Подробности в описании для опции --replace.
-l, --lock-tables
Блокировать ВСЕ таблицы на запись перед обработкой любых текстовых файлов. Это гарантирует, что все таблицы синхронизированы.
-L, --local
Читать входные файл с клиента. По умолчанию считается, что текстовые файлы хранятся на сервере, если Вы соединяетесь с хостом localhost (который является заданным по умолчанию компьютером).
-pyour_pass, --password[=your_pass]
Пароль, чтобы использовать при соединении с сервером. Если Вы не определяете часть =your_pass, mysqlimport запросит Вас относительно пароля.
-P port_num, --port=port_num
Порт TCP/IP, чтобы использовать для соединения с сервером. Это используется для подключений к системам, отличным от localhost, там применены сокеты Unix.
-r, --replace
Опции --replace и --ignore контролируют обработку управления параметров входных записей, которые дублируют существующие записи на уникальных значениях ключа. Если Вы определяете --replace, новые строки заменят существующие, которые имеют то же самое уникальное значение ключа. Если Вы определяете --ignore, они будут пропущены. Если Вы не определяете никакой опции вообще, происходит ошибка, когда найдено двойное значение ключа, а остальная часть текстового файла игнорируется.
-s, --silent
Тихий режим работы. На вывод подается информация только тогда, когда происходят ошибки в работе.
-S /path/to/socket, --socket=/path/to/socket
Файл сокета, чтобы использовать при соединении с localhost (является заданным по умолчанию компьютером).
-u user_name, --user=user_name
MySQL-пользователь под именем которого надо соединяться с сервером. Значение по умолчанию: Ваше Unix-имя входа в систему.
-v, --verbose
Подробный режим. Выводит большее количество информации относительно того, что программа делает.
-V, --version
Выводит информацию о версии.

Имеется типовой образец выполнения mysqlimport:

$ mysql --version
mysql  Ver 9.33 Distrib 3.22.25, for pc-linux-gnu (i686)
$ uname -a
Linux xxx.com 2.2.5-15 #1 Mon Apr 19 22:21:09 EDT 1999 i586 unknown
$ mysql -e 'CREATE TABLE imptest(id INT, n VARCHAR(30))' test
$ ed
a
100     Max Sydow
101     Count Dracula
.
w imptest.txt
32
q
$ od -c imptest.txt
0000000   1   0   0  \t   M   a   x       S   y   d   o   w  \n   1   0
0000020   1  \t   C   o   u   n   t       D   r   a   c   u   l   a  \n
0000040
$ mysqlimport --local test imptest.txt
test.imptest: Records: 2  Deleted: 0  Skipped: 0  Warnings: 0
$ mysql -e 'SELECT * FROM imptest' test
+------+---------------+
| id   | n             |
+------+---------------+
|  100 | Max Sydow     |
|  101 | Count Dracula |
+------+---------------+

12.8 Показ баз данных таблиц и столбцов

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

Программой mysql Вы можете получать ту же самую информацию командой SHOW. Подробности в разделе "4.10 Синтаксис SHOW".

mysqlshow вызывается подобно этому:

shell> mysqlshow [OPTIONS] [database [table [column]]]
  • Если никакая база данных не задана, показываются все базы данных.
  • Если никакая таблица не задана, показываются все таблицы в базе данных.
  • Если никакой столбец не задан, показываются все столбцы и типы столбцов в таблице, соответствующие запросу.

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

Если последний параметр содержит подстановочные знаки оболочки или SQL (*, ?, % или _), показывается только то, что согласовано групповым символом. Это может вызвать некоторый беспорядок, когда Вы пробуете отображать столбцы для таблицы с символом _ в имени, поскольку в этом случае mysqlshow показывает Вам имена, соответствующие образцу. Это легко устранимо добавлением в конце командной строки символа % (как отдельный параметр).

12.9 perror, объяснение кодов ошибок

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

shell> perror [OPTIONS] [ERRORCODE [ERRORCODE...]]

например:

shell> perror 64 79
Error code  64:  Machine is not on the network
Error code  79:  Can not access a needed shared library

perror может использоваться, чтобы отобразить описание для кода ошибки системы или драйвера таблицы MyISAM/ISAM. Сообщения об ошибках обычно зависят от системы.

12.10 Как выполнить команды SQL из текстового файла

Клиент mysql обычно используется в интерактивном режиме:

shell> mysql database

Однако, также возможно поместить Ваши команды SQL в файл и сообщить, чтобы mysql читал ввод из того файла. Чтобы сделать так, создайте текстовый файл text_file, хранящий команды, которые Вы желаете выполнить. Затем вызовите mysql как показано ниже:

shell> mysql database < text_file

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

shell> mysql < text_file


Поддержка MySQL ODBC

13 Поддержка MySQL ODBC

MySQL предоставляет поддержку интерфейса ODBC с помощью пакета MyODBC. Эта глава научит Вас, как установить и использовать MyODBC. Здесь Вы также найдете список общих программ, которые, как известно, работают с MyODBC.

13.1 Как ставить MyODBC

MyODBC представляет собой 32-bit ODBC (2.50) level 0 (с возможностями level 1 и level 2) драйвер для соединения ODBC-приложений с СУБД MySQL. MyODBC работает под Windows95, Windows98, NT и на некоторых Unix-системах.

MyODBC публично доступен, и Вы можете спокойно скачать его новейшую версию с http://www.mysql.com/downloads/api-myodbc.html.

Если Вы имеете проблему с MyODBC, и Ваша программа также работает с OLEDB, Вы должны попробовать драйвер для OLEDB, который Вы можете найти в разделе Contrib.

Обычно Вы должны установить MyODBC только на системах с Windows. Под Unix MyODBC Вам понадобится только, если Вы имеете программу подобную ColdFusion, которая выполняется на Unix-машине и использует ODBC, чтобы соединиться с базами данных.

Если Вы хотите устанавливать MyODBC под Unix, Вы будете также нуждаться в диспетчере ODBC. MyODBC, как известно, работает с большинством Unix ODBC-диспетчеров. Вы можете найти список ODBC-секции ссылок на страничке MySQL. Подробности в разделе "1.2.3 Хорошие ссылки по MySQL ".

Чтобы установить MyODBC в Windows, Вы должны загрузить соответствующий файл MyODBC .zip (для Windows9x или NT/Win2000), распаковывать его с помощью WINZIP или другой подобной программы и выполнить файл SETUP.EXE.

В Windows NT Вы можете получать следующую ошибку при попытке установить MyODBC:

An error occurred while copying C:\WINDOWS\SYSTEM\MFC30.DLL. Restart
Windows and try installing again (before running any applications
which use ODBC)

Проблема в этом случае состоит в том, что некоторая другая программа использует ODBC, а также из-за того, как неудобно устроена Windows, Вы не можете в этом случае установить новые ODBC-драйверы программой установки Microsoft ODBC setup. В большинстве случаев Вы можете продолжать установку, нажав кнопку Ignore, чтобы копировать остальную часть файлов MyODBC. Если это не работает, решение состоит в том, чтобы перезагрузить Ваш компьютер в safe mode (выберите это, нажимая F8 перед запуском Windows после перезагрузки), установить MyODBC и перезагрузиться назад в нормальный режим работы.

  • Чтобы сделать соединение с Unix-системой из Windows, приложением ODBC (которое не поддерживает напрямую MySQL), Вы должно сначала установить MyODBC на машине Windows.
  • Пользователь и Windows-машина должны иметь привилегии доступа к серверу MySQL на Unix-машине. Это должно быть установлено с помощью команды GRANT. Подробности в разделе "10.1 Синтаксис GRANT и REVOKE".
  • Вы должны создать запись ODBC DSN следующим образом:
    • Откройте Control Panel на Windows-системе.
    • Дважды щелкните по пиктограмме ODBC Data Sources 32 bits.
    • Нажмите метку User DSN.
    • Нажмите кнопку Add.
    • Выберите MySQL на экране Create New Data Source и нажмите кнопку Finish.
    • Показывается экран конфигурации значений по умолчанию драйвера MySQL. Подробности в разделе "13.2 Как заполнять поля в программе администрирования ODBC".
  • Теперь запустите Ваше приложение, и выберите ODBC-драйвер DSN, который Вы определили в администраторе ODBC.

Обратите внимание, что имеются другие опции конфигурации на экране MySQL (trace, don't prompt on connect, etc), которые Вы можете опробовать, если сталкиваетесь с проблемами.

13.2 Как заполнять поля в программе администрирования ODBC

Имеются три возможности для определения имени сервера в Windows95:

  • Использовать IP-адрес сервера.
  • Добавить в файл \windows\lmhosts следующую информацию:
    ip hostname
    Например:
    194.216.84.21 my_hostname
  • Настроить PC для использования DNS.

Пример того, как заполнить поля в ODBC setup:

Windows DSN name:   test
Description:        This is my test database
MySql Database:     test
Server:             194.216.84.21
User:               monty
Password:           my_password
Port:

Значение для поля Windows DSN name: любое имя, которое является уникальным в Вашей Windows ODBC-установке.

Вы не должны определить значения для полей Server, User, Password или Port на экране установки ODBC. Однако, если Вы это сделаете, значения будут использоваться как значения по умолчанию позже, когда Вы попытаетесь сделать соединение. Тогда их можно поменять.

Если номер порта явно не задан, используется заданный по умолчанию порт (3306).

Если Вы определяете опцию Read options from C:\my.cnf, группы client и odbc будут читаться из файла C:\my.cnf.

13.3 Параметры соединения для MyODBC

Можно определять следующие параметры для MyODBC в разделе [Servername] файла ODBC.INI или через аргумент InConnectionString в вызове SQLDriverConnect().

Параметр | Значение по умолчанию | Комментарий
user | ODBC (в Windows) | username используемый, чтобы соединиться с MySQL.
server | localhost | Имя хоста сервера MySQL.
database |  | Заданная по умолчанию база данных
option | 0 | Целое число, которым Вы можете определять, как MyODBC должен работать. Подробности ниже.
port | 3306 | Порт TCP/IP, чтобы использовать, если server не localhost.
stmt |  | Команда, которая будет выполнена при установлении соединения с MySQL.
password |  | Пароль для комбинации параметров server и user.
socket |  | Сокет или именованный канал Windows.

Параметр option используется, чтобы сообщить MyODBC, что клиент не на 100% ODBC-совместим. В Windows обычно устанавливаются опции на экране соединения, но можно также устанавливать это в параметре option. Следующие опции перечислены в том же самом порядке, в каком они появляются на экране соединения MyODBC:

Bit | Назначение
1 | Клиент не может обрабатывать возвращаемую MyODBC реальную ширину столбца.
2 | Клиент не может обрабатывать возвращаемое MySQL истинное значение числа обрабатываемых строк. Если этот флажок установлен MySQL возвращает найденные строки. Нужно иметь MySQL 3.21.14 или более новый, чтобы получить такую поддержку.
4 | Создает файл регистрации отладки c:\myodbc.log. Это аналогично указанию MYSQL_DEBUG=d:t:O,c::\myodbc.log в AUTOEXEC.BAT.
8 | Не устанавливать ограничение пакета для результатов и параметров.
16 | Не запрашивать ничего, даже если драйвер хотел бы что-то запросить.
32 | Моделировать драйвер ODBC 1.0 в некотором контексте.
64 | Игнорировать использование имени базы данных в 'database.table.column'.
128 | Принудительно использовать курсоры менеджера ODBC.
256 | Отключить использование расширенной выборки.
512 | Приводить поля CHAR к полной длине столбца.
1024 | SQLDescribeCol() возвратит полное имя столбца.
2048 | Использовать сжатый протокол сервера/клиента.
4096 | Сообщает, чтобы сервер игнорировал пробел после имени функции и перед '(' (необходимо для работы с PowerBuilder). Эта опция сделает все имена функций ключевыми словами!
8192 | Соединяться с именованными конвейерами с сервером mysqld под NT.
16384 | Изменить столбцы LONGLONG на INT (некоторые приложения не могут обрабатывать LONGLONG).
32768 | Вернуть 'user' как Table_qualifier и Table_owner из вызова SQLTables (экспериментально).
65536 | Читать параметры из групп client и odbc файла настроек my.cnf.
131072 | Добавляет некоторые дополнительные проверки безопасности (обычно не надо, но...).

Если Вы хотите иметь много опций, Вы должны сложить вышеупомянутые флажки. Например, установка option в 12 (4+8) дает Вам отладку без ограничений пакета.

По умолчанию MYODBC.DLL компилируется для оптимальной эффективности. Если Вы хотите отладить MyODBC (например, чтобы включить трассировку), Вы должны взамен использовать MYODBCD.DLL. Чтобы установить этот файл, скопируйте MYODBCD.DLL взамен установленной библиотеки MYODBC.DLL.

13.4 Как сообщать о проблемах с MyODBC

MyODBC был проверен с Access, Admndemo.exe, C++-Builder, Borland Builder 4, Centura Team Developer (прежде это был пакет Gupta SQL/Windows), ColdFusion (на Solaris и NT с svc pack 5), Crystal Reports, DataJunction, Delphi, ERwin, Excel, iHTML, FileMaker Pro, FoxPro, Notes 4.5/4.6, SBSS, Perl DBD-ODBC, Paradox, Powerbuilder, Powerdesigner 32 bit, VC++ и Visual Basic.

Если Вы знаете о любых других приложениях, которые работают с MyODBC, пожалуйста, напишите об этом на myodbc@lists.mysql.com!

С некоторыми программами Вы можете получать ошибку подобно: Another user has modifies the record that you have modified. В большинстве случаев это может быть решено следующим образом:

  • Добавьте первичный ключ для таблицы, если он еще не имеется.
  • Добавьте столбец timestamp, если его еще нет.
  • Используйте только поля double float. Некоторые программы могут терпеть неудачу, когда они сравнивают single float.

13.5 Программы, работающие с MyODBC

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

Программа
Комментарий
Access
Чтобы работать с Access:
  • Если Вы используете Access 2000, Вы должны получить и установить самый новый (version 2.6 или выше) компонент Microsoft MDAC (Microsoft Data Access Components) с адреса http://www.microsoft.com/data. Это устранит следующую ошибку в Access: когда Вы экспортируете данные в MySQL, таблица и названия столбцов не определены. Другой способ обхода этой ошибки в том, чтобы обновить MyODBC до Version 2.50.33 и MySQL до Version 3.23.x, они вместе обеспечивают обход для этой проблемы! Вы должны также получить и применить Microsoft Jet 4.0 Service Pack 5 (SP5), который можно найти на http://support.microsoft.com/support/kb/articles/Q 239/1/14.ASP. Это устранит некоторые случаи, где столбцы отмечены как #deleted# в пакете Access. Обратите внимание, что, если Вы используете MySQL Version 3.22, Вы должны применить заплату MDAC и использовать MyODBC 2.50.32 или 2.50.34.
  • Установите поле опции MyODBC ``Return matching rows'' при соединении с сервером MySQL.
  • Вы должны иметь первичный ключ в таблице. Если его там нет, новые или модифицируемые строки могут быть показаны как #Deleted#.
  • Вы должны иметь timestamp во всех таблицах, которые Вы хотите модифицировать. Для максимальной мобильности рекомендуются TIMESTAMP(14) или простой TIMESTAMP вместо других вариантов на тему TIMESTAMP(X).
  • Используйте поля типа double float. Access терпит неудачу при сравнении с single float. Симптомы: новые или модифицируемые строки могут помечаться как #Deleted#, или Вы не можете находить строки модификаций.
  • Если Вы все еще получаете ошибку Another user has changed your data после добавления столбца TIMESTAMP, следующий прием может помочь Вам: Не используйте просмотр листа данных table. Создайте взамен форму с полями, которые Вы хотите обрабатывать, и используйте эту форму для просмотра в формате form. Вы должны установить реквизит DefaultValue для столбца TIMESTAMP в значение NOW(). Неплохо скрыть столбец TIMESTAMP, чтобы не запутывать Ваших пользователей.
  • Access под NT покажет BLOB-столбцы как OLE OBJECTS. Если Вы хотите взамен иметь столбцы MEMO, Вы должны изменить столбец на TEXT через ALTER TABLE.
  • Access не может всегда правильно обрабатывать столбцы DATE. Если Вы имеете проблему с этим, измените столбцы на DATETIME.
  • В некоторых случаях Access может генерировать запрещенные запросы SQL, которые MySQL не может понимать. Вы можете исправить это выбором "Query|SQLSpecific|Pass-Through" из меню Access.
  • Если Вы имеете в Access столбец, определенный как BYTE, Access попробует экспортировать его как TINYINT вместо TINYINT UNSIGNED. Это задаст Вам проблем, если Вы имеете значения > 127!
  • Если Вы используете Access 7.0, Вы должны использовать флажок Return matching rows.
  • Если Вы используете Access 2.0, Вы должны использовать флажки Return matching rows и Simulate ODBC 1.0.
ADO
Когда Вы программируете с API ADO и MyODBC, Вы должны принять во внимание некоторые заданные по умолчанию реквизиты, которые не обеспечиваются сервером MySQL. Например, использование реквизита CursorLocation Property как adUseServer возвратит для RecordCount Property результат -1. Сомневаюсь, что это входит в Ваши планы... Чтобы иметь правильное значение, Вы должны установить реквизит adUseClient так, как показано в коде на VB ниже:
Dim myconn As New ADODB.Connection
Dim myrs As New Recordset
Dim mySQL As String
Dim myrows As Long

myconn.Open "DSN=MyODBCsample"
mySQL = "SELECT * from user"
myrs.Source = mySQL
Set myrs.ActiveConnection = myconn
myrs.CursorLocation = adUseClient
myrs.Open
myrows = myrs.RecordCount

myrs.Close
myconn.Close
Другой вариант: использовать SELECT COUNT(*) для подобного запроса, чтобы получить правильное число строк.
Active server pages (ASP)
Вы должны использовать опцию Return matching rows.
BDE applications
Вы должны установить опции Don't optimize column widths и Return matching rows.
Borland Builder 4
Когда Вы начинаете запрос, Вы можете использовать реквизит Active или метод Open. Обратите внимание, что Active при запуске автоматически выдает запрос SELECT * FROM ..., который не может быть хорошим, если Ваши таблицы большие!
ColdFusion (под Unix)
Следующая информация поступила из документации на ColdFusion: Используйте следующую информацию, чтобы конфигурировать сервер ColdFusion для Linux, чтобы использовать драйвер unixODBC с MyODBC для источников данных MySQL. MyODBC Version 2.50.26 работает с MySQL Version 3.22.27 и Linux ColdFusion. Любая более новая версия должна также работать. Вы можете скачать MyODBC с http://www.mysql.com/downloads/api-myodbc.html ColdFusion Version 4.5.1 позволяет Вам через ColdFusion Administrator добавить источник данных MySQL. Однако, драйвер не включен в поставку ColdFusion Version 4.5.1. Прежде, чем драйвер MySQL появится в списке ODBC datasources, Вы должны сформировать и скопировать драйвер MyODBC в /opt/coldfusion/lib/libmyodbc.so. Каталог Contrib хранит программу mydsn-xxx.zip, которая позволяет Вам формировать и удалять файл записи DSN для MyODBC драйвера в Coldfusion.
DataJunction
Вы должны изменить таблицу для вывода VARCHAR вместо ENUM, поскольку пакет экспортирует последнее способом, который вызывает разрушение MySQL.
Excel
Работает. Некоторые советы:
  • Если Вы имеете проблемы с датами, попробуйте выбирать их как строки, используя функцию CONCAT(). Например:
    select CONCAT(rise_time), CONCAT(set_time) from sunrise_sunset;
    Значения, найденные как строки, этим способом должны быть правильно распознаны как значения времени Excel97. Цель CONCAT() в этом примере состоит в том, чтобы ввести в заблуждение ODBC, чтобы тот принял столбец за строковый. Без CONCAT() ODBC знает, что столбец имеет тип времени, а Excel этого не понимает. Обратите внимание, что это ошибка в Excel. Она происходит потому, что он автоматически преобразовывает строку во время. Это хорошо, если источником был текстовый файл, но просто глупо, когда источником является ODBC-соединение, которое сообщает точные типы для каждого столбца.
Word
Чтобы получать данные из MySQL в документах Word/Excel, Вы должны использовать драйвер MyODBC и Add-in Microsoft Query help. Например, создайте базу данных с таблицей, содержащей 2 столбца текста:
  • Вставьте строки, используя клиента mysql.
  • Создайте DSN-файл, используя драйвер MyODBC, например, my для db выше.
  • Откройте приложение Word.
  • Создайте пустой новый документ.
  • На полосе инструментов Database, нажмите кнопку insert database.
  • Нажмите кнопку Get Data.
  • На правой стороне экрана Get Data нажмите кнопку Ms Query.
  • В Ms Query создайте New Data Source, используя DSN-файл my.
  • Выберите новый запрос.
  • Выберите столбцы, которые Вы хотите.
  • Сделайте фильтр, если Вы хотите его использовать.
  • Сделайте Sort, если Вы хотите его использовать.
  • Выберите Return Data в Microsoft Word.
  • Нажмите кнопку Finish.
  • Нажмите Insert data и выберите записи.
  • Нажмите OK, и Вы увидите строки в Вашем документе Word.
odbcadmin
Тестовая программа для ODBC.
Delphi
Вы должны использовать BDE Version 3.2 или более новую. Установите поле опции `Don't optimize column width' при соединении с MySQL. Также имеется некоторый потенциально полезный код на Delphi, который устанавливает ODBC и BDE записи для MyODBC (BDE-запись требуется BDE Alias Editor, который свободно выкачивается с Delphi Super Page. (Спасибо за него Bryan Brunton bryan@flesherfab.com):
fReg:= TRegistry.Create;
  fReg.OpenKey('\Software\ODBC\ODBC.INI\DocumentsFab', True);
  fReg.WriteString('Database', 'Documents');
  fReg.WriteString('Description', ' ');
  fReg.WriteString('Driver', 'C:\WINNT\System32\myodbc.dll');
  fReg.WriteString('Flag', '1');
  fReg.WriteString('Password', '');
  fReg.WriteString('Port', ' ');
  fReg.WriteString('Server', 'xmark');
  fReg.WriteString('User', 'winuser');
  fReg.OpenKey('\Software\ODBC\ODBC.INI\ODBC Data Sources', True);
  fReg.WriteString('DocumentsFab', 'MySQL');
  fReg.CloseKey;
  fReg.Free;
  Memo1.Lines.Add('DATABASE NAME=');
  Memo1.Lines.Add('USER NAME=');
  Memo1.Lines.Add('ODBC DSN=DocumentsFab');
  Memo1.Lines.Add('OPEN MODE=READ/WRITE');
  Memo1.Lines.Add('BATCH COUNT=200');
  Memo1.Lines.Add('LANGDRIVER=');
  Memo1.Lines.Add('MAX ROWS=-1');
  Memo1.Lines.Add('SCHEMA CACHE DIR=');
  Memo1.Lines.Add('SCHEMA CACHE SIZE=8');
  Memo1.Lines.Add('SCHEMA CACHE TIME=-1');
  Memo1.Lines.Add('SQLPASSTHRU MODE=SHARED AUTOCOMMIT');
  Memo1.Lines.Add('SQLQRYMODE=');
  Memo1.Lines.Add('ENABLE SCHEMA CACHE=FALSE');
  Memo1.Lines.Add('ENABLE BCD=FALSE');
  Memo1.Lines.Add('ROWSET SIZE=20');
  Memo1.Lines.Add('BLOBS TO CACHE=64');
  Memo1.Lines.Add('BLOB SIZE=32');
  AliasEditor.Add('DocumentsFab','MySQL',Memo1.Lines);
C++ Builder
Проверялось с BDE Version 3.0. Единственая известная проблема состоит в том, что, когда изменяется схема таблицы, поля запроса не модифицируются. BDE, кажется, не распознает первичные ключи, только первичный индекс, хотя это не было проблемой.
Vision
Вы должны установить флажок опций Return matching rows.
Visual Basic
Чтобы модифицировать таблицу, Вы должны определить первичный ключ для таблицы. Visual Basic с ADO не может обрабатывать большие числа типа integer. Это означает, что некоторые запросы, подобно SHOW PROCESSLIST, не будут работать правильно. Устраняется это указанием опции OPTION=16834 в строке соединения ODBC или опции Change BIGINT columns to INT на экране соединения MyODBC. Вы можете также устанавливать Return matching rows.
VisualInterDev
Если Вы получаете ошибку [Microsoft][ODBC Driver Manager] Driver does not support this parameter, причина может быть в том, что Вы имеете BIGINT в Вашем результате. Попробуйте устанавливать опцию Change BIGINT columns to INT на экране соединения MyODBC.
Visual Objects
Вы должны использовать флажок опции Don't optimize column widths .

13.6 Как получать значение столбцов с AUTO_INCREMENT в ODBC

Общая проблема: как получить значение автоматически сгенерированный ID из INSERT. С ODBC Вы можете делать что-нибудь вроде этого (считается, что auto является полем с AUTO_INCREMENT):

INSERT INTO foo (auto,text) VALUES(NULL,'text');
SELECT LAST_INSERT_ID();

Или, если Вы только собираетесь вставлять ID в другую таблицу, Вы можете сделать так:

INSERT INTO foo (auto,text) VALUES(NULL,'text');
INSERT INTO foo2 (id,text) VALUES(LAST_INSERT_ID(),'text');

Для пользы некоторых ODBC-приложений (по крайней мере Delphi и Access), следующий запрос может использоваться, чтобы найти недавно вставленную строку:

SELECT * FROM tbl_name WHERE auto IS NULL;

13.7 Сообщение о проблемах с MyODBC

Если Вы сталкиваетесь с трудностями с MyODBC, Вы должны сделать файл протокола менеджера ODBC (файл регистрации, который Вы получаете при запросе файлов регистрации из ODBCADMIN) и протокол из MyODBC.

Чтобы получить протокол из MyODBC, Вы должны сделать:

  1. Гарантируйте, что Вы используете myodbcd.dll, а не myodbc.dll. Самый простой способ делать это состоит в том, чтобы получить myodbcd.dll из дистрибутива MyODBC и скопировать на место myodbc.dll, которая, вероятно, находится в Вашем каталоге C:\windows\system32 или C:\winnt\system32. Обратите внимание, что Вы, вероятно, захотите восстановить старый файл myodbc.dll, когда закончите тестирование, поскольку он куда быстрее myodbcd.dll.
  2. Отметьте флажок опции `Trace MyODBC' на экране соединения/настройки MyODBC. Протокол будет записан в файл C:\myodbc.log. Если опция трассировки не появилась при обращении к вышеупомянутому экрану, это означает, что Вы не используете драйвер myodbcd.dll.
  3. Запустите приложение и попробуйте смоделировать сбой.

Проверьте MyODBC trace file, чтобы выяснить, что именно могло пойти не так. Вы должны быть способны выяснить выданные запросы, ища после строки >mysql_real_query в файле myodbc.log.

Вы должны также попробовать дублировать запросы в mysql monitor или admndemo, чтобы выяснить, ошибка это MyODBC или MySQL.

Если Вы выясняете, что что-то пошло неправильно, пожалуйста, пошлите только релевантные строки (максимум 36 строк) на адрес myodbc@lists.mysql.com. Пожалуйста, никогда не посылайте целый файл протокола ODBC или MyODBC!

Если Вы неспособны выяснить, что неправильно, последняя опция должна сделать архив (tar или zip), который содержит файл трассировки MyODBC, файл протокола ODBC и файл README, который объясняет проблему. Вы можете посылать это на ftp://support.mysql.com/pub/mysql/secret. Только в MySQL AB имеют доступ к файлам, которые Вы загружаете, и там будут очень аккуратны с данными!

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

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

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


Оптимизация в MySQL

14 Оптимизация в MySQL

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

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

14.1 Обзор оптимизации

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

Наиболее общие узкие места:

  • Дисковый поиск. Это требует времени для диска, чтобы найти часть данных. С современными дисками среднее время для этого обычно ниже, чем 10ms, так что мы можем в теории делать приблизительно 1000 позиционирований. Способ оптимизировать это состоит в том, чтобы распространить данные на несколько дисков, работающих параллельно.
  • Чтение и запись на диск. Когда диск в правильной позиции, мы должны прочитать с него данные. С современными дисками один диск доставляет что-то около 70-80 Mb данных в секунду. Это проще для оптимизации, чем поиск потому, что Вы можете читать параллельно с нескольких дисков.
  • Циклы CPU. Когда мы имеем данные в основной памяти (или если они уже были там), мы должны обработать их, чтобы добраться до нашего результата. Наличие маленьких таблиц, сравнимых по размеру с памятью, наиболее общий фактор ограничения быстродействия системы.
  • Скорость памяти. Когда CPU нужны данные, пропускная способность памяти становится узким местом. Это бывает редко, но лучше всего про него помнить.

14.1.1 Ограничения в MySQL

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

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

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

14.1.2 Мобильность

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

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

Вы можете использовать MySQL программу crash-me/web-page http://www.mysql.com/information/crash-me.php, чтобы найти функции, типы и ограничения, которые Вы можете использовать с выбором сервера базы данных. Crash-me проверяет далеко не все возможное, но тест выполнен для 450 задач.

Например, Вы не должны иметь имена столбцов более длинными, чем 18 символов, если Вы хотите использовать Informix или DB2.

Тесты и программа MySQL crash-me являются очень независимыми от базы данных. Изучение этих программ может помочь Вам в написании своих прикладных программ, независимых от базы данных. Эталонные тесты могут быть найдены в каталоге sql-bench дерева исходников MySQL. Они написаны на Perl с интерфейсом базы данных DBI (который решает проблемы доступа).

Результаты тестов есть на http://www.mysql.com/information/benchmarks.html.

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

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

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

Если Вы используете некоторое специфическое свойство для некоторой базы данных (подобно команде REPLACE в MySQL), Вы должны предусмотреть метод для других серверов SQL, чтобы выполнить то же самое свойство (но медленнее). С MySQL Вы можете использовать синтаксис /*! */, чтобы добавить MySQL-специфические ключевые слова к запросу. Код внутри /**/ будет обрабатываться как комментарий большинством других серверов SQL.

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

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

14.1.3 Для чего использовали MySQL?

Вот что пишут авторы пакета о том, как создавалась эта СУБД:

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

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

Данные огромны (приблизительно 7 миллионов итоговых транзакций в месяц), и мы имеем данные за последние 4-10 лет, которые должны представить пользователям. Мы получили еженедельно запросы от заказчиков, что они хотят иметь мгновенный доступ к новым отчетам из этих данных.

Мы решили это, сохраняя всю информацию за месяц в сжатых таблицах. Мы имеем набор простых макрокоманд (скриптов), который генерирует итоговые таблицы, сгруппированные в соответствии с различными критериями (product group, customer id, store, ...) из таблиц транзакции. Отчеты представляют собой Web-страницы, которые динамически генерируются маленьким скриптом на Perl, который анализирует Web-страницу, выполняет инструкции SQL и вставляет результаты. Мы использовали бы взамен PHP или mod_perl, но они не были доступны в то время.

Для графических данных мы написали на C простой инструмент, который может производить GIF-файлы, основываясь на результате запроса SQL (с некоторой обработкой результата). Это также динамически выполняется из скрипта на Perl, который анализирует HTML-файлы.

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

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

Мы не имели проблем с обработкой данных на Sun Ultra SPARCstation (2x200 Mhz). Недавно был проведен апгрейд до 2 CPU 400 Mhz UltraSPARC, и мы теперь планируем запускать транзакции обработки на уровне изделия товара, что означает десятикратное увеличение данных.

Мы также экспериментируем с Intel-Linux, чтобы быть способными получить большее количество более дешевой мощности CPU. Теперь, когда мы имеем двоичный переносимый формат базы данных (введен в Version 3.23), мы начнем использовать это для некоторых частей прикладной программы.

14.1.4 Пакет тестов MySQL Benchmark Suite

Этот раздел должен содержать техническое описание эталонного набора тестов MySQL и теста crash-me, но пока подробное руководство еще никем не написано (в том числе и авторами пакета). Так что говорить о нем рано. В настоящее время Вы можете получить хорошую помощь относительно эталонного теста, рассматривая код и результаты в каталоге sql-bench дистрибутива исходников MySQL.

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

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

Например, (запуск на машине с NT 4.0):

Чтение 2000000 строк по индексу | Секунд
mysql | 367
mysql_odbc | 464
db2_odbc | 1206
informix_odbc | 121126
ms-sql_odbc | 1634
oracle_odbc | 20800
solid_odbc | 877
sybase_odbc | 17614
Вставка 350768 строк | Секунд
mysql | 381
mysql_odbc | 619
db2_odbc | 3460
informix_odbc | 2692
ms-sql_odbc | 4012
oracle_odbc | 11291
solid_odbc | 1801
sybase_odbc | 4802

В вышеупомянутом тесте MySQL был выполнен с 8M индексным кэшем.

Мы имеем несколько больше эталонных результатов на http://www.mysql.com/information/benchmarks.html.

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

Чтобы выполнить эталонный набор, Вы должны загрузить исходники MySQL, установить драйвер perl DBI для базы данных, которую Вы хотите проверить, и затем отдать команды:

cd sql-bench
perl run-all-tests --server=#

Здесь # задает один из поддержанных серверов. Вы можете получить список всех параметров и поддержанных серверов командой run-all-tests --help .

Тест crash-me может определить, какие свойства база данных поддерживает, и перечень фактических возможностей и ограничений. Например, это определяет:

  • Какие типы столбца поддержаны
  • Сколько индексов поддержано
  • Какие функции доступны
  • Насколько велик может быть запрос
  • Насколько велик может быть столбец типа VARCHAR

Результаты теста crash-me для большого набора разных баз данных можно найти на http://www.mysql.com/information/crash-me.php.

14.1.5 Использование ваших собственных эталонных тестов

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

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

Некоторые проблемы происходят только тогда, когда система очень тяжело загружена. В каждом из этих случаев это обычно проблема с базисным проектом (просмотр таблицы НЕ хорош при высокой загрузке) или есть трудности с OS/Library. Большинство этих случаев было бы НАМНОГО проще исправить, если система еще не запущена в работу.

Чтобы избежать подобных проблем, Вы должны тестировать прикладную программу при самой плохой возможной загрузке! Вы можете использовать для этого Super Smack, который доступен по адресу http://www.mysql.com/Downloads/super-smack/super-smack-1.0.tar.gz.

14.2 Оптимизация SELECT и разных запросов

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

Если Вы не имеете никаких выполненных инструкций GRANT, MySQL оптимизирует проверку разрешений.

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

mysql> select benchmark(1000000,1+1);
+------------------------+
| benchmark(1000000,1+1) |
+------------------------+
|                      0 |
+------------------------+
1 row in set (0.32 sec)

Этот пример показывает, что MySQL может выполнять 1000000 операций сложения (+) за 0.32 секунды на PentiumII 400MHz.

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

14.2.1 Синтаксис EXPLAIN (получение информации о SELECT)

  EXPLAIN tbl_name or
  EXPLAIN SELECT select_options

EXPLAIN tbl_name представляет собой синоним для DESCRIBE tbl_name или SHOW COLUMNS FROM tbl_name.

Когда Вы перед SELECT задаете ключевое слово EXPLAIN, MySQL объясняет, как он обработал бы SELECT, обеспечивая информацию относительно того, как таблицы будут соединены, и в каком порядке.

С помощью EXPLAIN Вы можете видеть, когда Вы должны добавить индексы к таблицам, чтобы получить более быстрый SELECT, который использует индексы, чтобы найти записи. Вы можете также видеть, соединяет ли оптимизатор таблицы в оптимальном порядке. Чтобы вынуждать оптимизатор использовать специфический порядок объединения для инструкции SELECT, добавьте предложение STRAIGHT_JOIN.

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

Вывод из EXPLAIN включает в себя следующие столбцы:

table
Таблица, к которой строка вывода обращается.
type
Тип объединения. Информация относительно различных типов дана ниже.
possible_keys
Столбец possible_keys указывает, какие индексы MySQL мог бы использовать, чтобы найти строки в этой таблице. Обратите внимание, что этот столбец полностью не зависит от порядка таблиц. Это означает, что некоторые из ключей в possible_keys не могут быть пригодны для использования практически со сгенерированным порядком таблицы. Если этот столбец пуст, не имеется никаких релевантных индексов. В этом случае, Вы можете улучшить эффективность Вашего запроса, исследуя предложение WHERE, чтобы увидеть, обращается ли оно к некоторому столбцу или столбцам, которые были бы подходящими для индексации. Если так, создайте соответствующий индекс, и проверьте запрос с помощью EXPLAIN снова. Подробности в разделе "7.4 Синтаксис ALTER TABLE ". Чтобы увидеть, какие индексы таблица имеет, вызовите SHOW INDEX FROM tbl_name.
key
Столбец key указывает ключ, который MySQL фактически решил использовать. Если индекс не выбран, здесь будет NULL. Если MySQL выбирает неправильный индекс, Вы можете вынуждать MySQL использовать другой индекс, используя myisamchk --analyze. Можно применить и USE INDEX/IGNORE INDEX, подробности в разделе "8.1.1 Синтаксис JOIN".
key_len
Столбец key_len указывает длину ключа, который MySQL решил использовать. Длина равна NULL, если key равен NULL. Обратите внимание, что это сообщает нам, сколько частей составного ключа фактически использует MySQL.
ref
Столбец ref показывает, которые столбцы или константы используются с key, чтобы выбрать строки из таблицы.
rows
Столбец rows указывает число строк, которые MySQL должен исследовать, чтобы выполнить запрос.
Extra
Этот столбец содержит дополнительную информацию относительно того, как MySQL решит запрос. Имеется объяснение различных текстовых строк, которые могут быть найдены в этом столбце:
Distinct
MySQL не будет продолжать искать большее количество строк для текущей комбинации строк после того, как найдет первую строку соответствий.
Not exists
MySQL был способен делать оптимизацию LEFT JOIN на запросе и не будет исследовать большее количество строк в этой таблице для предыдущей комбинации строк после того, как найдет одну строку, которая соответствует критериям LEFT JOIN. Имеется пример этого:
SELECT * FROM t1 LEFT JOIN t2 ON t1.id=t2.id WHERE t2.id IS NULL;
Считается, что t2.id определен как NOT NULL. В этом случае MySQL просмотрит t1 и будет искать строки в t2 через t1.id. Если MySQL находит строку соответствий в t2, он знает, что t2.id никогда не может быть NULL, и не будет просматривать остальную часть строк в t2, которые имеют тот же самый идентификатор id. Другими словами, для каждой строки в t1 MySQL должен делать только одиночную поисковую таблицу в t2 независимо от того, сколько соответствий строк находится в t2.
range checked for each record (index map: #)
MySQL не смог найти подходящий индекс для использования. Вместо этого для каждой комбинации строк в обрабатываемых таблицах будет выполняться поиск хорошего индекса для применения (если они есть). Найденный индекс будет использован для получения строк из таблицы. Это не особенно быстро, но все же быстрее, чем объединение без индексов.
Using filesort
MySQL должен сделать дополнительный проход, чтобы выяснить, как получить строки в сортируемом порядке. Сортировка выполнена, проходя все строки согласно типу объединения (join type) и сохраняя ключ сортировки+указатель на строку для всех строк, которые соответствуют WHERE. Затем ключи сортируются. В заключение строки будут получены в сортируемом порядке.
Using index
Информация столбца получена из таблицы с применением только индексного дерева без дополнительного поиска для чтения актуальной строки. Это может быть сделано только, если все столбцы для таблицы являются частью одного и того же индекса.
Using temporary
Чтобы решить запрос, MySQL должен создать временную таблицы для хранения промежуточных результатов вычислений и поиска. Это обычно происходит, если Вы выполнили ORDER BY на наборе столбцов, отличном от того, который был задан в предложении GROUP BY.
Where used
Предложение WHERE будет использоваться, чтобы ограничить то, которые строки будут согласованы для следующей таблицы или посланы пользователю. Если Вы не имеете эту информацию, и таблица имеет тип ALL или index, Вы можете иметь что-то неправильное в Вашем запросе (если Вы не предполагаете выбирать/исследовать все строки из таблицы). Если Вы хотите получать ответы на Ваши запросы с такой скоростью, с какой только возможно, Вы должны рассмотреть применение Using filesort и Using temporary.

Различные типы объединения перечислены ниже в порядке от лучших к худшим:

system
Таблица имеет только одну строку (= system table). Это особый случай объединения типа const.
const
Таблица имеет одну соответствующую строку, которая будет читаться в начале запроса. Потому, что имеется только одна строка, значения из столбца в этой строке могут быть расценены как константы остальной частью оптимизатора. Таблицы const очень быстры, поскольку они доступны для чтения только однажды!
eq_ref
Одна строка будет читаться из этой таблицы для каждой комбинации строк из предыдущих таблиц. Это самый лучший возможный тип объединения, кроме const. Это используется, когда все части индекса применяются объединением, и индекс UNIQUE или PRIMARY KEY.
ref
Все строки с соответствием индексных значений будут читаться из этой таблицы для каждой комбинации строк из предыдущих таблиц. Тип ref используется, если объединение использует только крайний левый префикс ключа, или если ключ не UNIQUE или PRIMARY KEY (другими словами, если объединение не может выбирать одиночную строку, основанную на значении ключа).
range
Только строки, которые находятся в данном диапазоне, будут получены, используя индекс, чтобы выбрать строки. Столбец key указывает, который индекс используется. Столбец key_len содержит самую длинную часть ключа, которая использовалась. Столбец ref для этого типа будет NULL.
index
Аналогично ALL, за исключением того, что только индексное дерево будет просмотрено. Это обычно быстрее, чем ALL, поскольку индексный файл обычно меньше, чем файл данных.
ALL
Полный просмотр таблицы будет выполнен для каждой комбинации строк из предыдущих таблиц. Это обычно не очень хорошо, если таблица является первой таблицей, не маркированной как const, и обычно очень плохо во всех других случаях. Вы обычно можете избежать ALL, добавляя большее количество индексов, так, чтобы строка могла быть найдена, основываясь на постоянных значениях или значениях столбца более ранних таблиц.

Вы можете получать хорошую индикацию относительно того, насколько хорошим является объединение, умножая все значения в столбце rows вывода EXPLAIN. Это должно сообщить Вам грубо, сколько строк MySQL должен исследовать, чтобы выполнить запрос. Это число также используется, когда Вы ограничиваете запросы переменной max_join_size. Подробности в разделе "14.5.2 Настройка параметров сервера".

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

Предположим, что Вы имеете инструкцию SELECT, показанную ниже, и что Вы исследуете ее, используя EXPLAIN:

EXPLAIN SELECT tt.TicketNumber, tt.TimeIn, tt.ProjectReference,
               tt.EstimatedShipDate, tt.ActualShipDate, tt.ClientID,
               tt.ServiceCodes, tt.RepetitiveID, tt.CurrentProcess,
               tt.CurrentDPPerson, tt.RecordVolume, tt.DPPrinted,
               et.COUNTRY, et_1.COUNTRY, do.CUSTNAME
        FROM tt, et, et AS et_1, do WHERE tt.SubmitTime IS NULL
             AND tt.ActualPC = et.EMPLOYID AND tt.AssignedPC=et_1.EMPLOYID
             AND tt.ClientID = do.CUSTNMBR;

Например, предположим, что:

  • Все столбцы, используемые в сравнении, определены:
    Таблица | Столбец | Тип столбца
    tt | ActualPC | CHAR(10)
    tt | AssignedPC | CHAR(10)
    tt | ClientID | CHAR(10)
    et | EMPLOYID | CHAR(15)
    do | CUSTNMBR | CHAR(15)
  • Таблицы имеют индексы, показанные ниже:
    Таблица | Индекс
    tt | ActualPC
    tt | AssignedPC
    tt | ClientID
    et | EMPLOYID (первичный ключ)
    do | CUSTNMBR (первичный ключ)
  • Значения tt.ActualPC распределены неравномерно.

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

table type possible_keys                key  key_len ref  rows  Extra
et    ALL  PRIMARY                      NULL NULL    NULL 74
do    ALL  PRIMARY                      NULL NULL    NULL 2135
et_1  ALL  PRIMARY                      NULL NULL    NULL 74
tt    ALL  AssignedPC,ClientID,ActualPC NULL NULL    NULL 3872
      range checked for each record (key map: 35)

Поскольку type равен ALL для каждой таблицы, этот вывод указывает, что MySQL делает полное объединение для всех таблиц! Это займет очень длительное время, поскольку большое число строк в каждой таблице должно быть исследовано! Для нашего случая это 74*2135*74*3872=45268558720 строк. Если бы таблицы были больше, Вы можете только воображать, как много времени потребуется.

Одна проблема здесь состоит в том, что MySQL не может использовать индексы на столбцах эффективно, если они объявлены по-другому. В этом контексте VARCHAR и CHAR то же самое, если они не объявлены как различные длины. Потому, что tt.ActualPC определен как CHAR(10), а et.EMPLOYID объявлен как CHAR(15), имеется несоответствие длин.

Чтобы исправить это неравенство между длинами столбца, используйте ALTER TABLE, чтобы удлинить ActualPC с 10 до 15:

mysql> ALTER TABLE tt MODIFY ActualPC VARCHAR(15);

Теперь tt.ActualPC и et.EMPLOYID равны VARCHAR(15). Выполнение инструкции EXPLAIN производит этот результат:

table type   possible_keys   key     key_len ref         rows    Extra
tt    ALL    AssignedPC,ClientID,ActualPC NULL NULL NULL 3872    where used
do    ALL    PRIMARY         NULL    NULL    NULL        2135
      range checked for each record (key map: 1)
et_1  ALL    PRIMARY         NULL    NULL    NULL        74
      range checked for each record (key map: 1)
et    eq_ref PRIMARY         PRIMARY 15      tt.ActualPC 1

Это еще не совершенно, но намного лучше. Эта версия выполнена быстрее.

Второе исправление может быть сделано, чтобы устранить несоответствия длин столбцов для сравнений tt.AssignedPC=et_1.EMPLOYID и tt.ClientID=do.CUSTNMBR:

mysql> ALTER TABLE tt MODIFY AssignedPC VARCHAR(15),
                          MODIFY ClientID VARCHAR(15);

Сейчас EXPLAIN выведет следующее:

table type   possible_keys   key     key_len ref            rows     Extra
et    ALL    PRIMARY         NULL    NULL    NULL           74
tt    ref    AssignedPC,ClientID,ActualPC ActualPC 15 et.EMPLOYID 52 where used
et_1  eq_ref PRIMARY         PRIMARY 15      tt.AssignedPC  1
do    eq_ref PRIMARY         PRIMARY 15      tt.ClientID    1

Это почти столь же хорошо, как это возможно вообще. Но все же еще недостаточно хорошо. Продолжим...

Остающаяся проблема состоит в том, что по умолчанию MySQL считает, что значения в столбце tt.ActualPC равномерно распределены, а это не имеет место для таблицы tt. Можно просто сообщить MySQL об этом:

shell> myisamchk --analyze PATH_TO_MYSQL_DATABASE/tt
shell> mysqladmin refresh

Теперь объединение совершенно, и EXPLAIN выведет такой отчет:

table type   possible_keys   key     key_len ref            rows    Extra
tt    ALL    AssignedPC,ClientID,ActualPC NULL NULL NULL    3872    where used
et    eq_ref PRIMARY         PRIMARY 15      tt.ActualPC    1
et_1  eq_ref PRIMARY         PRIMARY 15      tt.AssignedPC  1
do    eq_ref PRIMARY         PRIMARY 15      tt.ClientID    1

Обратите внимание, что столбец rows в выводе EXPLAIN представляет собой обучаемое предположение оптимизатора объединения MySQL. Чтобы оптимизировать запрос, Вы должны проверить, являются ли числа близкими к истине. Если это не так, Вы можете получить лучшую эффективность, используя STRAIGHT_JOIN в Вашей инструкции SELECT и пробуя внести в список таблицы в различном порядке в предложении FROM запроса.

14.2.2 Ожидаемая производительность запросов

В большинстве случаев Вы можете оценивать эффективность, считая дисковые установки. Для маленьких таблиц Вы можете обычно находить строку за одну дисковую установку (поскольку индекс, вероятно, кэшируется). Для больших таблиц Вы можете оценивать (используя индексы дерева B++), что надо log(число строк)/log(длина блока индекса/3*2/(длина индекса+длина указателя данных))+1 установок, чтобы найти строку.

В MySQL блок индекса обычно равен 1024 байтам, а длина указателя данных составляет 4 байта. 500000 строк с индексом длиной в 3 (medium integer) обрабатываются за log(500000)/log(1024/3*2/(3+4))+1=4.

Поскольку вышеупомянутый индекс требовал бы приблизительно 500000*7*3/2=14.2M (считается, что индексные буфера заполнены на 2/3, что является типичным), Вы будете, вероятно, иметь многое из индекса в памяти, и Вы будете, вероятно, нуждаться только в 1-2 обращениях, чтобы читать данные из OS, чтобы найти строку.

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

Обратите внимание, что вышеупомянутое не означает, что Ваша прикладная программа будет требовать сложности N log N! Пока все кэшируется OS или SQL-сервером, работа будет идти только незначительно медленнее в то время, как таблица становится большей. После того, как данные становятся слишком большими, чтобы кэшироваться, работа будет идти намного медленнее, пока Ваши прикладные программы ограничены дисковыми установками (которые растут как N log N). Чтобы избежать этого, увеличьте индексный кэш, поскольку данные растут. Подробности в разделе "14.5.2 Настройка параметров сервера ".

14.2.3 Скорость запросов SELECT

Вообще, когда Вы хотите сделать медленный SELECT ... WHERE быстрее, первое, что подлежит проверке, можете или нет Вы добавить индекс. Подробности в разделе "14.4.3 Как MySQL использует индексы". Все ссылки между различными таблицами должны обычно делаться с индексами. Вы можете использовать команду EXPLAIN, чтобы определить, которые индексы используются для SELECT. Подробности в разделе "14.2.1 Синтаксис EXPLAIN (получение информации о SELECT)". Некоторые общие советы:

  • Чтобы оптимизировать запросы лучше, выполните myisamchk --analyze на таблице после того, как она была загружена релевантными данными. Это модифицирует значение для каждой индексной части, которая указывает среднее число строк, которые имеют то же самое значение. Для уникальных индексов, это всегда 1, конечно. MySQL использует это, чтобы решить, которые индексы выбрать, когда Вы подключаете две таблицы с неконстантным выражением. Вы можете проверять результат из analyze выполнением SHOW INDEX FROM table_name и исследования столбца Cardinality.
  • Чтобы сортировать индекс и данные согласно индексу, используйте myisamchk --sort-index --sort-records=1 (если Вы хотите сортировать на индексе 1). Если Вы имеете уникальный индекс, из которого Вы хотите читать все записи, это хороший способ сделать процесс быстрее. Обратите внимание, однако, что эта сортировка не написана оптимально и будет брать довольно длительное время для большой таблицы!

14.2.4 Как MySQL оптимизирует предложение WHERE

Оптимизация WHERE помещена в часть SELECT потому, что она обычно используется с SELECT, но теми же самыми методами оптимизируются инструкции DELETE и UPDATE.

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

Некоторые из оптимизаций, выполняемых MySQL перечислены ниже:

  • Удаление ненужных круглых скобок:
       ((a AND b) AND c OR (((a AND b) AND (c AND d))))
-> (a AND b AND c) OR (a AND b AND c AND d)
  • Свертывание констант:
       (a<b AND b=c) AND a=5
-> b>5 AND b=c AND a=5
  • Постоянное удаление условия (необходимо из-за свертывания констант):
       (B>=5 AND B=5) OR (B=6 AND 5=5) OR (B=7 AND 5=6)
-> B=5 OR B=6
  • Постоянные выражения, используемые индексами, оценены только однажды.
  • COUNT(*) на одиночной таблице без WHERE получен непосредственно из информации таблицы. Это также выполнено для любого выражения NOT NULL, когда используется только с одной таблицей.
  • Раннее обнаружение недопустимых постоянных выражений. MySQL быстро обнаруживает, что некоторые инструкции SELECT невозможны, и не возвращает никаких строк.
  • HAVING объединено с WHERE, если Вы не используете GROUP BY или групповые функции (COUNT(), MIN()...).
  • Для каждого подобъединения более простой WHERE будет создан, чтобы получить быструю оценку WHERE для каждого подобъединения, а также пропускать все записи как можно скорее.
  • Все постоянные таблицы читаются сначала, перед любыми другими таблицами в запросе. Постоянная таблица:
    • Пустая таблица или таблица с 1 строкой.
    • Таблица, которая используется с предложением WHERE на индексе UNIQUE или PRIMARY KEY, где все индексные части используются с постоянными выражениями и индексными частями, определена как NOT NULL.
    Все следующие таблицы используются как постоянные таблицы:
    mysql> SELECT * FROM t WHERE primary_key=1;
mysql> SELECT * FROM t1,t2
           WHERE t1.primary_key=1 AND t2.primary_key=t1.id;
  • Самая лучшая комбинация объединений, чтобы соединить таблицы будет найдена, пробуя все возможности. Если все столбцы в ORDER BY и в GROUP BY исходят из той же самой таблицы, то эта таблица использована сначала при объединении.
  • Если имеется предложение ORDER BY и отличное от него предложение GROUP BY, или если ORDER BY или GROUP BY содержит столбцы из таблиц, иных, чем первая таблица в очереди объединений, создается временная таблица.
  • Если Вы используете SQL_SMALL_RESULT, MySQL использует временную таблицу в памяти.
  • Каждый индекс таблицы делает запрос, и самый лучший индекс, который охватывает меньшее количество, чем 30% строк, используется. Если никакой такой индекс не может быть найден, применяется быстрый просмотр таблицы.
  • В некоторых случаях MySQL может читать строки из индекса без консультации с файлом данных. Если все столбцы, взятые из индекса, числовые, то только индексное дерево используется, чтобы решить запрос.
  • Прежде, чем каждая запись выводится, те, которые не соответствуют предложению HAVING, будут пропущены.

Некоторые примеры запросов, которые являются очень быстрыми:

mysql> SELECT COUNT(*) FROM tbl_name;
mysql> SELECT MIN(key_part1),MAX(key_part1) FROM tbl_name;
mysql> SELECT MAX(key_part2) FROM tbl_name WHERE key_part_1=constant;
mysql> SELECT ... FROM tbl_name ORDER BY key_part1,key_part2,...
                      LIMIT 10;
mysql> SELECT ... FROM tbl_name ORDER BY key_part1 DESC,key_part2
                      DESC,... LIMIT 10;

Следующие запросы решены, используя только индексное дерево (все индексированные столбцы числовые):

mysql> SELECT key_part1,key_part2 FROM tbl_name WHERE key_part1=val;
mysql> SELECT COUNT(*) FROM tbl_name WHERE key_part1=val1 AND
                  key_part2=val2;
mysql> SELECT key_part2 FROM tbl_name GROUP BY key_part1;

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

mysql> SELECT ... FROM tbl_name ORDER BY key_part1,key_part2,... ;
mysql> SELECT ... FROM tbl_name ORDER BY key_part1 DESC,key_part2
                      DESC,... ;

14.2.5 Как MySQL оптимизирует DISTINCT

DISTINCT преобразован в GROUP BY на всех столбцах, DISTINCT объединенный с ORDER BY тоже будет во многих случаях нуждаться во временной таблице.

При объединении LIMIT # с DISTINCT, MySQL остановится, как только успешно найдет # уникальных строк.

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

SELECT DISTINCT t1.a FROM t1,t2 where t1.a=t2.a;

В этом случае t1 используется прежде t2 (проверьте с помощью EXPLAIN), затем MySQL перестанет читать из t2 (для той специфической строки в t1), когда первая строка в t2 будет найдена.

14.2.6 Как MySQL оптимизирует LEFT JOIN и RIGHT JOIN

Действие A LEFT JOIN B в MySQL выполнено следующим образом:

  • Таблица B установлена, чтобы зависеть от таблицы A, и всех таблиц, которые зависят от A.
  • Таблица установлена A, чтобы зависеть от всех таблиц за исключением B, которые используются в условии LEFT JOIN.
  • Все условия LEFT JOIN перемещаются в WHERE.
  • Все стандартные оптимизации объединения выполнены за исключением того, что таблица всегда читается после всех таблиц, от которых она зависит. Если имеется круговая зависимость, то MySQL выдаст ошибку.
  • Все стандартные оптимизации WHERE выполнены.
  • Если имеется строка в A, которая соответствует предложению WHERE, но не имеется никакой строки в B, которая соответствует условию LEFT JOIN, то дополнительные строки B сгенерированы со всем набором столбцов в NULL.
  • Если Вы используете LEFT JOIN, чтобы найти строки, которые не существуют в некоторой таблице, и Вы имеете следующий тест: column_name IS NULL в части WHERE, где column_name представляет собой столбец, который объявлен как NOT NULL, то MySQL перестанет искать после большего количества строк (для специфической комбинации ключа после того, как найдет одну строку, которая соответствует условию LEFT JOIN).

RIGHT JOIN реализован аналогично LEFT JOIN.

Порядок чтения таблицы, принудительно заданный LEFT JOIN и STRAIGHT JOIN, поможет оптимизатору объединения (который вычисляет, в каком порядке таблицы должны быть соединены) сделать работу намного быстрее, так как имеется меньшее количество перестановок таблицы, которые надо проверить.

Обратите внимание, что вышеупомянутое означает, что, если Вы делаете запрос типа:

SELECT * FROM a,b LEFT JOIN c ON (c.key=a.key) LEFT JOIN d (d.key=a.key)
         WHERE b.key=d.key

MySQL будет делать полный просмотр b, поскольку LEFT JOIN вынудит это читаться прежде, чем d.

Исправление в этом случае должно изменить запрос на:

SELECT * FROM b,a LEFT JOIN c ON (c.key=a.key) LEFT JOIN d (d.key=a.key)
         WHERE b.key=d.key

14.2.7 Как MySQL оптимизирует LIMIT

В некоторых случаях MySQL обработает запрос по-другому, когда Вы используете LIMIT # и не используете HAVING:

  • Если Вы выбираете только несколько строк с LIMIT, MySQL использует индексы в некоторых случаях, когда он обычно предпочел бы сделать полный просмотр таблицы.
  • Если Вы используете LIMIT # в сочетании с ORDER BY, MySQL закончит сортировку, как только найдет первые # строк вместо того, чтобы сортировать целую таблицу.
  • При объединении LIMIT # с DISTINCT MySQL остановится, как только найдет # уникальных строк.
  • В некоторых случаях GROUP BY может быть решено, читая ключ по порядку (или сортируя по ключу) с последующим вычислением результата до изменений значения ключа. В этом случае LIMIT # не будет вычислять никакую ненужную операцию GROUP BY.
  • Как только MySQL послал первые # строк пользователю, он прервет текущий запрос.
  • LIMIT 0 будет всегда быстро возвращать пустой набор. Это полезно, чтобы проверить запрос и получить типы столбцов результата.
  • Размер временных таблиц использует LIMIT #, чтобы вычислить, сколько места необходимо, чтобы решить этот запрос.

14.2.8 Скорость запросов INSERT

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

  • Установление связи: (3)
  • Отправка запроса на сервер: (2)
  • Обработка запроса: (2)
  • Вставка записей: (1 x число записей)
  • Вставка индексов: (1 x количество индексов)
  • Завершение сеанса: (1)

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

Размер таблицы замедляет вставку индексов на N log N (B-деревья).

Некоторые способы ускорить вставки:

  • Если Вы вставляете много строк от того же самого пользователя в то же самое время, используйте многократные инструкции со списком значений INSERT. Это намного быстрее, чем использование отдельных инструкций INSERT. Грамотная настройка переменной myisam_bulk_insert_tree_size может сделать это даже быстрее. Подробности в разделе "4.10.4 SHOW VARIABLES".
  • Если Вы вставляете много строк из различных клиентов, Вы можете получить большее быстродействие, используя инструкцию INSERT DELAYED. Подробности в разделе "8.3 Синтаксис INSERT".
  • Обратите внимание, что с MyISAM Вы можете вставлять строки в то же самое время, когда работает SELECT, если не имеется никаких удаленных строк в таблицах.
  • При загрузке таблицы из текстового файла применяется LOAD DATA INFILE. Это примерно в 20 раз быстрее, чем использование набора команд INSERT. Подробности в разделе "8.9 Синтаксис LOAD DATA INFILE ".
  • Есть способ еще более ускорить LOAD DATA INFILE, когда таблица имеет много индексов. Используйте следующую процедуру:
    1. Факультативно создайте таблицу с помощью CREATE TABLE. Например, при использовании mysql или Perl-DBI.
    2. Выполните инструкцию FLUSH TABLES или команду оболочки mysqladmin flush-tables.
    3. Используйте myisamchk --keys-used=0 -rq /path/to/db/tbl_name. Это удалит все применяемые индексы из таблицы.
    4. Вставьте данные в таблицу с помощью вызова LOAD DATA INFILE. Это не будет модифицировать никакие индексы вообще и, следовательно, будет работать очень быстро.
    5. Если Вы собираетесь только читать таблицу в будущем, выполните myisampack, чтобы сделать ее еще меньше.
    6. Освежите индексы с помощью myisamchk -r -q /path/to/db/tbl_name. Это создаст индексное дерево в памяти перед записью его на диск, что является намного быстрее потому, что это избегает большого количества дисковых установок. Возникающее в результате индексное дерево также совершенно сбалансировано.
    7. Выполните инструкцию FLUSH TABLES или команду оболочки mysqladmin flush-tables.
    Эта процедура будет встроена в LOAD DATA INFILE в некоторой будущей версии MySQL. Начиная с MySQL 4.0, Вы также можете использовать ALTER TABLE tbl_name DISABLE KEYS вместо myisamchk --keys-used=0 -rq /path/to/db/tbl_name и ALTER TABLE tbl_name ENABLE KEYS вместо myisamchk -r -q /path/to/db/tbl_name. Этим путем Вы также можете обойти шаг FLUSH TABLES.
  • Вы можете ускорить вставки, блокируя Ваши таблицы:
    mysql> LOCK TABLES a WRITE;
mysql> INSERT INTO a VALUES (1,23),(2,34),(4,33);
mysql> INSERT INTO a VALUES (8,26),(6,29);
mysql> UNLOCK TABLES;
    Основное различие в быстродействии в том, что буфер индексов сбрасывают на диск только однажды после того, как все инструкции INSERT завершили. Обычно имелось бы так много индексных буферных потоков, сколько есть различных инструкций INSERT. Блокировка не является необходимой, если Вы можете вставлять все строки с одиночной инструкцией. Блокировка будет также снижать общее время тестов с несколькими подключениями, но максимальное время ожидания для некоторых потоков повысится (потому, что они ждут блокировки). Например:
    thread 1 does 1000 inserts
thread 2, 3, and 4 does 1 insert
thread 5 does 1000 inserts
    Если Вы не используете блокировку, 2, 3 и 4 закончаться перед 1 и 14. Если Вы используете блокировку, 2, 3 и 4, вероятно, не будут заканчиваться прежде, чем 1 или 5, но общее время должно быть приблизительно на 40% лучше. Так как операции INSERT, UPDATE и DELETE очень быстры в MySQL, Вы получите лучшую полную эффективность, добавляя блокировки вокруг всего, что делает больше, чем приблизительно 5 вставок или модификаций в строке. Если Вы делаете очень много вставок в строке, Вы могли бы делать LOCK TABLES, сопровождаемые UNLOCK TABLES время от времени (примерно каждые 1000 строк), чтобы позволить другим потокам доступ к таблице. Конечно же, LOAD DATA INFILE все равно намного быстрее для загрузки данных.

Чтобы дополнительно получить несколько большее быстродействие для операций LOAD DATA INFILE и INSERT, увеличьте буфер ключа. Подробности в разделе "14.5.2 Настройка параметров сервера".

14.2.9 Скорость запросов UPDATE

Запросы модификации оптимизированы как запрос SELECT. Быстродействие дополнительной записи зависит от размера данных, которые изменяются, и числа индексов, в которые вносятся поправки. Индексы, которые не изменены, не будет модифицироваться.

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

Обратите внимание, что, при работе с динамическим форматом записи модификация записи на более длинную может привести к разделению ее на фрагменты. Так что, если Вы делаете это часто, очень важно иногда вызывать OPTIMIZE TABLE. Подробности в разделе "4.6 Синтаксис OPTIMIZE TABLE ".

14.2.10 Скорость запросов DELETE

Если надо удалить все строки из таблицы, примените вызов TRUNCATE TABLE table_name. Подробности в разделе "8.7 Синтаксис TRUNCATE".

Время, нужное, чтобы удалить запись, точно пропорционально числу индексов. Чтобы удалять записи быстрее, Вы можете увеличивать размер индексного кэша. Подробности в разделе "14.5.2 Настройка параметров сервера".

14.2.11 Другие советы по оптимизации

  • Используйте постоянные подключения к базе данных, чтобы избежать накладных расходов на текущие подключения. Если Вы не можете использовать постоянные подключения, и Вы делаете много новых подключений, стоит изменить значение переменной thread_cache_size. Подробности в разделе "14.5.2 Настройка параметров сервера ".
  • Обязательно проверьте, что все Ваши запросы в самом деле используют индексы, которые Вы создали в таблицах. В MySQL Вы можете сделать это командой EXPLAIN. Подробности в разделе "14.2.1 Синтаксис EXPLAIN (получение информации о SELECT)".
  • Избегайте сложных запросов SELECT на таблицах, которые часто модифицируются. Это должно помочь избежать проблем с блокировкой таблицы.
  • Новые таблицы MyISAM могут вставлять строки в таблицу без удаленных строк в то же самое время, когда другой запрос ведет чтение. Если это важно для Вас, Вы должны рассмотреть методы, где Вы не должны удалить строки или выполните OPTIMIZE TABLE после того, как Вы удалили много строк сразу.
  • Используйте вызов ALTER TABLE ... ORDER BY expr1,expr2... если Вы обычно получаете строки в порядке expr1,expr2,... . Используя эту опцию после внесения больших изменений для таблицы, Вы можете получить значительно более высокую эффективность.
  • В некоторых случаях может иметь смысл представлять столбец, который является хэшем, основанным на информации из других столбцов. Если этот столбец короткий и приемлемо уникальный, это может быть намного быстрее, чем большой индекс на многих столбцах. В MySQL это очень легко в использовании: SELECT * FROM table_name WHERE hash=MD5(concat(col1,col2)) AND col_1='constant' AND col_2='constant'
  • Для таблиц, которые часто изменяются, Вы должен пробовать избежать любых столбцов типов VARCHAR или BLOB. Вы получите динамическую длину строки, как только Вы используете хоть один стобец VARCHAR или BLOB.
  • Если Вы очень часто должны вычислять значения, основанные на информации из большого количества строк (подобно количеству), вероятно, намного лучше представить новую таблицу и модифицировать счетчик в реальном времени. Модификация типа UPDATE table set count=count+1 where index_column=constant очень быстрая! Это действительно важно, когда Вы используете базы данных подобные MySQL, которые имеют только блокировку уровня таблицы. Это также даст лучшую эффективность с большинством баз данных, поскольку администратор блокировки строки в этом случае будет иметь куда меньше работы.
  • Если Вы должны собрать статистику из больших таблиц файла регистрации, используйте итоговые таблицы вместо того, чтобы просмотреть целую таблицу. Поддержание резюме должно быть намного быстрее, чем попытка сделать живую статистику. Намного быстрее получить новые итоговые таблицы из файлов регистрации, когда происходит изменение, чем менять работающее приложение!
  • Если возможно, нужно классифицировать отчеты как "живые" или "статистические", где данные, необходимые для статистических отчетов, сгенерированы только, исходя из итоговых таблиц, которые в свою очередь были сгенерированы из фактических данных.
  • Воспользуйтесь преимуществом того факта, что столбцы имеют значения по умолчанию. Вставляйте значения явно только, когда значение, которое будет вставлено, отличается от значения по умолчанию. Это уменьшает синтаксический анализ, который MySQL должен сделать, и улучшает быстродействие вставки.
  • В некоторых случаях удобно упаковывать и сохранить данные в blob. В этом случае Вы должны добавить некоторый дополнительный код к Вашей прикладной программе, чтобы упаковать/распаковать данные, но это может сохранить много времени доступа в некоторой стадии. Это удобно, когда Вы имеете данные, которые явно не соответствуют статической структуре таблицы.
  • Обычно Вы должны пробовать хранить все данные неизбыточными (что названо третьей нормальной формой в теории базы данных), но Вы не должны бояться дублирования или создания таблиц-резюме, если Вы нуждаетесь в них, чтобы получить большее быстродействие.
  • Сохраненные процедуры или UDF (определяемой пользователем функции) может быть хорошим способом получить большую эффективность. В этом случае Вы должны, однако, всегда иметь способ делать это некоторым другим (более медленным) путем, если Вы используете СУБД, которая не поддерживает это.
  • Вы можете всегда получать неплохие результаты, кэшируя запросы/ответы в Вашей прикладной программе и пробуя делать много вставок/модификаций в то же самое время. Если Ваша база данных поддерживает блокировки таблиц (подобно MySQL и Oracle), это должно помочь гарантировать, что индексный кэш сбрасывается только однажды после выполнения всех модификаций.
  • Используйте INSERT /*! DELAYED */, если Вы не должны знать, когда Ваши данные будут записаны. Это ускоряет дела потому, что много записей могут быть выполнены за один дисковый обмен.
  • Используйте INSERT /*! LOW_PRIORITY */, когда Вы хотите, чтобы Ваши вызовы select были более важными.
  • Используйте SELECT /*! HIGH_PRIORITY */, чтобы получить select, обходящий очередь. То есть select будет выполнен, даже если имеется кто-то ждущий, чтобы сделать запись в таблицу.
  • Используйте многострочную инструкцию INSERT, чтобы сохранить много строк одной командой SQL (многие серверы SQL поддерживают это).
  • Используйте LOAD DATA INFILE, чтобы загрузить большие количества данных. Это быстрее, чем нормальные вставки, а будет еще быстрее, когда myisamchk интегрирован в mysqld.
  • Используйте столбцы с поддержкой AUTO_INCREMENT, чтобы сделать уникальные значения.
  • Используйте OPTIMIZE TABLE время от времени, чтобы избежать фрагментации при использовании динамического формата таблицы. Подробности в разделе "4.6 Синтаксис OPTIMIZE TABLE".
  • При использовании нормальной установки Web-сервера, изображения должны быть сохранены как файлы. То есть сохраните только ссылку на файл в базе данных. Основная причина для этого в том, что нормальный Web-сервер намного лучше при кэшировании файлов, чем содержание базы данных. Так что намного проще получить быструю систему, если Вы используете файлы.
  • Используйте таблицы в памяти для некритических данных, к которым обращаются часто (подобно информации относительно последнего показанного баннера для пользователей, которые не имеют cookie).
  • Столбцы с идентичной информацией в различных таблицах должны быть объявлены идентично и иметь одинаковые имена. До Version 3.23 Вы получали медленные объединения в противном случае. Старайтесь делать имена проще (например, name вместо customer_name в таблице заказчиков). Чтобы сделать Ваши имена переносными на другие SQL-серверы, Вы должны озаботиться тем, чтобы они не превышали в длину 18 символов.
  • Если Вы нуждаетесь в ДЕЙСТВИТЕЛЬНО высокой скорости, Вы должны смотреть на интерфейсы низкого уровня для хранения данных, которые поддерживают различные серверы SQL! Например, обращаясь к MySQL MyISAM непосредственно, Вы могли бы получить увеличение быстродействия в 2-5 раз в сравнении с использованием интерфейса SQL. Чтобы сделать это, данные должны быть на том же самом сервере, что и прикладная программа, и обычно к ним можно обратиться только одним процессом (потому, что внешняя блокировка файла работает очень медленно). Можно было устранить вышеупомянутые проблемы, представляя команды MyISAM низкого уровня в сервере MySQL (это могло бы быть одним простым способом получить большее количество эффективности, если необходимо).
  • Во многих случаях быстрее обратиться к данным из базы данных (используя открытое подключение), чем к текстовому файлу только потому, что база данных, вероятно, будет более компактна, чем текстовый файл (если Вы используете числовые данные), и это потребует меньшее количество дисковых доступов. Вы также уменьшите код потому, что Вы не должны анализировать Ваши текстовые файлы, чтобы найти в них границы столбца и строки.
  • Объявление таблицы с DELAY_KEY_WRITE=1 будет делать модифицирование индексов быстрее, поскольку они не регистрируются на диске, пока файл не закрыт. Обратная сторона в том, что Вы должны выполнить myisamchk на этих таблицах прежде, чем Вы запускаете mysqld, чтобы гарантировать, что они правильные, если что-то уничтожило mysqld в середине запроса. Поскольку информация ключа может всегда генерироваться из данных, Вы не должны терять что-нибудь, используя DELAY_KEY_WRITE.

14.3 Проблемы блокировки

14.3.1 Как MySQL блокирует таблицы

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

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

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

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

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

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

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

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

Это может быть выполнено кодом:

mysql> LOCK TABLES real_table WRITE, insert_table WRITE;
mysql> insert into real_table select * from insert_table;
mysql> TRUNCATE TABLE insert_table;
mysql> UNLOCK TABLES;

Вы можете использовать параметр LOW_PRIORITY с инструкциями INSERT, UPDATE или DELETE, а HIGH_PRIORITY только с SELECT, если Вы хотите располагать по приоритетам поиск в некоторых специфических случаях. Вы можете также запустить mysqld с параметром --low-priority-updates, чтобы получить тот же самое поведение.

Использование SQL_BUFFER_RESULT может также сделать блокировку таблицы короче. Подробности в разделе "8.1 Синтаксис SELECT".

Вы могли бы также изменять код блокировки в mysys/thr_lock.c, чтобы использовать одиночную очередь. В этом случае блокировки записи и чтения имели бы тот же самый приоритет, что может помочь некоторым программам.

14.3.2 Советы по блокировке таблицы

Код блокировки таблиц в MySQL свободен от тупиков.

MySQL использует блокировку таблицы (вместо блокировки строки или столбца) на всех типах таблицы, за исключением BDB, чтобы достичь очень высокого быстродействия блокировки. Для больших таблиц блокировка таблицы НАМНОГО лучше, чем блокировка строки для большинства прикладных программ, но имеются, конечно, некоторые ловушки.

Для таблиц типов BDB и InnoDB MySQL использует блокировку таблицы только, если Вы скомандовали LOCK TABLES или выполняете команду, которая изменит каждую строку в таблице подобно ALTER TABLE. Для этих типов таблицы я рекомендую Вам не использовать LOCK TABLES вообще.

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

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

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

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

Блокировка таблицы, однако, не очень хороша в следующих случаях:

  • Пользователь выдает SELECT, который берет длительное время, чтобы выполниться.
  • Другой пользователь затем выдает UPDATE на используемой таблице. Этот клиент будет ждать, пока SELECT не закончится.
  • Другой пользователь выдает другую инструкцию SELECT относительно той же самой таблицы. Поскольку UPDATE имеет более высокий приоритет, чем SELECT, этот SELECT будет ждать UPDATE, чтобы закончиться. Это будет также ждать, когда закончится первый SELECT!
  • Поток ждет нечто подобное full disk, когда все потоки, которые хотят обращаться к прикладной таблице, будут также помещены в состояние ожидания до тех пор, пока большее количество дискового пространства не станет доступно.

Некоторые решения для этой проблемы:

  • Попытайтесь получить ускорение инструкции SELECT. Вам, вероятно, придется создавать некоторые итоговые таблицы, чтобы сделать это.
  • Запустите mysqld с опцией --low-priority-updates. Это даст всем инструкциям, которые модифицируют таблицу, более низкий приоритет, чем инструкции SELECT. В этом случае последняя инструкция SELECT в предыдущем сценарии выполнилась бы перед инструкцией INSERT.
  • Вы можете давать специфическую инструкцию INSERT, UPDATE или DELETE с более низким приоритетом, указав атрибут LOW_PRIORITY.
  • Запустите mysqld с низким значением для max_write_lock_count, чтобы дать блокировки READ после того, как отработает некоторое число блокировок WRITE.
  • Вы можете определить, что все модификации из специфического потока должны быть выполнены с низким приоритетом, используя команду SQL: SET SQL_LOW_PRIORITY_UPDATES=1. Подробности в разделе "14.5.6 Синтаксис SET".
  • Вы можете определять, что специфический SELECT очень важен с помощью атрибута HIGH_PRIORITY. Подробности в разделе "8.1 Синтаксис SELECT".
  • Если Вы имеете проблемы с INSERT, объединенной с SELECT, переключитесь, чтобы использовать новые таблицы типа MyISAM, поскольку они поддерживают параллельную работу вызовов SELECT и INSERT.
  • Если Вы главным образом смешиваете инструкции INSERT и SELECT, атрибут DELAYED в вызове INSERT, вероятно, решит Ваши проблемы. Подробности в разделе "8.3 Синтаксис INSERT".
  • Если Вы имеете проблемы с SELECT и DELETE, опция LIMIT в инструкции DELETE может помочь. Подробности в разделе "8.6 Синтаксис DELETE".

14.4 Оптимизация структуры базы данных

14.4.1 Выбор дизайна и интерьера

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

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

Более общий случай: индекс и данные сохранены вместе (подобно Oracle/Sybase). В этом случае Вы найдете информацию строк в листе страниц индекса. Хорошо с этим размещением то, что во многих случаях, в зависимости от того, как хорошо индекс кэшируется, экономится медленное дисковое чтение. Плохо с этим размещением то, что:

  • Просмотр таблицы намного медленнее потому, что Вы должны пролистать индексы, чтобы добраться до данных.
  • Вы не можете использовать только индексную таблицу, чтобы получить данные для решения запроса.
  • Вы теряете много места, поскольку Вы должны дублировать индексы из узлов (поскольку Вы не можете сохранять строку в узлах).
  • Удаление будет вырождать таблицу через какое-то время (поскольку индексы в узлах обычно не модифицируются на запросах удаления).
  • Тяжелее кэшировать ТОЛЬКО индексные данные.

14.4.2 Сделайте данные как можно меньше

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

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

Вы можете получать лучшую эффективность на таблице и минимизировать "складские площади" на диске, используя методы, перечисленные ниже:

  • Используйте наиболее эффективные (самые маленькие) возможные типы. MySQL имеет много разных специализированных типов, которые сохраняют дисковое пространство и память.
  • Используйте меньшие целочисленные типы, если возможно, чтобы получить меньшие таблицы. Например, MEDIUMINT часто бывает куда лучше, чем INT в чистом виде.
  • Объявите столбцы как NOT NULL, если это возможно. Это сделает все быстрее, и Вы сэкономите один бит на столбец. Обратите внимание, что, если Вы действительно нуждаетесь в NULL в Вашей прикладной программе, Вы должны определенно использовать это. Только не стоит иметь это свойство заданным на всех столбцах по умолчанию.
  • Если Вы не имеете столбцов переменной длины (VARCHAR, TEXT или BLOB), используется формат записи фиксированного размера. Это работает быстрее, но, к сожалению, может тратить впустую некоторое место.
  • Первичный индекс таблицы должен быть так короток, как только возможно. Это делает идентификацию одной строки простой и эффективной.
  • Для каждой таблицы Вы должны решить, который метод хранения и индексации надлежит в ней использовать.
  • Создайте только те индексы, в которых Вы действительно нуждаетесь. Индексы хороши для поиска, но плохи, когда Вы должны сохранить что-то быстро. Если Вы обычно обращаетесь к таблице, используя поиск на комбинации столбцов, сделайте индекс на них. Первая индексная часть должна быть наиболее используемым столбцом. Если Вы ВСЕГДА используете много столбцов, Вы должны применить столбец с большим количеством дубликатов первым, чтобы получить лучшее сжатие индекса.
  • Если вероятно, что столбец имеет уникальный префикс на некотором числе первых символов, лучше индексировать только этот префикс. MySQL поддерживает индекс на части символьного столбца. Короткие индексы быстрее не только потому, что они берут меньшее количество дискового пространства, но также и потому, что они дадут Вам большее количество попаданий в индексный кэш и таким образом меньшее количество дисковых установок. Подробности в разделе "14.5.2 Настройка параметров сервера ".
  • В некоторых обстоятельствах таблицу, которая бывает просмотрена очень часто, может быть полезно расчленить на две. Это особенно верно, если это таблица динамического формата, и можно использовать меньшую таблицу статического формата, которая может применяться, чтобы найти релевантные строки при просмотре этой таблицы.

14.4.3 Как MySQL использует индексы

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

Все индексы в MySQL (PRIMARY, UNIQUE и INDEX) сохранены в B-деревьях. Строки автоматически сжимаются с использованием конечных пробелов и префикса. Подробности в разделе "7.7 Синтаксис CREATE INDEX ".

Индексы используются для:

  • Быстрого поиска строк, которые соответствуют предложению WHERE.
  • Получения строк из других таблиц при выполнении объединений.
  • Поиска значений MAX() или MIN() для специфического индексированного столбца. Это оптимизировано препроцессором, который проверяет, используете ли Вы WHERE key_part_#=constant на всех частях ключа <N. В этом случае MySQL будет делать одиночный поиск ключа и заменит MIN() выражением с константой. Если все выражения заменятся на константы, запрос возвратится сразу:
    SELECT MIN(key_part2),MAX(key_part2) FROM table_name where key_part1=10
  • Сортировки или группировки таблиц, если сортировка или группировка выполнена на крайнем левом префиксе пригодного для использования ключа (например, ORDER BY key_part_1,key_part_2). Ключ читается в обратном порядке, если все части ключа сопровождаются словом DESC. Индекс может также использоваться, даже если ORDER BY не соответствует индексу точно, пока все неиспользуемые индексные части и все дополнительные столбцы в ORDER BY представляют собой константы в предложении WHERE. Следующие запросы используют индекс, чтобы решить часть ORDER BY:
    SELECT * FROM foo ORDER BY key_part1,key_part2,key_part3;
SELECT * FROM foo WHERE column=constant ORDER BY column, key_part1;
SELECT * FROM foo WHERE key_part1=const GROUP BY key_part2;
  • В некоторых случаях запрос может быть оптимизирован, чтобы получить значения без того, чтобы консультироваться с файлом данных. Если все используемые столбцы для некоторой таблицы числовые и формируют крайний левый префикс для некоторого ключа, значения могут быть получены прямо из индексного дерева для большего быстродействия:
    SELECT key_part3 FROM table_name WHERE key_part1=1

Предположим, что Вы выдаете следующую инструкцию SELECT:

mysql> SELECT * FROM tbl_name WHERE col1=val1 AND col2=val2;

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

Если таблица имеет многостолбиковый индекс, любой крайний левый префикс индекса может использоваться оптимизатором, чтобы найти строки. Например, если Вы имеете индекс с тремя столбцами на (col1,col2,col3), Вы индексировали возможности поиска на (col1), (col1,col2) и (col1,col2,col3).

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

mysql> SELECT * FROM tbl_name WHERE col1=val1;
mysql> SELECT * FROM tbl_name WHERE col2=val2;
mysql> SELECT * FROM tbl_name WHERE col2=val2 AND col3=val3;

Если индекс существует на (col1,col2,col3), только первый запрос, показанный выше, использует индекс. Второй и третий запросы включают индексированные столбцы, но (col2) и (col2,col3) не крайние левые префиксы для (col1,col2,col3).

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

mysql> select * from tbl_name where key_col LIKE "Patrick%";
mysql> select * from tbl_name where key_col LIKE "Pat%_ck%";

В первой инструкции только строки с "Patrick" <=key_col < "Patricl" рассматриваются. Во второй инструкции будут обработаны только строки с "Pat" <=key_col < "Pau".

Следующие инструкции SELECT не будут использовать индексы:

mysql> select * from tbl_name where key_col LIKE "%Patrick%";
mysql> select * from tbl_name where key_col LIKE other_col;

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

Поиск, использующий column_name IS NULL, применяет индексы, если column_name представляет собой индекс.

MySQL обычно использует индекс, который находит наименьшее число строк. Индекс используется для столбцов, которые Вы сравниваете следующими операторами: =, >, >=, <, <=, BETWEEN и LIKE с префиксом, представляющим собой не групповой символ, например, допустимо something%.

Любой индекс, который не охватывает все уровни AND в предложении WHERE, не используется, чтобы оптимизировать запрос. Другими словами: чтобы быть способным использовать индекс, префикс индекса должен использоваться в каждом AND в группе.

Следующие предложения WHERE используют индексы:

... WHERE index_part1=1 AND index_part2=2 AND other_column=3
... WHERE index=1 OR A=10 AND index=2      /* index = 1 OR index = 2 */
... WHERE index_part1='hello' AND index_part_3=5
          /* optimized like "index_part1='hello'" */
... WHERE index1=1 and index2=2 or index1=3 and index3=3;
          /* Can use index on index1 but not on index2 or index 3 */

Эти предложения WHERE НЕ используют индексы:

... WHERE index_part2=1 AND index_part3=2  /* index_part_1 is not used */
... WHERE index=1 OR A=10                  /* Index is not used in both AND parts */
... WHERE index_part1=1 OR index_part2=10  /* No index spans all rows */

Обратите внимание, что в некоторых случаях MySQL все равно не будет использовать индекс, даже если можно было бы это сделать. Это связано с особенностями логики СУБД. Некоторые из таких случаев:

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

14.4.4 Индексы столбцов

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

Максимальное число ключей и максимальная длина индекса определены в драйвере таблицы. Вы можете со всеми драйверами таблицы иметь по крайней мере 16 ключей и общую индексную длину по крайней мере в 256 байт.

Для столбцов типов CHAR и VARCHAR Вы можете индексировать префикс столбца. Это намного быстрее и требует меньшего количества дискового пространства, чем индексация целого столбца. Синтаксис, который надо использовать в инструкции CREATE TABLE, чтобы индексировать префикс для столбца, выглядит следующим образом:

KEY index_name (col_name(length))

Пример ниже создает индекс первых 10 символов столбца name:

mysql> CREATE TABLE test (name CHAR(200) NOT NULL,
                              KEY index_name (name(10)));

Для столбцов BLOB и TEXT Вы должны индексировать именно префикс столбца. Там Вы не можете индексировать весь столбец.

В MySQL Version 3.23.23 или позже Вы можете также создавать специальные индексы FULLTEXT. Они используются для полнотекстового поиска. Только тип таблицы MyISAM поддерживает индексы FULLTEXT. Они могут быть созданы только из столбцов VARCHAR и TEXT. Индексация всегда выполняется над всем столбцом, частичная индексация пока не поддержана. Подробности в разделе "9.4 Полнотекстовый поиск в MySQL".

14.4.5 Многостолбцовые индексы

MySQL может создавать индексы на нескольких столбцах. Индекс может включать до 15 столбцов. На столбцах типов CHAR и VARCHAR Вы можете использовать префикс столбца как часть индекса.

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

Предположим, что таблица создана, используя следующую спецификацию:

mysql> CREATE TABLE test (id INT NOT NULL, last_name CHAR(30) NOT NULL,
           first_name CHAR(30) NOT NULL, PRIMARY KEY (id),
           INDEX name (last_name,first_name));

Индекс name охватывает столбцы last_name и first_name. Индекс будет использоваться для запросов, которые определяют значения в известном диапазоне для last_name или для last_name и first_name вместе. Следовательно, индекс name будет использоваться для следующих запросов:

mysql> SELECT * FROM test WHERE last_name="Widenius";
mysql> SELECT * FROM test WHERE last_name="Widenius"
                  AND first_name="Michael";
mysql> SELECT * FROM test WHERE last_name="Widenius"
                  AND (first_name="Michael" OR first_name="Monty");
mysql> SELECT * FROM test WHERE last_name="Widenius"
                  AND first_name >="M" AND first_name < "N";

Однако, индекс name НЕ будет использоваться в запросах:

mysql> SELECT * FROM test WHERE first_name="Michael";
mysql> SELECT * FROM test WHERE last_name="Widenius" OR
                    first_name="Michael";

За подробностями по улучшению работы с индексами в MySQL отсылаю Вас к разделу "14.4.3 Как MySQL использует индексы".

14.4.6 Как MySQL открывает и закрывает таблицы

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

Переменная table_cache связана с max_connections. Например, для 200 параллельных подключений, Вы должны иметь кэш таблицы по крайней мере 200*n, где n максимальное число таблиц в объединении. Вы также должны резервировать некоторые описатели файла дополнительно для временных таблиц и файлов.

Кэш открытых таблиц может расти до максимума, заданного table_cache (значение по умолчанию 64, это может быть изменено с помощью опции -O table_cache=# при вызове сервера mysqld). Таблица никогда не будет закрыта за исключением того случая, когда кэш заполняется, а другой поток пробует открыть таблицу, или если Вы используете команду mysqladmin refresh или mysqladmin flush-tables.

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

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

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

Вы можете проверять, является ли Ваш кэш таблицы слишком маленьким, проверяя переменную opened_tables в mysqld. Если это значение очень большое, даже если Вы не делали много вызовов FLUSH TABLES, Вы должны увеличить Ваш кэш таблицы. Подробности в разделе "4.10.3 SHOW STATUS ".

14.4.7 Проблемы с созданием большого количества таблиц в базе данных

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

14.4.8 Почему так много открытых таблиц?

Когда Вы выполняете mysqladmin status, Вы будете видеть нечто вроде этого вывода:

Uptime: 426 Running threads: 1 Questions: 11082 Reloads: 1 Open tables: 12

Это может несколько озадачить, если Вы имеете только 6 таблиц.

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

14.5 Оптимизация сервера MySQL

14.5.1 Настройка параметров компиляции и запуска

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

Используемая OS очень важна! Чтобы с толком использовать многопроцессорные системы, нужно применять Solaris (потому, что потоки там работают очень хорошо) или Linux (потому, что ядро 2.2 имеет очень приличную поддержку SMP). Также на 32-разрядных машинах Linux имеет ограничение в 2G для размера файла по умолчанию. Но это исправлено в файловых системах XFS/Reiserfs. Если Вы имеете потребность в файлах больше, чем 2G, на Linux-intel 32 bit, Вы должны получить заплату LFS для файловой системы ext2.

Другие советы и предупреждения:

  • Если Вы имеете достаточно RAM, Вы могли бы удалить все свопы. Некоторые операционные системы используют своп в некоторых контекстах, даже если Вы имеете свободную память.
  • Используйте опцию --skip-locking в MySQL, чтобы избежать внешней блокировки. Обратите внимание, что это не будет воздействовать на функциональные возможности MySQL, пока Вы выполняете только один сервер. Только не забудьте завершить сервер (или блокировать релевантные части) прежде, чем Вы выполните myisamchk. На некоторых системах эта опция обязательна потому, что внешняя блокировка не работает в любом случае. Опция --skip-locking по умолчанию включена при компиляции с MIT-pthreads потому, что flock() не полностью поддержан MIT-pthreads на всех платформах. Это также значение по умолчанию для Linux, поскольку блокировка файлов в Linux еще не безопасна. Единственный случай, когда Вы не можете использовать --skip-locking: если Вы выполняете много серверов MySQL (не клиентов) на тех же самых данных или выполняете myisamchk на таблице без предварительной блокировки сервера и сброса таблиц на диск. Вы можете применять LOCK TABLES/UNLOCK TABLES, даже если Вы используете опцию --skip-locking

14.5.2 Настройка параметров сервера

Вы можете получать заданные по умолчанию буферные размеры, используемые сервером mysqld, этой командой:

shell> mysqld --help

Эта команда производит список всех параметров mysqld и переменных с перестраиваемой конфигурацией. Вывод включает значения по умолчанию и выглядит так:

Possible variables for option --set-variable (-O) are:
back_log              current value: 5
bdb_cache_size        current value: 1048540
binlog_cache_size     current_value: 32768
connect_timeout       current value: 5
delayed_insert_timeout  current value: 300
delayed_insert_limit  current value: 100
delayed_queue_size    current value: 1000
flush_time            current value: 0
interactive_timeout   current value: 28800
join_buffer_size      current value: 131072
key_buffer_size       current value: 1048540
lower_case_table_names  current value: 0
long_query_time       current value: 10
max_allowed_packet    current value: 1048576
max_binlog_cache_size current_value: 4294967295
max_connections       current value: 100
max_connect_errors    current value: 10
max_delayed_threads   current value: 20
max_heap_table_size   current value: 16777216
max_join_size         current value: 4294967295
max_sort_length       current value: 1024
max_tmp_tables        current value: 32
max_write_lock_count  current value: 4294967295
myisam_sort_buffer_size  current value: 8388608
net_buffer_length     current value: 16384
net_retry_count       current value: 10
net_read_timeout      current value: 30
net_write_timeout     current value: 60
query_buffer_size     current value: 0
record_buffer         current value: 131072
record_rnd_buffer     current value: 131072
slow_launch_time      current value: 2
sort_buffer           current value: 2097116
table_cache           current value: 64
thread_concurrency    current value: 10
tmp_table_size        current value: 1048576
thread_stack          current value: 131072
wait_timeout          current value: 28800

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

shell> mysqladmin variables

Вы можете находить полное описание для всех переменных в разделе "4.10.4 SHOW VARIABLES ".

Вы можете также видеть некоторую статистику с сервера, выдавая команду SHOW STATUS. Подробности в разделе "4.10.3 SHOW STATUS".

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

При настройке сервера MySQL есть две наиболее важных переменных: key_buffer_size и table_cache.

Если Вы имеете много памяти (>=256M) и много таблиц и хотите получить максимальную эффективность с умеренным числом клиентов, Вы должны использовать нечто подобное этому:

shell> safe_mysqld -O key_buffer=64M -O table_cache=256 \
                       -O sort_buffer=4M -O record_buffer=1M &

Если Вы имеете только 128M и всего несколько таблиц, но Вы делаете много сортировок, Вы можете использовать нечто, подобно этому:

shell> safe_mysqld -O key_buffer=16M -O sort_buffer=1M

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

shell> safe_mysqld -O key_buffer=512k -O sort_buffer=100k \
                       -O record_buffer=100k &

Или вот это:

shell> safe_mysqld -O key_buffer=512k -O sort_buffer=16k \
                       -O table_cache=32 -O record_buffer=8k \
                       -O net_buffer=1K &

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

Когда Вы установили MySQL, каталог support-files будет хранить некоторые различные файлы примера my.cnf, например, my-huge.cnf, my-large.cnf, my-medium.cnf и my-small.cnf, которые Вы можете использовать как основу, чтобы оптимизировать Вашу систему.

Если имеется очень много подключений, может происходить ``swapping problem'', если mysqld не был конфигурирован, чтобы использовать очень небольшую память для каждого подключения. Конечно, mysqld работает много лучше, если Вы имеете достаточно памяти для всех подключений.

Обратите внимание, что, если Вы изменяете опцию mysqld, это остается в силе только для этого образца станции.

Чтобы увидеть эффект от изменения параметра, сделайте:

shell> mysqld -O key_buffer=32m --help

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

14.5.3 Как компиляция и компоновка воздействуют на быстродействие MySQL

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

Вы получаете самую быструю выполнимую программу, когда Вы компонуете ее с опцией времени компоновки -static.

В Linux Вы получите самый быстрый код при компиляции с pgcc и опцией -O3. Чтобы откомпилировать sql_yacc.cc с этими параметрами, Вы нуждаетесь примерно в 200M памяти потому, что gcc/pgcc требует много памяти, чтобы сделать все функции встроенными. Вы должны также установить CXX=gcc при конфигурировании MySQL, чтобы избежать включения библиотеки libstdc++. Обратите внимание, что при работе с некоторыми версиями pgcc возникающий в результате код выполнится только на истинных процессорах Pentium, даже если Вы используете опцию транслятора, чтобы возникающий в результате код работал на всех процессорах типа x586.

Только используя лучший транслятор и/или лучшие параметры транслятора, Вы уже можете получить увеличение быстродействия Вашей прикладной программы на 10-30%! Это особенно важно, если Вы компилируете SQL-сервер сами.

Авторы пакета проверили компиляторы Cygnus CodeFusion и Fujitsu, но на момент этого тестирования они были недостаточно свободны от ошибок, чтобы позволить MySQL компилироваться с включенной оптимизацией.

Когда Вы компилируете MySQL, Вы должны включить поддержку только для тех наборов символов, которые Вы собираетесь использовать (опция --with-charset=xxx). Стандартные двоичные дистрибутивы MySQL компилируются с поддержкой всех наборов символов.

Имеется список некоторых измерений, которые сделали авторы пакета:

  • Если Вы используете pgcc и компилируете все с опцией -O6, сервер mysqld на 1% быстрее, чем с gcc 2.914.2.
  • Если Вы компонуете динамически (без -static), результат на 14% медленнее в Linux. Обратите внимание, что Вы все еще можете использовать динамическую библиотеку MySQL. Это критично только для сервера.
  • Если Вы обработаете mysqld командой strip libexec/mysqld, возникающий в результате двоичный код может быть до 4% быстрее.
  • Если Вы подключаетесь, используя TCP/IP вместо Unix-сокетов, результат на 7.5% медленнее на том же самом компьютере. Если Вы связываетесь с localhost, MySQL по умолчанию использует именно сокеты.
  • Если Вы подключаетесь, используя TCP/IP с другого компьютера по 100M Ethernet, это будет на 8-10% медленнее.
  • Если Вы компилируете с опцией --with-debug=full, теряете 20% скорости для большинства запросов, но некоторые запросы могут еще более замедлиться (эталонные тесты до 36%). Если Вы используете --with-debug, потери составят около 15%. Запуская mysqld, скомпилированный с опцией --with-debug=full, с --skip-safemalloc конечный результат должен быть близок к варианту --with-debug.
  • На Sun SPARCstation 20 SunPro C++ 4.2 на 5% быстрее, чем gcc 2.914.2.
  • Компиляция с помощью gcc 2.914.2 для ultrasparc с опциями -mcpu=v8 -Wa,-xarch=v8plusa дает еще 4% эффективности.
  • В Solaris 2.14.1 MIT-pthreads на 8-12% медленнее своих потоков Solaris на одном процессоре. С ростом загрузки и центральных процессоров различие должно стать больше.
  • Запуск с опцией --log-bin сделает MySQL примерно на 1% медленнее.
  • Компиляция на Linux-x86 с использованием gcc без frame pointers -fomit-frame-pointer или -fomit-frame-pointer -ffixed-ebp делает mysqld на 1-4% быстрее.

Дистрибутив MySQL-Linux, собранный в MySQL AB, использовал pgcc, но из-за ошибки при работе на процессорах AMD (причина в компиляторе, а не в процессорах, они-то как раз отменные!) теперь снова применяется обычный gcc, и так будет до тех пор, пока та ошибка не будет решена авторами транслятора. Тем временем, если Вы имеете не-AMD машину, Вы можете попробовать применить pgcc. Правда, не очень ясно, кто победит в этом споре: то ли более совершенный компилятор pgcc, то ли процессоры от AMD, которые просто по конструкции быстрее Intel... Стандартный двоичный дистрибутив MySQL для Linux скомпонован статически, чтобы получить большие быстродействие и переносимость.

14.5.4 Как MySQL использует память

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

  • Буфер ключей (переменная key_buffer_size) разделен всеми потоками. Другие буфера, используемые сервером, распределены как необходимо. Подробности в разделе "14.5.2 Настройка параметров сервера".
  • Каждое подключение использует некоторое специфическое для потока место: стек (заданный по умолчанию в 64КБ, переменная thread_stack), буфер подключений (переменная net_buffer_length) и буфер результатов (переменная net_buffer_length). Буфер подключений и буфер результатов будут динамически расширены до max_allowed_packet, когда это будет необходимо. Когда запрос обрабатывается, копия текущей строки запроса также распределена.
  • Все потоки совместно используют ту же самую основную память.
  • Только сжатые таблицы ISAM/MyISAM отображаются в памяти. Это потому, что 32-разрядное пространство памяти в 4GB недостаточно большое для наиболее крупных таблиц. Когда системы с 64-разрядным адресным пространством станут более распространенными, авторы пакета добавят общую поддержку для управления памятью по этому методу.
  • Каждый запрос, делающий последовательный просмотр таблицы, распределяет буфер чтений (переменная record_buffer).
  • При чтении строк в произвольном порядке (например, после сортировки) буфер для этого будет распределен, чтобы избежать дисковых установок (переменная record_rnd_buffer).
  • Все объединения выполнены в одном проходе, и большинство объединений может быть выполнено без применения временной таблицы. Временные таблицы с большой длиной записи или включающие столбцы BLOB сохранены на диске. Одна проблема в MySQL до Version 3.23.2 состоит в том, что, если таблица HEAP превышает размер tmp_table_size, Вы получите ошибку The table tbl_name is full. В более новых версиях это обработано автоматической заменой таблиц в памяти на дисковые по мере необходимости. Чтобы обойти эту проблему Вы можете увеличивать временный размер таблицы, устанавливая опцию tmp_table_size в mysqld или устанавливая в программе пользователя SQL-опцию SQL_BIG_TABLES. Подробности в разделе "14.5.6 Синтаксис SET". В MySQL Version 3.20 максимальный размер временной таблицы был record_buffer*16 так, что, если Вы используете эту версию, Вы должны увеличить значение record_buffer. Вы можете также запустить mysqld с опцией --big-tables, чтобы всегда сохранять временные таблицы на диске. Однако, это будет плохо воздействовать на быстродействие очень многих сложных запросов.
  • Большинство запросов, делающих сортировку, распределяет буфер сортировки и 0-2 временных файла в зависимости от размера набора результата. Подробности в разделе "11.4.4 Где MySQL сохраняет свои временные файлы.".
  • Почти весь синтаксический анализ и вычисления выполнены в локальной памяти. Никакая память не требуется для маленьких элементов. Память будет распределена только для неожиданно больших строк (это выполнено с помощью вызовов malloc() и free()).
  • Каждый индексный файл открыт однажды, а файл данных открыт однажды для каждого одновременно выполняемого потока. Для каждого параллельного потока распределены: структура таблицы, структура для каждого столбца и буфера размером 3*n (где n максимальная длина строки, не считая столбцы типа BLOB). BLOB использует от 5 до 8 байт плюс длина данных BLOB. Драйвер таблиц ISAM/MyISAM распределяет один буфер строк дополнительно для внутреннего использования.
  • Для каждой таблицы, имеющей столбцы BLOB, буфер будет расширен динамически, чтобы читать большие значения BLOB. Если Вы просматриваете таблицу, распределяется буфер такого размера, как самое большое значение BLOB.
  • Драйверы таблицы для всех используемых таблиц сохранены в кэше и управляются как FIFO. Обычно кэш имеет 64 записи. Если таблица использовалась двумя потоками в то же самое время, кэш содержит две записи для таблицы. Подробности в разделе "14.4.6 Как MySQL открывает и закрывает таблицы".
  • Команда mysqladmin flush-tables закрывает все таблицы, которые не находятся в использовании, и отмечает все таблицы, находящиеся в использовании, чтобы они были закрыты, когда работающий в настоящее время поток завершится. Это действительно освободит много памяти.

ps и другие программы состояния системы может сообщать, что mysqld использует много памяти. Это может быть вызвано стеками потоков на различных адресах памяти. Например, Solaris-версия ps считает неиспользуемую память между стеками как используемую память! Вы можете выяснить это, проверяя доступный своп командой swap -s. Сервер mysqld проверен с коммерческими детекторами утечки памяти, так что в нем не должно иметься никаких утечек памяти.

14.5.5 Как MySQL использует DNS

Когда новый процесс соединяется с mysqld, он запустит новый поток, чтобы обработать запрос. Этот поток сначала проверит, находится ли hostname в кэше hostname. Если нет, поток вызовет gethostbyaddr_r() и gethostbyname_r(), чтобы получить адрес машины.

Если операционная система не поддерживает вышеупомянутые поточно-безопасные обращения, поток блокирует mutex и вызывает gethostbyaddr() и gethostbyname(). Обратите внимание, что в этом случае никакой другой поток не может обработать другое имя до завершения первого потока.

Вы можете отключить поддержку DNS запуском mysqld с опцией --skip-name-resolve. В этом случае Вы можете использовать только IP-адреса в таблицах привилегий MySQL.

Если Вы имеете очень медленный DNS и много компьютеров, Вы можете получать большую эффективность отключая DNS опцией --skip-name-resolve или увеличивая определение HOST_CACHE_SIZE (значение по умолчанию: 128) с последующей перекомпиляцией сервера mysqld.

Вы можете отключать кэш hostname с помощью опции --skip-host-cache. Вы можете очищать кэш hostname с помощью команд FLUSH HOSTS или mysqladmin flush-hosts.

Если Вы не хотите позволять подключения по TCP/IP, Вы можете сделать это, запуская mysqld с опцией --skip-networking.

14.5.6 Синтаксис SET

SET [OPTION] SQL_VALUE_OPTION=value, ...

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

CHARACTER SET character_set_name|DEFAULT
Это отображает все строки для клиента по заданной карте символов. В настоящее время единственной опцией для character_set_name является cp1251_koi8, но Вы можете легко добавлять новые отображения, редактируя файл sql/convert.cc в дистрибутиве исходных текстов MySQL. Отображение значения по умолчанию может быть восстановлено, используя значение DEFAULT для переменной character_set_name. Обратите внимание, что синтаксис для установки опции CHARACTER SET отличается от синтаксиса для установки других параметров.
PASSWORD=PASSWORD('some password')
Устаналивает пароль для текущего пользователя. Любой неанонимный пользователь может изменять свой собственный пароль!
PASSWORD FOR user=PASSWORD('some password')
Устанавливает пароль для специфического пользователя на текущем компьютере. Только пользователь с доступом к базе данных mysql может делать это. Пользователь должен быть указан в формате user@hostname, где user и hostname указаны точно так, как они перечислены в столбцах User и Host записи в таблице mysql.user. Например, если Вы имели запись с полями User и Host равными bob и %.loc.gov, Вы будете писать:
mysql> SET PASSWORD FOR bob@"%.loc.gov"=PASSWORD("newpass");
или
mysql> UPDATE mysql.user SET password=PASSWORD("newpass")
                  where user="bob' and host="%.loc.gov";
SQL_AUTO_IS_NULL=0|1
Если установлено в 1 (значение по умолчанию), то можно находить последнюю вставленную строку для таблицы с поддержкой auto_increment применением следующей конструкции: WHERE auto_increment_column IS NULL. Это используется некоторыми программами ODBC, например, Access.
AUTOCOMMIT=0|1
Если установлено в 1, все изменения для таблицы будут выполнен сразу. Чтобы запустить многокомандную транзакцию, Вы должны использовать инструкцию BEGIN. Подробности в разделе "9.2.1 Синтаксис BEGIN/COMMIT/ROLLBACK". Если установлено в 0, Вы должны использовать COMMIT/ROLLBACK, чтобы принять или отменить эту транзакцию. Подробности в разделе "9.2.1 Синтаксис BEGIN/COMMIT/ROLLBACK". Обратите внимание, что, когда Вы изменяете режим с не-AUTOCOMMIT на AUTOCOMMIT, MySQL автоматически будет делать COMMIT на открытых транзакциях.
SQL_BIG_TABLES=0|1
Если установлено в 1, все временные таблицы сохранены на диске, а не в памяти. Это будет немного медленнее, но Вы не будете получать ошибку The table tbl_name is full для больших операций SELECT, которые требуют большой временной таблицы. Значение по умолчанию для нового подключения 0 (то есть использовать временные таблицы в памяти).
SQL_BIG_SELECTS=0|1
Если установлено в 0, MySQL прервется, если SELECT, вероятно, будет брать очень длительное время. Это полезно, когда была выдана нецелесообразная инструкция WHERE. Большой запрос определен как SELECT, которому, вероятно, придется исследовать больше, чем max_join_size строк. Значение по умолчанию для нового подключения: 1 (это позволяет выполнять все инструкции SELECT).
SQL_BUFFER_RESULT=0|1
SQL_BUFFER_RESULT вынудит результат SELECT попасть во временную таблицу. Это поможет MySQL освободить блокировку таблицы пораньше и поможет в случаях, где требуется длительное время, чтобы послать набор результатов пользователю.
SQL_LOW_PRIORITY_UPDATES=0|1
Если установлено в 1, все инструкции INSERT, UPDATE, DELETE и LOCK TABLE WRITE ждут до тех пор, пока не останется ни одного ждущего обработки запроса SELECT или LOCK TABLE READ на данной таблице.
SQL_MAX_JOIN_SIZE=value|DEFAULT
Не позволять SELECT, которые, вероятно, будут должны исследовать больше, чем value комбинаций строк. Устанавливая это значение, Вы можете захватывать SELECT, где ключи не используются правильно. Установка этого к иному значению, чем DEFAULT сбросит флажок SQL_BIG_SELECTS. Если Вы снова устанавливаете флажок SQL_BIG_SELECTS, переменная SQL_MAX_JOIN_SIZE будет игнорироваться. Вы можете устанавливать значение по умолчанию для этой переменной, запуская mysqld с опцией -O max_join_size=#.
SQL_SAFE_UPDATES=0|1
Если установлено в 1, MySQL прервется, если UPDATE или DELETE не использует ключ или LIMIT в предложении WHERE. Это делает возможным захватить неправильные модификации при создании SQL-команды вручную.
SQL_SELECT_LIMIT=value|DEFAULT
Максимальное число записей для возвращения из инструкций SELECT. Если SELECT имеет предложение LIMIT, то LIMIT имеет приоритет над значением в SQL_SELECT_LIMIT. Значение по умолчанию для нового подключения: ``unlimited''. Если Вы изменили ограничение, значение по умолчанию может быть восстановлено, используя значение DEFAULT.
SQL_LOG_OFF=0|1
Если установлено в 1, никакая регистрация не будет выполнена в стандартный файл регистрации для этого пользователя, если пользователь имеет привилегию process. Это не воздействует на файл регистрации модификаций!
SQL_LOG_UPDATE=0|1
Если установлено в 0, никакая регистрация не будет выполнена в файл регистрации модификаций для этого пользователя, если пользователь имеет привилегию process. Это не воздействует на стандартный файл регистрации!
SQL_QUOTE_SHOW_CREATE=0|1
Если установлено в 1, SHOW CREATE TABLE цитирует имена столбцов и таблиц. Это включено по умолчанию для репликации таблиц с нестандартными именами столбцов. Подробности в разделе "4.10.8 SHOW CREATE TABLE".
TIMESTAMP=timestamp_value|DEFAULT
Установить время для этого пользователя. Это применяется, чтобы получить оригинал timestamp, если Вы используете файл регистрации модификаций, чтобы восстановить строки. timestamp_value должен быть в формате UNIX Epoch timestamp, а не MySQL timestamp.
LAST_INSERT_ID=#
Установить значение, которое будет возвращено из LAST_INSERT_ID(). Это будет сохранено в файле регистрации модификаций, когда Вы используете LAST_INSERT_ID() в команде, которая модифицирует таблицу.
INSERT_ID=#
Установить значение, которое нужно использовать следующей командой INSERT или ALTER TABLE при вставке значения AUTO_INCREMENT. Это главным образом используется вместе с файлом для регистрации модификаций.

14.6 Дисковые проблемы

  • Как упомянуто ранее, установки дисков представляют собой наиболее узкое место эффективности. Эти проблемы становятся все более очевидными, когда данные вырастают настолько, что эффективное кэширование становится невозможным. Для больших баз данных, где Вы обращаетесь к данным более или менее беспорядочно, Вы можете убедиться, что Вам понадобиться по крайней мере одна дисковая установка, чтобы прочитать, и в двух-трех для записи. Чтобы минимизировать эту проблему, используйте диски с низким временем поиска.
  • Ускорение работы с дисками:
    Использование символических ссылок
    Это означает, что Вы переносите индекс и/или файлы данных с нормального каталога данных на другой диск. Это делает время поиска и чтения меньше (если эти диски не используются для других вещей). Подробности в разделе "14.6.1 Использование символических ссылок ".
    Striping
    Striping означает, что Вы имеете много дисков и помещаете первый блок на первый диск, второй блок на второй диск и N-й на (N mod number_of_disks) диск. Это означает, что если нормальный размер данных меньше, чем размер блока, Вы получите намного лучшую эффективность. Обратите внимание, что striping очень зависит от OS и размера блока. Обратите внимание, что различие быстродействия для striping очень зависит от параметров. В зависимости от того, как Вы устанавливаете параметры и число дисков, Вы можете получать различие в несколько раз. Обратите внимание, что Вы должны выбрать как оптимизировать: для произвольного или последовательного доступа.
  • Для пущей надежности Вы можете использовать RAID 0+1 (striping+mirroring, данные равномерно размазываются на физически разные диски), но в этом случае Вы будете нуждаться в 2*N дисках для N дисков данных. Это, вероятно, самый лучшый вариант, если Вы имеете деньги для его реализации! Вам, вероятно, также придется поставить некоторое программное обеспечение управления местом на дисках, чтобы работать эффективно.
  • Хорошая система должна иметь не очень важные данные (которые могут быть восстановлены) на диске RAID 0 при сохранении по-настоящему важных данных (подобно информации хостов и файлам регистрации) на диске RAID 0+1 или RAID N. RAID N может быть проблемой, если Вы имеете много записей из-за времени, нужного, чтобы модифицировать биты четности.
  • Вы можете также устанавливать параметры для файловой системы, которую база данных использует. Одно простое изменение должно установить файловую систему в режим noatime. Это заставляет систему пропустить модифицирование последнего времени доступа в inode и этим избежать ряда дисковых установок.
  • В Linux Вы можете получить намного большую эффективность (до 100% при некоторых видах загрузки), используя hdpram, чтобы конфигурировать интерфейс вашего диска! Достаточно хорошие параметры hdparm для MySQL (и, вероятно, для многих других прикладных программ):
    hdparm -m 16 -d 1
    Обратите внимание, что эффективность и надежность при использовании вышеупомянутого зависят от Ваших аппаратных средств, так что я настоятельно советую, чтобы Вы проверили Вашу систему полностью после использования hdparm. Пожалуйста, проконсультируйтесь с man-страницей на hdparm для получения большего количества информации. Если hdparm не используется грамотно, можно прихлопнуть все данные на диске. Резервируйте все перед экспериментированием.
  • На многих операционных системах Вы можете монтировать диски с флажком async, чтобы установить файловую систему, которую нужно модифицировать асинхронно. Если Ваш компьютер более-менее стабилен, это должно дать Вам большую эффективность без того, чтобы сильно жертвовать надежностью. Этот флажок включен по умолчанию в Linux.
  • Если Вы не должны знать, когда к файлу в последний раз обращались (а толку-то это знать на сервере?), Вы можете монтировать Ваши файловые системы с указанием флажка noatime.

14.6.1 Использование символических ссылок

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

14.6.1.1 Использование символических ссылок для баз данных

Надо сначала создать каталог на некотором диске, где Вы имеете свободное пространство, и затем создать ссылку туда из каталога баз данных MySQL:

shell> mkdir /dr1/databases/test
shell> ln -s /dr1/databases/test mysqld-datadir

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

shell> cd /path/to/datadir
shell> ln -s db1 db2

Теперь для любой таблицы tbl_a в db1 также имеется таблица tbl_a в db2. Если один поток модифицирует db1.tbl_a, а другой в то же время правит db2.tbl_a, они точно передерутся.

Если Вы хотите разрешить такие обращения, Вы должны изменить следующий код в файле исходного текста mysys/mf_format.c:

if (flag & 32 || (!lstat(to,&stat_buff) &&
   S_ISLNK(stat_buff.st_mode)))

на

if (1)

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

14.6.1.2 Использование символических ссылок для таблиц

До MySQL 4.0 не стоило пользоваться ссылками без их тщательнейшего контроля. Проблема состоит в том, что, если Вы выполняете ALTER TABLE, REPAIR TABLE или OPTIMIZE TABLE на таблице со связью, ссылка будет удалена и заменена первоначальными файлами. Это случается потому, что вышеупомянутая команда работает, создавая временный файл в каталоге баз данных, а когда команда завершится, первоначальный файл она заменит на временный файл.

Вы не должны связывать таблицы на системе, которая не имеет полностью рабочее обращение realpath(). По крайней мере Linux и Solaris точно поддерживают realpath().

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

Обработка символических связей в MySQL 4.0 работает следующим образом:

  • В каталоге данных Вы будете всегда иметь файл определения таблицы и файлы данных/индекса.
  • Вы можете перенаправить индексный файл и файл данных к различным каталогам, независимо друг от друга.
  • Установка ссылки может быть выполнена из операционной системы (если mysqld не запущен) или с помощью команды INDEX/DATA DIRECTORY="path-to-dir" в CREATE TABLE. Подробности в разделе "7.3 Синтаксис CREATE TABLE ".
  • myisamchk теперь уже не будет заменять ссылки на реальные файлы, а работает непосредственно на нужных файлах. Любые временные файлы будут созданы в том же самом каталоге, где лежит файл данных или индекса.
  • Когда Вы удаляете таблицу, которая использует ссылки, удалится ссылка и файл, на который она указывает. Это хорошая причина не выполнять mysqld как root, и не позволять кому попало иметь доступ для записи к каталогам баз данных MySQL.
  • Если Вы переименуете таблицу с помощью ALTER TABLE RENAME и не измените базу данных, ссылка в каталоге базы данных будет переименована, как и файл данных/индекса.
  • Если Вы используете ALTER TABLE RENAME, чтобы переместить таблицу в другую базу данных, то таблица будет перемещаться в другой каталог баз данных, а старая ссылка и файл, на который она указывала, удалятся.
  • Если Вы не используете ссылки, Вы должны использовать опцию --skip-symlink при запуске mysqld, чтобы гарантировать, что никто не может удалять или переименовывать файл вне каталога данных MySQL.

Свойства, которые еще не поддержаны:

  • ALTER TABLE игнорирует все опции INDEX/DATA DIRECTORY="path".
  • CREATE TABLE не сообщает, имеет ли таблица ссылки.
  • mysqldump не включает информацию ссылок в вывод.
  • Команды BACKUP TABLE и RESTORE TABLE не обрабатывают ссылки вообще.


Заключение

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

Автор выражает надежду, что эта книга не является последней, и послужит для читателя лишь первым шагом в изучении сложного и интересного мира под названием "СУБД MySQL".

Чего нет в этой книге

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

В этой книге ставилась задача охватить лишь первоначальные сведения о пакете, но сделать это на таком уровне, чтобы рядовой пользователь клиентской части пакета не только научился что-то делать, но и хорошо понимал, что и зачем он делает. Эта книга изначально задумывалась как противовес некоторым современным руководствам системы "шаг в сторону считается побегом", которые лишь дают конкретные решения очень узких проблем, совершенно не объясняя сути всех этих решений.

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

К сожалению, не могу порекомендовать никакой литературы на русском языке по данному направлению: литература-то есть, хоть ее и мало, но она ориентирована на совсем иной уровень подготовки читателя и другие решаемые задачи. Зато имеется огромное количество ресурсов Internet по MySQL. Большая их часть на английском языке, однако, именно там можно найти много ценного.

Информация и руководства по SQL

Очень хорошую подборку книг по MySQL, разделенную по темам, можно найти на http://www.mysql.com/portal/books/html/index.html. Сразу предупреждаю, что на русском языке в сети есть только одна работа (написана автором этой книги) http://www.botik.ru/~rldp/articles/mysqlrus/mysqlrus.htm. Она есть на множестве зеркал в сети, так что Вы ее без труда найдете. Вся прочая информация доступна, главным образом, на английском языке.

Учебники могут быть найдены на: http://www.mysql.com/portal/development/html/development-61-1.html

Полезные ссылки по MySQL

Много ссылок есть на сайте разработчиков MySQL: http://www.mysql.com/portal/development/html/index.html

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

Учебники и руководства по MySQL

MySQL Myths Debunked
MySQL используемый в реальном мире.
http://www.4t2.com/mysql
Информация о списке рассылки German MySQL.
http://www2.rent-a-database.de/mysql
MySQL-руководство на немецком.
http://www.bitmover.com:8888//home/bk/mysql
Web-доступ к репозитарию MySQL BitKeeper.
http://www.analysisandsolutions.com/code/mybasic.htm
Учебник для новичков в MySQL о том, как устанавливать MySQL под Windows.
http://www.devshed.com/Server_Side/MySQL
Много учебников MySQL.
http://mysql.hitstar.com
Руководство по MySQL на китайском.
http://www.linuxplanet.com/linuxplanet/tutorials/1046/1/
Создание MySQL-Web сайта.
http://www.hotwired.com/webmonkey/backend/tutorials/tutorial1.html
Описание связки MySQL-Perl.
http://www.iserver.com/support/contrib/perl5/modules.html
Установка новых Perl-модулей.
http://www.hotwired.com/webmonkey/databases/tutorials/tutorial4.html
Описание связки PHP/MySQL.
http://www.useractive.com
Краткий учебник по MySQL.

Портирование MySQL и применение MySQL на разных системах

http://www.entropy.ch/software/macosx/mysql
Двоичный клиент MySQL для Mac OS X. Включает информацию относительно того, как формировать и использовать MySQL на Mac OS X.
http://xclave.macnn.com/MySQL
Mac OS Xclave. Запуск MySQL на Mac OS X.
http://www.prnet.de/RegEx/mysql.html
MySQL для Mac OS X Server.
http://www.latencyzero.com/macosx/mysql.html
Построение MySQL для Mac OS X.
http://www.essencesw.com/Software/mysqllib.html
Новая клиентская библиотека для Mac OS Classic (Macintosh).
http://www.lilback.com/macsql
Клиентская библиотека для Mac OS Classic (Macintosh).
http://sixk.maniasys.com/index_en.html
MySQL для Amiga

Ссылки по языку Perl

http://dbimysql.photoflux.com
Perl DBI с MySQL FAQ.

Дискуссионные форумы по MySQL

http://www.weberdev.com
Примеры использования MySQL; (check Top 20)
http://futurerealm.com/forum/futureforum.htm
FutureForum Web Discussion Software.

Коммерческие приложения, поддерживающие MySQL

http://www.supportwizard.com
SupportWizard. Интерактивный Web-ассистент (включает запатентованную копию MySQL).
http://www.sonork.com
Sonork, агент мгновенных сообщений, который ориентирован не только на Internet. Это ориентировано на частные сети, и на маленькие и средние компании. Клиент свободен, сервер тоже свободен, но до 5 пользователей.
http://www.stweb.org
StWeb (Stratos Web and Application server). Удобная в работе, кроссплатформенная Internet/Intranet система разработки и развертывания для web-приложений. Стандартная версия StWeb имеет свой интерфейс к MySQL.
http://www.rightnowtech.com
Right Now Web. Web-автоматизация для обслуживания заказчика.
http://www.icaap.org/Bazaar
Bazaar. Интерактивный дискуссионный форум с Web-интерфейсом.
http://www.phonesweep.com
PhoneSweepT первый в мире коммерческий телефонный сканер. Много взломов за последние годы пришли не через Internet, а через несанкционированные dial-up модемы. PhoneSweep позволяет Вам находить эти модемы, отслеживая обращения по телефону к каждому номеру телефона, которым Ваша организация управляет. PhoneSweep имеет встроенную экспертную систему, которая может распознавать больше, чем 250 различных видов программ с удаленным доступом, включая Carbon Copy(TM), pcANYWHERE(TM) и Windows NT RAS. Вся информация сохранена в SQL базе данных.

SQL-клиенты и генераторы отчетов

urSQL
Редактор SQL и утилита запросов. Заказная подсветка синтаксиса, доступная для редактирования сетка результатов, экспорт результатов, основные функции администрирования MySQL и так далее. Работает под Windows.
MySQL Data Manager
Менеджер данных MySQL является платформно-независимым web-клиентом (написан на perl) для сервера MySQL с поддержкой TCP/IP.
http://ksql.sourceforge.net
Клиент MySQL для KDE.
http://www.ecker-software.de
Клиент для Windows GUI (автор David Ecker).
http://www.icaap.org/software/kiosk
Kiosk. Клиент MySQL для управления базами данных. Написан на Perl. Будет частью пакета Bazaar.
http://www.casestudio.com
Утилита для создания баз данных с поддержкой MySQL 3.23.
http://home.skif.net/~voland/zeos/eng/index.html
Zeos. Клиент, который поддерживает MySQL, Interbase и PostgreSQL.
http://www.geocities.com/SiliconValley/Ridge/4280/GenericReportWriter/grwhome.html
Свободный генератор отчетов на Java
http://www.javaframework.de
MySQLExport. Экспорт инструкций create и данных из MySQL в разные форматы (SQL, HTML, CVS, чистый текст, ZIP, GZIP...)
http://dlabs.4t2.com
M2D, клиент администрирования MySQL для Windows. M2D поддерживает администрирование баз данных MySQL, создание новых баз данных и таблиц, редактирование и многое другое.
http://dlabs.4t2.com
Dexter, маленький сервер, написанный на Perl, который может использоваться как прокси-сервер для MySQL или как расширитель базы данных.
http://www.scibit.com/Products/Software/Utils/Mascon.asp
Mascon представляет собой мощный Win32 GUI-инструмент для управления базами данных MySQL.
http://www.rtlabs.com/
MacSQL Monitor. GUI для баз данных MySQL, ODBC и JDBC для Mac OS.

Дистрибутивы, которые включают MySQL

http://www.suse.com
SuSE Linux (6.1 и выше)
http://www.redhat.com
RedHat Linux (7.0 и выше)
http://distro.conectiva.com.br
Conectiva Linux (4.0 и выше)

Инструменты разработки для Web, которые поддерживают MySQL

http://www.php.net
PHP: серверный язык, встраиваемый в HTML.
http://www.midgard-project.org
Midgard Application Server. Мощная среда Web-разработки, основанная на MySQL и языке PHP.
http://www.smartworker.org
SmartWorker, платформа для разработки Web-приложений.
http://xsp.lentus.se
XSP, e(X)tendible (S)erver (P)ages, встраиваемый в HTML язык, написан на Java (ранее был известен как XTAGS)
http://www.dbServ.de
dbServ расширение web-сервера, чтобы интегрировать вывод базы данных в Ваш HTML-код. Вы можете использовать любую функцию HTML в Вашем выводе. Это работает как автономный сервер или Java servlet.
http://www.chilisoft.com
Платформно-независимый ASP Chili!Soft
http://www.voicenet.com/~zellert/tjFM
Драйвер JDBC для MySQL.
http://www.wernhart.priv.at/php
Демонстрашки MySQL+PHP.
http://www.dbwww.com
ForwardSQL: HTML-интерфейс для работы с базами данных MySQL.
http://www.daa.com.au/~james/www-sql
WWW-SQL: отображает информацию из баз данных.
http://www.minivend.com/minivend
Minivend: система покупок через Web.
http://www.heitml.com
HeiTML: серверное расширение HTML и язык 4GL в то же самое время.
http://www.metahtml.com
Metahtml: язык динамического программирования для программ WWW.
http://www.binevolve.com
VelocityGen для Perl и Tcl.
http://hawkeye.net
Hawkeye Internet Server Suite.
http://www.fastflow.com
Сетевое подключение к базам данных для Linux.
http://www.wdbi.net
WDBI: Web-браузер как универсальный внешний интерфейс к базам данных, который хорошо поддерживает MySQL.
http://www.webgroove.com
WebGroove Script: компилятор HTML и серверный скриптовый язык.
http://www.ihtml.com
Серверный скриптовый язык для Web.
ftp://ftp.igc.apc.org/pub/myodbc/README
Как использовать MySQL с ColdFusion на Solaris.
http://calistra.com/MySQL
Администратор Calistra ODBC MySQL.
http://www.webmerger.com
Webmerger. CGI-инструмент интерпретирует файлы и генерирует динамический вывод, основанный на наборе простых отметок. Готов выполнять драйверы для MySQL и PostgreSQL через ODBC.
http://phpclub.net
PHPclub: много советов по PHP, CGI, MySQL, Perl и всему, что с этим хоть как-то связано.
http://www.penguinservices.com/scripts
MySQL и Perl скрипты.
http://www.widgetchuck.com
Widgetchuck: утилиты и примочки для Web-сайта.
http://www.adcycle.com
AdCycle: менеджер рекламы.
http://sourceforge.net/projects/pwpage
pwPage обеспечивает чрезвычайно быстрый и простой подход к созданию форм базы данных. То есть если таблица базы данных существует, и HTML-страница была создана, используя несколько простых руководящих принципов, то pwPage может немедленно использоваться для выборок данных из таблицы, вставок, модификаций, стирания и выборочного просмотра содержания таблицы.
http://www.omnis-software.com/products/studio/studio.html
OMNIS Studio: RAD-инструмент с поддержкой MySQL.
http://www.webplus.com
talentsoft Web+ 4.6 представляет собой мощный и всесторонний язык разработок для использования в создании web-приложений класса клиент-сервер без того, чтобы писать сложные и отнимающие много времени программы низкого уровня по протоколу CGI.

Утилиты разработки баз данных с поддержкой MySQL

http://www.mysql.com/documentation/dezign
"DeZign for databases" является инструментом разработки базы данных, который хорошо использует диаграмму связи объекта (ERD).

Web-сверверы с инструментами MySQL

ftp://ftp.kcilink.com/pub
mod_auth_mysql. Модуль авторизации для сервера Apache.
http://www.roxen.com
Roxen Challenger Web-сервер.

Расширения для других программ

http://www.seawood.org/msql_bind
Поддержка MySQL для BIND (Internet Domain Name Server).
http://www.inet-interactive.com/sendmail
Поддержка MySQL для Sendmail и Procmail.

Применение MySQL с другими программами

http://www.iserver.com/support/addonhelp/database/mysql/msaccess.html
Использование MySQL с Access.
http://www.iserver.com/support/contrib/perl5/modules.html
Установка новых модулей для Perl.

Ссылки по ODBC

http://www.iodbc.org
Популярный менеджер драйверов iODBC Driver Manager (libiodbc), ныне доступен как Open Source.
http://users.ids.net/~bjepson/freeODBC
Страничка FreeODBC.
http://genix.net/unixODBC
Цели проекта unixODBC состоят в том, чтобы разрабатывать и поддержать unixODBC, который должен стать окончательным стандартом для ODBC на платформе Linux. Это должно включать поддержку GUI для KDE. Самое смешное в том, что таких "окончательных стандартов" много...
http://www.sw-soft.com/products/BtrieveODBC
MySQL-ODBC драйвер для Btrieve.

Ссылки по API

http://www.jppp.com
Частично готовые TDataset-совместимые компоненты для MySQL.
http://www.riverstyx.net/qpopmysql
qpopmysql: заплата, чтобы позволить POP3 брать удостоверение из MySQL базы данных. Имеется также связь с заплатой (автор Paul Khavkine) для Procmail, чтобы позволить любому MTA работать с пользователями в MySQL.
http://www.pbc.ottawa.on.ca
Генератор классов Visual Basic для Active X.
http://www.essencesw.com/Software/mysqllib.html
Новая клиентская библотека для Mac OS Classic (Macintosh).
http://www.lilback.com/macsql
Клиентская библотека для Macintosh.
http://www.essencesw.com/Plugins/mysqlplug.html
Присоска для REALbasic (Macintosh)
http://www.iis.ee.ethz.ch/~neeri/macintosh/gusi-qa.html
Библиотека, которая эмулирует сокеты BSD и pthreads на Macintosh. Это может использоваться, если Вы хотите компилировать клиентскую библиотеку MySQL на Mac.
http://www.dedecker.net/jessie/scmdb
SCMDB дополнение для SCM, который портирует MySQL C library (SCM). С этими библиотечными разработчиками можно делать подключения к базе данных MySQL и использовать SQL в своих программах.

Прочие ссылки по MySQL

SAT
Small Application Toolkit (SAT) представляет собой совокупность утилит, предназначенную, чтобы упростить разработку маленьких, многопользовательских прикладных GUI-программ в среде клиент-сервер. Клиент работает под Microsoft Windows или X Window, сервер базируется под Unix.
http://www.wix.com/mysql-hosting
Реестр интернет-провайдеров, поддерживающих MySQL.
http://www.softagency.co.jp/mysql/index.en.html
Ссылки по использованию MySQL в Japan/Asia.
http://abattoir.cc.ndsu.nodak.edu/~nem/mysql/udf
Перечень MySQL UDF.
http://www.open.com.au/products.html
Система коммерческого Web-мониторинга ошибок.
http://www.stonekeep.com/pts
PTS: Project Tracking System.
http://tomato.nvgc.vt.edu/~hroberts/mot
Программное обеспечение, отслеживающее систему.
http://www.cynergi.net/exportsql
ExportSQL: скрипт, чтобы экспортировать данные из Access95+.
http://SAL.KachinaTech.COM/H/1/MYSQL.html
SAL (Scientific Applications on Linux) MySQL.
http://www.pmpcs.com/
PMP Computer Solutions. Разработчики баз данных, использующие MySQL и mSQL.
http://www.aewa.org
Ассоциация Airborne Early Warning.
http://www.dedserius.com/y2kmatrix
Тестер совместимости с Y2K.

Интерфейсы SQL и баз данных

http://java.sun.com/products/jdbc
JDBC API для доступа к БД.
http://www.gagme.com/mysql
Патч для mSQL Tcl.
http://www.amsoft.ru/easysql
EasySQL: ODBC-совместимый менеджер.
http://www.lightlink.com/hessling/rexxsql.html
REXX-интерфейс для SQL.
http://www.mytcl.cx
Tcl-интерфейс, основанный на tcl-sql.
http://www.binevolve.com/~tdarugar/tcl-sql
Интерфейс для Tcl.
http://www.contrib.andrew.cmu.edu/~shadow/sql.html
SQL Reference Page с большим количеством интересных ссылок.

Примеры использования MySQL

http://www.little6.com/about/linux
Little6 Inc. Интерактивный сайт поиска контрактов, использующий MySQL, PHP3 и Linux.
http://www.delec.com/is/products/prep/examples/BookShelf/index.html
DELECis. Инструмент, который делает очень простой автоматическую генерацию документации для таблицы.
http://www.worldrecords.com
World Records. Поисковик для информации относительно музыки, который использует MySQL и PHP.
http://www.webtechniques.com/archives/1998/01/note
База данных контактов, использующая MySQL и язык PHP.
http://modems.rosenet.net/mysql
Web-интерфейс с календарем на PHP.
http://www.odbsoft.com/cook/sources.htm
Perl-пакет, чтобы генерировать html из SQL-таблицы и для производства инструкций SQL из формы html.
http://www.gusnet.cx/proj/telsql
Базисная телефонная база данных, использующая DBI/DBD.
http://tecfa.unige.ch/guides/java/staf2x/ex/jdbc/coffee-break
Примеры работы с JDBC (автор: Daniel K. Schneider).
http://www.spade.com/linux/howto/PostgreSQL-HOWTO-41.html
SQL BNF
http://www.ooc.com/
Object Oriented Concepts Inc. Прикладные программы CORBA с примерами.
http://www.pbc.ottawa.on.ca
DBWiz. Включает пример того, как управлять курсорами в VB.
http://keilor.cs.umass.edu/pluribus
Pluribus свободный поисковик, который обучается, чтобы улучшить качество результатов поиска через какое-то время. Pluribus работает, делая запись о том, какие страницы пользователь предпочитает среди результатов поиска. Пользователь голосует за страницу, выбирая ее. Затем Pluribus использует это знание, чтобы улучшить качество результатов, когда кто-то еще представляет на рассмотрение тот же самый (или подобный) запрос. Использует PHP и MySQL.
http://www.stopbit.com/
Stopbit. Сайт новостей технологий, использующий MySQL и PHP.
http://www.linuxsupportline.com/~kalendar
Менеджер календарей для KDE.
http://tim.desert.net/~tim/imger
Пример сохранения и получения изображений с помощью MySQL и CGI.
http://www.city-gallery.com/album
Old Photo Album. Совместная популярная хронология проекта фотографий, который генерирует все страницы из данных, сохраненных в MySQL базе данных. Страницы будут динамически сгенерированы через интерфейс php3 к содержанию базы данных. Пользователи поставляют изображения и описания. Присланные изображения сохранены на web-сервере, чтобы избежать сохранения их в базе данных как объекты типа BLOB. Вся другая информация сохранена на общедоступном сервере MySQL.

Ссылки по базам данных

http://www.pcslink.com/~ej/dbweb.html
Database Jump Site
http://black.hole-in-the.net/guy/webdb
Домашняя страница списка рассылки webdb-l (Web Databases).
http://www.symbolstone.org/technology/perl/DBI/index.html
Страница модулей Perl DBI/DBD.
http://www.student.uni-koeln.de/cygwin
Проект Cygwin. Unix поверх Windows.
http://dbasecentral.com
dbasecentral.com. Разработка и распространение мощных и удобных в работе прикладных программ базы данных и систем.
http://www.tek-tips.com
Tek-Tips Forums: свыше 800 некоммерческих форумов для компьютерных профессионалов. Свойства включают: автоматическое сообщение по электронной почте ответов, библиотеки связей и гарантируемую конфиденциальность члена.
http://www.public.asu.edu/~peterjn/btree
B-Trees: структуры сбалансированных деревьев данных.
http://www.fit.qut.edu.au/~maire/baobab/lecture/sld001.htm
Лекции по B-деревьям.

Имеется также много Web-страниц по использованию MySQL. Подробности в разделе "Некоторые пользователи MySQL". Пошлите любые добавления к этому списку на webmaster@mysql.com. Авторы пакета требуют, чтобы Вы показали эмблему MySQL где-нибудь, если Вы желаете, чтобы Ваш сайт был добавлен в список.

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

Этот раздел представляет списки рассылки по MySQL и дает некоторые руководящие принципы относительно того, как использовать их.

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

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

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

Если Ваш адрес ответа неправилен, Вы можете определять ваш адрес явно. Добавление дефиса к слову subscribe или unsubscribe, сопровождаемое Вашим адресом, произведет нужный эффект. Замените в адресе символ @ на =. Например, чтобы подписать your_name@host.domain, направьте письмо на адрес mysql-subscribe-your_name=host.domain@lists.mysql.com.

Почта на адреса mysql-subscribe@lists.mysql.com и mysql-unsubscribe@lists.mysql.com автоматически обрабатывается процессором списка адресатов ezmlm. Информация относительно ezmlm доступна на Web-сайте пакета ezmlm http://www.ezmlm.org .

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

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

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

Есть следующие списки рассылки:

announce-subscribe@lists.mysql.com announce
Объявления относительно новых версий MySQL и связанных программ.
mysql-subscribe@lists.mysql.com mysql
Основной список для общего обсуждения MySQL. Пожалуйста, обратите внимание, что некоторые темы лучше обсуждать в специализированных списках. Если Вы пошлете письмо неправильному списку, Вы не можете получить ответ!
mysql-digest-subscribe@lists.mysql.com mysql-digest
Дайджест по материалам рассылки mysql. Это означает, что Вы получаете все индивидуальные сообщения, посланные как одно большое сообщение почты один раз в день.
bugs-subscribe@lists.mysql.com bugs
В этот список Вы должны посылать только полный отчет об ошибке, использующий скрипт mysqlbug (если Вы работаете под Windows, Вы должны включить описание операционной системы и версии MySQL). Предпочтительно, чтобы Вы проверили проблему при использовании последней версии пакета. Любой должен быть способен повторить ошибку, используя только mysql test < script на присланном образце. Все ошибки, зарегистрированные в этом списке, будут исправлены или зарегистрированы в следующем выпуске MySQL. Если имеются только маленькие изменения кода, авторы также публикуют здесь заплатку, которая решает проблему.
bugs-digest-subscribe@lists.mysql.com bugs-digest
Рассылка bugs в виде дайджеста.
internals-subscribe@lists.mysql.com internals
Список для людей, которые работают на коде MySQL. В этом списке можно также обсуждать MySQL разработку и публиковать свои заплатки.
internals-digest-subscribe@lists.mysql.com internals-digest
Дайджест-версия рассылки internals.
java-subscribe@lists.mysql.com java
Обсуждение относительно MySQL и Java. Обычно относительно JDBC-драйверов.
java-digest-subscribe@lists.mysql.com java-digest
Дайджест-версия рассылки java.
win32-subscribe@lists.mysql.com win32
Все относительно MySQL на операционных системах Microsoft типа Win95, Win98, WinNT и Win2000.
win32-digest-subscribe@lists.mysql.com win32-digest
Дайджест-версия рассылки win32.
myodbc-subscribe@lists.mysql.com myodbc
Все относительно соединения MySQL с ODBC.
myodbc-digest-subscribe@lists.mysql.com myodbc-digest
Дайджест-версия рассылки myodbc.
plusplus-subscribe@lists.mysql.com plusplus
Все относительно программирования C++ API и MySQL.
plusplus-digest-subscribe@lists.mysql.com plusplus-digest
Дайджест-версия рассылки plusplus.
msql-mysql-modules-subscribe@lists.mysql.com msql-mysql-modules
Список относительно поддержки Perl в MySQL и msql-mysql-modules.
msql-mysql-modules-digest-subscribe@lists.mysql.com msql-mysql-modules-digest
Дайджест-версия рассылки msql-mysql-modules.

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

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

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


Приложение 1

Приложение 1. Сопроводительный CD-ROM

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

Все архивы на диске поставляются в форматах Tar+Gzip и RPM, принятых в Linux и вообще почти всех Unix-системах. Основная масса архивов взята мной с сайта разработчиков MySQL. Диск охватывает все возможные дистрибутивы и дополнения к ним, которые официально представлены для этого пакета.

ВСЕ ПРОГРАММЫ НА СОПРОВОДИТЕЛЬНОМ CD-ROM ВЗЯТЫ МНОЙ ИЗ ОТКРЫТЫХ СЕТЕВЫХ ИСТОЧНИКОВ И РАСПРОСТРАНЯЮТСЯ В СТРОГОМ СООТВЕТСТВИИ С ИХ ЛИЦЕНЗИЯМИ. ДИСК НЕ СОДЕРЖИТ ПИРАТСКИХ КОПИЙ КАКОГО БЫ ТО НИ БЫЛО ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ. ОСНОВНАЯ ЧАСТЬ ПРОГРАММ НА НЕМ ПОСТАВЛЯЕТСЯ В ИСХОДНЫХ ТЕКСТАХ.


Приложение 2

Приложение 2. Переменные окружения

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

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

Во многих случаях предпочтительно использовать файл выбора конфигурации вместо системных переменных, чтобы изменить поведение MySQL. Подробности в разделе "4.11 Файл опций my.cnf".

DBI_USER | Заданный по умолчанию пользователь для интерфейса Perl DBI.
DBI_TRACE | Используется при трассировке Perl DBI.
HOME | Заданный по умолчанию путь для файла хронологии mysql, обычно $HOME/.mysql_history.
LD_RUN_PATH | Используется, чтобы определить, где находится Ваша библиотека libmysqlclient.so.
MYSQL_DEBUG | Опции трассировки при отладке.
MYSQL_HISTFILE | Путь к файлу хронологии mysql.
MYSQL_HOST | Заданное по умолчанию имя хоста, используемое подсказкой командной строки mysql.
MYSQL_PWD | Заданный по умолчанию пароль при соединении с mysqld. Обратите внимание, что использование этой возможности задания пароля опасно!
MYSQL_TCP_PORT | Заданный по умолчанию порт TCP/IP.
MYSQL_UNIX_PORT | Сокет по умолчанию. Используется для связи с localhost.
PATH | Используется оболочкой для поиска программ и утилит пакета MySQL.
TMPDIR | Каталог, где будут созданы временные таблицы или файлы.
TZ | Это должно быть установлено к Вашей зоне местного времени. Подробности в разделе "11.4.6 Проблемы часового пояса".
UMASK_DIR | Создание каталога пользователя будет выполнено с данной маской прав доступа. Обратите внимание, что это значение будет использовано в операции AND с UMASK!
UMASK | То же самое, но для создания файлов.
USER | Заданный по умолчанию пользователь в Windows, чтобы использовать при соединении с mysqld.


Приложение 3

Приложение 3. Выяснение вопросов или сообщение об ошибках в пакете

Перед отправкой отчета об ошибке или вопроса сделайте следующее:

  • Начните с поисков в руководстве по MySQL. Самая свежая версия (увы, только на английском языке) есть по адресу:
    http://www.mysql.com/documentation/manual.php
  • Ищите также в архиве списков рассылки по MySQL:
    http://www.mysql.com/documentation
  • Вы можете также использовать http://www.mysql.com/search.html для поиска по всем страницам на http://www.mysql.com.

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

Как сообщать об ошибках и сбоях

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

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

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

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

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

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

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

Самые лучшие отчеты такие, которые включают полный пример, показывающий как воспроизвести ошибку или проблему.

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

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

Пожалуйста, включите следующую информацию в Ваш отчет:

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

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

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

Руководящие принципы ответов на вопросы в списках рассылки

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

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


MySQL: Руководство администратора

Приложение 4. GNU GENERAL PUBLIC LICENSE

Version 2, June 1991

Copyright © 1989, 1991 Free Software Foundation, Inc.
59 Temple Place - Suite 330, Boston, MA  02111-1307, USA

Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.

Preamble

The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too.

When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things.

To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it.

For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.

We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software.

Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations.

Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all.

The precise terms and conditions for copying, distribution and modification follow.

2 TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

  1. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The ``Program'', below, refers to any such program or work, and a ``work based on the Program'' means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term ``modification''.) Each licensee is addressed as ``you''. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does.
  2. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.
  3. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:
    1. You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change.
    2. You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License.
    3. If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.)
    These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.
  4. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following:
    1. Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
    2. Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
    3. Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.)
    The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code.
  5. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.
  6. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it.
  7. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License.
  8. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.
  9. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.
  10. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and ``any later version'', you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation.
  11. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.

    9.4 NO WARRANTY

  12. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM ``AS IS'' WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
  13. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

9.5 END OF TERMS AND CONDITIONS

3 How to Apply These Terms to Your New Programs

If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms.

To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the ``copyright'' line and a pointer to where the full notice is found.

one line to give the program's name and a brief idea of what it does.

Copyright (C) yyyy name of author

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

Also add information on how to contact you by electronic and paper mail.

If the program is interactive, make it output a short notice like this when it starts in an interactive mode:

Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.

The hypothetical commands show w and show c should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than show w and show c; they could even be mouse-clicks or menu items--whatever suits your program.

You should also get your employer (if you work as a programmer) or your school, if any, to sign a ``copyright disclaimer'' for the program, if necessary. Here is a sample; alter the names:

Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.

signature of Ty Coon, 1 April 1989
Ty Coon, President of Vice

This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License.


MySQL: Руководство администратора

Приложение 5. GNU LESSER GENERAL PUBLIC LICENSE

Version 2.1, February 1999

Copyright © 1991, 1999 Free Software Foundation, Inc.
59 Temple Place -- Suite 330, Boston, MA 02111-1307, USA

Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.

[This is the first released version of the Lesser GPL.  It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]

1 Preamble

The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users.

This license, the Lesser General Public License, applies to some specially designated software--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below.

When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things.

To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it.

For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights.

We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library.

To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others.

Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license.

Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs.

When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library.

We call this license the Lesser General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances.

For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License.

In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system.

Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library.

The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a ``work based on the library'' and a ``work that uses the library''. The former contains code derived from the library, whereas the latter must be combined with the library in order to run.

2 TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

  1. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called ``this License''). Each licensee is addressed as ``you''. A ``library'' means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The ``Library'', below, refers to any such software library or work which has been distributed under these terms. A ``work based on the Library'' means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term ``modification''.) ``Source code'' for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does.
  2. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.
  3. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:
    1. The modified work must itself be a software library.
    2. You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change.
    3. You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License.
    4. If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.)
    These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.
  4. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library.
  5. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code.
  6. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a ``work that uses the Library''. Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a ``work that uses the Library'' with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a ``work that uses the library''. The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a ``work that uses the Library'' uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself.
  7. As an exception to the Sections above, you may also combine or link a ``work that uses the Library'' with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things:
    1. Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable ``work that uses the Library'', as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.)
    2. Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with.
    3. Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution.
    4. If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place.
    5. Verify that the user has already received a copy of these materials or that you have already sent this user a copy.
    For an executable, the required form of the ``work that uses the Library'' must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute.
  8. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things:
    1. Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above.
    2. Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work.
  9. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.
  10. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it.
  11. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License.
  12. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.
  13. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.
  14. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and ``any later version'', you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation.
  15. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.

    9.6 NO WARRANTY

  16. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY ``AS IS'' WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
  17. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

9.7 END OF TERMS AND CONDITIONS

3 How to Apply These Terms to Your New Libraries

If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License).

To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the ``copyright'' line and a pointer to where the full notice is found.

one line to give the library's name and an idea of what it does.
Copyright (C) year name of author

This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or (at
your option) any later version.

This library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.

Also add information on how to contact you by electronic and paper mail.

You should also get your employer (if you work as a programmer) or your school, if any, to sign a ``copyright disclaimer'' for the library, if necessary. Here is a sample; alter the names:

Yoyodyne, Inc., hereby disclaims all copyright interest in the library
`Frob' (a library for tweaking knobs) written by James Random Hacker.

signature of Ty Coon, 1 April 1990
Ty Coon, President of Vice

That's all there is to it!