MySQL中sp运行check表版本更新流程解析

SQL 视图 10 个实战场景:从创建到更新,含 WITH CHECK OPTION 详解 本文详细介绍了SQL视图的10个实战应用场景,从基础创建到高级特性如WITH CHECK OPTION的使用。通过多表查询、数据安全控制和性能优化等实例,帮助开发者掌握视图在数据库开发中的灵活运用,提升查询效率和数据管理能力。特别解析了WITH CHECK OPTION在确保数据完整性方面的重要作用。 阅读详情
  • GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源。
  • GreatSQL是MySQL的国产分支版本,使用上与MySQL一致。
  • 作者: wuyy
  • 文章来源:GreatSQL社区原创

目录

  • MySQL的sp运行SQL语句两个步骤介绍
  • 代码跟踪
  • 知识应用
  • 总结

一、MySQL的sp运行sql语句两个步骤介绍

MySQL的sp运行SQL语句需要执行2个步骤:prepare和execute。第一次执行的时候先执行prepare,进行相关语句parse、itemize、fix_fields等操作,然后才开始进行execute操作。等第二次再执行该sp的时候就直接运行execute而不需要再次进行重复的prepare操作,这样可以节省sp运行时候重复prepare的开销。但是,对于表操作就有一个问题产生,那就是如果执行第二遍的时候表的结构发生改变了,那么不进行reprepare而直接execute是会发生错误的。因此,本文章的目的在于寻找sp多次运行时候如何确认表版本更新并进行正确的操作。

先看下面的例子:
CREATE TABLE t1 (a INT, b VARCHAR(10));
INSERT INTO t1 VALUES (1,'11');
INSERT INTO t1 VALUES (2,'21');
MySQL> select * from t1;
+------+------+
| a    | b    |
+------+------+
|    1 | 11   |
|    2 | 21   |
+------+------+
2 rows in set (0.01 sec)
DELIMITER $$
CREATE PROCEDURE p1()
BEGIN
update t1 set b='aa' where a=1;
END $$
DELIMITER ;
MySQL> call p1; #这里第一次操作,因此会先执行update这句SQL的prepare再进行execute。
Query OK, 1 row affected (0.05 sec)

MySQL> select * from t1;
+------+------+
| a    | b    |
+------+------+
|    1 | aa   |
|    2 | 21   |
+------+------+
2 rows in set (0.01 sec)
MySQL> call p1; #这里第二次操作,直接执行update这句SQL的execute。
Query OK, 0 rows affected (13.78 sec)

#接着我们执行表结构的更新。
MySQL> alter table t1 add i int;
Query OK, 0 rows affected (0.41 sec)
Records: 0  Duplicates: 0  Warnings: 0

#然后再次执行sp,就会发现这次执行了这句SQL的prepare再进行execute。
MySQL> call p1;
Query OK, 0 rows affected (34.24 sec)

二、代码跟踪

现在跟踪一下这个sp看看上面在哪里check表版本并且能正确执行reprepare的。

#首先看一下这个sp涉及的instr。
MySQL> show procedure code p1;
+-----+---------------------------------------+
| Pos | Instruction                           |
+-----+---------------------------------------+
|   0 | stmt "update t1 set b='aa' where a=1" |
+-----+---------------------------------------+
1 row in set (0.01 sec)
可以看到这个sp只涉及了sp_instr_stmt::execute的运行,因此跟踪一下代码找到sp_lex_instr::validate_lex_and_execute_core,可以发现这个函数里面有一个无限while循环,如果发现is_invalid()的话就重新执行parse动作,如果!is_invalid()就直接执行exec_core,这个跟上面的运行步骤就对的上了。但是表结构变更后在哪里被判定为rc=true的呢,那就从reset_lex_and_exec_core这个函数继续跟踪下去。
bool sp_lex_instr::validate_lex_and_execute_core(THD *thd, uint *nextp,
                                                 bool open_tables) {
  while (true) {
    if (is_invalid() || (m_lex->has_udf() && !m_first_execution)) {
      LEX *lex = parse_expr(thd, thd->sp_runtime_ctx->sp);
    }
    bool rc = reset_lex_and_exec_core(thd, nextp, open_tables);
    if (!rc) return false;
    thd->clear_error();
    invalidate();
  }
}
#跟踪代码发现有一个check_and_update_table_version函数是用来check表版本是否一致的
#打印堆栈看一下代码调用过程:
Thread 51 "mysqld" hit Breakpoint 6, check_and_update_table_version (thd=0x7fff70001060, tables=0x7fff702c4e20, 
    table_share=0x7fff70297640) at /mysql/sql/sql_base.cc:3722
3722   if (!tables->is_table_ref_id_equal(table_share)) {
(gdb) bt
#0  check_and_update_table_version (thd=0x7fff70001060, tables=0x7fff702c4e20, table_share=0x7fff70297640)
    at /mysql/sql/sql_base.cc:3722
#1  0x0000000003340f71 in open_and_process_table (thd=0x7fff70001060, lex=0x7fff702c2650, tables=0x7fff702c4e20, 
    counter=0x7fff702c26a8, prelocking_strategy=0x7fffec2e7478, has_prelocking_list=false, ot_ctx=0x7fffec2e7368)
    at /MySQL/sql/sql_base.cc:5223
#2  0x000000000333f788 in open_tables (thd=0x7fff70001060, start=0x7fffec2e7488, counter=0x7fff702c26a8, flags=0, 
    prelocking_strategy=0x7fffec2e7478) at /mysql/sql/sql_base.cc:5968
#3  0x0000000003343c96 in open_tables_for_query (thd=0x7fff70001060, tables=0x7fff702c4e20, flags=0)
    at /MySQL/sql/sql_base.cc:6958
#4  0x0000000003514334 in Sql_cmd_dml::execute (this=0x7fff702c6138, thd=0x7fff70001060)
    at /MySQL/sql/sql_select.cc:543
#5  0x0000000003475097 in mysql_execute_command (thd=0x7fff70001060, first_level=false)
    at /MySQL/sql/sql_parse.cc:3832
#6  0x00000000033075c6 in sp_instr_stmt::exec_core (this=0x7fff70249a80, thd=0x7fff70001060, nextp=0x7fffec2eac38)
    at /MySQL/sql/sp_instr.cc:1008
#7  0x00000000033052ed in sp_lex_instr::reset_lex_and_exec_core (this=0x7fff70249a80, thd=0x7fff70001060, 
    nextp=0x7fffec2eac38, open_tables=false) at /mysql/sql/sp_instr.cc:457
#8  0x00000000033060a4 in sp_lex_instr::validate_lex_and_execute_core (this=0x7fff70249a80, thd=0x7fff70001060, 
    nextp=0x7fffec2eac38, open_tables=false) at /mysql/sql/sp_instr.cc:741
#9  0x0000000003306748 in sp_instr_stmt::execute (this=0x7fff70249a80, thd=0x7fff70001060, nextp=0x7fffec2eac38)
    at /MySQL/sql/sp_instr.cc:925
#10 0x00000000032f4d74 in sp_head::execute (this=0x7fff7018e7a0, thd=0x7fff70001060, merge_da_on_success=true)
    at /MySQL/sql/sp_head.cc:2272
#11 0x00000000032f80e1 in sp_head::execute_procedure (this=0x7fff7018e7a0, thd=0x7fff70001060, args=0x0)
    at /MySQL/sql/sp_head.cc:2977
#可以发现open_tables函数调用了这个函数,这个函数调用了ask_to_reprepare,
#在sp运行中这个ask_to_reprepare返回的是true。因此这里就解开了之前的问题,
#为何表版本更新了会return true然后重新进行parse操作。
static bool check_and_update_table_version(THD *thd, TABLE_LIST *tables,
                                           TABLE_SHARE *table_share) {
  if (!tables->is_table_ref_id_equal(table_share)) {
    /*
      Version of the table share is different from the
      previous execution of the prepared statement, and it is
      unacceptable for this SQLCOM.
    */
    if (ask_to_reprepare(thd)) return true;
    /* Always maintain the latest version and type */
    tables->set_table_ref_id(table_share);
  }
  return false;
}

三、知识应用

如果想开发一种动态表类型,需要每次执行sp都重新parse这个表,那就可以借用这个ask_to_reprepare函数来保证多次执行sp的时候都会进行重新reprepare。

四、总结

在MySQL的sp操作中涉及表操作的sql语句一定会执行check_and_update_table_version这个函数,每次会根据这个函数的结果来确定要不要重新parse该sql语句,如果没有版本改变就直接进行execute操作,如果有改变就重新parse,先prepare再execute,这样可以保证每次执行sp的SQL语句的时候表结构一定是最新的。

Enjoy GreatSQL 😃

关于 GreatSQL

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

相关链接: GreatSQL社区 Gitee GitHub Bilibili

GreatSQL社区:

image

社区有奖建议反馈: https://greatsql.cn/thread-54-1-1.html

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

社区2022年度勋章获奖名单: https://greatsql.cn/thread-184-1-1.html

(对文章有疑问或者有独到见解都可以去社区官网提出或分享哦~)

openEuler 22.03 SP4实战指南:静态IP配置、ARM兼容与UKUI桌面排障 操作系统是数字基础设施的底层基石,其服务模型、架构适配与启动机制直接决定系统稳定性与运维效率。openEuler并非Ubuntu或CentOS的替代品,而是面向全场景数字底座设计的‘服务原子化’系统,强调组件可插拔、资源粒度可控及跨架构深度兼容。其技术价值体现在对ARM服务器、国产GPU、信创硬件的原生支持,支撑金融核心迁移、边缘网关升级、政务云部署等高要求场景。实践中,‘欧拉系统配置静态IP’失败多因NetworkManager与systemd-networkd双栈冲突,‘openeuler ukui 进 阅读详情

相关推荐

SQL建表设计核心指南:从CREATE TABLE到生产级表管理

数据库表结构是数据系统稳定运行的根基,CREATE TABLE不仅是语法操作,更是业务建模与数据治理的起点。理解字段类型选择原理(如NVARCHAR vs VARCHAR、BIGINT主键必要性)、约束机制(CHECK/NOT NULL/外键)和索引设计逻辑(覆盖索引、聚簇索引影响),能显著提升查询性能与数据一致性。在金融、电商、医疗等高要求场景中,建表决策直接影响分库分表扩展性、跨时区时间处理、敏感字段加密合规等关键能力。本文聚焦SQL建表全生命周期实践——涵盖CREATE TABLE规范、ALTER T

cuiji1279的博客 496

mysql存储过程的创建,删除,调用及其他常用命令

mysql存储过程的创建,删除,调用及其他常用命令 一.创建存储过程 1.基本语法:create procedure sp_name() begin ……… end 例:create procedure zp() BEGIN      SELECT * from a;         END 2.参数传递 二.调用存储过程 1.基本语法:call sp_name

zygzzp的专栏 1634

MySQL存储过程实战:高性能强一致性数据操作指南

MySQL存储过程是一种在数据库服务端预编译、缓存执行计划的可编程SQL对象,其核心原理是将多步DML操作封装为原子性事务单元,规避网络开销与应用层ORM陷阱。相比普通SQL脚本,它通过执行计划复用显著提升高频调用性能,并依托FOR UPDATE行锁与事务控制保障强一致性。技术价值体现在降低连接池压力、消除N+1查询、统一错误处理与并发安全控制。典型应用场景包括电商下单、资金转账、库存扣减及定时报表聚合等需多表协同与数据准确性的业务逻辑。本文深入解析CREATE PROCEDURE定义规范、CALL调用机制

weixin_33798152的博客 374

使用shell脚本调用mysql数据库存储过程,并设置定时任务

本来是要mysql数据库中创建事件任务来,定时执行存储过程,做数据传输的。。。后来由于种种原因,就使用crontab来定时执行,调用存储过程。实现这个数据传输分为两步:第一步:编写shell脚本调用mysql数据库存储过程,如下:#!/bin/bash#0 1 * * * sh /home/drmTrans3/rj_proc.shhost1=127.0.0.1user=sys...

weixin_34258078的博客 874

数据库课程设计实战:宾馆管理系统表结构与核心SQL解析

数据库设计是任何业务信息系统的基石,它决定了数据如何被有效组织、关联与查询。在MySQL等关系型数据库的实践中,我们通过表结构设计、主外键约束、范式优化来构建稳定高效的数据模型,并借助索引提升查询性能,利用视图、触发器、存储过程与事务来处理复杂业务规则与并发控制。这些技术不仅是后端开发的核心能力,更是数据库课程设计中最关键的评分点。以经典的宾馆管理系统为例,它涵盖了多表关联、状态流转、账单统计等真实业务场景,是练习数据库设计与SQL编程的绝佳载体。从梳理顾客、房间、预订、入住等实体关系,到编写建库建表脚本和

weixin_34417183的博客 408

从‘静态拍照’到‘动态录像’:用Malmquist指数讲好你的效率变化故事(附Stata/R代码)

本文深入探讨了如何利用Malmquist指数构建动态效率分析框架,从静态数据到动态叙事的转变。通过分解技术效率变化(EC)和技术进步(TC),结合Stata/R代码实现四种动态可视化方法,帮助研究者更直观地展示效率变化的动态特征。文章还提供了诊断性叙事结构和比较叙事技巧,助力决策者理解效率提升的来源与趋势。

weixin_32678995的博客 603

mysql 调sp_mysql 基本操作

***********************************************************************关于MySQL的练习create tableStudent(Snoint primary key not null,--学号主键Sname varchar(50) not null,--学生姓名Ssex varchar(50) not null,--学生性别...

weixin_39683025的博客 276

企业微信群机器人Webhook配置全攻略:从创建到发送消息的完整流程

本文详细解析了企业微信群机器人的Webhook配置全流程,从创建机器人、获取关键Webhook地址,到使用代码发送文本、Markdown等多种消息类型。内容涵盖安全加固、错误处理及与CI/CD等系统集成的实战指南,帮助企业快速构建高效、稳定的内部通知系统。

ik678901的博客 1783

MySQL存储过程SP详解

为什么80%的码农都做不了架构师?>>> ...

weixin_33958585的博客 1055

figma MCP + cursor如何将设计稿生成前端页面

Figma MCP配置与代码生成指南 本文详细介绍了如何在Cursor中配置Figma MCP(多上下文处理器)的完整流程:从获取Figma API密钥、设置MCP服务器配置,到添加代码生成规则。关键步骤包括生成Figm a个人访问令牌、配置cursor settings文件、启用MCP服务,以及设置代码规则(包含TypeScript/Vue技术栈规范、BEM命名规则等)。最后提供了将Figma设计稿转化为Vue页面的prompt模板,涵盖文件结构、图片处理、样式规范等具体要求,确保生成代码与设计稿高度一致

weixin_45644355的博客 2908

OCSP环境搭建--Windows Server 2016

OCSP环境搭建--Windows Server 2016 一. OCSP环境中相关信息 1. 服务器1 操作系统:Win Server 2016 Standard版 IP地址:172.16.0.19/23,网关:172.16.0.1,首选DNS:127.0.0.1 服务器角色:域控制器、证书颁发机构、radius服务器、DNS服务器 ...

CsdnCHong_566的博客 3351

mysql sp_rename_【转】SQL SERVER 中 sp_rename 用法

因需求变更要改表的列名,平常都是跑到Enterprise manager中选取服务器->数据库->表,然后修改表,这样太麻烦了,查了一下,可以用script搞定,代码如下:EXEC sp_rename '表名.[原列名]', '新列名', 'column'Transact-SQL 参考sp_rename --更改当前数据库中用户创建对象(如表、列或用户定义数据类型)的名称。语法sp_r...

weixin_39914243的博客 445

单片机课程设计——交通灯

单片机课程设计——交通灯一、课程设计主要内容1.1 题目1.2摘要1.3关键词二、设计要求三、设计方案四、参考电路设计4.1.1数码管的设计4.1.2对应程序4.2.1独立按键的设计4.2.2对应程序4.2.3 使用逻辑4.3.1LED模块的设置4.3.2 LED实物图4.3.3 LED显示程序五、调试要点5.1 单片机最小系统5.2 数码管模块5.3 LED模块5.4 独立按键六、总结七、成品图完整程序 一、课程设计主要内容 1.1 题目 交通灯设计 1.2摘要 近年来,随着我国国民经济的快速发展,我国机

PKPROTEUS的博客 3万+

MySQL实战指南:索引与视图的高效应用

本文深入探讨了MySQL中索引与视图的高效应用。索引作为数据库查询的“高速公路”,通过B+树结构大幅提升查询效率,但需权衡空间与维护成本。视图则作为封装复杂查询的“虚拟表”,简化开发并提升数据安全性。文章结合实战案例,详细解析了索引的创建、管理与优化策略,以及单表与多表视图的创建与使用,帮助开发者掌握提升数据库性能与开发效率的核心技术。

m3n5b7v8c9x的博客 443

从‘包饺子’到‘包络线’:一个生活化比喻讲透长期与短期成本决策

本文通过饺子馆经营的生活化比喻,深入浅出地解析了长期与短期成本决策的核心逻辑。从调整人力(可变成本)到扩建厨房(固定成本),揭示了包络线理论在商业决策中的实际应用,帮助企业主在规模经济与成本控制间找到平衡点。

weixin_32006655的博客 339

从波士顿动力SpotMini拆解看四足机器人机械设计:关节布局与电机选型的5个关键决策点

本文深入解析波士顿动力SpotMini四足机器人的机械设计,聚焦关节布局与电机选型的5个关键决策点。通过拆解髋关节偏移距、膝关节传动链、电机热管理等核心设计,揭示商业级四足机器人的工程智慧,为工业巡检、物流机器人等应用提供实用参考。

postgres8guard的博客 893

MySQL事务深度解析:从ACID到并发控制的完整实现机制

MySQL事务机制通过ACID特性、隔离级别、日志系统与锁机制,构建了高可靠的数据操作体系。实际开发中需结合业务场景选择隔离级别,优化事务粒度,并关注死锁与性能瓶颈。

qq_21330821的博客 786

ARM交叉编译gdbserver并远程在线调试

arm-linux平台。5、生成完整的makefile,新建full_install,执行 ./configure --target=arm-linux-gnueabihf --host=arm-linux-gnueabihf --program-prefix=arm-linux-gnueabihf- CC=arm-linux-gnueabihf-gcc --prefix=/home/geyuxi/Documents/full_install。如果--host和--build不同,是交叉编译;

wangjie36的博客 3168

数据库——MySQL

MySQL数据库基础教程全面介绍了关系型数据库的核心概念和操作。

qq_46518480的博客 417

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

Ubuntu 16.04 LAMP 部署避坑指南:Apache MySQL PHP 版本兼容与配置陷阱

LAMP 是 Linux 下经典的 Web 开发栈,其核心在于 Linux、Apache、MySQL 和 PHP 四组件的协同工作。理解各版本间的兼容性原理至关重要——例如 Apache 的 MPM 模块选择直接影响 PHP 运行模式,MySQL 5.7 默认严格模式会中断依赖宽松语法的老代码,而 PHP 7.0 废弃 mcrypt 等扩展则要求开发者转向 openssl 等现代替代方案。这些技术细节共同决定了环境的稳定性与可维护性。在 Ubuntu 16.04 这一处于生态断层带的 LTS 版本中,上述问

aofan9566的博客 419

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

MYSQL SQL 执行系列2

-> open_and_process_table (为 Table_ref 获取 MDL 锁并打开表或视图)|-> open_table (对于基表)-> open_table (对于基表)所以open_table是真正打开一个的地方(视图、派生表、临时表有其他处理函数)。是 MySQL 服务器中的核心分发函数。它接收已经解析并填充好的LEX结构(语法树),根据的值(如等),调用相应的内部处理函数完成实际的数据操作、元数据变更或管理命令。该函数位于之后,是查询执行流程的最终入口。

Piemon&Anokata的博客 299

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

MySQL存储过程实战:从基础到高级优化

存储过程是数据库编程中的重要技术,它通过预编译SQL语句集合实现高效的数据操作。其核心原理是将业务逻辑封装在数据库层,通过减少网络传输和重复解析提升执行效率。在MySQL等关系型数据库中,存储过程支持变量声明、流程控制、异常处理等编程特性,能够有效降低应用层复杂度。典型应用场景包括报表生成、订单处理、定时任务等需要复杂数据操作的业务场景。本文以电商系统为例,详细解析存储过程在分页查询、事务管理、性能优化等方面的工程实践,特别针对高并发场景下的库存扣减等热点问题提供解决方案。

weixin_34396902的博客 362

mysql + mha + keepalive + vip_MYSQL + MHA +keepalive + VIP安装配置(二)--MHA的配置

一、总概1、MHA介绍MHA(Master High Availability)是自动的master故障转移和Slave提升的软件包.它是基于标准的MySQL复制(异步/半同步).MHA有两部分组成:MHA Manager(管理节点)和MHA Node(数据节点).MHA Manager可以单独部署在一台独立机器上管理多个master-slave集群,也可以部署在一台slave上.MHA Mana...

weixin_39818631的博客 278

MYSQL SQL 执行系列1

0)摘要(digest)是 SQL 语句规范化后的哈希,用于 performance_schema 中的语句统计和慢查询日志中的样本记录。如果全局变量非零(表示启用 digest 收集),则通知词法分析器在解析过程中计算 digest。

Piemon&Anokata的博客 395
上一篇: MySQL 8.0.32如期而至
下一篇: “采访”ChatGPT看看它对我们GreatSQL社区有什么看法
GreatSQL社区
博客等级 码龄5年 1210粉丝 390原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值