事务


1.事务-基本演示

1.1.概述

如果一个包含了多个步骤的业务操作被事务管理,那么这些操作要么同时成功,要么同时失败.

1.2.事务的操作

    • 开启事务 -> START TRANSACTION

    • 回滚 -> ROLLBACK

    • 提交 -> COMMIT

1.3.手动提交事务使用过程:
1) 执行成功的情况: 开启事务 ——>执行多条 SQL 语句——> 成功提交事务

2) 执行失败的情况: 开启事务——>执行多条 SQL 语句——> 事务的回滚

1.4.事务使用

-- 创建账户表
CREATE TABLE account (
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(100),
balance DOUBLE
);`changgou_config`

-- 添加两条记录`account`
INSERT INTO account (`name`,balance) VALUE ('zhagsan',1000),('lisi',1000);

-- 张三转账500给李四
UPDATE account SET balance = balance - 500 WHERE NAME = 'zhangsan';
UPDATE account SET balance = balance + 500 WHERE NAME = 'lisi';

-- 查询
SELECT * FROM account;


-- 开启事务

-- 张三转账500给李四
-- 1.开启事务
START TRANSACTION ;
-- 2.张三给李四转500
UPDATE account SET balance = balance - 500 WHERE NAME = 'zhangsan';
-- 遇到错误
出现错误了。。。。。。。。。。
UPDATE account SET balance = balance + 500 WHERE NAME = 'lisi';

-- 成功:提交事务
COMMIT;

失败:

 回滚事务:

-- 失败:回滚事务
ROLLBACK

1.5.事务原理
事务开启之后, 所有的操作都会临时保存到事务日志中, 事务日志只有在得到 commit 命令才会同步到数据表中,其他任何情况都会清空事务日志(rollback,断开连接) 。
原理图:

 事务的步骤:
1) 客户端连接数据库服务器,创建连接时创建此用户临时日志文件
2) 开启事务以后,所有的操作都会先写入到临时日志文件中
3) 所有的查询操作从表中查询,但会经过日志文件加工后才返回
4) 如果事务提交则将日志文件中的数据写到表中,否则清空日志文件。

 

2.事务-默认自动提交&手动提交

  • 事务提交的两种方式

    • 手动提交

      • 需要事先开启事务再进行提交.

    • 自动提交

      • MYSQL默认就是自动提交,一条DML语句会自动提交一次事务.

  • 查看当前MYSQL的事务提交方式

     -- 查看事务的默认提交方式
     SELECT @@AUTOCOMMIT;  -- 结果为1代表自动提交,结果为0代表手动提交.
  • 修改MYSQL的事务提交方式

     -- 修改事务的默认提交方式
     SET @@AUTOCOMMIT = 0;

    默认提交方式修改为手动后,执行DML操作需要执行COMMIT语句

    修改事务提交方式只针对当前访问客户端有效

3.事务-事务四大特征束

  • 事务的四大特征:

    1. 原子性:是不可分割的最小操作单位,要么同时成功,要么同时失败。

    2. 持久性:当事务提交或回滚后,数据库会持久化的保存数据。

    3. 隔离性:多个事务之间,相互独立。

    4. 一致性:事务操作前后,数据总量不变

4.事务-事务隔离级别介绍

  • 概念:

    • 多个事务之间隔离的,相互独立的。但是如果多个事务操作同一批数据,则会引发一些问题,设置不同的隔离级别就可以解决这些问题。

  • 事务的隔离级别存在的问题

  • MYSQL中的隔离级别

什么是串行化?
其实Java序列化和Java串行化都是一样的,都对应英文中的Serializable。
一个对象随着创建而存在,随着程序结束而结束。那如果我要保存一个对象的状态呢?Java序列化能够将对象的状态写入byte流存储起来,也从其他地方将byte流读取出来,重新构造一个新的对象。这种机制允许你将对象通过网络进行传播,并且可以随时把对象持久化到数据库、文件系统中。简而言之,序列化就是将一个对象的状态保存起来,而反序列化就是将已经保存的流对象恢复成原来的对象。
  • 查询当前MYSQL的隔离级别

    -- 查看MYSQL的默认隔离级别
     SELECT @@tx_isolation;
  • 设置当前MYSQL的隔离级别

    -- 设置当前MYSQL的隔离级别
     SET GLOBAL TRANSACTION ISOLATION LEVEL 级别字符串;

5._事务-事务隔离级别演示1

  • 操作语句

    • 设置事务的隔离级别为: READ UNCOMMITTED

    • 不同的客户端产生:脏读,不可重复读

    • 脏读示例代码

     SELECT @@tx_isolation;
     -- 设置当前MYSQL的隔离级别为 READ UNCOMMITTED
     SET GLOBAL TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
     ​
     START TRANSACTION;
     UPDATE account SET balance = balance - 500 WHERE id = 1;
     UPDATE account SET balance = balance + 500 WHERE id = 2;
     ​
     ROLLBACK;

    回滚前,在其他客户端可以查到修改未提交数据。

    • 设置事务的隔离级别为: READ COMMITTED

    • 不同的客户端:解决了脏读问题,不能解决不可重复读

    SELECT @@tx_isolation;
     -- 设置当前MYSQL的隔离级别为 READ COMMITTED
     SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED;
     ​
     START TRANSACTION;
     UPDATE account SET balance = balance - 500 WHERE id = 1;
     UPDATE account SET balance = balance + 500 WHERE id = 2;
     ​
     ROLLBACK;

    其他客户端同一事务,两次查询不一致。

6._事务-事务隔离级别演示2

  • 设置事务的隔离级别为: REPEATABLE READ

  • 不同的客户端:解决了脏读问题,解决了不可重复读,不能解决幻读

  • 示例代码

     SELECT @@tx_isolation;
     -- 设置当前MYSQL的隔离级别为 REPEATABLE READ
     SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ;
     ​
     START TRANSACTION;
     UPDATE account SET balance = balance - 500 WHERE id = 1;
     UPDATE account SET balance = balance + 500 WHERE id = 2;
     ​
     ROLLBACK;

    同一个事务,两次查询一致

  • MVCC解决了幻读

原文地址:https://www.cnblogs.com/aaaazzzz/p/12906245.html