赞
踩
最近在主要在做“工作流引擎”课题的预研工作,在涉及到“会签任务”(工作流业务概念,这与我们今天讨论文问题没有太多关联)的时候,遇到了一个并发修改同一个字段的应用场景。
大致是由于要等一个活动节点的所有实例任务都完成之后才能继续向下流转,则引擎必须在每次任务提交的时候进行判断。我选择了在数据库表中记录下每个活动节点对应的任务实例数目,活动实例完成提交时做相应的数目修改(active_ti_num - 1)来进行对应活动节点是否完成的判断。数据库表结构如下:
活动表字段名 | id(活动主键) | ai_name(活动名称) | active_ti_num(当前活动未完成实例个数) |
---|---|---|---|
示例数据 | 1213398753365504001 | 活动1 | 1 |
任务表字段名 | id(任务主键) | ai_id(对应活动id,外键) |
---|---|---|
示例数据 | 1213400206226272258 | 1213398753365504001 |
如上所示,当同一个活动具有多个任务实例的时候,而任务实例又并发完成,就可能由于并发update导致数据错误,所以我将任务实例提交处理封成了一个事务,再使用update自减的方式修改active_ti_num字段值。
Copy
<update id="decrementActiveNum" parameterType="int"> UPDATE wf_activtity_instance SET active_ti_num = active_ti_num + 1 WHERE id = #{id} </update>
这样在第一个事务修改了active_ti_num后,会锁住活动表中被修改的这一行,其他的事务便只能等待,等持有锁的事务锁释放之后,其他事务可以竞争锁再进行active_ti_num字段修改,从而保证了不出现数据错误。这种处理方法也是一种比较常见的处理方法。
啰啰嗦嗦说了这么多,业务问题虽然解决了,但不知道大家有没有过疑惑,虽然为了保证数据不发生错误,修改的数据被锁住了,但是MySQL究竟加的是行锁还是表锁?如果我们遇到的是并发insert操作而非update,那是否会出现新的问题?想解决这些疑惑,就需要引出我们今天的话题——“MVCC原理与在InnoDB中的实现”
在并发操作的控制上,MySQL的大多事务型存储引擎实现的都不是简单的行级锁。基于提升并发性能的考虑,他们一般都同时实现了MVCC(多版本并发控制)。可以认为MVCC是行级锁的一个变种,在很多场景下避免了加锁操作,因此开销更低。工作在 RC (读已提交)、RR(可重复度)两种隔离级别下。至于这个MVCC究竟是怎么做到既保证效果,又提高并发的,我们先来看看《高性能MySQL》中的介绍。
MVCC的实现,是通过保存数据在某个时间点的快照
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。