MySQL解答
一、sql
1、inner join和in
总结:
inner join是内连接,负责连接由条件相匹配的数据
in就是匹配条件
2、select * from xx for update;
for update是在数据库中上锁用的,可以为数据库中的行上一个排它锁。当一个事务的操作未完成时候,其他事务可以读取但是不能写入或更新。
3、数据库来实现乐观锁?
乐观锁(Optimistic Locking)是一种并发控制机制,只有在提交时检查数据是否已经被其他事务修改过,如果有冲突,则回滚操作,否则成功提交。这种机制特别适用于读取操作多、写操作少的场景。
在数据库中实现乐观锁通常依赖于版本号或时间戳字段,以下是具体实现方式:
3.1、 使用版本号实现乐观锁
通过为每一行数据增加一个版本号字段,每次更新数据时,首先检查该版本号是否与读取时的一致。如果一致,则更新并递增版本号;如果不一致,说明数据在期间已经被其他事务修改过,需要回滚操作。
3.2、使用时间戳实现乐观锁
除了版本号,还可以使用时间戳字段来实现乐观锁。每次更新数据时,检查该记录的时间戳是否与之前读取时的一致。如果一致,则更新数据并修改时间戳;如果不一致,则表示数据已经被修改过。
4、手写sql
特别是关联查询(内连接,左连接,右连接),各种分组统计,排序等。
-- 创建库
create database xx;
-- 查看库
show databases;
-- 删除库
drop database xx;
-- 创建表
create table xx(字段1 字段类型,字段2 字段类型...);
-- 创建备份表
create table xx_bak as select * from xx;
-- 查看表
show tables;
-- 删除表
drop table xx;
-- 添加字段
insert into 表名(字段1,字段2...) values(值1,值2...);
-- 修改字段
update xx set 字段1=值,字段2=值 where 条件(字段=?);
-- 删除
delete from xx where 条件;
-- 查询(like,and,or,in,on)
-- and(&&)、or(||)、not(!)用于多个条件逻辑连接
select * from 表名 where 条件1 and 条件2;
select * from 表名 where 条件1 or 条件2;
-- in、not in 判断列值是否是列表中指定的值
select * from 表名 where 字段 in ('值1','值2'...);
-- like的占位符:_表示单个任意字符,%表示多个任意字符
select * from 表名 where 字段 like '_m%';
-- ON 关键字常用于 JOIN 子句来指定连接条件
SELECT columns FROM table1 INNER JOIN table2 ON table1.column = table2.column;
-- 分组
select product,sum(price) from orders group by product having sum(price)>100;
-- 排序(默认是升序,asc升序,desc降序)
select * from 表名 where 条件 order by 列名1,列名2... asc;
-- 内连接
select 列名 from 表1 inner join 表2 on 表1.列名 = 表2.列名;
-- 左连接
select 列名 from 左表 left join 右表 on 左表.列名=右表.列名;
-- 右连接
select 列名 from 右表 right join 左表 on 右表.列名=左表.列名;
5、根据具体的场景描述,进行表结构设计
6、mysql中有哪些函数?哪些聚合函数?
总结:
cast(类型转换函数)
lower,upper,concat,substr(字符串处理函数)
str_to_date,date_format(日期函数)
count、max、min、sum、avg(聚合函数)
7、char与varchar区别?
总结:
长度不同
varchar为可变长度
char是固定长度
存储方式
varchar需要1个或2个额外字节记录字符串长度
char存储很短和长度近似的字符串
存储容量
char字符个数最多为255
varchar为65545-3个字节
8、limit 的优化
使用索引
优化sql语句
分页缓存
调整分页策略
使用游标
反向查找优化
子查询优化
9、行列转换
通常涉及表中的行数据转换为列数据。
MySQL中可以通过case,group by、聚合函数来实现效果
二、事务
1.1、基本概念
1、什么是事务?
事务就是用户定义的一系列执行sql语句的操作
一系列的操作的要么同时成功,要么同时失败
2、事务特点?
A:原子性、C:隔离性、I:一致性、D:持久性
3、能解释什么是脏读,什么是不可重复读,什么是幻读?
脏读:就是一个事务读到另一个事务未提交的数据
不可重复读:是一个事务读到另一个事务提交的数据
幻读:强调数据的插入操作
4、事务的隔离级别
未提交读(read-uncommitted):解决了丢失更新 还会存在脏读 和不可重复读 和幻读
提交读(read-committed):解决了丢失更新、脏读 ,还会存在不可重复读 和 幻读
可重复读(repeatable-read):解决了丢失更新、脏读、不可重复读 存在 幻读
串读(serializable):解决了所有问题(丢失更新、脏读、不可重复读、幻读)
mysql默认隔离级别是可重复读
5、怎么开启事务?
start transaction;
set autocommit=0;
//jdbc怎么控制事务?
connection.setAutoCommit(false);
connection.commit()/rollback();
1.2、说一下内连接和外连接的区别
内连接是指两张表的交集,用inner join来实现。
左外连接是指左边这部分和中间的交集,left join,
右外连接是指右边这部分和交集,用 right join
内连接、外连接(左外、右外)面试经常写sql题
分组:group by having这些使用
1.3、Statement和PreparedStatement的区别
Statement有sql注入问题,需要拼接sql语句
PreparedStatement能提前编译sql,提高性能;避免sql注入问题;设置值非常简单。
1.4、数据库设计三范式
第一范式:所有字段值是不可分解的
第二范式:在满足第一范式的基础上,非主键列必须依赖主键
第三范式:在满足第二范式的基础上,非主键列相互独立
1.5 Mysql中的B+树
什么是B树,B+树?
B树,B+树的区别?
B树的节点都可以存储数据,B+树只能在叶子节点存储数据
B树的叶子节点不构成链表,B+树的叶子节点构成链表
1.6、为什么B+树比B树更适合作为索引?
B+树的磁盘读写代价更低
B+树的查询效率更加稳定
B+树便于遍历
B+树更擅长范围查询
B+树占用内存空间小
1.7、Mysql存储引擎
InnoDB、MyISAM、Memory
MyISAM与InnoDB的区别:
InnoDB支持事务,MyISAM不支持
InnoDB支持表锁和行锁,MyISAM只支持表锁
InnoDB支持外键,MyISAM不支持
InnoDB是聚簇索引,索引和数据存放到一起;MyISAM是非聚簇索引,索引和数据分开存储;都是使用B+树作为索引结构
InnoDB不保存具体行数,MyISAM用一个变量保存了整表的行数
1.8、MySql优化
MySQL是运行在操作系统上的,os优化--运维
sql语句在MySQL Server上运行的,MySQL Server优化--运维或dba
sql优化--程序员
explains执行
查看表的读取顺序
查看数据库读取操作的操作类型
查看哪些索引有可能被用到
查看那些索引真正被用到
查看表之间的引用
查看表中有多少行记录被优化器查询
sql优化技巧
尽量走索引
遵循左匹配队则
不要再索引列上做操作
避免使用or执行连接
数据量较少时,可以全表扫描
索引对排序影响
索引覆盖
1.9、索引失效
什么是左匹配规则?
违背左匹配规则
对索引使用了函数,表达式或运算符
查询条件中使用了不等于操作符(!=),not null,not in
模糊查询
or条件
范围查询
数据类型不匹配,需要隐式转换类型
1.10、读写分离
读写分离就是主库处理事务性查询,从库处理select查询。主要是为了将数据库的读写操作分散不同的数据库节点上,缓解服务器的压力。
选择其中一台作为主数据库,另外一台作为从数据库
保证主库和从库之间的数据是实时同步的。(也是常说的主从复制)
写请求在主库,读请求在从库
1.11、主从复制
主库开启二进制日志,设置serverId,并给从库设置一个可以访问远程读取日志的账号,从库通过改账号访问日志来同步数据。
一种情况为半同步
复制的从服务器收到二进制日志文件保存到中继日志中,返回成功就主服务器继续执行下去,保证数据的一致性,如果超时,就降级为异步
1.12、分库分表
只分表:单表数据量大,读写出现瓶颈
只分库:整个数据库读写出现性能瓶颈,例如数据库连接数满了,或者时并发量太大了
分库分表:单表数据量大,库也出现了性能瓶颈,分为两种方式:
垂直拆分:把字段分开(字段太长了)
水平拆分:把记录分开(数据量达到百万,拆分表)
1.13、能说说什么是索引吗?索引的种类有哪些?
索引是有序的(排好序的)
索引用来快速地寻找那些具有特定值的记录,所有MySQL索引都以B+树的形式保存。
主键索引,哈希索引,唯一索引,普通索引,全文索引
1.14、什么情况下适合建索引?
where和order by条件经常使用
该字段的内容不是唯一的几个值
字段内容不是频繁变化
1.15 、你知道B+树的叶子结点都可以存放哪些东西吗?
InnoDB的B+树可能时存储整行数据,也能的主键的值
索引B+树叶子节点存储整行数据的是主键索引(也叫聚簇索引)
而索引B+树叶子节点单存储了主键的key是非主键索引(非聚簇索引)
1.16、聚簇索引和非聚簇索引,在查询的时候有区别吗?
什么是聚簇索引和非聚簇索引?
聚簇索引也叫主键索引,是将索引和数据存放到一起,找到索引就找到了数据
非聚簇索引是指二级索引,也叫辅助索引,通过非聚簇索引查到的主键值,再使用主键值通过聚簇索引找到查找的值。
区别
数据存储方式
聚簇索引:叶子节点包含了完整的数据行
非聚簇索引:索引和数据是分开存储的,索引的叶子节点存储指向数据行的指针
数据查找效率
聚簇快,非聚簇慢
范围查找性能
聚簇性能好,非聚簇性能低
1.17、 mysql日志:redo log、binlog、undo log区别与作用
redo log(重做日志)
确保事务的持久性,防止再发生故障的时间点,尚有脏页未写入磁盘,在重启mysql服务时,根据redo log进行重做,从而达到事务的持久性
bin log(二进制日志)
用于复制,在主从复制中,从库利用主库上的binlog进行重播,实现主从同步。用于数据库的基于时间点的还原。
undo log(回滚日志)
保存了事务发生之前的数据的一个版本,可以用于回滚,同时可以提供多版本并发控制下的读(MVCC),也即非锁定读
1.18、MySQL锁
共享锁,也叫S锁,读锁
当有事务对数据加读锁后,其他事务只能对锁定的数据加读锁。不能加写锁,所有其他事务只能读,不能写。主要为了支持并发读的场景,读时不允许写操作
排他锁,也叫X锁,写锁
当有事务对数据加写锁后,其他事务不能再对锁定的数据加任何锁,又因为InnoDB对select语句默认不加锁,所以其他事务除了不能写操作外,照样是允许读的。主要为了在事务进行写操作时,不允许其他事务修改。
1.19、InnoDB行锁实现方式
InnoDB行锁是通过给索引上的索引项加锁来是实现的。只有通过索引条件检索数据,InnoDB才使用行锁,否则使用表锁。
注意:行锁一定要使用索引
1.20、什么是MVCC?
MVCC(多版本并发控制),一般在数据库管理中,实现对数据库的并发访问,在编程语言中实现事务内存。
MVCC在MySQL InnoDB中实现主要是为了提高数据库并发性能,用更好的方法处理读写冲突。即使有读写冲突,也能做到不加锁,非阻塞并发读。
当前读
定义:就是它读取的是记录的最新版本,读取时还要保证其它事务不能修改当前记录,会对读取的记录进行加锁。常见的当前读有共享锁,排他锁,for update,update,insert
如果在可重复读(rr)隔离级别下,当前读,就是事务开启的第一条select语句
在提交读(rc)隔离级别下,当前读,就是每使用一个select就会产生一个当前读
快照读(提高数据库的并发查询能力)
像不加锁的select操作就是快照读,即不加锁的非阻塞读;
快照读的前提是隔离级别不是串行级别,串行级别下的快照读会退化成当前读;
之所以出现快照读的情况,是基于提高并发性能考虑,快照读的实现是基于多版本并发控制(MVCC),但在很多情况下,避免了加锁操作,降低开销;
既然是基于MVCC,即快照读可能读到的并不一定是最新版本的数据,有可能是之前的历史版本
当前读,快照读,MVCC的关系
MVCC是维持一个数据多个版本,使读写操作没有冲突,快照读是MySQL为实现MVCC的一个非阻塞读功能。
MVCC模块在mysql中的具体实现是由三个隐式字段,undo日志、read view三个组件来实现。
1.21、MVCC解决的问题是什么?
数据库并发场景有三种,分别是:
读读:不存在任何问题,也不需要并发控制
读写:有线程安全问题,可能会造成事务隔离性问题,可能遇到脏读、幻读、不可重复读
写写:有线程安全问题,可能存在更新丢失问题
功能:
MVCC是一种用来解决读写冲突的无锁并发控制,也就是为事务分配单项增长的时间戳,为每个修改保存一个版本,版本与事务时间戳的关联,读操作只读该事务开始前的数据库的快照。
解决的问题:
在并发读写数据库时,可以做到在读操作时不用阻塞写操作,写操作也不用阻塞读操作,提高了数据库并发读写的性能
解决脏读,幻读,不可重复读等事务隔离问题,但不能解决更新丢失问题。
1.22、同步锁、死锁、乐观锁、悲观锁
同步锁:并发执行多个线程时,在同一时间内只能一个线程访问共享资源。代表synchroned,lock
死锁:多个线程被阻塞,等待资源的释放
乐观锁:认为数据不会被别人修改,不会去加锁。所以再提交时检查数据是否被修改,是就回滚,否则就提交
悲观锁:认为数据会被别人修改,就会加锁。这样共享资源就上了一把锁,只能一个线程一个线程的访问
1.23、MySQL执行流程
客户端发起sql查询,
首先通过连接器,进行用户校验
查询缓存,有缓存就直接返回,没缓存执行后续操作
到达分析器,检查sql语法错误
到达优化器,以它自己的方式优化我们写的sql
到达执行器,执行sql返回结果
1.24、优化sql从那些方面着手
不需要的字段就不要查询出来
小结果集驱动大结果集,将能过滤更多数据的条件写到前面
in和not in尽量不要用
避免where中使用or连接
给经常使用查询的字段建立索引
表数据量太大了,考虑分表优化
1.25、如何定位慢sql
通过druid连接池的内置监控定位慢sql
通过MySQL的慢查询日志查看慢SQL
通过show processlist,查看当前数据库sql执行情况定位慢sql
1.26、页面上发起的一个查询很慢,你怎么去优化
先定位再优化sql