MySQL AUTO_INCREMENT 會 “跳號”

發佈於 發佈留言分類: 資訊科技

偶爾開發人員會被自動編號欄位跳號的現象誤導, 將其解釋為程式有寫入資料庫, 但是被資料庫把資料給搞丟了. (因為開發人員沒看到程式執行的錯誤, 也不認為寫入資料庫的資料有問題, 更不認為程式寫入資料庫的邏輯有問題.)

578326 這筆資料程式明明有寫入, MySQL 資料庫怎麼把資料給寫丟了呢?

其實, 關聯式資料庫引擎發展這麼久了, 要它把寫入的資料 “搞丟”, 應該算是還蠻困難的一件事. 開發人員進行程式除錯的時候, 抱持著千錯萬錯, 絕對不會是資料庫引擎的錯, 可能是一個還不錯的原則!

自動編號欄位會 “跳號”, 也不是 MySQL 特有的行為, Oracle / SQL Server 也都是如此.

以下是用來展示 MySQL AUTO_INCREMENT 欄位跳號現象的範例 SQL:

USE MYDB;

DROP TEMPORARY TABLE IF EXISTS t1;
DROP TEMPORARY TABLE IF EXISTS l1;

CREATE TEMPORARY TABLE t1
(
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
f1 VARCHAR(50) NOT NULL,
PRIMARY KEY (id)
);

CREATE TEMPORARY TABLE l1
(
message VARCHAR(255) NOT NULL
);

INSERT INTO t1 (f1) VALUES ('r1');
INSERT INTO l1 (message)
SELECT CONCAT_WS(' ', 'In the beginning,', 't1 has only', (SELECT count(*) FROM t1), 'rows.')
FROM DUAL;
INSERT INTO l1 (message)
SELECT CONCAT('This row is:', '(', (SELECT CONCAT_WS(', ', id, f1) FROM t1 ORDER BY id DESC LIMIT 1), ')')
FROM DUAL;

START TRANSACTION;
INSERT INTO t1 (f1) VALUES ('r2');
INSERT INTO t1 (f1) VALUES ('r3');
ROLLBACK;

INSERT INTO l1 (message)
SELECT CONCAT_WS(' ', 'After two rollbacked inserts,', 't1 still has', (SELECT count(*) FROM t1), 'row only.')
FROM DUAL;
INSERT INTO l1 (message)
SELECT CONCAT_WS(' ', 'Next auto increment id will be: ', LAST_INSERT_ID() + 1)
FROM DUAL;
INSERT INTO t1 (f1) VALUES ('r4');
INSERT INTO l1 (message)
SELECT CONCAT_WS(' ', 'After 1 committed insert,', 't1 now has', (SELECT count(*) FROM t1), 'rows.')
FROM DUAL;
INSERT INTO l1 (message)
SELECT CONCAT('The new row is: ', '(', (SELECT CONCAT_WS(', ', id, f1) FROM t1 ORDER BY id DESC LIMIT 1), ')')
FROM DUAL;

SELECT * FROM l1;

DROP TEMPORARY TABLE IF EXISTS t1;
DROP TEMPORARY TABLE IF EXISTS l1;
MySQL AUTO_INCREMENT 欄位跳號範例 SQL 輸出

參考資料

MySQL 動態產生包含特定日期所有分鐘的資料表

發佈於 發佈留言分類: 資訊科技

應用程式常常會有排程的需求, 在資料庫的應用中, 排程所需要的時間表可以用下列這幾種方式來產生:

  1. 事先產生好應用程式所需要的時間表於實體資料表
  2. 利用查表法動態產生虛擬資料表
  3. 利用演算法產生虛擬資料表

shortie 將於本文中, 示範第三種方法在 MySQL 的一種應用方式. 下面這段 SQL 將會產生某特定日期中的 1440 (24 * 60) 分鐘資料表, 用以跟其他資料表 JOIN, 達成應用程式之所需.

SELECT ADDDATE(d.the_date, INTERVAL t.the_time MINUTE) AS the_date_time
FROM (SELECT '2019-03-18' the_date) AS d,
(SELECT the_hour * 60 + the_minute AS the_time
FROM (SELECT 0 AS the_hour
UNION
SELECT 1
UNION
SELECT 2
UNION
SELECT 3
UNION
SELECT 4
UNION
SELECT 5
UNION
SELECT 6
UNION
SELECT 7
UNION
SELECT 8
UNION
SELECT 9
UNION
SELECT 10
UNION
SELECT 11
UNION
SELECT 12
UNION
SELECT 13
UNION
SELECT 14
UNION
SELECT 15
UNION
SELECT 16
UNION
SELECT 17
UNION
SELECT 18
UNION
SELECT 19
UNION
SELECT 20
UNION
SELECT 21
UNION
SELECT 22
UNION
SELECT 23) AS the_hours,
(SELECT the_ten * 10 + the_one AS the_minute
FROM (SELECT 0 AS the_ten
UNION
SELECT 1
UNION
SELECT 2
UNION
SELECT 3
UNION
SELECT 4
UNION
SELECT 5) AS tens,
(SELECT 0 AS the_one
UNION
SELECT 1
UNION
SELECT 2
UNION
SELECT 3
UNION
SELECT 4
UNION
SELECT 5
UNION
SELECT 6
UNION
SELECT 7
UNION
SELECT 8
UNION
SELECT 9) AS ones) AS the_minutes
ORDER BY the_time) AS t
ORDER BY the_date_time;

參考資料

查詢 MySQL 資料表大小的 SQL

發佈於 發佈留言分類: 資訊科技

雖然說很多 MySQL 工具都會提供資料表大小的資訊, 但是有些情況還是使用 SQL 查詢來得正確與快速. 以下面這個例子來說, SQL Maestro for MySQL 可以提供下列的資料表資訊清單:

SQL Maestro for MySQL – Browse Tables

雖然 Browse Tables 可以顯示資料表的大小, 但是我們可以注意到其中大小超過 2GB 的資料表顯示的資訊是 0. 因此在此文中紀錄查詢資料表大小的 SQL 備用.

information_schema.TABLES

SELECT t.table_schema AS                                               'Schema Name',
t.table_name AS 'Table Name',
ROUND(((t.data_length + index_length) / 1024 / 1024), 2) 'Size in MB',
ROUND(((t.data_length + index_length) / 1024 / 1024 / 1024), 2) 'Size in GB'
FROM information_schema.TABLES t
WHERE t.table_schema = 'MYDB'
AND t.data_length > 512 * 1024 * 1024
ORDER BY 'Size in MB' DESC;
Sample output

上述範例乃是符合 shortie 個人所需, 讀者可參考文件說明自行變化.

SHOW TABLE STATUS

SHOW TABLE STATUS FROM MYDB WHERE Data_length > 512 * 1024 * 1024;
Sample output

上述範例乃是符合 shortie 個人所需, 讀者可參考文件說明自行變化.

參考資料

資料庫轉換工具研究 v2019.09

發佈於 發佈留言分類: 資訊科技

資料庫是企業存放資料的主要方式, 市場上也有許多不同的資料庫管理系統可供企業選用.

企業內部有極大的可能性, 會存在一種以上的資料存放方式, 從最簡單的文字檔案、試算表檔案, 到高度複雜的企業等級資料庫管理系統等. 若是上述的狀況成立, 企業所使用的資料就必須在這些不同的存放方式之間流動, 以適合各自的應用情境; 同時企業也必須能夠確保這些不同存放方式中的資料是一致的, 以免錯誤的資料對企業活動產生不良的影響.

至於不同企業之間, 是否會使用不同的資料存放方式, 其可能性幾乎接近 100%, 雖然不同企業間的資料交換, 不如企業內部的部門間密切, 但是為了同步彼此之間所進行的商業活動, 總免不了要進行某總程度的資料交換.

資料庫轉換工具的用途之一就是為了這些企業內部、外部間之資料交換工作所設計.

免費工具

付費工具

自製工具元件

參考資料

SystemRescueCd

發佈於 發佈留言分類: 資訊科技

電腦突然開不了機, 有時候真的會讓人覺得很沮喪.

大多數無法順利開機的故障, 都只是因為開機所需要的系統檔案無法讀取 (磁區損毀、病毒或意外刪除等), 卻因此造成無法進入系統, 也無法將系統中有用的資料檔案取出.

進行任何進一步的修復工作前, 我們需要一個可順利使用故障系統開機的救援工具, 而 SystemRescueCd 算是此類工具中, shortie 覺得用來還算順手的工具之一.

參考資料

MySQL Workbench 8.0.15

發佈於 發佈留言分類: 資訊科技

為了發行而發行的版本? 這也算是一招.

This release contains no functional changes and is published to align version number with the MySQL Server 8.0.15 release.

https://dev.mysql.com/doc/relnotes/workbench/en/news-8-0-15.html

MySQL Workbench 8.0.15 About

參考資料

EdgeRouter PoE (ERPoe-5) 變磚後該這麼修

發佈於 發佈留言分類: 資訊科技

公司使用的 ERPoe-5 路由器, 某日在跳電/復電的過程中造成損壞, 使用 Hardware Reset 程序亦無法回復運作, 真真實實的成為一個「磚塊」. 一方面緊急採購了一部 Synology RT2600ac 路由器應急, 一方面也思考如何診斷 ERPoe-5 變磚的真正原因.

準備工作

  • RJ45 serial console cable
  • TFTP 伺服程式
    • 可以用來診斷的電腦是 Ubuntu 18.04 LTS, 因此 shortie 準備的是 tftpd-hpa 伺服程式.
  • DHCP 伺服程式

第一步: 取得 console 連接埠輸出, 確認損壞方式

使用 RJ45 serial console 連接線連接診斷電腦與 ERPoe-5 後, 可利用下列指令接收輸出:

$ screen /dev/ttyUSB0 115200

檢視 ERPoe-5 的輸出之後, 發現 kernel panic 訊息難怪她會變磚了:

ERPoe-5 boots to kernel panic

第二步: 參考 EMRK 說明, 執行 emrk-reinstall

不論有沒有設定好 DHCP, 進入 U-Boot 提示符號之後, 都可以依照文件中的指示設定 tftpboot所需要的參數. 一旦成功下載 emrk-0.9c.bin 之後, 就可以使用 bootoctlinux $loadaddr 讓 ERPoe-5 成功開機.

開機完成之後, 我們就可執行 emrk-reinstall 從網路下載最新的韌體: http://dl.ubnt.com/firmwares/edgemax/v1.10.x/ER-e100.v1.10.8.5142440.tar讓 ERPoe-5 恢復正常運作. 過程中注意兩點:

  • 提供可設定正常上網的 DHCP 對網路設定有幫助.
  • 輸入韌體的網址時要小心, 建議檢查三次以上.

後話

整個修復的過程, 從 serial console 輸出的訊息來看都很完美, 可惜的是在執行完重新安裝韌體之後, 重新開機還是出現 Kernel Panic 訊息, 看來公司這個 ERPoe-5 是確確實實變成一個磚塊了.

參考資料

Google 付了四千萬美元給 Fossil 買這東西

發佈於 發佈留言分類: 資訊科技

這筆交易的標的物是神秘的智慧手錶技術, 據傳聞可能是源自於 Misfit. 花了ˊ這麼些錢, 除了買智財 (IP, intellectual property) 和研發團隊主力之外, 如果沒跟醫療服務扯上一點關係的話, 那就不知道 Google 葫蘆裡賣甚麼藥了.

參考資料