Mysql基础6-事务

6.事务概述

6.1 事务概述:一个最小的不可再分的工作单元;通常一个事务对应一个完整的业务
  • 多个操作要么都成功,要么都失败
  • 事务只和DML语句有关,或者说DML语句才有事务
  • 事务原则:ACID-
    • 原子性(Automicity)、
    • 一致性(Consistency)、
    • 持久性、(Isolation)
    • 隔离性(Durability)(脏读、幻读…)
  • 将一组sql放在一个批次中去执行
  • innodb支持,myISAM最新版本也支持

原子性:针对一个事务的两个步骤一起成功或一起失败,不能只发生其中一个动作,不允许分割

一致性:针对一个事务操作前和操作后的状态一致,数据库从一个正确的状态变化到另一个正确的状态。结果最终一致性

持久性:事务还没有提交,恢复到原状、已经提交了,持久化到数据库,一旦提交不可逆。

隔离性:针对多个用户同时并发操作,排除其他事务对本次事务的影响,互不干扰;数据库为每个用户开启事务,不能被其他事务的操作数据干扰。

6.2 隔离级别
6.2.1 隔离导致
  • 脏读:一个事务读取了另一个事务未提交的数据
  • 不可重复读:一个事物读取表中某一行数据,多次读取结果不同。(不一定是错误,只是某些场合不对)
  • 虚读(幻读):一个事务内读取了别的事务插入的数据,导致前后读取不一致(一般是行影响,多了一行)
  • 总结:不可重复读侧重修改,幻读侧重新增和删除。不可重复读要锁符合条件的行数据,幻读要锁表
6.2.2 隔离级别(isolation-level)
  • 读未提交(READ UNCOMMITTED):一个事务还没提交时,它做的变更就能被别的事务看到。
  • 读提交(Orlace默认级别READ COMMITTED):一个事务提交之后,它做的变更才会被其他事务看到。解决脏读。
  • 可重复读(mysql默认级别REPEATABLE READ):事务不会读到其它事务提交的修改(一开始读到什么,最后也读到什么)解决脏读、不可重复读
  • 串行化(SERIALIZABLE):解决了脏读、不可重复读、幻读,相当于单进程,效率低下。
6.2.3 事务作用范围-2种
  • 全局级别(global):对所有会话有效
  • 会话级别(session):只对当前会话有效
6.2.4设置事务隔离级别
SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL <isolation-level>
GLOBAL:代表设置全局事务级别
SESSION:代表设置会话事务级别

设置会话隔离级别为READ COMMITTED↓
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
或
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;

设置全局隔离级别为READ COMMITTED↓
SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED;
6.2.5 查看事务隔离级别
查看会话隔离级别
select @@tx_isolation;
show variables like '%isolation%';
查看全局隔离级别
select @@global.tx_isolation;
6.3. 事务开启、标志
  • Mysql默认开启

  • 无论是否开启事务,都会马上执行命令,只是开启事务后将状态存入redo日志,commit后才写入磁盘

  • BEGIN; COMMIT; ROLLBACK;

-- 事务开启
BEGIN;
INSERT INTO testmd5(`name`,`pwd`) VALUES('李云',MD5('123456'));
COMMIT;  -- 提交
BEGIN;
INSERT INTO testmd5(`name`,`pwd`) VALUES('王华',MD5('123456'));
ROLLBACK; -- 回滚
  • 提交:成功的结束,将所有的DML语句操作历史记录和底层硬盘数据来一次同步
  • 回滚:失败的结束,将所有DML语句操作历史记录全部清空
  • mysql实现事务是根据undo日志和redo日志实现的
  • undo:记录修改前的状态,rollback基于undo实现
  • redo:记录修改后的状态,commit基于redo实现
  • 无论是否开启事务,都会立刻执行,只是开启事务后将执行结果保存在redo中,commit之后才写入磁盘
  • mysql中begin和start transaction区别
    • begin或start transaction 都是显式开启一个事务,是等价的;
    • commit 或commit work都是等价的;
    • rollback或rollback work 也是等价的;
6.4 提交和回滚
  • mysql默认情况下,事务是自动提交的,也就是说只要执行了一条DML语句就开启了事务,并且提交了事务
  • 自动提交机制是可以关闭的
-- 事务开启
BEGIN;
INSERT INTO testmd5(`name`,`pwd`) VALUES('李云',MD5('123456'));
COMMIT;  -- 提交
BEGIN;
INSERT INTO testmd5(`name`,`pwd`) VALUES('王华',MD5('123456'));
ROLLBACK; -- 回滚
  • spring开启事务和mysql开启事务不一致时,以spring事务为主。
6.5 redis事务(补充)
  • 参考:[Mysql事务]:https://blog.csdn.net/qq_42294627/article/details/114959148----乔霸
6.5.1 事务指令
Redis:multi(标记事务开始)、exec(执行commands队列)、discard(结束事务,并消除commands队列)
6.5.2 事务底层实现
  • Redis基于Commands队列实现
6.5.3 事务默认状态
  • Redis默认关闭

  • 没开启事务:立即执行并返回结果,直接写入内存

  • 开启事务:不会立刻执行,排入队列,并返回队列状态,调用exec才会执行commands中的命令

6.5.4.事务是否支持回滚
  • Mysql支持回滚 Redis不支持回滚,
  • 可以使用WATCH去监听key在事务发生之前是否被修改,若被修改则回滚
    在这里插入图片描述
  • WATCH /UNWATCh(取消所有监视)

6.5.5.事务是否原子性

  • mysql事务是原子性的,关系型数据库中的事务都是原子性的
-- 事务开启
BEGIN;
INSERT INTO testmd5(`id`,`name`,`pwd`) VALUES(8,'王m',MD5('123456'));
INSERT INTO testmd5(`id`,`name`,`pwd`) VALUES(8,'王m',MD5('789456'));
COMMIT;  -- 提交


[SQL]BEGIN;
受影响的行: 0
时间: 0.001s

[SQL]
INSERT INTO testmd5(`id`,`name`,`pwd`) VALUES(8,'王m',MD5('123456'));
受影响的行: 1
时间: 0.000s

[SQL]
INSERT INTO testmd5(`id`,`name`,`pwd`) VALUES(8,'王m',MD5('789456'));
[Err] 1062 - Duplicate entry '8' for key 'PRIMARY'

在这里插入图片描述

  • redis命令是原子性的,事务不是原子性的
  • 若事务队列中存在命令错误(类似java编译性错误),执行exec,所有命令都不会执行
  • 若事务中存在语法错误(类似java 1/0的运行时异常),执行 exec,正确命令会被执行,错误命令抛出异常
6.6 执行事务
  • mysql默认开启事务自动提交的
  • mysql是默认开启,oracle是默认不开启的
SET autocommit = 0 -- 关闭
SET autocommit = 1 -- 开启默认
-- 手动处理事务先关闭
SET autocommit = 0; -- 关闭自动提交
-- 事务开启
START TRANSACTION  -- 标记一个事务的开始,从这个命令之后的sql都在一个事务中
DML
-- 事务结束
-- 提交:持久化(成功)
COMMIT 
-- 回滚:回到原来的样子(失败)
ROLLBACK;

SET autocommit = 1 -- 开启自动提交


-- 其他
SAVEPOINT 保存点名;  -- 设置一个事务的保存点
ROLLBACK to SAVEPOINT 保存点名; -- 回滚到保存点
RELEASE SAVEPOINT 保存点名; -- 释放保存点
set autocommit = 0;
START TRANSACTION;
UPDATE `account` set `money` = `money`-200 WHERE name = '张三';
UPDATE `account` set `money` = `money`+200 WHERE name = '李四';
COMMIT;
ROLLBACK;
set autocommit = 1;
  • sql事务相对于java代码,相当于一段被try{业务代码:commit();}catch(){rollback()}的方法
mysql索引见本专栏下一篇
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值