2

サービスへの 2 つの同時リクエストが実際には同じ DB 接続を使用しているという奇妙な問題が発生したようです。

私たちのセットアップは ServiceStack + NHibernate + FluentNHibernate + MySQL です。問題を再現する小さなテストをセットアップしました。

public class AppHost : AppHostBase
{
    private ISessionFactory _sessionFactory;

    public AppHost() : base("Lala Service", typeof(AppHost).Assembly)
    {
    }

    public override void Configure(Container container)
    {
        _sessionFactory = Fluently.Configure()

            .Database(MySQLConfiguration.Standard.ConnectionString(conn =>
                conn.Server("localhost").Username("lala").Password("lala").Database("lala")))

            .Mappings(mappings => mappings.AutoMappings.Add(
                AutoMap.Assembly(GetType().Assembly).Where(t => t == typeof(Lala))
                       .Conventions.Add(DefaultLazy.Never(), DefaultCascade.All())))

        .BuildSessionFactory();

        container.Register(c => _sessionFactory.OpenSession()).ReusedWithin(ReuseScope.Request);
    }
}

public class Lala
{
    public int    ID   { get; set; }
    public string Name { get; set; }
}

[Route("/lala")]
public class LalaRequest
{
}

public class LalaReseponse
{
}

public class LalaService : Service
{
    private ISession _session;

    public ISession Session1
    {
        get { return _session; }
        set { _session = value; }
    }

    public LalaReseponse Get(LalaRequest request)
    {
        var lala = new Lala
        {
            Name = Guid.NewGuid().ToString()
        };

        _session.Persist(lala);
        _session.Flush();

        lala.Name += " XXX";

        _session.Flush();

        return new LalaReseponse();
    }
}

次のように、Ajaxを介してこのサービスを同時に10回ヒットしました。

    <script type="text/javascript">
        for (i = 0; i < 10; i++) {
            console.log("aa");
            $.ajax({
                url:      '/lala',
                dataType: 'json',
                cache:    false
            });
        }
    </script>

結果は一貫して次のとおりです。

  1. 開いている接続の数 < 10。
  2. すべてのレコードが更新されたわけではありません。
  3. ときどき -StaleObjectStateExceptionスロー - レコードを削除すると。

この背後にある理由は、接続が 2 つの同時要求によって再利用され、LAST_INSERT_ID() が間違った行の ID を与えるため、2 つの要求が同じ行を更新しているためです。

要するに、それは完全な混乱であり、リクエスト間で DB 接続を明らかに共有しています。

質問は次のとおりです。なぜですか。各リクエストが接続プールから独自の接続を取得するようにするには、どのように構成すればよいですか?

4

1 に答える 1