トップ 差分 一覧 ソース 検索 ヘルプ RSS ログイン

2007/04/23-01、skip-character-set-client-handshake について

[カテゴリ:etch]
[カテゴリ:all]
[カテゴリ:mysql]

*****************************
2010/01/29
google で skip-character-set-client-handshake を検索すると、
いつの間にか、このページが1番目に表示されるようになりました。
正確性に欠けるかもしれないがもう少し書いておきます。
文字化けを解決するのに、
skip-character-set-client-handshake や SET NAMES を
使うのは、もはや正解ではありません。
このページの情報は、時系列に追記しているので、ページ上部の情報は正しくありません。最後まで読むことをお勧めします。
*****************************

目次

skip-character-set-client-handshake について

4.1.15以降、5.0.13以降で追加された skip-character-set-client-handshake について

サーバ側で・・・
my.cnf

[mysqld]
default-character-set=utf8
skip-character-set-client-handshake

なんてしておくと、
クライアント側が接続したときに、*デフォルト*のキャラクタセットが
utf8 になるってことらしい。
(クライアントで接続毎に「SET NAMES utf8」を行わなくてもよいということ)

PHPからMySQL4.1とか5.0とか5.1とかに接続すると文字化けする : ::yossy.blog:::

MySQL の文字コードについて。 基本的に UTF-8 のエンコードで利用しているサーバに EUC-JP のデータベースを作成し、データをインポートしたいのですが、EUC-JP ではなく .. - 人力検索はてな:

サーバ、クライアント共にutf8で統一しているなら上記の設定でもいいけど、
データベース毎にキャラクタセットが違う場合は、やはり真面目に「SET NAMES ***」を行うのが正解

(2009/09/20追記)SET NAMES はセキュリティ上問題あるという話

MySQL、スクリプト言語から SET NAMES はセキュリティに問題あり - goungoun技術系雑記帳

(2010/01/29追記)skip-character-set-client-handshake、SET NAMES は使わない方がいいよ。

skip-character-set-client-handshake、SET NAMES で文字化けなどの問題を解決してしまうと、SQLインジェクションの脆弱性を生じます。

これらのオプションやコマンドは、文字コードの設定を*無理やり*変えてしまうので、問題の表層だけ解決しまう可能性があります。

文字化け(??になったり、無用な¥が挿入されたり)、SQLインジェクション、がなぜ発生するかというと「サーバ/データベース/クライアント」の文字コードの設定が一致していないからです。

シンプルに解決するには、これらを完全に一致させればよいわけです。

サーバ設定

/etc/my.cnf や c:\winnt\my.ini など

[mysqld]
default-character-set=utf8

もちろん skip-character-set-client-handshake は不要です。

データベース作成

必ず character set を指定します。

create databaase <dbname> default character set utf8; 

クライアント設定

クライアントの文字コードを SET NAMES コマンドで設定してはいけません。

使用するクライアントの種類により設定方法は異なりますが、
クライアントの設定ファイル(my.cnf)で指定します。

[client]
default-character-set=utf8

サーバマシンの設定ファイルに [client] と書いてもだめです。
クライアントマシンの設定ファイルに書いてください。
(サーバ、クライアントが物理的に1つのマシンに同居している場合は、設定ファイルが1つで済むこともありますが、ネットワーク経由で接続するなら、全てのマシン上に設定ファイルが必要です)

MyODBCの文字化け

mysql:13924
http://www.mysql.gr.jp/mysqlml/mysql/msg/13924

<設定手順>
1)データベース cp932_japanese_ci で作る。
2)適当にテーブルも作っておく。
3)c:\winnt\my.cnf
----------------
[client]
default-character-set=cp932
----------------
4)DSN作る。
  Connect Options->Initial Statement は空
  Advanced->Flags1->Don't Optimize Column Width をチェック
  Advanced->Flags1->Return Matching Rows をチェック
  Advanced->Flags3->Read Options From my.cnf をチェック
5)Accessで新規DBを作り、
  ファイル->外部データの取り込み→テーブルのリンク
  から、4)で作ったDSNを参照

mysql:15175
http://www.mysql.gr.jp/mysqlml/mysql/msg/15175

2、3年前の情報なので、今現在は状況が変わっているかもしれませんが、
cp932, sjis を使うのは難しいです。
文字化けといっても「?」になるだけでなく、insertすると
余分な「\」が付くトラブルもありました。

2010/01/31追記
MyODBC5.1 から SET NAMES は使えなくなったみたい。
データベース操作におけるエンコード

CONNECTION.Execute "SET NAMES SJIS"
※CONNECTIONはADODBのCONNECTIONオブジェクト
を実行したところ、
[MySQL][ODBC 5.1 Driver][mysqld-5.0.22]SET NAMES not allowed by driver
とのエラーが発生します。利用しているODBCドライバでは「SET NAMES」 を利用できないようです。

PHP+mysql

DBに接続して、クエリーとして SET NAMES(SET CLIENT_ENCODING等も) は禁止です。

my.cnfに設定したいところですが、PHPからはこれを見てくれません。
ではどうするかというと、mysql_set_charset()を使うのが正解です。

ところが、この関数が実装されたのはPHP5.2.3からなので、これより古いPHPを使っている場合、完全にこの問題を解決するのは困難です。

MySQL、スクリプト言語から SET NAMES はセキュリティに問題あり - goungoun技術系雑記帳

2010/02/10追記

PHP5からは mysqli_options() で my.cnf を読めるそうです。

MySQL 4.1 以降に発生する文字化け問題 - まとめ - Shoulder.jp

PHP version 5の場合
mysqli モジュールに、my.cnf を読む関数が用意されている。
mysqli_options(connection, MYSQLI_READ_DEFAULT_FILE, "/etc/my.cnf");
mysqli_options(connection, MYSQLI_READ_DEFAULT_GROUP, "php");

参考

へぼへぼCTO日記 - mysqlでskip-character-set-client-handshakeはもう使わないほうがいいと思われ
http://www.geminium.com/chiba_blog/2009/08/27/291/

(2010/01/29追記)マニュアルから抜粋

--character-set-client-handshake オプション

MySQL :: MySQL 5.1 リファレンスマニュアル :: 4.2.2 コマンド オプション
http://dev.mysql.com/doc/refman/5.1/ja/server-options.html

--character-set-client-handshake
  クライアント送信のキャラクタ セット情報を無視しない (ようにする) オプション。
  クライアント情報を無視して、サーバのデフォルトのキャラクタ セットを使用するには、
  --skip-character-set-client-handshake を使用する (MySQL が MySQL 4.0. のように
  動作するようにする。) 

SET NAMES, SET CHARACTER SET コマンド

MySQL :: MySQL 5.1 リファレンスマニュアル :: 9.4 接続のキャラクタセットおよび照合順序
http://dev.mysql.com/doc/refman/5.1/ja/charset-connection.html

SET NAMES 'x'ステートメントは下記の3ステートメントと等価です。
  SET character_set_client = x;
  SET character_set_results = x;
  SET character_set_connection = x;

 character_set_connectionをxにセットするとcollation_connectionも xのデフォルト
 照合順序にセットされます。その照合順序を正確にセットする必要はありません。
SET CHARACTER SET xステートメントは下記の3ステートメントと等価です。
  SET character_set_client = x;
  SET character_set_results = x;
  SET collation_connection = @@collation_database;

  collation_connectionを指定するとcharacter_set_connectionも照合順序に関係する
  キャラクタセットに指定されます (SET character_set_connection = @@character_set_database
  を実行することと同様)。character_set_connectionを正確に指定する必要はありません。 

character_set_*, collation_* 確認例

# mysql -u root -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1679
Server version: 5.0.51a-24+lenny2 (Debian)

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql>

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| test               |
| test_cp932         |
+--------------------+
4 rows in set (0.00 sec)

mysql> SHOW VARIABLES LIKE 'char%';
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | latin1                     |
| character_set_connection | latin1                     |
| character_set_database   | utf8                       |
| character_set_filesystem | binary                     |
| character_set_results    | latin1                     |
| character_set_server     | utf8                       |
| character_set_system     | utf8                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.00 sec)

mysql> SHOW VARIABLES LIKE 'coll%';
+----------------------+-------------------+
| Variable_name        | Value             |
+----------------------+-------------------+
| collation_connection | latin1_swedish_ci |
| collation_database   | utf8_general_ci   |
| collation_server     | utf8_general_ci   |
+----------------------+-------------------+
3 rows in set (0.00 sec)

mysql> use test_cp932;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql>

mysql> SHOW VARIABLES LIKE 'char%';
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | latin1                     |
| character_set_connection | latin1                     |
| character_set_database   | cp932                      |
| character_set_filesystem | binary                     |
| character_set_results    | latin1                     |
| character_set_server     | utf8                       |
| character_set_system     | utf8                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.00 sec)

mysql> SHOW VARIABLES LIKE 'coll%';
+----------------------+-------------------+
| Variable_name        | Value             |
+----------------------+-------------------+
| collation_connection | latin1_swedish_ci |
| collation_database   | cp932_japanese_ci |
| collation_server     | utf8_general_ci   |
+----------------------+-------------------+
3 rows in set (0.00 sec)

mysql>