最近做一个统计;需要把一个字段(存放数据是json)里某一个数字加1 然后在修改该字段;当时就那么一写最后发现该数据和明细对不上; 其实这个应该是并发引起的,先select 在update 这样写其实会出现一些问题
###第一种解决方案
事务,即用一个事务来包裹上面的SELECT+UPDATE操作+写共享锁。
读共享锁是通过下面这样的SQL获得的:SELECT * FROM parent WHERE NAME = 'Jones' LOCK IN SHARE MODE;
如果事务A获得了先获得了读共享锁,那么事务B之后仍然可以读取加了读共享锁的行数据,但必须等事务A commit或者roll back之后才可以更新或者删除加了读共享锁的行数据。
如果事务A先获得了某行的写共享锁,那么事务B就必须等待事务A commit或者roll back之后才可以访问行数据。
SELECT counter_field FROM child_codes FOR UPDATE;UPDATE child_codes SET counter_field = counter_field + 1;
###第二种解决方案
乐观锁,上面是一种观锁机制,而且SELECT...FOR UPDATE
方式也不太常用
SELECT counter_field FROM child_codes FOR UPDATE;UPDATE child_codes SET counter_field = counter_field + 1 WHERE counter_field='上面select出来的值' ;
这样可以根据UPDATE返回值来判断是否更新成功,如果返回值是0则表明存在并发更新,那么只需要重试一下就好了。
-
如果对读的响应度要求非常高,比如证券交易系统,那么适合用乐观锁,因为悲观锁会阻塞读
-
如果读远多于写,那么也适合用乐观锁,因为用悲观锁会导致大量读被少量的写阻塞
-
如果写操作频繁并且冲突比例很高,那么适合用悲观写独占锁