Database is getting locked when saving my record

Viewed 182

I am getting the database is locked when trying to save my record. I am trying a simple blog in rails. Having an article model, that contains the attribute, title, image and content. I have not encountered this error before. I am using carrierwave as the image uploader gem. Pls, what am I doing wrong?

Here is the error image enter image description here

the image uploader file

class ImageUploader < CarrierWave::Uploader::Base
  include CarrierWave::MiniMagick

  # Choose what kind of storage to use for this uploader:
  storage :file
  # storage :fog

  # Override the directory where uploaded files will be stored.
  # This is a sensible default for uploaders that are meant to be mounted:
  def store_dir
    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end

  # Create different versions of your uploaded files:
  version :full do
    process resize_to_fit: [650, 650]
  end

  version :thumb do
    process resize_to_fit: [200, 200]
  end

  # Add a white list of extensions which are allowed to be uploaded.
  # For images you might use something like this:
  def extension_whitelist
    %w(jpg jpeg png)
  end

end

Article model

class Article < ApplicationRecord
  belongs_to :author, class_name: 'User'
  mount_uploader :image, ImageUploader

  validates_presence_of :title, :text
  
end
1 Answers

I don't think this is specific to CarrierWave, but more the sqlite database you are working with / logic in your controller. First you are calling sqlite queries before you insert and not wrapping them in a transaction. current_user.articles may be calling many select statements dependant on how many articles they have which could be locking the insert statement so I would look at changing this if you want to continue using sqlite.

Sqlite is nefarious for locking on concurrent access. Whilst it is a fantastic piece of software, a more suitable DBMS like MySQL should be used and it's super easy to setup for local development in a docker container. If you want to save yourself some pain and setup MySQL I've included a little example below.

If you want to stay with sqlite you should open up a console on the database and vacuum it. I find extended development on such databases bloats and you should reclaim some unused space which generally assists with performance.

Lastly, sometimes sqlite files lock up thinking a ghost process is writing to them and restoring the database is one way to fix this. Check by running a simple select command directly on the database (I don't think this would be happening to you if you can view data in forms etc) but just in case, if the command returns true you can dump in bash using the following: echo '.dump' | sqlite3 xxx.db.locked | sqlite3 xxx.db.dumped

Setting up MySQL insert the below into the corresponding files and run docker-compose up if using bash

# Gemfile
gem 'mysql2'

# docker-compose.yml
mysql_repo:
  image: percona:5.7.25
  ports:
    - "3306:3306"
  environment:
    - MYSQL_ALLOW_EMPTY_PASSWORD=yes
    - MYSQL_DATABASE=machine_host
  volumes:
    - /var/lib/mysql

# database.yml
mysql_defaults: &mysql_default
  adapter: mysql2
  encoding: utf8mb4
  reconnect: false
  pool: 5
  username: root
  password:
  host: 0.0.0.0
  port: 3306
  socket: /tmp/mysql.sock

development:
  <<: *mysql_default
  database: repo_development

test:
  <<: *mysql_default
  database: repo_test

production:
  <<: *mysql_default
  database: repo_production
Related