做网站最贵,贺州同城购物网站建设,wordpress 主机要求,wordpress 苏醒主题MySQL的锁机制 1.共享锁(Shared Lock)和排他锁(Exclusive Lock)
事务不能同时具有行共享锁和排他锁#xff0c;如果事务想要获取排他锁#xff0c;前提是行没有共享锁和排他锁。而共享锁#xff0c;只要行没有排他锁都能获取到。
手动开启共享锁/排他锁#xff1a;
-- 对…MySQL的锁机制 1.共享锁(Shared Lock)和排他锁(Exclusive Lock)
事务不能同时具有行共享锁和排他锁如果事务想要获取排他锁前提是行没有共享锁和排他锁。而共享锁只要行没有排他锁都能获取到。
手动开启共享锁/排他锁
-- 对需要查询的行添加共享锁
select .... from .... lock in share mode;
-- 对读取记录加排他锁
select .... from .... for update;注意当一个事务尝试获取一个已经被其他事务持有的排他锁时它会进入等待状态直到该锁被释放为止。在MySQL 8.0版本中新增了NOWAIT和SKIP LOCKED两种语法可以用来控制事务在获取不到锁时的行为。
delete操作过程
事务开始获取待删除数据的排他锁。获取成功执行删除操作。事务提交释放锁。
update操作过程分为两种情况有更改主键值和未修改主键值。
未修改主键值
更新前后存储空间未发生变化获取排他锁在原记录进行修改。更新前后存储空间发生变化获取排他锁将该记录删除最后在插入一条新的记录。
修改主键值在原记录进行一次delete操作再来一次insert操作。
insert操作过程一般情况下insert操作并不加锁通过一种隐式锁保护新插入的记录不被未提交的事务所看到。
注意共享锁-排他锁阻塞共享锁阻塞
2.表锁
2.1X锁和S锁
表锁锁定整张表不依赖于存储引擎表锁的开销较小但是锁粒度大并发执行效率低。
特殊场景在修改表结构的过程中像alter table 、drop table这样的语句就会有表锁的存在同时也会阻塞其他对表的操作语句update、select…。
表级别的X锁和S锁
-- 添加S锁InnoDB引擎会对表table添加S锁
LOCK TABLES table READ;
-- 添加X锁InnoDB引擎会对表table添加X锁
LOCK TABLES table WRITE;
-- 解锁
UNLOCK TABLES;2.2意向锁intention lock
InnoDB支持多粒度锁允许行级锁和表级锁共存。
为了协调行锁和表的关系支持多粒度锁共存。
存在的问题如果数据量非常大表如果要知道哪一行存在锁就非常的麻烦因此就有了意向锁。
如果我们给某一行的数据添加了锁数据库会自动给更大的一级空间比如数据页或表添加上意向锁表示该数据页或数据表已经存在锁了。
-- 事务要获取某个行的S锁必须先获得IS锁。
SELECT ... FROM table ... LOCK IN SHARE MODE;
-- 添加排他锁会自动获取IS锁。
SELECT... FROM table ... for UPDATE;意向锁和意向锁的兼容性
意向共享锁意向排他锁意向共享锁兼容兼容意向排他锁兼容兼容
意向锁和表锁的兼容性
意向共享锁意向排他锁共享锁兼容不兼容排他锁不兼容不兼容
2.3自增锁
表中字段存在AUTO_INCREMENT属性。当新增数据自动生成主键时就会使用该锁来生成保证生成的主键是自增且唯一的。
AUTOINC 锁具有如下特点
AUTO_INC 锁互不兼容也就是说同一张表同时只允许有一个自增锁自增值一旦分配了就会 1如果事务回滚自增值也不会减回去所以自增值可能会出现中断的情况。
2.4元数据锁
主要为了解决表结构的修改和表数据修改冲突问题。
当对一个表增删改查操作的时候加MDL读锁当要对表结构变更操作的时候加MDL写锁。
3.乐观锁和悲观锁
3.1乐观锁
实现乐观锁可以采用CASCompare And Swap的方式乐观的认为产生锁冲突的概率较小。适用于锁冲突概率比较小的场景。 ABA问题假设最开始的数据是A在线程1执行的过程中有其他线程将数据修改成了B又再次被修改为A就会导致线程1错误的认为该数据没有被修改过因此可以通过对数据添加一个版本号对于每次修改都会产生一个新的修改数据版本通过比较数据版本判断数据是否被更改。
时间戳机制通过比较时间戳判断数据是否被修改。
3.2悲观锁
悲观锁依靠数据库提供的锁机制来实现。
SELECT … FOR UPDATE是MySQL中的悲观锁执行过程会将所有扫描的行都锁上因此在MySQL中用悲观锁必须使用索引而不是全表扫描否则会将整张表锁住。
4.行锁
4.1记录锁
SELECT ... FROM ... WHERE id 1 FOR UPDATE;记录锁记录锁Record Lock是一种锁定索引记录的锁定方式。当一个事务需要访问某个索引记录时它可以在该记录上加一个记录锁以防止其他事务修改或删除该记录。记录锁是针对单个记录的它只锁定该记录本身不会影响其他记录。
4.2间隙锁
间隙锁在REPEATABLE READ隔离级别下是可以解决幻读问题的。给不存在的索引添加锁那么添加的就是间隙锁。
例如有id {13581015}锁定13那么在区间1015之间都不能插入新的数据。
SELECT ... FROM ... WHERE id 13 FOR UPDATE;注意间隙锁的唯一目的就是阻止其他事务在间隙上插入记录一个事务在一个间隙上加锁并不会阻止其他事务在相同间隙上加锁无论是共享锁还是排它锁他们互不冲突执行相同的功能。
4.3临键锁
临键锁临键锁Next-Key Lock是结合记录锁和间隙锁的一种锁定方式。它不仅锁定索引上的记录还锁定该记录前面的间隙。
例如有id{13581015}记录15被锁定了且(10∞)不能添加记录。
SELECT ... FROM ... WHERE id15 AND id10 for update;4.4插入意向锁
插入意向锁Insert Intention Lock是MySQL中的一种间隙锁形式的意向锁用于在INSERT操作之前设置。
在真正执行INSERT操作之前每个事务会在要插入的行的前一条记录上加一个插入意向锁。这样其他事务在尝试插入相同间隙时会检查该间隙上是否已经存在插入意向锁。如果存在插入意向锁那么其他事务就可以知道已经有其他事务打算在这个间隙中插入数据就会进行等待而不是冲突。
由于插入意向锁之间不会相互冲突多个事务可以同时持有相同间隙上的插入意向锁。这就避免了事务之间的互相冲突提高了并发插入的性能。
需要注意的是插入意向锁之间并不会相互冲突多个事务可以同时持有相同间隙上的插入意向锁。
5.全局锁
锁整个数据库实例。
全局锁命令
FLUSH TABLES WITH READ LOCK;有相同间隙上的插入意向锁。这就避免了事务之间的互相冲突提高了并发插入的性能。
需要注意的是插入意向锁之间并不会相互冲突多个事务可以同时持有相同间隙上的插入意向锁。
5.全局锁
锁整个数据库实例。
全局锁命令
FLUSH TABLES WITH READ LOCK;