【问题标题】:Is there a db connection pool for swift in perfect?是否有完美的 swift 数据库连接池?
【发布时间】:2017-09-13 09:27:48
【问题描述】:

我正在寻找一个完美的数据库连接池包装器(swift 3 或更高版本)。我通过搜索找不到任何东西,所以我决定询问是否有人可以提供提示。

提前致谢

【问题讨论】:

    标签: swift3 perfect


    【解决方案1】:

    我宁愿说高效重用连接而不是池。以 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(),您可以轻松地将所有查询排队到一个连接中,并最大限度地提高效率 - 快速、原子、有序、共享和单例。

    如果坚持的话,你可以创建一个数组的有限数量的连接,每个连接保持一个锁来做一个平衡,比如说一个线程连接池,所以我相信这个平衡的解决方案可以在没有任何特殊模块的情况下建立关于完美本身:

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

    【讨论】:

    • 感谢您的回答
    【解决方案2】:

    我已经根据@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())
    
    }
    
    }
    

    【讨论】:

      猜你喜欢
      • 2022-08-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-09
      • 1970-01-01
      • 1970-01-01
      • 2010-10-23
      • 2015-08-09
      相关资源
      最近更新 更多