You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MariaDB崩溃日志分析及添加分区时崩溃问题求助

MariaDB添加分区时崩溃问题排查

崩溃信息

执行添加分区的SQL时,MariaDB 10.4.6在Windows平台崩溃,异常栈如下:

Thread pointer: 0x1ce1ecc6ab8
Attempting backtrace. You can use the following information to find out
where mysqld died. If you see no messages after this, something went
terribly wrong...
mysqld.exe!ha_partition::read_par_file()[ha_partition.cc:3021]
mysqld.exe!ha_partition::get_from_handler_file()[ha_partition.cc:3161]
mysqld.exe!ha_partition::initialize_partition()[ha_partition.cc:512]
mysqld.exe!partition_create_handler()[ha_partition.cc:185]
mysqld.exe!get_new_handler()[handler.cc:302]
mysqld.exe!TABLE_SHARE::init_from_binary_frm_image()[table.cc:2025]
mysqld.exe!open_table_def()[table.cc:698]
mysqld.exe!tdc_acquire_share()[table_cache.cc:842]
mysqld.exe!open_table()[sql_base.cc:1905]
mysqld.exe!open_and_process_table()[sql_base.cc:3802]
mysqld.exe!open_tables()[sql_base.cc:4300]
mysqld.exe!mysql_alter_table()[sql_table.cc:9353]
mysqld.exe!Sql_cmd_alter_table::execute()[sql_alter.cc:510]
mysqld.exe!mysql_execute_command()[sql_parse.cc:6087]
mysqld.exe!Prepared_statement::execute()[sql_prepare.cc:4760]
mysqld.exe!Prepared_statement::execute_loop()[sql_prepare.cc:4246]
mysqld.exe!mysql_sql_stmt_execute()[sql_prepare.cc:3364]
mysqld.exe!mysql_execute_command()[sql_parse.cc:3901]
mysqld.exe!sp_instr_stmt::exec_core()[sp_head.cc:3652]
mysqld.exe!sp_lex_keeper::reset_lex_and_exec_core()[sp_head.cc:3335]
mysqld.exe!sp_instr_stmt::execute()[sp_head.cc:3513]
mysqld.exe!sp_head::execute()[sp_head.cc:1346]
mysqld.exe!sp_head::execute_procedure()[sp_head.cc:2288]
mysqld.exe!do_execute_sp()[sql_parse.cc:3005]
mysqld.exe!Sql_cmd_call::execute()[sql_parse.cc:3247]
mysqld.exe!mysql_execute_command()[sql_parse.cc:6087]
mysqld.exe!sp_instr_stmt::exec_core()[sp_head.cc:3652]
mysqld.exe!sp_lex_keeper::reset_lex_and_exec_core()[sp_head.cc:3335]
mysqld.exe!sp_instr_stmt::execute()[sp_head.cc:3513]
mysqld.exe!sp_head::execute()[sp_head.cc:1346]
mysqld.exe!sp_head::execute_procedure()[sp_head.cc:2288]
mysqld.exe!Event_job_data::execute()[event_data_objects.cc:1459]
mysqld.exe!Event_worker_thread::run()[event_scheduler.cc:312]
mysqld.exe!event_worker_thread()[event_scheduler.cc:268]
mysqld.exe!pthread_start()[my_winthread.c:62]
ucrtbase.dll!_configthreadlocale()
KERNEL32.DLL!BaseThreadInitThunk()
tdll.dll!RtlUserThreadStart()

Trying to get some variables.
Some pointers may be invalid and cause the dump to abort.
Query (0x1ce21cf66b8): alter table mytable add PARTITION (PARTITION t20221103 VALUES LESS THAN (TO_DAYS("2022-11-03")+1))
Connection ID (thread ID): 1649
Status: NOT_KILLED

执行环境:Windows平台,无法调试核心文件。

源码定位

查看MariaDB 10.4.6版本的ha_partition.cc对应代码片段,崩溃发生在读取.par文件的逻辑中:

chksum= 0;
  for (i= 0; i < len_words; i++)
    chksum ^= uint4korr((file_buffer) + PAR_WORD_SIZE * i);
  if (chksum)
    goto err2;
  m_tot_parts= uint4korr((file_buffer) + PAR_NUM_PARTS_OFFSET);
  DBUG_PRINT("info", ("No of parts: %u", m_tot_parts));
  tot_partition_words= (m_tot_parts + PAR_WORD_SIZE - 1) / PAR_WORD_SIZE;

  tot_name_len_offset= file_buffer + PAR_ENGINES_OFFSET +
                       PAR_WORD_SIZE * tot_partition_words;
  tot_name_words= (uint4korr(tot_name_len_offset) + PAR_WORD_SIZE - 1) /
                  PAR_WORD_SIZE;  // <--- crashed here

1. 分析是否正确

你的分析准确:这确实是加载.par文件时的Bug。虽然代码中做了校验和检查,但校验逻辑存在漏洞——当m_tot_parts的值异常时,会导致tot_name_len_offset计算后指向文件缓冲区之外的内存地址,调用uint4korr读取该地址时触发崩溃。说明现有校验未覆盖m_tot_parts的合法性检查,或者.par文件已损坏但校验和未检测出问题。

2. 绕过异常的方法

  • 重建分区表迁移数据:先备份原表数据,创建带目标分区的新表,再将数据导入新表,最后替换原表。示例步骤:
    -- 创建新分区表
    CREATE TABLE new_mytable LIKE mytable;
    ALTER TABLE new_mytable PARTITION BY RANGE TO_DAYS(your_date_column) (
        PARTITION t20221103 VALUES LESS THAN (TO_DAYS("2022-11-03")+1)
        -- 添加其他需要的分区
    );
    -- 导入数据
    INSERT INTO new_mytable SELECT * FROM mytable;
    -- 替换原表
    RENAME TABLE mytable TO old_mytable, new_mytable TO mytable;
    
  • 升级MariaDB版本:该Bug大概率在后续版本中被修复,建议升级到10.4.x系列的最新稳定版,或直接升级到更高版本(如10.5+)。
  • 修复或重建.par文件:找到表对应的.par文件(位于MariaDB数据目录下,与.frm文件同目录),先备份该文件,然后删除它,重启MariaDB服务后再尝试执行分区操作。服务重启后会自动重建.par文件。

3. MariaDB崩溃日志分析方法

  • 定位崩溃核心函数:从崩溃栈顶部(最靠前的mysqld.exe函数)找到崩溃的具体函数和文件行号,结合源码逻辑分析问题点。
  • 结合执行SQL:崩溃时的Query信息直接指出触发崩溃的操作(ALTER TABLE添加分区),缩小问题范围到分区管理相关逻辑。
  • 检查源码逻辑:分析崩溃点附近的代码,判断是内存越界、非法指针访问还是数据校验缺失。比如这里是计算偏移时未做边界检查,导致读取了缓冲区外的内存。
  • 查看系统和数据库日志:Windows下通过事件查看器查看应用日志,同时检查MariaDB的error.log,看是否有崩溃前的异常信息(如磁盘空间不足、文件权限问题、表结构损坏预警等)。
  • 复现验证:在测试环境搭建相同版本的MariaDB,创建相同结构的表,执行相同的SQL,尝试复现崩溃,验证问题原因的推测。

内容的提问来源于stack exchange,提问作者Wotchin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 11:21:00