我有一个程序,使用Sequel gem将JSON请求数据存储到Postgres数据库中(它基本上是一个价格聚合器)。但是,使用线程快速从多个位置提取数据。
获得适当的数据后,我目前使用以下内容进行mutex.synchronize:
dbItem = Item.where(:sku => sku).first
dbItem = Item.create(:sku => sku, :name => itemName) if dbItem == nil
dbPrice = Price.create(:price => foundPrice, :quantity => quantity)
dbItem.add_price(dbPrice)
store.add_price(dbPrice)
如果我在没有互斥锁的情况下运行它,我会遇到线程问题 - 例如,代码将尝试在数据库中创建一个项目,但该项目将由另一个线程创建。
然而,使用互斥锁,此代码显着减慢 - 我看到我的程序需要大约四到六倍。
我诚实地对整个数据库做了新事物,所以我只想弄清楚处理线程的最佳方法。我做错了吗? Sequel的文档实际上表明几乎所有线程都安全... 除了模型实例,我相信我的项目情况属于。它说我应该先冻结模型,但我不知道如何在这里应用..
答案 0 :(得分:1)
您不是在处理共享模型实例,这不是线程安全问题,而是竞争条件(使用多个进程,而不仅仅是多个线程)。您需要使用特定于数据库的支持来以无竞争条件的方式处理此问题。在PostgreSQL 9.5+上,您需要使用数据集#insert_conflict。
PostgreSQL文档:https://www.postgresql.org/docs/9.5/static/sql-insert.html