- バックアップ一覧
- 差分 を表示
- 現在との差分 を表示
- ソース を表示
- FAQ へ行く。
- 1 (2005-01-25 14:01:14 (火))
- 2 (2005-01-27 14:43:07 (木))
- 3 (2005-01-28 14:17:26 (金))
- 4 (2005-01-30 23:32:39 (日))
- 5 (2005-01-31 08:51:07 (月))
- 6 (2005-02-04 16:42:46 (金))
- 7 (2005-02-04 23:53:29 (金))
- 8 (2005-02-05 14:50:54 (土))
- 9 (2005-02-06 01:29:07 (日))
- 10 (2005-02-06 21:56:36 (日))
- 11 (2005-02-16 12:31:28 (水))
- 12 (2005-02-17 22:23:50 (木))
- 13 (2005-02-18 14:30:05 (金))
- 14 (2005-02-20 20:46:59 (日))
- 15 (2005-02-22 01:06:57 (火))
- 16 (2005-02-22 12:01:46 (火))
- 17 (2005-02-23 02:15:35 (水))
- 18 (2005-02-23 14:14:32 (水))
- 19 (2005-02-24 00:06:45 (木))
- 20 (2005-02-24 20:52:31 (木))
- 21 (2005-02-25 17:36:38 (金))
- 22 (2005-02-26 12:19:20 (土))
- 23 (2005-02-27 00:06:55 (日))
- 24 (2005-02-28 18:23:28 (月))
- 25 (2005-02-28 23:41:16 (月))
- 26 (2005-03-01 21:10:13 (火))
- 27 (2005-03-02 20:28:50 (水))
- 28 (2005-03-06 12:20:24 (日))
- 29 (2005-03-17 03:36:14 (木))
- 30 (2005-04-06 18:59:56 (水))
- 31 (2005-04-11 07:48:47 (月))
- 32 (2005-04-20 10:26:18 (水))
- 33 (2005-04-21 10:04:57 (木))
- 34 (2005-04-22 03:10:55 (金))
- 35 (2005-05-06 20:48:49 (金))
- 36 (2005-05-07 11:46:41 (土))
- 37 (2005-05-08 10:04:06 (日))
- 38 (2005-09-28 00:36:06 (水))
- 39 (2005-11-25 09:34:53 (金))
- 40 (2006-06-03 10:37:40 (土))
- MySQLインストール
- MySQL運用
- OS選択
- ストレージエンジン??
- 複数のMySQLを同居させるには/MySQLを違うディレクトリで動かすには
- I/O分散
- ログとリカバリ
- バックアップ
- 日本語環境の設定
- my.cnf ファイルの読み込み順番
- init-connect
- AUTOCOMMIT モード
- 大きなフィールドを含む場合
- 多くの接続がある場合
- メモリーの使用量
- 4.1以上の壁
- 4.1 では何が変わったの?
- CHAR の定義の違いによる弊害
- 文字コードの自動変換機能による弊害
- mysqldump の仕様変更の弊害
- パスワード保存形式の変更
- データベース名、テーブル名、フィールド名は、utf8 コードに直されて保存されるように変わったことの弊害
- 3.X,4.0 -> 4.1 以上の手順
- 4.1サーバーと4.0クライアント
- version 4.1 以上の文字コード変換機能とうまくつきあうには?
- 4.1 にupgradeしたら文字が?になります / 4.1 にしたらクエリの結果がおかしいことがある
- いままでの説明の概念図
- mysql コマンドでは大丈夫なのに、PHP,perl,accessなどで文字が ? に化けるのは?
- クライアントとサーバーのキャラクターセットの確認
- 4.1以上の日本語に関する問題点まとめ
- 結局、どうしろと?
- MySQL連携
- MySQLインターナル
- MySQL開発
- MySQL ドキュメント
- その他
MySQLインストール †
mysqld が最低必要とする物 †
- basedir/share/ ディレクトリ以下(shareファイル。errmsg.sys や charsets/)
- datadir/mysql/ (mysql 権限データベース、テーブル)
権限テーブルや charsets/ がなければ mysqld は起動しない。
errmsg.sys はバージョンによって数が違うので、違うバージョンの errmsg.sys を使用していると mysqld が起動しない。
これらが起きた場合、.err ファイルにエラーが記録されないことが多い。
バイナリファイル †
- mysql-バージョン-ベンダ-OS-CPUアーキテクチャ.tar.gz
Unix, Unixライク用のバイナリ。
basedir は /usr/local/mysql/
datadir は /usr/local/mysql/var/
としてコンパイルされている
展開して、/usr/local/mysql/ にする。
- mysql-バージョン-win-noinstall.zip , mysql-noinstall-バージョン-win32.zip
ms-win用。
展開して、C:\mysql\ にする。
NT系列の場合、サービスに登録したければ、mysqld-nt --install を使う。
basedir は c:/mysql/
datadir は c:/mysql/data/
MySQL は Windows のレジストリには依存せず、コピーするだけで動く。
- mysql-バージョン-win.zip , mysql-バージョン-win32.zip , mysql-essential-バージョン-win32.msi
ms-win用。インストーラー付き。
インストーラーがおかしいことがあるので、こちらはあまり使わない。
mysql-バージョン-win-noinstall.zip (mysql-noinstall-バージョン-win32.zip) の方を使う。
Windows 用のバイナリ mysqld ファイル †
4.1バイナリ名 | named-pipe | BDB | |
mysqld.exe | 95系用 | - | - |
mysqld-max.exe | mysqld.exe の、フル機能バージョン | - | O |
mysqld-debug.exe | --debug オプションを有効にして作ったバイナリ | O | O |
mysqld-nt.exe | NT/XP 系用。named-pipe が使用できる | O | - |
mysqld-max-nt.exe | mysqld-nt の、フル機能バージョン | O | O |
MySQL サーバーの起動には、
- サービスで起動するか
- コマンドプロンプトで、直接 mysqld.exe を実行するか
- winmysqladmin.exe で起動するか
の方法がある。
起動しない場合は、
- c:\mysql\data\mysqld.err ファイルの中身を確認
- c:\mysql\share\ がちゃんとあるのか確認
- c:\mysql\data\ がちゃんとあるのか確認
Windows サービス †
- 登録
c:\mysql\bin\mysqld-max-nt.exe --install サービス名
mysqld のオプションを指定したい場合は:
c:\mysql\bin\mysqld-max-nt.exe --install サービス名 --defaults-file=c:/mymy.txt
のように、指定したいオプションをサービス名の後につける。
- 削除
c:\mysql\bin\mysqld-max-nt.exe --remove サービス名
登録と削除は同じバイナリで。
MySQL運用 †
OS選択 †
2004-12末時点
- 本格運用には、Unix, Unixライク OS を選ぶ。
- MS-Win は、実験とか開発とかのレベルにおさえておく
- Linux
- glibc 2.3 使用。
- LinuxThread 使用のこと。新しいスレッドは今は使わないように。
- 中途半端なバージョンの glibc は使用しない。redhatがよくやるような、バージョン x.y.90 とかは避けよ
- FreeBSD
- 今のところは LinuxThread を使うこと。
OS による MySQL の違い †
OS による違いはありません。
どの OS 用の MySQL でも動きや機能は同じです。
MS-Winはシンボリックリンクやソケットの実装がないので、それを MS-Win 用にしているぐらい。それ以外は Unix 用と同じです
ストレージエンジン?? †
MySQL は、データの保存形式を複数持っています。 その保存形式により、機能や特徴、パフォーマンスが変わります。 これをストレージエンジンと呼んでいます。
このモデルの利点は:
- 用途にあったストレージエンジンを選択することで、特別なチューニングを施すことなく、その目的に合った能力を得ることができる。
- 古いバージョンのMySQLで作成したファイルは、MySQLをバージョンアップをしてもそのまま使い続けることができる。 MySQL のバージョンアップに際して、データの吸い上げ、入れ直しは発生しない。
- 新しい手法が登場したとき、簡単にその手法を取り入れ、よりよい環境を提供できる。
- あるストレージエンジンは他のストレージエンジンに影響を及ぼさない。 このため、バグの影響が少ない
実際の使い方は
CREATE TABLE ..... (.....) TYPE=InnoDB;
のようにするだけ。
ALTER TABLE .... TYPE=MyISAM;
のように、テーブルのストレージエンジンを ALTER TABLE 文で変えることも可能。(TYPEのかわりに ENGINE キーワードでも OK)
代表的なストレージエンジン:
- MyISAM : 検索に強い
- InnoDB : トランザクション
- NDB : クラスター
- HEAP(MEMORY) : メモリ内で動作するテーブル
標準のストレージエンジン †
標準のストレージエンジンは MyISAM。
すなわち、TYPE とか ENGINE を指定しなければ、テーブルの型は MyISAM になるということ。
標準のストレージエンジンの変更 †
標準のストレージエンジンを InnoDB に変更したい場合は
mysqld --default-table-type=innodb
もしくは
mysqld --default-storage-engine=InnoDB
もちろん、my.cnf (my.ini) に default-table-type=InnoDB を書いてもよい。
(4.1.10のms-win用のインストーラー付きバイナリは、インストール時にインストーラーが my.ini ファイルを作るようになっています。
自動で作成された my.ini に default-storage-engine=InnoDB が記述されています)
権限テーブルのテーブルの型 †
mysql データベース(権限データベース)のテーブルは、MyISAM 以外にしてはいけない。
複数のMySQLを同居させるには/MySQLを違うディレクトリで動かすには †
mysqld --basedir=/usr/local/mysql-4.0.22 --datadir=/usr/local/mysql-4.0.22/data --socket=/tmp/sock4.0.22 --port=4022 &
もしくは
/usr/local/mysql-4.0.22/my.cnf に
[mysqld] basedir=/usr/local/mysql-4.0.22 datadir=/usr/local/mysql-4.0.22/data socket=/tmp/sock4.0.22 port=4022
と書いて
mysqld --defaults-file=/usr/local/mysql-4.0.22/my.cnf &
I/O分散 †
MyISAMの場合
CREATE TABLE .... (...) DATA DIRECTORY = '/path/to/directory/MYD' INDEX DIRECTORY = '/path/to/directory/MYI'
InnoDB の場合1
[mysqld] innodb_data_home_dir = innodb_data_file_path=/path/to/file1:10M;/path/to/file2:50M
InnoDBの場合2
[mysqld] innodb_file_per_table
OSでの対処の場合
- データベースは単なるディレクトリなので、違うdiskをそのディレクトリにマウント
- データベースのディレクトリをどこかに移動して、シンボリックリンクを張る
ログとリカバリ †
log-bin (バイナリ更新ログ) が肝です。
# 3.22 までは、log-update (更新ログ) を使います。
log-bin 採取開始時のデータに対して、log-bin の内容(テキストのSQL文) を順に全て当てていけば、現在のデータになります。
もちろん、ログの途中まであてれば、その時までの状態になります。
roll forward リカバリですね。
どういう運用ができるかはあなたのアイデア次第。
- max_binlog_size : 1つのバイナリ更新ログファイルの最大サイズ。これに達すると、自動でローテート
- log-bin=名前 : バイナリ更新ログファイルの名前の指定。ディレクトリを含めることが出来る。 log-bin=/disk1/logfile とすると、/disk1/logfile.###### ファイルになる。
mysqlbinlog †
バージョン 4.1 の mysqlbinlog には、バイナリ更新ログの切り出しに便利なオプションがあります。
- --start-datetime=
- --stop-datetime=
- --start-position=
- --stop-position=
バックアップ †
- mysqldump
mysqldump --single-transaction --master-data --skip-opt --default-character-set=binary
- バイナリ更新ログ
- バイナリ更新ログ(log-bin)ファイルと、log-bin採取開始時のデータベースの状態があればいい
- ファイルの直接コピー
- tar, rsync, cp, cpio など
- InnoDB Hot Backup
- InnoDB のみ。
- hot back up ツール
- mysqld 実行中のサーバー上で実行する
日本語環境の設定 †
標準のキャラクターセットが日本語になっていないバイナリを使用するときは、設定をしておきます。
[mysqld] default-character-set = ujis [mysqldump] default-character-set = ujis [mysql] default-character-set = ujis
なお、language = の指定は、日本語が扱える、扱えないには、全く関係ありません。設定しても無意味。
たんにエラーメッセージが日本語になるだけで、クエリやデータを日本語扱いにするという意味ではありません。
エラーメッセージが日本語になっても邪魔くさい(変な文だし、文字化けするかも)ので、通常は language は指定しません。
また、全てのアプリが my.cnf を読むわけではありません。勘違いしないように。
my.cnf を読むのは、原則、MySQL 付属のコマンドだけと思ってください。
それ以外は、アプリ側で読むようにコーディングする必要があります。
(この FAQ の「MySQL連携」を参照。)
my.cnf ファイルの読み込み順番 †
- Unix系列の場合
- /etc/my.cnf → データディレクトリ/my.cnf → --defaults-extra-file=で指定されたファイル → ~/.my.cnf
- 「データディレクトリ/my.cnf」 は、コンパイル時に指定されたデータディレクトリ固定です。
- /etc/my.cnf → データディレクトリ/my.cnf → --defaults-extra-file=で指定されたファイル → ~/.my.cnf
- MS-Windows 系列の場合
- %WINDIR%\my.ini → C:\my.cnf → --defaults-extra-file=で指定されたファイル
- my.ini , my.cnf が同時に存在する時は、両方読まれる。my.ini が先に読まれる(今は)
init-connect †
クライアントが接続時に、自動的にサーバー内部で実行される SQL 文を指定できる。
ただし、接続ユーザーに Super 権限がある場合は、この SQL 文は無視される。
ex. mysqld --init-connect='SET AUTOCOMMIT=0'
AUTOCOMMIT モード †
autocommit をはずす。
SET AUTOCOMMIT=0;
autocommit mode
SET AUTOCOMMIT=1;
標準は、AUTOCOMMIT=1
大きなフィールドを含む場合 †
mysqld --max_allowed_packet=
を指定します。
version 4.0 より前は、max_allowed_packetに指定できる値の上限は 16M まででした。
4.0 からは 1G まで指定できます。
これにより、1G弱の大きさの値を LONGBLOB フィールドに入れて扱うことができます。
なお、
- TINYBLOB, TINYTEXT : 255 (2^8-1) バイト
- BLOB, TEXT : 65535 (2^16-1) バイト
- MEDIUMBLOB,MEDIUMTEXT : 16777215 (2^24-1) バイト
- LONGBLOB, LONGTEXT : 4294967295 (2^32-1) バイト
多くの接続がある場合 †
mysqld --max_connections=500
これは同時接続数を500まで許すということ。
標準では 100。
接続数を増やす場合は、メモリーの使用量に注意。
1接続に対して1スレッドが割り当てられます。
メモリーの使用量 †
単純な計算式:
グローバルでのメモリー割り当て量 + 各スレッドへのメモリー割当量 * 接続数
注意:
- ハードウェアやOSによって、1つのプロセスに割り当てられるメモリーの上限値に違いがあることに注意
- メモリーが割り当てられなかったとき、子供のスレッドは立ち上がることができない。
変数(全部は書きません。バージョンによって違うし、常に指定される量を最大限に取るとも限らない)
- グローバルでの割り当て、代表的な変数:
- bdb_cache_size
- bdb_log_buffer_size
- innodb_additional_mem_pool_size
- innodb_buffer_pool_awe_mem_mb
- innodb_buffer_pool_size
- innodb_log_buffer_size
- key_buffer_size
- query_cache_size
- 各スレッドへの割り当て、代表的な変数:
- join_buffer_size
- read_buffer_size
- read_rnd_buffer_size
- sort_buffer_size
4.1以上の壁 †
MySQL 4.0 までは、3.X から 4.0 に upgrade しても、そのまんまなんの影響もなく古いデータを使えました。特にダンプしてリストアしなくても良かったし、ALTER TABLE も必要ありませんでした。
ところが、4.1 以上に upgrade するときは、我々日本語キャラクターセットを使う人間は、注意しなくてはならない点が複数存在します。
4.1 は、5.0pre だと思ってもいいぐらいの開きがあります。(4.0 と 4.1 を同じバージョン 4 だとは思わない方がいいという意味で。)
4.1 では何が変わったの? †
- CHAR(10) は 10 バイトから 10 文字に変わった。
- char() に、全てのバイト列が入らなくなった。例えば、ujis のフィールドには、EUC-JP に定義されるコード空間のバイトしか INSERT できない。全てを入れるパッチは http://www.mysql.gr.jp/frame/modules/bwiki/?Contrib
- パスワードの保存形式が変わった。(長くなった)
- 文字コードの自動変換機能が追加された。
- mysqldump の標準キャラクターセットがどうコンパイルしても utf8 になる
- データベース、テーブル、フィールド、それぞれ個別にキャラクターセットを指定できるようになった。
- データベース名、テーブル名は、OS 上では utf8 コードに直されて保存されるように変わった(ディレクトリ名、ファイル名が、utf8のコードで書かれるようになったということ)。4.0 まではバイナリ列がそのままデータベース名(=ディレクトリ名)、テーブル名(=ファイル名)になっていた。
- timestamp 型の表示フォーマットが変わった。4.0 までは 「20050116214504」 であったが、4.1 では 「2005-01-16 21:45:50」。アプリの作り方に注意。
- HEAP(MEMORY) テーブルのインデックスに、BTREE が加わった。4.0 までの HEAP テーブルは HASH のみ。(i int, INDEX USING BTREE (i)) TYPE=MEMORY;
- sub query の追加
- NDB クラスターの追加
- GIS追加
- utf8 キャラクターセットの追加
CHAR の定義の違いによる弊害 †
これは 3.X, 4.0 から 4.1 に upgrade したときに遭遇する問題です。
3.X, 4.0 で char(10) と定義していたフィールドが、
4.1 に uprade した瞬間に、char(3) もしくは char(5) 扱いになってしまいます。
なぜか?
- ujis は、最大で 3バイトを使用して 1文字を表現する。sjis は最大で 2バイトを使用して sjis 1文字を表現する。
- 4.0 で CHAR(10) と定義した。これは 10 バイト。
- 4.1 に upgrade したら、10バイトを、X文字にしなければならない。
- そこで、ujis の場合は、10バイト -> 3(ujis)文字となる。
文字コードの自動変換機能による弊害 †
4.0 までは、キャラクターセットはサーバーだけが設定するものであり、クライアントがサーバーのキャラクターセットに自動的に合せて動作していました。
ところが
4.1 になってから、サーバー、クライアントがそれぞれのキャラクターセットで動作するようになりました。
例えば、
- クライアントが sjis で動作
- サーバーが ujis で動作
している場合、サーバーは、クライアントに対しては常に sjis のデータを送るようになります。
サーバーは ujis のデータを sjis に変換して、クライアントに送るのです。
これは一見便利です。
が、落とし穴があります。
- 変換できないキャラクターセットの組み合わせの場合
- 変換しきれない文字があった場合
こういう場合は、文字が ? になったり、期待外れの文字になったりします。
例えば、
- クライアントが latin1 で動作
- サーバーが sjis で動作
の場合、どうやって sjis を latin1 の文字コードに変換できるというのでしょう?
出来るわけがないので、sjis 文字はあえなく全て ? になってしまいます。
(え、「?」にしなけりゃいいのにって?
私もそう思います。変換できなければ「?」にせず、そのままのバイトのままにしておけば クライアントが latin1 でも問題が少なかったかもしれません。が、仕様が「?」に変換なので、なんとも。)
例えば、
UTF を使用してアプリを作っている方は経験されているでしょうが、
UTF の変換マップというのは統一が取れていません。
同じことが MySQL にもおきています。
MySQL が変換するコードと、あなたが使用している環境が考えるコードと文字の形の組み合わせが一致するとは限りません。
では、クライアントが latin1 で、サーバーが ujis,sjis の状況というのは、起きうるものなのでしょうか?
困ったことに、現状では簡単にこの状態が引き起こってしまいます。
あなたが使用している PHP は、自分でコンパイルしましたか?
あなたが使用している MySQL は、ご自身の手でコンパイルしましたか?
ほとんどの方が、他の誰かがコンパイルしたものを使用していると思います。
では、あなたが使用している PHP, MySQL のライブラリ(libmysql.dll, libmysqlclient)の標準キャラクターセットは何かご存じですか?
そう、ここが問題なのです。
日本人以外のデベロッパーが作ったバイナリは、ujis,sjis を標準のキャラクターセットにしているわけがありません。
事実 MySQL AB 配布のバイナリは、latin1 が標準です。
それらのバイナリを使って PHP の MySQL モジュールを動かせば(作成すれば)、クライアント(PHP)は latin1 で動作し、サーバーは ujis,sjis で動くことになるのです。こうして日本語文字は破壊されます。
これらの問題を避けるには、方法は2つ。
- PHP(Ruby,Perl,C,...)のアプリの変更。サーバーに接続した後にすぐ、"SET NAMES キャラクターセット名" という SQL 文を実行する
- PHP(Ruby,Perl,C,...)の MySQL モジュールの標準キャラクターセットを、自分が使うキャラクターセットにする。これはアプリの変更はない。しかし、libmysql.dll, libmysqlclient のコンパイルし直しが発生する。
mysqldump の仕様変更の弊害 †
mysqldump は、3.X, 4.0 までは、コンパイルするときに指定されたキャラクターセットを標準としていました。
4.1 からは、mysqldump はコンパイル時のキャラクターセットを無視して、utf8 を標準とします。(ひどい。普通、mysqldump のキャラクターセットは、mysqlコマンドとかのキャラクターセットと同じだと思って使うよなぁ...)
これは、4.1 の文字コード自動変換機能と組合わさって、最低な状況を起こしてしまいます。
サーバーが ujis, sjis で動いていたとしても、utf8 に変換して dump します。
utf8 はご存じの通り、到底整理されているコードとは言い難く、そのため、dump した内容が壊れる可能性が高いです。
これを避けるためには、mysqldump を実行するとき、必ず default-character-set オプションを指定すべきです。
個人的には以下が好みです。
[mysqldump] default-character-set=binary skip-opt hex-blob single-transaction master-data
なお、コンパイル時のキャラクターセットを mysqldump が無視しなくなる、
mysqlコマンドと同じキャラクターセットと同じにするパッチは以下にあります。
http://www.mysql.gr.jp/frame/modules/bwiki/?Contrib
パスワード保存形式の変更 †
4.1 からは、パスワードの長さが長くなりました。
しかし、3.X, 4.0 までのパスワードはそのまま使えます。 3.X, 4.0 までの mysql データベースの内容は、そのまま引き続き使用できます。
例
Password | |
4.0まで | 12de31820cbc0fce |
4.1 | *59170D1E4A5E56267B6ED9C51ED62619FB817E6B |
3.X, 4.0 から 4.1 に upgrade して、mysql_fix_privilege_tables を実行しても、4.0 までの時代に設定した短いパスワードは変更されません。上記例では '12de31820cbc0fce' のままです。
4.1 であたらしくパスワードを設定した場合、'*59170D1E4A5E56267B6ED9C51ED62619FB817E6B' の形式になります。
4.1 のクライアントは、長い方のパスワードでも短い方のパスワードでも認証可能です。
4.0 までのクライアント( libmysqlclient , libmysql.dll ) と 4.1 のサーバーは、長い方のパスワードを使用したら、必ず認証失敗になります。
(「Client does not support authentication protocol requested by server;」)
4.0 までのクライアントと 4.1 のサーバー間の認証が成功する条件は、
- 保存されているパスワードが短い方の形式である場合
- 4.1 サーバーを4.0までのパスワード形式のみで動作させている場合 に限ります。
4.1 サーバーを4.0までのパスワード形式で動作させるには
[mysqld] old-passwords
を指定します。
これは 4.1 サーバーが生成するパスワードの形式を、4.0 までの短い方にするオプションです。
データベース名、テーブル名、フィールド名は、utf8 コードに直されて保存されるように変わったことの弊害 †
MySQL は、データベースをディレクトリ、テーブルを(基本的に)ファイルで表現します。フィールド名は .frm ファイルに記録されています。
4.0 まではバイナリ列がそのままデータベース名(=ディレクトリ名)、テーブル名(=ファイル名)、フィールド名になっていました。
ところが 4.1 からは、ディレクトリ名、ファイル名、フィールド名が、utf8のコードで書かれるようになったのです。
このために、4.0 までの MySQL で作成した日本語データベース名、テーブル名、フィールド名は、サーバーを 4.1 に upgrade したとたん、使えなくなります。
4.0 までに使用していた日本語のデータベース名、日本語のテーブル名、日本語のフィールド名を 4.1 に引き継ぐためには、
- 4.0 までのデータを一度フルダンプして(ファイルのコピーじゃ駄目)、
- 4.1 にバージョンアップしたあとに、
- フルリストアする必要があります。
3.X,4.0 -> 4.1 以上の手順 †
- クライアントの upgrade
Ruby, PHP, Perl など、C クライアントを 4.1 (以上)の libmysqlclient にリンクし直してインストール。
なお、文字の自動変換機能による弊害が発生する可能性があるので、他のFAQを参考のこと。
- 念のため、mysqldump でバックアップ
- upgrade
[mysqld] default-character-set = ujis old-passwords [mysqldump] default-character-set = ujis skip-opt [mysql] default-character-set = ujis
old-passwords オプションは、4.1以上のサーバーの認証方法を、4.0 までの認証方法のままにするということ。mysqldump は、標準では全てのデータを utf8 に変換してしまうという極悪な仕様に変わったので、それを避けるために default-character-set を指定。
- 権限テーブル upgrade
mysql_fix_privilege_tables もしくは
mysql -f -uroot mysql < mysql_fix_privilege_tables.sql
- 全ての CHAR(), VARCHAR() を ALTER する。 4.1 以上では CHAR(10) は 10文字を意味するようになったため。 http://www.mysql.gr.jp/frame/modules/bwiki/?Contrib 他のFAQも参照
4.1サーバーと4.0クライアント †
[mysqld-4.1] old-passwords
MySQL 4.1 サーバーを 4.0 までの認証で動かす。 こうすれば、3.X, 4.0の libmysqlclient(libmysql.dll) をリンクしているアプリケーションと 4.1 サーバーがきちんと接続できる。
version 4.1 以上の文字コード変換機能とうまくつきあうには? †
MySQL version 4.1 から、utf8 が組み込まれたり、文字コードの自動変換が組み込まれたりと、けっこう文字周りがかわりました。 4.0までの MySQL とは感覚が変わるので、一応、こうした方がトラブルは少ないね、という経験上のものを書いておきます。
- mysqldump には必ず --default-character-set= を指定すること。
- MySQL サーバーとクライアントは、必ず同じキャラクターセットにしておくこと。
- 4.1以上対応のアプリケーションには、必ず "SET NAMES キャラクターセット名" という SQL 文を、サーバーに接続した直後に実行すること。
- データベース名、テーブル名、フィールド名には、マルチバイト文字は使用しないこと。
- マルチバイトキャラクターセットと、latin1などのシングルバイトキャラクターセットを混在させないようにすること。
- キャラクターセットはデータベース単位、テーブル単位、フィールド単位で指定できるが、フィールド単位でのキャラクターセットの指定はなるべく避けた方がよいだろう
- 文字の自動変換機能を抑止する、--default-character-set=binary の使用が便利。
- 既にコンパイル済みのバイナリを使うときは、そのバイナリが作成されたときに埋め込まれている、標準のキャラクターセットを知っておいた方がよい。
- !!! MySQL AB のバイナリは latin1 が標準 !!!
- 自分でコンパイルする場合は、binary キャラクターセットを標準に指定してコンパイルすれば、アプリの変更や設定の変更無しに、MySQL 4.0,3.23 対象のアプリが動く。
- --init-connect='SET NAMES キャラクタセット名' は使わない。これはクライアントコマンドオプション --default-character-set= を無効にしてしまうから。
- 4.1 の mysqldump には --hex-blob というオプションが追加されている。これは BLOB のバイナリデータを壊さずに mysqldump 可能になる。
4.1 にupgradeしたら文字が?になります / 4.1 にしたらクエリの結果がおかしいことがある †
4.1 から文字の自動変換機能の追加、char() の仕様変更がありました。
なので、サーバーを 4.1 に upgrade すると、文字が ? になったり、文字が変になったり、クエリーの結果がおかしくなったりすることがあります。
4.1 に upgrade するならば、以下のようにします(アプリの変更をしないための方法)。
- まず、ソースから MySQL をビルドし直す。charset は binary にして。(後述、備考参照)
- ビルドしてできた libmysqlclient (windows の場合は libmysql.dll) を使用して、PHP, Perl, Ruby, などの MySQL モジュールをコンパイルし直す。
- サーバーを 4.1 にする前に、念のためバックアップを取っておく
- サーバーを 4.1 に upgrade する。
/etc/my.cnf には[mysqld-4.1] old-passwords [mysqld] default-character-set=使用するキャラクターセット名 [mysqldump] default-character-set=使用するキャラクターセット名 skip-opt [mysql] default-character-set=使用するキャラクターセット名
を書いて、4.1 の サーバー起動
- mysql_fix_privilege_tables を実行して、mysql データベースの権限テーブルを upgrade する。
Windows の場合は、mysql -f -uroot mysql < mysql_fix_privilege_tables.sql
とする
- すべてのテーブルを ALTER する。
char() の定義がおかしくなっているので、指定し直す。
Unix の場合は、MyNA の http://www.mysql.gr.jp/frame/modules/bwiki/?Contrib にあるシェルスクリプトを使ってもよい。
- また、mysql コマンド、mysqldump コマンド等は、必ず、default-character-set= を指定して使用しましょう。
character-set はサーバーと同じにしましょう。
- アプリのソースを変更して対応する方法:
クライアントプログラムのソースに、'SET NAMES ' 文を追加する方法もあります。この場合は、1,2 の手順は必須ではなくなります。
MySQL サーバーに接続した直後に、'SET NAMES クライアントのキャラクターセット名' という SQL 文を実行します。
- 備考. ソースからのビルド:
Unix なら ./configure --with-charset=binary にする。 Windows なら、
include/my_config.h , include/config-win.h の
#define MYSQL_DEFAULT_CHARSET_NAME "latin1"
を
#define MYSQL_DEFAULT_CHARSET_NAME "binary"
に。
#define MYSQL_DEFAULT_COLLATION_NAME "latin1_swedish_ci"
を
#define MYSQL_DEFAULT_COLLATION_NAME "binary"
に。
いままでの説明の概念図 †
例えば、PHP のアプリケーションの場合、次のような階層構造になります。
(等幅フォントで見てね)
+---- PHPアプリ ---------+ | 例えば PHPMyAdmin など | | | | connect() | | SET NAMES sjis; | <- SET NAMES を実行するのはこの層 +------------------------+ ↓↑ +------- PHP -------------+ | PHP エンジン | | ↓↑ | | PHP の MySQL モジュール | | mysql.so (UNIX) | | mysql.dll (Windows) | +-------------------------+ ↓↑ +----------------------------+ | libmysqlclient.so (UNIX) | +---- MySQL サーバー ------+ | libmysql.dll (Windows) | | | |標準キャラクターセット埋込 | ←→ [文字コード変換ルーチン] | <- こいつが曲者 | 例えば latin1 とする | | ↓↑ | +----------------------------+ | 内部の処理。結果を返す | SET NAMES が実行されない時 | | 埋込の標準charsetが使用される | サーバー側のcharsetは | これがとても曲者 | 例えば sjis とすると | | 「あ」は 0x82A0 | +--------------------------+ この例では、SET NAMES 文を実行しない場合、latin1 <-> sjis の組み合わせになる。 latin1 には 0x82A0 のコードがないので、「あ」は「?」に変換されてしまう。
char(10) が char(3) になるトリック 4.0 まで : 1 2 3 4 5 6 7 8 9 10 内部バイト: ■■■■■■■■■■ 4.1(ujis) : +----+-----+-----+ 1 2 3
mysql コマンドでは大丈夫なのに、PHP,perl,accessなどで文字が ? に化けるのは? †
良くある勘違いは、
「mysqlコマンドが動いているから、自分のアプリも正しくコード変換するだろう」
というものです。
これは間違いです。
上の図をじっくり見てください。
MySQL サーバーとおしゃべりしている libmysqlclient.so (libmysql.dll) に、キャラクターセットが埋め込まれています。
mysql コマンドには default-character-set のオプションがあり、キャラクターセットの指定ができます。
これは libmysqlclient.so (libmysql.dll) の埋込キャラクターセットを上書きします。
しかし、MySQL AB が提供しているコマンド(mysqldump, mysql, mysqlimport等)や MyODBC 以外の、
別の誰かが作ったアプリやコマンドは、
my.cnf を読んだり、default-character-set オプションがあったりするわけではありません。
my.cnf を読んだり、default-character-set オプションが使えたり、SET NAMES 文が実行されたりするのは、
あくまでも、アプリ側の責任、作り手の責任なのです。
上の図で言えば、PHPMyAdmin や PHP 自身の部分に、キャラクターセットの指定をする処理や my.cnf を読む処理を、作り手が意図して書かない限り、実現しないのです。
これは perl だろうが Ruby だろうが、access だろうが、PHP と同じです。
(MyODBC(Connector/ODBC)は設定をすることで、my.cnf の [odbc] グループを読みます。
access で MyODBC を使用しているなら、my.cnf を読むオプションを有効にしておきます。)
コードを書くのが嫌なら(変更することが出来ない状況なら)、libmysqlclient (libmysql,dll) の埋込キャラクターセットを変えるのです。
これは libmysqlclient(libmysql.dll)のコンパイルのし直しを意味します。
クライアントとサーバーのキャラクターセットの確認 †
クライアントのキャラクターセットが binary
サーバーのキャラクターセットが ujis
の場合、以下のように表示される。
mysql> SHOW VARIABLES LIKE 'char%'; +--------------------------+----------------------------+ | Variable_name | Value | +--------------------------+----------------------------+ | character_set_client | binary | | character_set_connection | binary | | character_set_database | ujis | | character_set_results | binary | | character_set_server | ujis | | character_set_system | utf8 | | character_sets_dir | /usr/share/mysql/charsets/ | +--------------------------+----------------------------+ 7 rows in set (0.00 sec)
サーバーとクライアントのキャラクターセットが同じ場合は、
文字の自動変換は起きず、
文字化けは発生しない。
| character_set_client | ujis | | character_set_connection | ujis | | character_set_database | ujis | | character_set_results | ujis | | character_set_server | ujis |
クライアントが binary の場合は、文字の自動変換は起きない。
文字化けは発生しない。
しかし、クライアントの SQL 文のエスケープに注意すること。
| character_set_client | binary | | character_set_connection | binary | | character_set_database | ujis | | character_set_results | binary | | character_set_server | ujis |
クライアントが latin1 で、
サーバーが日本語の場合は、
確実に文字が壊れる。
| character_set_client | latin1 | | character_set_connection | latin1 | | character_set_database | ujis | | character_set_results | latin1 | | character_set_server | ujis |
クライアントとサーバーがマルチバイトキャラクターセットだが、
違うキャラクターセットの場合、
幾つかの文字は破壊されるかもしれない。
| character_set_client | utf8 | | character_set_connection | utf8 | | character_set_database | ujis | | character_set_results | utf8 | | character_set_server | ujis |
4.1以上の日本語に関する問題点まとめ †
- 配布されているバイナリがlatin1であり、文字破壊が起きてしまうこと。
- コードのマッピングの問題
- euc,sjis,utf8間の、コードと文字グリフィスのマッピングが食い違うこと。
- MS-Winのコードマッピングは 5.0.3 から対応
- http://www.mysql.gr.jp/frame/modules/bwiki/?Contrib に4.1用のcp932,eucjpmsのパッチあり
- euc<->sjis の変換の時、一度utf8を通ること
- 自動変換を止めるオプションがないこと
- 自動変換を止めるにはクライアントをbinaryにするか、サーバーと同じcharsetにするしかない。
それだけでは全ての場合に対応できない。
昔のアプリやlatin1のバイナリを使っていても文字破壊や誤変換を防ぐ方法がないと、
導入や移行の障害となる- http://www.mysql.gr.jp/frame/modules/bwiki/?Contrib にとりあえずのパッチあり
- 自動変換を止めるにはクライアントをbinaryにするか、サーバーと同じcharsetにするしかない。
- 全てのバイト列がINSERTできない
- 全部のバイト列を通して欲しいが、そうはなっていない
- 文字破壊の原因解明が大変
- PHPMyAdmin でたとえるなら、PHPMyAdminの層、PHPの層、MySQLクライアントライブラリの層、MySQLサーバーの層、というように、階層が多すぎて、原因の特定に時間がかかる。
結局、どうしろと? †
- MySQL-4.0, 3.X を現在運用しているひとは:
原則、今のままキープですね。
サーバーを上げるといくつか問題に遭遇します。
充分な検証の結果、解決の目処がたってから、サーバーをバージョンアップしましょう。
- これから新しく導入する人は:
はじめから 4.1 以上でも OK。
- ただし、4.0までのアプリの資産を流用したい場合は、old-passwords や default-character-set 、SET NAMES 文に注意しましょう。
- これから作るアプリには必ず 「SET NAMES キャラクターセット名」 を接続直後に実行しましょう。
- サーバーとクライアントのキャラクターセットは同じにする。
- 4.1以上にバージョンアップするときに
- アプリの変更をしたくない人は:
- MySQL サーバー、クライアント、libmysqlclient (libmysql.dll) を使用する全ての クライアントをコンパイルし直す。
- アプリの変更をしてもかまわない人は:
- アプリのソースに、「SET NAMES クライアントのキャラクターセット名」 SQL 文を追加する。追加する位置は、MySQL サーバーに接続直後にする。
- old-passwords を指定しておく
- アプリの変更をしたくない人は:
MySQL連携 †
エスケープ †
クエリに与える文字列はエスケープしますが、基本的に MySQL 側が用意しているエスケープ関数を使うべきです。
キャラクターセットに従ってエスケープしてくれるからです。
SQLインジェクション対策のためにもエスケープは必要です。
C †
エスケープ †
- mysql_escape_string()
- mysql_real_escape_string()
を使う
my.cnf を読む †
mysql_options(&mysql, MYSQL_READ_DEFAULT_FILE, "/etc/my.cnf"); mysql_options(&mysql, MYSQL_READ_DEFAULT_GROUP, "groupname");
PHP †
エスケープ †
- mysql_escape_string()
- mysql_real_escape_string()
を使う
my.cnf を読む †
PHP version 4 の場合
読めない。[client] に書いても無駄。
http://www.mysql.gr.jp/frame/modules/bwiki/?Contrib
のパッチを当てる。
PHP version 5の場合
mysqli モジュールに、my.cnf を読む関数が用意されている。
mysqli_options(connection, MYSQLI_READ_DEFAULT_FILE, "/etc/my.cnf"); mysqli_options(connection, MYSQLI_READ_DEFAULT_GROUP, "php");
NULL の扱い †
- DBのデータが NULL の場合、PHP は "" を受け取る。NULL と空文字の区別が出来ない。
Ruby †
エスケープ †
escape_string() メソッドを使う
my.cnf を読む †
my.options(Mysql::READ_DEFAULT_FILE, "/etc/my.cnf") my.options(Mysql::READ_DEFAULT_GROUP, "ruby")
NULL の扱い †
- DBのデータが NULL の場合、Ruby は nil を受け取る。空文字ではない
Perl †
エスケープ †
DBI の quote() メソッドを使う。
my.cnf を読む †
$dsn = "DBI:mysql:test;mysql_read_default_group=perl;mysql_read_default_file=/etc/my.cnf";
MySQLインターナル †
SMP, 64bit対応ですか? †
最初っから。
SMP は CPU を増やすだけで OK。特別な設定や作り直しは不要です。
追記型ですか? †
いいえ
vacuumありますか? †
いいえ。
かわりに
MyISAM の場合は、OPTIMIZE TABLE 文か、REPAIR TABLE 文をします。
InnoDB の場合は、ALTER TABLE () TYPE=InnoDB を実行します。
たまにやればいいでしょう
トランザクション分離レベル †
InnoDB | BDB | NDB | |
READ UNCOMMITTED | ○ | - | - |
READ COMMITTED | ○ | ◎ | ◎ |
REPEATABLE READ | ◎ | - | - |
SERIALIZABLE | ○ | - | - |
InnoDB の標準は REPEATABLE READ。
InnoDBの REPEATABLE READは、phantom read は起きない実装。
ロック †
InnoDB | 行レベルロック |
NDB | 行レベルロック |
BDB | ページレベルロック |
MyISAM | テーブルレベルのロック |
- InnoDB、NDB の場合
- 必ず テーブルに primary key を作ります。
- LOCK TABLES は使わないように。
- 明示的にロックしたい場合は、InnoDB では、SELECT .... FOR UPDATE、 SELECT ..... LOCK IN SHARE MODE を使う。
- NDB の SELECT .... LOCK IN SHARE MODE、SELECT .... FOR UPDATE は将来対応予定
マルチバージョニング †
InnoDB は マルチバージョニング を実装しています
レプリケーション †
テーブル型(ストレージエンジン) †
- どのストレージエンジンでもレプリケーション可能
- master と slave のテーブルの型が違っても動く
埋込MySQLサーバー †
MySQLサーバーはライブラリ化されています。
./configure --with-embedded-server
libmysqld.a (libmysqld.dll) がそれです。
このライブラリに埋め込まれているのは
- SQL エンジン
- 各種ストレージエンジン
です。
埋め込まれていないのは
- 認証
- ネットワークからの接続管理
最大のフィールド数、レコード長、等 †
MyISAM | InnoDB | |
最大のフィールド数 | 4096 | 1000 |
実際はフィールドの長さ制限に左右されて少なくなる | ||
最大のレコード長 | BLOB,TEXTを除いて65535バイト | BLOB,TEXTを除いて8KB。 |
BLOB,TEXTを含んだレコードは4GBまで | ||
最大のキーの長さ | 1000バイト | 1024バイト |
4.1.2より前は500バイト | (InnoDB内部は3500だが、MySQL上位層の制限による) |
SELECT COUNT(*) †
1テーブルの WHERE 無しの SELECT COUNT(*) は、
- MyISAM の場合はテーブル情報(レコード数が書かれている)からレコード数を直接読み込みます。
- InnoDB の場合はインデックスツリーをその都度調べます。
なので、SELECT COUNT(*) の計測結果を取って両者を比較するというのは、
前提条件の違う物を比較しているので、
その結果からの考察を全くうのみにすることはできません。
InnoDB †
クラスタードインデックスとレコードについての誤った見解 †
「新しいレコードをインサートするたびに、全てのレコードをキー順になるように、全てのレコードを並び換えてディスク上に保存している。」
これは誤りです。
キー順にレコードが追えればいいわけで、
それは別に物理的な(ディスク上の)順序がキー順というわけではなく、
レコードを指している物をキー順に追えればいい実装になっています。
レコードへのポインターを操作しているにすぎません。
auto_increment †
InnoDB の場合、AUTO_INCREMENT の取るべき値は、メモリー上にあります。
mysqld 起動時に、最大の値がチェックされて、メモリーに保存されます。
(MyISAM の場合は、ファイルに書かれています。)
MySQL開発 †
aclocal 手順 †
aclocal autoheader libtoolize --automake --force automake autoconf cd innobase aclocal autoheader libtoolize --automake --force automake autoconf
libtoolize --force を実行しないと libmysqlclient.so.14 じゃなくて libmysqlclient.14 になってしまう環境がある。
bitkeeper で取る †
初めて取得するとき
bk clone bk://mysql.bkbits.net/mysql-5.0 mysql-5.0
更新するとき
bk pull
コンパイラー †
- 使用禁止
gcc-2.96, egcs-1, gcc-2.8
MySQL ドキュメント †
種類 †
manual.texi | リファレンスマニュアル |
include.texi | リファレンスマニュアルと internals.texi が include。定数定義 |
reservedwords.texi | リファレンスマニュアルが include。SQL予約語一覧 |
is.texi | INFORMATION_SCHEMA マニュアル |
internals.texi | 内部構造マニュアル |
manual.cluster.texi | クラスター |
bitkeeper †
初めて取得するとき
bk clone bk://mysql.bkbits.net/mysqldoc mysqldoc
更新するとき
bk pull
texi の加工 †
- texi ファイル -[texi2html]-> HTML ファイル
- texi ファイル -[texi2dvi]-> dvi ファイル -[dvi2ps]-> PS ファイル -[ps2pdf]-> PDF ファイル
- texi ファイル -[texi2db]-> DocBook形式ファイル
- manual.texi -> HTML への変換の場合
- manual.html ファイルができる。
- manual.texi , include.texi , reservedwords.texi を同じディレクトリに置く。
- texi ファイルのあるディレクトリで、
texi2html -Verbose -nomenu manual.texi
とすると、manual.html が出来る。
これは 1ファイル。
もし、章ごとにファイルを分割したい場合はtexi2html -nomenu -split=chapter manual.texi
- texi2html はバージョンによってオプションが違うので注意。
- manual.texi -> dvi への変換の場合
- manual.dvi ファイルが出来る
- manual.texi と、texinfo.tex ファイル (TeX用の、スタイル定義ファイル) を同じディレクトリに置く。
- texinfo.tex ファイルは、ネット上を探す
- texi ファイルのあるディレクトリで、
texi2dvi manual.texi
とすると manual.dvi ができる
- texi2html は perl スクリプト。日本の書き方やマルチバイトの事を考えていないので、頑張って修正しましょう。
- texinfo.tex も日本語を考慮していないので、がんばって修正する。
その他 †
ライセンスはどうなっていますか?商用利用ではどうすべきですか? †
MySQL のライセンスは単純です。 GPL か コマーシャルライセンスか。
GPL では具合が悪い、GPL では条件に合わない、GPL に納得できない場合に、コマーシャルライセンスを購入すればOK。
それは商用利用するかどうかには関係がありません。
GPL については http://www.gnu.org/home.ja.html をご覧ください。
2000年6月に、「GPLかコマーシャルライセンスか」への移行がありましたが、それ以前のライセンス(FPL)は 別物でした。
前のライセンス条項(FPL)は現在は適用されていません(無くなっています)。
古い情報で判断しないほうがお得です。
バグ報告、質問をする場合 †
心得
- 以下の情報を 必ず 含めよ
- mysqlbug の出力内容
- MS-Win の場合は、mysqlbug が実行できないので、mysqld --version の結果、OS のバージョンを含める
- my.cnf の内容
- テーブルの構造
- 問題となるデータ, SQL 文
- 得られる結果、エラーメッセージ、.err ファイルの出力
- .err ファイルは、MS-Win の場合は、data の下の mysql.err ファイルもしくは、「コンピュータ名」.errになっていることがある
- なにを、どうした時に、なにが起きるか、を書く
- mysqlbug の出力内容
- エラーメッセージをそのままコピーせよ
- 質問する前に、エラーメッセージを読め!
読み方 †
MySQL | まいえすきゅーえる、みーえすきゅーえる(^^;;; |
My | みー (ムーミンのミー) |
InnoDB | いのでーびー |
AB | あーべー |
Oy | おい |
GmbH | げーえむべーはー |