想支持emoji表情的曲折经历
前奏:android post到java后台的数据,后台使用String存储,通过hibernate insert到mysql5.1数据库,会看到有报错。
java.sql.SQLException: Incorrect string value: '\xF0\x9F\x92\x94' for column 'content' at row ……
就是不支持呗。我本地电脑是mariadb5.6,支持但是我使用的是utf8,它不会报错,会插入进去,但是数据库客户端和java都不支持,我也看不到,不知道是正确,或者不正确的。反正能存不报错。
也许大家都是分工明确的,所以从网上看到的教程里面,就只有移动端或者服务端,没有一个人能给出一个完整的解决方案。
本文后面会给出一个解决方案。
关于emoji的起源之类的,就去网上找吧。太多了,都是复制粘贴的。
为什么会不支持emoji?
因为它不是gbk,也不是utf8,而是utf8mb编码(utf8的超集)。同时它开始于ios,所以android上没有。。。
首先说支持emoji的两种方法:
一、前端显示的方法
1. 字库,用支持utf8mb的新字库。
2. 做图片映射,就是自己把这些表情代码找出来,并且替换成一些标记,比如[emoji]0x1f604[/emoji]。
二、后端传输及存储方式(java web)
1. 数据库存储utf8mb
2. 存储自定义标记,使用时再转换
优劣:
第一种方法:需要升级mysql数据库,mysql java驱动,但是对于多平台应用,不太合适。而且当前而言,utf8mb的使用并没有那么广泛。而且——我已经测试过了,tomcat7,jdk7,在windows环境下,存储后是????,并不能正确存储。而在linux上可以正确存储。可能是两个操作系统的编码问题。这样开发就不方便了。
第二种方法:不需要对现有环境做改变,但是需要自己写一些处理方法,识别出这些字符,做替换存储,使用时,再反向替换(显示为图片,比如web端和android端)。好处是,可以多平台通用。
我最终的方法是选择第二种,下面先讲第一种方法的曲折经历。
一、mysql数据库升级遇到的内存不足问题
mysql数据库升级 5.1到5.6 同时修改表支持utf8mb4
因为要给Andorid移动应用添加一个emoji表情支持。而网上大多说法是emoji是4个字节的utf8,现在服务器使用的都是3个字节的utf8。mysql从5.5.+的某个版本开始支持utf8mb4,也就是可以存4个字节的了。但是我一直在想在java后台怎么处理?
网上还有很多文章(X度能够搜出来的东西,基本上都是一个模板,内容都是Ctrl+V的),说的都是怎么在mysql数据库里面存emoji表情,那么就需要使用mysql5.5.+的那个开始支持的版本了,我去官网看了下,所以决定使用mysql5.6。
从昨天晚上的这一刻开始,我就给自己挖好了坑,并且舒舒服服地跳进去了。
服务器配置:X里云服务器。1核cpu,512M内存,20G硬盘,一个月50块,很贵的。
我在安装的时候就已经很困惑了,为什么mysql5.1和mysql5.6的安装包大小差距这么大,5.1只有10+m,5.6有70m。可能真的是年份久远了吧。
我在开发的时候其实一直使用mariadb5.6的。只不过在centos上,mysql安装更方便一些。看来,也许我的服务器也应该换了。
开始安装:
采用yum安装,非编译源码。编译源码太麻烦了。虽然其实还好了~~~
1. 备份数据库,这个自己动手,我就不多说了。
2. 卸载以前的版本(升级其实也不麻烦):yum remove mysql(慎用)
3. 从mysql官网下载yum源(安装方便):wget http://dev.mysql.com/get/mysql-community-release-el5-5.noarch.rpm
这个是支持redhat6.x版本的,可以自己去下载其它服务器版本的 http://dev.mysql.com/downloads/repo/yum/
4. 安装yum源:rpm -Uvh mysql-community-release-el5-5.noarch.rpm
5. 安装mysql:yum install mysql-server -y
这里会去下载安装包,等好久。学校网速在烂了。
而且大半夜熄灯后,我用手机2G网络ssh连接到服务器等着下载完成是多么痛苦的一件事情。而且今天发现,中午吃完饭的时候,网速貌似是最快的……
6. yum安装的好处就是什么都不用管,坏处就是,自定义性差,但是配置文件还是可以自己修改的。
7. 启动mysql(yum安装,服务会自己装好的,而且有环境变量,什么都不用配置,想我当年编译源码,搞了很久才好):service mysqld start
[root@AY140416152603506d4cZ ~]# service mysqld start
Initializing MySQL database: 2014-11-14 13:46:19 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
2014-11-14 13:46:19 5502 [Warning] No argument was provided to --log-bin, and --log-bin-index was not used; so replication may break when this MySQL server acts as a master and has his hostname changed!! Please use '--log-bin=AY140416152603506d4cZ-bin' to avoid this problem.
2014-11-14 13:46:19 5502 [Note] InnoDB: Using atomics to ref count buffer pool pages
2014-11-14 13:46:19 5502 [Note] InnoDB: The InnoDB memory heap is disabled
2014-11-14 13:46:19 5502 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins
2014-11-14 13:46:19 5502 [Note] InnoDB: Memory barrier is not used
2014-11-14 13:46:19 5502 [Note] InnoDB: Compressed tables use zlib 1.2.3
2014-11-14 13:46:19 5502 [Note] InnoDB: Using Linux native AIO
2014-11-14 13:46:19 5502 [Note] InnoDB: Using CPU crc32 instructions
2014-11-14 13:46:19 5502 [Note] InnoDB: Initializing buffer pool, size = 10.0M
2014-11-14 13:46:19 5502 [Note] InnoDB: Completed initialization of buffer pool
2014-11-14 13:46:19 5502 [Note] InnoDB: The first specified data file ./ibdata1 did not exist: a new database to be created!
2014-11-14 13:46:19 5502 [Note] InnoDB: Setting file ./ibdata1 size to 12 MB
2014-11-14 13:46:19 5502 [Note] InnoDB: Database physically writes the file full: wait...
2014-11-14 13:46:19 5502 [Note] InnoDB: Setting log file ./ib_logfile101 size to 48 MB
2014-11-14 13:46:21 5502 [Note] InnoDB: Setting log file ./ib_logfile1 size to 48 MB
2014-11-14 13:46:22 5502 [Note] InnoDB: Renaming log file ./ib_logfile101 to ./ib_logfile0
2014-11-14 13:46:22 5502 [Warning] InnoDB: New log files created, LSN=45781
2014-11-14 13:46:22 5502 [Note] InnoDB: Doublewrite buffer not found: creating new
2014-11-14 13:46:22 5502 [Note] InnoDB: Doublewrite buffer created
2014-11-14 13:46:22 5502 [Note] InnoDB: 128 rollback segment(s) are active.
2014-11-14 13:46:22 5502 [Warning] InnoDB: Creating foreign key constraint system tables.
2014-11-14 13:46:22 5502 [Note] InnoDB: Foreign key constraint system tables created
2014-11-14 13:46:22 5502 [Note] InnoDB: Creating tablespace and datafile system tables.
2014-11-14 13:46:22 5502 [Note] InnoDB: Tablespace and datafile system tables created.
2014-11-14 13:46:22 5502 [Note] InnoDB: Waiting for purge to start
2014-11-14 13:46:22 5502 [Note] InnoDB: 5.6.21 started; log sequence number 0
2014-11-14 13:46:23 5502 [Note] Binlog end
2014-11-14 13:46:23 5502 [Note] InnoDB: FTS optimize thread exiting.
2014-11-14 13:46:23 5502 [Note] InnoDB: Starting shutdown...
2014-11-14 13:46:24 5502 [Note] InnoDB: Shutdown completed; log sequence number 1625977[/p][p=30, 2, left]2014-11-14 13:46:24 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
2014-11-14 13:46:24 5524 [Warning] No argument was provided to --log-bin, and --log-bin-index was not used; so replication may break when this MySQL server acts as a master and has his hostname changed!! Please use '--log-bin=AY140416152603506d4cZ-bin' to avoid this problem.
2014-11-14 13:46:24 5524 [Note] InnoDB: Using atomics to ref count buffer pool pages
2014-11-14 13:46:24 5524 [Note] InnoDB: The InnoDB memory heap is disabled
2014-11-14 13:46:24 5524 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins
2014-11-14 13:46:24 5524 [Note] InnoDB: Memory barrier is not used
2014-11-14 13:46:24 5524 [Note] InnoDB: Compressed tables use zlib 1.2.3
2014-11-14 13:46:24 5524 [Note] InnoDB: Using Linux native AIO
2014-11-14 13:46:24 5524 [Note] InnoDB: Using CPU crc32 instructions
2014-11-14 13:46:24 5524 [Note] InnoDB: Initializing buffer pool, size = 10.0M
2014-11-14 13:46:24 5524 [Note] InnoDB: Completed initialization of buffer pool
2014-11-14 13:46:24 5524 [Note] InnoDB: Highest supported file format is Barracuda.
2014-11-14 13:46:24 5524 [Note] InnoDB: 128 rollback segment(s) are active.
2014-11-14 13:46:24 5524 [Note] InnoDB: Waiting for purge to start
2014-11-14 13:46:24 5524 [Note] InnoDB: 5.6.21 started; log sequence number 1625977
2014-11-14 13:46:24 5524 [Note] Binlog end
2014-11-14 13:46:24 5524 [Note] InnoDB: FTS optimize thread exiting.
2014-11-14 13:46:24 5524 [Note] InnoDB: Starting shutdown...
2014-11-14 13:46:26 5524 [Note] InnoDB: Shutdown completed; log sequence number 1625987[/p][p=30, 2, left]PLEASE REMEMBER TO SET A PASSWORD FOR THE MySQL root USER !
To do so, start the server, then issue the following commands:
/usr/bin/mysqladmin -u root password 'new-password'
/usr/bin/mysqladmin -u root -h AY140416152603506d4cZ password 'new-password'
Alternatively you can run:
/usr/bin/mysql_secure_installation
which will also give you the option of removing the test
databases and anonymous user created by default. This is
strongly recommended for production servers.
See the manual for more instructions.
Please report any problems at [url=http://bugs.mysql.com/]http://bugs.mysql.com/[/url]
The latest information about MySQL is available on the web at
[url=http://www.mysql.com]http://www.mysql.com[/url]
Support MySQL by buying support/licenses at [url=http://shop.mysql.com]http://shop.mysql.com[/url]
Note: new default config file not created.
Please make sure your config file is current
WARNING: Default config file /etc/my.cnf exists on the system
This file will be read by default by the MySQL server
If you do not want to use this, either remove it, or use the
--defaults-file argument to mysqld_safe when starting the server
[ OK ]
MySQL Daemon failed to start.
Starting mysqld: [FAILED]
141114 13:18:23 mysqld_safe Starting mysqld daemon with databases from /var/lib/mysql
141114 13:18:24 mysqld_safe mysqld from pid file /var/run/mysqld/mysqld.pid ended
# Remove leading # and set to the amount of RAM for the most important data
# cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%.
意思是说,设置mysql的缓存,如果是专用服务器,设置为内存的70%,其它服务器的设置为10%
它默认值是128M。
我设置了好几个一直不行,直到我设置成10M。。。
我们来看看它占用了多少。
没有开启mysql服务时:
[root@AY140416152603506d4cZ ~]# service mysqld stop
Stopping mysqld: [ OK ]
[root@AY140416152603506d4cZ ~]# free -m
total used free shared buffers cached
Mem: 490 61 429 0 1 15
-/+ buffers/cache: 45 445
Swap: 0 0 0
[root@AY140416152603506d4cZ ~]# service mysqld start
Starting mysqld: [ OK ]
[root@AY140416152603506d4cZ ~]# free -m
total used free shared buffers cached
Mem: 490 484 6 0 0 13
-/+ buffers/cache: 469 20
Swap: 0 0 0
performance_schema_max_table_instances 12500
table_definition_cache 1400
table_open_cache 2000
performance_schema_max_table_instances=200
table_definition_cache=200
table_open_cache=128
[root@AY140416152603506d4cZ ~]# free -m
total used free shared buffers cached
Mem: 490 134 356 0 3 35
-/+ buffers/cache: 95 395
Swap: 0 0 0
use mysql;
update user set PASSWORD = PASSWORD('******') where USER='root' and HOST='localhost';
./configure --prefix=/usr/local/php --with-config-file-path=/usr/local/php/etc --with-apxs2=/usr/local/apache2/bin/apxs --with-mysql=mysqlnd --with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd --with-libxml-dir=/usr/local/libxml2/ --with-png-dir=/usr/local/libpng/ --with-jpeg-dir=/usr/local/jpeg8/ --with-freetype-dir=/usr/local/freetype/ --with-gd --with-zlib-dir=/usr/local/zlib/ --with-mcrypt=/usr/local/libmcrypt/ --with-mysqli=/usr/local/mysql/bin/mysql_config --enable-soap --enable-mbstring=all --enable-sockets
周六一个上午都在弄这个,但是还是没有解决,按照官网的说法,使用mysqlnd连接,不需要预先安装mysql的,但是又报这个错,而且我的mysql已经启动就起来了。
修改后的编译参数(错误的):
./configure --prefix=/usr/local/php --with-config-file-path=/usr/local/php/etc --with-apxs2=/usr/local/apache2/bin/apxs --with-mysql=/usr --with-mysqli=/usr/bin/mysql_config --with-pdo-mysql=/usr --with-libxml-dir=/usr/local/libxml2/ --with-png-dir=/usr/local/libpng/ --with-jpeg-dir=/usr/local/jpeg8/ --with-freetype-dir=/usr/local/freetype/ --with-gd --with-zlib-dir=/usr/local/zlib/ --with-mcrypt=/usr/local/libmcrypt/ --with-mysqli=/usr/local/mysql/bin/mysql_config --enable-soap --enable-mbstring=all --enable-sockets
使用这个参数后,又找不到configure: error: Cannot find libmysqlclient under /usr
ln -s /usr/lib64/mysql/libmysqlclient.a /usr/lib/libmysqlclient.a
ln -s /usr/lib64/mysql/libmysqlclient_r.a /usr/lib/libmysqlclient_r.a
checking for mysql_close in -lmysqlclient... no
checking for mysql_error in -lmysqlclient... no
./configure --prefix=/usr/local/php --with-config-file-path=/usr/local/php/etc --with-apxs2=/usr/local/apache2/bin/apxs --with-mysql=mysqlnd --with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd --with-libxml-dir=/usr/local/libxml2/ --with-png-dir=/usr/local/libpng/ --with-jpeg-dir=/usr/local/jpeg8/ --with-freetype-dir=/usr/local/freetype/ --with-gd --with-zlib-dir=/usr/local/zlib/ --with-mcrypt=/usr/local/libmcrypt/ --enable-soap --enable-mbstring=all --enable-sockets --disable-fileinfo
但是又遇到新问题 虚拟内存耗尽 virtual memory exhausted: Cannot allocate memory
官网有解决方法 :https://bugs.php.net/bug.php?id=48809
Adding --disable-fileinfo to ./configure solves the problem.
最终还是把php5.6安装成功了。
但是数据库用的是5.0。按照这个理论,其实也可以用5.6的,但是我真的不想再折腾了。
三、误操作,删除了服务器数据库和数据文件
这个操作直接导致我的网站挂了……挂了好几天……
四、装虚拟机,配置环境,测试为什么在windows下不能存储emoji
1. 把mariadb从5.5(基于mysql5.6)升级到10.0(基于mysql5.6),理论来说都没有问题的。但是我还是试了一下,存储失败。在数据库里面看到的就是?
2. 在linux上成功的情况是,这些字符是看不见的,但传到手机上时就会看到emoji表情。所以判定第1条是失败。
3. 装虚拟机,配置环境,安装mysql5.6,tomcat,jdk,程序。直到启动后,再测试,没有问题,可以保存成功。
4. 然后使用windows的tomcat,linux的mysql。还是不能正确存储。
结论是,虽然可以使用mysql存储,但是却会因为环境的改变而发生变化,不稳定。
五、服务器还原我原来的mysql和php(这个是因为我有跑其它程序)
1. 以前使用过yum安装httpd,php,mysql,正常可用的。
2. 以前的以前mysql和php和apache都是编译源码安装的,不会出现问题。
3. 但是现在使用yum安装的却不能用。看来linux下用源码安装会比较靠谱
4. mysql5.0和php5.3源码安装成功。
5. 然后发现其实上面只是多一个参数。。。。--with-mysqli=/usr/local/mysql/bin/mysql_config
第一种方法,尽于此,不再做过多解释。不使用这个方法。
六、解决方案:
使用第二种方法:
请期待下一篇文章:
作者的论坛原文地址:
Andoird想支持emoji表情的曲折经历(未完待续)
http://bbs.vpigirl.com/forum.php?mod=viewthread&tid=498
(出处: 心惊变 回忆的路上,时间变得好慢!)