数据库的事务

82 阅读5分钟

数据库的事务

数据库中的事务是区别于文件系统的重要特征之一,只要我们有事务,就可以保证数据一致性,

还可以通过事务做恢复到某个时间节点的操作,从而保证数据的不丢失。

事务的概念:

      一组逻辑的操作单元,是数据从一种状态变成另外一种状态。
      11111     1转呼啦圈      1拍球     1走平衡木     1单脚跳     1爬杆子  
  经典的例子:转账      A转钱给B  B的账户增加100(增加的时候,报错了)  A少了100  B没有拿到 

当事务执行多个操作的时候,要么所有操作全部成功,要么全部失败。

有ACID四个特性

  • A原子性

事务是一个不可以分割的工作单位,要么全部提交,要么全部失败,不存在中间状态。

  • C一致性

事务的执行前后,从一个合法的状态,变成另外一个合法的状态,这种状态是语义上的,和业务相关

合法状态是什么意思?就是一种约束,满足这个状态,就表示合法。

举例:A账户有200元 转账 转300 这个时候A账户就有-100元 就是数据不一致。

所以在转账之前需要有约束,账户余额不足的约束。

A 200 转 给B 50 A 150 B 0 150+0 = 150 结果是不对的 校验A+B=200

不管数据去了哪里,最终账户里面的钱是不少的。

I隔离性

事务如果有多个的情况下,相互之间不能干扰

A 200 B 0 A转了2次钱给B 一次转50

  • D持久性

事务一旦被提交,对数据库中的改变就永久的。接下来的其他操作,比如系统故障都不应该对

其有任何影响。由事务的日志来保证 日志包含 重做日志 和 回滚日志

ACID总结:

原子性是基础,隔离性是手段,一致性是约束条件,持久性是最终的目的。

-- A转100块钱给B
update account set money = 200-50 where name = 'A'; -- 150
update account set money = 200-50 where name = 'A'; -- 150
-- B的账户要加100
update account set money = 0+50 where name = 'B';  -- 50
update account set money = 50+50 where name = 'B'; -- 100

事务的步骤:

  1. 开启事务

  2. 一系列的事务操作

  3. 提交事务或者回滚

开启事务

语法:

begin 和 start transaction

区别:

start transaction 可以加一些参数

read only 只读事务 属于该事务的数据库,数据只能读取

read write 读写事务 (默认)

with consistent snapshot; 启动一致性读

如果要连在一起写用逗号隔开

commit; 提交

rollback; 回滚 撤销正在执行的事务,没有提交的修改。


begin;
-- 开启一个只读的事务
start transaction read only;  
start transaction read write;  
insert into emp(empno) values(1);
select * from emp;

事务隔离级别:

mysql是一个DBMS,是一个C/S(客户端/服务器)架构的软件。 可以有N个客户端去连mysql,

每个客户端和服务器连接成功后,就可以称为一个会话(session)。每个客户端都可以在自己的会话中向服务器发送请求,一个请求可能某个事务的一部分,对于服务器来说,服务器可以同时处理多个事务。在事务中就有 隔离性的 特性。理论上说:事务对某个数据表进行访问的时候,其他事务需要排队。

只有当前的事务处理完成后,其他事务才可以去访问数据。 如果是这样的话,性能就会大打折扣。

如果不设置事务的隔离级别可能就会存在并发的问题:比如出现数据的脏写,脏读,不可重复读,幻读。

-- 脏写  两个客户端A,B   sessionA sessionB  A修改了emp表中的smith的sal=8000 A还没有提交成功 B也修改smith的sal为6000 
-- 脏读  A读取了已经被B修改的数据,但是B没有提交。  也就意味A读的数据是临时并且无效的数据 
-- 不可重复读 A 读取了sal 然后B 更新了sal,A再次读时候,就变成新的sal的值,A两次读的值不一样了 
select sal from emp where ename = 'smith';  -- 8000
set autocommit = 0;
update emp set sal = 8000 where ename = 'smith';
-- 幻读  A从一个表中读取了一个字段,然后B在emp表中又新加了一些数据,然后A再读emp表的时候,会发现新增了几条数据
select sal from emp;

-- 以上问题的严重程度的排序

-- 脏写>脏读>不可重复读>幻读

4个隔离级别:

read uncommited(读未提交) 不能避免脏读和不可重复读,幻读 read commited(读已提交) 可以避免脏读,不能避免不可重复读,幻读 repeatable read(可重复读) 不能避免幻读 serializable (串行化) 所有并发问题都可以解决,但是性能十分低下。 语法: set 隔离级别; -- 一次性的 可以修改配置文件 my.cnf里面去修改 -- 永久修改