设为首页 收藏本站
查看: 896|回复: 0

[经验分享] MySQL常见错误问答!

[复制链接]

尚未签到

发表于 2018-10-3 12:27:04 | 显示全部楼层 |阅读模式
18.2.8 Commands out of sync in client错误  如果你在你的客户代码中得到Commands out of sync; You can’t run this command now,你正在以错误的次序调用客户函数!
  这可能发生,例如,如果你正在使用mysql_use_result()并且在你已经调用了mysql_free_result()之前试图执行新查询。如果你在mysql_use_result()或mysql_store_result()之间试图执行返回数据的2个查询,它也可能发生。
  18.2.9 Ignoring user错误
  如果你得到下列错误:
  Found wrong password for user: ’some_user@some_host’; Ignoring user
  这意味着在mysqld启动时或在它再次装载权限表时,它在user表中找到了一个有一个无效口令的条目。结果,条目简单地被权限系统忽略。
  可能导致这个问题的原因和修正:
  你可能正在运行一个有一个老的user表的新版本mysqld。你可以通过执行mysqlshow mysql user看看口令字段是否少于 16个字符来检查它。如果是这样,你可以通过运行scripts/add_long_password脚本改正这种情况。
  用户有一个老式的口令(8个字符长)并且你没使用--old-protocol选项启动mysqld。用一个新口令更新在user表中的用户或用--old-protocol重启mysqld。
  你没有使用PASSWORD()函数在在user表中指定了一个口令。使用mysql以一个新口令更新在user表中的用户。确保使用PASSWORD()函数:
  mysql> update user set password=PASSWORD(’your password’)
  where user=’XXX’;
  18.2.10 Table ’xxx’ doesn’t exist错误
  如果你得到错误Table ’xxx’ doesn’t exist或Can’t find file: ’xxx’ (errno: 2),这意味着在当前数据库中没有名为xxx的表存在。
  注意,因为MySQL使用目录和文件存储数据库和表,数据库和表名件是区分大小写的!(在Win32上,数据库和表名不是区分大小写的,但是在查询中对所有表的引用必须使用相同的大小写!)
  你可以用SHOW TABLES检查你在当前数据库中有哪个表。见7.21 SHOW句法(得到表、列的信息)。
  18.3 MySQL怎样处理一个溢出的磁盘
  当出现一个磁盘溢出的情况时,MySQL做下列事情:
  它每分钟检查一次看是否有足够空间写入当前行。如果有足够的空间,它继续好像发生什么事情。
  每6分钟它将有关磁盘溢出的警告写入日志文件。
  为了缓和这个问题,你可以采取下列行动:
  继续,你只需释放足够的空闲磁盘空间以便插入所有记录。
  放弃线程,你必须发一个mysqladmin kill到线程。在下一次检查磁盘时,线程将被放弃(在1分钟内)。
  注意,其他线程可能正在等待引起“磁盘溢出”条件的表。如果你有几个“锁定的”的线程,杀死正在等待磁盘溢出条件的那个线程将允许其他线程继续。
  18.4 如何从一个文本文件运行SQL命令
  一般地,mysql客户被交互性地使用,象这样:
  shell> mysql database
  然而,也可以把你的SQL命令放在一个文件中并且告诉mysql从该文件读取其输入。要想这样做,创造一个文本文件“text_file”,它包含你想要执行的命令。然后如下那样调用mysql:
  shell> mysql database < text_file
  你也能启动有一个USE db_name语句的文本文件。在这种情况下,在命令行上指定数据库名是不必要的:
  shell> mysql < text_file
  见12.1 不同的MySQL程序概述。
  18.5 MySQL在哪儿存储临时文件
  MySQL使用TMPDIR环境变量的值作为存储临时文件的目录的路径名。如果你没有设置TMPDIR,MySQL使用系统缺省值,它通常是“/tmp”或“/usr/tmp”。如果包含你的临时文件目录的文件系统太小,你应该编辑safe_mysqld设定TMPDIR指向你有足够空间的一个文件系统!你也可以使用mysqld的--tmpdir选项目设置临时目录。
  MySQL以“隐含文件”创建所有临时文件。这保证了如果mysqld被终止,临时文件也将被删除。使用隐含文件的缺点是你将看不到一个大的临时文件填满了临时文件目录所在的文件系统。
  当排序(ORDER BY或GROUP BY)时,MySQL通常使用一个或两个临时文件。最大磁盘空间需求是:
  (存储东西的长度 + sizeof (数据库指针))
  * 匹配的行数
  * 2
  sizeof(数据库指针)通常是4,但是在未来对确实很大的表可能增加。
  对一些SELECT查询,MySQL也创建临时SQL表。这些没被隐含且有“SQL_*”格式的名字。
  ALTER TABLE和OPTIMIZE TABLE在原数据库表的同一个目录中创建一张临时表。
  18.6 怎样保护“/tmp/mysql.sock ”不被删除
  如果你有这个问题,事实上任何人可以删除MySQL通讯套接字“/tmp/mysql.sock”,在Unix的大多数版本上,你能通过为其设置sticky(t)位来保护你的“/tmp”文件系统。作为root登录并且做下列事情:
  shell> chmod +t /tmp
  这将保护你的“/tmp”文件系统使得文件仅能由他们的所有者或超级用户(root)删除。
  你能执行ls -ld /tmp检查sticky位是否被设置,如果最后一位许可位是t,该位被设置了。
  18.7 Access denied错误
  见6.6 权限系统如何工作。并且特别要看6.13 引起Access denied错误的原因。
  18.8 怎样作为一个一般用户运行MySQL
  MySQL服务器mysqld能被任何用户启动并运行。为了将mysqld改由Unix用户user_name来运行,你必须做下列事情:
  如果它正在运行,停止服务器(使用mysqladmin shutdown)。
  改变数据库目录和文件以便user_name有权限读和写文件(你可能需要作为Unix的root用户才能做到):
  shell> chown -R user_name /path/to/mysql/datadir
  如果在MySQL数据目录中的目录或文件是符号链接,你也将需要顺着那些链接并改变他们指向的目录和文件。chown -R不能跟随符号链接。
  以user_name用户启动服务器,或如果你正在使用MySQL 3.22或以后版本,以Unix root用户启动mysqld并使用--user=user_name选项,mysqld将在接受任何连接之前切换到以Unix user_name用户运行。
  如果在系统被重新启动时,你使用mysql.server脚本启动mysqld,你应该编辑mysql.server用su以用户user_name运行mysqld,或使用--user选项调用mysqld。(不改变safe_mysqld是必要的。)
  现在,你的mysqld进程应该正在作为Unix用户user_name运行,并运行完好。尽管有一件事情没有变化:权限表的内容。缺省 地(就在运行了脚本mysql_install_db安装的权限表后),MySQL用户root是唯一有存取mysql数据库或创建或抛弃数据库权限的用户。除非你改变了那些权限,否则他们仍然保持。当你作为一个Unix用户而不是root登录时,这不应该阻止你作为MySQL root用户来存取MySQL;只要为客户程序指定-u root的选项。
  注意通过在命令行上提供-u root,作为root存取MySQL,与作为Unix root用户或其他Unix用户运行MySQL没有关系。MySQL的存取权限和用户名与Unix用户名字是完全分开的。唯一与Unix用户名有关的是,如果当你调用一个客户程序时,你不提供一个-u选项,客户将试图使用你的Unix登录名作为你的MySQL用户名进行连接。
  如果你的Unix机器本身不安全,你可能应该至少在存取表中为MySQL root用户放上一个口令。否则,在那台机器上有一个帐号的任何用户能运行mysql -u root db_name并且做他喜欢做的任何事情。
  18.9 怎样重新设置一个忘记的口令
  如果你忘记了MySQL的root用户的口令,你可以用下列过程恢复它。
  通过发送一个kill(不是kill -9)到mysqld服务器来关闭mysqld服务器。pid 被保存在一个.pid文件中,通常在MySQL数据库目录中:
  kill `cat /mysql-data-directory/hostname.pid`
  你必须是一个UNIX root用户或运行服务器的相同用户做这个。
  使用--skip-grant-tables选项重启mysqld。
  用mysql -h hostname mysql连接mysqld服务器并且用一条GRANT命令改变口令。见7.26 GRANT和REVOKE句法。你也可以用mysqladmin -h hostname -u user password ’new password’ 进行。
  用mysqladmin -h hostname flush-privileges或用SQL命令FLUSH PRIVILEGES来装载权限表。
  18.10 文件许可权限问题
  如果你有与文件许可有关的问题,例如,如果当你创建一张表时,mysql发出下列错误消息:
  ERROR: Can’t find file: ’path/with/filename.frm’ (Errcode: 13)
  那么可能是在mysqld启动时,环境变量UMASK可能设置不正确。缺省的umask值是0660。你可以如下启动safe_mysqld改变其行为:
  shell> UMASK=384  # = 600 in octal
  shell> export UMASK
  shell> /path/to/safe_mysqld &
  18.11 文件没找到
  如果你从MySQL得到ERROR ’...’ not found (errno: 23), Can’t open file: ... (errno: 24)或任何其他有errno 23或errno 24的错误,它意味着,你没有为MySQL分配足够的文件描述符。你能使用perror实用程序得到错误号含义是什么的描述:
  shell> perror 23
  File table overflow
  shell> perror 24
  Too many open files
  这里的问题是mysqld正在试图同时保持打开太多的文件。你也可以告诉mysqld一次不打开那么多的文件,或增加mysqld可得到的文件描述符数量。为了告诉mysqld一次保持打开更少的文件,你可以通过使用safe_mysqld的-O table_cache=32选项(缺省值是64)使表缓冲更小。减小max_connections值也将减少打开文件的数量(缺省值是90)。
  要想改变mysqld可用的文件描述符数量,修改safe_mysqld脚本。脚本中有一条注释了的行ulimit -n 256。你可以删除’#’字符来去掉该行的注释,并且改变数字256改变为mysqld可用的文件描述符的数量。
  ulimit能增加文件描述符的数量,但是只能到操作系统强加的限制。如果你需要增加每个进程可用的文件描述符数量的OS限制,参见你的操作系统文档。注意,如果你运行tcsh外壳,ulimit将不工作!当你请求当前限制时,tcsh也将报告不正确的值!在这种情况下,你应该用sh启动safe_mysqld!
  18.12 使用DATE列的问题
  一个DATE值的格式是’YYYY-MM-DD’。根据ANSI SQL,不允许其他格式。你应该在UPDATE表达式和SELECT语句的WHERE子句中使用这个格式。例如:
  mysql> SELECT * FROM tbl_name WHERE date >= ’1997-05-05’;
  为了方便,如果日期用在数字上下文,MySQL自动变换一个日期到一个数字(并且反过来也如此)。当更新时和将一个日期与TIMESTAMP、DATE或DATETIME列比较的一个WHERE子句中,也是足够灵活以允许一种“宽松”的字符串格式。(宽松格式意味着任何标点字符用作在部件之间的分割符。例如,’1998-08-15’和’1998#08#15’是等价的。)MySQL也能变换不包含分割符的一个字符串(例如 ’19980815’),如果它作为一个日期说得通。特殊日期’0000-00-00’可以作为’0000-00-00’被存储和检索。当通过MyODBC使用一个’0000-00-00’日期时,在MyODBC 2.50.12和以上版本,它将自动被转换为NULL,因为ODBC不能处理这种日期。
  因为MySQL实行了上述的变换,下列语句可以工作:
  mysql> INSERT INTO tbl_name (idate) VALUES (19970505);
  mysql> INSERT INTO tbl_name (idate) VALUES (’19970505’);
  mysql> INSERT INTO tbl_name (idate) VALUES (’97-05-05’);
  mysql> INSERT INTO tbl_name (idate) VALUES (’1997.05.05’);
  mysql> INSERT INTO tbl_name (idate) VALUES (’1997 05 05’);
  mysql> INSERT INTO tbl_name (idate) VALUES (’0000-00-00’);
  mysql> SELECT idate FROM tbl_name WHERE idate >= ’1997-05-05’;
  mysql> SELECT idate FROM tbl_name WHERE idate >= 19970505;
  mysql> SELECT mod(idate,100) FROM tbl_name WHERE idate >= 19970505;
  mysql> SELECT idate FROM tbl_name WHERE idate >= ’19970505’;
  然而,下列将不工作:
  mysql> SELECT idate FROM tbl_name WHERE STRCMP(idate,’19970505’)=0;
  STRCMP()是字符串函数,因此它将idate转换为一个字符串并且实施字符串比较。它不将’19970505’转换为一个日期并实施日期比较。
  注意,MySQL不检查日期是否正确。如果你存储一个不正确的日期,例如’1998-2-31’,错误的日期将被存储。如果日期不能被变换到任何合理的值,在DATE字段中存储一个0。这主要是一个速度问题并且我们认为检查日期是应用程序的责任,而不服务器。
  18.13 时区问题
  如果你有一个问题,SELECT NOW()以GMT时间返回值而不是你的本地时间,你必须设定TZ环境变量为你的当前时区。这应该在服务器运行的环境进行,例如在safe_mysqld或mysql.server中。
  18.14 在搜索中的大小写敏感性
  缺省地,MySQL搜索是大小写不敏感的(尽管有一些字符集从来不是忽略大小写的,例如捷克语)。这意味着,如果你用col_name LIKE ’a%’搜寻,你将得到所有以A或a开始的列值。如果你想要使这个搜索大小写敏感,使用象INDEX(col_name, &quot;A&quot;)=0检查一个前缀。或如果列值必须确切是&quot;A&quot;,使用STRCMP(col_name, &quot;A&quot;) = 0。
  简单的比较操作(>=、>、= 、< 、 INSERT INTO my_table (phone) VALUES (NULL);
  mysql> INSERT INTO my_table (phone) VALUES (&quot;&quot;);
  两个语句把值插入到phone列,但是第一个插入一个NULL值而第二个插入一个空字符串。第一个的含义可以认为是“电话号码不知道”,而第二个则可意味着“她没有电话”。
  在SQL中,NULL值在于任何其他值甚至NULL值比较时总是假的(FALSE)。包含NULL的一个表达式总是产生一个NULL值,除非在包含在表达式中的运算符和函数的文档中指出。在下列例子,所有的列返回NULL:
  mysql> SELECT NULL,1+NULL,CONCAT(’Invisible’,NULL);
  如果你想要寻找值是NULL的列,你不能使用=NULL测试。下列语句不返回任何行,因为对任何表达式,expr = NULL是假的:
  mysql> SELECT * FROM my_table WHERE phone = NULL;
  要想寻找NULL值,你必须使用IS NULL测试。下例显示如何找出NULL电话号码和空的电话号码:
  mysql> SELECT * FROM my_table WHERE phone IS NULL;
  mysql> SELECT * FROM my_table WHERE phone = &quot;&quot;;
  在MySQL中,就像很多其他的SQL服务器一样,你不能索引可以有NULL值的列。你必须声明这样的列为NOT NULL,而且,你不能插入NULL到索引的列中。当用LOAD DATA INFILE读取数据时,空列用’’更新。如果你想要在一个列中有NULL值,你应该在文本文件中使用\N。字面词’NULL’也可以在某些情形下使用。见7.16 LOAD DATA INFILE句法。当使用ORDER BY时,首先呈现NULL值。如果你用DESC以降序排序,NULL值最后显示。当使用GROUP BY时,所有的NULL值被认为是相等的。为了有助于NULL的处理,你能使用IS NULL和IS NOT NULL运算符和IFNULL()函数。
  对某些列类型,NULL值被特殊地处理。如果你将NULL插入表的第一个TIMESTAMP列,则插入当前的日期和时间。如果你将NULL插入一个AUTO_INCREMENT列,则插入顺序中的下一个数字。
  18.16 alias问题
  你可以在GROUP BY、ORDER BY或在HAVING部分中使用别名引用列。别名也可以用来为列取一个更好点的名字:
  SELECT SQRT(a*b) as rt FROM table_name GROUP BY rt HAVING rt > 0;
  SELECT id,COUNT(*) AS cnt FROM table_name GROUP BY id HAVING cnt > 0;
  SELECT id AS &quot;Customer identity&quot; FROM table_name;
  注意,你的 ANSI SQL 不允许你在一个WHERE子句中引用一个别名。这是因为在WHERE代码被执行时,列值还可能没有终结。例如下列查询是不合法:SELECT id,COUNT(*) AS cnt FROM table_name WHERE cnt > 0 GROUP BY id;
  WHERE语句被执行以确定哪些行应该包括GROUP BY部分中,而HAVING用来决定应该只用结果集合中的哪些行。
  18.17 从关联的表中删除行
  因为MySQL不支持子选择或在DELETE语句中使用多个表,你应该使用下列方法从2个关联的表中删除行:
  在主表中基于某个WHERE条件SELECT行。
  在主表中基于相同的条件DELETE行。
  DELETE FROM related_table WHERE related_column IN (selected_rows)
  如果在related_column查询中的字符的全部数量超过1,048,576(缺省值max_allowed_packet),你应该分成更小的部分并且执行多个DELETE语句。如果related_column是一个索引,你每次只删除100-1000个related_column id将可能使得DELETE最快。如果related_column不是一个索引,速度与IN子句中参数的数量无关。
  18.18 解决没有匹配行的问题
  如果你有一个复杂的查询,涉及多个表,但没有返回任何行,你应该使用下列过程查找你的询问有什么不对:
  EXPLAIN测试查询并且检查你是否能找出显然是错误的一些东西。见7.22 EXPLAIN句法(得到关于一个SELECT的信息)。
  仅选择那些在WHERE子句中使用的字段。
  一次从查询中删除一个表,直到它返回一些行。如果表很大,对查询使用LIMIT 10是一个好主意。
  对应该已经匹配一行的列做一个SELECT,针对从询问中做后被删除的表。
  如果你将FLOAT或DOUBLE列与有小数的数字进行比较,你不能使用=!。这个问题在大多数计算机语言是常见的,因为浮点值不是准确的值。
  mysql> SELECT * FROM table_name WHERE float_column=3.5;
  ->
  mysql> SELECT * FROM table_name WHERE float_column between 3.45 and 3.55;
  在大多数情况下,将FLOAT改成一个DOUBLE将修正它!
  如果你仍然不能发现错误是什么,创建一个最小的可运行mysql test < query.sql的测试来显示你的问题。你可以用mysqldump --quick database tables > query.sql创建一个测试文件,在一个编辑器编辑文件,删除一些插入行(如果有太多这些语句)并且在文件末尾加入你的选择语句。测试你仍然有问题,可以这样做:
  shell> mysqladmin create test2
  shell> mysql test2 < query.sql
  使用mysqlbug的邮寄测试文件到mysql@lists.mysql.com
  18.19 与ALTER TABLE有关的问题
  如果ALTER TABLE死于这样一个错误:
  Error on rename of ’./database/name.frm’ to ’./database/B-a.frm’ (Errcode: 17)
  问题可能是MySQL在前一个ALTER TABLE中已经崩溃并且留下了一个名为“A-xxx”或“B-xxx”的老的数据库表。在这种情况下,到MySQL数据目录中并删除所有名字以A-或B-开始的文件。(你可以把他们移到别的地方而不是删除他们)。
  ALTER TABLE工作方式是:
  以要求的改变创建一个名为“A-xxx”的新表。
  从老表把所有行拷贝到“A-xxx”。
  老表被改名为“B-xxx”。
  “A-xxx”被改名为你的老表的名字。
  “B-xxx”被删除。
  如果某些改名操作出错,MySQL试图还原改变。如果出错严重(当然,这不应该发生。),MySQL可能留下了老表为“B-xxx”但是一个简单改名就应该恢复你的数据。
  18.20 怎样改变一张表中列的顺序
  SQL的要点是中抽象应用程序以避免数据存储格式。你应该总是以你想要检索数据的意愿指定顺序。例如:
  SELECT col_name1, col_name2, col_name3 FROM tbl_name;
  将以col_name1、col_name2、col_name3的顺序返回列,而:
  SELECT col_name1, col_name3, col_name2 FROM tbl_name;
  将以col_name1、col_name3、col_name2的顺序返回列。
  在一个应用程序中,你应该决不基于他们的位置使用SELECT * 检索列,因为被返回的列的顺序永远不能保证;对你的数据库的一个简单改变可能导致你的应用程序相当有戏剧性地失败。
  不管怎样,如果你想要改变列的顺序,你可以这样做:
  以正确的列顺序创建一张新表。
  执行INSERT INTO new_table SELECT fields-in-new_table-order FROM old_table.
  删除或改名old_table。
  ALTER TABLE new_table RENAME old_table。


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-609502-1-1.html 上篇帖子: MySQL初步使用 下篇帖子: MySQL高可用——PXC简介
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表