青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

兔子的技術博客

兔子

   :: 首頁 :: 聯系 :: 聚合  :: 管理
  202 Posts :: 0 Stories :: 43 Comments :: 0 Trackbacks

留言簿(10)

最新評論

閱讀排行榜

評論排行榜

摘自 

《深入淺出MySQL——數據庫開發、優化與管理維護》

20.3.3 InnoDB的行鎖模式及加鎖方法

InnoDB實現了以下兩種類型的行鎖。 

? 共享鎖(S):允許一個事務去讀一行,阻止其他事務獲得相同數據集的排他鎖。

? 排他鎖(X):允許獲得排他鎖的事務更新數據,阻止其他事務取得相同數據集的共享讀鎖和排他寫鎖。

另外,為了允許行鎖和表鎖共存,實現多粒度鎖機制,InnoDB還有兩種內部使用的意向鎖(Intention Locks),這兩種意向鎖都是表鎖。

? 意向共享鎖(IS):事務打算給數據行加行共享鎖,事務在給一個數據行加共享鎖前必須先取得該表的IS鎖。

? 意向排他鎖(IX):事務打算給數據行加行排他鎖,事務在給一個數據行加排他鎖前必須先取得該表的IX鎖。

上述鎖模式的兼容情況具體如表20-6所示。

表20-6     InnoDB行鎖模式兼容性列表

請求鎖模式

 

   是否兼容

 

當前鎖模式

X

IX

S

IS

X

沖突

沖突

沖突

沖突

IX

沖突

兼容

沖突

兼容

S

沖突

沖突

兼容

兼容

IS

沖突

兼容

兼容

兼容

如果一個事務請求的鎖模式與當前的鎖兼容,InnoDB就將請求的鎖授予該事務;反之,如果兩者不兼容,該事務就要等待鎖釋放。

意向鎖是InnoDB自動加的,不需用戶干預。對于UPDATE、DELETE和INSERT語句,InnoDB會自動給涉及數據集加排他鎖(X);對于普通SELECT語句,InnoDB不會加任何鎖;事務可以通過以下語句顯示給記錄集加共享鎖或排他鎖。

·共享鎖(S):SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE。

·排他鎖(X):SELECT * FROM table_name WHERE ... FOR UPDATE。

用SELECT ... IN SHARE MODE獲得共享鎖,主要用在需要數據依存關系時來確認某行記錄是否存在,并確保沒有人對這個記錄進行UPDATE或者DELETE操作。但是如果當前事務也需要對該記錄進行更新操作,則很有可能造成死鎖,對于鎖定行記錄后需要進行更新操作的應用,應該使用SELECT... FOR UPDATE方式獲得排他鎖。

在如表20-7所示的例子中,使用了SELECT ... IN SHARE MODE加鎖后再更新記錄,看看會出現什么情況,其中actor表的actor_id字段為主鍵。

表20-7           InnoDB存儲引擎的共享鎖例子

session_1

session_2

mysql> set autocommit = 0;

Query OK, 0 rows affected (0.00 sec)

 

mysql> select actor_id,first_name,last_name from actor where actor_id = 178;

+----------+------------+-----------+

| actor_id | first_name | last_name |

+----------+------------+-----------+

| 178      | LISA       | MONROE   |

+----------+------------+-----------+

1 row in set (0.00 sec)

mysql> set autocommit = 0;

Query OK, 0 rows affected (0.00 sec)

 

mysql> select actor_id,first_name,last_name from actor where actor_id = 178;

+----------+------------+-----------+

| actor_id | first_name | last_name |

+----------+------------+-----------+

| 178      | LISA       | MONROE   |

+----------+------------+-----------+

1 row in set (0.00 sec)

當前session對actor_id=178的記錄加share mode 的共享鎖:

mysql> select actor_id,first_name,last_name from actor where actor_id = 178 lock in share mode;

+----------+------------+-----------+

| actor_id | first_name | last_name |

+----------+------------+-----------+

| 178      | LISA       | MONROE   |

+----------+------------+-----------+

1 row in set (0.01 sec)

 

 

其他session仍然可以查詢記錄,并也可以對該記錄加share mode的共享鎖:

mysql> select actor_id,first_name,last_name from actor where actor_id = 178 lock in share mode;

+----------+------------+-----------+

| actor_id | first_name | last_name |

+----------+------------+-----------+

| 178      | LISA       | MONROE   |

+----------+------------+-----------+

1 row in set (0.01 sec)

當前session對鎖定的記錄進行更新操作,等待鎖:

mysql> update actor set last_name = 'MONROE T' where actor_id = 178;

等待

 

 

其他session也對該記錄進行更新操作,則會導致死鎖退出:

mysql> update actor set last_name = 'MONROE T' where actor_id = 178;

ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

獲得鎖后,可以成功更新:

mysql> update actor set last_name = 'MONROE T' where actor_id = 178;

Query OK, 1 row affected (17.67 sec)

Rows matched: 1  Changed: 1 Warnings: 0

 

當使用SELECT...FOR UPDATE加鎖后再更新記錄,出現如表20-8所示的情況。

表20-8             InnoDB存儲引擎的排他鎖例子

session_1

session_2

mysql> set autocommit = 0;

Query OK, 0 rows affected (0.00 sec)

 

mysql> select actor_id,first_name,last_name from actor where actor_id = 178;

+----------+------------+-----------+

| actor_id | first_name | last_name |

+----------+------------+-----------+

| 178      | LISA       | MONROE   |

+----------+------------+-----------+

1 row in set (0.00 sec)

mysql> set autocommit = 0;

Query OK, 0 rows affected (0.00 sec)

 

mysql> select actor_id,first_name,last_name from actor where actor_id = 178;

+----------+------------+-----------+

| actor_id | first_name | last_name |

+----------+------------+-----------+

| 178      | LISA       | MONROE   |

+----------+------------+-----------+

1 row in set (0.00 sec)

當前session對actor_id=178的記錄加for update的共享鎖:

mysql> select actor_id,first_name,last_name from actor where actor_id = 178 for update;

+----------+------------+-----------+

| actor_id | first_name | last_name |

+----------+------------+-----------+

| 178      | LISA       | MONROE   |

+----------+------------+-----------+

1 row in set (0.00 sec)

 

 

其他session可以查詢該記錄,但是不能對該記錄加共享鎖,會等待獲得鎖:

mysql> select actor_id,first_name,last_name from actor where actor_id = 178;

+----------+------------+-----------+

| actor_id | first_name | last_name |

+----------+------------+-----------+

| 178      | LISA       | MONROE   |

+----------+------------+-----------+

1 row in set (0.00 sec)

 

mysql> select actor_id,first_name,last_name from actor where actor_id = 178 for update;

等待

當前session可以對鎖定的記錄進行更新操作,更新后釋放鎖:

mysql> update actor set last_name = 'MONROE T' where actor_id = 178;

Query OK, 1 row affected (0.00 sec)

Rows matched: 1  Changed: 1 Warnings: 0

 

mysql> commit;

Query OK, 0 rows affected (0.01 sec)

 

 

其他session獲得鎖,得到其他session提交的記錄:

mysql> select actor_id,first_name,last_name from actor where actor_id = 178 for update;

+----------+------------+-----------+

| actor_id | first_name | last_name |

+----------+------------+-----------+

| 178      | LISA       | MONROE T |

+----------+------------+-----------+

1 row in set (9.59 sec)

 

 20.3.4 InnoDB行鎖實現方式

InnoDB行鎖是通過給索引上的索引項加鎖來實現的,這一點MySQL與Oracle不同,后者是通過在數據塊中對相應數據行加鎖來實現的。InnoDB這種行鎖實現特點意味著:只有通過索引條件檢索數據,InnoDB才使用行級鎖,否則,InnoDB將使用表鎖!

在實際應用中,要特別注意InnoDB行鎖的這一特性,不然的話,可能導致大量的鎖沖突,從而影響并發性能。下面通過一些實際例子來加以說明。

(1)在不通過索引條件查詢的時候,InnoDB確實使用的是表鎖,而不是行鎖。

在如表20-9所示的例子中,開始tab_no_index表沒有索引:

mysql> create table tab_no_index(id int,name varchar(10)) engine=innodb;
Query OK, 0 rows affected (0.15 sec)
mysql> insert into tab_no_index values(1,'1'),(2,'2'),(3,'3'),(4,'4');
Query OK, 4 rows affected (0.00 sec)
Records: 4  Duplicates: 0  Warnings: 0

表20-9         InnoDB存儲引擎的表在不使用索引時使用表鎖例子

session_1

session_2

mysql> set autocommit=0;

Query OK, 0 rows affected (0.00 sec)

mysql> select * from tab_no_index where id = 1 ;

+------+------+

| id   | name |

+------+------+

| 1    | 1    |

+------+------+

1 row in set (0.00 sec)

mysql> set autocommit=0;

Query OK, 0 rows affected (0.00 sec)

mysql> select * from tab_no_index where id = 2 ;

+------+------+

| id   | name |

+------+------+

| 2    | 2    |

+------+------+

1 row in set (0.00 sec)

mysql> select * from tab_no_index where id = 1 for update;

+------+------+

| id   | name |

+------+------+

| 1    | 1    |

+------+------+

1 row in set (0.00 sec)

 

 

mysql> select * from tab_no_index where id = 2 for update;

等待

在如表20-9所示的例子中,看起來session_1只給一行加了排他鎖,但session_2在請求其他行的排他鎖時,卻出現了鎖等待!原因就是在沒有索引的情況下,InnoDB只能使用表鎖。當我們給其增加一個索引后,InnoDB就只鎖定了符合條件的行,如表20-10所示。

創建tab_with_index表,id字段有普通索引:

mysql> create table tab_with_index(id int,name varchar(10)) engine=innodb;
Query OK, 0 rows affected (0.15 sec)
mysql> alter table tab_with_index add index id(id);
Query OK, 4 rows affected (0.24 sec)
Records: 4  Duplicates: 0  Warnings: 0

表20-10    InnoDB存儲引擎的表在使用索引時使用行鎖例子

session_1

session_2

mysql> set autocommit=0;

Query OK, 0 rows affected (0.00 sec)

mysql> select * from tab_with_index where id = 1 ;

+------+------+

| id   | name |

+------+------+

| 1    | 1    |

+------+------+

1 row in set (0.00 sec)

mysql> set autocommit=0;

Query OK, 0 rows affected (0.00 sec)

mysql> select * from tab_with_index where id = 2 ;

+------+------+

| id   | name |

+------+------+

| 2    | 2    |

+------+------+

1 row in set (0.00 sec)

mysql> select * from tab_with_index where id = 1 for update;

+------+------+

| id   | name |

+------+------+

| 1    | 1    |

+------+------+

1 row in set (0.00 sec)

 

 

mysql> select * from tab_with_index where id = 2 for update;

+------+------+

| id   | name |

+------+------+

| 2    | 2    |

+------+------+

1 row in set (0.00 sec)

(2)由于MySQL的行鎖是針對索引加的鎖,不是針對記錄加的鎖,所以雖然是訪問不同行的記錄,但是如果是使用相同的索引鍵,是會出現鎖沖突的。應用設計的時候要注意這一點。

在如表20-11所示的例子中,表tab_with_index的id字段有索引,name字段沒有索引:

mysql> alter table tab_with_index drop index name;
Query OK, 4 rows affected (0.22 sec)
Records: 4  Duplicates: 0  Warnings: 0
mysql> insert into tab_with_index  values(1,'4');
Query OK, 1 row affected (0.00 sec)
mysql> select * from tab_with_index where id = 1;
+------+------+
| id   | name |
+------+------+
| 1    | 1    |
| 1    | 4    |
+------+------+
2 rows in set (0.00 sec)

表20-11    InnoDB存儲引擎使用相同索引鍵的阻塞例子

session_1

session_2

mysql> set autocommit=0;

Query OK, 0 rows affected (0.00 sec)

mysql> set autocommit=0;

Query OK, 0 rows affected (0.00 sec)

mysql> select * from tab_with_index where id = 1 and name = '1' for update;

+------+------+

| id   | name |

+------+------+

| 1    | 1    |

+------+------+

1 row in set (0.00 sec)

 

 

雖然session_2訪問的是和session_1不同的記錄,但是因為使用了相同的索引,所以需要等待鎖:

mysql> select * from tab_with_index where id = 1 and name = '4' for update;

等待

(3)當表有多個索引的時候,不同的事務可以使用不同的索引鎖定不同的行,另外,不論是使用主鍵索引、唯一索引或普通索引,InnoDB都會使用行鎖來對數據加鎖。

在如表20-12所示的例子中,表tab_with_index的id字段有主鍵索引,name字段有普通索引:

mysql> alter table tab_with_index add index name(name);
Query OK, 5 rows affected (0.23 sec)
Records: 5  Duplicates: 0  Warnings: 0

表20-12    InnoDB存儲引擎的表使用不同索引的阻塞例子

·          session_1

·          session_2

mysql> set autocommit=0;

Query OK, 0 rows affected (0.00 sec)

mysql> set autocommit=0;

Query OK, 0 rows affected (0.00 sec)

mysql> select * from tab_with_index where id = 1 for update;

+------+------+

| id   | name |

+------+------+

| 1    | 1    |

| 1    | 4    |

+------+------+

2 rows in set (0.00 sec)

 

 

Session_2使用name的索引訪問記錄,因為記錄沒有被索引,所以可以獲得鎖:

mysql> select * from tab_with_index where name = '2' for update;

+------+------+

| id   | name |

+------+------+

| 2    | 2    |

+------+------+

1 row in set (0.00 sec)

 

由于訪問的記錄已經被session_1鎖定,所以等待獲得鎖。:

mysql> select * from tab_with_index where name = '4' for update;

(4)即便在條件中使用了索引字段,但是否使用索引來檢索數據是由MySQL通過判斷不同執行計劃的代價來決定的,如果MySQL認為全表掃描效率更高,比如對一些很小的表,它就不會使用索引,這種情況下InnoDB將使用表鎖,而不是行鎖。因此,在分析鎖沖突時,別忘了檢查SQL的執行計劃,以確認是否真正使用了索引。關于MySQL在什么情況下不使用索引的詳細討論,參見本章“索引問題”一節的介紹。

在下面的例子中,檢索值的數據類型與索引字段不同,雖然MySQL能夠進行數據類型轉換,但卻不會使用索引,從而導致InnoDB使用表鎖。通過用explain檢查兩條SQL的執行計劃,我們可以清楚地看到了這一點。

例子中tab_with_index表的name字段有索引,但是name字段是varchar類型的,如果where條件中不是和varchar類型進行比較,則會對name進行類型轉換,而執行的全表掃描。

mysql> alter table tab_no_index add index name(name);
Query OK, 4 rows affected (8.06 sec)
Records: 4  Duplicates: 0  Warnings: 0
mysql> explain select * from tab_with_index where name = 1 \G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: tab_with_index
type: ALL
possible_keys: name
key: NULL
key_len: NULL
ref: NULL
rows: 4
Extra: Using where
1 row in set (0.00 sec)
mysql> explain select * from tab_with_index where name = '1' \G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: tab_with_index
type: ref
possible_keys: name
key: name
key_len: 23
ref: const
rows: 1
Extra: Using where
1 row in set (0.00 sec)

標簽: Mysql事務
轉自:
http://www.cnblogs.com/zhizhesky/articles/2164089.html
posted on 2012-10-15 11:59 會飛的兔子 閱讀(489) 評論(0)  編輯 收藏 引用 所屬分類: 數據庫,MIS系統
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲午夜视频| 国产精品无码专区在线观看| 欧美一区国产一区| 欧美极品欧美精品欧美视频| 久久精品一区二区| 欧美日韩免费在线观看| 欧美风情在线观看| 国产一区二区中文字幕免费看| 999亚洲国产精| 亚洲精品免费网站| 美国十次成人| 久久综合九色综合欧美狠狠| 国产乱码精品1区2区3区| 99精品久久免费看蜜臀剧情介绍| 亚洲国产成人久久综合| 久久久999精品视频| 欧美一级久久久| 国产精品国产三级国产aⅴ9色| 亚洲国产国产亚洲一二三| 国产精品人成在线观看免费| 日韩视频免费观看| 国产精品99久久久久久宅男| 欧美精品久久99久久在免费线| 欧美成人精品激情在线观看| 在线日本高清免费不卡| 久久精品夜色噜噜亚洲a∨| 欧美专区在线| 国产一区二区三区久久久久久久久| 亚洲一区二区欧美日韩| 香蕉精品999视频一区二区| 国产精品福利av| 亚洲一区二区三区免费视频| 性亚洲最疯狂xxxx高清| 国产伦精品一区二区三区| 亚洲欧美日韩一区| 久久精品国产亚洲aⅴ| 极品少妇一区二区| 免费日韩av| 亚洲精品中文在线| 亚洲欧美日本国产专区一区| 国产精品性做久久久久久| 午夜电影亚洲| 欧美fxxxxxx另类| 亚洲乱码国产乱码精品精天堂| 欧美日本不卡视频| 亚洲小说欧美另类社区| 久久躁日日躁aaaaxxxx| 亚洲人体1000| 国产精品第一区| 久久精品国产999大香线蕉| 免费黄网站欧美| 一区二区三区精密机械公司| 国产精品剧情在线亚洲| 久久嫩草精品久久久精品一| 亚洲区一区二| 久久国产日韩| 亚洲精品视频在线观看网站| 国产精品毛片va一区二区三区| 午夜日韩在线| 亚洲国产精品尤物yw在线观看| 亚洲视频你懂的| 韩日欧美一区二区| 欧美日韩精品一区二区三区| 欧美在线观看一区二区| 亚洲精品国产日韩| 久久影视三级福利片| 一区二区精品在线| 伊人婷婷久久| 国产精品国产自产拍高清av| 久久久www成人免费无遮挡大片| 亚洲欧洲一区二区在线播放| 久久激情五月激情| 99国产精品久久久久老师| 国语自产偷拍精品视频偷| 欧美日韩免费看| 老司机一区二区| 午夜久久电影网| 亚洲精品久久久久久久久久久久 | 国产日韩欧美中文在线播放| 麻豆国产精品va在线观看不卡 | 亚洲精品人人| 免费的成人av| 欧美与黑人午夜性猛交久久久| 日韩亚洲欧美成人一区| 伊人一区二区三区久久精品| 国产精品一区二区你懂得 | 亚洲大片在线观看| 久久精品亚洲国产奇米99| 中文亚洲欧美| 日韩一区二区精品在线观看| 精品99一区二区| 国产亚洲精品高潮| 国产麻豆日韩| 欧美私人啪啪vps| 欧美精品综合| 欧美激情视频网站| 欧美成ee人免费视频| 久久久免费观看视频| 久久国产精品亚洲va麻豆| 亚洲一区在线观看视频| 亚洲视频在线观看三级| 一本久道综合久久精品| 亚洲精品日韩精品| 亚洲欧洲美洲综合色网| 亚洲国产精品尤物yw在线观看| 美女精品在线观看| 久久久精品一区| 欧美一区激情| 久久精品在线观看| 久久久天天操| 蜜桃伊人久久| 欧美肥婆bbw| 91久久精品国产91性色| 91久久中文| 亚洲精品激情| 99精品99久久久久久宅男| 日韩亚洲欧美中文三级| 宅男66日本亚洲欧美视频| 亚洲一区二区三区四区在线观看| 亚洲一级影院| 欧美一区二区三区视频免费播放 | 久久精品五月| 欧美1区2区| 欧美精品一区二区三区在线播放| 欧美日韩国产三区| 国产精品国产三级国产专播品爱网| 国产精品久久久久久久久果冻传媒| 国产精品日韩欧美一区二区| 国产欧美韩国高清| 在线观看欧美| 99成人精品| 欧美一区三区三区高中清蜜桃 | 亚洲精品国产精品乱码不99| 99成人在线| 欧美在线视频一区二区三区| 久久一区二区精品| 欧美日本精品一区二区三区| 国产精品稀缺呦系列在线| 狠狠色丁香婷婷综合久久片| 亚洲精品韩国| 午夜在线电影亚洲一区| 欧美jizz19性欧美| 日韩香蕉视频| 久久久久一区二区三区| 欧美日韩视频在线| 国产在线一区二区三区四区 | 在线观看日韩国产| 在线综合亚洲| 久久影院午夜论| 99天天综合性| 久久精品视频免费观看| 欧美日韩国产一区二区三区地区| 国产精品系列在线播放| 亚洲精品乱码久久久久久蜜桃91| 亚洲女人天堂成人av在线| 欧美a一区二区| 亚洲专区在线| 欧美日本韩国一区二区三区| 国产主播一区二区| 亚洲午夜久久久| 久久中文久久字幕| 亚洲一级在线观看| 欧美激情精品久久久久久黑人| 国产嫩草一区二区三区在线观看| 亚洲日本乱码在线观看| 久久久久久久久久久久久久一区| 99ri日韩精品视频| 美女精品网站| 狠狠入ady亚洲精品| 亚洲女人天堂av| 亚洲日本中文字幕免费在线不卡| 久久精品人人做人人综合| 国产精品电影网站| 一本色道久久88亚洲综合88| 免费黄网站欧美| 久久国产精品电影| 国产欧美一区二区精品性| 亚洲一区二区三区777| 亚洲国产欧洲综合997久久| 久久男女视频| 精品福利电影| 久久综合网色—综合色88| 亚洲免费中文字幕| 国产精品日韩精品| 亚洲女同在线| 亚洲网友自拍| 国产精品视频免费| 亚洲男人的天堂在线| 一区二区三区|亚洲午夜| 欧美日韩三级视频| 一区二区三区鲁丝不卡| 亚洲日韩中文字幕在线播放| 欧美电影在线观看完整版| 91久久精品美女高潮| 欧美成人一区二区三区| 美女黄毛**国产精品啪啪| 亚洲日本在线观看| 最新亚洲电影| 欧美日韩色婷婷| 亚洲女同在线|