基本用法
SELECT GET_LOCK(key, timeout) FROM DUAL;
SELECT RELEASE_LOCK(key) FROM DUAL;
含义解释
其中GET_LOCK()和RELEASE_LOCK()分别是两个函数,并且有参数和返回值,这里的DUAL是伪表,在Oracle中很常见,就是一个不存在的表,用来临时记录值的。
-
GET_LOCK有两个参数,一个是key,就是根据这个参数进行加锁的,另一个是等待时间(s),即获取锁失败后等待多久回滚事务。
这里假设连接A先GET_LOCK("lock_test", 10),因为lock_test这个字段在之前没有加锁所以不需要等待,直接返回1,加锁成功。
然后连接B再GET_LOCK("lock_test", 10),等待10s,若这期间没有释放这个字段的锁,则10s过后返回0,连接B加锁失败。
这里的问题就是这个加锁方式很危险,一旦加锁之后忘记释放,就会一直锁住这个字段,除非连接断开。尤其是第二个参数,千万不要理解成超时时间,并不是设置一个字段的锁,然后超过这个时间就自动释放了,这个是等待时间,即第二次对同一个字段加锁,等待多久然后返回。 这个RELEASE_LOCK就没什么好说的了,记得加锁之后释放就可以了,成功释放回返回1。
实际应用
需要注意的是这个锁是基于单个数据库的,如果在分布式环境下,有多台物理主机多个数据库,这个锁的方式就失效了,这种情况需要借助Zookeeper来实现了。
在单数据库的环境下,如果想防止多个线程操作同一个表(多个线程可能分布在不同的机器上),可以使用这种方式,取表名为key,操作前进行加锁,操作结束之后进行释放,这样在多个线程的时候,即保证了单个表的串行操作,又保证了多个不同表的并行操作。
实际上这个锁的应用场景还是很多的,但由于方法过于危险,应尽量谨慎使用。