がるの健忘録

エンジニアでゲーマーで講師で占い師なおいちゃんのブログです。

「おまえが悪い」ネタ第二弾 orz

んと。ちと色々ありまして

  • 現行本番のDBを色々したいってかとりあえず「ちと細工などしつつ」吸い上げたい
  • 本番DBくん、ぶっちゃけ「uptimeとかすごい事になってる orz」
  • 幸い、いくつか別マシンがある

って状況がお膳立てとしてありまして。
まぁ

  • 一瞬だけMySQL君に止まってもらう
  • データディレクトリを丸ごとcp -pR
  • cpしたファイル一式を、MySQLが入ってる別マシンに移動 & 起動

って処理して、別マシンで安心して吸い上げを開始したです。


さて………日本語が全然吸い上がらない orz


具体的には。0x3fからなります、いわゆる?か連打されております。
実際に?であることは、

head 対象ファイル.sql | od -x | less

で確認してございます orz


で、調査。
んと…my.cnfが違う orz


コンソールに入りまして。statusっちゅ〜コマンドを叩くです。
で、一部抜き出し。
元DB

Server characterset: sjis
Db characterset: sjis
Client characterset: sjis
Conn. characterset: sjis

ぶち込んだ吸い上げ用DB

Server characterset: latin1
Db characterset: sjis
Client characterset: latin1
Conn. characterset: latin1

orz orz orz
いいぢゃん所詮バイナリデータなんだしなにもしねぇで素直にはき出してくれよ ;;


中でなにをどのように処理してるのかかなり不明ですが。
とりあえず「copyするならmy.cnfまで全部コピらないと駄目」というノウハウを「げっとだぜ〜」(号泣

えと…いやまぁおいらが悪いんだけどさ orz

んと。
ちととある業務で色々ありまして「intで指定したカラムに小数点な数値がはいる」事故が発生しまして。
いやまぁ二次データなんで結構気ぃ抜いてたんですが orz


おいといて。


えと…ちょっと興味深いデータが見つかりまして実験をしてみたりしました。

create table aaa (
a int,
b varbinary(8)
);

で、以下のSQLを流します。

insert into aaa(a,b) values('1.0', '1.0');
insert into aaa(a,b) values('1.1', '1.1');
insert into aaa(a,b) values('1.2', '1.2');
insert into aaa(a,b) values('1.3', '1.3');
insert into aaa(a,b) values('1.4', '1.4');
insert into aaa(a,b) values('1.5', '1.5');
insert into aaa(a,b) values('1.6', '1.6');
insert into aaa(a,b) values('1.7', '1.7');
insert into aaa(a,b) values('1.8', '1.8');
insert into aaa(a,b) values('1.9', '1.9');
insert into aaa(a,b) values(2.0, '2.0');
insert into aaa(a,b) values(2.1, '2.1');
insert into aaa(a,b) values(2.2, '2.2');
insert into aaa(a,b) values(2.3, '2.3');
insert into aaa(a,b) values(2.4, '2.4');
insert into aaa(a,b) values(2.5, '2.5');
insert into aaa(a,b) values(2.6, '2.6');
insert into aaa(a,b) values(2.7, '2.7');
insert into aaa(a,b) values(2.8, '2.8');
insert into aaa(a,b) values(2.9, '2.9');

結果。

mysql> select * from aaa;
+------+------+
| a    | b    |
+------+------+
|    1 | 1.0  |
|    1 | 1.1  |
|    1 | 1.2  |
|    1 | 1.3  |
|    1 | 1.4  |
|    1 | 1.5  |
|    1 | 1.6  |
|    1 | 1.7  |
|    1 | 1.8  |
|    1 | 1.9  |
|    2 | 2.0  |
|    2 | 2.1  |
|    2 | 2.2  |
|    2 | 2.3  |
|    2 | 2.4  |
|    3 | 2.5  |
|    3 | 2.6  |
|    3 | 2.7  |
|    3 | 2.8  |
|    3 | 2.9  |
+------+------+
20 rows in set (0.00 sec)

えと…シングルクォートで囲むかどうかで変化する上に囲まない数値については四捨五入してくださがりやります orz


もちろん。
もちろん「整数って言ってるところに小数ぶち込む方が悪い」のですが…が…せめてinsert errorにして欲しいって思うのはわがままなんでしょうか orz
もし万が一「奇妙なバグに悩まされたら」、可能性の一つとして知っておくと便利な知識…かも、しれません。


やれやれ orz

DNSの逆引きでエラー

via http://www.res-system.com/weblog/item/582

んと。キーワードとしては「MySQLで時々妙に重くなる」とか「プロセス数がmaxいっちゃってconnect出来ない」とかそんな事象。
mysqlコンソールでログインしてshow processlistコマンドとかで見ると、unauthenticated user っちゅ〜プロセスがたまってることがあるです。
なんでもこの子。「MySQLDNS逆引き」のタイミングでおきてるとか。
いいからDBMSがresolveとかしなくて。


とりあえず。起動optionに --skip-name-resolve を入れるか、またはmy.cnfあたりの設定ファイルに

[mysqld]
skip-name-resolve

の設定を入れ込んでおきませう。


っつか…ねぇねぇMySQLって「余計なことしない代わりに軽いDBMS」ぢゃなかったの?
最近、失望する内容がわりと連打できてるのですが………;;

え?

http://itpro.nikkeibp.co.jp/article/NEWS/20080117/291269/

SunがMySQLを10億ドルで買収,「イルカの飛翔を手助け」

Sun Microsystemsは1月16日(米国時間),オープンソース・データベースの大手であるスウェーデンMySQLを10億ドルで買収すると発表した。Sunの社長兼CEO(最高経営責任者)であるJonathan Schwartz氏は,MySQLのマスコットにちなんで「イルカの飛翔を手助けする」と述べ,オープンソースへの支援を強化し続けることをアピールした。

えと…吉報なんだか凶報なんだかが全然判断つかにゃい orz

ははぁん大分見えてきた…けどね orz

さすがに見逃せない話が多々あったので、ちと調べてみた。
で…大分見えてきた。ポイントは多分「3つの自動化」。


まずわかりやすいのは「文字コードの自動化」。
彼ら的には、EUCとしての「おはよう」とUTF-8としての「おはよう」を、つまり

euc('おはよう') = utf-8('おはよう')

を、trueにしたいわけだ。
まぁわからんでもない。面倒起こしやすいことも多々あるのだが。


次に。「スペースパディング」の自動化。
padding(パディング)はいいよね? ゼロパディングとかあるし。雑に書くと「データ量の不足分を一定の文字で埋める」の。
で。
charとvarcharの違い。charは固定長なのに対して、varcharは可変長。んじゃ可変部分をどうやってるかって言うと、大抵は「先頭の1バイトとか2バイトとか4バイトとか8バイトとか使ってそこにlengthを埋め込んでる」の。
翻って。charは固定長。んじゃ「char(10)に8文字いれて。のこり2文字どうする?」。
大抵の場合。ここを「スペースパディング」するざます。つまり「空白で埋める」。
だとすると。このタイミングにおいては

'01234567' = '01234567  '

がtrueにならないと困る。だってスペースは「システムがシステムの都合で勝手に入れたもの」だから。
で、この考え方を応用したんだか横着したんだかして、かくして
http://dev.mysql.com/doc/refman/5.1/ja/char.html

全てのMySQL照合は PADSPACE タイプの物だと覚えておいてください。これは、MySQLの中の全ての CHAR と VARCHAR 値が後続スペースを無視して比較されるという事を意味します。

って流れになる。


最後に。………これはどうしても想像しにくいんだけど。「lowerとupperの自動化」。
少なくとも彼らの感性において、

'a' = 'A'

というのは、trueらしい。ちなみにこの延長線として、割合に容易に

'a' = 'A' = euc('A') = utf-8('a')

がtrueになるんだろうと思われる。後ろ二つはいわゆる「多バイト文字」ね。
そう考えた根拠はここ。
http://dev.mysql.com/doc/refman/5.1/ja/charset-binary-op.html

キャラクタ毎よりも、バイト毎の比較を強制的に行う簡単な方法です。

上述、キャラクタ的には同一視してると思われる。


さて。「文字コードの自動化」は、人によりけり微妙だけど、俺的にはNG。パディングと大小文字の自動化は論外。
で…対策は人生色々女も色々。


とりあえず文字コード抑制として、コンパイルオプション&my.cnfに手を入れてみる。
具体的には以下参照。
http://vivian.reverb.jp/mysql4.1.html

# MySQL4.1.12 ソースから--with-charset=binaryの指定ありでコンパイル(こうするとクライアントをbinaryで作れる)。
# my.cnfは以下。

[mysqld]
default-character-set=utf8
[mysqldump]
default-character-set=binary

これで、おそらくは「文字コードの自動化」が抑止できる。
以下、確認用のメモ。

mysql> SHOW VARIABLES LIKE "char%";
character_set_client
    クライアントから渡されるSQL文のキャラクタセット
character_set_connection
    SQL文中の文字列リテラルのキャラクタセットのデフォルト値
character_set_database
    CREATE DATABASE でキャラクタセットを指定しなかった場合にこの値が使用される
character_set_results
    クライアントへ結果を返す時のキャラクタセット
character_set_server
    character_set_database のデフォルト値に影響する
character_set_system
    テーブル名やカラム名用。どうあがいてもutf8で固定 

大文字小文字については、create tableのchar、varchar、textにbinaryをつけるのがひとつ。


で、大小文字+スペースパディングの抑止には、binaryによるキャストが有効。
ただ
http://mysql.mirrors-r-us.net/doc/refman/4.1/ja/case-sensitivity-operators.html

注意: MySQL の一部のコンテキストでは、インデックス付きのカラムを BINARY にキャストすると、インデックスを効率的に使用できなくなる。

という予想通りの文句があるので、binaryキャストは定数(シングルクォートした文字列)に対してやるほうが安全。
書式的には

カラム名 = binary '定数'
カラム名 = binary('定数')

こんな感じ。


で、最後に、すばらしくはしたないアイデア(笑
http://dev.mysql.com/doc/refman/5.1/ja/binary-varbinary.html

BINARY と VARBINARY タイプは、非バイナリ文字列ではなく、バイナリ文字列を含んでいるところ以外で CHAR と VARCHAR に似ています。それは、それらが文字の文字列ではなく、バイトの文字列を含んでいるという事です。これは、それらが文字セットを持たず、ソートと比較は値の中の数値バイトに基づいているという意味です。

http://dev.mysql.com/doc/refman/5.1/ja/blob.html

BLOB カラムはバイナリ文字列(バイト文字列)として扱われます。TEXT カラムは非バイナリ文字列(文字の文字列)として扱われます。BLOB カラムは文字セットを持たないので、ソートと比較は値の中の数値バイトに基づいています。TEXT カラムは文字セットを持つので、値は文字セットの照合に基づいてソート、比較されます。

つまりね。

sed -e s/varchar/varbinary/
sed -e s/text/blob/

ほぉらはしたないw


とりあえず……………おぢちゃん疲れたよ orz