Skip to content

Implement uncached behavior for multiple databases

Patrick Bair requested to merge pb-fix-multiple-databases-uncached into master

What does this MR do and why?

Related to #350191 (closed)

Adds Gitlab::Database.all_uncached, which works similar to ActiveRecord::Base.uncached, but for multiple database connections.

The method is only used in one location in the code right now, so it could be fixed at that spot, but it has somewhat surprising behavior due how it interacts with the load balancer. Since ActiveRecord::Base.uncached only disables the query cache for the current connection, if the load balancer swaps connections underneath, the query cache can be silently reenabled.

To work around that, we set the current session to only use the primary database from the point of calling uncached, to keep the connection consistent.

How to set up and validate locally

Rails implements SQL caching around controller actions, so we won't be able to test directly in the rails console.

  1. First setup your data for multiple databases according to nhttps://docs.gitlab.com/ee/development/database/multiple_databases.html#development-setup
  2. In the ProjectsController#show method add the following snippet before the respond_to block:
    logger.info "******************* testing cache ***************************"
    Project.first
    Project.first
    Ci::Pipeline.first
    Ci::Pipeline.first
  3. Tail the logs with something like tail -f log/development.log | grep -A 10 'testing cache'
  4. Go to the show page for a project, and look at the log output. You should see this for the queries, indicating the second run came from the cache:
    Project Load (1.0ms)  SELECT "projects"."id" ...
    CACHE Project Load (0.0ms)  SELECT "projects"."id" ...
    Ci::Pipeline Load (4.1ms)  SELECT "ci_pipelines".* ...
    CACHE Ci::Pipeline Load (0.0ms)  SELECT "ci_pipelines".*
  5. Now, wrap the entire snippet we added earlier in a Gitlab::Database.all_uncached block:
    Gitlab::Database.all_uncached do
      # earlier snippet
    end
  6. Reload the page, and look at the log output, which should now show the absence of cached queries:
    Project Load (5.2ms)  SELECT "projects"."id" ...
    Project Load (0.7ms)  SELECT "projects"."id" ...
    Ci::Pipeline Load (2.3ms)  SELECT "ci_pipelines".* ...
    Ci::Pipeline Load (0.4ms)  SELECT "ci_pipelines".* ...

MR acceptance checklist

This checklist encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability.

Edited by Patrick Bair

Merge request reports