Getting Started with Rails & TiDB
Getting Started with Rails & TiDB
可以说 Rails + TiDB 集成的资料尚属早期。缺乏相关基础入门资料。ActiveRecord 这种具有较高复杂性且存在一定的使用门槛与 TiDB 集成。因此编写了这样一个简明指南。
搭建本地TiDB开发环境
安装TiUP
TiUP的安装流程极为简便。不论是Darwin系统还是Linux系统,只需输入一行命令就可完成安装。
    curl --proto '=https' --tlsv1.2 -sSf https://tiup-mirrors.pingcap.com/install.sh | sh
        本机启动集群
    tiup playground
        输出
    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

详细文档
Rails & TiDB 配置
创建Rails项目
    rails new myapp --database=mysql
        database.yml配置
    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
        请注意tiup启动时本地集群的默认配置使用端口4000。为了在Rails中正常运行,请配置数据库连接参数tidb_enable_noop_functions为ON状态。这通常是为了使Rails应用程序能够有效地调用get_lock函数,在tidb中该功能通常是关闭的状态。
如果你使用URI的方式配置数据库链接,也是类似:
    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
        主键、自增、唯一索引
创建一个users表:
    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
        加一个唯一索引
    class AddUniqueIndexForEmail < ActiveRecord::Migration[6.1]
      def change
    add_index :users, :email, unique: true
      end
    end
        在功能上与单机MySQL并无差别,在性能表现上也表现出色;TiDB已展现出良好的兼容性优势;相较于其他分布式数据库而言较为易于上手;然而需要注意的是,在某些情况下需要特别注意其兼容性问题
看看生成的数据表:
    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
虽然在将TiDB与ActiveRecord结合时会遇到主要障碍——即由于TiDB不支持savepoint功能——但我开发了一个简短的补丁来解决这一问题。
    # 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)
        其本质是Rails框架仅在传递参数requires_new设为true时才会触发使用savepoint的功能。为此会在代码中将这些特定位置设置为空值并记录相关日志以完成迁移操作。通常情况下大部分基于Ruby的rails项目的开发中实际应用到savepoint的情况较为有限因此进行迁移操作难度相对较小。而在实际运行过程中当执行migration任务时系统会自动生成相应的savepoint但如果当前未开启多线程环境则无需额外处理即可避免潜在问题
Links
- The Latest Updates on TiDB 5.0*
- 
The Enable No-Op Functions Feature was introduced-in V40*
 
 - 
 
