Logo Море(!) аналитической информации!
IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware
Бесплатный конструктор сайтов и Landing Page

Хостинг с DDoS защитой от 2.5$ + Бесплатный SSL и Домен

SSD VPS в Нидерландах под различные задачи от 2.6$

✅ Дешевый VPS-хостинг на AMD EPYC: 1vCore, 3GB DDR4, 15GB NVMe всего за €3,50!

🔥 Anti-DDoS защита 12 Тбит/с!

VPS в 21 локации

От 104 рублей в месяц

Безлимитный трафик. Защита от ДДоС.

🔥 VPS до 5.7 ГГц под любые задачи с AntiDDoS в 7 локациях

💸 Гифткод CITFORUM (250р на баланс) и попробуйте уже сейчас!

🛒 Скидка 15% на первый платеж (в течение 24ч)

2004 г

MySQL: Руководство разработчика. Версия 1.0. 20 апреля 2004 г.

Алексей Паутов,
Все о MySQL на русском: http://www.botik.ru/~rldp/mysql.htm, ftp://ftp.botik.ru/rented/rldp/www/pub
Russian LDP: http://www.botik.ru/~rldp, ftp://ftp.botik.ru/rented/rldp

содержание

5.6. MySQLmodule-1.4

Этот модуль был разработан под Linux (RH50), MySQL 3.21.30 и Python 1.5.1. MySQLmodule-1.x основан на mySQLmodule-0.1.4, разработанном:

mySQLmodule-0.1.4 в свою очередь основан на mSQLmodule, разработанном:

  • Portions copyright (C) 1995 Thawte Consulting, cc
  • Portions copyright (C) 1994 Anthony Baxter
5.6.1 Почему другой интерфейс Python/MySQL?

Была обнаружена проблема при сохранении строк, содержащих ASCII-ноль (\0) в базе данных MySQL. После расследования в языке Python (который создал первоначальную ошибку), был проверен код mySQLmodule и там найден ряд проблем. Некоторые подпрограммы не освобождают распределенную память, некоторые функции MySQL API не были доступны, и многих разработчиков совершенно не устраивал тот факт, что mySQLmodule возвратит различные структуры данных в зависимости от метода. Так что я переделал код. Так как эти изменения включают изменение в методах Python и значениях возврата, был повышен код версии и изменено имя модуля на MySQL, чтобы оно не столкнулось с оригиналом (mySQL).

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

Data = DBH['select * from MyTable']
if Data:
   rows = len(Data)
   cols = len(Data[0])
   for i in range(rows):
     for j in range(cols):
       if not Data[i][j]: Data[i][j] = DefaultElement()
   Do_Something(Data)

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

5.6.2 Компиляция и установка модуля MySQL
  • Скопируйте MySQLmodule.c в подкаталог Modules дерева исходников Python.
  • Добавьте следующие строки в Ваш файл Setup в этом каталоге:
    MySQL MySQLmodule.c -L/usr/local/lib/mysql/ -lmysqlclient \
                        -I/usr/local/include/mysql
    

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

  • Если Вы формировали Python ранее, просто выполните make в Вашем основном каталоге Python. Если нет, следуйте командам о том, как компилировать и установить Python.

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

gcc -shared -I/usr/include/python1.5 -I/usr/local/include/mysql \
    MySQLmodule.c -lmysqlclient -L/usr/lib/python1.5/config \
    -lpython1.5 -o MySQLmodule.so

Переместите возникающий в результате файл MySQLmodule.so в PYTHONPATH. Замените соответствующие расположения Ваших библиотек и include-файлов.

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

Экспортируемые типы, функции и классы

Модуль MySQL экспортирует следующее:

  • DBH_Type:
    Тип объекта базы данных.
  • STH_Type:
    Тип ошибки объекта курсора (исключительная ситуация, выдаваемая в некоторых обстоятельствах вместо TypeError).
  • __doc__:
    Версия, доступная из Python
  • connect([host[,user[,pass]]])
    Функциональный возврат объекта базы данных. Факультативные параметры: имя компьютера (host), с которым надлежит соединиться, username для связи с MySQL и соответствуюющий пароль password. Если никакой компьютер не задан, функция примет localhost (и будет использовать Unix-сокет для подключения к нему).
  • escape(string)
    Вернет правильно экранированную строку, чтобы позволить вставку в DB. Эта подпрограмма вызывает mysql_escape_string(), которая в 3.21.29-gamma не работает. Версия 3.21.30 и выше работают нормально.

    Обратите внимание: в следующем "таблица" означает "список списков" (за исключением fetchdict). MySQL.connect() вернет дескриптор базы данных (DBH) со следующими методами:

  • Table = DBH.listdbs([wild])
    Возвращает таблицу, дающую имена баз данных на компьютере MySQL, с которым соединился через вызов MySQL.connect(). Факультативный параметр: MySQL-строка с символами подстановки (синтаксис аналогичен LIKE).
  • DBH.selectdb(DB_Name[,storage])
    Присоединяет этот объект к специфической базе данных. Выполненные запросы будут направлены к этой базе данных, пока не будет сделано другое обращение метода selectdb. Факультативный параметр storage типа integer может использоваться, чтобы хранить наборы результатов запросов на сервере. Обратите внимание, что это отрицательно воздействует на эффективность сервера, но позволяет клиентуре с маленькой памятью работать с записями по мере надобности. Значение по умолчанию: 0, то есть все записи перемещены пользователю сразу.
  • Table = DBH.listtables([wild])
    Возвращает таблицу с именами таблиц в выбранной базе данных. Имеет силу только после того, как было сделано обращение selectdb. Факультативный параметр может использоваться, чтобы ограничить возвращенный набор таблиц (тот же самый синтаксис, какой принят в LIKE).
  • Table = DBH.listfields(table[,wild])
    Возвращает таблицу описаний полей в данной таблице. Факультативный параметр может использоваться, чтобы ограничить возвращенный набор полей (тот же самый синтаксис, какой принят в LIKE).
  • Table = DBH.listprocesses()
    Возвращает информацию относительно работающих процессов MySQL. Требует соответствующих привилегий (иначе возвращает None).
  • String = DBH.stat()
    Возвращает информацию состояния из MySQL.
  • DBH.create(DB_Definition)
    Создает новую базу данных.
  • DBH.drop(DB_Name)
    Удаляет базу данных.
  • DBH.reload()
    Перезагружает таблицы привилегий MySQL.
  • DBH.shutdown()
    Завершает сервер MySQL.
  • DBH.close()
    Закрывает DB-подключение.
  • String = DBH.clientinfo()
    Возвращает информацию о версии MySQLmodule.
  • String = DBH.serverinfo()
    Возвращает информацию о сервере MySQL.
  • String = DBH.hostinfo()
    Возвращает информацию относительно хоста соединения и типа подключения.
  • Integer = DBH.protoinfo()
    Возвращает информацию о версии протокола MySQL.
  • Table = DBH.do(query) или Table = DBH[query]
    Возвращает результат запроса SQL или число обработанных строк. Оба метода используют тип памяти, установленный в DBH.selectdb().
  • Integer = DBH.insert_id()
    Предоставляет доступ к последнему сгенерированному числу auto_increment. Это число может изменяться, если были запросы между обращениями.
  • STH = DBH.query(query[,storage])
    Возвращает операторный дескриптор для методов курсора (см. ниже). Факультативный параметр storage может использоваться, чтобы отменить значение по умолчанию DBH, установленное DBH.selectdb().

Методы для операторных дескрипторов (STH):

  • Table = STH.fetchrows([n])
    Возвращает результаты запроса к DB. Если n<0, все строки будут выбраны. Иначе будут возвращены только следующие n строк. Значение по умолчанию должно возвратить все строки.
  • Table = STH.fetchdict([n])
    Аналогично STH.fetchrows(), за исключением того, что список словарей возвращен с парами tablename.fieldname:data.
  • Table = STH.fields()
    Возвращает описания поля результата запроса STH. В настоящее время MySQLmodule понимает "pri", "notnull", "auto_inc", "ukey" и "mkey" .
  • STH.seek(n)
    Двигает курсор к строке n (0 определяет первую строку). Доступен только, если результат хранится на стороне пользователя (выбрано в DBH.selectdb). Иначе создает исключительную ситуацию.
  • Integer = STH.numrows()
    Возвращает, сколько строк находятся в результате запроса STH. Предупреждение: в действительности это число отражает сколько записей получил клиент. Для методов хранения на стороне сервера, это начинается с 0 и увеличивается по мере того, как пользователь выбирает строки. Для методов хранения на стороне клиента это число немедленно дает общее количество строк для этого запроса.
  • Integer = STH.numfields()
    Возвращает, сколько столбцов находятся в результате запроса STH.
  • Integer = STH.affectedrows()
    Возвращает данные на сколько строк воздействовал последний запрос. Обратите внимание, что MySQL не всегда возвращает правильное значение.
  • Integer = STH.insert_id()
    Возвращает значение auto_increment из STH-запроса insert. Обратите внимание, что это число постоянно, пока STH существует.
  • Integer = STH.eof()
    Возвратит 1, если последняя строка читалась, иначе 0. Всегда 1, если выбрано хранение данных на стороне пользователя (значение по умолчанию).
Использование модуля MySQL
import MySQL
DBH = MySQL.connect()   # localhost
print DBH.listdbs()
DBH.selectdb('test')
print DBH.serverinfo()
print DBH.stat()
DBH["create table pytest (x int, y int, s char(20))"]
DBH["insert into pytest values (1,2,'abc')"]
DBH.do("insert into pytest values (3,4,'def')")
STH = DBH.query("insert into pytest values (5,6,'ghi')")
print STH.affectedrows()
print DBH['select * from pytest']
STH = DBH.query("select * from pytest")
print STH.numrows()
print STH.fields()
print STH.fetchrows(-1)
STH.seek(0)
print STH.fetchrows(1)
print STH.fetchrows(1)
STH.seek(0)
print STH.fetchrows(2)
print STH.fetchrows(2)
print STH.numfields()
STH.seek(0)
print STH.fetchdict(1)
print STH.fetchdict()
STH = DBH.query("select * from pytest",1)
print STH.fetchdict(1)
print STH.fetchdict() # compare to previous dicts
STH = DBH.query("select * from pytest",1)
print STH.fetchrows(1)
print STH.eof()
print STH.fetchrows()
print STH.eof()
DBH['drop table pytest']
5.6.3 Примечания относительно хранения на сервере

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

Заданный по умолчанию метод в MySQLmodule состоит в том, чтобы использовать хранение на стороне пользователя, то есть все запросы, включая методы курсора (STH), выбирают все данные с сервера. К строкам обращаются через STH.fetchrows(n) или STH.fetchdict(n) индивидуально (n=1), блочно (n>1), все строки забирают одной порцией (n<0) или не обращаются вообще (n=0). STH.numrows() может сообщать после запроса сколько строк находится в результате. STH.seek(k) может использоваться, чтобы обратиться к строкам в произвольном порядке. Недостаток хранения на стороне пользователя состоит в том, что это использует память пользователя, чтобы сохранить все строки. Этот способ учитывает конструкции типа:

STH = DBH.query("select * from Foo")
N = STH.numrows()
if N > 1000: raise Hell,"You must be joking!"
for i in xrange(N):
  [Data] = STH.fetchdict(1)

Так как пользователь действительно переместил к себе все строки, которые подготовил сервер, все транзакции на этом канале прекратились, и сервер готов принять новые команды. Это также означает, что STH.eof() всегда true (1) для хранения данных на стороне клиента.

Хранение на стороне сервера не требует, чтобы у пользователя было много памяти. Все записи будут перемещены на основании запроса. Однако, этот способ имеет несколько недостатков. Так как теперь возникает возможность того, что пользователь не забрал все строки, каждая новая команда должна проверить, является ли свободным, то есть готов ли он принять новую команду. Если нет, команда должна очистить канал команды, выдавая запросы на чтение в количестве, достаточном, чтобы получить оставшиеся строки. MySQL API 3.21 не предлагает команды abort(). STH.numrows() не знает ничего относительно того, сколько строк были выбраны запросом, так что вышеупомянутый код примера будет падать. STH.numrows() будет, однако, модифицироваться, поскольку строки все-таки читаются, например:

STH = DBH.query("select * from Foo")
Data = STH.fetchrows(-1)
print "Got",STH.numrows(),"rows."   # len(Data) is the same

STH.eof() имеет смысл только при хранении данных на сервере, но даже здесь такой код полезен не всегда:

STH = DBH.query("select 1")
print STH.eof()          # will print 0
Data = STH.fetchrows(1)  # retrieve the row
print STH.eof()          # still 0 :-(
Data = STH.fetchrows(1)  # must repeat. Data will be []
print STH.eof()          # now we get 1, but we already
                         # knew that we've hit the end

Можно было рассматривать это, как ошибку. STH.seek(k) больше не доступен и создает исключение ("cannot seek on server"), то есть строки должны теперь читаться последовательно.

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

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

STH = DBH.query("select * from Foo",1) # use server side storage
Tables = DBH.listtables()              # stomp on previous results
Data = STH.fetchrows()                 # nothing here anymore vs.
STH = DBH.query("select * from Foo",0) # use client side storage
Tables = DBH.listtables()              # won't interfere
Data = STH.fetchrows()                 # no problem...

Хранение на стороне сервера также создает более сложный код в MySQLmodule. Обычно при хранении на стороне клиента STH-курсоры независимы от дескриптора базы данных. Немедленно после запроса все данные будут перекачаны клиенту, и пользователь может делать все, что сочтет необходимым с дескриптором DBH. Но при хранении на стороне сервера это становится сложным. С курсорами стороны сервера указатель на дескриптор сохранен в дескрипторе STH. MySQLmodule удостоверится, что этот кусок памяти не освобожден прежде, чем закроются все ожидающие обработки курсоры. Это означает, что mysql_close() не обязательно вызван, если база данных, обрабатываемая DBH, разрушена:

DBH = MySQL.connect()         # get a DB handle
STH = DBH.query("select 1",1) # server side cursor
del DBH                       # mysql_close() *not* called
STH.fetchrows()               # will succeed!
del STH                       # now mysql_close() will be called
                              # in DBH_dealloc()

Если Вы должны закрыть дескриптор DB немедленно, используйте DBH.close(). Все дальнейшие попытки работать на этом дескрипторе (даже ожидающие обработки курсоры стороны сервера) получат исключительную ситуацию "... server has gone away". Начиная с того момента, как mySQL не может принимать команды из последовательности, все DBH-методы должны проверить незавершенные STH-курсоры. Чтобы обращаться к ним, дескриптор DBH хранит указатель на STH-курсор.

5.6.4 Установка MySQLmodule-1.4 под Windows NT

Следующие инструкции основаны на информации, предоставленной Nigel Head (nhead@houbits.com).

  • Вы должны получить файл libMySQL.dll из клиентского пакета win32-mysql версии 3.22.8 или выше, более ранние версии не будут работать. Это доступно на www.tcx.se (или зеркалах) для свободной загрузки. Вы должны, вероятно, переместить файл в то же самое расположение, что и Ваша библиотека python15.dll.
  • Скомпилируйте MySQLmodule-1.4 с включенным переключателем WIN32. VC5 и файлы проекта MySQL.dsp и MySQL.dsw включены (но, вероятно, их придется изменять, чтобы удовлетворить требованиям Вашей среды).
  • Переместите возникающий в результате файл MySQL.pyd в Ваш каталог Python DLL.

Если что-то пойдет не так, помощь лучше всего поискать в конференции comp.lang.python.

содержание       назад       вперед

Скидка до 20% на услуги дата-центра. Аренда серверной стойки. Colocation от 1U!

Миграция в облако #SotelCloud. Виртуальный сервер в облаке. Выбрать конфигурацию на сайте!

Виртуальная АТС для вашего бизнеса. Приветственные бонусы для новых клиентов!

Виртуальные VPS серверы в РФ и ЕС

Dedicated серверы в РФ и ЕС

По промокоду CITFORUM скидка 30% на заказ VPS\VDS

VPS/VDS серверы. 30 локаций на выбор

Серверы VPS/VDS с большим диском

Хорошие условия для реселлеров

4VPS.SU - VPS в 17-ти странах

2Gbit/s безлимит

Современное железо!

Новости мира IT:

Архив новостей

IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware

Информация для рекламодателей PR-акции, размещение рекламы — adv@citforum.ru,
тел. +7 495 7861149
Пресс-релизы — pr@citforum.ru
Обратная связь
Информация для авторов
Rambler's Top100 TopList liveinternet.ru: показано число просмотров за 24 часа, посетителей за 24 часа и за сегодня This Web server launched on February 24, 1997
Copyright © 1997-2000 CIT, © 2001-2019 CIT Forum
Внимание! Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав. Подробнее...