[英]Distributed transaction boundary with ActiveRecord
假设我有连接到另一个数据库的模型:
class Model1 < ActiveRecord::Base
establish_connection {config_to_connection_to_database2}
end
class Model2 < ActiveRecord::Base
establish_connection {config_to_connection_to_database2}
end
当我开始交易时,说
Model1.transaction do
Model1.create! something
Model2.create! something
#some other thing
end
生成的SQL是:
BEGIN
INSERT INTO model1 ...
BEGIN
INSERT INTO model2 ...
COMMIT
#some other thing might happen here
COMMIT
如果#some other thing
发生了错误,则INSERT INTO model2
处于嵌套事务中并且已经提交,因此不会回滚,而INSERT INTO model1
被回滚。
我发现了一个丑陋的解决方法:
Model1.transaction do
Model2.transaction do
Model1.create! something
Model2.create! something
#some other thing
end
end
SQL变为:
BEGIN
BEGIN
INSERT INTO model1 ...
INSERT INTO model2 ...
#some other thing might happen here
COMMIT
COMMIT
可行,但对我来说有点烦。
所以我的问题是:activerecord如何决定是否应该使用BEGIN
和COMMIT
包装SQL语句(看起来activerecord不会费心检查Model1和Model2是否连接到同一数据库),并且这里有更好的解决方法吗?
事实证明,解决方案非常简单(答案就在ActiveRecord :: Base文档中,我完全是盲目的)
开设课程
class Database2 < ActiveRecord::Base
self.abstract_class = true #this is important, otherwise the inherited class's table name would be 'database2'
establish_connection your_connection_config
end
然后Model1
和Model2
只需要继承Database2
,一切就可以正常进行。
万一有人怀疑,以这种方式, Model1
和Model2
共享相同的连接池。 如果调用establish_connection
在每类中,那么每个班级都会有自己的连接池,浪费资源,而且会在我的问题中提及的交易问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.