MySQL的锁机制

概念

锁是计算机协调多个进程或线程并发访问某一资源的机制(避免争抢)。
在数据库中,除传统的计算资源(如CPU、RAM、I/O等)的争用以外,数据也是一种供多用户共享的资源。

从对数据操作的粒度分
表锁:操作时,会锁定整个表
行锁:操作时,会锁定当前操作行

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

不同存储引擎支持不同的锁机制

存储引擎表级锁行级锁
MyISAM支持不支持
InnoDB支持支持
MEMORY支持不支持
BDB支持不支持

MySQL锁特性

锁类型特点
表级锁偏向MyISAM存储引擎,开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低
行级锁偏向InnoDB存储引擎,开销大,加锁慢;会出现死锁;锁定粒度小,发生锁冲突的概率最低,并发度也最高

MyISAM表锁

MyISAM在执行查询语句前,会自动给涉及的所有表加读锁,在执行更新操作(update、delete、insert等)前,会自动给涉及的表加写锁,这个过程并不需要用户干预,因此,用户一般不需要直接用lock table命令给MyISAM表显示加锁。

方法:
加读锁
LOCK TABLE table_name READ;
加写锁
LOCK TABLE table_name WRITE;

例如(这里的代码建议在B站上看一下相关视频学习):

DROP DATABASE IF EXISTS mydb14_lock;
CREATE DATABASE mydb14_lock;

USE mydb14_lock;

CREATE TABLE tb_book(
 id INT(11) auto_increment,
 name VARCHAR(50) DEFAULT NULL,
 publish_time DATE DEFAULT NULL,
 status CHAR(1) DEFAULT NULL,
 PRIMARY KEY(id)
);

INSERT INTO `mydb14_lock`.`tb_book`(`id`, `name`, `publish_time`, `status`) VALUES (1, 'java编程思想', '2088-08-01', '1');
INSERT INTO `mydb14_lock`.`tb_book`(`id`, `name`, `publish_time`, `status`) VALUES (2, 'solr编程思想', '2088-08-08', '0');

CREATE  TABLE tb_user(
id INT(11) auto_increment,
name VARCHAR(50) DEFAULT NULL,
PRIMARY KEY(id)
);

INSERT INTO `mydb14_lock`.`tb_user`(`id`, `name`) VALUES (1, '令狐冲');
INSERT INTO `mydb14_lock`.`tb_user`(`id`, `name`) VALUES (2, '田伯光');

-- 读锁
LOCK TABLE tb_book READ;

SELECT * FROM tb_book;
UPDATE tb_book SET status = '1' ;-- 此时不能修改会报错

UNLOCK TABLES;

-- 写锁 同时只能加一个
LOCK TABLE tb_book WRITE;

SELECT * FROM tb_book;
UPDATE tb_book SET status = '1'; -- 此时能修改不会报错


InnoDB行锁

行锁特点

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

行锁模式

InnoDB实现了两种类型的行锁

  • 共享锁(S):又称为读锁 ,简称S锁,共享锁就是多个事务对于统一数据可以共享一把锁,都能访问到数据,但是只能读不能修改
  • 排他锁(X):又称为写锁,简称X锁,排他锁就是不能与其他锁并存,如一个事务获取了一个数据行的排他锁,其他事物就不能再获取该行的其他锁,包括共享锁和排他锁,但是获取排他锁的事务是可以对数据就行读取和修改。

对于UPDATE、DELETE、INSERT语句,InnoDB会自动给涉及数据集加排他锁(X)
对于普通SELECT语句,InnoDB不会加任何锁

方法:
共享锁(S)
SELECT * FROM table_name WHERE … LOCK IN SHARE MODE
排他锁(X)
SELECT * FROM table_name WHERE … FOR UPDATE
例如((这里的代码建议在B站上看一下相关视频学习)):

DROP TABLE IF EXISTS test_innodb_lock;
CREATE TABLE test_innodb_lock(
id INT(11),
name VARCHAR(16),
sex VARCHAR(1)
);

INSERT INTO `mydb14_lock`.`test_innodb_lock`(`id`, `name`, `sex`) VALUES (1, '100', '1');
INSERT INTO `mydb14_lock`.`test_innodb_lock`(`id`, `name`, `sex`) VALUES (3, '3', '1');
INSERT INTO `mydb14_lock`.`test_innodb_lock`(`id`, `name`, `sex`) VALUES (4, '400', '0');
INSERT INTO `mydb14_lock`.`test_innodb_lock`(`id`, `name`, `sex`) VALUES (5, '500', '1');
INSERT INTO `mydb14_lock`.`test_innodb_lock`(`id`, `name`, `sex`) VALUES (6, '600', '0');
INSERT INTO `mydb14_lock`.`test_innodb_lock`(`id`, `name`, `sex`) VALUES (7, '700', '0');
INSERT INTO `mydb14_lock`.`test_innodb_lock`(`id`, `name`, `sex`) VALUES (8, '800', '1');
INSERT INTO `mydb14_lock`.`test_innodb_lock`(`id`, `name`, `sex`) VALUES (9, '900', '1');
INSERT INTO `mydb14_lock`.`test_innodb_lock`(`id`, `name`, `sex`) VALUES (1, '200', '0');


-- 关闭事务的自动提交
SET autocommit = 0;

-- 开启事务
BEGIN;

SELECT * FROM test_innodb_lock;-- select不会加任何锁

UPDATE test_innodb_lock SET sex = '2' WHERE id=1;

<think>好的,用户想了解MySQL锁机制及其工作原理。我需要根据提供的引用内容来组织回答。首先,引用1提到锁机制是保证数据一致性和并发性的重要部分,所以应该先介绍的基本作用。然后,引用4提到了表级和行级的区别,需要分点说明这两种的粒度、冲突概率和适用场景。 接下来,引用2指出行级实际上是索引,而不是直接记录,这一点很重要,需要详细解释,尤其是在InnoDB引擎下的不同索引情况下的行为。另外,引用3提到合理使用和事务管理可以避免数据冲突,所以在应用场景部分需要结合事务隔离级别来说明不同的使用情况。 还需要注意用户可能对的类型不太清楚,所以应该分类介绍共享和排他,并给出对应的SQL示例,比如SELECT ... LOCK IN SHARE MODE和SELECT ... FOR UPDATE。同时,要提到意向的概念,作为表级和行级之间的协调机制,这里可能需要解释意向的作用,避免冲突。 关于死,用户可能想知道如何处理,需要说明MySQL的自动检测和回滚机制,以及如何设置超时参数。编程示例部分,可以举一个事务中使用行级的例子,比如更新订单状态时定相关记录,确保数据的一致性。 最后,生成相关问题时要覆盖的类型、行与索引的关系、死处理、应用场景对比以及事务隔离级别的影响。需要确保所有引用内容都正确标注来源,并且语言通俗易懂,结构清晰。</think>### MySQL锁机制详解 MySQL锁机制数据库管理系统实现并发控制的核心技术,主要用于协调多个事务对共享资源的访问。其核心目标是在保证数据一致性的前提下,尽可能提高并发性能。以下是锁机制的核心要点: --- #### 一、的类型与层级 1. **表级** - **定粒度**:直接定整个表 - **冲突概率**:高(多个事务操作同一表的概率大) - **适用场景**:MyISAM引擎默认使用表级,适用于读多写少的场景[^4] - **示例语句**:`LOCK TABLES table_name READ/WRITE;` 2. **行级** - **定粒度**:仅定索引对应的行(注意:行通过索引实现,若未命中索引会退化为表)[^2] - **冲突概率**:低(仅定特定行) - **适用场景**:InnoDB引擎支持,适合高并发写入操作 - **示例语句**:`SELECT * FROM table WHERE id = 1 FOR UPDATE;` 3. **页级** - **定粒度**:介于表级和行级之间(定数据页) - **适用引擎**:BDB存储引擎 --- #### 二、的访问模式 1. **共享(S Lock)** - **作用**:允许事务读取数据,阻止其他事务获取排他 - **语法**:`SELECT ... LOCK IN SHARE MODE;` - **示例**:事务A持有共享时,事务B可读但不可写。 2. **排他(X Lock)** - **作用**:允许事务修改数据,阻止其他事务获取任何 - **语法**:`SELECT ... FOR UPDATE;` - **示例**:事务A更新某行时,其他事务无法读写该行。 3. **意向(Intention Locks)** - **作用**:表级,用于快速判断表中是否存在行级 - **类型**:意向共享(IS)、意向排他(IX) - **示例**:事务A对某行加共享前,需先获取表的IS。 --- #### 三、的实现细节 1. **行与索引的关系** - 当使用唯一索引时,仅定符合条件的行。 - 若未使用索引或索引失效,InnoDB会升级为表。 - **示例**:执行`UPDATE users SET name='Bob' WHERE age=30`,若`age`字段无索引,将定整个表。 2. **死处理** - MySQL自动检测死,并回滚代价较小的事务。 - **编程建议**:设置合理的超时时间(`innodb_lock_wait_timeout`)和重试机制。 --- #### 四、应用场景与编程示例 ```sql -- 事务中使用行级(InnoDB引擎) START TRANSACTION; SELECT * FROM orders WHERE order_id = 100 FOR UPDATE; -- 获取排他 UPDATE orders SET status = 'shipped' WHERE order_id = 100; COMMIT; ``` **说明**:通过`FOR UPDATE`定订单记录,确保在更新状态时其他事务无法修改该订单[^3]。 --- #### 五、锁机制与事务隔离级别 - **读未提交(Read Uncommitted)**:无控制,可能脏读。 - **读已提交(Read Committed)**:通过行级避免脏读。 - **可重复读(Repeatable Read)**:默认隔离级别,通过间隙(Gap Lock)防止幻读。 - **串行化(Serializable)**:强制所有操作加,牺牲并发性。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

火眼猊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值