swift完美的数据库连接池吗?

Is there a db connection pool for swift in perfect?

我正在寻找完美的数据库连接池包装器(swift 3 或以上)。我无法通过搜索找到任何内容,所以我决定询问是否有人可以提供提示。

提前致谢

我宁愿说高效重用连接而不是池。以Perfect-MySQL为例:

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)
}

通过使用 Threading.Lock(),您可以轻松地将所有查询排队到一个连接中并最大限度地提高效率 - 快速、原子、有序、共享和单例。

如果坚持的话,你可以创建有限数量的连接到一个数组,每个连接保持一个锁来平衡,比如说线程连接池,所以我相信这个平衡的解决方案不需要任何Perfect 本身的特殊模块:

struct MySQLPool {
  let mysql = MySQL()
  let lock = Threading.Lock()
 }
var pool: [MySQLPool] = []
for _ in 0 ..< 32 {
  pool.append(YourNewConnection)
}

我根据@PerfectlyRock的回答的最后一部分实现了一个简单的池机制,查看:

import PerfectMySQL
import Foundation
import PerfectThread
#if os(Linux)
import Glibc
#else
import Darwin
#endif

class DBManager {

struct MySQLPoolItem {
    let mysql = MySQL()
    let lock = Threading.Lock()
    func connect()->Bool{
        return mysql.connect(host: Prefs.dbhost, user: Prefs.dbuser, password: Prefs.dbpass, db: Prefs.schema)
    }
}

var pool: [MySQLPoolItem] = []

static let shared = DBManager()

func preparePool() {

    var connectionCount = Prefs.connectionPoolCount

    while connectionCount > 0 {

        let item = MySQLPoolItem()
        _ = item.mysql.setOption(.MYSQL_SET_CHARSET_NAME, "utf8")
        let connected = item.connect()
        guard connected else {
            // verify we connected successfully
            print(item.mysql.errorMessage())
            return
        }
        print("Database connection \((connectionCount)) success");
        pool.append(item)
        connectionCount -= 1
    }

}

func getAvailableConnection() -> MySQLPoolItem {

    var item : MySQLPoolItem? = nil;

    while item == nil {
        item = tryAvailableConnection()
        if(item == nil){
            sleep(1)
        }
    }

    return item!
}

private func tryAvailableConnection() -> MySQLPoolItem? {

    for item in pool {

        if(item.lock.tryLock()){

            if(!item.mysql.ping()){
                if(item.connect()){
                    return item
                }
                item.lock.unlock()
            }else{
                return item
            }

        }

    }

    return nil

}

func runSync(query: String) -> ((result:Bool,items:MySQL.Results?)) {

    let poolItem = getAvailableConnection()

    defer {
        poolItem.lock.unlock()
    }

    let querySuccess = poolItem.mysql.query(statement: query)

    return (querySuccess,poolItem.mysql.storeResults())

}

}