您的位置:首页 > 数据库

【事务系列3】锁,你的兄弟姐妹还能再多点吗?

2016-03-12 15:56 218 查看
在很长的一段时间里,我对数据库中锁的概念都处于一种蒙圈的状态。

锁是什么?锁的出现是为了解决什么问题?锁的类型究竟有哪些?为什么有悲观锁、乐观锁,又有行级锁、表级锁等等的称呼?

在数据库中,锁就像拦路虎,但可惜我不是武松,就算是喝了三杯,依然被这头猛虎摁趴在路上。

1.锁是什么?

锁是计算机协调多线程或者进程在并发请求同一资源的一种策略。在《事务的隔离级别以及低隔离级别下的数据异常情况》也写过,在并发情况下,会出现的各种数据问题,而数据库的锁,则是为了解决这些问题而出现的。

为了在高并发情况下,保证数据的一致性与数据运算的平衡,我们引入了隔离性这一概念。我们将高并发的情况,拆分成多个事务,这些事务具备原子性,最理想的状态,这些事务互不影响,即事务间的隔离性最高,这种串行的情况无法满足高性能的数据运算,因此我们很少用到这种隔离策略,我们更多的是为了兼顾性能以及数据一致采用了次一级的隔离策略:提交读(Read Commited),不可提交读(UnRead Commited),然而我们是如何去实现这种隔离策略的呢?这就引入锁这种概念。

我们将锁分成两种:

(1)悲观锁

(2)乐观锁

2.什么是悲观锁?什么是乐观锁?

乐观锁:乐观锁认为数据在一般情况下都不会造成冲突,因此只有在数据提交更改时,才会对是否冲突进行检测,一旦发现真的冲突了,则会回退并返回错误信息让用户进行操作判定

悲观锁:悲观锁则对数据的修改持一种保守的态度,在数据进行操作的过程中,他都保持一种锁定的状态,避免其他事务对数据进行操作。

可以这么认为,悲观锁以及乐观锁是锁机制的两种思路,其中实现的方法也不相同。在这里,为了提高锁的性能,我们又将锁进行颗粒度的划分:表锁、行锁等,同时也进行各种性质的划分:排它锁、共享锁、意向共享锁以及意向排它锁等。

3.锁的颗粒度

锁的颗粒度,通俗来理解,就是由锁进行锁定的数据范围大小。一般数据库的最小锁的颗粒度都会到行级别。行级别的锁,颗粒度相应较小,但是由于取锁以及去锁的流程比较复杂,所以带来系统性能的开销也相应变得比较大,此外由于在并发情况下,也会出现死锁的现象(多个锁彼此等待对方)。当然,颗粒度较小的锁可以应对高并发的请求。

表级锁相应的颗粒度较大,一旦获取了表级锁,那么整张表都会被锁定,使得其他数据操作无法进行。这种级别的锁,比较难出现死锁,解锁以及取锁的逻辑也简单的多,当然带来的负面影响就是比较难应对高并发的请求现象。

在不同的存储引擎设计思路中,锁的颗粒度级别设计也不尽相同。以MyISAM和InnoDB为例。由于MyISAM是非事务性的存储引擎,它更加倾向的粗放式的管理,他讲究的是性能开销的最小化,因此它采用的是表级锁的颗粒度。而InnoDB是事务性的存储引擎,它对数据在高并发情况下保持准确性更加敏感,所以它采用了行级锁这种细颗粒度的级别。

4.锁的性质划分

除了以锁的颗粒度进行划分,还有其他方式来对锁进行划分。根据锁的行为特征的不同,这里又将锁划分为排它锁、共享锁、意向共享锁以及意向排它锁等。

关于排它锁、共享锁、意向共享锁以及意向排它锁这里只提供他的概念参考,至于更深入的讨论会单独写文章来进行讨论。

共享锁:当一个数据资源被共享锁锁定后,它还能被另一个共享锁进行再次锁定

排它锁:当一个数据资源被排它锁锁定后,它无法再被其他锁进行锁定,直到被排它锁进行释放。

意向锁:意向锁的作用就是当一个事务在需要获取资源锁定的时候,如果遇到自己需要的资源已经被排他锁占用的时候,该事务可以需要锁定行的表上面添加一个合适的意向锁。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息