数据库事务:
什么是ACID:
什么是脏读:
是一个事务在处理过程中读取了另一个事务未提交的数据,当一个事务正在访问数据并且进行了修改,但是还没提交事务,这时另外一个事务也访问了这个数据,然后使用了这个数据,因为这个数据的修改还没提交到数据库,所以另外一个事务读取的数据就是"脏数据"
什么是丢失修改:
是指一个事务读取一个数据时,另外一个数据也访问了改数据,那么在第一个事务修改了这个数据之后,第二个事务也修改了这个数据。这样第一个事务内的修改结果就被丢失,这种情况被称为修改丢失
什么是不可重复读:
在一个事务内多次读取同一数据,在这个事务还没结束时,另外一个事务也访问了这个数据并对这个数据进行了修改,那么就可能造成第一个事务多次读取的数据不一致
什么是幻读:
是指同一个事务内多次查询返回结果集总数不一样(比如增加了或者减少了行记录)
不可重复读 和 幻读的区别:
事务隔离级别:
事务隔离级别 | 脏读 | 不可重复读(被修改) | 幻读(删减) |
读未提交( read - uncommitted) | 是 | 是 | 是 |
不可重复读(read-committed) | 否 | 是 | 是 |
可重复读(repeatable-read) | 否 | 否 | 是 |
串行化(serializable) | 否 | 否 | 否 |
InnoDB 存储引擎默认的事务隔离级别是可重复读
如何选择事务隔离级别:
隔离级别越低,事务请求的锁越少相应性能也就越高,如果没有特殊要求或发生错误,使用默认的隔离级别即可,如果系统中有高频读写并且对一致性要求高那么就需要比较高的事务隔离级别甚至串行化
一致性非锁定读和非锁定读:
锁定读: 使用读写锁
锁机制: 解决了多个事务同时更新数据,此时必须要有一个加锁的机制
非锁定读: 使用 mvcc 多版本控制实现
MVCC 内部细节:
Multi-Version Concurrency Control 多版本并发控制, MVCC 是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问
InnoDB 是一个多版本的存储引擎。它保存有关已更改行的旧版本的信息,以支持并发和回滚等事务特性。这些信息存储在一个称为回滚的数据结构中的系统表空间 或 undo 表空间中。 InnoDB 使用回滚段中的信息来执行事务回滚所需要的撤销消息。它还使用这些信息构建行的早期版本,以实现一致性的读取。
MVCC 的实现依赖于: 隐藏字段、 Read View、undo log
隐藏字段:
Read View:
Undo log:
MySQL 事务一致性,原子性是如何实现的:
MySQL 事务的持久性是如何实现:
使用 Redo log 保证了事务的持久性。当事务提交时,必须先将事务的所有日志写入日志文件进行持久化,就是我们常说的 WAL(write ahead log)机制,如果出现断电重启便可以从 redo log 中恢复,如果 redo log 写入失败那么也就意味着修改失败整个事务也就直接回滚了
表级锁和行级锁:
共享锁(读锁)或 S锁:其他事务可以继续加共享锁,但不能加排它锁
排它锁(写锁/独占锁)或 X 锁: 在进行写操作之前要申请并获得,其他事务不能再获得任何锁
意向锁:
当前读和快照读:
当前读:在锁定读(使用锁隔离事务) 的时候读到的最新版本的数据
快照读: 可重复读(repeatable-read) 下 MVCC 生效读取的数据的快照,并不是最新版本的数据(未提交事务的数据)
XA 协议:
AP(Application Program) 应用程序:定义事务边界(定义事务开始和结束)并访问事务边界内的资源
RM(Resource Manger) 资源管理器: 管理共享资源并提供外部访问接口。共外部程序来访问数据库等共享资源。此外,RM 还具有事务的回滚能力。
TM(Transaction Manger) 事务管理器: TM 是分布式事务的协调者,TM与每个RM进行通信,负责管理全局事务,分配事务唯一标识,监控事务的执行进度,并负责事务的提交、回滚、失败恢复等。
这些接口 一定要按顺序执行,比如 xa_start 接口一定要在 xa_end 之前。此外,这里千万要注意的事务管理器只是标记事务分支并不执行事务,事务操作最终由应用程序通知资源管理完成的。
XA 的接口:
MySQL xa 事务:
SHOW VARIABLES LIKE '%innodb_support_xa%'; --5.7
-- 8.0 默认开启无法关闭
-- xa 事务语法
XA START '自定义事务ID';
-- SQL 语句...
XA END '自定义事务ID';
XA PREPARE '自定义事务ID'; -- 执行成功后,事务信息将被持久化。即使会话中止甚至应用服务宕机,只要我们['自定义事务ID'] 记录下来,后续仍然可以使用它对事务进行 rollback 或者 commit
XA COMMIT\ROLLBACK '自定义事务ID';
select for update:
select 本身是一个查询语句,查询语句是不会产生冲突的一种行为,一般情况下没有锁的, 用 select for update 会让 select 语句产生一个排它锁(X), 这个锁 和 update 的效果一样,会使两个事务无法同时更新一条记录。
解决死锁问题: