InnoDB: Failing assertion: trx->isolation_level == TRX_ISO_READ_UNCOMMITTED

最近再次碰到之前遇到的断言失败的bug,错误信息如下:

InnoDB: Failing assertion: trx->isolation_level == TRX_ISO_READ_UNCOMMITTED

 

这是一个已知的bug(bug#62037),在MySQL5.5.22版本中被fix掉,在lauchpad上可以看到具体是如何修复的

 

如何重现

重现case,使用gdb的non-stop模式很容易重现:

启动gdb,使用non-stop

set target-async 1

set pagination off

set non-stop on

断点:

row0upd.c:2033   (Percona Server5.5.18)

case:

session 1:

 CREATE TABLE `t1` (   `a` int(11) DEFAULT NULL,   `b` text,   `c` text ) ENGINE=InnoDB DEFAULT CHARSET=gbk;

insert into t1 values (1,repeat(‘b’, 7000), repeat(‘c’, 100));

update t1 set c = concat(c, repeat(‘c’, 2000));

这时候会因为更新列c而导致b列的数据被外部存储(b的列长最大),停在断点

session 2:执行查询

select * from t1 where a = 1;

该bug主要包含两个问题:

问题一:运行时断言失败

主要原因是:

1.更新记录时,undo中只记录了那些被更新的列,而由于其他列更新,导致某个列需要外部存储时,这个列的值不会写入undo。

也就是说,在从函数btr_cur_pessimistic_update中返回后,记录上某个未被更新的列,可能存储的是无效的指针

例如上述场景b列被选出来外部存储,因为它的长度最大,因此b列的数据被修改成一个尚未生效的值全为0的指针;

在悲观更新返回后,由于先mtr commit,再更新外部存储数据,这导致block及索引上的排他锁都被释放掉;这时候其他连接的查询是可以看到这条记录的。

2.虽然MVCC保证查询可以看到修改过的列,但1提到的未修改但被选作外部存储的列没有做undo,因此查询看到的是指针,导致触发断言失败,实例crash

解决:

官方的解决办法是在悲观更新和更新完外部存储列后,才进行mtr commit,这可以保证中间不会有其他查询看到未完成的更新(被阻塞住)

问题二:断言失败crash后,无法crash recovery

原因:

如果在完成悲观更新和写入外部存储列的过程中crash,记录更新可能完成了,但外部存储列是失败的,在crash recovery后,记录依然维持在不一致的状态。这样只要一访问该记录,就会报和问题一一样的断言crash错误

解决:

将上述逻辑修改为:

1.对原记录进行修改,mtr不提交(用btr_mtr代表该mtr)

2.扩展新的外部存储页(不能使用btr_mtr之前释放掉的page,暂时没搞明白为什么…),对新的外部存储页的写入(包括初始化)使用另外一个mtr(称为blob_mtr),对记录上指针的更新使用btr_mtr

3.commit blob_mtr

4.commit btr_mtr

这样在crash recovery的时候,就会先恢复blob页,再恢复记录上的操作;最差的情况就是丢失更新,ibd中存在一个有部分数据的无效blob页,但记录本身仍然能保持一致的状态

 

另外在插入记录时也可能触发该bug,例如,当一条记录被标记删除,但未被purge掉时,如果再次插入该聚集索引记录,被标记删除的记录就会被更新成现在的记录,这时候触发bug的逻辑就和上述Update的逻辑类似了。

时间: 2024-08-24 13:00:37

InnoDB: Failing assertion: trx->isolation_level == TRX_ISO_READ_UNCOMMITTED的相关文章

解决Mysql InnoDB: Failing assertion: ret || !assert_on_error问题

国庆回来后,发现mysql停止服务了,没办法继续启动了.查看日志,看到: 131008 09:56:03 mysqld_safe Starting mysqld daemon with databases from /var/lib/mysql 131008  9:56:03 [Warning] option 'read_buffer_size': unsigned value 1024 adjusted to 8192 131008  9:56:03 [Note] Plugin 'FEDERA

数据库内核月报 - 2015 / 05-MySQL · 捉虫动态 · 5.6 与 5.5 InnoDB 不兼容导致 crash

bug 背景 RDS的备份工具用的是 Percona-XtraBackup(后面简称PXB),这个工具包里有2个重要的工具,innobackupex和xtrabackup,后者是C编译出的二进制文件,负责备份 InnoDB 数据,前者是一个Perl 脚本,对后者进行封装,同时负责备份非 InnoDB 数据.xtrabackup 二进制里内嵌了InnoDB引擎,所以能很好的处理InnoDB数据.在2.2版本之前,PXB 分别针对不同版本的 MySQL 源码(5.1/5.5/5.6)编译了不同版本的

MySQL · 引擎特性 · Innodb change buffer介绍

前言 在前面几期月报我们介绍了undo log.redo log以及InnoDB如何崩溃恢复来实现数据ACID的相关知识.本期我们介绍另外一种重要的数据变更日志,也就是InnoDB change buffer. Change buffer的主要目的是将对二级索引的数据操作缓存下来,以此减少二级索引的随机IO,并达到操作合并的效果. 在MySQL5.5之前的版本中,由于只支持缓存insert操作,所以最初叫做insert buffer,只是后来的版本中支持了更多的操作类型缓存,才改叫change

MySQL案例-初步恢复: alter引起的从库无限Crash

-------------------------------------------------------------------------------------------------正文--------------------------------------------------------------------------------------------------------------- 场景 : Crash发生时的数据库版本: MySQL-5.7.17, 从库在同

MySQL 5.6.17/5.5.37 发布

MySQL产品线更新.5.6.17/5.5.37 2014-03-27 之前版本2013-01-31的5.6.16/5.5.36主要是Bug修正.5.1还是5.1.73. 完全改进: MySQL 5.6.17 改进记录 (2014-03-27) 新特性和各种改进 Incompatible Change: The AES_ENCRYPT() and AES_DECRYPT() functions now permit control of the block encryption mode and

[MySQL5.6] MySQL 5.6.17新特性:online optimize table (以及其他主要bugfix)

在刚刚放出来的MySQL5.6.17版本中,最引人注意的功能当属于能够在线的进行opimitze table操作,这可以帮助减小表的大小而无需阻塞并发负载,另外以下几类操作也开始支持online ddl: OPTIMIZE TABLE ALTER TABLE ... FORCE ALTER TABLE ... ENGINE=INNODB (when run on an InnoDB table) 上述操作将触发表的rebuild,代码的改动量非常小 修改见 [Rev:5820] 这几个选项从sq

InnoDB 中文参考手册 --- 6 备份和恢复 InnoDB 数据库

备份|参考|参考手册|恢复|数据|数据库|中文 InnoDB 中文参考手册 --- 犬犬(心帆)翻译 6 备份和恢复 InnoDB 数据库安全的数据库管理就是使用正规的数据备份. InnoDB Hot Backup 是一个在线备份工具,你可以在 InnoDB 数据库运行时使用它来实现在线备份.InnoDB Hot Backup 不需要你关闭你的服务器也不需要加任何锁或影响其它普通的数据操作.InnoDB Hot Backup 是一个非免费的附加工具,它的费用为每 MySQL 服务器每年 400

《MySQL技术内幕:InnoDB存储引擎第2版》——2.7 启动、关闭与恢复

2.7 启动.关闭与恢复 InnoDB是MySQL数据库的存储引擎之一,因此InnoDB存储引擎的启动和关闭,更准确的是指在MySQL实例的启动过程中对InnoDB存储引擎的处理过程. 在关闭时,参数innodb_fast_shutdown影响着表的存储引擎为InnoDB的行为.该参数可取值为0.1.2,默认值为1. ?0表示在MySQL数据库关闭时,InnoDB需要完成所有的full purge和merge insert buffer,并且将所有的脏页刷新回磁盘.这需要一些时间,有时甚至需要几

mysql qpress压缩备份恢复

说明: 1.前面博客已经介绍过gzip压缩方法,备份正常,但后来测试恢复的时候,发现命中bug,报错如下:  InnoDB: Page [page id: space=9494, page number=27743946] log sequence number 2332453520996 is in the future! Current system log sequence number 2332453312855. InnoDB: Your database may be corrupt