使用索引列和非索引列来更新来自不同事务的数据有什么区别?

时间:2012-02-05 06:31:33

标签: mysql sql transactions transactional

我之前使用交易时遇到了一些问题。希望有人能帮助我弄明白。我会感激任何帮助。谢谢。

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. 在D
  2. 执行method1()并break(在eclipse中设置断点)
  3. 执行method2()并发
  4. 请注意,“someid”不在索引中,但它与“id”完全相同地存储相同的数据。

    然后我什么也没有,只要我不提交transaction1或者最终它将以事务超时结束。但是,如果我将where子句更改为 F 的id = 1,它将正常工作而无需任何等待。在这里我感到困惑,因为我没有锁定那个表或任何行。如果我这样做了,就不应该这样做,对吗?

    有谁能告诉我为什么会发生这种情况?谢谢!

2 个答案:

答案 0 :(得分:1)

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

在id = 1的情况下,dbs可以确定只有一行受到法规F的影响。插入语句不会更改此行。

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

答案 1 :(得分:1)

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

只有在第一笔交易完成后,第二笔交易才会继续,并且:

  • 更新行(如果提交了第一个事务)
  • 或不更新行(如果第一个事务回滚,那么实际上没有插入行。)

问题是:为什么索引id也不会发生?您确定在事务中使用了与someid相同的值吗?您是否更改了两个交易的WHERE条款?