記事一覧    ブログパーツ    carp_qr    まとめったー    deliciousブクマ数API    リンク集

InnoDBで行ロック/テーブルロックになる条件

MySQL にはよく使われるストレージエンジンとして MyISAM と InnoDB がありますが、違いの一つとしてロックの挙動が挙げられます。MyISAM はテーブルロック、InnoDB は行ロックが掛かるというのは有名な話じゃないかと。

ただ、最近知ったのですが、InnoDB だとしても必ずしも行ロックになるわけではなく、テーブルロックになる場合もあるようですね。。このことについて手元の MySQL 5.1.26RC で簡単ですが検証してみます。サンプルとして使うテーブルはこちら。

CREATE TABLE `lock_sample` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `c1` int(11) NOT NULL,
  `c2` int(11) NOT NULL,
  `val` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

サンプルデータとしてこのようなデータを用意しました。で、カラム c2 にはインデックスを張ります(カラム c1 はインデックス無し)。

+----+------+------+------+
| id | c1   | c2   | val  |
+----+------+------+------+
|  1 |   64 |  654 | NULL | 
|  2 |  234 |   53 | NULL | 
|  3 | 2435 |  324 | NULL | 
|  4 |    3 |   23 | NULL | 
|  5 |   45 | 3512 | NULL | 
|  6 |  324 |   14 | NULL | 
|  7 |   46 |  658 | NULL | 
|  8 |  654 |  658 | NULL | 
|  9 |   14 |  156 | NULL | 
+----+------+------+------+
9 rows in set (0.06 sec)

ALTER TABLE `lock_sample` ADD INDEX `c2` (`c2`);

これで準備は完了です。まずは primary key に対しての SQL でどういうロックが掛かるのか見てみましょう。まず、ある primary key に対して update します(コネクション1)。その後、別のコネクションで接続し、こちらでは別の primary key に対して update します(コネクション2)。このとき、コネクション1の処理は行ロックとなるため、コネクション2ではすぐに処理が行われます。

mysql1> START TRANSACTION;
Query OK, 0 rows affected (0.02 sec)

mysql1> UPDATE `lock_sample` SET val = "hoge" WHERE id = 3;
Query OK, 1 row affected (0.04 sec)
Rows matched: 1  Changed: 1  Warnings: 0

--- 別のコネクション

mysql2> START TRANSACTION;
Query OK, 0 rows affected (0.02 sec)

mysql2> UPDATE `lock_sample` SET val = "fuga" WHERE id = 4;
Query OK, 1 row affected (0.05 sec)
Rows matched: 1  Changed: 1  Warnings: 0

これは、インデックスを張った c2 でも全く同様でした。では、インデックスを張っていない c1 ではどうでしょうか??

mysql1> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)

mysql1> UPDATE `lock_sample` SET val = "foo" WHERE c1 = 45;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

--- 別のコネクション

mysql2> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)

mysql2> UPDATE `lock_sample` SET val = "bar" WHERE c1 = 3;
ERROR 1205 (HY000): Lock wait timeout exceeded

この場合には、ロック待ち時間の上限( innodb_lock_wait_timeout で設定された秒数。デフォルトでは 50 秒)を超えて強制ロールバックされるか、もしくはコネクション1を明示的に commit or rollback するまで処理が待たされます。

これ、最初は「インデックスを張らないと行ロックにならないの?」とか思ったんですが、そういうわけではないようです。試しに c1 にユニーク制約を貼ってみたら行ロックされることを確認しました。

ALTER TABLE `lock_sample` ADD UNIQUE (`c1`);

mysql1> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)

mysql1> UPDATE `lock_sample` SET val = "foo" WHERE c1 = 45;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

--- 別のコネクション

mysql2> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)

mysql2> UPDATE `lock_sample` SET val = "bar" WHERE c1 = 3;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

というわけで、InnoDB であってもユニーク制約 or インデックスが張られているカラムで検索した場合以外はテーブルロックになってしまうようです。これは注意しないと思わぬところでテーブルロックになってしまって大変なことになりそう!

・ユニーク制約 or インデックスが貼られているカラムで検索した場合、行ロック
・それ以外のカラムで検索した場合、テーブルロック


というわけで、InnoDB を使う方は行ロック/テーブルロックの発生する条件に気を付けてください ノシ

Cloudera を使って CentOS に Hadoop on EC2 な環境を整える 第二回

Clouderaのロゴ   amazon_aws

前回の続きです。前回はローカルに Hadoop をインストールするところまで行ったので、今回は EC2 上で Hadoop を使える環境まで構築してみます。

python スクリプトの hadoop-ec2 を手に入れる

Cloudera_3

まずは指示に従い、cloudera-for-hadoop-on-ec2-py-0.3.0-beta.tar.gz をダウンロードし、適当な場所に解凍後、パスを通します。この中に hadoop-ec2 という python スクリプトがあり、これを利用して EC2 上にインスタンスを起動したりします。このように利用します。

# 現在起動しているインスタンスの一覧を見る
hadoop-ec2 list

# [cluster] の master, slave の一覧を見る
hadoop-ec2 list [cluster]

# [cluster] として slave を [num] 個起動する( master は勝手に起動)
hadoop-ec2 launch-cluster [cluster] [num]

# [cluster] の master に ssh ログインする
hadoop-ec2 login [cluster]

# [cluster] を停止する
hadoop-ec2 terminate-cluster [cluster]

python とか boto とか simplejson を入れろ、と書いてあるので入れましょう。僕の環境では yum で python は 2.4 が入っていたんですが、2.5 以上を入れなくてはいけません。が、yum では入らない。。。ので、Python/インストール/Linux/Python - MinacoWiki を参考にして python 2.6.2 をインストールしました。boto と simplejson もソースを取って来て、手順に書かれているように

sudo python setup.py install

とすれば大丈夫です。simplejson は最初うまくインストール出来なかったけど、blog.comewalk.com: simplejson と setuptools と私 を参考にしたらすんなりいけました。

環境変数と設定ファイル

Cloudera_4

次に、.bashrc なり .zshrc なりに環境変数を設定します。これは Amazon AWS のサービスを利用するために必要なアクセスキーとシークレットキーです。これは Amazon AWS に会員登録後、Your Account の Security Credentials にアクセスすると見ることが出来ます。

Amazon_AWS

EC2 上に作成する Hadoop クラスタの設定ファイルを作成します。こんな感じです。

# ~/.hadoop-ec2/ec2-clusters.cfg
[sasata299-cluster] # クラスタに適当な名前を付ける、何でもおk
ami=ami-6159bf08 # 利用する AMI (インスタンス)の名前
instance_type=m1.small # 利用する AMI のタイプ
availability_zone=us-east-1c # 利用する EC2 のデータセンターの場所
key_name=sasata299's key pair # 秘密鍵の名前(ファイル名じゃない)
private_key=/home/sasata299/sasata299skeypair.pem # 秘密鍵の場所
ssh_options=-i %(private_key)s -o StrictHostKeyChecking=no

ssh 接続するために利用する秘密鍵の作成は、EC2 のコンソールの左側メニューの一番下 Key Pairs より作成してください。あ、EC2 を利用する際にはクレジットカードの登録が多分必須なのでそれも必要だったら登録してください。

Amazon_AWS_EC2

Cloudera を使って EC2 上に Hadoop クラスタを構築

ここまでくれば一通りのことが出来るようになっているはずです。実際にクラスタを構築してみましょう。ここでは slave 2 台、master 1 台のクラスタを起動してみます。

$ hadoop-ec2 launch-cluster sasata299-cluster 2

Waiting for master to start (Reservation:r-edbe6b85)
...................................................
master  ami-6159bf08    ec2-174-129-135-13.compute-1.amazonaws.com
Waiting for slaves to start
......................................................................
slave   ami-6159bf08    ec2-174-129-130-228.compute-1.amazonaws.com
slave   ami-6159bf08    ec2-72-44-60-235.compute-1.amazonaws.com
Waiting for jobtracker to start
.............................
Waiting for 2 tasktrackers to start
...............................................1............2.
Browse the cluster at http://ec2-174-129-135-13.compute-1.amazonaws.com/

master が 1 台、slave が 2 台起動出来ました!ログインも出来ました!

Cloudera_ログイン

ということで簡単ですが、これで EC2 上で Hadoop クラスタを構築することに成功しました。こういう環境が個人で簡単に作れるようになったというのはほんと素晴らしいですね゚+。*゚+。(*´Д`)

Cloudera を使って CentOS に Hadoop on EC2 な環境を整える 第一回

   Clouderaのロゴhadoop-logo

Hadoop のことをもっと知るために、Cloudera を使って Hadoop 環境を整えてみようと思います。Cloudera のインストールガイド を参考に進めてみます。OS は CentOS 5.2 です。

Cloudera's Distribution for Hadoop (CDH)

まず、yum のリポジトリに cloudera-stable.repos と cloudera-testing.repos を追加します。これで yum から Hadoop のインストールが出来るようになります。便利ですね〜。

Cloudera_1

ちなみに、cloudera-stable の方は Hadoop-0.18 が、cloudera-testing の方は Hadoop-0.20 が組み込まれています。cloudea-stable は十分に検証が行われていて、エンタープライズで利用しても問題が無いレベル、cloudera-testing は一通りのテストは終えているが、本番環境で利用するとバグを踏む可能性が残っているという違いがあるので注意してください。

で、yum のリポジトリを追加して早速 Hadoop をインストールしようとしたらこんなエラーが出てきます。。

Resolving Dependencies
--> Running transaction check
--> Package hadoop.noarch 0:0.18.3-5.cloudera.CH0_3 set to be updated
--> Processing Dependency: jdk >= 1.6 for package: hadoop
--> Finished Dependency Resolution
Error: Missing Dependency: jdk >= 1.6 is needed by package hadoop

JDK のインストール

調べてみたら Cloudera のサイトに そのものズバリな回答 がありました。やったね☆回答にそってやってみます。bin ファイルを実行したときに、can't create transaction lock on /var/lib/rpm/__db.000 というエラーが出るけどこれは無視すれば良いようです。

その後、改めて Hadoop をインストールしてみると、、

$ sudo yum install hadoop-0.20

Loading "fastestmirror" plugin
Loading mirror speeds from cached hostfile
* base: rsync.atworks.co.jp
* updates: ftp.iij.ad.jp
* cloudera-testing: archive.cloudera.com
* addons: rsync.atworks.co.jp
* cloudera-stable: archive.cloudera.com
* extras: rsync.atworks.co.jp
base                100% |=========================| 2.1 kB    00:00     
updates             100% |=========================| 1.9 kB    00:00     
addons              100% |=========================|  951 B    00:00     
cloudera-stable     100% |=========================|  951 B    00:00     
extras              100% |=========================| 1.1 kB    00:00     
Setting up Install Process
Parsing package install arguments
Resolving Dependencies
--> Running transaction check
--> Package hadoop-0.20.noarch 0:0.20.1+152-1 set to be updated
--> Finished Dependency Resolution

Dependencies Resolved

=======================================================================
Package           Arch       Version          Repository        Size 
=======================================================================
Installing:
hadoop-0.20       noarch     0.20.1+152-1     cloudera-testing   18 M

Transaction Summary
=======================================================================
Install      1 Package(s)         
Update       0 Package(s)         
Remove       0 Package(s)         
        
Total download size: 18 M
Is this ok [y/N]: y
Downloading Packages:
(1/1): hadoop-0.20-0.20.1 100% |=========================|  18 MB
Running rpm_check_debug
Running Transaction Test
Finished Transaction Test
Transaction Test Succeeded
Running Transaction
Installing: hadoop-0.20      ######################### [1/1] 
          
Installed: hadoop-0.20.noarch 0:0.20.1+152-1
Complete!

ローカルで Hadoop の動作確認を行う

出来たー。Hadoop 入りました!ここまでで、Hadoop をローカル(手元のマシン)で動かすことが出来るようになっているはずです。指示の通りに試してみましょう。/etc/hadoop-0.20/conf/hadoop-env.sh の JAVA_HOME だけは先に設定しておいた方が良さそうです。java が /usr/bin/java にインストールされている場合、/usr を設定します。

Cloudera_2

よし、動きました。ではここからは Hadoop を Amazon EC2 上で動かし、Hadoop クラスタを作れるように設定していきます。・・と思ったけど長くなったので次回に続きます。(^^;

Hadoop Conference Japan 2009 に参加してきました!

最近人気が出てきている、ゾウのマークでおなじみの Hadoop 。本日、日本で一回目の Hadoop カンファレンスである Hadoop Conrefence Japan 2009 が開催されました。そこで、最近 Hadoop を使っているものとして「これは参加しないとっ!」ということで参加。そのときの内容を簡単にまとめます。

Hadoop

Hadoop入門

PFI の西川さんによる、そもそも Hadoop とは何なのか?何故必要なのか?という話でした。Hadoop とは何か?についてはこの辺を見ていただくとして

Hadoop、hBaseで構築する大規模分散データ処理システム(1/2):CodeZine
Hadoop、hBaseで構築する大規模分散データ処理システム(2/2):CodeZine

何故 Hadoop のような分散処理が必要になったのか?という方が気になるところです!

近年、爆発的な勢いでデータは増えてきています。例えば Web サイト(ブログ?)をクローリングするとなると、全部で 200 億ページくらい。一つ 20KB だとしても約 400TB です。これだけの規模になってくると標準的なディスク ( 50MB/sec くらい?) だと読み込むだけで約 100 日、保存するとしても 500GB のディスクが 1000 個も必要です。ちょーー大変です。

少し前までは、こういった話は Google だけの問題だったかもしれません。でも爆発的にデータ量は増えてきていて、今では多くの企業、分野がこの問題に直面してきているのでは?そういった流れで、分散処理の必要性がどんどん高まってきているわけですね。

さらに、Hadoop を Mapper, Reducer を書いて利用するのではなく、SQL のような専用言語を使って、Mapper, Reducer をあまり意識する必要の無い PigHive についての紹介もありました。

楽天市場のHadoop利用事例

楽天の会員IDは、20万/月ずつ増加しているそうです。各種ログもどんどん増えている。そういった増え続けるデータに対して、広告のインプレッションログ解析やレコメンデーション、製品ランキングのデータ集計などのデータ処理に Hadoop を使っている。ちなみに先日リリースされた ROMA はデータ管理に利用されているとのこと。今開発が進められている分散処理フレームワーク Fairy では ROMA と連携する機能もあるそうです。使いたい。。

で、Perl でがしがしやっていた頃と比べて 580% になったそうです。速度ももちろんだけど、スケーラビリティを確保出来たのが大きいとのことでした。確かに!!

後は「集合知プログラミングを Hadoop 上で行う」という話が面白かったです。利用者のデータを利用して解析し、ユーザがもっと便利に、もっと楽しくなるようなデータを作り出すというのが集合知プログラミングですが、その手法の一つである k-means を、Hadoop 上で行おうと思ったらすでにそのための Apache Mahout というフレームワークがあったそうです(またゾウか!)。やっぱりみんなやりたいことは同じなんですねぇ。

Scala on Hadoop

はてなの田中さんによる、はてなでの Hadoop 利用事例の話でした。以前は Hadoop Streaming を使って Perl で記述していて、利用の際には Map とか Reduce とかのクラスを作り、YAML でどれを利用するかを指定して運用していたそうです。ただ、Hadoop Streaming ではどうしても以下のような問題(限界)が出てきてしまうとのことでした。。

1) CPU を食う
2) ジョブを KILL しても Perl の子プロセスが残っていたりする
3) HDFS 上のファイル操作が遅い
4) Combiner (Mapper の出力を iterater にして Reducer に渡したり?) が定義できない
5) 標準入出力のオーバーヘッドが大きい

そこで JVM 上で動く Scala を使ってみた、というお話でした。Scala も相当良さそうです。Java と比べるとだいぶコード量が少ない!

HadoopでかんたんWikipediaデータ処理

Amazon AWS の Amazon Elastic MapReduce というサービスを利用して、wikipedia のデータで大規模なデータ処理をした話でした。まぁ、EC2 上に自分で Hadoop クラスタを構築すれば良いのでわ?と思いましたが、EC2 上にインスタンスを作ることすら自動でやってくれるというイメージでしょうか。Mapper と Reducer を作るだけで Hadoop を使った分散処理が行えます。それと Elastic MapReduce では出力は自動的に? S3 に保存されるようです。あと、PageRank を決める方法も非常に興味深かったです。こうやって決まるものなのか〜。

Hadoop World 2009報告

10月に行われた Hadoop World New York '09 の報告セッションでした。Yahoo! が 25,000 ノード使ってて、Hadoop の最大のユーザだとか、facebook の扱うデータ量(一日のログサイズ?)が 2008/3 に 200GB だったものが 2009/4 には圧縮した状態で 2TB 以上、2009/10 には圧縮状態で 4TB 以上と文字通り爆発的に増加しているという話は驚きでしたが、VISA や JPモルガン などの Web 系の企業でも確実に Hadoop の需要が高まっている (Hadoop しか選択肢が無い)というのが意外でした。

あと、シリコンバレーの失業率は 12% と意外と高いですが、Hadoop 周りのエンジニアは引く手数多だそうですw やはりどの企業にとっても大量のデータの処理は課題なんですね。

SI事業の視点から見た Hadoop の適用領域と今後の展望

NTTデータの政谷さんによるセッション。NTTデータでもかなり Hadoop を利用しているんですねぇ。意外でした。もともと PostgreSQL を長年使ってきているそうで、Hadoop で二匹目のゾウを育てるとかw

Hadoop/HBase 開発

最後のセッションは HBase について。HBase って Google の BigTable のクローンということで、名前は知ってましたが具体的にどんなものかっていうのはよく知りませんでした。

そもそも HDFS ってブロックサイズ(デフォルトだと 64MB )単位でデータを格納していて、ブロック単位でデータを扱うのは得意ですが、もっと小さなデータの扱いは苦手です。そういう小さなデータをまとめて取り扱うのが得意なのが HBase みたいです。HDFS 上に保存されているデータに対してリアルタイムにランダムな読み書きをすることが出来るということで、分散 key/value ストアな感じなんですね。

RDBMS と違って、一つのカラムの中にタイムスタンプ付きで複数の値を格納できたり、複数のカラムを一つのグループ(カラムファミリ)としてまとめて管理したり出来るようです。

クロージング

日系コンピュータの記者の方のプレゼンが最後にあったんですが、非常に面白い内容でした。なんでも Yahoo! では Hadoop クラスタを構成しているたくさんのサーバをコンテナ型のデータセンターを利用していて、しかもそのコンテナは本社の駐車場によっこらせと置いているんだそうです。具体的な数字はちょっとメモってませんが、一台のコンテナで相当な CPU やメモリ、HDD でした。

Google ではかなり昔からそういう運用になっていて、ジャスコの駐車場みたいなところにコンテナをがしゃーんがしゃーんと置いているとかw ジャスコの駐車場w なぜにジャスコww

懇親会

最後に懇親会に参加してきました。もともとは 2,000 円程度掛かるとの話だったのですが、無料に!ありがとうございます!

で、たくさんの方とお話することが出来て、楽しい時間が過ごせました。ちょっと意外だったのは、実際に Hadoop を使っているという方はまだ少なくて、「興味がある」、「使ってみたい」、という方が多かったことです。これからどんどん使われだすかもしれないですね。あと、困っていることのヒントも聞けたりして良かった><

というわけで、簡単ですが(一部のセッションは割愛してます)こんな感じでした。関係者の皆様、このような楽しいカンファレンスを開催していただき、どうもありがとうございました。第二回もぜひ参加させていただきます!

階層の深いHashを作成するときに知っておいたら便利なこと

Ruby で階層の深いハッシュ(ハッシュの値がさらにハッシュとか)を作成するのって面倒です。何が面倒って毎回宣言しないといけないんですよー。まぁ他の言語やってた人なら当たり前なのかもしれませんが、Perl 出身の僕としては大変メンドクサイわけです。

例えばこのようなデータ構造を考えてみます。

#!/usr/bin/ruby

hash = {}

hash["hoge"] = 1
p hash # {"hoge"=>1}

hash["foo"]["bar"] = 1
p hash # undefined method `[]=' for nil:NilClass (NoMethodError)

最初に hash = {} と宣言しているので hash["hoge"] = 1 の部分は問題なく定義できますが、その後の hash["foo"]["bar"] = 1 の部分でエラーが出ています。hash["foo"] は nil なので []= メソッドが無いですよ、というわけです。

これを回避するためにはこのようにすれば問題無いです。最近まではこうやってました。

#!/usr/bin/ruby

hash = {}
hash["foo"] = {} # hash["foo"] はハッシュだと宣言してあげる

hash["foo"]["bar"] = 1
p hash # {"foo"=>{"bar"=>1}}

ただこれだとハッシュのキー毎にいちいち宣言しないといけないし、何よりも見た目が良くありません。そこで今回紹介するちょいテクですよ。このようにすれば良いようです。

#!/usr/bin/ruby

hash = Hash.new { |h,k| h[k] = {} }

hash["foo"]["bar"] = 1
p hash # {"foo"=>{"bar"=>1}}

3行目がミソです。簡単に説明しときます。

hash = Hash.new { |h,k| h[k] = __DEFAULT__ }

# hash はハッシュとして定義される
# ブロックに渡される h は hash のこと。k は ハッシュのキーを表す
# h[k] が定義されていない場合、デフォルト値として __DEFAULT__ が使われる

今回の場合だと、hash["foo"]["bar"] が参照されたときに hash["foo"] が定義されていないため、自動的に {} が代入されます。他のキー(例えば hash["xxx"] )が参照されるときも同様で、未定義であれば {} が代入されます。これは便利。

ちなみに Perl だとこんな感じです。なぁーんにも問題ありません。何というフリーダム!!

#!/usr/bin/perl

use strict;
use warnings;

my $hash = {};

$hash->{"foo"}->{"bar"} = 1;

use Data::Dumper;
print Dumper $hash; # エラーは出ません
<<  2009年11月  
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30          
ニコニコ時計
ニコニコ動画の公式ガジェット「ニコガジェ(時計編)」
ささたつについて
あわせて読みたいブログパーツ


作ったもの
http://twitter.com/matometter
http://netaru.sasata299.com/
http://rank.sasata299.com/
http://sbm.sasata299.com/
http://twitter.com/carp_qr
twitter
twitter / sasata299
はてブとか
この日記のはてなブックマーク数
人気ブログランキングへ
にほんブログ村 IT技術ブログへ

RubyKaigi2009
Archives
Amazonサーチ
記事検索
RSS登録
Subscribe with livedoor Reader

購読者数


ブックマーク数