记一次Mysql问题

记一次Mysql问题

今天突然的碰到了一次没碰到过的Mysql问题,找寻了一些解决办法,最终无可奈何,但是想要记录以下,也希望能有人有相同的经历并成功解决过,可以github联系我。哈哈哈哈

问题背景

win11,pycharm2022,mysql8

问题起源

本来在写一个Python的脚本,脚本是用来模拟生成一些数据的,在测试的过程中会不断的用pymysql去创建连接,当然啦,也会不断的断连接。

代码就类似如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
def connect_to_db(self):
return pymysql.connect(
**self.db_config,
cursorclass=pymysql.cursors.DictCursor
)

def query_from_db(self, query: str) -> List[Dict[str, Any]]:
connection = self.connect_to_db()
try:
with connection.cursor(cursor=pymysql.cursors.Cursor) as cursor:
cursor.execute(query)
return [row[0] for row in cursor.fetchall()]
except pymysql.MySQLError as e:
print(f"Error querying database: {e}")
return []
finally:
connection.close()

def save_to_mysql(self, data: List[Dict[str, Any]], table_name: str):
if not data:
return
connection = self.connect_to_db()
try:
with connection.cursor() as cursor:
keys = data[0].keys()
columns = ', '.join(keys)
placeholders = ', '.join(['%s'] * len(keys))
query = f"INSERT INTO {table_name} ({columns}) VALUES ({placeholders})"
values = [tuple(record[key] for key in keys) for record in data]
cursor.executemany(query, values)
connection.commit()
except pymysql.MySQLError as e:
print(f"Error while saving data to {table_name}: {e}")
finally:
connection.close()

按照道理来讲的话,这份代码是不会有太大的问题,但是在运行多次后,数据库中的一个表发生了一个错误,查看错误日志发现如下日志

1
2
2024-11-12T11:48:31.444178Z 8 [ERROR] [MY-012611] [InnoDB] Operating system error number 2 in a file operation.
2024-11-12T11:48:31.444684Z 8 [ERROR] [MY-012216] [InnoDB] Cannot open datafile for read-only: '.\erp\users.ibd' OS error: 71

发现报错信息是read-only,就思考了,是不是数据文件仅读了,然后就到存放idb的文件目录,后续查看了文件的读取执行权限,发现并不是读取执行权限的问题。

然后就拿执行查询语句报出的错误信息到网络中搜索,报错信息如下:

1
Tablespace is missing for table ‘db_rsk/XXX”

解决办法

  • 网络办法

    网络上说是磁盘空间满了,但是我这并没有满磁盘,所以这种症状不符合 Pass

    还有说是ibd文件损坏了的,我怀疑可能是这种,然后就按照他的操作的,他具体的操作如下

    1. 关闭mysql服务
    2. 删除该表的ibd文件,然后重启服务
    3. 做完收工

我就这么帅气的解决了


怎么可能,当时自我为是,以为自己碰到的就是这种问题,然后就直接删除了,都没有把ibd文件做备份,真的蠢~~

好了文件删除了,更轻松了,只需要找对病症,然后对症下药了,都不用考虑是什么原因导致的了。

重新诊治

问题如下:mysql的idb文件丢失,导致表无法访问怎么办?

好了,又从网络以及gpt搜集了一些解决办法

  1. 确认元数据信息是否还在
1
2
3
4
USE information_schema;
SELECT TABLE_NAME, ENGINE
FROM TABLES
WHERE TABLE_SCHEMA = '<your_database_name>' AND TABLE_NAME = 'users';

查询发现元数据信息还存在

  1. 尝试从idb文件恢复
    1. 停止mysql服务

    2. 然后从新创建一个结构相同表名相同的表,但是不同数库

    3. 将原来的ibd文件删除,替换成新创建表的ibd文件

    4. 确保新的表的权限是跟原来的ibd文件的权限相同

    5. 启动mysql服务

    6. 登录mysql服务并执行以下命令

      1
      2
      ALTER TABLE users DISCARD TABLESPACE;
      ALTER TABLE users IMPORT TABLESPACE;
    7. 好的操作结束

漂亮一通操作下来问题还是没有解决,nice~~

后面一想,反正数据不多而且都是模拟的数据,测试脚本嘛,不浪费时间了,将问题记录下来,把其他表结构复制到另外一个数据库,重新开始。

感想

写blog的时候想到了有个blog上说过,在5.6的时候或之前还是有办法解决的,但是在5.6之后的话只能放弃这个表名用其他的表明去替代,是不是这个样子的我没有尝试过,希望有经验的人能够为我解答一下。嘿嘿~~

这里附一个链接,在我看来是有可能能够解决的办法

14.22.3 对 InnoDB 数据字典操作进行故障排除

Thanks technology!