并发控制
在计算机科学,特别是程序设计、操作系统、多处理机和数据库等领域,并发控制(英语:Concurrency control)是确保及时纠正由并发操作导致的错误的一种机制。(维基百科)
数据库中的并发控制
简单来说并发控制的任务就是多个事务对同一数据同一时间进行操作时,不会破坏事务的正确性。
例如:现有两处火车票售票点,同时读取某一趟列车车票数据库中车票余额为 X。两处售票点同时卖出一张车票,同时修改余额为 X -1写回数据库,这样就造成了实际卖出两张火车票而数据库中的记录却只少了一张。
技术手段
封锁
锁(LOCKING)是最常用的并发控制机构,是确保及时纠正由并发操作导致的错误的一种机制。
一般说来,获得锁并不是禁止其他事务对加锁的数据的读/写,而是阻塞了其他事务对这些数据的加锁操作。例如,如果一般的select语句根本不申请加锁,所以能直接读取其他事务已经加了互斥锁的数据。
分类
按照粒度:
表锁页锁记录锁(行锁)按照使用方式:
互斥锁(exclusive lock,读锁)共享锁(sharing lock,写锁)
悲观并发控制(悲观锁)
它可以阻止一个事务以影响其他用户的方式来修改数据。如果一个事务执行的操作读某行数据应用了锁,那只有当这个事务把锁释放,其他事务才能够执行与该锁冲突的操作。
悲观的向着’坏的’方向想着,总是假设最坏的情况。
一般的关系型数据库中都使用到了”悲观锁”这种机制,比如:表锁 页锁 行锁 读锁 写锁,这些都是在操作之前先上锁,在本次事务完之前其他的事务无法进行数据的操作。
悲观锁的特点
一般的关系数据库默认会在修改完数据之后自动提交修改操作,也就是在更改完之后会自动释放锁。
在效率方面,处理加锁的机制会让数据库产生额外的开销,还有增加产生死锁的机会;并且他会降低并行性,一个事务如果锁定了某行数据,其他事务就必须等待该事务处理完才可以处理那行数据。
乐观并发控制(乐观锁)
它假设多用户并发的事务在处理时不会彼此互相影响,各事务能够在不产生锁的情况下处理各自影响的那部分数据。在提交数据更新之前,每个事务会先检查在该事务读取数据后,有没有其他事务又修改了该数据。如果其他事务有更新的话,正在提交的事务会进行回滚。
乐观的向着’好的’方向想着,总是假设最好的情况。
一般认为,每次去读取数据的时候都不会有其他操作去进行数据的修改,从而不会对事务的正确性产生破坏。也因为此读取数据时不会使用数据库的锁机制,所以会使数据的吞吐量提高,但这样的操作会使读取的数据不会有完全的正确性,在对数据的准确性没有很高的要求下可使用此操作。当然他也有拥有准确性的实现方式。
乐观锁的实现
版本号机制
CAS算法
乐观锁的缺点
- ABA问题
- 循环时间长开销大
- 只能保证一个共享变量的原子操作
随着”三高架构”(高并发、高性能、高可用)的提出,乐观锁越来越被用到更多的地方。
锁实现
语言级别 lock 关键字
RedLock 分布式锁
参考:
https://www.cnblogs.com/qlqwjy/p/7798266.html
https://www.cnblogs.com/kyoner/p/11318979.html
https://blog.csdn.net/qq_34337272/article/details/81072874
https://zh.wikipedia.org/wiki/%E5%B9%B6%E5%8F%91%E6%8E%A7%E5%88%B6