ちょっと硬派なコンピュータフリークのBlogです。

カスタム検索

2009-05-28

Semi Synchronous Replicationテストのお願い。

前回、MySQL 6.0は先日リリースされた6.0.11が最後のバージョンになるということについて書いたが、その記事の中で、MysQL 6.0の機能のうちで次のものはMySQL 5.4にも取り込まれるということを説明した。
  • サブクエリ最適化
  • BKA Join
  • SIGNAL/RESIGNAL
  • INFORMATION_SCHEMAの拡張
  • XML機能の拡張
  • DTrace Probes
また、次の機能は搭載されないことについても言及した。
しかし、MySQL 5.4はまだβであり正式リリースまでにはもうしばらく時間がある。今日、レプリケーションチームの開発をリードしているLars Thalmannと話をしていたとき

Semi-Synchronous Replicationを5.4に搭載しようかどうしようか迷っているんだけど、ユーザーからのフィードバックが欲しいんだよね。

という意味のことを言っていた。以前の投稿でも書いたが、Semi-Synchronous Replicationは最強のHA化手法なので、ぜひとも5.4には搭載して貰いたい。そこで、このブログを読んでくれている皆さんにお願いなのだが、MySQL 6.0最後のバージョンであるMySQL 6.0.11を使って、Sem-Synchronous Replicationの評価をして頂けないだろうか。

ぜひ欲しい!!
この機能がないとヤダ!!
Semi-Sync最高!!


という声をLarsに届けることができれば、MySQL 5.4にはSemi-Syncが搭載されることになるだろう。絶対コレは便利な機能なので、ぜひともご協力頂きたいところである。高価な共有ストレージなどを使わずに超高速なフェイルオーバーを実現するSemi-Synchronous ReplicationがMySQLに搭載されれば、きっと皆さんにもメリットがあるはずである。

フィードバックの方法は、MySQLのメーリングリストに登録してメールを送ってもらうことだが、メーリングリストは英語だし敷居が高いと思うので、この投稿にコメントをつけて頂けるとありがたい。

さて、Semi-Synchronous Replicationの使い方であるが、プラグインをインストールしなければならないので多少面倒臭い。詳しくはマニュアルを見て頂きたいが、概要は次の通り。


1. MySQL 6.0.11をインストールして、レプリケーションのセットアップをする。

2. ここからSemi-Syncプラグインのバイナリをダウンロードする。

ただし、現在用意されているのはLinux用だけなので注意。

3. バイナリをplugin_dirに展開する。

plugin_dirはSHOW GLOBAL VARIABLESで確認できる。

mysql> SHOW GLOBAL VARIABLES LIKE 'plugin_dir';


4. INSTALL PLUGINコマンドでプラグインをインストールする。

マスター上

mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'libsemisync_master.so';

スレーブ上

mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'libsemisync_slave.so';)


5. Semi-Synchronous Replicationを有効にする。

マスター上

mysql> SET GLOBAL rpl_semi_sync_master_enabled = 1;

スレーブ上

mysql> SET GLOBAL rpl_semi_sync_slave_enabled = 1;


6. スレーブI/Oスレッドを再起動する。


mysql> STOP SLAVE IO_THREAD; START SLAVE IO_THREAD;


ちなみに、MySQL 6.0は現時点でも安定性はそれほど問題無い。ただし新機能を使わなければ。(特にFalcon。)MySQL 6.0は、我々日本人にとっては特に4バイトUTF-8のサポートが嬉しいバージョンなので、ぜひそちらの検証も兼ねてSemi-Sync Replicationの評価もして頂きたい。

2009-05-25

Good Bye MySQL 6.0

MySQL 6.0.11-alphaがリリースされた。が、アナウンスレターには気になる記述がひとこと。「これはMySQL 6.0の最後のリリースです」と。寝耳に水かも知れないがこの話は本当だ。実はこれが最後のMySQL 6.0のリリースになる。つまり、MySQL 6.0の開発はこれでストップするのだ。

えっ!!MySQLはもう開発が終わっちゃうの?MySQL終了のお知らせ?!

などと心配しないで頂きたい。MySQLの開発はちゃんと継続される。開発の方針が変更されることになったからMySQL 6.0のリリースが見送られただけである。(ちなみに、次期バージョンはMySQL 5.4で、MySQL 6.0はその次のバージョンになる予定だったものである。といっても、MySQL 5.4は後から間に挿入された形なのだが。)理由は、ここのところMySQLの新バージョンのリリーススケジュールが遅れがちだったり色々と問題があったからだ。(何かが変更されるときは大抵その背景には問題があるだろう)次のバージョンに何どんな機能が搭載されるのかは現時点では未定であるが、とにかく6.0はいったん中止になってしまったわけで、MySQL 6.0を楽しみにしてくれていた方々には申し訳ない限りである。

新しい開発方針は次のページで見ることが出来る。
http://forge.mysql.com/wiki/Development_Cycle

こういう開発方針を赤裸々に綴った文書がWebで公開されるのは、オープンソースソフトウェアの醍醐味ではないだろうか。プロプラエタリソフトウェアではまずあり得ない種類の文書である。MySQL 6.0リリース中止のお知らせにガッカリした皆さんは、どうかこのドキュメントを読んで理由を確認して頂きたい。その上で水を差すも良し、応援するも良し。MySQLのメーリングリストでは、誰でもオープンに意見を述べ、議論することが出来る。議論に参加するのもオープンソースソフトウェアの醍醐味だからだ。

さて、上記は英語だし文章が長いのでここで簡単に要約すると、
  • 一気にたくさんの機能を一度に盛り込もうとせず、主要な機能を少しずつ追加して新版とする。
  • 新機能の開発は平行して行い、成熟した時点でtrunkにmergeする。
ということである。MySQL 5.0のリリース当初はバグだらけだったということや、MySQL 5.1のリリースが遅れに遅れてしまったという過去の失態から開発の方針を変更したのある。今後は、より早いサイクルで、新機能を欲張りすぎずに、安定したバージョンを出していこうというわけだ。というわけで、MySQL 6.0が打ち切りになったからMySQLの開発がストップするということは一切なく、逆に今まで以上に活発に開発を続けて行くことになるので安心して欲しい。

ちなみに、マニュアルには書かれていないが、MySQL 5.4にはMySQL 6.0で搭載する予定だった機能がいくつか既に追加されている。なので、MySQL 6.0がなくなったからといって、MySQL 6.0で予定していた機能が全て使えないわけではないので安心して欲しい。既に安定しているものに関してはtrunkにmergeされているのだ。

MySQL 5.4で追加されたMySQL 6.0の機能は以下のものがある。もし、これらの機能を待望にしていたのであれば、ぜひMySQL 5.4を使って見て欲しい。(ただし、5.4は現時点ではβなので、あくまでもテストという位置づけで利用すること!!)

サブクエリ最適化

semi-joinやMaterializationなど。「なぜMySQLのサブクエリは遅いのか。」でちょっとだけ言及しているので興味のある方は参照して頂きたい。

BKA Join

Batched Key Accessの略。MySQL Clusterなど、リモートホストにデータを格納するタイプのストレージエンジンでは、劇的にJOINの性能が向上する可能性がある。「MySQL6.0における新しいJOIN最適化手法 - BKA」を参照。

SIGNAL/RESIGNAL

ストアドプロシージャやトリガ、イベントを記述するときに使う構文である。クライアントへエラーを通知する。

INFORMATION_SCHEMAの拡張

PARAMETERSやROUTINESテーブルが追加された。

XML機能の拡張

LOAD XML文が追加された。

DTrace Probes

どうやって使うかは、現在本に書いているところなので乞うご期待。

詳細については開発チームのPeter Gulutzanのブログに書かれているので気になる人は見て欲しい。
http://blogs.mysql.com/peterg/2009/05/20/mysql-54/

MySQLの次期バージョンは現在β版である5.4というのは変わらないが、上記のドキュメント(Development Cycle)によるとその次のバージョンは5.5になる予定のようである。ちなみに、5.4は入っていない機能には次のものがある。

現時点では5.5(仮)に搭載される機能はまだ決まっていないが、将来的にマイルストーンが固まったらこのブログでも紹介したい。

Wikipediaのライセンスがクリエイティブコモンズになった。

ITMediaのニュースで報じられているように、WikipediaのライセンスがGFDL - GNU Free Document Licenseからクリエイティブコモンズライセンスに変更された。クリエイティブコモンズライセンスって何?と思う人も多いだろう。実は、以前からオトコのコンピュータ道にはクリエイティブコモンズライセンスを適用している。(ページ右上のCC-BY-NC-SAというのがそれである。)クリエイティブコモンズに関しては、以前の投稿で紹介したので詳しくはそちらを見て欲しい。

ここで概要を簡単に説明すると、クリエイティブコモンズはAll rights reservedではなくSome rights reservedのライセンス、つまり著作権を全て主張するのではなく、著作権の一部を主張するために考案されたライセンスである。著作権で守られたドキュメントや画像、写真、楽曲やその他著作物は再配布や二次利用が自由に出来ないが、クリエイティブコモンズライセンスによって許諾された著作物であれば可能なのである。クリエイティブコモンズライセンスでは、どのような利用方法が可能であるかを、4つの属性によって定義している。そして、その4つの属性を組み合わせることで、その著作物にどのようなライセンスが与えられているかが分かるのである。その4つの属性とは次の通り。
  • BY・・・原作者の氏名(クレジット)を明記すること。
  • NC・・・商用利用不可。(Non-Commercial)
  • ND・・・改変不可。(No Derives)
  • SA・・・改変したときは同じライセンスを与えること。(Share Alike)
NDとSAは同時に指定出来ない。また、著作権の一部を主張する場合、誰が著作者なのかが分からなくなると意味がないので、BYは必須となる。すると、考えられる組み合わせは6通りということになる。
  • BY
  • BY-NC
  • BY-NC-SA
  • BY-ND
  • BY-NC-ND
  • BY-SA
また、一切の著作権を主張しないことを示すため、CC0というライセンスが導入された。CC0はつまるところ、BY、ND、ND、SA4つの属性が一つもないということである。CC0を入れると、ライセンスの種類は7種類ということになる。

この度、Wikipediaで採用されることになったのは、CC-BY-SAである。明確に著作者のクレジットを表示し、なおかつ派生物に同じライセンスを与えれば、ドキュメントの改変や再配布を自由に行えるのである。CC-BY-SAははGFDLに近いが、GFDLよりライセンスが簡単で運用も楽なのである。

さて、Wikipediaのライセンスがクリエイティブコモンズになって何が変わるのだろうか?GFDLとCC-BY-SAは近いライセンスなので、実質的にはあまり変わらないというのが実情だろう。ただし、これまでCC-BY-SAでドキュメントを公開してきた人には朗報である。自由にWikipediaの文書を自らの著作物の中で利用することが出来るからである。逆に、Wikipediaで自分の文書を使われる可能性もあるが、その場合は明確にクレジット表示が残るというメリットがある。

CC-BY-SAと他のライセンスの互換性はどうか?という疑問が沸いてくることだろう。答えは、無し!!である。CC-BY-SAを用いた派生物は、CC-BY-SAライセンスでなくてはならない。ちなみに、このブログではCC-BY-NC-SAを用いているが、CC-BY-SAとは互換性がない。従って、Wikipediaの文書をこのブログで用いたり、逆にこのブログの文書がWikipediaで用いられるということはないのである。

ちょっと待て!!クリエイティブコモンズライセンスの互換性について分からなくなってきた!!

と思った人は、クリエイティブコモンズのFAQを見るといいだろう。互換性が表にまとめられている。このブログでも引用したい。(ちなみに、引用元はCC-BYなのでライセンス的にはOKである。)



二次的著作物
利用される著作物
CC
-BY
CC
-BY
-NC
CC
-BY
-NC
-ND
CC
-BY
-NC
-SA
CC
-BY
-ND
CC
-BY
-SA
CC0
CC0







CC-BY







CC-BY-NC







CC-BY-NC-ND







CC-BY-NC-SA



オトコ


CC-BY-ND







CC-BY-SA





Wiki-
pedia




つまり、WikipediaではCC0、CC-BY、CC-BY-SAでライセンスされたドキュメントを自由に使っていいが、その他のライセンスのドキュメントは使えない。このブログでは、CC0、CC-BY、CC-BY-NC、CC-BY-NC-SAライセンスのドキュメントを使えるわけである。しかし、Wikipediaのコンテンツを流用したい場合には、CC-BY-SAライセンスを利用しなければならない。このブログのコンテンツはCC-BY-NC-SAで利用出来る。

というわけで、CC-BY-NC-SAは少々悩ましいライセンスである。Wikipediaと互換性があったほうが多くの人にとってメリットがあるのは明白なので、NCを取ろうかどうしようか考え中である。

本来なら、ブログのようなコンテンツにはCC-BY-NDが望ましいだろう。ブログのコンテンツは一つのストーリーになっているので、勝手に改変されるのは困る場合があるからだ。(自分が上海に行ったと書いた日記が改変され、北京に行ったことにされた文書が流布してしまっては困るだろう。)しかし、このブログには技術的な内容を書いており、技術的なものは加工してまとめたり内容を修正したり加筆したりすることに意味があるので、あえてNDではなくSA属性をつけている。多くの人がお互いに技術文書を改編し合って、文書の質を高められたら素晴らしいことじゃないか。

クリエイティブコモンズライセンスは元々、著作物を二次利用(再配布・改変など)する場合に生じる種々の面倒で不便な問題点を解決するために考案されたライセンスであり、そのような不便を解消して、著作活動にさらなる創造性をもたらすものである。もし、ブログなどの文書を公開する場合に、まだどんなライセンスにするかが決まっていない場合には、ぜひクリエイティブコモンズライセンス(のどれか)を選択して欲しい。

2009-05-21

目覚ましい進化を見せるストレージエンジン - PBXT改善の軌跡

PBXTというストレージエンジンがある。これは、PrimeBase社によるストレージエンジンで、トランザクションをサポートした本格的なものである。(つまり、InnoDBやFalconの代替として使うことを目指したエンジンなのである。)PBXTは次のページからダウンロード可能だ。
http://www.primebase.org/

上記のページにも書いてあるが、PBXTの特徴は次の通り。
  • MVCC(Multi Version Concurrency Control)
  • トランザクションのサポート
  • ACID準拠
  • 行レベルのロック
  • デッドロック検知
  • 外部キーのサポート
  • Write Once(追記型アーキテクチャ)
  • BLOBストリーミング

最後の2つ以外はInnoDBと同じである。Write Onceとは追記型のアーキテクチャで、InnoDBのように独立したログが存在しないという意味である。(PostgreSQLの方式と同じである。)BLOBストリーミングとは読んで字のごとくで、MySQL--->PBXTに蓄えられたBLOBデータをストリーミングするための機能である。MySQLにはストリーミングを可能にするようなインターフェイスは存在しないので、ストリーミングを行う場合はストリーミングエンジンから直接データが送られる仕組みになっている。(http://www.blobstreaming.org/ 参照)

このPBXT、実績はあまりないが滅法速い。いや、実は少し前まではそれほど速くなかったのだが、最近目覚ましい改良が加えられたのである。PBXTの開発者であるPaul McCullagh氏が、その改善点を自身のブログで語っているので紹介したい。以下がその投稿である。

詳細はここでは省く(氏のブログを参照してほしい)が、概要は次の通りだ。

まず、最初の投稿「Improving PBXT DBT2 Performance」において、次の改善が行われている。
  • 随所に入れられているwaitが長すぎたので改善した。
  • インデックス操作時(search/insert/delete)にmemcpyが行われていたのを排除した。
  • これまでインデックス更新中ずっと該当インデックスページを排他ロックしていたのを改善した。(これにより、複数のスレッドが同時に同じインデックスページにアクセス出来るケースが増えた)
  • インデックススキャン時の効率を改善した。これまでスキャン実行時に各ページをコピーしていたのを、Copy On Writeに変更した。

2つめの投稿「Solving the PBXT DBT2 Scaling Problem」では、次の改善が行われている。
  • 行レベルロックのロジックを変更し、より効率的なロックを実装した。
  • テーブルのopen/closeを効率化した。

というわけで、このようにPBXTは地道な改善が重ねられている。その結果、InnoDBに勝るとも劣らない素晴らしい性能を発揮しているのである。PBXTが改善を重ねたアプローチは参考になる。プログラムの挙動を分析し、ボトルネックになっている箇所を見つけ出し、一つずつ丁寧に潰してきたわけである。今後もそのように改善が重ねられるとしたら、PBXTはまだまだ速くなるだろう。

GoogleのMark Callaghan氏もPBXTの性能テストをしたらしく、ブログ記事「PBXT is fast, no kidding」でベンチマーク結果が公開されているのだが、改良版sysbenchにおいてPBXTがGoogle Patch適用後のInnoDB(つまりMySQL 5.4相当)よりも良い性能を発揮したというから驚きである。ちなみに、ベンチマーク結果のグラフは「Results are here.」という文章(hereの上)にリンクが貼られているので、そこをクリックして欲しい。

ちなみに、PBXTはMariaDBにデフォルトで含まれているので、PBXTを試したい人はMariaDBを使って見るといいだろう。もちろん、PBXTを個別にダウンロードしてMySQLにプラグインとして組み込むことも可能だ。その辺の手順については近いうちに解説したいと思う。

2009-05-19

限界までMySQLを使い尽くす!!

どこまで出来るか?!やれるところまでやってやるぜ!!と、威勢が良いのは若い間だけの話。オトナのオトコは、攻めるときはとことん攻めるが自らの限界もわきまえて賢く振る舞うのがスマートってものである。というわけで、今日はMySQLのいろいろな限界についてまとめてみる。皆さんも是非MySQLの限界を知り、MySQLをもっとスマートに使って頂きたい。


SQL文の最大長

MySQLサーバーが実行出来るSQL文の最大長は、max_allowed_packetシステム変数で表される。max_allowed_packetの最大値は1GBである。max_allowed_packetの値はセッションごとにも設定可能なので、デフォルトではそこそこの値(16MBなど)に設定しておいて、必要に応じて大きな対を使うと良いだろう。

データベースの個数

データベースオブジェクトの個数に制限はない。データベースオブジェクトは、MySQLのデータディレクトリ(datadir)のサブディレクトリとして格納される。(データベースの属性は、各サブディレクトリのdb.optというファイルに格納されている。)従って、データベースの個数は「datadirにいくつディレクトリを作成することができるか?」で決まり、これはOSそのものやファイルシステムから制限を受ける。ちなみにLinuxの場合、ext2/ext3の場合は32768個までであり、ext4ではその制限は撤廃される。Solarisの場合、UFSでは32768個の制限があり、ZFSにはそのような制限はない。

データベースあたりのテーブル数

テーブル数についても、データベースの場合と同じようにOSそのものやファイルシステムから制限を受ける。しかし、ファイル数はサブディレクトリ数と違って制限はほとんどない。ext2の場合でも130兆個以上である。しかし、実質的には一つのディレクトリにあまりに大量のファイルを作成すると、ファイル操作が遅くなってしまうので性能上の限界が自ずと生じる。だいたい1万ファイルぐらいまでが関の山である。MyISAMの場合、.frm、.MYI、.MYDという3つのファイルを作成するので、3000テーブル程度にとどめておくのがいいだろう。パーティショニングを利用する場合、.parというファイルと、さらにパーティションごとに.MYIおよび.MYDが作成されるので、使用するファイル数は格段に増える。(パーティション数x2+2)InnoDBの場合、デフォルトではデータベースディレクトリに作成されるのは.frmファイルだけである。innodb_files_per_tableオプションを使用すると、.ibdファイルも作成される。

MySQLサーバー全体でのテーブル数

これはストレージエンジンごとの制限による。MyISAMやInnoDBでは特に制限はない。例えばMyISAMの場合、データベースを1024個つくり、データベースごとに1024個のテーブルを作れば、トータルで100万個のテーブルを作成することが可能だ。(そんな使い方をする人は居ないだろうが。)他のストレージエンジンには制限が存在するものもある。例えばMySQL Clusterでは、MaxNoOfTablesというパラメーターで設定する。MaxNoOfTablesの最大値は1600。

テーブルごとのカラム数


MySQLの制限値は4096個までである。さらに、ストレージエンジンごとにそれより小さい制限があればそれに従う。InnoDBの場合は1000カラムまでで、MyISAMは特に制限はなく4096個というMySQL自体の制限が適用される。MySQL Clusterではカラムとインデックスを合わせて128個までという制限がある。

システム全体でのカラム数


こちらもストレージエンジンごとの制限が適用されるが、MyISAMやInnoDBには制限はない。

MySQL ClusterではMaxNoOfAttributesパラメーターで設定することができる。MaxNoOfAttributesの最大値は2^32であるが、システム全体で保持することができるオブジェクト(テーブル、カラム、インデックス、データベースすべてを含む)が20320個までという制限があり、そちらが適用されることになる。

テーブルごとのインデックス数


ストレージエンジンには最低16個以上のインデックスをサポートすることが定められているが、上限は定義されていない。従って、ストレージエンジンごとの制限がそのまま適用される。MyISAMは64個、InnoDBは上限なし、MySQL Clusterはカラムとインデックスを合わせて128個までである。

インデックス長

MySQL自体の制限値は3072バイト(1024 x 3)までである。それぞれストレージエンジンごとの制限が適用されるが、InnoDBは内部的には3500バイトまでサポートしているので、インデックス長の制限値は適用されない。MyISAMは1000バイトまでである。MySQL Clusterにはインデックス長の制限はない。4.1以前のバージョンのMySQLでは1024バイトまでという制限があるので注意しよう。

インデックスあたりのカラム数

マルチカラムインデックスを作る場合、インデックス長も気にしなければいけないが、カラム数にも制限が存在する。MyISAMの場合は16まで、InnoDBの場合は制限なし、MySQL Clusterは32までである。

行サイズ

MySQL自体の上限は、64KBまでである。ただし、これにはBLOB(およびTEXT)は含まれない。BLOBは他の領域に格納されるからだ。さらに、ストレージエンジンごとに制限が存在する場合がある。

InnoDBは、テーブルスペースのページサイズの約半分で、ページサイズのデフォルトは16KBなのでデフォルトの行サイズは約8KBである。ページサイズを変更するには、MySQLをソースからコンパイルして、さらにテーブルスペースとログファイルを再作成する必要がある。ページサイズの上限は64KBであるので、その場合の1行の最大サイズは32KBとなる。MySQL Clusterは1行あたり最大8KB。

テーブルあたりの行数

MySQL自体にはテーブルごとの行数の制限はない。ただし、PRIMARYやUNIQUEインデックスが格納できる行数には限界があるので、だいたいはそちらの制限を受けることになる。例えばPRIMARY KEYのデータ型がINTの場合は-2147483648〜2147483647、INT UNSIGNEDの場合は0〜4294967295までという値の範囲をとるので、4294967295行以上を格納することは出来ないわけである。

テーブルサイズ

こちらもMySQL自体には制限はない。

InnoDBの場合は、テーブルスペースの最大サイズである64TBが実質の上限となる。それ以前に、64TBのファイルを作成できる必要があるのだが、ext3などのファイルシステムでは、ファイルサイズの上限が2TBなので、それより大きなテーブルを作成したい場合には、テーブルスペースを複数のファイルで構成する必要がある。

MyISAMの場合も、.MYIまたは.MYDファイルがOSまたはファイルシステムがサポートしているファイルの最大サイズの制限を受ける。Linuxの場合、ext2/ext3では2TB、ext4では16TB、XFSでは8エクサバイトまでである。SolarisではUFSの場合1TB、ZFSの場合16エクサバイトである。ただし、MyISAMはファイルサイズの他に、内部で利用しているポインタサイズによってもテーブルサイズの制限を受ける。デフォルトでは256TBまで(ただし5.0.6以前は4GBまで)のテーブルが作成可能である。ポインタサイズはCREATE TABLE実行時にMAX_ROWSおよびAVG_ROW_LENGTHオプションで指定可能である。(MAX_ROWS x AVG_ROW_LENGTHが希望するテーブルサイズ程度になるようにする。)

MySQL Clusterの場合はDataMemoryやIndexMemoryのサイズ、およびディスク型テーブルの場合はテーブルスペースのサイズが上限となる。

テンポラリテーブルサイズ

テンポラリテーブルは、メモリベースのものとディスクベースのものが存在する。メモリベースのもののサイズが限界に達すると、MyISAMに変換される。変換の処理が結構重いので、変換があまり発生しないようにテンポラリテーブルのサイズやクエリをチューニングする必要がある。

メモリベースのテンポラリテーブルのサイズは、tmp_table_sizeおよびmax_heap_table_sizeオプションで設定することができる。ディスクベースのテンポラリテーブルは、tmpdirの領域を使い尽くすまで作成可能である。

CHARのサイズ

255文字まで。バイトではなく文字で計算するのがミソである。マルチバイト文字を使うと、1文字辺りの最大バイト数x255バイトになる。例えばUTF-8の場合、1文字あたり3バイトまで消費するのでCHAR(255)は765バイトとなるので注意しよう。MySQL 6.0では4バイトUTF-8がサポートされるので、CHAR(255)は1020バイトになる。

VARCHARのサイズ

65535文字までである。ただし、1文字の最大サイズは3バイトなので、65535文字だと軽く1行あたりの最大サイズの上限である64KBを超えてしまう。そのような場合、自動的に(MEDIUM)TEXTなどに変換される。また、スペック上はシングルバイトの文字コードだとVARCHAR(65535)まで作成できることになっているが、実際には65529〜65535バイトの場合はエラーになってしまう。その場合は代わりにTEXTを使おう。

BLOB/TEXTのサイズ

通常のBLOB(TEXT)は64KBまで、TINYBLOB、MEDIUMBLOB、LONGBLOBはそれぞれ256バイト、16MB、4GBまでである。こちらはCHAR/VARCHARとは違って文字数ではなくバイト数なので気をつけよう。

INTの最大値


-2147483648〜2147483647、INT UNSIGNEDの場合は0〜4294967295まで。(4バイトだから。)TINYINTは1バイトなので-127〜128、SMALLINTは2バイトだから-32768〜32767、MEDIUMINTは3バイトだから-8388608〜8388607、BIGINTは8バイトだから-9223372036854775808〜9223372036854775807。UNSIGNEDはそれぞれ、TINYINTが255まで、SMALLINTが65535、MEDIUMINTが16777215、BIGINTが18446744073709551615。

DECIMALの最大値

DECIMALは最大で65桁まで定義することが可能である。小数点以下の桁数は30桁まで。従って、全体で65桁で小数点以下がない場合、つまりDECIMAL(65)は-99999999999999999999999999999999999999999999999999999999999999999〜99999999999999999999999999999999999999999999999999999999999999999まで格納することが出来る。全体で65桁で小数点以下が30の場合、つまりDECIMAL(65,30)は-99999999999999999999999999999999999.999999999999999999999999999999〜99999999999999999999999999999999999.999999999999999999999999999999まで格納することが出来る。

必要に応じて桁数を割り当てよう。

DATETIMEとTIMESTAMPの最大値

DATETIMEは1000-01-01 00:00:00〜9999-12-31 23:59:59、1970-01-01 00:00:01〜2038-01-09 03:14:07(ただし時間帯はUTC)まで格納することが出来る。TIMESTAMPは2038年問題にぶち当たるわけである。

テーブルあたりのパーティション数

1024(サブパーティション含む)

カラム名、テーブル名、データベース名などの識別子

MySQL自体の制限値は64文字までである。寿限無寿限無・・・と長いテーブル名をつけてもOKであるが、一般的には短くてわかり易い名前をつけることが多いので、テーブル名の最大長が問題になることはないだろう。

ただしMySQL Clusterは、カラム・インデックス名は31文字まで、テーブル名とデータベース名は合わせて122文字までという制限がある。

ユーザー数

制限なし。何名でも登録可能。ただし権限テーブルはメモリ内にキャッシュされるので、あまりに多すぎるとメモリを消費しすぎることになるので注意が必要だ。

ユーザー名

16文字まで。

パスワード長

制限なし。パスワードは、内部的にはPASSWORD()関数によってハッシュ値が計算され格納されるだけである。ただし、mysqlコマンドを-pオプションつきで実行した場合などに表示されるパスワードの入力を求めるプロンプトに対しては、80文字までしか入力出来ないという制限があるので注意しよう。

shell> mysql -uroot -p
Enter password: ←コレは80文字まで

パスワード長が長ければ長いほどセキュアなパスワードであると言えるが、あまりに長すぎると覚えにくいので気をつけよう。

同時接続数

max_connectionsパラメーターで調整可能。max_connectionsオプションの最大値は100000(MySQL 5.1.17以降)である。ただし、MySQLは一つのコネクションに対して一つのスレッドを作成する仕様になっている。そのため、OSが作成出来るスレッド数(プロセスあたり/システム全体)によって制限される。OSが作成することができるスレッド数は、システム起動時に自動的に調整されたり、スタック領域のサイズによって制限される場合が多い。各OSにおけるスレッド数の調整については、MySQL Practice Wikiにまとめてあるので参照して欲しい。

また、コネクションごとにOSがTCP/IPソケットを一つ作成するが、その度にファイルディスクリプタを一つ消費する。従って、一つのプロセスが同時に開くことができるファイル数にも制限を受けることになる。(下記、同時にオープンできるテーブル数参照)

同時実行クエリ数

制限なし。接続している全てのセッションがクエリを実行することができる。ただし、ロックの競合などが発生して待たされる場合が多々あるので、真に同時に(内部的に)実行されるクエリ数はもっと少ない。

また、ストレージエンジンには同時に実行出来るトランザクション数に限界があるので、そちらの制限に引っかかるだろう。InnoDBの場合は1023トランザクションまで、MySQL ClusterはMaxNoOfConcurrentTransactionsパラメーターで調整できる。MaxNoOfConcurrentTransactionsの最大値は2^32弱である。

同時にオープンできるテーブル数

MySQL自体には制限はなく、ストレージエンジンごとに制限が存在する。

MyISAMの場合、テーブルをセッションが開く度にファイルディスクリプタを消費する。.MYIは全てのセッションで共有されるが、.MYDはセッションごとに一つのファイルディスクリプタが必要になる。従って、多くのファイル、多くの接続を同時に使用する場合には、同時にオープンできるファイル数を増やさなければならない。同時にopenできるファイル数は、open_files_limitパラメーターで設定することができ、内部的にはsetrlimit(ulimitコマンド相当のシステムコール)で調整することができるが、カーネルがさらに上限値を持っていることが多い。Linuxの場合は、sys.fs.file-maxカーネルパラメーターで、Solarisの場合はrlim_fd_max、rlim_fd_curカーネルパラメーターで調整する。

InnoDBは、デフォルトではテーブルスペースを共有しているのでこのような制限はない。ただしinnodb_files_per_tableオプションを使用している場合は同様に一つのプロセスが開くことができるファイル数に制限を受けることになる。

JOINできるテーブル数

61

サブクエリのネスト数

31回まで。(最外部クエリを合わせると全体で32階層になる。)

テーブルに設定出来るトリガ数

それぞれBEFORE/AFTERとINSERT/UPDATE/DELETEの組み合わせで6つまで。同じ種類のトリガを重複して設定することは出来ない。

レプリケーションスレーブ数

スレーブ数はserver-idの制限を受ける。server-idは2^32-1=65535が最大値なので、65535個のスレーブを設置することが理論的には可能。ただし、スレーブはマスターへ接続する必要があるので、マスターにおいて同時接続数が先に限界を迎えるだろう。それ以前に、ネットワークポート数やネットワーク帯域数が先に限界を迎えることになるだろう。

バイナリログサイズ

max_binlog_sizeで調整可能。max_binlog_sizeの最大値は1GB。

バイナリログファイル数

2147483647まで。それ以上のバイナリログを作成することはできずにエラーになるが、ここまでバイナリログを作成しなければならない状況は滅多にないだろう。

利用可能CPU数

利用可能なCPUコア数/ソケット数などに制限はない。また、商用版のライセンス形態もCPU数ではなくサーバー単位である。ただし、CPUが利用可能なことといくつまでスケールするかは別の話。スケーラビリティを重視している人はMySQL 5.4を使おう。

同時に起動できるMySQLサーバーインスタンス数

データディレクトリやTCP/IPポート番号、UNIXソケット、PIDファイルなどの資源が被らなければいくつでも起動可能。ただし、OSが同時に起動出来るプロセス数や、同時に開くことができるファイル数、TCP/IPポート数などの制限を受ける。

利用可能メモリ量

MySQLはシングルプロセス/マルチスレッドのプログラムなので、32ビット版のOSの場合は2GB〜3GBの制限がある。いくらマシンに搭載しているメモリがそれより多くても関係ない。LinuxやSolarisでは3GBまで、Windowsの場合はデフォルトでは2GBまで利用可能である。ただし、Windowsの場合も/3GBスイッチを設定することで、一つのプロセスが3GBまで利用することが可能である。64ビット版のOSおよびMySQLを使えば、そのような制限はない。システムが搭載しているメモリを全て余すことなく使うことが出来るだろう。(ただしメモリを割り当てすぎてスワップが発生するのは禁物だ!!)

2009-05-15

Nokiaは引くタイミングを間違ったんじゃないだろうか。

今日は徒然なるままに今使っている携帯端末について語ってみようと思う。

俺は携帯電話はNokiaのE71を使っているのだが、これがなんとも具合がいい。E71はQWERTYキーボードを搭載している硬派なスマートフォンなのだが、Nokiaによる日本撤退によって発売が中止になってしまった幻の端末でもある。どうやってE71を手に入れたのかというと、海外携帯を扱ってるショップで買った・・・というわけではなく、昨年とあるギークな友人(現在iPhoneユーザー)からもらい受けたのである。幸いにしてそのE71端末はSIMロックフリーだったので、それまで使っていた携帯からSIMカードを差し替えれば使うことが出来たのだ。

E71がどんな端末なのかは、NokiaのE71公式ページImpressのレビュー記事なんかを参照してくれるといいだろう。

貰ったE71は英語版だったので、もちろんインターフェイスは全て英語である。しかしコンピュータのドキュメントを日々読みあさっているギークにとって、英語のインターフェイスは苦ではないはずだ。(むしろ俺は日本語より使用するメモリ量が少なく嬉しいぐらいである。)初期状態では日本語のフォントそのものが入っていないので日本語のウェブページやメールが見れなかったり、変換ソフトが入っていないので日本語の入力が出来ないという問題はあるのだが、Nokia端末に日本語のフォントをインストールする方法はググればすぐに出てくるし、日本語入力は+Jをインストールすることで対応が可能だ。自分で色々とDIYできる人なら、E71をセットアップするのはそれほど苦労はしないだろう。

ひとたびE71を使い始めると、これがなんとも具合が良い。iPhoneのように斬新な使い勝手はないが、スマートフォンの定番であるSymbian OSを搭載した端末の進化版として見れば非常に秀逸である。動作はキビキビとしていてレスポンスも良く、QWERTYキーボードは入力しやすく、さらにE61と比べて小型になったのでグリップ感もいい。Webブラウザもメールもストレス無く使うことが出来る。iSync用のプラグインを使えば、OSX上のアドレス帳やカレンダーとの同期もBlootoothで行えるので楽ちんだ。iTunesで管理しているMP3ファイルを簡単に転送できるのもポイントが高い。もちろんそれらを着信音に設定することだって可能である。

E71の前は同じくNokiaのN95を利用していたのだが、これはこれで優秀な端末である。どちらもSynbian OSを搭載しているので、基本的な操作方法は同じであるが、N95にはQWERTYキーボードはなく、代わりにカールツァイズ社製のレンズを用いた500万画素のカメラを搭載していたり、ミュージックプレイヤー用のボタンがついているなど、マルチメディア機能に主眼を置いた端末である。E71と比べると多少のもっさり感は否めないが、もちろん実用に耐えるレベルである。(E71がサクサクし過ぎなのだ!!)N95はマルチメディア携帯であり、E71は王道のスマートフォンである。自分はどちらが好きかといえば、もちろんE71だ。ギークだから。

正直言ってE71が日本で発売されなかったのが残念でならない。Nokiaは撤退するタイミングを間違ったかも知れないと思う。E71はこれまでの Nokia携帯のイメージを一新するぐらいの使い勝手の良さがあるので、一定のユーザーを獲得できていたかも知れないのに。撤退するなら少なくともE71 をリリースしてからにするべきだったと思う。

ところで、なんでマックユーザーなのにiPhoneじゃなくSymbianを使ってるんだ?と思われるかも知れないが、それは一言でいうとへそ曲がりだからだ。流行りすぎてると飛びつきづらいというかなんというか。だがそれだけではE71を選ぶ理由にはならない。iPhoneを避けるだけなら別に他の端末でもいいからだ。なぜE71なのかというと、やはり見た目がカッコイイからである。そしてiPhoneより一回り小さくて薄くて軽い。それでいてQWERTYキーボードが搭載されていて、なおかつカラーリングも渋めで落ち着いている。とまあ、好みの問題なのである。ちなみに、iPhoneとE71のサイズの比較はこんな感じ。

E71: 114 x 57 x 10 mm / 127g
iPhone: 115.5 x 62.1 x 12.3 mm / 133g

世界ではまだ高いシェアを獲得しているNokiaであるが、日本市場では苦戦した挙げ句に撤退してしまった。iPhoneやWindows Mobile、Black Berry、Androidなどのライバル達はいずれ劣らず強力なので、この先は海外でのシェアも危ぶまれるところである。Symbian OSといえば今はオープンソース化に向けて着々と準備を整えているところであるが、今後もシェアを獲得できるかどうかはオープンソース化が成功するかどうか、オープンソース化することによるメリットをどれだけ活かせるかということに掛かっているのかも知れない。

オープンソース携帯と言えばAndroidである。こちらは端からオープンソースであることを謳っている端末であり、オープンソース化のメリットを最大限に享受するなら迷わずこちらを使うべきなのかも知れない。正直凄く期待しているのだが、残念ながらまだオトコのハートをガッチリ掴む端末が出てこないのである。ちょっと古いけど、JornadaとかSigmarionとか、もしくはNokia E90みたいなゴツい感じの端末が出れば迷わず飛びついてしまうだろう。

2009-05-14

富士通の世界最速CPU「Venus」見参!!

なんと、富士通がインテルもIBMもブチ抜いて、世界最速のCPUの開発に成功したそうだ。GIGAZINEのニュース記事はこちら。
http://gigazine.net/index.php?/news/comments/20090513_fujitsu_venus/

このCPUの概要は次の通りである。
  • SPARC64の後継
  • 8コア/ソケット
  • クロック周波数は2GHz
  • 1クロックで8回の浮動小数点演算を実行
  • 2GHz x 8 x 8 = 128GFLOPs(世界最速!!)
というわけだ。SPARC64ベースなので、OSはもちろんSPARC版Solarisを使うことになるだろう。太陽は沈んでしまったが、Solarisだけは復権なるか?!

8コアという構成は、元々SunがNiagara CPUでとっていたものと同じである。Niagaraではスループットを重視したので各コア、つまりシングルスレッド性能はあまり高くないというコンセプトだったのだが、Venusでは各コアの性能も高くなったということだろう。

Venusの詳細については、GIGAZINEの記事にも書いてあるがマイコミジャーナルの記事の方で詳しく説明されているので、そちらを参照して欲しい。
http://journal.mycom.co.jp/articles/2009/03/12/sparc_viii_fx/index.html

ちなみに、記事にはインテルの最速CPUより2.5倍速いと書いてあるが、逆算するとインテルCPUの理論性能値は50GFLOPs程度ということになる。(WikipediaのFLOPSのページには、51GFLOPsとある。その他のソースはWebで調べても出てこなかった。誰か知ってたら教えて!!)IBMのPower6は、5GHz動作時で40GFLOPsらしい。(参考記事)5GHzのPower6より3倍以上速いというのは驚きである。

先日、現役SEでギークな友人とCPUについてメールで語り合ったりしていたのだが、その友人曰く「x86のCPUが優位性を保ってるのは量産効果があるからで、Atomによって下位の市場が侵食されれば上位のCPUに対する投資は減るから性能競争で再びUNIXサーバー陣営、つまりPowerやSPARCが性能競争で復権するのではないか。」というのである。とはいえ、x86 CPUの性能向上もめざましく、最初にその友人の話を聞いたときは訝い意見だなと思っていたのだが、Venus CPUに関するニュースを見てちょっと信憑性があるかも知れないと思った。CPUの性能競争はギークにとって楽しいこと極まりないトピックなので、ぜひx86とPower、SPARCなどのRISCチップ同士で、熾烈な性能競争を再び繰り広げて頂きたい。

ところで、VenusはCPUの中では最速になるだろうが、科学計算の世界にはもっと強力なライバルが存在する。それはGPUの存在である。ちなみに、FLOPSだけで見るとGPUの方がもっと速い。WikipediaのFLOPSのページによると、GeForce GTX280は933GFLOPsだそうである。何ともはや・・・Venusの7倍近い性能ではないか。

ただし、問題はいくら性能理論値が良くても、実測値が良くなければ意味がないということである。演算回路は超高速でも、データのロードストアに時間が掛かっていてはせっかくのハードウェアの性能を活かし切ることが出来ない。特にGPUでは、メモリへのアクセス速度が問題になると予想される。ちょっと古い記事であるが、マイコミジャーナルのCUDAに関する記事を見るとそれほどGPUの実測値は出ていないように見受けられる。とはいえ、比較されているx86よりは断然速いのだが。

いずれにしても、Venusの登場はCPU(GPU)の性能競争がさらに激化する時代への突入を予感させる。今後の動向が楽しみだ!!

2009-05-13

オトコの頭皮ケアテクニック2009

今日はちょっと閑話休題でコンピュータの話から離れてみようと思う。

漢に生まれてしまったら、一つ心配しなければならないことがある。そう、頭髪である。いくら父親がフサフサだったとしても油断は出来ない。遺伝子が似ていても、生活環境が違えば頭皮に与える影響だて違ってくるし、その結果ハゲてしまうことだって少なくないだろう。

頭皮なんか気にして女々しいヤツだ!!などという意見もあるかも知れないが、せっかく持って生まれた自分の身体は大事にしなければならない。日本男児たるもの、自らの肉体を粗末にしてはならないのである。

俺は幸いにしてまだハゲてはいない。若かりし頃から比べると、かなり額が広くなってしまったように思うし、頭皮が見えやすくなった気はするが、まだ大丈夫だと思う。たぶん。本宮ひろ志の漫画に、まだ、生きてる…というのがあるが、俺の場合は

まだ、生えてる...

である。ちなみに、「まだ、生きてる…」の主人公は、もう生えてない。

俺の父親はまだフサフサかつかなりの剛毛なのだが、俺の髪質は父親のそれとはまったく違って細い。なので家族から「お前はハゲるかも」などと言われることも多いのだが、なんとか踏みとどまっているわけである。どうやって?

今日は俺が普段頭髪を堅守するために心がけているテクニックを紹介したいと思う。

1. よく脂を落とす。

日々、風呂では入念に頭を洗うべし。脂が毛穴に詰まると髪の成長が阻害されてしまうからだ。シャンプーは脂をよく落とすタイプのものを選び、しっかりと力を入れて擦ること。頭皮を指先で力強く押すにしてマッサージするのも良い。

シャンプーをつけてシャカシャカシャカッ・・・と1分ぐらいで洗い終わるのでは脂は落ちない。出来れば3分ぐらいかけよう。毎日数分余分に時間をかけるだけで頭髪が守れるなら安いものである。

最後はシャンプーをしっかり流すべし。シャンプーが頭皮に残ったままだと頭皮が炎症を起こしてしまうことがあるからだ。

整髪料を使っている場合には、シャンプーを2回すると良い。1回目で整髪料を落とし、2回目で脂を落とすべく洗うわけである。2回目はしっかりとシャンプーを洗い流そう。

2. よく食べる。

髪が成長するためには、養分が必要である。植物は痩せた土地では育たないが、髪だって栄養のない頭皮では育たないのである。頭皮にもしっかり養分が回るよう、食事はしっかりと取ろう。朝食を抜いたりするのは良くない。毎日3食とるべし。

何を食べるのかというのも大事なのだが、偏って食べるのはよくない。肉ばっかり、野菜ばっかり、甘いものばっかり・・・というのは、すべてNGである。いろいろなものをバランス良く食べるのが良い。

ただし食べ過ぎは良くない。胃腸の調子を崩してしまっては本末転倒なので気をつけよう。

3. よく眠る。

髪はいつ成長するのか?それは夜、寝ている間である。夜中の2時ぐらいが最も髪の成長が促される時間帯だそうだ。

しっかりと頭皮の脂を取り除き、髪が育つための栄養をとっても、実際に育つための時間を潰してしまっては全てが台無しである。植物の栽培で例えるなら、水はけの良い土壌を用意し、しっかりと水分と養分を与えているのに、日光にあてないようなものである。日光がなければ植物は育たない。同じく睡眠がなければ頭髪は育たないのである!

夜中の2時に熟睡しているようにするためには、夜更かしは禁物である。遊びたい気持ちをグッとこらえて寝入るためには、早起きしてしまうのも手である。そうすれば眠くなってしまうからだ。俺は睡眠を規則正しくするため、毎朝6時に起きるようにしている。そして夜はさっさと寝てしまうようにしている。ブログを更新するのもだいたい朝である。

健全な頭髪は健全な肉体から。健全な肉体には睡眠がとても重要なのである。

4. ストレスをためない。

ストレスは、頭髪の天敵である。いくら健全に育っている植物でも(土壌、栄養、日光すべて良好な条件があっても)、台風になぎ倒されてしまっては一貫の終わりである。ストレスは頭皮に吹き付ける台風のようなものである。従ってストレスをためてはいけない。

とはいえ、人生色々ある。職場でも家庭でも、漢は常に戦いの渦中に居ることが多い。そうするとストレスが溜まる。漢は辛いよ!!である。なので、せめて一人になった時間には自分の好きなことをしよう。

ギークにとって好きなことと言えば、やはりコーディングであろう。コーディングに没頭している間は、嫌なことなどは全て忘れ去る事ができる。むしろ自分の思うとおりにプログラムが動き出した時の喜びは他では得られない最高のエクスタシーであり、ストレスなどは全て吹き飛んでしまうだろう。

ただし、いくらコーディングが楽しいからと言って、寝食を忘れるほど没頭してはいけない。ストレスは感じないかも知れないが、それ以前に頭皮から大事な栄養と睡眠を奪ってしまうことになるからである。何事も過ぎたるは及ばざるがごとしだ。

コーディングをする上で注意しなければならないことが一つある。それは、バグの存在である。デバッグも時には楽しい作業ではあるが、コーディングの進捗を妨げるものであることには違いない。プログラムが自分の意図するようになかなか動作しないと、徐々にストレスを感じてしまうことになる。そんな場合はいったん手を止めて、コーヒーでも飲もう。

5. オープンソースソフトウェアを使う。

プログラムが自分の意図するように動作しない場合、もしそれが自分が書いたコードに潜んでいるバグによるものであれば問題はない。自分で書いたコードであれば、デバッグはそれほど難しくない。だが、OSやライブラリに起因するバグであればどうだろうか。

もし、バグが存在するのがクローズドソースなライブラリの内部だったらどうしようか。ソースコードがなければ我々に打つ手はない。せいぜい開発元に問い合わせて回答を待つだけである。運が良ければ直して貰えるかもしれないが、それには往々にして何ヶ月も掛かってしまう。その間、苦虫を噛みつぶすような思いで待たなければならないことになるわけだが、それは頭皮には良くない。

オープンソースなライブラリならどうだろう。ソースコードがあれば自分で問題を調査することも出来るし、直すことだって出来る。直して、コンパイルして、インストールすれば、コーディングを再開することが可能だ。もちろんデバッグにはそれなりの時間は掛かるだろうが、何ヶ月も待つよりは遙かに良い。すぐに自分の好きなプログラムのコーディングに取りかかることができるわけである。ストレスはすぐに解消され、健全な頭皮が保たれる事であろう。

このように、ソースコードを参照することが出来れば、不要なストレスから解放されるわけである。

まとめ

今日はコンピュータの話から離れると言っておきながら、最終的にはオープンソースの話題に帰結してしまった。これはつまり、俺にとってコンピュータは生活から切っても切り離せないものとなっている証拠であると言えよう。

健全な頭髪を育成するためには、
  • しっかり洗う
  • よく食べる
  • よく眠る
  • ストレスをためない
  • そしてオープンソースソフトウェアを使う
である。

この手法が万人(もしくは全てのギーク)にとって適切なものであるかどうかは不明であるが、少なくとも俺はまだ生えてる。従って、一部の人には一定の効果がある手法であると推測できる。よく洗ってよく食べてよく眠っているにも係わらず最近頭皮が気になり出したよ!!という人は、オープンソースソフトウェアの利用を試して見て欲しい。(なんでやねん!!>俺)

ちなみに、本宮ひろ志の「まだ、生きてる…」は結構渋くて面白いので、俺は結構好きである。

2009-05-12

FOSS License Exception

MySQLにはFOSS License Exceptionという制度がある。そのような制度があることはあまり知られていないし、名前を知っていても内容はよく知らない、または誤解しているという人が結構居る。そこで、FOSS License Exceptionについて改めてここで紹介したい。

MySQL FOSS License Exception
http://www.mysql.com/about/legal/licensing/foss-exception/

知っての通り、MySQLはデュアルライセンスだ。無料で公開されているMySQL Community ServerはGPLv2でライセンスされており、その他に有料のコマーシャル・ライセンス版が存在する。コマーシャル・ライセンス版はソースコードを公開したくないユーザー向けのライセンスで、俗にOEM版とも呼ばれる。

さて、FOSS License Exceptionが対象とするのは、GPLv2版のMySQLサーバーである。GPLv2のソフトウェアをバンドル(正式にはリンク)したソフトウェア、または改変したソフトウェアは、ライセンスをGPLv2にしなければならない。多くのオープンソースプロジェクトの場合、GPLv2は最も良く利用されているライセンスであるので、自分が作成したソフトウェアをGPLv2にすることが問題になることはさほどないだろう。だが、GPLv2と互換性のないライセンスのライブラリを利用したい場合にはそうは問屋が卸さない。例えばApacheライセンスなどだ。

とあるApache 2.0ライセンスのライブラリがとても有用で、どうしてもそのライブラリを利用したいとする。だが一方でGPLv2版のMySQLも利用したい。しかしGPLv2とApacheライセンスは互換性がないので同時に利用することができない。はてさてどうしたものか?!

というわけで、そこで登場するのがFOSS License Exceptionという制度なのだ。これは、MySQL(サン・マイクロシステムズ)が許可したオープンソース・ライセンスに限って、GPLv2版のMySQLを利用した場合でもそのソフトウェア全体のライセンスをGPLv2にしなくてもいいですよという制度なのだ。そうすると、上記のような場合は、その作品にApache 2.0ライセンスを適用すれば、GPLv2版のMySQLの利用とApache 2.0ライセンスのライブラリのリンクを同時に行う事が可能になる。

FOSS License Exceptionで認められているライセンスの全リストは、上記のページに載っているので参照して欲しい。先に挙げたApache 1.0/1.1/2.0ライセンスやBSDライセンス、PHPライセンスなどがリストアップされている。

当然のことであるが、プロプラエタリなソフトウェアにはこの制度は適用されない。GPL違反をすると、MySQL(サン・マイクロシステムズ)は違反者を法的に訴えることが出来るので注意しよう。(そしてコマーシャル・ライセンスを買って貰ってライセンス料を頂いたりする。)しかし、オープンソース・ソフトウェアに対してそのようなことをしてもナンセンスである。なぜなら、オープンソース・ソフトウェアは無料で配布されていることが多いからだ。MySQLはオープンソースを支持しているので、自身はGPLv2であるが他のオープンソース・ソフトウェアで利用できるようにFOSS License Exceptionのような仕組みがあるのだ。

一点注意しなければならないのは、FOSS License Exceptionを適用した場合でも、バンドルされるMySQLは依然としてGPLv2として残るということだ。つまり、作品全体はGPLv2ではないオープンソース・ライセンスであったとしても、その一部にGPLv2のコンポーネントが含まれることになる。そのソフトウェアを利用して別の新たなソフトウェアをリリースする場合には、再度GPL違反にならないように注意しなければならない。例えば、PHPはPHPライセンスでリリースされているが、MySQLとの接続をサポートしている場合(つまりlibmysqlclient.soとリンクしている場合)にはFOSS License Exceptionが適用されているわけである。(そうでなければPHPはGPLv2ライセンスを適用しなければならない。)その場合、MySQLとの接続を前提にしたPHPソフトウェアを頒布する場合にば、GPLv2ライセンスまたはFOSS License Exceptionの対象になるオープンソース・ライセンスだけを適用することが出来るわけである。

MySQLを利用してプロプラエタリなソフトウェアをリリースしたい場合には、やっぱりコマーシャル・ライセンスが必要なのである。

2009-05-11

ALTER TABLEを上手に使いこなそう。

テーブル定義を変更したい。インデックスが壊れてしまったので再作成したい。そんな場合はALTER TABLEを使う。ALTER TABLEはテーブル定義を変更するお馴染みのコマンドであるが、その挙動は意外と知られていない。(エキスパートとおぼしき方々からも度々質問を受ける。)そんなわけで、今日はALTER TABLEについて解説しようと思う。

まず結論から言うと、なんとMySQLのALTER TABLEはテーブルのデータを全てコピーし直すのである。なんて無駄なことを!?と思うかも知れないが、テーブル定義(スキーマ)の変更を動的に行うには、ストレージエンジンによるサポートが必要であり、動的なスキーマ変更をサポートしているストレージエンジンはまだ少ないのである。(動的スキーマ変更をサポートしているのはMySQL Clusterぐらいだ。しかも追加だけ。)デフォルトで利用出来るMyISAMはInnoDBでは、全てのデータをコピーし直すのである。その場合の動作は次の通りだ。
  1. テーブルをTL_WRITE_ALLOW_READロックする。このロックは特殊なロックで、テーブルロックの一種であるが、他のセッションからのREADを許可し、WRITEをブロックする。
  2. 新しいテーブル定義を使って空のテンポラリテーブルを作成する。
  3. 古いテーブルから新しいテーブルへデータをコピーする。
  4. テーブルの名前を付け替えて、新しいテーブルを古いテーブルと同じ名前にする。古いテーブルは破棄する。
  5. 新しいテーブルへブロックしていたWRITEをリダイレクトする。
そんなわけで、大きなテーブルをALTERするときには長時間WRITEがブロックされてしまうので注意しよう。また、ALTER TABLEでは完全なテーブルのコピーを作成する必要があるので、元のテーブルのサイズと同じぐらいのディスク空き容量が必要であることにも注意しなければいけない。空き容量が足りないとALTER TABLEコマンドは失敗してしまう。

このようなALTER TABLEコマンドであるが、使いようによっては便利な面もある。コマンドの実行中もテーブルからREADが出来るからだ。テーブルが壊れた場合にはREPAIR TABLEコマンドを使うし、最適化したい場合にはOPTIMIZE TABLEコマンドを使うのだが、これらのコマンドはWRITEだけでなくREADもブロックしてしまう。従って、メンテナンス中にWRITEは出来なくてもREADだけは可能にしたい、というような場合には、まずはALTER TABLEを試して見るといいだろう。テーブル定義の変更をせずに、テーブルを再作成したい場合には、次のようにALTER TABLEコマンドを実行するといい。

mysql> ALTER TABLE tbl1 ENGINE InnoDB;
mysql> ALTER TABLE tbl2 ENGINE MyISAM;

このようにストレージエンジンを指定してやると、ALTER TABLEコマンドによってテーブルの再作成が行われるのである。もちろん、ストレージエンジンは元のテーブルと同じものを指定する必要がある。(SHOW CREATE TABLEまたはSHOW TABLE STATUSコマンドでストレージエンジンを確認しよう。)

ALTER TABLEコマンドは意外と速い。テーブルの単純なコピーが行われるだけだからだ。MySQL公式のemployeesデータベースのsalariesテーブルには2844047行のデータが格納されているが、そのテーブルでも次の通りである。

mysql> ALTER TABLE salaries ENGINE InnoDB;
Query OK, 2844047 rows affected (49.76 sec)
Records: 2844047 Duplicates: 0 Warnings: 0

ただし、この値はあくまでも参考値ということで捕らえて欲しい。この値を測定したのはノートパソコン(ディスクは5400rpmのSATA)上であるので、H/W RAIDやSSDなどを使っている場合にはもっと良い数値になるだろう。また、行数が増えた場合には所要時間は線形に増加するわけでない点にも注意しよう。インデックスの再構築にはO(N log N)の時間がかかるからだ。10倍の行数がある場合には、10倍以上の時間がかかる。メンテナンス時間を見積もるには、試験環境で同程度の行数のテーブルを使ってテストしなければならない。

ちなみに、ALTER TABLEは操作が正常に完了するまでは元のテーブルに対して一切の変更を加えない。たとえコマンド実行中にマシンがクラッシュしても、テンポラリテーブルの残骸が残るだけで、元のテーブルは元通りである。そういう意味では、ALTER TABLEはとても安全な操作であるとも言える。

上記のようなメンテナンスでなく、本当にスキーマの変更をしたい場合には注意するべき点が一つある。コマンドが一回で終わるように、カラムやインデックスの追加・削除を一行で書くということである。一行でALTER TABLEを書くには、加えるべき変更をカンマで区切って羅列する。次のように。

mysql> ALTER TABLE tbl1 DROP INDEX idx1, DROP INDEX idx2... ADD INDEX (idxX);

こうすることで、コピーが一回で済むわけである。テーブルサイズが大きくなればなるほど、操作を一回で済ませることのメリットは大きくなる。

MySQLのALTER TABLEでは、カラムを任意の場所に追加することが出来る。何も指定しない場合は最後尾に追加されるが、FIRSTまたはAFTERオプションを指定することで、先頭または任意のカラムの後にカラムを挿入できるのである。これは、テーブルを再作成することのメリットである。

mysql> ALTER TABLE tbl1 ADD colY VARCHAR(100) AFTER colX, ADD colA INT UNSIGNED FIRST;

というわけで、今日はALTER TABLEコマンドを使う際のテクニックを紹介した。このエントリを読んでくれた方は、MySQL DBAにとって必須のコマンドであるALTER TABLEを上手に使いこなして欲しい。

2009-05-09

LINEAR HASHパーティショニングってなんだ?

MySQL 5.1から利用出来るパーティショニングの種類には、次の4つがある。
  • RANGEパーティショニング
  • LISTパーティショニング
  • [LINEAR] HASHパーティショニング
  • [LINEAR] KEYパーティショニング
RANGEパーティショニングは値の範囲を指定する。次のように日付を用いて範囲を指定するのが代表的な使い方だ。詳細はこちらの記事(パーティショニングの使用例 - http session情報)を見て欲しい。
mysql> CREATE TABLE http_session (
-> session_id VARCHAR(32) NOT NULL,
-> last_access TIMESTAMP NOT NULL,
-> created TIMESTAMP NOT NULL,
-> t_session_data VARCHAR(1024)
-> ...(中略)...
-> PRIMARY KEY (session_id, last_access))
-> ENGINE InnoDB
-> PARTITION BY RANGE (TO_DAYS(last_access)) (
-> PARTITION p000001 VALUES LESS THAN (TO_DAYS('2009-04-01')),
-> PARTITION p000002 VALUES LESS THAN (TO_DAYS('2009-04-02')),
-> ...(中略)...
-> PARTITION p000020 VALUES LESS THAN (TO_DAYS('2009-04-20')),
-> PARTITION pmax VALUES LESS THAN MAXVALUE
-> );

2012/02/02追記
このCREATE TABLE文はMySQL 5.1.43以降のバージョンではエラーになるので注意。詳細はリリースノートを参照のこと。TO_DAYSの代わりにUNIX_TIMESTAMPを使いましょう。(指摘サンクスです。)

LISTパーティショニングはパーティショニングに使用するカラムの値がいくつかしかない場合に利用できる。例えばDBT-2ベンチマークで利用するcustomerテーブルを次のようにパーティショニングできるだろう。
mysql> ALTER TABLE customer DROP PRIMARY KEY, ADD PRIMARY KEY (c_id, c_w_id);
mysql> ALTER TABLE customer PARTITION BY LIST (c_w_id) (
-> PARTITION p1 VALUES IN (0, 1, 2, 3),
-> PARTITION p2 VALUES IN (4, 5, 6, 7)
... 略(warehouseの数だけ続く) ...
-> );
HASHパーティショニングとKEYパーティショニングは次のように利用出来る。
mysql> ALTER TABLE Country PARTITION BY HASH (ContinentId) PARTITIONS 7;

HASHパーティショニングは行が格納されるパーティションを算出するのにMOD(剰余)を利用し、KEYパーティショニングはPASSWORD()関数を使ってハッシュ値を算出する。PASSWORD関数を利用するので、文字列に対しても利用することが出来る。文字列のカラムを使ってパーティショニング出来るのは、KEYパーティショニングだけである。他のパーティショニング手法では、必ず整数値を用いなければならない。

さて、ようやくここからが本題である。(前置きなげーよ!>俺)

LINEAR HASHとはいかなるものだろうか。一応マニュアルににも説明はあるが、いまいち容量を得ない。LINEAR HASHには利点と欠点があり、適切に利用すればとてもメリットがある手法なので「使い方が分からないので使わない」のでは勿体ない。というわけで今日はLINEAR HASHについて解説しようと思う。

パーティショニングの定義はLINEAR HASHというキーワードを用いること以外、HASHパーティショニングと変わらない。例えば次のように定義することができる。
mysql> ALTER TABLE some_table PARTITION BY LINEAR HASH (col) PARTITIONS 10;

だが、行を格納するパーティションの算出方法が決定的に違う。MODではなく次のように論理積を使ったアルゴリズムを用いているので計算が非常に速いのである。
  1. パーティション数Nより大きいか同じものの中で、最小の2の累乗Vを求める。上記の例では、V(10より大きいか同じものの中で最小の2の累乗)は16である。

  2. 次の式でパーティションを求める。

    p = col & (V - 1)

    例えばcolが20の場合、20 & (16-1) = b'10100' & b'1111' = b'100' = 4 である。

  3. もし求められた値がパーティション数Nより大きいか同じ場合は、さらに次の式でパーティションを算出する。

    p' = p & (V/2 - 1)

    例えばcolが30の場合、30 & (16 - 1) = b'11110' & b'1111' = b'1110' = 14となり、これはパーティション数Nよりも大きい。従って、さらに 14 & (16/2 - 1) = 14 & 7 = b'1110' & b'111' = b'110' = 6という具合にパーティションを求めるわけである。
LINEAR HASHパーティショニングでは、各パーティションに格納される行数に偏りが出てしまう。上記の例では、最初の式で求められた値が10より大きいか同じ場合はさらに再計算されて0〜7の8つのパーティションに格納されることになるので、残りのパーティション8および9に格納される行数は少なくなってしまう。このようなことが起こらないようにするには、パーティション数を2の累乗、つまり2、4、8、16、32、64、128、256、512、1024のいずれかにすれば良い。そうすればパーティションを求める計算も一度で済むから高速である。

LINEAR HASHの利点は、HASHよりも計算が高速な点である。テーブルが大規模な場合には、HASHではなくLINEAR HASHの利用を検討するといいだろう。

LINEAR KEYパーティショニングは、PASSOWRD()関数で求められたハッシュ値に対して、さらに上記のアルゴリズムを用いてパーティションを算出する手法である。こちらもテーブルが大規模な場合に利用を検討するといい。

まとめ

LINEAR HASHパーティショニングのアルゴリズムは剰余ではなく論理積を用いるため非常に高速である。テーブルが大きい場合にはHASH/KEYではなくLINEAR HASH/LINEAR KEYパーティショニングを利用すること。ただしパーティション数は2の累乗で!