libmysqld, встраиваемая библиотека сервера MySQL
Обзор библиотеки встраиваемого сервера MySQL
Библиотека встраиваемого сервера MySQL обеспечивает возможность запуска полнофункционального сервера MySQL внутри клиентского приложения. Основные преимущества, которые дает ее использование, - увеличение скорости и более простое управление для встраиваемых приложений.
Интерфейсы API для встраиваемой версии MySQL и для версии клиент/сервер идентичны. Чтобы реализовать возможность использования встраиваемого сервера в старом приложении с потоками, обычно необходимо только добавить вызовы следующих функций:
Функция | Когда вызывается | mysql_server_init() | Должна вызываться перед любой другой функцией MySQL, предпочтительно раньше, чем функция main(). | mysql_server_end() | Должна вызываться перед выходом из данной программы. | mysql_thread_init() | Должна вызываться в каждом создаваемом потоке, который будет работать с MySQL. | mysql_thread_end() | Должна вызываться перед вызовом pthread_exit() |
После добавления функций необходимо связать данный код с библиотекой 'libmysqld.a' вместо 'libmysqlclient.a'.
Вышеприведенные функции типа mysql_server_xxx также включены в 'libmysqlclient.a' - таким образом обеспечивается возможность переключаться между встраиваемой и клиент-серверной версиями просто линкованием конкретного приложения с соответствующей библиотекой. См. раздел 1 mysql_server_init() .
Компиляция программ с libmysqld
Чтобы получить библиотеку libmysqld , необходимо сконфигурировать (при помощи configure ) сборку MySQL с опцией --with-embedded-server .
При связывании программы с libmysqld необходимо также включать специфические для данной системы библиотеки pthread и другие библиотеки, используемые сервером MySQL. Полный список библиотек можно получить, выполнив mysql_config --libmysqld-libs .
Для компиляции и связывания должны использоваться флаги компиляции потоковой программы, даже если никакие потоковые функции в данном коде явно не вызываются.
Ограничения при использовании встраиваемого сервера MySQL
Bстраиваемый сервер имеет следующие ограничения:
Не поддерживает таблицы ISAM (это сделано главным образом для уменьшения размеров библиотеки)
Не поддерживает функции UDF (функции, определяемые пользователем).
Не отслеживаются стеки на дампе оперативной памяти.
Нет внутренней поддержки RAID (обычно этого не требуется, так как большинство операционных систем в настоящее время имеют поддержку для больших файлов).
встраиваемый сервер MySQL нельзя установить как головной или подчиненный сервер репликации
К встраиваемому серверу нельзя подсоединиться из внешнего процесса через сокеты или по протоколу TCP/IP.
Некоторые из этих ограничений могут быть изменены путем редактирования включаемого файла 'mysql_embed.h' и перекомпилирования MySQL.
Использование файлов опций с встраиваемым сервером
Ниже приводятся рекомендации по использованию файлов опций для облегчения перехода между клиент-серверным приложением и приложением с встраиваемым MySQL (см. раздел Файлы параметров 'my.cnf').
Следует помещать общие опции в раздел [server] . Они будут читаться обеими версиями MySQL.
Следует помещать специфические клиент-серверные опции в раздел [mysqld] .
Следует помещать специфические опции встраиваемого MySQL в раздел [embedded] .
Следует помещать специфические опции приложения в раздел [ApplicationName_SERVER] .
Что осталось сделать по встраиваемомуому серверу (TODO)
В настоящее время поставляется только статическая версия библиотеки mysqld , в будущем будет поставляться также и динамическая библиотека.
Предполагается обеспечить возможность не включать некоторые части MySQL, чтобы сделать библиотеку меньше.
Многое еще нужно сделать для оптимизации скорости.
Ошибки записываются в stderr . Предполагается добавить возможность указывать для них имя файла.
Необходимо изменить InnoDB, чтобы вывод этого обработчика не был бы настолько подробным во встраиваемой версии.
Пример простого встраиваемого сервера
Этот пример программы и сборочного файла должен работать без каких-либо изменений под операционными системами Linux или FreeBSD. Для других операционных систем потребуются небольшие изменения. При разработке данного примера мы ставили перед собой цель предоставить достаточно информации для понимания рассматриваемой темы и в то же время не перегружать текст руководства лишними деталями, специфическими для реального приложения.
Чтобы запустить этот пример, создайте каталог 'test_libmysqld' там же, где находится каталог исходного кода mysql-4.0. Сохраните исходный код 'test_libmysqld.c' и 'GNUmakefile' в данном каталоге и запустите GNU 'make' в каталоге 'test_libmysqld'.
'test_libmysqld.c'
/* * Клиент простого примера с использованием библиотеки встраиваемого сервера MySQL */ #include #include #include #include
MYSQL *db_connect(const char *dbname); void db_disconnect(MYSQL *db); void db_do_query(MYSQL *db, const char *query);
const char *server_groups[] = { "test_libmysqld_SERVER", "embedded", "server", NULL };
int main(int argc, char **argv) { MYSQL *one, *two; /* Функцию mysql_server_init() необходимо вызывать перед любыми другими * функциями mysql. * Можно задать mysql_server_init(0, NULL, NULL); тогда для * инициализации сервера будут использоваться группы "server", * "embedded", NULL *}. * * В файле $HOME/.my.cnf можно указать:
[test_libmysqld_SERVER] language = /path/to/source/of/mysql/sql/share/english
* Можно было бы, конечно, модифицировать argc и argv непосредственно * перед передачей их в эту функцию или создать * новые аргументы - для этого годится любой выбранный вами способ. * Однако все аргументы в argv (кроме argv[0], который * представляет собой имя программы) должны быть допустимыми опциями * для сервера MySQL. * * Если данный клиент линкуется с нормальной библиотекой mysqlclient, * то эта функция является просто заглушкой, ничего не делающей. */
mysql_server_init(argc, argv, (char **)server_groups); one = db_connect("test"); two = db_connect(NULL); db_do_query(one, "SHOW TABLE STATUS"); db_do_query(two, "SHOW DATABASES"); mysql_close(two); mysql_close(one);
/* Эта функция должна вызываться после всех других функций mysql */
mysql_server_end(); exit(EXIT_SUCCESS);
}
static void die(MYSQL *db, char *fmt, ...) { va_list ap; va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); (void)putc('\n', stderr); if (db) db_disconnect(db); exit(EXIT_FAILURE); }
MYSQL * db_connect(const char *dbname) { MYSQL *db = mysql_init(NULL); if (!db) die(db, "mysql_init failed: no memory");
/* * Обратите внимание: клиент и сервер используют разные имена групп. * Это обязательное условие, поскольку сервер не должен использовать опции * клиента и наоборот. */
mysql_options(db, MYSQL_READ_DEFAULT_GROUP, "test_libmysqld_CLIENT"); if (!mysql_real_connect(db, NULL, NULL, NULL, dbname, 0, NULL, 0)) die(db, "mysql_real_connect failed: %s", mysql_error(db)); return db; }
void db_disconnect(MYSQL *db) { mysql_close(db); }
void db_do_query(MYSQL *db, const char *query) { if (mysql_query(db, query) != 0) goto err; if (mysql_field_count(db) > 0) { MYSQL_RES *res; MYSQL_ROW row, end_row; int num_fields; if (!(res = mysql_store_result(db))) goto err; num_fields = mysql_num_fields(res); while ((row = mysql_fetch_row(res))) { (void)fputs(">> ", stdout); for (end_row = row + num_fields; row < end_row; ++row) (void)printf("%s\t", row ? (char*)*row : "NULL"); (void)fputc('\n', stdout); } (void)fputc('\n', stdout); } else (void)printf("Affected rows: %lld\n", mysql_affected_rows(db)); return; err: die(db, "db_do_query failed: %s [%s]", mysql_error(db), query); }
'GNUmakefile'
# Предполагается, что программное обеспечение MySQL установлено в #/usr/local/mysql
inc := /usr/local/mysql/include/mysql lib := /usr/local/mysql/lib
# Если программное обеспечение MySQL еще не установлено, сделайте такую замену:
#inc := $(HOME)/mysql-4.0/include #lib := $(HOME)/mysql-4.0/libmysqld
CC := gcc CPPFLAGS := -I$(inc) -D_THREAD_SAFE -D_REENTRANT CFLAGS := -g -W -Wall LDFLAGS := -static
# Можно изменить -lmysqld на -lmysqlclient для того, чтобы использовать # обычную клиент-серверную библиотеку
LDLIBS = -L$(lib) -lmysqld -lz -lm -lcrypt ifneq (,$(shell grep FreeBSD /COPYRIGHT 2>/dev/null))
# Для FreeBSD
LDFLAGS += -pthread else
# Предполагается Linux
LDLIBS += -lpthread endif
# Это работает для простых однофайловых тестовых программ
sources := $(wildcard *.c) objects := $(patsubst %c,%o,$(sources)) targets := $(basename $(sources)) all: $(targets) clean: rm -f $(targets) $(objects) *.core
Лицензирование встраиваемого сервера
Исходный код MySQL подпадает под действие лицензии GNU GPL. Одно из следствий этого заключается в том, что любая программа, включающая (посредством связывания с libmysqld ) исходный код MySQL, должна выпускаться как открытое программное обеспечение (под лицензией, совместимой с GPL).
Мы стараемся всячески способствовать всем, кто распространяет открытое программное обеспечение, выпуская код под GPL или совместимой лицензией. Для тех же, кому эти условия не подходят, существует другая возможность - покупка коммерческой лицензии для кода MySQL у компании MySQL AB. Более подробная информация об этом находится в разделе Лицензии на ПО MySQL.
1 2 3 4 5 6
8 8 8
| |