面试题答案
一键面试MariaDB锁机制内部原理
- 共享锁(S锁)与排他锁(X锁):
- 共享锁允许并发事务读取同一数据,多个事务可以同时持有共享锁。例如,多个查询操作可以同时进行。
- 排他锁则阻止其他事务获取任何类型的锁,只有持有排他锁的事务能对数据进行写操作。如更新数据时会获取排他锁。
- 锁粒度:
- 表级锁:对整个表进行锁定。优点是实现简单,加锁和解锁快;缺点是并发度低,当一个事务锁住表时,其他事务对该表的任何操作都要等待。例如在执行
LOCK TABLES table_name WRITE
时。 - 行级锁:只锁定需要操作的行。优点是并发度高,能允许更多事务同时操作不同行;缺点是加锁和解锁开销大,因为需要更精确的定位。InnoDB存储引擎支持行级锁。
- 页级锁:介于表级锁和行级锁之间,锁定一页数据。开销和并发度也介于两者之间。
- 表级锁:对整个表进行锁定。优点是实现简单,加锁和解锁快;缺点是并发度低,当一个事务锁住表时,其他事务对该表的任何操作都要等待。例如在执行
性能调优和解决锁争用的策略
- 锁粒度控制:
- 根据操作类型选择锁粒度:
- 读多写少场景:尽量使用行级锁。例如在电商商品浏览场景,大量用户读取商品信息,行级锁可允许并发读取不同商品行数据,提高并发度。
- 写操作频繁场景:若写操作涉及整表数据变动,可考虑表级锁。如在每月初对会员积分进行统一调整,表级锁虽会降低并发度,但加解锁开销小。
- 减少锁持有时间:将大事务拆分成小事务。比如一个涉及多个表更新的事务,可按业务逻辑拆分成几个小事务,每个小事务尽快提交,减少锁的持有时间,降低锁争用。
- 根据操作类型选择锁粒度:
- 事务隔离级别调整:
- 读未提交(Read Uncommitted):最低隔离级别,一个事务可以读取另一个未提交的事务修改的数据。优点是并发度最高,缺点是会出现脏读。适用于对数据一致性要求不高,追求高并发的场景,如实时统计浏览量等临时数据。
- 读已提交(Read Committed):一个事务只能读取已经提交的事务所做的修改。避免了脏读,但可能出现不可重复读。大多数OLTP(联机事务处理)系统默认使用此级别,适合一般的业务场景,能保证一定的数据一致性和并发度。
- 可重复读(Repeatable Read):在同一个事务中多次读取相同数据时,结果保持一致,避免了不可重复读,但可能出现幻读。InnoDB默认隔离级别,适合对数据一致性要求较高,并发度也有一定要求的场景,如银行转账业务。
- 串行化(Serializable):最高隔离级别,所有事务串行执行,避免了所有并发问题,但并发度最低。适用于对数据一致性要求极高,不允许并发访问的场景,如涉及金钱计算的核心业务,且并发量极小的情况。
- 并发控制算法优化:
- 两阶段锁协议(2PL)优化:
- 严格两阶段锁:在事务提交或回滚前,不释放任何锁。能保证事务的可串行化,但可能导致死锁。通过死锁检测机制,如InnoDB的死锁检测算法,发现死锁后回滚一个代价最小的事务来解决。
- 改进的两阶段锁:允许在事务执行过程中提前释放一些锁,但仍要保证在事务提交前获取所有需要的锁。可提高并发度,但需要仔细评估提前释放锁是否会影响数据一致性。
- MVCC(多版本并发控制):
- InnoDB使用MVCC来实现高并发下的读操作不阻塞写操作,写操作不阻塞读操作。MVCC通过维护数据的多个版本,读操作读取的是数据的快照版本,而不是当前最新版本。适用于读多写少的场景,如新闻网站的文章浏览和偶尔更新场景。
- 两阶段锁协议(2PL)优化:
不同业务场景下的适用性和权衡要点
- 高并发读场景:
- 适用性:优先选择行级锁、读已提交或可重复读隔离级别、启用MVCC。
- 权衡要点:行级锁提高并发读能力,但加解锁开销大;读已提交隔离级别可保证读数据的一致性,可重复读能进一步避免不可重复读问题,但两者在性能上有一定差异。MVCC能实现读写不阻塞,但会增加存储开销。
- 高并发写场景:
- 适用性:若写操作涉及数据量较小,可选择行级锁;若涉及大量数据,可考虑表级锁。事务隔离级别可选择读已提交。
- 权衡要点:行级锁适合细粒度写操作,但大量行级锁操作可能导致锁争用加剧;表级锁虽并发度低,但对大量数据操作时加解锁简单。读已提交隔离级别在保证一定一致性的同时,可提供相对较高的并发写能力。
- 读写混合场景:
- 适用性:采用行级锁、可重复读隔离级别,结合MVCC。
- 权衡要点:行级锁可满足读写操作的并发需求,可重复读隔离级别能保证读操作的一致性,MVCC确保读写操作不相互阻塞。但要注意MVCC带来的存储开销和维护成本。