mysql存储在磁盘中,各种天灾人祸都会导致数据丢失。大公司的时候我们常常需要做好数据冷热备,对于小公司来说要做好所有数据备份需要支出大量的成本,很多公司也是不现实的。万一还没有做好备份,数据被误删除了,或者ibdata损坏了怎么办呢?别担心,只要有部分的frm、ibd存在就可以恢复部分数据。

注意:
一、这个是对innodb的数据恢复。myisam不需要这么麻烦,只要数据文件存在直接复制过去就可以。
二、大家的mysql数据库必须是按表存放数据的,默认不是,但是大家生产肯定是按分表设置的吧,如果不是,不好意思,这个方法不能恢复你的数据。my.ini的设置为 innodb_file_per_table = 1。

参考 http://blog.chinaunix.net/uid-24111901-id-2627876.html

1、找回表结构,如果表结构没有丢失直接到下一步

    a、先创建一个数据库,这个数据库必须是没有表和任何操作的。
    b、创建一个表结构,和要恢复的表名是一样的。表里的字段无所谓。一定要是innodb引擎的。CREATE TABLE `weibo_qq0`( `weiboid` bigint(20)) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    c、关闭mysql, service mysqld stop;
    d、用需要恢复的frm文件覆盖刚新建的frm文件;
    e、修改my.ini 里 innodb_force_recovery=1 , 如果不成修改为 2,3,4,5,6。
    f、 启动mysql,service mysqld start;show create table weibo_qq0 就能li到表结构信息了。

2、找回数据。记得上面把 innodb_force_recovery改掉了,需要注释掉,不然恢复模式不好操作。 这里有个关键的问题,就是innodb里的任何数据操作都是一个日志的记录点。也就是如果我们需要数据恢复,必须把之前的表的数据的日志记录点添加到一致。

    a、建立一个数据库,根据上面导出的创建表的sql执行创建表。
    b、找到记录点。先要把当前数据库的表空间废弃掉,使当前ibd的数据文件和frm分离。 ALTER TABLE weibo_qq0 DISCARD TABLESPACE;
    c、把之前要恢复的 .ibd文件复制到新的表结构文件夹下。 使当前的ibd 和frm发生关系。ALTER TABLE weibo_qq0 IMPORT TABLESPACE; 结果不出意外肯定会报错。就和我们开展数据开始说的那样,数据记录点不一致。我们看看之前ibd记录的点在什么位置。开始执行 import tablespace,报错 ERROR 1030 (HY000): Got error -1 from storage engine。找到mysql的错误日志,InnoDB: Error: tablespace id in file ‘.\test\weibo_qq0.ibd’ is 112, but in the InnoDB InnoDB: data dictionary it is 1. 因为 weibo_qq0 之前的记录点在112,当前的表只创建一次,所以记录点是1.
    d、那怎么从1记录到112。for ($1=1; $i<=111; $1++) {CREATE TABLE t# (id int) ENGINE=InnoDB;} 也许很奇怪,为什么是循环111,不是112。因为在a执行创建表结构的时候已经记录增加了一次。 e、修改表结构 alter table weibo_qq0 discard tablespace;使当前的表结构和ibd脱离关系。复制.ibd到当前的目录结构。 f、使原来数据的ibd和当前frm建立关系。 ALTER TABLE product IMPORT TABLESPACE; 这个时候没有错误,说明已经建立好了。但是查询数据还是查不出来。 g、相比这里大家已经知道为什么了,这个模式也不是说改了数据库就可以在生产环境使用。更改 innodb_force_recovery=1 , 如果不成修改为 2,3,4,5,6。直到可以 查询出数据为止,然后dump出来。数据就备份出来了。 h、把所有数据导出后,在新的数据库导入。所有数据就生成了。

扩展问题,很多时候我们是分表表结构怎么批量操作,提高速度呢。用循环!循环把表的空间废弃掉。
for i in `seq 0 111`; do mysql -uroot -P33061 -h127.0.0.1 -Dtestdd -e “CREATE TABLE inv_crawl_weibo_qq$i (id bigint(20) NOT NULL AUTO_INCREMENT,PRIMARY KEY (id)) ENGINE=innodb “; done
ALTER TABLE inv_crawl_weibo_qq0 DISCARD TABLESPACE;
从备份数据把ibd复制cp到dd数据库下,注意复制过来的文件权限。
循环导入表空间。
ALTER TABLE inv_crawl_weibo_qq0 IMPORT TABLESPACE;
没有报错就导入成功了

原创文章,转载请注明: 转载自LANCEYAN.COM

本文链接地址: Mysql ibdata 丢失或损坏如何通过frm&ibd 恢复数据

      在创业开始时,也许有一个点子,经过研究调查有市场可行性就开始召集人员开始创业。这个时候一般都是单打独斗,一两个人负责所有的事情,包括产品设计、交互原型设计、网页美工切割、程序开发、功能测试。这个时候基本不用合作,采用独立开发模式,自己搞定保存就可以了。不过也有风险就是硬盘坏了怎么办呢,要知道硬盘是最脆弱的东西了,我一般的话会定期备份硬盘的东西。

      如果发现创业模式可行,需要赶时间抢市场,一两个人完成不了很多任务,就需要更多专业的人加入才能做出一个交互很好、页面美观、功能好用的产品。这个时候一般的话应该有产品经理、美工设计、程序开发、测试、运维。但是这些角色不是说一定要安排这么多岗位的人,需要根据公司具体自身情况来设定。

    有了点市场机会,时间才是最重要的。如果按照传统的计划型开发模式就不太适合了,敏捷开发还算比较相像。不一定说非要采用什么开发模式,这个也要根据自己的公司来决定。我们的模式应该是像中国的社会主义社会一样是基于敏捷的XX公司的开发模式。

      好了,岗位都有了,咱们怎么分工合作呢?这时,因为是根据点子来演化产品,很多东西都是不确定的,不能定一个大的一成不变的长时间计划和需求。毕竟这个时候要求需求不变也是不可能的,我们本身自己就充当了产品经理的角色。不只要想市场和老板的需求,还要产品本身和功能实现的需求,逐步把一个模糊的东西变成可以实际操作的产品原型,再形成最终产品。结合敏捷开发的特点,以人为本,把一个大的需求分成小需求分给适合的人来完成。上面所说的那些角色不一定每个岗位都需要一个具体的人,也可以是一个人承担一个角色,或者多个人承担一个角色。比如我们公司暂时就没有产品经理、测试、运维,程序开发负责开发、测试、运维,产品设计所有人都要参与。总体产品设计由一个人来把关和跟踪,细分到每一个产品都要对自己的产品负责分析和跟进。相当于贯彻了一句话,好像来自于阿里巴巴的一个产品写的一本书《人人都是产品经理》。如果自己对自己的产品都不清楚、玩不转、操作不了,谈什么让用户喜欢呢?不管美工、研发、测试、运维,都需要对产品有很好的理解。如果可以的话,不只是要理解自己做的一小块需求的产品,还应该了解更多其他同事的产品。作为产品总体把关的人一般是技术总监需要对每一个产品都很熟悉,这样才能跟进和设计讨论。所以研发、美工、测试、运维不管做什么工作,都需要站在一定高度思考问题,既然创业就需要以创业的角度思考,这样对自己的职业发展有帮助,也可以做好产品。

      在根据一个大需求技术总监和大家讨论,把模糊的东西逐步清晰化得到一个比较明确的做法后分到合适的人上。这样大家各自领导自己的需求开始分析具体实现,得到一个大概的思路后再和技术总监讨论确定最终具体实现。关于美工总体需求分析可以参与,这样便于了解整个需求,还是那句话了解了才能设计出好看好用的产品界面。细节的需求和技术实现就让研发来想和确定。在研发确定好了实现方案后,和美工进行讨论界面的实现方案,这个时候美工就清楚了小需求的实现功能和界面方案。然后美工设计界面,有时间可以多弄几个方案,开始可以在草图用笔画,也要沟通、讨论、确定。最后选择一个用户界面,研发开始开发程序、美工切割页面。如果美工的模板和规范基本都有确定了,那工作可能就不是太紧张,所以可以应对几个开发的需求。这个根据具体的情况确定美工的人数。

      研发开始可以自己弄页面,先把动态的标签确定好了,后面根据美工切割的页面套入。然后研发后台逻辑,一般都是从前台到后台开发甚至db开发都需要懂点,这样才能保证高效开发。如果横向切分,一些人研发service、一些人研发dao,一些研发jsp会增加不必要的沟通浪费时间。如果后面项目庞大了,还是建议应该增加一个专业的前端js开发和后台DBA。研发开发好自己的业务代码对功能进行测试,测试ok技术总监确认就等集成连调。这个时候的开发都是在自己的本机完成,不在测试环境测试是为了提供研发速度和效率。大家都知道如果是java开发,部署war不断reload会影响他人的工作,如果工程比较大启动也比较慢。如果在本机,只是修改类里面的东西和jsp等直接就可以看到效果。修改类签名和增加类等需要重新部署。

      大家都开发好自己的模块后,集中在测试服务器集成测试。这里可以由指定人来打包部署,大家一起测试找问题,修改。关于前端一般是自己改好了原型界面,后面被嵌入了动态页面后就直接修改动态页面了。预览在集成服务器,这里可以把预览和svn服务器集成,前端美工提交jsp到svn后就生效,他也可以直接看到效果了。具体操作后面文章再介绍。最后测试没有问题,老板确认,发布外网服务器、部署db。这里也容易出错,如果发布者不是本人很容易漏掉东西,所以最好在发布时,如果改了除了程序以前的东西需要提供发布列表一并修改。

      再以后随着项目的庞大和人员的扩充就需要借助更多的模式和辅助工具来寻找更适合自己的方式了。比如页面发布工具(前端可以直接发布IDC)、持续集成(可以自动部署测试和IDC)等等。项目中最最重要的还是人,根据人来选择不同的工作模式,就像豆瓣CEO说的,什么语言工具技术都没关系,最重要的是人、团队。相信经过大家的磨合, 每一个都是超人(技能、沟通、合作)的团队就是这么诞生的。

原创文章,转载请注明: 转载自LANCEYAN.COM

本文链接地址: 谈谈创业公司技术的工作模式

不管是什么程序开发都可能会出现各种各样的异常。可能是程序错误,也可能是业务逻辑错误。针对这个各个开发人员都有自己的处理方式,不同的风格增加了业务系统的复杂度和维护难度。所以定义好一个统一的异常处理框架还是需要的。我们开发框架采用java实现,java中的异常一般分为两种,检查异常和运行时异常。检查异常(checked exception)有可能是程序的业务异常,这种异常一般都是开发人员自定义的、知道什么时候会抛出什么异常并进行捕捉处理。也可以是系统的异常,不捕捉编译不会通过,如  IOException、SQLException、ClassNotFoundException , 这种是必须要捕捉的并且大多都是继承Exception。 运行时异常一般都是系统抛出来的异常,这种异常不捕捉处理也不会报编译错误,如NullPointerException,ClassCastException。运行异常都是继承至RuntimeException。不管是检查异常还是运行时异常都是继承至Exception。另外还有一种异常是系统错误Error,这种异常是系统出现了故障抛出来的不能捕捉,如OutOfMemoryError。Exception和Error都是继承至Throwable。

了解了java的异常体系后,我们设计一下web框架的异常处理格式。在以往EJB时代的J2ee系统,一般是标准的三层架构:web层、业务逻辑层、数据访问层,并且每一层都分别部署在不同的机器集群中。这样我们的异常一般分为三个,WebException、BizException、DAOException分别映射到web层、业务逻辑层、数据访问层。并且这些异常都要设计的串行化可以跨机器传递生成异常链。这样的好处是看到异常链知道从哪儿抛出来的错误,比较清晰明了。

老异常链

随着后面spring的推出,java的开发越来越轻量级很多时候一台服务器可以同时部署三层并集群化,架构模式也慢慢由充血模式演变为贫血模式,再也没有了厚重的实体Bean和有状态会话Bean。针对现在轻量级的框架,异常结构如何设计呢?

先看看我们这个异常结构需要解决的问题是什么?

  1. 规范大家的异常处理方式。
  2. 简化异常处理。
  3. 区分业务异常和系统异常,业务异常需要业务逻辑支持,系统异常需要记录log。
  4. 友好的异常展示。
  5. 异常结构可扩展。

针对这些点,我的想法是开发可以使用三个类:SDKException、BizException、BizSystemException。SDKException是处理的基础类,可以在里面封装一些异常处理的基本函数。BizException是业务逻辑处理异常,一般这类异常是不需要记录log,只是展示给页面显示并提示给用户。如你的用户名、密码为空等错误。BizSystemException是业务系统异常,这类异常一般需要捕捉并记录log,比如数据库的主键冲突、sql语句错误等。按照三层架构的话,我们不可能对每一层都捕捉并且记录log,会造成重复log。可以从DAO层把捕捉到的数据库异常转换为BizSystemException抛出,如果有BizException也抛出。业务逻辑层对于BizSystemException、BizException不处理直接抛出。所有处理都在web层进行集中处理,如果是BizException,根据错误码和错误消息显示给用户对应的页面和错误消息。如果是BizSystemException告知用户系统错误,并把错误结果记入log。如果是其他异常和BizSystemException一致。这样就减少了异常处理的复杂度,开发也不用关心什么检查异常,运行时异常。

新错误结构

如果是ajax请求在做web层时,把返回的jsp变成json格式或者流格式输出即可,不影响异常框架。如采用struts2结构的代码:

public String testAjax()
{
    try
    {
         genAjaxDataStr(0, "{}");
    } catch (BizException e)
    {
         getRequest().setAttribute(this.ERRORMESSAGE, e.getErrorMessage());
         return this.ERRORJSON;
    } catch (BizSystemException e)
    {
         getRequest().setAttribute(this.ERRORMESSAGE, this.SYSTEMERROR);
         return this.ERRORJSON;
    } catch (Exception e)
    {
         this.errorTrace("test", e.getMessage(), e);
         getRequest().setAttribute(this.ERRORMESSAGE, this.SYSTEMERROR);
         return this.ERRORJSON;
    }
    return this.NONE;
}

这样前台就能根据我们的异常显示对应的错误页面了,并能把系统知道的和未知的异常记入log。

针对struts2还有个问题,在开发模式时,struts2和webwork的异常打印在页面,我们可以根据页面输出进行调试。一但部署在生产环境,需要将这个模式关闭,log就没有了。

<constant name="struts.devMode" value="false" />

为了记录一些未知的错误,需要做以下步骤:

  1. 将全局的异常映射页面从struts2的包定义里去掉。如果不去掉,在webwork不会抛出异常也就找不到出了什么问题。
  2. 扩展struts的DispatcherFilter捕捉未知的异常并记录入log。
<global-exception-mappings>
    <exception-mapping exception="com.linktong.sdk.biz.exception.BizException"
                result="checkedException" />
</global-exception-mappings>

这样,基本的异常框架就搭建完成。更进一步需要做的是:

  1. 分布式全局错误码体系,保证所有机器都共用一套错误码。
  2. 分布式部署,异常传递。可以采用hessian序列化错误码的机制,不用传输整个异常链节省带宽。
  3. 集中logger服务处理,所有机器的log统一发送到集中服务器处理。logger框架和log4j也有服务器的机制。

针对web框架、分布式部署、log服务器再讨论:)

原创文章,转载请注明: 转载自LANCEYAN.COM

本文链接地址: WEB框架的错误体系