首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >[MYSQL] mysql 参数lower_case_table_names的修改

[MYSQL] mysql 参数lower_case_table_names的修改

原创
作者头像
大大刺猬
发布于 2024-09-11 10:02:38
发布于 2024-09-11 10:02:38
1.5K02
代码可运行
举报
文章被收录于专栏:大大刺猬大大刺猬
运行总次数:2
代码可运行

导读

lower_case_table_names 是将表名转换为小写. 即:

为0时: 不启用转换小写, 也就是区分大小写

为1时: 转换为小写, 也就是不区分大小写.

不支持动态修改.

Command-Line Format

--lower-case-table-names[=#]

System Variable

lower_case_table_names

Scope

Global

Dynamic

No

SET_VAR Hint Applies

No

Type

Integer

Default Value (macOS)

2

Default Value (Unix)

0

Default Value (Windows)

1

Minimum Value

0

Maximum Value

2

该参数默认是0, 即区分大小写. 但现在又想要不区分大小写了. 也就是想设置其值为1. 首先我们要确保数据库里面的表均为小写, 我们可以通过如下sql查询

代码语言:sql
AI代码解释
复制
select * from (select lower(concat(table_schema,'.',table_name)) as n1, concat(table_schema,'.',table_name) as n2 from information_schema.tables where table_schema not in ('sys','information_schema')) as t where t.n1!=t.n2;

请自行修改

然后我们再修改该参数, 理论上就是可行的了. 但却报错了:

代码语言:txt
AI代码解释
复制
2024-09-11T05:58:38.397733Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
2024-09-11T05:58:39.389682Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
2024-09-11T05:58:39.452780Z 1 [ERROR] [MY-011087] [Server] Different lower_case_table_names settings for server ('1') and data dictionary ('0').
2024-09-11T05:58:39.453065Z 0 [ERROR] [MY-010020] [Server] Data Dictionary initialization failed.
2024-09-11T05:58:39.453091Z 0 [ERROR] [MY-010119] [Server] Aborting
2024-09-11T05:58:40.296502Z 0 [System] [MY-010910] [Server] /soft/mysql_3306/mysqlbase/mysql/bin/mysqld-debug: Shutdown complete (mysqld 8.0.37-debug)  MySQL Community Server - GPL - Debug.

说和数据字典不一致. 啊.这.......

分析

源码分析

首先我们先根据报错Data Dictionary initialization failed 找下相关的错误码. 我们直接使用万能的grep -r来找. (通常位于share/messages_to_error_log.txt)

代码语言:shell
AI代码解释
复制
grep -r 'Data Dictionary initialization failed'

发现对于的名字叫ER_DD_INIT_FAILED (应该是数据字典初始化失败的意思, 额,就是字面意思)

然后我们再使用万能的grep -r 看下是位于哪段代码的报错

代码语言:shell
AI代码解释
复制
grep -r ER_DD_INIT_FAILED

发现就是主函数.....(如果熟悉mysql启动流程的话, 应该直接就能猜到了)

代码语言:c++
AI代码解释
复制
  init_sql_command_flags();

  /*
    plugin_register_dynamic_and_init_all() needs DD initialized.
    Initialize DD to create data directory using current server.
  */

if (opt_initialize) {
    if (!is_help_or_validate_option()) {
      if (dd::init(dd::enum_dd_init_type::DD_INITIALIZE)) {
        LogErr(ERROR_LEVEL, ER_DD_INIT_FAILED);
        unireg_abort(1);
      }

      if (dd::init(dd::enum_dd_init_type::DD_INITIALIZE_SYSTEM_VIEWS)) {
        LogErr(ERROR_LEVEL, ER_SYSTEM_VIEW_INIT_FAILED);
        unireg_abort(1);
      }
    }
  } else {
    /*
      Initialize DD in case of upgrade and normal normal server restart.
      It is detected if we are starting on old data directory or current
      data directory. If it is old data directory, DD tables are created.
      If server is starting on data directory with DD tables, DD is initialized.
    */
    if (!is_help_or_validate_option() &&
        dd::init(dd::enum_dd_init_type::DD_RESTART_OR_UPGRADE)) {
      LogErr(ERROR_LEVEL, ER_DD_INIT_FAILED);
      /* If clone recovery fails, we rollback the files to previous
      dataset and attempt to restart server. */
      int exit_code =
          clone_recovery_error ? MYSQLD_RESTART_EXIT : MYSQLD_ABORT_EXIT;
      unireg_abort(exit_code);
    }
  }

也就是dd::init(dd::enum_dd_init_type::DD_RESTART_OR_UPGRADE))的时候返回true了. 我们再看看dd::init在干嘛

我们用类似的方法找到了namespace下的init (sql/dd/impl/dd.cc)

代码语言:c++
AI代码解释
复制
bool init(enum_dd_init_type dd_init) {
  if (dd_init == enum_dd_init_type::DD_INITIALIZE ||
      dd_init == enum_dd_init_type::DD_RESTART_OR_UPGRADE) {
    cache::Shared_dictionary_cache::init();
    System_tables::instance()->add_inert_dd_tables();
    System_views::instance()->init();
  }

  return Dictionary_impl::init(dd_init);
}

发现又是调用的Dictionary_impl::init .... 继续呗.

找到对应代码为如下, 即调用了run_bootstrap_thread(sql/dd/impl/dictionary_impl.cc), 这应该是最后一层了吧..

代码语言:c++
AI代码解释
复制
  /*
    Creation of Dictionary Tables in old Data Directory
    This function also takes care of normal server restart.
  */
  else if (dd_init == enum_dd_init_type::DD_RESTART_OR_UPGRADE)
    result = ::bootstrap::run_bootstrap_thread(
        nullptr, nullptr, &upgrade_57::do_pre_checks_and_initialize_dd,
        SYSTEM_THREAD_DD_INITIALIZE);

这里应该是do_pre_checks_and_initialize_dd更关键. 我们看下其实现

我们在sql/dd/upgrade_57/upgrade.cc中找到如下信息

代码语言:c++
AI代码解释
复制
  /*
    Initialize InnoDB in restart mode if mysql.ibd is present.
    Else, initialize InnoDB in upgrade mode to create mysql tablespace
    and upgrade redo and undo logs.
    If mysql.ibd does not exist but upgrade stage tracking file exist
    This can happen in rare scenario when server detects it needs to upgrade.
    Server creates mysql_dd_upgrade_info file but crashes/killed before
    creating mysql.ibd. In this case, innodb was initialized above in upgrade
    mode. It would create mysql tablespace. Do nothing here, we will treat this
    as upgrade.
  */

  if (exists_mysql_tablespace) {
    if (bootstrap::DDSE_dict_init(thd, DICT_INIT_CHECK_FILES,
                                  d->get_target_dd_version())) {
      LogErr(ERROR_LEVEL, ER_DD_SE_INIT_FAILED);
      return true;
    }
  } else {
    if (bootstrap::DDSE_dict_init(thd, DICT_INIT_UPGRADE_57_FILES,
                                  d->get_target_dd_version())) {
      LogErr(ERROR_LEVEL, ER_DD_UPGRADE_FAILED_INIT_DD_SE);
      Upgrade_status().remove();
      return true;
    }
  }

即通过bootstrap::DDSE_dict_init去检查mysql.ibd文件.....

越整越复杂....

我们换个关键词搜. 不是还有个[Server] Different lower_case_table_names settings for server ('1') and data dictionary ('0')

对应逻辑为:

代码语言:c++
AI代码解释
复制
    /*
      Reject restarting with a changed LCTN setting, since the collation
      for LCTN-dependent columns is decided during server initialization.
    */
    uint actual_lctn = 0;
    exists = false;
    if (dd::tables::DD_properties::instance().get(thd, "LCTN", &actual_lctn,
                                                  &exists) ||
        !exists) {
      LogErr(WARNING_LEVEL, ER_LCTN_NOT_FOUND, lower_case_table_names);
    } else if (actual_lctn != lower_case_table_names) {
      LogErr(ERROR_LEVEL, ER_LCTN_CHANGED, lower_case_table_names, actual_lctn);
      return true;
    }

原来是这里强制判断. 也就是我们只要修改元数据信息里面的LCTN为1即可.

数据库层面分析

系统的数据字典是无法直接访问的, 得使用debug启动才能访问

代码语言:sql
AI代码解释
复制
SET SESSION debug='+d,skip_dd_table_access_check';
SELECT name, schema_id, hidden, type FROM mysql.tables where schema_id=1 AND hidden='System';

应该就是mysql.dd_properties表了.

只有1大字段....., 查询发现是16进制的. 我们使用py来查询. 并找出LSTN的位置

代码语言:python
代码运行次数:0
运行
AI代码解释
复制
import pymysql
conn = pymysql.connect(
			host='127.0.0.1',
			port=3306,
			user='root',
			password='123456',
			)
cursor = conn.cursor()
cursor.execute("SET SESSION debug='+d,skip_dd_table_access_check';")
_ = cursor.fetchall()

cursor = conn.cursor()
cursor.execute('select * from mysql.dd_properties')

data = cursor.fetchall()


def find_xx_positions(s,x):
	positions = []
	xl = len(x)
	start = 0
	while True:
		pos = s.find(x, start)
		if pos == -1:
			break
		positions.append(pos)
		start = pos + xl
	return positions

find_xx_positions(data[0][0].decode(),'LCTN=')

发现就只有这里有... 我们使用hexdump -C 却发现好几处...

也就是还有几张表也记录了这玩意...

但剩下几张表看起来都不像啊.... (还想着直接数据库层面修改呢...) 是时候祭出我们的python了.(上面不是已经使用了么...)

python分析

我们现在使用python来分析mysql.ibd文件

代码语言:python
代码运行次数:0
运行
AI代码解释
复制
import struct
dd_dict = [
0x004e42c0,
0x005282c0,
0x0056c2c0,
0x005b02d0,
0x005f42d0,
]
filename = '/data/mysql_3306/mysqldata/mysql.ibd'
f = open(filename,'rb')
for x in dd_dict:
	page_offset = int(x/16384)
	_ = f.seek(page_offset*16384,0)
	data = f.read(16384)
	aa = struct.unpack('>4LQHQ',data[:34])
	print(f'PAGE_TYPE:{aa[-2]}')

全是24(FIL_PAGE_TYPE_LOB_FIRST) 还好我们之前解析过这种PAGE的. 都不用改, 直接拿来用就是了.

代码语言:python
代码运行次数:0
运行
AI代码解释
复制
import struct
def first_blob(f,pageno): # 这名字取得... 简单点吧
	"""
	input: f:  file desc  pageno FIL_PAGE_TYPE_LOB_FIRST NO
	output: binarydata
	"""
	firstpagno = pageno
	f.seek(pageno*16384,0)
	data = f.read(16384)
	entry = data[96:96+60]
	rdata = b''
	while True:
		if len(entry) < 12:
			break
		pageno,datalen,lobversion = struct.unpack('>3L',entry[-12:])
		datalen = datalen>>16
		if pageno == 0 or pageno == 4294967295:
			break
		elif pageno == firstpagno:
			rdata += data[696:696+datalen]
		else:
			f.seek(pageno*16384,0)
			rdata += f.read(16384)[49:49+datalen]
			#rdata += read_page(pageno)[39:39+datalen]
		next_entry_pageno,next_entry_offset = struct.unpack('>LH',entry[6:12])
		if next_entry_pageno >0 and next_entry_pageno < 4294967295:
			f.seek(next_entry_pageno*16384,0)
			entry = f.read(16384)[next_entry_offset:next_entry_offset+60]
		else:
			break
	return rdata

import struct
dd_dict = [
0x004e42c0,
0x005282c0,
0x0056c2c0,
0x005b02d0,
0x005f42d0,
]

def find_xx_positions(s,x):
	positions = []
	xl = len(x)
	start = 0
	while True:
		pos = s.find(x, start)
		if pos == -1:
			break
		positions.append(pos)
		start = pos + xl
	return positions


filename = '/data/mysql_3306/mysqldata/mysql.ibd'
f = open(filename,'rb')
for x in dd_dict:
	data = first_blob(f,int(x/16384)).decode()
	print('PAGENO:',int(x/16384),'OFFSET:',find_xx_positions(data,'LCTN'))

也就是这几个位置存在LCTN信息. 既然找到了确定位置, 那我们就可以直接修改值了. 修改完后记得做下crc32c校验. 好在我们之前也解析过. 于是我们整合整合就可以使用了.

修改lower_case_file_system

上面准备了那么多, 现在我们就可以修改lower_case_file_system啦. mysql层走不通, 我们直接修改mysql.ibd文件, 然后做下crc32的计算, 并写回数据库即可. (一定要先把大写的表给修改掉, 不然不知道发生什么, 或许什么也不会发生). 为了简单, 我这里就不写接口了. 信息直接写死.

代码语言:python
代码运行次数:0
运行
AI代码解释
复制
import struct
import sys,os
def create_crc32c_table():
    poly = 0x82f63b78
    table = []
    for i in range(256):
        crc = i
        for _ in range(8):
            if crc & 1:
                crc = (crc >> 1) ^ poly
            else:
                crc >>= 1
        table.append(crc)
    return table

			
def calculate_crc32c(data):
	crc = 0xFFFFFFFF
	for byte in data:
		crc = crc32_slice_table[(crc ^ byte) & 0xFF] ^ (crc >> 8)
	return crc ^ 0xFFFFFFFF


crc32_slice_table = create_crc32c_table()
filename = '/data/mysql_3306/mysqldata/mysql.ibd'
f = open(filename,'rb')
f2 = open('/tmp/t20240911_test_mysql.ibd','wb')
mpage = [313,330,347,364,381]
	
PAGENO = -1
while True:
	data = f.read(16384)
	PAGENO += 1
	if data == b'':
		break
	lctn_offset = data.find(b'LCTN')
	if lctn_offset < 1:
		f2.write(data)
		continue
	data = data[:lctn_offset+5] + b'1' + data[lctn_offset+6:]
	checksum_field1 = struct.unpack('>L',data[:4])[0]
	checksum_field2 = struct.unpack('>L',data[-8:-4])[0]
	c1 = calculate_crc32c(data[4:26])
	c2 = calculate_crc32c(data[38:16384-8])
	cb = struct.pack('>L',c1)
	data = cb + data[4:16384-8] + cb + data[16384-4:]
	f2.write(data)
	#print('PAGENO:',PAGENO,"CHECKSUM:",checksum_field1,checksum_field2,(c1^c2)&(2**32-1))

然后我们替换mysql.ibd,并修改参数, 再启动瞧瞧:

代码语言:shell
AI代码解释
复制
mv /data/mysql_3306/mysqldata/mysql.ibd /tmp
mv /tmp/t20240911_test_mysql.ibd /data/mysql_3306/mysqldata/mysql.ibd
chown mysql:mysql /data/mysql_3306/mysqldata/mysql.ibd
vim /data/mysql_3306/conf/mysql_3306.cnf

启动失败, 页有问题....(说是381有问题, 就是我们刚才解析的最后1页. 那我们不要这一页呢.)

修改回去之后, 又报错不能修改了...

也就是说在某个字段里面还存在着校验值.(非PAGE的CHECKSUM). (看来是没法走捷径了...)

看来就只有后面研究源码或者表结构了才行.

实际生产环境建议老老实实重建实例. 这里仅为测试环境的演示

当我准备就此结束的时候, 我使用之前写的坏块检查脚本跑了下, 发现刚才那几页是坏块

也就是说逻辑可能没得问题, 而是我们页拼接的时候有问题. 仔细一看,发现是 c1和c2忘记做^了.....

不过也因此确认了应该是381页记录的LCTN才是有效的.

然后再次测试,启动数据库再次, 登录验证: 发现确实修改成功了

啊, 我真棒!

总结

之前学习的ibd文件校验,ibd文件结构等信息再次使用上了. 虽然不推荐生产环境这么干. 但这种方法也确实是可行的. 而且尽量使用交叉验证, 某种方法失败的时候不一定是逻辑有问题, 有可能是哪里的细节有问题.

附源码

前面验证的就不再单独列出来了. 就只列出最后的代码即可. 使用的时候, 注意修改为自己的文件哈, 记得备份!

代码语言:python
代码运行次数:2
运行
AI代码解释
复制
import struct
import sys,os
def create_crc32c_table():
    poly = 0x82f63b78
    table = []
    for i in range(256):
        crc = i
        for _ in range(8):
            if crc & 1:
                crc = (crc >> 1) ^ poly
            else:
                crc >>= 1
        table.append(crc)
    return table

			
def calculate_crc32c(data):
	crc = 0xFFFFFFFF
	for byte in data:
		crc = crc32_slice_table[(crc ^ byte) & 0xFF] ^ (crc >> 8)
	return crc ^ 0xFFFFFFFF


crc32_slice_table = create_crc32c_table()
filename = '/tmp/mysql.ibd'
f = open(filename,'rb')
f2 = open('/tmp/t20240911_test_mysql.ibd','wb')
mpage = [313,330,347,364,381]
	
PAGENO = -1
while True:
	data = f.read(16384)
	PAGENO += 1
	if data == b'':
		break
	lctn_offset = data.find(b'LCTN')
	if lctn_offset < 1 :#or PAGENO in [381]:
		f2.write(data)
		continue
	print(PAGENO,lctn_offset)
	data = data[:lctn_offset+5] + b'1' + data[lctn_offset+6:]
	c1 = calculate_crc32c(data[4:26])
	c2 = calculate_crc32c(data[38:16384-8])
	cb = struct.pack('>L',(c1^c2)&(2**32-1))
	data = cb + data[4:16384-8] + cb + data[16384-4:]
	f2.write(data)
	#print('PAGENO:',PAGENO,"CHECKSUM:",checksum_field1,checksum_field2,(c1^c2)&(2**32-1))

f2.close()
f.close()

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
[MYSQL] 修改字段长度的时候不能使用instant算法? 其实inplace就够了
上一章我们讲了 mysql修改字段长度的时候不能使用instant算法, 而是使用inplace算法, inplace听起来没得instant快, 就认为inplace不止是修改元数据信息, 这是错误的.
大大刺猬
2025/07/30
920
[MYSQL] 修改字段长度的时候不能使用instant算法? 其实inplace就够了
[MYSQL] 修改字段长度的时候不能使用instant算法? 那就定制一个?
我们知道mysql 8.0.12引入了instant算法, 部分DDL只需要修改元数据信息即可完成修改, 这样速度是嘎嘎快. 但是支持有限, 大概如下:
大大刺猬
2025/07/25
1060
[MYSQL] 修改字段长度的时候不能使用instant算法? 那就定制一个?
[MYSQL] mysql忘记密码怎么办?
天有不测风云, 今晚(20240919,上海)台风Pulasan就要来了. 难免有忘记mysql密码的时候. 解决办法网上也是一找一大堆的. 这里做个小小的介绍. (不考虑history里面能查询到的情况, 况且那也不属于忘记密码的范畴)
大大刺猬
2024/09/19
6630
[MYSQL] mysql忘记密码怎么办?
[MYSQL] mysql.ibd 文件解析 (sdi page) (非debug模式下查看隐藏系统表)
在mysql 8.0版本,系统表的存储引擎由myisam改为了innodb, @@datadir/mysql目录下一堆的数据文件通通放到@@datadir/mysql.ibd文件中了. 但很多表在非debug模式下是无法查看里面的数据的. 这TM就很恼火. (刚学完innodb的磁盘结构, 我能受这气?). 所以我们现在来解析下mysql.ibd文件. (也顺便为 ibd2sql 2.0 做准备)
大大刺猬
2024/09/18
9910
[MYSQL] mysql.ibd 文件解析 (sdi page) (非debug模式下查看隐藏系统表)
[MYSQL] mysql坏块检查
当mysql存在坏块的时候, 查询对应的表就会报错,然后数据库就crash了. 比如:
大大刺猬
2024/08/22
7240
[MYSQL] mysql坏块检查
[MYSQL] MY-012095 表空间ID不对
有时候需要使用mysql的数据文件做恢复, 或者其它某些异常导致mysqld启动的时候报错如下:
大大刺猬
2024/09/13
5120
[MYSQL] MY-012095 表空间ID不对
MySQL8.0修改lower_case_table_names参数导致重启失败
事件起因:在测试一个数据迁移工具时,源端oracle19c数据迁移到目标端MySQL8.0,提示迁移目标端 Unknown database 'SBTEST',报错如下:
GreatSQL社区
2023/02/23
2.1K0
docker安装Mysql8.0的坑之lower_case_table_names
看到mysql启动成功,同时也能正常连接。(这里是本地虚拟机测试,所以docker run没有外挂宿主目录,显然这是个不好的习惯)。用navicat试一下,
有一只柴犬
2024/01/25
1.8K0
docker安装Mysql8.0的坑之lower_case_table_names
[ibd2sql] MYSQL ibd文件解析 (6) BLOB/TEXT 页如何存储在磁盘上的 -- FIL_PAGE_TYPE_LOB_FIRST
虽然ibd2sql已经支持了 大字段(BLOB), 但还不支持溢出页(extra page), 也就是对大字段支持不完全. 是时候表演正在的技术了 是时候来完善大字段溢出页了.
大大刺猬
2024/05/13
3070
[ibd2sql] MYSQL ibd文件解析 (6)  BLOB/TEXT 页如何存储在磁盘上的 -- FIL_PAGE_TYPE_LOB_FIRST
小知识:MySQL修改lower_case_table_names参数
环境:MySQL 5.7.25 起初创建环境时没有要求表名称不区分大小写,后续应用使用提出要设置lower_case_table_names=1的需求,期望表名不再区分大小写。 修改这个参数需要重启实例,另外一定要注意该参数修改会导致之前大写存储的表将无法识别,需要特殊处理。
Alfred Zhao
2020/07/02
10.5K0
修改 lower_case_table_names 导致 frm 文件删除失败
经过分析发现,报错信息中的数据库,所有表名都混用了大小写字母,因为创建表之后,系统变量 lower_case_table_names 的值被从 0 修改为 1,导致删除这个数据库时,每个表的 ibd 文件删除成功,frm 文件删除失败。
csch
2023/05/24
8350
修改 lower_case_table_names 导致 frm 文件删除失败
【MySQL】lower_case_table_names参数详解
简介: lower_case_table_names 是mysql设置大小写是否敏感的一个参数。
MySQL技术
2019/09/08
3K0
[Linux&MYSQL] xfs文件系统浅析 -- 恢复drop的表
我们知道ibd2sql可以解析ibd文件从而恢复mysql的数据, 但没得ibd文件的时候又该怎么办呢? (哎呀, 不小心drop了表, 又没得备份!)
大大刺猬
2024/10/15
4862
[Linux&MYSQL]  xfs文件系统浅析 -- 恢复drop的表
[mysql8]新坑哈 更改Mysql 表的大小转换设置lower_case_table_names=1
在安装了8.0.14之后,初始化的时候在my.cnf里设置了lower_case_table_names=1,安装好了之后,启动报错:
landv
2019/09/12
9.1K0
LOWER_CASE_TABLE_NAMES 转
http://blog.csdn.net/jesseyoung/article/details/40617031
双面人
2019/05/21
1.1K0
[ibd2sql] mysql数据恢复案例003 -- 有坏块的表怎么解析?
数据文件是5.7环境的, 现在ibd2sql不再需要转换到8.0环境即可解析. 于是我们使用如下命令解析:
大大刺猬
2025/04/22
2490
[ibd2sql] mysql数据恢复案例003 -- 有坏块的表怎么解析?
mysql8卸载重新安装并配置lower_case_table_names=1
因为mysql8不支持在已经初始化完成后再进行配置lower_case_table_names
阿超
2022/12/05
8590
mysql8卸载重新安装并配置lower_case_table_names=1
[MYSQL] REDUNDANT行格式的数据解析
mysql的行格式有4种,REDUNDANT,COMPACT,DYNAMIC和COMPRESSED. 最常用的就是DYNAMIC, 也是mysql默认的行格式(很早只有REDUNDANT). 该行格式虽然复杂一点, 但是支持的索引前缀可达3072字节.(REDUNDANT只支持到768字节).
大大刺猬
2024/12/06
3220
[MYSQL] REDUNDANT行格式的数据解析
MYSQL] mysql坏块检查
当mysql存在坏块的时候, 查询对应的表就会报错,然后数据库就crash了. 比如:
用户10864049
2024/08/24
3540
[MYSQL] 当一个PAGE里的数据全部被delete之后, 它还会存在于Btree+中吗?
我们知道在mysql里, delete数据只会对其打上delete_flag, 不会真正的删除数据,该数据还在页内, 该页也还在Btree+中; 遍历树节点的时候发现有delete_flag的行就直接跳过.
大大刺猬
2025/06/12
3452
[MYSQL] 当一个PAGE里的数据全部被delete之后, 它还会存在于Btree+中吗?
推荐阅读
相关推荐
[MYSQL] 修改字段长度的时候不能使用instant算法? 其实inplace就够了
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档