MySQL FOR UPDATE子句并发问题

时间:2017-03-08 05:58:28

标签: mysql concurrency vb6

我们有一个表,其中包含引用系统处理的每个事务的计数器的记录。

以下是表格的表格定义:

CREATE TABLE `controlnumber` (
  `StoreCode` varchar(10) NOT NULL,
  `TerminalNumber` varchar(10) NOT NULL,
  `TransactionType` varchar(25) NOT NULL,
  `LastSeries` bigint(20) unsigned DEFAULT NULL,
  `Prefix` varchar(10) NOT NULL,
  PRIMARY KEY (`StoreCode`,`TerminalNumber`,`TransactionType`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

表格中的数据样本如下:

+------------+----------------------+------------+
| LastSeries | TransactionType      | StoreCode  |
+------------+----------------------+------------+
|          1 |   Adjustments        | HeadOffice |
|     111982 |   Direct Transfer    | HeadOffice |
|        975 |   Location Transfer  | HeadOffice | 
|       8065 |   Receiving          | HeadOffice |
+------------+----------------------+------------+

创建使用此表的事务时,代码如下:

申请代码(vb6):

connection.BeginTrans
connection.execute("CALL saveReceiving(...)")
connection.execute("UPDATE controlnumber SET lastSeries = lastSeries + 1 WHERE TransactionType = 'Receiving' AND StoreCode = ...")
connection.CommitTrans

SQL代码:

CREATE PROCEDURE saveReceiving(...)
BEGIN
    //The "receiving" table is an InnoDB table
    INSERT INTO receiving (receivingnumber, transactiondate, ...) VALUES (createTransID('Receiving'), NOW(), ...);
END

createTransID MySQL函数的定义如下:

CREATE FUNCTION createTransID(TransactionType VARCHAR(15), pStoreCode VARCHAR(15)) 
 BEGIN

  DECLARE returnValue VARCHAR(45);
  CASE TransactionType
  ....
  WHEN 'Receiving' THEN
    SELECT CONCAT(Prefix,'-', LastSeries + 1) INTO returnValue FROM controlnumber WHERE StoreCode = pStoreCode FOR UPDATE;
  ...
  END

  RETURN returnValue;
 END 

现在我假设在使用FOR UPDATE子句时,我锁定了controlnumber表的记录,没有其他用户可以访问它因此,阻止 多个用户获得相同的lastSeries值。但实际情况是,多个用户可以获得相同的lastSeries值。我在这做错了什么?

  • 服务器:Windows Server 2012 R2上的MySQL 5.7.17
  • ODBC连接器:Windows 10上的MySQL ODBC 3.51.30
  • MySQL配置文件:http://pastebin.com/5HeHDRLe

0 个答案:

没有答案