写在前面:我们都是挖井人,也许挖到水的条件仅仅是需要保持专注而已!
行锁
-
什么是行锁?
顾名思义,行锁就是对数据行进行加锁,mysql的行锁是在引擎层实现的,innodb引擎支持行锁,而myisam不支持所以myisam只能使用表锁. -
行锁的两阶段协议
在innodb事务中,行锁是需要的时候才加上去的,但并不是不需要了就立即释放,而是要等到事务结束再释放
上述两个事务A,B中,事务B必须等到事务A提交后才能执行,在事务A提交前会一直处于等待状态 -
行锁的注意事项
a. 通过行锁的两阶段协议我们需要知道,如果一个事务中需要锁多行,要把最可能造成锁冲突,最可能影响并发度的锁尽量往后放
(越往后,加锁的时间越短,造成的影响也就越少)
b. InnoDB行锁是通过给索引上的索引项加锁来实现的,只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁!
c. 由于MySQL的行锁是针对索引加的锁,不是针对记录加的锁,所以虽然是访问不同行的记录,但是如果是使用相同的索引键,是会出现锁冲突的
-
死锁和死锁检测
当多个线程都在同时等待相互间的锁资源时,就会导致它们处于无线等待状态,我们把这种状态称之为死锁
事务A在等待事务B释放id=2的行锁,而事务B在等待事务A释放id=1的行锁,然后。。。它们就进入了无限等待的死锁状态
通常处理死锁问题有两种策略:
a. 设置锁超时时间,通过参数 innodb_lock_wait_timeout来调整
b. 发起死锁检测,发现死锁后主动回滚死锁链条中的某一个事务,让其他事务得以执行,
将参数innodb_deadlock_detect设置为on,mysql默认为on(当并发量大的时候会极大的消耗CPU资源)
臆想面试:
-
如果处理死锁问题?
如果我碰到这类面试问题,我想我只能先说出处理死锁的两种策略,然后说尽可能减少锁冲突的可能性来降低死锁概率,
具体业务需具体分析,采取的方案也大致不一 -
如果你要删除表里的前10000行数据,有以下三种方法可以做到:
a. 直接执行 delete from T limit 10000;
b. 在一个连接中循环执行20次 delete from T limit 500;
c. 在20个连接中同时执行 delete from T limit 500;
你会选哪个方案?
如果是我,我会选择第二种;第一种锁数据的时候太长,第三种不同连接容易造成锁冲突!
上述多数内容借鉴学习有感于:
林晓斌老师mysql实战45讲
https://www.cnblogs.com/lushilin/p/6135374.html