Top.Mail.Ru
? ?

Entries by tag: mysql

Solr + MySQL

"Если бы губы Никанора Ивановича да приставить к носу Ивана Кузьмича, да взять сколь-нибудь развязанное, какая у Балтазара Балтазаровича, да, пожалуй, прибавить к этому еще дородности Ивана Павловича — я бы тогда тотчас же решилась. А теперь — поди подумай!"
Н. В. Гоголь, "Женитьба"
Замечательная штука -- искать инструкции по установке чего-нибудь эдакого в интернете. Часто приходится собирать информацию по кускам из двух-трёх описаний одного и того же. Вот и со связкой Solr + MySQL получилось тоже самое.
За основу были взяты два описания: "Using Solr / Lucene for full text search with MySQL DB"  и "Apache Solr MySQL Sample Data Config". Плюс к этому множество форумов и багрепортов, ибо и Solr, и MySQL -- штуки местами удивительные и непредсказуемые.
Свои нечеловеческие эксперименты в области full-text поиска я начал с создания базы данных и таблицы, которые и будут являться хранилищем требуемых данных:
mysql> CREATE DATABASE solrdb;
mysql> USE solrdb;
mysql> CREATE TABLE `jos_content` (
> `id` bigint(20) NOT NULL AUTO_INCREMENT,
> `state` tinyint(3) unsigned NOT NULL DEFAULT '0',
> `title` char(10) DEFAULT NULL,
> `introtext` text,
> `ftext` text,
> PRIMARY KEY (`id`)
> ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

mysql> INSERT INTO jos_content VALUES(null, 1, a', 'intro1', 'ft1');
mysql> INSERT INTO jos_content VALUES(null, 1, 'b', 'intro2', 'ft2');
mysql> INSERT INTO jos_content VALUES(null, 1, 'c', 'intro3', 'ft3');
 
Следующий пункт программы -- это добыча подходящего MySQL JDBC-драйвера. Драйвера с версией младше 5.1.7 не подходят, поскольку не умеют работать с UTF8, в случае их использования JDBC-драйвер сгенерирует исключение java.sql.SQLException с загадочным обоснованием вида: "Unknown initial character set index '192' received from server. Initial client character set can be forced via the 'characterEncoding' property.". Во избежание проблем берётся самый последний из предлагаемого списка драйверов.

После того как драйвер найден, его необходимо положить в правильное место. "Правильным местом" является каталог /lib контейнера сервлетов или web-сервера, а не одноимённый каталог в домашней директории Solr. В противном случае ищите в логах запись про отсутствующий драйвер.

Дальше действия выполняются почти, как указано в инструкциях.
1. Создаётся конфигурационный xml-файл для работы с базой данных, я назвал его dataimport.xml. Поскольку я развлекался с прилагаемым к Solr демо-приложением и, опять же, прилагаемом контейнером сервлетов Jetty, то файл я разместил в <SOLR_HOME>/example/solr/conf. Вот его содержимое:
<?xml version="1.0" encoding="UTF-8"?>
  <dataConfig>
    <dataSource type="JdbcDataSource"
      driver="com.mysql.jdbc.Driver"
      url="jdbc:mysql://localhost/solrdb"
      user="root"
      password="11111111"/>

    <document name="doc">
        <entity name="jos_content" query="select * from jos_content WHERE state=1">
        <field column="id" name="id" />
        <field column="title" name="title" />
        <field column="introtext" name="introtext" />
        <field column="ftext" name="ftext" />
      </entity>
  </document>
</dataConfig>

2. В конфигурационный файл <SOLR_HOME>/example/solr/conf/solrconfig.xml добавляются настройки для выполнения импорта данных из базы:
<requestHandler name="/dataimport" class="org.apache.solr.handler.dataimport.DataImportHandler">
  <lst name="defaults">
    <str name="config">dataimport.xml</str>
  </lst>
</requestHandler>

3. В том же каталоге правлю schema.xml, меняю(добавляю) текущее содержимое тэгов fields, uniqueKey и defaultSearchField:
<fields>
  <field name="id" type="string" indexed="true" stored="true" required="true"/>
  <field name="title" type="text" indexed="true" stored="true" required="true"/>
  <field name="introtext" type="text" indexed="true" stored="true" required="true"/>
  <field name="ftext" type="text" indexed="true" stored="true" required="true"/>
  <dynamicField name="*" type="ignored" />
</fields>

<uniqueKey>id</uniqueKey>

<defaultSearchField>ftext</defaultSearchField>

4. Перезапускаю Solr: java -jar start.jar

5. Проверяю состояние и импортирую данные.
http://localhost:8983/solr/dataimport
http://localhost:8983/solr/dataimport?command=delta-import

6. Выполняю запрос.
http://localhost:8983/solr/select/?q=id:1

Tags:

RoR & lol. Продолжение

Продолжаю развлекаться с RoR.
Поскольку использовать sqlite неинтересно,
решил заправить какую-нибудь другую СУБД,
например MySQL.


После непродолжительного, но яркого секса сделал следующие выводы:
1. Устанавливать всякие gem лучше через rvm (Ruby Version Manager).
В этом случае вероятность ошибок, выдаваемых gem, падает в разы.
С gem для установки mysql я вообще совладать не смог.
Он ругался и на отсутствие native libraries, потом сказал, мол не могу получить доступ к памяти,
пару раз ложился с суровым некрологом "Segmentation fault". Так что rvm, однозначно.
Да, поставить rvm с помощью gem мне тоже не удалось, пришлось тащить из git-репозитория.
Соответственно, для rvm, понадобится ещё и git.
2. При генерации базы данных возможны неочевидные ошибки.
Так мне выдалось сообщение, цитирую:
  $ sudo rake --trace db:create
  ...
  ** Invoke db:create (first_time)
  ** Invoke db:load_config (first_time)
  ** Invoke rails_env (first_time)
  ** Execute rails_env
  ** Execute db:load_config
  ** Execute db:create
  rake aborted!
  can't convert Fixnum into String
  ...

Ошибка обнаружилась в config/database.yml:
...
username: root
password: 123
...
Чего же такого плохого в этом файле? А вот чего -- пароль доступа к базе воспринят как число, вместо строки, лечится заключением в двойные кавычки. При этом, будь это строка, кавычек не потребовалось бы. Так что be careful, внимательно читайте маны и stackoverflow.com :-)

Теперь о хорошем. Процесс разработки пока что оставляет положительные впечатления и не кажется трудным.
Отдыхаю после си и жаб и жду появления граблей. :-)
Один из наших сервисов использует самописный клиент MySQL,
который осуществляет периодический сброс статистики в базу.
Его задача очень простая:
1. проверить состояние соединения с СУБД.
2. если всё Ok, выполнить необходимые запросы.
3. ждать в течение заданного таймаута и повторить п.1,2.
Клиент и сервер MySQL находятся на разных хостах.
Функционал клиента выглядит примерно так:

static MYSQL *db;

static void db_disconnect() {
  if (db == NULL) return;
  mysql_close(db);
  db = NULL;
}

static int db_connect() {
  if (db)
    return 1;
  db = mysql_init(NULL);
  if (db == NULL) {
    log_w("Could not initialize db");
    return 0;
  }
  if (mysql_real_connect(db, ..., NULL, 0) == NULL){
    log_w("Connect MySQL failed: %s\n", mysql_error(db));
    db_disconnect();
    return 0;
  }
  log_w("DB (%s@%s) connect OK", ssrv_config.db_user, ssrv_config.db_name);
  return 1;
}

static int check_db() {
  if (db && (mysql_stat(db) == NULL)){
    log_w("DBconnection closed");
    db_disconnect();
  }
  if (!db)
    db_connect();
  if (!db)return 0;
    return 1;
}

void flush_stat() {
  if (!check_db())
    return;
  for (...){
    // SQL queries
    ...
  }
}

План тестирования.
1. Ограничения со стороны СУБД.
  1.1. Отобрать привилегии у пользователя СУБД и убедиться, что база становится недоступной клиенту.
  1.2. Назначить все необходимые привилегии пользователю посредством и убедиться, что соединение с базой восстановлено.

2. Ограничение со стороны FW.
В качестве FW использовался iptables.
Необходимо закрывать/открывать порт соединения с базой и исследовать результаты.
  2.1. Порт закрывается до работы клиента.
  2.2. Порт закрывается/открывается во время работы клиента.

Основные проблемы обнаружились в MySQL-API.
Смотрим ещё раз на check_db();

static int check_db() {
  if (db && (mysql_stat(db) == NULL)){
    log_w("DBconnection closed");
    db_disconnect();
  }
  if (!db)
    db_connect();
  if (!db)
    return 0;
  return 1;
}

Проблема первая: mysql_stat возвращает результат на момент соединения и далее не меняет своего значения.
Замена mysql_stat на mysql_ping привела к зависанию из-за большого таймаута соединения (mysql_ping, как известно, пытается восстанавливать соединение самостоятельно) на условии проверки.

Очевидным решением казалось применение опции таймаута соединения:

#define DBCONNECTION_TIMEOUT 5
...
static int db_connect() {
  unsigned int timeout = DBCONNECTION_TIMEOUT;
  ...
  if(mysql_options(db, MYSQL_OPT_CONNECT_TIMEOUT, &timeout)){
    log_w("Set options MySQL failed: %s\n", mysql_error(db));
  }
  ...
}


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

В результате пришлось оторвать проверку напрочь, а функция flash_stat() стала выглядеть следующим образом:

void flush_stat() {
  if (!db_connect())
    return;
  for (...) {
    // SQL queries
    ...
  }
  db_disconnect();
}

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

Результаты тестирования.
1. Тестирование доступа к базе на стороне MySQL Server:
1.1.REVOKE ALL PRIVILEGES ON database FROM 'user'@'host';
  Записи в логе клиента:
  [28.05.2010 19:42:55] flush stat
  [28.05.2010 19:42:55] DBconnection closed
  [28.05.2010 19:43:00] Connect MySQL failed: Can't connect to MySQL server on 'host'

1.2.GRANT ALL PRIVILEGES ON reklama TO 'user'@'host'
  Записи в логе клиента:
  [28.05.2010 19:43:55] flush stat
  [28.05.2010 19:43:55] DB (user@database) connect OK
  [28.05.2010 19:43:55] flush stat OK

2. Тестирование через FW
2.1.
  Закрываем порт соединения с базой и запускаем клиент:
  /etc/init.d/iptables restart
  iptables -A OUTPUT -p TCP --dport 3306 -j DROP
  Проверяем, что получилось командой iptables -L -n -v
  Записи в логе клиента:
  [28.05.2010 19:42:55] flush stat
  [28.05.2010 19:42:55] DBconnection closed
  [28.05.2010 19:43:00] Connect MySQL failed: Can't connect to MySQL server on 'host'

  Открываем порт соединения с базой
  iptables -D OUTPUT -p TCP --dport 3306 -j DROP
  Записи в логе клиента:
  [28.05.2010 19:43:55] flush stat
  [28.05.2010 19:43:55] DB (user@database) connect OK
  [28.05.2010 19:43:55] flush stat OK

2.2 Повторяем п.2.1., но при работающем клиенте. Результат аналогичен предыдущему.

Мораль этой басни не нова: be careful, при использовании MySQL-API.

Tags:

HackMySQL Tools

'mysqlreport is a Perl script that examines the server’s SHOW STATUS output, transforms it into an easy-to-read report, and prints it out. You can read this report much more quickly than you can examine SHOW STATUS, and it is quite thorough.' High Performance MySQL, SECOND EDITION.

Архив с запакованным скриптом располагается на ресурсе HackMySQL.
Установка Perl под Windows
  1. Выбираем подходящий порт на ресурсе CPAN. В данном случае это ActivePerl на www.activestate.com. Версия выбирается с учётом того, что в ней должен присутствовать модуль DBD::mysql. На текущий момент - это версия 'ActivePerl 5.8.9.826', в более поздней, 5.10.0.1005, модуль отсутствует.
  2. Скачиваем msi-пакет и устанавливаем.
  3. Теперь необходимо добавить модуль MySQL. В командной строке вводим ppm-shell или запускаем <путь к Perl>/bin/ppm-shell.bat:
    ppm> search DBD
    в отображаемом списке должен присутствовать DBD-mysql
    ppm> install DBD-mysql
    ppm>quit
Проверка работоспособности.
Переходим в каталог, где установлен mysqlreport, выполняем команду:
>perl mysqlreport

Склерозник:
ekimoff.ru/download/high-performance-mysql-second-edition.pdf
www.cpan.org/
www.internet-technologies.ru/articles/article_294.html
forum.dklab.ru/viewtopic.php

Profile

Image
Imagecpplang
cpplang

Latest Month

January 2020
S M T W T F S
   1234
567891011
12131415161718
19202122232425
262728293031 

Tags

Syndicate

RSS Atom

Comments

  • cpplang
    11 Jul 2012, 07:04
    Спасибо =) я знаю intuit, очень крутой сервис. тока я по ключам его настроила => а задача была по сертификатам =(, у меня как раз не выходит центр сертификации установить на мой сервер.

    но статья…
  • cpplang
    10 Jul 2012, 10:08
    Ничего подобного, наоборот, удивляюсь.

    Кстати, есть такая классная тётка, Лапонина Ольга Германовна, она в МГУ преподаёт. У неё есть учебник по протоколам безопасного сетевого взаимодействия, и там…
  • cpplang
    10 Jul 2012, 07:20
    чувствую нотки сарказма в ваших словах...

    нет, на винде.
  • cpplang
    9 Jul 2012, 20:15
    ipsec? вот это да, круть какая. не на FreeBSD случаем?
  • cpplang
    9 Jul 2012, 07:19
    на данный момент, пытаюсь настроить ipsec между машинами.

    Извините за глупые вопросы, если что.
Powered by LiveJournal.com
Designed by Emile Ong
Image