数据库原理
-
物理层:操作系统之上,对磁盘文件系统操作的层,是最底层
-
数据库组织架构核心:
- 数据库系统多进程模式:
在多进程模式中,数据库系统会为每一个客户端进程开启一个DBMS 核心进程,两个进程之间通过pipe,socket等多种方式进行通信,一般也称为会话(session)。
- DBMS 多线程模式
- 数据库事务
-
引入事务的主要目的:事务会把数据库从一种一致状态转换为另一种一致状态,在数据库提交工作时,可以确保所有修改都保存了,要么所有修改都未保存
-
事务的ACID:有些数据库的事务并不严格遵循ACID
- 原子性(Atomicity):整个数据库事务是不可分割的工作单位。只有事务中的所有操作都执行成功,才算整个事务成功。事务中任何一个sql执行失败,已经执行成功的sql语句也必须撤销,数据库状态应该退回到执行事务前的状态
- 一致性(consistency):一致性指事务将数据库从一种状态转变为下一种一致状态。在事务开始之前和事务结束以后,数据库的完整性约束没有被破坏。或指系统从一个正确的状态转到另一个正确的状态,具体参考博客
- 隔离性(isolation):隔离性还有其他的称呼,如并发控制,可串行化,锁等。事务的隔离性要求读写事务的对象对其他事务的操作对象能相互分离,即该事务提交前对其他事务都不可见,通常这使用锁来实现。
- 持久性(durability):事务一旦提交,其结果就是永久性的。如当系统发生崩溃,恢复后事务提交的数据也不会丢失。但事务的持久性不是保证系统的高可用性,二是高可靠性,高可用性需要一些系统共同配合来完成
-
事务的分类:
- 扁平事务(Flat Transactions):扁平事务是最简单的一种,也是实际使用中最频繁的一种。在扁平事务中,所有操作都处于同一层次,其由begin work开始,由commit work 或 rollback work 结束,其间的操作都是原子的,要么都执行,要么都回滚。
-
带保存点的扁平事务(Flat Transactions With Savepoint):可以设置回滚的保存点
-
链事务(Chained Transactions)
-
嵌套事务(Nested Transactions)
-
分布式事务(Distributed Transactions)
-
事务的实现
事务的隔离性是通过锁来实现,原子性和持久性由redo log实现,一致性由undo log实现
- 事务控制语句
- mysql命令行的默认设置下,事务是自动提交的,即执行sql语句马上执行commit 操作,可以通过set autocommit = 0;来禁用当前会话的自动提交
- start transaction 和 begin 命令都可以显示的开启一个事务,但在存储过程中只能使用start transaction,因为存储过程中begin 命令被识别为begin…end。在用start transaction 或 begin 命令显示开启事务后,在默认情况下(即completion_type 等于 0)mysql 会自动执行set autocommit = 0命令,并在commit 或 rollback 结束一个事务后,执行set autocommit = 1。 另外,对于不同语言的api,自动提交是不同的,如mysql Python api 会自动执行set autocommit = 0,以禁用自动提交
- commit [work]:提交
- rollback [work]:回滚
- savepoint 保存点名称:设置一个保存点,一个事务中可以有多个savepoint
- release savepoint 保存点名称:删除一个保存点
- rollback to [savepoint] 保存点名称:回滚到指定的保存点
- set transaction:设置事务的隔离级别,InnoDB存储引擎的隔离级别有:
- read uncommitted
- read committed
- repeatable read
- serializable
- 其他注意事项
- 长事务,即执行时间比较长的事务,可以分解为若干小事务
- mysql 锁
-
对某一资源正在进行写操作时,是不允许对这一资源再进行读或写操作的;对某一资源进行读操作时,可以再对这一资源进行读操作,但不能再对这一资源进行写操作
-
共享锁(shared lock)即读锁;排他锁(exclusive)即写锁
-
锁粒度:在给定的资源上,锁定的数据量越小,锁定的数据片越精确,则系统的并发程度越高,即性能越高,只要不发生冲突即可;但加锁也需要消耗资源,锁的各种操作,包括获得锁,检查锁是否解除,释放锁都会增加系统的开销。所以要在锁开销与并发程度之间取舍
-
锁要面对的问题:
- 脏读:事务A读取了事务B更新的数据,然后事务B回滚了,那么事务A读到的就是脏数据
- 不可重复读:事务A多次读取同一数据,事务B在事务A读取数据的过程中,更新这一数据并提交,导致事务A两次读到的数据不同
- 幻读:事务A查询一张表的记录数,第一次查询为a条,期间事务B插入或删除一条记录,则事务A第二次查询到的记录数则不为a条
- 丢失更新:事务A与事务B更新同一资源,先更新的结果会被后更新的结果覆盖
不可重复读与幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除,解决不可重复读锁定满足条件的行即可,解决幻读则需要锁定表
- 其他注意事项
-
mysql5.7 配置文件为 my.ini
-
事务隔离级别设置的影响范围:
-
SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE}
-
不带[SESSION | GLOBAL] 时,表示为当前会话的下一个事务设置隔离级别(仅仅是下一个,第二个就不起作用了)
-
带[SESSION]时,表示为当前会话的所有事务设置隔离级别
-
带[GLOBAL]时,表示设置全局隔离级别,对设置之后新连接的会话设置默认隔离级别,不会对已经存在的会话有影响,全局隔离级别的设置不会改变配置文件中默认的全局设置,服务器重启后按配置文件重置全局隔离级别
-
SELECT @@global.tx_isolation; 查询全局隔离级别设置
-
SELECT @@session.tx_isolation; SELECT @@tx_isolation; 以上两种方式都是查询会话隔离级别设置
-