- 投稿日:2020-01-21T18:29:40+09:00
MySQLのtimestampのデータが勝手に更新されてる
現象
> update users set status = 9, modified = now() where id = 1;上記を叩いてきちんと更新されているか確認してみると、
modified
だけではなくcreated
まで更新されてしまった。。-- 元々のデータ > select * from users; *************************** 1. row *************************** user_id: 1 status: 1 created: 2015-05-26 04:01:21 modified: 2018-03-03 05:54:54 -- 更新したデータ > select * from users; *************************** 1. row *************************** user_id: 1 status: 9 created: 2020-01-21 00:00:00 -- あれ、こっちまで更新されてる。。 modified: 2020-01-21 00:00:00原因
結論、
created
がCURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
で設定されているからでした。> show create table users\G *************************** 1. row *************************** Table: users Create Table: CREATE TABLE `users` ( `id` int(11) NOT NULL AUTO_INCREMENT, `status` tinyint(4) NOT NULL, `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8
CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
があるとupdate文をかけた時に自動更新されるような設定なため、勝手にcreated
も更新されていたようです。
timestamp型は、デフォルトでCURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
が付いてしまうらしい?無効化
下のsqlを叩いて自動更新を無効化しました。
> alter table users modify created timestamp default '1970-01-01 00:00:01'
- 投稿日:2020-01-21T17:35:12+09:00
Redmine のmysqlでAccess Deniedにはまった記録(低次元ミスでとても恥ずかしいが人柱で)
ちまたのWin Server 2008サポート切れに伴いWin Server 2016へ最新版Bitnami redmine 4.1をインストールし移行・・のためここを参考にmysqlのテーブル削除をトライするがmysqlのログインで弾かれる。
>mysql -u root -p
>Access denied for user 'root'@'localhost' (using password: YES)ググると同問題遭遇者が累々多数。
ほとんどがrootのパスワード再設定で解決のよう。
でもusing password: YESだからパスワード問題でないのでは?意図的にパスワード外すとusing password: NOって返るし。YESってことはパスワード問題でない?
でもネットにはAccess deniedでパスワード再設定以外は参考例なく1日半、調べてはトライの繰り返しで徒労に過ぎ。まずは旧環境でダンプ取れるのがユーザがbitnamiなので-u bitnamiでやるが同じ
TCP port番号を明記してやると通るような事例もあり --port 3306明記でやるが同じ
環境変数でINSTALLDIRが必要の事例ありなかったので作成するが同じ
-D付きでDBをbitnamiと明示してやると・・・でも同じ
ということで結局Bitnami redmineをアンインコ、再インスコして初期パスワードをセットすると問題なくログインできた
結局恥ずかしい理由は・・
初期ユーザ名設定をadminとパスワードセットしRedmineにadminで初回サインイン時にパスワード変更となりその変更したパスワードでmyselへログインしようとした、でrootのパスワード誤りが原因でした
Redmineインストール時のパスワード必ずメモで残すべし、それがmysqlのパスワードなので・・・
あー恥ずかしい
- 投稿日:2020-01-21T12:29:38+09:00
MySQL/PostgreSQLバージョン別利用できるプロダクト
MySQLのDBエンジンのバージョンで、Alibaba Cloudの使えるマネージドデータベースプロダクトが変わってくるのでリストにしてみたよ。(Alibaba Cloud International ベース)
コンソールベースで確認したのでドキュメントよりも新しいです。(2020年1月21日現在)
Engine RDS Basic RDS HA RDS Enterprise POLARDB MySQL8.0 ○ ○ ○ ○ MySQL5.7 ○ ○ ○ × MySQL5.6 × ○ ○ ○ MySQL5.5 × ○ × ×
Engine RDS Basic RDS HA POLARDB PostgreSQL 12 ○ × × PostgreSQL 11 ○ ○ ○ PostgreSQL 10 ○ ○ × PostgreSQL 9.4 × ○ × ApsaraDB for RDS edition overview
https://www.alibabacloud.com/help/doc-detail/55665.htm
(2020年1月21日現在最新に追いついてない様子)ApsaraDB for POLARDB
https://www.alibabacloud.com/ja/products/apsaradb-for-polardb
- 投稿日:2020-01-21T08:00:05+09:00
Rails6の複数DBを試してみた
Rails6からActive Record で複数のデータベースが利用できるようになった。
この機能はモノリシックなシステムをマイクロサービス化していく過程でも有効で、アプリケーションをロジック・データを順番に分けていく時に活用できる。(参考: IBM Developerサイト / マイクロサービス、SOA、API:味方か敵か / 図5.モノリシック・アプリケーションからマイクロサービスへ)
今回はベースとなるアプリケーション(Dogs)を作成し、そのデータを別の新しいアプリケーション(Cats)から参照して処理するケースを仮定して試してみる。
環境
$ ruby -v ruby 2.6.5p114 (2019-10-01 revision 67812) [x86_64-darwin19]$ gem -v 3.0.6$ rails -v Rails 6.0.2.1$ mysql -u root -e 'select version();' +-----------+ | version() | +-----------+ | 8.0.18 | +-----------+ベースアプリケーション(Dogs)の作成
まずRailsアプリケーションを作成し、プロジェクトルートに移動する
$ rails new -T -d mysql dogs $ cd dogs次に何かデータを入れたいので、チワワ(Chihuahua)のモデルを作成する
$ bundle exec rails g model Chihuahua name:string Running via Spring preloader in process 22237 invoke active_record create db/migrate/20200119010243_create_chihuahuas.rb create app/models/chihuahua.rb1つだとつまらないので、プードル(Poodle)のモデルも作成する
$ bundle exec rails g model Poodle name:string Running via Spring preloader in process 22245 invoke active_record create db/migrate/20200119010313_create_poodles.rb create app/models/poodle.rbDBを作成・マイグレーションする
$ bundle exec rake db:create db:migrate Created database 'dogs_development' Created database 'dogs_test' == 20200119010243 CreateChihuahuas: migrating ================================= -- create_table(:chihuahuas) -> 0.0098s == 20200119010243 CreateChihuahuas: migrated (0.0099s) ======================== == 20200119010313 CreatePoodles: migrating ==================================== -- create_table(:poodles) -> 0.0116s == 20200119010313 CreatePoodles: migrated (0.0117s) ===========================チワワとプードルに各々データを登録する
$ bundle exec rails r 'Chihuahua.create!(name:"ちくわ")' $ bundle exec rails r 'Chihuahua.create!(name:"わんこ")' $ bundle exec rails r 'Poodle.create!(name:"しらたま")'データが登録できたか確認する。
$ bundle exec rails r 'p Chihuahua.all' Running via Spring preloader in process 22407 #<ActiveRecord::Relation [#<Chihuahua id: 1, name: "ちくわ", created_at: "2020-01-19 01:11:49", updated_at: "2020-01-19 01:11:49">, #<Chihuahua id: 2, name: "わんこ", created_at: "2020-01-19 01:11:50", updated_at: "2020-01-19 01:11:50">]>$ bundle exec rails r 'p Poodle.all' Running via Spring preloader in process 22409 #<ActiveRecord::Relation [#<Poodle id: 1, name: "しらたま", created_at: "2020-01-19 01:11:51", updated_at: "2020-01-19 01:11:51">]>チワワに2件、プードルに1件登録されていることを確認する
新しいアプリケーション(Cats)の作成
別の新しいアプリケーション(Cats)を隣のパスに作成する
$ cd ../ $ rails new -T -d mysql cats $ cd catsそこにも同様にデータを入れたいので、アメリカンショートヘア(AmericanShortHair)のモデルを作成する
$ bundle exec rails g model AmericanShortHair name:string Running via Spring preloader in process 22466 invoke active_record create db/migrate/20200119011624_create_american_short_hairs.rb create app/models/american_short_hair.rbDBを作成・マイグレーションする
$ bundle exec rake db:create db:migrate Running via Spring preloader in process 22466 invoke active_record create db/migrate/20200119011624_create_american_short_hairs.rb create app/models/american_short_hair.rb Created database 'cats_development' Created database 'cats_test' == 20200119011624 CreateAmericanShortHairs: migrating ========================= -- create_table(:american_short_hairs) -> 0.0097s == 20200119011624 CreateAmericanShortHairs: migrated (0.0098s) ================アメリカンショートヘアに2件のデータを登録する
$ bundle exec rails r 'p AmericanShortHair.create!(name:"とら")' Running via Spring preloader in process 22487 #<AmericanShortHair id: 1, name: "とら", created_at: "2020-01-19 01:16:55", updated_at: "2020-01-19 01:16:55"> $ bundle exec rails r 'p AmericanShortHair.create!(name:"たま")' Running via Spring preloader in process 22489 #<AmericanShortHair id: 2, name: "たま", created_at: "2020-01-19 01:16:56", updated_at: "2020-01-19 01:16:56">正常に登録できていることを確認する
$ bundle exec rails r 'p AmericanShortHair.all' Running via Spring preloader in process 22492 #<ActiveRecord::Relation [#<AmericanShortHair id: 1, name: "とら", created_at: "2020-01-19 01:16:55", updated_at: "2020-01-19 01:16:55">, #<AmericanShortHair id: 2, name: "たま", created_at: "2020-01-19 01:16:56", updated_at: "2020-01-19 01:16:56">]>新しいCatsアプリケーションからベースアプリケーション(Dogs)のデータを参照する
以降はRailsガイドを参考に進める。
まずは
database.yml
をバックアップし、プレーンな設定のみ入れておく$ mv config/database.yml{,.org} $ cat <<'EOT' > config/database.yml default: &default adapter: mysql2 encoding: utf8mb4 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: root password: host: localhost development: <<: *default database: cats_development EOTこの状態でアメリカンショートヘアに登録されている2件のデータが表示されている
$ bundle exec rails r 'p AmericanShortHair.all' Running via Spring preloader in process 22626 #<ActiveRecord::Relation [#<AmericanShortHair id: 1, name: "とら", created_at: "2020-01-19 01:16:55", updated_at: "2020-01-19 01:16:55">, #<AmericanShortHair id: 2, name: "たま", created_at: "2020-01-19 01:16:56", updated_at: "2020-01-19 01:16:56">]>Catsのデータベースを
primary
として設定する$ cat <<'EOT' > config/database.yml default: &default adapter: mysql2 encoding: utf8mb4 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: root password: host: localhost development: primary: <<: *default database: cats_development EOTこの状態でもちゃんとアメリカンショートヘアに登録されている2件のデータが表示されている
$ bundle exec rails r 'p AmericanShortHair.all' Running via Spring preloader in process 22634 #<ActiveRecord::Relation [#<AmericanShortHair id: 1, name: "とら", created_at: "2020-01-19 01:16:55", updated_at: "2020-01-19 01:16:55">, #<AmericanShortHair id: 2, name: "たま", created_at: "2020-01-19 01:16:56", updated_at: "2020-01-19 01:16:56">]>新しいCatsアプリケーションにDogsのモデルをコピーする
$ cp -rf ../dogs/app/models app/models/dogsDogsのモデルはCatsとは別のデータベースを参照するので、基底クラスをApplicationRecordを継承した別クラスに置き換える
$ rm -rf app/models/dogs/application_record.rb app/models/dogs/concerns $ cat <<'EOT' > app/models/dogs/base.rb class Dogs::Base < ApplicationRecord self.abstract_class = true connects_to database: { writing: :dogs } end EOT各モデルクラスを前項で作成したDogs::Baseを継承する形に変更し、Dogsモジュール配下に入れる
$ find app/models/dogs -type f -name '*.rb' -print0 | xargs -0 sed -i.bak -e "s/^\(class\) \([^ ]*\) <.*/\1 Dogs::\2 < Dogs::Base/g" $ find app/models/dogs -type f -name '*.bak' -print0 | xargs -0 rm新しいCatsアプリケーションにDogsのマイグレーションファイルをコピーする
$ cp -rf ../dogs/db/migrate db/dogs_migrate最後に
database.yml
にdogsのデータベースを追加する$ cat <<'EOT' > config/database.yml default: &default adapter: mysql2 encoding: utf8mb4 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: root password: host: localhost development: primary: <<: *default database: cats_development dogs: <<: *default database: dogs_development EOTこれで一通り設定は完了。
以降でデータが取得できることを確認していく。もともとCatsアプリケーションにあったアメリカンショートヘアのデータが取得できている
$ bundle exec rails r 'p AmericanShortHair.all' Running via Spring preloader in process 22723 #<ActiveRecord::Relation [#<AmericanShortHair id: 1, name: "とら", created_at: "2020-01-19 01:16:55", updated_at: "2020-01-19 01:16:55">, #<AmericanShortHair id: 2, name: "たま", created_at: "2020-01-19 01:16:56", updated_at: "2020-01-19 01:16:56">]>加えて新しいCatsアプリケーションからDogsの各データが取得できるようになっている
$ bundle exec rails r 'p Dogs::Chihuahua.all' Running via Spring preloader in process 23116 #<ActiveRecord::Relation [#<Dogs::Chihuahua id: 1, name: "ちくわ", created_at: "2020-01-19 01:11:49", updated_at: "2020-01-19 01:11:49">, #<Dogs::Chihuahua id: 2, name: "わんこ", created_at: "2020-01-19 01:11:50", updated_at: "2020-01-19 01:11:50">]>$ bundle exec rails r 'p Dogs::Poodle.all' Running via Spring preloader in process 23118 #<ActiveRecord::Relation [#<Dogs::Poodle id: 1, name: "しらたま", created_at: "2020-01-19 01:11:51", updated_at: "2020-01-19 01:11:51">]>これでベースとなるアプリケーション(Dogs)のデータを、別の新しいアプリケーション(Cats)から参照することができた。
所感
これでデータストアを共通化した状態でロジックだけ新しいアプリに移すことが可能になるが、この実装ではリスクが高いと考える。
例えば、複数のアプリケーション1つのデータストアを触ることで、本来意図しないデータベースの更新が発生する(コールバック系の処理とか危なそう)であったり、参照しているモデルやマイグレーションファイルに更新が起きたとき、意図しない不整合が起きる(参照してる側が知らないうちにモデルやDBスキーマが変わってたとか・・・)であったりと言ったことが起きると考えられる。
この仕組みを導入するからには、最終的にはきっちりとしたマイクロサービスにしてデータの受け渡しはちゃんとAPI経由で行う仕切りにするか、モデルだけ別ライブラリに切り出してJavaのDAOクラス的な物として使うか……意外と後者側の方が使い勝手がいいかもしれない。
- 投稿日:2020-01-21T01:53:03+09:00
docker-composeでMySQLのrootパスワードを忘れた場合
docker-composeでMySQLのrootパスワードを忘れた場合に自分が行った対処のメモです。
権限なしでmysqlコンテナを起動する
パスワードをリセットするためには権限テーブルを非参照で起動する必要があります。下記のオプションをdocker-compose.ymlに追加。
command: mysqld --skip-grant-tables --skip-networkingdocker-compose.ymlmysql: build: context: ./mysql args: - MYSQL_VERSION=${MYSQL_VERSION} environment: - MYSQL_DATABASE=${MYSQL_DATABASE} - MYSQL_USER=${MYSQL_USER} - MYSQL_PASSWORD=${MYSQL_PASSWORD} - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD} - TZ=${WORKSPACE_TIMEZONE} command: mysqld --skip-grant-tables --skip-networking volumes: - ${DATA_PATH_HOST}/mysql:/var/lib/mysql - ${MYSQL_ENTRYPOINT_INITDB}:/docker-entrypoint-initdb.d ports: - "${MYSQL_PORT}:3306" networks: - backendコンテナを再起動し、変更を反映させます。
>docker-compose stop mysql >docker-compose up -d mysqlパスワード変更
mysqlコンテナに入る >docker-compose exec mysql bash パスワードなしでログインできるようになる mysql> mysql -u root ユーザ名、ホスト名を確認 mysql> use mysql; mysql> SELECT user, host FROM user; パスワードを変更 mysql> SET PASSWORD FOR ユーザ名@ホスト名 = 'パスワード';最後にcommand: mysqld --skip-grant-tables --skip-networkingをdocker-compose.ymlから削除し、再起動すれば完了。