MySQL/GreatSQL 游标重解析后条件下推core缺陷深度排查

MySQL-mysqlslap基准测试工具详解 1. 读取配置文件 /etc/mysql/mysqld.cnf2. 连接远程数据库 10.x.x.x:3306(root / Root)3. 选定 mysql 库作为测试库(--create-schema)4. 以 InnoDB 引擎为测试目标(--engine)5. 开启 100 个并发连接(--concurrency)6. 共执行 2000 次 SELECT * FROM user WHERE user='root'(--number-of-queries) 阅读详情

MySQL/GreatSQL 游标重解析后条件下推core缺陷深度排查

一、问题发现

在一次开发中发现当执行需要条件下推cursor重新解析语句之后,会导致数据库core。看下面复现步骤,这里用的是mysql8.4.4的debug版本代码。

1、创建表和View

greatsql> CREATE TABLE tb1 (EMPLOYEE_ID int, FIRST_NAME VARCHAR2(20), LAST_NAME VARCHAR(25), 
EMAIL VARCHAR2(25), PHONE_NUMBER VARCHAR2(20) DEFAULT NULL, HIRE_DATE DATE DEFAULT NULL, 
JOB_ID VARCHAR2(10), SALARY NUMBER(8,2) DEFAULT 1000, COMMISSION_PCT DECIMAL(2,2) DEFAULT NULL,
MANAGER_ID float(6,0), DEPARTMENT_ID NUMBER(4,0),PRIMARY KEY(EMPLOYEE_ID))  ;

greatsql> INSERT INTO tb1 VALUES (145,'John','Russell','JRUSSEL','011.44.1344.429268','2020-3-1','SA_MAN',14000,0.4,100,80);

greatsql> CREATE TABLE tb2 (
  EMPLOYEE_ID int PRIMARY KEY, 
  FIRST_NAME VARCHAR2(20) DEFAULT NULL,
  LAST_NAME VARCHAR(25) DEFAULT NULL,
  EMAIL VARCHAR2(25) DEFAULT NULL,
  PHONE_NUMBER VARCHAR2(20) DEFAULT NULL,
  HIRE_DATE DATE DEFAULT NULL,
  JOB_ID VARCHAR2(10) DEFAULT NULL,
  SALARY NUMBER(8,2) DEFAULT NULL, 
  COMMISSION_PCT DECIMAL(2,2) DEFAULT NULL,
  MANAGER_ID DECIMAL(6,0) DEFAULT NULL,
  DEPARTMENT_ID NUMBER(4,0) DEFAULT NULL
);
greatsql> INSERT INTO tb2 (EMPLOYEE_ID, FIRST_NAME, LAST_NAME, JOB_ID, SALARY, DEPARTMENT_ID)
VALUES (145, 'John', 'Bonus Record', 'SA_MAN', 2000, 80);

greatsql> CREATE VIEW v_tb1 AS
SELECT * FROM (    SELECT * FROM tb1    UNION    SELECT * FROM tb2) AS combined_tables
WHERE DEPARTMENT_ID = 80;

2、创建带有查询view的cursor的存储过程并执行sp

DROP PROCEDURE IF EXISTS `p1`;
DELIMITER $$
CREATE PROCEDURE `p1`(In p_dept_id integer)
BEGIN        
  declare cc cursor for SELECT EMPLOYEE_ID,DEPARTMENT_ID FROM v_tb1  WHERE department_id = p_dept_id;
  open cc;
end $$
DELIMITER ;

-- 以下可以正常执行
greatsql> call p1(80);
-- 以下可以正常执行
greatsql> call p1(80);

3、改变view相关表的表结构并再次执行sp

greatsql> ALTER TABLE tb2 modify FIRST_NAME VARCHAR2(200);
-- 这里发现数据库core了
greatsql> CALL p1(80);

core的堆栈如下:
Thread 53 "connection" received signal SIGABRT, Aborted.
__pthread_kill_implementation (no_tid=0, signo=6, threadid=140736954115648) at ./nptl/pthread_kill.c:44
44        ./nptl/pthread_kill.c: 没有那个文件或目录.
(gdb) bt
#0  __pthread_kill_implementation (no_tid=0, signo=6, threadid=140736954115648)
    at ./nptl/pthread_kill.c:44
#1  __pthread_kill_internal (signo=6, threadid=140736954115648) at ./nptl/pthread_kill.c:78
#2  __GI___pthread_kill (threadid=140736954115648, signo=signo@entry=6)
    at ./nptl/pthread_kill.c:89
#3  0x00007ffff7442476 in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
#4  0x00007ffff74287f3 in __GI_abort () at ./stdlib/abort.c:79
#5  0x00007ffff742871b in __assert_fail_base (
    fmt=0x7ffff75dd130 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", 
    assertion=0x55555bf8d54a "!field_info.empty()", 
    file=0x55555bf8d1d8 "sql/sql_derived.cc", 
    line=565, function=<optimized out>) at ./assert/assert.c:94
#6  0x00007ffff7439e96 in __GI___assert_fail (assertion=0x55555bf8d54a "!field_info.empty()", 
    file=0x55555bf8d1d8 "sql/sql_derived.cc", 
    line=565, function=0x55555bf8d4a0 "copy_field_info(THD*, Item*, Item*)::<lambda(Item*)>")
    at ./assert/assert.c:103
#7  0x00005555591f0641 in operator() (__closure=0x7fffe027c6a0, inner_item=0x7fff28c890d0)
    at sql/sql_derived.cc:565
#8  0x00005555591f4d1b in Item::walk_helper_thunk<copy_field_info(THD*, Item*, Item*)::<lambda(Item*)> >(uchar *) (this=0x7fff28c890d0, arg=0x7fffe027c6a0 "\300\306'\340\377\177")
    at sql/item.h:2559
#9  0x0000555558c4de9c in Item::walk (this=0x7fff28c890d0, 
    processor=(bool (Item::*)(Item * const, unsigned char *)) 0x5555591f4cf4 <Item::walk_helper_thunk<copy_field_info(THD*, Item*, Item*)::<lambda(Item*)> >(uchar *)>, walk=enum_walk::PREFIX, 
    arg=0x7fffe027c6a0 "\300\306'\340\377\177")
    at sql/item.h:2552
#10 0x0000555558d34d0d in Item_func::walk (this=0x7fff28c89258, 
    processor=(bool (Item::*)(Item * const, unsigned char *)) 0x5555591f4cf4 <Item::walk_helper_thunk<copy_field_info(THD*, Item*, Item*)::<lambda(Item*)> >(uchar *)>, walk=enum_walk::PREFIX, 
    argument=0x7fffe027c6a0 "\300\306'\340\377\177")
    at sql/item_func.cc:660
#11 0x0000555558cc05ad in Item_cond::walk (this=0x7fff28c88658, 
    processor=(bool (Item::*)(Item * const, unsigned char *)) 0x5555591f4cf4 <Item::walk_helper_thunk<copy_field_info(THD*, Item*, Item*)::<lambda(Item*)> >(uchar *)>, walk=enum_walk::PREFIX, 
    arg=0x7fffe027c6a0 "\300\306'\340\377\177")
    at sql/item_cmpfunc.cc:6100
#12 0x00005555591f4d6c in WalkItem<copy_field_info(THD*, Item*, Item*)::<lambda(Item*)> >(Item *, enum_walk, struct {...} &&) (item=0x7fff28c88658, walk=enum_walk::PREFIX, functor=...)
    at sql/item.h:3838
#13 0x00005555591f07ce in copy_field_info (thd=0x7fff28001060, orig_expr=0x7fff28c87878, 
    cloned_expr=0x7fff28c88658)
    at sql/sql_derived.cc:563
#14 0x00005555591f0ec1 in Query_block::clone_expression (this=0x7fff28c58840, 
    thd=0x7fff28001060, item=0x7fff28c87878)

从函数堆栈和调用初步发现是view里面的派生表执行了条件下推,拷贝查询语句outer条件的时候发生了core。

二、问题调查过程

从上面现象思考2个问题:

1、前两次执行 call p1(80)的时候为何没有core,只有第3次的时候core了?

2、第3次core是什么原因?

观察上面第三次的call,可以发现操作之前执行了表的alter操作,这个操作影响了第三次的运行。

分析代码之前我们先看一下这个view在查询的时候执行的条件下推是什么:

CREATE VIEW v_tb1 AS
SELECT * FROM (    SELECT * FROM tb1    UNION    SELECT * FROM tb2) AS combined_tables
WHERE DEPARTMENT_ID = 80;

这个查询用了派生表,优化器为了执行的时候提升效率会先对每张表进行条件过滤,最后再做union操作,这样可以减少表联合时候查询的行数。
于是上述例子在prepare的时候将会变成:
SELECT * FROM (    SELECT * FROM tb1  WHERE DEPARTMENT_ID = 8
UNION SELECT * FROM tb2 AS combined_tables WHERE DEPARTMENT_ID = 8);
可以看到条件原来是一个,这里做条件下推的时候就需要拷贝条件分别下推给两张表,于是就需要执行Query_block::clone_expression。

下面我们看一下core的地方copy_field_info相关代码调用流程。

Item *Query_block::clone_expression(THD *thd, Item *item) {
  // 从源Item解析出目标Item
  Item *cloned_item = parse_expression(thd, item, this);
  if (cloned_item == nullptr) return nullptr;
  if (item->item_name.is_set())
    cloned_item->item_name.set(item->item_name.ptr(), item->item_name.length());

  // 从源Item拷贝相关信息到目标Item
  if (copy_field_info(thd, item, cloned_item)) return nullptr;
}

bool copy_field_info(THD *thd, Item *orig_expr, Item *cloned_expr) {
  // 以下遍历orig_expr,从orig_expr参数中抽取出FIELD_ITEM并且加入到field_info,本次例子抽取出的field是2个department_id
  if (WalkItem(orig_expr, enum_walk::PREFIX,
               [&field_info, &depended_from, &context](Item *inner_item) {
                 if (inner_item->type() == Item::FIELD_ITEM) {
                   Item_field *field = down_cast<Item_field *>(inner_item);
                   if (field_info.push_back(
                           Field_info(context, field->table_ref, depended_from,
                                      field->cached_table, field->field)))
                     return true;
                 }
                 return false;
               }))
    return true;
  // Copy the information to the fields in the cloned expression.
  // 以下遍历cloned_expr,把从源表达式抽取出来的field信息拷贝到目标表达式cloned_expr对应的field。很显然,源和目标的field数量肯定是一样的。
  WalkItem(cloned_expr, enum_walk::PREFIX, [&field_info](Item *inner_item) {
    if (inner_item->type() == Item::FIELD_ITEM) {
      // 这里要从源拷贝field信息,因此必须保证当前field_info还有剩余field信息,如果为空了说明源和目标的field数量不一致就有问题了。
      // 本次core的地方在这里,就说明源和目标表达式的field数量不一致,因此需要调查为什么存在不一致。
      assert(!field_info.empty());
      Item_field *field = down_cast<Item_field *>(inner_item);
      field->context = field_info[0].m_field_context;
      field->table_ref = field_info[0].m_table_ref;
      field->depended_from = field_info[0].m_depended_from;
      field->cached_table = field_info[0].m_cached_table;
      field->field = field_info[0].m_field;
      field_info.pop_front();
    }
    return false;
  });
}

分析copy_field_info函数执行时候拆解出来的具体Item元素,用下表显示:

执行次数orig_expr条件条件包含的参数参数包含的Item元素
第一次Item_cond_andItem_func_eq (DEPARTMENT_ID = 80) Item_func_eq (DEPARTMENT_ID = p_dept_id)DEPARTMENT_ID = 80 分别是Item_field和Item_int DEPARTMENT_ID = p_dept_id 分别是Item_field和Item_splocal
第三次Item_cond_andItem_func_eq (DEPARTMENT_ID = 80) Item_func_eq (DEPARTMENT_ID = p_dept_id)DEPARTMENT_ID = 80 分别是Item_field和Item_int DEPARTMENT_ID = p_dept_id 分别是Item_field和Item_field(问题点)

通过对比表可以很清楚的看到有问题的第三次的最后一个Item变为了Item_field,而正确执行的第一次是解析为Item_splocal。就是这个field数量差异导致了core。

第三次执行的时候为什么Item会跟第一次不一样呢?我们注意到第三次之前做了alter table的操作,这个操作导致表版本更新,于是触发了cursor的查询语句的reprepare操作。对应的代码如下:

bool sp_lex_instr::validate_lex_and_execute_core(THD *thd, uint *nextp,
                                                 bool open_tables) {
  while (true) {
    DBUG_EXECUTE_IF("simulate_bug18831513", { invalidate(); });
    // 如果表版本有更新,就需要重新parse这个语句对应的查询语句
    if (is_invalid() ||
        ((m_lex->has_udf()) &&
         !m_first_execution)) {
      free_lex();
      LEX *lex = parse_expr(thd, thd->sp_runtime_ctx->sp);

      if (!lex) return true;

      set_lex(lex, true);

      m_first_execution = true;
    }
}

上面代码执行parse_expr的时候,在下面函数重新解析p_dept_id这个参数。可以发现就是因为lex->find_variable没有找到对应的参数最后一个元素才变为Item_field

bool PTI_simple_ident_ident::itemize(Parse_context *pc, Item **res) {
  if (!is_with_func_ident &&
      // 如果lex找到用户定义的参数就解析为Item_splocal
      (spv = lex->find_variable(ident.str, ident.length, &rh))) {
    *res = create_item_for_sp_var(
        thd, ident, rh, spv, sp->m_parser_data.get_current_stmt_start_ptr(),
        raw.start, raw.end);
    lex->safe_to_cache_query = false;
  } else
      // 如果lex没找到用户定义的参数就解析为Item_field
      *res = new (pc->mem_root) Item_field(POS(), NullS, NullS, ident.str);
}

GDB看一下find_variable为什么没有找到这个变量,打印下面spc的值发现是nullptr,因此发现是reparse查询语句以后lex->get_sp_current_parsing_ctx()变为空了,所以导致第三次没有找到对应的变量。

LEX::find_variable (this=0x7fffe047fc00, name=0x7fff30d9a918 "p_dept_id", name_len=9, ctx=0x7fffe047b7b0, rh=0x7fffe047b7f8, also_find_udt=true) at /home/wuyy/greatdb/gitmerge/percona-server/sql/sql_lex.cc:5955
5955          sp_pcontext *spc = get_sp_current_parsing_ctx();
(gdb) n
5957          if (spc && ((spv = spc->find_variable(name, name_len, false)) ||
(gdb) s
5967          sp_package *pkg = sphead ? sphead->get_package() : nullptr;
(gdb) p spc
$16 = (sp_pcontext *) 0x0

三、问题解决

从上面分析结论,我们发现是set_lex的时候没有把旧的sp_pcontext和sp_head值赋给新的lex,因此在set_lex的时候进行赋值就可以解决问题。

void sp_lex_instr::set_lex(LEX *lex, bool is_lex_owner) {
  free_lex();

  m_lex = lex;
  m_is_lex_owner = is_lex_owner;
  m_lex_query_tables_own_last = nullptr;

  if (m_lex) {
    m_lex->sp_lex_in_use = true;
    // 添加下面的赋值代码,判断当前lex有变化的时候进行赋值
    // It needs m_parsing_ctx and sphead in parse_expression to parse expr.
    if (!m_first_execution) {
      m_lex->set_sp_current_parsing_ctx(m_parsing_ctx);
      m_lex->sphead = current_thd->sp_runtime_ctx->sp;
    }
  }
}

void sp_lex_instr::free_lex() {
  if (!m_is_lex_owner || !m_lex) return;

  /* Prevent endless recursion. */
  m_lex->sphead = nullptr;
  // 释放的时候需要注意不能把旧的sp_pcontext删了,因此需要先置空
  if (!m_first_execution) m_lex->set_sp_current_parsing_ctx(nullptr);
  lex_end(m_lex);
  destroy(m_lex->result);
}

编译以后再次运行call p1,问题解决。
greatdb> alter table tb2 modify FIRST_NAME VARCHAR2(200);
greatdb> call p1(80);
Query OK, 0 rows affected (0.02 sec)

四、问题总结

针对 MySQL 8.4.4 调试版环境下,视图+游标联动场景触发数据库Core的问题做了完整排查与修复:修改视图关联表结构后,会触发游标语句重新解析,因重解析时存储过程上下文丢失,导致输入参数解析异常、字段数量不匹配,最终触发断言崩溃。

解决方案为补全语句重解析时的存储过程上下文传递逻辑,修复set_lex函数的上下文赋值环节即可解决问题。

日常开发需注意:涉及游标、嵌套视图的存储过程,要规避频繁变更关联表结构,内核开发需严控重解析场景的上下文生命周期,避免上下文丢失引发同类崩溃。

通过以上分析我们可以发现,cursor的使用因为跟查询语句密切相关,因此比别的存储过程的语句复杂很多,涉及的知识面也更广,想要解析相关问题需要从优化器和存储过程的执行原理出发分析才能找到问题点,需要扎实的数据库知识储备。平时开发需要注重积累,才能在发现问题的时候快速定位问题和解决问题。

SpringBoot+Vue+MySQL 高校学科竞赛平台 完整可运行版(源码+文档) 本项目基于SpringBoot+Vue+MySQL构建高校学科竞赛管理平台,覆盖学生、教师、领队教师、管理员四大角色,实现竞赛发布、报名、刷题、评分、公示等全流程闭环管理。系统架构清晰,技术主流,配套完整源码、数据库脚本、万字论文、开题报告、答辩PPT及部署文档,支持一键运行,适用于毕业设计、课程设计及院系二次开发,真正实现“开箱即用”。 阅读详情

相关推荐

SpringBoot+Vue+MySQL 民宿在线预定平台 完整可运行版(源码+文档)

本文介绍一套基于SpringBoot+Vue+MySQL的民宿在线预订平台,涵盖用户与管理员双角色全流程功能,实现房源展示、订单管理、支付模拟、数据看板等闭环业务。系统架构清晰,前后端分离,附带完整源码、数据库脚本、万字论文、答辩PPT及部署文档,适合毕设、课程设计或小型民宿二次开发,开箱即用,快速落地。

招风的黑耳优快云 173

MySQL 索引深入理解:B+ 树、二级索引、联合索引与查询优化

理解二级索引后,就可以理解回表了。SELECT *MySQL 的执行过程分为三个步骤。覆盖索引(Covering Index)并不是一种独立的索引类型,而是一种查询效果。SQL 查询需要的所有字段,都能够直接从某个索引中获得,不需要再访问聚簇索引获取其他字段。例如:因为user_id已经包含在二级索引中,所以 MySQL 可以直接返回结果。不需要回表。联合索引(Composite Index)是同时使用多个字段建立的索引。它的排序规则是:首先按照user_id排序。当user_id。

m0_64642997的博客 135

Emscripten安装(wasm编译)

5:配置对应环境变量--替换成自己对应的安装路径(2025最新的Emscripten工具链默认使用LLVM/WebAssembly标准工作流,java依赖已经移除了,所以以下java环境不配,需要使用java的手动添加即可---->emsdk install java-8-152-64bit。3:下载相应的依赖库---->emsdk install latest(我这里下的是最新的,如果有指定版本,把latest替换成版本号即可)6:测试是否成功---> emcc- v/em++ -v。

qq_31578301的博客 554

MySQL 单点详解(14)

给定一条 SQL,联合索引的列该怎么排呢?

2401_88601046的博客 345

别再凭感觉估算!用ADS的EBOND库精确仿真Bonding线寄生电感(附完整参数设置指南)

本文详细介绍了在ADS中使用EBOND库精确仿真Bonding线寄生电感的方法,帮助射频工程师在毫米波频段实现高精度建模。通过三维物理参数和电磁场求解算法,EBOND模型能将误差控制在5%以内,显著提升电路性能。文章还提供了完整的参数设置指南和实战操作步骤,适用于5G毫米波前端模块等高频应用场景。

weixin_28730131的博客 506

基于YOLOv8的工业瓷砖缺陷检测:深度学习与UI界面的应用

本文详细介绍了如何使用YOLOv8进行工业瓷砖缺陷检测,并结合图形用户界面(UI)提供了完整的实现方案。通过YOLOv8模型,我们可以高效、精确地检测瓷砖图像中的缺陷,显著提高生产过程中的质量控制水平。随着数据集的进一步扩展和YOLOv8模型的不断优化,未来瓷砖缺陷检测的精度和速度将不断提高。此外,基于深度学习的缺陷检测技术不仅可以应用于瓷砖生产,还可以推广到其他领域的质量检测中。

YOLO 604

MySQL 的 REPEATABLE READ 到底能不能防幻读——从快照读、当前读到 Next-Key Lock

本文系统讲解 InnoDB 可重复读级别下的幻读问题:从三类读异常切入,剖析快照读依赖 MVCC、当前读依赖 Next-Key Lock 的双防线机制,用双会话实验复现幻读仍会出现的边界场景,并解释各数据库在幻读防护上行为分歧的根源。

大模型全栈工程师 · Thanks_ks 297

基于STM32设计自动输液监测系统(241)

该系统集成了液位传感模块、光电传感器、电机模块、按键模块和OLED显示屏等多个功能模块,以实现全面的输液过程监控和控制。液位传感模块能够实时监测输液瓶中的液位,当液位到达限定值时,系统会自动控制步进电机夹紧输液管,并发出报警提醒,确保输液过程不会因液位过低而中断。

1342

Flink SQL 连接器实战:MySQL Source、Flink CDC 与 JDBC Sink 全解析

提供有界流读取,适合批处理和维表场景,简单直接但无法感知变更。MySQL CDC提供无界流读取,通过「全量快照 + binlog 增量」的方式实现实时捕获,是实时数仓的核心入口,但需要 MySQL 侧正确配置 binlog 和权限。JDBC Sink负责结果回写,关键在于区分仅插入流和更新流,更新流必须依赖主键完成 upsert。掌握这三者的差异,本质上就是掌握了 Flink 中「有界与无界」「追加与更新」这两组最基本的语义。

2401_83857914的博客 455

hadoop 切片机制详解

hadoop切片机制详解

congge 1万+

分类预测 | MATLAB实现ELM极限学习机多特征分类预测(二分类)

分类预测 | MATLAB实现ELM极限学习机多特征分类预测(二分类)

机器学习之心的博客,关注并私信文章链接,获取对应文章源码和数据。 779

MySQL 中 DISTINCT 与 GROUP BY 哪个效率更高?

DISTINCT与GROUP BY在纯去重场景下,MySQL 8.0 中执行计划通常一致,效率基本相同。老版本(8.0.13 之前)GROUP BY有隐式排序开销,DISTINCT往往更快。需要聚合或HAVING时,只能用GROUP BY。效率的真正决定因素是索引和执行计划,而不是这两个关键字本身。所以,与其问「哪个更快」,不如问「我的查询有没有走对索引」。

2601_96709915的博客 326

【原理图PCB专题】原理图图纸锁定/解锁与PCB文件加密方式

在工作中我们会遇到需要冻结原理图进行评审和加密图纸防止被他人盗用的需求。那么在OrCAD Capture中如何对图纸进行锁定与解锁,如何在Allegro中对PCB工程进行加密呢?

一点硬件 3256

Docker 部署 WordPress+MySQL 高可用架构

点「安装 WordPress」

一直在努力学习的菜鸟 227

【GEOS-Chem模拟教程第二期上】生物质燃烧排放 GFED4 数据配置

生物质燃烧排放 GFED4 数据配置

WW、forever的博客 1301

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

基于 FastAPI+LangChain+LangGraph+Agent+Vue3+MySQL 的房产数据采集与房价预测分析平台

本文介绍一个完整的「房产数据采集+AI房价预测」全栈项目,涵盖FastAPI异步后端、LangGraph Agent智能问答、爬虫采集、机器学习预测与Vue3前端,实现从数据采集到AI交互的闭环。项目融合多技术栈,具备真实业务场景与生产级设计(如降级策略、流式输出、多模型对比),兼具简历亮点与答辩演示优势,可系统性提升工程能力,并附高频面试题解析,是理想的技术综合实践项目。

深耕开发,专注编程实战。分享源码解析、项目搭建、问题排查笔记,沉淀技术,持续更新。 231

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

MySQL 8.0 双向主从复制故障修复与重建指南

MySQL 8.0 双向主从复制故障修复 SOP:XtraBackup 重建备用节点,解决 GTID 1236 / 历史日志冲突

「YYL DBA手记」 数据库 · 架构 · 运维 · 实战 yyldba.blog.youkuaiyun.com 298

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

MySQL 8.0停服了,信创替代的窗口正在关闭

最近跟几个做信创的朋友聊天,发现一个被忽略的问题。MySQL 8.0在今年4月正式停了官方支持,Oracle不再出安全补丁,bug也没人修了。但大量企业的业务系统还跑在上面。这事搁以前不算急,慢慢选就行了。但现在不行了,国资委79号文写得很清楚,2027年底前央国企核心系统得完成国产化替换。MySQL停服跟信创deadline撞在一起,留给MySQL用户做决定的时间不多了。我做过不少数据库迁移项目,MySQL替代这个事,坑比大多数人想的要多。今天聊几个我觉得最容易被忽视的点。

databasedb的博客 333

MySQL:库与表的操作

本文系统讲解MySQL库的操作,涵盖创建、查看、修改、删除数据库及字符集、校验规则的配置与影响。重点说明CREATE DATABASE语法、字符集(如utf8mb4)与校验规则(如utf8_general_ci vs utf8_bin)对大小写敏感性和排序的影响。通过实例演示不同校验规则下查询与排序结果差异。同时介绍SHOW DATABASES、USE、ALTER DATABASE、DROP DATABASE等操作,并强调备份恢复(mysqldump)与连接状态监控(SHOW PROCESSLIST)的重要

2401_87306079的博客 325

MySQL 主从复制进阶(2026):GTID、复制延迟排查与故障切换

load 高到底是 CPU 还是 IO?free 的 available 才是关键。us/sy/wa 决策树 + iostat/sar/iftop 实战,CPU/内存/磁盘/网络四大瓶颈定位方法论。

2502_91473995的博客 182

Linux、Shell、MySQL 测试卷逐题细讲(下篇:MySQL)

本文为Linux、Shell、MySQL测试卷下半段MySQL部分逐题讲解,包含填空、选择与SQL分析三类题型。填空题覆盖COUNT、HAVING、DISTINCT、事务、约束、索引等核心语法;选择题辨析存储过程、索引类型、ACID、存储引擎、用户管理等考点。SQL大题围绕员工、部门、职位、地点四张关联表,考察多表连接、分组聚合、自连接、相关子查询、NULL处理等高频写法,标注LEFT JOIN统计计数、NULL判断、子查询别名等易错坑点,同时梳理试卷OCR识别带来的干扰问题,重点提示SQL实操中的常见失误

dongziwen1的博客 185

MySQL 为什么选择 B+ 树作为索引结构

B 树和 B+ 树都是多路平衡树,但 B+ 树在数据库场景下更有优势,主要体现在以下几个方面。对比对象主要问题B+ 树的优势二叉树 / 红黑树树高过大,I/O 次数多多路平衡,树高仅 3~4 层哈希表不支持范围查询、排序天然有序,支持范围与排序B 树节点存数据,扇出小;查询路径不一致非叶子只存键,扇出大;查询路径稳定B+ 树用更矮的树高减少磁盘 I/O,用有序的叶子链表支撑范围查询,用只存键的非叶子节点换取更大的扇出,是磁盘数据库索引场景下综合表现最优的选择。

2601_96129122的博客 319

任务4-1 了解MySQL的数据类型

本文梳理了MySQL数据类型:数值型涵盖整型与实型,金额首选DECIMAL;字符串型按长度与用途分为CHAR、VARCHAR、TEXT及BLOB;日期型包含DATE、TIME、DATETIME及TIMESTAMP;特殊类型有ENUM、JSON等。掌握类型特性是高效建表的基础。

howard2005的专栏 147

mysql初阶--数据库设计

本文系统阐述数据库设计的核心方法论,从范式理论(1NF、2NF、3NF)出发,揭示数据冗余与操作异常的根源,强调3NF为工程实践的最优平衡点。通过E-R图构建实体关系模型,实现从业务需求到表结构的清晰映射。文章厘清类、实体、表三者对应关系,提出“抽象→建模→落地”的设计流程,帮助开发者建立可复用的数据库设计思维框架,避免“拍脑袋”建表的陷阱。

2601_97033068的博客 704

MySQL 高频面试题全解:索引失效、MVCC 与间隙锁、深度分页优化(2026 招聘 JD 真题复盘)

按 2026 招聘 JD 与一线面经整理 12 道 MySQL 高频题:B+树索引原理、聚簇索引与覆盖索引、最左前缀与索引失效真实场景、MVCC 与 ReadView、间隙锁与死锁实战、深度分页优化、慢 SQL 六步排查、count(*)、主从延迟、分库分表与两阶段提交,每题附可直接复述的工程化答案。

蒙眼过河 267
上一篇: 慎用mysqldump与GTID自动定位:一次备份数据“丢失“的排查
下一篇: 一文搞懂 MySQL/GreateSQL 只读参数:read_only 参数核心区别
GreatSQL社区
博客等级 码龄5年 1210粉丝 390原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值