由小見大-MySQL指令碼部署中的一些策略
線上上環境中部署指令碼,可謂是常在河邊走,哪有不溼鞋,所以大大小小的案例總結下來,還是會發現一些有趣的地方,這些可以作為操作時的一些參考,僅供參考而已。
第一類指令碼是修復指令碼,比如提供的資料修復功能,資料補丁等,這類指令碼的特點是後續的資料變更很可能會依賴於之前的操作,環環相扣。所以一旦執行過程中出現問題,就需要保證這個操作可回退,否則會是雪上加霜。
指令碼1 |
|
|
|
|
|
指令碼2 |
|
|
|
|
|
指令碼3 |
|
|
|
|
|
指令碼4 |
|
|
|
|
|
指令碼5 |
|
|
|
|
|
第二類的指令碼是彼此之間沒有直接聯絡。哪怕是中間執行出一點問題也不會直接影響其他業務。
指令碼1 |
|
指令碼2 |
|
指令碼3 |
|
指令碼4 |
|
指令碼5 |
|
第三類的指令碼介於兩者之間,有互相的依賴,也有彼此獨立的部分。
指令碼1 |
|
|
指令碼2 |
|
|
指令碼3 |
|
|
指令碼4 |
|
|
指令碼5 |
|
|
假設我們已經對上述三類需求很熟悉,很清楚自己在做什麼。在MySQL的場景中是否可以都一一滿足呢。
我們可以做一個簡單的測試來說明。首先我們建立一個表test_abc,然後插入3條數,其中第2條是有問題的,插入可能會報錯。
create table test_abc (id int primary key,name varchar(20));
insert into test_abc values(1,'aa');
insert into test_abc values('aa','bb');
insert into test_abc values(3,'cc');
那現在就有幾種實現方式,
1)執行第2條報錯,直接忽略,繼續執行
2)執行第2條報錯,直接在這裡定格,然後退出
3)執行第2條報錯,然後回滾退出
所以說這樣一個看起來極其簡單的語句其實可能有下面三種執行的結果,這就和我剛開始所說的場景很類似了。
我們來看看具體怎麼實現。
方法1:首先使用source的方式執行指令碼,發現執行在第2條insert出失敗,但是從執行日誌可以看出,是繼續執行了。
mysql> source test1.sql
Query OK, 0 rows affected (0.04 sec)
Query OK, 1 row affected (0.00 sec)
ERROR 1366 (HY000): Incorrect integer value: 'aa' for column 'id' at row 1
Query OK, 1 row affected (0.01 sec)
檢視執行後的表資料,確實id為1和3的記錄都插入了。
mysql> select *from test_abc;
+----+------+
| id | name |
+----+------+
| 1 | aa |
| 3 | cc |
+----+------+
2 rows in set (0.00 sec)
方法2:方法2看起來很簡潔,就是透過重定向的方式來執行,可以從錯誤日誌看出是執行到了第2條語句失敗了。
# mysql test < test1.sql
ERROR 1366 (HY000) at line 5: Incorrect integer value: 'aa' for column 'id' at row 1
檢視資料的情況,會發現前面的執行是成功了,後面都沒執行,直接退出了。
mysql> select *from test_abc;
+----+------+
| id | name |
+----+------+
| 1 | aa |
+----+------+
1 row in set (0.09 sec)
方法3:我們開啟事務,看看能否達到我們的預期結果,可以順利回滾。
mysql>begin;
mysql> source test1.sql
Query OK, 0 rows affected (0.03 sec)
Query OK, 1 row affected (0.00 sec)
ERROR 1366 (HY000): Incorrect integer value: 'aa' for column 'id' at row 1
Query OK, 1 row affected (0.01 sec)
這個時候檢視資料結果,會發現id為1和3都已經插入了。
mysql> select*from test_abc;
+----+------+
| id | name |
+----+------+
| 1 | aa |
| 3 | cc |
+----+------+
2 rows in set (0.00 sec)
我們來嘗試回滾
mysql> rollback;
Query OK, 0 rows affected (0.00 sec)
但是很不幸,沒有任何反應
mysql> select*from test_abc;
+----+------+
| id | name |
+----+------+
| 1 | aa |
| 3 | cc |
+----+------+
2 rows in set (0.00 sec)
這個問題的主要原因是什麼呢,其實是第一句是一個create語句,是DDL,會自動提交事務。所以後續的操作就直接無法回滾了。由此我們需要注意的就是在指令碼中是否有DDL,如果有還是需要特別 注意的。
方法4:
所以我們剔除指令碼里面的DDL,分開單獨執行,指令碼只保留了那3條insert.
然後我們手工開啟事務。
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> source test1.sql
Query OK, 1 row affected (0.00 sec)
ERROR 1366 (HY000): Incorrect integer value: 'aa' for column 'id' at row 1
Query OK, 1 row affected (0.01 sec)
這個時候檢視資料,id為1和3的結果都在。
mysql> select *from test_abc;
+----+------+
| id | name |
+----+------+
| 1 | aa |
| 3 | cc |
+----+------+
2 rows in set (0.00 sec)
果斷回滾,會發現資料可以達到我們的預期了。
mysql> rollback;
Query OK, 0 rows affected (0.09 sec)
mysql> select *from test_abc;
Empty set (0.00 sec)
所以針對上面三種情況,我們可以得到一很明確的結果。
而如果可以儘可能還是在事務裡來控制吧,畢竟MySQL是預設自動提交的。後悔了都來不及。
對於事務的完整性,還有兩點需要說一下,第一個是事務正常退出,事務是回滾還是提交。另外一個則是殺掉執行的會話,事務會預設提交還是回滾。
我們一個一個來測試,先來看kill會話的部分。
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into test_abc values(5,'ee');
Query OK, 1 row affected (0.00 sec)
然後開啟另外一個視窗 kill掉當前執行的會話。然後繼續觀察。
查詢的時候,會發現原來的會話其實已經殺掉了,會自動開啟一個新的會話。很明顯,事務做了回滾。
mysql> select *from test_abc;
ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
Connection id: 639
Current database: test
+----+------+
| id | name |
+----+------+
| 1 | aa |
+----+------+
1 row in set (0.09 sec)
另外一個則是正常退出情況下的
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into test_abc values(1,'ff');
Query OK, 1 row affected, 0 warning (0.00 sec)
mysql> select *from t1;
+------+------+
| col1 | col2 |
+------+------+
| 1 | ff|
+------+------+
1 row in set (0.00 sec)
mysql> exit --正常退出
Bye
重新登入來驗證,會發現事務已經回滾了。
mysql> select *from t1;
Empty set (0.00 sec)
所以透過上面的測試我們可以很清晰的知道這些可能的場景和具體的應對策略,如果明白了這些,在具體業務的操作中至少會長個心。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/23718752/viewspace-2146627/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- MySQL8.0的自動部署指令碼MySql指令碼
- 由小見大!不規則造型按鈕解決方案
- 一些奇怪的 unix 指令名字的由來(轉)
- 一些 JavaScript 中的程式碼小技巧JavaScript
- JDK原始碼中的一些“小技巧”JDK原始碼
- MySQL 5.5 執行指令碼中的SQLMySql指令碼
- 理解 shell 指令碼中的常見用法: 2>&1指令碼
- MySQL的一些功能實用的Linux shell指令碼分享MySqlLinux指令碼
- 關於MySQL的一些小見解MySql
- PowerShell 指令碼執行策略指令碼
- 一鍵部署指令碼指令碼
- MySQL指令碼MySql指令碼
- 一些有趣的VBS指令碼指令碼
- oracle dba 的一些指令碼Oracle指令碼
- MySQL中binlog備份指令碼分享MySql指令碼
- 一次rman 指令碼的部署指令碼
- 練習時的docker部署指令碼Docker指令碼
- linux中的一些常用指令Linux
- ORACLE一些不常用的指令碼Oracle指令碼
- LNMP自動部署指令碼LNMP指令碼
- 通用程式部署shell指令碼指令碼
- MySQL 常用指令碼MySql指令碼
- 【轉】MySQL 建表的優化策略 小結MySql優化
- Mysql中的小技巧MySql
- Mysql MHA部署-07常見問題MySql
- JS常見的小程式碼JS
- Ollydbg 編寫指令碼的一些語法及例子(OD指令碼)指令碼
- 知物由學 | Lua指令碼保護的前世今生指令碼
- 一次 oracle rman 指令碼的部署Oracle指令碼
- 開發中hive常見的調優策略Hive
- mysql中一些常見問題MySql
- SQL指令碼注入的不常見方法概括SQL指令碼
- MySQL批量轉換表名為小寫(Python指令碼)MySqlPython指令碼
- Rails程式用到的一些指令碼命令AI指令碼
- git repo程式碼部署策略及工具Git
- Docker 指令碼化一鍵部署Docker指令碼
- KafKa+Zookeeper+Flume部署指令碼Kafka指令碼
- vue自動化部署指令碼Vue指令碼