MySQL に絵文字表現を挿入できない問題の解決方法

MySQL に絵文字表現を挿入できない問題の解決方法

序文

最近この問題に遭遇するまで、私は UTF-8 が文字セットの問題に対する普遍的な解決策だと考えていました。最近、Sina Weibo のクローラーに取り組んでいました。データを保存するときに、絵文字表現を維持している限り、次の例外がスローされることに気付きました。

不正な文字列値: '\xF0\x90\x8D\x83\xF0\x90...'

ご存知のとおり、UTF-8 は 3 バイトで、日常生活で目にするほとんどのフォントが含まれています。しかし、3 バイトではすべてのテキストを収容するには十分ではないため、utf8mb4 が作成されました。utf8mb4 は utf8 のスーパーセットで、4 バイトを占め、utf8 と下位互換性があります。日常生活で使用する絵文字表現は 4 バイトです。

したがって、ここで utf8 テーブルにデータを挿入すると、 Incorrect string valueエラーが報告されます。

簡単に Google 検索すると解決策が見つかりました。具体的な解決策は次のとおりです。

1. データテーブルの文字セットをutf8mb4に変更する

これは非常に簡単です。オンラインで多くの変更ステートメントを見つけることができます。ただし、テーブルを再構築し、 mysqldump -uusername -ppassword database_name table_name > table.sqlを使用して対応するデータテーブルをバックアップし、テーブル作成ステートメントの文字セットを utf8mb4 に変更することをお勧めします。次に、 mysql -uusername -ppassword database_name < table.sql sql を再インポートし、文字セットの変更操作を完了します。

2. MySQLデータベースのバージョンは5.5.3以上である必要があります

インターネット上のすべての記事では、MySQL 5.5.3 以降のみが utf8mb4 をサポートしていると述べられています。ただし、私が使用したデータベースのバージョンは 5.5.18 で、最終的には問題を解決できました。したがって、急いでメンテナンス担当者にデータベースのアップグレードを依頼しないでください。まずは自分で問題を解決するようにしてください。

3. データベース設定ファイル /etc/my.cnf を変更し、mysql サービスを再起動します。

主な目的は、データベースのデフォルトの文字セット、および接続とクエリの文字セットを変更することです。[MySQL は絵文字をサポートし、エンコードを UTF8MB4 にアップグレードします][1] この記事には詳細な設定方法があり、[MySQL の詳細な文字セット設定][2] この記事には各文字セットセットの機能があります。自分で読んでみてください。

4. MySQLコネクタを5.1.21以上にアップグレードする

上記のすべての操作の中で最も重要なのは、ステップ3のデータベース構成ファイルの変更です。これにより、おそらく

[クライアント]
# クライアントソースデータのデフォルトの文字セット default-character-set = utf8mb4
[mysqld]
# サーバーのデフォルトの文字セットは、character-set-server=utf8mb4 です
# 接続層のデフォルト文字セット collat​​ion-server=utf8mb4_unicode_ci
[mysql]
# データベースのデフォルト文字セット default-character-set = utf8mb4

これらの構成は、データがクライアントからサーバーに渡されるパイプラインで使用される文字セットを指定します。これらのパイプラインのいずれかに問題があると、挿入が失敗したり、文字化けしたりする可能性があります。

しかし、多くの場合、オンラインデータベースはデータベースファイルを自由に変更できないため、運用保守の同僚はデータベース構成ファイルの変更要求を断固として拒否しました (T_T)

したがって、唯一の解決策はコードを使用することです。最初は、JDBC に接続するときに指定された文字セットから始めるつもりでした。

jdbc:mysql://localhost:3306/ding?characterEncoding=UTF-8

主に、Java スタイルの文字セット文字列を UTF-8 から utf8mb4 に変更すると、問題は解決するはずですよね?

残念ながら、Java JDBC には utf8mb4 に対応する文字セットがありません。UTF-8 を使用する場合は、urf8mb4 と互換性があり、文字セットが自動的に変換されます。

たとえば、Connector/J で 4 バイトの UTF-8 文字セットを使用するには、MySQL サーバーを character_set_server=utf8mb4 で構成し、Connector/J 接続文字列から characterEncoding を除外します。Connector/J は UTF-8 設定を自動検出します。 – [MySQL: 文字セットと Unicode の使用][3]

その後、各クエリ要求で使用する文字セットを明示的に指定できることを知りました。 set names utf8mb4を使用すると、この接続の文字セットを utf8mb4 として指定できますが、この設定は各接続が解放されると無効になります。

現在の解決策は、utf8mb4 を挿入する必要があるときに、次のようにset names utf8mb4明示的に呼び出して実行することです。

jdbcTemplate.execute("名前をutf8mb4に設定");
jdbcTemplate.execute("...");

ORM フレームワークを使用する場合、フレームワークはパフォーマンスの最適化のためにコミットを遅らせることに注意してください。トランザクションが終了するか、ユーザーが強制コミットを積極的に呼び出しない限り、実行を担当するset names utf8mb4有効になりません。

ここではMessageDaoを例にmyBatisを使用します。

// メッセージDao
パブリックインターフェースMessageDao {
 @Update("名前をutf8mb4に設定")
 パブリック void setCharsetToUtf8mb4();
 @Insert("tb_message に挿入......")
 public void insert(メッセージ msg);
}
// テストコード
SqlSession sqlSession = sqlSessioFactory.openSession();
messageDao = sqlSession.getMapper(MessageDao.class);
メッセージDao.setCharsetToUtf8mb4();
// 強制コミット sqlSession.commit();
messageDao.insert(メッセージ);

今のところ、問題は解決しました。

ああ、物事がこんなにスムーズに進むならいいのですが。プロジェクトでは、mybatis インスタンスは Spring によって管理されているため、sqlSession を取得できず、強制コミットできません。また、Spring トランザクション フレームワークの制限により、ユーザーは強制コミットを明示的に呼び出すことができません。私はまだこの問題に苦労しています。

解決策は2つあります。

  • AOP を使用すると、4 バイトの UTF8 文字が挿入される可能性がある場合、フロント メソッドはset names utf8mb4を実行しますが、このソリューションでは、AOP メソッドが Spring トランザクションによって管理されるかどうか、およびフロント メソッドで取得された接続が後で取得される接続オブジェクトと同じセッションであるかどうかを判断できません。
  • Spring JDBC の作成方法を調べ、新しいデータベース接続が作成されるたびにset names utf8mb4を実行するフックを記述して、すべての接続に文字セットが設定されていることを確認します。

要約する

以上がこの記事の全内容です。時間があるときに、上記 2 つの解決策を試してみたいと思います。この記事の内容が皆さんの勉強や仕事に少しでもお役に立てれば幸いです。ご質問があれば、メッセージを残してご連絡ください。123WORDPRESS.COM をご愛顧いただき、ありがとうございます。

以下もご興味があるかもしれません:
  • MySQLに絵文字表現を保存する詳細な手順
  • MySQL で絵文字表現を挿入できない理由と解決策
  • MySQL が絵文字表現を保存できない問題の解決策の分析
  • MySQL の絵文字テーブル ストレージのエラーに対処する方法 [エンコードを utf8mb4 に変更]
  • MySQL が絵文字表現を保存できない問題の解決策の分析
  • Java バックエンド MySQL データベースを有効にして絵文字表現をサポートする方法
  • 絵文字を保存するための MySQL の設定方法に関するチュートリアル
  • MySQLに絵文字表現を挿入する方法

<<:  JavaScript Reduceの詳しい説明

>>:  Linux オペレーティング システムで ssh/sftp を構成して権限を設定する方法

推薦する

MySQLシリーズ マルチテーブル結合クエリ92および99構文例詳細チュートリアル

目次1. デカルト積現象2. 接続クエリの知識ポイントのまとめ1) 結合クエリとは何ですか? 2) ...

Docker で Jenkins-2.249.3-1.1 をインストールする詳細な手順

目次1. Dockerをインストールする2. Jenkinsイメージファイルを取得する3. マウント...

プライベートウェアハウス(レジストリとハーバー)を構築するためのDockerの実装

使用される Docker イメージが増えるにつれて、イメージを保存する場所、つまりウェアハウスが必要...

CSS 透明ボーダー背景クリップマジック

この記事では、CSSの透明な境界線の背景クリップの素晴らしい使い方を主に紹介し、みんなと共有し、自分...

CSS 線形グラデーション凹型長方形遷移効果の実装

この記事では、線形グラデーションの凹四角形の遷移効果の難しさやアイデアについて説明します。主に、凹四...

webpackを使用してTypeScriptコードをパッケージ化およびコンパイルする方法を教えます

TypeScript バンドルwebpack 統合通常、実際の開発では、ビルド ツールを使用してコー...

MySQL トリガーの基本的な使い方(作成、表示、削除など)の詳細な説明

目次1. MySQLトリガーの作成: 1. MySQLトリガー作成構文: 2. MySQL作成構文の...

Vue で PC 解像度の適応を実装するためのサンプルコード

目次プラン依存関係をインストールする依存関係の導入pxをremに変換するFlexible.jsを変更...

ウェブサイトに最も必要なのは、ターゲットユーザーグループのエクスペリエンスを向上させることです。

「大河は東に流れ、波は歴代の英雄たちを洗い流した。古城の西側は三国時代の周朗の赤壁だと言われている...

CSSは、他のレイヤーを変更せずに、多層ネスト構造の最外層を回転させる効果を実現します。

次のようなシナリオがあります。円形のコンテナで、最も外側のコンテナの背景が円弧になっています。内側の...

過去の Linux イメージの問題を修正するためのサンプル分析

過去の Linux イメージに関する問題を修正従来の Linux イメージで作成された ECS クラ...

ubuntu18.04 での qt5.12.8 のインストールと環境設定に関する詳細なチュートリアル

環境システム: Ubuntu 18.04ソフトウェア: qt5.12.8 1. インストールパッケー...

CocosCreator ソースコードの解釈: エンジンの起動とメインループ

目次序文準備行く!文章プロセスを開始するメインループまとめ要約する序文準備皆さんは、こんなことを考え...

MySQLの自動増分主キーの実装の詳細な説明

目次1. 自己増分値はどこに保存されますか? 2. 自己価値修正メカニズム3. 自動増分値を変更する...