mysql四种隔离级别

mysql主键为int传入错误的String也能查询数据 mysql 字符串主键 坏处_数据库

RR下用MVCC用来解决不可再重读的问题,但是不能解决幻读问题(可以加锁解决)。
MVCC为什么有幻读问题:
1、RR下ReadView值使用的是在第一次查询的时候的值。
2、快照读和当前读

可重复读是怎么避免幻读的

间隙锁 -
语句后面加lock in share mode ,next-key locks

mvcc(多版本控制) 看下

一、每次再事务中提交数据都有一个版本链

每更改一次都会在链的最上端插入数据,他们都有2个隐藏的字段

mysql主键为int传入错误的String也能查询数据 mysql 字符串主键 坏处_数据库_02


1、当前的事务id

2、指向下一个节点的指针

通过undo log日志 、 ReadView

mysql主键为int传入错误的String也能查询数据 mysql 字符串主键 坏处_mysql_03


当第四列select事务开始的时候

此时记录两个属性

1、一个在select时候还没有提交的事务,

2、当前已经提交的最大事务id

此时当他查询的时候,

从一中提到的版本链路中从上往下找。

mysql主键为int传入错误的String也能查询数据 mysql 字符串主键 坏处_数据_04


有如图的几种情况,

1、链路中的id<我select查询时候记录的没有提交事务的数组中最小值。

此时这条数据是可见的(左边部分)

2、链路中的id>我select查询时候记录的已经提交的max_id

此时这条数据是不可见的(右边部分)

3、我select查询时候记录的没有提交事务的数组中最小值 <链路中的id <我select查询时候记录的已经提交的max_id(中间部分)

分两种情况 1、 在没有提交事务数组中, 不可见 2、 在数组中里面可见。

MySQL是如何实现事务ACID四个特性的?


Atomicity 原子性:主要依靠undo.log日志实现,即在事务失败时执行回滚。undo.log日志会记录事务执行的sql,当事务需要回滚时,通过反向补偿回滚数据库状态

Consistency 一致性:就是事务再执行的前和后数据库的状态都是正常的,表现为没有违反数据完整性,参照完整性和用户自定义完整性等等。而上面三种特性就是为了保证数据库的有一致性

Isolation 隔离性:我的理解就是多线程时多事务之间互相产生了影响,要避免这个影响,那就加锁。mysql的锁有表锁,行锁,间隙锁,好像还有一个锁数据库的,叫全局锁还是什么来着。写写操作通过加锁实现隔离性,亵渎操作通过MVCC实现

Durability 持久性:主要依靠redo.log日志实现。首先,mysql持久化通过缓存来提高效率,即在select时先查缓存,再查磁盘;在update时先更新缓冲,再更新磁盘。以减少磁盘io次数,提高效率。但由于缓存断电就没了,所以需要redo.log日志。在执行修改操作时,sql会先写入到redo.log日志,再写入缓存中。这样即使断电,也能保证数据不丢失,达到持久性

mysql 中sql语句优化想个表达

查询要尽量走索引,避免过多的回表和全表扫描的发生;尽量不要用*号,尽量带上where条件。
1、用EXPLAIN使你的SELECT查询更加清晰
2、利用LIMIT 1取得唯一行
3、尽量避免SELECT * 命令
4、不要使用BY RAND()命令
5、保证连接的索引是相同的类型
6、在mysql语句中尽量不进行复杂计算
7、
8、
9、

索引失效的场景

1、索引列不独立。独立值的是列不能是表达式的一部分,也不能是函数的参数

如 SELECT * FROM a WHERE b = a + 1

解决方案: 事先计算好参数的值,后查询

mysql主键为int传入错误的String也能查询数据 mysql 字符串主键 坏处_数据_05


2、作用了左模糊3、使用OR查询部分字段没有索引

4、字符串条件未使用’ '引起来

mysql主键为int传入错误的String也能查询数据 mysql 字符串主键 坏处_字段_06

5、不符合最左前缀原则的约束
6、索引字段建议添加NOT NULL 约束
7、隐式转换导致索引失效
两张表关联字段保持类型一致
8、字段的字符集不同

不设置主键,默认的主键是怎么样的。

原文链接:

InnoDB会自动帮你创建一个不可见的、长度为6字节的row_id,而且InnoDB维护了一个全局的dictsys.row_id,所以未定义主键的表都会共享该row_id,每次插入一条数据都把全局row_id当成主键id,然后全局row_id加1。

该全局row_id在代码实现上使用的事bigint unsigned类型,但实际上只给row_id保留了6字节,所以这种设计就会存在一个问题:如果全局row_id一直涨,直到2的48次幂-1时,这个时候再加1,row_id的低48位都会变为0,如果再插入新一行数据时,拿到的row_id就为0,这样的话就存在主键冲突的可能,所以为了避免这种隐患,每个表都需要一个主键。

事务的传播级别

数据库热点数据大批量更新怎么处理

这种场景又分为大量的请求是读请求还是写请求。
读请求
用缓存去抗就行。
写请求
可以使用消息队列

sql语句每个班级成绩最高的信息

表:

CREATE TABLE `t_student` (
  `id` int(11) NOT NULL,
  `class` varchar(45) DEFAULT NULL,
  `name` varchar(45) DEFAULT NULL,
  `score` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

数据

INSERT INTO `test`.`t_student`(`id`, `class`, `name`, `score`) VALUES (1, '1', 'a0', 10);
INSERT INTO `test`.`t_student`(`id`, `class`, `name`, `score`) VALUES (2, '2', 'b0', 10);
INSERT INTO `test`.`t_student`(`id`, `class`, `name`, `score`) VALUES (3, '3', 'c0', 30);
INSERT INTO `test`.`t_student`(`id`, `class`, `name`, `score`) VALUES (4, '1', 'a1', 40);
INSERT INTO `test`.`t_student`(`id`, `class`, `name`, `score`) VALUES (5, '3', 'c1', 30);

sql : 思路 一个t_student 关联 所有班级最高成绩 ,进而查询出全部信息。

SELECT a.id,a.score,a.class,a.name  
 FROM t_student a 
 inner join (select max(score) s ,class  from t_student  group by class) b on a.class = b.class and a.score = b.s;

mysql集群

分库分表

( 分表把分了的表放在不同的库中有什么区别。)
分库是为了分摊压力 分表是因为 查询速度

垂直分表 分字段数量
垂直分库 只是放在不同源中 ,

水平分表 分单表数据量
水平分库 只是放在不同源中

水平拆分数据库后二次迁移问题

1、停服
1)做好备份
2)写一个后台程序,读取原业务数据,根据新的规则,insert 到新表中
3)更改新的分片策略
如果失败恢复

2、不停服
1)修改系统中写库的逻辑,额外按规则新增insert到新库
2)编写一个后台迁移工具,从老的库里读数据,写入到新库中去
3)迁移完成之后,去比较一下新旧库表的数据,如果一模一样,则迁移完成,否则继续执行迁移。
4)新旧库表数据无差异之后,将代码中写入旧的数据库代码删掉,只写新库。

数据库锁有哪几种类型

排它锁

排他锁表示对数据进行写操作,如果一个事物给一个对象添加了排他锁,其他事物就不能给他加其他锁。产生排他锁的SQL语句如下:

select * from ad_plan for update;

共享锁

共享锁(S)表示对数据进行读操作,因此多个事物可以同时为一个对象加锁。这个事物释放锁之前,其他事物不能对该对象进行更新操作。产生共享锁的语句是:

select * from t_user lock in share mode;

行锁,表锁

行锁表示对一条记录加锁,只影响一条记录。通常用在DML语句中,如INSERT, UPDATE, DELETE等。
  InnoDB行锁是通过给索引上的索引项加锁来实现的,这一点MySQL与Oracle不同,后者是通过在数据块中对相应数据行加锁来实现的。
  InnoDB这种行锁实现特点意味着:只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁!

record lock锁住的永远是索引,而非记录本身,即使该表上没有任何索引,那么innodb会在后台创建一个隐藏的聚集主键索引,那么锁住的就是这个隐藏的聚集主键索引。

InnoDB使用行锁定,BDB使用页锁定。

间隙锁

间隙锁,通过索引对锁的优化,仅仅锁住一个索引区间(开区间,不包括双端端点)。

https://zhuanlan.zhihu.com/p/48269420 ,会锁住一段范围,来保证范围查询出现的幻读问题。
间隙锁的目的是为了防止幻读

间隙锁是封锁索引记录中的间隔,或者第一条索引记录之前的范围,又或者最后一条索引记录之后的范围。
使用普通索引锁定;
使用多列唯一索引;
使用唯一索引锁定多行记录。

对于使用唯一索引来搜索并给某一行记录加锁的语句,不会产生间隙锁。(这不包括搜索条件仅包括多列唯一索引的一些列的情况;在这种情况下,会产生间隙锁。)例如,如果id列具有唯一索引,则下面的语句仅对具有id值100的行使用记录锁,并不会产生间隙锁:
SELECT * FROM child WHERE id = 100 FOR UPDATE;

for update 是排它锁
如果使用了索引(主键)并且索引生效的情况下,锁的是查到的行,否则是表锁。
update 排他锁(X锁)
有索引锁行,无索引锁表

意向锁

意向锁的存在是为了协调行锁和表锁的关系,支持多粒度(表锁与行锁)的锁并存。

例子:事务A修改user表的记录r,会给记录r上一把行级的排他锁(X),同时会给user表上一把意向排他锁(IX),这时事务B要给user表上一个表级的排他锁就会被阻塞,不用在遍历所有的记录是否有无加锁。意向锁通过这种方式实现了行锁和表锁共存且满足事务隔离性的要求。

有了解过next key lock吗,它是用来解决什么问题的

解决幻读问题
行锁+gap锁 左开右闭 左边负无穷大到当前索引最大值+一个不可能达到的数

悲观锁是怎么进行加锁的

在串行化的级别下:对读读、读写、写写都独占加锁,其他范围都只能等待锁释放
在读已提交/可重复的级别:引入了MVCC的机制,我觉得优化的读读和读写的冲突。

数据库更新一个数据加锁的过程 快照读和当前读

从图中,可以看到,一个Update操作的具体流程。当Update SQL被发给MySQL后,MySQL Server会根据where条件,读取第一条满足条件的记录,然后InnoDB引擎会将第一条记录返回,并加锁 (current read)。待MySQL Server收到这条加锁的记录之后,会再发起一个Update请求,更新这条记录。一条记录操作完成,再读取下一条记录,直至没有满足条件的记录为止。因此,Update操作内部,就包含了一个当前读。同理,Delete操作也一样。Insert操作会稍微有些不同,简单来说,就是Insert操作可能会触发Unique Key的冲突检查,也会进行一个当前读。

快照读 (snapshot read)与当前读 (current read)。快照读,读取的是记录的可见版本 (有可能是历史版本),不用加锁。当前读,读取的是记录的最新版本,并且,当前读返回的记录,都会加上锁,保证其他事务不会再并发修改这条记录。

在一个支持MVCC并发控制的系统中,哪些读操作是快照读?哪些操作又是当前读呢?以MySQL InnoDB为例:

快照读:简单的select操作,属于快照读,不加锁。(当然,也有例外,下面会分析)

select * from table where ?;

当前读:特殊的读操作,插入/更新/删除操作,属于当前读,需要加锁。

select * from table where ? lock in share mode;

select * from table where ? for update;

                insert into table values (…);

                update table set ? where ?;

                delete from table where ?;

所有以上的语句,都属于当前读,读取记录的最新版本。并且,读取之后,还需要保证其他并发事务不能修改当前记录,对读取记录加锁。其中,除了第一条语句,对读取记录加S锁 (共享锁)外,其他的操作,都加的是X锁 (排它锁)。

innodb 引擎执行过程

总结:一条SQL语句的执行流程大致为,客户端先与MySQL服务器建立连接,然后,发送一条查询语句,如果MySQL开启了缓存的话,会将SQL语句存到缓存中,然后,解析器进行词法和语法的解析,接着预处理器会进行再次检查,比如检查表名和列名是否存在,没有问题的话,优化器会对SQL语句进行优化,生成一个执行计划,交给执行器执行SQL,执行器调用存储引擎,存储引擎读取磁盘数据,将查询结果交给执行器,执行器再将查询结果反馈给客户端或缓存。

innodb快照读和当前读

快照度读历史数据 通过MVCC保证的
当前读通过加锁,来获取实时数据 for update 或者 next-key-lock

读写分离,会出现刚写进去,有读不到的情况

通过切面 使业务 强制走主库

abc 的组合索引,, b>0 and a=1能命中索引吗?

c=0 and a=0 会走索引吗?

  • 最左前缀匹配原则,mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配,
  • 比如a=3 and b=4 and c>5 and d=6如果建立(a,b,c,d)顺序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引则都可以用到,a,b,d的顺序可以任意调整。
  • =和in可以乱序,比如a=1 and b=2 and c=3建立(a,b,c)索引可以任意顺序,mysql的查询优化器会帮你优化成索引可以识别的形式

四. 最左匹配原则的成因

  • 因为联合索引,如:abc,联合索引可以理解为有序的且形成的基础是建立在a上的,从a上建立b,b上建立c,所以必须要按照顺序来
  • 可以简单理解为:先对a排序建立索引,再在a的基础上对b进行排序,再是c
  • 所以联合索引在遇到范围查询,后面的索引会失效。

索引下推做了什么事情

在联合索引,查询中同时满足 两个字段,才进行回表查询

如果没有索引下推,联合索引中,会找到第一个条件满足,去找到主键,查询第二个条件,如果不满足,还要回表继续查询。

in 什么时候走索引,什么时候不走

in通常是走索引的,当in后面的数据在数据表中超过30%(上面的例子的匹配数据大约6000/16000 = 37.5%)的匹配时,会走全表扫描,即不走索引,因此in走不走索引和后面的数据有关系。

什么时候锁表,什么时候锁行

是基于索引进行加锁的

es和mongo区别

es偏向于检索、查询、数据分析,适用于OLAP系统。mongodb偏向于大数据规模下的CRUD,适用于对事务要求不强的OLTP系统。

什么时候考虑加机器,什么时候考虑分库分表

单表查询慢,查询扫描数量太大 减轻cup负担分表
热点数据太多,数据库缓存放不下,每次查询产生大量IO,突破磁盘读IO瓶颈 分库
大量并发情况加机器

b+树的叶子节点为什么要保证顺序

方便范围查找数据

自增和雪花算法,自增快在哪里

业务量小自增,业务量大用雪花安全点

对比速度文档

线上很大的表,加字段怎么办

正确的做法是这样,对于数据量很大的表,需要添加所有或者修改字段的做法是如下:

  • 1.先创建一张一样的表
    create table new_tb like tb_old;
  • 2.修改创建表的字段
    alter table new_tb add COLUMN new_column varchar(32) DEFAULT null;
  • 3.原始数据插入到新的数据表中
    insert into new_tb (字段) select 字段 from tb_old;
    这里需要注意下,你的额insert字段和你查询出来的字段一直,对应顺序也是需要需要一致的,如果你只是修改字段的属性,或者添加了索引之类的,字段数量没用变话,那么直接这样写
    insert into new_tb select * from tb_old;
  • 4.删除原来的数据表,并且重新命名新的数据表:
  1. drop table tb_old;
  2. alter table new_tb rename to tb_old;
  3. 如果含有外键约束的换,那么还需要处理下外键。
    这几部下来就可以防止修改大量数据表而带来的表锁死情况了。

一定在没有什么用户访问得情况下做操作。

先用show processlist; 查出当时正在运行的sql,
是否有大的事务 或者sql执行

删除表有两种方式 delete

sql中删除表中的数据有两种方法:

  1. delete * from TALBENAME
  2. truncate table TABLENAME
    上面的两种方式均是能够删除TABLENAME中的数据,但是第二种方式性能更好,第二种方式是不进行日志的记录。

mysql存储过程

相当于直接和数据库进行操作,在特定的条件下执行指定的语句

一个存储过程是一个事务吗

可以通过
start transaction
commit rollback 通知事务

MySQL 加字段的时候会锁表吗

Mysql在5.6版本之前,直接修改表结构的过程中会锁表,具体的操作步骤如下:
(1)首先创建新的临时表,表结构通过命令ALTAR TABLE新定义的结构
(2)然后把原表中数据导入到临时表
(3)删除原表
(4)最后把临时表重命名为原来的表名
5.6以后不会,可以在线修改,具体实现得不知道,但是在某些情况下还是会锁

为什么要锁
加字段应该所以的数据要进行更改字段和结构,这时候如果有查询可能会出问题,
如果修改过程中有新增也不好处理

char varchar text 区别

char大小0-255 存储会用空格填充,查询会去掉空格 为什么??要这么做
varchar 0-655

总结起来,有几点:

  1. 经常变化的字段用varchar
  2. 知道固定长度的用char
  3. 尽量用varchar
  4. 超过255字符的只能用varchar或者text
  5. 能用varchar的地方不用text

datetime和 timestamp 两个日期时间有什么区别

datetime、timestamp精确度都是秒,datetime与时区无关,存储的范围广(1001-9999),timestamp与时区有关,存储的范围小(1970-2038)。

select for update 和update的锁有什么区别

for update 是排它锁
如果使用了索引(主键)并且索引生效的情况下,锁的是查到的行,否则是表锁。

update 排他锁(X锁)
有索引锁行,无索引锁表

sign unsgin

unsigned 是mysql自定义的类型,表示无符号数值即非负数。signed为整型默认属性。
区别1:起到约束数值的作用。
区别2:可以增加数值范围。
以tinyint为例,它的取值范围-128-127,加不加signed都默认此范围。加上unsigned表示范围0-255,其实相当于把负数那部分加到正数上。例如身高、体重或者年龄等字段一般不会为负数,此时就可以设置一个 UNSIGNED ,不允许负数插入。

查询走索引是搜索的是真实文件还是搜索的索引其他文件

会生成新的文件 innodb 和mysiam 不一样

索引优化技巧

长字段索引调优

新建一个hash字段

新增的时候多加一个字段,这个字段由长字段hash转换而来

如下

mysql主键为int传入错误的String也能查询数据 mysql 字符串主键 坏处_mysql_07


但是上面的查询仅支持全部查询了。

想要支持 like = ‘xx%’ 是不行的

这样的mysql支持

mysql主键为int传入错误的String也能查询数据 mysql 字符串主键 坏处_数据_08

局限性:无法做order By group by ,无法使用聚集索引

mysql主键为int传入错误的String也能查询数据 mysql 字符串主键 坏处_面试_09

JOIN用法

mysql主键为int传入错误的String也能查询数据 mysql 字符串主键 坏处_数据_10

JOIN语句优化

1、尽量使用小表去驱动大表

1.1 一般不用人工去考虑,关联查询优化器会自动选择最优的执行顺序

1.2如果优化器抽风,可以使用STRAIGHT_JOIN 他会强制先读取左边的后读取右边的表

2、如果有where条件,应当要能够使用索引,并尽可能的减少外层循环的数量

3、JOIN的字段尽量使用索引,且类型一致

4、尽量减少JOIN关联的表,如果业务必须如此的话,可以拆分成两条

如:,写3个方法,然后拼接数据

mysql主键为int传入错误的String也能查询数据 mysql 字符串主键 坏处_字段_11

JOIN有哪些算法

Nested-Loop Join(NLJ)

mysql主键为int传入错误的String也能查询数据 mysql 字符串主键 坏处_数据库_12


Block Nested-Loop Join(BNLJ)

两表联查后,使用JoinBuffer缓存数据,然后 一次性的联查t3表

mysql主键为int传入错误的String也能查询数据 mysql 字符串主键 坏处_mysql_13


mysql主键为int传入错误的String也能查询数据 mysql 字符串主键 坏处_mysql_14


mysql主键为int传入错误的String也能查询数据 mysql 字符串主键 坏处_字段_15

Batch Key Access Join(BKA)

mysql主键为int传入错误的String也能查询数据 mysql 字符串主键 坏处_面试_16

mysql主键为int传入错误的String也能查询数据 mysql 字符串主键 坏处_数据库_17

mysql主键为int传入错误的String也能查询数据 mysql 字符串主键 坏处_面试_18

mysql主键为int传入错误的String也能查询数据 mysql 字符串主键 坏处_字段_19


mysql主键为int传入错误的String也能查询数据 mysql 字符串主键 坏处_数据_20

主键和唯一索引有什么区别

主键在唯一索引的基础上有别的约束

主键创建后一定包含唯一性索引,而唯一索引不一定就是主键

主键不能为null,唯一索引可以为null

分库分表,要考虑什么

分片规则
id生成
事务
跨节点join
扩容

用户商家查询订单,分表后怎么查询

怎么分片可以保证商家和用户
根据商家id分片生成一次订单表
在根据用户id分片生成订单表
这样就有两个表
通过不同场景查不同的表

只是类型不一样,数字和字符串做主键有什么区别

https://dev.mysql.com/doc/refman/8.0/en/optimize-numeric.html 对于可以表示为字符串或数字的唯一 ID 或其他值,首选数字列而不是字符串列。由于大数值可以存储在比相应字符串更少的字节中,因此传输和比较它们更快并且占用更少的内存。

读写分离怎么避免读取延迟的问题

1.数据同步写入从库
主从数据同步方案,一般都是采用的异步方式同步给备库。我们可以将其修改为同步方案,主从同步完成,主库上的写才能返回。

  1. 业务系统发起写操作,数据写主库;
  2. 写请求需要等待主从同步完成才能返回;
  3. 数据读从库,主从同步完成就能读到最新数据。
    这种方案,我们只需要修改数据库之间同步配置即可,业务层无需修改,相对简单。但随着从库的数据增加,由于主库写需要等待主从完成,写请求的时延将会增加,吞吐量将会降低。

强制走主库
不同的分库分表框架有不同的实现方式

优化器,主要优化什么