日期:2014-05-16  浏览次数:20482 次

emoji字符无法写入Mysql数据库问题

最近发现Kettle的ETL中一直在报错,查看日志发现有些字无法入库,类似以前遇到的数据源与目的数据库字段字符集不同导致的一样;但这个是从游戏接口日志文件读取的,字符集统一都是utf8,不应该是上述情况导致。错误日志如下

INFO  24-12 18:39:44,257 - Column types: string,smallint,string,string,string,string,int,string,string,string,string,string,string,string,string,int
ERROR 24-12 18:39:45,281 - Table output - Because of an error, this step can't continue: 
ERROR 24-12 18:39:45,281 - Table output - org.pentaho.di.core.exception.KettleException: 
Error batch inserting rows into table [t_oper_mone_first_buy_fact].
Errors encountered (first 10):
Incorrect string value: '\xF0\x9F\x91\x8D' for column 'f_char_name' at row 1
Error updating batch
Incorrect string value: '\xF0\x9F\x91\x8D' for column 'f_char_name' at row 1
        at org.pentaho.di.trans.steps.tableoutput.TableOutput.writeToTable(TableOutput.java:393)
        at org.pentaho.di.trans.steps.tableoutput.TableOutput.processRow(TableOutput.java:117)
        at org.pentaho.di.trans.step.RunThread.run(RunThread.java:40)
        at java.lang.Thread.run(Thread.java:662)
Caused by: org.pentaho.di.core.exception.KettleDatabaseBatchException: 
Error updating batch
Incorrect string value: '\xF0\x9F\x91\x8D' for column 'f_char_name' at row 1
        at org.pentaho.di.trans.steps.tableoutput.TableOutput.writeToTable(TableOutput.java:309)
        ... 3 more
Caused by: java.sql.BatchUpdateException: Incorrect string value: '\xF0\x9F\x91\x8D' for column 'f_char_name' at row 1
        at com.mysql.jdbc.ServerPreparedStatement.executeBatchSerially(ServerPreparedStatement.java:796)
        at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:1449)
        at org.pentaho.di.trans.steps.tableoutput.TableOutput.writeToTable(TableOutput.java:304)
        ... 3 more

?经过在网上查询,\xF0\x9F开头的确实是UTF8字符集范围;UTF8长度是2-4个字节,我们在Mysql常用的是2-3个字节长,但这个抛出来的错误显示是4个字节,所以就错在这了(用java写代码也会报同样错误,原因是jdbc在做数据插入前会严格检查字段的类型、长度,一但不符就会抛出异常;php在这方面稍微自作聪明点,会把多出来的字节截掉,但对数据本身就是丢掉了信息,不适合做数据ETL方面的工作)。


又经过网上查询,有说这种字符属于emoji表情符,关于emoji是什么,点这里有科普?http://baike.baidu.com/view/2631589.htm
找到问题就好办了,将f_char_name字段的字符集改为utf8mb4,在Kettle的数据库连接高级设置中,设置当前会话字符集为utf8mb4,问题解决。



?

?

经过这次问题,以后有些字段有必要考虑设置成utf8mb4字符集来支持更广阔的字符内容,缺点显而易见,就是多占地儿了。


是否采用,视具体情况而定吧。