我有一个应用程序对数据库有一些问题:当它试图打开到数据库的连接(或者执行一个查询,这是不清楚的)时,它突然冻结。没有错误消息。我怀疑有一些查询阻塞了其他查询,我正试图弄清楚这是什么。
我用过

SET profiling=1;

但当我执行时:
show profiles;

我只得到我自己执行的查询,而不是应用程序查询(应用程序和我使用的是同一个用户)。
打电话
 SHOW FULL PROCESSLIST;

返回包含所有进程的表。
+-----+----------+---------------------+--------+---------+------+-------+-----------------------+
| Id  | User     | Host                | db     | Command | Time | State | Info                  |
+-----+----------+---------------------+--------+---------+------+-------+-----------------------+
|   8 | user     | <HOST>              | DBs    | Sleep   |    3 |       | NULL                  |
| 722 | user     | <HOST>              | DBs    | Sleep   | 8205 |       | NULL                  |
| 726 | user     | <HOST>              | DBs    | Sleep   | 8212 |       | NULL                  |
| 727 | user     | <HOST>              | DBs    | Sleep   | 8205 |       | NULL                  |
| 728 | user     | <HOST>              | DBs    | Sleep   | 8205 |       | NULL                  |
| 730 | user     | <HOST>              | DBs    | Sleep   | 7172 |       | NULL                  |
| 732 | user     | <HOST>              | DBs    | Sleep   | 8095 |       | NULL                  |
| 733 | user     | <HOST>              | DBs    | Sleep   | 8055 |       | NULL                  |
| 735 | user     | <HOST>              | DBs    | Sleep   | 8075 |       | NULL                  |
| 736 | user     | <HOST>              | DBs    | Sleep   | 8075 |       | NULL                  |
| 737 | user     | <HOST>              | DBs    | Sleep   | 8035 |       | NULL                  |
| 738 | user     | <HOST>              | DBs    | Sleep   | 8015 |       | NULL                  |
| 740 | user     | <HOST>              | DBs    | Sleep   | 7995 |       | NULL                  |
| 741 | user     | <HOST>              | DBs    | Sleep   | 7975 |       | NULL                  |
| 742 | user     | <HOST>              | DBs    | Sleep   | 7955 |       | NULL                  |
| 774 | user     | <HOST>              | DBs    | Sleep   | 5772 |       | NULL                  |
| 779 | user     | <HOST>              | DBs    | Sleep   | 6068 |       | NULL                  |
| 806 | user     | <HOST>              | DBs    | Query   |    0 | init  | SHOW FULL PROCESSLIST |
+-----+----------+---------------------+--------+---------+------+-------+-----------------------+

打电话
show engine innodb status

返回许多事务,有些活动,有些未启动。但没有关于锁定查询的信息。
这个查询,应该会提供有关被阻止查询的信息,返回一个空集:
SELECT r.trx_id waiting_trx_id, r.trx_mysql_thread_id waiting_thread, r.trx_query waiting_query, b.trx_id blocking_trx_id,  b.trx_mysql_thread_id blocking_thread, b.trx_query blocking_query FROM       information_schema.innodb_lock_waits w INNER JOIN information_schema.innodb_trx b  ON   b.trx_id = w.blocking_trx_id INNER JOIN information_schema.innodb_trx r  ON   r.trx_id = w.requesting_trx_id;

有了这些信息,我能保证没有死锁吗?
你能猜一下会发生什么事吗?这样我就可以研究一下了。
有什么方法可以让我得到更多关于流程的信息吗?
我是数据库管理和mysql新手。
谢谢

最佳答案

锁等待延迟
你的意思可能是锁门等待。您可以通过启用慢速查询日志、收集一堆日志,然后查看日志来监视锁等待。下面是一个例子:

# Time: 140605 15:00:06
# User@Host: appuser[appuser] @  [127.0.0.1]  Id:    29
# Schema:   Last_errno: 0  Killed: 0
# Query_time: 0.011732  Lock_time: 0.000161  Rows_sent: 214  Rows_examined: 214  Rows_affected: 0
SET timestamp=1402005606;
SELECT ...blah blah blah...

您可以看到上面的字段Lock_time,它显示查询在开始执行之前等待锁161微秒。然后不到12毫秒执行(如Query_time所示)。
Lock_time非常小是很正常的,通常它甚至超出了范围,所以它显示为0.000000。如果它进入数百毫秒或更多,这是不寻常的。如果是整秒钟,你就有麻烦了。
请注意,除非Query_time超过配置变量long_query_time,否则慢查询日志项将不会写入日志,即使Lock_time很大。有关此问题的更多讨论,请参见http://www.mysqlperformanceblog.com/2012/11/22/get-me-some-query-logs/
连接延迟
您还提到,在运行任何查询之前,获取连接可能会导致延迟。你得查出是不是这样。在任何应用程序语言中,都应该很容易读取连接到数据库之前和之后的时间,并对它们进行比较,看看需要多长时间。有些框架甚至为每个查询提供这种类型的应用程序级分析(或者您可以自己做)。
例如,连接延迟的一个常见原因是mysql服务器正在执行反向dns查找,以将传入套接字的ip地址转换为主机名。它这样做是为了在grant表中查找主机名,以确定user@host拥有哪些特权。但是如果你的dns服务器很慢或者超载,这可能会很慢。令人惊讶的是,它会超过一分之一秒,但这是可能的。
您可以通过设置配置变量skip_name_resolve来加快速度。这意味着您不能基于主机名授予用户权限,您只能通过IP地址标识用户。现实世界中的大多数生产mysql实例都设置了skip_name_resolve
连接速度慢可能还有其他原因,但首先要进行一些应用程序分析,以确定是连接速度慢还是查询速度慢。
注:很多人在说“锁等待”时会说“死锁”,死锁是指两个事务在等待对方的锁时卡住,无法继续进行。死锁不会导致延迟,因为innodb会立即注意到循环依赖性并终止其中一个事务。您可以在show engine innodb status中,在一个名为“最新死锁”的部分中看到是否有死锁。

09-20 23:51