文章目录
为什么会专门写一篇博客去说锁和缓存呢,因为面试背问到了。满天飞的理论但是落地的话呢?接下来一块看看你们会不会!
锁
id | name |
---|---|
张三 | 李四 |
id是自增主键。
问题一:根据id去删除一行数据会走什么锁?
问题二:根据name删除一行数据会走什么锁?
问题三:给name加普通索引会走什么锁?
MyISAM在执行查询语句(SELECT)前,会自动给涉及的所有表加读锁,在执行更新操作(UPDATE、DELETE、INSERT等)前,会自动给涉及的表加写锁。
InnoDB行锁是通过给索引上的索引项加锁来实现的,因此InnoDB这种行锁实现特点意味着:只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁!
相信看完了这两句话心中都有答案了。如果在MySAM引擎下和InnoDB去分点回答~
缓存
MySql的Query Cache
Query Cache MySQL Query Cache是用来缓存我们所执行的SELECT语句以及该语句的结果集。MySql在实现Query Cache的具体技术细节上类似典型的KV存储,就是将SELECT语句和该查询语句的结果集做了一个HASH映射并保存在一定的内存区域中。当客户端发起SQL查询时,Query Cache的查找逻辑是,先对SQL进行相应的权限验证,接着就通过Query Cache来查找结果。不需要发生同任何存储引擎的交互,减少了大量的磁盘IO和CPU运算,所以有时候效率非常高。
缺点:
只有相同的查询操作才能命中缓存,因此MySQL的查询缓存命中率很低,另一方面,对于大结果集的查询,其查询结果可以从cache中直接读取,有效的提升了查询效率。
Query Cache 参数
可以去查看query_cache的参数和开启情况
开启
mysql> show variables like '%query_cache%';
+------------------------------+-------------+
| Variable_name | Value |
+------------------------------+-------------+
| have_query_cache | YES |
| query_cache_limit | 1048576 |
| query_cache_min_res_unit | 4096 |
| query_cache_size | 16106127360 |
| query_cache_type | ON |
| query_cache_wlock_invalidate | OFF |
+------------------------------+-------------+
6 rows in set (0.01 sec)
关闭:
mysql> show variables like '%query_cache%';
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| have_query_cache | NO |
+------------------+-------+
query_cache_type: 是否开启缓存功能,取值为ON, OFF, DEMAND,默认值为ON
- 值为OFF或0时,查询缓存功能关闭;
- 值为ON或1时,查询缓存功能打开,SELECT的结果符合缓存条件即会缓存,否则,不予缓存,显式指定SQL_NO_CACHE,不予缓存;
- 值为DEMAND或2时,查询缓存功能按需进行,显式指定SQL_CACHE的SELECT语句才会缓存;其它均不予缓存
query_cache_wlock_invalidate:表示当有其他客户端正在对MyISAM表进行写操作时,如果查询在query cache中,是否返回cache结果还是等写操作完成再读表获取结果。
query_cache_limit 指定单个查询能够使用的缓冲区大小,缺省为1M;
query_cache_min_res_unit为系统分配的最小缓存块大小,默认是4KB,设置值大对大数据查询有好处,但如果你的查询都是小数据查询,就容易造成内存碎片和浪费;query_cache_size:表示缓存的大小。
开启缓存举例:
mysql> select count(*) from user;
+----------+
| count(*) |
+----------+
| 87151154 |
+----------+
1 row in set (3 min 18.29 sec)
mysql> select count(*) from user;
+----------+
| count(*) |
+----------+
| 87151154 |
+----------+
1 row in set (0.00 sec)
mysql> select count(*) from user;
+----------+
| count(*) |
+----------+
| 87151154 |
+----------+
1 row in set (0.00 sec)
可以看出第一次查询是查询表中数据,之后再执行相同的SQL语句时候直接可以命中缓存。查询时间是相当快。