第 29.1 节:错误代码 1064:语法错误
SELECT LastName, FirstName, FROM Person;
返回消息:
Error Code: 1064. You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'from Person' at line 2.
从 MySQL 收到 "1064 error" 消息意味着查询无法被解析,存在语法错误。换句话说,MySQL 无法理解该查询。
错误消息中的引号从查询中 MySQL 无法解析的第一个字符开始。在此示例中,MySQL 在 from Person 的上下文中无法理解。这里,在 from Person 之前有一个多余的逗号。该逗号告诉 MySQL 在 SELECT 子句中期望另一个列描述。
语法错误总是显示 ... near '...'。引号开头的内容非常接近错误位置。要定位错误,请查看引号中的第一个标记以及引号之前的最后一个标记。
有时你会看到 ... near '',即引号内没有内容。这意味着 MySQL 无法理解的第一个字符恰好在语句的末尾或开头。这通常表明查询包含不平衡的引号(' 或 ")或不平衡的括号,或者你没有正确终止语句。
对于存储过程,你可能忘记了正确使用 DELIMITER。
因此,当你遇到错误 1064 时,请查看查询文本,找到错误消息中提到位置。在该位置附近仔细检查查询文本。
如果你请别人帮忙排查错误 1064,最好提供完整的查询文本和错误消息文本。
第 29.2 节:错误代码 1175:安全更新
当尝试更新或删除记录时,如果没有包含使用 KEY 列的 WHERE 子句,会出现此错误。
要强制执行删除或更新,可以设置:
SET SQL_SAFE_UPDATES = 0;
要重新启用安全模式:
SET SQL_SAFE_UPDATES = 1;
第 29.3 节:错误代码 1215:无法添加外键
当表的结构不足以处理开发者所要求的外键快速查找验证时,会发生此错误。
CREATE TABLE `gtType` (
`type` CHAR(2) NOT NULL,
`description` VARCHAR(1000) NOT NULL,
PRIMARY KEY (`type`)
) ENGINE=InnoDB;
CREATE TABLE `getTogethers` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`type` CHAR(2) NOT NULL,
`eventDT` DATETIME NOT NULL,
`location` VARCHAR(1000) NOT NULL,
PRIMARY KEY (`id`),
KEY `fk_gt2type` (`type`), -- 参见下面的 Note1
CONSTRAINT `gettogethers_ibfk_1` FOREIGN KEY (`type`) REFERENCES `gtType` (`type`)
) ENGINE=InnoDB;
Note1:如果由于后面行的 FK 定义需要,这样的 KEY 会自动创建。开发者可以跳过它,必要时会自动添加 KEY(索引)。下面 someOther 示例中展示了开发者跳过它的情形。
到目前为止一切正常,直到以下调用:
CREATE TABLE `someOther` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`someDT` DATETIME NOT NULL,
PRIMARY KEY (`id`),
CONSTRAINT `someOther_dt` FOREIGN KEY (`someDT`) REFERENCES `getTogethers` (`eventDT`)
) ENGINE=InnoDB;
错误:Error Code: 1215. Cannot add foreign key constraint
本例中失败的原因是,被引用表 getTogethers 中缺少用于快速查找 eventDT 的索引。解决方法如下:
CREATE INDEX `gt_eventdt` ON getTogethers (`eventDT`);
getTogethers 表被修改后,someOther 的创建将成功。
从 MySQL 手册《使用外键约束》中:
MySQL 要求外键和引用键上有索引,以便外键检查能够快速进行,而不需要全表扫描。在引用表中,必须有一个索引,其中外键列以相同的顺序作为第一列列出。如果不存在这样的索引,它会在引用表上自动创建。
外键和引用键中的对应列必须具有相似的数据类型。整数类型的大小和符号必须相同。字符串类型的长度不必相同。对于非二进制(字符)字符串列,字符集和排序规则必须相同。
InnoDB 允许外键引用任何索引列或列组。但是,在被引用表中,必须有一个索引,其中被引用的列以相同的顺序作为第一列列出。
请注意上面最后一点关于第一(最左)列的要求,以及不强制要求主键(尽管强烈建议有主键)。
成功创建引用(子)表后,可以使用如下命令查看自动为你创建的任何键:
SHOW CREATE TABLE someOther;
遇到此错误的其他常见情况包括(如文档所述,但应强调):
- 看似微小的差异,例如
INT指向INT UNSIGNED。 - 开发人员难以理解多列(复合)键和第一(最左)列顺序要求。
第 29.4 节:1067、1292、1366、1411 —— 数字、日期、默认值等错误的值
- 1067:可能与
TIMESTAMP默认值有关,这些默认值随时间发生了变化。请参阅日期和时间页面中的 TIMESTAMP 默认值。 - 1292/1366 DOUBLE/Integer:检查是否有字母或其他语法错误。检查列对齐;也许你认为你插入的是
VARCHAR,但实际对齐的是数字列。 - 1292 DATETIME:检查是否日期太远或太远。检查在夏令时更改的早晨 2 点到 3 点之间。检查是否有错误的语法,例如
+00时区内容。 - 1292 VARIABLE:检查你要
SET的变量的允许值。 - 1292 LOAD DATA:查看“错误”的行。检查转义符号等。查看数据类型。
- 1411 STR_TO_DATE:日期格式不正确?
第 29.5 节:1045 访问被拒绝
请参阅“GRANT”和“恢复 root 密码”中的讨论。
第 29.6 节:1236 复制中的“不可能的位置”
通常这意味着主库崩溃且 sync_binlog 设置为 OFF。解决方法是在从库上执行 CHANGE MASTER TO POS=0 指向下一个 binlog 文件(请查看主库)。
原因:主库在刷新到其 binlog 之前(当 sync_binlog=OFF 时)将复制项发送给从库。如果主库在刷新前崩溃,从库在逻辑上已经越过了 binlog 的文件结尾。当主库再次启动时,它会启动一个新的 binlog,因此 CHANGE 到该 binlog 的开头是目前可用的最佳解决方案。
更长期的解决方案是设置 sync_binlog=ON,如果你能承受它带来的额外 I/O。
(如果你使用了 GTID,可能有所不同?)
第 29.7 节:2002、2003 无法连接
检查是否有防火墙阻止端口 3306。
一些可能的诊断和/或解决方案:
- 服务器是否真的在运行?
service firewall stop和systemctl disable firewalltelnet master 3306- 检查
bind-address - 检查
skip-name-resolve - 检查 socket
第 29.8 节:126、127、134、144、145
当你尝试访问 MySQL 数据库中的记录时,可能会收到这些错误消息。这些错误消息是由于 MySQL 数据库损坏引起的。以下为错误类型:
- MySQL 错误代码 126 = 索引文件已崩溃
- MySQL 错误代码 127 = 记录文件已崩溃
- MySQL 错误代码 134 = 记录已被删除(或记录文件已崩溃)
- MySQL 错误代码 144 = 表已损坏且上次修复失败
- MySQL 错误代码 145 = 表被标记为已损坏,应进行修复
MySQL 错误、病毒攻击、服务器崩溃、不当关闭、表损坏都是导致此损坏的原因。当表损坏时,它将变得不可访问,你无法再访问它们。为了获得可访问性,最好从更新的备份中恢复数据。但是,如果你没有更新或任何有效的备份,则可以进行 MySQL 修复。
如果表引擎类型是 MyISAM,对表执行 CHECK TABLE,然后执行 REPAIR TABLE。
然后认真考虑转换为 InnoDB,这样这个错误就不会再发生了。
语法:
CHECK TABLE <table_name>; -- 检查数据库损坏程度
REPAIR TABLE <table_name>; -- 修复表
第 29.9 节:139
错误 139 可能意味着表定义中字段的数量和大小超过了一些限制。解决方法:
- 重新思考模式
- 规范化一些字段
- 垂直分区表
第 29.10 节:1366
这通常意味着客户端和服务器之间的字符集处理不一致。请参阅其他章节以获得进一步帮助。
第 29.11 节:24、126、1054、1146、1062 等
24 - 无法打开文件(Too many open files)
open_files_limit 来自操作系统设置。table_open_cache 需要小于该值。
以下情况可能导致此错误:
- 在存储过程中未能
DEALLOCATE PREPARE。 - 使用
PARTITION表且分区数量很大,同时innodb_file_per_table = ON。建议对一个表不超过 50 个分区(出于多种原因)。(当“本地分区”可用时,此建议可能会改变。)
明显的解决方法是增加操作系统限制:要允许更多文件,请更改 ulimit 或 /etc/security/limits.conf 或在 sysctl.conf 中(kern.maxfiles 和 kern.maxfilesperproc)或其他与操作系统相关的设置。然后增加 open_files_limit 和 table_open_cache。
从 5.6.8 开始,open_files_limit 会根据 max_connections 自动调整,但也可以更改默认值。
1062 - 重复条目
此错误主要出现在以下两种原因:
- 重复值 -
Error Code: 1062. Duplicate entry '12' for key 'PRIMARY'
主键列是唯一的,不接受重复条目。因此,当你试图插入表中已存在的新行时,会产生此错误。
解决方法:将主键列设置为 AUTO_INCREMENT。插入新行时,忽略主键列或为 PRIMARY KEY 插入 NULL 值。
```sql CREATE TABLE userDetails ( userId INT(10) NOT NULL AUTO_INCREMENT, firstname VARCHAR(50), lastname VARCHAR(50), isActive INT(1) DEFAULT 0, PRIMARY KEY (userId) );
-- 插入时 INSERT INTO userDetails VALUES (NULL, 'John', 'Doe', 1); ```
- 唯一数据字段 -
Error Code: 1062. Duplicate entry 'A' for key 'code'
你可能将某列指定为唯一列,并且试图插入该列已有值的新行。
解决方法:使用 INSERT IGNORE 代替普通的 INSERT。如果新行不重复现有记录,MySQL 将正常插入。如果记录重复,IGNORE 关键字会丢弃它而不产生任何错误。
sql
INSERT IGNORE INTO userDetails VALUES (NULL, 'John', 'Doe', 1);