DC's blog DC's blog
首页
  • 计算机基础
  • linux基础
  • mysql
  • git
  • 数据结构与算法
  • axure
  • english
  • docker
  • opp
  • oop
  • 网络并发编程
  • 不基础的py基础
  • 设计模式
  • html
  • css
  • javascript
  • jquery
  • UI
  • 第一次学vue
  • 第二次学vue
  • Django
  • drf
  • drf_re
  • 温故知新
  • flask
  • 前后端不分离

    • BBS
    • 订单系统
    • CRM
  • 前后端部分分离

    • pear-admin-flask
    • pear-admin-django
  • 前后端分离

    • 供应链系统
  • 理论基础
  • py数据分析包
  • 机器学习
  • 深度学习
  • 华中科大的网课
  • cursor
  • deepseek
  • 杂文
  • 罗老师语录
  • 关于我

    • me
  • 分类
  • 归档
GitHub (opens new window)

DC

愿我一生欢喜,不为世俗所及.
首页
  • 计算机基础
  • linux基础
  • mysql
  • git
  • 数据结构与算法
  • axure
  • english
  • docker
  • opp
  • oop
  • 网络并发编程
  • 不基础的py基础
  • 设计模式
  • html
  • css
  • javascript
  • jquery
  • UI
  • 第一次学vue
  • 第二次学vue
  • Django
  • drf
  • drf_re
  • 温故知新
  • flask
  • 前后端不分离

    • BBS
    • 订单系统
    • CRM
  • 前后端部分分离

    • pear-admin-flask
    • pear-admin-django
  • 前后端分离

    • 供应链系统
  • 理论基础
  • py数据分析包
  • 机器学习
  • 深度学习
  • 华中科大的网课
  • cursor
  • deepseek
  • 杂文
  • 罗老师语录
  • 关于我

    • me
  • 分类
  • 归档
GitHub (opens new window)
  • 计算机基础

  • linux基础

  • mysql

    • 基础

    • 进阶

      • index
      • explain
      • transaction
        • 事务是什么
        • 四大特性 ACID
          • 原子性 Atomicity
          • 一致性 Consistency
          • 隔离性 Isolation
          • 持久性 Durability
        • 三种运行模式
          • 隐式开启,隐式提交
          • 显式开启、显式提交
          • 隐式开启,显示提交
        • 实验
          • 准备数据
          • 开始实验
        • pymysql实现事务处理
      • db_readPhenomenon
      • lock
      • other
  • git

  • 数据结构与算法

  • axure

  • english

  • docker

  • IT_Need
  • mysql
  • 进阶
DC
2023-04-12
目录

transaction

# 事务是什么

transaction 事务是mysql的一种机制,每开启一个事务,都可以往里面放一系列的sql语句..

事务是单个逻辑工作单位执行的一系列的操作,要么全执行,要么全不执行.
每开启一个事务,相当于给数据库拍了一张快照,这意味着在提交之前可以回滚,在事务中可以设置多个保存点,然后可以回滚到每个保存点.

结束事务可以用commit或rollback,结束事务会释放事务中所有的锁.

# 四大特性 ACID

经典转账行为 A向B转账100 --- A账户减钱 B账户加钱
     step1: selectA账户的余额 if > 100; 500
     step2: update A账户 余额 减 100; 500-100
     step3: selectB账户的余额; 500
     step4: update B账户 余额 加 100; 600

# 原子性 Atomicity

多条sql语句是不可分割的整体 要么全部执行成,要么都不执行 但凡一条失败 全部回滚 一损俱损

执行到第三步的时候 B的账号突然不可用了(注销了) 那么就需要回滚

# 一致性 Consistency

(原子性和一致性这两点不分家)

转账前 A+B账户余额 == 转账后 A+B账户余额
前后的状态一致
        事务开启前余额字段规定为正整数 那么事务结束后得到的字段值不能为负数 前后都要符合字段的约束

# 隔离性 Isolation

多个事务并发执行时, 一个事务的执行不应影响其他事务的执行
即一个事务执行过程中, 不应该受到其它事务的干扰!

要先明白一点: 在A向B转账的整个过程中,只要事务还没有提交(commit),查询A账户和B账户的时候,两个账户里面的钱的数量都不会有变化     事务是对快照进行的操作,真正对数据库的修改是要commit后!!

同时开启了两个事务, 事务1 A向B转账100;事务2 C向B转账200。事务开启,事务1一个快照,事务2一个快照.
事务2先完成了commit提交,这时候数据库里AB的余额分别是300,700.
但事务2的完成对事务1不会有影响,事务1查看快照,查看B账户余额依旧会是500,一系列sql语句执行时.

mysql底层会进行处理(一抹多锁的机制),保证转账结果的准确..

# 持久性 Durability

执行commit后,会将数据写到数据库做持久化保存


# 三种运行模式

显示 -- 手动 ; 隐式 -- 自动.

# 隐式开启,隐式提交

mysql默认每执行一条sql语句都会开一个事务,在执行完sql语句后,事务会自动隐式执行commit操作.
如果出现错误,则进行事务回滚至之前状态.

-- start transaction;
update user set name='EGON' where id=1;
-- commit;
1
2
3

# 显式开启、显式提交

需要自己写start transaction; |begin;和commit; |rollback; , 将要执行的sql语句放在自己手动开启的事务里..
切记要commit提交事务或rollback回滚事务,不然一系列的操作,操作的是快照而不是真正的数据!!

注意: 这种方式在我们使用commit或者rollback后,事务就结束了.再次进入事务状态需要再次start transaction.

-- 准备数据
create table tr(id int,name varchar(10),age int);
desc tr;
insert into tr values (1,'小明',18),(2,'小红',16);
select * from tr;
+------+--------+------+
| id   | name   | age  |
+------+--------+------+
|    1 | 小明   |   18|
|    2 | 小红   |   16|
+------+--------+------+

-- 开始实验
mysql> begin; -- 显示开启事务
mysql> update tr set name='小晓' where id = 1; -- 改了 改的是快照
mysql> select * from tr;
+------+--------+------+
| id   | name   | age  |
+------+--------+------+
|    1 | 小晓   |   18|
|    2 | 小红   |   16|
+------+--------+------+
mysql> rollback; -- rollback不提交快照 commit提交快照. 但rollback和commit都会结束事务.
mysql> select * from tr; -- 不能说回来了,应该说快照从来没有提交过...
+------+--------+------+
| id   | name   | age  |
+------+--------+------+
|    1 | 小明   |   18|
|    2 | 小红   |   16|
+------+--------+------+

mysql> update tr set name='小川' where id = 1; -- 隐式开启隐式提交 自动commit 数据已经写入了硬盘.
mysql> rollback; -- rollback没用 事务已经被自动commit了 没有事务拿来回滚..
mysql> select * from tr;
+------+--------+------+
| id   | name   | age  |
+------+--------+------+
|    1 | 小川   |   18|
|    2 | 小红   |   16|
+------+--------+------+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

# 隐式开启,显示提交

mysql帮忙自动开启事务,但是提交和回滚归我自己管.

-- mysql通过关闭自动提交事务,来达到隐式开启事务,显示提交事务的目的..
set session autocommit = 0; -- 0是关闭,1是开启;session是设置当前会话变量,global是设置全局变量.
1
2

# 实验

验证一致性、原子性、隔离性

# 准备数据

create table employee(
	id int primary key auto_increment,
	name varchar(20) not null,
	age int(3) unsigned not null default 20
);

insert into employee(name) values
('egon'),
('alex'),
('wupeiqi');

update employee set age = 18 where id <=2;

select * from employee;
+----+---------+-----+
| id | name    | age |
+----+---------+-----+
|  1 | egon    |  18 |
|  2 | alex    |  18 |
|  3 | wupeiqi |  20 |
+----+---------+-----+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# 开始实验

两边同时开启事务 update语句中 age = age + 1,右边的age是会去原表中读数据的,update操作的是快照!

开了两个终端A和B,同时begin开启了事务. B执行了两条update语句.
看step3和step4, 在B提交事务前对事务A没有影响,
看step5和step6, 在B提交事务后对事务A依旧没有影响, 这就是 隔离性!!

继续进行step7,A将id为1的用户的年龄增加了1,结果与step6相比,会发现egon的年龄从18到了20!!
这是因为age = age + 1,虽然操作的是快照,但是为了 一致性 ,右边的age是会去读原表里的数据的!!
step8同理,继续往后,A事务提交前,step10的结果再次验证了 隔离性,
step11,A事务提交, 数据写入了硬盘, 持久性!step12, B可以读取到相应数据.


# pymysql实现事务处理

# pymysql默认是隐式开启事务,显式提交事务
# 以下代码看看就行 实际上在pymysql里只要我不commit,数据就不会真正的更改!!
# 查询不用放到事务里 写操作需要
try:
    cursor.execute(sql_1)  
    cursor.execute(sql_2)  
    cursor.execute(sql_3)  
except Exception as e:
    connect.rollback()  # 事务回滚
    print('事务处理失败', e)
else:
    connect.commit()  # 这里的commit就是事务提交的意思!!
    print('事务处理成功', cursor.rowcount)# 关闭连接
cursor.close()
connect.close()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

explain
db_readPhenomenon

← explain db_readPhenomenon→

最近更新
01
deepseek本地部署+知识库
02-17
02
实操-微信小程序
02-14
03
教学-cursor深度探讨
02-13
更多文章>
Theme by Vdoing | Copyright © 2023-2025 DC | One Piece
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式