MySQL笔记

https://blog.csdn.net/adminpd/article/details/122910606?
https://blog.csdn.net/TZ845195485/article/details/119550626?
https://programskills.blog.csdn.net/article/details/88526708?
https://blog.csdn.net/adminpd/article/details/122910606?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522165538140616782388064900%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=165538140616782388064900&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-122910606-null-null.142^v17^control,157^v15^new_3&utm_term=mysql%E9%9D%A2%E8%AF%95%E9%A2%98&spm=1018.2226.3001.4187
https://blog.csdn.net/WenWu_Both/article/details/124400021?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522165606041116782389458552%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=165606041116782389458552&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-2-124400021-null-null.142^v21^control,157^v15^new_3&utm_term=innodb%E5%A6%82%E4%BD%95%E5%AD%98%E5%82%A8%E5%A4%9A%E4%B8%AA%E7%B4%A2%E5%BC%95&spm=1018.2226.3001.4187

一、应用:
0、基本概念梳理?
数据库/表——对应存储在数据库服务器上。主从结构集群里,从备份主;
数据库服务器——具体的服务器带ip,eg: s1(192.168.1.1)、s2(192.168.1.2)、s3(192.168.1.3),在集群结构里分为主/从;
集群——由 主/从 数据库服务器s1/s2/s3组成,叫做一个C(class),也对应一个实例;
实例——一个集群对外提供的服务,叫一个实例;
数据库连接地址——由集群通过DNS出的一个固定名称,eg:loanplatform-mw0-3306-db.in.autohome.com.cn;
数据库连接——连接的是实例;
账号密码——客户端的权限;

1、innodb?
支持事务(所以不支持存储count(*))、支持聚簇索引、索引即数据、B+树

2、数据库范式?
第一范式(1NF):字段(或属性)是不可分割的最小单元,即不会有重复的列,体现原子性
第二范式(2NF):满足 1NF 前提下,存在一个候选码,非主属性全部依赖该候选码,即存在主键,体现唯一性,专业术语则是消除部分函数依赖
第三范式(3NF):满足 2NF 前提下,非主属性必须互不依赖,消除传递依赖


3、mysql架构:https://blog.csdn.net/TZ845195485/article/details/119550626?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522165553395816782425139174%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=165553395816782425139174&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-2-119550626-null-null.142^v17^control,157^v15^new_3&utm_term=mysql%E6%89%A7%E8%A1%8C%E5%99%A8&spm=1018.2226.3001.4187
(1)三层架构:
客户端;
server层:连接器、查询缓存、词法分析器(词法分析、语法分析)、优化器、执行器;
存储引擎层:存储引擎BufferPool;
本地磁盘文件:磁盘文件、undo日志文件、redo日志文件、binlog文件;

(2)查询优化器?https://blog.csdn.net/u013308490/article/details/121290581
MySQL 优化器使用基于成本的优化方式,利用数据字典和统计信息选择 SQL 语句的最佳执行方式,选择索引是优化器的事情。
同时,MySQL 为我们提供了控制优化器的各种选项,包括控制优化程度、设置成本常量、统计信息收集(SHOW INDEX FROM T)、启用/禁用优化行为以及使用优化器提示等。
a.逻辑转换,包括否定消除、等值传递和常量传递、常量表达式求值、外连接转换为内连接、子查询转换、视图合并等;通过SHOW WARNINGS命令可以查看逻辑转换之后的 SQL 语句;
b.基于成本优化,包括访问方法和连接顺序的选择等;
c.执行计划改进,例如表条件下推、访问方法调整、排序避免以及索引条件下推。

(3)查询缓存?https://blog.csdn.net/Hpsyche/article/details/104460944
在 mysql8 后已经没有查询缓存这个功能了,因为这个缓存非常容易被清空掉,命中率比较低。


4、innodb数据存储结构?
段(逻辑概念,索引和实际数据分开)、区、页、行


5、索引:
(1)MySQL里怎么查看是否使用了索引?explain
在select语句之前增加explain关键字,MySQL会在查询上设置一个标记,执行查询会返回执行计划的信息,而不是执行SQL。
EXPLAIN只对SELECT查询作解释,INSERT、UPDATE、DELETE不会。
1)表的读取顺序。(对应id)
2)数据读取操作的操作类型。(对应select_type)
3)哪些索引可以使用。(对应possible_keys)
4)哪些索引被实际使用。(对应key)
5)表直接的引用。(对应ref)
6)每张表有多少行被优化器查询。(对应rows)。

(2)explain原理?
优化器,利用数据库的统计信息决定 SQL 语句的最佳执行方式。使用索引还是全表扫描的方式访问单个表,多表连接的实现方式等。优化器是决定查询性能的关键组件,而数据库的统计信息是优化器判断的基础。

(2)二叉平衡树、B树、红黑树、B+树?https://blog.csdn.net/wanderlustLee/article/details/81297253?spm=1001.2014.3001.5506
二叉搜索树:父节点大于左子树 小于右子树,极端情况线性;
avl二叉平衡树:左右子树的高度差不大于1,多次自旋转,解决线性问题,但是由于二叉,层数大搜索次数多 需要多次磁盘IO;
B数 balance-tree:多路平衡树,对减少磁盘IO的次数,但是查找不稳定,目标节点会出现在非叶子节点;
B+树:数据只存储在叶子节点,非叶子节点只存放索引,这样保证每一层可以容纳更多元素,查找时,磁盘IO的次数减少; 并且每个叶子结点也通过指针指向构成了一种链表结构,所以遍历数据也会简单很多;

(3)mysql索引原理?
聚簇索引:以主键id为索引的B+树索引;
非聚簇索引:非主键id为索引的B+树索引,叶子节点每行数据只存储主键id,再去聚簇索引里根据id查 即回表;

(4)回表?索引覆盖指什么?最左匹配原则、索引下推?
回表:非聚簇索引根据主键id二次查询聚簇索引得到行完整数据的过程。条查询语句在索引a上做的是一个范围查询--Multi-Range Read优化:1. 根据索引a,定位到满足条件的记录,将id值放入read_rnd_buffer中;2. 将read_rnd_buffer中的id进行递增排序;3. 排序后的id数组,依次到主键id索引中查记录,并作为结果返回。
索引覆盖:一次索引查询后,不用回表;
最左匹配原则:where a like 'XXX%’,索引有效;
索引下推:联合索引查询时,where a like 'XXX%’and b='xxx',回表之前,会对b进行筛选,不用二次回表;

(5)联合索引?      https://blog.csdn.net/liujun19921020/article/details/103215701
当创建**(a,b,c)联合索引时,相当于创建了(a)单列索引**,(a,b)联合索引以及**(a,b,c)联合索引**
满足最左匹配原则,想要索引生效的话,只能使用 a和a,b和a,b,c三种组合;当然,我们上面测试过,a,c组合也可以,但实际上只用到了a的索引,c并没有用到!

(6)多个列的单字段索引?
index merge(索引合并),MySQL5.0之前,一个表一次只能使用一个索引,无法同时使用多个索引分别进行条件扫描。但是从5.1开始,引入了 index merge 优化技术,对同一个表可以使用多个索引分别进行条件扫描;

(7)orderby原理? 
建议where和orderby字段建立联合索引;
如果未建立联合索引,则orderby会在内存申请一块buffer,用于排序,还会在磁盘生成归并排序文件;
有两种 全排序 vs rowid排序,全排序不用回表不占用io资源但是文件会比较多、rowid排序需要回表占用io资源但是文件比较少;

(8)join原理?https://blog.csdn.net/qq_27184497/article/details/119302700
1). select * from A join B on A.id=B.id where A.id = 1;
在查询时,驱动表A会根据关联字段的索引进行查找B表,当在索引上找到符合的值,在回表进行查询,也就是说得匹配到索引后才会进行回表查询;
驱动表N条,被驱动表M条,因此整个执行过程,近似复杂度是 N+N*2*log M。
1. 使用join语句,性能比强行拆成多个单表执行SQL语句的性能要好;
2. 如果使用join语句的话,需要让小表做驱动表。
但是,你需要注意,这个结论的前提是“可以使用被驱动表的索引”。
2). select * from A join B on A.id=B.id;
无索引,申请一个Block Nested-Loop Join buffer 缓冲区,是内存操作,把驱动表select后面的列缓存,然后与批量与非驱动表进行匹配;
1. 两个表都做一次全表扫描,所以总的扫描行数是M+N;
2. 内存中的判断次数是M*N。
调换这两个算式中的M和N没差别,因此这时候选择大表还是小表做驱动表,执行耗时是一样的。

(10)什么样的字段加索引?
什么样的字段加索引?where(当like的时候最好用到最左前缀匹配原则 ‘XXX%’)、join、where+。orderby;
(11)什么样的字段不适合加索引?
不在enum上建、不在重复性高的字段建;
(12)什么情况索引失效?https://blog.csdn.net/qq_63815371/article/details/124337932?
列上进行运算、类型转换、 != 和NOT IN和<>操作、where a like '%XXX...’违反最左前缀 单个索引或者复合索引都失效、OR 前后只要存在非索引的列 都会导致索引失效 、范围条件右边的列索引失效;


6、mysql优化?
https://blog.csdn.net/orecle_littleboy/article/details/88534160
1)字段长度、类型 合理选择
2)用join连接取代in,因为in会建立临时表,join最好配合索引

7、日志:
(1)存储结构:
service层:执行器---负责对接引擎层,负责拿到数据进行计算 再返回给引擎层。
存储引擎层:引擎接口,内存Buffer Pool,redolog,磁盘数据。

(2)都有哪些日志:
https://www.cnblogs.com/myseries/p/10728533.html
重做日志(redo log):物理日志
作用是确保事务的持久性。 redo 日志记录事务执行后的状态,用来恢复未写入 data file 的已提交事务数据。
回滚日志(undo log):逻辑日志
作用是保证数据的原子性。 保存了事务发生之前的数据的一个版本,可以用于回滚,同时可以提供多版本并发控制下的读(MVCC),也即非锁定读。
二进制日志(binlog):逻辑日志
常用于主从同步或数据同步中,也可用于数据库基于时间点的还原。
错误日志(errorlog)
记录着 MySQL 启动和停止,以及服务器在运行过程中发生的错误的相关信息。在默认情况下,系统记录错误日志的功能是关闭的,错误信息被输出到标准错误输出。
普通查询日志(general query log)
记录了服务器接收到的每一个命令,无论命令语句是否正确,因此会带来不小开销,所以也是默认关闭的。
慢查询日志(slow query log)
记录执行时间过长和没有使用索引的查询语句(默认 10s),同时只会记录执行成功的语句。
中继日志(relay log)
在从节点中存储接收到的 binlog 日志内容,用于主从同步。


(3)日志简介?
https://blog.csdn.net/TZ845195485/article/details/119550626?
https://programskills.blog.csdn.net/article/details/88526708?
更新数据为例:update t set name = 'new' where name = 'old';
先写入undo磁盘日志文件,name='old';(用于事务提交失败要回滚时候,用undo日志恢复);
更新innoDB的BufferPool缓冲池,事务提交成功;
写redo磁盘日志文件,name=‘new';(如果事务提交成功,bufferpool里的数据更新了,但是还没来得及写入磁盘,此时系统宕机了,可以用redo日志恢复bufferpool的缓存数据);
binlog文件(属于service层),name='new';(binlog用于恢复数据库磁盘里的数据);

(一)redo log(重做日志)--崩溃恢复:
存储引擎层,是物理日志,记录的是数据库中物理页的情况 (可以保证即使数据库发生异常重启,之前提交的记录都不会丢失,这个能力称为crash-safe),“循环写”,用于崩溃恢复(写了内存还没来得及刷盘,内存挂了,用redolog恢复)。
redo log在事务中的作用?崩溃恢复。
redo log采用的是WAL(Write-ahead logging,预写式日志),所有修改先写入日志,再更新到Buffer Pool;

(二)binlog(归档日志):
1)Server层,binlog会记录所有的逻辑操作,“追加写”,用于主从同步、误删写。
2)数据库恢复到最近半个月内任意一秒的状态?
两个必备条件——保存最近半个月的所有binlog,同时系统会定期做整库备份。 
具体做法——找到最近的一次全量备份,恢复到临时库;从备份的时间点开始,将备份的binlog依次取出来,恢复到我们要的时间点;
两阶段提交的作用——为了让两份日志之间的逻辑一致,binlog用于主从同步与误删写、redolog用于崩溃恢复;
3)两阶段提交:为了让两份日志之间的逻辑一致。    https://blog.csdn.net/qq_33591903/article/details/122030252?
将redo log的写入拆成了两个步骤:prepare和commit
prepare:数据更新到了内存,redolog写入磁盘成功,--此时redo log处于prepare状态,然后告知执行器执行完成了,随时可以提交事务。
commit:执行器生成binlog,binlog写入磁盘成功,执行器调用引擎的提交事务接口 ---引擎把刚刚写入的redo log改成提交(commit)状态,更新完成。

(三)undo log(回滚日志) --往前追溯:
存储引擎层,用于回滚事务、实现事务隔离性的MVCC版本控制 实现快照读。
insert undo log
代表事务在 insert 新记录时产生的 undo log, 只在事务回滚时需要,并且在事务提交后可以被立即丢弃。
update undo log
事务在进行 update 或 delete 时产生的 undo log ; 不仅在事务回滚时需要,在快照读时也需要;所以不能随便删除,只有在快照读或事务回滚不涉及该日志时,对应的日志才会被 purge 线程统一清除。
不同事务或者相同事务的对同一记录的修改,会导致该记录的undo log成为一条记录版本线性表,既链表,undo log 的链首就是最新的旧记录,链尾就是最早的旧记录(当然就像之前说的该 undo log 的节点可能是会 purge 线程清除掉,向图中的第一条 insert undo log,其实在事务提交之后可能就被删除丢失了,不过这里为了演示,所以还放在这里)


8、mysql锁:
https://blog.csdn.net/SnailMann/article/details/88388829
(1)CAS思想:应用于乐观锁
CAS指令(Compare and Swap),
思想:CAS指令需要3个操作数,分别是内存位置V,旧的预期值A,和新值B。
CAS指令执行时,当我们读取的内置位置V的现值等于旧预期值A时,处理器才会将新值B去更新内置位置V的值。否则它就不执行更新,但无论是否更新V的值,都会返回V的旧值。

(2)乐观锁悲观锁思想?
乐观锁悲观锁是一种思想,本质都不是数据库中具体锁的概念,而是我们定义出来,用来描述两种类别的锁的思想。
(乐观锁和悲观锁的概念不仅仅存在于数据库领域,可以说存在线程安全,存在并发的场景几乎都有乐观锁和悲观锁的适用场景,比如Java中也有乐观锁和悲观锁思想的具体实现;但不同领域的乐观和悲观锁的具体实现都不尽相同,要解决的问题也可能有所不一样)
c. MVCC(多版本并发控制)
a. 悲观锁(悲观并发控制(PCC)):采用悲观的态度,默认数据被外界访问时,必然会产生冲突。
实现--数据库的悲观锁就是利用数据库本身提供的锁去实现的,解决读-写冲突和写-写冲突。
b. 乐观锁(乐观并发控制(OCC)):采用乐观的态度,默认数据被外界访问时,不会产生冲突。数据库的乐观并发控制指在用无锁的方式,解决数据库并发场景下的写-写冲突。
缺点:在写多读少的并发场景下,即在写操作竞争激烈的情况下,会导致CAS多次重试,冲突频率过高,导致开销比悲观锁更高。
实现--CAS思想
方式一:使用数据版本(version)实现---在表中添加一个version记录版本标识,读取了数据(包括version),做出更新 要提交的时候,就会拿取得的version去跟数据库中的version比较是否一致,一致则予以更新,不一致则返回冲突信息,让用户决定和下一步比如重试等。
             update table set num = num + 1 , version = version + 1 where version = #{version} and id = #{id}
方式二:使用时间戳(timestamp)实现---原理思想同上。
update table set num = num + 1 ,update_time = unix_timestamp(now()) where id = #{id} and update_time = #{updateTime} 

(3)锁机制?
1)锁粒度:并不是具体的锁,仅代表数据库某个层级上的数据锁定。具体怎么去锁这个数据,还要看具体的锁实现是什么。
表锁、页锁、行锁;
2)锁类型:
共享锁、排他锁、意向共享锁、意向排他锁;
(意向锁作用:意向锁用于快速判断表锁和行锁之间是否有冲突)
3)思想:
乐观锁、悲观锁;
(Mysql中悲观锁的实现是基于Mysql自身的锁机制实现,而乐观锁需要程序员自己去实现的锁机制,最常见的乐观锁实现就锁机制是使用版本号实现)

(4)myisam与innodb锁?
myisam---表锁(读读共享,读写互斥,写写互斥):共享锁、排他锁、意向共享锁、意向排他锁;
innodb---表锁:共享锁、排他锁、意向共享锁、意向排他锁;
               行锁:共享锁(S锁)、排他锁(X锁);

(5)InnoDB下 行锁与索引,行锁的实现原理?
表锁:省略;
行锁:InnoDB的行锁是加在索引之上的,这意味着只有通过索引条件检索数据,才会使用行锁,否则将使用表锁。
(行锁是基于聚簇索引实现的,不管该表存在多少个索引,行锁所锁的索引记录都是属于该表的聚簇索引的,既InnoDB的行锁锁住某行数据的本质是锁住行数据对应在聚簇索引的索引记录 。 
既当存在主键时,主键索引就是聚簇索引,当没有主键时,顺位第一个唯一非空列建立的索引就是聚簇索引,以上都不满足时,InnoDB就会启动内部生成隐式主键索引作为聚簇索引。)

(8)两阶段锁协议?
两阶段锁协议,分为加锁阶段和解锁阶段,所有的 lock 操作都在 unlock 操作之后。

(6)InnoDB下 锁与事务,锁的使用时机?
SELECT:不加锁,用MVCC多版本控制实现;
DELETE/INSERT/UPDATE:   加X锁;获得锁之后,事务便可以修改数据;该事务操作期间,这部分数据是锁定的,其他事务如果需要修改数据,需要等待当前事务提交或回滚后释放锁。(两阶段锁协议,分为加锁阶段和解锁阶段,所有的 lock 操作都在 unlock 操作之后。)

(7)行锁的死锁?
死锁:行锁是在事务提交之后才释放,在事务提交之前,一直持有行锁,如果两个事务各自持有对方需要的锁,则进入循环等待死锁。
innodb两种解决方案:
1. 超时时间可以通过参数 innodb_lock_wait_timeout来设置。在InnoDB中,innodb_lock_wait_timeout的默认值是50s,时间过长。但是超时时间设置太短的话,如果不是死锁,而是简单的锁等待则会出现很多失误。
2. 主动死锁检测nnodb_deadlock_detect的默认值本身就是on。
如果你的事务中需要锁多个行,要把最可能造成锁冲突、最可能影响并发度的锁的申请时机尽量往后放。
但是,调整语句顺序并不能完全避免死锁。所以我们引入了死锁和死锁检测的概念,以及提供了三个方案,来减少死锁对数据库的影响。减少死锁的主要方向,就是控制访问相同资源的并发事务量。


9、【单机事务】,遵从 ACID 原则:
(1)mysql事务特性:acid原则?
a原子性(Atomicity):指事务是一个不可分割的最小工作单位,事务中的操作只有都发生和都不发生两种情况
c一致性(Consistency):事务必须使数据库从一个一致状态变换到另外一个一致状态,举一个栗子,李二给王五转账50元,其事务就是让李二账户上减去50元,王五账户上加上50元;一致性是指其他事务看到的情况是要么李二还没有给王五转账的状态,要么王五已经成功接收到李二的50元转账。而对于李二少了50元,王五还没加上50元这个中间状态是不可见的。
i隔离性(Isolation):一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
d持久性(Durability):一个事务一旦提交成功,它对数据库中数据的改变将是永久性的,接下来的其他操作或故障不应对其有任何影响。

(2)并发情况下,事务需要解决几种问题?
1. 脏读:T2读取了T1未提交的变更 --------一个事务未提交就对数据库产生了实质影响
2.不可重复读:T2事务内,由于同一行数据T1提交后做了变更,T2多次读取结果不一致.   -----两个事务的读写/写写冲突,innodb事务隔离级别repeatable read(可重复读)就避免了 底层原理是MVCC;
3.幻读:T2事务内,不同行数据T1提交后做了变更,T2多次读取结果集多了.    ------两个事务同时读写/写写,但是由于没有冲突,innodb事务隔离级别repeatable read(可重复读)无法避免,serializable(串行化)锁表可以避免;

(3)事务隔离级别?
1. read uncommitted(读未提交数据):(脏读、不可重复读和幻读的问题都会出现)。
2. read committed(读已提交数据):(避免脏读,但不可重复读和幻读的问题仍然可能出现)
3.repeatable read(可重复读)---innodb隔离级别:(避免脏读和不可重复读,但幻读仍然存在)
4. serializable(串行化):(脏读、不可重复读和幻读的问题都 可以避免)。

(4)视图?https://blog.csdn.net/weixin_40228200/article/details/122020400
虚拟的表,本质对应后面的真实表数据,只可以查询和更新,不可以新增和删除。事务的隔离性的多版本控制用到了视图。

(5)事务隔离级别 repeatable read(可重复读)原理,MVCC多版本并发控制(快照读和当前读)?    

InnoDB的行数据有多个版本,每个数据版本有自己的rowtrx_id,每个事务或者语句有自己的一致性视图。普通查询语句是一致性读,一致性读会根据rowtrx_id和一致性视图确定数据版本的可见性。
对于可重复读,查询只承认在事务启动前就已经提交完成的数据;
对于读提交,查询只承认在语句启动前就已经提交完成的数据;
而当前读,总是读取已经提交完成的最新版本。
你也可以想一下,为什么表结构不支持“可重复读”?这是因为表结构没有对应的行数据,也没有rowtrx_id,因此只能遵循当前读的逻辑。当然,MySQL 8.0已经可以把表结构放在InnoDB字典里了,也许以后会支持表结构的可重复读。

 
当前读:更新数据都是先读后写的,而这个读,只能读当前的值,称为“当前读”(current read)。
             写update/insert/delete更新语句,读取的是记录的最新版本,读取时对读取的记录加锁,保证其他并发事务不能修改当前记录;
快照读:begin/start transaction 命令并不是一个事务的起点,在执行到它们之后的第一个操作InnoDB表的语句,事务才真正启动。如果你想要马上启动一个事务,可以使用start transaction with consistent snapshot 这个命令。
             读select查询语句,读可以读取当前事务版本,也就是当前行的历史版本,原理见MVCC,不用加锁,非阻塞读,(快照读的前提是隔离级别不是串行级别,串行级别下的快照读会退化成当前读);

A. MVCC原理--具体实现则是由 3 个隐式字段,undo 日志版本链 ,Read View(读视图) 等去完成的   --------------------------------(关注点:历史版本的快照读)
https://blog.csdn.net/SnailMann/article/details/94724197
MVCC,Multi-Version Concurrency Control ,即多版本并发控制。MVCC 在 MySQL InnoDB 中应用于 事务的隔离性(不可重复读),作用提高数据库并发性能,维持一个数据的多个版本,能做到不加锁 处理读-写冲突,非阻塞并发读。
     InnoDB里面每个事务有一个唯一的事务ID,叫作transaction id。它是在事务开始的时候向InnoDB的事务系统申请的,是按申请顺序严格递增的。
     而每行数据也都是有多个版本undolog的。每次事务更新数据的时候,都会生成一个新的数据版本undolog,并且把transaction id赋值给这个数据版本的事务ID,记为rowtrx_id。同时,旧的数据版本要保留,并且在新的数据版本中,能够有信息可以直接拿到它。
     Read View遵循一个可见性算法,对于每一行,当前事务Id维护可见的事务ID集合(包括自己在内)(如果事务内自己要写了,属于当前读,则视图的事务集合是变化的,可以读到最新版本数据并进行写操作), 满足可见性的最新的数据行undolog版本,找到这个版本的方法就是 沿着undolog链 从最新版本开始 倒序查找并用可见性做判断。

B.   update事务 具体实现步骤?   --------------------------------------(关注点:最新版本的当前写)
https://blog.csdn.net/u013314679/article/details/109389649
https://blog.csdn.net/inthat/article/details/123244844
a. 提交:更新事务   ----commit在哪个环节?
行加 排他锁 》写undolog 》修改内存值 》执行mtr_commit函数提交本MTR(内存值标记dirty,后续刷脏-同步到磁盘) 》写redolog(pre) 》 写binlog(commit) 》事务提交 释放 排他锁
b. 回滚:更新事务   ----rollback在哪个环节?
c. 异常:

(7)事务原子性底层原理?
事务原子性的底层原理--undolog回滚。

(8)事务持久性底层原理?
事务持久化的底层原理--redolg 二阶段提交,保证即使宕机也可以用redolog实现崩溃恢复。

(9)什么场景需要使用事务?以及事务会存在的问题?
1)保持事务的原子性,一起成功一起失败,多个Sql语句放在一个事务里。
2)一个事务里既有读也有写,并发场景下,事务也无法避免什么问题?
A.  事务T1,第一步读,事务T2写并提交,T1再写,此时写的数据已经不是最初读到的数据了。解决办法:更新的时候,where条件 用旧值做判断是否被其他事务更新了。
B.  事务T1,第一步读,事务T2写但未提交,T1再写,此时,就看谁先提交了,存在写覆盖问题。 解决办法:

(10)mysql事务,springboot中代码里具体如何实现的 ? ???


10、【分布式事务】-XA事务,遵从CAP原则,(用于分库分表场景--重点在于非单机环境,保证事务在多个服务器库上执行的原子性):——————————
(1)CAP原则:
CAP原则又称CAP定理,指的是在一个分布式系统中,一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance),三者不可共存。
CAP原则的精髓就是要么AP,要么CP,要么AC,但是不存在CAP。
(2)XA事务:
MySQL如何实现多个MySQL数据库更新的一致性呢?那就是MySQL XA。MySQL正是靠支持XA规范的二阶段提交协议,才实现了多个数据库的操作。

XA 不能自动提交。XA需要两阶段提交: prepare 和 commit————
第一阶段为 准备(prepare)阶段。即所有的参与者准备执行事务并锁住需要的资源。参与者ready时,向transaction manager报告已准备就绪。 
第二阶段为提交阶段(commit)。当transaction manager确认所有参与者都ready后,向所有参与者发送commit命令。 

假设有两个Connection, con1, con2, 大体的过程如下:
con1 = XAResouce1.getConnection...     
con2 = XAResouce2.getConnection...   

con1 do some thing.     
con2 do some thing.     
after they finish.     
 
pre1 = XAResouce1.prepare();     
pre2 = XAResouce2.prepare();     
 
if( both pre1 and pre2 are OK){     
XAResouce1 and 2 commit     
}else {     
XAResouce1 and 2 rollback     


11、分库分表:
https://blog.csdn.net/wdcl2468/article/details/102911160
(1)现在的数据量?5千万
select count(*) from midplatform_clearing_order_detail; #56600465
(2)分库分表的目的?
集群的读写分离,只能解决读的问题;
分库分表(sharding),解决写的问题,对写操作切分;
写的压力:
1、单服务器TPS,内存,IO都是有限的; ——分散到多个服务器
2、单个数据库处理能力有限;单库所在服务器上磁盘空间不足;单库上操作的IO瓶颈; ——分散成多个库
(3)什么情况适合分库分表?
一张表数据量达到 千万级别
(4)分库分表具体方案?
注释:分库分表,用到了 【分布式事务-XA】准从CAP原则;
垂直拆分:
1、垂直分表:一个表的不同字段,切分到多个表上(“大表拆小表”,基于列字段进行的);
2、垂直分库:不同业务功能的表,切分到不同服务器的不同库上(切分后,要放在多个服务器上);
水平拆分:
1、水平分表:
针对数据量巨大的单张表(比如订单表),按照某种规则(RANGE,HASH取模等),切分到多张表里面去。 但是这些表还是在同一个库中,所以库级别的数据库操作还是有IO瓶颈。不建议采用。
2、水平分库分表:
将单张表的数据切分到多个服务器上去,每个服务器具有相应的库与表,只是表中数据集合不同。 水平分库分表能够有效的缓解单机和单库的性能瓶颈和压力,突破IO、连接数、硬件资源等的瓶颈。


12、集群?
0)主从复制作用?
读写分离--使数据库能支撑更大的并发
数据热备--高可用;
1)主从复制方式?
一主一从
主主复制
一主多从—扩展系统读取的性能,因为读是在从库读取的;
多主一从—5.7开始支持
联级复制:多级复制架构只是在一主多从的基础上,再主库和各个从库之间增加了一个二级主库Master2,这个二级主库仅仅用来将一级主库推送给它的BInlog日志再推送给各个从库,以此来减轻一级主库的推送压力。
2)主从复制原理?
三步:
a. binlog 输出线程:每当有从库连接到主库的时候,主库都会创建一个线程然后发送 binlog内 容到从库。
在从库里,当复制开始的时候,从库就会创建两个线程进行处理:
b.从库 IO 线程:当 START SLAVE 语句在从库开始执行之后,从库创建一个 IO 线程,该线程连接到主库并请求主库发送 binlog 里面的更新记录到从库上。从库 IO 线程读取主库的 binlog 输出线程发送的更新并拷贝这些更新到本地文件,其中包括 relaylog 文件。
c.从库 SQL 线程:从库创建一个 SQL 线程,这个线程读取从库 IO 线程写到 relaylog 的更新事件并执行。
3)主从同步方式——异步与半同步(默认):
一主一从,一主多从情况下,Master 节点只要确认至少有一个 Slave 接受到了事务,即可向发起请求的客户端返回执行成功的操作。同时 Master 是不需要等待 Slave 成功执行完这个事务,Slave 节点接受到这个事务,并成功写入到本地 relay 日志中就算成功。
另外,在半同步复制时,如果主库的一个事务提交成功了,在推送到从库的过程当中,从库宕机了或网络故障,导致从库并没有接收到这个事务的Binlog,此时主库会等待一段时间(这个时间由rpl_semi_sync_master_timeout的毫秒数决定),如果这个时间过后还无法推送到从库,那 MySQL 会自动从半同步复制切换为异步复制,当从库恢复正常连接到主库后,主库又会自动切换回半同步复制。
半同步复制的“半”体现在,虽然主从库的Binlog是同步的,但主库不会等待从库执行完Relay-log后才返回,而是确认从库接收到Binlog,达到主从Binlog同步的目的后就返回了,所以从库的数据对于主库来说还是有延时的,这个延时就是从库执行Relay-log的时间。所以只能称为半同步。

4)读写分离?
理论:在MySQL和客户端之间有一个中间代理层proxy,客户端只连接proxy, 由proxy根据请求类型和上下文决定请求的分发路由。
实际:之家的请求分发路由实现——
JDBC > mwo 读写
JDBC > rso 读
LVS算法,rsio轮询机制分发请求;

5)针对读写分离,秒杀项目的处理?
由于主从本身有延迟,于是,在818的时候,秒杀项目 采取的方案是 ——顶层用redis,底层读与写都对接 主库,其实此时的数据库不是mysql了,而是TiDB(pnycap);


13、mysql项目配置?
  datasource:
    url: jdbc:mysql://autopay-mw0-3307-db.bj.autohome.com.cn:3307/redpacket?useUnicode=true&characterEncoding=utf-8
    username: redpacket_wr
    password: 3Wo_ls3WsDG3Yvo8
    driver-class-name: com.mysql.jdbc.Driver
    platform: mysql
    type: com.alibaba.druid.pool.DruidDataSource
    # 下面为连接池的补充设置,应用到上面所有数据源中
    # 初始化大小,最小,最大
    initialSize: 10
    minIdle: 10
    maxActive: 100
    # 配置获取连接等待超时的时间
    maxWait: 60000
    # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
    timeBetweenEvictionRunsMillis: 60000
    # 配置一个连接在池中最小生存的时间,单位是毫秒
    minEvictableIdleTimeMillis: 30000
    validationQuery: SELECT 1 FROM DUAL
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    # 打开PSCache,并且指定每个连接上PSCache的大小
    poolPreparedStatements: true
    maxPoolPreparedStatementPerConnectionSize: 20
    # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
    filters: stat,wall,slf4j
    # 通过connectProperties属性来打开mergeSql功能;慢SQL记录
    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
    # 合并多个DruidDataSource的监控数据
    #useGlobalDataSourceStat: true

数据库连接池?
https://blog.csdn.net/qq_32998153/article/details/79507324

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值