什么是MySQL锁机制

介绍

本篇内容主要讲解“什么是MySQL锁机制”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“什么是MySQL锁机制”吧!

无论什么时候,只要存在多个连接在同一时刻修改数据,都会涉及到并发控制的问题。MySQL实现了两个层面的并发控制:服务层和引擎层。

锁分类

按照使用场景分类

共享锁:共享锁(shared lock)也称为读锁(read  lock)。共享锁是共享的,或者说是相互不阻塞的。多个连接在同一时刻可以同时读取同一个资源,而不相互干扰。

排他锁:排他锁(exclusive lock)也称为写锁(write lock)。写锁是排他的,也就是一个写锁会阻塞其他的写锁和读锁。

按照加锁思想分类

悲观锁:对数据被外界修改保持悲观的态度,在整个数据处理过程中,数据都处于锁定状态。

乐观锁:它认为数据一般情况下不会造成冲突,在数据更新的时候才会对数据的冲突与否进行校验。

按照锁粒度分类

全局锁:对整个数据库实例加锁,它将整个数据库实例处于只读的状态。

表级锁:对整个表进行加锁的方式。MySQL表级锁分为表锁和元数据锁。

行级锁:行锁可以最大程度的支持并发处理,行锁是存储引擎层实现的,而MySQL服务层并没有实现行锁。InnoDB存储引擎行级锁类型:Record  Lock、Gap Lock、Next-key Lock。

读写锁

读锁

共享锁:共享锁(shared lock)也称为读锁(read  lock)。共享锁是共享的,或者说是相互不阻塞的。多个连接在同一时刻可以同时读取同一个资源,而不相互干扰。

加锁命令

select ...... lock in share mode;

测试

测试时,设置事务手动提交:set autocommit=0,后续如果没有明确的提示,autocommit都是0。

测试时,大家开启两个窗口,建立两个连接,窗口1和窗口2分别对应事务A和事务B。

  • 窗口1:查询id=6的行数据并添加读锁,正确返回数据。

  • 窗口2:依然查询id=6的行数据并添加读锁,正确返回数据。读读不冲突。

  • 窗口1:对id=6的行执行写操作(update语句),在窗口2的事务提交之前,写操作阻塞,并可能会超时退出。

什么是MySQL锁机制

如果写锁等待时间过长,则会超时退出。

窗口1 mysql> update user set age = 20 where id =6; ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

如果在窗口1中的事务在执行写操作等待期间,窗口2的事务也执行同一行数据的写操作,则会导致死锁错误。

窗口2 mysql> update user set age = 30 where id =6; ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

 写锁

排他锁(exclusive lock)也称为写锁(write lock)。写锁是排他的,也就是一个写锁会阻塞其他的写锁和读锁。

加锁命令

select ...... for update;

测试

  • 窗口1:查询id=6的行数据并添加写锁,正确返回数据。

  • 窗口2:依然查询id=6的行数据并添加写锁,阻塞。写写冲突。

  • 窗口1:对id=6的行执行写操作(update语句),写操作未阻塞。

  • 窗口1事务提交之后,窗口2的查询语句返回结果。

什么是MySQL锁机制

悲观锁和乐观锁

不论是乐观锁还是悲观锁都是人们定义的一种概念,并不是一种锁实现,它是一种思想。乐观锁比较适用于读多写少的场景,悲观锁适用于写多读少的场景。

悲观锁

当我们对数据库的某一条数据进行修改操作时,为了避免同时有其他人对同一行数据进行修改,通过对数据进行加锁的方式以防止并发问题。这种借助了数据库的锁机制,在修改数据之前先锁定再修改的方式称为悲观锁(Pessimistic  Lock)。

悲观锁具有强烈的独占性和排他性,在整个数据的写操作过程,都将数据处于锁定状态。悲观锁的实现往往需要数据库提供的锁机制。

悲观锁的实现: