<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    qileilove

    blog已經轉移至github,大家請訪問 http://qaseven.github.io/

    Linux中如何配置IP相關文件

    與網絡相關的文件:
      1) /etc/sysconfig/network   設置主機名稱及能否啟動Network
      2) /etc/sysconfig/network-scripts/ifcfg-eth0   設置網卡參數的文件
      3) /etc/modprobe.conf   開機時用來設置加載內核模塊的文件
      4) /etc/resolv.conf   設置DNS IP(解析服務器)的文件
      5) /etc/hosts   記錄計算機IP對應的主機名稱或主機別名
      6) /etc/protocols  定義IP數據包協議的相關數據,包括ICMP、TCP方面的數據包協議的定義等
      與網絡相關的啟動指令:
      1)/etc/init.d/network restart  可以重啟整個網絡的參數
      2)ifup eth0(ifdown eth0)   啟動或是關閉某個網絡接口,可以通過簡單的script來處理,這兩個script會主動到/etc/sysconfig/network-scripts/目錄下
      ·ifconfig 查詢、設置網卡與IP網段等相關參數
      ·ifup/ifdown 啟動/關閉網絡接口
      配置IP的三種方法:
      1、使用命令設置:
      只是暫時修改網絡接口,立即生效,但不永久有效
      #ifconfig ethX ip/netmask
      # ifconfig eth0 192.168.100.1  設置eth0的IP
      # ifconfig eth0 192.168.100.1 netmask 255.255.255.0 > mtu 8000 設置網絡接口值,同時設置MTU的值
      2、 圖形界面設置:
      system-config-network-gui
      system-config-network-tui
      輸入setup命令,進入圖形界面(配置設備IP等相關屬性信息、system-config中的服務集中在這一面板中),有時進入圖形設置網絡接口的界面時會出現亂碼,這時的解決方法是:退出此圖形界面,輸入當命令“export LANG=en”,再進入圖形界面,亂碼便會得到改善。
      進入圖形界面,選擇“Network configuration”
      修改后網絡接口之后,“Ok”、“Save”、“Save&Quit”、“Quit”退出,網絡接口修改完成。網絡接口不會立即生效,一旦生效,便會永久有效,讓IP生效的解決方法是:
      1. #ifdown eth1 && ifup eth1  先禁用,再啟用
      2. #service network restart  網絡服務重啟
      3. #/etc/init.d/network restart 也可以重啟網絡接口
      3、直接編輯配置文件:
      #vim /etc/sysconfig/network-scripts/ifcfg-ethX
      修改網絡接口的配置文件,配置文件中的常用的屬性有:
      DEVICE=ethX        設備名
      BOOTPROTO=(none | static(手動指定地址) | dhcp(動態獲取) | bootp)
      ONBOOT={yes | no}   系統啟動時,網絡設備是否被激活
      HWADDR=   物理地址,不可隨便改動
      IPADDR=     IP地址,必須
      NETMASK=    子網掩碼,必須
      TYPE=Ethernet   默認的,一般不要改,此項可以不存在
      常用屬性還有:
      GATEWAY=      網關
      USERCTL={yes | no}    是否允許普通用戶啟用和禁用網絡設備
      PEERDNS={yes | no}    若使用dhcp獲取地址,服務器分配一個IP地址,是否修改服務器DNS的默認指向(默認值為yes)
      網絡接口不會立即生效,一旦生效,便會永久有效,讓IP生效的解決方法和第二種方法一樣:
      1. #ifdown eth1 && ifup eth1  先禁用,再啟用
      2. #service network restart  網絡服務重啟
      3. #/etc/init.d/network restart 也可以重啟網絡接口

    posted @ 2014-10-30 12:02 順其自然EVO 閱讀(374) | 評論 (0)編輯 收藏

    SQL Server數據庫狀態監控 - 錯誤日志

     無論是操作系統 (Unix 或者Windows),還是應用程序 (Web 服務,數據庫系統等等) ,通常都有自身的日志機制,以便故障時追溯現場及原因。Windows Event Log和 SQL Server Error Log就是這樣的日志, PS: SQL Server 中的錯誤日志 (Error Log) 類似于 Oracle中的alert 文件。
      一. 錯誤日志簡介
      1. Windows事件日志與SQL Server 錯誤日志
      Windows事件日志中,應用程序里的SQL Server和SQL Server Agent服務,分別對應來源自MSSQLSERVER和SQLSERVERAGENT的日志信息;
      SQL Server錯誤日志中信息,與Windows事件日志里來源自MSSQLSERVER的日志信息基本一致,不同的是,Windows事件日志里信息為應用程序級,較為簡潔些,而SQL Server錯誤日志里通常有具體的數據庫錯誤信息。比如:
      Windows事件日志中錯誤信息:
      Login failed for user 'sa'. Reason: Password did not match that for the login provided. [CLIENT: 10.213.20.8]
      SQL Server錯誤日志中錯誤信息:
      Login failed for user 'sa'. Reason: Password did not match that for the login provided. [CLIENT: 10.213.20.8]
      Error: 18456, Severity: 14, State: 8.
      2. 如何理解SQL Server的Error message?
      以上面的Error: 18456, Severity: 14, State: 8.為例:
      (1) Error,錯誤編號,可以在系統表里查到對應的文本信息;
      select * From sys.messages where message_id = 18456
      (2) Severity,錯誤級別,表明這個錯誤的嚴重性,一共有25個等級,級別越高,就越需要我們去注意處理,20~25級別的錯誤會直接報錯并跳出執行,用SQL語句的TRY…CATCH是捕獲不到的;
      (3) State,錯誤狀態,比如18456錯誤,幫助文檔記載了如下狀態,不同狀態代表不同錯誤原因:
      1. Error information is not available. This state usually means you do not have permission to receive the error details. Contact your SQL Server administrator for more information.
      2.  User ID is not valid.
      5.  User ID is not valid.
      6.  An attempt was made to use a Windows login name with SQL Server Authentication.
      7.  Login is disabled, and the password is incorrect.
      8.  The password is incorrect.
      9.  Password is not valid.
      11. Login is valid, but server access failed.
      12. Login is valid login, but server access failed.
      18. Password must be changed.
      還有文檔未記載的State: 10, State: 16,通常是SQL Server啟動帳號權限問題,或者重啟SQL Server服務就好了。
      3. SQL Server 錯誤日志包含哪些信息
      SQL Server錯誤日志中包含SQL Server開啟、運行、終止整個過程的:運行環境信息、重要操作、級別比較高的錯誤等:
      (1)  SQL Server/Windows基本信息,如:版本、進程號、IP/主機名、端口、CPU個數等;
      (2) SQL Server啟動參數及認證模式、內存分配;
      (3) SQL Server實例下每個數據打開狀態(包括系統和用戶數據庫);
      (4) 數據庫或服務器配置選項變更,KILL操作,開關DBCC跟蹤,登錄失敗等等
      (5) 數據庫備份/還原的記錄;
      (6) 內存相關的錯誤和警告,可能會DUMP很多信息在錯誤日志里;
      (7) SQL Server調度異常警告、IO操作延遲警告、內部訪問越界 (也就是下面說到的Error 0);
      (8) 數據庫損壞的相關錯誤,以及DBCC CHECKDB的結果;
      (9) 實例關閉時間;
      另外,可以手動開關一些跟蹤標記(trace flags),來自定義錯誤日志的內容,比如:記錄如用戶登入登出記錄(login auditing),查詢的編譯執行等信息,比較常用的可能是用于檢查死鎖時的1204/1222 跟蹤標記。
      通常錯誤日志不會記錄SQL語句的性能問題,如:阻塞、超時的信息,也不會記錄Windows層面的異常(這會在windows事件日志中記載)。
      SQL Server Agent錯誤日志中同樣也包括:信息/警告/錯誤這幾類日志,但要簡單很多。
    4. SQL Server 錯誤日志存放在哪里
      假設SQL Server被安裝在X:\Program Files\Microsoft SQL Server,則SQL Server 與SQL Server Agent的錯誤日志文件默認被放在:
      X:\Program Files\Microsoft SQL Server\MSSQL.n\MSSQL\LOG\ ERRORLOG ~ ERRORLOG.n
      X:\Program Files\Microsoft SQL Server\MSSQL.n\MSSQL\LOG\SQLAGENT.n and SQLAGENT.out.
      如果錯誤日志路徑被管理員修改,可以通過以下某種方式找到:
      (1) 操作系統的應用程序日志里,SQL Server啟動時會留下錯誤日志文件的路徑;
      (2) 通過SSMS/管理/錯誤日志,SQL Server啟動時會留下錯誤日志文件的路徑;
      (3) SQL Server配置管理器里,點擊SQL Server實例/屬性/高級/啟動參數 (Startup parameters) ;
      (4) 通過一個未記載的SQL語句 (在SQL Server 2000中測試無效,2005及以后可以):
      SELECT SERVERPROPERTY('ErrorLogFileName')
      5. SQL Server 錯誤日志目錄下的其他文件
      在錯誤日志目錄下除了SQL Server和SQL Server Agent的日志,可能還會有以下文件:
      (1) 維護計劃產生的report文件 (SQL Server 2000的時候,后來的維護計劃log記錄在msdb);
      (2) 默認跟蹤(default trace) 生成的trace文件,PS: 審計(Audit) 產生的trace文件在\MSSQL\DATA下;
      (3) 全文索引的錯誤、日志文件;
      (4) SQLDUMP文件,比如:exception.log/SQLDump0001.txt/SQLDump0001.mdmp,大多是發生Error 0時DUMP出來的,同時在錯誤日志里通常會有類似如下記錄:
      Error: 0, Severity: 19, State: 0
      SqlDumpExceptionHandler: Process 232 generated fatal exception c0000005 EXCEPTION_ACCESS_VIOLATION. SQL Server is terminating this process.
      順便說下ERROR 0 的解釋:
      You've hit a bug of some kind - an access violation is an unexpected condition. You need to contact Product Support (http://support.microsoft.com/sql) to help figure out what happened and whether there's a fix available.
      Is your server up to date with service packs? If not, you might try updating to the latest build. This error is an internal error in sql server. If you are up to date, you should report it to MS.
      二. 錯誤日志維護
      1. 錯誤日志文件個數
      1.1 SQL Server錯誤日志
      SQL Server錯誤日志文件數量默認為7個:1個正在用的(ERRORLOG)和6個歸檔的(ERRORLOG.1 – ERRORLOG.6),可以配置以保留更多(最多99個);
      (1) 打開到SSMS/管理/SQL Server Logs文件夾/右擊/配置;
      (2) 通過未記載的擴展存儲過程,直接讀寫注冊表也行:
      USE [master]
      GO
      EXEC xp_instance_regwrite N'HKEY_LOCAL_MACHINE', N'Software\Microsoft\MSSQLServer\MSSQLServer', N'NumErrorLogs', REG_DWORD, 50
      GO
      --Check current errorlog amout
      USE [master]
      GO
      DECLARE @i int
      EXEC xp_instance_regread N'HKEY_LOCAL_MACHINE', N'Software\Microsoft\MSSQLServer\MSSQLServer', N'NumErrorLogs', @i OUTPUT
      SELECT @i
      SQL Server作為一個Windows下的應用程序,很多信息是寫在注冊表里的,自然也可以手動打開注冊表編輯器或寫SHELL去修改注冊表來作配置。
      最后,可以通過 如下SQL語句查看已存在的錯誤日志編號、起止時間、當前大小。
      EXEC master..xp_enumerrorlogs
      1.2 SQL Server Agent錯誤日志
      SQL Server Agent錯誤日志文件數量共為10個:1個正在用的(SQLAGENT.OUT),9個歸檔的(SQLAGENT.1 - SQLAGENT.9),個數不可以修改,但可以配置日志所記載的信息類型:信息、警告、錯誤。
      (1) 打開到SSMS/SQL Server Agent/Error Logs文件夾/右擊/配置;
      (2) 未記載的擴展存儲過程:
      USE [msdb]
      GO
      EXEC msdb.dbo.sp_set_sqlagent_properties @errorlogging_level=7
      GO
      至于@errorlogging_level各個值的意思,由于沒有文檔記載,需要自己測試并推算下。
      2. 錯誤日志文件歸檔
      2.1 為什么要歸檔錯誤日志?
      假設SQL Server實例從來沒被重啟過,也沒有手動歸檔過錯誤日志,那么錯誤日志文件可能會變得很大,尤其是有內部錯誤時會DUMP很多信息,一來占空間,更重要的是:想要查看分析也會不太方便。
      SQL Server/SQL Server Agent 錯誤日志有2種歸檔方式,即:創建一個新的日志文件,并將最老的日志刪除。
      (1) 自動歸檔:在SQL Server/ SQL Server Agent服務重啟時;
      (2) 手動歸檔:定期運行如下系統存儲過程
      EXEC master..sp_cycle_errorlog; --DBCC ERRORLOG 亦可
      EXEC msdb.dbo.sp_cycle_agent_errorlog;--SQL Agent 服務需在啟動狀態下才有效
      2.2 可不可以根據文件大小來歸檔?
      可能有人會覺得,雖然很久沒歸檔,但是錯誤日志確實不大,沒必要定期歸檔,最好可以根據文件大小來判斷。有以下幾種方法:
      (1) 有些監控工具,比如:SQL Diagnostic manager,就有檢測錯誤日志文件大小,并根據大小來決定是否歸檔的功能;
      (2) 自定義腳本也可以,比如:powershell, xp_enumerrorlogs 都可以檢查錯誤日志大小;
      (3) SQL Server 2012支持一個注冊表選項,以下語句限制每個錯誤日志文件為5M,到了5M就會自動歸檔,在2008/2008 R2測試無效:
      USE [master]
      GO
      EXEC xp_instance_regwrite N'HKEY_LOCAL_MACHINE', N'Software\Microsoft\MSSQLServer\MSSQLServer', N'ErrorLogSizeInKb', REG_DWORD, 5120;
    三. 錯誤日志查看及告警
      錯誤日志以文本方式記錄,記事本就可以查看,如果錯誤日志很大,可以選擇Gvim/UltraEdit /DOS窗口type errorlog等,這些方式都會“分頁”加載,不會卡住。
      1. 錯誤日志查看
      SQL Server提供了以下2種方式查看:
      (1) 日志查看器 (log viewer),除了可以查看SQL Server 與SQL Server Agent的錯誤日志,還可以查看操作系統日志、數據庫郵件日志。不過當日志文件太大時,圖形界面非常慢;
      (2) 未記載的擴展存儲過程xp_readerrorlog,另外還有一個名為sp_readerrorlog的存儲過程,它是對xp_readerrorlog的簡單封裝,并且只提供了4個參數,直接使用xp_readerrorlog即可:
      在SQL Server 2000里,僅支持一個參數,即錯誤日志號,默認為0~6:
    exec dbo.xp_readerrorlog   --寫0或null都會報錯,直接運行即可
    exec dbo.xp_readerrorlog 1
    exec dbo.xp_readerrorlog 6
    --sql server 2000 read error log
    if OBJECT_ID('tempdb..#tmp_error_log_all') is not null
    drop table #tmp_error_log_all
    create table #tmp_error_log_all
    (
    info varchar(8000),--datetime + processinfo + text
    num  int
    )
    insert into #tmp_error_log_all
    exec dbo.xp_readerrorlog
    --split error text
    if OBJECT_ID('tempdb..#tmp_error_log_split') is not null
    drop table #tmp_error_log_split
    create table #tmp_error_log_split
    (
    logdate      datetime,--datetime
    processinfo  varchar(100),--processinfo
    info         varchar(7900)--text
    )
    insert into #tmp_error_log_split
    select CONVERT(DATETIME,LEFT(info,22),120),
    LEFT(STUFF(info,1,23,''),CHARINDEX(' ',STUFF(info,1,23,'')) - 1),
    LTRIM(STUFF(info,1,23 + CHARINDEX(' ',STUFF(info,1,23,'')),''))
    from #tmp_error_log_all
    where ISNUMERIC(LEFT(info,4)) = 1
    and info <> '.'
    and substring(info,11,1) = ' '
    select *
    from #tmp_error_log_split
    where info like '%18456%'
      在SQL Server 2005及以后版本里,支持多達7個參數,說明如下:
      exec dbo.xp_readerrorlog 1,1,N'string1',N'string2',null,null,N'desc'
      參數1.日志文件號: 0 = 當前, 1 = Archive #1, 2 = Archive #2, etc...
      參數2.日志文件類型:  1 or NULL = SQL Server 錯誤日志, 2 = SQL Agent 錯誤日志
      參數3.檢索字符串1: 用來檢索的字符串
      參數4.檢索字符串2:  在檢索字符串1的返回結果之上再做過濾
      參數5.日志開始時間
      參數6.日志結束時間
      參數7.結果排序: N'asc' = 升序, N'desc' = 降序
    --sql server 2005 read error log
    if OBJECT_ID('tempdb..#tmp_error_log') is not null
    drop table #tmp_error_log
    create table #tmp_error_log
    (
    logdate      datetime,
    processinfo  varchar(100),
    info         varchar(8000)
    )
    insert into #tmp_error_log
    exec dbo.xp_readerrorlog
    select *
    from #tmp_error_log
    where info like '%18456%'
      2. 錯誤日志告警
      可以通過對某些關鍵字做檢索:錯誤(Error),警告(Warn),失敗(Fail),停止(Stop),而進行告警 (database mail),以下腳本檢索24小時內的錯誤日志:
    declare
    @start_time    datetime
    ,@end_time      datetime
    set @start_time = CONVERT(char(10),GETDATE() - 1,120)
    set @end_time = GETDATE()
    if OBJECT_ID('tempdb..#tmp_error_log') is not null
    drop table #tmp_error_log
    create table #tmp_error_log
    (
    logdate      datetime,
    processinfo  varchar(100),
    info         varchar(8000)
    )
    insert into #tmp_error_log
    exec dbo.xp_readerrorlog 0,1,NULL,NULL,@start_time,@end_time,N'desc'
    select COUNT(1) as num, MAX(logdate) as logdate,info
    from #tmp_error_log
    where (info like '%ERROR%'
    or info like '%WARN%'
    or info like '%FAIL%'
    or info like '%STOP%')
    and info not like '%CHECKDB%'
    and info not like '%Registry startup parameters%'
    and info not like '%Logging SQL Server messages in file%'
    and info not like '%previous log for older entries%'
    group by info
      當然,還可以添加更多關鍵字:kill, dead, victim, cannot, could, not, terminate, bypass, roll, truncate, upgrade, recover, IO requests taking longer than,但當中有個例外,就是DBCC CHECKDB,它的運行結果中必然包括Error字樣,如下:
      DBCC CHECKDB (xxxx) executed by sqladmin found 0 errors and repaired 0 errors.
      所以對0 errors要跳過,只有在發現非0 errors時才作告警。
      小結
      如果沒有監控工具,那么可選擇擴展存儲過程,結合數據庫郵件的方式,作自動檢查及告警,并定期歸檔錯誤日志文件以避免文件太大。大致步驟如下 :
      (1) 部署數據庫郵件;
      (2) 部署作業:定時檢查日志文件,如檢索到關鍵字,發郵件告警;
      (3) 部署作業:定期歸檔錯誤日志,可與步驟(2) 合并作為兩個step放在一個作業里。

    posted @ 2014-10-30 12:01 順其自然EVO 閱讀(2980) | 評論 (0)編輯 收藏

    通過vmstat的簡單分析數據庫操作

     vmstat一直以來就是linux/unix中進行性能監控的利器,相比top來說它的監控更加系統級,更側重于系統整體的情況。
      今天在學習vmstat的時候,突然想看看數據庫中的并行對于系統級的影響到底有多緊密,自己簡單測試了一下。
      首先來看看vmstat的命令的解釋。
      可能大家并不陌生,如果需要每隔2秒,生成3次報告,可以使用vmstat 2 3
      對于命令的輸出解釋如下:
      r代表等待cpu事件的進程數
      b代表處于不可中斷休眠中的進程數,
      swpd表示使用的虛擬內存的總量,單位是M
      free代表空閑的物理內存總量,單位是M
      buffer代表用作緩沖區的內存總量
      cache代表用做高速緩存的內存總量
      si代表從磁盤交換進來的內存總量
      so代表交換到磁盤的內存總量
      bi代表從塊設備收到的塊數,單位是1024bytes
      bo代表發送到塊設備的塊數
      in代表每秒的cpu中斷次數
      cs代表每秒的cpu上下文切換次數
      us代表用戶執行非內核代碼的cpu時間所占的百分比
      sy代表用于執行那個內核代碼的cpu時間所占的百分比
      id代表處于空閑狀態的cpu時間所占的百分比
      wa代表等待io的cpu時間所占的百分比
    procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----
    r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
    0  0      0 296716 399588 904276    0    0     0    16  639 1285  0  0 100  0  0
    0  0      0 296576 399588 904276    0    0    43    11  809 1484  1  1 98  0  0
    0  0      0 296576 399592 904276    0    0    53    25  764 1538  0  0 99  0  0
    0  0      0 296584 399592 904276    0    0     0    11  716 1502  0  0 100  0  0
    0  0      0 296584 399600 904276    0    0    21    16  756 1534  0  0 100  0  0
      零零總總說了一大堆,我們舉幾個例子,一個是文件的拷貝,這個最直接的io操作。看看在vmstat的監控下會有什么樣的數據變化。
      黃色部分代表開始運行cp命令時vmstat的變化,我們拷貝的文件是200M,可以看到空閑內存立馬騰出了將近200M的內存空間,buffer空間基本沒有變化,這部分空間都放入了cache,同時從設備收到的塊數也是急劇增加,cpu上下文的切換次數也是從930瞬間達到了1918,然后慢慢下降,cpu的使用率也是瞬間上升,最后基本控制在20%~30%。
    procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----
    r  b    swpd   free   buff      cache   si   so    bi    bo   in   cs us sy id wa st
    0  0      0 296716 399588 904276    0    0     0    16  639 1285  0  0 100  0  0
    0  0      0 296576 399588 904276    0    0    43    11  809 1484  1  1 98  0  0
    0  0      0 296576 399592 904276    0    0    53    25  764 1538  0  0 99  0  0
    0  0      0 296584 399592 904276    0    0     0    11  716 1502  0  0 100  0  0
    0  0      0 296584 399600 904276    0    0    21    16  756 1534  0  0 100  0  0
    0  0      0 296584 399600 904276    0    0     0    11  930 1625  1  1 98  0  0
    1  1      0  93960 399608 1104528    0    0 33427    24 1918 2094  0 23 71  7  0
    1  0      0  66440 399592 1131832    0    0  7573    12 1513 1323  0 25 74  2  0
    5  0      0  74988 399588 1123188    0    0  2859    33  887  594  0 24 75  1  0
    11  0      0  74280 399572 1114952    0    0  1963    15  770  738  3 44 53  0  0
    2  0      0  74492 399568 1125008    0    0  3776    16 1014  812  0 20 73  6  0
    2  0      0  72640 399560 1126696    0    0  2411    23  975  619  1 21 78  0  0
    1  0      0  70532 399556 1128936    0    0  2389    16 1018  732  0 22 77  0  0
    2  0      0  75396 399532 1116288    0    0  2795    15  831  673  2 47 51  0  0
    2  0      0  79576 399536 1121416    0    0  2901    20  850  688  1 24 63 12  0
    0  3      0  67052 399536 1130252    0    0  1493 43708  701  644  0 29 24 47  0
    1  0      0  74244 399540 1125600    0    0  1323    19  842  624  0 10 65 25  0
    3  0      0  70788 399532 1127728    0    0  2539 21152  936  624  0 18 58 24  0
    5  0      0  73164 399532 1120352    0    0  1109    27  458  447  4 71 17  9  0
    0  0      0  76120 399532 1125684    0    0  1859    15  957 1182  0 19 80  1  0
    0  0      0  76128 399532 1125688    0    0    21    19  679 1399  0  0 98  1  0  --拷貝工作完成系統的負載又逐步恢復了原值。
      對于文件的操作有了一個基本認識,來看看數據庫級的操作吧。

     首先看看全表掃描的情況。
      我們對于一個170萬數據的表進行查詢。可以看到
      從設備收到的塊數是急劇增加,效果跟文件的拷貝有些類似,但是buffer,cache基本沒有變化。我想這也就是數據庫級別的操作和系統級別的根本區別吧。數據庫的buffer_cache應該就是起這個作用的。
    SQL> select count(*)from test where object_id<>1;
    COUNT(*)
    ----------
    1732096
    [ora11g@rac1 arch]$ vmstat 3
    procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----
    r  b     swpd   free   buff       cache   si   so    bi    bo   in   cs us sy id wa st
    1  0      0 166520 399680 1023292    0    0    17    20    6    5  1  1 98  1  0
    0  0      0 175800 399680 1023292    0    0    53    11  680 1308  0  0 100  0  0
    1  0      0 175800 399680 1023292    0    0 18021    24 1451 1826  2  7 66 25  0
    0  0      0 175800 399680 1023292    0    0    53    53  812 1577  0  0 98  2  0
    0  0      0 166256 399680 1023292    0    0     0    16  881 1614  1  1 98  0  0
    1  0      0 175908 399680 1023292    0    0    21    11  866 1605  0  0 99  0  0
      接著來做一個更為消耗資源的操作,這個sql不建議在正式環境測試,因為很耗費資源
      對一個170多萬的表進行低效的連接。vmstat的情況如下。運行了較長的時間,過了好一段時間都沒有結束,可以看到cpu的使用率已經達到了40~50%,在開始的時候,從設備中得到的塊數急劇增加,然后基本趨于一個平均值,buffer,cache基本沒有變化。
    SQL> select count(*)from test t1,test t2 where t1.object_id=t2.object_id;
    procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----
    r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
    0  0      0 176024 399688 1023292    0    0    43    11  655 1284  0  0 99  1  0
    1  0      0 171420 399688 1023292    0    0     0    16  671 1302  1  1 98  0  0
    0  0      0 176164 399688 1023292    0    0     0    11  735 1331  0  1 99  0  0
    0  0      0 176164 399688 1023292    0    0    21    25  678 1291  0  0 99  0  0
    1  0      0 173452 399688 1023292    0    0 15643  5256 1835 2178  6 12 76  6  0
    2  0      0 163048 399688 1023292    0    0 15179  5748 2166 2271  7 12 67 14  0
    1  0      0 172072 399688 1023292    0    0  5541  2432 2226 1860 32  6 59  3  0
    1  0      0 169964 399688 1023292    0    0   656    24 2322 1656 46  1 50  4  0
    1  0      0 169848 399688 1023292    0    0   485    11 2335 1637 48  1 50  2  0
    1  0      0 159576 399692 1023288    0    0   448   115 2442 1738 49  1 48  2  0
    1  0      0 169344 399692 1023292    0    0   712    11 2351 1701 47  1 50  3  0
    1  0      0 169352 399696 1023288    0    0   619    24 2332 1649 48  1 49  2  0
    1  0      0 169360 399696 1023292    0    0   467    11 2339 1623 47  1 50  2  0
    1  0      0 159848 399700 1023288    0    0   693    16 2318 1673 48  1 48  3  0
    1  0      0 169368 399700 1023292    0    0   467    11 2309 1660 47  1 50  3  0
    2  0      0 169368 399700 1023292    0    0   467    28 2329 1624 48  1 50  2  0
      來看看并行的效果。最后返回的條數有近億條,這也就是這個連接低效的原因所在,但是在vmstat得到的信息來看和普通的數據查詢還是有很大的差別。
      首先是急劇消耗io,同時從內存中也取出了一塊內存空間。然后io基本趨于穩定,開始急劇消耗cpu資源。可以看到cpu的使用率達到了90%以上。
    SQL> select count(*)from test t1,test t2 where t1.object_id=t2.object_id;
    COUNT(*)
    ----------
    221708288
    procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----
    r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
    0  0      0 175048 399748 1023292    0    0     0    20  665 1274  0  0 100  0  0
    0  0      0 175048 399748 1023292    0    0    21    11  657 1286  0  0 100  0  0
    0  0      0 165644 399748 1023292    0    0     0    16  715 1310  1  1 98  0  0
    0  0      0 175056 399748 1023292    0    0     0    11  664 1284  0  0 99  0  0
    0  0      0 175056 399748 1023292    0    0    21    24  640 1289  0  0 99  0  0
    0  4      0 142364 399748 1025408    0    0  5957   988 1407 1869 10  8 64 18  0
    0  0      0 132092 399748 1025444    0    0 12520  4939 1903 2556 14 11 32 43  0
    0  2      0 140248 399748 1025444    0    0 10477  3973 1728 2427 11  7 29 53  0
    2  0      0 136776 399748 1025444    0    0  7987  4125 1536 2248 11  6 24 60  0
    2  0      0 136776 399748 1025444    0    0   971    20 2427 1663 98  1  0  1  0
    2  0      0 121404 399748 1025456    0    0  1160    11 2422 1730 96  3  0  1  0
    2  0      0 134528 399748 1025460    0    0  1195    17 2399 1695 97  2  0  2  0
    3  0      0 134520 399748 1025460    0    0  1325    19 2443 1693 96  1  0  3  0
    2  0      0 134536 399748 1025460    0    0  1176    16 2405 1674 99  1  0  0  0
    2  0      0 125108 399748 1025460    0    0  1139    11 2418 1647 97  2  0  1  0
    2  0      0 134628 399752 1025460    0    0  1235    16 2391 1653 98  1  0  1  0
    3  0      0 134644 399752 1025460    0    0  1197    21 2392 1640 97  2  0  1  0
    2  0      0 134652 399756 1025460    0    0  1400    16 2433 1670 97  1  0  3  0
    2  0      0 125116 399756 1025460    0    0  1008    11 2199 1564 97  2  0  1  0
      看來并行的實現還是有很多的細節,相比普通的查詢來說更加復雜,而且消耗的資源更多,這個也就是在使用并行的時候需要權衡的一個原因。

    posted @ 2014-10-30 12:00 順其自然EVO 閱讀(304) | 評論 (0)編輯 收藏

    磁盤讀寫與數據庫的關系

     一 磁盤物理結構
      (1) 盤片:硬盤的盤體由多個盤片疊在一起構成。
      在硬盤出廠時,由硬盤生產商完成了低級格式化(物理格式化),作用是將空白的盤片(Platter)劃分為一個個同圓心、不同半徑的磁道(Track),還將磁道劃分為若干個扇區(Sector),每個扇區可存儲128×2的N次方(N=0.1.2.3)字節信息,默認每個扇區的大小為512字節。通常使用者無需再進行低級格式化操作。
      (2) 磁頭:每張盤片的正反兩面各有一個磁頭。
      (3) 主軸:所有盤片都由主軸電機帶動旋轉。
      (4) 控制集成電路板:復雜!上面還有ROM(內有軟件系統)、Cache等。
      二 磁盤如何完成單次IO操作
      (1) 尋道
      當控制器對磁盤發出一個IO操作命令的時候,磁盤的驅動臂(Actuator Arm)帶動磁頭(Head)離開著陸區(Landing Zone,位于內圈沒有數據的區域),移動到要操作的初始數據塊所在的磁道(Track)的正上方,這個過程被稱為尋道(Seeking),對應消耗的時間被稱為尋道時間(Seek Time);
      (2) 旋轉延遲
      找到對應磁道還不能馬上讀取數據,這時候磁頭要等到磁盤盤片(Platter)旋轉到初始數據塊所在的扇區(Sector)落在讀寫磁頭正下方之后才能開始讀取數據,在這個等待盤片旋轉到可操作扇區的過程中消耗的時間稱為旋轉延時(Rotational Latency);
      (3) 數據傳送
      接下來就隨著盤片的旋轉,磁頭不斷的讀/寫相應的數據塊,直到完成這次IO所需要操作的全部數據,這個過程稱為數據傳送(Data Transfer),對應的時間稱為傳送時間(Transfer Time)。完成這三個步驟之后單次IO操作也就完成了。
      根據磁盤單次IO操作的過程,可以發現:
      單次IO時間 = 尋道時間 + 旋轉延遲 + 傳送時間
      進而推算IOPS(IO per second)的公式為:
      IOPS = 1000ms/單次IO時間
     三 磁盤IOPS計算
      不同磁盤,它的尋道時間,旋轉延遲,數據傳送所需的時間各是多少?
      1. 尋道時間
      考慮到被讀寫的數據可能在磁盤的任意一個磁道,既有可能在磁盤的最內圈(尋道時間最短),也可能在磁盤的最外圈(尋道時間最長),所以在計算中我們只考慮平均尋道時間。
      在購買磁盤時,該參數都有標明,目前的SATA/SAS磁盤,按轉速不同,尋道時間不同,不過通常都在10ms以下:
      2. 旋轉延時
      和尋道一樣,當磁頭定位到磁道之后有可能正好在要讀寫扇區之上,這時候是不需要額外的延時就可以立刻讀寫到數據,但是最壞的情況確實要磁盤旋轉整整一圈之后磁頭才能讀取到數據,所以這里也考慮的是平均旋轉延時,對于15000rpm的磁盤就是(60s/15000)*(1/2) = 2ms。
      3. 傳送時間
      (1) 磁盤傳輸速率
      磁盤傳輸速率分兩種:內部傳輸速率(Internal Transfer Rate),外部傳輸速率(External Transfer Rate)。
      內部傳輸速率(Internal Transfer Rate),是指磁頭與硬盤緩存之間的數據傳輸速率,簡單的說就是硬盤磁頭將數據從盤片上讀取出來,然后存儲在緩存內的速度。
      理想的內部傳輸速率不存在尋道,旋轉延時,就一直在同一個磁道上讀數據并傳到緩存,顯然這是不可能的,因為單個磁道的存儲空間是有限的;
      實際的內部傳輸速率包含了尋道和旋轉延時,目前家用磁盤,穩定的內部傳輸速率一般在30MB/s到45MB/s之間(服務器磁盤,應該會更高)。
      外部傳輸速率(External Transfer Rate),是指硬盤緩存和系統總線之間的數據傳輸速率,也就是計算機通過硬盤接口從緩存中將數據讀出交給相應的硬盤控制器的速率。
      硬盤廠商在硬盤參數中,通常也會給出一個最大傳輸速率,比如現在SATA3.0的6Gbit/s,換算一下就是6*1024/8,768MB/s,通常指的是硬盤接口對外的最大傳輸速率,當然實際使用中是達不到這個值的。
      這里計算IOPS,保守選擇實際內部傳輸速率,以40M/s為例。
      (2) 單次IO操作的大小
      有了傳送速率,還要知道單次IO操作的大小(IO Chunk Size),才可以算出單次IO的傳送時間。那么磁盤單次IO的大小是多少?答案是:不確定。
      操作系統為了提高 IO的性能而引入了文件系統緩存(File System Cache),系統會根據請求數據的情況將多個來自IO的請求先放在緩存里面,然后再一次性的提交給磁盤,也就是說對于數據庫發出的多個8K數據塊的讀操作有可能放在一個磁盤讀IO里就處理了。
      還有,有些存儲系統也是提供了緩存(Cache),接收到操作系統的IO請求之后也是會將多個操作系統的 IO請求合并成一個來處理。
      不管是操作系統層面的緩存,還是磁盤控制器層面的緩存,目的都只有一個,提高數據讀寫的效率。因此每次單獨的IO操作大小都是不一樣的,它主要取決于系統對于數據讀寫效率的判斷。這里以SQL Server數據庫的數據頁大小為例:8K。
      (3) 傳送時間
      傳送時間 = IO Chunk Size/Internal Transfer Rate = 8k/40M/s = 0.2ms
      可以發現:
      (3.1) 如果IO Chunk Size大的話,傳送時間會變長,單次IO時間就也變長,從而導致IOPS變小;
      (3.2) 機械磁盤的主要讀寫成本,都花在了尋址時間上,即:尋道時間 + 旋轉延遲,也就是磁盤臂的擺動,和磁盤的旋轉延遲。
      (3.3) 如果粗略的計算IOPS,可以忽略傳送時間,1000ms/(尋道時間 + 旋轉延遲)即可。
      4. IOPS計算示例
      以15000rpm為例:
      (1) 單次IO時間
      單次IO時間 = 尋道時間 + 旋轉延遲 + 傳送時間 = 3ms + 2ms + 0.2 ms = 5.2 ms
      (2) IOPS
      IOPS = 1000ms/單次IO時間 = 1000ms/5.2ms = 192 (次)
      這里計算的是單塊磁盤的隨機訪問IOPS。
      考慮一種極端的情況,如果磁盤全部為順序訪問,那么就可以忽略:尋道時間 + 旋轉延遲 的時長,IOPS的計算公式就變為:IOPS = 1000ms/傳送時間
      IOPS = 1000ms/傳送時間= 1000ms/0.2ms = 5000 (次)
      顯然這種極端的情況太過理想,畢竟每個磁道的空間是有限的,尋道時間 + 旋轉延遲 時長確實可以減少,不過是無法完全避免的。
      四 數據庫中的磁盤讀寫
      1. 隨機訪問和連續訪問
      (1) 隨機訪問(Random Access)
      指的是本次IO所給出的扇區地址和上次IO給出扇區地址相差比較大,這樣的話磁頭在兩次IO操作之間需要作比較大的移動動作才能重新開始讀/寫數據。
      (2) 連續訪問(Sequential Access)
      相反的,如果當次IO給出的扇區地址與上次IO結束的扇區地址一致或者是接近的話,那磁頭就能很快的開始這次IO操作,這樣的多個IO操作稱為連續訪問。
      (3) 以SQL Server數據庫為例
      數據文件,SQL Server統一區上的對象,是以extent(8*8k)為單位進行空間分配的,數據存放是很隨機的,哪個數據頁有空間,就寫在哪里,除非通過文件組給每個表預分配足夠大的、單獨使用的文件,否則不能保證數據的連續性,通常為隨機訪問。
      另外哪怕聚集索引表,也只是邏輯上的連續,并不是物理上。
      日志文件,由于有VLF的存在,日志的讀寫理論上為連續訪問,但如果日志文件設置為自動增長,且增量不大,VLF就會很多很小,那么就也并不是嚴格的連續訪問了。
      2. 順序IO和并發IO
      (1) 順序IO模式(Queue Mode)
      磁盤控制器可能會一次對磁盤組發出一連串的IO命令,如果磁盤組一次只能執行一個IO命令,稱為順序IO;
      (2) 并發IO模式(Burst Mode)
      當磁盤組能同時執行多個IO命令時,稱為并發IO。并發IO只能發生在由多個磁盤組成的磁盤組上,單塊磁盤只能一次處理一個IO命令。
      (3) 以SQL Server數據庫為例
      有的時候,盡管磁盤的IOPS(Disk Transfers/sec)還沒有太大,但是發現數據庫出現IO等待,為什么?通常是因為有了磁盤請求隊列,有過多的IO請求堆積。
      磁盤的請求隊列和繁忙程度,通過以下性能計數器查看:
      LogicalDisk/Avg.Disk Queue Length
      LogicalDisk/Current Disk Queue Length
      LogicalDisk/%Disk Time
      這種情況下,可以做的是:
      (1) 簡化業務邏輯,減少IO請求數;
      (2) 同一個實例下的多個用戶數據庫,遷移到不同實例下;
      (3) 同一個數據庫的日志、數據文件,分離到不同的存儲單元;
      (4) 借助HA策略,做讀寫操作的分離。
      3. IOPS和吞吐量(throughput)
      (1) IOPS
      IOPS即每秒進行讀寫(I/O)操作的次數。在計算傳送時間時,有提到:如果IO Chunk Size大的話,那么IOPS會變小,假設以100M為單位讀寫數據,那么IOPS就會很小。
      (2) 吞吐量(throughput)
      吞吐量指每秒可以讀寫的字節數。同樣假設以100M為單位讀寫數據,盡管IOPS很小,但是每秒讀寫了N*100M的數據,吞吐量并不小。
      (3) 以SQL Server數據庫為例
      對于OLTP的系統,經常讀寫小塊數據,多為隨機訪問,用IOPS來衡量讀寫性能;
      對于數據倉庫,日志文件,經常讀寫大塊數據,多為順序訪問,用吞吐量來衡量讀寫性能。
      磁盤當前的IOPS,通過以下性能計數器查看:
      LogicalDisk/Disk Transfers/sec
      LogicalDisk/Disk Reads/sec
      LogicalDisk/Disk Writes/sec
      磁盤當前的吞吐量,通過以下性能計數器查看:
      LogicalDisk/Disk Bytes/sec
      LogicalDisk/Disk Read Bytes/sec
      LogicalDisk/Disk Write Bytes/sec

    posted @ 2014-10-30 12:00 順其自然EVO 閱讀(446) | 評論 (0)編輯 收藏

    數據庫查詢結果數量問題

     ============問題描述============
      在數據庫中存放用戶發帖的信息,利用下面的程序得到該用戶發帖的數量。可是UserUtils的值一直是1,這是怎么回事?
    ResultSet res = sqlConn
    .executeQuery("select count(*) from" + username
    + "_message");
    while (res.next()) {
    UserUtils.flag = res.getInt(1);
    System.out.println("userUtils = " + UserUtils.flag);
    }
      ============解決方案1============
      from這后面加個空格吧
      ============解決方案2============
      select count(*) from后面少了一個空格樣。

    posted @ 2014-10-30 11:59 順其自然EVO 閱讀(205) | 評論 (0)編輯 收藏

    為MySQL選擇合適的備份方式

     數據庫的備份是極其重要的事情。如果沒有備份,遇到下列情況就會抓狂:
      UPDATE or DELETE whitout where…
      table was DROPPed accidentally…
      INNODB was corrupt…
      entire datacenter loses power…
      從數據安全的角度來說,服務器磁盤都會做raid,MySQL本身也有主從、drbd等容災機制,但它們都無法完全取代備份。容災和高可用能幫我們有效的應對物理的、硬件的、機械的故障,而對我們犯下的邏輯錯誤卻無能為力。每一種邏輯錯誤發生的概率都極低,但是當多種可能性疊加的時候,小概率事件就放大成很大的安全隱患,這時候備份的必要性就凸顯了。那么在眾多的MySQL備份方式中,哪一種才是適合我們的呢?
      常見的備份方式
      MySQL本身為我們提供了mysqldump、mysqlbinlog遠程備份工具,percona也為我們提供了強大的Xtrabackup,加上開源的mydumper,還有基于主從同步的延遲備份、從庫冷備等方式,以及基于文件系統快照的備份,其實選擇已經多到眼花繚亂。而備份本身是為了恢復,所以能夠讓我們在出現故障后迅速、準確恢復的備份方式,就是最適合我們的,當然,同時能夠省錢、省事,那就非常完美。下面就我理解的幾種備份工具進行一些比較,探討下它們各自的適用場景。
      1. mysqldump & mydumper
      mysqldump是最簡單的邏輯備份方式。在備份myisam表的時候,如果要得到一致的數據,就需要鎖表,簡單而粗暴。而在備份innodb表的時候,加上–master-data=1 –single-transaction 選項,在事務開始時刻,記錄下binlog pos點,然后利用mvcc來獲取一致的數據,由于是一個長事務,在寫入和更新量很大的數據庫上,將產生非常多的undo,顯著影響性能,所以要慎用。
      優點:簡單,可針對單表備份,在全量導出表結構的時候尤其有用。
      缺點:簡單粗暴,單線程,備份慢而且恢復慢,跨IDC有可能遇到時區問題。
      mydumper是mysqldump的加強版。相比mysqldump:
      內置支持壓縮,可以節省2-4倍的存儲空間。
      支持并行備份和恢復,因此速度比mysqldump快很多,但是由于是邏輯備份,仍不是很快。
      2. 基于文件系統的快照
      基于文件系統的快照,是物理備份的一種。在備份前需要進行一些復雜的設置,在備份開始時刻獲得快照并記錄下binlog pos點,然后采用類似copy-on-write的方式,把快照進行轉儲。轉儲快照本身會消耗一定的IO資源,而且在寫入壓力較大的實例上,保存被更改數據塊的前印象也會消耗IO,最終表現為整體性能的下降。而且服務器還要為copy-on-write快照預留較多的磁盤空間,這本身對資源也是一種浪費。因此這種備份方式我們使用的不多。
    3. Xtrabackup
      這或許是最為廣泛的備份方式。percona之所以家喻戶曉,Xtrabackup應該功不可沒。它實際上是物理備份+邏輯備份的組合。在備份innodb表的時候,它拷貝ibd文件,并一刻不停的監視redo log的變化,append到自己的事務日志文件。在拷貝ibd文件過程中,ibd文件本身可能被寫”花”,這都不是問題,因為在拷貝完成后的第一個prepare階段,Xtrabackup采用類似于innodb崩潰恢復的方法,把數據文件恢復到與日志文件一致的狀態,并把未提交的事務回滾。如果同時需要備份myisam表以及innodb表結構等文件,那么就需要用flush tables with lock來獲得全局鎖,開始拷貝這些不再變化的文件,同時獲得binlog位置,拷貝結束后釋放鎖,也停止對redo log的監視。
      它的工作原理如下:
      由于mysql中不可避免的含有myisam表,同時innobackup并不備份表結構等文件,因此想要完整的備份mysql實例,就少不了要執行flush tables with read lock,而這個語句會被任何查詢(包括select)阻塞,在阻塞過程中,它又反過來阻塞任何查詢(包括select)。如果碰巧備份實例上有長查詢先于flush tables with read lock執行,數據庫就會hang住。而當flush tables with read lock獲得全局鎖后,雖然查詢可以執行,但是仍會阻塞更新,所以,我們希望flush tables with read lock從發起到結束,持續的時間越短越好。
      為了解決這個問題,有兩種比較有效的方法:
      1. 盡量不用myisam表。
      2. Xtrabackup增加了–rsync選項,通過兩次rsync來減少持有全局鎖的時間。
      優化后的備份過程如下:
      優點:在線熱備,全備+增備+流備,支持限速,支持壓縮,支持加密。
      缺點:需要獲取全局鎖,如果遇到長查詢,等待時間將不可控,因此要做好監控,必要時殺死長查詢或自殺;遇到超大的實例,備份過程較長,redo log太大會影響恢復速度,這種情況下最好采用延遲備份。
      4. mysqlbinlog 5.6
      上述所有的備份方式,都只能把數據庫恢復到備份的某個時間點:mysqldump和mydumper,以及snapshot是備份開始的時間點;Xtrabackup是備份結束的時間點。要想實現point in time的恢復,還必須備份binlog。同時binlog也是實現增備的寶貴資源。
      幸運的是,mysql 5.6為我們提供了遠程備份binlog的選項:
      <code>mysqlbinlog --raw --read-from-remote-server --stop-never</code>
      它會偽裝成mysql從庫,從遠程獲取binlog然后進行轉儲。這對線上主庫容量不夠無法保存較多binlog的場景非常有用。但是,它畢竟不像真正的mysql從庫實例,狀態監控和同步都需要單獨部署。因此個人覺得采用blackhole來備份全量的binlog是更好的選擇。筆者曾經實現過一個自動搭建blackhole從庫的工具,稍加修改,就可以完美搭建出blackhole從庫。一旦同步起來,基本一勞永逸,很少出問題,主從切換的時候跟著切了就行。
      提示:
      不要小看binlog的備份。當5.6的多線程復制大規模使用后,從庫追趕主庫命令點的耗時將被極大縮短,這樣我們把每天一次的全量備份改為每3天一次、甚至每周一次的全量備份,和持續的binlog增量備份。遇到故障需要恢復數據的時候,重放3、5天的binlog也是極快的。降低備份頻率最直接的好處是,省錢、省事。
      blackhole對于備份binlog是極好的。一方面可以長久的備份binlog用于恢復數據庫,另一方面,在其上配置半同步復制,可以有效防止主庫的binlog丟失。
      總結
      備份方式各有千秋,而對我們來說,面對數千實例,選擇合適的備份工具來實現統一配置、統一規劃,構建智能調度的備份云平臺才是王道。畢竟,多種備份方式共存的運維成本是不容忽視的。
      從使用經驗來看,用Xtrabackup全備數據,用blackhole增備binlog,并定期對備份數據的有效性進行驗證,是當下比較好的選擇。

    posted @ 2014-10-30 11:58 順其自然EVO 閱讀(372) | 評論 (0)編輯 收藏

    Hibernate與數據庫的觸發器協同工作

    Hibernate 與數據庫中的觸發器協同工作時, 會造成兩類問題
      1、觸發器使 Session 的緩存中的持久化對象與數據庫中對應的數據不一致:觸發器運行在數據庫中, 它執行的操作對 Session 是透明的 Session 的
      解決方案: 在執行完 Session 的相關操作后, 立即調用 Session 的 flush() 和 refresh() 方法, 迫使 Session 的緩存與數據庫同步(refresh() 方法重新從數據庫中加載對象)
      2、update() 方法盲目地激發觸發器: 無論游離對象的屬性是否發生變化, 都會執行 update 語句, 而 update 語句會激發數據庫中相應的觸發器
      解決方案:在映射文件的的 <class> 元素中設置 select-before-update 屬性: 當 Session 的 update 或 saveOrUpdate() 方法更新一個游離對象時, 會先執行 Select 語句, 獲得當前游離對象在數據庫中的最新數據, 只有在不一致的情況下才會執行 update 語句(沒有用到觸發器的時候一般的情況下最好不要設置,因為會降低效率的)

    posted @ 2014-10-30 11:57 順其自然EVO 閱讀(356) | 評論 (0)編輯 收藏

    避免Java應用中NullPointerException的技巧和最佳實踐

      Java應用中拋出的空指針異常是解決空指針的最好方式,也是寫出能順利工作的健壯程序的關鍵。俗話說“預防勝于治療”,對于這么令人討厭的空指針異常,這句話也是成立的。值得慶幸的是運用一些防御性的編碼技巧,跟蹤應用中多個部分之間的聯系,你可以將Java中的空指針異常控制在一個很好的水平上。順便說一句,這是Javarevisited上的第二個空指針異常的帖子。在上個帖子中我們討論了Java中導致空指針異常的常見原因,而在本教程中我們將會學習一些Java的編程技巧和最佳實踐。這些技巧可以幫助你避免Java中的空指針異常。遵從這些技巧同樣可以減少Java代碼中到處都有的非空檢查的數量。作為一個有經驗的Java程序員,你可能已經知道其中的一部分技巧并且應用在你的項目中。但對于新手和中級開發人員來說,這將是很值得學習的。順便說一句,如果你知道其它的避免空指針異常和減少空指針檢查的Java技巧,請和我們分享。
      這些都是簡單的技巧,很容易應用,但是對代碼質量和健壯性有顯著影響。根據我的經驗,只有第一個技巧可以顯著改善代碼質量。如我之前所講,如果你知道任何避免空指針異常和減少空指針檢查的Java技巧,你可以通過評論本文來和分享。
      1) 從已知的String對象中調用equals()和equalsIgnoreCase()方法,而非未知對象。
      總是從已知的非空String對象中調用equals()方法。因為equals()方法是對稱的,調用a.equals(b)和調用b.equals(a)是完全相同的,這也是為什么程序員對于對象a和b這么不上心。如果調用者是空指針,這種調用可能導致一個空指針異常
    Object unknownObject = null;
    //錯誤方式 – 可能導致 NullPointerException
    if(unknownObject.equals("knownObject")){
    System.err.println("This may result in NullPointerException if unknownObject is null");
    }
    //正確方式 - 即便 unknownObject是null也能避免NullPointerException
    if("knownObject".equals(unknownObject)){
    System.err.println("better coding avoided NullPointerException");
    }
      這是避免空指針異常最簡單的Java技巧,但能夠導致巨大的改進,因為equals()是一個常見方法。
      2) 當valueOf()和toString()返回相同的結果時,寧愿使用前者。
      因為調用null對象的toString()會拋出空指針異常,如果我們能夠使用valueOf()獲得相同的值,那寧愿使用valueOf(),傳遞一個null給valueOf()將會返回“null”,尤其是在那些包裝類,像Integer、Float、Double和BigDecimal。
      BigDecimal bd = getPrice();
      System.out.println(String.valueOf(bd)); //不會拋出空指針異常
      System.out.println(bd.toString()); //拋出 "Exception in thread "main" java.lang.NullPointerException"
      3) 使用null安全的方法和庫 有很多開源庫已經為您做了繁重的空指針檢查工作。其中最常用的一個的是Apache commons 中的StringUtils。你可以使用StringUtils.isBlank(),isNumeric(),isWhiteSpace()以及其他的工具方法而不用擔心空指針異常。
    //StringUtils方法是空指針安全的,他們不會拋出空指針異常
    System.out.println(StringUtils.isEmpty(null));
    System.out.println(StringUtils.isBlank(null));
    System.out.println(StringUtils.isNumeric(null));
    System.out.println(StringUtils.isAllUpperCase(null));
    Output:
    true
    true
    false
    false
      但是在做出結論之前,不要忘記閱讀空指針方法的類的文檔。這是另一個不需要下大功夫就能得到很大改進的Java最佳實踐。

    posted @ 2014-10-30 11:56 順其自然EVO 閱讀(171) | 評論 (0)編輯 收藏

    關于在Java代碼中寫Sql語句需要注意的問題

    最近做程序,時不時需要自己去手動將sql語句直接寫入到Java代碼中,寫入sql語句時,需要注意幾個小問題。
      先看我之前寫的幾句簡單的sql語句,自以為沒有問題,但是編譯直接報錯。
      String str = "insert into XXX(a,b,c) values ('"a.getA()"','"a.getB()"','"a.getC()"');";
      研究了半天發現應該是連接字符串問題,第一次修改過后將賦值字段前后加“+”號來完成sql語句。改正后代碼如下
      String str = "insert into XXX(a,b,c) values ('"+a.getA()+"','"+a.getB()+"','"+a.getC()+"');";
      原來在數據庫中給字段動態賦值需要以‘“+···+”’的方式來完成。好的,編譯后成功,將運行的str的結果值放入sql數據庫中測試,沒有問題,自以為一切ok了,結果運行時再次報錯。這把自己困擾住了,反復測試,在數據庫中用sql語句來對比,沒有問題啊,現將我最后成功的代碼放上來,大家看看有沒有什么不同。
      String str = "insert into XXX(a,b,c) values ('"+a.getA()+"','"+a.getB()+"','"+a.getC()+"')";
      沒錯,就是最后的分號,原來在java語句中不能講分號加入到普通的sql語句中,雖然在數據庫中沒有報錯,但是在java中一定還是要注意這種小問題的。

    posted @ 2014-10-30 11:56 順其自然EVO 閱讀(283) | 評論 (0)編輯 收藏

    開發中遇到的java小知識

     今天在優化一個功能的時候遇到了instr與substr函數,之前沒有接觸過這兩個函數,但是今天無意中用到,一查才發現,真是實用的一對兄弟啊。
      先來說說substr函數,這個函數返回的是字符串的一部分。
      substr(string,start,length)
      其中string參數為必須參數,要截取的字符串內容。
      start為必須參數,為起始的位置,可以為正數也可以為負數,正數的話代表從在字符串的指定位置開始;負數代表從字符串結尾的指定位置開始;0代表在字符串中的第一個字符處開始。
      length不是必須參數,為截取的長度,正數代表從 start 參數所在的位置向后返回字符個數;負數代表從字符串末端指定位置向前返回字符個數。
      舉個例子:
      substr("Hello World!",2,1)返回的是e
      substr("Hello World!",2)返回的是ello World!
      substr("Hello World!",-2,1)返回的是d
      substr("Hello World!",-2,-1)返回的是d!
      instr( string1, string2, start_position,nth_appearance ) 函數返回要截取的字符串在源字符串中的位置。
      string1源字符串,要在此字符串中查找。
      string2要在string1中查找的字符串 。
      start_position代表開始的位置。
      nth_appearance代表要查找第幾次出現的string2. 此參數可選,如果省略,默認為 1.如果為負數系統會報錯。
      舉個例子:
      instr("Hello World!","o")返回的是5
      instr("Hello World!","o",1,2)返回的是8。解釋一下,這句話代表"o"從字符串第一個位置開始查詢,第二個“o”出現的位置。
      很有用的兩個函數呢

    posted @ 2014-10-30 11:56 順其自然EVO 閱讀(183) | 評論 (0)編輯 收藏

    僅列出標題
    共394頁: First 上一頁 25 26 27 28 29 30 31 32 33 下一頁 Last 
    <2025年5月>
    27282930123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

    導航

    統計

    常用鏈接

    留言簿(55)

    隨筆分類

    隨筆檔案

    文章分類

    文章檔案

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 青青青国产色视频在线观看国产亚洲欧洲国产综合 | 免费一级成人毛片| 国产精品免费久久| 亚洲国产综合专区在线电影| 在线a免费观看最新网站| 亚洲欧洲日产国码久在线| 久久久久亚洲AV综合波多野结衣| 成人免费视频69| 国产无限免费观看黄网站| 亚洲国产精品xo在线观看| 亚洲精品乱码久久久久久蜜桃| 91制片厂制作传媒免费版樱花 | 亚洲精品WWW久久久久久| 亚洲 无码 在线 专区| 亚洲人成人无码网www国产| 中文字幕亚洲日本岛国片| 亚洲国产精品无码专区在线观看| 成人看的午夜免费毛片| 中文字幕乱码免费看电影| 国产精品高清视亚洲一区二区| 婷婷亚洲综合五月天小说| 国产精品亚洲mnbav网站 | 亚洲国产精品专区在线观看 | 一级毛片免费全部播放| 国产精品亚洲精品| 亚洲一区二区三区偷拍女厕| 国产精品免费综合一区视频| 香蕉97超级碰碰碰免费公| 麻豆精品不卡国产免费看| 免费一级毛片在线播放视频免费观看永久 | 亚洲无码日韩精品第一页| 亚洲精品午夜国产VA久久成人| 亚洲VA综合VA国产产VA中| 国产成人精品日本亚洲专区61| 亚洲va中文字幕无码| 亚洲av日韩av不卡在线观看| 亚洲jjzzjjzz在线播放| 亚洲国产精品无码久久久| 久久精品国产亚洲AV麻豆网站| 亚洲AV无码不卡无码| 亚洲VA中文字幕无码一二三区 |