热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

一点关于MySQL参数delay_key_write、myisam_recover_options的使_MySQL

一点关于MySQL参数delay_key_write、myisam_recover_options的使用经验
bitsCN.com

一点关于MySQL参数delay_key_write、myisam_recover_options的使用经验

最近在做数据库实例迁移的时候遇到了几个比较诡异的问题:

MyISAM实例正常shutdown后rsync数据文件到另外一台机器上起实例后,访问表时提示表自动修复失败需要repair table。提示信息:Table './test/record_03' is marked as crashed and last (automatic?) repair failed

表损坏后,利用repair table命令将表修复时提示表里存在很多的duplicate key.

warning : Duplicate key for record at 129584986 against record at 62008769

warning : Duplicate key for record at 104678355 against record at 61426294

warning : Duplicate key for record at 297493788 against record at 61697778

warning : Duplicate key for record at 209950328 against record at 61548867

warning : Duplicate key for record at 105894968 against record at 61866949

...

...

补充一下当时的环境信息:

1.MySQL版本为官方版的5.5.12,表引擎是MyISAM

2.迁移的步骤:stop slave->flush tables->正常shutdown实例->rsync表文件->在新机器上起实例。rsync前后表文件MD5值一样。

3.表的结构类似这样:

[sql]

create table test (

id int auto_increment primary key,

a varchar(100) not null,

b int not null,

c int,

unique key (a,b)

)

首先说第一个问题,这里分两点:1.为什么会需要修复?2.为什么自动修复失败?

我是正常关闭实例,不明白表需要修复的原因于是请淘宝丁奇帮忙分析了数据文件,显示文件头里记录显示表被关闭仍有6个线程在访问。但我可以确定当时rsync数据文件前是正常shutdown实例的,这个可能是MyISAM本身的问题或者是本身数据文件就已经存在问题都不得而知,总而言之当我迁移过来后访问表时需要修复这点是合理的,因为表被关闭时还有线程在访问,这会被MySQL认为表非正常关闭,需要修复。

为什么会自动修复失败,这是由于我配置了参数myisam_recover_optiOns=default,这个配置表示每次访问MyISAM表之前都会先检测表是否需要修复,如果需要则自动进行,这也就是前面看到信息last (automatic?) repair failed。而修复失败是因为这个参数带来的修复行为默认是从key cache里面找需要修复的数据,而我当时是shutdown实例,rsync到新环境中起实例,此时已没有当时的现场(key cache环境),加上default不会强制进行修复(强制修复表如果索引文件和数据文件数据不一致则自动进行删除或者增加行),(如果是myisam_recover_optiOns=force,那么即使此时key cache不存在了也会进行强制修复,此时做的就是对比数据文件和索引文件,然后删除数据文件中多余的行,因此这样可能会丢数据)。在自动修复时可以再error log中看到如下信息:

130410 9:31:23 [ERROR] /usr/local/mysql55/bin/mysqld: Table './image_0/record_00' is marked as crashed and should be repaired

130410 9:31:23 [Warning] Checking table: './image_0/record_00'

130410 9:31:24 [ERROR] Got an error from unknown thread, /export/home/pb2/build/sb_0-3198286-1302530066.93/mysql-5.5.12/storage/myisam/ha_myisam.cc:868

130410 9:31:24 [Warning] Recovering table: './image_0/record_00'

130410 9:31:28 [Note] Retrying repair of: './image_0/record_00' with keycache

130410 9:31:37 [ERROR] Couldn't repair table: image_0.record_00

接着说第二个问题,在第一个问题中提示表损坏,需要手工repair table,而我执行了这条命令后提示表里存在很多重复键数据:

warning : Duplicate key for record at 129584986 against record at 62008769

warning : Duplicate key for record at 104678355 against record at 61426294

warning : Duplicate key for record at 297493788 against record at 61697778

warning : Duplicate key for record at 209950328 against record at 61548867

warning : Duplicate key for record at 105894968 against record at 61866949

这个重复键指的是唯一键(a,b),然后进行了一个小测试验证是数据文件里面有重复的行(在a,b字段上)。逻辑图大概是这样

[plain]

id a b c

1 1 2 3

2 1 2 4

3 2 3 55

4 2 3 54

上面这个列表是我自己模拟的,在(a,b)上有唯一键约束,但是在数据文件中却存在(a,b)重复的行。验证方法较简单:

/*强制走全表扫描*/select * from test where a=val1 and b=val2;

结果集有2行

/*强制走索引*/select * from test where a=val1 and b=val2;

结果集只有1行

当时遇到问题第一反应是开发人员那边是不是曾经导过数据且导数据的时候禁止了唯一约束检查,但是事实上开发说自己没这么干过,于是开发说这是MySQL的bug,我怎么也觉得MySQL不会存在这样大的bug,一直觉得是对MySQL使用方法不对。于是对迁移前后的环境做了对比检查终于发现了疑点:老的环境中配置了delay_key_write=ALL,myisam_recover_optiOns=OFF(默认是OFF)。而我的新环境中则是delay_key_write=ON,myisam_recover_optiOns=default 。

简单解释下delay_key_write,每次更新MyISAM表索引后不立即将更新flush到物理磁盘上,这些修改依然保留在内存中,直到这个表被关闭时再flush,ALL表示对所有的表都使用这一行为,ON表示对创建表时使用了delay_key_write的表使用这个功能。OFF表示不进行delay key write。而官方建议在使用delay_key_write时同时用myisam_recover_options这样才能保证数据一致性,否则,举个最简单的例子,索引数据一致都没flush到磁盘上,突然表被非正常关闭,等下次表被访问如果不进行相应的检测修复,那么就会出现数据文件与索引不一致的情况,这样就会导致数据不一致。

再简单解释下myisam_recover_options,default表示每次访问表时会先判断是否需要修复,但是不会强制修复(仅仅尝试从key cache中修复),backup表示修复时会先将老的数据文件先做个备份,force表示强制修复,具体用法见下图。

此时就大致可以确定是由于MySQL参数使用不合理导致的数据不一致问题,所以在使用MyISAM时如果配置了delay_key_write,就千万记得同时配置一个myisam_recover_options这样才可能防止数据不一致性的情况出现。那么我是怎么解决这个问题的呢?目前来说还是通过迁移后的MySQL配置参数环境保持与老环境一致,否则如果我现在强制加上参数myisam_recover_options,那么就会导致所有的表损坏,损坏之后恢复的唯一途径就是repair table,这会丢失数据(或者配置myisam_recover_optiOns=force,backup,这个效果是跟repair table一样,且同时对将要修改的MYD文件做一个备份),因为对于重复键的行,如果是利用repair table去做的话,我无法干预MySQL留下其中具体的哪行,所以如果强行repair table虽然可以解决重复键错误,但是最终留下的哪行不一定是用户想要的那行数据。当然还有另外两种可行的方法,第一,咨询业务负责人后手工删除重复键中不需要的行。第二,强制repair table 然后将老的数据留一份做备份,然后用户端发现异常了再进行数据恢复,不过这个做法不可取,否则都会被用户投诉致死。

总之,都21世纪了,都5.6了,不要再用MyISAM了吧,我这是历史系统,没办法,后期进行升级改造也是必须进行的。

bitsCN.com
推荐阅读
  • 一、Hadoop来历Hadoop的思想来源于Google在做搜索引擎的时候出现一个很大的问题就是这么多网页我如何才能以最快的速度来搜索到,由于这个问题Google发明 ... [详细]
  • 推荐一个ASP的内容管理框架(ASP Nuke)的优势和适用场景
    本文推荐了一个ASP的内容管理框架ASP Nuke,并介绍了其主要功能和特点。ASP Nuke支持文章新闻管理、投票、论坛等主要内容,并可以自定义模块。最新版本为0.8,虽然目前仍处于Alpha状态,但作者表示会继续更新完善。文章还分析了使用ASP的原因,包括ASP相对较小、易于部署和较简单等优势,适用于建立门户、网站的组织和小公司等场景。 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 本文介绍了如何在MySQL中将零值替换为先前的非零值的方法,包括使用内联查询和更新查询。同时还提供了选择正确值的方法。 ... [详细]
  • 在数据分析工作中,我们通常会遇到这样的问题,一个业务部门由若干业务组构成,需要筛选出每个业务组里业绩前N名的业务员。这其实是一个分组排序的 ... [详细]
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • Oracle Database 10g许可授予信息及高级功能详解
    本文介绍了Oracle Database 10g许可授予信息及其中的高级功能,包括数据库优化数据包、SQL访问指导、SQL优化指导、SQL优化集和重组对象。同时提供了详细说明,指导用户在Oracle Database 10g中如何使用这些功能。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • 本文详细介绍了MysqlDump和mysqldump进行全库备份的相关知识,包括备份命令的使用方法、my.cnf配置文件的设置、binlog日志的位置指定、增量恢复的方式以及适用于innodb引擎和myisam引擎的备份方法。对于需要进行数据库备份的用户来说,本文提供了一些有价值的参考内容。 ... [详细]
  • 本文由编程笔记小编整理,介绍了PHP中的MySQL函数库及其常用函数,包括mysql_connect、mysql_error、mysql_select_db、mysql_query、mysql_affected_row、mysql_close等。希望对读者有一定的参考价值。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • Oracle分析函数first_value()和last_value()的用法及原理
    本文介绍了Oracle分析函数first_value()和last_value()的用法和原理,以及在查询销售记录日期和部门中的应用。通过示例和解释,详细说明了first_value()和last_value()的功能和不同之处。同时,对于last_value()的结果出现不一样的情况进行了解释,并提供了理解last_value()默认统计范围的方法。该文对于使用Oracle分析函数的开发人员和数据库管理员具有参考价值。 ... [详细]
  • 本文介绍了brain的意思、读音、翻译、用法、发音、词组、同反义词等内容,以及脑新东方在线英语词典的相关信息。还包括了brain的词汇搭配、形容词和名词的用法,以及与brain相关的短语和词组。此外,还介绍了与brain相关的医学术语和智囊团等相关内容。 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • “你永远都不知道明天和‘公司的意外’哪个先来。”疫情期间,这是我们最战战兢兢的心情。但是显然,有些人体会不了。这份行业数据,让笔者“柠檬” ... [详细]
author-avatar
好好_haohao_100
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有