数据库管理系统(DBMS)中的并发控制的任务是确保在多个事务同时存取数据库中同一数据时不破坏事务的隔离性和统一性以及数据库的统一性。
乐观并发控制(乐观锁)和悲观并发控制(悲观锁)是并发控制主要采用的技术手段,具有强烈的独占和排他特性。
悲观锁
这种借助数据库锁机制在修改数据之前先锁定,再修改的方式被称之为悲观并发控制
悲观锁主要分为共享锁或排他锁
- 共享锁【Shared lock】又称为读锁,简称S锁。顾名思义,共享锁就是多个事务对于同一数据可以共享一把锁,都能访问到数据,但是只能读不能修改。
- 排他锁【Exclusive lock】又称为写锁,简称X锁。顾名思义,排他锁就是不能与其他锁并存,如果一个事务获取了一个数据行的排他锁,其他事务就不能再获取该行的其他锁,包括共享锁和排他锁,但是获取排他锁的事务是可以对数据行读取和修改。
悲观锁的流程如下:
- 在对记录进行修改前,先尝试为该记录加上排他锁(exclusive locking)。
- 如果加锁失败,说明该记录正在被修改,那么当前查询可能要等待或者抛出异常。具体响应方式由开发者根据实际需要决定。
- 如果成功加锁,那么就可以对记录做修改,事务完成后就会解锁了。
- 期间如果有其他对该记录做修改或加排他锁的操作,都会等待解锁或直接抛出异常。
悲观并发控制实际上是“先取锁再访问”的保守策略,为数据处理的安全提供了保证。
在mysql中,for update是一种行级锁,为排它锁。一旦用户对某个行施加了行级锁,则该用户可以查询也可以更新被加锁的数据行,其它用户只能查询但不能更新被加锁的数据行。如果其它用户想更新该表中的数据行,则也必须对该表施加行级锁。
乐观锁
使用乐观锁就不需要借助数据库的锁机制了。乐观锁主要就是两个步骤:冲突检测和数据更新。其实现方式有一种比较典型的就是CAS(Compare and Swap)。
CAS是项乐观锁技术,当多个线程尝试使用CAS同时更新同一个变量时(一般使用数据版本号等),只有其中一个线程能更新变量的值,而其它线程都失败,失败的线程并不会被挂起,而是被告知这次竞争中失败,并可以再次尝试。