zoukankan      html  css  js  c++  java
  • mysql事务

    mysql事务
    mysql中,事务是一个最小的不可分割的工作单元。事务能够保证一个业务的完整性

    比如银行转账:

    a ——> -100

    update user set money=money-100 where name ="a";

    b——> +100

    update user set money=money+100 where name ="b";

    实际的程序中,如果只有一条语句执行成功了,而另外一条没有执行成功?

    出现数据前后不一致

    多条sql语句,可能会有同时成功的要求,要么同时失效

    mysql中如何控制事务的
    1.mysql是默认开启事务的(自动提交)

    select @@autocommit;

    默认事务开启的作用是:当我们去执行一个sql语句时,效果会立即体现出来,且不能回滚。

    create database bank;
    create table user(
    id int primary key,
    name varchar(20),
    money int
    );

    insert into user values(1,"a",1000);

    事务的提交与撤销

    事务回滚:撤销sql语句执行效果

    rollback;

    设置mysql自动提交为false

    set autocommit=0 #关闭了mysql自动提交功能

    再次进行插入

    insert into user values(2,"b",1000)#其实是虚拟数据,未被提交
    rollback#可撤销上一步操作,

    如何改变其虚拟存储的效果呢?在一条语句后紧接着放一个commit

    insert into user values(3,"c",2000);
    commit#相当于手动提交数据
    rollback#再次回滚便没有效果,体现了事务的持久性......直接回滚到autocommit关闭处

    update user set money=money-100 where name ="a";
    update user set money=money+100 where name ="b";

    事务给我们提供了一个反悔的语句

    事务的分类

    自动提交@@autocommit=1
    手动提交commit
    事务回滚rollback
    begin;或者 start transction;

    begin;或者 start transction;#可以手动开启一个事务,可以回滚相当于autocommit=0
    commit #手动提交
    事务的四大特征(ACID)
    A 原子性:事务是最小的单位,不可以再分割
    C一致性:事务要求,同一事务中的sql语句,必须同时成功或者同时失效
    I 隔离性:事务1和事务2之间具有隔离性
    D 持久性:事务一旦结束(commit,rollback:一旦commit就不能rollback;一旦rollback就不能commit),j就不可以返回
    事务开启
    1.修改默认提交 set autocommit=0;
    2.begin;
    3.star transaction;
    事务手动提交
    commit;#虚拟的效果真实产生
    事务手动回滚
    rollback ;#虚拟的效果被撤销
    事务的隔离性
    1.read uncommitted; #读未提交的
    2.read committed; #读已提交的
    3.repeatable read; #可以重复读
    4.serializable ; #串行化

    --------->1-read uncommitted<---------

    如果有事务a和事务b,

    a事务对数据进行操作,在操作过程中,事务没有被提交,但b可以看见a操作的结果。

    bank数据库user表

    insert into user values(3,"小明",1000);
    insert into user values(4,"淘宝店",1000);
    +----+--------+-------+
    | id | name | money |
    +----+--------+-------+
    | 1 | a | 800 |
    | 2 | b | 1200 |
    | 3 | 小明 | 1000 |
    | 4 | 淘宝店 | 1000 |
    +----+--------+-------+

    ---如何查看数据库的隔离级别?

    select @@global.transaction_isolation;
    select @@transaction_isolation;
    +--------------------------------+
    | @@global.transaction_isolation |
    +--------------------------------+
    | REPEATABLE-READ |
    +--------------------------------+

    ---如何修改隔离级别?

    set global transaction isolation level read uncommitted;
    +--------------------------------+
    | @@global.transaction_isolation |
    +--------------------------------+
    | READ-UNCOMMITTED |
    +--------------------------------+

    --转账:小明在淘宝店买鞋子:800块钱

    小明->成都 ATM

    淘宝店 ->广州 ATM

    begin;
    update user set money=money-800 where name="小明";
    update user set money=money+800 where name="淘宝店";
    +----+--------+-------+
    | id | name | money |
    +----+--------+-------+
    | 1 | a | 800 |
    | 2 | b | 1200 |
    | 3 | 小明 | 200 |
    | 4 | 淘宝店 | 1800 |
    +----+--------+-------+

    --给淘宝店打电话,说你去查一下,是不是到账饿了

    --淘宝店在广州查账

    +----+--------+-------+
    | id | name | money |
    +----+--------+-------+
    | 1 | a | 800 |
    | 2 | b | 1200 |
    | 3 | 小明 | 200 |
    | 4 | 淘宝店 | 1800 |
    +----+--------+-------+

    --发货

    --晚上请女朋友吃好吃的

    --1800

    --小明在成都

    rollback
    +----+--------+-------+
    | id | name | money |
    +----+--------+-------+
    | 1 | a | 800 |
    | 2 | b | 1200 |
    | 3 | 小明 | 1000 |
    | 4 | 淘宝店 | 1000 |
    +----+--------+-------+

    --结账时发现钱不够

    select * from user;
    +----+--------+-------+
    | id | name | money |
    +----+--------+-------+
    | 1 | a | 800 |
    | 2 | b | 1200 |
    | 3 | 小明 | 1000 |
    | 4 | 淘宝店 | 1000 |
    +----+--------+-------+

    总结

    - 如果两个不同的地方,都在进行操作,如果a 开启之后,它的数据可以被其他事物读取到,这样就会出现脏读

    - 脏读:一个事务读到另外一个事务没有提交的数据,就叫做脏读

    -------->2.read committed<---------####

    set global transaction isolation level read committed;
    +--------------------------------+
    | @@global.transaction_isolation |
    +--------------------------------+
    | READ-COMMITTED |
    +--------------------------------+

    bank 数据库user表

    小张:银行的会计

    begin;
    select * from user;
    +----+--------+-------+
    | id | name | money |
    +----+--------+-------+
    | 1 | a | 800 |
    | 2 | b | 1200 |
    | 3 | 小明 | -600 |
    | 4 | 淘宝店 | 2600 |
    +----+--------+-------+

    小张出去上厕所,抽烟

    小王

    begin;
    insert into user values(5,"c",100);
    commit;
    +----+--------+-------+
    | id | name | money |
    +----+--------+-------+
    | 1 | a | 800 |
    | 2 | b | 1200 |
    | 3 | 小明 | -600 |
    | 4 | 淘宝店 | 2600 |
    | 5 | c | 100 |
    +----+--------+-------+

    --小张上完厕所,抽完烟回来

    select avg(money) from user;
    +------------+
    | avg(money) |
    +------------+
    | 820.0000 |
    +------------+

    --money的平均值不是1000,变少了?

    -- 虽然只读到另外一个事务提交的数据,但还是会出现问题————读取同一个表的数据,发现前后不一致。

    --不可重复现象:read commited

    ------------> repeatable read <---------------

    set global transaction isolation level repeatable read;
    select @@global.transaction_isolation;
    +--------------------------------+
    | @@global.transaction_isolation |
    +--------------------------------+
    | REPEATABLE-READ |
    +--------------------------------+

    ---王尼玛-北京

    begin;#同时打开begin
    insert into user values(8,"铁柱",1000);;
    +----+--------+-------+
    | id | name | money |
    +----+--------+-------+
    | 1 | a | 800 |
    | 2 | b | 1200 |
    | 3 | 小明 | -600 |
    | 4 | 淘宝店 | 2600 |
    | 5 | c | 100 |
    | 8 | 铁柱 | 1000 |
    +----+--------+-------+

    --张全蛋-成都

    begin;#同时打开begin
    insert into user values(8,"铁柱",1000);;

    待修改!!!!!

    +----+--------+-------+
    | id | name | money |
    +----+--------+-------+
    | 1 | a | 800 |
    | 2 | b | 1200 |
    | 3 | 小明 | -600 |
    | 4 | 淘宝店 | 2600 |
    | 5 | c | 100 |
    +----+--------+-------+
    mysql> insert into user values(8,"铁柱",1000);
    ERROR 1062 (23000): Duplicate entry '8' for key 'user.PRIMARY'

    --这种现象就叫做幻读

    ----事务a和事务b 同时操作一张表时,事务a提交的数据,也不能被事务b读到,就可以造成幻读

    --------> serializable(串行化) <--------

    set global transaction isolation level serializable;
    select @@global.transaction_isolation;
    +--------------------------------+
    | @@global.transaction_isolation |
    +--------------------------------+
    | SERIALIZABLE |
    +--------------------------------+

    --张全蛋-成都

    begin;
    insert into user values(7,"赵铁柱",1000);

    ---王尼玛-北京

    begin;
    insert into user values(7,"赵铁柱",1000);

    --sql语句被卡住了?

    当输入commit时即刻会被执行

    --当user表被另外一个事务操作执行的时候,其他事务里面的额写操作,是不可以进行的。

    --进入排队状态(串行化),只有当一边的事务结束后,写入操作才会被执行

    - 在没有等待超时的情况下

    ---串行化的问题:性能特差!!

    性能总结

    read uncommitted > read committed > repeatable read > serializable

    -隔离级别越高,性能越差

    -mysql默认隔离级别是repeatable read

    记录学习的点点滴滴
  • 相关阅读:
    【BZOJ2243】【SDOI2011】染色 (LCT)
    【BZOJ2631】tree (LCT)
    【BZOJ3626】【LNOI2014】LCA (树剖+离线)
    [BZOJ3244][NOI2013] 树的计数
    BZOJ2754 SCOI2012day1T2喵星球上的点名(后缀数组)
    BZOJ2753 SCOI2012day1T1滑雪与时间胶囊(bfs+kruskal)
    Swift
    Library not loaded: @rpath/libswiftCore.dylib
    PHP require include 区别
    Mac OS 下 eclipse中文乱码解决方法
  • 原文地址:https://www.cnblogs.com/yangzilaing/p/14617269.html
Copyright © 2011-2022 走看看