mysql-----鎖

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;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章