我们知道为了控制并发,我们可以使用mysql锁机制来实现,但是不同的锁的粒度不同,运用场景也不同。
1,读锁
-
描述:即事务A 使用共享锁 获取了某条(或者某些)记录时,事务B 可以读取这些记录,可以继续添加共享锁,但是不能修改或删除这些记录(当事务B 对这些数据修改或删除时会进入阻塞状态,直至锁等待超时或者事务A提交)
-
场景:读取结果集的最新版本,同时防止其他事务产生更新该结果集
主要用在需要数据依存关系时确认某行记录是否存在,并确保没有人对这个记录进行UPDATE或者DELETE操作,因为可能因为阻塞产生死锁
2,写锁(悲观锁)
- 描述:一个写锁会阻塞其他的读锁和写锁
即事务A 对某些记录添加写锁时,事务B 无法向这些记录添加写锁或者读锁(不添加锁的读取是可以的),事务B 也无法执行对 锁住的数据 update delete - 场景:读取结果集的最新版本,同时防止其他事务产生读取或者更新该结果集。
例如:并发下对商品库存的操作
但是悲观锁阻塞会导致吞吐量下降问题,在一些需要及时反馈的场景可以使用乐观锁或者分布式锁来代替悲观锁。
在使用读锁、写锁时都需要注意,读锁、写锁属于行级锁。即事务1 对商品A 获取写锁,和事务2 对商品B 获取写锁互相不会阻塞的。需要我们注意的是我们的SQL要合理使用索引,当我们的SQL 全表扫描的时候,行级锁会变成表锁。
使用EXPLAIN查看 SQL是否使用了索引,扫描了多少行
3,乐观锁
- 描述:
乐观锁是一种逻辑锁,通过数据的版本号(vesion)的机制来实现,极大降低了数据库的性能开销。
我们为表添加一个字段 version,读取数据时将此版本号一同读出,之后更新时,对此版本号+1,同时将提交数据的version 与数据库中对应记录的当前version 进行比对,如果提交的数据版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据
4,分布式锁
mysql的锁实现虽然简单,但是会收索引还有速度的影响,可以用redis实现分布式锁来控制并发