文章详情

短信预约信息系统项目管理师 报名、考试、查分时间动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

MySQL DBA如何"土土"地利用源码解决没有遇到过的错误?

2021-03-21 01:35

关注

MySQL DBA如何

问题描述

开发报错

MySQL error code 1615 (ER_NEED_REPREPARE): Prepared statement needs to be re-prepared

排查过程

乍一看,没见过这个错误啊,用大腿想了下这个应该是php程序为了防止SQL注入用的prepare执行的。赶紧官方bug搜了一下,一通操作以后路由到了如下地址:https://dev.mysql.com/doc/refman/5.5/en/statement-repreparation.html

简单看了一下,大概意思就是after prepare before execute的阶段,对应的表进行了DDL或者FLUSH TABLES以后table definition cache里面的metadata信息发生了改变,需要reprepare。

接着我搜了一下源码,关键字re-prepare,然后我看到官方test套件里有相关的测试。

可以看到对应的worklog为4166
拿到worklog id以后,我赶紧去官方的work log下搜,在High Level Architecture标签下,我注意到了下面几行:

Prepared_statement::execute_loop() -- try to execute

找到了对应的入口函数:
Prepared_statement::execute_loop()
主要抛出错误位置如下:

 if ((sql_command_flags[lex->sql_command] & CF_REEXECUTION_FRAGILE) &&

注意一下观察者Reprepare_observer定义

/**

注释里写的非常明显,

check_and_update_table_version() for details of the

所以我们主要目光聚集在函数check_and_update_table_version,其定义如下:

/**

从函数check_and_update_table_version中可以看出来,在prepare和execute之间这段时间内,如果table_ref_id(这里的table id其实就是binlog里面的table map event里面的table id,是可以变化的)如果发生了变化,那么需要reprepare。其中还有一点需要注意的是,在prepare之后,会释放对应的MDL锁,所以这个时候是可以进行DDL操作的。那么问题来了,什么情况下,这个table id会发生变化呢?

  1. DDL(包括ALTER/RENAME/TRUNCATE等)

  2. FLUSH TABLES显式地将表定义刷出缓存

  3. TABLE_DEFINITION_CACHE太小,导致对应的表定义缓存被刷出

以上根据自己的经验不完全统计。。。

关于table id

用户查询一个表的数据时,首先会构造根据库名、表名等信息构造hash key,然后从table_def_cache这个hash map中找是否有对应表的缓存,如果存在的话,实例化TABLE_SHARE结构体为TABLE,跟用户交互。如果不存在的话,那么会获取库名、表名等信息存入TABLE_SHARE结构体,在这里生成table_id。
生成table_id的函数如下:

static Table_id last_table_id;

过程模拟

本模拟案例由重庆八怪提供,非常感谢

session 1

session2

prepare xxx

调试过程:

这里我们只需要将reprepare_attempt < MAX_REPREPARE_ATTEMPTS 改为不满足条件即可因此
修改reprepare_attempt变量为3则,reprepare_attempt < MAX_REPREPARE_ATTEMPTS 返回false
进入报错流程而不会重新加载table

总结:

这个问题的本质就是table share 在 prepare 和 execute 之间被重新加载了多次
伪代码逻辑如下:

prepare:reprepare_attempt=0 MAX_REPREPARE_ATTEMPTS=3 :

实际会进行3次执行尝试,如果都失败就会报错。因此自己模拟的话还是比较难模拟的,除非直接gdb set 变量或者在线上高压力下才可能出现。

为解决上述的1615问题,可以通过以下办法:

  1. 增加table_definition_cache,防止表定义被刷出缓存

  2. 增加MAX_REPREPARE_ATTEMPTS次数,但是这个属于hard code,没法通过参数修改

  3. 没事别FLUSH TABLES...(如备份,包括extrabackup和mysqldump获取一致性位点都会做FTWRL,因此建议专门的从库做备份)

作者:徐晨亮

原文链接:https://mp.weixin.qq.com/s/6xLyXIEpWmHh4ahPtRRWpw

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-数据库
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯