PHPとコマンドラインでクエリを実行すると、順序が異なる結果が得られるという問題が発生しています。私の調査によると、エンコードが不適切な場合、次の問題が発生する可能性があります。結果の順序。
そうは言っても、私のDBテーブルはすべてutf8mb4
としてエンコードされ、照合順序はutf8mb4_general_ci
です。ただし、mysql変数が正しく設定されていないようです。
私はMysql5.5.5-10.1.26-MariaDbを使用しています。
これが私のCNF設定ですが、正直なところ、ここで何をしているのかわかりません。
[client]
default-character-set=utf8mb4
[mysql]
default-character-set=utf8mb4
[mariadb]
[mysqld]
character-set-server=utf8mb4
character_set_client=utf8mb4
collation-server=utf8mb4_general_ci
Mysqlから出力される変数:
character_set_client utf8
character_set_connection utf8
character_set_database utf8mb4
character_set_filesystem binary
character_set_results utf8
character_set_server utf8mb4
character_set_system utf8
collation_connection utf8_general_ci
collation_database utf8mb4_unicode_ci
collation_server utf8mb4_general_ci
更新:ある人が私がデータベースに接続する方法を尋ねてきました:
$this->connection = new PDO('mysql:Host='.DB_SERVER.';dbname='.DB_NAME.';port='.DB_PORT, DB_USER, DB_PASS, $options);
更新:utf8mb4_unicode_ci
に切り替えました(以下の回答の提案に従って)。
より正確であるため、おそらくutf8mb4_general_ciの代わりにutf8mb4_unicode_ciを使用する必要があります。古い/制限されたCPUを搭載したシステムでMariaDBを実行していて、パフォーマンスが大きな懸念事項でない限り。
そうは言っても、解決策は、MariaDB構成(またはコマンドラインでinit_connect
)に --init-connect
を設定することです。
init_connect = "SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci"
どちらの方法でも問題ありません。私は一方を他方よりも推奨していません。どちらも等しく有効なアプローチです。
MariaDB構成は、my.cnfまたはmy.cnfに含まれるファイル(通常は/ etc/mysqlの下にあります)にある可能性があります。詳細については、システムのドキュメントを確認してください。上記にリンクされているMariaDBのドキュメントに示されているように、サーバー変数を構成しているため、構成ファイルのサーバー部分で変数を設定する必要があります。構成ファイルのサーバー部分は、INI "d"で終わるセクション名で示されます。INIセクションは、角括弧で囲まれたキーワードで示されます。例:「[section]」。「d」は「daemon」を表し、サーバープロセスの標準的なUNIXの命名法です。変数は[mysqld]
セクションまたは[mariadb]
セクションのいずれかで設定できます。 。init_connect
サーバー変数はMySQLとMariaDBの両方に共通であるため、[mysqld]
の下に配置することをお勧めします。
貼り付けた構成でcharacter_set_client=utf8mb4
を設定しているようです。これを行う必要はありません。行を削除またはコメントアウトできます。コメントは、ポンド記号(#
)で始まる行であり、ハッシュマーク、オクトソープ、または番号記号とも呼ばれます。
サーバーに接続するすべてのクライアントは、他のコマンドが処理される前にこれらのコマンドを実行します。
character-set-client-handshake = FALSEも必要です。
/etc/my.cnf.d/character-set.cnf
# https://scottlinux.com/2017/03/04/mysql-mariadb-set-character-set-and-collation-to-utf8/
# https://mariadb.com/kb/en/library/setting-character-sets-and-collations/
# https://medium.com/@adamhooper/in-mysql-never-use-utf8-use-utf8mb4-11761243e434
# https://stackoverflow.com/questions/47566730/force-mariadb-clients-to-use-utf8mb4
[client]
default-character-set = utf8mb4
[mysql]
default-character-set = utf8mb4
[mysqld]
character-set-client-handshake = FALSE
collation-server = utf8mb4_unicode_ci
init-connect = 'SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci'
character-set-server = utf8mb4
私はすべてをutf8mb4にする1
MariaDB [(none)]> show variables like 'char%'; show variables like 'collation%';
+--------------------------+----------------------------+
| Variable_name | Value |
+--------------------------+----------------------------+
| character_set_client | utf8mb4 |
| character_set_connection | utf8mb4 |
| character_set_database | utf8mb4 |
| character_set_filesystem | binary |
| character_set_results | utf8mb4 |
| character_set_server | utf8mb4 |
| character_set_system | utf8 |
| character_sets_dir | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.00 sec)
+----------------------+--------------------+
| Variable_name | Value |
+----------------------+--------------------+
| collation_connection | utf8mb4_unicode_ci |
| collation_database | utf8mb4_unicode_ci |
| collation_server | utf8mb4_unicode_ci |
+----------------------+--------------------+
3 rows in set (0.00 sec)
MariaDB [(none)]>
ただし、character-set-client-handshake行がなくても、一部はutf8のままです。
MariaDB [(none)]> show variables like 'char%'; show variables like 'collation%';
+--------------------------+----------------------------+
| Variable_name | Value |
+--------------------------+----------------------------+
| character_set_client | utf8 |
| character_set_connection | utf8 |
| character_set_database | utf8mb4 |
| character_set_filesystem | binary |
| character_set_results | utf8 |
| character_set_server | utf8mb4 |
| character_set_system | utf8 |
| character_sets_dir | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.00 sec)
+----------------------+--------------------+
| Variable_name | Value |
+----------------------+--------------------+
| collation_connection | utf8_general_ci |
| collation_database | utf8mb4_unicode_ci |
| collation_server | utf8mb4_unicode_ci |
+----------------------+--------------------+
3 rows in set (0.01 sec)
MariaDB [(none)]>
1 character_set_systemは 常にutf8 です。
init_connect
は、root
として接続しているユーザーによって実行されないため、必要なほど普遍的ではありません。
SET NAMES utf8mb4
は3つのことを設定します。それを見るために実験してください。 3つすべてが必要です。
5.5までさかのぼらない場合は、より良い照合順序としてutf8mb4_unicode_520_ci
をお勧めします。「Unicode照合順序名には、照合順序が適用されるUnicode照合アルゴリズム(UCA)のバージョンを示すバージョン番号が含まれる場合があります。このように作成された最初の照合は、バージョンUCA 5.2.0を使用します。たとえば、utf8_unicode_520_ciはUCA 5.2.0に基づいています。バージョン番号を含まないUCAベースのUnicode照合名は、バージョン4.0.0に基づいています。」
バージョン8.0にはUnicode9.0標準があります。
質問に戻る:完璧な解決策はありません。ユーザーは、無知または悪意によって、あなたが行うことをすべて無効にすることができます。
あなたcould作成されたテーブルを監視しますが、それでもテーブルが正しく接続されないようにすることはできません。または正しく、ただし別の文字セットを使用します。 validSET NAMES latin1
を実行してから、latin1-encodeバイトを提供します。 MySQLは、保存/フェッチ時に変換します。
ただし、utf8でエンコードされたバイトがあり、SET NAMES latin1
と言うと、「ダブルエンコード」になります。この「バグ」は、正しく照合する可能性をすべて破壊しますが、それ以外の場合は(通常は)透過的です。つまり、保存時に混乱し、フェッチされると混乱しなくなります。
この警告を修正するには、編集する必要があります
/etc/my.cnf (my.ini on Windows)
ファイルに追加/設定するだけです
[client]
default-character-set=utf8mb4
[mysql]
default-character-set=utf8mb4
[mysqld]
collation-server=utf8mb4_unicode_ci
init-connect='SET NAMES utf8mb4'
character-set-server=utf8mb4