在运行时更改数据库连接

时间:2013-01-29 11:52:55

标签: ruby-on-rails multithreading sqlite database-connection

鉴于

我有一个模型需要连接到专用的内存中SQLite数据库。我正在做的是 - 在这样的类级别创建连接(这里我使用ExternalDatabase提供的连接跳过模式定义):

class ExternalDatabase < ActiveRecord::Base
  self.abstract_class = true

  establish_connection(adapter: 'sqlite', database: ':memory:')
end

class MyModel < ExternalDatabase
end

问题

我怀疑从多个线程访问时上述定义容易出错。一个很好的例子就是当运行Sidekiq工作者从他们的线程中同时写入数据库时​​。

所以问题是:

  1. 从不同的线程访问数据库时,我的怀疑是否正确读/写冲突? sqlite是否将资源锁定在较低级别,从而实现对读/写的安全并发访问?

  2. 如何在运行时更改给定模型的内存中SQLite数据库的连接?由于我使用的是内存数据库,ActiveRecord::Base#establish_connection对我不起作用。

    我想实现这样的目标:

    klass = Class.new(ActiveRecord::Base)
    klass.establish_connection(adapter: 'sqlite', database: ':memory:')  
    
    create_schema(klass.connection)
    
    MyClass.connection = klass.connection
    

    但是Rails在#connection=上缺少直接的ActiveRecord::Base方法(虽然它没有文档#connection_id但似乎仍无效。

2 个答案:

答案 0 :(得分:1)

得出两个结论:

  1. 对于内存数据库,一个线程总是获得一个唯一的连接,即它自己的DB版本,将始终是“新鲜的”,不会与其他线程中的类似数据库进行交互。
  2. 对于常规数据库,应确保在不在类定义内的运行时建立连接。

答案 1 :(得分:0)

这可能有用。

http://www.sqlite.org/faq.html#q6

我快速阅读它表明你可以通过多个踏板访问相同的sqlite数据库,但这是你应该尽量避免做的事情,并带来一些陷阱。