快捷搜索:  汽车  科技

mysql表中能存多少数据面试题(千万级别mysql表锁表了怎么办)

mysql表中能存多少数据面试题(千万级别mysql表锁表了怎么办)4)对线上大数据量并且活跃时间的表直接进行DDL操作或加索引操作,这也会造成锁表3)使用类似select * from user for update的sql语句显式锁表支持表锁和行锁,该存储引擎支持事务,由于支持细粒度的行锁,所以比较适合高并发操作,那到底什么时候使用表锁呢?根据我多年的经验,主要有以下几种场景:1)sql未使用索引,更新或删除单表中的数据2)sql使用索引,但不是唯一索引,这个时候如果更新表中的大量数据或全量数据,此时如果使用行锁,会造成事务长时间等待、 锁冲突,因此mysql会升级为锁表.sql操作了几张表,即传说中的大事务,比较复杂,这个时候mysql为了防止死锁和事务回滚,会同时锁相关的表

要回答这道面试题,首先要搞清楚mysql有哪些存储引擎呢?平常我们用的最多的就是InnoDB和MyISAM,它们在使用锁的方式上是不一样的,mysql常见的有三种锁:表锁、行锁、页面锁下面分别介绍:

1、MyISAM

只支持表级锁,无论是insert、update、delete都会对整表加锁,该存储引擎不支持事务,性能比较好,但由于整表锁,所以tps不太高,不适合高并发操作,选型时要慎重。

2、Innodb

支持表锁和行锁,该存储引擎支持事务,由于支持细粒度的行锁,所以比较适合高并发操作,那到底什么时候使用表锁呢?根据我多年的经验,主要有以下几种场景:

1)sql未使用索引,更新或删除单表中的数据

2)sql使用索引,但不是唯一索引,这个时候如果更新表中的大量数据或全量数据,此时如果使用行锁,会造成事务长时间等待、 锁冲突,因此mysql会升级为锁表.sql操作了几张表,即传说中的大事务,比较复杂,这个时候mysql为了防止死锁和事务回滚,会同时锁相关的表

3)使用类似select * from user for update的sql语句显式锁表

4)对线上大数据量并且活跃时间的表直接进行DDL操作或加索引操作,这也会造成锁表

假如当线上环境遇到锁表后怎么办?

1)线上如果发现大量sql语句导致长时间锁表,可以通过show processlist命令找出锁表的进程号,然后执行kill 进程号命令,快速结束锁表语句

2)根据上一步的锁表sql快速从程序中找出是哪个业务导致的,解决bug后紧急发版,如果是非核心业务导致,为了保证系统不被拖挂,可以将接口作降级处理

3)可以写一个检查锁表的运维脚本,每隔几分钟检查一次,出现长时间锁表的sql发出告警提醒

既然知道了锁表以后,我们有一些事后的补救措施,那我们是不是在刚开始设计的时候就可以尽可能规避这些坑呢,有没有一些比较好的实践?答案是有的,如下所示:

1)对于大表的操作,查询条件一定要保证命中索引,如果能命中唯一索引就更好了

2)我们在程序开发的时候,尽可能将大事务拆分为小事务,减少锁表或回滚,比如:抽离部分业务逻辑异步发送消息队列处理

3)更新很频繁的业务,尽量转为批量处理,另外尽可能减少单次处理的数据量,大数据量可以分批次处理

4)不要通过select * from user for update显示锁表,特别是高并发的时候,这种操作会很骚,严重影响tps,我们可以通过乐观锁加版本号实现或者先写到缓存然后异步写表等方案解决

5)业务高峰期,不要随便直接加字段或索引,尽量用户不活跃时执行,但是如果一定要在高峰期操作,可以复制旧表结构创建一个新表,然后在新表上加字段或索引,接着将原来旧表的数据copy到新表,再rename两个表,最后将rename期间旧表的增量数据迁移到新表

6)采用读写分离架构

最后做一下总结,如下图:

mysql表中能存多少数据面试题(千万级别mysql表锁表了怎么办)(1)

猜您喜欢: