如何杀掉空闲事务
本文内容遵从CC版权协议, 可以随意转载, 但必须以超链接形式标明文章原始出处和作者信息及版权声明网址: http://www.penglixun.com/tech/database/how_to_kill_idle_trx.html 我们经常遇到一个情况,就是网络断开或程序Bug导致COMMIT/ROLLBACK语句没有传到数
本文内容遵从CC版权协议, 可以随意转载, 但必须以超链接形式标明文章原始出处和作者信息及版权声明网址: http://www.penglixun.com/tech/database/how_to_kill_idle_trx.html
我们经常遇到一个情况,就是网络断开或程序Bug导致COMMIT/ROLLBACK语句没有传到数据库,也没有释放线程,但是线上事务锁定等待严重,连接数暴涨,尤其在测试库这种情况很多,线上也偶有发生,于是想为MySQL增加一个杀掉空闲事务的功能。
那么如何实现呢,通过MySQL Server层有很多不确定因素,最保险还是在存储引擎层实现,我们用的几乎都是InnoDB/XtraDB,所以就基于Percona来修改了,Oracle版的MySQL也可以照着修改。
需求:
1. 一个事务启动,如果事务内最后一个语句执行完超过一个时间(innodb_idle_trx_timeout),就应该关闭链接。
2. 如果事务是纯读事务,因为不加锁,所以无害,不需要关闭,保持即可。
虽然这个思路被Percona的指出Alexey Kopytov可能存在“Even though SELECT queries do not place row locks by default (there are exceptions), they can still block undo log records from being purged.”的问题,但是我们确实有场景SELECT是绝对不能kill的,除非之后的INSERT/UPDATE/DELETE发生了,所以我根据我们的业务特点来修改。
跟Percona的Yasufumi Kinoshita和Alexey Kopytov提出过纯SELECT事务不应被kill,但通过一个参数控制的方案还没有被Alexey Kopytov接受,作为通用处理我提出了用两个变量分别控制纯读事务的空闲超时时间和有锁事务的空闲超时时间,还在等待Percona的回复,因为这个方案还在测试,就先不开放修改了,当然如果你很熟悉MYSQL源码,我提出这个思路你肯定知道怎么分成这两个参数控制了。
根据这两个需求我们来设计方法,首先想到这个功能肯定是放在InnoDB Master Thread最方便,Master Thread每秒调度一次,可以顺便检查空闲事务,然后关闭,因为在事务中操作trx->mysql_thd并不安全,所以一般来说最好在InnoDB层换成Thread ID操作,并且InnoDB中除了ha_innodb.cc,其他地方不能饮用THD,所以Master Thread中需要的线程数值,都需要在ha_innodb中计算好传递整型或布尔型返回值给master thread调用。
首先,我们要增加一个参数:idle_trx_timeout,它表示事务多久没有下一条语句发生就超时关闭。
在storage/innodb_plugin/srv/srv0srv.c的“/* plugin options */”注释下增加如下代码注册idle_trx_timeout变量。
<span style="color: #0000ff;">static</span> MYSQL_SYSVAR_LONG<span style="color: #008000;">(</span>idle_trx_timeout, srv_idle_trx_timeout, PLUGIN_VAR_RQCMDARG, <span style="color: #FF0000;">"If zero then this function no effect, if no-zero then wait idle_trx_timeout seconds this transaction will be closed"</span>, <span style="color: #FF0000;">"Seconds of Idle-Transaction timeout"</span>, <span style="color: #0000ff;">NULL</span>, <span style="color: #0000ff;">NULL</span>, <span style="color: #0000dd;">0</span>, <span style="color: #0000dd;">0</span>, <span style="color: #0000ff;">LONG_MAX</span>, <span style="color: #0000dd;">0</span><span style="color: #008000;">)</span><span style="color: #008080;">;</span>
代码往下找在innobase_system_variables结构体内加上:
MYSQL_SYSVAR<span style="color: #008000;">(</span>idle_trx_timeout<span style="color: #008000;">)</span>,
有了这个变量,我们需要在Master Thread(storage/innodb_plugin/srv/srv0srv.c )中执行检测函数查找空闲事务。在loop循环的if (sync_array_print_long_waits(&waiter, &sema)判断后加上这段判断
<span style="color: #0000ff;">if</span> <span style="color: #008000;">(</span>srv_idle_trx_timeout <span style="color: #000040;">&&</span> trx_sys<span style="color: #008000;">)</span> <span style="color: #008000;">{</span> trx_t<span style="color: #000040;">*</span> trx<span style="color: #008080;">;</span> <span style="color: #0000ff;">time_t</span> now<span style="color: #008080;">;</span> rescan_idle<span style="color: #008080;">:</span> now <span style="color: #000080;">=</span> <span style="color: #0000dd;">time</span><span style="color: #008000;">(</span><span style="color: #0000ff;">NULL</span><span style="color: #008000;">)</span><span style="color: #008080;">;</span> mutex_enter<span style="color: #008000;">(</span><span style="color: #000040;">&</span>kernel_mutex<span style="color: #008000;">)</span><span style="color: #008080;">;</span> trx <span style="color: #000080;">=</span> UT_LIST_GET_FIRST<span style="color: #008000;">(</span>trx_sys<span style="color: #000040;">-</span><span style="color: #000080;">></span>mysql_trx_list<span style="color: #008000;">)</span><span style="color: #008080;">;</span> <span style="color: #339900;"># 从当前事务列表里获取第一个事务</span> <span style="color: #0000ff;">while</span> <span style="color: #008000;">(</span>trx<span style="color: #008000;">)</span> <span style="color: #008000;">{</span> <span style="color: #339900;"># 依次循环每个事务进行检查</span> <span style="color: #0000ff;">if</span> <span style="color: #008000;">(</span>trx<span style="color: #000040;">-</span><span style="color: #000080;">></span>conc_state <span style="color: #000080;">==</span> TRX_ACTIVE <span style="color: #000040;">&&</span> trx<span style="color: #000040;">-</span><span style="color: #000080;">></span>mysql_thd <span style="color: #000040;">&&</span> innobase_thd_is_idle<span style="color: #008000;">(</span>trx<span style="color: #000040;">-</span><span style="color: #000080;">></span>mysql_thd<span style="color: #008000;">)</span><span style="color: #008000;">)</span> <span style="color: #008000;">{</span> <span style="color: #339900;"># 如果事务还活着并且它的状态时空闲的</span> ib_int64_t start_time <span style="color: #000080;">=</span> innobase_thd_get_start_time<span style="color: #008000;">(</span>trx<span style="color: #000040;">-</span><span style="color: #000080;">></span>mysql_thd<span style="color: #008000;">)</span><span style="color: #008080;">;</span> <span style="color: #339900;"># 获取线程最后一个语句的开始时间</span> ulong thd_id <span style="color: #000080;">=</span> innobase_thd_get_thread_id<span style="color: #008000;">(</span>trx<span style="color: #000040;">-</span><span style="color: #000080;">></span>mysql_thd<span style="color: #008000;">)</span><span style="color: #008080;">;</span> <span style="color: #339900;">#获取线程ID,因为存储引擎内直接操作THD不安全</span> <span style="color: #0000ff;">if</span> <span style="color: #008000;">(</span>trx<span style="color: #000040;">-</span><span style="color: #000080;">></span>last_stmt_start <span style="color: #000040;">!</span><span style="color: #000080;">=</span> start_time<span style="color: #008000;">)</span> <span style="color: #008000;">{</span> <span style="color: #339900;"># 如果事务最后语句起始时间不等于线程最后语句起始时间说明事务是新起的</span> trx<span style="color: #000040;">-</span><span style="color: #000080;">></span>idle_start <span style="color: #000080;">=</span> now<span style="color: #008080;">;</span> <span style="color: #339900;"># 更新事务的空闲起始时间</span> trx<span style="color: #000040;">-</span><span style="color: #000080;">></span>last_stmt_start <span style="color: #000080;">=</span> start_time<span style="color: #008080;">;</span> <span style="color: #339900;"># 更新事务的最后语句起始时间</span> <span style="color: #008000;">}</span> <span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> <span style="color: #008000;">(</span><span style="color: #0000dd;">difftime</span><span style="color: #008000;">(</span>now, trx<span style="color: #000040;">-</span><span style="color: #000080;">></span>idle_start<span style="color: #008000;">)</span> <span style="color: #339900;"># 如果事务不是新起的,已经执行了一部分则判断空闲时间有多长了</span> <span style="color: #000080;">></span> srv_idle_trx_timeout<span style="color: #008000;">)</span> <span style="color: #008000;">{</span> <span style="color: #339900;"># 如果空闲时间超过阈值则杀掉链接</span> <span style="color: #ff0000; font-style: italic;">/* kill the session */</span> mutex_exit<span style="color: #008000;">(</span><span style="color: #000040;">&</span>kernel_mutex<span style="color: #008000;">)</span><span style="color: #008080;">;</span> thd_kill<span style="color: #008000;">(</span>thd_id<span style="color: #008000;">)</span><span style="color: #008080;">;</span> <span style="color: #339900;"># 杀链接</span> <span style="color: #0000ff;">goto</span> rescan_idle<span style="color: #008080;">;</span> <span style="color: #008000;">}</span> <span style="color: #008000;">}</span> trx <span style="color: #000080;">=</span> UT_LIST_GET_NEXT<span style="color: #008000;">(</span>mysql_trx_list, trx<span style="color: #008000;">)</span><span style="color: #008080;">;</span> <span style="color: #339900;"># 检查下一个事务</span> <span style="color: #008000;">}</span> mutex_exit<span style="color: #008000;">(</span><span style="color: #000040;">&</span>kernel_mutex<span style="color: #008000;">)</span><span style="color: #008080;">;</span> <span style="color: #008000;">}</span>
其中trx中的变量是新加的,在storage/innodb_plugin/include/trx0trx.h的trx_truct加上需要的变量:
<span style="color: #0000ff;">struct</span> trx_struct<span style="color: #008000;">{</span> ... <span style="color: #0000ff;">time_t</span> idle_start<span style="color: #008080;">;</span> ib_int64_t last_stmt_start<span style="color: #008080;">;</span> ... <span style="color: #008000;">}</span>
这里有几个函数是自定义的:
ibool innobase_thd_is_idle<span style="color: #008000;">(</span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">void</span><span style="color: #000040;">*</span> thd<span style="color: #008000;">)</span><span style="color: #008080;">;</span> ib_int64_t innobase_thd_get_start_time<span style="color: #008000;">(</span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">void</span><span style="color: #000040;">*</span> thd<span style="color: #008000;">)</span><span style="color: #008080;">;</span> ulong innobase_thd_get_thread_id<span style="color: #008000;">(</span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">void</span><span style="color: #000040;">*</span> thd<span style="color: #008000;">)</span><span style="color: #008080;">;</span>
这些函数在ha_innodb.cc中实现,需要在storage/innodb_plugin/srv/srv0srv.c头文件定义下加上这些函数的引用形势。
然后在storage/innodb_plugin/handler/ha_innodb.cc 中定义这些函数的实现:
<span style="color: #0000ff;">extern</span> <span style="color: #FF0000;">"C"</span> ibool innobase_thd_is_idle<span style="color: #008000;">(</span> <span style="color: #0000ff;">const</span> <span style="color: #0000ff;">void</span><span style="color: #000040;">*</span> thd<span style="color: #008000;">)</span> <span style="color: #ff0000; font-style: italic;">/*!< in: thread handle (THD*) */</span> <span style="color: #008000;">{</span> <span style="color: #0000ff;">return</span><span style="color: #008000;">(</span><span style="color: #008000;">(</span><span style="color: #008000;">(</span><span style="color: #0000ff;">const</span> THD<span style="color: #000040;">*</span><span style="color: #008000;">)</span>thd<span style="color: #008000;">)</span><span style="color: #000040;">-</span><span style="color: #000080;">></span>command <span style="color: #000080;">==</span> COM_SLEEP<span style="color: #008000;">)</span><span style="color: #008080;">;</span> <span style="color: #008000;">}</span> <span style="color: #0000ff;">extern</span> <span style="color: #FF0000;">"C"</span> ib_int64_t innobase_thd_get_start_time<span style="color: #008000;">(</span> <span style="color: #0000ff;">const</span> <span style="color: #0000ff;">void</span><span style="color: #000040;">*</span> thd<span style="color: #008000;">)</span> <span style="color: #ff0000; font-style: italic;">/*!< in: thread handle (THD*) */</span> <span style="color: #008000;">{</span> <span style="color: #0000ff;">return</span><span style="color: #008000;">(</span><span style="color: #008000;">(</span>ib_int64_t<span style="color: #008000;">)</span><span style="color: #008000;">(</span><span style="color: #008000;">(</span><span style="color: #0000ff;">const</span> THD<span style="color: #000040;">*</span><span style="color: #008000;">)</span>thd<span style="color: #008000;">)</span><span style="color: #000040;">-</span><span style="color: #000080;">></span>start_time<span style="color: #008000;">)</span><span style="color: #008080;">;</span> <span style="color: #008000;">}</span> <span style="color: #0000ff;">extern</span> <span style="color: #FF0000;">"C"</span> ulong innobase_thd_get_thread_id<span style="color: #008000;">(</span> <span style="color: #0000ff;">const</span> <span style="color: #0000ff;">void</span><span style="color: #000040;">*</span> thd<span style="color: #008000;">)</span> <span style="color: #008000;">{</span> <span style="color: #0000ff;">return</span><span style="color: #008000;">(</span>thd_get_thread_id<span style="color: #008000;">(</span><span style="color: #008000;">(</span><span style="color: #0000ff;">const</span> THD<span style="color: #000040;">*</span><span style="color: #008000;">)</span> thd<span style="color: #008000;">)</span><span style="color: #008000;">)</span><span style="color: #008080;">;</span> <span style="color: #008000;">}</span>
还有最重要的thd_kill函数负责杀线程的,在sql/sql_class.cc中,找个地方定义这个函数:
<span style="color: #0000ff;">void</span> thd_kill<span style="color: #008000;">(</span>ulong id<span style="color: #008000;">)</span> <span style="color: #008000;">{</span> THD <span style="color: #000040;">*</span>tmp<span style="color: #008080;">;</span> VOID<span style="color: #008000;">(</span>pthread_mutex_lock<span style="color: #008000;">(</span><span style="color: #000040;">&</span>LOCK_thread_count<span style="color: #008000;">)</span><span style="color: #008000;">)</span><span style="color: #008080;">;</span> I_List_iterator<span style="color: #000080;"><</span>THD<span style="color: #000080;">></span> it<span style="color: #008000;">(</span>threads<span style="color: #008000;">)</span><span style="color: #008080;">;</span> <span style="color: #0000ff;">while</span> <span style="color: #008000;">(</span><span style="color: #008000;">(</span>tmp<span style="color: #000080;">=</span>it<span style="color: #000040;">++</span><span style="color: #008000;">)</span><span style="color: #008000;">)</span> <span style="color: #008000;">{</span> <span style="color: #0000ff;">if</span> <span style="color: #008000;">(</span>tmp<span style="color: #000040;">-</span><span style="color: #000080;">></span>command <span style="color: #000080;">==</span> COM_DAEMON <span style="color: #000040;">||</span> tmp<span style="color: #000040;">-</span><span style="color: #000080;">></span>is_have_lock_thd <span style="color: #000080;">==</span> <span style="color: #0000dd;">0</span> <span style="color: #008000;">)</span> <span style="color: #339900;"># 如果是DAEMON线程和不含锁的线程就不要kill了</span> <span style="color: #0000ff;">continue</span><span style="color: #008080;">;</span> <span style="color: #0000ff;">if</span> <span style="color: #008000;">(</span>tmp<span style="color: #000040;">-</span><span style="color: #000080;">></span>thread_id <span style="color: #000080;">==</span> id<span style="color: #008000;">)</span> <span style="color: #008000;">{</span> pthread_mutex_lock<span style="color: #008000;">(</span><span style="color: #000040;">&</span>tmp<span style="color: #000040;">-</span><span style="color: #000080;">></span>LOCK_thd_data<span style="color: #008000;">)</span><span style="color: #008080;">;</span> <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span> <span style="color: #008000;">}</span> <span style="color: #008000;">}</span> VOID<span style="color: #008000;">(</span>pthread_mutex_unlock<span style="color: #008000;">(</span><span style="color: #000040;">&</span>LOCK_thread_count<span style="color: #008000;">)</span><span style="color: #008000;">)</span><span style="color: #008080;">;</span> <span style="color: #0000ff;">if</span> <span style="color: #008000;">(</span>tmp<span style="color: #008000;">)</span> <span style="color: #008000;">{</span> tmp<span style="color: #000040;">-</span><span style="color: #000080;">></span>awake<span style="color: #008000;">(</span>THD<span style="color: #008080;">::</span><span style="color: #007788;">KILL_CONNECTION</span><span style="color: #008000;">)</span><span style="color: #008080;">;</span> pthread_mutex_unlock<span style="color: #008000;">(</span><span style="color: #000040;">&</span>tmp<span style="color: #000040;">-</span><span style="color: #000080;">></span>LOCK_thd_data<span style="color: #008000;">)</span><span style="color: #008080;">;</span> <span style="color: #008000;">}</span> <span style="color: #008000;">}</span>
为了存储引擎能引用到这个函数,我们要把它定义到plugin中:
include/mysql/plugin.h和include/mysql/plugin.h中加上
<span style="color: #0000ff;">void</span> thd_kill<span style="color: #008000;">(</span><span style="color: #0000ff;">unsigned</span> <span style="color: #0000ff;">long</span> id<span style="color: #008000;">)</span><span style="color: #008080;">;</span>
如何判定线程的is_have_lock_thd值?首先在THD中加上这个变量(sql/sql_class.cc):
<span style="color: #0000ff;">class</span> THD <span style="color: #008080;">:</span><span style="color: #0000ff;">public</span> Statement, <span style="color: #0000ff;">public</span> Open_tables_state <span style="color: #008000;">{</span> .... <span style="color: #007788;">uint16</span> is_have_lock_thd<span style="color: #008080;">;</span> .... <span style="color: #008000;">}</span>
然后在SQL的必经之路mysql_execute_command拦上一刀,判断是有锁操作发生了还是事务提交或新起事务。
<span style="color: #0000ff;">switch</span> <span style="color: #008000;">(</span>lex<span style="color: #000040;">-</span><span style="color: #000080;">></span>sql_command<span style="color: #008000;">)</span> <span style="color: #008000;">{</span> <span style="color: #0000ff;">case</span> SQLCOM_REPLACE<span style="color: #008080;">:</span> <span style="color: #0000ff;">case</span> SQLCOM_REPLACE_SELECT<span style="color: #008080;">:</span> <span style="color: #0000ff;">case</span> SQLCOM_UPDATE<span style="color: #008080;">:</span> <span style="color: #0000ff;">case</span> SQLCOM_UPDATE_MULTI<span style="color: #008080;">:</span> <span style="color: #0000ff;">case</span> SQLCOM_DELETE<span style="color: #008080;">:</span> <span style="color: #0000ff;">case</span> SQLCOM_DELETE_MULTI<span style="color: #008080;">:</span> <span style="color: #0000ff;">case</span> SQLCOM_INSERT<span style="color: #008080;">:</span> <span style="color: #0000ff;">case</span> SQLCOM_INSERT_SELECT<span style="color: #008080;">:</span> thd<span style="color: #000040;">-</span><span style="color: #000080;">></span>is_have_lock_thd <span style="color: #000080;">=</span> <span style="color: #0000dd;">1</span><span style="color: #008080;">;</span> <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span> <span style="color: #0000ff;">case</span> SQLCOM_COMMIT<span style="color: #008080;">:</span> <span style="color: #0000ff;">case</span> SQLCOM_ROLLBACK<span style="color: #008080;">:</span> <span style="color: #0000ff;">case</span> SQLCOM_XA_START<span style="color: #008080;">:</span> <span style="color: #0000ff;">case</span> SQLCOM_XA_END<span style="color: #008080;">:</span> <span style="color: #0000ff;">case</span> SQLCOM_XA_PREPARE<span style="color: #008080;">:</span> <span style="color: #0000ff;">case</span> SQLCOM_XA_COMMIT<span style="color: #008080;">:</span> <span style="color: #0000ff;">case</span> SQLCOM_XA_ROLLBACK<span style="color: #008080;">:</span> <span style="color: #0000ff;">case</span> SQLCOM_XA_RECOVER<span style="color: #008080;">:</span> thd<span style="color: #000040;">-</span><span style="color: #000080;">></span>is_have_lock_thd <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span> <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span> <span style="color: #008000;">}</span>
为了尽可能兼容Percona的补丁,能引用的都引用了Percona的操作,有些函数调用是在层次太多看不下去了就简化了。
另外还有一个版本是我自己弄的,在THD中增加了一个last_sql_end_time,在do_command结束后更新last_sql_end_time,然后在事务中拿到THD查看last_sql_end_time就可以得出idle时间,Oracle版我还是建议这么做,不要去改trx_struct结构体了,那个感觉更危险。

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

怎麼更改MicrosoftEdge瀏覽器打開是360導航的頁面呢?其實很簡單,那麼現在小編就和大家一起分享關於更改MicrosoftEdge瀏覽器打開是360導航頁面的方法,有需要的朋友可以來看看哦,希望可以幫助大家。開啟MicrosoftEdge瀏覽器。我們看到是下圖這種頁面。點擊右上角的三點圖示。點選“設定”。在設定頁面的左側欄裡點選「啟動時」。點選右側欄裡的圖中示意的三點(不要能點選「開啟新標籤頁」),然後點選編輯,將網址改成「0」(或其他無意義的數字)。然後點選「儲存」。接下來,選擇“

downloads可以刪除嗎近年來,隨著數位時代的來臨,我們生活中出現了越來越多的數位化產品和服務。而隨之而來的,就是我們對於數位化內容的需求與日俱增。在日常生活和工作中,我們經常需要下載各種各樣的文件,如文件、圖片、音訊和視訊等等。而這些下載的文件,通常都被保存在一個名為「downloads」(下載)的資料夾中。然而,隨著時間的推移,我們經常發現,“

CheatEngine是一款遊戲編輯器,能夠對遊戲的記憶體進行編輯修改。但是它的預設語言是非中文的,對於很多小夥伴來說比較不方便,那麼CheatEngine怎麼設定中文呢?今天小編就跟大家詳細介紹一下CheatEngine設定中文的方法,希望可以幫助到你。 設定方法一 1、雙擊開啟軟體,點選左上角的「edit」。 2、接著點選下方選項清單中的「settings」。 3、在開啟的視窗介面中,點選左側欄中的“languages”

1.PDO簡介PDO是PHP的擴充庫,它提供了一個物件導向的方式來操作資料庫。 PDO支援多種資料庫,包括Mysql、postgresql、oracle、SQLServer等。 PDO使開發人員能夠使用統一的api來操作不同的資料庫,這使得開發人員可以在不同的資料庫之間輕鬆切換。 2.PDO連接資料庫要使用PDO連接資料庫,首先需要建立一個PDO物件。 PDO物件的建構函式接收三個參數:資料庫類型、主機名稱、資料庫使用者名稱和密碼。例如,以下程式碼建立了一個連接到mysql資料庫的物件:$dsn="mysq

MySQL事務處理:自動提交與手動提交的差異在MySQL資料庫中,事務是一組SQL語句的集合,要麼全部執行成功,要麼全部執行失敗,保證了資料的一致性和完整性。在MySQL中,事務可以分為自動提交和手動提交,其區別在於事務提交的時機以及對事務的控制範圍。以下將詳細介紹自動提交和手動提交的區別,並給出具體的程式碼範例來說明。一、自動提交在MySQL中,如果沒有顯示

i34150搭配1G獨顯能玩哪些遊戲能玩lol等小遊戲。 GTX750和GTX750TI是非常適合的顯示卡選擇。如果只是玩一些小遊戲或不玩遊戲,建議使用i34150的整合式顯示卡就可以了。一般來說,顯示卡和處理器的搭配差價並不是很大,所以選擇合理的搭配是很重要的。若需要2G顯存,建議選擇GTX750TI;若只需要1G顯存,直接選擇GTX750即可。 GTX750TI可以看作是GTX750的增強版本,具有超頻功能。 i34150可以搭配什麼顯示卡依需求,如果你打算玩單機遊戲,建議你考慮更換顯示卡。你可以選擇

事務確保資料庫資料完整性,包括原子性、一致性、隔離性和持久性。 JDBC使用Connection介面提供交易控制(setAutoCommit、commit、rollback)。並發控制機制協調並發操作,使用鎖或樂觀/悲觀並發控制來實現事務隔離性,以防止資料不一致。

PHP資料物件(PDO)擴充功能提供了與資料庫伺服器高效且物件導向的互動。其高級查詢和更新功能使開發人員能夠執行複雜的資料庫操作,從而提高效能和程式碼可維護性。本文將深入探討PDO的高階查詢與更新功能,引導您掌握其強大功能。進階查詢:使用佔位符和綁定參數佔位符和綁定參數是提高查詢效能和安全性的重要工具。佔位符使用問號(?)表示查詢中可替換的參數,而綁定參數則允許指定每個參數的資料類型和值。透過使用這些方法,您可以避免sql注入攻擊並提高效能,因為資料庫引擎可以提前最佳化查詢。 //使用佔位符$stmt=$
