SQL審核工具介紹

d3fw 9年前發布 | 64K 次閱讀 SQL

1.背景

現階段的業務變更過程是由運維提單,再由DBA對這些 SQL逐句進行審核,審核通過后再由運維執行。由于單據的多樣性與復雜性(部分單據大于1M),不止消耗DBA的大量時間精力,也讓審單無法面面俱到,從 而可能執行了非法的SQL導致變更時間延長,影響業務正常上線造成了損失。

SQL審核工具(tmysqlparse)用于對MySQL的SQL語句進行語法分析,判定語法正確性及檢測高危告警。通過將tmysqlparse集成到凱麗/GCS系統中,可以降低人工審單的難度及減少其工作量,從而實現審單的自動化。

在tmysqlparse集成凱麗/GCS系統中后,運維的提單就可由SQL審核工具自動進行語法檢查及高危告警處理,以保證提交語法正確的單據到現網服務器中。

2.功能

tmysqlparse工具能夠正確解析基于MySQL 5.5的SQL語法,并盡量兼容MySQL 5.0、MySQL 5.1。當前已解決不同版本間因保留字用法不同導致的語法差異。關于保留字的差異性詳見KM文章http://km.oa.com/group/mysql_internals/articles/show/131384

2.1 主要功能

   tmysqlparse工具主要用于檢測SQL(針對MySQL)語句是否存在語法問題,SQL語法標準參照MySQL 5.5,tmysqlparse能夠正確的分析基于MySQL 5.5中的語法。并在保留字的差異上兼容MySQL 5.0,MySQL 5.1的語法。下面語句是現網部分出錯單據示例,都能夠通過tmysqlparse檢測出語法錯誤。

  1. delete * from t1;
  2. alter table tbTipStrats Add column sPicture char(256) NOT NULL default '';
  3. create database d_rose_dailyglobal_limit if not exists;
  4. create table tbRestoreInfo(
  5. </ol>

        iID bigint(12) unsigned NOT NULL AUTO_INCREMENT primary key,

        iWorldId int(6) null default 0,

        iUin bigint(12) not null,

    dtBanTime datetime null default now(),

        dtCreateTime datetime null default now(),

           dtUpdateTime datetime null default now(),

            iRsFlg int(2) datetime not null default 0,

            iSource int(2) not null default 0,

        vMemo varchar2(100),

        key 'iWorldId'(iWorldId),

        key 'iUin'(iUin),

    );

    1. select read_only, read_write, `general`, slow_ from t1 where maxvalue>10 and linear<'a' and "resignal" = 'a';
    2. </ol>

        其中示例語句(5)在MySQL 5.0的版本中是沒有語法錯誤的。上述都是一些普通的語法錯誤,還有些比較極端錯誤比如編碼問題。

        tmysqlparse工具還提供對一些高危操作的告警。在現網中,比如刪表、刪庫操作都可能造成數據損失,造成重大事故。為此,對于這類操作更好是檢測出來并進一步確認。初步定義的高危操作如下,后續可以進一步補充。對于下列的操作都可以正確測試出。

      STMT_DROP_DB  刪除數據庫操作

      STMT _DROP_TABLE  刪除表操作

      STMT _DROP_VIEW 刪除視圖操作

      STMT _TRUNCATE 清空表操作

      STMT _DELETE 刪除操作不帶where條件

      STMT _UPDATE 更新操作不帶where條件

      STMT _CREATE_TABLE 創建表時blob/text字段數大于10

      STMT _ALTER_TABLE 更改表增加的blob/text字段數大于10

      2.2 輸入/輸出

        tmysqlparse提供兩種輸入方式:從終端輸入或者文本輸入。文本輸入可以通過./tmysqlparse < xxx.sql 。xxx.sql即為輸入的文件。tmysqlparse還提供一些參數,詳見如下:

        ./tmysqlparse  -f xxx.xml; 指定輸出結果到xxx.xml中

        ./tmysqlparse  -v version;version是MySQL版本號,如”5.0”

        ./tmysqlparse  -V/--version; 輸出tmysqlparse的版本信息

        ./tmysqlparse –help;提供幫助信息

        ./tmysqlparse test; 指定數據庫名為test

      示例命令: ./tmysqlparse –f xxx.xml test –v “5.1” < xxx.sql

      tmysqlparse以xml的形式輸出SQL檢查的結果,通過如下定義

      <result></result>中包含tmysqlparse分析后的所有結果;

      <syntax_failed></syntax_failed>包含所有語法出錯的信息;

      <failed_info></failed_info>包含一條出錯語句,里面再 分<sql>、<error_code>、<error_msg>和<line>四部分來輸出出錯 SQL語句的信息。

      <risk_warnings></risk_warnings>包含所有的高危告警信息,產生告警的前提是語法正確,與<syntax_failed></syntax_failed>互相獨立,不存在交集。

      <warning_info></warning_info>包含一條產生高危告警的SQL語句信息;<type>、<name>、<text>和<line>四部分給出告警SQL語句信息。

      <info></info>則存儲額外的信息

      <type>中包含是產生告警的類型,分為如下幾種:

      STMT_DROP_DB  刪除數據庫操作

      STMT _DROP_TABLE  刪除表操作

      STMT _DROP_VIEW 刪除視圖操作

      STMT _TRUNCATE 清空表操作

      STMT _DELETE 刪除操作不帶where條件

      STMT _UPDATE 更新操作不帶where條件

      STMT _CREATE_TABLE 創建表時blob/text字段數大于10

      STMT _ALTER_TABLE 更改表增加的blob/text字段數大于10

      下圖為輸出結果的截圖,以xml格式輸出有助于對結果進行解析。

            SQL審核工具介紹

       

      2.3 C/C++ API

      tmysqlparse不僅僅是一個SQL審核工具,也提供C/C++調用的 API函數。選取幾個函數作為示例:

      parse_global_init();     全局初始化函數

      parse_result_init();     查檢結果初始化函數

      query_parse();         語法分析函數

      parse_result_destroy();  結果銷毀函數

      parse_global_destroy();  全局釋放函數

      下面示例一個實際程序,展示如何調用組件提供的API

      int main(int argc, char **argv)

      {

          parse_result_t pr;

          char buf[1024];

          int i;

          /* 初始化全局數據 */

          parse_global_init();

          /* 初始化parse_result結構 */

          parse_result_init(&pr);

          while(1)

          {

              fprintf(stdout, "please input a query:\n");

              if (fgets(buf, MAX_BUF_SIZE, stdin) == NULL)

              {

                  fprintf(stderr, "fgets error\n");

                  break;

              }

              if (buf[strlen(buf) -1] == '\n')

                  buf[strlen(buf) - 1] = '\0';

              if (strcmp(buf, "exit") == 0)

                  break;

              /* 語法分析 */

              if (query_parse(buf, &pr))

                  printf("query_parse error: %s\n", pr.err_msg);

              else

              {

                  printf("%s :\n", parse_result_get_stmt_type_str(&pr));

                  for ( i = 0; i < pr.n_tables; ++i)

                           printf("dbname:%s,tablename:%s\n",pr.table_arr[i].dbname,pr.table_arr[i].

      tablename);

                  printf("\n");

              }

          }

          parse_result_destroy(&pr);

          parse_global_destroy();

          return 0;

      }

      通過上述程序,即可完成對SQL語句的語法分析。

      3.原理

      tmysqlparse工具主要是通過修改MySQL 5.5的源代碼實現。基本思路是分離出MySQL源代碼中的語法分析模塊與client處理模塊。MySQL源碼的各代碼模塊間比較耦合,所以會有大量的細節要處理。

      對于終端部分,主要是對SQL文本的處理,即如何將字符串分隔成完整的SQL語句。其中主要考慮的是字符串的處理及如何斷句,比如如何處理分號,處理 delimiter, 如何處理注釋,處理分號的問題。對于同時執行多條SQL語句,client應該如何與server進行交互。

      語法處理部分,也是從MySQL 5.5 源碼中抽離出來的。主要抽取sql_parse這一部分涉及的代碼,更需要注意的其中的涉及的諸多變量的初始化定義,還有各種內存的釋放等等。

      對于保留字的問題,如果某SQL語句測試出是保留字出錯,而當前處理的版本是5.0,則可以對該SQL語句進行封裝處理,將保留加個反引號,再次執行該SQL來解決MySQL 5.5對5.0及5.1在保留字上的語法差別。

      另外,通過對SQL語句的完整分析,可以準備得到SQL語句的類型及涉及的表、庫及其它關系。就可以從中獲取高危語句的的信息,從而輸出以示告警。

      4.測試

      測試結果詳見《SQL審核工具測試結果》

      5.應用示例

        凱麗/GCS系統當前已集成了tmysqlparse工具,下圖為應用tmysqlparse工具了,實際應用效果。     SQL審核工具介紹

           圖 1 凱麗系統中應用tmysqlparse檢測出語法錯誤

       

      SQL審核工具介紹

       

       

       

       

       

           圖表 2 點擊語法錯誤信息后所示

      </div> 來自: http://tencentdba.com/blog/sqlparse/

 本文由用戶 d3fw 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!