首先我們知道MySQL支持多種引擎,并且不同存儲(chǔ)引擎有很多不同,最重要的
即便是自動(dòng)提交模式下 當(dāng)start transaction;之后,必須要顯現(xiàn)的commit;才能釋放鎖資源,
myisam的鎖機(jī)制:
不支持行級(jí)鎖,支持的是表級(jí)鎖,分為共享讀鎖和獨(dú)占寫鎖。
1)什么是表鎖
表鎖:操作對(duì)象是數(shù)據(jù)表。Mysql大多數(shù)鎖策略都支持(常見(jiàn)mysql innodb),是系統(tǒng)開(kāi)銷最低但并發(fā)性最低的一個(gè)鎖策略。事務(wù)t對(duì)整個(gè)表加讀鎖,則其他事務(wù)可讀不可寫,若加寫鎖,則其他事務(wù)增刪改都不行
2)什么是讀鎖
讀鎖:也叫共享鎖、S鎖,若事務(wù)T對(duì)表A加上S鎖,則事務(wù)T可以讀表A但不能修改表A,其他事務(wù)只能再對(duì)表A加S鎖,而不能加X(jué)鎖,直到T釋放A上的S 鎖。這保證了其他事務(wù)可以讀表A,但在事務(wù)T釋放表A上的S鎖之前不能對(duì)表A做任何修改,總結(jié)起來(lái)就是:我讀的時(shí)候你不能寫;
3)什么是寫鎖
寫鎖:又稱排他鎖、X鎖。若事務(wù)T對(duì)表A加上X鎖,事務(wù)T可以讀表A也可以修改表A,其他事務(wù)不能再對(duì)表A加任何鎖,直到事務(wù)T釋放表A上的鎖。這保證了其他事務(wù)在事務(wù)T釋放表A上的鎖之前不能再讀取和修改表A,總結(jié)起來(lái)就是:我寫的時(shí)候,你不能讀,也不能寫。
實(shí)驗(yàn)一:我讀的時(shí)候你不能寫,但是你可以讀;
首先表company_info是myisam引擎的表;
事務(wù)1,執(zhí)行長(zhǎng)時(shí)間的查詢操作
mysql> select company_id from company_info where company_name like '%liluwedafasdf%';
Empty set (43.27 sec)
事務(wù)2,嘗試更新表company_info ,發(fā)現(xiàn)等待。。。執(zhí)行了21秒。
mysql>update company_info set company_name='liuhehhe' where company_id='4028809f60bf40fd0160bf4678be0000';
+----------------------------------+--------------+
| company_id | company_name |
+----------------------------------+--------------+
| 4028809f60bf40fd0160bf4678be0000 | liuhehhe |
+----------------------------------+--------------+
Query OK, 0 rows affected(21.98 sec)
Rows matched: 1 Changed: 0 Warnings: 0
再打開(kāi)一個(gè)窗口,可以看到,事務(wù)2確實(shí)在等待一個(gè)表級(jí)別的鎖:
mysql> show processlist;
+----+------+-----------+----------+---------+------+------------------------------+------------------------------------------------------------------------------------------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+------+-----------+----------+---------+------+------------------------------+------------------------------------------------------------------------------------------------------+
| 14 | root | localhost | liuwenhe | Sleep | 4506 | | NULL |
| 15 | root | localhost | liuwenhe | Query | 1 | Sending data | select company_id from company_info where company_name like '%liluwedafasdf%' |
| 16 | root | localhost | liuwenhe | Query | 1 |Waiting for table level lock| update company_info set company_name='liuhehhe' where company_id='4028809f60bf40fd0160bf4678be0000 |
| 17 | root | localhost | NULL | Query | 0 | init | show processlist |
+----+------+-----------+----------+---------+------+------------------------------+------------------------------------------------------------------------------------------------------+
4 rows in set (0.00 sec)
然后再開(kāi)啟一個(gè)窗口,執(zhí)行查詢操作(事務(wù)3):發(fā)現(xiàn)事務(wù)1還沒(méi)有執(zhí)行完,事務(wù)3就執(zhí)行完了,說(shuō)明事務(wù)1不會(huì)阻塞事務(wù)3;
mysql> select company_name from company_info where company_id='4028809f60bf40fd0160bf4678be0000';
+--------------+
| company_name |
+--------------+
| liuhehhe |
+--------------+
1 row in set (2.10 sec)
實(shí)驗(yàn)一證明:事務(wù)1對(duì)表A加上S鎖,則事務(wù)1可以讀表A但不能修改表A,其他事務(wù)只能再對(duì)表A加S鎖,而不能加X(jué)鎖,直到T釋放A上的S 鎖。也就是說(shuō)我讀的時(shí)候你不能寫,但是你可以讀;
實(shí)驗(yàn)二:我寫的時(shí)候,你不能讀,也不能寫;
事務(wù)1:執(zhí)行更新一個(gè)表的一個(gè)字段。
mysql> update company_info set company_name='liuhehhe' where company_name like '%liuwehe%';
Query OK, 0 rows affected (1.95 sec)
Rows matched: 0 Changed: 0 Warnings: 0
事務(wù)2嘗試查詢這個(gè)表,發(fā)現(xiàn)等待。。
mysql> select count(*) from company_info;
+----------+
| count(*) |
+----------+
| 1818708 |
+----------+
1 row in set (1.11 sec)
再開(kāi)啟一個(gè)窗口,查看進(jìn)程,發(fā)現(xiàn)事務(wù)2確實(shí)在等待一個(gè)表級(jí)別的鎖;
mysql> show processlist;
+----+------+-----------+----------+---------+------+------------------------------+----------------------------------------------------------------------------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+------+-----------+----------+---------+------+------------------------------+----------------------------------------------------------------------------------------+
| 19 | root | localhost | liuwenhe | Query | 1 | updating | update company_info set company_name='liuhehhe' where company_name like '%liuwehe%' |
| 20 | root | localhost | liuwenhe | Query | 1 |Waiting for table level lock| select count(*) from company_info |
| 21 | root | localhost | NULL | Query | 0 | init | show processlist |
+----+------+-----------+----------+---------+------+------------------------------+----------------------------------------------------------------------------------------+
3 rows in set (0.00 sec)
實(shí)驗(yàn)二證明:mysql的myisam引擎下,更新表的一行數(shù)據(jù),也會(huì)上一個(gè)表級(jí)別的鎖排他鎖,不允許其他事務(wù)讀取該表的數(shù)據(jù),當(dāng)然也不允許其他事務(wù)去寫這個(gè)表,也就是說(shuō):我寫的時(shí)候,你不能讀,也不能寫;
mysql myisam的鎖小結(jié):
MyISAM的讀操作和寫操作,以及寫操作之間是串行的!MyISAM在執(zhí)行讀寫操作的時(shí)候會(huì)自動(dòng)給表加相應(yīng)的鎖(也就是說(shuō)不用顯示的使用lock table命令,然后注意是表級(jí)別的鎖),MyISAM總是一次獲得SQL語(yǔ)句所需要的全部鎖,這也是MyISAM不會(huì)出現(xiàn)死鎖的原因.區(qū)別于mysql innodb的鎖機(jī)制,innodb的一般的select 是不會(huì)加任何鎖的,接下來(lái)會(huì)介紹innodb的鎖機(jī)制,請(qǐng)看下一篇文章
標(biāo)題名稱:mysqlmyisam的鎖機(jī)制
地址分享:
http://weahome.cn/article/ihoigi.html