Home  >  Article  >  Database  >  服务器上的Mysql表全丢了情况下恢复数据

服务器上的Mysql表全丢了情况下恢复数据

WBOY
WBOYOriginal
2016-06-07 14:51:221187browse

任务: web项目是在linux的Tomcat部署,Mysql也在上面,不知明原因下数据库宕机,启动不了,数据库表也突然没了,全空了!!!!!!!! mysql安装目录 惊喜的发现var/目录下有类似丢失数据库的表 接下来就是怎么恢复进去了,首先我们用的是mysql的InnoDb引擎,找了

任务:

web项目是在linux的Tomcat部署,Mysql也在上面,不知明原因下数据库宕机,启动不了,数据库表也突然没了,全空了!!!!!!!!

  • mysql安装目录

这里写图片描述

  • 惊喜的发现var/目录下有类似丢失数据库的表
    这里写图片描述

接下来就是怎么恢复进去了,首先我们用的是mysql的InnoDb引擎,找了下其资料:

<code class=" hljs sql">两种类型最主要的差别就是Innodb 支持事务处理与外键和行级锁.而MyISAM不支持.所以MyISAM往往就容易被人认为只适合在小项目中使用。
我作为使用MySQL的用户角度出发,Innodb和MyISAM都是比较喜欢的,但是从我目前运维的数据库平台要达到需求:99.9%的稳定性,方便的扩展性和高可用性来说的话,MyISAM绝对是我的首选。
原因如下:
1、首先我目前平台上承载的大部分项目是读多写少的项目,而MyISAM的读性能是比Innodb强不少的。
2、MyISAM的索引和数据是分开的,并且索引是有压缩的,内存使用率就对应提高了不少。能加载更多索引,而Innodb是索引和数据是紧密捆绑的,没有使用压缩从而会造成Innodb比MyISAM体积庞大不小。
3、从平台角度来说,经常隔1,2个月就会发生应用开发人员不小心<span class="hljs-operator"><span class="hljs-keyword">update</span>一个表<span class="hljs-keyword">where</span>写的范围不对,导致这个表没法正常用了,这个时候MyISAM的优越性就体现出来了,随便从当天拷贝的压缩包取出对应表的文件,随便放到一个数据库目录下,然后dump成<span class="hljs-keyword">sql</span>再导回到主库,并把对应的binlog补上。如果是Innodb,恐怕不可能有这么快速度,别和我说让Innodb定期用导出xxx.<span class="hljs-keyword">sql</span>机制备份,因为我平台上最小的一个数据库实例的数据量基本都是几十G大小。
<span class="hljs-number">4</span>、从我接触的应用逻辑来说,<span class="hljs-keyword">select</span> <span class="hljs-aggregate">count</span>(*) 和<span class="hljs-keyword">order</span> <span class="hljs-keyword">by</span> 是最频繁的,大概能占了整个<span class="hljs-keyword">sql</span>总语句的<span class="hljs-number">60</span>%以上的操作,而这种操作Innodb其实也是会锁表的,很多人以为Innodb是行级锁,那个只是<span class="hljs-keyword">where</span>对它主键是有效,非主键的都会锁全表的。
<span class="hljs-number">5</span>、还有就是经常有很多应用部门需要我给他们定期某些表的数据,MyISAM的话很方便,只要发给他们对应那表的frm.MYD,MYI的文件,让他们自己在对应版本的数据库启动就行,而Innodb就需要导出xxx.<span class="hljs-keyword">sql</span>了,因为光给别人文件,受字典数据文件的影响,对方是无法使用的。
<span class="hljs-number">6</span>、如果和MyISAM比<span class="hljs-keyword">insert</span>写操作的话,Innodb还达不到MyISAM的写性能,如果是针对基于索引的<span class="hljs-keyword">update</span>操作,虽然MyISAM可能会逊色Innodb,但是那么高并发的写,从库能否追的上也是一个问题,还不如通过多实例分库分表架构来解决。
<span class="hljs-number">7</span>、如果是用MyISAM的话,<span class="hljs-keyword">merge</span>引擎可以大大加快应用部门的开发速度,他们只要对这个<span class="hljs-keyword">merge</span>表做一些<span class="hljs-keyword">select</span> <span class="hljs-aggregate">count</span>(*)操作,非常适合大项目总量约几亿的<span class="hljs-keyword">rows</span>某一类型(如日志,调查统计)的业务表。
当然Innodb也不是绝对不用,用事务的项目如模拟炒股项目,我就是用Innodb的,活跃用户<span class="hljs-number">20</span>多万时候,也是很轻松应付了,因此我个人也是很喜欢Innodb的,只是如果从数据库平台应用出发,我还是会首选MyISAM。
另外,可能有人会说你MyISAM无法抗太多写操作,但是我可以通过架构来弥补,说个我现有用的数据库平台容量:主从数据总量在几百T以上,每天十多亿 pv的动态页面,还有几个大项目是通过数据接口方式调用未算进pv总数,(其中包括一个大项目因为初期memcached没部署,导致单台数据库每天处理 <span class="hljs-number">9</span>千万的查询)。而我的整体数据库服务器平均负载都在<span class="hljs-number">0.5</span>-<span class="hljs-number">1</span>左右。</span></code>

*MyISAM类型不支持事务处理等高级处理,而InnoDB类型支持

所谓事务处理,就是原子性操作。
打个比方,支持事务处理的Innodb表,建设一个中,发帖是给积分的。你发了一个帖子执行一个insert语句,来插入帖子内容,插入后就要执行一个update语句来增加你的积分。假设一种特殊情况突然发生,insert成功了,update操作却没有被执行。也就是说你发了帖子却没有增加相应的积分。这就会造成用户不满。如果使用了事务处理,insert和update都放入到事务中去执行,这个时候,只有当insert和update两条语句都执行生成的时候才会将数据更新、写入到中,如果其中任何一条语句失败,那么就会回滚为初始状态,不执行写入。这样就保证了insert和update肯定是一同执行的。mysiam表不支持事务处理,同时mysiam表不支持外键。外键不用说了吧?不知道的话,去网上查吧。同时,在执行数据库写入的操作(insert,update,delete)的时候,mysiam表会锁表,而innodb表会锁行。通俗点说,就是你执行了一个update语句,那么mysiam表会将整个表都锁住,其他的insert和delete、update都会被拒之门外,等到这个update语句执行完成后才会被依次执行。而锁行,就是说,你执行update语句是,只会将这一条记录进行锁定,只有针对这条记录的其他写入、更新操作会被阻塞并等待这条update语句执行完毕后再执行,针对其他记录的写入操作不会有影响。因此,当你的数据库有大量的写入、更新操作而查询比较少或者数据完整性要求比较高的时候就选择innodb表。当你的数据库主要以查询为主,相比较而言更新和写入比较少,并且业务方面数据完整性要求不那么严格,就选择mysiam表。因为mysiam表的查询操作效率和速度都比innodb要快*

恢复数据

初始化数据库

<code class=" hljs brainfuck"> <span class="hljs-string">.</span><span class="hljs-comment">/mysql_install_db</span> <span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-comment">user=mysql</span> <span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-comment">datadir=/usr/local/mysql/data</span> <span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-comment">basedir=/usr/local/mysql</span> </code>

注意初始化完成后事没密码登录的,如此便是初始化了,启动Mysql看看,发现可以了,不过数据没进去,那么InnoDb下
*.err
*.pid
mysql-bin-000010 等
ibdata1
ib-logfile0
ib-logfile1
TEST
是干什么呢?我们丢失的数据表假如是TEST,然后就是恢复进去数据给TEST.

  1. mysql-bin-000010 等是mysql的bin-log日志
    清理日志,需按照以下步骤:
      1. 在每个从属服务器上,使用SHOW SLAVE STATUS来检查它正在读取哪个日志。
      2. 使用SHOW MASTER LOGS获得主服务器上的一系列日志。
      3. 在所有的从属服务器中判定最早的日志。这个是目标日志。如果所有的从属服务器是更新的,这是清单上的最后一个日志。
      4. 制作您将要删除的所有日志的备份。(这个步骤是自选的,但是建议采用。)
      5. 清理所有的日志,但是不包括目标日志。
      my.cnf中有两个参数可以控制bin-log的。
    expire_logs_days
    二进制日志自动删除的天数。默认值为0,表示“没有自动删除”。
    SQL_LOG_BIN
    可以定义你此时的session的语句是否记录倒binlog中。关掉的话貌似可以提高1%的性能。bin-log中记录的是mysql的所有的操作信息,在还原是很有用,可以恢复到最近时间点。删除MYSQl BIN-LOG 日志,数据库坏了,误操作了,有日志还有的救,没日志又没备份,那就玩完了。
  2. ibdata1
    大多数地盘空间被 InnoDB 的共享表空间 ibdata1 使用.当 ibdata1 文件增长太快,通常是 MySQL 里长时间运行的被遗忘的事务引起的。尝试去解决问题越快越好(提交或者杀死事务),因为不经过痛苦缓慢的 mysqldump 过程,你就不能回收浪费的磁盘空间,非常推荐监控数据库以避免这些问题。
    比如IBDATA1的体积太大, 已经达到了300多G, 然后要扩展新的IBDATA, 于是我就在配置文件里面新加了一句,
    innodb_data_file_path = /old/ibdata1:296664170496M;/new/ibdata2:500G:autoextend:max:1000G

  3. ib-logfile0 ib-logfile1
    事务日志ib_logfile,事务日志或称redo日志,在mysql中默认以ib_logfile0,ib_logfile1名称存在,可以手工修改参数,调节
    开启几组日志来服务于当前mysql数据库,mysql采用顺序,循环写方式,每开启一个事务时,
    会把一些相关信息记录事务日志中(记录对数据文件数据修改的物理位置或叫做偏移量);
    作用:在系统崩溃重启时,作事务重做;在系统正常时,每次checkpoint时间点,会将之前写入事务
    应用到数据文件中。
    引入一个问题:在m/s环境中,innodb写完ib_logfile后,服务异常关闭,会不会主库能用ib_logfile恢复数据,而
    binlog没写导致从库同步时少少这个事务?从而导致主从不一致;
    redo日志写入方式:
    1.ib_logfile写入当前事务更新数据,并标上事务准备trx_prepare
    2.写入bin-log
    3.ib_logfile当前事务提交提交trx_commit
    恢复方式:
    如果ib_logfile已经写入事务准备,那么在恢复过程中,会依据bin-log中该事务是否存在恢复数据。
    假设:
    1)结束后异常,因没有写入bin-log,从库不会同步这个事务,主库上,重启时,在恢复日志中这个
    事务没有commit,即rollback这个事务.
    2)结束后异常,这会bin-log已经写入,从库会同步这个事务。主库依据恢复日志和bin-log,也正常恢复此事务
    综上描述:bin-log写入完成,主从会正常完成事务;bin-log没有写入,主从库rollback事务;不会出现主从库不一致问题.
    相关参数(全局&静态):
    innodb_log_buffer_size
    innodb_log_file_size
    innodb_log_files_in_group
    innodb_log_group_home_dir
    innodb_flush_log_at_trx_commit
    innodb_log_buffer_size:事务日志缓存区,可设置1M~8M,默认8M,延迟事务日志写入磁盘,
    把事务日志缓存区想象形如”漏斗”状,会不停向磁盘记录缓存的日志记录,而何时写入通过参数
    innodb_flush_log_at_trx_commit控制,稍后解释,启用大的事务日志缓存,可以将完整运行大事
    务日志,暂时存放在事务缓存区中,不必(事务提交前)写入磁盘保存,同时也起到节约磁盘空间占用;
    innodb_log_file_size:控制事务日志ib_logfile的大小,范围5MB~4G;所有事务日志ib_logfile0+
    ib_logfile1+..累加大小不能超过4G,事务日志大,checkpoint会少,节省磁盘IO,但是大的事务日
    志意味着数据库crash时,恢复起来较慢.
    引入问题:修改该参数大小,导致ib_logfile文件的大小和之前存在的文件大小不匹配
    解决方式:在干净关闭数据库情况下,删除ib_logfile,而后重启数据库,会自行创建该文件;
    innodb_log_files_in_group:DB中设置几组事务日志,默认是2;
    innodb_log_group_home_dir:事务日志存放目录,不设置,ib_logfile0…存在在数据文件目录下
    innodb_flush_log_at_trx_commit:控制事务日志何时写盘和刷盘,安全递增:0,2,1
    事务缓存区:log_buffer;
    0:每秒一次事务缓存区刷新到文件系统,同时文件系统到磁盘同步,但是事务提交时,不会触发log_buffer到文件系统同步;
    2:每次事务提交时,会把事务缓存区日志刷新到文件系统中去,且每秒文件系统到磁盘同步;
    1:每次事务提交时刷新到磁盘,最安全;
    适用环境:
    0:磁盘IO能力有限,安全方便较差,无复制或复制延迟可以接受,如日志性业务,mysql损坏丢失1s事务数据;
    2:数据安全性有要求,可以丢失一点事务日志,复制延迟也可以接受,OS损坏时才可能丢失数据;
    1:数据安全性要求非常高,且磁盘IO能力足够支持业务,如充值消费,敏感业务

  4. *.err
    错误日志
  5. *.pid
    MySQL pid 文件记录的是当前 mysqld 进程的 pid,pid 亦即 Process ID。
  6. TEST
    文件夹里面的那些表文件只是结构而已

修改my.cnf
socket初始化就有了,不必在意!
这里写图片描述

修改以下信息即可
这里写图片描述
然后重启即可
这里写图片描述

<code class=" hljs fix"><span class="hljs-attribute">mysqld_safe --defaults-file</span>=<span class="hljs-string">/etc/my.cnf &</span></code>

OK!
数据库就好了!好了很明显你登录Mysql时间会让你输入密码!!(初始化后千万不要/usr/local/mysql/bin/mysqladmin -S /tmp/mysql_3308.sock -u root password ‘new-password’)因为恢复的数据里有关于的密码数据。

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn