开发者学堂课程【云数据库 RDS MySQL 从入门到高阶:MySQL 数据库应用介绍】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/996/detail/15067
MySQL数据库应用介绍
内容介绍:
一、数据库概念
二、数据库 CURD
三、连接数据库
四、连接池
五、连接错误
一、数据库概念
首先我们来看基本概念
1、database/schema table column(与之前学习的内容可能会有些区别)
在 MySQL 中database/schema 是同义词。Database=schema
database 在物理中代表的是目录。所以一组 schema,是指一组对象的集合,包括这些表的集合。
一个 schema 是在一个 database 的目录下面,这两个概念是重合的。对于每一个table 来说里面有多个 column,每个 column 有不同的数据类型,来存储数据,以上是基本概念。
一个 schema 归属于一个 database,一个 database 下有多个 schema。
二、数据库 CURD
诞生:
CURD 代表一个数据库对象,从它的诞生创建开始到最后被删除生命周期结束。整个生命周期的动作。
首先看 create 创建:(具体的语法自己下去理解)在数据库中对应的 curd 分很多类型。包括 DDL,叫数据定义元。DDL 对数据库来说是一个很重的操作,在创建表或其他创建索引、改表字段、删除表时,实际上属于管理性操作。
在 MySQL 中建议:
1、采用 InnoDB 引擎
在 MySQL 中支持很多引擎,分为两个层面,引擎层支持多种引擎,但是建议使用InnoDB 引擎
在引擎层支持多种引擎,例如内存引擎,但是要支持事物下还要不错的处理推断能力。
大家在使用阿里云的产品时,如果指定其他引擎,不建议使用toke DB。所以建议使用 InnoDB 引擎,这是效率最好的。
InnoDB 引擎设置索引处置表,数据存在物理的组件内。是一种物理存储模式,所以要求具有显示的定义组件。不过不带有定义组件会(rds、MySQL 会自己选择一个隐藏的字段)在数据恢复的时候会有兼容性的问题。同时建议整形和长整形,作为组件类型。因为在 MySQL 中访问的最小内存单元、尺寸单元可以自定义。
16KB 是一个多路屏幕数,从根开始逐渐增加长度。所以它的书高决定层次。从根访问到最后一个叶子找到数据,这个过程是由树高来决定的。决定L代价。L代价由树高决定,树高是根据每一个数据块分支节点决定(每个块里面能够放多少个分支),与组件类型是相关的。每一个字段的单一行占的就比较大,上限决定了16KB,决定里面可能放不下这么多,每个节点放不下那麽多分支。那么在同样的行数下,树高会很明显高出来。
所以建议使用 MTB 同时尽量不要和业务相关作为组件。
如果每次进行列表的调整,那么他的代价就会非常大。所以我们要保持正向的递增,这样插入的话代价会比较低。
同时在创建表的时候需要注意字序,如果提前指定了uti8mb4 4个字节,代表一个字符。
如果字段没有指定,那么以表为主。如果表没有指定定义,那么就以delete base为主。如果创建的表都不指定主题,那么就会以库为主。所以创建datebase的时候注意一下默认的字符距,是否符合要求。如果与表不一致的话,比如有些表比较特殊,那么创建表的时候就要在表添加指令。如果不在表添加指令,那么要在字段添加指令,比如各个字段的排序规则是不一样的。在开发的时候,尤其多人开发项目,字符距最好统一,否则会带来新的问题。
在做 DDL 的时候,不可避免的要锁表,比如说加索引的时候。但是从5.6以后,到8.0修改表增加字段。因为8.0的表存储格式有变化,就不需要做某些操作了。不需要再调整数据,直接修改表的原数据即可。
操作 DDL 建议使用 BMS,本身 BMS 支持索变更,同时与 BPS 产品配合的更好。比如表正在做数据同步,作为原数据源同步到另外一个数据库里面。这种情况下如果要修改表结构,对数据同步是有影响的,如果通过 BMS 做这个影响会降低。
2、Update
Update 代表的是更新,是对 DML 数据操作,数据修改。
对于 OLTP 来说最好走索引,OLTP 本身就是考虑事务的存储量,事务不会特别复杂,要求大量事务的处理能力。OLTP 业务转变快,尽量查询走索引。Inserd 一般不走索引。做唯一性解锁的话,需要将数据块都堵到内存里面。同时将两者作比较。
建议尽量批量处理数据,后面可以带多个数据外流。例如:inserd into 一张表,values 后面带多条数据。如果要求插入性能比较高,能够做批量操作,尽量做批量操作,这样可以带多个值,可以插多行进来。这样插入效率会比较高。
控制事务大小:数据库中不适合大事务,长事务。
大事务:一次性删5千万行,这是一个很大的事务。这个事务就只有两种状态,要么失误,要么成功提交。
很大的事务对数据库就有很大的压力,同时相互之间会有所冲突。这是对数据库不管是L也好还是锁也好,都是一个很大的负担。会引起数据库很大的波动,甚至把数据库卡死。所以对于 OLTP 这种类型,一定要控制事务大小,不要太大。
控制事务时长:如果事务没有尽快提交,那么很多资源,包括锁,都不能及时的释放掉。时长是业务问题的根源。
3、Retrieve
OLTP 业务尽量走索引:如果表的尺寸不是很小,比如说300-500行,扫描可能会更快。全扫描、全组件扫描。如果表的尺寸比较大,而且选取的数据只在表中占很小的比例,超过表行数的20%,这种情况下是不会走索引的。
索引体作用的两个条件:1、表的行数比较多;2、查询 select query 从中间拿的很小很小的一部分。相当于在图书馆中藏书很多,你就从取走两本。如果说图书馆里面的藏书有十万册,我要一次性拿走5万册,不要解锁,直接按照柜子搬走就可以了。
仅选取必须字段:现在的开发许多都走框架,但是有很大的问题,会把表列为对象,之后实体化。每个都是它的属性。实体化之后通过属性来操作这个表。但是框架形成的查询不会显星,会把后面所有的字段都拿出来。
访问这个表的时候会需要这个表的属性,比如他有哪些字段,但是一查询来说对业务是透明的,拿到表的元数据之后,他会拼一个出来,会把所有的字段都列在里面。为什么这样不好?
因为是行式的存储,若把所有的字段都拿出来,只能访问一行,此时不能走覆盖性索引,就是不能把访问的数据局限在某一个层次上。覆盖性的索引不会回表,他的速度非常快,在回表的时候会有很多散乱的随机索取。不管底层用SSD也好,物理磁盘也好,底层的存储都是不欢迎的。喜欢TIY一体的。从一个点开始往后跨多少块,这种串行的访问是很欢迎的。但是如果是随机的访问,每次都是很小块,地址都不一样,也是不欢迎的。
因此 OLTP 最核心的查询(应用20-30%都是这个查询,带的条件都是一样的),也不是寻找所有字段,这时候添加索引,可以做最核心的查询。
不要用数据库做计算:硬件成本比较高(可能会占到整个项目一半),他的硬件会跑到小 T 上面,所以他的计算能力比较强。很多的业务逻辑,很多业务放到存储过程或者pakedge 里面。数据库是用来存数据或者取数据的,或者高效的存数据,高效的取数据,它最基本的功能就是这些,做计算不太合适。比如说做 orderby 还好,但是做哈希,计算,尽量放在前面去做。对于应用层,应用服务器层的运算是非常大的。这种前面的计算能力非常强,to C 或者手机端性能,最好不要将计算放在数据库,就像蚂蚁吃大象。这样数据受不了。
一次查询,多次复用:数据最好持久存储从数据库中取出来,在业务允许的情况下尽量多次复用,不要把相同的查询都放在数据库中。Redles 是用来抗这些访问量的。
4、Delete
表示对象的删除;这个对象的生命周期结束,没有存在意义,需要删除表。
DDL 要在业务发布窗口来操作:因为这是一个重操作,一定要有业务发展的窗口。而且在业务发展之前要在线下的环境做测试,但是不能做100%的测试,做30%左右的测试,估计一下时间。不要在业务高峰期做 DDL。为了避免后面真正出现问题,就可以建立一个索引。在业务高峰期建索引会带来很大的风险。
建议操作前做备份:不论是真正的销毁对象还是真正上去做 DDL,对于实力来说最好提前做备份,因为数据最重要。哪怕生长环境出现问题,但是数据不能丢。这种 DDL本身就是有风险的操作,所以建议操作之前做备份。
如果出现问题,比如删除了对象或者某些数据出现问题,首先第一件事情要保护现场,不要再引入新的错误。因为出错之后可能会比较慌张,可能会没有考虑清楚,又做了更多的错误操作。
由一个错误带来更多的错误。所以这个时候需要保护现场,我们 rds 或者 polo 这些都支持克隆实例恢复。
克隆实例数据:不要动现场的数据,保护现场。通过备份创建一个新的克隆实例。
指定时间表或者指定位点。然后做 DDL 的时候有件事情,尤其是 justone 加索引,删索引,删字段一定要只有一个,因为 DDL 本身是要改这个表的原数据,在整个执行过程中要有两次,要把这个表原数据拿到后置索引来,这时拿到后置锁,锁住表的原数据,其他任何都没有办法执行,即便是一个查询也要读数据。
要读一下表的元数据,读一下表有哪些字段。在同一个时段对多个字段进行操作会发现许多原数据锁,会对业务产生很大的影响。即便跑的是 alineDB 原数据也不能aline。
三、连接数据库
这里面是我们之前写的 TR 代码,连数据库很简单。从 main 入手加入代码。
1、创建一个连接对象
DB 的对象是g et connection 就是自己写的方法。
参数 url:远程访问数据库的地址,包括:端口、库可以写在里面,需要用户名、用户、密码。
参数 poolsize:是连接池,一个是连接池的大小,一个是连接池的初始大小。
驱动名:指定即可,是一个固定字符串。首先第一个要创建一个连接,从应用到数据库。下面用上面创建的连接执行查询,并且展示结果。之后关闭连接即可。关闭连接源于使用的连接池,默认为 jdbc 连接。
所有的连接都是基于 JDBC 的驱动,关不关闭是取决于连接池的特性。某些连接池是不用管 shutdown 的。
2、get connection
图中的 get connection 是先写了一段代码,下面模拟了市面上常见的 JDBC 驱动或者各种连接池(dbcp1、dbcp2、hikari、c3po、bonecp、tomcat)这些代码是用来做从应用到RDSMySQL,连接测试的。所以可以使用不同的连接池,作为一个参数传进来(是最原始的JDBC),连接数据库。(通过连接池的方式连接数据库)
Type 传进来之后会有不同的 case;
Dp0是来用于 dbcp 连接进行属性设置的;下面的代码就是设置不同的方式。
下面的也是,创建 source 然后设各种参数,然后 get connection 就好。
3、如何使用
所展示的就是所执行的;用 MySQL 的 cuid 做复制,唯一标识的 instens,实例的ID值。然后标明当天的时间、在哪一个数据库、MySQL 是什么版本的、当天是哪一位用户、唯一标识绘画的 ID 是哪一个?
下面就开始执行,其中包括用来输出的格式(无需关注),将上述的所有值拿到,展示出来。没有提到最后一个值的时候循环一下,展示出来。
这个是比较简单的,就是创建一个连接,执行我的 SQL,关闭连接。
上图实在控制文件内写的,MySQL 的驱动:connector Java;驱动版本:8.0.16(会自动更新,8.0建议使用更高的版本,低的版本8.0会出现问题,有些MY SQL的参数被取消掉了)
图片下面是执行的结果:时间、地点、版本、使用者、ID(schema是数据库中默认的系统库,代表很多底层的视图,比如information下面的tables,获取所有表的元数据的信息)通过这些图看一下当前有哪些活动的绘画,连接的绘画有哪些,取决于产品的条件。数据库的版本8.25.当天我是哪个用户上来的。
Session-ID,为什么要有 Session-ID?如果杀了我的绘画,怎么杀?就是tile+Session-ID.
驱动:com.MySQL.cj.jbdc
Java还好,都是长连接。
长连接:添加一个 tcpa,就是从客户端应用到数据库,建一个 tcpa 的连接。中间的通讯过程 SYN、ACK、三次握手,涉及到两个系统中的 syns queue、accept queue代表不同的状态。Dbsnt 就是解决以上事情的。不能接受新的连接,有用的业务就被忽略掉了,再创建连接就会被丢弃。
前面是内核处理的过程。真正 MY SQLD 业务进程,包括数据库也是一个特殊的应用。MySQL 从 queue 拿出来这个连接来处理,之后到用户来处理。如果将上述内容打码,那么后续的信息就难以传出。
发出一个查询到数据库内让数据库处理,数据库处理完之后将数据库结果即回给客户端,然后客户端收提了之后再去展现。
如果是一个长连接,(中间过程很复杂)每次建立一个连接的成本是很大的,一个连接建立之后,不光是本次使用,这个连接还可以使其他的内部连接来用。连接可以复用,这种情况下这种连接始终不会断的,可以在数据库中保持很长的时间。这种情况下叫做长连接。每次在发请求的时候不需要重新创建连接,可以复用之前的,叫做长连接模式。这种一般会使用连接池来管理数据库。这种情况下客户端看到数据库请求的迟延是从发请求开始的到收起结果。
短链接从 TCP 内核发 connect 请求,发 SYN 三次握手开始直到收起结果结束。可以看到明显上面一层多很多。
客户端 RT=服务器 RT+网络延迟+客户端处理时间,这里重点说一下客户看到的显示延迟是包含三个部分的,不是说客户看到我的 SQL 跑得很慢,就觉得数据库处理的慢,可能是网络延迟高,或者是客户端本身处理时间长。因为结果集发过来的时候,不管是什么也好,需要buf收起,从网卡往上面提交到 TCP,OS 的内核。收齐之后会在内核里面产生一个信号,因为一般情况下现在编程应用内测都是异步的L。不管是网络L也好还是磁盘的L也好,当然也有可能是乒乓协议(可能客户端就一直在等待)。这时候会产生一种信号,给你应用这一侧的进程。这个信号发给应用,应用如果在IF模式下面干别的这时候它必须跑到它能处理信号的节点上,他现在在某些原子操作里面出不来,那么信号就得一直等着。处理完信号从 TCP 系统的内核里面考出来到 ping 的内存空间里面。这是内存拷贝的过程。拷贝完了之后才能开始处理。
(我们看到不止一次客户端的 CPU 打满了,资源很紧张,资源满了,数据库处理的很快,客户端看到的RT非常高)客户端只能看到处理完结果之后的RT,但是看不到过程。
四、连接池
在应用一侧编程中专门设置一个连接池的对象,初始化一样的对象,这个对象可以管连接,在初始连接池被创建的时候,会连接到后来数据库。这样在使用应用的时候,内部不同的 thread 或者 process,一般都是 thread。
thread 从连接池的 borrow,拿一个连接出来,这个连接目前是空闲的,拿出来之后发出一个请求给数据库,处理完之后给应用。
这时候用完了,把数据 Return 归还到连接池内,方便其他人用。
五、连接错误
1、在连接或者请求,总有失败的时候(网络丢包,网络乱序,网络中断),在这种情况下会带来不同的错误。(配置写错、传输错误)
连接不上:查 TCP 是否建立了连接
2、Too many connections:连接到头
3、Connect timecout:在超时之前,MY-SQL 里面有一个参数 Connect timecout,发出 TCP 给客户端,客户端多长时间之内必须将 login request(用户名密码)发过来。如果连接在这个时间内没有完成登录、身份验证操作,那么这时候就会汇报这个错误。
这个错误首先用户名的密码是对的,如果不正确可以检查 Connect timecout 是否被别人修改。
4、reading from net:客户端收结果即在规定时间内没有收走,服务器端将结果写回到客户端,写不到应用这边。如果在规定的 net read timecout 超出之前,没有结果传出完毕,直接缺了一行数据,这是需要注意一下 net read timecout 是不是设置的太小了。网络不好的话,拉海量的数据可能在超时之前拉不完。这就会报错。
5、net rwrite timecout 在超时前,未能完成结果集收取
6、socket timecout 在超时前,未能完成结果集收取
7、空闲时间,这里有两个参数,这两个参数定义的是非交互模式的空闲时间,之后工作会选取适合的其中一个。
wait 超过空闲时间数据库会自动断开。针对于绘画(非交互模式)超过空闲时间数据库会自动断开。interactive timecout(交互模式)
以上两个只在数据库内定义了值,他们两个对于哪一个生效需要将绘画连上来,之后绘画级别的 timecout 会从两个中选取一个。