- 1 数据库概述
- 1.1 DBMS 简史
- 1.2 数据库理论
- 1.3 事务 Transaction
- 1.4 SQL
- 1.5 数据库接口
- 本章参考
- 2 Relational 关系数据库
- 2.1 关系理论
- 2.2 Oracle
- 2.5 Microsoft SQL Server
- 2.6 DB2
- RDBS 比较
- 本章参考
- 3 NoSQL 非关系数据库
- 3.1 NoSQL 分类
- 3.2 键值 key-value 数据库
- 3.3 列存储数据库
- 3.4 图形数据库
- 本章参考
- 4 NewSQL
- 4.1 NewSQL 分类
- 4.2 分布式数据库 Distributed
- 本章参考
- 5 时序数据库 TSDB
- 5.1 简介
- 5.2 时序数据库比较
- 本章参考
- 6 SQL 引擎
- 6.1 SQL 引擎分类
- 6.2 SQL On Hadoop
- 本章参考
- 7 其它数据库
- 7.1 内存数据库 In-memory
- 7.2 嵌入式数据库 Embed
- 7.3 搜索引擎
- 本章参考
- 8 各种数据库分析比较
- 8.1 数据库排行 db-engines
- 8.2 数据库技术选型
- 8.3 DB 性能比较
- 8.4 国产数据库产品列表
- 8.5 DB 常用 SQL 比较
- 本章参考
- 9 SQL 调优
- 9.1 SQL JOIN
- 9.2 SQL 执行流程
- 10 数据库大型应用实例
- 10.1 负载均衡技术
- 10.2 数据库的高可用 HA
- 10.3 数据库的读写分离
- 10.4 数据库拆分(分布式)
- 10.5 跨库查询
- 本章参考
- 参考资料
- 附录
1.3 事务 Transaction
在关系数据库中,一个事务可以是一条 SQL 语句,一组 SQL 语句或整个程序。事务由事务开始( begin transaction ) 和事务结束( end transaction ) 之间执行的全体操作组成。
事务是恢复和并发控制的基本单位。
事务使用 ACID 模型,具有 4 个属性:原子性、一致性、隔离性、持久性。
1.3.1 并发问题和隔离级别
并发事务常见问题:丢失更新、脏读、不可重读和幻读。
表格 2 并发事务引起的问题描述
问题 | 描述 | 结果 | 解决 |
---|---|---|---|
丢失更新 | A 读—B 读—A 改—B 改 | A 更改丢失 | |
Dirty Read 脏读 | A 改—B 读—A 回滚 一个事务处理过程里读取了另一个未提交的事务中的数据。 | B 读无效值 | 一般要解决 |
Nonrepeatable Read 不可重读 | A 读—B 改—A 读 | A 读不一致 | REPEATABLE READ SNAPSHOT |
Phantom Read 幻读 | A 读—B 增删—A 读 事务查询时没有增加范围锁。 | A 读或多或少 | SERIALIZABLE |
备注:事务提交过程中,别的连接是可以查询操作的,但数据是旧的。
隔离级别用于决定如何控制并发用户读写数据的操作。例如读操作默认使用共享锁,写操作需要使用排它锁。
SQL 92 标准定义了 4 种隔离级别(从高到低)分别是:可序列化(Serializable)、可重复读(Repeatable reads)、提交读(Read committed)、未提交读(Read uncommitted)。详见下表。
表格 3 SQL 隔离级别和对应的并发问题对照表
Isolation Level 隔离级别 | Dirty Read 脏读 | Nonrepeatable Read 不可重读 | Phantom Read 幻读 | Serialization Anomaly 序列化异常 |
---|---|---|---|---|
Read uncommitted 读未提交 | Possible | Possible | Possible | Possible |
Read committed 读已提交 | Not possible | Possible | Possible | Possible |
Repeatable read 可重复读 | Not possible | Not possible | Not possible in TiDB | Possible |
Serializable 串行化 | Not possible | Not possible | Not possible | Not possible |
表格 4 隔离级别原理
隔离级别 | 简述 | 原理 | 现象(并发问题) |
---|---|---|---|
Read uncommitted 读未提交 | 最低的隔离级别。,一个事务可以读到另外一个事务未提交的数据。 | 事务在读数据的时候并未对数据加锁。事务在修改数据的时候只对数据增加 行级 共享锁 。 | 都有。任何情况都无法保证。 |
Read committed 读已提交 | 在一个事务修改数据过程中,如果事务还没提交,其他事务不能读该数据。 | 事务对当前被读取的数据加行级共享锁(当读到时才加锁),一旦读完该行,立即释放该行级共享锁;事务在更新某数据的瞬间,必须先对其加行级排他锁,直到事务结束才释放。 | 只解决了脏读。 |
Repeatable read 可重复读 | 可以解决不可重复读的问题。 | 事务在读取某数据的瞬间,必须先对其加行级共享锁,直到事务结束才释放; 事务在更新某数据的瞬间,必须先对其加行级排他锁,直到事务结束才释放。 | 可避免脏读、不可重复读的发生。 |
Serializable 串行化 | 最高的隔离级别。 | 事务在读取数据时,必须先对其加 表级共享锁 ,直到事务结束才释放; 事务在更新数据时,必须先对其加 表级排他锁 ,直到事务结束才释放。 | 解决所有。可避免脏读、不可重复读、幻读的发生。 |
备注:1. 锁机制~一般读操作使用共享锁,写操作使用排它锁。另外还要看锁的粒度是行级还是表级。
- 序列化事务会产生以下效果:
无法读取其它事务已修改但未提交的记录。
在当前事务完成之前,其它事务不能修改目前事务已读取的记录。
在当前事务完成之前,其它事务所插入的新记录,其索引键值不能在当前事务的任何语句所读取的索引键范围中。
- 四种事务隔离级别从隔离程度上越来越高,但同时在并发性上也就越来越低。
1.3.2 数据库事务
表格 5 各 RDBMS 的事务处理机制
DBMS | 事务隔离级别 | 事务 SQL |
---|---|---|
MySQL | 4 种分别是: ① Serializable ② Repeatable read(默认级别)。 ③ Read committed ④ Read uncommitted | * 查看隔离级别 select **@@tx_isolation**; * 查询正在执行的事务 : SELECT * FROM information_schema.INNODB_TRX * 查看正在锁、等待锁 INFORMATION_SCHEMA.INNODB_LOCKS、 INFORMATION_SCHEMA.INNODB_LOCK_WAITS; |
Oracle | 2 种:Serializable 和 Read committed (默认级别) | |
SQL Server | 6 种:READ UNCOMMITED、READ COMMITED、REPEATABLE READ、SERIALIZEABLE 和 SNAPSHOT(快照)、READ COMMITED SNAPSHOT(已经提交读隔离)。 | |
Postgre | ||
Redis | 单个操作是原子性的。多个操作也支持事务,即原子性,通过 MULTI 和 EXEC 指令包起来。 | multi exec watch unwatch discard |
备注:1. SELECT 不需提交事务。DML 语言,比如 update,delete,insert 等修改表中数据的需要 commit; DDL 语言,比如 create,drop 等改变表结构的,就不需要写 commit(因为内部隐藏了 commit)
- 两阶段提交(2PC, Two-phase Commit)使用 XA 事务,是两阶段提交协议。MySQL 从 5.5 版本开始支持,SQL Server 2005 开始支持,Oracle 7 开始支持。
XA 协议分为以下两个阶段:
第一阶段:事务协调器要求每个涉及到事务的数据库预提交(precommit) 此操作,并反映是否可以提交。
第二阶段:事务协调器要求每个数据库提交数据。
1.3.3 分布式事务
分布式系统主要参照 CAP 和 BASE 理论。
分布式事务就是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。简单的说,就是一次大的操作 由不同的小操作组成,这些小的操作分布在不同的服务器上,且属于不同的应用,分布式事务需要保证这些小操作要么全部成功,要么全部失败。本质上来说,分布 式事务就是为了保证不同数据库的数据一致性。
表格 6 分布式事务的典型方案
简介 | 优点 | 缺点 | |
---|---|---|---|
两阶段提交(2PC) | 强一致性。牺牲了一部分可用性来换取的一致性。 | 尽量保证了数据的强一致,适合对数据强一致要求很高的关键领域。(其实也不能 100%保证强一致) | 实现复杂,牺牲了可用性,对性能影响较大,不适合高并发高性能场景,如果分布式系统跨接口调用,目前 .NET 界还没有实现方案。 |
补偿事务(TCC) | 即三阶段提交(3PC)。针对每个操作,都要注册一个与其对应的确认和补偿(撤销)操作。 | 跟 2PC 比起来,实现以及流程相对简单了一些,但数据的一致性比 2PC 也要差一些 | 在 2,3 步中都有可能失败。TCC 属于应用层的一种补偿方式,所以需要程序员在实现的时候多写很多补偿的代码,在一些场景中,一些业务流程可能用 TCC 不太好定义及处理。 |
本地消息表(异步确保) | 将分布式事务拆分成本地事务进行处理,来源于 eBay。 | 避免了分布式事务,实现了最终一致性。 | 消息表会耦合到业务系统中,如果没有封装好的解决方案,会有很多杂活需要处理。 |
MQ 事务消息 | 实现了最终一致性,不需要依赖本地数据库事务。 | 实现难度大,主流 MQ 不支持,没有.NET 客户端,RocketMQ 事务消息部分代码也未开源。 | |
Saga 事务模型 | 又名长时间运行事务(Long-running-transaction) | ||
Paxos 协议 | 分布式系统共识性的第一个实现方案。 |
备注:2PC 是强一致性,其它方案都是最终一致性。
1. 两阶段提交(2PC)
两阶段提交这种解决方案属于牺牲了一部分可用性来换取的一致性。
优点: 尽量保证了数据的强一致,适合对数据强一致要求很高的关键领域。(其实也不能 100%保证强一致)
缺点: 实现复杂,牺牲了可用性,对性能影响较大,不适合高并发高性能场景,如果分布式系统跨接口调用,目前 .NET 界还没有实现方案。
2. 被偿事务(TCC)
核心思想是:针对每个操作,都要注册一个与其对应的确认和补偿(撤销)操作。它分为三个阶段:
Try 阶段主要是对业务系统做检测及资源预留
Confirm 阶段主要是对业务系统做确认提交,Try 阶段执行成功并开始执行 Confirm 阶段时,默认 Confirm 阶段是不会出错的。即:只要 Try 成功,Confirm 一定成功。
Cancel 阶段主要是在业务执行错误,需要回滚的状态下执行的业务取消,预留资源释放。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论