Cra*_*lus 3 mysql transaction isolation-level
当使用数据库服务器存储货币/金融数据时,我只能假设使用交易是强制性的。
但我不确定通常的隔离级别是哪个?是READ-REPEATABLE二手的吗?还是只有序列化级别?
所有事务隔离级别的写行为都是相同的。然而,它们在读取方面有很大不同,特别是在事务中重复读取相同数据。您需要注意以下三种主要行为:
维基百科对这些行为有很好的解释:http://en.wikipedia.org/wiki/Isolation_ (database_systems)#Isolation_Levels_vs_Read_Phenomena
您需要弄清楚您的应用程序可以处理哪些行为。如果这是绝对要求,则这些都不会发生,那么您必须使用可序列化隔离级别。然而,这也是并发量最少的级别,因为防止这些现象需要大量的写入过程串行化。(由此得名。)
在许多情况下,只要您使用良好的编码实践,您就可以摆脱限制较少的隔离级别。例如,通常应避免在同一事务中两次读取同一记录。这样您就不必担心不可重复读取。
但是,有时您需要执行一些操作,例如检查记录是否存在并在必要时创建它。仅当使用可序列化隔离级别时,这两个步骤的过程才是安全的,因为它是唯一允许范围锁的级别,并且提供了一种方法来防止插入另一个事务已“查看”的表区域。
财务应用程序可能存在许多情况,其中读取一条记录,然后基于一条或多条记录(包括原始记录)进行更改。每次遇到类似的情况时,更重要的是通过请求写入或更新锁定来指示初始读取的写入意图。如果您在稍后执行写入的同一事务中执行此操作,则根本不依赖于隔离级别。您还将减少死锁的可能性。
最后,隔离级别的选择实际上取决于您的要求。应用程序的类型并不是选择隔离级别的良好指南。查看每个需求并查看实现是否需要特定的隔离级别。
FOR UPDATE下面是如何使用MySQL 中的提示在 select 语句期间请求更新锁的示例:
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。它不一定是解决所演示问题的最佳解决方案。
| 归档时间: |
|
| 查看次数: |
2090 次 |
| 最近记录: |