ありんこオフィスに行ってみた
シェアオフィス、コアワーキングスペースのありんこオフィスに先日行ってみました。
土曜日のお昼すぎでしたが、賑わっていてほぼ満席でした。
良い所
- ドロップインで一日ずっといても¥1000で利用できる
- フリードリンクがそこそこ豊富
- 食べ物持ち込みOK
微妙だったところ
- 椅子と机が長時間作業するにはちょっとつらい→一部良い椅子があったので運がよければ大丈夫
Gitのお便利設定
Gitを使い始めたらやっておきたい便利な設定いろいろ : アシアルブログ
bashのプロンプトにブランチ名を表示する際、上記エントリの情報だと古くてエラーになる。
-bash: __git_ps1: command not found
bash_completionで「-bash: __git_ps1: command not found」となった時の対処法 - くりにっき
こっちも参考にしつつ
git/contrib/completion/git-prompt.sh at master · git/git · GitHub も入れればOK
nokogiriとMechanizeでスクレイピングその1
趣味の関係でmixiをたまに使うのですが、(毎日見てないので)特定のコミュの書き込みがあったらメール飛んでくるようにしたいなと思いチャレンジ。
とりあえずログインして中の情報をなんとなくとってくるとこまで。
文字コードをちゃんと設定してないせいか、\nがたくさん出てる。
参考
スクレイピングのためのNokogiri利用メモ - それはそれ。これはこれ。
エンジニアの給料
エンジニアに最も高給を支払っている企業は意外にも・・・? | THE NEW CLASSIC
うーん、高いですね。
どの企業も世界的企業なので、単純に日本の企業と比較はできないかもしれませんが、やっぱりすごく高いと感じちゃいますね。
日本の企業で高そうなイメージだとDeNAとGreeでしょうか。
DeNA、GREE、サイバーエージェントの平均年収を比較してみた | CyberTimes [シバタイムス]
仕事の報酬は仕事
こんな記事がTLに流れてきました。
スタバはなぜ値下げやテレビCMをしない?高いブランド力構築の戦略を元CEOに聞く
http://zasshi.news.yahoo.co.jp/article?a=20131012-00010000-bjournal-bus_all&1381526511
この記事の中で気になったのが、「仕事の報酬は仕事」という言葉。
調べてみたら、昔からある言葉みたいですね。(誰が最初か、というのはよくわかりませんでしたが)
良い言葉だとは思いますが、一歩間違うと社畜一直線にもなってしまうので、使い方には注意が必要だなーと感じました。
http://www.gexeed.co.jp/column/cl018.html
http://bizmakoto.jp/makoto/articles/1106/08/news012.html
http://www.esofken.com/rensai/1011.html
仕事の報酬でより良い仕事を得て、その循環の先に何があるのか。
だから、給料は大事じゃない(低くても良い)って論調になると、違うんじゃないかな、と思います。どっちが大事って事ではなく、どっちも大事。
私は仕事が好きですが、仕事以外にも好きな事がいっぱいあるので、それを実現するためにはお金と時間が必要です。
結局、多くの人にとって人生の大部分を占める仕事において、何を求めるか、という哲学的な話になってくるのでしょうか。。。
InnoDBとREPEATABLE READとSELECT FOR UPDATEと楽観ロックその2
前回の話に排他(行ロック)を絡めてみる。
Versionカラムを使った楽観ロックをしてみます。
■ストーリー
1.セッション1 トランザクション開始
2.セッション2 トランザクション開始
3.セッション1 行情報取得→versionカラムを使って楽観ロックをした更新→commit or rollback
4.セッション2 行情報取得→versionカラムを使って楽観ロックをした更新→commit or rollback
楽観ロックなので、1行も更新できなかった場合はrollbackする想定です。
長いので1,2は省略しちゃいます。
READ COMMITTED
セッション1mysql> select * from Version; +----+------+---------+ | id | text | version | +----+------+---------+ | 1 | init | 1 | +----+------+---------+ 1 row in set (0.00 sec) mysql> update Version set text = 'updatedFromSession1' , version = version + 1 where id = 1 and version = 1; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> commit; Query OK, 0 rows affected (0.00 sec)
セッション2
mysql> update Version set text = 'updatedFromSession2' where id = 1 and version = 2; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> commit; Query OK, 0 rows affected (0.00 sec)
通ってしまいます。
REPEATABLE READ
セッション1mysql> select * from Version; +----+------+---------+ | id | text | version | +----+------+---------+ | 1 | init | 1 | +----+------+---------+ 1 row in set (0.00 sec) mysql> update Version set text = 'updatedFromSession1' , version = version + 1 where id = 1 and version = 1; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> commit; Query OK, 0 rows affected (0.00 sec)
セッション2
mysql> select * from Version; +----+---------------------+---------+ | id | text | version | +----+---------------------+---------+ | 1 | updatedFromSession1 | 2 | +----+---------------------+---------+ 1 row in set (0.00 sec) mysql> update Version set text = 'updatedFromSession2' where id = 1 and version = 2; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> commit; Query OK, 0 rows affected (0.00 sec)
こちらも通ってしまいます。
ここでストーリーを少し変えて、
■ストーリー
1.セッション1 トランザクション開始、tempテーブルselect
2.セッション2 トランザクション開始、tempテーブルselect
3.セッション1 行情報取得→versionカラムを使って楽観ロックをした更新→commit or rollback
4.セッション2 行情報取得→versionカラムを使って楽観ロックをした更新→commit or rollback
tempテーブルのselectを入れただけです。(for updateは無し)
READ COMMITTED
セッション1
mysql> select * from Version; +----+------+---------+ | id | text | version | +----+------+---------+ | 1 | init | 1 | +----+------+---------+ 1 row in set (0.01 sec) mysql> update Version set text = 'updatedFromSession1' , version = version + 1 where id = 1 and version = 1; Query OK, 1 row affected (0.01 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> commit; Query OK, 0 rows affected (0.00 sec)
セッション2
mysql> select * from Version; +----+---------------------+---------+ | id | text | version | +----+---------------------+---------+ | 1 | updatedFromSession1 | 2 | +----+---------------------+---------+ 1 row in set (0.00 sec) mysql> update Version set text = 'updatedFromSession2' where id = 1 and version = 2; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> commit; Query OK, 0 rows affected (0.00 sec)
変更前と同じ。
REPEATABLE READ
セッション1
mysql> select * from Version; +----+------+---------+ | id | text | version | +----+------+---------+ | 1 | init | 1 | +----+------+---------+ 1 row in set (0.00 sec) mysql> update Version set text = 'updatedFromSession1' , version = version + 1 where id = 1 and version = 1; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> commit; Query OK, 0 rows affected (0.00 sec)
セッション2
mysql> select * from Version; +----+------+---------+ | id | text | version | +----+------+---------+ | 1 | init | 1 | +----+------+---------+ 1 row in set (0.00 sec) mysql> update Version set text = 'updatedFromSession2' where id = 1 and version = 1; Query OK, 0 rows affected (0.00 sec) Rows matched: 0 Changed: 0 Warnings: 0 mysql> rollback; Query OK, 0 rows affected (0.00 sec)
なんと結果が変わります。
REPEATABLE READの場合、最初のselectのタイミングで取得するデータのスナップショットが決まるらしいです。
http://dev.mysql.com/doc/refman/5.1/ja/innodb-consistent-read.html
今回だと、2でtempをselectした時点でセッション2中でselectの結果として返ってくる値が全テーブルで確定するようです。
というわけで、1,2の処理にinsertやらが入っていても、REPEATABLE READなら排他がばっちり決まります。
またストーリーを少し変えてみます。
■ストーリー
1.セッション1 トランザクション開始、tempテーブルselect
2.セッション2 トランザクション開始、tempテーブルselect
3.セッション1 行情報取得(for update)
4.セッション2 行情報取得(for update)※トランザクション1のコミット待ち
5.セッション1 versionカラムを使って楽観ロックをした更新→commit or rollback
6.セッション2 versionカラムを使って楽観ロックをした更新→commit or rollback
楽観ロックがかかってるのに、for updateで悲観ロックをかけたとします。
で、コミットのタイミングを変えました。
READ COMMITTED
セッション1mysql> select * from Version where id = 1 for update; +----+------+---------+ | id | text | version | +----+------+---------+ | 1 | init | 1 | +----+------+---------+ 1 row in set (0.00 sec)
セッション2
mysql> select * from Version where id = 1 for update;
ロック開放待ち。
セッション1
mysql> update Version set text = 'updatedFromSession1' , version = version + 1 where id = 1 and version = 1; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> commit; Query OK, 0 rows affected (0.00 sec)
セッション2
+----+---------------------+---------+ | id | text | version | +----+---------------------+---------+ | 1 | updatedFromSession1 | 2 | +----+---------------------+---------+ 1 row in set (8.33 sec) mysql> update Version set text = 'updatedFromSession2' where id = 1 and version = 2; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> commit; Query OK, 0 rows affected (0.00 sec)
REPEATABLE READ
セッション1mysql> select * from Version where id = 1 for update; +----+------+---------+ | id | text | version | +----+------+---------+ | 1 | init | 1 | +----+------+---------+ 1 row in set (0.00 sec)
セッション2
mysql> select * from Version where id = 1 for update;
ロック開放待ち。
セッション1
mysql> update Version set text = 'updatedFromSession1' , version = version + 1 where id = 1 and version = 1; Query OK, 1 row affected (0.01 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> commit; Query OK, 0 rows affected (0.00 sec)
セッション2
+----+---------------------+---------+ | id | text | version | +----+---------------------+---------+ | 1 | updatedFromSession1 | 2 | +----+---------------------+---------+ 1 row in set (7.38 sec) mysql> update Version set text = 'updatedFromSession2' where id = 1 and version = 2; Query OK, 1 row affected (0.01 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> commit; Query OK, 0 rows affected (0.00 sec)
なんと、通ってしまいました。
REPEATABLE READでトランザクション開始後に1度selectしていても、select for update をかけると他トランザクションの影響を受けてしまうようです。
まとめ
REPEATABLE READの場合、READ COMMITTEDに比べて楽観ロックがシビアに効くこと場合がある。ただし、select for updateで悲観ロックするとREAD COMMITTEDの場合と同じになる。
既存処理で、楽観ロックだけどシビアに排他が効いてる処理を、
何気なく悲観ロック追加すると挙動が変わる場合があるので注意する。
InnoDBのトランザクションは、ネクストキーロックとかもあって、
ハマるポイントが多いですね。。
InnoDBとREPEATABLE READとSELECT FOR UPDATEと楽観ロックその1
現場でちょっとはまった話。
InnoDBのトランザクション分離レベルhttp://dev.mysql.com/doc/refman/5.1/ja/innodb-transaction-isolation.html
InnoDBはトランザクション分離レベルが選べますが、
デフォルトは「REPEATABLE READ」です。
Oracleは「READ COMMITTED」に近いとの事。(どこが違うんだろう。。)
じゃあこの2つどう違うかというと、
READ COMMITTED
セッション1mysql> begin; Query OK, 0 rows affected (0.00 sec) mysql> select * from Version; +----+------+---------+ | id | text | version | +----+------+---------+ | 1 | init | 1 | +----+------+---------+ 1 row in set (0.00 sec)
セッション2
mysql> begin; Query OK, 0 rows affected (0.00 sec) mysql> select * from Version; +----+------+---------+ | id | text | version | +----+------+---------+ | 1 | init | 1 | +----+------+---------+ 1 row in set (0.00 sec)
セッション1
mysql> update Version set text = 'updated' , version = version + 1 where id = 1; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> select * from Version; +----+---------+---------+ | id | text | version | +----+---------+---------+ | 1 | updated | 2 | +----+---------+---------+ 1 row in set (0.00 sec)
セッション2
mysql> select * from Version; +----+------+---------+ | id | text | version | +----+------+---------+ | 1 | init | 1 | +----+------+---------+ 1 row in set (0.00 sec)
セッション1
mysql> commit; Query OK, 0 rows affected (0.00 sec) mysql> select * from Version; +----+---------+---------+ | id | text | version | +----+---------+---------+ | 1 | updated | 2 | +----+---------+---------+ 1 row in set (0.00 sec)
セッション2
mysql> select * from Version; +----+---------+---------+ | id | text | version | +----+---------+---------+ | 1 | updated | 2 | +----+---------+---------+ 1 row in set (0.00 sec) mysql> commit; Query OK, 0 rows affected (0.00 sec) mysql> select * from Version; +----+---------+---------+ | id | text | version | +----+---------+---------+ | 1 | updated | 2 | +----+---------+---------+ 1 row in set (0.00 sec)
セッション1がコミットした段階で、セッション2にも更新が反映されました。
REPEATABLE READ
セッション1mysql> begin; Query OK, 0 rows affected (0.00 sec) mysql> select * from Version; +----+------+---------+ | id | text | version | +----+------+---------+ | 1 | init | 1 | +----+------+---------+ 1 row in set (0.00 sec)
セッション2
mysql> begin; Query OK, 0 rows affected (0.00 sec) mysql> select * from Version; +----+------+---------+ | id | text | version | +----+------+---------+ | 1 | init | 1 | +----+------+---------+ 1 row in set (0.00 sec)
セッション1
mysql> update Version set text = 'updated' , version = version + 1 where id = 1; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> select * from Version; +----+---------+---------+ | id | text | version | +----+---------+---------+ | 1 | updated | 2 | +----+---------+---------+ 1 row in set (0.00 sec)
セッション2
mysql> select * from Version; +----+------+---------+ | id | text | version | +----+------+---------+ | 1 | init | 1 | +----+------+---------+ 1 row in set (0.00 sec)
セッション1
mysql> commit; Query OK, 0 rows affected (0.00 sec) mysql> select * from Version; +----+---------+---------+ | id | text | version | +----+---------+---------+ | 1 | updated | 2 | +----+---------+---------+ 1 row in set (0.00 sec)
セッション2
mysql> select * from Version; +----+------+---------+ | id | text | version | +----+------+---------+ | 1 | init | 1 | +----+------+---------+ 1 row in set (0.00 sec) mysql> commit; Query OK, 0 rows affected (0.00 sec) mysql> select * from Version; +----+---------+---------+ | id | text | version | +----+---------+---------+ | 1 | updated | 2 | +----+---------+---------+ 1 row in set (0.00 sec)
commitしないとセッション1の更新が反映されない!
という感じで、セッション1が更新した内容をセッション2に反映されるのはセッション2がコミットした後(ロールバックでもOK)になります。
自分はOracle脳になっていたので、最初意味がわかりませんでした。。。
長いので次回に続く。
第69回 PHP勉強会に参加してきた #phpstudy
初参加してきました。
http://atnd.org/events/40476
PHP歴半年ほど(そもそも仕事でばりばりプログラム書くようになって半年ですが。。。)の身でちょっと心配でしたが、アットホームな感じで楽しい会でした。
ビールの乾杯から始まるってのが良いですね。
今回は8周年記念という事でした。
他の言語ユーザーからはPHPェ。。。と言われがちなPHPですが、
集まってる方達はガチな感じですごかったです。
とりあえず、発表(LT以外)の感想だけでも。
Vagrant + Chef で作るこれからの開発環境 @yando
全然知りませんでしたが良さそうですね。ローカルと本番で違う環境(MySQLのバージョンとか。。。)で動かしちゃってるんで、実際に検討してみようかと。php-gd2で画像を弄る話(仮) @yoyapp
gdのコアな話でした。palletとtrue colorの話からして頂いたので、非常にわかりやすかったです。
また行こう。
select count(distinct user_id)的な
最近Railsをちょいちょいさわる機会があります。
よくある、
select count(distinct user_id) from hoge_users;
みたいなSQLですが、ActiveRecordだと
Hoge_users.count('user_id', :distinct => true)
でいける。簡単でいいですね。
複数行レコードを横持ちに変える
GROUP_CONCATが最高に便利。サブクエリとかいらない。
http://d.hatena.ne.jp/kkz_tech/20100803/1280802260
http://blog.asial.co.jp/209
転職してました
随分日が空いてしまいましたが、昨年の9月末から恵比寿でゲーム作ってる会社で働いています。もう4ヶ月位ですね。
所謂ソシャゲーを作っています。最初は若干抵抗もありましたが、作ってみるとなかなか楽しいです。ソシャゲーはすごい儲かるみたいなイメージがありましたが、それだけ苦労もしてるなーという印象です。
言語的にはPHPとjs(とHTML)なので、転職前にぼんやり考えてたのとは違いますが、アジャイルな感じでばりばり仕様考えて即コーディング!で仕事できていて、余計なストレスは少ないです。
仕事にも慣れてきてある程度コントロールできるようになってきたので、ブログ書いたり、勉強会参加したりしたいなと思っています。
とりあえず近況報告まで。
Akasaka.scala 41 #akskscala
Scala勉強会第83回 in 秋葉原
初参戦。
いきなりですが、少ししゃべってきました。
http://www.slideshare.net/moyashidaisuke/20120718-scala
Slideshare初めて使いましたが、OpenOfficeのファイルだとフォントとか段落とか色々おかしいですね。
後、うまく埋め込みができないです。また仕様変更??
以下、メモ
- Scala Schoolには@seratchさんの意訳があり、あわせて読むと便利
- polymorphismにはランクという考え方が有り、Scalaは1までしかサポートしてない。Haskellだと2もサポート?
- 2.10では「SIP-11 - String Interpolation and formatting」という機能が追加される。結構便利そう
- @kmizuさんの記事見つけた
- ジェネリクスの型情報はコンパイル時に消えるはずが、実は色んな方法で取得できるらしい。