Active recordしか触れてこなかったのでmysqlの基礎からTransactionまで勉強しようと思った。

#環境
* sequel
* 遊びなれたmysqlDB
* ネットに広がるありがたい情報をみるためのChrome
* Vagrant
* Red Hat Linux
* mysql5.1.73
* Rails5

#Mysqlとは
* データベース管理システム
* データベース本体ではない
* 複数のストレージエンジンをテーブルごとに設定可能
* 言語、フレームワークに依存しない、独立したMysqlサーバーで動く


mysql自体はデータベースではなく、データベースを管理しているものであり、
実際にデータベースに値や更新処理、削除処理を行っているのはストレージエンジンというものらしいです。

またストレージエンジンをテーブルごとに設定することが可能なため、
テーブル用途別にストレージエンジンを変更するということも可能のようです。


##ストレージエンジンとは
* データベースにデータを書き込むためのもの
* CREATE TABLE文を打つときに指定できる
* 様々な種類がある（以下面白いと思ったやつだけ抜粋）
    * MyISAM ：デフォルトで設定されており、高速であるがTransaction処理ができない
    * InnoDB ：外部キー制約、Transaction処理に対応。
    * MERGE  :大容量データを扱う際に複数テーブルをまとめてくれるので便利
    * ARCHIVE:データを圧縮して保存、selectとinsertのみ可能
    * CSV    ：データがカンマ区切りで保存される


### ストレージエンジンを指定してテーブルを作成する方法

```mysql
-- ENGINEと指定するとそのテーブルのみINNODBで作成することが出来る。
CREATE TABLE user (age INT) ENGINE = INNODB;
```

参考サイト
<a href="http://shindolog.hatenablog.com/entry/2015/04/01/185703">MySQLの「InnoDB」と「MyISAM」についての易しめな違い</a>
<a href="http://pb-times.jp/P_51e7a71f997de">MySQLで使用できるストレートエンジンのまとめ</a>


##エンジンが書き込むためのストレージファイルとは
* MYD形式：実データ保存用ファイル
* MYI形式：テーブルごとのインデックスを保存するためのファイル

このような２つの種類のファイルから構成されており、このファイルの場所はmysqlのmy.cnfに記載されている。

```bash
sudo vi /etc/mysql/my.cnf
```

実際にファイルを開くとこのような記述があり

```
[mysqld]
datadir=/var/lib/mysql
```

var/lib/mysqlのディレクトリにデータを保存しているらしいということがわかる。

```zsh:とりあえず行ってみる
su
cd /var/lib/mysql
ls


hogehoge.frm
huga.frm 
hoge.frm
hoge.idb
```
テーブル名.frmというファイルにストレージエンジンがテーブルの構造などを実際に書き込んでいるのだとわかった。

```zsh:ちなみに開いてもデータ見れなかった
^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^
^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^
^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^
^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@
```

その他設定ファイル

* .frmファイル：テーブル自体の情報を記録するファイル
* .idbファイル：テーブルごとにインデックスを記録するファイル
* .optファイル：データベース自体の文字セットなどを保存するファイル


参考サイト
<a href="http://d.hatena.ne.jp/graySpace/20140911/1410450256">MySQLがデータを保管する場所　～　データディレクトリ</a>



##Mysqlの動作の流れおさらい
1. Client側からデータ更新リクエストが飛んでくる
2. リクエストの内容を読み、適正なアクセスか検証。
3. SQL文の構文が正しいか構文解析を行う。
4. ストレージエンジンへ書き込み処理命令を出す。
5. ストレージファイルが書き換わる


![image](https://qiita-image-store.s3.amazonaws.com/0/69647/ed014f17-7aea-0a96-a1c5-a9854cb5bc75.png)
引用：http://shindolog.hatenablog.com/entry/2015/04/01/185703



#MysqlTransactionとは
Mysqlを利用する際にテーブルのストレージエンジンがInnoDB（Transactionに対応しているもの）の時に利用可能

トランザクションとは ：特定の処理のまとまりの事

MysqlTransactionとは：処理の塊を実行し、また不具合が発生した際にはいつでもROLLBACKすることができる機能


#基礎
##安全にDBを触るためにROLLBACKを使って見る
* start transaction
* begin (start transactionのエイリアス)
* rollback
* commit

Mysqlでは公式ドキュメントにもありますがUpdate処理を叩いた瞬間即DBに書き込みを行ってくれます。
>テーブルを更新 (変更) するステートメントを実行するとすぐに、MySQL によってその更新がディスクに格納されて永続的になります。この変更はロールバックできません。


start transactionをSQLを叩く前に記述しておくことで、この自動更新を止めることが可能になり、
commitを実行した時点で初めて保存され、
rollbackを実行することでその処理を無視するといった動作が可能になります。



* updateでデータを更新
* select文で変更を確認
* 間違ってたらrollbackして再度update
* 正しかったらにcommit(保存）

という流れで作業できるようになります。

```sql:rollback実践
start transaction; --自動更新をOFFにする

update orders set delivery_way_id=9999 where id=1;
select delivery_way_id from orders where id=1;
-- delivery_way_id : 9999
rollback;
select delivery_way_id from orders where id=1;
-- delivery_way_id : NULL
```
rollbackを行うとstart transactionを実行した時の状態へ戻る。

```sql:commitで変更を保存してみる
start transaction;
select delivery_way_id from orders where id=1;
-- delivery_way_id :NULL
update orders set delivery_way_id=9999 where id=1;
select delivery_way_id from orders where id=1;
-- delivery_way_id :9999
commit;
rollback;
select delivery_way_id from orders where id=1;
-- delivery_way_id :9999
```
commitを行うことで変更が確定され、以降rollbackを行っても何も起きない。

##明示的に自動commit機能をOFFにする
* SET autocommit  
* SELECT @@autocommit

```sql:明示的にrollbackを切る
SELECT @@autocommit; --現在の設定を確認
SET autocommit=0;    --自動更新を切る
```

参考サイト
<a href="https://dev.mysql.com/doc/refman/5.6/ja/commit.html">13.3.1 START TRANSACTION、COMMIT、および ROLLBACK 構文</a>