#事务------------------>一个事务通常对应着一个业,同时事务是不可再分的,是最小的工作单元
#张三给李四转账100元
update act set money = 0 where name = "张三";
update act set money = 200 where name = "李四";
#上面这两个sql语句只能同时执行成功或失败,不可再分
#------------------------------------------------------------------------------
#做好相关配置工作,使得两个sql语句同时执行成功或失败,不可再分
update act set money = 0 where name = "张三";
update act set money = 200 where name = "李四";
#现实生活中可能出现很多问题导致两个sql语句不能同时执行
#比如 网络上传送是分开传送,有可能一个到达一个未到达导致一个成功一个失败
#--------------------------------------------------->配置的内容是---->事务的隔离级别
#什么是事务
#定义:
#1、事务是最小的不可分割的工作单元,通常一个事务对应着一个完整的业务
#2、一个完整的业务需要批量的DML(insert、update、delete)语句共同联合完成
#3、事务只和DML语句有关,或者说DML语句才有事务。这个和业务逻辑有关,业务逻辑不同,DML语句的个数不同
#事务的四大特性:
#1、事务具有原子性:指一个事务是一个不可分割的工作单位,其中的操作要么都成功,要么都失败
#2、事务具有持久性:指事务一旦提交,它对数据库的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响
#3、事务具有隔离性:事务和事务之间是相互隔离的,各个事务之间不能相互干扰
#4、事务具有一致性:事务在执行之前和执行之后,数据库的状态必须保持一致。这意味着事务执行过程中的任何变化都必须满足预定的规则和约束
#InnoDB 事务的ACID(事务)如何保证
# ~ 日志系统
#mysql如何实现事务:
#1、开启事务
#2、事务结束
#3、事务提交----------------->事务回滚--------------------->只有事务出错才会回滚
#非事务提交--------------------->非事务提交无法保证业务同时成功或失败
update act set money = 0 where name = "张三";
wadasfawetae
update act set money = 200 where name = "李四";
#事务提交
#事务提交之后再进行回滚,回滚是不生效的,因为事务提交之后,事务的持久性就会起作用
start transaction; #开启事务
update act set money = 0 where name = "张三";
update act set money = 200 where name = "李四";
commit; #事务提交
rollback; #事务回滚
#正确写法:
start transaction; #开启事务
update act set money = 0 where name = "张三";
update act set money = 200 where name = "李四";
-- 假设这里出现了错误,我们可以回滚事务
rollback;
-- 或者,如果没有出现错误,我们可以提交事务
commit;
#事务回滚------------->事务在执行rollback语句回滚到原来的状态
事务的并发问题:
1、脏读:事务B读取到了事务A修改但是未提交的数据
2、不可重复读:是指在一个事务内,多次读取到同一数据,但是数据的值发生了改变
3、幻读:指的是在同一个事务中,多次查询同一个范围的数据,却发现有新增或者减少的行。这是因为在这个事务进行的过程中,另一个事务插入或删除了符合查询条件的数据,导致前后两次的查询结果不一致
事务的隔离等级:为了解决并发所产生的问题,我们提出了事务的隔离级别,隔离级别越高,解决并发产生的问题越多
隔离性的隔离级别:
- 读未提交 read uncommitted:
- 事物A和事物B,事物A未提交的数据,事物B可以读取到。
- 这种隔离级别最低,这种级别一般是在理论上存在,数据库隔离级别一般都高于该级别。
- 三种并发问题都没解决。
设置读未提交的隔离级别:
set global transaction isolation level read uncommitted; #查看当前隔离级别 select @@global.tx_isolation,@@tx_isolation;
- 读已提交 read committed
- 事物A和事物B,事物A提交的数据,事物B才能读取到
- 这种隔离级别高于读未提交
- 换句话说,对方事物提交之后的数据,我当前事物才能读取到
- 这种级别可以避免“脏数据”
- 这种隔离级别会导致“不可重复读取”
- Oracle默认隔离级别
设置读已提交的隔离级别:
set global transaction isolation level read committed; #查看当前隔离级别 select @@global.tx_isolation,@@tx_isolation;
- 可重复读 repeatable read
- 事务A和事务B,事务A提交之后的数据,事务B读取不到
- 事务B是可重复读取数据
- 这种隔离级别高于读已提交
- 换句话说,对方提交之后的数据,我还是读取不到
- 这种隔离级别可以避免“不可重复读取”,达到可重复读取
- 比如1.和2.读到数据是同一个
- MySQL默认级别
- 虽然可以达到可重复读取,但是会导致“幻像读”
设置可重复读的隔离级别:
set global transaction isolation level repeatable read; #查看当前隔离级别 select @@global.tx_isolation,@@tx_isolation;
- 串行化 serializable
- 事务A和事务B,事务A在操作数据库时,事务B只能排队等待
- 这种隔离级别很少使用,吞吐量太低,用户体验差
- 这种级别可以避免“幻像读”,每一次读取的都是数据库中真实存在数据,事务A与事务B串行, 而不并发
设置串行化的隔离级别:
set global transaction isolation level serializable; #查看当前隔离级别 select @@global.tx_isolation,@@tx_isolation;