文章目录
- 视图
- 事务
- 事物的四大特性(ACID)
- 事务的开启和结束
- 事物隔离级别
- 现象
- 脏读
- 不可重复度
- 幻读
- 隔离级别
- 读未提交(READ UNCOMMITTED)
- 读提交 (READ COMMITTED)
- 可重复读 (REPECTABLE READ)
- 串行化 (SERIALIZABLE)
- 查看与设置事务隔离级别
- 重复读的幻读问题
- 快照读解决幻读
- 当前读解决幻读
- 出现幻读的两种情况
- 幻读总结
视图
- sql 语句很复杂,又要在很多地方写,改的时候太麻烦了,这时候可以用视图解决
- 视图可以隐藏表的字段名。
根据视图来查的,所以如果起了别名别名就是那个试图的字段名
只能将select语句创建为视图
对视图增删改(DML:insert delete update)会影响到原表数据。
创建视图
create [or replace] view v_emp as select e.ename,d.dname from emp e join dept d on e.deptno = d.deptno;
修改视图
alter view v_emp as select e.ename,d.dname,d.deptno from emp e join dept d on e.deptno = d.deptno;
删除视图
drop view if exists v_emp;
事务
事物就是一个最小的工作单元,在数据库中,事物表示一件完整的事
例如:一个业务的完成可能需要多条DML语句共同配合才能完成,例如转账业务,需要执行两条DML语句,先更新张三账户的余额,再更新李四账户的余额,为了保证转账业务不出现问题,就必须保证要么同时成功,要么同时失败,怎么保证同时成功或者同时失败呢?就需要使用事务机制。
事务只针对DML语句有效:因为只有这三个语句是改变表中数据的。
- insert
- delete
- update
事物的四大特性(ACID)
- 原子性(Atomicity):是指事务包含的所有操作要么全部成功,要么同时失败。
- 一致性(Consistency):是指事务开始前,和事务完成后,数据应该是一致的。例如张三和李四的钱加起来是5000,中间不管进行过多少次的转账操作(update),总量5000是不会变的。这就是事务的一致性。
- 隔离性(Isolation):隔离性是当多个⽤户并发访问数据库时,⽐如操作同⼀张表时,数据库为每⼀个⽤户开启的事务,不能被其他事务的操作所⼲扰,多个并发事务之间要相互隔离。
- 持久性(Durability):一旦事务成功提交,其对数据库数据的更改将被永久保存下来,不会因为系统故障、断电等问题而丢失这些更改
事务的开启和结束
MySQL 事物如果不执行:strat[begin] trancaction ,就一条语句提交一次事物。我们实际的业务是一堆 DML 构成事物,所以需要手动开启事物
回滚:rollback
提交:commit;
只要手动开启事物:执行回滚或者提交就是一次结束操作。所以要想好再提交,提交之后就回滚不了了
事物隔离级别
- 隔离级别从低到高:读未提交 < 读提交 < 读可重复读 < 串行化
- 现象的严重程度从低到高:幻读 < 不可重复读 < 脏读
mysql数据库默认是 读提交。Oracle 默认是 可重复读
存在脏读的话,就一定存在不可重复读和幻读问题。
现象
脏读
一个事务读取了,另一个事务未提交的数据。就是读取到了另一个事务中的脏数据。在这种情况下,如果事物回滚或者修改了这些数据,那么读取这些脏数据的事务所处理的数据就是不准确的。
不可重复度
一个事务内,多次读取同一个数据行。得到的结果可能不一样。这是由于其他事务对数据进行了修改操作。导致数据的不一致性
幻读
事务执行过程中,前后两次相同的查询条件得到的结果不一,可能会变多或变少
隔离级别
读未提交(READ UNCOMMITTED)
A事务与B事务,A事务可以读取到B事务未提交的数据。这是最低的隔离级别。几乎两个事务之间没有隔离。这种隔离级别是一种理论层面的,在实际的数据库产品中,没有从这个级别起步的。
读提交 (READ COMMITTED)
A事务与B事务,A事务可以读取到B事务提交之后的数据。Oracle数据库默认的就是这种隔离级别。
可重复读 (REPECTABLE READ)
A事务和B事务,A事务开启后,读取了某一条记录,然后B事务对这条记录进行修改并提交,A事务读取到的还是修改前的数据。这种隔离级别称为可重复读。MySQL数据库默认就是这种隔离级别。
串行化 (SERIALIZABLE)
这种隔离级别最高,避免了所有的问题,缺点是效率低,因为这种隔离级别会导致事务排队处理,不支持并发。
查看与设置事务隔离级别
查看当前事务隔离级别:
select @@transaction_isolation -查看当前会话隔离级别
select @@gobal.transaction_isolation -查看全局的隔离级别
设置事务隔离级别
会话级:set session transaction isolation level 事务隔离级别
全局级:set global transaction isolation level 事务隔离级别
事务隔离级别:
1.read uncommitted
2.read committed
3.repeatable read
4.serializable
重复读的幻读问题
可重复读,能很大程度上避免了幻读问题,但是并不能完全解决。
快照读解决幻读
普通的 select 语句都是采用快照读。(类似就是把那个时间段的表数据,保留下来。)
原理:
由 MVCC(多版本并发控制) 实现,实现的方式是开始事务后会创建一个 Read View 对象,后续查询语句利用整个 Read View,通过这个 Read View 就可以在 undo log 版本链找到快照查询执行时候的那个版本的数据。所以事务过程中每次快照查询数据都是一样的,即使中途有其他事务插入了新记录,是查询不出来这条数据的。避免了幻读
当前读解决幻读
当前读包括:update、delete、insert、select…for update。就是 DML 加上 for update。单独执行 DML 语句也会隐式执行当前读,
原理:
select…for update加的锁叫做:next-key lock。我们可以称其为:间隙锁 + 记录锁。间隙锁用来保证在锁定的范围内不允许insert操作。记录锁用来保证在锁定的范围内不允许delete和update操作。提交后锁失效
出现幻读的两种情况
在同一个事务处理过程中,如果前后两次都采用快照读,或者都采用当前读,则不会出现幻读问题。如果第一次使用快照读,后面使用了当前读,则会出现幻读问题。
第一种产生幻读的场景
A事务与B事务。在A事务中第一次查询使用快照读,B事务插入数据。然后在A事务中第二次查询使用当前读。则会产生幻读现象。
第二种产生幻读的场景
事务A与事务B,在事务A中第一次查询使用快照读,在事务B中插入一条数据,然后在事务A中更新事务B插入的那条记录,最后在事务A中再次使用快照读。则会发生幻读现象。
幻读总结
MySQL 可重复读隔离级别并没有彻底解决幻读,只是很大程度上避免了幻读现象的发生。
要避免这类特殊场景下发生幻读的现象的话,就是尽量在开启事务之后,马上执行 select … for update 这类当前读的语句,因为它会对记录加 next-key lock,把数据锁住。从而避免其他事务插入一条新记录。