django使用innodb类型表commit

本文介绍在使用Django ORM执行InnoDB存储引擎上的删除操作时,如何确保更改被正确提交到数据库。文中提供了两种有效的方法来完成事务提交,并避免因未执行commit导致的数据不一致问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

from django.db import connection   
cursor = connection.cursor()   
cursor.execute("delete from event where id=%s",[event_id])   
cursor.close()

 

innodb在上面情况下,不会生效,cursor.close() 并没有进行commit操作

两种解决方法:

1,

cursor.execute("commit")   
cursor.close()

 

2,

connection.close()

通过查看代码:

Lib\site-packages\django\db\backends\__init__.py

<think>我们面临的是十亿级数据表的主键变更操作,这属于高风险操作。核心难点在于:1.数据量大,直接ALTERTABLE会导致长时间锁表(可能数小时甚至数天)2.主键变更涉及所有二级索引的重建(InnoDB中二级索引叶子节点存储的是主键值)3.磁盘空间占用剧增(需要额外的空间存储临时表)解决方案必须围绕以下目标:-最小化锁表时间(理想是秒级)-可控的资源消耗(IO/CPU/内存)-可中断且可恢复的操作过程以下是分阶段实施方案:</think> ### 高效处理十亿级MySQL表主键变更的专业方案 在十亿级数据表上更改主键是极具挑战性的操作,需要精心设计的策略来避免长时间锁表和服务中断。以下是经过验证的分步解决方案: #### 核心思路:无锁变更 + 增量迁移 ```mermaid graph TD A[开始] --> B{当前主键是自增ID?} B -->|是| C[创建无主键新表] B -->|否| D[设计代理键] C --> E[使用pt-archiver增量迁移] E --> F[数据一致性验证] F --> G[原子切换表名] G --> H[重建二级索引] H --> I[完成] ``` #### 1. 前期准备(关键步骤) ```sql -- 1.1 分析当前表结构 SHOW CREATE TABLE billion_row_table; -- 1.2 创建影子表(无自增主键) CREATE TABLE billion_row_table_new ( id BIGINT UNSIGNED NOT NULL, data VARCHAR(255), -- 添加其它列... new_pk_col VARCHAR(64) NOT NULL, -- 新的主键列 PRIMARY KEY (new_pk_col) -- 新主键定义 ) ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8; -- 1.3 创建变更记录表 CREATE TABLE pk_change_log ( id BIGINT PRIMARY KEY, processed TINYINT DEFAULT 0, change_time TIMESTAMP ); ``` #### 2. 数据迁移工具(pt-archiver脚本) ```bash #!/bin/bash # pt-archiver增量迁移脚本 BATCH_SIZE=10000 THREADS=32 pt-archiver \ --source h=localhost,D=mydb,t=billion_row_table \ --dest h=localhost,D=mydb,t=billion_row_table_new \ --no-check-charset \ --progress 100000 \ --statistics \ --bulk-insert \ --bulk-delete \ --limit $BATCH_SIZE \ --commit-each \ --optimize-before-archive \ --where "id NOT IN (SELECT id FROM pk_change_log WHERE processed=1)" \ --replace \ --no-delete \ # 保留源表数据直到验证完成 --threads $THREADS \ --sleep 0.5 \ --why-quit \ --exec-after-archive "CALL log_processed_ids($BATCH_SIZE)" ``` #### 3. 配套存储过程 ```sql DELIMITER $$ -- 记录已迁移ID CREATE PROCEDURE log_processed_ids(IN batch INT) BEGIN INSERT INTO pk_change_log (id, processed) SELECT id, 1 FROM billion_row_table ORDER BY id DESC LIMIT batch; END$$ -- 数据验证过程 CREATE PROCEDURE verify_data_consistency() BEGIN -- 总量验证 SELECT COUNT(*) AS src_count FROM billion_row_table; SELECT COUNT(*) AS dest_count FROM billion_row_table_new; -- 抽样验证(1%样本) SELECT A.*, B.* FROM billion_row_table A LEFT JOIN billion_row_table_new B ON A.id = B.id WHERE A.id MOD 100 = 0 AND A.data != B.data; -- 此处替换实际数据列 -- 新主键唯一性验证 SELECT new_pk_col, COUNT(*) FROM billion_row_table_new GROUP BY new_pk_col HAVING COUNT(*) > 1; END$$ DELIMITER ; ``` #### 4. 灰度切换方案 ```python from django.db import connection def atomic_switch(): try: with connection.cursor() as cursor: # 停止写入(应用层配合) notify_application('MAINTENANCE_START') # 最终增量同步 cursor.execute(""" INSERT INTO billion_row_table_new (id, data, new_pk_col) SELECT id, data, /* 主键生成逻辑 */ FROM billion_row_table WHERE id NOT IN (SELECT id FROM pk_change_log) """) # 原子切换 cursor.execute("RENAME TABLE billion_row_table TO billion_row_table_old, billion_row_table_new TO billion_row_table") # 重建索引(在线) cursor.execute("ALTER TABLE billion_row_table ADD INDEX (data), ALGORITHM=INPLACE") except Exception as e: # 自动回退 cursor.execute("RENAME TABLE billion_row_table TO billion_row_table_error, billion_row_table_old TO billion_row_table") raise e finally: notify_application('MAINTENANCE_END') ``` #### 5. 性能优化配置 ```ini # my.cnf 关键配置 [mysqld] innodb_buffer_pool_size = 64G # 分配足够内存 innodb_io_capacity = 20000 # SSD配置 innodb_parallel_read_threads = 32 innodb_flush_log_at_trx_commit = 2 # 迁移期间降低持久化要求 skip-log-bin # 禁用二进制日志(迁移期间) max_allowed_packet=1G [pt-archiver] bulk-insert=5000 progress=100000 statistics=yes ``` #### 6. 灾难恢复方案 ```sql -- 快速回滚路径 DROP TABLE IF EXISTS billion_row_table_error; RENAME TABLE billion_row_table TO billion_row_table_abandoned, billion_row_table_old TO billion_row_table; -- 使用新主键重建原有索引 ALTER TABLE billion_row_table DROP INDEX idx_data; ALTER TABLE billion_row_table ADD PRIMARY KEY (id); ``` ### 操作关键要点 1. **时间窗口选择**:在业务低峰期操作(根据SHOW GLOBAL STATUS估算TPS) 2. **资源准备**:预留200%的磁盘空间(原始表空间 × 2.5) 3. **监控指标**: - `Innodb_rows_inserted/s`(插入速度) - `Threads_running`(并发连接数) - `Disk_io_utilization`(IO利用率) 4. **灰度发布**:先迁移10万行验证流程 --- ### 替代方案比较 | 方案 | 适用场景 | 优点 | 缺点 | |------|----------|------|------| | pt-online-schema-change | < 5亿行 | 自动管理流程 | 需重建全表 | | gh-ost | OLTP环境 | 读负载低 | 大表切换有风险 | | MySQL 8.0 Online DDL | 小范围修改 | 原生支持 | 实际仍有锁 | | **本文方案** | 十亿级迁移 | 秒级切换时间 | 操作复杂 |
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值