mysql锁

mysql锁

参考:https://blog.youkuaiyun.com/xifeijian/article/details/20313977

MyIsam支持表级锁

InnoDB支持表级锁,行级锁 ,但是默认是行级锁

  • 表级锁:
    • 开销小
    • 加锁快
    • 不会出现死锁!!
    • 锁定粒度大
    • 发生冲突概率最高
    • 并发度最低
  • 行级锁
    • 开销大
    • 加锁慢
    • 会出现死锁!!
    • 锁定粒度最小
表级锁(MyISam引擎)

两种模式:表共享读锁,表独占写锁

当一个用户对表进行读操作时,其他用户可以进行读操作,不能进行写操作

当一个用户对表进行写操作时,其他用户什么操作都不能动

为什么表级锁不会产生死锁??见第二点

  • MyIsam在执行查询语句的时候,会自动给所需要查询的表进行加锁操作的,不需要手动添加,只不过我们学习的时候进行手动添加
    • Lock tables A read local, A_deatils read local
  • **在用LOCK TABLES给表显式加表锁时,必须同时取得所有涉及到表的锁,并且MySQL不支持锁升级。也就是说,在执行LOCK TABLES后,只能访问显式加锁的这些表,不能访问未加锁的表;****同时,如果加的是读锁,那么只能执行查询操作,而不能执行更新操作。*其实, *在自动加锁的情况下也基本如此,MyISAM总是一次获得SQL语句所需要的全部锁。这也正是MyISAM表不会出现死锁(Deadlock Free)的原因。
  • 当使用LOCK TABLES时,不仅需要一次锁定用到的所有表,而且,同一个表在SQL语句中出现多少次,就要通过与SQL语句中相同的别名锁定多少次,否则也会出错!
表级锁–MyISam引擎—串行和并行

MyISam表的读和写是串行的,但这是就总体而言的,在一定的条件下,MyISam表也支持查询和插入操作的并发过程

这个一定的条件指的是:

  • MyISam存储引擎有一个系统变量concurrent_insert,专门用来控制并发插入的行为,值可以为0,1,2
  • 当concurrent_insert设置为0时,不允许并发插入。
  • 当concurrent_insert设置为1时,如果MyISAM表中没有空洞(即表的中间没有被删除的行),MyISAM允许在一个进程读表的同时,另一个进程从表尾插入记录。这也是MySQL的默认设置
  • 当concurrent_insert设置为2时,无论MyISAM表中有没有空洞,都允许在表尾并发插入记录。
  • MySQL的MYISam引擎默认允许当前session为读锁的时候,当前sesssion不允许插入和更新;;其他session允许进行插入操作,但是update不允许。
表级锁–MySIam引擎–锁调度

MyISam存储引擎的读锁和写锁是互斥的,读写操作是串行的

  • 问题一:当一个进程请求某个MyISam表的读锁,另外一个进行请求该表的写锁,MySQL如何处理
    • 写进程先获得锁,不仅如此,即使读请求先到锁等待队列,写请求后到,写请求也会直接插队到读请求之前。因为MySQL任务写请求比读请求更重要
    • 上面这个也会产生一个问题,当面临的大规模的更新操作和查询操作的时候,mySiam就不适合了,因为可能会导致查询操作很难获得读锁,从而永远堵塞。但是这里可以手动设置参数ow-priority-updates设置这里个操作的优先级,或者设置mx_write_lock_count,当读锁达到这个值的时候,就暂时将写请求的优先级降低,给读进程获得锁的机会。
行级锁–Innodb引擎(现在用的就是这个)

最大的特点就是比MYIsam引擎加上了 事务+行级锁

  • 事务的引进(并行事务处理)导致的问题
    • ****更新丢失(Lost Update):****当两个或多个事务选择同一行,然后基于最初选定的值更新该行时,由于每个事务都不知道其他事务的存在,就会发生丢失更新问题--最后的更新覆盖了由其他事务所做的更新。例如,两个编辑人员制作了同一文档的电子副本。每个编辑人员独立地更改其副本,然后保存更改后的副本,这样就覆盖了原始文档。最后保存其更改副本的编辑人员覆盖另一个编辑人员所做的更改。如果在一个编辑人员完成并提交事务之前,另一个编辑人员不能访问同一文件,则可避免此问题。
    • **脏读(Dirty Reads):**一个事务正在对一条记录做修改,在这个事务完成并提交前,这条记录的数据就处于不一致状态;这时,另一个事务也来读取同一条记录,如果不加控制,第二个事务读取了这些“脏”数据,并据此做进一步的处理,就会产生未提交的数据依赖关系。这种现象被形象地叫做"脏读"。
    • ****不可重复读(Non-Repeatable Reads):****一个事务在读取某些数据后的某个时间,再次读取以前读过的数据,却发现其读出的数据已经发生了改变、或某些记录已经被删除了!这种现象就叫做“不可重复读”
    • ****幻读(Phantom Reads):****一个事务按相同的查询条件重新读取以前检索过的数据,却发现其他事务插入了满足其查询条件的新数据,这种现象就称为“幻读”。

image-20220517164650250

行级锁模式和加锁方法
行锁类型
  • 共享锁;相当于Myisam的读锁,,允许事务去读一行,阻止其他事务获得相同数据集的排他锁(写锁)
  • 排它锁:相当于Myisam的写锁,允许获得排它锁的事务更新数据,阻止其他事务获得相同数据集的共享读锁和排他写锁
行锁表锁共存
  • Innodb是两个锁并存的,除了上面的共享锁和排它锁,Innodb内部使用了意向锁两种(就是tm的myisam表锁的两种)
    • 意向共享锁:事务打算给数据行加行共享锁,事务在给一个数据行加共享锁前必须先取得该表的IS锁。
    • 意向排它锁:事务打算给数据行加行排他锁,事务在给一个数据行加排他锁前必须先取得该表的IX锁。
行级锁Innodb实现方式
  1. 通过给索引项加锁来实现的,只有通过索引条件检索数据,Innodb才使用行级锁,否则Innobd使用表锁!!
  2. 由于mysql的行锁是针对索引加的锁,不是针对记录加的锁,所以虽然是访问不同行的记录,但是如果是访问相同的索引键,是会出现锁冲突的!
死锁介绍:

上面说过,Myisam表锁是deadlock free的,这是因为MyISam总是一次获得所需的全部锁,要不全部满足,要么等待,因此不会出现死锁!

但是在Innodb中,除了单个SQL组成的事务外,锁是逐步获得的,这就决定了在InnoDb中发生死锁是可能的

  • 发生死锁后,InnoDB一般都能自动检测到,并使一个事务释放锁并回退,另一个事务获得锁,继续完成事务。但在涉及外部锁,或涉及表锁的情况下,InnoDB并不能完全自动检测到死锁,这需要通过设置锁等待超时参数 innodb_lock_wait_timeout来解决。需要说明的是,这个参数并不是只用来解决死锁问题,在并发访问比较高的情况下,如果大量事务因无法立即获得所需的锁而挂起,会占用大量计算机资源,造成严重性能问题,甚至拖跨数据库。我们通过设置合适的锁等待超时阈值,可以避免这种情况发生。
规避死锁方法:

个参数并不是只用来解决死锁问题,在并发访问比较高的情况下,如果大量事务因无法立即获得所需的锁而挂起,会占用大量计算机资源,造成严重性能问题,甚至拖跨数据库。我们通过设置合适的锁等待超时阈值,可以避免这种情况发生。

规避死锁方法:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值