2012-03-07 62 views
0

我使用Valums Ajax Uploader在我的Rails应用程序中创建一个上传照片的好用户界面。一个问题是,它有时候会将Post请求提交得太近,然后它们会导致数据库锁定异常,从而导致所有上传失败一段时间。Rails允许双重请求锁定数据库吗?

这里的日志的例子:

Started POST "/photos?authenticity_token=WPJo8nnJ3KSoG9O%2B%2Flz%2BPbvdtX8cmbEaVB8TidnLx5Y%3D&qqfile=IMG_0417.JPG" for 127.0.0.1 at 2012-03-06 22:39:25 -0600 
Processing by PhotosController#create as HTML 
    Parameters: {"file"=>#<ActionDispatch::Http::UploadedFile:0x007f9e5529f518 @original_filename="IMG_0417.JPG", @content_type="application/octet-stream", @headers=nil, @tempfile=#<File:/var/folders/mf/06zfbjcn63j6p2rqvt6tc77c0000gn/T/raw-upload.20120306-53350-13pew0o>>, "authenticity_token"=>"WPJo8nnJ3KSoG9O+/lz+PbvdtX8cmbEaVB8TidnLx5Y=", "qqfile"=>"IMG_0417.JPG"} 
    User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1 


Started POST "/photos?authenticity_token=WPJo8nnJ3KSoG9O%2B%2Flz%2BPbvdtX8cmbEaVB8TidnLx5Y%3D&qqfile=IMG_0418.JPG" for 127.0.0.1 at 2012-03-06 22:39:30 -0600 
Processing by PhotosController#create as HTML 
    Parameters: {"file"=>#<ActionDispatch::Http::UploadedFile:0x007fcfddd8d268 @original_filename="IMG_0418.JPG", @content_type="application/octet-stream", @headers=nil, @tempfile=#<File:/var/folders/mf/06zfbjcn63j6p2rqvt6tc77c0000gn/T/raw-upload.20120306-53383-1plhm8r>>, "authenticity_token"=>"WPJo8nnJ3KSoG9O+/lz+PbvdtX8cmbEaVB8TidnLx5Y=", "qqfile"=>"IMG_0418.JPG"} 
"authenticity_token"=>"WPJo8nnJ3KSoG9O+/lz+PbvdtX8cmbEaVB8TidnLx5Y=", "qqfile"=>"IMG_0418.JPG"} 
    User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1 
    (0.1ms) begin transaction 
    CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1 
    SQL (0.6ms) INSERT INTO "photos" ("city", "comments_updated_at", "context_id", "country", "created_at", "custom_title", "description", "featured", "flagged", "focus_id", "full_downloads", "height", "image", "lat", "lng", "place", "presentation_downloads", "state", "status", "updated_at", "user_id", "width") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) [["city", nil], ["comments_updated_at", nil], ["context_id", nil], ["country", nil], ["created_at", Tue, 06 Mar 2012 22:39:37 CST -06:00], ["custom_title", nil], ["description", nil], ["featured", false], ["flagged", nil], ["focus_id", nil], ["full_downloads", 0], ["height", 2304], ["image", "admin_tester_630cm1715.JPG"], ["lat", nil], ["lng", nil], ["place", nil], ["presentation_downloads", 0], ["state", nil], ["status", "batch"], ["updated_at", Tue, 06 Mar 2012 22:39:37 CST -06:00], ["user_id", 1], ["width", 3072]] 
    SQL (0.2ms) UPDATE "users" SET "photos_count" = COALESCE("photos_count", 0) + 1 WHERE "users"."id" = 1 
    (0.1ms) begin transaction 
    CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1 
    SQL (5064.0ms) INSERT INTO "photos" ("city", "comments_updated_at", "context_id", "country", "created_at", "custom_title", "description", "featured", "flagged", "focus_id", "full_downloads", "height", "image", "lat", "lng", "place", "presentation_downloads", "state", "status", "updated_at", "user_id", "width") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) [["city", nil], ["comments_updated_at", nil], ["context_id", nil], ["country", nil], ["created_at", Tue, 06 Mar 2012 22:39:43 CST -06:00], ["custom_title", nil], ["description", nil], ["featured", false], ["flagged", nil], ["focus_id", nil], ["full_downloads", 0], ["height", 2304], ["image", "admin_tester_630cm171b.JPG"], ["lat", nil], ["lng", nil], ["place", nil], ["presentation_downloads", 0], ["state", nil], ["status", "batch"], ["updated_at", Tue, 06 Mar 2012 22:39:43 CST -06:00], ["user_id", 1], ["width", 3072]] 
SQLite3::BusyException: database is locked: INSERT INTO "photos" ("city", "comments_updated_at", "context_id", "country", "created_at", "custom_title", "description", "featured", "flagged", "focus_id", "full_downloads", "height", "image", "lat", "lng", "place", "presentation_downloads", "state", "status", "updated_at", "user_id", "width") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) 
    (0.3ms) rollback transaction 
SQLite3::BusyException: cannot rollback transaction - SQL statements in progress: rollback transaction 
Completed 500 Internal Server Error in 17749ms 

ActiveRecord::StatementInvalid (SQLite3::BusyException: cannot rollback transaction - SQL statements in progress: rollback transaction): 
    app/controllers/photos_controller.rb:29:in `create' 
    app/uploaders/flash_session_cookie_middleware.rb:16:in `call' 

显然,这是不好的,如果遇到这种情况只有一个用户上传几张图片就达不到生产标准。那么,你如何解决这个问题?处理上传和处理像这样的文件的正确方法是什么,以便并发性不是一个大问题?

回答

0

如果您有多个进程访问同一个数据库,您可能需要从SQLite进行迁移。虽然SQLite支持它,但它确实需要锁定整个数据库以避免在提交期间破坏数据。这在​​中以粗略的术语解释。

虽然SQLite适用于小规模数据库和开发工作,但对于看到大量写入活动的生产级应用程序来说,这可能不是最好的想法。

好消息是从SQLite转换到MySQL或Postgres通常非常简单。

由于SQLite处理锁定的方式,您可能会遇到某种死锁状况。同样奇怪的是,您的上传将花费如此长的时间来处理。