`

[转]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

分享到:
评论

相关推荐

    36谈谈MySQL支持的事务隔离级别,以及悲观锁和乐观锁的原理和应用场景?

    36谈谈MySQL支持的事务隔离级别,以及悲观锁和乐观锁的原理和应用场景?

    06-VIP-深入理解Mysql事务隔离级别与锁机制.pdf

    锁可以分为乐观锁和悲观锁两种,悲观锁又可以分为读锁和写锁两种。读锁是一种共享锁,允许多个读操作同时进行;写锁是一种排它锁,阻断其他写锁和读锁。 锁分类 锁可以从性能上分为乐观锁和悲观锁,从对数据库操作...

    深入理解Mysql事务隔离级别与锁机制.pdf

    锁可以分为乐观锁和悲观锁。乐观锁是通过版本对比来实现的,悲观锁是通过加锁来实现的。悲观锁可以分为表锁和行锁,表锁是对整个表加锁,行锁是对某一行数据加锁。悲观锁还可以分为读锁和写锁,读锁是共享锁,写锁是...

    详解Mysql事务隔离级别与锁机制.doc

    锁可以分为乐观锁和悲观锁两种,从对数据库操作的类型分,分为读锁和写锁,从对数据操作的粒度分,分为表锁和行锁。读锁是共享锁,允许多个读操作可以同时进行,而写锁是排它锁,当前写操作没有完成前,它会阻断其他...

    实例讲解MySQL中乐观锁和悲观锁

    乐观锁和悲观锁式并发控制主要采用的技术手段 悲观锁 在关系数据库管理系统中,悲观并发控制(悲观锁,PCC)是一种并发控制的方法。它可以阻止一个事务以影响其他用户的方式来修改数据。如果一个事务执行的操作的每...

    深入理解Mysql锁与事务隔离级别1

    本文将详细阐述MySQL中的锁机制以及事务的四种隔离级别,以帮助读者更好地理解和应用这些关键概念。 一、锁的概念与分类 1.1 锁的定义 锁是一种用于控制多进程或线程对共享资源访问的同步机制。在数据库中,它...

    Hibernate实现悲观锁和乐观锁代码介绍

    在本文中,我们将详细介绍 Hibernate 实现悲观锁和乐观锁的代码实现,并讨论 Hibernate 的隔离机制和锁机制。 Hibernate 的隔离机制 Hibernate 的隔离机制是基于数据库的事务隔离级别的。 Hibernate 提供了四种...

    VIP-深入理解Mysql锁与事务隔离级别1

    1. **乐观锁与悲观锁**:乐观锁假设很少发生冲突,所以在读取数据时不加锁,而在写回数据时检查是否发生冲突。而悲观锁则相反,它在读取数据时立即加锁,防止其他事务修改数据。 2. **读锁(共享锁)与写锁(排他锁...

    mysql中的事务、锁讲解和操作

    4. 从锁的态度分类,有悲观锁和乐观锁。悲观锁假定并发操作会导致冲突,所以在数据读取时立即加锁;乐观锁则假设不会发生冲突,仅在更新数据时检查是否发生冲突。 在实际应用中,根据业务需求和性能考虑,开发人员...

    MySQL面试题(记得被问过的一些题目)

    什么是乐观锁和悲观锁? 乐观锁和悲观锁的区别? 乐观锁和悲观锁的使用场景? 什么是死锁? 解决死锁的机制有哪些? 发生死锁的场景有哪些? 什么是事务? 事务的特性与适用场景? 事务的隔离级别与适用场景?

    Mysql 锁机制的详细说明

    - 通常通过版本号或时间戳实现,MySQL 中没有内置的乐观锁,但可以在应用层面实现。 六、减少锁冲突和死锁的措施 1. 优化事务处理逻辑,避免长时间持有锁。 2. 使用短事务,减少锁的持有时间。 3. 适当使用读未...

    MySQL与Java锁的学习

    在实际开发中,Java程序员需要根据业务需求和并发场景选择合适的锁策略,并合理设置事务隔离级别,以确保数据一致性并避免死锁。 总结来说,“MySQL与Java锁的学习”涵盖了数据库锁机制和Java中与数据库交互的并发...

    SQL数据库系统原理(二)———乐观锁与悲观锁、MVCC、范式理论、SQL和NoSQL比较

    在数据库系统中,为了保证数据的一致性和完整性,有多种并发控制策略,其中包括乐观锁和悲观锁。这两种锁机制主要用于解决事务在并发环境中的数据冲突问题。 乐观锁是一种假设事务在执行过程中不会发生冲突的策略。...

    MySql面试题适合初级工程师

    MySQL 中的事务隔离级别包括 Read uncommitted、Read committed、Repeatable read 和Serializable 四个级别,用于控制事务之间的并发访问。 性能优化 14. 如何优化 MySQL 的性能?可以使用合适的索引、避免全表...

    【课堂笔记】MySQL事务与锁详解.pdf

    - 按加锁的方式分为:乐观锁和悲观锁。 4. 行锁的原理与算法: 行锁是指只对数据库表中某一行记录加锁,MySQL中InnoDB存储引擎支持行锁,其目的是减少锁冲突,提高并发性。行锁的算法通常有: - 记录锁(Record ...

Global site tag (gtag.js) - Google Analytics