• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

[转]MySQL中的隔离级别跟悲观锁及乐观锁_mysql

mysql 搞代码 7年前 (2018-06-07) 182次浏览 已收录 0个评论

[转]mysql中的隔离级别和悲观锁及乐观锁

 

一、事务支持

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

    1. MyISAM 不支持事务,用于只读程序提高性能;

    2. InnoDB 支持ACID事务,行级锁、并发;

    3. Berkeley DB 支持事务。

 

二、隔离级别

    隔离级别决定了一个session中的事务可能对另一个session的影响、并发session对数据库的操作、一个session中所见数据的一致性。

    ANSI准定4个隔离级别MySQLInnoDB都支持:

    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 隔离级别设置:

# 设置 SET TRANSACTION ISOLATION LEVEL {READ-UNCOMMITTED | READ-COMMITTED | REPEATABLE-READ | SERIALIZABLE}  # 查看 SELECT @@tx_isolation

    MySQL的隔离级别REPEATABLE READ,在置隔离级别为READ UNCOMMITTEDSERIALIZABLE要小心,READ UNCOMMITTED致数据完整性的问题,而SERIALIZABLE致性能问题并增加死的机率。

 

三、悲观锁及乐观锁

    悲观锁:在读取数据时锁住那几行,其他对这几行的更新需要等到悲观锁结束时才能继续;
    乐观所:读取数据时不锁,更新时检查是否数据已经被更新过,如果是则取消当前更新

    一般在悲观锁的等待时间过长而不能接受才会选择乐观锁 。两种锁各有优缺点,不可认为一种好于另一种,像乐观锁适用于写比较少的情况下,即冲突真的很少发生的时候,这样可以省去了锁的开销,加大了系统的整个吞吐量。但如果经常产生冲突,上层应用会不断的进行retry,这样反倒是降低了性能,所以这种情况下用悲观锁就比较合适。

    悲观锁示例:

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/zztfj/article/details/6319740

欢迎大家阅读《[转]MySQL中的隔离级别跟悲观锁及乐观锁_mysql,跪求各位点评,by 搞代码


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:[转]MySQL中的隔离级别跟悲观锁及乐观锁_mysql

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址