事务

一、操作演示(张三给李四转1000块)

数据准备

CREATE TABLE account(
  id INT auto_increment PRIMARY KEY COMMENT '主键ID',
  name VARCHAR(10) COMMENT '姓名',
  money INT COMMENT '余额'
) COMMENT '账户表';
INSERT INTO account(name,money)VALUES('张三',2000),('李四',2000);

正常情况

#张三2000 李四2000
#第一步,李四余额加上1000
UPDATE account SET money=money+1000 WHERE name='李四'
#第二步,张三余额减去1000
UPDATE account SET money=money-1000 WHERE name='张三' AND money>=1000
#张三1000 李四3000

异常情况事务处理第一种方式:

创建一个转账的存储过程:

DELIMITER $$
CREATE  PROCEDURE `proc_zhuan_zhang`(
    IN  amount  INT)
BEGIN
  #转帐前查询
  SELECT * FROM account;
  #第一步,李四余额加上1000
   UPDATE account SET money=money+amount WHERE `name`='李四';
  #第二步,张三余额减去1000
   UPDATE account SET money=money-amount WHERE `name`='张三' AND money>=amount;
   IF ROW_COUNT() >= 1 THEN
     COMMIT;
     SELECT '转账成功';
   ELSE
     ROLLBACK;
     SELECT '转账失败';
   END IF;
   #转账结果查询
   SELECT * FROM account;
END$$

给张三余额改为800元,模拟余额不足1000转账失败事务回滚:

UPDATE account SET money=800 WHERE `name`='张三'

执行存储过程:

#查看事务提交方式
SELECT @@AUTOCOMMIT;
#设置事务提交方式,1为自动提交,0为手动提交,该设置只对当前会话有效
SET @@AUTOCOMMIT = 0;
call proc_zhuan_zhang(1000)

结果输出:

转帐前:张三800,李四1000
转账失败
转帐后:张三800,李四1000

我们也可以演示一下转账100元的成功情况:

#查看事务提交方式
SELECT @@AUTOCOMMIT;
#设置事务提交方式,1为自动提交,0为手动提交,该设置只对当前会话有效
SET @@AUTOCOMMIT = 0;
call proc_zhuan_zhang(100)

输出结果: 转帐前:张三800,李四1000 转账失败 转帐后:张三700,李四1100

二、开启/提交/回滚事务

上面演示操作异常的时候,SET @@AUTOCOMMIT = 0这样开启事务总是感觉有些扯淡,我们可以用如下的方式开启事务:

START TRANSACTIONBEGIN TRANSACTION;

例:

START TRANSACTION;
call proc_zhuan_zhang(1000)

提交事务

COMMIT;

回滚事务:

ROLLBACK;

三、事务的四大特性

  • 原子性(Atomicity):事务是不可分割的最小操作但愿,要么全部成功,要么全部失败
  • 一致性(Consistency):事务完成时,必须使所有数据都保持一致状态
  • 隔离性(Isolation):数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境下运行
  • 持久性(Durability):事务一旦提交或回滚,它对数据库中的数据的改变就是永久的

四、并发事务问题

问题描述
脏读 一个事务读到另一个事务还没提交的数据
不可重复读 一个事务先后读取同一条记录,但两次读取的数据不同
幻读 一个事务按照条件查询数据时,没有对应的数据行,但是再插入数据时,又发现这行数据已经存在

五、并发事务隔离级别

隔离级别脏读不可重复读幻读
Read uncommitted
Read committed ×
Repeatable Read(默认) × ×
Serializable × × ×
  • √表示在当前隔离级别下该问题会出现
  • Serializable 性能最低;Read uncommitted 性能最高,数据安全性最差
#查看事务隔离级别:
SELECT @@TRANSACTION_ISOLATION;
#设置事务隔离级别:
SET [ SESSION | GLOBAL ] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE };
SESSION 是会话级别,表示只针对当前会话有效,GLOBAL 表示对所有会话有效
posted @ 2024-03-14 22:46  lucsa  阅读(5)  评论(0编辑  收藏  举报