• 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

  • 相关阅读:
    【转】Nginx open_file_cache模块 文件描述符缓存
    缓冲区溢出二:从缓冲区溢出到获取反弹shell实例
    英文文法学习笔记(18)代名词
    英文文法学习笔记(17)特殊构句
    英文文法学习笔记(19)时态
    小知识:RMAN基于某个具体时间点的恢复示例
    小知识:NFS卡死问题处理
    英文文法学习笔记(20)时态的一致及叙述法
    英文文法学习笔记(21)连接词
    小知识:如何从图片中提取文字
  • 原文地址:https://www.cnblogs.com/jsStudyjj/p/5267925.html
Copyright © 2020-2023  润新知