英文:
IBM Informix: getting 245, 144 error doing a select while another transaction has done an insert - possible bug?
问题
在生产环境中遇到了一个死锁问题。我发现,如果一个事务在我的表中插入一行,而我想要从该表中选择一行完全不同的行,我会收到以下错误:
245: 无法通过索引在文件内定位。
144: ISAM 错误:键值被锁定
第1行错误
接近字符位置70
我的选择语句的形式为select * from table where bar = 3 and foo = "CCCC";
,其中"foo"是指向包含18行的表的外键,而"bar"是第一个表的主键。我的插入语句也插入了一个具有foo = "CCCC"
的行。有趣的是,选择查询在输出错误之前还返回了所需的行。
我在隔离级别设置为可重复读的情况下在Informix 12.10上尝试了所有这些操作。我在生产环境中尝试了它,并在一个只包含两个提到的表的新数据库中进行了设置。两个表的锁定模式都是"row"。
我通过修改选择语句进行了调查:select * from table where bar = 3;
不会失败。另外,select * from table where bar = 3 and foo = "CCCC" order by ber;
也不会失败(其中"ber"是表中的随机字段,"ber"没有索引)。
我期望我尝试的所有选择语句要么都返回所需的行而没有错误,要么都失败。在生产环境中,我的解决方案是按表中的随机字段进行排序,以解决死锁问题。
有人知道为什么会发生这个问题吗?我怀疑与表上的索引有关,这些索引在将主键和外键添加到表时都是自动创建的。但我对索引了解不够,无法理解发生了什么。这可能是一个bug吗?
表的架构:
create table options (
foo char(4) not null,
fee int not null)
extent size 16 next size 16
lock mode row;
alter table options add constraint (
primary key (foo)
constraint cons1 );
create table decisions (
bar char(3) not null,
foo char(4) not null,
ber int not null)
extent size 131072 next size 65536
lock mode row;
alter table decisions add constraint (
primary key (bar)
constraint cons2 );
alter table decisions add constraint (
foreign key (foo) references options(foo)
constraint cons3 );
我插入到"options"表中的数据:
AAAA|0|
BBBB|0|
CCCC|1|
DDDD|4|
EEEE|1|
FFFF|8|
我插入到"decisions"表中的数据:
QWE|AAAA|0|
WER|AAAA|9|
ERT|CCCC|2|
RTY|AAAA|32|
TYU|CCCC|1234|
YUI|CCCC|42398|
UIO|AAAA|23178|
IOP|CCCC|1233|
OPA|CCCC|11|
PAS|AAAA|890|
ASD|AAAA|90|
SDF|CCCC|2|
DFG|AAAA|4|
FGH|CCCC|7|
编辑:我使用了set explain on;
来进行查询。对于select * from decisions where foo = "CCCC" and bar = "QWE" order by foo;
,返回的索引是foo="CCCC"。然而,对于select * from decisions where foo = "CCCC" and bar = "QWE" order by ber;
,它使用的是索引bar="QWE"。
英文:
Encountered this problem in production in the form of a deadlock. Figured out that if a transaction was inserting a row on my table, and I wanted to select a totally different row from that table, I would get the following error:
245: Could not position within a file via an index.
144: ISAM error: key value locked
Error in line 1
Near character position 70
My select statement was of the form select * from table where bar = 3 and foo = "CCCC";
, where "foo" is a foreign key to a table with 18 rows, and "bar" is the first table's primary key. My insert statement was also inserting a row with foo = "CCCC"
. Curiously, the select query also returned the desired row before outputting the error.
I tried all this on informix 12.10 with isolation level set to repeatable read. I tried it on production, and in a fresh DB I set up with only the two tables mentioned. The lock mode of both tables is "row".
I investigated by modifying the select statement: select * from table where bar = 3;
would not fail. Also, select * from table where bar = 3 and foo = "CCCC" order by ber;
would not fail (ber being a random field from the table, ber is not indexed).
I would expect all the select statements I tried to return the desired row without error, OR all of them to fail. My solution in production was to order by a random field in the table, which fixed the deadlock issue
Does anyone know why this issue could have happened ? I suspect it is linked to the indexes on the table, which were all created automatically when adding the primary and foreign keys to the table. But I do not know enough about indexes to understand what happened. Could this be a bug ?
Schema of the tables:
create table options (
foo char(4) not null,
fee int not null)
extent size 16 next size 16
lock mode row;
alter table options add constraint (
primary key (foo)
constraint cons1 );
create table decisions (
bar char(3) not null,
foo char(4) not null,
ber int not null)
extent size 131072 next size 65536
lock mode row;
alter table decisions add constraint (
primary key (bar)
constraint cons2 );
alter table decisions add constraint (
foreign key (foo) references options(foo)
constraint cons3 );
Data I inserted into the "options" table:
AAAA|0|
BBBB|0|
CCCC|1|
DDDD|4|
EEEE|1|
FFFF|8|
Data I inserted into the "decisions" table:
QWE|AAAA|0|
WER|AAAA|9|
ERT|CCCC|2|
RTY|AAAA|32|
TYU|CCCC|1234|
YUI|CCCC|42398|
UIO|AAAA|23178|
IOP|CCCC|1233|
OPA|CCCC|11|
PAS|AAAA|890|
ASD|AAAA|90|
SDF|CCCC|2|
DFG|AAAA|4|
FGH|CCCC|7|
Edit: I used set explain on;
for the queries.
select * from decisions where foo = "CCCC" and bar = "QWE" order by foo;
returned that the index used was on foo="CCCC". However, for select * from decisions where foo = "CCCC" and bar = "QWE" order by ber;
, it's indexed on bar="QWE".
答案1
得分: 2
我把我的问题咨询了更有经验的同事,以下是答案:
当某些操作在事务中更新表中的行时(例如插入一行),插入的值对应的索引键会被锁定。因为我插入了一个 foo="CCCC" 的行,这个键值在 foo 索引中被锁定。然后,当我执行一个选择语句,其中 foo="CCCC" 时,如果该语句使用了 foo 索引,就会出错;而如果使用了其他索引,就会正常工作。
通过使用优化指令,你可以在查询中指定要使用的索引或要避免使用的索引。
我选择的解决方法是首先为我的表定义明确的索引。然后,我使用 AVOID_INDEX 指令来避免 "foo" 索引。
其他解决方法可能包括指定要使用的索引(但我担心选择可能会使用两个索引并仍然遇到 foo 索引的问题);将锁定模式设置为 WAIT X(但由于我是通过死锁来发现问题的,这不会有帮助);或者使用脏读隔离(但这不适用于特定选择的目的)。
在修复后,我再也没有遇到死锁问题。
英文:
I asked my question to more experienced people working with me and here is the answer:
When something updates a row in the table (for example inserting a row) in a transaction the index keys for the values inserted get locked. Since I was inserting a row with foo="CCCC", that key value was locked in the foo index. Then, when I did a select statement where foo="CCCC", when that statement used the foo index, it errored, and when it used another index, it worked.
Using Optimizer Directives, you can specify an index to use in a query or an index to avoid.
The solution I chose was, first, to define explicit indexes for my table. Then, I used the AVOID_INDEX directive to avoid the "foo" index.
Other solutions would have been to specify the index to use instead (but I was worried the select could use two indexes and still encounter the foo index); to set the lock mode to WAIT X (but since I found the issue through deadlocks this wouldn't have helped); or to use isolation dirty read (but this was unwanted for the purpose of that specific select).
Following the fix, I haven't gotten a deadlock yet.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论