我有一个简单的 Rails 应用程序,其中包含在 MySQL 5.5、Ruby 1.9.3 和 rails 3.2.12 上运行的文章和评论:
class Article < ActiveRecord::Base
attr_accessible :body, :title
has_many :comments
end
class Comment < ActiveRecord::Base
attr_accessible :content
belongs_to :article
end
我为一篇文章生成了很多评论,现在正试图在 rails 控制台中将它们全部删除:
$ rails c
Loading development environment (Rails 3.2.12)
[1] pry(main)> a = Article.find(1)
(2.0ms) SET SQL_AUTO_IS_NULL=0
Article Load (8.0ms) SELECT `articles`.* FROM `articles` WHERE `articles`.`id` = 1 LIMIT 1
=> #<Article id: 1, title: "Test", body: "---\n- Est vel provident. Laboriosam dolor asperiore...", created_at: "2013-05-17 09:54:54", updated_at: "2013-05-21 14:52:18">
[2] pry(main)> require 'benchmark'
[3] pry(main)> puts Benchmark.measure { a.comments.destroy_all }
Comment Load (896.0ms) SELECT `comments`.* FROM `comments` WHERE `comments`.`article_id` = 1
EXPLAIN (2.0ms) EXPLAIN SELECT `comments`.* FROM `comments` WHERE `comments`.`article_id` = 1
EXPLAIN for: SELECT `comments`.* FROM `comments` WHERE `comments`.`article_id` = 1
+----+-------------+----------+------+---------------+------------+---------+-------+-------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------+------+---------------+------------+---------+-------+-------+-------------+
| 1 | SIMPLE | comments | ref | article_id | article_id | 5 | const | 48186 | Using where |
+----+-------------+----------+------+---------------+------------+---------+-------+-------+-------------+
1 row in set (0.00 sec)
SQL (1.0ms) DELETE FROM `comments` WHERE `comments`.`id` = 2
SQL (2.0ms) DELETE FROM `comments` WHERE `comments`.`id` = 3
SQL (1.0ms) DELETE FROM `comments` WHERE `comments`.`id` = 4
SQL (1.0ms) DELETE FROM `comments` WHERE `comments`.`id` = 5
SQL (1.0ms) DELETE FROM `comments` WHERE `comments`.`id` = 6
SQL (5.0ms) DELETE FROM `comments` WHERE `comments`.`id` = 7
SQL (2.0ms) DELETE FROM `comments` WHERE `comments`.`id` = 8
SQL (2.0ms) DELETE FROM `comments` WHERE `comments`.`id` = 9
. . .
SQL (0.0ms) DELETE FROM `comments` WHERE `comments`.`id` = 37360
SQL (0.0ms) DELETE FROM `comments` WHERE `comments`.`id` = 37361
最后一个查询是删除最后一条评论,然后该过程会挂在那里很长时间,然后才最终返回并提交:
(1.9ms) COMMIT
690.380000 1.390000 691.770000 (693.885877)
SHOW PROCESSLIST
确认没有锁:
mysql> show processlist;
+----+----------+-----------+------------------+---------+------+-------+------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+----------+-----------+------------------+---------+------+-------+------------------+
| 6 | bloguser | localhost | blog_development | Query | 0 | NULL | show processlist |
| 7 | bloguser | localhost | blog_development | Sleep | 459 | | NULL |
+----+----------+-----------+------------------+---------+------+-------+------------------+
2 rows in set (0.00 sec)
delete_all
具有dependent: :destroy
或dependent: :delete_all
表现出非常相似的行为。
普遍的看法似乎是,问题destroy_all
在于它实例化了所有对象并一个一个地删除它们,但看起来这不是问题所在。DELETE
在所有的s 都被执行之后,以及 beforeCOMMIT
最终被调用之后,需要这么长时间来处理是什么?