2012-02-05 64 views
0

我在早些时候使用事务时遇到了一些问题。希望有人能帮我弄明白。我会感谢任何帮助。谢谢。使用索引列和非索引列来更新来自不同事务的数据有什么区别?

MySQL表结构:

create table test (
    id int not null, 
    someid int, 
    name varchar(50), 
    update_date datetime 
); 
primary key : id (auto-inc) 
index1 : id (unique) 
index2 : id, update_date (non-unique) 

Java方法:

// consider this method is Transaction 1 
method1() { 
    A. set session transaction isolation level read commited; 
    B. select update_date from test where someid = 1; 
    C. insert into test values (some new data..); 
    D. select update_date from test where someid = 1; 
} 

// consider this method is Transaction 2 
methodb() { 
    E. (start with default transaction isolation level - repeatable read) 
    F. update test set udpate_date = now() where someid = 1; 
} 

这里是我做的:

  1. 执行方法1(),打破(在Eclipse中设置断点)在D
  2. 执行方法2()并发

请注意,“someid”不在索引中,但它存储与“id”完全相同的数据。

然后,我只有等待,只要我不提交交易1,或者最终交易超时就结束。但如果我改变了从哪里条款到F id = 1,它会工作得很好,没有任何等待。在这里我感到困惑,因为我没有锁定该表或任何行。如果我这样做,不应该这样做,对吧?

有人可以告诉我为什么会发生这种情况吗?谢谢!

回答

1

条件someId = 1要求数据库系统扫描整个表,因为没有索引。 insert语句可以插入someid = 1的行,并因此影响第二个事务的结果。

使用where id = 1,dbs可以确定只有一行受到F语言的影响。插入语句不会更改此行。

我只是想知道,隔离级别是否会影响执行?

+0

谢谢你的回复!这对于更新是如何实现是有意义的,至少我认为是这样。嗯,我对交易并不熟悉,但相信隔离级别会影响更新声明,至少对我来说很难相信:-) – redfoxlee 2012-02-05 11:05:20

+0

btw:好像隔离级别会影响锁定模式。但在这种情况下,我看不到READ COMMITED和REPEATABLE READ之间的区别。 – redfoxlee 2012-02-05 15:05:34

1

我不是MySQL的并发控制专家,但我猜你正在看到锁定的影响:直到第一个事务提交,第二个无法知道第一个事务插入的行是否会被提交,所以必须停下来。

第一事务完成后,方可第二个事务继续,并且:

  • 更新的行(如果第一个事务提交)
  • 或无法更新行(如果第一个事务回滚,所以该行并未实际插入)。

现在的问题是:为什么没有发生索引id?您确定您使用与someid相同的价值进行交易吗?您是否更改了两项交易的WHERE条款?

+0

谢谢你的回复,首先。我的目标是从“测试”中复制一些数据作为模板并将它们插回到同一张表中。所以我必须确保我有一个正确的副本,这就是为什么我确实使用了上述方法。是的,我确定我对这两笔交易使用了相同的价值。那么,我不知道,现在看来tkr的答案在这里有一定意义:-)。任何其他想法? – redfoxlee 2012-02-05 10:51:17

+0

@redfoxlee事实上,第二个事务在提交第一个事务时会解锁_exactly_,这表明存在某种锁定。你使用什么存储引擎?我发现[MyISAM](http://dev.mysql.com/doc/refman/5.6/en/internal-locking.html)引擎有一个有趣的引用:_“如果有漏洞,并发插入被禁用但启用当所有的孔都填满了新的数据时,也会自动进行。“_。也许你只是不幸击中这些漏洞?你描述的行为是否一贯发生 - 你测试过多次了吗? – 2012-02-05 12:55:44

+0

嗯,自从我开始以来,我一直不走运......但确定的是我很幸运,因为我使用InnoDB引擎:-)。是的,我多次做了这个测试,每次都会发生:-( – redfoxlee 2012-02-05 15:02:20

相关问题