瀏覽標籤:

MariaDB

select...for update再insert造成deadlock的陷阱

最近在寫購票系統,因而踩中了這個坑。這個坑其實對InnoDB的鎖的觀念不熟悉的人會很難發現造成deadlock的原因,因此想特別寫一篇記錄一下,幫助也在開發類似功能的大家少走一點冤望路。

本篇的講解順序會先帶大家重現我之前引發Deadlock的購票功能邏輯,再來說明資料表使用InnoDB引擎下產生如此Deadlock的原因。

 

環境

  • 本篇範例使用的DB是 MariaDB 10.3.7 (開源版的MySQL)
  • 資料表採用預設的 InnoDB 引擎,隔離層級也是預設的 Repeatable Read
  • 範例資料表ticket的schema如下:
CREATE TABLE `ticket` (
  `id`      int(11) NOT NULL AUTO_INCREMENT,
  `show_id` int(11) NOT NULL,
  `user_id` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `ticket_show_id_IDX` (`show_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4

id是主鍵(PK)、show_id為了之後查詢上的需要,有建非唯一索引(non-unique index)、user_id理論上是外鍵(FK),但這個欄位不是本篇的重點所以忽略他。

  閱讀更多

Docker Compose File (Apache+PHP+MariaDB+phpMyAdmin)

備份一下在自己電腦測試網頁用的Docker Compose

(Apache2 + PHP 7.2 + MariaDB 10 + phpMyAdmin)

version: '3.1'

services:

  mariadb:
    container_name: mariadb10
    image: mariadb
    restart: unless-stopped
    ports:
      - 3006:3006
    environment:
      - MYSQL_ALLOW_EMPTY_PASSWORD=1
    volumes:
      - /Users/AndyWu/Documents/Docker/mysql:/var/lib/mysql
    networks:
      my_network:
        ipv4_address: "192.168.250.2"

  apache2:
    container_name: apache2
    image: mobingi/ubuntu-apache2-php7:7.2
    restart: unless-stopped
    ports:
      - 80:80
    volumes:
      - /Users/AndyWu/Documents/Docker/apache2+php7.2:/var/www/html
    networks:
      my_network:
        ipv4_address: "192.168.250.3"
    depends_on:
      - mariadb

  phpmyadmin:
    container_name: phpmyadmin
    image: phpmyadmin/phpmyadmin
    restart: unless-stopped
    ports:
      - 81:80
    environment:
      - PMA_ARBITRARY=1
      - PMA_HOST=192.168.250.2
      - PMA_PORTS=3006
    networks:
      my_network:
        ipv4_address: "192.168.250.4"
    depends_on:
      - mariadb

networks:
  my_network:
    driver: bridge
    ipam:
      config:
        - subnet: "192.168.250.0/24"

[MySQL / MariaDB] CSV檔匯入資料表

最近有從網路上下載CSV檔案,並且匯入資料庫準備拿來做分析的需求

一開始嘗試用phpMyAdmin裡的匯入功能

但是因為要經過分析轉譯,匯入速度實在不敢恭維

加上登入的session又會timeout,好不容易跑了10萬筆就被中斷,功虧一簣Orz

嘗試了數種方法,最後還是決定回到正統用SQL語法操作的方式。

LOAD DATA LOCAL INFILE  '/path/to/example.csv'
INTO TABLE table_name
CHARACTER SET UTF8
FIELDS TERMINATED BY ','
ENCLOSED BY '"'
LINES TERMINATED BY '\n'
IGNORE 1 ROWS;

P.S.

  • 用terminal進mysql後,記得先use myDatabase;到正確的資料庫下再進行操作。

  • 換行符號因作業系統而異,也有可能是\r\n