批量调用过程中重复的条目

时间:2014-07-10 12:56:31

标签: mysql google-app-engine google-cloud-sql

我有一个基本上看起来像这样的存储过程:

do_insert (IN in_x varchar(64), IN in_y varchar(64))
BEGIN
                declare v_x int(20) unsigned default -1;
                declare v_y int(20) unsigned default -1;

                select x into v_x from xs where x_col = in_x;

                if v_x = 0
                then
                    insert into xs (x_col) values(in_x);
                    select x into v_x from xs where x_col = in_x;
                end if;

                select y into v_y from ys where y_col = in_y;

                if v_y = 0
                then
                    insert into ys (y_col) values(in_y);
                    select y into v_y from ys where y_col = in_y;
                end if;

                insert ignore into unique_table (xId, yId) values(v_x, v_y);
END

基本上我看看我是否已经在各自的表中定义了varchars,如果是,我选择了id。如果没有,那么我创建它们并获取它们的ID。然后我将它们插入unique_table忽略它们是否已经存在。 (是的,我可能会在那里放更多的逻辑而不必进行最后的插入,但这不应该是一个问题并且KISS。)

我遇到的问题是,当我使用Google Cloud SQL在批处理JDBC语句中运行它时,我会在我的xs表中插入重复的条目。下次运行此存储过程时,我得到以下异常:

java.sql.SQLException: Result consisted of more than one row Query: call do_insert(:x, :y)

所以我认为正在发生的是在同一个批处理语句中发生了两个具有相同in_x值的调用。这两个调用是并行运行的,两个选择都返回0,因为它是一个新条目,然后它们都进行插入。然后下一次运行失败。

问题:

  • 如何防止这种情况?
  • 我应该将{select(和可能的插入)调用包装在该表的LOCK TABLE中以防止这种情况发生吗?
  • 我在本地MySQL上从未注意到这一点,Google Cloud SQL是否具体?或者只是我在当地的MySQL上看不到的侥幸?

1 个答案:

答案 0 :(得分:0)

我还没有测试过这个,但我猜测批处理语句引入了一定程度的并行性。所以'select x into v_x'语句可以与'insert into vx'语句竞争,允许后者执行多次。

尝试将'insert into xs'语句更改为'insert ignore'并在列上添加唯一索引。