hooopo/second_level_cache

after_commit :update_second_level_cache, :on => :update 会导致某些问题

huacnlee opened this issue · 4 comments

不知道这个算不算问题

我们的项目里面有 RSpec 跑测试,使用 database_cleaner 来实现清除数据,清除方式是 Transaction,然后我发现每次修改的动作 second_level_cache 都没有发起 write cache 的动作。

DatabaseCleaner.strategy = :transaction

test.log

(0.2ms)  BEGIN
(0.1ms)  SAVEPOINT active_record_1
(0.1ms)  RELEASE SAVEPOINT active_record_1
(0.1ms)  SAVEPOINT active_record_1

Photo Load (0.4ms)  SELECT `photos`.* FROM `photos` WHERE `photos`.`deleted_at` IS NULL AND `photos`.`id` = 2 LIMIT 1
Cache write: slc/photo/2/3 ({:expires_in=>7 days})
Photo Exists (0.4ms)  SELECT 1 AS one FROM `photos` WHERE (`photos`.`gcid` = BINARY '96b5b7b451771f9e0cf14fa72a1fceaf' AND `photos`.`id` != 2 AND `photos`.`user_id` = 2) LIMIT 1
SQL (0.3ms)  UPDATE `photos` SET `title` = 'foo', `desc` = 'bar', `updated_at` = '2013-12-24 07:45:31' WHERE `photos`.`id` = 2
# 这里应该有 Cache write: slc/photo/2/3 的
Cache read: slc/photo/2/3

(0.9ms)  ROLLBACK TO SAVEPOINT active_record_1
(0.1ms)  ROLLBACK

我看了一下 second_level_cache 的代码,发现重写 cache 是通过 after_commit 来实现的

after_commit :update_second_level_cache, :on => :update

由于 database_cleaner 直接 Rollback 了,看起来 commit 没有被调用到。
这个文件隐藏太深了,我还一直在怀疑是我其他地方写的东西导致的问题,结果一步一步差下来才发现是这里的问题,于是我将 database_cleaner 改成 Truncation 方式,问题就没了。

DatabaseCleaner.strategy = :truncation
User Load (0.4ms)  SELECT `users`.* FROM `users` WHERE `users`.`deleted_at` IS NULL AND `users`.`id` = 1 LIMIT 1
Cache write: slc/user/1/3 ({:expires_in=>7 days})
Cache read: slc/photo/1/3
(0.1ms)  BEGIN
Photo Exists (0.3ms)  SELECT 1 AS one FROM `photos` WHERE (`photos`.`gcid` = BINARY 'd8b61d7cd9222ccc33f6e31443be8654' AND `photos`.`id` != 1 AND `photos`.`user_id` = 1) LIMIT 1
SQL (0.2ms)  UPDATE `photos` SET `title` = 'foo', `desc` = 'bar', `updated_at` = '2013-12-24 07:56:11' WHERE `photos`.`id` = 1
(1.8ms)  COMMIT
Cache write: slc/photo/1/3 ({:expires_in=>7 days})

这个问题一直都存在,从缓存同步的角度,使用after commit是没问题的,确保只有写入数据库之后才同步缓存。
在 2013-12-24 下午4:01,"Jason Lee" notifications@github.com写道:

不知道这个算不算问题

我们的项目里面有 RSpec 跑测试,使用 database_cleanerhttps://github.com/bmabey/database_cleaner来实现清除数据,清除方式是
Transaction,然后我发现每次修改的动作 second_level_cache 都没有发起 write cache 的动作。

DatabaseCleaner.strategy = :transaction

test.log

(0.2ms) BEGIN(0.1ms) SAVEPOINT active_record_1(0.1ms) RELEASE SAVEPOINT active_record_1(0.1ms) SAVEPOINT active_record_1

Photo Load (0.4ms) SELECT photos.* FROM photos WHERE photos.deleted_at IS NULL AND photos.id = 2 LIMIT 1
Cache write: slc/photo/2/3 ({:expires_in=>7 days})
Photo Exists (0.4ms) SELECT 1 AS one FROM photos WHERE (photos.gcid = BINARY '96b5b7b451771f9e0cf14fa72a1fceaf' AND photos.id != 2 AND photos.user_id = 2) LIMIT 1
SQL (0.3ms) UPDATE photos SET title = 'foo', desc = 'bar', updated_at = '2013-12-24 07:45:31' WHERE photos.id = 2# 这里应该有 Cache write: slc/photo/2/3 的
Cache read: slc/photo/2/3
(0.9ms) ROLLBACK TO SAVEPOINT active_record_1(0.1ms) ROLLBACK

我看了一下 second_level_cache 的代码,发现重写 cache 是通过 after_commit 来实现的

after_commit :update_second_level_cache, :on => :update

由于 database_cleaner 直接 Rollback 了,看起来 commit 没有被调用到。
这个文件隐藏太深了,我还一直在怀疑是我其他地方写的东西导致的问题,结果一步一步差下来才发现是这里的问题,于是我将 database_cleaner
改成 Truncation 方式,问题就没了。

DatabaseCleaner.strategy = :truncation

User Load (0.4ms) SELECT users.* FROM users WHERE users.deleted_at IS NULL AND users.id = 1 LIMIT 1
Cache write: slc/user/1/3 ({:expires_in=>7 days})
Cache read: slc/photo/1/3(0.1ms) BEGIN
Photo Exists (0.3ms) SELECT 1 AS one FROM photos WHERE (photos.gcid = BINARY 'd8b61d7cd9222ccc33f6e31443be8654' AND photos.id != 1 AND photos.user_id = 1) LIMIT 1
SQL (0.2ms) UPDATE photos SET title = 'foo', desc = 'bar', updated_at = '2013-12-24 07:56:11' WHERE photos.id = 1(1.8ms) COMMIT
Cache write: slc/photo/1/3 ({:expires_in=>7 days})


Reply to this email directly or view it on GitHubhttps://github.com//issues/4
.

我只是觉得这个陷阱很容易遇到, DatabaseCleaner 默认的方式就是 transaction,遇到的时候很难想到是这个引起的

在readme里加个说明,怎么样?
在 2013-12-24 下午4:14,"Jason Lee" notifications@github.com写道:

我只是觉得这个陷阱很容易遇到, DatabaseCleaner 默认的方式就是 transaction,遇到的时候很难想到是这个引起的


Reply to this email directly or view it on GitHubhttps://github.com//issues/4#issuecomment-31162923
.

我看行!:smile: