控制并发度。但是如果在客户端做并发控制,如果客户端很多,即使每个客户端并发量很小,MySQL 服务器的并发量也会很大。因此,这个并发控制要做在数据库服务端。如果有中间件,可以考虑在中间件实现;如果团队有能修改 MySQL 源码的人,也可以做在 MySQL 里面。基本思路就是,对于相同行的更新,在进入引擎之前排队。这样在 InnoDB 内部就不会有大量的死锁检测工作了。
从设计上改善,通过将一行改成逻辑上的多行来减少锁冲突
The text was updated successfully, but these errors were encountered:
行锁
MySQL 的行锁是由存储引擎实现的,行锁就是针对数据表中行记录的锁。
行锁比表锁的粒度小,发生锁争用的可能小,并发度高。但行锁比表锁开销大,因为锁的各种操作(包括获取锁、释放锁、以及检查锁状态)都会增加系统开销。
InnoDB 行锁是通过给索引上的索引项加锁来实现的。所以,只有通过索引条件检索数据,InnoDB 才使用行级锁,否则,InnoDB 将使用表锁
从两段锁说起
InnoDB 事务中,行锁是在需要的时候才加上,等到事务结束之后才释放,这就是两阶段锁协议。
根据两阶段锁协议,在事务中如果需要锁多个行,要把最可能造成锁冲突、影响并发度的行往后放。
死锁和死锁检测
当并发系统中不同线程出现循环资源依赖,涉及的线程都在等待别的线程释放资源时,就会导致这几个线程都进入无限等待的状态,称为死锁。
当出现死锁以后,有两种策略:
innodb_lock_wait_timeout
来设置。innodb_deadlock_detect
设置为 on,表示开启这个逻辑。在 InnoDB 中,
innodb_lock_wait_timeout
的默认值是 50s,这个等待时间长得无法接受;但是如果将这个参数设置得过小,那么 InnoDB 可能就分不清锁等待和死锁。所以,第二种策略是比较常用的:主动监测死锁。但是第二种策略也会面临一个问题:死锁检测可能会极大耗费 CPU 资源。
死锁检测的一般过程是:每当一个事务被锁的时候,就要看看它所依赖的线程有没有被别人锁住,如此循环,最后判断是否出现了循环等待,也就是死锁。
怎么解决由热点行更新导致的性能问题呢?
The text was updated successfully, but these errors were encountered: