对MySQL的锁了解吗?
当数据库有并发事务的时候,可能会产生数据的不一致,这时候需要一些机制来保证访问的次序,锁机制就是这样的一个机制。
例子:就像酒店的房间,如果大家随意进出,就会出现多人抢夺一个房间的情况,而在房间上装上所,申请盗钥匙的人才可以入住并且将房间锁起来,其他人只有等他使用完毕才可以使用。
隔离级别与锁的关系
在Read Uncommited级别下,读取数据不需要加共享锁,这样就不会跟被修改的数据上的排他锁冲突。
在Read Commited级别下,读操作需要加共享锁,但是在语句执行完以后释放共享锁。
在Repeatable Read级别下,读操作需要加共享锁,但是在事务提交之前并不释放共享锁,也就是必须等待事务执行完毕以后才释放共享锁。
Serializable是限制性最强的隔离级别,因为该级别锁定整个范围的键,并一直持有锁,直到事务完成。
按照锁的粒度分数据库锁有哪些?锁机制与InnoDB锁算法
在关系型数据库中,可以按照锁的粒度把数据库锁分为行级锁(InnoDB引擎)、表级锁(MyISAM引擎)和页级锁(BDB引擎)。
MyISAM和InnoDB使用的锁:
1、MyISAM使用表级锁。
2、InnoDB支持行级锁和表级锁,默认为行级锁。
行级锁和表级锁对比
行级锁
行级锁是MySQL中锁定粒度最细的一种锁,表示只针对当前操作的行(Row)进行加锁。行级锁能大大减少数据库操作的冲突。其加锁粒度最小,但加锁的开销也最大。行级锁分为共享锁和排他锁。
特点:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突概率最低,并发度也最高。
表级锁
表级锁是MySQL中锁定粒度最大的一种锁,表示对当前操作的整张表加锁,它实现简单,资源消耗较少,被大部分MySQL引擎支持。最常用的MyISAM与InnoDB都支持表级锁。表级锁分为表共享读锁(共享锁)与表独占写锁(排他锁)。
特点:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。
从锁的分类来说,MySQL都有哪些锁?
从锁的类别来讲,有共享锁和排他锁。
共享锁
又叫读锁。当用户要进行数据读取时,对数据加上共享锁。共享锁可以同时加上多个。
排他锁
又叫写锁。当用户要进行数据的写入时,对数据加上排他锁。排他锁只可以加一个,它和其它排他锁、共享锁都互斥。
例子
假设用户行为有两种,一种是来看房,多个用户一起看房是可以接受的。一种是真正的入住一晚,在这期间,无论是像入住还是想看房都是不可以的。
锁的粒度取决于具体的存储引擎,InnoDB实现了行级锁,页级锁,表级锁。它们的加锁开销从大到小,
并发能力也是从大到小。
MySQL中InnoDB引擎的行锁是怎么实现的?
InnoDB是基于索引来完成行级锁的。
例如:select * from tab_with_index where id = 1 for update;
for update可以根据条件来完成行级锁顶,并且id是有索引键的列,如果id不是索引键那么InnoDB将完成表锁,并发将无从谈起。
InnoDB存储引擎的锁的算法有三种
1、record lock:单个行记录上的锁
2、gap lock:间隙锁,锁定一个范围,不包括记录本身
3、next-key lock:record + gap锁顶一个范围,包含记录本身
相关知识点:
1、InnoDB对于行的查询使用next-key lock
2、next-locking keying为了解决幻读问题
3、当查询的索引含有唯一属性时,将next-key lock降级为record lock
4、gap锁设计的目的是为了阻止多个事务将记录插入到同意范围内,而这会导致幻读问题的产生
5、有两种方式显式关闭gap锁:(除了外键约束和唯一性检查外,其余情况仅使用record lock)
A、将事务隔离级别设置为RC;
B、将参数innodb_locks_unsafe_for_binlog设置为1
什么是死锁?如何解决?
死锁是指两个或多个事务在同一资源上向胡战勇,并请求锁定对方的资源,从而导致恶性循环。
解决方案:
1、如果不同程序会并发存取多个表,尽量约定以相同的顺序访问表,可以大大降低发生死锁的风险。
2、同一个事务中,尽可能做到一次锁定所需要的所有资源,减少死锁产生概率。
3、对于非常容易产生死锁的业务部分,可以尝试升级锁定粒度,通过表级锁定来减少死锁产生的概率。
数据库的乐观锁和悲观锁是什么?怎么实现的?
数据库管理系统中的并发控制的任务是确保在多个事务同时存取数据库中同一份数据时不破坏事务的隔离性和统一性以及数据库的统一性。乐观并发控制(乐观锁)和悲观并发控制(悲观锁)是并发控制主要采用的技术手段。
悲观锁
假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作。在查询完数据的时候就把事务锁起来,直到提交事务。
实现方式:使用数据库中的锁机制。
乐观锁
假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性。在修改数据的时候把事务锁起来,通过版本控制的方式来进行锁定。
实现方式:一般会使用版本号机制或CAS算法实现。
乐观锁和悲观锁的使用场景
从上面对两种锁的介绍,我们知道两种锁各有优缺点,不可认为一种好于另一种,像乐观锁适用于写操作比较少的情况下(多读场景,也就是并发写操作较低的场景),即冲突真的很少发生的时候,这样可以省去加锁的开销,加大了整个系统的吞吐量。
但如果是并发写操作较多的情况下,一般会经常产生冲突,这就会导致上层应用会不断的进行retry,这样的话使用乐观锁反而是降低了性能,所以一般并发写操作较多的场景下使用悲观锁比较合适。
文章来自各大论坛和平台,并非本人原创,但是无奈找不到一个具体来源,故类别上写为原创。侵删。