近幾年IT界軟硬體「國產化」搞得很密集,給很多公司帶來了商機。但是有些公司拿國外的程式碼改改換個面板,就是「自主智慧財產權」的國產軟體,光明正大賣錢,這個有點...,還經常有醜聞露出,譬如某星瀏覽器、C某-IDE...
話不多說,最近有個專案需要國產化改造,業主方推薦了國產資料庫---瀚高資料庫,我們原來用的是MySQL社群版,業主方不認可。我去看了下,這個瀚高資料庫就是拿開源的postgresql資料庫改的,加了點三權分立、國密SM3/SM4啥的。
到官網登記試用,然後幾天內轉了幾個人,最後終於拿到安裝包媒介 hgdb-see_4.5.8-db43858_amd64.deb ,按照官方安裝檔案,有很多安裝引數需要設定,那是為了伺服器環境準備的,我們開發測試環境,就無所謂了。
在國產作業系統銀河麒麟linux上 sudo dpkg -i hgdb-see_4.5.8-db43858_amd64.deb 即可安裝。預設安裝目錄是 /opt/highgo/。
安裝完成後,記得安裝jdk(有了就忽略),一會啟動設定助手,需要jdk。
下一步,設定新範例,選擇server安裝的目錄、data存放的目錄,然後一直下一步到結束,中間的引數,可以拷貝出來另外,以備不時之需。
主要記住埠5866,三個使用者sysdba/syssao/syssso設定同一個口令,否則容易忘記(生產環境切勿)。
結束後,要給linux的root使用者和經常用的操作使用者設定環境變數,否則很多操作不方便。
命令是 vi ~/.bashrc ,加入以下幾行,儲存退出,然後 source ~/.bashrc 或重登入,讓其生效。
export HGDB_HOME=/opt/highgo/hgdb-see-4.5.8 export PGDATA=/root/data export PATH=$PATH:$HGDB_HOME/bin
啟停需要sudo操作,或者直接用root使用者操作。
通過服務啟動。
[root@hgdb ~]$ systemctl start hgdb-see-4.5.8.service
通過服務停止。
[root@hgdb ~]$ systemctl stop hgdb-see-4.5.8.service
通過資料庫命令啟動。
[root@hgdb ~]$ pg_ctl start -D /root/data
通過資料庫命令停止。
[root@hgdb ~]$ pg_ctl stop -D /root/data
瀚高資料庫自帶了一個sql developer,進入目錄 /opt/highgo/hgdbdeveloper/bin,sudo ./hgdbdeveloper即可啟動GUI介面,可以進行建立資料庫、建立使用者、建表、查詢等操作。
在這之前,我用了跨平臺的dbeaver來連線hgdb,用的postgre預設的jdbc jar都連不上,可能是hgdb改了jdbc的認證方式(比如加了sm3 、sm4)。他自帶驅動在這裡。
root@longware-ubuntu:/opt/highgo/hgdb-see-4.5.8/etc/drivers# ls DotNET JDBC ODBC
因為有了環境變數,可以直接psql口令登入,不知道命令可以help求助,可以直接各種SQL操作,select、create、alter、delete等,忘記了SQL語法可以看這裡。
longware@longware-ubuntu:~$ psql -U sysdba longware 使用者 sysdba 的口令: 注意: ------------------------------------------- Login User: sysdba Login time: 2023-11-10 17:12:11.142098+08 Login Address: [local] Last Login Status: SUCCESS Login Failures: 0 Valied Until: 2023-11-16 20:40:51+08 ------------------------------------------- psql (4.5.8) 輸入 "help" 來獲取幫助資訊. longware=# \d 關聯列表 架構模式 | 名稱 | 型別 | 擁有者 ----------+--------------------+--------+-------- public | company | 資料表 | sysdba public | hg_t_audit_log | 資料表 | syssao public | pg_buffercache | 檢視 | sysdba public | pg_stat_statements | 檢視 | sysdba public | t1 | 資料表 | sysdba (5 行記錄) longware=# \d t1 資料表 "public.t1" 欄位 | 型別 | 校對規則 | 可空的 | 預設 ---------+-------------------+----------+--------+------ column1 | character varying | | | column2 | "char"[] | | | longware=# select * from t1; column1 | column2 ------------+--------- aaaaaa | {b} aaaafdasaa | {c} aaa中國aa | {d} (3 行記錄) longware=#
編輯php.ini,找到ext dll區域,將pgsql、pdo_pgsql前面的分號去掉,儲存,重啟web服務,
檢視phpinfo裡是否有pgsql
要想遠端連線資料庫,需要開通遠端連線許可權,如果你連線db時程式報錯無許可權,
[10-Nov-2023 19:15:25 Asia/Shanghai] PHP Warning: pg_connect(): Unable to connect to PostgreSQL server: 致命錯誤: 沒有用於主機 "192.168.2.180", 使用者 "sysdba", 資料庫 "longware", SSL 關閉 的 pg_hba.conf 記錄 in D:\UPUPW_ANK_W32\WebRoot\Vhosts\local-php74\hgdb_pgsql.php on line 11
則編輯/root/data/pg_hba.conf,在末尾增加以下內容(192.x.x.x為我windows內網ip),儲存退出,過載設定。如果不報錯,可忽略。
root@longware-ubuntu:~# vi ./data/pg_hba.conf host all all 192.168.2.180/32 sm3 root@longware-ubuntu:~# pg_ctl reload 2023-11-10 19:10:55.840 CST [40163] 紀錄檔: 接收到 SIGHUP, 過載組態檔 伺服器程序發出訊號
改成「host all all 0.0.0.0/0 sm3」支援任意ip連線,但有風險。
如果php連線hgdb報以下錯誤資訊:
Warning: pg_connect(): Unable to connect to PostgreSQL server: authentication method 13 not supported in D:\Workspace\wwwroot\hgdb\hgdb_pgsql.php on line 11
則表示已經連線到hgdb了,但是使用者名稱和密碼驗證發生問題。pg_hba.conf裡可以設定sm3、md5、scram-sha-256、cert等驗證方式,更改這裡當然可以,但是其他的系統可能就會發生問題,最好是從連線發起端解決問題。
我的思路是:瀚高改了postgre的程式碼,驗證方式可能也有變更;但是他們官網說是可以直接用php自帶的postgre dll,但是php自帶的postgre dll可能沒有瀚高改的東西,所以問題應該就在這。
我諮詢了瀚高的技術人員,聊了大半天,沒有得到有效解決。網路搜了半天,大概也說是這個原因,但是沒看到有效的方法。在和瀚高的技術人員溝通過程中,聊到了libpq,我讓他們發一個windows libpq dll給我,經過測試無效。
於是我去deb安裝包裡找,果然有收穫。deb安裝包裡自帶的sql developer的目錄裡,除了linux的可執行檔案,還有windows的exe,有exe那就有dll,果然有。點此下載可用的libpq.dll
將libpq.dll拷貝到php目錄(我的有D:\UPUPW_ANK_W32\Modules\PHPX\PHP56 和 D:\UPUPW_ANK_W32\Modules\PHPX\PHP74),測試php程式,都能成功連線hgdb。
show me your code !
1 <?php 2 $host = "host=192.168.2.114"; 3 $port = "port=5866"; 4 $dbname = "dbname=longware"; 5 $credentials = "user=sysdba password=Aa123!"; 6 7 $db = pg_connect("$host $port $dbname $credentials"); 8 if(!$db){ 9 echo "Error : Unable to open database <br/>"; 10 } else { 11 echo "Opened database successfully <br/>"; 12 } 13 14 //建立資料表 15 $sql ="CREATE TABLE IF NOT EXISTS COMPANY (". 16 "ID INT PRIMARY KEY NOT NULL,". 17 "NAME TEXT NOT NULL,". 18 "AGE INT NOT NULL,". 19 "ADDRESS CHAR(50)," . 20 "SALARY REAL". 21 ");"; 22 23 $ret = pg_query($db, $sql); 24 if(!$ret){ 25 echo pg_last_error($db); 26 exit; 27 } else { 28 echo "Table created successfully <br/>"; 29 } 30 31 //插入資料 32 $sql ="INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)". 33 "VALUES (1, 'Paul', 32, 'California', 20000.00 );". 34 "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)". 35 "VALUES (2, 'Allen', 25, 'Texas', 15000.00 );". 36 "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)". 37 "VALUES (3, 'Teddy', 23, 'Norway', 20000.00 );". 38 "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)". 39 "VALUES (4, 'Mark', 25, 'Rich-Mond ', 65000.00 );"; 40 41 $ret = pg_query($db, $sql); 42 if(!$ret){ 43 echo pg_last_error($db); 44 exit; 45 } else { 46 echo "Records created successfully <br/>"; 47 } 48 49 //查詢資料 50 $sql ="SELECT * from COMPANY;"; 51 52 $ret = pg_query($db, $sql); 53 if(!$ret){ 54 echo pg_last_error($db); 55 exit; 56 } 57 while($row = pg_fetch_row($ret)){ 58 echo "ID = ". $row[0] . "\n"; 59 echo "NAME = ". $row[1] ."\n"; 60 echo "ADDRESS = ". $row[2] ."\n"; 61 echo "SALARY = ".$row[4] ."<br/>"; 62 } 63 echo "Operation done successfully<br/>"; 64 pg_close($db); 65 ?>
PHP使用PDO操作hgdb
<?php header("content-type:text/html;charset=utf-8"); //連線屬性 $dbms='pgsql'; //資料庫型別 $host='192.168.2.114'; //資料庫主機名 $dbName='longware'; //使用的資料庫 $user='sysdba'; //資料庫連線使用者名稱 $pass='Aa123!'; //對應的密碼 $port='5866'; $dsn="$dbms:host=$host;port=$port;dbname=$dbName"; try { //初始化一個PDO物件 $pdo = new PDO($dsn, $user, $pass); //初始化一個PDO物件 echo "成功連線到資料庫伺服器!<br>"; } catch (PDOException $e) { die ("Error!: " . $e->getMessage() . "<br>"); } /* CREATE SEQUENC Estudent_id_seq INCREMENT 1 MINVALUE 1 NO MAXVALUE START 1 CACHE 10; CREATE TABLE student ( id INT PRIMARY KEY DEFAULT nextval('student_id_seq'), name VARCHAR(255), age int, birthday date); */ // 預編譯插入語句 $sql = 'INSERT INTO student(id, name, age, birthday) VALUES(DEFAULT, :name, :age, :birthday)'; $stmt = $pdo->prepare($sql); // 繫結引數值 $name = 'tony'; $age=19; $birthday = '2020-06-01 20:11:11'; $stmt->bindValue(':name', $name); $stmt->bindValue(':age', $age); $stmt->bindValue(':birthday', $birthday); $stmt->execute();// 執行插入操作 // 返回id $id = $pdo->lastInsertId('student_id_seq'); echo '插入資料成功,使用者id:' . $id . '<br>'; // 繫結引數值 $name = 'david'; $age=23; $stmt->bindValue(':name', $name); $stmt->bindValue(':age', $age); $stmt->bindValue(':birthday', date("Y-m-d H:i:s")); $stmt->execute();// 執行插入操作 // 返回id $id = $pdo->lastInsertId('student_id_seq'); echo '插入資料成功,使用者id:' . $id . '<br>'; // 執行查詢語句 $stmt = $pdo->query('SELECT * FROM student'); $students = []; while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { $students[] = [ 'id' => $row['id'], 'name' => $row['name'], 'age' => $row['age'], 'birthday' => $row['birthday'] ]; } ?> <!DOCTYPE html> <html> <head> <style> table { font-family: arial, sans-serif; border-collapse: collapse; width: 100%; } td, th { border: 1px solid #dddddd; text-align: left; padding: 8px; } tr:nth-child(even) { background-color: #00bb00; } </style> <title>php_conn</title> </head> <body> <h2>學生列表</h2> <table> <thead> <tr> <th>ID</th> <th>Name</th> <th>Age</th> <th>Birthday</th> </tr> </thead> <tbody> <?php foreach ($students as $student) : ?> <tr> <td><?php echo htmlspecialchars($student['id']) ?></td> <td><?php echo htmlspecialchars($student['name']); ?></td> <td><?php echo htmlspecialchars($student['age']); ?></td> <td><?php echo htmlspecialchars($student['birthday']); ?></td> </tr> <?php endforeach; ?> </tbody> </table> </body> </html>
自帶的sql developer的bin目錄裡,雙擊exe,也能順利開啟,連線hgdb。
Java其實很簡單,從/opt/highgo/hgdb-see-4.5.8/etc/drivers/JDBC目錄拿到jdbc driver檔案hgjdbc-6.1.0.jar,在eclipse建立一個java project,將jar加入build path,寫幾行測試程式碼,即可連通。
1 package hgdb; 2 3 import java.sql.Connection; 4 import java.sql.DriverManager; 5 import java.sql.ResultSet; 6 import java.sql.Statement; 7 8 public class testhighgo { 9 10 public static void main(String[] args) { 11 Connection ct = null; 12 Statement sm = null; 13 ResultSet rs = null; 14 try { 15 // 載入HighGo DB的驅動 16 Class.forName("com.highgo.jdbc.Driver"); 17 ct = DriverManager.getConnection("jdbc:highgo://192.168.2.114:5866/longware", "sysdba", "Aa123!"); 18 sm = ct.createStatement(); 19 // 執行查詢語句 20 String sql = "select * from t1 order by 1"; 21 System.out.println("sql=====" + sql); 22 rs = sm.executeQuery(sql); 23 // 迴圈結果,並列印 24 while (rs.next()) { 25 System.out.println("====" + rs.getString(2) + "====" + rs.getString(1)); 26 } 27 // 丟擲異常 28 } catch (Exception e) { 29 e.printStackTrace(); 30 } finally { 31 // 關閉資料庫連線 32 try { 33 if (rs != null) { 34 rs.close(); 35 } 36 if (sm != null) { 37 sm.close(); 38 } 39 if (ct != null) { 40 ct.close(); 41 } 42 } catch (Exception ex) { 43 ex.printStackTrace(); 44 } 45 } 46 } 47 48 }
其實,我是先用java測試連線的,java沒有報錯,因為瀚高官方jdbc driver裡面有相關的認證處理,裡面還有SM3的程式碼。
用apt命令安裝好apache、php7.4,將info.php和前面的2個php指令碼拷貝到/var/www/html之下,用瀏覽器存取或命令列執行,仍然報錯 authentication method 13 not supported
因為知道是libpq的問題,那麼看看有哪些libpq庫檔案就知道問題了。
1 root@longware-ubuntu:/# locate libpq.so -----查詢檔案,發現檔案主要在hgdb lib和作業系統的usr lib 2 /opt/highgo/hgdb-see-4.5.8/etc/drivers/ODBC/psqlODBC/lib/libpq.so.5 3 /opt/highgo/hgdb-see-4.5.8/lib/libpq.so 4 /opt/highgo/hgdb-see-4.5.8/lib/libpq.so.5 5 /opt/highgo/hgdb-see-4.5.8/lib/libpq.so.5.12 6 /opt/highgo/hgproxy/lib/libpq.so 7 /opt/highgo/hgproxy/lib/libpq.so.5 8 /opt/highgo/hgproxy/lib/libpq.so.5.12 9 /usr/lib/x86_64-linux-gnu/libpq.so.5 10 /usr/lib/x86_64-linux-gnu/libpq.so.5.14 11 12 root@longware-ubuntu:/# ll /usr/lib/x86_64-linux-gnu/libpq.* -l ------看看具體檔案,是真實檔案,還是連結,發現1真1鏈 13 lrwxrwxrwx 1 root root 13 8月 9 20:01 /usr/lib/x86_64-linux-gnu/libpq.so.5 -> libpq.so.5.14 14 -rw-r--r-- 1 root root 329912 8月 9 20:01 /usr/lib/x86_64-linux-gnu/libpq.so.5.14 15 16 root@longware-ubuntu:/# ll /opt/highgo/hgdb-see-4.5.8/lib/libpq* -l ------看看具體檔案,是真實檔案,還是連結,發現2真2鏈 17 -rw-r--r-- 1 root root 360738 7月 8 2022 /opt/highgo/hgdb-see-4.5.8/lib/libpq.a 18 lrwxrwxrwx 1 root root 13 7月 8 2022 /opt/highgo/hgdb-see-4.5.8/lib/libpq.so -> libpq.so.5.12* 19 lrwxrwxrwx 1 root root 13 7月 8 2022 /opt/highgo/hgdb-see-4.5.8/lib/libpq.so.5 -> libpq.so.5.12* 20 -rwxr-xr-x 1 root root 362560 7月 8 2022 /opt/highgo/hgdb-see-4.5.8/lib/libpq.so.5.12* 21 22 root@longware-ubuntu:/# cd /usr/lib/x86_64-linux-gnu/ --------於是思路來了,狸貓換太子,將os的lib換成hgdb的lib,先備份,再軟連結 23 root@longware-ubuntu:/usr/lib/x86_64-linux-gnu# mv libpq.so.5 bak-libpq.so.5 24 root@longware-ubuntu:/usr/lib/x86_64-linux-gnu# mv libpq.so.5.14 bak-libpq.so.5.14 25 26 root@longware-ubuntu:/usr/lib/x86_64-linux-gnu# ln -s /opt/highgo/hgproxy/lib/libpq.so.5.12 libpq.so.5 27 root@longware-ubuntu:/usr/lib/x86_64-linux-gnu# ln -s /opt/highgo/hgproxy/lib/libpq.so.5.12 libpq.so.5.14 28 29 root@longware-ubuntu:/usr/lib/x86_64-linux-gnu# ll /usr/lib/x86_64-linux-gnu/libpq.* -l ---------檢視,再確認一下 30 lrwxrwxrwx 1 root root 37 11月 10 23:00 /usr/lib/x86_64-linux-gnu/libpq.so.5 -> /opt/highgo/hgproxy/lib/libpq.so.5.12* 31 lrwxrwxrwx 1 root root 37 11月 10 23:01 /usr/lib/x86_64-linux-gnu/libpq.so.5.14 -> /opt/highgo/hgproxy/lib/libpq.so.5.12* 32 33 root@longware-ubuntu:/usr/lib/x86_64-linux-gnu# systemctl restart apache2 ----------重啟apache
重啟apache之後,php在本機就可以連線hgdb了。
如果伺服器是共用的,有多個應用在跑,那麼不建議直接換lib,因為可能會導致其他應用掛掉。 對於獨佔或開發測試機,那就隨便折騰了。