选择和更新查询

时间:2016-08-18 01:12:10

标签: c# mysql database

我有一个包含3列复合主键的表:key1,key2和key3

我有另一个名为'Order'的列,它跟踪数据库中项目的顺序。每次将项目添加到数据库时,我都必须确保“Order”列具有最高值(对于key1和key2定义的同一组)。例如:

key1 | key2 | key3 | order
--------------------------
1    | 2    | 10   | 0
1    | 2    | 11   | 10
1    | 2    | 12   | 20
1    | 2    | 13   | 30

现在,如果我必须添加一个新项目(1,2,14),那么订单必须大于30,以便该项目添加列表的末尾。 用户还可以对项目进行重新排序,这意味着我可以修改(1,2,12)的“订单”列,使其值为-10,并将其置于列表的顶部。

在我们同时向表中添加项目之前,这一切都很好。我必须确保同一组中的项目的“Order”值不重复(key1和key2的值相等的项目)。

因此,我添加新项目的SQL代码如下所示:

START TRANSACTION;
INSERT INTO table_name VALUES (1, 2, 14, null);

UPDATE table_name SET `Order`=
(
    SELECT * FROM (SELECT COALESCE((SELECT MAX(`Order)
        FROM table_name
        WHERE `key1`=1 AND `key2`=2), 0)+10) a
) where `key1`=1 AND `key2`=2 AND `key3`=14;
COMMIT;

上述事务使用C#代码运行。在插入和更新之间,C#代码检查是否需要计算Order列。例如,对于key1 = 1和key2 = 2的组合,我们可能需要计算Order而不是组合key = 1和key2 = 3并将其保留为null。这就是为什么insert sql不计算Order列并将其保留为null的原因。

现在的问题是,它在我尝试同时添加大量记录之前一直很安静。我有一个同时发送20个项目的程序,并不是所有项目都成功添加到数据库中,因为它在update语句中死锁。

任何人都可以建议我一些方法来防止僵局,或者更好的设计。

由于

修改

在插入时尝试计算订单,但我现在在插入时遇到死锁。 我的插入基本上看起来像:

INSERT INTO table_name VALUES (1, 2, 14, (SELECT * FROM (SELECT COALESCE((SELECT MAX(Order) FROM table_name WHERE key1=1 AND key2`=2), 0)+10) a));

修改

所以这是我做的日志:SHOW ENGINE INNODB STATUS;

2016-08-19 09:38:08 15fc
*** (1) TRANSACTION:
TRANSACTION 2764458, ACTIVE 0 sec starting index read
mysql tables in use 3, locked 3
LOCK WAIT 9 lock struct(s), heap size 2936, 6 row lock(s), undo log entries 1
MySQL thread id 1780, OS thread handle 0x5508, query id 85256 localhost ::1 root Sending data
UPDATE table_name SET `Order`=
                     (
                        SELECT * FROM (SELECT COALESCE((SELECT MAX(`Order`) 
                            FROM table_name
                            WHERE `key1`=164420 AND `key2`=2), 0)+4294967296) c
                     )
                     WHERE `key1`=164420 AND `key2`=2 AND `key3`=3368
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 167 page no 1939 n bits 352 index `PRIMARY` of table `table_name` trx table locks 3 total table locks 2  trx id 2764458 lock mode S waiting lock hold time 0 wait time before grant 0 
*** (2) TRANSACTION:
TRANSACTION 2764459, ACTIVE 0 sec fetching rows
mysql tables in use 3, locked 3
11 lock struct(s), heap size 2936, 23 row lock(s), undo log entries 1
MySQL thread id 1782, OS thread handle 0x15fc, query id 85259 localhost ::1 root Sending data
UPDATE table_name SET `Order`=
                     (
                        SELECT * FROM (SELECT COALESCE((SELECT MAX(`Order`) 
                            FROM table_name
                            WHERE `key1`=164420 AND `key2`=2), 0)+4294967296) c
                     )
                     WHERE `key1`=164420 AND `key2`=2 AND `key3`=3338
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 167 page no 1939 n bits 352 index `PRIMARY` of table `table_name` trx table locks 3 total table locks 2  trx id 2764459 lock_mode X locks rec but not gap lock hold time 0 wait time before grant 0 
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 167 page no 1939 n bits 352 index `PRIMARY` of table `table_name` trx table locks 3 total table locks 2  trx id 2764459 lock mode S waiting lock hold time 0 wait time before grant 0 
*** WE ROLL BACK TRANSACTION (1)

0 个答案:

没有答案