20200208のMySQLに関する記事は8件です。

【Mysql】日付カラムのデータ型はdate型?varchar型? 問題を議論してみたい

こんにちは。
データエンジニアのKotaです。
初投稿ですが、お手柔らかにお願いします。

普段僕は自社プロダクトのデータ分析チームで、
ビッグデータ分析基盤の要件定義~運用まで一気通貫で作らせて頂いてます。

そこで今回議論したいのが、表題の件。

現場によっても、下手すれば現場内のDBによってもバラバラの型をしている日付カラム。
皆さんお持ちのDBでは、どちらの型になっているでしょうか??

議論したいと思ったきっかけ

かくいう僕も、この問題で先日上司と軽くバトりました。
まずはその話から簡単に触れます。ちなみにエンジンはMysqlです。

ある日、別の分析基盤を作っている後輩のDB設計書をレビューする機会がありました。メンバーは後輩・僕・上司の3人。
そこで後輩が、分析用一時テーブルの日付列のデータ型を以下の様にしていました。

カラム名 データ型
CREATE_TIME(作成日) varchar(14)
UPDATE_TIME(更新日) varchar(14)

恐らく一部マスタ系のテーブル以外はほぼ持っているであろうこのカラム。

これに対し、語気を強めてツッコミを入れたのが先輩です。

「ここの2つさ、datetime型にしてよ!!!」

お?そんな強く言うこと?
いや、てか別にvarcharで良くね?
むしろvarcharが良くね?と思ったのが僕。

その旨上司に伝えてみると、

「いやいや絶対datetime型!!」の一点張り。

その場で議論が始まるも、平行線。
ちなみに既存の分析基盤はdatetimeだったので、
しょうがなく僕が折れる形でdatetimeに決着しました。

僕の言い分

事実だけ伝えられても「そっか...」って感じだと思うので、
お互いの主張の理由を見てみましょう。

まずは僕から。僕の主張の根拠は以下3つです。

①チューニングのしやすさ
②業務用DBとのフォーマット合わせ


僕が重視したのはこれです。
検索の際に関数を指定しなくて良くなるので非常に楽。
特に既存の分析用SQLなんかは、
件数が億に迫るテーブルから、1日分のデータを以下のように算出していました。

SELECT ...
FROM ...
WHERE DATE(RPAD(UPDATE_TIME,14,0)) BETWEEN DATE_SUB(CURRENT_DATE(), INTERVAL 1 DAY) AND CURRENT_DATE();

ちなみにこれ以外に条件はありません。中にはこれに加え、結合を行っているものも複数あります。
WHERE条件で使用しているUPDATE_TIMEをdate型に変換+謎のRPAD関数と、
関数を2ネストかましています。(恐らく不良データ対策でしょう)
当然関数を使ってるのでインデックスは効きません。
それどころかこのテーブル、UPDATE_TIMEを第一項目としたインデックスすら付与していない始末。
既に件数が億近いテーブルからこの条件でデータ抽出。よく今までやってたな...って感じです。
UPDATE_TIMEがvarcharになれば、不必要にdate変換なんてしなくて良いので、
インデックス効くようになるし。RPADは知らん。作った人辞めてて理由は誰も知らん。地獄って感じ。

②こちらの理由もあります。うちの現場、UPDATE_TIMEの扱いがDBによって違います。

★業務用DB

カラム名 データ型
CREATE_TIME(作成日) varchar(14)
UPDATE_TIME(更新日) varchar(14)

★分析用DB

カラム名 データ型
CREATE_TIME(作成日) datetime
UPDATE_TIME(更新日) datetime

★分析結果可視化用DB

カラム名 データ型
CREATE_TIME(作成日) datetime
UPDATE_TIME(更新日) datetime

何で違うんでしょうね。作った人辞めてて理由は誰も知らん。地獄って感じ。
恐らく可視化の際に、BIツールでのデータソース読み込みで都合が悪そうだからdatetimeにしてるのかな...って感じはします。

今回後輩君はこの理由でvarcharにしたそうです。不良データなら可視化DBに移送する際にチェックできるし。だそうです。その通りだと思います。

上司の言い分

一方、上司の言い分です。

①現行踏襲
②不良データへのリスク
③設計書見て、「日付入れてるんだな」って分かりやすい

①、③は聴き流してました。

②が彼のメイン主張。
僕のチューニングに対する言い分を聞いた上で、
「運用乗ってるし、何か変わったときに変なデータ入って処理が落ちるリスクがある」んだそう。
その辺の検証をする時間的余裕はない!って言われてしまったので、
それ以上何も言い返せず、この場は終わりました。

モヤモヤする...。

あまりにモヤっとなのでここに書かせて頂きました。
またハードウェアに優しくない激重SQLが1つ出来上がってしまうのかと思うと...。

僕が経験してきた現場でも、ここの型にはバラツキがあったので気になります。どっちがより良いんでしょうか。

皆さんの現場ではここのデータ型、何にしていますか?
どんな理由があってその型にしていますか?

ぜひご教授頂けたら、とても嬉しいです。

最後まで見て頂いて、ありがとうございました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

mysqlのデフォルト値の設定

やりたいこと

デフォルトのプロフィール画像を設定したい。

マイグレーションでのデフォルト値設定

カラムにデフォルト値を設定するには->default('[値]')をつけるだけです。

    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->string('profile_image')->nullable()->comment("プロフィール画像")->default('default_icon.jpeg');
        });
    }

profile_imageカラムにdefault_icon.jpegをデフォルト値を設定しました。

あとはストレージにdefault_icon.jpegを置いとくだけ。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Node.js - MySQL「Error: Cannot enqueue Query after invoking quit.」の対処(Connection pool)

はじめに

本記事はデータベースにおけるコネクションプール(Connection pool)について触れていくものです。

実際にハマったシチュエーションをもとに説明していきたいと思います。

  • 事象の詳細
  • 原因
  • 状況を再現してみる
  • 適切な対処方法
  • コネクションプールの実装

事象の詳細

Node.jsにて、MySQLからデータを取得しようとしたとき、以下のエラーが発生した。

Error: Cannot enqueue Query after invoking quit.

どうやら2回目のGET:/api/todoを呼び出した時に必ず発生するようです。
その時のソースコードは以下です。

const express = require("express");
const mysql = require("mysql");
const app = express();

// データベースへのコネクションを生成
const connection = mysql.createConnection({
  // DB接続に関するオプション設定
});

connection.connect();

app.get("/api/todo", (req, res) => {
  const query = "SELECT * FROM todo;";

  connection.query(query, (err, rows) => {
    if (err) console.log("err: ", err);

    res.json(rows);
  });

  connection.end();
});

// サーバー起動
app.listen(8081, () => console.log("Example app listening on port 8081!"));

原因

コネクションは再利用できない。

変数connectionに対して、end()を呼び出し、丁寧に接続を切っています。
そこで再度connection()を呼び出せばまた接続できるのでは?という発想でした。

状況を再現してみる

実装した処理

同一のコネクションに対して、複数回接続を行う処理を作成してみました。

const mysql = require("mysql");

const connection = mysql.createConnection({
  // DB接続に関するオプション設定
});

for (let index = 0; index < 2; index++) {
  connection.connect();

  const query = connection.query("SELECT * FROM todo;");
  query.on("result", (row, index) => {
    console.log("--- result ---");
    console.log(row);
    console.log(index);
  });

  connection.end();
}

処理結果

nodeコマンドを使って、この処理を実行すると、以下のようなエラーになります。

Error: Cannot enqueue Handshake after invoking quit.

一度使ったんだから、ちゃんと破棄してくれってことですね。

適切な対処方法

何度もアクセス要求ができる接続窓口を作ってあげる。

実際のWebアプリケーションでは、同一のデータベースに対して何度も接続する処理が行われます。
規模にもよりますが、多人数で利用することを考えると、その数は膨大なものになります。

よって、以下の観点からコネクション確立処理は極力減らしたほうが良いです。

  • 本処理自体がオーバーヘッド(overhead)である
  • コネクション確立には時間がかかるため、ユーザーを都度待たせてしまう
  • コネクションの数だけDB側でメモリを確保する必要があるため、高負荷状態になりやすい

それらを実現するのがコネクションプール(Connection pool)です。

  • コネクションの状態を保持し、そのコネクションを使いまわすことができる
  • コネクション数に上限を設けることができる

コネクションプールの実装

MySQL - Pooling connections を参考に、コネクションプールを作成し、複数回のデータベース接続処理を行ってみます。

使用する関数はcreatePool()です。
実行するクエリが一つの場合、以下のような書き方でOKです。

const mysql = require("mysql");

const pool = mysql.createPool({
  // DB接続に関するオプション設定
});

pool.query("SELECT * FROM todo;", (error, results) => {
  if (error) throw error;
  console.log(results[0]);
});

プールが持つquery関数はpool.getConnection()connection.query()connection.release()を省略してくれます。

複数回のクエリ実行を行いたい場合などは以下です。

pool.getConnection((err, connection) => {
  if (err) throw err;

  connection.query("SELECT something FROM sometable", (error, results) => {
    connection.release();

    if (error) throw error;

    console.log(results[0])
  });
});

おわり

データベースに関する基礎的な知識が不足していたせいで、こんなところでハマってしまいました。
基礎的な部分を固めることができたと思うので、次の課題に取り組んでいきたいと思います。

あと、ライブラリのドキュメントに書いてあるとおりに実装していくと、コールバック地獄に陥りそうですね。
async/awaitなどを使ってもっとスマートに実装していきたいです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Node.js - Mysql「Error: Cannot enqueue Query after invoking quit.」の対処(Connection pool)

はじめに

本記事はデータベースにおけるコネクションプール(connection pool)について触れていくものです。

実際にハマったシチュエーションをもとに説明していきたいと思います。

  • 事象の詳細
  • 原因
  • 状況を再現してみる
  • 適切な対処方法
  • コネクションプールの実装

事象の詳細

Node.jsにて、Mysqlからデータを取得しようとしたとき、以下のエラーが発生した。

Error: Cannot enqueue Query after invoking quit.

どうやら2回目のGET:/api/todoを呼び出した時に必ず発生するようです。
その時のソースコードは以下です。

const express = require("express");
const mysql = require("mysql");
const app = express();

// データベースへのコネクションを生成
const connection = mysql.createConnection({
  // DB接続に関するオプション設定
});

connection.connect();

app.get("/api/todo", (req, res) => {
  const query = "SELECT * FROM todo;";

  connection.query(query, (err, rows) => {
    if (err) console.log("err: ", err);

    res.json(rows);
  });

  connection.end();
});

// サーバー起動
app.listen(8081, () => console.log("Example app listening on port 8081!"));

原因

コネクションは再利用できない。

変数connectionに対して、end()を呼び出し、丁寧に接続を切っています。
そこで再度connection()を呼び出せばまた接続できるのでは?という発想でした。

状況を再現してみる

実装した処理

同一のコネクションに対して、複数回接続を行う処理を作成してみました。

const mysql = require("mysql");

const connection = mysql.createConnection({
  // DB接続に関するオプション設定
});

for (let index = 0; index < 2; index++) {
  connection.connect();

  const query = connection.query("SELECT * FROM todo;");
  query.on("result", (row, index) => {
    console.log("--- result ---");
    console.log(row);
    console.log(index);
  });

  connection.end();
}

処理結果

nodeコマンドを使って、この処理を実行すると、以下のようなエラーになります。

Error: Cannot enqueue Handshake after invoking quit.

一度使ったんだから、ちゃんと破棄してくれってことですね。

適切な対処方法

何度もアクセス要求ができる接続窓口を作ってあげる。

実際のWebアプリケーションでは、同一のデータベースに対して何度も接続する処理が行われます。
規模にもよりますが、多人数で利用することを考えると、その数は膨大なものになります。

よって、以下の観点からコネクション確立処理は極力減らしたほうが良いです。

  • 本処理自体がオーバーヘッド(overhead)である
  • コネクション確立には時間がかかるため、ユーザーを都度待たせてしまう
  • コネクションの数だけDB側でメモリを確保する必要があるため、高負荷状態になりやすい

それらを実現するのがコネクションプール(connection pool)です。

  • コネクションの状態を保持し、そのコネクションを使いまわすことができる
  • コネクション数に上限を設けることができる

コネクションプールの実装

mysql - Pooling connections を参考に、コネクションプールを作成し、複数回のデータベース接続処理を行ってみます。

使用する関数はcreatePool()です。
実行するクエリが一つの場合、以下のような書き方でOKです。

const mysql = require("mysql");

const pool = mysql.createPool({
  // DB接続に関するオプション設定
});

pool.query("SELECT * FROM todo;", (error, results) => {
  if (error) throw error;
  console.log(results[0]);
});

プールが持つquery関数はpool.getConnection()connection.query()connection.release()を省略してくれます。

複数回のクエリ実行を行いたい場合などは以下です。

pool.getConnection((err, connection) => {
  if (err) throw err;

  connection.query("SELECT something FROM sometable", (error, results) => {
    connection.release();

    if (error) throw error;

    console.log(results[0])
  });
});

おわり

データベースに関する基礎的な知識が不足していたせいで、こんなところでハマってしまいました。
基礎的な部分を固めることができたと思うので、次の課題に取り組んでいきたいと思います。

あと、mysqlライブラリのドキュメントに書いてあるとおりに実装していくと、コールバック地獄に陥りそうですね。
async/awaitなどを使ってもっとスマートに実装していきたいです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Mysql2::Error at /auth/twitter/callback Incorrect string value: 【Rails】

Mysql2::Error at /auth/twitter/callback Incorrect string value:

MtSQLのエラーで、保存する値に絵文字:cake::cake::cake:が含まれていると起きる。

絵文字を扱うことが出来る文字コードはutf8mb4だがデータベースに設定されていた文字コードはutf8だった。それが原因。

MySQLに設定された文字コードを調べる

$ show variables like "chara%";

文字コードを変更する

MySQLのファイルはルートディレクトリの/etc/my.cnfにある。

$ vim my.cnf

以下のようにutf8utf8mb4に変更と追記。

[mysqld]
(省略)
character-set-server=utf8mb4

[client]
default-character-set=utf8mb4

DBの再起動

$ systemctl restart mysqld.service

RailsAppのdatabase.ymlを編集

default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: 5
  username: root
  password: <%= ENV['MYSQL2_PASSWORD'] %>
  host: localhost

encoding:の部分をutf8mb4に変更する。

データベースの作り直し

私は既存のデータベースの文字コードを変更したので、データベースも今一度作り直す必要があった。

$ rails db:drop
$ rails db:create
$ rails db:migrate

当然ではあるが、格納していたデータはすべて消える。マイグレーションファイルは残っているためrails db:migrateすればモデルは直ぐに作り直せる。

参考

https://babiy3104.hateblo.jp/entry/2014/02/13/000219

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Moodle 3.8 マニュアル - データベースのスキーマを確認する

原文

データベースのスキーマを確認する

もしあなたが Moodle をいくつかのバージョンに渡ってアップグレードしたのなら、ある変更があなたのデータベースとあなたが作成するあたらしい空のサイトで得るであろうバージョンの間のデータベースのテーブル定義("スキーマ")に忍び寄っている可能性(たぶん)があります。これはアップグレードスクリプトにおける小さなエラーあるいは見落としにより生じます。これらのほとんどの変更は害がないですが、いくつかは不思議な予期しない問題を引き起こすかもしれません。たとえば、デフォルトの値がフィールドに追加され、これがアップグレードスクリプトのコードに反映されなかった場合デフォルトを想定しているコードは期待通りには動作しないでしょう。

アップグレードをおこなった後(あるいは、もしあなたの問題がアップグレードが失敗するならば、前)に"本番"サイトと新しく作成したサイトのデータベースのスキーマを、全く同じコードのベースで比較することです。いくつかの方法がありますが、この記事は Unix コマンドラインを使用した簡単な方法で明らかにします。

  • アップグレードを完了する
  • 次のコマンドによりあなたの最近アップグレードしたサイトのデータベースのスキーマを生成する:
# MySQL
mysqldump --no-data -u root -p myproductiondb >production.schema
# PostgreSQL
pg_dump --schema-only -U postgres myproductiondb > production.schema
  • あなたの本番データベースのコードを新しい(ウェブでアクセス可能な)場所(これは重要です、そして同じバージョンでなければなりません)にコピーしてください。
  • インストールの指示により新しい、空のデータベースと moodledata の領域を新しいサイトに作成してください。
  • config.php ファイルを新しいデータベースとその場所に編集するかファイルを削除してインストールスクリプトを使用してください。
  • インストールスクリプトを走らせて config.php (もし該当するなら)とデータベース(admin とサイトの値は重要ではありません)を生成してください。
  • 次のコマンドによりあなたの新しいサイトのデータベースのスキーマを生成してください:
# MySQL
mysqldump --no-data -u root -p mycleandb >clean.schema
# PostgreSQL
pg_dump --schema-only -U postgres mycleandb > clean.schema
  • 変更を発見するために以下のコマンドを実行してください。
diff -u production.schema clean.schema >db.diff

今やあなたは差を確認するために db.diff ファイルをお気に入りのエディタで見ることができます。

注:上記は明らかに MySQL に当てはまります。その他のデータベースはスキーマだけをダンプする同様の機能を持っているようです。例えば PostgreSQL には pg_dump コマンドがあります。残りの議論はまだ当てはまります。

内容

1 diff ファイルを解釈する
1.1 手動で追いかけるには変更が多すぎますか?
2 心配すべきですか?
3 関連項目

1 diff ファイルを解釈する

まず、これが(実際の)一例です:

    --
    -- Table structure for table `mdl_backup_config`
       @@ -129,11 +93,11 @@
        DROP TABLE IF EXISTS `mdl_backup_config`;
        CREATE TABLE `mdl_backup_config` (
   -  `id` int(10) unsigned NOT NULL auto_increment,
   +  `id` bigint(10) unsigned NOT NULL auto_increment,
      `name` varchar(255) NOT NULL default ,
      `value` varchar(255) NOT NULL default ,
       PRIMARY KEY  (`id`),
   -  UNIQUE KEY `name` (`name`)
   +  UNIQUE KEY `mdl_backconf_nam_uix` (`name`)
        ) ENGINE=MyISAM AUTO_INCREMENT=15 DEFAULT CHARSET=utf8 COMMENT='To store backup configuration variables';

ファイルは多くの変更ブロックを持っているでしょう。- 行は削除された行を示し + の行は置き換えられた行(本番から新しいもの)を示しています。したがってここでは int が bigint に置き換えられ key name が変更されています。両者は、技術的にある点までアップグレードスクリプトにより変更されたはずですが、欠けているでしょう。このケースでは Moodle の動作には影響を及ぼすとは考えられません。

1.1 手動で追いかけるには変更が多すぎますか?

新旧の Moodle データベースを同期するために、あなたはデータベース管理プログラムを使用できます。
たとえば、MySQL データベースのための MySQL Workbench のように。

これはもし多くの変更がある場合には大変便利です。

Unix/Linux のコマンドラインを実行できるのなら Python script Schema Sync はあなたのデータベースをアップデートするための全てのコマンドを生成する素早く簡単な方法を提供します。

2 心配すべきですか?

フィールドのタイプ(それらが互換性がある限りにおいて)とキーネームの変更がよくあるの問題でしょうが問題を引き起こすものではないでしょう。見るべきものは欠けたフィールドとデフォルト値への変更についての行でしょう。

もしあなたが Moodle 2.0 にアップグレードしようとしているのならもっと心配する必要があります。アップグレードをスムーズにすすめるためにはこれらの問題を修正することはいい考えです。

3 関連項目

  • サイト管理->開発->XMLDBエディタ->インデックスをチェックする で欠けているインデックスリポート

カテゴリ:インストール
メインページ

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

MacでDocker+Rails+MySQL環境構築手順メモ

勉強するときに環境構築にかなりつまづいたので、その手順をメモしときたいと思います。

環境構築手順

前提として、rails開発用のディレクトリが用意されているものとします。

以下の手順に従ってファイル作成やコマンドを実行していけば問題なく手順は整うと思います。

Dockerfileの作成(以下をコピペ)

# rubyはお好みのバージョンで(ローカルのバージョンがいいと思います)

FROM ruby:2.6.3

# 必要なパッケージのインストール(基本的に必要になってくるものだと思うので削らないこと)

RUN apt-get update -qq && \

    apt-get install -y build-essential \

                       libpq-dev \        

                       nodejs           


# 作業ディレクトリの作成、設定

RUN mkdir /app_name

##作業ディレクトリ名をAPP_ROOTに割り当てて、以下$APP_ROOTで参照

ENV APP_ROOT /app_name

WORKDIR $APP_ROOT


# ホスト側(ローカル)のGemfileを追加する

ADD ./Gemfile $APP_ROOT/Gemfile

ADD ./Gemfile.lock $APP_ROOT/Gemfile.lock


# Gemfileのbundle install

RUN bundle install

ADD . $APP_ROOT

Gemfileの作成(以下をコピペ)

source 'https://rubygems.org'

#好きなバージョンを指定

gem 'rails', '5.2.2'

空のGemfile.lockの作成

何も書かなくていいです。

docker-compose.ymlを作成(以下をコピペ)

docker-compose.yml
version: '3'

services:
  db:
    image: mysql:8.0.17
    command: mysqld --default-authentication-plugin=mysql_native_password
    volumes:
      - ./db/mysql_data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: root
    ports:
      - "4306:3306"

  web:
    build: .
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    volumes:
      - .:/app_name
    ports:
      - "3000:3000"
    links:
      - db

ターミナルでrails newを実行

$ docker-compose run web rails new . --force --database=mysql --skip-bundle

上のコマンドを打ってしばらく待つ

database.ymlを修正(一度全て消してから以下をコピペ)

database.yml
default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: <%= ENV.fetch("MYSQL_USERNAME", "root") %>
  password: <%= ENV.fetch("MYSQL_PASSWORD", "root") %>
  host: <%= ENV.fetch("MYSQL_HOST", "db") %>

development:
  <<: *default
  database: app_name_development

test:
  <<: *default
  database: app_name_test

production:
  <<: *default
  database: app_name_production
  username: app_name
  password: <%= ENV['APP_NAME_DATABASE_PASSWORD'] %>

ターミナルでDockerを起動

docker-compose build

しばらく待つ。できたら以下を実行。

docker-compose up

DB作成

別のターミナルを開いて以下を実行

docker-compose run web rails db:create

ブラウザでlocalhost:3000にアクセス

サーバーが起動してたらおk。

サーバーを止める

docker-compose down

サーバーを再起動

docker-compose up

まとめ

これでrailsアプリ作成の準備が整うはずです。
環境構築は完全に初見ごろしだと思うので誰かの助けに慣れたら嬉しいです。
また、何かおかしい点とかあれば言って頂けるとありがたいです。

お付き合い頂きありがとうございました。

参考サイト

https://qiita.com/azul915/items/5b7063cbc80192343fc0

https://qiita.com/take18k_tech/items/ada21511c551bcfe0b8c

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rails6 テーブル作成時のmigrateでエラーが出た話

目的

  • テーブル作成を行なった際にmigrateでエラーが出た話をまとめる

エラー内容

  • 下記コマンドでモデルファイルを作成した。

    $ rails g model user name:string
    
  • その後、下記コマンドでmigreteを実行した。

    $ rails db:migrate
    
  • 下記のエラーが発生した

    [14:50:10]MacBook-miriwo~/workspace/study/rails/tropical_fish_sns_of_rails$ rails db:migrate
    == 20200206055010 CreateUsers: migrating ======================================
    -- create_table(:users)
    rails aborted!
    StandardError: An error has occurred, all later migrations canceled:
    
    Mysql2::Error: Table 'users' already exists
    /Users/admin/workspace/study/rails/tropical_fish_sns_of_rails/db/migrate/20200206055010_create_users.rb:3:in `change'
    /Users/admin/workspace/study/rails/tropical_fish_sns_of_rails/bin/rails:9:in `<top (required)>'
    /Users/admin/workspace/study/rails/tropical_fish_sns_of_rails/bin/spring:15:in `<top (required)>'
    bin/rails:3:in `load'
    bin/rails:3:in `<main>'
    
    Caused by:
    ActiveRecord::StatementInvalid: Mysql2::Error: Table 'users' already exists
    /Users/admin/workspace/study/rails/tropical_fish_sns_of_rails/db/migrate/20200206055010_create_users.rb:3:in `change'
    /Users/admin/workspace/study/rails/tropical_fish_sns_of_rails/bin/rails:9:in `<top (required)>'
    /Users/admin/workspace/study/rails/tropical_fish_sns_of_rails/bin/spring:15:in `<top (required)>'
    bin/rails:3:in `load'
    bin/rails:3:in `<main>'
    
    Caused by:
    Mysql2::Error: Table 'users' already exists
    /Users/admin/workspace/study/rails/tropical_fish_sns_of_rails/db/migrate/20200206055010_create_users.rb:3:in `change'
    /Users/admin/workspace/study/rails/tropical_fish_sns_of_rails/bin/rails:9:in `<top (required)>'
    /Users/admin/workspace/study/rails/tropical_fish_sns_of_rails/bin/spring:15:in `<top (required)>'
    bin/rails:3:in `load'
    bin/rails:3:in `<main>'
    Tasks: TOP => db:migrate
    (See full trace by running task with --trace)
    

原因調査

  • 下記コマンドを実行して現在のmigrateのステータスを確認した。

    $ rails db:migrate:status
    
  • 以前にmigrateを実施した際のmigrationファイルのが無いことが判明した。

    [14:52:57]MacBook- 
    miriwo~/workspace/study/rails/tropical_fish_sns_of_rails/db/migrate$ rails db:migrate:status
    
    database: tropical_fish_sns_development
    
     Status   Migration ID    Migration Name
    --------------------------------------------------
       up     20200206025324  ********** NO FILE **********
       up     20200206025916  ********** NO FILE **********
      down    20200206055010  Create users
    

解決法

  • 下記コマンドを実行してDBのリセットを行なった。

    $ rails db:migrate:reset
    
  • DBの状態を確認した。

    [14:54:33]MacBook-miriwo~/workspace/study/rails/tropical_fish_sns_of_rails/db/migrate$ rake 
    db:migrate:status
    (in /Users/admin/workspace/study/rails/tropical_fish_sns_of_rails)
    
    database: tropical_fish_sns_development
    
     Status   Migration ID    Migration Name
    --------------------------------------------------
       up     20200206055010  Create users
    
  • 正常に反映されていることをがわかった。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む