ハードコード
apollo11号のソースコードを読みつつ - aerith7’s blog
電気回路自体でロジックが実装されていることを「ハードコード」と言うのだと思っていたのだが、最近のセキュリティー事例を見ると「ソフトウェアのソースコード内にパスワードなどが固定で書き込まれていること」をハードコードと呼んでいたので、思い違いだったのかと思っていた。
だけどこの記事に 「メモリはプログラムを全て0と1に書き起こしたあと、町工場の女性の手によって1つづつ銅線に編み込んで作ったようです」とあって、やっぱり古い意味での「ハードコード」ってそういう事だったんだよなと思い直した。
MySQLのLAST_INSERT_ID()
2 番目の INSERT ステートメントで 3 つの新しい行が t に挿入されましたが、これらの行の 1 番目に生成された ID は 2 であり、あとに続く SELECT ステートメントでも、この値が LAST_INSERT_ID() によって返されます。
MySQL :: MySQL 5.6 リファレンスマニュアル :: 12.14 情報関数
…おい、こいつらは一体何を考えてDBを設計しているんだ?そこで「2」と返されたら困るだろ。
載っているサンプルは「三つの行をテーブルに追加して、最後のキーは4になった」状態。だが「 LAST_INSERT_ID()は2を返します」といっている。この関数は一体何のために使用できるというのだろうか…
調べようと思ったのは「最後に追加された」とは「テーブルに関して決まる」のか「接続に対して決まるのか」だったのだが、それ以前にこの関数が使える気がしなくなった。
(関数が読み出しのための引数を取らないから、接続に関して決まるのだろう。PDOのpostgreSQLでは引数に「シーケンスオブジェクト名を指定しろ」になっているので、テーブルに関して決まっていると推測される。)
MySQLにはSEQUENCEがない
必要があって検索したら出てきたのだが…これはテーブルをロックしないとレースコンディションの問題が発生するだろう。なのにロックをかけるのはアンチパターンだとなっている。処理速度しか見ていないのだろうか?
ほぼ同時に二つのプロセスが「データのインサート」を行い、そのあと「最後に追加されたIDの問い合わせ」をした場合、処理の順番が「インサート」「インサート」「問い合わせ」「問い合わせ」になってしまう可能性がある。そうすると、二つの違うプロセスに同じ番号が返ってしまう。
データをインサートする前にライトロックをかけておくと、同じタイミングの処理でも「ロック」「処理待ち」「インサート」「問い合わせ」「ロック解除」「ロック」「インサート」「問い合わせ」「ロック解除」になるので問題が無いはず。
このサンプルでいうと、「採番テーブルの削除処理に失敗する」「なぜか消えていない採番テーブルのデータがある」という事態で問題が発生したことが分かるだろう。
「問い合わせのアトム性」の問題だろうか?(検索すると「アトム性」がほとんど出てこないので、用語の記憶間違いがありそうだ。レースコンディションに絡んでatomicという表現はあるから、日本語訳が別にあるのだろうか。)
この件の場合、「インサート」と「読み込み」が「必ずセットで連続して行われる(不可分に行われる)」という「アトム性」の保証がないためにレースコンディションが発生する。
個人的に考えると、「データをインサートする際に別のユニーク制約付きの列にデータ(乱数)を書き込んで、それを元に連番を読み出す」という方式にすると思う。(というか、今から実装しなきゃならないのか?)
ユニーク制約のある列にインサートできたかを確認すれば、ロックしなくても他のプロセスから独立していることをユニーク制約が保証してくれる。あとはインサートしたデータを元に普通にセレクトすればいい。この場合、インサートが成功した時点で読み込める数字が確定しているのでアトム性の問題が無い。
元の例でいえば「採番テーブル」には「id」の他にもう一つユニークなフィールドを設定する事になる。そして LAST_INSERT_IDは使わない。(というか前に別の案件でLAST_INSERT_IDの使用を考えた時も、レースコンディションが排除できなくて使うのをやめた記憶がある。)
……まぁそもそもMySQLにSEQUENCEがないのが悪い。PostgreSQLにはあるのに。*1
(追記)MySQLのlast_insert_idは接続ごとに違う答えを返しそうなので、この問題は起きないのかもしれないが、そもそも戻ってくる値が想像以上に使えなさそうでもっと困ることが分かった。
あと、Webサーバーには「DB接続のプール」とかがあるので動作が確信できない点も気になるか。そこまで考えるとSEQUENCE機能以外信頼できないのか。
*1:というか、PostgreSQLにあったからそれを使う設計をしたのに、それをMySQLしか使えない場所に移植する羽目になったところでSEQUENCEがない事を知ったので愚痴っている。
PHP5と7の留意点メモ
今さらながらPHP5.6に対応するように書き変える作業をする前に、その次の7を見据えないといけない(笑)
PHP: 下位互換性のない変更点 - Manual
PHP5では諦めて型宣言しない。PHP7だとThrowableと書く。…型宣言しないのは教条的に嫌いなのだが。
- eval() のエラーハンドリングをする際には、catch ブロックを用意
例外を投げることがある。
- 変数やプロパティそしてメソッドへの間接的なアクセスを、厳密に左から右の順で評価するようになりました
むしろ今までの仕様の方が気持ち悪い。四則演算の結合規則みたいな明示的ルールがあったのだろうか。
- list() での変数の代入が、逆順ではなくなる
『どの順で行われるかに依存するコードは書かない』に従う。
- 空の list() の廃止
…何に使うのか分からなかった。
- list() は文字列変数を展開できなくなりました
『かわりに str_split() 』と書いてあって、むしろそんな処理がされていたことを知った。
- 参照による代入で自動的に作成した配列要素の並び順の変更
前の挙動をする意味が理解できない。まぁ連想配列の格納順に深い意味は本来ないのか。
- global は単純な変数だけを受け付ける
例文にあるような「メンバをグローバルにする」発想に付いていけない。『一般論として、単純な変数以外を global で使うことは推奨しません。』に同意する。
- foreach は内部の配列ポインタを変更しない
例文が何をしたいか分からなかった。
- 値渡しの foreach は、配列のコピーを使って操作を進める
個人的には予想外の事態が起こりにくくなるだけかな。(たぶん、性格的に自分でコピーを作ってから回す形にする。)
- 参照渡しの foreach の、反復処理の振る舞いを改良
予想外の事態を引き起こす変更だが、動的に何かするには必要だったりするのだよな。
- Traversable でないオブジェクトの反復処理
Traversableでない場合は参照渡しで反復処理したのと同じになるとあるので、要注意。
Traversableは「IteratorAggregate あるいは Iterator」を意味する抽象化らしい。型チェックで使うのか。
- 無効な形式の八進リテラル
パースエラーを出すようになる…って、最初からパースでエラーを出して下さい(笑)
- 負のビットシフト
エラーで良い(笑)
- 範囲外のビットシフト
Integerを超えると全てゼロになる…って、いままでの『環境依存』がこわすぎる。
- ゼロ除算の挙動の変更
ワーニングを出してfalseから、IEEE 754準拠で「 +INF、-INF あるいは NAN」。剰余計算だと例外を投げる。結構違う。
- 十六進数値形式の文字列は数値とはみなさない
自動変換の仕様変更。自動変換は極力信じないのが信条(笑)
- \u{ がエラーの原因になることがある
「Unicode コードポイントのエスケープ構文」とかぶる。
- (廃止)call_user_method() および call_user_method_array()
- (廃止)ereg* 系のすべての関数
データベース系はパッケージ化されているはずだったな。
- (廃止)intl のエイリアス
- (廃止)set_magic_quotes_runtime()
- (廃止)set_socket_blocking()
- (廃止)PHP-FPM における dl()
- (廃止)GD Type1 関数群
- (INI削除)always_populate_raw_post_dataとasp_tags
- (INI削除)xsl.security_prefs
- 新しいオブジェクトを参照渡しで代入できない
無名のオブジェクトみたいなものか。用途が分からない。
- 無効なクラス名、インターフェイス名、トレイト名
…それって今までは宣言できたのか(笑)というか、今も宣言できてしまうものがあるのか。objectとか宣言できちゃ駄目だろ。
- ASP タグと script タグの廃止
地味な話だが、意外と困る人もいるだろう。
- 非互換のコンテキストからの呼び出しの削除
古い仕様の方がおかしいな。
- yield が右代入演算子に
ジェネレーターの構文を使ったことがない。
- 同じ名前のパラメータをひとつの関数に複数定義できない
例文を見て一体なぜ複数定義することがあるのか分からなかった。というか、どういう動作をするのだ?
- 引数を調べる関数は、パラメータのその時点での値を報告する
用途によっては困るかも。だが逆に「その時点での値を知る方法」がなかったのか。
- Switch 文に複数の default ブロックを書けない
元が意味不明。
- $HTTP_RAW_POST_DATA の削除
- INI ファイルにおける # 形式のコメントの削除
セミコロンを使え、とのこと。
- JSON 拡張モジュールが JSOND に置き換わる
- 内部関数がオーバーフローしたときの挙動
「浮動小数点数値が大きすぎて整数として表せない場合に、 float から integer に変換した結果を黙って切り詰めていました」するな(笑)
- カスタムセッションハンドラの戻り値の修正
- 同値な要素の並び順
「その並び順がいつまでも同じであるとは限りません。」
確率
もう1つも同じである確率-追加情報は、確率にどう影響するか?:研究員の眼 | ハフポスト
二問目は極めてすぐに理解できたのだが、一問目がどうもしっくりこなくて考え込んだ結果、
少なくとも一人が男だと分かる
という現象が「相当おかしな現象」である事が分かった。
最初に「パーティー会場で兄弟が離ればなれになっている」「男の方に会う」というのを思い浮かべて「少なくとも一人が男だと分かる」を理解していたのだが、それでは「三分の一」にはならない。
この例だと、例えば「兄/妹」の片割れの「妹」に行き会ったときにも「兄がいる」事が分かるのでないと「三分の一」にはならなかった…
「どこそこの家の子供(二人のうち一人)が一人父親になった」という話からもう一人の性別を想像する、みたいなものを思い浮かべる必要があったらしい。*1
…あとは「兄弟姉妹は二人セットで行動していて、嗅覚で一人は男が居ることが分かる(犬か?)」だな(笑)
自炊代行最高裁判断
「自炊」代行は著作権侵害 最高裁で確定 - ITmedia NEWS
http://www.yomiuri.co.jp/national/20160317-OYT1T50119.html
訴訟が起こるまでの経緯とか憶えている私からすると「そんな結果の分かっている訴訟をいつまでもしていたのか」という感想なのだが、ブックマークとかを見ると経緯も判決がそうなる理由も分かっていない人が多いらしい。
続きを読む