天天看点

Mysql事务机制

事务机制解决问题:

  • 避免写入直接操作数据文件,直接操作数据文件是很危险的事,可以在确认无误后同步进总库.
  • MySQL有5种日志文件,其中只有redo日志和undo日志与事物有关(5种日志文件后续再说)
  • 默认情况下,MySQL执行每条SQL语句都会自动开启和提交事务
  • 为了让多条SQL语句纳入一个事务下,可以手动管理事务
  • Mysql事务机制

事务四种属性: 原子性 一致性 隔离性 持久性

原子性

事务是一个或者多个SQL语句组成的整体,要么全部执行成功,要么全都执行失败 ,事务执行之后,不允许停留在中间某个状态.比如:把10部门中MANGER员工调往20部门,其他岗位员工调往30部门,然后删除10部门. 涉及到事务:开启事务 UPDATE语句 DELETE语句 提交事务

Mysql事务机制

比如下边三行代码, 第一行开启一个事务, 第二行代表sql语句,第三行代表要么commit提交后叠加覆盖原始数据库,要么rollback取消这一过程所有操作.

START TRANSACTION;
SQL语句
[COMMIT | ROLLBACK];      

备注:COMMIT:持久化提交 ; ROLLBACK:回滚

举个例子:

START TRANSACTION;    -- 启动事务机制
delete from t_emp;  -- 增删改查过程
delete from t_dept;  -- 增删改查过程

SELECT * FROM t_emp;  -- 增删改查过程
SELECT * FROM t_dept;  -- 增删改查过程

-- COMMIT;  -- 提交同步(给注释掉了)
ROLLBACK ;  -- 回滚不同步      

事务一致性

不管在任何给定的时间\并发事务有多少, 事务必须保证运行结果的一致性,不允许数据歧义.比如银行转账,100个人互相乱七八糟的转账,但最后总额肯定是固定的.原来总值100万,经过一顿互相转账后,总额一定还是100万,不能因为几重了多钱,也不能因为bug少钱.

Mysql事务机制

隔离性

  • 隔离性要求事务不受其他并发事务的影响, 如果同在给定的时间内,该事物是数据库唯一运行的事务
  • 默认情况下A事务,只能看到日志中该事物的相关数据
  • 默认情况下A事务,只能看到该事物的相关数据
  • 除了默认情况下,想看别的事务内容? 请继续往下看到隔离级别部分.

持久性

  • 事务一旦提交,结果便是永久性的,即便发生宕机,仍然可以依靠事务日志完成数据的持久化

    事务的四个隔离级别

    刚才的隔离性上边说,默认情况下只看自己的,那么想看别人的或者想看曾经自己的,或者设定一些事务之间的sql执行顺序.那么就需要调整隔离级别了.首先看一张表:

  • Mysql事务机制
  • 买票案例–利用未提交事务read uncommitted

    A去刷12306软件买票, 看到还剩一个座位,拍了下来,正在付款, 此时B也看到了.也拍了下来,然后吧唧把钱付了.A则付款失败了,返回一看刚才的未售出状态边已售出了…这不耽误事么,半路杀出个程咬金.

  • Mysql事务机制
  • READ UNCOMMITTED 代表可以读取其他事务未提交的数据

还是这个案例,如果B拍了正在付款,A看到的时候应该显示已售出,就避免了竹篮子打水一场空, 淘宝下单同样的场景.

怎么用? 事务前加上 :SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

SQL语言的话可以如下案例,注意读里面注释

-- 案例一个
-- 事务A:开启事务,把所有工资设置为1,但是没提交(没commit) ,此时查出来都是1元;
START TRANSACTION;    -- 启动事务机制
UPDATE t_emp SET sal=1;
SELECT sal FROM t_emp;

-- 此时开启案例B,也来读sal
SELECT empno , ename, sal FROM t_emp;
-- 读出来的还是原来的工资数据.
-- 如果想要B读取出A设置后的东西,则改成下边代码

-- B的结果:读取A未提交的
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
START TRANSACTION;
SELECT empno , ename, sal FROM t_emp;      

转账支出案例-- 利用committed

Scott账务余额5000,B先支出100, 此时A开启进入系统,此时scott余额4900. 紧接着此时A转账1000,此时应该scott余额5900. 如果转账同时B又退回100,此时账户应该6000元.

但是如果不允许A读取B的操作未提交的,就没读到支出又退回的100.A读到5900块,少了100. 这样不对.大公司账面复杂,这一天得差飞了.

READ COMMITTED 代表只能读取其他事务提交的数据

承接上边的代码部分案例,请阅读备注

– 还是上边案例,若A没有提交commit 则B读不到的话,则用这句话:注意是committed

SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;

START TRANSACTION;

SELECT empno , ename, sal FROM t_emp;

下单后,提交订单前,商家提价了,按下单价支付案例–利用repeatable read

举例场景 : A下单时候350 ,但没付款. 正在犹豫时B商家把商品价格改高了到400. 过一会后A去付款还应该是付款350才对.

所以这个repeatable read 能读取当时执行时读到数据库的数据,不受后续数据库变化影响.

SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;      

序列化事务–依次执行,未到执行时挂着

这个将把一切并发禁用, 让事务逐一执行, 这会降低数据库操作并发能力

开头设置这句:SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;

SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
START TRANSACTION;
SELECT * FROM table1;

-- 若别的事务正在运行,这条将一直不出结果等待中      

举例:

A创建事务,修改了工资,但没commit提交确认,总库没改呢.此时B查东西将被挂起. 若A执行了commit或者rollback,则B进程结束.

Mysql事务机制

A执行,但没commit

Mysql事务机制

B 序列化设置的事务将挂着

Mysql事务机制