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

南方朱雀
• 阅读 134

本篇文章记录的是遇到一个未知错误的排查过程,由于本人水平有限,如有描述不正确的欢迎指正。

问题描述

开发报错
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/ref...

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

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

可以看到对应的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

MySQL DBA如何

用户查询一个表的数据时,首先会构造根据库名、表名等信息构造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

MySQL DBA如何

MySQL DBA如何

调试过程:
MySQL DBA如何

这里我们只需要将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/6x...

点赞
收藏
评论区
推荐文章
MySql索引下推知识分享
作者:刘邓忠Mysql是大家最常用的数据库,下面为大家带来mysql索引下推知识点的分享,以便巩固mysql基础知识,如有错误,还请各位大佬们指正。1什么是索引下推索引下推(IndexConditionPushdown,索引条件下推,简称ICP),是MyS
梦
4年前
微信小程序new Date()转换时间异常问题
微信小程序苹果手机页面上显示时间异常,安卓机正常问题image(https://imghelloworld.osscnbeijing.aliyuncs.com/imgs/b691e1230e2f15efbd81fe11ef734d4f.png)错误代码vardate'2021030617:00:00'vardateT
Wesley13 Wesley13
3年前
MySQL基础(一)
一、连接MySQL数据库1连接:2mysqlhhostuuserp34常见错误:5ERROR2002(HY000):Can'tconnecttolocalMySQLserverthroughsocket'/tmp/my
Stella981 Stella981
3年前
IntelliJ Idea解决Could not autowire
IntelliJIdea解决Couldnotautowire.Nobeansof'xxxx'typefound的错误提示1.问题描述  在Idea的spring工程里,经常会遇到
Wesley13 Wesley13
3年前
MySQL 3534 服务无法启动 服务没有报告任何错误
报告任何错误的经验。相信很多人都遇到过安装Mysql的时候出现各种各样的问题,今天小编就教大家解决window下mysql服务没有报告任何错误的情况下无法启动的问题。本文所用的mysql版本是5.7以上版本,解决方法:!(https://oscimg.oschina.net/oscnet/a9fc843debd06560feaa576f8743
Wesley13 Wesley13
3年前
mysql错误:The MySQL server is running with the
本文为大家讲解的是mysql错误:TheMySQLserverisrunningwiththeskipgranttablesoptionsoitcannotexecutethisstatement解决方法,感兴趣的同学参考下。错误描述:mysql grantalloncactidb.\todbuser
Wesley13 Wesley13
3年前
Java线程阻塞方法sleep()和wait()精炼详解
版权声明:因为个人水平有限,文章中可能会出现错误,如果你觉得有描述不当、代码错误等内容或者有更好的实现方式,欢迎在评论区告诉我,即刻回复!最后,欢迎关注博主!谢谢https://blog.csdn.net/weixin\_41101173/article/details/79889464一、前期基础知识储备sleep()和wait()方法都是Ja
Wesley13 Wesley13
3年前
MySql在触发器中调用存储过程
不太写触发器,今天遇到个语法问题,在朋友(DBA)的帮助下解决了,记录下来。需求:在CLASS\_PROPERTY\_REL删除记录时,调用存储过程gen\_ci\_property\_value问题反馈:SQL错误106442000:YouhaveanerrorinyourSQLsyntax;check
Wesley13 Wesley13
3年前
MySQL外键的个人理解
问题起因:这几天在建表的时候遇到的问题,想试一试插入一下外键,结果折腾了半天,找了不少资料,闹了不少笑话。如果文章写的有问题,请及时指正我的错误,谢谢了。问题描述:错误理解:原来我一直以为,两个表只要存在相同的列就可以把他设成外键,这个想法是错误的。问题解决:查了不少的资料,外键约束(FOREIGNK
Wesley13 Wesley13
3年前
openstack页面自定义插件使用详解(django、ajax、post)(zTree为例)
感谢朋友支持本博客,欢迎共同探讨交流,由于能力和时间有限,错误之处在所难免,欢迎指正!如有转载,请保留源作者博客信息。BetterMe的博客(https://www.oschina.net/action/GoToLink?urlhttp%3A%2F%2Fblog.csdn.net%2Ftantexian):blog.csdn.net/t
十月飞翔 十月飞翔
3年前
9种 OOM 常见原因及解决方案
当JVM内存严重不足时,就会抛出java.lang.OutOfMemoryError错误。本文总结了常见的OOM原因及其解决方法,如下图所示。如有遗漏或错误,欢迎补充指正。1、Javaheapspace当堆内存(HeapSpace)没有足够空间存放新创建的对象时,就会抛出java.lang.OutOfMemoryError:Javahea