当前位置:知识百科 > 正文

mysql怎么自动加锁

更新时间:2025-01-01 00:51 阅读量:8862

MySQL从入门到精通(九) MySQL锁,各种锁

全局锁就是对整个数据库实例加锁,加锁后整个实例就处于只读状态,后续的DML的写语句,DDL语句,已经更新操作的事务提交语句都将阻塞.其典型的使用场景就是做全库的逻辑备份,对所有的表进行锁定,从而获取一致性视图,保证数据的完整性.但是对数据库加全局锁是有弊端的,如在主库上备份,那么在备份期间都不能执行更新,业务会受影响,第二如果是在从库上备份,那么在备份期间从库不能执行主库同步过来的二进制日志,会导致主从延迟.

解决办法是在innodb引擎中,备份时加上--single-transaction参数来完成不加锁的一致性数据备份.

添加全局锁: flush tables with read lock; 解锁 unlock tables.

表级锁,每次操作会锁住整张表.锁定粒度大,发送锁冲突的概率最高,并发读最低,应用在myisam、innodb、BOB等存储引擎中.表级锁分为: 表锁、元数据锁(meta data lock, MDL)和意向锁.

表锁又分为: 表共享读锁 read lock、表独占写锁write lock

语法: 1、加锁 lock tables 表名 ... read/write

元数据锁,在加锁过程中是系统自动控制的,无需显示使用,在访问一张表的时候会自动加上,MDL锁主要作用是维护表元数据的数据一致性,在表上有活动事务的时候,不可以对元数据进行写入操作.为了避免DML和DDL冲突,保证读写的正确性.

查看元数据锁:

select object_type,object_schema,object_name,lock_type,lock_duration from performance_schema_metadata_locks;

意向锁,为了避免DML在执行时,加的行锁与表锁的冲突,在innodb中引入了意向锁,使得表锁不用检查每行数据是否加锁,使用意向锁来减少表锁的检查.意向锁分为,意向共享锁is由语句select ... lock in share mode添加.意向排他锁ix,由insert,update,delete,select...for update 添加.

select object_schema,object_name,index_name,lock_type,lock_mode,lock_data from performance_schema.data_lock;

行级锁,每次操作锁住对应的行数据,锁定粒度最小,发生锁冲突的概率最高,并发读最高,应用在innodb存储引擎中.

innodb的数据是基于索引组织的,行锁是通过对索引上的索引项加锁来实现的,而不是对记录加的锁,对于行级锁,主要分为以下三类:

①.、行锁或者叫record lock记录锁,锁定单个行记录的锁,防止其他事物对次行进行update和delete操作,在RC,RR隔离级别下都支持.

innodb实现了以下两种类型的行锁

①.、共享锁 S: 允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁.

insert 语句 排他锁 自动添加的

update语句 排他锁 自动添加

delete 语句 排他锁 自动添加

select 正常查询语句 不加锁 ...

select ...lock in share mode 共享锁 需要手动在select 之后加lock in share mode

select ...for update 排他锁 需要手动在select之后添加for update

默认情况下,innodb在repeatable read事务隔离级别运行,innodb使用next-key锁进行搜索和索引扫描,以防止幻读.

间隙锁唯一目的是防止其它事务插入间隙,间隙锁可以共存,一个事务采用的间隙锁不会阻止另一个事务在同一间隙上采用的间隙锁.

mysql数据库锁MDL锁的解释

在我们系统中有一张表它的查询概率非常高. 最近有个需求,需要对这个表增加一个字段 ,然而在增加字段的时候发现系统中有多个业务出现了超时操作,那么这个是什么原因导致的呢?经过查阅资料发现是数据库的 MDL锁+事务导致 的.

MDL锁属于表级别的元数据锁. 表级别锁分为数据锁和元数据锁,通常我们说的加锁一般指的是加的数据锁.跟数据锁一样,元数据锁也分读锁和读写锁.

MDL不需要显示使用,在进行表操作时会自动加上 .当对表进行增删改查时,会自动加上MDL读锁;当要对表进行加减字段的结构修改时,会自动加上MDL写锁.

MDL锁的存在,其实是为了保证数据的一致性. 想象一下,假如没有MDL锁,一个查询在遍历表数据的过程中,另外一个线程执行了ALTER TABLE t DELETE COLUMN 'col_1'把col_1这一列删掉了,那查询结果就乱了,结果中是否应该有这一列数据?

:表示正常往下执行

:表示卡住了,即无法往下执行.

解释:

如果先执行事务二,在执行事务三,则是可以成功的,因为alter数据ddl语句,和事物无关.

所以呢在我们开发的过程中,需要避免大的事务操作,防止占有锁的时间过长.

mysql读数据时怎么加写锁

加锁情况与死锁原因分析

为方便大家复现,完整表结构和数据如下:

+c1+ int(11) NOT NULL AUTO_INCREMENT,

PRIMARY KEY (+c1+),

) ENGINE=InnoDB

死锁日志如下:

INSERT INTENTION LOCK

但是插入意向锁是客观存在的,我们可以在官方手册中查到,不可忽略:

Prior to inserting the row, a type of gap lock called an insert intention gap lock is set. This lock signals the intent to insert in such a way that multiple transactions inserting into the same index gap need not wait for each other if they are not inserting at the same position within the gap.

当插入一条记录时,会去检查当前插入位置的下一条记录上是否存在锁对象,如果下一条记录上存在锁对象,就需要判断该锁对象是否锁住了 gap.如果 gap 被锁住了,则插入意向锁与之冲突,进入等待状态(插入意向锁之间并不互斥).最后提醒一下大家这把锁的属性:

① 它不会阻塞其他任何锁;


在学习 MySQL 过程中,一般只有在它被阻塞的时候才能观察到,所以这也是它常常被忽略的原因吧...

GAP LOCK

在此例中,另外一个重要的点就是 gap lock,通常情况下我们说到 gap lock 都只会联想到 REPEATABLE-READ 隔离级别利用其解决幻读.但实际上在 READ-COMMITTED 隔离级别,也会存在 gap lock ,只发生在:唯一约束检查到有唯一冲突的时候,会加 S Next-key Lock,即对记录以及与和上一条记录之间的间隙加共享锁.

通过下面这个例子就能验证:

有个困惑很久的疑问:出现唯一冲突需要加 S Next-Key Lock 是事实,但是加锁的意义是什么?还是说是通过 S Next-Key Lock 来实现的唯一约束检查,但是这样意味着在插入没有遇到唯一冲突的时候,这个锁会立刻释放,这不符合二阶段锁原则.这点希望能与大家一起讨论得到好的解释.

如果是在 REPEATABLE-READ,除以上所说的唯一约束冲突外,gap lock 的存在是这样的:

对于 gap lock,相信 DBA 们的心情是一样一样的,所以我的建议是:

① 在绝大部分的业务场景下,都可以把 MySQL 的隔离界别设置为 READ-COMMITTED;


锁冲突矩阵

前面我们说的 GAP LOCK 其实是锁的属性,另外我们知道 InnoDB 常规锁模式有:S 和 X,即共享锁和排他锁.锁模式和锁属性是可以随意组合的,组合之后的冲突矩阵如下,这对我们分析死锁很有帮助:

MySQL白菜教程(Level 10 - 意向锁&记录锁&间隙锁)

意向锁(Intention Locks; table-level lock)

意向锁是一种特殊的表级锁,意向锁是为了让 InnoDB 多粒度的锁能共存而设计的.取得行的共享锁和排他锁之前需要先取得表的意向共享锁(IS)和意向排他锁(IX),意向共享锁和意向排他锁都是系统自动添加和自动释放的,整个过程无需人工干预

意向锁就是指未来的某一个时刻事务可能要加共享锁或者排它锁,提前声明一个意向,分为两种:

意向共享锁(Intention Shared Lock) IS

事务有意向对表中的某些行加共享锁(S锁)

意向排它锁(Intention Exclusive Lock)IX

事务有意向对表中的某些行加排他锁(X锁)

记录锁(Record Locks)

官方原文

SELECT c1 FROM t WHERE c1 = 10 FOR UPDATE; 这一行则是使用了记录锁,不允许其他事务进行增,删,改

但是 SELECT c1 FROM t WHERE c1 = 10; 是没有锁的,走的是快照读,上文已经阐明过了

记录锁本身不是锁定记录数据本身而是锁定索引记录,如果要锁的列没有索引,则会进行全表记录加锁

间隙锁(Gap Locks)

这种默认存在于可重复读的事务隔离级别中的锁,锁定被圈定的范围不允许 insert,防止不可重复读,上文说了我们的事务隔离级别都是读已提交,默认会产生不可重复读的问题

mysql 的锁以及间隙锁

mysql 为并发事务同时对一条记录进行读写时,提出了两种解决方案:

①.)使用 mvcc 的方法,实现多事务的并发读写,但是这种读只是"快照读",一般读的是历史版本数据,还有一种是"当前读",一般加锁实现"当前读",或者 insert、update、delete 也是当前读.

快照读:就是select

当前读:特殊的读操作,插入/更新/删除操作,属于当前读,处理的都是当前的数据,需要加锁.

mysql 在 RR 级别怎么处理幻读的呢?一般来说,RR 级别通过 mvcc 机制,保证读到低于后面事务的数据.但是 select for update 不会触发 mvcc,它是当前读.如果后面事务插入数据并提交,那么在 RR 级别就会读到插入的数据.所以,mysql 使用 行锁 + gap 锁(简称 next-key 锁)来防止当前读的时候插入.

Gap Lock在InnoDB的唯一作用就是防止其他事务的插入操作,以此防止幻读的发生.

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