MySql锁机制(全网最全、最详细、最清晰)

1、MySql锁机制

锁机制的作用:

解决因为资源共享,而造成的并发问题。

没有锁机制时:

例如一号用户和二号用户都要去买同一件商品(假如这件商品是一件衣服),一号用户手速稍微快了一些,于是就先买到了这件衣服,但是因为没有“锁机制”,于是就造成了二号用户不知道这件衣服已经被人买了,所以就造成了“并发问题”。

有锁机制时:

但是有了“锁机制”,一号用户在买了衣服之后就会“对衣服进行加锁”,二号用户看到“衣服被加锁了”,于是就去“等待着衣服被解锁”。

在“衣服未被解锁”的过程中,衣服则会被一号用户进行“试穿”、“下单”、“付款”、“打包”、或者“不满意,取消订单”一系列的操作,这一系列操作之后“衣服会被解锁”。

如果一号用户这边觉得衣服还行打算买下来,在买完之后“衣服就会被解锁”,二号用户这边看到“衣服被解锁了”就会去查看衣服是否还存在,很明显已经不存在了,因为一号用户已经把衣服买了,如果一号用户“不满意,取消订单”,那么二号用户这边就可以购买这件衣服。

因此通过锁机制就很好的解决了买衣服造成的并发问题。

2、MySql锁的分类

按照“操作类型”分:

1、读锁(也叫“共享锁”):

对同一个数据(衣服),多个读操作可以同时进行,互不干扰。

2、写锁(也叫“互斥锁”)

如果当前写操作没有完毕(买衣服的一系列操作),则无法进行其他的读操作、写操作。

按照“操作范围”分:

1、表锁 :

一次性对一张表整体加锁。如MyISAM存储引擎使用表锁,开销小、加锁快;无死锁;但锁的范围大,容易发生锁冲突、并发度低。

2、行锁(与表锁的特性完全相反):

一次性对一条数据加锁。如InnoDB存储引擎使用行锁,开销大,加锁慢;容易出现死锁;锁的范围较小,不易发生锁冲突,并发度高(很小概率发生高并发问题:脏读、幻读、不可重复度、丢失更新等问题)。

3、页锁(几乎遇不见)

页锁的开销介于表锁和行锁之间,会出现死锁。锁定粒度介于表锁和行锁之间,并发度一般。

3、MySql表锁示例

准备工作:

1、创建两张表,表table和表lock

create table tab(
id int primary key auto_increment , 
name varchar(20)
)engine myisam;
insert into tab(name) values('tab1');
insert into tab(name) values('tab2');
insert into tab(name) values('tab3');
insert into tab(name) values('tab4');
insert into tab(name) values('tab5');
create table locktab(
id int primary key auto_increment , 
name varchar(20)
)engine myisam;
insert into locktab(name) values('locktab1');
insert into locktab(name) values('locktab2');
insert into locktab(name) values('locktab3');
insert into locktab(name) values('locktab4');
insert into locktab(name) values('locktab5');

2、再新建两个会话

加锁相关命令:

1、增加锁:

lock table 表1 read/write,表2 read/write,...;

2、释放锁:

unlock tables;

3、查看加锁的表:

show open tables;

加读锁(也叫“共享锁”):

会话192.168.11.101(1):

给表locktab加读锁:

lock table locktab read;
select * from locktab; --执行读操作(查),可以

delete from locktab where id =1; --执行写操作(增删改),不可以

操作没有加锁的表tab:

select * from tab; --读操作,不可以
delete from tab where id = 1; --写操作,不可以

结论:

1、如果某一个会话对A表加了read锁,则该会话可以对A表进行读操作、不能进行写操作;且该会话不能对其他表进行读、写操作。

2、即如果给A表加了读锁,则当前会话只能对A表进行读操作。

会话192.168.11.101(2),也就是其它会话:

操作加锁了的表locktab:

select * from locktab; --读操作(查),可以

delete from locktab where id =1; --写操作,会“等待”会话192.168.11.101(1)将锁释放

操作没有加锁的表tab:

select * from tab;  --读操作(查),可以
delete from tab where id = 1; --写操作(增删改),可以

再来在“会话192.168.11.101(1)”中把锁释放了,看看“delete from locktab where id =1;”是否会释放阻塞:

总结:

“会话192.168.11.101(1)”给表locktab加了锁,其他会话的操作:

1、可以对其他表(表locktab以外的表)进行读、写操作。

2、对表locktab:读操作可以,写操作需要等待释放锁。

加写锁(也叫“互斥锁”):

会话192.168.11.101(1):

给表locktab加读锁:

lock table locktab write;
select * from locktab; --读操作,可以
delete from locktab where id = 5; --写操作,可以

操作没有加锁的表tab:

select * from tab; --读操作,不可以
delete from tab where id = 3; --写操作,不可以

总结:

当前会话(会话192.168.11.101(1))可以对加了写锁的表进行任何操作(增删改查),但是不能操作(增删改查)其他表。

会话192.168.11.101(2):

操作加锁了的表locktab:

select * from locktab; --写操作,会阻塞

delete from locktab where id = 2; --写操作,也会阻塞

对“会话192.168.11.101(2)”中加写锁的表可以进行增删改查的前提是:等待“会话192.168.11.101(1)”释放写锁。

操作没加锁的表tab:

select * from tab; --读操作,可以
delete from tab where id = 2; --写操作,可以

MySQL表级锁的锁模式:

MyISAM在执行查询语句(SELECT)前,会自动给涉及的所有表加读锁,在执行更新操作(DML)前,会自动给涉及的表加写锁。

所以对MyISAM表进行操作,会有以下情况:

1、对MyISAM表的读操作(加读锁),不会阻塞其他进程(会话)对同一表的读请求,但会阻塞对同一表的写请求。只有当读锁释放后,才会执行其它进程的写操作。

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

分析表锁定:

查看哪些表加了锁:

show open tables

1代表被加了锁

分析表锁定的严重程度:

show status like 'table%';

Table_locks_immediate:即可能获取到的锁数。

Table_locks_waited:需要等待的表锁数(如果该值越大,说明存在越大的锁竞争)。

一般建议:

Table_locks_immediate/Table_locks_waited > 5000, 建议采用InnoDB引擎,否则MyISAM引擎。

4、MySql行锁示例

准备工作:

unlock tables; --需要先释放之前加的表锁
create table linelock(
id int(5) primary key auto_increment,
name varchar(20)
)engine=innodb ;
insert into linelock(name) values('1');
insert into linelock(name) values('2');
insert into linelock(name) values('3');
insert into linelock(name) values('4');
insert into linelock(name) values('5');

为了研究行锁,暂时将自动commit关闭,“set autocommit = 0;”,以后需要通过“commit”关键字提交写操作:

set autocommit = 0;

mysql默认自动commit,oracle默认不会自动commit。

行锁,操作同一条数据:

会话192.168.11.101(1):写操作

insert into linelock values(6,'a6');

会话192.168.11.101(2):写操作,同样的数据

update linelock set name='ax' where id = 6;

总结:

1、如果会话x对某条数据a进行DML操作(研究时:关闭了自动commit的情况下),则其他会话必须等待会话x结束事务(commit/rollback)后,才能对数据a进行操作。

2、表锁是通过unlock tables,也可以通过事务解锁;行锁是通过事务解锁。

行锁,操作不同数据:

会话192.168.11.101(1): 写操作

insert into linelock values(8,'a8');

会话192.168.11.101(2): 写操作,不同的数据

update linelock set name='ax' where id = 5;

总结:

行锁,一次锁一行数据;因此如果操作的是不同数据,则不干扰。

行锁的注意事项:

1、如果没有索引,则行锁会转为表锁

先给字段“name”加个索引:

show index from linelock;

可以看到有一条索引,这是主键索引,建表创建主键的时候自动加的。

这是mysql的基础,无论是创建主键还是外键都会自动创建主键索引或外键索引。

给name加个索引:

alter table linelock add index idx_linelock_name(name);

会话192.168.11.101(1): 写操作

update linelock set name = 'ai' where name = '3';

会话192.168.11.101(2): 写操作,不同的数据

update linelock set name = 'aiX' where name = '4';

可以看到在索引没有失效的情况下所有会话都可以对数据进行写操作。

会话192.168.11.101(1): 写操作

update linelock set name = 'ai' where name = 3;

会话192.168.11.101(2): 写操作,不同的数据

update linelock set name = 'aiX' where name = 4;

可以发现,数据被阻塞了(加锁)。

原因:如果索引列发生了类型转换,则索引失效。 因此此次操作,会从行锁转为表锁。

2、行锁的一种特殊情况:间隙锁:值在范围内,但却不存在。

此时linelock表中 没有id=7的数据:

“update linelock set name ='x' where id >1 and id<9;”即在此where范围中,没有id=7的数据,则id=7的数据成为间隙。

间隙:Mysql会自动给间隙加锁(间隙锁)。即会自动给id=7的数据加间隙锁(行锁)。

行锁:如果有where,则实际加锁的范围就是where后面的范围(不是实际的值)。

如果仅仅是查询数据,能否加锁? 可以使用for update:

select * from linelock where id =2 for update;

通过for update对query语句进行加锁。

mysql中,以下三种方式都可以将自动提交关闭:

set autocommit =0;
start transaction;
begin;

行锁:

InnoDB默认采用行锁。

缺点:

比表锁性能损耗大。

优点:

并发能力强,效率高。

因此建议,高并发用InnoDB,否则用MyISAM。

行锁分析:

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:等待次数。从系统启动到现在一共等待的次数。

  • 6
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
OpenStack是一种开源的云计算管理平台,它提供了一整套的云计算基础设施服务,包括计算、网络、存储、身份认证等。在实践中,OpenStack的安装通常包括以下几个主要步骤。 首先,准备环境。在安装OpenStack之前,需要确保所使用的服务器满足一定的硬件要求,并且已经正确安装了操作系统。通常推荐使用Ubuntu Server或CentOS等Linux发行版作为操作系统。 接下来,安装依赖软件。OpenStack运行需要一些其他的软件支持,如MySQL数据库、RabbitMQ消息队列中间件、Keystone身份认证服务等。这些软件可以通过包管理工具进行安装,比如apt-get或yum。 然后,安装OpenStack组件。OpenStack由多个组件组成,包括Nova计算服务、Neutron网络服务、Cinder块存储服务等。一般来说,可以使用apt-get或yum命令来安装这些组件。需要注意的是,不同的组件可能需要不同的配置文件和参数设置。 安装完成后,需要对OpenStack进行配置。配置涉及到的内容很多,包括网络配置、存储配置、身份认证配置等。这些配置可以通过修改相应的配置文件来完成,比如nova.conf、neutron.conf等。 最后,启动和测试OpenStack服务。启动过程中,需要确保各个组件的服务正常运行,并且没有错误信息输出。为了测试OpenStack安装是否成功,可以使用一些命令行工具或者图形界面来创建虚拟机、网络等资源,并进行相应的操作和管理。 总结来说,全网最全OpenStack的安装涉及到环境准备、依赖软件安装、OpenStack组件安装、配置和启动、测试等步骤。在实践中,可以参考OpenStack官方文档、社区论坛或者一些专业的安装指南来帮助完成安装过程。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值