错误案例)
来源:张甦
blog.51cto/sumongodb/1949426
各位技术⽼铁们,福利来了!今天给⼤家说说《数据库中⼗⼤经典错误案例》
⽼张我在刚开始学习数据库的时候,没少⾛弯路。经常会遇到各种稀奇古怪的 error 信息,遇到报错会很慌张,急需⼀个解决问题的办法。跟⽆头苍蝇⼀样,会不加思索地把错误粘到百度上,希望赶紧查⼀下有没有好的处理问题的⽅法。我想这个应该是刚从事数据库的⼩⽩,都会遇到窘境。
今天就给⼤家列举 MySQL 数据库中,最经典的⼗⼤错误案例,并附有处理问题的解决思路和⽅法,希望能给刚⼊⾏,或数据库爱好者⼀些帮助,今后再遇到任何报错,我们都可以很淡定地去处理。
学习任何⼀门技术的同时,其实就是⾃我修炼的过程。沉下⼼,尝试去拥抱数据的世界!
Top 1:Too many connections
(连接数过多,导致连接不上数据库,业务⽆法正常进⾏)
问题还原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 随着连接数的增加性能是会下降的,可以让开发配合设置 thread pool,连接复⽤。在MySQL商业版中加⼊了thread pool这项功能
另外对于有的监控程序会读取 information_schema 下⾯的表,可以考虑关闭下⾯的参数innodb_stats_on_metadata=0
set global innodb_stats_on_metadata=0
Top 2:(主从复制报错类型)
Last_SQL_Errno: 1062 (从库与主库数据冲突)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冲突)Last_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 this
does 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(从库少数据,主库更新的时候,从库报错)Last_SQL_Error:
Could not execute Update_rows event on table test.t; Can't find record
in 't', Error_code: 1032; handler error HA_ERR_KEY_NOT_FOUND; the
event's master log mysql-bin.000014, end_log_pos 1708
解决问题的办法:
根据报错信息,我们可以获取到报错⽇志和position号,然后就能到主库执⾏的哪条sql,导致的主从报错。
在主库执⾏:
/usr/local/mysql/bin/mysqlbinlog --no-defaults -v -v --base64-output=decode-rows /data/mysql/mysql-bin.000014 |grep -
A 10 1708 > 1.log
cat
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 `test`.`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 = 654
COMMIT/*!*/;
DELIMITER ;
#End of log file
ROLLBACK /* added by mysqlbinlog */;
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
获取到 sql 语句之后,就可以在从库反向执⾏ sql 语句。把从库缺少的 sql 语句补全,解决报错信息。
在从库依次执⾏:mysql> 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> exit
Bye
[root@node4 bin]# ./pt-slave-restart -uroot -proot123
案例分析论文格式2017-07-20T14:31:37 p=...,u=root node4-relay-bin.000005 283 1032
Top 3:MySQL安装过程中的报错[root@zs data]# /usr/local/mysql/bin/mysqld_safe --defaults-file=/etc/myf &[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 数据库的数据⽬录没有权限。
解决⽅法:[root@zs data]# chown mysql:mysql -R mysql
[root@zs data]# /usr/local/mysql/bin/mysqld_safe --defaults-file=/etc/myf &
[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,这样就可以避免权限问题。./mysql_install_db --basedir=/usr/local/mysql/ --datadir=/data/mysql/ --defaults-file=/etc/myf --user=mysql
Top 4:数据库密码忘记的问题[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 数据库的过程中,可以这样执⾏:
/usr/local/mysql/bin/mysqld_safe --defaults-file=/etc/myf --skip-grant-tables &
小说阅读网校园版这样启动,就可以不⽤输⼊密码,直接进⼊ mysql 数据库了。然后在修改你⾃⼰想要改的root密码即可。
update mysql.user set password=password('root123') where user='root';
Top 5:truncate 删除数据
李娜英图片导致⾃动清空⾃增ID,前端返回报错 not found。
这个问题的出现,就要考虑下 truncate 和 delete 的区别了。
看下实验演练:
⾸先先创建⼀张表;CREATE TABLE `t` (
`a` int(11) NOT NULL AUTO_INCREMENT,
`b` varchar(20) DEFAULT NULL,
PRIMARY KEY (`a`),
KEY `b` (`b`)
) ENGINE=InnoDB AUTO_INCREMENT=300 DEFAULT CHARSET=utf8
插⼊三条数据: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 对表进⾏删除操作,虽然可以回收表空间,但是会涉及⾃增属性问题。这些坑,我们不要轻易钻进去。
Top 6:
阿⾥云 MySQL 的配置⽂件中,需要注意⼀个参数设置就是:
lower_case_table_names = 0;默认情况
lower_case_table_names = 1;是不区分⼤⼩写 . 如果报你⼩写的表名不到, 那你就把远端数据库的表名改成⼩写 , 反之亦然 . 注意Mybatis 的 Mapper ⽂件的所有表名也要相应修改
Top 7:
有同学经常会问张⽼师,为什么我的数据库总会出现中⽂乱码的情况。⼀堆不知道怎么回事。当向数据库中写⼊创建表,并插⼊中⽂时,会出现这种问题。此报错会涉及数据库字符集的问题。
解决思路:
对于中⽂乱码的情况,记住⽼师告诉你的三个统⼀就可以。还要知道在⽬前的mysql数据库中字符集编码都是默认的UTF8
处理办法:
1、数据终端,也就是我们连接数据库的⼯具设置为 utf8
2、操作系统层⾯;可以通过 cat /etc/sysconfig/i18n 查看;也要设置为 utf8
3、数据库层⾯;在参数⽂件中的 mysqld 下,加⼊ character-set-server=utf8。
跨年留言Emoji 表情符号录⼊ mysql 数据库中报错。Caused by: java.sql.SQLException:
Incorrect string value: 'ðð...' for column 'CONTENT' at row 1
sql.ateSQLException(SQLError.java:1074)
sql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4096)
sql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4028)
sql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2490)
发布评论