首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >结果集中的SQL联接是否一致?

结果集中的SQL联接是否一致?
EN

Stack Overflow用户
提问于 2014-12-01 05:28:25
回答 2查看 103关注 0票数 0

我觉得自己有点像个白痴,因为我不知道这里该用什么术语。所以让我试着画出我能画的最好的画面。如果我把两个表和一个连接在一起

select t1.prop, t2.prop from t1 join t2 on t1.prop = t2.prop

t1.prop并不是唯一的,假设其中有两个,t2.prop是唯一的,有没有可能中间查询计算t2.prop被填充在其中一个,而不是另一个呢?在我的头脑中,我无法想象,我假设它会找到t2.prop的所有结果,然后将它应用到结果中。

所以如果答案是否定的,那么也许有人可以指出我在这里遗漏的一个可能的东西,我正在试图修复一个队列表,幸运的是我看到了某种种族状况。我把范围缩小到上面的语句(我不相信这一点),或者查询是基于锁定提示跳过项,或者是脏读(已提交隔离级别),或者我很困惑。

这是基本的工作流程。

  1. 在任何时候,都会使用大容量复制(SQLBulkCopy .net)将一大块项推入队列,并且它位于事务中,并使用时间戳提交(也只有一个线程正在填充该队列,因此实际上在任何时候,可能都有一个线程正在执行此操作)。
  2. 只有一个使用者正在使用如下所示的查询主动地扫描队列 在Q.Prop = t.Prop order by Q.Timestamp上,从队列Q中选择Q* with(rowlock,updlock,nowait)连接表t;

我的假设是,这将返回队列中按时间戳排序的最古老的已提交项(其中有一次,我在这里重新读过了,但我担心这可能会使我出现问题,我还随机地尝试了tablock,并将表锁定在insert上,但这并没有什么区别)。

因此,我的问题是,我一直让单个t.Prop的项目被按顺序处理。

我增加了触发器,显示项目时间戳在其他项目时间戳之前,但是它们被按错误的顺序读取掉队列。有什么提示或帮助吗?

更新

我证明了我能够得到一个局部的结果集,在这里我可以期望所有或什么都没有。

代码语言:javascript
运行
复制
private static void OutOfOrder()
{
    var cnt = 100;
    var go = true;
    using (var db = new DBManager())
    {
        using (var cmd = db.GetCommand())
        {
            cmd.CommandText = "Delete from Foo";
            cmd.ExecuteNonQuery();
            cmd.CommandText = "Delete from Bar";
            cmd.ExecuteNonQuery();

            cmd.CommandText = "Insert Into Foo (B) Values ('joint')";
            for (var i = 0; i < cnt; i++)
            {
                cmd.ExecuteNonQuery();
            }
        }
    }

    var task1 = Task.Run(() =>
    {
        var inserted = false;
        while (go)
        {
            using (var db = new DBManager())
            {
                using (var cmd = db.GetCommand())
                {
                    var text = inserted ? "Delete from Bar" : "Insert Into Bar (B, C) Values ('joint', 'blah')";
                    cmd.CommandText = text;
                    Console.WriteLine(DateTime.Now.ToLongTimeString() + "  -  " + text);
                    cmd.ExecuteNonQuery();
                    inserted = !inserted;
                }
            }
            Thread.Sleep(20);
        }
    });


    var task2 = Task.Run(() =>
    {
        var text = "Select * from Foo join Bar on Foo.B = Bar.B";
        while (go)
        {
            using (var db = new DBManager())
            {
                using (var cmd = db.GetCommand())
                {
                    cmd.CommandText = text;
                    Console.WriteLine(DateTime.Now.ToLongTimeString() + "  -  " + text);
                    var ret = cmd.ExecuteDataTable();
                    var retCount = ret.Rows.Count;
                    var valid = retCount == 0 || retCount == 100;

                    if (!valid)
                    {
                        Console.WriteLine("Error, got {0} rows back!!!", ret.Rows.Count);
                        go = false;
                    }
                }
            }
            Thread.Sleep(17);
        }
    });
}

我可以使用inner hash join将其变为全部或全部为零,但在另一个注意事项上,我可能尝试使用快照隔离级别。

EN

Stack Overflow用户

发布于 2014-12-01 10:30:53

要么在读取器中使用脏读(read uncommitted),要么批量复制不使用事务。检查两者都很容易:

代码语言:javascript
运行
复制
SELECT Q.* from Queue Q with(rowlock, updlock, nowait, readcommitted) 
  left join table t on Q.Prop = t.Prop
order by Q.Timestamp;

(尽管就我个人而言,我不会依赖nowait提示并添加了一个显式的where)。

可以很容易地跟踪后者。您不必在跟踪中包含所有块-只需添加与事务相关的事件即可。

尽管实现队列的最佳方法是使用队列。例如,Service队列。

票数 0
EN
查看全部 2 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27222206

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档