主頁 > 軟體設計 > 使用Python決議并“篡改”MySQL的Binlog

使用Python決議并“篡改”MySQL的Binlog

2020-10-01 04:15:11 軟體設計

文章目錄

  • 前言
  • Binlog的結構
  • 恢復誤洗掉的記錄
  • 找出 Binlog 中的大事務
  • 切割 Binlog 中的大事務
  • 后記

前言

MySQL 的 Binlog 記錄著 MySQL 資料庫的所有變更資訊,了解 Binlog 的結構可以幫助我們決議Binlog,甚至對 Binlog 進行一些修改,或者說是“篡改”,例如實作類似于 Oracle 的 flashback 的功能,恢復誤洗掉的記錄,把 update 的記錄再還原回去等,本文將帶您探討一下這些神奇功能的實作,您會發現比您想象地要簡單得多,本文指的 Binlog 是 ROW 模式的 Binlog,這也是 MySQL 8 里的默認模式,STATEMENT 模式因為使用中有很多限制,現在用地越來越少了,

Binlog的結構

Binlog由事件(event)組成,請注意是事件(event)不是事務(transaction),一個事務可以包含多個事件,事件描述對資料庫的修改內容,
從 MySQL 5 版本開始,Binlog 采用的是 v4 版本,事件的型別根據 MySQL 的內部檔案,有下面36類:

enum Log_event_type { 
  UNKNOWN_EVENT= 0, 
  START_EVENT_V3= 1, 
  QUERY_EVENT= 2, 
  STOP_EVENT= 3, 
  ROTATE_EVENT= 4, 
  INTVAR_EVENT= 5, 
  LOAD_EVENT= 6, 
  SLAVE_EVENT= 7, 
  CREATE_FILE_EVENT= 8, 
  APPEND_BLOCK_EVENT= 9, 
  EXEC_LOAD_EVENT= 10, 
  DELETE_FILE_EVENT= 11, 
  NEW_LOAD_EVENT= 12, 
  RAND_EVENT= 13, 
  USER_VAR_EVENT= 14, 
  FORMAT_DESCRIPTION_EVENT= 15, 
  XID_EVENT= 16, 
  BEGIN_LOAD_QUERY_EVENT= 17, 
  EXECUTE_LOAD_QUERY_EVENT= 18, 
  TABLE_MAP_EVENT = 19, 
  PRE_GA_WRITE_ROWS_EVENT = 20, 
  PRE_GA_UPDATE_ROWS_EVENT = 21, 
  PRE_GA_DELETE_ROWS_EVENT = 22, 
  WRITE_ROWS_EVENT = 23, 
  UPDATE_ROWS_EVENT = 24, 
  DELETE_ROWS_EVENT = 25, 
  INCIDENT_EVENT= 26, 
  HEARTBEAT_LOG_EVENT= 27, 
  IGNORABLE_LOG_EVENT= 28,
  ROWS_QUERY_LOG_EVENT= 29,
  WRITE_ROWS_EVENT = 30,
  UPDATE_ROWS_EVENT = 31,
  DELETE_ROWS_EVENT = 32,
  GTID_LOG_EVENT= 33,
  ANONYMOUS_GTID_LOG_EVENT= 34,
  PREVIOUS_GTIDS_LOG_EVENT= 35, 
  ENUM_END_EVENT 
  /* end marker */ 
};

每個 Binlog 檔案總是以 Format Description Event 作為開始,以 Rotate Event 結束作為結束,我們來看一個 Binlog 的例子:

mysql>  show binlog events in 'scut.000023';
+-------------+-----+----------------+-----------+-------------+--------------------------------------------------------+
| Log_name    | Pos | Event_type     | Server_id | End_log_pos | Info                                                   |
+-------------+-----+----------------+-----------+-------------+--------------------------------------------------------+
| scut.000023 |   4 | Format_desc    |      1024 |         123 | Server ver: 5.7.31-0ubuntu0.16.04.1-log, Binlog ver: 4 |
| scut.000023 | 123 | Previous_gtids |      1024 |         154 |                                                        |
| scut.000023 | 154 | Anonymous_Gtid |      1024 |         219 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'                   |
| scut.000023 | 219 | Query          |      1024 |         291 | BEGIN                                                  |
| scut.000023 | 291 | Rows_query     |      1024 |         330 | # delete from tt1                                      |
| scut.000023 | 330 | Table_map      |      1024 |         378 | table_id: 111 (test.tt1)                               |
| scut.000023 | 378 | Delete_rows    |      1024 |         434 | table_id: 111 flags: STMT_END_F                        |
| scut.000023 | 434 | Xid            |      1024 |         465 | COMMIT /* xid=216 */                                   |
| scut.000023 | 465 | Rotate         |      1024 |         507 | scut.000024;pos=4                                      |
+-------------+-----+----------------+-----------+-------------+--------------------------------------------------------+
9 rows in set (0.00 sec)

關于“show binlog events”語法顯示的每一列的作用說明如下:

列名說明
Log_name當前事件所在的 binlog 檔案名稱
Pos當前事件的開始位置,每個事件都占用固定的位元組大小,結束位置(End_log_position)減去Pos,就是這個事件占用的位元組數,
Event_type表示事件的型別
Server_id表示產生這個事件的 MySQL server_id
End_log_position下一個事件的開始位置
Info當前事件的描述資訊

每個事件型別的說明可以參考 MySQL 的內部檔案,我們這里說明一下這里遇到的幾個事件型別:

事件名說明
Format_desc是 binlog 檔案的第一個事件,在 Info 列,我們可以看到,其標明了 MySQL Server 的版本是5.7.31, Binlog 版本是4,
Previous_gtids這是表示之前的 Binlog 檔案中,已經執行過的 GTID,需要我們開啟 GTID 選項,這個事件才會有值,
Anonymous_Gtid沒有開啟 GTID 選項時,每個事務開始的事件;
Query是向 Binlog 發生一個陳述句,這里是事務的開始陳述句 begin,
Rows_query記錄SQL,這個事件只有當引數 binlog_rows_query_log_events 為 TRUE 的情況下才會產生,這個引數的默認為值為 FALSE,
Table_map記錄將要被修改的表的結構
Delete_rows從表中洗掉一個記錄
Xid事務 commit 的時候寫入事務 ID
RotateRotate Event是每個Binlog檔案的結束事件,在Info列中,我們看到了其指定了下一個 Binlog檔案的名稱是 mysql-bin.000018,

根據官方檔案,事件(event)資料結構如下:

+=====================================+
| event  | timestamp         0 : 4    |
| header +----------------------------+
|        | type_code         4 : 1    |
|        +----------------------------+
|        | server_id         5 : 4    |
|        +----------------------------+
|        | event_length      9 : 4    |
|        +----------------------------+
|        | next_position    13 : 4    |
|        +----------------------------+
|        | flags            17 : 2    |
|        +----------------------------+
|        | extra_headers    19 : x-19 |
+=====================================+
| event  | fixed part        x : y    |
| data   +----------------------------+
|        | variable part              |
+=====================================+

恢復誤洗掉的記錄

現在我們已經了解了 Binlog 的結構,我們可以試著修改 Binlog 里的資料,例如前面舉例的 Binlog 洗掉了一條記錄,我們可以試著把這條記錄恢復,Binlog 里面有個洗掉行(DELETE_ROWS_EVENT)的事件,就是這個事件洗掉了記錄,這個事件和寫行(WRITE_ROWS_EVENT)的事件的資料結構是完全一樣的, 只是洗掉行事件的型別是32,寫行事件的型別是30,我們把對應的 Binlog 位置的32改成30即可把已經洗掉的記錄再插入回去,從前面的“show binlog events”里面可看到這個 DELETE_ROWS_EVENT 是從位置378開始的,這里的位置就是 Binlog 檔案的實際位置(以位元組為單位),從事件(event)的結構里面可以看到 type_code 是在 event 的第5個位元組,我們寫個 Python 小程式把把第383(378+5=383)位元組改成30即可,當然您也可以用二進制編輯工具來改,下面是這個 Python 小程式的例子:

#! /usr/bin/python3
import sys

if len(sys.argv) != 3:
        print ('Please run chtype.py inputType changedType.')
        sys.exit()

inputType=open(sys.argv[1],"rb")
changedType=open(sys.argv[2],"wb")

changedType.write(inputType.read(382))
changedType.write(chr(30).encode())
inputType.seek(1,1)
while True:
  line = inputType.readline()  
  if not line:
        break
  changedType.write(line)
  
inputType.close()
changedType.close()

我們把原來的 Binlog 和修改后的 Binlog 進行一個對比:
Binlog 修改對比

發現這兩個 Binlog只有一個位元組有區別,也就是 type_code 從32變成了30,注意 Binlog 里面顯示的是16進制的數字,
我們分別應用一下原來的 Binlog 和修改后的 Binlog,看看效果如何?

$ mysql  -e "select * from test.tt1";
$ mysqlbinlog ./scut.000023_ch |mysql
$ mysql  -e "select * from test.tt1";
+---------------------+
| col1                |
+---------------------+
| aaaaaaaaaaaaaaaaaaa |
+---------------------+
$ mysqlbinlog ./scut.000023 |mysql
$ mysql  -e "select * from test.tt1";
$ mysqlbinlog ./scut.000023_ch |mysql
$ mysql  -e "select * from test.tt1";
+---------------------+
| col1                |
+---------------------+
| aaaaaaaaaaaaaaaaaaa |
+---------------------+

我們發現這兩個 Binlog 可以分別把對應的記錄洗掉和插入到 MySQL 資料庫中,這樣我們就成功地實作了類似于 Oracle 的 flashback 功能,

找出 Binlog 中的大事務

由于 ROW 模式的 Binlog 是每一個變更都記錄一條日志,因此一個簡單的 SQL,在 Binlog 里可能會產生一個巨無霸的事務,例如一個不帶 where 的 update 或 delete 陳述句,修改了全表里面的所有記錄,每條記錄都在 Binlog 里面記錄一次,結果是一個巨大的事務記錄,這樣的大事務經常是產生麻煩的根源,我的一個客戶有一次向我抱怨,一個 Binlog 前滾,滾了兩天也沒有動靜,我把那個 Binlog 決議了一下,發現里面有個事務產生了 1.4G 的記錄,修改了66萬條記錄!下面是一個簡單的找出 Binlog 中大事務的 Python 小程式,我們知道用 mysqlbinlog 決議的 Binlog,每個事務都是以BEGIN 開頭,以 COMMIT 結束,我們找出 BENGIN 前面的“# at”的位置,檢查 COMMIT 后面的“# at”位置,這兩個位置相減即可計算出這個事務的大小,下面是這個 Python程式的例子,

$ cat ./checkBigTran.py 
#! /usr/bin/python3
import sys

position=0
beginPosition=0
endPosition=0
maxSize=0
isEnd=0
for line in sys.stdin:
      if line[: 4]=='# at':
          position=int(line[5:])
          if isEnd:
             endPosition=position
             isEnd=0
      if line[: 5]=='BEGIN':
          beginPosition=position
      if line[: 6]=='COMMIT':
          isEnd=1
      if endPosition-beginPosition>maxSize:
          maxBeginPosition= beginPosition
          maxEndPosition=endPosition
          maxSize=endPosition-beginPosition

print("The largest transaction size is %d, the begion position is %d, the end position is %d." % (maxSize,maxBeginPosition,maxEndPosition))

用這個小程式檢查一下可能包含大事務的 Binlog:

$ mysqlbinlog binlog1|./checkBigTran.py 
The largest transaction size is 1468183501, the begion position is 5737766, the end position is 1473921267.

發現里面果然包含了一個1.4G的大事務,

切割 Binlog 中的大事務

對于大的事務, MySQL 會把它分解成多個事件(注意一個是事務TRANSACTION,另一個是事件EVENT),事件的大小由引數 binlog-row-event-max-size 決定,這個引數默認是8K,因此我們可以把若干個事件切割成一個單獨的略小的事務,例如下面這個 Binlog:

mysql> show binlog events in 'scut.000025';
+-------------+-----+----------------+-----------+-------------+--------------------------------------------------------+
| Log_name    | Pos | Event_type     | Server_id | End_log_pos | Info                                                   |
+-------------+-----+----------------+-----------+-------------+--------------------------------------------------------+
| scut.000025 |   4 | Format_desc    |      1024 |         123 | Server ver: 5.7.31-0ubuntu0.16.04.1-log, Binlog ver: 4 |
| scut.000025 | 123 | Previous_gtids |      1024 |         154 |                                                        |
| scut.000025 | 154 | Anonymous_Gtid |      1024 |         219 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'                   |
| scut.000025 | 219 | Query          |      1024 |         291 | BEGIN                                                  |
| scut.000025 | 291 | Rows_query     |      1024 |         343 | # insert into tt1 values ('1')                         |
| scut.000025 | 343 | Table_map      |      1024 |         391 | table_id: 111 (test.tt1)                               |
| scut.000025 | 391 | Write_rows     |      1024 |         429 | table_id: 111 flags: STMT_END_F                        |
| scut.000025 | 429 | Rows_query     |      1024 |         481 | # insert into tt1 values ('2')                         |
| scut.000025 | 481 | Table_map      |      1024 |         529 | table_id: 111 (test.tt1)                               |
| scut.000025 | 529 | Write_rows     |      1024 |         567 | table_id: 111 flags: STMT_END_F                        |
| scut.000025 | 567 | Xid            |      1024 |         598 | COMMIT /* xid=397 */                                   |
| scut.000025 | 598 | Rotate         |      1024 |         640 | scut.000026;pos=4                                      |
+-------------+-----+----------------+-----------+-------------+--------------------------------------------------------+
12 rows in set (0.01 sec)

這個 Binlog 的兩個 insert 是在一個事務里面完成的,我們可以兩個事務之間插入 xid、Anonymous_Gtid, Query 等三個事件把一個事務切割成兩個事務, Rows_query 這個事件不用插入,這個事件是注釋掉了的,記錄的是執行的 SQL,這個事件只有在引數 binlog_rows_query_log_events 為 on 時才會有,默認是 off ,相應的 Python 程式如下:

# cat splitTran.py 
#! /usr/bin/python3
import sys

if len(sys.argv) != 3:
    print ('Please run splitTrans.py inputBinlog changedBinlog.')
    sys.exit()

inputBinlog=open(sys.argv[1],"rb")
changedBinlog=open(sys.argv[2],"wb")

changedBinlog.write(inputBinlog.read(429))   # read from the head of  input binlog file to the first insert, then write into the changed binlog file.
firstInsert=inputBinlog.tell()
inputBinlog.seek(567,0)  # locate to the xid event
changedBinlog.write(inputBinlog.read(31))  # read from 567 to 598, write xid event, into the changed binlog file.
inputBinlog.seek(154,0)  # locate to the Anonymous_Gtid, Query events.
changedBinlog.write(inputBinlog.read(137))  # read from 154 to 291, write Anonymous_Gtid, Query events into changed binlog file.
inputBinlog.seek(firstInsert)
while True:
      line = inputBinlog.readline()  
      if not line:
           break
      changedBinlog.write(line)
  
inputBinlog.close()
changedBinlog.close()

我們執行這個 Python 程式,生成一個新的 Binlog ,然后把新的 Binlog 應用到 MySQL,

$  ./splitTran.py scut.000025 scut.000025_ch
$ mysqlbinlog scut.000025_ch |mysql
$ 

我們看看執行地效果:


mysql> show binlog events in 'scut.000026';
+-------------+-----+----------------+-----------+-------------+------------------------------------------------------------------------------------------------------------------------------------+
| Log_name    | Pos | Event_type     | Server_id | End_log_pos | Info                                                                                                                               |
+-------------+-----+----------------+-----------+-------------+------------------------------------------------------------------------------------------------------------------------------------+
| scut.000026 |   4 | Format_desc    |      1024 |         123 | Server ver: 5.7.31-0ubuntu0.16.04.1-log, Binlog ver: 4                                                                             |
| scut.000026 | 123 | Previous_gtids |      1024 |         154 |                                                                                                                                    |
| scut.000026 | 154 | Anonymous_Gtid |      1024 |         219 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'                                                                                               |
| scut.000026 | 219 | Query          |      1024 |         287 | BEGIN                                                                                                                              |
| scut.000026 | 287 | Rows_query     |      1024 |         439 | # BINLOG '
EbA7XxMABAAAMAAAAIcBAAAAAG8AAAAAAAEABHRlc3QAA3R0MQAB/gL+QAEYYumN
EbA7Xx4ABAAAJgAAAK0BAAAAAG8AAAAAAAEAAgAB//4BMeeyFcw=
' |
| scut.000026 | 439 | Table_map      |      1024 |         487 | table_id: 111 (test.tt1)                                                                                                           |
| scut.000026 | 487 | Write_rows     |      1024 |         525 | table_id: 111 flags: STMT_END_F                                                                                                    |
| scut.000026 | 525 | Xid            |      1024 |         556 | COMMIT /* xid=425 */                                                                                                               |
| scut.000026 | 556 | Anonymous_Gtid |      1024 |         621 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'                                                                                               |
| scut.000026 | 621 | Query          |      1024 |         689 | BEGIN                                                                                                                              |
| scut.000026 | 689 | Rows_query     |      1024 |         841 | # BINLOG '
F7A7XxMABAAAMAAAABECAAAAAG8AAAAAAAEABHRlc3QAA3R0MQAB/gL+QAE+WKbj
F7A7Xx4ABAAAJgAAADcCAAAAAG8AAAAAAAEAAgAB//4BMmfP2Zk=
' |
| scut.000026 | 841 | Table_map      |      1024 |         889 | table_id: 111 (test.tt1)                                                                                                           |
| scut.000026 | 889 | Write_rows     |      1024 |         927 | table_id: 111 flags: STMT_END_F                                                                                                    |
| scut.000026 | 927 | Xid            |      1024 |         958 | COMMIT /* xid=432 */                                                                                                               |
+-------------+-----+----------------+-----------+-------------+------------------------------------------------------------------------------------------------------------------------------------+
14 rows in set (0.00 sec)

我們看到兩個 insert 已經分開到兩個事務里面了,

后記

ROW模式下,即使我們只更新了一條記錄的其中某個欄位,也會記錄每個欄位變更前后的值,這個行為是 binlog_row_image 引數控制的,這個引數有3個值,默認為FULL,也就是記錄列的所有修改,即使欄位沒有發生變更也會記錄,這樣我們就可以實作類似 Oracle 的 flashback 的功能,我個人估計 MySQL 未來的版本從可能會基于 Binlog 推出這樣的功能,
了解了 Binlog 的結構,再加上 Python 這把瑞士軍刀,我們還可以實作很多功能,例如我們可以統計哪個表被修改地最多? 我們還可以把 Binlog 切割成一段一段的,然后再重組,可以靈活地進行 MySQL 資料庫的修改和遷移等作業,

姚遠2018 CSDN認證博客專家 10G OCM 12C OCM
Oracle10g,12c OCM; MySQL 5.6,5.7,8.0 OCP;CCNA; EMC Certified; IBM P Certified; RHCE; SQLServer 764; DB2 Certified; TOEIC 890;獲得過兩次國家部級科技進步獎;發明過兩項計算機專利,

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/144066.html

標籤:其他

上一篇:深入oracle索引,磁區

下一篇:MySQL8.0基本操作以及進階操作

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more