MySQL 服务器端的错误处理太弱了!

0
MySQL SQL C/C++ Go 10702 次浏览

没有一种合适的方式来捕捉和诊断 MySQL 服务器端的错误,因此想知道什么地方出错了基本上是不可能的。

我们使用下面这样一个查询来证明这个结论:

INSERT INTO my_table (my_column) VALUES (300);

这个查询可能发生什么错误?

  • 违反 UNIQUE KEY 约束
  • 违反 FOREIGN KEY 约束
  • my_column 字段类型可能是 TINYINT UNSIGNED, 而严格的 sql_mode 导致数值越界
  • 后者字段类型可能是某个枚举,如 ENUM (2,3,5,8)

还有可能是这样一些错误:

  • my_table 可能是一个只读的 MyISAM
  • 我们对 my_table 进行了锁表操作 LOCK TABLES my_table READ -- 违反了锁
  • 或者可能是一个 InnoDB 表,而 INSERT 可能导致死锁
  • 配置了 read_only=1 只读
  • 或者用户没法访问该表的权限
  • 或者表不存在
  • 也有可能是字段不存在

而且我还确定还可能有更多的错误原因存在。

现在,如果我写了一个 Java 程序,可能用了 Hibernate,那么我将会通过 SQLException 得到一个描述比较清晰的异常信息,我可以得知错误码和错误信息。

但在 MySQL 的服务器端,例如是存储过程呢?则不行!

再看看下面的代码:
CREATE PROCEDURE some_procedure ()
BEGIN
  DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET @error_found = 1;
  INSERT INTO my_table (my_column) VALUES (300);
  IF @error_found THEN -- Any what error exactly is this? What's the message? END IF;
END;

如果我们希望为指定的错误执行相应的动作,我们需要:

  DECLARE CONTINUE HANDLER FOR 1146 SET @error_found = 1146;
  DECLARE CONTINUE HANDLER FOR 1147 SET @error_found = 1147;
  DECLARE CONTINUE HANDLER FOR 1148 SET @error_found = 1148;
  DECLARE CONTINUE HANDLER FOR 1149 SET @error_found = 1149;
  ...

但如果我们比知道将会发生什么错误,但仍希望记录这个错误,这样我们可能需要定义成百上千的 HANDLERs,尽管如此还是无法覆盖所有的错误情况。

5.5 版本不是引入了 SINGAL 和 RESIGNAL 了吗?

是的,的确是引入了,但对你毫无帮助,你可以重新 RESIGNAL 一个错误,但并不意味着错误实际发生时你能知晓。

那么,问题是什么呢?

我想在服务器端做很多事情,而不是通过外部脚本如 Python/Perl/Java/Ruby/Shell 等,例如 event scheduler: 我的意思是有什么意义呢?如果在服务器端很多事情你没法做的话,那将是无用的。你不能够组织错误,不能得到足够的错误描述信息,这只不过是你想执行好工作的一小部分而已。

common_schema/QueryScript 中我提供了一些脚本,但错误处理该怎么办呢?我编写了一个完全不同的错误处理方法(尚未发布),但一旦在服务器端运行 common_schema , 因为服务器的限制导致其功能是有限的,也就是说用处的确很小。

本来不错

这是 error_count 连接会话变量,实际上也没有任何用途,有了下面两个变量就会好很多:

  • last_error_code
  • last_error_message

如果一个查询导致了多个错误,请选择其中一个。

或者使用其他方法来在服务器端解析 SHOW 命令(参考 这里). 如果我可以解析 SHOW ERRORS 命令,那么所有事情都能得以解决。

MySQL 5.0 引入了 INFORMATION_SCHEMA, 虽然并不完整。很快 SHOW 命令被排除在服务器端游标之外。因为太多的功能缺失,所以我提交了一个 bug report/feature request. 你支持我吗?

译者注:后面内容翻译的很糟糕,完全不知道在说什么,如果费劲请看英文原文或者共同翻译下。

请尽量让自己的答案能够对别人有帮助

1个答案

默认排序 按投票排序
0

This kind of error is really stressful. MySQL can be complicated sometimes. It is like playing stickman dismount.