数据库学习之事务
数据库事务
数据库事务(Database Transaction) ,是指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行。 事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源。通过将一组相关操作组合为一个要么全部成功要么全部失败的单元,可以简化错误恢复并使应用程序更加可靠。一个逻辑工作单元要成为事务,必须满足所谓的ACID(原子性、一致性、隔离性和持久性)属性。事务是数据库运行中的逻辑工作单位,由DBMS中的事务管理子系统负责事务的处理。
四个特性
事务相关命令
start transaction 开启事务 Rollback 回滚事务,即撤销指定的sql语句(只能回退insert delete update语句) Commit 提交事务,提交未存储的事务 savepoint保留点 事务处理中设置的临时占位符 你可以对它发布回退(与整个事务回退不同)
简单示例
我们在生活中,一个人给另一个人转钱。
假如李四给王五转5000,李四的钱扣了,但是王五没有收到这样的情况发生了。
准备
create table account(id int,name varchar(20),balance double); insert into account value(2,"alex",10000); insert into account value(3,"lili",10000);
转账实例:
update account set balance=balance-5000 where name="xinyi"; update account set balance=balance+5000 where name="lili";
start transaction; #开启事务 update account set balance=balance-5000 where name="xinyi"; #xinyi的账户减5000(这里进行的操作是没有保存到数据库中的,如果你此时commit才会写入数据库) select * from account; #查询表 rollback; #假设这里出现了网络问题,扣款失败,撤销前面的操作(撤销到开启事务或者上一次commit的地方) select * from account; #再次查询表 commit; #提交整个事务
pymysql中调用数据库启动事务
# 导入pymysql模块 import pymysql # 连接database conn = pymysql.connect( host="123.207.251.121", user="root", password="159357", db ="test", charset ="utf8") # 得到一个可以执行SQL语句的光标对象 cursor = conn.cursor() # 执行完毕返回的结果集默认以元组显示 # 事务处理 sql_0 = "insert into account value(4,'liurun',3400) " sql_1 = "update account set balance=balance-2000 where name='lili' " sql_2 = "update account set balance=balance+2000 where name='xinyi' " try: cursor.execute(sql_0) # 插入一条数据 conn.commit() cursor.execute(sql_1) # lili账号减5000 cursor.execute(sql_2) # xinyi账号多5000 except Exception as e: conn.rollback() # 事务回滚 print('事务处理失败', e) else: conn.commit() # 事务提交 print('事务处理成功', cursor.rowcount) # 关闭光标对象 cursor.close() # 关闭数据库连接 conn.close()
结果:
savepoint 保留点
前面使用rollback回滚事务,不管你前面有多少操作,都会撤销操作
如果前面有五十条操作,一下子回滚到最开始,那么肯定不合理,可不可以回滚到指定的操作上?
你只需要给相应的操作取一个名字,相当于一个标识。
设置标识点
savepoint 标识名;
回滚指定标识点
rollback to 标识名;
#开启事务
start transaction;
#第一次 insert into account values(4,"name1",8000); savepoint insert1; select * from account; #第二次 insert into account values(4,"name2",3000); savepoint insert2; select * from account; #第三次 delete from account where id=2; savepoint delete1; select * from account; #第四次 delete from account where id=4; savepoint delete2; select * from account;
原始数据:
第一次:(依次执行)
第二次:
第三次:
第四次:
回滚到delete1:
回滚到insert1: