如何检测MySQL中的死锁?什么可能导致我的应用程序在建立连接时挂起?

时间:2014-06-11 16:13:01

标签: mysql locking

我的应用程序遇到了数据库的一些问题:当它尝试打开与数据库的连接时突然冻结(或执行查询,这一点并不清楚)。没有错误消息。我怀疑有一些查询阻止其他人,我想弄清楚那是什么。 我用了

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的新手。

由于

1 个答案:

答案 0 :(得分:3)

锁定等待的延迟

锁等待可能就是你的意思。您可以通过启用慢查询日志,收集一堆日志,然后查看它来监视锁等待。这是一个例子:

# 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地址转换为主机名。它这样做,因此它可以在授权表中查找主机名,以确定user @ host具有哪些特权。但是,如果您的DNS服务器速度很慢或过载,这可能会很慢。令人惊讶的是,这将超过一秒钟,但它是可能的。

您可以通过设置配置变量skip_name_resolve来加快速度。这意味着您无法根据主机名向用户授予权限,您必须仅通过IP地址识别用户。现实世界中大多数生产MySQL实例都设置为skip_name_resolve

可能还有其他原因导致连接速度缓慢,但首先要进行一些应用程序分析,以确定最终是缓慢连接还是查询。


P.S。:当他们的意思是“锁定等待”时,很多人都说“死锁”。死锁是指两个事务卡在等待彼此的锁定时,它们无法继续。死锁不会导致延迟,因为InnoDB立即注意到周期性依赖并杀死其中一个事务。您可以在标题为“LATEST DEADLOCK”的部分中查看SHOW ENGINE INNODB STATUS中是否存在死锁。