前言
没有人比我更惨了,平时不备份,还经常会出现各种各样奇奇怪怪的mysql问题。此篇为血泪教训。
Q1:mysql服务启动不了的原因
(1)我打开了服务管理页面,然后发现mysql没有启动成功,于是我点击启动,奥,启动不成功。服务管理页面打开方法,先win+r,然后输入services.msc就行
请尝试操作:
(2)我尝试了方法1还是不行,那就得查看原因。应该都知道自己的mysql目录安装在哪吧。不知道的话,去查看编辑环境变量里的path里面的参数设置。
查看原因方法:首先打开你mysql的data目录,比如我的在D:\program\mysql-8.0.28-winx64\data这个目录下,找到后缀为.err的文件,这个是存储你的mysql服务启动信息的,请用记事本打开。
(2.1)err文件显示的启动错误原因,如果最新的错误原因里有pid等字眼的,看不懂就拿去翻译一下,如果说是进程问题的,那应该就是你的端口号被占用了。mysql端口号为3306,你没有改过就是这个了。
解决方法:当然是要先把占用端口的进程关掉啊,先win+r,输入cmd,回车就进入管理者命令行了。然后输入
netstat -ano | findstr 3306
tasklist | findstr 进程ID
最后再启动,看行不行吧,如果还出错,就重启一遍再试试。
(2.2).err的错误原因不是这个,是别的,也是先翻译问题,然后去百度找答案。
我遇到的问题,百度出来都不行,只能采取终极方法了。
终极方法
数据库的数据可以丢,那就看完第一二步就行。
(1)数据库里的数据我不能丢啊,没有备份
这个情况呢,首先将data整个目录给另存一份出来,最好就是一份zip一份解压这样用。要不然保存出来的如果被污染了,就啥啥没有了。
第一步(备份data目录啊):
备份好后,清空data目录下的文件,并且打开bin目录,进入它的命令行页面
然后具体的推荐去看一下这个博主的文章,这个博主写的很详细,但是数据库改密码的不建议采用.
https://blog.csdn.net/G18336319744/article/details/129761304
更改密码的,请先进入mysql>这个页面里,链接的博主里有说
然后输入
ALTER USER 'root'@'localhost' IDENTIFIED BY '新密码';
然后退出,再尝试登进去就行了。
第二步,输入net start mysql应该就可以启动成功了。如果不行就
执行三步骤,这样基本就可以了。
sc delete mysql
mysqld -install
net start mysql
还是不行,就继续尝试上面的操作。到这一步可以用新密码去打开navicat了。navicat之前建立的那些连接口别随便删啊,因为里面有一些sql文件在这里的,你那些查询函数啊都在里面(我又一次的教训啊)。
第三步:修复数据,你们会发现data里面的数据库对应的表数据都是ibd结尾的文件。(到这一步的时候,你们先别按我的方法,我给你介绍一篇文,如果那篇文的操作照做了,还是恢复不了。很好,你们沦落到我这个地步了。)
https://blog.csdn.net/baidu_34831792/article/details/109044189 先看别人的,别人的如果ok,就别尝试我的了,我的是要开成地狱级别的了。
其实前面那么多个步骤,看起来多,但其实也不多。都是我的教训,教训啊,我要发牢骚,我为什么手贱,为什么手贱,乱导sql文件,把mysql里的user给重置了,为什么为什么!!!还是恢复不了的那种手贱错误,前面的那么多个步骤全是我不辞辛劳,看了至少500篇解决文章提炼出来的解决方法,别人的那些方法要不就是老旧,要不就是不对我的情况,我的情况错到离谱啊,经此一战,实话说,我对于mysql的目录都快能手写出来了,我尝试过从binlog里提取sql文件,然后提取到了导致我mysql服务起不来的sql文件,然后服务再次宕机。我又开始清除data目录,最后我都是三个data目录来回切换组装的。一个原始数据,一个全新没问题的,还有一个造作的。
(还是对我没用,binlog文件应该会定期删除的,我早期的数据提取不出来。binlog文件1kb那些解析没用,里面没有实用数据,得至少是几十k那种才有用,亲测)binlog提取sql文件的文章:MySQL使用binlog恢复数据_mysqlbinlog恢复数据-CSDN博客
最后我发现至关重要的文件是:
mysql.ibd和各个数据库的文件,好了我吐槽完了。我现在展示一下如何把数据弄回去,这将是一个漫长的过程,但和我数据库丢失比起来不是问题不是问题啊!
(1)比如我要恢复名字叫“mvc”的数据库,我首先得在navicat手动建一个这个名称的
建好后,网上说要重新建一个与原来表一样的表结构,得从frm文件里获取建表语句的,但是我只有ibd的文件啊。mysql8.0以后的版本都将myd,frm,sdi的文件都合并在ibd文件里了,但是前提是你得有建表语句啊,我是写了一个java工具来提取的。
首先打开原始data目录的mvc数据,进入到那个页面命令行,输入:
ibd2sdi --dump-file rb_position.txt tb_book.ibd
java工具代码:
package com.chu.controller;
import org.json.JSONArray;
import org.json.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
public class xx {
public static void test() throws JsonMappingException, JsonProcessingException {
// 替换为你的 JSON 字符串
String jsonData = "放你那个txt文件";
if (jsonData.length() == 9) {
System.out.print("你没替换数据");
return;
}
jsonData = jsonData.substring(15, jsonData.length() - 3);
// 解析 JSON 数据
// ObjectMapper jsonObject = new ObjectMapper(jsonData);
ObjectMapper objectMapper = new ObjectMapper();
JsonNode jsonObject = objectMapper.readTree(jsonData);
// 提取表名和字段信息
JsonNode x = jsonObject.get("object").get("dd_object").get("name");
String tableName = x.asText();
System.out.println(tableName);
JsonNode columns = jsonObject.get("object").get("dd_object").get("columns");
if (columns == null) {
System.out.print("ddddsd");
return;
}
// JSONArray columns = new JSONArray();
// 构建创建表的 SQL 查询语句
StringBuilder sql = new StringBuilder("CREATE TABLE " + tableName + " (");
String priString = "";
for (JsonNode column : columns) {
String columnName = column.get("name").asText();
// 如果字段名不是 DB_TRX_ID, DB_ROLL_PTR, DB_ROW_ID,则构建该字段的 SQL
if (!"DB_TRX_ID".equals(columnName) && !"DB_ROLL_PTR".equals(columnName)
&& !"DB_ROW_ID".equals(columnName)) {
String columnType = column.get("column_type_utf8").asText();
String isNullable = column.get("is_nullable").asBoolean() != false ? "NULL" : "NOT NULL";
String defaultVal = column.get("default_value_null").asBoolean()
|| column.get("default_value_utf8_null").asBoolean() ? ""
: "DEFAULT '" + column.get("default_value").asText() + "'";
// 构建列的注释,如果注释为空,不包含 COMMENT 部分
String comment = "";
// if (column.has("comment") && !column.hasNonNull("comment") && !column.get("comment").isEmpty()) {
//
// }
comment = "COMMENT '" + column.get("comment").asText() + "'";
if (column.get("is_auto_increment").asBoolean()) {
priString = "PRIMARY KEY ( `" + columnName + "`)";
}
// 构建列的 SQL
sql.append(columnName).append(" ").append(columnType).append(" ").append(isNullable).append(" ")
.append(defaultVal).append(" ").append(comment).append(", ");
}
}
// 去除最后的逗号和空格
if (sql.length() > 0) {
sql.setLength(sql.length() - 2); // 移除最后的逗号和空格
}
sql.append("," + priString + ");");
// 输出 SQL 语句
System.out.println(sql.toString());
}
public static void main(String[] args) throws JsonMappingException, JsonProcessingException {
test();
}
}
替换数据后,执行出来两个结果,第一个是表名,第二个是建表语句,有时候建表语句有一点点问题,只要有点sql语句基础的,应该都可以改好,还是不会放到gpt,叫它改。它改的也不对,你就从网上找一个,对比看看就行了。
(2)把建表语句放到mvc数据库下执行它,然后重点来了,里面没有数据,只是表建好了,要恢复之前的数据,方法来了。
有时候建表语句明明执行成功了,但是下面的操作还是报错,可以尝试将表删掉,重新建表,并记得设主键就可以了。还是不行,那就放弃吧。你有空也可以去研究里面的json数据。我建表语句那里是根据是否有自动递增的所以有些操作,你们可以再改改,我自己够用了就不再修改了。
打开命令行页面,操作(命令和操作效果对比看吧):
use mvc;
alter table tb_brand DISCARD TABLESPACE;
放置原始data目录的那个tb_brand.ibd到新data目录下的mvc目录下
alter table tb_brand IMPORT TABLESPACE;
就是像这样能恢复一个表的数据,我重复操作了3个小时,我的数据恢复了90%多数据,我已经很满足了。
后言
好了,写完了。后面备份的如果我有心得,会再写一篇分享的。大家一定要记得备份。
mysqld --initialize --console
这个语句害人不浅,又有很多用处,要使用一定要先备份好,幸亏我还认得initialize这个单词,所以说要写文章分享的人,一定要把前提标好!