CyberX:エンジニアブログ -2ページ目

pt-online-schema-changeについて

CyberXのengineer、K.Mです。

MySQLのTableにカラムやインデックスの追加、修正する際にメンテナンスを入れることがあると思います。
AlterTable実行中は書き込みができないため、普通はメンテナンスを入れる必要があるのですが、
pt-online-schema-changeを使うとAlterTable実行中でも書き込みが可能になります。
本日はこのツールを紹介します。

pt-online-schema-changeはPercona Toolkitの1機能です。
Percona ToolkitはMaatkitとAspersaが元になっています。

実は似たツールが複数あり、米Facebook、MySQL向けのオンラインスキーマ変更ユーティリティ「OSC(Online Schema Change for MySQL)」もその一つです。

http://bazaar.launchpad.net/~mysqlatfacebook/mysqlatfacebook/tools/files
http://www.facebook.com/notes/mysql-at-facebook/online-schema-change-for-mysql/430801045932

pt-online-schema-changeはこのツールを改良したものだそうです。

なお、AlterTable実行時の処理の流れは以下の通りとなります。※InnoDBの場合
・テーブルをTL_WRITE_ALLOW_READロックする。(他のセッションからのREADを許可し、WRITEをブロックする。)
・新しいテーブル定義を使って空のテンポラリテーブルを作成する。
・古いテーブルから新しいテーブルへデータをコピーする。
・テーブルの名前を付け替えて、新しいテーブルを古いテーブルと同じ名前にする。古いテーブルは破棄する。
・新しいテーブルへブロックしていたWRITEをリダイレクトする。
http://nippondanji.blogspot.jp/2009/05/alter-table.html
ALTER TABLEも内部的に作業用テーブルへのINSERT処理を実行するのですね。


以下はpt-online-schema-changeを実行した際のsqlログとなります。
Connect root@localhost on db_name
・オートコミット機能を有効にする
Query set autocommit=1

Query SELECT @@SQL_MODE

・SHOW CREATE TABLE と SHOW CREATE DATABASEでテーブル名とカラム名は引用符で囲う
Query SET @@SQL_QUOTE_SHOW_CREATE = 1/*!40101, @@SQL_MODE='NO_AUTO_VALUE_ON_ZERO'*/

・待機状態(アイドル状態)になって○秒経過したら接続を切る。
Query SET wait_timeout=10000

・hostname, server_id取得
Query SELECT @@hostname, @@server_id

・行ロック待ちの秒数をセッション単位で指定
Query SET SESSION innodb_lock_wait_timeout=1

・versionなど取得
Query SHOW VARIABLES LIKE 'version%'

・使用可能なエンジン一覧取得
Query SHOW ENGINES

・innodbのversion取得
Query SHOW VARIABLES LIKE 'innodb_version'

・server_id取得
Query SELECT @@SERVER_ID

・accountに付与されている権限取得
Query SHOW GRANTS FOR CURRENT_USER()

・processlist確認
Query SHOW PROCESSLIST

・複製スレーブのリスト取得
Query SHOW SLAVE HOSTS

・スリープ状態になっていないスレッドの数 (1回目)
Query SHOW GLOBAL STATUS LIKE 'Threads_running'

・スリープ状態になっていないスレッドの数 (2回目)
Query SHOW GLOBAL STATUS LIKE 'Threads_running'

・指定したTableの存在確認
Query SHOW TABLES FROM `db_name` LIKE 'test\_table'

・指定したTableのトリガ一覧取得
Query SHOW TRIGGERS FROM `db_name` LIKE 'test\_table’
Query /*!40101 SET @OLD_SQL_MODE := @@SQL_MODE, @@SQL_MODE := REPLACE(REPLACE(@@SQL_MODE, 'ANSI_QUOTES', ''), ',,', ','), @OLD_QUOTE := @@SQL_QUOTE_SHOW_CREATE, @@SQL_QUOTE_SHOW_CREATE := 1 */

・DB選択
Query USE `db_name`

・変更対象Tableのcreate文取得
Query SHOW CREATE TABLE `db_name`.`table_name`
Query /*!40101 SET @@SQL_MODE := @OLD_SQL_MODE, @@SQL_QUOTE_SHOW_CREATE := @OLD_QUOTE */

・select
Query EXPLAIN SELECT * FROM `db_name`.`table_name` WHERE 1=1

・外部キーを張っているテーブルを調査
Query SELECT table_schema, table_name FROM information_schema.key_column_usage WHERE constraint_schema='db_name' AND referenced_table_name='table_name’
Query /*!40101 SET @OLD_SQL_MODE := @@SQL_MODE, @@SQL_MODE := REPLACE(REPLACE(@@SQL_MODE, 'ANSI_QUOTES', ''), ',,', ','), @OLD_QUOTE := @@SQL_QUOTE_SHOW_CREATE, @@SQL_QUOTE_SHOW_CREATE := 1 */

・DB選択(2回目)
Query USE `db_name`

・変更対象Tableのcreate文取得
Query SHOW CREATE TABLE `db_name`.`table_name`
Query /*!40101 SET @@SQL_MODE := @OLD_SQL_MODE, @@SQL_QUOTE_SHOW_CREATE := @OLD_QUOTE */

Query CREATE TABLE `db_name`.`_table_name_new` (
`id` int(11) NOT NULL DEFAULT '0',
`foo` int(11) DEFAULT NULL COMMENT 'testdao',
`category_id` int(11) DEFAULT NULL,
`title` varchar(64) DEFAULT NULL,
`author_name` varchar(32) DEFAULT NULL,
`detail` text,
`price` int(11) DEFAULT NULL,
`image` varchar(64) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `foo` (`foo`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1

・新しいTableにカラム追加
Query ALTER TABLE `db_name`.`_table_name_new` ADD foo2 INT( 11 ) NULL COMMENT 'testdao2' AFTER foo
Query /*!40101 SET @OLD_SQL_MODE := @@SQL_MODE, @@SQL_MODE := REPLACE(REPLACE(@@SQL_MODE, 'ANSI_QUOTES', ''), ',,', ','), @OLD_QUOTE := @@SQL_QUOTE_SHOW_CREATE, @@SQL_QUOTE_SHOW_CREATE := 1 */

・DB選択(3回目)
Query USE `db_name`

・移行用Tableのcreate文参照 (table生成確認)
Query SHOW CREATE TABLE `db_name`.`_table_name_new`

・SQL_MODE設定
Query /*!40101 SET @@SQL_MODE := @OLD_SQL_MODE, @@SQL_QUOTE_SHOW_CREATE := @OLD_QUOTE */

・deleteのtrigger/レコードの削除中にすべてのエラーを無視
Query CREATE TRIGGER `pt_osc_db_name_table_name_del` AFTER DELETE ON `db_name`.`table_name` FOR EACH ROW DELETE IGNORE FROM `db_name`.`_table_name_new` WHERE `db_name`.`_table_name_new`.`id` <=> OLD.`id`

・updateのtrigger
Query CREATE TRIGGER `pt_osc_db_name_table_name_upd` AFTER UPDATE ON `db_name`.`table_name` FOR EACH ROW REPLACE INTO `db_name`.`_table_name_new` (`id`, `foo`, `category_id`, `title`, `author_name`, `detail`, `price`, `image`) VALUES (NEW.`id`, NEW.`foo`, NEW.`category_id`, NEW.`title`, NEW.`author_name`, NEW.`detail`, NEW.`price`, NEW.`image`)

・insertのtrigger
Query CREATE TRIGGER `pt_osc_db_name_table_name_ins` AFTER INSERT ON `db_name`.`table_name` FOR EACH ROW REPLACE INTO `db_name`.`_table_name_new` (`id`, `foo`, `category_id`, `title`, `author_name`, `detail`, `price`, `image`) VALUES (NEW.`id`, NEW.`foo`, NEW.`category_id`, NEW.`title`, NEW.`author_name`, NEW.`detail`, NEW.`price`, NEW.`image`)

・explain
Query EXPLAIN SELECT * FROM `db_name`.`table_name` WHERE 1=1

・explain
Query EXPLAIN SELECT `id`, `foo`, `category_id`, `title`, `author_name`, `detail`, `price`, `image` FROM `db_name`.`table_name` /*explain pt-online-schema-change 6557 copy table*/

・旧Tableから新Tableに優先度低めでInsert & 実行中に起きたエラーは警告扱い
Query INSERT LOW_PRIORITY IGNORE INTO `db_name`.`_table_name_new` (`id`, `foo`, `category_id`, `title`, `author_name`, `detail`, `price`, `image`) SELECT `id`, `foo`, `category_id`, `title`, `author_name`, `detail`, `price`, `image` FROM `db_name`.`table_name` /*pt-online-schema-change 6557 copy table*/

・最後のステートメントから生じたエラー、警告など取得
Query SHOW WARNINGS

・スリープ状態になっていないスレッドの数
Query SHOW GLOBAL STATUS LIKE 'Threads_running'

・リネーム
Query RENAME TABLE `db_name`.`table_name` TO `db_name`.`_table_name_old`, `db_name`.`_table_name_new` TO `db_name`.`table_name`

・古いTable削除
Query DROP TABLE IF EXISTS `db_name`.`_table_name_old`

・triggerの削除
Query DROP TRIGGER IF EXISTS `db_name`.`pt_osc_db_name_table_name_del`
Query DROP TRIGGER IF EXISTS `db_name`.`pt_osc_db_name_table_name_upd`
Query DROP TRIGGER IF EXISTS `db_name`.`pt_osc_db_name_table_name_ins`

・移行用Tableの存在確認
Query SHOW TABLES FROM `db_name` LIKE '\_table\_name\_new'

Quit

実際実行すると、通常のAlterTableより時間がかかる傾向があります。
処理中に対象Tableの書き込みが発生しても、insert/updateのtriggerで旧Tableのデータが新Tableに反映される仕組みになっています。

なお、MySQL 5.6ではALTER TABLE...ADD INDEX/DROP INDEX中であっても参照・更新共に実行可能になる模様です。

実行する場合、バックアップした上で、似た環境で事前検証が必要です。
問題なければ、MySQL5.5以下はもちろん、5.6以上でもカラム追加、削除用途で使えると思います。

公式マニュアル
http://www.percona.com/doc/percona-toolkit/2.1/pt-online-schema-change.html
バグ情報
https://bugs.launchpad.net/percona-toolkit/+bugs?field.tag=pt-online-schema-change

WBSを活用しよう

はじめまして、CyberXエンジニアの稲垣です。





毎週金曜日恒例のエンジニアMTGにて、

発表の機会をいただいたので、発表内容の報告をします!



今回のテーマは…



「WBS」



です。





WBSって?



Work      → 目的を達成するために必要な作業

Breakdown → 漏れなく分解

Structure → 構造化して見える化


単語の意味のとおり、



作業分解して、構造化して見える化しましょうってことです。





WBSはPMだけのものだけじゃない!



WBSと聞くと、プロジェクトマネジャーがプロジェクトマネジメントを進めるために作成するもの、

と思っている方が多いかもしれません。

なぜなら、WBSは、プロジェクトマネジメントの普及とともに浸透してきた技術だからです。



とはいえ、WBSはマネジャー以外の人についてもとても便利です。



例えば、



・ イベント開発する(小規模チーム開発)

・ 社内フォーラムを開催する

・ 今月末の発表資料を作る

・ 友人のお祝いパーティを企画する

・ 年内に5kgやせる!

etc



これは、規模は小さいものの、1つのプロジェクトといえます。

つまり、WBSは、システムの開発だけでなく、プロジェクトといえるものすべてに活用できる

技術なのです。



前置きが長くなりましたが、





WBSのメリット!



WBSでは、トップダウンで論理的に作業や成果物を分解していくため、

作業家庭において、漏れたタスクに気づくことができたり、

それに伴い、タスクの優先度に気づき、そこからスケジュール作成をすることができます。

作業順序が明確になれば、担当者の割り振りであったり、

タスク単位で洗い出しを行うため、管理が用意になったりします。



タスクの洗い出しが完了すれば、そこから、

工数やコストの算出、スケジュール作成、必要リソースの確保、

タスク、機能品質の管理を行うことができます。

また、タスクが明確になっているため、

チームでのコミュニケーションも円滑に進めることができます。



① 作業の抜け・漏れや重複を防げる

② プロジェクトのスコープが決まる

③ 計画が明確になる

④ 先を見る習慣が身につく

⑤ 分解して管理する習慣が身につく




続いて…





作成ステップ!



                             ステップ① WBS作成の準備 


※全体の情報や必要な情報が見えていない状態でタスクの洗い出しを行うとタスクの漏れが発生したり、

認識の相違が出てきりするため、作成準備は特に重要になります。



                            ステップ② タスクの洗い出し


※洗い出す際にタスクの粒度が細かすぎると管理が煩雑になる可能性がありますので、1時間、2時間で

完了するようなタスクは記載をしないほうが良い。

                             ステップ③ 工数見積もり


                            ステップ④ スケジュール作成


                             ステップ⑤ 役割分担の作成




上記のステップでWBSを作成します。





作成例



CyberX:エンジニアブログ








今回は、WBSの概要レベルについて、発表させていただきました。

機会があれば、より深堀した内容を発表したいと思います。





以上です。ありがとうございました。

--






【告知】10月12日・13日 DODA転職フェアに参加いたします♪

みなさま、こんにちはテレビくん


弊社CyberXが参加いたします、
転職フェアイベントのお知らせです。

明日・明後日
2日間にわたって開催されますので

アメーバ弊社CyberX、そしてQuunAppGrenge 3社の
CyberAgent SAPグループ・エンジニア職
バッテリー・パックについて

ご興味のある皆様は、どうぞご来場くださいませ。

◆◇◆―詳細はこちらから―――
http://doda.jp/e/fair/
――――――――――◆◇◆◇◆

書く日時書く

   10月12日(金)
   14:00~21:00

   10月13日(土)
   11:00~18:00

入場料無料えんぴつ履歴書不要えんぴつ入退場自由えんぴつ事前予約不要えんぴつ


sei会場sei

   東京ドームシティ内 プリズムホール

seiアクセスsei

   最寄り駅(徒歩)
   ● JR「水道橋駅」より徒歩2分
   ● 都営三田線「水道橋駅」より徒歩1分
   ● 都営大江戸線「春日駅」より徒歩6分
   ● 東京メトロ丸ノ内線・南北線「後楽園駅」より徒歩5分

 ↓アクセスMAPはこちらから↓
http://doda.jp/e/fair/about/plan.html

当日は、弊社現場のエンジニアが質疑応答を承ります。
何か気になることがあれば個別にご相談いただくことももちろん可能ですあいさつ

◆◇◆―詳細はこちらから―――
http://doda.jp/e/fair/
――――――――――◆◇◆◇◆

当日、皆様にお会いできることを心よりお待ちしております。

■CyberX CEO小柳津ブログ
http://ameblo.jp/spotlight

■CyberX CTO白井ブログ
http://ameblo.jp/goodoo/

■CyberX コーポレイトサイト
http://www.cyberx.co.jp/

■CyberX 公式FaceBookページ
http://www.facebook.com/CyberX.since2008

■CyberX 広報担当のブログ
http://ameblo.jp/cyberx-pr-news/