MySQL锁机制

Posted 与君共舞

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL锁机制相关的知识,希望对你有一定的参考价值。

一、锁的分类

对数据操作的类型:读锁(共享锁)、写锁(排它锁)

对数据操作对粒度:表锁、行锁

lock table mylock read,tbl_dept write; #手动增加表锁
show open tables; #查看表上加过的锁
unlock tables; #解锁
 
show status like \'table%\';  #分析系统表锁定
#Table_locks_immediate  产生表级锁定的次数   
#Table_locks_waited表级锁定争用而发生的等待次数,此值很高,说明存在严重的表级锁争用情况  

二、表锁(偏读)

特点:偏向MyISAM存储引擎,开销小,加锁快,无死锁,锁定粒度大,发生锁冲突的概率最高,并发度最低。

MyISAM在执行查询语句前,会自动给涉及的所有表加读锁,在执行增删改操作前,会自动给涉及的表加写锁。

对MyISAM表加读锁,不会阻塞其他进程对同一表的读请求,但会阻塞对同一表的写请求,读锁释放才会执行其他进程的写操作

对MyISAM表加写锁,会阻塞其他进程对同一表的读和写操作,只有当写锁释放,才会执行其他的进程的读写操作。

读锁会阻塞写,但不会阻塞读,写锁则会阻塞读和写

建表语句

create table mylock(
id int not null primary key auto_increment,
name varchar(20)
)engine myisam;

insert into mylock(name) values(\'a\');
insert into mylock(name) values(\'b\');
insert into mylock(name) values(\'c\');
insert into mylock(name) values(\'d\');
insert into mylock(name) values(\'e\');

select * from mylock;  

 

三、行锁(偏写)

特点:偏向InnoDB存储引擎,开销大,加锁慢,会出现死锁,锁定粒度最小,发生锁冲突的概率最低,并发度也最高。

InnoDB:支持事务,采用了行级锁 

建表语句

CREATE TABLE test_innodb_lock(
a int(11),
b VARCHAR(16)
)ENGINE=INNODB;

INSERT INTO test_innodb_lock VALUES(1,\'b2\');
INSERT INTO test_innodb_lock VALUES(3,\'3\');
INSERT INTO test_innodb_lock VALUES(4,\'4000\');
INSERT INTO test_innodb_lock VALUES(5,\'5000\');
INSERT INTO test_innodb_lock VALUES(6,\'6000\');
INSERT INTO test_innodb_lock VALUES(7,\'7000\');
INSERT INTO test_innodb_lock VALUES(8,\'8000\');
INSERT INTO test_innodb_lock VALUES(9,\'90000\');
INSERT INTO test_innodb_lock VALUES(1,\'b1\');

CREATE INDEX idx_test_innodb_a ON test_innodb_lock(a);
CREATE INDEX idx_test_innodb_b ON test_innodb_lock(b);

SELECT * from test_innodb_lock;

1、行锁定基本演示

session_01session_02

关闭事务自动提交 

set autocommit=0;

关闭事务自动提交 

set autocommit=0;

UPDATE test_innodb_lock SET b=\'4001\' WHERE a=4;  
select * from test_innodb_lock

事务未提交,看到4000

select * from test_innodb_lock

事务提交 commit;

事务提交 commit;
select * from test_innodb_lock select * from test_innodb_lock
UPDATE test_innodb_lock SET b=\'4002\' WHERE a=4;

 操作同一行,存在行锁,被阻塞

UPDATE test_innodb_lock SET b=\'4003\' WHERE a=4;

UPDATE test_innodb_lock SET b=\'4005\' WHERE a=4;

 操作不同行,不存在行锁,正常执行

UPDATE test_innodb_lock SET b=\'90001\' WHERE a=9;

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2、无索引行锁升级为表锁

session_01 session_02
UPDATE test_innodb_lock SET a=41 WHERE b=4000;

更新不同的行操作被阻塞

UPDATE test_innodb_lock SET b=\'90001\' WHERE a=9;

 

 

 

 

 

3、什么是间隙锁:

当用范围条件而不是相等条件检索数据,并请求共享或排他锁,InnoDB会给符合条件的已有数据记录的索引项加锁。

对于键值在条件范围内但并不存在的记录,叫做“间隙”。

session_01 session_02
UPDATE test_innodb_lock SET b= ‘0629’ WHERE a>1 and a<6;

新增操作被阻塞

INSERT INTO test_innodb_lock values (2,\'2000\');

 

 

 

 

 

4、如何锁定一行?

session_01 session_02

BEGIN;

SELECT * from test_innodb_lock where a=8 for UPDATE;

更新操作被阻塞

UPDATE test_innodb_lock set b=\'1000\' where a=8;

COMMIT;  

 

 

 

 

 

 

5、行锁分析

show status like \'innodb_row_lock%\';
#Innodb_row_lock_current_waits:当前正在等待锁定的数量
#Innodb_row_lock_waits:等待总次数
#Innodb_row_lock_time:等待总时长
#Innodb_row_lock_time_avg:等待平均时长

四、页锁(了解)

开销和加锁时间介于表锁和行锁之间,

会出现死锁

锁定粒度介于表锁和行锁之间,并发度一般 

 

以上是关于MySQL锁机制的主要内容,如果未能解决你的问题,请参考以下文章

Mysql的锁机制与PHP文件锁处理高并发简单思路

Mysql的锁机制与PHP文件锁处理高并发简单思路

mysql 锁机制

mysql锁机制详解

MySQL锁机制

MySQL InnoDB锁机制