1.什么是数据库的锁?
当数据库有并发事务的时候,保证数据访问顺序的机制称为锁机制。
2.数据库的锁与隔离级别的关系?
3. 数据库锁的类型有哪些?
1)按照锁的粒度可以将MySql锁分为三种:
MyISAM默认采用表级锁,InnoDB默认采用行级锁。
2)从锁的锁级别划分上区别可以分为共享锁、排他锁、意向锁
1.共享锁:共享锁又称为读锁,简写为S锁,一个事务对一个数据对象加了S锁,可以对这个数据进行读取操作,但不能进行更新操作,并且在加锁期间其他事务只能对这个数据对象加S锁,不能加X锁
2.排它锁(Exclusive Lock)也称写锁,简称x锁,只允许一个事务独占访问资源,并对该资源进行读取和更改操作,加锁期间,其他事务不能对改数据对象进行加X锁或者S锁。
3.意向锁:
意向锁是一种优化锁机制,旨在提高多线程并发访问性能和减少锁冲突的次数。它是一种基于悲观锁的优化,由InnoDB存储引擎在MySQL数据库中实现。
意向锁分为两种类型,即意向共享锁(Intention Shared Lock,IS锁)和意向排他锁(Intention Exclusive Lock,IX锁)。IS锁表示当前线程有意向在共享模式下访问该资源,IX锁表示当前线程有意向在排他模式下访问该资源。
意向锁的作用在于,它能够协调锁的层次结构,避免不必要的锁冲突。例如,如果一个线程需要获取一个资源的排他锁,那么它必须先获取该资源的意向排他锁,如果其他线程已经持有该资源的共享锁,那么它需要等待所有的共享锁都被释放后才能获取意向排他锁,从而减少锁冲突的概率。
意向锁的另一个作用在于,它可以帮助优化锁的检查过程,提高锁的检查效率。由于IS锁和IX锁只是意向锁,不会阻塞其他线程对资源的访问,因此在锁的检查过程中,可以优先检查意向锁,避免不必要的锁检查。
总之,意向锁是一种优化锁机制,它能够协调锁的层次结构,减少锁冲突的概率,提高锁的检查效率,从而提高多线程并发访问性能。
3)按照实现方式分类: 根据实现方式,可以将数据库锁分为乐观锁和悲观锁。
乐观锁认为并发访问不会引起冲突,只在提交时检查是否有冲突发生,如果有则回滚操作。 悲观锁认为并发访问可能会引起冲突,因此在访问数据时就加锁,确保并发操作的安全性。
4.MySQL中InnoDB引擎的行锁模式及其是如何实现的?
行锁模式
在存在行锁和表锁的情况下,一个事务想对某个表加x锁时,需要先检查是否有其他事务对这个表加了锁或者对这个表的某一行加了锁,对表的每一行都进行检测这一次这是非常低效率的,为了解决这种问题,实现多粒度锁机制,InnoDB还有两种内部使用的意向锁,两种意向锁都是表锁。
1.意向共享锁:简称IS锁,一个事务打算给数据行加共享锁前必须先获得该表的IS锁。
2.意向排他锁:简称IX锁,一个事务打算给数据行加排他锁前必须先获得该表的IX锁
有了意向锁,一个事务想对某个表加X锁,只需要检查是否有其他事务对这个表加了X/IX/S/IS锁即可,
锁的兼容性如下:
行锁实现的方式:InnoDB的行锁是通过给索引上的索引项加锁实现的,如果没有索引,InnoBD将通过隐藏的聚簇索引来对记录进行加锁。
InnoDB行锁主要分为三种情况:
Record lock:对索引项加锁
Grap lock 对索引之间的间隙、第一条记录前的间隙或最后一条后的间隙加锁。
Next-key lock:前两种放入组合,对记录及前面的间隙加锁。
InnoDB行锁的特性:如果不通过索引条件检索数据,那么InnoDB将对表中所有记录加锁,世纪产生的效果和表锁一样的。
MVCC不能解决幻读问题,在可重复读隔离级别下,使用MVCC+Next-keys Locks可以解决幻读问题。
5.什么是数据库的乐观锁和悲观锁,如何实现?
乐观锁:是一种乐观的认为并发访问不会产生冲突的锁机制。在使用乐观锁时,系统不会阻塞任何一个线程,而是允许多个线程同时访问共享资源。当一个线程要更新共享资源时,它会先读取当前的版本号或时间戳,并将该值保存在本地。当线程提交更新时,它会将保存的版本号或时间戳与当前的版本号或时间戳进行比较,如果相同,则说明没有其他线程在该线程读取数据之后修改了共享资源,该线程可以成功提交更新。如果不同,则说明有其他线程修改了共享资源,该线程更新失败,需要重新读取数据并再次尝试更新。
乐观锁的实现通常基于版本号或时间戳等机制。在关系型数据库中,可以在表中添加一个版本号或时间戳字段,并在更新时将该字段的值加一或更新为当前时间戳,以实现乐观锁。
悲观锁是一种悲观的认为并发访问会产生冲突的锁机制。在使用悲观锁时,系统会阻塞其他线程对共享资源的访问,只有当前线程完成对共享资源的访问后,其他线程才能访问该资源。悲观锁的实现通常基于互斥锁等机制,在对共享资源进行操作时加锁,在操作完成后释放锁,以确保同一时间只有一个线程可以访问共享资源。
悲观锁的实现通常是通过线程同步机制来实现的,如Java中的synchronized关键字或Lock接口。在多线程环境
6.什么是死锁?如何避免?
死锁是指两个或者两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象。在MySQL中,MyISAM是一次获得所需的全部锁,要么全部满足,要么等待,所以不会出现死锁。在InnoDB储存引擎,除了单个Sql组成的事务外,锁都是逐步获得的,所以存在死锁问题。
如何避免MySql发生死锁或者锁冲突:
1.避免使用多个锁:尽可能减少代码中使用多个锁的情况,可以减少死锁的概率。
2.加锁顺序:对于需要多个锁的情况,要按照相同的顺序加锁,以避免不同的线程或进程以不同的顺序获取锁而导致死锁。
3.超时机制:在获取锁时,设置超时时间,如果在规定时间内未能获取到锁,则主动释放已持有的锁,避免长时间等待导致死锁。
4.死锁检测与恢复:在程序运行过程中,周期性地检测是否存在死锁的情况,如果存在,则通过释放某些资源或者中断某些线程来解除死锁状态。
5.资源限制:对于不同的资源,可以限制它们的使用数量,以减少相互竞争的情况,从而降低死锁的概率。
总之,避免死锁需要在设计阶段就考虑到多线程或多进程之间的相互依赖关系,并采取合适的措施来减少死锁的概率