YAMAGUCHI::weblog

海水パンツとゴーグルで、巨万の富を築きました。カリブの怪物、フリーアルバイター瞳です。

Mac OS X 10.8にMySQL 5.5.29+HandlerSocketをインストールする

はじめに

こんにちは、久々のPython界の情弱です。いままでMySQLLinuxでパッケージでぶち込むくらいでしか入れたことなかったので手元に入れてみた。意外と一気通貫な情報が見つからなかったのでログ用にメモ。 あと今日からはてなブログはMarkdownで書きます。

MySQLのインストール

MacPorts経由でインストールする

clangのバグのおかげでビルドが出来ない模様なのでパス。

ビルド済みtarballを使う

tarball取得

MySQL Community Serverを取得(要Oracle Webアカウント)

ディレクトリ作成

適当にディレクトリを作成。

% mkdir -p /opt/mysql/5.5
% mkdir -p /opt/mysql/data
% tar xzf mysql-5.5.29-osx10.6-x86_64.tar.gz
% mv mysql-5.5.29-osx10.6-x86_64 /opt/mysql/5.5

インストール

ここ読んでやってます。

% $basedir/scripts/mysql_install_db --user=$USER --basedir=/opt/mysql/5.5 --datadir=/opt/mysql/data --tmpdir=/tmp
Installing MySQL system tables...
OK
Filling help tables...
OK

To start mysqld at boot time you have to copy
support-files/mysql.server to the right place for your system

PLEASE REMEMBER TO SET A PASSWORD FOR THE MySQL root USER !
To do so, start the server, then issue the following commands:

/opt/mysql/5.5/bin/mysqladmin -u root password 'new-password'
/opt/mysql/5.5/bin/mysqladmin -u root -h dhcp-172-23-72-225.tok.corp.google.com password 'new-password'

Alternatively you can run:
/opt/mysql/5.5/bin/mysql_secure_installation

which will also give you the option of removing the test
databases and anonymous user created by default.  This is
strongly recommended for production servers.

See the manual for more instructions.

You can start the MySQL daemon with:
cd /opt/mysql/5.5 ; /opt/mysql/5.5/bin/mysqld_safe &

You can test the MySQL daemon with mysql-test-run.pl
cd /opt/mysql/5.5/mysql-test ; perl mysql-test-run.pl

Please report any problems with the /opt/mysql/5.5/scripts/mysqlbug script!

mysql.serverを変更する

% diff -u ./support-files/mysql.server{.orig,}
--- ./support-files/mysql.server.orig	2013-01-24 13:25:57.000000000 +0900
+++ ./support-files/mysql.server	2013-01-24 13:27:17.000000000 +0900
@@ -43,8 +43,8 @@
 # If you change base dir, you must also change datadir. These may get
 # overwritten by settings in the MySQL configuration files.
 
-basedir=
-datadir=
+basedir=/opt/mysql/5.5
+datadir=/opt/mysql/data

my.cnfのテンプレに文字コードの設定をしておく。

[client]
port		= 3306
socket	= /opt/mysql/data/mysql.sock
default-character-set = utf8

[mysqld]
port		= 3306
socket	= /opt/mysql/data/mysql.sock
skip-external-locking
key_buffer_size = 384M
max_allowed_packet = 1M
table_open_cache = 512
sort_buffer_size = 2M
read_buffer_size = 2M
read_rnd_buffer_size = 8M
myisam_sort_buffer_size = 64M
thread_cache_size = 8
query_cache_size = 32M
thread_concurrency = 8
skip-character-set-client-handshake
character-set-server = utf8
collation-server = utf8_general_ci
log-bin=mysql-bin
server-id	= 1

[mysqldump]
quick
max_allowed_packet = 16M
default-character-set = utf8

[mysql]
no-auto-rehash
default-character-set = utf8

[myisamchk]
key_buffer_size = 256M
sort_buffer_size = 256M
read_buffer = 2M
write_buffer = 2M

[mysqlhotcopy]
interactive-timeout

my.cnfが読み込み場所に設定しておく。今回は /etc/my.cnf としておいた。

% $basedir/bin/mysql --help | grep my.cnf
/etc/my.cnf /etc/mysql/my.cnf /usr/local/mysql/etc/my.cnf ~/.my.cnf 
% sudo cp $basedir/support-files/my-huge.cnf /etc/my.cnf
% sudo chown ymotongpoo /etc/my.cnf

MySQL起動

% $basedir/support-files/mysql.server start
Starting MySQL
.. SUCCESS!

MySQL adminの設定をする

% $basedir/bin/mysqladmin -u root -h <hostname> password 'welcome1'

HandlerSocketのインストール

ソースコードのダウンロード

今度はソースコードを落としてきて適当な場所に展開しておく。

% tar xzf mysql-5.5.29.tar.gz /tmp/

HandlerSocket plugin for MySQLをビルド&インストール

DeNAの皆さんありがとう。

% git clone https://github.com/DeNADev/HandlerSocket-Plugin-for-MySQL.git
% ./configure --with-mysql-source=/tmp/mysql-5.5.29 --with-mysql-bindir=/opt/mysql/5.5/bin --with-mysql-plugindir=/opt/mysql/5.5/lib/plugin
% make
% sudo make install

ライブラリファイルは置かれてるので、my.cnfを編集した後MySQLに読み込ませる。下の設定はインストールドキュメントにあったものをとりあえずで設定してます。

[mysqld]
handlersocket_port = 9998
handlersocket_port_wr = 9999
handlersocket_address =
handlersocket_verbose = 0
handlersocket_timeout = 300
handlersocket_threads = 16
thread_concurrency = 128
open_files_limit = 65535

こうした後にMySQLでreload

% $basedir/support-files/mysql.server reload 

MySQLに読み込ませる。

% mysql -u root -p
mysql> install plugin handlersocket soname 'handlersocket.so';
mysql> show plugins;
+--------------------------+----------+--------------------+------------------+---------+
| Name                     | Status   | Type               | Library          | License |
+--------------------------+----------+--------------------+------------------+---------+
| binlog                   | ACTIVE   | STORAGE ENGINE     | NULL             | GPL     |
                                              ...
| INNODB_BUFFER_PAGE_LRU   | ACTIVE   | INFORMATION SCHEMA | NULL             | GPL     |
| INNODB_BUFFER_POOL_STATS | ACTIVE   | INFORMATION SCHEMA | NULL             | GPL     |
| PERFORMANCE_SCHEMA       | ACTIVE   | STORAGE ENGINE     | NULL             | GPL     |
| partition                | ACTIVE   | STORAGE ENGINE     | NULL             | GPL     |
| handlersocket            | ACTIVE   | DAEMON             | handlersocket.so | BSD     |
+--------------------------+----------+--------------------+------------------+---------+

テスト

テーブルを適当に作る。

mysql> use test;
mysql> CREATE TABLE `user` (
    `user_id` INT(10) NOT NULL AUTO_INCREMENT,
    `name` VARCHAR(255) NULL DEFAULT NULL,
    `last_update` DATE NULL DEFAULT NULL,
    `memo` VARCHAR(255) NULL DEFAULT NULL,
    PRIMARY KEY (`user_id`)
);

python-handler-socketを使ってデータを投入したり参照したりしてみる。

test.py という名前で次のコードを保存して実行。

from pyhs import Manager

DB_NAME = 'test'
TABLE_NAME = 'user'

hs = Manager(
    read_servers=[('inet', 'localhost', 9998)],
    write_servers=[('inet', 'localhost', 9999)],
    debug=False)

hs.insert(DB_NAME, TABLE_NAME,
          [('name', "bucho"), ('last_update', "2013-01-25"), ('memo', "torumemo")]);
hs.insert(DB_NAME, TABLE_NAME,
          [('name', "xaxtsuxo"), ('last_update', "2013-01-26"), ('memo', "pep3138")]);
hs.insert(DB_NAME, TABLE_NAME,
          [('name', "wozozo"), ('last_update', "2013-01-27"), ('memo', "buy out")]);

res = hs.get(DB_NAME, TABLE_NAME, 
             ['name', 'last_update', 'memo'], 1)
print("get:")
print(res)

res = hs.find(DB_NAME, TABLE_NAME, 
              '>=', ['name', 'last_update', 'memo'], ['2'], 'PRIMARY', 10)
print("find:")
print(res)

実行してみる。

% python test.py
get:
[('name', 'bucho'), ('last_update', '2013-01-25'), ('memo', 'torumemo')]
find:
[[('name', 'xaxtsuxo'), ('last_update', '2013-01-26'), ('memo', 'pep3138')], [('name', 'wozozo'), ('last_update', '2013-01-27'), ('memo', 'buy out')]]

ちゃんと入ってるか確認。

mysql> select * from user;
+---------+----------+-------------+----------+
| user_id | name     | last_update | memo     |
+---------+----------+-------------+----------+
|       1 | bucho    | 2013-01-25  | torumemo |
|       2 | xaxtsuxo | 2013-01-26  | pep3138  |
|       3 | wozozo   | 2013-01-27  | buy out  |
+---------+----------+-------------+----------+