发现一种普遍的、错误的使用MySQL字符集的案例:
创建数据表时,指定数据表的default charset=utf8,但在客户端写入数据时,却没有设置对应的字符集。
默 认MySQL客户端的字符集一般是Latin1,这样就导致数据库将原本是utf8编码的数据,当作Latin1编码,然后转换成utf8编码,然后保存 到数据文件中。由于读取时,客户端依然是Latin1字符集,这时,MySQL数据库服务程序又将数据文件中存储的数据转换成Latin1编码,发送给客 户端。错上加错,负负得正,客户端居然得到了正确的数据。于是很多程序员就误以为就应该这样使用。
错误的影响在于数据文件容量大大增加,看以下的测试用例:
CREATE TABLE `x` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`c` varchar(1000) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `x2` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`c` varchar(1000) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
drop procedure tx;
drop procedure tx2;
truncate table x;
truncate table x2;
delimiter ;;
create procedure tx()
begin
declare i int default 100000;
while i > 0 do
set i=i-1;
insert into x (c) values ('【要娶的女人】:不一定好看,但在你的眼里要耐看;不一定懂很多道理,但争论时要能和你讲道理;不一定纯洁无瑕,但不能水性杨花;不一定挣很多钱,但 能知道为你省钱;不一定能走进你的思想里,但要能走进你的情感里;不一定爱你死去活来,但要能让你变得更精彩;不一定能为你争面子,但要能和你过日子 ');
end while;
end;;
delimiter ;
delimiter ;;
create procedure tx2()
begin
declare i int default 100000;
while i > 0 do
set i=i-1;
insert into x2 (c) values ('【要娶的女人】:不一定好看,但在你的眼里要耐看;不一定懂很多道理,但争论时要能和你讲道理;不一定纯洁无瑕,但不能水性杨花;不一定挣很多钱,但 能知道为你省钱;不一定能走进你的思想里,但要能走进你的情感里;不一定爱你死去活来,但要能让你变得更精彩;不一定能为你争面子,但要能和你过日子 ');
end while;
end;;
delimiter ;
上面的SQL要存为UTF8字符集,然后执行。
分别调用两个存储过程,对x、x2两个数据表进行数据初始化。
然后查看数据表的信息:
mysql> show table status like 'x'\G
*************************** 1. row ***************************
Name: x
Engine: InnoDB
Version: 10
Row_format: Compact
Rows: 100037
Avg_row_length: 488
Data_length: 48840704
Max_data_length: 0
Index_length: 0
Data_free: 6291456
Auto_increment: 100001
Create_time: 2011-02-28 09:52:02
Update_time: NULL
Check_time: NULL
Collation: latin1_swedish_ci
Checksum: NULL
Create_options:
Comment:
1 row in set (0.00 sec)
mysql> show table status like 'x2'\G
*************************** 1. row ***************************
Name: x2
Engine: InnoDB
Version: 10
Row_format: Compact
Rows: 100025
Avg_row_length: 1033
Data_length: 103415808
Max_data_length: 0
Index_length: 0
Data_free: 5242880
Auto_increment: 100001
Create_time: 2011-02-28 09:52:14
Update_time: NULL
Check_time: NULL
Collation: utf8_general_ci
Checksum: NULL
Create_options:
Comment:
1 row in set (0.00 sec)
[root@vm10110041 test]# ls -lh x*.ibd
-rw-rw---- 1 mysql mysql 108M Feb 28 10:09 x2.ibd
-rw-rw---- 1 mysql mysql 56M Feb 28 10:04 x.ibd
可以看到,表x2,由于错误的使用字符集,导致数据文件比x大出一倍左右。
再来看一下真实的数据:
数据表x中存储的是正确的数据.
数据表x2中存储的是由Latin1强制转换成utf8后的数据.
有兴趣的同学可以分析一下x2的数据是如何转换的,以及如何逆向转换成正确的数据。
综上所述,错误的使用字符集,可能导致大量的资源(磁盘空间,内存空间,CPU资源)的浪费,一定要给予高度的重视。
创建数据表时,指定数据表的default charset=utf8,但在客户端写入数据时,却没有设置对应的字符集。
默 认MySQL客户端的字符集一般是Latin1,这样就导致数据库将原本是utf8编码的数据,当作Latin1编码,然后转换成utf8编码,然后保存 到数据文件中。由于读取时,客户端依然是Latin1字符集,这时,MySQL数据库服务程序又将数据文件中存储的数据转换成Latin1编码,发送给客 户端。错上加错,负负得正,客户端居然得到了正确的数据。于是很多程序员就误以为就应该这样使用。
错误的影响在于数据文件容量大大增加,看以下的测试用例:
CREATE TABLE `x` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`c` varchar(1000) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `x2` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`c` varchar(1000) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
drop procedure tx;
drop procedure tx2;
truncate table x;
truncate table x2;
delimiter ;;
create procedure tx()
begin
declare i int default 100000;
while i > 0 do
set i=i-1;
insert into x (c) values ('【要娶的女人】:不一定好看,但在你的眼里要耐看;不一定懂很多道理,但争论时要能和你讲道理;不一定纯洁无瑕,但不能水性杨花;不一定挣很多钱,但 能知道为你省钱;不一定能走进你的思想里,但要能走进你的情感里;不一定爱你死去活来,但要能让你变得更精彩;不一定能为你争面子,但要能和你过日子 ');
end while;
end;;
delimiter ;
delimiter ;;
create procedure tx2()
begin
declare i int default 100000;
while i > 0 do
set i=i-1;
insert into x2 (c) values ('【要娶的女人】:不一定好看,但在你的眼里要耐看;不一定懂很多道理,但争论时要能和你讲道理;不一定纯洁无瑕,但不能水性杨花;不一定挣很多钱,但 能知道为你省钱;不一定能走进你的思想里,但要能走进你的情感里;不一定爱你死去活来,但要能让你变得更精彩;不一定能为你争面子,但要能和你过日子 ');
end while;
end;;
delimiter ;
上面的SQL要存为UTF8字符集,然后执行。
分别调用两个存储过程,对x、x2两个数据表进行数据初始化。
然后查看数据表的信息:
mysql> show table status like 'x'\G
*************************** 1. row ***************************
Name: x
Engine: InnoDB
Version: 10
Row_format: Compact
Rows: 100037
Avg_row_length: 488
Data_length: 48840704
Max_data_length: 0
Index_length: 0
Data_free: 6291456
Auto_increment: 100001
Create_time: 2011-02-28 09:52:02
Update_time: NULL
Check_time: NULL
Collation: latin1_swedish_ci
Checksum: NULL
Create_options:
Comment:
1 row in set (0.00 sec)
mysql> show table status like 'x2'\G
*************************** 1. row ***************************
Name: x2
Engine: InnoDB
Version: 10
Row_format: Compact
Rows: 100025
Avg_row_length: 1033
Data_length: 103415808
Max_data_length: 0
Index_length: 0
Data_free: 5242880
Auto_increment: 100001
Create_time: 2011-02-28 09:52:14
Update_time: NULL
Check_time: NULL
Collation: utf8_general_ci
Checksum: NULL
Create_options:
Comment:
1 row in set (0.00 sec)
[root@vm10110041 test]# ls -lh x*.ibd
-rw-rw---- 1 mysql mysql 108M Feb 28 10:09 x2.ibd
-rw-rw---- 1 mysql mysql 56M Feb 28 10:04 x.ibd
可以看到,表x2,由于错误的使用字符集,导致数据文件比x大出一倍左右。
再来看一下真实的数据:
数据表x中存储的是正确的数据.
数据表x2中存储的是由Latin1强制转换成utf8后的数据.
有兴趣的同学可以分析一下x2的数据是如何转换的,以及如何逆向转换成正确的数据。
综上所述,错误的使用字符集,可能导致大量的资源(磁盘空间,内存空间,CPU资源)的浪费,一定要给予高度的重视。