数据库高级知识——MySql锁机制

文章目录

    • 1.概述
      • 1.1 定义
      • 1.2 锁的分类
    • 2.三锁
      • 2.1 表锁(偏读)
      • 2.2 行锁(偏写)
      • 2.3 页锁

1.概述

1.1 定义

 锁是计算机协调多个进程或线程并发访问某一资源的机制。在数据库中,除传统的计算资源(如CPU、RAM、I/O等)的争用以外,数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性、有效性是所有数据库必须解决的一个问题,锁冲突也是影响数据库并发访问性能的一个重要因素。从这个角度来说,锁对数据库而言显得尤其重要,也更加复杂。

1.2 锁的分类

从对数据操作的类型(读\写)分:

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

从对数据操作的粒度分:

为了尽可能提高数据库的并发度,每次锁定的数据范围越小越好,
理论上每次只锁定当前操作的数据的方案会得到最大的并发度,
但是管理锁是很耗资源的事情(涉及获取,检查,释放锁等动作),
因此数据库系统需要在高并发响应和系统性能两方面进行平衡,
这样就产生了“锁粒度(Lock granularity)”的概念。一种提高共享资源并发发性的方式是让锁定对象更有选择性。
尽量只锁定需要修改的部分数据,而不是所有的资源。
更理想的方式是,只对会修改的数据片进行精确的锁定。
任何时候,在给定的资源上,锁定的数据量越少,则系统的并发程度越高,只要相互之间不发生冲突即可。

表锁
行锁

2.三锁

2.1 表锁(偏读)

1.特点

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

2.案例分析

【表级锁分析--建表SQL】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;【手动增加表锁】lock table 表名字1 read(write),表名字2 read(write),其它;
【查看表上加过的锁】
show open tables;【释放表锁】
unlock tables;

3.结论

MyISAM在执行查询语句(SELECT)前,会自动给涉及的所有表加读锁,
在执行增删改操作前,会自动给涉及的表加写锁。 MySQL的表级锁有两种模式:表共享读锁(Table Read Lock)表独占写锁(Table Write Lock)
锁类型他人可读他人可写
读锁
写锁
结论:
结合上表,所以对MyISAM表进行操作,会有以下情况: 1、对MyISAM表的读操作(加读锁),不会阻塞其他进程对同一表的读请求,但会阻塞对同一表的写请求。只有当读锁释放后,才会执行其它进程的写操作。 2、对MyISAM表的写操作(加写锁),会阻塞其他进程对同一表的读和写操作,只有当写锁释放后,才会执行其它进程的读写操作。
简而言之,就是读锁会阻塞写,但是不会堵塞读。而写锁则会把读和写都堵塞

2.2 行锁(偏写)

1.特点

偏向InnoDB存储引擎,开销大,加锁慢;
会出现死锁;
锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
InnoDB与MyISAM的最大不同有两点:一是支持事务(TRANSACTION);二是采用了行级锁

2.由于行锁支持事务,复习老知识

事务笔记

事务(Transaction)及其ACID属性

事务是由一组SQL语句组成的逻辑处理单元,事务具有以下4个属性,通常简称为事务的ACID属性。 
l 原子性(Atomicity):
事务是一个原子操作单元,其对数据的修改,要么全都执行,要么全都不执行。 l 一致性(Consistent):
在事务开始和完成时,数据都必须保持一致状态。
这意味着所有相关的数据规则都必须应用于事务的修改,以保持数据的完整性;
事务结束时,所有的内部数据结构(如B树索引或双向链表)也都必须是正确的。 l 隔离性(Isolation):
数据库系统提供一定的隔离机制,
保证事务在不受外部并发操作影响的“独立”环境执行。
这意味着事务处理过程中的中间状态对外部是不可见的,反之亦然。l 持久性(Durable):
事务完成之后,它对于数据的修改是永久性的,即使出现系统故障也能够保持。 

并发事务处理带来的问题

更新丢失(Lost Update)

当两个或多个事务选择同一行,然后基于最初选定的值更新该行时,
由于每个事务都不知道其他事务的存在,就会发生丢失更新问题--最后的更新覆盖了由其他事务所做的更新。例如,两个程序员修改同一java文件。每程序员独立地更改其副本,然后保存更改后的副本,
这样就覆盖了原始文档。最后保存其更改副本的编辑人员覆盖前一个程序员所做的更改。如果在一个程序员完成并提交事务之前,另一个程序员不能访问同一文件,则可避免此问题。 

脏读(Dirty Reads)

一个事务正在对一条记录做修改,在这个事务完成并提交前,这条记录的数据就处于不一致状态;
这时,另一个事务也来读取同一条记录,如果不加控制,
第二个事务读取了这些“脏”数据,并据此做进一步的处理,就会产生未提交的数据依赖关系。
这种现象被形象地叫做”脏读”。 一句话:事务A读取到了事务B已修改但尚未提交的的数据,还在这个数据基础上做了操作。
此时,如果B事务回滚,A读取的数据无效,不符合一致性要求。

不可重复读(Non-Repeatable Reads)

在一个事务内,多次读同一个数据。
在这个事务还没有结束时,另一个事务也访问该同一数据。
那么,在第一个事务的两次读数据之间。
由于第二个事务的修改,那么第一个事务读到的数据可能不一样,
这样就发生了在一个事务内两次读到的数据是不一样的,因此称为不可重复读,即原始读取不可重复。一句话:一个事务范围内两个相同的查询却返回了不同数据。

幻读(Phantom Reads)

 一个事务按相同的查询条件重新读取以前检索过的数据,却发现其他事务插入了满足其查询条件的新数据,这种现象就称为“幻读”。一句话:事务A 读取到了事务B提交的新增数据,不符合隔离性。 

事务隔离级别

脏读”、“不可重复读”和“幻读”,其实都是数据库读一致性问题,必须由数据库提供一定的事务隔离机制来解决。

在这里插入图片描述

数据库的事务隔离越严格,并发副作用越小,但付出的代价也就越大,
因为事务隔离实质上就是使事务在一定程度上 “串行化”进行,这显然与“并发”是矛盾的。
同时,不同的应用对读一致性和事务隔离程度的要求也是不同的,
比如许多应用对“不可重复读”和“幻读”并不敏感,可能更关心数据并发访问的能力。 常看当前数据库的事务隔离级别:show variables like 'transaction_isolation';
mysql> show variables like 'transaction_isolation';
+-----------------------+-----------------+
| Variable_name         | Value           |
+-----------------------+-----------------+
| transaction_isolation | REPEATABLE-READ |
+-----------------------+-----------------+
1 row in set (0.01 sec)

3.案例分析

建表SQL

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,'9000');
insert into test_innodb_lock values(1,'b1');create index test_innodb_a_ind on test_innodb_lock(a);create index test_innodb_lock_b_ind on test_innodb_lock(b);select * from test_innodb_lock;

行锁定基本演示

查看时候自动提交:

mysql> show variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit    | ON    |
+---------------+-------+
1 row in set (0.01 sec)

窗口1:

mysql> set autocommit=0;
Query OK, 0 rows affected (0.03 sec)

窗口2:

mysql> set autocommit=0;
Query OK, 0 rows affected (0.03 sec)

窗口1:

mysql> select * from test_innodb_lock;
+------+------+
| a    | b    |
+------+------+
|    1 | b2   |
|    3 | 3    |
|    4 | 4000 |
|    5 | 5000 |
|    6 | 6000 |
|    7 | 7000 |
|    8 | 8000 |
|    9 | 9000 |
|    1 | b1   |
+------+------+
9 rows in set (0.00 sec)mysql> update test_innodb_lock set b="4001" where a=4;
Query OK, 1 row affected (0.02 sec)
Rows matched: 1  Changed: 1  Warnings: 0mysql> select * from test_innodb_lock;
+------+------+
| a    | b    |
+------+------+
|    1 | b2   |
|    3 | 3    |
|    4 | 4001 |
|    5 | 5000 |
|    6 | 6000 |
|    7 | 7000 |
|    8 | 8000 |
|    9 | 9000 |
|    1 | b1   |
+------+------+
9 rows in set (0.00 sec)

窗口2:

mysql> select * from test_innodb_lock;
+------+------+
| a    | b    |
+------+------+
|    1 | b2   |
|    3 | 3    |
|    4 | 4000 |
|    5 | 5000 |
|    6 | 6000 |
|    7 | 7000 |
|    8 | 8000 |
|    9 | 9000 |
|    1 | b1   |
+------+------+
9 rows in set (0.00 sec)

窗口1:

mysql> commit;
Query OK, 0 rows affected (0.07 sec)

窗口2:

mysql> select * from test_innodb_lock;
+------+------+
| a    | b    |
+------+------+
|    1 | b2   |
|    3 | 3    |
|    4 | 4000 |
|    5 | 5000 |
|    6 | 6000 |
|    7 | 7000 |
|    8 | 8000 |
|    9 | 9000 |
|    1 | b1   |
+------+------+
9 rows in set (0.00 sec)mysql> commit;
Query OK, 0 rows affected (0.00 sec)mysql> select * from test_innodb_lock;
+------+------+
| a    | b    |
+------+------+
|    1 | b2   |
|    3 | 3    |
|    4 | 4001 |
|    5 | 5000 |
|    6 | 6000 |
|    7 | 7000 |
|    8 | 8000 |
|    9 | 9000 |
|    1 | b1   |
+------+------+
9 rows in set (0.00 sec)

无索引行锁升级为表锁

Select也可以加锁

读锁:

共享锁(Share Lock)共享锁又称读锁,是读取操作创建的锁。其他用户可以并发读取数据,
但任何事务都不能对数据进行修改(获取数据上的排他锁),直到已释放所有共享锁。
如果事务T对数据A加上共享锁后,则其他事务只能对A再加共享锁,不能加排他锁。
获准共享锁的事务只能读数据,不能修改数据。用法
SELECT ... LOCK IN SHARE MODE;在查询语句后面增加 LOCK IN SHARE MODE ,
Mysql会对查询结果中的每行都加共享锁,
当没有其他线程对查询结果集中的任何一行使用排他锁时,可以成功申请共享锁,否则会被阻塞。
其他线程也可以读取使用了共享锁的表(行?),而且这些线程读取的是同一个版本的数据。

写锁:

排他锁(eXclusive Lock)共享锁又称写锁,如果事务T对数据A加上排他锁后,则其他事务不能再对A加任任何类型的封锁。
获准排他锁的事务既能读数据,又能修改数据。用法
SELECT ... FOR UPDATE;在查询语句后面增加 FOR UPDATE ,Mysql会对查询结果中的每行都加排他锁,
当没有其他线程对查询结果集中的任何一行使用排他锁时,可以成功申请排他锁,否则会被阻塞。

间隙锁危害

【什么是间隙锁】
当我们用范围条件而不是相等条件检索数据,并请求共享或排他锁时,
InnoDB会给符合条件的已有数据记录的索引项加锁;
对于键值在条件范围内但并不存在的记录,叫做“间隙(GAP)”,
InnoDB也会对这个“间隙”加锁,这种锁机制就是所谓的间隙锁(GAP Lock)。【危害】
因为Query执行过程中通过过范围查找的话,他会锁定整个范围内所有的索引键值,即使这个键值并不存在。
间隙锁有一个比较致命的弱点,就是当锁定一个范围键值之后,即使某些不存在的键值也会被无辜的锁定,
而造成在锁定的时候无法插入锁定键值范围内的任何数据。在某些场景下这可能会对性能造成很大的危害

4.案列结论

Innodb存储引擎由于实现了行级锁定,
虽然在锁定机制的实现方面所带来的性能损耗可能比表级锁定会要更高一些,
但是在整体并发处理能力方面要远远优于MyISAM的表级锁定的。
当系统并发量较高的时候,Innodb的整体性能和MyISAM相比就会有比较明显的优势了。但是,Innodb的行级锁定同样也有其脆弱的一面,当我们使用不当的时候,可能会让Innodb的整体性能表现不仅不能比MyISAM高,甚至可能会更差。

5.行锁分析

【如何分析行锁定】
通过检查InnoDB_row_lock状态变量来分析系统上的行锁的争夺情况
mysql> show status like 'innodb_row_lock%';
+-------------------------------+-------+
| Variable_name                 | Value |
+-------------------------------+-------+
| Innodb_row_lock_current_waits | 0     |
| Innodb_row_lock_time          | 0     |
| Innodb_row_lock_time_avg      | 0     |
| Innodb_row_lock_time_max      | 0     |
| Innodb_row_lock_waits         | 0     |
+-------------------------------+-------+
5 rows in set (0.00 sec)对各个状态量的说明如下:Innodb_row_lock_current_waits:当前正在等待锁定的数量;
Innodb_row_lock_time:从系统启动到现在锁定总时间长度;
Innodb_row_lock_time_avg:每次等待所花平均时间;
Innodb_row_lock_time_max:从系统启动到现在等待最常的一次所花的时间;
Innodb_row_lock_waits:系统启动后到现在总共等待的次数;对于这5个状态变量,比较重要的主要是Innodb_row_lock_time_avg(等待平均时长),Innodb_row_lock_waits(等待总次数)Innodb_row_lock_time(等待总时长)这三项。
尤其是当等待次数很高,而且每次等待时长也不小的时候,
我们就需要分析系统中为什么会有如此多的等待,然后根据分析结果着手指定优化计划。最后可以通过
SELECT * FROM information_schema.INNODB_TRX\G;
来查询正在被锁阻塞的sql语句。

6.优化建议

尽可能让所有数据检索都通过索引来完成,避免无索引行锁升级为表锁。
尽可能较少检索条件,避免间隙锁
尽量控制事务大小,减少锁定资源量和时间长度
锁住某行后,尽量不要去调别的行或表,赶紧处理被锁住的行然后释放掉锁。
涉及相同表的事务,对于调用表的顺序尽量保持一致。
在业务环境允许的情况下,尽可能低级别事务隔离

2.3 页锁

开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/483126.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

最早的神经元从何而来?海绵基因图谱揭示神经系统起源

来源: 集智俱乐部作者:Viviane Callier译者:陈斯信 审校:梁金 编辑:邓一雪 导语海绵是动物生命演化树上最早的分支谱系之一,它们身体构造简单,却拥有许多与人类和其它复杂生物相同的基因。11月…

数据库高级知识——主从复制

文章目录1.复制的基本原理1.1 复制的原理和步骤2.复制的基本原则3.复制的最大问题4.一主一从常见配置4.1 主机修改my.ini配置文件4.2 从机修改my.cnf配置文件4.3 重启和关闭防火墙4.4 在Windows主机上建立帐户并授权slave4.5 在Linux从机上配置需要复制的主机4.6 关闭1.复制的基…

FrostSulliven最新发布引领全球增长的60大技术

来源:必达智库图片来源:网络沙利文特别推出“引领全球增长的60大技术”报告,该报告涵盖了环境与可持续发展、能源与公共事业、化学与新型材料、信息与通信技术、高端制造与自动化、传感器和仪器设备、健康领域、医疗器械与影响以及微电子等九…

GitHub基础——下载和上传

文章目录1.下载2.上传2.1 新建一个仓库2.2 上传2.3 拖拽1.下载 1.进入要下载的文件夹 2.右键,Git Bash Here,进入git bash 3.输入下载命令 19072LAPTOP-688SMNV8 MINGW64 /f/github download/设计模式 $ git clone https://github.com/rhyspang/CPP-De…

引导直觉解决数学猜想难题,DeepMind登上《Nature》封面

来源:机器之心编辑:nhyilin多年来,数学家们一直使用计算机来生成数据以帮助搜索数学模式,这种被称为实验数学的研究方法产生出许多重要的猜想,例如BSD猜想。虽然这种方法已经取得成功并且相当普遍,但从这些…

Centos6.5硬盘故障修复

以企业Centos6.5Linux为案例来修复系统,步骤如下: (1)远程备份本地其他重要数据,出现只读文件系统,需要先备份其他重要数据基于rsync|scp远程备份,其中/data为源目录,/data/backup/2…

认知AI的兴起:2025年AI将会发生质的飞跃

来源: Gadi Singer自 1956 年 AI 的概念首次被提出,至今已有 60 多年的发展史。如今,随着相关理论和技术的不断革新,AI 在数据、算力和算法 “三要素” 的支撑下越来越多地走进我们的日常生活。但是,这一系列惊喜的背后…

不上市就等死?AI故事难讲,豪门盛宴背后的“血”与“泪”

图片来源:视觉中国来源:帮尼资讯 部分参考来源:福布斯中国、凤凰网财经、前瞻产业研究院,图片来源网络最近,商汤港股IPO终于迎来新进展。12月7日,商汤集团在香港启动公开发售。据悉,香港公开发售…

windows下搭建vue开发环境

安装node.js 包管理器 到官网 下载安装包直接默认安装,安装完成后验证是否正常安装。打开命令提示符: 输入node -v。 如果显示版本号则证明安装完成。安装vue 打开命令提示符输入: npm install vue全局安装 vue-cli npm install --global vue…

中科院发布11大领域171个热点和新兴前沿!有你的研究方向吗?

来源:科学网12月8日,中国科学院科技战略咨询研究院、中国科学院文献情报中心与科睿唯安联合向全球发布了《2021研究前沿》报告和《2021研究前沿热度指数》报告。《2021研究前沿》报告遴选展示了在农业科学、植物学和动物学,生态与环境科学&am…

Reparameterization Trick

目录 Sample() is not differentiableReparameterization trickToo ComplexSample() is not differentiable 现在我们得到的不是一个向量,得到的是一个分布,而分布是无法使用梯度下降的Reparameterization trick Too Complex 转载于:https://www.cnblogs…

DeepMind 打造 AI 游戏系统,可以玩扑克、国际象棋、围棋等,战斗力爆表

来源:AI科技大本营(ID:rgznai100)编译:禾木木谷歌母公司 Alphabet 的人工智能实验室 DeepMind 长期以来一直投资于游戏人工智能系统。实验室的理念是,游戏虽然缺乏明显的商业应用,但却是认知和推理能力的独…

OO第四单元——UML及其解析器——总结 暨 OO课程大总结

第四单元总结 第四单元主要内容是写代码解析UML,因此需要理解UML UML相关 starUML的储存方式是一个.mdj文件,通过使用文本编辑器观察这个文件,我们可以看出这是一个json格式储存的文件。 通过把.mdj后缀名改为.json,可以更加直观地…

Nature重要新发现:将运动小鼠的血液输入久坐小鼠中,可以改善大脑功能!

来源:生物通 斯坦福大学医学院的研究人员已经表明,大量锻炼的成年小鼠的血液对年龄相同、久坐不动的小鼠的大脑有益。运动小鼠血液中的一种蛋白质似乎是主要原因。Tony Wyss-Coray一项新的研究表明,有可能把跑马拉松的小鼠对大脑的好处转移到…

软件构造-犯错的艺术——健壮性与正确性,异常,防御式编程,debugging与test的思考与总结...

健壮性与正确性 健壮性与正确性是不同的——一个倾向于使程序尽可能保持运行,即使遇到错误,一个倾向于使程序尽可能正确,不在意保持运行 异常 异常分为两种——checked exception与unchecked exception 二者的区别在于: checked e…

地球系统科学简史:理解地球复杂性的多学科探索历程

来源:集智俱乐部作者:Will Steffen, Katherine Richardson等人 译者:晏丽 审校:张澳 编辑:邓一雪 导语我们的地球是一个有生命的有机体,不仅有大气、陆地、海洋之间的物理化学过程,生物也会对环…

数值微分

像这样的由全部变量的偏导数汇总而成的向量称为梯度(gradient),梯度可以像下面这样来实现,这里使用的是用数值微分求梯度的方法。 def numerical_gradient(f, x):h 1e-4 # 0.0001grad np.zeros_like(x) # 生成和x形状相同的数组for idx in …

数据结构与算法——哈希表与字符串

文章目录1.预备知识1.1 最简单的哈希——统计字符个数1.2 哈希表排序整数1.3 哈希映射的问题2.最长回文串2.1 题目描述2.2 C代码实现3.单词规律3.1 题目描述3.2 算法思路3.3 C代码实现4.字母异位词分组4.1 题目描述4.2 算法思路4.3 C代码实现5.无重复字符的最长子串5.1 题目描述…

Science重磅:DeepMind再获突破,用AI开启理解电子相互作用之路

来源:学术头条作者:青苹果编辑:hs排版:李雪薇当电子问题遇到了神经网络,会碰撞出什么样的火花呢?DeepMind 的最新研究向我们揭晓了答案。刊登在最新一期 Science 论文 Pushing the frontiers of density fu…

腾讯-地图:腾讯位置服务

ylbtech-腾讯-地图:腾讯位置服务1.返回顶部 2.返回顶部3.返回顶部4.返回顶部5.返回顶部 1、https://lbs.qq.com/product/miniapp/customized/2、6.返回顶部作者:ylbtech出处:http://ylbtech.cnblogs.com/本文版权归作者和博客园共有&#xff…