数据库——锁


title: 数据库——锁
date: 2024-07-06 12:25:15
tags: 数据库
categories: 数据库
cover: /image/T2.jpg
description: 数据库里对锁的应用,锁的一些相关知识

在数据库管理和并发编程中,锁(Locks)是一种重要的同步机制,用于控制多个用户对共享资源的访问,以避免数据的不一致性和冲突。锁的主要目的是确保在给定时间内,只有一个事务(或进程、线程)可以访问特定的数据或资源。

锁的类型
  1. 共享锁(Shared Locks, S锁)

    • 允许多个事务同时读取同一资源,但禁止任何事务写入该资源。也称为读锁。
    • 当事务对数据加上S锁后,其他事务可以继续加S锁,但如果其他事务想加排他锁(X锁)则必须等待该事务释放S锁。
  2. 排他锁(Exclusive Locks, X锁)

    • 允许事务独占访问特定资源,即加锁期间既不允许其他事务读取,也不允许写入。也称为写锁。
    • 当事务对数据加上X锁后,其他事务不能对其加任何类型的锁,直到该锁被释放。
  3. 意向锁(Intention Locks)

    • 是一种特殊的表级锁,表示事务将来可能对表中的行加锁。意向锁分为意向共享锁(IS锁)和意向排他锁(IX锁)。
    • 意向锁的主要目的是表明事务的锁定意向,以提高锁定的效率。例如,在添加行级X锁之前,需要先在表上加IX锁,这样其他事务在尝试对表加S锁或X锁时就可以快速判断是否有冲突。
  4. 记录锁(Record Locks)

    • 锁定数据库表中的一条记录。
  5. 间隙锁(Gap Locks)

    • 锁定一个范围,但不包括记录本身。主要用于防止幻读。
  6. 临键锁(Next-Key Locks)

    • 是记录锁和间隙锁的组合,锁定一个范围并包括记录本身。MySQL的InnoDB存储引擎默认使用临键锁来防止幻读。
锁的特性
  • 互斥性:任何时刻,只有一个事务可以持有锁。
  • 可见性:锁定的资源对其他事务是不可见的,直到锁被释放。
  • 死锁:两个或多个事务在执行过程中,因争夺资源而造成的一种相互等待的现象。数据库管理系统需要检测和解决死锁问题。

锁的管理

  • 锁的粒度:决定了锁定资源的大小,可以是数据库、表、页或行。锁的粒度越小,系统的并发性越高,但管理锁的开销也越大。
  • 锁的策略:包括悲观锁(Pessimistic Locking)和乐观锁(Optimistic Locking)两种。悲观锁假定最坏的情况,在数据处理前就加锁;乐观锁则假设不会发生并发冲突,只在更新数据时检查是否有冲突。

在数据库设计中,合理地使用锁机制是保证数据一致性和完整性的关键。然而,过度的锁定会导致性能下降,因此需要根据具体的应用场景和需求来选择合适的锁策略和粒度。

事务隔离级别与锁
  • 在 读取未提交 隔离级别下,读取数据不需要加 共享锁,这样就不会跟被修改的数据上的 排他锁 冲突;

  • 在 读取已提交 隔离级别下,读操作需要加 共享锁,但是在语句执行完以后释放共享锁;

  • 在 可重复读 隔离级别下,读操作需要加 共享锁,但是在事务提交之前并不释放共享锁,也就是必须等待事务执行完毕以后才释放共享锁;

  • 可串行化 是限制性最强的隔离级别,因为该级别 锁定整个范围的键,并一直持有锁,直到事务完成

死锁与解决
死锁简述

死锁是指两个或多个进程在执行过程中,因争夺资源而造成的一种相互等待的现象,若无外力作用,这些进程都将无法向前推进。具体来说,当一组进程中的每个进程都在等待另一个进程所占有的资源时,这组进程就发生了死锁。

死锁的产生通常源于多个进程对资源的争夺,主要包括以下几点:

  1. 系统资源不足:系统分配给进程的资源不足以满足所有进程的需求。
  2. 进程运行推进的顺序不当:进程推进顺序不当也可能导致死锁。
  3. 资源分配不当:资源分配策略不合理,如资源分配不均匀或过于集中。
死锁产生的必要条件
  1. 互斥条件:进程在运行中对资源进行排他性使用,即一个资源仅能被一个进程使用,此时其他进程请求资源时,只能等待其释放。
  2. 请求与保持条件:某进程已经保持了一个资源,但又请求另一个资源,若该资源被其他进程占有,此时请求阻塞,且对已经占有的资源不释放。
  3. 不可抢占条件:进程获得的资源在未使用完时不可被抢占,只能在进程使用完时自己释放。
  4. 循环等待条件:发生死锁时,必然存在这样一个循环,一个进程p1等待p2占有的资源,进程p2等待p3占有的资源……进程pn等待p1占有的资源。
死锁的解决办法
  1. 死锁预防

    • 这是一种较简单和直观的事先预防的方法。通过设置某些限制条件,去破坏产生死锁的四个必要条件中的一个或者几个,来预防发生死锁。但这种方法可能会导致系统资源利用率和系统吞吐量降低。
  2. 死锁避免

    • 系统对进程发出的每一个系统能够满足的资源申请进行动态检查,并根据检查结果决定是否分配资源。如果分配后系统可能发生死锁,则不予分配,否则予以分配。这是一种保证系统不进入死锁状态的动态策略。
  3. 死锁检测和解除

    • 先检测:不须事先采取任何限制性措施,也不必检查系统是否已经进入不安全区。允许系统在运行过程中发生死锁,但可通过系统所设置的检测机构,及时地检测出死锁的发生,并精确地确定与死锁有关的进程和资源。检测方法包括定时检测、效率低时检测、进程等待时检测等。
    • 然后解除死锁:采取适当措施,从系统中将已发生的死锁清除掉。常用的实施方法是撤销或挂起一些进程,以便回收一些资源,再将这些资源分配给已处于阻塞状态的进程,使之转为就绪状态,以继续运行。
  4. 其他具体方法

    • 按序加锁:确保所有的线程都是按照相同的顺序获得锁,这样可以有效防止循环等待条件的出现。
    • 尝试加锁超时:线程在尝试获取锁时设置一个超时时间,如果超时则放弃对该锁的请求,并释放已经占有的锁,然后等待一段时间后重试。
    • 锁排序和分组:将锁按照一定的规则进行排序或分组,并规定严格的加锁顺序,以减少死锁的发生。
    • 使用无锁数据结构:通过原子操作等无锁机制来实现并发控制,从而避免死锁的发生。
乐观锁和悲观锁
乐观锁
  • 核心思想:乐观锁认为数据在多个事务之间很少会发生冲突,因此在读取数据时不对其加锁。当更新数据时,会检查数据是否自上次读取后已被其他事务修改(通常通过版本号或时间戳)。

  • 优点:并发性能好,因为读取数据时不加锁。

  • 缺点:在高并发情况下,可能会出现较多的更新冲突,需要重试。

悲观锁
  • 核心思想:悲观锁认为数据在多个事务之间很容易发生冲突,因此在读取数据时立即加锁,以防止其他事务修改数据。

  • 优点:数据一致性好,能够防止数据在并发环境下被多个事务同时修改。

  • 缺点:并发性能较低,因为读取数据时就需要加锁,可能阻塞其他事务的访问。

简而言之,乐观锁适合读多写少的场景,而悲观锁适合写多读少的场景。

  • 28
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值