首页 > 数据库 >6. MySQL

6. MySQL

时间:2023-02-17 08:22:05浏览次数:35  
标签:事务 数据库 索引 InnoDB MySQL 日志

MySQL 是一种关系型数据库,主要用于持久化存储我们的系统中的一些数据比如用户信息。

什么是关系型数据库?

关系型数据库(RDBMS,Relational Database Management System)就是一种建立在关系模型的基础上的数据库。关系模型表明了数据库中所存储的数据之间的联系(一对一、一对多、多对多)。

关系型数据库中,我们的数据都被存放在了各种表中(比如用户表),表中的每一行就存放着一条数据(比如一个用户的信息)
大部分关系型数据库都使用 SQL 来操作数据库中的数据。并且,大部分关系型数据库都支持事务的四大特性(ACID)

MySQL 的索引类型,最左前缀匹配原则

主键索引(Primary Key),二级索引(辅助索引)
最左前缀匹配原则指的是,在使用联合索引时,MySQL 会根据联合索引中的字段顺序,从左到右依次到查询条件中去匹配,如果查询条件中存在与联合索引中最左侧字段相匹配的字段,则就会使用该字段过滤一批数据,直至联合索引中全部字段匹配完成,或者在执行过程中遇到范围查询,如 >、<、between 和 以%开头的like查询 等条件,才会停止匹配。
所以,我们在使用联合索引时,可以将区分度高的字段放在最左边,这也可以过滤更多数据

底层索引数据结构,为什么不用B-树?Hash 表

哈希表是键值对的集合,通过键(key)即可快速取出对应的值(value),因此哈希表可以快速检索数据(接近 O(1))。
为何能够通过 key 快速取出 value 呢? 原因在于 哈希算法(也叫散列算法)。通过哈希算法,我们可以快速找到 key 对应的 index,找到了 index 也就找到了对应的 value。
但是!哈希算法有个 Hash 冲突 问题,也就是说多个不同的 key 最后得到的 index 相同。通常情况下,我们常用的解决办法是 链地址法。链地址法就是将哈希冲突数据存放在链表中。就比如 JDK1.8 之前 HashMap 就是通过链地址法来解决哈希冲突的。不过,JDK1.8 以后HashMap为了减少链表过长的时候搜索时间过长引入了红黑树。
B 树& B+树
B 树也称 B-树,全称为 多路平衡查找树 ,B+ 树是 B 树的一种变体。B 树和 B+树中的 B 是 Balanced (平衡)的意思。

目前大部分数据库系统及文件系统都采用 B-Tree 或其变种 B+Tree 作为索引结构。
B 树& B+树两者有何异同呢?
B 树的所有节点既存放键(key) 也存放 数据(data),而 B+树只有叶子节点存放 key 和 data,其他内节点只存放 key。
B 树的叶子节点都是独立的;B+树的叶子节点有一条引用链指向与它相邻的叶子节点。
B 树的检索的过程相当于对范围内的每个节点的关键字做二分查找,可能还没有到达叶子节点,检索就结束了。而 B+树的检索效率就很稳定了,任何查找都是从根节点到叶子节点的过程,叶子节点的顺序检索很明显。

索引失效如何排查?

使用 SELECT * 进行查询;
创建了组合索引,但查询条件未准守最左匹配原则;
在索引列上进行计算、函数、类型转换等操作;
以 % 开头的 LIKE 查询比如 like '%abc';;
查询条件中使用 or,且 or 的前后条件中有一个列没有索引,涉及的索引都不会被使用到;
发生隐式转换

InnoDB和 MyISAM 的区别?聚簇索引与非聚簇索引的区别?

InnoDB 支持行级别的锁粒度,MyISAM 不支持,只支持表级别的锁粒度。
MyISAM 不提供事务支持。InnoDB 提供事务支持,实现了 SQL 标准定义了四个隔离级别。
MyISAM 不支持外键,而 InnoDB 支持。
MyISAM 不支持 MVVC,而 InnoDB 支持。
虽然 MyISAM 引擎和 InnoDB 引擎都是使用 B+Tree 作为索引结构,但是两者的实现方式不太一样。
MyISAM 不支持数据库异常崩溃后的安全恢复,而 InnoDB 支持。
InnoDB 的性能比 MyISAM 更强大。

聚簇索引即索引结构和数据一起存放的索引,并不是一种单独的索引类型。InnoDB 中的主键索引就属于聚簇索引
非聚簇索引即索引结构和数据分开存放的索引,并不是一种单独的索引类型。二级索引(辅助索引)就属于非聚簇索引。MySQL 的 MyISAM 引擎,不管主键还是非主键,使用的都是非聚簇索引

SQL优化

1 避免使用select *
2 用union all代替union
3 小表驱动大表
4 批量操作
5 多用limit
6 in中值太多
7 增量查询
8 高效的分页
9 用连接查询代替子查询
10 join的表不宜过多
11 join时要注意
12 控制索引的数量
13 选择合理的字段类型
14 提升group by的效率
15 索引优化

常见并发问题

当多个同时运行的事务访问某一个数据时,如果采取相应措施,就有可能发生下列并发问题:

脏读 : 对于两个事务 T1, T2, T1 读取了已经被 T2 更新但还没有被提交的字段。之后, 若 T2 回滚, T1读取的内容是T2读出的内容就是T2没有被提交的字段,是临时且无效的。
不可重复读 : 对于两个事务T1与T2,T1读取了某个字段,这时T2更新并提交了该字段,则T1读取的内容会发生改变。大多数时候会忽略这个问题,但更严谨的是在T1没有执行完成时,保持T1读取的字段的一致性。
幻读 : 对于两个事务T1和T2,如果T1从一个表中读取了一个字段,然后T2在该表中插入了一些新的行。之后,如果T1再次读取这个字段时就会发现表数据多了几行。
数据库事务之间的隔离程度叫做隔离级别。数据库支持多种隔离级别。隔离级别越高,数据库的并发性就越低,性能也就越低。

事务的ACID特性和隔离级别。

事务是逻辑上的一组操作,要么都执行,要么都不执行
原子性(Atomicity) : 事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用;
一致性(Consistency): 执行事务前后,数据保持一致,例如转账业务中,无论事务是否成功,转账者和收款人的总额应该是不变的;
隔离性(Isolation): 并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立的;
持久性(Durability): 一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。
只有保证了事务的持久性、原子性、隔离性之后,一致性才能得到保障。也就是说 A、I、D 是手段,C 是目的! 想必大家也和我一样,被 ACID 这个概念被误导了很久! 我也是看周志明老师的公开课《周志明的软件架构课》才搞清楚的

SQL 标准定义了四个隔离级别:
READ-UNCOMMITTED(读取未提交) : 最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读。
READ-COMMITTED(读取已提交) : 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生。
REPEATABLE-READ(可重复读) : 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。
SERIALIZABLE(可串行化) : 最高的隔离级别,完全服从 ACID 的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。
MySQL InnoDB 存储引擎的默认支持的隔离级别是 REPEATABLE-READ(可重读)。我们可以通过SELECT @@tx_isolation;命令来查看,MySQL 8.0 该命令改为SELECT @@transaction_isolation;

Socket服务端向指定客户端发送消息

解决思想
I.指定客户端远程地址是存起来的。
II.服务端直接主动发信息给客户端,问题在于如何触发服务端下发信息。用线程新建一个客户端,发送消息给服务端,服务端接受消息后触发下发消息
如何上传与下发指令
硬件客户端通过socket通信。服务端提供socket服务端与硬件客户端连接(长连接),硬件客户端给服务端上传信息容易,只要连接上了可以随时发送消息。但是服务端如何下发指令,如何去出发下发指令,这是个问题
服务端模拟一个客户端,连接自己,发送下发信息,服务端再下发信息给客户端,这就容易多了,基本与多人聊天室场景相似
Web页面点击关闭按钮,web服务新建线程新建模拟客户端连接socket服务端,发送关闭指令串。
Socket服务端收到指令串,发送给硬件客户端。
硬件客户端执行关闭操作。
硬件客户端上传关闭完成信息。
Socket服务端收到关闭完成信息,新建线程通知web服务器更新数据库
跟新数据库,回显示到页面

MySQL中的锁机制,锁的种类。

表级锁和行级锁对比 :
表级锁: MySQL 中锁定粒度最大的一种锁(全局锁除外),是针对非索引字段加的锁,对当前操作的整张表加锁,实现简单,资源消耗也比较少,加锁快,不会出现死锁。不过,触发锁冲突的概率最高,高并发下效率极低。表级锁和存储引擎无关,MyISAM 和 InnoDB 引擎都支持表级锁。
行级锁: MySQL 中锁定粒度最小的一种锁,是 针对索引字段加的锁 ,只针对当前操作的行记录进行加锁。 行级锁能大大减少数据库操作的冲突。其加锁粒度最小,并发度高,但加锁的开销也最大,加锁慢,会出现死锁。行级锁和存储引擎有关,是在存储引擎层面实现的
共享锁和排他锁
共享锁(S 锁) :又称读锁,事务在读取记录的时候获取共享锁,允许多个事务同时获取(锁兼容)。
排他锁(X 锁) :又称写锁/独占锁,事务在修改记录的时候获取排他锁,不允许多个事务同时获取。如果一个记录已经被加了排他锁,那其他事务不能再对这条事务加任何类型的锁(锁不兼容)。
排他锁与任何的锁都不兼容,共享锁仅和共享锁兼容。
意向锁
意向锁是表级锁,共有两种:
意向共享锁(Intention Shared Lock,IS 锁):事务有意向对表中的某些记录加共享锁(S 锁),加共享锁前必须先取得该表的 IS 锁。
意向排他锁(Intention Exclusive Lock,IX 锁):事务有意向对表中的某些记录加排他锁(X 锁),加排他锁之前必须先取得该表的 IX 锁。
意向锁是有数据引擎自己维护的,用户无法手动操作意向锁,在为数据行加共享/排他锁之前,InooDB 会先获取该数据行所在在数据表的对应意向锁。
意向锁之间是互相兼容的。

乐观锁和悲观锁

悲观锁总是假设最坏的情况,认为共享资源每次被访问的时候就会出现问题(比如共享数据被修改),所以每次在获取资源操作的时候都会上锁,这样其他线程想拿到这个资源就会阻塞直到锁被上一个持有者释放。
也就是说,共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程。
像 Java 中synchronized和ReentrantLock等独占锁就是悲观锁思想的实现。
悲观锁通常多用于写多比较多的情况下(多写场景),避免频繁失败和重试影响性能

乐观锁总是假设最好的情况,认为共享资源每次被访问的时候不会出现问题,线程可以不停地执行,无需加锁也无需等待,只是在提交修改的时候去验证对应的资源(也就是数据)是否被其它线程修改了(具体方法可以使用版本号机制或 CAS 算法)。
在 Java 中java.util.concurrent.atomic包下面的原子变量类就是使用了乐观锁的一种实现方式 CAS 实现的。
乐观锁通常多于写比较少的情况下(多读场景),避免频繁加锁影响性能,大大提升了系统的吞吐量
乐观锁一般会使用版本号机制或 CAS 算法实现,CAS 算法相对来说更多一些,这里需要格外注意

MySQL的日志模块binlog和redo log。

比较重要的还要属二进制日志 binlog(归档日志)和事务日志 redo log(重做日志)和 undo log(回滚日志)
redo log(重做日志)是InnoDB存储引擎独有的,它让MySQL拥有了崩溃恢复能力。
比如 MySQL 实例挂了或宕机了,重启时,InnoDB存储引擎会使用redo log恢复数据,保证数据的持久性与完整性
redo log 它是物理日志,记录内容是“在某个数据页上做了什么修改”,属于 InnoDB 存储引擎。
而 binlog 是逻辑日志,记录内容是语句的原始逻辑,类似于“给 ID=2 这一行的 c 字段加 1”,属于MySQL Server 层。
不管用什么存储引擎,只要发生了表数据更新,都会产生 binlog 日志。
binlog 日志有三种格式
statement
row
mixed
redo log(重做日志)让InnoDB存储引擎拥有了崩溃恢复能力。
binlog(归档日志)保证了MySQL集群架构的数据一致性。
虽然它们都属于持久化的保证,但是侧重点不同
我们知道如果想要保证事务的原子性,就需要在异常发生时,对已经执行的操作进行回滚,在 MySQL 中,恢复机制是通过 回滚日志(undo log) 实现的,所有事务进行的修改都会先记录到这个回滚日志中,然后再执行相关的操作。如果执行过程中遇到异常的话,我们直接利用 回滚日志 中的信息将数据回滚到修改之前的样子即可

MySQL InnoDB 引擎使用 redo log(重做日志) 保证事务的持久性,使用 undo log(回滚日志) 来保证事务的原子性。
MySQL数据库的数据备份、主备、主主、主从都离不开binlog,需要依靠binlog来同步数据,保证数据一致性。

数据库三范式?

数据库表的设计依据。教你怎么进行数据库表的设计
数据库设计范式共有3个
第一范式:最核心,最重要的范式,所有表的设计都需要满足,要求任何一张表必须有主键,每一个字段原子性不可再分
第二范式:建立在第一范式的基础上,要求所有非主键字段完全依赖主键,不要产生部分依赖
第三范式:建立在第二范式的基础上,要求所有非主键字段直接依赖主键,不要产生传递依赖
数据库设计三范式是理论上的。
实践和理论有的时候有偏差。
最终的目的都是为了满足客户的需求,有的时候会拿冗余换执行速度
因为在sql当中,表和表之间连接次数越多,效率越低(笛卡尔积)
有的时候可能会存在冗余,但是为了减少表的连接次数,这样做也是合理的
并且对于开发人员来说,sql语句的编写难度也会降低

标签:事务,数据库,索引,InnoDB,MySQL,日志
From: https://www.cnblogs.com/song-hua/p/17128875.html

相关文章

  • 决战圣地玛丽乔亚Day13--Mysql性能调优以及乐观锁/悲观锁
    1.参数配置调优。 先pass2.索引调优如果使用联合索引,要遵循最左匹配原则。index(a,b,c) 如果想使用这个索引,那么必须遵循这个顺序使用。模糊查询也是要......
  • 批量数据插入MYSQL的研究
    MySQL中Innodb引擎不通插入方式对速度的影响简介最近在研究如何插入大量数据到MySQL中的Innodb数据库中,后来查阅资料发现有三种方法使用Mybatis使用JDBC使用JDBC批处......
  • Jmeter-jdbc-mysql
    1、下载驱动没驱动会报错:CannotloadJDBCdriverclass'com.mysql.jdbc.Driver'在选择驱动前,需要下载mysql-connector-java-5.1.7-bin.jar插件包,把插件包放置Jmeter\li......
  • MySQL(一)Linux下MySQL的安装
    Linux下MySQL的安装1MySQL的安装1.1Linux系统以及工具的准备这里使用两台CentOS7虚拟机,一台安装8.0版本,另一台克隆的虚拟机安装5.7版本克隆的虚拟机需要进行配置修......
  • MySQL(二)字符集、比较规则与规范
    1字符集的相关操作MySQL8.0之前的版本,默认字符集为latin1,8.0及之后默认为utfmb3、utfmb4,如果以前的版本忘记修改默认的密码,就会出现乱码的问题。1.1修改步骤修改mysql......
  • MySQL(四)用户与权限管理
    用户与权限管理......
  • MySQL(三)数据目录
    目录Mysql的主要目录结构1数据库文件的存放路径/var/lib/mysql/2相关命令目录/usr/bin/mysql/usr/sbin/mysql3配置文件目录/usr/share/mysql-8.0(命令及配置文件)/et......
  • MySQL--索引的数据结构
    1.为什么使用索引索引是存储引擎用于快速找到数据记录的一种数据结构,就好比一本教科书的目录部分,通过目录中找到对应文章的页面,便可以快速定位到需要的文章,mysql中也是一......
  • 解析MYSQL建表语句,生成表结构的JSON
    根据建表语句解析表结构,并将表结构解析为JSON。根据MYSQL的建表语句,建表语句:CREATETABLE`TEST`(`ID`varchar(56)NOTNULL,`CREAETE_TIME`datetimeN......
  • mysql 支持中文
    1.创建表的时候添加createtableentries2(idintauto_increment,titletext,contenttext,posted_ondatetime,prim......