1.1 锁分类
按使用方式划分:乐观锁、悲观锁
按锁级别划分:共享锁、排他锁
按锁的粒度划分:表级锁、行级锁、页级锁
按操作划分:DML锁,DDL锁
按加锁方式划分:自动锁、显示锁
1.2 共享锁和排它锁
共享锁(读锁)
1、共享锁又叫读锁,如果事务T对A加上共享锁,则其它事务只能对A再加共享锁,不能加其它锁。
2、获准共享锁的事务只能读数据,不能写数据。
3、用法: SELECT … LOCK IN SHARE MODE;
排它锁(写锁)
1、排它锁又叫写锁,如果事务T对A加上排它锁,则其它事务都不能对A加任何类型的锁。获准排它锁的事务既能读数据,又能写数据。
2、用法 : SELECT … FOR UPDATE
1.3 乐观锁和悲观锁
2.3.1 悲观锁:写少读多
1、MySQL会对查询结果集中每行数据都添加排他锁,其他线程对该记录的更新与删除操作都会阻塞
2、申请前提:没有线程对该结果集中的任何行数据使用排他锁或共享锁,否则申请会阻塞。
3、适用场景:悲观锁适合写入频繁的场景。
对商品数量-1操作,悲观锁实现
1、每次获取商品时,对该商品加排他锁
2、也就是在用户A获取获取 id=1 的商品信息时对该行记录加锁,期间其他用户阻塞等待访问该记录。
#### 悲观锁实现加一操作代码
# 我们可以看到,首先通过begin开启一个事物,在获得shop信息和修改数据的整个过程中都对数据加锁,保证了数据的一致性。
'''
begin;
select id,name,stock as old_stock from shop where id=1 for update;
update shop set stock=stock-1 where id=1 and stock=old_stock;
commit
'''
2.3.2 乐观锁:读多写少
1、在更新数据的时候需要比较程序中的库存量与数据库中的库存量是否相等,如果相等则进行更新。
2、反之程序重新获取库存量,再次进行比较,直到两个库存量的数值相等才进行数据更新。
3、乐观锁实现对商品-1操作
1、每次获取商品时,不对该商品加锁。
2、在更新数据的时候需要比较程序中的库存量与数据库中的库存量是否相等,如果相等则进行更新
3、反之程序重新获取库存量,再次进行比较,直到两个库存量的数值相等才进行数据更新。
#### 乐观锁实现加一操作代码
# 我们可以看到,只有当对数量-1操作时才会加锁,只有当程序中值和数据库中的值相等时才正真执行。
'''
//不加锁
select id,name,stock where id=1;
//业务处理
begin;
update shop set stock=stock-1 where id=1 and stock=stock;
commit;
'''
1.4 行级锁 & 表级锁
1、行级锁(写多读少)开销大,加锁慢,锁定粒度最小,发生锁冲突概率最低,并发度最高
2、表级锁(适合大量的读操作)开销小,加锁快,锁定粒度大、发生锁冲突最高,并发度最低