如何通过MySql实践关系型数据库应用开发?

摘要:多年开发实践中遇到的DB相关的话题研究和整理,不介绍DB的基本概念,也不过于深入DB原理,以满足日常应用、知其然知其所以然为准。
包含十几个子话题,含事务传播性、索引优化、拆分、FailOver等。
本文主要是对目前工作中使用到的DB相关知识点的总结,应用开发了解到以下深度基本足以应对日常需求,再深入下去更偏向于DB本身的理论、调优和运维实践。 不在本文重点关注讨论的内容(可能会提到一些): 具体的DQL、DML、DDL、DCL等语法 基础性的概念,如主键、索引、存储过程(即sql级的编程。注:阿里巴巴规范中禁止使用存储过程)等 联合查询,我个人不太喜欢在应用中写过于复杂的SQLsu,性能和后续维护容易出现问题 可能会用到的具体DB特性,如oracle的DATA GUARD 有一些属于基础知识或语法但是常用的信息,也会列一下,如join的用法。 一、基础 1.1 ACID DB的四大特性。 (错) 衡量事务的四个维度 (对) 原子性(Atomicity):事务操作中的多条SQL,要么全部成功要么全部失败,失败后回滚不对原有数据造成任何影响。 一致性(Consistency):事务开始前和结束后,数据库的完整性没有被破坏。如触发器、约束、级联回滚 隔离性(Isolation):多个事务支持并发读写。具体隔离级别见后文。 持久性(Durability):事务结束后,修改是永久的,不丢失。 如MySql: 原子性通过undo log保证 隔离性通过锁、MVCC近似保证 持久性通过undo/redo log和binlog保证 一致性通过以上三方面及应用层面保证 1.2 范式 这里展开讲比较复杂,实践中很少用到,一般满足1NF即可。 高一级必满足低一级。 1NF:每个属性都不可再分,即表的列是最原子的 2NF:在1NF基础上,消除非主属性对键的部分依赖。这里不解释非主属性和键的含义,可以简单认为是指不存在列A可以通过列B来获取,如“学生姓名-学号”这种y=f(x)的函数关系。 3NF:在2NF的基础之上,消除了非主属性对于码的传递函数依赖 BCNF:对于关系模式R,如果每一个函数依赖的决定因素都包含键,则R属于BCNF范式 有兴趣可以参考:范式通俗理解:1NF、2NF、3NF和BNCF 二、事务 事务的隔离级别 读现象 读现象是伴生于不同的隔离级别出现的。读现象的场景都是在多个事务并发执行的前提下可能出现的: 脏读 —— 一个事务读取了另一个未提交事务执行过程中的数据。此时另一个事务可能会由于提交失败而回滚。 不可重复读 —— 一个事务执行过程中多次查询同一条数据但返回了不同查询结果。这说明在事务执行过程中,数据被其他事务修改并提交了。 幻读 —— 事务1先行查询了某种数据,在修改或插入提交之前,事务2对此类数据进行了插入或删除并提交,导致了事务1对预期结果的数量变化。 隔离级别 未提交读(read uncommited):允许另外一个事务可以看到这个事务未提交的数据。 提交读(read commited):保证一个事务提交后才能被另外一个事务读取,而不能读取未提交的数据。 可重复读(repeatable read):保持读锁和写锁一直到事务提交,但不提供范围锁,因此不能避免幻读。 可序列化(serializable):代价最高但最可靠的事务隔离级别,事务被处理为顺序执行。 隔离级别与读现象 不同的隔离级别可以防止读现象。 隔离级别 脏读 不可重复读 幻影读 未提交读 可能发生 可能发生 可能发生 提交读 - 可能发生 可能发生 可重复读 - - 可能发生 可序列化 - - - 注:为什么提交读不能避免不可重复读?假设A事务需要读取两次变量a,第一次读取时a=10,执行过程中a被事务B修改变成了20,那么A第二次读时a与第一次的结果不同。 查看DB的隔离级别 // 查看当前会话 select @@tx_isolation; // 查看当前系统 select @@global.tx_isolation; MySql 5.7.14-ALISQL版默认是提交读。 2.2 事务传播性(Spring) 在多个含有事务方法的相互调用时,事务如何在这些方法间传播。 本节使用Spring事务注解的枚举,而不是全称(如PROPAGATION_REQUIRED)。 这里只支持单个库的事务。跨库事务请参考分布式事务章节。 spring支持7种事务传播行为: REQUIRED:如果当前没有事务,就新建一个事务;否则加入到这个已有事务中,这是最常见的选择。 SUPPORTS:支持当前事务,如果没有当前事务,就以非事务方法执行。 MANDATORY:使用当前事务,如果没有当前事务,就抛出异常。 REQUIRED_NEW:新建事务,如果当前存在事务,把当前事务挂起。
阅读全文