MySQL への絵文字表現の挿入に失敗する問題の解決策

巴扎黑
リリース: 2017-05-14 14:20:05
オリジナル
1698 人が閲覧しました

絵文字表現は日々の開発でよく遭遇しますが、最近mysqlに絵文字表現を挿入するときに問題に遭遇したので、関連情報を検索して最終的に解決したので、この記事は主にこの問題を解決するプロセスを共有します。 MySQL に絵文字表現を挿入できない問題の解決策を紹介しましたので、困っている人は参考にしてください。

はじめに

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


Incorrect string value: '\xF0\x90\x8D\x83\xF0\x90...'
ログイン後にコピー

ご存知のとおり、UTF-8 は3 バイトには、私がこれまでに見たフォントのほとんどが含まれていますが、すべてのテキストを収容するには十分ではないため、utf8mb4 は utf8 のスーパーセットで、4 バイトを占めます。 utf8 と互換性があります。私たちが毎日使用する絵文字です。絵文字はわずか 4 バイトです。

そのため、utf8 データ テーブルにデータを挿入すると、エラー Incorrect string value が報告されます。Incorrect string value这个错误.

Google一下很容易就找到了解决方案, 具体解决办法是如下:

一、修改数据表的字符集为utf8mb4

这点很简单, 修改语句网上找一大堆, 不过建议重新建表, 使用 mysqldump -uusername -ppassword database_name table_name > table.sql 备份相应数据表, 并修改其中的建表语句的字符集为 utf8mb4 即可, 然后 mysql -uusername -ppassword database_name < table.sql 重新导入sql即可完成修改字符集操作.

二、MySQL数据库版本要5.5.3及以上

网络上所有的文章都说明要MySQL 5.5.3以上的版本才支持utf8mb4, 不过我使用的数据库版本为5.5.18, 最终仍能解决问题, 所以同学们不要急着找运维哥哥升级数据库先, 先试试能不能自己解决问题.

三、修改数据库配置文件/etc/my.cnf并重启mysql服务

主要是修改数据库的默认字符集, 以及连接, 查询的字符集, [Mysql支持emoji 表情符号 升级编码为UTF8MB4][1] 这篇文章有详细的设置方法, [深入Mysql字符集设置][2] 这篇文章有其中设置的各个字符集的作用, 大家可以科普下.

四、升级MySQL Connector到5.1.21及以上

以上所有的操作, 最关键的是步骤3, 修改数据库的配置文件, 其中大概修改了


[client]
# 客户端来源数据的默认字符集
default-character-set = utf8mb4
[mysqld]
# 服务端默认字符集
character-set-server=utf8mb4
# 连接层默认字符集
collation-server=utf8mb4_unicode_ci
[mysql]
# 数据库默认字符集
default-character-set = utf8mb4
ログイン後にコピー

这些配置指定了数据从客户端到服务端所经过的一条条管道使用的字符集, 其中每一个管道出现问题都可能会导致插入失败或者乱码.

但很多时候, 线上的数据库是不能随便修改数据库文件的, 所以我们的运维同学很果断的回绝了我修改数据库配置文件的请求(T_T)

所以就只能用代码解决了, 一开始是准备从JDBC连接时候就指定使用的字符集处下手.


jdbc:mysql://localhost:3306/ding?characterEncoding=UTF-8
ログイン後にコピー

主要把UTF-8修改为utf8mb4对于的Java Style Charset字符串应该就能解决问题吧?

不过很遗憾的是, Java JDBC并不存在utf8mb4对于的字符集. 使用UTF-8的时候可以兼容urf8mb4并自动转换字符集.

For example, to use 4-byte UTF-8 character sets with Connector/J, configure the MySQL server with character_set_server=utf8mb4, and leave characterEncoding out of the Connector/J connection string. Connector/J will then autodetect the UTF-8 setting. – [MySQL:Using Character Sets and Unicode][3]

后来科普了一下, 在每一次查询请求的时候, 可以显式的指定使用的字符集, 使用 set names utf8mb4 可以指定本次链接的字符集为utf8mb4, 但这个设置在每次连接被释放后都会失效.

目前的解决办法是, 在需要插入utf8mb4的时候, 显示地调用执行set names utf8mb4, 如:


jdbcTemplate.execute("set names utf8mb4");
jdbcTempalte.execute("...");
ログイン後にコピー

需要注意的是, 我们在使用一下ORM框架的时候, 因为性能优化原因, 框架会延迟提交, 除非事务结束或者用户主动调用强制提交, 负责执行的set names utf8mb4

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] この記事には詳細な設定方法が記載されています。 Depth MySQL 文字セット設定][2] この記事には各文字セット セットの役割が記載されており、それについて学ぶことができます。🎜🎜🎜🎜🎜 4. MySQL Connector を 5.1.21 以降にアップグレードします 🎜🎜🎜🎜🎜 すべて上記の操作のうち、最も重要なのはステップ 3 です。データベース構成ファイルを変更します。これは、おそらく 🎜🎜🎜🎜🎜
// MessageDao
public interface MessageDao {
 @Update("set names utf8mb4")
 public void setCharsetToUtf8mb4();
 @Insert("insert into tb_message ......")
 public void insert(Message msg);
}
// test code
SqlSession sqlSession = sqlSessioFactory.openSession();
messageDao = sqlSession.getMapper(MessageDao.class);
messageDao.setCharsetToUtf8mb4();
// 强制提交
sqlSession.commit();
messageDao.insert(message);
ログイン後にコピー
🎜 を変更します。これらの構成では、クライアントからのデータを、サーバーが通過するパイプラインによって使用される文字セットに指定します。各パイプラインでは挿入失敗や文字化けが発生する可能性があります🎜🎜🎜しかし、オンラインデータベースはデータベースファイルを自由に変更できない場合が多く、データベース構成ファイルの変更要求を運用保守のクラスメートが断固拒否しました(T_T)🎜 🎜🎜なので、最初はJDBC接続時に指定した文字セットから始める予定でしたが🎜🎜🎜 🎜🎜rrreee🎜主にUTF-8をutf8mb4用のJava Style Charset文字列に変更する必要があります。問題は解決しますよね?🎜🎜🎜しかし残念ながら、Java JDBC には utf8mb4 の文字セットがありません。urf8mb4 と互換性のある UTF-8 を使用すると、文字セットが自動的に変換されます 🎜🎜🎜たとえば、4 バイトの UTF を使用するには。 Connector/J で -8 文字セットを使用する場合、character_set_server=utf8mb4 を使用して MySQL サーバーを構成し、Connector/J 接続文字列からcharacterEncoding を省略すると、Connector/J は UTF-8 設定を自動検出します。 – [MySQL: 文字セットの使用] Unicode][3]🎜🎜🎜後で、私はいくつかの一般的な科学を行いました。すべてのクエリリクエストで文字セットの使用を明示的に指定できます。このリンクの文字セットを指定するには、 set names utf8mb4 を使用します。 utf8mb4 と同じですが、この設定は接続が解放されるたびに無効になります 🎜🎜🎜 現在の解決策は、utf8mb4 を挿入するときに、次のように set names utf8mb4 を明示的に呼び出して実行することです。 🎜rrreee🎜 ORM フレームワークを使用する場合、パフォーマンス最適化の理由により、トランザクションが終了するかユーザーが積極的に強制コミットを呼び出しない限り、フレームワークは遅延コミットすることに注意してください。set names utf8mb4実行責任はまだ有効になりません🎜🎜🎜ここでは、MessageDao を例として myBatis を使用しています🎜🎜🎜🎜 🎜rrreee🎜この時点で、問題は解決されています...🎜🎜🎜プロジェクトでは、mybatis インスタンスが Spring によって管理されているため、sqlSession を取得できず、Spring トランザクション フレームワークの制限により強制的に送信することもできません。ユーザーが明示的に強制送信を呼び出すことを許可しない 🎜🎜🎜🎜 解決策は 2 つあります。
  • AOP を使用すると、4 バイトの UTF8 文字を挿入できる場合、prefix メソッドは set names utf8mb4 を実行しますが、このソリューションは AOP メソッドが Spring によって管理されるかどうかはまだわかりません。フロントエンドメソッドでは、取得したリンクが次に取得した接続オブジェクトと同じセッションかどうかを確認しますset names utf8mb4, 但该方案还不能确定AOP的方法会被Spring进行事务管理么, 并且在前置方法中,拿到的链接是否和接下来拿到的连接对象是同一个session.

  • 研究Spring JDBC的创建方法, 写一个hook在每次创建新的数据库连接的时候, 都执行一次set names utf8mb4

  • Spring JDBCの作成方法を勉強して、新しいデータベース接続が作成されるたびにフックを記述します。 code>set names utf8mb4 を 1 回実行して、取得したすべてのリンクに文字セットが設定されていることを確認します。
🎜🎜🎜

以上がMySQL への絵文字表現の挿入に失敗する問題の解決策の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!