库存等 共享资源等。 都需要锁,大量并发下,防止库存超卖等现象产生。
分类
1:(读,写)锁:对数据操作的类型分类
2: 对数据操作的粒度分 行锁,表锁
读写锁
读锁(共享锁):针对同一份数据,多个读操作可以同时进行而不相互影响。
写锁(排它锁):当前数据操作没有完成前,它会阻断其他写锁和读锁。
三锁
表锁(偏读):开销小,加锁快;无死锁,;锁粒度大,发生锁冲突概率大,并发低。
行锁(偏写):和表锁都是对立的。
页锁(介于中间):
原因:表锁:直接将整个表锁住了。不像行锁要找到具体哪行,在锁住。所以表锁,开销小,加锁快,但是行锁并发高,具体并发到了某一行数据了。
查看所有的表上是否加过锁
show open tables;
查看已经锁住的表
show OPEN TABLES where In_use > 0;
手动添加表锁(t1表加读锁,t2表加写锁)
lock table t1 read , t2 write;
t1表加读锁
lock table t1 read ;
解所有表的锁
unlock tables
锁分析
SHOW status like 'table%'
自动提交事务关闭:
set autocommit=0;
查看间隙锁 参数默认值是OFF, 也就是启用间隙锁
show variables like 'innodb_locks_unsafe_for_binlog';
查看行锁的相关信息
show status like 'innodb_row_lock%';
场景:不知道
读锁总结:
session1 给 mylock 表加了读锁,session1 只能读 mylock表,更新 mylock表报错,查询别的表报错。
其他session 干嘛都行,但是只要更新mylock表,会变成等待状态,一旦session1解锁,它将解除等待状态,他会立刻执行之前等待的那个update sql 。
步骤:
总结:写锁是独享且限制锁
加锁的session-----> 我只能对加锁的表任何sql,其他表一概不行。
其他session----->我对其他表任何sql都行,加锁的表的任何sql 都将陷入等待状态,直到那个表解锁,sql就会自动执行成功。
session1 给 mylock表加入写锁,只能对 mylock表的任何操作,其他表的操作不行。别的session对 mylock的任何sql都会陷入等待状态。知道session1解锁,立刻执行成功。
- CREATE TABLE `t1` (
- `t_id` int(20) NOT NULL,
- `t_name` varchar(20) DEFAULT NULL,
- PRIMARY KEY (`id`)
- ) ENGINE=InnoDB DEFAULT CHARSET=utf8
自动提交事务关闭:
set autocommit=0;
session1 | session2 | 解释 |
set autocommit=0; | set autocommit=0; | 都设置手动提交事务 |
update t1 SET t_name='aa' WHERE t_id='1'; | 更新id=1数据 | |
SELECT* from t1; | 事务隔离,还是只能看到之前的数据。 | |
update t1 SET t_name='bb' WHERE t_id='6'; | 更新id不等1的数据都是可以的。 | |
update t1 SET t_name='bb' WHERE t_id='1'; | 我也更新id=1的数据,会陷入等待状态。 行锁。 | |
COMMIT; | ||
更新id=1的sql,立刻执行成功。 | ||
SELECT* from t1; | 因为是它自己提交事务的所以会查到,name='aa' | |
SELECT* from t1; | 因为他还没有提交事务,但是它做了修改,所以查到的是 name='bb',如果没做修改。依然查不到name='aa',因为事务有隔离性。 | |
COMMIT; |
行锁升级为表锁:上述案例是在索引正常使用时,才会是行锁,一旦sql语句让索引失效,将会直接变成表锁,session2的 update将会直接陷入等待状态。
SELECT* from t1 where t_id=1 for update;
for update_llllkccc的博客-CSDN博客_for update
总结:间隙锁,会锁定整个范围内的所有索引键值,即使这个索引键值不存在,也会被无辜的锁住,造成锁定的时候无法插入锁定键值的范围内的任何数据。在某些场景下造成很大的危害。