dan*_*era 15
埃里克
我来自于测试它的行数非常多.
你永远不会在InnoDB mysql上发现有读取提交或更严格的隔离级别的幻像.它在文档中解释:
REPEATABLE READ:对于一致读取,与READ COMMITTED隔离级别有一个重要区别:同一事务中的所有一致读取读取第一次读取建立的快照.此约定意味着如果在同一事务中发出多个普通(非锁定)SELECT语句,则这些SELECT语句也相互一致.请参见第13.6.8.2节"一致的非锁定读取".
但是你也不能在read commited isolation level中找到幻像:这是必要的,因为必须阻止"幻像行"才能使MySQL复制和恢复工作.
更详细的信息:http://dev.mysql.com/doc/refman/5.1/en/set-transaction.html
我认为您需要转移到另一个数据库品牌,以向您的学生展示幻影.我同时使用MSSQLSERVER和Oracle.
嗯...对你的第一个问题很可惜.
Col*_*ang 12
MySQL隔离级别的MySQL中的"幻像读取"隐藏得很深,但仍然可以重现它.以下是步骤:
create table ab(一个int主键,b int);
Tx1:
开始;
从ab中选择*; //空集
对于InnoDB引擎以隔离级别重现幻像读取的可能性,REPEATABLE READ值得怀疑,因为InnoDB使用Multiversion并发控制 -对于每一行,MVCC引擎在插入和删除行时都知道事务编号,并且可以重现行更新的历史记录。
因此,所有随后的SELECT语句将在事务开始时显示表的状态,但同一事务在同一行中插入,删除或更新的行除外。其他事务提交的新行将不会出现,因为它们将具有比该事务大的插入事务编号,并且行范围在这里无关紧要。
我能够为Apache Derby数据库的隔离级别REPEATABLE READ再现PHANTOM READS ,因为它不使用多版本并发控制(在编写此答案时为版本10.8.2.2)。
要重现,请设置适当的事务级别(在ij-Derby的SQL客户端中):
-- Set autocommit off
autocommit off;
-- Set isolation level corresponding to ANSI REPEATABLE READ
set isolation rs;
Run Code Online (Sandbox Code Playgroud)
T1:
SELECT * FROM TableN;
Run Code Online (Sandbox Code Playgroud)
T2:
INSERT INTO TableN VALUES(55, 1);
COMMIT;
Run Code Online (Sandbox Code Playgroud)
再次T1:
SELECT * FROM TableN;
Run Code Online (Sandbox Code Playgroud)
现在T1应该再看到一行;
InnoDB应该像其他人一样防止幻像读取。
但是InnoDB具有与锁定有关的另一种怪异行为。查询获取锁时,它总是获取行的最新版本的锁。所以尝试以下
CREATE TABLE foo (i INT PRIMARY KEY, val INT);
INSERT INTO foo (i, val) VALUES (1, 10), (2, 20), (3, 30);
Run Code Online (Sandbox Code Playgroud)
然后在两个并发会话中(打开两个终端窗口):
-- window 1 -- window 2
START TRANSACTION;
START TRANSACTION;
SELECT * FROM foo;
UPDATE foo SET val=35 WHERE i=3;
SELECT * FROM foo;
Run Code Online (Sandbox Code Playgroud)
这应该在两个SELECT中都显示val = 10、20、30,因为REPEATABLE-READ表示第二个窗口仅看到事务开始时存在的数据。
然而:
SELECT * FROM foo FOR UPDATE;
Run Code Online (Sandbox Code Playgroud)
第二个窗口等待获取对第3行的锁定。
COMMIT;
Run Code Online (Sandbox Code Playgroud)
现在,第二个窗口中的SELECT完成,并显示val = 10、20、35的行,因为锁定该行会导致SELECT查看最新提交的版本。无论事务的隔离级别如何,InnoDB中的锁定操作都像在READ-COMMITTED下运行一样。
您甚至可以来回切换:
SELECT * FROM foo;
SELECT * FROM foo FOR UPDATE;
SELECT * FROM foo;
SELECT * FROM foo FOR UPDATE;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
8675 次 |
| 最近记录: |