事务具有 ACID(Atomicity、 Consistency、 Isolation、 Durability, 即原子性、 一致性、 隔离性、 持久性)
1.隔离性
当数据库上有多个事务同时执行的时候, 就可能出现脏读(dirtyread) 、 不可重复读(non-
repeatable read) 、 幻读(phantom read) 的问题, 为了解决这些问题, 就有了“隔离级别”的概
念
2.SQL标准的事务隔离级别包括:
读未提交(read uncommitted) 、读提交(read committed) 、 可重复读(repeatable read) 和串行化(serializable ) 。
- 读未提交:一个事务还没提交时, 它做的变更就能被别的事务看到。
- 读提交: 一个事务提交之后, 它做的变更才会被其他事务看到。
- 可重复读: 一个事务执行过程中看到的数据, 总是跟这个事务在启动时看到的数据是一致的。 当然在可重复读隔离级别下, 未提交变更对其他事务也是不可见的。
- 串行化: 顾名思义是对于同一行记录, “写”会加“写锁”, “读”会加“读锁”。 当出现读写锁冲突
的时候, 后访问的事务必须等前一个事务执行完成, 才能继续执行
3.事务隔离的实现
在MySQL中, 实际上每条记录在更新的时候都会同时记录一条回滚操作。 记录上的最新值, 通过回滚操作, 都可以得到前一个状态的值。
假设一个值从1被按顺序改成了2、 3、 4, 在回滚日志里面就会有类似下面的记录 ,这就是数据库的多版本并发控制(MVCC) 。 对于read-view A, 要得到1, 就必须将当前值依次执行图中所有的回滚操作得到
回滚日志总不能一直保留吧, 什么时候删除呢?
答案是, 在不需要的时候才删除。也就是说, 系统会判断, 当没有事务再需要用到这些回滚日志时, 回滚日志会被删除。
什么时候才不需要了呢?
就是当系统里没有比这个回滚日志更早的read-view的时候。
4. 什么时候才不需要了呢? 就是当系统里没有比这个回滚日志更早的read-view的时候。
长事务意味着系统里面会存在很老的事务视图。 由于这些事务随时可能访问数据库里面的任何数据, 所以这个事务提交之前, 数据库里面它可能用到的回滚记录都必须保留, 这就会导致大量占用存储空间
5. 事务的启动方式
- 显式启动事务语句, begin 或 start transaction。 配套的提交语句是commit, 回滚语句是
rollback。 - set autocommit=0, 这个命令会将这个线程的自动提交关掉。 意味着如果你只执行一个
select语句, 这个事务就启动了, 而且并不会自动提交。 这个事务持续存在直到你主动执行
commit 或 rollback 语句, 或者断开连接。
6.可重复读隔离级别
可重复读隔离级别, 事务T启动的时候会创建一个视图read-view, 之后事务T执行期间, 即使有其他事务修改了数据, 事务T看到的仍然跟在启动时看到的一样
在MySQL里, 有两个“视图”的概念
- 一个是view。 它是一个用查询语句定义的虚拟表, 在调用的时候执行查询语句并生成结果。
创建视图的语法是create view …, 而它的查询方法与表一样 - 另一个是InnoDB在实现MVCC时用到的一致性读视图, 即consistent read view, 用于支持 RC(Read Committed, 读提交) 和RR(Repeatable Read, 可重复读) 隔离级别的实现
7 “快照”在MVCC里是怎么工作的
InnoDB里面每个事务有一个唯一的事务ID, 叫作transaction id。 它是在事务开始的时候向InnoDB的事务系统申请的, 是按申请顺序严格递增的 而每行数据也都是有多个版本的。 每次事务更新数据的时候, 都会生成一个新的数据版本, 并且把transaction id赋值给这个数据版本的事务ID, 记为row trx_id。 同时, 旧的数据版本要保留,并且在新的数据版本中, 能够有信息可以直接拿到它。 也就是说, 数据表中的一行记录, 其实可能有多个版本(row), 每个版本有自己的row trx_id
8 语句更新会生成undo log(回滚日志)
9 一个数据版本, 对于一个事务视图来说, 除了自己的更新总是可见以外, 有三种情况
- 版本未提交, 不可见
- 版本已提交, 但是是在视图创建后提交的, 不可见
- 版本已提交, 而且是在视图创建前提交的, 可见
10 更新逻辑
更新数据都是先读后写的, 而这个读, 只能读当前的值, 称为“当前读”(current read) 。 除了update语句外, select语句如果加锁, 也是当前读。
11 事务的可重复读的能力是怎么实现的?
可重复读的核心就是一致性读(consistent read) ; 而事务更新数据的时候, 只能用当前读。 如果当前的记录的行锁被其他事务占用的话, 就需要进入锁等待
12 读提交的逻辑和可重复读的逻辑类最主要的区别 ?
- 在可重复读隔离级别下, 只需要在事务开始的时候创建一致性视图, 之后事务里的其他查询
都共用这个一致性视图 - 在读提交隔离级别下, 每一个语句执行前都会重新算出一个新的视图。
13 怎么删除表的前10000行
- 直接执行delete from T limit 10000 ( 在20个连接中同时执行delete from Tlimit 500) )
- 在一个连接中循环执行20次 delete from Tlimit 500。 (最优方案)
- 在20个连接中同时执行delete from Tlimit 500) ( 人为造成锁冲突 )
14 幻读是什么, 幻读有什么问题 ?
幻读指的是一个事务在前后两次查询同一个范围的时候, 后一次查询看到了前一次查询没有看到的行。 在可重复读隔离级别下, 普通的查询是快照读, 是不会看到别的事务插入的数据的。 因此,幻读在“当前读”下才会出现。
15 mysqldump是做什么的?为什么要把备份线程设置成可重复读呢?
1)mysqldump是用来备份工具来的,必须引擎支持事务才使用.如果不支持事务只能用FTwRL.
2)保证数据一致性,如果是读已提交的话数据经常变,会导致结果不一致