乐观锁 悲观锁
悲观锁: 查询时就加锁,通过数据库锁机制实现
举例:
A线程查询时加锁-----处理-------更新数据,
B线程进来时也进行:查询时加锁(这里会等待)-----处理-------更新数据,
乐观锁:
举例:
A线程:查询数据(查版本号)--处理---更新(判断版本号与数据库是否一致,不一致返回错误不更新)
update version=version+1 where a=? and version=lastVersion 如果找不到说明version被其它线程改了,所以不允许操作,回到第一步重新查询处理
B线程:查询数据(查版本号)--处理---更新(判断版本号与数据库是否一致,不一致返回错误不更新)
两种方式都能解决并发脏数据问题,如果更新多,更新冲突多,如果用乐观锁会一直返回错误retry,所以要用悲观锁。如果更新少,用乐观锁
乐观锁的一种实现机制:MVCC(多版本并发控制)
引用知乎上面的回答:
写写冲突的处理流程。一般是以读写冲突的处理来说明MVCC的优点。比如对于数据项A,它的数据版本为A1->A2->A3,最新版本是A3。如果事务X在读写数据项A时,A1和A2已提交的,事务Y正在修改A3,那么A3可以被提交,也可能被回滚。在使用锁协议时,事务X要等待Y结束,才能判断是否读到A3。在MVCC中,事务X可以读取已经提交的A2,而不必等待A3。这么操作逻辑上是合理的,因为事务X读到了一个最新的已经提交数据,这不会带来数据不一致,也避免了读写操作的冲突等待。在上面的情况中,X可以读到A2,如果X要写A怎么办?从逻辑上说,A3不确定是提交还是回滚,X必须等待Y结束,才能开始写操作,因此MVCC的写写操作是需要在数据对象上加写锁的,因此对于同一数据对象的写写操作,MVCC也是串行执行的。由于实际业务中读操作事务数量要大于写操作事务,MVCC读写不冲突(不加锁),写写冲突(加做)的机制,能够提高读事务的执行性能,从而提高系统的整体性能。