mysql unsupported data type._记一次mysql故障处理

本文记录了一次因配置不当导致的MySQL数据库故障,问题在于`innodb_buffer_pool_size`设置过大超出系统内存。解决方法包括调整配置参数、初始化MySQL、利用binlog恢复数据,并探讨了在Linux系统下如何释放内存缓存。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

突然间,个人网站崩溃了!相信这个报错作为运维都应该清楚的,是数据库宕机了。

369cf36285587891a267822898ce0ef1.png

数据库我采用mysql 5.1.63,上机查看错误日志:

171010 10:11:01 mysqld_safe Starting mysqld daemon with databases from /usr/local/mysql/var

171010 10:11:01 InnoDB: Initializing buffer pool, size = 512.0M

171010 10:11:01 InnoDB: Error: cannot allocate 536887296 bytes of

InnoDB: memory with malloc! Total allocated memory

InnoDB: by InnoDB 22442704 bytes. Operating system errno: 12

InnoDB: Check if you should increase the swap file or

InnoDB: ulimits of your operating system.

InnoDB: On FreeBSD check you have compiled the OS with

InnoDB: a big enough maximum process size.

InnoDB: Note that in most 32-bit computers the process

InnoDB: memory space is limited to 2 GB or 4 GB.

InnoDB: We keep retrying the allocation for 60 seconds...

171010 10:12:01InnoDB: Fatal error: cannot allocate the memory for the buffer pool

171010 10:12:01 [ERROR] Plugin 'InnoDB' init function returned error.

171010 10:12:01 [ERROR] Plugin 'InnoDB' registration as a STORAGE ENGINE failed.

171010 10:12:01 [ERROR] Unknown/unsupported table type: INNODB

171010 10:12:01 [ERROR] Aborting

171010 10:12:01 [Note] /usr/local/mysql/libexec/mysqld: Shutdown complete

171010 10:12:01 mysqld_safe mysqld from pid file /usr/local/mysql/var/qyi-599a87c5e1fa7.pid ended

^C

我以为是innoDB引擎的坏掉了,于是重新编译安装了mysql,后来才发现,原来是配置文件中

innodb_buffer_pool_size 设置的值过大了,(我设置了1G) 呵呵 ,缓冲池过大了,云服务器上的内存不过也就才1G。

4f71a3294e60d4e0e03cea8a6bdd8dd6.png

查了资料得知原因:

这个报错的大意是,内存基本耗尽,没有再可以分配的内存.

解决办法:查看/etc/my.cnf,找innodb_buffer_pool_size,发现设值已经超过了系统总内存,然后重新设置为系统内存1半,即innodb_buffer_pool_size = 512M 重启MySQL就OK了.

于是我修改my.cnf中参数:

innodb_buffer_pool_size         = 512M

尝试启动mysql,结果不尽人意,依然报错上述错误。

于是我方了。。。。。我尝试各种方法,比如说初始化!!!!

一般来说初始化不会对线上数据造成什么影响,但是~!生产环境可千万不要这样操作,万一哪天不幸运,初始化完出故障了,那这个锅你背定了。

按照我的想法继续走。我本人是个菜鸟,写这篇文章可能会被喷,是内存的问题为什么要动数据?

我本人是个喜欢折腾的人,而且这个又是我的云机器所以我当试验机随便折腾了。。好坏都无所谓。所以我这么做,还可以锻炼我对于mysql的理解呢,何乐而不为?

然后、、、初始化过后,我把datadir目录下的数据全都删了!!!!对没错,全删了,或者是移到了其他不重要的目录里面去。

是什么给了我这么大勇气删数据库?当然是binlog日志哈哈哈,我可是对他做了备份呢。诺,你看。之前操作过的数据都会保存在binlog日志中,在其他没有备份机制的情况下通过他可以备份出sql文件,然后导入MySQL。

mysqlbinlog --start-datetime="2017-09-30 16:41:00" --stop-datetime="2017-09-30 20:48:00" mysql-bin.000003 > wordpress.sql

fbb084d159da26257f096846d0d9e195.png

好了,这次备份也有了我重新进到MySQL 的datadir目录重新初始化,初始化完后目录下会有两个目录分别是mysql、test

启动mysql。这时候打开另一个会话窗口查看日志,我的心都要崩溃了。。。

跟上面报错一模一样,最后我没办法了,没脾气了,我直接reboot !!哼哼这次看你还怎么报错。

linux内存管理是非常合理的,是不需要我们插手管理的,他会根据内存大小自动存储到cache里。当然这次的重启就是为了释放内存,有人说我小题大做,手工释放一次内存不就行了?我能告诉你我当时没有想到这一点嘛。。。。看来我考虑的还不够全面啊哈哈,还是欠缺考虑。这次是我的试验机,下次如果是线上的业务机器不让重启那可就没辙了,还有万一重启起不来可就完蛋了。不过一般企业为了数据安全起见,都会部署至少两个或两个以上的数据库,做个主从,以备故障之需。上次线上机器mysql的innodb出现故障,还好只是sdb,于是我果断删除目录重新初始化,然后再从MDB把数据给同步过来恢复了正常。

在Linux系统下,我们一般不需要去释放内存,因为系统已经将内存管理的很好。但是凡事也有例外,有的时候内存会被缓存占用掉,导致系统使用SWAP空间影响性能,此时就需要执行释放内存(清理缓存)的操作了。我可真是傻,百度上有释放内存的资料,我竟然没有想到。哎,这里记录下一下吧。

配置文件/proc/sys/vm/drop_caches。这个文件中记录了缓存释放的参数,默认值为0,也就是不释放缓存。他的值可以为0~3之间的任意数字,代表着不同的含义:

0 – 不释放

1 – 释放页缓存

2 – 释放dentries和inodes

3 – 释放所有缓存

接下来,我们需要将需要的参数写进/proc/sys/vm/drop_caches文件中,比如我们需要释放所有缓存,就输入下面的命令:

#echo 3 > /proc/sys/vm/drop_caches

此指令输入后会立即生效,可以查询现在的可用内存明显的变多了。

要查询当前缓存释放的参数,可以输入下面的指令:

#cat /proc/sys/vm/drop_caches

好了重启ok了,之前做了所有服务开机自启动,发现mysql已经启动成功了,但是数据目录里面没有东西,原因是我刚才把它删了哈哈哈。。。。

所以现在备份的sql文件有作用了!!!

直接导入  mysql < wordpress.sql

46613845e086ef3f041e9fd76b48bd13.png

大功告成!!!!!我的个人网站又可以访问了。

""" title: SQL Server Access author: MENG author_urls: - https://github.com/mengvision description: A tool for reading database information and executing SQL queries, supporting multiple databases such as MySQL, PostgreSQL, SQLite, and Oracle. It provides functionalities for listing all tables, describing table schemas, and returning query results in CSV format. A versatile DB Agent for seamless database interactions. required_open_webui_version: 0.5.4 requirements: pymysql, sqlalchemy, cx_Oracle version: 0.1.6 licence: MIT # Changelog ## [0.1.6] - 2025-03-11 ### Added - Added `get_table_indexes` method to retrieve index information for a specific table, supporting MySQL, PostgreSQL, SQLite, and Oracle. - Enhanced metadata capabilities by providing detailed index descriptions (e.g., index name, columns, and type). - Improved documentation to include the new `get_table_indexes` method and its usage examples. - Updated error handling in `get_table_indexes` to provide more detailed feedback for unsupported database types. ## [0.1.5] - 2025-01-20 ### Changed - Updated `list_all_tables` and `table_data_schema` methods to accept `db_name` as a function parameter instead of using `self.valves.db_name`. - Improved flexibility by decoupling database name from class variables, allowing dynamic database selection at runtime. ## [0.1.4] - 2025-01-17 ### Added - Added support for Oracle database using `cx_Oracle` driver. - Added dynamic engine creation in each method to ensure fresh database connections for every operation. - Added support for Oracle-specific queries in `list_all_tables` and `table_data_schema` methods. ### Changed - Moved `self._get_engine()` from `__init__` to individual methods for better flexibility and tool compatibility. - Updated `_get_engine` method to support Oracle database connection URL. - Improved `table_data_schema` method to handle Oracle-specific column metadata. ### Fixed - Fixed potential connection issues by ensuring each method creates its own database engine. - Improved error handling for Oracle-specific queries and edge cases. ## [0.1.3] - 2025-01-17 ### Added - Added support for multiple database types (e.g., MySQL, PostgreSQL, SQLite) using SQLAlchemy. - Added configuration flexibility through environment variables or external configuration files. - Enhanced query security with stricter validation and SQL injection prevention. - Improved error handling with detailed exception messages for better debugging. ### Changed - Replaced `pymysql` with SQLAlchemy for broader database compatibility. - Abstracted database connection logic into a reusable `_get_engine` method. - Updated `table_data_schema` method to support multiple database types. ### Fixed - Fixed potential SQL injection vulnerabilities in query execution. - Improved handling of edge cases in query validation and execution. ## [0.1.2] - 2025-01-16 ### Added - Added support for specifying the database port with a default value of `3306`. - Abstracted database connection logic into a reusable `_get_connection` method. ## [0.1.1] - 2025-01-16 ### Added - Support for additional read-only query types: `SHOW`, `DESCRIBE`, `EXPLAIN`, and `USE`. - Enhanced query validation to block sensitive keywords (e.g., `INSERT`, `UPDATE`, `DELETE`, `CREATE`, `DROP`, `ALTER`). ### Fixed - Improved handling of queries starting with `WITH` (CTE queries). - Fixed case sensitivity issues in query validation. ## [0.1.0] - 2025-01-09 ### Initial Release - Basic functionality for listing tables, describing table schemas, and executing `SELECT` queries. - Query results returned in CSV format. """ import os from typing import List, Dict, Any from pydantic import BaseModel, Field import re from sqlalchemy import create_engine, text from sqlalchemy.engine.base import Engine from sqlalchemy.exc import SQLAlchemyError class Tools: class Valves(BaseModel): db_host: str = Field( default="localhost", description="The host of the database. Replace with your own host.", ) db_user: str = Field( default="admin", description="The username for the database. Replace with your own username.", ) db_password: str = Field( default="admin", description="The password for the database. Replace with your own password.", ) db_name: str = Field( default="db", description="The name of the database. Replace with your own database name.", ) db_port: int = Field( default=3306, # Oracle 默认端口 description="The port of the database. Replace with your own port.", ) db_type: str = Field( default="mysql", description="The type of the database (e.g., mysql, postgresql, sqlite, oracle).", ) def __init__(self): """ Initialize the Tools class with the credentials for the database. """ print("Initializing database tool class") self.citation = True self.valves = Tools.Valves() def _get_engine(self) -> Engine: """ Create and return a database engine using the current configuration. """ if self.valves.db_type == "mysql": db_url = f"mysql+pymysql://{self.valves.db_user}:{self.valves.db_password}@{self.valves.db_host}:{self.valves.db_port}/{self.valves.db_name}" elif self.valves.db_type == "postgresql": db_url = f"postgresql://{self.valves.db_user}:{self.valves.db_password}@{self.valves.db_host}:{self.valves.db_port}/{self.valves.db_name}" elif self.valves.db_type == "sqlite": db_url = f"sqlite:///{self.valves.db_name}" elif self.valves.db_type == "oracle": db_url = f"oracle+cx_oracle://{self.valves.db_user}:{self.valves.db_password}@{self.valves.db_host}:{self.valves.db_port}/?service_name={self.valves.db_name}" else: raise ValueError(f"Unsupported database type: {self.valves.db_type}") return create_engine(db_url) def list_all_tables(self, db_name: str) -> str: """ List all tables in the database. :param db_name: The name of the database. :return: A string containing the names of all tables. """ print("Listing all tables in the database") engine = self._get_engine() # 动态创建引擎 try: with engine.connect() as conn: if self.valves.db_type == "mysql": result = conn.execute(text("SHOW TABLES;")) elif self.valves.db_type == "postgresql": result = conn.execute( text( "SELECT table_name FROM information_schema.tables WHERE table_schema = 'public';" ) ) elif self.valves.db_type == "sqlite": result = conn.execute( text("SELECT name FROM sqlite_master WHERE type='table';") ) elif self.valves.db_type == "oracle": result = conn.execute(text("SELECT table_name FROM user_tables;")) else: return "Unsupported database type." tables = [row[0] for row in result.fetchall()] if tables: return ( "Here is a list of all the tables in the database:\n\n" + "\n".join(tables) ) else: return "No tables found." except SQLAlchemyError as e: return f"Error listing tables: {str(e)}" def get_table_indexes(self, db_name: str, table_name: str) -> str: """ Get the indexes of a specific table in the database. :param db_name: The name of the database. :param table_name: The name of the table. :return: A string describing the indexes of the table. """ print(f"Getting indexes for table: {table_name}") engine = self._get_engine() try: key, cloumn = 0, 1 with engine.connect() as conn: if self.valves.db_type == "mysql": query = text(f"SHOW INDEX FROM {table_name}") key, cloumn = 2, 4 elif self.valves.db_type == "postgresql": query = text( """ SELECT indexname, indexdef FROM pg_indexes WHERE tablename = :table_name; """ ) elif self.valves.db_type == "sqlite": query = text( """ PRAGMA index_list(:table_name); """ ) elif self.valves.db_type == "oracle": query = text( """ SELECT index_name, column_name FROM user_ind_columns WHERE table_name = :table_name; """ ) else: return "Unsupported database type." result = conn.execute(query) indexes = result.fetchall() if not indexes: return f"No indexes found for table: {table_name}" description = f"Indexes for table '{table_name}':\n" for index in indexes: description += f"- {index[key]}: {index[cloumn]}\n" return description # result = conn.execute(query) # description = result.fetchall() # if not description: # return f"No indexes found for table: {table_name}" # column_names = result.keys() # description = f"Query executed successfully. Below is the actual result of the query {query} running against the database in CSV format:\n\n" # description += ",".join(column_names) + "\n" # for row in description: # description += ",".join(map(str, row)) + "\n" # return description except SQLAlchemyError as e: return f"Error getting indexes: {str(e)}" def table_data_schema(self, db_name: str, table_name: str) -> str: """ Describe the schema of a specific table in the database, including column comments. :param db_name: The name of the database. :param table_name: The name of the table to describe. :return: A string describing the data schema of the table. """ print(f"Database: {self.valves.db_name}") print(f"Describing table: {table_name}") engine = self._get_engine() # 动态创建引擎 try: with engine.connect() as conn: if self.valves.db_type == "mysql": query = text( " SELECT COLUMN_NAME, COLUMN_TYPE, IS_NULLABLE, COLUMN_KEY, COLUMN_COMMENT " " FROM INFORMATION_SCHEMA.COLUMNS " f" WHERE TABLE_SCHEMA = '{self.valves.db_name}' AND TABLE_NAME = '{table_name}';" ) elif self.valves.db_type == "postgresql": query = text( """ SELECT column_name, data_type, is_nullable, column_default, '' FROM information_schema.columns WHERE table_name = :table_name; """ ) elif self.valves.db_type == "sqlite": query = text("PRAGMA table_info(:table_name);") elif self.valves.db_type == "oracle": query = text( """ SELECT column_name, data_type, nullable, data_default, comments FROM user_tab_columns LEFT JOIN user_col_comments ON user_tab_columns.table_name = user_col_comments.table_name AND user_tab_columns.column_name = user_col_comments.column_name WHERE user_tab_columns.table_name = :table_name; """ ) else: return "Unsupported database type." # result = conn.execute( # query, {"db_name": db_name, "table_name": table_name} # ) result = conn.execute(query) columns = result.fetchall() if not columns: return f"No such table: {table_name}" description = ( f"Table '{table_name}' in the database has the following columns:\n" ) for column in columns: if self.valves.db_type == "sqlite": column_name, data_type, is_nullable, _, _, _ = column column_comment = "" elif self.valves.db_type == "oracle": ( column_name, data_type, is_nullable, data_default, column_comment, ) = column else: ( column_name, data_type, is_nullable, column_key, column_comment, ) = column description += f"- {column_name} ({data_type})" if is_nullable == "YES" or is_nullable == "Y": description += " [Nullable]" if column_key == "PRI": description += " [Primary Key]" if column_comment: description += f" [Comment: {column_comment}]" description += "\n" return description except SQLAlchemyError as e: return f"Error describing table: {str(e)}" def execute_read_query(self, query: str) -> str: """ Execute a read query and return the result in CSV format. :param query: The SQL query to execute. :return: A string containing the result of the query in CSV format. """ print(f"Executing query: {query}") normalized_query = query.strip().lower() if not re.match( r"^\s*(select|with|show|describe|desc|explain|use)\s", normalized_query ): return "Error: Only read-only queries (SELECT, WITH, SHOW, DESCRIBE, EXPLAIN, USE) are allowed. CREATE, DELETE, INSERT, UPDATE, DROP, and ALTER operations are not permitted." sensitive_keywords = [ "insert", "update", "delete", "create", "drop", "alter", "truncate", "grant", "revoke", "replace", ] for keyword in sensitive_keywords: if re.search(rf"\b{keyword}\b", normalized_query): return f"Error: Query contains a sensitive keyword '{keyword}'. Only read operations are allowed." engine = self._get_engine() # 动态创建引擎 try: with engine.connect() as conn: result = conn.execute(text(query)) rows = result.fetchall() if not rows: return "No data returned from query." column_names = result.keys() csv_data = f"Query executed successfully. Below is the actual result of the query {query} running against the database in CSV format:\n\n" csv_data += ",".join(column_names) + "\n" for row in rows: csv_data += ",".join(map(str, row)) + "\n" return csv_data except SQLAlchemyError as e: return f"Error executing query: {str(e)}" 将上面的工具连接到Microsoft sql server
最新发布
07-23
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值