• MySQL8.0 show create view BUG解析


    • GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源。
    • GreatSQL是MySQL的国产分支版本,使用上与MySQL一致。
    • 作者:崔弘晨
    • 作者介绍:诺亚财富数据库DBA 擅长数据库SQL优化,喜欢分享技术
    • 文章来源:社区投稿

    背景

    ​ 前段时间碰到一个比较古怪的MySQL Crash事件,当时打了general日志,发现是一条命令show create view造成的,经过反复实验以及查看源码,终于得以复现并找到原因。

    环境如下:

    OS:Centos7.8
    MySQL:8.0.13/8.0.14/8.0.15
    • 1

    复现

    ​ 我在测试环境模拟了一套最简单的复现场景。

    用户权限如下

    root@localhost:[(none)]> show grants for test;
    +-------------------------------------+
    | Grants for test@%                   |
    +-------------------------------------+
    | GRANT USAGE ON *.* TO `test`@`%`    |
    | GRANT `test_role`@`%` TO `test`@`%` |
    +-------------------------------------+
    root@localhost:[(none)]> show grants for test_role;
    +-----------------------------------------------------+
    | Grants for test_role@%                              |
    +-----------------------------------------------------+
    | GRANT USAGE ON *.* TO `test_role`@`%`               |
    | GRANT ALL PRIVILEGES ON `test`.* TO `test_role`@`%` |
    +-----------------------------------------------------+
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    ​ 此处注意role角色是MySQL8.0新增的功能(大概是从oracle借鉴过来的),先将权限赋予role,再将role赋予用户。记得role赋权后用set default role all to user 激活(否则无法复现)。

    视图结构如下

    CREATE ALGORITHM=UNDEFINED DEFINER=`test`@`%` SQL SECURITY DEFINER VIEW `test_show_view` AS select 1 AS `1`

      ​ 这里创建了一个最简单的视图,仅仅执行select 1,然后顺便给大家复习一下视图definer的定义:

      ​ MySQL创建视图等其他对象时有两个选项:definer和invoker,SQL SECURITY { DEFINER | INVOKER } :指明谁有权限来执行。DEFINER 表示按定义者拥有的权限来执行;INVOKER 表示用调用者的权限来执行。默认情况下,系统指定为DEFINER。

      复现Crash

      ​ 先卖个关子,大家看看下两条指令有何不同,为何案例2会引发MySQL崩溃(而且是100%触发)?

      案例1:

      root@localhost:[test]> show create view test.test_show_view\G
      *************************** 1. row ***************************
                      View: test_show_view
               Create View: CREATE ALGORITHM=UNDEFINED DEFINER=`test`@`%` SQL SECURITY DEFINER VIEW `test_show_view` AS select 1 AS `1`
      character_set_client: utf8mb4
      collation_connection: utf8mb4_0900_ai_ci
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6

      案例2:

      root@localhost:[(none)]> show create view test.test_show_view\G
      ERROR 2013 (HY000): Lost connection to MySQL server during query
      • 1

      ​ 眼尖的同学们肯定发现了,案例2没有指定当前DB,是不是觉得很神奇?但的确是这个原因引发的一个bug。

      原因分析

      ​ 首先看errorlog。 ​ 我截取了一些关键信息,错误日志显示是acl_getroot函数上发生的问题以及is an invalid pointer 无效指针造成的Crash.

      file

      ​ 接着我们可以从源码中找出原因(启动Vscode!),调试后发现acl_getroot函数在 build/sql/auth/sql_auth_cache.cc代码里,用处是获取用户ROLE权限,然后出现问题的是在下面这段代码中。

        if (acl_user && sctx->get_active_roles()->size() > 0) {
          sctx->checkout_access_maps();
          ulong db_acl = sctx->db_acl({db, strlen(db)});
          sctx->cache_current_db_access(db_acl);
        }
        DBUG_RETURN(res);
      • 1
      • 2
      • 3
      • 4
      • 5

      ​ 重点在这一句

      ulong db_acl = sctx->db_acl({db, strlen(db)});

        ​ 还记得前面说的吗?复现的情况是没有指定当前db,此时db的值是0x0,sctx->db_acl({db, strlen(db)})直接报错返回空指针,MySQL此时也崩溃了。

        ​ 到这里,我们也终于找了崩溃的原因:因为show create view需要取definer的用户权限,但当用户有角色(role)权限时,且当前db未指定(0x0),会出现无效指针并引发Crash

        ​ 接下来我又去查看下8.0.13后版本是否有修改,发现在8.0.16版本上,此行代码加上了一个判断。

        ulong db_acl = db ? sctx->db_acl({db, strlen(db)}) : 0;

          ​ 也就是当前判断当前db未指定时,直接赋值是0。

          解决方案

          知道了原因,解决方案就很方便商定了

          1. 不使用role角色功能,直接赋予用户权限。
          2. 视图定义上definer直接定义为root@localhost,可以跳过acl_getroot函数。
          3. 升级版本,建议升级至更稳定的8.0.17或者20版本。

          Enjoy GreatSQL :)

          关于 GreatSQL

          GreatSQL是由万里数据库维护的MySQL分支,专注于提升MGR可靠性及性能,支持InnoDB并行查询特性,是适用于金融级应用的MySQL分支版本。

          相关链接: GreatSQL社区 Gitee GitHub Bilibili

          GreatSQL社区:

          捉虫活动详情:https://greatsql.cn/thread-97-1-1.html

          社区博客有奖征稿详情:https://greatsql.cn/thread-100-1-1.html

          6440

        • 相关阅读:
          计算机毕设 opencv python 深度学习垃圾图像分类系统
          dev C++5.11的使用技巧:调试、快捷键等(备战蓝桥杯)
          Bootstrap弹框使用
          elasticsearch配置
          建筑模板的成本如何控制?
          layui的一些问题
          02 【axios fetch 跨域】
          LeetCode 热题 HOT 100 第五十八天 226. 翻转二叉树 简单题 用python3求解
          【控制】自适应控制,对参考信号跟踪,对未知参数估计的小例子,带程序有结果图
          认识计算机中寄存器的本质
        • 原文地址:https://blog.csdn.net/GreatSQL2021/article/details/128189512