* GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源。
- 一、客户端显示字符背景介绍
- 二、代码跟踪
- 三、代码改造
- 四、总结
一、客户端显示字符背景介绍
MySQL最新版本有一个新功能,在使用客户端的时候,最后加上--skip-binary-as-hex
选项可以直接显示二进制值对应的字符串,不加该选项就可以按照原来的设置格式显示。先来看一下以下的varbinary
的显示例子。
#建表:
create table varb(id int,bb varbinary(1000));
insert into varb values(1,'abcd');
#登录:
mysql -h 127.0.0.1 -P3307 -uroot --skip-binary-as-hex
mysql> select * from varb;
------ ------
| id | bb |
------ ------
| 1 | abcd |
------ ------
1 row in set (0.00 sec)
如果不加--skip-binary-as-hex
选项的显示如下:
mysql -h 127.0.0.1 -P3307 -uroot
mysql> select * from varb;
------ ------------
| id | bb |
------ ------------
| 1 | 0x61626364 |
------ ------------
1 row in set (0.01 sec)
这个功能对于用惯了旧版本的同学们有的会觉得不方便,今天这里动手改造一下都显示成字符格式而不用通过--skip-binary-as-hex
选项设置。
二、代码跟踪
沿用上面的表查询一下哪段代码决定字符的显示格式,代码解析如下:
输入该命令后找到相关字符显示的代码:
代码语言:javascript复制mysql> select * from varb;
class Item_field
的成员函数如下:
const CHARSET_INFO *charset_for_protocol(void) override {
return field->charset_for_protocol();
#表字段的字符显示取决于field的字符设置。
}
继续找到class Field
的成员函数如下:
const CHARSET_INFO *charset_for_protocol() const {
return binary() ? &my_charset_bin : charset();
#field的字符设置取决于是否binary类型。
}
输入以上命令GDB跟踪一下代码堆栈:
代码语言:javascript复制Thread 47 "mysqld" hit Breakpoint 3, Item_field::charset_for_protocol (this=0x7fff340bc1f0)
at /home/greatdb/sql/item.h:4373
4373 const CHARSET_INFO *charset_for_protocol(void) override {
(gdb) bt
#0 Item_field::charset_for_protocol (this=0x7fff340bc1f0)
at /home/greatdb/sql/item.h:4373#1 0x0000555558e60ca8 in THD::send_result_metadata (this=0x7fff34000c00, list=..., flags=5)
at /home/greatdb/sql/sql_class.cc:2831
#2 0x0000555558d9fe59 in Query_result_send::send_result_set_metadata (this=0x7fff3429cfa0,
thd=0x7fff34000c00, list=..., flags=5)
at /home/greatdb/sql/query_result.cc:74
#3 0x0000555559093d1b in Query_expression::ExecuteIteratorQuery (this=0x7fff3429ae08,
thd=0x7fff34000c00) at /home/greatdb/sql/sql_union.cc:1169
#4 0x0000555559094452 in Query_expression::execute (this=0x7fff3429ae08, thd=0x7fff34000c00)
at /home/greatdb/sql/sql_union.cc:1305
#5 0x0000555558fd4b18 in Sql_cmd_dml::execute_inner (this=0x7fff3429cf68, thd=0x7fff34000c00)
at /home/greatdb/sql/sql_select.cc:810
#6 0x0000555558fd3f24 in Sql_cmd_dml::execute (this=0x7fff3429cf68, thd=0x7fff34000c00)
at /home/greatdb/sql/sql_select.cc:578
#7 0x0000555558f4ac03 in mysql_execute_command (thd=0x7fff34000c00, first_level=true)
at /home/greatdb/sql/sql_parse.cc:4784
#8 0x0000555558f4cd80 in dispatch_sql_command (thd=0x7fff34000c00, parser_state=0x7fffe82ab990,
update_userstat=false) at /home/greatdb/sql/sql_parse.cc:5384
#9 0x0000555558f42257 in dispatch_command (thd=0x7fff34000c00, com_data=0x7fffe82acb70,
command=COM_QUERY) at /home/greatdb/sql/sql_parse.cc:1992
#10 0x0000555558f405c7 in do_command (thd=0x7fff34000c00)
at /home/greatdb/sql/sql_parse.cc:1440
#11 0x0000555559163f7e in handle_connection (arg=0x55556091c920)
at /home/greatdb/sql/conn_handler/connection_handler_per_thread.cc:307
#12 0x000055555ad85edf in pfs_spawn_thread (arg=0x5555607808c0)
at /home/greatdb/storage/perfschema/pfs.cc:2899
#13 0x00007ffff77a6609 in start_thread (arg=<optimized out>) at pthread_create.c:477
#14 0x00007ffff76cb163 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
对于非表字段的内容显示格式取决于什么呢?继续找:
代码语言:javascript复制mysql> select 'abcd' from varb;
输入该命令后找到相关字符显示的代码,对于非表字段的内容取决于结果是否STRING_RESULT,'abcd'
属于Item_string,result_type()=STRING_RESULT
,所以显示字符格式是collation.collation
。
class Item
的成员函数如下:
virtual const CHARSET_INFO *charset_for_protocol() {
return result_type() == STRING_RESULT ? collation.collation
: &my_charset_bin;
}
三、代码改造
针对上面介绍的第一种情况改造代码如下:
代码语言:javascript复制mysql> select * from varb;
#class Field的成员函数改成如下,其中system_charset_info=my_charset_utf8_general_ci:
const CHARSET_INFO *charset_for_protocol() const {
return system_charset_info;
}
登录客户端,可以看到结果已经自动显示成字符格式而不是刚才看到的binary
格式。
mysql -h 127.0.0.1 -P3307 -uroot
mysql> select * from varb;
------ ------
| id | bb |
------ ------
| 1 | abcd |
------ ------
1 row in set (0.00 sec)
四、总结
MySQL客户端字符显示依赖charset_for_protocol()
函数,可以根据自己的需求修改该函数的显示方式,方便自己的使用。如果未来新定义Item
或者Field
记得也要相应修改该函数来正确显示数据。
Enjoy GreatSQL :)
《零基础学习MySQL》视频课程
戳此小程序即可直达B站
https://www.bilibili.com/video/BV1Da411W7Va?spm_id_from=333.999.0.0&vd_source=ae1951b64ea7b9e6ba11f1d0bbcff0e4
文章推荐:
- 包拯断案 | 别再让慢sql背锅@还故障一个真相
- 浅析TIMESTAMP类型
- 老司机开车@如何拯救沦陷的MySQL内存少女
- 13. 分布式恢复 | 深入浅出MGR
- 12. 新节点加入MGR集群过程解读 | 深入浅出MGR
关于 GreatSQL
GreatSQL是由万里数据库维护的MySQL分支,专注于提升MGR可靠性及性能,支持InnoDB并行查询特性,是适用于金融级应用的MySQL分支版本。
Gitee: https://gitee.com/GreatSQL/GreatSQL
GitHub: https://github.com/GreatSQL/GreatSQL
Bilibili:
https://space.bilibili.com/1363850082/video