docker run -d --restart=always \
--log-opt max-size=10m \
-m 1024MB \
-p 3306:3306 \
-v $(pwd)/data/mysql/conf:/etc/mysql/conf.d \
-v $(pwd)/data/mysql/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
--name mysql \
mysql:8
mysql -uroot -p
create user 'test'@'%' identified by '123456';
grant all privileges on *.* to 'test'@'%';
create index index_name on table_name (column_name);
alter table `table_name` add primary key ( `column` ); -- 添加primary key(主键索引)
alter table `table_name` add unique ( `column` ); -- 添加unique(唯一索引)
alter table `table_name` add index index_name ( `column` ); -- 添加index(普通索引)
alter table `table_name` add index index_name (column_name(length)); -- 添加index(前缀索引)
alter table `table_name` add fulltext ( `column`); -- 添加fulltext(全文索引)
alter table `table_name` add index index_name ( `column1`, `column2`, `column3` ); -- 添加多列索引
MySQL中的索引可以以一定顺序引用多列,这种索引叫作联合索引。如User表的name和city加联合索引就是(name,city),而最左前缀原则指的是,如果查询的时候查询条件精确匹配索引的左边连续一列或几列,则此列就可以被用到。如下:
sql
select * from user where name=xx and city=xx; --可以命中索引
select * from user where name=xx; --可以命中索引
select * from user where city=xx; --无法命中索引
这里需要注意的是,查询的时候如果两个条件都用上了,但是顺序不同,如 city= xx and name =xx
,那么现在的查询引擎会自动优化为匹配联合索引的顺序,这样是能够命中索引的。
由于最左前缀原则,在创建联合索引时,索引字段的顺序需要考虑字段值去重之后的个数,较多的放前面。ORDER BY子句也遵循此规则。
关系型数据库和非关系型数据库的理解
mysql的数据类型
null和''的区别
因此:my_sql 不建议使用 null 作为列默认值
boolean类型如何表示
my_sql 中没有专门的布尔类型。用int代替
常用sql语句
select database();
select now(), user(), version();
create database [if not exists] 数据库名 [character set charset_name | collate collation_name]
show databases [like 'pattern']
show create database 数据库名
alter database 库名 选项信息
drop database[if exists] 数据库名
create table [if not exists] [库名.]表名 (列名 列类型, ....) [表选项]
show tables from 库名
drop table[ if exists] 表名 ...
truncate [table] 表名
insert [into] 表名 [(字段列表)] values (值列表)[, (值列表), ...]
select 字段列表 from 表名[ 其他子句]
delete from 表名[ 删除条件子句]
update 表名 set 字段名=新值[, 字段名=新值] [更新条件]
数据库经常使用的函数
count(*/column):返回行数
sum(column): 返回指定列中唯一值的和
max(column):返回指定列或表达式中的数值最大值
min(column):返回指定列或表达式中的数值最小值
avg(column):返回指定列或表达式中的数值平均值
date(Expression): 返回指定表达式代表的日期值
my_sql 支持哪些存储引擎?默认使用哪个?
myisam 和 innodb
my_sql 中常见的日志有哪些?
binlog 与 redo log 的区别:binlog 是 mysql 的服务器层实现的,所有的存储引擎都可以使用,它记录的是 sql 语句;而 redo log 是 innodb 存储引擎特有的,它记录的是对数据页的物理修改操作。另外,binlog 是追加写的,当文件达到一定大小后会生成新的文件;而 redo log 是循环写的,当文件达到一定大小后会从头开始写。
事务 ACID 特性
A、I、D 是手段,C 是目的
MySQL 如何保证 ACID 的
原子性(Atomicity):
一致性(Consistency)
隔离性(Isolation)
持久性(Durability)
并发事务带来哪些问题
不可重复读和幻读有什么区别?
sql的事务隔离级别
离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
read-uncommitted(读取未提交) | √ | √ | √ |
read-committed(读取已提交) | × | √ | √ |
repeatable-read(可重复读) | × | × | √ |
serializable (可串行化) | × | × | × |
my_sql 的隔离级别基于锁和 mvcc 机制共同实现的。serializable 隔离级别是通过锁来实现的,read-committed 和 repeatable-read 隔离级别是基于 mvcc 实现的。不过, serializable 之外的其他隔离级别可能也需要用到锁机制,就比如 repeatable-read 在当前读情况下需要使用加锁读来保证不会出现幻读。
mysql innodb 存储引擎的默认支持的隔离级别是 repeatable-read(可重读)。可以通过select @@tx_isolation;命令来查看
MySQL数据的锁的种类,加锁的方式
按照类型来分有乐观锁和悲观锁
根据粒度来分有行级锁,页级锁,表级锁(粒度一个比一个大) (仅BDB,Berkeley Database支持页级锁)
根据作用来分有共享锁(读锁)和排他锁(写锁)。
什么是共享锁和排他锁
乐观锁与悲观锁解释一下, 乐观锁与悲观锁是怎么实现的
一般的数据库都会支持并发操作,在并发操作中为了避免数据冲突,所以需要对数据上锁,乐观锁和悲观锁就是两种不同的上锁方式。
悲观锁假设数据在并发操作中一定会发生冲突,所以在数据开始读取的时候就把数据锁住。而乐观锁则假设数据一般情况下不会发生冲突,所以在数据提交更新的时候,才会检测数据是否有冲突。
实现:
悲观锁有行级锁和页级锁两种形式。行级锁对正在使用的单条数据进行锁定,事务完成后释放该行数据,而页级锁则对整张表进行锁定,事务正在对该表进行访问的时候不允许其他事务并行访问。
悲观锁要求在整个过程中一直与数据库有一条连接,因为上一个事务完成后才能让下一个事务执行,这个过程是串行的。
乐观锁有三种常用的实现形式:
一种是在执行事务时把整个数据都拷贝到应用中,在数据更新提交的时候比较数据库中的数据与新数据,如果两个数据一摸一样则表示没有冲突可以直接提交,如果有冲突就要交给业务逻辑去解决。
一种是使用版本戳来对数据进行标记,数据每发生一次修改,版本号就增加1。某条数据在提交的时候,如果数据库中的版本号与自己的一致,就说明数据没有发生修改,否则就认为是过期数据需要处理。
最后一种采用时间戳对数据最后修改的时间进行标记。与上一种类似。
my_sql 中并发事务的控制方式
inno_db 有哪几类行锁?
在 innodb 默认的隔离级别 repeatable-read 下,行锁默认使用的是 next-key lock。但是,如果操作的索引是唯一索引或主键,innodb 会对 next-key lock 进行优化,将其降级为 record lock,即仅锁住索引本身,而不是范围。
innodb 的行锁是针对索引字段加的锁,表级锁是针对非索引字段加的锁。当执行 update、delete 语句时,如果 where条件中字段没有命中唯一索引或者索引失效的话,就会导致扫描全表对表中的所有行记录进行加锁。这个在日常工作开发中经常会遇到,一定要多多注意!!!不过,很多时候即使用了索引也有可能会走全表扫描,这是因为 mysql 优化器的原因。
事务回滚有什么实现机制?除了日志之外呢?
mysql性能优化
高频访问:
并发优化:
mysql索引类型
主键索引
唯一索引(unique key) :唯一索引也是一种约束。唯一索引的属性列不能出现重复的数据,但是允许数据为null,一张表允许创建多个唯一索引。建立唯一索引的目的大部分时候都是为了该属性列的数据的唯一性,而不是为了查询效率。
普通索引(index) :普通索引的唯一作用就是为了快速查询数据,一张表允许创建多个普通索引,并允许数据重复和null。
前缀索引(prefix) :前缀索引只适用于字符串类型的数据。前缀索引是对文本的前几个字符创建索引,相比普通索引建立的数据更小,
因为只取前几个字符。
全文索引(full text) :全文索引主要是为了检索大文本数据中的关键字的信息,是目前搜索引擎数据库使用的一种技术。mysql5.6之前只有myisam引擎支持全文索引,5.6之后inno_db也支持了全文索引。
联合索引/多列索引
联合索引的最左前缀原则:
my_sql中的索引可以以一定顺序引用多列,这种索引叫作联合索引。如user表的name和city加联合索引就是(name,city),而最左前缀原则指的是,如果查询的时候查询条件精确匹配索引的左边连续一列或几列,则此列就可以被用到。如下:
select * from user where name=xx and city=xx ; //可以命中索引
select * from user where name=xx ; // 可以命中索引
select * from user where city=xx ; // 无法命中索引
这里需要注意的是,查询的时候如果两个条件都用上了,但是顺序不同,如 city= xx and name =xx,那么现在的查询引擎会自动优化为匹配联合索引的顺序,这样是能够命中索引的。
由于最左前缀原则,在创建联合索引时,索引字段的顺序需要考虑字段值去重之后的个数,较多的放前面。order by子句也遵循此规则。
联合索引中间可以有 null 值吗,为什么
mysql索引如何实现
MySQL中的索引主要是通过B-Tree(平衡多路查找树)和Hash(哈希)两种数据结构来实现的。其中,B-Tree是MySQL中最常用的索引类型,它被用于MyISAM、InnoDB、Memory等存储引擎。
B-Tree索引:B-Tree索引可以处理等于、不等于、大于、小于、范围查询、LIKE 'abc%'等各种类型的查询。在B-Tree中,所有的值都存储在树的叶子节点上,非叶子节点不存储数据,只存储键值和指向子节点的指针。这样做的好处是每次查找的次数都相同,所以查找效率稳定。
Hash索引:Hash索引基于哈希表实现,只有Memory存储引擎显式支持。它能以O(1)的时间复杂度进行查找,但是这种超高效的查找速度是以牺牲其他功能为代价的。Hash索引仅支持等值查询,不支持范围查询和排序操作,也无法利用索引完成部分匹配查找。同时,Hash索引在处理大量数据时可能会出现哈希冲突的问题,且Hash索引无法避免表扫描。
B树和B+树的区别是什么?B+ 树的特点,原理?
B树(Balance Tree)和B+树(Balance Plus Tree)都是一种自平衡的多路搜索树,主要用于大量数据的存储系统中,如数据库和文件系统。它们都可以保持数据的有序性,并且可以在对数时间内完成查找、插入和删除操作。然而,它们之间还是存在一些重要的差别的。
B树的所有节点都包含键和值,即所有节点都可以是叶子节点,也都可以是内部节点。而B+树的内部节点只存储键,不存储值,只有叶子节点存储键和值。这意味着,在B+树中,所有的数据都存储在叶子节点上。
B+树的叶子节点之间通过指针相连,形成了一个链表结构,这使得范围查询更加高效。而B树并没有这样的链表结构,范围查询需要通过深度优先搜索来完成。
由于B+树的内部节点不存储数据,所以每个内部节点可以存储更多的键,因此B+树的树高通常比B树要低,这使得在大数据量的情况下,B+树的查询效率更高。
B+树的特点主要包括:
所有关键字都出现在叶子节点的链表中(稠密索引),且链表中的关键字恰好是有序的,不仅可以快速查询,也方便范围查找。而B树则做不到,只有分支节点才包含所有关键字,叶子节点并不包含所有关键字。
非叶子节点的子树指针与关键字个数相同。非叶子节点的子树指针P[i],指向关键字值属于[K[i], K[i+1])的子树(注意最后一个子树指针P[m],指向关键字值大于等于K[m]的子树)。
非叶子节点的关键字K[i],是其子树指针P[i+1]指向的子树中所有关键字的最小值。也就是说,非叶子节点中的关键字是分割左右子树的。
原理:B+树的查找过程是这样的,首先从根节点开始,通过二分查找的方式找到关键字K[i],使得K[i] <= key < K[i+1],然后沿着指针P[i+1]继续在下一层节点查找,直到查找到叶子节点。在叶子节点上按照从小到大的顺序查找到相应的关键字,如果找到了就返回该关键字及其对应的记录,否则就返回“查找失败”。
sql中索引失效的场景
联合索引不满足最左匹配原则,索引列上有计算或者函数,字段类型不同,比如varchar类型的字段与数字比较就不走索引,但是与字符串比较就走索引,模糊匹配,如果%在最左
主从同步如何实现
binlog。
复制过程中可能会遇到的问题包括网络延迟、主从数据不一致等。因此,在部署和监控MySQL主从复制时,需要考虑故障恢复、数据一致性校验以及延迟监控等因素。
MySQL的存储结构
表空间,段(包括数据段:即B+树的叶子结点,索引段:非叶子节点,回滚段),区(默认1M,64个连续页),页(InnoDB存储引擎磁盘管理的最小单元,默认16k),行
数据库的范式
第一范式(确保每列保持原子性)
第一范式是最基本的范式。如果数据库表中的所有字段值都是不可分解的原子值,就说明该数据库表满足了第一范式。
比如 学生 选课(包括很多课程) 就不符合第一范式
第二范式(确保表中的每列都和主键相关)
在满足第一范式的前提下,(主要针对联合主键而言)第二范式需要确保数据库表中的每一列都和主键的所有成员直接相关,由整个主键才能唯一确定,而不能只与主键的某一部分相关或者不相关。
比如一张学生信息表,由主键(学号)可以唯一确定一个学生的姓名,班级,年龄等信息。但是主键 (学号,班级) 与列 姓名,班主任,教室 就不符合第二范式,因为班主任跟部分主键(班级)是依赖关系
第三范式(确保非主键的列没有传递依赖)
在满足第二范式的前提下,第三范式需要确保数据表中的每一列数据都和主键直接相关,而不能间接相关。非主键的列不能确定其他列,列与列之间不能出现传递依赖。
比如一张学生信息表,主键是(学号)列包括 姓名,班级,班主任 就不符合第三范式,因为非主键的列中 班主任 依赖于 班级
主键有可能是由多个属性组合成的复合主键,那么多个主键之间不能有传递依赖。也就是复合主键之间谁也不能决定谁,相互之间没有关系。