読者です 読者をやめる 読者になる 読者になる

inohilog

/var/log/inohiro

MySQLへ4バイトの文字を挿入する時

mysql research
  • 研究用に手元に ja.dbpedia.org のクローンを構築している
    • SPARQL Endpoint には Virtuoso ではなく,Fuseki(Jena SDB,MySQL)でやる
    • MySQL Server 5.6.14 with Connector/J on Ubuntu 12.04.3
      • Connector/J のバージョンは 5.1.26-bin
  • 昨今,絵文字などの4バイト文字や非常用漢字(その中でもとくに変な文字)を入れようとすると,以下の様なエラーを吐く
    • "Incorrect string value: '\xF0\xA8\xB1\xBD' for column ..."
  • 対策として,character set に 'utf8mb4' を使うことで上記のエラーを回避することができる
  • 今回,jena-sdb のプログラムは jar 形式になっているため,初期化コマンド("$ jena-sdb/bin/sdbconfig SPEC --create")を実行後に,ALTER TABLEして varchar 型に設定されているカラムの character set を 'utf8mb4' に設定した
    • ただ,それぞれのカラムの character set を 'utf8mb4' に設定しても,テーブル(スキーマ)の default charset が 'utf8' のままだと結局挿入に失敗するので,以下の SQL を実行して,テーブルの default charset を変更した(jena-sdbの場合,`Nodes`と`Prefixes`テーブルにvarchar,longtext 型が含まれる)
ALTER TABLE `SDB`.`Nodes` CONVERT TO CHARACTER SET utf8mb4;
ALTER TABLE `SDB`.`Prefixes` CONVERT TO CHARACTER SET utf8mb4;
  • これを実行して,create table 文を確認すると,たしかに default charset が 'utf8bm4' になっている(`Nodes` テーブルの例)
CREATE TABLE `Nodes` (
  `hash` bigint(20) NOT NULL DEFAULT '0',
  `lex` longtext,
  `lang` varchar(10) NOT NULL DEFAULT '',
  `datatype` varchar(200) NOT NULL DEFAULT '',
  `type` int(10) unsigned NOT NULL DEFAULT '0',
  PRIMARY KEY (`hash`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
  • これで,4バイト文字のエラーは回避出来たかとおもいきや(大半のエラーは発生しなくなったように見えるが),ぐぐっても全然情報が出てこないエラーが発生するファイル(Turtle形式)があり,お手上げ状態になっている
    • ja.dbpedia.org のダンプファイルの一部 "jawiki-20130903-infobox-properties.ttl" を sbdload すると発生する
RROR Error in thread: Exception flushing
com.hp.hpl.jena.sdb.SDBException: Exception flushing
        at com.hp.hpl.jena.sdb.layout2.TupleLoaderBase.flush(TupleLoaderBase.java:234)
        at com.hp.hpl.jena.sdb.layout2.TupleLoaderBase.load(TupleLoaderBase.java:103)
        at com.hp.hpl.jena.sdb.layout2.LoaderTuplesNodes.updateOneTuple(LoaderTuplesNodes.java:299)
        at com.hp.hpl.jena.sdb.layout2.LoaderTuplesNodes.access$200(LoaderTuplesNodes.java:43)
        at com.hp.hpl.jena.sdb.layout2.LoaderTuplesNodes$Commiter.run(LoaderTuplesNodes.java:362)
        at java.lang.Thread.run(Thread.java:744)
Caused by: java.sql.BatchUpdateException: Incorrect string value: '\xF0\xA8\xB1\xBD' for column 'n1' at row 1
        at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:2056)
        at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:1467)
        at com.hp.hpl.jena.sdb.layout2.TupleLoaderBase.flush(TupleLoaderBase.java:214)
        ... 5 more
Caused by: java.sql.SQLException: Incorrect string value: '\xF0\xA8\xB1\xBD' for column 'n1' at row 1
        at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1078)
        at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4190)
        at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4122)
        at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2570)
        at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2731)
        at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2818)
        at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2157)
        at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2460)
        at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:2008)
        ... 7 more
com.hp.hpl.jena.sdb.SDBException: Exception flushing
        at com.hp.hpl.jena.sdb.layout2.TupleLoaderBase.flush(TupleLoaderBase.java:234)
        at com.hp.hpl.jena.sdb.layout2.TupleLoaderBase.load(TupleLoaderBase.java:103)
        at com.hp.hpl.jena.sdb.layout2.LoaderTuplesNodes.updateOneTuple(LoaderTuplesNodes.java:299)
        at com.hp.hpl.jena.sdb.layout2.LoaderTuplesNodes.access$200(LoaderTuplesNodes.java:43)
        at com.hp.hpl.jena.sdb.layout2.LoaderTuplesNodes$Commiter.run(LoaderTuplesNodes.java:362)
        at java.lang.Thread.run(Thread.java:744)
Caused by: java.sql.BatchUpdateException: Incorrect string value: '\xF0\xA8\xB1\xBD' for column 'n1' at row 1
        at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:2056)
        at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:1467)
        at com.hp.hpl.jena.sdb.layout2.TupleLoaderBase.flush(TupleLoaderBase.java:214)
        ... 5 more
Caused by: java.sql.SQLException: Incorrect string value: '\xF0\xA8\xB1\xBD' for column 'n1' at row 1
        at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1078)
        at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4190)
        at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4122)
        at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2570)
        at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2731)
        at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2818)
        at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2157)
        at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2460)
        at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:2008)
        ... 7 more