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())
}
}
我正在寻找完美的数据库连接池包装器(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())
}
}