如何查看mysql数据库并发情况
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何查看mysql数据库并发情况相关的知识,希望对你有一定的参考价值。
参考技术A 下载个mysql性能监视器可以的 参考技术B 1.mysql> show status like 'Threads%';+-------------------+-------+
| Variable_name | Value |
+-------------------+-------+
| Threads_cached | 58 |
| Threads_connected | 57 | ###这个数值指的是打开的连接数
| Threads_created | 3676 |
| Threads_running | 4 | ###这个数值指的是激活的连接数,这个数值一般远低于connected数值
+-------------------+-------+
Threads_connected 跟show processlist结果相同,表示当前连接数。准确的来说,Threads_running是代表当前并发数
这是是查询数据库当前设置的最大连接数
2.mysql> show variables like '%max_connections%';
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| max_connections | 1000 |
+-----------------+-------+
可以在/etc/my.cnf里面设置数据库的最大连接数
[mysqld]
max_connections = 1000
max_connections 参数可以用于控制数据库的最大连接数:
3.mysql> show variables like '%connect%';
+--------------------------+-------------------+
| Variable_name | Value |
+--------------------------+-------------------+
| character_set_connection | latin1 |
| collation_connection | latin1_swedish_ci |
| connect_timeout | 10 |
| init_connect | |
| max_connect_errors | 10 |
| max_connections | 4000 |
| max_user_connections | 0 |
+--------------------------+-------------------+
很多开发人员都会遇见”MySQL: ERROR 1040: Too many connections”的异常情况,造成这种情况的一种原因是访问量过高,MySQL服务器抗不住,这个时候就要考虑增加从服务器分散读压力;另一种原因就是MySQL配置文件中max_connections值过小。
首先,我们来查看mysql的最大连接数:
mysql> show variables like '%max_connections%';+-----------------+-------+| Variable_name | Value |+-----------------+-------+| max_connections | 151 |+-----------------+-------+1 row in set (0.00 sec)
其次,查看服务器响应的最大连接数:
mysql> show global status like 'Max_used_connections';
+----------------------+-------+| Variable_name | Value |+----------------------+-------+| Max_used_connections | 2 |+----------------------+-------+1 row in set (0.00 sec)
可以看到服务器响应的最大连接数为2,远远低于mysql服务器允许的最大连接数值。
对于mysql服务器最大连接数值的设置范围比较理想的是:服务器响应的最大连接数值占服务器上限连接数值的比例值在10%以上,如果在10%以下,说明mysql服务器最大连接上限值设置过高。
1
Max_used_connections / max_connections * 100% = 2/151 *100% ≈ 1%
我们可以看到占比远低于10%(因为这是本地测试服务器,结果值没有太大的参考意义,大家可以根据实际情况设置连接数的上限值)。
再来看一下自己 linode VPS 现在(时间:2013-11-13 23:40:11)的结果值:
mysql> show variables like '%max_connections%';
+-----------------+-------+| Variable_name | Value |+-----------------+-------+| max_connections | 151 |+-----------------+-------+1 row in set (0.19 sec)mysql> show global status like 'Max_used_connections';+----------------------+-------+| Variable_name | Value |+----------------------+-------+| Max_used_connections | 44 |+----------------------+-------+1 row in set (0.17 sec)
这里的最大连接数占上限连接数的30%左右。
上面我们知道怎么查看mysql服务器的最大连接数值,并且知道了如何判断该值是否合理,下面我们就来介绍一下如何设置这个最大连接数值。
方法1:
mysql> set GLOBAL max_connections=256;Query OK, 0 rows affected (0.00 sec)mysql> show variables like '%max_connections%';+-----------------+-------+| Variable_name | Value |+-----------------+-------+| max_connections | 256 |+-----------------+-------+1 row in set (0.00 sec)
方法2:
修改mysql配置文件my.cnf,在[mysqld]段中添加或修改max_connections值:
max_connections=128
重启mysql服务即可。本回答被提问者采纳 参考技术C
现象
Sysbench对MySQL进行压测, 并发数过大(>5k)时, Sysbench建立连接的步骤会超时.
猜想
猜想: 直觉上这很简单, Sysbench每建立一个连接, 都要消耗一个线程, 资源消耗过大导致超时.
验证: 修改Sysbench源码, 调大超时时间, 仍然会发生超时.
检查环境
猜想失败, 回到常规的环境检查:
MySQL error log 未见异常.
syslog 未见异常.
tcpdump 观察网络包未见异常, 连接能完成正常的三次握手; 只观察到在出问题的连接中, 有一部分的TCP握手的第一个SYN包发生了重传, 另一部分没有发生重传.
自己写一个简单的并发发生器, 替换sysbench, 可重现场景. 排除sysbench的影响
猜想2
怀疑 MySQL 在应用层因为某种原因, 没有发送握手包, 比如卡在某一个流程上:
检查MySQL堆栈未见异常, 仿佛MySQL在应用层没有看到新连接进入.
通过strace检查MySQL, 发现 accept() 调用确实没有感知到新连接.
怀疑是OS的原因, Google之, 得到参考文档: A TCP “stuck” connection mystery【http://www.evanjones.ca/tcp-stuck-connection-mystery.html】
分析
参考文档中的现象跟目前的状况很类似, 简述如下:
正常的TCP连接流程:
Client 向 Server 发起连接请求, 发送SYN.
Server 预留连接资源, 向 Client 回复SYN-ACK.
Client 向 Server 回复ACK.
Server 收到 ACK, 连接建立.
在业务层上, Client和Server间进行通讯.
当发生类似SYN-flood的现象时, TCP连接的流程会使用SYN-cookie, 变为:
Client 向 Server 发起连接请求, 发送SYN.
Server 不预留连接资源, 向 Client 回复SYN-ACK, 包中附带有签名A.
Client 向 Server 回复ACK, 附带 f(签名A) (对签名进行运算的结果).
Server 验证签名, 分配连接资源, 连接建立.
在业务层上, Client和Server间进行通讯.
当启用SYN-cookie时, 第3步的ACK包因为 某种原因 丢失, 那么:
从Client的视角, 连接已经建立.
从Server的视角, 连接并不存在, 既没有建立, 也没有”即将建立” (若不启用SYN-cookie, Server会知道某个连接”即将建立”)
发生这种情况时:
若业务层的第一个包应是从 Client 发往 Server, 则会进行重发或抛出连接错误
若业务层的第一个包应是从 Server 发往 Client的, Server不会发出第一个包. MySQL的故障就属于这种情况.
TCP握手的第三步ACK包为什么丢失
参考文档中, 对于TCP握手的第三步ACK包的丢失原因, 描述为:
Some of these packets get lost because some buffer somewhere overflows.我们可以通过Systemtap进一步探究原因. 通过一个简单的脚本:
probe kernel.function("cookie_v4_check").return
source_port = @cast($skb->head + $skb->transport_header, "struct tcphdr")->source
printf("source=%d, return=%d\\n",readable_port(source_port), $return)
function readable_port(port)
return (port & ((1<<9)-1)) << 8 | (port >> 8)
观察结果, 可以确认cookie_v4_check (syn cookie机制进行包签名检查的函数)会返回 NULL(0). 即验证是由于syn cookie验证不通过, 导致TCP握手的第三步ACK包不被接受.
之后就是对其中不同条件进行观察, 看看是哪个条件不通过. 最终原因是accept队列满(sk_acceptq_is_full):
static inline bool sk_acceptq_is_full(const struct sock *sk) return sk->sk_ack_backlog > sk- >sk_max_ack_backlog;恢复故障与日志的正关联
在故障处理的一开始, 我们就检查了syslog, 结论是未见异常.
当整个故障分析完成, 得知了故障与syn cookie有关, 回头看syslog, 里面是有相关的信息, 只是和故障发生的时间不匹配, 没有正关联, 因此被忽略.
检查Linux源码:
if (!queue->synflood_warned &&
sysctl_tcp_syncookies != 2 &&
xchg(&queue->synflood_warned, 1) == 0)
pr_info("%s: Possible SYN flooding on port %d. %s.
Check SNMP counters.\\n",
proto, ntohs(tcp_hdr(skb)->dest), msg);
可以看到日志受到了抑制, 因此日志与故障的正关联被破坏.
粗看源码, 每个listen socket只会发送一次告警日志, 要获得日志与故障的正关联, 必须每次测试重启MySQL.
解决方案
这种故障一旦形成, 难以检测; 系统日志中只会出现一次, 在下次重启MySQL之前就不会再出现了; Client如果没有合适的超时机制, 万劫不复.
解决方案:
1. 修改MySQL的协议, 让Client先发握手包. 显然不现实.
2. 关闭syn_cookie. 有安全的人又要跳出来了.
3. 或者调高syn_cookie的触发条件 (syn backlog长度). 降低系统对syn flood的敏感度, 使之可以容忍业务的syn波动.
有多个系统参数混合影响syn backlog长度, 参看【http://blog.dubbelboer.com/2012/04/09/syn-cookies.html】
下图为精华总结
如何同时从多个线程访问 MySQL
【中文标题】如何同时从多个线程访问 MySQL【英文标题】:How to access MySQL from multiple threads concurrently 【发布时间】:2010-11-30 02:57:57 【问题描述】:我们正在做一个 MySQL 的小型基准测试,我们想看看它对我们的数据的执行情况。
该测试的一部分是查看当多个并发线程通过各种查询冲击服务器时它是如何工作的。
MySQL documentation (5.0) 并不清楚多线程客户端。我应该指出,我确实链接到线程安全库 (libmysqlclient_r.so
)
我正在使用准备好的语句并同时执行读取 (SELECT) 和写入 (UPDATE、INSERT、DELETE)。
我应该为每个线程打开一个连接吗?如果是这样:我该怎么做.. 似乎mysql_real_connect()
返回了我调用mysql_init()
时得到的原始数据库句柄)
如果不是:如何确保结果和方法(例如 mysql_affected_rows
)返回正确的值,而不是与其他线程的调用发生冲突(互斥锁/锁可以工作,但感觉不对)
【问题讨论】:
【参考方案1】:作为一个从多个线程调用 MySQL 的相当大的 C 应用程序的维护者,我可以说我在每个线程中简单地建立一个新连接没有任何问题。我遇到的一些警告:
编辑:似乎此项目符号仅适用于 this page for your appropriate version:就像你说你已经在做的那样,链接到libmysqlclient_r
。
致电mysql_library_init()
(一次,来自main()
)。阅读有关在多线程环境中使用的文档,了解其必要性。
在每个线程中使用mysql_init()
创建一个新的MYSQL
结构。这具有为您调用mysql_thread_init()
的副作用。 mysql_real_connect()
像往常一样在每个线程中,具有线程特定的 MYSQL 结构。
如果您要创建/销毁大量线程,则需要在每个线程的末尾使用mysql_thread_end()
(并在main()
的末尾使用mysql_library_end()
)。无论如何,这是一种很好的做法。
基本上,不要共享 MYSQL
结构或为该结构创建的任何特定内容(即 MYSQL_STMT
s),它会按您的预期工作。
这似乎比为我建立一个连接池要少。
【讨论】:
这正是我需要的答案。我没有意识到我必须在每个线程中调用 mysql_init ——我只是在 main() 中调用过一次。谢谢 @chazomaticus,您通常会使用多少线程以及打开多少连接?这是否适用于大量线程/连接?如果您有很多线程(100 到 1000),但不希望打开 1000 个连接的开销(您可能无权访问,因为 max_connections 的默认值通常设置为 100),则连接池非常有用。如果您的线程数量较少,那么您的方法将起作用。为我展示代码示例 +1。 由于 Isak 试图对 DB 施加压力,因此尽可能多的线程。我已经运行了 ~1000 次没有问题(如果所有线程都发出查询,那么它们的大部分时间都在poll()
空闲,所以它不像你想象的那样占用大量 CPU,尽管它可以吃掉一大块内存)。你说得对,max_connections 默认限制在 100,所以为了最大压力,根据需要提高。
我在 mysql 5.6.11 上看不到 libmysqlclient_r
。在文档中也找不到任何多线程信息
看起来从 5.5 开始,他们停止在库的线程安全/不安全版本之间进行拆分。 (很好摆脱。)参见例如dev.mysql.com/doc/refman/5.6/en/c-api-threaded-clients.html 获取有关 5.6 上的多线程的文档。【参考方案2】:
从 mySQL 文档中我可以清楚地看到,任何特定的 MYSQL 结构都可以毫无困难地在线程中使用 - 同时在不同线程中使用 same MYSQL 结构显然会给您带来极其不可预测的结果因为状态存储在 MYSQL 连接中。
因此,要么为每个线程创建一个连接,要么使用上面建议的连接池,并使用某种互斥锁保护对该池的访问(即保留或释放连接)。
【讨论】:
这就是我所怀疑的......只需要弄清楚如何建立多个连接......现在无法让它工作 从来没有遇到过这个问题,但我通常不使用这些库。在我看来,您应该能够分配单独的 MYSQL 结构并初始化并连接每个结构。【参考方案3】:您可以创建一个连接池。每个需要连接的线程都可以从池中请求一个空闲的。如果没有可用的连接,则您要么阻止,要么通过向其添加新连接来扩大池。
有一篇文章here 描述了连接池的优缺点(虽然它是基于 java 的)
编辑:这是一个关于connection pools in C的问题/答案
Edit2:这是一个用 C++ 编写的示例Connection Pool for MySQL 的链接。 (当你实现自己的时候,你可能应该忽略 goto 语句。)
【讨论】:
好答案..谢谢。但是我仍然无法打开多个连接,并且您链接到的示例缺少那段代码。我给了你一个 +1,但我不想接受它(还),因为它不能解决我的问题打开多个连接的问题【参考方案4】:MySQL Threaded Clients in C
它指出 mysql_real_connect() 默认情况下不是线程安全的。需要为线程访问编译客户端库。
【讨论】:
我正在使用 libmysqlclient_r 库,所以我假设它已经编译了所有线程安全的东西。为了确定,我会在产生线程之前尝试做所有连接的东西,看看是否有帮助以上是关于如何查看mysql数据库并发情况的主要内容,如果未能解决你的问题,请参考以下文章