MySQL锁

在这里插入图片描述

开销加锁速度锁定粒度发生锁冲突的概率并发度是否会出现死锁
表级锁最高最低不会
行级锁最低最高

页级锁介于两者之间,会出现死锁

全局锁

对整个数据库实例加锁。
整个库处于只读状态,不能对数据进行增删改,不能有DDL操作。
应用场景:逻辑备份。

注:
物理备份:以磁盘块为单位将数据从主机复制到备机。
逻辑备份:以文件为单位将数据从主机复制到备机。

表级锁

读锁时,其他进程无法对表进行写操作
写锁时,其他进程无法进行读操作

写操作加锁原理:
如果表上没有锁,就在表上加写锁,否则把写锁请求放在写锁队列中
读操作加锁原理:
如果表上没有写锁,就在表上加读锁,否则把锁请求放在读锁队列里

表锁使用一次封锁,在会话开始的地方使用 lock 命令将后面所有要用到的表加上锁,在锁释放之前,我们只能访问这些加锁的表,不能访问其他的表,最后通过 unlock tables 释放所有表
锁。

当表数据大部分时间只需要读取时,速度大于级锁和行级锁
有很多group by操作时没有写操作时,速度更快

行级锁

共享锁:
多个事务只能读,不能修改数据。

排他锁:
事务不能在排他锁上加其他锁,InnoDB的增删改都会给涉及的数据加排他锁,select语句不会加任何锁。

MySQL InnoDB引擎自动给增删改语句添加排他锁。

InnoDB行锁是通过给索引项加锁来实现的,只有通过索引条件检索数据时,InnoDB才使用行锁,否则就使用表锁。

缺点:
比表级、页级锁占用更多内存
当表数据被频繁使用时,比页级或表级锁定速度慢,因为需要获得更多锁
如果经常使用group by或者必须扫描整张表,比其他锁慢

记录锁、间隙锁、next-key锁

记录锁会锁住一行的记录
间隙锁或锁住指定区间的记录
next-key锁包含了记录锁和间隙锁,锁定范围也锁定记录本身。

InnoDB默认的加锁方式是next-key锁。

InnoDB自动使用间隙锁的条件:

  • 必须在RR级别下
  • 检索条件必须有索引(没有索引的话,mysql会全表扫描)

解锁规则

  • 使用 UNLOCK TABLES 语句可以显示释放表锁
  • 如果会话在持有表锁的情况下执行 LOCK TABLES 语句,将会释放该会话之前持有的锁
  • 如果会话在持有表锁的情况下执行 START TRANSACTION 或 BEGIN 开启一个事务,将会释放该会话之前持有的锁
  • 如果会话连接断开,将会释放该会话所有的锁

MyISAM的锁机制

MyISAM总是一次性获得所需的全部锁,要么全部满足,要么全部等待。所以不会产生死锁,但是由于每操作一条记录就要锁定整个表,导致性能较低,并发不高。

InnoDB的锁机制

意向锁

InnoDB可以同时实现表锁和行锁,使用索引处理数据时使用行锁,否则使用表锁。意向锁是为了保证行锁和表锁不冲突的存在。

例如,事务A修改某表的某行记录,会给该行上X锁,同时给整张表上IX锁;这样后面的事务就不能对该表加表级X锁。

意向锁都是表级锁,因为事务企图想加表级X锁时,检查该表有没有意向锁就行了,就不用检查这张表的每行数据是否都加了意向锁。

行锁的解锁

在 InnoDB 事务中,行锁是在需要的时候才加上的,但并不是不需要了就立刻释放,而是要等到事务结束时才释放。这个就是两阶段锁协议。

所以,如果事务中需要锁多个行,要把最可能造成锁冲突、最可能影响并发度的锁尽量往后放。

InnoDB死锁

死锁发生的情形
  • 一个线程两次申请锁
  • 两个线程互相申请对方的锁,但是对方都不释放锁
死锁检测

针对死锁有两种策略:
一种是超时终止线程,这种时间不好把握,InnoDB默认是50秒
另外一种是自动检测事务死锁,并立刻回滚,然后返回错误。回滚通常选择undo量最小的事务

第二种比较灵活,但是相对会比较花费CPU资源。计算复杂度是n^2,也就是如果有1000个线程,死锁检测的时间复杂度是100万量级。

针对这个问题有一些解决方式:
首先判断这个场景下死锁检测是不是必须的,如果不是必须的可以关闭死锁检测;
或者可以控制并发的数量,例如设置某一行的update并行事务要在10个以下;
或者分摊一下字段压力,例如某个字段记录了公司的总营收,可以将这个字段分摊为10个字段,每次修改其中一个字段的数值即可。

### MySQL 机制详解 MySQL 中的机制是为了保障数据库在高并发环境下的数据一致性和稳定性而设计的重要功能之一。以下是关于 MySQL 机制的具体解析: #### 1. 的分类 MySQL 主要分为两种类型的和行级。 - ** (Table-Level Lock)** 是最简单的定策略,适用于 MyISAM 存储引擎。它会在整个上施加,无论是读操作还是写操作都会影响到整张。对于 `SELECT` 操作,MyISAM 会自动给涉及的所有加上读;而对于 `UPDATE`, `INSERT`, 和 `DELETE` 则会自动加上写[^3]。 - **行级 (Row-Level Lock)** 行级由 InnoDB 存储引擎实现,提供更高的并发能力。只有涉及到具体记录的操作才会触发行级。例如,在执行 `SELECT ... FOR UPDATE` 或者 `SELECT ... LOCK IN SHARE MODE` 时,InnoDB 只会对符合条件的特定行加而不是封整个[^2]。 #### 2. 不同存储引擎的特性 不同的存储引擎有不同的行为: - **MyISAM**: 默认使用的是级别的,这意味着即使是一个小范围内的更新也会阻塞其他线程对该任何部分的访问[^3]。 - **InnoDB**: 支持事务以及更细粒度的行级,这使得它可以更好地处理复杂的多用户场景下的并发请求[^4]。 #### 3. 常见类型及其作用 除了基本的级与行级区分外,还有几种具体的形式用于满足不同需求: - **共享 (Shared Lock, S-Lock)** 当一个客户端通过命令如 `LOCK TABLES table_name READ` 获取了一个上的共享之后,其它客户也可以获得该上的共享,但不能再获取排他直到当前持有共享的所有连接释放它们为止[^2]。 - **排他 (Exclusive Lock, X-Lock)** 排他允许独占式的修改权限。如果某个事务已经获得了某条记录或者某些列上的排他,则在此期间不允许别的事务再对此同一组资源申请任何形式的新——既包括另外的排他也包括新的共享[^2]。 - **GAP ** 这种特殊的用来阻止新纪录插入到现有两条连续记录之间的空隙(gap)里去。比如当我们运行下面这条SQL语句的时候就会用到gap lock:`SELECT * FROM table_name WHERE id > 10 FOR UPDATE;` - **Next-Key Lock** 是一种组合了索引记录本身(record)和其前面那个区间(gap)两者一起保护起来的一种复合型模式。主要用于解决可重复读(repeatable read)隔离级别下可能出现的幻影问题(phantom problem)[^4]。 #### 4. 死现象及预防措施 死是指两个或更多事务相互等待对方持有的资源从而进入僵局的状态。为避免这种情况发生可以采取以下方法: - 尽量按照固定的顺序访问资源; - 减少单次事务持续时间; - 设置合理的超时参数让系统能够及时发现并终止潜在的死循环状况等等[^4]。 ```sql -- 示例:如何手动解 UNLOCK TABLES; ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值