Getting Started with Rails & TiDB

Getting Started with Rails & TiDB

Perhaps the first Rails + TiDB integration tutorial, there are so few articles on the web for newbies to get started, and there is a real barrier to integrating a complex ORM like ActiveRecord with TiDB,…


This content originally appeared on DEV Community and was authored by Hooopo

Getting Started with Rails & TiDB

Perhaps the first Rails + TiDB integration tutorial, there are so few articles on the web for newbies to get started, and there is a real barrier to integrating a complex ORM like ActiveRecord with TiDB, so I wrote this tutorial to get started.

Build a local TiDB development environment

Installing TiUP

The TiUP installation process is very straightforward for both Darwin and Linux operating systems, and can be successfully installed with a single command.

curl --proto '=https' --tlsv1.2 -sSf https://tiup-mirrors.pingcap.com/install.sh | sh

Local start cluster

tiup playground

Output

tiup playground
Starting component ``playground``: /Users/hooopo/.tiup/components/playground/v1.4.1/tiup-playground
Use the latest stable version: v5.0.0

    Specify version manually: tiup playground <version>
    The stable version: tiup playground v4.0.0
    The nightly version: tiup playground nightly

Playground Bootstrapping...
Start pd instance
Start tikv instance
Start tidb instance
Waiting for tidb instances ready
127.0.0.1:4000 ... Done
Start tiflash instance
Waiting for tiflash instances ready
127.0.0.1:3930 ... Done
CLUSTER START SUCCESSFULLY, Enjoy it ^-^
To connect TiDB: mysql --host 127.0.0.1 --port 4000 -u root -p (no password)
To view the dashboard: http://127.0.0.1:2379/dashboard
To view the Prometheus: http://127.0.0.1:9090
To view the Grafana: http://127.0.0.1:3000

dashboard

detailed documentation

Rails & TiDB Configuration

Create a Rails project

rails new myapp --database=mysql

database.yml configuration

default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  port: 4000
  username: root
  password:
  host: 127.0.0.1
  variables:
    tidb_enable_noop_functions: ON

Note that the default port for the local cluster started by tidup is 4000, set the database connection variable tidb_enable_noop_functions: ON because Rails requires the get_lock function, which is turned off by default in tidb.

If you configure the database link using the URI method, it is similar to.

default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  url: <%= ENV.fetch("DB_URL") || "mysql2://root:pass@localhost:4000/myapp" %>
  variables:
    tidb_enable_noop_functions: ON

primary-key, auto-increment, unique-index

Create a users table.

class CreateUsers < ActiveRecord::Migration[6.1]
  def change
    create_table :users do |t|
      t.string :email
      t.string :password
      t.string :username

      t.timestamps
    end
  end
end

Add a unique index

class AddUniqueIndexForEmail < ActiveRecord::Migration[6.1]
  def change
    add_index :users, :email, unique: true
  end
end

There is no difference to using standalone MySQL, TiDB is already very compatible and much easier to get started with than other distributed databases, some of which are incompatible with primary keys, self-incrementing, unique indexes and other features that require additional handling.

Take a look at the generated data table.

mysql> show create table users;
+ -------+------------------------------------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------+
| Table | Create Table |
+-------+------------------------------------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------+
| users | CREATE TABLE `users` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `email` varchar(255) DEFAULT NULL,
  `password` varchar(255) DEFAULT NULL,
  `username` varchar(255) DEFAULT NULL,
  `created_at` datetime(6) NOT NULL,
  `updated_at` datetime(6) NOT NULL,
  PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */,
  UNIQUE KEY `index_users_on_email` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin AUTO_INCREMENT=30001 |
+-------+------------------------------------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------+
1 row in set (0.01 sec)

savepoint patch

The only obstacle to combining TiDB and ActiveRecord is that TiDB does not support savepoint, I wrote a simple patch to solve it:

# https://github.com/rails/rails/blob/6-1-stable/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb#L313
require 'active_record/connection_adapters/abstract/database_statements.rb'


module DisableSavepoint
  def transaction(requires_new: nil, isolation: nil, joinable: true)
    if requires_new
      requires_new = nil
      Rails.logger.warn "savepoint statement was used, but your db not support, ignored savepoint."
      Rails.logger.warn caller
      super(requires_new: requires_new, isolation: isolation, joinable: joinable)
    else
      super(requires_new: requires_new, isolation: isolation, joinable: joinable)
    end
  end
end

ActiveRecord::ConnectionAdapters::DatabaseStatements.send(:prepend, DisableSavepoint)

The principle is that Rails will only introduce savepoint when transaction passes the parameter requires_new to true, and then output logs to migrate through the patch where requires_new is true to nil. My experience is that most Rails projects don't use savepoint much, so it's not hard to migrate if you want to. When running migration, savepoint is introduced, but in scenarios where there is no concurrent migration, it's not a big deal to remove it directly.

Links


This content originally appeared on DEV Community and was authored by Hooopo


Print Share Comment Cite Upload Translate Updates
APA

Hooopo | Sciencx (2021-04-21T17:54:57+00:00) Getting Started with Rails & TiDB. Retrieved from https://www.scien.cx/2021/04/21/getting-started-with-rails-tidb/

MLA
" » Getting Started with Rails & TiDB." Hooopo | Sciencx - Wednesday April 21, 2021, https://www.scien.cx/2021/04/21/getting-started-with-rails-tidb/
HARVARD
Hooopo | Sciencx Wednesday April 21, 2021 » Getting Started with Rails & TiDB., viewed ,<https://www.scien.cx/2021/04/21/getting-started-with-rails-tidb/>
VANCOUVER
Hooopo | Sciencx - » Getting Started with Rails & TiDB. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2021/04/21/getting-started-with-rails-tidb/
CHICAGO
" » Getting Started with Rails & TiDB." Hooopo | Sciencx - Accessed . https://www.scien.cx/2021/04/21/getting-started-with-rails-tidb/
IEEE
" » Getting Started with Rails & TiDB." Hooopo | Sciencx [Online]. Available: https://www.scien.cx/2021/04/21/getting-started-with-rails-tidb/. [Accessed: ]
rf:citation
» Getting Started with Rails & TiDB | Hooopo | Sciencx | https://www.scien.cx/2021/04/21/getting-started-with-rails-tidb/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.