漫ろで行こう

自由気まま過ぎる、ギークになりたい男の子の話

Archive for the ‘データベース’ category

© 1995-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.


そりゃ、5.0.3 から FEDERATED エンジンが実装されたので見れませんでした。おわり。

4.x 系で稼働している MySQL(DB-A) のデータを、新しく構築する 5.1.x 系(DB-B)にあるサマリーテーブルに格納して有効活用するという案件が浮上してきたため。
DB-B にある DB を DB-A 側から MS SQL Server のリンクサーバーのように扱いたいという。
元々は MS SQL Server から、ODBC 経由で DB-B の DB をリンクサーバーを利用して操作するつもりでいたのですが、今回 MySQL 4.x 系のデータも同様のように処理する(かもしれない)ということに。

DB-A から DB-B をリンクサーバーのように参照するには?と考えたところ浮上してきたのが FEDERATED エンジン。
要は何が言いたいかと言うと、5.x 系での FEDERATED エンジンの記事はいっぱいあるけど、異なるバージョン間での FEDERATED エンジンを利用した記事が全然なかったので、実際に試してみました的なメモ。
FEDERATED エンジン使うの初めてなの……。

1.構成

◆リモートサーバー(DB-A)
MySQL 4.1.15
◆ローカルサーバー(DB-B)
MySQL 5.1.38

DB-A 側では FEDERATED エンジンが利用できないので、DB-B 側でローカルサーバーとします。
よくある記事ではローカルだとかリモートだとか、実際触ってみなくちゃ良くわからんかったです。触ってみた感覚としては、DB-A を DB-B 側からマウントするようなイメージが一番しっくりきました。

2.DB-A のテーブル確認
リモート側(参照される側)のテーブルは以下のような感じで作られているとします。

CREATE TABLE `tbl_ServerStatus` (
  `CDate` timestamp NOT NULL default CURRENT_TIMESTAMP,
  `Status` enum(‘Up’,'Down’) default NULL,
  `Memo` varchar(255) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

3.DB-B での FEDERATED エンジン利用の設定
自分が利用した MySQL 5.1.38 では、デフォルトで FEDERATED エンジンが DISABLED になっているため、そのままでは利用できません。
my.conf に利用出来るようにするための設定を記述する必要があります。

[mysqld]
federated

4.DB-B から DB-A のテーブルへ接続する
既に DB-A に存在するテーブルへ接続します。
感覚的には枠を用意してあげてリンクさせる感じでしょうか。

CREATE TABLE `tbl_ServerStatus` (
  `CDate` timestamp NOT NULL default CURRENT_TIMESTAMP,
  `Status` enum(‘Up’,'Down’) default NULL,
  `Memo` varchar(255) default NULL
) ENGINE=FEDERATED DEFAULT CHARSET=utf8
CONNECTION=’mysql://[UserName]:[Password]@[RemoteIP]:3306/[DBName]/[TableName]‘;

最後の「CONNECTION」の箇所が重要です。
[UserName][Password]は MySQL のユーザー名とパスワードになります。
[DBName][TableName]は、DB が「Test」だとした場合、今回は「/Test/tbl_ServerStatus」になります。

以上、設定おわり。
実際に SELECT してデータを参照することが出来ました。また、INSERT, UPDATE, DELETE も問題なく反映されました。

official.MySQL :: 世界でもっとも普及している、オープン ソース データベース

© 1995-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.


完全個人的なメモ書きです。
全然足りていないかと思うので、不足などあったら @suzuro2045 まで指摘していただけると助かります。
こうしてみると面白いエンジンがいっぱいです。
カラムナデータベースエンジンって無いのかしら?自分が知らないだけ?

基本的なの
MyISAM
InnoDB
MEARGE
MEMOY (HEAP)
EXAMPLE
FEDERATED
ARCHIVE
CSV
BLACKHOLE
Maria (旧:MyISAM++)
InnoDB の代替エンジン
official.Monty says
Sphinx
全文検索エンジン
official.Sphinx – Free open-source SQL full-text search engine
NDB
MySQL Cluster エンジン
via.hirohama.mysql
Q4M
メッセージキューエンジン
official.Q4M – a Message Queue for MySQL
Pacific
分散ストレージエンジン
via.Kazuho@Cybozu Labs: Pacific という名前の分散ストレージを作り始めた件
RethinkDB
SSD特化型ストレージエンジン
official.RethinkDB – The database for solid state drives.
Spider
Database Sharding エンジン
official.SpiderForMySQL.com
Vertical Partitioning
カラムパーティショニングエンジン(※not Column Database)
via.Wild Growth 日本語: [MySQL][VP]Vertical Partitioningストレージエンジン 0.1リリース
official.Vertical Partitioning for MySQL in Launchpad
BlitzDB
Drizzle 用ストレージエンジン
official.Efficient general purpose Storage Engine for the MySQL family in Launchpad
©2009 Google

©2009 Google

© 1995-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.

© 1995-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.


自分で Wrapper を書いたわけじゃないのですが、やっぱり MySQL に接続してみたいよね!ということで、GitHub に上がってるソーシャルコード mysqlgo を利用させていただき、接続および select クエリの発行をしてみました。
だから何だって話になったら元も子もないですが、完璧自己満足の世界ですので、あしからず。

テスト環境

  • CentOS 5.4
  • MySQL 5.1.38

まず、mysqlgo のソースコードを入手してインストールする必要があるのですが、Zip や Tar などのアーカイブをダウンロードする方法(mysqlgo のページに download ボタンがあります)と、git から clone を取得する方法の2パターンあります。
自分はまだ試したことがなかったので、後者の git を用いる方法で取得しインストールしてみました。

git のインストール
root ユーザーになって yum から git をインストールします

[root@host ~]# yum install git

git の初期設定
git のグローバル設定にユーザー名とメールアドレスを設定します

[user@host ~]$ git config –global –list
[user@host ~]$ git config –global user.name “Suzuro”
[user@host ~]$ git config –global user.email hoge@hoge.com
[user@host ~]$ git config –global –list
user.name=Suzuro
user.email=suzuro2045@gmail.com

mysqlgo のチェックアウト
チェックアウトとチェックアウトしたファイルの確認。

[user@host ~]$ git clone git://github.com/eden/mysqlgo.git
[user@host ~]$ ls mysqlgo/
LICENSE README.markdown gcc.patch mw.h mysql_test.go
Makefile example.go mw.c mysql.go

mysqlgo のインストール

[user@host mysqlgo]$ make install
cp _obj/mysql.a /home/suzuro/go/pkg/linux_386/mysql.a
gcc -I/usr/include/mysql -g -pipe -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector –param=ssp-buffer-size=4 -m32 -fasynchronous-unwind-tables -DUNIV_LINUX -DUNIV_LINUX -o mw.o -c mw.c
gcc -m32 -shared -lpthread -lm -o mysql_mysql.so mysql.cgo4.o mw.o -rdynamic -L/usr/lib/mysql -lmysqlclient -lz -lcrypt -lnsl -lm -lmygcc
cp mysql_mysql.so /home/suzuro/go/pkg/linux_386/./mysql_mysql.so

以上で mysqlgo のインストールは完了です。なんてお手軽!
次に、テスト用 DB およびテーブル、サンプルデータを MySQL に作成し、mysqlgo を利用したテストコードを書いて実行してみます。

テスト用 MySQL データの作成

DROP TABLE IF EXISTS `hoge`;
CREATE TABLE `hoge` (
`id` bigint(20) NOT NULL auto_increment,
`str` varchar(255) collate utf8_bin NOT NULL,
`cdate` timestamp NOT NULL default CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `cdate` (`cdate`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

insert into `hoge`(str) values
(‘aiueo’),
(‘あいうえお’),
(‘αβγ’),
(‘абв’);

mysql> select * from hoge;
+—-+—————–+———————+
| id | str | cdate |
+—-+—————–+———————+
| 1 | aiueo | 2009-11-17 12:40:53 |
| 2 | あいうえお | 2009-11-17 12:40:53 |
| 3 | αβγ | 2009-11-17 12:40:53 |
| 4 | абв | 2009-11-17 12:40:53 |
+—-+—————–+———————+
4 rows in set (0.00 sec)

mysqlgo テストコードの作成
まず、作業用のディレクトリを作成し、そこにコードを置きたいと思います。

[user@host mysqlgo]$ mkdir -p ~/test/mysqlgo
[user@host mysqlgo]$ cd ~/test/mysqlgo/
[user@host mysqlgo]$ vi mysqlgo.go

コードは以下のような感じで。手抜きも良いとこです。

package main

import (
  ”mysql”;
  ”fmt”;
)

func main ()
{
  conn := mysql.NewConn();
  err := conn.Connect(&mysql.ConnInfo{“localhost”, 3306, ”root”, ”", ”test”});

  if err != nil {
    panic(“Connect Error”);
  }

  cur := conn.Cursor();
  cur.Execute(“select * from hoge;”);
  tuple, err := cur.FetchOne();
  for ; err == nil && tuple != nil; tuple, err = cur.FetchOne()
  {
    fmt.Println(tuple);
  }

  conn.Close();
}

コンパイルして実行。

[user@host mysqlgo]$ 8g mysqlgo.go
[user@host mysqlgo]$ 8l -o mysqlgo mysqlgo.8
[user@host mysqlgo]$ ./mysqlgo
[1 aiueo 2009-11-17 12:40:53]
[2 あいうえお 2009-11-17 12:40:53]
[3 αβγ 2009-11-17 12:40:53]
[4 абв 2009-11-17 12:40:53]

以上で終わり。
ドキュメントがないので、サイトの Synopsis を参考にというかそのまま書かせてもらったのですが、今後 mysqlgo が一般的になってくるのか、はたまた MySQL AB からオフィシャルで Connector が出てくるのか。
かなり気にはなりますが、それ以前に今後の Go 言語の普及率がどうなるかが見物かもしれません。

© 1995-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.

© 1995-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.


会社の人に何故か質問されたのでメモ。

事の発端は、他の課の人から「無効な日付、例えば 0000-00-00 00:00:00 が含まれるデータを Connector/Net 経由でデータ抽出する場合にエラーが発生するのですが、その回避方法が掲載されているオフィシャルのドキュメントが意味不明なんです」というもの。
問題のドキュメントはこちら「MySQL :: MySQL 5.1 リファレンスマニュアル :: 24.2.4.6 Connector/NET で日付時間情報を処理する
で、問題の記述「24.2.4.6.4. 無効な日付の処理

無効な日付に MySqlDateTime を返すよう Connector/NET に指示するには、次のラインを接続ストリングに追加してください :

NotOverridable Public ReadOnly Property State As ConnectionState _
_
Implements IDbConnection.State

あー、うん。意味不明。VB での ConnectionState 取得方法な気がする。
ということで、当の本人には「公式ドキュメントが間違えている旨」と「Allow Zero Datetime を使用する旨」を伝えておきましたが、一応自分でチェックしておかないと怖いので念のため確認。

テスト環境は以下のような感じ。

  1. MySQL : 5.1.38
  2. MySQL Connector/Net : 6.1.2
  3. 言語 : C#

まずテーブルを作成してテスト用のデータを入れておく。

DROP TABLE IF EXISTS `hoge`;
CREATE TABLE `hoge` (
`id` bigint(20) auto_increment,
`str` varchar(255) DEFAULT ” NOT NULL,
`CDdate` datetime DEFAULT ’0000-00-00 00:00:00′,
`CStamp` timestamp DEFAULT NOW(),
KEY `id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO (str) values(‘a’),(‘b’),(‘c’),(‘d’);
SELECT * FROM hoge;

+—-+—–+———————+———————+
| id | str | CDdate | CStamp |
+—-+—–+———————+———————+
| 1 | a | 0000-00-00 00:00:00 | 2009-11-05 10:18:20 |
| 2 | b | 0000-00-00 00:00:00 | 2009-11-05 10:18:20 |
| 3 | c | 0000-00-00 00:00:00 | 2009-11-05 10:18:20 |
| 4 | d | 0000-00-00 00:00:00 | 2009-11-05 10:18:20 |
+—-+—–+———————+———————+

次にコードを書きますが端折ります。
基本的な書き方は System.Data.SqlClient と同様で、MySql.Data.MySqlClien を参照するだけです。
接続文字列に Allow Zero Datetime を設定しているパターンと設定していないパターンの結果が以下になります。
各出力の1行目にコネクションストリングを出力し、2行目以降に SELECT 結果を出力するようにしました。

Allow Zero Datetime 未設定

Database=test;Data Source=localhost;User Id=hoge;Password=hoge;
1 a MySql.Data.Types.MySqlConversionException: Unable to convert MySQL date/time value to System.DateTime
場所 MySql.Data.Types.MySqlDateTime.GetDateTime()
場所 MySql.Data.MySqlClient.MySqlDataReader.GetValue(Int32 i)
場所 MySql.Data.MySqlClient.MySqlDataReader.get_Item(Int32 i)
場所 AllowZeroDatetime.Program.ExecMySql(String cns) 場所 C:\test\AllowZeroDatetime\AllowZeroDatetime\Program.cs:行 43

Allow Zero Datetime 設定

Database=test;Data Source=localhost;User Id=hoge;Password=hoge;Allow Zero Datetime=True;
1 a 0000/00/00 0:00:00 2009/11/05 10:18:20
2 b 0000/00/00 0:00:00 2009/11/05 10:18:20
3 c 0000/00/00 0:00:00 2009/11/05 10:18:20
4 d 0000/00/00 0:00:00 2009/11/05 10:18:20

Allow Zero Datetime を設定していない場合、案の定 0000-00-00 00:00:00 が設定されているカラムで Exception が発生しました。設定している場合には、問題なく出力されていることが分かります。
個人的にはデフォルト値で 0000-00-00 00:00:00 を設定するのは気持ち悪いのでやりたくないですね。設定するくらいなら NULL にしておきたいですが。

ドキュメントの該当箇所に関してはフィードバックをしておきたいと思います。

© 1995-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.

© 1995-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.

所用で C# から MySQL :: Connector/Net 6.0 を利用して MySQL からデータを抜く必要があったため、コーディングしていたのですが
Fatal error encountered during command execution
といったエラーが。

原因は直ぐに特定できたのですが、どうにも腑に落ちない。
というのも、原因は条件式の検索文字列の先頭に「@」が付いているため、変数として誤認されるのが原因で回避策は後回しとして、通常の SELECT 文とプロシージャコールで挙動が異なること。
プロシージャは以下のような感じ。これで同様のエラーが発生することはなく、問題なく動作してしまう。

string hoge = "@abc";
string fuga = "asdf1234";
string query = string.Format("call proc_Test('{0}', '{1}');", hoge, fuga);

一方、通常の SELECT 文だと先述したプロシージャのようなコーディングを行うと Fatal error encountered during command execution と怒られてしまう。
対処方法としては以下のような感じにする必要がある。

string cns = "MySQL接続文字列";
string hoge = "@abc";
string fuga = "asdf1234";
string query = string.Format(
  "select * from atTest where testName=@TEST and testPass='{0}';", fuga);
using (MySqlConnection conn = new MySqlConnection(cns))
{
  MySqlCommand cmd = new MySqlCommand(query, conn);
  cmd.Parameters.Add(new MySqlParameter(
    "@TEST", MySqlDbType.VarChar, 40));
  cmd.Parameters["@TEST"].Value = hoge;
  cmd.CommandTimeout = 300;
  conn.Open();
  // 処理
  conn.Close();
}

後者も完璧ではないけども(fuga 変数の内容も本来であれば、Parameters に Add するべきなんだけど)プロシージャの場合は問題無いのはどういうことだろう?
Conncector/Net のバグなのか仕様なのか……。

official.MySQL Query Analyzer – Improving SQL Query Performance

© 1995-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.

© 1995-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.

先週末にリリースされた MySQL 5.1.38 において、InnoDB のプラグイン化がされたそうなので、試してみました。且つ覚書的な。

試してみた環境

OS バージョン
CentOS release 5.3 (Final)
MySQL バージョン
MySQL 5.0.45

Cent OS 5.3 ですが、MySQL :: MySQL 5.1 GA から Red Hat Enterprise Linux 5 RPM (x86) 版をダウンロード。
とりあえず、Server, Client, Shared libraries, Headers and libraries の4つ。

rpm -Uvh MySQL-client-community-5.1.38-0.rhel5.i386.rpm MySQL-server-community-5.1.38-0.rhel5.i386.rpm MySQL-devel-community-5.1.38-0.rhel5.i386.rpm MySQL-shared-community-5.1.38-0.rhel5.i386.rpm

実行したら Server のみ怒られました……。
なので、Server のみ削除してインストールします。

rpm –nodeps -ev mysql-server-5.0.45-7.el5

削除できたらインストール。

rpm -Uvh MySQL-server-community-5.1.38-0.rhel5.i386.rpm

インストールできたら mysqld を動作させて、過去バージョンとの差異というか整合性をあわせるために以下のコマンドを実行。

mysql_upgrade

これで準備完了。
my.cnf に以下を記述。

[mysqld]
ignore-builtin-innodb
plugin-load=innodb=ha_innodb_plugin.so

プラグインファイルを発見出来ず、起動することが出来ない場合があったら、プラグインのディレクトリを追記してあげます。
自分の環境ではプラグインの場所はこんな感じでした。

[user@host etc]# locate innodb_plugin
/usr/lib/mysql/plugin/ha_innodb_plugin.a
/usr/lib/mysql/plugin/ha_innodb_plugin.la
/usr/lib/mysql/plugin/ha_innodb_plugin.so
/usr/lib/mysql/plugin/ha_innodb_plugin.so.0
/usr/lib/mysql/plugin/ha_innodb_plugin.so.0.0.0

なので、my.cnf に記述すると以下のようになります。

[mysqld]
ignore-builtin-innodb
plugin-load=innodb=ha_innodb_plugin.so
plugin_dir=/usr/lib/mysql/plugin

設定が反映させているか確認。

mysql> show plugins;
+————+———-+—————-+———————+———+
| Name              | Status   | Type           | Library             | License |
+————+———-+—————-+———————+———+
| binlog            | ACTIVE   | STORAGE ENGINE | NULL                | GPL     |
| partition        | ACTIVE   | STORAGE ENGINE | NULL                | GPL     |
| ARCHIVE        | ACTIVE   | STORAGE ENGINE | NULL                | GPL     |
| BLACKHOLE    | ACTIVE   | STORAGE ENGINE | NULL                | GPL     |
| CSV                | ACTIVE   | STORAGE ENGINE | NULL                | GPL     |
| FEDERATED    | DISABLED | STORAGE ENGINE | NULL                | GPL     |
| MEMORY         | ACTIVE   | STORAGE ENGINE | NULL                | GPL     |
| MyISAM          | ACTIVE   | STORAGE ENGINE | NULL                | GPL     |
| MRG_MYISAM | ACTIVE   | STORAGE ENGINE | NULL                | GPL     |
| InnoDB           | ACTIVE   | STORAGE ENGINE | ha_innodb_plugin.so | GPL     |
+————+———-+—————-+———————+———+

Library が NULL ではなく、Plugin ファイル名が表示されていれば OK です。

InnoDB Plugin にしてどうなるか?ということは特にないです。
寧ろ現状ベータ版につき、不具合が発生するかもしれません。
5.1.38にアップデートしたら InnoDB は使えなくなるかというと No で、ちゃんと今まで通りビルトイン環境も残っているので、従来通りの使い方が出来ます。

じゃあ、InnoDB Plugin て不要じゃないかと思うかもしれませんが、今ではなく今後に期待すべきプラグインになります。
ビルトインじゃない分、プラグイン形式の方が開発に融通が利きます。また、新しいことを実装するためのテストなんかもプラグイン形式の方が作業を行いやすいです。
そういった融通の利きやすさに対して、今後に期待されています。

今度は Spider Plugin なんかも試してみたいですね。(SpiderForMySQL.com

official.MySQL :: 世界でもっとも普及している、オープン ソース データベース

© 1995-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.

© 1995-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.

仕事の絡みで以前にもやっていた集計をしていて嵌ったのでメモ。いや、普通に考えればそうしたら良いのだけど、混乱したので覚書。

以前の成功例
以前やっていたのは以下の状態。

  • MySQL 5.0.45
  • 対象の型は「decimal」のhogeというカラム
  • decimal 型の小数点以下は切り捨て
  • 対象の型には「正」の数値のみ
  • 合計した値を10で割った数値を出力

上記条件を満たしたクエリは以下。

select sum(cast(hoge as unsigned)/10) from test;

前回はコレで問題なかったのですが、今回同様にしてみたところ。どうしても結果に浮動小数点が表示される……。

今回の失敗例

  • MySQL 5.0.45
  • 対象の型は「int」のhogeというカラム
  • 対象の型には「負」の数値のみ
  • 合計した値を10で割った数値を出力

で、結果クエリがこうなりました。

select truncate(sum((hoge*-1)/10),0) from test;

「/10」がどうも悪さをしているようで、「/10」が無ければ浮動小数点が表示されないけども、10で割りたい。割ったら浮動小数点が表示される。悩んだ挙句、trancate の存在を忘れていたことを思い出したので解決。
うーん、整数で割ってて浮動小数点が表示されるのは何故なんだろう?

© 1995-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.

© 1995-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.


Windows で mysql-proxy を使用するための設定メモ的な。

Linux では利用しているのですが、Windows 環境では初めてだったため、面倒だなぁと思いつつも〆切りが近いのもあって渋々やることに。

以下から mysql-proxy Win32 版をダウンロード。
MySQL :: MySQL Proxy Alpha :: Windows

やったことは完結に以下のこと。

  1. ダウンロードした Zip ファイルを解凍
  2. 出来たフォルダを mysql-proxy にリネームして C:\Program Files 直下へ
  3. mysql-proxy\share\mysql-proxy\ に自分の好みの記述をした lua スクリプトの設置
  4. mysql-proxy\bin\mysql-proxy.exe のショートカットをデスクトップに作成
  5. ショートカットを開いて “C:\Program Files\mysql-proxy\bin\mysql-proxy.exe” を “C:\Program Files\mysql-proxy\bin\mysql-proxy.exe” –daemon –proxy-backend-addresses=[MySQL IP]:[MySQL Port] –proxy-lua-script=”C:\Program Files\mysql-proxy\share\mysql-proxy\hoge.lua” に修正
  6. 起動を確認

Windows では、何気に面倒な作業があるんじゃなかろうかという先入観があった状態で作業していたので、簡単に終わって拍子抜け。
後は適当に、本当に接続できるか確認して終わり。

なお、mysql-proxy はデフォルトで 4040 と 4041 ポートで起動しているので、そこだけ注意。
※あれ?接続出来ないぞ?的な意味で。

official.MySQL :: 世界でもっとも普及している、オープン ソース データベース

© 1995-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.

© 1995-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.

諸事情により言語側での IP チェック処理をしたくないため、MySQL で完結出来ないかなぁと探してみたのですが、ピンポイントで欲している情報がなかったため、色々試行錯誤した結果のメモ的な。

◆やりたいこと

  • DB 上に IP およびネットマスクが登録されている
  • 接続元 IP が DB に登録されている情報にマッチするかチェック
  • OK であれば、先へ進める
  • NG であれば、もちろん弾く

まず、テーブルとサンプルデータを用意。
Yahoo! 様と Google 様にご協力いただきました(勝手に)
本当であれば Yahoo! 様は2つ、Google 様は3つあるのですが、各1つずつ利用サンプルとして利用させていただきました。

DROP TABLE IF EXISTS `tbl_IPMask`;
CREATE TABLE `tbl_IPMask` (
`id` int(10) unsigned auto_increment NOT NULL,
`ip` int(10) unsigned NOT NULL,
`mask` int(10) unsigned NOT NULL,
`name` varchar(40) collate utf8_bin NOT NULL,
`cdate` timestamp NOT NULL default CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_ip` (`ip`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

INSERT INTO tbl_IPMask values
(0, INET_ATON(’124.83.128.0′), INET_ATON(’255.255.128.0′), ‘yahoo.co.jp’, CURRENT_TIMESTAMP),
(0, INET_ATON(’74.125.0.0′), INET_ATON(’255.255.0.0′), ‘google.co.jp’, CURRENT_TIMESTAMP);

1.登録済みネットマスクの取得
DB に登録してあるネットマスクをユニークで抜き出します。

SELECT DISTINCT(mask) from tbl_IPMask;

2.接続があった IP をチェック
MySQL には INET_ATON() と INET_NTOA() という関数があるので、これを利用します。
MySQL :: MySQL 5.1 リファレンスマニュアル :: 11.10.4 その他の関数

取得したユニークなマスクの分だけループして以下の SQL を回します。

SELECT COUNT(id) FROM tbl_IPMask WHERE ip=(INET_ATON(‘接続元 IP アドレス’) & 取得したネットマスク);

Yahoo! 様の場合「124.83.139.192」Google 様の場合「74.125.91.104」から接続があったこととします。

– Yahoo! 様の場合
SELECT COUNT(id) FROM tbl_IPMask WHERE ip=(INET_ATON(’124.83.139.192′) & 4294934528);
– Google 様の場合
SELECT COUNT(id) FROM tbl_IPMask WHERE ip=(INET_ATON(’74.125.91.104′) & 4294901760);

上記を実行すると「1」が返ってきます。「0」が返ってきた場合、NG なので弾きます。
登録されている情報にもよりますが、「0=NG」「0<>OK」とした方が良いかと思われます。

もっと良いやり方があれば、是非に教えていただければ!

via.MySQL :: MySQL 5.1 リファレンスマニュアル :: 11.10.4 その他の関数

サクッと終わらせるつもりが、結構時間を食われたので忘れないようにメモ?。

事の発端は MySQL レプリケーションのスレーブ側が、上手くデータを更新できなかった場合に直ぐメールを携帯に飛ばして対応できるようにしたかった。毎日スレーブ側で show slave status\G を叩くのも面倒なんで。
で、show slave status を叩いた結果で欲しい情報が以下。

  • Slave_IO_State
  • Slave_IO_Running
  • Slave_SQL_Running
  • Last_Errno
  • Last_Error

まぁ、普通に外部から MySQL へアクセスして必要なデータを抜いて、指定メールアドレスへメールを送信するだけの簡単なお仕事のプログラムを作って、ローカルでもデバッグ&テスト完了。いざサーバーへ実装&動作テストをしてみたら変な現象が。

◆カテゴリ
◇ホスト1
Slave_IO_State: System.Byte[]
Slave_IO_Running: System.Byte[]
Slave_SQL_Running: System.Byte[]
Last_Errno: 0
Last_Error: System.Byte[]

◇ホスト2
Slave_IO_State: System.Byte[]
Slave_IO_Running: System.Byte[]
Slave_SQL_Running: System.Byte[]
Last_Errno: 1064
Last_Error: System.Byte[]

System.Byte[] ってあんた……。
バイト配列が帰ってくるなら仕方ない。バイト配列をキャラクター配列に変換してーって、ローカルじゃ正常動作するからデバッグが出来ない?!いや、出来るけど肝心の部分がブラックボックスっぽくなっているのでイマイチ。
肝心の部分はというと、こんなカンジ。
(一部抜粋でもソース貼り付けって恥ずかしいのね)

string slaveIOStatus = reader["Slave_IO_State"].ToString();
string slaveIORunning = reader["Slave_IO_Running"].ToString();
string slaveSQLRunning = reader["Slave_SQL_Running"].ToString();
string lastErrNo = reader["Last_Errno"].ToString();
string lastError = reader["Last_Error"].ToString();

対象のサーバー

  • RedHat EL 5
  • MySQL 5.0.45

に対して、MySQL ODBC Driver 3.51 を使用して接続。

四苦八苦しても直らない。他プログラムではどうってことないのだけども。
あえて違うというと、DB User の権限?SUPER, REPLICATION CLIENT しか権限を与えていない。あとは、接続時の Database を指定していない。
で、結局のところ以下のようにソースを修正したら直った。

string slaveIOStatus = reader.GetString(0);
string slaveIORunning = reader.GetString(10);
string slaveSQLRunning = reader.GetString(11);
string lastErrNo = reader.GetString(18);
string lastError = reader.GetString(19);

期待値のメール内容はこんなカンジ。

◆カテゴリ
◇ホスト1
Slave_IO_State:
Slave_IO_Running: No
Slave_SQL_Running: Yes
Last_Errno: 0
Last_Error:

◇ホスト2
Slave_IO_State:
Slave_IO_Running: No
Slave_SQL_Running: No
Last_Errno: 1064
Last_Error: Error ‘You have an error in your SQL syntax; ‘ (略

DNS じゃないけど、名前解決的なことができていなかったっぽい。
取り急ぎソース修正で対応できたけども……。危険な気がする。

Get Adobe Flash playerPlugin by wpburn.com wordpress themes
Proudly powered by WordPress. Theme developed with WordPress Theme Generator.
Copyright © 漫ろで行こう. All rights reserved.