面试题答案
一键面试- 锁粒度控制
- 行级锁:在MySQL中尽量使用行级锁而非表级锁。比如在更新数据时,通过唯一索引精准定位到需要修改的行,减少锁的范围。例如对于用户表
users
,若要更新某个用户的信息,可以使用UPDATE users SET column1 = 'value1' WHERE user_id = 123 FOR UPDATE;
,这种方式只锁定满足条件的这一行数据,而非整个表。 - 读写锁分离:在Redis分布式锁中,可以考虑使用读写锁。对于读操作较多的场景,多个读操作可以同时获取读锁,而写操作需要获取写锁,且写锁获取时会排斥其他读写操作。例如在实现商品信息展示(读多)和商品库存更新(写少)场景时,读操作获取读锁,写操作获取写锁,提升系统并发度。
- 行级锁:在MySQL中尽量使用行级锁而非表级锁。比如在更新数据时,通过唯一索引精准定位到需要修改的行,减少锁的范围。例如对于用户表
- 事务隔离级别优化
- 降低隔离级别:如果业务允许,适当降低MySQL的事务隔离级别。比如从默认的
REPEATABLE READ
(可重复读)调整为READ COMMITTED
(读已提交)。READ COMMITTED
下,一个事务只能读到其他事务已提交的数据,减少了锁的持有时间,降低事务冲突概率。但需要注意这种调整可能导致不可重复读等问题,要根据具体业务进行评估。 - 快照隔离(Snapshot Isolation):在某些数据库支持的情况下,使用快照隔离。它允许读操作不阻塞写操作,写操作也不阻塞读操作。读操作基于数据的快照版本进行读取,写操作创建新的版本。例如在高并发的电商订单系统中,订单查询(读)和订单创建(写)可以通过快照隔离减少冲突。
- 降低隔离级别:如果业务允许,适当降低MySQL的事务隔离级别。比如从默认的
- 优化Redis分布式锁
- 锁超时设置:合理设置Redis分布式锁的超时时间。如果超时时间过短,可能导致业务未完成锁就释放,出现数据不一致;如果过长,会增加其他请求等待时间。可以根据业务预估执行时间,并适当增加一定冗余时间来设置。例如业务平均执行时间为10秒,设置超时时间为15秒。
- 异步释放锁:在业务处理完成后,通过异步方式释放Redis分布式锁。比如使用消息队列,将释放锁的操作发送到消息队列,由消息队列异步处理释放锁的任务,这样可以减少业务处理线程等待锁释放的时间。
- MySQL事务优化
- 减少事务内操作:将不必要的操作移出事务。例如在更新用户信息时,若涉及一些日志记录操作且这些操作对数据一致性并非关键,可以在事务提交后异步处理日志记录。这样可以缩短事务执行时间,减少锁的持有时间。
- 批量操作:在事务内尽量使用批量操作。比如要插入多条订单数据,使用
INSERT INTO orders (column1, column2) VALUES ('value1', 'value2'), ('value3', 'value4');
这种批量插入方式,相较于多次单条插入,减少了事务内操作次数,降低锁等待时间。