一、 首先了解一下什么是事务,特点及作用
- 概念: 如果一个包含多个步骤的业务操作,被事务管理,那么这些操作要么同时成功,要么同时失败。
- 操作:
开启事务: start transaction;
回滚:rollback;
提交:commit;
以mysql为例:其中innodb和bdb支持事务而myisam等不支持事务。要是你测试时事务开启了没起作用别忘了检查你的引擎哦
示例:张三给李四转账500
首先张三账户金额大于500,正常来说张三账户减少500,李四账户增加500
情况一:正常
上图是正常现象,mysql是自动提交事务,每次执行DML的时候都自动提交,在另一个事务中结果也是一样的。
情况二:执行中间出现异常
你就会发现张三账户钱减了500但是李四账户中没有添加上500,导致总量少了500。这就会出现混乱。
解决方法,使用事务,
开启了事务之后,虽然出现异常数据改动了但是并没有提交,这时候并没有将数据写入硬盘中(数据库),在重新查询打开的页面中查询并没有改动数据。
可以选择回滚(没有进行选择提交在关闭的时候就会默认回滚数据)
如果没有异常直接进行提交就行,提交之后就会更改数据,
-- 创建一个表
CREATE TABLE account (
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(10),
balance DOUBLE
);
-- 添加数据
INSERT INTO account (NAME, balance) VALUES ('zhangsan', 1000), ('lisi', 1000);
-- 修改所有金额为1000
update account set balance = 1000;
-- 查询表中的金额
select * from account;
-- 开启事务
start transaction;
-- 张三給李四转账五百;
update account set balance = balance - 500 where name='zhangsan';
-- 异常。。。
update account set balance = balance + 500 where name='lisi';
-- 出现异常就会滚
ROLLBACK;
-- 没有异常九八结束数据,提交
commit;
另一个查询
二、事务的默认提交和手动提交
1、MySQL中的事务是默认自动提交的。像Oracle数据库可就是需要手动来提交了
-- 查询事务默认提交方式 结果中1代表自动提交 0代表手动提交
select @@autocommit;
-- 修改默认提交方式
set @@autocommit = 0;
-- 可以自行去试
-
MySQL数据库中事务默认自动提交
* 事务提交的两种方式: * 自动提交: * mysql就是自动提交的 * 一条DML(增删改)语句会自动提交一次事务。 * 手动提交: * Oracle 数据库默认是手动提交事务 * 需要先开启事务,再提交 * 修改事务的默认提交方式: * 查看事务的默认提交方式:SELECT @@autocommit; -- 1 代表自动提交 0 代表手动提交 * 修改默认提交方式: set @@autocommit = 0;
三、事务的四大特征:
1、原子性:是不可分割的最小操作单位,要么同时成功要么同时失败
2、持久性:当事务提交或者回滚以后,数据库会持久化的保存数据。
3、隔离性:多个事之间。相互独立。
4、一致性:事务操作前后,数据总量不变
四、事务的隔离级别:(了解就好)
1、脏读: 一个事务读取得到另一个事务还没提交的数据
2、不可重复读(虚读):在同一个事务中,两次读取到的数据不一致。
3、幻读:一个事务操作(DML)数据表中所有的记录,另一个事务添加了一条数据,则第一个事务查询不到事物的修改
隔离级别:
1. read uncommitted:读未提交
----------- 产生的问题:脏读、不可重复读、幻读
2. read committed:读已提交 (Oracle)
----------- 产生的问题:不可重复读、幻读
3. repeatable read:可重复读 (MySQL默认)
----------- 产生的问题:幻读
4. serializable:串行化
----------- 可以解决所有的问题(这种级别在开启了事务中,没有提交前,另一个事务操作同一数据时会处于等待状态,上个事务提交后才会直接执行)
但是随着级别越高越安全,但是效率也会越来越低
查询
数据库查询隔离级别:
select @@tx_isolation;
例如mysql:
数据库设置隔离级别:
更改了隔离级别之后需要重新打开连接窗口才会生效哦!!!
set global transaction isolation level 级别字符串;