예제 #1
0
        /// <summary>
        /// Locks matching rows against updates.
        /// </summary>
        /// <param name="lockOption">Optional row <see cref="LockContention">lock option</see> to use.</param>
        /// <returns>This same <see cref="FindStatement"/> object set with the lock shared option.</returns>
        /// <exception cref="MySqlException">The server version is lower than 8.0.3.</exception>
        public FindStatement LockShared(LockContention lockOption = LockContention.Default)
        {
            if (!this.Session.InternalSession.GetServerVersion().isAtLeast(8, 0, 3))
            {
                throw new MySqlException(string.Format(ResourcesX.FunctionalityNotSupported, "8.0.3"));
            }

            findParams.Locking       = Protocol.X.RowLock.SharedLock;
            findParams.LockingOption = lockOption;
            SetChanged();
            return(this);
        }
예제 #2
0
        public void LockExclusiveAndSharedWithWaitingOptions(LockContention lockOption, LockMode lockMode)
        {
            if (!session.XSession.GetServerVersion().isAtLeast(8, 0, 3))
            {
                return;
            }

            CreateBooksTable();
            string tableName  = "books";
            string schemaName = "test";

            // first session locks the row
            using (Session s1 = MySQLX.GetSession(ConnectionString))
            {
                var t1 = s1.GetSchema(schemaName).GetTable(tableName);
                s1.StartTransaction();
                RowResult r1    = ExecuteSelectStatement(t1.Select().Where("id = :id").Bind("id", 1).LockExclusive());
                var       rows1 = r1.FetchAll();
                Assert.That(rows1, Has.One.Items);
                Assert.AreEqual(1, rows1[0]["id"]);

                // second session tries to read the locked row
                using (Session s2 = MySQLX.GetSession(ConnectionString))
                {
                    var t2 = s2.GetSchema(schemaName).GetTable(tableName);
                    ExecuteSQLStatement(s2.SQL("SET innodb_lock_wait_timeout = 1"));
                    s2.StartTransaction();
                    var stmt2 = t2.Select();
                    if (lockMode == LockMode.Exclusive)
                    {
                        stmt2.LockExclusive(lockOption);
                    }
                    else
                    {
                        stmt2.LockShared(lockOption);
                    }

                    switch (lockOption)
                    {
                    case LockContention.Default:
                        // error 1205 Lock wait timeout exceeded; try restarting transaction
                        Assert.AreEqual(1205u, Assert.Throws <MySqlException>(() => ExecuteSelectStatement(stmt2).FetchAll()).Code);
                        break;

                    case LockContention.NoWait:
                        // error 1205 Lock wait timeout exceeded; try restarting transaction
                        uint expectedError = 1205;
                        if (session.XSession.GetServerVersion().isAtLeast(8, 0, 5))
                        {
                            // error 3572 Statement aborted because lock(s) could not be acquired immediately and NOWAIT is set
                            expectedError = 3572;
                        }
                        Assert.AreEqual(expectedError, Assert.Throws <MySqlException>(() => ExecuteSelectStatement(stmt2).FetchAll()).Code);
                        break;

                    case LockContention.SkipLocked:
                        if (!session.XSession.GetServerVersion().isAtLeast(8, 0, 5))
                        {
                            // error 1205 Lock wait timeout exceeded; try restarting transaction
                            Assert.AreEqual(1205u, Assert.Throws <MySqlException>(() => ExecuteSelectStatement(stmt2).FetchAll()).Code);
                            break;
                        }
                        var rows2 = ExecuteSelectStatement(stmt2).FetchAll();
                        Assert.That(rows2, Has.One.Items);
                        Assert.AreEqual(2, rows2[0]["id"]);
                        break;

                    default:
                        throw new NotImplementedException(lockOption.ToString());
                    }
                }
                // first session frees the lock
                s1.Commit();
            }
        }