tgulacsi / goracle

cx_Oracle translation for Oracle access
Other
47 stars 16 forks source link

cgo error or something else? #21

Open ghost opened 10 years ago

ghost commented 10 years ago

Hi, I am using oracle times ten database and my code is as follow:

func main() {
        godrv.SetAutoCommit(false)
        db, err := sql.Open("goracle", os.Getenv("ORACLE_DSN"))
        if err != nil {
                log.Println(err)
                os.Exit(1)
        }
        db.SetMaxOpenConns(128)
        db.SetMaxIdleConns(64)
        // 10 go routine insert
        runtime.GOMAXPROCS(4)
        var wg sync.WaitGroup
        log.Println(time.Now())
        var numInsert = 2500
        for i := 0; i < 4; i++ {
                wg.Add(1)
                go func() {
                        tx, err := db.Begin()
                        exit(err)
                        stmt, err := tx.Prepare("INSERT INTO users VALUES(?)")
                        defer stmt.Close()
                        for i := 0; i < numInsert; i++ {
                                _, err = stmt.Exec(time.Now().UnixNano())
                                exit(err)
                        }
                        err = tx.Commit()
                        exit(err)
                        wg.Done()
                }()
        }
        wg.Wait()
        log.Println(time.Now())
}

If I set numInsert to 250, it will not raise any error. But while it's set to 2500 or more, the error is like this:

bc77568c-e472-46e1-b273-407cfa856d6c

a7922410-be36-47cd-b1c1-c8c158961da8

2651f78e-3b56-4424-bae6-7be5d5af9765

19b9d345-5cf9-490f-9e7d-4e5017c351e1

I am not sure if it's due to my misuse of goracle or any other error. I think the code is simple as it is. BTW, if I start more than 4 go routines to insert data into database, it raised the same error which really confused me. Would you help?

ghost commented 10 years ago

I dived into the source code and found this:

// MakeDSN makea a data source name given the host port and SID.
func MakeDSN(host string, port int, sid, serviceName string) string {
    var format, conn string
    if sid != "" {
        conn = sid
        format = ("(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=" +
            "(PROTOCOL=TCP)(HOST=%s)(PORT=%d)))(CONNECT_DATA=(SID=%s)))")
    } else {
        conn = serviceName
        format = ("(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=" +
            "(PROTOCOL=TCP)(HOST=%s)(PORT=%d)))(CONNECT_DATA=" +
            "(SERVICE_NAME=%s)))")
    }
    if format == "" {
        return ""
    }
    return fmt.Sprintf(format, host, port, conn)
}

Well, is the program connected to database via tcp? Maybe I prefer the OCI(direct access database via shared memory) way which I found my conf file contains

14087d85-1404-43d3-9c9e-a3e1eb57a1c1

ghost commented 10 years ago

lol. Actually I do not know much about oracle times ten database. Anyway, I just hope that it could work stable because it is used in production :-)

tgulacsi commented 10 years ago

I think you're right, the default connection method is through TCP, thus each connection implies an OS thread (with at least 8kb memory), thus too much of them means a lot of memory - this matches the panic message, which is in malloc.

You can use your hand crafted/stolen from output of tnsping DSN as you wish, as 'username/password@(DESCRIPTION=....)'.

ghost commented 10 years ago

Well, I have 128G ram on my server and it should be enough no matter if it is through tcp, right?

I simply want to use the godrv but seems godrv does not use the MakeDSN function to construct the DSN. So, any changes can I make ?

ghost commented 10 years ago

My code has been changed to this: 22c44295-5634-4c5e-941d-1b4e71d7b775

But error is the same: 8edc71ed-0199-4e04-bace-82c03564af38

If I only start one go routine, it will also raise the same error. But if I do the same job in a for loop, nothing is wrong. Unfortunately, we have to support multi go routines, like, many users login in the mean time or something else.

tgulacsi commented 10 years ago

No, your first report was about setRowCount, this latter is at getBindInfo. But both are at malloc.goc.

Which version of go do you use? The latest stable is 1.2.1, and that has something else at line 73 (http://golang.org/src/pkg/runtime/malloc.goc) - can you try with the latest go?

ghost commented 10 years ago

I am using the latest stable go.

tgulacsi commented 10 years ago

I'm just shooting blindly, as I cannot reproduce this issue (no TimesTen here), but what about runtime.LockOSThread() ?

Another blind shot could be trying github.com/tgulacsi/gocilib - that's C code is not written by me :)