mysqlswiftperfect

With Perfect/Swift mySQL Must You Have a Single Database Connection Per Request?


With Perfect/mySQL (https://github.com/PerfectlySoft/Perfect-MySQL), the examples I've seen suggest that you cannot reuse a single database connection across multiple connections. That is, you need a single database connection per HTTP request.

Examples I've seen are here: https://github.com/PerfectlySoft/Perfect-MySQL and here: https://perfect.org/docs/MySQL.html

Is this right? You must create a new db connection per request with Perfect/mySQL?


Solution

  • You can still reuse the connection for multiple times, but please note that the connection is not thread-safe, so must add thread locks on the same connection

    import MySQL
    import PerfectThread
    #if os(Linux)
    import Glibc
    #else
    import Darwin
    #endif
    
    let mysql = MySQL()
    let lock = Threading.Lock()
    var jobs = 10
    
    func now(_ id: Int) {
      print("Job Now #", id)
      lock.doWithLock {
        let x = mysql.query(statement: "SELECT now() as time")
        guard x, let y = mysql.storeResults(),
        let row = y.next() else {
        print(mysql.errorMessage())
          return
        }
        print(row[0] ?? "Now() FAILED")
        y.close()
        jobs -= 1
      }
    }
    
    func user(_ id: Int) {
      print("Job Usr #", id)
      lock.doWithLock {
        let x = mysql.query(statement: "select User from user")
        guard x, let y = mysql.storeResults(),
          let row = y.next() else {
           print(mysql.errorMessage())
           return
       }
        print(row[0] ?? "User() FAILED")
        y.close()
        jobs -= 1
      }
    }
    
    _ = mysql.setOption(.MYSQL_SET_CHARSET_NAME, "utf8mb4")
    guard mysql.connect(host: "127.0.0.1", user: "root", password: "your pass", db: "mysql") else {
      print(mysql.errorMessage())
      exit(0)
    }
    
    jobs = 10
    for id in 0 ..< 5 {
      Threading.dispatch {
        now(id)
      }
      Threading.dispatch {
        user(id)
      }
    }
    
    while jobs > 0 {
      sleep(1)
    }
    
    mysql.close()
    

    In this example, the both functions are sharing the same connection and running for a few times. That's OK. However, if each function is running in a separated thread, then it will cause a failure.