web-dev-qa-db-ja.com

MariaDBクライアントにutf8mb4の使用を強制する

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に切り替えました(以下の回答の提案に従って)。

5
stwhite

より正確であるため、おそらく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を設定しているようです。これを行う必要はありません。行を削除またはコメントアウトできます。コメントは、ポンド記号(#)で始まる行であり、ハッシュマーク、オクトソープ、または番号記号とも呼ばれます。

サーバーに接続するすべてのクライアントは、他のコマンドが処理される前にこれらのコマンドを実行します。

1
mwp

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 です。

5
hlovdal

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と言うと、「ダブルエンコード」になります。この「バグ」は、正しく照合する可能性をすべて破壊しますが、それ以外の場合は(通常は)透過的です。つまり、保存時に混乱し、フェッチされると混乱しなくなります。

2
Rick James

この警告を修正するには、編集する必要があります

/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