2012-12-24

MySQL テーブルスペース肥大化対応

現在、運用・保守しているシステムの本番環境のメンテナンスを実施していると、「innodb_file_per_table」が設定されていないことを発見。メンテナンスついでに通常のibdataファイルを複数表領域に変更する手順。

MySQL接続
# mysql -u root -p -h 127.0.0.1

更新系ロック実行
更新系の処理をロックする(参照系はロックされない)。
mysql> FLUSH TABLES WITH READ LOCK;
ログからテーブルスペースへ書き込み中の可能性もあるので、「Log sequence number」と「Log flushed up to」の値が同じであることを確認。
mysql> SHOW INNODB STATUS\G
~中略~
---
LOG
---
Log sequence number 642420560012
Log flushed up to   642420560012
Last checkpoint at  642420560012
0 pending log writes, 0 pending chkp writes
86747663 log i/o's done, 0.08 log i/o's/second
~中略~
SHOW STATUS」を実行して、「Key_blocks_not_flushed」が「0」であることを確認。
mysql> SHOW STATUS LIKE '%Key_blocks_not_flushed%';
+------------------------+-------+
| Variable_name          | Value |
+------------------------+-------+
| Key_blocks_not_flushed | 0     |
+------------------------+-------+
1 row in set (0.01 sec)

ダンプ
全てのデータベースをダンプする。
# mysqldump -u root -p -h 127.0.0.1 --all-database --master-data=2 --default-character-set=binary --single-transaction --flush-logs --quick | gzip --best -c > ./all_database.sql.gz
--all-database」
⇒ 全てのデータベースのからデータをダンプするように設定。
「--master-data=2」
⇒ スレーブのセットアップ用のバイナリーログのファイル名と開始位置を出力するように設定。
「--default-character-set=binary」
⇒ UTF-8のデータベースからのダンプ文字化け回避の為に設定。
「--single-transaction」
⇒ テーブルへの参照&更新をブロックすることなく、mysqldumpコマンド開始時点のスナップショットを取るように設定。(MyISAMなどでは利用できない)
「--flush-logs」
⇒ バイナリーログのローテーションを行うように設定。
「--quick」
⇒ クエリをバッファせず、stdouに直接ダンプするように設定。

更新系ロック解除
mysql> UNLOCK TABLES;

my.cnf変更
my.cnfの設定を変更する。
[mysqld]
innodb_data_file_path=ibdata1:10M:autoextend
innodb_autoextend_increment=64
innodb_file_per_table
innodb_data_file_path = ibdata1:10M:autoextend」
⇒ デフォルト値を設定。
「innodb_autoextend_increment=64」
⇒ 拡張時に64MBの領域を確保するように設定。
「innodb_file_per_table」
⇒ テーブルスペースをテーブル単位で作成するように設定。

MySQL接続
# mysql -u root -p -h 127.0.0.1

アクセス状況確認
他からのアクセスがないことを確認する。
mysql> SHOW PROCESSLIST;

スレーブ停止
mysql> SLAVE STOP;

MySQL停止
# /etc/init.d/mysqld stop

既存データ退避
# mkdir /home/mysql/tmp/data/
# mv /home/mysql/data/ib_logfile0 /home/mysql/tmp/data/ib_logfile0
# mv /home/mysql/data/ib_logfile1 /home/mysql/tmp/data/ib_logfile1
# mv /home/mysql/data/ibdata1 /home/mysql/tmp/data/ibdata1

MySQL起動
# /etc/init.d/mysqld start

リストア実行
# mysql -u root -p -h 127.0.0.1 --default-character-set=utf8 < ./all_database.sql

スレーブ設定
ダンプファイルからマスタの情報を取得。
# head -100 ./all_database.sql
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000454', MASTER_LOG_POS=106;
上記のコマンドで出力されたLOG_FILEとLOG_POSの値を、以下の「CHANGE MASTER TO」の「MASTER_LOG_FILE」、「MASTER_LOG_POS」の各値に設定する。
mysql> CHANGE MASTER TO
    -> MASTER_HOST = 'masterサーバーのIPアドレス',
    -> MASTER_PORT = 3306,
    -> MASTER_USER = 'slaveユーザーのアカウント名',
    -> MASTER_PASSWORD = 'slaveユーザーのパスワード',
    -> MASTER_LOG_FILE = 'mysql-bin.000454',
    -> MASTER_LOG_POS = 106,
    -> MASTER_CONNECT_RETRY = 10;

スレーブ開始
mysql> SLAVE START;
スレーブ状況を確認。
mysql> SHOW SLAVE STATUS\G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: masterサーバーのIPアドレス
                  Master_User: slaveユーザーのアカウント名
                  Master_Port: 3306
                Connect_Retry: 10
              Master_Log_File: mysql-bin.000454
          Read_Master_Log_Pos: 202859032
               Relay_Log_File: mysql-relay-bin.000006
                Relay_Log_Pos: 160873379
        Relay_Master_Log_File: mysql-bin.000454
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB:
          Replicate_Ignore_DB: test
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table:
                   Last_Errno: 0
                   Last_Error:
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 202859032
              Relay_Log_Space: 160873534
              Until_Condition: None
               Until_Log_File:
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File:
           Master_SSL_CA_Path:
              Master_SSL_Cert:
            Master_SSL_Cipher:
               Master_SSL_Key:
        Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error:
               Last_SQL_Errno: 0
               Last_SQL_Error:
1 row in set (0.00 sec)

ERROR:
No query specified

※また、本ページを作成するのに以下のサイトを参考にしました。
mysqlのibdataが原因でディスクフルになったときに復旧方法
MySQLのibdataファイルを複数表領域に変更する
MySQLの「innodb_buffer_pool_size」と「innodb_log_file_size」の設定
MySQLのInnoDBデータファイル「ibdata1」の最適化
ibdata1 のサイズを減らす手順
拡張され続ける InnoDB のデータファイルのサイズを小さくする方法
MySQLのバックアップと"FLUSH TABLES WITH READ LOCK"についてAdd Star
現場指向のレプリケーション詳説
MySQL innodbでのibdata1肥大問題
InnoDBのログとテーブルスペースの関係
InnoDBデータファイルのサイズを変更するには

2011-11-13

土屋鞄製造所 SESSIONシリーズ

左:キャリーオールボストン
右:ビッグトート

以前から新しい鞄が欲しくてリストアップしていた鞄が最終販売になった。
どうしても欲しいという欲求と、将来的に手に入らないという危機感みたいな感情に数週間悩まされたが、結局購入しました。

2011-08-08

Tokyo Tyrant ulog肥大化回避

Tokyo Tyrantのulogを放置していたら肥大化したので、最新10ファイルを残してそれ以外は削除するスクリプトを作成。
#!/bin/bash
#
# @(#) TokyoTyrantDeleteUlog.sh ver.1.0.0 2011.08.08
#
# Usage:
#   TokyoTyrantDeleteUlog.sh
#
# Description:
#   Tokyo Tyrantのulog削除スクリプト
#   最新10ファイルのみを保存
#
###########################################################################

# ulog保存先設定
logdir='/home/ttserver/data/ulog/'

# ulog保存先内ファイル一覧取得
mydir=`ls -t $logdir`

# ファイル分ループ
i=1
for file in $mydir
  do
    # 10ファイル目までは処理をスキップ
    if [ $i -gt 10 ]
    then
      # 削除処理
      rm -rf $logdir$file
    fi
    i=$((i+1))
  done
あとは定期的に実行するためにcronに登録。
# 午前00時処理
# ・Tokyo Tyrantのulog削除
0 0 * * * TokyoTyrantDeleteUlog.sh

2011-07-03

オープンソースの定義

何気なくサイトを見ていると、「オープンソース」を定義しているサイトに出会った。
記載されている内容はともかく、業界にいるので「オープンソース」という言葉を聞かない日がないほど有名な言葉であるが、改めて読んでみると、現在、私がこの業界で仕事が出来ているのも、ひとえに「オープンソース」という概念の恩恵があってこそであると改めて認識させられた。
小さい頃から結構憧れの業界であり、「入り込めればなんとかなるさ!」という何の根拠もない信念のもと携わってきたが、今一度、これまでの感謝とこれからの恩返しを心に誓うべく、「オープンソースの定義」を以下に記載します。


はじめに
「オープンソース」とは、単にソースコードが入手できるということだけを意味するのではありません。「オープンソース」であるプログラムの頒布条件は、以下の基準を満たしていなければなりません。

1.再頒布の自由
「オープンソース」であるライセンス(以下「ライセンス」と略)は、出自の様々なプログラムを集めたソフトウェア頒布物(ディストリビューション)の一部として、ソフトウェアを販売あるいは無料で頒布することを制限してはなりません。ライセンスは、このような販売に関して印税その他の報酬を要求してはなりません。
理由:ライセンスが自由な再頒布を要求するよう強制することにより、数多くの長期的利益をちょっとした短期的な販売収益を得るために投げ捨ててしまうというような誘惑を除くことができます。このような縛りをかけないと、協力者たちは変節せよという強い圧力にさらされてしまうでしょう。

2.ソースコード
「オープンソース」であるプログラムはソースコードを含んでいなければならず、コンパイル済形式と同様にソースコードでの頒布も許可されていなければなりません。何らかの事情でソースコードと共に頒布しない場合には、ソースコードを複製に要するコストとして妥当な額程度の費用で入手できる方法を用意し、それをはっきりと公表しなければなりません。方法として好ましいのはインターネットを通じての無料ダウンロードです。ソースコードは、プログラマがプログラムを変更しやすい形態でなければなりません。意図的にソースコードを分かりにくくすることは許されませんし、プリプロセッサや変換プログラムの出力のような中間形式は認められません。
理由:私たちは、意図的に分かりにくくされていないソースコードが入手できることを要求します。プログラムを改変することなしにはプログラムを発展させることはできないからです。私たちの目的はソフトウェアの発展をより容易なものにすることですから、変更が簡単に行えることを必要条件に加えています。

3.派生ソフトウェア
ライセンスは、ソフトウェアの変更と派生ソフトウェアの作成、並びに派生ソフトウェアを元のソフトウェアと同じライセンスの下で頒布することを許可しなければなりません。
理由:単にソースを読むことができるだけでは、独立したピアレビューや急速な発展的淘汰を維持するのに十分ではありません。急速な進化を実際に起こすためには、人々がそのソフトウェアでさまざまに実験し、変更点を再頒布することができる必要があります。

4.作者のソースコードの完全性(integrity)
バイナリ構築の際にプログラムを変更するため、ソースコードと一緒に「パッチファイル」を頒布することを認める場合に限り、ライセンスによって変更されたソースコードの頒布を制限することができます。ライセンスは、変更されたソースコードから構築されたソフトウェアの頒布を明確に許可していなければなりませんが、派生ソフトウェアに元のソフトウェアとは異なる名前やバージョン番号をつけるよう義務付けるのは構いません。
理由:盛んに改良することを奨励するのは良いことですが、ユーザには彼らが使っているソフトウェアについて誰が責任を持っているのか知る権利があります。反対に、ソフトウェアの作者と管理者にも彼らの名声を保護し、何をサポートすることが要求されているのか知る権利があります。

それゆえ、オープンソースなライセンスはそのソースが容易に入手可能であることを保証しなければならないのですが、一方でそれがいっさい変更されていない本来の基本ソースとパッチという形で頒布することを義務付けても構わないということにします。こうすれば、「非公式」な変更点は利用可能でありつつも、元のソースとは簡単に見分けがつくわけです。

5.個人やグループに対する差別の禁止
ライセンスは特定の個人やグループを差別してはなりません。
理由:進化の過程から最大の恩恵を引き出すためには、可能な限り多種多様な人々やグループに、平等にオープンソースに貢献する資格が与えられている必要があります。そこで、オープンソースなライセンスによって誰かを進化の過程から締め出すことは禁止されています。

アメリカ合衆国を含むいくつかの国では、ある種のソフトウェアに輸出制限を課しています。OSD準拠のライセンスは、適用される可能性がある制限についてライセンス受諾者に警告し、また彼らには法に従う義務があることを示唆しても構いません。しかし、ライセンス自身にそのような制限を取り込んではなりません。

6.利用する分野(fields of endeavor)に対する差別の禁止
ライセンスはある特定の分野でプログラムを使うことを制限してはなりません。例えば、プログラムの企業での使用や、遺伝子研究の分野での使用を制限してはなりません。
理由:この条項の主な意図は、ライセンスによってオープンソースが商業的に使われることを妨げるような策略を禁止することです。私たちは、営利的なユーザも私たちのコミュニティに加入してくれることを望んでおり、彼らがそこから排除されているような気分になっては欲しくないのです。

7.ライセンスの分配(distribution)
プログラムに付随する権利はそのプログラムが再頒布された者全てに等しく認め られなければならず、彼らが何らかの追加的ライセンスに同意することを必要としてはなりません。
理由:この条項は、ソフトウェアを機密保持契約への同意を要求するなどの間接的な手段によって囲い込むことの禁止を目的としています。

8.特定製品でのみ有効なライセンスの禁止
プログラムに付与された権利は、それがある特定のソフトウェア頒布物の一部であるということに依存するものであってはなりません。プログラムをその頒布物から取り出したとしても、そのプログラム自身のライセンスの範囲内で使用あるいは頒布される限り、プログラムが再頒布される全ての人々が、元のソフトウェア頒布物において与えられていた権利と同等の権利を有することを保証しなければなりません。
理由:この条項は、ライセンスによるこれまたよくあるタイプの策略を禁止します。

9.他のソフトウェアを制限するライセンスの禁止
ライセンスはそのソフトウェアと共に頒布される他のソフトウェアに制限を設けてはなりません。例えば、ライセンスは同じ媒体で頒布される他のプログラムが全てオープンソースソフトウェアであることを要求してはなりません。
理由:オープンソースなソフトウェアの頒布者には、彼ら自身のソフトウェアについては彼ら自身で選択する権利があります。

もちろんGPLはこの要件を満たしています。GPLが適用されたライブラリとリンクされたソフトウェアは、それが単一の著作物を形成する場合のみGPLを継承するのであって、単に一緒に頒布されるというだけならば他のソフトウェアには影響しません。

10.ライセンスは技術中立的でなければならない
ライセンス中に、特定の技術やインターフェースの様式に強く依存するような規定があってはなりません。
理由:この規定で特に念頭に置いているのは、ライセンサーとライセンシーの間で契約を成立させるために明示的な同意の意思表示を必要とするようなライセンスです。いわゆる「クリックラップ(click-wrap)」を要求する規定は、ソフトウェア頒布において重要な手法であるFTPダウンロードやCD-ROMアンソロジー、ウェブのミラーリングなどと衝突する可能性がありますので、このような規定もコードの再利用を妨げてしまいます。よって、本定義に準拠するライセンスは、(a)ソフトウェアの再頒布が、ダウンロード時のクリックラップをサポートしないようなウェブ以外の経路で起こりうるという可能性 (b)ライセンスで保護されるコード(あるいは保護されるコードの再利用された部分)はポップアップダイアログをサポートできない非GUIの環境でも実行されれうるという可能性、を認めなければなりません。

2011-07-01

Ext JS 4

クロスブラウザー対応、RIA開発用フレームワークであるExt JS。
Senchaの製品には複数のライセンスオプションが用意されているのだが、提供されるソースコードにどのような違いがあるのか検証してみた。

ソースコードの違いは以下の通り。
9、10行目のライセンスに関する記載のみ違いがありましたが、それ以外は同じソースコードでした。
注:時間がなかったので一階層目のソースコードのみ検証しました。のこりは時間のある時にでも・・・

商用ライセンス(ext-4.0.2a-commercial.zip)
/*

This file is part of Ext JS 4

Copyright (c) 2011 Sencha Inc

Contact:  http://www.sencha.com/contact

Commercial Usage
Licensees holding valid commercial licenses may use this file in accordance with the Commercial Software License Agreement provided with the Software or, alternatively, in accordance with the terms contained in a written agreement between you and Sencha.

If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.

*/

オープンソースライセンス(ext-4.0.2a-gpl.zip)
/*

This file is part of Ext JS 4

Copyright (c) 2011 Sencha Inc

Contact:  http://www.sencha.com/contact

GNU General Public License Usage
This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file.  Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.

If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.

*/

ちなにみ、複数のライセンスオプションは以下のとおり。

商用ライセンス(ext-4.0.2a-commercial.zip)
GPLが採用できないようなアプリケーション(ソースコードを公開したり配布したりできない場合等)を開発する場合に選択。
オープンソースライセンス(ext-4.0.2a-gpl.zip)
オープンソースライセンスは、GNU GPL license v3に準拠したオープンソースアプリケーションを作成する場合に選択。
OEMライセンス、リセラーライセンス
ソフトウェア開発ライブラリ、ツールキット、フレームワークを作成する場合に該当する場合に選択。Ext Japan, LLC (合同会社イーエクスティー)との契約が必要かと思います。

2011-06-30

MySQL Got error 139 from storage engine.

現在、運用・保守しているシステムの本番環境にて以下のエラーが発生した。
環境:MySQL 5.1.47、innodb plugin 1.0.8
ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 8126. You have to change some columns to TEXT or BLOBs

開発環境で同様の操作を行うと以下のエラーが発生。
環境:MySQL 5.1.45、Built-In innodb
ERROR 1030 (HY000): Got error 139 from storage engine

いろいろ検索してみると以下のような原因でエラーが発生している模様。
  • InnoDBの行サイズの上限はページサイズの約半分で、デフォルトでは約8KB。
  • 可変長カラム(VARBINARY、VARCHAR、BLOB、TEXT)のデータは行の外部に保存されるが、先頭の768Bだけは行の内部に保存される。
  • 一つのテーブルに11個のTEXT型フィールドを作り、それぞれに768B以上のデータを入れようとすると、768 * 11 = 8448 > 8000 なので保存できない。

MySQLのリファレンスマニュアルにも「InnoDBテーブルにおける制限」として以下のように記載されていました。
MySQL 5.1 Reference Manual :: 13.6.14. Restrictions on InnoDB Tables
The maximum row length, except for variable-length columns (VARBINARY, VARCHAR, BLOB and TEXT), is slightly less than half of a database page. That is, the maximum row length is about 8000 bytes. LONGBLOB and LONGTEXT columns must be less than 4GB, and the total row length, including BLOB and TEXT columns, must be less than 4GB.

まとめ:行サイズについて
MySQL自体の上限は、64KB。しかし、BLOBのデータは他の領域に格納されるので含みません。さらに、ストレージエンジンごとに制限が存在する場合があります。
InnoDBは、テーブルスペースのページサイズの約半分でが上限となり、ページサイズのデフォルトは16KBなのでデフォルトの行サイズは約8KBとなります。ページサイズを変更することも出来ますが、MySQLをソースからコンパイルして、さらにテーブルスペースとログファイルを再作成する必要があります。ページサイズの変更を行うと、ページサイズの上限は64KBとなるので、その場合の1行の最大サイズは32KBとなります。ちなみに、MySQL Clusterは1行あたり最大8KBです。

設計を見直すか・・・

※また、本ページを作成するのに以下のサイトを参考にしました。
InnoDBの意外な制約: Got error 139 from storage engine | へびにっき
Nix::WebLab : Got error 139 from storage engine
MySQL :: MySQL 5.1 Reference Manual :: 13.6.14 Restrictions on InnoDB Tables

2011-06-29

MySQL Innodb pluginバージョン確認

MySQLのInnodb pluginのバージョン確認方法。
mysql> SELECT @@innodb_version;
+------------------+
| @@innodb_version |
+------------------+
| 1.0.8            |
+------------------+
1 row in set (0.00 sec)