- 事务隔离(针对可重复读和串行化级别)
mysql使用的是二阶锁方案。得到锁之前会一直等待,这种方式的缺点是性能不好,优点是不需要失败后重试。属于悲观锁方案。
postgresql使用的是SSI——Serialized Snopshot Isolation,任何操作不需要等待,但是提交数据时若检测到数据有冲突会抛出异常并回滚。优点是不会出现死锁,缺点是当失败时需要不断重试,当失败的次数比较多时频繁重试会大量消耗性能。属于乐观锁方案。
引用
//www.greatytc.com/p/cb97f76a92fd
文中的一段话
在MySQL中,很多开发者倾向于自己在默认隔离级别之外手工加锁。而PostgreSQL则建议尽量避免直接加锁,因为其Repeatable Read和Serializable的实现已经相当完善,开发者没必要自找麻烦。
- 显式指定数据库行锁
人工给记录加锁,当然人工处理锁问题自然是比较麻烦还容易出错
mysql可用这种方式
- php处理
对于yii2框架来说ActiveRecord中已经集成了乐观锁的功能,悲观锁需自己或参考第三方实现
具体参考这篇文章
http://www.digpage.com/lock.html
如果用mysql数据库可以考虑这种方式,只是性能会比数据库行锁低一些。
- 业务级控制
redis锁,postgresql的advisory lock
这种主式比较灵活,需要自己控制,用的好可以实现性能最优,用不好也会性能比较差。单纯从锁性能来说应该是以上三种方案的。
关于秒杀的问题
秒杀的场景通常是有限的商品海量的人员去争抢,能抢到手的通常只有前几名人员。
- 如果是悲观锁方案,所有人(不管抢到没抢到)都会等待获取锁,直到超时结束。这会让没有抢到人的做不必要的等待。这个用无等待锁即可,直接返回请重试或抢购结束。
- 如果是乐观锁方案,所有人(不管抢到没抢到)都会去提交事务,这会浪费不必要的系统资源,使系统卡住。即使不重试也需要事务回滚,没有想到很好的避免方法。