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 を構成して権限を設定する方法

推薦する

Nginxサービス500:内部サーバーエラーの原因の1つ

500 (内部サーバー エラー) サーバーでエラーが発生したため、要求を完了できませんでした。 50...

熟練デザイナーの7つの原則(2):色の使い方

<br />前回の記事:優秀なデザイナーの7つの原則(1):フォントデザイン 英語 原文...

時点に基づくMySQLクイックリカバリソリューション

なぜこのような記事を書いたかというと、数日前の夜、仕事が終わろうとしていたときに、業務側で突然、テー...

Vueコンポーネント間のデータ共有の詳細な説明

目次1. プロジェクト開発において、コンポーネント間の最も一般的な関係は次の 2 つのタイプに分けら...

VMware+centOS 8 で http プロトコルに基づく Git サービスを構築する方法

目次1. 原因2. デバイス情報3. 準備4. Apacheをインストールする5. gitを設定する...

CentOS サーバーの時間を北京時間に変更する方法

1. VPSとCentOSシステムを購入しましたが、サーバーの時間が北京時間と一致せず、時差があるこ...

CSS を使用して小さな画像をプルダウンし、大きな画像と情報を表示する方法

今日は、Taobao、JD.comなどのショッピングモールでよく使われている、小さな画像の上にマウス...

【Webデザイン】E-WebTemplates の美しい海外の Web ページ テンプレート (FLASH+PSD ソース ファイル+HTML) を共有します

これらはすべて海外のE-WebTemplates WebサイトからのWebページテンプレートであり、...

JQueryセレクターの詳細な説明

目次基本的なセレクター:レベルセレクター:属性セレクター:フィルターセレクター:フォーム属性セレクタ...

Linux 上での Go 環境の構築のインストールと設定の説明

Linux で Go 環境を構築するのは非常に簡単です。 1. go1.2.1.linux-386....

現在使用されている設定ファイル my.cnf を表示する mysql メソッド (推奨)

my.cnfは、MySQL の起動時に読み込まれる設定ファイルです。通常は MySQL インストー...

img 画像タグに alt 属性を付与する必要がありますか?

img 画像タグに alt 属性を追加しますか?画像 img タグの alt 属性を見落とすことはよ...

Vueのシンプルな状態管理ストアモードを理解する方法

目次概要1. store.jsを定義する2. store.js を使用するコンポーネント3. 成果を...

Node.js の非同期イテレータの詳細な説明

目次序文非同期イテレータとは何ですか?非同期イテレータストリームとしてページング機能を備えたAPIの...

MySQLのバックアップとリカバリの簡単な分析

目次1. はじめに2. バックアップとリカバリの簡単な定義3. 復旧計画で考慮すべきいくつかの要素4...