一、事务特性
 
 原子性:强调事务的不可分割
 一致性:强调的是事务的执行的前后,数据的完整性要保持一致
 隔离性:一个事务的执行不应该受到其他事务的干扰
 持久性:事务一旦结束(提交/回滚)数据就持久保持到了数据库
 
 二、如果不考虑隔离性,会引发一些安全性问题
 
                                                读问题
 脏读:一个事务读到另一个事务还没有提交的数据
 不可重复读:一个事务读到了另一个事务已经提交的update数据,导致在当前的事务中多次查询数据不一致
 虚读/幻读:一个事务读到另一个事务已经insert数据,导致当前事务中多次查询结果不一致
 
                                              写问题
 引发两类丢失更新
 
 
 
三、解决引发的读问题  
 
                                  设置事务的隔离级别
 read uncommitted :未提交读。脏读,不可重复读,虚读都可能发生
 read committed :已提交读。避免脏读,不可重复读和虚度有可能发生
 repeatable read :可重复读。避免脏读和不可重复读,虚读可能发生
 serializable :串行化的。避免脏读,不可重复读,虚读的发生
 
 
 select @@tx_isolation; 查看隔离级别
 set session transaction isolation level 级别; 设置隔离级别
 
 
 四、演示读问题
 
                                                                                              演示脏读
 1.分别开启两个dos窗口 A.B
 2.先查看两个窗口的隔离级别 select @@tx_isolation;
 3.设置A窗口的隔离级别为未提交读 
 
 
 set session transaction isolation level read uncommitted;
 
 
 
 
4.分别在两个窗口开启事务
 
 
  start transaction;
 
 
5.分别开启两个dos窗口 A.B
 
 
 update account set money = money - 1000 where name = '张森';
 update account set money = money + 1000 where name = '凤姐';
 
 
6.在A窗口查询数据
 
 
 select * from account; -- A事务读到了B事务还没有提交的数据;
 
 
 
 
                                                                     演示避免脏读,演示不可重复读发送
 1.分别开两个窗口,A.B
 2.设置A窗口的隔离级别:read committed 
 
 
 set session transaction isolation level read committed;
 
 
3.分别在两个窗口开启事务 start transaction;
 
 4.在B窗口完成转账
 
 
 update account set money = money - 1000 where name = '张森';
 update account set money = money + 1000 where name = '凤姐';
 
 
5.在A窗口进行查询 
 
 
 select * from account; -- 避免脏读
 
 
6.在B窗口提交事务
 
 
 commit;
 
 
7.在A窗口中再次查询 
 
 
 select * from account;  转账成功.(不可重复读:一个事务读到另一个事务中已经提交的update的数据,导致多次查询结果不一致.)
 
 
   
 
                                                                                    避免脏读和不可重复读,演示虚读
 1.分别开启两个窗口,A.B
 2.设置A窗口的隔离级别:
 repeatable read 
 
 
 set session transaction isolation level repeatable read;
 
 
3.分别在两个窗口中开启事务 
 
 
 start transaction;
 
 
 
 
4.在B窗口完成转账的操作 
 
 
 update account set money = money - 1000 where name = '张森';
 update account set money = money + 1000 where name = '凤姐';
 
 
5.在A窗口查询
 
 
  select * from account; -- 转账没有成功:避免脏读.
 
 
6.在B窗口提交事务 
 
 
 commit;
 
 
7.在A窗口再次查询
 
 
 select * from account; -- 转账没有成功:避免不可重复读.
 
 
           
 
                                                                                           避免虚读
 1.分别开启两个窗口,A.B
 2.设置A窗口的隔离级别:repeatable read 
 
 
 set session transaction isolation level repeatable read;
 
 
3.分别在两个窗口中开启事务
 
 
 start transaction;
 
 
 
 
4.在B窗口完成插入操作 
 
 
 insert into account values (null,'王老师',10000)
 
 
5.在A中进行查询操作 
 
 
 select * from account; -- 没有查询到任何结果
 
 
6.在B窗口提交事务 
 
 
 commit; -- A窗口马上就会显示数据