利用可能な DNS サーバを調べる

nslookup コマンドを使うと、任意のISP(任意のネットワーク)が利用しているDNSサーバIPアドレスを調べることが可能です。
 
既に DNS が使える環境で、
nslookup を使い、ISP のホスト名についてネームサーバの解決をすることで調べます。

$ nslookup
Default Server: XXX.XXX.ne.jp
Address: XXX.XXX.XXX.XXX
 > set q=ns # ← set q=any でも可。
 > example.org # ← 調べたい ISP のホスト名
Default Server: XXX.XXX.ne.jp
Address: XXX.XXX.XXX.XXX
 
Non-authoritative answer:
example.org nameserver = a.iana-servers.net
example.org nameserver = b.iana-servers.net # ←DNSサーバのホスト名
 
Authoritative answers can be found from:
b.iana-servers.net internet address = 193.0.0.236 # ←DNS サーバの IP アドレス

この結果として返ってきた DNS サーバの IP アドレスを名前解決用 DNS サーバとして指定できます(できないこともあります)。
ただし、自分が所属している ISP 、ネットワーク以外を指定するとはじかれることがありますし、ネットワーク的に遠いと遅いこともままあるので、自分の IP アドレスの逆引きから調べるようにしたほうがいいでしょう。

テーブルロックの話

テーブルロックをうまく使うと、
・MyISAM でのパフォーマンス向上
・MyISAM で(InnoDB を使わずに)簡易的にトランザクションの一部機能を実現できる
といううまみがある。(InnoDB, BDB だと逆効果になりうる。
 
テーブルロックの基本的なクエリは次のとおり。
 
– 読み込みロック

LOCK TABLES foo READ

テーブルの読み込みロッククエリを実行すると、ロック中は現在の接続(と同時に実行中の他の全ての接続)で、指定したテーブル(例では `foo`)の更新が一切できなくなる。
複数の参照系クエリを連続で送る時に、途中でデータが書きかわると困る場合に利用する。サブクエリなどを使って1クエリにまとめてしまっている場合は不要。
 
別の接続で書き込みロックが発生している場合は、読み込みロックを獲得するまで待ちに入る。
なお、読み込みロックは性質的にパフォーマンスを向上させるものではなさそう。
 
– 書き込みロック

LOCK TABLES foo WRITE

テーブルの書き込みロッククエリを実行すると、ロック中は現在の接続以外からしか読み書きができなくなる。既にロック(読み/書きいずれか)が発生している場合はロックが獲得できるまで待ちに入る。また、デフォルトで READ よりも優先度が高い。
 
書き込みロックによってパフォーマンスが向上する可能性があるのは、処理時間の短いクエリを多く実行する場合(ロック解除時にまとめて実行するようになるため)。
 
更新を1回のクエリでしか実行しないのであれば、書き込みロックは不要。

(MySQL 4.1 公式リファレンスマニュアルより)
LOCK TABLES の使用時にいくつかの面で処理が迅速になる理由は、
MySQL でキーのキャッシュが UNLOCK TABLES が呼び出されるまで
フラッシュされないためである(通常、キーのキャッシュは各 SQL
ステートメントの後にフラッシュされる)。
それによって、MyISAM テーブルに対する挿入、更新、削除処理が
迅速化される。

 
– ロック解除

UNLOCK TABLES

テーブルロック解除クエリが実行されるか接続が終了した時点で、現在のスレッドが保持している全てのテーブルロックを解除する。
WRITE ロックの場合はこの時点で実際にデータベース上の値を書き換える。
 
参考:
MySQL4.1 リファレンスマニュアル: LOCK TABLES および UNLOCK TABLES 構文
– 釣ったよ!釣りとコンピュータ: MySQL InnoDB の利用: テーブル・ロックについて

InnoDB が本当に必要な時とは

行レベルロックが本当に必要な時のみ。
InnoDB を利用し、トランザクション処理を行う場合、MyISAM にはないエラー処理が必要になったり、対処事項が増えたり、MyISAM よりパフォーマンスに劣る面があるという点に留意すること。
 
InnoDB を利用しなくても済むような、以下の代替手段が存在する。
 
サブクエリ

UPDATE user SET presence = 1 WHERE
    job_id = (SELECT id FROM job WHERE name = ‘teacher’);

虎の子で条件分岐も使えるし、サブクエリだけで結構何でもできてしまう。
 
LOCK TABLES, UNLOCK TABLES]
今日のエントリを参照。
 
LAST_INSERT_ID()
最後に挿入したレコードの一意な ID はどのように取得するのか
mysql_insert_id()
 最後の挿入(INSERT),更新(UPDATE) で設定/生成されたレコードについての AUTO_INCREMENT 値が入る。AUTO_INCREMENT 値が更新/設定されなかった場合は 0 になる。
 
GET_LOCK(), RELEASE_LOCK()
Java や C# のオブジェクト指定のロックのような、名前指定のロック。
ただしデッドロックを避けるため同時に複数のロックを獲得することはできないようになっている。つまり、GET_LOCK() は、前回のGET_LOCK() によるロックを開放する。
 
参考:
– 釣ったよ!釣りとコンピュータ: MySQL InnoDB のトランザクション

MySQL41 の SJIS 環境のクライアントからの文字化けを防ぐ

SJIS 以外は SET NAMES クエリでの設定で解決するが、SJIS ではクエリでは解決できない。
 
結論からいうと、

mysql –default-character-set=sjis [ -u username [ -p ]] […]

のように、クライアントでの接続時に –default-character-set=sjis と明示してやるだけで解決する(SET NAMES .. は不要)。my.cnf の [mysql] の項目に sjis と設定してやってもよい。
 
PHP でも my.cnf を見ているらしい。PHP ではこれ以外の妥当な設定の手段がないもよう。
現在は、一部のコードでのみ対応したい場合は、自分でラッパ関数を作ってやるのがよさそう。PEAR::DB の prepared statement 構文を使う場合は ujis (EUC_JP)として通信させてやらないとうまくいかなかった。
 
詳しく書くと、DB_Common::prepare で呼び出している内部関数で非 UTF8 のつもりでエスケープ処理を行うため、事前エンコードをすると文字が壊れてしまうのが原因。EUC-JP だと、ASCII コードに互換性があるためエスケープ処理で文字が壊れないのでエンコード後のエスケープでも問題ない。
 

//
// 単純なサンプル。実用コードではありませんよ。
//
$con->query(‘SET NAMES ujis’);
echo dec( $con->getOne(enc(‘SELECT description FROM product WHERE name = ?’), enc(array(‘苛性ソーダ’))) ) ;

/**
 *
 */
function dec($val){
    return mb_convert_encoding($val, mb_internal_encoding(), ‘EUC-JP’);
}
/**
 * エンコード。クエリを実行する前の前処理。
 * @param string $val 変換対象の文字列
 * @return string DB クエリの文字コードに変換した文字列
 */
function enc($val){
    return mb_convert_encoding($val, ‘EUC-JP’);
    // $val は mb_internal_encoding() の文字コード。それ以外も
    // 受け付ける場合, 第三引数を ‘auto,UTF-8’ 等にしておく。
}

参考:
– OSS Web – 接続キャラクタセットの変更
ここにあるとおり、show variables like ‘character\_set\_%’ では同じなのに、実際は内部的には違うのがなんとも。

MySQL41 と PHP の間で文字化けをスマートに防ぐ(クライアントがSJIS以外の時)

$encod$#INGu = ‘ujis’; // ‘utf8’, ‘cp932’ ..
$con->query(‘SET NAMES ‘.$encoding);

などとすると、いちいち送受信時に mb_convert_encoding() とかしてやる必要は皆無になる。
通信時

IP アドレスを格納するのに最適なカラム型

MySQL4.x で IP アドレスを保存するには、int にして、関数で変換して利用してやると文字列よりも加工がしやすい。

mysql> SELECT INET_ATON(“209.207.224.40”);
       -> 3520061480

mysql> SELECT INET_NTOA(3520061480);
       -> “209.207.224.40”

ネットマスクは例えば次のようにチェックできる。

mysql> select INET_ATON(“192.168.0.255”) & INET_ATON(“192.168.0.0”) = INET_ATON(“192.168.0.0”);
       -> 1
 
mysql> select INET_ATON(“192.167.255.1”) & INET_ATON(“192.168.0.0”) = INET_ATON(“192.168.0.0”);
       -> 0

自動的にリソースを開放する構文

System.IDisposable を実装していると、using(obj){ /* … */ }という構文が使える。たとえば

Graphics g;
Brush b;
try{
g = pictureBox1.CreateGraphics();
b = new SolidBrush(Color.Black);
g.FillRectangle(b, 10, 0, 100, 100);
}finally{
b.Dispose();
g.Dispose();
}

は,

using(Graphics g = pictureBox1.CreateGraphics()){
using(Brush b = new SolidBrush(Color.Black)){
g.FillRectangle(b, 10, 0, 100, 100);
}
}

と等しい。
標準クラスライブラリでは多くのクラスがこのインターフェイスを実装しているため、ファイルアクセス、データベースアクセスなどでも利用できてなかなか便利。
参考:
C# Tips −usingを使え、使えったら使え(^^)
.NET Framework クラスライブラリ – IDisposable インターフェイス