暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

包拯断案 | collation带来的影响剖析@还故障一个真相

万里数据库 2023-08-09
190
作为DBA运维的你是否有过这些苦恼:





















现如今,DBA们在维护数据库实例(MySQL技术路线)时,面对字符集似乎已默认选择utf8 这个事情,是否关注过collation?


作为一名DBA运维人员,有时候会遇到一些我们无从下手的灵异现象。

例如:程序访问数据库每隔一段时间就会出现中断,时间可能固定或不固定,自己的三板斧抡完之后仍不奏效,求助开发,开发表示己方无错,夹在中间的你该如何处理?



心中有章,遇事不慌


如果我们第一次(或多次)遇到无法解决的问题该如何处理呢?可以关注公众号,关注《包拯断案》专栏让小编为你排忧解难~


包拯秘籍:

一整套故障排错及应对策略送给你,让你像包拯一样断案如神:

#首先

我们碰到此问题之后,要做到心中有章(章程),遇事不慌。一定要冷静,仔细了解故障现象(针对开发/用户反馈的问题,仔细沟通故障现象、操作流程、数据库架构等信息);

#其次

我们需要根据故障现象进行初步分析,先判断是程序问题还是基础服务问题;

#然后

结合上述思考,我们需要进行逐步验证并排除,并确定问题排查方向;

#接着

确定了问题方向,针对具体问题进行具体分析通过现象得出部分结论,通过部分结论继续进行排查及论证;

#最后  

针对问题有了具体分析,并进行线下复现,从而梳理故障报告。


真实案例,我们能赢


说了这么多理论,想必实践更让你心动。

那么我们就拿一个真实案例进行分析:

某客户在GreatDB准生产环境调试存储过程时,其中有一个存储过程执行call proc报“ERROR 1267 (HY000): Illegal mix of collations (utf8mb4_0900_bin,IMPLICIT) and (utf8mb4_bin,IMPLICIT)”,但反馈测试环境没问题。


2.1 故障处理场景

夫耳闻之,不如目见之;目见之,不如足践之;足践之不如手辨之。


故障背景:

业务模拟割接调试存储过程中,发现call procedure时报ERROR 1267 (HY000): Illegal mix of collations (utf8mb4_0900_bin,IMPLICIT) and (utf8mb4_bin,IMPLICIT)”错误,反馈测试环境没问题。


以下涉及到的信息均为自测模拟数据:





收到信息10s后:询问调用存储过程的基础信息(包含:存储过程名、库名、实例环境信息)


收到信息20s后:存储过程使用的collations是什么,为什么会产生不一致?

发送命令:

    show create   procedure gobench1_proc\G


    大脑回复:该存储过程字符集使用的是utf8mb4,校验集用的是utf8mb4_bin


      信息如下:

      greatdb> show create procedure gobench1_proc\G
      *************************** 1. row ***************************
      Procedure: gobench1_proc
      sql_mode: ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
      Create Procedure: CREATE DEFINER=`pcms`@`%` PROCEDURE `gobench1_proc`(sid varchar(10))
      begin
      select count(*) from info where NAME = sid;
      end
      character_set_client: utf8mb4
      collation_connection: utf8mb4_0900_ai_ci
      Database Collation: utf8mb4_bin
      1 row in set (0.00 sec)


      收到信息50s后:GreatDB全局校验集是什么?

      发送命令:

        show global   variables like "%coll%";


        大脑回复:GreatDB默认库级别的utf8mb4_0900_bin校验集


         输出信息

          greatdb>     show global variables like "%coll%";
          +-------------------------------+--------------------+
          | Variable_name | Value |
          +-------------------------------+--------------------+
          | collation_connection | utf8mb4_0900_bin |
          | collation_database | utf8mb4_0900_bin |
          | collation_server | utf8mb4_0900_bin |
          | default_collation_for_utf8mb4 | utf8mb4_0900_ai_ci |
          +-------------------------------+--------------------+
          4 rows in set (0.01 sec)



          收到信息70s后:存储过程中是否有字符串比较,存储过程参数传输是否有差异?

          发送命令:

            show create   procedure gobench1_proc\G


            大脑回复: 存储过程中涉及到几个表的查询,where条件中涉及到字符串比较


            收到信息100s后:查看涉及到的表的字符集和校验集是什么?

            发送命令:

              select   TABLE_COLLATION from information_schema.tables where   table_schema='collation_dbs' and table_name in ('info');


              大脑回复:表collation使用的也是utf8mb4_bin


              收到信息120s后:查看存储过程涉及的表的校验集

              发送指令:

                select   table_schema,table_name,COLUMN_NAME,COLLATION_NAME from COLUMNS where table_schema   = 'collation_dbs' and TABLE_NAME in ('info') and COLLATION_NAME
                AME like "utf8%";


                大脑回复:表中字符串列使用的是utf8mb4_0900_bin


                收到信息200s后:为什么库、表、存储过程的校验集和实例默认校验集不一致?

                发送指令:

                查看GreatDTS迁移工具在做表结构转换时,是否默认指定

                大脑回复:经过排查和确认,GreatDTS转换表结构并未指定collation


                收到信息250s后:表的字符集和校验集是哪来的?

                发送指令:

                查看库的校验集和表的校验集一致,进行测试,schema的校验集优先集比全局校验集高

                大脑回复:当建库时如果指定校验集,则创建表时不指定校验集会默认继承库的校验集,而不是全局校验集


                收到信息300s后:库的校验集哪来的?

                发送指令:

                测试-GreatDTS迁移工具创建库时是否指定了校验集

                大脑回复:GreatDTS迁移工具创建库时会指定一个校验集,校验集为utf8mb4_bin,导致表的校验集也是utf8mb4_bin


                (故障已定位并反馈,进行相应应急处理...)


                问题原因:

                因为使用GreatDTS迁移工具在做去O的表结构转换时,如果库不存在,则会默认创建库。


                在创建库时指定了字符集和校验集(字符集为utf8mb4,校验集为utfmb4_bin),表结构转换时不指定校验集和字符集,所以表的字符集和校验集继承了库,同时列的字符串校验集也会继承表的校验集,创建存储过程时默认列的校验集会继承库的校验集。


                处理手段:

                方法1:临时处理

                如果存储过程中用到的条件列比对只涉及一个表,或多个表条件列都是同一个校验集,那么可以通过session collation来规避;


                方法2:永久处理

                如果存储过程中用到的条件列对比涉及多个表,且条件列的校验集都不相同,那么需要重建表结构,将所有的字符串相关的列、库、表、存储过程、视图等的校验集都对齐。


                经过上述一顿猛如虎的操作和排查,5分钟内快速定位了问题原因,且及时和客户业务方进行沟通,最大化地减少并避免了业务受到的影响。



                同时,在故障排查过程中,保留了排查步骤及结果图,故障处理完成后进行故障报告编写,全流程专业、顺畅、有序的操作得到了客户的认可与肯定。




                整体项目运维经验复盘:


                1)本次故障主要由于第三方工作做表结构迁移导致;

                2)指定数据库运行环境及运行状态需要定期巡检;

                3)需增加相关参数的定期监控;

                4)要将根据巡检项开发自动化运维脚本与告警相结合。




                番外篇-展昭答疑解惑


                1)为什么列的校验集和表的还不一致?

                答:由于时间紧迫,且该环境有多人操作,可能导致列无法追查,也有可能做过alter table语句,做过业务适配修改。


                2)为什么100多个存储过程,只有这一个存储过程有问题?

                答:存储过程中如果不涉及到表列的比较,且校验集一致,则不会存在该问题。





                包拯断案 | 揭晓Linux下CPU利用率过高的谜底与方法@还故障一个真相

                包拯断案 | create connections failed的深度剖析@还故障一个真相

                包拯断案 | 别再让慢sql背锅@还故障一个真相


                关于万里数据库


                北京万里开源软件有限公司(简称“万里数据库”)成立于 2000 年,是专注于国产自主可控数据库产品研发的国家高新技术企业,拥有发明专利、软件著作权百余项。


                万里数据库的技术底蕴源自对底层核心代码的掌控,产品始终坚持以“极致稳定、极致性能、极致易用”为目标,经过20余年的研发经验积累,产品在功能、性能、稳定、易用等方面均处于行业领先水平,广泛应用于金融、运营商、能源、政府、交通等行业重要业务系统中的超 1000个业务场景,得到了用户和市场的认可与肯定。


                2021 年,公司创立 GreatSQL 开源社区,通过对 MySQL技术的优化,目前已成长为国内活跃的自主开源数据库社区


                极致稳定  极致性能  极致易用




                “在看”点一下,万里早知道

                文章转载自万里数据库,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                评论