大家都知道java里面的synchronized,對象鎖。(這里不扯什么類鎖,對象鎖,類鎖其實(shí)就是Class對象的對象鎖)
A線程拿o對象的鎖之后,其他的線程訪問o對象的鎖都需等待。
那MySQL的表鎖就是針對于表的。(行鎖就是行的唄)
MySQL鎖是啥?
鎖顧名思義,解決因資源共享,而造成的并發(fā)問題。
1,表鎖
MyISAM 存儲引擎默認(rèn)為表鎖。不想解釋太多上例子大家都懂了。
第一個客戶端,為了好舉例子先開一個事務(wù),不然看不到效果,然后修改job表,修改完之后先不提交,看第二個客戶端。
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> update job set jobName= 'Java開發(fā)工程師' where jobName = 'Java開發(fā)工程師';
Query OK, 0 rows affected (0.28 sec)
Rows matched: 3872 Changed: 0 Warnings: 0
mysql>
第二個客戶端,依然修改這個表,一樣的執(zhí)行一個update語句,發(fā)現(xiàn)這個時候卡住不動了?
不要以為你dos卡了??,這個時候是你的第一個客戶端獲取了job 表的鎖,但是并沒有提交事務(wù)也就是沒有釋放鎖所導(dǎo)致的
mysql> update job set jobName = '.net工程師' where jobName = '.net工程師';
........等待中
那么接下來給一個客戶端commit 試試。
mysql> update job set jobName = '.net工程師' where jobName = '.net工程師';
Query OK, 0 rows affected (33.14 sec)
Rows matched: 1286 Changed: 0 Warnings: 0
這時候看到了吧,你的第一個客戶端一提交事務(wù),你的第二個客戶端馬上執(zhí)行成功了,這個時候就是你的第一個客戶端釋放鎖之后,第二個客戶端就拿到鎖去執(zhí)行語句啦,這樣就非常好理解啦。
2,行鎖
InnoDB 默認(rèn)使用行鎖,既然知道了表鎖,那么行鎖的概念也很好理解,粒度更加細(xì)的一個鎖。
行鎖的一個大前提需要知道的就是對于行的條件必須是索引列,如果不是索引列則上升為表鎖(劃重點(diǎn))
那么也舉一個例子同上
先是修改job 表的某條數(shù)據(jù),首先你的serialNo必須是索引列,否則會上升為表鎖
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> update job set serialNo = '116004626' where serialNo = '116004626';
Query OK, 0 rows affected (0.00 sec)
Rows matched: 1 Changed: 0 Warnings: 0
mysql>
繼續(xù)第二個客戶端看
mysql> update job set serialNo = '116004626' where serialNo = '116004627';
Query OK, 0 rows affected (0.00 sec)
Rows matched: 0 Changed: 0 Warnings: 0
mysql>
這時候看,其實(shí)行鎖已經(jīng)生效了,因?yàn)槲业诙€客戶端和第一個客戶端修改的同一張表,但第二個客戶端并沒有進(jìn)入等待。
說明第一個客戶端只在 serialNo = '116004626' 這條記錄上加鎖了。
那么繼續(xù)看如果我們在第二個客戶端繼續(xù)修改serialNo = '116004626' 這條記錄,會怎么樣?
mysql> update job set serialNo = '116004626' where serialNo = '116004626';
........等待中
可以看到情況跟上面表鎖是一樣的。進(jìn)入等待了,這時候我們依然繼續(xù)commit第一個客戶端的事務(wù)
mysql> update job set serialNo = '116004626' where serialNo = '116004626';
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql> update job set serialNo = '116004626' where serialNo = '116004626';
Query OK, 0 rows affected (0.00 sec)
??不好意思超時了,重新執(zhí)行一下可以看到成功了,雖然超時了但是也是在commit 之后出現(xiàn)的,只要第一個客戶端的事務(wù)不提交那么其他客戶端對這條數(shù)據(jù)的寫操作都會進(jìn)行等待。