用于货币数据的数据库的标准隔离级别是什么?

Cra*_*lus 3 mysql transaction isolation-level

当使用数据库服务器存储货币/金融数据时,我只能假设使用交易是强制性的。
但我不确定通常的隔离级别是哪个?是READ-REPEATABLE二手的吗?还是只有序列化级别?

Seb*_*ine 5

所有事务隔离级别的写行为都是相同的。然而,它们在读取方面有很大不同,特别是在事务中重复读取相同数据。您需要注意以下三种主要行为:

  1. 脏读
  2. 不可重复读取
  3. 幻影

维基百科对这些行为有很好的解释:http://en.wikipedia.org/wiki/Isolation_ (database_systems)#Isolation_Levels_vs_Read_Phenomena

您需要弄清楚您的应用程序可以处理哪些行为。如果这是绝对要求,则这些都不会发生,那么您必须使用可序列化隔离级别。然而,这也是并发量最少的级别,因为防止这些现象需要大量的写入过程串行化。(由此得名。)

在许多情况下,只要您使用良好的编码实践,您就可以摆脱限制较少的隔离级别。例如,通常应避免在同一事务中两次读取同一记录。这样您就不必担心不可重复读取。

但是,有时您需要执行一些操作,例如检查记录是否存在并在必要时创建它。仅当使用可序列化隔离级别时,这两个步骤的过程才是安全的,因为它是唯一允许范围锁的级别,并且提供了一种方法来防止插入另一个事务已“查看”的表区域。

财务应用程序可能存在许多情况,其中读取一条记录,然后基于一条或多条记录(包括原始记录)进行更改。每次遇到类似的情况时,更重要的是通过请求写入或更新锁定来指示初始读取的写入意图。如果您在稍后执行写入的同一事务中执行此操作,则根本不依赖于隔离级别。您还将减少死锁的可能性。

最后,隔离级别的选择实际上取决于您的要求。应用程序的类型并不是选择隔离级别的良好指南。查看每个需求并查看实现是否需要特定的隔离级别。


FOR UPDATE下面是如何使用MySQL 中的提示在 select 语句期间请求更新锁的示例:

SQL小提琴

MySQL 5.5.32 架构设置

CREATE TABLE accounts(id INT, balance INT);

INSERT INTO accounts(id,balance) VALUES( 1,42);
INSERT INTO accounts(id,balance) VALUES( 2,16);

GO

CREATE PROCEDURE swap(
  pId1 INT,
  pId2 INT)
BEGIN
  START TRANSACTION;

  SELECT @Balance1 := balance 
    FROM accounts
   WHERE id = pId1 FOR UPDATE;

  SELECT @Balance2 := balance 
    FROM accounts 
   WHERE id = pId2 FOR UPDATE;

  UPDATE accounts SET
    balance = @Balance2 WHERE id = pId1;

  UPDATE accounts SET
    balance = @Balance1 WHERE id = pId2;

  COMMIT;
END;
Run Code Online (Sandbox Code Playgroud)

查询1

CALL swap(1,2);
Run Code Online (Sandbox Code Playgroud)

查询2

SELECT * FROM accounts
Run Code Online (Sandbox Code Playgroud)

结果

| ID | BALANCE |
|----|---------|
|  1 |      16 |
|  2 |      42 |
Run Code Online (Sandbox Code Playgroud)

请注意,这是如何实现提示的示例FOR UPDATE。它不一定是解决所演示问题的最佳解决方案。

  • 你的回答太长而且不连贯。可序列化是问题的答案。不要依赖开发人员在软件中处理它。符合 ACID 的 RDBMS 知道如何处理事情。我想使用 MySQL 处理资金应该被禁止:/ (3认同)