美文网首页
数据库_锁

数据库_锁

作者: 仁安天下 | 来源:发表于2019-11-30 10:40 被阅读0次

六、数据库锁
1.mysql都有什么锁,死锁判定原理和具体场景,死锁怎么解决?
MySQL有三种锁的级别:页级、表级、行级。

表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。
行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般
什么情况下会造成死锁?
什么是死锁?

死锁: 是指两个或两个以上的进程在执行过程中。因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等竺的进程称为死锁进程。

表级锁不会产生死锁.所以解决死锁主要还是针对于最常用的InnoDB。

死锁的关键在于:两个(或以上)的Session加锁的顺序不一致。

那么对应的解决死锁问题的关键就是:让不同的session加锁有次序。

死锁的解决办法?

1.查出的线程杀死 kill
SELECT trx_MySQL_thread_id FROM information_schema.INNODB_TRX;

2.设置锁的超时时间
Innodb 行锁的等待时间,单位秒。可在会话级别设置,RDS 实例该参数的默认值为 50(秒)。

生产环境不推荐使用过大的 innodb_lock_wait_timeout参数值
该参数支持在会话级别修改,方便应用在会话级别单独设置某些特殊操作的行锁等待超时时间,如下:
set innodb_lock_wait_timeout=1000; —设置当前会话 Innodb 行锁等待超时时间,单位秒。

3.指定获取锁的顺序

2.有哪些锁(乐观锁悲观锁),select 时怎么加排它锁?
悲观锁(Pessimistic Lock):

悲观锁特点:先获取锁,再进行业务操作。

即“悲观”的认为获取锁是非常有可能失败的,因此要先确保获取锁成功再进行业务操作。通常所说的“一锁二查三更新”即指的是使用悲观锁。通常来讲在数据库上的悲观锁需要数据库本身提供支持,即通过常用的select … for update操作来实现悲观锁。当数据库执行select for update时会获取被select中的数据行的行锁,因此其他并发执行的select for update如果试图选中同一行则会发生排斥(需要等待行锁被释放),因此达到锁的效果。select for update获取的行锁会在当前事务结束时自动释放,因此必须在事务中使用。
悲观锁分类:
1、共享锁(s锁):
也称读锁,事务A对对象T加s锁,其他事务也只能对对象T加s锁,多个事务能同时读,但不能进行同时写操作,直到事务A释放s锁
2、排他锁(x锁):
也称写锁,事务A对对象T加x锁,其他事务不能对对象加锁,直到事务A释放X锁
3、更新锁(u锁):
允许其他事务读,但不允许再施加U锁或x锁;更新锁只允许存在一个。当被读取的对象将要更新时,则升级为X锁。更新锁一般是为了解决多个线程获取共享锁后,企图更新数据(加排他锁做写操作,但要等待其他线程释放共享锁,两个或多个线程互相等待释放共享锁而导致死锁)死锁的情况。

补充:
不同的数据库对select for update的实现和支持都是有所区别的,

oracle支持select for update no wait,表示如果拿不到锁立刻报错,而不是等待,MySQL就没有no wait这个选项。
MySQL还有个问题是select for update语句执行中所有扫描过的行都会被锁上,这一点很容易造成问题。因此如果在MySQL中用悲观锁务必要确定走了索引,而不是全表扫描。
乐观锁(Optimistic Lock):

1.乐观锁,也叫乐观并发控制,它假设多用户并发的事务在处理时不会彼此互相影响,各事务能够在不产生锁的情况下处理各自影响的那部分数据。在提交数据更新之前,每个事务会先检查在该事务读取数据后,有没有其他事务又修改了该数据。如果其他事务有更新的话,那么当前正在提交的事务会进行回滚。

2.乐观锁的特点先进行业务操作,不到万不得已不去拿锁。即“乐观”的认为拿锁多半是会成功的,因此在进行完业务操作需要实际更新数据的最后一步再去拿一下锁就好。
乐观锁在数据库上的实现完全是逻辑的,不需要数据库提供特殊的支持。

3.一般的做法是在需要锁的数据上增加一个版本号,或者时间戳,

实现方式举例如下:

乐观锁(给表加一个版本号字段) 这个并不是乐观锁的定义,给表加版本号,是数据库实现乐观锁的一种方式。

SELECT data AS old_data, version AS old_version FROM …;
根据获取的数据进行业务操作,得到new_data和new_version
UPDATE SET data = new_data, version = new_version WHERE version = old_version
if (updated row > 0) {

// 乐观锁获取成功,操作完成

} else {

// 乐观锁获取失败,回滚并重试

}

注意:

乐观锁在不发生取锁失败的情况下开销比悲观锁小,但是一旦发生失败回滚开销则比较大,因此适合用在取锁失败概率比较小的场景,可以提升系统并发性能
乐观锁还适用于一些比较特殊的场景,例如在业务操作过程中无法和数据库保持连接等悲观锁无法适用的地方。
总结:
悲观锁和乐观锁是数据库用来保证数据并发安全防止更新丢失的两种方法,例子在select ... for update前加个事务就可以防止更新丢失。悲观锁和乐观锁大部分场景下差异不大,一些独特场景下有一些差别,一般我们可以从如下几个方面来判断。

响应速度: 如果需要非常高的响应速度,建议采用乐观锁方案,成功就执行,不成功就失败,不需要等待其他并发去释放锁。'

冲突频率: 如果冲突频率非常高,建议采用悲观锁,保证成功率,如果冲突频率大,乐观锁会需要多次重试才能成功,代价比较大。

重试代价: 如果重试代价大,建议采用悲观锁。

相关文章

  • mysql进阶-行级锁、表级锁、乐观锁、悲观锁

    从应用的角度来看数据库锁可分为悲观锁、乐观锁从数据库(InnoDB)的角度看,数据库锁可以分为行级锁和表级锁 1....

  • 两端锁协议

    1、数据库锁 数据库锁粒度划分:行锁、页锁、表锁。共享锁:读锁、S锁。事务T可以对A进行读取,其他事务只能读取而不...

  • MySQL05

    数据库高级对象,锁,权限管理 视图 索引 触发器 存储过程 悲观锁与乐观锁 行级锁、表级锁、页锁 数据库权限管理 ...

  • 数据库如何加锁?锁是用来干嘛的?

    数据库中的共享锁与排它锁 共享锁(S锁),又称为读锁,如果数据对象加上共享锁之后,则该数据库对象可以被其他事务查看...

  • 秒杀系统技术方案演变过程

    前言:秒杀系统需要保证商品库存不能出现超卖现象。一、数据库锁机制(悲观锁、乐观锁)实现秒杀(1)悲观锁:数据库本身...

  • mysql全局锁和表锁

    MySQL中的锁可以分为三类:全局锁,表级锁和行锁。 全局锁 全局锁是对整个数据库加锁,可以让整个数据库处于只读状...

  • 多线程之锁

    其实常用也就那么几个锁,总感觉线程所用的锁机制和数据库的很相似,什么读写锁,就和数据库的共享锁,排他锁没什么区别....

  • 解决并发问题,数据库常用的两把锁!

    在写入数据库的时候需要有锁,比如同时写入数据库的时候会出现丢数据,那么就需要锁机制。 数据锁分为乐观锁和悲观锁 它...

  • Java面试必备之数据库乐观锁和悲观锁分析!

    在写入数据库的时候需要有锁,比如同时写入数据库的时候会出现丢数据,那么就需要锁机制。 数据锁分为乐观锁和悲观锁 它...

  • DataFountain PHP面试

    数据库锁数据库锁方面这篇文章总结的挺好的 数据库锁总结 线程模型及原理操作系统核心原理-4.线程原理(上):线程基...

网友评论

      本文标题:数据库_锁

      本文链接:https://www.haomeiwen.com/subject/vgxowctx.html