我们都知道事务的特性有:
1)原子性(Atomicity)原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
2)一致性(Consistency)一个事务中,事务前后数据的完整性必须保持一致。
3)隔离性(Isolation)多个事务,事务的隔离性是指多个用户并发访问数据库时, 一个用户的 事务不能被其它用户的事务所干扰,多个并发事务之间数据要相互隔离。
4)持久性(Durability)持久性是指一个事务一旦被提交,它对数据库中数据的改变 就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。
那Tdsql 在执行事务时遇到死锁时是如何处理的 呢 ,如何保证事务的原子性和数据的一致性的呢?
首先我们看下面这个场景:
假设t2表的结构为:create table t2(aa int(10) primarykey,bb int(11)) shardkey= aa ;
如果第一个事务等待第二个事务的锁的时候,第二个事务又发起一个SQL导致等待第一个事务的锁的时候,这个时候就会产生死锁。这个TDSQL会如何处理呢 ?
为此proxy增加分布式死锁检测机制,原理如下:
Tdsql 在sql 引擎即proxy增加了死锁检测机制,在proxy 将SQL请求发往set之后就会开启计时,一旦收到SQL请求的响应就会取消计时。如果计时超时,则网关向后端各个set发送如下sql:
SELECT a.trx_xid, a.trx_mysql_thread_id as thread_id, a.trx_started, a.trx_rows_modified, b.trx_xid as blocking_trx
FROM information_schema.innodb_lock_waits as lock_info JOIN information_schema.innodb_trx as a JOIN information_schema.innodb_trx as b ON lock_info.requesting_trx_id = a.trx_id AND lock_info.blocking_trx_id = b.trx_id AND a.trx_xa_type = ‘external‘ and b.trx_xa_type = ‘external‘;
来检测是否有死锁形成,如果判断有交叉等待的锁形成死锁,就会开启死锁处理机制,终止其中一个会话,被终止的会话就会进行回滚。然后业务就会继续进行下去。
上面语句中涉及字段解释如下:
TRX_ID: 事务Id
TRX_STARTED:交易开始时间。
TRX_ROWS_MODIFIED:此事务中已修改和插入的行数。
TRX_MYSQL_THREAD_ID: MySQL线程ID,与show processlist中的ID值相对应
REQUESTING_TRX_ID:请求(阻止)事务的ID。
BLOCKING_TRX_ID: 阻止事务的ID。
所以在tdsql 遇到死锁时不会长时间进行等待,而是根据死锁检测机制进行处理,在快速处理死锁时同时保证事务的原子性和一致性。