乐观锁和悲观锁
作为刚毕业的小白,可能我所分享的知识比较浅显(大神请回避),但对于像我一样的还在努力学习的人来说
是一个很好的一起学习交流的机会(小白请留步),希望大家能共同进步。
在刚刚进入工作的时候,每次在编写对于某种数据修改的相关功能的时候,我都会思考一个问题,如果在同一时刻有两个请求
修改同一个数据,例如:两个操作,一个存钱,一个消费,查询的时候余额都是100元,存10,消费20,如果同时提交的会造成
什么情况呢,一条数据会不会将另一条数据覆盖呢,
这是在实际生产生活中遇到的问题,当然也一定是被我们智慧的人类解决的问题。
而解决问题的方式正是乐观锁和悲观锁
上面提到问题是典型的并发问题。在多用户环境中,在同一时间可能会有多个用户更新相同的记录,这会产生冲突。
典型的冲突有:
丢失更新:一个事务的更新覆盖了其它事务的更新结果,就是所谓的更新丢失。例如:用户A把值从6改为2,用户B把值从2改为6,则用户A丢失了他的更新。
脏读:当一个事务读取其它完成一半事务的记录时,就会发生脏读取。例如:用户A,B看到的值都是6,用户B把值改为2,用户A读到的值仍为6。
为了解决这些并发带来的问题。 我们需要引入并发控制机制。
并发控制机制
悲观锁:假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作。
乐观锁:假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性。
乐观锁应用
1. 使用自增长的整数表示数据版本号。更新时检查版本号是否一致,比如数据库中数据版本为6,更新提交时version=6+1,使用该version值(=7)与数据库version+1(=7)作比较,如果相等,则可以更新,如果不等则有可能其他程序已更新该记录,所以返回错误。
2. 使用时间戳来实现.
悲观锁应用
需要使用数据库的锁机制,比如SQL SERVER 的TABLOCKX(排它表锁,这种页锁的机制会降低效率) 此选项被选中时,SQL Server 将在整个表上置排它锁直至该命令或事务结束。这将防止其他进程读取或修改表中的数据。
在SqlServer等其余很多数据库中,数据的锁定通常采用页级锁的方式,也就是说对一张表内的数据是一种串行化的更新插入机制,在任何时间同一张表只会插1条数据,别的想插入的数据要等到这一条数据插完以后才能依次插入。带来的后果就是性能的降低,在多用户并发访问的时候,当对一张表进行频繁操作时,会发现响应效率很低,数据库经常处于一种假死状态。
MySQL数据库由于其自身架构的特点,存在多种数据存储引擎,每种存储引擎所针对的应用场景特点都不太一样,为了满足各自特定应用场景的需求,每种存储引擎的锁定机制都是为各自所面对的特定场景而优化设计,所以各存储引擎的锁定机制也有较大区别。
MyISAM:不支持事务,用于只读程序提高性能 ,采用表级锁
InnoDB:支持ACID事务、行级锁、并发
Berkeley DB:支持事务 页级锁
by lxh.