• MySQl中隔离级别和悲观锁乐观锁


    1.MySql的事物支持

    MySQL的事务支持不是绑定在MySQL服务器本身,而是与存储引擎相关:

    1. MyISAM:不支持事务,用于只读程序提高性能   
    2. InnoDB:支持ACID事务、行级锁、并发   
    3. Berkeley DB:支持事务

    2.隔离级别

    隔离级别决定了一个session中的事务可能对另一个session的影响、并发session对数据库的操作、一个session中所见数据的一致性 
    ANSI标准定义了4个隔离级别,MySQL的InnoDB都支持:

    Java代码

    1. READ UNCOMMITTED:最低级别的隔离,通常又称为dirty read,它允许一个事务读取还没commit的数据,这样可能会提高性能,但是dirty read可能不是我们想要的   
    2. READ COMMITTED:在一个事务中只允许已经commit的记录可见,如果session中select还在查询中,另一session此时insert一条记录,则新添加的数据不可见   
    3. REPEATABLE READ:在一个事务开始后,其他session对数据库的修改在本事务中不可见,直到本事务commit或rollback。在一个事务中重复select的结果一样,除非本事务中update数据库。   
    4. SERIALIZABLE:最高级别的隔离,只允许事务串行执行。为了达到此目的,数据库会锁住每行已经读取的记录,其他session不能修改数据直到前一事务结束,事务commit或取消时才释放锁。  

    可以使用如下语句设置MySQL的session隔离级别:

    SET TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE} 

    MySQL默认的隔离级别是REPEATABLE READ,在设置隔离级别为READ UNCOMMITTED或SERIALIZABLE时要小心,READ UNCOMMITTED会导致数据完整性的严重问题,而SERIALIZABLE会导致性能问题并增加死锁的机率.


    3.乐观锁和悲观锁的策略

    乐观所和悲观锁策略: 
    悲观锁:在读取数据时锁住那几行,其他对这几行的更新需要等到悲观锁结束时才能继续 .
    乐观所:读取数据时不锁,更新时检查是否数据已经被更新过,如果是则取消当前更新 .
    一般在悲观锁的等待时间过长而不能接受时我们才会选择乐观锁
    .

    悲观锁的例子:

    CREATE PROCEDURE tfer_funds     
           (from_account INT, to_account INT,tfer_amount NUMERIC(10,2),     
            OUT status INT, OUT message VARCHAR(30))     
    BEGIN     
        DECLARE from_account_balance NUMERIC(10,2);     
        
        START TRANSACTION;     
        
        
        SELECT balance     
          INTO from_account_balance     
          FROM account_balance     
         WHERE account_id=from_account     
           FOR UPDATE;     
        
        IF from_account_balance>=tfer_amount THEN     
        
             UPDATE account_balance     
                SET balance=balance-tfer_amount     
              WHERE account_id=from_account;     
        
             UPDATE account_balance     
                SET balance=balance+tfer_amount     
              WHERE account_id=to_account;     
             COMMIT;     
        
             SET status=0;     
             SET message='OK';     
        ELSE     
             ROLLBACK;     
             SET status=-1;     
             SET message='Insufficient funds';     
        END IF;     
    END;    

    乐观锁的例子:

    CREATE PROCEDURE tfer_funds     
        (from_account INT, to_account INT, tfer_amount NUMERIC(10,2),     
            OUT status INT, OUT message VARCHAR(30) )     
        
    BEGIN     
        
        DECLARE from_account_balance    NUMERIC(8,2);     
        DECLARE from_account_balance2   NUMERIC(8,2);     
        DECLARE from_account_timestamp1 TIMESTAMP;     
        DECLARE from_account_timestamp2 TIMESTAMP;     
        
        SELECT account_timestamp,balance     
            INTO from_account_timestamp1,from_account_balance     
                FROM account_balance     
                WHERE account_id=from_account;     
        
        IF (from_account_balance>=tfer_amount) THEN     
        
            -- Here we perform some long running validation that     
            -- might take a few minutes */     
            CALL long_running_validation(from_account);     
        
            START TRANSACTION;     
        
            -- Make sure the account row has not been updated since     
            -- our initial check     
            SELECT account_timestamp, balance     
                INTO from_account_timestamp2,from_account_balance2     
                FROM account_balance     
                WHERE account_id=from_account     
                FOR UPDATE;     
        
            IF (from_account_timestamp1 <> from_account_timestamp2 OR     
                from_account_balance    <> from_account_balance2)  THEN     
                ROLLBACK;     
                SET status=-1;     
                SET message=CONCAT("Transaction cancelled due to concurrent update",     
                    " of account"  ,from_account);     
            ELSE     
                UPDATE account_balance     
                    SET balance=balance-tfer_amount     
                    WHERE account_id=from_account;     
        
                UPDATE account_balance     
                    SET balance=balance+tfer_amount     
                    WHERE account_id=to_account;     
        
                COMMIT;     
        
                SET status=0;     
                SET message="OK";     
            END IF;     
        
        ELSE     
            ROLLBACK;     
            SET status=-1;     
            SET message="Insufficient funds";     
        END IF;     
    END$$    

     一个讲解比较清楚的博客推荐:http://blog.csdn.net/csh624366188/article/details/7654996

  • 相关阅读:
    <2014 04 29> *nix环境编程常用库总结
    <2014 04 29> c/c++常用库总结
    <2014 04 26> 《Coders at Work编程人生:15位软件先驱访谈录》
    <2014 04 16> 上班实习第一天
    <2014 04 15> C++语言回顾精要(原创By Andrew)
    [荐][转]为何应该使用 MacOS X(论GUI环境下开发人员对软件的配置与重用)
    [荐][转]王垠:我和权威的故事(2014)
    [荐][转]如何用美剧真正提升你的英语水平
    [转] 数学的用处(一)(二)(三)(四)(数学图谱)
    metadata 和 routing
  • 原文地址:https://www.cnblogs.com/jsStudyjj/p/5267925.html
Copyright © 2020-2023  润新知