数据库中有那些锁?他们是区别是什么?

149 阅读4分钟

行锁和表锁

1.针对粒度划分,一般分为行锁、表锁、库锁

(1)行锁:访问数据库的时候,锁定整个行的数据,防止并发错误

(2)表锁:访问数据库的时候,锁定整个表的数据,防止并发错误

(3)库锁:全局锁,确保了在锁住期间,整个数据库的完整性和一致性;但也可能会出现以下问题:

  a.单点故障:如果数据库出现问题,整个系统可能会瘫痪。
  b.性能开销:全局锁会导致大量的等待和锁竞争,严重影响系统性能。
  c.死锁风险:如果锁未被正确释放,可能导致死锁情况,使得其他操作无法进行。

2.行锁和表锁的区别

  • 表锁:开销小,加锁快,不会出现死锁;锁定力度大,发生锁冲突概率高,并发度低;表级锁因为是锁定整张表格,所以适用于并发性不高,以查询为主,少量更新的应用,就是多读少写;
  • 行锁:开销大,加锁慢,会出现死锁;锁定力度小,发生锁冲突几率低,并发度高;行锁适用于高并发环境下,对事务完整性要求高的系统,如在线事务处理系统;

悲观锁和乐观锁

1.悲观锁:顾名思义,就是很悲观,每次去拿数据的时候,都认为别人会修改,所以每次拿数据都会上锁,这样别人想拿这个锁就会block直到它拿到锁;行锁、表锁等,读锁、写锁等,都是在操作之前先上锁,用到了这种锁机制;

2.乐观锁:顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,在更新的时候回去判断一下此期间有没有人去更新这个数据,一般使用版本号或者时间戳来判断;

3.乐观锁和悲观锁的区别:乐观锁适用于多读少写的场景,这样可以提高吞吐量;悲观锁则和乐观锁相反适用于多写少读,经常产生冲突的场景;

共享锁、独享锁

1.共享锁: 共享锁指的是对于多个不同的事务,对于同一个资源共享同一个锁;相当于一把锁有多把钥匙,这几把钥匙都可以打开房门。共享锁也是悲观锁的一种;执行SQL时在语句后面加上lock in share mode就代表对某些资源加上共享锁了;

SELECT * FROM t WHERE c=5 LOCK IN SHARE MODE;  

共享锁在当前事务结束时自动释放。如果是自动提交模式,那么在执行完加锁的查询后,事务就会结束,锁也会被释放。如果是在事务中,需要执行 COMMIT 或 ROLLBACK 来结束事务,并释放锁。 2.独享锁: 是指该锁一次只能被一个线程持有;

在实际应用中,都是读锁使用共享锁保证并发可读,写操作使用独享锁保证数据唯一性

公平锁、非公平锁

1.公平锁: 顾名思义,就是很公平的锁;在并发环境下,每个线程获取锁前都会优先查看此锁维护的等待队列,如果为空亦或当前线程是队列的第一个,就占有锁,否则就加入到等待队列中,按照先进先出(FIFO) 的规则获取锁;公平锁的优点就是不会有锁饿死,缺点就是整体吞吐效率相对于非公平锁要低,等待队列中除去队列第一个线程,其他的所有的线程都会阻塞,这就增加了CPU唤醒阻塞锁的开销; 2.非公平锁: 顾名思义,就是不公平的锁,不按照先进先出的机制去排队,上来就先试试插队,先直接就尝试占有锁,如果尝试插队失败,再去按照先进先出的机制排队;非公平锁的优点就是当他上来就获取到锁了,这个线程就不需要阻塞再被唤醒,减少线程唤醒的开销,整体吞吐量就高了;这样就又会带来一个问题,如果有线程能一直插队成功,那后面等待的线程就会等待很久才能获取到锁或者可能被饿死;

分段锁

分段锁其实是一种锁的设计方案,并不是具体的一种锁;例如ConcurrentHashMap就是用分段锁的形式来实现高效的并发操作的;以它来说就是HashMap的数据结构是由数组+链表/红黑树实现的,将某个hashCode进行加锁(即该hashCode即为一个分段),除非也是操作这个hashCode的数据,否则都是并行处理;