zoukankan      html  css  js  c++  java
  • 【14】事务的四大特征

    1、事务的四大特征

    A:原子性:事务是最小的单位,不可以在分割;

    C:一致性:事务要求,同一事务中的sql语句,必须保证同时成功或同时失败;

    I:隔离性:事务1和事务2之间是具有隔离性的;

    D:持久性:事务一旦结束,就不可以返回。

    事务开启方式:

    1.修改默认提交;

    2.begin;

    3.start transaction;

    事务提交:

    commit;

    事务手动回滚:

    rollback;

    2、事务的隔离性:

    1.read uncommitted; 读未提交的

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

    mysql> INSERT INTO user VALUES(3,'小明',1000);
    mysql> INSERT INTO user VALUES(4,'淘宝',1000);
    mysql> select * from user;
    +----+------+-------+
    | id | name | money |
    +----+------+-------+
    |  1 | a    |   900 |
    |  2 | b    |  1100 |
    |  3 | 小明 |  1000 |
    |  4 | 淘宝 |  1000 |
    +----+------+-------+

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

    系统级别:

    mysql> select @@global.transaction_isolation;

    会话级别:

    mysql> select @@transaction_isolation;

    默认的隔离级别:

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

    如何修改隔离级别?

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

     eg.小明买鞋

    成都的小明转账800:

    mysql> start transaction;
    mysql> update user set money=money-800 where name='小明';
    mysql> update user set money=money+800 where name='淘宝';
    mysql> select * from user;
    +----+------+-------+
    | id | name | money |
    +----+------+-------+
    |  1 | a    |   900 |
    |  2 | b    |  1100 |
    |  3 | 小明 |   200 |
    |  4 | 淘宝 |  1800 |
    +----+------+-------+

    广州的淘宝查收:

    mysql> use bank;
    Database changed
    mysql> select * from user;
    +----+------+-------+
    | id | name | money |
    +----+------+-------+
    |  1 | a    |   900 |
    |  2 | b    |  1100 |
    |  3 | 小明 |   200 |
    |  4 | 淘宝 |  1800 |
    +----+------+-------+

    之后成都的小明:

    mysql> rollback;
    mysql> select * from user;
    +----+------+-------+
    | id | name | money |
    +----+------+-------+
    |  1 | a    |   900 |
    |  2 | b    |  1100 |
    |  3 | 小明 |  1000 |
    |  4 | 淘宝 |  1000 |
    +----+------+-------+

    之后广州的淘宝才发现:

    mysql> select * from user;
    +----+------+-------+
    | id | name | money |
    +----+------+-------+
    |  1 | a    |   900 |
    |  2 | b    |  1100 |
    |  3 | 小明 |  1000 |
    |  4 | 淘宝 |  1000 |
    +----+------+-------+

    如果两个不同的地方都在进行操作,事务A(小明)开启之后,它的数据仍可以被其他事务B(广州)读取到。这样就会出现(脏读)。

    脏读:一个事务读到了另外一个事务没有提交的数据。实际上开发是不允许脏读出现的。

    2.read committed; 读已提交的

    修改隔离级别并查看:

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

    eg.

    银行的会计小张:

    mysql> start transaction;
    mysql> select * from user;
    +----+------+-------+
    | id | name | money |
    +----+------+-------+
    |  1 | a    |   900 |
    |  2 | b    |  1100 |
    |  3 | 小明 |  1000 |
    |  4 | 淘宝 |  1000 |
    +----+------+-------+

    小张出去上厕所了。

    此时的小王:

    mysql> use bank;
    Database changed
    mysql> start transaction;
    mysql> insert into user values(5,'c',100);
    mysql> commit;
    mysql> select * from user;
    +----+------+-------+
    | id | name | money |
    +----+------+-------+
    |  1 | a    |   900 |
    |  2 | b    |  1100 |
    |  3 | 小明 |  1000 |
    |  4 | 淘宝 |  1000 |
    |  5 | c    |   100 |
    +----+------+-------+

    小张回来了:

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

    咦?money的平均值不应该是1000么?怎么变成了820?

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

    此称为:不可重复读现象。

    3.repeatable read; 可以重复读

     修改隔离级别并查看:

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

    在REPEATABLE-READ隔离级别下又会出现什么问题?

    张全蛋在成都

    mysql> start transaction;

    王尼玛在北京

    mysql> start transaction;

    张全蛋在成都

    mysql> insert into user values(6,'d',1000);
    mysql> commit;
    mysql> select * from user;
    +----+------+-------+
    | id | name | money |
    +----+------+-------+
    |  1 | a    |   900 |
    |  2 | b    |  1100 |
    |  3 | 小明 |  1000 |
    |  4 | 淘宝 |  1000 |
    |  5 | c    |   100 |
    |  6 | d    |  1000 |
    +----+------+-------+

    王尼玛在北京

    mysql> insert into user values(6,'d',1000);
    ERROR 1062 (23000): Duplicate entry '6' for key 'PRIMARY'
    mysql> select * from user;
    +----+------+-------+
    | id | name | money |
    +----+------+-------+
    |  1 | a    |   900 |
    |  2 | b    |  1100 |
    |  3 | 小明 |  1000 |
    |  4 | 淘宝 |  1000 |
    |  5 | c    |   100 |
    +----+------+-------+

    这种现象叫幻读

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

    4.serializable; 串行化

     修改隔离级别:

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

    当前记录:

    mysql> select * from user;
    +----+------+-------+
    | id | name | money |
    +----+------+-------+
    |  1 | a    |   900 |
    |  2 | b    |  1100 |
    |  3 | 小明 |  1000 |
    |  4 | 淘宝 |  1000 |
    |  5 | c    |   100 |
    |  6 | d    |  1000 |
    +----+------+-------+

    张全蛋在成都

    mysql> start transaction;

    王尼玛在北京

    mysql> start transaction;

    张全蛋在成都

    mysql> insert into user values(7,'铁柱',1000);
    mysql> commit;
    mysql> select * from user;
    +----+------+-------+
    | id | name | money |
    +----+------+-------+
    |  1 | a    |   900 |
    |  2 | b    |  1100 |
    |  3 | 小明 |  1000 |
    |  4 | 淘宝 |  1000 |
    |  5 | c    |   100 |
    |  6 | d    |  1000 |
    |  7 | 铁柱 |  1000 |
    +----+------+-------+

    王尼玛在北京

    mysql> select * from user;
    +----+------+-------+
    | id | name | money |
    +----+------+-------+
    |  1 | a    |   900 |
    |  2 | b    |  1100 |
    |  3 | 小明 |  1000 |
    |  4 | 淘宝 |  1000 |
    |  5 | c    |   100 |
    |  6 | d    |  1000 |
    |  7 | 铁柱 |  1000 |
    +----+------+-------+

    张全蛋在成都

    mysql> insert into user values(8,'小花',1000);

    sql语句会卡住,直到王尼玛commit。

    当user表被另外一个事务操作的时候,其他事务里面的写操作是不可以进行的。进入排队状态(串行化)。

    直到王尼玛事务结束以后,张全蛋的写入操作才会执行。

    串行化的问题是:性能特差。性能:

    READ-UNCOMMITTED (脏读)> READ COMMITTED > REPEATABLE READ(幻读) > SERIALIZABLE

    隔离级别越高,性能越差,默认级别是REPEATABLE READ。

  • 相关阅读:
    购物车宣传页
    项目开发流程
    AJAX跨域
    jQuery中的AJAX
    AJAX封装
    AJAX里使用模板引擎
    AJAX的具体使用
    AJAX的基本使用
    js技巧汇总
    CSS特效汇集
  • 原文地址:https://www.cnblogs.com/direwolf22/p/12696532.html
Copyright © 2011-2022 走看看