Mysql 带有ActiveRecord的分布式事务边界
假设我有连接到另一个数据库的模型:Mysql 带有ActiveRecord的分布式事务边界,mysql,ruby-on-rails,activerecord,transactions,Mysql,Ruby On Rails,Activerecord,Transactions,假设我有连接到另一个数据库的模型: class Model1 < ActiveRecord::Base establish_connection {config_to_connection_to_database2} end class Model2 < ActiveRecord::Base establish_connection {config_to_connection_to_database2} end 生成的SQL是: BEGIN INSERT INTO
class Model1 < ActiveRecord::Base
establish_connection {config_to_connection_to_database2}
end
class Model2 < ActiveRecord::Base
establish_connection {config_to_connection_to_database2}
end
生成的SQL是:
BEGIN
INSERT INTO model1 ...
BEGIN
INSERT INTO model2 ...
COMMIT
#some other thing might happen here
COMMIT
当#其他一些事情发生错误时,插入模型2
将不会回滚,因为它位于嵌套事务中并且已提交,而插入模型1
将回滚
我发现了一个丑陋的解决方法:
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
类数据库2
然后Model1
和Model2
只需继承Database2
,一切正常
如果有人想知道,通过这种方式,Model1
和Model2
共享同一个连接池。如果在每个类中调用build\u connection
,那么每个类都会有自己的连接池,这会浪费资源,并且会出现我问题中提到的事务问题
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