zoukankan      html  css  js  c++  java
  • MYSQL:基础——事务处理

    MYSQL:基础——事务处理

    事物处理

    什么是事物处理

      试想我们实现一个销售结算的业务,这个完整的操作大致需要执行3条SQL语句:

    UPDATE MS_GOODS  SET quantity = quantity - 5 WHERE id = '1001' AND quantity >=5;  --库存-5
    UPDATE MS_WALLET  SET money = money - 500 WHERE userid = 'admin' AND money >=500; --客户资产-500
    INSERT INTO MS_DETAIL;  --插入订单记录
    

      如果这三条语句执行期间某一条语句出现问题都将导致错误后果,甚至造成不可挽回的损失。所以,这三条语句应该一起执行,即为一个原子操作,要么都成功,要么都失败!怎样让其成为一个原子操作呢,这就引入了事务的概念。事务是一个序列操作,其中的操作要么都执行,要么都不执行,一个事务为一个原子操作

      在MySQL中,手动开启事务的代码如下:

    BEGIN; -- 或START TRANSACTION;
        UPDATE MS_SALE  SET quantity = quantity - 5 WHERE id = '1001' AND quantity >=5;
        UPDATE MS_WALLET  SET money = money - 500 WHERE userid = 'admin' AND money >=500;
        INSERT INTO MS_DETAIL;
    COMMIT; 

    更改默认的提交行为

      在 MySQL 命令行的默认设置下,事务都是自动提交的,即执行 SQL 语句后就会马上执行 COMMIT 操作。因此要显式地开启一个事务务须使用命令 BEGIN 或 START TRANSACTION,或者执行命令 SET AUTOCOMMIT=0,用来禁止使用当前会话的自动提交。

    SET AUTOCOMMIT = 0 -- 关闭自动提交
    SET AUTOCOMMIT = 1 -- 打开自动提交

    RollBack和Commit

      开启事务后,如果我修改了一些数据,发现数据修改错误,可以执行rollback命令来使数据回滚到事务开始前的状态;当然如果事务内的代码执行没有问题,我们可以执行commit,让修改真正生效。

    BEGIN;
        UPDATE...
        INSERT...
        DELETE...
        --发现修改错误
    ROLLBACK; --回滚到修改前的状态
    
    BEGIN;
        UPDATE...
        INSERT...
        DELETE...
        --修改的没毛病
    COMMIT; --使修改生效
    

      如果直接调用ROLLBACK,会使是事务内的所有操作失效,但是如果设置保留点的话,可以使数据更加灵活的恢复到保留点时的状态

    BEGIN;
        UPDATE...
        INSERT...
        INSERT...
        INSERT...
    SAVEPOINT MYPOINT
        DELETE...
    ROLLBACK TO MYPOINT; --回滚到delete前的状态  

    事物的隔离级别

      事物的隔离级别主要关于多个事务访问同一数据时,MySQL的处理策略。主要有RU、RC、RR、Serializable四种,并且执行效率依次降低。

      

    read uncommitted(读取未提交数据)

      将事务隔离级别设置为read uncommitted,即便是事务没有commit,但是我们仍然能读到未提交的数据,这是所有隔离级别中最低的一种。事务B可以访问到事务A还没提交的数据,这种情况称之为脏读。

    read committed(可以读取其他事务提交的数据)

       当我们将当前会话的隔离级别设置为read committed的时候,当前会话只能读取到其他事务提交的数据,未提交的数据读不到。

      

    repeatable read(可重读)

      这是MySQL默认的隔离级别,在同一个事务中查询结果必须保持一致。事务A查询数据后,如果其他事务B新增了一条数据D并提交,但是事务A再查是查不到新增的数据D的,此时事务A插入数据D是会报错的,因为实际上数据D已经插入到数据库中了,这种情况也称之为幻读。

    serializable(串行化)

      当我们将当前会话的隔离级别设置为serializable的时候,其他会话对该表的写操作将被挂起。串行化是隔离级别中最严格的,但是这样做势必对性能造成影响。所以在实际的选用上,我们要根据当前具体的情况选用合适的。

    参考资料

  • 相关阅读:
    Sql Server Tempdb原理-日志机制解析实践
    Sql Server 高频,高并发访问中的键查找死锁解析
    SQL Server 高并发Insert数据解析,实践
    Sql Server 2012新特性 Online添加非空栏位.
    SQL Server 利用批量(batchsize)提交加快数据生成/导入
    SQL Server 最小化日志操作解析,应用
    SQL Server 统计信息(Statistics)-概念,原理,应用,维护
    SQL Server 索引知识-应用,维护
    BigDecimal加减乘除计算
    如何判断一个String字符串不为空或这不为空字符串
  • 原文地址:https://www.cnblogs.com/MrSaver/p/7453994.html
Copyright © 2011-2022 走看看