MySQL数据库常见错误及解决方案
Tags: MySQL
MySQL无法重启问题解决Warning: World-writable config file ‘/etc/my.cnf’ is ignored
原因:
今天帮朋友维护服务器,在关闭数据库的命令发现mysql关不了,提示Warning: World-writable config file '/etc/my.cnf' is ignored ,大概意思是权限全局可写,任何一个用户都可以写。mysql担心这种文件被其他用户恶意修改,所以忽略掉这个配置文件。这样mysql无法关闭。
1 2 3 4 | [root@ttlsa ~]# service mysqld stop Warning: World-writable config file '/etc/my.cnf' is ignored Warning: World-writable config file '/etc/my.cnf' is ignored MySQL manager or server PID file could not be found![FAILED] |
查看my.cnf的权限
1 2 | [root@ttlsa ~]# ls -l /etc/my.cnf -rwxrwxrwx 1 root root 4878 Jul 30 11:31 /etc/my.cnf |
权限777,任何一个用户都可以改my.cnf,存在很大的安全隐患.
解决方案:
修复MySQL问题,my.cnf设置为用户可读写,其他用户不可写
1 | chmod 644 /etc/my.cnf |
Can't connect to MySQL server on 'localhost' (10061)
原因:
不能连接到 localhost 上的mysql
解决方案:
这说明“localhost”计算机是存在的,但在这台机器上却没提供MySQL服务。
需要启动这台机器上的MySQL服务,如果机子负载太高没空相应请求也会产生这个错误。
解决:既然没有启动那就去启动这台机子的mysql。如果启动不成功,多数是因为你的my.ini配置的有问题。重新配置其即可。
如果觉得mysql负载异常,可以到mysql/bin 的目录下执行mysqladmin -uroot -p123 processlist来查看mysql当前的进程。
Unknown MySQL Server Host 'localhosadst' (11001)
原因:
未知的MySQL服务器 localhosadst,服务器 localhosasdst 不存在。或者根本无法连接。
解决方案:
仔细检查自己论坛下面的 ./config.inc.php 找到$dbhost重新设置为正确的mysql 服务器地址。
Access denied for user: 'roota@localhost' (Using password: YES)
原因:
用户 roota 访问 localhost 被拒绝(没有允许通过),造成这个错误一般数据库用户名和密码相对mysql服务器不正确
解决方案:
仔细检查自己论坛下面的 ./config.inc.php 找到$dbuser、$dbpw核实后重新设置保存即可。
Access denied for user: 'red@localhost' to database 'newbbs'
原因:
用户 red 在localhost 服务器上没有权限操作数据库newbbs
这个提示和问题三是不同的。那个是在连接数据库的时候就被阻止了,而这个错误是在对数据库进行操作时引起的。比如在select update等等。这个是因为该用户没有操作数据库相应的权力。比如select 这个操作在mysql.user.Select_priv里记录 Y 可以操作N 不可以操作。
解决方案:
如果是自己的独立主机那么更新mysql.user 的相应用户记录,比如这里要更新的用户为red 。或者直接修改 ./config.inc.php 为其配置一个具有对数据库操作权限的用户
或者通过如下的命令来更新授权grant all privileges on dbname.* to 'user'@'localhost' identified by 'password’
提示:更新了mysql库中的记录一定要重启mysql服务器才能使更新生效
No Database Selected
原因:
产生的原因:有两种。
config.inc.php 里面$dbname设置的不对。致使数据库根本不存在,所以在 $db->select_db($dbname); 时返回了false
和上面问题四是一样的,数据库用户没有select权限,同样会导致这样的错误。当你发现config.inc.php的设置没有任何问题,但还是提示这个错误,那一定就是这种情况了。
解决方案:
对症下药
打开config.inc.php 找到$dbname核实重新配置并保存
同问题四的解决方法
Can't open file: 'xxx_forums.MYI'. (errno: 145)
原因:
这种情况是不能打开 cdb_forums.MYI 造成的,引起这种情况可能的原因:有:
1、服务器非正常关机,数据库所在空间已满,或一些其它未知的原因:,对数据库表造成了损坏。
2、类 unix 操作系统下直接将数据库文件拷贝移动会因为文件的属组问题而产生这个错误。
解决方案:
1、修复数据表
可以使用下面的两种方式修复数据表:(第一种方法仅适合独立主机用户)
1)使用 myisamchk ,MySQL 自带了专门用户数据表检查和修复的工具 —— myisamchk 。更改当前目录到 MySQL/bin 下面,一般情况下只有在这个下面才能运行 myisamchk 命令。常用的修复命令为:myisamchk -r 数据文件目录/数据表名.MYI;
2)通过 phpMyAdmin 修复, phpMyAdmin 带有修复数据表的功能,进入到某一个表中后,点击“操作”,在下方的“表维护”中点击“修复表”即可。
注意:以上两种修复方式在执行前一定要备份数据库。
2、修改文件的属组(仅适合独立主机用户)
复制数据库文件的过程中没有将数据库文件设置为 MySQL 运行的帐号可读写(一般适用于 Linux 和 FreeBSD 用户)。
Table 'test.xxx_sessions' doesn't exist
翻译:xxxxx表不存在
原因:
在执行sql语句时没有找到表,比如:SELECT * FROM xxx_members WHERE uid=’XX’ 这里如果表xxx_members不存在于$dbname库里,那么就会提示这个错误。具体可分为以下三种情况来讨论:
安装插件或者hack时修改了程序文件,而忘记了对数据库作相应的升级。
后台使用了不完全备份,导入数据时没有导入到已经安装了相应版本的论坛的数据库中。
解决方案:
同样对症下药,不同的原因:不同的处理方法。
仔细对照插件作者提供的安装说明,把遗漏的对数据库的操作补上,如果仍然不能解决问题,那么应该怀疑该插件的可用性了。去咨询一下插件作者,或者将其卸载。
不要张冠李戴,多大的脚就穿多大的鞋。总之使得程序文件和数据库配套即可.
Unknown column 'column_name' in 'field list'
原因:
在执行sql语句是出现了指定表中没有的字段名称,就会出现这个错误。具体导致的原因:可分为以下两种安装插件或者hack时修改了程序文件,而忘记了对数据库作相应的升级。
程序文件和数据库不配套,比如d2.5的数据库配置给d4.1的程序来用肯定会出现这个错误。
解决方案:
导致的原因:和问题八的1和 3是相同的,所以解决方法也一样。
You have an error in your SQL syntax
原因:
论坛标准的程序是没有sql语法错误的。所以造成这个错误的原因:一般就两类:安装插件或擅自修改程序。
不同的数据库版本数据库导出导入,比如MySQL4.1的数据在导出的语句包含了MySQL4.0没有的功能,像字符集的设定,这时如果将这些sql导入到MySQL4.0的时候就会产生sql语法错误。
解决方案:
仔细检查看到底是哪里的错误,将其修正,实在不行就用标准程序把出错的程序替换。
在数据库备份的时候要留意,如果不打算倒入到其他版本的mysql中则不用特殊考虑,反之要特殊的设定。使用DZ4.1的后台数据备份,可以按照提示去设定想要的格式。独立主机的也可以在到处的时候将其导出为mysql4.0的格式。
mysqldump -uroot -p --default-character-set=latin1 --set-charset=gbk --skip-opt databse > test.sql
Duplicate entry 'xxx' for key 1
翻译:插入 xxx 使索引1重复
原因:
索引如果是primary unique这两两种,那么数据表的数据对应的这个字段就必须保证其每条记录的唯一性。否则就会产生这个错误。
一般发生在对数据库写操作的时候,例如Discuz!4.1论坛程序要求所有会员的用户名username必须唯一,即username的索引是 unique,这时如果强行往cdb_members表里插入一个已有的username的记录就会发上这个错误,或者将一条记录的username更新 为已有的一个username。
改变表结构的时候也有可能导致这个错误。例如 Discuz!4.0论坛的数据库中cdb_members.username 的索引类型是index这个时候是允许有相同username的记录存在的,在升级到4.1的时候,因为要将username的索引由原来的index变 为unique。如果这时cdb_members里存在有相同的username的记录,那么就会引发这个错误。
导出数据据时有时会因为一些原因:(作者目前还不清楚)导致同一条记录被重复导出,那么这个备份数据在导入的时候出现这个错误是在所难免的了。
修改了auto_increment的值,致使“下一个 Autoindex”为一条已经存在的记录。
解决方案:
两种思路,一是破坏掉唯一性的索引。二是把重复的数据记录干掉,只保留一条。很显然第一种思路是不可取的。那么按照二的思路我们得出以下几种解决方法,对应上面的i ii iii
略
按照错误提示里的信息到数据库中将重复的记录删除,仅保留一条即可。之后继续执行升级操作。
这种情况发生的概率很小,可以用文本编辑器打开备份文档,查找重复的信息。将其多余的拿掉,仅保留一条即可。
查询出表中auto_increment最大的一条记录,设置auto_incerment比其大一即可。
PS:repaire table "表名“,可以暂时解决问题。
Duplicate key name 'xxx'
翻译:索引名重复
原因:
要创建的索引已经存在了,就会引发这个错误,这个错误多发生在升级的时候。可能是已经升级过的,重复升级引起的错误。也有可能是之前用户擅自加的索引,刚好与升级文件中的所以相同了。
解决方案:
看看已经存在的索引和要添加的索引是否一样,一样的话可以跳过这条sql语句,如果不一样那么现删除已存在的所以,之后再执行。
Duplicate column name 'xxx'
翻译:字段名xxx重复
原因:
添加的字段xxx已经存在,多发生在升级过程中,与问题十二的产生是一样的。
解决方案:
看一下已经存在的字段是否和将要添加的字段属性完全相同,如果相同则可以跳过不执行这句sql,如果不一样则删除掉这个字段。之后继续执行升级程序。
Table 'xxx' already exists
翻译:数据表xxx已经存在
原因:
xxx表已经存在于库中,再次试图创建这个名字的表就会引发这个错误。同样多发生在论坛的升级中。类似于问题十二。
解决方案:
看看已经存在的表是否和将要创建的表完全一样,一样的话可以跳过不执行这个sql,否则请将存在的表先删除,之后继续执行升级文件。
Can't create database 'xxx'. Database exists
不能创建数据库xxx,数据库已经存在
原因:
一个mysql下面的数据库名称必须保证唯一性,否则就会有这个错误。
解决方案:
把已经存在的数据库改名或者把将要创建的数据库改名,总之不让他们的名称冲突。
小结(针对问题 11\12\13\14\15)
此类问题错误提示中都暗藏一个关键词duplicate(重复)
那么对于mysql数据库来说什么东西是不能重复的呢?
数据库 database
同一个数据库下数据表 table
同一个数据表下字段 column
同一个数据表下索引 key
同一个数据表在索引唯一(UNIQUE PRIMARY)的情况下记录中的这些字段不可以重复
Unknown system variable 'NAMES'
翻译:未知的系统变量NAMES
原因:
Mysql版本不支持字符集设定,此时强行设定字符集就会出现这个错误。
解决方案:
将sql语句中的SET NAMES ‘xxx’ 语句去掉
Lost connection to MySQL server during query
翻译:MySQL服务器失去连接在查询期间
原因:
远程连接数据库是有时会有这个问题。MySQL服务器在执行一条sql语句的时候失去了连接造成的。
解决方案:
一般不需要怎么去处理,如果频繁的出现那么考虑改善硬件环境。
User 'red' has exceeded the 'max_updates' resource (current value: 500)
翻译:msql用户red已经超过了'max_updates'(最大更新次数),'max_questions'(最大查询次数),'max_connections'(最大连接数),当前设定为500
原因:
在mysql数据库的下有一个库为mysql,它其中有一个表为user这里面的纪录每一条都对应为一个mysql用户的授权。其中字段 max_questions max_updates max_connections分别记录着最大查询次数 最大更新数 最大连接数,当目前的任何一个参数大于任何一个设定的值就会产生这个错误。
解决方案:
独立主机用户可以直接修改授权表。修改完之后重启mysql或者跟新授权表,进入mysql提示符下执行FLUSH PRIVILEGES;
记得后面要有分号’;’
虚拟主机的用户如果总是出现这个问题可找空间商协商解决。
Too many connections (1040)链接过多
翻译:达到最大连接数
原因:
连接数超过了mysql设置的值,与max_connections 和wait_timeout 都有关系。wait_timeout的值越大,连接的空闲等待就越长,这样就会造成当前连接数越大
解决方案:
1.虚拟主机用户请联系空间商优化 MySQL 服务器的配置;
2.独立主机用户请联系服务器管理员优化 MySQL 服务器的配置,可参考:
修改 MySQL 配置文件 my.ini 或者 my.cnf 中的参数:
max_connections= 1000
wait_timeout = 10
修改后重启 MySQL ,如果经常性的报此错误,请做一下服务器的整体优化。
There is no such grant defined for user '%s' on host '%s'
错误编号:1141
原因:
MySQL 当前用户无权访问数据库。
解决方案:
1、虚拟主机用户请联系空间商,确认给你提供的帐号是否有授权数据库的权限。
2、独立主机用户请联系服务器管理员,确认给您提供的数据库帐号是否有管理此数据库的权限。
Error on rename of '%s' to '%s' (errno: %d)
error.:1025
原因:
请检查一下您的程序是否有修改数据库表名的语句。
解决方案:
1.请检查您的程序中哪些地方需要修改数据库表名;
2.如果您的实际应用确实需要修改到数据库表名的话,请联系空间商或者服务器管理员给您开放修改库名的权限和服务器本身是否正常。
Error reading file '%s' (errno: %d)
error.:1023
原因:
数据库文件不能被读取。
解决方案:
1.虚拟主机用户请联系空间商查看数据库是否完好。
2.独立主机用户请联系服务器管理员检查一下 MySQL 本身是否正常, MySQL 是否可以读取文件,Linux 用户可以检查一下 MySQL 的数据库文件的属主是否正确以及本身的文件是否损坏。
Host '...' is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts'
error.:1129
原因:
数据库出现异常,请重启数据库。
解决方案:
由于存在很多连接错误,主机''被屏蔽,虚拟主机用户请联系空间商处理,独立主机用户请联系服务器管理员,在 MySQL 的命令控制台下执行'mysqladmin flush-hosts'解除屏蔽即可,或者重启 MySQL 数据库。
dropping database (can't delete '%s', errno: %d)
error.:1009
原因:
不能删除数据库文件,导致删除数据库失败。
解决方案:
1.检查您使用的数据库管理帐号是否有权限删除数据。
2.检查数据库是否存在。
Got error 28 from table handler
error.:1030
原因:
数据库所在磁盘空间已满。
解决方案:
1.虚拟主机用户请联系空间商增加 MySQL 所在的磁盘空间或者清理一些无用文件;
2.独立主机用户请联系服务器管理员增加 MySQL 所在的磁盘空间或者清理一些无用文件
Can't create a new thread; if you are not out of available memory, you can consult the manual for a possible OS-dependent bug。
error.:11/35
原因:
数据库服务器问题,数据库操作无法创建新线程。一般是两个原因:**:
1.服务器系统内存溢出。
2.环境软件损坏或系统损坏。
解决方案:**
1.虚拟主机用户请联系下空间商数据库服务器的内存和系统是否正常。
2.独立主机用户请联系服务器管理员检查服务器的内存和系统是否正常,如果服务器内存紧张,请检查一下哪些进程消耗了服务器的内存,同时考虑是否增加服务器的内存来提高整个的负载能力。
Error: Client does not support authentication protocol requested by server; consider upgrading MySQL client
error.:1251
原因:
如果你升级 MySQL 到 4.1 以上版本后遇到以上问题,请先确定你的 MySQL Client 是 4.1 或者更高版本( Windows 下有问题你就直接跳到下面看解决方法了,因为 MySQL 在 Windows 是 client 和 server 一起装上了的)。
解决方案:
1. Windows 平台
主要是改变连接 MySQL 的帐户的加密方式,MySQL 4.1/5.0 是通过 PASSWORD 这种方式加密的。可以通过以下两种方法得到解决:
\1) mysql->SET PASSWORD FOR 'some_user'@'some_host'=OLD_PASSWORD('new_password');
\2) mysql->UPDATE mysql.user SET Password=OLD_PASSWORD('new_password') WHERE Host='some_host' AND User='some_user';
\2. Linux/Unix 平台
Linux 平台下首先确定是否安装过 MySQL 的客户端,这个用 rpm 安装很简单,Linux 代码为:
rpm -ivh MySQL-client-4.1.15-0.i386.rpm
然后在编译 php 的时候要加上:
--with-mysql=/your/path/to/mysql
一般情况下都可以解决。如果还出现这种错误,可以按照下面的方法来做:
1 2 | mysql->SET PASSWORD FOR 'some_user'@'some_host'=OLD_PASSWORD('new_password'); mysql->UPDATE mysql.user SET Password=OLD_PASSWORD('new_password') WHERE Host='some_host' AND User='some_user'; |
Error: Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock'
error.:2002
原因:
出现这个错误一般情况下是因为下面两个原因:**:
1.MySQL 服务器没有开启。
2.MySQL 服务器开启了,但不能找到 socket 文件。
解决方案:
1.虚拟主机用户,请联系空间商确认数据库是否正常启动。
2.独立主机用户,请检查一下 MySQL 服务是否已经开启,没有开启,请启动 MySQL 服务;如果已经开启,并且是 Linux 系统,请检查一下 MySQL 的 socket 的路径,然后打开 config.inc.php 找到
$dbhost = 'localhost'; 在 hostname 后面加冒号‘:’和 MySQL 的 socket 的路径。
比如 MySQL 服务器为 localhost
MySQL 的 socket 的路径为 /tmp/mysql.sock
那么就改成如下:
$dbhost = 'localhost:/temp/mysql.sock';**
Can't connect to MySQL server on 'localhost'
error.:2003
原因:
MySQL 服务没有启动,一般是在异常的情况下 MySQL 无法启动导致的,比如无可用的磁盘空间,my.ini 里 MySQL 的 basedir 路径设置错误等。
解决方案:
1.检查磁盘空间是否还有剩余可用空间,尽量保持有足够的磁盘空间可用。
2.检查 my.ini 里的 basedir 等参数设置是否正确,然后重新启动下 MySQL 服务。
Lost connection to MySQL server during query
error.:2013
原因:
数据库查询过程中丢失了与 MySQL 服务器的连接。
解决方案:
1.请确认您的程序中是否有效率很低的程序,比如某些插件,可以卸载掉插件,检查一下服务器是否正常;
2.服务器本身资源紧张,虚拟主机用户请联系空间商确认,独立主机用户请联系服务器管理员,检查一下服务器是否正常。
Got a packet bigger than 'max_allowed_packet' bytes
错误编号:1153
原因:
调整了 Mantis 的上传附件的大小却没有调整 MySQL 的配置文件。
解决方案:
1、独立主机用户请按照以下方法调整:
查找 MySQL 的配置文件(my.cnf 或者 my.ini)
在 [mysqld] 部分添加一句(如果存在,调整其值就可以):
max_allowed_packet=10M
重启 MySQL 服务就可以了。这里设置的是 10MB。
2、虚拟主机用户请联系空间商调整此参数。
Too many connections(连接数过多,导致连接不上数据库,业务无法正常进行)
问题还原:
1 2 3 4 5 6 | mysql> show variables like '%max_connection%'; | Variable_name | Value | max_connections | 151 | mysql> set global max_connections=1;Query OK, 0 rows affected (0.00 sec) [root@node4 ~]# mysql -uzs -p123456 -h 192.168.56.132 ERROR 1040 (00000): Too many connections |
解决问题的思路:
1、首先先要考虑在我们 MySQL 数据库参数文件里面,对应的 max_connections 这个参数值是不是设置的太小了,导致客户端连接数超过了数据库所承受的最大值。
- 该值默认大小是 151,我们可以根据实际情况进行调整。
- 对应解决办法:set global max_connections=500
但这样调整会有隐患,因为我们无法确认数据库是否可以承担这么大的连接压力,就好比原来一个人只能吃一个馒头,但现在却非要让他吃 10 个,他肯定接受不了。反应到服务器上面,就有可能会出现宕机的可能。
所以这又反映出了,我们在新上线一个业务系统的时候,要做好压力测试。保证后期对数据库进行优化调整。
2、其次可以限制 Innodb 的并发处理数量,如果 innodb_thread_concurrency = 0(这种代表不受限制) 可以先改成 16 或是 64 看服务器压力。
如果非常大,可以先改的小一点让服务器的压力下来之后,然后再慢慢增大,根据自己的业务而定,个人建议可以先调整为 16 即可。
MySQL 随着连接数的增加性能是会下降的,在 MySQL 5.7 之前都需要让开发配合设置 thread pool,连接复用。MySQL 5.7 之后数据库自带 thread pool 了,连接数问题也得到了相应的解决。
另外对于有的监控程序会读取 information_schema 下面的表,可以考虑关闭下面的参数: - innodb_stats_on_metadata=0
- set global innodb_stats_on_metadata=0
主从复制报错类型
Last_SQL_Errno: 1062 (从库与主库数据冲突)
1 2 3 4 5 | Last_Errno: 1062 Last_Error: Could not execute Write_rows event on table test.t; Duplicate entry '4' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log mysql-bin.000014, end_log_pos 1505 |
针对这个报错,我们首先要考虑是不是在从库中误操作导致的。结果发现,我们在从库中进行了一条针对有主键表的 sql 语句的插入,导致主库再插入相同 sql 的时候,主从状态出现异常。发生主键冲突的报错。
解决方法:
在确保主从数据一致性的前提下,可以在从库进行错误跳过。一般使用 percona-toolkit 中的 pt-slave-restart 进行。
在从库完成如下操作:
- [root@zs bin]# ./pt-slave-restart -uroot -proot123
2017-07-20T14:05:30 p=...,u=root node4-relay-bin.000002 1506 1062
之后最好在从库中开启 read_only 参数,禁止在从库进行写入操作。
Last_IO_Errno: 1593(server-id冲突)12345Last_IO_Error:Fatal error: The slave I/O thread stops because master and slave have equal MySQL server ids;these ids must be different for replication to work(or the --replicate-same-server-id option must be used on slave but thisdoes not always make sense; please check the manual before using it)这个报错出现之后,就能一目了然看到两台机器的 server-id 是一样的。
在搭建主从复制的过程中,我们要确保两台机器的 server-id 是唯一的。这里再强调一下 server-id 的命名规则(服务器 ip 地址的最后一位+本 MySQL 服务的端口号)。
解决方法:
在主从两台机器上设置不同的 server-id。
Last_SQL_Errno: 1032(从库少数据,主库更新的时候,从库报错)1234Last_SQL_Error:Could not execute Update_rows event on table test.t; Can't find recordin 't', Error_code: 1032; handler error HA_ERR_KEY_NOT_FOUND; theevent's master log mysql-bin.000014, end_log_pos 1708解决问题的办法:
根据报错信息,我们可以获取到报错日志和position号,然后就能找到主库执行的哪条sql,导致的主从报错。
在主库执行:123456789101112131415161718/usr/local/mysql/bin/mysqlbinlog --no-defaults -v -v --base64-output=decode-rows /data/mysql/mysql-bin.000014 |grep -A 10 1708 > 1.logcat 1.log\#170720 14:20:15 server id 3 end_log_pos 1708 CRC32 0x97b6bdec Update_rows: table id 113 flags: STMT_END_F\### UPDATE <code>test</code>.<code>t\### WHERE\### @1=4 /* INT meta=0 nullable=0 is_null=0 */\### @2='dd' /* VARSTRING(60) meta=60 nullable=1 is_null=0 */\### SET\### @1=4 /* INT meta=0 nullable=0 is_null=0 */\### @2='ddd' /* VARSTRING(60) meta=60 nullable=1 is_null=0 */\# at 1708\#170720 14:20:15 server id 3 end_log_pos 1739 CRC32 0xecaf1922 Xid = 654COMMIT/*!*/;DELIMITER ;\# End of log fileROLLBACK /* added by mysqlbinlog */;/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;获取到 sql 语句之后,就可以在从库反向执行 sql 语句。把从库缺少的 sql 语句补全,解决报错信息。
在从库依次执行:123456789mysql> insert into t (b) values ('ddd');Query OK, 1 row affected (0.01 sec)mysql> stop slave;Query OK, 0 rows affected (0.00 sec)mysql> exitBye[root@node4 bin]# ./pt-slave-restart -uroot -proot1232017-07-20T14:31:37 p=...,u=root node4-relay-bin.000005 283 1032
MySQL安装过程中的报错
1 2 3 4 5 6 7 8 9 10 | [root@zs data]# /usr/local/mysql/bin/mysqld_safe --defaults-file=/etc/my.cnf &[1] 3758 [root@zs data]# 170720 14:41:24 mysqld_safe Logging to '/data/mysql/error.log'. 170720 14:41:24 mysqld_safe Starting mysqld daemon with databases from /data/mysql170720 14:41:25 mysqld_safe mysqld from pid file /data/mysql/node4.pid ended 170720 14:41:24 mysqld_safe Starting mysqld daemon with databases from /data/mysql2017-07-20 14:41:25 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details)./usr/local/mysql/bin/mysqld: File '/data/mysql/mysql-bin.index' not found (Errcode: 13 - Permission denied) 2017-07-20 14:41:25 4388 [ERROR] Aborting |
解决思路:
遇到这样的报错信息,我们要学会时时去关注错误日志 error log 里面的内容。看见了关键的报错点Permission denied,证明当前 MySQL 数据库的数据目录没有权限。
解决方法:
1 2 3 4 5 | [root@zs data]# chown mysql:mysql -R mysql [root@zs data]# /usr/local/mysql/bin/mysqld_safe --defaults-file=/etc/my.cnf & [1] 4402 [root@zs data]# 170720 14:45:56 mysqld_safe Logging to '/data/mysql/error.log'. 170720 14:45:56 mysqld_safe Starting mysqld daemon with databases from /data/mysql |
启动成功。
如何避免这类问题,个人建议在安装 MySQL 初始化的时候,一定加上--user=mysql,这样就可以避免权限问题。
1 2 3 | ./mysql_install_db --basedir=/usr/local/mysql/ --datadir=/data/mysql/ --defaults-file=/etc/my.cnf --user=mysql |
数据库密码忘记的问题
1 2 3 4 5 6 | [root@zs ~]# mysql -uroot -p Enter password: ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES) [root@zs ~]# mysql -uroot -p Enter password: ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES) |
我们有可能刚刚接手别人的 MySQL 数据库,而且没有完善的交接文档。root 密码可以丢失或者忘记了。
解决思路:
目前是进入不了数据库的情况,所以我们要考虑是不是可以跳过权限。因为在数据库中,MySQL 数据库中 user 表记录着我们用户的信息。
解决方法:
启动 MySQL 数据库的过程中,可以这样执行:
1 | /usr/local/mysql/bin/mysqld_safe --defaults-file=/etc/my.cnf --skip-grant-tables & |
这样启动,就可以不用输入密码,直接进入 MySQL 数据库了。然后在修改你自己想要改的 root 密码即可。
1 2 | update mysql.user set password=password('root123') where user='root'; |
truncate 删除数据,导致自动清空自增 ID,前端返回报错 not found
这个问题的出现,就要考虑下 truncate 和 delete 的区别了,看下实验演练:
首先先创建一张表:
1 2 3 4 5 6 | CREATE TABLE <code>t</code> ( a</code> int(11) NOT NULL AUTO_INCREMENT, b</code> varchar(20) DEFAULT NULL, PRIMARY KEY (<code>a</code>), KEY <code>b</code> (<code>b</code>) ) ENGINE=InnoDB AUTO_INCREMENT=300 DEFAULT CHARSET=utf8 |
插入三条数据:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | mysql> insert into t (b) values ('aa'); Query OK, 1 row affected (0.00 sec) mysql> insert into t (b) values ('bb'); Query OK, 1 row affected (0.00 sec) mysql> insert into t (b) values ('cc'); Query OK, 1 row affected (0.00 sec) mysql> select * from t; +-----+------+ | a | b | +-----+------+ | 300 | aa | | 301 | bb | | 302 | cc | +-----+------+ 3 rows in set (0.00 sec) |
先用 delete 进行删除全表信息,再插入新值。
结果发现 truncate 把自增初始值重置了,自增属性从 1 开始记录了。当前端用主键 id 进行查询时,就会报没有这条数据的错误。
个人建议不要使用 truncate 对表进行删除操作,虽然可以回收表空间,但是会涉及自增属性问题。这些坑,我们不要轻易钻进去。
阿里云 MySQL 的配置文件
阿里云 MySQL 的配置文件中,需要注意一个参数设置就是:
- lower_case_table_names = 0;默认情况。
- lower_case_table_names = 1;是不是区分大小写。
如果报你小写的表名找不到,那你就把远端数据库的表名改成小写,反之亦然。注意 Mybatis 的 Mapper 文件的所有表名也要相应修改。
数据库总会出现中文乱码的情况
有同学经常会问,为什么我的数据库总会出现中文乱码的情况。一堆中文乱码不知道怎么回事?当向数据库中写入创建表,并插入中文时,会出现这种问题。此报错会涉及数据库字符集的问题。
解决思路:
对于中文乱码的情况,记住老师告诉你的三个统一就可以。还要知道在目前的 MySQL 数据库中字符集编码都是默认的 UTF8。
处理办法:
- 数据终端,也就是我们连接数据库的工具设置为 utf8。
- 操作系统层面,可以通过 cat /etc/sysconfig/i18n 查看,也要设置为 utf8。
数据库层面,在参数文件中的 mysqld 下,加入 character-set-server=utf8。
Emoji 表情符号录入 MySQL 数据库中报错:123456789Caused by: java.sql.SQLException: Incorrect string value: '\xF0\x9F\x98\x97\xF0\x9F...' for column 'CONTENT' at row 1at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1074)at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4096)at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4028)at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2490)at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2651)at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2734)at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2155)at com.mysql.jdbc.PreparedStatement.execute(PreparedStatement.java:1379)解决思路:
针对表情插入的问题,一定还是字符集的问题。
处理方法:
我们可以直接在参数文件中,加入:
vim /etc/my.cnf
[mysqld]
init-connect='SET NAMES utf8mb4'
character-set-server=utf8mb4
注:utf8mb4 是 utf8 的超集。
使用 binlog_format=statement 这种格式,跨库操作,导致从库丢失数据,用户访问导致出现错误数据信息
当前数据库二进制日志的格式为:binlog_format=statement
在主库设置 binlog-do-db=mydb1(只同步mydb1这一个库)。
在主库执行 use mydb2;
insert into mydb1.t1 values ('bb');这条语句不会同步到从库。
但是这样操作就可以;
use mydb1;
insert into mydb1.t1 values ('bb');因为这是在同一个库中完成的操作。
在生产环境中建议使用binlog的格式为row,而且慎用 binlog-do-db 参数。
MySQL 数据库连接超时的报错
org.hibernate.util.JDBCExceptionReporter - SQL Error:0, SQLState: 08S01
org.hibernate.util.JDBCExceptionReporter - The last packet successfully received from the server was43200 milliseconds ago.The last packet sent successfully to the server was 43200 milliseconds ago, which is longer than the server configured value of 'wait_timeout'. You should consider either expiring and/or testing connection validity before use in your application, increasing the server configured values for client timeouts, or using the Connector/J connection 'autoReconnect=true' to avoid this problem.
org.hibernate.event.def.AbstractFlushingEventListener - Could not synchronize database state with session
org.hibernate.exception.JDBCConnectionException: Could not execute JDBC batch update
com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Connection.close() has already been called. Invalid operation in this state.
org.hibernate.util.JDBCExceptionReporter - SQL Error:0, SQLState: 08003
org.hibernate.util.JDBCExceptionReporter - No operations allowed after connection closed. Connection was implicitly closed due to underlying exception/error:
BEGIN NESTED EXCEPTION
大多数做 DBA 的同学,可能都会被开发人员告知,你们的数据库报了这个错误了,赶紧看看是哪里的问题。
这个问题是由两个参数影响的,wait_timeout 和 interactive_timeout。
数据默认的配置时间是 28800(8小时)意味着,超过这个时间之后,MySQL 数据库为了节省资源,就会在数据库端断开这个连接,MySQL 服务器端将其断开了,但是我们的程序再次使用这个连接时没有做任何判断,所以就挂了。
解决思路:
先要了解这两个参数的特性,这两个参数必须同时设置,而且必须要保证值一致才可以。
我们可以适当加大这个值,8 小时太长了,不适用于生产环境。因为一个连接长时间不工作,还占用我们的连接数,会消耗我们的系统资源。
解决方法:
可以适当在程序中做判断,强烈建议在操作结束时更改应用程序逻辑以正确关闭连接,然后设置一个比较合理的 timeout 的值(根据业务情况来判断)。
can't open file (errno:24)
有的时候,数据库跑得好好的,突然报不能打开数据库文件的错误了。
解决思路:
首先我们要先查看数据库的 error log。然后判断是表损坏,还是权限问题。还有可能磁盘空间不足导致的不能正常访问表;操作系统的限制也要关注下;用 perror 工具查看具体错误!
1 2 | linux:/usr/local/mysql/bin # ./perror 24 OS error code 24: Too many open files |
超出最大打开文件数限制!ulimit -n 查看系统的最大打开文件数是 65535,不可能超出!那必然是数据库的最大打开文件数超出限制!
在 MySQL 里查看最大打开文件数限制命令:show variables like 'open_files_limit';
发现该数值过小,改为 2048,重启 MySQL,应用正常。
处理方法:
1 2 | repair table ; chown mysql 权限 |
清理磁盘中的垃圾数据