データベースの運用で避けられないのが、ロック競合によって起こるシステムトラブルへの対応です。「2時までに終わるはずのバッチ処理が朝になっても終わっていない」とか「負荷が高いわけでもないのにシステムが無応答になっている」といったトラブルが発生したとき、DBエンジニアはそれがロック競合によるものなのかどうかを切り分けて、適切に対処しなければなりません。 これまでInnoDBはロック競合に対してほとんど打つ手がなかったのですが、最近ようやく対処方法がでてきました。今日はその手順を確認していきたいと思います。 前提 今回ご紹介する手順は、MySQLの以下のバージョンを対象にしています。 MySQL 5.1+InnoDB Plugin 1.0 MySQL 5.4 いきなりハードルを上げてしまって申し訳ありませんが、バージョン5.0以下や素の5.1では使えませんのでご注意ください。以降の実行例はすべて
Redis による分散ロック¶ 異なるプロセス同士が、相互に排他的な方法で共有リソースに対して操作を実行する、という環境において、分散ロックは非常に役に立ちます。 Redis を使った DLM (Distributed Lock Manager) の実装については、多くのライブラリやブログポストがあります。しかし、ライブラリごとに異なるアプローチがとられており、またその多くは、より複雑なデザインと比較するとシンプルで、そのぶん保証される内容が低いアプローチとなっています。 このページは、Redis 上で分散ロックを実装するにあたり、標準的なアルゴリズムを提供することを目指すものです。私たちはここで Redlock と呼ぶアルゴリズムを提供します。これは DLM 実装の一種で、よく見かけるような、ひとつのインスタンスを使うアプローチよりも安全である、と私たちは考えています。コミュニティがこの
この記事はMySQL Casual Advent Calendar 2013 3日目の記事です。 はじめに 以前にSELECT ... FOR UPDATEとロックの挙動 - walf443's blogの記事にTwitterで少し言及したんですが、それの補足というか、InnoDBのロックの範囲について僕はこう理解していますよという話です。 MySQLといえば、InnoDBをネットワークサーバとして使うためのフレームワークであり、DBのインデックスにアクセスするためのDSLといっても過言ではないでしょう。 InnoDBのロックとはつまるところインデックス行のロックなので、InnoDBのロックの範囲を理解するためにInnoDBのインデックスについて少し前置きしておきます(だいぶ端折ったけど長くなった…)。 クラスタインデックスとセカンダリインデックス すでにInnoDBのイン
はじめに この記事は、MySQL Casual Advent Calendar 2013 7日目の記事です。 〜 Casual に記事を書けばええんやでヽ(´ー`)ノ 〜 私がMySQLで えっ?! っと思った下記エントリーの挙動が何故そうなってしまうのかを書きたいと思います。 InnoDBで行ロック/テーブルロックになる条件 MyISAM はテーブルロック、InnoDB は行ロックが掛かるというのは有名な話じゃないかと。 ただ、最近知ったのですが、InnoDB だとしても必ずしも行ロックになるわけではなく、テーブルロックになる場合もあるようですね。 ... InnoDB であってもユニーク制約 or インデックスが張られているカラムで検索した場合以外はテーブルロックになってしまうようです。これは注意しないと思わぬところでテーブルロックになってしまって大変なことになりそう! http://
ロック機能のポイントはSETNXです。 指定したキーがなかった場合は値をセットして1を返し、 既に存在する場合は何もせず0が返ってきます。 つまり、1はロック成功、0は他からロック済みと判断することができます。 それでは実装に進みましょう。 まずロックのインタフェースを用意します。 public interface Lock { public void lock() throws Timeoublic void unlock(); } 最低限のロックとアンロックを用意しました。 続いて中身を実装します。 public class RedisLock implements Lock { private static final String LOCK_KEY_PREFIX = "lock:"; private static final int LOCK_EXPIR
ロック読み取り (SELECT ... FOR UPDATE および SELECT ... LOCK IN SHARE MODE)
MySQLで行ロックかけてトランザクションを効かせたい場合、SELECT FOR UPDATEを使うわけですが、 以下のようなクエリを発行しちゃうと行ロックではなくテーブルロック風味に扱われるので注意。 mysql> begin; Query OK, 0 rows affected (0.00 sec) mysql> select * from user order by id DESC limit 1 for update; +----+---------+ | id | name | +----+---------+ | 4 | xaicron | +----+---------+ 1 row in set (0.00 sec)このクエリを実行中に別のセッションから同じことを実行するとロック待ち状態になり 最悪デッドロックで死亡します。
単純なロックの問題点 Java にはマルチスレッドプログラミングにおける一般的な排他制御を記述するのに適した synchronized ブロック、synchronized メソッドという構文があり、保護したいデータにアクセスする全てのコードをこれらの構文を使って同期化すれば、排他制御は簡単に実現できる。しかし、この方法には問題もある。例えば電子掲示板システムのログデータにこの方法を適用することを考えてみよう。 電子掲示板に対するアクセスを全て同期化するということは、一度に一人のユーザしかログにアクセスできないということである。なんらかの理由(サーバ・クライアント間の回線速度やクライアントの処理速度の低下など)でログの読み込みに時間がかかっているユーザが一人れば、サーバ側の計算機資源にいくら余裕があっても、その間は他の大勢のユーザは掲示板にアクセスできない。すなわち計算機資源の利用効率が著し
MySQLのInnoDBストレージエンジンは行ロックをサポートしています。しかしOracleと同じ感覚でアプリケーションを作っていると、思わぬところでデッドロックに出くわすことがあります。これはInnoDBのロック範囲がOracleよりも微妙に広いためです。 実際の例で確認してみましょう。 mysql> select * from t; +----+------+ | c1 | c2 | +----+------+ | 10 | a | | 15 | a | | 20 | a | | 25 | a | | 30 | a | | 35 | a | | 40 | a | | 45 | a | | 50 | a | +----+------+c1列は主キーになっています。1つめのセッションで以下のmysql> set tx_isolation = 'repeatable-r
リリース、障害情報などのサービスのお知らせ
最新の人気エントリーの配信
処理を実行中です
j次のブックマーク
k前のブックマーク
lあとで読む
eコメント一覧を開く
oページを開く