mysql 事务

1、概述

事务就是将一组SQL语句放在同一批次内去执行,如果一个SQL语句出错,则该批次内的所有SQL都将被取消执行;MySQL事务处理只支持InnoDB和BDB数据表类型


2、事务的ACID原则 百度 ACID

  • 原子性(Atomic)

整个事务中的所有操作,要么全部完成,要么全部不完成,不可能停滞在中间某个环节。事务在执行过程中发生错误,会被回滚(ROLLBACK)到事务开始前的状态,就像这个事务从来没有执行过一样。

  • 一致性(Consist)

一个事务可以封装状态改变(除非它是一个只读的)。事务必须始终保持系统处于一致的状态,不管在任何给定的时间并发事务有多少。也就是说:如果事务是并发多个,系统也必须如同串行事务一样操作。其主要特征是保护性和不变性(Preserving an Invariant),以转账案例为例,假设有五个账户,每个账户余额是100元,那么五个账户总额是500元,如果在这个5个账户之间同时发生多个转账,无论并发多少个,比如在A与B账户之间转账5元,在C与D账户之间转账10元,在B与E之间转账15元,五个账户总额也应该还是500元,这就是保护性和不变性。

  • 隔离性(Isolated)

隔离状态执行事务,使它们好像是系统在给定时间内执行的唯一操作。如果有两个事务,运行在相同的时间内,执行相同的功能,事务的隔离性将确保每一事务在系统中认为只有该事务在使用系统。这种属性有时称为串行化,为了防止事务操作间的混淆,必须串行化或序列化请求,使得在同一时间仅有一个请求用于同一数据。

  • 持久性(Durable)

在事务完成以后,该事务对数据库所作的更改便持久的保存在数据库之中,并不会被回滚。

3、事务实现

  • 基本语法:
-- 使用set语句来改变自动提交模式
set autocommit = 0; /*关闭*/
set autocommit = 1; /*开启*/
-- 注意:
--- 1.mysql中默认是自动提交
--- 2.使用事务时应先关闭自动提交
-- 开始一个事务,标记事务的起始点
start transaction

-- 提交一个事务给数据库
commit
-- 将事务回滚,数据回到本次事务的初始状态
rollback
-- 还原mysql数据库的自动提交
set autocommit =1;
-- 保存点
savepoint 保存点名称 -- 设置一个事务保存点
rollback to savepoint 保存点名称 -- 回滚到保存点
release savepoint 保存点名称 -- 删除保存点
  • 事务处理步骤:

mysql 事务_第1张图片

4、测试题目 

/*
课堂测试题目
A在线买一款价格为500元商品,网上银行转账.
A的银行卡余额为2000,然后给商家B支付500.
商家B一开始的银行卡余额为10000
创建数据库shop和创建表account并插入2条数据
*/
create database `shop` character set utf8 collate utf8_general_ci;
use `shop`;

create table `account`
(
    `id`   int(11)       not null auto_increment,
    `name` varchar(32)   not null,
    `cash` decimal(9, 2) not null,
    primary key (`id`)
) engine = innodb
  default charset = utf8;



insert into account (`name`,`cash`) values('a',2000.00),('b',10000.00)
-- 转账实现
set autocommit = 0; -- 关闭自动提交
start transaction; -- 开始一个事务,标记事务的起始点
update account set cash=cash-500 where `name`='a';
update account set cash=cash+500 where `name`='b';
commit; -- 提交事务
-- rollback;
set autocommit = 1; -- 恢复自动提交

chatgpt举例:

-- 开启事务
START TRANSACTION;

-- 执行转账操作
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1; -- 从账户1扣除100元
UPDATE accounts SET balance = balance + 100 WHERE account_id = 2; -- 向账户2添加100元

-- 插入交易记录
INSERT INTO transactions (from_account, to_account, amount) VALUES (1, 2, 100); -- 插入一笔转账交易记录

-- 判断条件
IF (SELECT balance FROM accounts WHERE account_id = 1) >= 0 THEN
    -- 账户1余额足够,提交事务
    COMMIT;
ELSE
    -- 账户1余额不足,回滚事务
    ROLLBACK;
END IF;
-- 开始事务
start transaction;

-- 更新转出账户的余额
update accounts set balance = balance - 100 where account_id = 1;

-- 更新转入账户的余额
update accounts set balance = balance + 100 where account_id = 2;

-- 插入一条交易记录
insert into transactions (from_account, to_account, amount) values (1, 2, 100);

-- 判断转出账户和转入账户的余额是否小于零,如果是则回滚事务
select balance into @from_balance from accounts where account_id = 1;
select balance into @to_balance from accounts where account_id = 2;
if @from_balance < 0 or @to_balance < 0 then
    rollback;
else
    -- 提交事务
    commit;
end if;

-- 开始事务
start transaction;

-- 插入用户信息
insert into users (username, email) values ('user1', '[email protected]');

-- 获取上一步插入的用户id
set @user_id = last_insert_id();

-- 插入订单信息
insert into orders (user_id, product_name, price) values (@user_id, 'product1', 10.99);

-- 判断是否满足条件
if (条件) then
    -- 如果满足条件,则提交事务
    commit;
else
    -- 如果不满足条件,则回滚事务
    rollback;
end if;

-- 结束事务
commit;

你可能感兴趣的:(Mysql,mysql)