数据库的事务
数据库中的事务是区别于文件系统的重要特征之一,只要我们有事务,就可以保证数据一致性,
还可以通过事务做恢复到某个时间节点的操作,从而保证数据的不丢失。
事务的概念:
一组逻辑的操作单元,是数据从一种状态变成另外一种状态。
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
事务的步骤:
-
开启事务
-
一系列的事务操作
-
提交事务或者回滚
开启事务
语法:
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里面去修改 -- 永久修改