MySQL进阶(四)

关于MySQL锁的机制。

锁的概念:锁机制用于管理对共享资源的并发访问,是数据库系统区别文件系统的关键特性。

通常,我们根据对数据操作的类型(读/写)或对数据操作的粒度(行/表)来对锁进行分类。

a、按类型分:

  • 读锁(共享锁):针对同一份数据,多个读操作可以同时进行而不会互相影响。
  • 写锁(排它锁):当前写操作没有完成前,它会阻断其他写锁和读锁。

b、按粒度分:

  • 行锁(偏写):操作时只锁某一行,不对其它行有影响。
  • 表锁(偏读):即使操作一条记录也会锁住整个表。

这里,我们主要了解行锁和表锁。

一、表锁

表锁的话,偏向MyISAM存储引擎,因为它开销小,加锁快;无死锁;锁定粒度大(针对表),发生锁冲突的概率最高,并发度最低。

了解表锁,在这里我们通过开启两个会话来了解,我们在会话一中开启锁或解除锁的机制。

首先,给出开启锁、解除锁以及显示所有锁的语法:

-- 给表添加读/写锁:
lock table 表名1 read, 表名2 write;

-- 释放表锁
unlock table 表名;

-- 显示库中所有表中锁的情况
show open tables;

-- 分析表锁定
-- 通过检查table_locks_waited和table_locks_immediate状态变量来分析系统上的表锁定:
show status like 'table%';

-- table_locks_immediate:产生表级锁定的次数,表示可以立即获得锁的查询次数,每立即获取锁,值加1
-- table_locks_waited:出现表级锁定争用而发生等待的次数(即不能立即获得锁的次数,每等待一次锁值
-- 加1),这个值高则说明存在着较严重的表级锁争用情况。

假定库中有mylock、book两张表:

了解表锁中的读锁特点:

                                   会话一                                         会话二
 

上锁后当前会话可以查询表中内容

其他会话同样可以查询上读锁后的内容

当前会话不能访问其他表

其他会话可以访问其他表

因为有读锁,当前会话不能对表进行增删改

其他会话增删改时会进入无限的等待。

释放表锁

释放的同时,该会话的任务完成。

了解表锁中的写锁特点:

会话一 会话二
 

当前会话不能访问未上锁的其他表。

其他会话可以访问未上锁的其他表。

 

当前会话对未上锁的其他表可以增删改

当前会话可以访问写锁的表内容

其他会话访问时进入无限的等待。

当前会话可以对写锁中内容进行增删查改

 

释放写锁

MySQL进阶(四)_第1张图片

与此同时,会话二的查询语句得到结果

简而言之,就是读锁会阻塞写,但是不会堵塞读,而写锁则会把读和写都堵塞。

二、行锁

行锁的话,偏向于InnoDB存储引擎,开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。(题外话:InnoDB与MyISAM的最大不同点在于支持事务和采用行锁)

首先,建立两张表:

-- 建表
create table if not exists innodb_lock(
a int (11),
b varchar(16)
)engine innodb charset utf8;

-- 插入数据
insert into innodb_lock
values
(1,'a2'),
(2,'2'),
(3,'hate'),
(4,'ugly'),
(5,'cute'),
(6,'6000'),
(7,'a1');

-- 建立索引
create index idx_innodb_a on innodb_lock(a); 
create index idx_innodb_b on innodb_lock(b); 


--手动开启行锁
begin;
select * from innodb_lock where a = 1 for update;
--针对该行数据的增删改操作
commit;

--行锁分析
show status like 'innodb_row_lock%';
-- innodb_row_lock_current_waits:当前正在等待锁定的数量
-- innodb_row_lock_time:系统启动到现在锁定总时间长度
-- innodb_row_lock_time_avg:每次等待所花的平均时间
-- innodb_row_lock_time_max:系统启动到现在等待最长的一次所花的时间
-- innodb_row_lock_waits:系统启动后到目前总共等待的次数

引擎innoDB,包含事务与行级锁,在事务中默认以分号为自动提交。

同样,我们开启两个会话来比较:

会话一 会话二

更新,但是没有提交

MySQL进阶(四)_第2张图片

此时,另一会话中查询结果无变化

手动提交

手动提交

 

MySQL进阶(四)_第3张图片

提交后查询,结果已经更新

会话更新,但未手动提交

另一会话更新同一行记录,进入无限的等待

手动提交

立即执行语句

 

 

MySQL进阶(四)_第4张图片

完成更新

两个会话更新不同行记录,不会发生阻塞,手动提交后执行

两个会话更新不同行记录,不会发生阻塞,手动提交后执行

索引失效,导致行锁升级为表锁

0行受影响,说明行锁已升级为表锁

注意项:

间隙锁:用范围条件检索数据,并请求共享或排它锁时,innoDB会给符合条件的已有数据记录的索引项加锁,对于键值在条件范围内但并不存在的记录,叫做“间隙(GAP)”,innoDB也会对这个“间隙”加锁,这种锁机制就是所谓的间隙锁(Next-key锁)。

间隙锁通常会带来危害:因为语句执行过程中通过范围查找时,会锁住整个范围内所有的索引键值,即使键值并不存在。

 

 

 

 

你可能感兴趣的:(MySQL进阶(四))