分類  >  資料庫 >

遊戲資料庫數據治理系統開發體會

tags:    時間:2014-05-04 12:36:13
遊戲資料庫數據管理系統開發體會

2014年年初的時候,接到運營部老大給的一個遊戲資料庫數據管理的系統,pm把rp圖畫好之後,就讓我自己做了,所有的讓我一個人用14個工作日昨開發完。

下面就把這個小系統的開發體會記錄一下,免得以後忘記了。


一、總體規劃

時間計劃:

2014-2-15 ~ 2014-3-6,共14個工作日,開發時間為10個工作日,調試和修改時間為4個工作日。時間比較緊張,而且pm總是催來催去,時不時來一句:做到哪裡了,搞得我心煩意亂。

功能模塊:

主要:系統由前台和後台兩個部分組成,前台是經分人員和產品研發人員使用的基本界面,後台是系統配置管理部分,主要有管理員和epr同事操作,用於對遊戲業務和資料庫/表進行相關授權。

這兩個部分主要區分方式是許可權控制,系統中有一張用戶類型數據表,根據用戶類型區分用戶操作後台或前台的許可權。而對於業務表的操作(增刪查改),則必須由特定人員給某用戶進行授權之後,該用戶才可以操作。

基本組成:業務類、用戶操作類(用戶授權查詢,用戶授權,許可權類型、用戶列表、業務數據表配置與顯示、業務資料庫配置與顯示),日誌記錄類(前台操作記錄、後台操作記錄)。


二、詳細設計

日誌記錄類:

1、前台操作記錄,即「經分人員和產品研發人員」和後台操作人員使用前台的時候,產生的日誌記錄。
2、後台操作記錄,即系統管理員和epr同事進行後台操作產生的日誌記錄。

日誌記錄類使用兩個相同數據結構的數據表,使用同一個方法進行入庫:

/* 	*操作記錄 	*type:1後台操作記錄,2:前台操作記錄 	* 	*/ 	function opeartionLog($type,$opName,$opDescription,$sql){ 		$c=new CommonModel(); 		if($type==1){ 			$data=array( 				'vAdmName'=>cookie('username')?cookie('username'):'test用戶', 				'vAdmOpName'=>$opName, 				'vAdmOpDescription'=>$opDescription, 				'sqlType'=>$sql, 				'date'=>date("Y-m-d H:i:s") 			); 			$c->c_insert('tbadmoplog',$data); 		}else if($type==2){ 			$data=array( 				'vUserName'=>cookie('username')?cookie('username'):'test用戶', 				'vUserOpName'=>$opName, 				'iUserOpDescription'=>$opDescription, 				'sqlType'=>$sql, 				'date'=>date("Y-m-d H:i:s") 			); 			$c->c_insert('tbuseroplog',$data); 		} 	} 

用戶操作類:

用戶操作類整TMD是個煩人的事情,因為遊戲業務、資料庫列表、數據表列表、我都需要通過API獲取,而且返回的數據結構還經常會變化,也不告訴我(我們不在同一地點辦公),後面還有更煩人的呢。

基本流程:

遊戲業務授權--->業務資料庫授權--->業務數據表授權(根據用戶名進行授權,許可權類型包括:查詢、更新、刪除、新增、上傳、下載等)

遊戲業務授權和業務資料庫授權以及用戶授權還都很簡單,直接通過api拉取遊戲業務或業務資料庫列表,授權入庫即可。

許可權控制:

程序中的每一個操作模塊在類中都是一個獨立的方法,所以授權的時候,我直接在類初始化的時候,獲取請求方法名稱,然後strtolower()操作下,再根據配置中配置的信息,查詢該用戶是否有本方法的某些操作許可權,有的話,進行後續操作,沒有的話直接返回錯誤信息。其實之前也考慮過設計成類似linux的分組管理,對組進行授權,但後來發現不能滿足我們的需求,也可能是我對linux的許可權管理理解的不夠深刻。

下面是代碼:

控制其中的初始化方法:

<?php ini_set('memory_limit','2024M'); ini_set('max_execution_time',-1); set_time_limit(0); header("Content-type:text/html;charset=utf-8");  /***************************************************************************** *功能:業務類控制方法 *作者:byu *時間:2012-02-08 *****************************************************************************/  class ServiceAction extends Action {  	/*初始化方法,許可權控制方法*/ 	public function _initialize(){ 		if(ACTION_NAME=="downloadtabledata"){ 			$post=$_GET; 		}else{ 			$post=$_POST; 		} 		$authList=C('AUTH'); 		$public=array("downloadtabledata","uploadedit","getdatabynum","ajax_upload","ajax_adddata","editonedataview","deleteone"); 		if(in_array(ACTION_NAME,$public)){ 			$authType=$authList['service'][ACTION_NAME]; 			/************業務和表-start***************8****/ 			$id=explode("@",$post['id']); 			$table=$post['table']; 			/************業務和表-end*******************/ 			//dump($iSerID."&".$table."&".$authType); 			$permit=auth($id[0],$id[1],$table,$authType); 			if(!$permit){ 				if($this->isAjax()){ 					echo ""; 				}else{ 					echo "對不起,許可權不足,請向管理員申請"; 				} 				exit(); 			}else{ 				 			} 		}else{ 			 		} 	}


綜合許可權控制方法:

/* 	*綜合性許可權控制方法 	*參數:業務ID,表名稱,許可權類型(英文) 	*返回:boolean 	*/ 	function auth($iSerID,$dataSourceID,$table,$authType){ 		$c=new CommonModel(); 		$sql="select iAuthID from tbauthlist where vAuthName='{$authType}'"; 		$result=$c->c_sql($sql); 		$username=cookie("username"); 		$iAuthID=$result[0]['iAuthID']; 		$where=array( 			'iUserName'=>$username, 			'iAuthID'=>$iAuthID, 			'iSerID'=>$iSerID, 			'dataSource'=>$dataSourceID, 			'table'=>$table 		); 		$permit=$c->c_getCount($table="tbuserauth",$where); 		if($permit){ 			return true; 		}else{ 			return false; 		} 	} 

配置文件中配置的信息:

/***********************配置許可權***********************************/ 	'AUTH'=>array( 		'service'=>array( 			'uploadEdit'=>'upload', 			'index'=>'select', 			'ajax_adddata'=>'insert', 			'getdatabynum'=>'select', 			'ajax_upload'=>'upload', 			'uploadtabledata'=>'download', 			'editonedataview'=>'update', 			'deleteone'=>'delete', 			'downloadtabledata'=>'download' 		) 	) 
另外,資料庫中的許可權表還記錄著一些信息,就不貼出來了。


業務類:

業務類真TMD煩人,耗費了我好長時間,其實大部分時間不是在開發商,都TMD耗費在交流上了,為啥呢?因為他們那邊的業務都沒有跟我說說清楚,讓PM去問清楚啊,又問的不明不白,搞得我浪費了大把的時間。

下面把詳細設計、開發記錄一下。

概況:本模塊中使用jquery的樹形結構設計,顯示的數據是登陸用戶有許可權的遊戲業務、業務資料庫、業務表。

樹狀結構中都是一步步的非同步獲取,沒什麼可說的。下面說說對遊戲數據表的操作。

遊戲數據表操作:

根據表,會獲取表結構,然後顯示在右側的特定區域,獲取數據表,因為之前說的之後npsSQL資料庫,後來,又來了個mysql資料庫,再後來,連sql server 、oracle、sqlite也都出來了,好吧,我要寫一個方法,根據不同的資料庫類型獲取不同的查詢表結構的語句,以及後來的「增刪查改」都要修改成不同的語句,真TMD之前信息不通暢,我以為很簡單的,搞得程序太耦合,後來花了大把的時間修改。

部分代碼:

/* 	*根據資料庫類型提取查詢表結構的語句 	*@param $DbType string 	*@param $tableName string 	*@return string 	*/ 	function getSqlForStructureByDB($DbType,$tableName){ 		$DbType=strtolower($DbType); 		$sql=array( 			'mysql'=>'show columns from %s', 			'sqlite'=>NULL, 			'sqlserver'=>NULL, 			'oracle'=>NULL, 			'npgsql'=>"SELECT * from information_schema.columns where table_name = '%s'"// column_name, data_type 		); 		foreach($sql as $k => $v){ 			if($DbType==$k){ 				$sql=sprintf($v,$tableName); 				return $sql; 			} 		} 	} 
/* 	*查詢表數據 	*@param $iSerID 	*@param $methodName string 	*@param $sql string or array 	*@return array 	*/ 	function getTableData($iSerID,$dataSourecID,$methodName="GetDataSet",$sql){ 		//第一步獲取數據源 		$db = getDataSourceBySerID($iSerID); 		$db = filterDataSourceByDataSourecID($dataSourecID,$db); 		 		$result = execute($methodName,$db,$sql); 		//解析 		$result = simplexml_load_string($result); 		$result = objectToArray($result); 		//$result = getTableName($result); 		//處理數據 		$date=array(); 		$fix=''; 		foreach($result['Tables']['DataTable']['Columns']['DataColumn'] as $k => $v){ 			$data['title'][$k]=$v['Name']; 			if($v['Name']=='id'){ 				$fix=$k; 			} 		} 		//dump($data['title']); 		//$data['title'][]="操作"; 		foreach($result['Tables']['DataTable']['Rows']['DataRow'] as $k => $v){ 			foreach($v['ItemArray']['DataItem'] as $k1 => $v1){ 			//dump($data['title'][$k1]); 				$data['data'][$k][$data['title'][$k1]]=$v1['Value']; 				if($k1==$fix){ 					$del_id=$v1['Value']; 				} 			} 			$data['del'][$k]=$del_id; 		} 		return $data; 	} 	 	/* 	*獲取一條數據的信息 	*@param $iSerID int 	*@param $methodName string 	*@param $sql string or array 	*@return array 	*/ 	function getOneDataInfo($iSerID,$dataSourecID,$methodName="GetDataSet",$sql){ 		//第一步獲取數據源 		$db = getDataSourceBySerID($iSerID); 		$db = filterDataSourceByDataSourecID($dataSourecID,$db); 		$result = execute($methodName,$db,$sql); 		//解析 		$result = simplexml_load_string($result); 		$result = objectToArray($result); 		//dump($sql); 		$data=array(); 		foreach($result['Tables']['DataTable']["Rows"]["DataRow"]["ItemArray"]["DataItem"] as $k => $v){ 			$data[$k]['columnName']=$v['ColumnName']; 			$data[$k]['value']=$v['Value']; 		} 		return $data; 		//dump($data); 		//dump($result['Tables']['DataTable']["Rows"]["DataRow"]["ItemArray"]["DataItem"]); 	} 	 	/* 	*新增數據 	*@param $iSerID int 	*@param $methodName string 	*@param $sql string or array 	*@return 返回的數據類型與$methodName的類型有關 默認返回int 	*/ 	function add($iSerID,$dataSourecID,$methodName="GetDataSet",$sql){ 		//第一步獲取數據源 		$db = getDataSourceBySerID($iSerID); 		$db = filterDataSourceByDataSourecID($dataSourecID,$db); 		//dump($sql); 		$result = execute($methodName,$db,$sql); 		//dump($result); 		return $result; 		//dump($result); 	} 	 	/* 	*公共執行方法 	*@param $iSerID int 	*@param $methodName string 	*@param $sql string or array 	*@return 返回的數據類型與$methodName的類型有關 默認返回int 	*/ 	function common($iSerID,$dataSourecID,$methodName="GetDataSet",$sql){ 		//第一步獲取數據源 		$db = getDataSourceBySerID($iSerID); 		$db = filterDataSourceByDataSourecID($dataSourecID,$db); 		//dump($dataSourecID); 		$result = execute($methodName,$db,$sql); 		return $result; 	} 	 	/* 	*通過介面執行sql方法 	*$MethodName:MethodName類型,字元串。ExecuteNonQuery  執行第一條sql,返回影響行數。GetDataSet  執行第一條,返回結果集。ExecuteScalar  執行第一條,返回單個值,第一個欄位的值。ExecuteSql  執行所有sql,返回影響行數 	*$db:資料庫連接信息,數組 	*$Sqls:sql語句,數組 	*/ 	function execute($MethodName="ExecuteNonQuery",$db,$Sqls){ 		$requestparam = array("MethodName"=>$MethodName); 		$requestparam['DB'] = array( 			"DBType"=>getDBType($db['DbType']),//資料庫類型,1=mysql,2=sqlite,3=sqlserver,4=oracle,5=npgsql 			"ConnectionString"=>"server={$db['serverip']};database={$db['DbName']};user id={$db['UserName']};password={$db['UserPwd']};port={$db['Port']}",//資料庫連接串 		); 		//dump($requestparam); 		if(!is_array($Sqls)){ 			$requestparam["Sqls"] = array($Sqls); 		}else{ 			foreach($Sqls as $v){ 				$requestparam["Sqls"][]=$v; 			} 		} 		//$requestparam["Sqls"] = array("update tbname set a=a where id=xxx","insert tbname() values()"); 		$dbproxyurl = "http://epr.dbproxy.qq.com/DBProxy.ashx"; 		//dump($requestparam); 		$par = json_encode($requestparam); 		$result=httpPostRequest($dbproxyurl,$par); 		//dump($result); 		return $result; 	} 	 	/** 	 * 發送http post請求 	 * @param $url string 	 * @param $date json 	 * @param $method string  	 * @param $timeout int 	 * @return int 是否成功 	 */ 	function httpPostRequest($url,$data,$method="POST",$timeout=120){ 		$opts = array('http'=>array( 					'method'=>$method, 					'header'=>'Content-Type:application/x-www-form-urlencoded', 					'content'=>$data, 					'timeout'=>$timeout 			)); 			//dump($data); 		$context = stream_context_create($opts); 		$result = file_get_contents($url,false,$context); 		return $result; 	} 	 	 
/* 	*複合型對象數組轉化成對象 	*@param $str object or array 	*@return array 	*/ 	function objectToArray($str){ 		if(is_object($str)){ 			$str=get_object_vars($str); 			$str=objectToArray($str); 		}else if(is_array($str)){ 			if(count($str)>0){ 				foreach($str as $k => $v){ 					$str[$k]=objectToArray($v); 				} 			} 		} 		return $str; 	} 	 	/** 	*判斷是否二維數組 	*/ 	function isTwoArray($array){ 		/*判斷是否為二維數組*/ 		$isTwoArray; 		if(is_array($array)){ 			foreach($array as $v){ 				if(is_array($v)){ 					$isTwoArray=true; 				}else{ 					$isTwoArray=false; 				} 			} 		} 		return $isTwoArray; 	} 

以上是一些基本的代碼。

數據表操作:

主要包括:查詢,單條新增,批量追加新增,全量覆蓋新增,刪除,編輯等部分。

查詢的話,就是,獲取遊戲業務ID,獲取資料庫連接信息,配置sql語句,調用方法,

返回數據,處理數據,前台展示。

批量追加新增和全量覆蓋新增都是先上傳excel表格,在讀取,組合成sql語句數組,

調用方法。全量覆蓋新增會先刪除表中的所有數據,在insert上去。

刪除和查詢類此,就sql語句不同。

編輯的話,把我折騰的,哎。編輯和查詢類似,只是sql語句不同。

由於這個小系統要進行分散式部署,每個業務數據結構都不一樣,

創建的主鍵、索引等等,所以要做成自動化的,不管是什麼數據表結構,

都能進行自動識別。所以編輯的時候,會根據全部欄位去查詢,

但是一旦有時間類型(time、date等),就查不出來,後來發現是編碼問題

,他們那邊調好之後,就可以了,後來發現,一旦條件中有中文,又不行了,這個也可能是編碼問題,但是,拖拖拉拉,到現在還沒有人幫我解決。我感到好凄涼。。。


到目前為止,已經部署了五個系統上。

這個小破系統,我還以為做的多好,真TMD的傻技術含量都沒有。

上次到博雅互動面試,我怎麼就說這個系統好了,我應該說我參與開發了元數據系統的,哎,我真的太。。。


推薦閱讀文章

Bookmark the permalink ,來源:互聯網