go-xorm mysqlロックテスト
6219 ワード
mysqlデータベーススクリプト
テスト1
for updateの条件はbalance=8888 balance非索則テーブルレベルロックです
実行結果:[xorm][info]2019/09/15 20:33:33.212445[SQL]BEGIN TRANSACTION[xorm][info]2019/09/15 20:33:33.212653[SQL]select*from user where balance=8888 for update[xorm][info]2019/09/15 20:33:33.3.216061[SQL]UPDATE`user`SET`balance`=?WHERE (id = ?) []interface {}{88837, 1} [xorm] [info] 2019/09/15 20:33:35.207591 [SQL] update user set name = ?, balance = ? where id = ? []interface{}{"12313",9999,2}[xorm][info]2019/09/15 20:33:53.222873[SQL]COMMIT実行COMMITがCOMMITの前にロックされていない
テスト2
for updateは使用されていませんが、トランザクションの条件はプライマリ・キーIDが1で、TestUpdateVersion関数が更新したのはIDが1で、ロックがあります
[xorm] [info] 2019/09/15 20:35:09.674575 [SQL] BEGIN TRANSACTION [xorm] [info] 2019/09/15 20:35:09.674927 [SQL] UPDATE `user` SET `balance` = ? WHERE (id = ?) []interface {}{88837, 1} [xorm] [info] 2019/09/15 20:35:11.669606 [SQL] update user set name = ?, balance = ? where id = ? []interface{}{"12313",9999,1}[xorm][info]2019/09/15 20:35:29.679462[SQL]COMMIT実行COMMIT前はロックされていません
テスト3
for updateは使用されず、トランザクション条件IDは1、TestUpdateVersion関数はID 2のデータを更新し、ID 2のデータはロックされていないので、トランザクション条件は文であり、行レベルロックである
[xorm] [info] 2019/09/15 20:38:23.217078 [SQL] BEGIN TRANSACTION [xorm] [info] 2019/09/15 20:38:23.217437 [SQL] UPDATE `user` SET `balance` = ? WHERE (id = ?) []interface {}{88837, 1} [xorm] [info] 2019/09/15 20:38:25.207137 [SQL] update user set name = ?, balance = ? where id = ? []interface{}{"12313",9999,2}実行COMMITの前にロックされていない[xorm][info]2019/09/15 20:38:43.221392[SQL]COMMIT
テスト4
for update条件はid=2で、トランザクション内のupdate条件id=1で、結果的にロックが発生するので、for update条件がインデックスであればロック行
[xorm] [info] 2019/09/15 20:41:29.932293 [SQL] BEGIN TRANSACTION [xorm] [info] 2019/09/15 20:41:29.932448 [SQL] select * from user where id = 2 for update [xorm] [info] 2019/09/15 20:41:29.933547 [SQL] UPDATE `user` SET `balance` = ? WHERE (id = ?) []interface {}{88837, 1} [xorm] [info] 2019/09/15 20:41:31.925843 [SQL] update user set name = ?, balance = ? where id = ? []interface{}{"12313",9999,1}[xorm][info]2019/09/15 20:41:49.939323[SQL]COMMIT実行COMMIT前はロックされていません
テスト5
トランザクションではbalance=9999.00をid 1として使用します.balanceはインデックスではなく、ロックがあります(表レベルのロック)
[xorm] [info] 2019/09/15 20:54:48.451605 [SQL] BEGIN TRANSACTION [xorm] [info] 2019/09/15 20:54:48.451942 [SQL] UPDATE `user` SET `balance` = ? WHERE (balance = ?) []interface {}{88837, 9999} [xorm] [info] 2019/09/15 20:54:50.448837 [SQL] update user set name = ?, balance = ? where id = ? []interface{}{"12313",9999,2}[xorm][info]2019/09/15 20:55:08.457835[SQL]COMMIT実行COMMIT前はロックなし
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`balance` decimal(10,2) NOT NULL DEFAULT '0.00',
`version` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `idx_name` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4;
-- ----------------------------
-- Records of `user`
-- ----------------------------
BEGIN;
INSERT INTO `user` VALUES ('1', '12313', '9999.00', '1'), ('2', '12313', '9999.00', '2');
COMMIT;
テスト1
for updateの条件はbalance=8888 balance非索則テーブルレベルロックです
package main
import (
"fmt"
"game_server/log"
_ "github.com/go-sql-driver/mysql"
"github.com/go-xorm/xorm"
"time"
)
type (
User struct {
Id int64
Name string `xorm:"varchar(255) notnull 'name'"`
Balance float32 `xorm:"float notnull 'balance'"`
//Version int `xorm:"version"`
}
)
var (
mysqlEngine *xorm.Engine
err error
)
func main() {
mysqlEngine, err = xorm.NewEngine("mysql", "root:123456@tcp(localhost:3306)/test?charset=utf8")
if err != nil {
log.Fatal("init mysql failed [%+v]", err)
}
mysqlEngine.ShowSQL(true)
go TestTransaction()
time.Sleep(2 * time.Second)
user := new(User)
user.Id = 2
user.Name = "12313"
user.Balance = 9999
go TestUpdate(user)
time.Sleep(30 * time.Second)
}
func TestTransaction() {
session := mysqlEngine.NewSession()
defer session.Close()
err = session.Begin()
if err != nil {
panic(err)
}
session.Query("select * from user where balance = 8888 for update")
//session.Where("balance = ?", 8888).ForUpdate() //
session.Where("id = ?", 1).Update(&User{
Balance: 88837,
})
time.Sleep(20 * time.Second)
session.Commit()
}
func TestUpdate(user *User) {
// context
//ctx,cancelFunc := context.WithTimeout(context.TODO(), 5*time.Second)
//defer cancelFunc()
//affected, err := mysqlEngine.Context(ctx).Exec("update user set name = ?, balance = ? where id = ?", user.Name, user.Balance, user.Id)
//fmt.Printf("######## %#v, %+v
", affected, err)
//cancelFunc()
//
mysqlEngine.Exec("update user set name = ?, balance = ? where id = ?", user.Name, user.Balance, user.Id)
fmt.Printf(" COMMIT
")
}
実行結果:[xorm][info]2019/09/15 20:33:33.212445[SQL]BEGIN TRANSACTION[xorm][info]2019/09/15 20:33:33.212653[SQL]select*from user where balance=8888 for update[xorm][info]2019/09/15 20:33:33.3.216061[SQL]UPDATE`user`SET`balance`=?WHERE (id = ?) []interface {}{88837, 1} [xorm] [info] 2019/09/15 20:33:35.207591 [SQL] update user set name = ?, balance = ? where id = ? []interface{}{"12313",9999,2}[xorm][info]2019/09/15 20:33:53.222873[SQL]COMMIT実行COMMITがCOMMITの前にロックされていない
テスト2
for updateは使用されていませんが、トランザクションの条件はプライマリ・キーIDが1で、TestUpdateVersion関数が更新したのはIDが1で、ロックがあります
func main() {
user := new(User)
user.Id = 1
user.Name = "12313"
user.Balance = 9999
}
func TestTransaction() {
....
session.Where("id = ?", 1).Update(&User{
Balance: 88837,
})
...
}
[xorm] [info] 2019/09/15 20:35:09.674575 [SQL] BEGIN TRANSACTION [xorm] [info] 2019/09/15 20:35:09.674927 [SQL] UPDATE `user` SET `balance` = ? WHERE (id = ?) []interface {}{88837, 1} [xorm] [info] 2019/09/15 20:35:11.669606 [SQL] update user set name = ?, balance = ? where id = ? []interface{}{"12313",9999,1}[xorm][info]2019/09/15 20:35:29.679462[SQL]COMMIT実行COMMIT前はロックされていません
テスト3
for updateは使用されず、トランザクション条件IDは1、TestUpdateVersion関数はID 2のデータを更新し、ID 2のデータはロックされていないので、トランザクション条件は文であり、行レベルロックである
func main() {
user := new(User)
user.Id = 2
user.Name = "12313"
user.Balance = 9999
}
func TestTransaction() {
....
session.Where("id = ?", 1).Update(&User{
Balance: 88837,
})
...
}
[xorm] [info] 2019/09/15 20:38:23.217078 [SQL] BEGIN TRANSACTION [xorm] [info] 2019/09/15 20:38:23.217437 [SQL] UPDATE `user` SET `balance` = ? WHERE (id = ?) []interface {}{88837, 1} [xorm] [info] 2019/09/15 20:38:25.207137 [SQL] update user set name = ?, balance = ? where id = ? []interface{}{"12313",9999,2}実行COMMITの前にロックされていない[xorm][info]2019/09/15 20:38:43.221392[SQL]COMMIT
テスト4
for update条件はid=2で、トランザクション内のupdate条件id=1で、結果的にロックが発生するので、for update条件がインデックスであればロック行
func main() {
...
user := new(User)
user.Id = 2
user.Name = "12313"
user.Balance = 9999
...
}
func TestTransaction() {
...
session.Query("select * from user where id = 2 for update")
session.Where("id = ?", 1).Update(&User{
Balance: 88837,
})
...
}
[xorm] [info] 2019/09/15 20:41:29.932293 [SQL] BEGIN TRANSACTION [xorm] [info] 2019/09/15 20:41:29.932448 [SQL] select * from user where id = 2 for update [xorm] [info] 2019/09/15 20:41:29.933547 [SQL] UPDATE `user` SET `balance` = ? WHERE (id = ?) []interface {}{88837, 1} [xorm] [info] 2019/09/15 20:41:31.925843 [SQL] update user set name = ?, balance = ? where id = ? []interface{}{"12313",9999,1}[xorm][info]2019/09/15 20:41:49.939323[SQL]COMMIT実行COMMIT前はロックされていません
テスト5
トランザクションではbalance=9999.00をid 1として使用します.balanceはインデックスではなく、ロックがあります(表レベルのロック)
func main() {
...
user := new(User)
user.Id = 2
user.Name = "12313"
user.Balance = 9999
...
}
func TestTransaction() {
...
session.Where("balance = ?", 9999.00).Update(&User{
Balance: 88837,
})
...
}
[xorm] [info] 2019/09/15 20:54:48.451605 [SQL] BEGIN TRANSACTION [xorm] [info] 2019/09/15 20:54:48.451942 [SQL] UPDATE `user` SET `balance` = ? WHERE (balance = ?) []interface {}{88837, 9999} [xorm] [info] 2019/09/15 20:54:50.448837 [SQL] update user set name = ?, balance = ? where id = ? []interface{}{"12313",9999,2}[xorm][info]2019/09/15 20:55:08.457835[SQL]COMMIT実行COMMIT前はロックなし