#数据库锁
悲观锁(Pessimistic Lock)
悲观锁,是程序员给予锁的定义之一,代表着对数据很悲观,每次操作数据时,都怕别人同时对数据进行修改。所以每次操作数据时,都会对数据进行上锁,防止别人操作。
1 共享锁(Share Lock)
共享锁(S锁)也称为 读锁;用于所有的只读数据操作。共享锁为非占有型,它允许多个事务同时读取锁定的资源。
特点
- 多个事务可同时上锁资源
- 上锁时,数据可读,但任何事务都无法修改数据
- 通常读完数据后马上释放。
2 排他锁(Exclusive Lock)
排他锁(X锁),也称为写锁,如果对一个对象加了写锁,则其他事务不能对该数据进行任何操作,知道加锁的事务提交。
特点
- 仅允许一个事务操作
- 其他事务必须等待加锁事物提交才可访问
- 需要等待加锁事务提交事务后,锁才会释放
3 更新锁(Update Lock)
更新锁(U锁),用于修改操作在初始化阶段对需要修改的数据进行锁定,这样可以避免共享锁进入死锁的状态;
- 例如:当两个事务同时拥有共享锁,并都需要升级为排他锁时,双方都会进入互相等待状态,形成死锁。但有个更新锁,则一方先获得更新锁时,另一方只能读完数据后退出共享锁,无法升级成排他锁,指导获得更新锁的事务提交结束后才可操作。
特点
- 用于预定要对数据进行排他锁,它允许其他事务读,但允许再加排他锁和更新锁
- 更新锁一致到事务提交时结束
4 行锁、表锁
分别为对一行数据/一张表进行锁定;
- 例如
当你使用update … where id=?这样的语句时,数据库明确知道会影响哪一行,它就会使用行锁;
当你使用update … where birthday=?这样的的语句时,因为事先不知道会影响哪些行就可能会使用表锁。
乐观锁
顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以,不会上锁。但是在更新的时候会判断一下在此期间别人有没有更新这个数据,可以使用版本号、时间戳等机制。
通过版本号、时间戳实现乐观锁
在数据表中,新增字段 version/timestamp;用于记录每一条数据的版本或者操作时间;每一次更新数据时,同时将版本version+1/ 更新时间戳字段timestamp;若数据库版本/时间戳与你获取的不同,意味着该数据已被别人操作过,可以重新获取一次最新的数据,再执行一次更新操作。
//具体实现
update user set name = '小四', version = 2
where id = 1 and version= 1;
//此时如果返回结果为0,则意味着where条件中version=1条件不符合,
//该数据已经被别人修改过,故重新获取最新数据,再跟新一遍即可