go-gorm / gorm

The fantastic ORM library for Golang, aims to be developer friendly
https://gorm.io
MIT License
36.96k stars 3.93k forks source link

Transaction update RowsAffected is 0 #2038

Closed aimuz closed 4 years ago

aimuz commented 6 years ago

Transaction update RowsAffected is 0

Just like the following code, when it updates, RowsAffected is 0

What version of Go are you using (go version)?

go version go1.10.3 darwin/amd64

Which database and its version are you using?

mysql 5.7

package main

import (
    "github.com/jinzhu/gorm"
    _ "github.com/jinzhu/gorm/dialects/mysql"
    "log"
)

var db *gorm.DB

func init() {
    var err error
    db, err = gorm.Open("mysql", "gorm:gorm@tcp(localhost:9910)/gorm?charset=utf8&parseTime=True")
    if err != nil {
        panic(err)
    }
    db.LogMode(true)
}

type UserTest struct {
    gorm.Model

    Name     string
    Password string
}

func main() {
    ret := db.AutoMigrate(&UserTest{})
    if ret.Error != nil {
        log.Fatal(ret.Error)
    }

    user := &UserTest{
        Name:     "5",
        Password: "2",
    }
    ret = db.Model(&UserTest{}).Create(user)
    if ret.Error != nil {
        log.Fatal(ret.Error)
    }

    var users []UserTest
    ret = db.Model(&UserTest{}).Find(&users)
    if ret.Error != nil {
        log.Fatal(ret.Error)
        return
    }

    for _, v := range users {
        log.Println(v.Name, v.Password)
    }

    tx := db.Begin()

    ret = tx.Table("user_tests").Where("name = ?", "5").Updates(map[string]interface{}{
        "password": "12345",
    })
    if ret.Error != nil {
        log.Fatal(ret.Error)
        tx.Rollback()
        return
    }
    log.Println(ret.RowsAffected)

    ret = tx.Table("user_tests").Where("name = ?", "4").Updates(map[string]interface{}{
        "password": "44444",
    })
    if ret.Error != nil {
        log.Fatal(ret.Error)
        tx.Rollback()
        return
    }
    log.Println(ret.RowsAffected)
    tx.Commit()

    // 重新查
    ret = db.Model(&UserTest{}).Find(&users)
    if ret.Error != nil {
        log.Fatal(ret.Error)
        return
    }
    for _, v := range users {
        log.Println(v.Name, v.Password)
    }
}
wx20180815-105911 2x
pedromorgan commented 6 years ago

I can't see what the problem (but am stupid), can u provide more detail if possible..

Is this a bug?

aimuz commented 6 years ago

Yes, I think it's a Bug, and this bug's problem leads to the fact that when you update a record the same as a database, you don't get a return record.

aimuz commented 6 years ago

The most important thing is that this Bug's lead occurs only when the transaction occurs, and when the update command is executed separately, the number of rows that can be updated is obtained. I'm puzzled

alicksnake22 commented 5 years ago

@aimuz no data with name = 4

gozelus commented 5 years ago

I got the same problem. I find the affected in db debug log is right

UPDATE `orders` SET `status` = 2, `updated_at` = '2019-07-11 19:08:08'  WHERE (order_no = 155765990288785421 and status = 1)  
[1 rows affected or returned ] 

But zero (not right) in return:

tx.Model(&tradeModel.Order{}).
        Where("order_no = ? and status = ?", orderNo, int16(pb.OrderStatus_OrderStatusWaitConfirm)).
        Update("status", int16(status))
log.Println(tx.RowsAffected) // is zero 
aimuz commented 5 years ago

I don't know if this project is stopped.

kutysam commented 5 years ago

This is affecting me too. Even for delete within a transaction.

caojunxyz commented 4 years ago

I got the same problem

AlessandroSechi commented 4 years ago

Same problem also for me on go version go1.13.1 linux/amd64 and github.com/jinzhu/gorm v1.9.11

bluebrown commented 4 years ago

i have the same. db log says one row affected but db.AffectedRows is zero.

BeatsKitano commented 4 years ago

serious bug

seon1-kim commented 4 years ago

this issue isn't solved? I have same issue. So I tried to send query at mysql cli, is working(value updated and rows affected is correct).

aimuz commented 4 years ago

Yes, it hasn't been solved yet

CHURLZ commented 4 years ago

For others coming to this thread, I could verify this works for sqlite3 and postgres.

if ret.RowsAffected == 0 {
    tx.Rollback()
    return fmt.Errorf("no record found for id %s and status CREATED", _feedback.Id)
} else if ret.RowsAffected > 1 {
    tx.Rollback()
    return fmt.Errorf("update affected %d rows, maximum allowed = 1", ret.RowsAffected)
}
eruca commented 4 years ago

me too

yiippee commented 4 years ago

have plan to fix this bug? or there is aother way to know the RowsAffected. Thanks a lot.

ovdmar commented 4 years ago

It happened to me too.

Bulesxz commented 4 years ago

image

Your question does not match your description

Bulesxz commented 4 years ago

I got the same problem. I find the affected in db debug log is right

UPDATE `orders` SET `status` = 2, `updated_at` = '2019-07-11 19:08:08'  WHERE (order_no = 155765990288785421 and status = 1)  
[1 rows affected or returned ] 

But zero (not right) in return:

tx.Model(&tradeModel.Order{}).
      Where("order_no = ? and status = ?", orderNo, int16(pb.OrderStatus_OrderStatusWaitConfirm)).
      Update("status", int16(status))
log.Println(tx.RowsAffected) // is zero 

tx.RowsAffected Incorrect usage

ret = tx.Model(&tradeModel.Order{}). Where("order_no = ? and status = ?", orderNo, int16(pb.OrderStatus_OrderStatusWaitConfirm)). Update("status", int16(status)) log.Println(ret.RowsAffected)

ret.RowsAffected != tx.RowsAffected

Bulesxz commented 4 years ago

tx.RowsAffected Incorrect usage tx not RowsAffected

aimuz commented 4 years ago

tx.RowsAffected Incorrect usage tx not RowsAffected

So how to use it

It seems that I'm not alone in this problem

Bulesxz commented 4 years ago

tx.RowsAffected Incorrect usage tx not RowsAffected

So how to use it

It seems that I'm not alone in this problem

tx.RowsAffected Incorrect usage

ret = tx.Model(&tradeModel.Order{}). Where("order_no = ? and status = ?", orderNo, int16(pb.OrderStatus_OrderStatusWaitConfirm)). Update("status", int16(status)) log.Println(ret.RowsAffected)

ret.RowsAffected != tx.RowsAffected

ret replace tx

aimuz commented 4 years ago

tx.RowsAffected Incorrect usage tx not RowsAffected

So how to use it It seems that I'm not alone in this problem

tx.RowsAffected Incorrect usage

ret = tx.Model(&tradeModel.Order{}). Where("order_no = ? and status = ?", orderNo, int16(pb.OrderStatus_OrderStatusWaitConfirm)). Update("status", int16(status)) log.Println(ret.RowsAffected)

ret.RowsAffected != tx.RowsAffected

ret replace tx

I don't think you understand me

Although I haven't used it for a long time, by checking my history

There are two updates in the transaction. The first update can get the rowsaffected, while the second update cannot get the correct rowsaffected

If I were to ask questions at that time, I might have more details.

Bulesxz commented 4 years ago

tx.RowsAffected Incorrect usage tx not RowsAffected

So how to use it It seems that I'm not alone in this problem

tx.RowsAffected Incorrect usage ret = tx.Model(&tradeModel.Order{}). Where("order_no = ? and status = ?", orderNo, int16(pb.OrderStatus_OrderStatusWaitConfirm)). Update("status", int16(status)) log.Println(ret.RowsAffected) ret.RowsAffected != tx.RowsAffected ret replace tx

I don't think you understand me

Although I haven't used it for a long time, by checking my history

There are two updates in the transaction. The first update can get the rowsaffected, while the second update cannot get the correct rowsaffected

If I were to ask questions at that time, I might have more details.

image

从你的截图里面看,是你使用的方法不对 不能使用 tx.RowsAffected 这个是个全局的,应该使用ret.RowsAffected (ret 是每一次操作单独调用结果)

zhoulin1359 commented 2 years ago

{"cost":0.003117164,"file":"/www/host/blockchain-price/src/infra/repo/currency_repo.go:77","level":"info","msg":"","request_id":"iZwz9heg0pec2ut18ixomcZ.1663682053.1572222602964398080","rows":0,"sql":"UPDATEcurrencySETday_change=-4.930000,day_change_amount=-0.084000,high_price=1.920000,low_price=1.583000,price=1.620000,update_time='2022-09-20 21:54:14.409' WHEREsymbol= 'NEBL'","time":"2022-09-20T21:54:14+08:00"} {"cost":0.003309807,"file":"/www/host/blockchain-price/src/infra/repo/currency_repo.go:77","level":"info","msg":"","request_id":"iZwz9heg0pec2ut18ixomcZ.1663682052.1572222599189524480","rows":1,"sql":"UPDATEcurrencySETday_change=-4.930000,day_change_amount=-0.084000,high_price=1.920000,low_price=1.583000,price=1.620000,update_time='2022-09-20 21:54:13.595' WHEREsymbol= 'NEBL'","time":"2022-09-20T21:54:13+08:00"}

这是我日志记录的sql,第一个记得rows为0,第二个记录rows为1,这区间数据库没有任何改动,加上 update_time 是为了保证数据库有值就一定变更,结果是数据库变更了,RowsAffected还是为0

davenewza commented 2 years ago

I am also experiencing this issue.

akshay-pj-open commented 1 year ago

I'm also facing this issue, even though it actually inserts the records. Kindly note that for me this bug arises only during batch inserts.

LemonNekoGH commented 1 year ago

tx.RowsAffected Incorrect usage tx not RowsAffected

So how to use it It seems that I'm not alone in this problem

tx.RowsAffected Incorrect usage ret = tx.Model(&tradeModel.Order{}). Where("order_no = ? and status = ?", orderNo, int16(pb.OrderStatus_OrderStatusWaitConfirm)). Update("status", int16(status)) log.Println(ret.RowsAffected) ret.RowsAffected != tx.RowsAffected ret replace tx

I don't think you understand me Although I haven't used it for a long time, by checking my history There are two updates in the transaction. The first update can get the rowsaffected, while the second update cannot get the correct rowsaffected If I were to ask questions at that time, I might have more details.

image

从你的截图里面看,是你使用的方法不对 不能使用 tx.RowsAffected 这个是个全局的,应该使用ret.RowsAffected (ret 是每一次操作单独调用结果)

谢谢,解决了 Issue solved, thank you

Fantomo commented 7 months ago

It’s 2024 and this bug hasn’t been solved yet

rea1shane commented 6 months ago

When I run

// gorm gen query
d := query.Day
info, err := d.Where(d.ID.Eq(1)).Update(d.Status, 1)

sometimes info.RowsAffected is 1, sometimes is 0. But even though the value is 0, the database is updated successfully.

strconv commented 2 weeks ago
//  wrong case
tx := xx.Begin()
tx.Update(xx).Error
fmt.Println(tx.RowsAffected)   // result is 0

// correct case
tx := xx.Begin()
db := tx.Update(xx)
fmt.Println(db.RowsAffected)   // result is n