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さんの記事見つけた
- ジェネリクスの型情報はコンパイル時に消えるはずが、実は色んな方法で取得できるらしい。
なぜアジャイルをやってみたいのか考える
退職しましたで、「アジャイルやりたいなぁ」と書いたのですが、もう少し掘り下げてみます。
経験した現場の何がダメだった?
- 成果
- 予算・期間:オーバー
- 品質:低い
- 使いにくい
- バグ多い
いわゆる失敗プロジェクトですね。
経験した現場がなぜダメだった?
- 工程
- 無駄とおもえる作業が多い
- 大量のドキュメント
- 生産性が低いフレームワーク、開発の規約
- 明らかになっているリスクへの無対策により発生するコスト
- 単体テストまで完了させたのにリリースしない機能(予算超過のため)
- コミュニケーションエラー
- 仕様について言った言わない
- ここからは契約外なのでできません(追加費用が発生します)
- 追加要求のみしてくるユーザー、1次受け
- 無駄とおもえる作業が多い
- 体制、組織風土
- 改善提案を受け入れられない
- PDCA・カイゼン活動をしない
- リスクコントロールしない
- 名ばかりの管理者(1次受けの人)
- 形だけのレビュー
- 技術力不足
- 明らかなテスト不足による障害
- 保守性・拡張性に乏しいコード
集約するとこんな感じかと思います。
- 開発工程・契約
- 顧客・開発のプロジェクト管理能力不足
- 開発の技術力不足
じゃあどうしたらいい?
そこでアジャイルという可能性に出会いました。
プロセスやツールよりも個人と対話を、
包括的なドキュメントよりも動くソフトウェアを、
契約交渉よりも顧客との協調を、
計画に従うことよりも変化への対応を、価値とする。
そう、これだよ!
決められているやり方に縛られて契約上にしか価値の無いドキュメントを作るのをやめて開発作業にもっと力を注いで、「契約だからできない」ではなくてどうやったらお互いにWinWinになれるか考えて、実際には必ず発生する変化を前提に取り組めば、プロジェクトが成功する確率はもっと高くなると思いました。
さらに
ビジネス側の人と開発者は、プロジェクトを通して日々一緒に働かなければなりません。
プロジェクトの成功には顧客側の積極的な関わりが必須。
意欲に満ちた人々を集めてプロジェクトを構成します。環境と支援を与え仕事が無事終わるまで彼らを信頼します。
ヤル気ない人、定時内に出勤している事が仕事だと思っている人はプロジェクトにとってマイナス。いない方がいいです。
技術的卓越性と優れた設計に対する不断の注意が機敏さを高めます。
技術者は技術に対する努力をし続けるべき。
最良のアーキテクチャ・要求・設計は、自己組織的なチームから生み出されます。
チームがもっと効率を高めることができるかを定期的に振り返り、それに基づいて自分たちのやり方を最適に調整します。
組織は人の寄せ集めでは無いです。人員を代替可能なものとして見積もるやり方はもうやりたくないです。
というわけで、考え方にとても共感できました。
この考え方に共感できる人が集まっているプロジェクトなら、とても良い仕事ができるんじゃないか、と。
で、どうする?
SI業界でもアジャイル化の動きが出ていますが、結果が出るのはもう少し先かと思います。
となると、Webサービス系の企業にチャンスがありそうです。
でも、今までやってきたBtoBのSIを、ちゃんと成功させてみたいなぁ、という気持ちもあります。むむむ。
参考
アジャイルサムライ 読書会 埼玉道場(第4回)
超ゴージャスだった第1回に続き、久々に参戦。2回目。
以下、めも。
第3章 みんなをバスに乗せる
- 基本的にインセプションデッキの内容や目的は、PMBOKのプロジェクト憲章と同じ。でも継続的にメンテをする。
- 完璧に作れなくても(というか無理)良いので、できる範囲で作成すればおk。ぼやっとしてる部分はぼやっとしている事を明確になっていればおk
- プロジェクトが立ち上がる前(キックオフの前)に作成するのが効果的?
- プロジェクト憲章と同じ。
第4章 全体像を捉える
- 「司令官」って誰の事? => プロジェクトの目標・目的を司令官に例えてるだけなので、具体的にきまっているわけではない。
- パッケージデザインを作る必要性は?エレベーターピッチと何が違う?
- パッケージデザインはエンドユーザーから見たメリット。後、作るのが楽しいのでチームの一体感が出るのでは?
第5章 具現化させる
- 荒ぶる四天王でスコープだけが変更可能としてあるけど、ウォーターフォールでは時間と予算を伸ばすことの方が多かったため、いまいち実感できない。
- スコープの変更とは機能を削るだけでなく、機能の簡素化(画面の共通化とか)も含まれる。
- ウォーターフォールの場合、時間と予算には予めバッファを積んである事が常なので、変更しやすいのでは?
- ステークホルダーとご近所さんの違いは?
- 第5章の最終判断の下りでの「ステークホルダー」は利害関係者ではなく出資者の意味では?
- ご近所さんにはステークホルダー(利害関係者)も含むと捉えて良いのでは
その他
インセプションデッキとか、エレベーターピッチとかウォーターフォールでは使わない単語を良い感じに翻訳しているので、「アジャイル」という単語を出さずに進めたい場合に良さそうです。
第31回 HTML5とか勉強会 JavaScript MVCフレームワーク に参加してきた #html5j
行ってきました。
HTML5勉強会は初めてです。こちらの記事でAngularJSが紹介されてて、面白そうと思ったのがきっかけです。
補欠でしたが、当日キャンセルが出てらしく参加できました。ラッキー。
- Backbone.js
- Spine.js
素のJSにかなり近いイメージ。シンプルなので、元々JSが得意な人には小回りが効いて良さそう。Twitter見てると、Spine.jsは勉強に向いているとか。Coffeescriptから勉強しなきゃなんだけど。
- Ember.js
先の2つに比べると、かなり厚い?感じ。どことなくRORっぽい。
- Angular.js
さらに厚い感じで、ほとんどJSっぽくない。HTMLベースでちょいちょい動きを変えられて作りやすそう。Play1系のテンプレートみたいだな、と思った。楽しそう。
JS本当に知らないのですが、フレームワークレベルなら違いがわかって結構面白かったです。
Coffeescriptの勉強がてらSpine.jsと、Angular.jsは少し触ってみようと思います。
退職しました
少し前の話ですが6月末を以って、4年と3ヶ月働いた会社を退職しました。
大学を中退し、プロを目指して音楽活動
→音楽を仕事にする事をやめる決断
→未経験で大学中退でもまともに働ける業界って何があるだろう。。。
→IT業界いけんじゃね!年功序列じゃなくて実力主義っぽいし!
→うわ!この業界いろんな意味でksだな。。ITコンサルが一番儲かるっぽいけど、まずはちゃんとエンジニアとしての経験を積まないとだめだな。
→就職!
でした。
SIerからの2次受けが中心の中小企業でしたがとても良い会社だったと思います。
- 技術支援制度が充実していた
- 評価もそれなりに実力主義だった
- 会社の規模の割には給料も良かった
- 経営(売上・利益)が安定していて、安心して働けた
おかげ様で、SIer系の業界で働く分には1人前のSE、リーダーになれたと思います。
やって来た事(プロジェクト編)
2つの現場を経験しました。1つ目は基幹システムのリプレース作業(COBOL→Java)で、なかなかひどいプロジェクトでした。。いきなりIT業界を満喫できました。
- 延期につぐ延期
- 尽きることのない仕様変更
- 作業効率最悪の開発環境(Cerlonはやめて。。。)
- お客様作成のオレオレフレームワーク
- 作業の足を引っ張るコーディング規約(staticメソッドのみ許可、List禁止・配列でetc...)
- 本当にテストしたのか疑問が残る他チームの作成モジュール
自分の所属していたチームだけは順調でしたが、それ以外が尽くダメなので、まぁ大変でした。
全体しては色々と問題有り有りでしたが、個人的にはプログラマー→SE→サブリーダー→リーダー という王道(?)を経験できましたし、Seasar2のコミッターの方と一緒に仕事ができたりしました。
2つ目はエンドユーザー会社のIT部門と直契約で、グループ会社への倉庫のパッケージ導入支援でした。
最初から導入したいパッケージが決まっていた状態でしたが、プロジェクトの立ち上げからという、ウォーターフォールで言う超上流に関われました。
やって来た事(プロジェクト以外編)
まず、資格を取りまくりました。- 経験が無いけど、知識としては持ってるよ!が証明できる。
- 勉強する人ですよ!が証明できる。
- ITの知識無い人でも1,2がわかるよ!
というメリットがあると考えたためです。3番目は資格ならではだと思います。単価上げやすいらしいです。
で、とったのは(順不同)
I-Tパスポート
- 基本情報処理技術者
- ソフトウェア開発技術者試験
- DBスペシャリスト
- システムアーキテクト
- SJC-A
- SJC-P
- SJC-WC
- OracleMaster Silver 11g
- Silver Oracle PL/SQL Developer
- 簿記3級
- LPIC Level1
です。最後の1年はとってないので、3年間でけっこう取りました。
また別の記事で詳しく書こうと思います。
後は社内勉強会を作りました。
ここで悩んでますが、約半年間、毎月定期的に開催してとりあえずは軌道に載せることができました。
これも今度詳しく書きたいです。
退職する理由
とまあ、それなりに順調だったのですが、こんな疑問ややりきれない気持ちを抱くようになってきました。- 自分がどんなに頑張って成果を出してもプロジェクトとしては成功していない。。。
- 政治的・契約的な環境に評価が影響を受けすぎていて、成果物が評価されない。。
- Excelとパワポを作るだけの日々はつらすぎる。。。
- 技術的な下積みが浅すぎるで将来が不安。。
- 技術的に刺激を受ける人物が現場にはいない。。。
- 管理職になる以外のスキルパスが存在しない。
もちろん、自分の影響の輪を大きくしてこれらを解決するという方法もありますが、29歳という自分の年齢を考えると退職して別の環境に身を置く事にしました。
次はこんな環境がいいなぁ、と思ってます。
- 成果物によりユーザー、社内の評価が決まる
- 技術重視
- 新しい技術を積極的に試そうとする
- すごい人がいる
- 管理職以外のスキルパスがある
- 客先常駐ではない
- ワークライフバランスを重視している(計画的に長期休暇が取れる)
- 企業理念が明確である
- アジャイルやってみたいなぁ
これから
すぐには転職活動をせずに充電期間を置きます。長期の休暇となりますので、やりたい事をやろうと思います。
- 普通免許取得(7/11完了!)
- 海外旅行
- 技術のほりさげ、やりたい技術キーワードの確定
3番目が大事で、プログラミングをちゃんとやりたいんだぜ!と言って退職したものの、何やりたいのかが不明確なのです。なので転職活動もできません。
2012年中にやりたい事が明確になって、マッチする企業さんに転職できればとなんとなく考えています。
しばらくはあちこちの勉強会に顔出してつまみ食いしてみますので、みなさまよろしくお願い致します。
java-ja『LOG.debug("nice catch!")』に参加してきた
参加してきましたー。
http://connpass.com/event/607/
イベントの詳細はしんやさんが素晴らしいレポートを提供されているので省略します。感想だけ。
[勉強会][Java]java-ja『LOG.debug("nice catch!")』に参加してきた #java_ja"]
java-jaと自分
java-ja自体は昔から(3年位前?)知っていたのですが、当時はTwitter等のSNSやATNDのようなイベント管理サービスは無く、興味はあるけどなんか怖い状態でした。で、やっと参加できる機会がやってきたわけです。うれしい!
感想
すごく楽しかったです。小学生みたいな感想で申し訳ないですが。言語とか主催者によってイベントの雰囲気はすごく違いますが、java-jaはとても緩いです(懇親会10分!)。でも心地良い。
心地良いのは、きちんとしたバックグラウンドの知識を持っているという前提が、共有できているからだと思います。今回は人数が多すぎて、直接お話する時間があまり取れなかったのが少し残念でしたが、それは次の機会という事で。
結論
- 関数型も身につけよう→積本になってるコップ本を再開しなきゃ。。。
- 達人プログラマーとかEffectiveJavaとか、もう一度ちゃんと読もう→読書会形式とかにしようかなぁ。
- GREEぱねぇ!
Webサービスを作るってみるその2 OpenIDでmixiと連携
今回はOpenIDを使用して、mixiとの連携機能を作成します。
Play1系で、しかもJavaで、しかもmixiと連携しようという方はきっと少ないでしょうが。。。。
ちなみに、PlayにはOpenID用のライブラリが標準で用意されてますので楽チンです。
mixiのOpenID仕様
オフィシャルはこちら。単純にmixiにログインしているかどうかだけでなく、マイミクシィ認証とコミュニティ認証という機能があるのが面白いですね。
コミュニティ認証を使って、見られる範囲の制限なんかに使えそうです。(所属しているコミュニティのセッションだけ参加できるとか)
概要
下記を参考に、認証機能を作成していきます。想定する動作は、
- 画面上で [mixiでログイン] のアイコンをクリック。
- サーバから mixiの URL へ OpenID を要求する。
- mixi からリダイレクトで認証レスポンスの呼び出し。認証に成功していれば OpenID を取得。
- OpenID に含まれるmixiのnicknameをセッションに保存する。
※ログインしていない場合は、必ずログイン画面に遷移させる
ログイン画面
まずはログイン画面。まずはログイン用のボタンをmixi公式から取得して、public以下に配置します。
で、ログイン用のviewを作成。
#{extends 'main.html' /} #{set title:'ログイン' /} <div class="container"> <div class="row"> <div class="span8 offset4"> <div id="login"> <h1>&{'secure.title'}</h1> <div class="control-group" > #{if flash.error} <p class="error"> <div class="control-group error"> <label class="control-label" for="inputWarning">&{flash.error}</label> </div> </p> #{/if} #{if flash.success} <p class="success"> &{flash.success} </p> #{/if} <a href="@{Auth.mixi()}"> <img src="@{'/public/images/login_btn002.png'}" ></a> </div> </div> </div> </div> </div>
ログインボタンにAuth.mixi()へのリンクを作成しただけのViewです。
認証Controllerの作成
認証用のControllerであるAuthを作成します。
package controllers; import play.libs.OpenID; import play.libs.OpenID.UserInfo; import play.mvc.Before; import play.mvc.Controller; public class Auth extends Controller { @Before(unless = { "login", "mixi", "logout" }) static void begin() { if (!isLoggedIn()) { login(); } } private static boolean isLoggedIn() { return session.contains("username"); } public static void login() { render(); } public static void mixi() { authenticate("https://mixi.jp"); } private static void authenticate(String url) { // 認証完了のレスポンスでなければ OpenID の検証を要求する if (!OpenID.isAuthenticationResponse()) { OpenID.id(url).required("nickname").verify(); //nicknameも要求する return; } // 認証処理の結果を評価 UserInfo user = OpenID.getVerifiedID(); if (user == null) { flash.put("error", "認証に失敗しました"); login(); } else { // 認証完了 String nickname = user.extensions.get("nickname"); session.put("username", nickname); render("@Application.index"); } } public static void logout() { session.clear(); login(); } }
ポイントはいくつかありますが、
- @Beforeでログイン有無を確認(@Withと組み合わせ。後述)
- OpenID.requiredに"nickname"を指定することで、戻りにニックネームを含めてもらう
- OpenID.extensions.get("nickname")で、戻りのニックネームを取得
でしょうか。
認証完了の処理はとりあえずニックネームを取得しているだけですが、アプリで管理するユーザーとのひもづけとか、色々やる予定です。
他Controllerとのひもづけ
「※ログインしていない場合は、必ずログイン画面に遷移させる」を実装します。他のControllerに@Withを使うだけです。
@With(Auth.class) public class Application extends Controller {
確認
いいですね!
でもこれ、テストどうすればいいんですかね?
mixiのログイン状態に依存するので、すごい難しそうですが。。。。
Webサービスを作るってみるその1
Webサービスを作ってみる事にしました。
アプリ概要
自分は趣味でギターをやってるんですが、セッション会という名のオフ会によく参加しています。で、事前にmixiのコミュニティで選曲やらパート分けやら、アレンジの相談をして当日に臨むのですが、掲示板の機能だけではわけがわからないので、みんなgoogle docや、自作のHTMLや、Wikiで管理してます。
これを、誰でもできるようにしちゃおうぜ! というシステムです。超絶ニッチですね。
アーキテクト
play framework1.2.4 + twitter bootstrap + Heroku で。とりあえずScalaは使わない。
一気に新しい事に挑戦しすぎちゃうと、自分の実力ではいつまでたってもリリースできませんorz
バージョン管理はgithub。タスクもgithubのissueで管理。DBはとりあえずHerokuの無料範囲で。
というわけで
とりあえずなんとなく画面イメージがわかる位まで作って公開しました。http://miximusicsession.herokuapp.com/
ちまたでは良く言われてる事ですが、とりあえずでも公開まで持ってくというのは勉強になりますねー。
なんとなく良さそうなのでこのまま作り続けます。6月末位までに一段落が目標です。
話かわりますが、playframework使いやすいです。良い意味でJavaっぽくなくて楽チン。