现在使用SQLite3运行rails站点。

大概每500个请求左右,我得到一个

ActiveRecord :: StatementInvalid(SQLite3 :: BusyException:数据库被锁定:...

解决这个问题的方法是什么,这对我的代码来说是微创的?

我目前正在使用SQLLite,因为您可以将数据库存储在源代码控制中,这使得备份变得自然,您可以非常快速地推出更改。 但是,它显然没有真正设置为并发访问。 我明天早上会迁移到MySQL。

===============>>#1 票数:54

您提到这是一个Rails站点。 Rails允许您在database.yml配置文件中设置SQLite重试超时:

production:
  adapter: sqlite3
  database: db/mysite_prod.sqlite3
  timeout: 10000

超时值以毫秒为单位指定。 将其增加到10或15秒应该会减少您在日志中看到的BusyExceptions的数量。

不过,这只是一个临时解决方案。 如果您的站点需要真正的并发性,那么您将不得不迁移到另一个数据库引擎。

===============>>#2 票数:9 已采纳

默认情况下,如果数据库忙且已锁定,则sqlite会立即返回阻塞的忙碌错误。 你可以要求它等待,并在放弃之前继续尝试一段时间。 这通常可以解决问题,除非你有1000个线程访问你的数据库,当我同意sqlite是不合适的。

// set SQLite to wait and retry for up to 100ms if database locked
    sqlite3_busy_timeout( db, 100 );

===============>>#3 票数:3

所有这些都是正确的,但它没有回答这个问题,这很可能是:为什么我的Rails应用程序偶尔会在生产中引发SQLite3 :: BusyException?

@Shalmanese:生产托管环境是什么样的? 它是在共享主机上吗? 是否在NFS共享上包含sqlite数据库的目录? (可能在共享主机上)。

这个问题可能与文件锁定w / NFS共享和SQLite缺乏并发现象有关。

===============>>#4 票数:2

bundle exec rake db:reset

它对我有用,它将重置并显示待处理的迁移。

===============>>#5 票数:2

仅供记录。 在使用Rails 2.3.8的一个应用程序中,我们发现Rails忽略了Rifkin Habsburg建议的“超时”选项。

经过一些调查后,我们在Rails dev中发现了一个可能相关的错误: http//dev.rubyonrails.org/ticket/8811 经过一些调查后,我们找到了解决方案 (使用Rails 2.3.8测试):

编辑此ActiveRecord文件:activerecord-2.3.8 / lib / active_record / connection_adapters / sqlite_adapter.rb

替换这个:

  def begin_db_transaction #:nodoc:
    catch_schema_changes { @connection.transaction }
  end

  def begin_db_transaction #:nodoc:
    catch_schema_changes { @connection.transaction(:immediate) }
  end

就这样! 我们没有注意到性能下降,现在该应用程序支持更多请求而不会中断(它等待超时)。 Sqlite很好!

===============>>#6 票数:1

如果您遇到此问题但增加超时不会改变任何内容 ,那么事务可能会出现另一个并发问题,这里是摘要:

  1. 开始交易(获取共享锁)
  2. 从DB读取一些数据(我们仍在使用SHARED锁)
  3. 同时,另一个进程启动事务并写入数据(获取RESERVED锁)。
  4. 然后你尝试写,你现在正在尝试请求RESERVED
  5. SQLite 立即引发SQLITE_BUSY异常(不依赖于您的超时),因为您之前的读取在获得RESERVED锁定时可能不再准确。

修复此问题的一种方法是修补active_record sqlite适配器,以便在事务开始时直接通过将:immediate选项填充到驱动程序来获取RESERVED锁。 这会稍微降低性能,但至少所有交易都将遵循您的超时并且一个接一个地发生。 下面是如何使用prepend (Ruby 2.0+)将它放在初始化器中:

module SqliteTransactionFix
  def begin_db_transaction
    log('begin immediate transaction', nil) { @connection.transaction(:immediate) }
  end
end

module ActiveRecord
  module ConnectionAdapters
    class SQLiteAdapter < AbstractAdapter
      prepend SqliteTransactionFix
    end
  end
end

在这里阅读更多内容: https//rails.lighthouseapp.com/projects/8994/tickets/5941-sqlite3busyexceptions-are-raised-immediately-in-some-cases-despite-setting-sqlite3_busy_timeout

===============>>#7 票数:1

大多数答案都是针对Rails而不是原始ruby,OPs问题是轨道问题,这很好。 :)

所以我只想在这里留下这个解决方案,如果任何原始ruby用户有这个问题,并且没有使用yml配置。

实例化连接后,您可以这样设置:

db = SQLite3::Database.new "#{path_to_your_db}/your_file.db"
db.busy_timeout=(15000) # in ms, meaning it will retry for 15 seconds before it raises an exception.
#This can be any number you want. Default value is 0.

===============>>#8 票数:1

我在rake db:migrate中遇到了类似的问题。 问题是工作目录位于SMB共享上。 我通过将文件夹复制到我的本地机器来修复它。

===============>>#9 票数:1

Sqlite可以允许其他进程等到当前进程完成。

当我知道我可能有多个进程尝试访问Sqlite DB时,我使用此行进行连接:

conn = sqlite3.connect('filename', isolation_level ='exclusive'

根据Python Sqlite文档:

您可以通过isolation_level参数到connect()调用或通过connections的isolation_level属性来控制pysqlite隐式执行哪种BEGIN语句(或根本不执行)。

===============>>#10 票数:1

资料来源: 此链接

- Open the database
db = sqlite3.open("filename")

-- Ten attempts are made to proceed, if the database is locked
function my_busy_handler(attempts_made)
  if attempts_made < 10 then
    return true
  else
    return false
  end
end

-- Set the new busy handler
db:set_busy_handler(my_busy_handler)

-- Use the database
db:exec(...)

===============>>#11 票数:0

我在sqlite3 ruby​​扩展程序上发现了一个死锁,并在此处修复它:继续使用它,看看这是否能修复你的问题。

https://github.com/dxj19831029/sqlite3-ruby

我打开了一个拉取请求,没有他们的回复。

无论如何,如sqlite3本身所述,预计会有一些繁忙的异常。

请注意这个条件: sqlite很忙

The presence of a busy handler does not guarantee that it will be invoked when there is 
    lock contention. If SQLite determines that invoking the busy handler could result in a 
    deadlock, it will go ahead and return SQLITE_BUSY or SQLITE_IOERR_BLOCKED instead of 
    invoking the busy handler. Consider a scenario where one process is holding a read lock 
    that it is trying to promote to a reserved lock and a second process is holding a reserved 
    lock that it is trying to promote to an exclusive lock. The first process cannot proceed 
    because it is blocked by the second and the second process cannot proceed because it is 
    blocked by the first. If both processes invoke the busy handlers, neither will make any 
    progress. Therefore, SQLite returns SQLITE_BUSY for the first process, hoping that this 
    will induce the first process to release its read lock and allow the second process to 
    proceed.

如果您满足此条件,超时将不再有效。 要避免它,请不要将select放在begin / commit中。 或者使用独占锁来开始/提交。

希望这可以帮助。 :)

===============>>#12 票数:0

这通常是访问同一数据库的多个进程的连续错误,即如果在RubyMine中未设置“仅允许一个实例”标志

===============>>#13 票数:0

尝试运行以下内容,它可能有所帮助:

ActiveRecord::Base.connection.execute("BEGIN TRANSACTION; END;") 

来自: Ruby:SQLite3 :: BusyException:数据库被锁定:

这可以清除阻止系统的任何事务

===============>>#14 票数:0

遇到锁时访问了什么表?

你有长期交易吗?

在遇到锁定时,您能确定哪些请求仍在处理中吗?

===============>>#15 票数:0

唉 - 这是我上周存在的祸根。 当任何进程写入数据库时,Sqlite3会锁定db文件。 IE任何UPDATE / INSERT类型查询(由于某种原因也选择count(*))。 但是,它处理多个读取就好了。

所以,我终于感到沮丧,在数据库调用周围编写自己的线程锁定代码。 通过确保应用程序在任何时候只能有一个线程写入数据库,我能够扩展到1000个线程。

是的,它的速度很慢。 但它也足够快和正确 ,这是一个不错的财产。

===============>>#16 票数:-8

我相信当交易超时时会发生这种情况。 你真的应该使用“真正的”数据库。 像Drizzle或MySQL这样的东西。 您之所以更喜欢SQLite而不是之前的两个选项吗?

  ask by Shalmanese translate from so

未解决问题?本站智能推荐:

2回复

ActiveRecord,Sqlite3和BusyException

我有一个配置了混合mysql和sqlite3 db连接的rails应用程序,并且要将特定模型与sqlite3关联,我向每个类定义添加了一个“ Establishment_connection'sqlite_db_config_name'”行。 当我尝试分别保存任何与sqlite3连接的模型
1回复

更新期间出现SQLite3 BusyException

我很难更新数据库中的信息。 最初,当我尝试保存更改时,它给了我数据库被锁定的错误。 这是有问题的守护程序: 我仅使用sqlite来存储一些信息,另一个数据库是仅从中读取的MySQL数据库。 任何帮助深表感谢。
1回复

ActiveRecord :: StatementInvalid SQLite3 :: BusyException:数据库在批处理插入中被锁定

我正在使用以下方法批量插入 此方法效果很好,但最近才开始引发以下错误: 此错误之后是我尝试执行的sql insert命令。 当我直接将它放入dbconsole时,它可以正常工作。 有什么建议么?
1回复

在Rails上配置远程sqlite3数据库

我使用Rails对应用程序进行了编程,可以将其部署在单台计算机上。 它使用在本地计算机上创建的sqlite3数据库。 现在,我需要将该数据库放在另一台计算机上,但是我不知道如何。 我在另一台计算机和sqlite3上安装了Rails环境。 我以这种方式配置了database.yml文件
1回复

Rails SQlite3 ActiveRecord选择然后更新

我有一个表,我需要在其中选择一些行并根据先前的值对其进行更新,或者如果不存在则创建该表,并且如果针对同一行/记录一次发出多个HTTP请求,则需要这样做以确保安全。 我尝试使用事务和ActiveRecord.lock,但是每当有多个请求时,都会导致“ ActiveRecord :: Stat
1回复

SQLite3 :: SQLException在Rails中实现搜索功能

我正在使用Rails的搜索功能。 我遵循了以下教程 http://railscasts.com/episodes/37-simple-search-form 因此,我使用以下内容更新了tutorial.rb 使用以下内容更新我的tutorials_controller.rb
16回复

Ruby:SQLite3 :: BusyException:数据库被锁定:

今晚开发时SQLite3::BusyException: database is locked:此错误消息: SQLite3::BusyException: database is locked: 我有两个型号: 播客有许多曲目 曲目属于播客。 播客文件托管在mi
1回复

Rails控制台:项目(表不存在?)-SQLite3

我遇到了一个问题。 我最近在github上克隆了一个应用程序,并尝试使用Rails控制台启动它。 当我键入其中一个表的名称时,我收到了此消息。 这是Schema.rb文件 这是项目迁移 宝石文件 这是我的database.yml文件 我尝试了迁移数据库
2回复

Ruby on Rails:到PostgreSQL的数据库sqlite3 [RALS] [重复]

这个问题已经在这里有了答案: PostgreSQL错误:严重:角色“用户名”不存在 14答案 我正在Rails项目中将数据库从sqlite3转换为PostgreSQL,所以我遵循此教程: https : //devcenter.heroku.com/articles
1回复

ActiveRecord SQLite3 BusyException“无法打开保存点”

我正在将Rails3与FactoryGirl和RSpec一起使用进行测试。 某些测试开始失败,并显示以下错误: 失败/错误:let!(:user){FactoryGirl.create:user} ActiveRecord :: StatementInvalid: S