mysql鎖:是爲了防止多用戶操作同一塊數據出現問題的機制
(1)按照鎖的類型可以分爲讀鎖、寫鎖
(2)按照鎖的細粒度分可以分爲表鎖、行鎖
create table mylock(
id int not null primary key auto_increment,
name varchar(20)
)engine myisam;
insert into mylock(name)
values
('a'),('b'),('c'),('d'),('e');
查看有沒有表被上鎖:show open tables;
上鎖:lock table tab_name read/write;
解鎖:unlock tables;
讀鎖實例:
1.給mylock增加讀鎖
lock table mylock read;
然後在兩個mysql終端窗口中查看錶的內容信息都是可以正常操作的,由此得出:讀鎖是共享鎖。
2.在1的基礎上修改mylock的記錄發現並不能修改,同時也不能對其他表進行其他操作(包括讀寫)。
此時在其他session上只能對mylock表進行讀操作,不能進行寫操作,如果進行會導致阻塞該session直到釋放讀鎖。
但是可以對其他表進行read/write操作。
加鎖的session:
mysql> update mylock set name = 'a2' where id = 1;
ERROR 1099 (HY000): Table 'mylock' was locked with a READ lock and can't be updated
其他的session:
mysql> insert into stu(stu_name,stu_age) value('s',10);
Query OK, 1 row affected (0.14 sec)
mysql> update mylock set name = 'a2' where id = 1;(此處阻塞不動)
寫鎖實例:
1. 給mylock增加寫鎖
lock table mylock write;
mysql> select * from mylock;
+----+------+
| id | name |
+----+------+
| 1 | a2 |
| 2 | b |
| 3 | c |
| 4 | d |
| 5 | e |
+----+------+
5 rows in set (0.00 sec)
mysql> update mylock set name = 'a4' where id = 4;
Query OK, 1 row affected (0.84 sec)
然後在加鎖的session裏可以對mylock進行讀寫操作,但是不能對其他表進行讀寫操作;
在其他的session裏不能對mylock表進行讀寫操作,但可以對其他表進行讀寫操作。
在MyISAM引擎下,對錶進行讀操作時會自動給表增加讀鎖,對錶進行修改操作時會自動給表增加寫鎖。
簡而言之,讀鎖會阻塞寫但不會阻塞讀操作。寫鎖會阻塞讀寫操作。
行鎖:是Innodb默認的鎖,開銷大,加鎖慢,可能會出現死鎖。
鎖的力度最小併發度最高。
Innodb和MyISAM的最大不同有兩點:支持事務;採用行級鎖。
實例:
create table innodb_lock
(
a int,
b varchar(16)
)engine = innodb;
insert into innodb_lock values
(1,'a1'),
(2,'a3'),
(3,'a3'),
(4,'a4'),
(5,'a5'),
(6,'a6');
create index idx_a on innodb_lock(a);
create index idx_b on innodb_lock(b);
在兩個session(A,B)終端設置set autocommit = 0;
此時在A中修改了innodb_lock的記錄,在A中查看可能看到修改後的數據,但是在B中看到的還是未修改的數據。
注意A和B修改的不是同一條記錄。因爲innodb支持事務,因此這是正常的。只有在A中執行commit,B中才能看到修改後的數據
但是如果在A中修改了第一條記錄,卻未執行commit,然後在B中也修改第一條記錄,則B會阻塞。
innodb下索引使用不當會導致:導致行鎖升級爲表鎖。
這個大家在關閉autocommit的前提下,在索引列上查找時故意使用強制類型轉化即可看到效果。
如何鎖定一行:
(1)關閉自動提交
(2)使用update更新表的記錄,在原有語句前增加for update,如:
update innodb_lock set b = 'xxx' where a = 4 for update;
此時如果在別的終端操作第四行記錄會被阻塞,直到在本終端執行commit;