More Related Content Similar to Character Encoding and Database Transcoding Project (20) Character Encoding and Database Transcoding Project4. ASCIIASCII
标准标准 ASCIIASCII :: 77 位容器,位容器, 0x00-0x7F0x00-0x7F ,表示,表示 128128 个个
字符字符
拓展拓展 ASCIIASCII :新增定义:新增定义 128128 到到 255255 的字符的字符
比如“比如“ AA ”” :: echo chr(65);echo chr(65); 或者或者 echo "x41";echo "x41";
7. UnicodeUnicode
拓展自拓展自 ASCIIASCII ,范围,范围 0x000000 - 0x10FFFF0x000000 - 0x10FFFF
可容纳可容纳 11141121114112 个字符个字符
转码映射关系转码映射关系 codepagecodepage 的基础的基础
JAVAJAVA 及部分高级语言的内部编码及部分高级语言的内部编码
8. 万能的万能的 UTF-8UTF-8
使用变长使用变长 8bit8bit 模板来传输和存储模板来传输和存储 UnicodeUnicode
11 字节兼容字节兼容 ASCIIASCII ,希腊文字用,希腊文字用 22 字节,中文用字节,中文用 33
字节,辅助平面字符用字节,辅助平面字符用 44 字节字节
UTF-8UTF-8 只是编码方式,而不是字符集只是编码方式,而不是字符集
http://www.ietf.org/rfc/rfc3629.txthttp://www.ietf.org/rfc/rfc3629.txt
10. UnicodeUnicode 转转 UTF-8UTF-8
00000000 - 0000007F : 0xxxxxxx00000000 - 0000007F : 0xxxxxxx
00000080 - 000007FF : 110xxxxx 10xxxxxx00000080 - 000007FF : 110xxxxx 10xxxxxx
00000800 - 0000FFFF : 1110xxxx 10xxxxxx 10xxxxxx00000800 - 0000FFFF : 1110xxxx 10xxxxxx 10xxxxxx
00010000 - 001FFFFF : 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx00010000 - 001FFFFF : 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
11. UnicodeUnicode 转转 UTF-8UTF-8
““ 汉”:汉”: UnicodeUnicode 是是 0x6C490x6C49
0x6C490x6C49 二进制是:二进制是: 0110 1100 0100 10010110 1100 0100 1001 ,,
代替代替 33 字节模板后得到:字节模板后得到:
11100110 10110001 1000100111100110 10110001 10001001 ,即,即 E6 B1 89E6 B1 89 。。
18. ANSIANSI 字符代码字符代码
使用使用 22 个字节代表一个字符的编码统称个字节代表一个字符的编码统称
如如 GB2312GB2312 ,, Big5Big5 ,, JISJIS 等等等等
不同不同 ANSIANSI 编码之间一般互不兼容编码之间一般互不兼容
ANSI CANSI C
19. ANSI vs UnicodeANSI vs Unicode
ANSIANSI 编码表示英文字符时用一个字节,表示中文编码表示英文字符时用一个字节,表示中文
用两个字节用两个字节
UnicodeUnicode 不管表示英文字符还是中文都是用两个字不管表示英文字符还是中文都是用两个字
节来表示。节来表示。
28. 乱码乱码
一般乱码“一般乱码“ 我和ä½æˆ‘和佔 :比如用 Big5 解析 GBK
不兼容乱码“????”:比如把中文从不兼容乱码“????”:比如把中文从 UTF-8UTF-8 转转
latin1latin1 导致失真导致失真
空格或方格“□”:比如用空格或方格“□”:比如用 GBKGBK 显示显示 UTF-8UTF-8 中的日中的日
文文
36. 导出数据命令:导出数据命令:
# latin1# latin1 表表
set names latin1; select * from $table into outfile '$table.latin1' fields terminated byset names latin1; select * from $table into outfile '$table.latin1' fields terminated by
'<#>' lines terminated by '<%>n';'<#>' lines terminated by '<%>n';
# utf8# utf8 表表
set names utf8;select * from $table into outfile '$table.utf8' fields terminated by '<#>'set names utf8;select * from $table into outfile '$table.utf8' fields terminated by '<#>'
lines terminated by '<%>n';lines terminated by '<%>n';
## 其他库其他库
mysqldump -S $socket --lines-terminated-by='<%>n' --fields-terminated-by='<#>'mysqldump -S $socket --lines-terminated-by='<%>n' --fields-terminated-by='<#>'
-N --single-transaction --default-character-set=utf8 -T $data/$db/ $db-N --single-transaction --default-character-set=utf8 -T $data/$db/ $db
38. ## 主表转码主表转码
cat $table.latin1 | php /home/xxx/bin/m.php > $table.txtcat $table.latin1 | php /home/xxx/bin/m.php > $table.txt
## 其他表转码其他表转码
cat $table.latin1 | php /home/xxx/bin/s.php > $table.txtcat $table.latin1 | php /home/xxx/bin/s.php > $table.txt
## 导入数据导入数据
LOAD DATA INFILE '$table.txt' ignore INTO TABLE $table CHARACTER SETLOAD DATA INFILE '$table.txt' ignore INTO TABLE $table CHARACTER SET
UTF8 fields terminated by '<#>' lines terminated by '<%>n';UTF8 fields terminated by '<#>' lines terminated by '<%>n';
40. SET NAMES latin1SET NAMES latin1 改为改为 SET NAMES utf8SET NAMES utf8
去掉去掉 mb_convert_encoding($str, 'UTF-8', 'GBK');mb_convert_encoding($str, 'UTF-8', 'GBK');
为上述修改加上开关,方便回滚为上述修改加上开关,方便回滚
42. 旧旧 tagtag :: latin1 varchar(10)latin1 varchar(10)
新 tag : utf-8 varchar(10)
兼容新旧兼容新旧 tagtag 的简单办法 :的简单办法 : $tag = substr($tag, 0, 15);$tag = substr($tag, 0, 15);
兼容会导致乱码么?兼容会导致乱码么?
44. 导入导出 binlog 的命令:
mysql -f -A -h xxx.xxx.xxx.xxx -P xx --default-character-set=utf8 > sync.sql
mysql -f -A -h xxx.xxx.xxx.xxx -P xx --default-character-set=utf8 < sync.sql
46. BinlogBinlog 转码问题转码问题 11 ::
由于使用外部转码,而非由于使用外部转码,而非 mysqlmysql 内部转码,导致的转义符 “内部转码,导致的转义符 “ ”” 被破被破
坏的问题坏的问题
$str = preg_replace("/(*)',/", "',", $str);$str = preg_replace("/(*)',/", "',", $str);
47. BinlogBinlog 转码问题转码问题 22 ::
//// 按指定行结束符读取每行的按指定行结束符读取每行的 PHPPHP 函数函数
function getline($fp, $delim = "n")function getline($fp, $delim = "n")
{{
$result = '';$result = '';
$ds = strlen($delim);$ds = strlen($delim);
while (!feof($fp)) {while (!feof($fp)) {
$result .= fgetc($fp);$result .= fgetc($fp);
if ($delim === substr($result, -$ds)) {if ($delim === substr($result, -$ds)) {
return substr($result, 0, -$ds);return substr($result, 0, -$ds);
}}
}}
return $result;return $result;
}}
48. BinlogBinlog 转码问题转码问题 33 ::
// binlog// binlog 的的 sqlsql 语句被 “语句被 “ n”n” 截为多行的问题截为多行的问题
if (substr($str, -3) == "',n") {if (substr($str, -3) == "',n") {
$str = substr($str, 0, -3);$str = substr($str, 0, -3);
$subfix = "',n";$subfix = "',n";
}}
//// 转码后再把转码后再把 nn 拼回去拼回去
$str = safeEncoding($str);$str = safeEncoding($str);
$str .= $subfix;$str .= $subfix;
51. 在在 binlogbinlog 转码之前还需要过滤掉转码之前还需要过滤掉 MySQLMySQL 的会话配置,否则在导入时的会话配置,否则在导入时
将出现编码混乱的情况。将出现编码混乱的情况。
mysqlbinlog $bin | sed '/@@session.character_set_client/d;//*!Cmysqlbinlog $bin | sed '/@@session.character_set_client/d;//*!C
/d;/^#/d;/session.sql_mode/d' | php /home/xxx/bin/binlog.php >/d;/^#/d;/session.sql_mode/d' | php /home/xxx/bin/binlog.php >
sync.sqlsync.sql
54. 回滚方案:回滚方案:
1.1. 代码回退代码回退
2. MySQL-VIP2. MySQL-VIP 切换回原主库所在机器(切换回原主库所在机器( 5min5min ))
3.3. 恢复服务并测试确认恢复服务并测试确认
57. 总结总结
1.1. 抓主要矛盾抓主要矛盾
2.2. 优化:提前提示用户在切换期间不要上传长视频优化:提前提示用户在切换期间不要上传长视频
3.3. 旧代码必须下线,旧接口必须升级旧代码必须下线,旧接口必须升级
4.4. 经验虽好,可是不要太多经验虽好,可是不要太多