Mysql中的事务
一、概述
1、首先,什么是事务呢?
事务就是由单独单元的一个或多个sql语句组成,在这个单元中,每个sql语句都是相互依赖的。而整个单独单元是作为一个不可分割的整体存在,类似于物理当中的原子(一种不可分割的最小单位)。
通过一组逻辑操作单元(一组DML——sql语句),将数据从一种状态切换到另外一种状态。
往通俗的讲就是,事务就是一个整体,里面的内容要么都执行成功,要么都不成功。不存在部分执行成功而部分执行不成功的情况。
二、事务的特性
1、事务的特性共有四种:
1.1、原子性:一个事务不可再分割,要么都执行要么都不执行。
1.2、一致性:一个事务执行会使数据从一个一致状态切换到另外一个一致状态。
1.3、隔离性:一个事务的执行不受其他事务的干扰。
1.4、持久性:一个事务一旦提交,则会永久的改变数据库的数据。
三、案例映入
转账案例:
假设张三丰和郭襄两人现在各有1000元,现在郭襄问张三丰借500元。那么张三丰此时就需要向郭襄转账。
在转账的过程中,我们需要确保做到万无一失,那么此时就需要用到我们Mysql中的事务概念了。
张三丰 1000
郭襄 1000
update 表 set 张三丰的余额=500 where name=‘张三丰’
意外
update 表 set 郭襄的余额=1500 where name=‘郭襄’
四、事务的隔离级别
4.1事务并发问题如何发生?
当多个事务同时操作同一个数据库的相同数据时。
4.2事务的并发问题有哪些?
4.2.1、脏读
一个事务读取到了另外一个事务未提交的数据。
4.2.2、不可重复读
同一个事务中,多次读取到的数据不一致。
4.2.3、幻读
一个事务读取数据时,另外一个事务进行更新,导致第一个事务读取到了没有更新的数据。
4.3 如何避免事务的并发问题?
通过设置事务的隔离级别
1、READ UNCOMMITTED
2、READ COMMITTED 可以避免脏读
3、REPEATABLE READ 可以避免脏读、不可重复读和一部分幻读
4、SERIALIZABLE 可以避免脏读、不可重复读和幻读
5、查看隔离级别:
select @@tx_isolation;
6、设置隔离级别:
set session(或global) transaction isolation level 隔离级别名;
五、事务的分类
5.1、隐式事务,没有明显的开启和结束事务的标志。
比如:insert、update、delete语句本身就是一个事务
5.2、显式事务,具有明显的开启和结束事务的标志。【前提:必须先设置自动提交功能为禁用】
六、事务操作的相关步骤
6.1、开启事务 取消自动提交事务的功能
set autocommit=0;
6.2、编写事务的一组逻辑操作单元(多条sql语句)
insert update delete
6.3、提交事务或回滚事务。
6.3.1、提交事务:commit;
6.3.2、回滚事务:rollback;
七、事务的演练
SET autocommit=0;
UPDATE account SET balance=20 WHERE username=‘li4’;
UPDATE account SET balance=150 WHERE username=‘li5’;
#关闭事务
commit;
#回滚了,数据是不会变化的
ROLLBACK;
八、隔离级别的演示—脏读
1、打开win窗口2个 A B
2、A窗口中设置事务的隔离级别为最低。
set session(或global) transaction isolation level READ UNCOMMITTED
3、A窗口中输入。
set autocommit=0;
update account set balance=100 where username =‘li4’;
没有提交事务的情况下
4、打开B窗口,同样设置事务的隔离级别为最低,输入
set session(或global) transaction isolation level READ UNCOMMITTED
set autocommit=0;
查询表数据,发现数据是修改之后的数据,这样就是脏读【万一人家数据回滚呢】
九、演示解决脏读的情况
1、先将之前的(即八中的数据)commit提交上去。
2、同时修改A B 两个窗口的隔离级别为read committed
set session(或global) transaction isolation level READ COMMITTED;
3、A 窗口中操作
set autocommit=0;
update account set balance=100 where username=‘li4’;
未提交情况下去B窗口中查看【注意:之前的一定要先commit】
4、B窗口中操作
set autocommit=0;
select * from account;
此时可以发现数据是修改之前的数据,避免了脏读的情况,