数据库中锁(简易描述,持续更新)
1.共享锁
共享锁和共享锁可以共存,共享锁和排它锁不能共存,只有在serializable隔离级别下做查询会添加共享锁
案例:打开两个客户端并都设置隔离级别为serializable,分别在两个客户端中进行查询
实现步骤:
1.打开2个窗口分别设置隔离级别都为serializable
2.开启事务执行查询
窗口1:
窗口2:
3.在 窗口2中执行更新操作,出现如下情况,进程被阻塞
通过上面的测试可以得出结论:共享锁就是多个事务对于同一数据可以共享一把锁,都能访问到数据,但是只能读不能修改
2.排它锁
排它锁与任何锁都不能共存,任何隔离级别下做增删改操作时都会添加排它锁
案例:基于前面的案例
在两边都查询的基础上,将其中一边进行增删改操作
任意一边:update user set money=money+100 where name='b';
运行结果就是共享锁中描述的步骤3
3.死锁
两个线程彼此握着对方需要的资源,互不释放
MySQL可以检测到死锁的存在,让其中一方报错,另一方执行
4、悲观锁
1、当事务在操作数据时把这部分数据进行锁定,直到操作完毕后再解锁,其他事务操作才可操作该部分数据。这将防止其他进程读取或修改表中的数据。
2、实现:
一般使用 select ...for update 对所选择的数据进行加锁处理,例如 SELECT * FROM `yzm_order` WHERE `order_no` = 'S201909277894' LIMIT 1 FOR UPDATE ,这样就通过开启排他锁的方式实现了悲观锁。此时在 yzm_order 表中,order_no 为 S201909277894 的那条数据就被我们锁定了,其它的事务必须等本次事务提交之后才能执行。这样我们可以保证当前的数据不会被其它事务修改。
5、乐观锁
1、如果有人在你之前更新了,你的更新应当是被拒绝的,可以让用户重新操作。
2、实现:
大多数基于数据版本(Version)记录机制实现,
具体可通过给表加一个版本号或时间戳字段实现,当读取数据时,将version字段的值一同读出,数据每更新一次,对此version值加一。当我们提交更新的时候,判断当前版本信息与第一次取出来的版本值大小,如果数据库表当前版本号与第一次取出来的version值相等,则予以更新,否则认为是过期数据,拒绝更新,让用户重新操作。