1、MySQL的锁
参考:https://blog.csdn.net/qq_40378034/article/details/90904573
全局锁
给整个数据库实例加锁。例如全局读锁:Flush tables with read lock。
应用场景:全库逻辑备份,将整个库的每个表都select出来存成文本。
表级锁
两种:表锁、元数据锁。
表锁:lock tables…read/write。
MDL(元数据)锁:当对一个表做增删改查操作的时候,加MDL读锁;当要对表结构做变更操作的时候,加MDL写锁。
事务的MDL锁在语句执行开始时申请,但是语句结束后并不会马上释放,而会等到整个事务提交后释放。
行锁
不是所有引擎都支持行锁,MyISAM不支持。
在InnoDB中,行锁是在需要的时候加上的,但是要等到事务结束时才释放。(两阶段锁协议)
把最可能造成锁冲突、最可能影响并发度的锁尽量往后放。
当出现死锁时,有两种策略:
- 设置超时时间。直接进入等待,直到超时。
- 发起死锁检测,回滚死锁链中的某个事务。
开启死锁检测后,每当一个事务被锁的时候,就要看看他所依赖的线程有没有被别人锁住,如此循环,最后判断是否出现了循环等待(死锁)。如果所有事务都要更新同一行,那么每个新来的阻塞线程都要判断会不会由于自己的加入导致死锁。
这种性能问题如何解决?
- 1、暂时将死锁检测关掉;
- 2、控制并发度;
- 3、将一行改成逻辑上的多行来减少锁冲突。
间隙锁
为了解决幻读问题,InnoDB引入了间隙锁,锁的是两个值之间的空隙。
当执行select * from t where d=5 for update的时候,就不止是给数据库中已有的6个记录加上了行锁,还同时加了7个间隙锁。这样就确保了无法再插入新的记录。
间隙锁+行锁合称为next-key lock,每个next-key lock是前开后闭区间。
2、可重复读是怎么实现的?
通过MVCC解决的。
InnoDB中每个事务都有一个唯一的事务ID,是在事务开始的时候向InnoDB的事务系统申请的,按照申请顺序严格递增的。
在每条记录进行更新的时候都会同时记录一条undo log链,这条log会记录上当前事务的事务id( row trx_id ),记录的最新状态通过回滚可以得到前一个状态的值。
3、线程池
可以聊的点:线程池的好处、实现原理、七大参数、四大拒绝策略。
四大拒绝策略:
- ① AbortPolicy(直接抛出异常)
- ② CallerRunsPolicy:只用调用者所在线程来运行任务
- ③ DiscardOldestPolicy:丢弃队列里最近的任务,并执行该任务
- ④ DiscardPolicy:不处理,直接丢弃
线程池的执行流程
类比成坐公交:首先上车,看靠窗的位置(核心线程池)是否坐满,坐满了则看其他位置(等待队列)是否坐满,坐满了则看公交还有没有站的位置(整个线程池是否还有空位),要是整个公交都满了就只能看司机怎么安排了(拒绝策略处理)。
找规律