這一片海,源于那一瓢水

          Schema的優(yōu)化和索引 - 高性能的索引策略 - 索引和鎖(轉)

          InnoDB中,索引所扮演的角色是非常重要的。因為它們可以能讓語句鎖定更少的行。這是個要考慮的事情,因為在MySQL5.0 InnoDB中一個事物提前之前,是不會釋放鎖的。

          如果查詢語句不會檢索它們不需要的行。它們將鎖定更少的行。并且對于性能有提高,原因有二:首先,即使InnoDB行鎖是非常有效率的并且使用更少的內存,但是行鎖也會消耗一定的資源。其次,鎖定很多的行就提高了鎖的競爭并且降低了并發(fā)。

          僅當InnoDB訪問行的時候,才對它們加鎖,并且一個索引可以降低InnoDB所要訪問的行,因此也會降低鎖。然而,這種情況只適用于在存儲引擎級別中,InnoDB過濾了不期望的行。如果索引不允許InnoDB那么做,MySQL服務器就會在InnoDB取到這些值并且返回服務層之后,應用WHERE條件了。這種情況下,避免行的鎖定就太晚了:InnoDB已經(jīng)鎖定了它們,并且服務器是不可能解鎖的。

          為了更好的理解我們看個例子,我們還是用以前的數(shù)據(jù)庫Sakila

          mysql> SET AUTOCOMMIT=0;
          mysql> BEGIN;
          mysql> SELECT actor_id FROM sakila.actor WHERE actor_id < 5
              -> AND actor_id <> 1 FOR UPDATE;
          +----------+
          | actor_id |
          +----------+
          |        2 |
          |        3 |
          |        4 |
          +----------+

          這個查詢返回了2到4行,但是實際上它已經(jīng)獲得了1到4行的獨占鎖。InnoDB鎖定了第一行,因為這個語句是個索引范圍讀取:

          mysql> EXPLAIN SELECT actor_id FROM sakila.actor
              -> WHERE actor_id < 5 AND actor_id <> 1 FOR UPDATE;
          +----+-------------+-------+-------+---------+--------------------------+
          | id | select_type | table | type  | key     | Extra                    |
          +----+-------------+-------+-------+---------+--------------------------+
          |  1 | SIMPLE      | actor | range | PRIMARY | Using where; Using index |
          +----+-------------+-------+-------+---------+--------------------------+

          換句話說,這個低級別的存儲引擎操作是“從索引開始并且獲取所有的行直到actor_id<5為false”。服務器是不會告訴InnoDB,WHERE actor_id <>1的條件。來看下EXTRA列的Using where。這就說明了在存儲引擎返回行之后,MySQL服務器用WHERE進行了過濾。

          下面的語句證明了第一行已經(jīng)被鎖了,即使它不會出現(xiàn)在第一個查詢結果之中。丟掉第一個連接,開始第二個連接執(zhí)行下列語句。

          mysql> SET AUTOCOMMIT=0;
          mysql> BEGIN;
          mysql> SELECT actor_id FROM sakila.actor WHERE actor_id = 1 FOR UPDATE;

          這個查詢會被掛起。等待第一個事物是否第一行的鎖。這個行為是為了保證基于語句級的復制是正確的。(在復制的一節(jié)會說道。)

          就像這個例子所顯示的,即使使用了索引,InnoDB還回會鎖定它并不是真正需要的行。當不使用索引去查找和鎖定行,這樣的問題會更嚴重:如果這個語句沒有索引,不管需不需要,MySQL都會掃描整張表并且鎖定每個行。

          下面談一下InnoDB,索引和鎖的一些鮮為人知的細節(jié):InnoDB會把共享鎖放置在次要索引上,但是獨占鎖需要訪問主鍵。這就降低了使用覆蓋索引的可能性并且會導致SELECT FOR UPDATE 慢于LOCK IN SHARE MODE 或者沒有鎖的查詢。

          posted on 2010-06-25 17:54 何方 閱讀(173) 評論(0)  編輯  收藏 所屬分類: Stack

          My Links

          Blog Stats

          常用鏈接

          留言簿

          隨筆檔案

          文章分類

          文章檔案

          相冊

          搜索

          最新評論

          主站蜘蛛池模板: 汝南县| 吉林省| 汾阳市| 华亭县| 平安县| 山西省| 亳州市| 北碚区| 定结县| 瓦房店市| 乐山市| 贵德县| 定日县| 永州市| 甘德县| 德保县| 蕉岭县| 舞阳县| 柳林县| 陇西县| 崇义县| 黄骅市| 泽普县| 神农架林区| 卓资县| 渭南市| 丹东市| 昭通市| 视频| 新密市| 上林县| 和田市| 达拉特旗| 闽侯县| 桂林市| 冕宁县| 德钦县| 镇康县| 浦县| 罗山县| 桦甸市|