新しいサイトを作る時
のMySQL(大規模風味)
2012/06/27 Wed
@Spring_MT
自己紹介
 twitter id : Spring_MT
 10xlabという会社で働いています

 転職して福岡に来たばっかりです

 インフラ、アプリと色々見ています

初心者なので皆様お手柔らかにお願いします
まず
今やっているプロジェクトのMySQL
の構成についてお話します

結構大規模になってくれることを想定
しています
基本構成
基本構成
version : 5.5系

Engine : InnoDB(基本的に)

文字コード : UTF8

複数DBかつレプリする

 初心者なので黙ってUTF8
         http://www.slideshare.net/tmtm/mysql-13117441
SJISだと5C問題とかが

Shift_JISの2バイト目が0x5C()である
ことに起因する問題。

「表」とか死ぬ。

セキュリティホールにもなりうる。
Collation(照合順序、ソート順)

      collation                                      details             Ex

                                               ASCII/ラテン文字の大文字小文字
   utf8_general_ci             デフォルト
                                               を区別しない
                                                                         A=a



       utf8_bin                                全ての文字を区別する                A!=a


                                               大文字/小文字/全角/半角/カタカ        a=A=A
 utf8_unicode_ci                               ナ/ひらが な/濁音を区別しない     は=ば=ぱ=ハ=バ=パ=ハ

collationは20種類以上あるのでここでは代表的なものを出しています

参照 :http://www.slideshare.net/tmtm/mysql-13117441
日付と時刻
特殊な振る舞いはともかく、TIMESTAMPは
DATATIMEよりもストレージ効率がよいため、
TIMESTAMPを使用できる場合は一般にそれを使用
すべきである。UNIXのタイムスタンプを整数値と
して格納することもあるが、通常はそうしたとこ
ろで何の得もない。その形式は何かと扱いにくい
ので、お勧めしない。

    実践ハイパフォーマンスMySQL 第2版 p94より抜粋
日付と時刻
 TIMESTAMP カラムの値は、ストレージでは現在
 のタイム ゾーンから UTC へ、読み出しでは UTC
 からカレントのタイム ゾーンに変換します。


これだと、サーバーのタイムゾーンに依存するのでアプリ側
で GMTに   えて、DATETIME型で保存する予定
Join
Join

DBをわけることを前提にしているの
で基本Joinしない(もうRDBじゃない
じゃん >_<)

ただし要件による
Replication
Replication


レプリはします!

master 1 : slave : 4
構成                DB
                    DB
                 slave
  DB               slave
 master    レプリ        DB
  (user)                 DB
                     slave
                        slave



                  DB
                    DB
                 slave
  DB               slave
           レプリ        DB
 master
  (user)                 DB
                     slave
                        slave
レプリ遅延
 masterからslaveにレプリする際、どうしても遅延
 する

 開発の時に気付きにくい




  開発では、故意にレプリを遅らせる
master slaveの接続を意識してアプリを作る
pt-slave-delay

Percona Toolkitの中のツールの一つ

STOP SLAVEとSTART SLAVEを定期
的に打ってレプリが遅延しているよう
に見せている
Percona Toolkit

Maatkitを継承してるツール

Maatkitにあって、Perconaにないツー
ルもある
$ cpanm DBD::mysql
$ brew install percona-toolkit
$ pt-slave-delay --delay 1m --interval 1m -u root -p xxxx -h slavehost

2012-06-26T23:09:50 slave running 0 seconds behind
2012-06-26T23:09:50 STOP SLAVE until 2012-06-26T23:10:50 at
master position mysql-bin.000002/235710
2012-06-26T23:10:50 no new binlog events
2012-06-26T23:11:50 START SLAVE until master
2012-06-26T23:10:50 mysql-bin.000002/235894




--daemonizeオプションもあります
SUPER or REPLICATION CLIENTの権限が必要
MASTER_DELAYオプション



MySQL 5.6からは、CHANGE MASTER TOコマン
ドにおいて、MASTER_DELAYオプションで指定で
きるようになります(秒単位)
Sharding
Shardingとは

マスター分割のこと

基本的に、shardすることを前提にし
ています

shardすると色々と問題が、、、
AUTO_INCREMENT
AUTO_INCREMENT

基本的にshardすることを考えているので、
AUTO_INCREMENTは使わない

 AUTO_INCREMENTした場合は、IDの発行にず
 れがでる
Shardなしの場合               Shardありの場合




                 User           User         User
    User
                shard1         shard2       shard3


  user_id : 1   user_id : 1   user_id : 1   user_id : 1
  user_id : 2   user_id : 2   user_id : 2   user_id : 2
  user_id : 3   user_id : 3   user_id : 3   user_id : 3
  user_id : 4   user_id : 4   user_id : 4   user_id : 4
  user_id : 5   user_id : 5   user_id : 5   user_id : 5
     ・             ・             ・             ・
      ・             ・             ・             ・

      ID発行に重複がでてしまう!
sequenceテーブル
                                          CREATE TABLE `sequence` (
                                            `id` bigint(20) unsigned NOT NULL
         ①ID発行                 Sequence   ) ENGINE=MyISAM;


        UPDATE sequence
        SET id=LAST_INSERT_ID(id+1);
App

                                           User
      ②発行されたIDを使ってINSERT                  shard1
                                                User
        SELECT LAST_INSERT_ID();               shard2

                                                         User
                                                        shard3
LAST_INSERT_ID
UPDATE seq_user SET id=LAST_INSERT_ID(id+1)
とかでupdateを打ってIDをインクリメントした場
合、生成された ID は、接続ベースで サーバ内で保
持される

なので、update打ったあとに違う接続でupdateを
打っても、SELECT LAST_INSERT_IDの値は変化
しない。

http://dev.mysql.com/doc/refman/5.1/ja/information-functions.html
Index
HandlerSocket
HandlerSocket

  MySQLデータベースへのアクセスを高速化するた
  めのプラグインです。MySQLのSQLパーザをすっ
  飛ばし、ネットワーク通信とマルチスレッド処理
  周辺を置き換えることによって、InnoDB等のデー
  タベースエンジンの性能を限界まで引き出します。

http://engineer.dena.jp/2010/08/handlersocket-plugin-for-mysql.html より抜粋
MySQLのプラグイン

単純なデータの書き込み、読み出しを
高速に処理できる

トランザクションはない
HandlerSocket
          ポート 3306         SQL
          基本はこっち          レイヤー
         レプリはこっち
MySQL
                                    ストレージ
クライ
                                    エンジン
アント
        ポート9998 or 9999   Handler
          回数が多い or        Socket
Install Handler Socket
@Server
# wget http://ftp.jaist.ac.jp/pub/Linux/Fedora/updates/16/SRPMS/
mysql-5.5.23-1.fc16.src.rpm
# rpm2cpio mysql-5.5.23-1.fc16.src.rpm | cpio -id
# tar zxvf mysql-5.5.23-nodocs.tar.gz
# cd ../
# git clone https://github.com/ahiguti/HandlerSocket-Plugin-for-MySQL.git
# yum install libtool
# yum install gcc gcc-c++
# cd HandlerSocket-Plugin-for-MySQL
# ./autogen.sh
# ./configure 
--with-mysql-source=/root/src/mysql/mysql-5.5.23 
--with-mysql-bindir=/usr/bin 
--with-mysql-plugindir=/usr/lib64/mysql/plugin

# find ./ | xargs grep "DMY_PTHREAD_FASTMUTEX"
DMY_PTHREAD_FASTMUTEXがあるところを消す!(Fedora 16)
ERROR 1126 (HY000): Can't open shared library '/usr/lib64/mysql/plugin/handlersocket.so' (errno: 2 /usr/lib64/mysql/
plugin/handlersocket.so: undefined symbol: my_pthread_fastmutex_lock)
# make
# make install
# ls /usr/lib64/mysql/plugin/handlersocket*
/usr/lib64/mysql/plugin/handlersocket.a /usr/lib64/mysql/plugin/handlersocket.so /usr/lib64/mysql/plugin/
handlersocket.so.0.0.0
/usr/lib64/mysql/plugin/handlersocket.la /usr/lib64/mysql/plugin/handlersocket.so.0
Install Handler Socket
@Client (Ruby)
$ git clone https://github.com/ahiguti/HandlerSocket-Plugin-for-MySQL.git
$ cd HandlerSocket-Plugin-for-MySQL/
$ ./autogen.sh
$ ./configure --disable-handlersocket-server
$ make
$ sudo make install

$ gem install handlersocket
・
handler_socket.cc:2:10: fatal error: 'hstcpcli.hpp' file not found
#include "hstcpcli.hpp"
      ^
1 error generated.
make: *** [handler_socket.o] Error 1
$ vim extconf.rb
$CFLAGS << " -I/usr/include/handlersocket"
↓
$CFLAGS << " -I/usr/local/include/handlersocket"
$ ruby extconf.rb
$ make
compiling handler_socket.cc
3 warnings generated.
linking shared-object handler_socket.bundle
$ sudo make install
/usr/bin/install -c -m 0755 handler_socket.bundle /Users/makotoharuyama/.rbenv/versions/1.9.3-p125/lib/ruby/
site_ruby/1.9.1/x86_64-darwin11.3.0
installing default handler_socket libraries
サンプルコード
#!/usr/bin/env ruby
# encoding: UTF-8

require 'handler_socket'
require 'ap'

@hs = HandlerSocket.new(:host => '192.168.110.25', :port =>
'9998')
@hs.open_index(1, 'hs_test', 'test', 'PRIMARY', 'data')
ap @hs.execute_single(1, '=', [1], 1,0)

@hs.close


CREATE DATABASE test_haru;
CREATE TABLE `test` (
  `id` int(11) NOT NULL,
  `data` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;
パフォーマンス

今回は時間がなく、自分ではベンチとってないで
す>_<

参照に関してはIndexありInnoDBやmemdよりも約
8倍位のパフォーマンスが出ています

  NoSQL データベースファーストガイドより
MHA
MHA
MySQL Master High Availabilitymanager and tools
(MySQL MHA)

master/slaveのズレを解消して、自動でフェイル
オーバーさせる

障害 -> master切替 -> 通知までの一連の処理をし
てくれる

手動切替にも対応しています
まず、sshのkeyを登録しておく
MySQLの権限を振っておく(remoteからのアクセスとレプリ)
nodeをrpmで入れておく
# vim /etc/app.cnf
[server default]
# mysql user and password
user=root
password=root
ssh_user=root
repl_password=xxxxxx
# working directory on the manager
manager_workdir=/var/log/masterha/app1
# working directory on MySQL servers
remote_workdir=/var/log/masterha/app1

[server1]
hostname=192.168.110.27

[server2]
hostname=192.168.110.28

# masterha_check_ssh --conf=/etc/app.cnf
# masterha_check_repl --conf=/etc/app.cnf
Q4M
Q4Mとは

  MySQLのストレージエンジンとして実装されてる
  Message Queue

  MySQL 5.1系だけが対応

  トランザクションはない


レスポンスを期待するのがジョブキュー,レスポンスを必要としないのがメッセージキュー
参照 : http://gihyo.jp/dev/serial/01/perl-hackers-hub/001001
ちょっとした Tips
INSERT ... ON DUPLICATE
KEY UPDATE 構文
UNIQUE インデックスか PRIMARY KEY 内で重複
してる値をINSERTした場合、古い行のUPDATEが
実行される

重複しているか確認する必要がないので便利だ
が、扱いに気をつけないと・・・

複合UNIQUEキーがあっても「複数の固有インデックス」さえなければ
「INSERT ... ON DUPLICATE KEY UPDATE」構文は使える
YAPC
参照

MySQL サーバのタイム ゾーン サポート : http://dev.mysql.com/doc/refman/5.1/ja/time-zone-
support.html


INSERT ... ON DUPLICATE KEY UPDATE 構文 : http://dev.mysql.com/doc/refman/5.1/ja/insert-on-
duplicate.html


複合UNIQUEキーでも「INSERT ... ON DUPLICATE KEY UPDATE」構文は使える : http://
d.hatena.ne.jp/IwamotoTakashi/20080329/p1
参照
HandlerSocket plugin for MySQL : http://www.slideshare.net/akirahiguchi/handlersocket-plugin-for-
mysql-4664154

HandlerSocketソースコード公開しました : http://engineer.dena.jp/2010/08/handlersocket-plugin-for-
mysql.html

ahiguti / HandlerSocket-Plugin-for-MySQL : https://github.com/ahiguti/HandlerSocket-Plugin-for-
MySQL

Can't load handlersocket.so with Mysql 5.5.12 (and 5.5.13) on Fedora 15 x86_64 : https://github.com/
DeNADev/HandlerSocket-Plugin-for-MySQL/issues/58

HandlerSocket Make MySQLD got signal 11 : https://github.com/DeNADev/HandlerSocket-Plugin-
for-MySQL/issues/66

CentOSにMySQLとHandler Socketを入れてみる : http://d.hatena.ne.jp/
kotaroito2002/20111213/1323755054

handlersocket(ruby client) : https://github.com/miyucy/handlersocket

HandlerSocket pluginのRubyバインディングを作りました : http://d.hatena.ne.jp/winebarrel/
20100828/p1
参照


Percona Toolkit Documentation : http://www.percona.com/doc/percona-toolkit/2.1/index.html


mk-slave-delay : http://www.maatkit.org/doc/mk-slave-delay.html
参照
Introducing MySQL MHA (JP/LT) : http://www.slideshare.net/matsunobu/introducing-mysql-mha-jplt


mysql-master-ha : http://code.google.com/p/mysql-master-ha


Q4M : http://q4m.github.com/


Q4M dist : http://q4m.kazuhooku.com/dist/


Q4Mを簡単に導入する方法 : http://blog.nomadscafe.jp/2011/12/q4m---mysql-casual-advent-
calendar-2011.html


バイナリ版Q4Mインストールメモ : http://blog.nomadscafe.jp/archives/000737.html
参照
#mysqlbt : http://topsy.com/s?offset=160&om=aaaaaaaaaaaaaaaa&page=17&q=
%23mysqlbt&window=d25


初心者向けMySQLの始め方 : http://www.slideshare.net/tmtm/mysql-13117441


MySQL biginners talk : http://togetter.com/li/311837


NHNテクノロジーカンファレンスでしゃべって来た : http://blog.riywo.com/2012/05/22/033512


NHNテクノロジーカンファレンスで見たDeNAのMySQL運用の話とAmazon RDSの比較など。 : http://
debiancdn.wordpress.com/2012/05/20/nhn%E3%83%86%E3%82%AF%E3%83%8E%E3%83%AD
%E3%82%B8%E3%83%BC%E3%82%AB
%E3%83%B3%E3%83%95%E3%82%A1%E3%83%AC
%E3%83%B3%E3%82%B9%E3%81%A7%E8%A6%8B%E3%81%9Fdena%E3%81%AEmysql
%E9%81%8B%E7%94%A8%E3%81%AE/

My sql casual_in_fukuoka_vol1