由MySQL too many connections引起的事故

问题起因

oj有一个给contest匹配namelist的功能:选择已经insert的名单,添加到contest的管理界面。

其中有两个更新名单的按钮不会自动去重,即 选择名单后,点击两次会插入两次相同的95人名单,共计190条记录。

为了暂时解决这个问题,我直接在MySQL中删除了后添加的95条数据。

然后通过浏览器查看名单,OJ就崩了!!但是如果不看contest相关的功能,oj可以正常work。

重启apache依旧只能正常访问非contest模块。

这个时候我发现MySQL连不上了,显示Connect failed: Too many connections,修改/etc/my.cnf

max_connections = 1500

重启MySQL,MySQL可以正常连接了,开头出现的问题也解决了。

分析原因

1.MySQL最大连接数

MySQL 5.7默认的最大连接数是151 ,文档在此

既然修改最大连接数解决之前oj卡的问题,大概率是因为之前MySQL的最大连接数不够造成的。

2.MySQL隔离级别

既然在修改最大连接数之前,oj除contest相关功能,其他功能都可以正常访问。

尝试在本地重现,删除几条多余的记录,刷新网页,并没有卡。

查看本地数据库,在information_schema数据库-GLOBAL_VARIABLES表中查看max_connections=151。

说明是访问非本地数据时才有的缓存问题,已知MySQL的默认隔离级别是可重复读,确认当前会话和系统的隔离级别

mysql> use information_schema;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> select @@tx_isolation;
+-----------------+
| @@tx_isolation  |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set, 1 warning (0.00 sec)

mysql> select @@global.tx_isolation;
+-----------------------+
| @@global.tx_isolation |
+-----------------------+
| REPEATABLE-READ       |
+-----------------------+
1 row in set, 1 warning (0.00 sec)

均为可重复读,即可能出现幻读错误。

3.MySQL锁

已知oj的MySQL选取InnoDB索引,即默认使用行级锁。但是当我一下子删除95条数据的时候,且使用索引操作数据,所以并没有升级为表锁。进而开销大,加锁慢;会出现死锁。

4.web端缓存问题

已知使用Bootstrap前端框架,在加载表格数据时使用的是client模式,即一次性加载全部表格内容,根据设置自动分页,无需再次请求服务器。

5.在线上重现问题

将最大连接数还原回默认,重启MySQL,删除没用比赛中的某几条记录,刷新网页,oj并没有卡,怀疑是在线人数较少的原因。

6.查阅相关资料,以及apache的MPM模式

event模式解决了在keep-alive场景下,长期被占用的线程的资源浪费问题,在现在版本里的已经是稳定可用的模式。event MPM中,会有一个专门的线程来管理这些keep-alive类型的线程,当有真实请求过来的时候,将请求传递给服务线程,执行完毕后,又允许它释放。这样增强了高并发场景下的请求处理能力。

结论

昨晚oj卡的原因是,删除数据时请求人数过多(当时上公选课 100人左右,都怀疑自己网的问题,一个劲的刷新,导致火上浇油),每个client都持有访问MySQL的句柄,并且由于当时删除数据contest相关表格出现死锁,导致当前连接超过最大连接数。

update:之前没卡是因为 apache可能是维护了一个MySQL连接池的东西,所以,只要不是【同时】需要MySQL连接,就没有问题,即使考试or比赛有几百人登录。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值